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,218 @@
1
+ import { nanoid } from 'nanoid'
2
+
3
+ import { postgresUrl } from '../../../test/containers.js'
4
+ import * as Db from '../Db.js'
5
+ import * as SponsoredTransactions from './sponsoredTransactions.js'
6
+
7
+ const create = () => Db.postgres({ connectionString: postgresUrl, schema: `t_${nanoid()}` })
8
+
9
+ /** Baseline insert input; tests override per case. */
10
+ const input = {
11
+ apiKeyId: 'key_1',
12
+ billable: true,
13
+ chainId: 42431,
14
+ environment: 'production',
15
+ orgId: 'org_1',
16
+ projectId: 'prj_1',
17
+ signPayload: `0x${'bb'.repeat(32)}`,
18
+ transaction: `0x76${'cc'.repeat(16)}`,
19
+ transactionHash: `0x${'aa'.repeat(32)}`,
20
+ } satisfies SponsoredTransactions.upsert.Input
21
+
22
+ /** Redacts nondeterministic row fields (generated nanoid ids, timestamps). */
23
+ function redact(record: SponsoredTransactions.Record) {
24
+ return {
25
+ ...record,
26
+ createdAt: '<timestamp>',
27
+ finalizedAt: record.finalizedAt === null ? null : '<timestamp>',
28
+ id: /^stx_[\w-]{21}$/.test(record.id) ? 'stx_<id>' : record.id,
29
+ }
30
+ }
31
+
32
+ describe('upsert', () => {
33
+ test('behavior: records a pending sponsorship with a generated id', async () => {
34
+ const db = create()
35
+ await db.migrate()
36
+ const record = await SponsoredTransactions.upsert(db, input)
37
+ expect(record.id).toMatch(/^stx_/)
38
+ expect(redact(record)).toMatchInlineSnapshot(`
39
+ {
40
+ "apiKeyId": "key_1",
41
+ "billable": true,
42
+ "chainId": 42431,
43
+ "createdAt": "<timestamp>",
44
+ "environment": "production",
45
+ "feeAmount": null,
46
+ "feeToken": null,
47
+ "finalizedAt": null,
48
+ "id": "stx_<id>",
49
+ "orgId": "org_1",
50
+ "projectId": "prj_1",
51
+ "signPayload": "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
52
+ "status": "pending",
53
+ "transaction": "0x76cccccccccccccccccccccccccccccccc",
54
+ "transactionHash": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
55
+ }
56
+ `)
57
+ expect(await SponsoredTransactions.get(db, record.id)).toStrictEqual(record)
58
+ await db.close()
59
+ })
60
+
61
+ test('behavior: preserves an explicit fee token', async () => {
62
+ const db = create()
63
+ await db.migrate()
64
+ const record = await SponsoredTransactions.upsert(db, { ...input, feeToken: `0x${'fe'.repeat(20)}` }) // prettier-ignore
65
+ expect(record.feeToken).toMatchInlineSnapshot(`"0xfefefefefefefefefefefefefefefefefefefefe"`)
66
+ await db.close()
67
+ })
68
+
69
+ test('behavior: records fill intents without a transaction hash', async () => {
70
+ const db = create()
71
+ await db.migrate()
72
+ const { transactionHash: _, ...intent } = input
73
+ const record = await SponsoredTransactions.upsert(db, intent)
74
+ expect(record.transactionHash).toBeNull()
75
+ expect(record.status).toMatchInlineSnapshot(`"pending"`)
76
+ await db.close()
77
+ })
78
+
79
+ test('behavior: a raw submission upgrades a fill intent in place', async () => {
80
+ const db = create()
81
+ await db.migrate()
82
+ const { transactionHash: _, ...intent } = input
83
+ const first = await SponsoredTransactions.upsert(db, intent)
84
+ const second = await SponsoredTransactions.upsert(db, input)
85
+
86
+ // Same commitment, one row: the raw record fills the intent's hash.
87
+ expect(second.id).toBe(first.id)
88
+ expect(second.transactionHash).toMatchInlineSnapshot(
89
+ `"0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"`,
90
+ )
91
+ expect(await SponsoredTransactions.listPending(db)).toHaveLength(1)
92
+ await db.close()
93
+ })
94
+
95
+ test('behavior: a raw submission reopens a failed fill intent', async () => {
96
+ const db = create()
97
+ await db.migrate()
98
+ const { transactionHash: _, ...intent } = input
99
+ const first = await SponsoredTransactions.upsert(db, intent)
100
+ await SponsoredTransactions.fail(db, first.id, '2026-01-01T00:00:00.000Z')
101
+
102
+ const second = await SponsoredTransactions.upsert(db, input)
103
+
104
+ expect(second.id).toBe(first.id)
105
+ expect(second.status).toMatchInlineSnapshot(`"pending"`)
106
+ expect(second.finalizedAt).toBeNull()
107
+ expect(second.transactionHash).toMatchInlineSnapshot(
108
+ `"0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"`,
109
+ )
110
+ expect(await SponsoredTransactions.listPending(db)).toHaveLength(1)
111
+ await db.close()
112
+ })
113
+
114
+ test('behavior: a duplicate intent never clears a known hash', async () => {
115
+ const db = create()
116
+ await db.migrate()
117
+ const first = await SponsoredTransactions.upsert(db, input)
118
+ const { transactionHash: _, ...intent } = input
119
+ const second = await SponsoredTransactions.upsert(db, intent)
120
+
121
+ expect(second.id).toBe(first.id)
122
+ expect(second.transactionHash).toMatchInlineSnapshot(
123
+ `"0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"`,
124
+ )
125
+ await db.close()
126
+ })
127
+ })
128
+
129
+ describe('listPending', () => {
130
+ test('behavior: returns only pending rows, capped by limit', async () => {
131
+ const db = create()
132
+ await db.migrate()
133
+ await SponsoredTransactions.upsert(db, { ...input, signPayload: `0x${'b1'.repeat(32)}`, transactionHash: `0x${'a1'.repeat(32)}` }) // prettier-ignore
134
+ const second = await SponsoredTransactions.upsert(db, { ...input, signPayload: `0x${'b2'.repeat(32)}`, transactionHash: `0x${'a2'.repeat(32)}` }) // prettier-ignore
135
+ await SponsoredTransactions.upsert(db, { ...input, signPayload: `0x${'b3'.repeat(32)}`, transactionHash: `0x${'a3'.repeat(32)}` }) // prettier-ignore
136
+ await SponsoredTransactions.finalize(db, second.id, {
137
+ feeAmount: '100',
138
+ finalizedAt: new Date().toISOString(),
139
+ })
140
+
141
+ const pending = await SponsoredTransactions.listPending(db)
142
+ // Inserts can share a millisecond, so assert membership, not order.
143
+ expect(pending.map((row) => row.transactionHash).sort()).toMatchInlineSnapshot(`
144
+ [
145
+ "0xa1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1",
146
+ "0xa3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3",
147
+ ]
148
+ `)
149
+ expect(await SponsoredTransactions.listPending(db, { limit: 1 })).toHaveLength(1)
150
+ await db.close()
151
+ })
152
+ })
153
+
154
+ describe('assignTransactionHash', () => {
155
+ test('behavior: reopens a failed intent when reconciliation finds its hash', async () => {
156
+ const db = create()
157
+ await db.migrate()
158
+ const { transactionHash: _, ...intent } = input
159
+ const record = await SponsoredTransactions.upsert(db, intent)
160
+ await SponsoredTransactions.fail(db, record.id, '2026-01-01T00:00:00.000Z')
161
+
162
+ await SponsoredTransactions.assignTransactionHash(db, record.id, input.transactionHash)
163
+
164
+ const assigned = await SponsoredTransactions.get(db, record.id)
165
+ expect(assigned?.status).toMatchInlineSnapshot(`"pending"`)
166
+ expect(assigned?.finalizedAt).toBeNull()
167
+ expect(assigned?.transactionHash).toMatchInlineSnapshot(
168
+ `"0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"`,
169
+ )
170
+ await db.close()
171
+ })
172
+ })
173
+
174
+ describe('finalize', () => {
175
+ test('behavior: transitions pending → finalized with the actual fee', async () => {
176
+ const db = create()
177
+ await db.migrate()
178
+ const record = await SponsoredTransactions.upsert(db, input)
179
+ await SponsoredTransactions.finalize(db, record.id, {
180
+ feeAmount: '21000',
181
+ finalizedAt: '2026-01-01T00:00:00.000Z',
182
+ })
183
+ const finalized = await SponsoredTransactions.get(db, record.id)
184
+ expect(finalized?.status).toMatchInlineSnapshot(`"finalized"`)
185
+ expect(finalized?.feeAmount).toMatchInlineSnapshot(`"21000"`)
186
+ expect(finalized?.finalizedAt).toMatchInlineSnapshot(`"2026-01-01T00:00:00.000Z"`)
187
+ await db.close()
188
+ })
189
+
190
+ test('behavior: no-op on rows that are no longer pending', async () => {
191
+ const db = create()
192
+ await db.migrate()
193
+ const record = await SponsoredTransactions.upsert(db, input)
194
+ await SponsoredTransactions.fail(db, record.id, '2026-01-01T00:00:00.000Z')
195
+ await SponsoredTransactions.finalize(db, record.id, {
196
+ feeAmount: '21000',
197
+ finalizedAt: '2026-01-02T00:00:00.000Z',
198
+ })
199
+ const row = await SponsoredTransactions.get(db, record.id)
200
+ expect(row?.status).toMatchInlineSnapshot(`"failed"`)
201
+ expect(row?.feeAmount).toBeNull()
202
+ await db.close()
203
+ })
204
+ })
205
+
206
+ describe('fail', () => {
207
+ test('behavior: transitions pending → failed without a fee', async () => {
208
+ const db = create()
209
+ await db.migrate()
210
+ const record = await SponsoredTransactions.upsert(db, input)
211
+ await SponsoredTransactions.fail(db, record.id, '2026-01-01T00:00:00.000Z')
212
+ const failed = await SponsoredTransactions.get(db, record.id)
213
+ expect(failed?.status).toMatchInlineSnapshot(`"failed"`)
214
+ expect(failed?.feeAmount).toBeNull()
215
+ expect(failed?.finalizedAt).toMatchInlineSnapshot(`"2026-01-01T00:00:00.000Z"`)
216
+ await db.close()
217
+ })
218
+ })
@@ -0,0 +1,236 @@
1
+ import type { ExpressionBuilder, Selectable } from 'kysely'
2
+ import { sql } from 'kysely'
3
+ import { nanoid } from 'nanoid'
4
+
5
+ import type * as Db from '../Db.js'
6
+ import type * as db_Schema from '../Schema.js'
7
+
8
+ /** Columns of the `sponsored_transactions` table, derived from `Schema.SponsoredTransaction`. */
9
+ export type Table = db_Schema.SponsoredTransaction
10
+
11
+ /** A stored sponsored-transaction row. */
12
+ export type Record = Selectable<Table>
13
+
14
+ /**
15
+ * Records one sponsorship commitment as `pending`, keyed by its fee-payer
16
+ * sign payload. Written after fee-payer signing and before any broadcast, so
17
+ * no sponsored transaction goes unrecorded; a later recording site for the
18
+ * same envelope (raw submission after a fill intent) upgrades the row with
19
+ * its transaction hash, reopening failed rows for finalization.
20
+ *
21
+ * @param db - The database.
22
+ * @param input - Attribution and envelope facts captured at signing time.
23
+ * @returns The stored record.
24
+ */
25
+ export async function upsert(db: Db.Db, input: upsert.Input): Promise<Record> {
26
+ const record: Record = {
27
+ apiKeyId: input.apiKeyId,
28
+ billable: input.billable,
29
+ chainId: input.chainId,
30
+ createdAt: new Date().toISOString(),
31
+ environment: input.environment,
32
+ feeAmount: null,
33
+ feeToken: input.feeToken ?? null,
34
+ finalizedAt: null,
35
+ id: `stx_${nanoid()}`,
36
+ orgId: input.orgId,
37
+ projectId: input.projectId,
38
+ signPayload: input.signPayload,
39
+ status: 'pending',
40
+ transaction: input.transaction,
41
+ transactionHash: input.transactionHash ?? null,
42
+ }
43
+ return await db.kysely
44
+ .insertInto('sponsored_transactions')
45
+ .values(record)
46
+ .onConflict((oc) =>
47
+ oc.column('signPayload').doUpdateSet((eb) => ({
48
+ // A raw submission fills the intent's hash; a duplicate intent never
49
+ // clears an already-known hash.
50
+ transactionHash: eb.fn.coalesce(
51
+ eb.ref('excluded.transactionHash'),
52
+ eb.ref('sponsored_transactions.transactionHash'),
53
+ ),
54
+ createdAt: sql`CASE WHEN ${eb.ref('sponsored_transactions.status')} = 'failed' THEN ${eb.ref('excluded.createdAt')} ELSE ${eb.ref('sponsored_transactions.createdAt')} END`,
55
+ finalizedAt: sql`CASE WHEN ${eb.ref('sponsored_transactions.status')} = 'failed' THEN NULL ELSE ${eb.ref('sponsored_transactions.finalizedAt')} END`,
56
+ status: sql`CASE WHEN ${eb.ref('sponsored_transactions.status')} = 'failed' THEN 'pending' ELSE ${eb.ref('sponsored_transactions.status')} END`,
57
+ })),
58
+ )
59
+ .returningAll()
60
+ .executeTakeFirstOrThrow()
61
+ }
62
+
63
+ export declare namespace upsert {
64
+ /** Attribution and envelope facts recorded at sponsorship time. */
65
+ type Input = {
66
+ /** API key id (`key_…`) that requested sponsorship. */
67
+ apiKeyId: string
68
+ /** Whether the sponsorship accrues billable spend; false for sandbox. */
69
+ billable: boolean
70
+ /** Chain the sponsored transaction targets. */
71
+ chainId: number
72
+ /** Key environment the sponsorship was requested under. */
73
+ environment: Table['environment']
74
+ /** Fee token the sponsorship resolved, when known. */
75
+ feeToken?: string | undefined
76
+ /** Organization id (`org_…`) the spend attributes to. */
77
+ orgId: string
78
+ /** Project id (`prj_…`) the spend attributes to. */
79
+ projectId: string
80
+ /** Fee-payer sign payload — a stable identity for the sponsored envelope. */
81
+ signPayload: string
82
+ /** Serialized sponsored transaction, kept for observability beyond log retention. */
83
+ transaction: string
84
+ /** Transaction hash; omit for fill intents, whose senders have not signed yet. */
85
+ transactionHash?: string | undefined
86
+ }
87
+ }
88
+
89
+ /**
90
+ * Reads one sponsorship row by id.
91
+ *
92
+ * @param db - The database.
93
+ * @param id - The sponsored-transaction id (`stx_…`).
94
+ * @returns The record, or `undefined` when absent.
95
+ */
96
+ export function get(db: Db.Db, id: string): Promise<Record | undefined> {
97
+ return db.kysely
98
+ .selectFrom('sponsored_transactions')
99
+ .selectAll()
100
+ .where('id', '=', id)
101
+ .executeTakeFirst()
102
+ }
103
+
104
+ /**
105
+ * Lists pending sponsorships, oldest first, for the finalization job.
106
+ *
107
+ * @param db - The database.
108
+ * @param options - Paging options.
109
+ * @returns The pending records.
110
+ */
111
+ export function listPending(db: Db.Db, options: listPending.Options = {}): Promise<Record[]> {
112
+ let query = db.kysely
113
+ .selectFrom('sponsored_transactions')
114
+ .selectAll()
115
+ .where('status', '=', 'pending')
116
+ // `id` breaks same-millisecond `createdAt` ties for a deterministic scan.
117
+ .orderBy('createdAt', 'asc')
118
+ .orderBy('id', 'asc')
119
+ if (options.limit !== undefined) query = query.limit(options.limit)
120
+ return query.execute()
121
+ }
122
+
123
+ export declare namespace listPending {
124
+ /** Options for {@link listPending}. */
125
+ type Options = {
126
+ /** Maximum rows to return. */
127
+ limit?: number | undefined
128
+ }
129
+ }
130
+
131
+ /**
132
+ * Lists hash-less fill intents, oldest first, for the reconciliation pass.
133
+ * Failed intents are included only when the caller supplies a recovery floor.
134
+ *
135
+ * @param db - The database.
136
+ * @param options - Paging options.
137
+ * @returns The pending intents.
138
+ */
139
+ export function listIntents(db: Db.Db, options: listIntents.Options = {}): Promise<Record[]> {
140
+ let query = db.kysely
141
+ .selectFrom('sponsored_transactions')
142
+ .selectAll()
143
+ .where(intentStatus(options.failedSince))
144
+ .where('transactionHash', 'is', null)
145
+ // `pending` sorts after `failed`; descending keeps active intents first.
146
+ .orderBy('status', 'desc')
147
+ .orderBy('createdAt', 'asc')
148
+ .orderBy('id', 'asc')
149
+ if (options.limit !== undefined) query = query.limit(options.limit)
150
+ return query.execute()
151
+ }
152
+
153
+ export declare namespace listIntents {
154
+ /** Options for {@link listIntents}. */
155
+ type Options = listPending.Options & {
156
+ /** Include failed intents whose terminal timestamp is at or after this ISO timestamp. */
157
+ failedSince?: string | undefined
158
+ }
159
+ }
160
+
161
+ /**
162
+ * Fills a reconciled intent's transaction hash and reopens failed intents.
163
+ * A no-op once another pass already assigned the hash.
164
+ *
165
+ * @param db - The database.
166
+ * @param id - The sponsored-transaction id (`stx_…`).
167
+ * @param transactionHash - The matched on-chain transaction hash.
168
+ */
169
+ export async function assignTransactionHash(
170
+ db: Db.Db,
171
+ id: string,
172
+ transactionHash: string,
173
+ ): Promise<void> {
174
+ await db.kysely
175
+ .updateTable('sponsored_transactions')
176
+ .set({ finalizedAt: null, status: 'pending', transactionHash })
177
+ .where('id', '=', id)
178
+ .where('status', 'in', ['failed', 'pending'])
179
+ .where('transactionHash', 'is', null)
180
+ .execute()
181
+ }
182
+
183
+ /**
184
+ * Transitions a pending sponsorship to `finalized` with the receipt's actual
185
+ * fee. A no-op when the row is no longer pending (idempotent re-runs).
186
+ *
187
+ * @param db - The database.
188
+ * @param id - The sponsored-transaction id (`stx_…`).
189
+ * @param input - The finalized fee facts.
190
+ */
191
+ export async function finalize(db: Db.Db, id: string, input: finalize.Input): Promise<void> {
192
+ await db.kysely
193
+ .updateTable('sponsored_transactions')
194
+ .set({ feeAmount: input.feeAmount, finalizedAt: input.finalizedAt, status: 'finalized' })
195
+ .where('id', '=', id)
196
+ .where('status', '=', 'pending')
197
+ .execute()
198
+ }
199
+
200
+ export declare namespace finalize {
201
+ /** Fee facts resolved from the transaction receipt. */
202
+ type Input = {
203
+ /** Actual fee paid in fee-token base units. */
204
+ feeAmount: string
205
+ /** When the sponsorship finalized (ISO 8601). */
206
+ finalizedAt: string
207
+ }
208
+ }
209
+
210
+ /**
211
+ * Transitions a pending sponsorship to `failed` (never landed within the
212
+ * pending TTL). A no-op when the row is no longer pending.
213
+ *
214
+ * @param db - The database.
215
+ * @param id - The sponsored-transaction id (`stx_…`).
216
+ * @param finalizedAt - When the sponsorship was marked failed (ISO 8601).
217
+ */
218
+ export async function fail(db: Db.Db, id: string, finalizedAt: string): Promise<void> {
219
+ await db.kysely
220
+ .updateTable('sponsored_transactions')
221
+ .set({ finalizedAt, status: 'failed' })
222
+ .where('id', '=', id)
223
+ .where('status', '=', 'pending')
224
+ .execute()
225
+ }
226
+
227
+ /** Intent status predicate; failed rows are recovery candidates only briefly. */
228
+ function intentStatus(failedSince: string | undefined) {
229
+ return (eb: ExpressionBuilder<Db.Database, 'sponsored_transactions'>) => {
230
+ if (failedSince === undefined) return eb('status', '=', 'pending')
231
+ return eb.or([
232
+ eb('status', '=', 'pending'),
233
+ eb.and([eb('status', '=', 'failed'), eb('finalizedAt', '>=', failedSince)]),
234
+ ])
235
+ }
236
+ }
@@ -0,0 +1,85 @@
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 `users` table, derived from `Schema.User`. */
8
+ export type Table = db_Schema.User
9
+
10
+ /** A stored user row. */
11
+ export type Record = Selectable<Table>
12
+
13
+ /**
14
+ * Reads a user by id (`usr_…`).
15
+ *
16
+ * @param db - The database.
17
+ * @param id - The user id.
18
+ * @returns The record, or `undefined` when absent.
19
+ */
20
+ export function get(db: Db.Db, id: string): Promise<Record | undefined> {
21
+ return db.kysely.selectFrom('users').selectAll().where('id', '=', id).executeTakeFirst()
22
+ }
23
+
24
+ /**
25
+ * Reads a user by wallet address (compared lowercase).
26
+ *
27
+ * @param db - The database.
28
+ * @param address - The wallet address.
29
+ * @returns The record, or `undefined` when absent.
30
+ */
31
+ export function getByAddress(db: Db.Db, address: string): Promise<Record | undefined> {
32
+ return db.kysely
33
+ .selectFrom('users')
34
+ .selectAll()
35
+ .where('address', '=', address.toLowerCase())
36
+ .executeTakeFirst()
37
+ }
38
+
39
+ /**
40
+ * Inserts a user for `address` when absent and returns the stored record.
41
+ * Existing users are returned unchanged, so repeated sign-ins are idempotent.
42
+ *
43
+ * @param db - The database.
44
+ * @param input - The user to ensure.
45
+ * @returns The stored record.
46
+ */
47
+ export async function upsertByAddress(db: Db.Db, input: upsertByAddress.Input): Promise<Record> {
48
+ const address = input.address.toLowerCase()
49
+ const now = new Date().toISOString()
50
+ const inserted = await db.kysely
51
+ .insertInto('users')
52
+ .values({ address, createdAt: now, email: null, id: `usr_${nanoid()}`, updatedAt: now })
53
+ .onConflict((oc) => oc.column('address').doNothing())
54
+ .returningAll()
55
+ .executeTakeFirst()
56
+ if (inserted) return inserted
57
+ return db.kysely
58
+ .selectFrom('users')
59
+ .selectAll()
60
+ .where('address', '=', address)
61
+ .executeTakeFirstOrThrow()
62
+ }
63
+
64
+ export declare namespace upsertByAddress {
65
+ /** Fields accepted when ensuring a user. */
66
+ type Input = {
67
+ /** Wallet address that signed in (stored lowercase). */
68
+ address: string
69
+ }
70
+ }
71
+
72
+ /**
73
+ * Sets a user's verified email, bumping `updatedAt`.
74
+ *
75
+ * @param db - The database.
76
+ * @param id - The user id (`usr_…`).
77
+ * @param email - The verified email.
78
+ */
79
+ export async function setEmail(db: Db.Db, id: string, email: string): Promise<void> {
80
+ await db.kysely
81
+ .updateTable('users')
82
+ .set({ email, updatedAt: new Date().toISOString() })
83
+ .where('id', '=', id)
84
+ .execute()
85
+ }
@@ -0,0 +1,111 @@
1
+ import type { Selectable } from 'kysely'
2
+ import type { Hex } from 'ox'
3
+
4
+ import type * as VerifiedTokens from '../../internal/VerifiedTokens.js'
5
+ import type * as Db from '../Db.js'
6
+ import type * as db_Schema from '../Schema.js'
7
+
8
+ /** Columns of the `verified_tokens` table, derived from `Schema.VerifiedToken`. */
9
+ export type Table = db_Schema.VerifiedToken
10
+
11
+ /** Columns of the `verified_token_lists` table, derived from `Schema.VerifiedTokenList`. */
12
+ export type ListTable = db_Schema.VerifiedTokenList
13
+
14
+ /** A stored verified-token row. */
15
+ export type Row = Selectable<Table>
16
+
17
+ /** A chain's list-level metadata. */
18
+ export type Meta = Selectable<ListTable>
19
+
20
+ /**
21
+ * Reads a chain's list metadata — the "head" the soft-refresh cache compares
22
+ * versions against.
23
+ *
24
+ * @param db - The database.
25
+ * @param chainId - The chain id.
26
+ * @returns The metadata, or `undefined` when the chain has no list yet.
27
+ */
28
+ export function head(db: Db.Db, chainId: number): Promise<Meta | undefined> {
29
+ return db.kysely
30
+ .selectFrom('verified_token_lists')
31
+ .selectAll()
32
+ .where('chainId', '=', chainId)
33
+ .executeTakeFirst()
34
+ }
35
+
36
+ /**
37
+ * Reads a chain's tokens in canonical list order.
38
+ *
39
+ * @param db - The database.
40
+ * @param chainId - The chain id.
41
+ * @returns The rows.
42
+ */
43
+ export function list(db: Db.Db, chainId: number): Promise<Row[]> {
44
+ return db.kysely
45
+ .selectFrom('verified_tokens')
46
+ .selectAll()
47
+ .where('chainId', '=', chainId)
48
+ .orderBy('position')
49
+ .execute()
50
+ }
51
+
52
+ /**
53
+ * Publishes a chain's whole list: replaces its token rows (positions rewritten
54
+ * wholesale) and bumps the list metadata. Callers run this inside the
55
+ * per-chain publish lock/transaction, so the rewrite is atomic.
56
+ *
57
+ * @param db - The database (a transaction-scoped handle).
58
+ * @param chainId - The chain id.
59
+ * @param input - The validated list and its new version metadata.
60
+ */
61
+ export async function publish(db: Db.Db, chainId: number, input: publish.Input): Promise<void> {
62
+ await db.kysely.deleteFrom('verified_tokens').where('chainId', '=', chainId).execute()
63
+ if (input.tokens.length > 0)
64
+ await db.kysely
65
+ .insertInto('verified_tokens')
66
+ .values(
67
+ input.tokens.map((token, position) => ({
68
+ address: token.address,
69
+ chainId,
70
+ currency: token.currency,
71
+ decimals: token.decimals,
72
+ logoUri: token.logoUri ?? null,
73
+ name: token.name,
74
+ position,
75
+ symbol: token.symbol,
76
+ })),
77
+ )
78
+ .execute()
79
+ await db.kysely
80
+ .insertInto('verified_token_lists')
81
+ .values({ chainId, updatedAt: input.updatedAt, version: input.version })
82
+ .onConflict((oc) =>
83
+ oc.column('chainId').doUpdateSet({ updatedAt: input.updatedAt, version: input.version }),
84
+ )
85
+ .execute()
86
+ }
87
+
88
+ export declare namespace publish {
89
+ /** A validated list to publish. */
90
+ type Input = {
91
+ /** Tokens in canonical order (addresses lowercased by the domain layer). */
92
+ tokens: readonly VerifiedTokens.Token[]
93
+ /** ISO timestamp of the publish. */
94
+ updatedAt: string
95
+ /** New opaque list version. */
96
+ version: string
97
+ }
98
+ }
99
+
100
+ /** Maps a stored row to the domain token (null `logoUri` → absent field). */
101
+ export function toToken(row: Row): VerifiedTokens.Token {
102
+ return {
103
+ address: row.address as Hex.Hex,
104
+ currency: row.currency,
105
+ decimals: row.decimals,
106
+ id: row.address as Hex.Hex,
107
+ name: row.name,
108
+ symbol: row.symbol,
109
+ ...(row.logoUri === null ? {} : { logoUri: row.logoUri }),
110
+ }
111
+ }