Quick Overview of ASA and AlgoSigner
For those having experience in Ethereum, digital assets (always known as tokens) are implemented through (smart) contract, riding on top of an Ethereum network. This is called Layer-2 implementation. Algorand is taking a different approach, making digital assets as states of any given accounts. It is called Layer-1 implementation. When we inspect the account information of a given account, we can see the balance of Algos, the native currency in Algorand, and all the digital assets held in this account.
This means that we do not need to deploy a token contract on Algorand, and can perform the lifecycle of digital assets directly on Algorand, including creation, transfer and destruction. We are showing this here with JavaScript SDK. ASA in fact comes with very comprehensive capabilities, good for both fungible and non-fungible tokens. This is not covered in this article.
You can explore more about ASA here.
Meanwhile, PureStake recently released AlgoSigner, a chrome plug-in as an Algorand wallet. For those familiarized with Metamask on Ethereum, this is the right way to understand AlgoSigner on Algorand. In this demonstration we will use AlgoSigner to perform digital asset transfer.
Source
This work is largely based on a complete example by Ryan Fox (link). His work can be found here. For better illustration, I broke it down into steps. Besides, when ASA transactions are signed and submitted, Ryan’s code provides a decent way to wait for confirmation and show the asset details. I am not using this here, but it is highly recommended when we are developing a better application. Here I just use a separate script to inspect the account information.
Demonstration
We create two accounts, each of which comes with the 25-word mnemonic. For simplicity we specify them as Alice and Bob. Here are the addresses of both Alice and Bob’s account.
In our demonstration we will perform the following tasks
- Alice creates a new digital asset, 1m KCCOINs, in Algorand Testnet.
- Alice sends Bob 200k KCCOINs. This fails as Bob does not opt-in KCCOIN yet.
- Bob opt-in KCCOIN. And Alice sends Bob 200k KCCOINs with success.
- Use AlgoSigner to observe both accounts.
- Alice sends Bob 100k KCCOINs using AlgoSigner.
- Alice destroys KCCOINs. This fails as Alice does not hold all the KCCOINs (some are still in Bob’s Account)
- Bob sends Alice back all (300k) KCCOINs.
- Alice deletes KCCOINs.
- Bob removes KCCOIN in his account.
Those scripts are provided in each demo step when applicable. Before using them, make sure you update
- 25-word mnemonic for your own accounts, and those account addresses.
- The asset-ID for the asset you have created.
Over this demonstration, we keep checking ASA from both Alice and Bob’s account. Here is the script asa_checkBoth.js
to show the assets in both accounts.
const algosdk=require('algosdk'); const server="https://testnet-algorand.api.purestake.io/ps2"; const port=""; const token={ "x-api-key": "mV *** BY" // fill in yours }; var aliceAddress = '5SL7MUMPYFNDBHUD4L7J4LJRQCQWXQUD3RDK7SBGIDWPH3ZFK47BTH43HE'; // change to yours var bobAddress = 'BDGUP3RKI3DJVM327B3R4SYT6PQUJBMDMQWHQICKSEQQT6PWCMNAYWEY4M'; // change to yours let client=new algosdk.Algodv2(token, server, port); ( async() => { let alice_account_info = (await client.accountInformation(aliceAddress).do()); console.log("Asset of Alice: "); console.log(alice_account_info.assets); let bob_account_info = (await client.accountInformation(bobAddress).do()); console.log("Asset of Bob: "); console.log(bob_account_info.assets); })().catch(e => { console.log(e); })
As seen at the beginning, both Alice and Bob do not have any assets defined.
Step 1: Create ASA
Here is the script asa_aliceCreate.js
to let Alice create KCCOINs.
const algosdk = require('algosdk'); const server="https://testnet-algorand.api.purestake.io/ps2"; const port=""; const token={ "x-api-key": "mV *** BY" // fill in yours }; var alice_mnemonic = "cash riot *** able can"; // fill in yours var aliceAccount = algosdk.mnemonicToSecretKey(alice_mnemonic); let client = new algosdk.Algodv2(token, server, port); (async () => { let params = await client.getTransactionParams().do(); let note = undefined; let addr = aliceAccount.addr; let defaultFrozen = false; let decimals = 0; let totalIssuance = 1000000; let unitName = "KCCOIN"; let assetName = "KC Coin"; let assetURL = "http://someurl"; let assetMetadataHash = "01234567890123456789012345678901"; let manager = aliceAccount.addr; let reserve = aliceAccount.addr; let freeze = aliceAccount.addr; let clawback = aliceAccount.addr; let txn = algosdk.makeAssetCreateTxnWithSuggestedParams(addr, note, totalIssuance, decimals, defaultFrozen, manager, reserve, freeze, clawback, unitName, assetName, assetURL, assetMetadataHash, params); let rawSignedTxn = txn.signTxn(aliceAccount.sk); let tx = (await client.sendRawTransaction(rawSignedTxn).do()); console.log("Transaction : " + tx.txId); })().catch(e => { console.log(e); });
We are using algosdk.makeAssetCreateTxnWithSuggestedParams
to construct a transaction for asset creation (line 29).
Note the Asset ID (here is 13300122). We will use this in other scripts.
Step 2: Transfer of ASA with Receiver not Opt-in
Here is the script asa_aliceSendToBob.js
to perform a transfer of 200k KCCOINs from Alice to Bob.
const algosdk = require('algosdk'); const server="https://testnet-algorand.api.purestake.io/ps2"; const port=""; const token={ "x-api-key": "mV *** BY" // fill in yours }; var alice_mnemonic = "cash riot *** able can"; // fill in yours var aliceAccount = algosdk.mnemonicToSecretKey(alice_mnemonic); var bobAddress = 'BDGUP3RKI3DJVM327B3R4SYT6PQUJBMDMQWHQICKSEQQT6PWCMNAYWEY4M'; // change to yours let client = new algosdk.Algodv2(token, server, port); (async () => { let assetID = 13300122; // change to your own assetID let params = await client.getTransactionParams().do(); let sender = aliceAccount.addr; let recipient = bobAddress; let revocationTarget = undefined; let closeRemainderTo = undefined; let note = undefined; let amount = 200000; let txn = algosdk.makeAssetTransferTxnWithSuggestedParams(sender, recipient, closeRemainderTo, revocationTarget, amount, note, assetID, params); let rawSignedTxn = txn.signTxn(aliceAccount.sk) let tx = (await client.sendRawTransaction(rawSignedTxn).do()); console.log("Transaction : " + tx.txId); })().catch(e => { console.log(e); });
We are using algosdk.makeAssetTransferTxnWithSuggestedParams
to construct a transaction for asset transfer (line 24).
When we execute this script and see the error message: Bob’s account (BDG…Y4M) does not opt-in yet (that asset is not in Bob’s account yet).
Step 3: Opt-in and Successful Transfer of ASA
The script asa_bobOptIn.js
makes Bob opt-in to KCCOIN.
const algosdk = require('algosdk'); const server="https://testnet-algorand.api.purestake.io/ps2"; const port=""; const token={ "x-api-key": "mV *** BY" // fill in yours }; var bob_mnemonic = "truth erase *** above magic"; // fill in yours var bobAccount = algosdk.mnemonicToSecretKey(bob_mnemonic); let client = new algosdk.Algodv2(token, server, port); (async () => { let assetID = 13300122; // change to your own assetID let params = await client.getTransactionParams().do(); let sender = bobAccount.addr; let recipient = sender; let revocationTarget = undefined; let closeRemainderTo = undefined; let note = undefined; let amount = 0; let txn = algosdk.makeAssetTransferTxnWithSuggestedParams(sender, recipient, closeRemainderTo, revocationTarget, amount, note, assetID, params); let rawSignedTxn = txn.signTxn(bobAccount.sk) let tx = (await client.sendRawTransaction(rawSignedTxn).do()); console.log("Transaction : " + tx.txId); })().catch(e => { console.log(e); });
Note that the opt-in is done by sending a transaction to oneself with the asset ID and amount zero (line 15, 17, 18 and 22).
After opt-in, we see the asset is now in Bob’s account, with amount zero.
After opt-in Asset is seen in Bob’s account with amount zero.Now we execute this script to transfer 200k KCCOINs from Alice to Bob (previous script). It is successful. And the balance is updated.
Step 4: Observation in AlgoSigner
I have imported both Alice and Bob’s account into AlgoSigner. Here is the current status. We see Alice and Bob have one asset (ASA).
Both accounts are imported to my AlgoSigner wallet.And here are the details of both Alice and Bob. The right balance of KCCOIN is shown here in both accounts.
Alice’s account Bob’s accountStep 5: Alice sends 100k KCCOINs to Bob with AlgoSigner
We choose Alice account, click Send, and specify Bob’s address with the amount and the selected ASA (KCCOIN here).
Alice sends 100k KCCOINs to Bob in AlgoSignerA wallet login is required as approval.
Now we can check the balance again. The transfer is properly processed.
Step 6: Destroy ASA with Outstanding ASAs
Alice now destroys this asset with script asa_aliceDestroy.js
. Note that as there are still outstanding KCCOINs in other accounts, the deletion fails.
const algosdk = require('algosdk'); const server="https://testnet-algorand.api.purestake.io/ps2"; const port=""; const token={ "x-api-key": "mV *** BY" // fill in yours }; var alice_mnemonic = "cash riot *** able can"; // fill in yours var aliceAccount = algosdk.mnemonicToSecretKey(alice_mnemonic); let client = new algosdk.Algodv2(token, server, port); (async () => { let assetID = 13300122; // change to your own asset let params = await client.getTransactionParams().do(); let addr = aliceAccount.addr; let note = undefined; let txn = algosdk.makeAssetDestroyTxnWithSuggestedParams(addr, note, assetID, params); let rawSignedTxn = txn.signTxn(aliceAccount.sk); let tx = (await client.sendRawTransaction(rawSignedTxn).do()); console.log("Transaction : " + tx.txId); })().catch(e => { console.log(e); });
We are using algosdk.makeAssetDestroyTxnWithSuggestedParams
to construct a transaction for asset destruction (line 19).
We see the error here. Creator (Alice) does not have all the KCCOINs and therefore is unable to destroy this asset. Creator needs to hold all the amount issued before this asset can be destroyed.
Step 7: Return all ASA to Creator
We use AlgoSigner again to have Bob sending back 300k KCCOINs to Alice.
Bob sends 300k KCCOINs to Alice in AlgoSignerAnd after transaction is processed, we can check the balance again for both accounts.
Now all the ASAs are back to the creator. Creator (Alice) can destroy KCCOINs.
Step 8: Destroy ASA
Now Alice can destroy ASA.
It is interesting to note that the ASA is removed from Alice the creator. However, this transaction has no way to remove opt-in from other accounts. That is the reason we see the ASA still in Bob’s account despite the zero amount.
Step 9: Remove Opt-in
We use asa_bobRemoveOptIn.js
to remove Bob’s opt-in.
const algosdk = require('algosdk'); const server="https://testnet-algorand.api.purestake.io/ps2"; const port=""; const token={ "x-api-key": "mV *** BY" }; var bob_mnemonic = "truth erase *** above magic"; // fill in yours var bobAccount = algosdk.mnemonicToSecretKey(bob_mnemonic); var aliceAddress = '5SL7MUMPYFNDBHUD4L7J4LJRQCQWXQUD3RDK7SBGIDWPH3ZFK47BTH43HE'; // change to yours let client = new algosdk.Algodv2(token, server, port); (async () => { let assetID = 13300122; // change to your own assetID let params = await client.getTransactionParams().do(); let sender = bobAccount.addr; let recipient = aliceAddress; let revocationTarget = undefined; let closeRemainderTo = aliceAddress; let note = undefined; let amount = 0; let txn = algosdk.makeAssetTransferTxnWithSuggestedParams(sender, recipient, closeRemainderTo, revocationTarget, amount, note, assetID, params); let rawSignedTxn = txn.signTxn(bobAccount.sk) let tx = (await client.sendRawTransaction(rawSignedTxn).do()); console.log("Transaction : " + tx.txId); })().catch(e => { console.log(e); });
We are using a transaction with closeRemainderTo
set to the creator to construct a transaction for opt-in removal (line 22 and 25).
With this transaction being processed, we see no more asset in Bob’s account.
This ends our demonstration. We showed how to use JavaScript SDK to perform the basic lifecycle of digital assets in Algorand. We also used AlgoSigner, a chrome plug-in Algorand wallet, to make asset transfers. As mentioned before, ASA provides lots of options and feel free to explore more here. Besides, here is the complete code on JavaScript developed by Ryan Fox.Summary
This article has been published from the source link without modifications to the text. Only the headline has been changed.
Source link