JavaScript SDK

The JavaScript SDK provides a set of stand alone functions and client wrappers for the kmd and algod processes. The stand alone functions allow you to do many of the kmd functions without having access to the kmd process, such as creating and signing a transaction, creating an account, getting a backup mnemonic and restoring an account. These functions are meant for quick integration code and offer the common functions that developers will need to interact with the algorand network.  The client wrappers provide additional functions that interact with the kmd and algod processes

Install the SDK

See the readme in the github repository for additional information.

Node.js

npm install algosdk

Browser

Download the SDK's minified JavaScript file from our repository.

<script src="algosdk.min.js"/>

Using Stand-Alone Functions

The stand-alone functions provide functions that are not reliant on the kmd or algod processes. These include the following functions:

  • generateAccount - This function can be used to create an account that can be used with the Algorand blockchain. It returns a JSON object containing an address and a secret key.
  • isValidAddress - This function allows you to verify that an address is a valid address. It returns either true or false.
  • mnemonicToSecretKey - This function takes a 25 word mnemonic and returns a JSON object containing an account and a secret key. This functions primary purpose is to recover an account.
  • secretKeyToMnemonic - This function retrieves the 25 word mnemonic when passed an account's secret key. When creating a new account this is often used to store the backup phrase.
  • mnemonicToMasterDerivationKey - This function takes a 25 word mnemonic and returns a master derivation key. This is primarily used with the kmd client wrapper to restore a wallet. It should only be used with kmd functions.
  • masterDerivationKeyToMnemonic - This function takes a master derivation key and returns a 25 word mnemonic. This is a helper function to be used with the kmd client wrapper. It allows you to use the JS SDK to get the backup phrase from a wallet managed by a kmd process.
  • signTransaction - This function allows the JS SDK to be used to sign a transaction stand alone, without using a kmd process.
  • signBid - This function allows the JS SDK to be used to sign a bid used in an Algorand auction.
  • encodeObj - The encodeObj function is used to encode arbitrary JavaScript objects. These encoded objects then can be written to a transaction note field.
  • decodeObj - This function decodes  encoded objects. This function can be used to decode arbitrary JavaScript. Objects that are retrieved from a transaction note field. 

Examples:

Using The Client Wrapper Functions

The client wrapper functions are provided for interacting with the kmd and algod processes directly. If you are using only the stand-alone functions of the SDK the following sections on the kmd and algod processes will not apply. For more information on the algod and kmd processes see the Node Overview documentation.

Start the algod and kmd Processes

When using the SDK, it can interact with the algod, kmd or both processes. The algod process starts automatically when nodes are started. The kmd process automatically starts when called using the goal command line tool but with a 60-second timeout. This means it will shut down when no activity is detected for 60 seconds. To make sure the kmd is available for use with the SDK you can use the goal kmd command to start the kmd process with an indefinite timeout. Typically this will be just entering the command:

goal kmd start -d <data-dir>

Once the kmd is started, it will create  kmd.net and kmd.token files within the data directory for kmd. The algod data directory also has the algod.net and algod.token files. These files contain the host and port number for the REST endpoints and API tokens that the SDK will need to communicate with their respective processes.

kmd Configuration for the Browser

If you plan on using the kmd client wrapper within the browser environment, you will need to be prepared to handle the CORS requirements that are implemented in the kmd process. The kmd will need to be configured to whitelist the domains that are allowed to access the kmd. This can be done by creating the kmd_config.json file in your kmd directory with the allowed-origins setting. This property accepts an array of URLs that are allowed to access the node’s kmd process. Additionally, the kmd must be started before accessing it’s API enpoint.

Examples:

Examples with Web Apps

Using Stand-Alone Functions

A simple webapp for generating an account is shown below:

      <!--html-->
      <html>

      <head>
          <meta charset="utf-8">
          <script src="algosdk.min.js"></script>
          <link rel="stylesheet" type="text/css" href="test.css">
      </head>

      <body>
          <p>
          <button class="styled" type="button" id='block'>
          Generate Account
          </button>
          </p>
          <textarea id="ta" name="ta"
                rows="1" cols="70">
          </textarea>
      </body>
      <script src="test.js"></script>

      </html>
      /*css*/
      .styled {
          border: 0;
          line-height: 2.5;
          padding: 0 20px;
          font-size: 1rem;
          text-align: center;
          color: #fff;
          text-shadow: 1px 1px 1px #000;
          border-radius: 10px;
          background-color: rgb(126, 134, 227);
          background-image: linear-gradient(to top left,
                                            rgba(0, 0, 0, .2),
                                            rgba(0, 0, 0, .2) 30%,
                                            rgba(0, 0, 0, 0));
          box-shadow: inset 2px 2px 3px rgba(255, 255, 255, .6),
                      inset -2px -2px 3px rgba(0, 0, 0, .6);
      }

      .styled:hover {
          background-color: rgba(126, 134, 227, 1);
      }

      .styled:active {
          box-shadow: inset -2px -2px 3px rgba(255, 255, 255, .6),
                      inset 2px 2px 3px rgba(0, 0, 0, .6);
      }
      body {
          padding: 3rem;
          font-size: 16px;
      }
      //javascript
      (function() {
          var tb = document.getElementById('block');
          var ta = document.getElementById('ta');
          var signKey = null;
          var account = null;

          if (tb) {
              tb.onclick = function() {
                  ta.innerHTML = "";
                  //create an account
                  try{
                      var account = algosdk.generateAccount();
                      console.log( account.addr );
                      ta.innerHTML = account.addr;
                  }
                  catch(err) {
                      ta.innerHTML = err.message;
                  }

              }
          }

      })();

Using Client Wrapper Functions

As a simple example we can access the algod process and display the latest block by using the following code. Please make sure to change the algod REST API server, port and API token variables in the JavaScript file. These values can be retrieved from the algod.net and algod.token files in your algod directory.

      <!--html-->
      <html>

      <head>
          <meta charset="utf-8">
          <script src="algosdk.min.js"></script>
          <link rel="stylesheet" type="text/css" href="test.css">
      </head>

      <body>
          <p>
          <button class="styled" type="button" id='block'>
          Get Latest Block
          </button>
          <textarea name="" id="ta" ></textarea>

      </body>
      <script src="test.js"></script>

      </html>
      /*css*/
      .styled {
          border: 0;
          line-height: 2.5;
          padding: 0 20px;
          font-size: 1rem;
          text-align: center;
          color: #fff;
          text-shadow: 1px 1px 1px #000;
          border-radius: 10px;
          background-color: rgb(126, 134, 227);
          background-image: linear-gradient(to top left,
                                            rgba(0, 0, 0, .2),
                                            rgba(0, 0, 0, .2) 30%,
                                            rgba(0, 0, 0, 0));
          box-shadow: inset 2px 2px 3px rgba(255, 255, 255, .6),
                      inset -2px -2px 3px rgba(0, 0, 0, .6);
      }

      .styled:hover {
          background-color: rgba(126, 134, 227, 1);
      }

      .styled:active {
          box-shadow: inset -2px -2px 3px rgba(255, 255, 255, .6),
                      inset 2px 2px 3px rgba(0, 0, 0, .6);
      }
      body {
          padding: 3rem;
          font-size: 16px;
      }

      textarea {
          width: 100%;
          min-height: 30rem;
          font-family: "Lucida Console", Monaco, monospace;
          font-size: 0.8rem;
          line-height: 1.2;
      }
      //javascript
      (function() {

          const atoken = "get your token from algod.net";
          const aserver = "http://127.0.0.1"; //verify this where the algod is running in algod.net
          const aport = 8080;//verify this is the port in algod.net


          var tb = document.getElementById('block');
          var ta = document.getElementById('ta');

          var signKey = null;
          var account = null;

          if (tb) {
              tb.onclick = function() {
                  ta.innerHTML = "";
                  const algodclient = new algosdk.Algod(atoken, aserver, aport);

                  (async () => {
                      let lastround = (await algodclient.status()).lastRound;
                      let block = (await algodclient.block(lastround));
                      var textedJson = JSON.stringify(block, undefined, 4);
                      ta.innerHTML = textedJson;
                      console.log(block);
                  })().catch(e => {
                      console.log(e);
                  });
              }
          }

      })();

Examples with Node

Using Stand-Alone Functions

The Readme from the github repository has many examples of using the stand-alone functions. The example below shows the use of many of these functions to create, backup, restore an account and sign a transaction.

//node example
const algosdk = require('algosdk');

//create an account
var account = algosdk.generateAccount();
console.log( account.addr );
//get backup phrase for account
var mnemonic = algosdk.secretKeyToMnemonic(account.sk);
console.log( mnemonic );
//Recover the account
var recovered_account = algosdk.mnemonicToSecretKey(mnemonic);
console.log( recovered_account.addr );
//check to see if account is valid
var isValid = algosdk.isValidAddress(recovered_account.addr);
console.log("Is this a valid address: " + isValid);
//create a transaction
let txn = {
  "from": recovered_account.addr,
  "to": "AEC4WDHXCDF4B5LBNXXRTB3IJTVJSWUZ4VJ4THPU2QGRJGTA3MIDFN3CQA",
  "fee": 1000,
  "amount": 1000,
  "firstRound": 5000,
  "lastRound": 5500,
  "note": new Uint8Array(0),
  "genesisID": "testnet-v31.0",
  "genesisHash": "JgsgCaCTqIaLeVhyL6XlRu3n7Rfk2FxMeK+wRSaQ7dI="
};

//sign the transaction
var signedTxn = algosdk.signTransaction(txn, recovered_account.sk);
console.log(signedTxn.txID);

A more elaborate example is available within the GitHub repository’s examples folder. The above example used a transaction where most of the fields are hard coded and the entire example can be run on a standalone machine that is not connected to the Algorand network. If you can connect to a network node you can use the wrapper functions to get specific suggested transaction parameters like the genesis hash and id. Additionally, you can retrieve the current round of the network and suggested fee. This model supports creating a transaction on an online node, signing it offline, and submitting the transaction online.

Retrieving Latest Block Information

To retrieve the latest block’s information you would use the algod client wrapper functions shown below.

const algosdk = require('algosdk');

//Retrieve the token, server and port values for your installation in the algod.net
//and algod.token files within the data directory
const atoken = "d60cb951132a5fed9dde1abeadd4ea02b2c8d9815ee1eb1cb932941eaa3821c8";
const aserver = "http://127.0.0.1";
const aport = 8080;

const algodclient = new algosdk.Algod(atoken, aserver, aport);

(async () => {
    let lastround = (await algodclient.status()).lastRound;
    let block = (await algodclient.block(lastround));
    console.log( block );
})().catch(e => {
    console.log(e);
});

Creating a New Wallet and Account Using kmd

The following example creates a wallet and generates an account within that wallet using the kmd.

const algosdk = require('algosdk');

//Retrieve the token, server and port values for your installation in the kmd.net
//and kmd.token files within the kmd directory
const kmdtoken = "33ddbaa45869ef169cfb572af0752016f6577efc2e30bbd8c6383d3b344a41e5";
const kmdserver = "http://127.0.0.1";
const kmdport = 7833;

const kmdclient = new algosdk.Kmd(kmdtoken, kmdserver, kmdport);


var walletid = null;
var wallethandle = null;


(async () => {
    let walletid = (await kmdclient.createWallet("MyTestWallet", "testpassword", "", "sqlite")).wallet.id;
    console.log("Created wallet.", walletid);

    let wallethandle = (await kmdclient.initWalletHandle(walletid, "testpassword")).wallet_handle_token;
    console.log("Got wallet handle.", wallethandle);

    let address = (await kmdclient.generateKey(wallethandle)).address;
    console.log("Created new account.", address);
})().catch(e => {
    console.log(e);
});

Backing Up and Restoring a Wallet

You can export a master derivation key from the wallet and convert it to a mnemonic phrase in order to back up any wallet generated accounts. This backup phrase will only allow you to recover wallet-generated keys; if you import an external key into a kmd-managed wallet, you'll need to back up that key by itself in order to recover it.


const algosdk = require('algosdk');

//Retrieve the token, server and port values for your installation in the kmd.net
//and kmd.token files within the kmd directory
const kmdtoken = "33ddbaa45869ef169cfb572af0752016f6577efc2e30bbd8c6383d3b344a41e5";
const kmdserver = "http://127.0.0.1";
const kmdport = 7833;

const kmdclient = new algosdk.Kmd(kmdtoken, kmdserver, kmdport);


  (async () => {
    //get a list of the wallets and find the one we are looking for
    var walletid = null;
    let wallets = (await kmdclient.listWallets()).wallets;
    console.log("List Wallet.", wallets);
    wallets.forEach(function (arrayItem) {
        console.log(arrayItem.name);
        if( arrayItem.name === 'MyTestWallet'){
            walletid = arrayItem.id;
        }
    });
    //Get a wallet handle
    let wallethandle = (await kmdclient.initWalletHandle(walletid, "testpassword")).wallet_handle_token;
    console.log("Got wallet handle.", wallethandle);
    //export the master derivation key
    let mdk = (await kmdclient.exportMasterDerivationKey(wallethandle, "testpassword")).master_derivation_key;
    console.log("mdk.", mdk);
    //get backup phrase to store offline in a safe place
    console.log(algosdk.masterDerivationKeyToMnemonic(mdk));
})().catch(e => {
    console.log(e);
});

To restore a wallet, convert the phrase to a key and pass it to CreateWallet. This call will fail if the wallet already exists:


const algosdk = require('algosdk');

//Retrieve the token, server and port values for your installation in the kmd.net
//and kmd.token files within the kmd directory
const kmdtoken = "33ddbaa45869ef169cfb572af0752016f6577efc2e30bbd8c6383d3b344a41e5";
const kmdserver = "http://127.0.0.1";
const kmdport = 7833;

const kmdclient = new algosdk.Kmd(kmdtoken, kmdserver, kmdport);

// Recover a wallet example
(async () => {
    //Get the master get from the backup phrase
    let mn = "palace common video because garlic acoustic diary also brand deliver napkin toddler allow sphere digital congress spy sweet method display comfort lesson royal abstract dad";
    let mdk =  (await algosdk.mnemonicToMasterDerivationKey(mn));
    console.log(mdk);
    //Create the wallet using the master derivation key
    let walletid = (await kmdclient.createWallet("RecoveredWalletName", "", mdk)).wallet.id;;
    console.log(walletid);
    //Get a wallet handle
    let wallethandle = (await kmdclient.initWalletHandle(walletid, "")).wallet_handle_token;
    console.log("Got wallet handle.", wallethandle);
    //Generate 1 address. You could generate multiple accounts
    let address = (await kmdclient.generateKey(wallethandle)).address;
    console.log("Created new account.", address);
})().catch(e => {
    console.log(e.text);
})

Signing and Submitting a Transaction

You can use the stand-alone functions to create and sign a transaction, but to submit it you will need access to an algod process. You will need to use an algod client wrapper function to submit it to the network. This can be done using code similar to the following:

const algosdk = require('algosdk');

//Retrieve the token, server and port values for your installation in the algod.net
//and algod.token files within the data directory
const atoken = "yourapitoken";
const aserver = "http://127.0.0.1";
const aport = 8080;

//Recover the account 
var mnemonic = "you mnemonic string"; 
var recoveredAccount = algosdk.mnemonicToSecretKey(mnemonic); 
console.log(recoveredAccount.addr);
//instantiate the algod wrapper
let algodclient = new algosdk.Algod(token, server, port); 
(async() => {
    //Get the relevant params from the algod
    let params = await algodclient.getTransactionParams();
    let endRound = params.lastRound + parseInt(1000);
    //create a transaction
    //note that the closeRemainderTo parameter is commented out
    //This parameter will clear the remaining funds in an account and 
    //send to the specified account if main transaction commits
    let txn = {
        "from": recoveredAccount.addr,
        "to": "AEC4WDHXCDF4B5LBNXXRTB3IJTVJSWUZ4VJ4THPU2QGRJGTA3MIDFN3CQA",
        "fee": 1000,
        "amount": 1000,
        "firstRound": params.lastRound,
        "lastRound": endRound,
        "genesisID": params.genesisID,
        "genesisHash": params.genesishashb64,
        "note": new Uint8Array(0),
        //"closeRemainderTo": "IDUTJEUIEVSMXTU4LGTJWZ2UE2E6TIODUKU6UW3FU3UKIQQ77RLUBBBFLA"
    };
    //sign the transaction
    let signedTxn = algosdk.signTransaction(txn, recoveredAccount.sk);
    //submit the transaction
    let tx = (await algodclient.sendRawTransaction(signedTxn.blob));
    console.log("Transaction : " + tx.txId);

})().catch(e => {
    console.log(e);
});

In the above example, we comment out the closeRemainderTo parameter. If you provide the closeRemainderTo parameter, your account will be cleared and the remaining funds will be transferred to the specified account. If you do provide this parameter, the transaction will fail if there are not enough funds being transferred to the closeRemainderTo account or the recipient of the transaction's account. Meaning they must wind up above minimum balance.

Locating a Transaction

Once a transaction is submitted and finalized into a block, you can find it later using several methods. If the node's archival property is not set to true, you will only be allowed to search a limited number of local blocks on your node. If the archival property is set to true the entire blockchain will be available for searching. It is important to understand that changing the archival mode property only affects future block storage, so if you set this to true and want to get the oldest blocks of the ledger stored locally you will need to remove your existing ledger files and let the node rebuild the ledger. See the node configuration settings page for details.

You can use the accounts' address with the transaction id and call the algod clients transactionInformation function to find a specific transaction. This call currently only reads through the last 1000 blocks:


let tx = (await algodclient.transactionInformation( address, txid ));

You can also iterate across all transactions for a given address and round range:

let params = await algodclient.getTransactionParams();
//get all transactions for an address for the last 1000 rounds
let txts = (await algodclient.transactionByAddress( addr, params.lastRound - 1000, params.lastRound ));
let lastTransaction = txts.transactions[txts.transactions.length-1];

You can also Iterate over all the blocks in a given range and search for a specific transaction. This is the least efficient method:

const algosdk = require('algosdk'); 

//Retrieve the token, server and port values for your installation in the algod.net
//and algod.token files within the data directory
const token = "yourapitoken";
const server = "http://127.0.0.1";
const port = 8080;
var txid = "CP6XWAGLBBLKL6ZVY542EXXCD5RHAICN4L6JJG4DUW3FRPJOQWMQ";


let algodclient = new algosdk.Algod(token, server, port);
(async () => {
    let params = await algodclient.getTransactionParams();
    mainloop:  
    for( let i=params.lastRound; i>(params.lastRound-100); i--){
        let block = (await algodclient.block(i));
        console.log("Number of Transactions: " + block.txns.transactions.length);
        let txcn = block.txns.transactions.length;
        for( let j=0; j < txcn -1; j++){
            if( block.txns.transactions[j].tx.substring(3) === txid){
                if (undefined !== block.txns.transactions[j].note && block.txns.transactions[j].note.length) {
                    let textedJson = JSON.stringify(block.txns.transactions[j], undefined, 4);
                    console.log( "Transaction: " + textedJson );
                    break mainloop;

                }
            }    


        }
    }
 
})().catch(e => {
    console.log(e);
});

Another option for locating any transaction on the blockchain quickly is to use the indexer on a node that already has the archival property set to true. This can be done by setting isIndexerActive to true in the node configuration. See the node configuration settings page for details on how to set it. Additional information is also available on Algorand Node Types. This will open up two REST calls, one of which is implemented in the SDK (/v1/transactions/{txid}):

const algosdk = require('algosdk');

//Retrieve the token, server and port values for your installation in the algod.net
//and algod.token files within the data directory
const token = "yourapitoken";
const server = "http://127.0.0.1";
const port = 8080;
var txid = "ZRMXP7FUM2MQB3JTXGL5JNUPH5BFBN7B6N4UAEOCOIZSPGH26UUQ";

let algodclient = new algosdk.Algod(token, server, port);
//submit the transaction
(async() => {
    // /v1/transactions/{txid}
    let tx = (await algodclient.transactionById(txid));
    var textedJson = JSON.stringify(tx, undefined, 4);
    console.log(textedJson);

})().catch(e => {
    console.log(e);
});

Writing to the Note Field of a Transaction

Up to 1kb of arbitrary data can be stored in any Transaction. This is done using the note field of the transaction. The data must first be encoded and the SDK provides a convenience function to do this. The following example creates a transaction and encodes an object into the note field.

const algosdk = require('algosdk');

//Retrieve the token, server and port values for your installation in the algod.net
//and algod.token files within the data directory
const token = "yourapitoken";
const server = "http://127.0.0.1";
const port = 8080;

//Recover the account
var mnemonic = "you mnemonic string";
var recoveredAccount = algosdk.mnemonicToSecretKey(mnemonic);
console.log(recoveredAccount.addr);
//check to see if account is valid
var isValid = algosdk.isValidAddress(recoveredAccount.addr);
console.log("Is this a valid address: " + isValid);


//instantiate the algod wrapper
let algodclient = new algosdk.Algod(token, server, port);
(async () => {
    //Get the relevant params from the algod
    let params = await algodclient.getTransactionParams();
    let endRound = params.lastRound + parseInt(1000);

    let person = {
        firstName: "John",
        lastName: "Doe",
        age: 50,
        eyeColor: "blue"
    };

    //create a transaction
    let txn = {
        "from": recoveredAccount.addr,
        "to": "7ZUECA7HFLZTXENRV24SHLU4AVPUTMTTDUFUBNBD64C73F3UHRTHAIOF6Q",
        "fee": params.fee,
        "amount": 100,
        "firstRound": params.lastRound,
        "lastRound": endRound,
        "genesisID": params.genesisID,
        "genesisHash": params.genesishashb64,
        "note": algosdk.encodeObj(person),
    };
    //sign the transaction
    let signedTxn = algosdk.signTransaction(txn, recoveredAccount.sk);

    let tx = (await algodclient.sendRawTransaction(signedTxn.blob));
    console.log("Transaction : " + tx.txId);

})().catch(e => {
    console.log(e);
});

Reading the Note Field of a Transaction

Up to 1kb of arbitrary data can be stored in any Transaction. This data can be stored and read from the transactions note field. If this data is encoded using the SDKs encodeObj function you can decode the data from the note field using the decodeObj function. Below is an example of using the account address and the transaction id to locate a specific transaction and decode the note field.

const algosdk = require('algosdk'); 

//Retrieve the token, server and port values for your installation in the algod.net
//and algod.token files within the data directory
const token = "yourapitoken";
const server = "http://127.0.0.1";
const port = 8080;
let txid = "MUPBNQ7RV3LDMQMHQCITDSO5EJO3Q62HN3IW4VV5GPJF7ETAJULQ";
let mnemonic = "your mnemonic string";
let recoveredAccount = algosdk.mnemonicToSecretKey(mnemonic);
console.log( recoveredAccount.addr );

let algodclient = new algosdk.Algod(token, server, port);
(async () => {
    let params = await algodclient.getTransactionParams();

    let tx = (await algodclient.transactionInformation( recoveredAccount.addr, txid ));
    let encodednote =   JSON.stringify(algosdk.decodeObj(tx.note), undefined, 4);
    console.log( "Decoded: " + encodednote );
 
})().catch(e => {
    console.log(e.error);
});

Creating a Multisignature Account and Signing a Transaction

Multisignature(multisig) accounts are made up of multiples standard accounts. The multisig account also has a threshold property that specifies how many signatures are required when signing a transaction. So if a multisig account has 5 associated accounts and a threshold of 3 then 3 of the 5 signatures are required to spend tokens from the account.  In the following example, we create a three account multisig account with a threshold of 2. Next, we create a transaction and sign with two accounts and submit it to the TestNet network. We also add a pause in to allow using the TestNet dispenser to put tokens into the newly created multisig account.

const algosdk = require('algosdk'); 
const token = "yourapitoken";
const server = "http://127.0.0.1";
const port = 8080;


const keypress = async() => {
    process.stdin.setRawMode(true)
    return new Promise(resolve => process.stdin.once('data', () => {
        process.stdin.setRawMode(false)
        resolve()
    }))
}


(async() => {
    //create an account
    var account1 = algosdk.generateAccount();
    console.log(account1.addr);
    //create an account
    var account2 = algosdk.generateAccount();
    console.log(account2.addr);
    //create an account
    var account3 = algosdk.generateAccount();
    console.log(account3.addr);

    //Setup the parameters for the multisig account
    const mparams = {
        version: 1,
        threshold: 2,
        addrs: [
            account1.addr,
            account2.addr,
            account3.addr,
        ],
    };

    var multsigaddr = algosdk.multisigAddress(mparams);
    console.log("Multisig Address: " + multsigaddr);
    //Pause execution to allow using the dispenser on testnet to put tokens in account
    console.log('Make sure address above has tokens using the dispenser');
    await keypress();
    try {
        let algodclient = new algosdk.Algod(token, server, port);

        //Get the relevant params from the algod
        let params = await algodclient.getTransactionParams();
        let endRound = params.lastRound + parseInt(1000);
        //example of how to write an object into the notefield

        //create a transaction
        let txn = {
            "from": multsigaddr,
            "to": "AEC4WDHXCDF4B5LBNXXRTB3IJTVJSWUZ4VJ4THPU2QGRJGTA3MIDFN3CQA",
            "fee": params.fee,
            "amount": 200000,
            "firstRound": params.lastRound,
            "lastRound": endRound,
            "genesisID": params.genesisID,
            "genesisHash": params.genesishashb64,
            "note": new Uint8Array(0)
        };
        //Sign wiith first signature
        let rawSignedTxn = algosdk.signMultisigTransaction(txn, mparams, account1.sk).blob;
        //sign with second account
        let twosigs = algosdk.appendSignMultisigTransaction(rawSignedTxn, mparams, account2.sk).blob;
        //submit the transaction
        let tx = (await algodclient.sendRawTransaction(twosigs));
        console.log("Transaction : " + tx.txId);

    } catch (err) {
        console.log(err); 
    }
})().then(process.exit)