tapimo 0.11.0 → 0.12.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 (339) hide show
  1. package/dist/App.d.ts +2296 -1010
  2. package/dist/App.d.ts.map +1 -1
  3. package/dist/App.js +2 -2
  4. package/dist/App.js.map +1 -1
  5. package/dist/Assets.d.ts +15 -0
  6. package/dist/Assets.d.ts.map +1 -1
  7. package/dist/Assets.js +7 -0
  8. package/dist/Assets.js.map +1 -1
  9. package/dist/admin/App.d.ts +53 -4
  10. package/dist/admin/App.d.ts.map +1 -1
  11. package/dist/admin/apps/api-keys.d.ts +4 -4
  12. package/dist/admin/apps/earn-vaults.d.ts +114 -0
  13. package/dist/admin/apps/earn-vaults.d.ts.map +1 -1
  14. package/dist/admin/apps/earn-vaults.js +59 -6
  15. package/dist/admin/apps/earn-vaults.js.map +1 -1
  16. package/dist/admin/apps/organizations.d.ts.map +1 -1
  17. package/dist/admin/apps/organizations.js +4 -2
  18. package/dist/admin/apps/organizations.js.map +1 -1
  19. package/dist/admin/apps/verified-tokens.d.ts +9 -9
  20. package/dist/admin/ui.generated.d.ts +1 -1
  21. package/dist/admin/ui.generated.d.ts.map +1 -1
  22. package/dist/admin/ui.generated.js +151 -151
  23. package/dist/admin/ui.generated.js.map +1 -1
  24. package/dist/apps/data/App.d.ts +1699 -749
  25. package/dist/apps/data/App.d.ts.map +1 -1
  26. package/dist/apps/data/App.js +56 -7
  27. package/dist/apps/data/App.js.map +1 -1
  28. package/dist/apps/data/ZoneSelection.d.ts +62 -0
  29. package/dist/apps/data/ZoneSelection.d.ts.map +1 -0
  30. package/dist/apps/data/ZoneSelection.js +44 -0
  31. package/dist/apps/data/ZoneSelection.js.map +1 -0
  32. package/dist/apps/data/routes/activities.d.ts +2367 -4
  33. package/dist/apps/data/routes/activities.d.ts.map +1 -1
  34. package/dist/apps/data/routes/activities.js +368 -87
  35. package/dist/apps/data/routes/activities.js.map +1 -1
  36. package/dist/apps/data/routes/addresses.d.ts +471 -340
  37. package/dist/apps/data/routes/addresses.d.ts.map +1 -1
  38. package/dist/apps/data/routes/balances.d.ts +28 -28
  39. package/dist/apps/data/routes/balances.js +1 -1
  40. package/dist/apps/data/routes/balances.js.map +1 -1
  41. package/dist/apps/data/routes/blocks.d.ts +4 -4
  42. package/dist/apps/data/routes/blocks.js +1 -1
  43. package/dist/apps/data/routes/blocks.js.map +1 -1
  44. package/dist/apps/data/routes/coingecko.d.ts +176 -176
  45. package/dist/apps/data/routes/earn.d.ts +131 -6
  46. package/dist/apps/data/routes/earn.d.ts.map +1 -1
  47. package/dist/apps/data/routes/earn.js +157 -25
  48. package/dist/apps/data/routes/earn.js.map +1 -1
  49. package/dist/apps/data/routes/exchanges.d.ts +825 -119
  50. package/dist/apps/data/routes/exchanges.d.ts.map +1 -1
  51. package/dist/apps/data/routes/exchanges.js +16 -13
  52. package/dist/apps/data/routes/exchanges.js.map +1 -1
  53. package/dist/apps/data/routes/fee-amm.d.ts.map +1 -1
  54. package/dist/apps/data/routes/fee-amm.js +9 -11
  55. package/dist/apps/data/routes/fee-amm.js.map +1 -1
  56. package/dist/apps/data/routes/indexer.d.ts +34 -34
  57. package/dist/apps/data/routes/receipts.d.ts +230 -230
  58. package/dist/apps/data/routes/receipts.js +1 -1
  59. package/dist/apps/data/routes/receipts.js.map +1 -1
  60. package/dist/apps/data/routes/rpc.js +24 -10
  61. package/dist/apps/data/routes/rpc.js.map +1 -1
  62. package/dist/apps/data/routes/tokenlist.d.ts.map +1 -1
  63. package/dist/apps/data/routes/tokenlist.js +16 -15
  64. package/dist/apps/data/routes/tokenlist.js.map +1 -1
  65. package/dist/apps/data/routes/tokens.d.ts +14 -0
  66. package/dist/apps/data/routes/tokens.d.ts.map +1 -1
  67. package/dist/apps/data/routes/tokens.js +34 -15
  68. package/dist/apps/data/routes/tokens.js.map +1 -1
  69. package/dist/apps/data/routes/transactions.js +1 -1
  70. package/dist/apps/data/routes/transactions.js.map +1 -1
  71. package/dist/apps/data/routes/transfers.d.ts.map +1 -1
  72. package/dist/apps/data/routes/transfers.js +7 -9
  73. package/dist/apps/data/routes/transfers.js.map +1 -1
  74. package/dist/apps/data/routes/webhooks.d.ts +4 -4
  75. package/dist/apps/data/routes/webhooks.d.ts.map +1 -1
  76. package/dist/apps/data/routes/webhooks.js +2 -2
  77. package/dist/apps/data/routes/webhooks.js.map +1 -1
  78. package/dist/apps/data/routes/zones.d.ts +30 -30
  79. package/dist/apps/funding/App.d.ts +27 -27
  80. package/dist/apps/funding/routes/chains.d.ts.map +1 -1
  81. package/dist/apps/funding/routes/chains.js +5 -4
  82. package/dist/apps/funding/routes/chains.js.map +1 -1
  83. package/dist/apps/funding/routes/deposit-addresses.d.ts +16 -16
  84. package/dist/apps/funding/routes/deposit-addresses.d.ts.map +1 -1
  85. package/dist/apps/funding/routes/deposit-addresses.js +8 -8
  86. package/dist/apps/funding/routes/deposit-addresses.js.map +1 -1
  87. package/dist/apps/funding/routes/providers.d.ts +13 -13
  88. package/dist/apps/funding/routes/providers.d.ts.map +1 -1
  89. package/dist/apps/funding/routes/providers.js +3 -2
  90. package/dist/apps/funding/routes/providers.js.map +1 -1
  91. package/dist/apps/funding/routes/quotes.d.ts.map +1 -1
  92. package/dist/apps/funding/routes/quotes.js +2 -2
  93. package/dist/apps/funding/routes/quotes.js.map +1 -1
  94. package/dist/apps/management/App.d.ts +627 -293
  95. package/dist/apps/management/App.d.ts.map +1 -1
  96. package/dist/apps/management/Billing.d.ts.map +1 -1
  97. package/dist/apps/management/Billing.js +19 -6
  98. package/dist/apps/management/Billing.js.map +1 -1
  99. package/dist/apps/management/routes/api-keys.d.ts +114 -54
  100. package/dist/apps/management/routes/api-keys.d.ts.map +1 -1
  101. package/dist/apps/management/routes/api-keys.js +76 -30
  102. package/dist/apps/management/routes/api-keys.js.map +1 -1
  103. package/dist/apps/management/routes/billing.d.ts +103 -30
  104. package/dist/apps/management/routes/billing.d.ts.map +1 -1
  105. package/dist/apps/management/routes/billing.js +91 -32
  106. package/dist/apps/management/routes/billing.js.map +1 -1
  107. package/dist/apps/management/routes/faucet.d.ts +33 -33
  108. package/dist/apps/management/routes/faucet.d.ts.map +1 -1
  109. package/dist/apps/management/routes/faucet.js +23 -12
  110. package/dist/apps/management/routes/faucet.js.map +1 -1
  111. package/dist/apps/management/routes/invitations.d.ts +46 -13
  112. package/dist/apps/management/routes/invitations.d.ts.map +1 -1
  113. package/dist/apps/management/routes/invitations.js +79 -29
  114. package/dist/apps/management/routes/invitations.js.map +1 -1
  115. package/dist/apps/management/routes/invite-links.d.ts +86 -41
  116. package/dist/apps/management/routes/invite-links.d.ts.map +1 -1
  117. package/dist/apps/management/routes/invite-links.js +100 -41
  118. package/dist/apps/management/routes/invite-links.js.map +1 -1
  119. package/dist/apps/management/routes/me.d.ts +5 -5
  120. package/dist/apps/management/routes/me.d.ts.map +1 -1
  121. package/dist/apps/management/routes/me.js +14 -10
  122. package/dist/apps/management/routes/me.js.map +1 -1
  123. package/dist/apps/management/routes/members.d.ts +93 -72
  124. package/dist/apps/management/routes/members.d.ts.map +1 -1
  125. package/dist/apps/management/routes/members.js +37 -18
  126. package/dist/apps/management/routes/members.js.map +1 -1
  127. package/dist/apps/management/routes/orgs.d.ts +48 -8
  128. package/dist/apps/management/routes/orgs.d.ts.map +1 -1
  129. package/dist/apps/management/routes/orgs.js +48 -19
  130. package/dist/apps/management/routes/orgs.js.map +1 -1
  131. package/dist/apps/management/routes/projects.d.ts +90 -28
  132. package/dist/apps/management/routes/projects.d.ts.map +1 -1
  133. package/dist/apps/management/routes/projects.js +72 -21
  134. package/dist/apps/management/routes/projects.js.map +1 -1
  135. package/dist/apps/management/routes/scopes.d.ts.map +1 -1
  136. package/dist/apps/management/routes/scopes.js +8 -5
  137. package/dist/apps/management/routes/scopes.js.map +1 -1
  138. package/dist/apps/management/routes/usage.d.ts +78 -78
  139. package/dist/apps/management/routes/usage.d.ts.map +1 -1
  140. package/dist/apps/management/routes/usage.js +41 -31
  141. package/dist/apps/management/routes/usage.js.map +1 -1
  142. package/dist/apps/management/routes/verified-token-requests.d.ts +34 -6
  143. package/dist/apps/management/routes/verified-token-requests.d.ts.map +1 -1
  144. package/dist/apps/management/routes/verified-token-requests.js +36 -17
  145. package/dist/apps/management/routes/verified-token-requests.js.map +1 -1
  146. package/dist/apps/management/routes/webhooks.d.ts +147 -130
  147. package/dist/apps/management/routes/webhooks.d.ts.map +1 -1
  148. package/dist/apps/management/routes/webhooks.js +80 -35
  149. package/dist/apps/management/routes/webhooks.js.map +1 -1
  150. package/dist/apps/mpp/internal/Adapter.d.ts +1 -1
  151. package/dist/apps/mpp/internal/Adapter.d.ts.map +1 -1
  152. package/dist/apps/mpp/internal/Adapter.js +12 -0
  153. package/dist/apps/mpp/internal/Adapter.js.map +1 -1
  154. package/dist/db/Db.d.ts +2 -0
  155. package/dist/db/Db.d.ts.map +1 -1
  156. package/dist/db/Db.js +40 -0
  157. package/dist/db/Db.js.map +1 -1
  158. package/dist/db/Schema.d.ts +23 -1
  159. package/dist/db/Schema.d.ts.map +1 -1
  160. package/dist/db/Schema.js +19 -3
  161. package/dist/db/Schema.js.map +1 -1
  162. package/dist/db/tables/earnVaults.d.ts +5 -1
  163. package/dist/db/tables/earnVaults.d.ts.map +1 -1
  164. package/dist/db/tables/earnVaults.js +5 -0
  165. package/dist/db/tables/earnVaults.js.map +1 -1
  166. package/dist/db/tables/webhookDeliveries.d.ts.map +1 -1
  167. package/dist/db/tables/webhookDeliveries.js +10 -0
  168. package/dist/db/tables/webhookDeliveries.js.map +1 -1
  169. package/dist/db/tables/webhookQueueCompletions.d.ts +15 -0
  170. package/dist/db/tables/webhookQueueCompletions.d.ts.map +1 -0
  171. package/dist/db/tables/webhookQueueCompletions.js +32 -0
  172. package/dist/db/tables/webhookQueueCompletions.js.map +1 -0
  173. package/dist/db/tables/webhookQueueEvents.d.ts +14 -20
  174. package/dist/db/tables/webhookQueueEvents.d.ts.map +1 -1
  175. package/dist/db/tables/webhookQueueEvents.js +68 -47
  176. package/dist/db/tables/webhookQueueEvents.js.map +1 -1
  177. package/dist/db/tables/webhookSubscriptions.d.ts +16 -5
  178. package/dist/db/tables/webhookSubscriptions.d.ts.map +1 -1
  179. package/dist/db/tables/webhookSubscriptions.js +29 -5
  180. package/dist/db/tables/webhookSubscriptions.js.map +1 -1
  181. package/dist/internal/Auth.d.ts +8 -1
  182. package/dist/internal/Auth.d.ts.map +1 -1
  183. package/dist/internal/Auth.js +13 -3
  184. package/dist/internal/Auth.js.map +1 -1
  185. package/dist/internal/Cache.d.ts.map +1 -1
  186. package/dist/internal/Cache.js +11 -7
  187. package/dist/internal/Cache.js.map +1 -1
  188. package/dist/internal/EarnVaults.d.ts +41 -2
  189. package/dist/internal/EarnVaults.d.ts.map +1 -1
  190. package/dist/internal/EarnVaults.js +167 -0
  191. package/dist/internal/EarnVaults.js.map +1 -1
  192. package/dist/internal/OpenApi.d.ts +26 -22
  193. package/dist/internal/OpenApi.d.ts.map +1 -1
  194. package/dist/internal/OpenApi.js +128 -39
  195. package/dist/internal/OpenApi.js.map +1 -1
  196. package/dist/internal/Response.d.ts +13 -8
  197. package/dist/internal/Response.d.ts.map +1 -1
  198. package/dist/internal/Response.js +16 -5
  199. package/dist/internal/Response.js.map +1 -1
  200. package/dist/internal/Schema.d.ts +5 -7
  201. package/dist/internal/Schema.d.ts.map +1 -1
  202. package/dist/internal/Schema.js +6 -7
  203. package/dist/internal/Schema.js.map +1 -1
  204. package/dist/internal/Store.d.ts +15 -6
  205. package/dist/internal/Store.d.ts.map +1 -1
  206. package/dist/internal/Store.js +45 -15
  207. package/dist/internal/Store.js.map +1 -1
  208. package/dist/internal/Tidx.d.ts +2 -0
  209. package/dist/internal/Tidx.d.ts.map +1 -1
  210. package/dist/internal/Tidx.js +16 -4
  211. package/dist/internal/Tidx.js.map +1 -1
  212. package/dist/internal/Webhooks.d.ts +29 -12
  213. package/dist/internal/Webhooks.d.ts.map +1 -1
  214. package/dist/internal/Webhooks.js +37 -20
  215. package/dist/internal/Webhooks.js.map +1 -1
  216. package/dist/internal/funding/Deposit.d.ts +2 -2
  217. package/dist/internal/funding/Deposit.d.ts.map +1 -1
  218. package/dist/internal/funding/Deposit.js +9 -8
  219. package/dist/internal/funding/Deposit.js.map +1 -1
  220. package/dist/internal/funding/DepositAddress.d.ts +4 -4
  221. package/dist/internal/funding/DepositAddress.d.ts.map +1 -1
  222. package/dist/internal/funding/DepositAddress.js +9 -8
  223. package/dist/internal/funding/DepositAddress.js.map +1 -1
  224. package/dist/internal/funding/Provider.d.ts.map +1 -1
  225. package/dist/internal/funding/Provider.js +13 -12
  226. package/dist/internal/funding/Provider.js.map +1 -1
  227. package/dist/internal/funding/providers/stargate.d.ts +19 -0
  228. package/dist/internal/funding/providers/stargate.d.ts.map +1 -0
  229. package/dist/internal/funding/providers/stargate.js +143 -0
  230. package/dist/internal/funding/providers/stargate.js.map +1 -0
  231. package/dist/providers/index.d.ts +7 -0
  232. package/dist/providers/index.d.ts.map +1 -1
  233. package/dist/providers/index.js +3 -0
  234. package/dist/providers/index.js.map +1 -1
  235. package/package.json +2 -2
  236. package/src/App.test.ts +48 -0
  237. package/src/App.ts +4 -2
  238. package/src/Assets.test.ts +18 -0
  239. package/src/Assets.ts +22 -0
  240. package/src/Client.test-d.ts +265 -16
  241. package/src/admin/apps/earn-vaults.test.ts +143 -0
  242. package/src/admin/apps/earn-vaults.ts +83 -6
  243. package/src/admin/apps/organizations.ts +6 -2
  244. package/src/admin/ui/src/routes/api-keys.tsx +36 -0
  245. package/src/admin/ui.generated.ts +151 -189
  246. package/src/apps/data/App.test.ts +31 -0
  247. package/src/apps/data/App.ts +56 -8
  248. package/src/apps/data/ZoneSelection.test.ts +196 -0
  249. package/src/apps/data/ZoneSelection.ts +108 -0
  250. package/src/apps/data/routes/activities.test.ts +328 -1
  251. package/src/apps/data/routes/activities.ts +498 -93
  252. package/src/apps/data/routes/balances.ts +1 -1
  253. package/src/apps/data/routes/blocks.ts +1 -1
  254. package/src/apps/data/routes/earn.test.ts +183 -23
  255. package/src/apps/data/routes/earn.ts +225 -29
  256. package/src/apps/data/routes/earn.zone-access.test.ts +46 -0
  257. package/src/apps/data/routes/exchanges.test.ts +31 -1
  258. package/src/apps/data/routes/exchanges.ts +19 -15
  259. package/src/apps/data/routes/fee-amm.ts +18 -11
  260. package/src/apps/data/routes/receipts.ts +1 -1
  261. package/src/apps/data/routes/rpc.test.ts +75 -0
  262. package/src/apps/data/routes/rpc.ts +23 -9
  263. package/src/apps/data/routes/tokenlist.ts +21 -18
  264. package/src/apps/data/routes/tokens.test.ts +29 -0
  265. package/src/apps/data/routes/tokens.ts +38 -15
  266. package/src/apps/data/routes/transactions.ts +1 -1
  267. package/src/apps/data/routes/transfers.test.ts +3 -3
  268. package/src/apps/data/routes/transfers.ts +12 -9
  269. package/src/apps/data/routes/webhooks.ts +6 -2
  270. package/src/apps/data/routes/zones.test.ts +19 -13
  271. package/src/apps/funding/routes/chains.test.ts +211 -7
  272. package/src/apps/funding/routes/chains.ts +19 -12
  273. package/src/apps/funding/routes/deposit-addresses.test.ts +394 -0
  274. package/src/apps/funding/routes/deposit-addresses.ts +84 -72
  275. package/src/apps/funding/routes/providers.ts +9 -5
  276. package/src/apps/funding/routes/quotes.test.ts +46 -0
  277. package/src/apps/funding/routes/quotes.ts +8 -5
  278. package/src/apps/funding/routes/transfers.test.ts +35 -32
  279. package/src/apps/management/Billing.test.ts +26 -0
  280. package/src/apps/management/Billing.ts +24 -7
  281. package/src/apps/management/routes/api-keys.test.ts +178 -0
  282. package/src/apps/management/routes/api-keys.ts +203 -144
  283. package/src/apps/management/routes/billing.test.ts +209 -0
  284. package/src/apps/management/routes/billing.ts +254 -177
  285. package/src/apps/management/routes/faucet.test.ts +39 -0
  286. package/src/apps/management/routes/faucet.ts +75 -41
  287. package/src/apps/management/routes/invitations.test.ts +216 -0
  288. package/src/apps/management/routes/invitations.ts +186 -109
  289. package/src/apps/management/routes/invite-links.test.ts +263 -1
  290. package/src/apps/management/routes/invite-links.ts +295 -214
  291. package/src/apps/management/routes/me.test.ts +49 -0
  292. package/src/apps/management/routes/me.ts +42 -32
  293. package/src/apps/management/routes/members.test.ts +124 -1
  294. package/src/apps/management/routes/members.ts +81 -51
  295. package/src/apps/management/routes/orgs.test.ts +176 -0
  296. package/src/apps/management/routes/orgs.ts +101 -59
  297. package/src/apps/management/routes/projects.test.ts +183 -0
  298. package/src/apps/management/routes/projects.ts +124 -60
  299. package/src/apps/management/routes/scopes.test.ts +44 -0
  300. package/src/apps/management/routes/scopes.ts +37 -28
  301. package/src/apps/management/routes/usage.test.ts +92 -0
  302. package/src/apps/management/routes/usage.ts +186 -151
  303. package/src/apps/management/routes/verified-token-requests.test.ts +114 -0
  304. package/src/apps/management/routes/verified-token-requests.ts +166 -133
  305. package/src/apps/management/routes/webhooks.test.ts +234 -0
  306. package/src/apps/management/routes/webhooks.ts +191 -78
  307. package/src/apps/mpp/internal/Adapter.ts +13 -1
  308. package/src/db/Db.test.ts +41 -0
  309. package/src/db/Db.ts +62 -0
  310. package/src/db/Schema.ts +28 -3
  311. package/src/db/tables/earnVaults.test.ts +22 -0
  312. package/src/db/tables/earnVaults.ts +11 -1
  313. package/src/db/tables/webhookDeliveries.ts +13 -0
  314. package/src/db/tables/webhookQueueCompletions.ts +55 -0
  315. package/src/db/tables/webhookQueueEvents.ts +95 -61
  316. package/src/db/tables/webhookSubscriptions.ts +45 -6
  317. package/src/internal/Auth.ts +23 -5
  318. package/src/internal/Cache.ts +14 -7
  319. package/src/internal/EarnVaults.capabilities.test.ts +33 -0
  320. package/src/internal/EarnVaults.test.ts +79 -0
  321. package/src/internal/EarnVaults.ts +277 -0
  322. package/src/internal/OpenApi.ts +165 -49
  323. package/src/internal/Response.test.ts +95 -0
  324. package/src/internal/Response.ts +40 -2
  325. package/src/internal/Schema.test.ts +16 -0
  326. package/src/internal/Schema.ts +7 -7
  327. package/src/internal/Store.test.ts +186 -0
  328. package/src/internal/Store.ts +57 -17
  329. package/src/internal/Tidx.test.ts +19 -0
  330. package/src/internal/Tidx.ts +16 -4
  331. package/src/internal/Webhooks.test.ts +122 -8
  332. package/src/internal/Webhooks.ts +59 -29
  333. package/src/internal/funding/Deposit.ts +71 -64
  334. package/src/internal/funding/DepositAddress.ts +50 -43
  335. package/src/internal/funding/Provider.ts +164 -142
  336. package/src/internal/funding/providers/index.test.ts +185 -0
  337. package/src/internal/funding/providers/stargate.ts +184 -0
  338. package/src/providers/index.test.ts +1 -0
  339. package/src/providers/index.ts +9 -0
@@ -149,6 +149,37 @@ describe('MPP session management', () => {
149
149
  PaymentRequest.serialize({ _mppx_scope: 'GET /v1/scopes' }),
150
150
  )
151
151
  })
152
+
153
+ test('applies POST auth overrides to QUERY aliases', async () => {
154
+ const app = TestApp.create({
155
+ auth: {
156
+ overrides: {
157
+ 'POST /v1/exchange/quotes': { mpp: false, public: false },
158
+ },
159
+ },
160
+ })
161
+
162
+ const post = await app.request('/v1/exchange/quotes', { method: 'POST' })
163
+ const query = await app.request('/v1/exchange/quotes', { method: 'QUERY' })
164
+
165
+ expect([post.status, query.status]).toEqual([401, 401])
166
+ })
167
+
168
+ test('prefers an explicit QUERY auth override', async () => {
169
+ const app = TestApp.create({
170
+ auth: {
171
+ overrides: {
172
+ 'POST /v1/exchange/quotes': { mpp: false, public: false },
173
+ 'QUERY /v1/exchange/quotes': false,
174
+ },
175
+ },
176
+ })
177
+
178
+ const post = await app.request('/v1/exchange/quotes', { method: 'POST' })
179
+ const query = await app.request('/v1/exchange/quotes', { method: 'QUERY' })
180
+
181
+ expect([post.status, query.status]).toEqual([401, 400])
182
+ })
152
183
  })
153
184
 
154
185
  describe('zone chain gate', () => {
@@ -3,7 +3,7 @@ import { matchedRoutes } from 'hono/route'
3
3
  import { ZoneRpcAuthentication } from 'ox/tempo'
4
4
  import * as z from 'zod/mini'
5
5
 
6
- import type * as Assets from '../../Assets.js'
6
+ import * as Assets from '../../Assets.js'
7
7
  import type * as App from '../../App.js'
8
8
  import * as Auth from '../../internal/Auth.js'
9
9
  import * as EdgeCache from '../../internal/EdgeCache.js'
@@ -17,6 +17,7 @@ import * as Scope from '../../Scope.js'
17
17
  import * as Metadata from '../metadata.js'
18
18
 
19
19
  import type * as FxOracle from './FxOracle.js'
20
+ import * as ZoneSelection from './ZoneSelection.js'
20
21
 
21
22
  import { transactions as transactionActivities } from './routes/activities.js'
22
23
  import { addresses } from './routes/addresses.js'
@@ -58,9 +59,17 @@ export function data(options: data.Options = {}) {
58
59
  const dataRouteHandlers = new Set<unknown>()
59
60
 
60
61
  const getTidx = Tidx.createGetClient({ tidx })
62
+ const addresses_routes = addresses({ fx: options.fx })
61
63
  const earn_routes = earn({ fx: options.fx })
62
64
  const indexer_routes = indexer()
65
+ const transactionActivities_routes = transactionActivities({ fx: options.fx })
63
66
  const indexerRouteHandlers = new Set(indexer_routes.routes.map((route) => route.handler))
67
+ const inferredZoneRouteHandlers = new Set([
68
+ ...addresses_routes.routes
69
+ .filter((route) => route.path === '/v1/addresses/:address/activities')
70
+ .map((route) => route.handler),
71
+ ...transactionActivities_routes.routes.map((route) => route.handler),
72
+ ])
64
73
  const rpcOnlyRouteHandlers = new Set(
65
74
  earn_routes.routes
66
75
  .filter((route) => route.path === '/v1/earn/vaults/:vaultId/positions/:address')
@@ -106,6 +115,7 @@ export function data(options: data.Options = {}) {
106
115
  c,
107
116
  defaultChainId,
108
117
  handlers: dataRouteHandlers,
118
+ inferredZoneHandlers: inferredZoneRouteHandlers,
109
119
  indexerHandlers: indexerRouteHandlers,
110
120
  rpcOnlyHandlers: rpcOnlyRouteHandlers,
111
121
  })
@@ -120,6 +130,30 @@ export function data(options: data.Options = {}) {
120
130
  const rpc_config = c.get('rpc')
121
131
  const tidx_config = c.get('tidx')
122
132
  const zones = c.get('zones')
133
+ if (selection.inferredZones) {
134
+ if (principal?.type !== 'api_key')
135
+ return Response.error(c, {
136
+ code: 'api_key_forbidden',
137
+ message: '`include=zones` requires an API key with readable Zone scopes.',
138
+ status: 403,
139
+ })
140
+ const zoneChainIds = ZoneSelection.readableChainIds({
141
+ parentChainId: selection.chainId,
142
+ principal,
143
+ rpc: rpc_config,
144
+ tidx: tidx_config,
145
+ zones,
146
+ })
147
+ if (zoneChainIds.length === 0)
148
+ return Response.error(c, {
149
+ code: 'api_key_forbidden',
150
+ message: 'The API key has no readable configured Zones.',
151
+ status: 403,
152
+ })
153
+ c.set('supportedChainIds', new Set(zoneChainIds))
154
+ c.set('zoneChainIds', zoneChainIds)
155
+ return next()
156
+ }
123
157
  // Raw passthroughs and RPC-only reads need only RPC; composed data routes
124
158
  // require both upstreams to avoid falling through to unrelated defaults.
125
159
  const narrowedChainIds = new Set(
@@ -147,10 +181,12 @@ export function data(options: data.Options = {}) {
147
181
  c,
148
182
  defaultChainId: c.get('chainId'),
149
183
  handlers: dataRouteHandlers,
184
+ inferredZoneHandlers: inferredZoneRouteHandlers,
150
185
  indexerHandlers: indexerRouteHandlers,
151
186
  rpcOnlyHandlers: rpcOnlyRouteHandlers,
152
187
  })
153
188
  if (!selection.matched) return next()
189
+ if (selection.inferredZones) return next()
154
190
  const chainId = c.get('chainId')
155
191
  if (!zones.has(chainId)) return next()
156
192
 
@@ -187,10 +223,12 @@ export function data(options: data.Options = {}) {
187
223
  c,
188
224
  defaultChainId: c.get('chainId'),
189
225
  handlers: dataRouteHandlers,
226
+ inferredZoneHandlers: inferredZoneRouteHandlers,
190
227
  indexerHandlers: indexerRouteHandlers,
191
228
  rpcOnlyHandlers: rpcOnlyRouteHandlers,
192
229
  })
193
- if (!selection.matched || !Viem.isMainnet(c.get('chainId'))) return next()
230
+ if (!selection.matched || selection.inferredZones || !Viem.isMainnet(c.get('chainId')))
231
+ return next()
194
232
 
195
233
  return Response.error(c, {
196
234
  code: 'api_key_forbidden',
@@ -211,7 +249,7 @@ export function data(options: data.Options = {}) {
211
249
  'Content-Type': asset.contentType,
212
250
  })
213
251
  })
214
- .route('/', addresses({ fx: options.fx }))
252
+ .route('/', addresses_routes)
215
253
  .route('/', blocks())
216
254
  .route('/', earn_routes)
217
255
  .route('/', exchanges({ fx: options.fx }))
@@ -221,7 +259,7 @@ export function data(options: data.Options = {}) {
221
259
  .route('/', tokenlist())
222
260
  .route('/', tokens())
223
261
  .route('/', transactions())
224
- .route('/', transactionActivities({ fx: options.fx }))
262
+ .route('/', transactionActivities_routes)
225
263
  .route('/', transfers({ fx: options.fx }))
226
264
  .route('/', verifiedTokens())
227
265
  .route(
@@ -240,14 +278,16 @@ export function data(options: data.Options = {}) {
240
278
  c,
241
279
  defaultChainId: c.get('chainId'),
242
280
  handlers: dataRouteHandlers,
281
+ inferredZoneHandlers: inferredZoneRouteHandlers,
243
282
  indexerHandlers: indexerRouteHandlers,
244
283
  rpcOnlyHandlers: rpcOnlyRouteHandlers,
245
284
  })
246
- if (selection.matched && !selection.conflict && !selection.invalid)
285
+ if (selection.matched && !selection.conflict && !selection.inferredZones && !selection.invalid)
247
286
  c.set('chainId', selection.chainId)
248
287
  return (
249
288
  selection.matched &&
250
289
  !selection.conflict &&
290
+ !selection.inferredZones &&
251
291
  !selection.invalid &&
252
292
  !c.get('zones').has(selection.chainId)
253
293
  )
@@ -302,6 +342,7 @@ function resolveChainSelector(options: {
302
342
  c: Context<App.Environment>
303
343
  defaultChainId: Viem.ChainId
304
344
  handlers: ReadonlySet<unknown>
345
+ inferredZoneHandlers: ReadonlySet<unknown>
305
346
  indexerHandlers: ReadonlySet<unknown>
306
347
  rpcOnlyHandlers: ReadonlySet<unknown>
307
348
  }) {
@@ -310,9 +351,11 @@ function resolveChainSelector(options: {
310
351
  let rpc = false
311
352
  let rpcOnly = false
312
353
  let indexer = false
354
+ let inferredZonesAllowed = false
313
355
  for (const route of matchedRoutes(options.c)) {
314
356
  if (!options.handlers.has(route.handler)) continue
315
357
  matched = true
358
+ if (options.inferredZoneHandlers.has(route.handler)) inferredZonesAllowed = true
316
359
  if (options.indexerHandlers.has(route.handler)) indexer = true
317
360
  if (options.rpcOnlyHandlers.has(route.handler)) rpcOnly = true
318
361
  const selector = pathChainSelector(route.path, options.c.req.path)
@@ -326,6 +369,7 @@ function resolveChainSelector(options: {
326
369
  return {
327
370
  chainId: options.defaultChainId,
328
371
  conflict: false,
372
+ inferredZones: false,
329
373
  indexer: false,
330
374
  invalid: false,
331
375
  matched: false,
@@ -334,6 +378,10 @@ function resolveChainSelector(options: {
334
378
  }
335
379
 
336
380
  const search = new URL(options.c.req.url).searchParams
381
+ const include = inferredZonesAllowed
382
+ ? search.getAll('include').flatMap((value) => value.split(',').map((part) => part.trim()))
383
+ : []
384
+ const inferredZones = include.includes('zones')
337
385
  const raw = [
338
386
  ...(path === undefined ? [] : [path]),
339
387
  ...(rpc ? [] : search.getAll('chainId')),
@@ -344,6 +392,7 @@ function resolveChainSelector(options: {
344
392
  return {
345
393
  chainId: chainIds[0] ?? options.defaultChainId,
346
394
  conflict: chainIds.length > 1,
395
+ inferredZones,
347
396
  indexer,
348
397
  invalid: parsed.some((result) => !result.success),
349
398
  matched: true,
@@ -473,7 +522,6 @@ function createGetAsset(options: createGetAsset.Options): App.GetAsset {
473
522
  const { assets, basePath, origin } = options
474
523
  if (!assets) return () => undefined
475
524
  const getAsset: App.GetAsset = async (chainId, path) => {
476
- const pathname = Path.join(basePath, 'assets', String(chainId), path)
477
525
  // `path` may be absolute (`Path.join` returns a leading slash); strip it so
478
526
  // the key is `:chainId/:path`, not `:chainId//:path`.
479
527
  const key = `${chainId}/${path.replace(/^\/+/, '')}`
@@ -483,7 +531,7 @@ function createGetAsset(options: createGetAsset.Options): App.GetAsset {
483
531
  response: new globalThis.Response(asset.body, {
484
532
  headers: { 'Content-Type': asset.contentType },
485
533
  }),
486
- uri: new URL(pathname, origin).toString(),
534
+ uri: Assets.url({ basePath, chainId, origin, path }),
487
535
  }
488
536
  }
489
537
  const list = assets.list
@@ -492,7 +540,7 @@ function createGetAsset(options: createGetAsset.Options): App.GetAsset {
492
540
  const prefix = `${chainId}/${path.replace(/^\/+/, '')}`
493
541
  return (await list(prefix)).map((key) => ({
494
542
  key,
495
- uri: new URL(Path.join(basePath, 'assets', key), origin).toString(),
543
+ uri: Assets.url({ basePath, chainId, origin, path: key.slice(String(chainId).length + 1) }),
496
544
  }))
497
545
  }
498
546
  return getAsset
@@ -0,0 +1,196 @@
1
+ import * as ApiKey from '../../ApiKey.js'
2
+ import * as App from '../../App.js'
3
+ import * as Db from '../../db/Db.js'
4
+ import type * as Auth from '../../internal/Auth.js'
5
+ import * as Viem from '../../internal/Viem.js'
6
+ import * as Zones from '../Zones.js'
7
+
8
+ import * as Data from './App.js'
9
+ import * as ZoneSelection from './ZoneSelection.js'
10
+ import * as Activities from './routes/activities.js'
11
+
12
+ describe('transaction activity Zone query', () => {
13
+ test('accepts the Zones include with an optional parent chain', () => {
14
+ expect(
15
+ Activities.schema.getTransactionActivities.Query.parse({ include: 'zones' }).include,
16
+ ).toStrictEqual(['zones'])
17
+ expect(
18
+ Activities.schema.getTransactionActivities.Query.parse({
19
+ chainId: '4217',
20
+ include: 'zones',
21
+ }),
22
+ ).toMatchObject({ chainId: 4217, include: ['zones'] })
23
+ expect(
24
+ Activities.schema.getTransactionActivities.Query.safeParse({ includeZones: 'true' }).success,
25
+ ).toBe(false)
26
+ })
27
+
28
+ test('opts in only activity routes and accepts a parent chain', async () => {
29
+ const app = App.create({
30
+ auth: false,
31
+ db: Db.postgres({ connectionString: 'postgresql://unused@127.0.0.1:1/unused' }),
32
+ zones: [Zones.zoneModeratoInternal],
33
+ }).route('/', Data.data({ webhook: false }))
34
+ const address = '0x0000000000000000000000000000000000000001'
35
+ const hash = `0x${'00'.repeat(32)}`
36
+ const addressScoped = await app.request(
37
+ `/v1/addresses/${address}/activities?include=zones&chainId=${Viem.chainId.testnet}`,
38
+ )
39
+ const forbidden = await app.request(`/v1/transactions/${hash}/activities?include=zones`)
40
+ const scoped = await app.request(
41
+ `/v1/transactions/${hash}/activities?include=zones&chainId=${Viem.chainId.testnet}`,
42
+ )
43
+ const unsupported = await app.request('/v1/tokenlist?include=zones')
44
+
45
+ expect(forbidden.status).toBe(403)
46
+ expect(forbidden.headers.get('cache-control')).toBe('no-store')
47
+ expect(await addressScoped.json()).toMatchObject({ error: { code: 'api_key_forbidden' } })
48
+ expect(await scoped.json()).toMatchObject({ error: { code: 'api_key_forbidden' } })
49
+ expect(await unsupported.json()).toMatchObject({ error: { code: 'query_invalid' } })
50
+ })
51
+ })
52
+
53
+ describe('readableChainIds', () => {
54
+ test('intersects the parent chain, scopes, and configured routable Zones', () => {
55
+ const principal = apiKeyPrincipal({
56
+ scopes: [
57
+ 'data:read',
58
+ `zone:${Zones.zoneMainnetInternal.id}:read`,
59
+ `zone:${Zones.zoneModeratoInternal.id}:write`,
60
+ ],
61
+ })
62
+
63
+ expect(
64
+ ZoneSelection.readableChainIds({
65
+ parentChainId: Viem.chainId.testnet,
66
+ principal,
67
+ zones: new Map(Zones.chains.map((zone) => [zone.id, zone])),
68
+ }),
69
+ ).toStrictEqual([Zones.zoneModeratoInternal.id])
70
+ expect(
71
+ ZoneSelection.readableChainIds({
72
+ parentChainId: Viem.chainId.mainnet,
73
+ principal,
74
+ zones: new Map(Zones.chains.map((zone) => [zone.id, zone])),
75
+ }),
76
+ ).toStrictEqual([Zones.zoneMainnetInternal.id])
77
+ })
78
+
79
+ test('lets wildcard keys read every configured routable Zone of the parent chain', () => {
80
+ expect(
81
+ ZoneSelection.readableChainIds({
82
+ parentChainId: Viem.chainId.testnet,
83
+ principal: apiKeyPrincipal({ scopes: ['*'] }),
84
+ zones: new Map(Zones.chains.map((zone) => [zone.id, zone])),
85
+ }),
86
+ ).toStrictEqual([Zones.zoneModeratoInternal.id])
87
+ })
88
+
89
+ test('filters sandbox keys by each Zone parent chain', () => {
90
+ const principal = apiKeyPrincipal({
91
+ environment: 'sandbox',
92
+ scopes: [
93
+ 'data:read',
94
+ `zone:${Zones.zoneMainnetInternal.id}:read`,
95
+ `zone:${Zones.zoneModeratoInternal.id}:read`,
96
+ ],
97
+ })
98
+
99
+ expect(
100
+ ZoneSelection.readableChainIds({
101
+ parentChainId: Viem.chainId.testnet,
102
+ principal,
103
+ zones: new Map(Zones.chains.map((zone) => [zone.id, zone])),
104
+ }),
105
+ ).toStrictEqual([Zones.zoneModeratoInternal.id])
106
+ expect(
107
+ ZoneSelection.readableChainIds({
108
+ parentChainId: Viem.chainId.mainnet,
109
+ principal,
110
+ zones: new Map(Zones.chains.map((zone) => [zone.id, zone])),
111
+ }),
112
+ ).toStrictEqual([])
113
+ })
114
+
115
+ test('requires data read access and both upstreams', () => {
116
+ const zone = {
117
+ ...Zones.zoneModeratoInternal,
118
+ id: 1_424_310_099,
119
+ rpcUrls: { default: { http: ['https://zone.rpc.test'] } },
120
+ }
121
+ const zones = new Map([[zone.id, zone]])
122
+
123
+ expect(
124
+ ZoneSelection.readableChainIds({
125
+ parentChainId: zone.sourceId,
126
+ principal: apiKeyPrincipal({ scopes: [`zone:${zone.id}:read`] }),
127
+ zones,
128
+ }),
129
+ ).toStrictEqual([])
130
+ expect(
131
+ ZoneSelection.readableChainIds({
132
+ parentChainId: zone.sourceId,
133
+ principal: apiKeyPrincipal({ scopes: ['data:read', `zone:${zone.id}:read`] }),
134
+ zones,
135
+ }),
136
+ ).toStrictEqual([])
137
+ })
138
+ })
139
+
140
+ describe('uniqueMatch', () => {
141
+ test('selects one match after every Zone completes', () => {
142
+ expect(
143
+ ZoneSelection.uniqueMatch([
144
+ { chainId: 1, value: null },
145
+ { chainId: 2, value: 'receipt' },
146
+ ]),
147
+ ).toStrictEqual({ chainId: 2, kind: 'selected', value: 'receipt' })
148
+ })
149
+
150
+ test('distinguishes no match from ambiguous matches', () => {
151
+ expect(ZoneSelection.uniqueMatch([{ chainId: 1, value: null }])).toStrictEqual({
152
+ kind: 'not_found',
153
+ })
154
+ expect(
155
+ ZoneSelection.uniqueMatch([
156
+ { chainId: 1, value: 'first' },
157
+ { chainId: 2, value: 'second' },
158
+ ]),
159
+ ).toStrictEqual({ kind: 'ambiguous' })
160
+ })
161
+
162
+ test('fails the selection when any Zone lookup fails', () => {
163
+ const cause = new Error('unavailable')
164
+ expect(
165
+ ZoneSelection.uniqueMatch([
166
+ { chainId: 1, value: 'receipt' },
167
+ { cause, chainId: 2 },
168
+ ]),
169
+ ).toStrictEqual({ failures: [{ cause, chainId: 2 }], kind: 'failed' })
170
+ })
171
+ })
172
+
173
+ function apiKeyPrincipal(
174
+ options: apiKeyPrincipal.Options,
175
+ ): Extract<Auth.Principal, { type: 'api_key' }> {
176
+ const apiKey = ApiKey.schema.ApiKey.parse({
177
+ environment: options.environment,
178
+ id: 'key_test',
179
+ orgId: 'org_test',
180
+ scopes: options.scopes,
181
+ })
182
+ return {
183
+ apiKey,
184
+ environment: apiKey.environment,
185
+ id: apiKey.id,
186
+ orgId: apiKey.orgId,
187
+ type: 'api_key',
188
+ }
189
+ }
190
+
191
+ declare namespace apiKeyPrincipal {
192
+ type Options = {
193
+ environment?: 'production' | 'sandbox' | undefined
194
+ scopes: readonly string[]
195
+ }
196
+ }
@@ -0,0 +1,108 @@
1
+ import type { Chain } from 'viem'
2
+
3
+ import type * as Auth from '../../internal/Auth.js'
4
+ import * as Tidx from '../../internal/Tidx.js'
5
+ import * as Viem from '../../internal/Viem.js'
6
+ import * as Scope from '../../Scope.js'
7
+
8
+ /** Returns configured and routable Zones that an API key may read. */
9
+ export function readableChainIds(options: readableChainIds.Options): readonly number[] {
10
+ const { parentChainId, principal, zones } = options
11
+ const scopes = principal.apiKey.scopes
12
+ if (!scopes.includes(Scope.wildcard) && !scopes.includes('data:read')) return []
13
+
14
+ const chainIds = [...zones.values()].flatMap((zone) => {
15
+ if (zone.sourceId !== parentChainId) return []
16
+ const allowed =
17
+ scopes.includes(Scope.wildcard) ||
18
+ scopes.includes(`zone:${zone.id}:read`) ||
19
+ scopes.includes(`zone:${zone.id}:write`)
20
+ if (!allowed) return []
21
+ if (
22
+ principal.environment === 'sandbox' &&
23
+ (zone.sourceId === undefined || Viem.isMainnet(zone.sourceId))
24
+ )
25
+ return []
26
+
27
+ const context = { chainId: zone.id, principal, zone }
28
+ if (Viem.resolveRpc(options.rpc, context).url === undefined) return []
29
+ if (Tidx.resolve(options.tidx, context).baseUrl === undefined) return []
30
+ return [zone.id]
31
+ })
32
+ return chainIds.sort((a, b) => a - b)
33
+ }
34
+
35
+ export declare namespace readableChainIds {
36
+ /** Inputs for resolving the readable inferred-Zone set. */
37
+ type Options = {
38
+ /** Parent Tempo chain whose Zones may be selected. */
39
+ parentChainId: Viem.ChainId
40
+ /** Authenticated API-key principal selecting Zones. */
41
+ principal: Extract<Auth.Principal, { type: 'api_key' }>
42
+ /** RPC configuration used to exclude unroutable Zones. */
43
+ rpc?: Viem.getClient.Rpc | undefined
44
+ /** TIDX configuration used to exclude unroutable Zones. */
45
+ tidx?: Tidx.getClient.Tidx | undefined
46
+ /** Hosted Zone metadata keyed by chain id. */
47
+ zones: ReadonlyMap<number, Chain>
48
+ }
49
+ }
50
+
51
+ /** Resolves receipt probes without treating partial upstream results as complete. */
52
+ export function uniqueMatch<const value>(
53
+ probes: readonly uniqueMatch.Probe<value>[],
54
+ ): uniqueMatch.Result<value> {
55
+ const failures = probes.flatMap((probe) => ('cause' in probe ? [probe] : []))
56
+ if (failures.length > 0) return { failures, kind: 'failed' }
57
+
58
+ const matches = probes.flatMap((probe) =>
59
+ 'value' in probe && probe.value !== null
60
+ ? [{ chainId: probe.chainId, value: probe.value }]
61
+ : [],
62
+ )
63
+ if (matches.length === 0) return { kind: 'not_found' }
64
+ if (matches.length > 1) return { kind: 'ambiguous' }
65
+ return { ...matches[0]!, kind: 'selected' }
66
+ }
67
+
68
+ export declare namespace uniqueMatch {
69
+ /** One completed Zone lookup. */
70
+ type Probe<value> =
71
+ | {
72
+ /** Zone that completed the lookup. */
73
+ chainId: number
74
+ /** Matching value, or null when the Zone did not contain the resource. */
75
+ value: value | null
76
+ }
77
+ | {
78
+ /** Upstream failure from this Zone. */
79
+ cause: unknown
80
+ /** Zone that failed the lookup. */
81
+ chainId: number
82
+ }
83
+
84
+ /** Unique-match decision across every requested Zone. */
85
+ type Result<value> =
86
+ | {
87
+ /** Zone containing the unique match. */
88
+ chainId: number
89
+ /** Unique match result. */
90
+ kind: 'selected'
91
+ /** Value found in the selected Zone. */
92
+ value: value
93
+ }
94
+ | {
95
+ /** Every failed Zone lookup. */
96
+ failures: readonly Extract<Probe<value>, { cause: unknown }>[]
97
+ /** Partial failure result. */
98
+ kind: 'failed'
99
+ }
100
+ | {
101
+ /** Ambiguous match result. */
102
+ kind: 'ambiguous'
103
+ }
104
+ | {
105
+ /** No-match result. */
106
+ kind: 'not_found'
107
+ }
108
+ }