tapimo 0.10.0 → 0.10.2

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 (295) 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 +6007 -5003
  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 +1 -1
  12. package/dist/Webhooks.d.ts.map +1 -1
  13. package/dist/Webhooks.js +6 -6
  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 +22 -13
  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/ui.generated.d.ts +1 -1
  24. package/dist/admin/ui.generated.js +69 -69
  25. package/dist/admin/ui.generated.js.map +1 -1
  26. package/dist/analytics/Analytics.d.ts.map +1 -1
  27. package/dist/analytics/Analytics.js +232 -0
  28. package/dist/analytics/Analytics.js.map +1 -1
  29. package/dist/analytics/tables/requestEvents.d.ts +4 -0
  30. package/dist/analytics/tables/requestEvents.d.ts.map +1 -1
  31. package/dist/analytics/tables/requestEvents.js +2 -0
  32. package/dist/analytics/tables/requestEvents.js.map +1 -1
  33. package/dist/apps/Zones.d.ts +4266 -82
  34. package/dist/apps/Zones.d.ts.map +1 -1
  35. package/dist/apps/Zones.js +27 -8
  36. package/dist/apps/Zones.js.map +1 -1
  37. package/dist/apps/data/App.d.ts +3467 -2696
  38. package/dist/apps/data/App.d.ts.map +1 -1
  39. package/dist/apps/data/App.js +2 -0
  40. package/dist/apps/data/App.js.map +1 -1
  41. package/dist/apps/data/routes/activities.d.ts +2999 -100
  42. package/dist/apps/data/routes/activities.d.ts.map +1 -1
  43. package/dist/apps/data/routes/activities.js +340 -2
  44. package/dist/apps/data/routes/activities.js.map +1 -1
  45. package/dist/apps/data/routes/addresses.d.ts +514 -0
  46. package/dist/apps/data/routes/addresses.d.ts.map +1 -1
  47. package/dist/apps/data/routes/balances.d.ts +26 -26
  48. package/dist/apps/data/routes/balances.d.ts.map +1 -1
  49. package/dist/apps/data/routes/balances.js +7 -3
  50. package/dist/apps/data/routes/balances.js.map +1 -1
  51. package/dist/apps/data/routes/blocks.d.ts +4 -4
  52. package/dist/apps/data/routes/earn.d.ts +75 -75
  53. package/dist/apps/data/routes/earn.d.ts.map +1 -1
  54. package/dist/apps/data/routes/earn.js +65 -36
  55. package/dist/apps/data/routes/earn.js.map +1 -1
  56. package/dist/apps/data/routes/exchanges.d.ts +124 -120
  57. package/dist/apps/data/routes/exchanges.d.ts.map +1 -1
  58. package/dist/apps/data/routes/exchanges.js +115 -77
  59. package/dist/apps/data/routes/exchanges.js.map +1 -1
  60. package/dist/apps/data/routes/fee-amm.d.ts +24 -24
  61. package/dist/apps/data/routes/indexer.d.ts +2 -1
  62. package/dist/apps/data/routes/indexer.d.ts.map +1 -1
  63. package/dist/apps/data/routes/indexer.js +3 -2
  64. package/dist/apps/data/routes/indexer.js.map +1 -1
  65. package/dist/apps/data/routes/receipts.d.ts +4 -3
  66. package/dist/apps/data/routes/receipts.d.ts.map +1 -1
  67. package/dist/apps/data/routes/receipts.js +15 -14
  68. package/dist/apps/data/routes/receipts.js.map +1 -1
  69. package/dist/apps/data/routes/rpc.d.ts.map +1 -1
  70. package/dist/apps/data/routes/rpc.js +5 -1
  71. package/dist/apps/data/routes/rpc.js.map +1 -1
  72. package/dist/apps/data/routes/tokenlist.d.ts +12 -12
  73. package/dist/apps/data/routes/tokens.d.ts +1 -1
  74. package/dist/apps/data/routes/tokens.d.ts.map +1 -1
  75. package/dist/apps/data/routes/tokens.js +4 -3
  76. package/dist/apps/data/routes/tokens.js.map +1 -1
  77. package/dist/apps/data/routes/transfers.d.ts.map +1 -1
  78. package/dist/apps/data/routes/transfers.js +25 -7
  79. package/dist/apps/data/routes/transfers.js.map +1 -1
  80. package/dist/apps/data/routes/verified-tokens.d.ts +37 -37
  81. package/dist/apps/data/routes/webhooks.d.ts +71 -1
  82. package/dist/apps/data/routes/webhooks.d.ts.map +1 -1
  83. package/dist/apps/data/routes/webhooks.js +177 -23
  84. package/dist/apps/data/routes/webhooks.js.map +1 -1
  85. package/dist/apps/data/routes/zones.js +1 -1
  86. package/dist/apps/data/routes/zones.js.map +1 -1
  87. package/dist/apps/funding/App.d.ts +322 -89
  88. package/dist/apps/funding/App.d.ts.map +1 -1
  89. package/dist/apps/funding/routes/deposit-addresses.d.ts +375 -45
  90. package/dist/apps/funding/routes/deposit-addresses.d.ts.map +1 -1
  91. package/dist/apps/funding/routes/deposit-addresses.js +208 -12
  92. package/dist/apps/funding/routes/deposit-addresses.js.map +1 -1
  93. package/dist/apps/funding/routes/transfers.d.ts +32 -32
  94. package/dist/apps/funding/routes/transfers.js +1 -1
  95. package/dist/apps/funding/routes/transfers.js.map +1 -1
  96. package/dist/apps/management/App.d.ts +418 -418
  97. package/dist/apps/management/routes/api-keys.d.ts +50 -50
  98. package/dist/apps/management/routes/billing.d.ts +72 -72
  99. package/dist/apps/management/routes/billing.js +1 -1
  100. package/dist/apps/management/routes/billing.js.map +1 -1
  101. package/dist/apps/management/routes/faucet.d.ts +8 -8
  102. package/dist/apps/management/routes/faucet.js +2 -2
  103. package/dist/apps/management/routes/faucet.js.map +1 -1
  104. package/dist/apps/management/routes/invite-links.d.ts +42 -42
  105. package/dist/apps/management/routes/me.d.ts +6 -6
  106. package/dist/apps/management/routes/members.d.ts +14 -14
  107. package/dist/apps/management/routes/projects.d.ts +40 -40
  108. package/dist/apps/management/routes/usage.d.ts +8 -8
  109. package/dist/apps/management/routes/webhooks.d.ts +49 -49
  110. package/dist/apps/mcp.d.ts.map +1 -1
  111. package/dist/apps/mcp.js +4 -1
  112. package/dist/apps/mcp.js.map +1 -1
  113. package/dist/db/Db.d.ts +2 -0
  114. package/dist/db/Db.d.ts.map +1 -1
  115. package/dist/db/Db.js +90 -0
  116. package/dist/db/Db.js.map +1 -1
  117. package/dist/db/Schema.d.ts +19 -0
  118. package/dist/db/Schema.d.ts.map +1 -1
  119. package/dist/db/Schema.js +24 -0
  120. package/dist/db/Schema.js.map +1 -1
  121. package/dist/db/tables/fundingDepositAddresses.d.ts +20 -0
  122. package/dist/db/tables/fundingDepositAddresses.d.ts.map +1 -1
  123. package/dist/db/tables/fundingDepositAddresses.js +17 -0
  124. package/dist/db/tables/fundingDepositAddresses.js.map +1 -1
  125. package/dist/db/tables/fundingDeposits.d.ts +41 -0
  126. package/dist/db/tables/fundingDeposits.d.ts.map +1 -1
  127. package/dist/db/tables/fundingDeposits.js +69 -0
  128. package/dist/db/tables/fundingDeposits.js.map +1 -1
  129. package/dist/db/tables/webhookQueueEvents.d.ts +122 -0
  130. package/dist/db/tables/webhookQueueEvents.d.ts.map +1 -0
  131. package/dist/db/tables/webhookQueueEvents.js +160 -0
  132. package/dist/db/tables/webhookQueueEvents.js.map +1 -0
  133. package/dist/db/tables/webhookSubscriptions.d.ts +2 -0
  134. package/dist/db/tables/webhookSubscriptions.d.ts.map +1 -1
  135. package/dist/db/tables/webhookSubscriptions.js +10 -0
  136. package/dist/db/tables/webhookSubscriptions.js.map +1 -1
  137. package/dist/internal/Auth.d.ts +3 -26
  138. package/dist/internal/Auth.d.ts.map +1 -1
  139. package/dist/internal/Auth.js +6 -37
  140. package/dist/internal/Auth.js.map +1 -1
  141. package/dist/internal/Credential.d.ts +27 -0
  142. package/dist/internal/Credential.d.ts.map +1 -0
  143. package/dist/internal/Credential.js +34 -0
  144. package/dist/internal/Credential.js.map +1 -0
  145. package/dist/internal/EarnRates.js +11 -7
  146. package/dist/internal/EarnRates.js.map +1 -1
  147. package/dist/internal/Log.d.ts +8 -0
  148. package/dist/internal/Log.d.ts.map +1 -1
  149. package/dist/internal/Log.js +4 -0
  150. package/dist/internal/Log.js.map +1 -1
  151. package/dist/internal/MetricSink.d.ts +51 -0
  152. package/dist/internal/MetricSink.d.ts.map +1 -1
  153. package/dist/internal/MetricSink.js +54 -2
  154. package/dist/internal/MetricSink.js.map +1 -1
  155. package/dist/internal/RateLimit.d.ts +4 -6
  156. package/dist/internal/RateLimit.d.ts.map +1 -1
  157. package/dist/internal/RateLimit.js +15 -14
  158. package/dist/internal/RateLimit.js.map +1 -1
  159. package/dist/internal/Store.d.ts +2 -1
  160. package/dist/internal/Store.d.ts.map +1 -1
  161. package/dist/internal/Store.js +57 -18
  162. package/dist/internal/Store.js.map +1 -1
  163. package/dist/internal/Tidx.d.ts +4 -3
  164. package/dist/internal/Tidx.d.ts.map +1 -1
  165. package/dist/internal/Tidx.js +2 -2
  166. package/dist/internal/Tidx.js.map +1 -1
  167. package/dist/internal/Value.d.ts +2 -0
  168. package/dist/internal/Value.d.ts.map +1 -1
  169. package/dist/internal/Value.js +25 -0
  170. package/dist/internal/Value.js.map +1 -1
  171. package/dist/internal/Viem.d.ts +4 -3
  172. package/dist/internal/Viem.d.ts.map +1 -1
  173. package/dist/internal/Viem.js +3 -2
  174. package/dist/internal/Viem.js.map +1 -1
  175. package/dist/internal/WebhookTransfer.d.ts +20 -0
  176. package/dist/internal/WebhookTransfer.d.ts.map +1 -1
  177. package/dist/internal/WebhookTransfer.js +7 -4
  178. package/dist/internal/WebhookTransfer.js.map +1 -1
  179. package/dist/internal/Webhooks.d.ts +141 -0
  180. package/dist/internal/Webhooks.d.ts.map +1 -1
  181. package/dist/internal/Webhooks.js +139 -10
  182. package/dist/internal/Webhooks.js.map +1 -1
  183. package/dist/internal/funding/providers/relay.d.ts +3 -4
  184. package/dist/internal/funding/providers/relay.d.ts.map +1 -1
  185. package/dist/internal/funding/providers/relay.js +59 -8
  186. package/dist/internal/funding/providers/relay.js.map +1 -1
  187. package/dist/internal/index.d.ts +1 -0
  188. package/dist/internal/index.d.ts.map +1 -1
  189. package/dist/internal/index.js +1 -0
  190. package/dist/internal/index.js.map +1 -1
  191. package/package.json +3 -3
  192. package/src/ApiKeys.test.ts +20 -0
  193. package/src/ApiKeys.ts +28 -1
  194. package/src/App.test.ts +40 -8
  195. package/src/App.ts +1 -0
  196. package/src/Client.test-d.ts +34 -1
  197. package/src/Webhooks.ts +20 -18
  198. package/src/admin/apps/api-keys.test.ts +9 -0
  199. package/src/admin/apps/api-keys.ts +15 -0
  200. package/src/admin/ui/src/lib/query-client.ts +3 -2
  201. package/src/admin/ui/src/routes/api-keys.tsx +31 -9
  202. package/src/admin/ui.generated.ts +69 -69
  203. package/src/analytics/Analytics.test.ts +42 -0
  204. package/src/analytics/Analytics.ts +232 -0
  205. package/src/analytics/tables/requestEvents.ts +6 -0
  206. package/src/apps/Zones.test.ts +20 -3
  207. package/src/apps/Zones.ts +28 -8
  208. package/src/apps/composition.test.ts +2 -0
  209. package/src/apps/data/App.test.ts +2 -2
  210. package/src/apps/data/App.ts +2 -0
  211. package/src/apps/data/routes/activities.bench.ts +41 -0
  212. package/src/apps/data/routes/activities.test.ts +103 -2
  213. package/src/apps/data/routes/activities.ts +401 -2
  214. package/src/apps/data/routes/balances.bench.ts +21 -0
  215. package/src/apps/data/routes/balances.ts +7 -3
  216. package/src/apps/data/routes/blocks.bench.ts +34 -0
  217. package/src/apps/data/routes/coingecko.bench.ts +53 -0
  218. package/src/apps/data/routes/earn.bench.ts +71 -0
  219. package/src/apps/data/routes/earn.ts +66 -36
  220. package/src/apps/data/routes/exchanges.bench.ts +85 -0
  221. package/src/apps/data/routes/exchanges.test.ts +8 -3
  222. package/src/apps/data/routes/exchanges.ts +134 -82
  223. package/src/apps/data/routes/fee-amm.bench.ts +13 -0
  224. package/src/apps/data/routes/indexer.bench.ts +8 -0
  225. package/src/apps/data/routes/indexer.test.ts +2 -1
  226. package/src/apps/data/routes/indexer.ts +3 -2
  227. package/src/apps/data/routes/receipts.bench.ts +39 -0
  228. package/src/apps/data/routes/receipts.ts +16 -14
  229. package/src/apps/data/routes/rpc.bench.ts +14 -0
  230. package/src/apps/data/routes/rpc.test.ts +27 -0
  231. package/src/apps/data/routes/rpc.ts +5 -1
  232. package/src/apps/data/routes/tokenlist.bench.ts +3 -0
  233. package/src/apps/data/routes/tokens.bench.ts +76 -0
  234. package/src/apps/data/routes/tokens.ts +3 -2
  235. package/src/apps/data/routes/transactions.bench.ts +48 -0
  236. package/src/apps/data/routes/transfers.bench.ts +28 -0
  237. package/src/apps/data/routes/transfers.ts +36 -10
  238. package/src/apps/data/routes/valuation.bench.ts +14 -0
  239. package/src/apps/data/routes/verified-tokens.bench.ts +8 -0
  240. package/src/apps/data/routes/webhooks.bench.ts +26 -0
  241. package/src/apps/data/routes/webhooks.scan.test.ts +326 -0
  242. package/src/apps/data/routes/webhooks.test.ts +53 -6
  243. package/src/apps/data/routes/webhooks.ts +252 -24
  244. package/src/apps/data/routes/zones.bench.ts +32 -0
  245. package/src/apps/data/routes/zones.test.ts +1 -1
  246. package/src/apps/data/routes/zones.ts +1 -1
  247. package/src/apps/funding/routes/chains.test.ts +1 -1
  248. package/src/apps/funding/routes/deposit-addresses.test.ts +217 -3
  249. package/src/apps/funding/routes/deposit-addresses.ts +255 -19
  250. package/src/apps/funding/routes/providers.test.ts +1 -1
  251. package/src/apps/funding/routes/quotes.test.ts +1 -1
  252. package/src/apps/funding/routes/transfers.test.ts +20 -8
  253. package/src/apps/funding/routes/transfers.ts +1 -1
  254. package/src/apps/management/routes/billing.ts +1 -1
  255. package/src/apps/management/routes/faucet.ts +2 -2
  256. package/src/apps/management/routes/me.test.ts +31 -0
  257. package/src/apps/mcp.ts +4 -1
  258. package/src/db/Db.ts +117 -0
  259. package/src/db/Schema.ts +32 -0
  260. package/src/db/tables/fundingDepositAddresses.test.ts +28 -0
  261. package/src/db/tables/fundingDepositAddresses.ts +39 -0
  262. package/src/db/tables/fundingDeposits.test.ts +82 -0
  263. package/src/db/tables/fundingDeposits.ts +130 -0
  264. package/src/db/tables/webhookQueueEvents.ts +285 -0
  265. package/src/db/tables/webhookSubscriptions.ts +15 -0
  266. package/src/internal/Auth.test.ts +61 -98
  267. package/src/internal/Auth.ts +9 -63
  268. package/src/internal/Credential.test.ts +51 -0
  269. package/src/internal/Credential.ts +58 -0
  270. package/src/internal/EarnRates.ts +13 -7
  271. package/src/internal/EarnVaults.test.ts +2 -2
  272. package/src/internal/Log.test.ts +3 -1
  273. package/src/internal/Log.ts +14 -0
  274. package/src/internal/MetricSink.test.ts +108 -2
  275. package/src/internal/MetricSink.ts +112 -2
  276. package/src/internal/RateLimit.test.ts +23 -18
  277. package/src/internal/RateLimit.ts +23 -15
  278. package/src/internal/Store.test.ts +99 -13
  279. package/src/internal/Store.ts +52 -17
  280. package/src/internal/Tidx.test.ts +4 -4
  281. package/src/internal/Tidx.ts +5 -4
  282. package/src/internal/Value.test.ts +25 -0
  283. package/src/internal/Value.ts +29 -0
  284. package/src/internal/Viem.test.ts +4 -0
  285. package/src/internal/Viem.ts +6 -4
  286. package/src/internal/WebhookTransfer.test.ts +89 -0
  287. package/src/internal/WebhookTransfer.ts +11 -7
  288. package/src/internal/Webhooks.test.ts +488 -0
  289. package/src/internal/Webhooks.ts +291 -10
  290. package/src/internal/funding/Provider.test.ts +1 -1
  291. package/src/internal/funding/providers/index.test.ts +73 -3
  292. package/src/internal/funding/providers/relay.test.ts +1 -5
  293. package/src/internal/funding/providers/relay.ts +56 -12
  294. package/src/internal/index.test.ts +1 -0
  295. package/src/internal/index.ts +1 -0
@@ -154,7 +154,7 @@ export namespace schema {
154
154
  .strictObject({
155
155
  chainId: Schema.ChainId.check(
156
156
  z.describe('Private Zone chain id.'),
157
- z.meta({ examples: [421700001] }),
157
+ z.meta({ examples: [1424310001] }),
158
158
  ),
159
159
  inputTokens: z
160
160
  .array(Schema.Address)
@@ -164,7 +164,7 @@ export namespace schema {
164
164
  ),
165
165
  name: z
166
166
  .string()
167
- .check(z.describe('Private Zone name.'), z.meta({ examples: ['zone-moderato'] })),
167
+ .check(z.describe('Private Zone name.'), z.meta({ examples: ['zone-moderato-internal'] })),
168
168
  outputTokens: z
169
169
  .array(Schema.Address)
170
170
  .check(
@@ -2034,6 +2034,8 @@ export async function listVaults(c: Context<App.Environment>, options: listVault
2034
2034
  core_EarnVaults.list(db, { chainId: options.chainId }),
2035
2035
  VerifiedTokens.snapshot(c, options.chainId),
2036
2036
  ])
2037
+ const include = vaultInclude(options)
2038
+ const apyByVault = new Map<string, EarnRates.Apy | null>()
2037
2039
  const registry = new Map(records.map((record) => [record.vaultAddress.toLowerCase(), record]))
2038
2040
  const decoded = options.cursor ? Cursor.decode(options.cursor, ['int', 'int']) : undefined
2039
2041
  let position = decoded
@@ -2062,22 +2064,44 @@ export async function listVaults(c: Context<App.Environment>, options: listVault
2062
2064
  }
2063
2065
  scanned += page.items.length
2064
2066
 
2065
- const discovered = await Promise.all(
2066
- page.items.map(async (item) => {
2067
- const record = registry.get(item.vaultAddress.toLowerCase())
2068
- try {
2069
- const discovery = await resolveVaultDiscovery(c, {
2067
+ const apyVaults =
2068
+ apyByVault.size === 0 &&
2069
+ include.includes('apy') &&
2070
+ options.capability.length === 0 &&
2071
+ options['engine.type'] === undefined
2072
+ ? page.items
2073
+ .slice(0, options.limit - matches.length)
2074
+ .map(({ vaultAddress }) => vaultAddress)
2075
+ : []
2076
+ // Rate boundaries and historical quotes depend only on candidate addresses,
2077
+ // so the unfiltered page can resolve them alongside live vault discovery.
2078
+ const [discovered, prefetchedApy] = await Promise.all([
2079
+ Promise.all(
2080
+ page.items.map(async (item) => {
2081
+ const record = registry.get(item.vaultAddress.toLowerCase())
2082
+ try {
2083
+ const discovery = await resolveVaultDiscovery(c, {
2084
+ chainId: options.chainId,
2085
+ include: discoveryInclude(options),
2086
+ vaultAddress: item.vaultAddress,
2087
+ })
2088
+ return { discovery, position: item.position, record }
2089
+ } catch (cause) {
2090
+ if (!record && isIncompatible(cause)) return undefined
2091
+ throw cause
2092
+ }
2093
+ }),
2094
+ ),
2095
+ apyVaults.length > 0
2096
+ ? resolvePageApy(c, {
2070
2097
  chainId: options.chainId,
2071
- include: discoveryInclude(options),
2072
- vaultAddress: item.vaultAddress,
2098
+ include,
2099
+ vaults: apyVaults,
2100
+ window: options['apy.window'],
2073
2101
  })
2074
- return { discovery, position: item.position, record }
2075
- } catch (cause) {
2076
- if (!record && isIncompatible(cause)) return undefined
2077
- throw cause
2078
- }
2079
- }),
2080
- )
2102
+ : undefined,
2103
+ ])
2104
+ for (const [vault, apy] of prefetchedApy ?? []) apyByVault.set(vault, apy)
2081
2105
  for (const match of discovered) {
2082
2106
  if (!match || !matchesVaultFilters(match.discovery, options)) continue
2083
2107
  matches.push(match)
@@ -2089,17 +2113,25 @@ export async function listVaults(c: Context<App.Environment>, options: listVault
2089
2113
 
2090
2114
  const page = matches.slice(0, options.limit)
2091
2115
  const discoveries = page.map(({ discovery }) => discovery)
2092
- const include = vaultInclude(options)
2093
- const [apy, rates, tokens] = await Promise.all([
2094
- resolvePageApy(c, {
2095
- chainId: options.chainId,
2096
- discoveries,
2097
- include,
2098
- window: options['apy.window'],
2099
- }),
2116
+ const missingApyVaults = include.includes('apy')
2117
+ ? discoveries.flatMap(({ vaultAddress }) =>
2118
+ apyByVault.has(vaultAddress.toLowerCase()) ? [] : [vaultAddress],
2119
+ )
2120
+ : []
2121
+ const [missingApy, rates, tokens] = await Promise.all([
2122
+ missingApyVaults.length > 0
2123
+ ? resolvePageApy(c, {
2124
+ chainId: options.chainId,
2125
+ include,
2126
+ vaults: missingApyVaults,
2127
+ window: options['apy.window'],
2128
+ })
2129
+ : undefined,
2100
2130
  resolvePageRates(c, { discoveries, include, oracle: options.oracle, snapshot }),
2101
2131
  resolvePageTokens(c, { chainId: options.chainId, discoveries, include, snapshot }),
2102
2132
  ])
2133
+ for (const [vault, apy] of missingApy ?? []) apyByVault.set(vault, apy)
2134
+ const apy = include.includes('apy') ? apyByVault : undefined
2103
2135
  const data = page.map((match) =>
2104
2136
  resolveVault(c, { ...match, apy, include, rates, snapshot, tokens }),
2105
2137
  )
@@ -2181,8 +2213,8 @@ export async function listVerifiedVaults(
2181
2213
  const [apy, rates, tokens] = await Promise.all([
2182
2214
  resolvePageApy(c, {
2183
2215
  chainId: options.chainId,
2184
- discoveries,
2185
2216
  include,
2217
+ vaults: discoveries.map(({ vaultAddress }) => vaultAddress),
2186
2218
  window: options['apy.window'],
2187
2219
  }),
2188
2220
  resolvePageRates(c, { discoveries, include, oracle: options.oracle, snapshot }),
@@ -2503,8 +2535,8 @@ export async function getVault(c: Context<App.Environment>, options: getVault.Op
2503
2535
  const [apy, rates, tokens] = await Promise.all([
2504
2536
  resolvePageApy(c, {
2505
2537
  chainId: options.chainId,
2506
- discoveries,
2507
2538
  include,
2539
+ vaults: discoveries.map(({ vaultAddress }) => vaultAddress),
2508
2540
  window: options['apy.window'],
2509
2541
  }),
2510
2542
  resolvePageRates(c, { discoveries, include, oracle: options.oracle, snapshot }),
@@ -2616,7 +2648,7 @@ function resolvePageApy(c: Context<App.Environment>, options: resolvePageApy.Opt
2616
2648
  getClient: c.get('getClient'),
2617
2649
  getTidx: c.get('getTidx'),
2618
2650
  store: c.get('store'),
2619
- vaults: options.discoveries.map(({ vaultAddress }) => vaultAddress),
2651
+ vaults: options.vaults,
2620
2652
  window: options.window,
2621
2653
  }),
2622
2654
  )
@@ -2625,8 +2657,8 @@ function resolvePageApy(c: Context<App.Environment>, options: resolvePageApy.Opt
2625
2657
  declare namespace resolvePageApy {
2626
2658
  type Options = {
2627
2659
  chainId: z.output<typeof Schema.ChainId>
2628
- discoveries: readonly EarnVaults.Discovery[]
2629
2660
  include: z.output<typeof schema.getEarnVault.Query>['include']
2661
+ vaults: readonly z.output<typeof Schema.Address>[]
2630
2662
  window: z.output<typeof schema.getEarnVault.Query>['apy.window']
2631
2663
  }
2632
2664
  }
@@ -2837,7 +2869,7 @@ async function queryDeployments(
2837
2869
  c: Context<App.Environment>,
2838
2870
  options: queryDeployments.Options,
2839
2871
  ): Promise<queryDeployments.Result> {
2840
- const filters = ['deployment_rank = 1']
2872
+ const filters: string[] = []
2841
2873
  if (options.asset) filters.push(`lower(asset) = '${options.asset.toLowerCase()}'`)
2842
2874
  if (options.cursor)
2843
2875
  filters.push(
@@ -2855,7 +2887,7 @@ async function queryDeployments(
2855
2887
  ]),
2856
2888
  )
2857
2889
 
2858
- // ClickHouse supports ordering and windowing over decoded event CTEs.
2890
+ // Deduplicate before outer filters so every vault is filtered by its latest deployment.
2859
2891
  const result = await c
2860
2892
  .get('getTidx')(options.chainId)
2861
2893
  .fetch({
@@ -2868,14 +2900,12 @@ async function queryDeployments(
2868
2900
  "earnVault",
2869
2901
  asset,
2870
2902
  block_num,
2871
- log_idx,
2872
- row_number() OVER (
2873
- PARTITION BY lower("earnVault")
2874
- ORDER BY block_num DESC, log_idx DESC
2875
- ) AS deployment_rank
2903
+ log_idx
2876
2904
  FROM EarnStackDeployed
2905
+ ORDER BY block_num DESC, log_idx DESC
2906
+ LIMIT 1 BY lower("earnVault")
2877
2907
  )
2878
- WHERE ${filters.join(' AND ')}
2908
+ ${filters.length > 0 ? `WHERE ${filters.join(' AND ')}` : ''}
2879
2909
  ORDER BY block_num DESC, log_idx DESC
2880
2910
  LIMIT ${options.limit + 1}
2881
2911
  ` as string,
@@ -0,0 +1,85 @@
1
+ import * as QueryBench from '../../../../test/QueryBench.js'
2
+
3
+ const fixtures = {
4
+ 4217: {
5
+ base: '0x20c0000000000000000000001a47bebe936d00d7',
6
+ filledOrderId: '3881',
7
+ orderId: '3312',
8
+ },
9
+ 42431: {
10
+ base: '0x20c000000000000000000000746cbc54ce86a3cb',
11
+ filledOrderId: '18047908',
12
+ orderId: '18048313',
13
+ },
14
+ } as const
15
+
16
+ QueryBench.bench({
17
+ name: 'getSwaps',
18
+ path: '/v1/exchange/swaps',
19
+ queries: ['include=token.logoUri', 'include=token.verified', 'valuation.currency=USD'],
20
+ })
21
+
22
+ QueryBench.bench({
23
+ name: 'getPairs',
24
+ path: '/v1/exchange/pairs',
25
+ queries: ['include=tokens', 'include=totalCount', 'sort=liquidity'],
26
+ })
27
+
28
+ QueryBench.bench({
29
+ name: 'getPair',
30
+ path: {
31
+ 4217: `/v1/exchange/pairs/${fixtures[4217].base}`,
32
+ 42431: `/v1/exchange/pairs/${fixtures[42431].base}`,
33
+ },
34
+ queries: ['include=tokens'],
35
+ })
36
+
37
+ QueryBench.bench({
38
+ name: 'getOrders',
39
+ path: '/v1/exchange/orders',
40
+ queries: ['include=tokens', 'include=totalCount'],
41
+ })
42
+
43
+ QueryBench.bench({
44
+ name: 'getOrders?base',
45
+ path: {
46
+ 4217: `/v1/exchange/orders?base=${fixtures[4217].base}`,
47
+ 42431: `/v1/exchange/orders?base=${fixtures[42431].base}`,
48
+ },
49
+ })
50
+
51
+ QueryBench.bench({
52
+ name: 'getOrder',
53
+ path: {
54
+ 4217: `/v1/exchange/orders/${fixtures[4217].orderId}`,
55
+ 42431: `/v1/exchange/orders/${fixtures[42431].orderId}`,
56
+ },
57
+ queries: ['include=tokens'],
58
+ })
59
+
60
+ QueryBench.bench({
61
+ name: 'getOrderFills',
62
+ path: {
63
+ 4217: `/v1/exchange/orders/${fixtures[4217].filledOrderId}/fills`,
64
+ 42431: `/v1/exchange/orders/${fixtures[42431].filledOrderId}/fills`,
65
+ },
66
+ queries: ['include=totalCount'],
67
+ })
68
+
69
+ QueryBench.bench({
70
+ name: 'getPairOhlc',
71
+ path: {
72
+ 4217: `/v1/exchange/pairs/${fixtures[4217].base}/ohlc`,
73
+ 42431: `/v1/exchange/pairs/${fixtures[42431].base}/ohlc`,
74
+ },
75
+ queries: ['include=tokens'],
76
+ })
77
+
78
+ QueryBench.bench({
79
+ name: 'getPairDepth',
80
+ path: {
81
+ 4217: `/v1/exchange/pairs/${fixtures[4217].base}/depth`,
82
+ 42431: `/v1/exchange/pairs/${fixtures[42431].base}/depth`,
83
+ },
84
+ queries: ['include=tokens'],
85
+ })
@@ -531,7 +531,7 @@ describe('GET /exchange/orders?base=… (pair-scoped orders)', () => {
531
531
  })
532
532
 
533
533
  describe('GET /exchange/pairs/:base/depth', () => {
534
- test('returns orderbook depth for a real pair', async () => {
534
+ test('returns orderbook depth when token metadata is requested', async () => {
535
535
  const client = TestApp.client()
536
536
  const pairsResponse = await client.v1.exchange.pairs.$get(
537
537
  { query: { limit: '5' } },
@@ -547,21 +547,25 @@ describe('GET /exchange/pairs/:base/depth', () => {
547
547
  // throttles the multicall response.
548
548
  let body: z.output<typeof Exchanges.schema.getPairDepth.Response> | null = null
549
549
  let pair: (typeof pairs.data)[number] | null = null
550
+ let timing: string | null = null
550
551
  for (const candidate of pairs.data) {
551
552
  const response = await client.v1.exchange.pairs[':base'].depth.$get(
552
- { param: { base: candidate.base.address }, query: {} },
553
+ { param: { base: candidate.base.address }, query: { include: 'tokens' } },
553
554
  TestApp.auth,
554
555
  )
555
556
  if (response.status === 502) return
556
557
  expect(response.status).toBe(200)
557
558
  body = await TestApp.json(response, Exchanges.schema.getPairDepth.Response)
558
559
  pair = candidate
560
+ timing = response.headers.get('server-timing')
559
561
  if (body.bids.length > 0 || body.asks.length > 0) break
560
562
  }
561
563
  if (!body || !pair) return
562
564
 
563
565
  expect(body.base.address).toBe(pair.base.address)
564
566
  expect(body.quote.address).toBe(pair.quote.address)
567
+ expect(timing).toContain('pair_lookup;dur=')
568
+ expect(timing).not.toContain('pair_index;dur=')
565
569
 
566
570
  // Asks are emitted lowest-tick first (best ask outward); bids are
567
571
  // emitted highest-tick first (best bid outward). Per-row `cumulativeSize`
@@ -689,9 +693,9 @@ describe('GET /exchange/swaps', () => {
689
693
  const response = await client.v1.exchange.swaps.$get({ query: { limit: '10' } }, TestApp.auth)
690
694
  expect(response.status).toBe(200)
691
695
  const body = await TestApp.json(response, Exchanges.schema.getSwaps.Response)
696
+ expect(body.data.length).toBeGreaterThan(0)
692
697
  expect(body.data.length).toBeLessThanOrEqual(10)
693
698
  expect(response.headers.get('server-timing')).not.toContain('valuation_rates;dur=')
694
- if (body.data.length === 0) return
695
699
 
696
700
  for (const swap of body.data) {
697
701
  expect(swap.taker).toMatch(/^0x[0-9a-f]{40}$/)
@@ -827,6 +831,7 @@ describe('GET /exchange/swaps', () => {
827
831
  TestApp.auth,
828
832
  )
829
833
  expect(response.status).toBe(200)
834
+ expect(response.headers.get('server-timing')).not.toContain('token_logo_uri;dur=')
830
835
  const body = await TestApp.json(response, Exchanges.schema.getSwaps.Response)
831
836
  if (body.data.length === 0) return
832
837