# Gas Statistics

The `gasStats` topic streams per-shard gas price and PPU (Price Per Unit) statistics every 50ms. Use this data to set competitive gas prices, detect shard congestion, and time transaction submission.

***

## Subscribe

```javascript
ws.send(JSON.stringify({
  action: 'subscribe',
  topic: 'gasStats'
}));
```

An initial snapshot is delivered immediately upon subscription. Updates follow every 50ms while the subscription is active.

***

## Message Schema

Each message covers a single shard. A separate message is emitted per shard per interval.

```json
{
  "type": "gasStats",
  "data": {
    "shard": 0,
    "gasPrice": {
      "min": 1000000000,
      "max": 1500000000,
      "avg": 1200000000,
      "bucketAvg": 1210000000,
      "percentiles": {
        "p50": 1150000000,
        "p75": 1350000000,
        "p90": 1450000000
      }
    },
    "ppu": {
      "min": 10,
      "max": 15,
      "avg": 12,
      "bucketAvg": 12.1
    }
  }
}
```

### Field Descriptions

| Field                           | Type   | Description                                                                   |
| ------------------------------- | ------ | ----------------------------------------------------------------------------- |
| `type`                          | string | Always `"gasStats"`                                                           |
| `data.shard`                    | number | Shard identifier: `0`, `1`, or `2`                                            |
| `data.gasPrice.min`             | number | Minimum gas price observed in the current window (atomic units)               |
| `data.gasPrice.max`             | number | Maximum gas price observed in the current window (atomic units)               |
| `data.gasPrice.avg`             | number | Simple average gas price across the full 30-minute window (atomic units)      |
| `data.gasPrice.bucketAvg`       | number | Weighted average computed from 10-second buckets — less sensitive to old data |
| `data.gasPrice.percentiles.p50` | number | 50th percentile gas price; half of transactions paid at or below this value   |
| `data.gasPrice.percentiles.p75` | number | 75th percentile gas price                                                     |
| `data.gasPrice.percentiles.p90` | number | 90th percentile gas price; spam-resistant upper bound for competitive pricing |
| `data.ppu.min`                  | number | Minimum Price Per Unit in the window                                          |
| `data.ppu.max`                  | number | Maximum Price Per Unit in the window                                          |
| `data.ppu.avg`                  | number | Average Price Per Unit across the full window                                 |
| `data.ppu.bucketAvg`            | number | Bucket-weighted average PPU                                                   |

***

## Sliding Window and Bucket Algorithm

Gas statistics are computed over a **30-minute sliding window** divided into **10-second buckets** (180 buckets total).

* As each bucket expires, it is dropped from the window and the oldest transaction data is discarded.
* The `avg` fields represent a simple mean across all transactions in the full 30-minute window.
* The `bucketAvg` fields are computed as the mean of per-bucket averages, giving more recent buckets equal weight regardless of transaction volume. This prevents a high-volume period from distorting the metric.
* Percentiles (p50, p75, p90) are computed over the sliding window using reservoir sampling. Because spam transactions cluster at the minimum gas price, percentiles above p50 provide a spam-resistant view of what legitimate transactions actually paid.

### Choosing a Gas Price

| Goal                                | Recommended value              |
| ----------------------------------- | ------------------------------ |
| Minimum acceptance                  | `1000000000` (network minimum) |
| Fast inclusion, low congestion      | `gasPrice.bucketAvg`           |
| Reliable inclusion                  | `gasPrice.percentiles.p75`     |
| Priority inclusion under congestion | `gasPrice.percentiles.p90`     |

***

## PPU — Price Per Unit

PPU is the effective cost per unit of gas computation, factoring in the transaction's data payload. For a plain EGLD transfer with no data, PPU equals `gasPrice`. For transactions with a `data` field, each byte costs an additional 1,500 gas units at the current gas price, making PPU higher than the raw `gasPrice`.

Use PPU to compare the true cost of transactions with different data sizes.

***

## Example: Dynamic Gas Price Selection

```javascript
class GasAdvisor {
  constructor() {
    this.stats = new Map(); // shard -> latest gasStats data

    this.ws = new WebSocket('wss://relayer.xoxno.com/ws');

    this.ws.onopen = () => {
      this.ws.send(JSON.stringify({ action: 'subscribe', topic: 'gasStats' }));
    };

    this.ws.onmessage = (event) => {
      const msg = JSON.parse(event.data);
      if (msg.type === 'gasStats') {
        this.stats.set(msg.data.shard, msg.data);
      }
    };
  }

  /**
   * Returns a gas price for the given shard suitable for reliable inclusion.
   * Falls back to the network minimum if no data is available.
   */
  getGasPrice(shard, priority = 'normal') {
    const data = this.stats.get(shard);
    if (!data) return 1000000000;

    switch (priority) {
      case 'low':    return data.gasPrice.bucketAvg;
      case 'normal': return data.gasPrice.percentiles.p75;
      case 'high':   return data.gasPrice.percentiles.p90;
      default:       return data.gasPrice.percentiles.p75;
    }
  }

  /**
   * Returns true if the given shard's avg gas price is significantly
   * above the network minimum, indicating congestion.
   */
  isCongested(shard) {
    const data = this.stats.get(shard);
    if (!data) return false;
    return data.gasPrice.avg > 1200000000;
  }
}

const advisor = new GasAdvisor();

// After connection stabilizes, use advisor:
// const gasPrice = advisor.getGasPrice(0, 'normal');
```

***

## Unsubscribe

```javascript
ws.send(JSON.stringify({
  action: 'unsubscribe',
  topic: 'gasStats'
}));
```

***

## Use Cases

* **Dynamic fee estimation** — Set `gasPrice` on outbound transactions using `percentiles.p75` for reliable confirmation without overpaying.
* **Congestion detection** — Monitor `avg` across shards; route time-sensitive operations away from congested shards when possible.
* **Wallet fee display** — Show users a real-time estimated fee before they confirm a transaction.
* **MEV / sequencing tools** — Use `bucketAvg` and percentiles to model current mempool competition.

{% hint style="info" %}
When a shard has no recent transactions, all gas price fields return `1000000000` (the network minimum) and PPU fields return `0`. This indicates the shard has full capacity available.
{% endhint %}

***

## Related Pages

* [Network Statistics](https://github.com/XOXNO/docs/blob/main/developers/relayer-api/network-stats.md) — TPS, mempool pressure, block times
* [Transaction Broadcasting](/developers/relayer-api/transaction-broadcasting.md) — Submit pre-signed transactions
* [Transaction Relaying](/developers/relayer-api/transaction-relaying.md) — Co-signed relayed transactions
* [Error Reference](https://github.com/XOXNO/docs/blob/main/developers/relayer-api/error-reference.md) — WebSocket error codes


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.xoxno.com/developers/relayer-api/gas-stats.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
