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
@@ -155,7 +155,7 @@ describe('require', () => {
155
155
  const app = createApp({
156
156
  policy: {
157
157
  apiKey: { scopes: ['data:read'] },
158
- public: { rateLimit: { perMinute: 60 } },
158
+ public: { rateLimit: { limit: 60, period: 'minute' } },
159
159
  },
160
160
  })
161
161
  const response = await app.request('/protected', {
@@ -180,7 +180,7 @@ describe('require', () => {
180
180
  logger: (entry) => void entries.push(entry),
181
181
  policy: {
182
182
  apiKey: { scopes: ['data:read'] },
183
- public: { rateLimit: { perMinute: 60 } },
183
+ public: { rateLimit: { limit: 60, period: 'minute' } },
184
184
  },
185
185
  })
186
186
  const response = await app.request('/protected', {
@@ -723,7 +723,9 @@ describe('require', () => {
723
723
  }
724
724
  const policy: Auth.require.Policy = {
725
725
  apiKey: { scopes: [Scope.wildcard] },
726
- ...(options.public === false ? {} : { public: { rateLimit: { perMinute: 60 } } }),
726
+ ...(options.public === false
727
+ ? {}
728
+ : { public: { rateLimit: { limit: 60, period: 'minute' } } }),
727
729
  ...(options.mpp ? { mpp: { session: { amount: '1' } } } : {}),
728
730
  }
729
731
  const app = new Hono<Auth.Environment>()
@@ -825,7 +827,7 @@ describe('require', () => {
825
827
 
826
828
  test('throttles a sandbox key to the public quota when billing is inactive', async () => {
827
829
  const app = createChainApp({
828
- public: true, // policy.public.rateLimit is { perMinute: 60 }
830
+ public: true, // policy.public.rateLimit is { limit: 60, period: 'minute' }
829
831
  sandboxBillingActive: false,
830
832
  })
831
833
  const response = await app.request('/protected?chainId=42431', {
@@ -863,7 +865,7 @@ describe('require', () => {
863
865
  test('throttles to the configured public default on API-key-only routes', async () => {
864
866
  const app = createChainApp({
865
867
  public: false, // no per-route public lane
866
- publicRateLimit: { perMinute: 7 },
868
+ publicRateLimit: { limit: 7, period: 'minute' },
867
869
  sandboxBillingActive: false,
868
870
  })
869
871
  const response = await app.request('/protected?chainId=42431', {
@@ -927,7 +929,7 @@ describe('require', () => {
927
929
  expect(response.headers.get('RateLimit-Scope')).toBe('mpp')
928
930
  expect(consume).toHaveBeenCalledWith({
929
931
  key: 'mpp:public:2001:db8:abcd:12',
930
- limit: { perMinute: 100 },
932
+ limit: { limit: 100, period: 'minute' },
931
933
  })
932
934
  })
933
935
 
@@ -954,7 +956,7 @@ describe('require', () => {
954
956
  expect(response.status).toBe(200)
955
957
  expect(consume).toHaveBeenCalledWith({
956
958
  key: 'mpp:public:anonymous',
957
- limit: { perMinute: 100 },
959
+ limit: { limit: 100, period: 'minute' },
958
960
  })
959
961
  })
960
962
 
@@ -980,7 +982,7 @@ describe('require', () => {
980
982
  expect(response.status).toBe(200)
981
983
  expect(consume).toHaveBeenCalledWith({
982
984
  key: 'mpp:public:2001:db8:abcd:12',
983
- limit: { perMinute: 100 },
985
+ limit: { limit: 100, period: 'minute' },
984
986
  })
985
987
  })
986
988
 
@@ -1009,7 +1011,7 @@ describe('require', () => {
1009
1011
  expect(response.status).toBe(200)
1010
1012
  expect(consume).toHaveBeenCalledWith({
1011
1013
  key: 'mpp:api_key:key_test',
1012
- limit: { perMinute: 100 },
1014
+ limit: { limit: 100, period: 'minute' },
1013
1015
  })
1014
1016
  })
1015
1017
 
@@ -1017,7 +1019,7 @@ describe('require', () => {
1017
1019
  const app = createApp({
1018
1020
  auth: {
1019
1021
  apiKey: { resolve: TestApp.resolver({ keys: [{ ...key, token }] }) },
1020
- mpp: createMppHandler({ rateLimit: { perMinute: 25 } }),
1022
+ mpp: createMppHandler({ rateLimit: { limit: 25, period: 'minute' } }),
1021
1023
  rateLimit: underQuota(),
1022
1024
  },
1023
1025
  policy: { mpp: { session: { amount: '1' } } },
@@ -1034,12 +1036,12 @@ describe('require', () => {
1034
1036
  const app = createApp({
1035
1037
  auth: {
1036
1038
  apiKey: { resolve: TestApp.resolver({ keys: [{ ...key, token }] }) },
1037
- mpp: createMppHandler({ rateLimit: { perMinute: 25 } }),
1039
+ mpp: createMppHandler({ rateLimit: { limit: 25, period: 'minute' } }),
1038
1040
  rateLimit: underQuota(),
1039
1041
  },
1040
1042
  policy: {
1041
1043
  mpp: {
1042
- rateLimit: { perMinute: 5 },
1044
+ rateLimit: { limit: 5, period: 'minute' },
1043
1045
  session: { amount: '1' },
1044
1046
  },
1045
1047
  },
@@ -1082,7 +1084,7 @@ describe('require', () => {
1082
1084
  },
1083
1085
  policy: {
1084
1086
  mpp: { session: { amount: '1', description: 'Protected data' } },
1085
- public: { rateLimit: { perMinute: 1 } },
1087
+ public: { rateLimit: { limit: 1, period: 'minute' } },
1086
1088
  },
1087
1089
  })
1088
1090
  const response = await app.request('/protected')
@@ -1103,7 +1105,7 @@ describe('require', () => {
1103
1105
  },
1104
1106
  policy: {
1105
1107
  mpp: { session: { amount: '1', description: 'Protected data' } },
1106
- public: { rateLimit: { perMinute: 1 } },
1108
+ public: { rateLimit: { limit: 1, period: 'minute' } },
1107
1109
  },
1108
1110
  })
1109
1111
  const response = await createMppClient(app).fetch('http://tempo-api.test/protected')
@@ -1134,7 +1136,7 @@ describe('require', () => {
1134
1136
  },
1135
1137
  policy: {
1136
1138
  apiKey: {
1137
- rateLimit: { perMinute: 1 },
1139
+ rateLimit: { limit: 1, period: 'minute' },
1138
1140
  scopes: ['data:read'],
1139
1141
  },
1140
1142
  mpp: { session: { amount: '1', description: 'Protected data' } },
@@ -1160,7 +1162,7 @@ describe('require', () => {
1160
1162
  },
1161
1163
  policy: {
1162
1164
  apiKey: {
1163
- rateLimit: { perMinute: 1 },
1165
+ rateLimit: { limit: 1, period: 'minute' },
1164
1166
  scopes: ['data:read'],
1165
1167
  },
1166
1168
  mpp: { session: { amount: '1', description: 'Protected data' } },
@@ -1199,7 +1201,7 @@ describe('require', () => {
1199
1201
  },
1200
1202
  policy: {
1201
1203
  mpp: { session: { amount: '1', description: 'Protected data' } },
1202
- public: { rateLimit: { perMinute: 1 } },
1204
+ public: { rateLimit: { limit: 1, period: 'minute' } },
1203
1205
  },
1204
1206
  })
1205
1207
  const response = await app.request('/protected')
@@ -1237,7 +1239,7 @@ describe('require', () => {
1237
1239
  },
1238
1240
  policy: {
1239
1241
  mpp: { session: { amount: '1' } },
1240
- public: { rateLimit: { perMinute: 1 } },
1242
+ public: { rateLimit: { limit: 1, period: 'minute' } },
1241
1243
  },
1242
1244
  })
1243
1245
 
@@ -1272,7 +1274,7 @@ describe('require', () => {
1272
1274
  },
1273
1275
  policy: {
1274
1276
  mpp: { session: { amount: '1' } },
1275
- public: { rateLimit: { perMinute: 1 } },
1277
+ public: { rateLimit: { limit: 1, period: 'minute' } },
1276
1278
  },
1277
1279
  })
1278
1280
 
@@ -1294,7 +1296,7 @@ describe('require', () => {
1294
1296
  },
1295
1297
  policy: {
1296
1298
  mpp: { session: { amount: '2.5', suggestedDeposit: '10' } },
1297
- public: { rateLimit: { perMinute: 1 } },
1299
+ public: { rateLimit: { limit: 1, period: 'minute' } },
1298
1300
  },
1299
1301
  })
1300
1302
  const response = await app.request('/protected')
@@ -1318,7 +1320,7 @@ describe('require', () => {
1318
1320
  },
1319
1321
  policy: {
1320
1322
  mpp: { session: { amount: '1', description: 'Protected data' } },
1321
- public: { rateLimit: { perMinute: 1 } },
1323
+ public: { rateLimit: { limit: 1, period: 'minute' } },
1322
1324
  },
1323
1325
  })
1324
1326
  const response = await createMppClient(app).fetch('http://tempo-api.test/protected')
@@ -1354,7 +1356,7 @@ describe('require', () => {
1354
1356
  policy: {
1355
1357
  // The suggested deposit pre-funds the channel for both requests.
1356
1358
  mpp: { session: { amount: '1', suggestedDeposit: '2' } },
1357
- public: { rateLimit: { perMinute: 1 } },
1359
+ public: { rateLimit: { limit: 1, period: 'minute' } },
1358
1360
  },
1359
1361
  })
1360
1362
  const client = createMppClient(app)
@@ -1390,7 +1392,7 @@ describe('require', () => {
1390
1392
  },
1391
1393
  policy: {
1392
1394
  mpp: { session: { amount: '1', suggestedDeposit: '2' } },
1393
- public: { rateLimit: { perMinute: 1 } },
1395
+ public: { rateLimit: { limit: 1, period: 'minute' } },
1394
1396
  },
1395
1397
  })
1396
1398
  const client = createMppClient({ fetch: (request) => app.fetch(request) })
@@ -1404,7 +1406,7 @@ describe('require', () => {
1404
1406
  },
1405
1407
  policy: {
1406
1408
  mpp: { session: { amount: '1', suggestedDeposit: '2' } },
1407
- public: { rateLimit: { perMinute: 1 } },
1409
+ public: { rateLimit: { limit: 1, period: 'minute' } },
1408
1410
  },
1409
1411
  })
1410
1412
  const second = await client.fetch('http://tempo-api.test/protected')
@@ -1427,7 +1429,7 @@ describe('require', () => {
1427
1429
  },
1428
1430
  policy: {
1429
1431
  mpp: { session: { amount: '1' } },
1430
- public: { rateLimit: { perMinute: 1 } },
1432
+ public: { rateLimit: { limit: 1, period: 'minute' } },
1431
1433
  },
1432
1434
  })
1433
1435
  const client = createMppClient(app)
@@ -1463,7 +1465,7 @@ describe('require', () => {
1463
1465
  },
1464
1466
  policy: {
1465
1467
  mpp: { session: { amount: '1' } },
1466
- public: { rateLimit: { perMinute: 1 } },
1468
+ public: { rateLimit: { limit: 1, period: 'minute' } },
1467
1469
  },
1468
1470
  })
1469
1471
  const response = await app.request('/protected', {
@@ -1478,7 +1480,7 @@ describe('require', () => {
1478
1480
  describe('rateLimit', () => {
1479
1481
  test('allows anonymous public requests under quota', async () => {
1480
1482
  const app = createApp({
1481
- policy: { public: { rateLimit: { perMinute: 60 } } },
1483
+ policy: { public: { rateLimit: { limit: 60, period: 'minute' } } },
1482
1484
  })
1483
1485
  const response = await app.request('/protected', {
1484
1486
  headers: { 'cf-connecting-ip': '203.0.113.10' },
@@ -1502,7 +1504,7 @@ describe('require', () => {
1502
1504
  apiKey: { resolve: TestApp.resolver({ keys: [{ ...key, token }] }) },
1503
1505
  rateLimit: overQuota(),
1504
1506
  },
1505
- policy: { public: { rateLimit: { perMinute: 1 } } },
1507
+ policy: { public: { rateLimit: { limit: 1, period: 'minute' } } },
1506
1508
  })
1507
1509
  const response = await app.request('/protected')
1508
1510
  const body = await response.json()
@@ -1530,7 +1532,7 @@ describe('require', () => {
1530
1532
  },
1531
1533
  },
1532
1534
  },
1533
- policy: { public: { rateLimit: { perMinute: 1 } } },
1535
+ policy: { public: { rateLimit: { limit: 1, period: 'minute' } } },
1534
1536
  })
1535
1537
  const response = await app.request('/protected', {
1536
1538
  headers: { 'cf-connecting-ip': '203.0.113.10' },
@@ -1588,7 +1590,7 @@ describe('require', () => {
1588
1590
  // the consume must not block the request indefinitely.
1589
1591
  rateLimit: { consume: () => new Promise<never>(() => {}) },
1590
1592
  },
1591
- policy: { public: { rateLimit: { perMinute: 1 } } },
1593
+ policy: { public: { rateLimit: { limit: 1, period: 'minute' } } },
1592
1594
  })
1593
1595
  const pending = app.request('/protected', {
1594
1596
  headers: { 'cf-connecting-ip': '203.0.113.10' },
@@ -1632,7 +1634,7 @@ describe('require', () => {
1632
1634
  },
1633
1635
  },
1634
1636
  },
1635
- policy: { public: { rateLimit: { perMinute: 1 } } },
1637
+ policy: { public: { rateLimit: { limit: 1, period: 'minute' } } },
1636
1638
  })
1637
1639
  const response = await app.request('/protected', {
1638
1640
  headers: { 'cf-connecting-ip': '203.0.113.10' },
@@ -1669,7 +1671,7 @@ describe('require', () => {
1669
1671
  },
1670
1672
  },
1671
1673
  },
1672
- policy: { public: { rateLimit: { perMinute: 1 } } },
1674
+ policy: { public: { rateLimit: { limit: 1, period: 'minute' } } },
1673
1675
  })
1674
1676
  const response = await app.request('/protected', {
1675
1677
  headers: { 'cf-connecting-ip': '203.0.113.10' },
@@ -1698,7 +1700,7 @@ describe('require', () => {
1698
1700
  },
1699
1701
  },
1700
1702
  },
1701
- policy: { public: { rateLimit: { perMinute: 1 } } },
1703
+ policy: { public: { rateLimit: { limit: 1, period: 'minute' } } },
1702
1704
  })
1703
1705
  const response = await app.request('/protected', {
1704
1706
  headers: { 'cf-connecting-ip': '203.0.113.10' },
@@ -1731,7 +1733,10 @@ describe('require', () => {
1731
1733
  test('does not share quota across scopes', async () => {
1732
1734
  const auth = {
1733
1735
  apiKey: {
1734
- rateLimits: { 'data:read': { perMinute: 1 }, 'webhooks:write': { perMinute: 1 } },
1736
+ rateLimits: {
1737
+ 'data:read': { limit: 1, period: 'minute' },
1738
+ 'webhooks:write': { limit: 1, period: 'minute' },
1739
+ },
1735
1740
  resolve: TestApp.resolver({
1736
1741
  keys: [{ ...key, scopes: [Scope.wildcard], token }],
1737
1742
  }),
@@ -1785,7 +1790,7 @@ describe('require', () => {
1785
1790
  test('route cap overrides the configured scope limit', async () => {
1786
1791
  const auth = {
1787
1792
  apiKey: {
1788
- rateLimits: { 'data:read': { perMinute: 1_000 } },
1793
+ rateLimits: { 'data:read': { limit: 1_000, period: 'minute' } },
1789
1794
  resolve: TestApp.resolver({
1790
1795
  keys: [{ ...key, scopes: [Scope.wildcard], token }],
1791
1796
  }),
@@ -1797,7 +1802,9 @@ describe('require', () => {
1797
1802
  routes: [
1798
1803
  {
1799
1804
  path: '/protected',
1800
- policy: { apiKey: { rateLimit: { perMinute: 5 }, scopes: ['data:read'] } },
1805
+ policy: {
1806
+ apiKey: { rateLimit: { limit: 5, period: 'minute' }, scopes: ['data:read'] },
1807
+ },
1801
1808
  },
1802
1809
  ],
1803
1810
  })
@@ -1814,7 +1821,7 @@ describe('require', () => {
1814
1821
  keys: [
1815
1822
  {
1816
1823
  ...key,
1817
- rateLimits: { '*': { perMinute: 7 } },
1824
+ rateLimits: { '*': { limit: 7, period: 'minute' } },
1818
1825
  scopes: [Scope.wildcard],
1819
1826
  token,
1820
1827
  },
@@ -1823,7 +1830,7 @@ describe('require', () => {
1823
1830
 
1824
1831
  const open = createScopedApp({
1825
1832
  auth: {
1826
- apiKey: { rateLimits: { '*': { perMinute: 1_000 } }, resolve },
1833
+ apiKey: { rateLimits: { '*': { limit: 1_000, period: 'minute' } }, resolve },
1827
1834
  rateLimit: RateLimit.memory(),
1828
1835
  },
1829
1836
  routes: [{ path: '/protected', policy: { apiKey: { scopes: ['data:read'] } } }],
@@ -1834,13 +1841,15 @@ describe('require', () => {
1834
1841
 
1835
1842
  const capped = createScopedApp({
1836
1843
  auth: {
1837
- apiKey: { rateLimits: { '*': { perMinute: 1_000 } }, resolve },
1844
+ apiKey: { rateLimits: { '*': { limit: 1_000, period: 'minute' } }, resolve },
1838
1845
  rateLimit: RateLimit.memory(),
1839
1846
  },
1840
1847
  routes: [
1841
1848
  {
1842
1849
  path: '/protected',
1843
- policy: { apiKey: { rateLimit: { perMinute: 5 }, scopes: ['data:read'] } },
1850
+ policy: {
1851
+ apiKey: { rateLimit: { limit: 5, period: 'minute' }, scopes: ['data:read'] },
1852
+ },
1844
1853
  },
1845
1854
  ],
1846
1855
  })
@@ -1861,7 +1870,7 @@ describe('require', () => {
1861
1870
  keys: [
1862
1871
  {
1863
1872
  ...key,
1864
- rateLimits: { 'data:read': { perMinute: 9 } },
1873
+ rateLimits: { 'data:read': { limit: 9, period: 'minute' } },
1865
1874
  scopes: [Scope.wildcard],
1866
1875
  token,
1867
1876
  },
@@ -1875,7 +1884,9 @@ describe('require', () => {
1875
1884
  routes: [
1876
1885
  {
1877
1886
  path: '/protected',
1878
- policy: { apiKey: { rateLimit: { perMinute: 5 }, scopes: ['data:read'] } },
1887
+ policy: {
1888
+ apiKey: { rateLimit: { limit: 5, period: 'minute' }, scopes: ['data:read'] },
1889
+ },
1879
1890
  },
1880
1891
  ],
1881
1892
  })
@@ -1894,7 +1905,7 @@ describe('require', () => {
1894
1905
  rateLimit: overQuota(),
1895
1906
  },
1896
1907
  logger: (entry) => void entries.push(entry),
1897
- policy: { apiKey: { rateLimit: { perMinute: 1 }, scopes: ['data:read'] } },
1908
+ policy: { apiKey: { rateLimit: { limit: 1, period: 'minute' }, scopes: ['data:read'] } },
1898
1909
  })
1899
1910
  const response = await app.request('/protected', {
1900
1911
  headers: { 'tempo-api-key': token },
@@ -1923,7 +1934,7 @@ describe('require', () => {
1923
1934
  rateLimit: overQuota(),
1924
1935
  },
1925
1936
  policy: {
1926
- apiKey: { rateLimit: { perMinute: 1 }, scopes: ['data:read'] },
1937
+ apiKey: { rateLimit: { limit: 1, period: 'minute' }, scopes: ['data:read'] },
1927
1938
  mpp: { session: { amount: '1', description: 'Protected data' } },
1928
1939
  },
1929
1940
  })
@@ -2089,54 +2100,6 @@ describe('ensureProject', () => {
2089
2100
  })
2090
2101
  })
2091
2102
 
2092
- describe('parseCredential', () => {
2093
- test('parses credentials keyed by chain id', () => {
2094
- const credential = Auth.parseCredential(
2095
- JSON.stringify({ 4217: 'mainnet:secret', 421700001: 'zone:secret' }),
2096
- )
2097
-
2098
- expect(credential).toEqual({ 4217: 'mainnet:secret', 421700001: 'zone:secret' })
2099
- })
2100
-
2101
- test('supports a shared credential', () => {
2102
- expect(Auth.parseCredential('shared:secret')).toBe('shared:secret')
2103
- })
2104
-
2105
- test('rejects malformed credential maps', () => {
2106
- expect(() => Auth.parseCredential('{"4217":1}')).toThrowErrorMatchingInlineSnapshot(
2107
- `[Error: Expected a credential or a chain-id-to-credential JSON object.]`,
2108
- )
2109
- })
2110
- })
2111
-
2112
- describe('resolveCredential', () => {
2113
- test('infers Basic auth from a credential containing a colon', () => {
2114
- expect(Auth.resolveCredential({ chainId: 4217, value: 'user:password' })).toEqual({
2115
- basicAuth: 'user:password',
2116
- })
2117
- })
2118
-
2119
- test('infers Bearer auth from a credential without a colon', () => {
2120
- expect(Auth.resolveCredential({ chainId: 4217, value: 'bearer-token' })).toEqual({
2121
- basicAuth: undefined,
2122
- bearerAuth: 'bearer-token',
2123
- })
2124
- })
2125
-
2126
- test('selects a credential by chain id', () => {
2127
- const value = JSON.stringify({ 4217: 'mainnet:secret', 421700001: 'zone-token' })
2128
-
2129
- expect(Auth.resolveCredential({ chainId: 4217, value })).toEqual({
2130
- basicAuth: 'mainnet:secret',
2131
- })
2132
- expect(Auth.resolveCredential({ chainId: 421700001, value })).toEqual({
2133
- basicAuth: undefined,
2134
- bearerAuth: 'zone-token',
2135
- })
2136
- expect(Auth.resolveCredential({ chainId: 42431, value })).toEqual({ basicAuth: undefined })
2137
- })
2138
- })
2139
-
2140
2103
  function createScopedApp(options: {
2141
2104
  auth?: Auth.Context | undefined
2142
2105
  routes: readonly { path: string; policy: Auth.require.Policy }[]
@@ -2312,7 +2275,7 @@ function overQuota(): RateLimit.Store {
2312
2275
  async consume(options) {
2313
2276
  return {
2314
2277
  allowed: false,
2315
- limit: options.limit.perMinute,
2278
+ limit: options.limit.limit,
2316
2279
  remaining: 0,
2317
2280
  reset: Math.ceil(Date.now() / 1_000) + 60,
2318
2281
  }
@@ -2325,8 +2288,8 @@ function underQuota(): RateLimit.Store {
2325
2288
  async consume(options) {
2326
2289
  return {
2327
2290
  allowed: true,
2328
- limit: options.limit.perMinute,
2329
- remaining: Math.max(options.limit.perMinute - 1, 0),
2291
+ limit: options.limit.limit,
2292
+ remaining: Math.max(options.limit.limit - 1, 0),
2330
2293
  reset: Math.ceil(Date.now() / 1_000) + 60,
2331
2294
  }
2332
2295
  },
@@ -2339,13 +2302,13 @@ function overQuotaExceptMpp(): RateLimit.Store {
2339
2302
  if (options.key.startsWith('mpp:'))
2340
2303
  return {
2341
2304
  allowed: true,
2342
- limit: options.limit.perMinute,
2343
- remaining: Math.max(options.limit.perMinute - 1, 0),
2305
+ limit: options.limit.limit,
2306
+ remaining: Math.max(options.limit.limit - 1, 0),
2344
2307
  reset: Math.ceil(Date.now() / 1_000) + 60,
2345
2308
  }
2346
2309
  return {
2347
2310
  allowed: false,
2348
- limit: options.limit.perMinute,
2311
+ limit: options.limit.limit,
2349
2312
  remaining: 0,
2350
2313
  reset: Math.ceil(Date.now() / 1_000) + 60,
2351
2314
  }
@@ -28,11 +28,12 @@ import * as Response from './Response.js'
28
28
  import * as Schema from './Schema.js'
29
29
  import * as Scope from '../Scope.js'
30
30
  import * as Users from '../db/tables/users.js'
31
+ import type * as Viem from './Viem.js'
31
32
 
32
33
  const policySymbol = Symbol('tempo-api.auth.policy')
33
34
  const mppManagementSymbol = Symbol('tempo-api.auth.mpp-management')
34
- const defaultApiKeyRateLimit = { perMinute: 10_000 } satisfies RateLimit.Limit
35
- const defaultMppRateLimit = { perMinute: 100 } satisfies RateLimit.Limit
35
+ const defaultApiKeyRateLimit = { limit: 10_000, period: 'minute' } satisfies RateLimit.Limit
36
+ const defaultMppRateLimit = { limit: 100, period: 'minute' } satisfies RateLimit.Limit
36
37
 
37
38
  /** Auth context consumed by Tempo API handlers. */
38
39
  export type Context = {
@@ -788,6 +789,7 @@ export function install(options: install.Options) {
788
789
  (typeof options_session === 'object' ? options_session.wallet : undefined) ?? {}
789
790
 
790
791
  const handler = Accounts.Handler.auth({
792
+ getClient: options.getClient,
791
793
  ...(issuer || requireEmail
792
794
  ? { identity: { ...(issuer ? { issuer } : {}), ...(requireEmail ? { required: true } : {}) } } // prettier-ignore
793
795
  : {}),
@@ -912,6 +914,7 @@ export function install(options: install.Options) {
912
914
  409: handlerError('Challenge nonce already used or unknown.'),
913
915
  429: OpenApi.standardError(429, 'Rate limited.'),
914
916
  500: OpenApi.standardError(500, 'Internal server error.'),
917
+ 502: handlerError('The Tempo RPC could not verify the signature.'),
915
918
  },
916
919
  summary: 'Authenticate (SIWE)',
917
920
  tags: ['Authentication'],
@@ -967,6 +970,8 @@ export declare namespace install {
967
970
  | undefined
968
971
  /** Authoritative database holding user rows. */
969
972
  db: Db.Source
973
+ /** Resolves the configured Tempo RPC client used for SIWE signature verification. */
974
+ getClient: (chainId: number) => Viem.getClient.ReturnType
970
975
  /** KV state store, or undefined when key auth is closed. */
971
976
  kv: { store: Store.State } | undefined
972
977
  /** Scope catalog accepted while resolving API-key records. */
@@ -1142,7 +1147,7 @@ function laneDefaults(options: middleware.Options): LaneDefaults {
1142
1147
  scopes: apiKey?.scopes ?? [Scope.wildcard],
1143
1148
  },
1144
1149
  mpp: { session: {} },
1145
- public: { rateLimit: public_?.rateLimit ?? { perMinute: 60 } },
1150
+ public: { rateLimit: public_?.rateLimit ?? { limit: 60, period: 'minute' } },
1146
1151
  session: true,
1147
1152
  }
1148
1153
  }
@@ -1525,7 +1530,7 @@ export function require<environment extends Environment = Environment>(
1525
1530
  // A throttled sandbox key shares the key's bucket but at the public
1526
1531
  // ceiling, so activating billing lifts the limit on the same counter.
1527
1532
  const limit = throttled
1528
- ? (policy.public?.rateLimit ?? auth.publicRateLimit ?? { perMinute: 60 })
1533
+ ? (policy.public?.rateLimit ?? auth.publicRateLimit ?? { limit: 60, period: 'minute' })
1529
1534
  : resolveApiKeyLimit({ apiKey, auth, policy: policy.apiKey, scope })
1530
1535
  const result = await consumeRateLimit(auth, {
1531
1536
  key: `api_key:${apiKey.id}:scope:${scope}`,
@@ -1669,65 +1674,6 @@ type RateLimitAccess = PaymentAccess & {
1669
1674
  rateLimit: RateLimit.Result
1670
1675
  }
1671
1676
 
1672
- /** Shared or per-chain credentials. */
1673
- export type ChainCredential = string | Record<number, string>
1674
-
1675
- /** Parses shared or per-chain credentials from an environment value. */
1676
- export function parseCredential(value: ChainCredential | undefined): parseCredential.ReturnType {
1677
- if (!value) return undefined
1678
- if (typeof value !== 'string') return value
1679
- const credentials = (() => {
1680
- try {
1681
- return JSON.parse(value) as unknown
1682
- } catch {
1683
- return value
1684
- }
1685
- })()
1686
- if (typeof credentials === 'string') return credentials
1687
- if (
1688
- !credentials ||
1689
- typeof credentials !== 'object' ||
1690
- Array.isArray(credentials) ||
1691
- Object.values(credentials).some((credential) => typeof credential !== 'string')
1692
- )
1693
- throw new Error('Expected a credential or a chain-id-to-credential JSON object.')
1694
- return credentials as Record<number, string>
1695
- }
1696
-
1697
- export declare namespace parseCredential {
1698
- /** Parsed shared or per-chain credentials. */
1699
- type ReturnType = ChainCredential | undefined
1700
- }
1701
-
1702
- /** Resolves a chain credential and infers its HTTP authorization scheme. */
1703
- export function resolveCredential(
1704
- options: resolveCredential.Options,
1705
- ): resolveCredential.ReturnType {
1706
- const credentials = parseCredential(options.value)
1707
- const credential = typeof credentials === 'string' ? credentials : credentials?.[options.chainId]
1708
- if (!credential) return { basicAuth: undefined }
1709
- if (credential.includes(':')) return { basicAuth: credential }
1710
- return { basicAuth: undefined, bearerAuth: credential }
1711
- }
1712
-
1713
- export declare namespace resolveCredential {
1714
- /** Options for resolving a chain credential. */
1715
- type Options = {
1716
- /** Chain id selecting a per-chain credential. */
1717
- chainId: number
1718
- /** Shared or per-chain credentials. */
1719
- value?: ChainCredential | undefined
1720
- }
1721
-
1722
- /** Resolved HTTP authorization credentials. */
1723
- type ReturnType = {
1724
- /** Basic credentials inferred from a value containing a colon. */
1725
- basicAuth: string | undefined
1726
- /** Bearer credential inferred from a value without a colon. */
1727
- bearerAuth?: string | undefined
1728
- }
1729
- }
1730
-
1731
1677
  /**
1732
1678
  * How long to wait for the rate-limit counter before failing open. A hot
1733
1679
  * counter backend (e.g. a single Durable Object serving one busy quota bucket)
@@ -0,0 +1,51 @@
1
+ import * as Credential from './Credential.js'
2
+
3
+ describe('parseCredential', () => {
4
+ test('parses credentials keyed by chain id', () => {
5
+ const credential = Credential.parseCredential(
6
+ JSON.stringify({ 4217: 'mainnet:secret', 421700001: 'zone:secret' }),
7
+ )
8
+
9
+ expect(credential).toEqual({ 4217: 'mainnet:secret', 421700001: 'zone:secret' })
10
+ })
11
+
12
+ test('supports a shared credential', () => {
13
+ expect(Credential.parseCredential('shared:secret')).toBe('shared:secret')
14
+ })
15
+
16
+ test('rejects malformed credential maps', () => {
17
+ expect(() => Credential.parseCredential('{"4217":1}')).toThrowErrorMatchingInlineSnapshot(
18
+ `[Error: Expected a credential or a chain-id-to-credential JSON object.]`,
19
+ )
20
+ })
21
+ })
22
+
23
+ describe('resolveCredential', () => {
24
+ test('infers Basic auth from a credential containing a colon', () => {
25
+ expect(Credential.resolveCredential({ chainId: 4217, value: 'user:password' })).toEqual({
26
+ basicAuth: 'user:password',
27
+ })
28
+ })
29
+
30
+ test('infers Bearer auth from a credential without a colon', () => {
31
+ expect(Credential.resolveCredential({ chainId: 4217, value: 'bearer-token' })).toEqual({
32
+ basicAuth: undefined,
33
+ bearerAuth: 'bearer-token',
34
+ })
35
+ })
36
+
37
+ test('selects a credential by chain id', () => {
38
+ const value = JSON.stringify({ 4217: 'mainnet:secret', 421700001: 'zone-token' })
39
+
40
+ expect(Credential.resolveCredential({ chainId: 4217, value })).toEqual({
41
+ basicAuth: 'mainnet:secret',
42
+ })
43
+ expect(Credential.resolveCredential({ chainId: 421700001, value })).toEqual({
44
+ basicAuth: undefined,
45
+ bearerAuth: 'zone-token',
46
+ })
47
+ expect(Credential.resolveCredential({ chainId: 42431, value })).toEqual({
48
+ basicAuth: undefined,
49
+ })
50
+ })
51
+ })