AlgorandFungible TokenJavascript

Shayan Shaikh

Fri Apr 29 2022

Shayan Shaikh
blog

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');

  1. 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.

  1. Adding some funds to the created account. Visit the Algorand Testnet Dispenser site and request for some Algos. You will get 5 Algos per request.
  1. 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

  1. 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 };

    }

  1. 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();

  1. 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

  1. Algo Explorer result for RTL token on algorand blockchain.

    Algorand Blockchain Explorer

Conclusion

Finally our Fungible Token is created. Thank you!


Share post on
Recent Posts

Why Reveation Labs

We are a team that is technically proficient and simultaneously caring for your business. Our ideology is to provide the latest technologies that suit your business well.

Let’s discuss your requirements!

Give your business the next-gen technology it deserves. Be a part of our family of successful enterprises that work on high-end software solutions.

Experts
Experts

In all the latest technologies and developments.

Experts
Creative

To innovate the best solutions and pick the right technology for you.

Experts
Ethical

To always put you first & respect your business values and procedures.

Experts
Dedicated

To meet the deadlines and help you until the very end and beyond.

Experts
Approachable

For all your business needs and queries at any point of time.

Experts
Transparent

In our ways of working.