fix(core): one swap per taker leg, and solver hops are never trades
A 3,000-block survey of intents.near from our own node (350 outcomes, 1,026 legs) showed the referral leg is the user — per-quote implicit accounts, none on a solver — and that its own diff mirrors the rest of the outcome to within the protocol fee in all 576 amounts checked. So each taker leg is now its own trade, priced from what that user gave and got. It also showed the pooling rule counted solver routing as trading: in 45% of outcomes with a taker the solvers traded through a pair no taker touched, usually USDT on Ethereum, and each such leg on the tracked asset became a phantom trade against a token the user never saw. Two takers on one pair — an account round-tripping wNEAR, in the case captured — were merged into one trade with a nonsense price. Now an outcome with any taker yields only the takers' trades; only an outcome with no referral at all (solvers trading with each other) is pooled, as `kind: unattributed`, with no side. `kind` is stored (migration 0010, no re-scan: production held no QTC rows) and on the wire, and the panel says how many of a figure's trades were users'. Tests run on the three captured outcomes. Checked live against near.internal with wNEAR: 18 trades from 18 outcomes, every taker an implicit account, and no counter that was only a hop. Closes #30 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015pkwBsR54NRmZyU4QVhvfj
This commit is contained in:
@@ -22,6 +22,11 @@ decimals: number | null,
|
||||
* as this count, and one trade is one trade however it is labelled.
|
||||
*/
|
||||
trades: number,
|
||||
/**
|
||||
* How many of them were users' trades rather than solvers trading with
|
||||
* each other.
|
||||
*/
|
||||
taker_trades: number,
|
||||
/**
|
||||
* The latest trade's price.
|
||||
*/
|
||||
|
||||
@@ -48,8 +48,13 @@ counter_amount: BigUintDec,
|
||||
*/
|
||||
price: number | null,
|
||||
/**
|
||||
* `buy` or `sell`, from the taker's side. **Inferred** from the one leg
|
||||
* that carried a `referral`; absent when that could not be told.
|
||||
* `taker` — a user's trade, from the leg that carried a `referral` — or
|
||||
* `unattributed`, solvers trading with each other with no taker to name.
|
||||
*/
|
||||
kind: string,
|
||||
/**
|
||||
* `buy` or `sell`, from the taker's side. Absent for an unattributed
|
||||
* trade: there is no side to take.
|
||||
*/
|
||||
side: string | null,
|
||||
/**
|
||||
|
||||
@@ -164,7 +164,9 @@ export function IntentsPanel({
|
||||
key={c.counter_token}
|
||||
label={`${asset} in ${unit}`}
|
||||
value={`${fmtPrice(c.vwap)} ${unit}`}
|
||||
note={`${fmtHeight(c.trades)} trade${c.trades === 1 ? '' : 's'} · last ${fmtPrice(c.last_price)} ${unit}, ${ago(c.last_at)}`}
|
||||
note={`${fmtHeight(c.trades)} trade${c.trades === 1 ? '' : 's'}${
|
||||
c.taker_trades === c.trades ? '' : `, ${fmtHeight(c.taker_trades)} by users`
|
||||
} · last ${fmtPrice(c.last_price)} ${unit}, ${ago(c.last_at)}`}
|
||||
title={c.counter_token}
|
||||
/>
|
||||
)
|
||||
@@ -180,8 +182,10 @@ export function IntentsPanel({
|
||||
Some of these rest on fewer than five trades; a figure from one trade is one trade.{' '}
|
||||
</strong>
|
||||
)}
|
||||
Token names are each token's own description of itself; the contract behind a figure is
|
||||
in its tooltip.
|
||||
A trade is one user's side of a swap, priced from what they gave and what they got; a
|
||||
solver's routing through other tokens is never counted as a trade of its own, and
|
||||
solvers trading with each other are counted but name no side. Token names are each
|
||||
token's own description of itself; the contract behind a figure is in its tooltip.
|
||||
</p>
|
||||
<p className="panel-note">What is read: {data.reads}</p>
|
||||
</section>
|
||||
|
||||
Reference in New Issue
Block a user