@gibs/bridge-sdk 1.18.0 → 1.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +33 -0
- package/dist/abis.js +0 -2
- package/dist/bridge-limits.js +0 -38
- package/dist/chain-info.js +0 -116
- package/dist/chain-names.js +0 -151
- package/dist/chains.js +0 -198
- package/dist/cjs/abis.js +0 -2
- package/dist/cjs/bridge-limits.js +0 -38
- package/dist/cjs/chain-info.js +0 -116
- package/dist/cjs/chain-names.js +0 -151
- package/dist/cjs/chains.js +0 -198
- package/dist/cjs/claims.js +0 -60
- package/dist/cjs/config.js +1 -208
- package/dist/cjs/consolidated-quote.js +2 -464
- package/dist/cjs/destination-calldata.js +0 -71
- package/dist/cjs/ecosystems.js +0 -183
- package/dist/cjs/execution.js +0 -92
- package/dist/cjs/fee-type.js +0 -1
- package/dist/cjs/hyperliquid-execution.js +0 -98
- package/dist/cjs/image-links.js +0 -108
- package/dist/cjs/lifi-execution-guard.js +65 -172
- package/dist/cjs/near-intents-conformance.js +0 -110
- package/dist/cjs/near-intents-route.d.ts +13 -0
- package/dist/cjs/near-intents-route.js +7 -140
- package/dist/cjs/near-intents.js +0 -562
- package/dist/cjs/origin-deposit.js +0 -56
- package/dist/cjs/pre-quote.js +0 -80
- package/dist/cjs/prices.js +0 -113
- package/dist/cjs/providers.js +0 -83
- package/dist/cjs/quote-fees.js +0 -80
- package/dist/cjs/referral.js +0 -75
- package/dist/cjs/relay-currencies.js +0 -31
- package/dist/cjs/relay-depository.js +52 -77
- package/dist/cjs/relay-quote.js +0 -394
- package/dist/cjs/route-steps.js +0 -100
- package/dist/cjs/routing/amounts.js +0 -83
- package/dist/cjs/routing/candidate-route.d.ts +46 -1
- package/dist/cjs/routing/candidate-route.js +12 -40
- package/dist/cjs/routing/candidate.js +0 -46
- package/dist/cjs/routing/carrier-provider-key.js +0 -27
- package/dist/cjs/routing/carriers/omnibridge.js +0 -120
- package/dist/cjs/routing/carriers/pulsex-paths.js +0 -57
- package/dist/cjs/routing/carriers/pulsex-split.js +0 -92
- package/dist/cjs/routing/carriers/pulsex.js +0 -279
- package/dist/cjs/routing/carriers/wrap.js +0 -57
- package/dist/cjs/routing/composed-route-quality.js +0 -95
- package/dist/cjs/routing/entry-chain-anchor.js +0 -27
- package/dist/cjs/routing/format.js +0 -50
- package/dist/cjs/routing/index.d.ts +1 -1
- package/dist/cjs/routing/index.js +3 -30
- package/dist/cjs/routing/producers.js +0 -854
- package/dist/cjs/routing/providers.js +0 -27
- package/dist/cjs/routing/search/compose.js +0 -56
- package/dist/cjs/routing/search/graph.js +0 -364
- package/dist/cjs/routing/search/plan-route-data.js +5 -510
- package/dist/cjs/routing/search/score.js +0 -344
- package/dist/cjs/routing/swap-transactions.js +0 -74
- package/dist/cjs/routing/usd-value.js +0 -12
- package/dist/cjs/settings.js +1 -456
- package/dist/cjs/swap-venues.js +0 -17
- package/dist/cjs/ton-connect.js +0 -82
- package/dist/cjs/ton-execution.js +0 -6
- package/dist/cjs/ton.js +0 -42
- package/dist/cjs/tron-execution.js +0 -145
- package/dist/cjs/types.d.ts +8 -0
- package/dist/claims.js +0 -60
- package/dist/config.js +1 -211
- package/dist/consolidated-quote.js +2 -464
- package/dist/destination-calldata.js +0 -71
- package/dist/ecosystems.js +0 -183
- package/dist/execution.js +0 -92
- package/dist/fee-type.js +0 -2
- package/dist/hyperliquid-execution.js +0 -98
- package/dist/image-links.js +0 -108
- package/dist/lifi-execution-guard.js +65 -172
- package/dist/near-intents-conformance.js +0 -110
- package/dist/near-intents-route.d.ts +13 -0
- package/dist/near-intents-route.js +5 -139
- package/dist/near-intents.js +0 -562
- package/dist/origin-deposit.js +0 -56
- package/dist/pre-quote.js +0 -80
- package/dist/prices.js +0 -113
- package/dist/providers.js +0 -83
- package/dist/quote-fees.js +0 -80
- package/dist/referral.js +0 -75
- package/dist/relay-currencies.js +0 -31
- package/dist/relay-depository.js +52 -77
- package/dist/relay-quote.js +0 -394
- package/dist/route-steps.js +0 -100
- package/dist/routing/amounts.js +0 -83
- package/dist/routing/candidate-route.d.ts +46 -1
- package/dist/routing/candidate-route.js +10 -39
- package/dist/routing/candidate.js +0 -46
- package/dist/routing/carrier-provider-key.js +0 -27
- package/dist/routing/carriers/omnibridge.js +0 -120
- package/dist/routing/carriers/pulsex-paths.js +0 -57
- package/dist/routing/carriers/pulsex-split.js +0 -92
- package/dist/routing/carriers/pulsex.js +0 -279
- package/dist/routing/carriers/wrap.js +0 -57
- package/dist/routing/composed-route-quality.js +0 -95
- package/dist/routing/entry-chain-anchor.js +0 -27
- package/dist/routing/format.js +0 -50
- package/dist/routing/index.d.ts +1 -1
- package/dist/routing/index.js +1 -29
- package/dist/routing/producers.js +0 -854
- package/dist/routing/providers.js +0 -27
- package/dist/routing/search/compose.js +0 -56
- package/dist/routing/search/graph.js +0 -364
- package/dist/routing/search/plan-route-data.js +6 -511
- package/dist/routing/search/score.js +0 -344
- package/dist/routing/swap-transactions.js +0 -74
- package/dist/routing/usd-value.js +0 -12
- package/dist/settings.js +1 -456
- package/dist/swap-venues.js +0 -17
- package/dist/ton-connect.js +0 -82
- package/dist/ton-execution.js +0 -6
- package/dist/ton.js +0 -42
- package/dist/tron-execution.js +0 -145
- package/dist/types.d.ts +8 -0
- package/package.json +3 -3
|
@@ -3,70 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.compareRoutePlansByGasAdjustedDeliveredAmount = exports.gasAdjustedDeliveredAmount = exports.sectionIsFundedByLanding = exports.zeroGasCostFor = exports.scoreRoutePlan = exports.compareRoutePlansByScoreAdjustedDeliveredAmount = exports.GAS_TOPUP_PENALTY_FLOOR_USD = exports.GAS_TOPUP_PENALTY_PPM = exports.SIGNATURE_PENALTY_FLOOR_USD = exports.SIGNATURE_PENALTY_PPM = exports.waitPenaltyPpm = void 0;
|
|
4
4
|
const ecosystems_js_1 = require("../../ecosystems.js");
|
|
5
5
|
const graph_js_1 = require("./graph.js");
|
|
6
|
-
/**
|
|
7
|
-
* PHASE 0 — FOUNDATION ONLY. Today this module holds exactly one function,
|
|
8
|
-
* {@link waitPenaltyPpm}, moved here unchanged from
|
|
9
|
-
* `packages/ui/src/lib/stores/consolidated-quote.ts` (that file now imports
|
|
10
|
-
* and re-exports it, so every existing caller keeps working). Phase 1's
|
|
11
|
-
* `score.ts` work (design section 4) generalizes `candidateNetValueUsd` and
|
|
12
|
-
* `netValueAfterWaitPenalty` from `../producers.js` and
|
|
13
|
-
* `packages/ui/src/lib/state/useRouteOptions.ts` into one `scoreRoutePlan`
|
|
14
|
-
* function that lives here beside it.
|
|
15
|
-
*
|
|
16
|
-
* WHY THIS MOVES TO `bridge-sdk` AT ALL. `waitPenaltyPpm` is a pure function
|
|
17
|
-
* of a number — it has no dependency on React, a store, or any
|
|
18
|
-
* user-interface concern — and `scoreRoutePlan` will need it to score a
|
|
19
|
-
* `RoutePlan` (`../graph.js`), which is a `bridge-sdk` type. Leaving the
|
|
20
|
-
* function in the user-interface package would make `bridge-sdk`'s own
|
|
21
|
-
* scoring logic import FROM the application that is supposed to consume it.
|
|
22
|
-
*/
|
|
23
|
-
/**
|
|
24
|
-
* The share of the transfer a full minute of extra waiting is charged, in
|
|
25
|
-
* parts per million — 5,000 ppm is half of one percent.
|
|
26
|
-
*
|
|
27
|
-
* WHERE THE NUMBER COMES FROM. The owner's own crossing: LI.FI (through
|
|
28
|
-
* squid) claimed twenty seconds and Relay claimed two, and the strip
|
|
29
|
-
* preferred LI.FI because it delivered 0.075% more — nine cents on a
|
|
30
|
-
* hundred and twenty-six dollars. The transfer was still unsettled
|
|
31
|
-
* twenty-five minutes later. A second live measurement on Base to Polygon:
|
|
32
|
-
* twenty-nine seconds against three, for 0.0545%. Both are the same shape —
|
|
33
|
-
* a few cents of advantage bought with a ten-fold increase in the wait —
|
|
34
|
-
* and under this rate both go the other way: at eighteen seconds of extra
|
|
35
|
-
* claimed wait a route must deliver 0.15% more to win, and at twenty-six
|
|
36
|
-
* seconds it must deliver 0.217% more. Neither does.
|
|
37
|
-
*
|
|
38
|
-
* The rate is also calibrated NOT to override a real price advantage. A
|
|
39
|
-
* route that is a full minute slower still wins on 0.6% more delivered,
|
|
40
|
-
* which on a hundred-and-twenty-six-dollar transfer is seventy-six cents —
|
|
41
|
-
* a figure worth waiting a minute for, where nine cents is not.
|
|
42
|
-
*/
|
|
43
6
|
const WAIT_PENALTY_PPM_PER_MINUTE = 5_000;
|
|
44
|
-
/** The wait beyond which extra claimed seconds stop adding to the penalty. */
|
|
45
7
|
const WAIT_PENALTY_CEILING_SECONDS = 60;
|
|
46
|
-
/**
|
|
47
|
-
* What a quote's CLAIMED duration costs it in the ranking, as a share of the
|
|
48
|
-
* transfer in parts per million. It ramps linearly to
|
|
49
|
-
* {@link WAIT_PENALTY_PPM_PER_MINUTE} at {@link WAIT_PENALTY_CEILING_SECONDS}
|
|
50
|
-
* and stops there.
|
|
51
|
-
*
|
|
52
|
-
* THE DURATION IS A CLAIM AND IS TREATED AS ONE. The route that prompted
|
|
53
|
-
* this ran about seventy-five times its provider's own estimate, so the
|
|
54
|
-
* figure cannot be trusted as a measurement of anything. It is still the
|
|
55
|
-
* only signal there is, and it is informative in one direction: a provider
|
|
56
|
-
* that says it will take longer is not going to turn out faster, and a
|
|
57
|
-
* claimed wait understates the real one far more often than it overstates
|
|
58
|
-
* it. So the penalty is used to demand a real price advantage before ANY
|
|
59
|
-
* extra claimed wait is accepted — never to predict a settlement time, and
|
|
60
|
-
* never to produce a number shown to the reader. Nothing on screen is
|
|
61
|
-
* adjusted by this; only the order is.
|
|
62
|
-
*
|
|
63
|
-
* The ceiling is what keeps the rule from becoming a speed preference. Past
|
|
64
|
-
* a minute the penalty stops growing, so a route that is genuinely worth
|
|
65
|
-
* waiting for still wins on the strength of its price.
|
|
66
|
-
*
|
|
67
|
-
* @param durationSeconds - the provider's own claimed execution duration
|
|
68
|
-
* @returns the penalty as parts per million of the transfer, 0 for a missing claim
|
|
69
|
-
*/
|
|
70
8
|
const waitPenaltyPpm = (durationSeconds) => {
|
|
71
9
|
if (typeof durationSeconds !== 'number' || !Number.isFinite(durationSeconds))
|
|
72
10
|
return 0;
|
|
@@ -76,185 +14,13 @@ const waitPenaltyPpm = (durationSeconds) => {
|
|
|
76
14
|
return Math.round((WAIT_PENALTY_PPM_PER_MINUTE * rampedSeconds) / WAIT_PENALTY_CEILING_SECONDS);
|
|
77
15
|
};
|
|
78
16
|
exports.waitPenaltyPpm = waitPenaltyPpm;
|
|
79
|
-
// ---------------------------------------------------------------------------
|
|
80
|
-
// scoreRoutePlan — the one maximization function
|
|
81
|
-
// ---------------------------------------------------------------------------
|
|
82
|
-
/**
|
|
83
|
-
* The share of the transfer charged for EACH reader action beyond the first,
|
|
84
|
-
* in parts per million — see {@link signaturePenaltyUsd}.
|
|
85
|
-
*
|
|
86
|
-
* THIS IS A PROPOSAL, NOT A MEASUREMENT. Unlike {@link WAIT_PENALTY_PPM_PER_MINUTE},
|
|
87
|
-
* which is calibrated against two logged, live crossings, no comparable
|
|
88
|
-
* signature-count measurement exists yet. 2,500 ppm (0.25% of the delivered
|
|
89
|
-
* amount) is a starting point sized to sit BELOW the wait penalty's own
|
|
90
|
-
* ceiling (5,000 ppm) — a second signature should cost less than the worst
|
|
91
|
-
* wait penalty already accepted, since a signature is a moment of the
|
|
92
|
-
* reader's attention, not twenty-five minutes of theirs. The owner is meant
|
|
93
|
-
* to calibrate this against real reader behavior once it ships.
|
|
94
|
-
*/
|
|
95
17
|
exports.SIGNATURE_PENALTY_PPM = 2_500;
|
|
96
|
-
/**
|
|
97
|
-
* SUPERSEDED FOR THE SEARCH ENGINE'S OWN RANKING — see
|
|
98
|
-
* {@link compareRoutePlansByGasAdjustedDeliveredAmount}, below, which
|
|
99
|
-
* `waves.ts` now uses in place of {@link compareRoutePlansByScoreAdjustedDeliveredAmount}
|
|
100
|
-
* once real gas data exists. A flat parts-per-million guess cannot tell a
|
|
101
|
-
* cheap chain from an expensive one, and it charges nothing for gas at all —
|
|
102
|
-
* the owner's own instruction: "it's custom for each provider ... gather the
|
|
103
|
-
* logic around how much a user is about to be charged." This constant, and
|
|
104
|
-
* {@link GAS_TOPUP_PENALTY_PPM} below, are KEPT UNCHANGED because
|
|
105
|
-
* {@link scoreRoutePlan} and every existing United States dollar-based
|
|
106
|
-
* caller of it (`plan-route-data.ts`, `producers.ts`, the user interface's
|
|
107
|
-
* own single-candidate scoring) still read them — migrating those callers to
|
|
108
|
-
* a real gas-cost model is FLAGGED HERE as follow-up work outside this
|
|
109
|
-
* module's own owned scope, not done silently in this change.
|
|
110
|
-
*/
|
|
111
|
-
/**
|
|
112
|
-
* The minimum a signature is ever charged, in United States dollars — see
|
|
113
|
-
* {@link signaturePenaltyUsd}.
|
|
114
|
-
*
|
|
115
|
-
* THIS IS A PROPOSAL, NOT A MEASUREMENT. Without a floor, {@link SIGNATURE_PENALTY_PPM}
|
|
116
|
-
* charges almost nothing on a small transfer (0.25% of ten dollars is two and
|
|
117
|
-
* a half cents), which would let a route add a whole extra signature for a
|
|
118
|
-
* fraction of a cent. One dollar is a guess at what a reader's own time and
|
|
119
|
-
* attention for one extra wallet prompt is worth, floored so it cannot be
|
|
120
|
-
* bought away by a large delivered amount either — the floor and the rate are
|
|
121
|
-
* a `max`, so whichever is larger applies. The owner is meant to calibrate
|
|
122
|
-
* this once real reader behavior is observed.
|
|
123
|
-
*/
|
|
124
18
|
exports.SIGNATURE_PENALTY_FLOOR_USD = 1;
|
|
125
|
-
/**
|
|
126
|
-
* The share of the transfer charged for EACH intermediate chain where the
|
|
127
|
-
* reader holds no gas, in parts per million — see {@link gasTopUpPenaltyUsd}.
|
|
128
|
-
*
|
|
129
|
-
* THIS IS A PROPOSAL, NOT A MEASUREMENT. Sized larger than
|
|
130
|
-
* {@link SIGNATURE_PENALTY_PPM} because a gas top-up is not a moment of
|
|
131
|
-
* attention like a signature — it is a SEPARATE errand: acquire the
|
|
132
|
-
* intermediate chain's native coin, by another bridge or a purchase, before
|
|
133
|
-
* the planned hop can even be signed. That errand risks stranding the
|
|
134
|
-
* transfer mid-route if the reader does not complete it, which the
|
|
135
|
-
* "stranded funds" risk in the route-search design's section 10 names
|
|
136
|
-
* directly. The owner is meant to calibrate this once real reader behavior
|
|
137
|
-
* is observed.
|
|
138
|
-
*/
|
|
139
19
|
exports.GAS_TOPUP_PENALTY_PPM = 10_000;
|
|
140
|
-
/**
|
|
141
|
-
* The minimum a gas top-up is ever charged, in United States dollars — see
|
|
142
|
-
* {@link gasTopUpPenaltyUsd}.
|
|
143
|
-
*
|
|
144
|
-
* THIS IS A PROPOSAL, NOT A MEASUREMENT. Set higher than
|
|
145
|
-
* {@link SIGNATURE_PENALTY_FLOOR_USD} for the same reason
|
|
146
|
-
* {@link GAS_TOPUP_PENALTY_PPM} is: this penalty stands in for a separate
|
|
147
|
-
* errand with its own real cost (buying gas on a chain the reader was not
|
|
148
|
-
* already using), not a moment of attention. The owner is meant to calibrate
|
|
149
|
-
* this once real reader behavior is observed.
|
|
150
|
-
*/
|
|
151
20
|
exports.GAS_TOPUP_PENALTY_FLOOR_USD = 3;
|
|
152
|
-
/**
|
|
153
|
-
* What one extra reader action (a signature or a pay-by-hand deposit) costs
|
|
154
|
-
* in the ranking, in United States dollars: the larger of
|
|
155
|
-
* {@link SIGNATURE_PENALTY_FLOOR_USD} and {@link SIGNATURE_PENALTY_PPM} of
|
|
156
|
-
* the delivered amount. See both constants' docs for where the numbers come
|
|
157
|
-
* from and that they are proposals, not measurements.
|
|
158
|
-
*
|
|
159
|
-
* @param deliveredUsd - the route's delivered value in United States dollars
|
|
160
|
-
* @returns the penalty for one extra action, always positive
|
|
161
|
-
*/
|
|
162
21
|
const signaturePenaltyUsd = (deliveredUsd) => Math.max(exports.SIGNATURE_PENALTY_FLOOR_USD, (deliveredUsd * exports.SIGNATURE_PENALTY_PPM) / 1_000_000);
|
|
163
|
-
/**
|
|
164
|
-
* What one intermediate chain with no reader gas costs in the ranking, in
|
|
165
|
-
* United States dollars: the larger of {@link GAS_TOPUP_PENALTY_FLOOR_USD}
|
|
166
|
-
* and {@link GAS_TOPUP_PENALTY_PPM} of the delivered amount. See both
|
|
167
|
-
* constants' docs for where the numbers come from and that they are
|
|
168
|
-
* proposals, not measurements.
|
|
169
|
-
*
|
|
170
|
-
* @param deliveredUsd - the route's delivered value in United States dollars
|
|
171
|
-
* @returns the penalty for one gasless intermediate chain, always positive
|
|
172
|
-
*/
|
|
173
22
|
const gasTopUpPenaltyUsd = (deliveredUsd) => Math.max(exports.GAS_TOPUP_PENALTY_FLOOR_USD, (deliveredUsd * exports.GAS_TOPUP_PENALTY_PPM) / 1_000_000);
|
|
174
|
-
/**
|
|
175
|
-
* The one maximization function a route search ranks every plan by —
|
|
176
|
-
* generalizing today's `candidateNetValueUsd` and `netValueAfterWaitPenalty`
|
|
177
|
-
* (`../producers.js` and `packages/ui/src/lib/state/useRouteOptions.ts`)
|
|
178
|
-
* from a single quoted candidate to a whole {@link RouteScoreInputs} plan, per
|
|
179
|
-
* the route-search design's section 4:
|
|
180
|
-
*
|
|
181
|
-
* ```
|
|
182
|
-
* score = D − P − F
|
|
183
|
-
* − Σ_legs D·waitPenaltyPpm(claimedSeconds_leg)/1e6
|
|
184
|
-
* − (A − 1)·max($1, D·SIGNATURE_PENALTY_PPM/1e6)
|
|
185
|
-
* − G·max($3, D·GAS_TOPUP_PENALTY_PPM/1e6)
|
|
186
|
-
* ```
|
|
187
|
-
*
|
|
188
|
-
* A HIGHER SCORE IS BETTER. A route search picks the plan with the largest
|
|
189
|
-
* `scoreRoutePlan` result, exactly as today's ranking picks the candidate
|
|
190
|
-
* with the largest `netValueAfterWaitPenalty`.
|
|
191
|
-
*
|
|
192
|
-
* THE WAIT PENALTY IS UNCHANGED, JUST SUMMED ACROSS LEGS. Today's single-quote
|
|
193
|
-
* penalty is `deliveredUsd * waitPenaltyPpm(oneClaimedDuration) / 1e6`, one
|
|
194
|
-
* term. A plan can carry several hops, each with its own claimed duration, so
|
|
195
|
-
* this sums that same per-unit charge over every hop in
|
|
196
|
-
* {@link RouteScoreInputs.legClaimedDurationsSeconds} — still against the
|
|
197
|
-
* PLAN'S total delivered value, not each leg's own, because the reader is
|
|
198
|
-
* charged for the whole route's wait, not a fraction of it per leg.
|
|
199
|
-
*
|
|
200
|
-
* WHAT IS NEW: THE ACTION AND GAS-TOP-UP TERMS. Today's ranking only ever
|
|
201
|
-
* compared plans that cost one signature, so it had nothing to charge for a
|
|
202
|
-
* second one. A general search can find a plan needing two or three actions,
|
|
203
|
-
* or one that strands the reader without gas on an intermediate chain — see
|
|
204
|
-
* `signaturePenaltyUsd` and `gasTopUpPenaltyUsd` for what each extra action
|
|
205
|
-
* or gasless chain costs, and {@link SIGNATURE_PENALTY_PPM} /
|
|
206
|
-
* {@link GAS_TOPUP_PENALTY_PPM} for where the rates come from.
|
|
207
|
-
*
|
|
208
|
-
* WHY `(A − 1)` AND NOT `A`. Every plan needs at least one action to execute
|
|
209
|
-
* at all — signing or depositing is not itself a mark against a route, it is
|
|
210
|
-
* what EXECUTES it. Only actions beyond the first are extra friction the
|
|
211
|
-
* reader would not have paid on a one-action alternative, so only those are
|
|
212
|
-
* charged.
|
|
213
|
-
*
|
|
214
|
-
* REFUSES AN UNPRICED PLAN BY SCORING IT NEGATIVE INFINITY — PHASE 3. When
|
|
215
|
-
* {@link RouteScoreInputs.basis} is `'unpriced'`, `deliveredUsd` is a bare
|
|
216
|
-
* decimal rescale with no value behind it (see `EstimateBasis`'s own doc,
|
|
217
|
-
* `graph.ts`), and no arithmetic performed on it below would make it
|
|
218
|
-
* trustworthy. Returning `Number.NEGATIVE_INFINITY` rather than, say, `-1` or
|
|
219
|
-
* `0` is what makes this impossible to sidestep BY ACCIDENT: an ordinary `>`
|
|
220
|
-
* comparison, a plain numeric `.sort()`, or a `Math.max` over several plans'
|
|
221
|
-
* scores all already put an unpriced plan last WITHOUT the caller having to
|
|
222
|
-
* remember to check {@link RouteScoreInputs.basis} first — the same defence
|
|
223
|
-
* `compareRoutePlansByDeliveredAmount` (`graph.ts`) applies explicitly to a
|
|
224
|
-
* plan-to-plan comparison, applied here so a caller who reaches for
|
|
225
|
-
* `scoreRoutePlan` directly, for a single plan's score, gets the same
|
|
226
|
-
* protection for free.
|
|
227
|
-
*
|
|
228
|
-
* @param inputs - the plan's already-priced figures; see {@link RouteScoreInputs}
|
|
229
|
-
* @returns the plan's score — higher is better, and the units are United
|
|
230
|
-
* States dollars throughout; `Number.NEGATIVE_INFINITY` for an unpriced plan
|
|
231
|
-
*/
|
|
232
|
-
// ---------------------------------------------------------------------------
|
|
233
|
-
// compareRoutePlansByScoreAdjustedDeliveredAmount — ranking that charges for
|
|
234
|
-
// an extra signature, without needing a United States dollar price
|
|
235
|
-
// ---------------------------------------------------------------------------
|
|
236
|
-
/** `SIGNATURE_PENALTY_PPM`'s denominator: parts per million, as a bigint. */
|
|
237
23
|
const PPM_DENOMINATOR = 1000000n;
|
|
238
|
-
/**
|
|
239
|
-
* `plan`'s last-hop `deliveredAmount`, discounted by {@link SIGNATURE_PENALTY_PPM}
|
|
240
|
-
* for every signature beyond the first — proportionally, in the delivered
|
|
241
|
-
* token's own base units, entirely in bigint arithmetic.
|
|
242
|
-
*
|
|
243
|
-
* WHY ONLY THE PROPORTIONAL SHARE, NEVER {@link SIGNATURE_PENALTY_FLOOR_USD}.
|
|
244
|
-
* The floor is denominated in United States dollars; converting a base-unit
|
|
245
|
-
* `deliveredAmount` into dollars needs a live price, which a `RoutePlan`
|
|
246
|
-
* (`graph.ts`) does not carry — it is a bigint amount in one token's own
|
|
247
|
-
* units, nothing more. `scoreRoutePlan` still applies the full formula,
|
|
248
|
-
* floor included, once a caller (`plan-route-data.ts`) has priced a plan into
|
|
249
|
-
* `RouteScoreInputs`. This function is the version usable at the STRUCTURAL
|
|
250
|
-
* ranking sites — `enumerate.ts`'s cut and `waves.ts`'s between-wave
|
|
251
|
-
* re-ranking — which only ever see the plan's own hops, not a price. See
|
|
252
|
-
* {@link compareRoutePlansByScoreAdjustedDeliveredAmount}'s own doc for why a
|
|
253
|
-
* proportional-only penalty is still enough to settle the case it exists for.
|
|
254
|
-
*
|
|
255
|
-
* @param plan - the plan to discount
|
|
256
|
-
* @returns the discounted delivered amount, floored at zero
|
|
257
|
-
*/
|
|
258
24
|
const signaturePenaltyAdjustedDeliveredAmount = (plan) => {
|
|
259
25
|
const deliveredAmount = plan.hops[plan.hops.length - 1]?.outcome.deliveredAmount ?? 0n;
|
|
260
26
|
const extraActionCount = Math.max(0, plan.signatures.length - 1);
|
|
@@ -262,45 +28,6 @@ const signaturePenaltyAdjustedDeliveredAmount = (plan) => {
|
|
|
262
28
|
const retainedPpm = penaltyPpm >= PPM_DENOMINATOR ? 0n : PPM_DENOMINATOR - penaltyPpm;
|
|
263
29
|
return (deliveredAmount * retainedPpm) / PPM_DENOMINATOR;
|
|
264
30
|
};
|
|
265
|
-
/**
|
|
266
|
-
* Orders two RANKABLE plans (both pass `graph.ts`'s `planIsRankable`) by
|
|
267
|
-
* their {@link signaturePenaltyAdjustedDeliveredAmount} rather than their raw
|
|
268
|
-
* `deliveredAmount` — the STRUCTURAL counterpart to `graph.ts`'s
|
|
269
|
-
* {@link @gibs/bridge-sdk/routing/search/graph!compareRoutePlansByDeliveredAmount},
|
|
270
|
-
* reusing every one of that function's rules (rankable beats unrankable,
|
|
271
|
-
* `compareUnrankablePlans`'s tiebreak among two unrankable plans) and adding
|
|
272
|
-
* exactly one more: within two RANKABLE plans, a plan needing more
|
|
273
|
-
* signatures than another must clear {@link SIGNATURE_PENALTY_PPM} of
|
|
274
|
-
* "extra" delivered value per extra signature before it is allowed to win,
|
|
275
|
-
* not merely `> 0`.
|
|
276
|
-
*
|
|
277
|
-
* THE DEFECT THIS CLOSES. `SIGNATURE_PENALTY_PPM` and `GAS_TOPUP_PENALTY_PPM`
|
|
278
|
-
* existed in this module as constants `scoreRoutePlan` charges — but nothing
|
|
279
|
-
* in the actual ranking path called `scoreRoutePlan` at all:
|
|
280
|
-
* `enumerate.ts`'s cut, `waves.ts`'s between-wave re-ranking, and
|
|
281
|
-
* `useRouteSearch.ts`'s final sort all imported `graph.ts`'s plain
|
|
282
|
-
* delivered-amount comparator directly, so a route needing a second
|
|
283
|
-
* signature for a fractional gain (measured: 0.006% more, needing one more
|
|
284
|
-
* wallet prompt) always won outright. Sorting on
|
|
285
|
-
* {@link signaturePenaltyAdjustedDeliveredAmount} instead is what makes that
|
|
286
|
-
* lose to the one-signature alternative: the extra signature's proportional
|
|
287
|
-
* cost (0.25% per {@link SIGNATURE_PENALTY_PPM}) outweighs a 0.006% edge by
|
|
288
|
-
* roughly forty times.
|
|
289
|
-
*
|
|
290
|
-
* WHY NOT `GAS_TOPUP_PENALTY_PPM` HERE TOO. A gasless-intermediate-chain
|
|
291
|
-
* charge needs to know whether the connected account holds gas on a chain in
|
|
292
|
-
* the middle of the plan — a live wallet balance read `RoutePlan` has no way
|
|
293
|
-
* to name. Applying it here would require guessing, which this comparator
|
|
294
|
-
* refuses to do; `GAS_TOPUP_PENALTY_PPM` is still applied wherever a caller
|
|
295
|
-
* has that balance and reaches for `scoreRoutePlan` directly (`plan-route-data.ts`
|
|
296
|
-
* onward). Left as an OWNER DECISION whether a structural ranking site should
|
|
297
|
-
* ever get gas-balance context of its own.
|
|
298
|
-
*
|
|
299
|
-
* @param a - one plan being compared
|
|
300
|
-
* @param b - the other
|
|
301
|
-
* @returns negative when `a` ranks ahead of `b`, positive when `b` ranks
|
|
302
|
-
* ahead of `a`, zero when they tie
|
|
303
|
-
*/
|
|
304
31
|
const compareRoutePlansByScoreAdjustedDeliveredAmount = (a, b) => {
|
|
305
32
|
const rankableA = (0, graph_js_1.planIsRankable)(a.hops);
|
|
306
33
|
const rankableB = (0, graph_js_1.planIsRankable)(b.hops);
|
|
@@ -331,34 +58,8 @@ const scoreRoutePlan = (inputs) => {
|
|
|
331
58
|
totalGasTopUpPenaltyUsd);
|
|
332
59
|
};
|
|
333
60
|
exports.scoreRoutePlan = scoreRoutePlan;
|
|
334
|
-
/**
|
|
335
|
-
* A PLACEHOLDER {@link GasCostFor} that charges nothing — preserves the
|
|
336
|
-
* behaviour of ranking on raw delivered amount for a caller that has not yet
|
|
337
|
-
* wired a real gas-price and native-price source. NOT A PRODUCTION DEFAULT:
|
|
338
|
-
* unlike {@link WAIT_PENALTY_PPM_PER_MINUTE}'s two logged, live crossings, no
|
|
339
|
-
* per-chain gas figure here would be a measurement — it would be a guess
|
|
340
|
-
* dressed up as one, exactly what Rule 13 of this codebase's own working
|
|
341
|
-
* principles warns against. A host should always supply its own
|
|
342
|
-
* {@link GasCostFor} once it has gas-price and native-price feeds to build
|
|
343
|
-
* one from; this export exists only so `waves.ts`'s own default comparator
|
|
344
|
-
* has something total to call when nobody has.
|
|
345
|
-
*/
|
|
346
61
|
const zeroGasCostFor = () => ({ gasAmount: 0n, refuelAmount: 0n });
|
|
347
62
|
exports.zeroGasCostFor = zeroGasCostFor;
|
|
348
|
-
/**
|
|
349
|
-
* Whether the section at `sectionIndex` starts with native coin already in
|
|
350
|
-
* the reader's hand: the hop that ends the PREVIOUS section delivers the
|
|
351
|
-
* chain's native coin, so the reader arrives holding gas for this section's
|
|
352
|
-
* own signature and needs no top-up there, whatever their balance was.
|
|
353
|
-
*
|
|
354
|
-
* Always false for the first section — nothing lands before it, so its gas
|
|
355
|
-
* can only come from the reader's own balance.
|
|
356
|
-
*
|
|
357
|
-
* @param plan - the plan the section belongs to
|
|
358
|
-
* @param sectionIndex - 0-based index into `plan.signatures`
|
|
359
|
-
* @returns true when the previous section lands native coin on this
|
|
360
|
-
* section's chain
|
|
361
|
-
*/
|
|
362
63
|
const sectionIsFundedByLanding = (plan, sectionIndex) => {
|
|
363
64
|
if (sectionIndex < 1)
|
|
364
65
|
return false;
|
|
@@ -369,20 +70,6 @@ const sectionIsFundedByLanding = (plan, sectionIndex) => {
|
|
|
369
70
|
return (0, ecosystems_js_1.isNativeAsset)(landingHop.edge.to.address, landingHop.edge.to.ecosystem);
|
|
370
71
|
};
|
|
371
72
|
exports.sectionIsFundedByLanding = sectionIsFundedByLanding;
|
|
372
|
-
/**
|
|
373
|
-
* `plan`'s last-hop `deliveredAmount`, minus the REAL cost of every
|
|
374
|
-
* signature it needs — `gasCostFor` charged ONCE per signature group
|
|
375
|
-
* (`plan.signatures`, built by `groupHopsBySignature`), on the chain and
|
|
376
|
-
* carrier of that group's FIRST hop, which is the hop the reader actually
|
|
377
|
-
* signs (or deposits by hand) for that group. A group's refuel cost is
|
|
378
|
-
* dropped when the previous group lands native coin
|
|
379
|
-
* ({@link sectionIsFundedByLanding}). Floored at zero: a plan whose
|
|
380
|
-
* gas costs exceed its own delivered amount is worth nothing, never negative.
|
|
381
|
-
*
|
|
382
|
-
* @param plan - the plan to charge
|
|
383
|
-
* @param gasCostFor - supplies each signature's real cost; see {@link GasCostFor}
|
|
384
|
-
* @returns the gas-adjusted delivered amount, in the plan's destination token's base units
|
|
385
|
-
*/
|
|
386
73
|
const gasAdjustedDeliveredAmount = (plan, gasCostFor) => {
|
|
387
74
|
const deliveredAmount = plan.hops[plan.hops.length - 1]?.outcome.deliveredAmount ?? 0n;
|
|
388
75
|
const totalGasCost = plan.signatures.reduce((total, group, sectionIndex) => {
|
|
@@ -398,32 +85,6 @@ const gasAdjustedDeliveredAmount = (plan, gasCostFor) => {
|
|
|
398
85
|
return netAmount < 0n ? 0n : netAmount;
|
|
399
86
|
};
|
|
400
87
|
exports.gasAdjustedDeliveredAmount = gasAdjustedDeliveredAmount;
|
|
401
|
-
/**
|
|
402
|
-
* Orders two plans by {@link gasAdjustedDeliveredAmount} rather than raw
|
|
403
|
-
* `deliveredAmount` or {@link signaturePenaltyAdjustedDeliveredAmount}'s flat
|
|
404
|
-
* ppm guess — the structural ranking `waves.ts` uses once Round A/B have real
|
|
405
|
-
* gas data to charge, replacing {@link SIGNATURE_PENALTY_PPM}/
|
|
406
|
-
* {@link GAS_TOPUP_PENALTY_PPM} at that one site per the owner's own
|
|
407
|
-
* instruction (see both constants' updated docs). A CURRIED FACTORY, not a
|
|
408
|
-
* plain comparator, because the real cost this needs — {@link GasCostFor} —
|
|
409
|
-
* is caller-supplied and cannot be a module-level default the way
|
|
410
|
-
* {@link compareRoutePlansByScoreAdjustedDeliveredAmount} is; call it once
|
|
411
|
-
* per search with the caller's own `gasCostFor`, then pass the returned
|
|
412
|
-
* comparator wherever a plan-to-plan comparison is needed.
|
|
413
|
-
*
|
|
414
|
-
* KEEPS THE SAME RANKABLE-BEFORE-UNRANKABLE RULE `compareRoutePlansByScoreAdjustedDeliveredAmount`
|
|
415
|
-
* ALREADY APPLIES, unchanged, including its `compareRoutePlansByDeliveredAmount`
|
|
416
|
-
* tiebreak among two unrankable plans — only the tiebreak among two RANKABLE
|
|
417
|
-
* plans changes, from a proportional signature-count discount to the route's
|
|
418
|
-
* own real charges.
|
|
419
|
-
*
|
|
420
|
-
* @param gasCostFor - supplies each signature's real cost; see {@link GasCostFor}
|
|
421
|
-
* TIE-BREAK: when the gas-adjusted amounts are equal, the plan with fewer
|
|
422
|
-
* signatures ranks first.
|
|
423
|
-
*
|
|
424
|
-
* @returns a comparator: negative when `a` ranks ahead of `b`, positive when
|
|
425
|
-
* `b` ranks ahead of `a`, zero when they tie
|
|
426
|
-
*/
|
|
427
88
|
const compareRoutePlansByGasAdjustedDeliveredAmount = (gasCostFor) => (a, b) => {
|
|
428
89
|
const rankableA = (0, graph_js_1.planIsRankable)(a.hops);
|
|
429
90
|
const rankableB = (0, graph_js_1.planIsRankable)(b.hops);
|
|
@@ -435,11 +96,6 @@ const compareRoutePlansByGasAdjustedDeliveredAmount = (gasCostFor) => (a, b) =>
|
|
|
435
96
|
const adjustedB = (0, exports.gasAdjustedDeliveredAmount)(b, gasCostFor);
|
|
436
97
|
if (adjustedA !== adjustedB)
|
|
437
98
|
return adjustedA > adjustedB ? -1 : 1;
|
|
438
|
-
// EQUAL FIGURES: FEWER SIGNATURES RANKS FIRST. Two plans that deliver the
|
|
439
|
-
// same amount cost the reader different effort — each signature is one more
|
|
440
|
-
// wallet prompt. Without this the stable sort kept the depth-first walk
|
|
441
|
-
// order, so a three-signature plan could be selected over a two-signature
|
|
442
|
-
// plan showing the same figure.
|
|
443
99
|
return a.signatures.length - b.signatures.length;
|
|
444
100
|
};
|
|
445
101
|
exports.compareRoutePlansByGasAdjustedDeliveredAmount = compareRoutePlansByGasAdjustedDeliveredAmount;
|
|
@@ -5,50 +5,7 @@ const viem_1 = require("viem");
|
|
|
5
5
|
const settings_js_1 = require("../settings.js");
|
|
6
6
|
const config_js_1 = require("../config.js");
|
|
7
7
|
const pulsex_js_1 = require("./carriers/pulsex.js");
|
|
8
|
-
/**
|
|
9
|
-
* The minimal WETH9-style wrap/unwrap interface: `deposit()` mints the
|
|
10
|
-
* wrapped token for the native coin sent with the call, `withdraw(uint256)`
|
|
11
|
-
* burns wrapped balance and returns native coin. Every wrapped-native
|
|
12
|
-
* contract this application bridges to exposes exactly this pair — see
|
|
13
|
-
* `carriers/wrap.ts`, whose own doc records the selectors as confirmed
|
|
14
|
-
* present on WPLS by bytecode inspection (2026-09-24). Kept local rather than
|
|
15
|
-
* added to `@gibs/abis`: the interface is two standard, unchanging selectors
|
|
16
|
-
* rather than a contract-specific ABI.
|
|
17
|
-
*/
|
|
18
8
|
const wrapAbi = (0, viem_1.parseAbi)(['function deposit() payable', 'function withdraw(uint256 amount)']);
|
|
19
|
-
/**
|
|
20
|
-
* Builds a same-chain PulseX swap transaction for one planned route-search
|
|
21
|
-
* hop. The interface's section signing (`packages/ui` `state/sectionSigning.ts`)
|
|
22
|
-
* and the SDK's execution planner (`execution.ts`) both call it, so there is
|
|
23
|
-
* exactly one place that turns "swap this hop" into calldata.
|
|
24
|
-
*
|
|
25
|
-
* SIGNS THE PATH THE HOP WAS PRICED ON. The PulseX carrier picks the best of
|
|
26
|
-
* many paths through its hub tokens and records the winner on the hop's
|
|
27
|
-
* outcome; `pulseXSwapPathForHop` (`carriers/pulsex.ts`) reads it back
|
|
28
|
-
* and checks it fits the hop's edge. This never rebuilds a path: a rebuilt
|
|
29
|
-
* path is a quote on one route and a signature on another. A hop that
|
|
30
|
-
* records no path is refused. REUSES `pulseXSwapTransactionInputs` (`settings.ts`)
|
|
31
|
-
* for the encoding, never re-implements it: that function already carries the
|
|
32
|
-
* `swapRefusal` guard (refuses to build a call for a leg the screen is not
|
|
33
|
-
* looking at) and the native-in/native-out/token-token branching.
|
|
34
|
-
*
|
|
35
|
-
* SIGNS ON THE EDGE'S OWN ROUTER. A PulseX edge names the deployment it was
|
|
36
|
-
* quoted on (`venueForEdge`: V1 or V2, each with its own pools). The
|
|
37
|
-
* caller's `routerAddress` must be that same router — it is also the router
|
|
38
|
-
* the caller approved to spend the input token — or nothing is built. A V2
|
|
39
|
-
* quote signed on V1 would trade against a different pool than the one the
|
|
40
|
-
* reader was shown.
|
|
41
|
-
*
|
|
42
|
-
* @param options - the hop to swap, the amount and slippage-adjusted
|
|
43
|
-
* minimum, who receives the output, the signing deadline, what the caller
|
|
44
|
-
* believes this signature does (`signedLeg`), the chain it executes on, the
|
|
45
|
-
* resolved router address, and the swap venues the router must belong to
|
|
46
|
-
* (the defaults when omitted)
|
|
47
|
-
* @returns the swap transaction inputs, or null when the hop records no
|
|
48
|
-
* PulseX swap path, names no known router, `routerAddress` is not the
|
|
49
|
-
* edge's own router, the leg on screen disagrees, or any of
|
|
50
|
-
* `pulseXSwapTransactionInputs`'s own preconditions are unmet
|
|
51
|
-
*/
|
|
52
9
|
const buildPulseXSwapTransaction = (options) => {
|
|
53
10
|
const { hop, amountIn, minAmountOut, recipient, deadline, signedLeg, chainId, routerAddress } = options;
|
|
54
11
|
const { edge } = hop;
|
|
@@ -74,25 +31,6 @@ const buildPulseXSwapTransaction = (options) => {
|
|
|
74
31
|
});
|
|
75
32
|
};
|
|
76
33
|
exports.buildPulseXSwapTransaction = buildPulseXSwapTransaction;
|
|
77
|
-
/**
|
|
78
|
-
* Builds a native-coin wrap/unwrap transaction for one route-search graph
|
|
79
|
-
* edge — PLS<->WPLS on PulseChain, ETH<->WETH on Ethereum, or the same pair
|
|
80
|
-
* on any other chain `config.ts`'s `nativeAssetOut` names one for.
|
|
81
|
-
*
|
|
82
|
-
* A WRAP IS NOT A SWAP CALL. There is no PulseX pool for native-versus-wrapped
|
|
83
|
-
* — see `routing/carriers/wrap.ts`'s own doc — so this never touches the
|
|
84
|
-
* PulseX router: wrapping sends `amountIn` native coin to the wrapped token's
|
|
85
|
-
* own `deposit()`; unwrapping calls `withdraw(amountIn)` on it with zero
|
|
86
|
-
* value. The `edge` names which direction: its `from`/`to` addresses are
|
|
87
|
-
* checked against the zero-address sentinel, never assumed from a caller
|
|
88
|
-
* flag, so a swapped/malformed edge is refused rather than guessed at.
|
|
89
|
-
*
|
|
90
|
-
* @param options - the edge to wrap or unwrap, and the amount in the SOURCE
|
|
91
|
-
* token's base units (native units wrapping, wrapped units unwrapping —
|
|
92
|
-
* native and wrapped share decimals on every chain this carrier covers)
|
|
93
|
-
* @returns the wrap/unwrap transaction inputs, or null when `amountIn` is not
|
|
94
|
-
* positive or the edge is not exactly one native/wrapped pair
|
|
95
|
-
*/
|
|
96
34
|
const buildWrapTransaction = (options) => {
|
|
97
35
|
const { edge, amountIn } = options;
|
|
98
36
|
if (amountIn <= 0n) {
|
|
@@ -100,8 +38,6 @@ const buildWrapTransaction = (options) => {
|
|
|
100
38
|
}
|
|
101
39
|
const fromIsNative = edge.from.address.toLowerCase() === viem_1.zeroAddress;
|
|
102
40
|
const toIsNative = edge.to.address.toLowerCase() === viem_1.zeroAddress;
|
|
103
|
-
// Exactly one side must be the native sentinel — a token/token pair, or a
|
|
104
|
-
// native/native no-op, is not a wrap edge at all.
|
|
105
41
|
if (fromIsNative === toIsNative) {
|
|
106
42
|
return null;
|
|
107
43
|
}
|
|
@@ -119,15 +55,5 @@ const buildWrapTransaction = (options) => {
|
|
|
119
55
|
};
|
|
120
56
|
};
|
|
121
57
|
exports.buildWrapTransaction = buildWrapTransaction;
|
|
122
|
-
/**
|
|
123
|
-
* The slippage floor a swap signs: the quoted output less the slippage
|
|
124
|
-
* allowance, rounded down. The interface's engine signing and the SDK's
|
|
125
|
-
* execution planner both read it, so the two never sign different floors for
|
|
126
|
-
* the same quote.
|
|
127
|
-
*
|
|
128
|
-
* @param options.quotedAmount - the hop's quoted output, in the output token's base units
|
|
129
|
-
* @param options.slippageBasisPoints - the allowance, in basis points (100 is 1%)
|
|
130
|
-
* @returns the minimum output the swap accepts
|
|
131
|
-
*/
|
|
132
58
|
const swapMinimumOut = ({ quotedAmount, slippageBasisPoints, }) => (quotedAmount * (10000n - slippageBasisPoints)) / 10000n;
|
|
133
59
|
exports.swapMinimumOut = swapMinimumOut;
|
|
@@ -2,18 +2,6 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.usdValueOfAmount = void 0;
|
|
4
4
|
const viem_1 = require("viem");
|
|
5
|
-
/**
|
|
6
|
-
* The United States dollar value of a base-unit token amount at a given price, as
|
|
7
|
-
* a NUMBER — the numeric core of the user interface's `formatFiatValue` without the
|
|
8
|
-
* currency string. Returns null when the token is unpriced (`price` is null) or the
|
|
9
|
-
* computed value is not finite, mirroring the "return null for invalid state"
|
|
10
|
-
* convention so callers can fall back.
|
|
11
|
-
*
|
|
12
|
-
* @param params.balance - the amount in base units
|
|
13
|
-
* @param params.decimals - the token's decimals
|
|
14
|
-
* @param params.price - the token's United States dollar price, or null when unpriced
|
|
15
|
-
* @returns the dollar value as a number, or null
|
|
16
|
-
*/
|
|
17
5
|
const usdValueOfAmount = (params) => {
|
|
18
6
|
const { balance, decimals, price } = params;
|
|
19
7
|
if (price === null)
|