Skip to main content
Every multichain transaction follows the same lifecycle, but each client exposes different boundaries. Embedded wallets manage preparation, authorization, and submission through sendIntent(). The custom signer SDK exposes each step. REST integrations call the endpoints directly.

Transaction lifecycle

  1. Define the destination, delivery, calls, and funding selection for your client.
  2. Prepare a route and review its inputs, outputs, fees, and expiry. SDK and direct HTTP integrations also review the plan, requirements, and ordered signing requests.
  3. Complete any token requirements for the account type.
  4. Authorize the exact prepared route.
  5. Submit the signed intent.
  6. Track the intent until it completes or fails.
An accepted submission is not an onchain success. Keep the intent ID so you can resume status checks without creating another transaction.

Follow the flow

Reuse the chains, token addresses, amount, and calls from Send a transaction.
Use the initialized wallet client from Accounts after the user signs in; sends always use the authenticated account.
1

Review, authorize, and submit

The Solana alternative delivers Base Sepolia USDC to the user’s ready Devnet wallet. Use a client configured to expose that managed wallet and follow setup first. Delivery itself is EVM-funded and does not need a Solana signature. For Solana-funded sends or instructions, experimental_solana and a retained fresh sign-in passkey are required; SOLANA_SIGN_IN_REQUIRED means sign in again. See availability.Embedded wallets prepare the route, handle their smart-account token requirements, request passkey approval, and submit the intent. They do not expose the custom signer SDK’s ranked quotes or separate signing and submission methods.Sponsorship is required by default. closeOn: "completed" waits for completion; waitForHash: true separately requests the onchain transaction hash. The user approves the passkey prompt from Rhinestone’s prepared-action review.Persist the whole result before handling errors: intentId, status, submitted, shouldResubmit, targetChain, source, recipient, tokenRequests, instructions, operationId, transactionHash, and refund when present. Do not reduce it to success or discard metadata on failure. transactionHash is destination-native: a Solana fill uses a base58 signature, not an EVM hash or the origin transaction. Refunds retain their own chain and native identifier. An omitted requested amount means max output, not zero or realized output.Save any non-empty result.intentId before handling errors. STATUS_TIMEOUT, HASH_TIMEOUT, or a dialog cancellation with an intent ID can occur after submission. They are not reasons to send a replacement intent. There is no intent history API, so an uncertain submission without an ID cannot be looked up later. Treat status: "submitted_uncertain" or submitted: true as possibly live, and do not send a replacement automatically.For a funded Solana action, wait for delivery to complete before a separate same-cluster instruction request. Keep both intent IDs: failed execution does not undo completed funding. Sponsorship supplies no instruction assets. Solana instruction sends track until completion, failure, expiry, the hashTimeoutMs window (120 seconds by default), or dialog closure; they may take longer to resolve, and tracking never resubmits.Logout, wallet switching, or fresh authentication invalidates unsubmitted work. Already dispatched completion may still execute after cancellation. Expired Solana quotes require explicit refresh and another Sign action.
2

Check or resume execution

Use getIntentStatus() when you have an intent ID. Check for a lookup error before interpreting the status:
Retain each status response’s outcome metadata, including destination-native identifiers and chain-qualified refunds, just as for the send result. The same status helper handles EVM and Solana intents; there is no need for separate VM-specific polling.The helper stops after 60 status requests. undefined means the outcome is still unknown, not failed; retain the ID for a later check. Stopping your poll does not cancel the intent.getIntentStatus() returns success: true only for completed; valid non-terminal statuses return success: false. A failed lookup returns status: "unknown" with an error such as STATUS_FAILED or NETWORK_ERROR. An error-free failed or expired status, by contrast, is an execution outcome.Status reads need the owner’s signed-in session. To resume after a reload, keep the intentId and query it once the same user signs in again. Without a session the lookup returns APP_ORIGIN_SESSION_REQUIRED; another user’s intent returns status: "unknown", like a missing one. Restoring status does not require experimental_solana. A temporary not-found response is not proof that resubmission is safe; shouldResubmit is not an instruction to retry automatically.

Recover from errors

Local statuses such as submitted, claimed, preconfirmed, filled, and completed are not the custom signer SDK’s uppercase statuses. Record error.details?.traceId when present; do not show raw diagnostics or simulation URLs to users.

Send a transaction

Define delivery, calls, and funding selection.

Unified balance

Read spendable balances across supported chains.