tapimo 0.5.2 → 0.6.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 (299) hide show
  1. package/dist/App.d.ts +13987 -5755
  2. package/dist/App.d.ts.map +1 -1
  3. package/dist/App.js.map +1 -1
  4. package/dist/admin/App.d.ts +910 -412
  5. package/dist/admin/App.d.ts.map +1 -1
  6. package/dist/admin/App.js +4 -0
  7. package/dist/admin/App.js.map +1 -1
  8. package/dist/admin/apps/early-access.d.ts +148 -0
  9. package/dist/admin/apps/early-access.d.ts.map +1 -0
  10. package/dist/admin/apps/early-access.js +133 -0
  11. package/dist/admin/apps/early-access.js.map +1 -0
  12. package/dist/admin/apps/verified-tokens.d.ts +643 -118
  13. package/dist/admin/apps/verified-tokens.d.ts.map +1 -1
  14. package/dist/admin/apps/verified-tokens.js +214 -1
  15. package/dist/admin/apps/verified-tokens.js.map +1 -1
  16. package/dist/admin/ui.generated.d.ts +1 -1
  17. package/dist/admin/ui.generated.d.ts.map +1 -1
  18. package/dist/admin/ui.generated.js +45 -33
  19. package/dist/admin/ui.generated.js.map +1 -1
  20. package/dist/apps/data/App.d.ts +3733 -2428
  21. package/dist/apps/data/App.d.ts.map +1 -1
  22. package/dist/apps/data/App.js +11 -6
  23. package/dist/apps/data/App.js.map +1 -1
  24. package/dist/apps/data/FundingQuoteProviders.d.ts +34 -1
  25. package/dist/apps/data/FundingQuoteProviders.d.ts.map +1 -1
  26. package/dist/apps/data/FundingQuoteProviders.js +193 -2
  27. package/dist/apps/data/FundingQuoteProviders.js.map +1 -1
  28. package/dist/apps/data/FxOracle.d.ts +71 -0
  29. package/dist/apps/data/FxOracle.d.ts.map +1 -0
  30. package/dist/apps/data/FxOracle.js +97 -0
  31. package/dist/apps/data/FxOracle.js.map +1 -0
  32. package/dist/apps/data/index.d.ts +1 -0
  33. package/dist/apps/data/index.d.ts.map +1 -1
  34. package/dist/apps/data/index.js +1 -0
  35. package/dist/apps/data/index.js.map +1 -1
  36. package/dist/apps/data/routes/activities.d.ts +3575 -1358
  37. package/dist/apps/data/routes/activities.d.ts.map +1 -1
  38. package/dist/apps/data/routes/activities.js +230 -88
  39. package/dist/apps/data/routes/activities.js.map +1 -1
  40. package/dist/apps/data/routes/addresses.d.ts +963 -342
  41. package/dist/apps/data/routes/addresses.d.ts.map +1 -1
  42. package/dist/apps/data/routes/addresses.js +11 -9
  43. package/dist/apps/data/routes/addresses.js.map +1 -1
  44. package/dist/apps/data/routes/balances.d.ts +108 -57
  45. package/dist/apps/data/routes/balances.d.ts.map +1 -1
  46. package/dist/apps/data/routes/balances.js +88 -45
  47. package/dist/apps/data/routes/balances.js.map +1 -1
  48. package/dist/apps/data/routes/coingecko.d.ts +169 -169
  49. package/dist/apps/data/routes/exchanges.d.ts +952 -201
  50. package/dist/apps/data/routes/exchanges.d.ts.map +1 -1
  51. package/dist/apps/data/routes/exchanges.js +518 -76
  52. package/dist/apps/data/routes/exchanges.js.map +1 -1
  53. package/dist/apps/data/routes/fee-amm.d.ts +24 -24
  54. package/dist/apps/data/routes/funding.d.ts +8 -2
  55. package/dist/apps/data/routes/funding.d.ts.map +1 -1
  56. package/dist/apps/data/routes/funding.js +32 -6
  57. package/dist/apps/data/routes/funding.js.map +1 -1
  58. package/dist/apps/data/routes/indexer.d.ts +5 -5
  59. package/dist/apps/data/routes/receipts.d.ts +392 -315
  60. package/dist/apps/data/routes/receipts.d.ts.map +1 -1
  61. package/dist/apps/data/routes/receipts.js +152 -77
  62. package/dist/apps/data/routes/receipts.js.map +1 -1
  63. package/dist/apps/data/routes/tokens.d.ts +166 -173
  64. package/dist/apps/data/routes/tokens.d.ts.map +1 -1
  65. package/dist/apps/data/routes/tokens.js +14 -12
  66. package/dist/apps/data/routes/tokens.js.map +1 -1
  67. package/dist/apps/data/routes/transactions.d.ts +277 -536
  68. package/dist/apps/data/routes/transactions.d.ts.map +1 -1
  69. package/dist/apps/data/routes/transactions.js +96 -77
  70. package/dist/apps/data/routes/transactions.js.map +1 -1
  71. package/dist/apps/data/routes/transfers.d.ts +82 -17
  72. package/dist/apps/data/routes/transfers.d.ts.map +1 -1
  73. package/dist/apps/data/routes/transfers.js +70 -13
  74. package/dist/apps/data/routes/transfers.js.map +1 -1
  75. package/dist/apps/data/routes/valuation.d.ts +307 -0
  76. package/dist/apps/data/routes/valuation.d.ts.map +1 -0
  77. package/dist/apps/data/routes/valuation.js +292 -0
  78. package/dist/apps/data/routes/valuation.js.map +1 -0
  79. package/dist/apps/data/routes/verified-tokens.d.ts.map +1 -1
  80. package/dist/apps/data/routes/verified-tokens.js +7 -5
  81. package/dist/apps/data/routes/verified-tokens.js.map +1 -1
  82. package/dist/apps/data/routes/webhooks.d.ts +459 -479
  83. package/dist/apps/data/routes/webhooks.d.ts.map +1 -1
  84. package/dist/apps/data/routes/webhooks.js +124 -25
  85. package/dist/apps/data/routes/webhooks.js.map +1 -1
  86. package/dist/apps/index.d.ts +1 -1
  87. package/dist/apps/index.d.ts.map +1 -1
  88. package/dist/apps/index.js +1 -1
  89. package/dist/apps/index.js.map +1 -1
  90. package/dist/apps/management/App.d.ts +8606 -1681
  91. package/dist/apps/management/App.d.ts.map +1 -1
  92. package/dist/apps/management/App.js +12 -1
  93. package/dist/apps/management/App.js.map +1 -1
  94. package/dist/apps/management/routes/api-keys.d.ts +23 -0
  95. package/dist/apps/management/routes/api-keys.d.ts.map +1 -1
  96. package/dist/apps/management/routes/api-keys.js +5 -3
  97. package/dist/apps/management/routes/api-keys.js.map +1 -1
  98. package/dist/apps/management/routes/billing.d.ts +88 -48
  99. package/dist/apps/management/routes/billing.d.ts.map +1 -1
  100. package/dist/apps/management/routes/billing.js +10 -2
  101. package/dist/apps/management/routes/billing.js.map +1 -1
  102. package/dist/apps/management/routes/faucet.d.ts +218 -0
  103. package/dist/apps/management/routes/faucet.d.ts.map +1 -0
  104. package/dist/apps/management/routes/faucet.js +139 -0
  105. package/dist/apps/management/routes/faucet.js.map +1 -0
  106. package/dist/apps/management/routes/invitations.d.ts +121 -121
  107. package/dist/apps/management/routes/invitations.d.ts.map +1 -1
  108. package/dist/apps/management/routes/invitations.js +3 -0
  109. package/dist/apps/management/routes/invitations.js.map +1 -1
  110. package/dist/apps/management/routes/invite-links.d.ts +197 -168
  111. package/dist/apps/management/routes/invite-links.d.ts.map +1 -1
  112. package/dist/apps/management/routes/invite-links.js +26 -1
  113. package/dist/apps/management/routes/invite-links.js.map +1 -1
  114. package/dist/apps/management/routes/me.d.ts +2 -0
  115. package/dist/apps/management/routes/me.d.ts.map +1 -1
  116. package/dist/apps/management/routes/me.js +4 -0
  117. package/dist/apps/management/routes/me.js.map +1 -1
  118. package/dist/apps/management/routes/members.d.ts +49 -49
  119. package/dist/apps/management/routes/orgs.d.ts +91 -91
  120. package/dist/apps/management/routes/projects.d.ts +115 -115
  121. package/dist/apps/management/routes/usage.d.ts +35 -32
  122. package/dist/apps/management/routes/usage.d.ts.map +1 -1
  123. package/dist/apps/management/routes/usage.js +4 -0
  124. package/dist/apps/management/routes/usage.js.map +1 -1
  125. package/dist/apps/management/routes/verified-token-requests.d.ts +697 -0
  126. package/dist/apps/management/routes/verified-token-requests.d.ts.map +1 -0
  127. package/dist/apps/management/routes/verified-token-requests.js +271 -0
  128. package/dist/apps/management/routes/verified-token-requests.js.map +1 -0
  129. package/dist/apps/management/routes/webhooks.d.ts +6977 -0
  130. package/dist/apps/management/routes/webhooks.d.ts.map +1 -0
  131. package/dist/apps/management/routes/webhooks.js +573 -0
  132. package/dist/apps/management/routes/webhooks.js.map +1 -0
  133. package/dist/apps/mcp.d.ts +9 -2
  134. package/dist/apps/mcp.d.ts.map +1 -1
  135. package/dist/apps/mcp.js +9 -4
  136. package/dist/apps/mcp.js.map +1 -1
  137. package/dist/cli/Cli.d.ts.map +1 -1
  138. package/dist/cli/Cli.js +7 -2
  139. package/dist/cli/Cli.js.map +1 -1
  140. package/dist/db/Db.d.ts +4 -0
  141. package/dist/db/Db.d.ts.map +1 -1
  142. package/dist/db/Db.js +83 -0
  143. package/dist/db/Db.js.map +1 -1
  144. package/dist/db/Schema.d.ts +41 -0
  145. package/dist/db/Schema.d.ts.map +1 -1
  146. package/dist/db/Schema.js +45 -0
  147. package/dist/db/Schema.js.map +1 -1
  148. package/dist/db/tables/earlyAccess.d.ts +50 -0
  149. package/dist/db/tables/earlyAccess.d.ts.map +1 -0
  150. package/dist/db/tables/earlyAccess.js +63 -0
  151. package/dist/db/tables/earlyAccess.js.map +1 -0
  152. package/dist/db/tables/invitations.d.ts +12 -1
  153. package/dist/db/tables/invitations.d.ts.map +1 -1
  154. package/dist/db/tables/invitations.js +23 -0
  155. package/dist/db/tables/invitations.js.map +1 -1
  156. package/dist/db/tables/inviteLinks.d.ts +10 -2
  157. package/dist/db/tables/inviteLinks.d.ts.map +1 -1
  158. package/dist/db/tables/inviteLinks.js +10 -1
  159. package/dist/db/tables/inviteLinks.js.map +1 -1
  160. package/dist/db/tables/sponsoredTransactions.d.ts +2 -0
  161. package/dist/db/tables/sponsoredTransactions.d.ts.map +1 -1
  162. package/dist/db/tables/sponsoredTransactions.js +2 -0
  163. package/dist/db/tables/sponsoredTransactions.js.map +1 -1
  164. package/dist/db/tables/verifiedTokenRequests.d.ts +94 -0
  165. package/dist/db/tables/verifiedTokenRequests.d.ts.map +1 -0
  166. package/dist/db/tables/verifiedTokenRequests.js +120 -0
  167. package/dist/db/tables/verifiedTokenRequests.js.map +1 -0
  168. package/dist/db/tables/webhookSubscriptions.d.ts +14 -0
  169. package/dist/db/tables/webhookSubscriptions.d.ts.map +1 -1
  170. package/dist/db/tables/webhookSubscriptions.js +16 -0
  171. package/dist/db/tables/webhookSubscriptions.js.map +1 -1
  172. package/dist/internal/Auth.d.ts +43 -2
  173. package/dist/internal/Auth.d.ts.map +1 -1
  174. package/dist/internal/Auth.js +60 -45
  175. package/dist/internal/Auth.js.map +1 -1
  176. package/dist/internal/FundingQuotes.d.ts +69 -15
  177. package/dist/internal/FundingQuotes.d.ts.map +1 -1
  178. package/dist/internal/FundingQuotes.js +74 -25
  179. package/dist/internal/FundingQuotes.js.map +1 -1
  180. package/dist/internal/Log.d.ts +19 -1
  181. package/dist/internal/Log.d.ts.map +1 -1
  182. package/dist/internal/Log.js +2 -0
  183. package/dist/internal/Log.js.map +1 -1
  184. package/dist/internal/MetricSink.d.ts.map +1 -1
  185. package/dist/internal/MetricSink.js +9 -0
  186. package/dist/internal/MetricSink.js.map +1 -1
  187. package/dist/internal/OpenApi.d.ts +2 -2
  188. package/dist/internal/OpenApi.d.ts.map +1 -1
  189. package/dist/internal/OpenApi.js +3 -0
  190. package/dist/internal/OpenApi.js.map +1 -1
  191. package/dist/internal/Schema.d.ts +14 -5
  192. package/dist/internal/Schema.d.ts.map +1 -1
  193. package/dist/internal/Schema.js +23 -5
  194. package/dist/internal/Schema.js.map +1 -1
  195. package/dist/internal/Value.d.ts +18 -0
  196. package/dist/internal/Value.d.ts.map +1 -1
  197. package/dist/internal/Value.js +11 -1
  198. package/dist/internal/Value.js.map +1 -1
  199. package/dist/internal/VerifiedTokens.d.ts.map +1 -1
  200. package/dist/internal/VerifiedTokens.js +10 -1
  201. package/dist/internal/VerifiedTokens.js.map +1 -1
  202. package/dist/internal/Viem.d.ts +1 -1
  203. package/dist/internal/Webhooks.d.ts +24 -3
  204. package/dist/internal/Webhooks.d.ts.map +1 -1
  205. package/dist/internal/Webhooks.js +34 -8
  206. package/dist/internal/Webhooks.js.map +1 -1
  207. package/package.json +2 -2
  208. package/src/App.ts +9 -1
  209. package/src/Client.test-d.ts +638 -6
  210. package/src/admin/App.ts +4 -0
  211. package/src/admin/apps/early-access.test.ts +125 -0
  212. package/src/admin/apps/early-access.ts +175 -0
  213. package/src/admin/apps/verified-tokens.test.ts +201 -0
  214. package/src/admin/apps/verified-tokens.ts +532 -286
  215. package/src/admin/ui/plugin.ts +2 -1
  216. package/src/admin/ui/src/lib/early-access.ts +63 -0
  217. package/src/admin/ui/src/lib/verified-tokens.ts +79 -0
  218. package/src/admin/ui/src/routeTree.gen.ts +33 -2
  219. package/src/admin/ui/src/routes/__root.tsx +2 -1
  220. package/src/admin/ui/src/routes/early-access.tsx +157 -0
  221. package/src/admin/ui/src/routes/verified-tokens.tsx +230 -19
  222. package/src/admin/ui.generated.ts +48 -33
  223. package/src/apps/data/App.ts +22 -14
  224. package/src/apps/data/FundingQuoteProviders.test.ts +298 -0
  225. package/src/apps/data/FundingQuoteProviders.ts +257 -4
  226. package/src/apps/data/FxOracle.test.ts +118 -0
  227. package/src/apps/data/FxOracle.ts +153 -0
  228. package/src/apps/data/index.ts +1 -0
  229. package/src/apps/data/routes/activities.test.ts +173 -3
  230. package/src/apps/data/routes/activities.ts +403 -132
  231. package/src/apps/data/routes/addresses.ts +19 -9
  232. package/src/apps/data/routes/balances.test.ts +144 -11
  233. package/src/apps/data/routes/balances.ts +140 -51
  234. package/src/apps/data/routes/exchanges.test.ts +540 -9
  235. package/src/apps/data/routes/exchanges.ts +690 -103
  236. package/src/apps/data/routes/funding.test.ts +84 -0
  237. package/src/apps/data/routes/funding.ts +38 -6
  238. package/src/apps/data/routes/receipts.test.ts +125 -23
  239. package/src/apps/data/routes/receipts.ts +205 -100
  240. package/src/apps/data/routes/tokens.test.ts +43 -0
  241. package/src/apps/data/routes/tokens.ts +27 -12
  242. package/src/apps/data/routes/transactions.test.ts +72 -19
  243. package/src/apps/data/routes/transactions.ts +162 -92
  244. package/src/apps/data/routes/transfers.test.ts +146 -4
  245. package/src/apps/data/routes/transfers.ts +91 -13
  246. package/src/apps/data/routes/valuation.test.ts +422 -0
  247. package/src/apps/data/routes/valuation.ts +423 -0
  248. package/src/apps/data/routes/verified-tokens.ts +14 -2
  249. package/src/apps/data/routes/webhooks.test.ts +56 -8
  250. package/src/apps/data/routes/webhooks.ts +144 -27
  251. package/src/apps/index.ts +1 -1
  252. package/src/apps/management/App.ts +13 -0
  253. package/src/apps/management/routes/api-keys.test.ts +87 -0
  254. package/src/apps/management/routes/api-keys.ts +4 -3
  255. package/src/apps/management/routes/billing.test.ts +112 -1
  256. package/src/apps/management/routes/billing.ts +7 -2
  257. package/src/apps/management/routes/faucet.test.ts +79 -0
  258. package/src/apps/management/routes/faucet.ts +185 -0
  259. package/src/apps/management/routes/invitations.test.ts +172 -0
  260. package/src/apps/management/routes/invitations.ts +3 -0
  261. package/src/apps/management/routes/invite-links.test.ts +117 -0
  262. package/src/apps/management/routes/invite-links.ts +43 -1
  263. package/src/apps/management/routes/me.test.ts +140 -88
  264. package/src/apps/management/routes/me.ts +6 -0
  265. package/src/apps/management/routes/usage.test.ts +6 -0
  266. package/src/apps/management/routes/usage.ts +7 -0
  267. package/src/apps/management/routes/verified-token-requests.test.ts +377 -0
  268. package/src/apps/management/routes/verified-token-requests.ts +397 -0
  269. package/src/apps/management/routes/webhooks.test.ts +426 -0
  270. package/src/apps/management/routes/webhooks.ts +672 -0
  271. package/src/apps/mcp.test.ts +13 -0
  272. package/src/apps/mcp.ts +18 -5
  273. package/src/cli/Cli.test.ts +36 -0
  274. package/src/cli/Cli.ts +7 -2
  275. package/src/db/Db.test.ts +19 -0
  276. package/src/db/Db.ts +95 -0
  277. package/src/db/Schema.ts +53 -0
  278. package/src/db/tables/earlyAccess.ts +86 -0
  279. package/src/db/tables/invitations.ts +26 -1
  280. package/src/db/tables/inviteLinks.ts +22 -3
  281. package/src/db/tables/sponsoredTransactions.ts +4 -0
  282. package/src/db/tables/verifiedTokenRequests.test.ts +200 -0
  283. package/src/db/tables/verifiedTokenRequests.ts +182 -0
  284. package/src/db/tables/webhookSubscriptions.ts +31 -0
  285. package/src/internal/Auth.ts +73 -45
  286. package/src/internal/FundingQuotes.test.ts +143 -1
  287. package/src/internal/FundingQuotes.ts +95 -28
  288. package/src/internal/Log.test-d.ts +21 -0
  289. package/src/internal/Log.test.ts +50 -0
  290. package/src/internal/Log.ts +24 -1
  291. package/src/internal/MetricSink.test.ts +160 -0
  292. package/src/internal/MetricSink.ts +10 -0
  293. package/src/internal/OpenApi.ts +3 -0
  294. package/src/internal/Schema.ts +50 -5
  295. package/src/internal/Value.test.ts +20 -0
  296. package/src/internal/Value.ts +24 -1
  297. package/src/internal/VerifiedTokens.ts +9 -1
  298. package/src/internal/Webhooks.test.ts +140 -0
  299. package/src/internal/Webhooks.ts +53 -9
@@ -14,6 +14,7 @@ import * as Tidx from '../../internal/Tidx.js'
14
14
  import * as Viem from '../../internal/Viem.js'
15
15
  import * as Scope from '../../Scope.js'
16
16
  import * as Metadata from '../metadata.js'
17
+ import type * as FxOracle from './FxOracle.js'
17
18
 
18
19
  import { transactions as transactionActivities } from './routes/activities.js'
19
20
  import { addresses } from './routes/addresses.js'
@@ -42,6 +43,12 @@ import { schema as webhookSchema, webhooks } from './routes/webhooks.js'
42
43
  */
43
44
  export function data(options: data.Options = {}) {
44
45
  const { assets, tidx } = options
46
+ const webhook =
47
+ options.webhook === false
48
+ ? undefined
49
+ : (options.webhook ?? {
50
+ supportedChainIds: [Viem.chainId.mainnet, Viem.chainId.testnet],
51
+ })
45
52
 
46
53
  // Zone endpoints are explicit trust boundaries; the API never derives them.
47
54
  const zones = new Map((options.zones ?? []).map((zone) => [zone.chainId, zone]))
@@ -66,7 +73,7 @@ export function data(options: data.Options = {}) {
66
73
  c.set('supportedChainIds', supportedChainIds)
67
74
  c.set('tidx', tidx)
68
75
  c.set('verifiedTokens', options.verifiedTokens === false ? undefined : (options.verifiedTokens ?? {})) // prettier-ignore
69
- c.set('webhook', options.webhook === false ? undefined : (options.webhook ?? {}))
76
+ c.set('webhook', webhook)
70
77
  c.set('zones', zones)
71
78
  await next()
72
79
  })
@@ -158,18 +165,18 @@ export function data(options: data.Options = {}) {
158
165
  'Content-Type': asset.contentType,
159
166
  })
160
167
  })
161
- .route('/', addresses())
168
+ .route('/', addresses({ fx: options.fx }))
162
169
  .route('/', blocks())
163
- .route('/', exchanges())
170
+ .route('/', exchanges({ fx: options.fx }))
164
171
  .route('/', feeAmm())
165
172
  .route('/', funding(options.funding))
166
173
  .route('/', indexer())
167
- .route('/', receipts())
174
+ .route('/', receipts({ fx: options.fx }))
168
175
  .route('/', tokenlist())
169
176
  .route('/', tokens())
170
177
  .route('/', transactions())
171
- .route('/', transactionActivities())
172
- .route('/', transfers())
178
+ .route('/', transactionActivities({ fx: options.fx }))
179
+ .route('/', transfers({ fx: options.fx }))
173
180
  .route('/', verifiedTokens())
174
181
  .route('/', webhooks({ enabled: options.webhook !== false }))
175
182
  .route('/', rpc())
@@ -206,6 +213,8 @@ export declare namespace data {
206
213
  assets?: Assets.Assets | undefined
207
214
  /** Funding quote provider configuration. */
208
215
  funding?: funding.Options | undefined
216
+ /** FX configuration for the valuation endpoint. */
217
+ fx?: Fx | undefined
209
218
  /** TIDX query client options. */
210
219
  tidx?: Tidx.getClient.Tidx | undefined
211
220
  /** Verified-token feature configuration. Enabled by default (token rows live in `db`; empty until published); pass `false` to always serve an empty verified list. */
@@ -219,6 +228,12 @@ export declare namespace data {
219
228
  zones?: readonly Zone[] | undefined
220
229
  }
221
230
 
231
+ /** FX configuration for the valuation endpoint. */
232
+ type Fx = {
233
+ /** FX rate oracle backing currency conversion. Defaults to the ECB daily reference rates (`FxOracle.ecb()`). */
234
+ oracle?: FxOracle.Oracle | undefined
235
+ }
236
+
222
237
  /** One zone chain served by this deployment. */
223
238
  type Zone = {
224
239
  /** Zone chain id. Consumer-supplied literal; the API never derives zone chain ids. */
@@ -238,14 +253,7 @@ export declare namespace data {
238
253
  }
239
254
 
240
255
  /** Webhook feature configuration. */
241
- type Webhook = {
242
- /**
243
- * Maximum active subscriptions per owner; creation is rejected with
244
- * `403 limit_exceeded` once reached. Defaults to 100, bounding the spam/SSRF
245
- * and delivery-cost surface per owner.
246
- */
247
- maxPerOwner?: number | undefined
248
- }
256
+ type Webhook = App.Webhook
249
257
  }
250
258
 
251
259
  function resolveChainSelector(options: {
@@ -38,6 +38,15 @@ describe('FundingQuoteProviders', () => {
38
38
  })
39
39
  })
40
40
 
41
+ test('configures Symbiosis only when its quote user is present', () => {
42
+ expect(FundingQuoteProviders.configureSymbiosis()).toBeUndefined()
43
+ expect(
44
+ FundingQuoteProviders.configureSymbiosis({
45
+ userAddress: '0x1111111111111111111111111111111111111111',
46
+ }),
47
+ ).toEqual({ userAddress: '0x1111111111111111111111111111111111111111' })
48
+ })
49
+
41
50
  test('maps successful Across quotes to available quote probes', async () => {
42
51
  const requests: RecordedRequest[] = []
43
52
  const candidate = quoteCandidate('across')
@@ -262,6 +271,180 @@ describe('FundingQuoteProviders', () => {
262
271
  })
263
272
  })
264
273
 
274
+ test('maps successful Symbiosis quotes to available quote probes', async () => {
275
+ const requests: RecordedRequest[] = []
276
+ const candidate = quoteCandidate('symbiosis')
277
+ const fetch = recordingFetch(requests, async () => jsonResponse(symbiosisQuote(candidate)))
278
+ const adapter = FundingQuoteProviders.symbiosis({
279
+ baseUrl: 'https://symbiosis.test/crosschain/',
280
+ fetch,
281
+ now,
282
+ userAddress: '0x1111111111111111111111111111111111111111',
283
+ })
284
+
285
+ const result = await adapter.probeQuote(probeInput(candidate), new AbortController().signal)
286
+
287
+ expect(requests).toHaveLength(1)
288
+ expect(requests[0]?.url.pathname).toBe('/crosschain/v2/quote')
289
+ expect(new Headers(requests[0]?.init?.headers).get('x-partner-id')).toBe('tempo')
290
+ expect(jsonRequestBody(requests[0])).toEqual({
291
+ from: '0x1111111111111111111111111111111111111111',
292
+ slippage: 100,
293
+ to: '0x1111111111111111111111111111111111111111',
294
+ tokenAmountIn: {
295
+ address: candidate.sourceToken.address,
296
+ amount: '1000000',
297
+ chainId: 8453,
298
+ decimals: 6,
299
+ symbol: 'USDC',
300
+ },
301
+ tokenOut: {
302
+ address: candidate.destinationToken.address,
303
+ chainId: 4217,
304
+ decimals: 6,
305
+ symbol: 'USDC.e',
306
+ },
307
+ })
308
+ expect(result).toEqual({
309
+ minimumOutputAmount: '979000',
310
+ outputAmount: '989000',
311
+ outputAmountFormatted: '0.989',
312
+ quality: {
313
+ estimatedSeconds: 18,
314
+ liquiditySource: 'providerQuote',
315
+ sourceDetail: 'symbiosis:quote-v2',
316
+ tier: 'liquid',
317
+ },
318
+ sampledAt: '2026-01-01T00:00:00.000Z',
319
+ status: 'available',
320
+ })
321
+ })
322
+
323
+ test('maps Tron identifiers into Symbiosis quote requests', async () => {
324
+ const requests: RecordedRequest[] = []
325
+ const candidate = quoteCandidate('symbiosis', {
326
+ destinationToken: 'USDT0',
327
+ sourceChain: 'tron',
328
+ sourceToken: 'USDT',
329
+ })
330
+ const fetch = recordingFetch(requests, async () => jsonResponse(symbiosisQuote(candidate)))
331
+ const adapter = FundingQuoteProviders.symbiosis({
332
+ fetch,
333
+ now,
334
+ userAddress: '0x1111111111111111111111111111111111111111',
335
+ })
336
+
337
+ await adapter.probeQuote(probeInput(candidate), new AbortController().signal)
338
+
339
+ expect(jsonRequestBody(requests[0])).toMatchObject({
340
+ tokenAmountIn: {
341
+ address: '0xa614f803b6fd780986a42c78ec9c7f77e6ded13c',
342
+ chainId: 728126428,
343
+ decimals: 6,
344
+ symbol: 'USDT',
345
+ },
346
+ tokenOut: {
347
+ address: candidate.destinationToken.address,
348
+ chainId: 4217,
349
+ decimals: 6,
350
+ symbol: 'USDT0',
351
+ },
352
+ })
353
+ })
354
+
355
+ test('rejects Symbiosis responses without route identity fields', async () => {
356
+ const candidate = quoteCandidate('symbiosis')
357
+ const quote = symbiosisQuote(candidate)
358
+ const response = {
359
+ tokenAmountOut: quote.tokenAmountOut,
360
+ tokenAmountOutMin: quote.tokenAmountOutMin,
361
+ }
362
+ const adapter = FundingQuoteProviders.symbiosis({
363
+ fetch: recordingFetch([], async () => jsonResponse(response)),
364
+ now,
365
+ userAddress: '0x1111111111111111111111111111111111111111',
366
+ })
367
+
368
+ await expect(
369
+ adapter.probeQuote(probeInput(candidate), new AbortController().signal),
370
+ ).rejects.toThrowErrorMatchingInlineSnapshot(`[FundingQuoteProviders.ProviderPayloadError]`)
371
+ })
372
+
373
+ test('enforces the Symbiosis provider quota before fetching', async () => {
374
+ const requests: RecordedRequest[] = []
375
+ const candidate = quoteCandidate('symbiosis')
376
+ const adapter = FundingQuoteProviders.symbiosis({
377
+ fetch: recordingFetch(requests, async () => jsonResponse(symbiosisQuote(candidate))),
378
+ now,
379
+ userAddress: '0x1111111111111111111111111111111111111111',
380
+ })
381
+
382
+ await Promise.all(
383
+ Array.from({ length: 4 }, () =>
384
+ adapter.probeQuote(probeInput(candidate), new AbortController().signal),
385
+ ),
386
+ )
387
+ const cause = await adapter
388
+ .probeQuote(probeInput(candidate), new AbortController().signal)
389
+ .catch((error: unknown) => error)
390
+
391
+ expect(requests).toHaveLength(4)
392
+ expect(cause).toMatchObject({
393
+ name: 'FundingQuoteProviders.ProviderRateLimitError',
394
+ })
395
+ expect(FundingQuoteProviders.providerFailure({ cause, provider: 'symbiosis' })).toEqual({
396
+ failure: 'rate_limit',
397
+ id: 'symbiosis',
398
+ operation: 'v2/quote',
399
+ })
400
+ })
401
+
402
+ test('maps unavailable Symbiosis routes to unavailable quote probes', async () => {
403
+ const candidate = quoteCandidate('symbiosis')
404
+ const adapter = FundingQuoteProviders.symbiosis({
405
+ fetch: recordingFetch([], async () => jsonResponse({ code: 'NO_ROUTE' }, 400)),
406
+ now,
407
+ userAddress: '0x1111111111111111111111111111111111111111',
408
+ })
409
+
410
+ await expect(
411
+ adapter.probeQuote(probeInput(candidate), new AbortController().signal),
412
+ ).resolves.toMatchObject({
413
+ quality: {
414
+ sourceDetail: 'symbiosis:quote-v2:NO_ROUTE',
415
+ tier: 'unavailable',
416
+ },
417
+ status: 'unavailable',
418
+ })
419
+ })
420
+
421
+ test('maps Symbiosis fee-floor errors to unavailable quote probes', async () => {
422
+ const candidate = quoteCandidate('symbiosis')
423
+ const adapter = FundingQuoteProviders.symbiosis({
424
+ fetch: recordingFetch([], async () =>
425
+ jsonResponse({ code: 0, message: 'Amount is too low to cover fees' }, 400),
426
+ ),
427
+ now,
428
+ userAddress: '0x1111111111111111111111111111111111111111',
429
+ })
430
+
431
+ await expect(
432
+ adapter.probeQuote(probeInput(candidate), new AbortController().signal),
433
+ ).resolves.toMatchObject({
434
+ quality: {
435
+ sourceDetail: 'symbiosis:quote-v2:AMOUNT_TOO_LOW',
436
+ tier: 'unavailable',
437
+ },
438
+ status: 'unavailable',
439
+ })
440
+ })
441
+
442
+ test('rejects invalid Symbiosis configuration', () => {
443
+ expect(() =>
444
+ FundingQuoteProviders.symbiosis({ userAddress: 'invalid' }),
445
+ ).toThrowErrorMatchingInlineSnapshot(`[FundingQuoteProviders.ProviderConfigurationError]`)
446
+ })
447
+
265
448
  test('maps successful Rhino quotes to available quote probes', async () => {
266
449
  const requests: RecordedRequest[] = []
267
450
  const candidate = quoteCandidate('rhino')
@@ -585,6 +768,73 @@ describe('FundingQuoteProviders', () => {
585
768
  ).rejects.toThrowErrorMatchingInlineSnapshot(`[FundingQuoteProviders.ProviderPayloadError]`)
586
769
  })
587
770
 
771
+ const invalidSymbiosisQuotes = [
772
+ [
773
+ 'unsupported route kinds',
774
+ (body: ReturnType<typeof symbiosisQuote>) => (body.kind = 'onchain-swap' as never),
775
+ ],
776
+ [
777
+ 'mismatched execution types',
778
+ (body: ReturnType<typeof symbiosisQuote>) => (body.type = 'tron'),
779
+ ],
780
+ [
781
+ 'mismatched transaction chains',
782
+ (body: ReturnType<typeof symbiosisQuote>) => (body.tx.chainId = 1),
783
+ ],
784
+ ['empty routes', (body: ReturnType<typeof symbiosisQuote>) => (body.routes = [])],
785
+ [
786
+ 'mismatched source token addresses',
787
+ (body: ReturnType<typeof symbiosisQuote>) =>
788
+ (body.routes[0]!.tokens[0]!.address = '0xfde4c96c8593536e31f229ea8f37b2ada2699bb2'),
789
+ ],
790
+ [
791
+ 'mismatched source chains',
792
+ (body: ReturnType<typeof symbiosisQuote>) => (body.routes[0]!.tokens[0]!.chainId = 1),
793
+ ],
794
+ [
795
+ 'mismatched route destination tokens',
796
+ (body: ReturnType<typeof symbiosisQuote>) =>
797
+ (body.routes[0]!.tokens[1]!.address = '0x20c00000000000000000000014f22ca97301eb73'),
798
+ ],
799
+ [
800
+ 'mismatched output token addresses',
801
+ (body: ReturnType<typeof symbiosisQuote>) =>
802
+ (body.tokenAmountOut.address = '0x20c00000000000000000000014f22ca97301eb73'),
803
+ ],
804
+ [
805
+ 'mismatched minimum output chains',
806
+ (body: ReturnType<typeof symbiosisQuote>) => (body.tokenAmountOutMin.chainId = 1),
807
+ ],
808
+ [
809
+ 'mismatched output decimals',
810
+ (body: ReturnType<typeof symbiosisQuote>) => (body.tokenAmountOut.decimals = 18 as never),
811
+ ],
812
+ [
813
+ 'zero output amounts',
814
+ (body: ReturnType<typeof symbiosisQuote>) => (body.tokenAmountOut.amount = '0'),
815
+ ],
816
+ [
817
+ 'invalid output bounds',
818
+ (body: ReturnType<typeof symbiosisQuote>) => (body.tokenAmountOutMin.amount = '990000'),
819
+ ],
820
+ ] as const
821
+
822
+ for (const [name, mutate] of invalidSymbiosisQuotes)
823
+ test(`rejects Symbiosis quotes with ${name}`, async () => {
824
+ const candidate = quoteCandidate('symbiosis')
825
+ const body = symbiosisQuote(candidate)
826
+ mutate(body)
827
+ const adapter = FundingQuoteProviders.symbiosis({
828
+ fetch: recordingFetch([], async () => jsonResponse(body)),
829
+ now,
830
+ userAddress: '0x1111111111111111111111111111111111111111',
831
+ })
832
+
833
+ await expect(
834
+ adapter.probeQuote(probeInput(candidate), new AbortController().signal),
835
+ ).rejects.toThrowErrorMatchingInlineSnapshot(`[FundingQuoteProviders.ProviderPayloadError]`)
836
+ })
837
+
588
838
  test('returns bounded Across failure diagnostics', async () => {
589
839
  const candidate = quoteCandidate('across')
590
840
  const adapter = FundingQuoteProviders.across({
@@ -634,6 +884,19 @@ describe('FundingQuoteProviders', () => {
634
884
  operation: 'v2/route',
635
885
  })
636
886
  })
887
+
888
+ test('returns bounded Symbiosis failure diagnostics', () => {
889
+ expect(
890
+ FundingQuoteProviders.providerFailure({
891
+ cause: new TypeError('network failure'),
892
+ provider: 'symbiosis',
893
+ }),
894
+ ).toEqual({
895
+ failure: 'network',
896
+ id: 'symbiosis',
897
+ operation: 'v2/quote',
898
+ })
899
+ })
637
900
  })
638
901
 
639
902
  type RecordedRequest = {
@@ -711,6 +974,41 @@ function squidQuote(candidate: FundingQuotes.QuoteProbeInput['candidate']) {
711
974
  }
712
975
  }
713
976
 
977
+ function symbiosisQuote(candidate: FundingQuotes.QuoteProbeInput['candidate']) {
978
+ const source =
979
+ candidate.sourceChain.kind === 'tron'
980
+ ? {
981
+ address: '0xa614f803b6fd780986a42c78ec9c7f77e6ded13c',
982
+ chainId: 728126428,
983
+ decimals: candidate.sourceToken.decimals,
984
+ }
985
+ : {
986
+ address: candidate.sourceToken.address,
987
+ chainId: Number(candidate.sourceChain.id.replace('eip155:', '')),
988
+ decimals: candidate.sourceToken.decimals,
989
+ }
990
+ const destination = {
991
+ address: candidate.destinationToken.address,
992
+ chainId: 4217,
993
+ decimals: candidate.destinationToken.decimals,
994
+ }
995
+ return {
996
+ estimatedTime: 17.2,
997
+ kind: 'crosschain-swap' as const,
998
+ routes: [{ tokens: [source, destination] }],
999
+ tokenAmountOut: {
1000
+ ...destination,
1001
+ amount: '989000',
1002
+ },
1003
+ tokenAmountOutMin: {
1004
+ ...destination,
1005
+ amount: '979000',
1006
+ },
1007
+ tx: { chainId: source.chainId },
1008
+ type: candidate.sourceChain.kind,
1009
+ }
1010
+ }
1011
+
714
1012
  function probeInput(
715
1013
  candidate: FundingQuotes.QuoteProbeInput['candidate'],
716
1014
  ): FundingQuotes.QuoteProbeInput {