SV3 logo

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:

  1. Confirm walletClient and that account matches prepared.account.
  2. Re-read stateNonce and marketStateHash from constraints.stateTarget ?? prepared.to. On mismatch throw StaleStateError.
  3. simulateContract with the wallet account.
  4. sendTransaction.
  5. wait confirms and decodes protocol events.

acceptStale: true skips the nonce check but still re-simulates and never rewrites calldata.

Return Value

Promise<PendingProtocolTransaction>

FieldMeaning
hashTransaction hash
requestThe simulated request that was sent
simulationsimulateContract 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

ErrorWhen
WalletClientRequiredErrorNo wallet
AccountMismatchErrorPrepared account ≠ wallet
StaleStateErrorNonce or state hash moved
SimulationFailedErrorsimulateContract reverted; cause is ProtocolRevertError
TransactionRejectedErrorWallet rejected the send
TransactionRevertedErrorMined 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.