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 walletfromwallet A. (bar to abar) - transfer asset to 
wallet Bfromanonymous 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());