tapimo 0.7.2 → 0.8.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 (294) hide show
  1. package/README.md +10 -7
  2. package/dist/ApiKey.d.ts +3 -0
  3. package/dist/ApiKey.d.ts.map +1 -1
  4. package/dist/ApiKey.js +10 -0
  5. package/dist/ApiKey.js.map +1 -1
  6. package/dist/ApiKeys.d.ts +7 -3
  7. package/dist/ApiKeys.d.ts.map +1 -1
  8. package/dist/ApiKeys.js +9 -2
  9. package/dist/ApiKeys.js.map +1 -1
  10. package/dist/App.d.ts +20434 -19484
  11. package/dist/App.d.ts.map +1 -1
  12. package/dist/App.js +62 -4
  13. package/dist/App.js.map +1 -1
  14. package/dist/admin/App.d.ts +84 -74
  15. package/dist/admin/App.d.ts.map +1 -1
  16. package/dist/admin/apps/api-keys.d.ts +14 -1
  17. package/dist/admin/apps/api-keys.d.ts.map +1 -1
  18. package/dist/admin/apps/api-keys.js +6 -2
  19. package/dist/admin/apps/api-keys.js.map +1 -1
  20. package/dist/admin/apps/organizations.d.ts +2 -0
  21. package/dist/admin/apps/organizations.d.ts.map +1 -1
  22. package/dist/admin/apps/verified-tokens.d.ts +168 -168
  23. package/dist/admin/ui.generated.d.ts +1 -1
  24. package/dist/admin/ui.generated.js +67 -67
  25. package/dist/admin/ui.generated.js.map +1 -1
  26. package/dist/analytics/Analytics.d.ts +2 -0
  27. package/dist/analytics/Analytics.d.ts.map +1 -1
  28. package/dist/analytics/Analytics.js +3 -0
  29. package/dist/analytics/Analytics.js.map +1 -1
  30. package/dist/apps/data/App.d.ts +10305 -12785
  31. package/dist/apps/data/App.d.ts.map +1 -1
  32. package/dist/apps/data/App.js +4 -8
  33. package/dist/apps/data/App.js.map +1 -1
  34. package/dist/apps/data/routes/activities.d.ts +24 -24
  35. package/dist/apps/data/routes/addresses.d.ts +288 -288
  36. package/dist/apps/data/routes/balances.d.ts +6 -6
  37. package/dist/apps/data/routes/blocks.d.ts +39 -39
  38. package/dist/apps/data/routes/coingecko.d.ts +170 -170
  39. package/dist/apps/data/routes/earn.d.ts +436 -6
  40. package/dist/apps/data/routes/earn.d.ts.map +1 -1
  41. package/dist/apps/data/routes/earn.js +631 -4
  42. package/dist/apps/data/routes/earn.js.map +1 -1
  43. package/dist/apps/data/routes/exchanges.d.ts +10 -10
  44. package/dist/apps/data/routes/fee-amm.d.ts +2 -2
  45. package/dist/apps/data/routes/indexer.d.ts +6 -6
  46. package/dist/apps/data/routes/indexer.js +4 -1
  47. package/dist/apps/data/routes/indexer.js.map +1 -1
  48. package/dist/apps/data/routes/receipts.d.ts +235 -235
  49. package/dist/apps/data/routes/rpc.d.ts +1 -1
  50. package/dist/apps/data/routes/rpc.js +4 -1
  51. package/dist/apps/data/routes/rpc.js.map +1 -1
  52. package/dist/apps/data/routes/tokenlist.d.ts +36 -36
  53. package/dist/apps/data/routes/tokens.d.ts +6 -6
  54. package/dist/apps/data/routes/transactions.d.ts +2 -2
  55. package/dist/apps/data/routes/transfers.d.ts +1 -1
  56. package/dist/apps/data/routes/valuation.d.ts +1 -1
  57. package/dist/apps/data/routes/verified-tokens.d.ts +36 -36
  58. package/dist/apps/data/routes/webhooks.d.ts +9 -9
  59. package/dist/apps/data/routes/zones.d.ts +14 -14
  60. package/dist/apps/funding/Access.d.ts +16 -0
  61. package/dist/apps/funding/Access.d.ts.map +1 -0
  62. package/dist/apps/funding/Access.js +22 -0
  63. package/dist/apps/funding/Access.js.map +1 -0
  64. package/dist/apps/{data/routes/funding.d.ts → funding/App.d.ts} +1717 -3035
  65. package/dist/apps/funding/App.d.ts.map +1 -0
  66. package/dist/apps/funding/App.js +46 -0
  67. package/dist/apps/funding/App.js.map +1 -0
  68. package/dist/apps/funding/Inventory.d.ts +5 -0
  69. package/dist/apps/funding/Inventory.d.ts.map +1 -0
  70. package/dist/apps/funding/Inventory.js +25 -0
  71. package/dist/apps/funding/Inventory.js.map +1 -0
  72. package/dist/apps/funding/ProviderAttempts.d.ts +5 -0
  73. package/dist/apps/funding/ProviderAttempts.d.ts.map +1 -0
  74. package/dist/apps/funding/ProviderAttempts.js +24 -0
  75. package/dist/apps/funding/ProviderAttempts.js.map +1 -0
  76. package/dist/apps/funding/index.d.ts +2 -0
  77. package/dist/apps/funding/index.d.ts.map +1 -0
  78. package/dist/apps/funding/index.js +2 -0
  79. package/dist/apps/funding/index.js.map +1 -0
  80. package/dist/apps/funding/routes/chains.d.ts +169 -0
  81. package/dist/apps/funding/routes/chains.d.ts.map +1 -0
  82. package/dist/apps/funding/routes/chains.js +80 -0
  83. package/dist/apps/funding/routes/chains.js.map +1 -0
  84. package/dist/apps/funding/routes/deposit-addresses.d.ts +2388 -0
  85. package/dist/apps/funding/routes/deposit-addresses.d.ts.map +1 -0
  86. package/dist/apps/funding/routes/deposit-addresses.js +860 -0
  87. package/dist/apps/funding/routes/deposit-addresses.js.map +1 -0
  88. package/dist/apps/funding/routes/providers.d.ts +91 -0
  89. package/dist/apps/funding/routes/providers.d.ts.map +1 -0
  90. package/dist/apps/funding/routes/providers.js +56 -0
  91. package/dist/apps/funding/routes/providers.js.map +1 -0
  92. package/dist/apps/funding/routes/quotes.d.ts +426 -0
  93. package/dist/apps/funding/routes/quotes.d.ts.map +1 -0
  94. package/dist/apps/funding/routes/quotes.js +188 -0
  95. package/dist/apps/funding/routes/quotes.js.map +1 -0
  96. package/dist/apps/funding/routes/transfers.d.ts +1999 -0
  97. package/dist/apps/funding/routes/transfers.d.ts.map +1 -0
  98. package/dist/apps/funding/routes/transfers.js +614 -0
  99. package/dist/apps/funding/routes/transfers.js.map +1 -0
  100. package/dist/apps/index.d.ts +1 -0
  101. package/dist/apps/index.d.ts.map +1 -1
  102. package/dist/apps/index.js +1 -0
  103. package/dist/apps/index.js.map +1 -1
  104. package/dist/apps/management/App.d.ts +430 -165
  105. package/dist/apps/management/App.d.ts.map +1 -1
  106. package/dist/apps/management/routes/api-keys.d.ts +298 -21
  107. package/dist/apps/management/routes/api-keys.d.ts.map +1 -1
  108. package/dist/apps/management/routes/api-keys.js +75 -1
  109. package/dist/apps/management/routes/api-keys.js.map +1 -1
  110. package/dist/apps/management/routes/billing.d.ts +6 -6
  111. package/dist/apps/management/routes/faucet.d.ts +35 -35
  112. package/dist/apps/management/routes/invitations.d.ts +48 -48
  113. package/dist/apps/management/routes/invite-links.d.ts +38 -38
  114. package/dist/apps/management/routes/members.d.ts +69 -69
  115. package/dist/apps/management/routes/orgs.d.ts +37 -37
  116. package/dist/apps/management/routes/projects.d.ts +25 -25
  117. package/dist/apps/management/routes/scopes.d.ts +1 -1
  118. package/dist/apps/management/routes/usage.d.ts +72 -72
  119. package/dist/apps/management/routes/verified-token-requests.d.ts +18 -18
  120. package/dist/apps/management/routes/webhooks.d.ts +128 -128
  121. package/dist/apps/mcp.d.ts +2 -3
  122. package/dist/apps/mcp.d.ts.map +1 -1
  123. package/dist/apps/mcp.js +16 -14
  124. package/dist/apps/mcp.js.map +1 -1
  125. package/dist/apps/metadata.d.ts +4 -0
  126. package/dist/apps/metadata.d.ts.map +1 -1
  127. package/dist/apps/metadata.js +10 -0
  128. package/dist/apps/metadata.js.map +1 -1
  129. package/dist/apps/mpp/App.d.ts +2 -2
  130. package/dist/cloudflare.d.ts +50 -0
  131. package/dist/cloudflare.d.ts.map +1 -1
  132. package/dist/cloudflare.js +178 -0
  133. package/dist/cloudflare.js.map +1 -1
  134. package/dist/db/Db.d.ts +2 -0
  135. package/dist/db/Db.d.ts.map +1 -1
  136. package/dist/db/Db.js +37 -0
  137. package/dist/db/Db.js.map +1 -1
  138. package/dist/db/Schema.d.ts +12 -0
  139. package/dist/db/Schema.d.ts.map +1 -1
  140. package/dist/db/Schema.js +20 -0
  141. package/dist/db/Schema.js.map +1 -1
  142. package/dist/db/tables/fundingDepositAddresses.d.ts +13 -0
  143. package/dist/db/tables/fundingDepositAddresses.d.ts.map +1 -1
  144. package/dist/db/tables/fundingDepositAddresses.js +12 -0
  145. package/dist/db/tables/fundingDepositAddresses.js.map +1 -1
  146. package/dist/db/tables/fundingDepositRequestObservations.d.ts +45 -0
  147. package/dist/db/tables/fundingDepositRequestObservations.d.ts.map +1 -0
  148. package/dist/db/tables/fundingDepositRequestObservations.js +46 -0
  149. package/dist/db/tables/fundingDepositRequestObservations.js.map +1 -0
  150. package/dist/db/tables/fundingDeposits.d.ts +57 -1
  151. package/dist/db/tables/fundingDeposits.d.ts.map +1 -1
  152. package/dist/db/tables/fundingDeposits.js +82 -0
  153. package/dist/db/tables/fundingDeposits.js.map +1 -1
  154. package/dist/internal/Auth.d.ts +11 -11
  155. package/dist/internal/Auth.d.ts.map +1 -1
  156. package/dist/internal/Auth.js +41 -15
  157. package/dist/internal/Auth.js.map +1 -1
  158. package/dist/internal/Cache.js +1 -1
  159. package/dist/internal/Cache.js.map +1 -1
  160. package/dist/internal/EdgeCache.d.ts +2 -2
  161. package/dist/internal/EdgeCache.d.ts.map +1 -1
  162. package/dist/internal/EdgeCache.js +10 -4
  163. package/dist/internal/EdgeCache.js.map +1 -1
  164. package/dist/internal/IpAllowlist.d.ts +15 -0
  165. package/dist/internal/IpAllowlist.d.ts.map +1 -0
  166. package/dist/internal/IpAllowlist.js +27 -0
  167. package/dist/internal/IpAllowlist.js.map +1 -0
  168. package/dist/internal/OpenApi.d.ts +1 -1
  169. package/dist/internal/OpenApi.js +1 -1
  170. package/dist/internal/OpenApi.js.map +1 -1
  171. package/dist/internal/Tidx.d.ts +6 -0
  172. package/dist/internal/Tidx.d.ts.map +1 -1
  173. package/dist/internal/Tidx.js +13 -3
  174. package/dist/internal/Tidx.js.map +1 -1
  175. package/dist/internal/Viem.d.ts +8 -0
  176. package/dist/internal/Viem.d.ts.map +1 -1
  177. package/dist/internal/Viem.js +12 -5
  178. package/dist/internal/Viem.js.map +1 -1
  179. package/dist/internal/funding/Deposit.d.ts +42 -0
  180. package/dist/internal/funding/Deposit.d.ts.map +1 -1
  181. package/dist/internal/funding/Deposit.js +37 -5
  182. package/dist/internal/funding/Deposit.js.map +1 -1
  183. package/dist/internal/funding/Evidence.d.ts +1 -5
  184. package/dist/internal/funding/Evidence.d.ts.map +1 -1
  185. package/dist/internal/funding/Evidence.js +4 -3
  186. package/dist/internal/funding/Evidence.js.map +1 -1
  187. package/dist/internal/funding/Provider.d.ts +102 -0
  188. package/dist/internal/funding/Provider.d.ts.map +1 -1
  189. package/dist/internal/funding/Provider.js +5 -0
  190. package/dist/internal/funding/Provider.js.map +1 -1
  191. package/dist/internal/funding/Reconciliation.d.ts +16 -2
  192. package/dist/internal/funding/Reconciliation.d.ts.map +1 -1
  193. package/dist/internal/funding/Reconciliation.js +257 -48
  194. package/dist/internal/funding/Reconciliation.js.map +1 -1
  195. package/dist/internal/funding/SourceObservation.d.ts +108 -0
  196. package/dist/internal/funding/SourceObservation.d.ts.map +1 -0
  197. package/dist/internal/funding/SourceObservation.js +143 -0
  198. package/dist/internal/funding/SourceObservation.js.map +1 -0
  199. package/dist/internal/funding/Subsidy.d.ts +2 -2
  200. package/dist/internal/funding/Subsidy.d.ts.map +1 -1
  201. package/dist/internal/funding/Subsidy.js +1 -1
  202. package/dist/internal/funding/Subsidy.js.map +1 -1
  203. package/dist/internal/funding/index.d.ts +1 -0
  204. package/dist/internal/funding/index.d.ts.map +1 -1
  205. package/dist/internal/funding/index.js +1 -0
  206. package/dist/internal/funding/index.js.map +1 -1
  207. package/dist/internal/funding/providers/relay.d.ts +43 -1
  208. package/dist/internal/funding/providers/relay.d.ts.map +1 -1
  209. package/dist/internal/funding/providers/relay.js +434 -27
  210. package/dist/internal/funding/providers/relay.js.map +1 -1
  211. package/package.json +3 -3
  212. package/src/ApiKey.test.ts +35 -0
  213. package/src/ApiKey.ts +27 -0
  214. package/src/ApiKeys.test.ts +29 -0
  215. package/src/ApiKeys.ts +11 -3
  216. package/src/App.test.ts +23 -5
  217. package/src/App.ts +76 -5
  218. package/src/Client.test-d.ts +171 -19
  219. package/src/admin/apps/api-keys.test.ts +25 -1
  220. package/src/admin/apps/api-keys.ts +6 -2
  221. package/src/admin/ui.generated.ts +67 -67
  222. package/src/analytics/Analytics.ts +4 -0
  223. package/src/apps/composition.test.ts +100 -2
  224. package/src/apps/data/App.test.ts +0 -12
  225. package/src/apps/data/App.ts +4 -8
  226. package/src/apps/data/routes/earn.test.ts +283 -0
  227. package/src/apps/data/routes/earn.ts +800 -3
  228. package/src/apps/data/routes/indexer.ts +2 -1
  229. package/src/apps/data/routes/rpc.ts +2 -0
  230. package/src/apps/data/routes/tokens.test.ts +6 -8
  231. package/src/apps/funding/Access.ts +26 -0
  232. package/src/apps/funding/App.test.ts +78 -0
  233. package/src/apps/funding/App.ts +63 -0
  234. package/src/apps/funding/Inventory.ts +30 -0
  235. package/src/apps/funding/ProviderAttempts.ts +26 -0
  236. package/src/apps/funding/index.ts +1 -0
  237. package/src/apps/funding/routes/chains.test.ts +78 -0
  238. package/src/apps/funding/routes/chains.ts +101 -0
  239. package/src/apps/funding/routes/deposit-addresses.test.ts +1628 -0
  240. package/src/apps/funding/routes/deposit-addresses.ts +1015 -0
  241. package/src/apps/funding/routes/providers.test.ts +165 -0
  242. package/src/apps/funding/routes/providers.ts +73 -0
  243. package/src/apps/funding/routes/quotes.test.ts +511 -0
  244. package/src/apps/funding/routes/quotes.ts +205 -0
  245. package/src/apps/funding/routes/transfers.test.ts +1255 -0
  246. package/src/apps/funding/routes/transfers.ts +704 -0
  247. package/src/apps/index.ts +1 -0
  248. package/src/apps/management/routes/api-keys.test.ts +98 -0
  249. package/src/apps/management/routes/api-keys.ts +96 -1
  250. package/src/apps/mcp.test.ts +17 -2
  251. package/src/apps/mcp.ts +18 -13
  252. package/src/apps/metadata.ts +12 -0
  253. package/src/apps/mpp/internal/Policy.test.ts +7 -1
  254. package/src/cloudflare.ts +279 -0
  255. package/src/db/Db.ts +62 -0
  256. package/src/db/Schema.ts +24 -0
  257. package/src/db/tables/fundingDepositAddresses.ts +28 -0
  258. package/src/db/tables/fundingDepositRequestObservations.test.ts +106 -0
  259. package/src/db/tables/fundingDepositRequestObservations.ts +99 -0
  260. package/src/db/tables/fundingDeposits.test.ts +138 -0
  261. package/src/db/tables/fundingDeposits.ts +145 -1
  262. package/src/internal/Auth.test.ts +177 -5
  263. package/src/internal/Auth.ts +48 -18
  264. package/src/internal/Cache.test.ts +37 -3
  265. package/src/internal/Cache.ts +1 -1
  266. package/src/internal/EdgeCache.test.ts +7 -7
  267. package/src/internal/EdgeCache.ts +13 -4
  268. package/src/internal/IpAllowlist.test.ts +52 -0
  269. package/src/internal/IpAllowlist.ts +39 -0
  270. package/src/internal/Log.test.ts +7 -1
  271. package/src/internal/OpenApi.ts +1 -1
  272. package/src/internal/Tidx.test.ts +28 -0
  273. package/src/internal/Tidx.ts +19 -3
  274. package/src/internal/Viem.test.ts +28 -0
  275. package/src/internal/Viem.ts +21 -5
  276. package/src/internal/funding/Deposit.ts +74 -5
  277. package/src/internal/funding/Evidence.test.ts +2 -2
  278. package/src/internal/funding/Evidence.ts +4 -9
  279. package/src/internal/funding/Provider.ts +115 -0
  280. package/src/internal/funding/Reconciliation.local.test.ts +7 -0
  281. package/src/internal/funding/Reconciliation.test.ts +1052 -35
  282. package/src/internal/funding/Reconciliation.ts +328 -56
  283. package/src/internal/funding/SourceObservation.test.ts +301 -0
  284. package/src/internal/funding/SourceObservation.ts +267 -0
  285. package/src/internal/funding/Subsidy.ts +2 -2
  286. package/src/internal/funding/index.test.ts +1 -0
  287. package/src/internal/funding/index.ts +1 -0
  288. package/src/internal/funding/providers/relay.test.ts +94 -4
  289. package/src/internal/funding/providers/relay.ts +528 -27
  290. package/dist/apps/data/routes/funding.d.ts.map +0 -1
  291. package/dist/apps/data/routes/funding.js +0 -1557
  292. package/dist/apps/data/routes/funding.js.map +0 -1
  293. package/src/apps/data/routes/funding.test.ts +0 -2994
  294. package/src/apps/data/routes/funding.ts +0 -1821
@@ -11,7 +11,10 @@ import type * as EarnRates from './internal/EarnRates.js'
11
11
  import * as Exchanges from './apps/data/routes/exchanges.js'
12
12
  import * as Faucet from './apps/management/routes/faucet.js'
13
13
  import * as FeeAmm from './apps/data/routes/fee-amm.js'
14
- import * as Funding from './apps/data/routes/funding.js'
14
+ import * as FundingChains from './apps/funding/routes/chains.js'
15
+ import * as FundingDepositAddresses from './apps/funding/routes/deposit-addresses.js'
16
+ import * as FundingQuotes from './apps/funding/routes/quotes.js'
17
+ import * as FundingTransfers from './apps/funding/routes/transfers.js'
15
18
  import type * as FundingDepositAddress from './internal/funding/DepositAddress.js'
16
19
  import * as Indexer from './apps/data/routes/indexer.js'
17
20
  import * as InviteLinks from './apps/management/routes/invite-links.js'
@@ -141,7 +144,7 @@ describe('narrows responses by status', () => {
141
144
  }
142
145
  case 403: {
143
146
  const json = await res.json()
144
- expectTypeOf(json.error.code).toEqualTypeOf<'api_key_forbidden'>()
147
+ expectTypeOf(json.error.code).toEqualTypeOf<'api_key_forbidden' | 'api_key_ip_forbidden'>()
145
148
  expectTypeOf(json.error.message).toEqualTypeOf<string>()
146
149
  void json
147
150
  return
@@ -357,6 +360,59 @@ describe('narrows responses by status', () => {
357
360
  }
358
361
  })
359
362
 
363
+ test('GET /v1/earn/vaults/:vaultId/earnings/:address', async () => {
364
+ const client = Client.create()
365
+ const res = await client.v1.earn.vaults[':vaultId'].earnings[':address'].$get({
366
+ param: {
367
+ address: `0x${'bb'.repeat(20)}`,
368
+ vaultId: `0x${'aa'.repeat(20)}`,
369
+ },
370
+ })
371
+
372
+ expectTypeOf(res.status).toEqualTypeOf<200 | 400 | 404 | 502 | PaidAccessStatus>()
373
+
374
+ if (res.status === 200) {
375
+ const json = await res.json()
376
+ expectTypeOf(json).toEqualTypeOf<z.output<typeof Earn.schema.getEarnVaultEarnings.Response>>()
377
+ expectTypeOf(json.account).toEqualTypeOf<`0x${string}`>()
378
+ expectTypeOf(json.assetToken).toEqualTypeOf<`0x${string}`>()
379
+ expectTypeOf(json.currentValue).toEqualTypeOf<string>()
380
+ expectTypeOf(json.id).toEqualTypeOf<`0x${string}`>()
381
+ expectTypeOf(json.period).toEqualTypeOf<'active' | 'lifetime'>()
382
+ expectTypeOf(json.status).toEqualTypeOf<
383
+ 'complete' | 'incomplete_cost_basis' | 'pending_redemption'
384
+ >()
385
+ if (json.status === 'complete' && json.period === 'active')
386
+ expectTypeOf(json.activeEarnings).toEqualTypeOf<string>()
387
+ if (json.status === 'complete' && json.period === 'lifetime')
388
+ expectTypeOf(json.lifetimeEarnings).toEqualTypeOf<string>()
389
+ void json
390
+ return
391
+ }
392
+ if (res.status === 400) {
393
+ const json = await res.json()
394
+ expectTypeOf(json.error.code).toEqualTypeOf<
395
+ Access400<
396
+ 'chain_id_invalid' | 'chain_id_unsupported' | 'earnings_invalid' | 'query_invalid'
397
+ >
398
+ >()
399
+ void json
400
+ return
401
+ }
402
+ if (res.status === 404) {
403
+ const json = await res.json()
404
+ expectTypeOf(json.error.code).toEqualTypeOf<'earn_vault_not_found'>()
405
+ void json
406
+ return
407
+ }
408
+ if (res.status === 502) {
409
+ const json = await res.json()
410
+ expectTypeOf(json.error.code).toEqualTypeOf<'upstream_error'>()
411
+ void json
412
+ return
413
+ }
414
+ })
415
+
360
416
  test('GET /v1/me', async () => {
361
417
  const client = Client.create()
362
418
  const res = await client.v1.me.$get()
@@ -580,7 +636,7 @@ describe('narrows responses by status', () => {
580
636
  case 403: {
581
637
  const json = await res.json()
582
638
  expectTypeOf(json.error.code).toEqualTypeOf<
583
- 'api_key_forbidden' | 'billing_source_disabled' | 'forbidden'
639
+ 'api_key_forbidden' | 'api_key_ip_forbidden' | 'billing_source_disabled' | 'forbidden'
584
640
  >()
585
641
  void json
586
642
  return
@@ -867,7 +923,7 @@ describe('narrows responses by status', () => {
867
923
  const res = await client.v1.orgs[':orgId{org_[A-Za-z0-9_-]+}'].projects[
868
924
  ':projectId{prj_[A-Za-z0-9_-]+}'
869
925
  ]['api-keys'].$post({
870
- json: { scopes: ['data:read'] },
926
+ json: { allowedIps: ['203.0.113.0/24'], scopes: ['data:read'] },
871
927
  param: { orgId: 'org_test', projectId: 'prj_test' },
872
928
  })
873
929
 
@@ -878,6 +934,7 @@ describe('narrows responses by status', () => {
878
934
  const json = await res.json()
879
935
  expectTypeOf(json.token).toEqualTypeOf<string>()
880
936
  expectTypeOf(json.id).toEqualTypeOf<string>()
937
+ expectTypeOf(json.allowedIps).toEqualTypeOf<readonly string[]>()
881
938
  void json
882
939
  return
883
940
  }
@@ -905,6 +962,7 @@ describe('narrows responses by status', () => {
905
962
  const json = await res.json()
906
963
  expectTypeOf(json.data[0]!.id).toEqualTypeOf<string>()
907
964
  expectTypeOf(json.data[0]!.environment).toEqualTypeOf<'production' | 'sandbox'>()
965
+ expectTypeOf(json.data[0]!.allowedIps).toEqualTypeOf<readonly string[]>()
908
966
  // Absent on org-wide keys minted without project attribution.
909
967
  expectTypeOf(json.data[0]!.projectId).toEqualTypeOf<string | undefined>()
910
968
  void json
@@ -913,6 +971,24 @@ describe('narrows responses by status', () => {
913
971
  }
914
972
  })
915
973
 
974
+ test('PATCH /v1/orgs/:orgId/projects/:projectId/api-keys/:keyId', async () => {
975
+ const client = Client.create()
976
+ const res = await client.v1.orgs[':orgId{org_[A-Za-z0-9_-]+}'].projects[
977
+ ':projectId{prj_[A-Za-z0-9_-]+}'
978
+ ]['api-keys'][':keyId{key_[A-Za-z0-9_-]+}'].$patch({
979
+ json: { allowedIps: [] },
980
+ param: { keyId: 'key_test', orgId: 'org_test', projectId: 'prj_test' },
981
+ })
982
+
983
+ expectTypeOf(res.status).toEqualTypeOf<200 | 404 | 502 | PublicAccessStatus>()
984
+
985
+ if (res.status === 200) {
986
+ const json = await res.json()
987
+ expectTypeOf(json.allowedIps).toEqualTypeOf<readonly string[]>()
988
+ void json
989
+ }
990
+ })
991
+
916
992
  test('DELETE /v1/orgs/:orgId/projects/:projectId/api-keys/:keyId', async () => {
917
993
  const client = Client.create()
918
994
  const res = await client.v1.orgs[':orgId{org_[A-Za-z0-9_-]+}'].projects[
@@ -1116,7 +1192,7 @@ describe('narrows responses by status', () => {
1116
1192
  }
1117
1193
  case 403: {
1118
1194
  const json = await res.json()
1119
- expectTypeOf(json.error.code).toEqualTypeOf<'api_key_forbidden'>()
1195
+ expectTypeOf(json.error.code).toEqualTypeOf<'api_key_forbidden' | 'api_key_ip_forbidden'>()
1120
1196
  expectTypeOf(json.error.message).toEqualTypeOf<string>()
1121
1197
  void json
1122
1198
  return
@@ -1810,7 +1886,9 @@ describe('narrows responses by status', () => {
1810
1886
  | undefined
1811
1887
  >()
1812
1888
  expectTypeOf(json.data[0]!.sourceAmount).toEqualTypeOf<
1813
- z.output<typeof Funding.schema.quoteFunding.Response>['data'][number]['sourceAmount']
1889
+ z.output<
1890
+ typeof FundingQuotes.schema.quoteFunding.Response
1891
+ >['data'][number]['sourceAmount']
1814
1892
  >()
1815
1893
  // @ts-expect-error token references do not contain quantities
1816
1894
  void json.data[0]!.sourceToken.amount
@@ -1855,7 +1933,7 @@ describe('narrows responses by status', () => {
1855
1933
  const json = await res.json()
1856
1934
  expectTypeOf(json.data[0]!.tokens[0]!.symbol).toEqualTypeOf<
1857
1935
  z.output<
1858
- typeof Funding.schema.getFundingChains.Response
1936
+ typeof FundingChains.schema.getFundingChains.Response
1859
1937
  >['data'][number]['tokens'][number]['symbol']
1860
1938
  >()
1861
1939
  expectTypeOf(json.data[0]!.addressFormat).toEqualTypeOf<'base58' | 'base58check' | 'hex'>()
@@ -1921,7 +1999,9 @@ describe('narrows responses by status', () => {
1921
1999
  const json = await res.json()
1922
2000
  expectTypeOf(json.id).toEqualTypeOf<string>()
1923
2001
  expectTypeOf(json.status).toEqualTypeOf<
1924
- z.output<typeof Funding.schema.createFundingDepositAddress.Response>['status']
2002
+ z.output<
2003
+ typeof FundingDepositAddresses.schema.createFundingDepositAddress.Response
2004
+ >['status']
1925
2005
  >()
1926
2006
  expectTypeOf(json.subsidize).toEqualTypeOf<boolean>()
1927
2007
  if ('quote' in json) {
@@ -1964,7 +2044,7 @@ describe('narrows responses by status', () => {
1964
2044
  case 200: {
1965
2045
  const json = await res.json()
1966
2046
  expectTypeOf(json.status).toEqualTypeOf<
1967
- z.output<typeof Funding.schema.DepositAddress>['status']
2047
+ z.output<typeof FundingDepositAddresses.schema.DepositAddress>['status']
1968
2048
  >()
1969
2049
  expectTypeOf(json.sourceChain.kind).toEqualTypeOf<'evm' | 'solana' | 'tron'>()
1970
2050
  expectTypeOf(json.subsidize).toEqualTypeOf<boolean>()
@@ -1982,6 +2062,46 @@ describe('narrows responses by status', () => {
1982
2062
  }
1983
2063
  })
1984
2064
 
2065
+ test('POST /v1/funding/deposit-addresses/:id/reconcile', async () => {
2066
+ const client = Client.create()
2067
+ const res = await client.v1.funding['deposit-addresses'][
2068
+ ':id{fda_[A-Za-z0-9_-]+}'
2069
+ ].reconcile.$post({ param: { id: 'fda_test' } })
2070
+
2071
+ expectTypeOf(res.status).toEqualTypeOf<202 | 400 | 401 | 403 | 404 | 409 | 429 | 501 | 502>()
2072
+
2073
+ switch (res.status) {
2074
+ case 202: {
2075
+ expectTypeOf(await res.text()).toEqualTypeOf<string>()
2076
+ return
2077
+ }
2078
+ case 404: {
2079
+ const json = await res.json()
2080
+ expectTypeOf(json.error.code).toEqualTypeOf<'funding_deposit_address_not_found'>()
2081
+ void json
2082
+ return
2083
+ }
2084
+ case 409: {
2085
+ const json = await res.json()
2086
+ expectTypeOf(json.error.code).toEqualTypeOf<'funding_deposit_address_not_active'>()
2087
+ void json
2088
+ return
2089
+ }
2090
+ case 501: {
2091
+ const json = await res.json()
2092
+ expectTypeOf(json.error.code).toEqualTypeOf<'not_implemented'>()
2093
+ void json
2094
+ return
2095
+ }
2096
+ case 502: {
2097
+ const json = await res.json()
2098
+ expectTypeOf(json.error.code).toEqualTypeOf<'upstream_error'>()
2099
+ void json
2100
+ return
2101
+ }
2102
+ }
2103
+ })
2104
+
1985
2105
  test('GET /v1/funding/deposit-addresses/:id/deposits', async () => {
1986
2106
  const client = Client.create()
1987
2107
  const res = await client.v1.funding['deposit-addresses'][
@@ -1993,8 +2113,11 @@ describe('narrows responses by status', () => {
1993
2113
  switch (res.status) {
1994
2114
  case 200: {
1995
2115
  const json = await res.json()
2116
+ expectTypeOf(json.data[0]!.detectionTrigger).toEqualTypeOf<
2117
+ 'chain' | 'manual' | 'poll' | 'webhook' | undefined
2118
+ >()
1996
2119
  expectTypeOf(json.data[0]!.status).toEqualTypeOf<
1997
- z.output<typeof Funding.schema.Deposit>['status']
2120
+ z.output<typeof FundingDepositAddresses.schema.Deposit>['status']
1998
2121
  >()
1999
2122
  expectTypeOf(json.nextCursor).toEqualTypeOf<string | null>()
2000
2123
  void json
@@ -2009,6 +2132,30 @@ describe('narrows responses by status', () => {
2009
2132
  }
2010
2133
  })
2011
2134
 
2135
+ test('GET /v1/funding/deposits', async () => {
2136
+ const client = Client.create()
2137
+ // @ts-expect-error `recipient` is required for the deposit list.
2138
+ void client.v1.funding.deposits.$get({ query: {} })
2139
+ const res = await client.v1.funding.deposits.$get({
2140
+ query: { recipient: `0x${'11'.repeat(20)}` },
2141
+ })
2142
+
2143
+ expectTypeOf(res.status).toEqualTypeOf<200 | 400 | 502 | PublicAccessStatus>()
2144
+
2145
+ switch (res.status) {
2146
+ case 200: {
2147
+ const json = await res.json()
2148
+ expectTypeOf(json.data[0]!.recipient).toEqualTypeOf<string>()
2149
+ expectTypeOf(json.data[0]!.status).toEqualTypeOf<
2150
+ z.output<typeof FundingDepositAddresses.schema.Deposit>['status']
2151
+ >()
2152
+ expectTypeOf(json.nextCursor).toEqualTypeOf<string | null>()
2153
+ void json
2154
+ return
2155
+ }
2156
+ }
2157
+ })
2158
+
2012
2159
  test('GET /v1/funding/deposits/:id', async () => {
2013
2160
  const client = Client.create()
2014
2161
  const res = await client.v1.funding.deposits[':id{fdp_[A-Za-z0-9_-]+}'].$get({
@@ -2020,12 +2167,15 @@ describe('narrows responses by status', () => {
2020
2167
  switch (res.status) {
2021
2168
  case 200: {
2022
2169
  const json = await res.json()
2170
+ expectTypeOf(json.detectionTrigger).toEqualTypeOf<
2171
+ 'chain' | 'manual' | 'poll' | 'webhook' | undefined
2172
+ >()
2023
2173
  expectTypeOf(json.destinationAmountRequired).toEqualTypeOf<
2024
- z.output<typeof Funding.schema.Deposit>['destinationAmountRequired']
2174
+ z.output<typeof FundingDepositAddresses.schema.Deposit>['destinationAmountRequired']
2025
2175
  >()
2026
2176
  expectTypeOf(json.sourceTransferIndex).toEqualTypeOf<number | undefined>()
2027
2177
  expectTypeOf(json.statusReason).toEqualTypeOf<
2028
- z.output<typeof Funding.schema.Deposit>['statusReason']
2178
+ z.output<typeof FundingDepositAddresses.schema.Deposit>['statusReason']
2029
2179
  >()
2030
2180
  // @ts-expect-error provider request identifiers remain private
2031
2181
  void json.providerRequestIds
@@ -2052,7 +2202,7 @@ describe('narrows responses by status', () => {
2052
2202
  const json = await res.json()
2053
2203
  expectTypeOf(json.data[0]!.id).toEqualTypeOf<string>()
2054
2204
  expectTypeOf(json.data[0]!.status).toEqualTypeOf<
2055
- z.output<typeof Funding.schema.Transfer>['status']
2205
+ z.output<typeof FundingTransfers.schema.Transfer>['status']
2056
2206
  >()
2057
2207
  expectTypeOf(json.data[0]!.version).toEqualTypeOf<number>()
2058
2208
  // Transfer reads never expose the executable action.
@@ -2060,7 +2210,7 @@ describe('narrows responses by status', () => {
2060
2210
  void json.data[0]!.action
2061
2211
  // `meta` (opt-in `include=totalCount` count) is optional.
2062
2212
  expectTypeOf(json.meta).toEqualTypeOf<
2063
- z.output<typeof Funding.schema.listFundingTransfers.Response>['meta']
2213
+ z.output<typeof FundingTransfers.schema.listFundingTransfers.Response>['meta']
2064
2214
  >()
2065
2215
  expectTypeOf(json.nextCursor).toEqualTypeOf<string | null>()
2066
2216
  void json
@@ -2102,7 +2252,7 @@ describe('narrows responses by status', () => {
2102
2252
  expectTypeOf(json.action.type).toEqualTypeOf<'evm:calls'>()
2103
2253
  expectTypeOf(json.id).toEqualTypeOf<string>()
2104
2254
  expectTypeOf(json.status).toEqualTypeOf<
2105
- z.output<typeof Funding.schema.createFundingTransfer.Response>['status']
2255
+ z.output<typeof FundingTransfers.schema.createFundingTransfer.Response>['status']
2106
2256
  >()
2107
2257
  void json
2108
2258
  return
@@ -2191,10 +2341,10 @@ describe('narrows responses by status', () => {
2191
2341
  const json = await res.json()
2192
2342
  expectTypeOf(json.id).toEqualTypeOf<string>()
2193
2343
  expectTypeOf(json.status).toEqualTypeOf<
2194
- z.output<typeof Funding.schema.getFundingTransfer.Response>['status']
2344
+ z.output<typeof FundingTransfers.schema.getFundingTransfer.Response>['status']
2195
2345
  >()
2196
2346
  expectTypeOf(json.statusReason).toEqualTypeOf<
2197
- z.output<typeof Funding.schema.getFundingTransfer.Response>['statusReason']
2347
+ z.output<typeof FundingTransfers.schema.getFundingTransfer.Response>['statusReason']
2198
2348
  >()
2199
2349
  // @ts-expect-error `action` is a creation-only field
2200
2350
  void json.action
@@ -2944,7 +3094,7 @@ describe('narrows responses by status', () => {
2944
3094
  }
2945
3095
  case 403: {
2946
3096
  const json = await res.json()
2947
- expectTypeOf(json.error.code).toEqualTypeOf<'api_key_forbidden'>()
3097
+ expectTypeOf(json.error.code).toEqualTypeOf<'api_key_forbidden' | 'api_key_ip_forbidden'>()
2948
3098
  void json
2949
3099
  return
2950
3100
  }
@@ -3120,7 +3270,9 @@ describe('narrows responses by status', () => {
3120
3270
  }
3121
3271
  if (res.status === 403) {
3122
3272
  const json = await res.json()
3123
- expectTypeOf(json.error.code).toEqualTypeOf<'api_key_forbidden' | 'limit_exceeded'>()
3273
+ expectTypeOf(json.error.code).toEqualTypeOf<
3274
+ 'api_key_forbidden' | 'api_key_ip_forbidden' | 'limit_exceeded'
3275
+ >()
3124
3276
  }
3125
3277
  })
3126
3278
 
@@ -24,6 +24,7 @@ describe('POST /api-keys', () => {
24
24
  expect(body.createdBy).toBe(TestAdmin.identity.email)
25
25
  expect(TestAdmin.redact(body)).toMatchInlineSnapshot(`
26
26
  {
27
+ "allowedIps": [],
27
28
  "createdAt": "<createdAt>",
28
29
  "createdBy": "admin@tempo.xyz",
29
30
  "environment": "production",
@@ -290,6 +291,23 @@ describe('DELETE /api-keys/:id', () => {
290
291
  })
291
292
 
292
293
  describe('PATCH /api-keys/:id', () => {
294
+ test('preserves the allowlist when omitted', async () => {
295
+ const { client, store } = TestAdmin.setup()
296
+ const { record } = await core_ApiKeys.mint(store, {
297
+ allowedIps: ['203.0.113.0/24'],
298
+ name: 'Restricted',
299
+ scopes: ['data:read'],
300
+ })
301
+
302
+ const response = await client['api-keys'][':id'].$patch({
303
+ json: { name: 'Renamed' },
304
+ param: { id: record.id },
305
+ })
306
+
307
+ expect(response.status).toBe(200)
308
+ expect((await core_ApiKeys.get(store, record.id))?.allowedIps).toEqual(['203.0.113.0/24'])
309
+ })
310
+
293
311
  test('renames and associates a one-off key without changing its token', async () => {
294
312
  const { client, db, store } = TestAdmin.setup()
295
313
  const organization = await Organizations.create(db, { name: 'Tempo' })
@@ -299,12 +317,18 @@ describe('PATCH /api-keys/:id', () => {
299
317
  })
300
318
 
301
319
  const response = await client['api-keys'][':id'].$patch({
302
- json: { name: 'Explorer', orgId: organization.id, projectId: 'prj_real' },
320
+ json: {
321
+ allowedIps: ['203.0.113.0/24'],
322
+ name: 'Explorer',
323
+ orgId: organization.id,
324
+ projectId: 'prj_real',
325
+ },
303
326
  param: { id: record.id },
304
327
  })
305
328
  expect(response.status).toBe(200)
306
329
  const body = await TestApp.json(response, core_ApiKeys.schema.Record)
307
330
  expect(body.name).toBe('Explorer')
331
+ expect(body.allowedIps).toEqual(['203.0.113.0/24'])
308
332
  expect(body.orgId).toBe(organization.id)
309
333
  expect(body.projectId).toBe('prj_real')
310
334
 
@@ -1,6 +1,7 @@
1
1
  import { Hono } from 'hono'
2
2
  import * as z from 'zod/mini'
3
3
 
4
+ import * as core_ApiKey from '../../ApiKey.js'
4
5
  import * as ApiKeys from '../../ApiKeys.js'
5
6
  import * as Db from '../../db/Db.js'
6
7
  import * as Organizations from '../../db/tables/organizations.js'
@@ -111,6 +112,9 @@ export namespace schema {
111
112
  /** Request body updating a key; omitted fields keep their value. */
112
113
  export const Body = Schema.describe(
113
114
  z.object({
115
+ allowedIps: z
116
+ .optional(core_ApiKey.schema.AllowedIps)
117
+ .check(z.describe('Replacement client IP/CIDR allowlist. An empty list clears it.')),
114
118
  name: z.optional(Name).check(z.describe('New human-readable key name.')),
115
119
  orgId: z
116
120
  .optional(z.string())
@@ -163,7 +167,7 @@ export namespace schema {
163
167
  * returning the one-time token.
164
168
  * - `GET /` lists key records (metadata only), optionally filtered by `orgId`.
165
169
  * - `DELETE /:id` revokes a key by id (`404` if absent).
166
- * - `PATCH /:id` updates a key's name or project, or assigns its first organization.
170
+ * - `PATCH /:id` updates a key's allowlist, name, or project, or assigns its first organization.
167
171
  * - `POST /backfill` rebuilds the id and org index entries for every record.
168
172
  */
169
173
  export function apiKeys() {
@@ -307,7 +311,7 @@ export function apiKeys() {
307
311
  message: 'Invalid request body',
308
312
  }),
309
313
  OpenApi.describeRoute({
310
- description: 'Update a key name or project, or assign its first organization. The token is unchanged.', // prettier-ignore
314
+ description: 'Update a key allowlist, name, or project, or assign its first organization. The token is unchanged.', // prettier-ignore
311
315
  operationId: 'updateApiKey',
312
316
  responses: OpenApi.responses({
313
317
  errors: {