Algob Console

Sometimes it’s nice to work with your contracts interactively for testing and debugging purposes, getting network config, paths, or for executing transactions by hand.

algob provides you an easy way to do this via an interactive console, with your contracts available and ready to use.

Usage

NOTE: Make sure you have installed algob and configured algob in your project. For creating and setting up a new project, click here.

  • To open console session run algob console in your project root.
  • To select network add --network networkName to the command.(eg. algob console --network localhost)
  • To exit algob console type .exit, ctrl + D or ctrl + C (twice).
  • To clear REPL console, use ctrl + L.
  • To enter multi-line mode type: .break.

After opening console, you should get the following: image

Globals

Following globals are available in an algob console REPL:

  • deployer : algob deployer in run mode. User can access checkpoints, get logic signature, transferAlgos and all other functions supported by algob deployer.
  • algodClient : algosdk.Algodv2- an instance of algorand driver based on the current network (default if --network flag is not passed).
  • algosdk : User can access algosdk package functions using this object. (eg. algosdk.encodeAddress(..))
  • algob : all algob exported functions (eg. algob.mkAccounts(..), algob.balanceOf(..) etc)

Example Walkthrough

For demonstration purpose, we will be using examples/asa project where user will be able to setup scripts and accounts, transfer algo’s (in microalgos) & ASA between accounts, interact with stateless smart contracts (contract account and delegation signature mode) using algob console.

Setup

In the examples/asa directory:

  1. Follow the README file
  2. deploy assets and smart contracts using algob deploy

This will deploy your assets (gold and tesla in this case) and store asc1 logic signature in checkpoint for delegated approval mode. Also, let’s initialize some of the accounts which we will use in further transactions.

Open a console session using algob console and initialize master account using deployer object

algob> masterAccount = deployer.accountsByName.get("master-account")

image

Similarly, initialize few more accounts (check algob.config.js for more details about accounts used in ASA template)

let goldOwner = deployer.accountsByName.get("alice");
let john = deployer.accountsByName.get("john");
let bob = deployer.accountsByName.get("bob");

You can also retreive asset information from checkpoints. Eg.

algob> deployer.asa
Map(1) {
  'gold' => {
    creator: 'EDXG4GGBEHFLNX6A7FGT3F6Z3TQGIU6WVVJNOXGYLVNTLWDOCEJJ35LWJY',
    txId: 'QBKYATG6Y7BS5A5NXE6OYRZ5B5TY22EOJC2UEK25GFMW5S7WVEVA',
    assetIndex: 25,
    confirmedRound: 3446,
    assetDef: {
      total: 5912599999515,
      decimals: 0,
      defaultFrozen: false,
      unitName: 'GLD',
      url: 'url',
      metadataHash: '12312442142141241244444411111133',
      note: 'note',
      noteb64: 'noteb64',
      manager: 'WWYNX3TKQYVEREVSW6QQP3SXSFOCE3SKUSEIVJ7YAGUPEACNI5UGI4DZCE',
      reserve: '2ILRL5YU3FZ4JDQZQVXEZUYKEWF7IEIGRRCPCMI36VKSGDMAS6FHSBXZDQ',
      freeze: 'WWYNX3TKQYVEREVSW6QQP3SXSFOCE3SKUSEIVJ7YAGUPEACNI5UGI4DZCE',
      clawback: 'WWYNX3TKQYVEREVSW6QQP3SXSFOCE3SKUSEIVJ7YAGUPEACNI5UGI4DZCE',
      optInAccNames: [Array]
    }
  }
}
algob>

image

Now, we show how to use algob.executeTransaction to execute transactions in an Algorand Network.

Transfer Algos

Here, we will transfer 1 Algo from masterAccount to john. Code can be found in /scrips/transfer/master-fund-john.js.

Transaction params looks like :

algob> rtypes = algob.runtime.types
algob> algoTransferParams = {
...   type: rtypes.TransactionType.TransferAlgo,
...   sign: rtypes.SignType.SecretKey,
...   fromAccount: masterAccount,
...   toAccountAddr: john.addr,
...   amountMicroAlgos: 1e6,
...   payFlags: { note: 'ALGO PAID' }
... };
{
  type: 0,
  sign: 0,
  fromAccount: {
    name: 'master-account',
    addr: 'WWYNX3TKQYVEREVSW6QQP3SXSFOCE3SKUSEIVJ7YAGUPEACNI5UGI4DZCE',
    sk: Uint8Array(64) [
       81, 210,  16, 184, 214, 254, 152, 138, 107, 191,  12,
      188, 175, 162,  72, 134,  82, 233, 249,  40,  97, 197,
      132,  81, 113,  16, 244,  19, 200, 221, 193, 155, 181,
      176, 219, 238, 106, 134,  42,  72, 146, 178, 183, 161,
        7, 238,  87, 145,  92,  34, 110,  74, 164, 136, 138,
      167, 248,   1, 168, 242,   0,  77,  71, 104
    ]
  },
  toAccountAddr: '2UBZKFR6RCZL7R24ZG327VKPTPJUPFM6WTG7PJG2ZJLU234F5RGXFLTAKA',
  amountMicroAlgos: 1000000,
  payFlags: { note: 'ALGO PAID' }
}

image

Executing the transaction above gives the following result:

algob> await algob.executeTransaction(deployer, algoTransferParams);
{
  'confirmed-round': 3727,
  'pool-error': '',
  'receiver-rewards': 184,
  'sender-rewards': 3997582,
  txn: {
    sig: Uint8Array(64) [
       57, 175,  29, 200,  41, 197,  17, 105,  16,   6, 207,
      212, 234,  17,  11, 212, 103, 128, 253,  57,  65, 153,
       47,  59, 220, 182, 226, 212,  35,  72, 248, 103, 123,
       76,   1, 223, 193, 196, 117, 231, 147,  45,  80,  53,
      104, 133, 229, 135, 144, 198,  21, 238,  73, 253, 177,
      135, 114, 142,  42,  36,  42,  97, 130,  11
    ],
    txn: {
      amt: 1000000,
      fee: 257000,
      fv: 3725,
      gen: 'private-v1',
      gh: [Uint8Array],
      lv: 4725,
      note: [Uint8Array],
      rcv: [Uint8Array],
      snd: [Uint8Array],
      type: 'pay'
    }
  }
}

image

Transfer Assets

We will transfer a single unit of gold ASA (which we deployed during the setup) from goldOwner to john. Relevant code can be found in /scrips/transfer/gold-to-john.js.

Let’s use .editor mode of REPL to write & execute multiple lines of code at once:-

algob> .editor
// Entering editor mode (Ctrl+D to finish, Ctrl+C to cancel)
const rtypes = algob.runtime.types;
const gold = deployer.asa.get('gold'); // asa info from checkpoint
const goldOwner = deployer.accountsByName.get('alice');
const john = deployer.accountsByName.get('john');
algob.executeTransaction(deployer, {
  type: rtypes.TransactionType.TransferAsset,
  sign: rtypes.SignType.SecretKey,
  fromAccount: goldOwner,
  toAccountAddr: john.addr,
  amount: 1,
  assetID: gold.assetIndex,
  payFlags: {}
});

image

After transferring ASA, you can also check the balance (asset holding) of john using algob.balanceOf(..)

algob> await algob.balanceOf(deployer, john.addr, gold.assetIndex);

image

Similar example can be found in /scrips/transfer/tesla-to-john.js (tesla ASA).

Transfer Algos according to ASC logic (Contract Account)

Here we will transfer some algos from a stateless smart contract (/assets/teal/2-gold-contract-asc.teal) to john.

  • We will first load the logic signature (using deployer.loadLogic(<file_name>.teal) and get it’s address(lsig.address()).
  • This address will be the sender(contract account mode) and receiver will be john.
  • Finally, we will transfer some algos using algob.executeTransaction(..) function. Transaction will pass/fail according to asc logic.
    lsig = await deployer.loadLogic("2-gold-contract-asc.teal");
    sender = lsig.address();
    

    image

The contract ensures that amount in microalgos must be <=100, otherwise the transaction will be rejected.

Transaction Pass:

algob> .editor
// Entering editor mode (Ctrl+D to finish, Ctrl+C to cancel)
// Transactions for Transaction for ALGO - Contract : '2-gold-contract-asc.teal'  (Contract Mode)
// sender is contract account
const algoTxParam = {
  type: rtypes.TransactionType.TransferAlgo,
  sign: rtypes.SignType.LogicSignature,
  fromAccountAddr: lsig.address(),
  toAccountAddr: john.addr,
  amountMicroAlgos: 20n, // amt <= 100
  lsig: lsig,
  payFlags: { totalFee: 1000 }
};

// Transaction PASS - As according to .teal logic, amount should be <= 100
algob.executeTransaction(deployer, algoTxParam);

{
  'confirmed-round': 4418,
  'pool-error': '',
  'receiver-rewards': 93,
  'sender-rewards': 1,
  txn: {
    lsig: { l: [Uint8Array] },
    txn: {
      amt: 20,
      fee: 1000,
      fv: 4416,
      gen: 'private-v1',
      gh: [Uint8Array],
      lv: 5416,
      rcv: [Uint8Array],
      snd: [Uint8Array],
      type: 'pay'
    }
  }
}

Transaction fail:

algob> .editor
// Entering editor mode (Ctrl+D to finish, Ctrl+C to cancel)
const invalidTxnParams = {
  type: rtypes.TransactionType.TransferAlgo,
  sign: rtypes.SignType.LogicSignature,
  fromAccountAddr: lsig.address(),
  toAccountAddr: john.addr,
  amountMicroAlgos: 200, // amt > 100
  lsig: lsig,
  payFlags: { totalFee: 1000 }
};

// Transaction FAIL - rejected by logic. According to .teal logic, amount should be <= 100
algob.executeTransaction(deployer, invalidTxnParams);

// rejected by logic
Error: Bad Request
    at Request.callback (/home/ratik/Scale-it/algo-builder/node_modules/superagent/src/node/index.js:879:15)
    at fn (/home/ratik/Scale-it/algo-builder/node_modules/superagent/src/node/index.js:1130:18)
    at IncomingMessage.<anonymous> (/home/ratik/Scale-it/algo-builder/node_modules/superagent/src/node/parsers/json.js:19:7)
...

Code can be found in /scripts/transfer/gold-contract-sc.js

Transfer Assets according to ASC (Delegated Approval)

Here, we will first transfer some Algorand Standard Assets(ASA) from goldOwner (delegating authority in this case) to john according to asc /assets/4-gold-asa.teal. goldOwner is the delegating authority here, as during deployment (algob deploy) the smart contract’s logic signature was signed by this account (check /scripts/2-gold-asc.js).

Logic signature (stored in checkpoint) is retreived using deployer.getDelegatedLsig('<file_name>.teal'). Assets are transferred using algob.executeTransaction({ type: TransactionType.TransferAsset, ...}).

Retreive lsig & assetId from checkpoint:

algob> lsigGoldOwner = deployer.getDelegatedLsig('4-gold-asa.teal');
LogicSig {
  tag: [
     80, 114, 111,
    103, 114,  97,
    109
  ],
  logic: [
     2,  32,   5,   1,   0,   4, 232,   7, 144,  78,  38,   1,
    32,  32, 238, 110,  24, 193,  33, 202, 182, 223, 192, 249,
    77,  61, 151, 217, 220, 224, 100,  83, 214, 173,  82, 215,
    92, 216,  93,  91,  53, 216, 110,  17,  18,  50,   4,  34,
    18,  49,  22,  35,  18,  16,  49,  18,  35,  18,  16,  49,
    16,  36,  18,  49,   0,  40,  18,  16,  49,  18,  37,  14,
    16,  17,  49,  16,  36,  18,  49,  32,  50,   3,  18,  16,
    49,   9,  50,   3,  18,  16,  49,   1,  33,   4,  14,  16,
    16
  ],
  args: [],
  sig: Uint8Array(64) [
     91, 218, 167,  24,  16, 245,  64, 176, 167, 113, 206,
    221,  37, 222, 184, 149,  22, 193, 197, 144,  50,  10,
    135, 207, 224,  74, 210, 194, 107,  66, 184, 151, 223,
    231, 203, 197, 255, 193, 187, 106, 184, 190, 204, 229,
     79, 143,  63, 255, 193,  56,  22,  46,  23, 200, 253,
     43, 126,  92, 137,  50,  26, 141, 222,  13
  ],
  msig: null
}
algob> assetID =  deployer.asa.get("gold").assetIndex;
25
algob>

Here, the smart contract rejects a transaction if Asset Amount > 1000. Transactions for passing & failing scenario are shown below :-

algob> .editor
// Entering editor mode (Ctrl+D to finish, Ctrl+C to cancel)
let validParams = {
  type: rtypes.TransactionType.TransferAsset,
  sign: rtypes.SignType.LogicSignature,
  fromAccountAddr: goldOwner.addr,
  toAccountAddr: john.addr,
  amount: 500,
  assetID: 'gold', // passing asa name is also supported
  lsig: lsigGoldOwner,
  payFlags: { totalFee: 1000 }
};

// Transaction PASS
algob.executeTransaction(deployer, validParams);

{
  'confirmed-round': 4628,
  'pool-error': '',
   ...
}

algob> .editor
// Entering editor mode (Ctrl+D to finish, Ctrl+C to cancel)
validParams.amount = 1500;

// Transaction FAIL
algob.executeTransaction(deployer, validParams);

Error: Bad Request
    at Request.callback (/home/ratik/Scale-it/algo-builder/node_modules/superagent/src/node/index.js:879:15)
    at fn (/home/ratik/Scale-it/algo-builder/node_modules/superagent/src/node/index.js:1130:18)
...

Code can be found in /scripts/transfer/gold-delegated-lsig.js

All smart contracts used in these examples can be found in /assets folder and scripts in /scripts/transfer folder.