Docs
Building

Tolk wrappers

Learn how to generate Tolk wrappers and use them in tests and scripts

acton wrapper generates a typed Tolk wrapper from a contract's compiler ABI. The wrapper exposes methods to create, deploy, send messages to, and call get methods on the contract — the same API works in both tests and scripts.

Generate a Tolk wrapper

Run acton wrapper with the contract name from Acton.toml:

acton wrapper Counter

This writes a Counter.gen.tolk wrapper to wrappers/ by default. The acton wrapper does not require a prior acton build run.

Generate wrappers for every contract in Acton.toml at once:

acton wrapper --all

When generating all wrappers, use --output-dir to choose a directory. --output is only for a single contract because it names one file.

Precompiled .boc contracts can also have wrappers when their contract section points types to a Tolk interface file:

Acton.toml
[contracts.Precompiled]
src = "contracts/Precompiled.boc"
types = "contracts/Precompiled.types.tolk"

Acton reads deployable code from the BoC and reads the ABI from Precompiled.types.tolk. A BoC contract without types is skipped by acton wrapper --all, and acton wrapper Precompiled reports that types is required. See Precompiled BoC contracts for the build and wrapper workflow.

Pass --test to also emit a runnable test stub alongside the wrapper:

acton wrapper Counter --test

The stub is written to tests/Counter.test.tolk and contains a setupTest() helper with an example test case ready to extend.

Wrapper file structure

The generated file provides:

  • Counter.fromStorage(storage) — initializes contract state from a storage struct instance and calculates the deployment address.
  • counter.deploy(from, config) — deploys the contract.
  • counter.send{MessageName}(from, ...) — one method per internal incoming message type declared in contract { incomingMessages: ... }.
  • counter.sendAny(from, body, config) — sends a custom internal body cell.
  • counter.sendExternal{MessageName}(...) — one method per external incoming message type declared in contract { incomingExternal: ... }; these methods return ExternalSendResult.
  • counter.sendAnyExternal(body) — sends a custom external-in body when the contract declares external incoming messages.
  • counter.{getMethodName}() — one method per declared get method.

Fine tune wrapper generation with the contract { ... } header in the contract entrypoint file:

  • storage: ... enables the typed fromStorage() initializer; without it, the initializer falls back to an untyped form.
  • incomingMessages: ... enables typed send{MessageName} helpers; without it, only the generic sendAny() internal-message helper is generated.
  • incomingExternal: ... enables sendExternal{MessageName} helpers and sendAnyExternal().

Use a wrapper in a Tolk test

Import the wrapper and any types it references, then create and deploy the contract:

tests/Counter.test.tolk
import "@wrappers/Counter.gen"
import "@contracts/types"
import "@acton/emulation/testing"
import "@acton/testing/expect"

get fun `test increase`() {
    val deployer = testing.treasury("deployer");

    val contract = Counter.fromStorage({ id: 0, counter: 0 });
    val deployResult = contract.deploy(deployer.address, { value: ton("0.05") });
    expect(deployResult).toHaveSuccessfulDeploy({ to: contract.address });

    val sendResult = contract.sendIncreaseCounter(deployer.address, 5);
    expect(sendResult).toHaveTransaction({ success: true });

    expect(contract.currentCounter()).toEqual(5);
}

See the testing guides for more.

Use a wrapper in a Tolk script

Replace testing.treasury() with scripts.wallet():

scripts/deploy.tolk
import "@wrappers/Counter.gen"
import "@contracts/types"
// Replaces @acton/emulation/testing:
import "@acton/emulation/scripts"

fun main() {
    val deployer = scripts.wallet("deployer");

    val contract = Counter.fromStorage({ id: 0, counter: 0 });
    val result = contract.deploy(deployer.address, { value: ton("0.05") });
    result.waitForFirstTransaction();

    println("Deployed to {}", contract.address);
}

Run and test locally first, then broadcast to testnet with --net:

acton script scripts/deploy.tolk
acton script scripts/deploy.tolk --net testnet

See the scripting guides for more.

Regenerate after contract changes

Regenerate the wrapper whenever the contract's storage struct, accepted messages, or get-methods change:

acton wrapper Counter

Generate a TypeScript wrapper

Pass --ts to emit a TypeScript wrapper:

acton wrapper Counter --ts

This writes a Counter.gen.ts wrapper to wrappers-ts/ by default.

Node.js, npm, and npx must be available in the PATH.

See the dApps development guide for working with TypeScript wrappers.

Configure wrapper defaults

Set per-project defaults in Acton.toml:

Acton.toml
[wrappers.tolk]
output-dir = "wrappers"
generate-test = true
test-output-dir = "tests"

[wrappers.typescript]
output-dir = "wrappers-ts"

See the build reference for all available fields.

See also

Last updated on

On this page