Skip to main content

Crypto SDK Guide

This guide will show you how Yellow Submarine allows users to convert an asset to a private asset and transfer it to a brand new wallet address by Findora Triple Masking.

It conducts two ZKP operations:

  • transfer asset to anonymous wallet from wallet A. (bar to abar)
  • transfer asset to wallet B from anonymous wallet. (abar to bar)

The combination of these two operations is the key to removing the trace.

Installing the Findora SDK

To install the Findora SDK we only need to run one single command:

yarn add @findora-network/findora-sdk.js

1. Setup the Findora SDK

  // Top-level await
const findoraSdk = await import('@findora-network/findora-sdk.js');
const findoraWasm = await findoraSdk.getWebLedger();

const { Network: NetworkApi, Transaction: TransactionApi } = findoraSdk.Api;

2. Create two Findora Wallet

  // create a Findora Wallet, this wallet will be the source wallet
const keypairA = findoraWasm.new_keypair();
const walletA = {
keypair: keypairA,
keyStore: findoraWasm.keypair_to_str(keypairA),
privateKey: findoraWasm.get_priv_key_str(keypairA).replace(/\"/g, ''),
publickey: findoraWasm.get_pub_key_str(keypairA).replace(/\"/g, ''),
address: findoraWasm.public_key_to_bech32(findoraWasm.get_pk_from_keypair(keypairA)),
};

// create another Findora Wallet, this wallet will be the destination wallet
const keypairB = findoraWasm.new_keypair();
const walletB = {
keypair: keypairB,
keyStore: findoraWasm.keypair_to_str(keypairB),
privateKey: findoraWasm.get_priv_key_str(keypairB).replace(/\"/g, ''),
publickey: findoraWasm.get_pub_key_str(keypairB).replace(/\"/g, ''),
address: findoraWasm.public_key_to_bech32(findoraWasm.get_pk_from_keypair(keypairB)),
};

3. Create a Findora Anonymous Wallet

  // create a Findora Anonymous Wallet
const anonKeys = findoraWasm.gen_anon_keys();
const anonWallet = {
axfrPublicKey: anonKeys.axfr_public_key,
axfrSecretKey: anonKeys.axfr_secret_key,
decKey: anonKeys.dec_key,
encKey: anonKeys.enc_key,
};

// release the anonymous keys instance
anonKeys.free();

4. Bar to Abar

  // create an instance of the transaction builder
const transactionBuilder = await TransactionApi.getTransactionBuilder();

// get the informance of the UTXO by specific sid
const { response: [sid] } = await NetworkApi.getOwnedSids(walletA.address);
const { response: utxo } = await NetworkApi.getUtxo(sid);
const { response: ownerMemoData } = await NetworkApi.getOwnerMemo(sid);

const ownerMemo = ownerMemoData ? findoraWasm.OwnerMemo.from_json(ownerMemoData) : null;
const assetRecord = findoraWasm.ClientAssetRecord.from_json(utxo);

// the destination anonymous wallet
const axfrPublicKey = findoraWasm.axfr_pubkey_from_string(anonWallet.axfrPublicKey);
const encKey = findoraWasm.x_pubkey_from_string(anonWallet.encKey);

const keypair = findoraWasm.keypair_from_str(walletA.keyStore as string);

// add_operation_bar_to_abar will return a instance of the transactionBuilder, which would be used to submit the generated tx to the network
transactionBuilder = transactionBuilder.add_operation_bar_to_abar(
keypair,
axfrPublicKey,
BigInt(sid),
assetRecord,
ownerMemo?.clone(),
encKey,
);

// The only way to get access to the funds from the `abar` is to ensure that commitment is saved
// after the operation is completed and transaction is broadcasted.
// `commitments` MUST be saved in order to get access to the funds later.
const commitments = transactionBuilder?.get_commitments();

// Finally, broadcast this transaction to the network
await TransactionApi.submitTransaction(transactionBuilder.transaction());

5. Abar to Bar

  // create an instance of the transaction builder
const transactionBuilder = await TransactionApi.getTransactionBuilder();

// the destination wallet
const receiverXfrPublicKey = findoraWasm.public_key_from_base64(walletB.publickey);

// the source anonymous wallet
const aXfrKeyPairSender = findoraWasm.axfr_keypair_from_string(anonWallet.axfrSecretKey);
const secretDecKeySender = findoraWasm.x_secretkey_from_string(anonWallet.decKey);

// we need to provide a commitment string which we would `transfer` to the destination wallet
const commitment = 'YOUR_COMMITMENT';

// `Abar to Bar` operation would require instances of abar, which will be created (restored)
// using the commitment strings
const { response: ownedAbarsResponse } = await NetworkApi.getOwnedAbars(commitment);
const [atxoSid, _ownedAbar] = ownedAbarsResponse;
// instances of abar
const ownedAbar = findoraWasm.abar_from_json(_ownedAbar);

// get the informance of the abar
const { response: abarOwnerMemoData } = await NetworkApi.getAbarOwnerMemo(atxoSid);
const { response: mtLeafInfoData } = await NetworkApi.getMTLeafInfo(atxoSid);
const abarOwnerMemo = findoraWasm.OwnerMemo.from_json(abarOwnerMemoData);
const mTLeafInfo = findoraWasm.MTLeafInfo.from_json(mtLeafInfoData);

// add_operation_abar_to_bar will return a instance of the transactionBuilder, which would be used to submit the generated tx to the network
transactionBuilder = transactionBuilder.add_operation_abar_to_bar(
ownedAbar,
abarOwnerMemo,
mTLeafInfo,
aXfrKeyPairSender,
secretDecKeySender,
receiverXfrPublicKey,
false,
false,
);

// Finally, broadcast this transaction to the network
await TransactionApi.submitTransaction(transactionBuilder.transaction());