Core patterns
Read state, drive the three execution paths, interpret statuses and handle errors with @bloxchain/sdk.
You need: SDK setup complete, an account address on Sepolia
Read state
Use a PublicClient and the read methods of each wrapper. All wrappers point at the same account address.
Who owns the account, who can recover it, who may broadcast
SecureOwnable.owner(), getRecovery(), getBroadcasters()
How long is the time lock
SecureOwnable.getTimeLockPeriodSec()
Which roles exist and who holds them
RuntimeRBAC.getSupportedRoles(), getRole(hash), getWalletRoles(address), hasRole(hash, address)
What an action's schema looks like
RuntimeRBAC.getFunctionSchema(selector)
Which requests are open
BaseStateMachine.getPendingTransactions(), getTransaction(txId)
Details and signatures: API reference.
The three execution paths
The Platform names three execution paths. Each maps to Protocol calls and permission steps.
Delayed release
Delayed
Time-locked request, then on-chain approve
Yes
Request: GuardController.executeWithTimeLock(...). After releaseTime: approveTimeLockExecution(txId). Cancel during the wait is also on chain.
Signed approval
Signed
Request on chain, approval signed off chain, submitted by a broadcaster
No (the signature is the authorisation)
Approver: MetaTransactionSigner.createSignedMetaTransactionForExisting(...). Broadcaster submits the signed approval.
One signature
One sign
Request and approval in one signature, submitted by a broadcaster
No
Requester: MetaTransactionSigner.createUnsignedMetaTransactionForNew(...), sign. Broadcaster: GuardController.requestAndApproveExecution(metaTx).
The nine action steps
Permissions are granted per step, not per path. There are nine steps, and each is a TxAction value in the SDK. Each step belongs to one of three phases: Request, Approval, Execute.
Step
TxAction
Phase
Pending Request
EXECUTE_TIME_DELAY_REQUEST
Request
Approve
EXECUTE_TIME_DELAY_APPROVE
Approval
Cancel
EXECUTE_TIME_DELAY_CANCEL
Approval
Sign and approve request
SIGN_META_REQUEST_AND_APPROVE
Request
Sign approval
SIGN_META_APPROVE
Approval
Sign cancellation
SIGN_META_CANCEL
Approval
Finalize approved request
EXECUTE_META_REQUEST_AND_APPROVE
Execute
Finalize approval
EXECUTE_META_APPROVE
Execute
Finalize cancellation
EXECUTE_META_CANCEL
Execute
A role needs the step for the phase it performs, and the matching gate on the handler selector that carries the step. Granting a step without its gate is the most common reason a correctly assigned wallet still cannot act. To grant either from code, see Configure an account programmatically. See also How governed operations work.
Delayed release
Request. A wallet with request permission calls
executeWithTimeLock(target, value, selector, params, gasLimit, operationType, { from }). A record is created with statusPENDINGandreleaseTime = now + timeLockPeriodSec.Wait. Approving before
releaseTimereverts.Approve. A wallet with approve permission calls
approveTimeLockExecution(txId, { from }). The record moves toEXECUTINGand the guarded call runs in the same transaction.Record. The record ends
COMPLETEDorFAILED. Cancelling a pending record ends itCANCELLED.
Always wait for the receipt before reading state.
Signed approval and One signature
Build the unsigned meta-transaction with
MetaTransactionSigner. The contract itself generates the EIP-712 digest, so the signed payload always matches what the chain verifies.Sign the raw digest, with no EIP-191 wrapper. The contract recovers the signer with a plain
ecrecoverover the digest itself, so any prefix breaks recovery. Use the signer'ssignMetaTransactionWithWallet(unsigned)for a browser or hardware wallet, which signs the digest as EIP-712 typed data, oraccount.sign({ hash: unsigned.message })when you hold the key in process. Do not reach for viem'ssignMessage, including its{ raw }form: it always prepends\x19Ethereum Signed Message:\nbefore hashing, which is exactly the prefix the contract cannot accept.Set a short deadline and use the signer's current nonce (
getSignerNonce). Nonces are per signer and sequential, so one signer's meta-transactions must be submitted in order.A Broadcaster submits the signed payload and pays gas. The handler selector in the payload must match the function actually used to submit.
Signed payloads can also leave your system as a .bloxmeta.json file and be imported into the Platform. See Signed files and Meta-transactions.
Statuses
Protocol statuses on the record: UNDEFINED, PENDING, EXECUTING, COMPLETED, FAILED, CANCELLED, plus PROCESSING_PAYMENT when an attached payment runs. There is no APPROVED status; approval moves a record straight from PENDING to EXECUTING.
The Platform layers user-facing labels on top of these. In Approvals, a PENDING record shows as Awaiting Approval or Awaiting Your Approval, with a State of Blocked while the time lock runs and Ready once it has passed. A signed but unsubmitted payload sits in the Approved tab as Ready to Execute, or Ready to Submit Cancellation for a signed cancellation, and becomes Expired once its deadline passes. While a submission confirms, rows read Submitting, Pending Confirmation, Executing and then Confirmed. Settled records show in History as Executed, Cancelled or Failed. See Approvals and the Glossary.
Errors
SDK errors extend
BloxchainError(code,details); contract calls raiseContractError(contractAddress,method); bad inputs raiseValidationError.A
FAILEDrecord means the guarded call reverted after approval. Read the revert data from the execution transaction.Most reverts before execution are policy denials: missing role, missing gate, target or recipient not on an allowlist, or an approval attempted before
releaseTime. Fix the policy, do not retry blindly.
Retries
Reads and simulations are safe to retry.
For writes, re-simulate after a failure. Re-sending a request creates a second
PENDINGrecord, which is rarely what you want.Respect the time lock: poll
getTransaction(txId).releaseTimeand approve only after it passes.For meta-transactions, a resubmitted payload with a consumed nonce or an expired deadline will revert. Sign a fresh one.
Worked examples
Short snippets verified against the Protocol reference, for a smart account on Sepolia. Install and client setup are covered once in SDK setup and authentication; these snippets assume publicClient, walletClient, account and accountAddress from that page, and RPC_URL, ACCOUNT_ADDRESS and (for writes) PRIVATE_KEY in your environment. Fuller samples: Basic examples and Protocol getting started.
Delayed release: request, wait, approve
A time-locked ownership transfer is the simplest end-to-end delayed request. The requester must be the owner or recovery address; approval is possible only after the time lock.
Delayed release: a guarded call to an allowlisted contract
For registered actions, the request goes through the guard. The target must be on the account's Allowed contracts list for that function.
Signed approval: sign off chain, submit with a broadcaster
The approver signs; a Broadcaster submits and pays gas. Sign the raw digest that the contract produced.
When the key is in process rather than in a wallet, sign the digest directly and attach the signature yourself:
txId is the pending record you are approving; metaTxParams (including the signer's current nonce and a deadline) is described in Meta-transactions. The same signed payload, saved as a .bloxmeta.json file, can be imported into the Platform under Approvals → Import signed file. See Signed files.
Configuration batches
Registering an action, creating a role, granting a gate or adding a destination to an allowlist all travel as signed configuration batches that a Broadcaster submits. The batch shape, a worked allowlist example and the idempotency rules are on Configure an account programmatically.
Wait for and check a transaction
A successful receipt on an approval does not by itself mean the guarded call succeeded. Read the record: COMPLETED means it ran, FAILED means it reverted inside the guard.
Runnable references
The Protocol repository ships SDK sanity suites under scripts/sanity-sdk/ (run with npm run test:sanity-sdk) that exercise SecureOwnable, RuntimeRBAC and GuardController end to end. Browse them at the pinned commit: scripts/sanity-sdk.
Version alignment
@bloxchain/sdk, @bloxchain/contracts and the deployed bytecode must come from the same release. See Releases and compatibility.
Related
Last updated
Was this helpful?