Skip to main content
Every action (POST /v1/actions/enter, /exit, or /manage) returns transactions[], each with an unsignedTransaction you sign and submit yourself. We construct. You sign; yield.xyz never holds keys and never signs on your behalf. This guide covers the parts of that contract that are the same across every yield: how to decode unsignedTransaction for the chain family you’re on, when to validate it before signing, and which of the two submission paths to use. For the request, sort, and poll loop itself, see Enter and exit flows.

Prerequisites

  • An action’s transactions[], already sorted by stepIndex with terminal transactions (CONFIRMED, SKIPPED, FAILED) filtered out. See Enter and exit flows.
  • A signer for the target chain: a raw key for local testing, an embedded/MPC wallet provider (see Embedded wallets), or a custody or HSM backend (see Custody and signing flows).
We construct. You sign. Inspect every unsignedTransaction before signing it, and never modify its values, whatever library you use to parse or re-key it.

Decode unsignedTransaction by chain family

unsignedTransaction is a string on most chains, but its encoding and structure are chain-family specific. Decode it before signing: Other supported chain families return unsignedTransaction in their own native encoding; the sign, submit, and poll pattern on this page still applies, decoded with that chain’s own SDK.

Validate before signing (optional)

Before signing, you can run the same validation engine that powers yield.xyz’s optional server-side Defense Mode, so a malformed or tampered unsignedTransaction is rejected in your own process rather than after a signature exists:
@yieldxyz/shield also ships as a standalone binary for non-Node stacks. See Shield integration for installation and the binary path; this call is the only step relevant to signing.

Sign and choose a submission path

Sign the decoded transaction with your chain-specific signer (see the per-family guides), then submit through exactly one of two paths for that transaction, never both: Both paths are idempotent for a repeat of the exact same signed payload or hash. Submitting a different signed transaction or hash for a transaction that is already at a terminal status returns 412 Precondition Failed; treat that as already settled and fetch the transaction instead of retrying.

Wait for confirmation, unless the action is batched

Sign and submit transactions[] in stepIndex order, waiting for each to reach a terminal transaction status before the next, unless the action’s executionPattern is batch. A batched action returns a single BATCH transaction whose unsignedTransaction is a JSON array of calls ({ to, data, value } per call, one entry per step that a non-batched action would otherwise return as separate transactions) for a smart account or wallet that supports atomic multi-call execution, such as EIP-5792 wallet_sendCalls. There is only one transaction to sign and submit, so there is no sequencing to wait on. See Enter and exit flows for the full branch on executionPattern.

Next steps

EVM signing

Parse and sign the JSON transaction with ethers.js or viem.

Solana signing

Detect legacy vs versioned encoding and sign with @solana/web3.js.

Embedded wallets

Wire an MPC or embedded wallet provider into the same sign and submit loop.

Custody and signing flows

Run this contract from a custody or HSM backend instead of a client signer.