Operations and Transactions

An Operation is the unit of write in CRE Connect. It packages one or more EVM transactions into a single, atomic, EIP-712-signed batch that a Smart Account executes on behalf of your application without your application managing gas, nonces, or relayers. If any transaction in the batch reverts, the entire Operation reverts.

For deferred-signing workflows, see Draft Operations. For the underlying signing mechanism and the on-chain execution model, see EIP-712 Signing and Smart Accounts.

Data model

An Operation is composed of two structs that live in transact/types:

type Transaction struct {
    To    common.Address  `json:"to"`
    Value *big.Int        `json:"value,string"`
    Data  hexutil.Bytes   `json:"data"`
}

type Operation struct {
    ID           *big.Int        `json:"id"`
    Account      common.Address  `json:"account"`
    Deadline     *big.Int        `json:"deadline"`
    Transactions []Transaction   `json:"transactions"`
}
Field
Meaning
IDThe wallet operation ID. A nonce-like value chosen by the client. When you call ExecuteTransactions, the SDK generates a random 128-bit ID; when you construct an Operation manually, you choose the ID yourself.
AccountThe Smart Account address (the wallet) that will execute the Operation. This must equal the verifyingContract of the EIP-712 domain.
DeadlineA Unix timestamp after which the Operation must not be executed. The DON ignores Operations whose deadline has passed.
TransactionsAn ordered list of Transaction structs. They execute in order, atomically.

Each Transaction is just (to, value, data), exactly what you would pass to eth_sendTransaction, except the sender is the Smart Account, not the EOA that signed the Operation.

End-to-end flow

Signing

The SDK signs the Operation client-side using EIP-712 typed data. The domain is fixed across CRE Connect:

FieldValue
nameCLLSmartAccount
version1
chainIdDerived from the chainSelector argument via GetChainIDFromSelector.
verifyingContractThe Smart Account address (Operation.Account).

The signing key can be any implementation of the signer.Signer interface: local ECDSA, AWS KMS, HashiCorp Vault, Fireblocks, Privy, or your own custom adapter.

Submission helpers

The SDK exposes two entry points on client.Transact:

ExecuteTransactions

The high-level helper. Builds the Operation, signs it, and submits it in one call.

op, err := client.Transact.ExecuteTransactions(
    ctx,
    channelID,                    // uuid.UUID
    operationSigner,              // signer.Signer
    smartAccountAddress,          // common.Address
    []types.Transaction{tx1, tx2},
    big.NewInt(time.Now().Add(15*time.Minute).Unix()), // deadline
    chainSelector,                // string
)

ExecuteTransactions generates a random 128-bit wallet operation ID, so two calls in the same second never collide. If you construct the Operation manually instead, you own the ID: make it unique per Smart Account, because the Smart Account rejects re-used IDs.

ExecuteOperation

Lower-level: takes a fully-formed *types.Operation (so you can override ID or assemble a complex multi-transaction batch yourself), signs it, and submits it. Use this when you need precise nonce control or want to construct the Operation through extension builders such as the DTA Prepare*Operation helpers.

op, err := client.Transact.ExecuteOperation(ctx, channelID, signer, builtOperation, chainSelector)

Draft operations

Operations can also be created without a signature. CRE Connect stores these as draft operations in pending_signature state until your application finalizes them with a digest and signature, cancels them, or lets their deadline expire.

Drafts are useful when the signer is not available synchronously: MPC policy approval, human review, KMS approval workflows, or UIs that show decoded transaction previews before the user signs. See Draft Operations for the model and Draft Operations: Create, Finalize, Cancel for the SDK flow.

Lifecycle

The submitted Operation is observable through the channel's event stream. A signed operation starts at accepted; a draft starts at pending_signature and must be finalized before relay. From there, CRE Connect reports relay progress, progressive on-chain confirmation, cancellation, expiration, or failure through operation.status events.

For the complete state diagram and status table, see Lifecycles. For the confirmation model, see Multi-Event Finality. For polling and event verification patterns, see Submit and Track Operations.

Draft lifecycle events (pending_signature, cancelled, expired) are operational notifications without DON proofs. Confirmation events (confirmed_latest, confirmed_safe, confirmed) carry DON proofs and can be verified with client.Events.VerifyOperationStatus.

Atomicity

All transactions in a single Operation execute atomically: the Smart Account either executes every transaction successfully, or it reverts the entire batch. This guarantee makes Operations useful for multi-step on-chain flows, for example, "approve token + call DTA contract + emit auxiliary log", that would otherwise require careful retry handling on partial failure.

If you need all-or-some semantics (e.g. several independent token transfers that should succeed independently), submit them as separate Operations, one Operation per transaction. See Batch Transactions for guidance on choosing.

Get the latest Chainlink content straight to your inbox.