@gibs/bridge-sdk 1.13.1 → 1.18.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 (228) hide show
  1. package/README.md +295 -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 +255 -0
  28. package/dist/cjs/config.js +569 -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 +359 -0
  36. package/dist/cjs/execution.js +495 -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 +24 -0
  44. package/dist/cjs/index.js +40 -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 +117 -0
  59. package/dist/cjs/prices.js +224 -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/carrier-provider-key.d.ts +31 -0
  81. package/dist/cjs/routing/carrier-provider-key.js +42 -0
  82. package/dist/cjs/routing/carriers/ask-answer.d.ts +77 -0
  83. package/dist/cjs/routing/carriers/ask-answer.js +2 -0
  84. package/dist/cjs/routing/carriers/omnibridge.d.ts +137 -0
  85. package/dist/cjs/routing/carriers/omnibridge.js +459 -0
  86. package/dist/cjs/routing/carriers/pulsex-paths.d.ts +80 -0
  87. package/dist/cjs/routing/carriers/pulsex-paths.js +97 -0
  88. package/dist/cjs/routing/carriers/pulsex-split.d.ts +175 -0
  89. package/dist/cjs/routing/carriers/pulsex-split.js +193 -0
  90. package/dist/cjs/routing/carriers/pulsex.d.ts +184 -0
  91. package/dist/cjs/routing/carriers/pulsex.js +615 -0
  92. package/dist/cjs/routing/carriers/wrap.d.ts +25 -0
  93. package/dist/cjs/routing/carriers/wrap.js +119 -0
  94. package/dist/cjs/routing/composed-route-quality.d.ts +125 -0
  95. package/dist/cjs/routing/composed-route-quality.js +144 -0
  96. package/dist/cjs/routing/entry-chain-anchor.d.ts +88 -0
  97. package/dist/cjs/routing/entry-chain-anchor.js +59 -0
  98. package/dist/cjs/routing/format.d.ts +31 -0
  99. package/dist/cjs/routing/format.js +64 -0
  100. package/dist/cjs/routing/index.d.ts +42 -0
  101. package/dist/cjs/routing/index.js +142 -0
  102. package/dist/cjs/routing/producers.d.ts +770 -0
  103. package/dist/cjs/routing/producers.js +1617 -0
  104. package/dist/cjs/routing/providers.d.ts +31 -0
  105. package/dist/cjs/routing/providers.js +48 -0
  106. package/dist/cjs/routing/route-data.d.ts +397 -0
  107. package/dist/cjs/routing/route-data.js +2 -0
  108. package/dist/cjs/routing/search/compose.d.ts +168 -0
  109. package/dist/cjs/routing/search/compose.js +104 -0
  110. package/dist/cjs/routing/search/graph.d.ts +668 -0
  111. package/dist/cjs/routing/search/graph.js +461 -0
  112. package/dist/cjs/routing/search/plan-route-data.d.ts +285 -0
  113. package/dist/cjs/routing/search/plan-route-data.js +871 -0
  114. package/dist/cjs/routing/search/score.d.ts +356 -0
  115. package/dist/cjs/routing/search/score.js +445 -0
  116. package/dist/cjs/routing/swap-transactions.d.ts +95 -0
  117. package/dist/cjs/routing/swap-transactions.js +133 -0
  118. package/dist/cjs/routing/usd-value.d.ts +17 -0
  119. package/dist/cjs/routing/usd-value.js +29 -0
  120. package/dist/cjs/settings.d.ts +785 -0
  121. package/dist/cjs/settings.js +1074 -0
  122. package/dist/cjs/swap-venues.d.ts +43 -0
  123. package/dist/cjs/swap-venues.js +29 -0
  124. package/dist/cjs/ton-connect.d.ts +98 -0
  125. package/dist/cjs/ton-connect.js +206 -0
  126. package/dist/cjs/ton-execution.d.ts +7 -0
  127. package/dist/cjs/ton-execution.js +23 -0
  128. package/dist/cjs/ton.d.ts +37 -0
  129. package/dist/cjs/ton.js +83 -0
  130. package/dist/cjs/tron-execution.d.ts +146 -0
  131. package/dist/cjs/tron-execution.js +248 -0
  132. package/dist/cjs/types.d.ts +51 -0
  133. package/dist/cjs/types.js +2 -0
  134. package/dist/claims.d.ts +198 -0
  135. package/dist/claims.js +140 -0
  136. package/dist/config.d.ts +42 -3
  137. package/dist/config.js +87 -21
  138. package/dist/consolidated-quote.d.ts +109 -15
  139. package/dist/consolidated-quote.js +310 -52
  140. package/dist/execution.d.ts +359 -0
  141. package/dist/execution.js +455 -0
  142. package/dist/hyperliquid-execution.js +2 -3
  143. package/dist/index.d.ts +4 -0
  144. package/dist/index.js +4 -0
  145. package/dist/lifi-execution-guard.d.ts +13 -2
  146. package/dist/lifi-execution-guard.js +4 -0
  147. package/dist/near-intents.js +2 -3
  148. package/dist/pre-quote.d.ts +6 -6
  149. package/dist/pre-quote.js +10 -14
  150. package/dist/prices.d.ts +10 -0
  151. package/dist/prices.js +52 -1
  152. package/dist/providers.d.ts +17 -0
  153. package/dist/providers.js +6 -0
  154. package/dist/referral.d.ts +12 -4
  155. package/dist/referral.js +12 -4
  156. package/dist/relay-depository.d.ts +2 -0
  157. package/dist/relay-depository.js +82 -0
  158. package/dist/relay-quote.js +2 -3
  159. package/dist/routing/candidate.d.ts +3 -3
  160. package/dist/routing/candidate.js +3 -3
  161. package/dist/routing/carrier-provider-key.d.ts +31 -0
  162. package/dist/routing/carrier-provider-key.js +37 -0
  163. package/dist/routing/carriers/ask-answer.d.ts +17 -0
  164. package/dist/routing/carriers/omnibridge.js +23 -21
  165. package/dist/routing/carriers/pulsex-paths.d.ts +80 -0
  166. package/dist/routing/carriers/pulsex-paths.js +92 -0
  167. package/dist/routing/carriers/pulsex-split.d.ts +175 -0
  168. package/dist/routing/carriers/pulsex-split.js +185 -0
  169. package/dist/routing/carriers/pulsex.d.ts +81 -46
  170. package/dist/routing/carriers/pulsex.js +267 -148
  171. package/dist/routing/composed-route-quality.d.ts +28 -6
  172. package/dist/routing/composed-route-quality.js +36 -5
  173. package/dist/routing/entry-chain-anchor.d.ts +1 -1
  174. package/dist/routing/entry-chain-anchor.js +1 -1
  175. package/dist/routing/index.d.ts +11 -3
  176. package/dist/routing/index.js +8 -2
  177. package/dist/routing/producers.js +1 -1
  178. package/dist/routing/providers.d.ts +5 -0
  179. package/dist/routing/providers.js +5 -0
  180. package/dist/routing/route-data.d.ts +47 -5
  181. package/dist/routing/search/graph.d.ts +15 -0
  182. package/dist/routing/search/plan-route-data.d.ts +42 -1
  183. package/dist/routing/search/plan-route-data.js +68 -9
  184. package/dist/routing/search/score.d.ts +3 -0
  185. package/dist/routing/search/score.js +11 -3
  186. package/dist/routing/swap-transactions.d.ts +95 -0
  187. package/dist/routing/swap-transactions.js +127 -0
  188. package/dist/settings.d.ts +94 -1
  189. package/dist/settings.js +95 -3
  190. package/dist/swap-venues.d.ts +43 -0
  191. package/dist/swap-venues.js +24 -0
  192. package/dist/ton-connect.d.ts +98 -0
  193. package/dist/ton-connect.js +200 -0
  194. package/dist/ton-execution.d.ts +4 -114
  195. package/dist/ton-execution.js +4 -244
  196. package/dist/ton.d.ts +37 -0
  197. package/dist/ton.js +65 -0
  198. package/docs/examples/example-a-ether-to-pulse.ts +300 -0
  199. package/docs/examples/example-b-token-pulsechain-to-ethereum.ts +270 -0
  200. package/docs/examples/shared.ts +261 -0
  201. package/docs/examples/tsconfig.json +18 -0
  202. package/docs/integration-guide.md +617 -0
  203. package/ecosystems/package.json +6 -0
  204. package/execution/package.json +6 -0
  205. package/fee-type/package.json +6 -0
  206. package/hyperliquid-execution/package.json +6 -0
  207. package/image-links/package.json +6 -0
  208. package/lifi-execution-guard/package.json +6 -0
  209. package/llms.txt +75 -10
  210. package/near-intents/package.json +6 -0
  211. package/near-intents-route/package.json +6 -0
  212. package/origin-deposit/package.json +6 -0
  213. package/package.json +817 -10
  214. package/pre-quote/package.json +6 -0
  215. package/prices/package.json +6 -0
  216. package/providers/package.json +6 -0
  217. package/quote-fees/package.json +6 -0
  218. package/referral/package.json +6 -0
  219. package/relay-currencies/package.json +6 -0
  220. package/relay-quote/package.json +6 -0
  221. package/route-steps/package.json +6 -0
  222. package/routing/package.json +6 -0
  223. package/settings/package.json +6 -0
  224. package/ton/package.json +6 -0
  225. package/ton-connect/package.json +6 -0
  226. package/ton-execution/package.json +6 -0
  227. package/tron-execution/package.json +6 -0
  228. package/types/package.json +6 -0
@@ -0,0 +1,31 @@
1
+ import type { Hex } from 'viem';
2
+ import { type Provider } from '../config.js';
3
+ /**
4
+ * Builds the PulseX swap path for a conversion leg, from the bridged anchor to the
5
+ * wanted token. Routes through WPLS (`[anchor, WPLS, wanted]`) by default because
6
+ * most PulseChain tokens have a deep WPLS pool but rarely a direct pool with the USD
7
+ * anchor; it collapses to a direct `[anchor, wanted]` hop only when one side already
8
+ * IS WPLS (no point hopping through WPLS to reach WPLS). The router prices the path
9
+ * with `getAmountsOut`, so a path with no liquidity simply yields no quote.
10
+ *
11
+ * A FIXED PATH, NOT THE BEST ONE. The route search's PulseX carrier prices
12
+ * this path alongside others through its hub tokens and signs whichever
13
+ * delivers most (`carriers/pulsex-paths.ts`). This one remains the
14
+ * carrier's asynchronous `ask` path (`pulseXWrappedNativePath`).
15
+ *
16
+ * @param anchorAddress - the bridged anchor token (the swap input)
17
+ * @param wantedAddress - the token the user wants (the swap output)
18
+ * @param wplsAddress - the wrapped-native intermediary (WPLS)
19
+ * @returns the ordered swap path for `getAmountsOut`
20
+ */
21
+ export declare const pulseXConversionSwapPath: (anchorAddress: Hex, wantedAddress: Hex, wplsAddress: Hex) => readonly Hex[];
22
+ /**
23
+ * The bridge provider that crosses each omnibridge entry point to PulseChain.
24
+ *
25
+ * Typed `Provider | null` rather than `string | null` — this is the root
26
+ * source `RouteCandidate.omnibridgeProvider` and `RouteData.headlineProviderKey`
27
+ * both derive from, so a widened return type here forced every caller downstream
28
+ * to re-widen too, which is what let a wrong-kind key reach `providerDisplayName`
29
+ * unnoticed. See `routing/candidate.ts` and `routing/route-data.ts`.
30
+ */
31
+ export declare const omnibridgeProviderForEntryChain: (entryChainId: number) => Provider | null;
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.omnibridgeProviderForEntryChain = exports.pulseXConversionSwapPath = void 0;
4
+ const config_js_1 = require("../config.js");
5
+ const ecosystems_js_1 = require("../ecosystems.js");
6
+ /**
7
+ * Builds the PulseX swap path for a conversion leg, from the bridged anchor to the
8
+ * wanted token. Routes through WPLS (`[anchor, WPLS, wanted]`) by default because
9
+ * most PulseChain tokens have a deep WPLS pool but rarely a direct pool with the USD
10
+ * anchor; it collapses to a direct `[anchor, wanted]` hop only when one side already
11
+ * IS WPLS (no point hopping through WPLS to reach WPLS). The router prices the path
12
+ * with `getAmountsOut`, so a path with no liquidity simply yields no quote.
13
+ *
14
+ * A FIXED PATH, NOT THE BEST ONE. The route search's PulseX carrier prices
15
+ * this path alongside others through its hub tokens and signs whichever
16
+ * delivers most (`carriers/pulsex-paths.ts`). This one remains the
17
+ * carrier's asynchronous `ask` path (`pulseXWrappedNativePath`).
18
+ *
19
+ * @param anchorAddress - the bridged anchor token (the swap input)
20
+ * @param wantedAddress - the token the user wants (the swap output)
21
+ * @param wplsAddress - the wrapped-native intermediary (WPLS)
22
+ * @returns the ordered swap path for `getAmountsOut`
23
+ */
24
+ const pulseXConversionSwapPath = (anchorAddress, wantedAddress, wplsAddress) => {
25
+ const isWpls = (address) => (0, ecosystems_js_1.sameAddress)(address, wplsAddress, 'evm');
26
+ if (isWpls(anchorAddress) || isWpls(wantedAddress))
27
+ return [anchorAddress, wantedAddress];
28
+ return [anchorAddress, wplsAddress, wantedAddress];
29
+ };
30
+ exports.pulseXConversionSwapPath = pulseXConversionSwapPath;
31
+ /**
32
+ * The bridge provider that crosses each omnibridge entry point to PulseChain.
33
+ *
34
+ * Typed `Provider | null` rather than `string | null` — this is the root
35
+ * source `RouteCandidate.omnibridgeProvider` and `RouteData.headlineProviderKey`
36
+ * both derive from, so a widened return type here forced every caller downstream
37
+ * to re-widen too, which is what let a wrong-kind key reach `providerDisplayName`
38
+ * unnoticed. See `routing/candidate.ts` and `routing/route-data.ts`.
39
+ */
40
+ const omnibridgeProviderForEntryChain = (entryChainId) => {
41
+ const entryChain = (0, config_js_1.toChain)(entryChainId);
42
+ if (entryChain === config_js_1.Chains.ETH)
43
+ return config_js_1.Providers.PULSECHAIN;
44
+ if (entryChain === config_js_1.Chains.BNB)
45
+ return config_js_1.Providers.TOKENSEX;
46
+ return null;
47
+ };
48
+ exports.omnibridgeProviderForEntryChain = omnibridgeProviderForEntryChain;
@@ -0,0 +1,397 @@
1
+ import type { Hex } from 'viem';
2
+ import type { QuoteFee } from '../quote-fees.js';
3
+ import type { ProviderKey } from '../providers.js';
4
+ import type { CarrierStepKind } from './carrier-provider-key.js';
5
+ /**
6
+ * The executing engine family a route runs through.
7
+ *
8
+ * `'swap'` is a same-chain PulseX swap: one signature, no crossing, no
9
+ * `entryChainId`, headlined by the PulseX provider rather than an omnibridge
10
+ * or aggregator one. It exists as its own kind rather than being folded into
11
+ * `'direct'` because a swap and a crossing are refused by two DIFFERENT
12
+ * guards (`swapRefusal` versus `crossingRefusal` in `@gibs/bridge-sdk/settings`)
13
+ * — collapsing the kinds would collapse the distinction the guards exist to
14
+ * keep honest.
15
+ */
16
+ export type RouteKind = 'direct' | 'aggregated' | 'conversion' | 'swap';
17
+ /**
18
+ * What grounds a figure that is NOT a live, provider-confirmed quote.
19
+ *
20
+ * DECLARED HERE, NOT IN `routing/search/graph.ts`, even though the general
21
+ * route search is what produces every estimate today. `RouteData` (this
22
+ * module) is the lower layer that `graph.ts` already depends on for
23
+ * `RouteKind` and the rest of the raw route shape — so the union belongs
24
+ * where the module that needs it already reaches, rather than forcing this
25
+ * one to import upward from the module that depends on it. `graph.ts` imports
26
+ * this type and re-exports it rather than declaring its own; there is exactly
27
+ * one definition.
28
+ *
29
+ * - `'probe-rate'` — a tiny reference trade's realized rate, scaled up.
30
+ * - `'priced-conversion'` — a currency conversion applied to a priced figure.
31
+ * - `'provider-model'` — an aggregator carrier's own provider-model estimate
32
+ * (`@gibs/quotes`'s `Carrier.estimate`): a price ratio times (one minus its
33
+ * typical fee) minus a fixed cost, calibrated against observed history.
34
+ * RANKABLE, same as `'probe-rate'` and `'priced-conversion'` — see
35
+ * {@link RANKABLE_ESTIMATE_BASES} in `routing/search/graph.ts` — but NEVER
36
+ * CONFIRMED (see {@link isConfirmedBasis} there): it never asked a real
37
+ * provider for this exact edge, only modeled one, so a search may prune and
38
+ * rank on it but may never report it as the final winner without a live
39
+ * quote first.
40
+ * - `'unpriced'` — a bare decimal rescale with no value behind it at all. This
41
+ * basis never reaches {@link RouteLandingData.estimateBasis} or
42
+ * {@link RouteOutputData.estimateBasis} — a figure grounded on nothing is
43
+ * left out of `amount` entirely rather than labelled; see that field's own
44
+ * note.
45
+ */
46
+ export type EstimateBasis = 'probe-rate' | 'priced-conversion' | 'provider-model' | 'unpriced';
47
+ /**
48
+ * A token reference in raw form — symbol, on-chain address, decimal chain id, and
49
+ * token decimals. Token and chain logos are OPTIONAL pre-resolved passthroughs: a
50
+ * producer that already has the correct image url for its route family (for
51
+ * example the direct path, whose token logos come from the multi-source asset
52
+ * resolver and chain metadata) sets them; a producer that does not leaves them
53
+ * undefined and the user-interface adapter resolves them from `chainId` + `address`
54
+ * via the image service. A field set to `null` means "deliberately no logo" and is
55
+ * preserved as-is (distinct from undefined, which triggers adapter resolution).
56
+ */
57
+ export type RouteTokenRef = {
58
+ /** Token ticker symbol, e.g. "USDC". */
59
+ symbol: string;
60
+ /**
61
+ * Token contract address on `chainId`.
62
+ *
63
+ * Typed as `string` rather than `Hex` because a route can pass through a
64
+ * non-Ethereum chain, where the token identifier is not `0x`-prefixed — a
65
+ * Bitcoin address, a Solana or Tron base58 address, a The Open Network
66
+ * user-friendly address. Treat it as an opaque identifier; anything deriving an
67
+ * image or a checksum from it must check for the `0x` prefix first.
68
+ */
69
+ address: string;
70
+ /** Decimal chain identifier this reference is presented on. */
71
+ chainId: number;
72
+ /**
73
+ * Token decimals, for amount formatting downstream. Optional because an
74
+ * INTERMEDIATE stop carries no amount to format — it renders as an icon only,
75
+ * and the provider quote that named it does not always report its decimals.
76
+ */
77
+ decimals?: number;
78
+ /** Pre-resolved token logo url; undefined → adapter resolves, null → no logo. */
79
+ logoUri?: string | null;
80
+ /** Pre-resolved chain-badge logo url; undefined → adapter resolves, null → none. */
81
+ chainLogoUri?: string | null;
82
+ };
83
+ /**
84
+ * One underlying hop within a signature section, in raw form. United States dollar
85
+ * cost is a NUMBER (`feeUsdValue`); the adapter formats it. Provider identity is a
86
+ * raw display `providerName` plus, when the hop resolves its logo from a provider
87
+ * key rather than a quote-supplied url, an optional `providerKey`. When the hop's
88
+ * logo comes straight from the aggregator quote, `providerLogoUri` carries it and
89
+ * the adapter prefers it over key resolution.
90
+ */
91
+ export type RouteHopData = {
92
+ /** Display name for the hop's provider, e.g. "LI.FI", "PulseChain Bridge". */
93
+ providerName: string;
94
+ /** Raw provider key for logo resolution when no `providerLogoUri` is supplied. */
95
+ providerKey?: ProviderKey | null;
96
+ /**
97
+ * What the hop does when no provider performs it (a native wrap). Such a hop
98
+ * has a null `providerKey`; the adapter draws its mark from this kind.
99
+ */
100
+ stepKind?: CarrierStepKind | null;
101
+ /** Quote-supplied provider logo url (aggregator legs); preferred when present. */
102
+ providerLogoUri?: string | null;
103
+ /** Human-readable hop title, e.g. "Bridge to PulseChain". */
104
+ title: string;
105
+ /** Token conversion subtitle derived from symbols, e.g. "ETH → USDC", or null. */
106
+ conversion?: string | null;
107
+ /**
108
+ * The token this hop CONSUMES, when the provider named it. Present alongside
109
+ * {@link conversion} rather than replacing it: the conversion line is prose for
110
+ * the hop detail, while these references are structural, so the section's token
111
+ * flow can be derived from the hops instead of guessing at the endpoints.
112
+ */
113
+ fromToken?: RouteTokenRef | null;
114
+ /**
115
+ * The token this hop PRODUCES — the stop the funds actually reach when the hop
116
+ * completes. Null/undefined when the provider named no output token.
117
+ */
118
+ toToken?: RouteTokenRef | null;
119
+ /** Per-hop fee in United States dollars as a NUMBER, or null when unknown. A search route's figure INCLUDES the signature's network gas (carried on the section's first hop). */
120
+ feeUsdValue?: number | null;
121
+ /** The part of {@link feeUsdValue} that is not network gas: what the hop costs in value. Absent when the producer states no gas split. */
122
+ feeExcludingGasUsdValue?: number | null;
123
+ /** The network gas of the signature this hop opens, in dollars; null or absent on every hop that opens none, and when gas is unknown. */
124
+ gasUsdValue?: number | null;
125
+ /** True when this hop runs automatically inside the section's single signature. */
126
+ automatic?: boolean;
127
+ };
128
+ /**
129
+ * The network gas a route needs on one signing chain, summed across the
130
+ * signatures it signs there.
131
+ */
132
+ export type RouteGasByChain = {
133
+ /** The chain the signatures broadcast on. */
134
+ chainId: number;
135
+ /** The native coin they burn, in base units (wei), or null when the chain's gas price is unknown. */
136
+ amountWei: bigint | null;
137
+ /** The same gas in dollars, or null when the amount or the native price is unknown. */
138
+ usdValue: number | null;
139
+ };
140
+ /**
141
+ * What a signature section's funds LAND IN when that step completes — the stop
142
+ * the money actually comes to rest at, named in tokens rather than only drawn as
143
+ * an icon in the flow. Every step of a route ends somewhere, and until this
144
+ * existed only the route's FINAL delivery was stated in words: an intermediate
145
+ * step showed its cost but never how much of what it left the user holding.
146
+ *
147
+ * `amount` is null when the step is quoted only on return (a deferred leg), in
148
+ * which case the step still names the token it will land in.
149
+ */
150
+ export type RouteLandingData = {
151
+ /** Amount landed in base units, or null when the step is not yet quoted. */
152
+ amount: bigint | null;
153
+ /** Landed token decimals, for formatting. */
154
+ decimals: number;
155
+ /** Landed token symbol, e.g. "USDC". */
156
+ symbol: string;
157
+ /** Landed value in United States dollars as a NUMBER, or null when unpriced. */
158
+ usdValue?: number | null;
159
+ /**
160
+ * What grounds `amount` when it is NOT a live, provider-confirmed quote —
161
+ * absent (or null) for an ordinary quoted figure. See {@link EstimateBasis}
162
+ * for the members and why it is declared in this module.
163
+ *
164
+ * `'unpriced'` never reaches here: a figure grounded on no value at all is
165
+ * left out of `amount` entirely rather than labelled.
166
+ */
167
+ estimateBasis?: EstimateBasis | null;
168
+ };
169
+ /**
170
+ * Origin tokens a step does NOT consume, which therefore stay in the user's
171
+ * wallet.
172
+ *
173
+ * This exists because a route is quoted in two phases: the first solves FORWARD
174
+ * for the amount the user typed and reports the provider's guaranteed delivery
175
+ * floor, and the second solves BACKWARD to that floor. Backward-solving to a
176
+ * floor that sits below the forward expectation needs LESS origin token than was
177
+ * typed, so the difference — the slippage cushion, whatever the provider's
178
+ * tolerance happens to be — is simply never spent.
179
+ *
180
+ * It is deliberately NOT modelled as a cost and never enters `totalCostUsdValue`:
181
+ * the user keeps this money. Folding it into either the amount paid or the amount
182
+ * delivered would make one of those figures state something untrue, which is why
183
+ * it is carried as its own fact for the step's breakdown to name.
184
+ */
185
+ export type RouteUnspentData = {
186
+ /** Unspent amount in ORIGIN token base units. */
187
+ amount: bigint;
188
+ /** Origin token decimals, for formatting. */
189
+ decimals: number;
190
+ /** Origin token symbol, e.g. "ETH". */
191
+ symbol: string;
192
+ /** Unspent value in United States dollars as a NUMBER, or null when unpriced. */
193
+ usdValue: number | null;
194
+ };
195
+ /**
196
+ * One signature section of a route, in raw form. One section per manual wallet
197
+ * signature. Token flow is raw references; the section fee is a NUMBER. Provider
198
+ * identity is an optional raw `providerKey` the adapter resolves to name + logo.
199
+ */
200
+ export type RouteSectionData = {
201
+ /** Stable within-route key, e.g. "candidate-1-signature-1". */
202
+ id: string;
203
+ /** Short label naming what this signature does, e.g. "Bridge to PulseChain". */
204
+ label: string;
205
+ /** Raw provider key for the service executing this signature, or null. */
206
+ providerKey?: ProviderKey | null;
207
+ /** What the signature does when no provider performs it (a native wrap); see {@link RouteHopData.stepKind}. */
208
+ stepKind?: CarrierStepKind | null;
209
+ /**
210
+ * The token-icon flow this signature walks, in raw references: the source, then
211
+ * every INTERMEDIATE stop the funds pass through, then the destination. A
212
+ * producer that knows its hops derives this from them (source, then each hop's
213
+ * output token) so the stops shown are the ones the route actually makes; a
214
+ * producer with a single hop emits just source → destination.
215
+ */
216
+ tokenFlow: RouteTokenRef[];
217
+ /**
218
+ * What this step leaves the user holding when it completes. Absent on a step
219
+ * whose producer cannot say — the step then shows its cost alone, as before.
220
+ */
221
+ landing?: RouteLandingData | null;
222
+ /**
223
+ * Origin tokens this step does not consume; they stay in the user's wallet.
224
+ * Absent on every step that spends exactly what it was given, which is all of
225
+ * them but the aggregator leg. See {@link RouteUnspentData} for why this is not
226
+ * a cost.
227
+ */
228
+ unspent?: RouteUnspentData | null;
229
+ /** Section total fee in United States dollars as a NUMBER, or null. A search route's figure INCLUDES this signature's network gas. */
230
+ feeUsdValue?: number | null;
231
+ /** The part of {@link feeUsdValue} that is not network gas. Absent when the producer states no gas split. */
232
+ feeExcludingGasUsdValue?: number | null;
233
+ /** This signature's network gas in dollars, or null/absent when unknown. */
234
+ gasUsdValue?: number | null;
235
+ /** Numeric inputs for an optional fee breakdown line (conversion mode). */
236
+ feePercent?: number | null;
237
+ /** Price-impact percentage for an optional fee breakdown line (conversion mode). */
238
+ priceImpactPercent?: number | null;
239
+ /** Estimated duration for this signature in minutes, or null to omit. */
240
+ etaMinutes?: number | null;
241
+ /** Estimated duration for this signature in seconds (sub-minute legs), or null. */
242
+ etaSeconds?: number | null;
243
+ /** The underlying hops this signature performs, first to last. */
244
+ hops: RouteHopData[];
245
+ /** True when signed only after a prior section's crossing settles (deferred). */
246
+ deferred?: boolean;
247
+ /** Explanation shown for a deferred section; the adapter supplies a default. */
248
+ deferredNote?: string;
249
+ /**
250
+ * Per-step transaction-transparency details for the advanced disclosure: the
251
+ * contract address(es) this signature touches and its encoded calldata.
252
+ * Absent until known. The direct route populates {@link bridgeFrom},
253
+ * {@link bridgeTo} and {@link destinationRouter} from the resolved omnibridge
254
+ * pathway; the same-chain PulseX swap route populates {@link destinationRouter}
255
+ * (the PulseX router, never a bridge mediator) and {@link calldata} from the
256
+ * SAME builder its own signing button calls
257
+ * (`pulseXSwapTransactionInputs` in `settings.ts`) — never a second encoding.
258
+ * Every other producer leaves it undefined until its execute path is wired.
259
+ */
260
+ advanced?: {
261
+ /** Source-side bridge mediator address for this step, or null. */
262
+ bridgeFrom?: Hex | null;
263
+ /** Destination-side bridge mediator address for this step, or null. */
264
+ bridgeTo?: Hex | null;
265
+ /**
266
+ * The destination-side router this step's delivery calls, or null when
267
+ * none. For the same-chain swap route this IS the PulseX router — the
268
+ * whole signature, not a delivery leg inside a crossing.
269
+ */
270
+ destinationRouter?: Hex | null;
271
+ /** Encoded calldata for this step's signature, or null when unknown. */
272
+ calldata?: Hex | null;
273
+ };
274
+ /**
275
+ * What the aggregator carrying this signature charges, itemized.
276
+ *
277
+ * The single `feeUsdValue` above is the difference between what the sender
278
+ * pays and what lands, which is a true total and says nothing about where it
279
+ * went. This is the breakdown behind it - and it is the only place a charge
280
+ * levied OUTSIDE `fromAmount` can appear at all, because such a charge never
281
+ * shows up in that difference.
282
+ */
283
+ fees?: QuoteFee[];
284
+ };
285
+ /** What a route delivers, in raw form. `amount` is null when not yet known. */
286
+ export type RouteOutputData = {
287
+ /** Delivered amount in base units, or null when unknown at quote time. */
288
+ amount: bigint | null;
289
+ /** Delivered token decimals, for formatting. */
290
+ decimals: number;
291
+ /** Delivered token symbol. */
292
+ symbol: string;
293
+ /** Delivered value in United States dollars as a NUMBER, or null when unpriced. */
294
+ usdValue?: number | null;
295
+ /**
296
+ * What grounds `amount` when it is NOT a live, provider-confirmed quote. See
297
+ * {@link RouteLandingData.estimateBasis} for the full rule — this is the
298
+ * same field, on the route's final delivery rather than one step's landing.
299
+ */
300
+ estimateBasis?: EstimateBasis | null;
301
+ };
302
+ /**
303
+ * One route in raw, data-only form — the framework-agnostic shape route builders
304
+ * produce. Carries bigint amounts, numeric United States dollar values, chain
305
+ * identifiers, and raw provider keys ONLY: no logo urls, no pre-formatted strings,
306
+ * and no human-readable chain names. The user-interface adapter `toRouteView`
307
+ * derives all of those to produce the display-ready route.
308
+ */
309
+ export type RouteData = {
310
+ /**
311
+ * Structural id. Unset by raw producers in this phase; the user-interface
312
+ * adapter assigns it from the assembled display option so shared links stay
313
+ * stable. Optional so producers need not compute it.
314
+ */
315
+ id?: string;
316
+ /** The executing engine family this route runs through. */
317
+ kind: RouteKind;
318
+ /** The omnibridge entry chain id for non-direct routes; null for direct. */
319
+ entryChainId: number | null;
320
+ /**
321
+ * Optional override for the chain shown as the route's "via" crossing, when it
322
+ * differs from {@link entryChainId}. The outbound route sets this to the chain it
323
+ * bridges TO while keeping `entryChainId` null (it has no aggregator entry chain).
324
+ * Unset on every other route, where the adapter falls back to `entryChainId`.
325
+ */
326
+ viaChainId?: number | null;
327
+ /**
328
+ * Raw provider key for the route's headline provider — the omnibridge crossing
329
+ * when the route has one, otherwise the aggregator that carries the whole
330
+ * journey.
331
+ *
332
+ * Typed `ProviderKey`, not `string`. Every producer always supplies a real
333
+ * one (an omnibridge `Provider` when there is a bridge leg, the aggregator's
334
+ * own `ProviderId` otherwise — see `producers.ts`'s `omnibridgeProviderKey ??
335
+ * candidate.quote.provider`), so there is no case where a route has none.
336
+ * `providerDisplayName` (`producers.ts`) still accepts a bare `string`
337
+ * itself, deliberately: display code reading a STORED or otherwise
338
+ * deserialized `RouteData` cannot rely on this type annotation to have
339
+ * survived the round trip, and must render something rather than throw on a
340
+ * value it no longer recognizes.
341
+ */
342
+ headlineProviderKey: ProviderKey;
343
+ /** The signature sections of the route, top to bottom. */
344
+ sections: RouteSectionData[];
345
+ /** What the route delivers — used for ranking and the output row. */
346
+ output: RouteOutputData;
347
+ /**
348
+ * Aggregate ALL-IN cost in United States dollars as a NUMBER, or null:
349
+ * value lost plus network gas. The ranking reads this figure. For the
350
+ * figure without gas, read {@link costExcludingGasUsdValue}.
351
+ */
352
+ totalCostUsdValue?: number | null;
353
+ /** {@link totalCostUsdValue} without network gas: the value the reader gives up. Absent when the producer states no gas split. */
354
+ costExcludingGasUsdValue?: number | null;
355
+ /**
356
+ * The network gas the reader pays across every signature, in dollars, or
357
+ * null/absent when no signing chain has a gas reading. Never zero for
358
+ * "unknown".
359
+ */
360
+ gasCostUsdValue?: number | null;
361
+ /** The gas by signing chain, in signing order: what to hold, and in which coin. */
362
+ gasByChain?: RouteGasByChain[];
363
+ /** The user's net United States dollar outcome; the figure routes are ranked on. */
364
+ netValueUsd?: number | null;
365
+ /** Estimated end-to-end duration in minutes, or null when unknown. */
366
+ etaMinutes?: number | null;
367
+ /** True for the single best route; set by the ranker. */
368
+ isBest?: boolean;
369
+ /** Percentage difference versus the best route, negative; set by the ranker. */
370
+ deltaPercent?: number | null;
371
+ /**
372
+ * The general-search plan's stable path identity, when this route came
373
+ * from one — see the route-search design, section 1, and
374
+ * `RoutePlan.pathKey` in `routing/search/graph.ts`.
375
+ *
376
+ * ABSENT ON EVERY ROUTE PHASE 0 PRODUCES. `journeyPlan.ts`'s `pathKeyFor`
377
+ * derives a route's path key from `entryChainId` alone today; once a route
378
+ * carries this field, Phase 3's `journeyPlan.ts` work prefers it, because
379
+ * `entryChainId` alone cannot tell two plans that share an entry chain but
380
+ * cross through different intermediate assets or carriers apart.
381
+ */
382
+ pathKey?: string;
383
+ /**
384
+ * The decimal chain ids every intermediate hop of the route passes
385
+ * through, origin and destination excluded, in hop order.
386
+ *
387
+ * ABSENT ON EVERY ROUTE PHASE 0 PRODUCES, and on any route with no
388
+ * intermediate chain (a same-chain crossing, or a route with exactly one
389
+ * hop). {@link viaChainId} on `RouteOption` already names the SINGLE entry
390
+ * chain today's two-hop routes pass through; this field exists because a
391
+ * general-search plan can pass through MORE than one intermediate chain
392
+ * (for example Zcash → NEAR's Ethereum settlement → the omnibridge entry
393
+ * chain → PulseChain), and a single `viaChainId` cannot name more than one
394
+ * of them.
395
+ */
396
+ viaChainIds?: number[];
397
+ };
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,168 @@
1
+ import { type ComposedPathBasis, type EstimateBasis, type HopEdge } from './graph.js';
2
+ /**
3
+ * PHASE 1 — composes a path's per-hop figures into one end-to-end delivered
4
+ * amount, as design section 3 describes ("Composition"): "A later hop's
5
+ * output is estimated as its probe rate × the actual input. Rank on that
6
+ * estimate."
7
+ *
8
+ * WHY THIS IS ITS OWN MODULE, SEPARATE FROM `graph.ts` AND `score.ts`. A
9
+ * {@link HopEdge} names WHO carries a hop and WHICH two assets it connects;
10
+ * it says nothing about a delivered amount, because Phase 0 introduced no
11
+ * quoting. `PlannedHop.outcome` (`graph.ts`) says what a hop delivers ONCE
12
+ * something has already computed that figure. This module is the thing that
13
+ * computes it: given a starting amount and a sequence of hop figures — each
14
+ * either a REAL QUOTE (an exact amount) or a PROBE RATE (a ratio observed at
15
+ * some other, unrelated amount) — it walks the path and produces the single
16
+ * number a search ranks on.
17
+ *
18
+ * WHY EVERY RESULT IS AN ESTIMATE. Only the route's first signature has to be
19
+ * a binding quote (design section 3: "Only signature 1 must be binding").
20
+ * Composing a chain of figures — even a chain where every individual figure
21
+ * happens to be a real quote — is not itself something any provider quoted
22
+ * end to end, so the composed, path-level figure is never treated as a
23
+ * binding quote. It is always an ESTIMATE, which is what keeps a later leg
24
+ * honestly labelled until the reader returns to it and it is re-quoted for
25
+ * real (design section 3; section 4's `D` still uses this estimate for
26
+ * RANKING, which is a different thing from promising it).
27
+ *
28
+ * WHY BASE-UNIT BIGINTS, NEVER A FLOAT. A composed figure is money. Every
29
+ * amount here is kept as a bigint in the token's own base units all the way
30
+ * through; a rate is an exact bigint ratio ({@link ExchangeRate}), and
31
+ * applying it is one bigint multiply followed by one bigint divide — never a
32
+ * floating-point multiply, which would round a real amount away from what
33
+ * the chain will actually move.
34
+ */
35
+ /**
36
+ * An exact exchange rate, expressed as a bigint ratio: `numerator` output
37
+ * base units per `denominator` input base units, at the amount the rate was
38
+ * observed. Never a float — see this module's doc.
39
+ *
40
+ * This is what a Phase 1 "probe" produces: one carrier asked, once, "what
41
+ * would this hop return for a REFERENCE amount," and the ratio of that
42
+ * reference's output to its input is the rate. The reference amount itself
43
+ * plays no further part once the ratio is taken; only the ratio composes.
44
+ */
45
+ export type ExchangeRate = {
46
+ /** Output base units the rate implies, per {@link denominator} input base units. */
47
+ readonly numerator: bigint;
48
+ /** Input base units the rate is quoted against. Must be a positive number. */
49
+ readonly denominator: bigint;
50
+ };
51
+ /**
52
+ * What one hop knows about its own pricing, before composition applies it to
53
+ * the amount actually arriving at that hop.
54
+ *
55
+ * `'quote'` — the carrier returned an exact `outputAmount` for the exact
56
+ * amount that arrives at this hop in THIS path. Used as given; composition
57
+ * does no further math on it.
58
+ *
59
+ * `'probeRate'` — the carrier was asked at some other, reference amount, and
60
+ * only the resulting {@link ExchangeRate} survived. Composition multiplies
61
+ * this rate by the ACTUAL amount arriving at the hop, per design section 3.
62
+ * Carries the {@link EstimateBasis} that grounds it (`graph.ts`) — PHASE 3:
63
+ * a `'probeRate'` figure is not always a genuine probe; `waves.ts` also uses
64
+ * this kind to carry forward a hop's pre-network `'priced-conversion'` or
65
+ * `'unpriced'` estimate when no fresh answer landed, and the basis is what
66
+ * tells the two apart.
67
+ */
68
+ export type ComposableHopFigure = {
69
+ readonly kind: 'quote';
70
+ readonly outputAmount: bigint;
71
+ } | {
72
+ readonly kind: 'probeRate';
73
+ readonly rate: ExchangeRate;
74
+ readonly basis: EstimateBasis;
75
+ };
76
+ /** The {@link ComposedPathBasis} one hop's figure contributes: `'quoted'` for a bound quote, its own basis for a `'probeRate'`. */
77
+ export declare const composableHopBasis: (figure: ComposableHopFigure) => ComposedPathBasis;
78
+ /**
79
+ * One hop of a path being composed: the edge it travels (which carries the
80
+ * two {@link AssetNode}s composition checks for a decimals disagreement) and
81
+ * what is known about its pricing.
82
+ */
83
+ export type ComposableHop = {
84
+ /** The graph edge this hop travels — supplies both endpoints' decimals. */
85
+ readonly edge: HopEdge;
86
+ /** What this hop knows about its own pricing. */
87
+ readonly figure: ComposableHopFigure;
88
+ };
89
+ /**
90
+ * Why {@link composeRouteDelivery} refused to compose a path, rather than
91
+ * guess at an answer it cannot stand behind.
92
+ *
93
+ * `'empty-path'` — there were no hops to compose across.
94
+ *
95
+ * `'discontinuous-path'` — one hop's `to` asset is not the next hop's `from`
96
+ * asset, so there is no single amount that "arrives" at the second hop; the
97
+ * hops given do not describe one connected path.
98
+ *
99
+ * `'decimals-mismatch'` — two hops name the SAME asset (by
100
+ * {@link assetNodeKey}) with two DIFFERENT decimal counts. This is a data
101
+ * bug — one asset has one true decimals count — and composing through it
102
+ * would silently misplace a decimal point in real money.
103
+ *
104
+ * `'missing-rate'` — a hop's figure is a {@link ComposableHopFigure} of kind
105
+ * `'probeRate'` whose {@link ExchangeRate.denominator} is not a positive
106
+ * number, so the rate names no real ratio.
107
+ */
108
+ export type ComposeRefusalReason = 'empty-path' | 'discontinuous-path' | 'decimals-mismatch' | 'missing-rate';
109
+ /**
110
+ * The result of composing a path: either the estimated delivered amount, or
111
+ * why composition refused to produce one.
112
+ */
113
+ export type ComposedRouteDelivery = {
114
+ readonly kind: 'estimate';
115
+ /** The composed delivered amount, in the LAST hop's `to` asset's base units. */
116
+ readonly deliveredAmount: bigint;
117
+ /**
118
+ * What grounds {@link deliveredAmount} — the WORST (least-grounded)
119
+ * {@link ComposedPathBasis} among every hop composed (see
120
+ * {@link combineComposedPathBasis}). PHASE 3: a ranking must check this
121
+ * before comparing {@link deliveredAmount} against another path's — see
122
+ * `graph.ts`'s {@link isRankableBasis} for the rule.
123
+ */
124
+ readonly basis: ComposedPathBasis;
125
+ } | {
126
+ readonly kind: 'refused';
127
+ readonly reason: ComposeRefusalReason;
128
+ /** Which hop (0-based, into the `hops` argument) triggered the refusal. */
129
+ readonly hopIndex: number;
130
+ };
131
+ /**
132
+ * Composes a path's per-hop figures into one end-to-end estimated delivered
133
+ * amount, applying design section 3's rule: a later hop's output is its
134
+ * probe rate applied to the ACTUAL amount arriving at that hop — never the
135
+ * reference amount the probe itself was taken at.
136
+ *
137
+ * REFUSES RATHER THAN GUESSES in three cases, checked hop by hop so the
138
+ * refusal names the exact hop responsible: the path is empty
139
+ * ({@link ComposeRefusalReason} `'empty-path'`); a hop does not connect to the
140
+ * one before it (`'discontinuous-path'`); two hops disagree about a shared
141
+ * asset's decimals (`'decimals-mismatch'`); or a `'probeRate'` figure names
142
+ * no real ratio (`'missing-rate'`). See {@link ComposeRefusalReason} for why
143
+ * each of these is a refusal and not a best-effort answer.
144
+ *
145
+ * @param inputAmount - the base-unit amount entering the path's first hop
146
+ * @param hops - the path's hops, first to last
147
+ * @returns the composed estimate, or the refusal that stopped composition
148
+ */
149
+ export declare const composeRouteDelivery: (inputAmount: bigint, hops: readonly ComposableHop[]) => ComposedRouteDelivery;
150
+ /**
151
+ * One hop's output amount for the actual amount arriving at it: the quote's
152
+ * own `outputAmount` when the figure is a real quote, or the probe rate
153
+ * applied to `actualInput` when it is a `'probeRate'`. Returns null — never a
154
+ * guessed number — when a `'probeRate'` figure's rate names no positive
155
+ * denominator.
156
+ *
157
+ * EXPORTED SO `waves.ts` REUSES THIS MATH RATHER THAN RESTATING IT.
158
+ * `recomposePath` (`waves.ts`) needs each hop's OWN output amount, not just
159
+ * the path's final total {@link composeRouteDelivery} returns, to refresh
160
+ * every hop's individual `outcome` — this is the one place that division
161
+ * happens, so both call sites agree by construction instead of by two
162
+ * separately-maintained copies of `numerator * input / denominator`.
163
+ *
164
+ * @param hop - the hop to price
165
+ * @param actualInput - the actual base-unit amount arriving at this hop
166
+ * @returns the hop's output amount, or null when its rate is missing
167
+ */
168
+ export declare const hopOutputAmount: (hop: ComposableHop, actualInput: bigint) => bigint | null;