@gibs/bridge-sdk 1.19.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/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 +0 -465
- 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.js +0 -149
- 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.js +0 -73
- 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.js +0 -28
- 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 +0 -508
- 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/claims.js +0 -60
- package/dist/config.js +1 -211
- package/dist/consolidated-quote.js +0 -465
- 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.js +0 -149
- 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.js +0 -73
- 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.js +0 -28
- 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 +0 -508
- 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/package.json +3 -3
|
@@ -3,77 +3,18 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.buildDestinationCalldata = exports.destinationGasLimits = void 0;
|
|
4
4
|
const viem_1 = require("viem");
|
|
5
5
|
const settings_js_1 = require("./settings.js");
|
|
6
|
-
/**
|
|
7
|
-
* Conservative per-shape gas budgets for omnibridge entry calls executed by an
|
|
8
|
-
* aggregator on the destination chain. An undershoot reverts the executor's
|
|
9
|
-
* call and strands funds at the aggregator's fallback address, so these err
|
|
10
|
-
* high; the aggregator prices unused gas into the quote rather than burning it.
|
|
11
|
-
*
|
|
12
|
-
* MEASURED against the deployed mediators on a fork of Ethereum mainnet,
|
|
13
|
-
* 2026-08-31, by `destination-calldata.fork.test.ts`:
|
|
14
|
-
*
|
|
15
|
-
* relayTokens 195,967 USD Coin, an ordinary registered token
|
|
16
|
-
* wrapAndRelayTokens 200,347 native ether through the router
|
|
17
|
-
* transferAndCall 187,000 wrapped Pulse, a bridged representation home
|
|
18
|
-
* to 204,000, depending on the fork block
|
|
19
|
-
*
|
|
20
|
-
* The figures move with block state — whether a storage slot the call touches
|
|
21
|
-
* is already warm — so treat them as a band, not a constant. The spread
|
|
22
|
-
* measured across two blocks minutes apart was about nine percent.
|
|
23
|
-
*
|
|
24
|
-
* THE BUDGET STAYS AT 400,000, and the headroom is deliberate. Every figure
|
|
25
|
-
* above is a token the bridge has carried before. The first crossing of a
|
|
26
|
-
* token the mediator has not seen writes its limits as well, and a token with
|
|
27
|
-
* a transfer hook costs more again — neither is measured here, and both fail
|
|
28
|
-
* by stranding the user's funds rather than by costing us a little gas. The
|
|
29
|
-
* fork test asserts each shape stays under the budget, so a regression that
|
|
30
|
-
* eats the headroom fails a test rather than a transfer.
|
|
31
|
-
*/
|
|
32
6
|
exports.destinationGasLimits = {
|
|
33
7
|
relayTokens: 400000n,
|
|
34
8
|
transferAndCall: 400000n,
|
|
35
9
|
wrapAndRelayTokens: 400000n,
|
|
36
10
|
};
|
|
37
|
-
/**
|
|
38
|
-
* Builds the call an aggregator's executor must perform on the bridge's
|
|
39
|
-
* foreign chain (e.g. Ethereum) to relay just-bridged funds onward through the
|
|
40
|
-
* omnibridge to the recipient on the home chain (e.g. PulseChain).
|
|
41
|
-
*
|
|
42
|
-
* This is the second leg of a consolidated route: the aggregator bridges the
|
|
43
|
-
* user's funds to the foreign chain with a guaranteed minimum amount, then its
|
|
44
|
-
* executor performs this call. Because the executor — not the user — is the
|
|
45
|
-
* caller, the result always encodes the fixed `amount` and names the user as
|
|
46
|
-
* `recipient`; delivery-fee encoding never applies (home-chain gas handout is
|
|
47
|
-
* a separate automatic system).
|
|
48
|
-
*
|
|
49
|
-
* @param pathway - the bridge pathway whose foreign side the executor enters
|
|
50
|
-
* @param assetIn - the foreign-chain token the aggregator delivers (zero address for native)
|
|
51
|
-
* @param recipient - the user's address on the home chain
|
|
52
|
-
* @param sender - the user's address, threaded through pathways that take an extra sender param
|
|
53
|
-
* @param assetLink - the asset link for the token, used to detect bridged representations
|
|
54
|
-
* @param amount - the exact token amount the executor will relay
|
|
55
|
-
* @returns the destination call, or null when the inputs cannot form a valid call
|
|
56
|
-
*/
|
|
57
11
|
const buildDestinationCalldata = ({ pathway, assetIn, recipient, sender, assetLink, amount, unwrap = false, }) => {
|
|
58
12
|
if (amount <= 0n) {
|
|
59
13
|
return null;
|
|
60
14
|
}
|
|
61
|
-
// `transactionInputs` rejects both of these too, but it cannot say so to the
|
|
62
|
-
// type checker, and the entry fields below are read straight off them. Asking
|
|
63
|
-
// first keeps the answer honest rather than asserted.
|
|
64
15
|
if (!pathway || !assetLink) {
|
|
65
16
|
return null;
|
|
66
17
|
}
|
|
67
|
-
// THE UNWRAP RIDES THE DATA PARAMETER, which is the same slot the recipient
|
|
68
|
-
// travels in. Naming the destination router there and the recipient after it
|
|
69
|
-
// tells the home mediator to hand the arriving tokens to the router, which
|
|
70
|
-
// unwraps them and forwards the coin on. `destinationDataParam` owns that
|
|
71
|
-
// encoding for the direct path already, so it owns it here too rather than
|
|
72
|
-
// being restated.
|
|
73
|
-
//
|
|
74
|
-
// The gate is the pathway's own bridged native asset. Anything else arrives
|
|
75
|
-
// wrapped whatever the caller asked for, so obeying the request would build a
|
|
76
|
-
// call that does something other than what the caller believes it does.
|
|
77
18
|
const unwrapOnArrival = unwrap &&
|
|
78
19
|
assetIn !== null &&
|
|
79
20
|
pathway.destinationRouter !== null &&
|
|
@@ -90,17 +31,10 @@ const buildDestinationCalldata = ({ pathway, assetIn, recipient, sender, assetLi
|
|
|
90
31
|
unwrap: true,
|
|
91
32
|
})
|
|
92
33
|
: recipient;
|
|
93
|
-
// Only reachable when the unwrap was asked for and could not be encoded.
|
|
94
|
-
// Falling back to a plain recipient would quietly deliver the wrapped token.
|
|
95
34
|
if (destinationData === null) {
|
|
96
35
|
return null;
|
|
97
36
|
}
|
|
98
37
|
const inputs = (0, settings_js_1.transactionInputs)({
|
|
99
|
-
// NO READER COMPOSED THIS CALL, so there is no pair on screen for it to
|
|
100
|
-
// disagree with. An aggregator's executor performs it on the entry chain
|
|
101
|
-
// after the reader has already signed their own transaction, and the chain
|
|
102
|
-
// pair IS this pathway. See `crossingRefusal` for why the field is nullable
|
|
103
|
-
// rather than optional: every caller has to say which of the two it is.
|
|
104
38
|
bridgeKey: null,
|
|
105
39
|
signedCrossing: null,
|
|
106
40
|
bridgePathway: pathway,
|
|
@@ -108,8 +42,6 @@ const buildDestinationCalldata = ({ pathway, assetIn, recipient, sender, assetLi
|
|
|
108
42
|
recipient,
|
|
109
43
|
account: sender,
|
|
110
44
|
assetLink,
|
|
111
|
-
// for bridged tokens the data param rides transferAndCall and the
|
|
112
|
-
// mediator decodes it as the home-chain recipient
|
|
113
45
|
destinationDataParam: destinationData,
|
|
114
46
|
amountToBridge: amount,
|
|
115
47
|
feeDirectorStructEncoded: null,
|
|
@@ -123,9 +55,6 @@ const buildDestinationCalldata = ({ pathway, assetIn, recipient, sender, assetLi
|
|
|
123
55
|
assetLink,
|
|
124
56
|
assetInAddress: assetIn?.address ?? null,
|
|
125
57
|
});
|
|
126
|
-
// Both are the same for every shape: the pathway's own mediator, and the
|
|
127
|
-
// on-chain address the link resolved (already the wrapped one for a native
|
|
128
|
-
// asset, because `tokenBridgeInfo` substitutes it before looking anything up).
|
|
129
58
|
const entry = {
|
|
130
59
|
entryMediator: pathway.from,
|
|
131
60
|
entryTokenAddress: assetLink.assetInAddress,
|
package/dist/cjs/ecosystems.js
CHANGED
|
@@ -2,47 +2,21 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.normalizeAddressIn = exports.isValidAddressIn = exports.isNativeAsset = exports.sameAddress = exports.ecosystemByCaipNamespace = exports.isEcosystemProvenEndToEnd = exports.ecosystemById = exports.ecosystemRegistry = void 0;
|
|
4
4
|
const viem_1 = require("viem");
|
|
5
|
-
// Solana public keys are base58 (no 0, O, I, l) and 32–44 characters long.
|
|
6
5
|
const base58Solana = /^[1-9A-HJ-NP-Za-km-z]{32,44}$/;
|
|
7
|
-
// Bitcoin mainnet: bech32 (bc1…) or base58 pay-to-key/script (starts 1 or 3).
|
|
8
6
|
const bech32Bitcoin = /^bc1[0-9ac-hj-np-z]{6,87}$/;
|
|
9
7
|
const base58Bitcoin = /^[13][1-9A-HJ-NP-Za-km-z]{25,39}$/;
|
|
10
|
-
// Tron base58check addresses are always 34 characters and always begin with a
|
|
11
|
-
// capital T (the encoding of the 0x41 mainnet prefix byte).
|
|
12
8
|
const base58Tron = /^T[1-9A-HJ-NP-Za-km-z]{33}$/;
|
|
13
|
-
// The Open Network has two interchangeable address encodings, and Relay uses
|
|
14
|
-
// both: the 48-character "user-friendly" base64url form (EQ/UQ on mainnet,
|
|
15
|
-
// kQ/0Q on testnet), and the "raw" form of a workchain, a colon, and a
|
|
16
|
-
// 64-character hex account identifier.
|
|
17
9
|
const friendlyTon = /^[EUk0]Q[A-Za-z0-9_-]{46}$/;
|
|
18
10
|
const rawTon = /^-?\d+:[0-9a-fA-F]{64}$/;
|
|
19
|
-
// HyperCore token identifiers are hex of a length Ethereum never uses: sixteen
|
|
20
|
-
// bytes for most tokens, nineteen for a few. Twenty is allowed too so a token
|
|
21
|
-
// that is addressed by a full Ethereum address still resolves.
|
|
22
11
|
const hyperliquidTokenId = /^0x[0-9a-fA-F]{32,40}$/;
|
|
23
|
-
// Zcash TRANSPARENT addresses only, and the restriction is the service's, not
|
|
24
|
-
// ours: a shielded (`zs1…`) or unified (`u1…`) address is refused at the door
|
|
25
|
-
// with `refundTo is not valid`, before a solver is ever reached. Both
|
|
26
|
-
// transparent forms are base58check over a two-byte prefix, which always
|
|
27
|
-
// encodes to exactly 35 characters: `t1` pays to a public key hash, `t3` to a
|
|
28
|
-
// script hash. The pattern rejects the shielded forms by construction, because
|
|
29
|
-
// neither begins with `t`.
|
|
30
12
|
const transparentZcash = /^t[13][1-9A-HJ-NP-Za-km-z]{33}$/;
|
|
31
13
|
const evmDescriptor = {
|
|
32
14
|
id: 'evm',
|
|
33
15
|
label: 'Ethereum Virtual Machine',
|
|
34
16
|
caipNamespace: 'eip155',
|
|
35
|
-
// The all-zero address, exactly as the Relay builder uses across every
|
|
36
|
-
// Ethereum Virtual Machine chain for the native gas token.
|
|
37
17
|
nativeAssetSentinel: '0x0000000000000000000000000000000000000000',
|
|
38
|
-
// The only proof the product holds. The bridge's own contracts run on
|
|
39
|
-
// PulseChain, Ethereum and Binance Smart Chain, and every aggregator origin
|
|
40
|
-
// LI.FI carries is an Ethereum Virtual Machine chain, so this is the family
|
|
41
|
-
// real transfers have crossed.
|
|
42
18
|
endToEndProof: 'verified',
|
|
43
19
|
isValidAddress: (value) => (0, viem_1.isAddress)(value),
|
|
44
|
-
// getAddress applies the mixed-case checksum; it throws on a non-address, so
|
|
45
|
-
// fall back to the raw input to keep normalize total and side-effect-free.
|
|
46
20
|
normalizeAddress: (value) => ((0, viem_1.isAddress)(value) ? (0, viem_1.getAddress)(value) : value),
|
|
47
21
|
addressCasing: 'insensitive',
|
|
48
22
|
};
|
|
@@ -50,16 +24,9 @@ const svmDescriptor = {
|
|
|
50
24
|
id: 'svm',
|
|
51
25
|
label: 'Solana',
|
|
52
26
|
caipNamespace: 'solana',
|
|
53
|
-
// Solana native currency (the System Program address), as Relay expects it.
|
|
54
27
|
nativeAssetSentinel: '11111111111111111111111111111111',
|
|
55
|
-
// Connects through the Reown AppKit Solana adapter and signs for real
|
|
56
|
-
// (`useSolanaDepositSigner` builds a versioned transaction and calls the
|
|
57
|
-
// wallet's sign-and-send). Every test around it drives a mocked wallet, and
|
|
58
|
-
// Relay — the only provider that quotes this origin — has never had its
|
|
59
|
-
// on-chain execution confirmed by a funded transfer.
|
|
60
28
|
endToEndProof: 'pending',
|
|
61
29
|
isValidAddress: (value) => base58Solana.test(value),
|
|
62
|
-
// base58 is case-significant; canonical form is the input unchanged.
|
|
63
30
|
normalizeAddress: (value) => value,
|
|
64
31
|
addressCasing: 'significant',
|
|
65
32
|
};
|
|
@@ -67,17 +34,9 @@ const bvmDescriptor = {
|
|
|
67
34
|
id: 'bvm',
|
|
68
35
|
label: 'Bitcoin',
|
|
69
36
|
caipNamespace: 'bip122',
|
|
70
|
-
// Bitcoin native currency string, as Relay expects it.
|
|
71
37
|
nativeAssetSentinel: 'bc1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqmql8k8',
|
|
72
|
-
// The best-evidenced of the four, and still short of proof. A partially
|
|
73
|
-
// signed transaction the pipeline builds is accepted by a real node, but
|
|
74
|
-
// that test runs against a local regtest node behind `BITCOIN_REGTEST=1`
|
|
75
|
-
// and never in the normal suite. The browser wallet that signs in
|
|
76
|
-
// production is driven by nothing but a mock, and no funded mainnet
|
|
77
|
-
// transfer has completed.
|
|
78
38
|
endToEndProof: 'pending',
|
|
79
39
|
isValidAddress: (value) => bech32Bitcoin.test(value) || base58Bitcoin.test(value),
|
|
80
|
-
// bech32 and base58 are case-significant; canonical form is the input unchanged.
|
|
81
40
|
normalizeAddress: (value) => value,
|
|
82
41
|
addressCasing: 'significant',
|
|
83
42
|
};
|
|
@@ -85,16 +44,9 @@ const tvmDescriptor = {
|
|
|
85
44
|
id: 'tvm',
|
|
86
45
|
label: 'Tron',
|
|
87
46
|
caipNamespace: 'tron',
|
|
88
|
-
// Tron native currency (TRX), as Relay expects it. Not a real contract: it is
|
|
89
|
-
// the placeholder address Relay publishes for the chain's native asset.
|
|
90
47
|
nativeAssetSentinel: 'T9yD14Nj9j7xAB4dbGeiX9h8unkKHxuWwb',
|
|
91
|
-
// The first wallet the interface reaches outside Reown AppKit: it reads an
|
|
92
|
-
// injected provider directly. That is more of the connection path owned
|
|
93
|
-
// here, and therefore more of it unexercised outside a mock. No funded
|
|
94
|
-
// transfer has completed.
|
|
95
48
|
endToEndProof: 'pending',
|
|
96
49
|
isValidAddress: (value) => base58Tron.test(value),
|
|
97
|
-
// base58check is case-significant; canonical form is the input unchanged.
|
|
98
50
|
normalizeAddress: (value) => value,
|
|
99
51
|
addressCasing: 'significant',
|
|
100
52
|
};
|
|
@@ -102,17 +54,9 @@ const tonvmDescriptor = {
|
|
|
102
54
|
id: 'tonvm',
|
|
103
55
|
label: 'The Open Network',
|
|
104
56
|
caipNamespace: 'ton',
|
|
105
|
-
// Relay publishes Gram — NOT the Toncoin gas asset — as this chain's native
|
|
106
|
-
// currency, so a native-asset route on The Open Network is denominated in
|
|
107
|
-
// Gram. Kept byte-equal to Relay's own value rather than "corrected".
|
|
108
57
|
nativeAssetSentinel: 'EQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAM9c',
|
|
109
|
-
// The second wallet outside Reown AppKit, on a separate connection library,
|
|
110
|
-
// and the one origin whose deposit identifier is derived from the returned
|
|
111
|
-
// cell rather than handed back by the wallet. Only a mock has ever returned
|
|
112
|
-
// that cell. No funded transfer has completed.
|
|
113
58
|
endToEndProof: 'pending',
|
|
114
59
|
isValidAddress: (value) => friendlyTon.test(value) || rawTon.test(value),
|
|
115
|
-
// both encodings are case-significant; canonical form is the input unchanged.
|
|
116
60
|
normalizeAddress: (value) => value,
|
|
117
61
|
addressCasing: 'significant',
|
|
118
62
|
};
|
|
@@ -120,71 +64,22 @@ const hypevmDescriptor = {
|
|
|
120
64
|
id: 'hypevm',
|
|
121
65
|
label: 'Hyperliquid',
|
|
122
66
|
caipNamespace: 'hyperliquid',
|
|
123
|
-
// Relay publishes USD Coin — NOT the Hype gas asset — as this chain's native
|
|
124
|
-
// currency, and addresses it by a sixteen-byte HyperCore token identifier
|
|
125
|
-
// rather than the twenty-byte all-zero address every Ethereum Virtual Machine
|
|
126
|
-
// chain uses. The two sentinels are therefore different strings.
|
|
127
67
|
nativeAssetSentinel: '0x00000000000000000000000000000000',
|
|
128
|
-
// THE WORST OF THE SIX, and the one that was actively misleading. The
|
|
129
|
-
// interface's source picker never offers Hyperliquid — nothing can quote it
|
|
130
|
-
// — yet the landing page drew a pill for it that set the source chain to
|
|
131
|
-
// Hyperliquid on click. A reader who pressed it arrived at a chain the form
|
|
132
|
-
// does not list and no provider answers. Removing the pill removes that dead
|
|
133
|
-
// end; the descriptor stays because the route layer still has to be able to
|
|
134
|
-
// NAME the chain.
|
|
135
68
|
endToEndProof: 'pending',
|
|
136
|
-
// This predicate checks TOKEN addresses, and HyperCore identifies a token by a
|
|
137
|
-
// hex string SHORTER than an Ethereum address — sixteen bytes for most,
|
|
138
|
-
// nineteen for a few — so the twenty-byte `isAddress` check would reject the
|
|
139
|
-
// very identifiers it exists to accept. Its only consumer silently falls back
|
|
140
|
-
// to the native sentinel when this returns false, so an over-strict pattern
|
|
141
|
-
// would quietly swallow valid token links instead of surfacing an error.
|
|
142
|
-
// Accounts are a different namespace (ordinary twenty-byte Ethereum
|
|
143
|
-
// addresses) and are validated by the wallet layer, not here.
|
|
144
69
|
isValidAddress: (value) => hyperliquidTokenId.test(value),
|
|
145
|
-
// Hex is case-insensitive and Relay emits lower case, so lower case is the
|
|
146
|
-
// canonical form. It matters: the token-equality check compares non-Ethereum
|
|
147
|
-
// addresses exactly, and only a single canonical case makes that correct.
|
|
148
70
|
normalizeAddress: (value) => hyperliquidTokenId.test(value) ? value.toLowerCase() : value,
|
|
149
71
|
addressCasing: 'significant',
|
|
150
72
|
};
|
|
151
73
|
const zcashDescriptor = {
|
|
152
74
|
id: 'zcash',
|
|
153
75
|
label: 'Zcash',
|
|
154
|
-
// Zcash is not a Relay chain and has no widely-registered chain-agnostic
|
|
155
|
-
// namespace. `zcash` is this repository's own key, and nothing maps a
|
|
156
|
-
// connected wallet through it, because no wallet connects to this family.
|
|
157
76
|
caipNamespace: 'zcash',
|
|
158
|
-
// DERIVED, NOT INVENTED: the transparent pay-to-public-key-hash address of
|
|
159
|
-
// an all-zero key hash, base58check over the mainnet prefix `1cb8` followed
|
|
160
|
-
// by twenty zero bytes. Nobody holds a key for it. It follows the pattern of
|
|
161
|
-
// Relay's Bitcoin sentinel, an all-zero witness program, and for the same
|
|
162
|
-
// reason: the sentinel stands where a token address is expected, so it must
|
|
163
|
-
// pass this family's own address check. Zcash carries no tokens on this
|
|
164
|
-
// route, so the native asset is the only asset.
|
|
165
77
|
nativeAssetSentinel: 't1Hsc1LR8yKnbbe3twRp88p6vFfC5t7DLbs',
|
|
166
|
-
// THE FIRST ECOSYSTEM WITH NO WALLET AT ALL, and therefore the first whose
|
|
167
|
-
// hold cannot be cleared by connecting one. The reader pays an address by
|
|
168
|
-
// hand from wherever they hold the coin, so every part of the journey that
|
|
169
|
-
// this repository owns — the quote, the address, the amount, the deadline,
|
|
170
|
-
// the status poll — is exercised only by a fixture. Nothing funded has
|
|
171
|
-
// crossed. Clearing this is one word, after one transfer.
|
|
172
78
|
endToEndProof: 'pending',
|
|
173
79
|
isValidAddress: (value) => transparentZcash.test(value),
|
|
174
|
-
// base58check is case-significant; canonical form is the input unchanged.
|
|
175
80
|
normalizeAddress: (value) => value,
|
|
176
81
|
addressCasing: 'significant',
|
|
177
82
|
};
|
|
178
|
-
/**
|
|
179
|
-
* Every ecosystem the bridge can originate from. LI.FI-compatible one first.
|
|
180
|
-
*
|
|
181
|
-
* Registration means the library can MODEL and QUOTE the ecosystem, not that an
|
|
182
|
-
* interface can sign it — see the note on {@link Ecosystem}.
|
|
183
|
-
*
|
|
184
|
-
* It means less than that again where a public claim is concerned: read
|
|
185
|
-
* {@link EndToEndProof} before listing this registry anywhere a reader will
|
|
186
|
-
* take it as an offer.
|
|
187
|
-
*/
|
|
188
83
|
exports.ecosystemRegistry = [
|
|
189
84
|
evmDescriptor,
|
|
190
85
|
svmDescriptor,
|
|
@@ -195,14 +90,6 @@ exports.ecosystemRegistry = [
|
|
|
195
90
|
zcashDescriptor,
|
|
196
91
|
];
|
|
197
92
|
const byId = new Map(exports.ecosystemRegistry.map((descriptor) => [descriptor.id, descriptor]));
|
|
198
|
-
/**
|
|
199
|
-
* Looks up the descriptor for an ecosystem id. Total over the `Ecosystem` union;
|
|
200
|
-
* throws only if the registry is ever left incomplete (a programming error the
|
|
201
|
-
* round-trip test would catch).
|
|
202
|
-
*
|
|
203
|
-
* @param id - the ecosystem key
|
|
204
|
-
* @returns the descriptor whose `id` equals `id`
|
|
205
|
-
*/
|
|
206
93
|
const ecosystemById = (id) => {
|
|
207
94
|
const descriptor = byId.get(id);
|
|
208
95
|
if (descriptor === undefined) {
|
|
@@ -211,88 +98,18 @@ const ecosystemById = (id) => {
|
|
|
211
98
|
return descriptor;
|
|
212
99
|
};
|
|
213
100
|
exports.ecosystemById = ecosystemById;
|
|
214
|
-
/**
|
|
215
|
-
* Whether a transfer has been carried through this ecosystem end to end.
|
|
216
|
-
*
|
|
217
|
-
* The predicate a surface calls before ADVERTISING an origin. It is separate
|
|
218
|
-
* from anything the router asks, and deliberately so: the router must keep
|
|
219
|
-
* quoting and naming every registered ecosystem, because a reader who reaches
|
|
220
|
-
* an unproven chain through a link still needs the page to work. This governs
|
|
221
|
-
* only what the product offers unprompted.
|
|
222
|
-
*
|
|
223
|
-
* @param id - the ecosystem key
|
|
224
|
-
* @returns true when a real transfer has completed through it
|
|
225
|
-
*/
|
|
226
101
|
const isEcosystemProvenEndToEnd = (id) => (0, exports.ecosystemById)(id).endToEndProof === 'verified';
|
|
227
102
|
exports.isEcosystemProvenEndToEnd = isEcosystemProvenEndToEnd;
|
|
228
103
|
const byNamespace = new Map(exports.ecosystemRegistry.map((descriptor) => [descriptor.caipNamespace, descriptor]));
|
|
229
|
-
/**
|
|
230
|
-
* Resolves an ecosystem from a chain-agnostic identifier namespace.
|
|
231
|
-
*
|
|
232
|
-
* @param namespace - the leading segment of a "namespace:reference:address" id
|
|
233
|
-
* @returns the matching descriptor, or undefined when the namespace is unknown
|
|
234
|
-
*/
|
|
235
104
|
const ecosystemByCaipNamespace = (namespace) => byNamespace.get(namespace);
|
|
236
105
|
exports.ecosystemByCaipNamespace = ecosystemByCaipNamespace;
|
|
237
|
-
/**
|
|
238
|
-
* Whether two addresses in the same ecosystem name the same thing.
|
|
239
|
-
*
|
|
240
|
-
* THE ONE PLACE THIS QUESTION IS ANSWERED. It was answered in two: this
|
|
241
|
-
* registry, which knows each family's address rules, and a ternary in the
|
|
242
|
-
* interface's routing module that hard-coded "Ethereum is case-insensitive,
|
|
243
|
-
* everything else is not". Two homes means a family added here is still
|
|
244
|
-
* compared wrongly there, silently, because a loose comparison does not fail —
|
|
245
|
-
* it merges two different accounts into one.
|
|
246
|
-
*
|
|
247
|
-
* @param a - an address
|
|
248
|
-
* @param b - an address, in the same ecosystem
|
|
249
|
-
* @param ecosystem - the ecosystem both belong to
|
|
250
|
-
* @returns whether they are the same address
|
|
251
|
-
*/
|
|
252
106
|
const sameAddress = (a, b, ecosystem) => (0, exports.ecosystemById)(ecosystem).addressCasing === 'insensitive'
|
|
253
107
|
? a.toLowerCase() === b.toLowerCase()
|
|
254
108
|
: a === b;
|
|
255
109
|
exports.sameAddress = sameAddress;
|
|
256
|
-
/**
|
|
257
|
-
* Whether an address is the ecosystem's own native asset rather than a token.
|
|
258
|
-
*
|
|
259
|
-
* Every ecosystem already declares its `nativeAssetSentinel`, and this is the
|
|
260
|
-
* predicate that reads it. The comparison goes through {@link sameAddress}
|
|
261
|
-
* rather than `toLowerCase()`, which matters for exactly the families where the
|
|
262
|
-
* hand-written checks were wrong to begin with: Solana's, Bitcoin's and The
|
|
263
|
-
* Open Network's sentinels are case-significant, so lower-casing them before
|
|
264
|
-
* comparing can match an address that is not the sentinel.
|
|
265
|
-
*
|
|
266
|
-
* @param value - the address to test
|
|
267
|
-
* @param ecosystem - the ecosystem it belongs to
|
|
268
|
-
* @returns whether it names the native asset
|
|
269
|
-
*/
|
|
270
110
|
const isNativeAsset = (value, ecosystem) => (0, exports.sameAddress)(value, (0, exports.ecosystemById)(ecosystem).nativeAssetSentinel, ecosystem);
|
|
271
111
|
exports.isNativeAsset = isNativeAsset;
|
|
272
|
-
/**
|
|
273
|
-
* Whether a string is a well-formed address in this ecosystem.
|
|
274
|
-
*
|
|
275
|
-
* A free function over the registry, so a caller needs the ecosystem key and
|
|
276
|
-
* nothing else. Reaching for viem's `isAddress` directly is the thing this
|
|
277
|
-
* replaces: it answers only for Ethereum and answers FALSE — confidently — for
|
|
278
|
-
* every valid Solana, Bitcoin, Tron and Open Network address.
|
|
279
|
-
*
|
|
280
|
-
* @param value - the string to test
|
|
281
|
-
* @param ecosystem - the ecosystem to test it against
|
|
282
|
-
* @returns whether the string is a valid address there
|
|
283
|
-
*/
|
|
284
112
|
const isValidAddressIn = (value, ecosystem) => (0, exports.ecosystemById)(ecosystem).isValidAddress(value);
|
|
285
113
|
exports.isValidAddressIn = isValidAddressIn;
|
|
286
|
-
/**
|
|
287
|
-
* The ecosystem's canonical spelling of an address.
|
|
288
|
-
*
|
|
289
|
-
* Total and side-effect-free: an input this ecosystem cannot parse comes back
|
|
290
|
-
* unchanged rather than throwing, because normalizing is something callers do
|
|
291
|
-
* on the way to a comparison and a throw there would be a crash on a typo.
|
|
292
|
-
*
|
|
293
|
-
* @param value - the address to normalize
|
|
294
|
-
* @param ecosystem - the ecosystem it belongs to
|
|
295
|
-
* @returns the canonical form, or the input when it cannot be parsed
|
|
296
|
-
*/
|
|
297
114
|
const normalizeAddressIn = (value, ecosystem) => (0, exports.ecosystemById)(ecosystem).normalizeAddress(value);
|
|
298
115
|
exports.normalizeAddressIn = normalizeAddressIn;
|
package/dist/cjs/execution.js
CHANGED
|
@@ -42,22 +42,15 @@ const consolidated_quote_js_1 = require("./consolidated-quote.js");
|
|
|
42
42
|
const pulsex_js_1 = require("./routing/carriers/pulsex.js");
|
|
43
43
|
const swap_transactions_js_1 = require("./routing/swap-transactions.js");
|
|
44
44
|
const settings_js_1 = require("./settings.js");
|
|
45
|
-
/**
|
|
46
|
-
* An {@link AllowanceReader} that reports no allowance anywhere, so the plan
|
|
47
|
-
* includes every approval. For a caller that reads allowances itself at send
|
|
48
|
-
* time.
|
|
49
|
-
*/
|
|
50
45
|
const assumeNoAllowance = async () => 0n;
|
|
51
46
|
exports.assumeNoAllowance = assumeNoAllowance;
|
|
52
47
|
const refusal = (value) => ({ kind: 'refused', refusal: value });
|
|
53
|
-
/** The fee director a delivery choice encodes, or null when the reader buys no delivery. */
|
|
54
48
|
const encodeDelivery = ({ leg, pathway, }) => {
|
|
55
49
|
const { delivery } = leg;
|
|
56
50
|
if (!delivery.shouldDeliver)
|
|
57
51
|
return { kind: 'encoded', feeDirector: null };
|
|
58
52
|
if (!pathway.requiresDelivery)
|
|
59
53
|
return refusal({ reason: 'delivery-not-offered' });
|
|
60
|
-
// A zero fee pays no relayer, so the transfer would wait for a delivery that never comes.
|
|
61
54
|
if (delivery.fee.maximumFee <= 0n)
|
|
62
55
|
return refusal({ reason: 'delivery-fee-missing' });
|
|
63
56
|
const feeDirector = (0, settings_js_1.feeDirectorStructEncoded)({
|
|
@@ -132,16 +125,6 @@ const omnibridgeCalls = (leg, account) => {
|
|
|
132
125
|
delivery: deliveryTermsOf(leg.delivery),
|
|
133
126
|
};
|
|
134
127
|
};
|
|
135
|
-
/**
|
|
136
|
-
* The venue a swap edge was priced on, from the venues execution was given.
|
|
137
|
-
* A router that is not in those venues THROWS: signing on another router, on
|
|
138
|
-
* PulseX most of all, would trade against pools the reader was never shown.
|
|
139
|
-
*
|
|
140
|
-
* @param venues - the venues passed to execution
|
|
141
|
-
* @param edge - the swap edge
|
|
142
|
-
* @returns the venue
|
|
143
|
-
* @throws when the edge's router is not in `venues`, or its chain has no venue
|
|
144
|
-
*/
|
|
145
128
|
const requireSwapVenue = (venues, edge) => {
|
|
146
129
|
const venue = (0, pulsex_js_1.venueForEdge)(venues, edge);
|
|
147
130
|
if (venue !== null)
|
|
@@ -156,8 +139,6 @@ const pulseXSwapCalls = (leg, venues) => {
|
|
|
156
139
|
if (edge.carrier !== 'PulseX')
|
|
157
140
|
return refusal({ reason: 'swap-refused' });
|
|
158
141
|
const routerAddress = requireSwapVenue(venues, edge).router;
|
|
159
|
-
// The builder refuses a hop that records no priced path, a router other
|
|
160
|
-
// than the edge's own, and a leg on screen that disagrees.
|
|
161
142
|
const call = (0, swap_transactions_js_1.buildPulseXSwapTransaction)({
|
|
162
143
|
hop: leg.hop,
|
|
163
144
|
amountIn: leg.amountIn,
|
|
@@ -222,7 +203,6 @@ const legCalls = (leg, account, venues) => {
|
|
|
222
203
|
return wrapCalls(leg);
|
|
223
204
|
return aggregatorCalls(leg);
|
|
224
205
|
};
|
|
225
|
-
/** The approve transactions an approval needs now: none when the allowance on chain covers it. */
|
|
226
206
|
const approvalTransactions = async ({ approval, account, readAllowance, }) => {
|
|
227
207
|
const allowance = await readAllowance(approval.chainId, approval.token, account, approval.spender);
|
|
228
208
|
return (0, settings_js_1.approvalAmounts)({ allowance, minimum: approval.minimum }).map((amount) => ({
|
|
@@ -232,20 +212,6 @@ const approvalTransactions = async ({ approval, account, readAllowance, }) => {
|
|
|
232
212
|
gasLimit: null,
|
|
233
213
|
}));
|
|
234
214
|
};
|
|
235
|
-
/**
|
|
236
|
-
* Plans the transactions for a list of legs, in order.
|
|
237
|
-
*
|
|
238
|
-
* Each leg contributes the exact approval it needs when the allowance on
|
|
239
|
-
* chain does not cover it (a reset to zero first when a smaller allowance
|
|
240
|
-
* remains), then its own call. Nothing is sent.
|
|
241
|
-
*
|
|
242
|
-
* @param options.account - the account that signs every transaction
|
|
243
|
-
* @param options.legs - the legs, in the order the wallet signs them
|
|
244
|
-
* @param options.readAllowance - reads an allowance on chain; see {@link AllowanceReader}
|
|
245
|
-
* @param options.swapVenues - the routers swaps may sign on, merged over the defaults; a swap whose router is in none of them throws
|
|
246
|
-
* @returns the ordered transactions, or the first leg that cannot be planned
|
|
247
|
-
* @throws when a swap leg's router is not in the swap venues
|
|
248
|
-
*/
|
|
249
215
|
const planExecution = async ({ account, legs, readAllowance, swapVenues, }) => {
|
|
250
216
|
const venues = (0, swap_venues_js_1.resolveSwapVenues)(swapVenues);
|
|
251
217
|
const calls = legs.map((leg) => legCalls(leg, account, venues));
|
|
@@ -312,7 +278,6 @@ const pulseXSectionLeg = (hop, inputs) => {
|
|
|
312
278
|
if (quotedAmountOut !== undefined && quotedAmountOut <= 0n) {
|
|
313
279
|
return { kind: 'refused', refusal: { reason: 'swap-quote-not-positive' } };
|
|
314
280
|
}
|
|
315
|
-
// Without a fresh quote the floor comes from the hop's own figure, so it must be a real quote.
|
|
316
281
|
if (quotedAmountOut === undefined && hop.outcome.kind !== 'quote') {
|
|
317
282
|
return { kind: 'refused', refusal: { reason: 'swap-estimate-only' } };
|
|
318
283
|
}
|
|
@@ -331,7 +296,6 @@ const pulseXSectionLeg = (hop, inputs) => {
|
|
|
331
296
|
},
|
|
332
297
|
};
|
|
333
298
|
};
|
|
334
|
-
/** Turns one section of an engine plan into its leg, dispatching on the first hop's carrier. */
|
|
335
299
|
const planSectionLeg = ({ hops, inputs, resolveToken, }) => {
|
|
336
300
|
const firstHop = hops[0];
|
|
337
301
|
if (firstHop === undefined)
|
|
@@ -339,8 +303,6 @@ const planSectionLeg = ({ hops, inputs, resolveToken, }) => {
|
|
|
339
303
|
const { carrier, origin, from, to } = firstHop.edge;
|
|
340
304
|
if (origin === 'by-hand')
|
|
341
305
|
return { kind: 'refused', refusal: { reason: 'paid-by-hand' } };
|
|
342
|
-
// An aggregator section may run several hops inside one signature (a fused
|
|
343
|
-
// omnibridge entry); every other carrier signs exactly one hop.
|
|
344
306
|
const singleHop = hops.length === 1;
|
|
345
307
|
if (isOmnibridgeCarrier(carrier)) {
|
|
346
308
|
if (!singleHop)
|
|
@@ -359,18 +321,7 @@ const planSectionLeg = ({ hops, inputs, resolveToken, }) => {
|
|
|
359
321
|
}
|
|
360
322
|
return aggregatorSectionLeg(carrier, inputs);
|
|
361
323
|
};
|
|
362
|
-
/** The sections of a plan, each as its hops. */
|
|
363
324
|
const planSections = (plan) => plan.signatures.map((group) => group.flatMap((hopIndex) => plan.hops[hopIndex] ?? []));
|
|
364
|
-
/**
|
|
365
|
-
* A candidate built without an engine plan is one signature: either a
|
|
366
|
-
* same-chain omnibridge crossing (`buildDirectCrossingCandidate`, whose quote
|
|
367
|
-
* names the bridge) or an aggregator quote.
|
|
368
|
-
*
|
|
369
|
-
* THE CANDIDATE'S OWN QUOTE IS NEVER SIGNED. It priced the route on screen
|
|
370
|
-
* and may be stale or a dry probe; only the live quote in
|
|
371
|
-
* `inputs.aggregator` is. Without one the section is refused with
|
|
372
|
-
* `live-quote-required`.
|
|
373
|
-
*/
|
|
374
325
|
const planlessSectionLeg = (candidate, inputs) => {
|
|
375
326
|
const provider = candidate.quote.provider;
|
|
376
327
|
if (isOmnibridgeCarrier(provider)) {
|
|
@@ -384,10 +335,6 @@ const planlessSectionLeg = (candidate, inputs) => {
|
|
|
384
335
|
}
|
|
385
336
|
return aggregatorSectionLeg(provider, inputs);
|
|
386
337
|
};
|
|
387
|
-
/**
|
|
388
|
-
* What is wrong with the requested window of sections, or null when it fits.
|
|
389
|
-
* A window starts at `firstSectionIndex` and spans `plannedCount` sections.
|
|
390
|
-
*/
|
|
391
338
|
const sectionWindowProblem = ({ firstSectionIndex, plannedCount, sectionCount, }) => {
|
|
392
339
|
if (!Number.isSafeInteger(firstSectionIndex) || firstSectionIndex < 0) {
|
|
393
340
|
return `firstSectionIndex must be a non-negative safe integer, received ${firstSectionIndex}`;
|
|
@@ -399,32 +346,6 @@ const sectionWindowProblem = ({ firstSectionIndex, plannedCount, sectionCount, }
|
|
|
399
346
|
}
|
|
400
347
|
return null;
|
|
401
348
|
};
|
|
402
|
-
/**
|
|
403
|
-
* Plans the transactions for a chosen route candidate: the candidate
|
|
404
|
-
* `buildRouteCandidateFromPlan` returns for an engine plan (the interface's
|
|
405
|
-
* `buildCandidateFromEnginePlan`), or a candidate built without a plan.
|
|
406
|
-
*
|
|
407
|
-
* ONE SECTION IS ONE SIGNATURE. A plan's `signatures` groups its hops into
|
|
408
|
-
* sections; the section's first hop names its carrier. An omnibridge section
|
|
409
|
-
* becomes a crossing, a PulseX section a swap signed on its recorded path, a
|
|
410
|
-
* wrap section a wrap or unwrap, and any other wallet-signed carrier an
|
|
411
|
-
* aggregator deposit from the live quote the caller supplies. A section paid
|
|
412
|
-
* by hand has nothing to sign and is refused.
|
|
413
|
-
*
|
|
414
|
-
* A LATER SECTION CAN BE PLANNED ALONE. Pass `firstSectionIndex` to skip the
|
|
415
|
-
* sections that already landed. The wallet then plans the swap after the
|
|
416
|
-
* crossing arrived, from the amount that arrived, with a fresh
|
|
417
|
-
* `swap.quotedAmountOut` and a fresh `swap.deadline`. The slippage floor and the
|
|
418
|
-
* deadline are not fixed minutes before the swap is signed. Every safety check
|
|
419
|
-
* still applies to the later section: verified spenders, live quotes for
|
|
420
|
-
* aggregator sections, exact approvals.
|
|
421
|
-
*
|
|
422
|
-
* Every `sectionIndex` in a refusal and every `legIndex` in `deliveries` is
|
|
423
|
-
* the absolute section index.
|
|
424
|
-
*
|
|
425
|
-
* @param inputs - see {@link CandidateExecutionInputs}
|
|
426
|
-
* @returns the ordered transactions with the deliveries they buy, or the first section that cannot be planned
|
|
427
|
-
*/
|
|
428
349
|
const planCandidateExecution = async (inputs) => {
|
|
429
350
|
const { candidate, account, readAllowance, resolveToken, sections, swapVenues } = inputs;
|
|
430
351
|
const firstSectionIndex = inputs.firstSectionIndex ?? 0;
|
|
@@ -461,19 +382,6 @@ const planCandidateExecution = async (inputs) => {
|
|
|
461
382
|
};
|
|
462
383
|
};
|
|
463
384
|
exports.planCandidateExecution = planCandidateExecution;
|
|
464
|
-
/**
|
|
465
|
-
* Reads a fresh quote for a PulseX section: what the router's `getAmountsOut`
|
|
466
|
-
* says the swap delivers for `amountIn`, along the exact path the swap signs
|
|
467
|
-
* ({@link pulseXSwapPathForHop}) on the edge's own router. A wallet passes the
|
|
468
|
-
* result as `swap.quotedAmountOut` just before it signs.
|
|
469
|
-
*
|
|
470
|
-
* @param options.hop - the swap hop; its recorded path and edge name what to read
|
|
471
|
-
* @param options.amountIn - the amount the swap spends, in base units
|
|
472
|
-
* @param options.client - a client that can call `readContract`
|
|
473
|
-
* @param options.swapVenues - the routers swaps may sign on, merged over the defaults
|
|
474
|
-
* @returns the amount the last token of the path delivers, or null when the hop records no path, the amount is not positive, or the read fails or returns nothing
|
|
475
|
-
* @throws when the hop records a path but its router is not in the swap venues
|
|
476
|
-
*/
|
|
477
385
|
const readPulseXSectionQuote = async ({ hop, amountIn, client, swapVenues, }) => {
|
|
478
386
|
const path = (0, pulsex_js_1.pulseXSwapPathForHop)(hop);
|
|
479
387
|
if (path === null || amountIn <= 0n)
|
package/dist/cjs/fee-type.js
CHANGED
|
@@ -6,5 +6,4 @@ exports.feeTypeValToKeyMap = exports.FeeType = void 0;
|
|
|
6
6
|
FeeType["GAS_TIP"] = "gas+%";
|
|
7
7
|
FeeType["FIXED"] = "fixed";
|
|
8
8
|
})(exports.FeeType || (exports.FeeType = {}));
|
|
9
|
-
/** A map of fee type values to keys */
|
|
10
9
|
exports.feeTypeValToKeyMap = new Map(Object.keys(exports.FeeType).map((key) => [exports.FeeType[key], key]));
|