@gibs/bridge-sdk 1.10.1 → 1.13.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 (122) hide show
  1. package/LICENSE +15 -0
  2. package/README.md +234 -432
  3. package/dist/abis.d.ts +1 -0
  4. package/dist/abis.js +3 -0
  5. package/dist/bridge-limits.d.ts +103 -0
  6. package/dist/bridge-limits.js +84 -0
  7. package/dist/{src/chain-info.d.ts → chain-info.d.ts} +66 -27
  8. package/dist/{src/chain-info.js → chain-info.js} +106 -46
  9. package/dist/chain-names.d.ts +160 -0
  10. package/dist/chain-names.js +200 -0
  11. package/dist/chains.d.ts +65 -0
  12. package/dist/chains.js +284 -0
  13. package/dist/config.d.ts +216 -0
  14. package/dist/{src/config.js → config.js} +151 -44
  15. package/dist/consolidated-quote.d.ts +554 -0
  16. package/dist/consolidated-quote.js +773 -0
  17. package/dist/destination-calldata.d.ts +118 -0
  18. package/dist/destination-calldata.js +152 -0
  19. package/dist/ecosystems.d.ts +217 -0
  20. package/dist/ecosystems.js +288 -0
  21. package/dist/hyperliquid-execution.d.ts +152 -0
  22. package/dist/hyperliquid-execution.js +168 -0
  23. package/dist/image-links.d.ts +117 -0
  24. package/dist/image-links.js +142 -0
  25. package/dist/index.d.ts +20 -0
  26. package/dist/index.js +20 -0
  27. package/dist/lifi-execution-guard.d.ts +199 -0
  28. package/dist/lifi-execution-guard.js +400 -0
  29. package/dist/near-intents-conformance.d.ts +85 -0
  30. package/dist/near-intents-conformance.js +329 -0
  31. package/dist/near-intents-route.d.ts +47 -0
  32. package/dist/near-intents-route.js +265 -0
  33. package/dist/near-intents.d.ts +524 -0
  34. package/dist/near-intents.js +1055 -0
  35. package/dist/origin-deposit.d.ts +326 -0
  36. package/dist/origin-deposit.js +68 -0
  37. package/dist/pre-quote.d.ts +198 -0
  38. package/dist/pre-quote.js +175 -0
  39. package/dist/prices.d.ts +107 -0
  40. package/dist/prices.js +162 -0
  41. package/dist/providers.d.ts +221 -0
  42. package/dist/providers.js +157 -0
  43. package/dist/quote-fees.d.ts +102 -0
  44. package/dist/quote-fees.js +195 -0
  45. package/dist/referral.d.ts +77 -0
  46. package/dist/referral.js +72 -0
  47. package/dist/relay-currencies.d.ts +47 -0
  48. package/dist/relay-currencies.js +89 -0
  49. package/dist/relay-quote.d.ts +301 -0
  50. package/dist/relay-quote.js +983 -0
  51. package/dist/route-steps.d.ts +138 -0
  52. package/dist/route-steps.js +305 -0
  53. package/dist/routing/amounts.d.ts +80 -0
  54. package/dist/routing/amounts.js +120 -0
  55. package/dist/routing/candidate-route.d.ts +43 -0
  56. package/dist/routing/candidate-route.js +45 -0
  57. package/dist/routing/candidate.d.ts +237 -0
  58. package/dist/routing/candidate.js +96 -0
  59. package/dist/routing/carriers/ask-answer.d.ts +58 -0
  60. package/dist/routing/carriers/omnibridge.d.ts +137 -0
  61. package/dist/routing/carriers/omnibridge.js +419 -0
  62. package/dist/routing/carriers/pulsex.d.ts +111 -0
  63. package/dist/routing/carriers/pulsex.js +404 -0
  64. package/dist/routing/carriers/wrap.d.ts +25 -0
  65. package/dist/routing/carriers/wrap.js +115 -0
  66. package/dist/routing/composed-route-quality.d.ts +103 -0
  67. package/dist/routing/composed-route-quality.js +108 -0
  68. package/dist/routing/entry-chain-anchor.d.ts +88 -0
  69. package/dist/routing/entry-chain-anchor.js +55 -0
  70. package/dist/routing/format.d.ts +31 -0
  71. package/dist/routing/format.js +58 -0
  72. package/dist/routing/index.d.ts +34 -0
  73. package/dist/routing/index.js +42 -0
  74. package/dist/routing/producers.d.ts +770 -0
  75. package/dist/routing/producers.js +1564 -0
  76. package/dist/routing/providers.d.ts +26 -0
  77. package/dist/routing/providers.js +38 -0
  78. package/dist/routing/route-data.d.ts +355 -0
  79. package/dist/routing/route-data.js +1 -0
  80. package/dist/routing/search/compose.d.ts +168 -0
  81. package/dist/routing/search/compose.js +98 -0
  82. package/dist/routing/search/graph.d.ts +639 -0
  83. package/dist/routing/search/graph.js +445 -0
  84. package/dist/routing/search/plan-route-data.d.ts +244 -0
  85. package/dist/routing/search/plan-route-data.js +767 -0
  86. package/dist/routing/search/score.d.ts +324 -0
  87. package/dist/routing/search/score.js +400 -0
  88. package/dist/routing/usd-value.d.ts +17 -0
  89. package/dist/routing/usd-value.js +25 -0
  90. package/dist/settings.d.ts +692 -0
  91. package/dist/{src/settings.js → settings.js} +338 -71
  92. package/dist/ton-execution.d.ts +117 -0
  93. package/dist/ton-execution.js +247 -0
  94. package/dist/tron-execution.d.ts +146 -0
  95. package/dist/tron-execution.js +239 -0
  96. package/dist/{src/types.d.ts → types.d.ts} +8 -1
  97. package/dist/types.js +1 -0
  98. package/package.json +210 -23
  99. package/dist/src/abis.d.ts +0 -384
  100. package/dist/src/abis.js +0 -68
  101. package/dist/src/chains.d.ts +0 -6
  102. package/dist/src/chains.js +0 -86
  103. package/dist/src/config.d.ts +0 -136
  104. package/dist/src/image-links.d.ts +0 -41
  105. package/dist/src/image-links.js +0 -45
  106. package/dist/src/index.d.ts +0 -8
  107. package/dist/src/index.js +0 -8
  108. package/dist/src/settings.d.ts +0 -357
  109. package/dist/tsconfig.tsbuildinfo +0 -1
  110. package/src/abis.ts +0 -70
  111. package/src/chain-info.ts +0 -464
  112. package/src/chains.ts +0 -88
  113. package/src/config.ts +0 -480
  114. package/src/fee-type.ts +0 -14
  115. package/src/image-links.ts +0 -61
  116. package/src/index.ts +0 -8
  117. package/src/settings.ts +0 -898
  118. package/src/types.ts +0 -48
  119. package/tsconfig.json +0 -16
  120. /package/dist/{src/fee-type.d.ts → fee-type.d.ts} +0 -0
  121. /package/dist/{src/fee-type.js → fee-type.js} +0 -0
  122. /package/dist/{src/types.js → routing/carriers/ask-answer.js} +0 -0
@@ -1,5 +1,5 @@
1
- import { getAddress, keccak256, stringToHex, zeroAddress } from "viem";
2
- import _ from 'lodash';
1
+ import * as _ from 'lodash-es';
2
+ import { getAddress, isAddress, isAddressEqual, keccak256, stringToHex, zeroAddress, } from 'viem';
3
3
  /**
4
4
  * Add here your chain id as hex, be sure to add your chain in the chainsMetadata object too
5
5
  */
@@ -62,6 +62,40 @@ export const uniV2Routers = {
62
62
  '0x636f6407B90661b73b1C0F7e24F4C79f624d0738',
63
63
  ],
64
64
  };
65
+ /**
66
+ * Each {@link uniV2Routers} entry's OWN factory address, same index, same
67
+ * chain — `router.factory()` read live from `one.valve.city` on 2026-09-24.
68
+ * Only PulseChain mainnet is filled: PulseX carries funds nowhere else
69
+ * (`routing/carriers/pulsex.ts`'s own `pulseXCarries`), so no other chain's
70
+ * factory has ever been needed or verified.
71
+ *
72
+ * MEASURED, NOT ASSUMED (owner Rule 13). Reading each factory's `getPair`
73
+ * and the resulting pool's `getReserves`, then recomputing `getAmountsOut`
74
+ * from the standard constant-product formula, showed the SAME fee ratio for
75
+ * both — `9971/10000` (0.29%) — to the base unit, on both a one-hop and a
76
+ * two-hop path. "V1 and V2 differ" was the assumption going in; measurement
77
+ * said otherwise, so `routing/carriers/pulsex.ts`'s `exact` uses one shared
78
+ * fee constant rather than two.
79
+ *
80
+ * `0x1715a3E4A142d8b698131108995174F37aEBA10D` (the V1 factory, index 0) is
81
+ * NOT a copy-paste of the omnibridge's Ethereum mediator address from
82
+ * `pathways` above — it is the same string on a DIFFERENT chain (PulseChain,
83
+ * not Ethereum), confirmed by reading it fresh from `one.valve.city/…/evm/369`.
84
+ * Two unrelated contracts landing on the same address on two different
85
+ * chains is possible (a shared deployer at a matching nonce, or a CREATE2
86
+ * salt collision) and worth this note so a future reader does not assume a
87
+ * transcription error and "fix" it back to something wrong.
88
+ */
89
+ export const uniV2Factories = {
90
+ [Chains.PLS]: [
91
+ '0x1715a3E4A142d8b698131108995174F37aEBA10D',
92
+ '0x29eA7545DEf87022BAdc76323F373EA1e707C523',
93
+ ],
94
+ [Chains.ETH]: [],
95
+ [Chains.BNB]: [],
96
+ [Chains.SEP]: [],
97
+ [Chains.V4PLS]: [],
98
+ };
65
99
  /** A map of chains to native token symbols */
66
100
  export const nativeTokenSymbol = {
67
101
  [Chains.PLS]: 'PLS',
@@ -235,26 +269,48 @@ export const validBridgeKeys = (isProd) => [
235
269
  ...mainnetBridgeKeys,
236
270
  ...(isProd ? [] : testnetBridgeKeys),
237
271
  ];
272
+ /** Every chain that appears only on a testnet pathway. */
273
+ const testnetChains = new Set(testnetBridgeKeys.flatMap(([, fromChain, toChain]) => [fromChain, toChain]));
274
+ /**
275
+ * Whether a chain belongs to the testnet pathway map rather than the mainnet one.
276
+ * @param chain - the chain to classify
277
+ * @returns true for Sepolia and PulseChain testnet V4
278
+ */
279
+ export const isTestnetChain = (chain) => testnetChains.has(chain);
238
280
  /**
239
- * Infers the bridge key from the current key, provider, from chain, and to chain
240
- * @param currentKey - the current bridge key
241
- * @param provider - the provider
242
- * @param fromChain - the from chain
243
- * @param toChain - the to chain
244
- * @returns the inferred bridge key
281
+ * Infers the bridge key from the current key, provider, from chain, and to chain.
282
+ *
283
+ * A chain the provider does not serve falls back to the provider's first chain,
284
+ * so a provider switch lands on a real pathway. That fallback never crosses
285
+ * between the testnet and mainnet maps: when testnets are off and a requested
286
+ * chain is a testnet chain, this returns null rather than a mainnet key for a
287
+ * testnet pair.
288
+ *
289
+ * @param options.currentKey - the current bridge key
290
+ * @param options.provider - the provider
291
+ * @param options.fromChain - the from chain (defaults to the current key's)
292
+ * @param options.toChain - the to chain (defaults to the current key's)
293
+ * @param options.isProd - true leaves testnet pathways out (default false: both maps)
294
+ * @returns the inferred bridge key, or null when no pathway can honour the request
245
295
  */
246
- export const inferBridgeKey = ({ currentKey, provider, fromChain, toChain, }) => {
296
+ export const inferBridgeKey = ({ currentKey, provider, fromChain, toChain, isProd = false, }) => {
247
297
  const [, fromChainKey, toChainKey] = currentKey;
248
298
  const from = fromChain ?? fromChainKey;
249
299
  const to = toChain ?? toChainKey;
250
- const currentFromChainIsValid = !!_.get(pathways, [provider, from]);
251
- const nextFromChain = currentFromChainIsValid
252
- ? from
253
- : Object.keys(pathways[provider])[0];
254
- const currentToChainIsValid = !!_.get(pathways, [provider, nextFromChain, to]);
255
- const nextToChain = currentToChainIsValid
256
- ? to
257
- : Object.keys(pathways[provider][nextFromChain])[0];
300
+ if (isProd && (isTestnetChain(from) || isTestnetChain(to))) {
301
+ return null;
302
+ }
303
+ const network = isTestnetChain(from) ? testnetPathways : pathways;
304
+ const providerGroups = network[provider] ?? {};
305
+ const nextFromChain = providerGroups[from] ? from : Object.keys(providerGroups)[0];
306
+ if (!nextFromChain) {
307
+ return null;
308
+ }
309
+ const destinations = providerGroups[nextFromChain] ?? {};
310
+ const nextToChain = destinations[to] ? to : Object.keys(destinations)[0];
311
+ if (!nextToChain) {
312
+ return null;
313
+ }
258
314
  return [provider, nextFromChain, nextToChain];
259
315
  };
260
316
  /**
@@ -264,6 +320,23 @@ export const inferBridgeKey = ({ currentKey, provider, fromChain, toChain, }) =>
264
320
  * @param assetInAddress - the asset in address
265
321
  * @returns the pathway
266
322
  */
323
+ /**
324
+ * The pathway group for one provider on one chain, honouring the testnet map.
325
+ *
326
+ * Exists because {@link pathway} already knew that testnet pathways live in a
327
+ * SECOND map and are only in play off production, while other callers reached
328
+ * straight into `pathways` and therefore could not see a testnet route at all.
329
+ * That is the sort of knowledge that has to live in one place: duplicated, one
330
+ * copy silently lags the other, and the symptom is a thrown "no pathway found"
331
+ * on a route the rest of the application considers perfectly valid.
332
+ *
333
+ * @param provider - the bridge provider
334
+ * @param chain - the chain being bridged FROM
335
+ * @param isProd - whether this is a production build; testnets are off when true
336
+ * @returns the group keyed by destination chain, or undefined when unknown
337
+ */
338
+ export const pathwayGroup = (provider, chain, isProd) => _.get(pathways, [provider, chain]) ||
339
+ (!isProd ? _.get(testnetPathways, [provider, chain]) : undefined);
267
340
  export const pathway = (bridgeKey, isProd, assetInAddress) => {
268
341
  if (!bridgeKey)
269
342
  return;
@@ -293,45 +366,63 @@ export const defaultAssetIn = ($bridgeKey, isProd) => {
293
366
  return defaultAssetIn;
294
367
  };
295
368
  /**
296
- * Returns whether the given asset is the native asset for the given bridge key
369
+ * Returns whether the given asset is the native asset for the given bridge key.
370
+ *
371
+ * Never throws. A token whose address is not known yet (a {@link TokenOut} for a
372
+ * not-yet-bridged token), an address that is not a valid address, and a bridge
373
+ * key with no pathway each answer false.
374
+ *
297
375
  * @param asset - the asset
298
376
  * @param bridgeKey - the bridge key
377
+ * @param options - which pathway maps to read; see {@link PathwayLookupOptions}
299
378
  * @returns whether the given asset is the native asset for the given bridge key
300
379
  */
301
- export const isNative = (asset, bridgeKey) => {
302
- if (!bridgeKey || !asset) {
380
+ export const isNative = (asset, bridgeKey, options = {}) => {
381
+ if (!bridgeKey || !asset?.address || !isAddress(asset.address, { strict: false })) {
382
+ return false;
383
+ }
384
+ const path = pathway(bridgeKey, options.isProd ?? false);
385
+ if (!path) {
303
386
  return false;
304
387
  }
305
- const path = pathway(bridgeKey, false);
306
- return (getAddress(asset.address) === getAddress(path.bridgedNativeAssetOut) ||
307
- (asset.address === zeroAddress ||
308
- nativeAssetOut[toChain(asset.chainId)]?.toLowerCase() === asset.address?.toLowerCase()) &&
309
- !asset.name.includes(' from Pulsechain'));
388
+ if (isAddressEqual(asset.address, path.bridgedNativeAssetOut)) {
389
+ return true;
390
+ }
391
+ const wrappedNative = nativeAssetOut[toChain(asset.chainId)];
392
+ const isGasTokenOrItsWrapper = isAddressEqual(asset.address, zeroAddress) ||
393
+ (!!wrappedNative && isAddressEqual(asset.address, wrappedNative));
394
+ return isGasTokenOrItsWrapper && !asset.name.includes(' from Pulsechain');
310
395
  };
311
396
  /**
312
- * Returns whether the given asset is unwrappable for the given bridge key
397
+ * Returns whether the given asset is unwrappable for the given bridge key.
398
+ *
399
+ * Never throws: a missing or malformed address and a bridge key with no
400
+ * pathway each answer false.
401
+ *
313
402
  * @param bridgeKey - the bridge key
314
403
  * @param assetIn - the asset in
404
+ * @param options - which pathway maps to read; see {@link PathwayLookupOptions}
315
405
  * @returns whether the given asset is unwrappable for the given bridge key
316
406
  */
317
- export const isUnwrappable = (bridgeKey, assetIn) => {
318
- if (!bridgeKey || !assetIn) {
407
+ export const isUnwrappable = (bridgeKey, assetIn, options = {}) => {
408
+ if (!bridgeKey || !assetIn?.address || !isAddress(assetIn.address, { strict: false })) {
319
409
  return false;
320
410
  }
321
- const addr = getAddress(assetIn.address);
322
- const path = pathway(bridgeKey, false);
323
- if (!path)
411
+ const path = pathway(bridgeKey, options.isProd ?? false);
412
+ if (!path) {
324
413
  return false;
325
- return path.bridgedNativeAssetOut === getAddress(addr);
414
+ }
415
+ return isAddressEqual(path.bridgedNativeAssetOut, assetIn.address);
326
416
  };
327
417
  /**
328
418
  * Returns whether the given asset can be unwrapped for the given bridge key
329
419
  * @param bridgeKey - the bridge key
330
420
  * @param assetIn - the asset in
421
+ * @param options - which pathway maps to read; see {@link PathwayLookupOptions}
331
422
  * @returns boolean
332
423
  */
333
- export const canChangeUnwrap = (bridgeKey, assetIn) => {
334
- return !!assetIn && isUnwrappable(bridgeKey, assetIn);
424
+ export const canChangeUnwrap = (bridgeKey, assetIn, options = {}) => {
425
+ return !!assetIn && isUnwrappable(bridgeKey, assetIn, options);
335
426
  };
336
427
  export const chains = {
337
428
  ethereum: 1,
@@ -341,46 +432,62 @@ export const chains = {
341
432
  sepolia: 11155111,
342
433
  };
343
434
  export const chainIds = Object.values(chains);
435
+ /** Start blocks aligned with when bridge validators began operating — canonical reference for all ponder indexers in this monorepo. */
436
+ export const startBlocks = {
437
+ ethereum: 17_264_119,
438
+ bsc: 28_987_313,
439
+ pulsechain: 17_268_300,
440
+ pulsechainV4: 16_564_233,
441
+ sepolia: 3_331_901,
442
+ };
344
443
  // provider -> home -> foreign
345
444
  export const bridgeConfigs = {
346
445
  [Providers.PULSECHAIN]: {
347
446
  [chains.pulsechain]: {
348
- [chains.ethereum]: [{
447
+ [chains.ethereum]: [
448
+ {
349
449
  pair: 'mainnet',
350
450
  key: 'erc20',
351
451
  home: '0x4fD0aaa7506f3d9cB8274bdB946Ec42A1b8751Ef',
352
452
  foreign: '0x1715a3e4a142d8b698131108995174f37aeba10d',
353
- }, {
453
+ },
454
+ {
354
455
  pair: 'mainnet',
355
456
  key: 'native',
356
457
  home: '0x0e18d0d556b652794EF12Bf68B2dC857EF5f3996',
357
458
  foreign: '0xe20E337DB2a00b1C37139c873B92a0AAd3F468bF',
358
- }],
459
+ },
460
+ ],
359
461
  },
360
462
  [chains.pulsechainV4]: {
361
- [chains.sepolia]: [{
463
+ [chains.sepolia]: [
464
+ {
362
465
  pair: 'v4',
363
466
  key: 'erc20',
364
467
  home: '0x6B08a50865aDeCe6e3869D9AfbB316d0a0436B6c',
365
468
  foreign: '0x546e37DAA15cdb82fd1a717E5dEEa4AF08D4349A',
366
- }, {
469
+ },
470
+ {
367
471
  pair: 'v4',
368
472
  key: 'native',
369
473
  home: '0x81c10846F40fA2B173FC47958D0a892529983F50',
370
474
  foreign: '0x5e238ef968467cf443ef5ecb683b76c5a04a0421',
371
- }],
475
+ },
476
+ ],
372
477
  },
373
478
  },
374
479
  [Providers.TOKENSEX]: {
375
480
  [chains.pulsechain]: {
376
- [chains.bsc]: [{
481
+ [chains.bsc]: [
482
+ {
377
483
  pair: 'bsctokensex',
378
484
  key: 'erc20',
379
485
  home: '0xf1DFc63e10fF01b8c3d307529b47AefaD2154C0e',
380
486
  foreign: '0xb4005881e81a6ecd2c1f75d58e8e41f28d59c6b1',
381
- }],
487
+ },
488
+ ],
382
489
  },
383
490
  },
384
491
  };
385
- export const HOME_TO_FOREIGN_FEE = keccak256(stringToHex("homeToForeignFee"));
386
- export const FOREIGN_TO_HOME_FEE = keccak256(stringToHex("foreignToHomeFee"));
492
+ export const HOME_TO_FOREIGN_FEE = keccak256(stringToHex('homeToForeignFee'));
493
+ export const FOREIGN_TO_HOME_FEE = keccak256(stringToHex('foreignToHomeFee'));