State Management | Algorand Developer Portal

State Management

algorand-typescript-testing provides tools to test state-related abstractions in Algorand smart contracts. This guide covers global state, local state, boxes, and scratch space management.

import * as algots from '@algorandfoundation/algorand-typescript';

import { TestExecutionContext } from '@algorandfoundation/algorand-typescript-testing';

// Create the context manager for snippets below

const ctx = new TestExecutionContext();

Global State

Global state is represented as instance attributes on algots.Contract and algots.arc4.Contract classes.

class MyContract extends algots.arc4.Contract {

stateA = algots.GlobalState<algots.uint64>({ key: 'globalStateA' });

stateB = algots.GlobalState({ initialValue: algots.Uint64(1), key: 'globalStateB' });

}

// In your test

const contract = ctx.contract.create(MyContract);

contract.stateA.value = algots.Uint64(10);

contract.stateB.value = algots.Uint64(20);

Local State

Local state is defined similarly to global state, but accessed using account addresses as keys.

class MyContract extends algots.arc4.Contract {

localStateA = algots.LocalState<algots.uint64>({ key: 'localStateA' });

}

// In your test

const contract = ctx.contract.create(MyContract);

const account = ctx.any.account();

contract.localStateA(account).value = algots.Uint64(10);

Boxes

The framework supports various Box abstractions available in algorand-typescript.

class MyContract extends algots.arc4.Contract {

box: algots.Box<algots.uint64> | undefined;

boxMap = algots.BoxMap<algots.bytes, algots.uint64>({ keyPrefix: 'boxMap' });

@algots.arc4.abimethod()

someMethod(keyA: algots.bytes, keyB: algots.bytes, keyC: algots.bytes) {

this.box = algots.Box<algots.uint64>({ key: keyA });

this.box.value = algots.Uint64(1);

this.boxMap.set(keyB, algots.Uint64(1));

this.boxMap.set(keyC, algots.Uint64(2));

}

}

// In your test

const contract = ctx.contract.create(MyContract);

const keyA = algots.Bytes('keyA');

const keyB = algots.Bytes('keyB');

const keyC = algots.Bytes('keyC');

contract.someMethod(keyA, keyB, keyC);

// Access boxes

const boxContent = ctx.ledger.getBox(contract, keyA);

expect(ctx.ledger.boxExists(contract, keyA)).toBe(true);

// Set box content manually

ctx.ledger.setBox(contract, keyA, algots.op.itob(algots.Uint64(1)));

Scratch Space

Scratch space is represented as a list of 256 slots for each transaction.

@algots.contract({ scratchSlots: [1, 2, { from: 3, to: 20 }] })

class MyContract extends algots.Contract {

approvalProgram(): boolean {

algots.op.Scratch.store(1, algots.Uint64(5));

algots.assert(algots.op.Scratch.loadUint64(1) === algots.Uint64(5));

return true;

}

}

// In your test

const contract = ctx.contract.create(MyContract);

const result = contract.approvalProgram();

expect(result).toBe(true);

const scratchSpace = ctx.txn.lastGroup.getScratchSpace();

expect(scratchSpace[1]).toEqual(5);

For more detailed information, explore the example contracts in the examples/ directory, the coverage page, and the API documentation.

// test cleanup

ctx.reset();