tapimo 0.1.0 → 0.3.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 (520) hide show
  1. package/README.md +57 -16
  2. package/dist/ApiKey.d.ts +4 -1
  3. package/dist/ApiKey.d.ts.map +1 -1
  4. package/dist/ApiKey.js +6 -2
  5. package/dist/ApiKey.js.map +1 -1
  6. package/dist/ApiKeys.d.ts +98 -3
  7. package/dist/ApiKeys.d.ts.map +1 -1
  8. package/dist/ApiKeys.js +150 -1
  9. package/dist/ApiKeys.js.map +1 -1
  10. package/dist/App.d.ts +7917 -2315
  11. package/dist/App.d.ts.map +1 -1
  12. package/dist/App.js +141 -329
  13. package/dist/App.js.map +1 -1
  14. package/dist/Scope.d.ts +20 -4
  15. package/dist/Scope.d.ts.map +1 -1
  16. package/dist/Scope.js +23 -4
  17. package/dist/Scope.js.map +1 -1
  18. package/dist/Webhooks.d.ts +2 -2
  19. package/dist/Webhooks.d.ts.map +1 -1
  20. package/dist/Webhooks.js +2 -2
  21. package/dist/Webhooks.js.map +1 -1
  22. package/dist/admin/App.d.ts +203 -120
  23. package/dist/admin/App.d.ts.map +1 -1
  24. package/dist/admin/apps/api-keys.d.ts +111 -6
  25. package/dist/admin/apps/api-keys.d.ts.map +1 -1
  26. package/dist/admin/apps/api-keys.js +67 -0
  27. package/dist/admin/apps/api-keys.js.map +1 -1
  28. package/dist/admin/apps/scopes.d.ts +12 -1
  29. package/dist/admin/apps/scopes.d.ts.map +1 -1
  30. package/dist/admin/apps/scopes.js +3 -0
  31. package/dist/admin/apps/scopes.js.map +1 -1
  32. package/dist/admin/apps/verified-tokens.d.ts +116 -116
  33. package/dist/admin/apps/verified-tokens.js +1 -1
  34. package/dist/admin/apps/verified-tokens.js.map +1 -1
  35. package/dist/admin/ui.generated.d.ts +1 -1
  36. package/dist/admin/ui.generated.js +13 -13
  37. package/dist/admin/ui.generated.js.map +1 -1
  38. package/dist/analytics/Analytics.d.ts +151 -0
  39. package/dist/analytics/Analytics.d.ts.map +1 -0
  40. package/dist/analytics/Analytics.js +212 -0
  41. package/dist/analytics/Analytics.js.map +1 -0
  42. package/dist/analytics/tables/requestEvents.d.ts +215 -0
  43. package/dist/analytics/tables/requestEvents.d.ts.map +1 -0
  44. package/dist/analytics/tables/requestEvents.js +264 -0
  45. package/dist/analytics/tables/requestEvents.js.map +1 -0
  46. package/dist/apps/data/App.d.ts +19576 -0
  47. package/dist/apps/data/App.d.ts.map +1 -0
  48. package/dist/apps/data/App.js +272 -0
  49. package/dist/apps/data/App.js.map +1 -0
  50. package/dist/apps/data/index.d.ts +3 -0
  51. package/dist/apps/data/index.d.ts.map +1 -0
  52. package/dist/apps/data/index.js +3 -0
  53. package/dist/apps/data/index.js.map +1 -0
  54. package/dist/apps/{activities.d.ts → data/routes/activities.d.ts} +32 -32
  55. package/dist/apps/{activities.d.ts.map → data/routes/activities.d.ts.map} +1 -1
  56. package/dist/apps/{activities.js → data/routes/activities.js} +13 -13
  57. package/dist/apps/data/routes/activities.js.map +1 -0
  58. package/dist/apps/{addresses.d.ts → data/routes/addresses.d.ts} +22 -22
  59. package/dist/apps/{addresses.d.ts.map → data/routes/addresses.d.ts.map} +1 -1
  60. package/dist/apps/{addresses.js → data/routes/addresses.js} +5 -5
  61. package/dist/apps/data/routes/addresses.js.map +1 -0
  62. package/dist/apps/{balances.d.ts → data/routes/balances.d.ts} +4 -4
  63. package/dist/apps/data/routes/balances.d.ts.map +1 -0
  64. package/dist/apps/{balances.js → data/routes/balances.js} +42 -11
  65. package/dist/apps/data/routes/balances.js.map +1 -0
  66. package/dist/apps/{blocks.d.ts → data/routes/blocks.d.ts} +47 -47
  67. package/dist/apps/data/routes/blocks.d.ts.map +1 -0
  68. package/dist/apps/{blocks.js → data/routes/blocks.js} +13 -13
  69. package/dist/apps/data/routes/blocks.js.map +1 -0
  70. package/dist/apps/{coingecko.d.ts → data/routes/coingecko.d.ts} +8 -8
  71. package/dist/apps/data/routes/coingecko.d.ts.map +1 -0
  72. package/dist/apps/{coingecko.js → data/routes/coingecko.js} +13 -13
  73. package/dist/apps/data/routes/coingecko.js.map +1 -0
  74. package/dist/apps/{exchanges.d.ts → data/routes/exchanges.d.ts} +108 -108
  75. package/dist/apps/data/routes/exchanges.d.ts.map +1 -0
  76. package/dist/apps/{exchanges.js → data/routes/exchanges.js} +19 -19
  77. package/dist/apps/data/routes/exchanges.js.map +1 -0
  78. package/dist/apps/{fee-amm.d.ts → data/routes/fee-amm.d.ts} +39 -39
  79. package/dist/apps/data/routes/fee-amm.d.ts.map +1 -0
  80. package/dist/apps/{fee-amm.js → data/routes/fee-amm.js} +17 -17
  81. package/dist/apps/data/routes/fee-amm.js.map +1 -0
  82. package/dist/apps/data/routes/funding.d.ts +765 -0
  83. package/dist/apps/data/routes/funding.d.ts.map +1 -0
  84. package/dist/apps/data/routes/funding.js +383 -0
  85. package/dist/apps/data/routes/funding.js.map +1 -0
  86. package/dist/apps/{indexer.d.ts → data/routes/indexer.d.ts} +4 -4
  87. package/dist/apps/data/routes/indexer.d.ts.map +1 -0
  88. package/dist/apps/{indexer.js → data/routes/indexer.js} +13 -9
  89. package/dist/apps/data/routes/indexer.js.map +1 -0
  90. package/dist/apps/{receipts.d.ts → data/routes/receipts.d.ts} +49 -49
  91. package/dist/apps/data/routes/receipts.d.ts.map +1 -0
  92. package/dist/apps/{receipts.js → data/routes/receipts.js} +14 -20
  93. package/dist/apps/data/routes/receipts.js.map +1 -0
  94. package/dist/apps/{rpc.d.ts → data/routes/rpc.d.ts} +33 -40
  95. package/dist/apps/data/routes/rpc.d.ts.map +1 -0
  96. package/dist/apps/{rpc.js → data/routes/rpc.js} +35 -7
  97. package/dist/apps/data/routes/rpc.js.map +1 -0
  98. package/dist/apps/{tokenlist.d.ts → data/routes/tokenlist.d.ts} +40 -40
  99. package/dist/apps/data/routes/tokenlist.d.ts.map +1 -0
  100. package/dist/apps/{tokenlist.js → data/routes/tokenlist.js} +8 -8
  101. package/dist/apps/data/routes/tokenlist.js.map +1 -0
  102. package/dist/apps/{tokens.d.ts → data/routes/tokens.d.ts} +468 -468
  103. package/dist/apps/data/routes/tokens.d.ts.map +1 -0
  104. package/dist/apps/{tokens.js → data/routes/tokens.js} +19 -19
  105. package/dist/apps/data/routes/tokens.js.map +1 -0
  106. package/dist/apps/{transactions.d.ts → data/routes/transactions.d.ts} +304 -304
  107. package/dist/apps/data/routes/transactions.d.ts.map +1 -0
  108. package/dist/apps/{transactions.js → data/routes/transactions.js} +13 -13
  109. package/dist/apps/data/routes/transactions.js.map +1 -0
  110. package/dist/apps/{transfers.d.ts → data/routes/transfers.d.ts} +62 -62
  111. package/dist/apps/data/routes/transfers.d.ts.map +1 -0
  112. package/dist/apps/{transfers.js → data/routes/transfers.js} +13 -13
  113. package/dist/apps/data/routes/transfers.js.map +1 -0
  114. package/dist/apps/{verified-tokens.d.ts → data/routes/verified-tokens.d.ts} +6 -6
  115. package/dist/apps/data/routes/verified-tokens.d.ts.map +1 -0
  116. package/dist/apps/{verified-tokens.js → data/routes/verified-tokens.js} +9 -9
  117. package/dist/apps/data/routes/verified-tokens.js.map +1 -0
  118. package/dist/apps/{webhooks.d.ts → data/routes/webhooks.d.ts} +17 -17
  119. package/dist/apps/{webhooks.d.ts.map → data/routes/webhooks.d.ts.map} +1 -1
  120. package/dist/apps/{webhooks.js → data/routes/webhooks.js} +38 -34
  121. package/dist/apps/data/routes/webhooks.js.map +1 -0
  122. package/dist/apps/docs/App.d.ts +29 -0
  123. package/dist/apps/docs/App.d.ts.map +1 -0
  124. package/dist/apps/docs/App.js +54 -0
  125. package/dist/apps/docs/App.js.map +1 -0
  126. package/dist/{internal/OpenApi.fonts.d.ts → apps/docs/fonts.d.ts} +1 -1
  127. package/dist/apps/docs/fonts.d.ts.map +1 -0
  128. package/dist/{internal/OpenApi.fonts.js → apps/docs/fonts.js} +1 -1
  129. package/dist/apps/docs/fonts.js.map +1 -0
  130. package/dist/apps/docs/index.d.ts +2 -0
  131. package/dist/apps/docs/index.d.ts.map +1 -0
  132. package/dist/apps/docs/index.js +2 -0
  133. package/dist/apps/docs/index.js.map +1 -0
  134. package/dist/{internal/OpenApi.logo.d.ts → apps/docs/logo.d.ts} +1 -1
  135. package/dist/apps/docs/logo.d.ts.map +1 -0
  136. package/dist/{internal/OpenApi.logo.js → apps/docs/logo.js} +1 -1
  137. package/dist/apps/docs/logo.js.map +1 -0
  138. package/dist/apps/docs/reference.d.ts +21 -0
  139. package/dist/apps/docs/reference.d.ts.map +1 -0
  140. package/dist/apps/docs/reference.js +112 -0
  141. package/dist/apps/docs/reference.js.map +1 -0
  142. package/dist/apps/index.d.ts +5 -0
  143. package/dist/apps/index.d.ts.map +1 -0
  144. package/dist/apps/index.js +5 -0
  145. package/dist/apps/index.js.map +1 -0
  146. package/dist/apps/mcp.d.ts +76 -0
  147. package/dist/apps/mcp.d.ts.map +1 -0
  148. package/dist/apps/mcp.js +188 -0
  149. package/dist/apps/mcp.js.map +1 -0
  150. package/dist/apps/metadata.d.ts +7 -0
  151. package/dist/apps/metadata.d.ts.map +1 -0
  152. package/dist/apps/metadata.js +15 -0
  153. package/dist/apps/metadata.js.map +1 -0
  154. package/dist/apps/platform/App.d.ts +5262 -0
  155. package/dist/apps/platform/App.d.ts.map +1 -0
  156. package/dist/apps/platform/App.js +84 -0
  157. package/dist/apps/platform/App.js.map +1 -0
  158. package/dist/apps/platform/Billing.d.ts +279 -0
  159. package/dist/apps/platform/Billing.d.ts.map +1 -0
  160. package/dist/apps/platform/Billing.js +477 -0
  161. package/dist/apps/platform/Billing.js.map +1 -0
  162. package/dist/apps/platform/index.d.ts +3 -0
  163. package/dist/apps/platform/index.d.ts.map +1 -0
  164. package/dist/apps/platform/index.js +3 -0
  165. package/dist/apps/platform/index.js.map +1 -0
  166. package/dist/apps/platform/routes/api-keys.d.ts +973 -0
  167. package/dist/apps/platform/routes/api-keys.d.ts.map +1 -0
  168. package/dist/apps/platform/routes/api-keys.js +430 -0
  169. package/dist/apps/platform/routes/api-keys.js.map +1 -0
  170. package/dist/apps/platform/routes/billing.d.ts +1520 -0
  171. package/dist/apps/platform/routes/billing.d.ts.map +1 -0
  172. package/dist/apps/platform/routes/billing.js +795 -0
  173. package/dist/apps/platform/routes/billing.js.map +1 -0
  174. package/dist/apps/platform/routes/invitations.d.ts +851 -0
  175. package/dist/apps/platform/routes/invitations.d.ts.map +1 -0
  176. package/dist/apps/platform/routes/invitations.js +471 -0
  177. package/dist/apps/platform/routes/invitations.js.map +1 -0
  178. package/dist/apps/platform/routes/me.d.ts +95 -0
  179. package/dist/apps/platform/routes/me.d.ts.map +1 -0
  180. package/dist/apps/platform/routes/me.js +81 -0
  181. package/dist/apps/platform/routes/me.js.map +1 -0
  182. package/dist/apps/platform/routes/members.d.ts +554 -0
  183. package/dist/apps/platform/routes/members.d.ts.map +1 -0
  184. package/dist/apps/platform/routes/members.js +251 -0
  185. package/dist/apps/platform/routes/members.js.map +1 -0
  186. package/dist/apps/platform/routes/orgs.d.ts +596 -0
  187. package/dist/apps/platform/routes/orgs.d.ts.map +1 -0
  188. package/dist/apps/platform/routes/orgs.js +276 -0
  189. package/dist/apps/platform/routes/orgs.js.map +1 -0
  190. package/dist/apps/platform/routes/projects.d.ts +740 -0
  191. package/dist/apps/platform/routes/projects.d.ts.map +1 -0
  192. package/dist/apps/platform/routes/projects.js +286 -0
  193. package/dist/apps/platform/routes/projects.js.map +1 -0
  194. package/dist/apps/platform/routes/scopes.d.ts +107 -0
  195. package/dist/apps/platform/routes/scopes.d.ts.map +1 -0
  196. package/dist/apps/platform/routes/scopes.js +66 -0
  197. package/dist/apps/platform/routes/scopes.js.map +1 -0
  198. package/dist/apps/platform/routes/usage.d.ts +588 -0
  199. package/dist/apps/platform/routes/usage.d.ts.map +1 -0
  200. package/dist/apps/platform/routes/usage.js +391 -0
  201. package/dist/apps/platform/routes/usage.js.map +1 -0
  202. package/dist/apps/relay/App.d.ts +44 -0
  203. package/dist/apps/relay/App.d.ts.map +1 -0
  204. package/dist/apps/relay/App.js +211 -0
  205. package/dist/apps/relay/App.js.map +1 -0
  206. package/dist/apps/relay/Sponsorships.d.ts +107 -0
  207. package/dist/apps/relay/Sponsorships.d.ts.map +1 -0
  208. package/dist/apps/relay/Sponsorships.js +194 -0
  209. package/dist/apps/relay/Sponsorships.js.map +1 -0
  210. package/dist/apps/relay/index.d.ts +3 -0
  211. package/dist/apps/relay/index.d.ts.map +1 -0
  212. package/dist/apps/relay/index.js +3 -0
  213. package/dist/apps/relay/index.js.map +1 -0
  214. package/dist/cli/Cli.d.ts +9 -2
  215. package/dist/cli/Cli.d.ts.map +1 -1
  216. package/dist/cli/Cli.js +12 -4
  217. package/dist/cli/Cli.js.map +1 -1
  218. package/dist/cli/commands/admin.d.ts +5 -1
  219. package/dist/cli/commands/admin.d.ts.map +1 -1
  220. package/dist/cli/commands/admin.js +82 -3
  221. package/dist/cli/commands/admin.js.map +1 -1
  222. package/dist/db/Db.d.ts +17 -0
  223. package/dist/db/Db.d.ts.map +1 -1
  224. package/dist/db/Db.js +254 -0
  225. package/dist/db/Db.js.map +1 -1
  226. package/dist/db/Schema.d.ts +159 -0
  227. package/dist/db/Schema.d.ts.map +1 -1
  228. package/dist/db/Schema.js +187 -2
  229. package/dist/db/Schema.js.map +1 -1
  230. package/dist/db/tables/billingSettings.d.ts +55 -0
  231. package/dist/db/tables/billingSettings.d.ts.map +1 -0
  232. package/dist/db/tables/billingSettings.js +70 -0
  233. package/dist/db/tables/billingSettings.js.map +1 -0
  234. package/dist/db/tables/invitations.d.ts +84 -0
  235. package/dist/db/tables/invitations.d.ts.map +1 -0
  236. package/dist/db/tables/invitations.js +165 -0
  237. package/dist/db/tables/invitations.js.map +1 -0
  238. package/dist/db/tables/memberships.d.ts +108 -0
  239. package/dist/db/tables/memberships.d.ts.map +1 -0
  240. package/dist/db/tables/memberships.js +153 -0
  241. package/dist/db/tables/memberships.js.map +1 -0
  242. package/dist/db/tables/organizations.d.ts +48 -0
  243. package/dist/db/tables/organizations.d.ts.map +1 -1
  244. package/dist/db/tables/organizations.js +97 -2
  245. package/dist/db/tables/organizations.js.map +1 -1
  246. package/dist/db/tables/projects.d.ts +65 -0
  247. package/dist/db/tables/projects.d.ts.map +1 -0
  248. package/dist/db/tables/projects.js +75 -0
  249. package/dist/db/tables/projects.js.map +1 -0
  250. package/dist/db/tables/requestUsage.d.ts +121 -0
  251. package/dist/db/tables/requestUsage.d.ts.map +1 -0
  252. package/dist/db/tables/requestUsage.js +150 -0
  253. package/dist/db/tables/requestUsage.js.map +1 -0
  254. package/dist/db/tables/sponsoredTransactions.d.ts +239 -0
  255. package/dist/db/tables/sponsoredTransactions.d.ts.map +1 -0
  256. package/dist/db/tables/sponsoredTransactions.js +314 -0
  257. package/dist/db/tables/sponsoredTransactions.js.map +1 -0
  258. package/dist/db/tables/stripeCustomers.d.ts +81 -0
  259. package/dist/db/tables/stripeCustomers.d.ts.map +1 -0
  260. package/dist/db/tables/stripeCustomers.js +120 -0
  261. package/dist/db/tables/stripeCustomers.js.map +1 -0
  262. package/dist/db/tables/users.d.ts +48 -0
  263. package/dist/db/tables/users.d.ts.map +1 -0
  264. package/dist/db/tables/users.js +65 -0
  265. package/dist/db/tables/users.js.map +1 -0
  266. package/dist/handlers/internal/executionError.d.ts.map +1 -1
  267. package/dist/handlers/internal/executionError.js +2 -0
  268. package/dist/handlers/internal/executionError.js.map +1 -1
  269. package/dist/handlers/internal/multisig.d.ts +2 -6
  270. package/dist/handlers/internal/multisig.d.ts.map +1 -1
  271. package/dist/handlers/internal/multisig.js +11 -36
  272. package/dist/handlers/internal/multisig.js.map +1 -1
  273. package/dist/handlers/internal/sponsorship.d.ts +35 -2
  274. package/dist/handlers/internal/sponsorship.d.ts.map +1 -1
  275. package/dist/handlers/internal/sponsorship.js +53 -14
  276. package/dist/handlers/internal/sponsorship.js.map +1 -1
  277. package/dist/handlers/internal/utils.d.ts +10 -3
  278. package/dist/handlers/internal/utils.d.ts.map +1 -1
  279. package/dist/handlers/internal/utils.js +14 -6
  280. package/dist/handlers/internal/utils.js.map +1 -1
  281. package/dist/handlers/relay.d.ts +6 -2
  282. package/dist/handlers/relay.d.ts.map +1 -1
  283. package/dist/handlers/relay.js +16 -2
  284. package/dist/handlers/relay.js.map +1 -1
  285. package/dist/index.d.ts +1 -0
  286. package/dist/index.d.ts.map +1 -1
  287. package/dist/index.js +1 -0
  288. package/dist/index.js.map +1 -1
  289. package/dist/internal/Auth.d.ts +222 -6
  290. package/dist/internal/Auth.d.ts.map +1 -1
  291. package/dist/internal/Auth.js +625 -74
  292. package/dist/internal/Auth.js.map +1 -1
  293. package/dist/internal/Cache.d.ts.map +1 -1
  294. package/dist/internal/Cache.js +4 -1
  295. package/dist/internal/Cache.js.map +1 -1
  296. package/dist/internal/EdgeCache.d.ts +10 -0
  297. package/dist/internal/EdgeCache.d.ts.map +1 -1
  298. package/dist/internal/EdgeCache.js +39 -8
  299. package/dist/internal/EdgeCache.js.map +1 -1
  300. package/dist/internal/Fees.d.ts +27 -0
  301. package/dist/internal/Fees.d.ts.map +1 -0
  302. package/dist/internal/Fees.js +48 -0
  303. package/dist/internal/Fees.js.map +1 -0
  304. package/dist/internal/FundingRoutes.d.ts +183 -0
  305. package/dist/internal/FundingRoutes.d.ts.map +1 -0
  306. package/dist/internal/FundingRoutes.js +490 -0
  307. package/dist/internal/FundingRoutes.js.map +1 -0
  308. package/dist/internal/Id.d.ts +15 -0
  309. package/dist/internal/Id.d.ts.map +1 -0
  310. package/dist/internal/Id.js +22 -0
  311. package/dist/internal/Id.js.map +1 -0
  312. package/dist/internal/Log.d.ts +9 -3
  313. package/dist/internal/Log.d.ts.map +1 -1
  314. package/dist/internal/Log.js +7 -0
  315. package/dist/internal/Log.js.map +1 -1
  316. package/dist/internal/OpenApi.d.ts +10 -20
  317. package/dist/internal/OpenApi.d.ts.map +1 -1
  318. package/dist/internal/OpenApi.js +8 -58
  319. package/dist/internal/OpenApi.js.map +1 -1
  320. package/dist/internal/RateLimit.d.ts +25 -0
  321. package/dist/internal/RateLimit.d.ts.map +1 -1
  322. package/dist/internal/RateLimit.js +51 -0
  323. package/dist/internal/RateLimit.js.map +1 -1
  324. package/dist/internal/Response.d.ts +1 -1
  325. package/dist/internal/Response.d.ts.map +1 -1
  326. package/dist/internal/Schema.d.ts +8 -0
  327. package/dist/internal/Schema.d.ts.map +1 -1
  328. package/dist/internal/Schema.js +7 -0
  329. package/dist/internal/Schema.js.map +1 -1
  330. package/dist/internal/Store.d.ts +7 -1
  331. package/dist/internal/Store.d.ts.map +1 -1
  332. package/dist/internal/Store.js +16 -2
  333. package/dist/internal/Store.js.map +1 -1
  334. package/dist/internal/Viem.d.ts +84 -0
  335. package/dist/internal/Viem.d.ts.map +1 -1
  336. package/dist/internal/Webhooks.d.ts +1 -1
  337. package/dist/internal/Webhooks.d.ts.map +1 -1
  338. package/dist/internal/Webhooks.js +3 -3
  339. package/dist/internal/Webhooks.js.map +1 -1
  340. package/package.json +33 -6
  341. package/src/ApiKey.ts +10 -2
  342. package/src/ApiKeys.test.ts +155 -1
  343. package/src/ApiKeys.ts +203 -1
  344. package/src/App.test.ts +64 -75741
  345. package/src/App.ts +218 -420
  346. package/src/Client.test-d.ts +657 -15
  347. package/src/Scope.ts +26 -4
  348. package/src/Webhooks.ts +2 -2
  349. package/src/admin/apps/api-keys.test.ts +51 -0
  350. package/src/admin/apps/api-keys.ts +84 -0
  351. package/src/admin/apps/scopes.test.ts +11 -1
  352. package/src/admin/apps/scopes.ts +3 -0
  353. package/src/admin/apps/verified-tokens.ts +1 -1
  354. package/src/admin/ui/src/components/Page.tsx +2 -3
  355. package/src/admin/ui/src/routes/__root.tsx +2 -2
  356. package/src/admin/ui/src/routes/api-keys.tsx +2 -2
  357. package/src/admin/ui.generated.ts +13 -13
  358. package/src/analytics/Analytics.test.ts +527 -0
  359. package/src/analytics/Analytics.ts +318 -0
  360. package/src/analytics/tables/requestEvents.ts +523 -0
  361. package/src/apps/composition.test.ts +66 -0
  362. package/src/apps/data/App.test.ts +72 -0
  363. package/src/apps/data/App.ts +330 -0
  364. package/src/apps/data/index.ts +2 -0
  365. package/src/apps/{activities.test.ts → data/routes/activities.test.ts} +3 -3
  366. package/src/apps/{activities.ts → data/routes/activities.ts} +15 -15
  367. package/src/apps/{addresses.ts → data/routes/addresses.ts} +6 -6
  368. package/src/apps/{balances.test.ts → data/routes/balances.test.ts} +2 -2
  369. package/src/apps/{balances.ts → data/routes/balances.ts} +46 -12
  370. package/src/apps/{blocks.test.ts → data/routes/blocks.test.ts} +3 -3
  371. package/src/apps/{blocks.ts → data/routes/blocks.ts} +14 -14
  372. package/src/apps/{coingecko.test.ts → data/routes/coingecko.test.ts} +2 -2
  373. package/src/apps/{coingecko.ts → data/routes/coingecko.ts} +14 -14
  374. package/src/apps/{exchanges.test.ts → data/routes/exchanges.test.ts} +1 -1
  375. package/src/apps/{exchanges.ts → data/routes/exchanges.ts} +20 -20
  376. package/src/apps/{fee-amm.test.ts → data/routes/fee-amm.test.ts} +3 -3
  377. package/src/apps/{fee-amm.ts → data/routes/fee-amm.ts} +18 -18
  378. package/src/apps/data/routes/funding.test.ts +214 -0
  379. package/src/apps/data/routes/funding.ts +584 -0
  380. package/src/apps/{indexer.test.ts → data/routes/indexer.test.ts} +26 -5
  381. package/src/apps/{indexer.ts → data/routes/indexer.ts} +13 -10
  382. package/src/apps/{receipts.test.ts → data/routes/receipts.test.ts} +3 -3
  383. package/src/apps/{receipts.ts → data/routes/receipts.ts} +15 -22
  384. package/src/apps/{rpc.test.ts → data/routes/rpc.test.ts} +122 -7
  385. package/src/apps/{rpc.ts → data/routes/rpc.ts} +38 -8
  386. package/src/apps/{tokenlist.test.ts → data/routes/tokenlist.test.ts} +3 -3
  387. package/src/apps/{tokenlist.ts → data/routes/tokenlist.ts} +9 -9
  388. package/src/apps/{tokens.test.ts → data/routes/tokens.test.ts} +2 -2
  389. package/src/apps/{tokens.ts → data/routes/tokens.ts} +20 -20
  390. package/src/apps/{transactions.test.ts → data/routes/transactions.test.ts} +3 -3
  391. package/src/apps/{transactions.ts → data/routes/transactions.ts} +15 -15
  392. package/src/apps/{transfers.test.ts → data/routes/transfers.test.ts} +2 -2
  393. package/src/apps/{transfers.ts → data/routes/transfers.ts} +15 -15
  394. package/src/apps/{verified-tokens.test.ts → data/routes/verified-tokens.test.ts} +3 -3
  395. package/src/apps/{verified-tokens.ts → data/routes/verified-tokens.ts} +10 -10
  396. package/src/apps/{webhooks.test.ts → data/routes/webhooks.test.ts} +7 -7
  397. package/src/apps/{webhooks.ts → data/routes/webhooks.ts} +50 -43
  398. package/src/apps/docs/App.ts +65 -0
  399. package/src/apps/docs/index.ts +1 -0
  400. package/src/apps/docs/reference.ts +132 -0
  401. package/src/apps/index.ts +4 -0
  402. package/src/apps/mcp.test.ts +206 -0
  403. package/src/apps/mcp.ts +250 -0
  404. package/src/apps/metadata.ts +23 -0
  405. package/src/apps/platform/App.ts +169 -0
  406. package/src/apps/platform/Billing.test.ts +530 -0
  407. package/src/apps/platform/Billing.ts +682 -0
  408. package/src/apps/platform/index.ts +2 -0
  409. package/src/apps/platform/routes/api-keys.test.ts +493 -0
  410. package/src/apps/platform/routes/api-keys.ts +543 -0
  411. package/src/apps/platform/routes/billing.test.ts +1100 -0
  412. package/src/apps/platform/routes/billing.ts +966 -0
  413. package/src/apps/platform/routes/invitations.test.ts +409 -0
  414. package/src/apps/platform/routes/invitations.ts +587 -0
  415. package/src/apps/platform/routes/me.test.ts +351 -0
  416. package/src/apps/platform/routes/me.ts +106 -0
  417. package/src/apps/platform/routes/members.test.ts +195 -0
  418. package/src/apps/platform/routes/members.ts +313 -0
  419. package/src/apps/platform/routes/orgs.test.ts +313 -0
  420. package/src/apps/platform/routes/orgs.ts +365 -0
  421. package/src/apps/platform/routes/projects.test.ts +181 -0
  422. package/src/apps/platform/routes/projects.ts +367 -0
  423. package/src/apps/platform/routes/scopes.test.ts +29 -0
  424. package/src/apps/platform/routes/scopes.ts +85 -0
  425. package/src/apps/platform/routes/usage.test.ts +422 -0
  426. package/src/apps/platform/routes/usage.ts +527 -0
  427. package/src/apps/relay/App.test.ts +933 -0
  428. package/src/apps/relay/App.ts +236 -0
  429. package/src/apps/relay/Sponsorships.test.ts +375 -0
  430. package/src/apps/relay/Sponsorships.ts +306 -0
  431. package/src/apps/relay/index.ts +2 -0
  432. package/src/cli/Cli.test.ts +25 -2
  433. package/src/cli/Cli.ts +18 -3
  434. package/src/cli/commands/admin.test.ts +83 -0
  435. package/src/cli/commands/admin.ts +91 -3
  436. package/src/db/Db.ts +296 -0
  437. package/src/db/Schema.ts +241 -2
  438. package/src/db/tables/billingSettings.test.ts +87 -0
  439. package/src/db/tables/billingSettings.ts +108 -0
  440. package/src/db/tables/invitations.ts +198 -0
  441. package/src/db/tables/memberships.ts +208 -0
  442. package/src/db/tables/organizations.test.ts +38 -2
  443. package/src/db/tables/organizations.ts +117 -2
  444. package/src/db/tables/projects.ts +107 -0
  445. package/src/db/tables/requestUsage.ts +231 -0
  446. package/src/db/tables/sponsoredTransactions.test.ts +325 -0
  447. package/src/db/tables/sponsoredTransactions.ts +464 -0
  448. package/src/db/tables/stripeCustomers.test.ts +109 -0
  449. package/src/db/tables/stripeCustomers.ts +162 -0
  450. package/src/db/tables/users.ts +85 -0
  451. package/src/handlers/internal/executionError.ts +2 -0
  452. package/src/handlers/internal/multisig.test.ts +84 -10
  453. package/src/handlers/internal/multisig.ts +15 -50
  454. package/src/handlers/internal/sponsorship.ts +106 -20
  455. package/src/handlers/internal/utils.ts +19 -7
  456. package/src/handlers/{internal/relay.localnet.test.ts → relay.test.ts} +2 -2
  457. package/src/handlers/relay.ts +23 -5
  458. package/src/index.ts +1 -0
  459. package/src/internal/Auth.test.ts +491 -25
  460. package/src/internal/Auth.ts +839 -84
  461. package/src/internal/Cache.ts +5 -1
  462. package/src/internal/Cursor.test.ts +3 -2
  463. package/src/internal/EdgeCache.test.ts +27 -4
  464. package/src/internal/EdgeCache.ts +47 -9
  465. package/src/internal/Fees.test.ts +32 -0
  466. package/src/internal/Fees.ts +51 -0
  467. package/src/internal/FundingRoutes.ts +583 -0
  468. package/src/internal/Id.test.ts +17 -0
  469. package/src/internal/Id.ts +24 -0
  470. package/src/internal/Log.test.ts +2 -1
  471. package/src/internal/Log.ts +16 -3
  472. package/src/internal/MetricSink.ts +1 -1
  473. package/src/internal/OpenApi.ts +12 -60
  474. package/src/internal/RateLimit.test.ts +84 -0
  475. package/src/internal/RateLimit.ts +70 -0
  476. package/src/internal/Response.ts +1 -1
  477. package/src/internal/Schema.ts +8 -0
  478. package/src/internal/Store.test.ts +52 -0
  479. package/src/internal/Store.ts +24 -5
  480. package/src/internal/Tidx.local.test.ts +1 -1
  481. package/src/internal/VerifiedTokens.test.ts +1 -1
  482. package/src/internal/WebhookDestination.test.ts +1 -1
  483. package/src/internal/Webhooks.test.ts +7 -7
  484. package/src/internal/Webhooks.ts +4 -4
  485. package/dist/apps/activities.js.map +0 -1
  486. package/dist/apps/addresses.js.map +0 -1
  487. package/dist/apps/balances.d.ts.map +0 -1
  488. package/dist/apps/balances.js.map +0 -1
  489. package/dist/apps/blocks.d.ts.map +0 -1
  490. package/dist/apps/blocks.js.map +0 -1
  491. package/dist/apps/coingecko.d.ts.map +0 -1
  492. package/dist/apps/coingecko.js.map +0 -1
  493. package/dist/apps/exchanges.d.ts.map +0 -1
  494. package/dist/apps/exchanges.js.map +0 -1
  495. package/dist/apps/fee-amm.d.ts.map +0 -1
  496. package/dist/apps/fee-amm.js.map +0 -1
  497. package/dist/apps/indexer.d.ts.map +0 -1
  498. package/dist/apps/indexer.js.map +0 -1
  499. package/dist/apps/receipts.d.ts.map +0 -1
  500. package/dist/apps/receipts.js.map +0 -1
  501. package/dist/apps/rpc.d.ts.map +0 -1
  502. package/dist/apps/rpc.js.map +0 -1
  503. package/dist/apps/tokenlist.d.ts.map +0 -1
  504. package/dist/apps/tokenlist.js.map +0 -1
  505. package/dist/apps/tokens.d.ts.map +0 -1
  506. package/dist/apps/tokens.js.map +0 -1
  507. package/dist/apps/transactions.d.ts.map +0 -1
  508. package/dist/apps/transactions.js.map +0 -1
  509. package/dist/apps/transfers.d.ts.map +0 -1
  510. package/dist/apps/transfers.js.map +0 -1
  511. package/dist/apps/verified-tokens.d.ts.map +0 -1
  512. package/dist/apps/verified-tokens.js.map +0 -1
  513. package/dist/apps/webhooks.js.map +0 -1
  514. package/dist/internal/OpenApi.fonts.d.ts.map +0 -1
  515. package/dist/internal/OpenApi.fonts.js.map +0 -1
  516. package/dist/internal/OpenApi.logo.d.ts.map +0 -1
  517. package/dist/internal/OpenApi.logo.js.map +0 -1
  518. package/src/handlers/internal/multisig.localnet.test.ts +0 -146
  519. /package/src/{internal/OpenApi.fonts.ts → apps/docs/fonts.ts} +0 -0
  520. /package/src/{internal/OpenApi.logo.ts → apps/docs/logo.ts} +0 -0
@@ -1,11 +1,11 @@
1
1
  import { type Db, Webhooks as Core } from 'tapimo'
2
2
 
3
- import * as Tidx from '../internal/Tidx.js'
4
- import * as Viem from '../internal/Viem.js'
5
- import * as TestApp from '../../test/App.js'
6
- import * as Mppx from '../../test/Mppx.js'
7
- import * as Runtime from '../../test/runtime.js'
8
- import * as Tempo from '../../test/Tempo.js'
3
+ import * as Tidx from '../../../internal/Tidx.js'
4
+ import * as Viem from '../../../internal/Viem.js'
5
+ import * as TestApp from '../../../../test/App.js'
6
+ import * as Mppx from '../../../../test/Mppx.js'
7
+ import * as Runtime from '../../../../test/runtime.js'
8
+ import * as Tempo from '../../../../test/Tempo.js'
9
9
  import * as Webhooks from './webhooks.js'
10
10
 
11
11
  /** API key with both webhook scopes, owned by `org_test`. */
@@ -1151,7 +1151,7 @@ describe.skipIf(Runtime.get().mode === 'localnet')('poll', () => {
1151
1151
  // the real keyset/`toBlock` SQL and decode path end to end — no fabricated rows.
1152
1152
  const realTidx = Tidx.getClient({
1153
1153
  chainId: 42431,
1154
- tidx: { baseUrl: 'https://tidx.tempo.xyz', basicAuth: process.env.VITE_TIDX_BASIC_AUTH },
1154
+ tidx: { baseUrl: 'https://tidx.tempo.xyz', basicAuth: process.env.TIDX_BASIC_AUTH },
1155
1155
  })
1156
1156
  // The monitoring scanners (`log:emitted`/`block:created`/`transaction:included`)
1157
1157
  // read the same immutable historical window over real RPC (chain 42431 →
@@ -2,20 +2,20 @@ import { type Context, Hono } from 'hono'
2
2
  import { type AbiEvent, parseAbiItem } from 'viem'
3
3
  import * as z from 'zod/mini'
4
4
 
5
- import type * as App from '../App.js'
6
- import * as Auth from '../internal/Auth.js'
7
- import * as Cache from '../internal/Cache.js'
8
- import * as Cursor from '../internal/Cursor.js'
9
- import * as Db from '../db/Db.js'
10
- import * as OpenApi from '../internal/OpenApi.js'
11
- import * as Response from '../internal/Response.js'
12
- import * as Schema from '../internal/Schema.js'
13
- import * as Store from '../internal/Store.js'
14
- import type * as Tidx from '../internal/Tidx.js'
15
- import * as Ttl from '../internal/Ttl.js'
16
- import * as Value from '../internal/Value.js'
17
- import type * as Viem from '../internal/Viem.js'
18
- import * as Webhooks from '../internal/Webhooks.js'
5
+ import type * as App from '../../../App.js'
6
+ import * as Auth from '../../../internal/Auth.js'
7
+ import * as Cache from '../../../internal/Cache.js'
8
+ import * as Cursor from '../../../internal/Cursor.js'
9
+ import * as Db from '../../../db/Db.js'
10
+ import * as OpenApi from '../../../internal/OpenApi.js'
11
+ import * as Response from '../../../internal/Response.js'
12
+ import * as Schema from '../../../internal/Schema.js'
13
+ import * as Store from '../../../internal/Store.js'
14
+ import type * as Tidx from '../../../internal/Tidx.js'
15
+ import * as Ttl from '../../../internal/Ttl.js'
16
+ import * as Value from '../../../internal/Value.js'
17
+ import type * as Viem from '../../../internal/Viem.js'
18
+ import * as Webhooks from '../../../internal/Webhooks.js'
19
19
  import * as Receipts from './receipts.js'
20
20
  import * as Transactions from './transactions.js'
21
21
  import * as Transfers from './transfers.js'
@@ -378,7 +378,7 @@ export namespace schema {
378
378
  .record(z.string(), z.unknown())
379
379
  .check(
380
380
  z.describe(
381
- 'Match decoded event arguments by name (indexed or non-indexed). Requires `signature`. Each value is an exact value or an operator object.',
381
+ 'Match decoded event arguments by name (indexed or non-indexed). Requires `signature`. Each value is an exact value or a super admin object.',
382
382
  ),
383
383
  z.meta({ examples: [{ to: '0x9e39034aae71fb89f66061a2602eb6efec271754' }] }),
384
384
  ),
@@ -533,7 +533,7 @@ export namespace schema {
533
533
  .string()
534
534
  .check(
535
535
  z.describe('Webhook subscription ID (`wh_…`).'),
536
- z.meta({ examples: ['wh_abc123'] }),
536
+ z.meta({ examples: ['wh_001718668800000_2ZPE2gvateYEQ0dQslgvkhjx'] }),
537
537
  ),
538
538
  lastDeliveryAt: z
539
539
  .optional(z.iso.datetime())
@@ -594,7 +594,10 @@ export namespace schema {
594
594
  ),
595
595
  id: z
596
596
  .string()
597
- .check(z.describe('Webhook delivery ID (`whd_…`).'), z.meta({ examples: ['whd_abc123'] })),
597
+ .check(
598
+ z.describe('Webhook delivery ID (`whd_…`).'),
599
+ z.meta({ examples: ['whd_001718668800000_C1yJkk7CuML98HFthEDk9PsY'] }),
600
+ ),
598
601
  requestUrl: z
599
602
  .string()
600
603
  .check(
@@ -620,7 +623,7 @@ export namespace schema {
620
623
  .string()
621
624
  .check(
622
625
  z.describe('Subscription ID (`wh_…`) this delivery belongs to.'),
623
- z.meta({ examples: ['wh_abc123'] }),
626
+ z.meta({ examples: ['wh_001718668800000_2ZPE2gvateYEQ0dQslgvkhjx'] }),
624
627
  ),
625
628
  })
626
629
  .check(z.describe('One attempt by Tempo to deliver an event to your webhook URL.'))
@@ -901,7 +904,7 @@ export namespace schema {
901
904
  .string()
902
905
  .check(
903
906
  z.describe('Subscription ID (`wh_…`) that produced this delivery.'),
904
- z.meta({ examples: ['wh_abc123'] }),
907
+ z.meta({ examples: ['wh_001718668800000_2ZPE2gvateYEQ0dQslgvkhjx'] }),
905
908
  ),
906
909
  }
907
910
 
@@ -1075,7 +1078,7 @@ export namespace schema {
1075
1078
  .string()
1076
1079
  .check(
1077
1080
  z.describe('Webhook subscription ID (`wh_…`).'),
1078
- z.meta({ examples: ['wh_001718668800000_V1StGXR8Z5jdHi6B2myTq'] }),
1081
+ z.meta({ examples: ['wh_001718668800000_2ZPE2gvateYEQ0dQslgvkhjx'] }),
1079
1082
  ),
1080
1083
  })
1081
1084
  .check(z.describe('Path parameters for a webhook subscription request.'))
@@ -1158,13 +1161,13 @@ export namespace schema {
1158
1161
  .string()
1159
1162
  .check(
1160
1163
  z.describe('Delivery ID (`whd_…`) you want Tempo to replay.'),
1161
- z.meta({ examples: ['whd_001718668800000_8oQ2pVmZ4kKxWnLcRfTbN'] }),
1164
+ z.meta({ examples: ['whd_001718668800000_C1yJkk7CuML98HFthEDk9PsY'] }),
1162
1165
  ),
1163
1166
  id: z
1164
1167
  .string()
1165
1168
  .check(
1166
1169
  z.describe('Webhook subscription ID (`wh_…`).'),
1167
- z.meta({ examples: ['wh_001718668800000_V1StGXR8Z5jdHi6B2myTq'] }),
1170
+ z.meta({ examples: ['wh_001718668800000_2ZPE2gvateYEQ0dQslgvkhjx'] }),
1168
1171
  ),
1169
1172
  })
1170
1173
  .check(z.describe('Path parameters for retrying a webhook delivery.'))
@@ -1209,7 +1212,7 @@ export namespace schema {
1209
1212
  .string()
1210
1213
  .check(
1211
1214
  z.describe('ID of the webhook subscription that was deleted.'),
1212
- z.meta({ examples: ['wh_abc123'] }),
1215
+ z.meta({ examples: ['wh_001718668800000_2ZPE2gvateYEQ0dQslgvkhjx'] }),
1213
1216
  ),
1214
1217
  })
1215
1218
  .check(z.describe('Confirmation that the webhook subscription was deleted.'))
@@ -1225,21 +1228,25 @@ export namespace schema {
1225
1228
  */
1226
1229
  export function webhooks(options: webhooks.Options = {}) {
1227
1230
  const hidden = !options.enabled
1228
- return (
1229
- new Hono<App.Environment>()
1230
- .use('*', async (c, next) => {
1231
- // Gate the whole resource on a configured state store. Without it the
1232
- // outbound-HTTP surface is disabled (read-only deployment).
1233
- if (!c.get('webhook')) return notEnabled(c) as never
1231
+ // Gate the whole resource on a configured state store. Without it the
1232
+ // outbound-HTTP surface is disabled (read-only deployment).
1233
+ const gate = async (c: Context<App.Environment>, next: () => Promise<void>) => {
1234
+ if (!c.get('webhook')) return notEnabled(c) as never
1234
1235
 
1235
- await next()
1236
+ await next()
1236
1237
 
1237
- // Subscriptions are principal-scoped, mutating, and stateful: never cache.
1238
- if (!c.res.headers.has('Cache-Control')) c.res.headers.set('Cache-Control', 'no-store')
1239
- return
1240
- })
1238
+ // Subscriptions are principal-scoped, mutating, and stateful: never cache.
1239
+ if (!c.res.headers.has('Cache-Control')) c.res.headers.set('Cache-Control', 'no-store')
1240
+ return
1241
+ }
1242
+ return (
1243
+ new Hono<App.Environment>()
1244
+ // `/v1/webhooks/*` does not match the collection root, so it gets its
1245
+ // own registration.
1246
+ .use('/v1/webhooks', gate)
1247
+ .use('/v1/webhooks/*', gate)
1241
1248
  .get(
1242
- '/event-types',
1249
+ '/v1/webhooks/event-types',
1243
1250
  Auth.policy({ apiKey: { scopes: ['data:read'] }, mpp: true, public: true }),
1244
1251
  OpenApi.describeRoute({
1245
1252
  description: 'See which onchain event types Tempo can POST to your webhook URL.',
@@ -1275,7 +1282,7 @@ export function webhooks(options: webhooks.Options = {}) {
1275
1282
  },
1276
1283
  )
1277
1284
  .post(
1278
- '/',
1285
+ '/v1/webhooks',
1279
1286
  Auth.policy({ apiKey: { scopes: ['webhooks:write'] } }),
1280
1287
  OpenApi.validate('json', schema.createWebhook.Body, {
1281
1288
  code: 'body_invalid',
@@ -1338,7 +1345,7 @@ export function webhooks(options: webhooks.Options = {}) {
1338
1345
  },
1339
1346
  )
1340
1347
  .get(
1341
- '/',
1348
+ '/v1/webhooks',
1342
1349
  Auth.policy({ apiKey: { scopes: ['webhooks:read'] } }),
1343
1350
  OpenApi.validate('query', schema.listWebhooks.Query, {
1344
1351
  code: 'query_invalid',
@@ -1412,7 +1419,7 @@ export function webhooks(options: webhooks.Options = {}) {
1412
1419
  // constraint, this API-key-only route's policy would be collected for the
1413
1420
  // event-types request and override its (intentionally public) access.
1414
1421
  .get(
1415
- '/:id{wh_[A-Za-z0-9_-]+}',
1422
+ '/v1/webhooks/:id{wh_[A-Za-z0-9_-]+}',
1416
1423
  Auth.policy({ apiKey: { scopes: ['webhooks:read'] } }),
1417
1424
  OpenApi.validate('param', schema.getWebhook.Params, {
1418
1425
  code: 'param_invalid',
@@ -1464,7 +1471,7 @@ export function webhooks(options: webhooks.Options = {}) {
1464
1471
  },
1465
1472
  )
1466
1473
  .get(
1467
- '/:id{wh_[A-Za-z0-9_-]+}/deliveries',
1474
+ '/v1/webhooks/:id{wh_[A-Za-z0-9_-]+}/deliveries',
1468
1475
  Auth.policy({ apiKey: { scopes: ['webhooks:read'] } }),
1469
1476
  OpenApi.validate('param', schema.listWebhookDeliveries.Params, {
1470
1477
  code: 'param_invalid',
@@ -1555,7 +1562,7 @@ export function webhooks(options: webhooks.Options = {}) {
1555
1562
  },
1556
1563
  )
1557
1564
  .post(
1558
- '/:id{wh_[A-Za-z0-9_-]+}/ping',
1565
+ '/v1/webhooks/:id{wh_[A-Za-z0-9_-]+}/ping',
1559
1566
  Auth.policy({ apiKey: { scopes: ['webhooks:write'] } }),
1560
1567
  OpenApi.validate('param', schema.pingWebhook.Params, {
1561
1568
  code: 'param_invalid',
@@ -1620,7 +1627,7 @@ export function webhooks(options: webhooks.Options = {}) {
1620
1627
  },
1621
1628
  )
1622
1629
  .post(
1623
- '/:id{wh_[A-Za-z0-9_-]+}/deliveries/:deliveryId/retry',
1630
+ '/v1/webhooks/:id{wh_[A-Za-z0-9_-]+}/deliveries/:deliveryId/retry',
1624
1631
  Auth.policy({ apiKey: { scopes: ['webhooks:write'] } }),
1625
1632
  OpenApi.validate('param', schema.retryWebhookDelivery.Params, {
1626
1633
  code: 'param_invalid',
@@ -1691,7 +1698,7 @@ export function webhooks(options: webhooks.Options = {}) {
1691
1698
  },
1692
1699
  )
1693
1700
  .patch(
1694
- '/:id{wh_[A-Za-z0-9_-]+}',
1701
+ '/v1/webhooks/:id{wh_[A-Za-z0-9_-]+}',
1695
1702
  Auth.policy({ apiKey: { scopes: ['webhooks:write'] } }),
1696
1703
  OpenApi.validate('param', schema.updateWebhook.Params, {
1697
1704
  code: 'param_invalid',
@@ -1763,7 +1770,7 @@ export function webhooks(options: webhooks.Options = {}) {
1763
1770
  },
1764
1771
  )
1765
1772
  .delete(
1766
- '/:id{wh_[A-Za-z0-9_-]+}',
1773
+ '/v1/webhooks/:id{wh_[A-Za-z0-9_-]+}',
1767
1774
  Auth.policy({ apiKey: { scopes: ['webhooks:write'] } }),
1768
1775
  OpenApi.validate('param', schema.deleteWebhook.Params, {
1769
1776
  code: 'param_invalid',
@@ -0,0 +1,65 @@
1
+ import type { Context } from 'hono'
2
+ import { Hono } from 'hono'
3
+ import type { Handler as vocs_Handler } from 'vocs/server'
4
+
5
+ import type * as App from '../../App.js'
6
+ import * as Metadata from '../metadata.js'
7
+
8
+ /**
9
+ * The docs route group: the Vocs API reference served at the app root.
10
+ *
11
+ * ```ts
12
+ * import { docs } from 'tapimo/docs'
13
+ * App.create(options).route('/', data()).route('/', platform()).route('/', docs())
14
+ * ```
15
+ *
16
+ * The group registers no routes itself: it carries a reference factory (via
17
+ * {@link Metadata}) that `App.create` mounts on finalize, after every group and
18
+ * the OpenAPI/OpenRPC documents — so the reference always renders the full
19
+ * composed surface and its catch-all stays behind API routes, wherever the
20
+ * group sits in the composition chain.
21
+ *
22
+ * Lives in the `tapimo/docs` subpath (never re-exported from `tapimo/apps`) so
23
+ * the Vocs renderer and its multi-MB icon/font data are bundled only by
24
+ * deployments that actually serve docs. Even then the renderer loads lazily on
25
+ * the first docs request (see `reference.ts`), so API traffic and isolate
26
+ * startup never pay for it.
27
+ */
28
+ export function docs(options: docs.Options = {}) {
29
+ return Metadata.attach(new Hono<App.Environment>(), {
30
+ docs: ({ spec }) => {
31
+ // Memoized across requests: all docs traffic shares one handler.
32
+ let handler: Promise<Hono> | undefined
33
+ return new Hono<App.Environment>().get('*', async (c, next) => {
34
+ handler ??= import('./reference.js').then((m) =>
35
+ m.create({ mount: mountFromRoutePath(c.req.routePath), spec, vocs: options }),
36
+ )
37
+ const response = await (await handler).fetch(c.req.raw, c.env, executionCtx(c))
38
+ // Inner 404 means "not a docs route" (`fallback: 'next'` semantics):
39
+ // defer to the host app's later routes / JSON `notFound`.
40
+ if (response.status === 404) return next()
41
+ return response
42
+ })
43
+ },
44
+ })
45
+ }
46
+
47
+ export declare namespace docs {
48
+ /** Vocs API reference options (theme, top navigation, logo, socials, …). */
49
+ type Options = NonNullable<Parameters<typeof vocs_Handler.openApi>[0]['vocs']>
50
+ }
51
+
52
+ /** Derives the host mount prefix from Hono's matched `routePath` (`/api/*` → `/api`, `/*` → ``). */
53
+ function mountFromRoutePath(routePath: string) {
54
+ return routePath.replace(/\*+$/, '').replace(/\/+$/, '')
55
+ }
56
+
57
+ // `c.executionCtx` throws outside Workers (tests, Node); docs rendering never
58
+ // uses `waitUntil`, so absence is fine.
59
+ function executionCtx(c: Context) {
60
+ try {
61
+ return c.executionCtx
62
+ } catch {
63
+ return undefined
64
+ }
65
+ }
@@ -0,0 +1 @@
1
+ export { docs } from './App.js'
@@ -0,0 +1,132 @@
1
+ import { Hono } from 'hono'
2
+ import { Handler as vocs_Handler } from 'vocs/server'
3
+
4
+ import type * as App from '../../App.js'
5
+ import openrpcSpec from '../../openrpc.json' with { type: 'json' }
6
+ import type { docs } from './App.js'
7
+ import { pilatFontFaces } from './fonts.js'
8
+ import { logoUrl } from './logo.js'
9
+
10
+ /**
11
+ * Builds the Vocs reference handler. Loaded via dynamic import on the first
12
+ * docs request (see `docs()` in `App.ts`), keeping the multi-MB renderer off
13
+ * isolate startup.
14
+ */
15
+ export function create(options: create.Options): Hono {
16
+ const { mount, spec, vocs } = options
17
+ const handler = vocs_Handler.openApi(
18
+ {
19
+ // Inline the OpenRPC doc so vocs expands it without a self-subrequest
20
+ // (see `inlineOpenrpc`); the public `/openapi.json` keeps the URL ref.
21
+ spec: () => spec().then(inlineOpenrpc),
22
+ sidebar: { collapsed: true },
23
+ vocs: { logoUrl, title: 'Tempo API Reference', ...vocs },
24
+ },
25
+ { css, fallback: 'next' },
26
+ )
27
+ if (!mount) return handler
28
+ // Re-mount under the host prefix so the handler's `routePath`-derived mount
29
+ // (asset link bases, known-route checks) matches a direct `.route()` mount.
30
+ return new Hono().route(mount, handler)
31
+ }
32
+
33
+ export declare namespace create {
34
+ /** Options for building the reference handler. */
35
+ type Options = {
36
+ /** Host mount prefix derived from the wrapper's matched `routePath` (`''` at root). */
37
+ mount: string
38
+ /** Memoized OpenAPI document builder — the same document served at `/openapi.json`. */
39
+ spec: App.create.DocsContext['spec']
40
+ /** Vocs reference options (theme, top navigation, logo, socials, …). */
41
+ vocs: docs.Options
42
+ }
43
+ }
44
+
45
+ /**
46
+ * Custom CSS injected into the standalone reference's shell `<head>` (via
47
+ * `Handler.openApi(_, { css })`), after the Vocs design-system styles so it
48
+ * overrides them:
49
+ *
50
+ * - Page/surface backgrounds use Tempo's near-black dark palette and pure-white
51
+ * light palette via `light-dark(<light>, <dark>)`.
52
+ * - The dark border color is darkened (the light theme keeps its default).
53
+ * - Every corner is squared. The universal `!important` rule beats hard-coded
54
+ * `border-radius` values and inline styles (e.g. the Scalar playground), which
55
+ * overriding the radius scale variables alone would miss.
56
+ * - The default sans/body font is Pilat (Vocs reads `--vocs-font-family`); the
57
+ * webfont is embedded via {@link pilatFontFaces}. Body stays at the default
58
+ * weight (400); headings are pinned to 500, which renders Pilat Demi (the
59
+ * family has no 500 cut, so Demi covers the 500-600 range — see
60
+ * {@link pilatFontFaces}).
61
+ */
62
+ const css = `${pilatFontFaces}
63
+
64
+ :root {
65
+ --vocs-font-family: "Pilat", Arial, Helvetica, sans-serif;
66
+ --vocs-background-color-primary: light-dark(#fafafa, #0a0a0a);
67
+ --vocs-background-color-surface: light-dark(#fff, #121212);
68
+ }
69
+
70
+ :is(h1, h2, h3, h4, h5, h6)[data-v] {
71
+ font-weight: 500;
72
+ }
73
+
74
+ /* Nudge the header logo a touch larger than the default max-h-7 (1.75rem). */
75
+ [data-v-logo-image] {
76
+ max-height: 2rem;
77
+ }
78
+
79
+ /* Sidebar leaf items render Regular (the nav's 450 default otherwise resolves to
80
+ * Demi via the 500-600 range). Group labels ([data-v-sidebar-section-header])
81
+ * keep their heavier weight. */
82
+ [data-v-sidebar-item] {
83
+ font-weight: 400;
84
+ }
85
+
86
+ [data-vocs-theme='dark'] {
87
+ --vocs-color-gray4: oklch(20% 0 0);
88
+ --vocs-color-gray5: oklch(0.23 0 0);
89
+ --vocs-border-color-primary: oklch(0.25 0 0);
90
+ --vocs-border-color-secondary: oklch(0.25 0 0);
91
+ }
92
+
93
+ *,
94
+ *::before,
95
+ *::after {
96
+ border-radius: 0 !important;
97
+ }`
98
+
99
+ /**
100
+ * Returns a shallow copy of `spec` with the JSON-RPC passthrough operation's
101
+ * `x-openrpc` replaced by the inline OpenRPC document, for the docs handler.
102
+ *
103
+ * Vocs expands `x-openrpc` at request time. A URL reference (as kept in the
104
+ * public `/openapi.json` by `App.create`'s `applyOpenrpcLink`) would make the
105
+ * docs worker fetch its own `/openrpc.json` — a self-subrequest that is
106
+ * unreliable on Cloudflare Workers and silently falls back to a single,
107
+ * unexpanded operation. Inlining the committed artifact keeps expansion
108
+ * deterministic across local and deployed environments, without bloating the
109
+ * public spec. Only the affected path/op are cloned; the rest of the (large)
110
+ * document is shared by reference.
111
+ */
112
+ function inlineOpenrpc<spec extends { paths: Record<string, unknown> }>(spec: spec): spec {
113
+ const paths: Record<string, unknown> = {}
114
+ for (const [pathname, item] of Object.entries(spec.paths)) {
115
+ let next = item
116
+ if (isRecord(item))
117
+ for (const [method, op] of Object.entries(item))
118
+ if (isRpcOperation(op)) next = { ...item, [method]: { ...op, 'x-openrpc': openrpcSpec } }
119
+ paths[pathname] = next
120
+ }
121
+ return { ...spec, paths }
122
+ }
123
+
124
+ // The JSON-RPC passthrough's operation id, set by its route definition and
125
+ // targeted by `App.create`'s `applyOpenrpcLink`.
126
+ function isRpcOperation(op: unknown): op is Record<string, unknown> {
127
+ return isRecord(op) && op['operationId'] === 'rpcRequest'
128
+ }
129
+
130
+ function isRecord(value: unknown): value is Record<string, unknown> {
131
+ return !!value && typeof value === 'object' && !Array.isArray(value)
132
+ }
@@ -0,0 +1,4 @@
1
+ export { data } from './data/index.js'
2
+ export { mcp } from './mcp.js'
3
+ export { platform } from './platform/index.js'
4
+ export { relay } from './relay/index.js'
@@ -0,0 +1,206 @@
1
+ import { Cli as incur_Cli, z } from 'incur'
2
+
3
+ import * as TestApp from '../../test/App.js'
4
+ import * as Runtime from '../../test/runtime.js'
5
+ import { mcp } from './mcp.js'
6
+
7
+ const origin = 'https://api.tempo-api.test'
8
+
9
+ /** API key with read-only webhook scope, used to prove header forwarding. */
10
+ const reader = {
11
+ id: 'key_reader',
12
+ orgId: 'org_test',
13
+ scopes: ['webhooks:read'],
14
+ token: 'secret_reader',
15
+ } satisfies TestApp.kvStore.Key
16
+
17
+ /** Composes a test app with the MCP group mounted, dispatching in-process. */
18
+ function createHost(
19
+ options: {
20
+ app?: ReturnType<typeof TestApp.create> | undefined
21
+ docs?: mcp.Options['docs'] | undefined
22
+ } = {},
23
+ ) {
24
+ const app = options.app ?? TestApp.create()
25
+ const host = mcp({ docs: options.docs ?? false, fetch: (request) => app.fetch(request) })
26
+ return { app, host }
27
+ }
28
+
29
+ /** Stub remote docs MCP server: an in-process incur CLI serving `/mcp`. */
30
+ function docsStub() {
31
+ const remote = incur_Cli.create('docs-remote', { version: '1.0.0' }).command('search', {
32
+ description: 'Search docs',
33
+ options: z.object({ query: z.string().describe('Search query') }),
34
+ run: (context) => ({ hits: [context.options.query] }),
35
+ })
36
+ return { fetch: (request: Request) => remote.fetch(request), url: 'http://docs.local/mcp' }
37
+ }
38
+
39
+ /** Anything serving `/mcp`: the group host, or a composed app it is mounted into. */
40
+ type Host = { fetch: (request: Request) => Response | Promise<Response> }
41
+
42
+ async function request(host: Host, body: unknown, headers: Record<string, string> = {}) {
43
+ const response = await host.fetch(
44
+ new Request(new URL('/mcp', origin), {
45
+ body: JSON.stringify(body),
46
+ headers: {
47
+ accept: 'application/json, text/event-stream',
48
+ 'content-type': 'application/json',
49
+ ...headers,
50
+ },
51
+ method: 'POST',
52
+ }),
53
+ )
54
+ expect(response.status).toBe(200)
55
+ return (await response.json()) as { result: any }
56
+ }
57
+
58
+ function initialize(host: Host) {
59
+ return request(host, {
60
+ id: 1,
61
+ jsonrpc: '2.0',
62
+ method: 'initialize',
63
+ params: {
64
+ capabilities: {},
65
+ clientInfo: { name: 'test-client', version: '1.0.0' },
66
+ protocolVersion: '2025-03-26',
67
+ },
68
+ })
69
+ }
70
+
71
+ async function toolsList(host: Host) {
72
+ const body = await request(host, { id: 2, jsonrpc: '2.0', method: 'tools/list', params: {} })
73
+ return (body.result.tools as { name: string }[]).map((tool) => tool.name)
74
+ }
75
+
76
+ async function toolsCall(
77
+ host: Host,
78
+ name: string,
79
+ args: Record<string, unknown>,
80
+ headers: Record<string, string> = {},
81
+ ) {
82
+ const body = await request(
83
+ host,
84
+ { id: 3, jsonrpc: '2.0', method: 'tools/call', params: { arguments: args, name } },
85
+ headers,
86
+ )
87
+ return body.result as {
88
+ content: { text: string; type: string }[]
89
+ isError?: boolean
90
+ structuredContent?: Record<string, unknown>
91
+ }
92
+ }
93
+
94
+ /** Parses a tool result: structured content when present, else the JSON text item. */
95
+ function resultJson(result: Awaited<ReturnType<typeof toolsCall>>) {
96
+ return result.structuredContent ?? JSON.parse(result.content[0]!.text)
97
+ }
98
+
99
+ test('scopes tools to the data domain', async () => {
100
+ const { app, host } = createHost({ docs: docsStub() })
101
+
102
+ // The domain filter must drop paths that actually exist in the spec.
103
+ const spec = (await (await app.fetch(new Request(new URL('/openapi.json', origin)))).json()) as {
104
+ paths: Record<string, unknown>
105
+ }
106
+ expect(Object.keys(spec.paths).some((path) => path.startsWith('/gecko/'))).toBe(true)
107
+ expect(Object.keys(spec.paths).some((path) => path.startsWith('/v1/auth/'))).toBe(true)
108
+ expect(Object.keys(spec.paths).some((path) => path.startsWith('/v1/orgs'))).toBe(true)
109
+
110
+ await initialize(host)
111
+ const tools = await toolsList(host)
112
+
113
+ expect(tools).toContain('v1_tokens_get')
114
+ expect(tools).toContain('docs_search')
115
+ // RPC is part of the data domain tag group.
116
+ expect(tools.some((name) => name.startsWith('rpc'))).toBe(true)
117
+ // Out of domain: CoinGecko mirrors, session auth, platform, relay.
118
+ expect(tools.some((name) => name.startsWith('gecko_'))).toBe(false)
119
+ expect(tools.some((name) => name.startsWith('v1_auth_'))).toBe(false)
120
+ expect(tools.some((name) => name.startsWith('v1_orgs'))).toBe(false)
121
+ expect(tools.some((name) => name.startsWith('v1_me'))).toBe(false)
122
+ })
123
+
124
+ test('executes generated tools against the composed app', async () => {
125
+ // Verified tokens are database-backed, so seed the default chain.
126
+ const db = TestApp.database()
127
+ await TestApp.verifiedSeed(db, Runtime.get().chainId)
128
+ const { host } = createHost({ app: TestApp.create({ db }) })
129
+
130
+ await initialize(host)
131
+ const result = await toolsCall(host, 'v1_tokens_get', { verified: true })
132
+
133
+ expect(result.isError).toBeFalsy()
134
+ const body = resultJson(result) as { data: { verified: boolean }[]; nextCursor: unknown }
135
+ expect(body.data.length).toBeGreaterThan(0)
136
+ expect(body.data.every((token) => token.verified === true)).toBe(true)
137
+ })
138
+
139
+ test('forwards the caller Authorization header to authenticated tools', async () => {
140
+ const { host } = createHost({ app: TestApp.create({ auth: { keys: [reader] } }) })
141
+ await initialize(host)
142
+
143
+ const denied = await toolsCall(host, 'v1_webhooks_get', {})
144
+ expect(denied.isError).toBe(true)
145
+
146
+ const allowed = await toolsCall(
147
+ host,
148
+ 'v1_webhooks_get',
149
+ {},
150
+ { authorization: `Bearer ${reader.token}` },
151
+ )
152
+ expect(allowed.isError).toBeFalsy()
153
+ expect(resultJson(allowed)).toMatchObject({ data: [] })
154
+ })
155
+
156
+ test('proxies docs tool calls to the remote MCP source', async () => {
157
+ const { host } = createHost({ docs: docsStub() })
158
+ await initialize(host)
159
+
160
+ const result = await toolsCall(host, 'docs_search', { query: 'fees' })
161
+
162
+ expect(result.isError).toBeFalsy()
163
+ expect(resultJson(result)).toMatchObject({ hits: ['fees'] })
164
+ })
165
+
166
+ test('documents POST /mcp and keeps it open under auth enforcement', async () => {
167
+ // Worker-style composition: the group mounted into the app it dispatches to.
168
+ const app = TestApp.create()
169
+ app.route('/', mcp({ docs: false, fetch: (request) => app.fetch(request) }))
170
+
171
+ const spec = (await (await app.fetch(new Request(new URL('/openapi.json', origin)))).json()) as {
172
+ paths: Record<string, { post?: { operationId?: string; security?: unknown; tags?: string[] } }>
173
+ 'x-tagGroups': { name: string; tags: string[] }[]
174
+ }
175
+ const operation = spec.paths['/mcp']?.post
176
+ expect(operation?.operationId).toBe('mcpRequest')
177
+ expect(operation?.tags).toEqual(['MCP'])
178
+ // Anonymous and any-valid-key access; no required scopes.
179
+ expect(operation?.security).toEqual([{ apiKey: [] }, { bearerAuth: [] }, {}])
180
+
181
+ // Surfaces under `Data API` in the reference, but the tool filter excludes the `MCP` tag.
182
+ const groups = Object.fromEntries(spec['x-tagGroups'].map((group) => [group.name, group.tags]))
183
+ expect(groups['MCP']).toBeUndefined()
184
+ expect(groups['Data API']).toContain('MCP')
185
+
186
+ // Documenting the route makes it auth-enforced; the public lane keeps it
187
+ // anonymously reachable, and the endpoint never surfaces itself as a tool.
188
+ await initialize(app)
189
+ const tools = await toolsList(app)
190
+ expect(tools.length).toBeGreaterThan(0)
191
+ expect(tools.some((name) => name.startsWith('mcp'))).toBe(false)
192
+
193
+ // A presented-but-invalid key is rejected at the transport.
194
+ const rejected = await app.fetch(
195
+ new Request(new URL('/mcp', origin), {
196
+ body: JSON.stringify({ id: 1, jsonrpc: '2.0', method: 'tools/list', params: {} }),
197
+ headers: {
198
+ accept: 'application/json, text/event-stream',
199
+ authorization: 'Bearer not-a-key',
200
+ 'content-type': 'application/json',
201
+ },
202
+ method: 'POST',
203
+ }),
204
+ )
205
+ expect(rejected.status).toBe(401)
206
+ })