# Transaction Fields

Every transaction submitted to the Bullet exchange is wrapped in an `UnsignedTransaction` containing three components:
the call message, a uniqueness value, and transaction details. This guide covers the uniqueness and details fields.

## Uniqueness

The `UniquenessData` field prevents transaction replay. Bullet supports two modes:

```rust
enum UniquenessData {
    Nonce(u64) = 0,
    Generation(u64) = 1,
}
```

### Generation mode (recommended)

The uniqueness value can be whatever you want — it just needs to be unique per user within a block window (~5-6
seconds).
We recommend using microsecond timestamps.

- No need to track or increment a counter
- Multiple transactions can be in-flight concurrently

**Best practice:** use `SystemTime::now()` in microseconds. Avoid reusing values — if you submit multiple
transactions in a tight loop, ensure each is distinct.

### Nonce mode

Use `Nonce(u64)` for strict sequential ordering. The nonce must be exactly `current_nonce + 1` for the credential.
This mode is simpler but only allows one in-flight transaction at a time.

## TxDetails

```rust
struct TxDetails {
    max_priority_fee_bips: u64,
    max_fee: Amount,
    gas_limit: Option<[u64; 2]>,
    chain_id: u64,
}
```

These fields are required in every transaction. We recommend using the values below.

| Field                   | Type               | Description                                                                     |
|-------------------------|--------------------|---------------------------------------------------------------------------------|
| `chain_id`              | `u64`              | Chain identifier — fetch from `GET /fapi/v1/exchangeInfo` → `chainInfo.chainId` |
| `max_fee`               | `Amount(u128)`     | Maximum fee the sender is willing to pay                                        |
| `gas_limit`             | `Option<[u64; 2]>` | 2D gas limit: `[compute, storage]`. `None` defaults to block limit              |
| `max_priority_fee_bips` | `u64`              | Priority fee tip in basis points                                                |

### Gas model

Bullet uses a **2D gas model** with separate compute and storage dimensions. The `gas_limit` field caps how much of
each resource a transaction may consume.

### Paymaster

Gas fees are covered by a paymaster — users do not pay gas out of pocket. The fields are still required for
transaction validity.

## Recommended Values

| Field                   | Recommended value            | Notes                                                                                                                                       |
|-------------------------|------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------|
| `uniqueness`            | `Generation(timestamp_us())` | Microsecond timestamp                                                                                                                       |
| `max_priority_fee_bips` | `0`                          |                                                                                                                                             |
| `max_fee`               | `1 << 48`                    |                                                                                                                                             |
| `gas_limit`             | `None`                       | Defaults to block limit. Use `[5_000_000, 5_000_000]` for order placement or `[500_000, 500_000]` for simpler ops if you want explicit caps |
| `chain_id`              | from `exchangeInfo`          | Must match the chain you are submitting to                                                                                                  |

See the [default_tx_details](./tx-signing.md#helpers) helper for a ready-to-use implementation.
