js-algorand-sdk
![npm version](https://badge.fury.io/js/algosdk.svg)
AlgoSDK is a javascript library for communicating with the Algorand network for modern browsers and node.js.
Installation
node.js
$ npm install algosdk
Browser
The dist
directory contains a minified version of the library - algosdk.min.js
.
Include this line in your HTML.
<script src="algosdk.min.js"/>
SDK Development
Run tests with make docker-test
Quick Start
const token = "Your algod API token";
const server = "http://127.0.0.1";
const port = 8080;
const client = new algosdk.Algod(token, server, port);
(async () => {
console.log(await client.status());
})().catch(e => {
console.log(e);
});
Documentation
For detailed information about the different API calls in client
, visit https://developer.algorand.org
Usage
Generate an Algorand account
var keys = algosdk.generateAccount();
Example result
{addr: "IB3NJALXLDX5JLYCD4TMTMLVCKDRZNS4JONHMIWD6XM7DSKYR7MWHI6I7U", sk: Uint8Array(64)}
Secret key to mnemonic
var mnemonic = algosdk.secretKeyToMnemonic(keys.sk);
Example result
"gorilla fortune learn marble essay uphold defense hover index effort ice atom figure will improve mom indoor mansion people elder hill material donkey abandon gown"
Mnemonic to secret sey
var secret_key = algosdk.mnemonicToSecretKey(mnemonic);
Example result
{addr: "IB3NJALXLDX5JLYCD4TMTMLVCKDRZNS4JONHMIWD6XM7DSKYR7MWHI6I7U", sk: Uint8Array(64)}
Check the validity of an Address
var isValid = algosdk.isValidAddress("IB3NJALXLDX5JLYCD4TMTMLVCKDRZNS4JONHMIWD6XM7DSKYR7MWHI6I7U");
Example result
true
Sign a transaction
In order to create and sign a transaction, create first an object with the relevant properties.
There is no need to specify the from
address, it is computed directly from the secretKey.
Note -- The fields names must be identical to the following example's.
Note 2 -- In order to encode data into the note field, simply encode any JavaScript object using algosdk.encodeObj(o)
.
var txn = {
"to": "7ZUECA7HFLZTXENRV24SHLU4AVPUTMTTDUFUBNBD64C73F3UHRTHAIOF6Q",
"fee": 10,
"amount": 847,
"firstRound": 51,
"lastRound": 61,
"genesisID": "devnet-v33.0",
"genesisHash": "JgsgCaCTqIaLeVhyL6XlRu3n7Rfk2FxMeK+wRSaQ7dI=",
"closeRemainderTo": "IDUTJEUIEVSMXTU4LGTJWZ2UE2E6TIODUKU6UW3FU3UKIQQ77RLUBBBFLA",
"note": new Uint8Array(Buffer.from("6gAVR0Nsv5Y=", "base64"))
};
Then, call signTransaction
and pass the transaction along with relevant private key.
var signedTxn = algosdk.signTransaction(txn, keys.sk);
Now signedTxn
can be posted to the network via algod.sendRawTransaction()
.
Master derivation key to mnemonic
var mnemonic = algosdk.masterDerivationKeyToMnemonic(mdk);
Example result
label danger traffic dream path boss runway worry awful abuse stairs spare wasp clock steel impact swear eagle canal diagram nation upon creek abstract pride
Mnemonic to master derivation key
var mdk = algosdk.mnemonicToMasterDerivationKey(mnemonic);
Example result
Uint8Array(32)
Sign a bid
Bids have similar pattern to a transaction.
First, create an object with the bid's information
var bid = {
"bidderKey": "IB3NJALXLDX5JLYCD4TMTMLVCKDRZNS4JONHMIWD6XM7DSKYR7MWHI6I7U",
"auctionKey": "7ZUECA7HFLZTXENRV24SHLU4AVPUTMTTDUFUBNBD64C73F3UHRTHAIOF6Q",
"bidAmount": 1000,
"maxPrice": 10,
"bidID": 2,
"auctionID": 56
};
Then, call signBid
and pass the bid and information along with the private key.
var signedBid = algosdk.signBid(bid, keys.sk);
In order to send a bid to the network. Embbed the output of algosdk.signBid
to a transaction note
's field.
For example,
var txn = {
"to": "7ZUECA7HFLZTXENRV24SHLU4AVPUTMTTDUFUBNBD64C73F3UHRTHAIOF6Q",
"fee": 10,
"amount": 0,
"firstRound": 51,
"lastRound": 61,
"note": <signedBid>
};
Manipulating Multisig Transactions
This SDK also supports manipulating multisignature payment and keyreg transactions.
To create a multisignature transaction, first set up the multisignature identity:
const params = {
version: 1,
threshold: 2,
addrs: [
"DN7MBMCL5JQ3PFUQS7TMX5AH4EEKOBJVDUF4TCV6WERATKFLQF4MQUPZTA",
"BFRTECKTOOE7A5LHCF3TTEOH2A7BW46IYT2SX5VP6ANKEXHZYJY77SJTVM",
"47YPQTIGQEO7T4Y4RWDYWEKV6RTR2UNBQXBABEEGM72ESWDQNCQ52OPASU",
],
};
With these multisignature parameters, we can now create a (partially) signed multisignature transaction:
let mnem3 = "advice pudding treat near rule blouse same whisper inner electric quit surface sunny dismiss leader blood seat clown cost exist hospital century reform able sponsor";
let seed = passphrase.seedFromMnemonic(mnem3);
let sk = nacl.keyPairFromSeed(seed).secretKey;
let txn = {
"to": "47YPQTIGQEO7T4Y4RWDYWEKV6RTR2UNBQXBABEEGM72ESWDQNCQ52OPASU",
"fee": 10,
"amount": 10000,
"firstRound": 1000,
"lastRound": 1000,
"genesisID": "devnet-v33.0",
"genesisHash": "JgsgCaCTqIaLeVhyL6XlRu3n7Rfk2FxMeK+wRSaQ7dI=",
"closeRemainderTo": "IDUTJEUIEVSMXTU4LGTJWZ2UE2E6TIODUKU6UW3FU3UKIQQ77RLUBBBFLA",
"note": new Uint8Array(Buffer.from("6gAVR0Nsv5Y=", "base64")),
};
let rawSignedTxn = algosdk.signMultisigTransaction(txn, params, sk).blob;
Now, we can broadcast this raw partially signed transaction to the network, which is valid if the threhsold is 1.
We can also write it to a file (in node):
const fs = require('fs');
fs.writeFile("/tmp/example_multisig.tx", Buffer.from(rawSignedTxn), function(err) {
if(err) {
return console.log(err);
}
console.log("The file was saved!");
});
We can import multiple files or raw signed transactions, and merge the multisignature transactions:
let partialTxn1 = new Uint8Array(fs.readFileSync('/tmp/example_multisig.tx'));
let partialTxn2 = new Uint8Array(fs.readFileSync('/tmp/example_multisig_two.tx'));
let mergedTsigTxn = algosdk.mergeMultisigTransactions([partialTxn1, partialTxn2]);
We can also append our own signature, with knowledge of the public identity (params):
let partialTxn1 = new Uint8Array(fs.readFileSync('/tmp/example_multisig.tx'));
const params = {
version: 1,
threshold: 2,
addrs: [
"DN7MBMCL5JQ3PFUQS7TMX5AH4EEKOBJVDUF4TCV6WERATKFLQF4MQUPZTA",
"BFRTECKTOOE7A5LHCF3TTEOH2A7BW46IYT2SX5VP6ANKEXHZYJY77SJTVM",
"47YPQTIGQEO7T4Y4RWDYWEKV6RTR2UNBQXBABEEGM72ESWDQNCQ52OPASU",
],
};
let mnem1 = "auction inquiry lava second expand liberty glass involve ginger illness length room item discover ahead table doctor term tackle cement bonus profit right above catch";
let seed = passphrase.seedFromMnemonic(mnem1);
let sk = nacl.keyPairFromSeed(seed).secretKey;
let appendedMsigTxn = algosdk.appendSignMultisigTransaction(partialTxn1, params, sk).blob;
Any transaction blob returned by the multisignature API can be submitted to the network:
let algodclient = new algosdk.Algod(atoken, aserver, aport);
(async () => {
let tx = (await algodclient.sendRawTransaction(appendedMsigTxn));
console.log(tx);
})().catch(e => {
console.log(e.error);
});
Transaction group
Example below show how to group and send transactions:
let txns = [...];
let sks = [...];
assert(txns.length == sks.length);
let txgroup = algosdk.assignGroupID(txns);
assert(txgroup.length == sks.length);
let signed = [];
for (let idx in txgroup) {
signed.push(algosdk.signTransaction(txgroup[idx], sks[idx]));
}
let algodclient = new algosdk.Algod(atoken, aserver, aport);
algodclient.sendRawTransactions(signed);
LogicSig Transactions
Demonstrate delegation for a standard account.
let mnem = "auction inquiry lava second expand liberty glass involve ginger illness length room item discover ahead table doctor term tackle cement bonus profit right above catch";
let seed = passphrase.seedFromMnemonic(mnem1);
let keys = nacl.keyPairFromSeed(seed);
let sender_pk = address.encode(keys.publicKey)
let program = Uint8Array.from([1, 32, 1, 0, 34]);
let lsig = algosdk.makeLogicSig(program);
lsig.sign(keys.secretKey);
assert lsig.verify(sender_pk);
let txn = {
"to": "47YPQTIGQEO7T4Y4RWDYWEKV6RTR2UNBQXBABEEGM72ESWDQNCQ52OPASU",
"from": sender,
"fee": 10,
"amount": 10000,
"firstRound": 1000,
"lastRound": 1000,
"genesisID": "devnet-v33.0",
"genesisHash": "JgsgCaCTqIaLeVhyL6XlRu3n7Rfk2FxMeK+wRSaQ7dI=",
"closeRemainderTo": "IDUTJEUIEVSMXTU4LGTJWZ2UE2E6TIODUKU6UW3FU3UKIQQ77RLUBBBFLA",
"note": new Uint8Array(Buffer.from("6gAVR0Nsv5Y=", "base64")),
};
let rawSignedTxn = algosdk.signLogicSigTransaction(txn, lsig).blob;
let algodclient = new algosdk.Algod(atoken, aserver, aport);
algodclient.sendRawTransaction(rawSignedTxn);
Assets
The Algorand protocol allows users to create and trade named assets on layer one. Creating and managing these assets
is done through the issuing of asset transactions. This section details how to make asset transactions, and what they do.
Asset creation: This allows a user to issue a new asset. The user can define the number of assets in circulation,
whether there is an account that can revoke assets, whether there is an account that can freeze user accounts,
whether there is an account that can be considered the asset reserve, and whether there is an account that can change
the other accounts. The creating user can also do things like specify a name for the asset.
let addr = "BH55E5RMBD4GYWXGX5W5PJ5JAHPGM5OXKDQH5DC4O2MGI7NW4H6VOE4CP4";
let fee = 10;
let defaultFrozen = false;
let genesisHash = "SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=";
let totalIssuance = 100;
let decimals = 0;
let reserve = addr;
let freeze = addr;
let clawback = addr;
let manager = addr;
let unitName = "tst";
let assetName = "testcoin";
let genesisID = "";
let firstRound = 322575;
let lastRound = 322575;
let note = undefined;
let assetURL = "http://someurl";
let assetMetadataHash = "16efaa3924a6fd9d3a4824799a4ac65d";
let txn = algosdk.makeAssetCreateTxn(addr, fee, firstRound, lastRound, note,
genesisHash, genesisID, totalIssuance, decimals, defaultFrozen, manager, reserve, freeze, clawback,
unitName, assetName, assetURL, assetMetadataHash);
Asset reconfiguration: This allows the address specified as manager
to change any of the special addresses for the asset,
such as the reserve address. To keep an address the same, it must be re-specified in each new configuration transaction.
Supplying an empty address is the same as turning the associated feature off for this asset. Once a special address
is set to the empty address, it can never change again. For example, if an asset configuration transaction specifying
clawback=""
were issued, the associated asset could never be revoked from asset holders, and clawback=""
would be
true for all time. The optional strictEmptyAddressChecking
argument can help with this behavior: when set to its default true
,
makeAssetConfigTxn
will throw
if any undefined
management addresses are passed.
let addr = "BH55E5RMBD4GYWXGX5W5PJ5JAHPGM5OXKDQH5DC4O2MGI7NW4H6VOE4CP4";
let fee = 10;
let assetIndex = 1234;
let genesisHash = "SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=";
let manager = addr;
let reserve = addr;
let freeze = addr;
let clawback = addr;
let genesisID = "";
let firstRound = 322575;
let lastRound = 322575;
let note = undefined;
let strictEmptyAddressChecking = true;
let txn = algosdk.makeAssetConfigTxn(addr, fee, firstRound, lastRound, note, genesisHash, genesisID,
assetIndex, manager, reserve, freeze, clawback, strictEmptyAddressChecking);
Asset destruction: This allows the creator to remove the asset from the ledger, if all outstanding assets are held
by the creator.
let addr = "BH55E5RMBD4GYWXGX5W5PJ5JAHPGM5OXKDQH5DC4O2MGI7NW4H6VOE4CP4";
let fee = 10;
let assetIndex = 1234;
let genesisHash = "SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=";
let genesisID = "";
let firstRound = 322575;
let lastRound = 322575;
let note = undefined;
let txn = algosdk.makeAssetDestroyTxn(addr, fee, firstRound, lastRound, note, genesisHash, genesisID, assetIndex);
Begin accepting an asset: Before a user can begin transacting with an asset, the user must first issue an asset acceptance transaction.
This is a special case of the asset transfer transaction, where the user sends 0 assets to themself. After issuing this transaction,
the user can begin transacting with the asset. Each new accepted asset increases the user's minimum balance.
let addr = "47YPQTIGQEO7T4Y4RWDYWEKV6RTR2UNBQXBABEEGM72ESWDQNCQ52OPASU";
let fee = 10;
let sender = addr;
let recipient = sender;
let revocationTarget = undefined;
let closeRemainderTo = undefined;
let assetIndex = 1234;
let amount = 0;
let genesisHash = "SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=";
let genesisID = "";
let firstRound = 322575;
let lastRound = 322575;
let note = undefined;
let txn = algosdk.makeAssetTransferTxn(sender, recipient, closeRemainderTo, revocationTarget,
fee, amount, firstRound, lastRound, note, genesisHash, genesisID, assetIndex);
Transfer an asset: This allows users to transact with assets, after they have issued asset acceptance transactions. The
optional closeRemainderTo
argument can be used to stop transacting with a particular asset. Note: A frozen account can always close
out to the asset creator.
let addr = "BH55E5RMBD4GYWXGX5W5PJ5JAHPGM5OXKDQH5DC4O2MGI7NW4H6VOE4CP4";
let fee = 10;
let sender = addr;
let recipient = "47YPQTIGQEO7T4Y4RWDYWEKV6RTR2UNBQXBABEEGM72ESWDQNCQ52OPASU";
let revocationTarget = undefined;
let closeRemainderTo = undefined;
let assetIndex = 1234;
let amount = 10;
let genesisHash = "SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=";
let genesisID = "";
let firstRound = 322575;
let lastRound = 322575;
let note = undefined;
let txn = algosdk.makeAssetTransferTxn(sender, recipient, closeRemainderTo, revocationTarget,
fee, amount, firstRound, lastRound, note, genesisHash, genesisID, assetIndex);
Revoke an asset: This allows an asset's revocation manager to transfer assets on behalf of another user. It will only work when
issued by the asset's revocation manager.
let addr = "BH55E5RMBD4GYWXGX5W5PJ5JAHPGM5OXKDQH5DC4O2MGI7NW4H6VOE4CP4";
let fee = 10;
let sender = addr;
let recipient = addr;
let revocationTarget = "47YPQTIGQEO7T4Y4RWDYWEKV6RTR2UNBQXBABEEGM72ESWDQNCQ52OPASU";
let closeRemainderTo = undefined;
let assetIndex = 1234;
let amount = 10;
let genesisHash = "SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=";
let genesisID = "";
let firstRound = 322575;
let lastRound = 322575;
let note = undefined;
let txn = algosdk.makeAssetTransferTxn(sender, recipient, closeRemainderTo, revocationTarget,
fee, amount, firstRound, lastRound, note, genesisHash, genesisID, assetIndex);
Rekeying
To rekey an account to a new address, simply call the addRekey
function on any transaction.
let txn = algosdk.makePaymentTxnWithSuggestedParams(from, to, amount, closeRemainderTo, note, suggestedParams);
txn.addRekey("47YPQTIGQEO7T4Y4RWDYWEKV6RTR2UNBQXBABEEGM72ESWDQNCQ52OPASU")
When submitting a transaction from an account that was rekeying, simply use relevant SK. algosdk.signTransaction
/transaction.signTxn
will detect
that the SK corresponding address is different than the sender's and will set the AuthAddr
accordingly. Alternatively, you can use kmdclient.signTransactionWithSpecificPublicKey
.
Application Calls
The Algorand protocol allows users to define stateful TEAL contracts, also known as applications.
The makeApplicationCreateTxn
allows you to create an application:
let from = "47YPQTIGQEO7T4Y4RWDYWEKV6RTR2UNBQXBABEEGM72ESWDQNCQ52OPASU"
let approvalProgram = getApprovalProgram();
let clearProgram = getClearProgram();
let numLocalInts = 1;
let numLocalByteSlices = 1;
let numGlobalInts = 1;
let numGlobalByteSlices = 1;
let createTxn = algosdk.makeApplicationCreateTxn(from, suggestedParams, onComplete, approvalProgram, clearProgram,
numLocalInts, numLocalByteSlices, numGlobalInts, numGlobalByteSlices);
Once created, an application can have its approval and clear programs updated with makeApplicationUpdateTxn
:
let updateTxn = algosdk.makeApplicationUpdateTxn(from, suggestedParams, appIndex, newApprovalProgram, newClearProgram);
Likewise, the application can later be deleted by its creator:
let deleteTxn = algosdk.makeApplicationDeleteTxn(from, suggestedParams, appIndex);
Users have several transaction types for interacting with applications. To begin using an application, a user must first opt in with an opt-in transaction, similar to opting in to an asset:
let optInTxn = algosdk.makeApplicationOptInTxn(userAddress, suggestedParams, appIndex);
After opting in, a user can call the application with a no-op transaction:
let callAppTxn = algosdk.makeApplicationNoOpTxn(userAddress, suggestedParams, appIndex);
The user also has two options for opting back out of an application. Closing out is the default way of opting out, clearing the user's state in the application, but it is subject to the approvalProgram
and so may fail:
let closeOutTxn = algosdk.makeApplicationCloseOutTxn(userAddress, suggestedParams, appIndex);
For a forced opt-out, the user also has the option of submitting a clear state transaction, guaranteeing the user can reclaim their minBalance
.
let clearStateTxn = algosdk.makeApplicationClearStateTxn(userAddress, suggestedParams, appIndex);
These application transaction-making functions also support additional optional fields like the note
field - see each function's comments for more information.
License
js-algorand-sdk is licensed under a MIT license. See the LICENSE file for details.