ExecutionClient.execute runs an arbitrary pre-signed EVM transaction inside an intent. Use this when TradingClient doesn’t cover what you’re doing: calling your own contract, deploying, or interacting with a non-AMM Flashnet contract.
Sign and submit
signedTx is the RLP-encoded EIP-1559 transaction, 0x-prefixed.
Bundle deposits with execution
Passdeposits alongside the signed tx to credit Spark transfers in the same intent that runs the call. Each deposit references an existing Spark transfer by id; the caller is responsible for issuing the Spark-side transfer first (execute does not touch the SparkWallet).
ACCEPTED until the deposit oracle confirms every transfer id against the Spark operator DB. Deposits land before the EVM transaction runs, so doThing can spend the just-credited balance.
For the single-intent round-trip (Spark → EVM → Spark) without managing the transfer leg yourself, use TradingClient.swap({ useAvailableBalance: true }).
Zero gas
Flashnet runsbaseFeePerGas = 0 and maxPriorityFeePerGas = 0 for every block. There is no base fee to charge and no priority fee to bid. Set both fee fields on your transaction to 0n. Viem’s estimateFeesPerGas defaults will inject non-zero floors that fight you; pass zero explicitly.
fetchEip1559Fees(rpcUrl) queries the node and returns the values it currently reports, so a future fee-policy change surfaces here without breaking clients. Note: it ships under the /execution subpath of the SDK barrel, not the root.
value field on a transaction) is denominated in 18-decimal wei. One sat is 10_000_000_000 wei (WEI_PER_SAT). Setting value: 100_000n sends 100,000 wei (a tiny fraction of a sat), not 100,000 sats. Multiply by WEI_PER_SAT when you mean sats.
Decoding reverts
When an execute intent’s transaction reverts, the gateway sets status toEXPIRED and packs the revert output into statusMessage:
decodeRevertReason translates the selector back to a name:
SparkGateway and Conductor errors plus Solidity built-ins. For your own contracts, pass extraErrors:
traceInnermostRevert walks the call trace and returns the deepest revert frame:
address, output (ABI-encoded revert bytes), depth, and optionally error and revertReason. There is no input field.
traceInnermostRevert uses debug_traceTransaction, which the gateway’s RPC proxy explicitly blocks. Point directRpcUrl at a full-node RPC that exposes the debug namespace (the localnet sequencer does; production typically uses an internal node). Calling against the gateway URL returns null.
Status lifecycle
| Stage | What happened |
|---|---|
ACCEPTED | Gateway took the intent: signature, expiry, and replay checks passed, and it is queued for sequencer admission. A deposit-shaped intent stays here while the deposit oracle confirms every referenced transfer against the Spark operator DB. |
INCLUDED_PENDING_FINALITY | The sequencer included the intent in a block. The EVM transaction ran successfully. Validators are signing the finality certificate. |
FINALIZED | Validators reached quorum. The action ran and settlement dispatched. |
EXPIRED | Terminal failure. The expiresAt deadline passed, gateway admission failed, the deposit oracle could not verify a transfer, or the EVM transaction reverted. statusMessage carries the reason. |
withdraw or withdrawToken if needed.
When to use this vs TradingClient
Use TradingClient | Use execute |
|---|---|
| Trading on Flashnet pools | Calling your own contract |
| Deposit + swap + withdraw atomically | Deposit + arbitrary call |
| Permit2 / EIP-2612 plumbing | Custom interaction patterns |
TradingClient for trading and execute for everything else.