Menu

Exchange rates

A payment can come in as XRP and leave as dollars, or the other way. This page explains where your node's rates come from, how it prices a conversion, and how it keeps its holdings in balance without ever trading on an exchange.

On this page
  1. One rate that matters
  2. Where rates come from
  3. Dollar tokens and the peg guard
  4. Pricing by what you hold
  5. Snapshots of a node's prices
  6. Swaps with peers
  7. Market makers

One rate that matters

Every ledger a node settles on today holds either XRP or a dollar token, such as DSUSD on the testnet. A dollar token is booked as dollars, one to one. So only one rate ever moves money: the price of XRP in dollars.

Your node keeps rates for a few more currencies (euros, pounds, yen, Swiss francs, Canadian and Australian dollars), but only to show you your total in the currency you choose. A total is shown only while every rate it needs is fresh. With one missing, the wallet shows no total rather than a wrong one.

Where rates come from

Every minute, your node asks its rate sources and takes the median of the answers. A new node starts with four sources, so that every currency is covered three times, from three independent places:

Source Covers
Coinbase's exchange rates every currency
Kraken's ticker every currency
Bitstamp's ticker XRP
The European Central Bank's daily reference rates the other currencies
  • The median. A rate counts once more than half of its sources answered. One wrong source can move it only as far as the others allow. With one source silent, the other two must agree closely.
  • Exact. Rates are read and used as exact decimals, never as floating point, and every conversion rounds down.
  • Fresh, or nothing. Your node keeps its last rates across a restart. A rate older than an hour is not used: until a fresh one arrives, payments that would convert through it are turned away with a temporary error, and payments that stay on one ledger go on as usual.

You can change the list of sources in the wallet. See Exchange-rate settings.

The exchanges license their data for personal or internal use only. Sources whose terms allow a node to convert by them for a fee, XRP's price from the XRP Ledger's own XRP/RLUSD pool, and the other currencies from four central banks in place of the exchanges, are not there yet. What's next

Why three sources and a median, and which sources come next.

Dollar tokens and the peg guard

Booking a dollar token at par is only safe while the token is worth a dollar. A node that converted at par while the token was off its peg could be drained. So each dollar token has a peg guard: once a minute your node reads the token's pool on the XRP Ledger, with a proof, and prices the token against XRP's rate.

When the token stays off its peg for a while, the guard pauses every conversion to or from it, on your own account and in its hub alike. Settling and paying out in the token go on. When the token is back near a dollar for a longer while, conversions start again. A guard that cannot read the pool for long enough pauses too, rather than guess. See Dollar tokens and the peg guard for what you see in the wallet.

Pricing by what you hold

A node that converts for others drifts. If more payments flow from XRP to dollars through it than back, it fills up with XRP and runs out of dollars. Once it holds nothing on a ledger, it can convert nothing out of it. Your node never trades on an exchange to fix this. Instead, it lets its price lean.

  • A target for each asset. Your node values what you hold of each asset at the market rate, and aims for equal shares, one per asset. What it holds in a hub and on your own account on the ledger count together, as one holding.
  • Better for what it lacks, worse for what it has. Bringing in an asset your node is short of gets a better rate than the market; taking it out gets a worse one. So whoever profits from the gap, a peer's swap, a market maker or an ordinary payment, moves your node back toward balance.
  • A cap on the bonus, none on the penalty. Your node never pays more than the rebalancing share above the market for what it lacks, 5% by default. Taking out what it is short of gets dearer the scarcer it is, and nothing converts out of a ledger you hold nothing on.
  • Each packet pays its own way. A packet is priced after its own effect on your holdings, and as if every other packet in flight against it went through. So a round trip never gains, and nobody can improve their price by holding other payments back.

With the default 5%, a node that holds a quarter of its value in one asset and three quarters in the other pays the scarce one out at about 6% below the market rate.

Three settings in the wallet shape this, all charged only on what passes from one peer to another:

Setting What it does Default
Fee A share of what passes through, rounded down. 0%
Spread A share of what is converted from one currency to another. 0%
Rebalancing How far your holdings lean the rate: the bonus cap above. 5%

Your own payments are never charged, and when a peer pays you in another currency, it converts at the market rate. A packet only converts when it has to: your node sends it on in the asset it came in, if any next hop can take that asset.

Why it works this way, and what it costs a node that runs short.

Snapshots of a node's prices

Peers and market makers need to know what a node converts at, often and cheaply. So each core node that offers swaps signs a snapshot of its prices with its node key: one small message, made again at most once a second while its prices move, and every thirty seconds anyway, so readers know it is alive.

  • A bid and an ask per hub. For each settlement method its peers can pay it on, the snapshot says what the node gives for money coming in and asks for money going out, with its fee and spread folded in. A reader prices a swap from one method to another by the one's bid over the other's ask.
  • A ladder for each. It also says how much can come in or go out before the price falls by more than each step of a grid, from 0.01% to 30%. So a reader knows how far a swap can go, not only what the first unit gets.
  • A promise, never more. A snapshot never says more than the node gives. A method the node offers but cannot convert on now, for want of a fresh rate or a dollar token off its peg, is listed closed.

Peers subscribe to each other's snapshots over the peer protocol, and get each new one as it is made. Anyone else can ask a core node once, over UDP port 7768. A request is as large as the largest snapshot, so the answer is never larger than the request, and the node answers only so many each second. Open UDP 7768 in your firewall so readers can reach it. If the node cannot bind that port, it runs as usual and answers no requests, and its peers still get its snapshots.

A periphery node offers no swaps, so it makes no snapshot and answers no request. dassie status and the wallet's network page show whether your node answers, and how many requests it has answered.

To read a snapshot yourself, see Read a node's snapshot and the snapshot wire format.

What a snapshot says, and how a node makes it

Swaps with peers

Two peers that share an XRP hub and a dollar hub can pay each other in either asset within one peering. So a node can swap one asset for the other with a peer directly: it sends a packet to the peer on one hub, and the peer converts it at its own prices and sends it straight back on the other. A swap is never routed anywhere else.

  • A core node swaps by itself. It reads its peers' snapshots and swaps with a peer while what the peer's snapshot promises, valued by its own curve, beats its costs: the fees of settling over the hub and of moving money in and out of it. A peer's prices pay most for what it lacks, so a swap tends to move both nodes toward balance.
  • A periphery node swaps by itself only toward your targets. Its holdings are its owner's choice, so it has none by default and swaps only when you ask. You set targets in the wallet's Peers settings; see Swaps with peers.
  • Any node swaps when you ask, through its owner API (SwapWithPeer), as a market maker does.

Two settings in the wallet, both on by default, control this: Swaps for peers, whether peers may swap with your node, shown only on a core node, and Swapping with peers, whether your node swaps with them. See Exchange-rate settings.

Swaps spread drift around; they do not remove it. Where payments flow one way through the whole network, every node drifts alike, and only market makers and owners bring in new money.

Why peers swap this way, and what it accepts in return.

Market makers

A market maker brings in what nodes lack from outside, from an AMM pool on the XRP Ledger. It runs as dassie market-maker, beside one periphery node of its own. That node is a member of the testnet's XRP hub and its DSUSD hub, and is pinned with DASSIE_UPLINKS to the core nodes it trades through, so it gets their snapshots over its peerings with them.

  • It trades by swapping. When what a core node's snapshot promises for a swap and the pool's price differ by more than a margin, the market maker asks its node to swap with that core node, at a rate no worse than the pool makes worth it. Each such swap brings the core node what it lacks.
  • It rebalances on the pool. When it holds more of one asset than its band allows, it trades the extra for the other on the pool, with one payment from its XRP Ledger account to itself, which never spends more than a set limit.
  • It holds no books. Every amount is moved by its node or by the ledger.

See Run a market maker for its config.

How the market maker decides

A kopje of granite blocks against the sun, in veld grass; one dassie climbs its slab, one keeps lookout on top inside the sun, and one sleeps on the next rock; on a wide screen, a pair sits on a kopje to the left