executePrepared
Re-check market state, simulate as the wallet, send the prepared call, and wait for a typed receipt.
Sends a frozen PreparedAction. This is the write path for trades and other SDK actions.
Internally this is the viem pattern: simulateContract as the wallet account, then sendTransaction. It does not rewrite calldata. If the market moved, you get StaleStateError instead of a silent re-quote.
Floor actions (raiseIfEligible, raiseManyIfEligible) skip that market-stale check because prepared.to is the controller or Multicall3, not the FloorMarket. Offset-perp actions instead set constraints.stateTarget to FloorMarket while prepared.to remains OffsetPerpMarket, so the correct curve state is checked before the actual perp selector is simulated. Use raiseIfEligible for floor actions and Prepare perps actions for perps.
Import
import { createSv3Client } from "@repo/contract-client";
Usage
const prepared = await sv3.trade.prepareBuyForReserveBudget({
market,
amount: parseUsdc("1"),
slippageBps: 100n,
});
const pending = await sv3.transactions.executePrepared(prepared);
const confirmed = await pending.wait();
confirmed.hash;
confirmed.events;
Flow:
- Confirm
walletClientand thataccountmatchesprepared.account. - Re-read
stateNonceandmarketStateHashfromconstraints.stateTarget ?? prepared.to. On mismatch throwStaleStateError. simulateContractwith the wallet account.sendTransaction.waitconfirms and decodes protocol events.
acceptStale: true skips the nonce check but still re-simulates and never rewrites calldata.
Return Value
Promise<PendingProtocolTransaction>
| Field | Meaning |
|---|---|
hash | Transaction hash |
request | The simulated request that was sent |
simulation | simulateContract result |
wait() | See wait |
wait() returns { hash, receipt, events }.
Parameters
prepared
- Type:
PreparedAction
From sv3.trade.prepare*, sv3.position.prepare*, or sv3.perp.prepare*. Frozen: to, data, functionName, args, deadline, constraints.
await sv3.transactions.executePrepared(prepared);
options.confirmations (optional)
- Type:
number
Passed through to wait.
await sv3.transactions.executePrepared(prepared, { confirmations: 2 });
options.acceptStale (optional)
- Type:
boolean - Default:
false
await sv3.transactions.executePrepared(prepared, { acceptStale: true });
options.permit (optional)
- Type:
PermitData
Pass a collected EIP-2612 signature. getRequirements never sends approve itself.
await sv3.transactions.executePrepared(prepared, { permit });
Error
| Error | When |
|---|---|
WalletClientRequiredError | No wallet |
AccountMismatchError | Prepared account ≠ wallet |
StaleStateError | Nonce or state hash moved |
SimulationFailedError | simulateContract reverted; cause is ProtocolRevertError |
TransactionRejectedError | Wallet rejected the send |
TransactionRevertedError | Mined revert; cause is decoded when possible |
See Errors.
Tips
- Always simulate as the connected account. Simulating as the zero address misses allowance and pause checks the wallet will hit.
- If you already have a hash (for example a wallet that sent outside the SDK), confirm with
sv3.transactions.wait(hash)instead.