DpExchange.Core.Types.Conversion (DpExchangeCore v0.3.22)

Copy Markdown View Source

A conversion between two assets — quoted first, committed second.

This is the facade's only two-step operation, and the gap between the steps is the risk

Every other write in this contract is one call: place an order, cancel it, stake. A conversion is two. The venue quotes a rate, hands back an identifier, and holds that rate for a short window; the caller then commits against the identifier or lets it lapse.

:expires_at is the whole reason this type exists. A caller that commits an expired quote does not get the rate it was shown. Depending on the venue it gets an error — or a fill at the current rate, which is the dangerous case, because the operation appears to have succeeded and the numbers are all real. The window is typically seconds.

nil means the venue did not state an expiry, not that the quote is open-ended. A caller treating an unstated expiry as unlimited is making the same mistake as reading a missing liquidation price as safety.

:status distinguishes a quote from a trade

The same identifier addresses both stages, so the struct carries which stage it is in:

  • :quoted — a rate is held; nothing has moved
  • :committed — the caller accepted; the venue is executing
  • :settled — the assets have moved
  • :expired — the window closed unaccepted
  • :failed — the venue rejected or could not complete it

:quoted is not a conversion that happened. A package that reported a quote as complete would be reporting an intention as a fact.

Summary

Functions

Whether a quote has passed its stated expiry, as at now.

Builds a t/0, failing closed if a required field is absent or nil.

Types

status()

@type status() :: :quoted | :committed | :settled | :expired | :failed

t()

@type t() :: %DpExchange.Core.Types.Conversion{
  expires_at: DateTime.t() | nil,
  fee: Decimal.t() | nil,
  from_amount: Decimal.t() | nil,
  from_asset: String.t(),
  id: String.t(),
  provider: atom(),
  rate: Decimal.t() | nil,
  status: status(),
  to_amount: Decimal.t() | nil,
  to_asset: String.t(),
  venue_time: DateTime.t() | nil
}

Functions

expired?(conversion, now)

@spec expired?(t(), DateTime.t()) :: boolean() | nil

Whether a quote has passed its stated expiry, as at now.

Returns nil when the venue stated no expiry — unknown, not "still valid". A caller that cannot establish the window should re-quote rather than assume it has one.

This is advisory. The venue decides whether a commit succeeds, and a quote can be refused inside its stated window; asking here is how a caller avoids the round trip, not how it learns the outcome.

new(attrs)

@spec new(keyword() | map()) :: t()

Builds a t/0, failing closed if a required field is absent or nil.

@enforce_keys guards presence, not nil — see DpExchange.Core.Types.Validate.