@gibs/bridge-sdk 1.18.0 → 1.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (120) hide show
  1. package/README.md +33 -0
  2. package/dist/abis.js +0 -2
  3. package/dist/bridge-limits.js +0 -38
  4. package/dist/chain-info.js +0 -116
  5. package/dist/chain-names.js +0 -151
  6. package/dist/chains.js +0 -198
  7. package/dist/cjs/abis.js +0 -2
  8. package/dist/cjs/bridge-limits.js +0 -38
  9. package/dist/cjs/chain-info.js +0 -116
  10. package/dist/cjs/chain-names.js +0 -151
  11. package/dist/cjs/chains.js +0 -198
  12. package/dist/cjs/claims.js +0 -60
  13. package/dist/cjs/config.js +1 -208
  14. package/dist/cjs/consolidated-quote.js +2 -464
  15. package/dist/cjs/destination-calldata.js +0 -71
  16. package/dist/cjs/ecosystems.js +0 -183
  17. package/dist/cjs/execution.js +0 -92
  18. package/dist/cjs/fee-type.js +0 -1
  19. package/dist/cjs/hyperliquid-execution.js +0 -98
  20. package/dist/cjs/image-links.js +0 -108
  21. package/dist/cjs/lifi-execution-guard.js +65 -172
  22. package/dist/cjs/near-intents-conformance.js +0 -110
  23. package/dist/cjs/near-intents-route.d.ts +13 -0
  24. package/dist/cjs/near-intents-route.js +7 -140
  25. package/dist/cjs/near-intents.js +0 -562
  26. package/dist/cjs/origin-deposit.js +0 -56
  27. package/dist/cjs/pre-quote.js +0 -80
  28. package/dist/cjs/prices.js +0 -113
  29. package/dist/cjs/providers.js +0 -83
  30. package/dist/cjs/quote-fees.js +0 -80
  31. package/dist/cjs/referral.js +0 -75
  32. package/dist/cjs/relay-currencies.js +0 -31
  33. package/dist/cjs/relay-depository.js +52 -77
  34. package/dist/cjs/relay-quote.js +0 -394
  35. package/dist/cjs/route-steps.js +0 -100
  36. package/dist/cjs/routing/amounts.js +0 -83
  37. package/dist/cjs/routing/candidate-route.d.ts +46 -1
  38. package/dist/cjs/routing/candidate-route.js +12 -40
  39. package/dist/cjs/routing/candidate.js +0 -46
  40. package/dist/cjs/routing/carrier-provider-key.js +0 -27
  41. package/dist/cjs/routing/carriers/omnibridge.js +0 -120
  42. package/dist/cjs/routing/carriers/pulsex-paths.js +0 -57
  43. package/dist/cjs/routing/carriers/pulsex-split.js +0 -92
  44. package/dist/cjs/routing/carriers/pulsex.js +0 -279
  45. package/dist/cjs/routing/carriers/wrap.js +0 -57
  46. package/dist/cjs/routing/composed-route-quality.js +0 -95
  47. package/dist/cjs/routing/entry-chain-anchor.js +0 -27
  48. package/dist/cjs/routing/format.js +0 -50
  49. package/dist/cjs/routing/index.d.ts +1 -1
  50. package/dist/cjs/routing/index.js +3 -30
  51. package/dist/cjs/routing/producers.js +0 -854
  52. package/dist/cjs/routing/providers.js +0 -27
  53. package/dist/cjs/routing/search/compose.js +0 -56
  54. package/dist/cjs/routing/search/graph.js +0 -364
  55. package/dist/cjs/routing/search/plan-route-data.js +5 -510
  56. package/dist/cjs/routing/search/score.js +0 -344
  57. package/dist/cjs/routing/swap-transactions.js +0 -74
  58. package/dist/cjs/routing/usd-value.js +0 -12
  59. package/dist/cjs/settings.js +1 -456
  60. package/dist/cjs/swap-venues.js +0 -17
  61. package/dist/cjs/ton-connect.js +0 -82
  62. package/dist/cjs/ton-execution.js +0 -6
  63. package/dist/cjs/ton.js +0 -42
  64. package/dist/cjs/tron-execution.js +0 -145
  65. package/dist/cjs/types.d.ts +8 -0
  66. package/dist/claims.js +0 -60
  67. package/dist/config.js +1 -211
  68. package/dist/consolidated-quote.js +2 -464
  69. package/dist/destination-calldata.js +0 -71
  70. package/dist/ecosystems.js +0 -183
  71. package/dist/execution.js +0 -92
  72. package/dist/fee-type.js +0 -2
  73. package/dist/hyperliquid-execution.js +0 -98
  74. package/dist/image-links.js +0 -108
  75. package/dist/lifi-execution-guard.js +65 -172
  76. package/dist/near-intents-conformance.js +0 -110
  77. package/dist/near-intents-route.d.ts +13 -0
  78. package/dist/near-intents-route.js +5 -139
  79. package/dist/near-intents.js +0 -562
  80. package/dist/origin-deposit.js +0 -56
  81. package/dist/pre-quote.js +0 -80
  82. package/dist/prices.js +0 -113
  83. package/dist/providers.js +0 -83
  84. package/dist/quote-fees.js +0 -80
  85. package/dist/referral.js +0 -75
  86. package/dist/relay-currencies.js +0 -31
  87. package/dist/relay-depository.js +52 -77
  88. package/dist/relay-quote.js +0 -394
  89. package/dist/route-steps.js +0 -100
  90. package/dist/routing/amounts.js +0 -83
  91. package/dist/routing/candidate-route.d.ts +46 -1
  92. package/dist/routing/candidate-route.js +10 -39
  93. package/dist/routing/candidate.js +0 -46
  94. package/dist/routing/carrier-provider-key.js +0 -27
  95. package/dist/routing/carriers/omnibridge.js +0 -120
  96. package/dist/routing/carriers/pulsex-paths.js +0 -57
  97. package/dist/routing/carriers/pulsex-split.js +0 -92
  98. package/dist/routing/carriers/pulsex.js +0 -279
  99. package/dist/routing/carriers/wrap.js +0 -57
  100. package/dist/routing/composed-route-quality.js +0 -95
  101. package/dist/routing/entry-chain-anchor.js +0 -27
  102. package/dist/routing/format.js +0 -50
  103. package/dist/routing/index.d.ts +1 -1
  104. package/dist/routing/index.js +1 -29
  105. package/dist/routing/producers.js +0 -854
  106. package/dist/routing/providers.js +0 -27
  107. package/dist/routing/search/compose.js +0 -56
  108. package/dist/routing/search/graph.js +0 -364
  109. package/dist/routing/search/plan-route-data.js +6 -511
  110. package/dist/routing/search/score.js +0 -344
  111. package/dist/routing/swap-transactions.js +0 -74
  112. package/dist/routing/usd-value.js +0 -12
  113. package/dist/settings.js +1 -456
  114. package/dist/swap-venues.js +0 -17
  115. package/dist/ton-connect.js +0 -82
  116. package/dist/ton-execution.js +0 -6
  117. package/dist/ton.js +0 -42
  118. package/dist/tron-execution.js +0 -145
  119. package/dist/types.d.ts +8 -0
  120. package/package.json +3 -3
package/README.md CHANGED
@@ -441,6 +441,39 @@ if (plan.kind === 'refused') throw new Error(plan.refusal.reason);
441
441
  asked for your wallet, in `sections[i].aggregator`. The candidate's own quote
442
442
  priced the route on screen and is never signed.
443
443
 
444
+ ### Counting signatures, approvals included
445
+
446
+ `routeSignatureCount(route)` counts sections only, so a USDC route reads 1 and
447
+ then asks for two prompts. It leaves out approvals. Use
448
+ `routeSignatureCountForAccount` for the number the wallet will really ask for:
449
+
450
+ ```ts
451
+ import {
452
+ type AllowanceReader,
453
+ type ResolveNodeToken,
454
+ type RouteCandidate,
455
+ type SectionExecutionInputs,
456
+ routeSignatureCountForAccount,
457
+ } from '@gibs/bridge-sdk';
458
+ import type { Hex } from 'viem';
459
+
460
+ declare const candidate: RouteCandidate;
461
+ declare const account: Hex;
462
+ declare const readAllowance: AllowanceReader;
463
+ declare const resolveToken: ResolveNodeToken;
464
+ declare const sections: SectionExecutionInputs[];
465
+
466
+ const { signatures, approvals, total } = await routeSignatureCountForAccount({
467
+ candidate, account, readAllowance, resolveToken, sections,
468
+ });
469
+ ```
470
+
471
+ It takes the inputs `planCandidateExecution` takes and counts the plan, so it
472
+ uses the same allowance rule and the same spender (mediator, swap router, or
473
+ aggregator address). A native input and a covered allowance add no approval. A
474
+ short, non-zero allowance counts two approvals (reset, then approve). It throws
475
+ when a section cannot be planned.
476
+
444
477
  ## Overriding swap routers
445
478
 
446
479
  The package swaps on PulseX V1 and V2 on PulseChain by default. You can swap on
package/dist/abis.js CHANGED
@@ -1,3 +1 @@
1
- // All ABIs have moved to the standalone @gibs/abis package.
2
- // This module re-exports everything for backwards compatibility.
3
1
  export * from '@gibs/abis';
@@ -1,25 +1,8 @@
1
1
  import { parseAbi } from 'viem';
2
- /**
3
- * Exported so a batched reader (`routing/carriers/omnibridge.ts`'s `prepare`)
4
- * can multicall the same two functions across many tokens in one call rather
5
- * than duplicating this ABI.
6
- */
7
2
  export const entryLimitsAbi = parseAbi([
8
3
  'function minPerTx(address token) external view returns(uint256)',
9
4
  'function maxAvailablePerTx(address token) external view returns(uint256)',
10
5
  ]);
11
- /**
12
- * Reads the bounds the entry mediator will enforce on this exact call.
13
- *
14
- * IT TAKES THE CALL, NOT A MEDIATOR AND A TOKEN. The two travel together on the
15
- * destination call precisely so a caller cannot pair one route's mediator with
16
- * another route's token and get a plausible number back — the reads would
17
- * succeed and the answer would be about a transfer nobody is making.
18
- *
19
- * @param destinationCall - the entry call, or null when none could be built
20
- * @param entryChainClient - a client on the chain the funds leave
21
- * @returns the two bounds, or null when there is no call to measure
22
- */
23
6
  export const bridgeEntryLimits = async ({ destinationCall, entryChainClient, }) => {
24
7
  if (!destinationCall) {
25
8
  return null;
@@ -41,28 +24,7 @@ export const bridgeEntryLimits = async ({ destinationCall, entryChainClient, })
41
24
  ]);
42
25
  return { minimumPerTransaction, availablePerTransaction };
43
26
  };
44
- /**
45
- * Decides whether an amount can enter the bridge.
46
- *
47
- * WHY THIS IS WORTH CHECKING BEFORE A ROUTE IS OFFERED: on a consolidated
48
- * route the entry call is made by an aggregator's executor, not by the user.
49
- * When the mediator rejects the amount the executor's call reverts, the
50
- * aggregator has already delivered the funds, and they stop at the fallback
51
- * address on the entry chain. The user is left holding an entry-chain token
52
- * and a second transfer to make. Refusing the quote costs them nothing.
53
- *
54
- * The bounds are inclusive: the mediator accepts an amount equal to either.
55
- *
56
- * @param amount - the transfer, in the token's base units
57
- * @param limits - the bounds from {@link bridgeEntryLimits}, or null when they
58
- * could not be read
59
- * @returns a verdict naming the bound that was missed
60
- */
61
27
  export const checkEntryAmount = ({ amount, limits, }) => {
62
- // An unread limit is not a failed one. A network hiccup must not block a
63
- // route that the mediator would accept — the transaction still gets the
64
- // mediator's own answer, and this guard exists to save the user a wasted
65
- // crossing, not to be the only thing standing between them and a revert.
66
28
  if (!limits) {
67
29
  return { fits: true };
68
30
  }
@@ -4,34 +4,8 @@ import { encodeFunctionData, getContract, multicall3Abi, zeroAddress, } from 'vi
4
4
  import * as abis from './abis.js';
5
5
  import { chainsMetadata } from './chains.js';
6
6
  import { nativeAssetOut, pathway, toChain, uniV2Routers, } from './config.js';
7
- /** Cache key for the links memoize: one entry per (chain, bridge, token) triple. */
8
7
  const linksCacheKey = ({ chainId, target, address, }) => `${chainId}-${target}-${address}`.toLowerCase();
9
- /**
10
- * Whether a {@link links} answer says the token has no mapping on this bridge
11
- * yet. That answer is temporary: the first transfer of the token creates the
12
- * mapping, so it must not be cached.
13
- * @param pair - the bridged and native addresses the mediator returned
14
- * @returns true when both are the zero address
15
- */
16
8
  const isUnmappedAnswer = ([bridged, native]) => bridged === zeroAddress && native === zeroAddress;
17
- /**
18
- * Returns the bridged token address and native token address that a mediator
19
- * holds for one token.
20
- *
21
- * A non-zero answer is cached for the life of the process: a mediator never
22
- * changes a mapping once the first transfer creates it. A failed read, and a
23
- * `[zero, zero]` answer (the token is not bridged yet), are not cached, so the
24
- * next call reads the chain again. Call {@link clearChainInfoCaches} to drop
25
- * every cached answer.
26
- *
27
- * @param inputs.chainId - the chain id being targeted
28
- * @param inputs.target - the mediator to ask
29
- * @param inputs.address - the token address
30
- * @param inputs.client - a client for that chain
31
- * @returns the bridged token address and native token address
32
- */
33
- // The body reaches for `links.cache` to evict an answer, so the cache surface
34
- // is spelled out to the extent this file uses it.
35
9
  export const links = memoizeByKey(async (inputs) => {
36
10
  const { chainId, target, address, client } = inputs;
37
11
  const evict = () => links.cache.delete(linksCacheKey(inputs));
@@ -45,34 +19,17 @@ export const links = memoizeByKey(async (inputs) => {
45
19
  { functionName: 'nativeTokenAddress', args: [address] },
46
20
  ],
47
21
  }).catch((error) => {
48
- // a transient read failure must not poison the cache for the session
49
22
  evict();
50
23
  throw error;
51
24
  });
52
25
  if (isUnmappedAnswer(pair)) {
53
- // the token may be bridged a minute from now; ask again next time
54
26
  evict();
55
27
  }
56
28
  return pair;
57
29
  }, linksCacheKey);
58
- /**
59
- * Drops every answer this module has cached, so the next read goes to the chain.
60
- *
61
- * Use it after a token's first transfer, in a long-running process that wants
62
- * a fresh view, or between tests.
63
- */
64
30
  export const clearChainInfoCaches = () => {
65
31
  links.cache.clear();
66
32
  };
67
- /**
68
- * Returns the token bridge info for the given bridge key, asset in, is prod, from chain client, and to chain client
69
- * @param bridgeKey - the bridge key
70
- * @param assetIn - the asset in
71
- * @param isProd - whether to use the production pathway
72
- * @param fromChainClient - the from chain client
73
- * @param toChainClient - the to chain client
74
- * @returns the token bridge info
75
- */
76
33
  export const tokenBridgeInfo = async ({ bridgeKey, assetIn, isProd, fromChainClient, toChainClient, }) => {
77
34
  const bridgePathway = pathway(bridgeKey, isProd, assetIn?.address);
78
35
  if (!assetIn || !bridgePathway) {
@@ -140,7 +97,6 @@ export const tokenBridgeInfo = async ({ bridgeKey, assetIn, isProd, fromChainCli
140
97
  },
141
98
  };
142
99
  }
143
- // the token has not been bridged yet
144
100
  return {
145
101
  originationChainId: toChain,
146
102
  assetInAddress: assetInAddress,
@@ -160,23 +116,11 @@ export const tokenBridgeInfo = async ({ bridgeKey, assetIn, isProd, fromChainCli
160
116
  }),
161
117
  };
162
118
  };
163
- /**
164
- * Check the prices that each router offers for the given paths
165
- * @param assetInAddress the address of the asset going into the bridge
166
- * @param oneTokenInt the number of tokens to push into the bridge (before fees)
167
- * @param chain the chain of the asset going into the bridge
168
- * @param bridgeKey the bridge key
169
- * @param blockNumber the block number to use for the price
170
- * @param paths the paths to check
171
- * @returns the prices as bigint for each path, hex whenever the price is not available
172
- */
173
119
  const readAmountOut = ({ amountIn, chain, paths, client, uniV2Router, }) => {
174
120
  return multicallRead({
175
121
  chain: chainsMetadata[chain],
176
122
  client,
177
123
  abi: abis.univ2Router,
178
- // pulsex router
179
- // a chain with no router reads nothing, as lodash's flatMap over undefined did
180
124
  calls: (uniV2Router ? [uniV2Router] : (uniV2Routers[chain] ?? [])).flatMap((target) => paths.map((path) => ({
181
125
  functionName: 'getAmountsOut',
182
126
  allowFailure: true,
@@ -185,22 +129,9 @@ const readAmountOut = ({ amountIn, chain, paths, client, uniV2Router, }) => {
185
129
  }))),
186
130
  });
187
131
  };
188
- /**
189
- * Fetch the price corrective for the given bridge key, asset out, measurement token, from chain client, to chain client, asset link, amount in, and is prod
190
- * @param bridgeKeyPartner - the bridge key partner
191
- * @param assetOut - the asset out
192
- * @param measurementToken - the measurement token
193
- * @param fromChainClient - the from chain client
194
- * @param toChainClient - the to chain client
195
- * @param assetLink - the asset link
196
- * @param amountIn - the amount in
197
- * @param isProd - whether to use the production pathway
198
- * @returns the price corrective
199
- */
200
132
  export const fetchPriceCorrective = ({ bridgeKeyPartner, assetOut, measurementToken, fromChainClient, toChainClient, assetLink, amountIn, isProd, }) => {
201
133
  return {
202
134
  getPaymentToken: async () => {
203
- // fetch the token bridge info for the token that is about to be spent by the delivery service
204
135
  return await tokenBridgeInfo({
205
136
  bridgeKey: bridgeKeyPartner,
206
137
  assetIn: {
@@ -208,8 +139,6 @@ export const fetchPriceCorrective = ({ bridgeKeyPartner, assetOut, measurementTo
208
139
  address: measurementToken,
209
140
  },
210
141
  isProd,
211
- // clients are reversed here because we are actually fetching the
212
- // tokens going the opposite direction to the provided bridge key
213
142
  fromChainClient: toChainClient,
214
143
  toChainClient: fromChainClient,
215
144
  });
@@ -222,9 +151,7 @@ export const fetchPriceCorrective = ({ bridgeKeyPartner, assetOut, measurementTo
222
151
  uniV2Router,
223
152
  client,
224
153
  paths: [
225
- // check the direct route
226
154
  [assetLink.assetInAddress, paymentTokenResult.assetOutAddress],
227
- // might have heavier liquidity going through the native asset on the home side
228
155
  [assetLink.assetInAddress, nativeAssetOut[chain], paymentTokenResult.assetOutAddress],
229
156
  ],
230
157
  }),
@@ -234,22 +161,17 @@ export const fetchPriceCorrective = ({ bridgeKeyPartner, assetOut, measurementTo
234
161
  uniV2Router,
235
162
  client,
236
163
  paths: [[assetOut.address, measurementToken]],
237
- // only the direct route is available.
238
- // might be able to create a whitelist for this at some point
239
164
  }),
240
165
  ]);
241
166
  },
242
167
  reduceResults: ({ results, oneToken, }) => {
243
168
  const outputFromRouter = (result) => {
244
169
  if (typeof result === 'string') {
245
- // the router failed to return a result
246
170
  return 0n;
247
171
  }
248
172
  if (!result.length) {
249
- // the router returned an empty result
250
173
  return 0n;
251
174
  }
252
- // the last element is the amount of the output token
253
175
  const last = result[result.length - 1];
254
176
  return (last * oneToken) / amountIn;
255
177
  };
@@ -258,7 +180,6 @@ export const fetchPriceCorrective = ({ bridgeKeyPartner, assetOut, measurementTo
258
180
  .filter((amount) => amount !== undefined)
259
181
  .reduce((max, current) => (max < current ? current : max), 0n);
260
182
  };
261
- // could do with a refactor to unify the results
262
183
  const [outputs, inputs] = results;
263
184
  const outputAmounts = outputs.map(outputFromRouter);
264
185
  const inputAmounts = inputs.map(outputFromRouter);
@@ -273,36 +194,12 @@ export const fetchPriceCorrective = ({ bridgeKeyPartner, assetOut, measurementTo
273
194
  },
274
195
  };
275
196
  };
276
- /**
277
- * Read the smallest amount the bridge will accept for this asset on this pathway.
278
- *
279
- * THE ENTRY MEDIATOR DECIDES, so this always reads `pathway.from` on the chain
280
- * the funds leave. `feeManager` says which side prices the transfer; it has
281
- * never said which side validates the amount, and using it for both is what
282
- * produced the defect this replaces.
283
- *
284
- * Both mediators keep a `minPerTx` under the same name, and for a token that
285
- * originates on the entry chain the two sides usually hold the same number. That
286
- * agreement is a coincidence of configuration - each side is separately
287
- * governed, and both happen to apply one blanket default. It breaks outright for
288
- * a token that originates on the far side, because the two mediators key their
289
- * limits by different addresses. Wrapped Pulse entering from Ethereum is the
290
- * live case: the entry mediator enforces 50,000, and the destination mediator
291
- * answers 0 for that same address because it files that token under its
292
- * PulseChain address instead. Reading the destination got both the chain and the
293
- * token key wrong, and reported no floor where a real one stood.
294
- * @param assetIn - the asset the sender holds, on the chain it leaves from
295
- * @param pathway - the pathway, with any per-asset overrides already applied
296
- * @param fromPublicClient - a client for the chain the funds leave
297
- * @returns the smallest amount the entry mediator will accept
298
- */
299
197
  export const minBridgeAmountIn = async ({ assetIn, pathway, fromPublicClient, }) => fromPublicClient.readContract({
300
198
  abi: abis.inputBridge,
301
199
  functionName: 'minPerTx',
302
200
  args: [assetIn.address],
303
201
  address: pathway.from,
304
202
  });
305
- /** get the symbol of the native asset, unwrap it if it needs to be */
306
203
  export const nativeSymbol = (asset, unwrap = false) => {
307
204
  return asset
308
205
  ? unwrap && asset.address === nativeAssetOut[toChain(asset.chainId)]
@@ -310,12 +207,6 @@ export const nativeSymbol = (asset, unwrap = false) => {
310
207
  : asset.symbol
311
208
  : '';
312
209
  };
313
- /**
314
- * Returns the Multicall3 contract for the client's chain.
315
- * @param client - a client whose `chain` is one of {@link chainsMetadata}'s chains
316
- * @returns the Multicall3 contract instance
317
- * @throws when the client carries no chain, or the chain has no Multicall3 address
318
- */
319
210
  export const chainMulticall = (client) => {
320
211
  const chainId = client.chain?.id;
321
212
  if (chainId === undefined) {
@@ -327,13 +218,6 @@ export const chainMulticall = (client) => {
327
218
  }
328
219
  return getContract({ abi: multicall3Abi, client, address });
329
220
  };
330
- /**
331
- * Load the bridge fees for the given pathway, from chain client, and to chain client
332
- * @param pathway - the pathway
333
- * @param fromChainClient - the from chain client
334
- * @param toChainClient - the to chain client
335
- * @returns the bridge fees
336
- */
337
221
  export const loadBridgeFees = async ({ pathway, fromChainClient, toChainClient, }) => {
338
222
  const multicall = pathway.feeManager === 'from' ? chainMulticall(fromChainClient) : chainMulticall(toChainClient);
339
223
  const [feeManagerResponse] = await multicall.read.aggregate3([
@@ -1,117 +1,22 @@
1
- /**
2
- * Chain identifiers and their human-readable display names, in one place.
3
- *
4
- * This module exists to break an import cycle. `relay-quote.ts` imports the
5
- * step normalizers from `route-steps.ts`, and `route-steps.ts` needs to name
6
- * Relay's non-Ethereum chains when it labels a leg. Holding the shared lookup
7
- * here lets both import it without either importing the other.
8
- *
9
- * Names are spelled out in full — these strings are shown to someone choosing
10
- * where their funds leave from, so "The Open Network", never "TON".
11
- */
12
- /**
13
- * Relay's numeric chain identifiers for the non-Ethereum-Virtual-Machine origin
14
- * chains this bridge supports. These are Relay's OWN identifiers, distinct from
15
- * any native chain id, and are required verbatim as the request's
16
- * `originChainId`.
17
- *
18
- * Source: https://api.relay.link/chains, where each entry's `vmType` names the
19
- * ecosystem and each is reported `depositEnabled`.
20
- */
21
1
  export const relayChainIds = {
22
- /** Relay's chain id for Solana mainnet (virtual-machine type `svm`). */
23
2
  solana: 792703809,
24
- /**
25
- * Relay's chain id for Eclipse (virtual-machine type `svm`) — a SECOND chain
26
- * in the Solana ecosystem, sharing Solana's address encoding, deposit shape
27
- * and native-asset sentinel while being a different network with a different
28
- * native asset (Ether, not Sol).
29
- *
30
- * Quotable, but see the guard in the interface's Solana signer: sharing an
31
- * ecosystem means sharing a wallet adapter, and that adapter is bound to ONE
32
- * Solana network at a time. A deposit for this chain must never be signed
33
- * against a connection pointed at Solana.
34
- */
35
3
  eclipse: 9286185,
36
- /** Relay's chain id for Bitcoin mainnet (virtual-machine type `bvm`). */
37
4
  bitcoin: 8253038,
38
- /** Relay's chain id for Tron mainnet (virtual-machine type `tvm`). */
39
5
  tron: 728126428,
40
- /** Relay's chain id for The Open Network (virtual-machine type `tonvm`). */
41
6
  ton: 224235520,
42
- /**
43
- * Relay's chain id for Hyperliquid (virtual-machine type `hypevm`).
44
- *
45
- * BEWARE: 1337 is also the default chain id of a local Ganache development
46
- * node, so this is the one Relay identifier that can collide with a real
47
- * Ethereum Virtual Machine chain a developer might be running. Treating a
48
- * local test chain as Hyperliquid would route it down the HyperCore deposit
49
- * path, so never feed a local development chain id through
50
- * `ecosystemByChainId`.
51
- */
52
7
  hyperliquid: 1337,
53
8
  };
54
- /**
55
- * Chain identifiers for origin chains a reader PAYS BY HAND.
56
- *
57
- * WHAT MAKES THESE DIFFERENT FROM EVERY OTHER CHAIN HERE. Every identifier
58
- * above names a chain this interface can connect a wallet to and sign on.
59
- * These name chains it cannot. There is no connector, no signer and no
60
- * transaction: the provider issues an address, the reader sends an ordinary
61
- * transfer to it from any wallet or any exchange, and the provider's own
62
- * watcher reports the arrival. The chain identifier exists so the route layer
63
- * can NAME the chain, price it and draw it — nothing more.
64
- *
65
- * THE NUMBERS ARE DERIVED, NOT INVENTED, and the derivation is written down
66
- * because a chain identifier typed from memory is a hypothesis every later
67
- * reader will trust. Each is the chain's registered SLIP-0044 coin type with
68
- * the hardened bit set, exactly as a BIP-44 derivation path writes it:
69
- * `0x80000000 + coinType`. That puts them above every chain identifier in
70
- * public use, so one can never collide with a real Ethereum chain and be
71
- * mistaken for one — which is the failure that matters, because an Ethereum
72
- * chain has a wallet and would be handed a payload to sign.
73
- *
74
- * They are LOCAL identifiers and never travel on a wire. NEAR Intents names
75
- * Zcash `zec`; `chainIdByNearIntentsChain` is where the two are reconciled.
76
- */
77
9
  export const depositAddressChainIds = {
78
- /** Zcash mainnet. SLIP-0044 coin type 133, hardened: 0x80000000 + 133. */
79
10
  zcash: 2_147_483_781,
80
11
  };
81
- /**
82
- * Display names for the chains a reader pays by hand, one entry per member of
83
- * {@link DepositAddressChain}. Typed on the union rather than on `number` so a
84
- * chain added to {@link depositAddressChainIds} without a name here is a
85
- * compile error, not a blank badge.
86
- */
87
12
  const depositAddressChainNamesByChain = {
88
13
  zcash: 'Zcash',
89
14
  };
90
- /** {@link depositAddressChainNamesByChain}, keyed by chain id for lookup. */
91
15
  const depositAddressChainNames = new Map(Object.keys(depositAddressChainIds).map((chain) => [
92
16
  depositAddressChainIds[chain],
93
17
  depositAddressChainNamesByChain[chain],
94
18
  ]));
95
- /**
96
- * Whether a chain identifier names a chain this interface CANNOT SIGN ON.
97
- *
98
- * The one predicate every surface asks before offering a wallet. A chain that
99
- * answers true has no connector, so anything that would connect, switch
100
- * networks, estimate gas or compose a transaction for it is wrong — the reader
101
- * is shown an address to pay instead.
102
- *
103
- * @param chainId - a chain identifier
104
- * @returns whether the reader pays this chain by hand
105
- */
106
19
  export const isDepositAddressChain = (chainId) => depositAddressChainNames.has(chainId);
107
- /**
108
- * Display names for Relay's non-Ethereum origin chains.
109
- *
110
- * An ecosystem label is NOT a chain name, and using one as a name is actively
111
- * wrong: `svm` holds both Solana and Eclipse, so labelling by ecosystem renders
112
- * Eclipse as "Solana" — a different network, shown to someone choosing where
113
- * their funds leave from. Keyed by chain id for exactly that reason.
114
- */
115
20
  export const relayChainNames = new Map([
116
21
  [relayChainIds.solana, 'Solana'],
117
22
  [relayChainIds.eclipse, 'Eclipse'],
@@ -120,11 +25,6 @@ export const relayChainNames = new Map([
120
25
  [relayChainIds.ton, 'The Open Network'],
121
26
  [relayChainIds.hyperliquid, 'Hyperliquid'],
122
27
  ]);
123
- /**
124
- * Display names for the Ethereum-Virtual-Machine chains a route can traverse.
125
- * Only the chains this bridge actually routes through need an entry; anything
126
- * else falls back to its numeric identifier rather than being dropped.
127
- */
128
28
  const virtualMachineChainNames = new Map([
129
29
  [1, 'Ethereum'],
130
30
  [56, 'Binance Smart Chain'],
@@ -133,28 +33,7 @@ const virtualMachineChainNames = new Map([
133
33
  [42161, 'Arbitrum One'],
134
34
  [11155111, 'Sepolia'],
135
35
  ]);
136
- /**
137
- * Names registered at startup from the wider chain registry.
138
- *
139
- * This package cannot import that registry — it sits below the client that
140
- * holds it — but it must still be the ONE place a chain name is decided. The
141
- * alternative was what this replaced: three resolvers, each with different
142
- * coverage, so the same chain read as "Base" beside one element, "chain 8453"
143
- * beside another, and vanished entirely from a third. A reader hovering two
144
- * parts of the same row saw two different answers.
145
- */
146
36
  const registeredChainNames = new Map();
147
- /**
148
- * Registers display names for chains this module does not know about.
149
- *
150
- * Call once during startup, before anything renders. Entries are merged, and a
151
- * name declared in `virtualMachineChainNames` above WINS over a registered one:
152
- * the local table is deliberate ("Binance Smart Chain", not the registry's
153
- * "BNB Smart Chain"), and a registry that happens to disagree must not quietly
154
- * rename a chain the product has already named.
155
- *
156
- * @param entries - chain id and display name pairs
157
- */
158
37
  export const registerChainNames = (entries) => {
159
38
  for (const [chainId, name] of entries) {
160
39
  if (!name)
@@ -162,37 +41,7 @@ export const registerChainNames = (entries) => {
162
41
  registeredChainNames.set(chainId, name);
163
42
  }
164
43
  };
165
- /**
166
- * Returns a human-readable chain name for the given chain id, covering both
167
- * Ethereum-Virtual-Machine chains and Relay's non-Ethereum pseudo identifiers.
168
- *
169
- * Falls back to the numeric id stringified when the chain is not known — better
170
- * to show "chain 999" than to silently drop the leg that traverses it.
171
- *
172
- * @param chainId - a decimal chain id, Relay's identifier included
173
- * @returns the display name, or `chain <id>` when unknown
174
- */
175
44
  export const chainDisplayName = (chainId) => knownChainName(chainId) ?? `chain ${chainId}`;
176
- /**
177
- * The name this module KNOWS for a chain, or null when it knows none.
178
- *
179
- * Same lookup as {@link chainDisplayName} without the placeholder, so a caller
180
- * with a better fallback of its own can reach one. {@link chainDisplayName} is
181
- * defined in terms of this, which is the point: the two can never disagree
182
- * about which chains are known.
183
- *
184
- * WHY A CALLER WOULD WANT THIS. The network chips in the token picker have a
185
- * second name to fall back on — the aggregator's own chain list, which reaches
186
- * chains this registry has never been told about and says "Unknown network"
187
- * rather than printing a bare number. Choosing between the two used to be done
188
- * by comparing `chainDisplayName`'s answer against the literal string
189
- * `chain <id>`, which is a caller reaching into another function's fallback
190
- * format: rename the placeholder here and that comparison quietly stops
191
- * matching, leaving every unknown chain labelled with its number.
192
- *
193
- * @param chainId - a decimal chain id, Relay's identifiers included
194
- * @returns the display name, or null when the chain is not known here
195
- */
196
45
  export const knownChainName = (chainId) => virtualMachineChainNames.get(chainId) ??
197
46
  relayChainNames.get(chainId) ??
198
47
  depositAddressChainNames.get(chainId) ??