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
@@ -1,16 +1,18 @@
1
1
  import type { Context } from 'hono'
2
+ import { sql } from 'kysely'
2
3
  import { Hex } from 'ox'
3
4
  import * as z from 'zod/mini'
4
5
 
5
6
  import type * as App from '../App.js'
7
+ import * as Db from '../db/Db.js'
8
+ import * as core_VerifiedTokens from '../db/tables/verifiedTokens.js'
6
9
  import * as Schema from './Schema.js'
7
- import * as Store from './Store.js'
8
10
  import * as Timing from './Timing.js'
9
11
 
10
12
  /** Chain id covered by the curated verified-token lists. */
11
13
  export type ChainId = z.output<typeof Schema.ChainId>
12
14
 
13
- /** Schema for a chain's verified token list (the value stored in KV). */
15
+ /** Schema for a chain's verified token list (validated at the write boundary). */
14
16
  export const Data = z
15
17
  .array(
16
18
  z
@@ -68,7 +70,8 @@ export function compile(options: compile.Options): Snapshot {
68
70
  const { chainId, tokens, updatedAt, version } = options
69
71
  // Backfill the derived `id` (lowercased address) without re-parsing through
70
72
  // `Data`/`Schema.Address`, which would lowercase the stored `address` and
71
- // drop its curated checksum casing. Callers (readBlob/normalize) own validation.
73
+ // drop its curated checksum casing. Validation happens at the write boundary
74
+ // (`normalize`); reads trust the typed columns.
72
75
  const list: SnapshotToken[] = tokens.map((token) => ({
73
76
  ...token,
74
77
  id: token.id ?? (token.address.toLowerCase() as Hex.Hex),
@@ -112,90 +115,34 @@ export declare namespace compile {
112
115
  }
113
116
  }
114
117
 
115
- // Storage layout: one head pointer + one whole-chain blob per version, so
116
- // reads are a single `get` by known key (no `list()` scans) and a publish is an
117
- // atomic flip of `head` to a new, already-written `snapshot:{version}`.
118
- const keyPrefix = 'verified-token:v1'
118
+ // Storage layout: one `verified_tokens` row per curated token (ordered by
119
+ // `position`) plus a per-chain `verified_token_lists` row carrying the opaque
120
+ // list `version` the soft-refresh cache and `If-Match` preconditions compare.
119
121
 
120
- // Storage schema version stamped on every head/blob, so a future on-disk format
121
- // change can be detected and migrated.
122
- const storeSchema = 1
122
+ /** A chain's list-level metadata (the "head" the cache compares against). */
123
+ export type Head = core_VerifiedTokens.Meta
123
124
 
124
- /** Store key for a chain's head pointer (current version + metadata). */
125
- function headKey(chainId: ChainId): string {
126
- return `${keyPrefix}:${chainId}:head`
127
- }
128
-
129
- /** Store key for a chain's immutable snapshot blob at a given version. */
130
- function snapshotKey(chainId: ChainId, version: string): string {
131
- return `${keyPrefix}:${chainId}:snapshot:${version}`
132
- }
133
-
134
- // Head pointer: tiny, read once per soft-TTL window to detect version changes
135
- // without fetching the (much larger) token blob.
136
- const Head = z
137
- .object({
138
- chainId: z.number().check(z.int(), z.describe('Chain the head belongs to.')),
139
- count: z.number().check(z.int(), z.nonnegative(), z.describe('Token count at this version.')),
140
- schema: z.number().check(z.int(), z.describe('Storage schema version.')),
141
- updatedAt: z.string().check(z.describe('ISO timestamp of the last publish.')),
142
- version: z.string().check(z.describe('Current snapshot version.')),
143
- })
144
- .check(z.describe('Verified-token head pointer stored under the head key.'))
145
-
146
- // Immutable per-version blob holding the validated token list.
147
- const Blob = z
148
- .object({
149
- chainId: z.number().check(z.int(), z.describe('Chain the blob belongs to.')),
150
- schema: z.number().check(z.int(), z.describe('Storage schema version.')),
151
- tokens: Data,
152
- updatedAt: z.string().check(z.describe('ISO timestamp of the last publish.')),
153
- version: z.string().check(z.describe('Snapshot version this blob holds.')),
154
- })
155
- .check(z.describe('Verified-token snapshot blob stored under a versioned key.'))
156
-
157
- /** Parsed head pointer for a chain. */
158
- export type Head = z.output<typeof Head>
159
-
160
- /** Reads a chain's head pointer, or `null` when the chain has no head yet. */
161
- async function readHead(store: Store.State, chainId: ChainId): Promise<Head | null> {
162
- const raw = await store.get(headKey(chainId))
163
- if (!raw) return null
164
- return Head.parse(JSON.parse(raw))
125
+ /** Reads a chain's list metadata, or `null` when it has no list yet. */
126
+ async function readHead(db: Db.Db, chainId: ChainId): Promise<Head | null> {
127
+ return (await core_VerifiedTokens.head(db, chainId)) ?? null
165
128
  }
166
129
 
167
130
  /**
168
- * Reads and compiles a chain's snapshot blob at a specific version. Throws
169
- * {@link TornStateError} when the blob is missing (a torn write that should
170
- * never happen given the write-blob-before-flip-head ordering).
131
+ * Reads and compiles a chain's current verified list. Returns `null` when the
132
+ * chain has none.
171
133
  */
172
- async function readBlob(store: Store.State, chainId: ChainId, version: string): Promise<Snapshot> {
173
- const raw = await store.get(snapshotKey(chainId, version))
174
- if (!raw) throw new TornStateError({ chainId, version })
175
- const parsed = JSON.parse(raw)
176
- const blob = Blob.parse({
177
- ...parsed,
178
- tokens: Array.isArray(parsed.tokens) ? withIds(parsed.tokens) : parsed.tokens,
179
- })
134
+ export async function read(db: Db.Db, chainId: ChainId): Promise<Snapshot | null> {
135
+ const head = await readHead(db, chainId)
136
+ if (!head) return null
137
+ const rows = await core_VerifiedTokens.list(db, chainId)
180
138
  return compile({
181
139
  chainId,
182
- tokens: blob.tokens,
183
- updatedAt: blob.updatedAt,
184
- version: blob.version,
140
+ tokens: rows.map(core_VerifiedTokens.toToken),
141
+ updatedAt: head.updatedAt,
142
+ version: head.version,
185
143
  })
186
144
  }
187
145
 
188
- /**
189
- * Reads and compiles the snapshot a chain's head points at. Returns `null` when
190
- * the chain has no head. Throws {@link TornStateError} when `head` references a
191
- * missing snapshot blob.
192
- */
193
- export async function read(store: Store.State, chainId: ChainId): Promise<Snapshot | null> {
194
- const head = await readHead(store, chainId)
195
- if (!head) return null
196
- return readBlob(store, chainId, head.version)
197
- }
198
-
199
146
  // Tracks the last epoch-ms used by `nextVersion` so versions stay strictly
200
147
  // monotonic even when multiple writes land in the same millisecond.
201
148
  let lastVersionMs = 0
@@ -246,48 +193,56 @@ function withIds(tokens: readonly unknown[]): unknown[] {
246
193
  // Returns the current authoritative list for a chain to read-modify-write
247
194
  // against: the durable snapshot, or an empty list when the chain has no head yet
248
195
  // (the first write starts the chain's list from scratch).
249
- async function currentList(
250
- store: Store.State,
251
- chainId: ChainId,
252
- ): Promise<readonly SnapshotToken[]> {
253
- return (await read(store, chainId))?.list ?? []
196
+ async function currentList(db: Db.Db, chainId: ChainId): Promise<readonly SnapshotToken[]> {
197
+ return (await read(db, chainId))?.list ?? []
254
198
  }
255
199
 
256
- // Best-effort optimistic concurrency: when `ifMatch` is set, the caller's
257
- // expected version must equal the current head version. On KV the head
258
- // read can itself be stale, so this narrows but does not eliminate — the
259
- // lost-update window under concurrent writers.
200
+ // Optimistic concurrency: when `ifMatch` is set, the caller's expected version
201
+ // must equal the current head version. Runs inside the publish lock, so —
202
+ // unlike the old best-effort KV checkthe compare-and-set actually holds.
260
203
  async function assertVersion(
261
- store: Store.State,
204
+ db: Db.Db,
262
205
  chainId: ChainId,
263
206
  ifMatch: string | undefined,
264
207
  ): Promise<void> {
265
208
  if (ifMatch === undefined) return
266
- const head = await readHead(store, chainId)
209
+ const head = await readHead(db, chainId)
267
210
  const actual = head?.version ?? emptyVersion
268
211
  if (actual !== ifMatch) throw new VersionMismatchError({ actual, chainId, expected: ifMatch })
269
212
  }
270
213
 
271
- // Write-modify-flip-prime: validate the whole list, write the immutable
272
- // blob, flip `head` to it, then prime this isolate for read-your-write. Writing
273
- // the blob before flipping head means a crash in between leaves the old head
274
- // valid (no torn state).
214
+ /**
215
+ * Fixed first key for the per-chain publish advisory lock (the ASCII bytes of
216
+ * `"vtok"`); the chain id is the second key.
217
+ */
218
+ const publishLockKey = 0x76746f6b
219
+
220
+ // Runs a write's read-modify-publish inside one transaction holding a
221
+ // per-chain advisory lock, serializing concurrent writers so `assertVersion`
222
+ // and the read-modify-write can't interleave (the lock releases on commit).
223
+ async function withPublishLock<value>(
224
+ db: Db.Db,
225
+ chainId: ChainId,
226
+ fn: (tx: Db.Db) => Promise<value>,
227
+ ): Promise<value> {
228
+ return db.transaction(async (tx) => {
229
+ await sql`SELECT pg_advisory_xact_lock(${publishLockKey}, ${chainId})`.execute(tx.kysely)
230
+ return fn(tx)
231
+ })
232
+ }
233
+
234
+ // Validate-replace-prime: validate the whole list, replace the chain's rows
235
+ // and bump its list version (atomic inside the publish lock's transaction),
236
+ // then prime this isolate for read-your-write.
275
237
  async function publish(
276
- store: Store.State,
238
+ db: Db.Db,
277
239
  chainId: ChainId,
278
240
  tokens: readonly TokenInput[],
279
241
  ): Promise<Snapshot> {
280
242
  const list = normalize(chainId, tokens)
281
243
  const version = nextVersion()
282
244
  const updatedAt = new Date().toISOString()
283
- await store.put(
284
- snapshotKey(chainId, version),
285
- JSON.stringify({ chainId, schema: storeSchema, tokens: list, updatedAt, version }),
286
- )
287
- await store.put(
288
- headKey(chainId),
289
- JSON.stringify({ chainId, count: list.length, schema: storeSchema, updatedAt, version }),
290
- )
245
+ await core_VerifiedTokens.publish(db, chainId, { tokens: list, updatedAt, version })
291
246
  const snapshot = compile({ chainId, tokens: list, updatedAt, version })
292
247
  prime(chainId, snapshot)
293
248
  return snapshot
@@ -297,21 +252,23 @@ async function publish(
297
252
  * Appends a verified token to a chain's list and publishes a new snapshot.
298
253
  * Throws on a duplicate address or (case-insensitive) symbol.
299
254
  */
300
- export async function create(store: Store.State, input: create.Input): Promise<create.Result> {
255
+ export async function create(db: Db.Db, input: create.Input): Promise<create.Result> {
301
256
  const { chainId, currency, decimals, logoUri, name, symbol } = input
302
257
  const address = input.address.toLowerCase() as Hex.Hex
303
- const list = await currentList(store, chainId)
304
- const token: Token = {
305
- address,
306
- currency,
307
- decimals,
308
- id: address,
309
- name,
310
- symbol,
311
- ...(logoUri === undefined ? {} : { logoUri }),
312
- }
313
- const snapshot = await publish(store, chainId, [...list, token])
314
- return { snapshot, token: snapshot.byAddress.get(address)! }
258
+ return withPublishLock(db, chainId, async (tx) => {
259
+ const list = await currentList(tx, chainId)
260
+ const token: Token = {
261
+ address,
262
+ currency,
263
+ decimals,
264
+ id: address,
265
+ name,
266
+ symbol,
267
+ ...(logoUri === undefined ? {} : { logoUri }),
268
+ }
269
+ const snapshot = await publish(tx, chainId, [...list, token])
270
+ return { snapshot, token: snapshot.byAddress.get(address)! }
271
+ })
315
272
  }
316
273
 
317
274
  export declare namespace create {
@@ -347,33 +304,35 @@ export declare namespace create {
347
304
  * absent, and the uniqueness errors when an edit collides with another entry.
348
305
  */
349
306
  export async function patch(
350
- store: Store.State,
307
+ db: Db.Db,
351
308
  chainId: ChainId,
352
309
  address: string,
353
310
  input: patch.Input,
354
311
  options: patch.Options = {},
355
312
  ): Promise<create.Result> {
356
- await assertVersion(store, chainId, options.ifMatch)
357
313
  const target = address.toLowerCase() as Hex.Hex
358
- const list = await currentList(store, chainId)
359
- const index = list.findIndex((token) => token.address.toLowerCase() === target)
360
- if (index === -1) throw new NotFoundError({ address: target, chainId })
361
- // Edit in place, overriding only the fields the patch supplies.
362
- const next = list.map((token, i) => {
363
- if (i !== index) return token
364
- const logoUri = input.logoUri ?? token.logoUri
365
- return {
366
- address: target,
367
- currency: input.currency ?? token.currency,
368
- decimals: input.decimals ?? token.decimals,
369
- id: target,
370
- name: input.name ?? token.name,
371
- symbol: input.symbol ?? token.symbol,
372
- ...(logoUri === undefined ? {} : { logoUri }),
373
- }
314
+ return withPublishLock(db, chainId, async (tx) => {
315
+ await assertVersion(tx, chainId, options.ifMatch)
316
+ const list = await currentList(tx, chainId)
317
+ const index = list.findIndex((token) => token.address.toLowerCase() === target)
318
+ if (index === -1) throw new NotFoundError({ address: target, chainId })
319
+ // Edit in place, overriding only the fields the patch supplies.
320
+ const next = list.map((token, i) => {
321
+ if (i !== index) return token
322
+ const logoUri = input.logoUri ?? token.logoUri
323
+ return {
324
+ address: target,
325
+ currency: input.currency ?? token.currency,
326
+ decimals: input.decimals ?? token.decimals,
327
+ id: target,
328
+ name: input.name ?? token.name,
329
+ symbol: input.symbol ?? token.symbol,
330
+ ...(logoUri === undefined ? {} : { logoUri }),
331
+ }
332
+ })
333
+ const snapshot = await publish(tx, chainId, next)
334
+ return { snapshot, token: snapshot.byAddress.get(target)! }
374
335
  })
375
- const snapshot = await publish(store, chainId, next)
376
- return { snapshot, token: snapshot.byAddress.get(target)! }
377
336
  }
378
337
 
379
338
  export declare namespace patch {
@@ -402,17 +361,19 @@ export declare namespace patch {
402
361
  * Throws {@link NotFoundError} when the address is absent.
403
362
  */
404
363
  export async function remove(
405
- store: Store.State,
364
+ db: Db.Db,
406
365
  chainId: ChainId,
407
366
  address: string,
408
367
  options: patch.Options = {},
409
368
  ): Promise<remove.Result> {
410
- await assertVersion(store, chainId, options.ifMatch)
411
369
  const target = address.toLowerCase()
412
- const list = await currentList(store, chainId)
413
- const next = list.filter((token) => token.address.toLowerCase() !== target)
414
- if (next.length === list.length) throw new NotFoundError({ address: target, chainId })
415
- return { snapshot: await publish(store, chainId, next) }
370
+ return withPublishLock(db, chainId, async (tx) => {
371
+ await assertVersion(tx, chainId, options.ifMatch)
372
+ const list = await currentList(tx, chainId)
373
+ const next = list.filter((token) => token.address.toLowerCase() !== target)
374
+ if (next.length === list.length) throw new NotFoundError({ address: target, chainId })
375
+ return { snapshot: await publish(tx, chainId, next) }
376
+ })
416
377
  }
417
378
 
418
379
  export declare namespace remove {
@@ -428,13 +389,15 @@ export declare namespace remove {
428
389
  * bulk-load the initial list and to roll back to a previous one.
429
390
  */
430
391
  export async function replace(
431
- store: Store.State,
392
+ db: Db.Db,
432
393
  chainId: ChainId,
433
394
  tokens: readonly TokenInput[],
434
395
  options: patch.Options = {},
435
396
  ): Promise<remove.Result> {
436
- await assertVersion(store, chainId, options.ifMatch)
437
- return { snapshot: await publish(store, chainId, tokens) }
397
+ return withPublishLock(db, chainId, async (tx) => {
398
+ await assertVersion(tx, chainId, options.ifMatch)
399
+ return { snapshot: await publish(tx, chainId, tokens) }
400
+ })
438
401
  }
439
402
 
440
403
  // Sentinel version/time for the empty snapshot served before a chain has any
@@ -491,7 +454,7 @@ export function prime(chainId: ChainId, snapshot: Snapshot): void {
491
454
  // chain share one in-flight refresh.
492
455
  function refresh(
493
456
  c: Context<App.Environment>,
494
- store: Store.State,
457
+ db: Db.Db,
495
458
  chainId: ChainId,
496
459
  cell: Cell | undefined,
497
460
  ): Promise<Snapshot> {
@@ -499,7 +462,7 @@ function refresh(
499
462
  if (existing) return existing
500
463
  const flight = (async () => {
501
464
  try {
502
- return await refreshCell(c, store, chainId, cell)
465
+ return await refreshCell(c, db, chainId, cell)
503
466
  } finally {
504
467
  refreshes.delete(chainId)
505
468
  }
@@ -513,15 +476,15 @@ function refresh(
513
476
  // when the chain has no head yet).
514
477
  async function refreshCell(
515
478
  c: Context<App.Environment>,
516
- store: Store.State,
479
+ db: Db.Db,
517
480
  chainId: ChainId,
518
481
  cell: Cell | undefined,
519
482
  ): Promise<Snapshot> {
520
- // Cold: no prior snapshot. Load from store, or an empty snapshot when the
521
- // chain has no head. A hard failure here propagates (we have nothing good to
522
- // serve, and must not resurrect deleted tokens).
483
+ // Cold: no prior snapshot. Load from the database, or an empty snapshot when
484
+ // the chain has no head. A hard failure here propagates (we have nothing good
485
+ // to serve, and must not resurrect deleted tokens).
523
486
  if (!cell) {
524
- const loaded = await Timing.time(c, 'verified_snapshot', () => read(store, chainId))
487
+ const loaded = await Timing.time(c, 'verified_snapshot', () => read(db, chainId))
525
488
  const snapshot = loaded ?? emptySnapshot(chainId)
526
489
  cells.set(chainId, { checkedAt: Date.now(), snapshot })
527
490
  return snapshot
@@ -530,16 +493,15 @@ async function refreshCell(
530
493
  // Soft-stale: serve the last good in-memory snapshot and log loudly on
531
494
  // failure rather than dropping to empty (no resurrection of deleted tokens).
532
495
  try {
533
- const head = await Timing.time(c, 'verified_head', () => readHead(store, chainId))
496
+ const head = await Timing.time(c, 'verified_head', () => readHead(db, chainId))
534
497
  // Unchanged version (or head not yet present): keep snapshot, bump checkedAt.
535
498
  if (!head || head.version === cell.snapshot.version) {
536
499
  cells.set(chainId, { checkedAt: Date.now(), snapshot: cell.snapshot })
537
500
  return cell.snapshot
538
501
  }
539
- // Version changed: load the new blob directly (head already in hand).
540
- const snapshot = await Timing.time(c, 'verified_snapshot', () =>
541
- readBlob(store, chainId, head.version),
542
- )
502
+ // Version changed: reload the current list (kept on a racing delete).
503
+ const snapshot =
504
+ (await Timing.time(c, 'verified_snapshot', () => read(db, chainId))) ?? cell.snapshot
543
505
  cells.set(chainId, { checkedAt: Date.now(), snapshot })
544
506
  return snapshot
545
507
  } catch (error) {
@@ -553,32 +515,32 @@ async function refreshCell(
553
515
  * Returns the compiled verified-token {@link Snapshot} for a chain.
554
516
  *
555
517
  * When the verified-tokens feature is unconfigured, serves an empty snapshot.
556
- * When configured with a {@link Store.State}, serves a per-isolate snapshot
557
- * refreshed on a soft TTL: fresh lookups do zero store I/O; soft-stale
518
+ * When configured, serves a per-isolate snapshot backed by the app database,
519
+ * refreshed on a soft TTL: fresh lookups do zero database I/O; soft-stale
558
520
  * lookups return the current snapshot immediately and refresh in the background
559
521
  * (single-flight, head-only unless the version changed); a cold isolate loads
560
- * from the store (an empty snapshot when no head exists).
522
+ * from the database (an empty snapshot when no head exists).
561
523
  */
562
524
  export async function snapshot(c: Context<App.Environment>, chainId: ChainId): Promise<Snapshot> {
563
525
  return Timing.time(c, 'verified_tokens', () => {
564
526
  const config = c.get('verifiedTokens')
565
- // Unconfigured: nothing is verified. No store, no cell.
527
+ // Unconfigured: nothing is verified. No reads, no cell.
566
528
  if (!config) return emptySnapshot(chainId)
567
529
 
568
530
  const refreshMs = config.refreshMs ?? defaultRefreshMs
569
531
  const cell = cells.get(chainId)
570
532
 
571
- // Fresh: serve the in-memory snapshot with zero store I/O.
533
+ // Fresh: serve the in-memory snapshot with zero database I/O.
572
534
  if (cell && Date.now() - cell.checkedAt < refreshMs) return cell.snapshot
573
535
 
574
536
  // Soft-stale: serve immediately, refresh in the background. Never blocks.
575
537
  if (cell) {
576
- void refresh(c, config.store, chainId, cell)
538
+ void refresh(c, Db.get(c.get('dbCached')), chainId, cell)
577
539
  return cell.snapshot
578
540
  }
579
541
 
580
542
  // Cold: must load before the first response.
581
- return refresh(c, config.store, chainId, undefined)
543
+ return refresh(c, Db.get(c.get('dbCached')), chainId, undefined)
582
544
  })
583
545
  }
584
546
 
@@ -590,20 +552,6 @@ export async function snapshot(c: Context<App.Environment>, chainId: ChainId): P
590
552
  */
591
553
  export const currencies = ['EUR', 'USD']
592
554
 
593
- /**
594
- * Thrown when a chain's `head` points at a snapshot version whose blob is
595
- * missing from the store. The write path always writes the blob before flipping
596
- * the head, so this indicates a torn write or external tampering.
597
- */
598
- export class TornStateError extends Error {
599
- override name = 'VerifiedTokens.TornStateError'
600
- constructor(options: { chainId: number; version: string }) {
601
- super(
602
- `verified-token head for chain ${options.chainId} points at missing snapshot version "${options.version}".`,
603
- )
604
- }
605
- }
606
-
607
555
  /** Thrown when a write would introduce a duplicate address on a chain. */
608
556
  export class DuplicateAddressError extends Error {
609
557
  override name = 'VerifiedTokens.DuplicateAddressError'
@@ -3,7 +3,7 @@ import * as WebhookDestination from './WebhookDestination.js'
3
3
  const envelope = {
4
4
  chainId: 4217,
5
5
  createdAt: '2026-01-01T00:00:00.000Z',
6
- data: { amount: '1000', token: '0xabc' },
6
+ data: { amount: '1000', token: `0x${'aa'.repeat(20)}` },
7
7
  id: 'evt_test',
8
8
  subscriptionId: 'wh_test',
9
9
  type: 'token:transfer',