/** * The asset's Ref Finance DCL pools: what they offer, and what has traded. * * Kept apart from the NEAR Intents market on purpose. A user who buys through * 1Click is filled by a solver (a trade on that market), and the solver then * restocks from this pool (a swap here). Both are real, and summing them would * count the same demand twice — so they are two markets and never one volume. * * The pool contract is on a shard our node does not track, so its state is * read from a public endpoint and its swaps are found on intents.near's shard * and fetched whole. A swap made by calling the pool directly is not read, and * the coverage row says exactly how much of the pool's own recorded volume * that leaves out (blackbeard/observer#37). */ import { useEffect, useState } from 'react' import { Link } from 'react-router-dom' import type { RefPools } from '../api/generated/RefPools' import type { RefSwap } from '../api/generated/RefSwap' import type { RefSwaps } from '../api/generated/RefSwaps' import { RequestFailed, fetchRefPools, fetchRefSwaps } from '../api/rest' import { ago, height as fmtHeight, price as fmtPrice, tokens, when } from '../lib/format' import { href } from '../lib/routes' import { Field } from './Field' const EXPLORER = 'https://nearblocks.io/txns/' const REFRESH_MS = 60_000 /** A share as a percentage, or a dash where there is nothing to divide. */ function pct(part: string, whole: string): string { const w = Number(whole) if (!w) return '—' return `${((Number(part) / w) * 100).toFixed(2)}%` } /** How each kind of rung reads in the table. */ const KIND: Record = { asks: 'offers the asset', bids: 'bids for the asset', current: 'the current point', } export function RefDclMarket({ chain, decimals, symbol, }: { chain: string decimals: number symbol: string }) { const [pools, setPools] = useState(undefined) const [swaps, setSwaps] = useState(null) const [older, setOlder] = useState([]) const [error, setError] = useState(null) useEffect(() => { let controller = new AbortController() const load = () => { controller = new AbortController() Promise.all([ fetchRefPools(chain, controller.signal), fetchRefSwaps(chain, null, controller.signal), ]) .then(([p, s]) => { setPools(p) setSwaps(s) setError(null) }) .catch((e: unknown) => { if (controller.signal.aborted) return setError(e instanceof RequestFailed ? e.message : 'Could not reach the observer.') }) } setOlder([]) load() const id = window.setInterval(load, REFRESH_MS) return () => { window.clearInterval(id) controller.abort() } }, [chain]) const asset = pools?.asset_symbol ?? swaps?.asset_symbol ?? symbol const assetDecimals = pools?.asset_decimals ?? swaps?.asset_decimals ?? decimals const cursor = swaps?.next ?? null const loadOlder = () => { if (!cursor) return fetchRefSwaps(chain, cursor) .then((page) => { setOlder((rows) => [...rows, ...page.swaps]) setSwaps((s) => (s ? { ...s, next: page.next } : page)) }) .catch(() => {}) } const rows = swaps ? [...swaps.swaps, ...older] : [] return ( <>

Markets › Ref Finance DCL

{error &&

{error}

} {!error && pools === undefined &&

Reading the pools…

} {!error && pools === null && (

Not read yet — the first read is a minute after the observer starts.

)} {pools && pools.pools.length === 0 &&

No Ref DCL pool holds {asset}.

} {pools?.pools.map((p) => { const counter = p.counter_symbol ?? p.counter_token const amount = (raw: string, d: number) => tokens(raw, d) return (

{asset}/{counter} pool

{p.contract} · {(p.fee / 10_000).toFixed(2)}% fee · {p.state} · read{' '} {ago(pools.checked_at)}
{p.rungs.map((r) => ( ))}
The pool's liquidity ladder
Price of {asset} This range {asset} {counter} {counter} to take all its {asset}
{r.kind === 'current' ? fmtPrice(r.price_from) : `${fmtPrice(r.price_from)} – ${fmtPrice(r.price_to)}`} {KIND[r.kind] ?? r.kind} {r.asset > 0 ? r.asset.toLocaleString('en-US', { maximumFractionDigits: 3 }) : '—'} {r.counter > 0 ? r.counter.toLocaleString('en-US', { maximumFractionDigits: 4 }) : '—'} {r.counter_to_clear > 0 ? r.counter_to_clear.toLocaleString('en-US', { maximumFractionDigits: 0, }) : '—'}

The ladder is the pool's liquidity, range by range: what it holds at each price and what it would take to clear it. A range above the current price offers {asset}; one below it bids for {asset}. These are standing amounts, not trades — and{' '} “swaps indexed” is measured against the pool's own cumulative counters : anything under 100% is volume made by calling the pool directly, which this observer does not read. Accounts allowed to swap here: {p.whitelist.join(', ')}.

) })} {pools && pools.pools.length > 0 && (

Pool swaps

newest first
{rows.length === 0 ? (

No swap in these pools has been indexed yet.

) : (
{rows.map((s) => ( ))}
Swaps in the pools, newest first
Settled Solver Side {asset} Price Tx
{when(s.at)} {s.trader} {s.side === 'buy' ? 'bought' : 'sold'} {tokens(s.asset_amount, assetDecimals)} {asset} {fmtPrice(s.price)} {s.tx_hash.slice(0, 8)}…
)} {cursor && (
)}

A pool swap is a solver trading with the pool — typically restocking after filling a user on NEAR Intents, which is why these are not added to that market's trades. The price includes the pool's fee. The solver is named from its own intent; the pool itself records the swapper as intents.near.

What is read: {pools.reads}

)} ) }