Skip to content

Guides

Rates, and the "never guessed" rule

How a crypto payment is priced at the moment it is decided, where the rate comes from, how long it is reused, and what happens when there is no rate.

A crypto payment is judged in money: the rule says “up to £25 a payment”, not “up to 33 USDC”. So every crypto payment is priced at the moment it is decided, and the price is kept with the decision.

#Where the rate comes from

Two public price APIs, neither needing a key, tried in order:

SourceRequestWhat is read
CoinbaseGET https://api.coinbase.com/v2/prices/USDC-GBP/spot (docs)data.amount, with data.base and data.currency checked against what was asked
KrakenGET https://api.kraken.com/0/public/Ticker?pair=USDCGBP (docs)the last trade price, c[0], of the first pair in result (Kraken names some pairs its own way, so XBTGBP comes back as XXBTZGBP)

Coinbase is asked first. If it does not answer within the timeout (1.5 seconds by default, IMMISCIBLE_CRYPTO_RATE_TIMEOUT_MS), or answers with anything other than a usable price, Kraken is asked. Neither response carries a timestamp of its own, so the time recorded is when Immiscible received the price.

The rate is reused for up to 45 seconds (IMMISCIBLE_CRYPTO_RATE_CACHE_SECONDS, at most 60), and its age is recorded with every decision.

#The currency

A payment is priced in the currency of the agent’s crypto rule: pounds by default, or euros or US dollars if the rule is written in them. Conversion is exact decimal arithmetic, rounded up to the next penny, so a payment is never counted as smaller than it is.

#Stablecoins are priced too

USDC is not assumed to be worth one dollar. It is priced into the rule’s currency like anything else, and also against its own peg (USDC and USDT against US dollars, EURC against euros). If it trades further from its peg than the rule allows (1% by default, crypto.depegBps), the payment is held for a person, with the price in the reason.

#Never guessed

If no source answers in time, there is no rate, and Immiscible does not invent one. The payment is not refused and not allowed: it waits for a person, with the plain reason

Couldn’t price this payment right now.

No limit is judged on a guessed value. When a person approves it in the console or the phone app, the payment is priced again at that moment and judged at that rate; if there is still no rate, the person approves the asset amount they can see, and the record says it was not priced.

#Where the rate is kept

On the action and the decision (crypto.rate: rate, currency, time, age, source name and URL, and the peg price), on the ledger record of the decision (crypto.rate, rateAt, rateSource, rateAgeMs, value), and on the signed receipt, in the cry.fx claim. A payment approved later carries both: the rate when it was asked for, and the rate when it was allowed.

The console shows it the same way on every row: “£9.48 at the rate at that moment (1 USDC = £0.7581 at 14:32:05, Coinbase)”.

#The demo workspace

The Amethyst demo seed uses a fixed table of demo rates instead of the sources above, so it works offline. Every seeded record names it: “Demo rate (seed data)”. It is never a market price.