tapimo 0.0.2 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (517) hide show
  1. package/README.md +38 -16
  2. package/dist/ApiKey.d.ts +14 -11
  3. package/dist/ApiKey.d.ts.map +1 -1
  4. package/dist/ApiKey.js +11 -12
  5. package/dist/ApiKey.js.map +1 -1
  6. package/dist/ApiKeys.d.ts +207 -0
  7. package/dist/ApiKeys.d.ts.map +1 -0
  8. package/dist/ApiKeys.js +282 -0
  9. package/dist/ApiKeys.js.map +1 -0
  10. package/dist/App.d.ts +6771 -3819
  11. package/dist/App.d.ts.map +1 -1
  12. package/dist/App.js +145 -317
  13. package/dist/App.js.map +1 -1
  14. package/dist/Handler.d.ts +86 -0
  15. package/dist/Handler.d.ts.map +1 -0
  16. package/dist/Handler.js +83 -0
  17. package/dist/Handler.js.map +1 -0
  18. package/dist/Scope.d.ts +14 -4
  19. package/dist/Scope.d.ts.map +1 -1
  20. package/dist/Scope.js +16 -4
  21. package/dist/Scope.js.map +1 -1
  22. package/dist/Webhooks.d.ts +5 -7
  23. package/dist/Webhooks.d.ts.map +1 -1
  24. package/dist/Webhooks.js +11 -4
  25. package/dist/Webhooks.js.map +1 -1
  26. package/dist/admin/Access.d.ts +1 -3
  27. package/dist/admin/Access.d.ts.map +1 -1
  28. package/dist/admin/Access.js +1 -3
  29. package/dist/admin/Access.js.map +1 -1
  30. package/dist/admin/App.d.ts +167 -205
  31. package/dist/admin/App.d.ts.map +1 -1
  32. package/dist/admin/App.js +2 -4
  33. package/dist/admin/App.js.map +1 -1
  34. package/dist/admin/apps/api-keys.d.ts +105 -5
  35. package/dist/admin/apps/api-keys.d.ts.map +1 -1
  36. package/dist/admin/apps/api-keys.js +75 -9
  37. package/dist/admin/apps/api-keys.js.map +1 -1
  38. package/dist/admin/apps/scopes.d.ts +6 -0
  39. package/dist/admin/apps/scopes.d.ts.map +1 -1
  40. package/dist/admin/apps/verified-tokens.d.ts +35 -149
  41. package/dist/admin/apps/verified-tokens.d.ts.map +1 -1
  42. package/dist/admin/apps/verified-tokens.js +18 -39
  43. package/dist/admin/apps/verified-tokens.js.map +1 -1
  44. package/dist/admin/ui.generated.d.ts +1 -1
  45. package/dist/admin/ui.generated.js +1 -1
  46. package/dist/apps/data/App.d.ts +19176 -0
  47. package/dist/apps/data/App.d.ts.map +1 -0
  48. package/dist/apps/data/App.js +236 -0
  49. package/dist/apps/data/App.js.map +1 -0
  50. package/dist/apps/data/index.d.ts +3 -0
  51. package/dist/apps/data/index.d.ts.map +1 -0
  52. package/dist/apps/data/index.js +3 -0
  53. package/dist/apps/data/index.js.map +1 -0
  54. package/dist/apps/{activities.d.ts → data/routes/activities.d.ts} +32 -32
  55. package/dist/apps/{activities.d.ts.map → data/routes/activities.d.ts.map} +1 -1
  56. package/dist/apps/{activities.js → data/routes/activities.js} +13 -13
  57. package/dist/apps/data/routes/activities.js.map +1 -0
  58. package/dist/apps/{addresses.d.ts → data/routes/addresses.d.ts} +22 -22
  59. package/dist/apps/{addresses.d.ts.map → data/routes/addresses.d.ts.map} +1 -1
  60. package/dist/apps/{addresses.js → data/routes/addresses.js} +5 -5
  61. package/dist/apps/data/routes/addresses.js.map +1 -0
  62. package/dist/apps/{balances.d.ts → data/routes/balances.d.ts} +49 -49
  63. package/dist/apps/data/routes/balances.d.ts.map +1 -0
  64. package/dist/apps/{balances.js → data/routes/balances.js} +42 -11
  65. package/dist/apps/data/routes/balances.js.map +1 -0
  66. package/dist/apps/{blocks.d.ts → data/routes/blocks.d.ts} +47 -47
  67. package/dist/apps/data/routes/blocks.d.ts.map +1 -0
  68. package/dist/apps/{blocks.js → data/routes/blocks.js} +13 -13
  69. package/dist/apps/data/routes/blocks.js.map +1 -0
  70. package/dist/apps/{coingecko.d.ts → data/routes/coingecko.d.ts} +183 -183
  71. package/dist/apps/data/routes/coingecko.d.ts.map +1 -0
  72. package/dist/apps/{coingecko.js → data/routes/coingecko.js} +13 -13
  73. package/dist/apps/data/routes/coingecko.js.map +1 -0
  74. package/dist/apps/{exchanges.d.ts → data/routes/exchanges.d.ts} +460 -460
  75. package/dist/apps/data/routes/exchanges.d.ts.map +1 -0
  76. package/dist/apps/{exchanges.js → data/routes/exchanges.js} +19 -19
  77. package/dist/apps/data/routes/exchanges.js.map +1 -0
  78. package/dist/apps/{fee-amm.d.ts → data/routes/fee-amm.d.ts} +94 -94
  79. package/dist/apps/data/routes/fee-amm.d.ts.map +1 -0
  80. package/dist/apps/{fee-amm.js → data/routes/fee-amm.js} +17 -17
  81. package/dist/apps/data/routes/fee-amm.js.map +1 -0
  82. package/dist/apps/{indexer.d.ts → data/routes/indexer.d.ts} +4 -4
  83. package/dist/apps/data/routes/indexer.d.ts.map +1 -0
  84. package/dist/apps/{indexer.js → data/routes/indexer.js} +13 -9
  85. package/dist/apps/data/routes/indexer.js.map +1 -0
  86. package/dist/apps/{receipts.d.ts → data/routes/receipts.d.ts} +6 -6
  87. package/dist/apps/data/routes/receipts.d.ts.map +1 -0
  88. package/dist/apps/{receipts.js → data/routes/receipts.js} +12 -12
  89. package/dist/apps/data/routes/receipts.js.map +1 -0
  90. package/dist/apps/{rpc.d.ts → data/routes/rpc.d.ts} +4 -4
  91. package/dist/apps/data/routes/rpc.d.ts.map +1 -0
  92. package/dist/apps/{rpc.js → data/routes/rpc.js} +6 -6
  93. package/dist/apps/data/routes/rpc.js.map +1 -0
  94. package/dist/apps/{tokenlist.d.ts → data/routes/tokenlist.d.ts} +4 -4
  95. package/dist/apps/data/routes/tokenlist.d.ts.map +1 -0
  96. package/dist/apps/{tokenlist.js → data/routes/tokenlist.js} +8 -8
  97. package/dist/apps/data/routes/tokenlist.js.map +1 -0
  98. package/dist/apps/{tokens.d.ts → data/routes/tokens.d.ts} +11 -11
  99. package/dist/apps/data/routes/tokens.d.ts.map +1 -0
  100. package/dist/apps/{tokens.js → data/routes/tokens.js} +19 -19
  101. package/dist/apps/data/routes/tokens.js.map +1 -0
  102. package/dist/apps/{transactions.d.ts → data/routes/transactions.d.ts} +288 -288
  103. package/dist/apps/data/routes/transactions.d.ts.map +1 -0
  104. package/dist/apps/{transactions.js → data/routes/transactions.js} +13 -13
  105. package/dist/apps/data/routes/transactions.js.map +1 -0
  106. package/dist/apps/{transfers.d.ts → data/routes/transfers.d.ts} +35 -35
  107. package/dist/apps/data/routes/transfers.d.ts.map +1 -0
  108. package/dist/apps/{transfers.js → data/routes/transfers.js} +13 -13
  109. package/dist/apps/data/routes/transfers.js.map +1 -0
  110. package/dist/apps/{verified-tokens.d.ts → data/routes/verified-tokens.d.ts} +42 -42
  111. package/dist/apps/data/routes/verified-tokens.d.ts.map +1 -0
  112. package/dist/apps/{verified-tokens.js → data/routes/verified-tokens.js} +9 -9
  113. package/dist/apps/data/routes/verified-tokens.js.map +1 -0
  114. package/dist/apps/{webhooks.d.ts → data/routes/webhooks.d.ts} +66 -63
  115. package/dist/apps/{webhooks.d.ts.map → data/routes/webhooks.d.ts.map} +1 -1
  116. package/dist/apps/{webhooks.js → data/routes/webhooks.js} +67 -59
  117. package/dist/apps/data/routes/webhooks.js.map +1 -0
  118. package/dist/apps/docs/App.d.ts +27 -0
  119. package/dist/apps/docs/App.d.ts.map +1 -0
  120. package/dist/apps/docs/App.js +122 -0
  121. package/dist/apps/docs/App.js.map +1 -0
  122. package/dist/{internal/OpenApi.fonts.d.ts → apps/docs/fonts.d.ts} +1 -1
  123. package/dist/apps/docs/fonts.d.ts.map +1 -0
  124. package/dist/{internal/OpenApi.fonts.js → apps/docs/fonts.js} +1 -1
  125. package/dist/apps/docs/fonts.js.map +1 -0
  126. package/dist/apps/docs/index.d.ts +2 -0
  127. package/dist/apps/docs/index.d.ts.map +1 -0
  128. package/dist/apps/docs/index.js +2 -0
  129. package/dist/apps/docs/index.js.map +1 -0
  130. package/dist/{internal/OpenApi.logo.d.ts → apps/docs/logo.d.ts} +1 -1
  131. package/dist/apps/docs/logo.d.ts.map +1 -0
  132. package/dist/{internal/OpenApi.logo.js → apps/docs/logo.js} +1 -1
  133. package/dist/apps/docs/logo.js.map +1 -0
  134. package/dist/apps/index.d.ts +4 -0
  135. package/dist/apps/index.d.ts.map +1 -0
  136. package/dist/apps/index.js +4 -0
  137. package/dist/apps/index.js.map +1 -0
  138. package/dist/apps/metadata.d.ts +7 -0
  139. package/dist/apps/metadata.d.ts.map +1 -0
  140. package/dist/apps/metadata.js +15 -0
  141. package/dist/apps/metadata.js.map +1 -0
  142. package/dist/apps/platform/App.d.ts +2985 -0
  143. package/dist/apps/platform/App.d.ts.map +1 -0
  144. package/dist/apps/platform/App.js +74 -0
  145. package/dist/apps/platform/App.js.map +1 -0
  146. package/dist/apps/platform/index.d.ts +2 -0
  147. package/dist/apps/platform/index.d.ts.map +1 -0
  148. package/dist/apps/platform/index.js +2 -0
  149. package/dist/apps/platform/index.js.map +1 -0
  150. package/dist/apps/platform/routes/api-keys.d.ts +681 -0
  151. package/dist/apps/platform/routes/api-keys.d.ts.map +1 -0
  152. package/dist/apps/platform/routes/api-keys.js +328 -0
  153. package/dist/apps/platform/routes/api-keys.js.map +1 -0
  154. package/dist/apps/platform/routes/invitations.d.ts +733 -0
  155. package/dist/apps/platform/routes/invitations.d.ts.map +1 -0
  156. package/dist/apps/platform/routes/invitations.js +413 -0
  157. package/dist/apps/platform/routes/invitations.js.map +1 -0
  158. package/dist/apps/platform/routes/me.d.ts +95 -0
  159. package/dist/apps/platform/routes/me.d.ts.map +1 -0
  160. package/dist/apps/platform/routes/me.js +81 -0
  161. package/dist/apps/platform/routes/me.js.map +1 -0
  162. package/dist/apps/platform/routes/members.d.ts +554 -0
  163. package/dist/apps/platform/routes/members.d.ts.map +1 -0
  164. package/dist/apps/platform/routes/members.js +251 -0
  165. package/dist/apps/platform/routes/members.js.map +1 -0
  166. package/dist/apps/platform/routes/orgs.d.ts +582 -0
  167. package/dist/apps/platform/routes/orgs.d.ts.map +1 -0
  168. package/dist/apps/platform/routes/orgs.js +265 -0
  169. package/dist/apps/platform/routes/orgs.js.map +1 -0
  170. package/dist/apps/platform/routes/projects.d.ts +740 -0
  171. package/dist/apps/platform/routes/projects.d.ts.map +1 -0
  172. package/dist/apps/platform/routes/projects.js +286 -0
  173. package/dist/apps/platform/routes/projects.js.map +1 -0
  174. package/dist/apps/relay/App.d.ts +41 -0
  175. package/dist/apps/relay/App.d.ts.map +1 -0
  176. package/dist/apps/relay/App.js +103 -0
  177. package/dist/apps/relay/App.js.map +1 -0
  178. package/dist/apps/relay/Sponsorships.d.ts +107 -0
  179. package/dist/apps/relay/Sponsorships.d.ts.map +1 -0
  180. package/dist/apps/relay/Sponsorships.js +193 -0
  181. package/dist/apps/relay/Sponsorships.js.map +1 -0
  182. package/dist/apps/relay/index.d.ts +3 -0
  183. package/dist/apps/relay/index.d.ts.map +1 -0
  184. package/dist/apps/relay/index.js +3 -0
  185. package/dist/apps/relay/index.js.map +1 -0
  186. package/dist/{Cli.d.ts → cli/Cli.d.ts} +13 -2
  187. package/dist/cli/Cli.d.ts.map +1 -0
  188. package/dist/cli/Cli.js +19 -0
  189. package/dist/cli/Cli.js.map +1 -0
  190. package/dist/cli/bin.d.ts +3 -0
  191. package/dist/cli/bin.d.ts.map +1 -0
  192. package/dist/cli/bin.js +4 -0
  193. package/dist/cli/bin.js.map +1 -0
  194. package/dist/cli/commands/admin.d.ts +15 -0
  195. package/dist/cli/commands/admin.d.ts.map +1 -0
  196. package/dist/cli/commands/admin.js +60 -0
  197. package/dist/cli/commands/admin.js.map +1 -0
  198. package/dist/cloudflare.d.ts +7 -0
  199. package/dist/cloudflare.d.ts.map +1 -1
  200. package/dist/cloudflare.js +9 -0
  201. package/dist/cloudflare.js.map +1 -1
  202. package/dist/db/Db.d.ts +113 -0
  203. package/dist/db/Db.d.ts.map +1 -0
  204. package/dist/db/Db.js +402 -0
  205. package/dist/db/Db.js.map +1 -0
  206. package/dist/db/Schema.d.ts +168 -0
  207. package/dist/db/Schema.d.ts.map +1 -0
  208. package/dist/db/Schema.js +229 -0
  209. package/dist/db/Schema.js.map +1 -0
  210. package/dist/db/tables/invitations.d.ts +84 -0
  211. package/dist/db/tables/invitations.d.ts.map +1 -0
  212. package/dist/db/tables/invitations.js +165 -0
  213. package/dist/db/tables/invitations.js.map +1 -0
  214. package/dist/db/tables/memberships.d.ts +108 -0
  215. package/dist/db/tables/memberships.d.ts.map +1 -0
  216. package/dist/db/tables/memberships.js +153 -0
  217. package/dist/db/tables/memberships.js.map +1 -0
  218. package/dist/db/tables/organizations.d.ts +123 -0
  219. package/dist/db/tables/organizations.d.ts.map +1 -0
  220. package/dist/db/tables/organizations.js +170 -0
  221. package/dist/db/tables/organizations.js.map +1 -0
  222. package/dist/db/tables/projects.d.ts +65 -0
  223. package/dist/db/tables/projects.d.ts.map +1 -0
  224. package/dist/db/tables/projects.js +75 -0
  225. package/dist/db/tables/projects.js.map +1 -0
  226. package/dist/db/tables/sponsoredTransactions.d.ts +120 -0
  227. package/dist/db/tables/sponsoredTransactions.d.ts.map +1 -0
  228. package/dist/db/tables/sponsoredTransactions.js +161 -0
  229. package/dist/db/tables/sponsoredTransactions.js.map +1 -0
  230. package/dist/db/tables/users.d.ts +48 -0
  231. package/dist/db/tables/users.d.ts.map +1 -0
  232. package/dist/db/tables/users.js +65 -0
  233. package/dist/db/tables/users.js.map +1 -0
  234. package/dist/db/tables/verifiedTokens.d.ts +53 -0
  235. package/dist/db/tables/verifiedTokens.d.ts.map +1 -0
  236. package/dist/db/tables/verifiedTokens.js +74 -0
  237. package/dist/db/tables/verifiedTokens.js.map +1 -0
  238. package/dist/db/tables/webhookDeliveries.d.ts +71 -0
  239. package/dist/db/tables/webhookDeliveries.d.ts.map +1 -0
  240. package/dist/db/tables/webhookDeliveries.js +119 -0
  241. package/dist/db/tables/webhookDeliveries.js.map +1 -0
  242. package/dist/db/tables/webhookSubscriptions.d.ts +158 -0
  243. package/dist/db/tables/webhookSubscriptions.d.ts.map +1 -0
  244. package/dist/db/tables/webhookSubscriptions.js +272 -0
  245. package/dist/db/tables/webhookSubscriptions.js.map +1 -0
  246. package/dist/handlers/internal/executionError.d.ts +25 -0
  247. package/dist/handlers/internal/executionError.d.ts.map +1 -0
  248. package/dist/handlers/internal/executionError.js +186 -0
  249. package/dist/handlers/internal/executionError.js.map +1 -0
  250. package/dist/handlers/internal/multisig.d.ts +233 -0
  251. package/dist/handlers/internal/multisig.d.ts.map +1 -0
  252. package/dist/handlers/internal/multisig.js +542 -0
  253. package/dist/handlers/internal/multisig.js.map +1 -0
  254. package/dist/handlers/internal/requestListener.d.ts +124 -0
  255. package/dist/handlers/internal/requestListener.d.ts.map +1 -0
  256. package/dist/handlers/internal/requestListener.js +173 -0
  257. package/dist/handlers/internal/requestListener.js.map +1 -0
  258. package/dist/handlers/internal/sponsorship.d.ts +113 -0
  259. package/dist/handlers/internal/sponsorship.d.ts.map +1 -0
  260. package/dist/handlers/internal/sponsorship.js +128 -0
  261. package/dist/handlers/internal/sponsorship.js.map +1 -0
  262. package/dist/handlers/internal/types.d.ts +284 -0
  263. package/dist/handlers/internal/types.d.ts.map +1 -0
  264. package/dist/handlers/internal/types.js +2 -0
  265. package/dist/handlers/internal/types.js.map +1 -0
  266. package/dist/handlers/internal/utils.d.ts +34 -0
  267. package/dist/handlers/internal/utils.d.ts.map +1 -0
  268. package/dist/handlers/internal/utils.js +131 -0
  269. package/dist/handlers/internal/utils.js.map +1 -0
  270. package/dist/handlers/relay.d.ts +123 -0
  271. package/dist/handlers/relay.d.ts.map +1 -0
  272. package/dist/handlers/relay.js +1278 -0
  273. package/dist/handlers/relay.js.map +1 -0
  274. package/dist/index.d.ts +4 -2
  275. package/dist/index.d.ts.map +1 -1
  276. package/dist/index.js +4 -2
  277. package/dist/index.js.map +1 -1
  278. package/dist/internal/Auth.d.ts +224 -16
  279. package/dist/internal/Auth.d.ts.map +1 -1
  280. package/dist/internal/Auth.js +572 -33
  281. package/dist/internal/Auth.js.map +1 -1
  282. package/dist/internal/Log.d.ts +7 -3
  283. package/dist/internal/Log.d.ts.map +1 -1
  284. package/dist/internal/Log.js +4 -0
  285. package/dist/internal/Log.js.map +1 -1
  286. package/dist/internal/OpenApi.d.ts +0 -19
  287. package/dist/internal/OpenApi.d.ts.map +1 -1
  288. package/dist/internal/OpenApi.js +0 -57
  289. package/dist/internal/OpenApi.js.map +1 -1
  290. package/dist/internal/RpcSchema.d.ts +10 -0
  291. package/dist/internal/RpcSchema.d.ts.map +1 -0
  292. package/dist/internal/RpcSchema.js +2 -0
  293. package/dist/internal/RpcSchema.js.map +1 -0
  294. package/dist/internal/Store.d.ts +49 -4
  295. package/dist/internal/Store.d.ts.map +1 -1
  296. package/dist/internal/Store.js +81 -5
  297. package/dist/internal/Store.js.map +1 -1
  298. package/dist/internal/VerifiedTokens.d.ts +15 -34
  299. package/dist/internal/VerifiedTokens.d.ts.map +1 -1
  300. package/dist/internal/VerifiedTokens.js +115 -159
  301. package/dist/internal/VerifiedTokens.js.map +1 -1
  302. package/dist/internal/Viem.d.ts +84 -0
  303. package/dist/internal/Viem.d.ts.map +1 -1
  304. package/dist/internal/Webhooks.d.ts +50 -36
  305. package/dist/internal/Webhooks.d.ts.map +1 -1
  306. package/dist/internal/Webhooks.js +92 -205
  307. package/dist/internal/Webhooks.js.map +1 -1
  308. package/package.json +37 -6
  309. package/src/ApiKey.test.ts +3 -3
  310. package/src/ApiKey.ts +11 -12
  311. package/src/ApiKeys.test.ts +278 -0
  312. package/src/ApiKeys.ts +358 -0
  313. package/src/App.test-d.ts +1 -1
  314. package/src/App.test.ts +40508 -19083
  315. package/src/App.ts +239 -416
  316. package/src/Client.test-d.ts +307 -16
  317. package/src/Handler.ts +154 -0
  318. package/src/Scope.ts +17 -4
  319. package/src/Webhooks.test.ts +8 -7
  320. package/src/Webhooks.ts +13 -7
  321. package/src/admin/Access.ts +1 -3
  322. package/src/admin/App.ts +19 -24
  323. package/src/admin/apps/api-keys.test.ts +70 -18
  324. package/src/admin/apps/api-keys.ts +92 -9
  325. package/src/admin/apps/scopes.test.ts +8 -0
  326. package/src/admin/apps/verified-tokens.test.ts +3 -30
  327. package/src/admin/apps/verified-tokens.ts +18 -37
  328. package/src/admin/ui.generated.ts +1 -1
  329. package/src/apps/composition.test.ts +66 -0
  330. package/src/apps/data/App.ts +295 -0
  331. package/src/apps/data/index.ts +2 -0
  332. package/src/apps/{activities.test.ts → data/routes/activities.test.ts} +3 -3
  333. package/src/apps/{activities.ts → data/routes/activities.ts} +15 -15
  334. package/src/apps/{addresses.ts → data/routes/addresses.ts} +6 -6
  335. package/src/apps/{balances.test.ts → data/routes/balances.test.ts} +6 -5
  336. package/src/apps/{balances.ts → data/routes/balances.ts} +46 -12
  337. package/src/apps/{blocks.test.ts → data/routes/blocks.test.ts} +4 -4
  338. package/src/apps/{blocks.ts → data/routes/blocks.ts} +14 -14
  339. package/src/apps/{coingecko.test.ts → data/routes/coingecko.test.ts} +2 -2
  340. package/src/apps/{coingecko.ts → data/routes/coingecko.ts} +14 -14
  341. package/src/apps/{exchanges.test.ts → data/routes/exchanges.test.ts} +2 -2
  342. package/src/apps/{exchanges.ts → data/routes/exchanges.ts} +20 -20
  343. package/src/apps/{fee-amm.test.ts → data/routes/fee-amm.test.ts} +3 -3
  344. package/src/apps/{fee-amm.ts → data/routes/fee-amm.ts} +18 -18
  345. package/src/apps/{indexer.test.ts → data/routes/indexer.test.ts} +27 -6
  346. package/src/apps/{indexer.ts → data/routes/indexer.ts} +13 -10
  347. package/src/apps/{receipts.test.ts → data/routes/receipts.test.ts} +4 -4
  348. package/src/apps/{receipts.ts → data/routes/receipts.ts} +13 -13
  349. package/src/apps/{rpc.test.ts → data/routes/rpc.test.ts} +142 -13
  350. package/src/apps/{rpc.ts → data/routes/rpc.ts} +7 -7
  351. package/src/apps/{tokenlist.test.ts → data/routes/tokenlist.test.ts} +8 -10
  352. package/src/apps/{tokenlist.ts → data/routes/tokenlist.ts} +9 -9
  353. package/src/apps/{tokens.test.ts → data/routes/tokens.test.ts} +6 -5
  354. package/src/apps/{tokens.ts → data/routes/tokens.ts} +20 -20
  355. package/src/apps/{transactions.test.ts → data/routes/transactions.test.ts} +4 -4
  356. package/src/apps/{transactions.ts → data/routes/transactions.ts} +15 -15
  357. package/src/apps/{transfers.test.ts → data/routes/transfers.test.ts} +3 -3
  358. package/src/apps/{transfers.ts → data/routes/transfers.ts} +15 -15
  359. package/src/apps/{verified-tokens.test.ts → data/routes/verified-tokens.test.ts} +27 -15
  360. package/src/apps/{verified-tokens.ts → data/routes/verified-tokens.ts} +10 -10
  361. package/src/apps/{webhooks.test.ts → data/routes/webhooks.test.ts} +137 -150
  362. package/src/apps/{webhooks.ts → data/routes/webhooks.ts} +83 -81
  363. package/src/apps/docs/App.ts +136 -0
  364. package/src/apps/docs/index.ts +1 -0
  365. package/src/apps/index.ts +3 -0
  366. package/src/apps/metadata.ts +23 -0
  367. package/src/apps/platform/App.ts +130 -0
  368. package/src/apps/platform/index.ts +1 -0
  369. package/src/apps/platform/routes/api-keys.test.ts +330 -0
  370. package/src/apps/platform/routes/api-keys.ts +427 -0
  371. package/src/apps/platform/routes/invitations.test.ts +361 -0
  372. package/src/apps/platform/routes/invitations.ts +519 -0
  373. package/src/apps/platform/routes/me.test.ts +121 -0
  374. package/src/apps/platform/routes/me.ts +106 -0
  375. package/src/apps/platform/routes/members.test.ts +195 -0
  376. package/src/apps/platform/routes/members.ts +313 -0
  377. package/src/apps/platform/routes/orgs.test.ts +313 -0
  378. package/src/apps/platform/routes/orgs.ts +343 -0
  379. package/src/apps/platform/routes/projects.test.ts +181 -0
  380. package/src/apps/platform/routes/projects.ts +367 -0
  381. package/src/apps/relay/App.test.ts +484 -0
  382. package/src/apps/relay/App.ts +128 -0
  383. package/src/apps/relay/Sponsorships.test.ts +375 -0
  384. package/src/apps/relay/Sponsorships.ts +305 -0
  385. package/src/apps/relay/index.ts +2 -0
  386. package/src/{Cli.test.ts → cli/Cli.test.ts} +10 -9
  387. package/src/{Cli.ts → cli/Cli.ts} +16 -9
  388. package/src/cli/bin.ts +4 -0
  389. package/src/cli/commands/admin.test.ts +71 -0
  390. package/src/cli/commands/admin.ts +60 -0
  391. package/src/cloudflare.ts +10 -0
  392. package/src/db/Db.test.ts +84 -0
  393. package/src/db/Db.ts +542 -0
  394. package/src/db/Schema.ts +301 -0
  395. package/src/db/tables/invitations.ts +198 -0
  396. package/src/db/tables/memberships.ts +208 -0
  397. package/src/db/tables/organizations.test.ts +160 -0
  398. package/src/db/tables/organizations.ts +232 -0
  399. package/src/db/tables/projects.ts +107 -0
  400. package/src/db/tables/sponsoredTransactions.test.ts +218 -0
  401. package/src/db/tables/sponsoredTransactions.ts +236 -0
  402. package/src/db/tables/users.ts +85 -0
  403. package/src/db/tables/verifiedTokens.ts +111 -0
  404. package/src/db/tables/webhookDeliveries.ts +159 -0
  405. package/src/db/tables/webhookSubscriptions.ts +358 -0
  406. package/src/handlers/internal/executionError.ts +207 -0
  407. package/src/handlers/internal/multisig.test.ts +818 -0
  408. package/src/handlers/internal/multisig.ts +823 -0
  409. package/src/handlers/internal/requestListener.ts +273 -0
  410. package/src/handlers/internal/sponsorship.ts +245 -0
  411. package/src/handlers/internal/types.ts +378 -0
  412. package/src/handlers/internal/utils.ts +153 -0
  413. package/src/handlers/relay.test.ts +2035 -0
  414. package/src/handlers/relay.ts +1623 -0
  415. package/src/index.ts +4 -2
  416. package/src/internal/Auth.test.ts +337 -21
  417. package/src/internal/Auth.ts +783 -44
  418. package/src/internal/Cursor.test.ts +3 -2
  419. package/src/internal/Log.test.ts +1 -1
  420. package/src/internal/Log.ts +11 -3
  421. package/src/internal/MetricSink.ts +1 -1
  422. package/src/internal/OpenApi.ts +0 -59
  423. package/src/internal/RateLimit.test.ts +1 -1
  424. package/src/internal/RpcSchema.ts +10 -0
  425. package/src/internal/Store.test.ts +150 -10
  426. package/src/internal/Store.ts +136 -11
  427. package/src/internal/Tidx.local.test.ts +1 -1
  428. package/src/internal/VerifiedTokens.test.ts +99 -115
  429. package/src/internal/VerifiedTokens.ts +123 -175
  430. package/src/internal/WebhookDestination.test.ts +1 -1
  431. package/src/internal/Webhooks.test.ts +111 -111
  432. package/src/internal/Webhooks.ts +103 -221
  433. package/dist/ApiKeySource.d.ts +0 -166
  434. package/dist/ApiKeySource.d.ts.map +0 -1
  435. package/dist/ApiKeySource.js +0 -234
  436. package/dist/ApiKeySource.js.map +0 -1
  437. package/dist/Cli.d.ts.map +0 -1
  438. package/dist/Cli.js +0 -13
  439. package/dist/Cli.js.map +0 -1
  440. package/dist/apps/activities.js.map +0 -1
  441. package/dist/apps/addresses.js.map +0 -1
  442. package/dist/apps/balances.d.ts.map +0 -1
  443. package/dist/apps/balances.js.map +0 -1
  444. package/dist/apps/blocks.d.ts.map +0 -1
  445. package/dist/apps/blocks.js.map +0 -1
  446. package/dist/apps/coingecko.d.ts.map +0 -1
  447. package/dist/apps/coingecko.js.map +0 -1
  448. package/dist/apps/exchanges.d.ts.map +0 -1
  449. package/dist/apps/exchanges.js.map +0 -1
  450. package/dist/apps/fee-amm.d.ts.map +0 -1
  451. package/dist/apps/fee-amm.js.map +0 -1
  452. package/dist/apps/indexer.d.ts.map +0 -1
  453. package/dist/apps/indexer.js.map +0 -1
  454. package/dist/apps/receipts.d.ts.map +0 -1
  455. package/dist/apps/receipts.js.map +0 -1
  456. package/dist/apps/rpc.d.ts.map +0 -1
  457. package/dist/apps/rpc.js.map +0 -1
  458. package/dist/apps/tokenlist.d.ts.map +0 -1
  459. package/dist/apps/tokenlist.js.map +0 -1
  460. package/dist/apps/tokens.d.ts.map +0 -1
  461. package/dist/apps/tokens.js.map +0 -1
  462. package/dist/apps/transactions.d.ts.map +0 -1
  463. package/dist/apps/transactions.js.map +0 -1
  464. package/dist/apps/transfers.d.ts.map +0 -1
  465. package/dist/apps/transfers.js.map +0 -1
  466. package/dist/apps/verified-tokens.d.ts.map +0 -1
  467. package/dist/apps/verified-tokens.js.map +0 -1
  468. package/dist/apps/webhooks.js.map +0 -1
  469. package/dist/internal/OpenApi.fonts.d.ts.map +0 -1
  470. package/dist/internal/OpenApi.fonts.js.map +0 -1
  471. package/dist/internal/OpenApi.logo.d.ts.map +0 -1
  472. package/dist/internal/OpenApi.logo.js.map +0 -1
  473. package/seeds/31318/icons/0x20c0000000000000000000000000000000000000.svg +0 -1
  474. package/seeds/31318/icons/0x20c0000000000000000000000000000000000001.svg +0 -1
  475. package/seeds/31318/icons/0x20c0000000000000000000000000000000000002.svg +0 -1
  476. package/seeds/31318/icons/0x20c0000000000000000000000000000000000003.svg +0 -1
  477. package/seeds/31318/verified-tokens.json +0 -30
  478. package/seeds/4217/icons/0x20c0000000000000000000000000000000000000.svg +0 -25
  479. package/seeds/4217/icons/0x20c000000000000000000000048c8f36df1c9a4a.svg +0 -1
  480. package/seeds/4217/icons/0x20c0000000000000000000000520792dcccccccc.svg +0 -1
  481. package/seeds/4217/icons/0x20c0000000000000000000000a6da882d075a4c3.svg +0 -4
  482. package/seeds/4217/icons/0x20c000000000000000000000111111111e910f0f.svg +0 -30
  483. package/seeds/4217/icons/0x20c00000000000000000000014f22ca97301eb73.svg +0 -1
  484. package/seeds/4217/icons/0x20c0000000000000000000001621e21f71cf12fb.svg +0 -1
  485. package/seeds/4217/icons/0x20c0000000000000000000002f52d5cc21a3207b.svg +0 -1
  486. package/seeds/4217/icons/0x20c0000000000000000000003158081efd85bfc2.svg +0 -11
  487. package/seeds/4217/icons/0x20c0000000000000000000003554d28269e0f3c2.svg +0 -1
  488. package/seeds/4217/icons/0x20c000000000000000000000383a23bacb546ab9.svg +0 -1
  489. package/seeds/4217/icons/0x20c00000000000000000000042109aef2f8b28e1.png +0 -0
  490. package/seeds/4217/icons/0x20c0000000000000000000005c0bac7cef389a11.svg +0 -1
  491. package/seeds/4217/icons/0x20c0000000000000000000006fd9a167923ba194.png +0 -0
  492. package/seeds/4217/icons/0x20c0000000000000000000007f7ba549dd0251b9.svg +0 -1
  493. package/seeds/4217/icons/0x20c0000000000000000000008191667423f70e67.svg +0 -5
  494. package/seeds/4217/icons/0x20c0000000000000000000008ee4fcff88888888.svg +0 -1
  495. package/seeds/4217/icons/0x20c0000000000000000000009a4a4b17e0dc6651.svg +0 -1
  496. package/seeds/4217/icons/0x20c000000000000000000000ab02d39df30bd17e.svg +0 -1
  497. package/seeds/4217/icons/0x20c000000000000000000000ae247a1130450f09.svg +0 -1
  498. package/seeds/4217/icons/0x20c000000000000000000000aeed2ec36a54d0e5.svg +0 -1
  499. package/seeds/4217/icons/0x20c000000000000000000000b9537d11c60e8b50.svg +0 -1
  500. package/seeds/4217/icons/0x20c000000000000000000000bd95bfb69fbe6ce3.svg +0 -1
  501. package/seeds/4217/icons/0x20c000000000000000000000c412ec89d0c08be5.svg +0 -1
  502. package/seeds/4217/icons/0x20c000000000000000000000f047dd7018e50367.png +0 -0
  503. package/seeds/4217/verified-tokens.json +0 -177
  504. package/seeds/42431/icons/0x20c0000000000000000000000000000000000000.svg +0 -25
  505. package/seeds/42431/icons/0x20c0000000000000000000000000000000000001.svg +0 -1
  506. package/seeds/42431/icons/0x20c0000000000000000000000000000000000002.svg +0 -1
  507. package/seeds/42431/icons/0x20c0000000000000000000000000000000000003.svg +0 -1
  508. package/seeds/42431/icons/0x20c0000000000000000000009e8d7eb59b783726.svg +0 -1
  509. package/seeds/42431/icons/0x20c000000000000000000000d72572838bbee59c.svg +0 -1
  510. package/seeds/42431/verified-tokens.json +0 -44
  511. package/seeds/openrpc/README.md +0 -27
  512. package/seeds/openrpc/execution-apis.json +0 -8989
  513. package/src/ApiKeySource.test-d.ts +0 -11
  514. package/src/ApiKeySource.test.ts +0 -295
  515. package/src/ApiKeySource.ts +0 -303
  516. /package/src/{internal/OpenApi.fonts.ts → apps/docs/fonts.ts} +0 -0
  517. /package/src/{internal/OpenApi.logo.ts → apps/docs/logo.ts} +0 -0
@@ -0,0 +1,823 @@
1
+ import { Hex, Json, RpcResponse, Signature } from 'ox'
2
+ import { MultisigConfig, SignatureEnvelope, TxEnvelopeTempo } from 'ox/tempo'
3
+ import type { Address, Client } from 'viem'
4
+ import type { LocalAccount } from 'viem/accounts'
5
+ import { Transaction } from 'viem/tempo'
6
+
7
+ import * as core_Store from '../../internal/Store.js'
8
+ import * as Sponsorship from './sponsorship.js'
9
+ import * as Utils from './utils.js'
10
+
11
+ /** Default submission-claim TTL in milliseconds. */
12
+ export const defaultClaimTtl = 30_000
13
+
14
+ /** Returns whether a raw transaction carries a native multisig signature. */
15
+ export function isMultisigTransaction(serialized: Hex.Hex) {
16
+ if (!Utils.isSerializedTempoTransaction(serialized)) return false
17
+ try {
18
+ const transaction = Transaction.deserialize(serialized as never)
19
+ return isMultisigSignature((transaction as { signature?: unknown }).signature)
20
+ } catch {
21
+ return false
22
+ }
23
+ }
24
+
25
+ /** Handles a native multisig raw transaction submission. */
26
+ export async function handleRawTransaction(
27
+ options: handleRawTransaction.Options,
28
+ ): Promise<handleRawTransaction.ReturnType> {
29
+ const result = await collect(options)
30
+ if (result.status.status === 'pending' || result.status.status === 'submitting')
31
+ return result.status.operation.id
32
+ if (result.status.status === 'submitted')
33
+ return result.status.operation.submittedHash ?? result.status.operation.id
34
+ if (options.method === 'eth_sendRawTransactionSync') return result.broadcastResult
35
+ return result.status.operation.submittedHash!
36
+ }
37
+
38
+ export declare namespace handleRawTransaction {
39
+ /** Options for handling a raw multisig transaction submission. */
40
+ type Options = collect.Options
41
+
42
+ /** Raw transaction handler return value. */
43
+ // oxlint-disable-next-line typescript/no-redundant-type-constituents
44
+ type ReturnType = Hex.Hex | unknown
45
+ }
46
+
47
+ async function collect(options: collect.Options): Promise<collect.ReturnType> {
48
+ const {
49
+ claimTtl = defaultClaimTtl,
50
+ finalize = 'sync',
51
+ getClient,
52
+ method,
53
+ request,
54
+ resolveConfig,
55
+ sponsor,
56
+ store,
57
+ } = options
58
+ const serialized = request.params?.[0]
59
+ if (!Utils.isSerializedTempoTransaction(serialized))
60
+ throw new RpcResponse.InvalidParamsError({
61
+ message: 'Only Tempo (0x76/0x78) transactions are supported.',
62
+ })
63
+
64
+ const input = parse(serialized)
65
+ const pending = await store.get(input.id)
66
+ const config = await resolveValidatedConfig({
67
+ account: input.account,
68
+ chainId: input.chainId,
69
+ init: input.init,
70
+ pending,
71
+ resolveConfig,
72
+ })
73
+ if (!config)
74
+ throw new RpcResponse.InvalidParamsError({
75
+ message:
76
+ 'Multisig config is required to collect approvals. Provide it in the bootstrap transaction or configure `multisig.resolveConfig`.',
77
+ })
78
+ const initConfig = resolveInitConfig({
79
+ config,
80
+ init: input.init,
81
+ nonce: input.nonce,
82
+ pending,
83
+ })
84
+
85
+ const now = Date.now()
86
+ let operation: Operation = {
87
+ account: input.account,
88
+ chainId: input.chainId,
89
+ claimExpiresAt: pending?.claimExpiresAt,
90
+ config,
91
+ createdAt: pending?.createdAt ?? now,
92
+ id: input.id,
93
+ init: pending?.init || !!initConfig,
94
+ initConfig,
95
+ payload: input.payload,
96
+ signatures: mergeSignatures([...(pending?.signatures ?? []), ...input.signatures]),
97
+ status: pending?.status === 'submitted' ? 'submitted' : 'pending',
98
+ submittedHash: pending?.submittedHash,
99
+ transaction: serialized as Hex.Hex,
100
+ updatedAt: now,
101
+ }
102
+
103
+ let approvals = getApprovals({
104
+ account: input.account,
105
+ config,
106
+ payload: input.payload,
107
+ signatures: operation.signatures,
108
+ })
109
+ if (operation.status === 'submitted')
110
+ return {
111
+ broadcastResult: operation.submittedHash,
112
+ status: { operation, status: 'submitted' },
113
+ }
114
+
115
+ if (approvals.weight < approvals.threshold) {
116
+ operation = await store.savePending(operation)
117
+ approvals = getApprovals({
118
+ account: operation.account,
119
+ config,
120
+ payload: operation.payload,
121
+ signatures: operation.signatures,
122
+ })
123
+ if (approvals.weight < approvals.threshold)
124
+ return { status: { operation, status: operation.status } }
125
+ }
126
+
127
+ const claim = await store.claimSubmission(operation, { ttl: claimTtl })
128
+ if (claim.status !== 'claimed') return { status: claim }
129
+
130
+ operation = claim.operation
131
+ approvals = getApprovals({
132
+ account: operation.account,
133
+ config,
134
+ payload: operation.payload,
135
+ signatures: operation.signatures,
136
+ })
137
+ const client = getClient(operation.chainId)
138
+ const final = await serializeFinal({
139
+ account: operation.account,
140
+ init: operation.initConfig ?? initConfig,
141
+ signatures: approvals.signatures,
142
+ transaction: input.transaction,
143
+ })
144
+ const broadcastMethod =
145
+ method === 'eth_sendRawTransaction' && finalize === 'sync'
146
+ ? 'eth_sendRawTransactionSync'
147
+ : method
148
+ const feePayerState = (() => {
149
+ try {
150
+ const transaction = Transaction.deserialize(final as never) as Record<string, unknown>
151
+ // No fee-payer field means finalized transaction does not request sponsorship.
152
+ if (!('feePayerSignature' in transaction)) return {}
153
+ // Preserve fee-token/signature marker for sponsorship decision below.
154
+ return {
155
+ feeToken:
156
+ typeof transaction['feeToken'] === 'string'
157
+ ? (transaction['feeToken'] as Address)
158
+ : undefined,
159
+ signature: transaction['feePayerSignature'],
160
+ }
161
+ } catch {
162
+ // Decode failure falls back to direct broadcast.
163
+ return {}
164
+ }
165
+ })()
166
+ const sponsorFeeToken = await (async () => {
167
+ // No sponsor configured, so finalized multisig transaction broadcasts as-is.
168
+ if (!sponsor) return undefined
169
+ // Already fee-payer signed transactions must not be rewritten by this relay.
170
+ if (feePayerState.signature !== null) return undefined
171
+ // Explicit relay fee token wins when the transaction requests sponsorship.
172
+ if (sponsor.feeToken) return sponsor.feeToken
173
+ // `null` requests relay-added fee-payer signature.
174
+ return await sponsor.resolveFeeToken?.(operation.chainId)
175
+ })()
176
+ const shouldSponsor = (() => {
177
+ // No sponsor configured, so no sponsorship path to take.
178
+ if (!sponsor) return false
179
+ // `null` requests relay-added fee-payer signature.
180
+ if (feePayerState.signature === null) return true
181
+ // Missing or already-present fee-payer signatures broadcast unchanged.
182
+ return false
183
+ })()
184
+ const result = await (async () => {
185
+ // Sponsorship enabled, so sponsor adds/signs fee-payer fields.
186
+ if (shouldSponsor && sponsor)
187
+ return await Sponsorship.handleRawTransaction({
188
+ account: sponsor.account,
189
+ feeToken: sponsorFeeToken,
190
+ getFeeToken: sponsor.resolveFeeToken
191
+ ? async (chainId) => await sponsor.resolveFeeToken?.(chainId)
192
+ : undefined,
193
+ getClient,
194
+ method: broadcastMethod,
195
+ onSponsored: sponsor.onSponsored,
196
+ request: { params: [final] },
197
+ sender: operation.account,
198
+ validate: sponsor.validate,
199
+ })
200
+ // Otherwise, multisig transaction is final and can broadcast directly.
201
+ return await client.request({
202
+ method: broadcastMethod,
203
+ params: [final],
204
+ } as never)
205
+ })()
206
+ const submittedHash = (() => {
207
+ if (typeof result === 'string') return result as Hex.Hex
208
+ if (result && typeof result === 'object' && 'transactionHash' in result) {
209
+ const response = result as { transactionHash?: unknown }
210
+ if (typeof response.transactionHash === 'string') return response.transactionHash as Hex.Hex
211
+ }
212
+ throw new Error('Expected transaction hash in multisig broadcast result.')
213
+ })()
214
+ const submitted = await store.setSubmitted(operation.id, submittedHash)
215
+
216
+ return {
217
+ broadcastResult: result,
218
+ status: { operation: submitted, status: 'claimed' },
219
+ }
220
+ }
221
+
222
+ /** Resolves a multisig operation id for standard transaction lookup methods. */
223
+ export async function handleGetTransaction(
224
+ options: handleGetTransaction.Options,
225
+ ): Promise<handleGetTransaction.ReturnType> {
226
+ const id = options.request.params?.[0]
227
+ if (typeof id !== 'string') return undefined
228
+
229
+ const operation = await options.store.get(id as Hex.Hex)
230
+ if (!operation) return undefined
231
+ if (operation.status !== 'submitted' || !operation.submittedHash) return { result: null }
232
+
233
+ const result = await options.getClient(operation.chainId).request({
234
+ method: options.method,
235
+ params: [operation.submittedHash],
236
+ } as never)
237
+ return { result }
238
+ }
239
+
240
+ export declare namespace handleGetTransaction {
241
+ /** Options for resolving a multisig operation id through transaction lookup methods. */
242
+ type Options = {
243
+ /** Client resolver keyed by transaction `chainId`. */
244
+ getClient: (chainId?: number) => Client
245
+ /** Standard transaction lookup method to handle. */
246
+ method: 'eth_getTransactionByHash' | 'eth_getTransactionReceipt'
247
+ /** Incoming JSON-RPC request. */
248
+ request: { params?: readonly unknown[] | undefined }
249
+ /** Pending multisig operation store. */
250
+ store: Store
251
+ }
252
+
253
+ /** Transaction lookup result wrapper. */
254
+ type ReturnType = { result: unknown } | undefined
255
+ }
256
+
257
+ declare namespace collect {
258
+ type Options = {
259
+ /** Submission claim TTL in milliseconds. @default 30000 */
260
+ claimTtl?: number | undefined
261
+ /** How to broadcast once quorum is met. @default 'sync' */
262
+ finalize?: 'submitted' | 'sync' | undefined
263
+ /** Client resolver keyed by transaction `chainId`. */
264
+ getClient: (chainId?: number) => Client
265
+ /** Raw transaction method to handle. */
266
+ method: 'eth_sendRawTransaction' | 'eth_sendRawTransactionSync'
267
+ /** Incoming JSON-RPC request. */
268
+ request: { params?: readonly unknown[] | undefined }
269
+ /** Resolves the genesis multisig config for quorum checks. */
270
+ resolveConfig?: ResolveConfig | undefined
271
+ /** Optional fee payer used to sponsor finalized multisig transactions. */
272
+ sponsor?: Sponsor | undefined
273
+ /** Pending multisig operation store. */
274
+ store: Store
275
+ }
276
+
277
+ type ReturnType = {
278
+ /** Raw broadcast result once quorum is met and this caller claimed submission. */
279
+ broadcastResult?: unknown
280
+ /** Structured operation claim status. */
281
+ status: ClaimSubmissionResult | { operation: Operation; status: 'claimed' }
282
+ }
283
+ }
284
+
285
+ /** Returns a stored native multisig operation status. */
286
+ export async function getStatus(options: getStatus.Options): Promise<Status | null> {
287
+ const operation = await options.store.get(options.id)
288
+ if (!operation) return null
289
+ const config = await resolveValidatedConfig({
290
+ account: operation.account,
291
+ chainId: operation.chainId,
292
+ pending: operation,
293
+ resolveConfig: options.resolveConfig,
294
+ })
295
+ if (!config)
296
+ return {
297
+ account: operation.account,
298
+ chainId: operation.chainId,
299
+ id: operation.id,
300
+ signatures: operation.signatures.length,
301
+ status: operation.status,
302
+ submittedHash: operation.submittedHash,
303
+ }
304
+ const approvals = getApprovals({
305
+ account: operation.account,
306
+ config,
307
+ payload: operation.payload,
308
+ signatures: operation.signatures,
309
+ })
310
+ return toStatus({ approvals, operation })
311
+ }
312
+
313
+ export declare namespace getStatus {
314
+ /** Options for reading one multisig operation status. */
315
+ type Options = {
316
+ /** Operation id returned by a pending multisig submission. */
317
+ id: Hex.Hex
318
+ /** Resolves the genesis multisig config for quorum status. */
319
+ resolveConfig?: ResolveConfig | undefined
320
+ /** Pending multisig operation store. */
321
+ store: Store
322
+ }
323
+ }
324
+
325
+ /** Returns pending native multisig operation statuses for an account. */
326
+ export async function listStatuses(options: listStatuses.Options): Promise<readonly Status[]> {
327
+ const operations = await options.store.listPendingByAddress(options.account)
328
+ return await Promise.all(
329
+ operations.map(async (operation) => {
330
+ const config = await resolveValidatedConfig({
331
+ account: operation.account,
332
+ chainId: operation.chainId,
333
+ pending: operation,
334
+ resolveConfig: options.resolveConfig,
335
+ })
336
+ if (!config)
337
+ return {
338
+ account: operation.account,
339
+ chainId: operation.chainId,
340
+ id: operation.id,
341
+ signatures: operation.signatures.length,
342
+ status: operation.status,
343
+ submittedHash: operation.submittedHash,
344
+ }
345
+ const approvals = getApprovals({
346
+ account: operation.account,
347
+ config,
348
+ payload: operation.payload,
349
+ signatures: operation.signatures,
350
+ })
351
+ return toStatus({ approvals, operation })
352
+ }),
353
+ )
354
+ }
355
+
356
+ export declare namespace listStatuses {
357
+ /** Options for listing multisig operation statuses. */
358
+ type Options = {
359
+ /** Native multisig account address. */
360
+ account: Address
361
+ /** Resolves the genesis multisig config for quorum status. */
362
+ resolveConfig?: ResolveConfig | undefined
363
+ /** Pending multisig operation store. */
364
+ store: Store
365
+ }
366
+ }
367
+
368
+ /**
369
+ * Creates a multisig operation store backed by a Tempo API state store
370
+ * (`Store.memory()`, a static-name Durable Object store, …).
371
+ *
372
+ * Approval merges and submission claims go through `Store.update`, so the
373
+ * backing store needs the atomic `swap` compare-and-swap to serialize
374
+ * concurrent writers (the get + put fallback is dev-only). It must also be
375
+ * enumerable — `listPendingByAddress` scans a key prefix — so sharded Durable
376
+ * Object stores and caches do not qualify.
377
+ */
378
+ export function fromStore(state: core_Store.State): Store {
379
+ const key = (id: Hex.Hex) => `multisig:op:${id.toLowerCase()}`
380
+ const read = (raw: null | string) => (raw ? (Json.parse(raw) as Operation) : undefined)
381
+
382
+ return {
383
+ async claimSubmission(operation, options) {
384
+ let result: ClaimSubmissionResult | undefined
385
+ await core_Store.update(state, key(operation.id), (raw) => {
386
+ const now = Date.now()
387
+ const existing = read(raw)
388
+ if (existing?.status === 'submitted') {
389
+ result = { operation: existing, status: 'submitted' }
390
+ return raw as string
391
+ }
392
+ if (existing?.status === 'submitting' && (existing.claimExpiresAt ?? 0) > now) {
393
+ result = { operation: existing, status: 'submitting' }
394
+ return raw as string
395
+ }
396
+ const claimed = mergeOperation(existing, operation, {
397
+ claimExpiresAt: now + options.ttl,
398
+ status: 'submitting',
399
+ updatedAt: now,
400
+ })
401
+ result = { operation: claimed, status: 'claimed' }
402
+ return Json.stringify(claimed)
403
+ })
404
+ return result as ClaimSubmissionResult
405
+ },
406
+ async get(id) {
407
+ return read(await state.get(key(id)))
408
+ },
409
+ async listPendingByAddress(address) {
410
+ const { keys } = await state.list({ prefix: 'multisig:op:' })
411
+ const operations = await Promise.all(keys.map(({ name }) => state.get(name)))
412
+ return operations
413
+ .map(read)
414
+ .filter((operation) => operation !== undefined)
415
+ .filter(
416
+ (operation) =>
417
+ operation.account.toLowerCase() === address.toLowerCase() &&
418
+ operation.status !== 'submitted',
419
+ )
420
+ },
421
+ async savePending(operation) {
422
+ let saved: Operation | undefined
423
+ await core_Store.update(state, key(operation.id), (raw) => {
424
+ const now = Date.now()
425
+ const existing = read(raw)
426
+ if (existing?.status === 'submitted') {
427
+ saved = existing
428
+ return raw as string
429
+ }
430
+ saved = mergeOperation(existing, operation, {
431
+ status:
432
+ existing?.status === 'submitting' && (existing.claimExpiresAt ?? 0) > now
433
+ ? 'submitting'
434
+ : 'pending',
435
+ updatedAt: now,
436
+ })
437
+ return Json.stringify(saved)
438
+ })
439
+ return saved as Operation
440
+ },
441
+ async setSubmitted(id, submittedHash) {
442
+ let submitted: Operation | undefined
443
+ await core_Store.update(state, key(id), (raw) => {
444
+ const existing = read(raw)
445
+ if (!existing) throw new Error('Cannot mark an unknown multisig operation submitted.')
446
+ submitted = {
447
+ ...existing,
448
+ claimExpiresAt: undefined,
449
+ status: 'submitted',
450
+ submittedHash,
451
+ updatedAt: Date.now(),
452
+ } satisfies Operation
453
+ return Json.stringify(submitted)
454
+ })
455
+ return submitted as Operation
456
+ },
457
+ }
458
+ }
459
+
460
+ /** Creates an in-memory multisig operation store for development and tests only. */
461
+ export function memoryStore(): Store {
462
+ return fromStore(core_Store.memory())
463
+ }
464
+
465
+ /** Native multisig relay options. */
466
+ export type Options = {
467
+ /** Submission claim TTL in milliseconds. @default 30000 */
468
+ claimTtl?: number | undefined
469
+ /** How to broadcast once quorum is met. @default 'sync' */
470
+ finalize?: 'submitted' | 'sync' | undefined
471
+ /** Resolves the genesis multisig config for quorum checks. */
472
+ resolveConfig?: ResolveConfig | undefined
473
+ /**
474
+ * State store holding pending multisig operations. Needs the store's atomic
475
+ * `swap` for correctness (approval merges and submission claims serialize
476
+ * through it) and must be enumerable, so sharded Durable Object stores and
477
+ * caches do not qualify.
478
+ */
479
+ store: core_Store.State
480
+ }
481
+
482
+ /** Resolves the genesis multisig config for quorum checks. */
483
+ export type ResolveConfig = (request: {
484
+ /** Native multisig account address. */
485
+ account: Address
486
+ /** Transaction chain id. */
487
+ chainId: number
488
+ /** Bootstrap config carried by the transaction, when present. */
489
+ init?: MultisigConfig.Config | undefined
490
+ }) => MultisigConfig.Config | Promise<MultisigConfig.Config | undefined> | undefined
491
+
492
+ /** Optional fee payer used to sponsor finalized multisig transactions. */
493
+ export type Sponsor = {
494
+ /** Account used as the fee payer. */
495
+ account: LocalAccount
496
+ /** Fee token to set before fee payer signing. */
497
+ feeToken?: Address | undefined
498
+ /** Called once the fee payer has signed, before any broadcast. */
499
+ onSponsored?: Sponsorship.handleRawTransaction.Options['onSponsored']
500
+ /** Resolves the default fee token for raw sponsorship. */
501
+ resolveFeeToken?:
502
+ | ((chainId: number) => Address | Promise<Address | undefined> | undefined)
503
+ | undefined
504
+ /** Optional sponsorship approval callback. */
505
+ validate?: Sponsorship.handleRawTransaction.Options['validate']
506
+ }
507
+
508
+ /** Storage for native multisig operation approvals and submission claims. */
509
+ export type Store = {
510
+ /** Atomically claims submission for a quorum-ready operation. Only a `claimed` result may broadcast. */
511
+ claimSubmission: (
512
+ operation: Operation,
513
+ options: claimSubmission.Options,
514
+ ) => Promise<ClaimSubmissionResult>
515
+ /** Reads a stored operation. */
516
+ get: (id: Hex.Hex) => Promise<Operation | undefined>
517
+ /** Lists non-submitted operations for a native multisig account address. */
518
+ listPendingByAddress: (address: Address) => Promise<readonly Operation[]>
519
+ /** Saves a pending operation, preserving already-stored approvals. */
520
+ savePending: (operation: Operation) => Promise<Operation>
521
+ /** Marks a claimed operation submitted with its real transaction hash. */
522
+ setSubmitted: (id: Hex.Hex, submittedHash: Hex.Hex) => Promise<Operation>
523
+ }
524
+
525
+ /** `Store.claimSubmission` types. */
526
+ export declare namespace claimSubmission {
527
+ /** Options for claiming submission. */
528
+ type Options = {
529
+ /** Claim TTL in milliseconds. */
530
+ ttl: number
531
+ }
532
+ }
533
+
534
+ /** Result of atomically claiming a multisig operation for submission. */
535
+ export type ClaimSubmissionResult =
536
+ | {
537
+ /** Operation this caller may broadcast. */
538
+ operation: Operation
539
+ /** Claim status. */
540
+ status: 'claimed'
541
+ }
542
+ | {
543
+ /** Current stored operation. */
544
+ operation: Operation
545
+ /** Current non-claimed status. */
546
+ status: 'pending' | 'submitting' | 'submitted'
547
+ }
548
+
549
+ /** Stored native multisig operation. */
550
+ export type Operation = {
551
+ /** Native multisig account address. */
552
+ account: Address
553
+ /** Transaction chain id. */
554
+ chainId: number
555
+ /** Submission claim expiry timestamp in milliseconds. */
556
+ claimExpiresAt?: number | undefined
557
+ /** Resolved genesis config used for approval checks. */
558
+ config?: MultisigConfig.Config | undefined
559
+ /** Creation timestamp in milliseconds. */
560
+ createdAt: number
561
+ /** Deterministic operation id. */
562
+ id: Hex.Hex
563
+ /** Whether the finalized transaction must carry the genesis init config. */
564
+ init?: boolean | undefined
565
+ /** Genesis init config to attach when finalizing a bootstrap transaction. */
566
+ initConfig?: MultisigConfig.Config | undefined
567
+ /** Unsigned Tempo transaction sign payload. */
568
+ payload: Hex.Hex
569
+ /** Collected owner approval signatures. */
570
+ signatures: readonly Hex.Hex[]
571
+ /** Operation state. */
572
+ status: 'pending' | 'submitting' | 'submitted'
573
+ /** Transaction hash once submitted. */
574
+ submittedHash?: Hex.Hex | undefined
575
+ /** Last submitted serialized transaction carrying this operation. */
576
+ transaction: Hex.Hex
577
+ /** Last update timestamp in milliseconds. */
578
+ updatedAt: number
579
+ }
580
+
581
+ /** Native multisig operation status. */
582
+ export type Status = {
583
+ /** Native multisig account address. */
584
+ account: Address
585
+ /** Transaction chain id. */
586
+ chainId: number
587
+ /** Deterministic operation id. */
588
+ id: Hex.Hex
589
+ /** Number of collected owner approvals. */
590
+ signatures: number
591
+ /** Operation state. */
592
+ status: Operation['status']
593
+ /** Submitted transaction hash. */
594
+ submittedHash?: Hex.Hex | undefined
595
+ /** Required owner weight. */
596
+ threshold?: number | undefined
597
+ /** Collected owner weight. */
598
+ weight?: number | undefined
599
+ }
600
+
601
+ function parse(serialized: Hex.Hex) {
602
+ const transaction = Transaction.deserialize(serialized as never) as Record<string, unknown>
603
+ const signature = transaction['signature']
604
+ if (!isMultisigSignature(signature))
605
+ throw new RpcResponse.InvalidParamsError({
606
+ message: 'Transaction does not contain a native multisig signature.',
607
+ })
608
+
609
+ const { signature: _, ...unsigned } = transaction
610
+ const payload = TxEnvelopeTempo.getSignPayload(TxEnvelopeTempo.from(unsigned as never))
611
+ const chainId = Number(transaction['chainId'])
612
+ const id = MultisigConfig.getSignPayload({
613
+ account: signature.account,
614
+ payload,
615
+ })
616
+ const init = signature.init ? MultisigConfig.from(signature.init) : undefined
617
+ const nonce = typeof transaction['nonce'] === 'number' ? transaction['nonce'] : undefined
618
+
619
+ return {
620
+ account: signature.account,
621
+ chainId,
622
+ id,
623
+ init,
624
+ nonce,
625
+ payload,
626
+ signatures: signature.signatures.map((value) => SignatureEnvelope.serialize(value)),
627
+ transaction,
628
+ }
629
+ }
630
+
631
+ function isMultisigSignature(value: unknown): value is SignatureEnvelope.Multisig {
632
+ return (
633
+ typeof value === 'object' &&
634
+ value !== null &&
635
+ (value as { type?: unknown }).type === 'multisig' &&
636
+ typeof (value as { account?: unknown }).account === 'string' &&
637
+ Array.isArray((value as { signatures?: unknown }).signatures)
638
+ )
639
+ }
640
+
641
+ async function resolveValidatedConfig(options: {
642
+ account: Address
643
+ chainId: number
644
+ init?: MultisigConfig.Config | undefined
645
+ pending?: Operation | undefined
646
+ resolveConfig?: ResolveConfig | undefined
647
+ }) {
648
+ const { account, chainId, init, pending, resolveConfig } = options
649
+ const config = (await resolveConfig?.({ account, chainId, init })) ?? pending?.config ?? init
650
+ if (!config) return undefined
651
+
652
+ const normalized = MultisigConfig.from(config)
653
+ if (
654
+ init &&
655
+ MultisigConfig.getAddress(MultisigConfig.from(init)).toLowerCase() !== account.toLowerCase()
656
+ )
657
+ throw new RpcResponse.InvalidParamsError({
658
+ message: 'Bootstrap multisig init config does not match the multisig account.',
659
+ })
660
+ return normalized
661
+ }
662
+
663
+ function resolveInitConfig(options: {
664
+ config: MultisigConfig.Config
665
+ init?: MultisigConfig.Config | undefined
666
+ nonce?: number | undefined
667
+ pending?: Operation | undefined
668
+ }) {
669
+ const { config, init, nonce, pending } = options
670
+ if (pending?.initConfig) return pending.initConfig
671
+ if (pending?.init && pending.config) return pending.config
672
+ if (init) return init
673
+ if (nonce === 0) return config
674
+ return undefined
675
+ }
676
+
677
+ function mergeSignatures(signatures: readonly Hex.Hex[]) {
678
+ const seen = new Set<string>()
679
+ const out: Hex.Hex[] = []
680
+ for (const signature of signatures) {
681
+ const key = signature.toLowerCase()
682
+ if (seen.has(key)) continue
683
+ seen.add(key)
684
+ out.push(signature)
685
+ }
686
+ return out
687
+ }
688
+
689
+ function getApprovals(options: {
690
+ account: Address
691
+ config: MultisigConfig.Config
692
+ payload: Hex.Hex
693
+ signatures: readonly Hex.Hex[]
694
+ }) {
695
+ const { account, config, payload } = options
696
+ const digest = MultisigConfig.getSignPayload({ account, payload })
697
+ const owners = new Map(
698
+ config.owners.map((owner) => [
699
+ owner.owner.toLowerCase(),
700
+ { address: owner.owner, weight: Number(owner.weight) },
701
+ ]),
702
+ )
703
+ const seen = new Set<string>()
704
+ const signatures: Hex.Hex[] = []
705
+ let weight = 0
706
+
707
+ for (const value of options.signatures) {
708
+ const signature = SignatureEnvelope.from(value)
709
+ const owner = SignatureEnvelope.extractAddress({ payload: digest, signature })
710
+ const key = owner.toLowerCase()
711
+ const configured = owners.get(key)
712
+ if (!configured)
713
+ throw new RpcResponse.InvalidParamsError({ message: `Signature from non-owner ${owner}.` })
714
+ if (seen.has(key)) continue
715
+ const valid = (() => {
716
+ try {
717
+ return SignatureEnvelope.verify(signature, { payload: digest, address: configured.address })
718
+ } catch {
719
+ return false
720
+ }
721
+ })()
722
+ if (!valid)
723
+ throw new RpcResponse.InvalidParamsError({
724
+ message: `Invalid signature from owner ${configured.address}.`,
725
+ })
726
+ seen.add(key)
727
+ signatures.push(SignatureEnvelope.serialize(signature))
728
+ weight += configured.weight
729
+ }
730
+
731
+ return { signatures, threshold: Number(config.threshold), weight }
732
+ }
733
+
734
+ async function serializeFinal(options: {
735
+ account: Address
736
+ init?: MultisigConfig.Config | undefined
737
+ signatures: readonly Hex.Hex[]
738
+ transaction: Record<string, unknown>
739
+ }) {
740
+ const { signature: _, ...transaction } = options.transaction
741
+ const envelope = TxEnvelopeTempo.from({
742
+ ...transaction,
743
+ feePayerSignature: (() => {
744
+ const value = transaction['feePayerSignature']
745
+ // Preserve missing/null fee-payer markers so sponsorship can add signature later.
746
+ if (!value) return value
747
+ // Normalize RPC-shaped signatures before rebuilding final transaction envelope.
748
+ if (typeof value === 'object' && 'r' in value && 's' in value) {
749
+ const signature = value as {
750
+ r: bigint | number | string
751
+ s: bigint | number | string
752
+ v?: bigint | number | string | undefined
753
+ yParity?: bigint | number | string | undefined
754
+ }
755
+ const yParity = (() => {
756
+ const value = signature.yParity ?? signature.v
757
+ // Some signature shapes omit parity until later normalization.
758
+ if (typeof value === 'undefined') return undefined
759
+ const number = Number(value)
760
+ // RPC signatures may carry Ethereum 27/28 `v`; `ox` expects 0/1 parity.
761
+ if (number === 27 || number === 28) return number - 27
762
+ return number
763
+ })()
764
+ if (typeof yParity === 'number')
765
+ return Signature.from({ r: BigInt(signature.r), s: BigInt(signature.s), yParity })
766
+ }
767
+ // Fall back to `ox` for already-normalized signature inputs.
768
+ return Signature.from(value as never)
769
+ })(),
770
+ } as never)
771
+ const payload = TxEnvelopeTempo.getSignPayload(envelope)
772
+ const signatures = options.signatures.map((approval) => SignatureEnvelope.from(approval))
773
+ const sorted = SignatureEnvelope.sortMultisigApprovals({
774
+ account: options.account,
775
+ payload,
776
+ signatures,
777
+ })
778
+ const signature = SignatureEnvelope.from({
779
+ account: options.account,
780
+ signatures: sorted,
781
+ ...(options.init ? { init: options.init } : {}),
782
+ })
783
+ return TxEnvelopeTempo.serialize(envelope, {
784
+ ...('feePayerSignature' in transaction
785
+ ? { feePayerSignature: transaction['feePayerSignature'] as never }
786
+ : {}),
787
+ signature,
788
+ })
789
+ }
790
+
791
+ function mergeOperation(
792
+ existing: Operation | undefined,
793
+ operation: Operation,
794
+ patch: Partial<Operation>,
795
+ ) {
796
+ return {
797
+ ...operation,
798
+ ...existing,
799
+ ...patch,
800
+ config: operation.config ?? existing?.config,
801
+ init: existing?.init || operation.init,
802
+ initConfig: existing?.initConfig ?? operation.initConfig,
803
+ signatures: mergeSignatures([...(existing?.signatures ?? []), ...operation.signatures]),
804
+ transaction: operation.transaction,
805
+ } satisfies Operation
806
+ }
807
+
808
+ function toStatus(options: {
809
+ approvals: { signatures: readonly Hex.Hex[]; threshold: number; weight: number }
810
+ operation: Operation
811
+ }): Status {
812
+ const { approvals, operation } = options
813
+ return {
814
+ account: operation.account,
815
+ chainId: operation.chainId,
816
+ id: operation.id,
817
+ signatures: approvals.signatures.length,
818
+ status: operation.status,
819
+ submittedHash: operation.submittedHash,
820
+ threshold: approvals.threshold,
821
+ weight: approvals.weight,
822
+ }
823
+ }