tapimo 0.14.0 → 0.15.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 (1141) hide show
  1. package/README.md +7 -4
  2. package/dist/ApiKey.js +1 -1
  3. package/dist/ApiKey.js.map +1 -1
  4. package/dist/ApiKeys.d.ts +95 -14
  5. package/dist/ApiKeys.d.ts.map +1 -1
  6. package/dist/ApiKeys.js +360 -49
  7. package/dist/ApiKeys.js.map +1 -1
  8. package/dist/App.d.ts +12457 -10365
  9. package/dist/App.d.ts.map +1 -1
  10. package/dist/App.js +300 -22
  11. package/dist/App.js.map +1 -1
  12. package/dist/Assets.d.ts.map +1 -1
  13. package/dist/Assets.js +2 -1
  14. package/dist/Assets.js.map +1 -1
  15. package/dist/Handler.d.ts +0 -1
  16. package/dist/Handler.d.ts.map +1 -1
  17. package/dist/Handler.js +0 -1
  18. package/dist/Handler.js.map +1 -1
  19. package/dist/Scope.d.ts +13 -5
  20. package/dist/Scope.d.ts.map +1 -1
  21. package/dist/Scope.js +16 -5
  22. package/dist/Scope.js.map +1 -1
  23. package/dist/Webhooks.js +1 -1
  24. package/dist/Webhooks.js.map +1 -1
  25. package/dist/admin/App.d.ts +3057 -549
  26. package/dist/admin/App.d.ts.map +1 -1
  27. package/dist/admin/App.js +26 -5
  28. package/dist/admin/App.js.map +1 -1
  29. package/dist/admin/apps/api-keys.d.ts +159 -7
  30. package/dist/admin/apps/api-keys.d.ts.map +1 -1
  31. package/dist/admin/apps/api-keys.js +95 -43
  32. package/dist/admin/apps/api-keys.js.map +1 -1
  33. package/dist/admin/apps/earn-vaults.d.ts +1398 -0
  34. package/dist/admin/apps/earn-vaults.d.ts.map +1 -1
  35. package/dist/admin/apps/earn-vaults.js +463 -7
  36. package/dist/admin/apps/earn-vaults.js.map +1 -1
  37. package/dist/admin/apps/organizations.d.ts +267 -15
  38. package/dist/admin/apps/organizations.d.ts.map +1 -1
  39. package/dist/admin/apps/organizations.js +241 -25
  40. package/dist/admin/apps/organizations.js.map +1 -1
  41. package/dist/admin/apps/routes-support.d.ts +95 -0
  42. package/dist/admin/apps/routes-support.d.ts.map +1 -0
  43. package/dist/admin/apps/routes-support.js +151 -0
  44. package/dist/admin/apps/routes-support.js.map +1 -0
  45. package/dist/admin/apps/routes.d.ts +2764 -0
  46. package/dist/admin/apps/routes.d.ts.map +1 -0
  47. package/dist/admin/apps/routes.js +728 -0
  48. package/dist/admin/apps/routes.js.map +1 -0
  49. package/dist/admin/apps/subsidies.d.ts +501 -0
  50. package/dist/admin/apps/subsidies.d.ts.map +1 -0
  51. package/dist/admin/apps/subsidies.js +384 -0
  52. package/dist/admin/apps/subsidies.js.map +1 -0
  53. package/dist/admin/apps/verified-tokens.d.ts +88 -88
  54. package/dist/admin/apps/verified-tokens.d.ts.map +1 -1
  55. package/dist/admin/apps/verified-tokens.js +3 -3
  56. package/dist/admin/apps/verified-tokens.js.map +1 -1
  57. package/dist/admin/ui.generated.d.ts +1 -1
  58. package/dist/admin/ui.generated.d.ts.map +1 -1
  59. package/dist/admin/ui.generated.js +129 -69
  60. package/dist/admin/ui.generated.js.map +1 -1
  61. package/dist/analytics/Analytics.d.ts +5 -2
  62. package/dist/analytics/Analytics.d.ts.map +1 -1
  63. package/dist/analytics/Analytics.js +31 -1
  64. package/dist/analytics/Analytics.js.map +1 -1
  65. package/dist/analytics/tables/requestEvents.d.ts +2 -1
  66. package/dist/analytics/tables/requestEvents.d.ts.map +1 -1
  67. package/dist/analytics/tables/requestEvents.js +10 -1
  68. package/dist/analytics/tables/requestEvents.js.map +1 -1
  69. package/dist/analytics/tables/routesLifecycleIntervals.d.ts +72 -0
  70. package/dist/analytics/tables/routesLifecycleIntervals.d.ts.map +1 -0
  71. package/dist/analytics/tables/routesLifecycleIntervals.js +56 -0
  72. package/dist/analytics/tables/routesLifecycleIntervals.js.map +1 -0
  73. package/dist/apps/Zones.d.ts +21 -12526
  74. package/dist/apps/Zones.d.ts.map +1 -1
  75. package/dist/apps/Zones.js +37 -5
  76. package/dist/apps/Zones.js.map +1 -1
  77. package/dist/apps/data/App.d.ts +3971 -2595
  78. package/dist/apps/data/App.d.ts.map +1 -1
  79. package/dist/apps/data/App.js +76 -21
  80. package/dist/apps/data/App.js.map +1 -1
  81. package/dist/apps/data/routes/activities.d.ts +364 -34
  82. package/dist/apps/data/routes/activities.d.ts.map +1 -1
  83. package/dist/apps/data/routes/activities.js +495 -190
  84. package/dist/apps/data/routes/activities.js.map +1 -1
  85. package/dist/apps/data/routes/addresses.d.ts +72 -0
  86. package/dist/apps/data/routes/addresses.d.ts.map +1 -1
  87. package/dist/apps/data/routes/blocks.d.ts +37 -37
  88. package/dist/apps/data/routes/coingecko.d.ts.map +1 -1
  89. package/dist/apps/data/routes/coingecko.js +47 -21
  90. package/dist/apps/data/routes/coingecko.js.map +1 -1
  91. package/dist/apps/data/routes/earn.d.ts +1450 -337
  92. package/dist/apps/data/routes/earn.d.ts.map +1 -1
  93. package/dist/apps/data/routes/earn.js +1226 -144
  94. package/dist/apps/data/routes/earn.js.map +1 -1
  95. package/dist/apps/data/routes/fee-amm.d.ts +5 -0
  96. package/dist/apps/data/routes/fee-amm.d.ts.map +1 -1
  97. package/dist/apps/data/routes/fee-amm.js +31 -19
  98. package/dist/apps/data/routes/fee-amm.js.map +1 -1
  99. package/dist/apps/data/routes/indexer.d.ts +125 -0
  100. package/dist/apps/data/routes/indexer.d.ts.map +1 -1
  101. package/dist/apps/data/routes/indexer.js +83 -27
  102. package/dist/apps/data/routes/indexer.js.map +1 -1
  103. package/dist/apps/data/routes/rpc.d.ts +507 -33
  104. package/dist/apps/data/routes/rpc.d.ts.map +1 -1
  105. package/dist/apps/data/routes/rpc.js +266 -156
  106. package/dist/apps/data/routes/rpc.js.map +1 -1
  107. package/dist/apps/data/routes/tokenlist.d.ts +47 -15
  108. package/dist/apps/data/routes/tokenlist.d.ts.map +1 -1
  109. package/dist/apps/data/routes/tokenlist.js +68 -11
  110. package/dist/apps/data/routes/tokenlist.js.map +1 -1
  111. package/dist/apps/data/routes/tokens.d.ts +2 -0
  112. package/dist/apps/data/routes/tokens.d.ts.map +1 -1
  113. package/dist/apps/data/routes/tokens.js +26 -14
  114. package/dist/apps/data/routes/tokens.js.map +1 -1
  115. package/dist/apps/data/routes/transfers.d.ts +28 -12
  116. package/dist/apps/data/routes/transfers.d.ts.map +1 -1
  117. package/dist/apps/data/routes/transfers.js +9 -7
  118. package/dist/apps/data/routes/transfers.js.map +1 -1
  119. package/dist/apps/data/routes/valuation.d.ts +30 -30
  120. package/dist/apps/data/routes/verified-tokens.d.ts +9 -9
  121. package/dist/apps/data/routes/verified-tokens.d.ts.map +1 -1
  122. package/dist/apps/data/routes/verified-tokens.js +64 -20
  123. package/dist/apps/data/routes/verified-tokens.js.map +1 -1
  124. package/dist/apps/data/routes/webhooks.d.ts +613 -176
  125. package/dist/apps/data/routes/webhooks.d.ts.map +1 -1
  126. package/dist/apps/data/routes/webhooks.js +291 -195
  127. package/dist/apps/data/routes/webhooks.js.map +1 -1
  128. package/dist/apps/data/routes/zones.d.ts.map +1 -1
  129. package/dist/apps/data/routes/zones.js +20 -12
  130. package/dist/apps/data/routes/zones.js.map +1 -1
  131. package/dist/apps/docs/reference.js +2 -2
  132. package/dist/apps/docs/reference.js.map +1 -1
  133. package/dist/apps/index.d.ts +1 -1
  134. package/dist/apps/index.d.ts.map +1 -1
  135. package/dist/apps/index.js +1 -1
  136. package/dist/apps/index.js.map +1 -1
  137. package/dist/apps/management/App.d.ts +3763 -3385
  138. package/dist/apps/management/App.d.ts.map +1 -1
  139. package/dist/apps/management/App.js +5 -14
  140. package/dist/apps/management/App.js.map +1 -1
  141. package/dist/apps/management/Billing.d.ts +48 -7
  142. package/dist/apps/management/Billing.d.ts.map +1 -1
  143. package/dist/apps/management/Billing.js +204 -25
  144. package/dist/apps/management/Billing.js.map +1 -1
  145. package/dist/apps/management/routes/api-keys.d.ts +106 -4
  146. package/dist/apps/management/routes/api-keys.d.ts.map +1 -1
  147. package/dist/apps/management/routes/api-keys.js +43 -15
  148. package/dist/apps/management/routes/api-keys.js.map +1 -1
  149. package/dist/apps/management/routes/billing.d.ts +290 -4
  150. package/dist/apps/management/routes/billing.d.ts.map +1 -1
  151. package/dist/apps/management/routes/billing.js +274 -49
  152. package/dist/apps/management/routes/billing.js.map +1 -1
  153. package/dist/apps/management/routes/faucet.d.ts +6 -6
  154. package/dist/apps/management/routes/faucet.js +1 -1
  155. package/dist/apps/management/routes/faucet.js.map +1 -1
  156. package/dist/apps/management/routes/invitations.d.ts +77 -2
  157. package/dist/apps/management/routes/invitations.d.ts.map +1 -1
  158. package/dist/apps/management/routes/invitations.js +117 -13
  159. package/dist/apps/management/routes/invitations.js.map +1 -1
  160. package/dist/apps/management/routes/invite-links.d.ts +4 -4
  161. package/dist/apps/management/routes/me.d.ts.map +1 -1
  162. package/dist/apps/management/routes/me.js +6 -2
  163. package/dist/apps/management/routes/me.js.map +1 -1
  164. package/dist/apps/management/routes/members.d.ts +30 -30
  165. package/dist/apps/management/routes/orgs.d.ts +18 -2
  166. package/dist/apps/management/routes/orgs.d.ts.map +1 -1
  167. package/dist/apps/management/routes/orgs.js +52 -12
  168. package/dist/apps/management/routes/orgs.js.map +1 -1
  169. package/dist/apps/management/routes/projects.d.ts +4 -4
  170. package/dist/apps/management/routes/projects.d.ts.map +1 -1
  171. package/dist/apps/management/routes/projects.js +6 -1
  172. package/dist/apps/management/routes/projects.js.map +1 -1
  173. package/dist/apps/management/routes/scopes.d.ts.map +1 -1
  174. package/dist/apps/management/routes/scopes.js +4 -1
  175. package/dist/apps/management/routes/scopes.js.map +1 -1
  176. package/dist/apps/management/routes/usage.d.ts +24 -24
  177. package/dist/apps/management/routes/usage.js +21 -4
  178. package/dist/apps/management/routes/usage.js.map +1 -1
  179. package/dist/apps/management/routes/verified-token-requests.d.ts +2 -2
  180. package/dist/apps/management/routes/webhooks.d.ts +280 -214
  181. package/dist/apps/management/routes/webhooks.d.ts.map +1 -1
  182. package/dist/apps/management/routes/webhooks.js +58 -12
  183. package/dist/apps/management/routes/webhooks.js.map +1 -1
  184. package/dist/apps/mcp.d.ts +1 -1
  185. package/dist/apps/mcp.js +7 -7
  186. package/dist/apps/mcp.js.map +1 -1
  187. package/dist/apps/mpp/App.d.ts.map +1 -1
  188. package/dist/apps/mpp/App.js +35 -7
  189. package/dist/apps/mpp/App.js.map +1 -1
  190. package/dist/apps/mpp/internal/Adapter.d.ts +2 -0
  191. package/dist/apps/mpp/internal/Adapter.d.ts.map +1 -1
  192. package/dist/apps/mpp/internal/Adapter.js +30 -1
  193. package/dist/apps/mpp/internal/Adapter.js.map +1 -1
  194. package/dist/apps/mpp/internal/Policy.d.ts +22 -4
  195. package/dist/apps/mpp/internal/Policy.d.ts.map +1 -1
  196. package/dist/apps/mpp/internal/Policy.js +24 -6
  197. package/dist/apps/mpp/internal/Policy.js.map +1 -1
  198. package/dist/apps/mpp/internal/Sponsorship.d.ts +3 -0
  199. package/dist/apps/mpp/internal/Sponsorship.d.ts.map +1 -1
  200. package/dist/apps/mpp/internal/Sponsorship.js +6 -3
  201. package/dist/apps/mpp/internal/Sponsorship.js.map +1 -1
  202. package/dist/apps/relay/App.d.ts +2 -0
  203. package/dist/apps/relay/App.d.ts.map +1 -1
  204. package/dist/apps/relay/App.js +134 -75
  205. package/dist/apps/relay/App.js.map +1 -1
  206. package/dist/apps/relay/Sponsorships.d.ts +5 -3
  207. package/dist/apps/relay/Sponsorships.d.ts.map +1 -1
  208. package/dist/apps/relay/Sponsorships.js +209 -28
  209. package/dist/apps/relay/Sponsorships.js.map +1 -1
  210. package/dist/apps/{funding → routes}/Access.d.ts +4 -4
  211. package/dist/apps/routes/Access.d.ts.map +1 -0
  212. package/dist/apps/{funding → routes}/Access.js +4 -4
  213. package/dist/apps/routes/Access.js.map +1 -0
  214. package/dist/apps/{funding → routes}/App.d.ts +418 -124
  215. package/dist/apps/{funding → routes}/App.d.ts.map +1 -1
  216. package/dist/apps/{funding → routes}/App.js +16 -16
  217. package/dist/apps/routes/App.js.map +1 -0
  218. package/dist/apps/routes/Inventory.d.ts.map +1 -0
  219. package/dist/apps/{funding → routes}/Inventory.js +2 -2
  220. package/dist/apps/routes/Inventory.js.map +1 -0
  221. package/dist/apps/routes/index.d.ts +2 -0
  222. package/dist/apps/routes/index.d.ts.map +1 -0
  223. package/dist/apps/routes/index.js +2 -0
  224. package/dist/apps/routes/index.js.map +1 -0
  225. package/dist/apps/{funding → routes}/routes/chains.d.ts +7 -7
  226. package/dist/apps/routes/routes/chains.d.ts.map +1 -0
  227. package/dist/apps/{funding → routes}/routes/chains.js +25 -25
  228. package/dist/apps/routes/routes/chains.js.map +1 -0
  229. package/dist/apps/{funding → routes}/routes/deposit-addresses.d.ts +107 -43
  230. package/dist/apps/routes/routes/deposit-addresses.d.ts.map +1 -0
  231. package/dist/apps/{funding → routes}/routes/deposit-addresses.js +497 -222
  232. package/dist/apps/routes/routes/deposit-addresses.js.map +1 -0
  233. package/dist/apps/{funding → routes}/routes/providers.d.ts +8 -8
  234. package/dist/apps/routes/routes/providers.d.ts.map +1 -0
  235. package/dist/apps/routes/routes/providers.js +57 -0
  236. package/dist/apps/routes/routes/providers.js.map +1 -0
  237. package/dist/apps/{funding → routes}/routes/quotes.d.ts +19 -16
  238. package/dist/apps/routes/routes/quotes.d.ts.map +1 -0
  239. package/dist/apps/{funding → routes}/routes/quotes.js +55 -38
  240. package/dist/apps/routes/routes/quotes.js.map +1 -0
  241. package/dist/apps/{funding → routes}/routes/transfers.d.ts +379 -74
  242. package/dist/apps/routes/routes/transfers.d.ts.map +1 -0
  243. package/dist/apps/routes/routes/transfers.js +1140 -0
  244. package/dist/apps/routes/routes/transfers.js.map +1 -0
  245. package/dist/cli/Cli.d.ts +30 -0
  246. package/dist/cli/Cli.d.ts.map +1 -1
  247. package/dist/cli/commands/admin.d.ts +36 -0
  248. package/dist/cli/commands/admin.d.ts.map +1 -1
  249. package/dist/cli/commands/admin.js +273 -0
  250. package/dist/cli/commands/admin.js.map +1 -1
  251. package/dist/cloudflare.d.ts +16 -14
  252. package/dist/cloudflare.d.ts.map +1 -1
  253. package/dist/cloudflare.js +26 -21
  254. package/dist/cloudflare.js.map +1 -1
  255. package/dist/db/Db.d.ts +63 -21
  256. package/dist/db/Db.d.ts.map +1 -1
  257. package/dist/db/Db.js +1030 -15
  258. package/dist/db/Db.js.map +1 -1
  259. package/dist/db/Schema.d.ts +780 -133
  260. package/dist/db/Schema.d.ts.map +1 -1
  261. package/dist/db/Schema.js +575 -162
  262. package/dist/db/Schema.js.map +1 -1
  263. package/dist/db/tables/apiKeyAdmissionBootstraps.d.ts +4 -0
  264. package/dist/db/tables/apiKeyAdmissionBootstraps.d.ts.map +1 -0
  265. package/dist/db/tables/apiKeyAdmissionBootstraps.js +2 -0
  266. package/dist/db/tables/apiKeyAdmissionBootstraps.js.map +1 -0
  267. package/dist/db/tables/apiKeyAdmissions.d.ts +73 -0
  268. package/dist/db/tables/apiKeyAdmissions.d.ts.map +1 -0
  269. package/dist/db/tables/apiKeyAdmissions.js +142 -0
  270. package/dist/db/tables/apiKeyAdmissions.js.map +1 -0
  271. package/dist/db/tables/apiKeyOwnerAdmissions.d.ts +4 -0
  272. package/dist/db/tables/apiKeyOwnerAdmissions.d.ts.map +1 -0
  273. package/dist/db/tables/apiKeyOwnerAdmissions.js +2 -0
  274. package/dist/db/tables/apiKeyOwnerAdmissions.js.map +1 -0
  275. package/dist/db/tables/apiKeyOwnerTombstones.d.ts +20 -0
  276. package/dist/db/tables/apiKeyOwnerTombstones.d.ts.map +1 -0
  277. package/dist/db/tables/apiKeyOwnerTombstones.js +57 -0
  278. package/dist/db/tables/apiKeyOwnerTombstones.js.map +1 -0
  279. package/dist/db/tables/apiKeyRevocations.d.ts +21 -0
  280. package/dist/db/tables/apiKeyRevocations.d.ts.map +1 -0
  281. package/dist/db/tables/apiKeyRevocations.js +98 -0
  282. package/dist/db/tables/apiKeyRevocations.js.map +1 -0
  283. package/dist/db/tables/authAccounts.d.ts +47 -0
  284. package/dist/db/tables/authAccounts.d.ts.map +1 -0
  285. package/dist/db/tables/authAccounts.js +72 -0
  286. package/dist/db/tables/authAccounts.js.map +1 -0
  287. package/dist/db/tables/authSessions.d.ts +12 -0
  288. package/dist/db/tables/authSessions.d.ts.map +1 -0
  289. package/dist/db/tables/authSessions.js +2 -0
  290. package/dist/db/tables/authSessions.js.map +1 -0
  291. package/dist/db/tables/authVerifications.d.ts +12 -0
  292. package/dist/db/tables/authVerifications.d.ts.map +1 -0
  293. package/dist/db/tables/authVerifications.js +2 -0
  294. package/dist/db/tables/authVerifications.js.map +1 -0
  295. package/dist/db/tables/invitations.d.ts +17 -1
  296. package/dist/db/tables/invitations.d.ts.map +1 -1
  297. package/dist/db/tables/invitations.js +123 -43
  298. package/dist/db/tables/invitations.js.map +1 -1
  299. package/dist/db/tables/memberships.d.ts +8 -0
  300. package/dist/db/tables/memberships.d.ts.map +1 -1
  301. package/dist/db/tables/memberships.js +51 -2
  302. package/dist/db/tables/memberships.js.map +1 -1
  303. package/dist/db/tables/organizations.d.ts +32 -10
  304. package/dist/db/tables/organizations.d.ts.map +1 -1
  305. package/dist/db/tables/organizations.js +110 -49
  306. package/dist/db/tables/organizations.js.map +1 -1
  307. package/dist/db/tables/projects.d.ts +2 -0
  308. package/dist/db/tables/projects.d.ts.map +1 -1
  309. package/dist/db/tables/projects.js +12 -3
  310. package/dist/db/tables/projects.js.map +1 -1
  311. package/dist/db/tables/requestUsage.d.ts.map +1 -1
  312. package/dist/db/tables/requestUsage.js.map +1 -1
  313. package/dist/db/tables/rewardAccounts.d.ts +86 -0
  314. package/dist/db/tables/rewardAccounts.d.ts.map +1 -0
  315. package/dist/db/tables/rewardAccounts.js +88 -0
  316. package/dist/db/tables/rewardAccounts.js.map +1 -0
  317. package/dist/db/tables/rewardCampaignDistributors.d.ts +36 -0
  318. package/dist/db/tables/rewardCampaignDistributors.d.ts.map +1 -0
  319. package/dist/db/tables/rewardCampaignDistributors.js +30 -0
  320. package/dist/db/tables/rewardCampaignDistributors.js.map +1 -0
  321. package/dist/db/tables/rewardCampaigns.d.ts +171 -0
  322. package/dist/db/tables/rewardCampaigns.d.ts.map +1 -0
  323. package/dist/db/tables/rewardCampaigns.js +392 -0
  324. package/dist/db/tables/rewardCampaigns.js.map +1 -0
  325. package/dist/db/tables/rewardCredits.d.ts +53 -0
  326. package/dist/db/tables/rewardCredits.d.ts.map +1 -0
  327. package/dist/db/tables/rewardCredits.js +63 -0
  328. package/dist/db/tables/rewardCredits.js.map +1 -0
  329. package/dist/db/tables/rewardEligibilityAssociations.d.ts +61 -0
  330. package/dist/db/tables/rewardEligibilityAssociations.d.ts.map +1 -0
  331. package/dist/db/tables/rewardEligibilityAssociations.js +103 -0
  332. package/dist/db/tables/rewardEligibilityAssociations.js.map +1 -0
  333. package/dist/db/tables/rewardRuns.d.ts +188 -0
  334. package/dist/db/tables/rewardRuns.d.ts.map +1 -0
  335. package/dist/db/tables/rewardRuns.js +278 -0
  336. package/dist/db/tables/rewardRuns.js.map +1 -0
  337. package/dist/db/tables/rewardTransactionAttempts.d.ts +100 -0
  338. package/dist/db/tables/rewardTransactionAttempts.d.ts.map +1 -0
  339. package/dist/db/tables/rewardTransactionAttempts.js +163 -0
  340. package/dist/db/tables/rewardTransactionAttempts.js.map +1 -0
  341. package/dist/db/tables/routesCatalog.d.ts +58 -0
  342. package/dist/db/tables/routesCatalog.d.ts.map +1 -0
  343. package/dist/db/tables/{fundingCatalog.js → routesCatalog.js} +19 -19
  344. package/dist/db/tables/routesCatalog.js.map +1 -0
  345. package/dist/db/tables/routesDepositAddresses.d.ts +476 -0
  346. package/dist/db/tables/routesDepositAddresses.d.ts.map +1 -0
  347. package/dist/db/tables/routesDepositAddresses.js +587 -0
  348. package/dist/db/tables/routesDepositAddresses.js.map +1 -0
  349. package/dist/db/tables/{fundingDepositRequestObservations.d.ts → routesDepositRequestObservations.d.ts} +6 -6
  350. package/dist/db/tables/routesDepositRequestObservations.d.ts.map +1 -0
  351. package/dist/db/tables/{fundingDepositRequestObservations.js → routesDepositRequestObservations.js} +6 -6
  352. package/dist/db/tables/routesDepositRequestObservations.js.map +1 -0
  353. package/dist/db/tables/{fundingDeposits.d.ts → routesDeposits.d.ts} +210 -22
  354. package/dist/db/tables/routesDeposits.d.ts.map +1 -0
  355. package/dist/db/tables/routesDeposits.js +576 -0
  356. package/dist/db/tables/routesDeposits.js.map +1 -0
  357. package/dist/db/tables/routesIdempotency.d.ts +166 -0
  358. package/dist/db/tables/routesIdempotency.d.ts.map +1 -0
  359. package/dist/db/tables/routesIdempotency.js +330 -0
  360. package/dist/db/tables/routesIdempotency.js.map +1 -0
  361. package/dist/db/tables/routesSubsidies.d.ts +27 -0
  362. package/dist/db/tables/routesSubsidies.d.ts.map +1 -0
  363. package/dist/db/tables/routesSubsidies.js +45 -0
  364. package/dist/db/tables/routesSubsidies.js.map +1 -0
  365. package/dist/db/tables/{fundingTransferEvents.d.ts → routesTransferEvents.d.ts} +3 -3
  366. package/dist/db/tables/routesTransferEvents.d.ts.map +1 -0
  367. package/dist/db/tables/{fundingTransferEvents.js → routesTransferEvents.js} +3 -3
  368. package/dist/db/tables/routesTransferEvents.js.map +1 -0
  369. package/dist/db/tables/routesTransferSubsidies.d.ts +19 -0
  370. package/dist/db/tables/routesTransferSubsidies.d.ts.map +1 -0
  371. package/dist/db/tables/routesTransferSubsidies.js +17 -0
  372. package/dist/db/tables/routesTransferSubsidies.js.map +1 -0
  373. package/dist/db/tables/routesTransferSubsidyNonces.d.ts +51 -0
  374. package/dist/db/tables/routesTransferSubsidyNonces.d.ts.map +1 -0
  375. package/dist/db/tables/routesTransferSubsidyNonces.js +82 -0
  376. package/dist/db/tables/routesTransferSubsidyNonces.js.map +1 -0
  377. package/dist/db/tables/routesTransferTransactions.d.ts +77 -0
  378. package/dist/db/tables/routesTransferTransactions.d.ts.map +1 -0
  379. package/dist/db/tables/{fundingTransferTransactions.js → routesTransferTransactions.js} +31 -13
  380. package/dist/db/tables/routesTransferTransactions.js.map +1 -0
  381. package/dist/db/tables/routesTransfers.d.ts +319 -0
  382. package/dist/db/tables/routesTransfers.d.ts.map +1 -0
  383. package/dist/db/tables/routesTransfers.js +372 -0
  384. package/dist/db/tables/routesTransfers.js.map +1 -0
  385. package/dist/db/tables/sponsoredTransactions.d.ts +75 -20
  386. package/dist/db/tables/sponsoredTransactions.d.ts.map +1 -1
  387. package/dist/db/tables/sponsoredTransactions.js +124 -54
  388. package/dist/db/tables/sponsoredTransactions.js.map +1 -1
  389. package/dist/db/tables/sponsorshipAttributions.d.ts +69 -0
  390. package/dist/db/tables/sponsorshipAttributions.d.ts.map +1 -0
  391. package/dist/db/tables/sponsorshipAttributions.js +77 -0
  392. package/dist/db/tables/sponsorshipAttributions.js.map +1 -0
  393. package/dist/db/tables/sponsorshipReconciliationCursors.d.ts +22 -0
  394. package/dist/db/tables/sponsorshipReconciliationCursors.d.ts.map +1 -0
  395. package/dist/db/tables/sponsorshipReconciliationCursors.js +45 -0
  396. package/dist/db/tables/sponsorshipReconciliationCursors.js.map +1 -0
  397. package/dist/db/tables/stripeCustomers.d.ts +11 -0
  398. package/dist/db/tables/stripeCustomers.d.ts.map +1 -1
  399. package/dist/db/tables/stripeCustomers.js +13 -0
  400. package/dist/db/tables/stripeCustomers.js.map +1 -1
  401. package/dist/db/tables/users.d.ts +17 -1
  402. package/dist/db/tables/users.d.ts.map +1 -1
  403. package/dist/db/tables/users.js +47 -2
  404. package/dist/db/tables/users.js.map +1 -1
  405. package/dist/db/tables/webhookQueueEvents.d.ts.map +1 -1
  406. package/dist/db/tables/webhookQueueEvents.js +5 -1
  407. package/dist/db/tables/webhookQueueEvents.js.map +1 -1
  408. package/dist/db/tables/webhookSubscriptions.d.ts +19 -11
  409. package/dist/db/tables/webhookSubscriptions.d.ts.map +1 -1
  410. package/dist/db/tables/webhookSubscriptions.js +45 -13
  411. package/dist/db/tables/webhookSubscriptions.js.map +1 -1
  412. package/dist/handlers/internal/executionError.d.ts +2 -2
  413. package/dist/handlers/internal/executionError.d.ts.map +1 -1
  414. package/dist/handlers/internal/executionError.js +1 -2
  415. package/dist/handlers/internal/executionError.js.map +1 -1
  416. package/dist/handlers/internal/multisig.d.ts +4 -232
  417. package/dist/handlers/internal/multisig.d.ts.map +1 -1
  418. package/dist/handlers/internal/multisig.js +11 -537
  419. package/dist/handlers/internal/multisig.js.map +1 -1
  420. package/dist/handlers/internal/sponsorship.d.ts +19 -8
  421. package/dist/handlers/internal/sponsorship.d.ts.map +1 -1
  422. package/dist/handlers/internal/sponsorship.js +13 -9
  423. package/dist/handlers/internal/sponsorship.js.map +1 -1
  424. package/dist/handlers/relay.d.ts +9 -12
  425. package/dist/handlers/relay.d.ts.map +1 -1
  426. package/dist/handlers/relay.js +81 -85
  427. package/dist/handlers/relay.js.map +1 -1
  428. package/dist/index.d.ts +0 -17
  429. package/dist/index.d.ts.map +1 -1
  430. package/dist/index.js +0 -17
  431. package/dist/index.js.map +1 -1
  432. package/dist/internal/AssetResponse.d.ts +12 -0
  433. package/dist/internal/AssetResponse.d.ts.map +1 -0
  434. package/dist/internal/AssetResponse.js +21 -0
  435. package/dist/internal/AssetResponse.js.map +1 -0
  436. package/dist/internal/Auth.d.ts +48 -12
  437. package/dist/internal/Auth.d.ts.map +1 -1
  438. package/dist/internal/Auth.js +603 -175
  439. package/dist/internal/Auth.js.map +1 -1
  440. package/dist/internal/BetterAuth.d.ts +1488 -0
  441. package/dist/internal/BetterAuth.d.ts.map +1 -0
  442. package/dist/internal/BetterAuth.js +253 -0
  443. package/dist/internal/BetterAuth.js.map +1 -0
  444. package/dist/internal/Cache.d.ts +2 -0
  445. package/dist/internal/Cache.d.ts.map +1 -1
  446. package/dist/internal/Cache.js +2 -0
  447. package/dist/internal/Cache.js.map +1 -1
  448. package/dist/internal/EarnRates.d.ts +26 -3
  449. package/dist/internal/EarnRates.d.ts.map +1 -1
  450. package/dist/internal/EarnRates.js +84 -19
  451. package/dist/internal/EarnRates.js.map +1 -1
  452. package/dist/internal/EarnSharePrices.d.ts +120 -0
  453. package/dist/internal/EarnSharePrices.d.ts.map +1 -0
  454. package/dist/internal/EarnSharePrices.js +179 -0
  455. package/dist/internal/EarnSharePrices.js.map +1 -0
  456. package/dist/internal/EarnVaults.d.ts +4 -0
  457. package/dist/internal/EarnVaults.d.ts.map +1 -1
  458. package/dist/internal/EarnVaults.js +27 -10
  459. package/dist/internal/EarnVaults.js.map +1 -1
  460. package/dist/internal/Email.d.ts +37 -0
  461. package/dist/internal/Email.d.ts.map +1 -0
  462. package/dist/internal/Email.js +16 -0
  463. package/dist/internal/Email.js.map +1 -0
  464. package/dist/internal/Log.d.ts +32 -28
  465. package/dist/internal/Log.d.ts.map +1 -1
  466. package/dist/internal/Log.js +18 -11
  467. package/dist/internal/Log.js.map +1 -1
  468. package/dist/internal/MetricSink.d.ts +3 -0
  469. package/dist/internal/MetricSink.d.ts.map +1 -1
  470. package/dist/internal/MetricSink.js +67 -8
  471. package/dist/internal/MetricSink.js.map +1 -1
  472. package/dist/internal/Mpp.d.ts.map +1 -1
  473. package/dist/internal/Mpp.js +20 -25
  474. package/dist/internal/Mpp.js.map +1 -1
  475. package/dist/internal/OpenApi.d.ts +26 -3
  476. package/dist/internal/OpenApi.d.ts.map +1 -1
  477. package/dist/internal/OpenApi.js +25 -10
  478. package/dist/internal/OpenApi.js.map +1 -1
  479. package/dist/internal/Provider.d.ts +1 -1
  480. package/dist/internal/Provider.d.ts.map +1 -1
  481. package/dist/internal/RateLimit.d.ts.map +1 -1
  482. package/dist/internal/RateLimit.js +13 -1
  483. package/dist/internal/RateLimit.js.map +1 -1
  484. package/dist/internal/Store.d.ts +16 -0
  485. package/dist/internal/Store.d.ts.map +1 -1
  486. package/dist/internal/Store.js +59 -8
  487. package/dist/internal/Store.js.map +1 -1
  488. package/dist/internal/Tidx.d.ts +9 -2
  489. package/dist/internal/Tidx.d.ts.map +1 -1
  490. package/dist/internal/Tidx.js +78 -11
  491. package/dist/internal/Tidx.js.map +1 -1
  492. package/dist/internal/Timing.d.ts +26 -0
  493. package/dist/internal/Timing.d.ts.map +1 -1
  494. package/dist/internal/Timing.js +63 -5
  495. package/dist/internal/Timing.js.map +1 -1
  496. package/dist/internal/VercelOidc.d.ts +94 -0
  497. package/dist/internal/VercelOidc.d.ts.map +1 -0
  498. package/dist/internal/VercelOidc.js +128 -0
  499. package/dist/internal/VercelOidc.js.map +1 -0
  500. package/dist/internal/VerifiedTokens.d.ts +2 -8
  501. package/dist/internal/VerifiedTokens.d.ts.map +1 -1
  502. package/dist/internal/VerifiedTokens.js +24 -24
  503. package/dist/internal/VerifiedTokens.js.map +1 -1
  504. package/dist/internal/Viem.d.ts +30 -2067
  505. package/dist/internal/Viem.d.ts.map +1 -1
  506. package/dist/internal/Viem.js +167 -17
  507. package/dist/internal/Viem.js.map +1 -1
  508. package/dist/internal/Webhooks.d.ts +12 -4
  509. package/dist/internal/Webhooks.d.ts.map +1 -1
  510. package/dist/internal/Webhooks.js +9 -3
  511. package/dist/internal/Webhooks.js.map +1 -1
  512. package/dist/internal/ZoneRpc.d.ts +7 -0
  513. package/dist/internal/ZoneRpc.d.ts.map +1 -0
  514. package/dist/internal/ZoneRpc.js +49 -0
  515. package/dist/internal/ZoneRpc.js.map +1 -0
  516. package/dist/internal/index.d.ts +3 -1
  517. package/dist/internal/index.d.ts.map +1 -1
  518. package/dist/internal/index.js +3 -1
  519. package/dist/internal/index.js.map +1 -1
  520. package/dist/internal/rewards/Audit.d.ts +88 -0
  521. package/dist/internal/rewards/Audit.d.ts.map +1 -0
  522. package/dist/internal/rewards/Audit.js +134 -0
  523. package/dist/internal/rewards/Audit.js.map +1 -0
  524. package/dist/internal/rewards/Campaigns.d.ts +572 -0
  525. package/dist/internal/rewards/Campaigns.d.ts.map +1 -0
  526. package/dist/internal/rewards/Campaigns.js +531 -0
  527. package/dist/internal/rewards/Campaigns.js.map +1 -0
  528. package/dist/internal/rewards/Credits.d.ts +76 -0
  529. package/dist/internal/rewards/Credits.d.ts.map +1 -0
  530. package/dist/internal/rewards/Credits.js +95 -0
  531. package/dist/internal/rewards/Credits.js.map +1 -0
  532. package/dist/internal/rewards/Events.d.ts +100 -0
  533. package/dist/internal/rewards/Events.d.ts.map +1 -0
  534. package/dist/internal/rewards/Events.js +340 -0
  535. package/dist/internal/rewards/Events.js.map +1 -0
  536. package/dist/internal/rewards/Projection.d.ts +237 -0
  537. package/dist/internal/rewards/Projection.d.ts.map +1 -0
  538. package/dist/internal/rewards/Projection.js +616 -0
  539. package/dist/internal/rewards/Projection.js.map +1 -0
  540. package/dist/internal/rewards/Rates.d.ts +44 -0
  541. package/dist/internal/rewards/Rates.d.ts.map +1 -0
  542. package/dist/internal/rewards/Rates.js +60 -0
  543. package/dist/internal/rewards/Rates.js.map +1 -0
  544. package/dist/internal/rewards/Read.d.ts +158 -0
  545. package/dist/internal/rewards/Read.d.ts.map +1 -0
  546. package/dist/internal/rewards/Read.js +292 -0
  547. package/dist/internal/rewards/Read.js.map +1 -0
  548. package/dist/internal/rewards/Runner.d.ts +164 -0
  549. package/dist/internal/rewards/Runner.d.ts.map +1 -0
  550. package/dist/internal/rewards/Runner.js +1778 -0
  551. package/dist/internal/rewards/Runner.js.map +1 -0
  552. package/dist/internal/rewards/Signer.d.ts +224 -0
  553. package/dist/internal/rewards/Signer.d.ts.map +1 -0
  554. package/dist/internal/rewards/Signer.js +135 -0
  555. package/dist/internal/rewards/Signer.js.map +1 -0
  556. package/dist/internal/rewards/index.d.ts +15 -0
  557. package/dist/internal/rewards/index.d.ts.map +1 -0
  558. package/dist/internal/rewards/index.js +15 -0
  559. package/dist/internal/rewards/index.js.map +1 -0
  560. package/dist/internal/{funding → routes}/Action.d.ts +12 -1
  561. package/dist/internal/routes/Action.d.ts.map +1 -0
  562. package/dist/internal/{funding → routes}/Action.js +17 -9
  563. package/dist/internal/routes/Action.js.map +1 -0
  564. package/dist/internal/{funding → routes}/Catalog.d.ts +20 -20
  565. package/dist/internal/routes/Catalog.d.ts.map +1 -0
  566. package/dist/internal/{funding → routes}/Catalog.js +29 -29
  567. package/dist/internal/routes/Catalog.js.map +1 -0
  568. package/dist/internal/{funding → routes}/Chain.d.ts +10 -10
  569. package/dist/internal/routes/Chain.d.ts.map +1 -0
  570. package/dist/internal/{funding → routes}/Chain.js +3 -3
  571. package/dist/internal/routes/Chain.js.map +1 -0
  572. package/dist/internal/{funding → routes}/Deposit.d.ts +45 -23
  573. package/dist/internal/routes/Deposit.d.ts.map +1 -0
  574. package/dist/internal/{funding → routes}/Deposit.js +60 -27
  575. package/dist/internal/routes/Deposit.js.map +1 -0
  576. package/dist/internal/{funding → routes}/DepositAddress.d.ts +56 -27
  577. package/dist/internal/routes/DepositAddress.d.ts.map +1 -0
  578. package/dist/internal/{funding → routes}/DepositAddress.js +95 -33
  579. package/dist/internal/routes/DepositAddress.js.map +1 -0
  580. package/dist/internal/{funding → routes}/DepositWebhook.d.ts +4 -4
  581. package/dist/internal/routes/DepositWebhook.d.ts.map +1 -0
  582. package/dist/internal/{funding → routes}/DepositWebhook.js +4 -4
  583. package/dist/internal/routes/DepositWebhook.js.map +1 -0
  584. package/dist/internal/routes/Economics.d.ts +25 -0
  585. package/dist/internal/routes/Economics.d.ts.map +1 -0
  586. package/dist/internal/routes/Economics.js +28 -0
  587. package/dist/internal/routes/Economics.js.map +1 -0
  588. package/dist/internal/{funding → routes}/Evidence.d.ts +3 -3
  589. package/dist/internal/routes/Evidence.d.ts.map +1 -0
  590. package/dist/internal/{funding → routes}/Evidence.js +7 -7
  591. package/dist/internal/routes/Evidence.js.map +1 -0
  592. package/dist/internal/routes/Observability.d.ts +154 -0
  593. package/dist/internal/routes/Observability.d.ts.map +1 -0
  594. package/dist/internal/routes/Observability.js +389 -0
  595. package/dist/internal/routes/Observability.js.map +1 -0
  596. package/dist/internal/{funding → routes}/Provider.d.ts +311 -105
  597. package/dist/internal/routes/Provider.d.ts.map +1 -0
  598. package/dist/internal/{funding → routes}/Provider.js +229 -98
  599. package/dist/internal/routes/Provider.js.map +1 -0
  600. package/dist/internal/{funding → routes}/Reconciliation.d.ts +11 -6
  601. package/dist/internal/routes/Reconciliation.d.ts.map +1 -0
  602. package/dist/internal/{funding → routes}/Reconciliation.js +408 -158
  603. package/dist/internal/routes/Reconciliation.js.map +1 -0
  604. package/dist/internal/routes/Route.d.ts +21 -0
  605. package/dist/internal/routes/Route.d.ts.map +1 -0
  606. package/dist/internal/{funding → routes}/Route.js +1 -1
  607. package/dist/internal/routes/Route.js.map +1 -0
  608. package/dist/internal/{funding → routes}/SourceObservation.d.ts +6 -6
  609. package/dist/internal/routes/SourceObservation.d.ts.map +1 -0
  610. package/dist/internal/{funding → routes}/SourceObservation.js +8 -8
  611. package/dist/internal/routes/SourceObservation.js.map +1 -0
  612. package/dist/internal/{funding → routes}/Subsidy.d.ts +48 -3
  613. package/dist/internal/routes/Subsidy.d.ts.map +1 -0
  614. package/dist/internal/{funding → routes}/Subsidy.js +43 -3
  615. package/dist/internal/routes/Subsidy.js.map +1 -0
  616. package/dist/internal/{funding → routes}/Token.d.ts +4 -4
  617. package/dist/internal/routes/Token.d.ts.map +1 -0
  618. package/dist/internal/{funding → routes}/Token.js +3 -3
  619. package/dist/internal/routes/Token.js.map +1 -0
  620. package/dist/internal/{funding → routes}/Transfer.d.ts +241 -46
  621. package/dist/internal/routes/Transfer.d.ts.map +1 -0
  622. package/dist/internal/routes/Transfer.js +728 -0
  623. package/dist/internal/routes/Transfer.js.map +1 -0
  624. package/dist/internal/{funding → routes}/TransferReconciliation.d.ts +13 -10
  625. package/dist/internal/routes/TransferReconciliation.d.ts.map +1 -0
  626. package/dist/internal/routes/TransferReconciliation.js +422 -0
  627. package/dist/internal/routes/TransferReconciliation.js.map +1 -0
  628. package/dist/internal/routes/TransferSubsidy.d.ts +201 -0
  629. package/dist/internal/routes/TransferSubsidy.d.ts.map +1 -0
  630. package/dist/internal/routes/TransferSubsidy.js +256 -0
  631. package/dist/internal/routes/TransferSubsidy.js.map +1 -0
  632. package/dist/internal/{funding → routes}/TransferWebhook.d.ts +5 -5
  633. package/dist/internal/routes/TransferWebhook.d.ts.map +1 -0
  634. package/dist/internal/{funding → routes}/TransferWebhook.js +3 -3
  635. package/dist/internal/routes/TransferWebhook.js.map +1 -0
  636. package/dist/internal/{funding → routes}/index.d.ts +2 -0
  637. package/dist/internal/routes/index.d.ts.map +1 -0
  638. package/dist/internal/{funding → routes}/index.js +2 -0
  639. package/dist/internal/routes/index.js.map +1 -0
  640. package/dist/internal/{funding → routes}/providers/across.d.ts +4 -4
  641. package/dist/internal/routes/providers/across.d.ts.map +1 -0
  642. package/dist/internal/{funding → routes}/providers/across.js +13 -13
  643. package/dist/internal/routes/providers/across.js.map +1 -0
  644. package/dist/internal/{funding → routes}/providers/relay.d.ts +21 -12
  645. package/dist/internal/routes/providers/relay.d.ts.map +1 -0
  646. package/dist/internal/{funding → routes}/providers/relay.js +194 -110
  647. package/dist/internal/routes/providers/relay.js.map +1 -0
  648. package/dist/internal/{funding → routes}/providers/rhino.d.ts +4 -4
  649. package/dist/internal/routes/providers/rhino.d.ts.map +1 -0
  650. package/dist/internal/{funding → routes}/providers/rhino.js +10 -10
  651. package/dist/internal/routes/providers/rhino.js.map +1 -0
  652. package/dist/internal/{funding → routes}/providers/squid.d.ts +4 -4
  653. package/dist/internal/routes/providers/squid.d.ts.map +1 -0
  654. package/dist/internal/{funding → routes}/providers/squid.js +14 -14
  655. package/dist/internal/routes/providers/squid.js.map +1 -0
  656. package/dist/internal/{funding → routes}/providers/stargate.d.ts +46 -18
  657. package/dist/internal/routes/providers/stargate.d.ts.map +1 -0
  658. package/dist/internal/routes/providers/stargate.js +898 -0
  659. package/dist/internal/routes/providers/stargate.js.map +1 -0
  660. package/dist/internal/{funding → routes}/providers/symbiosis.d.ts +4 -4
  661. package/dist/internal/routes/providers/symbiosis.d.ts.map +1 -0
  662. package/dist/internal/{funding → routes}/providers/symbiosis.js +30 -20
  663. package/dist/internal/routes/providers/symbiosis.js.map +1 -0
  664. package/dist/internal/webhookDestinations/slack.js +12 -12
  665. package/dist/internal/webhookDestinations/slack.js.map +1 -1
  666. package/dist/providers/index.d.ts +12 -12
  667. package/dist/providers/index.d.ts.map +1 -1
  668. package/dist/providers/index.js +12 -12
  669. package/dist/providers/index.js.map +1 -1
  670. package/dist/server.d.ts +19 -0
  671. package/dist/server.d.ts.map +1 -0
  672. package/dist/server.js +19 -0
  673. package/dist/server.js.map +1 -0
  674. package/package.json +15 -4
  675. package/src/ApiKey.ts +1 -1
  676. package/src/ApiKeys.test.ts +1033 -3
  677. package/src/ApiKeys.ts +489 -48
  678. package/src/App.test-d.ts +1 -1
  679. package/src/App.test.ts +216 -25
  680. package/src/App.ts +334 -31
  681. package/src/Assets.test.ts +2 -2
  682. package/src/Assets.ts +3 -1
  683. package/src/Auth.test-d.ts +1 -1
  684. package/src/Client.test-d.ts +539 -110
  685. package/src/Handler.ts +0 -1
  686. package/src/OpenApi.contract.test.ts +195 -0
  687. package/src/Scope.ts +17 -5
  688. package/src/Webhooks.ts +1 -1
  689. package/src/admin/App.test.ts +30 -2
  690. package/src/admin/App.ts +42 -6
  691. package/src/admin/apps/api-keys.test.ts +267 -5
  692. package/src/admin/apps/api-keys.ts +100 -50
  693. package/src/admin/apps/earn-vaults.test.ts +158 -0
  694. package/src/admin/apps/earn-vaults.ts +679 -6
  695. package/src/admin/apps/organizations.test.ts +306 -17
  696. package/src/admin/apps/organizations.ts +299 -24
  697. package/src/admin/apps/routes-support.test.ts +200 -0
  698. package/src/admin/apps/routes-support.ts +201 -0
  699. package/src/admin/apps/routes.test.ts +450 -0
  700. package/src/admin/apps/routes.ts +896 -0
  701. package/src/admin/apps/scopes.test.ts +15 -5
  702. package/src/admin/apps/subsidies.test.ts +306 -0
  703. package/src/admin/apps/subsidies.ts +457 -0
  704. package/src/admin/apps/verified-tokens.test.ts +8 -3
  705. package/src/admin/apps/verified-tokens.ts +3 -3
  706. package/src/admin/ui/plugin.ts +1 -2
  707. package/src/admin/ui/src/components/RewardCampaignForm.tsx +1009 -0
  708. package/src/admin/ui/src/lib/config.ts +11 -2
  709. package/src/admin/ui/src/lib/earn-vaults.ts +2 -2
  710. package/src/admin/ui/src/lib/organizations.test.ts +83 -50
  711. package/src/admin/ui/src/lib/organizations.ts +106 -25
  712. package/src/admin/ui/src/lib/query-client.ts +1 -1
  713. package/src/admin/ui/src/lib/reward-campaigns.ts +136 -0
  714. package/src/admin/ui/src/lib/routes.test.ts +88 -0
  715. package/src/admin/ui/src/lib/routes.ts +304 -0
  716. package/src/admin/ui/src/lib/subsidies.ts +75 -0
  717. package/src/admin/ui/src/routeTree.gen.ts +63 -0
  718. package/src/admin/ui/src/routes/__root.tsx +12 -1
  719. package/src/admin/ui/src/routes/api-keys.tsx +196 -84
  720. package/src/admin/ui/src/routes/earn.vaults_.$vaultId.edit.tsx +105 -70
  721. package/src/admin/ui/src/routes/organizations_.$orgId.tsx +239 -23
  722. package/src/admin/ui/src/routes/routes.tsx +1615 -0
  723. package/src/admin/ui/src/routes/routes_.support.tsx +248 -0
  724. package/src/admin/ui/src/routes/subsidies.tsx +799 -0
  725. package/src/admin/ui.generated.ts +144 -69
  726. package/src/analytics/Analytics.test.ts +108 -18
  727. package/src/analytics/Analytics.ts +38 -6
  728. package/src/analytics/tables/requestEvents.test.ts +100 -0
  729. package/src/analytics/tables/requestEvents.ts +10 -1
  730. package/src/analytics/tables/routesLifecycleIntervals.ts +140 -0
  731. package/src/apps/Zones.test.ts +15 -0
  732. package/src/apps/Zones.ts +52 -5
  733. package/src/apps/composition.test.ts +68 -60
  734. package/src/apps/data/App.test.ts +154 -2
  735. package/src/apps/data/App.ts +88 -28
  736. package/src/apps/data/routes/activities.test.ts +419 -7
  737. package/src/apps/data/routes/activities.ts +683 -216
  738. package/src/apps/data/routes/balances.test.ts +2 -2
  739. package/src/apps/data/routes/blocks.test.ts +46 -1
  740. package/src/apps/data/routes/coingecko.test.ts +419 -1
  741. package/src/apps/data/routes/coingecko.ts +309 -253
  742. package/src/apps/data/routes/earn.discovery.test.ts +274 -0
  743. package/src/apps/data/routes/earn.test.ts +1294 -17
  744. package/src/apps/data/routes/earn.ts +1838 -321
  745. package/src/apps/data/routes/exchanges.test.ts +12 -15
  746. package/src/apps/data/routes/fee-amm.test.ts +224 -0
  747. package/src/apps/data/routes/fee-amm.ts +191 -160
  748. package/src/apps/data/routes/indexer.test.ts +389 -0
  749. package/src/apps/data/routes/indexer.ts +165 -69
  750. package/src/apps/data/routes/receipts.test.ts +1 -1
  751. package/src/apps/data/routes/rpc.test.ts +352 -8
  752. package/src/apps/data/routes/rpc.ts +407 -219
  753. package/src/apps/data/routes/rpc.zone.test.ts +340 -0
  754. package/src/apps/data/routes/tokenlist.test.ts +285 -0
  755. package/src/apps/data/routes/tokenlist.ts +173 -88
  756. package/src/apps/data/routes/tokens.test.ts +93 -3
  757. package/src/apps/data/routes/tokens.ts +39 -23
  758. package/src/apps/data/routes/transactions.test.ts +1 -1
  759. package/src/apps/data/routes/transfers.test.ts +56 -24
  760. package/src/apps/data/routes/transfers.ts +19 -8
  761. package/src/apps/data/routes/valuation.test.ts +1 -1
  762. package/src/apps/data/routes/verified-tokens.test.ts +345 -0
  763. package/src/apps/data/routes/verified-tokens.ts +99 -29
  764. package/src/apps/data/routes/webhooks.test.ts +645 -83
  765. package/src/apps/data/routes/webhooks.ts +1089 -857
  766. package/src/apps/data/routes/zones.test.ts +148 -71
  767. package/src/apps/data/routes/zones.ts +71 -55
  768. package/src/apps/docs/reference.ts +2 -2
  769. package/src/apps/index.ts +1 -1
  770. package/src/apps/management/App.ts +9 -51
  771. package/src/apps/management/Billing.test.ts +375 -14
  772. package/src/apps/management/Billing.ts +265 -29
  773. package/src/apps/management/routes/api-keys.test.ts +269 -7
  774. package/src/apps/management/routes/api-keys.ts +61 -20
  775. package/src/apps/management/routes/billing.test.ts +477 -15
  776. package/src/apps/management/routes/billing.ts +377 -50
  777. package/src/apps/management/routes/faucet.test.ts +1 -1
  778. package/src/apps/management/routes/faucet.ts +1 -1
  779. package/src/apps/management/routes/invitations.test.ts +270 -3
  780. package/src/apps/management/routes/invitations.ts +185 -15
  781. package/src/apps/management/routes/invoicePreview.test.ts +549 -0
  782. package/src/apps/management/routes/me.test.ts +246 -5
  783. package/src/apps/management/routes/me.ts +7 -2
  784. package/src/apps/management/routes/members.test.ts +108 -0
  785. package/src/apps/management/routes/orgs.test.ts +191 -3
  786. package/src/apps/management/routes/orgs.ts +58 -11
  787. package/src/apps/management/routes/projects.test.ts +33 -3
  788. package/src/apps/management/routes/projects.ts +6 -1
  789. package/src/apps/management/routes/scopes.test.ts +30 -2
  790. package/src/apps/management/routes/scopes.ts +4 -1
  791. package/src/apps/management/routes/usage.test.ts +32 -0
  792. package/src/apps/management/routes/usage.ts +22 -4
  793. package/src/apps/management/routes/webhooks.test.ts +49 -26
  794. package/src/apps/management/routes/webhooks.ts +78 -22
  795. package/src/apps/mcp.test.ts +6 -6
  796. package/src/apps/mcp.ts +7 -7
  797. package/src/apps/mpp/App.ts +37 -7
  798. package/src/apps/mpp/Mpp.test.ts +49 -8
  799. package/src/apps/mpp/Mpp.zone.test.ts +219 -0
  800. package/src/apps/mpp/internal/Adapter.ts +34 -0
  801. package/src/apps/mpp/internal/Policy.test.ts +86 -31
  802. package/src/apps/mpp/internal/Policy.ts +49 -7
  803. package/src/apps/mpp/internal/Sponsorship.test.ts +207 -0
  804. package/src/apps/mpp/internal/Sponsorship.ts +9 -3
  805. package/src/apps/relay/App.test.ts +839 -64
  806. package/src/apps/relay/App.ts +148 -81
  807. package/src/apps/relay/App.zone-billing.test.ts +257 -0
  808. package/src/apps/relay/Sponsorships.test.ts +67 -4
  809. package/src/apps/relay/Sponsorships.ts +233 -32
  810. package/src/apps/relay/Sponsorships.zone.test.ts +102 -0
  811. package/src/apps/{funding → routes}/Access.ts +6 -6
  812. package/src/apps/routes/App.test.ts +165 -0
  813. package/src/apps/routes/App.ts +96 -0
  814. package/src/apps/{funding → routes}/Inventory.ts +2 -2
  815. package/src/apps/routes/index.ts +1 -0
  816. package/src/apps/{funding → routes}/routes/chains.test.ts +66 -66
  817. package/src/apps/{funding → routes}/routes/chains.ts +23 -23
  818. package/src/apps/{funding → routes}/routes/deposit-addresses.test.ts +1358 -458
  819. package/src/apps/{funding → routes}/routes/deposit-addresses.ts +566 -246
  820. package/src/apps/{funding → routes}/routes/providers.test.ts +27 -33
  821. package/src/apps/{funding → routes}/routes/providers.ts +23 -23
  822. package/src/apps/{funding → routes}/routes/quotes.test.ts +298 -41
  823. package/src/apps/{funding → routes}/routes/quotes.ts +57 -40
  824. package/src/apps/{funding → routes}/routes/transfers.test.ts +1100 -353
  825. package/src/apps/routes/routes/transfers.ts +1332 -0
  826. package/src/cli/Cli.test.ts +1 -1
  827. package/src/cli/commands/admin.test.ts +748 -1
  828. package/src/cli/commands/admin.ts +278 -0
  829. package/src/cloudflare.ts +52 -47
  830. package/src/db/Db.test.ts +245 -2
  831. package/src/db/Db.ts +1476 -34
  832. package/src/db/Schema.ts +729 -228
  833. package/src/db/tables/apiKeyAdmissionBootstraps.ts +4 -0
  834. package/src/db/tables/apiKeyAdmissions.ts +218 -0
  835. package/src/db/tables/apiKeyOwnerAdmissions.ts +4 -0
  836. package/src/db/tables/apiKeyOwnerTombstones.ts +81 -0
  837. package/src/db/tables/apiKeyRevocations.test.ts +74 -0
  838. package/src/db/tables/apiKeyRevocations.ts +121 -0
  839. package/src/db/tables/authAccounts.ts +105 -0
  840. package/src/db/tables/authSessions.ts +13 -0
  841. package/src/db/tables/authVerifications.ts +13 -0
  842. package/src/db/tables/invitations.ts +142 -45
  843. package/src/db/tables/memberships.ts +79 -3
  844. package/src/db/tables/organizations.test.ts +690 -13
  845. package/src/db/tables/organizations.ts +139 -55
  846. package/src/db/tables/projects.test.ts +16 -0
  847. package/src/db/tables/projects.ts +13 -3
  848. package/src/db/tables/requestUsage.ts +4 -1
  849. package/src/db/tables/rewardAccounts.ts +178 -0
  850. package/src/db/tables/rewardCampaignDistributors.ts +68 -0
  851. package/src/db/tables/rewardCampaigns.test.ts +1388 -0
  852. package/src/db/tables/rewardCampaigns.ts +647 -0
  853. package/src/db/tables/rewardCredits.ts +110 -0
  854. package/src/db/tables/rewardEligibilityAssociations.test.ts +271 -0
  855. package/src/db/tables/rewardEligibilityAssociations.ts +184 -0
  856. package/src/db/tables/rewardRuns.ts +514 -0
  857. package/src/db/tables/rewardTransactionAttempts.ts +272 -0
  858. package/src/db/tables/routesCatalog.test.ts +185 -0
  859. package/src/db/tables/routesCatalog.ts +163 -0
  860. package/src/db/tables/routesDepositAddresses.test.ts +1048 -0
  861. package/src/db/tables/routesDepositAddresses.ts +1008 -0
  862. package/src/db/tables/{fundingDepositRequestObservations.test.ts → routesDepositRequestObservations.test.ts} +13 -14
  863. package/src/db/tables/{fundingDepositRequestObservations.ts → routesDepositRequestObservations.ts} +10 -10
  864. package/src/db/tables/{fundingDeposits.test.ts → routesDeposits.test.ts} +316 -46
  865. package/src/db/tables/routesDeposits.ts +1062 -0
  866. package/src/db/tables/routesIdempotency.test.ts +796 -0
  867. package/src/db/tables/routesIdempotency.ts +496 -0
  868. package/src/db/tables/routesSubsidies.test.ts +120 -0
  869. package/src/db/tables/routesSubsidies.ts +71 -0
  870. package/src/db/tables/{fundingTransferEvents.ts → routesTransferEvents.ts} +4 -4
  871. package/src/db/tables/routesTransferSubsidies.ts +38 -0
  872. package/src/db/tables/routesTransferSubsidyNonces.ts +124 -0
  873. package/src/db/tables/routesTransferTransactions.test.ts +195 -0
  874. package/src/db/tables/{fundingTransferTransactions.ts → routesTransferTransactions.ts} +63 -18
  875. package/src/db/tables/routesTransfers.test.ts +338 -0
  876. package/src/db/tables/routesTransfers.ts +662 -0
  877. package/src/db/tables/sponsoredTransactions.test.ts +269 -45
  878. package/src/db/tables/sponsoredTransactions.ts +225 -65
  879. package/src/db/tables/sponsorshipAttributions.test.ts +160 -0
  880. package/src/db/tables/sponsorshipAttributions.ts +168 -0
  881. package/src/db/tables/sponsorshipReconciliationCursors.test.ts +115 -0
  882. package/src/db/tables/sponsorshipReconciliationCursors.ts +67 -0
  883. package/src/db/tables/stripeCustomers.test.ts +85 -0
  884. package/src/db/tables/stripeCustomers.ts +24 -0
  885. package/src/db/tables/users.test.ts +129 -0
  886. package/src/db/tables/users.ts +49 -3
  887. package/src/db/tables/webhookQueueEvents.ts +8 -1
  888. package/src/db/tables/webhookSubscriptions.ts +95 -20
  889. package/src/handlers/internal/executionError.ts +3 -4
  890. package/src/handlers/internal/multisig.ts +13 -816
  891. package/src/handlers/internal/sponsorship.ts +26 -10
  892. package/src/handlers/relay.test-d.ts +9 -1
  893. package/src/handlers/relay.test.ts +823 -3
  894. package/src/handlers/relay.ts +127 -107
  895. package/src/index.test-d.ts +7 -0
  896. package/src/index.ts +0 -17
  897. package/src/internal/AssetResponse.ts +26 -0
  898. package/src/internal/Auth.test.ts +1564 -9
  899. package/src/internal/Auth.ts +833 -239
  900. package/src/internal/BetterAuth.test.ts +242 -0
  901. package/src/internal/BetterAuth.ts +349 -0
  902. package/src/internal/Cache.ts +2 -0
  903. package/src/internal/EarnRates.test.ts +17 -0
  904. package/src/internal/EarnRates.ts +124 -31
  905. package/src/internal/EarnSharePrices.test.ts +182 -0
  906. package/src/internal/EarnSharePrices.ts +313 -0
  907. package/src/internal/EarnVaults.test.ts +21 -0
  908. package/src/internal/EarnVaults.ts +33 -11
  909. package/src/internal/Email.ts +54 -0
  910. package/src/internal/Idempotency.test.ts +2 -2
  911. package/src/internal/Log.test-d.ts +8 -7
  912. package/src/internal/Log.test.ts +114 -16
  913. package/src/internal/Log.ts +53 -40
  914. package/src/internal/MetricSink.test.ts +313 -26
  915. package/src/internal/MetricSink.ts +73 -8
  916. package/src/internal/Mpp.test.ts +31 -0
  917. package/src/internal/Mpp.ts +21 -24
  918. package/src/internal/OpenApi.ts +45 -12
  919. package/src/internal/Provider.test.ts +1 -1
  920. package/src/internal/Provider.ts +1 -1
  921. package/src/internal/RateLimit.test.ts +21 -3
  922. package/src/internal/RateLimit.ts +12 -1
  923. package/src/internal/Store.test-d.ts +1 -1
  924. package/src/internal/Store.test.ts +151 -8
  925. package/src/internal/Store.ts +76 -9
  926. package/src/internal/Tidx.test.ts +59 -8
  927. package/src/internal/Tidx.ts +86 -14
  928. package/src/internal/Timing.test.ts +77 -0
  929. package/src/internal/Timing.ts +83 -6
  930. package/src/internal/VercelOidc.test.ts +188 -0
  931. package/src/internal/VercelOidc.ts +193 -0
  932. package/src/internal/VerifiedTokens.test.ts +60 -6
  933. package/src/internal/VerifiedTokens.ts +21 -24
  934. package/src/internal/Viem.batch.test.ts +80 -0
  935. package/src/internal/Viem.test.ts +201 -2
  936. package/src/internal/Viem.ts +221 -25
  937. package/src/internal/Webhooks.test.ts +85 -6
  938. package/src/internal/Webhooks.ts +22 -4
  939. package/src/internal/ZoneRpc.ts +50 -0
  940. package/src/internal/exchange/Provider.test.ts +2 -2
  941. package/src/internal/index.test.ts +3 -1
  942. package/src/internal/index.ts +3 -1
  943. package/src/internal/rewards/Audit.ts +231 -0
  944. package/src/internal/rewards/Campaigns.test.ts +1234 -0
  945. package/src/internal/rewards/Campaigns.ts +1205 -0
  946. package/src/internal/rewards/Credits.ts +165 -0
  947. package/src/internal/rewards/Events.local.test.ts +113 -0
  948. package/src/internal/rewards/Events.test.ts +152 -0
  949. package/src/internal/rewards/Events.ts +468 -0
  950. package/src/internal/rewards/Projection.test.ts +681 -0
  951. package/src/internal/rewards/Projection.ts +987 -0
  952. package/src/internal/rewards/Rates.test.ts +171 -0
  953. package/src/internal/rewards/Rates.ts +110 -0
  954. package/src/internal/rewards/Read.test.ts +501 -0
  955. package/src/internal/rewards/Read.ts +476 -0
  956. package/src/internal/rewards/Runner.checkpoint.test.ts +80 -0
  957. package/src/internal/rewards/Runner.states.test.ts +188 -0
  958. package/src/internal/rewards/Runner.test.ts +90 -0
  959. package/src/internal/rewards/Runner.ts +2229 -0
  960. package/src/internal/rewards/Signer.test.ts +79 -0
  961. package/src/internal/rewards/Signer.ts +180 -0
  962. package/src/internal/rewards/index.ts +14 -0
  963. package/src/internal/{funding → routes}/Action.test.ts +63 -14
  964. package/src/internal/{funding → routes}/Action.ts +35 -8
  965. package/src/internal/{funding → routes}/Catalog.test.ts +3 -3
  966. package/src/internal/{funding → routes}/Catalog.ts +39 -39
  967. package/src/internal/{funding → routes}/Chain.test.ts +1 -1
  968. package/src/internal/{funding → routes}/Chain.ts +11 -11
  969. package/src/internal/{funding → routes}/Deposit.test.ts +1 -1
  970. package/src/internal/{funding → routes}/Deposit.ts +93 -45
  971. package/src/internal/{funding → routes}/DepositAddress.test.ts +11 -3
  972. package/src/internal/{funding → routes}/DepositAddress.ts +132 -53
  973. package/src/internal/{funding → routes}/DepositWebhook.test.ts +61 -18
  974. package/src/internal/{funding → routes}/DepositWebhook.ts +9 -9
  975. package/src/internal/routes/Economics.test.ts +42 -0
  976. package/src/internal/routes/Economics.ts +47 -0
  977. package/src/internal/{funding → routes}/Evidence.test.ts +6 -6
  978. package/src/internal/{funding → routes}/Evidence.ts +9 -9
  979. package/src/internal/routes/Observability.test.ts +636 -0
  980. package/src/internal/routes/Observability.ts +668 -0
  981. package/src/internal/{funding → routes}/Provider.test.ts +489 -153
  982. package/src/internal/{funding → routes}/Provider.ts +489 -186
  983. package/src/internal/{funding → routes}/Reconciliation.local.test.ts +84 -12
  984. package/src/internal/{funding → routes}/Reconciliation.test.ts +1213 -279
  985. package/src/internal/{funding → routes}/Reconciliation.ts +501 -203
  986. package/src/internal/routes/Reconciliation.unattributed.test.ts +250 -0
  987. package/src/internal/{funding → routes}/Route.ts +7 -7
  988. package/src/internal/{funding → routes}/SourceObservation.test.ts +13 -14
  989. package/src/internal/{funding → routes}/SourceObservation.ts +13 -13
  990. package/src/internal/{funding → routes}/Subsidy.local.test.ts +7 -7
  991. package/src/internal/routes/Subsidy.test.ts +169 -0
  992. package/src/internal/{funding → routes}/Subsidy.ts +86 -6
  993. package/src/internal/{funding → routes}/Token.test.ts +1 -1
  994. package/src/internal/{funding → routes}/Token.ts +5 -5
  995. package/src/internal/routes/Transfer.test.ts +1199 -0
  996. package/src/internal/routes/Transfer.ts +1206 -0
  997. package/src/internal/routes/TransferReconciliation.test.ts +731 -0
  998. package/src/internal/routes/TransferReconciliation.ts +527 -0
  999. package/src/internal/routes/TransferSubsidy.test.ts +172 -0
  1000. package/src/internal/routes/TransferSubsidy.ts +447 -0
  1001. package/src/internal/{funding → routes}/TransferWebhook.test.ts +13 -13
  1002. package/src/internal/{funding → routes}/TransferWebhook.ts +7 -7
  1003. package/src/internal/{funding → routes}/index.test.ts +5 -3
  1004. package/src/internal/{funding → routes}/index.ts +2 -0
  1005. package/src/internal/{funding → routes}/providers/across.ts +16 -16
  1006. package/src/internal/{funding → routes}/providers/index.test.ts +157 -44
  1007. package/src/internal/{funding → routes}/providers/relay.test.ts +165 -32
  1008. package/src/internal/{funding → routes}/providers/relay.ts +228 -121
  1009. package/src/internal/{funding → routes}/providers/rhino.ts +16 -16
  1010. package/src/internal/{funding → routes}/providers/squid.ts +17 -17
  1011. package/src/internal/routes/providers/stargate.test.ts +728 -0
  1012. package/src/internal/routes/providers/stargate.ts +1276 -0
  1013. package/src/internal/{funding → routes}/providers/symbiosis.ts +64 -24
  1014. package/src/internal/webhookDestinations/slack.ts +10 -10
  1015. package/src/providers/index.ts +13 -13
  1016. package/src/server.ts +18 -0
  1017. package/dist/apps/funding/Access.d.ts.map +0 -1
  1018. package/dist/apps/funding/Access.js.map +0 -1
  1019. package/dist/apps/funding/App.js.map +0 -1
  1020. package/dist/apps/funding/Inventory.d.ts.map +0 -1
  1021. package/dist/apps/funding/Inventory.js.map +0 -1
  1022. package/dist/apps/funding/ProviderAttempts.d.ts +0 -5
  1023. package/dist/apps/funding/ProviderAttempts.d.ts.map +0 -1
  1024. package/dist/apps/funding/ProviderAttempts.js +0 -24
  1025. package/dist/apps/funding/ProviderAttempts.js.map +0 -1
  1026. package/dist/apps/funding/index.d.ts +0 -2
  1027. package/dist/apps/funding/index.d.ts.map +0 -1
  1028. package/dist/apps/funding/index.js +0 -2
  1029. package/dist/apps/funding/index.js.map +0 -1
  1030. package/dist/apps/funding/routes/chains.d.ts.map +0 -1
  1031. package/dist/apps/funding/routes/chains.js.map +0 -1
  1032. package/dist/apps/funding/routes/deposit-addresses.d.ts.map +0 -1
  1033. package/dist/apps/funding/routes/deposit-addresses.js.map +0 -1
  1034. package/dist/apps/funding/routes/providers.d.ts.map +0 -1
  1035. package/dist/apps/funding/routes/providers.js +0 -57
  1036. package/dist/apps/funding/routes/providers.js.map +0 -1
  1037. package/dist/apps/funding/routes/quotes.d.ts.map +0 -1
  1038. package/dist/apps/funding/routes/quotes.js.map +0 -1
  1039. package/dist/apps/funding/routes/transfers.d.ts.map +0 -1
  1040. package/dist/apps/funding/routes/transfers.js +0 -828
  1041. package/dist/apps/funding/routes/transfers.js.map +0 -1
  1042. package/dist/db/tables/fundingCatalog.d.ts +0 -58
  1043. package/dist/db/tables/fundingCatalog.d.ts.map +0 -1
  1044. package/dist/db/tables/fundingCatalog.js.map +0 -1
  1045. package/dist/db/tables/fundingDepositAddresses.d.ts +0 -192
  1046. package/dist/db/tables/fundingDepositAddresses.d.ts.map +0 -1
  1047. package/dist/db/tables/fundingDepositAddresses.js +0 -235
  1048. package/dist/db/tables/fundingDepositAddresses.js.map +0 -1
  1049. package/dist/db/tables/fundingDepositRequestObservations.d.ts.map +0 -1
  1050. package/dist/db/tables/fundingDepositRequestObservations.js.map +0 -1
  1051. package/dist/db/tables/fundingDeposits.d.ts.map +0 -1
  1052. package/dist/db/tables/fundingDeposits.js +0 -295
  1053. package/dist/db/tables/fundingDeposits.js.map +0 -1
  1054. package/dist/db/tables/fundingIdempotency.d.ts +0 -91
  1055. package/dist/db/tables/fundingIdempotency.d.ts.map +0 -1
  1056. package/dist/db/tables/fundingIdempotency.js +0 -103
  1057. package/dist/db/tables/fundingIdempotency.js.map +0 -1
  1058. package/dist/db/tables/fundingTransferEvents.d.ts.map +0 -1
  1059. package/dist/db/tables/fundingTransferEvents.js.map +0 -1
  1060. package/dist/db/tables/fundingTransferTransactions.d.ts +0 -53
  1061. package/dist/db/tables/fundingTransferTransactions.d.ts.map +0 -1
  1062. package/dist/db/tables/fundingTransferTransactions.js.map +0 -1
  1063. package/dist/db/tables/fundingTransfers.d.ts +0 -99
  1064. package/dist/db/tables/fundingTransfers.d.ts.map +0 -1
  1065. package/dist/db/tables/fundingTransfers.js +0 -110
  1066. package/dist/db/tables/fundingTransfers.js.map +0 -1
  1067. package/dist/internal/funding/Action.d.ts.map +0 -1
  1068. package/dist/internal/funding/Action.js.map +0 -1
  1069. package/dist/internal/funding/Catalog.d.ts.map +0 -1
  1070. package/dist/internal/funding/Catalog.js.map +0 -1
  1071. package/dist/internal/funding/Chain.d.ts.map +0 -1
  1072. package/dist/internal/funding/Chain.js.map +0 -1
  1073. package/dist/internal/funding/Deposit.d.ts.map +0 -1
  1074. package/dist/internal/funding/Deposit.js.map +0 -1
  1075. package/dist/internal/funding/DepositAddress.d.ts.map +0 -1
  1076. package/dist/internal/funding/DepositAddress.js.map +0 -1
  1077. package/dist/internal/funding/DepositWebhook.d.ts.map +0 -1
  1078. package/dist/internal/funding/DepositWebhook.js.map +0 -1
  1079. package/dist/internal/funding/Evidence.d.ts.map +0 -1
  1080. package/dist/internal/funding/Evidence.js.map +0 -1
  1081. package/dist/internal/funding/Provider.d.ts.map +0 -1
  1082. package/dist/internal/funding/Provider.js.map +0 -1
  1083. package/dist/internal/funding/Reconciliation.d.ts.map +0 -1
  1084. package/dist/internal/funding/Reconciliation.js.map +0 -1
  1085. package/dist/internal/funding/Route.d.ts +0 -21
  1086. package/dist/internal/funding/Route.d.ts.map +0 -1
  1087. package/dist/internal/funding/Route.js.map +0 -1
  1088. package/dist/internal/funding/SourceObservation.d.ts.map +0 -1
  1089. package/dist/internal/funding/SourceObservation.js.map +0 -1
  1090. package/dist/internal/funding/Subsidy.d.ts.map +0 -1
  1091. package/dist/internal/funding/Subsidy.js.map +0 -1
  1092. package/dist/internal/funding/Token.d.ts.map +0 -1
  1093. package/dist/internal/funding/Token.js.map +0 -1
  1094. package/dist/internal/funding/Transfer.d.ts.map +0 -1
  1095. package/dist/internal/funding/Transfer.js +0 -462
  1096. package/dist/internal/funding/Transfer.js.map +0 -1
  1097. package/dist/internal/funding/TransferReconciliation.d.ts.map +0 -1
  1098. package/dist/internal/funding/TransferReconciliation.js +0 -192
  1099. package/dist/internal/funding/TransferReconciliation.js.map +0 -1
  1100. package/dist/internal/funding/TransferWebhook.d.ts.map +0 -1
  1101. package/dist/internal/funding/TransferWebhook.js.map +0 -1
  1102. package/dist/internal/funding/index.d.ts.map +0 -1
  1103. package/dist/internal/funding/index.js.map +0 -1
  1104. package/dist/internal/funding/providers/across.d.ts.map +0 -1
  1105. package/dist/internal/funding/providers/across.js.map +0 -1
  1106. package/dist/internal/funding/providers/relay.d.ts.map +0 -1
  1107. package/dist/internal/funding/providers/relay.js.map +0 -1
  1108. package/dist/internal/funding/providers/rhino.d.ts.map +0 -1
  1109. package/dist/internal/funding/providers/rhino.js.map +0 -1
  1110. package/dist/internal/funding/providers/squid.d.ts.map +0 -1
  1111. package/dist/internal/funding/providers/squid.js.map +0 -1
  1112. package/dist/internal/funding/providers/stargate.d.ts.map +0 -1
  1113. package/dist/internal/funding/providers/stargate.js +0 -579
  1114. package/dist/internal/funding/providers/stargate.js.map +0 -1
  1115. package/dist/internal/funding/providers/symbiosis.d.ts.map +0 -1
  1116. package/dist/internal/funding/providers/symbiosis.js.map +0 -1
  1117. package/src/apps/funding/App.test.ts +0 -78
  1118. package/src/apps/funding/App.ts +0 -88
  1119. package/src/apps/funding/ProviderAttempts.ts +0 -26
  1120. package/src/apps/funding/index.ts +0 -1
  1121. package/src/apps/funding/routes/transfers.ts +0 -987
  1122. package/src/db/tables/fundingCatalog.test.ts +0 -122
  1123. package/src/db/tables/fundingCatalog.ts +0 -163
  1124. package/src/db/tables/fundingDepositAddresses.test.ts +0 -608
  1125. package/src/db/tables/fundingDepositAddresses.ts +0 -443
  1126. package/src/db/tables/fundingDeposits.ts +0 -572
  1127. package/src/db/tables/fundingIdempotency.test.ts +0 -182
  1128. package/src/db/tables/fundingIdempotency.ts +0 -180
  1129. package/src/db/tables/fundingTransferTransactions.test.ts +0 -112
  1130. package/src/db/tables/fundingTransfers.test.ts +0 -115
  1131. package/src/db/tables/fundingTransfers.ts +0 -189
  1132. package/src/handlers/internal/multisig.test.ts +0 -818
  1133. package/src/internal/funding/Subsidy.test.ts +0 -75
  1134. package/src/internal/funding/Transfer.test.ts +0 -524
  1135. package/src/internal/funding/Transfer.ts +0 -762
  1136. package/src/internal/funding/TransferReconciliation.test.ts +0 -147
  1137. package/src/internal/funding/TransferReconciliation.ts +0 -264
  1138. package/src/internal/funding/providers/stargate.test.ts +0 -328
  1139. package/src/internal/funding/providers/stargate.ts +0 -856
  1140. /package/dist/apps/{funding → routes}/Inventory.d.ts +0 -0
  1141. /package/src/internal/{funding → routes}/Route.test.ts +0 -0
@@ -1,11 +1,19 @@
1
+ import { serve } from '@hono/node-server'
2
+ import * as Accounts from 'accounts/server'
1
3
  import { Hono, type Context } from 'hono'
2
4
  import { requestId } from 'hono/request-id'
3
- import { Challenge, Receipt } from 'mppx'
5
+ import { exportJWK, generateKeyPair } from 'jose'
6
+ import { Challenge, Receipt, Store as MppStore } from 'mppx'
4
7
  import { Mppx, tempo } from 'mppx/hono'
5
- import type { Session } from 'mppx/tempo'
6
- import { RateLimit, Store } from 'tapimo'
7
- import { Actions } from 'viem/tempo'
8
+ import { Session } from 'mppx/tempo'
9
+ import { RateLimit, Store } from 'tapimo/server'
10
+ import { createClient, custom, decodeFunctionData, isAddressEqual, maxUint256 } from 'viem'
11
+ import { getTransaction } from 'viem/actions'
12
+ import { Actions, Transaction } from 'viem/tempo'
13
+ import { generatePrivateKey, privateKeyToAccount } from 'viem/accounts'
14
+ import * as App from '../App.js'
8
15
  import * as ApiKey from '../ApiKey.js'
16
+ import * as Management from '../apps/management/App.js'
9
17
  import type * as Db from '../db/Db.js'
10
18
  import * as Memberships from '../db/tables/memberships.js'
11
19
  import * as Organizations from '../db/tables/organizations.js'
@@ -1009,6 +1017,7 @@ describe('require', () => {
1009
1017
  })
1010
1018
 
1011
1019
  expect(response.status).toBe(200)
1020
+ expect(consume).toHaveBeenCalledTimes(1)
1012
1021
  expect(consume).toHaveBeenCalledWith({
1013
1022
  key: 'mpp:api_key:key_test',
1014
1023
  limit: { limit: 100, period: 'minute' },
@@ -1310,8 +1319,8 @@ describe('require', () => {
1310
1319
  })
1311
1320
  })
1312
1321
 
1313
- test('paid retry opens a funded on-chain channel', async () => {
1314
- const mpp = createMppServer()
1322
+ test('paid retry settles the accepted voucher on-chain', async () => {
1323
+ const mpp = createMppServer({ settlementSchedule: { units: 1 } })
1315
1324
  const app = createApp({
1316
1325
  auth: {
1317
1326
  apiKey: { resolve: TestApp.resolver({ keys: [{ ...key, token }] }) },
@@ -1340,9 +1349,150 @@ describe('require', () => {
1340
1349
  })
1341
1350
  // The client deposits the request amount when no deposit is suggested.
1342
1351
  expect(state.deposit).toBe(1_000_000n)
1343
- // No settlement schedule configured, so nothing settles inline.
1344
- expect(state.settled).toBe(0n)
1352
+ expect(state.settled).toBe(BigInt(receipt.acceptedCumulative))
1345
1353
  expect(state.closeRequestedAt).toBe(0)
1354
+
1355
+ const transaction = await getTransaction(Tempo.client, { hash: receipt.txHash! })
1356
+ expect(transaction.nonceKey).toBe(maxUint256)
1357
+ expect(transaction.nonce).toBe(0)
1358
+ })
1359
+
1360
+ test('settles independent session channels concurrently', async () => {
1361
+ const mpp = createMppServer({ settlementSchedule: { units: 1 } })
1362
+ const app = createApp({
1363
+ auth: {
1364
+ apiKey: { resolve: TestApp.resolver({ keys: [{ ...key, token }] }) },
1365
+ mpp,
1366
+ rateLimit: overQuotaExceptMpp(),
1367
+ },
1368
+ policy: {
1369
+ mpp: { session: { amount: '1', description: 'Protected data' } },
1370
+ public: { rateLimit: { limit: 1, period: 'minute' } },
1371
+ },
1372
+ })
1373
+
1374
+ const responses = await Promise.all([
1375
+ createMppClient(app).fetch('http://tempo-api.test/protected'),
1376
+ createMppClient(app).fetch('http://tempo-api.test/protected'),
1377
+ ])
1378
+ const receipts = responses.map(sessionReceipt)
1379
+ const transactions = await Promise.all(
1380
+ receipts.map((receipt) => getTransaction(Tempo.client, { hash: receipt.txHash! })),
1381
+ )
1382
+
1383
+ expect(responses.map((response) => response.status)).toEqual([200, 200])
1384
+ expect(receipts[0]!.channelId).not.toBe(receipts[1]!.channelId)
1385
+ expect(transactions.map((transaction) => [transaction.nonceKey, transaction.nonce])).toEqual([
1386
+ [maxUint256, 0],
1387
+ [maxUint256, 0],
1388
+ ])
1389
+ })
1390
+
1391
+ test('rolls back the request charge when scheduled settlement fails', async () => {
1392
+ const failures: Session.Server.SessionSettlementFailureContext[] = []
1393
+ const store = MppStore.memory()
1394
+ const mpp = createMppServer({
1395
+ account: Tempo.accounts[3],
1396
+ onSessionSettlementFailure: (context) => {
1397
+ failures.push(context)
1398
+ },
1399
+ recipient: Tempo.accounts[3].address,
1400
+ settlementSchedule: { units: 1 },
1401
+ store,
1402
+ })
1403
+ const app = createApp({
1404
+ auth: {
1405
+ apiKey: { resolve: TestApp.resolver({ keys: [{ ...key, token }] }) },
1406
+ mpp,
1407
+ rateLimit: overQuotaExceptMpp(),
1408
+ },
1409
+ policy: {
1410
+ mpp: { session: { amount: '1', description: 'Protected data' } },
1411
+ public: { rateLimit: { limit: 1, period: 'minute' } },
1412
+ },
1413
+ })
1414
+
1415
+ const response = await createMppClient(app).fetch('http://tempo-api.test/protected')
1416
+
1417
+ expect(response.status).toBe(402)
1418
+ expect(failures.length).toBeGreaterThan(0)
1419
+ for (const failure of failures) {
1420
+ expect(failure).toMatchObject({
1421
+ chainId: Tempo.chain.id,
1422
+ outcome: 'failed',
1423
+ stage: 'settlement',
1424
+ trigger: 'scheduled',
1425
+ })
1426
+ expect(failure.error).toBeInstanceOf(Error)
1427
+ }
1428
+ const channels = Session.Server.ChannelStore.fromStore(store)
1429
+ for (const channelId of new Set(failures.map(({ channelId }) => channelId))) {
1430
+ const channel = await channels.getChannel(channelId)
1431
+ expect({ spent: channel?.spent, units: channel?.units }).toEqual({ spent: 0n, units: 0 })
1432
+ }
1433
+ })
1434
+
1435
+ test('leaves request charges untouched when settlement submission is ambiguous', async () => {
1436
+ const failures: Session.Server.SessionSettlementFailureContext[] = []
1437
+ const store = MppStore.memory()
1438
+ const client = createClient({
1439
+ account: Tempo.accounts[2],
1440
+ chain: Tempo.chain,
1441
+ transport: custom({
1442
+ request(parameters) {
1443
+ if (parameters.method === 'eth_sendRawTransaction') {
1444
+ const transaction = Transaction.deserialize(parameters.params[0] as `0x76${string}`)
1445
+ const isSettlement = transaction.calls.some(
1446
+ (call) =>
1447
+ call.to &&
1448
+ call.data &&
1449
+ isAddressEqual(call.to, Session.Precompile.Protocol.tip20ChannelEscrow) &&
1450
+ decodeFunctionData({ abi: Session.Precompile.escrowAbi, data: call.data })
1451
+ .functionName === 'settle',
1452
+ )
1453
+ if (isSettlement) throw new Error('settlement submission timed out')
1454
+ }
1455
+ return Tempo.client.request(parameters as never)
1456
+ },
1457
+ }),
1458
+ })
1459
+ const mpp = createMppServer({
1460
+ getClient: () => client,
1461
+ onSessionSettlementFailure: (context) => {
1462
+ failures.push(context)
1463
+ },
1464
+ settlementSchedule: { units: 1 },
1465
+ store,
1466
+ })
1467
+ const app = createApp({
1468
+ auth: {
1469
+ apiKey: { resolve: TestApp.resolver({ keys: [{ ...key, token }] }) },
1470
+ mpp,
1471
+ rateLimit: overQuotaExceptMpp(),
1472
+ },
1473
+ policy: {
1474
+ mpp: { session: { amount: '1', description: 'Protected data' } },
1475
+ public: { rateLimit: { limit: 1, period: 'minute' } },
1476
+ },
1477
+ })
1478
+
1479
+ const response = await createMppClient(app).fetch('http://tempo-api.test/protected')
1480
+
1481
+ expect(response.status).toBe(402)
1482
+ expect(failures.length).toBeGreaterThan(0)
1483
+ const channels = Session.Server.ChannelStore.fromStore(store)
1484
+ for (const failure of failures) {
1485
+ expect(failure).toMatchObject({
1486
+ chainId: Tempo.chain.id,
1487
+ outcome: 'ambiguous',
1488
+ stage: 'settlement',
1489
+ trigger: 'scheduled',
1490
+ })
1491
+ await expect(channels.getChannel(failure.channelId)).resolves.toMatchObject({
1492
+ spent: 0n,
1493
+ units: 0,
1494
+ })
1495
+ }
1346
1496
  })
1347
1497
 
1348
1498
  test('reuses the session channel across paid requests', async () => {
@@ -2224,6 +2374,7 @@ function createMppServer(options: createMppServer.Options = {}) {
2224
2374
  return Mppx.create({
2225
2375
  methods: [
2226
2376
  tempo.session({
2377
+ account: Tempo.accounts[2],
2227
2378
  bootstrap: false,
2228
2379
  chainId: Tempo.chain.id,
2229
2380
  currency: Tempo.currency,
@@ -2242,7 +2393,13 @@ function createMppServer(options: createMppServer.Options = {}) {
2242
2393
  declare namespace createMppServer {
2243
2394
  type Options = Pick<
2244
2395
  NonNullable<Parameters<typeof tempo.session>[0]>,
2245
- 'chainId' | 'getClient' | 'store'
2396
+ | 'account'
2397
+ | 'chainId'
2398
+ | 'getClient'
2399
+ | 'onSessionSettlementFailure'
2400
+ | 'recipient'
2401
+ | 'settlementSchedule'
2402
+ | 'store'
2246
2403
  >
2247
2404
  }
2248
2405
 
@@ -2366,3 +2523,1401 @@ function normalizePaymentPayer(value: unknown) {
2366
2523
  function isRecord(value: unknown): value is Record<string, unknown> {
2367
2524
  return !!value && typeof value === 'object' && !Array.isArray(value)
2368
2525
  }
2526
+
2527
+ const origin = 'https://api.example.com'
2528
+ const secret = 'test-better-auth-secret-at-least-32-characters'
2529
+
2530
+ describe('Google sign-in', () => {
2531
+ test('resolves a Google session without an email sender', async () => {
2532
+ const db = TestApp.database()
2533
+ const app = TestApp.create({
2534
+ db,
2535
+ session: {
2536
+ google: {
2537
+ clientId: 'google-client-id',
2538
+ clientSecret: 'google-client-secret',
2539
+ },
2540
+ secret,
2541
+ wallet: { origin },
2542
+ },
2543
+ })
2544
+ const now = new Date()
2545
+ const sessionToken = 'google-session-token'
2546
+
2547
+ try {
2548
+ await db.kysely
2549
+ .insertInto('users')
2550
+ .values({
2551
+ address: null,
2552
+ createdAt: now.toISOString(),
2553
+ email: 'developer@example.com',
2554
+ emailVerified: true,
2555
+ id: 'usr_google',
2556
+ image: null,
2557
+ name: 'Tempo Developer',
2558
+ updatedAt: now.toISOString(),
2559
+ })
2560
+ .execute()
2561
+ await db.kysely
2562
+ .insertInto('auth_sessions')
2563
+ .values({
2564
+ createdAt: now,
2565
+ expiresAt: new Date(now.getTime() + 60_000),
2566
+ id: 'ses_google',
2567
+ ipAddress: null,
2568
+ provider: 'google',
2569
+ token: sessionToken,
2570
+ updatedAt: now,
2571
+ userAgent: null,
2572
+ userId: 'usr_google',
2573
+ })
2574
+ .execute()
2575
+ const sessionKey = await crypto.subtle.importKey(
2576
+ 'raw',
2577
+ new TextEncoder().encode(secret),
2578
+ { hash: 'SHA-256', name: 'HMAC' },
2579
+ false,
2580
+ ['sign'],
2581
+ )
2582
+ const signature = await crypto.subtle.sign(
2583
+ 'HMAC',
2584
+ sessionKey,
2585
+ new TextEncoder().encode(sessionToken),
2586
+ )
2587
+ const cookie = `${sessionToken}.${btoa(String.fromCharCode(...new Uint8Array(signature)))}`
2588
+
2589
+ const response = await app.request(`${origin}/v1/me`, {
2590
+ headers: { cookie: `tempo_auth.session_token=${cookie}` },
2591
+ })
2592
+
2593
+ expect(response.status).toBe(200)
2594
+ expect(await response.json()).toMatchObject({
2595
+ email: 'developer@example.com',
2596
+ id: 'usr_google',
2597
+ })
2598
+ } finally {
2599
+ await db.close()
2600
+ }
2601
+ })
2602
+
2603
+ test('uses a trusted forwarded Console origin for its callback', async () => {
2604
+ const consoleOrigin = 'https://console.example.com'
2605
+ const app = TestApp.create({
2606
+ session: {
2607
+ google: {
2608
+ clientId: 'google-client-id',
2609
+ clientSecret: 'google-client-secret',
2610
+ },
2611
+ secret,
2612
+ trustedOrigins: [consoleOrigin],
2613
+ wallet: { origin },
2614
+ },
2615
+ })
2616
+ const response = await app.request(`${origin}/v1/auth/sign-in/social`, {
2617
+ body: JSON.stringify({ callbackURL: `${consoleOrigin}/`, provider: 'google' }),
2618
+ headers: {
2619
+ 'content-type': 'application/json',
2620
+ origin: consoleOrigin,
2621
+ 'x-forwarded-host': 'console.example.com',
2622
+ 'x-forwarded-proto': 'https',
2623
+ },
2624
+ method: 'POST',
2625
+ })
2626
+
2627
+ expect(response.status).toBe(200)
2628
+ const body = (await response.json()) as { url: string }
2629
+ expect(new URL(body.url).searchParams.get('redirect_uri')).toBe(
2630
+ `${consoleOrigin}/v1/auth/callback/google`,
2631
+ )
2632
+ })
2633
+ })
2634
+
2635
+ describe('email OTP', () => {
2636
+ test.each([
2637
+ {
2638
+ body: '{',
2639
+ name: 'malformed challenge JSON',
2640
+ path: '/v1/auth/siwe/challenge',
2641
+ },
2642
+ {
2643
+ body: JSON.stringify([]),
2644
+ name: 'schema-invalid challenge JSON',
2645
+ path: '/v1/auth/siwe/challenge',
2646
+ },
2647
+ { body: JSON.stringify({}), name: 'schema-invalid verification JSON', path: '/v1/auth/siwe' },
2648
+ ])('validates $name', async ({ body, path }) => {
2649
+ const app = TestApp.create({ session: { secret, wallet: { origin } } })
2650
+
2651
+ const response = await app.request(`${origin}${path}`, {
2652
+ body,
2653
+ headers: { 'content-type': 'application/json' },
2654
+ method: 'POST',
2655
+ })
2656
+
2657
+ expect(response.status).toBe(400)
2658
+ expect(await response.json()).toMatchObject({
2659
+ error: { code: 'body_invalid', message: 'Invalid request body' },
2660
+ })
2661
+ })
2662
+
2663
+ test('leaves unmatched auth requests available to later routes', async () => {
2664
+ const app = TestApp.create({
2665
+ session: { secret, wallet: { origin } },
2666
+ }).route(
2667
+ '/',
2668
+ new Hono().post('/v1/auth/dev-oidc/token', async (c) =>
2669
+ c.json({ idToken: 'test', request: await c.req.json() }),
2670
+ ),
2671
+ )
2672
+
2673
+ const response = await app.request(
2674
+ '/v1/auth/dev-oidc/token',
2675
+ json({ subject: 'developer@example.com' }),
2676
+ )
2677
+
2678
+ expect(response.status).toBe(200)
2679
+ expect(await response.json()).toEqual({
2680
+ idToken: 'test',
2681
+ request: { subject: 'developer@example.com' },
2682
+ })
2683
+ })
2684
+
2685
+ test('keeps Better Auth routes out of OpenAPI while using the session scheme', async () => {
2686
+ const app = TestApp.create({
2687
+ session: { secret, wallet: { origin } },
2688
+ })
2689
+ const spec = await (await app.request('/openapi.json')).json()
2690
+
2691
+ expect(spec.paths['/v1/auth/email-otp/send-verification-otp']).toBeUndefined()
2692
+ expect(spec.paths['/v1/auth/sign-in/email-otp']).toBeUndefined()
2693
+ expect(spec.paths['/v1/auth/sign-out']).toBeUndefined()
2694
+ expect(spec.paths['/v1/auth/email-otp']).toBeUndefined()
2695
+ expect(spec.paths['/v1/auth/siwe/logout']).toBeUndefined()
2696
+ expect(spec.components.securitySchemes.emailSession).toBeUndefined()
2697
+ expect(spec.components.securitySchemes.session).toMatchObject({
2698
+ in: 'header',
2699
+ name: 'Cookie',
2700
+ type: 'apiKey',
2701
+ })
2702
+ expect(spec.paths['/v1/auth/logout'].post.responses['204']).toBeDefined()
2703
+ expect(spec.paths['/v1/auth/logout'].post.security).toEqual([])
2704
+ expect(spec.paths['/v1/me'].get.security).toContainEqual({ session: [] })
2705
+ })
2706
+
2707
+ test('sends email OTP without the management group', async () => {
2708
+ const db = TestApp.database()
2709
+ const messages: App.Email.Message[] = []
2710
+ const app = App.create({
2711
+ auth: { session: { secret, wallet: { origin } } },
2712
+ db,
2713
+ email: {
2714
+ from: 'noreply@example.com',
2715
+ send: async (message) => void messages.push(message),
2716
+ },
2717
+ kv: { store: Store.memory() },
2718
+ })
2719
+
2720
+ try {
2721
+ const response = await app.request(
2722
+ `${origin}/v1/auth/email-otp/send-verification-otp`,
2723
+ json({ email: 'developer@example.com', type: 'sign-in' }),
2724
+ )
2725
+
2726
+ expect(response.status).toBe(200)
2727
+ expect(messages).toHaveLength(1)
2728
+ } finally {
2729
+ await db.close()
2730
+ }
2731
+ })
2732
+
2733
+ test('accepts the legacy management email option', async () => {
2734
+ const db = TestApp.database()
2735
+ const messages: App.Email.Message[] = []
2736
+ const app = App.create({
2737
+ auth: { session: { secret, wallet: { origin } } },
2738
+ db,
2739
+ kv: { store: Store.memory() },
2740
+ }).route(
2741
+ '/',
2742
+ Management.management({
2743
+ email: {
2744
+ from: 'noreply@example.com',
2745
+ send: async (message) => void messages.push(message),
2746
+ },
2747
+ }),
2748
+ )
2749
+
2750
+ try {
2751
+ const response = await app.request(
2752
+ `${origin}/v1/auth/email-otp/send-verification-otp`,
2753
+ json({ email: 'developer@example.com', type: 'sign-in' }),
2754
+ )
2755
+
2756
+ expect(response.status).toBe(200)
2757
+ expect(messages).toHaveLength(1)
2758
+ } finally {
2759
+ await db.close()
2760
+ }
2761
+ })
2762
+
2763
+ test('creates a canonical Tempo user and Better Auth session', async () => {
2764
+ const db = TestApp.database()
2765
+ const messages: App.Email.Message[] = []
2766
+ const app = TestApp.create({
2767
+ db,
2768
+ email: {
2769
+ from: 'noreply@example.com',
2770
+ send: async (message) => void messages.push(message),
2771
+ },
2772
+ session: {
2773
+ secret,
2774
+ wallet: { origin },
2775
+ },
2776
+ })
2777
+
2778
+ try {
2779
+ const sent = await app.request(
2780
+ `${origin}/v1/auth/email-otp/send-verification-otp`,
2781
+ json({ email: 'Developer@Example.com', type: 'sign-in' }),
2782
+ )
2783
+ expect(sent.status).toBe(200)
2784
+ expect(await sent.json()).toEqual({ success: true })
2785
+ expect(messages).toHaveLength(1)
2786
+ const otp = messages[0]!.text.match(/\b\d{6}\b/)?.[0]
2787
+ expect(otp).toBeDefined()
2788
+ expect(messages[0]).toMatchObject({
2789
+ from: 'noreply@example.com',
2790
+ subject: `${otp} is your Tempo sign-in code`,
2791
+ to: 'developer@example.com',
2792
+ })
2793
+
2794
+ const verification = await db.kysely
2795
+ .selectFrom('auth_verifications')
2796
+ .select(['value'])
2797
+ .executeTakeFirstOrThrow()
2798
+ expect(verification.value).not.toContain(otp!)
2799
+
2800
+ const verified = await app.request(
2801
+ `${origin}/v1/auth/sign-in/email-otp`,
2802
+ json({ email: 'developer@example.com', otp }),
2803
+ )
2804
+ expect(verified.status).toBe(200)
2805
+ expect(await verified.json()).toMatchObject({ user: { email: 'developer@example.com' } })
2806
+
2807
+ const existing = await Users.getByEmail(db, 'developer@example.com')
2808
+ expect(existing).toBeDefined()
2809
+
2810
+ const setCookie = verified.headers.get('set-cookie')
2811
+ expect(setCookie).toContain('tempo_auth.session_token=')
2812
+ expect(setCookie).toContain('Max-Age=86400')
2813
+ expect(setCookie).toContain('Path=/')
2814
+ expect(setCookie).toContain('HttpOnly')
2815
+ expect(setCookie).toContain('Secure')
2816
+ expect(setCookie).toContain('SameSite=Lax')
2817
+
2818
+ const session = await app.request(`${origin}/v1/auth/get-session`, {
2819
+ headers: { cookie: setCookie!.split(';', 1)[0]! },
2820
+ })
2821
+ expect(await session.json()).toMatchObject({ session: { provider: 'email' } })
2822
+
2823
+ const response = await app.request(`${origin}/v1/me`, {
2824
+ headers: { cookie: setCookie!.split(';', 1)[0]! },
2825
+ })
2826
+ expect(response.status).toBe(200)
2827
+ expect(await response.json()).toMatchObject({
2828
+ email: 'developer@example.com',
2829
+ id: existing!.id,
2830
+ })
2831
+
2832
+ const users = await db.kysely.selectFrom('users').selectAll().execute()
2833
+ expect(users).toHaveLength(1)
2834
+ expect(users[0]).toMatchObject({
2835
+ email: 'developer@example.com',
2836
+ emailVerified: true,
2837
+ })
2838
+ expect(users[0]!.createdAt).toMatch(/Z$/)
2839
+ expect(users[0]!.updatedAt).toMatch(/Z$/)
2840
+ } finally {
2841
+ await db.close()
2842
+ }
2843
+ })
2844
+
2845
+ test('selects the oldest user for a duplicate email', async () => {
2846
+ const db = TestApp.database()
2847
+ const messages: App.Email.Message[] = []
2848
+ const app = TestApp.create({
2849
+ db,
2850
+ email: {
2851
+ from: 'noreply@example.com',
2852
+ send: async (message) => void messages.push(message),
2853
+ },
2854
+ session: { secret, wallet: { origin } },
2855
+ })
2856
+
2857
+ try {
2858
+ await db.kysely
2859
+ .insertInto('users')
2860
+ .values([
2861
+ {
2862
+ address: null,
2863
+ createdAt: '2025-01-01T00:00:00.000Z',
2864
+ email: 'developer@example.com',
2865
+ emailVerified: true,
2866
+ id: 'usr_duplicate_oldest',
2867
+ image: null,
2868
+ name: 'Oldest user',
2869
+ updatedAt: '2025-01-01T00:00:00.000Z',
2870
+ },
2871
+ {
2872
+ address: null,
2873
+ createdAt: '2026-01-01T00:00:00.000Z',
2874
+ email: 'developer@example.com',
2875
+ emailVerified: true,
2876
+ id: 'usr_duplicate_newest',
2877
+ image: null,
2878
+ name: 'Newest user',
2879
+ updatedAt: '2026-01-01T00:00:00.000Z',
2880
+ },
2881
+ ])
2882
+ .execute()
2883
+ const cookie = await signInEmail(app, {
2884
+ email: 'developer@example.com',
2885
+ messages,
2886
+ })
2887
+
2888
+ const response = await app.request(`${origin}/v1/me`, {
2889
+ headers: { cookie },
2890
+ })
2891
+
2892
+ expect(response.status).toBe(200)
2893
+ expect(await response.json()).toMatchObject({ id: 'usr_duplicate_oldest' })
2894
+ } finally {
2895
+ await db.close()
2896
+ }
2897
+ })
2898
+
2899
+ test('mounts the Better Auth handler surface', async () => {
2900
+ const app = TestApp.create({
2901
+ session: { secret, wallet: { origin } },
2902
+ })
2903
+
2904
+ const response = await app.request(`${origin}/v1/auth/get-session`)
2905
+
2906
+ expect(response.status).toBe(200)
2907
+ expect(await response.json()).toBeNull()
2908
+ })
2909
+
2910
+ test('mounts Better Auth under the app base path', async () => {
2911
+ const app = TestApp.create({
2912
+ path: '/api',
2913
+ session: { secret, wallet: { origin } },
2914
+ })
2915
+
2916
+ const response = await app.request(`${origin}/api/v1/auth/get-session`)
2917
+
2918
+ expect(response.status).toBe(200)
2919
+ expect(await response.json()).toBeNull()
2920
+ })
2921
+
2922
+ test('handles SIWE routes under an application path', async () => {
2923
+ const app = TestApp.create({
2924
+ path: '/api',
2925
+ session: { secret, wallet: { origin } },
2926
+ })
2927
+ const account = privateKeyToAccount(generatePrivateKey())
2928
+
2929
+ const { verifyResponse } = await TestApp.signIn(
2930
+ { request: (path, init) => app.request(`/api${path}`, init) },
2931
+ account,
2932
+ )
2933
+
2934
+ expect(verifyResponse.status).toBe(200)
2935
+ })
2936
+
2937
+ test('returns the canonical error envelope when the SIWE store fails', async () => {
2938
+ const entries: Log.Entry[] = []
2939
+ const app = TestApp.create({
2940
+ kv: {
2941
+ store: Store.from({
2942
+ ...Store.memory(),
2943
+ async put() {
2944
+ throw new Error('Session store unavailable')
2945
+ },
2946
+ }),
2947
+ },
2948
+ logger: (entry) => void entries.push(entry),
2949
+ session: { secret, wallet: { origin } },
2950
+ })
2951
+
2952
+ const response = await app.request(`${origin}/v1/auth/siwe/challenge`, json({}))
2953
+
2954
+ expect(response.status).toBe(500)
2955
+ expect(await response.json()).toMatchObject({
2956
+ error: { code: 'internal_error', message: 'Internal server error' },
2957
+ })
2958
+ expect(entries.at(-1)).toMatchObject({ errorCode: 'internal_error', level: 'error' })
2959
+ })
2960
+
2961
+ test('does not mount Better Auth without session authentication', async () => {
2962
+ const app = TestApp.create({ auth: false })
2963
+
2964
+ const response = await app.request(`${origin}/v1/auth/get-session`)
2965
+
2966
+ expect(response.status).toBe(404)
2967
+ })
2968
+
2969
+ test('signs out through the Better Auth handler', async () => {
2970
+ const messages: App.Email.Message[] = []
2971
+ const app = TestApp.create({
2972
+ email: {
2973
+ from: 'noreply@example.com',
2974
+ send: async (message) => void messages.push(message),
2975
+ },
2976
+ session: { secret, wallet: { origin } },
2977
+ })
2978
+ const cookie = await signInEmail(app, {
2979
+ email: 'developer@example.com',
2980
+ messages,
2981
+ })
2982
+
2983
+ const response = await app.request(`${origin}/v1/auth/sign-out`, {
2984
+ headers: { cookie },
2985
+ method: 'POST',
2986
+ })
2987
+
2988
+ expect(response.status).toBe(200)
2989
+ expect(await response.json()).toMatchObject({ success: true })
2990
+ expect(response.headers.get('set-cookie')).toContain('tempo_auth.session_token=')
2991
+ expect(
2992
+ await app.request(`${origin}/v1/me`, {
2993
+ headers: { cookie },
2994
+ }),
2995
+ ).toMatchObject({ status: 401 })
2996
+ })
2997
+
2998
+ test('rejects unsupported OTP purposes before delivery', async () => {
2999
+ const messages: App.Email.Message[] = []
3000
+ const app = TestApp.create({
3001
+ email: {
3002
+ from: 'noreply@example.com',
3003
+ send: async (message) => void messages.push(message),
3004
+ },
3005
+ session: { secret, wallet: { origin } },
3006
+ })
3007
+
3008
+ const response = await app.request(
3009
+ `${origin}/v1/auth/email-otp/send-verification-otp`,
3010
+ json({ email: 'developer@example.com', type: 'email-verification' }),
3011
+ )
3012
+
3013
+ expect(response.status).toBe(400)
3014
+ expect(await response.json()).toMatchObject({ error: { code: 'body_invalid' } })
3015
+ expect(messages).toHaveLength(0)
3016
+ })
3017
+
3018
+ test('signs out Better Auth through the canonical logout route', async () => {
3019
+ const messages: App.Email.Message[] = []
3020
+ const app = TestApp.create({
3021
+ email: {
3022
+ from: 'noreply@example.com',
3023
+ send: async (message) => void messages.push(message),
3024
+ },
3025
+ session: { secret, wallet: { origin } },
3026
+ })
3027
+ const cookie = await signInEmail(app, {
3028
+ email: 'developer@example.com',
3029
+ messages,
3030
+ })
3031
+
3032
+ const response = await app.request(`${origin}/v1/auth/logout`, {
3033
+ headers: { cookie },
3034
+ method: 'POST',
3035
+ })
3036
+
3037
+ expectSessionsCleared(response)
3038
+ expect(
3039
+ await app.request(`${origin}/v1/me`, {
3040
+ headers: { cookie },
3041
+ }),
3042
+ ).toMatchObject({ status: 401 })
3043
+ })
3044
+
3045
+ test('signs out wallet sessions without email configuration', async () => {
3046
+ const app = TestApp.create({ session: { secret, wallet: { origin } } })
3047
+ const account = privateKeyToAccount(generatePrivateKey())
3048
+ const { cookie } = await TestApp.signIn(app, account)
3049
+
3050
+ const response = await app.request(`${origin}/v1/auth/logout`, {
3051
+ headers: { cookie: cookie! },
3052
+ method: 'POST',
3053
+ })
3054
+
3055
+ expectSessionsCleared(response)
3056
+ expect(
3057
+ await app.request(`${origin}/v1/me`, {
3058
+ headers: { cookie: cookie! },
3059
+ }),
3060
+ ).toMatchObject({ status: 401 })
3061
+ })
3062
+
3063
+ test('reports wallet session-store logout failures', async () => {
3064
+ const entries: Log.Entry[] = []
3065
+ const source = Store.memory()
3066
+ let failDeletes = false
3067
+ const app = TestApp.create({
3068
+ kv: {
3069
+ store: Store.from({
3070
+ ...source,
3071
+ async delete(key) {
3072
+ if (failDeletes) throw new Error('Session store unavailable')
3073
+ await source.delete(key)
3074
+ },
3075
+ }),
3076
+ },
3077
+ logger: (entry) => void entries.push(entry),
3078
+ session: { secret, wallet: { origin } },
3079
+ })
3080
+ const account = privateKeyToAccount(generatePrivateKey())
3081
+ const { cookie } = await TestApp.signIn(app, account)
3082
+ entries.length = 0
3083
+ failDeletes = true
3084
+
3085
+ const response = await app.request(`${origin}/v1/auth/logout`, {
3086
+ headers: { cookie: cookie! },
3087
+ method: 'POST',
3088
+ })
3089
+
3090
+ expect(response.status).toBe(500)
3091
+ expect(await response.json()).toMatchObject({
3092
+ error: { code: 'session_logout_failed', message: 'Session logout failed' },
3093
+ })
3094
+ expect(entries).toHaveLength(1)
3095
+ expect(entries[0]).toMatchObject({ errorCode: 'session_logout_failed', level: 'error' })
3096
+ })
3097
+
3098
+ test('does not resolve email sessions when email is unconfigured', async () => {
3099
+ const db = TestApp.database()
3100
+ const messages: App.Email.Message[] = []
3101
+ const email = TestApp.create({
3102
+ db,
3103
+ email: {
3104
+ from: 'noreply@example.com',
3105
+ send: async (message) => void messages.push(message),
3106
+ },
3107
+ session: { secret, wallet: { origin } },
3108
+ })
3109
+ const cookie = await signInEmail(email, {
3110
+ email: 'developer@example.com',
3111
+ messages,
3112
+ })
3113
+ const wallet = TestApp.create({
3114
+ db,
3115
+ session: { secret, wallet: { origin } },
3116
+ })
3117
+
3118
+ try {
3119
+ const unauthorized = await wallet.request(`${origin}/v1/me`, {
3120
+ headers: { cookie },
3121
+ })
3122
+ expect(unauthorized.status).toBe(401)
3123
+
3124
+ const logout = await wallet.request(`${origin}/v1/auth/logout`, {
3125
+ headers: { cookie },
3126
+ method: 'POST',
3127
+ })
3128
+ expectSessionsCleared(logout)
3129
+
3130
+ const session = await email.request(`${origin}/v1/auth/get-session`, {
3131
+ headers: { cookie },
3132
+ })
3133
+ expect(await session.json()).toBeNull()
3134
+ } finally {
3135
+ await db.close()
3136
+ }
3137
+ })
3138
+
3139
+ test('clears invalid sessions idempotently', async () => {
3140
+ const app = TestApp.create({ session: { secret, wallet: { origin } } })
3141
+
3142
+ const response = await app.request(`${origin}/v1/auth/logout`, {
3143
+ headers: {
3144
+ cookie: 'accounts_auth=expired; tempo_auth.session_token=expired',
3145
+ },
3146
+ method: 'POST',
3147
+ })
3148
+
3149
+ expectSessionsCleared(response)
3150
+ })
3151
+
3152
+ test('reports session database failures', async () => {
3153
+ const db = TestApp.database()
3154
+ const messages: App.Email.Message[] = []
3155
+ const app = TestApp.create({
3156
+ db,
3157
+ email: {
3158
+ from: 'noreply@example.com',
3159
+ send: async (message) => void messages.push(message),
3160
+ },
3161
+ session: { secret, wallet: { origin } },
3162
+ })
3163
+ const cookie = await signInEmail(app, {
3164
+ email: 'developer@example.com',
3165
+ messages,
3166
+ })
3167
+ await db.close()
3168
+
3169
+ const response = await app.request(`${origin}/v1/me`, {
3170
+ headers: { cookie },
3171
+ })
3172
+
3173
+ expect(response.status).toBe(500)
3174
+ expect(await response.json()).toMatchObject({ error: { code: 'internal_error' } })
3175
+ })
3176
+
3177
+ test('rejects consumed and superseded codes without revealing the cause', async () => {
3178
+ const db = TestApp.database()
3179
+ const messages: App.Email.Message[] = []
3180
+ const app = TestApp.create({
3181
+ db,
3182
+ email: {
3183
+ from: 'noreply@example.com',
3184
+ send: async (message) => void messages.push(message),
3185
+ },
3186
+ session: { secret, wallet: { origin } },
3187
+ })
3188
+
3189
+ try {
3190
+ await app.request(
3191
+ `${origin}/v1/auth/email-otp/send-verification-otp`,
3192
+ json({ email: 'developer@example.com', type: 'sign-in' }),
3193
+ )
3194
+ const first = messages[0]!.text.match(/\b\d{6}\b/)![0]!
3195
+ await app.request(
3196
+ `${origin}/v1/auth/email-otp/send-verification-otp`,
3197
+ json({ email: 'developer@example.com', type: 'sign-in' }),
3198
+ )
3199
+ const second = messages[1]!.text.match(/\b\d{6}\b/)![0]!
3200
+
3201
+ const superseded = await app.request(
3202
+ `${origin}/v1/auth/sign-in/email-otp`,
3203
+ json({ email: 'developer@example.com', otp: first }),
3204
+ )
3205
+ expect(superseded.status).toBe(400)
3206
+ expect(await superseded.json()).toMatchObject({ code: 'INVALID_OTP' })
3207
+
3208
+ const verified = await app.request(
3209
+ `${origin}/v1/auth/sign-in/email-otp`,
3210
+ json({ email: 'developer@example.com', otp: second }),
3211
+ )
3212
+ expect(verified.status).toBe(200)
3213
+
3214
+ const consumed = await app.request(
3215
+ `${origin}/v1/auth/sign-in/email-otp`,
3216
+ json({ email: 'developer@example.com', otp: second }),
3217
+ )
3218
+ expect(consumed.status).toBe(400)
3219
+ expect(await consumed.json()).toMatchObject({ code: 'INVALID_OTP' })
3220
+ } finally {
3221
+ await db.close()
3222
+ }
3223
+ })
3224
+
3225
+ test('rejects expired codes through Better Auth', async () => {
3226
+ const db = TestApp.database()
3227
+ const messages: App.Email.Message[] = []
3228
+ const app = TestApp.create({
3229
+ db,
3230
+ email: {
3231
+ from: 'noreply@example.com',
3232
+ send: async (message) => void messages.push(message),
3233
+ },
3234
+ session: { secret, wallet: { origin } },
3235
+ })
3236
+
3237
+ try {
3238
+ await app.request(
3239
+ `${origin}/v1/auth/email-otp/send-verification-otp`,
3240
+ json({ email: 'developer@example.com', type: 'sign-in' }),
3241
+ )
3242
+ const otp = messages[0]!.text.match(/\b\d{6}\b/)![0]!
3243
+ await db.kysely
3244
+ .updateTable('auth_verifications')
3245
+ .set({ expiresAt: new Date(0) })
3246
+ .execute()
3247
+
3248
+ const response = await app.request(
3249
+ `${origin}/v1/auth/sign-in/email-otp`,
3250
+ json({ email: 'developer@example.com', otp }),
3251
+ )
3252
+
3253
+ expect(response.status).toBe(400)
3254
+ expect(await response.json()).toMatchObject({ code: 'OTP_EXPIRED' })
3255
+ } finally {
3256
+ await db.close()
3257
+ }
3258
+ })
3259
+
3260
+ test('uses Better Auth rate limits across request-scoped instances', async () => {
3261
+ const app = TestApp.create({
3262
+ auth: { clientIp: (request) => request.headers.get('x-trusted-ip') ?? undefined },
3263
+ email: { from: 'noreply@example.com', send: async () => {} },
3264
+ rateLimit: { now: () => new Date('2026-01-01T00:00:00.000Z') },
3265
+ session: { secret, wallet: { origin } },
3266
+ })
3267
+
3268
+ for (let index = 0; index < 3; index++) {
3269
+ const response = await app.request(`${origin}/v1/auth/email-otp/send-verification-otp`, {
3270
+ ...json({ email: `developer-${index}@example.com`, type: 'sign-in' }),
3271
+ headers: {
3272
+ 'cf-connecting-ip': `198.51.100.${index}`,
3273
+ 'content-type': 'application/json',
3274
+ 'x-trusted-ip': '203.0.113.10',
3275
+ },
3276
+ })
3277
+ expect(response.status).toBe(200)
3278
+ }
3279
+
3280
+ const response = await app.request(`${origin}/v1/auth/email-otp/send-verification-otp`, {
3281
+ ...json({ email: 'developer-3@example.com', type: 'sign-in' }),
3282
+ headers: {
3283
+ 'cf-connecting-ip': '198.51.100.4',
3284
+ 'content-type': 'application/json',
3285
+ 'x-trusted-ip': '203.0.113.10',
3286
+ },
3287
+ })
3288
+ expect(response.status).toBe(429)
3289
+ expect(response.headers.get('x-retry-after')).toBe('60')
3290
+ expect(await response.json()).toMatchObject({ message: expect.any(String) })
3291
+ })
3292
+
3293
+ test('limits verification attempts', async () => {
3294
+ const messages: App.Email.Message[] = []
3295
+ const app = TestApp.create({
3296
+ email: {
3297
+ from: 'noreply@example.com',
3298
+ send: async (message) => void messages.push(message),
3299
+ },
3300
+ session: { secret, wallet: { origin } },
3301
+ })
3302
+ await app.request(
3303
+ `${origin}/v1/auth/email-otp/send-verification-otp`,
3304
+ json({ email: 'developer@example.com', type: 'sign-in' }),
3305
+ )
3306
+ const otp = messages[0]!.text.match(/\b\d{6}\b/)![0]!
3307
+ const wrong = `${otp[0] === '0' ? '1' : '0'}${otp.slice(1)}`
3308
+
3309
+ for (let index = 0; index < 3; index++) {
3310
+ const response = await app.request(
3311
+ `${origin}/v1/auth/sign-in/email-otp`,
3312
+ json({ email: 'developer@example.com', otp: wrong }),
3313
+ )
3314
+ expect(response.status).toBe(400)
3315
+ }
3316
+ const response = await app.request(
3317
+ `${origin}/v1/auth/sign-in/email-otp`,
3318
+ json({ email: 'developer@example.com', otp: wrong }),
3319
+ )
3320
+ expect(response.status).toBe(429)
3321
+ expect(await response.json()).toMatchObject({ message: expect.any(String) })
3322
+ })
3323
+
3324
+ test('accepts matching email and wallet sessions', async () => {
3325
+ const db = TestApp.database()
3326
+ const messages: App.Email.Message[] = []
3327
+ const app = TestApp.create({
3328
+ db,
3329
+ email: {
3330
+ from: 'noreply@example.com',
3331
+ send: async (message) => void messages.push(message),
3332
+ },
3333
+ session: { secret, wallet: { origin } },
3334
+ })
3335
+
3336
+ try {
3337
+ const account = privateKeyToAccount(generatePrivateKey())
3338
+ const wallet = await TestApp.signIn(app, account)
3339
+ expect(wallet.verifyResponse.status).toBe(200)
3340
+ const user = await Users.getByAddress(db, account.address)
3341
+ expect(user).toBeDefined()
3342
+ await Users.setEmail(db, user!.id, 'developer@example.com')
3343
+ const email = await signInEmail(app, {
3344
+ email: 'developer@example.com',
3345
+ messages,
3346
+ })
3347
+
3348
+ const response = await app.request(`${origin}/v1/me`, {
3349
+ headers: { cookie: `${email}; ${wallet.cookie}` },
3350
+ })
3351
+
3352
+ expect(response.status).toBe(200)
3353
+ expect(await response.json()).toMatchObject({ email: 'developer@example.com', id: user!.id })
3354
+
3355
+ const logout = await app.request(`${origin}/v1/auth/logout`, {
3356
+ headers: { cookie: `${email}; ${wallet.cookie}` },
3357
+ method: 'POST',
3358
+ })
3359
+ expect(logout.status).toBe(204)
3360
+ expect(
3361
+ await app.request(`${origin}/v1/me`, {
3362
+ headers: { cookie: email },
3363
+ }),
3364
+ ).toMatchObject({ status: 401 })
3365
+ expect(
3366
+ await app.request(`${origin}/v1/me`, {
3367
+ headers: { cookie: wallet.cookie! },
3368
+ }),
3369
+ ).toMatchObject({ status: 401 })
3370
+ } finally {
3371
+ await db.close()
3372
+ }
3373
+ })
3374
+
3375
+ test('rejects conflicting email and wallet sessions', async () => {
3376
+ const db = TestApp.database()
3377
+ const messages: App.Email.Message[] = []
3378
+ const app = TestApp.create({
3379
+ db,
3380
+ email: {
3381
+ from: 'noreply@example.com',
3382
+ send: async (message) => void messages.push(message),
3383
+ },
3384
+ session: {
3385
+ secret,
3386
+ wallet: { origin },
3387
+ },
3388
+ })
3389
+
3390
+ try {
3391
+ const account = privateKeyToAccount(generatePrivateKey())
3392
+ const wallet = await TestApp.signIn(app, account)
3393
+ expect(wallet.verifyResponse.status).toBe(200)
3394
+ const email = await signInEmail(app, {
3395
+ email: 'developer@example.com',
3396
+ messages,
3397
+ })
3398
+
3399
+ const response = await app.request(`${origin}/v1/me`, {
3400
+ headers: { cookie: `${email}; ${wallet.cookie}` },
3401
+ })
3402
+
3403
+ expect(response.status).toBe(401)
3404
+
3405
+ const logout = await app.request(`${origin}/v1/auth/logout`, {
3406
+ headers: { cookie: `${email}; ${wallet.cookie}` },
3407
+ method: 'POST',
3408
+ })
3409
+ expectSessionsCleared(logout)
3410
+ const emailSession = await app.request(`${origin}/v1/auth/get-session`, {
3411
+ headers: { cookie: email },
3412
+ })
3413
+ expect(emailSession.status).toBe(200)
3414
+ expect(await emailSession.json()).toBeNull()
3415
+ expect(
3416
+ await app.request(`${origin}/v1/me`, {
3417
+ headers: { cookie: email },
3418
+ }),
3419
+ ).toMatchObject({ status: 401 })
3420
+ expect(
3421
+ await app.request(`${origin}/v1/me`, {
3422
+ headers: { cookie: wallet.cookie! },
3423
+ }),
3424
+ ).toMatchObject({ status: 401 })
3425
+ } finally {
3426
+ await db.close()
3427
+ }
3428
+ })
3429
+
3430
+ test('signs out conflicting wallet bearer and email cookie sessions', async () => {
3431
+ const db = TestApp.database()
3432
+ const messages: App.Email.Message[] = []
3433
+ const app = TestApp.create({
3434
+ db,
3435
+ email: {
3436
+ from: 'noreply@example.com',
3437
+ send: async (message) => void messages.push(message),
3438
+ },
3439
+ session: { secret, wallet: { origin } },
3440
+ })
3441
+
3442
+ try {
3443
+ const account = privateKeyToAccount(generatePrivateKey())
3444
+ const wallet = await TestApp.signIn(app, account, { returnToken: true })
3445
+ expect(wallet.verifyResponse.status).toBe(200)
3446
+ const { token } = (await wallet.verifyResponse.json()) as { token: string }
3447
+ const email = await signInEmail(app, {
3448
+ email: 'developer@example.com',
3449
+ messages,
3450
+ })
3451
+
3452
+ const response = await app.request(`${origin}/v1/me`, {
3453
+ headers: { authorization: `Bearer ${token}`, cookie: email },
3454
+ })
3455
+ expect(response.status).toBe(401)
3456
+
3457
+ const logout = await app.request(`${origin}/v1/auth/logout`, {
3458
+ headers: { authorization: `Bearer ${token}`, cookie: email },
3459
+ method: 'POST',
3460
+ })
3461
+ expectSessionsCleared(logout)
3462
+ expect(
3463
+ await app.request(`${origin}/v1/me`, {
3464
+ headers: { cookie: email },
3465
+ }),
3466
+ ).toMatchObject({ status: 401 })
3467
+ expect(
3468
+ await app.request(`${origin}/v1/me`, {
3469
+ headers: { authorization: `Bearer ${token}` },
3470
+ }),
3471
+ ).toMatchObject({ status: 401 })
3472
+ } finally {
3473
+ await db.close()
3474
+ }
3475
+ })
3476
+
3477
+ test('signs out wallet cookies when a bearer credential is also present', async () => {
3478
+ const app = TestApp.create({ session: { secret, wallet: { origin } } })
3479
+ const account = privateKeyToAccount(generatePrivateKey())
3480
+ const wallet = await TestApp.signIn(app, account)
3481
+
3482
+ const logout = await app.request(`${origin}/v1/auth/logout`, {
3483
+ headers: {
3484
+ authorization: 'Bearer unrelated-credential',
3485
+ cookie: wallet.cookie!,
3486
+ },
3487
+ method: 'POST',
3488
+ })
3489
+
3490
+ expectSessionsCleared(logout)
3491
+ expect(
3492
+ await app.request(`${origin}/v1/me`, {
3493
+ headers: { cookie: wallet.cookie! },
3494
+ }),
3495
+ ).toMatchObject({ status: 401 })
3496
+ })
3497
+
3498
+ test('rate limits unauthenticated logout requests', async () => {
3499
+ const app = TestApp.create({ session: { secret, wallet: { origin } } })
3500
+
3501
+ for (let index = 0; index < 60; index++)
3502
+ expect(
3503
+ await app.request(`${origin}/v1/auth/logout`, {
3504
+ method: 'POST',
3505
+ }),
3506
+ ).toMatchObject({ status: 204 })
3507
+
3508
+ const response = await app.request(`${origin}/v1/auth/logout`, {
3509
+ method: 'POST',
3510
+ })
3511
+
3512
+ expect(response.status).toBe(429)
3513
+ expect(await response.json()).toMatchObject({ error: { code: 'rate_limit_exceeded' } })
3514
+ })
3515
+ })
3516
+
3517
+ describe('one-time session tokens', () => {
3518
+ test('redeems the current Better Auth session once', async () => {
3519
+ const db = TestApp.database()
3520
+ const messages: App.Email.Message[] = []
3521
+ const app = TestApp.create({
3522
+ db,
3523
+ email: {
3524
+ from: 'noreply@example.com',
3525
+ send: async (message) => void messages.push(message),
3526
+ },
3527
+ session: { secret, wallet: { origin } },
3528
+ })
3529
+
3530
+ try {
3531
+ const cookie = await signInEmail(app, {
3532
+ email: 'developer@example.com',
3533
+ messages,
3534
+ })
3535
+ const generated = await app.request(`${origin}/v1/auth/one-time-token/generate`, {
3536
+ headers: { cookie },
3537
+ })
3538
+ const { token } = (await generated.json()) as { token: string }
3539
+ const redeem = () => app.request(`${origin}/v1/auth/one-time-token/verify`, json({ token }))
3540
+
3541
+ expect(generated.status).toBe(200)
3542
+ const first = await redeem()
3543
+ expect(first.status).toBe(200)
3544
+ expect(first.headers.get('set-cookie')).toBeNull()
3545
+ expect(await first.json()).toMatchObject({
3546
+ user: { email: 'developer@example.com', emailVerified: true },
3547
+ })
3548
+ expect((await redeem()).status).toBe(400)
3549
+ } finally {
3550
+ await db.close()
3551
+ }
3552
+ })
3553
+ })
3554
+
3555
+ describe('identity sign-in', () => {
3556
+ test('rejects cross-site form bodies', async () => {
3557
+ const app = TestApp.create({
3558
+ session: { identity: { audience: origin }, secret, wallet: { origin } },
3559
+ })
3560
+
3561
+ const response = await app.request(`${origin}/v1/auth/identity`, {
3562
+ body: JSON.stringify({ idToken: 'attacker-token', padding: '' }),
3563
+ headers: {
3564
+ 'content-type': 'text/plain',
3565
+ origin: 'https://attacker.example.com',
3566
+ },
3567
+ method: 'POST',
3568
+ })
3569
+
3570
+ expect(response.status).toBe(400)
3571
+ expect(await response.json()).toMatchObject({
3572
+ error: { code: 'body_invalid', message: 'Invalid request body' },
3573
+ })
3574
+ expect(response.headers.get('set-cookie')).toBeNull()
3575
+ })
3576
+
3577
+ test('verifies a Wallet identity and creates an API session', async () => {
3578
+ const db = TestApp.database()
3579
+ const issuer = await createIdentityIssuer({ email: 'developer@example.com' })
3580
+ const account = privateKeyToAccount(generatePrivateKey())
3581
+ const app = TestApp.create({
3582
+ db,
3583
+ session: {
3584
+ identity: { audience: origin, issuer: issuer.url },
3585
+ secret,
3586
+ wallet: { origin },
3587
+ },
3588
+ })
3589
+
3590
+ try {
3591
+ const response = await app.request(
3592
+ `${origin}/v1/auth/identity`,
3593
+ json({ idToken: await issuer.mint({ address: account.address, audience: origin }) }),
3594
+ )
3595
+ const cookie = response.headers.get('set-cookie')?.split(';', 1)[0]
3596
+
3597
+ expect(response.status).toBe(200)
3598
+ expect(cookie).toMatch(/^tempo_identity=/)
3599
+ expect(response.headers.get('set-cookie')).toContain('Max-Age=86400')
3600
+ expect(response.headers.get('set-cookie')).toContain('HttpOnly')
3601
+ expect(response.headers.get('set-cookie')).toContain('SameSite=Lax')
3602
+ expect(response.headers.get('set-cookie')).toContain('Secure')
3603
+
3604
+ const me = await app.request(`${origin}/v1/me`, { headers: { cookie: cookie! } })
3605
+ expect(me.status).toBe(200)
3606
+ expect(await me.json()).toMatchObject({
3607
+ address: account.address.toLowerCase(),
3608
+ email: 'developer@example.com',
3609
+ })
3610
+
3611
+ const logout = await app.request(`${origin}/v1/auth/logout`, {
3612
+ headers: { cookie: cookie! },
3613
+ method: 'POST',
3614
+ })
3615
+ expect(logout.status).toBe(204)
3616
+ expect(logout.headers.getSetCookie()).toEqual(
3617
+ expect.arrayContaining([expect.stringContaining('tempo_identity=')]),
3618
+ )
3619
+ expect(await app.request(`${origin}/v1/me`, { headers: { cookie: cookie! } })).toMatchObject({
3620
+ status: 401,
3621
+ })
3622
+ } finally {
3623
+ await issuer.close()
3624
+ await db.close()
3625
+ }
3626
+ })
3627
+
3628
+ test('clears the identity cookie when session revocation fails', async () => {
3629
+ const db = TestApp.database()
3630
+ const issuer = await createIdentityIssuer({ email: 'developer@example.com' })
3631
+ const source = Store.memory()
3632
+ let failDeletes = false
3633
+ const app = TestApp.create({
3634
+ db,
3635
+ kv: {
3636
+ store: Store.from({
3637
+ ...source,
3638
+ async delete(key) {
3639
+ if (failDeletes) throw new Error('Session store unavailable')
3640
+ await source.delete(key)
3641
+ },
3642
+ }),
3643
+ },
3644
+ session: {
3645
+ identity: { audience: origin, issuer: issuer.url },
3646
+ secret,
3647
+ wallet: { origin },
3648
+ },
3649
+ })
3650
+ const account = privateKeyToAccount(generatePrivateKey())
3651
+
3652
+ try {
3653
+ const identity = await app.request(
3654
+ `${origin}/v1/auth/identity`,
3655
+ json({ idToken: await issuer.mint({ address: account.address, audience: origin }) }),
3656
+ )
3657
+ const cookie = identity.headers.get('set-cookie')?.split(';', 1)[0]
3658
+ failDeletes = true
3659
+ const logout = await app.request(`${origin}/v1/auth/logout`, {
3660
+ headers: { cookie: cookie! },
3661
+ method: 'POST',
3662
+ })
3663
+
3664
+ expect(logout.status).toBe(500)
3665
+ expect(logout.headers.getSetCookie()).toEqual(
3666
+ expect.arrayContaining([expect.stringMatching(/^tempo_identity=; Max-Age=0;/)]),
3667
+ )
3668
+ } finally {
3669
+ await issuer.close()
3670
+ await db.close()
3671
+ }
3672
+ })
3673
+
3674
+ test('does not resolve identity sessions when identity is unconfigured', async () => {
3675
+ const db = TestApp.database()
3676
+ const issuer = await createIdentityIssuer({ email: 'developer@example.com' })
3677
+ const store = Store.memory()
3678
+ const configured = TestApp.create({
3679
+ db,
3680
+ kv: { store },
3681
+ session: {
3682
+ identity: { audience: origin, issuer: issuer.url },
3683
+ secret,
3684
+ wallet: { origin },
3685
+ },
3686
+ })
3687
+ const unconfigured = TestApp.create({
3688
+ db,
3689
+ kv: { store },
3690
+ session: { secret, wallet: { origin } },
3691
+ })
3692
+ const account = privateKeyToAccount(generatePrivateKey())
3693
+
3694
+ try {
3695
+ const identity = await configured.request(
3696
+ `${origin}/v1/auth/identity`,
3697
+ json({ idToken: await issuer.mint({ address: account.address, audience: origin }) }),
3698
+ )
3699
+ const cookie = identity.headers.get('set-cookie')?.split(';', 1)[0]
3700
+ const response = await unconfigured.request(`${origin}/v1/me`, {
3701
+ headers: { cookie: cookie! },
3702
+ })
3703
+
3704
+ expect(identity.status).toBe(200)
3705
+ expect(response.status).toBe(401)
3706
+ } finally {
3707
+ await issuer.close()
3708
+ await db.close()
3709
+ }
3710
+ })
3711
+
3712
+ test('reports identity issuer failures', async () => {
3713
+ const db = TestApp.database()
3714
+ const issuer = await createIdentityIssuer({ email: 'developer@example.com' })
3715
+ const account = privateKeyToAccount(generatePrivateKey())
3716
+ const idToken = await issuer.mint({ address: account.address, audience: origin })
3717
+ const entries: Log.Entry[] = []
3718
+ const app = TestApp.create({
3719
+ db,
3720
+ logger: (entry) => void entries.push(entry),
3721
+ session: {
3722
+ identity: { audience: origin, issuer: issuer.url },
3723
+ secret,
3724
+ wallet: { origin },
3725
+ },
3726
+ })
3727
+ await issuer.close()
3728
+
3729
+ try {
3730
+ const response = await app.request(`${origin}/v1/auth/identity`, json({ idToken }))
3731
+
3732
+ expect(response.status).toBe(500)
3733
+ expect(await response.json()).toMatchObject({
3734
+ error: { code: 'internal_error', message: 'Internal server error' },
3735
+ })
3736
+ expect(entries.at(-1)).toMatchObject({ errorCode: 'internal_error', level: 'error' })
3737
+ } finally {
3738
+ await db.close()
3739
+ }
3740
+ })
3741
+
3742
+ test('reconciles the Wallet address into an active email session', async () => {
3743
+ const db = TestApp.database()
3744
+ const issuer = await createIdentityIssuer({ email: 'developer@example.com' })
3745
+ const messages: App.Email.Message[] = []
3746
+ const account = privateKeyToAccount(generatePrivateKey())
3747
+ const app = TestApp.create({
3748
+ db,
3749
+ email: {
3750
+ from: 'noreply@example.com',
3751
+ send: async (message) => void messages.push(message),
3752
+ },
3753
+ session: {
3754
+ identity: { audience: origin, issuer: issuer.url },
3755
+ secret,
3756
+ wallet: { origin },
3757
+ },
3758
+ })
3759
+
3760
+ try {
3761
+ const emailCookie = await signInEmail(app, {
3762
+ email: 'developer@example.com',
3763
+ messages,
3764
+ })
3765
+ const identity = await app.request(
3766
+ `${origin}/v1/auth/identity`,
3767
+ json({ idToken: await issuer.mint({ address: account.address, audience: origin }) }),
3768
+ )
3769
+ const identityCookie = identity.headers.get('set-cookie')?.split(';', 1)[0]
3770
+ const me = await app.request(`${origin}/v1/me`, {
3771
+ headers: { cookie: `${emailCookie}; ${identityCookie}` },
3772
+ })
3773
+
3774
+ expect(identity.status).toBe(200)
3775
+ expect(await me.json()).toMatchObject({
3776
+ address: account.address.toLowerCase(),
3777
+ email: 'developer@example.com',
3778
+ })
3779
+ } finally {
3780
+ await issuer.close()
3781
+ await db.close()
3782
+ }
3783
+ })
3784
+
3785
+ test('rejects an identity issued for another audience', async () => {
3786
+ const issuer = await createIdentityIssuer({ email: 'developer@example.com' })
3787
+ const account = privateKeyToAccount(generatePrivateKey())
3788
+ const app = TestApp.create({
3789
+ session: {
3790
+ identity: { audience: origin, issuer: issuer.url },
3791
+ secret,
3792
+ wallet: { origin },
3793
+ },
3794
+ })
3795
+
3796
+ try {
3797
+ const response = await app.request(
3798
+ `${origin}/v1/auth/identity`,
3799
+ json({
3800
+ idToken: await issuer.mint({
3801
+ address: account.address,
3802
+ audience: 'https://attacker.example.com',
3803
+ }),
3804
+ }),
3805
+ )
3806
+
3807
+ expect(response.status).toBe(401)
3808
+ expect(await response.json()).toMatchObject({
3809
+ error: { code: 'identity_invalid', message: 'Invalid identity token' },
3810
+ })
3811
+ expect(response.headers.get('set-cookie')).toBeNull()
3812
+ } finally {
3813
+ await issuer.close()
3814
+ }
3815
+ })
3816
+
3817
+ test('documents identity sign-in only when configured', async () => {
3818
+ const configured = TestApp.create({
3819
+ session: { identity: { audience: origin }, secret, wallet: { origin } },
3820
+ })
3821
+ const unconfigured = TestApp.create({ session: { secret, wallet: { origin } } })
3822
+
3823
+ const configuredSpec = await (await configured.request('/openapi.json')).json()
3824
+ const unconfiguredSpec = await (await unconfigured.request('/openapi.json')).json()
3825
+
3826
+ expect(configuredSpec.paths['/v1/auth/identity'].post).toBeDefined()
3827
+ expect(unconfiguredSpec.paths['/v1/auth/identity']).toBeUndefined()
3828
+ })
3829
+ })
3830
+
3831
+ function json(body: unknown) {
3832
+ return {
3833
+ body: JSON.stringify(body),
3834
+ headers: { 'content-type': 'application/json' },
3835
+ method: 'POST',
3836
+ }
3837
+ }
3838
+
3839
+ function expectSessionsCleared(response: globalThis.Response) {
3840
+ expect(response.status).toBe(204)
3841
+ expect(response.headers.getSetCookie()).toEqual(
3842
+ expect.arrayContaining([
3843
+ expect.stringContaining('accounts_auth='),
3844
+ expect.stringContaining('tempo_auth.session_token='),
3845
+ ]),
3846
+ )
3847
+ }
3848
+
3849
+ /** Local Wallet-style OIDC issuer for identity verification tests. */
3850
+ async function createIdentityIssuer(options: createIdentityIssuer.Options) {
3851
+ const { privateKey, publicKey } = await generateKeyPair('EdDSA', { extractable: true })
3852
+ let provider!: ReturnType<typeof Accounts.Handler.oidcProvider>
3853
+ type Listener = { close: () => Promise<void>; url: string }
3854
+ const { close, url } = await new Promise<Listener>((resolve) => {
3855
+ const server = serve({ fetch: (request) => provider.fetch(request), port: 0 }, (info) =>
3856
+ resolve({
3857
+ close: () => new Promise((done) => server.close(() => done())),
3858
+ url: `http://127.0.0.1:${info.port}`,
3859
+ }),
3860
+ )
3861
+ })
3862
+ provider = Accounts.Handler.oidcProvider({
3863
+ getClaims: () => ({ email: options.email, email_verified: true }),
3864
+ issuer: url,
3865
+ publicKey: JSON.stringify(await exportJWK(publicKey)),
3866
+ signingKey: JSON.stringify(await exportJWK(privateKey)),
3867
+ })
3868
+ return {
3869
+ close,
3870
+ async mint(parameters: createIdentityIssuer.MintParameters) {
3871
+ const response = await provider.fetch(
3872
+ new Request(`${url}/token`, {
3873
+ body: JSON.stringify({
3874
+ audience: parameters.audience,
3875
+ subject: parameters.address,
3876
+ }),
3877
+ headers: { 'content-type': 'application/json' },
3878
+ method: 'POST',
3879
+ }),
3880
+ )
3881
+ const { idToken } = (await response.json()) as { idToken: string }
3882
+ return idToken
3883
+ },
3884
+ url,
3885
+ }
3886
+ }
3887
+
3888
+ declare namespace createIdentityIssuer {
3889
+ type MintParameters = {
3890
+ /** Wallet address used as the token subject. */
3891
+ address: string
3892
+ /** Origin used as the token audience. */
3893
+ audience: string
3894
+ }
3895
+
3896
+ type Options = {
3897
+ /** Verified email included in issued tokens. */
3898
+ email: string
3899
+ }
3900
+ }
3901
+
3902
+ async function signInEmail(app: TestApp.signIn.App, options: signInEmail.Options) {
3903
+ await app.request(
3904
+ `${origin}/v1/auth/email-otp/send-verification-otp`,
3905
+ json({ email: options.email, type: 'sign-in' }),
3906
+ )
3907
+ const otp = options.messages.at(-1)!.text.match(/\b\d{6}\b/)![0]!
3908
+ const response = await app.request(
3909
+ `${origin}/v1/auth/sign-in/email-otp`,
3910
+ json({ email: options.email, otp }),
3911
+ )
3912
+ expect(response.status).toBe(200)
3913
+ return response.headers.get('set-cookie')!.split(';', 1)[0]!
3914
+ }
3915
+
3916
+ declare namespace signInEmail {
3917
+ type Options = {
3918
+ /** Email to authenticate. */
3919
+ email: string
3920
+ /** Captured outbound messages. */
3921
+ messages: readonly App.Email.Message[]
3922
+ }
3923
+ }