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
@@ -45,7 +45,7 @@ const providers = [
45
45
  integratorId: '0xdead',
46
46
  userAddress: '0x1111111111111111111111111111111111111111',
47
47
  }),
48
- Relay.relay({ userAddress: '0x1111111111111111111111111111111111111111' }),
48
+ Relay.relay({ userAddresses: TestFunding.relayQuoteUsers }),
49
49
  Rhino.rhino(),
50
50
  Squid.squid({
51
51
  integratorId: 'squid-integrator-id',
@@ -966,6 +966,67 @@ describe.skipIf(!relayApiKey)('POST /funding/deposit-addresses (relay)', () => {
966
966
  })
967
967
  })
968
968
 
969
+ describe('GET /funding/deposit-addresses', () => {
970
+ test('pages organization addresses and narrows project-attributed keys', async () => {
971
+ const app = transfersApp()
972
+ const first = await seedDepositAddress({ orgId: fundingAddressListReader.orgId })
973
+ const second = await seedDepositAddress({ orgId: fundingAddressListReader.orgId })
974
+ const third = await seedDepositAddress({ orgId: fundingAddressListReader.orgId })
975
+ const project = await seedDepositAddress({
976
+ orgId: fundingAddressListReader.orgId,
977
+ projectId: fundingAddressListProjectReader.projectId,
978
+ })
979
+ const sibling = await seedDepositAddress({
980
+ orgId: fundingAddressListReader.orgId,
981
+ projectId: 'prj_funding_address_list_sibling',
982
+ })
983
+ const sixth = await seedDepositAddress({ orgId: fundingAddressListReader.orgId })
984
+ await seedDepositAddress({ orgId: fundingForeign.orgId })
985
+ await seedDepositAddress({
986
+ environment: 'sandbox',
987
+ orgId: fundingAddressListReader.orgId,
988
+ })
989
+
990
+ const path = '/v1/funding/deposit-addresses'
991
+ expect((await app.request(path)).status).toBe(401)
992
+ expect((await app.request(path, as(TestApp.key))).status).toBe(403)
993
+
994
+ const response = await app.request(`${path}?limit=5`, as(fundingAddressListReader))
995
+ expect(response.status).toBe(200)
996
+ expect({
997
+ cacheControl: response.headers.get('cache-control'),
998
+ etag: response.headers.get('etag'),
999
+ vary: response.headers.get('vary'),
1000
+ }).toEqual({
1001
+ cacheControl: 'no-store',
1002
+ etag: null,
1003
+ vary: 'Accept-Encoding, Authorization, Tempo-API-Key, X-API-Key',
1004
+ })
1005
+ const body = await TestApp.json(response, Funding.schema.listFundingDepositAddresses.Response)
1006
+ expect(body.data.map((address) => address.id)).toEqual([
1007
+ sixth.id,
1008
+ sibling.id,
1009
+ project.id,
1010
+ third.id,
1011
+ second.id,
1012
+ ])
1013
+ expect(body.nextCursor).toBe(Cursor.encode([second.createdAt, second.id]))
1014
+
1015
+ const next = await TestApp.json(
1016
+ await app.request(`${path}?limit=5&cursor=${body.nextCursor}`, as(fundingAddressListReader)),
1017
+ Funding.schema.listFundingDepositAddresses.Response,
1018
+ )
1019
+ expect(next.data.map((address) => address.id)).toEqual([first.id])
1020
+ expect(next.nextCursor).toBeNull()
1021
+
1022
+ const projectBody = await TestApp.json(
1023
+ await app.request(path, as(fundingAddressListProjectReader)),
1024
+ Funding.schema.listFundingDepositAddresses.Response,
1025
+ )
1026
+ expect(projectBody.data.map((address) => address.id)).toEqual([project.id])
1027
+ })
1028
+ })
1029
+
969
1030
  describe('GET /funding/deposit-addresses/:id', () => {
970
1031
  test('requires funding:read and returns the owned address', async () => {
971
1032
  const app = transfersApp()
@@ -1329,6 +1390,63 @@ describe('GET /funding/deposits?depositAddress', () => {
1329
1390
  })
1330
1391
  })
1331
1392
 
1393
+ describe('GET /funding/deposits', () => {
1394
+ test('pages organization deposits and narrows project-attributed keys', async () => {
1395
+ const app = transfersApp()
1396
+ const firstAddress = await seedDepositAddress({ orgId: fundingDepositListReader.orgId })
1397
+ const secondAddress = await seedDepositAddress({ orgId: fundingDepositListReader.orgId })
1398
+ const thirdAddress = await seedDepositAddress({ orgId: fundingDepositListReader.orgId })
1399
+ const projectAddress = await seedDepositAddress({
1400
+ orgId: fundingDepositListReader.orgId,
1401
+ projectId: fundingDepositListProjectReader.projectId,
1402
+ })
1403
+ const siblingAddress = await seedDepositAddress({
1404
+ orgId: fundingDepositListReader.orgId,
1405
+ projectId: 'prj_funding_deposit_list_sibling',
1406
+ })
1407
+ const sixthAddress = await seedDepositAddress({ orgId: fundingDepositListReader.orgId })
1408
+ const first = await seedDeposit(firstAddress)
1409
+ const second = await seedDeposit(secondAddress)
1410
+ const third = await seedDeposit(thirdAddress)
1411
+ const project = await seedDeposit(projectAddress)
1412
+ const sibling = await seedDeposit(siblingAddress)
1413
+ const sixth = await seedDeposit(sixthAddress)
1414
+ const foreignAddress = await seedDepositAddress({ orgId: fundingForeign.orgId })
1415
+ await seedDeposit(foreignAddress)
1416
+ const sandboxAddress = await seedDepositAddress({
1417
+ environment: 'sandbox',
1418
+ orgId: fundingDepositListReader.orgId,
1419
+ })
1420
+ await seedDeposit(sandboxAddress)
1421
+
1422
+ const path = '/v1/funding/deposits'
1423
+ const response = await app.request(`${path}?limit=5`, as(fundingDepositListReader))
1424
+ expect(response.status).toBe(200)
1425
+ const body = await TestApp.json(response, Funding.schema.listFundingDeposits.Response)
1426
+ expect(body.data.map((deposit) => deposit.id)).toEqual([
1427
+ sixth.id,
1428
+ sibling.id,
1429
+ project.id,
1430
+ third.id,
1431
+ second.id,
1432
+ ])
1433
+ expect(body.nextCursor).toBe(Cursor.encode([second.createdAt, second.id]))
1434
+
1435
+ const next = await TestApp.json(
1436
+ await app.request(`${path}?limit=5&cursor=${body.nextCursor}`, as(fundingDepositListReader)),
1437
+ Funding.schema.listFundingDeposits.Response,
1438
+ )
1439
+ expect(next.data.map((deposit) => deposit.id)).toEqual([first.id])
1440
+ expect(next.nextCursor).toBeNull()
1441
+
1442
+ const projectBody = await TestApp.json(
1443
+ await app.request(path, as(fundingDepositListProjectReader)),
1444
+ Funding.schema.listFundingDeposits.Response,
1445
+ )
1446
+ expect(projectBody.data.map((deposit) => deposit.id)).toEqual([project.id])
1447
+ })
1448
+ })
1449
+
1332
1450
  describe('GET /funding/deposits?recipient', () => {
1333
1451
  test('requires funding:read and pages recipient deposits across addresses', async () => {
1334
1452
  const app = transfersApp()
@@ -1336,7 +1454,6 @@ describe('GET /funding/deposits?recipient', () => {
1336
1454
  const path = `/v1/funding/deposits?recipient=${recipient.toLowerCase()}`
1337
1455
  expect((await app.request(path)).status).toBe(401)
1338
1456
  expect((await app.request(path, as(TestApp.key))).status).toBe(403)
1339
- expect((await app.request('/v1/funding/deposits', as(fundingReader))).status).toBe(400)
1340
1457
  expect(
1341
1458
  (await app.request('/v1/funding/deposits?depositAddress=', as(fundingReader))).status,
1342
1459
  ).toBe(400)
@@ -1347,7 +1464,7 @@ describe('GET /funding/deposits?recipient', () => {
1347
1464
  as(fundingReader),
1348
1465
  )
1349
1466
  ).status,
1350
- ).toBe(400)
1467
+ ).toBe(200)
1351
1468
 
1352
1469
  const firstAddress = await seedDepositAddress({
1353
1470
  snapshot: TestFunding.depositAddressSnapshot({
@@ -1438,6 +1555,61 @@ describe('GET /funding/deposits?recipient', () => {
1438
1555
  })
1439
1556
  })
1440
1557
 
1558
+ describe('GET /funding/deposits?filters', () => {
1559
+ test('AND-combines canonical aliases and includes the matching count', async () => {
1560
+ const app = transfersApp()
1561
+ const snapshot = TestFunding.depositAddressSnapshot({
1562
+ address: 'TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE',
1563
+ })
1564
+ const address = await seedDepositAddress({
1565
+ orgId: fundingDepositFilterReader.orgId,
1566
+ snapshot,
1567
+ })
1568
+ const deposit = await seedDeposit(address)
1569
+ const unrelatedAddress = await seedDepositAddress({
1570
+ orgId: fundingDepositFilterReader.orgId,
1571
+ snapshot: TestFunding.depositAddressSnapshot({
1572
+ provider: { id: 'relay_unrelated', name: 'Relay' },
1573
+ recipient: `0x${'22'.repeat(20)}`,
1574
+ }),
1575
+ })
1576
+ await seedDeposit(unrelatedAddress)
1577
+ const query = new URLSearchParams({
1578
+ depositAddress: snapshot.address,
1579
+ destinationToken: 'usdt0',
1580
+ include: 'totalCount',
1581
+ provider: 'relay',
1582
+ recipient: snapshot.recipient.toLowerCase(),
1583
+ sourceChain: 'tron',
1584
+ sourceToken: 'usdt',
1585
+ status: 'detected',
1586
+ })
1587
+
1588
+ const body = await TestApp.json(
1589
+ await app.request(`/v1/funding/deposits?${query}`, as(fundingDepositFilterReader)),
1590
+ Funding.schema.listFundingDeposits.Response,
1591
+ )
1592
+ expect(body).toEqual({
1593
+ data: [FundingDeposit.toPublic(deposit)],
1594
+ meta: { totalCount: 1, totalCountCapped: false },
1595
+ nextCursor: null,
1596
+ })
1597
+
1598
+ const empty = await TestApp.json(
1599
+ await app.request(
1600
+ '/v1/funding/deposits?sourceToken=unknown&include=totalCount',
1601
+ as(fundingDepositFilterReader),
1602
+ ),
1603
+ Funding.schema.listFundingDeposits.Response,
1604
+ )
1605
+ expect(empty).toEqual({
1606
+ data: [],
1607
+ meta: { totalCount: 0, totalCountCapped: false },
1608
+ nextCursor: null,
1609
+ })
1610
+ })
1611
+ })
1612
+
1441
1613
  describe('GET /funding/deposits/:id', () => {
1442
1614
  test('returns the owned deposit without private reconciliation state', async () => {
1443
1615
  const app = transfersApp()
@@ -1544,6 +1716,43 @@ const fundingReader = {
1544
1716
  token: 'secret_funding_reader',
1545
1717
  } satisfies TestApp.kvStore.Key
1546
1718
 
1719
+ const fundingAddressListReader = {
1720
+ id: 'key_funding_address_list',
1721
+ orgId: 'org_funding_address_list',
1722
+ scopes: ['funding:read'],
1723
+ token: 'secret_funding_address_list',
1724
+ } satisfies TestApp.kvStore.Key
1725
+
1726
+ const fundingAddressListProjectReader = {
1727
+ id: 'key_funding_address_list_project',
1728
+ orgId: fundingAddressListReader.orgId,
1729
+ projectId: 'prj_funding_address_list',
1730
+ scopes: ['funding:read'],
1731
+ token: 'secret_funding_address_list_project',
1732
+ } satisfies TestApp.kvStore.Key
1733
+
1734
+ const fundingDepositListReader = {
1735
+ id: 'key_funding_deposit_list',
1736
+ orgId: 'org_funding_deposit_list',
1737
+ scopes: ['funding:read'],
1738
+ token: 'secret_funding_deposit_list',
1739
+ } satisfies TestApp.kvStore.Key
1740
+
1741
+ const fundingDepositFilterReader = {
1742
+ id: 'key_funding_deposit_filter',
1743
+ orgId: 'org_funding_deposit_filter',
1744
+ scopes: ['funding:read'],
1745
+ token: 'secret_funding_deposit_filter',
1746
+ } satisfies TestApp.kvStore.Key
1747
+
1748
+ const fundingDepositListProjectReader = {
1749
+ id: 'key_funding_deposit_list_project',
1750
+ orgId: fundingDepositListReader.orgId,
1751
+ projectId: 'prj_funding_deposit_list',
1752
+ scopes: ['funding:read'],
1753
+ token: 'secret_funding_deposit_list_project',
1754
+ } satisfies TestApp.kvStore.Key
1755
+
1547
1756
  const fundingProjectReader = {
1548
1757
  id: 'key_funding_project',
1549
1758
  orgId: 'org_funding',
@@ -1589,6 +1798,11 @@ function transfersApp(options: TestApp.create.Options = {}) {
1589
1798
  auth: {
1590
1799
  keys: [
1591
1800
  TestApp.key,
1801
+ fundingAddressListProjectReader,
1802
+ fundingAddressListReader,
1803
+ fundingDepositFilterReader,
1804
+ fundingDepositListProjectReader,
1805
+ fundingDepositListReader,
1592
1806
  fundingForeign,
1593
1807
  fundingForeignWriter,
1594
1808
  fundingProjectReader,
@@ -126,6 +126,27 @@ export namespace schema {
126
126
  export const Response = DepositAddress
127
127
  }
128
128
 
129
+ /** Schemas for the listFundingDepositAddresses operation. */
130
+ export namespace listFundingDepositAddresses {
131
+ /** Query parameters for listing funding deposit addresses. */
132
+ export const Query = z
133
+ .object({
134
+ cursor: Schema.Cursor,
135
+ limit: Schema.Limit,
136
+ })
137
+ .check(z.describe('Paging parameters for listing funding deposit addresses.'))
138
+
139
+ /** One page of reusable funding deposit addresses. */
140
+ export const Response = z
141
+ .object({
142
+ data: z
143
+ .array(DepositAddress)
144
+ .check(z.describe('Funding deposit addresses on this page, newest first.')),
145
+ nextCursor: Schema.NextCursor,
146
+ })
147
+ .check(z.describe('A page of reusable funding deposit addresses.'))
148
+ }
149
+
129
150
  /** Schemas for the reconcileFundingDepositAddress operation. */
130
151
  export namespace reconcileFundingDepositAddress {
131
152
  /** Path parameters for reconciling a funding deposit address. */
@@ -144,32 +165,49 @@ export namespace schema {
144
165
  z.meta({ examples: ['TJRabPrwbZy45sbavfcjinPJC18kjpRTv8'] }),
145
166
  ),
146
167
  cursor: Schema.Cursor,
168
+ destinationToken: z
169
+ .optional(z.string().check(z.minLength(1)))
170
+ .check(
171
+ z.describe('Destination token symbol, contract address, or token key.'),
172
+ z.meta({ examples: ['usdt0'] }),
173
+ ),
174
+ include: Schema.totalCountInclude,
147
175
  limit: Schema.Limit,
176
+ provider: z
177
+ .optional(z.string().check(z.minLength(1)))
178
+ .check(z.describe('Funding provider id.'), z.meta({ examples: ['relay'] })),
148
179
  recipient: z
149
180
  .optional(Schema.Address)
150
181
  .check(
151
182
  z.describe('Tempo account that received the deposits.'),
152
183
  z.meta({ examples: [`0x${'11'.repeat(20)}`] }),
153
184
  ),
185
+ sourceChain: z
186
+ .optional(z.string().check(z.minLength(1)))
187
+ .check(
188
+ z.describe('Source chain CAIP-2 id, slug, or alias.'),
189
+ z.meta({ examples: ['tron'] }),
190
+ ),
191
+ sourceToken: z
192
+ .optional(z.string().check(z.minLength(1)))
193
+ .check(
194
+ z.describe('Source token symbol, contract address, or token key.'),
195
+ z.meta({ examples: ['usdt'] }),
196
+ ),
197
+ status: z.optional(FundingDeposit.schema.Status),
154
198
  })
155
- .check(
156
- z.refine(
157
- (query) => (query.depositAddress === undefined) !== (query.recipient === undefined),
158
- {
159
- error: 'Pass exactly one of `depositAddress` or `recipient`.',
160
- path: ['depositAddress'],
161
- },
162
- ),
163
- z.describe('Exactly one deposit filter and optional paging parameters.'),
164
- )
199
+ .check(z.describe('Optional deposit filters and paging parameters.'))
165
200
 
166
201
  /** One page of detected deposits. */
167
202
  export const Response = z
168
203
  .object({
169
204
  data: z.array(Deposit).check(z.describe('Detected deposits on this page, newest first.')),
205
+ meta: z
206
+ .optional(Schema.CountMeta)
207
+ .check(z.describe('Extra response metadata requested with `include`.')),
170
208
  nextCursor: Schema.NextCursor,
171
209
  })
172
- .check(z.describe('A page of funding deposits matching the selected filter.'))
210
+ .check(z.describe('A page of visible funding deposits.'))
173
211
  }
174
212
 
175
213
  /** Schemas for the getFundingDeposit operation. */
@@ -276,9 +314,114 @@ const fundingDepositExample = {
276
314
 
277
315
  const fundingDepositsExample = {
278
316
  data: [fundingDepositExample],
317
+ meta: { totalCount: 1, totalCountCapped: false },
279
318
  nextCursor: null,
280
319
  } satisfies z.output<typeof schema.listFundingDeposits.Response>
281
320
 
321
+ const fundingDepositAddressesExample = {
322
+ data: [fundingDepositAddressExample],
323
+ nextCursor: null,
324
+ } satisfies z.output<typeof schema.listFundingDepositAddresses.Response>
325
+
326
+ function resolveDepositFilters(options: resolveDepositFilters.Options): FundingDeposits.Filters {
327
+ const { catalog, parameters } = options
328
+ return {
329
+ ...(parameters.depositAddress === undefined
330
+ ? {}
331
+ : { depositAddress: parameters.depositAddress }),
332
+ ...(parameters.destinationToken === undefined
333
+ ? {}
334
+ : {
335
+ destinationTokenKeys: resolveTokenKeys({
336
+ catalog,
337
+ input: parameters.destinationToken,
338
+ side: 'destination',
339
+ }),
340
+ }),
341
+ ...(parameters.provider === undefined
342
+ ? {}
343
+ : { providerId: parameters.provider.trim().toLowerCase() }),
344
+ ...(parameters.recipient === undefined ? {} : { recipient: parameters.recipient }),
345
+ ...(parameters.sourceChain === undefined
346
+ ? {}
347
+ : { sourceChainIds: resolveChainIds(catalog, parameters.sourceChain) }),
348
+ ...(parameters.sourceToken === undefined
349
+ ? {}
350
+ : {
351
+ sourceTokenKeys: resolveTokenKeys({
352
+ catalog,
353
+ input: parameters.sourceToken,
354
+ side: 'source',
355
+ }),
356
+ }),
357
+ ...(parameters.status === undefined ? {} : { status: parameters.status }),
358
+ }
359
+ }
360
+
361
+ declare namespace resolveDepositFilters {
362
+ type Options = {
363
+ catalog?: FundingCatalog.Snapshot | undefined
364
+ parameters: z.output<typeof schema.listFundingDeposits.Query>
365
+ }
366
+ }
367
+
368
+ function resolveChainIds(catalog: FundingCatalog.Snapshot | undefined, input: string): string[] {
369
+ const trimmed = input.trim()
370
+ const chain = catalog?.chainsByKey.get(trimmed.toLowerCase())
371
+ if (chain) return [chain.id]
372
+ return /^[a-z][a-z0-9-]*:.+$/i.test(trimmed) ? [trimmed] : []
373
+ }
374
+
375
+ function resolveTokenKeys(options: resolveTokenKeys.Options): string[] {
376
+ const trimmed = options.input.trim()
377
+ const normalized = trimmed.toLowerCase()
378
+ const keys =
379
+ options.catalog?.routes
380
+ .map((entry) => entry.route[options.side])
381
+ .filter((token) => matchesToken(token, trimmed, normalized))
382
+ .map(tokenKey) ?? []
383
+ if (keys.length) return [...new Set(keys)]
384
+ if (!/^[a-z][a-z0-9-]*:.+\/(?:erc20|trc20|token):.+$/i.test(trimmed)) return []
385
+ return [/\/erc20:/i.test(trimmed) ? normalized : trimmed]
386
+ }
387
+
388
+ declare namespace resolveTokenKeys {
389
+ type Options = {
390
+ catalog?: FundingCatalog.Snapshot | undefined
391
+ input: string
392
+ side: 'destination' | 'source'
393
+ }
394
+ }
395
+
396
+ type ResolvedToken = FundingCatalog.Snapshot['routes'][number]['route']['source']
397
+
398
+ function matchesToken(token: ResolvedToken, trimmed: string, normalized: string): boolean {
399
+ return (
400
+ token.slug === normalized ||
401
+ token.symbol.toLowerCase() === normalized ||
402
+ matchesTokenIdentifier(token, token.address, trimmed, normalized) ||
403
+ matchesTokenIdentifier(token, tokenKey(token), trimmed, normalized)
404
+ )
405
+ }
406
+
407
+ function matchesTokenIdentifier(
408
+ token: ResolvedToken,
409
+ candidate: string,
410
+ trimmed: string,
411
+ normalized: string,
412
+ ): boolean {
413
+ return token.chain.kind === 'evm' ? candidate.toLowerCase() === normalized : candidate === trimmed
414
+ }
415
+
416
+ function tokenKey(token: ResolvedToken): string {
417
+ const namespace = (() => {
418
+ if (token.chain.kind === 'solana') return 'token'
419
+ if (token.chain.kind === 'tron') return 'trc20'
420
+ return 'erc20'
421
+ })()
422
+ return `${token.chain.id}/${namespace}:${token.address}`
423
+ }
424
+
282
425
  const reconcileFundingDepositAddressResponses = (() => {
283
426
  const responses = OpenApi.responses({
284
427
  errors: {
@@ -646,6 +789,72 @@ export function depositAddresses(options: depositAddresses.Options = {}) {
646
789
  }
647
790
  },
648
791
  )
792
+ .get(
793
+ '/v1/funding/deposit-addresses',
794
+ Auth.policy({ apiKey: { scopes: ['funding:read'] } }),
795
+ OpenApi.validate('query', schema.listFundingDepositAddresses.Query, {
796
+ code: 'query_invalid',
797
+ message: 'Check the query parameters and try again.',
798
+ }),
799
+ OpenApi.describeRoute({
800
+ description: 'Lists reusable funding deposit addresses, newest first.',
801
+ operationId: 'listFundingDepositAddresses',
802
+ responses: OpenApi.responses({
803
+ errors: {
804
+ 400: { codes: ['query_invalid'] },
805
+ },
806
+ success: {
807
+ description: 'A page of reusable funding deposit addresses.',
808
+ example: fundingDepositAddressesExample,
809
+ schema: schema.listFundingDepositAddresses.Response,
810
+ },
811
+ }),
812
+ summary: 'List deposit addresses',
813
+ tags: ['Deposit Addresses'],
814
+ }),
815
+ async (c) => {
816
+ if (Auth.narrowAccess) return Auth.accessError(c)
817
+ if (OpenApi.narrowValidation)
818
+ return OpenApi.validationError(c, {
819
+ code: 'query_invalid',
820
+ message: 'Check the query parameters and try again.',
821
+ })
822
+
823
+ const owner = Access.owner(c)
824
+ if (!owner) return Access.unauthorized(c)
825
+
826
+ const db = Db.get(c.get('db'))
827
+ const { cursor, limit } = c.req.valid('query')
828
+ const decoded = cursor ? Cursor.decode(cursor, ['timestamp', 'id']) : undefined
829
+ try {
830
+ const rows = await FundingDepositAddresses.list(db, {
831
+ ...(decoded
832
+ ? { cursor: { createdAt: String(decoded[0]), id: String(decoded[1]) } }
833
+ : {}),
834
+ limit: limit + 1,
835
+ owner,
836
+ })
837
+ const page = Cursor.paginate({
838
+ key: (record) => [record.createdAt, record.id],
839
+ limit,
840
+ rows,
841
+ })
842
+ const data = page.rows.map(FundingDepositAddress.toPublic)
843
+
844
+ c.header('Cache-Control', Cache.policies.noStore)
845
+ c.header('Vary', 'Accept-Encoding, Authorization, Tempo-API-Key, X-API-Key')
846
+ return c.json(
847
+ Response.validated(schema.listFundingDepositAddresses.Response, {
848
+ data,
849
+ nextCursor: page.nextCursor,
850
+ }),
851
+ 200,
852
+ )
853
+ } catch (cause) {
854
+ return Response.upstream(c, cause)
855
+ }
856
+ },
857
+ )
649
858
  .get(
650
859
  '/v1/funding/deposit-addresses/:id{fda_[A-Za-z0-9_-]+}',
651
860
  Auth.policy({ apiKey: { scopes: ['funding:read'] } }),
@@ -712,7 +921,7 @@ export function depositAddresses(options: depositAddresses.Options = {}) {
712
921
  .post(
713
922
  '/v1/funding/deposit-addresses/:id{fda_[A-Za-z0-9_-]+}/reconcile',
714
923
  Auth.policy({
715
- apiKey: { rateLimit: { perMinute: 10 }, scopes: ['funding:write'] },
924
+ apiKey: { rateLimit: { limit: 10, period: 'minute' }, scopes: ['funding:write'] },
716
925
  }),
717
926
  OpenApi.validate('param', schema.reconcileFundingDepositAddress.Params, {
718
927
  code: 'param_invalid',
@@ -782,14 +991,14 @@ export function depositAddresses(options: depositAddresses.Options = {}) {
782
991
  message: 'Check the query parameters and try again.',
783
992
  }),
784
993
  OpenApi.describeRoute({
785
- description: 'Lists deposits by deposit address or Tempo recipient, newest first.',
994
+ description: 'Lists visible deposits, optionally filtered, newest first.',
786
995
  operationId: 'listFundingDeposits',
787
996
  responses: OpenApi.responses({
788
997
  errors: {
789
998
  400: { codes: ['query_invalid'] },
790
999
  },
791
1000
  success: {
792
- description: 'A page of funding deposits matching the selected filter.',
1001
+ description: 'A page of visible funding deposits.',
793
1002
  example: fundingDepositsExample,
794
1003
  schema: schema.listFundingDeposits.Response,
795
1004
  },
@@ -809,32 +1018,59 @@ export function depositAddresses(options: depositAddresses.Options = {}) {
809
1018
  if (!owner) return Access.unauthorized(c)
810
1019
 
811
1020
  const db = Db.get(c.get('db'))
812
- const { cursor, depositAddress, limit, recipient } = c.req.valid('query')
1021
+ const parameters = c.req.valid('query')
1022
+ const { cursor, include, limit } = parameters
813
1023
  const decoded = cursor ? Cursor.decode(cursor, ['timestamp', 'id']) : undefined
814
1024
  try {
1025
+ const catalog =
1026
+ parameters.destinationToken !== undefined ||
1027
+ parameters.sourceChain !== undefined ||
1028
+ parameters.sourceToken !== undefined
1029
+ ? await FundingCatalog.snapshot(c)
1030
+ : undefined
1031
+ const filters = resolveDepositFilters({ catalog, parameters })
1032
+ // Counts are best-effort and share every ownership and filter predicate
1033
+ // with the page query. A failure omits `meta` rather than failing the page.
1034
+ const countPromise = include.includes('totalCount')
1035
+ ? FundingDeposits.count(db, {
1036
+ ...filters,
1037
+ cap: Schema.countCap,
1038
+ owner,
1039
+ }).catch(() => {
1040
+ c.set('fundingDepositCountFailed', true)
1041
+ return undefined
1042
+ })
1043
+ : undefined
815
1044
  const paging = {
1045
+ ...filters,
816
1046
  ...(decoded
817
1047
  ? { cursor: { createdAt: String(decoded[0]), id: String(decoded[1]) } }
818
1048
  : {}),
819
1049
  limit: limit + 1,
820
1050
  owner,
821
1051
  }
822
- const rows =
823
- depositAddress === undefined
824
- ? await FundingDeposits.listByRecipient(db, { ...paging, recipient: recipient! })
825
- : await FundingDeposits.listByDepositAddress(db, { ...paging, depositAddress })
1052
+ const rows = await FundingDeposits.list(db, paging)
826
1053
  const page = Cursor.paginate({
827
1054
  key: (record) => [record.createdAt, record.id],
828
1055
  limit,
829
1056
  rows,
830
1057
  })
831
1058
  const data = page.rows.map(FundingDeposit.toPublic)
1059
+ const count = await countPromise
832
1060
 
833
1061
  c.header('Cache-Control', Cache.policies.noStore)
834
1062
  c.header('Vary', 'Accept-Encoding, Authorization, Tempo-API-Key')
835
1063
  return c.json(
836
1064
  Response.validated(schema.listFundingDeposits.Response, {
837
1065
  data,
1066
+ ...(count === undefined
1067
+ ? {}
1068
+ : {
1069
+ meta: {
1070
+ totalCount: Math.min(count, Schema.countCap),
1071
+ totalCountCapped: count > Schema.countCap,
1072
+ },
1073
+ }),
838
1074
  nextCursor: page.nextCursor,
839
1075
  }),
840
1076
  200,
@@ -28,7 +28,7 @@ const providers = [
28
28
  integratorId: '0xdead',
29
29
  userAddress: '0x1111111111111111111111111111111111111111',
30
30
  }),
31
- Relay.relay({ userAddress: '0x1111111111111111111111111111111111111111' }),
31
+ Relay.relay({ userAddresses: TestFunding.relayQuoteUsers }),
32
32
  Rhino.rhino(),
33
33
  Squid.squid({
34
34
  integratorId: 'squid-integrator-id',
@@ -28,7 +28,7 @@ const providers = [
28
28
  integratorId: '0xdead',
29
29
  userAddress: '0x1111111111111111111111111111111111111111',
30
30
  }),
31
- Relay.relay({ userAddress: '0x1111111111111111111111111111111111111111' }),
31
+ Relay.relay({ userAddresses: TestFunding.relayQuoteUsers }),
32
32
  Rhino.rhino(),
33
33
  Squid.squid({
34
34
  integratorId: 'squid-integrator-id',