tapimo 0.15.1 → 0.18.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 (709) hide show
  1. package/README.md +137 -0
  2. package/dist/ApiKey.d.ts +1 -0
  3. package/dist/ApiKey.d.ts.map +1 -1
  4. package/dist/ApiKey.js +4 -2
  5. package/dist/ApiKey.js.map +1 -1
  6. package/dist/ApiKeys.d.ts +37 -11
  7. package/dist/ApiKeys.d.ts.map +1 -1
  8. package/dist/ApiKeys.js +163 -10
  9. package/dist/ApiKeys.js.map +1 -1
  10. package/dist/App.d.ts +13085 -11974
  11. package/dist/App.d.ts.map +1 -1
  12. package/dist/App.js +46 -15
  13. package/dist/App.js.map +1 -1
  14. package/dist/Scope.d.ts +1 -1
  15. package/dist/Scope.d.ts.map +1 -1
  16. package/dist/Scope.js +1 -1
  17. package/dist/Scope.js.map +1 -1
  18. package/dist/admin/App.d.ts +893 -191
  19. package/dist/admin/App.d.ts.map +1 -1
  20. package/dist/admin/App.js +5 -1
  21. package/dist/admin/App.js.map +1 -1
  22. package/dist/admin/apps/api-keys.d.ts +70 -70
  23. package/dist/admin/apps/api-keys.d.ts.map +1 -1
  24. package/dist/admin/apps/api-keys.js +8 -3
  25. package/dist/admin/apps/api-keys.js.map +1 -1
  26. package/dist/admin/apps/earn-vaults.d.ts +66 -27
  27. package/dist/admin/apps/earn-vaults.d.ts.map +1 -1
  28. package/dist/admin/apps/earn-vaults.js +36 -7
  29. package/dist/admin/apps/earn-vaults.js.map +1 -1
  30. package/dist/admin/apps/organizations.d.ts +25 -25
  31. package/dist/admin/apps/organizations.d.ts.map +1 -1
  32. package/dist/admin/apps/organizations.js +5 -4
  33. package/dist/admin/apps/organizations.js.map +1 -1
  34. package/dist/admin/apps/route-policies.d.ts +632 -0
  35. package/dist/admin/apps/route-policies.d.ts.map +1 -0
  36. package/dist/admin/apps/route-policies.js +257 -0
  37. package/dist/admin/apps/route-policies.js.map +1 -0
  38. package/dist/admin/apps/routes-support.js +39 -3
  39. package/dist/admin/apps/routes-support.js.map +1 -1
  40. package/dist/admin/apps/routes.d.ts +529 -76
  41. package/dist/admin/apps/routes.d.ts.map +1 -1
  42. package/dist/admin/apps/routes.js +82 -1
  43. package/dist/admin/apps/routes.js.map +1 -1
  44. package/dist/admin/apps/verified-tokens.d.ts +157 -157
  45. package/dist/admin/index.d.ts +0 -1
  46. package/dist/admin/index.d.ts.map +1 -1
  47. package/dist/admin/index.js +0 -1
  48. package/dist/admin/index.js.map +1 -1
  49. package/dist/admin/ui.generated.d.ts +1 -1
  50. package/dist/admin/ui.generated.d.ts.map +1 -1
  51. package/dist/admin/ui.generated.js +205 -201
  52. package/dist/admin/ui.generated.js.map +1 -1
  53. package/dist/analytics/Analytics.d.ts.map +1 -1
  54. package/dist/analytics/Analytics.js +65 -1
  55. package/dist/analytics/Analytics.js.map +1 -1
  56. package/dist/analytics/tables/requestEvents.d.ts +1 -1
  57. package/dist/analytics/tables/requestEvents.d.ts.map +1 -1
  58. package/dist/analytics/tables/requestEvents.js +58 -59
  59. package/dist/analytics/tables/requestEvents.js.map +1 -1
  60. package/dist/apps/data/App.d.ts +2709 -2670
  61. package/dist/apps/data/App.d.ts.map +1 -1
  62. package/dist/apps/data/routes/activities.d.ts +357 -357
  63. package/dist/apps/data/routes/activities.d.ts.map +1 -1
  64. package/dist/apps/data/routes/activities.js +50 -0
  65. package/dist/apps/data/routes/activities.js.map +1 -1
  66. package/dist/apps/data/routes/addresses.d.ts +248 -248
  67. package/dist/apps/data/routes/balances.d.ts +22 -22
  68. package/dist/apps/data/routes/balances.d.ts.map +1 -1
  69. package/dist/apps/data/routes/balances.js +5 -7
  70. package/dist/apps/data/routes/balances.js.map +1 -1
  71. package/dist/apps/data/routes/blocks.d.ts +125 -125
  72. package/dist/apps/data/routes/coingecko.d.ts +54 -54
  73. package/dist/apps/data/routes/earn.d.ts +103 -12
  74. package/dist/apps/data/routes/earn.d.ts.map +1 -1
  75. package/dist/apps/data/routes/earn.js +456 -220
  76. package/dist/apps/data/routes/earn.js.map +1 -1
  77. package/dist/apps/data/routes/exchanges.d.ts.map +1 -1
  78. package/dist/apps/data/routes/exchanges.js +267 -97
  79. package/dist/apps/data/routes/exchanges.js.map +1 -1
  80. package/dist/apps/data/routes/fee-amm.d.ts +109 -127
  81. package/dist/apps/data/routes/fee-amm.d.ts.map +1 -1
  82. package/dist/apps/data/routes/fee-amm.js +83 -54
  83. package/dist/apps/data/routes/fee-amm.js.map +1 -1
  84. package/dist/apps/data/routes/indexer.d.ts +43 -43
  85. package/dist/apps/data/routes/receipts.d.ts +235 -235
  86. package/dist/apps/data/routes/rpc.d.ts +30 -30
  87. package/dist/apps/data/routes/tokens.d.ts.map +1 -1
  88. package/dist/apps/data/routes/tokens.js +11 -6
  89. package/dist/apps/data/routes/tokens.js.map +1 -1
  90. package/dist/apps/data/routes/transactions.d.ts +2 -0
  91. package/dist/apps/data/routes/transactions.d.ts.map +1 -1
  92. package/dist/apps/data/routes/transactions.js +30 -22
  93. package/dist/apps/data/routes/transactions.js.map +1 -1
  94. package/dist/apps/data/routes/transfers.d.ts +77 -77
  95. package/dist/apps/data/routes/valuation.d.ts +32 -32
  96. package/dist/apps/data/routes/verified-tokens.d.ts +86 -86
  97. package/dist/apps/data/routes/webhooks.d.ts.map +1 -1
  98. package/dist/apps/data/routes/webhooks.js +1 -1
  99. package/dist/apps/data/routes/webhooks.js.map +1 -1
  100. package/dist/apps/data/routes/zones.d.ts +31 -31
  101. package/dist/apps/management/App.d.ts +2909 -2064
  102. package/dist/apps/management/App.d.ts.map +1 -1
  103. package/dist/apps/management/App.js +2 -0
  104. package/dist/apps/management/App.js.map +1 -1
  105. package/dist/apps/management/Billing.d.ts +2 -4
  106. package/dist/apps/management/Billing.d.ts.map +1 -1
  107. package/dist/apps/management/Billing.js +65 -26
  108. package/dist/apps/management/Billing.js.map +1 -1
  109. package/dist/apps/management/routes/api-keys.d.ts +257 -245
  110. package/dist/apps/management/routes/api-keys.d.ts.map +1 -1
  111. package/dist/apps/management/routes/api-keys.js +70 -11
  112. package/dist/apps/management/routes/api-keys.js.map +1 -1
  113. package/dist/apps/management/routes/billing.d.ts +84 -84
  114. package/dist/apps/management/routes/cli.d.ts +912 -0
  115. package/dist/apps/management/routes/cli.d.ts.map +1 -0
  116. package/dist/apps/management/routes/cli.js +416 -0
  117. package/dist/apps/management/routes/cli.js.map +1 -0
  118. package/dist/apps/management/routes/faucet.d.ts +8 -8
  119. package/dist/apps/management/routes/invitations.d.ts +138 -138
  120. package/dist/apps/management/routes/invite-links.d.ts +172 -172
  121. package/dist/apps/management/routes/members.d.ts +16 -16
  122. package/dist/apps/management/routes/orgs.d.ts +104 -104
  123. package/dist/apps/management/routes/orgs.d.ts.map +1 -1
  124. package/dist/apps/management/routes/orgs.js +8 -2
  125. package/dist/apps/management/routes/orgs.js.map +1 -1
  126. package/dist/apps/management/routes/projects.d.ts +125 -125
  127. package/dist/apps/management/routes/usage.d.ts +8 -8
  128. package/dist/apps/management/routes/verified-token-requests.d.ts +86 -86
  129. package/dist/apps/management/routes/webhooks.d.ts +485 -485
  130. package/dist/apps/mpp/App.d.ts +44 -44
  131. package/dist/apps/mpp/internal/Policy.d.ts.map +1 -1
  132. package/dist/apps/mpp/internal/Policy.js +4 -2
  133. package/dist/apps/mpp/internal/Policy.js.map +1 -1
  134. package/dist/apps/mpp/internal/Sponsorship.d.ts.map +1 -1
  135. package/dist/apps/mpp/internal/Sponsorship.js +6 -4
  136. package/dist/apps/mpp/internal/Sponsorship.js.map +1 -1
  137. package/dist/apps/relay/App.d.ts +8 -0
  138. package/dist/apps/relay/App.d.ts.map +1 -1
  139. package/dist/apps/relay/App.js +16 -4
  140. package/dist/apps/relay/App.js.map +1 -1
  141. package/dist/apps/relay/Sponsorships.d.ts +4 -6
  142. package/dist/apps/relay/Sponsorships.d.ts.map +1 -1
  143. package/dist/apps/relay/Sponsorships.js +71 -60
  144. package/dist/apps/relay/Sponsorships.js.map +1 -1
  145. package/dist/apps/routes/Access.d.ts +53 -0
  146. package/dist/apps/routes/Access.d.ts.map +1 -1
  147. package/dist/apps/routes/Access.js +121 -0
  148. package/dist/apps/routes/Access.js.map +1 -1
  149. package/dist/apps/routes/App.d.ts +397 -158
  150. package/dist/apps/routes/App.d.ts.map +1 -1
  151. package/dist/apps/routes/App.js.map +1 -1
  152. package/dist/apps/routes/routes/chains.d.ts +25 -25
  153. package/dist/apps/routes/routes/deposit-addresses.d.ts +169 -61
  154. package/dist/apps/routes/routes/deposit-addresses.d.ts.map +1 -1
  155. package/dist/apps/routes/routes/deposit-addresses.js +217 -32
  156. package/dist/apps/routes/routes/deposit-addresses.js.map +1 -1
  157. package/dist/apps/routes/routes/quotes.d.ts +171 -81
  158. package/dist/apps/routes/routes/quotes.d.ts.map +1 -1
  159. package/dist/apps/routes/routes/quotes.js +101 -27
  160. package/dist/apps/routes/routes/quotes.js.map +1 -1
  161. package/dist/apps/routes/routes/transfers.d.ts +532 -480
  162. package/dist/apps/routes/routes/transfers.d.ts.map +1 -1
  163. package/dist/apps/routes/routes/transfers.js +182 -37
  164. package/dist/apps/routes/routes/transfers.js.map +1 -1
  165. package/dist/cli/ApiKeys.d.ts +120 -0
  166. package/dist/cli/ApiKeys.d.ts.map +1 -0
  167. package/dist/cli/ApiKeys.js +138 -0
  168. package/dist/cli/ApiKeys.js.map +1 -0
  169. package/dist/cli/Cli.d.ts +92 -34
  170. package/dist/cli/Cli.d.ts.map +1 -1
  171. package/dist/cli/Cli.js +188 -11
  172. package/dist/cli/Cli.js.map +1 -1
  173. package/dist/cli/Credentials.d.ts +95 -0
  174. package/dist/cli/Credentials.d.ts.map +1 -0
  175. package/dist/cli/Credentials.js +110 -0
  176. package/dist/cli/Credentials.js.map +1 -0
  177. package/dist/cli/Spec.d.ts +59 -0
  178. package/dist/cli/Spec.d.ts.map +1 -0
  179. package/dist/cli/Spec.js +77 -0
  180. package/dist/cli/Spec.js.map +1 -0
  181. package/dist/cli/bin.js +5 -1
  182. package/dist/cli/bin.js.map +1 -1
  183. package/dist/cli/commands/admin.d.ts +5 -5
  184. package/dist/cli/commands/admin.d.ts.map +1 -1
  185. package/dist/cli/commands/auth.d.ts +73 -0
  186. package/dist/cli/commands/auth.d.ts.map +1 -0
  187. package/dist/cli/commands/auth.js +204 -0
  188. package/dist/cli/commands/auth.js.map +1 -0
  189. package/dist/cli/commands/keys.d.ts +17 -0
  190. package/dist/cli/commands/keys.d.ts.map +1 -0
  191. package/dist/cli/commands/keys.js +109 -0
  192. package/dist/cli/commands/keys.js.map +1 -0
  193. package/dist/cloudflare.d.ts +27 -2
  194. package/dist/cloudflare.d.ts.map +1 -1
  195. package/dist/cloudflare.js +144 -17
  196. package/dist/cloudflare.js.map +1 -1
  197. package/dist/db/Db.d.ts +23 -0
  198. package/dist/db/Db.d.ts.map +1 -1
  199. package/dist/db/Db.js +413 -1
  200. package/dist/db/Db.js.map +1 -1
  201. package/dist/db/Schema.d.ts +44 -1
  202. package/dist/db/Schema.d.ts.map +1 -1
  203. package/dist/db/Schema.js +56 -3
  204. package/dist/db/Schema.js.map +1 -1
  205. package/dist/db/tables/apiKeyAdmissions.d.ts +28 -2
  206. package/dist/db/tables/apiKeyAdmissions.d.ts.map +1 -1
  207. package/dist/db/tables/apiKeyAdmissions.js +65 -9
  208. package/dist/db/tables/apiKeyAdmissions.js.map +1 -1
  209. package/dist/db/tables/apiKeyOwnerTombstones.d.ts +2 -0
  210. package/dist/db/tables/apiKeyOwnerTombstones.d.ts.map +1 -1
  211. package/dist/db/tables/apiKeyOwnerTombstones.js +2 -2
  212. package/dist/db/tables/apiKeyOwnerTombstones.js.map +1 -1
  213. package/dist/db/tables/authAccounts.d.ts.map +1 -1
  214. package/dist/db/tables/authAccounts.js +1 -0
  215. package/dist/db/tables/authAccounts.js.map +1 -1
  216. package/dist/db/tables/earnVaults.d.ts +5 -1
  217. package/dist/db/tables/earnVaults.d.ts.map +1 -1
  218. package/dist/db/tables/earnVaults.js +12 -1
  219. package/dist/db/tables/earnVaults.js.map +1 -1
  220. package/dist/db/tables/organizations.d.ts +4 -2
  221. package/dist/db/tables/organizations.d.ts.map +1 -1
  222. package/dist/db/tables/organizations.js +8 -34
  223. package/dist/db/tables/organizations.js.map +1 -1
  224. package/dist/db/tables/requestUsage.d.ts +5 -1
  225. package/dist/db/tables/requestUsage.d.ts.map +1 -1
  226. package/dist/db/tables/requestUsage.js +10 -2
  227. package/dist/db/tables/requestUsage.js.map +1 -1
  228. package/dist/db/tables/rewardEligibilityAssociations.d.ts +13 -0
  229. package/dist/db/tables/rewardEligibilityAssociations.d.ts.map +1 -1
  230. package/dist/db/tables/rewardEligibilityAssociations.js +11 -0
  231. package/dist/db/tables/rewardEligibilityAssociations.js.map +1 -1
  232. package/dist/db/tables/rewardRuns.d.ts.map +1 -1
  233. package/dist/db/tables/rewardRuns.js +4 -0
  234. package/dist/db/tables/rewardRuns.js.map +1 -1
  235. package/dist/db/tables/rewardTransactionAttempts.d.ts.map +1 -1
  236. package/dist/db/tables/rewardTransactionAttempts.js +2 -0
  237. package/dist/db/tables/rewardTransactionAttempts.js.map +1 -1
  238. package/dist/db/tables/routesDepositAddresses.d.ts +29 -0
  239. package/dist/db/tables/routesDepositAddresses.d.ts.map +1 -1
  240. package/dist/db/tables/routesDepositAddresses.js +84 -31
  241. package/dist/db/tables/routesDepositAddresses.js.map +1 -1
  242. package/dist/db/tables/routesDeposits.d.ts.map +1 -1
  243. package/dist/db/tables/routesDeposits.js +31 -21
  244. package/dist/db/tables/routesDeposits.js.map +1 -1
  245. package/dist/db/tables/routesIdempotency.d.ts.map +1 -1
  246. package/dist/db/tables/routesIdempotency.js +2 -0
  247. package/dist/db/tables/routesIdempotency.js.map +1 -1
  248. package/dist/db/tables/routesPolicies.d.ts +58 -0
  249. package/dist/db/tables/routesPolicies.d.ts.map +1 -0
  250. package/dist/db/tables/routesPolicies.js +198 -0
  251. package/dist/db/tables/routesPolicies.js.map +1 -0
  252. package/dist/db/tables/routesTransferSubsidies.d.ts +22 -0
  253. package/dist/db/tables/routesTransferSubsidies.d.ts.map +1 -1
  254. package/dist/db/tables/routesTransferSubsidies.js +41 -0
  255. package/dist/db/tables/routesTransferSubsidies.js.map +1 -1
  256. package/dist/db/tables/routesTransferSubsidyNonces.d.ts.map +1 -1
  257. package/dist/db/tables/routesTransferSubsidyNonces.js +12 -4
  258. package/dist/db/tables/routesTransferSubsidyNonces.js.map +1 -1
  259. package/dist/db/tables/routesTransfers.d.ts +26 -1
  260. package/dist/db/tables/routesTransfers.d.ts.map +1 -1
  261. package/dist/db/tables/routesTransfers.js +36 -6
  262. package/dist/db/tables/routesTransfers.js.map +1 -1
  263. package/dist/db/tables/sponsoredTransactions.d.ts +45 -13
  264. package/dist/db/tables/sponsoredTransactions.d.ts.map +1 -1
  265. package/dist/db/tables/sponsoredTransactions.js +144 -33
  266. package/dist/db/tables/sponsoredTransactions.js.map +1 -1
  267. package/dist/db/tables/users.d.ts +2 -0
  268. package/dist/db/tables/users.d.ts.map +1 -1
  269. package/dist/db/tables/users.js +11 -0
  270. package/dist/db/tables/users.js.map +1 -1
  271. package/dist/handlers/internal/multisig.d.ts +1 -1
  272. package/dist/handlers/internal/multisig.d.ts.map +1 -1
  273. package/dist/handlers/internal/multisig.js +3 -2
  274. package/dist/handlers/internal/multisig.js.map +1 -1
  275. package/dist/handlers/relay.d.ts +2 -0
  276. package/dist/handlers/relay.d.ts.map +1 -1
  277. package/dist/handlers/relay.js +34 -15
  278. package/dist/handlers/relay.js.map +1 -1
  279. package/dist/internal/Auth.d.ts +57 -6
  280. package/dist/internal/Auth.d.ts.map +1 -1
  281. package/dist/internal/Auth.js +182 -78
  282. package/dist/internal/Auth.js.map +1 -1
  283. package/dist/internal/BetterAuth.d.ts +22 -0
  284. package/dist/internal/BetterAuth.d.ts.map +1 -1
  285. package/dist/internal/BetterAuth.js +17 -14
  286. package/dist/internal/BetterAuth.js.map +1 -1
  287. package/dist/internal/Cache.d.ts +5 -0
  288. package/dist/internal/Cache.d.ts.map +1 -1
  289. package/dist/internal/Cache.js +3 -1
  290. package/dist/internal/Cache.js.map +1 -1
  291. package/dist/internal/CliAuth.d.ts +243 -0
  292. package/dist/internal/CliAuth.d.ts.map +1 -0
  293. package/dist/internal/CliAuth.js +249 -0
  294. package/dist/internal/CliAuth.js.map +1 -0
  295. package/dist/internal/EarnSharePrices.d.ts +1 -1
  296. package/dist/internal/EarnSharePrices.d.ts.map +1 -1
  297. package/dist/internal/EarnSharePrices.js +7 -3
  298. package/dist/internal/EarnSharePrices.js.map +1 -1
  299. package/dist/internal/EarnVaults.d.ts +47 -0
  300. package/dist/internal/EarnVaults.d.ts.map +1 -1
  301. package/dist/internal/EarnVaults.js +188 -4
  302. package/dist/internal/EarnVaults.js.map +1 -1
  303. package/dist/internal/EarnWithdrawals.d.ts +73 -0
  304. package/dist/internal/EarnWithdrawals.d.ts.map +1 -0
  305. package/dist/internal/EarnWithdrawals.js +189 -0
  306. package/dist/internal/EarnWithdrawals.js.map +1 -0
  307. package/dist/internal/ExecutionContext.d.ts +21 -0
  308. package/dist/internal/ExecutionContext.d.ts.map +1 -0
  309. package/dist/internal/ExecutionContext.js +16 -0
  310. package/dist/internal/ExecutionContext.js.map +1 -0
  311. package/dist/internal/Log.d.ts +7 -3
  312. package/dist/internal/Log.d.ts.map +1 -1
  313. package/dist/internal/Log.js +163 -130
  314. package/dist/internal/Log.js.map +1 -1
  315. package/dist/internal/MetricSink.d.ts.map +1 -1
  316. package/dist/internal/MetricSink.js +26 -1
  317. package/dist/internal/MetricSink.js.map +1 -1
  318. package/dist/internal/RateLimit.d.ts +67 -0
  319. package/dist/internal/RateLimit.d.ts.map +1 -1
  320. package/dist/internal/RateLimit.js +174 -27
  321. package/dist/internal/RateLimit.js.map +1 -1
  322. package/dist/internal/Store.d.ts +6 -0
  323. package/dist/internal/Store.d.ts.map +1 -1
  324. package/dist/internal/Store.js +4 -5
  325. package/dist/internal/Store.js.map +1 -1
  326. package/dist/internal/Timing.d.ts +6 -0
  327. package/dist/internal/Timing.d.ts.map +1 -1
  328. package/dist/internal/Timing.js +21 -1
  329. package/dist/internal/Timing.js.map +1 -1
  330. package/dist/internal/Tron.d.ts +124 -0
  331. package/dist/internal/Tron.d.ts.map +1 -0
  332. package/dist/internal/Tron.js +202 -0
  333. package/dist/internal/Tron.js.map +1 -0
  334. package/dist/internal/Viem.d.ts +4 -0
  335. package/dist/internal/Viem.d.ts.map +1 -1
  336. package/dist/internal/Viem.js +25 -6
  337. package/dist/internal/Viem.js.map +1 -1
  338. package/dist/internal/rewards/Read.d.ts +2 -2
  339. package/dist/internal/rewards/Read.d.ts.map +1 -1
  340. package/dist/internal/rewards/Read.js +11 -2
  341. package/dist/internal/rewards/Read.js.map +1 -1
  342. package/dist/internal/routes/Action.d.ts +27 -0
  343. package/dist/internal/routes/Action.d.ts.map +1 -1
  344. package/dist/internal/routes/Action.js +49 -1
  345. package/dist/internal/routes/Action.js.map +1 -1
  346. package/dist/internal/routes/Chain.d.ts +2 -0
  347. package/dist/internal/routes/Chain.d.ts.map +1 -1
  348. package/dist/internal/routes/Chain.js +4 -0
  349. package/dist/internal/routes/Chain.js.map +1 -1
  350. package/dist/internal/routes/DepositAddress.d.ts.map +1 -1
  351. package/dist/internal/routes/DepositAddress.js +5 -0
  352. package/dist/internal/routes/DepositAddress.js.map +1 -1
  353. package/dist/internal/routes/Evidence.d.ts.map +1 -1
  354. package/dist/internal/routes/Evidence.js +6 -2
  355. package/dist/internal/routes/Evidence.js.map +1 -1
  356. package/dist/internal/routes/EvmTransferSettlement.d.ts +17 -0
  357. package/dist/internal/routes/EvmTransferSettlement.d.ts.map +1 -0
  358. package/dist/internal/routes/EvmTransferSettlement.js +196 -0
  359. package/dist/internal/routes/EvmTransferSettlement.js.map +1 -0
  360. package/dist/internal/routes/Policy.d.ts +161 -0
  361. package/dist/internal/routes/Policy.d.ts.map +1 -0
  362. package/dist/internal/routes/Policy.js +249 -0
  363. package/dist/internal/routes/Policy.js.map +1 -0
  364. package/dist/internal/routes/Provider.d.ts +66 -3
  365. package/dist/internal/routes/Provider.d.ts.map +1 -1
  366. package/dist/internal/routes/Provider.js +106 -27
  367. package/dist/internal/routes/Provider.js.map +1 -1
  368. package/dist/internal/routes/Quota.d.ts +57 -0
  369. package/dist/internal/routes/Quota.d.ts.map +1 -0
  370. package/dist/internal/routes/Quota.js +144 -0
  371. package/dist/internal/routes/Quota.js.map +1 -0
  372. package/dist/internal/routes/Reconciliation.d.ts.map +1 -1
  373. package/dist/internal/routes/Reconciliation.js +163 -47
  374. package/dist/internal/routes/Reconciliation.js.map +1 -1
  375. package/dist/internal/routes/SolanaTransferSettlement.d.ts +12 -0
  376. package/dist/internal/routes/SolanaTransferSettlement.d.ts.map +1 -0
  377. package/dist/internal/routes/SolanaTransferSettlement.js +220 -0
  378. package/dist/internal/routes/SolanaTransferSettlement.js.map +1 -0
  379. package/dist/internal/routes/SolanaTransferSubsidy.d.ts +172 -0
  380. package/dist/internal/routes/SolanaTransferSubsidy.d.ts.map +1 -0
  381. package/dist/internal/routes/SolanaTransferSubsidy.js +564 -0
  382. package/dist/internal/routes/SolanaTransferSubsidy.js.map +1 -0
  383. package/dist/internal/routes/Subsidy.d.ts +2 -2
  384. package/dist/internal/routes/Subsidy.d.ts.map +1 -1
  385. package/dist/internal/routes/Subsidy.js +2 -2
  386. package/dist/internal/routes/Subsidy.js.map +1 -1
  387. package/dist/internal/routes/Transfer.d.ts +229 -1
  388. package/dist/internal/routes/Transfer.d.ts.map +1 -1
  389. package/dist/internal/routes/Transfer.js +644 -7
  390. package/dist/internal/routes/Transfer.js.map +1 -1
  391. package/dist/internal/routes/TransferReconciliation.d.ts +6 -0
  392. package/dist/internal/routes/TransferReconciliation.d.ts.map +1 -1
  393. package/dist/internal/routes/TransferReconciliation.js +83 -159
  394. package/dist/internal/routes/TransferReconciliation.js.map +1 -1
  395. package/dist/internal/routes/TransferSettlement.d.ts +45 -0
  396. package/dist/internal/routes/TransferSettlement.d.ts.map +1 -0
  397. package/dist/internal/routes/TransferSettlement.js +2 -0
  398. package/dist/internal/routes/TransferSettlement.js.map +1 -0
  399. package/dist/internal/routes/TransferSubsidy.d.ts +23 -8
  400. package/dist/internal/routes/TransferSubsidy.d.ts.map +1 -1
  401. package/dist/internal/routes/TransferSubsidy.js +64 -5
  402. package/dist/internal/routes/TransferSubsidy.js.map +1 -1
  403. package/dist/internal/routes/TronTransferSettlement.d.ts +12 -0
  404. package/dist/internal/routes/TronTransferSettlement.d.ts.map +1 -0
  405. package/dist/internal/routes/TronTransferSettlement.js +201 -0
  406. package/dist/internal/routes/TronTransferSettlement.js.map +1 -0
  407. package/dist/internal/routes/TronTransferSubsidy.d.ts +174 -0
  408. package/dist/internal/routes/TronTransferSubsidy.d.ts.map +1 -0
  409. package/dist/internal/routes/TronTransferSubsidy.js +439 -0
  410. package/dist/internal/routes/TronTransferSubsidy.js.map +1 -0
  411. package/dist/internal/routes/index.d.ts +3 -0
  412. package/dist/internal/routes/index.d.ts.map +1 -1
  413. package/dist/internal/routes/index.js +3 -0
  414. package/dist/internal/routes/index.js.map +1 -1
  415. package/dist/internal/routes/providers/across.d.ts +3 -0
  416. package/dist/internal/routes/providers/across.d.ts.map +1 -1
  417. package/dist/internal/routes/providers/across.js +11 -0
  418. package/dist/internal/routes/providers/across.js.map +1 -1
  419. package/dist/internal/routes/providers/legacyMesh.d.ts +29 -0
  420. package/dist/internal/routes/providers/legacyMesh.d.ts.map +1 -0
  421. package/dist/internal/routes/providers/legacyMesh.js +474 -0
  422. package/dist/internal/routes/providers/legacyMesh.js.map +1 -0
  423. package/dist/internal/routes/providers/legacyMeshDelivery.d.ts +59 -0
  424. package/dist/internal/routes/providers/legacyMeshDelivery.d.ts.map +1 -0
  425. package/dist/internal/routes/providers/legacyMeshDelivery.js +229 -0
  426. package/dist/internal/routes/providers/legacyMeshDelivery.js.map +1 -0
  427. package/dist/internal/routes/providers/legacyMeshOutbound.d.ts +19 -0
  428. package/dist/internal/routes/providers/legacyMeshOutbound.d.ts.map +1 -0
  429. package/dist/internal/routes/providers/legacyMeshOutbound.js +457 -0
  430. package/dist/internal/routes/providers/legacyMeshOutbound.js.map +1 -0
  431. package/dist/internal/routes/providers/legacyMeshOutboundDelivery.d.ts +123 -0
  432. package/dist/internal/routes/providers/legacyMeshOutboundDelivery.d.ts.map +1 -0
  433. package/dist/internal/routes/providers/legacyMeshOutboundDelivery.js +333 -0
  434. package/dist/internal/routes/providers/legacyMeshOutboundDelivery.js.map +1 -0
  435. package/dist/internal/routes/providers/propAmm.d.ts +70 -0
  436. package/dist/internal/routes/providers/propAmm.d.ts.map +1 -0
  437. package/dist/internal/routes/providers/propAmm.js +524 -0
  438. package/dist/internal/routes/providers/propAmm.js.map +1 -0
  439. package/dist/internal/routes/providers/relay.d.ts +3 -0
  440. package/dist/internal/routes/providers/relay.d.ts.map +1 -1
  441. package/dist/internal/routes/providers/relay.js +352 -41
  442. package/dist/internal/routes/providers/relay.js.map +1 -1
  443. package/dist/internal/routes/providers/rhino.d.ts +3 -0
  444. package/dist/internal/routes/providers/rhino.d.ts.map +1 -1
  445. package/dist/internal/routes/providers/rhino.js +11 -0
  446. package/dist/internal/routes/providers/rhino.js.map +1 -1
  447. package/dist/internal/routes/providers/squid.d.ts +3 -0
  448. package/dist/internal/routes/providers/squid.d.ts.map +1 -1
  449. package/dist/internal/routes/providers/squid.js +19 -0
  450. package/dist/internal/routes/providers/squid.js.map +1 -1
  451. package/dist/internal/routes/providers/stargate.d.ts.map +1 -1
  452. package/dist/internal/routes/providers/stargate.js +22 -9
  453. package/dist/internal/routes/providers/stargate.js.map +1 -1
  454. package/dist/internal/routes/providers/symbiosis.d.ts.map +1 -1
  455. package/dist/internal/routes/providers/symbiosis.js +13 -17
  456. package/dist/internal/routes/providers/symbiosis.js.map +1 -1
  457. package/dist/providers/index.d.ts +14 -0
  458. package/dist/providers/index.d.ts.map +1 -1
  459. package/dist/providers/index.js +6 -0
  460. package/dist/providers/index.js.map +1 -1
  461. package/package.json +16 -6
  462. package/src/ApiKey.ts +7 -3
  463. package/src/ApiKeys.test.ts +652 -8
  464. package/src/ApiKeys.ts +191 -11
  465. package/src/App.test.ts +405 -18
  466. package/src/App.ts +51 -15
  467. package/src/Client.test-d.ts +157 -10
  468. package/src/Client.test.ts +4 -4
  469. package/src/Scope.ts +1 -2
  470. package/src/admin/App.ts +11 -5
  471. package/src/admin/apps/api-keys.test.ts +98 -2
  472. package/src/admin/apps/api-keys.ts +21 -12
  473. package/src/admin/apps/earn-vaults.test.ts +76 -7
  474. package/src/admin/apps/earn-vaults.ts +47 -8
  475. package/src/admin/apps/organizations.test.ts +147 -31
  476. package/src/admin/apps/organizations.ts +5 -4
  477. package/src/admin/apps/route-policies.test.ts +220 -0
  478. package/src/admin/apps/route-policies.ts +322 -0
  479. package/src/admin/apps/routes-support.test.ts +107 -2
  480. package/src/admin/apps/routes-support.ts +43 -3
  481. package/src/admin/apps/routes.test.ts +150 -0
  482. package/src/admin/apps/routes.ts +97 -1
  483. package/src/admin/apps/scopes.test.ts +1 -1
  484. package/src/admin/index.ts +0 -1
  485. package/src/admin/ui/plugin.ts +2 -1
  486. package/src/admin/ui/src/components/Dialog.tsx +1 -1
  487. package/src/admin/ui/src/components/EarnVaultForm.tsx +45 -0
  488. package/src/admin/ui/src/components/RoutePicker.tsx +79 -0
  489. package/src/admin/ui/src/lib/earn-vaults.ts +1 -1
  490. package/src/admin/ui/src/lib/route-policies.test.ts +452 -0
  491. package/src/admin/ui/src/lib/route-policies.ts +232 -0
  492. package/src/admin/ui/src/lib/routes.ts +34 -0
  493. package/src/admin/ui/src/routeTree.gen.ts +21 -0
  494. package/src/admin/ui/src/routes/api-keys.tsx +21 -2
  495. package/src/admin/ui/src/routes/early-access.tsx +1 -0
  496. package/src/admin/ui/src/routes/earn.vaults.tsx +1 -0
  497. package/src/admin/ui/src/routes/earn.vaults_.$vaultId.edit.tsx +22 -0
  498. package/src/admin/ui/src/routes/earn.vaults_.new.tsx +10 -0
  499. package/src/admin/ui/src/routes/organizations.tsx +1 -0
  500. package/src/admin/ui/src/routes/organizations_.$orgId.tsx +18 -3
  501. package/src/admin/ui/src/routes/route-policies.tsx +678 -0
  502. package/src/admin/ui/src/routes/routes.tsx +85 -2
  503. package/src/admin/ui/src/routes/routes_.support.tsx +6 -22
  504. package/src/admin/ui/src/routes/subsidies.tsx +1 -0
  505. package/src/admin/ui/src/routes/verified-tokens.tsx +1 -0
  506. package/src/admin/ui.generated.ts +258 -202
  507. package/src/analytics/Analytics.test.ts +4 -50
  508. package/src/analytics/Analytics.ts +65 -1
  509. package/src/analytics/tables/requestEvents.test.ts +402 -1
  510. package/src/analytics/tables/requestEvents.ts +62 -93
  511. package/src/apps/data/routes/activities.test.ts +315 -14
  512. package/src/apps/data/routes/activities.ts +60 -0
  513. package/src/apps/data/routes/balances.ts +5 -7
  514. package/src/apps/data/routes/earn.bench.ts +18 -0
  515. package/src/apps/data/routes/earn.local.test.ts +507 -0
  516. package/src/apps/data/routes/earn.test.ts +405 -127
  517. package/src/apps/data/routes/earn.ts +660 -270
  518. package/src/apps/data/routes/exchanges.bench.ts +3 -1
  519. package/src/apps/data/routes/exchanges.test.ts +166 -2
  520. package/src/apps/data/routes/exchanges.ts +308 -101
  521. package/src/apps/data/routes/fee-amm.test.ts +134 -2
  522. package/src/apps/data/routes/fee-amm.ts +122 -60
  523. package/src/apps/data/routes/receipts.test.ts +21 -18
  524. package/src/apps/data/routes/rpc.test.ts +2 -2
  525. package/src/apps/data/routes/tokens.provenance.test.ts +157 -0
  526. package/src/apps/data/routes/tokens.test.ts +4 -4
  527. package/src/apps/data/routes/tokens.ts +11 -6
  528. package/src/apps/data/routes/transactions.test.ts +29 -0
  529. package/src/apps/data/routes/transactions.ts +33 -22
  530. package/src/apps/data/routes/webhooks.test.ts +12 -3
  531. package/src/apps/data/routes/webhooks.ts +2 -1
  532. package/src/apps/management/App.ts +4 -0
  533. package/src/apps/management/Billing.test.ts +253 -27
  534. package/src/apps/management/Billing.ts +83 -29
  535. package/src/apps/management/routes/api-keys.test.ts +1 -1
  536. package/src/apps/management/routes/api-keys.ts +85 -11
  537. package/src/apps/management/routes/billing.test.ts +68 -4
  538. package/src/apps/management/routes/cli.test.ts +370 -0
  539. package/src/apps/management/routes/cli.ts +533 -0
  540. package/src/apps/management/routes/me.test.ts +14 -4
  541. package/src/apps/management/routes/orgs.test.ts +108 -4
  542. package/src/apps/management/routes/orgs.ts +7 -2
  543. package/src/apps/management/routes/usage.test.ts +2 -2
  544. package/src/apps/mpp/internal/Policy.test.ts +51 -4
  545. package/src/apps/mpp/internal/Policy.ts +6 -2
  546. package/src/apps/mpp/internal/Sponsorship.test.ts +29 -0
  547. package/src/apps/mpp/internal/Sponsorship.ts +6 -4
  548. package/src/apps/relay/App.test.ts +85 -1
  549. package/src/apps/relay/App.ts +28 -4
  550. package/src/apps/relay/Sponsorships.test.ts +97 -1
  551. package/src/apps/relay/Sponsorships.ts +77 -66
  552. package/src/apps/routes/Access.test.ts +319 -0
  553. package/src/apps/routes/Access.ts +147 -0
  554. package/src/apps/routes/App.ts +10 -0
  555. package/src/apps/routes/routes/chains.test.ts +3 -2
  556. package/src/apps/routes/routes/deposit-addresses.test.ts +978 -34
  557. package/src/apps/routes/routes/deposit-addresses.ts +243 -32
  558. package/src/apps/routes/routes/propAmm.local.test.ts +951 -0
  559. package/src/apps/routes/routes/quotes.test.ts +81 -8
  560. package/src/apps/routes/routes/quotes.ts +109 -27
  561. package/src/apps/routes/routes/transfers.test.ts +252 -15
  562. package/src/apps/routes/routes/transfers.ts +212 -33
  563. package/src/cli/ApiKeys.test.ts +265 -0
  564. package/src/cli/ApiKeys.ts +189 -0
  565. package/src/cli/Cli.test.ts +188 -0
  566. package/src/cli/Cli.ts +280 -12
  567. package/src/cli/Credentials.test.ts +122 -0
  568. package/src/cli/Credentials.ts +144 -0
  569. package/src/cli/Spec.test.ts +133 -0
  570. package/src/cli/Spec.ts +132 -0
  571. package/src/cli/bin.test.ts +49 -0
  572. package/src/cli/bin.ts +5 -1
  573. package/src/cli/commands/auth.test.ts +138 -0
  574. package/src/cli/commands/auth.ts +254 -0
  575. package/src/cli/commands/keys.test.ts +68 -0
  576. package/src/cli/commands/keys.ts +125 -0
  577. package/src/cloudflare.ts +184 -36
  578. package/src/db/Db.test.ts +877 -0
  579. package/src/db/Db.ts +498 -1
  580. package/src/db/Schema.ts +75 -4
  581. package/src/db/tables/apiKeyAdmissions.test.ts +57 -0
  582. package/src/db/tables/apiKeyAdmissions.ts +101 -11
  583. package/src/db/tables/apiKeyOwnerTombstones.ts +2 -2
  584. package/src/db/tables/authAccounts.test.ts +30 -0
  585. package/src/db/tables/authAccounts.ts +1 -0
  586. package/src/db/tables/earnVaults.test.ts +34 -0
  587. package/src/db/tables/earnVaults.ts +17 -2
  588. package/src/db/tables/organizations.test.ts +148 -84
  589. package/src/db/tables/organizations.ts +11 -43
  590. package/src/db/tables/requestUsage.ts +13 -2
  591. package/src/db/tables/rewardCampaigns.test.ts +163 -0
  592. package/src/db/tables/rewardEligibilityAssociations.test.ts +14 -0
  593. package/src/db/tables/rewardEligibilityAssociations.ts +24 -0
  594. package/src/db/tables/rewardRuns.ts +4 -0
  595. package/src/db/tables/rewardTransactionAttempts.ts +2 -0
  596. package/src/db/tables/routesDepositAddresses.test.ts +263 -0
  597. package/src/db/tables/routesDepositAddresses.ts +118 -34
  598. package/src/db/tables/routesDeposits.test.ts +66 -5
  599. package/src/db/tables/routesDeposits.ts +47 -26
  600. package/src/db/tables/routesIdempotency.test.ts +80 -0
  601. package/src/db/tables/routesIdempotency.ts +2 -0
  602. package/src/db/tables/routesPolicies.test.ts +143 -0
  603. package/src/db/tables/routesPolicies.ts +251 -0
  604. package/src/db/tables/routesTransferSubsidies.ts +64 -0
  605. package/src/db/tables/routesTransferSubsidyNonces.ts +16 -4
  606. package/src/db/tables/routesTransfers.test.ts +183 -2
  607. package/src/db/tables/routesTransfers.ts +65 -6
  608. package/src/db/tables/sponsoredTransactions.test.ts +351 -76
  609. package/src/db/tables/sponsoredTransactions.ts +182 -38
  610. package/src/db/tables/users.test.ts +51 -0
  611. package/src/db/tables/users.ts +12 -0
  612. package/src/handlers/internal/multisig.store.test.ts +120 -0
  613. package/src/handlers/internal/multisig.test.ts +389 -0
  614. package/src/handlers/internal/multisig.ts +13 -10
  615. package/src/handlers/relay.test.ts +259 -83
  616. package/src/handlers/relay.ts +36 -17
  617. package/src/internal/Auth.test.ts +291 -8
  618. package/src/internal/Auth.ts +227 -96
  619. package/src/internal/BetterAuth.test.ts +58 -22
  620. package/src/internal/BetterAuth.ts +23 -17
  621. package/src/internal/Cache.ts +3 -1
  622. package/src/internal/CliAuth.test.ts +279 -0
  623. package/src/internal/CliAuth.ts +319 -0
  624. package/src/internal/EarnSharePrices.test.ts +25 -0
  625. package/src/internal/EarnSharePrices.ts +9 -2
  626. package/src/internal/EarnVaults.test.ts +67 -0
  627. package/src/internal/EarnVaults.ts +299 -4
  628. package/src/internal/EarnWithdrawals.test.ts +315 -0
  629. package/src/internal/EarnWithdrawals.ts +266 -0
  630. package/src/internal/ExecutionContext.ts +31 -0
  631. package/src/internal/Log.test.ts +210 -0
  632. package/src/internal/Log.ts +180 -142
  633. package/src/internal/MetricSink.test.ts +190 -15
  634. package/src/internal/MetricSink.ts +27 -1
  635. package/src/internal/RateLimit.test.ts +144 -8
  636. package/src/internal/RateLimit.ts +254 -26
  637. package/src/internal/Store.ts +4 -5
  638. package/src/internal/Timing.test.ts +32 -0
  639. package/src/internal/Timing.ts +20 -1
  640. package/src/internal/Tron.test-d.ts +22 -0
  641. package/src/internal/Tron.test.ts +94 -0
  642. package/src/internal/Tron.ts +289 -0
  643. package/src/internal/Viem.rpc.test.ts +76 -0
  644. package/src/internal/Viem.ts +29 -6
  645. package/src/internal/rewards/Read.test.ts +109 -0
  646. package/src/internal/rewards/Read.ts +13 -4
  647. package/src/internal/routes/Action.test.ts +70 -0
  648. package/src/internal/routes/Action.ts +76 -1
  649. package/src/internal/routes/Chain.test.ts +18 -0
  650. package/src/internal/routes/Chain.ts +5 -0
  651. package/src/internal/routes/DepositAddress.ts +5 -0
  652. package/src/internal/routes/Evidence.test.ts +64 -0
  653. package/src/internal/routes/Evidence.ts +11 -3
  654. package/src/internal/routes/EvmTransferSettlement.ts +213 -0
  655. package/src/internal/routes/Policy.test.ts +316 -0
  656. package/src/internal/routes/Policy.ts +399 -0
  657. package/src/internal/routes/Provider.test.ts +103 -2
  658. package/src/internal/routes/Provider.ts +149 -27
  659. package/src/internal/routes/Quota.test.ts +149 -0
  660. package/src/internal/routes/Quota.ts +226 -0
  661. package/src/internal/routes/Reconciliation.local.test.ts +285 -0
  662. package/src/internal/routes/Reconciliation.test.ts +371 -13
  663. package/src/internal/routes/Reconciliation.ts +193 -42
  664. package/src/internal/routes/SolanaTransferSettlement.ts +232 -0
  665. package/src/internal/routes/SolanaTransferSubsidy.test.ts +471 -0
  666. package/src/internal/routes/SolanaTransferSubsidy.ts +760 -0
  667. package/src/internal/routes/SourceObservation.test.ts +221 -0
  668. package/src/internal/routes/Subsidy.local.test.ts +46 -0
  669. package/src/internal/routes/Subsidy.ts +4 -2
  670. package/src/internal/routes/Transfer.solana.test.ts +389 -0
  671. package/src/internal/routes/Transfer.test.ts +130 -1
  672. package/src/internal/routes/Transfer.tron.test.ts +172 -0
  673. package/src/internal/routes/Transfer.ts +866 -8
  674. package/src/internal/routes/TransferReconciliation.test.ts +26 -4
  675. package/src/internal/routes/TransferReconciliation.ts +91 -166
  676. package/src/internal/routes/TransferSettlement.ts +48 -0
  677. package/src/internal/routes/TransferSubsidy.local.test.ts +143 -0
  678. package/src/internal/routes/TransferSubsidy.test.ts +34 -4
  679. package/src/internal/routes/TransferSubsidy.ts +87 -12
  680. package/src/internal/routes/TronTransferSettlement.ts +212 -0
  681. package/src/internal/routes/TronTransferSubsidy.test.ts +109 -0
  682. package/src/internal/routes/TronTransferSubsidy.ts +619 -0
  683. package/src/internal/routes/index.test.ts +3 -0
  684. package/src/internal/routes/index.ts +3 -0
  685. package/src/internal/routes/providers/across.ts +13 -0
  686. package/src/internal/routes/providers/index.test.ts +141 -0
  687. package/src/internal/routes/providers/legacyMesh.test.ts +484 -0
  688. package/src/internal/routes/providers/legacyMesh.ts +633 -0
  689. package/src/internal/routes/providers/legacyMeshDelivery.test.ts +306 -0
  690. package/src/internal/routes/providers/legacyMeshDelivery.ts +320 -0
  691. package/src/internal/routes/providers/legacyMeshOutbound.test.ts +401 -0
  692. package/src/internal/routes/providers/legacyMeshOutbound.ts +566 -0
  693. package/src/internal/routes/providers/legacyMeshOutboundDelivery.ts +473 -0
  694. package/src/internal/routes/providers/propAmm.ts +640 -0
  695. package/src/internal/routes/providers/relay.test.ts +1263 -41
  696. package/src/internal/routes/providers/relay.ts +423 -38
  697. package/src/internal/routes/providers/rhino.ts +14 -1
  698. package/src/internal/routes/providers/squid.ts +21 -0
  699. package/src/internal/routes/providers/stargate.test.ts +105 -1
  700. package/src/internal/routes/providers/stargate.ts +22 -9
  701. package/src/internal/routes/providers/symbiosis.ts +13 -47
  702. package/src/providers/index.test.ts +2 -0
  703. package/src/providers/index.ts +18 -0
  704. package/dist/admin/Access.d.ts +0 -39
  705. package/dist/admin/Access.d.ts.map +0 -1
  706. package/dist/admin/Access.js +0 -73
  707. package/dist/admin/Access.js.map +0 -1
  708. package/src/admin/Access.test.ts +0 -130
  709. package/src/admin/Access.ts +0 -85
@@ -1,5 +1,6 @@
1
1
  import { Hono, type Context } from 'hono'
2
2
  import { AbiEvent, AbiParameters, Hash, type Hex } from 'ox'
3
+ import { zeroAddress } from 'viem'
3
4
  import { Abis, Addresses } from 'viem/tempo'
4
5
  import * as z from 'zod/mini'
5
6
 
@@ -7,6 +8,7 @@ import type * as App from '../../../App.js'
7
8
  import * as Auth from '../../../internal/Auth.js'
8
9
  import * as Cache from '../../../internal/Cache.js'
9
10
  import * as Cursor from '../../../internal/Cursor.js'
11
+ import type * as Log from '../../../internal/Log.js'
10
12
  import * as OpenApi from '../../../internal/OpenApi.js'
11
13
  import * as Response from '../../../internal/Response.js'
12
14
  import * as Schema from '../../../internal/Schema.js'
@@ -695,35 +697,16 @@ declare namespace listPools {
695
697
  }
696
698
  }
697
699
 
698
- /**
699
- * The set of token addresses usable to pay transaction fees on a chain: the
700
- * curated verified tokens that have at least one Fee AMM pool (i.e. appear as a
701
- * `userToken` / topic2 in the FeeManager's `Mint` logs), plus the protocol
702
- * default fee token (`pathUSD`), which pays fees without needing a pool.
703
- * Addresses are lowercased to match the indexer's stored casing.
704
- *
705
- * The set is intentionally gated to the verified list rather than every pooled
706
- * token: anyone can mint a single-mint spam pool, so the raw set of pool
707
- * `userToken`s is unbounded (tens of thousands on busy chains) and those
708
- * liquidity-less pools can't actually settle fees. Restricting to verified
709
- * tokens keeps the set small (a handful of USD stablecoins), bounds the scan
710
- * (the `topic2 IN (…)` candidate list is the verified list), and matches the
711
- * tokens fees are realistically paid in.
712
- *
713
- * Memoized per chain and verified-snapshot version (the only inputs), so
714
- * callers — e.g. the address balances endpoint — can flag which holdings are
715
- * fee-usable without a second `/fee-amm/pools` query.
716
- */
700
+ /** Returns lowercased verified tokens currently usable for transaction fees. The protocol default (`pathUSD`) is always included. */
717
701
  export async function feeTokenSet(
718
702
  c: Context<App.Environment>,
719
703
  chainId: z.output<typeof Schema.ChainId>,
720
704
  ): Promise<Set<string>> {
721
705
  const store = c.get('store')
722
- const tidx = c.get('getTidx')(chainId)
723
706
  const snapshot = await VerifiedTokens.snapshot(c, chainId)
724
707
  // pathUSD is always fee-usable; the verified tokens are the only other
725
708
  // candidates we probe for a pool. With no verified candidates there is
726
- // nothing to query — pathUSD stands alone.
709
+ // nothing to query, so pathUSD stands alone.
727
710
  const candidates = snapshot.list.map((token) => token.address.toLowerCase())
728
711
  if (candidates.length === 0) return new Set([pathUsd])
729
712
 
@@ -733,36 +716,106 @@ export async function feeTokenSet(
733
716
  Store.memoize(
734
717
  async () => {
735
718
  const tokens = new Set<string>([pathUsd])
736
- // PostgreSQL's `topic2` index proves negative lookups without scanning
737
- // FeeManager history. Probe serially so an uncapped verified list
738
- // cannot fan out indexer load.
739
- for (const address of candidates) {
740
- const topic = padTopic(address as `0x${string}`)
741
- const result = await tidx.fetch({
742
- chainId,
743
- engine: 'postgres',
744
- query: `
745
- SELECT 1 AS present
746
- FROM logs
747
- WHERE address = '${feeManager}' AND selector IN ('${mintTopic}', '${legacyMintTopic}')
748
- AND topic2 = '${topic}'
749
- LIMIT 1
750
- ` as string,
719
+ const validatorTokens = await getValidatorTokens(c, { chainId })
720
+ // Verified candidates prevent permissionless spam pools from expanding
721
+ // the lookup. Small batches also bound RPC fan-out for Zone clients.
722
+ const probes = candidates
723
+ .filter((address) => {
724
+ if (!validatorTokens.includes(address)) return true
725
+ tokens.add(address)
726
+ return false
751
727
  })
752
- if (result.rows.length > 0) tokens.add(address)
728
+ .flatMap((userToken) =>
729
+ validatorTokens.map((validatorToken) => ({ userToken, validatorToken })),
730
+ )
731
+ const unresolved = new Map<string, unknown>()
732
+ for (let index = 0; index < probes.length; index += 8) {
733
+ const group = probes.slice(index, index + 8)
734
+ const results = await Promise.allSettled(
735
+ group.map(({ userToken, validatorToken }) =>
736
+ readPoolReserves(c, {
737
+ chainId,
738
+ userToken: userToken as z.output<typeof Schema.Address>,
739
+ validatorToken: validatorToken as z.output<typeof Schema.Address>,
740
+ }),
741
+ ),
742
+ )
743
+ for (const [offset, result] of results.entries()) {
744
+ const userToken = group[offset]!.userToken
745
+ if (result.status === 'rejected') {
746
+ unresolved.set(userToken, result.reason)
747
+ continue
748
+ }
749
+ if (BigInt(result.value.userToken) > 0n && BigInt(result.value.validatorToken) > 0n) {
750
+ tokens.add(userToken)
751
+ unresolved.delete(userToken)
752
+ }
753
+ }
753
754
  }
755
+ const failure = Array.from(unresolved).find(([address]) => !tokens.has(address))
756
+ if (failure) throw failure[1]
754
757
  return Array.from(tokens)
755
758
  },
756
759
  {
757
- key: `feeamm:v2:${chainId}:fee-token-set:v:${snapshot.version}`,
760
+ key: `feeamm:v3:${chainId}:fee-token-set:v:${snapshot.version}`,
758
761
  store,
759
- ttl: Ttl.minutes(5),
762
+ ttl: Ttl.seconds(30),
760
763
  },
761
764
  ),
762
- )
765
+ ).catch((cause) => {
766
+ const failure = {
767
+ chainId,
768
+ failure: 'unknown',
769
+ id: 'rpc',
770
+ operation: 'feeTokenSet',
771
+ } satisfies Log.ProviderFailure
772
+ c.set('providerFailures', [...(c.get('providerFailures') ?? []), failure])
773
+ throw cause
774
+ })
763
775
  return new Set(addresses)
764
776
  }
765
777
 
778
+ /** Resolves the distinct fee tokens preferred by active validators. */
779
+ async function getValidatorTokens(
780
+ c: Context<App.Environment>,
781
+ options: getValidatorTokens.Options,
782
+ ) {
783
+ const { chainId } = options
784
+ const client = c.get('getClient')(chainId)
785
+ const validators = await client.readContract({
786
+ abi: Abis.validatorConfig,
787
+ address: Addresses.validator,
788
+ functionName: 'getValidators',
789
+ })
790
+ const active = validators.filter((validator) => validator.active)
791
+ if (active.length === 0) return [pathUsd]
792
+ const preferred = await Promise.all(
793
+ active.map((validator) =>
794
+ client.readContract({
795
+ abi: Abis.feeManager,
796
+ address: Addresses.feeManager,
797
+ args: [validator.validatorAddress],
798
+ functionName: 'validatorTokens',
799
+ }),
800
+ ),
801
+ )
802
+ return Array.from(
803
+ new Set(
804
+ preferred.map((address) =>
805
+ address.toLowerCase() === zeroAddress ? pathUsd : address.toLowerCase(),
806
+ ),
807
+ ),
808
+ )
809
+ }
810
+
811
+ declare namespace getValidatorTokens {
812
+ /** Options for resolving active validators' preferred fee tokens. */
813
+ type Options = {
814
+ /** Chain whose validator preferences should be read. */
815
+ chainId: z.output<typeof Schema.ChainId>
816
+ }
817
+ }
818
+
766
819
  /**
767
820
  * Reads a pool's current on-chain reserves via `FeeManager.getPool`, memoized
768
821
  * briefly per pool. Reserves are best-effort decoration on the pool listing:
@@ -775,28 +828,37 @@ function getPoolReserves(
775
828
  options: getPoolReserves.Options,
776
829
  ): Promise<getPoolReserves.Reserves | null> {
777
830
  const { chainId, userToken, validatorToken } = options
778
- const client = c.get('getClient')(chainId)
779
831
  const store = c.get('store')
780
832
 
781
- return Store.memoize(
782
- async () => {
783
- const pool = await client.readContract({
784
- abi: Abis.feeAmm,
785
- address: Addresses.feeManager,
786
- args: [userToken, validatorToken],
787
- functionName: 'getPool',
788
- })
789
- return {
790
- userToken: pool.reserveUserToken.toString(),
791
- validatorToken: pool.reserveValidatorToken.toString(),
792
- }
793
- },
794
- {
795
- key: `feeamm:v1:${chainId}:pool:${userToken}:${validatorToken}:reserves`,
796
- store,
797
- ttl: Ttl.seconds(30),
798
- },
799
- ).catch(() => null)
833
+ return Store.memoize(() => readPoolReserves(c, { chainId, userToken, validatorToken }), {
834
+ key: `feeamm:v1:${chainId}:pool:${userToken}:${validatorToken}:reserves`,
835
+ store,
836
+ ttl: Ttl.seconds(30),
837
+ }).catch(() => null)
838
+ }
839
+
840
+ /** Reads a pool's current on-chain reserves and propagates RPC failures. */
841
+ async function readPoolReserves(
842
+ c: Context<App.Environment>,
843
+ options: readPoolReserves.Options,
844
+ ): Promise<getPoolReserves.Reserves> {
845
+ const { chainId, userToken, validatorToken } = options
846
+ const client = c.get('getClient')(chainId)
847
+ const pool = await client.readContract({
848
+ abi: Abis.feeAmm,
849
+ address: Addresses.feeManager,
850
+ args: [userToken, validatorToken],
851
+ functionName: 'getPool',
852
+ })
853
+ return {
854
+ userToken: pool.reserveUserToken.toString(),
855
+ validatorToken: pool.reserveValidatorToken.toString(),
856
+ }
857
+ }
858
+
859
+ declare namespace readPoolReserves {
860
+ /** Options for reading one fee pool. */
861
+ type Options = getPoolReserves.Options
800
862
  }
801
863
 
802
864
  declare namespace getPoolReserves {
@@ -346,18 +346,30 @@ async function findRecentTransactionHash() {
346
346
  }
347
347
 
348
348
  describe('GET /transactions/receipts?address=…', () => {
349
- test('returns receipts involving an address', async () => {
349
+ let account: string
350
+
351
+ beforeAll(async () => {
350
352
  const client = TestApp.client()
351
- // Seed a real sender from the global receipt feed.
352
- const seedResponse = await client.v1.transactions.receipts.$get(
353
- { query: { limit: '5' } },
354
- TestApp.auth,
353
+ // A replica can briefly return an empty head page. Require an indexed receipt before testing address filters.
354
+ account = await vi.waitFor(
355
+ async () => {
356
+ const response = await client.v1.transactions.receipts.$get(
357
+ { query: { limit: '5' } },
358
+ { headers: { ...TestApp.auth.headers, 'cache-control': 'no-store' } },
359
+ )
360
+ const body = await TestApp.json(response, Receipts.schema.getReceipts.Response)
361
+ expect(response.status).toBe(200)
362
+ expect(body.data.length).toBeGreaterThan(0)
363
+ const sender = body.data[0]!.sender
364
+ expect(sender).toMatch(/^0x[0-9a-f]{40}$/)
365
+ return sender
366
+ },
367
+ { interval: 1_000, timeout: 30_000 },
355
368
  )
356
- const seed = await TestApp.json(seedResponse, Receipts.schema.getReceipts.Response)
357
- expect(seedResponse.status).toBe(200)
358
- const account = seed.data[0]!.sender
359
- expect(account).toMatch(/^0x[0-9a-f]{40}$/)
369
+ })
360
370
 
371
+ test('returns receipts involving an address', async () => {
372
+ const client = TestApp.client()
361
373
  const baseResponse = await client.v1.transactions.receipts.$get(
362
374
  { query: { address: account, limit: '5' } },
363
375
  TestApp.auth,
@@ -390,15 +402,6 @@ describe('GET /transactions/receipts?address=…', () => {
390
402
 
391
403
  test('narrows receipts by execution status', async () => {
392
404
  const client = TestApp.client()
393
- const seedResponse = await client.v1.transactions.receipts.$get(
394
- { query: { limit: '5' } },
395
- TestApp.auth,
396
- )
397
- const seed = await TestApp.json(seedResponse, Receipts.schema.getReceipts.Response)
398
- expect(seedResponse.status).toBe(200)
399
- const account = seed.data[0]!.sender
400
- expect(account).toMatch(/^0x[0-9a-f]{40}$/)
401
-
402
405
  const response = await client.v1.transactions.receipts.$get(
403
406
  { query: { address: account, limit: '5', status: 'success' } },
404
407
  TestApp.auth,
@@ -1230,7 +1230,7 @@ describe('POST /rpc', () => {
1230
1230
  {
1231
1231
  "error": {
1232
1232
  "code": "api_key_forbidden",
1233
- "message": "API key missing required scope",
1233
+ "message": "API key is missing required permissions: data:read. Use an API key with these scopes.",
1234
1234
  },
1235
1235
  }
1236
1236
  `)
@@ -1531,7 +1531,7 @@ describe('POST /rpc/relay', () => {
1531
1531
  {
1532
1532
  "error": {
1533
1533
  "code": "api_key_forbidden",
1534
- "message": "API key missing required scope",
1534
+ "message": "API key is missing required permissions: rpc-relay:read. Use an API key with these scopes.",
1535
1535
  },
1536
1536
  }
1537
1537
  `)
@@ -0,0 +1,157 @@
1
+ import * as fs from 'node:fs'
2
+ import {
3
+ GenericContainer,
4
+ Network,
5
+ type StartedNetwork,
6
+ type StartedTestContainer,
7
+ Wait,
8
+ } from 'testcontainers'
9
+ import { encodeAbiParameters, encodeEventTopics, parseAbi, zeroAddress, zeroHash } from 'viem'
10
+
11
+ import * as TestApp from '../../../../test/App.js'
12
+ import * as Runtime from '../../../../test/runtime.js'
13
+ import * as Tokens from './tokens.js'
14
+
15
+ const abi = parseAbi([
16
+ 'event TokenCreated(address indexed token, string name, string symbol, string currency, address quoteToken, address admin, bytes32 salt)',
17
+ ])
18
+ const attacker = '0x1111111111111111111111111111111111111111'
19
+ const token = '0x20c0000000000000000000000000000000000001'
20
+
21
+ let url: string
22
+
23
+ describe.runIf(Runtime.get().mode === 'testnet')('Token provenance', () => {
24
+ let app: ReturnType<typeof TestApp.create>
25
+ let clickhouse: StartedTestContainer
26
+ let indexer: StartedTestContainer
27
+ let network: StartedNetwork
28
+ let postgres: StartedTestContainer
29
+
30
+ beforeAll(async () => {
31
+ const compose = fs.readFileSync(
32
+ new URL('../../../../docker-compose.yml', import.meta.url),
33
+ 'utf8',
34
+ )
35
+ const image = compose.match(/TEMPO_API_TIDX_IMAGE:-([^}]+)}/)?.[1]
36
+ const image_clickhouse = compose.match(/TEMPO_API_CLICKHOUSE_IMAGE:-([^}]+)}/)?.[1]
37
+ const image_postgres = compose.match(/TEMPO_API_POSTGRES_IMAGE:-([^}]+)}/)?.[1]
38
+ if (!image || !image_clickhouse || !image_postgres)
39
+ throw new Error('Missing pinned database images.')
40
+ network = await new Network().start()
41
+ postgres = await new GenericContainer(image_postgres)
42
+ .withEnvironment({ POSTGRES_PASSWORD: 'postgres' })
43
+ .withNetwork(network)
44
+ .withNetworkAliases('postgres')
45
+ .withExposedPorts(5432)
46
+ .withWaitStrategy(Wait.forLogMessage(/database system is ready to accept connections/, 2))
47
+ .start()
48
+ clickhouse = await new GenericContainer(image_clickhouse)
49
+ .withEnvironment({ CLICKHOUSE_PASSWORD: 'clickhouse', CLICKHOUSE_USER: 'clickhouse' })
50
+ .withNetwork(network)
51
+ .withNetworkAliases('clickhouse')
52
+ .withExposedPorts(8123)
53
+ .withWaitStrategy(Wait.forHttp('/ping', 8123))
54
+ .start()
55
+ url = `http://${clickhouse.getHost()}:${clickhouse.getMappedPort(8123)}`
56
+ indexer = await new GenericContainer(image)
57
+ .withPlatform('linux/amd64')
58
+ .withNetwork(network)
59
+ .withCopyContentToContainer([
60
+ {
61
+ content: `
62
+ [http]
63
+ enabled = true
64
+ port = 8080
65
+ bind = "0.0.0.0"
66
+ [prometheus]
67
+ enabled = false
68
+ [[chains]]
69
+ name = "token-provenance"
70
+ chain_id = 42431
71
+ rpc_url = "http://127.0.0.1:1"
72
+ pg_url = "postgres://postgres:postgres@postgres:5432/postgres"
73
+ backfill = false
74
+ [chains.clickhouse]
75
+ enabled = true
76
+ url = "http://clickhouse:8123"
77
+ user = "clickhouse"
78
+ password_env = "CLICKHOUSE_PASSWORD"
79
+ repair_derived_on_startup = false
80
+ `,
81
+ target: '/tmp/config.toml',
82
+ },
83
+ ])
84
+ .withEnvironment({ CLICKHOUSE_PASSWORD: 'clickhouse' })
85
+ .withCommand(['up', '--config', '/tmp/config.toml'])
86
+ .withExposedPorts(8080)
87
+ .withWaitStrategy(Wait.forListeningPorts())
88
+ .withStartupTimeout(120_000)
89
+ .start()
90
+ await vi.waitFor(
91
+ async () => {
92
+ const response = await query(
93
+ "SELECT count() FROM system.tables WHERE database = 'tidx_42431' AND name = 'logs'",
94
+ )
95
+ expect(response.trim()).toBe('1')
96
+ },
97
+ { timeout: 60_000 },
98
+ )
99
+ app = TestApp.create({
100
+ auth: false,
101
+ cache: { edge: false },
102
+ rpc: { url: 'http://127.0.0.1:1' },
103
+ tidx: { baseUrl: `http://${indexer.getHost()}:${indexer.getMappedPort(8080)}` },
104
+ })
105
+ })
106
+
107
+ afterAll(async () => {
108
+ await indexer?.stop()
109
+ await clickhouse?.stop()
110
+ await postgres?.stop()
111
+ await network?.stop()
112
+ })
113
+
114
+ test('excludes TokenCreated logs from non-factory emitters', async () => {
115
+ await insertForgedToken()
116
+
117
+ const response = await app.request('/v1/tokens?chainId=42431&limit=5')
118
+ expect(response.status, await response.clone().text()).toBe(200)
119
+ const body = await TestApp.json(response, Tokens.schema.getTokens.Response)
120
+ expect(body).toEqual({ data: [], nextCursor: null })
121
+ })
122
+ })
123
+
124
+ async function query(sql: string) {
125
+ const response = await fetch(url, {
126
+ body: sql,
127
+ headers: { Authorization: `Basic ${btoa('clickhouse:clickhouse')}` },
128
+ method: 'POST',
129
+ })
130
+ const body = await response.text()
131
+ if (!response.ok) throw new Error(body)
132
+ return body
133
+ }
134
+
135
+ async function insertForgedToken() {
136
+ const [selector, topic1] = encodeEventTopics({
137
+ abi,
138
+ args: { token },
139
+ eventName: 'TokenCreated',
140
+ })
141
+ if (typeof selector !== 'string' || typeof topic1 !== 'string')
142
+ throw new Error('Invalid TokenCreated event topics.')
143
+ const data = encodeAbiParameters(
144
+ [
145
+ { type: 'string' },
146
+ { type: 'string' },
147
+ { type: 'string' },
148
+ { type: 'address' },
149
+ { type: 'address' },
150
+ { type: 'bytes32' },
151
+ ],
152
+ ['Forged USD', 'FUSD', 'USD', zeroAddress, attacker, zeroHash],
153
+ )
154
+ await query(`INSERT INTO tidx_42431.logs
155
+ (block_num, block_timestamp, log_idx, tx_idx, tx_hash, address, selector, topic0, topic1, data)
156
+ VALUES (100, '2026-01-01 00:00:00', 0, 0, '${zeroHash}', '${attacker}', '${selector}', '${selector}', '${topic1}', '${data}')`)
157
+ }
@@ -19,7 +19,7 @@ function app(options: TestApp.create.Options = {}) {
19
19
  return TestApp.client({ db, ...options })
20
20
  }
21
21
 
22
- const verifiedTokenCount = 6
22
+ const verifiedTokenCount = 7
23
23
 
24
24
  describe('getTokenMetadata', () => {
25
25
  const address = '0x20c0000000000000000000000000000000000001'
@@ -914,14 +914,14 @@ describe('GET /tokens?verified=true', () => {
914
914
 
915
915
  test('paginates the verified list via limit + cursor', async () => {
916
916
  const client = app({ assetsPath: false })
917
- // Full list for comparison (6 verified tokens on the test chain).
917
+ // Full list for comparison (7 verified tokens on the test chain).
918
918
  const full = await TestApp.json(
919
919
  await client.v1.tokens.$get({ query: { verified: 'true' } }, TestApp.auth),
920
920
  Tokens.schema.getTokens.Response,
921
921
  )
922
922
 
923
923
  // First page: a bounded slice with a cursor to the next page (`minLimit` is
924
- // 5, and the test chain has 6 verified tokens, so a page of 5 leaves 1).
924
+ // 5, and the test chain has 7 verified tokens, so a page of 5 leaves 2).
925
925
  const first = await TestApp.json(
926
926
  await client.v1.tokens.$get({ query: { verified: 'true', limit: '5' } }, TestApp.auth),
927
927
  Tokens.schema.getTokens.Response,
@@ -937,7 +937,7 @@ describe('GET /tokens?verified=true', () => {
937
937
  ),
938
938
  Tokens.schema.getTokens.Response,
939
939
  )
940
- expect(second.data.length).toBe(1)
940
+ expect(second.data.length).toBe(verifiedTokenCount - 5)
941
941
  expect(second.nextCursor).toBeNull()
942
942
 
943
943
  // The two pages reconstruct the full list in order, with no overlap.
@@ -1,7 +1,7 @@
1
1
  import { Hono, type Context } from 'hono'
2
2
  import { AbiEvent, AbiParameters, Hash } from 'ox'
3
3
  import { type Address, ContractFunctionExecutionError } from 'viem'
4
- import { Abis } from 'viem/tempo'
4
+ import { Abis, Addresses } from 'viem/tempo'
5
5
  import * as z from 'zod/mini'
6
6
 
7
7
  import * as Assets from '../../../Assets.js'
@@ -52,6 +52,7 @@ const tokenCreatedSignature =
52
52
  // lookup reads the raw `logs` table by topic0 and ABI-decodes the data blob
53
53
  // instead.
54
54
  const tokenCreatedTopic = AbiEvent.getSelector(tokenCreatedSignature)
55
+ const tip20Factory = Addresses.tip20Factory.toLowerCase()
55
56
 
56
57
  // Non-indexed `TokenCreated` data layout, in event-parameter order:
57
58
  // `[name, symbol, currency, quoteToken, admin, salt]`.
@@ -2072,7 +2073,7 @@ export async function getTokenCreatedAtByAddress(
2072
2073
 
2073
2074
  if (addresses.length === 0) return {}
2074
2075
 
2075
- const key = (address: string) => `token:v1:${options.chainId}:${address}:created_at`
2076
+ const key = (address: string) => `token:v2:${options.chainId}:${address}:created_at`
2076
2077
 
2077
2078
  const cached = await Promise.all(addresses.map((address) => store.get(key(address))))
2078
2079
  const createdAtByAddress: Record<string, string> = {}
@@ -2095,7 +2096,8 @@ export async function getTokenCreatedAtByAddress(
2095
2096
  query: `
2096
2097
  SELECT token, block_timestamp
2097
2098
  FROM tokencreated
2098
- WHERE token IN (${misses.map((address) => `'${address}'`).join(', ')})
2099
+ WHERE address = '${tip20Factory}'
2100
+ AND token IN (${misses.map((address) => `'${address}'`).join(', ')})
2099
2101
  `,
2100
2102
  signatures: [tokenCreatedSignature],
2101
2103
  })
@@ -2165,7 +2167,7 @@ async function getTokenCreatedByAddress(
2165
2167
 
2166
2168
  if (addresses.length === 0) return {}
2167
2169
 
2168
- const key = (address: string) => `token:v2:${options.chainId}:${address}:created`
2170
+ const key = (address: string) => `token:v3:${options.chainId}:${address}:created`
2169
2171
 
2170
2172
  const cached = await Promise.all(addresses.map((address) => store.get(key(address))))
2171
2173
  const createdByAddress: Record<string, getTokenCreatedByAddress.Created> = {}
@@ -2193,6 +2195,7 @@ async function getTokenCreatedByAddress(
2193
2195
  SELECT topic1, data, block_timestamp
2194
2196
  FROM logs
2195
2197
  WHERE selector = '${tokenCreatedTopic}'
2198
+ AND address = '${tip20Factory}'
2196
2199
  AND topic1 IN (${misses.map((address) => `'0x${'0'.repeat(24)}${address.slice(2)}'`).join(', ')})
2197
2200
  ` as string,
2198
2201
  })
@@ -2445,7 +2448,9 @@ async function getTokens(c: Context<App.Environment>, options: getTokens.Options
2445
2448
  // here are real columns like `block_num` and `currency`, plus the
2446
2449
  // cursor keyset; verified-only mode is handled above by serving the
2447
2450
  // curated static list directly.
2448
- const filters: string[] = []
2451
+ // Authenticate the emitter before pagination so forged events cannot
2452
+ // crowd canonical factory-created tokens out of the public list.
2453
+ const filters = [`address = '${tip20Factory}'`]
2449
2454
  if (cursor !== undefined)
2450
2455
  filters.push(
2451
2456
  Cursor.keyset([
@@ -2490,7 +2495,7 @@ async function getTokens(c: Context<App.Environment>, options: getTokens.Options
2490
2495
  }
2491
2496
  },
2492
2497
  {
2493
- key: `token:v1:${options.chainId}:indexed:${order}:${encodeURIComponent(options.currency?.toLowerCase() ?? '')}:${cursor ? `cursor:${cursor[0]}:${cursor[1]}` : offset !== undefined ? `page:${options.page}` : 'head'}:${limit}`,
2498
+ key: `token:v2:${options.chainId}:indexed:${order}:${encodeURIComponent(options.currency?.toLowerCase() ?? '')}:${cursor ? `cursor:${cursor[0]}:${cursor[1]}` : offset !== undefined ? `page:${options.page}` : 'head'}:${limit}`,
2494
2499
  store,
2495
2500
  ttl: Ttl.minutes(2),
2496
2501
  },
@@ -3,6 +3,7 @@
3
3
  import { Schema } from 'tapimo/server'
4
4
  import { Hex } from 'ox'
5
5
  import { zeroHash } from 'viem'
6
+ import { Addresses } from 'viem/tempo'
6
7
 
7
8
  import * as TestApp from '../../../../test/App.js'
8
9
  import * as Runtime from '../../../../test/runtime.js'
@@ -502,4 +503,32 @@ describe('GET /transactions?address=…', () => {
502
503
  head.data.slice(5, 10).map((entry) => entry.hash),
503
504
  )
504
505
  })
506
+
507
+ test('serves an ascending page for a token contract that never sends', async () => {
508
+ // A TIP-20 contract never sends, so its `"from"` side has no matches: the
509
+ // ascending shape that can time out into the fenced retry.
510
+ const client = TestApp.client()
511
+ const response = await client.v1.transactions.$get(
512
+ { query: { address: Addresses.pathUsd, include: 'receipt', limit: '10', order: 'asc' } },
513
+ TestApp.auth,
514
+ )
515
+ const body = await TestApp.json(response, Transactions.schema.getTransactions.Response)
516
+ expect(response.status).toBe(200)
517
+ expect({
518
+ ascending: body.data.every(
519
+ (entry, index) =>
520
+ index === 0 || (body.data[index - 1]!.blockNumber ?? 0) <= (entry.blockNumber ?? 0),
521
+ ),
522
+ everyReceiptMatchesHash: body.data.every(
523
+ (entry) => entry.meta.receipt?.transactionHash === entry.hash,
524
+ ),
525
+ everyRecipientIsToken: body.data.every((entry) => entry.recipient === Addresses.pathUsd),
526
+ }).toMatchInlineSnapshot(`
527
+ {
528
+ "ascending": true,
529
+ "everyReceiptMatchesHash": true,
530
+ "everyRecipientIsToken": true,
531
+ }
532
+ `)
533
+ })
505
534
  })