Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions benchmarks/terminal-fill-quality.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ methodology:
- "Trade-size buckets (under $25, $25 to $250, over $250): median loss per bucket in the public JSON and on each product page, so terminals with different typical trade sizes are compared at equal size."
- "One row per product; the chain selector shows the product on one chain (Solana and five EVM chains), All chains pools its swaps across chains (bridge funding legs stay out). Each chain is sampled at a fixed daily rate, so All chains weighs a chain's sampled swaps by its swap attempts per sample: the pooled figure follows the users, not the sampler. Published from 50 priced swaps pooled over the chains at 25 or more; it waits while the chain carrying most of the flow fills."
- "Cross-chain (FOMO): the user pays on BNB, Robinhood Chain, Base, Ethereum or Arc and Relay delivers on Solana. Relay's public requests feed identifies the app's requests (fee address or referrer) with what the user sent in USD, the fees, both hashes and the status. Value received = what the settlement delivered on Solana: USDC / SOL exactly (FOMO funds the wallet this way; the token buy that follows is a native swap in the FOMO row) or a token at the pool's state before the swap."
- "Cross-chain split: terminal = the app fee the user paid; network = the origin gas (receipt on the chain's public RPC); relay = Relay's fees and spread (deposit minus received minus app fee); pool only when a token was delivered. A token sold on the origin chain is priced at that chain's pool state in its per-chain row; a token deposit from Solana keeps Relay's valuation, shown, not counted. Refunds and failures count in the fail rate. Perps are not measured; swaps under $2 are dropped."
- "Cross-chain split: terminal = the app fee the user paid; network = origin gas plus the destination gas Relay charged (its fee breakdown); relay = Relay's fixed and price fees plus the solver's spread (deposit minus received minus app fee minus that gas); pool only when a token was delivered. A token sold on the origin chain is priced at that chain's pool state in its per-chain row. Refunds and failures count in the fail rate. Perps are not measured; swaps under $2 are dropped."
- "Trading on another chain (FOMO on Robinhood Chain, BNB, Base, Ethereum, Arc): the user pays in USDC or SOL from the FOMO wallet, a Relay solver buys the token there. Value given = what was sent (tx fee inside); value received = the tokens delivered at the pool's state before the settlement swap: v2 forks from the Sync reserves minus the swap, v3 forks and Uniswap v4 from the price left by the previous swap on the pool, all from the pool's own logs on public RPCs."
- "Which side of an EVM pool is the token is settled by matching the swap event's amounts with the receipt's transfers, not the pool's token order. Split: terminal = the app fee; relay = what Relay kept (fees, spread, gas); pool = the settlement swap's impact and LP fee; network = the Solana tx fee (0 when the app's sponsor signs). Sales the other way (a token sold on that chain, USDC or SOL delivered on Solana) sit in the same per-chain row, priced at the origin pool's state before the sale."
- "FOMO sponsors gas: its own signer pays the tx fee, so the user's network cost is zero; its fee is a router commission plus user-signed USDC legs, all counted as terminal fee. pump.fun's app takes no fee; the fixed 0.001 SOL it forwards on some swaps is counted as network."
Expand Down Expand Up @@ -122,7 +122,7 @@ metric_panels:
metric: tfq_component_bps{component="network",chain="all"}
unit: bp
higher_is_better: false
description: "Median transaction fee paid by the user plus inclusion tips (Jito and the terminal's own relay), share of the trade. Zero when the terminal sponsors gas."
description: "Median transaction fee paid by the user plus inclusion tips (Jito and the terminal's own relay), share of the trade; on cross-chain rows the destination gas Relay charged (its fee breakdown) is included. Zero when the terminal sponsors gas."
- id: pool
label: Pool
label_key: terminal
Expand All @@ -137,7 +137,7 @@ metric_panels:
unit: bp
higher_is_better: false
tab: false
description: "Relay's fees and spread (deposit minus received minus app fee), share of the trade: the median on a chain row; on All chains, each chain's median weighted by its flow, blank when the bridged rows carry under half the product's flow (FOMO: most of its swaps are native on Solana)."
description: "Relay's fixed and price fees plus the solver's spread (deposit minus received minus app fee minus the destination gas, which is in Network), share of the trade: the chain row's median; on All chains flow-weighted, blank when the bridged rows carry under half the flow."
- id: other
label: Other fees
label_key: terminal
Expand Down
26 changes: 16 additions & 10 deletions harnesses/terminal-fill-quality/cmd/script/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -808,8 +808,8 @@ func sampleXchain(ctx context.Context, rpc *rpcClient, httpc *http.Client, st *S
q := sw.QuoteUSD
sw.UserQ = (x.UsdIn + gasUSD) / q // what the user sent on the origin chain, plus its gas
sw.TerminalQ = x.AppFeeUsd / q
sw.RelayQ = x.RelayFeeUsd / q
sw.NetworkQ = gasUSD / q
sw.RelayQ = (x.RelayFeeUsd + relayDeclaredFees(x)) / q
sw.NetworkQ = (gasUSD + x.DestGasUsd) / q
sw.Others, sw.OtherQ = nil, nil
if sw.PoolQ > 0 && sw.Pools == 1 {
o := sw.UserQ - sw.PoolQ - sw.TerminalQ - sw.RelayQ - sw.NetworkQ
Expand Down Expand Up @@ -1066,7 +1066,7 @@ var chainNames = map[string]string{"bnb": "BNB", "robinhood": "Robinhood Chain",
func cohort() []Terminal {
out := append([]Terminal{}, terminals...)
for _, a := range xchainApps {
out = append(out, Terminal{Slug: a.Slug + "-funding", Name: a.Name + " · funding", Kind: "app", Note: "Funding legs through Relay, either way: the user pays on BNB, Robinhood Chain, Base, Ethereum or Arc and receives USDC or SOL on Solana (FOMO; the token buy that follows is a native swap in the app's Solana row), or moves funds between the Solana and EVM wallets of the same app account, either direction (BasedBot: an in-app bridge, not a deposit to trade). Value given = the origin deposit plus its gas; received = the amount delivered; terminal = the app fee the user paid; relay = what Relay kept (fees and spread); network = origin gas. Refunded and failed requests count in the fail rate. Out of the product's pooled figure: a bridge, not a fill."})
out = append(out, Terminal{Slug: a.Slug + "-funding", Name: a.Name + " · funding", Kind: "app", Note: "Funding legs through Relay, either way: the user pays on BNB, Robinhood Chain, Base, Ethereum or Arc and receives USDC or SOL on Solana (FOMO; the token buy that follows is a native swap in the app's Solana row), or moves funds between the Solana and EVM wallets of the same app account, either direction (BasedBot: an in-app bridge, not a deposit to trade). Value given = the origin deposit plus its gas; received = the amount delivered; terminal = the app fee the user paid; network = origin gas plus the destination gas Relay charged (its fee breakdown); relay = the rest of what Relay kept (fixed and price fees, the solver's spread). Refunded and failed requests count in the fail rate. Out of the product's pooled figure: a bridge, not a fill."})
if a.FundingOnly {
continue
}
Expand All @@ -1084,6 +1084,12 @@ func cohort() []Terminal {
return out
}

// relayDeclaredFees: Relay's fixed and price fees (USD) from its breakdown,
// for the rows whose relay figure is not a residual.
func relayDeclaredFees(x relayRequest) float64 {
return x.RelayFixedUsd
}

// evmSaleRow measures a request that sold a token on its origin chain and
// settled USDC / SOL on Solana: the tokens sold at the origin pool's state
// before the swap versus what reached the user on Solana.
Expand Down Expand Up @@ -1117,9 +1123,9 @@ func evmSaleRow(ctx context.Context, rpc *rpcClient, httpc *http.Client, t Termi
}
sw.UserQ = recv.Tokens // quote received on Solana
sw.TerminalQ = x.AppFeeUsd / q
sw.NetworkQ = s.GasUSD / q // origin gas, paid by the user
sw.PoolQ = s.PoolInUSD / q // quote the origin pool paid out
relay := s.PoolInUSD - s.OtherUSD - x.AppFeeUsd - recv.Tokens*q
sw.NetworkQ = (s.GasUSD + x.DestGasUsd) / q // origin gas paid by the user, plus the destination gas Relay charged
sw.PoolQ = s.PoolInUSD / q // quote the origin pool paid out
relay := s.PoolInUSD - s.OtherUSD - x.AppFeeUsd - recv.Tokens*q - x.DestGasUsd
if relay < 0 {
relay = 0
}
Expand Down Expand Up @@ -1216,8 +1222,8 @@ func evmFundingRow(ctx context.Context, rpc *rpcClient, t Terminal, x relayReque
}
sw.UserQ = givenUSD / price
sw.TerminalQ = x.AppFeeUsd / price
sw.NetworkQ = feeUSD / price
relay := givenUSD - feeUSD - recv*price - x.AppFeeUsd
sw.NetworkQ = (feeUSD + x.DestGasUsd) / price
relay := givenUSD - feeUSD - recv*price - x.AppFeeUsd - x.DestGasUsd
if relay < 0 {
relay = 0
}
Expand Down Expand Up @@ -1268,9 +1274,9 @@ func evmRow(ctx context.Context, rpc *rpcClient, httpc *http.Client, t Terminal,
}
sw.UserQ = givenUSD / q
sw.TerminalQ = x.AppFeeUsd / q
sw.NetworkQ = feeUSD / q
sw.NetworkQ = (feeUSD + x.DestGasUsd) / q // origin gas, plus the destination gas Relay charged
sw.PoolQ = s.PoolInUSD / q
relay := givenUSD - feeUSD - x.AppFeeUsd - s.PoolInUSD - s.OtherUSD
relay := givenUSD - feeUSD - x.AppFeeUsd - s.PoolInUSD - s.OtherUSD - x.DestGasUsd
if relay < 0 {
relay = 0
}
Expand Down
77 changes: 52 additions & 25 deletions harnesses/terminal-fill-quality/cmd/script/xchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"fmt"
"io"
"log"
"math"
"math/rand"
"net/http"
"os"
Expand Down Expand Up @@ -158,26 +159,28 @@ func (x relayRequest) rowSlug() string {

// relayRequest is one settled (or failed) Relay request of a cohort app.
type relayRequest struct {
ID string `json:"id"`
App string `json:"app"`
Chain string `json:"chain"` // origin chain slug ("solana" when leaving Solana)
DestChain string `json:"dest_chain"` // destination chain slug when not Solana
TokenOut string `json:"token_out"` // destination token address when not Solana
Funding bool `json:"funding,omitempty"` // the gas coin (or Arc's USDC) delivered to the user's wallet on the destination: a funding leg, not a trade
OutValueWei string `json:"out_value_wei,omitempty"` // native amount delivered on the destination (Funding)
Status string `json:"status"`
User string `json:"user"` // origin address
Recipient string `json:"recipient"` // destination wallet
InTx string `json:"in_tx"`
OutTx string `json:"out_tx"` // destination transaction (Solana signature or EVM hash)
UsdIn float64 `json:"usd_in"`
UsdOut float64 `json:"usd_out"` // Relay's own valuation of the output, cross-check only
AppFeeUsd float64 `json:"app_fee_usd"`
RelayFeeUsd float64 `json:"relay_fee_usd"`
OutIsToken bool `json:"out_is_token"` // Solana side delivers a token (not SOL / a stable)
InIsToken bool `json:"in_is_token"` // origin side was a token (not the gas coin / a stable): usd_in is Relay's valuation, not an on-chain mid
TokenIn string `json:"token_in"` // origin token address when InIsToken
Created int64 `json:"created"`
ID string `json:"id"`
App string `json:"app"`
Chain string `json:"chain"` // origin chain slug ("solana" when leaving Solana)
DestChain string `json:"dest_chain"` // destination chain slug when not Solana
TokenOut string `json:"token_out"` // destination token address when not Solana
Funding bool `json:"funding,omitempty"` // the gas coin (or Arc's USDC) delivered to the user's wallet on the destination: a funding leg, not a trade
OutValueWei string `json:"out_value_wei,omitempty"` // native amount delivered on the destination (Funding)
Status string `json:"status"`
User string `json:"user"` // origin address
Recipient string `json:"recipient"` // destination wallet
InTx string `json:"in_tx"`
OutTx string `json:"out_tx"` // destination transaction (Solana signature or EVM hash)
UsdIn float64 `json:"usd_in"`
UsdOut float64 `json:"usd_out"` // Relay's own valuation of the output, cross-check only
AppFeeUsd float64 `json:"app_fee_usd"`
RelayFeeUsd float64 `json:"relay_fee_usd"`
DestGasUsd float64 `json:"dest_gas_usd,omitempty"`
RelayFixedUsd float64 `json:"relay_fixed_usd,omitempty"` // Relay's fixed + price fees from its breakdown // destination gas Relay charged the user (actual execution when reported, else the quoted gas fee): network cost
OutIsToken bool `json:"out_is_token"` // Solana side delivers a token (not SOL / a stable)
InIsToken bool `json:"in_is_token"` // origin side was a token (not the gas coin / a stable): usd_in is Relay's valuation, not an on-chain mid
TokenIn string `json:"token_in"` // origin token address when InIsToken
Created int64 `json:"created"`
}

type relayResp struct {
Expand All @@ -198,8 +201,16 @@ type relayRaw struct {
Bps string `json:"bps"`
AmountUsd string `json:"amountUsd"`
} `json:"appFees"`
InTxs []relayTx `json:"inTxs"`
OutTxs []relayTx `json:"outTxs"`
InTxs []relayTx `json:"inTxs"`
OutTxs []relayTx `json:"outTxs"`
// Relay's own fee breakdown, USD: gas (destination execution), fixed (the relayer), price (the swap).
FeesUsd map[string]string `json:"feesUsd"`
// What actually happened, USD, signed from the user's side: execution (gas, negative), app, swap, relay.
ExpandedPriceImpact struct {
Actual map[string]struct {
Usd string `json:"usd"`
} `json:"actual"`
} `json:"expandedPriceImpact"`
Metadata struct {
CurrencyIn relayAmount `json:"currencyIn"`
CurrencyOut relayAmount `json:"currencyOut"`
Expand Down Expand Up @@ -699,14 +710,30 @@ func classify(a xchainApp, c originChain, r relayRaw) (relayRequest, bool) {
} else {
x.AppFeeUsd = appFee
}
for _, k := range []string{"execution", "swap", "relay", "rent"} {
for _, k := range []string{"swap", "relay", "rent"} {
if v, ok := comps[k]; ok {
x.RelayFeeUsd += f64(v.UserPays.AmountUsd)
}
}
if v, ok := comps["execution"]; ok {
x.DestGasUsd = f64(v.UserPays.AmountUsd)
}
} else {
x.AppFeeUsd = appFee
}
for _, k := range []string{"fixed", "price"} {
if v, ok := r.Data.FeesUsd[k]; ok {
x.RelayFixedUsd += math.Abs(f64(v))
}
}
// Relay's breakdown: the destination gas is network cost, not the bridge's take.
if x.DestGasUsd == 0 {
if v, ok := r.Data.ExpandedPriceImpact.Actual["execution"]; ok {
x.DestGasUsd = math.Abs(f64(v.Usd))
} else if g, ok := r.Data.FeesUsd["gas"]; ok {
x.DestGasUsd = math.Abs(f64(g))
}
}
return x, true
}

Expand Down Expand Up @@ -782,8 +809,8 @@ func bridgeRow(t Terminal, x relayRequest, tx *parsedTx, solUSD, gasUSD float64)
}
sw.UserQ = (x.UsdIn + gasUSD) / q
sw.TerminalQ = x.AppFeeUsd / q
sw.NetworkQ = gasUSD / q
relay := x.UsdIn - recv*q - x.AppFeeUsd
sw.NetworkQ = (gasUSD + x.DestGasUsd) / q // origin gas plus the destination gas Relay charged
relay := x.UsdIn - recv*q - x.AppFeeUsd - x.DestGasUsd
if relay < 0 {
relay = 0
}
Expand Down
2 changes: 1 addition & 1 deletion src/components/terminal-fill-section.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@
<Th right title="Median value lost per swap against the pool's state before the trade, all costs included, basis points of the trade (100 bps = 1 %); hover for the percent and the 95 % interval of the median">Value lost</Th>
<Th right title="Median loss applied to the median trade: what the typical swap on this terminal loses, in dollars">Lost / swap</Th>
<Th right title="What the terminal took, basis points of the trade (median): its fee wallets and fee legs on Solana, the router's residual after the pool and the gas on the EVM rows (referral transfers included), the app fee on Relay legs; referral or cashback legs count as terminal fee where the terminal's list holds them, else they sit in Other">Terminal</Th>
<Th right title="Transaction fee paid by the user plus inclusion tips (Jito and the terminal's own relay), basis points (median per chain; flow-weighted on All chains)">Network</Th>
<Th right title="Transaction fee paid by the user plus inclusion tips (Jito and the terminal's own relay), and on cross-chain rows the destination gas Relay charged, basis points (median per chain; flow-weighted on All chains)">Network</Th>
<Th right title="The final pool's LP fee and price impact, basis points (median per chain; on All chains each chain's median weighted by its flow); on cross-chain products the bridge's take is shown next to it as relay; on the EVM rows the stable-to-gas-coin hop's own cost is included (the native leg is valued at that hop's pre-trade mid)">Pool</Th>
<Th right title="pump.fun protocol and creator fees, referral payouts, and on routed swaps the routers' cuts and hop leftovers, basis points (median per chain; flow-weighted on All chains)">Other</Th>
<Th right title="Share of the terminal's swap attempts that failed on-chain; the priority fee is paid anyway unless the app sponsors gas (FOMO)">Failed</Th>
Expand Down Expand Up @@ -147,7 +147,7 @@
</table>
</div>
<p className="mb-6 flex flex-wrap gap-x-4 gap-y-1 text-[11px] text-ink-soft">
<span className="text-ink-faint">Split columns are medians of each cost in basis points of the trade (100 bps = 1 %), each chain's median weighted by its flow on a multi-chain product; they do not sum to the median loss, the per-swap sums do (audit table).</span>

Check failure on line 150 in src/components/terminal-fill-section.tsx

View workflow job for this annotation

GitHub Actions / check

`'` can be escaped with `&apos;`, `&lsquo;`, `&#39;`, `&rsquo;`
{PARTS.map((c) => (
<span key={c} className="inline-flex items-center gap-1.5">
<i className="inline-block h-2 w-2 rounded-sm" style={{ background: COLORS[c] }} />
Expand Down
2 changes: 1 addition & 1 deletion src/components/terminal-fill-swaps.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ export function TerminalFillSwaps({ swaps, terminals, focus }: { swaps: FillSamp
{th("loss", "Loss", "1 − value received / value given, basis points of the trade; ! = out of bounds, excluded from the statistics")}
{th(undefined, "Where it goes", "terminal fee · network (tx fee + tips) · other (pump.fun, creator, referral) · pool (LP fee + impact, hops); shared 0 to 1,000 bps scale", "left")}
{th("terminal", "Fee", "terminal fee, bps")}
{th("network", "Net", "tx fee + inclusion tips, bps")}
{th("network", "Net", "tx fee + inclusion tips, bps; on Relay rows the destination gas Relay charged is included")}
{th(undefined, "Other", "pump.fun / creator / referral fees, and on routed swaps the routers' cuts and hop leftovers, bps; blank when a routed swap's residual exceeds a quarter of the trade (left in Pool)")}
{th("pool", "Pool", "loss − explicit costs: LP fee + impact (+ hops), bps")}
{th(undefined, "Reference", "exact mid: the pool's reserves before the swap; previous trade: the trade before ours on the same pool, age in seconds", "left")}
Expand Down
Loading