Mint USDX on Kava’s Testnet-5000

Denali Marsh
8 min readApr 8, 2020

--

We’re pleased to announce the launch of Kava’s testnet-5000 simplifying how you develop, debug, and deploy. With KAVA’s testnet-5000 you’re now able to transfer BNB from Binance Chain to Kava and use it to mint USDX.

We’re also releasing our new JavaScript SDK for interacting with the Kava blockchain. Now you can take advantage of the features that Kava has designed to help developers to engineer their projects best.

“While this is a testnet, it’s more like an alpha launch with a complete software package of the Binance-to-Kava bridge. It’s a landmark development as the first bridge between two Cosmos based blockchains. The aim of this testnet is to more thoroughly test the bridge for vulnerabilities and see how it performs in the wild” said Brian Kerr, Founder and CEO of Kava. “The hope is that in this public testnet we’ll find any remaining bugs and vulnerabilities and better understand how the Binance-to-Kava bridge holds up under certain circumstances.”

“Everything Kava has built internally is now revealed in the testnet. Kava’s engineering team will spend this month testing the codebase in preparation for our mainnet launch,” he continues to say. “The Kava mainnet launch will be a major milestone for the company and the entire crypto community, making DeFi for the first time more accessible to the greater crypto industry,” he explains.

The following steps detail how to send BNB from Binance Chain to Kava and use it to mint USDX. Our article on cross-chain transfers with testnet-5000 is required reading before attempting the treasure hunt for USDX. All the code in this article is on GitHub (link at the bottom).

1. Create testnet accounts

We’ll need to create addresses on both Binance Chain and Kava in order to swap assets between them. Kava’s JavaScript SDK supports the generation of mnemonics, from which we can load a new address. Let’s install it with npm.

npm install @kava-labs/javascript-sdk

In a new JavaScript file import the crypto library, then create a new mnemonic and load the associated address.

const kava = require("@kava-labs/javascript-sdk");
const crypto = kava.crypto;
const mnemonic = crypto.generateMnemonic();
const addr = crypto.getAddressFromMnemonic(mnemonic);
console.log("Mnemonic:", mnemonic);
console.log("Address:", addr);

To create an account on the Binance Chain testnet, we recommend their wallet creation guide. Make sure to save your mnemonic!

2. Load testnet funds

Before we can get started, head over to Kava’s faucet to get some testnet KAVA sent to your new address. This is a required step as it registers your address in the blockchain state.

Kava testnet-5000 faucet
Kava’s faucet can be used to claim testnet KAVA

In order to create swaps, our new Binance Chain account needs testnet BNB. We recommend using Binance’s faucet guide to get 200 testnet BNB from their faucet.

Follow Binance’s guide in order to receive testnet BNB

3. Start Binance Chain client

We’ll be using Binance Chain’s JavaScript SDK for sending transactions to their testnet. In a new directory, install the Binance Chain JavaScript SDK.

npm install @binance-chain/javascript-sdk

Create a new file titled main.js. Let’s set up the chain’s deputy address and initialize a new client using our mnemonic and API endpoint.

const BnbApiClient = require(“@binance-chain/javascript-sdk”);
const bnbCrypto = BnbApiClient.crypto;
const BINANCE_CHAIN_API_TESTNET = "https://testnet-dex.binance.org";
const BINANCE_CHAIN_DEPUTY = "tbnb1et8vmd0dgvswjnyaf73ez8ye0jehc8a7t7fljv";
const bnbAddress = "your binance chain testnet address";
const bnbMnemonic = "secret words that unlock your address";
// Start Binance Chain client
const bnbClient = await new BnbApiClient(BINANCE_CHAIN_API_TESTNET);
bnbClient.chooseNetwork("testnet");
const privateKey = bnbCrypto.getPrivateKeyFromMnemonic(bnbMnemonic);
bnbClient.setPrivateKey(privateKey);
await bnbClient.initChain();

4. Start Kava client

We’ll be using Kava’s JavaScript SDK for sending transactions to testnet-5000. Similarly, let’s set up the deputy address and initialize a new client.

const kava = require("@kava-labs/javascript-sdk");
const KavaClient = kava.KavaClient;
const KAVA_API_TESTNET = "http://kava-testnet-5000.kava.io:1317";
const KAVA_DEPUTY = "kava1aphsdnz5hu2t5ty2au6znprug5kx3zpy6zwq29";
const kavaAddress = "your kava testnet-5000 address";
const kavaMnemonic = "secret words that unlock your address"
// Start Kava client
kavaClient = new KavaClient(KAVA_API_TESTNET);
kavaClient.setWallet(kavaMnemonic);
await kavaClient.initChain();

5. Send create swap transaction to Binance Chain

With our two blockchain clients up and running, let’s create a swap of 5 BNB from Binance Chain to Kava.

Since BNB and USDX have different decimals, we should probably start by adding some conversion factor constants to keep things organized.

const BNB_CONVERSION_FACTOR = 10 ** 8;
const USDX_CONVERSION_FACTOR = 10 ** 6;

Let’s set up the swap’s general parameters. This swap of 5 BNB will be sent from our Binance Chain address to the deputy’s Binance Chain address. Later once we claim the swap, an equivalent amount of pegged bnb will be sent from the deputy’s Kava address to our Kava address.

// Assets involved in the swap
const asset = "BNB";
const amount = 5 * BNB_CONVERSION_FACTOR;
// Format asset parameters
const tokens = [{
denom: asset,
amount: amount
}];
const expectedIncome = [String(amount), ":", asset].join("");
// Addresses involved in the swap
const sender = bnbAddress;
const recipient = BINANCE_CHAIN_DEPUTY;
const senderOtherChain = KAVA_DEPUTY;
const recipientOtherChain = kavaAddress;
// Number of blocks that swap will be active
const heightSpan = 10001;

We’ll use Kava’s JavaScript SDK utils to generate a hex-encoded secret random number and calculate the swap’s random number hash from the timestamp and random number.

// Add utils from Kava's JavaScript SDK to imports
const kavaUtils = kava.utils;
const randomNumber = kavaUtils.generateRandomNumber();
const timestamp = Math.floor(Date.now() / 1000);
const randomNumberHash = kavaUtils.calculateRandomNumberHash(randomNumber, timestamp);
console.log("Secret random number:", randomNumber);

Now we’re ready to create the swap. Let’s send the transaction to Binance.

const res = await bnbClient.swap.HTLT(sender, recipient, recipientOtherChain, senderOtherChain, randomNumberHash, timestamp, tokens, expectedIncome, heightSpan, true);// Log the tx hash or log an error and return
if (res && res.status == 200) {
console.log("Create swap tx hash: ", res.result[0].hash);
} else {
console.log("Tx error:", res);
return;
}

Assuming everything went well, we’ll see the tx hash in our console.

Create swap tx hash: 8C424710C357E56EC75B982C95AFF3D90E45CEB3ECC9CB7CAB7AE467A7265115

We can use Binance’s testnet explorer to check our transaction by its hash.

Binance Chain create swap tx result
Successful swap creation transaction result on Binance Chain

In addition to the transaction’s status, involved addresses, and value, we can see the swap’s data.

Create swap Binance Chain tx result data
Our created swap’s data and swap ID on Binance Chain

6. Send claim swap transaction to Kava

We’ll need the swap’s ID on Kava in order to claim it. It’s different than the swap’s ID on Binance Chain, so we’ll have to calculate it.

const kavaSwapID = kavaUtils.calculateSwapID(randomNumberHash, senderOtherChain, sender);

Now we can claim the swap using our secret random number.

const txHashClaim = await kavaClient.claimSwap(kavaSwapID, randomNumber);
console.log(“Claim swap tx hash: “, txHashClaim);

Let’s query our Kava account’s balances in order to confirm that we received the pegged bnb as expected. We’re using lodash here, so we’ll need to add the package to our imports.

const _ = require("lodash");let acc = await kavaClient.getAccount(kavaClient.wallet.address);
console.log(“Address:”, _.get(acc, “value.address”));
console.log(“Balances:”, _.get(acc, “value.coins”), “\n”);
// Coins should include "{ denom: 'bnb', amount: '499999000' }"

7. Send create CDP transaction to Kava

Now that our Kava account is loaded with pegged bnb, let’s mint USDX by creating a new Collateralized Debt Position (CDP). In order to mint USDX (our principal), it must be over collateralized with pegged bnb (our collateral) by at least 200%. So if we want to mint $10 of USDX, we’ll need at least $20 of pegged bnb.

But while the USDX stable coin is always worth $1, pegged bnb is worth BNB’s fair market value. If BNB is worth $10, we’ll need 2 pegged bnb to meet the minimum collateralization ratio. If BNB is worth $40, we’ll need 0.5 pegged bnb.

Kava has a minimum principal requirement for CDPs. We can get the USDX limit by querying the CDP module’s parameters and searching for ‘usdx’. Afterward, we apply our USDX conversion factor and print the result.

const paramsCDP = await kavaClient.getParamsCDP();
const debtParams = _.get(paramsCDP, “debt_params”);
const principalAmount = Number(debtParams.find(coin => coin.denom == “usdx”).debt_floor);
console.log(“Minimum principal:”, principalAmount + “usdx”);

We’ll see that testnet-5000 has a minimum principal requirement of 10000000usdx, or 10 USDX, since USDX’s conversion factor is 10**6.

Now we need to calculate the collateral required for this principal amount. Kava’s price feed has the current market price of BNB. Let’s use it to calculate the equivalent amount of collateral in our base asset.

const bnbValuation = await kavaClient.getPrice(“bnb:usd”);
const equivalentCollateral = principalAmount / Number(bnbValuation.price);

The minimum collateralization ratio for BNB is 200%, so we’ll have to apply a 2x multiplier in order to get the true amount of required collateral. We want some padding to avoid liquidation, so let’s add a 2.1x multiplier for a collateralization ratio of 210%.

const rawRequiredAmount = equivalentCollateral * 2.1;// Apply conversion factor and drop decimals
const adjustedAmount = (rawRequiredAmount / USDX_CONVERSION_FACTOR) * BNB_CONVERSION_FACTOR;
const collateralAmount = adjustedAmount.toFixed(0);
console.log("Required collateral:", collateralAmount + "bnb");

At the time of this writing, BNB is worth $15.09, so our required collateral amount comes out to 139165009bnb, or ~1.39BNB.

The next block of code applies the correct number of decimals to the collateral amount checks our account’s pegged bnb balance. If we don’t have enough, we won’t be able to send the create CDP transaction.

try {
account = await kavaClient.getAccount(kavaClient.wallet.address);
const coins = _.get(account, “value.coins”);
const bnbBalance = coins.find(coin => coin.denom == “bnb”).amount;
if (bnbBalance < collateralAmount) {
throw {
message: “Account only has “ + bnbBalance + “bnb”
};
}
} catch (err) {
console.log(“Error:”, err.message);
return;
}

We’ve calculated the collateral amount and we’ve confirmed our balances, so all that’s left is load the principal and collateral as formatted coins.

const principal = kavaUtils.formatCoins(Number(principalAmount), "usdx");
const collateral = kavaUtils.formatCoins(Number(collateralAmount), "bnb");

Now, we can use our collateral and principal to create a valid CDP using the Kava client.

const txHashCDP = await kavaClient.createCDP(principal, collateral);
console.log(“Create CDP tx hash (Kava): “, txHashCDP);
// Get account balance
account = await kavaClient.getAccount(kavaClient.wallet.address);
console.log("Address:", _.get(account, "value.address"));
console.log("Balances:", _.get(account, "value.coins"), "\n");
// Coins should include "{ denom: 'usdx', amount: '10000000' }"

There it is, our gold at the end of the treasure hunt. Well done, you’ve successfully minted USDX!

USDX minting script

We’ve combined steps 3–7 into a single script that you can use to create a swap on Binance Chain, claim the swap on Kava, and open a CDP with the received tokens. You can find it on GitHub as a gist.

The output of the script should look something like this:

Secret random number: 1121d1c5639a6a663f1286ca3489b0de109c9cc861c8772eb9f9276de58dda4e
Create swap tx hash (Binance Chain): 8AE0CB9DEC1D52AB9A807971811F5B712B0B052B99570A430FF984157D73F1D5
Claim swap tx hash (Kava): 412658B0A17ABF94ACAEB4E63ED149A218F43BBA181C8A02827A16DFC11A2998
Address: kava1sj6drj8agdplcc0t48lw5flenrxude9tqx7wy2
Balances: [ { denom: ‘bnb’, amount: ‘499999000’ },
{ denom: ‘ukava’, amount: ‘50000000’ } ]
Minimum principal: 10000000usdx
Required collateral: 139257294bnb
Create CDP tx hash (Kava): B1190B67FBC64267BE3D853FE73A5AC27FCF4E99350AC6143D9D96348B72F72F
Address: kava1sj6drj8agdplcc0t48lw5flenrxude9tqx7wy2
Balances: [ { denom: ‘bnb’, amount: ‘360741706’ },
{ denom: ‘ukava’, amount: ‘50000000’ },
{ denom: ‘usdx’, amount: ‘10000000’ } ]

Kava is working with several wallet providers to build user interfaces for testnet-5000. We’ll keep you posted and let you know when those are publically available.

Stay in touch!

Disclaimer: This content is provided for informational purposes only, and should not be relied upon as legal, business, investment, or tax advice. You should consult your own advisers as to those matters. References to any securities or digital assets are for illustrative purposes only, and do not constitute an investment recommendation or offer to provide investment advisory services. Furthermore, this content is not directed at nor intended for use by any investors or prospective investors, and may not under any circumstances be relied upon when making investment decisions.

--

--