Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Transaction Fields

Every transaction submitted to the Bullet exchange is wrapped in an UnsignedTransaction containing the call message, a uniqueness value, transaction details, and an optional address_override. This guide covers the uniqueness, details, and address override fields.

Uniqueness

The UniquenessData field prevents transaction replay. Bullet supports three modes:

#![allow(unused)]
fn main() {
enum UniquenessData {
    Nonce(u64) = 0,
    Generation(u64) = 1,
    Window(u64) = 2,
}
}

The uniqueness value can be whatever you want — it just needs to be unique per key within an increasing block window of 1000 nonces. We recommend using millisecond timestamps.

Compared to the strictly monotonic Nonce variant multiple transactions can be in-flight concurrently.

Best practice: use SystemTime::now() in milliseconds. 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

#![allow(unused)]
fn main() {
struct TxDetails {
    max_priority_fee_bips: u64,
    max_fee: Amount,
    gas_limit: Option<[u64; 2]>,
    chain_hash_fragment: u64,
}
}

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

FieldTypeDescription
chain_hash_fragmentu64First 8 bytes of the chain hash (GET /fapi/v1/exchangeInfo → chainHash) as a little-endian u64; see chain_hash_fragment
max_feeAmount(u128)Maximum fee the sender is willing to pay
gas_limitOption<[u64; 2]>2D gas limit: [compute, storage]. None defaults to block limit
max_priority_fee_bipsu64Priority fee tip in basis points

The fragment lets the exchange pick the chain hash a transaction was signed over when more than one is valid during a chain-hash rotation. It replaces the former chain_id field.

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.

FieldRecommended valueNotes
uniquenessWindow(timestamp_ms())Millisecond timestamp
max_priority_fee_bips0
max_fee1 << 48
gas_limitNoneDefaults 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_hash_fragmentchain_hash_fragment(&chain_hash)Derived from the chainHash you sign with
address_overrideNoneExecute as your own address. Only set it to act on another account that explicitly authorized your key

See the default_tx_details helper for a ready-to-use implementation.

Address override

UnsignedTransaction.address_override is an Option<[u8; 32]> and is part of the signed bytes. Leave it None: the transaction then executes as the account the exchange resolves for the signing credential, which is the key’s own account or, for a registered delegate key, the delegator’s main account (see Delegate Accounts; delegation needs no override). Some(address) executes as that account instead and is only admitted when the account has explicitly authorized the signing credential; otherwise the transaction is skipped before execution.