@gibs/bridge-sdk 1.18.0 → 1.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (120) hide show
  1. package/README.md +33 -0
  2. package/dist/abis.js +0 -2
  3. package/dist/bridge-limits.js +0 -38
  4. package/dist/chain-info.js +0 -116
  5. package/dist/chain-names.js +0 -151
  6. package/dist/chains.js +0 -198
  7. package/dist/cjs/abis.js +0 -2
  8. package/dist/cjs/bridge-limits.js +0 -38
  9. package/dist/cjs/chain-info.js +0 -116
  10. package/dist/cjs/chain-names.js +0 -151
  11. package/dist/cjs/chains.js +0 -198
  12. package/dist/cjs/claims.js +0 -60
  13. package/dist/cjs/config.js +1 -208
  14. package/dist/cjs/consolidated-quote.js +2 -464
  15. package/dist/cjs/destination-calldata.js +0 -71
  16. package/dist/cjs/ecosystems.js +0 -183
  17. package/dist/cjs/execution.js +0 -92
  18. package/dist/cjs/fee-type.js +0 -1
  19. package/dist/cjs/hyperliquid-execution.js +0 -98
  20. package/dist/cjs/image-links.js +0 -108
  21. package/dist/cjs/lifi-execution-guard.js +65 -172
  22. package/dist/cjs/near-intents-conformance.js +0 -110
  23. package/dist/cjs/near-intents-route.d.ts +13 -0
  24. package/dist/cjs/near-intents-route.js +7 -140
  25. package/dist/cjs/near-intents.js +0 -562
  26. package/dist/cjs/origin-deposit.js +0 -56
  27. package/dist/cjs/pre-quote.js +0 -80
  28. package/dist/cjs/prices.js +0 -113
  29. package/dist/cjs/providers.js +0 -83
  30. package/dist/cjs/quote-fees.js +0 -80
  31. package/dist/cjs/referral.js +0 -75
  32. package/dist/cjs/relay-currencies.js +0 -31
  33. package/dist/cjs/relay-depository.js +52 -77
  34. package/dist/cjs/relay-quote.js +0 -394
  35. package/dist/cjs/route-steps.js +0 -100
  36. package/dist/cjs/routing/amounts.js +0 -83
  37. package/dist/cjs/routing/candidate-route.d.ts +46 -1
  38. package/dist/cjs/routing/candidate-route.js +12 -40
  39. package/dist/cjs/routing/candidate.js +0 -46
  40. package/dist/cjs/routing/carrier-provider-key.js +0 -27
  41. package/dist/cjs/routing/carriers/omnibridge.js +0 -120
  42. package/dist/cjs/routing/carriers/pulsex-paths.js +0 -57
  43. package/dist/cjs/routing/carriers/pulsex-split.js +0 -92
  44. package/dist/cjs/routing/carriers/pulsex.js +0 -279
  45. package/dist/cjs/routing/carriers/wrap.js +0 -57
  46. package/dist/cjs/routing/composed-route-quality.js +0 -95
  47. package/dist/cjs/routing/entry-chain-anchor.js +0 -27
  48. package/dist/cjs/routing/format.js +0 -50
  49. package/dist/cjs/routing/index.d.ts +1 -1
  50. package/dist/cjs/routing/index.js +3 -30
  51. package/dist/cjs/routing/producers.js +0 -854
  52. package/dist/cjs/routing/providers.js +0 -27
  53. package/dist/cjs/routing/search/compose.js +0 -56
  54. package/dist/cjs/routing/search/graph.js +0 -364
  55. package/dist/cjs/routing/search/plan-route-data.js +5 -510
  56. package/dist/cjs/routing/search/score.js +0 -344
  57. package/dist/cjs/routing/swap-transactions.js +0 -74
  58. package/dist/cjs/routing/usd-value.js +0 -12
  59. package/dist/cjs/settings.js +1 -456
  60. package/dist/cjs/swap-venues.js +0 -17
  61. package/dist/cjs/ton-connect.js +0 -82
  62. package/dist/cjs/ton-execution.js +0 -6
  63. package/dist/cjs/ton.js +0 -42
  64. package/dist/cjs/tron-execution.js +0 -145
  65. package/dist/cjs/types.d.ts +8 -0
  66. package/dist/claims.js +0 -60
  67. package/dist/config.js +1 -211
  68. package/dist/consolidated-quote.js +2 -464
  69. package/dist/destination-calldata.js +0 -71
  70. package/dist/ecosystems.js +0 -183
  71. package/dist/execution.js +0 -92
  72. package/dist/fee-type.js +0 -2
  73. package/dist/hyperliquid-execution.js +0 -98
  74. package/dist/image-links.js +0 -108
  75. package/dist/lifi-execution-guard.js +65 -172
  76. package/dist/near-intents-conformance.js +0 -110
  77. package/dist/near-intents-route.d.ts +13 -0
  78. package/dist/near-intents-route.js +5 -139
  79. package/dist/near-intents.js +0 -562
  80. package/dist/origin-deposit.js +0 -56
  81. package/dist/pre-quote.js +0 -80
  82. package/dist/prices.js +0 -113
  83. package/dist/providers.js +0 -83
  84. package/dist/quote-fees.js +0 -80
  85. package/dist/referral.js +0 -75
  86. package/dist/relay-currencies.js +0 -31
  87. package/dist/relay-depository.js +52 -77
  88. package/dist/relay-quote.js +0 -394
  89. package/dist/route-steps.js +0 -100
  90. package/dist/routing/amounts.js +0 -83
  91. package/dist/routing/candidate-route.d.ts +46 -1
  92. package/dist/routing/candidate-route.js +10 -39
  93. package/dist/routing/candidate.js +0 -46
  94. package/dist/routing/carrier-provider-key.js +0 -27
  95. package/dist/routing/carriers/omnibridge.js +0 -120
  96. package/dist/routing/carriers/pulsex-paths.js +0 -57
  97. package/dist/routing/carriers/pulsex-split.js +0 -92
  98. package/dist/routing/carriers/pulsex.js +0 -279
  99. package/dist/routing/carriers/wrap.js +0 -57
  100. package/dist/routing/composed-route-quality.js +0 -95
  101. package/dist/routing/entry-chain-anchor.js +0 -27
  102. package/dist/routing/format.js +0 -50
  103. package/dist/routing/index.d.ts +1 -1
  104. package/dist/routing/index.js +1 -29
  105. package/dist/routing/producers.js +0 -854
  106. package/dist/routing/providers.js +0 -27
  107. package/dist/routing/search/compose.js +0 -56
  108. package/dist/routing/search/graph.js +0 -364
  109. package/dist/routing/search/plan-route-data.js +6 -511
  110. package/dist/routing/search/score.js +0 -344
  111. package/dist/routing/swap-transactions.js +0 -74
  112. package/dist/routing/usd-value.js +0 -12
  113. package/dist/settings.js +1 -456
  114. package/dist/swap-venues.js +0 -17
  115. package/dist/ton-connect.js +0 -82
  116. package/dist/ton-execution.js +0 -6
  117. package/dist/ton.js +0 -42
  118. package/dist/tron-execution.js +0 -145
  119. package/dist/types.d.ts +8 -0
  120. package/package.json +3 -3
@@ -8,164 +8,18 @@ const chain_names_js_1 = require("./chain-names.js");
8
8
  const ecosystems_js_1 = require("./ecosystems.js");
9
9
  const relay_quote_js_1 = require("./relay-quote.js");
10
10
  const referral_js_1 = require("./referral.js");
11
- /**
12
- * NEAR Intents, through its "one click" quoting service.
13
- *
14
- * THIS PROVIDER CANNOT EXECUTE ON THE DESTINATION CHAIN, AND IS REGISTERED
15
- * ANYWAY. Read both halves of that before changing anything here.
16
- *
17
- * The service validates its request body against a closed property list and
18
- * answers `property destinationCall should not exist` for every name a call
19
- * could travel under — `destinationCall`, `calldata`, `msg`, `txs`, `hook`,
20
- * `action`, `postSwapAction`. The only thing nameable on the destination side
21
- * is an address: `recipient`, with a `recipientType` of `DESTINATION_CHAIN`,
22
- * `INTENTS` or `CONFIDENTIAL_INTENTS`. That is measured, not inferred from
23
- * silence. `docs/near-intents-capability-survey.md` holds the evidence.
24
- *
25
- * DELIVERING TO THE MEDIATOR INSTEAD IS NOT A WAY AROUND IT, and the reason is
26
- * structural rather than a matter of configuration. The service will happily
27
- * deliver to a contract — a quote naming a well-known router as `recipient` is
28
- * accepted. But every omnibridge entry point learns WHO THE READER IS from a
29
- * data field: `transferAndCall` carries the recipient in its third argument,
30
- * `relayTokens` in its second, `wrapAndRelayTokens` in its first. A plain
31
- * token transfer has no data field. So a bare arrival cannot name a recipient,
32
- * which means it can only ever credit the sender — the solver — or nobody at
33
- * all. Do not attempt it.
34
- *
35
- * SO THE ROUTE TAKES TWO SIGNATURES, and the interface says so on the route
36
- * strip rather than in a tooltip. The reader signs the origin transfer; NEAR
37
- * Intents lands the anchor token in THEIR OWN WALLET on the entry chain; then
38
- * they sign the ordinary bridge leg themselves. `near-intents-route.ts` builds
39
- * that shape, and `executesDestinationCalls: false` on the descriptor is what
40
- * keeps this provider out of the single-signature machinery, including the
41
- * entry-anchor pre-quote — that phase feeds an exact-output target to the
42
- * providers that DO execute, and a target only a non-executing provider can
43
- * reach is a target nobody can fill.
44
- *
45
- * TWO SIZE FLOORS MAKE THIS A ROUTING RULE, NOT A FOOTNOTE. Binance Smart
46
- * Chain — one of the two omnibridge entry chains — refuses any transfer worth
47
- * one thousand United States dollars or less, in either direction, and Polygon
48
- * and Tron carry floors of their own. The service imposed these on 2026-09-09
49
- * and calls them temporary. Only asking reveals them, so a route has to be
50
- * WITHDRAWN on a refusal rather than left to fail: see
51
- * {@link NearIntentsQuoteRefusal} and `near-intents-route.ts`.
52
- */
53
- /** Base address for the NEAR Intents one-click service. */
54
11
  exports.nearIntentsApiBaseUrl = 'https://1click.chaindefuser.com';
55
- /** Quote endpoint. Verified live: no key required, and a key-less request is answered in full. */
56
12
  exports.nearIntentsQuoteUrl = `${exports.nearIntentsApiBaseUrl}/v0/quote`;
57
- /** The list of assets the service can carry, keyed by its own asset identifiers. */
58
13
  exports.nearIntentsTokensUrl = `${exports.nearIntentsApiBaseUrl}/v0/tokens`;
59
- /**
60
- * Optional notification that the reader's deposit has been sent. The service
61
- * detects the deposit on its own; telling it the transaction hash only makes
62
- * the detection faster. Takes `{ txHash, depositAddress }`.
63
- */
64
14
  exports.nearIntentsDepositSubmitUrl = `${exports.nearIntentsApiBaseUrl}/v0/deposit/submit`;
65
- /**
66
- * What a key-less request costs, in basis points of the input amount.
67
- *
68
- * NOT A FEE THIS CODE CHARGES OR CAN DECLINE. The service inserts it into the
69
- * echoed request as an `appFees` entry payable to its own account whenever no
70
- * key is presented, so a reader on a key-less route pays a quarter of a percent
71
- * that no part of this repository asked for. It is named here so the parser can
72
- * surface it as a charge rather than let it disappear into the delivered
73
- * amount. A partner key reduces it; obtaining one is an owner decision.
74
- */
75
15
  exports.nearIntentsUnauthenticatedFeeBasisPoints = 25;
76
- /**
77
- * What a partner-key request costs instead, in basis points of the input
78
- * amount, for an ordinary (non-stablecoin) pair.
79
- *
80
- * Read from the service's own current documentation on 2026-09-18:
81
- * `docs.near-intents.org/integration/distribution-channels/1click-api/authentication`.
82
- * See `docs/near-intents-partner-key.md` for the full process of obtaining a
83
- * key and what else changes once one is configured.
84
- */
85
16
  exports.nearIntentsAuthenticatedFeeBasisPoints = 20;
86
- /**
87
- * What a partner-key request costs on a stablecoin pair or a same-asset
88
- * multi-chain route, in basis points of the input amount.
89
- *
90
- * Read from the same page as {@link nearIntentsAuthenticatedFeeBasisPoints} on
91
- * 2026-09-18. Kept as its own constant rather than a special case of the other
92
- * one because the service documents it as a distinct figure for a distinct
93
- * class of route, not a discount computed from the ordinary rate.
94
- */
95
17
  exports.nearIntentsAuthenticatedStablecoinFeeBasisPoints = 1;
96
- /**
97
- * Builds the status-poll address for one quote.
98
- *
99
- * The deposit address IS the lookup key here, unlike every other provider in
100
- * this repository, which key by a request identifier. Each quote is issued its
101
- * own deposit address, so the two are one and the same fact — see
102
- * {@link parseNearIntentsQuote}, which puts the deposit address in `quoteId`
103
- * for exactly this reason.
104
- *
105
- * @param options.quoteId - the quote's deposit address
106
- * @returns the fully-formed status address
107
- */
108
18
  const nearIntentsStatusUrl = ({ quoteId }) => {
109
19
  return (0, url_1.buildUrl)(`${exports.nearIntentsApiBaseUrl}/v0/status`, { depositAddress: quoteId });
110
20
  };
111
21
  exports.nearIntentsStatusUrl = nearIntentsStatusUrl;
112
- /**
113
- * What this repository calls itself when it asks the one-click service.
114
- *
115
- * SENT BECAUSE THE SERVICE REFUSES SOME CALLERS BY NAME, and until now the
116
- * name was whatever the runtime happened to supply. The service sits behind
117
- * Cloudflare, which answers a refused caller with HTTP 403 and a body reading
118
- * `error code: 1010` — a page, not a quote, so a parser sees a shape it cannot
119
- * read and the whole provider looks like an outage.
120
- *
121
- * MEASURED against the live quote endpoint on 2026-09-21, one identical body,
122
- * one header changed:
123
- *
124
- * | user agent | answer |
125
- * | ------------------------- | ------ |
126
- * | none (Node 26 default) | 201 |
127
- * | `undici` | 201 |
128
- * | `node` | 201 |
129
- * | `curl/8.7.1` | 201 |
130
- * | `python-requests/2.32` | 201 |
131
- * | `Python-urllib/3.14` | 403 |
132
- * | this value | 201 |
133
- *
134
- * So nothing is blocked today. The point is that whether we are blocked was
135
- * being decided by a list we do not control, matched against a string we never
136
- * chose — and a runtime upgrade could change that string without anyone here
137
- * touching a line. Naming ourselves fixes the input to that decision.
138
- *
139
- * A BROWSER IGNORES THIS, and that is fine. `User-Agent` is a forbidden header
140
- * name for `fetch`, so the browser drops it silently and sends its own. The
141
- * value therefore governs Node alone: the live test harness, the deposit
142
- * poller, and any script written later.
143
- */
144
22
  exports.nearIntentsUserAgent = 'gibs-bridge/1.0 (+https://gibs.finance)';
145
- /**
146
- * Request headers for the one-click service.
147
- *
148
- * THE KEY IS A JSON WEB TOKEN, NOT A PLAIN IDENTIFIER LIKE RELAY'S. The
149
- * service's own documentation accepts it as `Authorization: Bearer` as well as
150
- * `X-API-Key`, calls it a "JWT token" throughout, and tells an integrator to
151
- * "store your JWT token securely and never commit it to version control. Use
152
- * environment variables or secure secret management systems." Relay's
153
- * documentation says none of that about its key. `X-API-Key` is the form sent
154
- * here because the service accepts it and it matches the header name Relay
155
- * already uses, so one code path serves both — but the caller of this
156
- * function decides where the value comes from, and that decision is where the
157
- * secrecy question has to be answered. See `packages/ui/src/lib/config.ts`
158
- * and `docs/near-intents-partner-key.md`.
159
- *
160
- * THE DEFAULT `User-Agent` NAMES GIBS FINANCE, AND THAT COSTS A CALLER
161
- * NOTHING: it carries no key and no rate-limit budget, and a browser drops it.
162
- * Pass `options.userAgent` to name yourself instead, or `null` to send none and
163
- * let the runtime use its own.
164
- *
165
- * @param apiKey - a partner key, when one is configured
166
- * @param options - `userAgent`: your own value, or `null` for none (defaults to {@link nearIntentsUserAgent})
167
- * @returns the headers, carrying the key only when there is one to carry
168
- */
169
23
  const nearIntentsRequestHeaders = (apiKey, options = {}) => {
170
24
  const userAgent = (0, referral_js_1.resolveAttribution)(options.userAgent, exports.nearIntentsUserAgent);
171
25
  return {
@@ -175,24 +29,6 @@ const nearIntentsRequestHeaders = (apiKey, options = {}) => {
175
29
  };
176
30
  };
177
31
  exports.nearIntentsRequestHeaders = nearIntentsRequestHeaders;
178
- /**
179
- * This repository's chain identifiers, keyed by the service's short chain name.
180
- *
181
- * The Ethereum-virtual-machine entries are read from viem rather than written
182
- * down, because a chain identifier typed from memory is a hypothesis that every
183
- * later reader will trust — and a wrong one here does not fail loudly, it
184
- * simply quotes a different chain's token.
185
- *
186
- * The non-Ethereum entries are this repository's own identifiers for those
187
- * families, which are Relay's numbers (see {@link relayChainIds}); the service
188
- * uses short names and has no numeric identifier of its own to reconcile with.
189
- *
190
- * DELIBERATELY SHORTER THAN THE SERVICE'S CHAIN LIST. The service names about
191
- * thirty-five chains. Only the ones this bridge can actually originate from or
192
- * enter are listed, because an unlisted chain resolves to no asset and
193
- * therefore to no route, which is the honest outcome, whereas a guessed
194
- * identifier resolves to a route on the wrong chain.
195
- */
196
32
  exports.chainIdByNearIntentsChain = new Map([
197
33
  ['eth', chains_1.mainnet.id],
198
34
  ['bsc', chains_1.bsc.id],
@@ -208,10 +44,6 @@ exports.chainIdByNearIntentsChain = new Map([
208
44
  ['tron', chain_names_js_1.relayChainIds.tron],
209
45
  ['ton', chain_names_js_1.relayChainIds.ton],
210
46
  ['hypercore', chain_names_js_1.relayChainIds.hyperliquid],
211
- // THE ONE ENTRY WITH NO WALLET BEHIND IT. Zcash is not a Relay chain and not
212
- // a LI.FI chain; this repository names it itself, in `chain-names.ts`, so
213
- // that a route from it can be priced and drawn. The reader pays the address
214
- // this service issues, by hand, from wherever they hold the coin.
215
47
  ['zec', chain_names_js_1.depositAddressChainIds.zcash],
216
48
  ]);
217
49
  const asRecord = (value) => {
@@ -220,17 +52,6 @@ const asRecord = (value) => {
220
52
  }
221
53
  return value;
222
54
  };
223
- /**
224
- * Reads `GET /v0/tokens` into the asset records the identifier lookup needs.
225
- *
226
- * An entry missing any field the lookup reads is dropped rather than patched
227
- * with a default: an asset whose decimals were invented would price every
228
- * amount wrong by orders of magnitude, and an asset whose identifier is
229
- * missing cannot be quoted at all.
230
- *
231
- * @param payload - the raw JSON body from `GET /v0/tokens`
232
- * @returns every readable asset, in the order the service listed them
233
- */
234
55
  const parseNearIntentsTokens = (payload) => {
235
56
  if (!Array.isArray(payload)) {
236
57
  return [];
@@ -261,24 +82,6 @@ const parseNearIntentsTokens = (payload) => {
261
82
  return assets;
262
83
  };
263
84
  exports.parseNearIntentsTokens = parseNearIntentsTokens;
264
- /**
265
- * Finds the service's identifier for one token on one chain.
266
- *
267
- * THE IDENTIFIER CANNOT BE CONSTRUCTED, ONLY LOOKED UP. It reads like a
268
- * pattern — a chain name, the token's address, a fixed suffix — and for an
269
- * Ethereum-virtual-machine token it currently is one. It is not one for the
270
- * other families: Solana's USD Coin carries a hexadecimal handle that is
271
- * nothing like its base58 mint. Building the string from its parts therefore
272
- * produces an identifier that is well-formed and refers to nothing, so the
273
- * asset list is the only source.
274
- *
275
- * @param options.assets - the parsed asset list
276
- * @param options.chainId - this repository's identifier for the chain
277
- * @param options.tokenAddress - the token's address on that chain
278
- * @param options.ecosystem - the chain's virtual-machine family, which decides
279
- * whether the native-coin test and the address comparison are meaningful
280
- * @returns the matching asset, or null when the service does not carry it
281
- */
282
85
  const findNearIntentsAsset = ({ assets, chainId, tokenAddress, ecosystem, }) => {
283
86
  const onChain = assets.filter((asset) => exports.chainIdByNearIntentsChain.get(asset.blockchain) === chainId);
284
87
  if (onChain.length === 0) {
@@ -287,8 +90,6 @@ const findNearIntentsAsset = ({ assets, chainId, tokenAddress, ecosystem, }) =>
287
90
  if ((0, ecosystems_js_1.isNativeAsset)(tokenAddress, ecosystem)) {
288
91
  return onChain.find((asset) => asset.contractAddress === null) ?? null;
289
92
  }
290
- // Only an Ethereum-virtual-machine chain reports a token's real address here,
291
- // so a match on any other family would be a coincidence of hexadecimal.
292
93
  if (ecosystem !== 'evm') {
293
94
  return null;
294
95
  }
@@ -296,48 +97,10 @@ const findNearIntentsAsset = ({ assets, chainId, tokenAddress, ecosystem, }) =>
296
97
  return match ?? null;
297
98
  };
298
99
  exports.findNearIntentsAsset = findNearIntentsAsset;
299
- /**
300
- * How far ahead the requested refund deadline is set, in milliseconds.
301
- *
302
- * WHAT IS SENT, NOT WHAT COMES BACK. The service does not honour this value: it
303
- * returns a `deadline` of exactly three days after the one asked for, and
304
- * returns `timeWhenInactive` equal to that same instant rather than to the
305
- * earlier moment the documentation describes. Both are visible in the checked-in
306
- * capture — asked 2026-09-17T23:49:52.805Z, answered 2026-09-20T23:49:52.805Z.
307
- *
308
- * So anything that needs the real clock must read `quote.deadline` off the
309
- * answer. Reading `quoteRequest.deadline` back gives this number, which is the
310
- * request echoed, not a commitment; and treating `deadline` and
311
- * `timeWhenInactive` as two milestones reads a distinction the service is not
312
- * currently making.
313
- */
314
100
  const defaultDeadlineMilliseconds = 30 * 60 * 1000;
315
- /**
316
- * Slippage THIS MODULE sends when the caller states none, in basis points.
317
- *
318
- * Not a default the service holds. `slippageTolerance` is a required property —
319
- * the service rejects a request without it — so there is no "leave it to them"
320
- * option here as there is with the other providers, and one percent is a value
321
- * chosen on this side.
322
- */
323
101
  const defaultSlippageBasisPoints = 100;
324
- /**
325
- * Converts a slippage fraction into the basis points the service expects.
326
- *
327
- * @param slippage - tolerance as a fraction (0.005 means half a percent)
328
- * @returns basis points (0.005 becomes 50)
329
- */
330
102
  const slippageToNearIntentsBasisPoints = (slippage) => Math.round(slippage * 10_000);
331
103
  exports.slippageToNearIntentsBasisPoints = slippageToNearIntentsBasisPoints;
332
- /**
333
- * Reads the build inputs out of the shared provider context.
334
- *
335
- * Returns null when the asset list is absent, and that is not a defensive
336
- * check — without the list no asset identifier can be resolved, so there is no
337
- * request to form. Answering null leaves the route to the providers that can
338
- * express it, which is the same thing every other builder here does when it
339
- * cannot express a request.
340
- */
341
104
  const buildOptionsFrom = (context, { dry }) => {
342
105
  const assets = context?.nearIntentsAssets;
343
106
  if (assets === undefined || assets.length === 0) {
@@ -345,46 +108,6 @@ const buildOptionsFrom = (context, { dry }) => {
345
108
  }
346
109
  return { assets, now: context?.now ?? new Date(), referral: context?.referral, dry };
347
110
  };
348
- /**
349
- * Where a refund goes, and it is a different answer for a chain the reader
350
- * cannot sign on.
351
- *
352
- * THE ORDINARY CASE. A refund lands back on the ORIGIN chain, at the reader's
353
- * own origin-chain address — never the delivery address, which could not
354
- * receive one there.
355
- *
356
- * THE PAY-BY-HAND CASE, WHICH IS THE WHOLE REASON THIS FLOW IS POSSIBLE. A
357
- * reader with no Zcash wallet has no Zcash address to refund to, and
358
- * `refundType` offers no destination-chain option: the three values are
359
- * `ORIGIN_CHAIN`, `INTENTS` and `CONFIDENTIAL_INTENTS`. `INTENTS` credits the
360
- * refund to a ledger row inside the settlement contract `intents.near`, and the
361
- * row may be named for the reader's own Ethereum address, which the same
362
- * Ethereum key controls. So the reader types nothing, and the refund fee falls
363
- * from 32,000 base units to zero: crediting a balance inside a contract needs
364
- * no Zcash transaction. `docs/near-implicit-account-refunds.md` checks the
365
- * claim at the protocol level.
366
- *
367
- * TWO TRAPS, BOTH MEASURED, BOTH CAPABLE OF COSTING SOMEBODY THEIR MONEY.
368
- *
369
- * FIRST, LOWER CASE IS NOT COSMETIC. The account name must be lower case. The
370
- * same address in its checksummed spelling is refused outright with `refundTo
371
- * is not valid` — the capture is
372
- * `__fixtures__/near-intents/quote-error-zcash-refund-mixed-case.json`.
373
- *
374
- * SECOND, ACCEPTANCE PROVES NOTHING. On the intents path the service checks
375
- * only that the string looks like a NEAR account name — the literal
376
- * `not-an-address-at-all` quotes happily. A wrong value therefore passes
377
- * quoting and is discovered only when a swap is refunded to nobody. That is
378
- * why this reads `connectedEthereumAccount`, whose contract is that it comes
379
- * from the wallet connection, and why it builds nothing when that is absent
380
- * or is not an Ethereum address.
381
- *
382
- * @param options.fromChainId - the origin chain
383
- * @param options.fromAddress - the reader's address on the origin chain
384
- * @param options.connectedEthereumAccount - the reader's connected Ethereum account
385
- * @returns the two refund properties, or null when a pay-by-hand route has no
386
- * connected Ethereum account to name
387
- */
388
111
  const refundFields = ({ fromChainId, fromAddress, connectedEthereumAccount, }) => {
389
112
  if (!(0, chain_names_js_1.isDepositAddressChain)(fromChainId)) {
390
113
  return { refundTo: fromAddress, refundType: 'ORIGIN_CHAIN' };
@@ -394,81 +117,21 @@ const refundFields = ({ fromChainId, fromAddress, connectedEthereumAccount, }) =
394
117
  }
395
118
  return { refundTo: connectedEthereumAccount.toLowerCase(), refundType: 'INTENTS' };
396
119
  };
397
- /**
398
- * The smallest Zcash deposit that can actually be credited, in base units:
399
- * 0.01 Zcash.
400
- *
401
- * THE LARGER OF TWO FIGURES THAT DISAGREE. The quoting service prices a Zcash
402
- * input down to about two cents — the smaller floor, read live from its
403
- * refusal by {@link parseNearIntentsQuoteRefusal}. But Zcash crosses on the
404
- * Proof of Authority bridge, not the Omni Bridge, and that bridge publishes
405
- * `min_deposit_amount: 1000000` for native Zcash. A quote between the two is
406
- * priced by one surface and below the other's floor, so it takes the money and
407
- * stalls — and the published stuck-deposit recovery flow is written for the
408
- * Omni Bridge, so it does not cover Zcash. Measured 2026-09-21; see
409
- * `docs/near-intents-capability-survey.md`.
410
- */
411
120
  exports.zcashWorkingFloorBaseUnits = 1000000n;
412
- /**
413
- * The working floor for each chain a reader pays by hand, in base units of
414
- * that chain's native asset, one entry per member of {@link DepositAddressChain}.
415
- * Typed on the union rather than on `number` so a pay-by-hand chain added to
416
- * {@link depositAddressChainIds} without a floor here is a compile error.
417
- */
418
121
  const workingFloorBaseUnitsByChain = {
419
122
  zcash: exports.zcashWorkingFloorBaseUnits,
420
123
  };
421
- /** {@link workingFloorBaseUnitsByChain}, keyed by chain id for lookup. */
422
124
  const workingFloorByChainId = new Map(Object.keys(chain_names_js_1.depositAddressChainIds).map((chain) => [
423
125
  chain_names_js_1.depositAddressChainIds[chain],
424
126
  workingFloorBaseUnitsByChain[chain],
425
127
  ]));
426
- /**
427
- * The working floor for a pay-by-hand chain, in base units, or null when the
428
- * chain has none registered.
429
- *
430
- * EXPORTED SO A SCREEN NEVER KEEPS ITS OWN COPY. {@link isBelowWorkingFloor} is
431
- * the decision this library enforces when quoting; this is the SAME table,
432
- * exposed so a payment screen can PRINT the figure it refuses under instead of
433
- * hand-copying the table — a copy that would silently disagree with quoting
434
- * the moment a second pay-by-hand chain gets a floor here and not there.
435
- *
436
- * @param chainId - the origin chain
437
- * @returns the floor in base units, or null when the chain has none
438
- */
439
128
  const workingFloorFor = (chainId) => workingFloorByChainId.get(chainId) ?? null;
440
129
  exports.workingFloorFor = workingFloorFor;
441
- /**
442
- * Whether an amount is below the floor a deposit on this chain can actually
443
- * be credited at.
444
- *
445
- * ASK IT BEFORE ASKING FOR A LIVE QUOTE. The quote request builder already
446
- * declines such an amount, so no deposit address is ever issued for money that
447
- * would stall. This predicate lets a surface say WHY there is no route, and
448
- * what size would work.
449
- *
450
- * @param options.chainId - the origin chain
451
- * @param options.amount - the input, in base units of the origin asset
452
- * @returns whether the amount is below that chain's working floor
453
- */
454
130
  const isBelowWorkingFloor = ({ chainId, amount, }) => {
455
131
  const floor = workingFloorByChainId.get(chainId);
456
132
  return floor !== undefined && amount < floor;
457
133
  };
458
134
  exports.isBelowWorkingFloor = isBelowWorkingFloor;
459
- /**
460
- * Builds the request body every quote and pre-quote shares.
461
- *
462
- * THE ORIGIN ECOSYSTEM IS DERIVED FROM THE CHAIN ID, NOT ACCEPTED AS AN
463
- * ARGUMENT. It used to be read off the request's own `originVmType` while the
464
- * pay-by-hand `swapType` decision two lines below read `fromChainId` through
465
- * {@link isDepositAddressChain} — two signals that a caller could set to
466
- * disagree, most easily by simply leaving `originVmType` unset on a
467
- * deposit-address request. `near-intents.test.ts` certified exactly that
468
- * contradiction as a valid Zcash request before this was fixed. Deriving both
469
- * decisions from the same chain id, in the same function, makes the
470
- * disagreement impossible to construct rather than merely unlikely.
471
- */
472
135
  const buildBody = ({ fromChainId, fromTokenAddress, fromAddress, connectedEthereumAccount, toChainId, toTokenAddress, recipient, amount, swapType, slippage, options, }) => {
473
136
  if (amount <= 0n) {
474
137
  return null;
@@ -485,8 +148,6 @@ const buildBody = ({ fromChainId, fromTokenAddress, fromAddress, connectedEthere
485
148
  if (originAsset === null) {
486
149
  return null;
487
150
  }
488
- // The delivered side of every route this module can express lands on an
489
- // entry chain, which is always an Ethereum Virtual Machine chain.
490
151
  const destinationAsset = (0, exports.findNearIntentsAsset)({
491
152
  assets: options.assets,
492
153
  chainId: toChainId,
@@ -502,8 +163,6 @@ const buildBody = ({ fromChainId, fromTokenAddress, fromAddress, connectedEthere
502
163
  }
503
164
  return {
504
165
  dry: options.dry,
505
- // A reader paying by hand gets the flexible band; a reader whose wallet
506
- // composes the transfer to the exact base unit does not need one.
507
166
  swapType: (0, chain_names_js_1.isDepositAddressChain)(fromChainId) ? 'FLEX_INPUT' : swapType,
508
167
  slippageTolerance: slippage === undefined
509
168
  ? defaultSlippageBasisPoints
@@ -519,24 +178,7 @@ const buildBody = ({ fromChainId, fromTokenAddress, fromAddress, connectedEthere
519
178
  ...(options.referral === undefined ? {} : { referral: options.referral }),
520
179
  };
521
180
  };
522
- /**
523
- * Builds the forward-solving origin-to-anchor pre-quote body.
524
- *
525
- * READ THE HEAD OF THIS MODULE BEFORE CALLING THIS FROM THE ROUTER. The
526
- * entry-anchor pre-quote takes the largest delivered amount across providers
527
- * and hands it to the providers that execute, so a pre-quote from a provider
528
- * that cannot execute raises a target nobody can reach. This builder exists
529
- * because the request shape is real and testable, not because that wiring is
530
- * wanted.
531
- *
532
- * @param request - the provider-agnostic pre-quote request
533
- * @param options - the asset list, the clock, and the referral tag
534
- * @returns the request body, or null when the service carries neither asset or
535
- * the amount is not positive
536
- */
537
181
  const buildNearIntentsPreQuoteRequest = (request, context) => {
538
- // A pre-quote prices a route it will never execute, so it must not reserve a
539
- // deposit address; asking dry also keeps it out of the service's records.
540
182
  const options = buildOptionsFrom(context, { dry: true });
541
183
  if (options === null) {
542
184
  return null;
@@ -546,8 +188,6 @@ const buildNearIntentsPreQuoteRequest = (request, context) => {
546
188
  fromChainId: request.fromChainId,
547
189
  fromTokenAddress: request.fromTokenAddress,
548
190
  fromAddress: request.fromAddress,
549
- // A pre-quote carries no connected account, so a pay-by-hand origin builds
550
- // no pre-quote. None is wanted: this provider never bids in the pre-quote.
551
191
  connectedEthereumAccount: undefined,
552
192
  toChainId: request.toChainId,
553
193
  toTokenAddress: request.toTokenAddress,
@@ -559,24 +199,6 @@ const buildNearIntentsPreQuoteRequest = (request, context) => {
559
199
  });
560
200
  };
561
201
  exports.buildNearIntentsPreQuoteRequest = buildNearIntentsPreQuoteRequest;
562
- /**
563
- * Builds the execution quote body for a crossing with nothing to run on arrival.
564
- *
565
- * REFUSES ANY REQUEST CARRYING A DESTINATION CALL, and that refusal is the
566
- * whole point of it. The service has no field a call can travel in, so a
567
- * request built without the call would look like a valid quote for the same
568
- * route and would deliver the reader's funds to an address instead of into the
569
- * omnibridge — a silent, funds-affecting difference. Returning null leaves that
570
- * route to the providers that execute.
571
- *
572
- * @param request - the provider-agnostic consolidated request
573
- * @param context - carries the asset list, the clock and the referral tag
574
- * @param options.dry - price only, reserving nothing. What a route ON DISPLAY
575
- * must ask; a live quote reserves a deposit address for three days, so it is
576
- * asked only when the reader commits. See `UnreservedDeposit`.
577
- * @returns the request body, or null when the route needs a destination call,
578
- * names no input amount, or the service carries neither asset
579
- */
580
202
  const buildNearIntentsQuoteRequest = (request, context, { dry = false } = {}) => {
581
203
  if (request.destinationCall !== undefined) {
582
204
  return null;
@@ -615,17 +237,6 @@ const parseAmount = (value) => {
615
237
  return null;
616
238
  }
617
239
  };
618
- /**
619
- * Parses a quote response into the delivered amounts a pre-quote reports.
620
- *
621
- * `amountOut` is the expected delivery and `minAmountOut` the guaranteed floor
622
- * after slippage, which is the same pair the other providers' pre-quote parsers
623
- * produce, so the three rank on like figures.
624
- *
625
- * @param payload - the raw JSON body from `POST /v0/quote`
626
- * @returns the delivered amounts, or null when the payload is an error or
627
- * otherwise not a quote
628
- */
629
240
  const parseNearIntentsPreQuote = (payload) => {
630
241
  const quote = asRecord(asRecord(payload)?.quote);
631
242
  if (!quote) {
@@ -639,33 +250,7 @@ const parseNearIntentsPreQuote = (payload) => {
639
250
  return { expectedAmount, minimumAmount: minimumAmount ?? expectedAmount };
640
251
  };
641
252
  exports.parseNearIntentsPreQuote = parseNearIntentsPreQuote;
642
- /**
643
- * Builds the transfer the reader signs to fund a quote.
644
- *
645
- * THE SERVICE RETURNS NO TRANSACTION, ONLY AN ADDRESS. Every other provider in
646
- * this repository hands back a signable payload; this one hands back a deposit
647
- * address and watches the chain for an ordinary transfer into it. So the origin
648
- * deposit is CONSTRUCTED here from the request, not read off the response, and
649
- * the response alone is not enough to produce one.
650
- *
651
- * There is never an approval. Nothing pulls from the reader's account — they
652
- * send — so a spender allowance has nothing to authorize.
653
- *
654
- * @param options.depositAddress - the address the quote reserved
655
- * @param options.amount - the input amount, in the origin token's base units
656
- * @param options.request - the request the quote answered
657
- * @returns the Ethereum deposit, or null for an origin family this cannot build
658
- */
659
253
  const nearIntentsOriginDeposit = ({ depositAddress, amount, request, }) => {
660
- // Only Ethereum-virtual-machine origins are built. The other families need a
661
- // transfer composed in that family's own encoding — a Solana instruction, a
662
- // Bitcoin transaction — and no signer in this repository accepts a transfer
663
- // this module composed. Returning null declines the route rather than
664
- // handing a wallet a payload meant for a different chain.
665
- //
666
- // Derived from the chain id, never from the request's own `originVmType` —
667
- // see the note on {@link buildBody}, which fixes the same signal for the
668
- // same reason.
669
254
  if ((0, relay_quote_js_1.ecosystemByChainId)(request.fromChainId) !== 'evm') {
670
255
  return null;
671
256
  }
@@ -696,37 +281,6 @@ const nearIntentsOriginDeposit = ({ depositAddress, amount, request, }) => {
696
281
  gasLimit: null,
697
282
  };
698
283
  };
699
- /**
700
- * Builds the deposit for a chain the reader pays by hand: an address, an
701
- * amount, a tolerance and a clock, and nothing to sign.
702
- *
703
- * EVERY FIELD IS READ OFF THE LIVE ANSWER, and each one refuses rather than
704
- * defaults, because a wrong figure here is shown to a person who then sends
705
- * money by hand:
706
- *
707
- * - the address must be a well-formed address ON THE ORIGIN CHAIN. An answer
708
- * that issued an Ethereum-shaped address for a Zcash route is not a Zcash
709
- * deposit, whatever else it says.
710
- * - the displayed minimum is the LARGER of two floors, never `minAmountIn`
711
- * alone. `minAmountIn` is the service's flexible-input floor, priced about
712
- * one percent under the quoted amount; {@link isBelowWorkingFloor} is the
713
- * bridge's own floor, which does not move with the quote and can sit above
714
- * `minAmountIn` for a small Zcash amount. A reader told to send the smaller
715
- * figure sends a deposit the bridge will not credit, and it stalls with no
716
- * published recovery — see {@link zcashWorkingFloorBaseUnits}. The combined
717
- * minimum still may not exceed the quoted amount; one that did would tell
718
- * the reader to send more than asked, so that is refused rather than shown.
719
- * - `deadline` is the answer's own. The request's echoed deadline is ignored
720
- * by the service, which substitutes one three days out — see
721
- * {@link defaultDeadlineMilliseconds}.
722
- *
723
- * @param options.quote - the `quote` record of a live answer
724
- * @param options.depositAddress - the address that answer issued
725
- * @param options.amount - the quoted input, in base units of the origin asset
726
- * @param options.chainId - the origin chain
727
- * @param options.decimals - the origin asset's decimal places
728
- * @returns the deposit, or null when any field is missing or malformed
729
- */
730
284
  const depositAddressOriginDeposit = ({ quote, depositAddress, amount, chainId, decimals, }) => {
731
285
  if (!(0, ecosystems_js_1.isValidAddressIn)(depositAddress, (0, relay_quote_js_1.ecosystemByChainId)(chainId))) {
732
286
  return null;
@@ -754,16 +308,6 @@ const depositAddressOriginDeposit = ({ quote, depositAddress, amount, chainId, d
754
308
  expiresAtMs,
755
309
  };
756
310
  };
757
- /**
758
- * Reads what the route charges.
759
- *
760
- * TWO OF THE THREE NUMBERS THE SERVICE REPORTS ARE COSTS, AND ONE IS NOT.
761
- * `withdrawFee` is taken out of the delivered amount on every successful route,
762
- * and the key-less surcharge in the echoed `appFees` is taken out of the input,
763
- * so both are real. `refundFee` is charged ONLY when a swap is refunded — it is
764
- * the price of a route that did not happen — so counting it would overstate
765
- * what a completed crossing costs, and it is deliberately left out.
766
- */
767
311
  const nearIntentsQuoteFees = ({ quote, quoteRequest, originToken, destinationToken, }) => {
768
312
  const fees = [];
769
313
  const withdrawFee = parseAmount(quote.withdrawFee);
@@ -774,8 +318,6 @@ const nearIntentsQuoteFees = ({ quote, quoteRequest, originToken, destinationTok
774
318
  amount: withdrawFee,
775
319
  token: destinationToken,
776
320
  amountUsd: null,
777
- // Taken out of what is delivered rather than added to what is sent, so
778
- // the reader never pays it on top.
779
321
  includedInFromAmount: true,
780
322
  });
781
323
  }
@@ -800,34 +342,10 @@ const nearIntentsQuoteFees = ({ quote, quoteRequest, originToken, destinationTok
800
342
  }
801
343
  return fees;
802
344
  };
803
- /**
804
- * Normalizes a quote response into the shared consolidated quote shape.
805
- *
806
- * READS THE REQUEST AS WELL AS THE RESPONSE, unlike every other parser here,
807
- * and it has to: the response names a deposit address and no transaction, so
808
- * the origin chain, the origin token and the ecosystem — everything needed to
809
- * build the transfer the reader signs — exist only on the request. That is why
810
- * {@link ProviderQuoteContext} carries a request at all.
811
- *
812
- * A DRY QUOTE IS REFUSED. It carries prices and no deposit address, so it can
813
- * never be executed, and a quote that cannot be executed must not be returned
814
- * as one.
815
- *
816
- * @param payload - the raw JSON body from `POST /v0/quote`
817
- * @param context - carries the request this answers and both tokens' metadata
818
- * @returns the normalized quote, or null when the payload cannot produce one
819
- */
820
- /**
821
- * The parts of an answer every NEAR Intents quote needs, reserved or not.
822
- *
823
- * @returns the pieces, or null when the context or the body is unusable
824
- */
825
345
  const quoteEssentials = (payload, context) => {
826
346
  const request = context?.request;
827
347
  const originToken = context?.originToken;
828
348
  const destinationToken = context?.destinationToken;
829
- // Without the request there is no chain and no token to compose a transfer
830
- // from, so there is no quote to return — the same answer as a malformed body.
831
349
  if (request === undefined || originToken === undefined || destinationToken === undefined) {
832
350
  return null;
833
351
  }
@@ -845,11 +363,6 @@ const quoteEssentials = (payload, context) => {
845
363
  }
846
364
  return { request, originToken, destinationToken, body, quote, fromAmount, timeEstimate: quote.timeEstimate };
847
365
  };
848
- /**
849
- * Assembles the shared quote shape around a deposit.
850
- *
851
- * @returns the normalized quote
852
- */
853
366
  const nearIntentsQuoteShape = ({ essentials: { body, quote, fromAmount, timeEstimate, originToken, destinationToken }, quoteId, originDeposit, }) => {
854
367
  const toAmount = parseAmount(quote.amountOut);
855
368
  return {
@@ -861,10 +374,8 @@ const nearIntentsQuoteShape = ({ essentials: { body, quote, fromAmount, timeEsti
861
374
  ...(toAmount === null ? {} : { toAmount }),
862
375
  fromAmountUsd: typeof quote.amountInUsd === 'string' ? quote.amountInUsd : null,
863
376
  ...(typeof quote.amountOutUsd === 'string' ? { toAmountUsd: quote.amountOutUsd } : {}),
864
- // Nothing pulls from the reader's account, so no spender is ever approved.
865
377
  approvalAddress: null,
866
378
  executionDurationSeconds: timeEstimate,
867
- // The service reports no per-leg breakdown, only the two ends of the trade.
868
379
  steps: [],
869
380
  originDeposit,
870
381
  fees: nearIntentsQuoteFees({
@@ -875,19 +386,6 @@ const nearIntentsQuoteShape = ({ essentials: { body, quote, fromAmount, timeEsti
875
386
  }),
876
387
  };
877
388
  };
878
- /**
879
- * Normalizes a DRY answer into a quote that can be drawn and not paid.
880
- *
881
- * Same figures, fees and timing as a live quote; its deposit is
882
- * {@link UnreservedDeposit} and its `quoteId` is empty, because a dry answer
883
- * reserves no address and the address is a quote's identity. A caller that
884
- * reaches the commit asks live with `buildNearIntentsQuoteRequest(…, { dry:
885
- * false })` and pays that answer instead.
886
- *
887
- * @param payload - the raw JSON body of a `dry: true` quote
888
- * @param context - the same context the live parser reads
889
- * @returns the priced quote, or null when the body is not a quote
890
- */
891
389
  const parseNearIntentsPriceQuote = (payload, context) => {
892
390
  const essentials = quoteEssentials(payload, context);
893
391
  if (essentials === null) {
@@ -922,31 +420,11 @@ const parseNearIntentsQuote = (payload, context) => {
922
420
  if (originDeposit === null) {
923
421
  return null;
924
422
  }
925
- // The deposit address is this quote's identity: the service issues a fresh
926
- // one per quote and the status endpoint is keyed by it. See
927
- // {@link nearIntentsStatusUrl}.
928
423
  return nearIntentsQuoteShape({ essentials, quoteId: depositAddress, originDeposit });
929
424
  };
930
425
  exports.parseNearIntentsQuote = parseNearIntentsQuote;
931
- // "Temporary swap limits: minimum swap amount is $1,000" — thousands separators
932
- // and all. Captured live against Binance Smart Chain, Polygon and Tron.
933
426
  const chainMinimumPattern = /minimum swap amount is \$([\d,]+(?:\.\d+)?)/;
934
- // "Amount is too low for bridge, try at least 303824" — base units of the
935
- // origin asset, quoted live and different on consecutive requests.
936
427
  const bridgeMinimumPattern = /try at least (\d+)/;
937
- /**
938
- * Reads why a quote request was declined.
939
- *
940
- * WORTH READING RATHER THAN TREATING AS A FAILURE. A route below one of these
941
- * floors is not a fault to retry — it is a route this provider will never
942
- * carry at that size, so a router can drop the provider from the competition
943
- * and a surface can say what size would work. Left as a bare rejection, the
944
- * same route simply produces a slower answer with one fewer bidder and nothing
945
- * on screen to explain it.
946
- *
947
- * @param payload - the raw JSON body of a declined `POST /v0/quote`
948
- * @returns the refusal, or null when the body carries no message to read
949
- */
950
428
  const parseNearIntentsQuoteRefusal = (payload) => {
951
429
  const message = asRecord(payload)?.message;
952
430
  if (typeof message !== 'string') {
@@ -966,10 +444,6 @@ const parseNearIntentsQuoteRefusal = (payload) => {
966
444
  return { reason: 'other' };
967
445
  };
968
446
  exports.parseNearIntentsQuoteRefusal = parseNearIntentsQuoteRefusal;
969
- /**
970
- * The lifecycle states the status endpoint reports. `SUCCESS`, `REFUNDED` and
971
- * `FAILED` are terminal; the rest are still in flight.
972
- */
973
447
  const nearIntentsInFlightStatuses = [
974
448
  'KNOWN_DEPOSIT_TX',
975
449
  'PENDING_DEPOSIT',
@@ -977,15 +451,6 @@ const nearIntentsInFlightStatuses = [
977
451
  'PROCESSING',
978
452
  ];
979
453
  const isEthereumTransactionHash = (value) => typeof value === 'string' && /^0x[0-9a-fA-F]{64}$/.test(value);
980
- /**
981
- * Finds the destination-chain transaction hash, which is what hands a route
982
- * over from provider polling to the omnibridge indexer.
983
- *
984
- * The hashes arrive as records carrying a `hash` and an explorer address, and
985
- * the destination chain may not be an Ethereum one, so anything that is not a
986
- * full thirty-two-byte hash collapses to null rather than being passed on as
987
- * though it were a transaction.
988
- */
989
454
  const destinationTransactionHash = (swapDetails) => {
990
455
  const hashes = swapDetails?.destinationChainTxHashes;
991
456
  if (!Array.isArray(hashes)) {
@@ -999,25 +464,6 @@ const destinationTransactionHash = (swapDetails) => {
999
464
  }
1000
465
  return null;
1001
466
  };
1002
- /**
1003
- * Where a refund was credited, when it went into an account inside NEAR
1004
- * Intents rather than back to the origin chain.
1005
- *
1006
- * READ FROM THE PROVIDER'S OWN ECHO OF THE REQUEST. The status response carries
1007
- * the quote request it answered, so the refund's account, type and asset come
1008
- * from what the provider says it did — not from a guess on our side about
1009
- * which asset a chain's refund would be in. The amount is the provider's own
1010
- * `refundedAmount`.
1011
- *
1012
- * NULL FOR AN `ORIGIN_CHAIN` REFUND, which lands back in the reader's own
1013
- * origin wallet and needs nothing from them, and null whenever any field is
1014
- * missing: a refund step that names the wrong account or asset would send the
1015
- * reader looking in the wrong place.
1016
- *
1017
- * @param body - the whole status response
1018
- * @param swapDetails - its `swapDetails` record
1019
- * @returns the account refund, or null
1020
- */
1021
467
  const intentsAccountRefund = (body, swapDetails) => {
1022
468
  const request = asRecord(asRecord(body?.quoteResponse)?.quoteRequest);
1023
469
  if (request?.refundType !== 'INTENTS') {
@@ -1033,12 +479,6 @@ const intentsAccountRefund = (body, swapDetails) => {
1033
479
  }
1034
480
  return { account: refundTo.toLowerCase(), assetId: originAsset, baseUnits: refundedAmount };
1035
481
  };
1036
- /**
1037
- * Normalizes a `GET /v0/status` response.
1038
- *
1039
- * @param payload - the raw JSON body
1040
- * @returns the normalized status, or null when the payload names no status
1041
- */
1042
482
  const parseNearIntentsStatus = (payload) => {
1043
483
  const body = asRecord(payload);
1044
484
  const status = body?.status;
@@ -1064,8 +504,6 @@ const parseNearIntentsStatus = (payload) => {
1064
504
  if (nearIntentsInFlightStatuses.some((inFlight) => inFlight === status)) {
1065
505
  return { status: 'PENDING', substatus: status, receivingTxHash };
1066
506
  }
1067
- // An unrecognized state is treated as still settling rather than terminal, so
1068
- // a new state the service adds never reads as a completed transfer.
1069
507
  return { status: 'NOT_FOUND', substatus: status, receivingTxHash };
1070
508
  };
1071
509
  exports.parseNearIntentsStatus = parseNearIntentsStatus;