@gibs/bridge-sdk 1.13.1 → 1.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (217) hide show
  1. package/README.md +244 -18
  2. package/abis/package.json +6 -0
  3. package/bridge-limits/package.json +6 -0
  4. package/chain-info/package.json +6 -0
  5. package/chain-names/package.json +6 -0
  6. package/chains/package.json +6 -0
  7. package/claims/package.json +6 -0
  8. package/config/package.json +6 -0
  9. package/consolidated-quote/package.json +6 -0
  10. package/destination-calldata/package.json +6 -0
  11. package/dist/chain-info.d.ts +1 -1
  12. package/dist/chain-info.js +11 -12
  13. package/dist/chains.d.ts +25 -0
  14. package/dist/chains.js +55 -20
  15. package/dist/cjs/abis.d.ts +1 -0
  16. package/dist/cjs/abis.js +19 -0
  17. package/dist/cjs/bridge-limits.d.ts +103 -0
  18. package/dist/cjs/bridge-limits.js +89 -0
  19. package/dist/cjs/chain-info.d.ts +169 -0
  20. package/dist/cjs/chain-info.js +452 -0
  21. package/dist/cjs/chain-names.d.ts +160 -0
  22. package/dist/cjs/chain-names.js +207 -0
  23. package/dist/cjs/chains.d.ts +90 -0
  24. package/dist/cjs/chains.js +357 -0
  25. package/dist/cjs/claims.d.ts +198 -0
  26. package/dist/cjs/claims.js +182 -0
  27. package/dist/cjs/config.d.ts +240 -0
  28. package/dist/cjs/config.js +537 -0
  29. package/dist/cjs/consolidated-quote.d.ts +648 -0
  30. package/dist/cjs/consolidated-quote.js +1048 -0
  31. package/dist/cjs/destination-calldata.d.ts +118 -0
  32. package/dist/cjs/destination-calldata.js +156 -0
  33. package/dist/cjs/ecosystems.d.ts +217 -0
  34. package/dist/cjs/ecosystems.js +298 -0
  35. package/dist/cjs/execution.d.ts +346 -0
  36. package/dist/cjs/execution.js +468 -0
  37. package/dist/cjs/fee-type.d.ts +10 -0
  38. package/dist/cjs/fee-type.js +10 -0
  39. package/dist/cjs/hyperliquid-execution.d.ts +152 -0
  40. package/dist/cjs/hyperliquid-execution.js +175 -0
  41. package/dist/cjs/image-links.d.ts +117 -0
  42. package/dist/cjs/image-links.js +153 -0
  43. package/dist/cjs/index.d.ts +23 -0
  44. package/dist/cjs/index.js +39 -0
  45. package/dist/cjs/lifi-execution-guard.d.ts +210 -0
  46. package/dist/cjs/lifi-execution-guard.js +409 -0
  47. package/dist/cjs/near-intents-conformance.d.ts +85 -0
  48. package/dist/cjs/near-intents-conformance.js +337 -0
  49. package/dist/cjs/near-intents-route.d.ts +47 -0
  50. package/dist/cjs/near-intents-route.js +303 -0
  51. package/dist/cjs/near-intents.d.ts +524 -0
  52. package/dist/cjs/near-intents.js +1071 -0
  53. package/dist/cjs/origin-deposit.d.ts +326 -0
  54. package/dist/cjs/origin-deposit.js +82 -0
  55. package/dist/cjs/package.json +3 -0
  56. package/dist/cjs/pre-quote.d.ts +198 -0
  57. package/dist/cjs/pre-quote.js +180 -0
  58. package/dist/cjs/prices.d.ts +107 -0
  59. package/dist/cjs/prices.js +172 -0
  60. package/dist/cjs/providers.d.ts +238 -0
  61. package/dist/cjs/providers.js +171 -0
  62. package/dist/cjs/quote-fees.d.ts +102 -0
  63. package/dist/cjs/quote-fees.js +201 -0
  64. package/dist/cjs/referral.d.ts +85 -0
  65. package/dist/cjs/referral.js +85 -0
  66. package/dist/cjs/relay-currencies.d.ts +47 -0
  67. package/dist/cjs/relay-currencies.js +95 -0
  68. package/dist/cjs/relay-depository.d.ts +2 -0
  69. package/dist/cjs/relay-depository.js +85 -0
  70. package/dist/cjs/relay-quote.d.ts +301 -0
  71. package/dist/cjs/relay-quote.js +996 -0
  72. package/dist/cjs/route-steps.d.ts +138 -0
  73. package/dist/cjs/route-steps.js +310 -0
  74. package/dist/cjs/routing/amounts.d.ts +80 -0
  75. package/dist/cjs/routing/amounts.js +126 -0
  76. package/dist/cjs/routing/candidate-route.d.ts +43 -0
  77. package/dist/cjs/routing/candidate-route.js +50 -0
  78. package/dist/cjs/routing/candidate.d.ts +237 -0
  79. package/dist/cjs/routing/candidate.js +100 -0
  80. package/dist/cjs/routing/carriers/ask-answer.d.ts +77 -0
  81. package/dist/cjs/routing/carriers/ask-answer.js +2 -0
  82. package/dist/cjs/routing/carriers/omnibridge.d.ts +137 -0
  83. package/dist/cjs/routing/carriers/omnibridge.js +459 -0
  84. package/dist/cjs/routing/carriers/pulsex-paths.d.ts +80 -0
  85. package/dist/cjs/routing/carriers/pulsex-paths.js +97 -0
  86. package/dist/cjs/routing/carriers/pulsex-split.d.ts +175 -0
  87. package/dist/cjs/routing/carriers/pulsex-split.js +193 -0
  88. package/dist/cjs/routing/carriers/pulsex.d.ts +159 -0
  89. package/dist/cjs/routing/carriers/pulsex.js +565 -0
  90. package/dist/cjs/routing/carriers/wrap.d.ts +25 -0
  91. package/dist/cjs/routing/carriers/wrap.js +119 -0
  92. package/dist/cjs/routing/composed-route-quality.d.ts +125 -0
  93. package/dist/cjs/routing/composed-route-quality.js +144 -0
  94. package/dist/cjs/routing/entry-chain-anchor.d.ts +88 -0
  95. package/dist/cjs/routing/entry-chain-anchor.js +59 -0
  96. package/dist/cjs/routing/format.d.ts +31 -0
  97. package/dist/cjs/routing/format.js +64 -0
  98. package/dist/cjs/routing/index.d.ts +38 -0
  99. package/dist/cjs/routing/index.js +134 -0
  100. package/dist/cjs/routing/producers.d.ts +770 -0
  101. package/dist/cjs/routing/producers.js +1617 -0
  102. package/dist/cjs/routing/providers.d.ts +31 -0
  103. package/dist/cjs/routing/providers.js +48 -0
  104. package/dist/cjs/routing/route-data.d.ts +355 -0
  105. package/dist/cjs/routing/route-data.js +2 -0
  106. package/dist/cjs/routing/search/compose.d.ts +168 -0
  107. package/dist/cjs/routing/search/compose.js +104 -0
  108. package/dist/cjs/routing/search/graph.d.ts +668 -0
  109. package/dist/cjs/routing/search/graph.js +461 -0
  110. package/dist/cjs/routing/search/plan-route-data.d.ts +269 -0
  111. package/dist/cjs/routing/search/plan-route-data.js +848 -0
  112. package/dist/cjs/routing/search/score.d.ts +356 -0
  113. package/dist/cjs/routing/search/score.js +445 -0
  114. package/dist/cjs/routing/swap-transactions.d.ts +91 -0
  115. package/dist/cjs/routing/swap-transactions.js +131 -0
  116. package/dist/cjs/routing/usd-value.d.ts +17 -0
  117. package/dist/cjs/routing/usd-value.js +29 -0
  118. package/dist/cjs/settings.d.ts +785 -0
  119. package/dist/cjs/settings.js +1074 -0
  120. package/dist/cjs/ton-connect.d.ts +98 -0
  121. package/dist/cjs/ton-connect.js +206 -0
  122. package/dist/cjs/ton-execution.d.ts +7 -0
  123. package/dist/cjs/ton-execution.js +23 -0
  124. package/dist/cjs/ton.d.ts +37 -0
  125. package/dist/cjs/ton.js +83 -0
  126. package/dist/cjs/tron-execution.d.ts +146 -0
  127. package/dist/cjs/tron-execution.js +248 -0
  128. package/dist/cjs/types.d.ts +51 -0
  129. package/dist/cjs/types.js +2 -0
  130. package/dist/claims.d.ts +198 -0
  131. package/dist/claims.js +140 -0
  132. package/dist/config.d.ts +24 -0
  133. package/dist/config.js +39 -5
  134. package/dist/consolidated-quote.d.ts +109 -15
  135. package/dist/consolidated-quote.js +310 -52
  136. package/dist/execution.d.ts +346 -0
  137. package/dist/execution.js +428 -0
  138. package/dist/hyperliquid-execution.js +2 -3
  139. package/dist/index.d.ts +3 -0
  140. package/dist/index.js +3 -0
  141. package/dist/lifi-execution-guard.d.ts +13 -2
  142. package/dist/lifi-execution-guard.js +4 -0
  143. package/dist/near-intents.js +2 -3
  144. package/dist/pre-quote.d.ts +6 -6
  145. package/dist/pre-quote.js +10 -14
  146. package/dist/providers.d.ts +17 -0
  147. package/dist/providers.js +6 -0
  148. package/dist/referral.d.ts +12 -4
  149. package/dist/referral.js +12 -4
  150. package/dist/relay-depository.d.ts +2 -0
  151. package/dist/relay-depository.js +82 -0
  152. package/dist/relay-quote.js +2 -3
  153. package/dist/routing/candidate.d.ts +3 -3
  154. package/dist/routing/candidate.js +3 -3
  155. package/dist/routing/carriers/ask-answer.d.ts +17 -0
  156. package/dist/routing/carriers/omnibridge.js +23 -21
  157. package/dist/routing/carriers/pulsex-paths.d.ts +80 -0
  158. package/dist/routing/carriers/pulsex-paths.js +92 -0
  159. package/dist/routing/carriers/pulsex-split.d.ts +175 -0
  160. package/dist/routing/carriers/pulsex-split.js +185 -0
  161. package/dist/routing/carriers/pulsex.d.ts +31 -21
  162. package/dist/routing/carriers/pulsex.js +141 -71
  163. package/dist/routing/composed-route-quality.d.ts +28 -6
  164. package/dist/routing/composed-route-quality.js +36 -5
  165. package/dist/routing/entry-chain-anchor.d.ts +1 -1
  166. package/dist/routing/entry-chain-anchor.js +1 -1
  167. package/dist/routing/index.d.ts +6 -2
  168. package/dist/routing/index.js +6 -2
  169. package/dist/routing/producers.js +1 -1
  170. package/dist/routing/providers.d.ts +5 -0
  171. package/dist/routing/providers.js +5 -0
  172. package/dist/routing/search/graph.d.ts +15 -0
  173. package/dist/routing/search/plan-route-data.d.ts +25 -0
  174. package/dist/routing/search/plan-route-data.js +43 -7
  175. package/dist/routing/search/score.d.ts +3 -0
  176. package/dist/routing/search/score.js +11 -3
  177. package/dist/routing/swap-transactions.d.ts +91 -0
  178. package/dist/routing/swap-transactions.js +125 -0
  179. package/dist/settings.d.ts +94 -1
  180. package/dist/settings.js +95 -3
  181. package/dist/ton-connect.d.ts +98 -0
  182. package/dist/ton-connect.js +200 -0
  183. package/dist/ton-execution.d.ts +4 -114
  184. package/dist/ton-execution.js +4 -244
  185. package/dist/ton.d.ts +37 -0
  186. package/dist/ton.js +65 -0
  187. package/docs/examples/example-a-ether-to-pulse.ts +300 -0
  188. package/docs/examples/example-b-token-pulsechain-to-ethereum.ts +270 -0
  189. package/docs/examples/shared.ts +261 -0
  190. package/docs/examples/tsconfig.json +18 -0
  191. package/docs/integration-guide.md +617 -0
  192. package/ecosystems/package.json +6 -0
  193. package/execution/package.json +6 -0
  194. package/fee-type/package.json +6 -0
  195. package/hyperliquid-execution/package.json +6 -0
  196. package/image-links/package.json +6 -0
  197. package/lifi-execution-guard/package.json +6 -0
  198. package/llms.txt +75 -10
  199. package/near-intents/package.json +6 -0
  200. package/near-intents-route/package.json +6 -0
  201. package/origin-deposit/package.json +6 -0
  202. package/package.json +817 -10
  203. package/pre-quote/package.json +6 -0
  204. package/prices/package.json +6 -0
  205. package/providers/package.json +6 -0
  206. package/quote-fees/package.json +6 -0
  207. package/referral/package.json +6 -0
  208. package/relay-currencies/package.json +6 -0
  209. package/relay-quote/package.json +6 -0
  210. package/route-steps/package.json +6 -0
  211. package/routing/package.json +6 -0
  212. package/settings/package.json +6 -0
  213. package/ton/package.json +6 -0
  214. package/ton-connect/package.json +6 -0
  215. package/ton-execution/package.json +6 -0
  216. package/tron-execution/package.json +6 -0
  217. package/types/package.json +6 -0
@@ -212,6 +212,98 @@ export declare const deliveryFee: ({ shouldDeliver, routeOffersDelivery, feeType
212
212
  fixedFee: bigint | null;
213
213
  limit: bigint | null;
214
214
  }) => DeliveryFee;
215
+ /**
216
+ * The four-bit fee-type settings word a fee director carries.
217
+ *
218
+ * - bit 0: fixed fee mode.
219
+ * - bit 1: unwrap the delivered token to the native coin.
220
+ * - bit 2: exclude the priority fee from the delivery cost. Always set.
221
+ * - bit 3: percent fee mode.
222
+ *
223
+ * @param options.feeType - the delivery fee mode
224
+ * @param options.unwrap - whether the delivery unwraps to the native coin
225
+ * @returns the settings word for {@link feeDirectorStructEncoded}
226
+ */
227
+ export declare const feeTypeSettings: ({ feeType, unwrap }: {
228
+ feeType: FeeType;
229
+ unwrap: boolean;
230
+ }) => bigint;
231
+ /**
232
+ * An ERC-20 allowance a transaction needs before it can run: `spender` must
233
+ * be allowed to pull at least `minimum` of `token` from the sender on
234
+ * `chainId`.
235
+ */
236
+ export type ApprovalRequirement = {
237
+ chainId: number;
238
+ token: Hex;
239
+ spender: Hex;
240
+ minimum: bigint;
241
+ };
242
+ /**
243
+ * The ERC-20 `approve` call, as a target, a value and calldata. The
244
+ * interface's approval broadcast and the SDK's execution planner both build it
245
+ * here.
246
+ *
247
+ * @param options.token - the token to approve
248
+ * @param options.spender - the address allowed to pull it
249
+ * @param options.amount - the allowance to set
250
+ * @returns the call
251
+ */
252
+ export declare const approveCall: ({ token, spender, amount, }: {
253
+ token: Hex;
254
+ spender: Hex;
255
+ amount: bigint;
256
+ }) => {
257
+ to: Hex;
258
+ value: bigint;
259
+ data: Hex;
260
+ };
261
+ /**
262
+ * The `approve` amounts to send, in order, so the spender may pull exactly
263
+ * `minimum`. Empty when the allowance on chain already covers it.
264
+ *
265
+ * EXACT, NEVER UNLIMITED. An unlimited approval lets the spender pull the
266
+ * reader's whole balance for as long as the approval stands, so a later fault
267
+ * in that contract, or a spender a compromised quote named, costs everything
268
+ * rather than one transfer. The owner chose exact approvals everywhere
269
+ * (2026-10-07); the interface and the SDK's execution planner both decide
270
+ * here.
271
+ *
272
+ * A SHORT, NON-ZERO ALLOWANCE IS RESET TO ZERO FIRST. Some tokens (Tether on
273
+ * Ethereum is the known one) revert an `approve` that changes one non-zero
274
+ * allowance into another. Exact approvals leave such remainders more often,
275
+ * because an aggregator may spend less than it was allowed. A reset first
276
+ * works for every token, at the cost of one extra transaction in that case.
277
+ *
278
+ * @param options.allowance - the allowance on chain now
279
+ * @param options.minimum - the amount the next transaction pulls
280
+ * @returns the amounts to approve, in order: none, `[minimum]`, or `[0n, minimum]`
281
+ */
282
+ export declare const approvalAmounts: ({ allowance, minimum, }: {
283
+ allowance: bigint;
284
+ minimum: bigint;
285
+ }) => readonly bigint[];
286
+ /**
287
+ * The allowance a direct omnibridge crossing needs, or null when it needs none.
288
+ *
289
+ * Reads the SAME predicate {@link transactionInputs} uses to pick the call: a
290
+ * token the bridge minted ({@link interactingWithBridgeToken}) is burned by
291
+ * `transferAndCall` and needs no allowance, and the native coin is sent as
292
+ * value. Every other token is pulled by the pathway's `from` mediator through
293
+ * `relayTokens` or `relayTokensAndCall`.
294
+ *
295
+ * @param options.bridgePathway - the crossing's pathway
296
+ * @param options.assetIn - the token the crossing spends
297
+ * @param options.assetLink - the token's bridge link
298
+ * @param options.amountToBridge - the amount the crossing pulls
299
+ * @returns the approval the crossing needs, or null
300
+ */
301
+ export declare const omnibridgeApproval: ({ bridgePathway, assetIn, assetLink, amountToBridge, }: {
302
+ bridgePathway: Pathway;
303
+ assetIn: Token;
304
+ assetLink: TokenBridgeInfo;
305
+ amountToBridge: bigint;
306
+ }) => ApprovalRequirement | null;
215
307
  /**
216
308
  * Calculates the reasonable fixed fee from the estimated token network cost and desired excess compensation basis points
217
309
  * @param estimatedTokenNetworkCost - the estimated token network cost
@@ -605,7 +697,8 @@ export declare const assertCandidatePickAgrees: ({ pick, leg, sectionIndex, }: {
605
697
  * the chain's native coin
606
698
  * @param toTokenAddress - the output token address, or the zero address for
607
699
  * the chain's native coin
608
- * @param swapPath - the ordered swap path (see `pulseXConversionSwapPath`),
700
+ * @param swapPath - the ordered swap path — for a route-search hop, the one
701
+ * its quote was priced along (`pulseXSwapPathForHop`),
609
702
  * already expressed in the router's own token addresses — the wrapped-native
610
703
  * token stands in for either native end
611
704
  * @param amountIn - the amount to swap, in the input token's base units
package/dist/settings.js CHANGED
@@ -1,4 +1,4 @@
1
- import { concatHex, encodeAbiParameters, encodeFunctionData, getAddress, isAddress, isAddressEqual, zeroAddress, } from 'viem';
1
+ import { concatHex, encodeAbiParameters, encodeFunctionData, erc20Abi, getAddress, isAddress, isAddressEqual, zeroAddress, } from 'viem';
2
2
  import * as abis from './abis.js';
3
3
  import { isNative, nativeAssetOut, pathway } from './config.js';
4
4
  import { FeeType } from './fee-type.js';
@@ -230,6 +230,95 @@ export const deliveryFee = ({ shouldDeliver, routeOffersDelivery, feeType, amoun
230
230
  rate: percentFee,
231
231
  };
232
232
  };
233
+ /**
234
+ * The four-bit fee-type settings word a fee director carries.
235
+ *
236
+ * - bit 0: fixed fee mode.
237
+ * - bit 1: unwrap the delivered token to the native coin.
238
+ * - bit 2: exclude the priority fee from the delivery cost. Always set.
239
+ * - bit 3: percent fee mode.
240
+ *
241
+ * @param options.feeType - the delivery fee mode
242
+ * @param options.unwrap - whether the delivery unwraps to the native coin
243
+ * @returns the settings word for {@link feeDirectorStructEncoded}
244
+ */
245
+ export const feeTypeSettings = ({ feeType, unwrap }) => {
246
+ const fixedBit = feeType === FeeType.FIXED ? 1n : 0n;
247
+ const unwrapBit = unwrap ? 1n : 0n;
248
+ const excludePriorityBit = 1n;
249
+ const percentBit = feeType === FeeType.PERCENT ? 1n : 0n;
250
+ return (percentBit << 3n) | (excludePriorityBit << 2n) | (unwrapBit << 1n) | fixedBit;
251
+ };
252
+ /**
253
+ * The ERC-20 `approve` call, as a target, a value and calldata. The
254
+ * interface's approval broadcast and the SDK's execution planner both build it
255
+ * here.
256
+ *
257
+ * @param options.token - the token to approve
258
+ * @param options.spender - the address allowed to pull it
259
+ * @param options.amount - the allowance to set
260
+ * @returns the call
261
+ */
262
+ export const approveCall = ({ token, spender, amount, }) => ({
263
+ to: token,
264
+ value: 0n,
265
+ data: encodeFunctionData({ abi: erc20Abi, functionName: 'approve', args: [spender, amount] }),
266
+ });
267
+ /**
268
+ * The `approve` amounts to send, in order, so the spender may pull exactly
269
+ * `minimum`. Empty when the allowance on chain already covers it.
270
+ *
271
+ * EXACT, NEVER UNLIMITED. An unlimited approval lets the spender pull the
272
+ * reader's whole balance for as long as the approval stands, so a later fault
273
+ * in that contract, or a spender a compromised quote named, costs everything
274
+ * rather than one transfer. The owner chose exact approvals everywhere
275
+ * (2026-10-07); the interface and the SDK's execution planner both decide
276
+ * here.
277
+ *
278
+ * A SHORT, NON-ZERO ALLOWANCE IS RESET TO ZERO FIRST. Some tokens (Tether on
279
+ * Ethereum is the known one) revert an `approve` that changes one non-zero
280
+ * allowance into another. Exact approvals leave such remainders more often,
281
+ * because an aggregator may spend less than it was allowed. A reset first
282
+ * works for every token, at the cost of one extra transaction in that case.
283
+ *
284
+ * @param options.allowance - the allowance on chain now
285
+ * @param options.minimum - the amount the next transaction pulls
286
+ * @returns the amounts to approve, in order: none, `[minimum]`, or `[0n, minimum]`
287
+ */
288
+ export const approvalAmounts = ({ allowance, minimum, }) => {
289
+ if (allowance >= minimum)
290
+ return [];
291
+ if (allowance === 0n)
292
+ return [minimum];
293
+ return [0n, minimum];
294
+ };
295
+ /**
296
+ * The allowance a direct omnibridge crossing needs, or null when it needs none.
297
+ *
298
+ * Reads the SAME predicate {@link transactionInputs} uses to pick the call: a
299
+ * token the bridge minted ({@link interactingWithBridgeToken}) is burned by
300
+ * `transferAndCall` and needs no allowance, and the native coin is sent as
301
+ * value. Every other token is pulled by the pathway's `from` mediator through
302
+ * `relayTokens` or `relayTokensAndCall`.
303
+ *
304
+ * @param options.bridgePathway - the crossing's pathway
305
+ * @param options.assetIn - the token the crossing spends
306
+ * @param options.assetLink - the token's bridge link
307
+ * @param options.amountToBridge - the amount the crossing pulls
308
+ * @returns the approval the crossing needs, or null
309
+ */
310
+ export const omnibridgeApproval = ({ bridgePathway, assetIn, assetLink, amountToBridge, }) => {
311
+ if (assetIn.address === zeroAddress)
312
+ return null;
313
+ if (interactingWithBridgeToken({ assetLink, assetInAddress: assetIn.address }))
314
+ return null;
315
+ return {
316
+ chainId: assetIn.chainId,
317
+ token: assetIn.address,
318
+ spender: bridgePathway.from,
319
+ minimum: amountToBridge,
320
+ };
321
+ };
233
322
  /**
234
323
  * Calculates the reasonable fixed fee from the estimated token network cost and desired excess compensation basis points
235
324
  * @param estimatedTokenNetworkCost - the estimated token network cost
@@ -358,7 +447,9 @@ export const destinationDataParam = ({ recipient, bridgePathway, assetIn, destin
358
447
  if (!destinationRouter) {
359
448
  return null;
360
449
  }
361
- if (bridgePathway.requiresDelivery && !feeDirectorStructEncoded) {
450
+ // Only a delivery needs the fee director. A crossing without delivery sends
451
+ // to the recipient, whatever the fee director would have said.
452
+ if (bridgePathway.requiresDelivery && shouldDeliver && !feeDirectorStructEncoded) {
362
453
  return null;
363
454
  }
364
455
  if (!assetLink) {
@@ -653,7 +744,8 @@ export const assertCandidatePickAgrees = ({ pick, leg, sectionIndex, }) => {
653
744
  * the chain's native coin
654
745
  * @param toTokenAddress - the output token address, or the zero address for
655
746
  * the chain's native coin
656
- * @param swapPath - the ordered swap path (see `pulseXConversionSwapPath`),
747
+ * @param swapPath - the ordered swap path — for a route-search hop, the one
748
+ * its quote was priced along (`pulseXSwapPathForHop`),
657
749
  * already expressed in the router's own token addresses — the wrapped-native
658
750
  * token stands in for either native end
659
751
  * @param amountIn - the amount to swap, in the input token's base units
@@ -0,0 +1,98 @@
1
+ import type { TonDeposit } from './origin-deposit.js';
2
+ /**
3
+ * Executing a deposit on The Open Network, as pure data, with no TON library.
4
+ *
5
+ * This module imports nothing outside the package, so it loads anywhere: a
6
+ * browser, Node, or a React Native app under Hermes, with no `Buffer` and no
7
+ * polyfill. It uses only `atob` and `btoa`, which Hermes provides. The one TON
8
+ * helper that needs `@ton/core`, the TEP-467 message hash, lives in
9
+ * `@gibs/bridge-sdk/ton` instead.
10
+ *
11
+ * Relay describes a deposit as a list of internal messages carrying `to`,
12
+ * `value`, `body` and a `bounce` flag. A connected wallet, however, is driven
13
+ * through the TON Connect protocol, whose request shape is different in one way
14
+ * that silently loses money:
15
+ *
16
+ * **TON Connect has no per-message `bounce` field.** A wallet derives whether a
17
+ * message bounces from the FORM OF THE ADDRESS — the bounceable `EQ…` prefix or
18
+ * the non-bounceable `UQ…` one. Passing Relay's address through unchanged while
19
+ * dropping its `bounce: false` therefore sends a deposit to the bounceable form,
20
+ * and the depository bounces the funds straight back to the sender. The transfer
21
+ * looks like it succeeded and the route never fills.
22
+ *
23
+ * {@link buildTonConnectRequest} folds `bounce` into the address so the flag
24
+ * cannot be dropped on the way to a wallet.
25
+ *
26
+ * Kept free of transport and of clock reads so it is fully testable: nothing
27
+ * here signs, fetches, or calls `Date.now`. The caller supplies the deadline and
28
+ * performs the request.
29
+ *
30
+ * The rules encoded here are those of Relay's own wallet adapter, which is the
31
+ * only reference implementation of this mapping.
32
+ */
33
+ /**
34
+ * The TON Connect network identifier for mainnet. Relay bridges only mainnet, so
35
+ * a request is always tagged with this.
36
+ */
37
+ export declare const tonConnectMainnetNetwork = "-239";
38
+ /** How long a request stays valid by default, in seconds, matching Relay's adapter. */
39
+ export declare const tonConnectDefaultValidForSeconds = 300;
40
+ /** An address split into the parts that survive a change of encoding. */
41
+ type ParsedTonAddress = {
42
+ workchain: number;
43
+ hash: Uint8Array;
44
+ /** Preserved rather than assumed: re-encoding a testnet address as mainnet would misdirect it. */
45
+ testOnly: boolean;
46
+ };
47
+ /**
48
+ * Parses either address form The Open Network uses.
49
+ *
50
+ * @param value - a friendly (`EQ…`/`UQ…`) or raw (`0:…`) address
51
+ * @returns the address parts, or null when it is neither form or fails its checksum
52
+ */
53
+ export declare const parseTonAddress: (value: string) => ParsedTonAddress | null;
54
+ /**
55
+ * Re-encodes an address into the friendly form matching a bounce setting.
56
+ *
57
+ * This is the whole point of the module: the bounce flag has nowhere else to
58
+ * live in a TON Connect request, so it has to be carried by the address itself.
59
+ *
60
+ * @param address - the address in either form
61
+ * @param options.bounceable - whether the message may bounce back to the sender
62
+ * @returns the friendly address, or null when the input cannot be parsed
63
+ */
64
+ export declare const encodeTonAddress: (address: string, { bounceable }: {
65
+ bounceable: boolean;
66
+ }) => string | null;
67
+ /** One message of a TON Connect request. Note `address`/`amount`, not `to`/`value`. */
68
+ export type TonConnectMessage = {
69
+ address: string;
70
+ /** Attached amount in nanotons, as a decimal string. */
71
+ amount: string;
72
+ /** Base64 bag-of-cells body, omitted when the message carries none. */
73
+ payload?: string;
74
+ };
75
+ /** The request handed to a wallet's TON Connect `sendTransaction` call. */
76
+ export type TonConnectRequest = {
77
+ /** Unix seconds after which a wallet must refuse the request. */
78
+ validUntil: number;
79
+ network: string;
80
+ /** The sending account, when the deposit names one. */
81
+ from?: string;
82
+ messages: TonConnectMessage[];
83
+ };
84
+ /**
85
+ * Builds the TON Connect request for a deposit.
86
+ *
87
+ * @param deposit - the parsed origin deposit
88
+ * @param options.validUntil - unix seconds after which the request expires.
89
+ * Supplied by the caller rather than read from a clock here so the transform
90
+ * stays pure; {@link tonConnectDefaultValidForSeconds} is the usual offset.
91
+ * @returns the request, or null when the deposit carries no messages or any
92
+ * destination address cannot be re-encoded — never a request whose bounce
93
+ * setting has been silently dropped
94
+ */
95
+ export declare const buildTonConnectRequest: (deposit: TonDeposit, { validUntil }: {
96
+ validUntil: number;
97
+ }) => TonConnectRequest | null;
98
+ export {};
@@ -0,0 +1,200 @@
1
+ /**
2
+ * Executing a deposit on The Open Network, as pure data, with no TON library.
3
+ *
4
+ * This module imports nothing outside the package, so it loads anywhere: a
5
+ * browser, Node, or a React Native app under Hermes, with no `Buffer` and no
6
+ * polyfill. It uses only `atob` and `btoa`, which Hermes provides. The one TON
7
+ * helper that needs `@ton/core`, the TEP-467 message hash, lives in
8
+ * `@gibs/bridge-sdk/ton` instead.
9
+ *
10
+ * Relay describes a deposit as a list of internal messages carrying `to`,
11
+ * `value`, `body` and a `bounce` flag. A connected wallet, however, is driven
12
+ * through the TON Connect protocol, whose request shape is different in one way
13
+ * that silently loses money:
14
+ *
15
+ * **TON Connect has no per-message `bounce` field.** A wallet derives whether a
16
+ * message bounces from the FORM OF THE ADDRESS — the bounceable `EQ…` prefix or
17
+ * the non-bounceable `UQ…` one. Passing Relay's address through unchanged while
18
+ * dropping its `bounce: false` therefore sends a deposit to the bounceable form,
19
+ * and the depository bounces the funds straight back to the sender. The transfer
20
+ * looks like it succeeded and the route never fills.
21
+ *
22
+ * {@link buildTonConnectRequest} folds `bounce` into the address so the flag
23
+ * cannot be dropped on the way to a wallet.
24
+ *
25
+ * Kept free of transport and of clock reads so it is fully testable: nothing
26
+ * here signs, fetches, or calls `Date.now`. The caller supplies the deadline and
27
+ * performs the request.
28
+ *
29
+ * The rules encoded here are those of Relay's own wallet adapter, which is the
30
+ * only reference implementation of this mapping.
31
+ */
32
+ /**
33
+ * The TON Connect network identifier for mainnet. Relay bridges only mainnet, so
34
+ * a request is always tagged with this.
35
+ */
36
+ export const tonConnectMainnetNetwork = '-239';
37
+ /** How long a request stays valid by default, in seconds, matching Relay's adapter. */
38
+ export const tonConnectDefaultValidForSeconds = 300;
39
+ /** Address tag byte for the bounceable (`EQ…`) form. */
40
+ const bounceableTag = 0x11;
41
+ /** Address tag byte for the non-bounceable (`UQ…`) form. */
42
+ const nonBounceableTag = 0x51;
43
+ /** Bit set on the tag byte for testnet-only addresses (`kQ…` / `0Q…`). */
44
+ const testnetTagFlag = 0x80;
45
+ /** A friendly address is a 36-byte structure: tag, workchain, hash, checksum. */
46
+ const friendlyAddressByteLength = 36;
47
+ /** An account identifier is always 32 bytes, in every address form. */
48
+ const accountHashByteLength = 32;
49
+ /**
50
+ * Cyclic redundancy check (16-bit, the XModem variant) over an address body.
51
+ * The Open Network appends it to every friendly address, and a re-encoded
52
+ * address whose checksum is not recomputed is rejected by wallets as malformed.
53
+ */
54
+ const checksum = (data) => {
55
+ let remainder = 0;
56
+ for (const byte of data) {
57
+ remainder ^= byte << 8;
58
+ for (let bit = 0; bit < 8; bit += 1) {
59
+ remainder =
60
+ remainder & 0x8000 ? ((remainder << 1) ^ 0x1021) & 0xffff : (remainder << 1) & 0xffff;
61
+ }
62
+ }
63
+ return remainder;
64
+ };
65
+ /** Decodes the url-safe base64 alphabet the friendly address form uses. */
66
+ const decodeBase64Url = (value) => {
67
+ const standard = value.replaceAll('-', '+').replaceAll('_', '/');
68
+ const padded = standard.padEnd(Math.ceil(standard.length / 4) * 4, '=');
69
+ try {
70
+ const binary = atob(padded);
71
+ return Uint8Array.from(binary, (character) => character.charCodeAt(0));
72
+ }
73
+ catch {
74
+ return null;
75
+ }
76
+ };
77
+ /** Encodes bytes back into the url-safe, unpadded base64 form. */
78
+ const encodeBase64Url = (bytes) => {
79
+ let binary = '';
80
+ for (const byte of bytes) {
81
+ binary += String.fromCharCode(byte);
82
+ }
83
+ return btoa(binary).replaceAll('+', '-').replaceAll('/', '_').replaceAll('=', '');
84
+ };
85
+ const parseRawAddress = (value) => {
86
+ const separator = value.indexOf(':');
87
+ if (separator < 0) {
88
+ return null;
89
+ }
90
+ const workchain = Number(value.slice(0, separator));
91
+ const hex = value.slice(separator + 1);
92
+ if (!Number.isInteger(workchain) || hex.length !== accountHashByteLength * 2) {
93
+ return null;
94
+ }
95
+ const hash = new Uint8Array(accountHashByteLength);
96
+ for (let index = 0; index < accountHashByteLength; index += 1) {
97
+ const byte = Number.parseInt(hex.slice(index * 2, index * 2 + 2), 16);
98
+ if (Number.isNaN(byte)) {
99
+ return null;
100
+ }
101
+ hash[index] = byte;
102
+ }
103
+ // The raw form carries no network tag, so mainnet is the only safe assumption.
104
+ return { workchain, hash, testOnly: false };
105
+ };
106
+ const parseFriendlyAddress = (value) => {
107
+ const bytes = decodeBase64Url(value);
108
+ if (bytes === null || bytes.length !== friendlyAddressByteLength) {
109
+ return null;
110
+ }
111
+ const body = bytes.subarray(0, friendlyAddressByteLength - 2);
112
+ // Every index below is in range: the length was checked to be exactly
113
+ // `friendlyAddressByteLength` above, so the non-null assertions are sound.
114
+ const stated = (bytes[friendlyAddressByteLength - 2] << 8) | bytes[friendlyAddressByteLength - 1];
115
+ if (checksum(body) !== stated) {
116
+ return null;
117
+ }
118
+ const tag = bytes[0];
119
+ const withoutTestFlag = tag & ~testnetTagFlag;
120
+ if (withoutTestFlag !== bounceableTag && withoutTestFlag !== nonBounceableTag) {
121
+ return null;
122
+ }
123
+ const workchainByte = bytes[1];
124
+ return {
125
+ // The masterchain is workchain -1, which travels as the byte 0xff.
126
+ workchain: workchainByte === 0xff ? -1 : workchainByte,
127
+ hash: bytes.slice(2, 2 + accountHashByteLength),
128
+ testOnly: (tag & testnetTagFlag) !== 0,
129
+ };
130
+ };
131
+ /**
132
+ * Parses either address form The Open Network uses.
133
+ *
134
+ * @param value - a friendly (`EQ…`/`UQ…`) or raw (`0:…`) address
135
+ * @returns the address parts, or null when it is neither form or fails its checksum
136
+ */
137
+ export const parseTonAddress = (value) => value.includes(':') ? parseRawAddress(value) : parseFriendlyAddress(value);
138
+ /**
139
+ * Re-encodes an address into the friendly form matching a bounce setting.
140
+ *
141
+ * This is the whole point of the module: the bounce flag has nowhere else to
142
+ * live in a TON Connect request, so it has to be carried by the address itself.
143
+ *
144
+ * @param address - the address in either form
145
+ * @param options.bounceable - whether the message may bounce back to the sender
146
+ * @returns the friendly address, or null when the input cannot be parsed
147
+ */
148
+ export const encodeTonAddress = (address, { bounceable }) => {
149
+ const parsed = parseTonAddress(address);
150
+ if (parsed === null) {
151
+ return null;
152
+ }
153
+ const bytes = new Uint8Array(friendlyAddressByteLength);
154
+ bytes[0] =
155
+ (bounceable ? bounceableTag : nonBounceableTag) | (parsed.testOnly ? testnetTagFlag : 0);
156
+ bytes[1] = parsed.workchain < 0 ? 0xff : parsed.workchain;
157
+ bytes.set(parsed.hash, 2);
158
+ const stated = checksum(bytes.subarray(0, friendlyAddressByteLength - 2));
159
+ bytes[friendlyAddressByteLength - 2] = (stated >> 8) & 0xff;
160
+ bytes[friendlyAddressByteLength - 1] = stated & 0xff;
161
+ return encodeBase64Url(bytes);
162
+ };
163
+ /**
164
+ * Builds the TON Connect request for a deposit.
165
+ *
166
+ * @param deposit - the parsed origin deposit
167
+ * @param options.validUntil - unix seconds after which the request expires.
168
+ * Supplied by the caller rather than read from a clock here so the transform
169
+ * stays pure; {@link tonConnectDefaultValidForSeconds} is the usual offset.
170
+ * @returns the request, or null when the deposit carries no messages or any
171
+ * destination address cannot be re-encoded — never a request whose bounce
172
+ * setting has been silently dropped
173
+ */
174
+ export const buildTonConnectRequest = (deposit, { validUntil }) => {
175
+ if (deposit.messages.length === 0) {
176
+ return null;
177
+ }
178
+ const messages = [];
179
+ for (const message of deposit.messages) {
180
+ const address = encodeTonAddress(message.to, { bounceable: message.bounce });
181
+ // Refuse rather than fall back to the unencoded address: the fallback is
182
+ // exactly the bounce-losing behaviour this module exists to prevent.
183
+ if (address === null) {
184
+ return null;
185
+ }
186
+ messages.push({
187
+ address,
188
+ amount: message.value.toString(),
189
+ ...(message.body ? { payload: message.body } : {}),
190
+ });
191
+ }
192
+ // `messages[0]` is present: the empty case returned null above.
193
+ const from = deposit.messages[0].from;
194
+ return {
195
+ validUntil,
196
+ network: tonConnectMainnetNetwork,
197
+ ...(from === null ? {} : { from }),
198
+ messages,
199
+ };
200
+ };
@@ -1,117 +1,7 @@
1
- import type { TonDeposit } from './origin-deposit.js';
2
1
  /**
3
- * Executing a deposit on The Open Network, as pure data.
2
+ * The original name of `@gibs/bridge-sdk/ton`, kept so existing imports work.
4
3
  *
5
- * Relay describes a deposit as a list of internal messages carrying `to`,
6
- * `value`, `body` and a `bounce` flag. A connected wallet, however, is driven
7
- * through the TON Connect protocol, whose request shape is different in one way
8
- * that silently loses money:
9
- *
10
- * **TON Connect has no per-message `bounce` field.** A wallet derives whether a
11
- * message bounces from the FORM OF THE ADDRESS — the bounceable `EQ…` prefix or
12
- * the non-bounceable `UQ…` one. Passing Relay's address through unchanged while
13
- * dropping its `bounce: false` therefore sends a deposit to the bounceable form,
14
- * and the depository bounces the funds straight back to the sender. The transfer
15
- * looks like it succeeded and the route never fills.
16
- *
17
- * {@link buildTonConnectRequest} folds `bounce` into the address so the flag
18
- * cannot be dropped on the way to a wallet.
19
- *
20
- * Kept free of transport and of clock reads so it is fully testable: nothing
21
- * here signs, fetches, or calls `Date.now`. The caller supplies the deadline and
22
- * performs the request.
23
- *
24
- * The rules encoded here are those of Relay's own wallet adapter, which is the
25
- * only reference implementation of this mapping.
26
- */
27
- /**
28
- * The TON Connect network identifier for mainnet. Relay bridges only mainnet, so
29
- * a request is always tagged with this.
30
- */
31
- export declare const tonConnectMainnetNetwork = "-239";
32
- /** How long a request stays valid by default, in seconds, matching Relay's adapter. */
33
- export declare const tonConnectDefaultValidForSeconds = 300;
34
- /** An address split into the parts that survive a change of encoding. */
35
- type ParsedTonAddress = {
36
- workchain: number;
37
- hash: Uint8Array;
38
- /** Preserved rather than assumed: re-encoding a testnet address as mainnet would misdirect it. */
39
- testOnly: boolean;
40
- };
41
- /**
42
- * Parses either address form The Open Network uses.
43
- *
44
- * @param value - a friendly (`EQ…`/`UQ…`) or raw (`0:…`) address
45
- * @returns the address parts, or null when it is neither form or fails its checksum
46
- */
47
- export declare const parseTonAddress: (value: string) => ParsedTonAddress | null;
48
- /**
49
- * Re-encodes an address into the friendly form matching a bounce setting.
50
- *
51
- * This is the whole point of the module: the bounce flag has nowhere else to
52
- * live in a TON Connect request, so it has to be carried by the address itself.
53
- *
54
- * @param address - the address in either form
55
- * @param options.bounceable - whether the message may bounce back to the sender
56
- * @returns the friendly address, or null when the input cannot be parsed
57
- */
58
- export declare const encodeTonAddress: (address: string, { bounceable }: {
59
- bounceable: boolean;
60
- }) => string | null;
61
- /** One message of a TON Connect request. Note `address`/`amount`, not `to`/`value`. */
62
- export type TonConnectMessage = {
63
- address: string;
64
- /** Attached amount in nanotons, as a decimal string. */
65
- amount: string;
66
- /** Base64 bag-of-cells body, omitted when the message carries none. */
67
- payload?: string;
68
- };
69
- /** The request handed to a wallet's TON Connect `sendTransaction` call. */
70
- export type TonConnectRequest = {
71
- /** Unix seconds after which a wallet must refuse the request. */
72
- validUntil: number;
73
- network: string;
74
- /** The sending account, when the deposit names one. */
75
- from?: string;
76
- messages: TonConnectMessage[];
77
- };
78
- /**
79
- * Builds the TON Connect request for a deposit.
80
- *
81
- * @param deposit - the parsed origin deposit
82
- * @param options.validUntil - unix seconds after which the request expires.
83
- * Supplied by the caller rather than read from a clock here so the transform
84
- * stays pure; {@link tonConnectDefaultValidForSeconds} is the usual offset.
85
- * @returns the request, or null when the deposit carries no messages or any
86
- * destination address cannot be re-encoded — never a request whose bounce
87
- * setting has been silently dropped
88
- */
89
- export declare const buildTonConnectRequest: (deposit: TonDeposit, { validUntil }: {
90
- validUntil: number;
91
- }) => TonConnectRequest | null;
92
- /**
93
- * Derives the transaction identifier from a wallet's `sendTransaction` response.
94
- *
95
- * A wallet answers with a `boc`: the base64 bag-of-cells of the signed
96
- * external-in message it broadcast — NOT the resulting transaction, and NOT a
97
- * hash. The identifier explorers and indexers (toncenter, TonAPI) resolve a
98
- * transaction by is the hash of that external message, but it must be the
99
- * NORMALIZED hash of TEP-467, not the hash of the bytes the wallet happened to
100
- * send.
101
- *
102
- * The distinction is the whole point, and getting it wrong loses a resume record
103
- * for real funds. An external-in message can be serialized several equivalent
104
- * ways — a wallet may or may not include its own `src`, may set a non-zero
105
- * `import_fee`, may attach a `stateInit`, may store the body inline or as a
106
- * reference. The raw cell hash changes with each of those wallet-specific
107
- * choices, so it frequently does NOT match what an indexer keyed the same
108
- * transaction under. TEP-467 rebuilds the message with those variable fields
109
- * stripped (`src` to none, `import_fee` to zero, `init` dropped, body forced to a
110
- * reference) so the hash is stable across wallets and matches the indexers.
111
- *
112
- * @param boc - the wallet's base64 `boc` field from `sendTransaction`
113
- * @returns the 64-character hex normalized hash, or null when the input is not a
114
- * parseable external-in message
4
+ * @deprecated Import from `@gibs/bridge-sdk/ton` for the full TON surface, or
5
+ * from `@gibs/bridge-sdk/ton-connect` for the helpers that need no TON library.
115
6
  */
116
- export declare const tonExternalMessageHash: (boc: string) => string | null;
117
- export {};
7
+ export * from './ton.js';