tapimo 0.5.2 → 0.6.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 (299) hide show
  1. package/dist/App.d.ts +13987 -5755
  2. package/dist/App.d.ts.map +1 -1
  3. package/dist/App.js.map +1 -1
  4. package/dist/admin/App.d.ts +910 -412
  5. package/dist/admin/App.d.ts.map +1 -1
  6. package/dist/admin/App.js +4 -0
  7. package/dist/admin/App.js.map +1 -1
  8. package/dist/admin/apps/early-access.d.ts +148 -0
  9. package/dist/admin/apps/early-access.d.ts.map +1 -0
  10. package/dist/admin/apps/early-access.js +133 -0
  11. package/dist/admin/apps/early-access.js.map +1 -0
  12. package/dist/admin/apps/verified-tokens.d.ts +643 -118
  13. package/dist/admin/apps/verified-tokens.d.ts.map +1 -1
  14. package/dist/admin/apps/verified-tokens.js +214 -1
  15. package/dist/admin/apps/verified-tokens.js.map +1 -1
  16. package/dist/admin/ui.generated.d.ts +1 -1
  17. package/dist/admin/ui.generated.d.ts.map +1 -1
  18. package/dist/admin/ui.generated.js +45 -33
  19. package/dist/admin/ui.generated.js.map +1 -1
  20. package/dist/apps/data/App.d.ts +3733 -2428
  21. package/dist/apps/data/App.d.ts.map +1 -1
  22. package/dist/apps/data/App.js +11 -6
  23. package/dist/apps/data/App.js.map +1 -1
  24. package/dist/apps/data/FundingQuoteProviders.d.ts +34 -1
  25. package/dist/apps/data/FundingQuoteProviders.d.ts.map +1 -1
  26. package/dist/apps/data/FundingQuoteProviders.js +193 -2
  27. package/dist/apps/data/FundingQuoteProviders.js.map +1 -1
  28. package/dist/apps/data/FxOracle.d.ts +71 -0
  29. package/dist/apps/data/FxOracle.d.ts.map +1 -0
  30. package/dist/apps/data/FxOracle.js +97 -0
  31. package/dist/apps/data/FxOracle.js.map +1 -0
  32. package/dist/apps/data/index.d.ts +1 -0
  33. package/dist/apps/data/index.d.ts.map +1 -1
  34. package/dist/apps/data/index.js +1 -0
  35. package/dist/apps/data/index.js.map +1 -1
  36. package/dist/apps/data/routes/activities.d.ts +3575 -1358
  37. package/dist/apps/data/routes/activities.d.ts.map +1 -1
  38. package/dist/apps/data/routes/activities.js +230 -88
  39. package/dist/apps/data/routes/activities.js.map +1 -1
  40. package/dist/apps/data/routes/addresses.d.ts +963 -342
  41. package/dist/apps/data/routes/addresses.d.ts.map +1 -1
  42. package/dist/apps/data/routes/addresses.js +11 -9
  43. package/dist/apps/data/routes/addresses.js.map +1 -1
  44. package/dist/apps/data/routes/balances.d.ts +108 -57
  45. package/dist/apps/data/routes/balances.d.ts.map +1 -1
  46. package/dist/apps/data/routes/balances.js +88 -45
  47. package/dist/apps/data/routes/balances.js.map +1 -1
  48. package/dist/apps/data/routes/coingecko.d.ts +169 -169
  49. package/dist/apps/data/routes/exchanges.d.ts +952 -201
  50. package/dist/apps/data/routes/exchanges.d.ts.map +1 -1
  51. package/dist/apps/data/routes/exchanges.js +518 -76
  52. package/dist/apps/data/routes/exchanges.js.map +1 -1
  53. package/dist/apps/data/routes/fee-amm.d.ts +24 -24
  54. package/dist/apps/data/routes/funding.d.ts +8 -2
  55. package/dist/apps/data/routes/funding.d.ts.map +1 -1
  56. package/dist/apps/data/routes/funding.js +32 -6
  57. package/dist/apps/data/routes/funding.js.map +1 -1
  58. package/dist/apps/data/routes/indexer.d.ts +5 -5
  59. package/dist/apps/data/routes/receipts.d.ts +392 -315
  60. package/dist/apps/data/routes/receipts.d.ts.map +1 -1
  61. package/dist/apps/data/routes/receipts.js +152 -77
  62. package/dist/apps/data/routes/receipts.js.map +1 -1
  63. package/dist/apps/data/routes/tokens.d.ts +166 -173
  64. package/dist/apps/data/routes/tokens.d.ts.map +1 -1
  65. package/dist/apps/data/routes/tokens.js +14 -12
  66. package/dist/apps/data/routes/tokens.js.map +1 -1
  67. package/dist/apps/data/routes/transactions.d.ts +277 -536
  68. package/dist/apps/data/routes/transactions.d.ts.map +1 -1
  69. package/dist/apps/data/routes/transactions.js +96 -77
  70. package/dist/apps/data/routes/transactions.js.map +1 -1
  71. package/dist/apps/data/routes/transfers.d.ts +82 -17
  72. package/dist/apps/data/routes/transfers.d.ts.map +1 -1
  73. package/dist/apps/data/routes/transfers.js +70 -13
  74. package/dist/apps/data/routes/transfers.js.map +1 -1
  75. package/dist/apps/data/routes/valuation.d.ts +307 -0
  76. package/dist/apps/data/routes/valuation.d.ts.map +1 -0
  77. package/dist/apps/data/routes/valuation.js +292 -0
  78. package/dist/apps/data/routes/valuation.js.map +1 -0
  79. package/dist/apps/data/routes/verified-tokens.d.ts.map +1 -1
  80. package/dist/apps/data/routes/verified-tokens.js +7 -5
  81. package/dist/apps/data/routes/verified-tokens.js.map +1 -1
  82. package/dist/apps/data/routes/webhooks.d.ts +459 -479
  83. package/dist/apps/data/routes/webhooks.d.ts.map +1 -1
  84. package/dist/apps/data/routes/webhooks.js +124 -25
  85. package/dist/apps/data/routes/webhooks.js.map +1 -1
  86. package/dist/apps/index.d.ts +1 -1
  87. package/dist/apps/index.d.ts.map +1 -1
  88. package/dist/apps/index.js +1 -1
  89. package/dist/apps/index.js.map +1 -1
  90. package/dist/apps/management/App.d.ts +8606 -1681
  91. package/dist/apps/management/App.d.ts.map +1 -1
  92. package/dist/apps/management/App.js +12 -1
  93. package/dist/apps/management/App.js.map +1 -1
  94. package/dist/apps/management/routes/api-keys.d.ts +23 -0
  95. package/dist/apps/management/routes/api-keys.d.ts.map +1 -1
  96. package/dist/apps/management/routes/api-keys.js +5 -3
  97. package/dist/apps/management/routes/api-keys.js.map +1 -1
  98. package/dist/apps/management/routes/billing.d.ts +88 -48
  99. package/dist/apps/management/routes/billing.d.ts.map +1 -1
  100. package/dist/apps/management/routes/billing.js +10 -2
  101. package/dist/apps/management/routes/billing.js.map +1 -1
  102. package/dist/apps/management/routes/faucet.d.ts +218 -0
  103. package/dist/apps/management/routes/faucet.d.ts.map +1 -0
  104. package/dist/apps/management/routes/faucet.js +139 -0
  105. package/dist/apps/management/routes/faucet.js.map +1 -0
  106. package/dist/apps/management/routes/invitations.d.ts +121 -121
  107. package/dist/apps/management/routes/invitations.d.ts.map +1 -1
  108. package/dist/apps/management/routes/invitations.js +3 -0
  109. package/dist/apps/management/routes/invitations.js.map +1 -1
  110. package/dist/apps/management/routes/invite-links.d.ts +197 -168
  111. package/dist/apps/management/routes/invite-links.d.ts.map +1 -1
  112. package/dist/apps/management/routes/invite-links.js +26 -1
  113. package/dist/apps/management/routes/invite-links.js.map +1 -1
  114. package/dist/apps/management/routes/me.d.ts +2 -0
  115. package/dist/apps/management/routes/me.d.ts.map +1 -1
  116. package/dist/apps/management/routes/me.js +4 -0
  117. package/dist/apps/management/routes/me.js.map +1 -1
  118. package/dist/apps/management/routes/members.d.ts +49 -49
  119. package/dist/apps/management/routes/orgs.d.ts +91 -91
  120. package/dist/apps/management/routes/projects.d.ts +115 -115
  121. package/dist/apps/management/routes/usage.d.ts +35 -32
  122. package/dist/apps/management/routes/usage.d.ts.map +1 -1
  123. package/dist/apps/management/routes/usage.js +4 -0
  124. package/dist/apps/management/routes/usage.js.map +1 -1
  125. package/dist/apps/management/routes/verified-token-requests.d.ts +697 -0
  126. package/dist/apps/management/routes/verified-token-requests.d.ts.map +1 -0
  127. package/dist/apps/management/routes/verified-token-requests.js +271 -0
  128. package/dist/apps/management/routes/verified-token-requests.js.map +1 -0
  129. package/dist/apps/management/routes/webhooks.d.ts +6977 -0
  130. package/dist/apps/management/routes/webhooks.d.ts.map +1 -0
  131. package/dist/apps/management/routes/webhooks.js +573 -0
  132. package/dist/apps/management/routes/webhooks.js.map +1 -0
  133. package/dist/apps/mcp.d.ts +9 -2
  134. package/dist/apps/mcp.d.ts.map +1 -1
  135. package/dist/apps/mcp.js +9 -4
  136. package/dist/apps/mcp.js.map +1 -1
  137. package/dist/cli/Cli.d.ts.map +1 -1
  138. package/dist/cli/Cli.js +7 -2
  139. package/dist/cli/Cli.js.map +1 -1
  140. package/dist/db/Db.d.ts +4 -0
  141. package/dist/db/Db.d.ts.map +1 -1
  142. package/dist/db/Db.js +83 -0
  143. package/dist/db/Db.js.map +1 -1
  144. package/dist/db/Schema.d.ts +41 -0
  145. package/dist/db/Schema.d.ts.map +1 -1
  146. package/dist/db/Schema.js +45 -0
  147. package/dist/db/Schema.js.map +1 -1
  148. package/dist/db/tables/earlyAccess.d.ts +50 -0
  149. package/dist/db/tables/earlyAccess.d.ts.map +1 -0
  150. package/dist/db/tables/earlyAccess.js +63 -0
  151. package/dist/db/tables/earlyAccess.js.map +1 -0
  152. package/dist/db/tables/invitations.d.ts +12 -1
  153. package/dist/db/tables/invitations.d.ts.map +1 -1
  154. package/dist/db/tables/invitations.js +23 -0
  155. package/dist/db/tables/invitations.js.map +1 -1
  156. package/dist/db/tables/inviteLinks.d.ts +10 -2
  157. package/dist/db/tables/inviteLinks.d.ts.map +1 -1
  158. package/dist/db/tables/inviteLinks.js +10 -1
  159. package/dist/db/tables/inviteLinks.js.map +1 -1
  160. package/dist/db/tables/sponsoredTransactions.d.ts +2 -0
  161. package/dist/db/tables/sponsoredTransactions.d.ts.map +1 -1
  162. package/dist/db/tables/sponsoredTransactions.js +2 -0
  163. package/dist/db/tables/sponsoredTransactions.js.map +1 -1
  164. package/dist/db/tables/verifiedTokenRequests.d.ts +94 -0
  165. package/dist/db/tables/verifiedTokenRequests.d.ts.map +1 -0
  166. package/dist/db/tables/verifiedTokenRequests.js +120 -0
  167. package/dist/db/tables/verifiedTokenRequests.js.map +1 -0
  168. package/dist/db/tables/webhookSubscriptions.d.ts +14 -0
  169. package/dist/db/tables/webhookSubscriptions.d.ts.map +1 -1
  170. package/dist/db/tables/webhookSubscriptions.js +16 -0
  171. package/dist/db/tables/webhookSubscriptions.js.map +1 -1
  172. package/dist/internal/Auth.d.ts +43 -2
  173. package/dist/internal/Auth.d.ts.map +1 -1
  174. package/dist/internal/Auth.js +60 -45
  175. package/dist/internal/Auth.js.map +1 -1
  176. package/dist/internal/FundingQuotes.d.ts +69 -15
  177. package/dist/internal/FundingQuotes.d.ts.map +1 -1
  178. package/dist/internal/FundingQuotes.js +74 -25
  179. package/dist/internal/FundingQuotes.js.map +1 -1
  180. package/dist/internal/Log.d.ts +19 -1
  181. package/dist/internal/Log.d.ts.map +1 -1
  182. package/dist/internal/Log.js +2 -0
  183. package/dist/internal/Log.js.map +1 -1
  184. package/dist/internal/MetricSink.d.ts.map +1 -1
  185. package/dist/internal/MetricSink.js +9 -0
  186. package/dist/internal/MetricSink.js.map +1 -1
  187. package/dist/internal/OpenApi.d.ts +2 -2
  188. package/dist/internal/OpenApi.d.ts.map +1 -1
  189. package/dist/internal/OpenApi.js +3 -0
  190. package/dist/internal/OpenApi.js.map +1 -1
  191. package/dist/internal/Schema.d.ts +14 -5
  192. package/dist/internal/Schema.d.ts.map +1 -1
  193. package/dist/internal/Schema.js +23 -5
  194. package/dist/internal/Schema.js.map +1 -1
  195. package/dist/internal/Value.d.ts +18 -0
  196. package/dist/internal/Value.d.ts.map +1 -1
  197. package/dist/internal/Value.js +11 -1
  198. package/dist/internal/Value.js.map +1 -1
  199. package/dist/internal/VerifiedTokens.d.ts.map +1 -1
  200. package/dist/internal/VerifiedTokens.js +10 -1
  201. package/dist/internal/VerifiedTokens.js.map +1 -1
  202. package/dist/internal/Viem.d.ts +1 -1
  203. package/dist/internal/Webhooks.d.ts +24 -3
  204. package/dist/internal/Webhooks.d.ts.map +1 -1
  205. package/dist/internal/Webhooks.js +34 -8
  206. package/dist/internal/Webhooks.js.map +1 -1
  207. package/package.json +2 -2
  208. package/src/App.ts +9 -1
  209. package/src/Client.test-d.ts +638 -6
  210. package/src/admin/App.ts +4 -0
  211. package/src/admin/apps/early-access.test.ts +125 -0
  212. package/src/admin/apps/early-access.ts +175 -0
  213. package/src/admin/apps/verified-tokens.test.ts +201 -0
  214. package/src/admin/apps/verified-tokens.ts +532 -286
  215. package/src/admin/ui/plugin.ts +2 -1
  216. package/src/admin/ui/src/lib/early-access.ts +63 -0
  217. package/src/admin/ui/src/lib/verified-tokens.ts +79 -0
  218. package/src/admin/ui/src/routeTree.gen.ts +33 -2
  219. package/src/admin/ui/src/routes/__root.tsx +2 -1
  220. package/src/admin/ui/src/routes/early-access.tsx +157 -0
  221. package/src/admin/ui/src/routes/verified-tokens.tsx +230 -19
  222. package/src/admin/ui.generated.ts +48 -33
  223. package/src/apps/data/App.ts +22 -14
  224. package/src/apps/data/FundingQuoteProviders.test.ts +298 -0
  225. package/src/apps/data/FundingQuoteProviders.ts +257 -4
  226. package/src/apps/data/FxOracle.test.ts +118 -0
  227. package/src/apps/data/FxOracle.ts +153 -0
  228. package/src/apps/data/index.ts +1 -0
  229. package/src/apps/data/routes/activities.test.ts +173 -3
  230. package/src/apps/data/routes/activities.ts +403 -132
  231. package/src/apps/data/routes/addresses.ts +19 -9
  232. package/src/apps/data/routes/balances.test.ts +144 -11
  233. package/src/apps/data/routes/balances.ts +140 -51
  234. package/src/apps/data/routes/exchanges.test.ts +540 -9
  235. package/src/apps/data/routes/exchanges.ts +690 -103
  236. package/src/apps/data/routes/funding.test.ts +84 -0
  237. package/src/apps/data/routes/funding.ts +38 -6
  238. package/src/apps/data/routes/receipts.test.ts +125 -23
  239. package/src/apps/data/routes/receipts.ts +205 -100
  240. package/src/apps/data/routes/tokens.test.ts +43 -0
  241. package/src/apps/data/routes/tokens.ts +27 -12
  242. package/src/apps/data/routes/transactions.test.ts +72 -19
  243. package/src/apps/data/routes/transactions.ts +162 -92
  244. package/src/apps/data/routes/transfers.test.ts +146 -4
  245. package/src/apps/data/routes/transfers.ts +91 -13
  246. package/src/apps/data/routes/valuation.test.ts +422 -0
  247. package/src/apps/data/routes/valuation.ts +423 -0
  248. package/src/apps/data/routes/verified-tokens.ts +14 -2
  249. package/src/apps/data/routes/webhooks.test.ts +56 -8
  250. package/src/apps/data/routes/webhooks.ts +144 -27
  251. package/src/apps/index.ts +1 -1
  252. package/src/apps/management/App.ts +13 -0
  253. package/src/apps/management/routes/api-keys.test.ts +87 -0
  254. package/src/apps/management/routes/api-keys.ts +4 -3
  255. package/src/apps/management/routes/billing.test.ts +112 -1
  256. package/src/apps/management/routes/billing.ts +7 -2
  257. package/src/apps/management/routes/faucet.test.ts +79 -0
  258. package/src/apps/management/routes/faucet.ts +185 -0
  259. package/src/apps/management/routes/invitations.test.ts +172 -0
  260. package/src/apps/management/routes/invitations.ts +3 -0
  261. package/src/apps/management/routes/invite-links.test.ts +117 -0
  262. package/src/apps/management/routes/invite-links.ts +43 -1
  263. package/src/apps/management/routes/me.test.ts +140 -88
  264. package/src/apps/management/routes/me.ts +6 -0
  265. package/src/apps/management/routes/usage.test.ts +6 -0
  266. package/src/apps/management/routes/usage.ts +7 -0
  267. package/src/apps/management/routes/verified-token-requests.test.ts +377 -0
  268. package/src/apps/management/routes/verified-token-requests.ts +397 -0
  269. package/src/apps/management/routes/webhooks.test.ts +426 -0
  270. package/src/apps/management/routes/webhooks.ts +672 -0
  271. package/src/apps/mcp.test.ts +13 -0
  272. package/src/apps/mcp.ts +18 -5
  273. package/src/cli/Cli.test.ts +36 -0
  274. package/src/cli/Cli.ts +7 -2
  275. package/src/db/Db.test.ts +19 -0
  276. package/src/db/Db.ts +95 -0
  277. package/src/db/Schema.ts +53 -0
  278. package/src/db/tables/earlyAccess.ts +86 -0
  279. package/src/db/tables/invitations.ts +26 -1
  280. package/src/db/tables/inviteLinks.ts +22 -3
  281. package/src/db/tables/sponsoredTransactions.ts +4 -0
  282. package/src/db/tables/verifiedTokenRequests.test.ts +200 -0
  283. package/src/db/tables/verifiedTokenRequests.ts +182 -0
  284. package/src/db/tables/webhookSubscriptions.ts +31 -0
  285. package/src/internal/Auth.ts +73 -45
  286. package/src/internal/FundingQuotes.test.ts +143 -1
  287. package/src/internal/FundingQuotes.ts +95 -28
  288. package/src/internal/Log.test-d.ts +21 -0
  289. package/src/internal/Log.test.ts +50 -0
  290. package/src/internal/Log.ts +24 -1
  291. package/src/internal/MetricSink.test.ts +160 -0
  292. package/src/internal/MetricSink.ts +10 -0
  293. package/src/internal/OpenApi.ts +3 -0
  294. package/src/internal/Schema.ts +50 -5
  295. package/src/internal/Value.test.ts +20 -0
  296. package/src/internal/Value.ts +24 -1
  297. package/src/internal/VerifiedTokens.ts +9 -1
  298. package/src/internal/Webhooks.test.ts +140 -0
  299. package/src/internal/Webhooks.ts +53 -9
@@ -1,12 +1,20 @@
1
- import { Address, Hex } from 'ox'
1
+ import { Address, Hex, Value as core_Value } from 'ox'
2
+ import { FxOracle } from 'tapimo/apps'
2
3
  import { encodeAbiParameters, encodeEventTopics } from 'viem'
3
4
  import { Abis } from 'viem/tempo'
4
5
 
5
6
  import * as TestApp from '../../../../test/App.js'
6
7
  import * as Runtime from '../../../../test/runtime.js'
8
+ import * as Cursor from '../../../internal/Cursor.js'
7
9
  import * as Store from '../../../internal/Store.js'
8
10
  import * as Activities from './activities.js'
9
11
 
12
+ // Deterministic EUR-based rate set so conversion math is exact in assertions.
13
+ const fixed = FxOracle.from({
14
+ name: 'fixed',
15
+ rates: async () => ({ asOf: '2026-01-01', base: 'EUR', rates: { AUD: '1.6', USD: '1.0' } }),
16
+ })
17
+
10
18
  /**
11
19
  * Real Tempo (Moderato) accounts, each exercising specific activity types.
12
20
  * Discovered by scanning indexed `logs` for the event each type classifies
@@ -102,6 +110,32 @@ function find(items: readonly Activities.Entry[], type: string): Activities.Entr
102
110
  }
103
111
 
104
112
  describe('GET /addresses/:address/activities', () => {
113
+ test('parses granular token includes for both activity endpoints', () => {
114
+ expect(
115
+ Activities.schema.getAddressActivities.Query.parse({
116
+ include: 'token.logoUri,token.verified',
117
+ }).include,
118
+ ).toMatchInlineSnapshot(`
119
+ [
120
+ "token.logoUri",
121
+ "token.verified",
122
+ ]
123
+ `)
124
+ expect(
125
+ Activities.schema.getTransactionActivities.Query.parse({
126
+ include: 'token.logoUri,token.verified',
127
+ }).include,
128
+ ).toMatchInlineSnapshot(`
129
+ [
130
+ "token.logoUri",
131
+ "token.verified",
132
+ ]
133
+ `)
134
+ expect(
135
+ Activities.schema.getAddressActivities.Query.safeParse({ include: 'token' }).success,
136
+ ).toBe(false)
137
+ })
138
+
105
139
  test('returns a newest-first, schema-valid feed with timing', async () => {
106
140
  const response = await request(accounts.keychain, { limit: '10' })
107
141
  expect(response.status).toBe(200)
@@ -130,7 +164,31 @@ describe('GET /addresses/:address/activities', () => {
130
164
  expect(transfer.data.transactionHash).toMatch(/^0x[0-9a-f]{64}$/)
131
165
  expect(typeof transfer.data.blockNumber).toBe('number')
132
166
  expect(transfer.data.sourceToken.address).toMatch(/^0x[0-9a-f]{40}$/)
133
- expect(transfer.data.sourceToken.amount).toMatch(/^\d+$/)
167
+ expect(transfer.data.sourceToken).not.toHaveProperty('amount')
168
+ expect(typeof transfer.data.sourceToken.currency).toBe('string')
169
+ expect(typeof transfer.data.sourceToken.decimals).toBe('number')
170
+ expect(typeof transfer.data.sourceToken.name).toBe('string')
171
+ expect(typeof transfer.data.sourceToken.symbol).toBe('string')
172
+ expect(transfer.data.sourceAmount.baseUnits).toMatch(/^\d+$/)
173
+ expect(transfer.data.sourceAmount.currency).toBe(transfer.data.sourceToken.currency)
174
+ expect(transfer.data.sourceAmount.decimals).toBe(transfer.data.sourceToken.decimals)
175
+ expect(transfer.data.sourceAmount.formatted).toMatch(/^\d+(\.\d+)?$/)
176
+ expect(transfer.data.sourceToken.logoUri).toBeUndefined()
177
+ expect(transfer.data.sourceToken.verified).toBeUndefined()
178
+ })
179
+
180
+ test('includes requested token verification', async () => {
181
+ const transfer = find(
182
+ (
183
+ await activities(accounts.creator, {
184
+ include: 'token.logoUri,token.verified',
185
+ })
186
+ ).data,
187
+ 'transfer',
188
+ )
189
+ expect(transfer?.type).toBe('transfer')
190
+ if (transfer?.type !== 'transfer') return
191
+ expect(typeof transfer.data.sourceToken.verified).toBe('boolean')
134
192
  })
135
193
 
136
194
  test.skipIf(runtime.mode === 'localnet')('swap data carries both sides of the swap', async () => {
@@ -139,8 +197,30 @@ describe('GET /addresses/:address/activities', () => {
139
197
  if (swap?.type !== 'swap') return
140
198
  expect(swap.data.sourceToken.address).toMatch(/^0x[0-9a-f]{40}$/)
141
199
  expect(swap.data.destinationToken.address).toMatch(/^0x[0-9a-f]{40}$/)
200
+ expect(swap.data.sourceToken).not.toHaveProperty('amount')
201
+ expect(swap.data.destinationToken).not.toHaveProperty('amount')
202
+ expect(swap.data.sourceAmount.baseUnits).toMatch(/^\d+$/)
203
+ expect(swap.data.destinationAmount.baseUnits).toMatch(/^\d+$/)
142
204
  })
143
205
 
206
+ test.skipIf(runtime.mode === 'localnet')(
207
+ 'adds a structured refund amount when a session closes with a refund',
208
+ async () => {
209
+ const session = find((await activities(accounts.channel)).data, 'session-closed')
210
+ expect(session?.type).toBe('session-closed')
211
+ if (session?.type !== 'session-closed') return
212
+ if (!session.data.refund) {
213
+ expect(session.data.refundAmount).toBeUndefined()
214
+ return
215
+ }
216
+ expect(session.data.refundAmount).toBeDefined()
217
+ expect(session.data.refund).not.toHaveProperty('amount')
218
+ expect(session.data.refundAmount?.baseUnits).toMatch(/^\d+$/)
219
+ expect(session.data.refundAmount?.currency).toBe(session.data.refund.currency)
220
+ expect(session.data.refundAmount?.decimals).toBe(session.data.refund.decimals)
221
+ },
222
+ )
223
+
144
224
  test.skipIf(runtime.mode !== 'localnet')(
145
225
  'surfaces a cross-token transfer as outgoing in the sender feed',
146
226
  async () => {
@@ -162,6 +242,10 @@ describe('GET /addresses/:address/activities', () => {
162
242
  expect(transfer.data.recipient).toBe(crossToken.recipient)
163
243
  expect(transfer.data.sourceToken.address).toBe(crossToken.sourceToken)
164
244
  expect(transfer.data.destinationToken?.address).toBe(crossToken.destinationToken)
245
+ expect(transfer.data.sourceToken).not.toHaveProperty('amount')
246
+ expect(transfer.data.destinationToken).not.toHaveProperty('amount')
247
+ expect(transfer.data.sourceAmount.baseUnits).toMatch(/^\d+$/)
248
+ expect(transfer.data.destinationAmount?.baseUnits).toMatch(/^\d+$/)
165
249
  },
166
250
  )
167
251
 
@@ -202,6 +286,39 @@ describe('GET /addresses/:address/activities', () => {
202
286
  },
203
287
  )
204
288
 
289
+ test.skipIf(runtime.mode !== 'localnet')('values curated activity amounts', async () => {
290
+ const db = TestApp.database()
291
+ await TestApp.verifiedSeed(db, runtime.chainId)
292
+ const client = TestApp.client({ db, fx: { oracle: fixed } })
293
+ const hash = runtime.fixtures!.faucetTransactionHashes[0]!
294
+
295
+ const response = await client.v1.transactions[':transactionHash'].activities.$get(
296
+ { param: { transactionHash: hash }, query: { denomination: 'AUD' } },
297
+ TestApp.auth,
298
+ )
299
+ const body = await TestApp.json(response, Activities.schema.getTransactionActivities.Response)
300
+ expect(response.status).toBe(200)
301
+
302
+ // The faucet transaction moves curated USD tokens; their amounts value at
303
+ // the fixed 1.6 USD -> AUD rate.
304
+ const amounts = body.data.flatMap((item) =>
305
+ item.type === 'transfer' || item.type === 'mint' ? [item.data.sourceAmount] : [],
306
+ )
307
+ expect(amounts.length).toBeGreaterThan(0)
308
+ for (const amount of amounts)
309
+ expect(amount.valuation).toEqual({
310
+ amount: core_Value.format((BigInt(amount.baseUnits) * 16n) / 10n, 6),
311
+ currency: 'AUD',
312
+ })
313
+ expect(body.meta?.pricing).toMatchInlineSnapshot(`
314
+ {
315
+ "asOf": "2026-01-01",
316
+ "basis": "nominal",
317
+ "source": "fixed",
318
+ }
319
+ `)
320
+ })
321
+
205
322
  test('returns every item at the root by default (no group entries)', async () => {
206
323
  const body = await activities(accounts.channel)
207
324
  expect(body.data.every((entry) => entry.type !== 'group')).toBe(true)
@@ -210,9 +327,34 @@ describe('GET /addresses/:address/activities', () => {
210
327
  test('paginates with an opaque cursor', async () => {
211
328
  const first = await activities(accounts.keychain, { limit: '5' })
212
329
  if (!first.nextCursor) return
213
- const second = await activities(accounts.keychain, { limit: '5', cursor: first.nextCursor })
330
+ const response = await request(accounts.keychain, { limit: '5', cursor: first.nextCursor })
331
+ expect(response.headers.get('cache-control')).toMatchInlineSnapshot(
332
+ `"private, max-age=60, stale-while-revalidate=300"`,
333
+ )
334
+ const second = await TestApp.json(response, Activities.schema.getAddressActivities.Response)
214
335
  expect(Array.isArray(second.data)).toBe(true)
215
336
  })
337
+
338
+ test('validates denominations on empty feeds', async () => {
339
+ const client = TestApp.client({ fx: { oracle: fixed } })
340
+ const cursor = Cursor.encode([0, 0])
341
+ const emptyResponse = await client.v1.addresses[':address'].activities.$get(
342
+ { param: { address: accounts.keychain }, query: { cursor, limit: '5' } },
343
+ TestApp.auth,
344
+ )
345
+ const empty = await TestApp.json(emptyResponse, Activities.schema.getAddressActivities.Response)
346
+ expect(emptyResponse.status).toBe(200)
347
+ expect(empty.data).toMatchInlineSnapshot(`[]`)
348
+
349
+ const response = await client.v1.addresses[':address'].activities.$get(
350
+ {
351
+ param: { address: accounts.keychain },
352
+ query: { cursor, denomination: 'JPY', limit: '5' },
353
+ },
354
+ TestApp.auth,
355
+ )
356
+ expect(response.status).toBe(400)
357
+ })
216
358
  })
217
359
 
218
360
  /** Resolves a real transaction hash from an address's (non-grouped) activity feed. */
@@ -239,6 +381,9 @@ describe('GET /transactions/:transactionHash/activities', () => {
239
381
 
240
382
  const response = await transactionActivitiesRequest(transactionHash)
241
383
  expect(response.status).toBe(200)
384
+ expect(response.headers.get('cache-control')).toMatchInlineSnapshot(
385
+ `"private, max-age=60, stale-while-revalidate=300"`,
386
+ )
242
387
  expect(response.headers.get('server-timing')?.includes('transaction_activities;dur=')).toBe(
243
388
  true,
244
389
  )
@@ -262,6 +407,27 @@ describe('GET /transactions/:transactionHash/activities', () => {
262
407
  )
263
408
  })
264
409
 
410
+ test('supports requested token verification', async () => {
411
+ const address = await activities(accounts.creator)
412
+ const entry = address.data.find((item) => item.type !== 'group' && 'sourceToken' in item.data)
413
+ expect(entry?.type).not.toBe('group')
414
+ if (!entry || entry.type === 'group') return
415
+
416
+ const body = await TestApp.json(
417
+ await transactionActivitiesRequest(entry.transactionHash, {
418
+ include: 'token.verified',
419
+ }),
420
+ Activities.schema.getTransactionActivities.Response,
421
+ )
422
+ const item = body.data.find((item) => 'sourceToken' in item.data)
423
+ expect(item).toBeDefined()
424
+ if (!item || !('sourceToken' in item.data) || !item.data.sourceToken || !item.data.sourceAmount)
425
+ return
426
+ expect(typeof item.data.sourceToken.verified).toBe('boolean')
427
+ expect(item.data.sourceToken).not.toHaveProperty('amount')
428
+ expect(item.data.sourceAmount.baseUnits).toMatch(/^\d+$/)
429
+ })
430
+
265
431
  test.skipIf(runtime.mode !== 'localnet')(
266
432
  'classifies a seeded cross-token transfer with both source and destination tokens',
267
433
  async () => {
@@ -283,6 +449,10 @@ describe('GET /transactions/:transactionHash/activities', () => {
283
449
  expect(transfer.data.recipient).toBe(crossToken.recipient)
284
450
  expect(transfer.data.sourceToken.address).toBe(crossToken.sourceToken)
285
451
  expect(transfer.data.destinationToken?.address).toBe(crossToken.destinationToken)
452
+ expect(transfer.data.sourceToken).not.toHaveProperty('amount')
453
+ expect(transfer.data.destinationToken).not.toHaveProperty('amount')
454
+ expect(transfer.data.sourceAmount.baseUnits).toMatch(/^\d+$/)
455
+ expect(transfer.data.destinationAmount?.baseUnits).toMatch(/^\d+$/)
286
456
  },
287
457
  )
288
458