@gibs/bridge-sdk 1.13.1 → 1.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (217) hide show
  1. package/README.md +244 -18
  2. package/abis/package.json +6 -0
  3. package/bridge-limits/package.json +6 -0
  4. package/chain-info/package.json +6 -0
  5. package/chain-names/package.json +6 -0
  6. package/chains/package.json +6 -0
  7. package/claims/package.json +6 -0
  8. package/config/package.json +6 -0
  9. package/consolidated-quote/package.json +6 -0
  10. package/destination-calldata/package.json +6 -0
  11. package/dist/chain-info.d.ts +1 -1
  12. package/dist/chain-info.js +11 -12
  13. package/dist/chains.d.ts +25 -0
  14. package/dist/chains.js +55 -20
  15. package/dist/cjs/abis.d.ts +1 -0
  16. package/dist/cjs/abis.js +19 -0
  17. package/dist/cjs/bridge-limits.d.ts +103 -0
  18. package/dist/cjs/bridge-limits.js +89 -0
  19. package/dist/cjs/chain-info.d.ts +169 -0
  20. package/dist/cjs/chain-info.js +452 -0
  21. package/dist/cjs/chain-names.d.ts +160 -0
  22. package/dist/cjs/chain-names.js +207 -0
  23. package/dist/cjs/chains.d.ts +90 -0
  24. package/dist/cjs/chains.js +357 -0
  25. package/dist/cjs/claims.d.ts +198 -0
  26. package/dist/cjs/claims.js +182 -0
  27. package/dist/cjs/config.d.ts +240 -0
  28. package/dist/cjs/config.js +537 -0
  29. package/dist/cjs/consolidated-quote.d.ts +648 -0
  30. package/dist/cjs/consolidated-quote.js +1048 -0
  31. package/dist/cjs/destination-calldata.d.ts +118 -0
  32. package/dist/cjs/destination-calldata.js +156 -0
  33. package/dist/cjs/ecosystems.d.ts +217 -0
  34. package/dist/cjs/ecosystems.js +298 -0
  35. package/dist/cjs/execution.d.ts +346 -0
  36. package/dist/cjs/execution.js +468 -0
  37. package/dist/cjs/fee-type.d.ts +10 -0
  38. package/dist/cjs/fee-type.js +10 -0
  39. package/dist/cjs/hyperliquid-execution.d.ts +152 -0
  40. package/dist/cjs/hyperliquid-execution.js +175 -0
  41. package/dist/cjs/image-links.d.ts +117 -0
  42. package/dist/cjs/image-links.js +153 -0
  43. package/dist/cjs/index.d.ts +23 -0
  44. package/dist/cjs/index.js +39 -0
  45. package/dist/cjs/lifi-execution-guard.d.ts +210 -0
  46. package/dist/cjs/lifi-execution-guard.js +409 -0
  47. package/dist/cjs/near-intents-conformance.d.ts +85 -0
  48. package/dist/cjs/near-intents-conformance.js +337 -0
  49. package/dist/cjs/near-intents-route.d.ts +47 -0
  50. package/dist/cjs/near-intents-route.js +303 -0
  51. package/dist/cjs/near-intents.d.ts +524 -0
  52. package/dist/cjs/near-intents.js +1071 -0
  53. package/dist/cjs/origin-deposit.d.ts +326 -0
  54. package/dist/cjs/origin-deposit.js +82 -0
  55. package/dist/cjs/package.json +3 -0
  56. package/dist/cjs/pre-quote.d.ts +198 -0
  57. package/dist/cjs/pre-quote.js +180 -0
  58. package/dist/cjs/prices.d.ts +107 -0
  59. package/dist/cjs/prices.js +172 -0
  60. package/dist/cjs/providers.d.ts +238 -0
  61. package/dist/cjs/providers.js +171 -0
  62. package/dist/cjs/quote-fees.d.ts +102 -0
  63. package/dist/cjs/quote-fees.js +201 -0
  64. package/dist/cjs/referral.d.ts +85 -0
  65. package/dist/cjs/referral.js +85 -0
  66. package/dist/cjs/relay-currencies.d.ts +47 -0
  67. package/dist/cjs/relay-currencies.js +95 -0
  68. package/dist/cjs/relay-depository.d.ts +2 -0
  69. package/dist/cjs/relay-depository.js +85 -0
  70. package/dist/cjs/relay-quote.d.ts +301 -0
  71. package/dist/cjs/relay-quote.js +996 -0
  72. package/dist/cjs/route-steps.d.ts +138 -0
  73. package/dist/cjs/route-steps.js +310 -0
  74. package/dist/cjs/routing/amounts.d.ts +80 -0
  75. package/dist/cjs/routing/amounts.js +126 -0
  76. package/dist/cjs/routing/candidate-route.d.ts +43 -0
  77. package/dist/cjs/routing/candidate-route.js +50 -0
  78. package/dist/cjs/routing/candidate.d.ts +237 -0
  79. package/dist/cjs/routing/candidate.js +100 -0
  80. package/dist/cjs/routing/carriers/ask-answer.d.ts +77 -0
  81. package/dist/cjs/routing/carriers/ask-answer.js +2 -0
  82. package/dist/cjs/routing/carriers/omnibridge.d.ts +137 -0
  83. package/dist/cjs/routing/carriers/omnibridge.js +459 -0
  84. package/dist/cjs/routing/carriers/pulsex-paths.d.ts +80 -0
  85. package/dist/cjs/routing/carriers/pulsex-paths.js +97 -0
  86. package/dist/cjs/routing/carriers/pulsex-split.d.ts +175 -0
  87. package/dist/cjs/routing/carriers/pulsex-split.js +193 -0
  88. package/dist/cjs/routing/carriers/pulsex.d.ts +159 -0
  89. package/dist/cjs/routing/carriers/pulsex.js +565 -0
  90. package/dist/cjs/routing/carriers/wrap.d.ts +25 -0
  91. package/dist/cjs/routing/carriers/wrap.js +119 -0
  92. package/dist/cjs/routing/composed-route-quality.d.ts +125 -0
  93. package/dist/cjs/routing/composed-route-quality.js +144 -0
  94. package/dist/cjs/routing/entry-chain-anchor.d.ts +88 -0
  95. package/dist/cjs/routing/entry-chain-anchor.js +59 -0
  96. package/dist/cjs/routing/format.d.ts +31 -0
  97. package/dist/cjs/routing/format.js +64 -0
  98. package/dist/cjs/routing/index.d.ts +38 -0
  99. package/dist/cjs/routing/index.js +134 -0
  100. package/dist/cjs/routing/producers.d.ts +770 -0
  101. package/dist/cjs/routing/producers.js +1617 -0
  102. package/dist/cjs/routing/providers.d.ts +31 -0
  103. package/dist/cjs/routing/providers.js +48 -0
  104. package/dist/cjs/routing/route-data.d.ts +355 -0
  105. package/dist/cjs/routing/route-data.js +2 -0
  106. package/dist/cjs/routing/search/compose.d.ts +168 -0
  107. package/dist/cjs/routing/search/compose.js +104 -0
  108. package/dist/cjs/routing/search/graph.d.ts +668 -0
  109. package/dist/cjs/routing/search/graph.js +461 -0
  110. package/dist/cjs/routing/search/plan-route-data.d.ts +269 -0
  111. package/dist/cjs/routing/search/plan-route-data.js +848 -0
  112. package/dist/cjs/routing/search/score.d.ts +356 -0
  113. package/dist/cjs/routing/search/score.js +445 -0
  114. package/dist/cjs/routing/swap-transactions.d.ts +91 -0
  115. package/dist/cjs/routing/swap-transactions.js +131 -0
  116. package/dist/cjs/routing/usd-value.d.ts +17 -0
  117. package/dist/cjs/routing/usd-value.js +29 -0
  118. package/dist/cjs/settings.d.ts +785 -0
  119. package/dist/cjs/settings.js +1074 -0
  120. package/dist/cjs/ton-connect.d.ts +98 -0
  121. package/dist/cjs/ton-connect.js +206 -0
  122. package/dist/cjs/ton-execution.d.ts +7 -0
  123. package/dist/cjs/ton-execution.js +23 -0
  124. package/dist/cjs/ton.d.ts +37 -0
  125. package/dist/cjs/ton.js +83 -0
  126. package/dist/cjs/tron-execution.d.ts +146 -0
  127. package/dist/cjs/tron-execution.js +248 -0
  128. package/dist/cjs/types.d.ts +51 -0
  129. package/dist/cjs/types.js +2 -0
  130. package/dist/claims.d.ts +198 -0
  131. package/dist/claims.js +140 -0
  132. package/dist/config.d.ts +24 -0
  133. package/dist/config.js +39 -5
  134. package/dist/consolidated-quote.d.ts +109 -15
  135. package/dist/consolidated-quote.js +310 -52
  136. package/dist/execution.d.ts +346 -0
  137. package/dist/execution.js +428 -0
  138. package/dist/hyperliquid-execution.js +2 -3
  139. package/dist/index.d.ts +3 -0
  140. package/dist/index.js +3 -0
  141. package/dist/lifi-execution-guard.d.ts +13 -2
  142. package/dist/lifi-execution-guard.js +4 -0
  143. package/dist/near-intents.js +2 -3
  144. package/dist/pre-quote.d.ts +6 -6
  145. package/dist/pre-quote.js +10 -14
  146. package/dist/providers.d.ts +17 -0
  147. package/dist/providers.js +6 -0
  148. package/dist/referral.d.ts +12 -4
  149. package/dist/referral.js +12 -4
  150. package/dist/relay-depository.d.ts +2 -0
  151. package/dist/relay-depository.js +82 -0
  152. package/dist/relay-quote.js +2 -3
  153. package/dist/routing/candidate.d.ts +3 -3
  154. package/dist/routing/candidate.js +3 -3
  155. package/dist/routing/carriers/ask-answer.d.ts +17 -0
  156. package/dist/routing/carriers/omnibridge.js +23 -21
  157. package/dist/routing/carriers/pulsex-paths.d.ts +80 -0
  158. package/dist/routing/carriers/pulsex-paths.js +92 -0
  159. package/dist/routing/carriers/pulsex-split.d.ts +175 -0
  160. package/dist/routing/carriers/pulsex-split.js +185 -0
  161. package/dist/routing/carriers/pulsex.d.ts +31 -21
  162. package/dist/routing/carriers/pulsex.js +141 -71
  163. package/dist/routing/composed-route-quality.d.ts +28 -6
  164. package/dist/routing/composed-route-quality.js +36 -5
  165. package/dist/routing/entry-chain-anchor.d.ts +1 -1
  166. package/dist/routing/entry-chain-anchor.js +1 -1
  167. package/dist/routing/index.d.ts +6 -2
  168. package/dist/routing/index.js +6 -2
  169. package/dist/routing/producers.js +1 -1
  170. package/dist/routing/providers.d.ts +5 -0
  171. package/dist/routing/providers.js +5 -0
  172. package/dist/routing/search/graph.d.ts +15 -0
  173. package/dist/routing/search/plan-route-data.d.ts +25 -0
  174. package/dist/routing/search/plan-route-data.js +43 -7
  175. package/dist/routing/search/score.d.ts +3 -0
  176. package/dist/routing/search/score.js +11 -3
  177. package/dist/routing/swap-transactions.d.ts +91 -0
  178. package/dist/routing/swap-transactions.js +125 -0
  179. package/dist/settings.d.ts +94 -1
  180. package/dist/settings.js +95 -3
  181. package/dist/ton-connect.d.ts +98 -0
  182. package/dist/ton-connect.js +200 -0
  183. package/dist/ton-execution.d.ts +4 -114
  184. package/dist/ton-execution.js +4 -244
  185. package/dist/ton.d.ts +37 -0
  186. package/dist/ton.js +65 -0
  187. package/docs/examples/example-a-ether-to-pulse.ts +300 -0
  188. package/docs/examples/example-b-token-pulsechain-to-ethereum.ts +270 -0
  189. package/docs/examples/shared.ts +261 -0
  190. package/docs/examples/tsconfig.json +18 -0
  191. package/docs/integration-guide.md +617 -0
  192. package/ecosystems/package.json +6 -0
  193. package/execution/package.json +6 -0
  194. package/fee-type/package.json +6 -0
  195. package/hyperliquid-execution/package.json +6 -0
  196. package/image-links/package.json +6 -0
  197. package/lifi-execution-guard/package.json +6 -0
  198. package/llms.txt +75 -10
  199. package/near-intents/package.json +6 -0
  200. package/near-intents-route/package.json +6 -0
  201. package/origin-deposit/package.json +6 -0
  202. package/package.json +817 -10
  203. package/pre-quote/package.json +6 -0
  204. package/prices/package.json +6 -0
  205. package/providers/package.json +6 -0
  206. package/quote-fees/package.json +6 -0
  207. package/referral/package.json +6 -0
  208. package/relay-currencies/package.json +6 -0
  209. package/relay-quote/package.json +6 -0
  210. package/route-steps/package.json +6 -0
  211. package/routing/package.json +6 -0
  212. package/settings/package.json +6 -0
  213. package/ton/package.json +6 -0
  214. package/ton-connect/package.json +6 -0
  215. package/ton-execution/package.json +6 -0
  216. package/tron-execution/package.json +6 -0
  217. package/types/package.json +6 -0
@@ -0,0 +1,85 @@
1
+ /**
2
+ * One way a payload departs from the shape the parsers were written against.
3
+ *
4
+ * `found` is a description rather than the value itself, so a finding can be
5
+ * printed in a continuous-integration log without carrying an address, an
6
+ * amount or anything else from a real response into it.
7
+ */
8
+ export type NearIntentsShapeFinding = {
9
+ /** Where in the payload, as a dotted path from the root. */
10
+ readonly path: string;
11
+ /** What the parsers require there. */
12
+ readonly expected: string;
13
+ /** What was there instead, described rather than quoted. */
14
+ readonly found: string;
15
+ };
16
+ /**
17
+ * Checks a `POST /v0/quote` answer against everything the quote parsers read.
18
+ *
19
+ * THE DOLLAR FIGURES ARE CHECKED THOUGH THE PARSER TOLERATES THEIR ABSENCE.
20
+ * `parseNearIntentsQuote` turns a missing `amountInUsd` into null and carries
21
+ * on, which is right for a quote and wrong for a conformance check: losing the
22
+ * dollar figure leaves the reader a route with no price beside it, and nothing
23
+ * else in the system would report that the service stopped sending one.
24
+ *
25
+ * @param payload - the raw JSON body the service answered with
26
+ * @param options.expectDepositAddress - true for an executable (`dry: false`)
27
+ * answer, false for a dry one. A dry answer omits the deposit address by
28
+ * design, so requiring it there would report a finding on a healthy service
29
+ * @returns every departure from the expected shape; empty means conformant
30
+ */
31
+ export declare const nearIntentsQuoteShapeFindings: (payload: unknown, { expectDepositAddress }: {
32
+ expectDepositAddress: boolean;
33
+ }) => readonly NearIntentsShapeFinding[];
34
+ /**
35
+ * Checks a `GET /v0/tokens` answer, including the chain names we map by hand.
36
+ *
37
+ * AN UNMAPPED CHAIN NAME IS THE DRIFT MOST LIKELY TO HAPPEN AND LEAST LIKELY
38
+ * TO BE NOTICED. `chainIdByNearIntentsChain` is a hand-written table, and
39
+ * `findNearIntentsAsset` matches through it — so if the service renames a
40
+ * chain or adds one, every asset on that chain becomes invisible to this
41
+ * repository while the asset list parses perfectly and every test stays green.
42
+ * The names are reported rather than the assets, because a new chain we do not
43
+ * carry is ordinary and a renamed chain we DO carry is the emergency.
44
+ *
45
+ * @param payload - the raw JSON body from the asset endpoint
46
+ * @param options.requiredChains - the service's own names for the chains this
47
+ * repository must keep reaching. A name missing from the answer means the
48
+ * service renamed or dropped it
49
+ * @returns every departure from the expected shape; empty means conformant
50
+ */
51
+ export declare const nearIntentsTokenListShapeFindings: (payload: unknown, { requiredChains }: {
52
+ requiredChains: readonly string[];
53
+ }) => readonly NearIntentsShapeFinding[];
54
+ /**
55
+ * The service's own names for every chain this repository maps to a chain
56
+ * identifier, which is exactly the set whose renaming would be invisible.
57
+ */
58
+ export declare const nearIntentsMappedChainNames: () => readonly string[];
59
+ /**
60
+ * Checks a `GET /v0/status` answer against what the status parser reads.
61
+ *
62
+ * THE DELIVERY HASH IS NOT REQUIRED, and that is not laxity. A route awaiting
63
+ * its deposit has genuinely not produced one, and the captured
64
+ * `status-pending-deposit.json` is exactly that case — so requiring it would
65
+ * report a finding on a perfectly healthy in-flight transfer. What is required
66
+ * is that the ARRAY exists, because its absence is the difference between "no
67
+ * hash yet" and "the service stopped telling us where the funds landed".
68
+ *
69
+ * @param payload - the raw JSON body from the status endpoint
70
+ * @returns every departure from the expected shape; empty means conformant
71
+ */
72
+ export declare const nearIntentsStatusShapeFindings: (payload: unknown) => readonly NearIntentsShapeFinding[];
73
+ /**
74
+ * Checks a refusal body carries the message the refusal parser reads.
75
+ *
76
+ * BOTH SIZE FLOORS ARRIVE ONLY AS PROSE IN THIS FIELD. There is no code, no
77
+ * limits endpoint and no structured figure — `parseNearIntentsQuoteRefusal`
78
+ * runs a regular expression over the sentence. So if the wording changes, a
79
+ * refusal that should withdraw the route from the competition instead reads as
80
+ * `other`, and the reader waits for a bid that will never come.
81
+ *
82
+ * @param payload - the raw JSON body of a refused quote
83
+ * @returns every departure from the expected shape; empty means conformant
84
+ */
85
+ export declare const nearIntentsRefusalShapeFindings: (payload: unknown) => readonly NearIntentsShapeFinding[];
@@ -0,0 +1,337 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.nearIntentsRefusalShapeFindings = exports.nearIntentsStatusShapeFindings = exports.nearIntentsMappedChainNames = exports.nearIntentsTokenListShapeFindings = exports.nearIntentsQuoteShapeFindings = void 0;
4
+ /**
5
+ * Does the live service still answer in the shape this repository parses?
6
+ *
7
+ * THIS EXISTS BECAUSE NEAR INTENTS HAS NO TEST NETWORK. The vendor states it
8
+ * four times in its own current material, most plainly in its list of common
9
+ * questions: "There is no testnet deployment and no plans for one. We
10
+ * recommend testing on NEAR mainnet using separate dev/test NEAR accounts."
11
+ * So there is no safe copy of the service to check an integration against, and
12
+ * the only honest substitute is a priced request against production that
13
+ * reserves nothing — a dry quote. See `docs/near-intents-capability-survey.md`.
14
+ *
15
+ * WHAT THIS CLOSES THAT THE FIXTURES CANNOT. `near-intents.test.ts` runs
16
+ * against real captures taken on 2026-09-17. A capture is a photograph: it
17
+ * proves the parser reads what the service sent that day, and it goes on
18
+ * proving that forever, including after the service stops sending it. Every
19
+ * parser here is tolerant by design — it returns null rather than throwing —
20
+ * so a field that changes type does not break a test, it removes a provider
21
+ * from the interface with no message anywhere. `amountOut` arriving as a
22
+ * number instead of a string is the whole failure: 37 green tests, and NEAR
23
+ * Intents silently never bids again.
24
+ *
25
+ * So these functions name every field the parsers actually depend on and
26
+ * report what is missing, rather than returning a normalized value. Handed a
27
+ * live response they answer "has production drifted away from the captures".
28
+ * Handed a capture they answer "is this capture still a fair stand-in".
29
+ *
30
+ * They are deliberately NOT parsers. A parser answers "can I use this"; these
31
+ * answer "is this what I was written against", which is a different question
32
+ * and needs the failures enumerated rather than collapsed into a null.
33
+ */
34
+ const near_intents_js_1 = require("./near-intents.js");
35
+ /** Which parser depends on a field, so a finding says what will break. */
36
+ const describe = (value) => {
37
+ if (value === undefined) {
38
+ return 'absent';
39
+ }
40
+ if (value === null) {
41
+ return 'null';
42
+ }
43
+ if (Array.isArray(value)) {
44
+ return `array of ${value.length}`;
45
+ }
46
+ return typeof value;
47
+ };
48
+ const asRecord = (value) => typeof value === 'object' && value !== null && !Array.isArray(value)
49
+ ? value
50
+ : null;
51
+ /**
52
+ * Checks one field and returns a finding when it is not the required type.
53
+ *
54
+ * A base-unit amount must be a NON-EMPTY string, because that is what
55
+ * `parseAmount` in `near-intents.ts` requires: it refuses an empty string and
56
+ * refuses a number, so either one silently collapses the whole quote to null.
57
+ */
58
+ const requireField = ({ container, key, path, kind, }) => {
59
+ const value = container[key];
60
+ if (kind === 'amount') {
61
+ if (typeof value === 'string' && value !== '') {
62
+ return null;
63
+ }
64
+ return { path, expected: 'a non-empty string of base units', found: describe(value) };
65
+ }
66
+ if (kind === 'number') {
67
+ return typeof value === 'number'
68
+ ? null
69
+ : { path, expected: 'a number', found: describe(value) };
70
+ }
71
+ if (kind === 'array') {
72
+ return Array.isArray(value) ? null : { path, expected: 'an array', found: describe(value) };
73
+ }
74
+ return typeof value === 'string' && value !== ''
75
+ ? null
76
+ : { path, expected: 'a non-empty string', found: describe(value) };
77
+ };
78
+ const compact = (findings) => findings.filter((finding) => finding !== null);
79
+ /**
80
+ * Checks a `POST /v0/quote` answer against everything the quote parsers read.
81
+ *
82
+ * THE DOLLAR FIGURES ARE CHECKED THOUGH THE PARSER TOLERATES THEIR ABSENCE.
83
+ * `parseNearIntentsQuote` turns a missing `amountInUsd` into null and carries
84
+ * on, which is right for a quote and wrong for a conformance check: losing the
85
+ * dollar figure leaves the reader a route with no price beside it, and nothing
86
+ * else in the system would report that the service stopped sending one.
87
+ *
88
+ * @param payload - the raw JSON body the service answered with
89
+ * @param options.expectDepositAddress - true for an executable (`dry: false`)
90
+ * answer, false for a dry one. A dry answer omits the deposit address by
91
+ * design, so requiring it there would report a finding on a healthy service
92
+ * @returns every departure from the expected shape; empty means conformant
93
+ */
94
+ const nearIntentsQuoteShapeFindings = (payload, { expectDepositAddress }) => {
95
+ const body = asRecord(payload);
96
+ if (!body) {
97
+ return [{ path: '', expected: 'an object', found: describe(payload) }];
98
+ }
99
+ const quote = asRecord(body.quote);
100
+ if (!quote) {
101
+ return [{ path: 'quote', expected: 'an object', found: describe(body.quote) }];
102
+ }
103
+ const findings = compact([
104
+ requireField({ container: quote, key: 'amountIn', path: 'quote.amountIn', kind: 'amount' }),
105
+ requireField({ container: quote, key: 'amountOut', path: 'quote.amountOut', kind: 'amount' }),
106
+ requireField({
107
+ container: quote,
108
+ key: 'minAmountOut',
109
+ path: 'quote.minAmountOut',
110
+ kind: 'amount',
111
+ }),
112
+ requireField({
113
+ container: quote,
114
+ key: 'withdrawFee',
115
+ path: 'quote.withdrawFee',
116
+ kind: 'amount',
117
+ }),
118
+ requireField({
119
+ container: quote,
120
+ key: 'timeEstimate',
121
+ path: 'quote.timeEstimate',
122
+ kind: 'number',
123
+ }),
124
+ requireField({
125
+ container: quote,
126
+ key: 'amountInUsd',
127
+ path: 'quote.amountInUsd',
128
+ kind: 'string',
129
+ }),
130
+ requireField({
131
+ container: quote,
132
+ key: 'amountOutUsd',
133
+ path: 'quote.amountOutUsd',
134
+ kind: 'string',
135
+ }),
136
+ expectDepositAddress
137
+ ? requireField({
138
+ container: quote,
139
+ key: 'depositAddress',
140
+ path: 'quote.depositAddress',
141
+ kind: 'string',
142
+ })
143
+ : null,
144
+ ]);
145
+ return [...findings, ...nearIntentsAppFeeFindings(body.quoteRequest)];
146
+ };
147
+ exports.nearIntentsQuoteShapeFindings = nearIntentsQuoteShapeFindings;
148
+ /**
149
+ * Checks the echoed request for the surcharge a key-less caller is charged.
150
+ *
151
+ * THE SERVICE INSERTS THIS, NOT US. Nothing in this repository asks for an
152
+ * `appFees` entry, and the fee parser only finds the twenty-five-basis-point
153
+ * charge because the service writes it into the request it echoes back. If it
154
+ * ever stops echoing it, the charge does not stop — it disappears from the
155
+ * fee rows and the reader is shown a route that costs a quarter of a percent
156
+ * more than the interface says. That is a silent understatement of cost, so it
157
+ * is a finding rather than a tolerated absence.
158
+ */
159
+ const nearIntentsAppFeeFindings = (quoteRequest) => {
160
+ const request = asRecord(quoteRequest);
161
+ if (!request) {
162
+ return [
163
+ { path: 'quoteRequest', expected: 'an object', found: describe(quoteRequest) },
164
+ ];
165
+ }
166
+ const appFees = request.appFees;
167
+ if (!Array.isArray(appFees)) {
168
+ return [{ path: 'quoteRequest.appFees', expected: 'an array', found: describe(appFees) }];
169
+ }
170
+ if (appFees.length === 0) {
171
+ return [
172
+ {
173
+ path: 'quoteRequest.appFees',
174
+ expected: 'at least one entry, the surcharge the service adds to a key-less request',
175
+ found: 'array of 0',
176
+ },
177
+ ];
178
+ }
179
+ return compact(appFees.map((entry, index) => {
180
+ const record = asRecord(entry);
181
+ if (!record) {
182
+ return {
183
+ path: `quoteRequest.appFees[${index}]`,
184
+ expected: 'an object',
185
+ found: describe(entry),
186
+ };
187
+ }
188
+ return requireField({
189
+ container: record,
190
+ key: 'fee',
191
+ path: `quoteRequest.appFees[${index}].fee`,
192
+ kind: 'number',
193
+ });
194
+ }));
195
+ };
196
+ /**
197
+ * Checks a `GET /v0/tokens` answer, including the chain names we map by hand.
198
+ *
199
+ * AN UNMAPPED CHAIN NAME IS THE DRIFT MOST LIKELY TO HAPPEN AND LEAST LIKELY
200
+ * TO BE NOTICED. `chainIdByNearIntentsChain` is a hand-written table, and
201
+ * `findNearIntentsAsset` matches through it — so if the service renames a
202
+ * chain or adds one, every asset on that chain becomes invisible to this
203
+ * repository while the asset list parses perfectly and every test stays green.
204
+ * The names are reported rather than the assets, because a new chain we do not
205
+ * carry is ordinary and a renamed chain we DO carry is the emergency.
206
+ *
207
+ * @param payload - the raw JSON body from the asset endpoint
208
+ * @param options.requiredChains - the service's own names for the chains this
209
+ * repository must keep reaching. A name missing from the answer means the
210
+ * service renamed or dropped it
211
+ * @returns every departure from the expected shape; empty means conformant
212
+ */
213
+ const nearIntentsTokenListShapeFindings = (payload, { requiredChains }) => {
214
+ if (!Array.isArray(payload)) {
215
+ return [{ path: '', expected: 'an array of assets', found: describe(payload) }];
216
+ }
217
+ if (payload.length === 0) {
218
+ return [{ path: '', expected: 'at least one asset', found: 'array of 0' }];
219
+ }
220
+ const findings = [];
221
+ const chainsSeen = new Set();
222
+ payload.forEach((entry, index) => {
223
+ const record = asRecord(entry);
224
+ if (!record) {
225
+ findings.push({ path: `[${index}]`, expected: 'an object', found: describe(entry) });
226
+ return;
227
+ }
228
+ const blockchain = record.blockchain;
229
+ if (typeof blockchain === 'string') {
230
+ chainsSeen.add(blockchain);
231
+ }
232
+ findings.push(...compact([
233
+ requireField({
234
+ container: record,
235
+ key: 'assetId',
236
+ path: `[${index}].assetId`,
237
+ kind: 'string',
238
+ }),
239
+ requireField({
240
+ container: record,
241
+ key: 'blockchain',
242
+ path: `[${index}].blockchain`,
243
+ kind: 'string',
244
+ }),
245
+ requireField({ container: record, key: 'symbol', path: `[${index}].symbol`, kind: 'string' }),
246
+ requireField({
247
+ container: record,
248
+ key: 'decimals',
249
+ path: `[${index}].decimals`,
250
+ kind: 'number',
251
+ }),
252
+ ]));
253
+ });
254
+ for (const chain of requiredChains) {
255
+ if (chainsSeen.has(chain)) {
256
+ continue;
257
+ }
258
+ findings.push({
259
+ path: `chain "${chain}"`,
260
+ expected: 'present in the asset list, because chainIdByNearIntentsChain maps it',
261
+ found: 'absent — the service renamed or dropped it',
262
+ });
263
+ }
264
+ return findings;
265
+ };
266
+ exports.nearIntentsTokenListShapeFindings = nearIntentsTokenListShapeFindings;
267
+ /**
268
+ * The service's own names for every chain this repository maps to a chain
269
+ * identifier, which is exactly the set whose renaming would be invisible.
270
+ */
271
+ const nearIntentsMappedChainNames = () => [
272
+ ...near_intents_js_1.chainIdByNearIntentsChain.keys(),
273
+ ];
274
+ exports.nearIntentsMappedChainNames = nearIntentsMappedChainNames;
275
+ /**
276
+ * Checks a `GET /v0/status` answer against what the status parser reads.
277
+ *
278
+ * THE DELIVERY HASH IS NOT REQUIRED, and that is not laxity. A route awaiting
279
+ * its deposit has genuinely not produced one, and the captured
280
+ * `status-pending-deposit.json` is exactly that case — so requiring it would
281
+ * report a finding on a perfectly healthy in-flight transfer. What is required
282
+ * is that the ARRAY exists, because its absence is the difference between "no
283
+ * hash yet" and "the service stopped telling us where the funds landed".
284
+ *
285
+ * @param payload - the raw JSON body from the status endpoint
286
+ * @returns every departure from the expected shape; empty means conformant
287
+ */
288
+ const nearIntentsStatusShapeFindings = (payload) => {
289
+ const body = asRecord(payload);
290
+ if (!body) {
291
+ return [{ path: '', expected: 'an object', found: describe(payload) }];
292
+ }
293
+ const findings = compact([
294
+ requireField({ container: body, key: 'status', path: 'status', kind: 'string' }),
295
+ ]);
296
+ const swapDetails = asRecord(body.swapDetails);
297
+ if (!swapDetails) {
298
+ return [
299
+ ...findings,
300
+ { path: 'swapDetails', expected: 'an object', found: describe(body.swapDetails) },
301
+ ];
302
+ }
303
+ return [
304
+ ...findings,
305
+ ...compact([
306
+ requireField({
307
+ container: swapDetails,
308
+ key: 'destinationChainTxHashes',
309
+ path: 'swapDetails.destinationChainTxHashes',
310
+ kind: 'array',
311
+ }),
312
+ ]),
313
+ ];
314
+ };
315
+ exports.nearIntentsStatusShapeFindings = nearIntentsStatusShapeFindings;
316
+ /**
317
+ * Checks a refusal body carries the message the refusal parser reads.
318
+ *
319
+ * BOTH SIZE FLOORS ARRIVE ONLY AS PROSE IN THIS FIELD. There is no code, no
320
+ * limits endpoint and no structured figure — `parseNearIntentsQuoteRefusal`
321
+ * runs a regular expression over the sentence. So if the wording changes, a
322
+ * refusal that should withdraw the route from the competition instead reads as
323
+ * `other`, and the reader waits for a bid that will never come.
324
+ *
325
+ * @param payload - the raw JSON body of a refused quote
326
+ * @returns every departure from the expected shape; empty means conformant
327
+ */
328
+ const nearIntentsRefusalShapeFindings = (payload) => {
329
+ const body = asRecord(payload);
330
+ if (!body) {
331
+ return [{ path: '', expected: 'an object', found: describe(payload) }];
332
+ }
333
+ return compact([
334
+ requireField({ container: body, key: 'message', path: 'message', kind: 'string' }),
335
+ ]);
336
+ };
337
+ exports.nearIntentsRefusalShapeFindings = nearIntentsRefusalShapeFindings;
@@ -0,0 +1,47 @@
1
+ import type { DeferredCrossing, RouteCandidate } from './routing/candidate.js';
2
+ import type { RouteData } from './routing/route-data.js';
3
+ /**
4
+ * Builds the two-signature route for a candidate whose aggregator cannot
5
+ * execute the omnibridge entry call.
6
+ *
7
+ * The result has exactly two sections, and the order carries the meaning:
8
+ *
9
+ * 1. The aggregator's leg, signed NOW. It ends with the anchor token sitting
10
+ * in the reader's own wallet on the entry chain.
11
+ * 2. The omnibridge crossing, marked `deferred`, signed LATER by the reader.
12
+ *
13
+ * COSTS ARE SPLIT BETWEEN THE SECTIONS RATHER THAN POOLED, because a reader
14
+ * deciding whether to accept a second signature needs to know what each half
15
+ * costs. The first section's spread is the difference between the aggregator's
16
+ * own paid and delivered figures — both from the one answer that priced them,
17
+ * never from two feeds. The second section's cost is the omnibridge crossing
18
+ * fee, computed from the known on-chain rate.
19
+ *
20
+ * THE DELIVERED FIGURE IS AN ESTIMATE AND THE INTERFACE KNOWS IT. A route whose
21
+ * last section is deferred has not been quoted end to end, so
22
+ * `outputAmountIsUnsettled` blanks the received-amount field on the reader's
23
+ * behalf. The figure is still carried — the conversion route sets its estimate
24
+ * the same way — so the route can be ranked and compared.
25
+ *
26
+ * @param candidate - the route candidate, which must carry a `deferredCrossing`
27
+ * @returns the two-section route, or null when the candidate names no deferred
28
+ * crossing or no omnibridge provider to perform it
29
+ */
30
+ export declare const buildNearIntentsTwoStepRouteData: (candidate: RouteCandidate) => RouteData | null;
31
+ /**
32
+ * Describes the anchor a two-signature route leaves the reader holding.
33
+ *
34
+ * A small constructor rather than an inline object literal at the call site,
35
+ * so the three fields are named and documented in one place and a caller
36
+ * cannot quietly pair one aggregator's amount with another's valuation.
37
+ *
38
+ * @param options.anchorToken - the entry-chain token the aggregator delivers
39
+ * @param options.anchorAmount - how much of it lands, in its base units
40
+ * @param options.anchorUsdValue - the AGGREGATOR'S own valuation of that landing
41
+ * @returns the deferred-crossing record, or null when no amount is known
42
+ */
43
+ export declare const describeDeferredCrossing: ({ anchorToken, anchorAmount, anchorUsdValue, }: {
44
+ anchorToken: DeferredCrossing["anchorToken"] | null;
45
+ anchorAmount: bigint | null | undefined;
46
+ anchorUsdValue: string | null | undefined;
47
+ }) => DeferredCrossing | null;