> ## Documentation Index
> Fetch the complete documentation index at: https://xoxno.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Transaction lifecycle

> Complete walkthrough of a swap transaction from quote to on-chain confirmation, with error handling at each step.

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

## Overview

```mermaid theme={"system"}
sequenceDiagram
    participant App as Your App
    participant User as User Wallet
    participant Aggregator as Aggregator
    participant Relayer as Relayer
    participant Chain as MultiversX

    App->>Aggregator: 1. GET /quote (from, to, amountIn, sender)
    Aggregator-->>App: transaction object, amountOutMin
    App->>User: 2. Request signature
    User-->>App: signed transaction
    App->>Relayer: 3. subscribe address/{sender}
    App->>Relayer: 4. broadcast signed tx
    Relayer->>Chain: 5. P2P gossipsub
    Chain->>Chain: 6. execute on-chain
    Chain->>Relayer: 7. notifier event
    Relayer-->>App: 8. tx-status confirmation
```

## Step-by-step guide

<Steps>
  <Step title="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).

    <Tabs>
      <Tab title="cURL">
        ```bash theme={"system"}
        curl "https://swap.xoxno.com/api/v1/quote?from=WEGLD-bd4d79&to=USDC-c76f1f&amountIn=1000000000000000000&slippage=0.01"
        ```
      </Tab>

      <Tab title="TypeScript">
        ```ts theme={"system"}
        const params = new URLSearchParams({
          from: 'WEGLD-bd4d79',
          to: 'USDC-c76f1f',
          amountIn: '1000000000000000000',
          slippage: '0.01'
        });

        const res = await fetch(`https://swap.xoxno.com/api/v1/quote?${params}`);
        const quote = await res.json();

        const { txData, amountOutMin, priceImpact } = quote;
        ```
      </Tab>

      <Tab title="Python">
        ```python theme={"system"}
        import httpx

        params = {
            "from": "WEGLD-bd4d79",
            "to": "USDC-c76f1f",
            "amountIn": "1000000000000000000",
            "slippage": "0.01",
        }

        async with httpx.AsyncClient() as client:
            res = await client.get("https://swap.xoxno.com/api/v1/quote", params=params)
            quote = res.json()
        ```
      </Tab>

      <Tab title="Rust">
        ```rust theme={"system"}
        let quote: serde_json::Value = reqwest::Client::new()
            .get("https://swap.xoxno.com/api/v1/quote")
            .query(&[
                ("from", "WEGLD-bd4d79"),
                ("to", "USDC-c76f1f"),
                ("amountIn", "1000000000000000000"),
                ("slippage", "0.01"),
            ])
            .send()
            .await?
            .json()
            .await?;
        ```
      </Tab>
    </Tabs>

    <Warning>
      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.
    </Warning>
  </Step>

  <Step title="Build and sign the transaction">
    Construct the transaction from the quote response and have the user sign it.

    ```ts theme={"system"}
    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)](/relayer/transaction-relaying) for details.
  </Step>

  <Step title="Subscribe to the sender address">
    Before broadcasting, subscribe to `address/{sender}` to receive transaction status events for each transaction from that address.

    ```ts theme={"system"}
    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](/relayer/tx-status-tracking) for both approaches.
  </Step>

  <Step title="Broadcast the signed transaction">
    ```ts theme={"system"}
    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`.
  </Step>

  <Step title="Wait for on-chain confirmation">
    The `txStatus` event arrives on the `address/{sender}` subscription when the transaction finalizes.

    ```ts theme={"system"}
    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);
        }
      }
    };
    ```
  </Step>
</Steps>

## 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.

## Related pages

<CardGroup cols={2}>
  <Card title="Gas optimization" icon="gauge-high" href="/resources/gas-optimization">
    Choose the right gas price using real-time statistics.
  </Card>

  <Card title="Relaying (Gasless V3)" icon="zap" href="/relayer/transaction-relaying">
    Detailed reference for the relay action and shard routing.
  </Card>
</CardGroup>
