Create Fungible Token On Algorand Using JavaScript SDK

What are fungible tokens?

  • Fungible tokens are the kind of asset which we can divide into multiple units.
  • Every unit is fundamentally the same and interchangeable, which means every unit is equal to another unit
  • Loyalty programs that provide rewards points that can be redeemed for goods or services or traded for merchandise or services are considered fungible.
  • Fiat currencies are also fungible and their representation on the blockchain is considered a stable coin. Example — USDT which maintains a steady value.
  • Tokenization of fungible tokens is a kind way to achieve all the benefits of blockchain technology.

How to create fungible tokens?

  • Algorand Fungible tokens are called Algorand Standard Assets (ASAs) after implementation.
  • Algorand Standard Assets (ASAs) are implemented by using a special transaction.
  • Algorand is different than other blockchains because some of the blockchains require smart contracts to represent an asset but smart contracts are not necessary for algorand to create a fungible token. Just need to specify a few parameters to identify as a Fungible Token. e.g., the total count is greater than 1.
  • For this example, we are going to use Javascript SDK.

Steps to create your Fungible Token in Algorand

  1. Install the “algodesk” package by declaring the following statement.
    const algosdk = require('algosdk');
  2. Create an Account using javascript SDK.
    const keypress = async () => {
    process.stdin.setRawMode(true)
    return new Promise(resolve => process.stdin.once('data', () => {
    process.stdin.setRawMode(false)
    resolve()
    }))
    }
    const createAccount = function () {
    try {
    // let account1_mnemonic = "goat march toilet hope fan federal around nut drip island tooth mango table deal diesel reform lecture warrior tent volcano able wheel marriage absorb minimum";
    // const myaccount = algosdk.mnemonicToSecretKey(account1_mnemonic);
    const myaccount = algosdk.generateAccount();
    console.log("Account Address = " + myaccount.addr);
    let account_mnemonic = algosdk.secretKeyToMnemonic(myaccount.sk);
    console.log("Account Mnemonic = " + account_mnemonic);
    console.log("Account created. Save off Mnemonic and address");
    console.log("Add funds to account using the TestNet Dispenser: ");
    console.log("https://dispenser.testnet.aws.algodev.network/?account=" + myaccount.addr);
    return myaccount;
    }
    catch (err) {
    console.log("err", err);
    }
    };
    Once the account is created successfully, need to add funds.
  3. Adding some funds to the created account. Visit the Algorand Testnet Dispenser site and request some Algos. You will get 5 Algos per request.
  4. Creating an Asset -
    For creating a fungible token we just need to specify some parameters and sign the transaction.
    async function createAsset(algodClient, RLT) {
    console.log("");
    console.log("==> CREATE ASSET");
    //Check account balance
    const accountInfo = await algodClient.accountInformation(RLT.addr).do();
    const startingAmount = accountInfo.amount;
    console.log("RLT account balance: %d microAlgos", startingAmount);
    // Construct the transaction const params = await algodClient.getTransactionParams().do();
    // comment out the next two lines to use suggested fee
    // params.fee = 1000;
    // params.flatFee = true;
    // const closeout = receiver; //closeRemainderTo
    // WARNING! all remaining funds in the sender account above will be sent to the closeRemainderTo Account
    // In order to keep all remaining funds in the sender account after tx, set closeout parameter to undefined.
    // For more info see:
    // https://developer.algorand.org/docs/reference/transactions/#payment-transaction
    // Asset creation specific parameters
    // The following parameters are asset specific
    // Throughout the example these will be re-used.
    // Whether user accounts will need to be unfrozen before transacting const defaultFrozen = false;
    // Used to display asset units to user
    const unitName = "RLTCOI";
    // Friendly name of the asset
    const assetName = "RLT's Artwork Coins@arc3";
    // Optional string pointing to a URL relating to the asset
    const url = "https://s3.amazonaws.com/your-bucket/metadata.json";
    // Optional hash commitment of some sort relating to the asset. 32 character length.
    // metadata can define the unitName and assetName as well.
    // see ASA metadata conventions here: https://github.com/algorandfoundation/ARCs/blob/main/ARCs/arc-0003.md
    // const metadataJSON = {
    // "name": "RLTCOI",
    // "description": "RLT's Coins",
    // "properties": {
    // "simple_property": "RLT's coins",
    // "rich_property": {
    // "name": "RLTCoi",
    // "value": "001",
    // "display_value": "001",
    // "class": "emphasis",
    // "css": {
    // "color": "#ffffff",
    // "font-weight": "bold",
    // "text-decoration": "underline"
    // }
    // },
    // "array_property": {
    // "name": "RLT Coins",
    // "value": [1, 2, 3, 4],
    // "class": "emphasis"
    // }
    // }
    // }
    // The following parameters are the only ones
    // that can be changed, and they have to be changed
    // by the current manager
    // Specified address can change reserve, freeze, clawback, and manager
    // If they are set to undefined at creation time, you will not be able to modify these later
    const managerAddr = RLT.addr; // OPTIONAL: FOR DEMO ONLY, USED TO DESTROY ASSET WITHIN THIS SCRIPT
    // Specified address is considered the asset reserve
    // (it has no special privileges, this is only informational)
    const reserveAddr = undefined;
    // Specified address can freeze or unfreeze user asset holdings
    const freezeAddr = undefined;
    // Specified address can revoke user asset holdings and send
    // them to other addresses
    const clawbackAddr = undefined;
    // Use actual asset total > 1 to create a Fungible Token
    // example 1:(fungible Tokens)
    // totalIssuance = 10, decimals = 0, result is 10 actual asset total
    // example 2: (fractional NFT, each is 0.1)
    // totalIssuance = 10, decimals = 1, result is 1.0 actual asset total
    // example 3: (NFT)
    // totalIssuance = 1, decimals = 0, result is 1 actual asset total
    // integer number of decimals for asset unit calculation
    const decimals = 0;
    const total = 100000; // how many of this asset there will be
    // temp fix for replit
    //const metadata2 = "16efaa3924a6fd9d3a4824799a4ac65d";
    const fullPath = __dirname + '/FT/metadata.json';
    const metadatafile = (await fs.readFileSync(fullPath)).toString();
    const hash = crypto.createHash('sha256');
    hash.update(metadatafile);
    // replit error - work around
    const metadata = "16efaa3924a6fd9d3a4824799a4ac65d";
    // replit error - the following only runs in debug mode in replit, and use this in your code
    // const metadata = new Uint8Array(hash.digest()); // use this in your code
  5. Sign the Transaction and send it.
    // signing and sending "txn" allows "addr" to create an asset
    const txn = algosdk.makeAssetCreateTxnWithSuggestedParamsFromObject({
    from: RLT.addr,
    total,
    decimals,
    assetName,
    unitName,
    assetURL: url,
    assetMetadataHash: metadata,
    defaultFrozen,
    freeze: freezeAddr,
    manager: managerAddr,
    clawback: clawbackAddr,
    reserve: reserveAddr,
    suggestedParams: params,});
    const rawSignedTxn = txn.signTxn(RLT.sk);
    const tx = (await algodClient.sendRawTransaction(rawSignedTxn).do());
    let assetID = null;
    // wait for transaction to be confirmed
    const ptx = await algosdk.waitForConfirmation(algodClient, tx.txId, 4);
    console.log("Transaction " + tx.txId + " confirmed in round " + ptx["confirmed-round"]);
    //Get the completed Transaction
    assetID = ptx["asset-index"];
    // console.log("AssetID = " + assetID);
    await printCreatedAsset(algodClient, RLT.addr, assetID);
    await printAssetHolding(algodClient, RLT.addr, assetID);
    console.log("You can verify the metadata-hash above in the asset creation details");
    console.log("Using terminal the Metadata hash should appear as identical to the output of");
    console.log("cat metadata.json | openssl dgst -sha256 -binary | openssl base64 -A");
    // console.log("That is: V6XCVkh97N3ym+eEZCSfWFyON3bT1PVHdCh6LwVvWPY=");
    return { assetID };
    }
  6. Lastly, we call the above function.
    async function firstFT() {
    try {
    let alice = createAccount();
    console.log("Press any key when the account is funded");
    await keypress();
    // Connect your client
    // const algodToken = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa';
    // const algodServer = 'http://localhost';
    // const algodPort = 4001;
    const algodToken = '2f3203f21e738a1de6110eba6984f9d03e5a95d7a577b34616854064cf2c0e7b';
    const algodServer = 'https://academy-algod.dev.aws.algodev.network';
    const algodPort = 443;
    let algodClient = new algosdk.Algodv2(algodToken, algodServer, algodPort);
    // CREATE ASSET
    const { assetID } = await createAsset(algodClient, RLT);
    }
    catch (err) {
    console.log("err", err);
    }
    process.exit();
    };
    firstFT();
  7. Finally, our Fungible Token is created you get this output.
    Account Address =
    S5AED44F5NXJ6C4FZ2VXVQFV4D2DDP3MAFTO3WLTSHU6RPNC3J3C5CNMP4
    Account Mnemonic = helmet autumn choose crumble path wise eye decade enhance letter picnic perfect swallow forget decide engage easy emotion modify coral carpet message win abstract bus
    Account created. Save off Mnemonic and address
    Add funds to account using the TestNet Dispenser:
    https://dispenser.testnet.aws.algodev.network/?account=S5AED44F5NXJ6C4FZ2VXVQFV4D2DDP3MAFTO3WLTSHU6RPNC3J3C5CNMP4
    Press any key when the account is funded
    Hint: hit control+c anytime to enter REPL.
    ==> CREATE ASSET
    Alice account balance: 5000000 microAlgos
    Transaction EBPS3QU7PIXXIJY2SHNINPXRMOSCZLLK7KHY5FN4I7MDPCZPLRCA confirmed in round 20622897
    AssetID = 80766669
    parms = {
    "creator": "S5AED44F5NXJ6C4FZ2VXVQFV4D2DDP3MAFTO3WLTSHU6RPNC3J3C5CNMP4",
    "decimals": 0,
    "default-frozen": false,
    "manager": "S5AED44F5NXJ6C4FZ2VXVQFV4D2DDP3MAFTO3WLTSHU6RPNC3J3C5CNMP4",
    "metadata-hash": "MTZlZmFhMzkyNGE2ZmQ5ZDNhNDgyNDc5OWE0YWM2NWQ=",
    "name": "Reveation Lab Token",
    "name-b64": "UmV2ZWF0aW9uIExhYiBUb2tlbg==",
    "total": 100000,
    "unit-name": "RLT",
    "unit-name-b64": "UkxU",
    "url": "https://gateway.pinata.cloud/ipfs/QmWKBf8hxJZQKMU56N4n8NwECE24hR2PZKPuA5RdfsuExj",
    "url-b64": "aHR0cHM6Ly9nYXRld2F5LnBpbmF0YS5jbG91ZC9pcGZzL1FtV0tCZjhoeEpaUUtNVTU2TjRuOE53RUNFMjRoUjJQWktQdUE1UmRmc3VFeGo="
    }
    assetholdinginfo = {
    "amount": 100000,
    "asset-id": 80766669,
    "is-frozen": false
    }
    You can verify the metadata-hash above in the asset creation details
    Using terminal the Metadata hash should appear as identical to the output of
    cat metadata.json | openssl dgst -sha256 -binary | openssl base64 -A
    We can confirm the transaction on Algorand explorer by visiting the Algorand Blockchain Explorer.
    The transaction ID for the above code is — EBPS3QU7PIXXIJY2SHNINPXRMOSCZLLK7KHY5FN4I7MDPCZPLRCA
  8. Algo Explorer result for RTL token on algorand blockchain.

Conclusion

Finally, our Fungible Token is created. Thank you!

Originally Published at Reveation Labs Blogs Page

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Reveation Labs

Reveation Labs

47 Followers

We are an established Blockchain Development Company based in the US, dealing in Blockchain, NFT Marketplace, Metaverse, Web 3.0, DeFi, and Tokenomics.