@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.
Files changed (111) hide show
  1. package/dist/abis.js +0 -2
  2. package/dist/bridge-limits.js +0 -38
  3. package/dist/chain-info.js +0 -116
  4. package/dist/chain-names.js +0 -151
  5. package/dist/chains.js +0 -198
  6. package/dist/cjs/abis.js +0 -2
  7. package/dist/cjs/bridge-limits.js +0 -38
  8. package/dist/cjs/chain-info.js +0 -116
  9. package/dist/cjs/chain-names.js +0 -151
  10. package/dist/cjs/chains.js +0 -198
  11. package/dist/cjs/claims.js +0 -60
  12. package/dist/cjs/config.js +1 -208
  13. package/dist/cjs/consolidated-quote.js +0 -465
  14. package/dist/cjs/destination-calldata.js +0 -71
  15. package/dist/cjs/ecosystems.js +0 -183
  16. package/dist/cjs/execution.js +0 -92
  17. package/dist/cjs/fee-type.js +0 -1
  18. package/dist/cjs/hyperliquid-execution.js +0 -98
  19. package/dist/cjs/image-links.js +0 -108
  20. package/dist/cjs/lifi-execution-guard.js +65 -172
  21. package/dist/cjs/near-intents-conformance.js +0 -110
  22. package/dist/cjs/near-intents-route.js +0 -149
  23. package/dist/cjs/near-intents.js +0 -562
  24. package/dist/cjs/origin-deposit.js +0 -56
  25. package/dist/cjs/pre-quote.js +0 -80
  26. package/dist/cjs/prices.js +0 -113
  27. package/dist/cjs/providers.js +0 -83
  28. package/dist/cjs/quote-fees.js +0 -80
  29. package/dist/cjs/referral.js +0 -75
  30. package/dist/cjs/relay-currencies.js +0 -31
  31. package/dist/cjs/relay-depository.js +52 -77
  32. package/dist/cjs/relay-quote.js +0 -394
  33. package/dist/cjs/route-steps.js +0 -100
  34. package/dist/cjs/routing/amounts.js +0 -83
  35. package/dist/cjs/routing/candidate-route.js +0 -73
  36. package/dist/cjs/routing/candidate.js +0 -46
  37. package/dist/cjs/routing/carrier-provider-key.js +0 -27
  38. package/dist/cjs/routing/carriers/omnibridge.js +0 -120
  39. package/dist/cjs/routing/carriers/pulsex-paths.js +0 -57
  40. package/dist/cjs/routing/carriers/pulsex-split.js +0 -92
  41. package/dist/cjs/routing/carriers/pulsex.js +0 -279
  42. package/dist/cjs/routing/carriers/wrap.js +0 -57
  43. package/dist/cjs/routing/composed-route-quality.js +0 -95
  44. package/dist/cjs/routing/entry-chain-anchor.js +0 -27
  45. package/dist/cjs/routing/format.js +0 -50
  46. package/dist/cjs/routing/index.js +0 -28
  47. package/dist/cjs/routing/producers.js +0 -854
  48. package/dist/cjs/routing/providers.js +0 -27
  49. package/dist/cjs/routing/search/compose.js +0 -56
  50. package/dist/cjs/routing/search/graph.js +0 -364
  51. package/dist/cjs/routing/search/plan-route-data.js +0 -508
  52. package/dist/cjs/routing/search/score.js +0 -344
  53. package/dist/cjs/routing/swap-transactions.js +0 -74
  54. package/dist/cjs/routing/usd-value.js +0 -12
  55. package/dist/cjs/settings.js +1 -456
  56. package/dist/cjs/swap-venues.js +0 -17
  57. package/dist/cjs/ton-connect.js +0 -82
  58. package/dist/cjs/ton-execution.js +0 -6
  59. package/dist/cjs/ton.js +0 -42
  60. package/dist/cjs/tron-execution.js +0 -145
  61. package/dist/claims.js +0 -60
  62. package/dist/config.js +1 -211
  63. package/dist/consolidated-quote.js +0 -465
  64. package/dist/destination-calldata.js +0 -71
  65. package/dist/ecosystems.js +0 -183
  66. package/dist/execution.js +0 -92
  67. package/dist/fee-type.js +0 -2
  68. package/dist/hyperliquid-execution.js +0 -98
  69. package/dist/image-links.js +0 -108
  70. package/dist/lifi-execution-guard.js +65 -172
  71. package/dist/near-intents-conformance.js +0 -110
  72. package/dist/near-intents-route.js +0 -149
  73. package/dist/near-intents.js +0 -562
  74. package/dist/origin-deposit.js +0 -56
  75. package/dist/pre-quote.js +0 -80
  76. package/dist/prices.js +0 -113
  77. package/dist/providers.js +0 -83
  78. package/dist/quote-fees.js +0 -80
  79. package/dist/referral.js +0 -75
  80. package/dist/relay-currencies.js +0 -31
  81. package/dist/relay-depository.js +52 -77
  82. package/dist/relay-quote.js +0 -394
  83. package/dist/route-steps.js +0 -100
  84. package/dist/routing/amounts.js +0 -83
  85. package/dist/routing/candidate-route.js +0 -73
  86. package/dist/routing/candidate.js +0 -46
  87. package/dist/routing/carrier-provider-key.js +0 -27
  88. package/dist/routing/carriers/omnibridge.js +0 -120
  89. package/dist/routing/carriers/pulsex-paths.js +0 -57
  90. package/dist/routing/carriers/pulsex-split.js +0 -92
  91. package/dist/routing/carriers/pulsex.js +0 -279
  92. package/dist/routing/carriers/wrap.js +0 -57
  93. package/dist/routing/composed-route-quality.js +0 -95
  94. package/dist/routing/entry-chain-anchor.js +0 -27
  95. package/dist/routing/format.js +0 -50
  96. package/dist/routing/index.js +0 -28
  97. package/dist/routing/producers.js +0 -854
  98. package/dist/routing/providers.js +0 -27
  99. package/dist/routing/search/compose.js +0 -56
  100. package/dist/routing/search/graph.js +0 -364
  101. package/dist/routing/search/plan-route-data.js +0 -508
  102. package/dist/routing/search/score.js +0 -344
  103. package/dist/routing/swap-transactions.js +0 -74
  104. package/dist/routing/usd-value.js +0 -12
  105. package/dist/settings.js +1 -456
  106. package/dist/swap-venues.js +0 -17
  107. package/dist/ton-connect.js +0 -82
  108. package/dist/ton-execution.js +0 -6
  109. package/dist/ton.js +0 -42
  110. package/dist/tron-execution.js +0 -145
  111. 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,
@@ -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;
@@ -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)
@@ -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]));