Aller au contenu
login
arrow_backRetour aux issues
Wayfare-labs/wayfare #54

Effective transfer cost decomposition: FX loss, fees, slippage, expected-failure-cost

ecoDébutant help wanted area:pricing difficulty:medium

descriptionDescription

> Written to the standard set by #33 — read that issue first for the expected level of detail. ## What Decompose the effective transfer cost into four separately-reported components: FX loss, fees, slippage, and expected failure cost. Each is computed and reported independently. Expected failure cost stays **explicitly unknown** until failure history exists. Currently, the verdict reports a single loss percentage against fair value. That number is useful but opaque — a 27% loss could be mostly FX spread, mostly fees, mostly slippage, or some combination. A reader deciding whether to use a corridor needs to know *where* the cost is coming from, not just that it exists. ## Why it matters A route with a worse headline rate can be cheaper all-in if it has lower fees or less slippage. Showing that decomposition is the point — it turns a single verdict into actionable information. Without it, the reader cannot distinguish "this corridor has a bad rate" from "this corridor has good rates but high fees" from "this corridor is thin and slippage dominates at size." ## Which layer **Layer 2 — computed from observable data.** The components are derived from pathfinding results, SEP-38 quotes, and the reference rate. Nothing is inferred beyond what the data supports. ## Exactly where the code goes - **Modified files:** `route/route.go` (or a new `route/cost.go` if the decomposition is complex enough) - **Tests:** `route/route_test.go` - The decomposition should be a function that takes a priced route and returns the four components - Each component is a `decimal.Decimal` with a unit (percent or absolute) - The wire format in `server/api.go` is extended to include the decomposition (or a new endpoint) ## Where the data comes from - **FX loss:** difference between the route's received amount and the reference mid (already computed by the verdict) - **Fees:** sum of explicit fees from SEP-38 quotes and implicit fees from the route's spread (available from `sep38/` and `dex/`) - **Slippage:** difference between the quoted price and the executable price at the actual trade size (available from `dex/` order book data) - **Expected failure cost:** explicitly `UNABLE-TO-DETERMINE` — the data does not exist yet ## What "unmeasurable" means here The expected failure cost is the key case. Until the project has observed actual payment failures (which requires history that `runstore` is collecting but does not yet have enough of), this component must be reported as unknown. It must not be estimated, defaulted to zero, or filled in with a plausible-looking number. The other three components are computable from existing data. If any of them cannot be computed for a specific route (e.g., no SEP-38 quote available), that component is reported as `UNABLE-TO-DETERMINE` with a reason. ## Acceptance criteria - [ ] Implements the decomposition as described in `docs/checks.md` (MetricResult shape, not CheckResult) - [ ] Each component is reported separately — never blended into a single number - [ ] Expected failure cost is `UNABLE-TO-DETERMINE` with a reason explaining why - [ ] `decimal.Decimal` for all values; no `float64` - [ ] Network I/O goes through the existing `http.RoundTripper` seam - [ ] Table tests driven from recorded bytes — no live network in tests - [ ] Includes a negative test: a case where a component must be undeterminable - [ ] `gofmt`, `go vet`, `go test -race`, `golangci-lint` all clean - [ ] Does not change the headline integrity state or verdict thresholds - [ ] The wire format is backward-compatible (new fields are optional/omittable) ## Out of scope Do not change: - The verdict thresholds or bands - The integrity taxonomy - `refrate/` code - `runstore/runstore.go` — the record shape is hash-chained; changing it is a version bump - The check engine in `checks/` ## How to verify locally ```bash make offline-test go test ./route/ -run TestCostDecomposition -v make fmt vet test race lint ``` Then confirm it falsifies —
codeOuvre sur GitHub