Skip to main content
A complete swap involves three services and eight steps. This guide covers each step with error handling and edge cases.

Overview

Step-by-step guide

1

Get a swap quote

Call the Aggregator quote endpoint with the token pair and amount. The response includes txData (a ready-to-use transaction payload) and amountOutMin (the slippage-protected minimum output).
curl "https://swap.xoxno.com/api/v1/quote?from=WEGLD-bd4d79&to=USDC-c76f1f&amountIn=1000000000000000000&slippage=0.01"
Pool state updates in real time from the notifier, but on-chain reserves can still shift between your quote and execution. The amountOutMin field protects against this: the smart contract reverts if the actual output falls below this value.
2

Build and sign the transaction

Construct the transaction from the quote response and have the user sign it.
const tx = {
  nonce: accountNonce,
  value: '0',
  receiver: AGGREGATOR_CONTRACT,
  sender: senderAddress,
  gasPrice: 1000000000,
  gasLimit: 50_000_000,
  data: quote.txData,
  chainID: '1',
  version: 2
};

tx.signature = await userSigner.sign(serializeForSigning(tx));
For gasless relaying (enterprise), add a relayer field with the shard-matched relayer address before signing. The relayer co-signs and covers gas for the user. See Relaying (Gasless V3) for details.
3

Subscribe to the sender address

Before broadcasting, subscribe to address/{sender} to receive transaction status events for each transaction from that address.
const ws = new WebSocket('wss://relayer.xoxno.com/ws');

ws.onopen = () => {
  ws.send(JSON.stringify({
    action: 'subscribe',
    topic: `address/${senderAddress}`
  }));
};
If you compute the transaction hash locally, subscribe to tx-status/{hash} for single-transaction tracking. See Tx status tracking for both approaches.
4

Broadcast the signed transaction

ws.send(JSON.stringify({
  action: 'broadcast',
  requestId: `swap-${Date.now()}`,
  tx
}));
The Relayer injects the transaction into the P2P network and returns the hash in the response, matched by your requestId.
5

Wait for on-chain confirmation

The txStatus event arrives on the address/{sender} subscription when the transaction finalizes.
ws.onmessage = (event) => {
  const msg = JSON.parse(event.data);

  if (msg.type === 'txStatus') {
    if (msg.data.status === 'success') {
      console.log('Swap confirmed:', msg.data.hash);
    } else {
      console.error('Failed:', msg.data.status, msg.data.reason);
    }
  }
};

Edge cases

Cross-shard transactions

When sender and contract are on different shards, the transaction requires two block rounds: roughly 12 seconds on the current network. With the upcoming Supernova upgrade (600 ms block times), cross-shard finality drops to approximately 1.2 seconds. The txStatus event fires after the receiver’s shard processes the cross-shard message.

Smart contract revert

If the actual swap output falls below amountOutMin, the smart contract reverts. The transaction appears on-chain with fail status, but token balances remain unchanged. Re-quote with wider slippage and retry.

Gas optimization

Choose the right gas price using real-time statistics.

Relaying (Gasless V3)

Detailed reference for the relay action and shard routing.