tapimo 0.0.2 → 0.2.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 (517) hide show
  1. package/README.md +38 -16
  2. package/dist/ApiKey.d.ts +14 -11
  3. package/dist/ApiKey.d.ts.map +1 -1
  4. package/dist/ApiKey.js +11 -12
  5. package/dist/ApiKey.js.map +1 -1
  6. package/dist/ApiKeys.d.ts +207 -0
  7. package/dist/ApiKeys.d.ts.map +1 -0
  8. package/dist/ApiKeys.js +282 -0
  9. package/dist/ApiKeys.js.map +1 -0
  10. package/dist/App.d.ts +6771 -3819
  11. package/dist/App.d.ts.map +1 -1
  12. package/dist/App.js +145 -317
  13. package/dist/App.js.map +1 -1
  14. package/dist/Handler.d.ts +86 -0
  15. package/dist/Handler.d.ts.map +1 -0
  16. package/dist/Handler.js +83 -0
  17. package/dist/Handler.js.map +1 -0
  18. package/dist/Scope.d.ts +14 -4
  19. package/dist/Scope.d.ts.map +1 -1
  20. package/dist/Scope.js +16 -4
  21. package/dist/Scope.js.map +1 -1
  22. package/dist/Webhooks.d.ts +5 -7
  23. package/dist/Webhooks.d.ts.map +1 -1
  24. package/dist/Webhooks.js +11 -4
  25. package/dist/Webhooks.js.map +1 -1
  26. package/dist/admin/Access.d.ts +1 -3
  27. package/dist/admin/Access.d.ts.map +1 -1
  28. package/dist/admin/Access.js +1 -3
  29. package/dist/admin/Access.js.map +1 -1
  30. package/dist/admin/App.d.ts +167 -205
  31. package/dist/admin/App.d.ts.map +1 -1
  32. package/dist/admin/App.js +2 -4
  33. package/dist/admin/App.js.map +1 -1
  34. package/dist/admin/apps/api-keys.d.ts +105 -5
  35. package/dist/admin/apps/api-keys.d.ts.map +1 -1
  36. package/dist/admin/apps/api-keys.js +75 -9
  37. package/dist/admin/apps/api-keys.js.map +1 -1
  38. package/dist/admin/apps/scopes.d.ts +6 -0
  39. package/dist/admin/apps/scopes.d.ts.map +1 -1
  40. package/dist/admin/apps/verified-tokens.d.ts +35 -149
  41. package/dist/admin/apps/verified-tokens.d.ts.map +1 -1
  42. package/dist/admin/apps/verified-tokens.js +18 -39
  43. package/dist/admin/apps/verified-tokens.js.map +1 -1
  44. package/dist/admin/ui.generated.d.ts +1 -1
  45. package/dist/admin/ui.generated.js +1 -1
  46. package/dist/apps/data/App.d.ts +19176 -0
  47. package/dist/apps/data/App.d.ts.map +1 -0
  48. package/dist/apps/data/App.js +236 -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} +49 -49
  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} +183 -183
  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} +460 -460
  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} +94 -94
  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/{indexer.d.ts → data/routes/indexer.d.ts} +4 -4
  83. package/dist/apps/data/routes/indexer.d.ts.map +1 -0
  84. package/dist/apps/{indexer.js → data/routes/indexer.js} +13 -9
  85. package/dist/apps/data/routes/indexer.js.map +1 -0
  86. package/dist/apps/{receipts.d.ts → data/routes/receipts.d.ts} +6 -6
  87. package/dist/apps/data/routes/receipts.d.ts.map +1 -0
  88. package/dist/apps/{receipts.js → data/routes/receipts.js} +12 -12
  89. package/dist/apps/data/routes/receipts.js.map +1 -0
  90. package/dist/apps/{rpc.d.ts → data/routes/rpc.d.ts} +4 -4
  91. package/dist/apps/data/routes/rpc.d.ts.map +1 -0
  92. package/dist/apps/{rpc.js → data/routes/rpc.js} +6 -6
  93. package/dist/apps/data/routes/rpc.js.map +1 -0
  94. package/dist/apps/{tokenlist.d.ts → data/routes/tokenlist.d.ts} +4 -4
  95. package/dist/apps/data/routes/tokenlist.d.ts.map +1 -0
  96. package/dist/apps/{tokenlist.js → data/routes/tokenlist.js} +8 -8
  97. package/dist/apps/data/routes/tokenlist.js.map +1 -0
  98. package/dist/apps/{tokens.d.ts → data/routes/tokens.d.ts} +11 -11
  99. package/dist/apps/data/routes/tokens.d.ts.map +1 -0
  100. package/dist/apps/{tokens.js → data/routes/tokens.js} +19 -19
  101. package/dist/apps/data/routes/tokens.js.map +1 -0
  102. package/dist/apps/{transactions.d.ts → data/routes/transactions.d.ts} +288 -288
  103. package/dist/apps/data/routes/transactions.d.ts.map +1 -0
  104. package/dist/apps/{transactions.js → data/routes/transactions.js} +13 -13
  105. package/dist/apps/data/routes/transactions.js.map +1 -0
  106. package/dist/apps/{transfers.d.ts → data/routes/transfers.d.ts} +35 -35
  107. package/dist/apps/data/routes/transfers.d.ts.map +1 -0
  108. package/dist/apps/{transfers.js → data/routes/transfers.js} +13 -13
  109. package/dist/apps/data/routes/transfers.js.map +1 -0
  110. package/dist/apps/{verified-tokens.d.ts → data/routes/verified-tokens.d.ts} +42 -42
  111. package/dist/apps/data/routes/verified-tokens.d.ts.map +1 -0
  112. package/dist/apps/{verified-tokens.js → data/routes/verified-tokens.js} +9 -9
  113. package/dist/apps/data/routes/verified-tokens.js.map +1 -0
  114. package/dist/apps/{webhooks.d.ts → data/routes/webhooks.d.ts} +66 -63
  115. package/dist/apps/{webhooks.d.ts.map → data/routes/webhooks.d.ts.map} +1 -1
  116. package/dist/apps/{webhooks.js → data/routes/webhooks.js} +67 -59
  117. package/dist/apps/data/routes/webhooks.js.map +1 -0
  118. package/dist/apps/docs/App.d.ts +27 -0
  119. package/dist/apps/docs/App.d.ts.map +1 -0
  120. package/dist/apps/docs/App.js +122 -0
  121. package/dist/apps/docs/App.js.map +1 -0
  122. package/dist/{internal/OpenApi.fonts.d.ts → apps/docs/fonts.d.ts} +1 -1
  123. package/dist/apps/docs/fonts.d.ts.map +1 -0
  124. package/dist/{internal/OpenApi.fonts.js → apps/docs/fonts.js} +1 -1
  125. package/dist/apps/docs/fonts.js.map +1 -0
  126. package/dist/apps/docs/index.d.ts +2 -0
  127. package/dist/apps/docs/index.d.ts.map +1 -0
  128. package/dist/apps/docs/index.js +2 -0
  129. package/dist/apps/docs/index.js.map +1 -0
  130. package/dist/{internal/OpenApi.logo.d.ts → apps/docs/logo.d.ts} +1 -1
  131. package/dist/apps/docs/logo.d.ts.map +1 -0
  132. package/dist/{internal/OpenApi.logo.js → apps/docs/logo.js} +1 -1
  133. package/dist/apps/docs/logo.js.map +1 -0
  134. package/dist/apps/index.d.ts +4 -0
  135. package/dist/apps/index.d.ts.map +1 -0
  136. package/dist/apps/index.js +4 -0
  137. package/dist/apps/index.js.map +1 -0
  138. package/dist/apps/metadata.d.ts +7 -0
  139. package/dist/apps/metadata.d.ts.map +1 -0
  140. package/dist/apps/metadata.js +15 -0
  141. package/dist/apps/metadata.js.map +1 -0
  142. package/dist/apps/platform/App.d.ts +2985 -0
  143. package/dist/apps/platform/App.d.ts.map +1 -0
  144. package/dist/apps/platform/App.js +74 -0
  145. package/dist/apps/platform/App.js.map +1 -0
  146. package/dist/apps/platform/index.d.ts +2 -0
  147. package/dist/apps/platform/index.d.ts.map +1 -0
  148. package/dist/apps/platform/index.js +2 -0
  149. package/dist/apps/platform/index.js.map +1 -0
  150. package/dist/apps/platform/routes/api-keys.d.ts +681 -0
  151. package/dist/apps/platform/routes/api-keys.d.ts.map +1 -0
  152. package/dist/apps/platform/routes/api-keys.js +328 -0
  153. package/dist/apps/platform/routes/api-keys.js.map +1 -0
  154. package/dist/apps/platform/routes/invitations.d.ts +733 -0
  155. package/dist/apps/platform/routes/invitations.d.ts.map +1 -0
  156. package/dist/apps/platform/routes/invitations.js +413 -0
  157. package/dist/apps/platform/routes/invitations.js.map +1 -0
  158. package/dist/apps/platform/routes/me.d.ts +95 -0
  159. package/dist/apps/platform/routes/me.d.ts.map +1 -0
  160. package/dist/apps/platform/routes/me.js +81 -0
  161. package/dist/apps/platform/routes/me.js.map +1 -0
  162. package/dist/apps/platform/routes/members.d.ts +554 -0
  163. package/dist/apps/platform/routes/members.d.ts.map +1 -0
  164. package/dist/apps/platform/routes/members.js +251 -0
  165. package/dist/apps/platform/routes/members.js.map +1 -0
  166. package/dist/apps/platform/routes/orgs.d.ts +582 -0
  167. package/dist/apps/platform/routes/orgs.d.ts.map +1 -0
  168. package/dist/apps/platform/routes/orgs.js +265 -0
  169. package/dist/apps/platform/routes/orgs.js.map +1 -0
  170. package/dist/apps/platform/routes/projects.d.ts +740 -0
  171. package/dist/apps/platform/routes/projects.d.ts.map +1 -0
  172. package/dist/apps/platform/routes/projects.js +286 -0
  173. package/dist/apps/platform/routes/projects.js.map +1 -0
  174. package/dist/apps/relay/App.d.ts +41 -0
  175. package/dist/apps/relay/App.d.ts.map +1 -0
  176. package/dist/apps/relay/App.js +103 -0
  177. package/dist/apps/relay/App.js.map +1 -0
  178. package/dist/apps/relay/Sponsorships.d.ts +107 -0
  179. package/dist/apps/relay/Sponsorships.d.ts.map +1 -0
  180. package/dist/apps/relay/Sponsorships.js +193 -0
  181. package/dist/apps/relay/Sponsorships.js.map +1 -0
  182. package/dist/apps/relay/index.d.ts +3 -0
  183. package/dist/apps/relay/index.d.ts.map +1 -0
  184. package/dist/apps/relay/index.js +3 -0
  185. package/dist/apps/relay/index.js.map +1 -0
  186. package/dist/{Cli.d.ts → cli/Cli.d.ts} +13 -2
  187. package/dist/cli/Cli.d.ts.map +1 -0
  188. package/dist/cli/Cli.js +19 -0
  189. package/dist/cli/Cli.js.map +1 -0
  190. package/dist/cli/bin.d.ts +3 -0
  191. package/dist/cli/bin.d.ts.map +1 -0
  192. package/dist/cli/bin.js +4 -0
  193. package/dist/cli/bin.js.map +1 -0
  194. package/dist/cli/commands/admin.d.ts +15 -0
  195. package/dist/cli/commands/admin.d.ts.map +1 -0
  196. package/dist/cli/commands/admin.js +60 -0
  197. package/dist/cli/commands/admin.js.map +1 -0
  198. package/dist/cloudflare.d.ts +7 -0
  199. package/dist/cloudflare.d.ts.map +1 -1
  200. package/dist/cloudflare.js +9 -0
  201. package/dist/cloudflare.js.map +1 -1
  202. package/dist/db/Db.d.ts +113 -0
  203. package/dist/db/Db.d.ts.map +1 -0
  204. package/dist/db/Db.js +402 -0
  205. package/dist/db/Db.js.map +1 -0
  206. package/dist/db/Schema.d.ts +168 -0
  207. package/dist/db/Schema.d.ts.map +1 -0
  208. package/dist/db/Schema.js +229 -0
  209. package/dist/db/Schema.js.map +1 -0
  210. package/dist/db/tables/invitations.d.ts +84 -0
  211. package/dist/db/tables/invitations.d.ts.map +1 -0
  212. package/dist/db/tables/invitations.js +165 -0
  213. package/dist/db/tables/invitations.js.map +1 -0
  214. package/dist/db/tables/memberships.d.ts +108 -0
  215. package/dist/db/tables/memberships.d.ts.map +1 -0
  216. package/dist/db/tables/memberships.js +153 -0
  217. package/dist/db/tables/memberships.js.map +1 -0
  218. package/dist/db/tables/organizations.d.ts +123 -0
  219. package/dist/db/tables/organizations.d.ts.map +1 -0
  220. package/dist/db/tables/organizations.js +170 -0
  221. package/dist/db/tables/organizations.js.map +1 -0
  222. package/dist/db/tables/projects.d.ts +65 -0
  223. package/dist/db/tables/projects.d.ts.map +1 -0
  224. package/dist/db/tables/projects.js +75 -0
  225. package/dist/db/tables/projects.js.map +1 -0
  226. package/dist/db/tables/sponsoredTransactions.d.ts +120 -0
  227. package/dist/db/tables/sponsoredTransactions.d.ts.map +1 -0
  228. package/dist/db/tables/sponsoredTransactions.js +161 -0
  229. package/dist/db/tables/sponsoredTransactions.js.map +1 -0
  230. package/dist/db/tables/users.d.ts +48 -0
  231. package/dist/db/tables/users.d.ts.map +1 -0
  232. package/dist/db/tables/users.js +65 -0
  233. package/dist/db/tables/users.js.map +1 -0
  234. package/dist/db/tables/verifiedTokens.d.ts +53 -0
  235. package/dist/db/tables/verifiedTokens.d.ts.map +1 -0
  236. package/dist/db/tables/verifiedTokens.js +74 -0
  237. package/dist/db/tables/verifiedTokens.js.map +1 -0
  238. package/dist/db/tables/webhookDeliveries.d.ts +71 -0
  239. package/dist/db/tables/webhookDeliveries.d.ts.map +1 -0
  240. package/dist/db/tables/webhookDeliveries.js +119 -0
  241. package/dist/db/tables/webhookDeliveries.js.map +1 -0
  242. package/dist/db/tables/webhookSubscriptions.d.ts +158 -0
  243. package/dist/db/tables/webhookSubscriptions.d.ts.map +1 -0
  244. package/dist/db/tables/webhookSubscriptions.js +272 -0
  245. package/dist/db/tables/webhookSubscriptions.js.map +1 -0
  246. package/dist/handlers/internal/executionError.d.ts +25 -0
  247. package/dist/handlers/internal/executionError.d.ts.map +1 -0
  248. package/dist/handlers/internal/executionError.js +186 -0
  249. package/dist/handlers/internal/executionError.js.map +1 -0
  250. package/dist/handlers/internal/multisig.d.ts +233 -0
  251. package/dist/handlers/internal/multisig.d.ts.map +1 -0
  252. package/dist/handlers/internal/multisig.js +542 -0
  253. package/dist/handlers/internal/multisig.js.map +1 -0
  254. package/dist/handlers/internal/requestListener.d.ts +124 -0
  255. package/dist/handlers/internal/requestListener.d.ts.map +1 -0
  256. package/dist/handlers/internal/requestListener.js +173 -0
  257. package/dist/handlers/internal/requestListener.js.map +1 -0
  258. package/dist/handlers/internal/sponsorship.d.ts +113 -0
  259. package/dist/handlers/internal/sponsorship.d.ts.map +1 -0
  260. package/dist/handlers/internal/sponsorship.js +128 -0
  261. package/dist/handlers/internal/sponsorship.js.map +1 -0
  262. package/dist/handlers/internal/types.d.ts +284 -0
  263. package/dist/handlers/internal/types.d.ts.map +1 -0
  264. package/dist/handlers/internal/types.js +2 -0
  265. package/dist/handlers/internal/types.js.map +1 -0
  266. package/dist/handlers/internal/utils.d.ts +34 -0
  267. package/dist/handlers/internal/utils.d.ts.map +1 -0
  268. package/dist/handlers/internal/utils.js +131 -0
  269. package/dist/handlers/internal/utils.js.map +1 -0
  270. package/dist/handlers/relay.d.ts +123 -0
  271. package/dist/handlers/relay.d.ts.map +1 -0
  272. package/dist/handlers/relay.js +1278 -0
  273. package/dist/handlers/relay.js.map +1 -0
  274. package/dist/index.d.ts +4 -2
  275. package/dist/index.d.ts.map +1 -1
  276. package/dist/index.js +4 -2
  277. package/dist/index.js.map +1 -1
  278. package/dist/internal/Auth.d.ts +224 -16
  279. package/dist/internal/Auth.d.ts.map +1 -1
  280. package/dist/internal/Auth.js +572 -33
  281. package/dist/internal/Auth.js.map +1 -1
  282. package/dist/internal/Log.d.ts +7 -3
  283. package/dist/internal/Log.d.ts.map +1 -1
  284. package/dist/internal/Log.js +4 -0
  285. package/dist/internal/Log.js.map +1 -1
  286. package/dist/internal/OpenApi.d.ts +0 -19
  287. package/dist/internal/OpenApi.d.ts.map +1 -1
  288. package/dist/internal/OpenApi.js +0 -57
  289. package/dist/internal/OpenApi.js.map +1 -1
  290. package/dist/internal/RpcSchema.d.ts +10 -0
  291. package/dist/internal/RpcSchema.d.ts.map +1 -0
  292. package/dist/internal/RpcSchema.js +2 -0
  293. package/dist/internal/RpcSchema.js.map +1 -0
  294. package/dist/internal/Store.d.ts +49 -4
  295. package/dist/internal/Store.d.ts.map +1 -1
  296. package/dist/internal/Store.js +81 -5
  297. package/dist/internal/Store.js.map +1 -1
  298. package/dist/internal/VerifiedTokens.d.ts +15 -34
  299. package/dist/internal/VerifiedTokens.d.ts.map +1 -1
  300. package/dist/internal/VerifiedTokens.js +115 -159
  301. package/dist/internal/VerifiedTokens.js.map +1 -1
  302. package/dist/internal/Viem.d.ts +84 -0
  303. package/dist/internal/Viem.d.ts.map +1 -1
  304. package/dist/internal/Webhooks.d.ts +50 -36
  305. package/dist/internal/Webhooks.d.ts.map +1 -1
  306. package/dist/internal/Webhooks.js +92 -205
  307. package/dist/internal/Webhooks.js.map +1 -1
  308. package/package.json +37 -6
  309. package/src/ApiKey.test.ts +3 -3
  310. package/src/ApiKey.ts +11 -12
  311. package/src/ApiKeys.test.ts +278 -0
  312. package/src/ApiKeys.ts +358 -0
  313. package/src/App.test-d.ts +1 -1
  314. package/src/App.test.ts +40508 -19083
  315. package/src/App.ts +239 -416
  316. package/src/Client.test-d.ts +307 -16
  317. package/src/Handler.ts +154 -0
  318. package/src/Scope.ts +17 -4
  319. package/src/Webhooks.test.ts +8 -7
  320. package/src/Webhooks.ts +13 -7
  321. package/src/admin/Access.ts +1 -3
  322. package/src/admin/App.ts +19 -24
  323. package/src/admin/apps/api-keys.test.ts +70 -18
  324. package/src/admin/apps/api-keys.ts +92 -9
  325. package/src/admin/apps/scopes.test.ts +8 -0
  326. package/src/admin/apps/verified-tokens.test.ts +3 -30
  327. package/src/admin/apps/verified-tokens.ts +18 -37
  328. package/src/admin/ui.generated.ts +1 -1
  329. package/src/apps/composition.test.ts +66 -0
  330. package/src/apps/data/App.ts +295 -0
  331. package/src/apps/data/index.ts +2 -0
  332. package/src/apps/{activities.test.ts → data/routes/activities.test.ts} +3 -3
  333. package/src/apps/{activities.ts → data/routes/activities.ts} +15 -15
  334. package/src/apps/{addresses.ts → data/routes/addresses.ts} +6 -6
  335. package/src/apps/{balances.test.ts → data/routes/balances.test.ts} +6 -5
  336. package/src/apps/{balances.ts → data/routes/balances.ts} +46 -12
  337. package/src/apps/{blocks.test.ts → data/routes/blocks.test.ts} +4 -4
  338. package/src/apps/{blocks.ts → data/routes/blocks.ts} +14 -14
  339. package/src/apps/{coingecko.test.ts → data/routes/coingecko.test.ts} +2 -2
  340. package/src/apps/{coingecko.ts → data/routes/coingecko.ts} +14 -14
  341. package/src/apps/{exchanges.test.ts → data/routes/exchanges.test.ts} +2 -2
  342. package/src/apps/{exchanges.ts → data/routes/exchanges.ts} +20 -20
  343. package/src/apps/{fee-amm.test.ts → data/routes/fee-amm.test.ts} +3 -3
  344. package/src/apps/{fee-amm.ts → data/routes/fee-amm.ts} +18 -18
  345. package/src/apps/{indexer.test.ts → data/routes/indexer.test.ts} +27 -6
  346. package/src/apps/{indexer.ts → data/routes/indexer.ts} +13 -10
  347. package/src/apps/{receipts.test.ts → data/routes/receipts.test.ts} +4 -4
  348. package/src/apps/{receipts.ts → data/routes/receipts.ts} +13 -13
  349. package/src/apps/{rpc.test.ts → data/routes/rpc.test.ts} +142 -13
  350. package/src/apps/{rpc.ts → data/routes/rpc.ts} +7 -7
  351. package/src/apps/{tokenlist.test.ts → data/routes/tokenlist.test.ts} +8 -10
  352. package/src/apps/{tokenlist.ts → data/routes/tokenlist.ts} +9 -9
  353. package/src/apps/{tokens.test.ts → data/routes/tokens.test.ts} +6 -5
  354. package/src/apps/{tokens.ts → data/routes/tokens.ts} +20 -20
  355. package/src/apps/{transactions.test.ts → data/routes/transactions.test.ts} +4 -4
  356. package/src/apps/{transactions.ts → data/routes/transactions.ts} +15 -15
  357. package/src/apps/{transfers.test.ts → data/routes/transfers.test.ts} +3 -3
  358. package/src/apps/{transfers.ts → data/routes/transfers.ts} +15 -15
  359. package/src/apps/{verified-tokens.test.ts → data/routes/verified-tokens.test.ts} +27 -15
  360. package/src/apps/{verified-tokens.ts → data/routes/verified-tokens.ts} +10 -10
  361. package/src/apps/{webhooks.test.ts → data/routes/webhooks.test.ts} +137 -150
  362. package/src/apps/{webhooks.ts → data/routes/webhooks.ts} +83 -81
  363. package/src/apps/docs/App.ts +136 -0
  364. package/src/apps/docs/index.ts +1 -0
  365. package/src/apps/index.ts +3 -0
  366. package/src/apps/metadata.ts +23 -0
  367. package/src/apps/platform/App.ts +130 -0
  368. package/src/apps/platform/index.ts +1 -0
  369. package/src/apps/platform/routes/api-keys.test.ts +330 -0
  370. package/src/apps/platform/routes/api-keys.ts +427 -0
  371. package/src/apps/platform/routes/invitations.test.ts +361 -0
  372. package/src/apps/platform/routes/invitations.ts +519 -0
  373. package/src/apps/platform/routes/me.test.ts +121 -0
  374. package/src/apps/platform/routes/me.ts +106 -0
  375. package/src/apps/platform/routes/members.test.ts +195 -0
  376. package/src/apps/platform/routes/members.ts +313 -0
  377. package/src/apps/platform/routes/orgs.test.ts +313 -0
  378. package/src/apps/platform/routes/orgs.ts +343 -0
  379. package/src/apps/platform/routes/projects.test.ts +181 -0
  380. package/src/apps/platform/routes/projects.ts +367 -0
  381. package/src/apps/relay/App.test.ts +484 -0
  382. package/src/apps/relay/App.ts +128 -0
  383. package/src/apps/relay/Sponsorships.test.ts +375 -0
  384. package/src/apps/relay/Sponsorships.ts +305 -0
  385. package/src/apps/relay/index.ts +2 -0
  386. package/src/{Cli.test.ts → cli/Cli.test.ts} +10 -9
  387. package/src/{Cli.ts → cli/Cli.ts} +16 -9
  388. package/src/cli/bin.ts +4 -0
  389. package/src/cli/commands/admin.test.ts +71 -0
  390. package/src/cli/commands/admin.ts +60 -0
  391. package/src/cloudflare.ts +10 -0
  392. package/src/db/Db.test.ts +84 -0
  393. package/src/db/Db.ts +542 -0
  394. package/src/db/Schema.ts +301 -0
  395. package/src/db/tables/invitations.ts +198 -0
  396. package/src/db/tables/memberships.ts +208 -0
  397. package/src/db/tables/organizations.test.ts +160 -0
  398. package/src/db/tables/organizations.ts +232 -0
  399. package/src/db/tables/projects.ts +107 -0
  400. package/src/db/tables/sponsoredTransactions.test.ts +218 -0
  401. package/src/db/tables/sponsoredTransactions.ts +236 -0
  402. package/src/db/tables/users.ts +85 -0
  403. package/src/db/tables/verifiedTokens.ts +111 -0
  404. package/src/db/tables/webhookDeliveries.ts +159 -0
  405. package/src/db/tables/webhookSubscriptions.ts +358 -0
  406. package/src/handlers/internal/executionError.ts +207 -0
  407. package/src/handlers/internal/multisig.test.ts +818 -0
  408. package/src/handlers/internal/multisig.ts +823 -0
  409. package/src/handlers/internal/requestListener.ts +273 -0
  410. package/src/handlers/internal/sponsorship.ts +245 -0
  411. package/src/handlers/internal/types.ts +378 -0
  412. package/src/handlers/internal/utils.ts +153 -0
  413. package/src/handlers/relay.test.ts +2035 -0
  414. package/src/handlers/relay.ts +1623 -0
  415. package/src/index.ts +4 -2
  416. package/src/internal/Auth.test.ts +337 -21
  417. package/src/internal/Auth.ts +783 -44
  418. package/src/internal/Cursor.test.ts +3 -2
  419. package/src/internal/Log.test.ts +1 -1
  420. package/src/internal/Log.ts +11 -3
  421. package/src/internal/MetricSink.ts +1 -1
  422. package/src/internal/OpenApi.ts +0 -59
  423. package/src/internal/RateLimit.test.ts +1 -1
  424. package/src/internal/RpcSchema.ts +10 -0
  425. package/src/internal/Store.test.ts +150 -10
  426. package/src/internal/Store.ts +136 -11
  427. package/src/internal/Tidx.local.test.ts +1 -1
  428. package/src/internal/VerifiedTokens.test.ts +99 -115
  429. package/src/internal/VerifiedTokens.ts +123 -175
  430. package/src/internal/WebhookDestination.test.ts +1 -1
  431. package/src/internal/Webhooks.test.ts +111 -111
  432. package/src/internal/Webhooks.ts +103 -221
  433. package/dist/ApiKeySource.d.ts +0 -166
  434. package/dist/ApiKeySource.d.ts.map +0 -1
  435. package/dist/ApiKeySource.js +0 -234
  436. package/dist/ApiKeySource.js.map +0 -1
  437. package/dist/Cli.d.ts.map +0 -1
  438. package/dist/Cli.js +0 -13
  439. package/dist/Cli.js.map +0 -1
  440. package/dist/apps/activities.js.map +0 -1
  441. package/dist/apps/addresses.js.map +0 -1
  442. package/dist/apps/balances.d.ts.map +0 -1
  443. package/dist/apps/balances.js.map +0 -1
  444. package/dist/apps/blocks.d.ts.map +0 -1
  445. package/dist/apps/blocks.js.map +0 -1
  446. package/dist/apps/coingecko.d.ts.map +0 -1
  447. package/dist/apps/coingecko.js.map +0 -1
  448. package/dist/apps/exchanges.d.ts.map +0 -1
  449. package/dist/apps/exchanges.js.map +0 -1
  450. package/dist/apps/fee-amm.d.ts.map +0 -1
  451. package/dist/apps/fee-amm.js.map +0 -1
  452. package/dist/apps/indexer.d.ts.map +0 -1
  453. package/dist/apps/indexer.js.map +0 -1
  454. package/dist/apps/receipts.d.ts.map +0 -1
  455. package/dist/apps/receipts.js.map +0 -1
  456. package/dist/apps/rpc.d.ts.map +0 -1
  457. package/dist/apps/rpc.js.map +0 -1
  458. package/dist/apps/tokenlist.d.ts.map +0 -1
  459. package/dist/apps/tokenlist.js.map +0 -1
  460. package/dist/apps/tokens.d.ts.map +0 -1
  461. package/dist/apps/tokens.js.map +0 -1
  462. package/dist/apps/transactions.d.ts.map +0 -1
  463. package/dist/apps/transactions.js.map +0 -1
  464. package/dist/apps/transfers.d.ts.map +0 -1
  465. package/dist/apps/transfers.js.map +0 -1
  466. package/dist/apps/verified-tokens.d.ts.map +0 -1
  467. package/dist/apps/verified-tokens.js.map +0 -1
  468. package/dist/apps/webhooks.js.map +0 -1
  469. package/dist/internal/OpenApi.fonts.d.ts.map +0 -1
  470. package/dist/internal/OpenApi.fonts.js.map +0 -1
  471. package/dist/internal/OpenApi.logo.d.ts.map +0 -1
  472. package/dist/internal/OpenApi.logo.js.map +0 -1
  473. package/seeds/31318/icons/0x20c0000000000000000000000000000000000000.svg +0 -1
  474. package/seeds/31318/icons/0x20c0000000000000000000000000000000000001.svg +0 -1
  475. package/seeds/31318/icons/0x20c0000000000000000000000000000000000002.svg +0 -1
  476. package/seeds/31318/icons/0x20c0000000000000000000000000000000000003.svg +0 -1
  477. package/seeds/31318/verified-tokens.json +0 -30
  478. package/seeds/4217/icons/0x20c0000000000000000000000000000000000000.svg +0 -25
  479. package/seeds/4217/icons/0x20c000000000000000000000048c8f36df1c9a4a.svg +0 -1
  480. package/seeds/4217/icons/0x20c0000000000000000000000520792dcccccccc.svg +0 -1
  481. package/seeds/4217/icons/0x20c0000000000000000000000a6da882d075a4c3.svg +0 -4
  482. package/seeds/4217/icons/0x20c000000000000000000000111111111e910f0f.svg +0 -30
  483. package/seeds/4217/icons/0x20c00000000000000000000014f22ca97301eb73.svg +0 -1
  484. package/seeds/4217/icons/0x20c0000000000000000000001621e21f71cf12fb.svg +0 -1
  485. package/seeds/4217/icons/0x20c0000000000000000000002f52d5cc21a3207b.svg +0 -1
  486. package/seeds/4217/icons/0x20c0000000000000000000003158081efd85bfc2.svg +0 -11
  487. package/seeds/4217/icons/0x20c0000000000000000000003554d28269e0f3c2.svg +0 -1
  488. package/seeds/4217/icons/0x20c000000000000000000000383a23bacb546ab9.svg +0 -1
  489. package/seeds/4217/icons/0x20c00000000000000000000042109aef2f8b28e1.png +0 -0
  490. package/seeds/4217/icons/0x20c0000000000000000000005c0bac7cef389a11.svg +0 -1
  491. package/seeds/4217/icons/0x20c0000000000000000000006fd9a167923ba194.png +0 -0
  492. package/seeds/4217/icons/0x20c0000000000000000000007f7ba549dd0251b9.svg +0 -1
  493. package/seeds/4217/icons/0x20c0000000000000000000008191667423f70e67.svg +0 -5
  494. package/seeds/4217/icons/0x20c0000000000000000000008ee4fcff88888888.svg +0 -1
  495. package/seeds/4217/icons/0x20c0000000000000000000009a4a4b17e0dc6651.svg +0 -1
  496. package/seeds/4217/icons/0x20c000000000000000000000ab02d39df30bd17e.svg +0 -1
  497. package/seeds/4217/icons/0x20c000000000000000000000ae247a1130450f09.svg +0 -1
  498. package/seeds/4217/icons/0x20c000000000000000000000aeed2ec36a54d0e5.svg +0 -1
  499. package/seeds/4217/icons/0x20c000000000000000000000b9537d11c60e8b50.svg +0 -1
  500. package/seeds/4217/icons/0x20c000000000000000000000bd95bfb69fbe6ce3.svg +0 -1
  501. package/seeds/4217/icons/0x20c000000000000000000000c412ec89d0c08be5.svg +0 -1
  502. package/seeds/4217/icons/0x20c000000000000000000000f047dd7018e50367.png +0 -0
  503. package/seeds/4217/verified-tokens.json +0 -177
  504. package/seeds/42431/icons/0x20c0000000000000000000000000000000000000.svg +0 -25
  505. package/seeds/42431/icons/0x20c0000000000000000000000000000000000001.svg +0 -1
  506. package/seeds/42431/icons/0x20c0000000000000000000000000000000000002.svg +0 -1
  507. package/seeds/42431/icons/0x20c0000000000000000000000000000000000003.svg +0 -1
  508. package/seeds/42431/icons/0x20c0000000000000000000009e8d7eb59b783726.svg +0 -1
  509. package/seeds/42431/icons/0x20c000000000000000000000d72572838bbee59c.svg +0 -1
  510. package/seeds/42431/verified-tokens.json +0 -44
  511. package/seeds/openrpc/README.md +0 -27
  512. package/seeds/openrpc/execution-apis.json +0 -8989
  513. package/src/ApiKeySource.test-d.ts +0 -11
  514. package/src/ApiKeySource.test.ts +0 -295
  515. package/src/ApiKeySource.ts +0 -303
  516. /package/src/{internal/OpenApi.fonts.ts → apps/docs/fonts.ts} +0 -0
  517. /package/src/{internal/OpenApi.logo.ts → apps/docs/logo.ts} +0 -0
@@ -0,0 +1,208 @@
1
+ import type { Selectable } from 'kysely'
2
+
3
+ import type * as Db from '../Db.js'
4
+ import type * as db_Schema from '../Schema.js'
5
+
6
+ /** Columns of the `memberships` table, derived from `Schema.Membership`. */
7
+ export type Table = db_Schema.Membership
8
+
9
+ /** A stored membership row. */
10
+ export type Record = Selectable<Table>
11
+
12
+ /** A membership role. */
13
+ export type Role = Record['role']
14
+
15
+ /** Fixed membership roles, least to most privileged. */
16
+ export const roles = ['member', 'admin', 'owner'] as const satisfies readonly Role[]
17
+
18
+ /** Privilege rank per role; higher ranks satisfy lower minimums. */
19
+ export const rank = { admin: 1, member: 0, owner: 2 } as const satisfies { [role in Role]: number }
20
+
21
+ /**
22
+ * Inserts a membership and returns the stored record.
23
+ *
24
+ * @param db - The database.
25
+ * @param input - The membership to insert.
26
+ * @returns The stored record.
27
+ */
28
+ export function create(db: Db.Db, input: create.Input): Promise<Record> {
29
+ const now = new Date().toISOString()
30
+ return db.kysely
31
+ .insertInto('memberships')
32
+ .values({
33
+ createdAt: now,
34
+ orgId: input.orgId,
35
+ role: input.role,
36
+ updatedAt: now,
37
+ userId: input.userId,
38
+ })
39
+ .returningAll()
40
+ .executeTakeFirstOrThrow()
41
+ }
42
+
43
+ export declare namespace create {
44
+ /** Fields accepted when inserting a membership. */
45
+ type Input = {
46
+ /** Organization id (`org_…`). */
47
+ orgId: string
48
+ /** Granted role. */
49
+ role: Role
50
+ /** Member user id (`usr_…`). */
51
+ userId: string
52
+ }
53
+ }
54
+
55
+ /**
56
+ * Reads one user's membership in an organization.
57
+ *
58
+ * @param db - The database.
59
+ * @param orgId - The organization id (`org_…`).
60
+ * @param userId - The member user id (`usr_…`).
61
+ * @returns The record, or `undefined` when absent.
62
+ */
63
+ export function get(db: Db.Db, orgId: string, userId: string): Promise<Record | undefined> {
64
+ return db.kysely
65
+ .selectFrom('memberships')
66
+ .selectAll()
67
+ .where('orgId', '=', orgId)
68
+ .where('userId', '=', userId)
69
+ .executeTakeFirst()
70
+ }
71
+
72
+ /**
73
+ * Lists an organization's memberships, oldest first (stable member ordering).
74
+ *
75
+ * @param db - The database.
76
+ * @param orgId - The organization id (`org_…`).
77
+ * @returns The records.
78
+ */
79
+ export function listByOrg(db: Db.Db, orgId: string): Promise<Record[]> {
80
+ return db.kysely
81
+ .selectFrom('memberships')
82
+ .selectAll()
83
+ .where('orgId', '=', orgId)
84
+ .orderBy('createdAt', 'asc')
85
+ .execute()
86
+ }
87
+
88
+ /**
89
+ * Lists an organization's memberships joined with member identity (address,
90
+ * email), oldest first.
91
+ *
92
+ * @param db - The database.
93
+ * @param orgId - The organization id (`org_…`).
94
+ * @returns The records with `address`/`email` from the member's user row.
95
+ */
96
+ export function listByOrgDetailed(
97
+ db: Db.Db,
98
+ orgId: string,
99
+ ): Promise<(Record & { address: string | null; email: string | null })[]> {
100
+ return db.kysely
101
+ .selectFrom('memberships')
102
+ .innerJoin('users', 'users.id', 'memberships.userId')
103
+ .where('memberships.orgId', '=', orgId)
104
+ .selectAll('memberships')
105
+ .select(['users.address', 'users.email'])
106
+ .orderBy('memberships.createdAt', 'asc')
107
+ .execute()
108
+ }
109
+
110
+ /**
111
+ * Changes a member's role atomically, refusing to demote the last owner. The
112
+ * org's owner rows are locked for the transaction, so a concurrent demotion or
113
+ * removal cannot race two guards into leaving the organization ownerless.
114
+ *
115
+ * @param db - The database.
116
+ * @param orgId - The organization id (`org_…`).
117
+ * @param userId - The member user id (`usr_…`).
118
+ * @param input - The fields to update.
119
+ * @returns The updated record, or an `error` when absent or the last owner.
120
+ */
121
+ export function update(
122
+ db: Db.Db,
123
+ orgId: string,
124
+ userId: string,
125
+ input: update.Input,
126
+ ): Promise<update.Result> {
127
+ const now = new Date().toISOString()
128
+ return db.kysely.transaction().execute(async (trx) => {
129
+ const owners = await trx
130
+ .selectFrom('memberships')
131
+ .select('userId')
132
+ .where('orgId', '=', orgId)
133
+ .where('role', '=', 'owner')
134
+ .forUpdate()
135
+ .execute()
136
+ const current = await trx
137
+ .selectFrom('memberships')
138
+ .selectAll()
139
+ .where('orgId', '=', orgId)
140
+ .where('userId', '=', userId)
141
+ .executeTakeFirst()
142
+ if (!current) return { error: 'not_found' as const }
143
+ if (current.role === 'owner' && input.role !== 'owner' && owners.length <= 1)
144
+ return { error: 'last_owner' as const }
145
+ const record = await trx
146
+ .updateTable('memberships')
147
+ .set({ role: input.role, updatedAt: now })
148
+ .where('orgId', '=', orgId)
149
+ .where('userId', '=', userId)
150
+ .returningAll()
151
+ .executeTakeFirstOrThrow()
152
+ return { record }
153
+ })
154
+ }
155
+
156
+ export declare namespace update {
157
+ /** Mutable membership fields. */
158
+ type Input = {
159
+ /** New role. */
160
+ role: Role
161
+ }
162
+
163
+ /** Outcome of a guarded role change. */
164
+ type Result =
165
+ | { error: 'last_owner' | 'not_found'; record?: undefined }
166
+ | { error?: undefined; record: Record }
167
+ }
168
+
169
+ /**
170
+ * Deletes a membership atomically, refusing to remove the last owner. Locks
171
+ * the org's owner rows for the transaction (see {@link update}) so concurrent
172
+ * removals cannot race the organization ownerless.
173
+ *
174
+ * @param db - The database.
175
+ * @param orgId - The organization id (`org_…`).
176
+ * @param userId - The member user id (`usr_…`).
177
+ * @returns `removed` on success, otherwise why the removal was refused.
178
+ */
179
+ export function remove(db: Db.Db, orgId: string, userId: string): Promise<remove.Result> {
180
+ return db.kysely.transaction().execute(async (trx) => {
181
+ const owners = await trx
182
+ .selectFrom('memberships')
183
+ .select('userId')
184
+ .where('orgId', '=', orgId)
185
+ .where('role', '=', 'owner')
186
+ .forUpdate()
187
+ .execute()
188
+ const current = await trx
189
+ .selectFrom('memberships')
190
+ .selectAll()
191
+ .where('orgId', '=', orgId)
192
+ .where('userId', '=', userId)
193
+ .executeTakeFirst()
194
+ if (!current) return 'not_found'
195
+ if (current.role === 'owner' && owners.length <= 1) return 'last_owner'
196
+ await trx
197
+ .deleteFrom('memberships')
198
+ .where('orgId', '=', orgId)
199
+ .where('userId', '=', userId)
200
+ .execute()
201
+ return 'removed'
202
+ })
203
+ }
204
+
205
+ export declare namespace remove {
206
+ /** Outcome of a guarded removal. */
207
+ type Result = 'last_owner' | 'not_found' | 'removed'
208
+ }
@@ -0,0 +1,160 @@
1
+ import { nanoid } from 'nanoid'
2
+
3
+ import * as Webhooks from '../../internal/Webhooks.js'
4
+ import * as Db from '../Db.js'
5
+ import * as Organizations from './organizations.js'
6
+ import { postgresUrl } from '../../../test/containers.js'
7
+
8
+ const create = () => Db.postgres({ connectionString: postgresUrl, schema: `t_${nanoid()}` })
9
+
10
+ /** Redacts nondeterministic row fields (generated nanoid ids, timestamps). */
11
+ function redact(record: Organizations.Record) {
12
+ return {
13
+ ...record,
14
+ createdAt: '<timestamp>',
15
+ id: /^org_[\w-]{21}$/.test(record.id) ? 'org_<id>' : record.id,
16
+ updatedAt: '<timestamp>',
17
+ }
18
+ }
19
+
20
+ describe('create', () => {
21
+ test('behavior: inserts with a generated id and defaults', async () => {
22
+ const db = create()
23
+ await db.migrate()
24
+ const record = await Organizations.create(db, { name: 'Acme, Inc.' })
25
+ expect(record.id).toMatch(/^org_/)
26
+ expect(redact(record)).toMatchInlineSnapshot(`
27
+ {
28
+ "createdAt": "<timestamp>",
29
+ "createdBy": null,
30
+ "id": "org_<id>",
31
+ "name": "Acme, Inc.",
32
+ "updatedAt": "<timestamp>",
33
+ "userId": null,
34
+ }
35
+ `)
36
+ await db.close()
37
+ })
38
+
39
+ test('behavior: preserves an explicit id and createdBy', async () => {
40
+ const db = create()
41
+ await db.migrate()
42
+ const record = await Organizations.create(db, {
43
+ createdBy: 'admin@tempo.xyz',
44
+ id: 'org_explicit',
45
+ name: 'Explicit',
46
+ })
47
+ expect(redact(record)).toMatchInlineSnapshot(`
48
+ {
49
+ "createdAt": "<timestamp>",
50
+ "createdBy": "admin@tempo.xyz",
51
+ "id": "org_explicit",
52
+ "name": "Explicit",
53
+ "updatedAt": "<timestamp>",
54
+ "userId": null,
55
+ }
56
+ `)
57
+ await db.close()
58
+ })
59
+ })
60
+
61
+ describe('get', () => {
62
+ test('behavior: returns undefined when absent', async () => {
63
+ const db = create()
64
+ await db.migrate()
65
+ expect(await Organizations.get(db, 'org_missing')).toBeUndefined()
66
+ await db.close()
67
+ })
68
+ })
69
+
70
+ describe('list', () => {
71
+ test('behavior: lists newest first', async () => {
72
+ const db = create()
73
+ await db.migrate()
74
+ await Organizations.create(db, { id: 'org_a', name: 'A' })
75
+ // Distinct createdAt for a deterministic order.
76
+ await new Promise((resolve) => setTimeout(resolve, 5))
77
+ await Organizations.create(db, { id: 'org_b', name: 'B' })
78
+ expect((await Organizations.list(db)).map((record) => record.id)).toMatchInlineSnapshot(`
79
+ [
80
+ "org_b",
81
+ "org_a",
82
+ ]
83
+ `)
84
+ await db.close()
85
+ })
86
+ })
87
+
88
+ describe('update', () => {
89
+ test('behavior: renames and bumps updatedAt', async () => {
90
+ const db = create()
91
+ await db.migrate()
92
+ const created = await Organizations.create(db, { id: 'org_1', name: 'Before' })
93
+ await new Promise((resolve) => setTimeout(resolve, 5))
94
+ const updated = await Organizations.update(db, 'org_1', { name: 'After' })
95
+ expect(updated?.name).toMatchInlineSnapshot(`"After"`)
96
+ expect(updated && updated.updatedAt > created.updatedAt).toBe(true)
97
+ await db.close()
98
+ })
99
+
100
+ test('behavior: returns undefined when absent', async () => {
101
+ const db = create()
102
+ await db.migrate()
103
+ expect(await Organizations.update(db, 'org_missing', { name: 'X' })).toBeUndefined()
104
+ await db.close()
105
+ })
106
+ })
107
+
108
+ describe('upsert', () => {
109
+ test('behavior: inserts when absent, defaulting name to the id', async () => {
110
+ const db = create()
111
+ await db.migrate()
112
+ await Organizations.upsert(db, { id: 'key_fallback' })
113
+ expect((await Organizations.get(db, 'key_fallback'))?.name).toMatchInlineSnapshot(
114
+ `"key_fallback"`,
115
+ )
116
+ await db.close()
117
+ })
118
+
119
+ test('behavior: leaves an existing row untouched', async () => {
120
+ const db = create()
121
+ await db.migrate()
122
+ await Organizations.create(db, { id: 'org_1', name: 'Original' })
123
+ await Organizations.upsert(db, { id: 'org_1', name: 'Clobbered' })
124
+ expect((await Organizations.get(db, 'org_1'))?.name).toMatchInlineSnapshot(`"Original"`)
125
+ await db.close()
126
+ })
127
+ })
128
+
129
+ describe('deleteOrganization', () => {
130
+ test('behavior: deletes api-key-owned webhook subscriptions', async () => {
131
+ const db = create()
132
+ await db.migrate()
133
+ await Organizations.create(db, { id: 'org_1', name: 'One' })
134
+ await Organizations.create(db, { id: 'org_2', name: 'Two' })
135
+ const deletedOrg = { orgId: 'org_1', type: 'api_key' } as const
136
+ const keptOrg = { orgId: 'org_2', type: 'api_key' } as const
137
+ const keptMpp = { payer: 'did:pkh:eip155:1:0xabc', type: 'mpp' } as const
138
+ await Webhooks.createSubscription(db, subscription(deletedOrg))
139
+ const keptApiKey = await Webhooks.createSubscription(db, subscription(keptOrg))
140
+ const keptMppSubscription = await Webhooks.createSubscription(db, subscription(keptMpp))
141
+
142
+ expect(await Organizations.deleteOrganization(db, 'org_1')).toBe(true)
143
+
144
+ expect(await Webhooks.listSubscriptions(db, deletedOrg)).toEqual([])
145
+ const active = await Webhooks.listActive(db, 4217, 'token:transfer')
146
+ expect(active.map(({ id }) => id).sort()).toEqual(
147
+ [keptApiKey.id, keptMppSubscription.id].sort(),
148
+ )
149
+ await db.close()
150
+ })
151
+ })
152
+
153
+ function subscription(owner: Webhooks.Owner): Webhooks.CreateInput {
154
+ return {
155
+ chainId: 4217,
156
+ destination: { type: 'url', url: 'https://hooks.example.com/endpoint' },
157
+ eventType: 'token:transfer',
158
+ owner,
159
+ }
160
+ }
@@ -0,0 +1,232 @@
1
+ import type { Selectable } from 'kysely'
2
+ import { nanoid } from 'nanoid'
3
+
4
+ import type * as Db from '../Db.js'
5
+ import type * as db_Schema from '../Schema.js'
6
+
7
+ /** Columns of the `organizations` table, derived from `Schema.Organization`. */
8
+ export type Table = db_Schema.Organization
9
+
10
+ /** A stored organization row. */
11
+ export type Record = Selectable<Table>
12
+
13
+ /**
14
+ * Inserts an organization and returns the stored record. The `id` defaults to
15
+ * a generated `org_…` handle when omitted.
16
+ *
17
+ * @param db - The database.
18
+ * @param input - The organization to insert.
19
+ * @returns The stored record.
20
+ */
21
+ export function create(db: Db.Db, input: create.Input): Promise<Record> {
22
+ const now = new Date().toISOString()
23
+ return db.kysely
24
+ .insertInto('organizations')
25
+ .values({
26
+ createdAt: now,
27
+ createdBy: input.createdBy ?? null,
28
+ id: input.id ?? `org_${nanoid()}`,
29
+ name: input.name,
30
+ updatedAt: now,
31
+ userId: input.userId ?? null,
32
+ })
33
+ .returningAll()
34
+ .executeTakeFirstOrThrow()
35
+ }
36
+
37
+ export declare namespace create {
38
+ /** Fields accepted when inserting an organization. */
39
+ type Input = {
40
+ /** Identity creating the organization (e.g. admin email), recorded for audit. */
41
+ createdBy?: string | undefined
42
+ /** Explicit id; a generated `org_…` handle is used when omitted. */
43
+ id?: string | undefined
44
+ /** Human-readable organization name. */
45
+ name: string
46
+ /** Owning user id (`usr_…`); null for organizations created by the super admin. */
47
+ userId?: string | undefined
48
+ }
49
+ }
50
+
51
+ /**
52
+ * Inserts an organization owned by `userId` — the org row plus its `owner`
53
+ * membership, atomically.
54
+ *
55
+ * @param db - The database.
56
+ * @param input - The organization to insert.
57
+ * @returns The stored record.
58
+ */
59
+ export function createOwned(db: Db.Db, input: createOwned.Input): Promise<Record> {
60
+ const now = new Date().toISOString()
61
+ return db.kysely.transaction().execute(async (trx) => {
62
+ const record = await trx
63
+ .insertInto('organizations')
64
+ .values({
65
+ createdAt: now,
66
+ createdBy: input.userId,
67
+ id: `org_${nanoid()}`,
68
+ name: input.name,
69
+ updatedAt: now,
70
+ userId: input.userId,
71
+ })
72
+ .returningAll()
73
+ .executeTakeFirstOrThrow()
74
+ await trx
75
+ .insertInto('memberships')
76
+ .values({
77
+ createdAt: now,
78
+ orgId: record.id,
79
+ role: 'owner',
80
+ updatedAt: now,
81
+ userId: input.userId,
82
+ })
83
+ .execute()
84
+ return record
85
+ })
86
+ }
87
+
88
+ export declare namespace createOwned {
89
+ /** Fields accepted when inserting a user-owned organization. */
90
+ type Input = {
91
+ /** Human-readable organization name. */
92
+ name: string
93
+ /** Owning user id (`usr_…`), granted the `owner` membership. */
94
+ userId: string
95
+ }
96
+ }
97
+
98
+ /**
99
+ * Deletes an organization and its owned rows atomically.
100
+ *
101
+ * @param db - The database.
102
+ * @param id - The organization id (`org_…`).
103
+ * @returns Whether the organization existed and was deleted.
104
+ */
105
+ export function deleteOrganization(db: Db.Db, id: string): Promise<boolean> {
106
+ return db.kysely.transaction().execute(async (trx) => {
107
+ await trx
108
+ .deleteFrom('webhook_subscriptions')
109
+ .where('ownerType', '=', 'api_key')
110
+ .where('ownerId', '=', id)
111
+ .execute()
112
+ await trx.deleteFrom('invitations').where('orgId', '=', id).execute()
113
+ await trx.deleteFrom('memberships').where('orgId', '=', id).execute()
114
+ await trx.deleteFrom('projects').where('orgId', '=', id).execute()
115
+ const result = await trx.deleteFrom('organizations').where('id', '=', id).executeTakeFirst()
116
+ return result.numDeletedRows > 0n
117
+ })
118
+ }
119
+
120
+ /**
121
+ * Reads an organization by id.
122
+ *
123
+ * @param db - The database.
124
+ * @param id - The organization id (`org_…`).
125
+ * @returns The record, or `undefined` when absent.
126
+ */
127
+ export function get(db: Db.Db, id: string): Promise<Record | undefined> {
128
+ return db.kysely.selectFrom('organizations').selectAll().where('id', '=', id).executeTakeFirst()
129
+ }
130
+
131
+ /**
132
+ * Lists organizations, newest first.
133
+ *
134
+ * @param db - The database.
135
+ * @returns The records.
136
+ */
137
+ export function list(db: Db.Db): Promise<Record[]> {
138
+ return db.kysely.selectFrom('organizations').selectAll().orderBy('createdAt', 'desc').execute()
139
+ }
140
+
141
+ /**
142
+ * Lists organizations owned by `userId`, newest first.
143
+ *
144
+ * @param db - The database.
145
+ * @param userId - The owning user id (`usr_…`).
146
+ * @returns The records.
147
+ */
148
+ export function listByUser(db: Db.Db, userId: string): Promise<Record[]> {
149
+ return db.kysely
150
+ .selectFrom('organizations')
151
+ .selectAll()
152
+ .where('userId', '=', userId)
153
+ .orderBy('createdAt', 'desc')
154
+ .execute()
155
+ }
156
+
157
+ /**
158
+ * Lists organizations `userId` is a member of (any role), newest first.
159
+ *
160
+ * @param db - The database.
161
+ * @param userId - The member user id (`usr_…`).
162
+ * @returns The records.
163
+ */
164
+ export function listByMember(db: Db.Db, userId: string): Promise<Record[]> {
165
+ return db.kysely
166
+ .selectFrom('organizations')
167
+ .innerJoin('memberships', 'memberships.orgId', 'organizations.id')
168
+ .where('memberships.userId', '=', userId)
169
+ .selectAll('organizations')
170
+ .orderBy('organizations.createdAt', 'desc')
171
+ .execute()
172
+ }
173
+
174
+ /**
175
+ * Renames an organization, bumping `updatedAt`.
176
+ *
177
+ * @param db - The database.
178
+ * @param id - The organization id (`org_…`).
179
+ * @param input - The fields to update.
180
+ * @returns The updated record, or `undefined` when absent.
181
+ */
182
+ export function update(db: Db.Db, id: string, input: update.Input): Promise<Record | undefined> {
183
+ return db.kysely
184
+ .updateTable('organizations')
185
+ .set({ name: input.name, updatedAt: new Date().toISOString() })
186
+ .where('id', '=', id)
187
+ .returningAll()
188
+ .executeTakeFirst()
189
+ }
190
+
191
+ export declare namespace update {
192
+ /** Mutable organization fields. */
193
+ type Input = {
194
+ /** New human-readable organization name. */
195
+ name: string
196
+ }
197
+ }
198
+
199
+ /**
200
+ * Inserts an organization when absent (`ON CONFLICT DO NOTHING`) — the
201
+ * mint/backfill path, where a key's `orgId` must resolve to a real row. The
202
+ * `name` defaults to the id for degenerate orgs created by the mint fallback.
203
+ *
204
+ * @param db - The database.
205
+ * @param input - The organization to ensure.
206
+ */
207
+ export async function upsert(db: Db.Db, input: upsert.Input): Promise<void> {
208
+ const now = new Date().toISOString()
209
+ await db.kysely
210
+ .insertInto('organizations')
211
+ .values({
212
+ createdAt: now,
213
+ createdBy: input.createdBy ?? null,
214
+ id: input.id,
215
+ name: input.name ?? input.id,
216
+ updatedAt: now,
217
+ })
218
+ .onConflict((oc) => oc.column('id').doNothing())
219
+ .execute()
220
+ }
221
+
222
+ export declare namespace upsert {
223
+ /** Fields accepted when ensuring an organization exists. */
224
+ type Input = {
225
+ /** Identity creating the organization, recorded for audit. */
226
+ createdBy?: string | undefined
227
+ /** The organization id (`org_…`, or a mint-fallback key id). */
228
+ id: string
229
+ /** Human-readable organization name; defaults to the id. */
230
+ name?: string | undefined
231
+ }
232
+ }
@@ -0,0 +1,107 @@
1
+ import type { Selectable } from 'kysely'
2
+ import { nanoid } from 'nanoid'
3
+
4
+ import type * as Db from '../Db.js'
5
+ import type * as db_Schema from '../Schema.js'
6
+
7
+ /** Columns of the `projects` table, derived from `Schema.Project`. */
8
+ export type Table = db_Schema.Project
9
+
10
+ /** A stored project row. */
11
+ export type Record = Selectable<Table>
12
+
13
+ /**
14
+ * Inserts a project and returns the stored record.
15
+ *
16
+ * @param db - The database.
17
+ * @param input - The project to insert.
18
+ * @returns The stored record.
19
+ */
20
+ export function create(db: Db.Db, input: create.Input): Promise<Record> {
21
+ const now = new Date().toISOString()
22
+ return db.kysely
23
+ .insertInto('projects')
24
+ .values({
25
+ createdAt: now,
26
+ id: `prj_${nanoid()}`,
27
+ name: input.name,
28
+ orgId: input.orgId,
29
+ updatedAt: now,
30
+ })
31
+ .returningAll()
32
+ .executeTakeFirstOrThrow()
33
+ }
34
+
35
+ export declare namespace create {
36
+ /** Fields accepted when inserting a project. */
37
+ type Input = {
38
+ /** Human-readable project name. */
39
+ name: string
40
+ /** Owning organization id (`org_…`). */
41
+ orgId: string
42
+ }
43
+ }
44
+
45
+ /**
46
+ * Deletes a project.
47
+ *
48
+ * @param db - The database.
49
+ * @param id - The project id (`prj_…`).
50
+ * @returns Whether the project existed and was deleted.
51
+ */
52
+ export async function deleteProject(db: Db.Db, id: string): Promise<boolean> {
53
+ const result = await db.kysely.deleteFrom('projects').where('id', '=', id).executeTakeFirst()
54
+ return result.numDeletedRows > 0n
55
+ }
56
+
57
+ /**
58
+ * Reads a project by id.
59
+ *
60
+ * @param db - The database.
61
+ * @param id - The project id (`prj_…`).
62
+ * @returns The record, or `undefined` when absent.
63
+ */
64
+ export function get(db: Db.Db, id: string): Promise<Record | undefined> {
65
+ return db.kysely.selectFrom('projects').selectAll().where('id', '=', id).executeTakeFirst()
66
+ }
67
+
68
+ /**
69
+ * Lists an organization's projects, newest first.
70
+ *
71
+ * @param db - The database.
72
+ * @param orgId - The owning organization id (`org_…`).
73
+ * @returns The records.
74
+ */
75
+ export function listByOrg(db: Db.Db, orgId: string): Promise<Record[]> {
76
+ return db.kysely
77
+ .selectFrom('projects')
78
+ .selectAll()
79
+ .where('orgId', '=', orgId)
80
+ .orderBy('createdAt', 'desc')
81
+ .execute()
82
+ }
83
+
84
+ /**
85
+ * Renames a project, bumping `updatedAt`.
86
+ *
87
+ * @param db - The database.
88
+ * @param id - The project id (`prj_…`).
89
+ * @param input - The fields to update.
90
+ * @returns The updated record, or `undefined` when absent.
91
+ */
92
+ export function update(db: Db.Db, id: string, input: update.Input): Promise<Record | undefined> {
93
+ return db.kysely
94
+ .updateTable('projects')
95
+ .set({ name: input.name, updatedAt: new Date().toISOString() })
96
+ .where('id', '=', id)
97
+ .returningAll()
98
+ .executeTakeFirst()
99
+ }
100
+
101
+ export declare namespace update {
102
+ /** Mutable project fields. */
103
+ type Input = {
104
+ /** New human-readable project name. */
105
+ name: string
106
+ }
107
+ }