@gibs/bridge-sdk 1.18.0 → 1.19.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/cjs/consolidated-quote.js +3 -0
- package/dist/cjs/near-intents-route.d.ts +13 -0
- package/dist/cjs/near-intents-route.js +19 -3
- package/dist/cjs/routing/candidate-route.d.ts +46 -1
- package/dist/cjs/routing/candidate-route.js +47 -2
- package/dist/cjs/routing/index.d.ts +1 -1
- package/dist/cjs/routing/index.js +3 -2
- package/dist/cjs/routing/search/plan-route-data.js +9 -6
- package/dist/cjs/types.d.ts +8 -0
- package/dist/consolidated-quote.js +3 -0
- package/dist/near-intents-route.d.ts +13 -0
- package/dist/near-intents-route.js +17 -2
- package/dist/routing/candidate-route.d.ts +46 -1
- package/dist/routing/candidate-route.js +45 -1
- package/dist/routing/index.d.ts +1 -1
- package/dist/routing/index.js +1 -1
- package/dist/routing/search/plan-route-data.js +10 -7
- package/dist/types.d.ts +8 -0
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -441,6 +441,39 @@ if (plan.kind === 'refused') throw new Error(plan.refusal.reason);
|
|
|
441
441
|
asked for your wallet, in `sections[i].aggregator`. The candidate's own quote
|
|
442
442
|
priced the route on screen and is never signed.
|
|
443
443
|
|
|
444
|
+
### Counting signatures, approvals included
|
|
445
|
+
|
|
446
|
+
`routeSignatureCount(route)` counts sections only, so a USDC route reads 1 and
|
|
447
|
+
then asks for two prompts. It leaves out approvals. Use
|
|
448
|
+
`routeSignatureCountForAccount` for the number the wallet will really ask for:
|
|
449
|
+
|
|
450
|
+
```ts
|
|
451
|
+
import {
|
|
452
|
+
type AllowanceReader,
|
|
453
|
+
type ResolveNodeToken,
|
|
454
|
+
type RouteCandidate,
|
|
455
|
+
type SectionExecutionInputs,
|
|
456
|
+
routeSignatureCountForAccount,
|
|
457
|
+
} from '@gibs/bridge-sdk';
|
|
458
|
+
import type { Hex } from 'viem';
|
|
459
|
+
|
|
460
|
+
declare const candidate: RouteCandidate;
|
|
461
|
+
declare const account: Hex;
|
|
462
|
+
declare const readAllowance: AllowanceReader;
|
|
463
|
+
declare const resolveToken: ResolveNodeToken;
|
|
464
|
+
declare const sections: SectionExecutionInputs[];
|
|
465
|
+
|
|
466
|
+
const { signatures, approvals, total } = await routeSignatureCountForAccount({
|
|
467
|
+
candidate, account, readAllowance, resolveToken, sections,
|
|
468
|
+
});
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
It takes the inputs `planCandidateExecution` takes and counts the plan, so it
|
|
472
|
+
uses the same allowance rule and the same spender (mediator, swap router, or
|
|
473
|
+
aggregator address). A native input and a covered allowance add no approval. A
|
|
474
|
+
short, non-zero allowance counts two approvals (reset, then approve). It throws
|
|
475
|
+
when a section cannot be planned.
|
|
476
|
+
|
|
444
477
|
## Overriding swap routers
|
|
445
478
|
|
|
446
479
|
The package swaps on PulseX V1 and V2 on PulseChain by default. You can swap on
|
|
@@ -1041,6 +1041,9 @@ const parseLifiTokens = (payload, chainId) => {
|
|
|
1041
1041
|
// Preserve the inline spot price the LI.FI list carries — it is the USD
|
|
1042
1042
|
// price source for aggregator chains (the dapp image lists carry none).
|
|
1043
1043
|
priceUSD: typeof entry.priceUSD === 'string' ? entry.priceUSD : null,
|
|
1044
|
+
// Additive: kept only when LI.FI sends them, so a token without them has the same shape as before.
|
|
1045
|
+
...(typeof entry.coinKey === 'string' ? { coinKey: entry.coinKey } : {}),
|
|
1046
|
+
...(typeof entry.verificationStatus === 'string' ? { verificationStatus: entry.verificationStatus } : {}),
|
|
1044
1047
|
});
|
|
1045
1048
|
}
|
|
1046
1049
|
return parsed;
|
|
@@ -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,7 +33,7 @@ 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");
|
|
@@ -89,6 +89,22 @@ const tokenNode = (token, chainId) => ({
|
|
|
89
89
|
logoUri: imageLinks.tokenImageOrChainFallback(token),
|
|
90
90
|
chainLogoUri: imageLinks.networkOrPseudo(chainId),
|
|
91
91
|
});
|
|
92
|
+
/**
|
|
93
|
+
* The name of a step that starts on one chain and ends on another (or the same).
|
|
94
|
+
*
|
|
95
|
+
* A step whose two chains differ is "Send to {end chain}". A step that never
|
|
96
|
+
* leaves its chain is a swap, so it is "Swap on {chain}". "Send to Ethereum"
|
|
97
|
+
* on a swap that starts and ends on Ethereum names a crossing that never
|
|
98
|
+
* happens.
|
|
99
|
+
*
|
|
100
|
+
* @param startChainId - the chain the step starts on
|
|
101
|
+
* @param endChainId - the chain the step ends on
|
|
102
|
+
* @returns the step's English label
|
|
103
|
+
*/
|
|
104
|
+
const sendOrSwapLabel = (startChainId, endChainId) => startChainId === endChainId
|
|
105
|
+
? `Swap on ${(0, chain_names_js_1.chainDisplayName)(endChainId)}`
|
|
106
|
+
: `Send to ${(0, chain_names_js_1.chainDisplayName)(endChainId)}`;
|
|
107
|
+
exports.sendOrSwapLabel = sendOrSwapLabel;
|
|
92
108
|
/**
|
|
93
109
|
* Parses one of the aggregator's own dollar figures.
|
|
94
110
|
*
|
|
@@ -174,7 +190,7 @@ const buildNearIntentsTwoStepRouteData = (candidate) => {
|
|
|
174
190
|
// silently naming a different provider.
|
|
175
191
|
providerName: (0, providers_js_1.providerById)(candidate.quote.provider).label,
|
|
176
192
|
providerKey: candidate.quote.provider,
|
|
177
|
-
title:
|
|
193
|
+
title: (0, exports.sendOrSwapLabel)(originToken.chainId, candidate.entryChainId),
|
|
178
194
|
conversion: `→ ${anchorToken.symbol}`,
|
|
179
195
|
fromToken: originNode,
|
|
180
196
|
toToken: anchorNode,
|
|
@@ -187,7 +203,7 @@ const buildNearIntentsTwoStepRouteData = (candidate) => {
|
|
|
187
203
|
// Named for where the funds END UP, and pointedly NOT "Bridge to
|
|
188
204
|
// PulseChain": this signature does not reach PulseChain and a label that
|
|
189
205
|
// said so would be the single-signature claim this route exists to avoid.
|
|
190
|
-
label:
|
|
206
|
+
label: (0, exports.sendOrSwapLabel)(originToken.chainId, candidate.entryChainId),
|
|
191
207
|
providerKey: candidate.quote.provider,
|
|
192
208
|
tokenFlow: [originNode, anchorNode],
|
|
193
209
|
// WHAT THE READER IS LEFT HOLDING between the two signatures, in their own
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type CandidateExecutionInputs } from '../execution.js';
|
|
1
2
|
import type { RouteCandidate } from './candidate.js';
|
|
2
3
|
import type { RouteData } from './route-data.js';
|
|
3
4
|
/**
|
|
@@ -37,7 +38,51 @@ export declare const buildRouteDataForCandidate: (candidate: RouteCandidate) =>
|
|
|
37
38
|
* site, so a surface that warns about a long journey and a surface that ranks
|
|
38
39
|
* routes cannot come to different counts.
|
|
39
40
|
*
|
|
41
|
+
* THIS COUNT LEAVES OUT APPROVALS. A token that is not the chain's native coin
|
|
42
|
+
* needs an `approve` transaction before its first section when the allowance
|
|
43
|
+
* is too small, and that approval is a signature too. Raw route data does not
|
|
44
|
+
* say who the spender is or what the account has approved already, so this
|
|
45
|
+
* function cannot count it. Use {@link routeSignatureCountForAccount} for the
|
|
46
|
+
* number the wallet will really ask for.
|
|
47
|
+
*
|
|
40
48
|
* @param route - the raw route data
|
|
41
|
-
* @returns the number of signatures, one per section
|
|
49
|
+
* @returns the number of signatures, one per section, with no approvals
|
|
42
50
|
*/
|
|
43
51
|
export declare const routeSignatureCount: (route: RouteData) => number;
|
|
52
|
+
/** What {@link routeSignatureCountForAccount} reports. */
|
|
53
|
+
export type RouteSignatureCount = {
|
|
54
|
+
/** Signatures for the sections themselves: one per planned section. */
|
|
55
|
+
readonly signatures: number;
|
|
56
|
+
/** Approval transactions the account must sign first, given what it has approved already. */
|
|
57
|
+
readonly approvals: number;
|
|
58
|
+
/** `signatures + approvals`: every wallet prompt the planned sections cause. */
|
|
59
|
+
readonly total: number;
|
|
60
|
+
};
|
|
61
|
+
/**
|
|
62
|
+
* How many wallet signatures a route asks one account for, approvals included.
|
|
63
|
+
*
|
|
64
|
+
* {@link routeSignatureCount} counts sections only, so a USDC route reads "1"
|
|
65
|
+
* and then asks for two prompts: approve, then send. This function plans the
|
|
66
|
+
* sections with {@link planCandidateExecution} and counts what that plan
|
|
67
|
+
* contains, so it uses the same allowance rule and the same spender the
|
|
68
|
+
* execution planner uses. A native input needs no approval. An allowance that
|
|
69
|
+
* already covers the amount needs none. A smaller, non-zero allowance counts
|
|
70
|
+
* the reset and the new approval, the two transactions the planner emits. The
|
|
71
|
+
* spender is whatever the planner picks: the omnibridge mediator, a swap
|
|
72
|
+
* venue's router (including routers passed in `swapVenues`), or the
|
|
73
|
+
* aggregator's approval address.
|
|
74
|
+
*
|
|
75
|
+
* Pass every section of the route to count the whole route. Pass fewer to
|
|
76
|
+
* count only the window you plan now; each section is counted against the
|
|
77
|
+
* allowance on chain today, so a later section that spends a token an earlier
|
|
78
|
+
* section delivers is counted as if the approval is still needed.
|
|
79
|
+
*
|
|
80
|
+
* An aggregator section needs its `aggregator` inputs, a quote and the request
|
|
81
|
+
* it answered, exactly as {@link planCandidateExecution} does. Without them
|
|
82
|
+
* this function throws, because the approval spender comes from that quote.
|
|
83
|
+
*
|
|
84
|
+
* @param inputs - the same inputs {@link planCandidateExecution} takes
|
|
85
|
+
* @returns the signatures, approvals, and their total
|
|
86
|
+
* @throws when a section cannot be planned; the message names the section and the reason
|
|
87
|
+
*/
|
|
88
|
+
export declare const routeSignatureCountForAccount: (inputs: CandidateExecutionInputs) => Promise<RouteSignatureCount>;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.routeSignatureCount = exports.buildRouteDataForCandidate = void 0;
|
|
3
|
+
exports.routeSignatureCountForAccount = exports.routeSignatureCount = exports.buildRouteDataForCandidate = void 0;
|
|
4
4
|
const near_intents_route_js_1 = require("../near-intents-route.js");
|
|
5
|
+
const execution_js_1 = require("../execution.js");
|
|
5
6
|
const producers_js_1 = require("./producers.js");
|
|
6
7
|
/**
|
|
7
8
|
* One door in front of the two base route builders.
|
|
@@ -43,8 +44,52 @@ exports.buildRouteDataForCandidate = buildRouteDataForCandidate;
|
|
|
43
44
|
* site, so a surface that warns about a long journey and a surface that ranks
|
|
44
45
|
* routes cannot come to different counts.
|
|
45
46
|
*
|
|
47
|
+
* THIS COUNT LEAVES OUT APPROVALS. A token that is not the chain's native coin
|
|
48
|
+
* needs an `approve` transaction before its first section when the allowance
|
|
49
|
+
* is too small, and that approval is a signature too. Raw route data does not
|
|
50
|
+
* say who the spender is or what the account has approved already, so this
|
|
51
|
+
* function cannot count it. Use {@link routeSignatureCountForAccount} for the
|
|
52
|
+
* number the wallet will really ask for.
|
|
53
|
+
*
|
|
46
54
|
* @param route - the raw route data
|
|
47
|
-
* @returns the number of signatures, one per section
|
|
55
|
+
* @returns the number of signatures, one per section, with no approvals
|
|
48
56
|
*/
|
|
49
57
|
const routeSignatureCount = (route) => route.sections.length;
|
|
50
58
|
exports.routeSignatureCount = routeSignatureCount;
|
|
59
|
+
/**
|
|
60
|
+
* How many wallet signatures a route asks one account for, approvals included.
|
|
61
|
+
*
|
|
62
|
+
* {@link routeSignatureCount} counts sections only, so a USDC route reads "1"
|
|
63
|
+
* and then asks for two prompts: approve, then send. This function plans the
|
|
64
|
+
* sections with {@link planCandidateExecution} and counts what that plan
|
|
65
|
+
* contains, so it uses the same allowance rule and the same spender the
|
|
66
|
+
* execution planner uses. A native input needs no approval. An allowance that
|
|
67
|
+
* already covers the amount needs none. A smaller, non-zero allowance counts
|
|
68
|
+
* the reset and the new approval, the two transactions the planner emits. The
|
|
69
|
+
* spender is whatever the planner picks: the omnibridge mediator, a swap
|
|
70
|
+
* venue's router (including routers passed in `swapVenues`), or the
|
|
71
|
+
* aggregator's approval address.
|
|
72
|
+
*
|
|
73
|
+
* Pass every section of the route to count the whole route. Pass fewer to
|
|
74
|
+
* count only the window you plan now; each section is counted against the
|
|
75
|
+
* allowance on chain today, so a later section that spends a token an earlier
|
|
76
|
+
* section delivers is counted as if the approval is still needed.
|
|
77
|
+
*
|
|
78
|
+
* An aggregator section needs its `aggregator` inputs, a quote and the request
|
|
79
|
+
* it answered, exactly as {@link planCandidateExecution} does. Without them
|
|
80
|
+
* this function throws, because the approval spender comes from that quote.
|
|
81
|
+
*
|
|
82
|
+
* @param inputs - the same inputs {@link planCandidateExecution} takes
|
|
83
|
+
* @returns the signatures, approvals, and their total
|
|
84
|
+
* @throws when a section cannot be planned; the message names the section and the reason
|
|
85
|
+
*/
|
|
86
|
+
const routeSignatureCountForAccount = async (inputs) => {
|
|
87
|
+
const plan = await (0, execution_js_1.planCandidateExecution)(inputs);
|
|
88
|
+
if (plan.kind === 'refused') {
|
|
89
|
+
throw new Error(`Cannot count signatures: section ${plan.sectionIndex} cannot be planned (${JSON.stringify(plan.refusal)}).`);
|
|
90
|
+
}
|
|
91
|
+
const approvals = plan.transactions.filter((transaction) => transaction.kind === 'approve').length;
|
|
92
|
+
const signatures = plan.transactions.length - approvals;
|
|
93
|
+
return { signatures, approvals, total: plan.transactions.length };
|
|
94
|
+
};
|
|
95
|
+
exports.routeSignatureCountForAccount = routeSignatureCountForAccount;
|
|
@@ -8,7 +8,7 @@ export { netDeliveredAmount, restateInDecimals, valueEquivalentAmount } from './
|
|
|
8
8
|
export { omnibridgeProviderForEntryChain, pulseXConversionSwapPath } from './providers.js';
|
|
9
9
|
export { buildDirectCrossingCandidate } from './candidate.js';
|
|
10
10
|
export type { RouteCandidate, DeferredCrossing, DirectCrossingCandidateInputs } from './candidate.js';
|
|
11
|
-
export { buildRouteDataForCandidate, routeSignatureCount } from './candidate-route.js';
|
|
11
|
+
export { buildRouteDataForCandidate, routeSignatureCount, routeSignatureCountForAccount, type RouteSignatureCount, } from './candidate-route.js';
|
|
12
12
|
export { COMPOSED_ROUTE_MAX_PRICE_IMPACT_PERCENT, COMPOSED_ROUTE_MAX_VALUE_GAIN_PERCENT, COMPOSED_ROUTE_MAX_VALUE_LOSS_PERCENT, assessComposedRoute, composedRouteMayBeOffered, } from './composed-route-quality.js';
|
|
13
13
|
export type { ComposedRouteVerdict } from './composed-route-quality.js';
|
|
14
14
|
export { entryChainAnchorsForPair } from './entry-chain-anchor.js';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
exports.swapMinimumOut = exports.buildWrapTransaction = exports.buildPulseXSwapTransaction = exports.createWrapCarrier = exports.resolveSwapVenues = exports.findSwapVenue = exports.pulseXHubTokens = exports.candidatePulseXPaths = exports.bestPulseXPathQuote = exports.pulseXWrappedNativePath = exports.pulseXVenues = exports.pulseXSwapPathForHop = exports.venueForEdge = exports.pulseXRouterForEdge = exports.createPulseXCarrier = exports.withOmnibridgeEntryFusing = exports.createOmnibridgeCarrier = exports.derivePlanKind = exports.deriveViaChainIdsFromPlan = exports.deriveOmnibridgeProviderFromPlan = exports.deriveEntryChainIdFromPlan = exports.deriveDeferredCrossingFromPlan = exports.buildRouteScoreInputsFromPlan = exports.buildRouteDataFromPlan = exports.buildRouteCandidateFromPlan = exports.carrierStepKind = exports.carrierProviderKey = exports.WRAP_CARRIER_ID = exports.zeroGasCostFor = exports.waitPenaltyPpm = exports.sectionIsFundedByLanding = exports.scoreRoutePlan = exports.gasAdjustedDeliveredAmount = exports.compareRoutePlansByScoreAdjustedDeliveredAmount = exports.compareRoutePlansByGasAdjustedDeliveredAmount = exports.SIGNATURE_PENALTY_PPM = exports.SIGNATURE_PENALTY_FLOOR_USD = exports.GAS_TOPUP_PENALTY_PPM = exports.GAS_TOPUP_PENALTY_FLOOR_USD = exports.hopOutputAmount = void 0;
|
|
3
|
+
exports.composableHopBasis = exports.routePlanPathKey = exports.planIsRankable = exports.planIsConfirmed = exports.planComposedBasis = exports.isRateLimitedCarrier = exports.isRankableBasis = exports.isConfirmedBasis = exports.hopEdgeKey = exports.hopComposedBasis = exports.groupHopsBySignature = exports.compareRoutePlansByDeliveredAmount = exports.combineComposedPathBasis = exports.assetNodeKey = exports.RANKABLE_ESTIMATE_BASES = exports.candidatePaidUsd = exports.candidateOutsideFeesUsd = exports.candidateNetValueUsd = exports.candidateDeliveredUsd = exports.buildSameChainSwapRouteData = exports.buildOutboundRouteData = exports.buildPulseXSwapSectionData = exports.buildPulseXSwapEstimateData = exports.buildDirectRouteData = exports.buildConversionRouteData = exports.buildCandidateRouteData = exports.resolveEntryChainName = exports.providerDisplayName = exports.addUsdValues = exports.pulsechainChainId = exports.PULSEX_MARGINAL_REFERENCE_DIVISOR = exports.BRIDGE_SETTLEMENT_ETA_MINUTES = exports.formatUsdNullable = exports.formatUsd = exports.usdValueOfAmount = exports.entryChainAnchorsForPair = exports.composedRouteMayBeOffered = exports.assessComposedRoute = exports.COMPOSED_ROUTE_MAX_VALUE_LOSS_PERCENT = exports.COMPOSED_ROUTE_MAX_VALUE_GAIN_PERCENT = exports.COMPOSED_ROUTE_MAX_PRICE_IMPACT_PERCENT = exports.routeSignatureCountForAccount = exports.routeSignatureCount = exports.buildRouteDataForCandidate = exports.buildDirectCrossingCandidate = exports.pulseXConversionSwapPath = exports.omnibridgeProviderForEntryChain = exports.valueEquivalentAmount = exports.restateInDecimals = exports.netDeliveredAmount = void 0;
|
|
4
|
+
exports.swapMinimumOut = exports.buildWrapTransaction = exports.buildPulseXSwapTransaction = exports.createWrapCarrier = exports.resolveSwapVenues = exports.findSwapVenue = exports.pulseXHubTokens = exports.candidatePulseXPaths = exports.bestPulseXPathQuote = exports.pulseXWrappedNativePath = exports.pulseXVenues = exports.pulseXSwapPathForHop = exports.venueForEdge = exports.pulseXRouterForEdge = exports.createPulseXCarrier = exports.withOmnibridgeEntryFusing = exports.createOmnibridgeCarrier = exports.derivePlanKind = exports.deriveViaChainIdsFromPlan = exports.deriveOmnibridgeProviderFromPlan = exports.deriveEntryChainIdFromPlan = exports.deriveDeferredCrossingFromPlan = exports.buildRouteScoreInputsFromPlan = exports.buildRouteDataFromPlan = exports.buildRouteCandidateFromPlan = exports.carrierStepKind = exports.carrierProviderKey = exports.WRAP_CARRIER_ID = exports.zeroGasCostFor = exports.waitPenaltyPpm = exports.sectionIsFundedByLanding = exports.scoreRoutePlan = exports.gasAdjustedDeliveredAmount = exports.compareRoutePlansByScoreAdjustedDeliveredAmount = exports.compareRoutePlansByGasAdjustedDeliveredAmount = exports.SIGNATURE_PENALTY_PPM = exports.SIGNATURE_PENALTY_FLOOR_USD = exports.GAS_TOPUP_PENALTY_PPM = exports.GAS_TOPUP_PENALTY_FLOOR_USD = exports.hopOutputAmount = exports.composeRouteDelivery = void 0;
|
|
5
5
|
/**
|
|
6
6
|
* Framework-agnostic routing core for the Gibs bridge. Holds the raw numeric
|
|
7
7
|
* primitives, the candidate shape, and candidate construction — none of which
|
|
@@ -20,6 +20,7 @@ Object.defineProperty(exports, "buildDirectCrossingCandidate", { enumerable: tru
|
|
|
20
20
|
var candidate_route_js_1 = require("./candidate-route.js");
|
|
21
21
|
Object.defineProperty(exports, "buildRouteDataForCandidate", { enumerable: true, get: function () { return candidate_route_js_1.buildRouteDataForCandidate; } });
|
|
22
22
|
Object.defineProperty(exports, "routeSignatureCount", { enumerable: true, get: function () { return candidate_route_js_1.routeSignatureCount; } });
|
|
23
|
+
Object.defineProperty(exports, "routeSignatureCountForAccount", { enumerable: true, get: function () { return candidate_route_js_1.routeSignatureCountForAccount; } });
|
|
23
24
|
var composed_route_quality_js_1 = require("./composed-route-quality.js");
|
|
24
25
|
Object.defineProperty(exports, "COMPOSED_ROUTE_MAX_PRICE_IMPACT_PERCENT", { enumerable: true, get: function () { return composed_route_quality_js_1.COMPOSED_ROUTE_MAX_PRICE_IMPACT_PERCENT; } });
|
|
25
26
|
Object.defineProperty(exports, "COMPOSED_ROUTE_MAX_VALUE_GAIN_PERCENT", { enumerable: true, get: function () { return composed_route_quality_js_1.COMPOSED_ROUTE_MAX_VALUE_GAIN_PERCENT; } });
|
|
@@ -215,6 +215,8 @@ const groupEndsWithBridgeHop = (hops) => isBridgeCarrier(hops[hops.length - 1].e
|
|
|
215
215
|
* section, in BOTH its shapes (the entry-chain swap and the onward
|
|
216
216
|
* aggregator hop) — the section label names where the journey finishes
|
|
217
217
|
* regardless of which service carries the last leg.
|
|
218
|
+
* - **"Swap on {X}"** — a group of the "Send to" shape whose first hop starts
|
|
219
|
+
* on the chain its last hop ends on: nothing is sent anywhere.
|
|
218
220
|
* - **"Send to {X}"** — every other case: a non-final, non-bridge-ending
|
|
219
221
|
* group. Matches `buildNearIntentsTwoStepRouteData`'s first section.
|
|
220
222
|
*
|
|
@@ -236,7 +238,7 @@ const sectionLabel = (group, groupIndex, plan) => {
|
|
|
236
238
|
if (isFinalGroup) {
|
|
237
239
|
return `Complete at ${(0, chain_names_js_1.chainDisplayName)(destinationChainId)}`;
|
|
238
240
|
}
|
|
239
|
-
return
|
|
241
|
+
return (0, near_intents_route_js_1.sendOrSwapLabel)(hops[0].edge.from.chainId, destinationChainId);
|
|
240
242
|
};
|
|
241
243
|
// ---------------------------------------------------------------------------
|
|
242
244
|
// Hop-level rendering
|
|
@@ -291,7 +293,8 @@ const hopProviderName = (carrier) => {
|
|
|
291
293
|
* `"Bridge to {toChainName}"` (matches `buildOutboundRouteData`'s onward
|
|
292
294
|
* hop, which names the chain it finishes on even though an aggregator,
|
|
293
295
|
* not the omnibridge, carries it);
|
|
294
|
-
* - any other aggregator hop (something follows it) → `"Send to {toChainName}"
|
|
296
|
+
* - any other aggregator hop (something follows it) → `"Send to {toChainName}"`,
|
|
297
|
+
* or `"Swap on {chainName}"` when the hop starts and ends on one chain
|
|
295
298
|
* (matches `buildNearIntentsTwoStepRouteData`'s aggregator hop).
|
|
296
299
|
*
|
|
297
300
|
* @param hop - the hop to title
|
|
@@ -310,10 +313,10 @@ const hopTitle = (hop, hopIndex, plan, resolveToken) => {
|
|
|
310
313
|
if (carrier === 'PulseX') {
|
|
311
314
|
return `Swap to ${resolveToken(hop.edge.to).symbol}`;
|
|
312
315
|
}
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
316
|
+
if (isFinalHopOfPlan(hopIndex, plan)) {
|
|
317
|
+
return `Bridge to ${(0, chain_names_js_1.chainDisplayName)(hop.edge.to.chainId)}`;
|
|
318
|
+
}
|
|
319
|
+
return (0, near_intents_route_js_1.sendOrSwapLabel)(hop.edge.from.chainId, hop.edge.to.chainId);
|
|
317
320
|
};
|
|
318
321
|
/**
|
|
319
322
|
* A hop's conversion subtitle.
|
package/dist/cjs/types.d.ts
CHANGED
|
@@ -30,6 +30,14 @@ export type Token = TokenMetadata & {
|
|
|
30
30
|
* that carry no price (e.g. the dapp image lists).
|
|
31
31
|
*/
|
|
32
32
|
priceUSD?: string | null;
|
|
33
|
+
/**
|
|
34
|
+
* LI.FI's `coinKey`: a short key naming the asset across chains (for example
|
|
35
|
+
* "USDC"). Present only on tokens parsed from a LI.FI list that carries one.
|
|
36
|
+
* LI.FI repeats some keys within one chain, so a key alone is not an identity.
|
|
37
|
+
*/
|
|
38
|
+
coinKey?: string;
|
|
39
|
+
/** LI.FI's `verificationStatus` (for example "verified"). Present only on tokens parsed from a LI.FI list that carries one. */
|
|
40
|
+
verificationStatus?: string;
|
|
33
41
|
};
|
|
34
42
|
/** The token out for a given asset */
|
|
35
43
|
export type TokenOut = Omit<Token, 'address'> & {
|
|
@@ -1025,6 +1025,9 @@ export const parseLifiTokens = (payload, chainId) => {
|
|
|
1025
1025
|
// Preserve the inline spot price the LI.FI list carries — it is the USD
|
|
1026
1026
|
// price source for aggregator chains (the dapp image lists carry none).
|
|
1027
1027
|
priceUSD: typeof entry.priceUSD === 'string' ? entry.priceUSD : null,
|
|
1028
|
+
// Additive: kept only when LI.FI sends them, so a token without them has the same shape as before.
|
|
1029
|
+
...(typeof entry.coinKey === 'string' ? { coinKey: entry.coinKey } : {}),
|
|
1030
|
+
...(typeof entry.verificationStatus === 'string' ? { verificationStatus: entry.verificationStatus } : {}),
|
|
1028
1031
|
});
|
|
1029
1032
|
}
|
|
1030
1033
|
return parsed;
|
|
@@ -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.
|
|
@@ -53,6 +53,21 @@ const tokenNode = (token, chainId) => ({
|
|
|
53
53
|
logoUri: imageLinks.tokenImageOrChainFallback(token),
|
|
54
54
|
chainLogoUri: imageLinks.networkOrPseudo(chainId),
|
|
55
55
|
});
|
|
56
|
+
/**
|
|
57
|
+
* The name of a step that starts on one chain and ends on another (or the same).
|
|
58
|
+
*
|
|
59
|
+
* A step whose two chains differ is "Send to {end chain}". A step that never
|
|
60
|
+
* leaves its chain is a swap, so it is "Swap on {chain}". "Send to Ethereum"
|
|
61
|
+
* on a swap that starts and ends on Ethereum names a crossing that never
|
|
62
|
+
* happens.
|
|
63
|
+
*
|
|
64
|
+
* @param startChainId - the chain the step starts on
|
|
65
|
+
* @param endChainId - the chain the step ends on
|
|
66
|
+
* @returns the step's English label
|
|
67
|
+
*/
|
|
68
|
+
export const sendOrSwapLabel = (startChainId, endChainId) => startChainId === endChainId
|
|
69
|
+
? `Swap on ${chainDisplayName(endChainId)}`
|
|
70
|
+
: `Send to ${chainDisplayName(endChainId)}`;
|
|
56
71
|
/**
|
|
57
72
|
* Parses one of the aggregator's own dollar figures.
|
|
58
73
|
*
|
|
@@ -138,7 +153,7 @@ export const buildNearIntentsTwoStepRouteData = (candidate) => {
|
|
|
138
153
|
// silently naming a different provider.
|
|
139
154
|
providerName: providerById(candidate.quote.provider).label,
|
|
140
155
|
providerKey: candidate.quote.provider,
|
|
141
|
-
title:
|
|
156
|
+
title: sendOrSwapLabel(originToken.chainId, candidate.entryChainId),
|
|
142
157
|
conversion: `→ ${anchorToken.symbol}`,
|
|
143
158
|
fromToken: originNode,
|
|
144
159
|
toToken: anchorNode,
|
|
@@ -151,7 +166,7 @@ export const buildNearIntentsTwoStepRouteData = (candidate) => {
|
|
|
151
166
|
// Named for where the funds END UP, and pointedly NOT "Bridge to
|
|
152
167
|
// PulseChain": this signature does not reach PulseChain and a label that
|
|
153
168
|
// said so would be the single-signature claim this route exists to avoid.
|
|
154
|
-
label:
|
|
169
|
+
label: sendOrSwapLabel(originToken.chainId, candidate.entryChainId),
|
|
155
170
|
providerKey: candidate.quote.provider,
|
|
156
171
|
tokenFlow: [originNode, anchorNode],
|
|
157
172
|
// WHAT THE READER IS LEFT HOLDING between the two signatures, in their own
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type CandidateExecutionInputs } from '../execution.js';
|
|
1
2
|
import type { RouteCandidate } from './candidate.js';
|
|
2
3
|
import type { RouteData } from './route-data.js';
|
|
3
4
|
/**
|
|
@@ -37,7 +38,51 @@ export declare const buildRouteDataForCandidate: (candidate: RouteCandidate) =>
|
|
|
37
38
|
* site, so a surface that warns about a long journey and a surface that ranks
|
|
38
39
|
* routes cannot come to different counts.
|
|
39
40
|
*
|
|
41
|
+
* THIS COUNT LEAVES OUT APPROVALS. A token that is not the chain's native coin
|
|
42
|
+
* needs an `approve` transaction before its first section when the allowance
|
|
43
|
+
* is too small, and that approval is a signature too. Raw route data does not
|
|
44
|
+
* say who the spender is or what the account has approved already, so this
|
|
45
|
+
* function cannot count it. Use {@link routeSignatureCountForAccount} for the
|
|
46
|
+
* number the wallet will really ask for.
|
|
47
|
+
*
|
|
40
48
|
* @param route - the raw route data
|
|
41
|
-
* @returns the number of signatures, one per section
|
|
49
|
+
* @returns the number of signatures, one per section, with no approvals
|
|
42
50
|
*/
|
|
43
51
|
export declare const routeSignatureCount: (route: RouteData) => number;
|
|
52
|
+
/** What {@link routeSignatureCountForAccount} reports. */
|
|
53
|
+
export type RouteSignatureCount = {
|
|
54
|
+
/** Signatures for the sections themselves: one per planned section. */
|
|
55
|
+
readonly signatures: number;
|
|
56
|
+
/** Approval transactions the account must sign first, given what it has approved already. */
|
|
57
|
+
readonly approvals: number;
|
|
58
|
+
/** `signatures + approvals`: every wallet prompt the planned sections cause. */
|
|
59
|
+
readonly total: number;
|
|
60
|
+
};
|
|
61
|
+
/**
|
|
62
|
+
* How many wallet signatures a route asks one account for, approvals included.
|
|
63
|
+
*
|
|
64
|
+
* {@link routeSignatureCount} counts sections only, so a USDC route reads "1"
|
|
65
|
+
* and then asks for two prompts: approve, then send. This function plans the
|
|
66
|
+
* sections with {@link planCandidateExecution} and counts what that plan
|
|
67
|
+
* contains, so it uses the same allowance rule and the same spender the
|
|
68
|
+
* execution planner uses. A native input needs no approval. An allowance that
|
|
69
|
+
* already covers the amount needs none. A smaller, non-zero allowance counts
|
|
70
|
+
* the reset and the new approval, the two transactions the planner emits. The
|
|
71
|
+
* spender is whatever the planner picks: the omnibridge mediator, a swap
|
|
72
|
+
* venue's router (including routers passed in `swapVenues`), or the
|
|
73
|
+
* aggregator's approval address.
|
|
74
|
+
*
|
|
75
|
+
* Pass every section of the route to count the whole route. Pass fewer to
|
|
76
|
+
* count only the window you plan now; each section is counted against the
|
|
77
|
+
* allowance on chain today, so a later section that spends a token an earlier
|
|
78
|
+
* section delivers is counted as if the approval is still needed.
|
|
79
|
+
*
|
|
80
|
+
* An aggregator section needs its `aggregator` inputs, a quote and the request
|
|
81
|
+
* it answered, exactly as {@link planCandidateExecution} does. Without them
|
|
82
|
+
* this function throws, because the approval spender comes from that quote.
|
|
83
|
+
*
|
|
84
|
+
* @param inputs - the same inputs {@link planCandidateExecution} takes
|
|
85
|
+
* @returns the signatures, approvals, and their total
|
|
86
|
+
* @throws when a section cannot be planned; the message names the section and the reason
|
|
87
|
+
*/
|
|
88
|
+
export declare const routeSignatureCountForAccount: (inputs: CandidateExecutionInputs) => Promise<RouteSignatureCount>;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { buildNearIntentsTwoStepRouteData } from '../near-intents-route.js';
|
|
2
|
+
import { planCandidateExecution } from '../execution.js';
|
|
2
3
|
import { buildCandidateRouteData } from './producers.js';
|
|
3
4
|
/**
|
|
4
5
|
* One door in front of the two base route builders.
|
|
@@ -39,7 +40,50 @@ export const buildRouteDataForCandidate = (candidate) => candidate.deferredCross
|
|
|
39
40
|
* site, so a surface that warns about a long journey and a surface that ranks
|
|
40
41
|
* routes cannot come to different counts.
|
|
41
42
|
*
|
|
43
|
+
* THIS COUNT LEAVES OUT APPROVALS. A token that is not the chain's native coin
|
|
44
|
+
* needs an `approve` transaction before its first section when the allowance
|
|
45
|
+
* is too small, and that approval is a signature too. Raw route data does not
|
|
46
|
+
* say who the spender is or what the account has approved already, so this
|
|
47
|
+
* function cannot count it. Use {@link routeSignatureCountForAccount} for the
|
|
48
|
+
* number the wallet will really ask for.
|
|
49
|
+
*
|
|
42
50
|
* @param route - the raw route data
|
|
43
|
-
* @returns the number of signatures, one per section
|
|
51
|
+
* @returns the number of signatures, one per section, with no approvals
|
|
44
52
|
*/
|
|
45
53
|
export const routeSignatureCount = (route) => route.sections.length;
|
|
54
|
+
/**
|
|
55
|
+
* How many wallet signatures a route asks one account for, approvals included.
|
|
56
|
+
*
|
|
57
|
+
* {@link routeSignatureCount} counts sections only, so a USDC route reads "1"
|
|
58
|
+
* and then asks for two prompts: approve, then send. This function plans the
|
|
59
|
+
* sections with {@link planCandidateExecution} and counts what that plan
|
|
60
|
+
* contains, so it uses the same allowance rule and the same spender the
|
|
61
|
+
* execution planner uses. A native input needs no approval. An allowance that
|
|
62
|
+
* already covers the amount needs none. A smaller, non-zero allowance counts
|
|
63
|
+
* the reset and the new approval, the two transactions the planner emits. The
|
|
64
|
+
* spender is whatever the planner picks: the omnibridge mediator, a swap
|
|
65
|
+
* venue's router (including routers passed in `swapVenues`), or the
|
|
66
|
+
* aggregator's approval address.
|
|
67
|
+
*
|
|
68
|
+
* Pass every section of the route to count the whole route. Pass fewer to
|
|
69
|
+
* count only the window you plan now; each section is counted against the
|
|
70
|
+
* allowance on chain today, so a later section that spends a token an earlier
|
|
71
|
+
* section delivers is counted as if the approval is still needed.
|
|
72
|
+
*
|
|
73
|
+
* An aggregator section needs its `aggregator` inputs, a quote and the request
|
|
74
|
+
* it answered, exactly as {@link planCandidateExecution} does. Without them
|
|
75
|
+
* this function throws, because the approval spender comes from that quote.
|
|
76
|
+
*
|
|
77
|
+
* @param inputs - the same inputs {@link planCandidateExecution} takes
|
|
78
|
+
* @returns the signatures, approvals, and their total
|
|
79
|
+
* @throws when a section cannot be planned; the message names the section and the reason
|
|
80
|
+
*/
|
|
81
|
+
export const routeSignatureCountForAccount = async (inputs) => {
|
|
82
|
+
const plan = await planCandidateExecution(inputs);
|
|
83
|
+
if (plan.kind === 'refused') {
|
|
84
|
+
throw new Error(`Cannot count signatures: section ${plan.sectionIndex} cannot be planned (${JSON.stringify(plan.refusal)}).`);
|
|
85
|
+
}
|
|
86
|
+
const approvals = plan.transactions.filter((transaction) => transaction.kind === 'approve').length;
|
|
87
|
+
const signatures = plan.transactions.length - approvals;
|
|
88
|
+
return { signatures, approvals, total: plan.transactions.length };
|
|
89
|
+
};
|
package/dist/routing/index.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ export { netDeliveredAmount, restateInDecimals, valueEquivalentAmount } from './
|
|
|
8
8
|
export { omnibridgeProviderForEntryChain, pulseXConversionSwapPath } from './providers.js';
|
|
9
9
|
export { buildDirectCrossingCandidate } from './candidate.js';
|
|
10
10
|
export type { RouteCandidate, DeferredCrossing, DirectCrossingCandidateInputs } from './candidate.js';
|
|
11
|
-
export { buildRouteDataForCandidate, routeSignatureCount } from './candidate-route.js';
|
|
11
|
+
export { buildRouteDataForCandidate, routeSignatureCount, routeSignatureCountForAccount, type RouteSignatureCount, } from './candidate-route.js';
|
|
12
12
|
export { COMPOSED_ROUTE_MAX_PRICE_IMPACT_PERCENT, COMPOSED_ROUTE_MAX_VALUE_GAIN_PERCENT, COMPOSED_ROUTE_MAX_VALUE_LOSS_PERCENT, assessComposedRoute, composedRouteMayBeOffered, } from './composed-route-quality.js';
|
|
13
13
|
export type { ComposedRouteVerdict } from './composed-route-quality.js';
|
|
14
14
|
export { entryChainAnchorsForPair } from './entry-chain-anchor.js';
|
package/dist/routing/index.js
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
export { netDeliveredAmount, restateInDecimals, valueEquivalentAmount } from './amounts.js';
|
|
8
8
|
export { omnibridgeProviderForEntryChain, pulseXConversionSwapPath } from './providers.js';
|
|
9
9
|
export { buildDirectCrossingCandidate } from './candidate.js';
|
|
10
|
-
export { buildRouteDataForCandidate, routeSignatureCount } from './candidate-route.js';
|
|
10
|
+
export { buildRouteDataForCandidate, routeSignatureCount, routeSignatureCountForAccount, } from './candidate-route.js';
|
|
11
11
|
export { COMPOSED_ROUTE_MAX_PRICE_IMPACT_PERCENT, COMPOSED_ROUTE_MAX_VALUE_GAIN_PERCENT, COMPOSED_ROUTE_MAX_VALUE_LOSS_PERCENT, assessComposedRoute, composedRouteMayBeOffered, } from './composed-route-quality.js';
|
|
12
12
|
export { entryChainAnchorsForPair } from './entry-chain-anchor.js';
|
|
13
13
|
export { usdValueOfAmount } from './usd-value.js';
|
|
@@ -2,7 +2,7 @@ import * as imageLinks from '../../image-links.js';
|
|
|
2
2
|
import { chainDisplayName } from '../../chain-names.js';
|
|
3
3
|
import { findProviderById } from '../../providers.js';
|
|
4
4
|
import { WRAP_CARRIER_ID, carrierProviderKey, carrierStepKind } from '../carrier-provider-key.js';
|
|
5
|
-
import { describeDeferredCrossing } from '../../near-intents-route.js';
|
|
5
|
+
import { describeDeferredCrossing, sendOrSwapLabel } from '../../near-intents-route.js';
|
|
6
6
|
import { candidateDeliveredUsd, candidateOutsideFeesUsd, candidatePaidUsd, pulsechainChainId, providerDisplayName, } from '../producers.js';
|
|
7
7
|
import { assetNodeKey, planComposedBasis, } from './graph.js';
|
|
8
8
|
/**
|
|
@@ -179,6 +179,8 @@ const groupEndsWithBridgeHop = (hops) => isBridgeCarrier(hops[hops.length - 1].e
|
|
|
179
179
|
* section, in BOTH its shapes (the entry-chain swap and the onward
|
|
180
180
|
* aggregator hop) — the section label names where the journey finishes
|
|
181
181
|
* regardless of which service carries the last leg.
|
|
182
|
+
* - **"Swap on {X}"** — a group of the "Send to" shape whose first hop starts
|
|
183
|
+
* on the chain its last hop ends on: nothing is sent anywhere.
|
|
182
184
|
* - **"Send to {X}"** — every other case: a non-final, non-bridge-ending
|
|
183
185
|
* group. Matches `buildNearIntentsTwoStepRouteData`'s first section.
|
|
184
186
|
*
|
|
@@ -200,7 +202,7 @@ const sectionLabel = (group, groupIndex, plan) => {
|
|
|
200
202
|
if (isFinalGroup) {
|
|
201
203
|
return `Complete at ${chainDisplayName(destinationChainId)}`;
|
|
202
204
|
}
|
|
203
|
-
return
|
|
205
|
+
return sendOrSwapLabel(hops[0].edge.from.chainId, destinationChainId);
|
|
204
206
|
};
|
|
205
207
|
// ---------------------------------------------------------------------------
|
|
206
208
|
// Hop-level rendering
|
|
@@ -255,7 +257,8 @@ const hopProviderName = (carrier) => {
|
|
|
255
257
|
* `"Bridge to {toChainName}"` (matches `buildOutboundRouteData`'s onward
|
|
256
258
|
* hop, which names the chain it finishes on even though an aggregator,
|
|
257
259
|
* not the omnibridge, carries it);
|
|
258
|
-
* - any other aggregator hop (something follows it) → `"Send to {toChainName}"
|
|
260
|
+
* - any other aggregator hop (something follows it) → `"Send to {toChainName}"`,
|
|
261
|
+
* or `"Swap on {chainName}"` when the hop starts and ends on one chain
|
|
259
262
|
* (matches `buildNearIntentsTwoStepRouteData`'s aggregator hop).
|
|
260
263
|
*
|
|
261
264
|
* @param hop - the hop to title
|
|
@@ -274,10 +277,10 @@ const hopTitle = (hop, hopIndex, plan, resolveToken) => {
|
|
|
274
277
|
if (carrier === 'PulseX') {
|
|
275
278
|
return `Swap to ${resolveToken(hop.edge.to).symbol}`;
|
|
276
279
|
}
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
280
|
+
if (isFinalHopOfPlan(hopIndex, plan)) {
|
|
281
|
+
return `Bridge to ${chainDisplayName(hop.edge.to.chainId)}`;
|
|
282
|
+
}
|
|
283
|
+
return sendOrSwapLabel(hop.edge.from.chainId, hop.edge.to.chainId);
|
|
281
284
|
};
|
|
282
285
|
/**
|
|
283
286
|
* A hop's conversion subtitle.
|
package/dist/types.d.ts
CHANGED
|
@@ -30,6 +30,14 @@ export type Token = TokenMetadata & {
|
|
|
30
30
|
* that carry no price (e.g. the dapp image lists).
|
|
31
31
|
*/
|
|
32
32
|
priceUSD?: string | null;
|
|
33
|
+
/**
|
|
34
|
+
* LI.FI's `coinKey`: a short key naming the asset across chains (for example
|
|
35
|
+
* "USDC"). Present only on tokens parsed from a LI.FI list that carries one.
|
|
36
|
+
* LI.FI repeats some keys within one chain, so a key alone is not an identity.
|
|
37
|
+
*/
|
|
38
|
+
coinKey?: string;
|
|
39
|
+
/** LI.FI's `verificationStatus` (for example "verified"). Present only on tokens parsed from a LI.FI list that carries one. */
|
|
40
|
+
verificationStatus?: string;
|
|
33
41
|
};
|
|
34
42
|
/** The token out for a given asset */
|
|
35
43
|
export type TokenOut = Omit<Token, 'address'> & {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gibs/bridge-sdk",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.19.0",
|
|
4
4
|
"description": "Build and price cross-chain transfers between PulseChain, Ethereum, and Binance Smart Chain.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ethereum",
|
|
@@ -1007,8 +1007,8 @@
|
|
|
1007
1007
|
"test:live:near-intents": "../../scripts/near-intents-live.sh"
|
|
1008
1008
|
},
|
|
1009
1009
|
"dependencies": {
|
|
1010
|
-
"@gibs/abis": "^1.
|
|
1011
|
-
"@gibs/common": "^1.
|
|
1010
|
+
"@gibs/abis": "^1.19.0",
|
|
1011
|
+
"@gibs/common": "^1.19.0",
|
|
1012
1012
|
"@ton/core": "^0.63.1",
|
|
1013
1013
|
"@ton/crypto": "^3.3.0"
|
|
1014
1014
|
},
|