tapimo 0.5.3 → 0.7.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 (376) hide show
  1. package/dist/App.d.ts +15830 -7220
  2. package/dist/App.d.ts.map +1 -1
  3. package/dist/App.js +9 -1
  4. package/dist/App.js.map +1 -1
  5. package/dist/Scope.d.ts +4 -0
  6. package/dist/Scope.d.ts.map +1 -1
  7. package/dist/Scope.js +5 -0
  8. package/dist/Scope.js.map +1 -1
  9. package/dist/admin/App.d.ts +1011 -412
  10. package/dist/admin/App.d.ts.map +1 -1
  11. package/dist/admin/App.js +4 -0
  12. package/dist/admin/App.js.map +1 -1
  13. package/dist/admin/apps/api-keys.d.ts +2 -1
  14. package/dist/admin/apps/api-keys.d.ts.map +1 -1
  15. package/dist/admin/apps/early-access.d.ts +148 -0
  16. package/dist/admin/apps/early-access.d.ts.map +1 -0
  17. package/dist/admin/apps/early-access.js +133 -0
  18. package/dist/admin/apps/early-access.js.map +1 -0
  19. package/dist/admin/apps/organizations.d.ts +124 -1
  20. package/dist/admin/apps/organizations.d.ts.map +1 -1
  21. package/dist/admin/apps/organizations.js +97 -6
  22. package/dist/admin/apps/organizations.js.map +1 -1
  23. package/dist/admin/apps/verified-tokens.d.ts +526 -1
  24. package/dist/admin/apps/verified-tokens.d.ts.map +1 -1
  25. package/dist/admin/apps/verified-tokens.js +214 -1
  26. package/dist/admin/apps/verified-tokens.js.map +1 -1
  27. package/dist/admin/ui.generated.d.ts +1 -1
  28. package/dist/admin/ui.generated.d.ts.map +1 -1
  29. package/dist/admin/ui.generated.js +95 -75
  30. package/dist/admin/ui.generated.js.map +1 -1
  31. package/dist/analytics/Analytics.d.ts.map +1 -1
  32. package/dist/analytics/Analytics.js +20 -0
  33. package/dist/analytics/Analytics.js.map +1 -1
  34. package/dist/analytics/tables/requestEvents.d.ts +18 -0
  35. package/dist/analytics/tables/requestEvents.d.ts.map +1 -1
  36. package/dist/analytics/tables/requestEvents.js +36 -7
  37. package/dist/analytics/tables/requestEvents.js.map +1 -1
  38. package/dist/apps/data/App.d.ts +6260 -4924
  39. package/dist/apps/data/App.d.ts.map +1 -1
  40. package/dist/apps/data/App.js +11 -6
  41. package/dist/apps/data/App.js.map +1 -1
  42. package/dist/apps/data/FundingQuoteProviders.d.ts +34 -1
  43. package/dist/apps/data/FundingQuoteProviders.d.ts.map +1 -1
  44. package/dist/apps/data/FundingQuoteProviders.js +194 -16
  45. package/dist/apps/data/FundingQuoteProviders.js.map +1 -1
  46. package/dist/apps/data/FxOracle.d.ts +71 -0
  47. package/dist/apps/data/FxOracle.d.ts.map +1 -0
  48. package/dist/apps/data/FxOracle.js +97 -0
  49. package/dist/apps/data/FxOracle.js.map +1 -0
  50. package/dist/apps/data/index.d.ts +1 -0
  51. package/dist/apps/data/index.d.ts.map +1 -1
  52. package/dist/apps/data/index.js +1 -0
  53. package/dist/apps/data/index.js.map +1 -1
  54. package/dist/apps/data/routes/activities.d.ts +3599 -1382
  55. package/dist/apps/data/routes/activities.d.ts.map +1 -1
  56. package/dist/apps/data/routes/activities.js +250 -88
  57. package/dist/apps/data/routes/activities.js.map +1 -1
  58. package/dist/apps/data/routes/addresses.d.ts +872 -251
  59. package/dist/apps/data/routes/addresses.d.ts.map +1 -1
  60. package/dist/apps/data/routes/addresses.js +11 -9
  61. package/dist/apps/data/routes/addresses.js.map +1 -1
  62. package/dist/apps/data/routes/balances.d.ts +77 -26
  63. package/dist/apps/data/routes/balances.d.ts.map +1 -1
  64. package/dist/apps/data/routes/balances.js +88 -45
  65. package/dist/apps/data/routes/balances.js.map +1 -1
  66. package/dist/apps/data/routes/blocks.d.ts +39 -39
  67. package/dist/apps/data/routes/coingecko.d.ts +54 -54
  68. package/dist/apps/data/routes/exchanges.d.ts +856 -105
  69. package/dist/apps/data/routes/exchanges.d.ts.map +1 -1
  70. package/dist/apps/data/routes/exchanges.js +518 -76
  71. package/dist/apps/data/routes/exchanges.js.map +1 -1
  72. package/dist/apps/data/routes/fee-amm.d.ts +81 -67
  73. package/dist/apps/data/routes/fee-amm.d.ts.map +1 -1
  74. package/dist/apps/data/routes/fee-amm.js +76 -91
  75. package/dist/apps/data/routes/fee-amm.js.map +1 -1
  76. package/dist/apps/data/routes/funding.d.ts +80 -36
  77. package/dist/apps/data/routes/funding.d.ts.map +1 -1
  78. package/dist/apps/data/routes/funding.js +65 -31
  79. package/dist/apps/data/routes/funding.js.map +1 -1
  80. package/dist/apps/data/routes/receipts.d.ts +392 -315
  81. package/dist/apps/data/routes/receipts.d.ts.map +1 -1
  82. package/dist/apps/data/routes/receipts.js +152 -77
  83. package/dist/apps/data/routes/receipts.js.map +1 -1
  84. package/dist/apps/data/routes/tokens.d.ts +167 -174
  85. package/dist/apps/data/routes/tokens.d.ts.map +1 -1
  86. package/dist/apps/data/routes/tokens.js +15 -13
  87. package/dist/apps/data/routes/tokens.js.map +1 -1
  88. package/dist/apps/data/routes/transactions.d.ts +277 -536
  89. package/dist/apps/data/routes/transactions.d.ts.map +1 -1
  90. package/dist/apps/data/routes/transactions.js +96 -77
  91. package/dist/apps/data/routes/transactions.js.map +1 -1
  92. package/dist/apps/data/routes/transfers.d.ts +157 -81
  93. package/dist/apps/data/routes/transfers.d.ts.map +1 -1
  94. package/dist/apps/data/routes/transfers.js +272 -130
  95. package/dist/apps/data/routes/transfers.js.map +1 -1
  96. package/dist/apps/data/routes/valuation.d.ts +307 -0
  97. package/dist/apps/data/routes/valuation.d.ts.map +1 -0
  98. package/dist/apps/data/routes/valuation.js +292 -0
  99. package/dist/apps/data/routes/valuation.js.map +1 -0
  100. package/dist/apps/data/routes/verified-tokens.d.ts +36 -36
  101. package/dist/apps/data/routes/verified-tokens.d.ts.map +1 -1
  102. package/dist/apps/data/routes/verified-tokens.js +7 -5
  103. package/dist/apps/data/routes/verified-tokens.js.map +1 -1
  104. package/dist/apps/data/routes/webhooks.d.ts +103 -123
  105. package/dist/apps/data/routes/webhooks.d.ts.map +1 -1
  106. package/dist/apps/data/routes/webhooks.js +124 -25
  107. package/dist/apps/data/routes/webhooks.js.map +1 -1
  108. package/dist/apps/index.d.ts +2 -1
  109. package/dist/apps/index.d.ts.map +1 -1
  110. package/dist/apps/index.js +2 -1
  111. package/dist/apps/index.js.map +1 -1
  112. package/dist/apps/management/App.d.ts +8554 -1692
  113. package/dist/apps/management/App.d.ts.map +1 -1
  114. package/dist/apps/management/App.js +12 -1
  115. package/dist/apps/management/App.js.map +1 -1
  116. package/dist/apps/management/routes/api-keys.d.ts +7 -0
  117. package/dist/apps/management/routes/api-keys.d.ts.map +1 -1
  118. package/dist/apps/management/routes/api-keys.js +17 -3
  119. package/dist/apps/management/routes/api-keys.js.map +1 -1
  120. package/dist/apps/management/routes/billing.d.ts +157 -162
  121. package/dist/apps/management/routes/billing.d.ts.map +1 -1
  122. package/dist/apps/management/routes/billing.js +31 -23
  123. package/dist/apps/management/routes/billing.js.map +1 -1
  124. package/dist/apps/management/routes/faucet.d.ts +232 -0
  125. package/dist/apps/management/routes/faucet.d.ts.map +1 -0
  126. package/dist/apps/management/routes/faucet.js +154 -0
  127. package/dist/apps/management/routes/faucet.js.map +1 -0
  128. package/dist/apps/management/routes/invitations.d.ts +60 -60
  129. package/dist/apps/management/routes/invite-links.d.ts +49 -20
  130. package/dist/apps/management/routes/invite-links.d.ts.map +1 -1
  131. package/dist/apps/management/routes/invite-links.js +26 -1
  132. package/dist/apps/management/routes/invite-links.js.map +1 -1
  133. package/dist/apps/management/routes/me.d.ts +6 -6
  134. package/dist/apps/management/routes/members.d.ts +6 -6
  135. package/dist/apps/management/routes/orgs.d.ts +42 -42
  136. package/dist/apps/management/routes/orgs.d.ts.map +1 -1
  137. package/dist/apps/management/routes/orgs.js +5 -0
  138. package/dist/apps/management/routes/orgs.js.map +1 -1
  139. package/dist/apps/management/routes/projects.d.ts +44 -44
  140. package/dist/apps/management/routes/usage.d.ts +3 -0
  141. package/dist/apps/management/routes/usage.d.ts.map +1 -1
  142. package/dist/apps/management/routes/usage.js +4 -0
  143. package/dist/apps/management/routes/usage.js.map +1 -1
  144. package/dist/apps/management/routes/verified-token-requests.d.ts +697 -0
  145. package/dist/apps/management/routes/verified-token-requests.d.ts.map +1 -0
  146. package/dist/apps/management/routes/verified-token-requests.js +271 -0
  147. package/dist/apps/management/routes/verified-token-requests.js.map +1 -0
  148. package/dist/apps/management/routes/webhooks.d.ts +6977 -0
  149. package/dist/apps/management/routes/webhooks.d.ts.map +1 -0
  150. package/dist/apps/management/routes/webhooks.js +573 -0
  151. package/dist/apps/management/routes/webhooks.js.map +1 -0
  152. package/dist/apps/mpp/App.d.ts +363 -0
  153. package/dist/apps/mpp/App.d.ts.map +1 -0
  154. package/dist/apps/mpp/App.js +72 -0
  155. package/dist/apps/mpp/App.js.map +1 -0
  156. package/dist/apps/mpp/Mpp.d.ts +178 -0
  157. package/dist/apps/mpp/Mpp.d.ts.map +1 -0
  158. package/dist/apps/mpp/Mpp.js +183 -0
  159. package/dist/apps/mpp/Mpp.js.map +1 -0
  160. package/dist/apps/mpp/index.d.ts +3 -0
  161. package/dist/apps/mpp/index.d.ts.map +1 -0
  162. package/dist/apps/mpp/index.js +3 -0
  163. package/dist/apps/mpp/index.js.map +1 -0
  164. package/dist/apps/relay/App.d.ts.map +1 -1
  165. package/dist/apps/relay/App.js +56 -9
  166. package/dist/apps/relay/App.js.map +1 -1
  167. package/dist/db/Db.d.ts +6 -0
  168. package/dist/db/Db.d.ts.map +1 -1
  169. package/dist/db/Db.js +110 -0
  170. package/dist/db/Db.js.map +1 -1
  171. package/dist/db/Schema.d.ts +53 -0
  172. package/dist/db/Schema.d.ts.map +1 -1
  173. package/dist/db/Schema.js +56 -0
  174. package/dist/db/Schema.js.map +1 -1
  175. package/dist/db/tables/earlyAccess.d.ts +50 -0
  176. package/dist/db/tables/earlyAccess.d.ts.map +1 -0
  177. package/dist/db/tables/earlyAccess.js +63 -0
  178. package/dist/db/tables/earlyAccess.js.map +1 -0
  179. package/dist/db/tables/enabledBillingSources.d.ts +73 -0
  180. package/dist/db/tables/enabledBillingSources.d.ts.map +1 -0
  181. package/dist/db/tables/enabledBillingSources.js +69 -0
  182. package/dist/db/tables/enabledBillingSources.js.map +1 -0
  183. package/dist/db/tables/invitations.d.ts.map +1 -1
  184. package/dist/db/tables/invitations.js +3 -0
  185. package/dist/db/tables/invitations.js.map +1 -1
  186. package/dist/db/tables/inviteLinks.d.ts +10 -2
  187. package/dist/db/tables/inviteLinks.d.ts.map +1 -1
  188. package/dist/db/tables/inviteLinks.js +10 -1
  189. package/dist/db/tables/inviteLinks.js.map +1 -1
  190. package/dist/db/tables/organizations.d.ts +5 -2
  191. package/dist/db/tables/organizations.d.ts.map +1 -1
  192. package/dist/db/tables/organizations.js +13 -2
  193. package/dist/db/tables/organizations.js.map +1 -1
  194. package/dist/db/tables/sponsoredTransactions.d.ts +2 -0
  195. package/dist/db/tables/sponsoredTransactions.d.ts.map +1 -1
  196. package/dist/db/tables/sponsoredTransactions.js +2 -0
  197. package/dist/db/tables/sponsoredTransactions.js.map +1 -1
  198. package/dist/db/tables/verifiedTokenRequests.d.ts +94 -0
  199. package/dist/db/tables/verifiedTokenRequests.d.ts.map +1 -0
  200. package/dist/db/tables/verifiedTokenRequests.js +120 -0
  201. package/dist/db/tables/verifiedTokenRequests.js.map +1 -0
  202. package/dist/db/tables/webhookSubscriptions.d.ts +14 -0
  203. package/dist/db/tables/webhookSubscriptions.d.ts.map +1 -1
  204. package/dist/db/tables/webhookSubscriptions.js +16 -0
  205. package/dist/db/tables/webhookSubscriptions.js.map +1 -1
  206. package/dist/handlers/internal/utils.d.ts +1 -16
  207. package/dist/handlers/internal/utils.d.ts.map +1 -1
  208. package/dist/handlers/internal/utils.js +17 -6
  209. package/dist/handlers/internal/utils.js.map +1 -1
  210. package/dist/handlers/relay.d.ts.map +1 -1
  211. package/dist/handlers/relay.js +37 -5
  212. package/dist/handlers/relay.js.map +1 -1
  213. package/dist/internal/Auth.d.ts +11 -2
  214. package/dist/internal/Auth.d.ts.map +1 -1
  215. package/dist/internal/Auth.js +14 -47
  216. package/dist/internal/Auth.js.map +1 -1
  217. package/dist/internal/FundingQuotes.d.ts +147 -47
  218. package/dist/internal/FundingQuotes.d.ts.map +1 -1
  219. package/dist/internal/FundingQuotes.js +119 -33
  220. package/dist/internal/FundingQuotes.js.map +1 -1
  221. package/dist/internal/Log.d.ts +37 -5
  222. package/dist/internal/Log.d.ts.map +1 -1
  223. package/dist/internal/Log.js +52 -3
  224. package/dist/internal/Log.js.map +1 -1
  225. package/dist/internal/MetricSink.d.ts.map +1 -1
  226. package/dist/internal/MetricSink.js +24 -0
  227. package/dist/internal/MetricSink.js.map +1 -1
  228. package/dist/internal/OpenApi.d.ts +2 -2
  229. package/dist/internal/OpenApi.d.ts.map +1 -1
  230. package/dist/internal/OpenApi.js +3 -0
  231. package/dist/internal/OpenApi.js.map +1 -1
  232. package/dist/internal/Response.d.ts +2 -2
  233. package/dist/internal/Response.d.ts.map +1 -1
  234. package/dist/internal/Response.js +12 -4
  235. package/dist/internal/Response.js.map +1 -1
  236. package/dist/internal/Schema.d.ts +14 -5
  237. package/dist/internal/Schema.d.ts.map +1 -1
  238. package/dist/internal/Schema.js +23 -5
  239. package/dist/internal/Schema.js.map +1 -1
  240. package/dist/internal/Value.d.ts +18 -0
  241. package/dist/internal/Value.d.ts.map +1 -1
  242. package/dist/internal/Value.js +11 -1
  243. package/dist/internal/Value.js.map +1 -1
  244. package/dist/internal/VerifiedTokens.d.ts.map +1 -1
  245. package/dist/internal/VerifiedTokens.js +10 -1
  246. package/dist/internal/VerifiedTokens.js.map +1 -1
  247. package/dist/internal/Webhooks.d.ts +24 -3
  248. package/dist/internal/Webhooks.d.ts.map +1 -1
  249. package/dist/internal/Webhooks.js +34 -8
  250. package/dist/internal/Webhooks.js.map +1 -1
  251. package/package.json +7 -2
  252. package/src/App.test.ts +9 -4
  253. package/src/App.ts +23 -3
  254. package/src/Client.test-d.ts +733 -20
  255. package/src/Scope.ts +5 -0
  256. package/src/admin/App.test.ts +4 -0
  257. package/src/admin/App.ts +4 -0
  258. package/src/admin/apps/early-access.test.ts +125 -0
  259. package/src/admin/apps/early-access.ts +176 -0
  260. package/src/admin/apps/organizations.test.ts +86 -2
  261. package/src/admin/apps/organizations.ts +155 -31
  262. package/src/admin/apps/scopes.test.ts +5 -0
  263. package/src/admin/apps/verified-tokens.test.ts +201 -0
  264. package/src/admin/apps/verified-tokens.ts +532 -286
  265. package/src/admin/ui/plugin.ts +2 -1
  266. package/src/admin/ui/src/lib/early-access.ts +63 -0
  267. package/src/admin/ui/src/lib/organizations.test.ts +81 -1
  268. package/src/admin/ui/src/lib/organizations.ts +92 -0
  269. package/src/admin/ui/src/lib/verified-tokens.ts +79 -0
  270. package/src/admin/ui/src/routeTree.gen.ts +33 -2
  271. package/src/admin/ui/src/routes/__root.tsx +2 -1
  272. package/src/admin/ui/src/routes/api-keys.tsx +1 -1
  273. package/src/admin/ui/src/routes/early-access.tsx +162 -0
  274. package/src/admin/ui/src/routes/organizations_.$orgId.tsx +103 -0
  275. package/src/admin/ui/src/routes/verified-tokens.tsx +230 -19
  276. package/src/admin/ui.generated.ts +95 -94
  277. package/src/analytics/Analytics.test.ts +83 -0
  278. package/src/analytics/Analytics.ts +20 -0
  279. package/src/analytics/tables/requestEvents.ts +60 -7
  280. package/src/apps/composition.test.ts +11 -2
  281. package/src/apps/data/App.test.ts +1 -1
  282. package/src/apps/data/App.ts +22 -14
  283. package/src/apps/data/FundingQuoteProviders.test.ts +297 -4
  284. package/src/apps/data/FundingQuoteProviders.ts +255 -29
  285. package/src/apps/data/FxOracle.test.ts +118 -0
  286. package/src/apps/data/FxOracle.ts +153 -0
  287. package/src/apps/data/index.ts +1 -0
  288. package/src/apps/data/routes/activities.test.ts +177 -3
  289. package/src/apps/data/routes/activities.ts +441 -132
  290. package/src/apps/data/routes/addresses.ts +19 -9
  291. package/src/apps/data/routes/balances.test.ts +148 -11
  292. package/src/apps/data/routes/balances.ts +140 -51
  293. package/src/apps/data/routes/exchanges.test.ts +544 -9
  294. package/src/apps/data/routes/exchanges.ts +690 -103
  295. package/src/apps/data/routes/fee-amm.test.ts +47 -23
  296. package/src/apps/data/routes/fee-amm.ts +98 -119
  297. package/src/apps/data/routes/funding.test.ts +113 -8
  298. package/src/apps/data/routes/funding.ts +77 -51
  299. package/src/apps/data/routes/receipts.test.ts +129 -23
  300. package/src/apps/data/routes/receipts.ts +205 -100
  301. package/src/apps/data/routes/tokens.test.ts +43 -0
  302. package/src/apps/data/routes/tokens.ts +28 -13
  303. package/src/apps/data/routes/transactions.test.ts +72 -19
  304. package/src/apps/data/routes/transactions.ts +162 -92
  305. package/src/apps/data/routes/transfers.test.ts +341 -31
  306. package/src/apps/data/routes/transfers.ts +358 -158
  307. package/src/apps/data/routes/valuation.test.ts +437 -0
  308. package/src/apps/data/routes/valuation.ts +423 -0
  309. package/src/apps/data/routes/verified-tokens.ts +14 -2
  310. package/src/apps/data/routes/webhooks.test.ts +56 -8
  311. package/src/apps/data/routes/webhooks.ts +144 -27
  312. package/src/apps/index.ts +2 -1
  313. package/src/apps/management/App.ts +13 -0
  314. package/src/apps/management/routes/api-keys.test.ts +14 -0
  315. package/src/apps/management/routes/api-keys.ts +27 -3
  316. package/src/apps/management/routes/billing.test.ts +152 -20
  317. package/src/apps/management/routes/billing.ts +34 -18
  318. package/src/apps/management/routes/faucet.test.ts +87 -0
  319. package/src/apps/management/routes/faucet.ts +201 -0
  320. package/src/apps/management/routes/invite-links.test.ts +117 -0
  321. package/src/apps/management/routes/invite-links.ts +43 -1
  322. package/src/apps/management/routes/me.test.ts +9 -99
  323. package/src/apps/management/routes/orgs.test.ts +45 -2
  324. package/src/apps/management/routes/orgs.ts +6 -0
  325. package/src/apps/management/routes/scopes.test.ts +1 -0
  326. package/src/apps/management/routes/usage.test.ts +6 -0
  327. package/src/apps/management/routes/usage.ts +7 -0
  328. package/src/apps/management/routes/verified-token-requests.test.ts +377 -0
  329. package/src/apps/management/routes/verified-token-requests.ts +397 -0
  330. package/src/apps/management/routes/webhooks.test.ts +426 -0
  331. package/src/apps/management/routes/webhooks.ts +672 -0
  332. package/src/apps/mpp/App.ts +86 -0
  333. package/src/apps/mpp/Mpp.test.ts +193 -0
  334. package/src/apps/mpp/Mpp.ts +353 -0
  335. package/src/apps/mpp/index.ts +2 -0
  336. package/src/apps/mpp/internal/Adapter.ts +11 -0
  337. package/src/apps/mpp/internal/Error.ts +9 -0
  338. package/src/apps/mpp/internal/Idempotency.ts +7 -0
  339. package/src/apps/mpp/internal/Screening.ts +10 -0
  340. package/src/apps/relay/App.test.ts +88 -6
  341. package/src/apps/relay/App.ts +61 -9
  342. package/src/db/Db.test.ts +19 -0
  343. package/src/db/Db.ts +125 -0
  344. package/src/db/Schema.ts +68 -0
  345. package/src/db/tables/earlyAccess.ts +86 -0
  346. package/src/db/tables/enabledBillingSources.test.ts +303 -0
  347. package/src/db/tables/enabledBillingSources.ts +118 -0
  348. package/src/db/tables/invitations.ts +3 -0
  349. package/src/db/tables/inviteLinks.ts +22 -3
  350. package/src/db/tables/organizations.test.ts +103 -0
  351. package/src/db/tables/organizations.ts +18 -2
  352. package/src/db/tables/sponsoredTransactions.ts +4 -0
  353. package/src/db/tables/verifiedTokenRequests.test.ts +200 -0
  354. package/src/db/tables/verifiedTokenRequests.ts +182 -0
  355. package/src/db/tables/webhookSubscriptions.ts +31 -0
  356. package/src/handlers/internal/utils.ts +22 -6
  357. package/src/handlers/relay.errors.test.ts +153 -0
  358. package/src/handlers/relay.ts +42 -7
  359. package/src/internal/Auth.test.ts +3 -3
  360. package/src/internal/Auth.ts +15 -47
  361. package/src/internal/FundingQuotes.test.ts +161 -6
  362. package/src/internal/FundingQuotes.ts +141 -39
  363. package/src/internal/Log.test-d.ts +21 -0
  364. package/src/internal/Log.test.ts +141 -0
  365. package/src/internal/Log.ts +93 -6
  366. package/src/internal/MetricSink.test.ts +215 -0
  367. package/src/internal/MetricSink.ts +24 -0
  368. package/src/internal/OpenApi.ts +3 -0
  369. package/src/internal/Response.test.ts +28 -0
  370. package/src/internal/Response.ts +12 -4
  371. package/src/internal/Schema.ts +50 -5
  372. package/src/internal/Value.test.ts +20 -0
  373. package/src/internal/Value.ts +24 -1
  374. package/src/internal/VerifiedTokens.ts +9 -1
  375. package/src/internal/Webhooks.test.ts +140 -0
  376. package/src/internal/Webhooks.ts +53 -9
package/src/Scope.ts CHANGED
@@ -49,6 +49,11 @@ export const catalog = [
49
49
  scope: 'management:write',
50
50
  selfServe: true,
51
51
  },
52
+ {
53
+ description: 'Validate and broadcast MPP payment credentials through the Tempo relay.',
54
+ scope: 'mpp:write',
55
+ selfServe: true,
56
+ },
52
57
  {
53
58
  description: 'Fill and submit transactions through the relay.',
54
59
  scope: 'rpc-relay:read',
@@ -20,6 +20,10 @@ describe('create', () => {
20
20
  new Request('http://admin/api-keys/key_x', { method: 'DELETE' }),
21
21
  new Request('http://admin/organizations'),
22
22
  new Request('http://admin/organizations/org_x'),
23
+ new Request('http://admin/organizations/org_x/billing-sources/stripe', { method: 'PUT' }),
24
+ new Request('http://admin/organizations/org_x/billing-sources/stripe', {
25
+ method: 'DELETE',
26
+ }),
23
27
  new Request('http://admin/organizations/org_x/members'),
24
28
  new Request('http://admin/organizations/org_x/projects'),
25
29
  new Request('http://admin/verified-tokens?chainId=42431', {
package/src/admin/App.ts CHANGED
@@ -11,6 +11,7 @@ import type * as Store from '../internal/Store.js'
11
11
  import * as Response from '../internal/Response.js'
12
12
 
13
13
  import { apiKeys } from './apps/api-keys.js'
14
+ import { earlyAccess } from './apps/early-access.js'
14
15
  import { organizations } from './apps/organizations.js'
15
16
  import { scopes } from './apps/scopes.js'
16
17
  import { verifiedTokens } from './apps/verified-tokens.js'
@@ -117,6 +118,8 @@ export function create(options: create.Options) {
117
118
  '/config.json',
118
119
  '/api-keys',
119
120
  '/api-keys/*',
121
+ '/early-access',
122
+ '/early-access/*',
120
123
  '/organizations',
121
124
  '/organizations/*',
122
125
  '/scopes',
@@ -152,6 +155,7 @@ export function create(options: create.Options) {
152
155
  const routed = app
153
156
  .get('/config.json', (c) => c.json(authConfig(c.get('identity')), 200))
154
157
  .route('/api-keys', apiKeys())
158
+ .route('/early-access', earlyAccess())
155
159
  .route('/organizations', organizations())
156
160
  .route('/scopes', scopes())
157
161
  .route('/verified-tokens', verifiedTokens())
@@ -0,0 +1,125 @@
1
+ import * as TestAdmin from '../../../test/Admin.js'
2
+ import * as TestApp from '../../../test/App.js'
3
+ import * as EarlyAccessApp from './early-access.js'
4
+
5
+ /** Lists the table's entries. */
6
+ async function listAdded(client: ReturnType<typeof TestAdmin.setup>['client']) {
7
+ const response = await client['early-access'].$get()
8
+ const body = await TestApp.json(response, EarlyAccessApp.schema.listEarlyAccessEntries.Response)
9
+ return body.data
10
+ }
11
+
12
+ describe('authentication', () => {
13
+ test('denied identity → 401 on every route', async () => {
14
+ const { app } = TestAdmin.setup({ identify: () => null })
15
+ const routes = [
16
+ new Request('http://admin/early-access'),
17
+ new Request('http://admin/early-access', {
18
+ body: JSON.stringify({ entry: 'example.org' }),
19
+ headers: { 'content-type': 'application/json' },
20
+ method: 'POST',
21
+ }),
22
+ new Request('http://admin/early-access', {
23
+ body: JSON.stringify({ entry: 'example.org' }),
24
+ headers: { 'content-type': 'application/json' },
25
+ method: 'DELETE',
26
+ }),
27
+ ]
28
+ for (const request of routes) {
29
+ const response = await app.request(request)
30
+ expect(response.status).toBe(401)
31
+ }
32
+ })
33
+ })
34
+
35
+ describe('GET /early-access', () => {
36
+ test('starts empty; entries are seeded through the dash, never migrations', async () => {
37
+ const { client } = TestAdmin.setup()
38
+ const response = await client['early-access'].$get()
39
+ const body = await TestApp.json(response, EarlyAccessApp.schema.listEarlyAccessEntries.Response)
40
+
41
+ expect(response.status).toBe(200)
42
+ expect(body.data).toEqual([])
43
+ })
44
+ })
45
+
46
+ describe('POST /early-access', () => {
47
+ test('add → list → remove round-trip', async () => {
48
+ const { client } = TestAdmin.setup()
49
+
50
+ const created = await client['early-access'].$post({ json: { entry: 'a/b@example.org' } })
51
+ expect(created.status).toBe(200)
52
+ const body = await TestApp.json(created, EarlyAccessApp.schema.createEarlyAccessEntry.Response)
53
+ expect(body.data.entry).toBe('a/b@example.org')
54
+ // createdBy is the verified admin email, never client-supplied.
55
+ expect(body.data.createdBy).toBe(TestAdmin.identity.email)
56
+
57
+ expect((await listAdded(client)).map((record) => record.entry)).toEqual(['a/b@example.org'])
58
+
59
+ // Reserved URL characters stay in the JSON body.
60
+ const removed = await client['early-access'].$delete({ json: { entry: 'a/b@example.org' } })
61
+ expect(removed.status).toBe(200)
62
+ expect(await listAdded(client)).toEqual([])
63
+ })
64
+
65
+ test('normalizes the entry lowercase and trimmed', async () => {
66
+ const { client } = TestAdmin.setup()
67
+ const response = await client['early-access'].$post({ json: { entry: ' User@Example.ORG ' } })
68
+ const body = await TestApp.json(response, EarlyAccessApp.schema.createEarlyAccessEntry.Response)
69
+
70
+ expect(response.status).toBe(200)
71
+ expect(body.data.entry).toBe('user@example.org')
72
+ })
73
+
74
+ test('rejects an invalid entry with 400', async () => {
75
+ const { client } = TestAdmin.setup()
76
+ for (const entry of ['', ' ', 'no spaces.org x', 'not-a-domain', '@example.org', 'user@']) {
77
+ const response = await client['early-access'].$post({ json: { entry } })
78
+ const body = (await response.json()) as { error?: { code?: string } }
79
+ expect(response.status).toBe(400)
80
+ expect(body.error?.code).toBe('body_invalid')
81
+ }
82
+ })
83
+
84
+ test('rejects a duplicate entry with 409', async () => {
85
+ const { client } = TestAdmin.setup()
86
+ await client['early-access'].$post({ json: { entry: 'example.org' } })
87
+ const duplicate = await client['early-access'].$post({ json: { entry: 'Example.org' } })
88
+ const body = (await duplicate.json()) as { error?: { code?: string } }
89
+
90
+ expect(duplicate.status).toBe(409)
91
+ expect(body.error?.code).toBe('entry_exists')
92
+ })
93
+ })
94
+
95
+ describe('DELETE /early-access', () => {
96
+ test('removing an unknown entry → 404', async () => {
97
+ const { client } = TestAdmin.setup()
98
+ const response = await client['early-access'].$delete({
99
+ json: { entry: 'missing.example.org' },
100
+ })
101
+ const body = (await response.json()) as { error?: { code?: string } }
102
+
103
+ expect(response.status).toBe(404)
104
+ expect(body.error?.code).toBe('entry_not_found')
105
+ })
106
+ })
107
+
108
+ describe('audit logging', () => {
109
+ test('writes an audit row for allowlist mutations', async () => {
110
+ const { client, db } = TestAdmin.setup()
111
+ await client['early-access'].$post({ json: { entry: 'example.org' } })
112
+ const records = await db.kysely
113
+ .selectFrom('admin_audit_logs')
114
+ .selectAll()
115
+ .orderBy('createdAt', 'desc')
116
+ .execute()
117
+
118
+ expect(records[0]).toMatchObject({
119
+ actor: TestAdmin.identity.email,
120
+ method: 'POST',
121
+ path: '/early-access',
122
+ status: 200,
123
+ })
124
+ })
125
+ })
@@ -0,0 +1,176 @@
1
+ import { Hono } from 'hono'
2
+ import * as z from 'zod/mini'
3
+
4
+ import * as Db from '../../db/Db.js'
5
+ import * as db_Schema from '../../db/Schema.js'
6
+ import * as EarlyAccess from '../../db/tables/earlyAccess.js'
7
+ import * as OpenApi from '../../internal/OpenApi.js'
8
+ import * as Response from '../../internal/Response.js'
9
+ import * as Schema from '../../internal/Schema.js'
10
+ import type * as App from '../App.js'
11
+
12
+ // A bare domain (`example.org`) or a full email (`user@example.org`), matched
13
+ // after the trim/lowercase transforms below.
14
+ const entryPattern =
15
+ /^(?:[^\s@]+@)?[a-z0-9](?:[a-z0-9-]*[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]*[a-z0-9])?)+$/
16
+
17
+ /** Zod schemas owned by the admin early-access handler. */
18
+ export namespace schema {
19
+ /** A stored early-access allowlist entry (the `early_access` row shape). */
20
+ export const Entry = Schema.describe(
21
+ db_Schema.EarlyAccessEntry,
22
+ 'A stored early-access allowlist entry.',
23
+ )
24
+
25
+ /** Schemas for the listEarlyAccessEntries operation. */
26
+ export namespace listEarlyAccessEntries {
27
+ /** Response body: all allowlist entries. */
28
+ export const Response = Schema.describe(
29
+ z.object({
30
+ data: z.array(Entry).check(z.describe('Allowlist entries, ordered by entry.')),
31
+ }),
32
+ 'Accounts whose new organizations receive early access features by default.',
33
+ )
34
+ }
35
+
36
+ /** Schemas for the createEarlyAccessEntry operation. */
37
+ export namespace createEarlyAccessEntry {
38
+ /** Request body for adding an allowlist entry. */
39
+ export const Body = z
40
+ .object({
41
+ entry: z.string().check(
42
+ z.trim(),
43
+ z.toLowerCase(),
44
+ z.regex(entryPattern, 'Must be a bare domain (example.org) or a full email (user@example.org).'), // prettier-ignore
45
+ z.describe('Domain or exact email whose new organizations receive early access features; normalized lowercase.'), // prettier-ignore
46
+ ),
47
+ })
48
+ .check(z.describe('Request body for adding an allowlist entry.'))
49
+
50
+ /** Response body: the stored entry. */
51
+ export const Response = Schema.describe(
52
+ z.object({ data: Entry }),
53
+ 'The stored allowlist entry.',
54
+ )
55
+ }
56
+
57
+ /** Schemas for the deleteEarlyAccessEntry operation. */
58
+ export namespace deleteEarlyAccessEntry {
59
+ /** Request body addressing one allowlist entry. */
60
+ export const Body = z
61
+ .object({
62
+ entry: z.string().check(
63
+ z.trim(),
64
+ z.toLowerCase(),
65
+ z.regex(entryPattern, 'Must be a bare domain (example.org) or a full email (user@example.org).'), // prettier-ignore
66
+ z.describe('The allowlist entry to remove; normalized lowercase.'),
67
+ ),
68
+ })
69
+ .check(z.describe('Request body for removing an allowlist entry.'))
70
+
71
+ /** Response body: the removed entry. */
72
+ export const Response = Schema.describe(
73
+ z.object({ data: Entry }),
74
+ 'The removed allowlist entry.',
75
+ )
76
+ }
77
+ }
78
+
79
+ /**
80
+ * Management routes for the early-access allowlist (`early_access` table).
81
+ * Matching users receive Stripe by default when they create an organization.
82
+ *
83
+ * - `GET /` lists entries.
84
+ * - `POST /` adds an entry (`409` on a duplicate).
85
+ * - `DELETE /` removes an entry (`404` if absent).
86
+ */
87
+ export function earlyAccess() {
88
+ return new Hono<App.Environment>()
89
+ .get(
90
+ '/',
91
+ OpenApi.describeRoute({
92
+ operationId: 'listEarlyAccessEntries',
93
+ responses: OpenApi.responses({
94
+ success: {
95
+ description:
96
+ 'Accounts whose new organizations receive early access features by default.',
97
+ schema: schema.listEarlyAccessEntries.Response,
98
+ },
99
+ }),
100
+ summary: 'List early access',
101
+ tags: ['Early Access'],
102
+ }),
103
+ async (c) => {
104
+ const db = Db.get(c.get('db'))
105
+ return c.json(
106
+ Response.validated(schema.listEarlyAccessEntries.Response, {
107
+ data: await EarlyAccess.list(db),
108
+ }),
109
+ )
110
+ },
111
+ )
112
+ .post(
113
+ '/',
114
+ OpenApi.validate('json', schema.createEarlyAccessEntry.Body, {
115
+ code: 'body_invalid',
116
+ message: 'Invalid request body',
117
+ }),
118
+ OpenApi.describeRoute({
119
+ operationId: 'createEarlyAccessEntry',
120
+ responses: OpenApi.responses({
121
+ errors: { 409: 'Entry already exists.' },
122
+ success: {
123
+ description: 'The stored allowlist entry.',
124
+ schema: schema.createEarlyAccessEntry.Response,
125
+ },
126
+ }),
127
+ summary: 'Add early-access entry',
128
+ tags: ['Early Access'],
129
+ }),
130
+ async (c) => {
131
+ const db = Db.get(c.get('db'))
132
+ const { entry } = c.req.valid('json')
133
+ // `createdBy` is the verified admin email; `requireAuth` guarantees
134
+ // identity on this gated route.
135
+ const record = await EarlyAccess.add(db, { createdBy: c.get('identity')!.email, entry })
136
+ if (!record)
137
+ return Response.error(c, {
138
+ code: 'entry_exists',
139
+ message: 'Entry already exists.',
140
+ status: 409,
141
+ })
142
+ return c.json(Response.validated(schema.createEarlyAccessEntry.Response, { data: record }))
143
+ },
144
+ )
145
+ .delete(
146
+ '/',
147
+ OpenApi.validate('json', schema.deleteEarlyAccessEntry.Body, {
148
+ code: 'body_invalid',
149
+ message: 'Invalid request body',
150
+ }),
151
+ OpenApi.describeRoute({
152
+ operationId: 'deleteEarlyAccessEntry',
153
+ responses: OpenApi.responses({
154
+ errors: { 404: 'Entry not found.' },
155
+ success: {
156
+ description: 'The removed allowlist entry.',
157
+ schema: schema.deleteEarlyAccessEntry.Response,
158
+ },
159
+ }),
160
+ summary: 'Remove early-access entry',
161
+ tags: ['Early Access'],
162
+ }),
163
+ async (c) => {
164
+ const db = Db.get(c.get('db'))
165
+ const { entry } = c.req.valid('json')
166
+ const record = await EarlyAccess.remove(db, entry)
167
+ if (!record)
168
+ return Response.error(c, {
169
+ code: 'entry_not_found',
170
+ message: 'Entry not found.',
171
+ status: 404,
172
+ })
173
+ return c.json(Response.validated(schema.deleteEarlyAccessEntry.Response, { data: record }))
174
+ },
175
+ )
176
+ }
@@ -1,6 +1,7 @@
1
1
  import type * as Analytics from '../../analytics/Analytics.js'
2
2
  import * as ApiKeys from '../../ApiKeys.js'
3
3
  import * as BillingSettings from '../../db/tables/billingSettings.js'
4
+ import * as EnabledBillingSources from '../../db/tables/enabledBillingSources.js'
4
5
  import * as Memberships from '../../db/tables/memberships.js'
5
6
  import * as Organizations from '../../db/tables/organizations.js'
6
7
  import * as Projects from '../../db/tables/projects.js'
@@ -134,6 +135,16 @@ describe('GET /organizations/:orgId', () => {
134
135
  })
135
136
  await Users.setEmail(db, user.id, 'owner@tempo.xyz')
136
137
  const organization = await Organizations.createOwned(db, { name: 'Tempo', userId: user.id })
138
+ await EnabledBillingSources.add(db, {
139
+ createdBy: TestAdmin.identity.email,
140
+ orgId: organization.id,
141
+ source: 'stripe',
142
+ })
143
+ await EnabledBillingSources.add(db, {
144
+ createdBy: TestAdmin.identity.email,
145
+ orgId: organization.id,
146
+ source: 'tempo',
147
+ })
137
148
  await Projects.create(db, { name: 'API', orgId: organization.id })
138
149
  await BillingSettings.upsert(db, {
139
150
  environment: 'production',
@@ -161,6 +172,7 @@ describe('GET /organizations/:orgId', () => {
161
172
  expect(response.status).toBe(200)
162
173
  expect(body.memberCount).toBe(1)
163
174
  expect(body.projectCount).toBe(1)
175
+ expect(body.billing.enabledSources).toEqual(['stripe', 'tempo'])
164
176
  expect(body.billing.production).toMatchObject({
165
177
  settings: { spendLimit: '250', txFeeLimit: '0.50' },
166
178
  source: { status: 'active', stripeCustomerId: 'cus_admin_lookup' },
@@ -182,6 +194,7 @@ describe('GET /organizations/:orgId', () => {
182
194
 
183
195
  expect(body).toMatchObject({
184
196
  billing: {
197
+ enabledSources: [],
185
198
  production: { settings: null, source: null },
186
199
  sandbox: { settings: null, source: null },
187
200
  },
@@ -202,6 +215,78 @@ describe('GET /organizations/:orgId', () => {
202
215
  })
203
216
  })
204
217
 
218
+ describe('PUT/DELETE /organizations/:orgId/billing-sources/:source', () => {
219
+ test('enables and disables sources idempotently', async () => {
220
+ const { client, db } = TestAdmin.setup()
221
+ const organization = await Organizations.create(db, { name: 'Billing sources' })
222
+
223
+ for (const source of ['tempo', 'stripe', 'stripe'] as const) {
224
+ const response = await client.organizations[':orgId']['billing-sources'][':source'].$put({
225
+ param: { orgId: organization.id, source },
226
+ })
227
+ const body = await TestApp.json(response, AdminOrganizations.schema.setBillingSource.Response)
228
+ expect(response.status).toBe(200)
229
+ expect(body.data).toEqual(source === 'tempo' ? ['tempo'] : ['stripe', 'tempo'])
230
+ }
231
+
232
+ expect(await EnabledBillingSources.listByOrg(db, organization.id)).toMatchObject([
233
+ { createdBy: TestAdmin.identity.email, source: 'stripe' },
234
+ { createdBy: TestAdmin.identity.email, source: 'tempo' },
235
+ ])
236
+
237
+ for (const source of ['stripe', 'stripe'] as const) {
238
+ const response = await client.organizations[':orgId']['billing-sources'][':source'].$delete({
239
+ param: { orgId: organization.id, source },
240
+ })
241
+ const body = await TestApp.json(response, AdminOrganizations.schema.setBillingSource.Response)
242
+ expect(response.status).toBe(200)
243
+ expect(body.data).toEqual(['tempo'])
244
+ }
245
+
246
+ const detailResponse = await client.organizations[':orgId'].$get({
247
+ param: { orgId: organization.id },
248
+ })
249
+ const detail = await TestApp.json(
250
+ detailResponse,
251
+ AdminOrganizations.schema.getOrganization.Response,
252
+ )
253
+ expect(detail.billing.enabledSources).toEqual(['tempo'])
254
+ })
255
+
256
+ test('rejects unsupported sources and unknown organizations', async () => {
257
+ const { app, client } = TestAdmin.setup()
258
+ const invalid = await app.request('/organizations/org_example/billing-sources/card', {
259
+ method: 'PUT',
260
+ })
261
+ expect(invalid.status).toBe(400)
262
+
263
+ const missing = await client.organizations[':orgId']['billing-sources'][':source'].$put({
264
+ param: { orgId: 'org_missing', source: 'stripe' },
265
+ })
266
+ expect(missing.status).toBe(404)
267
+ })
268
+
269
+ test('records billing-source mutations in the admin audit log', async () => {
270
+ const { client, db } = TestAdmin.setup()
271
+ const organization = await Organizations.create(db, { name: 'Audited billing' })
272
+ await client.organizations[':orgId']['billing-sources'][':source'].$put({
273
+ param: { orgId: organization.id, source: 'tempo' },
274
+ })
275
+
276
+ const records = await db.kysely
277
+ .selectFrom('admin_audit_logs')
278
+ .selectAll()
279
+ .orderBy('createdAt', 'desc')
280
+ .execute()
281
+ expect(records[0]).toMatchObject({
282
+ actor: TestAdmin.identity.email,
283
+ method: 'PUT',
284
+ path: `/organizations/${organization.id}/billing-sources/tempo`,
285
+ status: 200,
286
+ })
287
+ })
288
+ })
289
+
205
290
  describe('GET /organizations/:orgId/members', () => {
206
291
  test('returns a bounded cursor page without duplicates', async () => {
207
292
  const { client, db } = TestAdmin.setup()
@@ -444,8 +529,7 @@ const usageAnalytics: Analytics.Analytics = {
444
529
  async insert() {},
445
530
  async migrate() {},
446
531
  async query(sql) {
447
- if (sql.includes('GROUP BY error_code'))
448
- return [{ code: 'upstream_error', requests: 2 }] as never[]
532
+ if (sql.includes('GROUP BY code')) return [{ code: 'upstream_error', requests: 2 }] as never[]
449
533
  if (sql.includes('GROUP BY route'))
450
534
  return [{ averageDurationMs: 12.5, errors: 2, requests: 20, route: '/v1/tokens' }] as never[]
451
535
  if (sql.includes('GROUP BY status')) return [{ requests: 2, status: 500 }] as never[]