Skip to main content
sendTransaction and callContract require an active Ethereum wallet session. They accept different transaction inputs but run the same lifecycle. Solana and Tron wallets use their own methods with the same lifecycle and result shape.

Follow the transaction lifecycle

  1. The SDK prepares the transaction for the selected network. The default mode for EVM and Solana is TransactionMode.Relayer. Tron transactions always use native mode.
  2. OMS marks the prepared transaction as sponsored or returns fee-token options. Sponsored transactions need no fee selection. Unsponsored transactions need one option.
  3. The SDK executes the prepared OMS transaction and receives its latest status.
  4. Unless waitForStatus is false, the SDK polls for a transaction hash or terminal status and returns the latest result.
Whether a transaction is sponsored is decided by your project’s settings, not by your application. See Gas Sponsorship.

Choose a transaction input

Use sendTransaction for a native transfer, pre-encoded calldata, or a viem-compatible ABI call. Use callContract when your input is a function name plus typed argument objects. The examples import helpers such as parseUnits from viem. Install it with pnpm add viem.
Pass callContract the bare function name, such as 'transfer'. The wallet service builds the signature from the args types, and the SDK rejects a full signature such as 'transfer(address,uint256)' with OMSWalletValidationError before sending a request. Native value amounts are bigint values in raw base units. A calldata or ABI transaction can also include value. All forms require a recipient or contract address; these methods do not expose a recipient-free contract deployment input.

Send a Solana transfer

Use sendSolanaTransfer with a selected Solana wallet. Set asset to SOL for a native transfer or to an SPL token mint address. amount is a bigint in the asset’s smallest unit: lamports for SOL or base units for an SPL token.
For an SPL transfer, to is the recipient wallet address, not an associated token account. WaaS uses an existing associated token account or creates one when required. Solana transfers use the same fee selector, execution mode, status waiting, and result shape as EVM transactions.

Send a Tron transaction

Use sendTronTransaction for TRX transfers and callTronContract for TRC-20 and other contract calls. Both require an active Tron wallet session and a TronNetworks value. Tron addresses are Base58Check strings that start with T.
value is a bigint in sun (1 TRX is 1,000,000 sun). callTronContract takes a bare function name and lets the wallet service ABI-encode the arguments; address arguments accept Base58Check addresses. TRC-10 tokens are not supported. sendTronTransaction also accepts encoded data. Passing data, even '0x', makes the transaction a contract call. Tron transactions take no mode. Each Tron account gets free bandwidth every day, so many Tron transactions need no fee; when it is used up, the fee is a single TRX option that your fee selector receives like any other.

Select fees accurately

When you provide a selector, a sponsored transaction calls it with an empty array. Return undefined to continue with the sponsored transaction, or throw to stop execution. FeeOptionSelector.firstAvailable handles the empty array by returning undefined. For an unsponsored transaction:
  • With no selector, the SDK chooses the first fee option returned by OMS. It does not check whether the wallet can afford that option.
  • FeeOptionSelector.firstAvailable queries indexer balances and chooses the first returned option whose raw balance covers its raw fee value.
  • A custom selector receives the same enriched FeeOptionWithBalance[] and returns one option’s selection.
firstAvailable returns no selection when balance data is unavailable or no option is affordable. The transaction then fails before execution with a fee-selection error.
Each enriched option includes the original feeOption, its ready-to-return selection, and optional balance fields. feeOption.value and availableRaw are raw integer strings. available is formatted with known token decimals. balance, available, availableRaw, and decimals can be undefined when the indexer or token metadata cannot supply them.

Interpret the result

SendTransactionResponse contains:
  • txnId: the OMS transaction ID returned during preparation. Keep it for later status checks.
  • status: the latest OMS status: quoted, pending, executed, failed, or unknown.
  • txnHash: the chain transaction hash when OMS has one. It is optional.
  • statusResolution: resolved, timed-out, or not-requested.
resolved means polling observed executed, failed, or a transaction hash. It does not mean the chain has reached application-specific confirmation depth. A response can have status: 'pending' and statusResolution: 'resolved' once a hash exists. Tron transactions report status: 'pending' with a txnHash until the block is solidified, which takes about a minute, so status waiting resolves as soon as the hash is available. timed-out returns the last observed status without treating the transaction as failed. The transaction can still progress after the SDK returns.

Control status waiting

Waiting is enabled by default. The SDK performs a status request immediately, waits 400 ms between early polls, then 2 seconds between later polls, with a 60-second total timeout. These defaults correspond to:
Override only the values your application needs:
Return immediately after execution when your application will track the OMS transaction itself:
The immediate response does not include txnHash. Use getTransactionStatus until OMS returns the status your application requires.

Handle execution failures

Handle three outcomes:
  • OMS_TRANSACTION_EXECUTION_UNCONFIRMED, with a txnId: the SDK cannot tell whether the transaction was submitted. Check its status with the txnId before sending it again.
  • OMS_REQUEST_FAILED without a txnId: nothing was submitted. For example, simulation shows the transaction would revert (upstreamError.code '7314'), or a Tron wallet cannot cover the transfer and its fee. upstreamError.cause gives the wallet API’s reason when it has one. Fix the cause, then prepare the transaction again.
  • OMSWalletSessionError with code OMS_SESSION_EXPIRED: the session ended and nothing was submitted. Sign the user in again.
A wallet API call that takes longer than 30 seconds also fails with one of these errors. If execution succeeds but automatic status lookup fails, the SDK throws OMS_TRANSACTION_STATUS_LOOKUP_FAILED with txnId. Retry getTransactionStatus for that ID. An onchain failed status is returned as a normal transaction result rather than thrown as an SDK request error.