@gibs/bridge-sdk 1.13.0 → 1.17.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 +244 -18
- package/abis/package.json +6 -0
- package/bridge-limits/package.json +6 -0
- package/chain-info/package.json +6 -0
- package/chain-names/package.json +6 -0
- package/chains/package.json +6 -0
- package/claims/package.json +6 -0
- package/config/package.json +6 -0
- package/consolidated-quote/package.json +6 -0
- package/destination-calldata/package.json +6 -0
- package/dist/chain-info.d.ts +1 -1
- package/dist/chain-info.js +11 -12
- package/dist/chains.d.ts +25 -0
- package/dist/chains.js +55 -20
- package/dist/cjs/abis.d.ts +1 -0
- package/dist/cjs/abis.js +19 -0
- package/dist/cjs/bridge-limits.d.ts +103 -0
- package/dist/cjs/bridge-limits.js +89 -0
- package/dist/cjs/chain-info.d.ts +169 -0
- package/dist/cjs/chain-info.js +452 -0
- package/dist/cjs/chain-names.d.ts +160 -0
- package/dist/cjs/chain-names.js +207 -0
- package/dist/cjs/chains.d.ts +90 -0
- package/dist/cjs/chains.js +357 -0
- package/dist/cjs/claims.d.ts +198 -0
- package/dist/cjs/claims.js +182 -0
- package/dist/cjs/config.d.ts +240 -0
- package/dist/cjs/config.js +537 -0
- package/dist/cjs/consolidated-quote.d.ts +648 -0
- package/dist/cjs/consolidated-quote.js +1048 -0
- package/dist/cjs/destination-calldata.d.ts +118 -0
- package/dist/cjs/destination-calldata.js +156 -0
- package/dist/cjs/ecosystems.d.ts +217 -0
- package/dist/cjs/ecosystems.js +298 -0
- package/dist/cjs/execution.d.ts +346 -0
- package/dist/cjs/execution.js +468 -0
- package/dist/cjs/fee-type.d.ts +10 -0
- package/dist/cjs/fee-type.js +10 -0
- package/dist/cjs/hyperliquid-execution.d.ts +152 -0
- package/dist/cjs/hyperliquid-execution.js +175 -0
- package/dist/cjs/image-links.d.ts +117 -0
- package/dist/cjs/image-links.js +153 -0
- package/dist/cjs/index.d.ts +23 -0
- package/dist/cjs/index.js +39 -0
- package/dist/cjs/lifi-execution-guard.d.ts +210 -0
- package/dist/cjs/lifi-execution-guard.js +409 -0
- package/dist/cjs/near-intents-conformance.d.ts +85 -0
- package/dist/cjs/near-intents-conformance.js +337 -0
- package/dist/cjs/near-intents-route.d.ts +47 -0
- package/dist/cjs/near-intents-route.js +303 -0
- package/dist/cjs/near-intents.d.ts +524 -0
- package/dist/cjs/near-intents.js +1071 -0
- package/dist/cjs/origin-deposit.d.ts +326 -0
- package/dist/cjs/origin-deposit.js +82 -0
- package/dist/cjs/package.json +3 -0
- package/dist/cjs/pre-quote.d.ts +198 -0
- package/dist/cjs/pre-quote.js +180 -0
- package/dist/cjs/prices.d.ts +107 -0
- package/dist/cjs/prices.js +172 -0
- package/dist/cjs/providers.d.ts +238 -0
- package/dist/cjs/providers.js +171 -0
- package/dist/cjs/quote-fees.d.ts +102 -0
- package/dist/cjs/quote-fees.js +201 -0
- package/dist/cjs/referral.d.ts +85 -0
- package/dist/cjs/referral.js +85 -0
- package/dist/cjs/relay-currencies.d.ts +47 -0
- package/dist/cjs/relay-currencies.js +95 -0
- package/dist/cjs/relay-depository.d.ts +2 -0
- package/dist/cjs/relay-depository.js +85 -0
- package/dist/cjs/relay-quote.d.ts +301 -0
- package/dist/cjs/relay-quote.js +996 -0
- package/dist/cjs/route-steps.d.ts +138 -0
- package/dist/cjs/route-steps.js +310 -0
- package/dist/cjs/routing/amounts.d.ts +80 -0
- package/dist/cjs/routing/amounts.js +126 -0
- package/dist/cjs/routing/candidate-route.d.ts +43 -0
- package/dist/cjs/routing/candidate-route.js +50 -0
- package/dist/cjs/routing/candidate.d.ts +237 -0
- package/dist/cjs/routing/candidate.js +100 -0
- package/dist/cjs/routing/carriers/ask-answer.d.ts +77 -0
- package/dist/cjs/routing/carriers/ask-answer.js +2 -0
- package/dist/cjs/routing/carriers/omnibridge.d.ts +137 -0
- package/dist/cjs/routing/carriers/omnibridge.js +459 -0
- package/dist/cjs/routing/carriers/pulsex-paths.d.ts +80 -0
- package/dist/cjs/routing/carriers/pulsex-paths.js +97 -0
- package/dist/cjs/routing/carriers/pulsex-split.d.ts +175 -0
- package/dist/cjs/routing/carriers/pulsex-split.js +193 -0
- package/dist/cjs/routing/carriers/pulsex.d.ts +159 -0
- package/dist/cjs/routing/carriers/pulsex.js +565 -0
- package/dist/cjs/routing/carriers/wrap.d.ts +25 -0
- package/dist/cjs/routing/carriers/wrap.js +119 -0
- package/dist/cjs/routing/composed-route-quality.d.ts +125 -0
- package/dist/cjs/routing/composed-route-quality.js +144 -0
- package/dist/cjs/routing/entry-chain-anchor.d.ts +88 -0
- package/dist/cjs/routing/entry-chain-anchor.js +59 -0
- package/dist/cjs/routing/format.d.ts +31 -0
- package/dist/cjs/routing/format.js +64 -0
- package/dist/cjs/routing/index.d.ts +38 -0
- package/dist/cjs/routing/index.js +134 -0
- package/dist/cjs/routing/producers.d.ts +770 -0
- package/dist/cjs/routing/producers.js +1617 -0
- package/dist/cjs/routing/providers.d.ts +31 -0
- package/dist/cjs/routing/providers.js +48 -0
- package/dist/cjs/routing/route-data.d.ts +355 -0
- package/dist/cjs/routing/route-data.js +2 -0
- package/dist/cjs/routing/search/compose.d.ts +168 -0
- package/dist/cjs/routing/search/compose.js +104 -0
- package/dist/cjs/routing/search/graph.d.ts +668 -0
- package/dist/cjs/routing/search/graph.js +461 -0
- package/dist/cjs/routing/search/plan-route-data.d.ts +269 -0
- package/dist/cjs/routing/search/plan-route-data.js +848 -0
- package/dist/cjs/routing/search/score.d.ts +356 -0
- package/dist/cjs/routing/search/score.js +445 -0
- package/dist/cjs/routing/swap-transactions.d.ts +91 -0
- package/dist/cjs/routing/swap-transactions.js +131 -0
- package/dist/cjs/routing/usd-value.d.ts +17 -0
- package/dist/cjs/routing/usd-value.js +29 -0
- package/dist/cjs/settings.d.ts +785 -0
- package/dist/cjs/settings.js +1074 -0
- package/dist/cjs/ton-connect.d.ts +98 -0
- package/dist/cjs/ton-connect.js +206 -0
- package/dist/cjs/ton-execution.d.ts +7 -0
- package/dist/cjs/ton-execution.js +23 -0
- package/dist/cjs/ton.d.ts +37 -0
- package/dist/cjs/ton.js +83 -0
- package/dist/cjs/tron-execution.d.ts +146 -0
- package/dist/cjs/tron-execution.js +248 -0
- package/dist/cjs/types.d.ts +51 -0
- package/dist/cjs/types.js +2 -0
- package/dist/claims.d.ts +198 -0
- package/dist/claims.js +140 -0
- package/dist/config.d.ts +24 -0
- package/dist/config.js +39 -5
- package/dist/consolidated-quote.d.ts +109 -15
- package/dist/consolidated-quote.js +310 -52
- package/dist/execution.d.ts +346 -0
- package/dist/execution.js +428 -0
- package/dist/hyperliquid-execution.js +2 -3
- package/dist/index.d.ts +3 -0
- package/dist/index.js +3 -0
- package/dist/lifi-execution-guard.d.ts +13 -2
- package/dist/lifi-execution-guard.js +4 -0
- package/dist/near-intents.js +2 -3
- package/dist/pre-quote.d.ts +6 -6
- package/dist/pre-quote.js +10 -14
- package/dist/providers.d.ts +17 -0
- package/dist/providers.js +6 -0
- package/dist/referral.d.ts +12 -4
- package/dist/referral.js +12 -4
- package/dist/relay-depository.d.ts +2 -0
- package/dist/relay-depository.js +82 -0
- package/dist/relay-quote.js +2 -3
- package/dist/routing/candidate.d.ts +3 -3
- package/dist/routing/candidate.js +3 -3
- package/dist/routing/carriers/ask-answer.d.ts +19 -0
- package/dist/routing/carriers/omnibridge.js +23 -21
- package/dist/routing/carriers/pulsex-paths.d.ts +80 -0
- package/dist/routing/carriers/pulsex-paths.js +92 -0
- package/dist/routing/carriers/pulsex-split.d.ts +175 -0
- package/dist/routing/carriers/pulsex-split.js +185 -0
- package/dist/routing/carriers/pulsex.d.ts +69 -21
- package/dist/routing/carriers/pulsex.js +184 -65
- package/dist/routing/composed-route-quality.d.ts +28 -6
- package/dist/routing/composed-route-quality.js +36 -5
- package/dist/routing/entry-chain-anchor.d.ts +1 -1
- package/dist/routing/entry-chain-anchor.js +1 -1
- package/dist/routing/index.d.ts +7 -3
- package/dist/routing/index.js +7 -3
- package/dist/routing/producers.js +1 -1
- package/dist/routing/providers.d.ts +5 -0
- package/dist/routing/providers.js +5 -0
- package/dist/routing/search/graph.d.ts +29 -0
- package/dist/routing/search/plan-route-data.d.ts +25 -0
- package/dist/routing/search/plan-route-data.js +43 -7
- package/dist/routing/search/score.d.ts +33 -1
- package/dist/routing/search/score.js +41 -6
- package/dist/routing/swap-transactions.d.ts +91 -0
- package/dist/routing/swap-transactions.js +125 -0
- package/dist/settings.d.ts +94 -1
- package/dist/settings.js +95 -3
- package/dist/ton-connect.d.ts +98 -0
- package/dist/ton-connect.js +200 -0
- package/dist/ton-execution.d.ts +4 -114
- package/dist/ton-execution.js +4 -244
- package/dist/ton.d.ts +37 -0
- package/dist/ton.js +65 -0
- package/docs/examples/example-a-ether-to-pulse.ts +300 -0
- package/docs/examples/example-b-token-pulsechain-to-ethereum.ts +270 -0
- package/docs/examples/shared.ts +261 -0
- package/docs/examples/tsconfig.json +18 -0
- package/docs/integration-guide.md +617 -0
- package/ecosystems/package.json +6 -0
- package/execution/package.json +6 -0
- package/fee-type/package.json +6 -0
- package/hyperliquid-execution/package.json +6 -0
- package/image-links/package.json +6 -0
- package/lifi-execution-guard/package.json +6 -0
- package/llms.txt +234 -0
- package/near-intents/package.json +6 -0
- package/near-intents-route/package.json +6 -0
- package/origin-deposit/package.json +6 -0
- package/package.json +818 -10
- package/pre-quote/package.json +6 -0
- package/prices/package.json +6 -0
- package/providers/package.json +6 -0
- package/quote-fees/package.json +6 -0
- package/referral/package.json +6 -0
- package/relay-currencies/package.json +6 -0
- package/relay-quote/package.json +6 -0
- package/route-steps/package.json +6 -0
- package/routing/package.json +6 -0
- package/settings/package.json +6 -0
- package/ton/package.json +6 -0
- package/ton-connect/package.json +6 -0
- package/ton-execution/package.json +6 -0
- package/tron-execution/package.json +6 -0
- package/types/package.json +6 -0
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.normalizeAddressIn = exports.isValidAddressIn = exports.isNativeAsset = exports.sameAddress = exports.ecosystemByCaipNamespace = exports.isEcosystemProvenEndToEnd = exports.ecosystemById = exports.ecosystemRegistry = void 0;
|
|
4
|
+
const viem_1 = require("viem");
|
|
5
|
+
// Solana public keys are base58 (no 0, O, I, l) and 32–44 characters long.
|
|
6
|
+
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
|
+
const bech32Bitcoin = /^bc1[0-9ac-hj-np-z]{6,87}$/;
|
|
9
|
+
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
|
+
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
|
+
const friendlyTon = /^[EUk0]Q[A-Za-z0-9_-]{46}$/;
|
|
18
|
+
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
|
+
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
|
+
const transparentZcash = /^t[13][1-9A-HJ-NP-Za-km-z]{33}$/;
|
|
31
|
+
const evmDescriptor = {
|
|
32
|
+
id: 'evm',
|
|
33
|
+
label: 'Ethereum Virtual Machine',
|
|
34
|
+
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
|
+
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
|
+
endToEndProof: 'verified',
|
|
43
|
+
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
|
+
normalizeAddress: (value) => ((0, viem_1.isAddress)(value) ? (0, viem_1.getAddress)(value) : value),
|
|
47
|
+
addressCasing: 'insensitive',
|
|
48
|
+
};
|
|
49
|
+
const svmDescriptor = {
|
|
50
|
+
id: 'svm',
|
|
51
|
+
label: 'Solana',
|
|
52
|
+
caipNamespace: 'solana',
|
|
53
|
+
// Solana native currency (the System Program address), as Relay expects it.
|
|
54
|
+
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
|
+
endToEndProof: 'pending',
|
|
61
|
+
isValidAddress: (value) => base58Solana.test(value),
|
|
62
|
+
// base58 is case-significant; canonical form is the input unchanged.
|
|
63
|
+
normalizeAddress: (value) => value,
|
|
64
|
+
addressCasing: 'significant',
|
|
65
|
+
};
|
|
66
|
+
const bvmDescriptor = {
|
|
67
|
+
id: 'bvm',
|
|
68
|
+
label: 'Bitcoin',
|
|
69
|
+
caipNamespace: 'bip122',
|
|
70
|
+
// Bitcoin native currency string, as Relay expects it.
|
|
71
|
+
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
|
+
endToEndProof: 'pending',
|
|
79
|
+
isValidAddress: (value) => bech32Bitcoin.test(value) || base58Bitcoin.test(value),
|
|
80
|
+
// bech32 and base58 are case-significant; canonical form is the input unchanged.
|
|
81
|
+
normalizeAddress: (value) => value,
|
|
82
|
+
addressCasing: 'significant',
|
|
83
|
+
};
|
|
84
|
+
const tvmDescriptor = {
|
|
85
|
+
id: 'tvm',
|
|
86
|
+
label: 'Tron',
|
|
87
|
+
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
|
+
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
|
+
endToEndProof: 'pending',
|
|
96
|
+
isValidAddress: (value) => base58Tron.test(value),
|
|
97
|
+
// base58check is case-significant; canonical form is the input unchanged.
|
|
98
|
+
normalizeAddress: (value) => value,
|
|
99
|
+
addressCasing: 'significant',
|
|
100
|
+
};
|
|
101
|
+
const tonvmDescriptor = {
|
|
102
|
+
id: 'tonvm',
|
|
103
|
+
label: 'The Open Network',
|
|
104
|
+
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
|
+
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
|
+
endToEndProof: 'pending',
|
|
114
|
+
isValidAddress: (value) => friendlyTon.test(value) || rawTon.test(value),
|
|
115
|
+
// both encodings are case-significant; canonical form is the input unchanged.
|
|
116
|
+
normalizeAddress: (value) => value,
|
|
117
|
+
addressCasing: 'significant',
|
|
118
|
+
};
|
|
119
|
+
const hypevmDescriptor = {
|
|
120
|
+
id: 'hypevm',
|
|
121
|
+
label: 'Hyperliquid',
|
|
122
|
+
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
|
+
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
|
+
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
|
+
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
|
+
normalizeAddress: (value) => hyperliquidTokenId.test(value) ? value.toLowerCase() : value,
|
|
149
|
+
addressCasing: 'significant',
|
|
150
|
+
};
|
|
151
|
+
const zcashDescriptor = {
|
|
152
|
+
id: 'zcash',
|
|
153
|
+
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
|
+
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
|
+
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
|
+
endToEndProof: 'pending',
|
|
173
|
+
isValidAddress: (value) => transparentZcash.test(value),
|
|
174
|
+
// base58check is case-significant; canonical form is the input unchanged.
|
|
175
|
+
normalizeAddress: (value) => value,
|
|
176
|
+
addressCasing: 'significant',
|
|
177
|
+
};
|
|
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
|
+
exports.ecosystemRegistry = [
|
|
189
|
+
evmDescriptor,
|
|
190
|
+
svmDescriptor,
|
|
191
|
+
bvmDescriptor,
|
|
192
|
+
tvmDescriptor,
|
|
193
|
+
tonvmDescriptor,
|
|
194
|
+
hypevmDescriptor,
|
|
195
|
+
zcashDescriptor,
|
|
196
|
+
];
|
|
197
|
+
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
|
+
const ecosystemById = (id) => {
|
|
207
|
+
const descriptor = byId.get(id);
|
|
208
|
+
if (descriptor === undefined) {
|
|
209
|
+
throw new Error(`no ecosystem descriptor registered for id "${id}"`);
|
|
210
|
+
}
|
|
211
|
+
return descriptor;
|
|
212
|
+
};
|
|
213
|
+
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
|
+
const isEcosystemProvenEndToEnd = (id) => (0, exports.ecosystemById)(id).endToEndProof === 'verified';
|
|
227
|
+
exports.isEcosystemProvenEndToEnd = isEcosystemProvenEndToEnd;
|
|
228
|
+
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
|
+
const ecosystemByCaipNamespace = (namespace) => byNamespace.get(namespace);
|
|
236
|
+
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
|
+
const sameAddress = (a, b, ecosystem) => (0, exports.ecosystemById)(ecosystem).addressCasing === 'insensitive'
|
|
253
|
+
? a.toLowerCase() === b.toLowerCase()
|
|
254
|
+
: a === b;
|
|
255
|
+
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
|
+
const isNativeAsset = (value, ecosystem) => (0, exports.sameAddress)(value, (0, exports.ecosystemById)(ecosystem).nativeAssetSentinel, ecosystem);
|
|
271
|
+
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
|
+
const isValidAddressIn = (value, ecosystem) => (0, exports.ecosystemById)(ecosystem).isValidAddress(value);
|
|
285
|
+
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
|
+
const normalizeAddressIn = (value, ecosystem) => (0, exports.ecosystemById)(ecosystem).normalizeAddress(value);
|
|
298
|
+
exports.normalizeAddressIn = normalizeAddressIn;
|
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
import { type Hex, type PublicClient } from 'viem';
|
|
2
|
+
import type { TokenBridgeInfo } from './chain-info.js';
|
|
3
|
+
import { type AggregatorOriginRefusal, type ConsolidatedQuote, type ConsolidatedQuoteRequest } from './consolidated-quote.js';
|
|
4
|
+
import type { FeeType } from './fee-type.js';
|
|
5
|
+
import type { RouteCandidate } from './routing/candidate.js';
|
|
6
|
+
import type { HopEdge, PlannedHop } from './routing/search/graph.js';
|
|
7
|
+
import type { ResolveNodeToken } from './routing/search/plan-route-data.js';
|
|
8
|
+
import type { BridgeKey, Token } from './types.js';
|
|
9
|
+
/**
|
|
10
|
+
* EXECUTION PLANS. Turns a chosen route into the ordered list of transactions
|
|
11
|
+
* a wallet sends, one {@link PlannedTx} at a time.
|
|
12
|
+
*
|
|
13
|
+
* Every builder here is the one the interface already signs with: the
|
|
14
|
+
* omnibridge call is `settings.ts`'s `transactionInputs`, the PulseX swap and
|
|
15
|
+
* the wrap are `routing/swap-transactions.ts`, the aggregator deposit is
|
|
16
|
+
* `consolidated-quote.ts`'s `aggregatorOriginCalls`, and the approval is
|
|
17
|
+
* `settings.ts`'s `approveCall` sized by `approvalAmounts`. This module only
|
|
18
|
+
* orders them and decides which approvals to skip.
|
|
19
|
+
*
|
|
20
|
+
* EVERY SPENDER IS ONE THIS CODE ALREADY KNOWS. Approvals are for the exact
|
|
21
|
+
* amount spent, never unlimited, and go only to:
|
|
22
|
+
* - the omnibridge pathway's `from` mediator, read from `config.ts`;
|
|
23
|
+
* - the PulseX router the edge was quoted on, read from `config.ts`;
|
|
24
|
+
* - an aggregator spender that `aggregatorOriginCalls` checked against a
|
|
25
|
+
* fixed table for its provider and chain (LI.FI's Diamond, Relay's
|
|
26
|
+
* depository). A quote cannot name its own spender.
|
|
27
|
+
*
|
|
28
|
+
* A PLAN IS ORDERED, AND EACH STEP WAITS FOR THE ONE BEFORE IT. An approval
|
|
29
|
+
* must land before the call that spends it, and a later section spends what
|
|
30
|
+
* the earlier one delivered. So every transaction except the last carries
|
|
31
|
+
* `waitForReceipt: true`.
|
|
32
|
+
*
|
|
33
|
+
* A RECEIPT IS NOT ARRIVAL. When a later section starts on a different chain
|
|
34
|
+
* than the one before it ends on, the earlier receipt only says the crossing
|
|
35
|
+
* started. The wallet must also wait for the funds to arrive on the next
|
|
36
|
+
* chain (the bridge indexer's delivery status) before it sends that section.
|
|
37
|
+
*/
|
|
38
|
+
/** What one planned transaction does. */
|
|
39
|
+
export type PlannedTxKind = 'approve' | 'bridge' | 'swap' | 'wrap' | 'unwrap' | 'claim';
|
|
40
|
+
/** One transaction for the wallet to sign and send, in plan order. */
|
|
41
|
+
export type PlannedTx = {
|
|
42
|
+
readonly chainId: number;
|
|
43
|
+
readonly kind: PlannedTxKind;
|
|
44
|
+
readonly to: Hex;
|
|
45
|
+
readonly data: Hex;
|
|
46
|
+
readonly value: bigint;
|
|
47
|
+
/** The gas limit the quote names, or null to let the wallet estimate it. */
|
|
48
|
+
readonly gasLimit: bigint | null;
|
|
49
|
+
/** True when the next transaction depends on this one, so the wallet must wait for its receipt first. */
|
|
50
|
+
readonly waitForReceipt: boolean;
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* Reads an ERC-20 allowance on chain.
|
|
54
|
+
*
|
|
55
|
+
* @param chainId - the chain the token lives on
|
|
56
|
+
* @param token - the token
|
|
57
|
+
* @param owner - the account that sends the plan
|
|
58
|
+
* @param spender - the contract that pulls the token
|
|
59
|
+
* @returns the current allowance, in the token's base units
|
|
60
|
+
*/
|
|
61
|
+
export type AllowanceReader = (chainId: number, token: Hex, owner: Hex, spender: Hex) => Promise<bigint>;
|
|
62
|
+
/**
|
|
63
|
+
* An {@link AllowanceReader} that reports no allowance anywhere, so the plan
|
|
64
|
+
* includes every approval. For a caller that reads allowances itself at send
|
|
65
|
+
* time.
|
|
66
|
+
*/
|
|
67
|
+
export declare const assumeNoAllowance: AllowanceReader;
|
|
68
|
+
/**
|
|
69
|
+
* The delivery fee terms, quoted before the plan is built. They become the
|
|
70
|
+
* on-chain fee director, so the reader sees exactly what the router may take.
|
|
71
|
+
*/
|
|
72
|
+
export type QuotedDeliveryFee = {
|
|
73
|
+
readonly feeType: FeeType;
|
|
74
|
+
/**
|
|
75
|
+
* The most the delivery router may take, in base units of {@link assetOut}.
|
|
76
|
+
* It is the fee director's `limit` in every mode: the fixed fee, the gas
|
|
77
|
+
* cap, or the percent fee's own cap.
|
|
78
|
+
*/
|
|
79
|
+
readonly maximumFee: bigint;
|
|
80
|
+
/** The percent rate as a fraction of one ether (5e14 is 0.05%). Read in percent mode only. */
|
|
81
|
+
readonly percentFee: bigint;
|
|
82
|
+
/** The tip over the gas cost as a fraction of one ether. Read in gas mode only. */
|
|
83
|
+
readonly gasTipFee: bigint;
|
|
84
|
+
/** The native-coin price in the delivered token, as `priceCorrective` reads it in `settings.ts`. */
|
|
85
|
+
readonly priceCorrective: bigint;
|
|
86
|
+
/** The token the destination router delivers and takes its fee in. */
|
|
87
|
+
readonly assetOut: Token;
|
|
88
|
+
};
|
|
89
|
+
/**
|
|
90
|
+
* Whether the reader buys delivery, and at what fee. There is no default: the
|
|
91
|
+
* caller states it.
|
|
92
|
+
*
|
|
93
|
+
* Only a pathway whose `requiresDelivery` is true sells delivery (PulseChain
|
|
94
|
+
* to Ethereum or BNB Smart Chain). On the way home to PulseChain the bridge
|
|
95
|
+
* itself delivers, so the only accepted choice there is `shouldDeliver: false`.
|
|
96
|
+
*/
|
|
97
|
+
export type DeliveryChoice = {
|
|
98
|
+
readonly shouldDeliver: false;
|
|
99
|
+
} | {
|
|
100
|
+
readonly shouldDeliver: true;
|
|
101
|
+
readonly fee: QuotedDeliveryFee;
|
|
102
|
+
};
|
|
103
|
+
/** A direct omnibridge crossing: `relayTokens`, `relayTokensAndCall`, `wrapAndRelayTokens` or `transferAndCall`. */
|
|
104
|
+
export type OmnibridgeLeg = {
|
|
105
|
+
readonly kind: 'omnibridge';
|
|
106
|
+
readonly bridgeKey: BridgeKey;
|
|
107
|
+
/** True reads only the mainnet pathways; false also reads the testnet ones. */
|
|
108
|
+
readonly isProd: boolean;
|
|
109
|
+
readonly assetIn: Token;
|
|
110
|
+
readonly assetLink: TokenBridgeInfo;
|
|
111
|
+
readonly amountIn: bigint;
|
|
112
|
+
readonly recipient: Hex;
|
|
113
|
+
readonly delivery: DeliveryChoice;
|
|
114
|
+
/** Whether the crossing unwraps to the native coin on arrival. Pass the value the pair allows, not only the reader's wish. */
|
|
115
|
+
readonly unwrap: boolean;
|
|
116
|
+
};
|
|
117
|
+
/** A PulseX swap, signed along the path its hop was priced on. */
|
|
118
|
+
export type PulseXSwapLeg = {
|
|
119
|
+
readonly kind: 'pulsex-swap';
|
|
120
|
+
readonly hop: Pick<PlannedHop, 'edge' | 'outcome'>;
|
|
121
|
+
readonly amountIn: bigint;
|
|
122
|
+
readonly minAmountOut: bigint;
|
|
123
|
+
readonly recipient: Hex;
|
|
124
|
+
/** The unix-seconds deadline the router enforces. */
|
|
125
|
+
readonly deadline: bigint;
|
|
126
|
+
};
|
|
127
|
+
/** A native-coin wrap or unwrap on the wrapped token's own contract. */
|
|
128
|
+
export type WrapLeg = {
|
|
129
|
+
readonly kind: 'wrap';
|
|
130
|
+
readonly edge: HopEdge;
|
|
131
|
+
readonly amountIn: bigint;
|
|
132
|
+
};
|
|
133
|
+
/** An aggregator's origin deposit, from a LIVE quote asked for the reader's own wallet. */
|
|
134
|
+
export type AggregatorLeg = {
|
|
135
|
+
readonly kind: 'aggregator';
|
|
136
|
+
readonly quote: ConsolidatedQuote;
|
|
137
|
+
readonly request: ConsolidatedQuoteRequest;
|
|
138
|
+
};
|
|
139
|
+
/** One signature's worth of work, in concrete terms. */
|
|
140
|
+
export type ExecutionLeg = OmnibridgeLeg | PulseXSwapLeg | WrapLeg | AggregatorLeg;
|
|
141
|
+
/** Why a leg or a section cannot be planned. */
|
|
142
|
+
export type ExecutionRefusal = {
|
|
143
|
+
readonly reason: 'amount-not-positive';
|
|
144
|
+
} | {
|
|
145
|
+
readonly reason: 'no-pathway';
|
|
146
|
+
} | {
|
|
147
|
+
readonly reason: 'delivery-not-offered';
|
|
148
|
+
} | {
|
|
149
|
+
readonly reason: 'delivery-fee-missing';
|
|
150
|
+
} | {
|
|
151
|
+
readonly reason: 'delivery-fee-unencodable';
|
|
152
|
+
} | {
|
|
153
|
+
readonly reason: 'bridge-call-refused';
|
|
154
|
+
} | {
|
|
155
|
+
readonly reason: 'swap-refused';
|
|
156
|
+
} | {
|
|
157
|
+
readonly reason: 'swap-estimate-only';
|
|
158
|
+
} | {
|
|
159
|
+
readonly reason: 'swap-quote-not-positive';
|
|
160
|
+
} | {
|
|
161
|
+
readonly reason: 'wrap-refused';
|
|
162
|
+
} | {
|
|
163
|
+
readonly reason: 'aggregator-origin-refused';
|
|
164
|
+
readonly origin: AggregatorOriginRefusal;
|
|
165
|
+
} | {
|
|
166
|
+
readonly reason: 'live-quote-required';
|
|
167
|
+
} | {
|
|
168
|
+
readonly reason: 'quote-provider-mismatch';
|
|
169
|
+
readonly quoteProvider: string;
|
|
170
|
+
readonly sectionCarrier: string;
|
|
171
|
+
} | {
|
|
172
|
+
readonly reason: 'paid-by-hand';
|
|
173
|
+
} | {
|
|
174
|
+
readonly reason: 'section-inputs-missing';
|
|
175
|
+
readonly needs: 'omnibridge' | 'swap';
|
|
176
|
+
} | {
|
|
177
|
+
readonly reason: 'section-shape';
|
|
178
|
+
readonly detail: string;
|
|
179
|
+
};
|
|
180
|
+
/** The delivery one omnibridge leg buys. */
|
|
181
|
+
export type DeliveryTerms = {
|
|
182
|
+
readonly status: 'not-requested';
|
|
183
|
+
} | {
|
|
184
|
+
readonly status: 'requested';
|
|
185
|
+
readonly feeType: FeeType;
|
|
186
|
+
/** The most the router may take, in base units of {@link feeToken}. */
|
|
187
|
+
readonly maximumFee: bigint;
|
|
188
|
+
readonly feeToken: Token;
|
|
189
|
+
};
|
|
190
|
+
/** The delivery a planned leg buys, so the wallet can show the fee before signing. */
|
|
191
|
+
export type PlannedDelivery = DeliveryTerms & {
|
|
192
|
+
readonly legIndex: number;
|
|
193
|
+
};
|
|
194
|
+
/** The transactions for a list of legs, or the first leg that cannot be planned. */
|
|
195
|
+
export type ExecutionPlan = {
|
|
196
|
+
readonly kind: 'planned';
|
|
197
|
+
readonly transactions: readonly PlannedTx[];
|
|
198
|
+
/** One entry per omnibridge leg, in leg order. */
|
|
199
|
+
readonly deliveries: readonly PlannedDelivery[];
|
|
200
|
+
} | {
|
|
201
|
+
readonly kind: 'refused';
|
|
202
|
+
readonly legIndex: number;
|
|
203
|
+
readonly refusal: ExecutionRefusal;
|
|
204
|
+
};
|
|
205
|
+
/**
|
|
206
|
+
* Plans the transactions for a list of legs, in order.
|
|
207
|
+
*
|
|
208
|
+
* Each leg contributes the exact approval it needs when the allowance on
|
|
209
|
+
* chain does not cover it (a reset to zero first when a smaller allowance
|
|
210
|
+
* remains), then its own call. Nothing is sent.
|
|
211
|
+
*
|
|
212
|
+
* @param options.account - the account that signs every transaction
|
|
213
|
+
* @param options.legs - the legs, in the order the wallet signs them
|
|
214
|
+
* @param options.readAllowance - reads an allowance on chain; see {@link AllowanceReader}
|
|
215
|
+
* @returns the ordered transactions, or the first leg that cannot be planned
|
|
216
|
+
*/
|
|
217
|
+
export declare const planExecution: ({ account, legs, readAllowance, }: {
|
|
218
|
+
readonly account: Hex;
|
|
219
|
+
readonly legs: readonly ExecutionLeg[];
|
|
220
|
+
readonly readAllowance: AllowanceReader;
|
|
221
|
+
}) => Promise<ExecutionPlan>;
|
|
222
|
+
/**
|
|
223
|
+
* What the caller supplies for one signature section of a candidate. Each
|
|
224
|
+
* kind-specific group is read only when the section needs it.
|
|
225
|
+
*/
|
|
226
|
+
export type SectionExecutionInputs = {
|
|
227
|
+
/** The amount this section spends, in its first token's base units. */
|
|
228
|
+
readonly amountIn: bigint;
|
|
229
|
+
/** Where this section delivers: the reader's own wallet, or their chosen address on the last section. */
|
|
230
|
+
readonly recipient: Hex;
|
|
231
|
+
/** Needed by an omnibridge section. */
|
|
232
|
+
readonly omnibridge?: {
|
|
233
|
+
readonly isProd: boolean;
|
|
234
|
+
readonly assetLink: TokenBridgeInfo;
|
|
235
|
+
readonly delivery: DeliveryChoice;
|
|
236
|
+
readonly unwrap: boolean;
|
|
237
|
+
};
|
|
238
|
+
/** Needed by a PulseX swap section. */
|
|
239
|
+
readonly swap?: {
|
|
240
|
+
readonly slippageBasisPoints: bigint;
|
|
241
|
+
/**
|
|
242
|
+
* The unix-seconds deadline the router enforces. A section planned late
|
|
243
|
+
* should pass a fresh deadline, not one chosen before the crossing before it.
|
|
244
|
+
*/
|
|
245
|
+
readonly deadline: bigint;
|
|
246
|
+
/**
|
|
247
|
+
* A fresh quote of what the swap delivers for this section's `amountIn`,
|
|
248
|
+
* read just before signing (see {@link readPulseXSectionQuote}). When
|
|
249
|
+
* given, the slippage floor comes from it and not from the hop's
|
|
250
|
+
* search-time figure, so the hop may be an estimate. When absent, the
|
|
251
|
+
* floor comes from the hop, which must hold a real quote.
|
|
252
|
+
*/
|
|
253
|
+
readonly quotedAmountOut?: bigint;
|
|
254
|
+
};
|
|
255
|
+
/**
|
|
256
|
+
* Needed by an aggregator section: the LIVE quote asked for this reader's
|
|
257
|
+
* wallet, recipient and amount, with the request it answered. A route's
|
|
258
|
+
* display price is a dry probe and cannot be signed, so the candidate's own
|
|
259
|
+
* quote is never used in its place.
|
|
260
|
+
*/
|
|
261
|
+
readonly aggregator?: {
|
|
262
|
+
readonly quote: ConsolidatedQuote;
|
|
263
|
+
readonly request: ConsolidatedQuoteRequest;
|
|
264
|
+
};
|
|
265
|
+
};
|
|
266
|
+
/** What {@link planCandidateExecution} reads. */
|
|
267
|
+
export type CandidateExecutionInputs = {
|
|
268
|
+
readonly candidate: RouteCandidate;
|
|
269
|
+
readonly account: Hex;
|
|
270
|
+
readonly readAllowance: AllowanceReader;
|
|
271
|
+
/** The resolver the candidate was built with; turns a plan's graph node into its token. */
|
|
272
|
+
readonly resolveToken: ResolveNodeToken;
|
|
273
|
+
/**
|
|
274
|
+
* The index of the section that `sections[0]` plans. It defaults to 0.
|
|
275
|
+
* Pass it to plan a later section after the earlier ones landed, with the
|
|
276
|
+
* amount that actually arrived and fresh swap figures. Then `sections[i]`
|
|
277
|
+
* plans section `firstSectionIndex + i`.
|
|
278
|
+
*/
|
|
279
|
+
readonly firstSectionIndex?: number;
|
|
280
|
+
/**
|
|
281
|
+
* One entry per section to plan now, first section first. Pass one entry
|
|
282
|
+
* to plan only the signature the reader can make now; pass more to plan
|
|
283
|
+
* later sections whose amounts are already known.
|
|
284
|
+
*/
|
|
285
|
+
readonly sections: readonly SectionExecutionInputs[];
|
|
286
|
+
};
|
|
287
|
+
/**
|
|
288
|
+
* The transactions for the planned sections of a candidate, or the first
|
|
289
|
+
* section that cannot be planned. Every section index is absolute: it counts
|
|
290
|
+
* from the first section of the candidate, not from `firstSectionIndex`.
|
|
291
|
+
*/
|
|
292
|
+
export type CandidateExecutionPlan = {
|
|
293
|
+
readonly kind: 'planned';
|
|
294
|
+
readonly transactions: readonly PlannedTx[];
|
|
295
|
+
/** One entry per omnibridge section planned; `legIndex` is the absolute section index. */
|
|
296
|
+
readonly deliveries: readonly PlannedDelivery[];
|
|
297
|
+
/** How many sections still follow the planned ones (after `firstSectionIndex + sections.length`). Each needs its own plan later. */
|
|
298
|
+
readonly remainingSectionCount: number;
|
|
299
|
+
} | {
|
|
300
|
+
readonly kind: 'refused';
|
|
301
|
+
readonly sectionIndex: number;
|
|
302
|
+
readonly refusal: ExecutionRefusal;
|
|
303
|
+
};
|
|
304
|
+
/**
|
|
305
|
+
* Plans the transactions for a chosen route candidate: the candidate
|
|
306
|
+
* `buildRouteCandidateFromPlan` returns for an engine plan (the interface's
|
|
307
|
+
* `buildCandidateFromEnginePlan`), or a candidate built without a plan.
|
|
308
|
+
*
|
|
309
|
+
* ONE SECTION IS ONE SIGNATURE. A plan's `signatures` groups its hops into
|
|
310
|
+
* sections; the section's first hop names its carrier. An omnibridge section
|
|
311
|
+
* becomes a crossing, a PulseX section a swap signed on its recorded path, a
|
|
312
|
+
* wrap section a wrap or unwrap, and any other wallet-signed carrier an
|
|
313
|
+
* aggregator deposit from the live quote the caller supplies. A section paid
|
|
314
|
+
* by hand has nothing to sign and is refused.
|
|
315
|
+
*
|
|
316
|
+
* A LATER SECTION CAN BE PLANNED ALONE. Pass `firstSectionIndex` to skip the
|
|
317
|
+
* sections that already landed. The wallet then plans the swap after the
|
|
318
|
+
* crossing arrived, from the amount that arrived, with a fresh
|
|
319
|
+
* `swap.quotedAmountOut` and a fresh `swap.deadline`. The slippage floor and the
|
|
320
|
+
* deadline are not fixed minutes before the swap is signed. Every safety check
|
|
321
|
+
* still applies to the later section: verified spenders, live quotes for
|
|
322
|
+
* aggregator sections, exact approvals.
|
|
323
|
+
*
|
|
324
|
+
* Every `sectionIndex` in a refusal and every `legIndex` in `deliveries` is
|
|
325
|
+
* the absolute section index.
|
|
326
|
+
*
|
|
327
|
+
* @param inputs - see {@link CandidateExecutionInputs}
|
|
328
|
+
* @returns the ordered transactions with the deliveries they buy, or the first section that cannot be planned
|
|
329
|
+
*/
|
|
330
|
+
export declare const planCandidateExecution: (inputs: CandidateExecutionInputs) => Promise<CandidateExecutionPlan>;
|
|
331
|
+
/**
|
|
332
|
+
* Reads a fresh quote for a PulseX section: what the router's `getAmountsOut`
|
|
333
|
+
* says the swap delivers for `amountIn`, along the exact path the swap signs
|
|
334
|
+
* ({@link pulseXSwapPathForHop}) on the edge's own router. A wallet passes the
|
|
335
|
+
* result as `swap.quotedAmountOut` just before it signs.
|
|
336
|
+
*
|
|
337
|
+
* @param options.hop - the swap hop; its recorded path and edge name what to read
|
|
338
|
+
* @param options.amountIn - the amount the swap spends, in base units
|
|
339
|
+
* @param options.client - a client that can call `readContract`
|
|
340
|
+
* @returns the amount the last token of the path delivers, or null when the hop records no path, names no known router, the amount is not positive, or the read fails or returns nothing
|
|
341
|
+
*/
|
|
342
|
+
export declare const readPulseXSectionQuote: ({ hop, amountIn, client, }: {
|
|
343
|
+
readonly hop: Pick<PlannedHop, "edge" | "outcome">;
|
|
344
|
+
readonly amountIn: bigint;
|
|
345
|
+
readonly client: Pick<PublicClient, "readContract">;
|
|
346
|
+
}) => Promise<bigint | null>;
|