@gibs/bridge-sdk 1.12.0 → 1.13.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/LICENSE +15 -0
- package/README.md +234 -432
- package/dist/abis.d.ts +1 -0
- package/dist/bridge-limits.d.ts +103 -0
- package/dist/bridge-limits.js +84 -0
- package/dist/chain-info.d.ts +169 -0
- package/dist/chain-info.js +410 -0
- package/dist/chain-names.d.ts +160 -0
- package/dist/chain-names.js +200 -0
- package/dist/chains.d.ts +65 -0
- package/dist/chains.js +284 -0
- package/dist/config.d.ts +216 -0
- package/dist/config.js +493 -0
- package/dist/consolidated-quote.d.ts +554 -0
- package/dist/consolidated-quote.js +773 -0
- package/dist/destination-calldata.d.ts +118 -0
- package/dist/destination-calldata.js +152 -0
- package/dist/ecosystems.d.ts +217 -0
- package/dist/ecosystems.js +288 -0
- package/dist/fee-type.d.ts +10 -0
- package/dist/fee-type.js +9 -0
- package/dist/hyperliquid-execution.d.ts +152 -0
- package/dist/hyperliquid-execution.js +168 -0
- package/dist/image-links.d.ts +117 -0
- package/dist/image-links.js +142 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.js +20 -0
- package/dist/lifi-execution-guard.d.ts +199 -0
- package/dist/lifi-execution-guard.js +400 -0
- package/dist/near-intents-conformance.d.ts +85 -0
- package/dist/near-intents-conformance.js +329 -0
- package/dist/near-intents-route.d.ts +47 -0
- package/dist/near-intents-route.js +265 -0
- package/dist/near-intents.d.ts +524 -0
- package/dist/near-intents.js +1055 -0
- package/dist/origin-deposit.d.ts +326 -0
- package/dist/origin-deposit.js +68 -0
- package/dist/pre-quote.d.ts +198 -0
- package/dist/pre-quote.js +175 -0
- package/dist/prices.d.ts +107 -0
- package/dist/prices.js +162 -0
- package/dist/providers.d.ts +221 -0
- package/dist/providers.js +157 -0
- package/dist/quote-fees.d.ts +102 -0
- package/dist/quote-fees.js +195 -0
- package/dist/referral.d.ts +77 -0
- package/dist/referral.js +72 -0
- package/dist/relay-currencies.d.ts +47 -0
- package/dist/relay-currencies.js +89 -0
- package/dist/relay-quote.d.ts +301 -0
- package/dist/relay-quote.js +983 -0
- package/dist/route-steps.d.ts +138 -0
- package/dist/route-steps.js +305 -0
- package/dist/routing/amounts.d.ts +80 -0
- package/dist/routing/amounts.js +120 -0
- package/dist/routing/candidate-route.d.ts +43 -0
- package/dist/routing/candidate-route.js +45 -0
- package/dist/routing/candidate.d.ts +237 -0
- package/dist/routing/candidate.js +96 -0
- package/dist/routing/carriers/ask-answer.d.ts +58 -0
- package/dist/routing/carriers/ask-answer.js +1 -0
- package/dist/routing/carriers/omnibridge.d.ts +137 -0
- package/dist/routing/carriers/omnibridge.js +419 -0
- package/dist/routing/carriers/pulsex.d.ts +111 -0
- package/dist/routing/carriers/pulsex.js +404 -0
- package/dist/routing/carriers/wrap.d.ts +25 -0
- package/dist/routing/carriers/wrap.js +115 -0
- package/dist/routing/composed-route-quality.d.ts +103 -0
- package/dist/routing/composed-route-quality.js +108 -0
- package/dist/routing/entry-chain-anchor.d.ts +88 -0
- package/dist/routing/entry-chain-anchor.js +55 -0
- package/dist/routing/format.d.ts +31 -0
- package/dist/routing/format.js +58 -0
- package/dist/routing/index.d.ts +34 -0
- package/dist/routing/index.js +42 -0
- package/dist/routing/producers.d.ts +770 -0
- package/dist/routing/producers.js +1564 -0
- package/dist/routing/providers.d.ts +26 -0
- package/dist/routing/providers.js +38 -0
- package/dist/routing/route-data.d.ts +355 -0
- package/dist/routing/route-data.js +1 -0
- package/dist/routing/search/compose.d.ts +168 -0
- package/dist/routing/search/compose.js +98 -0
- package/dist/routing/search/graph.d.ts +639 -0
- package/dist/routing/search/graph.js +445 -0
- package/dist/routing/search/plan-route-data.d.ts +244 -0
- package/dist/routing/search/plan-route-data.js +767 -0
- package/dist/routing/search/score.d.ts +324 -0
- package/dist/routing/search/score.js +400 -0
- package/dist/routing/usd-value.d.ts +17 -0
- package/dist/routing/usd-value.js +25 -0
- package/dist/settings.d.ts +692 -0
- package/dist/settings.js +909 -0
- package/dist/ton-execution.d.ts +117 -0
- package/dist/ton-execution.js +247 -0
- package/dist/tron-execution.d.ts +146 -0
- package/dist/tron-execution.js +239 -0
- package/dist/types.d.ts +51 -0
- package/dist/types.js +1 -0
- package/package.json +203 -23
- package/src/chain-info.test.ts +0 -968
- package/src/chain-info.ts +0 -498
- package/src/chains.test.ts +0 -123
- package/src/chains.ts +0 -88
- package/src/config.test.ts +0 -679
- package/src/config.ts +0 -500
- package/src/fee-type.test.ts +0 -45
- package/src/fee-type.ts +0 -14
- package/src/image-links.test.ts +0 -160
- package/src/image-links.ts +0 -65
- package/src/index.ts +0 -8
- package/src/settings.test.ts +0 -2754
- package/src/settings.ts +0 -875
- package/src/types.ts +0 -48
- package/tsconfig.json +0 -17
- package/vitest.config.ts +0 -13
- /package/{src/abis.ts → dist/abis.js} +0 -0
|
@@ -0,0 +1,770 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure route-producer helpers and constants shared by every route builder.
|
|
3
|
+
* Lives in the software development kit so the builders can relocate here in
|
|
4
|
+
* subsequent tasks without pulling user-interface dependencies into the kit.
|
|
5
|
+
*
|
|
6
|
+
* All helpers are framework-agnostic: no React, no Svelte, no display formatters.
|
|
7
|
+
*/
|
|
8
|
+
import { type Provider } from '../config.js';
|
|
9
|
+
import type { DeliveryFee } from '../settings.js';
|
|
10
|
+
import type { RouteCandidate } from './candidate.js';
|
|
11
|
+
import type { Token, BridgeKey } from '../types.js';
|
|
12
|
+
import type { RouteData, RouteSectionData } from './route-data.js';
|
|
13
|
+
import { type Hex } from 'viem';
|
|
14
|
+
/**
|
|
15
|
+
* Divisor for the MARGINAL reference swap quote. A swap's price impact cannot be
|
|
16
|
+
* read from the trade quote alone — `getAmountsOut(fullInput)` already folds the
|
|
17
|
+
* impact into its output, and the PulseChain USD prices are themselves PulseX
|
|
18
|
+
* pool quotes, so differencing them cancels the impact out (it vanishes to
|
|
19
|
+
* $0.00). Instead the estimate quotes a TINY reference input — `1/this` of the
|
|
20
|
+
* trade — whose own impact is negligible, giving the near-spot marginal rate. The
|
|
21
|
+
* gap between that marginal rate and the full trade's realized rate IS the price
|
|
22
|
+
* impact (the swap fee rides in BOTH quotes, so it cancels and the gap is impact
|
|
23
|
+
* alone). 1/10000 of the trade is small enough to be effectively marginal yet
|
|
24
|
+
* large enough that its output does not round away.
|
|
25
|
+
*/
|
|
26
|
+
export declare const PULSEX_MARGINAL_REFERENCE_DIVISOR = 10000n;
|
|
27
|
+
/**
|
|
28
|
+
* The approximate wall-clock wait for an omnibridge crossing to settle before a
|
|
29
|
+
* DEFERRED swap leg can be signed — the same ~20 minutes whether the swap happens
|
|
30
|
+
* on the entry chain (outbound PulseChain → Ethereum/Binance Smart Chain) or on
|
|
31
|
+
* PulseChain (conversion route: bridge an anchor in, then swap on PulseX).
|
|
32
|
+
* Surfaced compactly as `~20 min` in the deferred section head, mirroring how
|
|
33
|
+
* every other section shows its estimate, rather than spelled out inside the
|
|
34
|
+
* deferred note.
|
|
35
|
+
*/
|
|
36
|
+
export declare const BRIDGE_SETTLEMENT_ETA_MINUTES = 20;
|
|
37
|
+
/** Decimal chain id for PulseChain — the shared destination of every inbound route. */
|
|
38
|
+
export declare const pulsechainChainId: number;
|
|
39
|
+
/**
|
|
40
|
+
* The display name for an omnibridge crossing, fully spelled out. Narrowed to
|
|
41
|
+
* exactly {@link Provider} — the two real crossings — rather than any string,
|
|
42
|
+
* so passing an aggregator's `ProviderId` (or anything else) is a COMPILE
|
|
43
|
+
* ERROR here, not a silently wrong name.
|
|
44
|
+
*
|
|
45
|
+
* PREFER THIS OVER {@link providerDisplayName} wherever the caller already
|
|
46
|
+
* holds a genuine `Provider`. `providerDisplayName` exists only because some
|
|
47
|
+
* callers (`RouteCandidate.omnibridgeProvider`, `RouteData.headlineProviderKey`)
|
|
48
|
+
* are typed `string` at their own source and cannot be narrowed from here.
|
|
49
|
+
*
|
|
50
|
+
* @param provider - a real omnibridge provider
|
|
51
|
+
* @returns the spelled-out provider name
|
|
52
|
+
*/
|
|
53
|
+
export declare const omnibridgeProviderDisplayName: (provider: Provider) => string;
|
|
54
|
+
/**
|
|
55
|
+
* Adds two nullable United States dollar NUMBERS. A null operand contributes
|
|
56
|
+
* nothing; two nulls yield null so an all-unpriced route keeps a null cost rather
|
|
57
|
+
* than a misleading 0.
|
|
58
|
+
*
|
|
59
|
+
* This sums the RAW values and leaves the single cent-rounding to the display
|
|
60
|
+
* adapter (round(a + b)). It deliberately differs from the pre-split
|
|
61
|
+
* `sumFormattedUsd`, which summed two already-cent-rounded strings
|
|
62
|
+
* (round(a) + round(b)); the two can diverge by a cent when both operands carry
|
|
63
|
+
* sub-cent fractions. Rounding the total once is the more accurate result and
|
|
64
|
+
* keeps this helper free of any display formatter, so the raw producers stay
|
|
65
|
+
* relocatable. See the "sums the raw total once" test for the locked behavior.
|
|
66
|
+
*
|
|
67
|
+
* @param first - the first dollar value, or null/undefined when absent
|
|
68
|
+
* @param second - the second dollar value, or null/undefined when absent
|
|
69
|
+
* @returns the sum, or null when both operands are absent
|
|
70
|
+
*/
|
|
71
|
+
export declare const addUsdValues: (first: number | null | undefined, second: number | null | undefined) => number | null;
|
|
72
|
+
/**
|
|
73
|
+
* Subtracts a cost from a dollar value on the SAME basis — the operation every
|
|
74
|
+
* producer uses to derive what a leg delivers from what entered it.
|
|
75
|
+
*
|
|
76
|
+
* Unlike {@link addUsdValues} this is deliberately NOT symmetric about null: an
|
|
77
|
+
* unknown starting value cannot be reduced, so it stays unknown, while an unknown
|
|
78
|
+
* cost is treated as no cost. That asymmetry is what keeps a route with one
|
|
79
|
+
* unpriced leg from reporting a delivered value it never established.
|
|
80
|
+
*
|
|
81
|
+
* @param value - the dollar value entering the leg, or null/undefined when unknown
|
|
82
|
+
* @param cost - the leg's dollar cost, or null/undefined when unpriced
|
|
83
|
+
* @returns the value less the cost, or null when the starting value is unknown
|
|
84
|
+
*/
|
|
85
|
+
export declare const subtractUsdValues: (value: number | null | undefined, cost: number | null | undefined) => number | null;
|
|
86
|
+
/**
|
|
87
|
+
* The display name for an omnibridge crossing, accepting a raw `string` rather
|
|
88
|
+
* than {@link Provider}.
|
|
89
|
+
*
|
|
90
|
+
* PREFER {@link omnibridgeProviderDisplayName} INSTEAD wherever the caller
|
|
91
|
+
* already holds a genuine `Provider` — that one is a compile error for
|
|
92
|
+
* anything else. This wide version exists only for callers whose OWN field is
|
|
93
|
+
* typed `string` at its source and so cannot be narrowed here:
|
|
94
|
+
* `RouteCandidate.omnibridgeProvider` and `RouteData.headlineProviderKey`
|
|
95
|
+
* (`routing/candidate.ts`, `routing/route-data.ts`).
|
|
96
|
+
*
|
|
97
|
+
* KEPT DELIBERATELY NON-THROWING, UNLIKE {@link providerById}. The obvious
|
|
98
|
+
* next step — throw on an unrecognized key, the way `providerById` does for
|
|
99
|
+
* an aggregator — was tried and reverted: `toRouteView.ts`'s headline
|
|
100
|
+
* resolution calls this with `RouteData.headlineProviderKey`, a `string` this
|
|
101
|
+
* repository does not otherwise guarantee is a real provider of ANY kind, and
|
|
102
|
+
* an existing, deliberate test (`toRouteView.test.ts`, "headline falls back
|
|
103
|
+
* to 'Omnibridge' for an unknown headline provider key") requires that a
|
|
104
|
+
* genuinely-unrecognized key render a generic label rather than crash the
|
|
105
|
+
* whole route card. A NEAR Intents leg being mislabeled "Omnibridge" was a
|
|
106
|
+
* real defect (see `near-intents-route.ts`), fixed there by calling the
|
|
107
|
+
* RIGHT function (`providerById(id).label`) instead of this one — not by
|
|
108
|
+
* making this one less forgiving of input nobody validates before it arrives.
|
|
109
|
+
*
|
|
110
|
+
* `'PulseX'` IS RECOGNIZED HERE TOO, unlike an aggregator `ProviderId`, and for
|
|
111
|
+
* a different reason than the omnibridge case: it needs no registry lookup —
|
|
112
|
+
* there is exactly one PulseX, the label IS the key — so there is nothing an
|
|
113
|
+
* aggregator-style `providerById(id).label` call would add. A same-chain
|
|
114
|
+
* PulseX swap route (`RouteData.kind === 'swap'`) has NO omnibridge leg at
|
|
115
|
+
* all, so falling back to "Omnibridge" for it would name a bridge that never
|
|
116
|
+
* ran.
|
|
117
|
+
*
|
|
118
|
+
* @param provider - the raw provider key (e.g. `'pulsechain'`, `'PulseX'`)
|
|
119
|
+
* @returns the spelled-out provider name, or "Omnibridge" when unregistered
|
|
120
|
+
*/
|
|
121
|
+
export declare const providerDisplayName: (provider: string) => string;
|
|
122
|
+
/**
|
|
123
|
+
* The fully spelled-out display name of an omnibridge entry chain, or null when
|
|
124
|
+
* the chain id is null or is not one of the two entry points (Ethereum, Binance
|
|
125
|
+
* Smart Chain). A null result makes route builders return null, so an
|
|
126
|
+
* unrecognised destination leaves the strip empty rather than naming a chain it
|
|
127
|
+
* cannot bridge to.
|
|
128
|
+
*
|
|
129
|
+
* @param entryChainId - the decimal entry chain id, or null for direct routes
|
|
130
|
+
* @returns the spelled-out chain name, or null
|
|
131
|
+
*/
|
|
132
|
+
export declare const resolveEntryChainName: (entryChainId: number | null) => string | null;
|
|
133
|
+
/**
|
|
134
|
+
* Parses one of the aggregator's own United States dollar figures —
|
|
135
|
+
* `fromAmountUsd` or `toAmountUsd` on a candidate's quote.
|
|
136
|
+
*
|
|
137
|
+
* `Number('')` IS `0`, NOT "UNKNOWN", and both the LI.FI and Relay quote
|
|
138
|
+
* parsers can hand this module a blank amount string. Read with a bare
|
|
139
|
+
* `Number()`, a blank `fromAmountUsd` priced a route's origin leg at zero
|
|
140
|
+
* cost — one measured case showed a route reporting a net gain of +$273 that
|
|
141
|
+
* had in fact cost real money, and led the strip on the strength of it — and
|
|
142
|
+
* a blank `toAmountUsd` would do the same to what a direct route (no
|
|
143
|
+
* omnibridge leg) reports as delivered. A dollar figure only means something
|
|
144
|
+
* when it is a positive, finite number: blank text, non-numeric text, zero,
|
|
145
|
+
* and a negative number are all treated as UNPRICED rather than free.
|
|
146
|
+
*
|
|
147
|
+
* @param raw - the provider's amount string, or null/undefined when absent
|
|
148
|
+
* @returns the parsed value, or null when the field cannot be trusted
|
|
149
|
+
*/
|
|
150
|
+
export declare const usdNumber: (raw: string | null | undefined) => number | null;
|
|
151
|
+
/**
|
|
152
|
+
* What the user pays for a candidate's origin leg, in United States dollars, as
|
|
153
|
+
* the provider itself valued it (`fromAmountUsd`). This is the candidate's SOURCE
|
|
154
|
+
* BASIS: every dollar figure the route reports is derived from it, so the costs
|
|
155
|
+
* shown and the value delivered can never drift onto different price sources.
|
|
156
|
+
*
|
|
157
|
+
* @param candidate - the priced route candidate
|
|
158
|
+
* @returns the amount paid in United States dollars, or null when the provider gave none
|
|
159
|
+
*/
|
|
160
|
+
/**
|
|
161
|
+
* Exported so `search/plan-route-data.ts` can generalize this SAME valuation
|
|
162
|
+
* to a general-search plan's first hop, per the route-search design's
|
|
163
|
+
* `RouteScoreInputs` doc ("import and reuse them; do not write a second
|
|
164
|
+
* valuation") — a candidate-shaped module boundary, not a second formula.
|
|
165
|
+
*/
|
|
166
|
+
export declare const candidatePaidUsd: (candidate: RouteCandidate) => number | null;
|
|
167
|
+
/**
|
|
168
|
+
* What a candidate's delivered tokens are worth, in United States dollars.
|
|
169
|
+
*
|
|
170
|
+
* TWO SOURCES, AND WHICH ONE APPLIES IS DECIDED BY WHETHER A SECOND LEG
|
|
171
|
+
* FOLLOWS — never by which one happens to be present.
|
|
172
|
+
*
|
|
173
|
+
* A route with no omnibridge leg ends where the provider drops the funds, so
|
|
174
|
+
* the provider valued the very tokens the reader receives, in the same answer
|
|
175
|
+
* and on the same feed as `fromAmountUsd`. The difference between the two is
|
|
176
|
+
* then the route's cost and nothing else. This is the case that had no price at
|
|
177
|
+
* all: the destination chain is not one the bridge's own price sources cover,
|
|
178
|
+
* so `destinationUsdPrice` arrived null and every direct route reported no fee.
|
|
179
|
+
*
|
|
180
|
+
* A route that continues through the omnibridge must NOT use it. The provider's
|
|
181
|
+
* delivered side there is the entry chain's tokens, handed to the mediator —
|
|
182
|
+
* not what finally lands on PulseChain, which is what `deliveredAmount` counts.
|
|
183
|
+
* Those two differ by the omnibridge's own fee, so reading the provider's
|
|
184
|
+
* figure would report a crossing as free.
|
|
185
|
+
*
|
|
186
|
+
* Exported because the ranking must value a route on the SAME basis the route
|
|
187
|
+
* states. The ranker used to price the delivered tokens against
|
|
188
|
+
* `destinationUsdPrice` alone, which is null on every direct route, so every
|
|
189
|
+
* direct route was unpriced and the ranker fell back to an order that could not
|
|
190
|
+
* see what each route delivers.
|
|
191
|
+
*
|
|
192
|
+
* @param candidate - the priced route candidate
|
|
193
|
+
* @returns the delivered value in United States dollars, or null when unpriced
|
|
194
|
+
*/
|
|
195
|
+
export declare const candidateDeliveredUsd: (candidate: RouteCandidate) => number | null;
|
|
196
|
+
/**
|
|
197
|
+
* The fee inputs an omnibridge crossing's cost is built from. Shared by the
|
|
198
|
+
* direct and the outbound builders, which cross the same bridge.
|
|
199
|
+
*
|
|
200
|
+
* WHY TWO INPUTS AND NOT ONE. The route used to state its cost from the
|
|
201
|
+
* delivery fee alone. A crossing out of PulseChain to Ethereum pays the
|
|
202
|
+
* bridge 0.3% before delivery takes its 0.05%, so 1,000 WETH in showed a cost
|
|
203
|
+
* of 0.4985 ETH while 3.4985 left the reader's hands: understated about seven
|
|
204
|
+
* times. Over Tokens Express to Binance Smart Chain the bridge takes 2.97%, and
|
|
205
|
+
* the understatement was about sixty times. Each fee now arrives as its own
|
|
206
|
+
* fact, from the settings cascade that already knows it.
|
|
207
|
+
*/
|
|
208
|
+
export type CrossingFeeRoots = {
|
|
209
|
+
/**
|
|
210
|
+
* The bridge's own fee, in base units of the token on the side where its fee
|
|
211
|
+
* manager lives (see {@link bridgeFeeToken}). This is `bridgeCost` from the
|
|
212
|
+
* settings cascade: `amountToBridge * fee / 1 ether`, which is exactly
|
|
213
|
+
* `amountToBridge - amountAfterBridgeFee`. Null while the fee manager's rate
|
|
214
|
+
* is still loading, which makes the route's cost unknown.
|
|
215
|
+
*/
|
|
216
|
+
bridgeFeeAmount: bigint | null;
|
|
217
|
+
/**
|
|
218
|
+
* The bridge fee's rate as a fraction of one ether (3e15 is 0.3%), for the
|
|
219
|
+
* fee's label only. Null or absent leaves the rate out of the label.
|
|
220
|
+
*/
|
|
221
|
+
bridgeFeeRate?: bigint | null;
|
|
222
|
+
/**
|
|
223
|
+
* The Gibs delivery fee, which tells "no delivery" apart from "not priced
|
|
224
|
+
* yet". Build it with `deliveryFee` from the settings module.
|
|
225
|
+
*/
|
|
226
|
+
deliveryFee: DeliveryFee;
|
|
227
|
+
};
|
|
228
|
+
/**
|
|
229
|
+
* Everything a candidate is charged that sits OUTSIDE `fromAmount`, in United
|
|
230
|
+
* States dollars.
|
|
231
|
+
*
|
|
232
|
+
* THIS REPLACES A PER-STEP GAS SUM that could only ever see part of the picture.
|
|
233
|
+
* That sum read `step.gasUsd`, so it was ZERO for every Relay quote — Relay
|
|
234
|
+
* publishes no per-leg breakdown — and for LI.FI it counted the network gas
|
|
235
|
+
* while missing the larger charge: a LayerZero fee of about 1.37 dollars marked
|
|
236
|
+
* `included: false`, paid on top in native currency. Reading the quote's own
|
|
237
|
+
* normalized fee list catches both, and cannot double-count the per-step gas
|
|
238
|
+
* against the aggregate the provider reports.
|
|
239
|
+
*
|
|
240
|
+
* A charge whose dollar value the provider did not give is skipped rather than
|
|
241
|
+
* guessed. It is still named in the breakdown the reader can open.
|
|
242
|
+
*
|
|
243
|
+
* Exported for the same reason {@link candidatePaidUsd} is — `search/plan-route-data.ts`
|
|
244
|
+
* reuses this exact valuation rather than restating it for a plan's last hop.
|
|
245
|
+
*/
|
|
246
|
+
export declare const candidateOutsideFeesUsd: (candidate: RouteCandidate) => number;
|
|
247
|
+
/**
|
|
248
|
+
* The user's NET dollar outcome for a candidate: the value delivered minus
|
|
249
|
+
* everything paid to reach it. Three cost components:
|
|
250
|
+
*
|
|
251
|
+
* - the origin tokens spent (`quote.fromAmountUsd`);
|
|
252
|
+
* - every charge paid on top ({@link candidateOutsideFeesUsd}), NOT part of
|
|
253
|
+
* `fromAmount` — the sender's own network gas, and any provider fee the
|
|
254
|
+
* quote marked as charged outside the amount;
|
|
255
|
+
* - the omnibridge CROSSING fee, already netted into `deliveredAmount`.
|
|
256
|
+
*
|
|
257
|
+
* The delivered value comes from {@link candidateDeliveredUsd}, the same figure
|
|
258
|
+
* the route's own dollar value and cost are built from. This is the one ranking
|
|
259
|
+
* rule: the route strip orders by it, so the route the reader sees costing least
|
|
260
|
+
* is the route that leads.
|
|
261
|
+
*
|
|
262
|
+
* @param candidate - the priced route candidate
|
|
263
|
+
* @returns the net outcome in United States dollars, or null when the leg or
|
|
264
|
+
* the delivered tokens are unpriced
|
|
265
|
+
*/
|
|
266
|
+
export declare const candidateNetValueUsd: (candidate: RouteCandidate) => number | null;
|
|
267
|
+
/**
|
|
268
|
+
* The roots the direct-route builder reads. See full documentation on
|
|
269
|
+
* {@link buildDirectRouteData}.
|
|
270
|
+
*/
|
|
271
|
+
export type DirectRouteRoots = CrossingFeeRoots & {
|
|
272
|
+
/** Logo url for the input (source) token, or null. */
|
|
273
|
+
assetInLogoUri?: string | null;
|
|
274
|
+
/** Logo url for the output (delivered) token, or null. */
|
|
275
|
+
assetOutLogoUri?: string | null;
|
|
276
|
+
/** Logo url for the source chain badge, or null. */
|
|
277
|
+
fromChainLogoUri?: string | null;
|
|
278
|
+
/** Logo url for the destination chain badge, or null. */
|
|
279
|
+
toChainLogoUri?: string | null;
|
|
280
|
+
/** The active bridge key tuple `[provider, fromChain, toChain]`. */
|
|
281
|
+
bridgeKey: BridgeKey;
|
|
282
|
+
/** The resolved input token, or null while the cascade is still resolving. */
|
|
283
|
+
assetIn: Token | null;
|
|
284
|
+
/** The resolved output (delivered) token, or null. */
|
|
285
|
+
assetOut: Token | null;
|
|
286
|
+
/**
|
|
287
|
+
* The estimated delivered amount in `assetOut` base units (after the bridge fee
|
|
288
|
+
* and delivery cost). Zero before the user enters an amount, which renders the
|
|
289
|
+
* route's amounts as zero.
|
|
290
|
+
*/
|
|
291
|
+
estimatedAmountOut: bigint;
|
|
292
|
+
/**
|
|
293
|
+
* Per-`assetIn`-token United States dollar price, or null when unpriced. This is
|
|
294
|
+
* the route's basis: BOTH the fee and the delivered value are priced from it, so
|
|
295
|
+
* the two sides of the crossing can never be stated on different feeds.
|
|
296
|
+
*/
|
|
297
|
+
assetInUsdPrice: number | null;
|
|
298
|
+
/**
|
|
299
|
+
* Per-`assetOut`-token United States dollar price, or null when unpriced. Used
|
|
300
|
+
* ONLY as the fallback basis for the delivered value when `assetInUsdPrice` is
|
|
301
|
+
* absent — never alongside it, which is what let a zero-fee crossing report a loss.
|
|
302
|
+
*/
|
|
303
|
+
assetOutUsdPrice: number | null;
|
|
304
|
+
/**
|
|
305
|
+
* Per-step transaction-transparency passthrough — the bridge mediator
|
|
306
|
+
* addresses, destination router, and encoded calldata for the single direct
|
|
307
|
+
* signature. Optional; the produced section carries it verbatim when supplied.
|
|
308
|
+
*/
|
|
309
|
+
advanced?: {
|
|
310
|
+
bridgeFrom?: Hex | null;
|
|
311
|
+
bridgeTo?: Hex | null;
|
|
312
|
+
destinationRouter?: Hex | null;
|
|
313
|
+
calldata?: Hex | null;
|
|
314
|
+
};
|
|
315
|
+
};
|
|
316
|
+
/**
|
|
317
|
+
* Builds the RAW, data-only {@link RouteData} for one priced aggregator candidate
|
|
318
|
+
* — the framework-agnostic half of the candidate path, carrying NUMBERS, raw
|
|
319
|
+
* token references, and raw provider keys ONLY. The display wrapper runs this
|
|
320
|
+
* through `toRouteView` to resolve every logo, name, formatted string, and the
|
|
321
|
+
* structural id.
|
|
322
|
+
*
|
|
323
|
+
* The candidate is a single signature (the aggregator swap auto-calls the
|
|
324
|
+
* omnibridge), so it produces exactly one {@link RouteSectionData} whose hops are
|
|
325
|
+
* the aggregator legs the provider reported (Relay reports none) followed by the
|
|
326
|
+
* omnibridge crossing leg. Each hop carries its OWN numeric fee so the user sees
|
|
327
|
+
* where cost accrues.
|
|
328
|
+
*
|
|
329
|
+
* @param candidate - one priced route candidate
|
|
330
|
+
* @returns the raw, data-only route for the candidate
|
|
331
|
+
*/
|
|
332
|
+
export declare const buildCandidateRouteData: (candidate: RouteCandidate) => RouteData;
|
|
333
|
+
/**
|
|
334
|
+
* Builds the ALWAYS-PRESENT direct omnibridge route from the current outbound
|
|
335
|
+
* settings, so the strip is never empty for a resolvable pathway.
|
|
336
|
+
*
|
|
337
|
+
* The direct route is a SINGLE SIGNATURE — the user signs the omnibridge call
|
|
338
|
+
* once — so it is exactly ONE {@link RouteSectionData}. Returns null only when
|
|
339
|
+
* the pathway is NOT resolvable (a missing input or output asset).
|
|
340
|
+
*
|
|
341
|
+
* @param roots - the resolved settings + price + logo roots (see {@link DirectRouteRoots})
|
|
342
|
+
* @returns the single direct {@link RouteData}, or null when unresolvable
|
|
343
|
+
*/
|
|
344
|
+
export declare const buildDirectRouteData: (roots: DirectRouteRoots) => RouteData | null;
|
|
345
|
+
/**
|
|
346
|
+
* Where an outbound route's SECOND signature lands when it leaves the entry chain
|
|
347
|
+
* rather than swapping on it.
|
|
348
|
+
*
|
|
349
|
+
* WHY THESE THREE FACTS ARRIVE TOGETHER rather than as three optional fields on
|
|
350
|
+
* the roots. Each one alone is enough to describe a route that cannot be drawn.
|
|
351
|
+
* A chain id with no name leaves section 2 labelled after the entry chain while
|
|
352
|
+
* its token sits on another; a chain with no provider leaves the hop credited to
|
|
353
|
+
* "Swap", which is the PulseX label and the wrong service. Grouping them means a
|
|
354
|
+
* caller either states the whole onward hop or states none of it, and the absent
|
|
355
|
+
* case is the existing same-chain swap, unchanged.
|
|
356
|
+
*
|
|
357
|
+
* THE OMNIBRIDGE STILL CROSSES ONLY TO ETHEREUM OR BINANCE SMART CHAIN. This
|
|
358
|
+
* widens where the SECOND leg may land, never where the first one may. The entry
|
|
359
|
+
* guard in {@link buildOutboundRouteData} is unaffected.
|
|
360
|
+
*/
|
|
361
|
+
export type OutboundOnwardHop = {
|
|
362
|
+
/**
|
|
363
|
+
* The decimal chain id the deferred leg delivers on. Must equal the
|
|
364
|
+
* `finalToken`'s own `chainId`; the builder returns null when they disagree
|
|
365
|
+
* rather than drawing a token on a chain it does not live on.
|
|
366
|
+
*/
|
|
367
|
+
chainId: number;
|
|
368
|
+
/**
|
|
369
|
+
* The chain's fully spelled-out name, for section 2's label and the hop title.
|
|
370
|
+
* Resolved by the caller, which owns the chain table — the same threading the
|
|
371
|
+
* logo urls already use.
|
|
372
|
+
*/
|
|
373
|
+
chainName: string;
|
|
374
|
+
/**
|
|
375
|
+
* The display name of the service that will quote and carry the onward hop
|
|
376
|
+
* (for example "Relay"), from the provider registry. This hop is NOT a PulseX
|
|
377
|
+
* swap and must not be credited to one.
|
|
378
|
+
*/
|
|
379
|
+
providerName: string;
|
|
380
|
+
/** Pre-resolved chain-badge logo url for `chainId`; undefined lets the adapter resolve it. */
|
|
381
|
+
chainLogoUri?: string | null;
|
|
382
|
+
};
|
|
383
|
+
/**
|
|
384
|
+
* The roots the OUTBOUND two-signature route builder reads. See full documentation
|
|
385
|
+
* on {@link buildOutboundRouteData}.
|
|
386
|
+
*/
|
|
387
|
+
export type OutboundRouteRoots = CrossingFeeRoots & {
|
|
388
|
+
/** Logo url for the input (source) token, or null. */
|
|
389
|
+
assetInLogoUri?: string | null;
|
|
390
|
+
/** Logo url for the output (delivered) token, or null. */
|
|
391
|
+
assetOutLogoUri?: string | null;
|
|
392
|
+
/** Logo url for the source chain badge, or null. */
|
|
393
|
+
fromChainLogoUri?: string | null;
|
|
394
|
+
/** Logo url for the destination chain badge, or null. */
|
|
395
|
+
toChainLogoUri?: string | null;
|
|
396
|
+
/** The active outbound omnibridge pathway tuple `[provider, fromChain, toChain]`. */
|
|
397
|
+
bridgeKey: BridgeKey;
|
|
398
|
+
/** The resolved PulseChain source token, or null while the cascade resolves. */
|
|
399
|
+
assetIn: Token | null;
|
|
400
|
+
/**
|
|
401
|
+
* The token the omnibridge delivers on the entry chain (Ethereum / Binance
|
|
402
|
+
* Smart Chain). It is section 1's destination and section 2's source. Null
|
|
403
|
+
* while the cascade resolves — the builder then returns null.
|
|
404
|
+
*/
|
|
405
|
+
intermediateToken: Token | null;
|
|
406
|
+
/**
|
|
407
|
+
* The token the user ultimately wants — section 2's destination. It sits on the
|
|
408
|
+
* ENTRY chain by default and on {@link OutboundOnwardHop.chainId} when `onward`
|
|
409
|
+
* is supplied. Null while the cascade resolves — the builder then returns null.
|
|
410
|
+
*/
|
|
411
|
+
finalToken: Token | null;
|
|
412
|
+
/**
|
|
413
|
+
* Where section 2 lands when it is NOT a swap on the entry chain. Absent (or
|
|
414
|
+
* null) keeps today's behaviour exactly: the deferred leg is a PulseX-style swap
|
|
415
|
+
* that stays on the entry chain. See {@link OutboundOnwardHop}.
|
|
416
|
+
*/
|
|
417
|
+
onward?: OutboundOnwardHop | null;
|
|
418
|
+
/**
|
|
419
|
+
* The omnibridge-delivered amount of `intermediateToken`, in its base units
|
|
420
|
+
* (leg 1's output). Zero before the user enters an amount.
|
|
421
|
+
*/
|
|
422
|
+
estimatedAmountOut: bigint;
|
|
423
|
+
/** Per-`assetIn`-token United States dollar price, or null when unpriced. */
|
|
424
|
+
assetInUsdPrice: number | null;
|
|
425
|
+
/** Per-`intermediateToken` United States dollar price, or null when unpriced. */
|
|
426
|
+
intermediateUsdPrice: number | null;
|
|
427
|
+
/**
|
|
428
|
+
* Logo url for the `finalToken` (the deferred leg's destination token), or null
|
|
429
|
+
* to fall back to a placeholder glyph in section 2's token flow.
|
|
430
|
+
*/
|
|
431
|
+
finalTokenLogoUri?: string | null;
|
|
432
|
+
/**
|
|
433
|
+
* Logo url for the entry chain's badge (Ethereum / Binance Smart Chain), used on
|
|
434
|
+
* the intermediate and final token nodes that both live on the entry chain, or
|
|
435
|
+
* null to omit the badge.
|
|
436
|
+
*/
|
|
437
|
+
intermediateChainLogoUri?: string | null;
|
|
438
|
+
};
|
|
439
|
+
/**
|
|
440
|
+
* Builds the TWO-SIGNATURE OUTBOUND raw {@link RouteData} from PulseChain, across
|
|
441
|
+
* an omnibridge entry chain (Ethereum or Binance Smart Chain), to wherever the
|
|
442
|
+
* second signature lands.
|
|
443
|
+
*
|
|
444
|
+
* The route is exactly TWO {@link RouteSectionData}s:
|
|
445
|
+
* - SECTION 1 ("Bridge to {entry chain}") — the omnibridge out.
|
|
446
|
+
* - SECTION 2 ("Complete at {final chain}") — DEFERRED. Signed only after section
|
|
447
|
+
* 1's crossing settles, and carrying no binding quote until then.
|
|
448
|
+
*
|
|
449
|
+
* SECTION 2 HAS TWO SHAPES, and `roots.onward` is what picks between them.
|
|
450
|
+
* Without it the deferred leg is a swap that stays on the entry chain: the
|
|
451
|
+
* existing behaviour, down to its approximate ~0.29% PulseX fee. With it the
|
|
452
|
+
* deferred leg is an onward BRIDGE to `onward.chainId`, carried by the named
|
|
453
|
+
* provider, and it states NO fee — see the fee note in the body for why quoting
|
|
454
|
+
* the swap constant there would be a fabricated number.
|
|
455
|
+
*
|
|
456
|
+
* WHY THE FIRST LEG CANNOT WIDEN THE SAME WAY. The bridged message carries
|
|
457
|
+
* `(token, receiver, value, data)` and no chain id, and a mediator's counterpart
|
|
458
|
+
* is wired in at deploy time, so the omnibridge's destination is structural
|
|
459
|
+
* rather than a parameter. The reach comes from composing a second signature on
|
|
460
|
+
* the far side, which is what this builder draws.
|
|
461
|
+
*
|
|
462
|
+
* Returns null when `assetIn`, `intermediateToken`, or `finalToken` is missing,
|
|
463
|
+
* when the crossing's destination is not one of the two omnibridge entry chains,
|
|
464
|
+
* or when `onward.chainId` disagrees with the final token's own `chainId`.
|
|
465
|
+
*
|
|
466
|
+
* @param roots - the resolved settings + price + logo roots (see {@link OutboundRouteRoots})
|
|
467
|
+
* @returns the two-section raw outbound {@link RouteData}, or null when unresolvable
|
|
468
|
+
*/
|
|
469
|
+
export declare const buildOutboundRouteData: (roots: OutboundRouteRoots) => RouteData | null;
|
|
470
|
+
/**
|
|
471
|
+
* The roots the raw PulseX swap section builder reads. See full documentation on
|
|
472
|
+
* {@link buildPulseXSwapSectionData}.
|
|
473
|
+
*/
|
|
474
|
+
export type PulseXSwapSectionDataRoots = {
|
|
475
|
+
/**
|
|
476
|
+
* Caller-supplied stable identity for the section, used for keys and disclosure
|
|
477
|
+
* state. The composing route owns uniqueness, so this is passed in verbatim
|
|
478
|
+
* rather than derived here.
|
|
479
|
+
*/
|
|
480
|
+
id: string;
|
|
481
|
+
/** The token held on PulseChain before the swap — the swap's input. */
|
|
482
|
+
fromToken: Token;
|
|
483
|
+
/** The token the user wants on PulseChain — the swap's output. */
|
|
484
|
+
toToken: Token;
|
|
485
|
+
/**
|
|
486
|
+
* The swap's TOTAL cost in United States dollars as a NUMBER, or null when the
|
|
487
|
+
* caller could not price the swap.
|
|
488
|
+
*/
|
|
489
|
+
feeUsdValue?: number | null;
|
|
490
|
+
/**
|
|
491
|
+
* The swap's price impact as a percentage NUMBER, or null when unknown.
|
|
492
|
+
*/
|
|
493
|
+
priceImpactPercent?: number | null;
|
|
494
|
+
/**
|
|
495
|
+
* The `toToken` amount the swap is expected to deliver, in base units — what
|
|
496
|
+
* this step lands the user in. Null or absent leaves the step naming its landed
|
|
497
|
+
* TOKEN without an amount, which is the honest reading for a leg that carries no
|
|
498
|
+
* binding quote yet.
|
|
499
|
+
*/
|
|
500
|
+
landedAmount?: bigint | null;
|
|
501
|
+
/**
|
|
502
|
+
* The landed amount's value in United States dollars, or null when unpriced.
|
|
503
|
+
* Supplied by the composing route rather than derived here, so it stays on the
|
|
504
|
+
* same basis as every other figure that route reports.
|
|
505
|
+
*/
|
|
506
|
+
landedUsdValue?: number | null;
|
|
507
|
+
/** Estimated swap duration in minutes, or null to omit the time chip. */
|
|
508
|
+
etaMinutes?: number | null;
|
|
509
|
+
/**
|
|
510
|
+
* Estimated swap duration in SECONDS, for the near-instant swap leg the minute
|
|
511
|
+
* chip would round misleadingly. Takes precedence over `etaMinutes` in the view.
|
|
512
|
+
*/
|
|
513
|
+
etaSeconds?: number | null;
|
|
514
|
+
/** Logo url for the `fromToken` node, or null to fall back to a placeholder. */
|
|
515
|
+
fromTokenLogoUri?: string | null;
|
|
516
|
+
/** Logo url for the `toToken` node, or null to fall back to a placeholder. */
|
|
517
|
+
toTokenLogoUri?: string | null;
|
|
518
|
+
/**
|
|
519
|
+
* Logo url for the PulseChain chain badge shown on BOTH token-flow nodes (both
|
|
520
|
+
* tokens live on PulseChain), or null to omit the badge.
|
|
521
|
+
*/
|
|
522
|
+
pulsechainChainLogoUri?: string | null;
|
|
523
|
+
/**
|
|
524
|
+
* True only in the rare case where the swap is signed AFTER a prior section's
|
|
525
|
+
* async bridge crossing settles. Defaults to false.
|
|
526
|
+
*/
|
|
527
|
+
deferred?: boolean;
|
|
528
|
+
/**
|
|
529
|
+
* Transaction-transparency details for the advanced disclosure, built by the
|
|
530
|
+
* caller from the SAME builder the swap button itself calls
|
|
531
|
+
* (`pulseXSwapTransactionInputs` in `settings.ts`) — never a second encoding
|
|
532
|
+
* here. Absent while the swap is not yet buildable (no connected recipient,
|
|
533
|
+
* or no router deployed for the chain), which leaves the section's
|
|
534
|
+
* `advanced` field undefined rather than half-populated.
|
|
535
|
+
*/
|
|
536
|
+
advanced?: {
|
|
537
|
+
/** The PulseX router this swap calls, or null when none is deployed. */
|
|
538
|
+
destinationRouter: Hex | null;
|
|
539
|
+
/** The swap's encoded calldata from `pulseXSwapTransactionInputs`, or null. */
|
|
540
|
+
calldata: Hex | null;
|
|
541
|
+
} | null;
|
|
542
|
+
};
|
|
543
|
+
/**
|
|
544
|
+
* Builds a single composable raw {@link RouteSectionData} for a swap on PulseX,
|
|
545
|
+
* the decentralized exchange on PulseChain. A composing route appends this to its
|
|
546
|
+
* `sections` array. Both tokens live on PulseChain (chain id 369), so both
|
|
547
|
+
* token-flow nodes carry the PulseChain chain badge.
|
|
548
|
+
*
|
|
549
|
+
* The section carries raw numeric fields (`feePercent`, `priceImpactPercent`,
|
|
550
|
+
* `feeUsdValue`); the adapter (`toRouteView`) formats them into the display
|
|
551
|
+
* breakdown string.
|
|
552
|
+
*
|
|
553
|
+
* @param roots - the section's identity, tokens, pricing, and logos
|
|
554
|
+
* @returns one raw PulseX swap {@link RouteSectionData}
|
|
555
|
+
*/
|
|
556
|
+
export declare const buildPulseXSwapSectionData: (roots: PulseXSwapSectionDataRoots) => RouteSectionData;
|
|
557
|
+
/**
|
|
558
|
+
* The raw numeric counterpart of the string-formatted swap estimate: every field
|
|
559
|
+
* is a number (or bigint / null) instead of a formatted string. Produced by
|
|
560
|
+
* {@link buildPulseXSwapEstimateData} so the conversion composition can flow the
|
|
561
|
+
* numbers straight into a {@link RouteData} without re-parsing formatted currency
|
|
562
|
+
* strings.
|
|
563
|
+
*/
|
|
564
|
+
export type PulseXSwapEstimateData = {
|
|
565
|
+
/** The wanted-token amount the swap is expected to deliver, in base units. */
|
|
566
|
+
outputAmount: bigint;
|
|
567
|
+
/**
|
|
568
|
+
* The PulseX protocol fee alone in United States dollars as a plain number — the
|
|
569
|
+
* flat ~0.29% the exchange takes on the swapped value. Null only when NEITHER
|
|
570
|
+
* side is priced.
|
|
571
|
+
*/
|
|
572
|
+
feeUsdValue: number | null;
|
|
573
|
+
/**
|
|
574
|
+
* The swap's TOTAL cost in United States dollars as a plain number — the fee
|
|
575
|
+
* PLUS the price impact. Null only when neither side is priced. Clamped at zero.
|
|
576
|
+
* The fee is rounded to cents before summing (matching the pre-split builder's
|
|
577
|
+
* rounding so downstream cents-level totals stay identical).
|
|
578
|
+
*/
|
|
579
|
+
costUsdValue: number | null;
|
|
580
|
+
/**
|
|
581
|
+
* The swap's price impact as a percentage (e.g. 0.8 for "0.8% price impact").
|
|
582
|
+
* Null when both sides are not priced or no reference quote is supplied.
|
|
583
|
+
*/
|
|
584
|
+
priceImpactPercent: number | null;
|
|
585
|
+
/** Estimated swap duration in minutes, or null (a PulseX swap is near-instant). */
|
|
586
|
+
etaMinutes: number | null;
|
|
587
|
+
};
|
|
588
|
+
/**
|
|
589
|
+
* Roots for {@link buildConversionRouteData}: the base raw route that delivers
|
|
590
|
+
* the anchor token onto PulseChain, the swap's tokens, the pre-derived raw
|
|
591
|
+
* estimate, and the logos for the appended swap section's token flow.
|
|
592
|
+
*/
|
|
593
|
+
export type ConversionRouteComposition = {
|
|
594
|
+
/**
|
|
595
|
+
* The raw route data that bridges the LIQUID anchor token onto PulseChain. Its
|
|
596
|
+
* last section delivers the anchor; this composition appends the PulseX swap
|
|
597
|
+
* that converts it to the wanted token.
|
|
598
|
+
*/
|
|
599
|
+
baseData: RouteData;
|
|
600
|
+
/**
|
|
601
|
+
* The base route's display id, computed by the user interface via `toRouteView`
|
|
602
|
+
* and injected so this producer holds no display dependency. Only the swap
|
|
603
|
+
* section's React key uses it; `routeStripHash` ignores section ids, so it
|
|
604
|
+
* never affects route identity.
|
|
605
|
+
*/
|
|
606
|
+
baseRouteId: string;
|
|
607
|
+
/** The anchor token the base route delivers on PulseChain — the swap's input. */
|
|
608
|
+
anchorToken: Token;
|
|
609
|
+
/** The token the user actually wants on PulseChain — the swap's output. */
|
|
610
|
+
wantedToken: Token;
|
|
611
|
+
/** The pre-derived raw swap figures (see {@link buildPulseXSwapEstimateData}). */
|
|
612
|
+
estimate: PulseXSwapEstimateData;
|
|
613
|
+
/** Logo url for the anchor token node in the swap section's flow, or null. */
|
|
614
|
+
anchorTokenLogoUri?: string | null;
|
|
615
|
+
/** Logo url for the wanted token node in the swap section's flow, or null. */
|
|
616
|
+
wantedTokenLogoUri?: string | null;
|
|
617
|
+
/** Logo url for the PulseChain chain badge on both swap-section nodes, or null. */
|
|
618
|
+
pulsechainChainLogoUri?: string | null;
|
|
619
|
+
};
|
|
620
|
+
/**
|
|
621
|
+
* Composes a raw {@link RouteData} for the conversion route: bridge a liquid anchor
|
|
622
|
+
* token onto PulseChain, then a DEFERRED PulseX swap to the wanted token.
|
|
623
|
+
*
|
|
624
|
+
* Operates entirely at the raw data level — no display formatting. The caller runs
|
|
625
|
+
* the result through `toRouteView` to get the display-ready `RouteOption`.
|
|
626
|
+
*
|
|
627
|
+
* Per the owner's two locked decisions:
|
|
628
|
+
*
|
|
629
|
+
* - **LOCKED DECISION 1 — normalise via the liquid anchor.** When the omnibridge
|
|
630
|
+
* cannot deliver the wanted token directly (the wanted token has not yet been
|
|
631
|
+
* bridged, or its canonical foreign-chain pair is illiquid), the rails bridge a
|
|
632
|
+
* well-known liquid anchor token instead and a PulseX swap leg converts it on
|
|
633
|
+
* PulseChain. The {@link ConversionRouteComposition.baseData} is the raw route
|
|
634
|
+
* that delivers that anchor; this function appends the conversion leg. The two
|
|
635
|
+
* combined sections represent one complete user journey: bridge to the anchor,
|
|
636
|
+
* then swap the anchor to the wanted token.
|
|
637
|
+
*
|
|
638
|
+
* - **LOCKED DECISION 2 — the swap is a deferred second signature.** The PulseX
|
|
639
|
+
* swap can only be signed AFTER the PulseChain Bridge lands the anchor on
|
|
640
|
+
* PulseChain — the funds must arrive before the user can authorise the swap. The
|
|
641
|
+
* appended section therefore carries `deferred: true` and an ESTIMATED fee that
|
|
642
|
+
* firms up on arrival (price impact and pool depth may shift in the ~20 minutes
|
|
643
|
+
* the crossing takes). Do not collapse these into one signature.
|
|
644
|
+
*
|
|
645
|
+
* The composed route:
|
|
646
|
+
* - keeps the base route's provider and entry chain (`entryChainId` / `via`) — it
|
|
647
|
+
* is the same PulseChain Bridge crossing with a swap bolted on at the
|
|
648
|
+
* destination;
|
|
649
|
+
* - takes a DISTINCT identifier (`<baseRouteId>-pulsex-swap`) so React keys and
|
|
650
|
+
* selection never collide with the bare anchor-delivery route;
|
|
651
|
+
* - re-drives the output to the wanted token: the estimate's delivered amount, its
|
|
652
|
+
* United States dollar value, and the wanted token's symbol (the bare anchor
|
|
653
|
+
* route would otherwise claim the anchor as the delivered token);
|
|
654
|
+
* - sums the swap's total cost (fee + price impact) into `totalCostUsdValue` so
|
|
655
|
+
* the aggregate cost is honest — aggregator spread + omnibridge crossing +
|
|
656
|
+
* PulseX swap — and subtracts it from `netValueUsd`.
|
|
657
|
+
*
|
|
658
|
+
* @param composition - the base route data, swap tokens, estimate, logos, and the
|
|
659
|
+
* injected base route id (computed by the caller via `toRouteView`)
|
|
660
|
+
* @returns the composed raw two-section conversion route (bridge, then deferred PulseX swap)
|
|
661
|
+
*/
|
|
662
|
+
export declare const buildConversionRouteData: (composition: ConversionRouteComposition) => RouteData;
|
|
663
|
+
/**
|
|
664
|
+
* Derives a {@link PulseXSwapEstimateData} — the raw NUMERIC form of the PulseX
|
|
665
|
+
* swap estimate — from a PulseX `getAmountsOut` quote.
|
|
666
|
+
*
|
|
667
|
+
* Returns raw numbers rather than formatted currency strings, so the conversion
|
|
668
|
+
* composition can flow them straight into a {@link RouteData} without re-parsing
|
|
669
|
+
* currency strings.
|
|
670
|
+
*
|
|
671
|
+
* Returns null when the quote is absent or empty (the router reverted or has not
|
|
672
|
+
* loaded) — the composing route then has no swap leg to append.
|
|
673
|
+
*
|
|
674
|
+
* @param params.amountsOut - the router's amounts-out array, or null when unquoted
|
|
675
|
+
* @param params.inputAmount - the anchor amount entering the swap, in its base units
|
|
676
|
+
* @param params.inputToken - the anchor token (the swap input)
|
|
677
|
+
* @param params.inputUsdPrice - the anchor token's per-token dollar price, or null
|
|
678
|
+
* @param params.outputToken - the wanted token (the swap output)
|
|
679
|
+
* @param params.outputUsdPrice - the wanted token's per-token dollar price, or null
|
|
680
|
+
* @param params.referenceAmountsOut - marginal reference quote amounts-out, or null
|
|
681
|
+
* @param params.referenceInputAmount - the reference quote's input amount
|
|
682
|
+
* @returns the derived estimate with numeric fields, or null when the quote yields no output amount
|
|
683
|
+
*/
|
|
684
|
+
export declare const buildPulseXSwapEstimateData: ({ amountsOut, inputAmount, inputToken, inputUsdPrice, outputToken, outputUsdPrice, referenceAmountsOut, referenceInputAmount, }: {
|
|
685
|
+
amountsOut: readonly bigint[] | null;
|
|
686
|
+
inputAmount: bigint;
|
|
687
|
+
inputToken: Token;
|
|
688
|
+
inputUsdPrice: number | null;
|
|
689
|
+
outputToken: Token;
|
|
690
|
+
outputUsdPrice: number | null;
|
|
691
|
+
/**
|
|
692
|
+
* The amounts-out of a tiny MARGINAL reference quote along the SAME path (see
|
|
693
|
+
* {@link PULSEX_MARGINAL_REFERENCE_DIVISOR}). Its near-spot rate is what lets the
|
|
694
|
+
* price impact be isolated from the fee without differencing two circular
|
|
695
|
+
* PulseX-derived prices. Null/empty → impact is unknown and the cost degrades to
|
|
696
|
+
* the flat fee.
|
|
697
|
+
*/
|
|
698
|
+
referenceAmountsOut?: readonly bigint[] | null;
|
|
699
|
+
/** The reference quote's input amount (the tiny marginal input). */
|
|
700
|
+
referenceInputAmount?: bigint;
|
|
701
|
+
}) => PulseXSwapEstimateData | null;
|
|
702
|
+
/**
|
|
703
|
+
* Roots for {@link buildSameChainSwapRouteData}: the swap's two tokens (both
|
|
704
|
+
* live on PulseChain), the pre-derived raw estimate, and what the reader paid
|
|
705
|
+
* for the input, so the route's cost and net value are on the same basis as
|
|
706
|
+
* every other route.
|
|
707
|
+
*/
|
|
708
|
+
export type SameChainSwapRouteRoots = {
|
|
709
|
+
/** Caller-supplied stable identity for the route, used for the section id. */
|
|
710
|
+
id: string;
|
|
711
|
+
/** The token the reader holds before the swap — the swap's input. */
|
|
712
|
+
fromToken: Token;
|
|
713
|
+
/** The token the reader wants after the swap — the swap's output. */
|
|
714
|
+
toToken: Token;
|
|
715
|
+
/** The pre-derived raw swap figures (see {@link buildPulseXSwapEstimateData}). */
|
|
716
|
+
estimate: PulseXSwapEstimateData;
|
|
717
|
+
/**
|
|
718
|
+
* What the input side is worth in United States dollars, or null when
|
|
719
|
+
* unpriced. This is the route's OWN basis for `totalCostUsdValue` and
|
|
720
|
+
* `netValueUsd` — there is no bridge leg underneath to inherit a basis from,
|
|
721
|
+
* unlike {@link buildConversionRouteData}.
|
|
722
|
+
*/
|
|
723
|
+
inputUsdValue: number | null;
|
|
724
|
+
/** Logo url for the `fromToken` node, or null to fall back to a placeholder. */
|
|
725
|
+
fromTokenLogoUri?: string | null;
|
|
726
|
+
/** Logo url for the `toToken` node, or null to fall back to a placeholder. */
|
|
727
|
+
toTokenLogoUri?: string | null;
|
|
728
|
+
/** Logo url for the PulseChain chain badge on both token-flow nodes, or null. */
|
|
729
|
+
pulsechainChainLogoUri?: string | null;
|
|
730
|
+
/**
|
|
731
|
+
* Transaction-transparency details for the advanced disclosure, built by the
|
|
732
|
+
* caller from the SAME builder the swap button itself calls
|
|
733
|
+
* (`pulseXSwapTransactionInputs` in `settings.ts`) — never a second encoding
|
|
734
|
+
* here. Absent while the swap is not yet buildable.
|
|
735
|
+
*/
|
|
736
|
+
advanced?: {
|
|
737
|
+
/** The PulseX router this swap calls, or null when none is deployed. */
|
|
738
|
+
destinationRouter: Hex | null;
|
|
739
|
+
/** The swap's encoded calldata from `pulseXSwapTransactionInputs`, or null. */
|
|
740
|
+
calldata: Hex | null;
|
|
741
|
+
} | null;
|
|
742
|
+
};
|
|
743
|
+
/**
|
|
744
|
+
* Composes a raw {@link RouteData} for a SAME-CHAIN PulseX swap: PulseChain on
|
|
745
|
+
* both sides of the selection, one signature, no crossing at all.
|
|
746
|
+
*
|
|
747
|
+
* WHY THIS IS ITS OWN PRODUCER, RATHER THAN `buildConversionRouteData` WITH NO
|
|
748
|
+
* BASE. The conversion route APPENDS a swap section to a bridge route that
|
|
749
|
+
* already delivered the anchor onto PulseChain; its cost, its `entryChainId`,
|
|
750
|
+
* and its "deferred" swap all inherit from that base. A same-chain swap has no
|
|
751
|
+
* base — the reader already holds the input token on PulseChain before
|
|
752
|
+
* pressing anything — so the section is signed IMMEDIATELY (`deferred` stays
|
|
753
|
+
* false, the {@link buildPulseXSwapSectionData} default) and the route has no
|
|
754
|
+
* `entryChainId` at all, exactly like the direct omnibridge route it sits
|
|
755
|
+
* beside in the strip.
|
|
756
|
+
*
|
|
757
|
+
* NOT DEFERRED, AND THAT IS LOAD-BEARING FOR THE TRACKER. `deferred` means "the
|
|
758
|
+
* reader has not yet signed this" (see `sectionProgress.ts`); a same-chain swap
|
|
759
|
+
* is signed in the very press that builds it, so marking it deferred would tell
|
|
760
|
+
* the tracker a signature is still owed for a transaction already broadcast.
|
|
761
|
+
* What DOES need care downstream is the opposite failure the tracker's own
|
|
762
|
+
* `routeChainSequence` can produce for a route whose every stop shares one
|
|
763
|
+
* chain id — see `routeProgress.ts`'s `reachedChainIndex` for the fix that
|
|
764
|
+
* keeps a same-chain route from reading "delivered" the instant it is merely
|
|
765
|
+
* broadcast.
|
|
766
|
+
*
|
|
767
|
+
* @param roots - the route's identity, tokens, pricing, and logos
|
|
768
|
+
* @returns the one-section same-chain swap {@link RouteData}
|
|
769
|
+
*/
|
|
770
|
+
export declare const buildSameChainSwapRouteData: (roots: SameChainSwapRouteRoots) => RouteData;
|