@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
|
@@ -1,38 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.nearIntentsRefusalShapeFindings = exports.nearIntentsStatusShapeFindings = exports.nearIntentsMappedChainNames = exports.nearIntentsTokenListShapeFindings = exports.nearIntentsQuoteShapeFindings = void 0;
|
|
4
|
-
/**
|
|
5
|
-
* Does the live service still answer in the shape this repository parses?
|
|
6
|
-
*
|
|
7
|
-
* THIS EXISTS BECAUSE NEAR INTENTS HAS NO TEST NETWORK. The vendor states it
|
|
8
|
-
* four times in its own current material, most plainly in its list of common
|
|
9
|
-
* questions: "There is no testnet deployment and no plans for one. We
|
|
10
|
-
* recommend testing on NEAR mainnet using separate dev/test NEAR accounts."
|
|
11
|
-
* So there is no safe copy of the service to check an integration against, and
|
|
12
|
-
* the only honest substitute is a priced request against production that
|
|
13
|
-
* reserves nothing — a dry quote. See `docs/near-intents-capability-survey.md`.
|
|
14
|
-
*
|
|
15
|
-
* WHAT THIS CLOSES THAT THE FIXTURES CANNOT. `near-intents.test.ts` runs
|
|
16
|
-
* against real captures taken on 2026-09-17. A capture is a photograph: it
|
|
17
|
-
* proves the parser reads what the service sent that day, and it goes on
|
|
18
|
-
* proving that forever, including after the service stops sending it. Every
|
|
19
|
-
* parser here is tolerant by design — it returns null rather than throwing —
|
|
20
|
-
* so a field that changes type does not break a test, it removes a provider
|
|
21
|
-
* from the interface with no message anywhere. `amountOut` arriving as a
|
|
22
|
-
* number instead of a string is the whole failure: 37 green tests, and NEAR
|
|
23
|
-
* Intents silently never bids again.
|
|
24
|
-
*
|
|
25
|
-
* So these functions name every field the parsers actually depend on and
|
|
26
|
-
* report what is missing, rather than returning a normalized value. Handed a
|
|
27
|
-
* live response they answer "has production drifted away from the captures".
|
|
28
|
-
* Handed a capture they answer "is this capture still a fair stand-in".
|
|
29
|
-
*
|
|
30
|
-
* They are deliberately NOT parsers. A parser answers "can I use this"; these
|
|
31
|
-
* answer "is this what I was written against", which is a different question
|
|
32
|
-
* and needs the failures enumerated rather than collapsed into a null.
|
|
33
|
-
*/
|
|
34
4
|
const near_intents_js_1 = require("./near-intents.js");
|
|
35
|
-
/** Which parser depends on a field, so a finding says what will break. */
|
|
36
5
|
const describe = (value) => {
|
|
37
6
|
if (value === undefined) {
|
|
38
7
|
return 'absent';
|
|
@@ -48,13 +17,6 @@ const describe = (value) => {
|
|
|
48
17
|
const asRecord = (value) => typeof value === 'object' && value !== null && !Array.isArray(value)
|
|
49
18
|
? value
|
|
50
19
|
: null;
|
|
51
|
-
/**
|
|
52
|
-
* Checks one field and returns a finding when it is not the required type.
|
|
53
|
-
*
|
|
54
|
-
* A base-unit amount must be a NON-EMPTY string, because that is what
|
|
55
|
-
* `parseAmount` in `near-intents.ts` requires: it refuses an empty string and
|
|
56
|
-
* refuses a number, so either one silently collapses the whole quote to null.
|
|
57
|
-
*/
|
|
58
20
|
const requireField = ({ container, key, path, kind, }) => {
|
|
59
21
|
const value = container[key];
|
|
60
22
|
if (kind === 'amount') {
|
|
@@ -76,21 +38,6 @@ const requireField = ({ container, key, path, kind, }) => {
|
|
|
76
38
|
: { path, expected: 'a non-empty string', found: describe(value) };
|
|
77
39
|
};
|
|
78
40
|
const compact = (findings) => findings.filter((finding) => finding !== null);
|
|
79
|
-
/**
|
|
80
|
-
* Checks a `POST /v0/quote` answer against everything the quote parsers read.
|
|
81
|
-
*
|
|
82
|
-
* THE DOLLAR FIGURES ARE CHECKED THOUGH THE PARSER TOLERATES THEIR ABSENCE.
|
|
83
|
-
* `parseNearIntentsQuote` turns a missing `amountInUsd` into null and carries
|
|
84
|
-
* on, which is right for a quote and wrong for a conformance check: losing the
|
|
85
|
-
* dollar figure leaves the reader a route with no price beside it, and nothing
|
|
86
|
-
* else in the system would report that the service stopped sending one.
|
|
87
|
-
*
|
|
88
|
-
* @param payload - the raw JSON body the service answered with
|
|
89
|
-
* @param options.expectDepositAddress - true for an executable (`dry: false`)
|
|
90
|
-
* answer, false for a dry one. A dry answer omits the deposit address by
|
|
91
|
-
* design, so requiring it there would report a finding on a healthy service
|
|
92
|
-
* @returns every departure from the expected shape; empty means conformant
|
|
93
|
-
*/
|
|
94
41
|
const nearIntentsQuoteShapeFindings = (payload, { expectDepositAddress }) => {
|
|
95
42
|
const body = asRecord(payload);
|
|
96
43
|
if (!body) {
|
|
@@ -145,17 +92,6 @@ const nearIntentsQuoteShapeFindings = (payload, { expectDepositAddress }) => {
|
|
|
145
92
|
return [...findings, ...nearIntentsAppFeeFindings(body.quoteRequest)];
|
|
146
93
|
};
|
|
147
94
|
exports.nearIntentsQuoteShapeFindings = nearIntentsQuoteShapeFindings;
|
|
148
|
-
/**
|
|
149
|
-
* Checks the echoed request for the surcharge a key-less caller is charged.
|
|
150
|
-
*
|
|
151
|
-
* THE SERVICE INSERTS THIS, NOT US. Nothing in this repository asks for an
|
|
152
|
-
* `appFees` entry, and the fee parser only finds the twenty-five-basis-point
|
|
153
|
-
* charge because the service writes it into the request it echoes back. If it
|
|
154
|
-
* ever stops echoing it, the charge does not stop — it disappears from the
|
|
155
|
-
* fee rows and the reader is shown a route that costs a quarter of a percent
|
|
156
|
-
* more than the interface says. That is a silent understatement of cost, so it
|
|
157
|
-
* is a finding rather than a tolerated absence.
|
|
158
|
-
*/
|
|
159
95
|
const nearIntentsAppFeeFindings = (quoteRequest) => {
|
|
160
96
|
const request = asRecord(quoteRequest);
|
|
161
97
|
if (!request) {
|
|
@@ -193,23 +129,6 @@ const nearIntentsAppFeeFindings = (quoteRequest) => {
|
|
|
193
129
|
});
|
|
194
130
|
}));
|
|
195
131
|
};
|
|
196
|
-
/**
|
|
197
|
-
* Checks a `GET /v0/tokens` answer, including the chain names we map by hand.
|
|
198
|
-
*
|
|
199
|
-
* AN UNMAPPED CHAIN NAME IS THE DRIFT MOST LIKELY TO HAPPEN AND LEAST LIKELY
|
|
200
|
-
* TO BE NOTICED. `chainIdByNearIntentsChain` is a hand-written table, and
|
|
201
|
-
* `findNearIntentsAsset` matches through it — so if the service renames a
|
|
202
|
-
* chain or adds one, every asset on that chain becomes invisible to this
|
|
203
|
-
* repository while the asset list parses perfectly and every test stays green.
|
|
204
|
-
* The names are reported rather than the assets, because a new chain we do not
|
|
205
|
-
* carry is ordinary and a renamed chain we DO carry is the emergency.
|
|
206
|
-
*
|
|
207
|
-
* @param payload - the raw JSON body from the asset endpoint
|
|
208
|
-
* @param options.requiredChains - the service's own names for the chains this
|
|
209
|
-
* repository must keep reaching. A name missing from the answer means the
|
|
210
|
-
* service renamed or dropped it
|
|
211
|
-
* @returns every departure from the expected shape; empty means conformant
|
|
212
|
-
*/
|
|
213
132
|
const nearIntentsTokenListShapeFindings = (payload, { requiredChains }) => {
|
|
214
133
|
if (!Array.isArray(payload)) {
|
|
215
134
|
return [{ path: '', expected: 'an array of assets', found: describe(payload) }];
|
|
@@ -264,27 +183,10 @@ const nearIntentsTokenListShapeFindings = (payload, { requiredChains }) => {
|
|
|
264
183
|
return findings;
|
|
265
184
|
};
|
|
266
185
|
exports.nearIntentsTokenListShapeFindings = nearIntentsTokenListShapeFindings;
|
|
267
|
-
/**
|
|
268
|
-
* The service's own names for every chain this repository maps to a chain
|
|
269
|
-
* identifier, which is exactly the set whose renaming would be invisible.
|
|
270
|
-
*/
|
|
271
186
|
const nearIntentsMappedChainNames = () => [
|
|
272
187
|
...near_intents_js_1.chainIdByNearIntentsChain.keys(),
|
|
273
188
|
];
|
|
274
189
|
exports.nearIntentsMappedChainNames = nearIntentsMappedChainNames;
|
|
275
|
-
/**
|
|
276
|
-
* Checks a `GET /v0/status` answer against what the status parser reads.
|
|
277
|
-
*
|
|
278
|
-
* THE DELIVERY HASH IS NOT REQUIRED, and that is not laxity. A route awaiting
|
|
279
|
-
* its deposit has genuinely not produced one, and the captured
|
|
280
|
-
* `status-pending-deposit.json` is exactly that case — so requiring it would
|
|
281
|
-
* report a finding on a perfectly healthy in-flight transfer. What is required
|
|
282
|
-
* is that the ARRAY exists, because its absence is the difference between "no
|
|
283
|
-
* hash yet" and "the service stopped telling us where the funds landed".
|
|
284
|
-
*
|
|
285
|
-
* @param payload - the raw JSON body from the status endpoint
|
|
286
|
-
* @returns every departure from the expected shape; empty means conformant
|
|
287
|
-
*/
|
|
288
190
|
const nearIntentsStatusShapeFindings = (payload) => {
|
|
289
191
|
const body = asRecord(payload);
|
|
290
192
|
if (!body) {
|
|
@@ -313,18 +215,6 @@ const nearIntentsStatusShapeFindings = (payload) => {
|
|
|
313
215
|
];
|
|
314
216
|
};
|
|
315
217
|
exports.nearIntentsStatusShapeFindings = nearIntentsStatusShapeFindings;
|
|
316
|
-
/**
|
|
317
|
-
* Checks a refusal body carries the message the refusal parser reads.
|
|
318
|
-
*
|
|
319
|
-
* BOTH SIZE FLOORS ARRIVE ONLY AS PROSE IN THIS FIELD. There is no code, no
|
|
320
|
-
* limits endpoint and no structured figure — `parseNearIntentsQuoteRefusal`
|
|
321
|
-
* runs a regular expression over the sentence. So if the wording changes, a
|
|
322
|
-
* refusal that should withdraw the route from the competition instead reads as
|
|
323
|
-
* `other`, and the reader waits for a bid that will never come.
|
|
324
|
-
*
|
|
325
|
-
* @param payload - the raw JSON body of a refused quote
|
|
326
|
-
* @returns every departure from the expected shape; empty means conformant
|
|
327
|
-
*/
|
|
328
218
|
const nearIntentsRefusalShapeFindings = (payload) => {
|
|
329
219
|
const body = asRecord(payload);
|
|
330
220
|
if (!body) {
|
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
import type { DeferredCrossing, RouteCandidate } from './routing/candidate.js';
|
|
2
2
|
import type { RouteData } from './routing/route-data.js';
|
|
3
|
+
/**
|
|
4
|
+
* The name of a step that starts on one chain and ends on another (or the same).
|
|
5
|
+
*
|
|
6
|
+
* A step whose two chains differ is "Send to {end chain}". A step that never
|
|
7
|
+
* leaves its chain is a swap, so it is "Swap on {chain}". "Send to Ethereum"
|
|
8
|
+
* on a swap that starts and ends on Ethereum names a crossing that never
|
|
9
|
+
* happens.
|
|
10
|
+
*
|
|
11
|
+
* @param startChainId - the chain the step starts on
|
|
12
|
+
* @param endChainId - the chain the step ends on
|
|
13
|
+
* @returns the step's English label
|
|
14
|
+
*/
|
|
15
|
+
export declare const sendOrSwapLabel: (startChainId: number, endChainId: number) => string;
|
|
3
16
|
/**
|
|
4
17
|
* Builds the two-signature route for a candidate whose aggregator cannot
|
|
5
18
|
* execute the omnibridge entry call.
|
|
@@ -33,69 +33,24 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.describeDeferredCrossing = exports.buildNearIntentsTwoStepRouteData = void 0;
|
|
36
|
+
exports.describeDeferredCrossing = exports.buildNearIntentsTwoStepRouteData = exports.sendOrSwapLabel = void 0;
|
|
37
37
|
const imageLinks = __importStar(require("./image-links.js"));
|
|
38
38
|
const producers_js_1 = require("./routing/producers.js");
|
|
39
39
|
const providers_js_1 = require("./providers.js");
|
|
40
40
|
const usd_value_js_1 = require("./routing/usd-value.js");
|
|
41
41
|
const chain_names_js_1 = require("./chain-names.js");
|
|
42
|
-
/**
|
|
43
|
-
* The route shape for an aggregator that cannot execute on the chain it
|
|
44
|
-
* delivers to.
|
|
45
|
-
*
|
|
46
|
-
* WHY THIS EXISTS AT ALL. Every other consolidated route in this repository is
|
|
47
|
-
* ONE signature: the aggregator carries the reader's funds to an omnibridge
|
|
48
|
-
* entry chain and its executor performs the entry call on arrival, so the
|
|
49
|
-
* crossing into PulseChain happens inside the same transaction the reader
|
|
50
|
-
* already signed. NEAR Intents cannot do that — it delivers tokens to an
|
|
51
|
-
* address and runs nothing — and no arrangement of recipients works around it,
|
|
52
|
-
* because every omnibridge entry point learns who the reader is from a data
|
|
53
|
-
* field and a plain token transfer has none. See the head of `near-intents.ts`.
|
|
54
|
-
*
|
|
55
|
-
* So the crossing becomes TWO signatures, and the honest thing is to draw it
|
|
56
|
-
* that way. The aggregator lands the anchor token in the reader's OWN wallet on
|
|
57
|
-
* the entry chain; the reader then signs the ordinary omnibridge call
|
|
58
|
-
* themselves. The interface already renders exactly this shape — a section
|
|
59
|
-
* marked `deferred` draws "You sign this later" on the route itself rather than
|
|
60
|
-
* hiding the fact in a tooltip — so nothing new had to be invented to show it.
|
|
61
|
-
*
|
|
62
|
-
* WHAT THIS MUST NEVER DO is present the second signature as optional, or let
|
|
63
|
-
* the route claim a delivered amount as though it were settled. The reader is
|
|
64
|
-
* mid-journey until they sign again, and a route that implies otherwise is
|
|
65
|
-
* selling a single-signature experience it does not deliver.
|
|
66
|
-
*/
|
|
67
|
-
/**
|
|
68
|
-
* Turns a token into the display node the route strip draws, resolving its logo
|
|
69
|
-
* here rather than in the view.
|
|
70
|
-
*
|
|
71
|
-
* Pre-resolved deliberately: a view-layer image fallback reaches only the nodes
|
|
72
|
-
* a builder left unset, so a builder that sets the field and a builder that
|
|
73
|
-
* does not produce different pictures for the same token.
|
|
74
|
-
*
|
|
75
|
-
* The chain badge goes through `networkOrPseudo`, not `network` — a deposit-
|
|
76
|
-
* address origin (Zcash) carries a local, invented chain id the numeric
|
|
77
|
-
* endpoint 404s on. See that helper's own note for why this lives in
|
|
78
|
-
* `image-links.ts` rather than the richer client-side resolver.
|
|
79
|
-
*/
|
|
80
42
|
const tokenNode = (token, chainId) => ({
|
|
81
43
|
symbol: token.symbol,
|
|
82
44
|
address: token.address,
|
|
83
45
|
chainId,
|
|
84
46
|
decimals: token.decimals,
|
|
85
|
-
// `tokenImageOrChainFallback`, NOT `image` — the ANCHOR node this call also
|
|
86
|
-
// draws can reach here before its exact address is known (the deferred
|
|
87
|
-
// crossing has not settled yet), and `image` either throws on an address it
|
|
88
|
-
// cannot checksum or draws nothing at all. See that helper's own note.
|
|
89
47
|
logoUri: imageLinks.tokenImageOrChainFallback(token),
|
|
90
48
|
chainLogoUri: imageLinks.networkOrPseudo(chainId),
|
|
91
49
|
});
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
* rather than zero, because zero is a real value that reads as "this leg is
|
|
97
|
-
* free" — which is the one thing a cost figure must never say by accident.
|
|
98
|
-
*/
|
|
50
|
+
const sendOrSwapLabel = (startChainId, endChainId) => startChainId === endChainId
|
|
51
|
+
? `Swap on ${(0, chain_names_js_1.chainDisplayName)(endChainId)}`
|
|
52
|
+
: `Send to ${(0, chain_names_js_1.chainDisplayName)(endChainId)}`;
|
|
53
|
+
exports.sendOrSwapLabel = sendOrSwapLabel;
|
|
99
54
|
const usdNumber = (value) => {
|
|
100
55
|
if (typeof value !== 'string' || value === '') {
|
|
101
56
|
return null;
|
|
@@ -103,41 +58,11 @@ const usdNumber = (value) => {
|
|
|
103
58
|
const parsed = Number(value);
|
|
104
59
|
return Number.isFinite(parsed) ? parsed : null;
|
|
105
60
|
};
|
|
106
|
-
/**
|
|
107
|
-
* Builds the two-signature route for a candidate whose aggregator cannot
|
|
108
|
-
* execute the omnibridge entry call.
|
|
109
|
-
*
|
|
110
|
-
* The result has exactly two sections, and the order carries the meaning:
|
|
111
|
-
*
|
|
112
|
-
* 1. The aggregator's leg, signed NOW. It ends with the anchor token sitting
|
|
113
|
-
* in the reader's own wallet on the entry chain.
|
|
114
|
-
* 2. The omnibridge crossing, marked `deferred`, signed LATER by the reader.
|
|
115
|
-
*
|
|
116
|
-
* COSTS ARE SPLIT BETWEEN THE SECTIONS RATHER THAN POOLED, because a reader
|
|
117
|
-
* deciding whether to accept a second signature needs to know what each half
|
|
118
|
-
* costs. The first section's spread is the difference between the aggregator's
|
|
119
|
-
* own paid and delivered figures — both from the one answer that priced them,
|
|
120
|
-
* never from two feeds. The second section's cost is the omnibridge crossing
|
|
121
|
-
* fee, computed from the known on-chain rate.
|
|
122
|
-
*
|
|
123
|
-
* THE DELIVERED FIGURE IS AN ESTIMATE AND THE INTERFACE KNOWS IT. A route whose
|
|
124
|
-
* last section is deferred has not been quoted end to end, so
|
|
125
|
-
* `outputAmountIsUnsettled` blanks the received-amount field on the reader's
|
|
126
|
-
* behalf. The figure is still carried — the conversion route sets its estimate
|
|
127
|
-
* the same way — so the route can be ranked and compared.
|
|
128
|
-
*
|
|
129
|
-
* @param candidate - the route candidate, which must carry a `deferredCrossing`
|
|
130
|
-
* @returns the two-section route, or null when the candidate names no deferred
|
|
131
|
-
* crossing or no omnibridge provider to perform it
|
|
132
|
-
*/
|
|
133
61
|
const buildNearIntentsTwoStepRouteData = (candidate) => {
|
|
134
62
|
const deferredCrossing = candidate.deferredCrossing;
|
|
135
63
|
if (!deferredCrossing) {
|
|
136
64
|
return null;
|
|
137
65
|
}
|
|
138
|
-
// No omnibridge leg means there is no second signature, which means this is
|
|
139
|
-
// not the shape being built. A route the aggregator carries end to end is an
|
|
140
|
-
// ordinary one-signature route and belongs to `buildCandidateRouteData`.
|
|
141
66
|
const omnibridgeProviderKey = candidate.omnibridgeProvider;
|
|
142
67
|
if (omnibridgeProviderKey === null) {
|
|
143
68
|
return null;
|
|
@@ -149,9 +74,6 @@ const buildNearIntentsTwoStepRouteData = (candidate) => {
|
|
|
149
74
|
const destinationNode = tokenNode(destinationToken, producers_js_1.pulsechainChainId);
|
|
150
75
|
const paidUsd = usdNumber(candidate.quote.fromAmountUsd);
|
|
151
76
|
const landedUsd = usdNumber(anchorUsdValue);
|
|
152
|
-
// The aggregator's spread on its own leg: what the reader paid, less what the
|
|
153
|
-
// aggregator says arrives. Both figures come from the same answer, so the
|
|
154
|
-
// difference is the route and nothing else.
|
|
155
77
|
const aggregatorFeeUsd = (0, producers_js_1.subtractUsdValues)(paidUsd, landedUsd);
|
|
156
78
|
const crossingFeeUsd = (0, usd_value_js_1.usdValueOfAmount)({
|
|
157
79
|
balance: candidate.omnibridgeFeeAmount,
|
|
@@ -163,35 +85,20 @@ const buildNearIntentsTwoStepRouteData = (candidate) => {
|
|
|
163
85
|
? Math.ceil(candidate.quote.executionDurationSeconds / 60)
|
|
164
86
|
: null;
|
|
165
87
|
const aggregatorHop = {
|
|
166
|
-
// THIS HOP IS THE AGGREGATOR, NOT THE OMNIBRIDGE — `providerDisplayName`
|
|
167
|
-
// (used for the crossing hop below) is keyed only on `Providers.PULSECHAIN`
|
|
168
|
-
// / `Providers.TOKENSEX` and falls back to the generic "Omnibridge" for
|
|
169
|
-
// anything else. Run through it here, `candidate.quote.provider` (a
|
|
170
|
-
// `ProviderId` — 'lifi' | 'relay' | 'near-intents') had no entry, so a
|
|
171
|
-
// NEAR Intents two-step route named its first leg "Omnibridge" — the
|
|
172
|
-
// bridge, not the aggregator that actually carried it. `providerById` is
|
|
173
|
-
// total over `ProviderId` and throws on an unregistered one rather than
|
|
174
|
-
// silently naming a different provider.
|
|
175
88
|
providerName: (0, providers_js_1.providerById)(candidate.quote.provider).label,
|
|
176
89
|
providerKey: candidate.quote.provider,
|
|
177
|
-
title:
|
|
90
|
+
title: (0, exports.sendOrSwapLabel)(originToken.chainId, candidate.entryChainId),
|
|
178
91
|
conversion: `→ ${anchorToken.symbol}`,
|
|
179
92
|
fromToken: originNode,
|
|
180
93
|
toToken: anchorNode,
|
|
181
94
|
feeUsdValue: aggregatorFeeUsd,
|
|
182
|
-
// The reader's own signature starts this leg; nothing runs inside it.
|
|
183
95
|
automatic: false,
|
|
184
96
|
};
|
|
185
97
|
const aggregatorSection = {
|
|
186
98
|
id: `${candidate.id}-signature-1`,
|
|
187
|
-
|
|
188
|
-
// PulseChain": this signature does not reach PulseChain and a label that
|
|
189
|
-
// said so would be the single-signature claim this route exists to avoid.
|
|
190
|
-
label: `Send to ${(0, chain_names_js_1.chainDisplayName)(candidate.entryChainId)}`,
|
|
99
|
+
label: (0, exports.sendOrSwapLabel)(originToken.chainId, candidate.entryChainId),
|
|
191
100
|
providerKey: candidate.quote.provider,
|
|
192
101
|
tokenFlow: [originNode, anchorNode],
|
|
193
|
-
// WHAT THE READER IS LEFT HOLDING between the two signatures, in their own
|
|
194
|
-
// wallet on the entry chain. This is the step's whole point.
|
|
195
102
|
landing: {
|
|
196
103
|
amount: anchorAmount,
|
|
197
104
|
decimals: anchorToken.decimals,
|
|
@@ -212,9 +119,6 @@ const buildNearIntentsTwoStepRouteData = (candidate) => {
|
|
|
212
119
|
fromToken: anchorNode,
|
|
213
120
|
toToken: destinationNode,
|
|
214
121
|
feeUsdValue: crossingFeeUsd,
|
|
215
|
-
// NOT automatic, and this is the difference the whole route turns on. On a
|
|
216
|
-
// one-signature route the aggregator's executor makes this call; here the
|
|
217
|
-
// reader does, by hand, after the anchor lands.
|
|
218
122
|
automatic: false,
|
|
219
123
|
};
|
|
220
124
|
const crossingSection = {
|
|
@@ -229,23 +133,8 @@ const buildNearIntentsTwoStepRouteData = (candidate) => {
|
|
|
229
133
|
usdValue: (0, producers_js_1.subtractUsdValues)(landedUsd, crossingFeeUsd),
|
|
230
134
|
},
|
|
231
135
|
feeUsdValue: crossingFeeUsd,
|
|
232
|
-
// THE FLAG THAT MAKES THE ROUTE HONEST. It is what draws "You sign this
|
|
233
|
-
// later" on the step, what makes the primary button name the step it
|
|
234
|
-
// actually signs, and what stops any surface stating the delivered amount
|
|
235
|
-
// as settled. Removing it would turn this into a route that silently
|
|
236
|
-
// promises one signature and asks for two.
|
|
237
136
|
deferred: true,
|
|
238
|
-
// `sectionDescription` in the route strip reads `section.deferredNote ??
|
|
239
|
-
// defaultDeferredNote()`, so a note supplied HERE replaces the default
|
|
240
|
-
// sentence outright rather than adding to it. The default sentence is
|
|
241
|
-
// "Fee is approximate — quoted when you return." — the one fact that
|
|
242
|
-
// tells the reader the output figure they are looking at is not settled.
|
|
243
|
-
// A note that names only the second signature and drops that fact leaves
|
|
244
|
-
// a settled-looking figure on screen with nothing anywhere saying
|
|
245
|
-
// otherwise, so this note must carry BOTH facts itself.
|
|
246
137
|
deferredNote: `The bridge crossing is a second signature you make once the funds arrive on ${(0, chain_names_js_1.chainDisplayName)(candidate.entryChainId)}. The amount shown is approximate and is quoted again when you return.`,
|
|
247
|
-
// The crossing's own settlement wait, which is the long part of the journey
|
|
248
|
-
// and has nothing to do with the aggregator's estimate above.
|
|
249
138
|
etaMinutes: producers_js_1.BRIDGE_SETTLEMENT_ETA_MINUTES,
|
|
250
139
|
hops: [crossingHop],
|
|
251
140
|
};
|
|
@@ -255,42 +144,20 @@ const buildNearIntentsTwoStepRouteData = (candidate) => {
|
|
|
255
144
|
return {
|
|
256
145
|
kind: 'aggregated',
|
|
257
146
|
entryChainId: candidate.entryChainId,
|
|
258
|
-
// Named after the omnibridge, matching the one-signature route: a route is
|
|
259
|
-
// named for the thing that performs its defining leg.
|
|
260
147
|
headlineProviderKey: omnibridgeProviderKey,
|
|
261
148
|
sections: [aggregatorSection, crossingSection],
|
|
262
149
|
output: {
|
|
263
150
|
amount: candidate.deliveredAmount,
|
|
264
151
|
decimals: destinationToken.decimals,
|
|
265
152
|
symbol: destinationToken.symbol,
|
|
266
|
-
// The source basis, carried the whole way: what was paid, less what each
|
|
267
|
-
// leg costs. Re-pricing the delivered token against its own feed would
|
|
268
|
-
// state this route's cost twice and the two would not agree.
|
|
269
153
|
usdValue: (0, producers_js_1.subtractUsdValues)(paidUsd, totalCostUsdValue),
|
|
270
154
|
},
|
|
271
155
|
totalCostUsdValue,
|
|
272
|
-
// Ranked on the same net figure as every other route: delivered value less
|
|
273
|
-
// everything the journey costs.
|
|
274
156
|
netValueUsd: (0, producers_js_1.subtractUsdValues)(paidUsd, totalCostUsdValue),
|
|
275
|
-
// The reader's wait is BOTH legs, not the aggregator's leg alone. A route
|
|
276
|
-
// that reported only the first would claim to finish before its second
|
|
277
|
-
// signature had even been asked for.
|
|
278
157
|
etaMinutes: (etaMinutes ?? 0) + producers_js_1.BRIDGE_SETTLEMENT_ETA_MINUTES,
|
|
279
158
|
};
|
|
280
159
|
};
|
|
281
160
|
exports.buildNearIntentsTwoStepRouteData = buildNearIntentsTwoStepRouteData;
|
|
282
|
-
/**
|
|
283
|
-
* Describes the anchor a two-signature route leaves the reader holding.
|
|
284
|
-
*
|
|
285
|
-
* A small constructor rather than an inline object literal at the call site,
|
|
286
|
-
* so the three fields are named and documented in one place and a caller
|
|
287
|
-
* cannot quietly pair one aggregator's amount with another's valuation.
|
|
288
|
-
*
|
|
289
|
-
* @param options.anchorToken - the entry-chain token the aggregator delivers
|
|
290
|
-
* @param options.anchorAmount - how much of it lands, in its base units
|
|
291
|
-
* @param options.anchorUsdValue - the AGGREGATOR'S own valuation of that landing
|
|
292
|
-
* @returns the deferred-crossing record, or null when no amount is known
|
|
293
|
-
*/
|
|
294
161
|
const describeDeferredCrossing = ({ anchorToken, anchorAmount, anchorUsdValue, }) => {
|
|
295
162
|
if (anchorToken === null) {
|
|
296
163
|
return null;
|