Raxol.Payments.SettlementRecorder (Raxol Payments v0.2.0)

Copy Markdown View Source

Turns a completed cross-chain fill into a Raxol.Payments.SettlementLedger entry: resolves the fee token, fetches the destination fill receipt via a Raxol.Payments.ChainReader to price the native gas burned, and records it.

Called from the execute-then-poll orchestrator -- the only seam that holds the quote's fee together with the settled destination tx_hash. PollXochiStatus has no fee; ExecuteXochiIntent has no terminal receipt. It is opt-in and additive: the production Riddler execution path is never forced through it, and it never blocks a poll loop (a not-yet-mined receipt returns :receipt_pending or records :pending for later amend_gas/4).

Gas attribution caveat

gas_native is the destination fill tx's full gas cost -- the money-losing leg for micro-notional L1 fills. The origin pull is ERC-3009/Permit2 gasless (agent-side), so it is not attributed here. A solver that batches multiple fills into one destination tx would over-attribute gas to a single intent; treat the number as an upper bound in that case.

Summary

Types

Recorder input, assembled by the orchestrator from the quote + poll result. fee_collected is the quote's fee in atomic units (e.g. quote.xochi_fee); tx_hash is the destination settlement tx (status.tx_hash).

Types

input()

@type input() :: %{
  :intent_id => String.t(),
  :from_chain_id => pos_integer(),
  :to_chain_id => pos_integer(),
  optional(:token_symbol) => String.t() | nil,
  optional(:token_address) => String.t() | nil,
  optional(:to_token) => String.t() | nil,
  optional(:from_amount) => String.t() | integer() | Decimal.t() | nil,
  optional(:to_amount) => String.t() | integer() | Decimal.t() | nil,
  optional(:fee_collected) => String.t() | integer() | Decimal.t(),
  optional(:fee_currency) => String.t() | nil,
  optional(:estimated_gas_cost) => String.t() | nil,
  optional(:tx_hash) => String.t() | nil,
  optional(:settlement_type) => atom() | nil,
  optional(:metadata) => map()
}

Recorder input, assembled by the orchestrator from the quote + poll result. fee_collected is the quote's fee in atomic units (e.g. quote.xochi_fee); tx_hash is the destination settlement tx (status.tx_hash).

Functions

record(ledger, reader, input, opts \\ [])

@spec record(
  GenServer.server(),
  Raxol.Payments.ChainReader.reader(),
  input(),
  keyword()
) ::
  {:ok, :recorded | :duplicate} | {:error, term()}

Record one completed fill.

Options:

  • :record_pending -- when the receipt is not yet mined, record the entry with gas_status: :pending (backfill later via SettlementLedger.amend_gas/4) instead of returning {:error, :receipt_pending}. Default false.
  • :strict -- bubble a receipt-fetch error instead of recording gas_status: :error. Default false.