tapimo 0.9.0 → 0.10.1

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 (319) hide show
  1. package/dist/ApiKey.d.ts +2 -1
  2. package/dist/ApiKey.d.ts.map +1 -1
  3. package/dist/ApiKeys.d.ts +4 -2
  4. package/dist/ApiKeys.d.ts.map +1 -1
  5. package/dist/ApiKeys.js +26 -1
  6. package/dist/ApiKeys.js.map +1 -1
  7. package/dist/App.d.ts +4292 -3708
  8. package/dist/App.d.ts.map +1 -1
  9. package/dist/App.js +1 -0
  10. package/dist/App.js.map +1 -1
  11. package/dist/Webhooks.d.ts +21 -20
  12. package/dist/Webhooks.d.ts.map +1 -1
  13. package/dist/Webhooks.js +66 -23
  14. package/dist/Webhooks.js.map +1 -1
  15. package/dist/admin/App.d.ts +91 -84
  16. package/dist/admin/App.d.ts.map +1 -1
  17. package/dist/admin/apps/api-keys.d.ts +26 -17
  18. package/dist/admin/apps/api-keys.d.ts.map +1 -1
  19. package/dist/admin/apps/api-keys.js +6 -0
  20. package/dist/admin/apps/api-keys.js.map +1 -1
  21. package/dist/admin/apps/organizations.d.ts +4 -2
  22. package/dist/admin/apps/organizations.d.ts.map +1 -1
  23. package/dist/admin/apps/verified-tokens.d.ts +168 -168
  24. package/dist/admin/ui.generated.d.ts +1 -1
  25. package/dist/admin/ui.generated.js +69 -69
  26. package/dist/admin/ui.generated.js.map +1 -1
  27. package/dist/analytics/Analytics.d.ts.map +1 -1
  28. package/dist/analytics/Analytics.js +26 -0
  29. package/dist/analytics/Analytics.js.map +1 -1
  30. package/dist/apps/Zones.d.ts +4280 -84
  31. package/dist/apps/Zones.d.ts.map +1 -1
  32. package/dist/apps/Zones.js +30 -10
  33. package/dist/apps/Zones.js.map +1 -1
  34. package/dist/apps/data/App.d.ts +5799 -4929
  35. package/dist/apps/data/App.d.ts.map +1 -1
  36. package/dist/apps/data/FxOracle.d.ts +4 -5
  37. package/dist/apps/data/FxOracle.d.ts.map +1 -1
  38. package/dist/apps/data/FxOracle.js +19 -4
  39. package/dist/apps/data/FxOracle.js.map +1 -1
  40. package/dist/apps/data/routes/activities.d.ts +3391 -492
  41. package/dist/apps/data/routes/activities.d.ts.map +1 -1
  42. package/dist/apps/data/routes/activities.js +372 -29
  43. package/dist/apps/data/routes/activities.js.map +1 -1
  44. package/dist/apps/data/routes/addresses.d.ts +853 -339
  45. package/dist/apps/data/routes/addresses.d.ts.map +1 -1
  46. package/dist/apps/data/routes/balances.d.ts +10 -10
  47. package/dist/apps/data/routes/balances.d.ts.map +1 -1
  48. package/dist/apps/data/routes/balances.js +145 -83
  49. package/dist/apps/data/routes/balances.js.map +1 -1
  50. package/dist/apps/data/routes/blocks.d.ts +123 -123
  51. package/dist/apps/data/routes/coingecko.d.ts +169 -169
  52. package/dist/apps/data/routes/earn.d.ts +455 -1
  53. package/dist/apps/data/routes/earn.d.ts.map +1 -1
  54. package/dist/apps/data/routes/earn.js +369 -45
  55. package/dist/apps/data/routes/earn.js.map +1 -1
  56. package/dist/apps/data/routes/exchanges.d.ts.map +1 -1
  57. package/dist/apps/data/routes/exchanges.js +114 -118
  58. package/dist/apps/data/routes/exchanges.js.map +1 -1
  59. package/dist/apps/data/routes/fee-amm.d.ts +24 -24
  60. package/dist/apps/data/routes/indexer.d.ts +35 -34
  61. package/dist/apps/data/routes/indexer.d.ts.map +1 -1
  62. package/dist/apps/data/routes/indexer.js +3 -2
  63. package/dist/apps/data/routes/indexer.js.map +1 -1
  64. package/dist/apps/data/routes/receipts.d.ts.map +1 -1
  65. package/dist/apps/data/routes/receipts.js +68 -47
  66. package/dist/apps/data/routes/receipts.js.map +1 -1
  67. package/dist/apps/data/routes/rpc.d.ts +31 -31
  68. package/dist/apps/data/routes/rpc.d.ts.map +1 -1
  69. package/dist/apps/data/routes/rpc.js +5 -1
  70. package/dist/apps/data/routes/rpc.js.map +1 -1
  71. package/dist/apps/data/routes/tokenlist.d.ts +12 -12
  72. package/dist/apps/data/routes/tokens.d.ts +461 -459
  73. package/dist/apps/data/routes/tokens.d.ts.map +1 -1
  74. package/dist/apps/data/routes/transactions.d.ts +313 -305
  75. package/dist/apps/data/routes/transactions.d.ts.map +1 -1
  76. package/dist/apps/data/routes/transactions.js +25 -23
  77. package/dist/apps/data/routes/transactions.js.map +1 -1
  78. package/dist/apps/data/routes/transfers.d.ts +108 -86
  79. package/dist/apps/data/routes/transfers.d.ts.map +1 -1
  80. package/dist/apps/data/routes/transfers.js +618 -105
  81. package/dist/apps/data/routes/transfers.js.map +1 -1
  82. package/dist/apps/data/routes/valuation.d.ts +21 -21
  83. package/dist/apps/data/routes/valuation.d.ts.map +1 -1
  84. package/dist/apps/data/routes/valuation.js +2 -2
  85. package/dist/apps/data/routes/valuation.js.map +1 -1
  86. package/dist/apps/data/routes/webhooks.d.ts +519 -868
  87. package/dist/apps/data/routes/webhooks.d.ts.map +1 -1
  88. package/dist/apps/data/routes/webhooks.js +642 -353
  89. package/dist/apps/data/routes/webhooks.js.map +1 -1
  90. package/dist/apps/data/routes/zones.d.ts +31 -31
  91. package/dist/apps/data/routes/zones.d.ts.map +1 -1
  92. package/dist/apps/data/routes/zones.js +4 -2
  93. package/dist/apps/data/routes/zones.js.map +1 -1
  94. package/dist/apps/funding/routes/deposit-addresses.js +1 -1
  95. package/dist/apps/funding/routes/deposit-addresses.js.map +1 -1
  96. package/dist/apps/funding/routes/providers.d.ts +13 -13
  97. package/dist/apps/funding/routes/quotes.d.ts +89 -89
  98. package/dist/apps/funding/routes/transfers.d.ts +36 -36
  99. package/dist/apps/funding/routes/transfers.js +1 -1
  100. package/dist/apps/funding/routes/transfers.js.map +1 -1
  101. package/dist/apps/management/App.d.ts +11 -309
  102. package/dist/apps/management/App.d.ts.map +1 -1
  103. package/dist/apps/management/routes/api-keys.d.ts +74 -74
  104. package/dist/apps/management/routes/billing.js +1 -1
  105. package/dist/apps/management/routes/billing.js.map +1 -1
  106. package/dist/apps/management/routes/faucet.d.ts +35 -35
  107. package/dist/apps/management/routes/faucet.js +2 -2
  108. package/dist/apps/management/routes/faucet.js.map +1 -1
  109. package/dist/apps/management/routes/invitations.d.ts +134 -134
  110. package/dist/apps/management/routes/invite-links.d.ts +80 -80
  111. package/dist/apps/management/routes/members.d.ts +69 -69
  112. package/dist/apps/management/routes/orgs.d.ts +98 -98
  113. package/dist/apps/management/routes/projects.d.ts +60 -60
  114. package/dist/apps/management/routes/usage.d.ts +72 -72
  115. package/dist/apps/management/routes/verified-token-requests.d.ts +83 -83
  116. package/dist/apps/management/routes/webhooks.d.ts +203 -618
  117. package/dist/apps/management/routes/webhooks.d.ts.map +1 -1
  118. package/dist/apps/mcp.d.ts.map +1 -1
  119. package/dist/apps/mcp.js +4 -1
  120. package/dist/apps/mcp.js.map +1 -1
  121. package/dist/apps/mpp/App.d.ts +56 -44
  122. package/dist/apps/mpp/App.d.ts.map +1 -1
  123. package/dist/apps/mpp/Mpp.d.ts +3 -0
  124. package/dist/apps/mpp/Mpp.d.ts.map +1 -1
  125. package/dist/apps/mpp/Mpp.js +3 -0
  126. package/dist/apps/mpp/Mpp.js.map +1 -1
  127. package/dist/apps/mpp/internal/Adapter.d.ts.map +1 -1
  128. package/dist/apps/mpp/internal/Adapter.js +9 -2
  129. package/dist/apps/mpp/internal/Adapter.js.map +1 -1
  130. package/dist/db/Db.d.ts +4 -2
  131. package/dist/db/Db.d.ts.map +1 -1
  132. package/dist/db/Db.js +75 -15
  133. package/dist/db/Db.js.map +1 -1
  134. package/dist/db/Schema.d.ts +19 -0
  135. package/dist/db/Schema.d.ts.map +1 -1
  136. package/dist/db/Schema.js +24 -0
  137. package/dist/db/Schema.js.map +1 -1
  138. package/dist/db/tables/sponsoredTransactions.d.ts.map +1 -1
  139. package/dist/db/tables/sponsoredTransactions.js +4 -1
  140. package/dist/db/tables/sponsoredTransactions.js.map +1 -1
  141. package/dist/db/tables/webhookQueueEvents.d.ts +122 -0
  142. package/dist/db/tables/webhookQueueEvents.d.ts.map +1 -0
  143. package/dist/db/tables/webhookQueueEvents.js +160 -0
  144. package/dist/db/tables/webhookQueueEvents.js.map +1 -0
  145. package/dist/db/tables/webhookSubscriptions.d.ts +58 -3
  146. package/dist/db/tables/webhookSubscriptions.d.ts.map +1 -1
  147. package/dist/db/tables/webhookSubscriptions.js +86 -3
  148. package/dist/db/tables/webhookSubscriptions.js.map +1 -1
  149. package/dist/internal/Auth.d.ts +3 -0
  150. package/dist/internal/Auth.d.ts.map +1 -1
  151. package/dist/internal/Auth.js +6 -4
  152. package/dist/internal/Auth.js.map +1 -1
  153. package/dist/internal/MetricSink.d.ts +139 -3
  154. package/dist/internal/MetricSink.d.ts.map +1 -1
  155. package/dist/internal/MetricSink.js +144 -4
  156. package/dist/internal/MetricSink.js.map +1 -1
  157. package/dist/internal/RateLimit.d.ts +4 -6
  158. package/dist/internal/RateLimit.d.ts.map +1 -1
  159. package/dist/internal/RateLimit.js +15 -14
  160. package/dist/internal/RateLimit.js.map +1 -1
  161. package/dist/internal/Schema.js +1 -1
  162. package/dist/internal/Schema.js.map +1 -1
  163. package/dist/internal/Store.d.ts +2 -1
  164. package/dist/internal/Store.d.ts.map +1 -1
  165. package/dist/internal/Store.js +57 -18
  166. package/dist/internal/Store.js.map +1 -1
  167. package/dist/internal/Tidx.d.ts +1 -3
  168. package/dist/internal/Tidx.d.ts.map +1 -1
  169. package/dist/internal/Tidx.js +1 -3
  170. package/dist/internal/Tidx.js.map +1 -1
  171. package/dist/internal/Value.d.ts +2 -0
  172. package/dist/internal/Value.d.ts.map +1 -1
  173. package/dist/internal/Value.js +25 -0
  174. package/dist/internal/Value.js.map +1 -1
  175. package/dist/internal/Viem.d.ts.map +1 -1
  176. package/dist/internal/Viem.js +2 -1
  177. package/dist/internal/Viem.js.map +1 -1
  178. package/dist/internal/WebhookDestination.d.ts +2 -0
  179. package/dist/internal/WebhookDestination.d.ts.map +1 -1
  180. package/dist/internal/WebhookDestination.js +11 -0
  181. package/dist/internal/WebhookDestination.js.map +1 -1
  182. package/dist/internal/WebhookTransfer.d.ts +75 -0
  183. package/dist/internal/WebhookTransfer.d.ts.map +1 -0
  184. package/dist/internal/WebhookTransfer.js +299 -0
  185. package/dist/internal/WebhookTransfer.js.map +1 -0
  186. package/dist/internal/Webhooks.d.ts +176 -0
  187. package/dist/internal/Webhooks.d.ts.map +1 -1
  188. package/dist/internal/Webhooks.js +216 -20
  189. package/dist/internal/Webhooks.js.map +1 -1
  190. package/dist/internal/funding/Provider.d.ts +4 -0
  191. package/dist/internal/funding/Provider.d.ts.map +1 -1
  192. package/dist/internal/funding/Provider.js +11 -7
  193. package/dist/internal/funding/Provider.js.map +1 -1
  194. package/dist/internal/funding/Reconciliation.d.ts.map +1 -1
  195. package/dist/internal/funding/Reconciliation.js +128 -0
  196. package/dist/internal/funding/Reconciliation.js.map +1 -1
  197. package/dist/internal/funding/providers/relay.d.ts +6 -4
  198. package/dist/internal/funding/providers/relay.d.ts.map +1 -1
  199. package/dist/internal/funding/providers/relay.js +71 -9
  200. package/dist/internal/funding/providers/relay.js.map +1 -1
  201. package/package.json +4 -4
  202. package/src/ApiKeys.test.ts +20 -0
  203. package/src/ApiKeys.ts +28 -1
  204. package/src/App.test.ts +10 -8
  205. package/src/App.ts +1 -0
  206. package/src/Client.test-d.ts +61 -5
  207. package/src/Webhooks.bench.ts +714 -0
  208. package/src/Webhooks.memory.bench.ts +250 -0
  209. package/src/Webhooks.test.ts +77 -6
  210. package/src/Webhooks.ts +85 -29
  211. package/src/admin/apps/api-keys.test.ts +9 -0
  212. package/src/admin/apps/api-keys.ts +15 -0
  213. package/src/admin/ui/src/lib/query-client.ts +3 -2
  214. package/src/admin/ui/src/routes/api-keys.tsx +31 -9
  215. package/src/admin/ui.generated.ts +69 -69
  216. package/src/analytics/Analytics.test.ts +8 -0
  217. package/src/analytics/Analytics.ts +26 -0
  218. package/src/apps/Zones.test.ts +23 -5
  219. package/src/apps/Zones.ts +31 -10
  220. package/src/apps/composition.test.ts +1 -0
  221. package/src/apps/data/App.test.ts +2 -2
  222. package/src/apps/data/FxOracle.test.ts +18 -0
  223. package/src/apps/data/FxOracle.ts +28 -5
  224. package/src/apps/data/routes/activities.bench.ts +41 -0
  225. package/src/apps/data/routes/activities.test.ts +122 -2
  226. package/src/apps/data/routes/activities.ts +435 -32
  227. package/src/apps/data/routes/balances.bench.ts +21 -0
  228. package/src/apps/data/routes/balances.test.ts +119 -10
  229. package/src/apps/data/routes/balances.ts +164 -97
  230. package/src/apps/data/routes/blocks.bench.ts +34 -0
  231. package/src/apps/data/routes/blocks.test.ts +12 -6
  232. package/src/apps/data/routes/coingecko.bench.ts +53 -0
  233. package/src/apps/data/routes/earn.bench.ts +71 -0
  234. package/src/apps/data/routes/earn.test.ts +197 -0
  235. package/src/apps/data/routes/earn.ts +487 -45
  236. package/src/apps/data/routes/exchanges.bench.ts +85 -0
  237. package/src/apps/data/routes/exchanges.test.ts +7 -6
  238. package/src/apps/data/routes/exchanges.ts +124 -117
  239. package/src/apps/data/routes/fee-amm.bench.ts +13 -0
  240. package/src/apps/data/routes/indexer.bench.ts +8 -0
  241. package/src/apps/data/routes/indexer.test.ts +2 -1
  242. package/src/apps/data/routes/indexer.ts +3 -2
  243. package/src/apps/data/routes/receipts.bench.ts +39 -0
  244. package/src/apps/data/routes/receipts.test.ts +24 -7
  245. package/src/apps/data/routes/receipts.ts +67 -50
  246. package/src/apps/data/routes/rpc.bench.ts +14 -0
  247. package/src/apps/data/routes/rpc.test.ts +27 -0
  248. package/src/apps/data/routes/rpc.ts +5 -1
  249. package/src/apps/data/routes/tokenlist.bench.ts +3 -0
  250. package/src/apps/data/routes/tokens.bench.ts +76 -0
  251. package/src/apps/data/routes/tokens.test.ts +51 -0
  252. package/src/apps/data/routes/transactions.bench.ts +40 -0
  253. package/src/apps/data/routes/transactions.test.ts +42 -0
  254. package/src/apps/data/routes/transactions.ts +44 -39
  255. package/src/apps/data/routes/transfers.bench.ts +28 -0
  256. package/src/apps/data/routes/transfers.test.ts +402 -24
  257. package/src/apps/data/routes/transfers.ts +708 -101
  258. package/src/apps/data/routes/valuation.bench.ts +14 -0
  259. package/src/apps/data/routes/valuation.test.ts +26 -0
  260. package/src/apps/data/routes/valuation.ts +6 -2
  261. package/src/apps/data/routes/verified-tokens.bench.ts +8 -0
  262. package/src/apps/data/routes/webhooks.bench.ts +26 -0
  263. package/src/apps/data/routes/webhooks.scan.test.ts +326 -0
  264. package/src/apps/data/routes/webhooks.test.ts +466 -135
  265. package/src/apps/data/routes/webhooks.ts +820 -429
  266. package/src/apps/data/routes/zones.bench.ts +32 -0
  267. package/src/apps/data/routes/zones.test.ts +1 -1
  268. package/src/apps/data/routes/zones.ts +7 -2
  269. package/src/apps/funding/routes/chains.test.ts +1 -1
  270. package/src/apps/funding/routes/deposit-addresses.test.ts +1 -1
  271. package/src/apps/funding/routes/deposit-addresses.ts +1 -1
  272. package/src/apps/funding/routes/providers.test.ts +1 -1
  273. package/src/apps/funding/routes/quotes.test.ts +2 -2
  274. package/src/apps/funding/routes/transfers.test.ts +3 -6
  275. package/src/apps/funding/routes/transfers.ts +1 -1
  276. package/src/apps/management/routes/billing.ts +1 -1
  277. package/src/apps/management/routes/faucet.ts +2 -2
  278. package/src/apps/management/routes/me.test.ts +31 -0
  279. package/src/apps/mcp.ts +4 -1
  280. package/src/apps/mpp/Mpp.test.ts +13 -1
  281. package/src/apps/mpp/Mpp.ts +8 -0
  282. package/src/apps/mpp/internal/Adapter.ts +10 -2
  283. package/src/db/Db.test.ts +40 -6
  284. package/src/db/Db.ts +114 -19
  285. package/src/db/Schema.ts +32 -0
  286. package/src/db/tables/sponsoredTransactions.ts +9 -2
  287. package/src/db/tables/webhookQueueEvents.ts +285 -0
  288. package/src/db/tables/webhookSubscriptions.ts +131 -4
  289. package/src/internal/Auth.test.ts +61 -50
  290. package/src/internal/Auth.ts +9 -4
  291. package/src/internal/EarnVaults.test.ts +2 -2
  292. package/src/internal/MetricSink.test.ts +575 -0
  293. package/src/internal/MetricSink.ts +325 -10
  294. package/src/internal/RateLimit.test.ts +23 -18
  295. package/src/internal/RateLimit.ts +23 -15
  296. package/src/internal/Schema.ts +1 -1
  297. package/src/internal/Store.test.ts +99 -13
  298. package/src/internal/Store.ts +52 -17
  299. package/src/internal/Tidx.test.ts +4 -4
  300. package/src/internal/Tidx.ts +1 -3
  301. package/src/internal/Value.test.ts +25 -0
  302. package/src/internal/Value.ts +29 -0
  303. package/src/internal/Viem.test.ts +8 -0
  304. package/src/internal/Viem.ts +2 -1
  305. package/src/internal/WebhookDestination.test.ts +20 -0
  306. package/src/internal/WebhookDestination.ts +10 -0
  307. package/src/internal/WebhookTransfer.test.ts +89 -0
  308. package/src/internal/WebhookTransfer.ts +430 -0
  309. package/src/internal/Webhooks.test.ts +616 -0
  310. package/src/internal/Webhooks.ts +412 -24
  311. package/src/internal/funding/Provider.test.ts +48 -8
  312. package/src/internal/funding/Provider.ts +12 -7
  313. package/src/internal/funding/Reconciliation.local.test.ts +3 -1
  314. package/src/internal/funding/Reconciliation.test.ts +1240 -0
  315. package/src/internal/funding/Reconciliation.ts +136 -0
  316. package/src/internal/funding/SourceObservation.test.ts +1 -0
  317. package/src/internal/funding/providers/index.test.ts +73 -3
  318. package/src/internal/funding/providers/relay.test.ts +2 -9
  319. package/src/internal/funding/providers/relay.ts +72 -13
@@ -184,6 +184,14 @@ describe('migrations', () => {
184
184
  for (const column of Object.keys(row)) expect(sql).toContain(column)
185
185
  expect(sql).toContain('timings Map(String, Float64)')
186
186
  })
187
+
188
+ test('the migrations declare query benchmark history', () => {
189
+ const sql = Analytics.migrations.map((migration) => migration.sql).join('\n')
190
+ expect(sql).toContain('CREATE TABLE IF NOT EXISTS query_benchmark_results')
191
+ expect(sql).toContain('ORDER BY (chain_id, query, metric, timestamp, run_id)')
192
+ expect(sql).toContain('rpc_url String')
193
+ expect(sql).toContain('tidx_url String')
194
+ })
187
195
  })
188
196
 
189
197
  describe('get', () => {
@@ -192,6 +192,32 @@ export const migrations: readonly Migration[] = [
192
192
  ADD COLUMN IF NOT EXISTS timings Map(String, Float64)
193
193
  `,
194
194
  },
195
+ {
196
+ name: '0005_query_benchmark_results',
197
+ sql: `
198
+ CREATE TABLE IF NOT EXISTS query_benchmark_results (
199
+ timestamp DateTime64(3, 'UTC'),
200
+ run_id String,
201
+ repository LowCardinality(String),
202
+ git_sha String,
203
+ git_ref LowCardinality(String),
204
+ chain_id UInt32,
205
+ chain LowCardinality(String),
206
+ query String,
207
+ metric LowCardinality(String),
208
+ mean_ms Float64,
209
+ min_ms Float64,
210
+ max_ms Float64,
211
+ samples UInt16,
212
+ tidx_queries Array(String),
213
+ rpc_url String,
214
+ tidx_url String
215
+ )
216
+ ENGINE = ReplacingMergeTree
217
+ PARTITION BY toYYYYMM(timestamp)
218
+ ORDER BY (chain_id, query, metric, timestamp, run_id)
219
+ `,
220
+ },
195
221
  ]
196
222
 
197
223
  /**
@@ -5,16 +5,34 @@ describe('chains', () => {
5
5
  expect(Zones.chains).toMatchObject([
6
6
  {
7
7
  contracts: {
8
- messenger: { address: '0x254356112cCf6f32fAd84F16CC5E0A0cCA17Beb7' },
9
- portal: { address: '0x59831A17340EE14FE136d751EfbeA8b630470fD2' },
8
+ messenger: { address: '0x2fB7Aba18510622cd88F5f45B3AC0E7Dd70606a5' },
9
+ portal: { address: '0x5765e8B9003054e479df44D12D3dEeaADEfa8b7c' },
10
+ verifier: { address: '0xfa16b9C6A356a096F0e7ceF0135C393A81d4a355' },
10
11
  },
11
- id: 421_700_001,
12
+ id: 1_424_310_001,
13
+ name: 'zone-moderato-internal',
12
14
  rpcUrls: {
13
- default: { http: ['https://rpc-zone-e.testnet.tempo.xyz'] },
14
- internal: { http: ['https://rpc-zone-e.testnet.tempo.xyz'] },
15
+ default: { http: ['https://zone-internal-rpc.testnet.tempo.xyz'] },
16
+ internal: { http: ['https://zone-internal-rpc.testnet.tempo.xyz'] },
17
+ tidx: { http: ['https://indexer-zone-internal.testnet.tempo.xyz'] },
15
18
  },
16
19
  sourceId: 42_431,
17
20
  },
21
+ {
22
+ contracts: {
23
+ messenger: { address: '0x171699d2B5211414C23E5Cd306d05046b78FdD16' },
24
+ portal: { address: '0xe5208b9604972CA6a2E1EF656a9d2bDF2e530B9A' },
25
+ verifier: { address: '0x3E7C1cC9C049052eb061116A4Ee7a7C281fa1F30' },
26
+ },
27
+ id: 421_700_001,
28
+ name: 'zone-mainnet-internal',
29
+ rpcUrls: {
30
+ default: { http: ['https://zone-internal-rpc.tempo.xyz'] },
31
+ internal: { http: ['https://zone-internal-rpc.tempo.xyz'] },
32
+ tidx: { http: ['https://indexer-zone-internal.tempo.xyz'] },
33
+ },
34
+ sourceId: 4_217,
35
+ },
18
36
  {
19
37
  contracts: {
20
38
  messenger: { address: '0x5A4d000000000000000000000000000000000000' },
package/src/apps/Zones.ts CHANGED
@@ -1,23 +1,44 @@
1
1
  import { defineChain } from 'viem'
2
- import { tempoDevnet, tempoTestnet } from 'viem/tempo/chains'
2
+ import { tempo, tempoDevnet, tempoTestnet } from 'viem/tempo/chains'
3
3
 
4
- /** Zone E on Tempo testnet. */
5
- export const zoneE = defineChain({
4
+ /** Internal Moderato Zone on Tempo testnet. */
5
+ export const zoneModeratoInternal = defineChain({
6
6
  ...tempoTestnet,
7
7
  contracts: {
8
8
  ...tempoTestnet.contracts,
9
- messenger: { address: '0x254356112cCf6f32fAd84F16CC5E0A0cCA17Beb7' },
10
- portal: { address: '0x59831A17340EE14FE136d751EfbeA8b630470fD2' },
9
+ messenger: { address: '0x2fB7Aba18510622cd88F5f45B3AC0E7Dd70606a5' },
10
+ portal: { address: '0x5765e8B9003054e479df44D12D3dEeaADEfa8b7c' },
11
+ verifier: { address: '0xfa16b9C6A356a096F0e7ceF0135C393A81d4a355' },
11
12
  },
12
- id: 421_700_001,
13
- name: 'zone-e',
13
+ id: 1_424_310_001,
14
+ name: 'zone-moderato-internal',
14
15
  rpcUrls: {
15
- default: { http: ['https://rpc-zone-e.testnet.tempo.xyz'] },
16
- internal: { http: ['https://rpc-zone-e.testnet.tempo.xyz'] },
16
+ default: { http: ['https://zone-internal-rpc.testnet.tempo.xyz'] },
17
+ internal: { http: ['https://zone-internal-rpc.testnet.tempo.xyz'] },
18
+ tidx: { http: ['https://indexer-zone-internal.testnet.tempo.xyz'] },
17
19
  },
18
20
  sourceId: tempoTestnet.id,
19
21
  })
20
22
 
23
+ /** Internal Zone on Tempo mainnet. */
24
+ export const zoneMainnetInternal = defineChain({
25
+ ...tempo,
26
+ contracts: {
27
+ ...tempo.contracts,
28
+ messenger: { address: '0x171699d2B5211414C23E5Cd306d05046b78FdD16' },
29
+ portal: { address: '0xe5208b9604972CA6a2E1EF656a9d2bDF2e530B9A' },
30
+ verifier: { address: '0x3E7C1cC9C049052eb061116A4Ee7a7C281fa1F30' },
31
+ },
32
+ id: 421_700_001,
33
+ name: 'zone-mainnet-internal',
34
+ rpcUrls: {
35
+ default: { http: ['https://zone-internal-rpc.tempo.xyz'] },
36
+ internal: { http: ['https://zone-internal-rpc.tempo.xyz'] },
37
+ tidx: { http: ['https://indexer-zone-internal.tempo.xyz'] },
38
+ },
39
+ sourceId: tempo.id,
40
+ })
41
+
21
42
  /** Stable hosted Zone on Tempo devnet. */
22
43
  export const zoneStable = defineChain({
23
44
  ...tempoDevnet,
@@ -37,4 +58,4 @@ export const zoneStable = defineChain({
37
58
  })
38
59
 
39
60
  /** Hosted Zone chains served by the API and admin. */
40
- export const chains = [zoneE, zoneStable] as const
61
+ export const chains = [zoneModeratoInternal, zoneMainnetInternal, zoneStable] as const
@@ -197,6 +197,7 @@ describe('data()', () => {
197
197
  42431,
198
198
  421700001,
199
199
  421700006,
200
+ 1424310001,
200
201
  ],
201
202
  }
202
203
  `)
@@ -436,8 +436,8 @@ describe('sandbox chain guard', () => {
436
436
  })
437
437
 
438
438
  async function exhaustPublicQuota(store: Store.Store) {
439
- const limit = { perMinute: 60 }
439
+ const limit = { limit: 60, period: 'minute' } satisfies RateLimit.Limit
440
440
  const rateLimit = RateLimit.memory({ store })
441
- for (let index = 0; index < limit.perMinute; index++)
441
+ for (let index = 0; index < limit.limit; index++)
442
442
  await rateLimit.consume({ key: 'public:anonymous', limit })
443
443
  }
@@ -41,6 +41,24 @@ describe('from', () => {
41
41
  })
42
42
 
43
43
  describe('ecb', () => {
44
+ test('caches the daily feed for one day', () => {
45
+ expect(FxOracle.ecb({ url: feedUrl('1.25') }).ttl).toMatchInlineSnapshot(`86400000`)
46
+ })
47
+
48
+ test('rotates the cache key after the daily publication window', () => {
49
+ vi.useFakeTimers()
50
+ try {
51
+ const oracle = FxOracle.ecb({ url: feedUrl('1.25') })
52
+
53
+ vi.setSystemTime('2026-01-02T15:59:00.000Z')
54
+ expect(oracle.cacheKey?.()).toMatchInlineSnapshot(`"ecb:2026-01-01"`)
55
+ vi.setSystemTime('2026-01-02T16:00:00.000Z')
56
+ expect(oracle.cacheKey?.()).toMatchInlineSnapshot(`"ecb:2026-01-02"`)
57
+ } finally {
58
+ vi.useRealTimers()
59
+ }
60
+ })
61
+
44
62
  test('fetches and parses the daily reference rates', async () => {
45
63
  const rates = await FxOracle.ecb({ url: feedUrl('1.25') }).rates()
46
64
  expect(rates).toMatchInlineSnapshot(`
@@ -4,6 +4,8 @@ import * as Ttl from '../../internal/Ttl.js'
4
4
 
5
5
  /** A pluggable fiat FX rate oracle consumed by the valuation endpoint. */
6
6
  export type Oracle = {
7
+ /** Returns the cache-key suffix for the oracle's current publication window. */
8
+ cacheKey?: (() => string) | undefined
7
9
  /** Oracle identifier, surfaced as valuation rate provenance (e.g. `ecb`). */
8
10
  name: string
9
11
  /** Fetches the oracle's current rate set. */
@@ -34,6 +36,7 @@ export const ecbUrl = 'https://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily
34
36
  */
35
37
  export function from(oracle: from.Value): Oracle {
36
38
  return {
39
+ ...(oracle.cacheKey ? { cacheKey: oracle.cacheKey } : {}),
37
40
  name: oracle.name,
38
41
  rates: async () => {
39
42
  try {
@@ -48,19 +51,17 @@ export function from(oracle: from.Value): Oracle {
48
51
 
49
52
  export declare namespace from {
50
53
  /** Oracle definition accepted by {@link from}. */
51
- type Value = Pick<Oracle, 'name' | 'rates'> & {
54
+ type Value = Pick<Oracle, 'cacheKey' | 'name' | 'rates'> & {
52
55
  /** Cache lifetime for a fetched rate set, in milliseconds. @default `Ttl.hours(1)` */
53
56
  ttl?: number | undefined
54
57
  }
55
58
  }
56
59
 
57
- /**
58
- * European Central Bank euro reference rates: one EUR-based set covering ~30
59
- * currencies, published once per working day.
60
- */
60
+ /** European Central Bank reference rates, cached for one day to match their publication cadence. */
61
61
  export function ecb(options: ecb.Options = {}): Oracle {
62
62
  const { fetch = globalThis.fetch, url = ecbUrl } = options
63
63
  return from({
64
+ cacheKey: () => `ecb:${ecbPublication(new Date())}`,
64
65
  name: 'ecb',
65
66
  rates: async () => {
66
67
  const response = await fetch(url, {
@@ -90,9 +91,31 @@ export function ecb(options: ecb.Options = {}): Oracle {
90
91
  if (!asOf || rates['USD'] === undefined) throw new ParseError()
91
92
  return { asOf: `${asOf}T00:00:00.000Z`, base: 'EUR', rates }
92
93
  },
94
+ ttl: Ttl.days(1),
93
95
  })
94
96
  }
95
97
 
98
+ const ecbTime = new Intl.DateTimeFormat('en-CA', {
99
+ day: '2-digit',
100
+ hour: '2-digit',
101
+ hourCycle: 'h23',
102
+ month: '2-digit',
103
+ timeZone: 'Europe/Brussels',
104
+ year: 'numeric',
105
+ })
106
+
107
+ function ecbPublication(now: Date) {
108
+ const parts = Object.fromEntries(
109
+ ecbTime.formatToParts(now).map((part) => [part.type, part.value]),
110
+ )
111
+ // Rotate one hour after the ECB's usual 16:00 CET publication time.
112
+ const date = Number(parts['hour']) >= 17 ? now : new Date(now.getTime() - Ttl.days(1))
113
+ const publication = Object.fromEntries(
114
+ ecbTime.formatToParts(date).map((part) => [part.type, part.value]),
115
+ )
116
+ return `${publication['year']}-${publication['month']}-${publication['day']}`
117
+ }
118
+
96
119
  export declare namespace ecb {
97
120
  /** Options for the ECB oracle. */
98
121
  type Options = {
@@ -0,0 +1,41 @@
1
+ import * as QueryBench from '../../../../test/QueryBench.js'
2
+
3
+ const fixtures = {
4
+ 4217: {
5
+ address: '0xc24357119432595a547cb2c1e41c51d753645519',
6
+ transactionHash: '0x7f98e4b2bf4d1444b257526f7dd294ac3480d73cd91f723bf0df6062d1ba1c82',
7
+ },
8
+ 42431: {
9
+ address: '0x15496d3123afb2cfadc0ac068eadd11d0f8ae799',
10
+ transactionHash: '0x1c8ccebb169f863b72388cc057fcecee240032eb7d2c64aa6f6fb8e5a60d3f9a',
11
+ },
12
+ } as const
13
+
14
+ QueryBench.bench({
15
+ name: 'getAddressActivities',
16
+ path: {
17
+ 4217: `/v1/addresses/${fixtures[4217].address}/activities`,
18
+ 42431: `/v1/addresses/${fixtures[42431].address}/activities`,
19
+ },
20
+ queries: [
21
+ 'group=true',
22
+ 'include=token.logoUri',
23
+ 'include=token.verified',
24
+ 'logs=true',
25
+ 'valuation.currency=USD',
26
+ ],
27
+ })
28
+
29
+ QueryBench.bench({
30
+ name: 'getTransactionActivities',
31
+ path: {
32
+ 4217: `/v1/transactions/${fixtures[4217].transactionHash}/activities`,
33
+ 42431: `/v1/transactions/${fixtures[42431].transactionHash}/activities`,
34
+ },
35
+ queries: [
36
+ 'include=token.logoUri',
37
+ 'include=token.verified',
38
+ 'logs=true',
39
+ 'valuation.currency=USD',
40
+ ],
41
+ })
@@ -328,6 +328,25 @@ describe('GET /addresses/:address/activities', () => {
328
328
  `)
329
329
  })
330
330
 
331
+ test.skipIf(runtime.mode !== 'localnet')('omits activity valuations by default', async () => {
332
+ const response = await client.v1.transactions[':transactionHash'].activities.$get(
333
+ {
334
+ param: { transactionHash: runtime.fixtures!.faucetTransactionHashes[0]! },
335
+ query: {},
336
+ },
337
+ TestApp.auth,
338
+ )
339
+ const body = await TestApp.json(response, Activities.schema.getTransactionActivities.Response)
340
+ expect(response.status).toBe(200)
341
+
342
+ const amounts = body.data.flatMap((item) =>
343
+ item.type === 'transfer' || item.type === 'mint' ? [item.data.sourceAmount] : [],
344
+ )
345
+ expect(amounts.length).toBeGreaterThan(0)
346
+ for (const amount of amounts) expect('valuation' in amount).toBe(false)
347
+ expect(response.headers.get('server-timing')).not.toContain('valuation_rates;dur=')
348
+ })
349
+
331
350
  test('returns every item at the root by default (no group entries)', async () => {
332
351
  const body = await activities(accounts.channel)
333
352
  expect(body.data.every((entry) => entry.type !== 'group')).toBe(true)
@@ -680,11 +699,12 @@ describe('Activities.list precompile classification', () => {
680
699
  logIdx: number
681
700
  }): Activities.Row {
682
701
  type Param = { indexed?: boolean; name?: string; type: string }
683
- const event = Abis.abis.find((a) => a.type === 'event' && a.name === options.eventName) as {
702
+ const abi = [...Abis.abis, ...Abis.earnRouter, ...Abis.earnVault]
703
+ const event = abi.find((a) => a.type === 'event' && a.name === options.eventName) as {
684
704
  inputs: readonly Param[]
685
705
  }
686
706
  const topics = encodeEventTopics({
687
- abi: Abis.abis,
707
+ abi,
688
708
  eventName: options.eventName as never,
689
709
  args: options.args as never,
690
710
  }) as (string | null)[]
@@ -732,6 +752,106 @@ describe('Activities.list precompile classification', () => {
732
752
  return items
733
753
  }
734
754
 
755
+ test('classifies every Earn vault and private-router event', async () => {
756
+ const requestId = `0x${'c'.repeat(64)}` as Hex.Hex
757
+ const cases = [
758
+ ['Deposited', { assets: 100n, caller: viewer, earnShares: 90n, receiver: viewer }],
759
+ [
760
+ 'VenueSharesDeposited',
761
+ {
762
+ caller: viewer,
763
+ earnShares: 90n,
764
+ receivedEngineShares: 95n,
765
+ receiver: viewer,
766
+ requestedVenueShares: 100n,
767
+ },
768
+ ],
769
+ ['Redeemed', { assets: 100n, caller: viewer, earnShares: 90n, receiver: viewer }],
770
+ ['WithdrewExact', { assets: 100n, caller: viewer, earnSharesBurned: 90n, receiver: viewer }],
771
+ ['RedeemRequested', { earnShares: 90n, receiver: viewer, requestId, requester: viewer }],
772
+ [
773
+ 'RedeemFinalized',
774
+ { asset: tokenA, assets: 100n, earnShares: 90n, receiver: viewer, requestId },
775
+ ],
776
+ ['RedeemCancelled', { earnShares: 90n, receiver: viewer, requestId }],
777
+ [
778
+ 'EarnDeposit',
779
+ {
780
+ actionId: requestId,
781
+ earnShares: 90n,
782
+ earnVault: tokenA,
783
+ inputAmount: 100n,
784
+ inputToken: tokenA,
785
+ vaultAssets: 100n,
786
+ zoneDepositHash: requestId,
787
+ },
788
+ ],
789
+ [
790
+ 'EarnRedeem',
791
+ {
792
+ actionId: requestId,
793
+ earnShares: 90n,
794
+ earnVault: tokenA,
795
+ outputAmount: 100n,
796
+ outputToken: tokenA,
797
+ vaultAssets: 100n,
798
+ zoneDepositHash: requestId,
799
+ },
800
+ ],
801
+ ] as const
802
+
803
+ const types = []
804
+ for (const [eventName, args] of cases) {
805
+ const items = await classify([logRow({ address: tokenA, args, eventName, logIdx: 0 })])
806
+ types.push(items[0]?.type)
807
+ }
808
+
809
+ expect(types).toMatchInlineSnapshot(`
810
+ [
811
+ "assets-deposited",
812
+ "shares-deposited",
813
+ "shares-redeemed",
814
+ "assets-withdrawn",
815
+ "shares-redemption-requested",
816
+ "shares-redemption-finalized",
817
+ "shares-redemption-cancelled",
818
+ "private-assets-deposited",
819
+ "private-shares-redeemed",
820
+ ]
821
+ `)
822
+ })
823
+
824
+ test('prefers a private Earn event over its underlying vault event', async () => {
825
+ const actionId = `0x${'c'.repeat(64)}` as Hex.Hex
826
+ const items = await classify([
827
+ logRow({
828
+ address: tokenA,
829
+ args: { assets: 100n, caller: viewer, earnShares: 90n, receiver: viewer },
830
+ eventName: 'Deposited',
831
+ logIdx: 0,
832
+ }),
833
+ logRow({
834
+ address: tokenA,
835
+ args: {
836
+ actionId,
837
+ earnShares: 90n,
838
+ earnVault: tokenA,
839
+ inputAmount: 100n,
840
+ inputToken: tokenA,
841
+ vaultAssets: 100n,
842
+ zoneDepositHash: actionId,
843
+ },
844
+ eventName: 'EarnDeposit',
845
+ logIdx: 1,
846
+ }),
847
+ ])
848
+ expect(items.map((item) => item.type)).toMatchInlineSnapshot(`
849
+ [
850
+ "private-assets-deposited",
851
+ ]
852
+ `)
853
+ })
854
+
735
855
  test('classifies ChannelOpened as `channel-opened` with the deposit token', async () => {
736
856
  const items = await classify([
737
857
  logRow({