# System Architecture

XOXNO's three core infrastructure services communicate as follows, carrying data from blockchain node to client application.

***

## Services Overview

| Service         | Role                                                               | External Interface                                                          |
| --------------- | ------------------------------------------------------------------ | --------------------------------------------------------------------------- |
| **arb-algo**    | DEX aggregation and optimal swap routing                           | REST API at `https://swap.xoxno.com`                                        |
| **mx-relayer**  | Transaction co-signing, broadcasting, and real-time data streaming | WebSocket at `wss://relayer.xoxno.com/ws`; REST at `/v1/*`                  |
| **mx-notifier** | Blockchain event ingestion and fan-out                             | Internal WebSocket `/hub/ws` (binary protobuf); RabbitMQ; Azure Service Bus |

***

## Architecture Diagram

```
  MultiversX Network
  ┌───────────────────────────────────────────────────┐
  │  Shard 0        Shard 1        Shard 2   Metachain │
  │  Validators     Validators     Validators Validators│
  └───────────┬───────────────────────────────────────┘
              │ P2P gossipsub (transactions_0_0, etc.)
              │ binary protobuf WebSocket
              ▼
  ┌─────────────────────────────────────────────────────────────────────┐
  │                           mx-notifier                               │
  │                                                                     │
  │  Topics received from node:                                         │
  │  • SaveBlock            • SaveValidatorsPubKeys                     │
  │  • FinalizedBlock       • SaveValidatorsRating                      │
  │  • SaveAccounts         • RevertIndexedBlock                        │
  │  • SaveRoundsInfo       • Settings                                  │
  │                                                                     │
  │  Filter levels: All | Address | AddressIdentifier |                 │
  │                 Identifier | Topics                                 │
  │                                                                     │
  │  ┌──────────────┐    ┌──────────────────────────────────────────┐  │
  │  │ Preprocessor │───▶│  Fan-out                                 │  │
  │  │ • Normalize  │    │  • /hub/ws  (binary protobuf WebSocket)  │  │
  │  │ • Dedup      │    │  • RabbitMQ publisher                    │  │
  │  └──────────────┘    │  • Azure Service Bus publisher           │  │
  │                      └──────────────────────────────────────────┘  │
  └──────────────────────────────────┬──────────────────────────────────┘
                                     │ /hub/ws (binary protobuf)
                                     ▼
  ┌─────────────────────────────────────────────────────────────────────┐
  │                           mx-relayer                                │
  │                                                                     │
  │  Inbound from notifier:                                             │
  │  • SaveBlock → extract tx status, account deltas                   │
  │  • SaveAccounts → propagate balance/nonce changes                  │
  │                                                                     │
  │  Outbound (WebSocket, JSON):                                        │
  │  • gasStats      50ms cadence  per-shard p50/p75/p90               │
  │  • networkStats  250ms cadence TPS, mempool, validator health       │
  │  • address/{bech32}  event-driven  account balance + nonce         │
  │  • tx-status/{hash}  event-driven  success/fail, TTL 60s           │
  │                                                                     │
  │  Outbound (REST):                                                   │
  │  • POST /v1/sign      sign batch transactions                       │
  │  • POST /v1/broadcast broadcast pre-signed transactions             │
  │  • GET  /v1/network-stats/history  historical stats                │
  │                                                                     │
  │  P2P broadcast:                                                     │
  │  • transactions_{senderShard}_{receiverShard} gossipsub topic       │
  └───────────────────────────────────────┬─────────────────────────────┘
                                          │ WebSocket (JSON) / REST
                                          ▼
                                   Client Applications

  ┌─────────────────────────────────────────────────────────────────────┐
  │                    arb-algo  (independent service)                  │
  │                                                                     │
  │  Pool data refresh: every 5 seconds from Xoxno API                 │
  │  DEXs: xExchange, AshSwap, JEX, OneDex                             │
  │                                                                     │
  │  REST API:                                                          │
  │  • GET /api/v1/quote         optimal route + txData                 │
  │  • GET /api/v1/pair-config   token support + decimal metadata       │
  │  • GET /health               pool/token counts, uptime              │
  └───────────────────────────────────────┬─────────────────────────────┘
                                          │ REST
                                          ▼
                                   Client Applications
```

***

## Service Responsibilities

### arb-algo

arb-algo maintains a live graph of all liquidity pools across supported DEXs and runs beam search plus split optimization to find the route that maximizes output for a given input (or minimizes input for a given output). Every quote request computes routes against the current pool state; arb-algo carries no per-client state.

Pool data refreshes atomically every 5 seconds. In-flight requests during a refresh continue reading the previous snapshot — no window of inconsistency exists.

The `txData` field in every quote response is a base64-encoded smart contract call payload. Clients submit this field directly as the transaction `data` field with no further encoding.

arb-algo does not broadcast transactions, track transaction status, or provide gas price data. Use mx-relayer for those capabilities.

### mx-relayer

mx-relayer has two primary responsibilities:

1. **Real-time data streaming.** mx-relayer subscribes to mx-notifier and reformats blockchain events into JSON WebSocket messages for client applications. Clients subscribe to named topics; the relayer delivers only relevant events.
2. **Transaction submission.** Clients send signed transactions to the relayer via WebSocket or REST. For relay actions, the relayer validates shard alignment, appends its co-signature (`relayerSignature`), and broadcasts to MultiversX's P2P gossipsub network. For broadcast actions, no co-signing occurs.

### mx-notifier

mx-notifier is an internal service. It connects to MultiversX nodes via binary protobuf WebSocket, receives raw blockchain events, normalizes and deduplicates them, and fans out to downstream consumers. Client applications connect to mx-relayer, not mx-notifier.

***

## Network Topology

```
Connection               Protocol              Direction
────────────────────     ──────────────────    ─────────────────────
MultiversX node          binary protobuf WS    node → mx-notifier
  → mx-notifier

mx-notifier              binary protobuf WS    mx-notifier → mx-relayer
  → mx-relayer /hub/ws

mx-notifier              AMQP                  mx-notifier → RabbitMQ
  → RabbitMQ

mx-notifier              AMQP/HTTPS            mx-notifier → Azure SB
  → Azure Service Bus

mx-relayer               JSON WebSocket        mx-relayer → clients
  → clients /ws

mx-relayer               JSON WebSocket        mx-relayer → clients
  → clients /ws/stats

arb-algo                 HTTPS REST            arb-algo → Xoxno API
  → Xoxno pool API

arb-algo                 HTTPS REST            clients → arb-algo
  → clients

mx-relayer P2P           gossipsub             mx-relayer → validators
  → MultiversX validators
```

***

## Data Flow: Quote to Confirmation

The following sequence traces what happens when a client executes a swap.

**Step 1 — Quote.** The client sends a GET request to arb-algo with the input token, output token, and amount. arb-algo runs beam search over the current pool graph, solves the split optimization, and returns the optimal route, expected output, slippage-adjusted minimum output, and a ready-to-use `txData` payload.

**Step 2 — Subscribe before sending.** The client subscribes to `tx-status/{txHash}` on the relayer WebSocket before sending the transaction. The status event fires once and is not replayed. Because the transaction hash is deterministic from the signed transaction, the client knows it before broadcast.

**Step 3 — Relay.** The client sends a `relay` action to the relayer WebSocket. The transaction must include the `relayer` field set to the shard-appropriate relayer address, and the user must sign with that field present. The relayer validates shard alignment, appends its co-signature, and broadcasts to the P2P network.

**Step 4 — Block production.** Validators on the sender's shard receive the transaction via gossipsub, include it in a block, and execute it. If the receiver is on a different shard, a cross-shard message is processed in a subsequent block on the receiver's shard.

**Step 5 — Notification.** The MultiversX node pushes `SaveBlock` to mx-notifier. mx-notifier extracts transaction results and account state changes, then forwards them to mx-relayer via `/hub/ws`.

**Step 6 — Client delivery.** mx-relayer fans out to subscribers:

* Clients subscribed to `tx-status/{hash}` receive the final status (`success` or `fail`).
* Clients subscribed to `address/{bech32}` receive updated account balance and nonce.

***

## Operational Characteristics

| Characteristic                      | Value                         |
| ----------------------------------- | ----------------------------- |
| arb-algo pool refresh interval      | 5 seconds                     |
| gasStats stream cadence             | 50ms                          |
| networkStats stream cadence         | 250ms                         |
| tx-status TTL                       | 60 seconds after subscription |
| Max WebSocket topics per connection | 64                            |
| Max control messages per 5s window  | 64                            |
| Max WebSocket message size          | 4 MB                          |
| Ping/pong heartbeat interval        | 30 seconds                    |
| gasStats sliding window             | 30 minutes                    |
| gasStats bucket size                | 10 seconds                    |

***

## When to Use Relayer vs. Direct Gateway Submission

Use mx-relayer when:

* You need real-time transaction status without polling. The `tx-status/{hash}` subscription delivers the result as soon as the block finalizes.
* You need co-signed (relayed) transactions so the relayer pays gas. This requires the Relayer V3 transaction format with shard-specific relayer addresses.
* You want per-shard gas statistics to set competitive gas prices before submission.
* You need account update events (balance, nonce) without running your own indexer.

Use direct gateway submission when:

* You run your own infrastructure and have no need for real-time event streaming.
* Your application signs and pays for gas independently, with no co-signing requirement.
* You have an existing polling-based confirmation flow.

***

## Related Pages

* [Transaction Lifecycle](https://docs.xoxno.com/developers/guides/transaction-lifecycle) — Step-by-step walkthrough with code
* [Gas Optimization](https://docs.xoxno.com/developers/guides/gas-optimization) — Using gas statistics for optimal submission
* [Aggregator API](https://docs.xoxno.com/developers/aggregator-api) — Quote endpoint reference
* [Relayer WebSocket API](https://docs.xoxno.com/developers/relayer-api) — Subscription and relay reference
* [Notifier](https://docs.xoxno.com/developers/notifier) — Internal event topics
