Skip to content

Transactions and batches

Declare mutable txcast resources by stable ID. Saving freezes the declaration; run creation resolves and freezes its current value.

import { defineWorkflow, schema } from "@txcast/workflow-sdk"
export default defineWorkflow({
name: "Token transfer",
input: schema.object({
recipient: schema.address(),
amount: schema.uint256(),
}),
output: schema.object({}),
references: {
treasury: {
kind: "controlled_account",
id: "018fe2f2-3f4a-7abc-8def-0123456789ab",
chainId: 1,
},
token: {
kind: "contract",
id: "018fe2f2-3f4a-7abc-8def-0123456789ac",
chainId: 1,
},
},
capabilities: {
effects: ["evm.transactions"],
networks: [1],
controlledAccounts: [{ fromReference: "treasury" }],
transactionTargets: { "1": [{ fromReference: "token" }] },
httpHosts: [],
notifications: false,
},
async run(ctx, input) {
await ctx.evm.transactions({
key: "transfer",
label: "Transfer token",
controlledAccountId: ctx.refs.treasury.id,
chainId: ctx.refs.token.chainId,
calls: [
{
kind: "registry-abi",
contractKey: ctx.refs.token.contractKey,
to: ctx.refs.token.address,
functionKey: "transfer(address,uint256)",
args: [input.recipient, input.amount],
},
],
maxResultBytes: 96_000,
})
return {}
},
})

Controlled accounts, address-book entries, and registered contracts are available through typed ctx.refs. A rename keeps working because the declaration uses a stable ID. A missing resource or ABI prevents run creation.

Transaction lists have no authored count ceiling inside the bounded canonical request. This allows a dynamic acquireBatch-style program to construct the exact array it needs.

Two structured forms are available:

  • kind: "registry-abi" selects a saved same-chain ABI by canonical contract key. An optional to may point at another valid address while retaining the saved contract as interface provenance.
  • kind: "abi" includes a frozen inline ABI fragment and target.

txcast independently encodes every call and freezes the actual target, value, calldata, function ABI, and ABI-source provenance for review.

kind: "raw" requires an exact target, calldata, value, human-readable label, and reason. It is a conspicuous escape hatch. Prefer a structured ABI call whenever possible.

Delegatecall is not available to authored calls.

A Safe list executes atomically. One call is a direct Safe CALL; multiple calls use MultiSendCallOnly with inner CALL operations. txcast freezes the Safe nonce, owners, threshold, typed data, and batch before accepting signatures. Eligible owners review, sign, and execute through their wallets.

An EOA list is deliberately sequential. txcast exposes one transaction at a time, pins its account nonce, and waits for confirmed success before exposing the next. Earlier confirmed calls remain onchain if a later call fails.

Calls from the same chain/account lane serialize globally. Different accounts or chains may make progress concurrently.