tapimo 0.1.0 → 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 (385) hide show
  1. package/README.md +28 -15
  2. package/dist/ApiKey.d.ts +3 -1
  3. package/dist/ApiKey.d.ts.map +1 -1
  4. package/dist/ApiKey.js +1 -0
  5. package/dist/ApiKey.js.map +1 -1
  6. package/dist/ApiKeys.d.ts +71 -3
  7. package/dist/ApiKeys.d.ts.map +1 -1
  8. package/dist/ApiKeys.js +117 -1
  9. package/dist/ApiKeys.js.map +1 -1
  10. package/dist/App.d.ts +7139 -4197
  11. package/dist/App.d.ts.map +1 -1
  12. package/dist/App.js +133 -329
  13. package/dist/App.js.map +1 -1
  14. package/dist/Scope.d.ts +11 -4
  15. package/dist/Scope.d.ts.map +1 -1
  16. package/dist/Scope.js +12 -4
  17. package/dist/Scope.js.map +1 -1
  18. package/dist/Webhooks.d.ts +2 -2
  19. package/dist/Webhooks.d.ts.map +1 -1
  20. package/dist/Webhooks.js +2 -2
  21. package/dist/Webhooks.js.map +1 -1
  22. package/dist/admin/App.d.ts +126 -53
  23. package/dist/admin/App.d.ts.map +1 -1
  24. package/dist/admin/apps/api-keys.d.ts +104 -6
  25. package/dist/admin/apps/api-keys.d.ts.map +1 -1
  26. package/dist/admin/apps/api-keys.js +67 -0
  27. package/dist/admin/apps/api-keys.js.map +1 -1
  28. package/dist/admin/apps/scopes.d.ts +4 -1
  29. package/dist/admin/apps/scopes.d.ts.map +1 -1
  30. package/dist/admin/apps/verified-tokens.d.ts +115 -115
  31. package/dist/admin/apps/verified-tokens.js +1 -1
  32. package/dist/admin/apps/verified-tokens.js.map +1 -1
  33. package/dist/admin/ui.generated.d.ts +1 -1
  34. package/dist/admin/ui.generated.js +1 -1
  35. package/dist/apps/data/App.d.ts +19176 -0
  36. package/dist/apps/data/App.d.ts.map +1 -0
  37. package/dist/apps/data/App.js +236 -0
  38. package/dist/apps/data/App.js.map +1 -0
  39. package/dist/apps/data/index.d.ts +3 -0
  40. package/dist/apps/data/index.d.ts.map +1 -0
  41. package/dist/apps/data/index.js +3 -0
  42. package/dist/apps/data/index.js.map +1 -0
  43. package/dist/apps/{activities.d.ts → data/routes/activities.d.ts} +32 -32
  44. package/dist/apps/{activities.d.ts.map → data/routes/activities.d.ts.map} +1 -1
  45. package/dist/apps/{activities.js → data/routes/activities.js} +13 -13
  46. package/dist/apps/data/routes/activities.js.map +1 -0
  47. package/dist/apps/{addresses.d.ts → data/routes/addresses.d.ts} +22 -22
  48. package/dist/apps/{addresses.d.ts.map → data/routes/addresses.d.ts.map} +1 -1
  49. package/dist/apps/{addresses.js → data/routes/addresses.js} +5 -5
  50. package/dist/apps/data/routes/addresses.js.map +1 -0
  51. package/dist/apps/{balances.d.ts → data/routes/balances.d.ts} +49 -49
  52. package/dist/apps/data/routes/balances.d.ts.map +1 -0
  53. package/dist/apps/{balances.js → data/routes/balances.js} +42 -11
  54. package/dist/apps/data/routes/balances.js.map +1 -0
  55. package/dist/apps/{blocks.d.ts → data/routes/blocks.d.ts} +47 -47
  56. package/dist/apps/data/routes/blocks.d.ts.map +1 -0
  57. package/dist/apps/{blocks.js → data/routes/blocks.js} +13 -13
  58. package/dist/apps/data/routes/blocks.js.map +1 -0
  59. package/dist/apps/{coingecko.d.ts → data/routes/coingecko.d.ts} +183 -183
  60. package/dist/apps/data/routes/coingecko.d.ts.map +1 -0
  61. package/dist/apps/{coingecko.js → data/routes/coingecko.js} +13 -13
  62. package/dist/apps/data/routes/coingecko.js.map +1 -0
  63. package/dist/apps/{exchanges.d.ts → data/routes/exchanges.d.ts} +460 -460
  64. package/dist/apps/data/routes/exchanges.d.ts.map +1 -0
  65. package/dist/apps/{exchanges.js → data/routes/exchanges.js} +19 -19
  66. package/dist/apps/data/routes/exchanges.js.map +1 -0
  67. package/dist/apps/{fee-amm.d.ts → data/routes/fee-amm.d.ts} +94 -94
  68. package/dist/apps/data/routes/fee-amm.d.ts.map +1 -0
  69. package/dist/apps/{fee-amm.js → data/routes/fee-amm.js} +17 -17
  70. package/dist/apps/data/routes/fee-amm.js.map +1 -0
  71. package/dist/apps/{indexer.d.ts → data/routes/indexer.d.ts} +4 -4
  72. package/dist/apps/data/routes/indexer.d.ts.map +1 -0
  73. package/dist/apps/{indexer.js → data/routes/indexer.js} +13 -9
  74. package/dist/apps/data/routes/indexer.js.map +1 -0
  75. package/dist/apps/{receipts.d.ts → data/routes/receipts.d.ts} +49 -49
  76. package/dist/apps/data/routes/receipts.d.ts.map +1 -0
  77. package/dist/apps/{receipts.js → data/routes/receipts.js} +12 -12
  78. package/dist/apps/data/routes/receipts.js.map +1 -0
  79. package/dist/apps/{rpc.d.ts → data/routes/rpc.d.ts} +4 -4
  80. package/dist/apps/data/routes/rpc.d.ts.map +1 -0
  81. package/dist/apps/{rpc.js → data/routes/rpc.js} +6 -6
  82. package/dist/apps/data/routes/rpc.js.map +1 -0
  83. package/dist/apps/{tokenlist.d.ts → data/routes/tokenlist.d.ts} +4 -4
  84. package/dist/apps/data/routes/tokenlist.d.ts.map +1 -0
  85. package/dist/apps/{tokenlist.js → data/routes/tokenlist.js} +8 -8
  86. package/dist/apps/data/routes/tokenlist.js.map +1 -0
  87. package/dist/apps/{tokens.d.ts → data/routes/tokens.d.ts} +468 -468
  88. package/dist/apps/data/routes/tokens.d.ts.map +1 -0
  89. package/dist/apps/{tokens.js → data/routes/tokens.js} +19 -19
  90. package/dist/apps/data/routes/tokens.js.map +1 -0
  91. package/dist/apps/{transactions.d.ts → data/routes/transactions.d.ts} +304 -304
  92. package/dist/apps/data/routes/transactions.d.ts.map +1 -0
  93. package/dist/apps/{transactions.js → data/routes/transactions.js} +13 -13
  94. package/dist/apps/data/routes/transactions.js.map +1 -0
  95. package/dist/apps/{transfers.d.ts → data/routes/transfers.d.ts} +6 -6
  96. package/dist/apps/data/routes/transfers.d.ts.map +1 -0
  97. package/dist/apps/{transfers.js → data/routes/transfers.js} +13 -13
  98. package/dist/apps/data/routes/transfers.js.map +1 -0
  99. package/dist/apps/{verified-tokens.d.ts → data/routes/verified-tokens.d.ts} +42 -42
  100. package/dist/apps/data/routes/verified-tokens.d.ts.map +1 -0
  101. package/dist/apps/{verified-tokens.js → data/routes/verified-tokens.js} +9 -9
  102. package/dist/apps/data/routes/verified-tokens.js.map +1 -0
  103. package/dist/apps/{webhooks.d.ts → data/routes/webhooks.d.ts} +62 -62
  104. package/dist/apps/{webhooks.d.ts.map → data/routes/webhooks.d.ts.map} +1 -1
  105. package/dist/apps/{webhooks.js → data/routes/webhooks.js} +30 -26
  106. package/dist/apps/data/routes/webhooks.js.map +1 -0
  107. package/dist/apps/docs/App.d.ts +27 -0
  108. package/dist/apps/docs/App.d.ts.map +1 -0
  109. package/dist/apps/docs/App.js +122 -0
  110. package/dist/apps/docs/App.js.map +1 -0
  111. package/dist/{internal/OpenApi.fonts.d.ts → apps/docs/fonts.d.ts} +1 -1
  112. package/dist/apps/docs/fonts.d.ts.map +1 -0
  113. package/dist/{internal/OpenApi.fonts.js → apps/docs/fonts.js} +1 -1
  114. package/dist/apps/docs/fonts.js.map +1 -0
  115. package/dist/apps/docs/index.d.ts +2 -0
  116. package/dist/apps/docs/index.d.ts.map +1 -0
  117. package/dist/apps/docs/index.js +2 -0
  118. package/dist/apps/docs/index.js.map +1 -0
  119. package/dist/{internal/OpenApi.logo.d.ts → apps/docs/logo.d.ts} +1 -1
  120. package/dist/apps/docs/logo.d.ts.map +1 -0
  121. package/dist/{internal/OpenApi.logo.js → apps/docs/logo.js} +1 -1
  122. package/dist/apps/docs/logo.js.map +1 -0
  123. package/dist/apps/index.d.ts +4 -0
  124. package/dist/apps/index.d.ts.map +1 -0
  125. package/dist/apps/index.js +4 -0
  126. package/dist/apps/index.js.map +1 -0
  127. package/dist/apps/metadata.d.ts +7 -0
  128. package/dist/apps/metadata.d.ts.map +1 -0
  129. package/dist/apps/metadata.js +15 -0
  130. package/dist/apps/metadata.js.map +1 -0
  131. package/dist/apps/platform/App.d.ts +2985 -0
  132. package/dist/apps/platform/App.d.ts.map +1 -0
  133. package/dist/apps/platform/App.js +74 -0
  134. package/dist/apps/platform/App.js.map +1 -0
  135. package/dist/apps/platform/index.d.ts +2 -0
  136. package/dist/apps/platform/index.d.ts.map +1 -0
  137. package/dist/apps/platform/index.js +2 -0
  138. package/dist/apps/platform/index.js.map +1 -0
  139. package/dist/apps/platform/routes/api-keys.d.ts +681 -0
  140. package/dist/apps/platform/routes/api-keys.d.ts.map +1 -0
  141. package/dist/apps/platform/routes/api-keys.js +328 -0
  142. package/dist/apps/platform/routes/api-keys.js.map +1 -0
  143. package/dist/apps/platform/routes/invitations.d.ts +733 -0
  144. package/dist/apps/platform/routes/invitations.d.ts.map +1 -0
  145. package/dist/apps/platform/routes/invitations.js +413 -0
  146. package/dist/apps/platform/routes/invitations.js.map +1 -0
  147. package/dist/apps/platform/routes/me.d.ts +95 -0
  148. package/dist/apps/platform/routes/me.d.ts.map +1 -0
  149. package/dist/apps/platform/routes/me.js +81 -0
  150. package/dist/apps/platform/routes/me.js.map +1 -0
  151. package/dist/apps/platform/routes/members.d.ts +554 -0
  152. package/dist/apps/platform/routes/members.d.ts.map +1 -0
  153. package/dist/apps/platform/routes/members.js +251 -0
  154. package/dist/apps/platform/routes/members.js.map +1 -0
  155. package/dist/apps/platform/routes/orgs.d.ts +582 -0
  156. package/dist/apps/platform/routes/orgs.d.ts.map +1 -0
  157. package/dist/apps/platform/routes/orgs.js +265 -0
  158. package/dist/apps/platform/routes/orgs.js.map +1 -0
  159. package/dist/apps/platform/routes/projects.d.ts +740 -0
  160. package/dist/apps/platform/routes/projects.d.ts.map +1 -0
  161. package/dist/apps/platform/routes/projects.js +286 -0
  162. package/dist/apps/platform/routes/projects.js.map +1 -0
  163. package/dist/apps/relay/App.d.ts +41 -0
  164. package/dist/apps/relay/App.d.ts.map +1 -0
  165. package/dist/apps/relay/App.js +103 -0
  166. package/dist/apps/relay/App.js.map +1 -0
  167. package/dist/apps/relay/Sponsorships.d.ts +107 -0
  168. package/dist/apps/relay/Sponsorships.d.ts.map +1 -0
  169. package/dist/apps/relay/Sponsorships.js +193 -0
  170. package/dist/apps/relay/Sponsorships.js.map +1 -0
  171. package/dist/apps/relay/index.d.ts +3 -0
  172. package/dist/apps/relay/index.d.ts.map +1 -0
  173. package/dist/apps/relay/index.js +3 -0
  174. package/dist/apps/relay/index.js.map +1 -0
  175. package/dist/cli/Cli.d.ts +1 -1
  176. package/dist/cli/Cli.js +1 -1
  177. package/dist/cli/commands/admin.d.ts +1 -1
  178. package/dist/cli/commands/admin.js +2 -2
  179. package/dist/cli/commands/admin.js.map +1 -1
  180. package/dist/db/Db.d.ts +10 -0
  181. package/dist/db/Db.d.ts.map +1 -1
  182. package/dist/db/Db.js +128 -0
  183. package/dist/db/Db.js.map +1 -1
  184. package/dist/db/Schema.d.ts +80 -0
  185. package/dist/db/Schema.d.ts.map +1 -1
  186. package/dist/db/Schema.js +99 -0
  187. package/dist/db/Schema.js.map +1 -1
  188. package/dist/db/tables/invitations.d.ts +84 -0
  189. package/dist/db/tables/invitations.d.ts.map +1 -0
  190. package/dist/db/tables/invitations.js +165 -0
  191. package/dist/db/tables/invitations.js.map +1 -0
  192. package/dist/db/tables/memberships.d.ts +108 -0
  193. package/dist/db/tables/memberships.d.ts.map +1 -0
  194. package/dist/db/tables/memberships.js +153 -0
  195. package/dist/db/tables/memberships.js.map +1 -0
  196. package/dist/db/tables/organizations.d.ts +44 -0
  197. package/dist/db/tables/organizations.d.ts.map +1 -1
  198. package/dist/db/tables/organizations.js +89 -0
  199. package/dist/db/tables/organizations.js.map +1 -1
  200. package/dist/db/tables/projects.d.ts +65 -0
  201. package/dist/db/tables/projects.d.ts.map +1 -0
  202. package/dist/db/tables/projects.js +75 -0
  203. package/dist/db/tables/projects.js.map +1 -0
  204. package/dist/db/tables/sponsoredTransactions.d.ts +120 -0
  205. package/dist/db/tables/sponsoredTransactions.d.ts.map +1 -0
  206. package/dist/db/tables/sponsoredTransactions.js +161 -0
  207. package/dist/db/tables/sponsoredTransactions.js.map +1 -0
  208. package/dist/db/tables/users.d.ts +48 -0
  209. package/dist/db/tables/users.d.ts.map +1 -0
  210. package/dist/db/tables/users.js +65 -0
  211. package/dist/db/tables/users.js.map +1 -0
  212. package/dist/handlers/internal/executionError.d.ts.map +1 -1
  213. package/dist/handlers/internal/executionError.js +2 -0
  214. package/dist/handlers/internal/executionError.js.map +1 -1
  215. package/dist/handlers/internal/multisig.d.ts +2 -6
  216. package/dist/handlers/internal/multisig.d.ts.map +1 -1
  217. package/dist/handlers/internal/multisig.js +11 -36
  218. package/dist/handlers/internal/multisig.js.map +1 -1
  219. package/dist/handlers/internal/sponsorship.d.ts +32 -2
  220. package/dist/handlers/internal/sponsorship.d.ts.map +1 -1
  221. package/dist/handlers/internal/sponsorship.js +34 -9
  222. package/dist/handlers/internal/sponsorship.js.map +1 -1
  223. package/dist/handlers/relay.d.ts +6 -2
  224. package/dist/handlers/relay.d.ts.map +1 -1
  225. package/dist/handlers/relay.js +16 -2
  226. package/dist/handlers/relay.js.map +1 -1
  227. package/dist/internal/Auth.d.ts +208 -6
  228. package/dist/internal/Auth.d.ts.map +1 -1
  229. package/dist/internal/Auth.js +500 -21
  230. package/dist/internal/Auth.js.map +1 -1
  231. package/dist/internal/Log.d.ts +7 -3
  232. package/dist/internal/Log.d.ts.map +1 -1
  233. package/dist/internal/Log.js +4 -0
  234. package/dist/internal/Log.js.map +1 -1
  235. package/dist/internal/OpenApi.d.ts +0 -19
  236. package/dist/internal/OpenApi.d.ts.map +1 -1
  237. package/dist/internal/OpenApi.js +0 -57
  238. package/dist/internal/OpenApi.js.map +1 -1
  239. package/dist/internal/Store.d.ts +7 -1
  240. package/dist/internal/Store.d.ts.map +1 -1
  241. package/dist/internal/Store.js +16 -2
  242. package/dist/internal/Store.js.map +1 -1
  243. package/dist/internal/Viem.d.ts +84 -0
  244. package/dist/internal/Viem.d.ts.map +1 -1
  245. package/dist/internal/Webhooks.d.ts +1 -1
  246. package/dist/internal/Webhooks.d.ts.map +1 -1
  247. package/package.json +31 -5
  248. package/src/ApiKey.ts +1 -0
  249. package/src/ApiKeys.test.ts +104 -1
  250. package/src/ApiKeys.ts +154 -1
  251. package/src/App.test.ts +11187 -179
  252. package/src/App.ts +200 -420
  253. package/src/Client.test-d.ts +306 -15
  254. package/src/Scope.ts +13 -4
  255. package/src/Webhooks.ts +2 -2
  256. package/src/admin/apps/api-keys.test.ts +51 -0
  257. package/src/admin/apps/api-keys.ts +84 -0
  258. package/src/admin/apps/scopes.test.ts +5 -1
  259. package/src/admin/apps/verified-tokens.ts +1 -1
  260. package/src/admin/ui.generated.ts +1 -1
  261. package/src/apps/composition.test.ts +66 -0
  262. package/src/apps/data/App.ts +295 -0
  263. package/src/apps/data/index.ts +2 -0
  264. package/src/apps/{activities.test.ts → data/routes/activities.test.ts} +3 -3
  265. package/src/apps/{activities.ts → data/routes/activities.ts} +15 -15
  266. package/src/apps/{addresses.ts → data/routes/addresses.ts} +6 -6
  267. package/src/apps/{balances.test.ts → data/routes/balances.test.ts} +2 -2
  268. package/src/apps/{balances.ts → data/routes/balances.ts} +46 -12
  269. package/src/apps/{blocks.test.ts → data/routes/blocks.test.ts} +3 -3
  270. package/src/apps/{blocks.ts → data/routes/blocks.ts} +14 -14
  271. package/src/apps/{coingecko.test.ts → data/routes/coingecko.test.ts} +2 -2
  272. package/src/apps/{coingecko.ts → data/routes/coingecko.ts} +14 -14
  273. package/src/apps/{exchanges.test.ts → data/routes/exchanges.test.ts} +1 -1
  274. package/src/apps/{exchanges.ts → data/routes/exchanges.ts} +20 -20
  275. package/src/apps/{fee-amm.test.ts → data/routes/fee-amm.test.ts} +3 -3
  276. package/src/apps/{fee-amm.ts → data/routes/fee-amm.ts} +18 -18
  277. package/src/apps/{indexer.test.ts → data/routes/indexer.test.ts} +26 -5
  278. package/src/apps/{indexer.ts → data/routes/indexer.ts} +13 -10
  279. package/src/apps/{receipts.test.ts → data/routes/receipts.test.ts} +3 -3
  280. package/src/apps/{receipts.ts → data/routes/receipts.ts} +13 -13
  281. package/src/apps/{rpc.test.ts → data/routes/rpc.test.ts} +44 -5
  282. package/src/apps/{rpc.ts → data/routes/rpc.ts} +7 -7
  283. package/src/apps/{tokenlist.test.ts → data/routes/tokenlist.test.ts} +3 -3
  284. package/src/apps/{tokenlist.ts → data/routes/tokenlist.ts} +9 -9
  285. package/src/apps/{tokens.test.ts → data/routes/tokens.test.ts} +2 -2
  286. package/src/apps/{tokens.ts → data/routes/tokens.ts} +20 -20
  287. package/src/apps/{transactions.test.ts → data/routes/transactions.test.ts} +3 -3
  288. package/src/apps/{transactions.ts → data/routes/transactions.ts} +15 -15
  289. package/src/apps/{transfers.test.ts → data/routes/transfers.test.ts} +2 -2
  290. package/src/apps/{transfers.ts → data/routes/transfers.ts} +15 -15
  291. package/src/apps/{verified-tokens.test.ts → data/routes/verified-tokens.test.ts} +3 -3
  292. package/src/apps/{verified-tokens.ts → data/routes/verified-tokens.ts} +10 -10
  293. package/src/apps/{webhooks.test.ts → data/routes/webhooks.test.ts} +6 -6
  294. package/src/apps/{webhooks.ts → data/routes/webhooks.ts} +39 -35
  295. package/src/apps/docs/App.ts +136 -0
  296. package/src/apps/docs/index.ts +1 -0
  297. package/src/apps/index.ts +3 -0
  298. package/src/apps/metadata.ts +23 -0
  299. package/src/apps/platform/App.ts +130 -0
  300. package/src/apps/platform/index.ts +1 -0
  301. package/src/apps/platform/routes/api-keys.test.ts +330 -0
  302. package/src/apps/platform/routes/api-keys.ts +427 -0
  303. package/src/apps/platform/routes/invitations.test.ts +361 -0
  304. package/src/apps/platform/routes/invitations.ts +519 -0
  305. package/src/apps/platform/routes/me.test.ts +121 -0
  306. package/src/apps/platform/routes/me.ts +106 -0
  307. package/src/apps/platform/routes/members.test.ts +195 -0
  308. package/src/apps/platform/routes/members.ts +313 -0
  309. package/src/apps/platform/routes/orgs.test.ts +313 -0
  310. package/src/apps/platform/routes/orgs.ts +343 -0
  311. package/src/apps/platform/routes/projects.test.ts +181 -0
  312. package/src/apps/platform/routes/projects.ts +367 -0
  313. package/src/apps/relay/App.test.ts +484 -0
  314. package/src/apps/relay/App.ts +128 -0
  315. package/src/apps/relay/Sponsorships.test.ts +375 -0
  316. package/src/apps/relay/Sponsorships.ts +305 -0
  317. package/src/apps/relay/index.ts +2 -0
  318. package/src/cli/Cli.ts +1 -1
  319. package/src/cli/commands/admin.ts +2 -2
  320. package/src/db/Db.ts +159 -0
  321. package/src/db/Schema.ts +137 -0
  322. package/src/db/tables/invitations.ts +198 -0
  323. package/src/db/tables/memberships.ts +208 -0
  324. package/src/db/tables/organizations.test.ts +37 -1
  325. package/src/db/tables/organizations.ts +105 -0
  326. package/src/db/tables/projects.ts +107 -0
  327. package/src/db/tables/sponsoredTransactions.test.ts +218 -0
  328. package/src/db/tables/sponsoredTransactions.ts +236 -0
  329. package/src/db/tables/users.ts +85 -0
  330. package/src/handlers/internal/executionError.ts +2 -0
  331. package/src/handlers/internal/multisig.test.ts +84 -10
  332. package/src/handlers/internal/multisig.ts +15 -50
  333. package/src/handlers/internal/sponsorship.ts +74 -15
  334. package/src/handlers/{internal/relay.localnet.test.ts → relay.test.ts} +2 -2
  335. package/src/handlers/relay.ts +23 -5
  336. package/src/internal/Auth.test.ts +316 -0
  337. package/src/internal/Auth.ts +691 -25
  338. package/src/internal/Cursor.test.ts +3 -2
  339. package/src/internal/Log.test.ts +1 -1
  340. package/src/internal/Log.ts +11 -3
  341. package/src/internal/MetricSink.ts +1 -1
  342. package/src/internal/OpenApi.ts +0 -59
  343. package/src/internal/Store.test.ts +52 -0
  344. package/src/internal/Store.ts +24 -5
  345. package/src/internal/Tidx.local.test.ts +1 -1
  346. package/src/internal/VerifiedTokens.test.ts +1 -1
  347. package/src/internal/WebhookDestination.test.ts +1 -1
  348. package/src/internal/Webhooks.test.ts +4 -4
  349. package/src/internal/Webhooks.ts +1 -1
  350. package/dist/apps/activities.js.map +0 -1
  351. package/dist/apps/addresses.js.map +0 -1
  352. package/dist/apps/balances.d.ts.map +0 -1
  353. package/dist/apps/balances.js.map +0 -1
  354. package/dist/apps/blocks.d.ts.map +0 -1
  355. package/dist/apps/blocks.js.map +0 -1
  356. package/dist/apps/coingecko.d.ts.map +0 -1
  357. package/dist/apps/coingecko.js.map +0 -1
  358. package/dist/apps/exchanges.d.ts.map +0 -1
  359. package/dist/apps/exchanges.js.map +0 -1
  360. package/dist/apps/fee-amm.d.ts.map +0 -1
  361. package/dist/apps/fee-amm.js.map +0 -1
  362. package/dist/apps/indexer.d.ts.map +0 -1
  363. package/dist/apps/indexer.js.map +0 -1
  364. package/dist/apps/receipts.d.ts.map +0 -1
  365. package/dist/apps/receipts.js.map +0 -1
  366. package/dist/apps/rpc.d.ts.map +0 -1
  367. package/dist/apps/rpc.js.map +0 -1
  368. package/dist/apps/tokenlist.d.ts.map +0 -1
  369. package/dist/apps/tokenlist.js.map +0 -1
  370. package/dist/apps/tokens.d.ts.map +0 -1
  371. package/dist/apps/tokens.js.map +0 -1
  372. package/dist/apps/transactions.d.ts.map +0 -1
  373. package/dist/apps/transactions.js.map +0 -1
  374. package/dist/apps/transfers.d.ts.map +0 -1
  375. package/dist/apps/transfers.js.map +0 -1
  376. package/dist/apps/verified-tokens.d.ts.map +0 -1
  377. package/dist/apps/verified-tokens.js.map +0 -1
  378. package/dist/apps/webhooks.js.map +0 -1
  379. package/dist/internal/OpenApi.fonts.d.ts.map +0 -1
  380. package/dist/internal/OpenApi.fonts.js.map +0 -1
  381. package/dist/internal/OpenApi.logo.d.ts.map +0 -1
  382. package/dist/internal/OpenApi.logo.js.map +0 -1
  383. package/src/handlers/internal/multisig.localnet.test.ts +0 -146
  384. /package/src/{internal/OpenApi.fonts.ts → apps/docs/fonts.ts} +0 -0
  385. /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
+ }
@@ -34,6 +34,7 @@ export const messages: Record<AbiErrorName, string> = {
34
34
  ChannelNotFound: 'Channel not found.',
35
35
  CloseNotReady: 'Channel is not ready to close.',
36
36
  ContractPaused: 'Contract is paused.',
37
+ DelegateCallNotAllowed: 'Delegate call is not allowed.',
37
38
  DepositOverflow: 'Deposit overflow.',
38
39
  DivisionByZero: 'Division by zero.',
39
40
  EmptyV1ValidatorSet: 'Validator set is empty.',
@@ -65,6 +66,7 @@ export const messages: Record<AbiErrorName, string> = {
65
66
  InvalidLogoURI: 'Invalid logo URI.',
66
67
  InvalidMasterAddress: 'Invalid master address.',
67
68
  InvalidMigrationIndex: 'Invalid migration index.',
69
+ InvalidMode: 'Invalid mode.',
68
70
  InvalidNonceKey: 'Invalid nonce key.',
69
71
  InvalidOwner: 'Invalid owner.',
70
72
  InvalidPayee: 'Invalid payee.',