@thirdweb-dev/service-utils 0.4.4-nightly-2088de1c-20230901183809 → 0.4.5-next-bc537e5a-20230919062653

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 (29) hide show
  1. package/cf-worker/dist/thirdweb-dev-service-utils-cf-worker.cjs.dev.js +42 -24
  2. package/cf-worker/dist/thirdweb-dev-service-utils-cf-worker.cjs.prod.js +42 -24
  3. package/cf-worker/dist/thirdweb-dev-service-utils-cf-worker.esm.js +41 -25
  4. package/dist/declarations/src/cf-worker/index.d.ts +6 -2
  5. package/dist/declarations/src/cf-worker/index.d.ts.map +1 -1
  6. package/dist/declarations/src/cf-worker/usage.d.ts +14 -11
  7. package/dist/declarations/src/cf-worker/usage.d.ts.map +1 -1
  8. package/dist/declarations/src/core/api.d.ts +17 -1
  9. package/dist/declarations/src/core/api.d.ts.map +1 -1
  10. package/dist/declarations/src/core/authorize/client.d.ts.map +1 -1
  11. package/dist/declarations/src/core/authorize/index.d.ts.map +1 -1
  12. package/dist/declarations/src/core/authorize/service.d.ts.map +1 -1
  13. package/dist/declarations/src/core/rateLimit/index.d.ts +10 -0
  14. package/dist/declarations/src/core/rateLimit/index.d.ts.map +1 -0
  15. package/dist/declarations/src/core/rateLimit/types.d.ts +9 -0
  16. package/dist/declarations/src/core/rateLimit/types.d.ts.map +1 -0
  17. package/dist/declarations/src/core/usageLimit/index.d.ts +5 -0
  18. package/dist/declarations/src/core/usageLimit/index.d.ts.map +1 -0
  19. package/dist/declarations/src/core/usageLimit/types.d.ts +9 -0
  20. package/dist/declarations/src/core/usageLimit/types.d.ts.map +1 -0
  21. package/dist/declarations/src/node/index.d.ts +2 -0
  22. package/dist/declarations/src/node/index.d.ts.map +1 -1
  23. package/dist/{index-6e0ecc5f.cjs.prod.js → index-807f6a60.cjs.dev.js} +132 -6
  24. package/dist/{index-ffddf746.esm.js → index-bcf68113.esm.js} +131 -7
  25. package/dist/{index-cd4f96ef.cjs.dev.js → index-cfc8027b.cjs.prod.js} +132 -6
  26. package/node/dist/thirdweb-dev-service-utils-node.cjs.dev.js +28 -22
  27. package/node/dist/thirdweb-dev-service-utils-node.cjs.prod.js +28 -22
  28. package/node/dist/thirdweb-dev-service-utils-node.esm.js +27 -22
  29. package/package.json +2 -1
@@ -6,7 +6,7 @@ async function fetchKeyMetadataFromApi(clientId, config) {
6
6
  serviceScope,
7
7
  serviceApiKey
8
8
  } = config;
9
- const url = `${apiUrl}/v1/keys/use?clientId=${clientId}&scope=${serviceScope}`;
9
+ const url = `${apiUrl}/v1/keys/use?clientId=${clientId}&scope=${serviceScope}&includeUsage=true`;
10
10
  const response = await fetch(url, {
11
11
  method: "GET",
12
12
  headers: {
@@ -27,7 +27,7 @@ async function fetchAccountFromApi(jwt, config, useWalletAuth) {
27
27
  apiUrl,
28
28
  serviceApiKey
29
29
  } = config;
30
- const url = useWalletAuth ? `${apiUrl}/v1/wallet/me` : `${apiUrl}/v1/account/me`;
30
+ const url = useWalletAuth ? `${apiUrl}/v1/wallet/me?includeUsage=true` : `${apiUrl}/v1/account/me?includeUsage=true`;
31
31
  const response = await fetch(url, {
32
32
  method: "GET",
33
33
  headers: {
@@ -44,6 +44,25 @@ async function fetchAccountFromApi(jwt, config, useWalletAuth) {
44
44
  }
45
45
  return json;
46
46
  }
47
+ async function updateRateLimitedAt(apiKeyId, config) {
48
+ const {
49
+ apiUrl,
50
+ serviceScope: scope,
51
+ serviceApiKey
52
+ } = config;
53
+ const url = `${apiUrl}/usage/rateLimit`;
54
+ await fetch(url, {
55
+ method: "PUT",
56
+ headers: {
57
+ "x-service-api-key": serviceApiKey,
58
+ "content-type": "application/json"
59
+ },
60
+ body: JSON.stringify({
61
+ apiKeyId,
62
+ scope
63
+ })
64
+ });
65
+ }
47
66
 
48
67
  function authorizeClient(authOptions, apiKeyMeta) {
49
68
  const {
@@ -63,7 +82,10 @@ function authorizeClient(authOptions, apiKeyMeta) {
63
82
  id: apiKeyMeta.accountId,
64
83
  // TODO update this later
65
84
  name: "",
66
- creatorWalletAddress: apiKeyMeta.creatorWalletAddress
85
+ creatorWalletAddress: apiKeyMeta.creatorWalletAddress,
86
+ limits: apiKeyMeta.limits,
87
+ rateLimits: apiKeyMeta.rateLimits,
88
+ usage: apiKeyMeta.usage
67
89
  }
68
90
  };
69
91
 
@@ -193,12 +215,15 @@ function authorizeService(apiKeyMetadata, serviceConfig, authorizationPayload) {
193
215
  }
194
216
  return {
195
217
  authorized: true,
218
+ apiKeyMeta: apiKeyMetadata,
196
219
  accountMeta: {
197
220
  id: apiKeyMetadata.accountId,
198
221
  name: "",
199
- creatorWalletAddress: apiKeyMetadata.creatorWalletAddress
200
- },
201
- apiKeyMeta: apiKeyMetadata
222
+ creatorWalletAddress: apiKeyMetadata.creatorWalletAddress,
223
+ limits: apiKeyMetadata.limits,
224
+ rateLimits: apiKeyMetadata.rateLimits,
225
+ usage: apiKeyMetadata.usage
226
+ }
202
227
  };
203
228
  }
204
229
 
@@ -416,9 +441,110 @@ async function authorize(authData, serviceConfig, cacheOptions) {
416
441
  id: apiKeyMeta.accountId,
417
442
  // TODO update this later
418
443
  name: "",
444
+ limits: apiKeyMeta.limits,
445
+ rateLimits: apiKeyMeta.rateLimits,
446
+ usage: apiKeyMeta.usage,
419
447
  creatorWalletAddress: apiKeyMeta.creatorWalletAddress
420
448
  }
421
449
  };
422
450
  }
423
451
 
452
+ const DEFAULT_RATE_LIMIT_WINDOW_SECONDS = 10;
453
+ const HARD_LIMIT_MULTIPLE = 2; // 2x of allowed limit
454
+
455
+ async function rateLimit(authzResult, serviceConfig, cacheOptions) {
456
+ if (!authzResult.authorized) {
457
+ return {
458
+ rateLimited: false
459
+ };
460
+ }
461
+ const {
462
+ apiKeyMeta,
463
+ accountMeta
464
+ } = authzResult;
465
+ const {
466
+ rateLimits
467
+ } = apiKeyMeta || accountMeta || {};
468
+ const accountId = apiKeyMeta?.accountId || accountMeta?.id;
469
+ const {
470
+ serviceScope
471
+ } = serviceConfig;
472
+ if (!rateLimits || !(serviceScope in rateLimits)) {
473
+ // No rate limit is provided. Assume the request is not rate limited.
474
+ return {
475
+ rateLimited: false
476
+ };
477
+ }
478
+ const limit = rateLimits[serviceScope];
479
+
480
+ // Floors the current time to the nearest DEFAULT_RATE_LIMIT_WINDOW_SECONDS.
481
+ const bucketId = Math.floor(Date.now() / (1000 * DEFAULT_RATE_LIMIT_WINDOW_SECONDS)) * DEFAULT_RATE_LIMIT_WINDOW_SECONDS;
482
+ const key = [serviceScope, accountId, bucketId].join(":");
483
+ const value = parseInt((await cacheOptions.get(key)) || "0");
484
+ const current = value + 1;
485
+
486
+ // limit is in seconds, but we need in DEFAULT_RATE_LIMIT_WINDOW_SECONDS
487
+ const limitWindow = limit * DEFAULT_RATE_LIMIT_WINDOW_SECONDS;
488
+ if (current > limitWindow) {
489
+ // report rate limit hits
490
+ if (apiKeyMeta?.id) {
491
+ await updateRateLimitedAt(apiKeyMeta.id, serviceConfig);
492
+ }
493
+
494
+ // actually rate limit only when reached hard limit
495
+ if (current > limitWindow * HARD_LIMIT_MULTIPLE) {
496
+ return {
497
+ rateLimited: true,
498
+ status: 429,
499
+ errorMessage: `You've exceeded your ${serviceScope} rate limit at ${limit} reqs/sec. To get higher rate limits, contact us at https://thirdweb.com/contact-us.`,
500
+ errorCode: "RATE_LIMIT_EXCEEDED"
501
+ };
502
+ }
503
+ } else {
504
+ await cacheOptions.put(key, current.toString());
505
+ }
506
+ return {
507
+ rateLimited: false
508
+ };
509
+ }
510
+
511
+ async function usageLimit(authzResult, serviceConfig) {
512
+ if (!authzResult.authorized) {
513
+ return {
514
+ usageLimited: false
515
+ };
516
+ }
517
+ const {
518
+ apiKeyMeta,
519
+ accountMeta
520
+ } = authzResult;
521
+ const {
522
+ limits,
523
+ usage
524
+ } = apiKeyMeta || accountMeta || {};
525
+ const {
526
+ serviceScope
527
+ } = serviceConfig;
528
+ if (!usage || !(serviceScope in usage) || !limits || !(serviceScope in limits)) {
529
+ // No usage limit is provided. Assume the request is not limited.
530
+ return {
531
+ usageLimited: false
532
+ };
533
+ }
534
+ const limit = limits.storage;
535
+ if (serviceScope === "storage" && (usage.storage?.sumFileSizeBytes || 0) > limit) {
536
+ return {
537
+ usageLimited: true,
538
+ status: 403,
539
+ errorMessage: `You've used all of your total usage limit for Storage Pinning. Please add your payment method at https://thirdweb.com/dashboard/settings/billing.`,
540
+ errorCode: "PAYMENT_METHOD_REQUIRED"
541
+ };
542
+ }
543
+ return {
544
+ usageLimited: false
545
+ };
546
+ }
547
+
424
548
  exports.authorize = authorize;
549
+ exports.rateLimit = rateLimit;
550
+ exports.usageLimit = usageLimit;
@@ -4,7 +4,7 @@ async function fetchKeyMetadataFromApi(clientId, config) {
4
4
  serviceScope,
5
5
  serviceApiKey
6
6
  } = config;
7
- const url = `${apiUrl}/v1/keys/use?clientId=${clientId}&scope=${serviceScope}`;
7
+ const url = `${apiUrl}/v1/keys/use?clientId=${clientId}&scope=${serviceScope}&includeUsage=true`;
8
8
  const response = await fetch(url, {
9
9
  method: "GET",
10
10
  headers: {
@@ -25,7 +25,7 @@ async function fetchAccountFromApi(jwt, config, useWalletAuth) {
25
25
  apiUrl,
26
26
  serviceApiKey
27
27
  } = config;
28
- const url = useWalletAuth ? `${apiUrl}/v1/wallet/me` : `${apiUrl}/v1/account/me`;
28
+ const url = useWalletAuth ? `${apiUrl}/v1/wallet/me?includeUsage=true` : `${apiUrl}/v1/account/me?includeUsage=true`;
29
29
  const response = await fetch(url, {
30
30
  method: "GET",
31
31
  headers: {
@@ -42,6 +42,25 @@ async function fetchAccountFromApi(jwt, config, useWalletAuth) {
42
42
  }
43
43
  return json;
44
44
  }
45
+ async function updateRateLimitedAt(apiKeyId, config) {
46
+ const {
47
+ apiUrl,
48
+ serviceScope: scope,
49
+ serviceApiKey
50
+ } = config;
51
+ const url = `${apiUrl}/usage/rateLimit`;
52
+ await fetch(url, {
53
+ method: "PUT",
54
+ headers: {
55
+ "x-service-api-key": serviceApiKey,
56
+ "content-type": "application/json"
57
+ },
58
+ body: JSON.stringify({
59
+ apiKeyId,
60
+ scope
61
+ })
62
+ });
63
+ }
45
64
 
46
65
  function authorizeClient(authOptions, apiKeyMeta) {
47
66
  const {
@@ -61,7 +80,10 @@ function authorizeClient(authOptions, apiKeyMeta) {
61
80
  id: apiKeyMeta.accountId,
62
81
  // TODO update this later
63
82
  name: "",
64
- creatorWalletAddress: apiKeyMeta.creatorWalletAddress
83
+ creatorWalletAddress: apiKeyMeta.creatorWalletAddress,
84
+ limits: apiKeyMeta.limits,
85
+ rateLimits: apiKeyMeta.rateLimits,
86
+ usage: apiKeyMeta.usage
65
87
  }
66
88
  };
67
89
 
@@ -191,12 +213,15 @@ function authorizeService(apiKeyMetadata, serviceConfig, authorizationPayload) {
191
213
  }
192
214
  return {
193
215
  authorized: true,
216
+ apiKeyMeta: apiKeyMetadata,
194
217
  accountMeta: {
195
218
  id: apiKeyMetadata.accountId,
196
219
  name: "",
197
- creatorWalletAddress: apiKeyMetadata.creatorWalletAddress
198
- },
199
- apiKeyMeta: apiKeyMetadata
220
+ creatorWalletAddress: apiKeyMetadata.creatorWalletAddress,
221
+ limits: apiKeyMetadata.limits,
222
+ rateLimits: apiKeyMetadata.rateLimits,
223
+ usage: apiKeyMetadata.usage
224
+ }
200
225
  };
201
226
  }
202
227
 
@@ -414,9 +439,108 @@ async function authorize(authData, serviceConfig, cacheOptions) {
414
439
  id: apiKeyMeta.accountId,
415
440
  // TODO update this later
416
441
  name: "",
442
+ limits: apiKeyMeta.limits,
443
+ rateLimits: apiKeyMeta.rateLimits,
444
+ usage: apiKeyMeta.usage,
417
445
  creatorWalletAddress: apiKeyMeta.creatorWalletAddress
418
446
  }
419
447
  };
420
448
  }
421
449
 
422
- export { authorize as a };
450
+ const DEFAULT_RATE_LIMIT_WINDOW_SECONDS = 10;
451
+ const HARD_LIMIT_MULTIPLE = 2; // 2x of allowed limit
452
+
453
+ async function rateLimit(authzResult, serviceConfig, cacheOptions) {
454
+ if (!authzResult.authorized) {
455
+ return {
456
+ rateLimited: false
457
+ };
458
+ }
459
+ const {
460
+ apiKeyMeta,
461
+ accountMeta
462
+ } = authzResult;
463
+ const {
464
+ rateLimits
465
+ } = apiKeyMeta || accountMeta || {};
466
+ const accountId = apiKeyMeta?.accountId || accountMeta?.id;
467
+ const {
468
+ serviceScope
469
+ } = serviceConfig;
470
+ if (!rateLimits || !(serviceScope in rateLimits)) {
471
+ // No rate limit is provided. Assume the request is not rate limited.
472
+ return {
473
+ rateLimited: false
474
+ };
475
+ }
476
+ const limit = rateLimits[serviceScope];
477
+
478
+ // Floors the current time to the nearest DEFAULT_RATE_LIMIT_WINDOW_SECONDS.
479
+ const bucketId = Math.floor(Date.now() / (1000 * DEFAULT_RATE_LIMIT_WINDOW_SECONDS)) * DEFAULT_RATE_LIMIT_WINDOW_SECONDS;
480
+ const key = [serviceScope, accountId, bucketId].join(":");
481
+ const value = parseInt((await cacheOptions.get(key)) || "0");
482
+ const current = value + 1;
483
+
484
+ // limit is in seconds, but we need in DEFAULT_RATE_LIMIT_WINDOW_SECONDS
485
+ const limitWindow = limit * DEFAULT_RATE_LIMIT_WINDOW_SECONDS;
486
+ if (current > limitWindow) {
487
+ // report rate limit hits
488
+ if (apiKeyMeta?.id) {
489
+ await updateRateLimitedAt(apiKeyMeta.id, serviceConfig);
490
+ }
491
+
492
+ // actually rate limit only when reached hard limit
493
+ if (current > limitWindow * HARD_LIMIT_MULTIPLE) {
494
+ return {
495
+ rateLimited: true,
496
+ status: 429,
497
+ errorMessage: `You've exceeded your ${serviceScope} rate limit at ${limit} reqs/sec. To get higher rate limits, contact us at https://thirdweb.com/contact-us.`,
498
+ errorCode: "RATE_LIMIT_EXCEEDED"
499
+ };
500
+ }
501
+ } else {
502
+ await cacheOptions.put(key, current.toString());
503
+ }
504
+ return {
505
+ rateLimited: false
506
+ };
507
+ }
508
+
509
+ async function usageLimit(authzResult, serviceConfig) {
510
+ if (!authzResult.authorized) {
511
+ return {
512
+ usageLimited: false
513
+ };
514
+ }
515
+ const {
516
+ apiKeyMeta,
517
+ accountMeta
518
+ } = authzResult;
519
+ const {
520
+ limits,
521
+ usage
522
+ } = apiKeyMeta || accountMeta || {};
523
+ const {
524
+ serviceScope
525
+ } = serviceConfig;
526
+ if (!usage || !(serviceScope in usage) || !limits || !(serviceScope in limits)) {
527
+ // No usage limit is provided. Assume the request is not limited.
528
+ return {
529
+ usageLimited: false
530
+ };
531
+ }
532
+ const limit = limits.storage;
533
+ if (serviceScope === "storage" && (usage.storage?.sumFileSizeBytes || 0) > limit) {
534
+ return {
535
+ usageLimited: true,
536
+ status: 403,
537
+ errorMessage: `You've used all of your total usage limit for Storage Pinning. Please add your payment method at https://thirdweb.com/dashboard/settings/billing.`,
538
+ errorCode: "PAYMENT_METHOD_REQUIRED"
539
+ };
540
+ }
541
+ return {
542
+ usageLimited: false
543
+ };
544
+ }
545
+
546
+ export { authorize as a, rateLimit as r, usageLimit as u };
@@ -6,7 +6,7 @@ async function fetchKeyMetadataFromApi(clientId, config) {
6
6
  serviceScope,
7
7
  serviceApiKey
8
8
  } = config;
9
- const url = `${apiUrl}/v1/keys/use?clientId=${clientId}&scope=${serviceScope}`;
9
+ const url = `${apiUrl}/v1/keys/use?clientId=${clientId}&scope=${serviceScope}&includeUsage=true`;
10
10
  const response = await fetch(url, {
11
11
  method: "GET",
12
12
  headers: {
@@ -27,7 +27,7 @@ async function fetchAccountFromApi(jwt, config, useWalletAuth) {
27
27
  apiUrl,
28
28
  serviceApiKey
29
29
  } = config;
30
- const url = useWalletAuth ? `${apiUrl}/v1/wallet/me` : `${apiUrl}/v1/account/me`;
30
+ const url = useWalletAuth ? `${apiUrl}/v1/wallet/me?includeUsage=true` : `${apiUrl}/v1/account/me?includeUsage=true`;
31
31
  const response = await fetch(url, {
32
32
  method: "GET",
33
33
  headers: {
@@ -44,6 +44,25 @@ async function fetchAccountFromApi(jwt, config, useWalletAuth) {
44
44
  }
45
45
  return json;
46
46
  }
47
+ async function updateRateLimitedAt(apiKeyId, config) {
48
+ const {
49
+ apiUrl,
50
+ serviceScope: scope,
51
+ serviceApiKey
52
+ } = config;
53
+ const url = `${apiUrl}/usage/rateLimit`;
54
+ await fetch(url, {
55
+ method: "PUT",
56
+ headers: {
57
+ "x-service-api-key": serviceApiKey,
58
+ "content-type": "application/json"
59
+ },
60
+ body: JSON.stringify({
61
+ apiKeyId,
62
+ scope
63
+ })
64
+ });
65
+ }
47
66
 
48
67
  function authorizeClient(authOptions, apiKeyMeta) {
49
68
  const {
@@ -63,7 +82,10 @@ function authorizeClient(authOptions, apiKeyMeta) {
63
82
  id: apiKeyMeta.accountId,
64
83
  // TODO update this later
65
84
  name: "",
66
- creatorWalletAddress: apiKeyMeta.creatorWalletAddress
85
+ creatorWalletAddress: apiKeyMeta.creatorWalletAddress,
86
+ limits: apiKeyMeta.limits,
87
+ rateLimits: apiKeyMeta.rateLimits,
88
+ usage: apiKeyMeta.usage
67
89
  }
68
90
  };
69
91
 
@@ -193,12 +215,15 @@ function authorizeService(apiKeyMetadata, serviceConfig, authorizationPayload) {
193
215
  }
194
216
  return {
195
217
  authorized: true,
218
+ apiKeyMeta: apiKeyMetadata,
196
219
  accountMeta: {
197
220
  id: apiKeyMetadata.accountId,
198
221
  name: "",
199
- creatorWalletAddress: apiKeyMetadata.creatorWalletAddress
200
- },
201
- apiKeyMeta: apiKeyMetadata
222
+ creatorWalletAddress: apiKeyMetadata.creatorWalletAddress,
223
+ limits: apiKeyMetadata.limits,
224
+ rateLimits: apiKeyMetadata.rateLimits,
225
+ usage: apiKeyMetadata.usage
226
+ }
202
227
  };
203
228
  }
204
229
 
@@ -416,9 +441,110 @@ async function authorize(authData, serviceConfig, cacheOptions) {
416
441
  id: apiKeyMeta.accountId,
417
442
  // TODO update this later
418
443
  name: "",
444
+ limits: apiKeyMeta.limits,
445
+ rateLimits: apiKeyMeta.rateLimits,
446
+ usage: apiKeyMeta.usage,
419
447
  creatorWalletAddress: apiKeyMeta.creatorWalletAddress
420
448
  }
421
449
  };
422
450
  }
423
451
 
452
+ const DEFAULT_RATE_LIMIT_WINDOW_SECONDS = 10;
453
+ const HARD_LIMIT_MULTIPLE = 2; // 2x of allowed limit
454
+
455
+ async function rateLimit(authzResult, serviceConfig, cacheOptions) {
456
+ if (!authzResult.authorized) {
457
+ return {
458
+ rateLimited: false
459
+ };
460
+ }
461
+ const {
462
+ apiKeyMeta,
463
+ accountMeta
464
+ } = authzResult;
465
+ const {
466
+ rateLimits
467
+ } = apiKeyMeta || accountMeta || {};
468
+ const accountId = apiKeyMeta?.accountId || accountMeta?.id;
469
+ const {
470
+ serviceScope
471
+ } = serviceConfig;
472
+ if (!rateLimits || !(serviceScope in rateLimits)) {
473
+ // No rate limit is provided. Assume the request is not rate limited.
474
+ return {
475
+ rateLimited: false
476
+ };
477
+ }
478
+ const limit = rateLimits[serviceScope];
479
+
480
+ // Floors the current time to the nearest DEFAULT_RATE_LIMIT_WINDOW_SECONDS.
481
+ const bucketId = Math.floor(Date.now() / (1000 * DEFAULT_RATE_LIMIT_WINDOW_SECONDS)) * DEFAULT_RATE_LIMIT_WINDOW_SECONDS;
482
+ const key = [serviceScope, accountId, bucketId].join(":");
483
+ const value = parseInt((await cacheOptions.get(key)) || "0");
484
+ const current = value + 1;
485
+
486
+ // limit is in seconds, but we need in DEFAULT_RATE_LIMIT_WINDOW_SECONDS
487
+ const limitWindow = limit * DEFAULT_RATE_LIMIT_WINDOW_SECONDS;
488
+ if (current > limitWindow) {
489
+ // report rate limit hits
490
+ if (apiKeyMeta?.id) {
491
+ await updateRateLimitedAt(apiKeyMeta.id, serviceConfig);
492
+ }
493
+
494
+ // actually rate limit only when reached hard limit
495
+ if (current > limitWindow * HARD_LIMIT_MULTIPLE) {
496
+ return {
497
+ rateLimited: true,
498
+ status: 429,
499
+ errorMessage: `You've exceeded your ${serviceScope} rate limit at ${limit} reqs/sec. To get higher rate limits, contact us at https://thirdweb.com/contact-us.`,
500
+ errorCode: "RATE_LIMIT_EXCEEDED"
501
+ };
502
+ }
503
+ } else {
504
+ await cacheOptions.put(key, current.toString());
505
+ }
506
+ return {
507
+ rateLimited: false
508
+ };
509
+ }
510
+
511
+ async function usageLimit(authzResult, serviceConfig) {
512
+ if (!authzResult.authorized) {
513
+ return {
514
+ usageLimited: false
515
+ };
516
+ }
517
+ const {
518
+ apiKeyMeta,
519
+ accountMeta
520
+ } = authzResult;
521
+ const {
522
+ limits,
523
+ usage
524
+ } = apiKeyMeta || accountMeta || {};
525
+ const {
526
+ serviceScope
527
+ } = serviceConfig;
528
+ if (!usage || !(serviceScope in usage) || !limits || !(serviceScope in limits)) {
529
+ // No usage limit is provided. Assume the request is not limited.
530
+ return {
531
+ usageLimited: false
532
+ };
533
+ }
534
+ const limit = limits.storage;
535
+ if (serviceScope === "storage" && (usage.storage?.sumFileSizeBytes || 0) > limit) {
536
+ return {
537
+ usageLimited: true,
538
+ status: 403,
539
+ errorMessage: `You've used all of your total usage limit for Storage Pinning. Please add your payment method at https://thirdweb.com/dashboard/settings/billing.`,
540
+ errorCode: "PAYMENT_METHOD_REQUIRED"
541
+ };
542
+ }
543
+ return {
544
+ usageLimited: false
545
+ };
546
+ }
547
+
424
548
  exports.authorize = authorize;
549
+ exports.rateLimit = rateLimit;
550
+ exports.usageLimit = usageLimit;
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var node_crypto = require('node:crypto');
6
- var index = require('../../dist/index-cd4f96ef.cjs.dev.js');
6
+ var index = require('../../dist/index-807f6a60.cjs.dev.js');
7
7
  var services = require('../../dist/services-a3f36057.cjs.dev.js');
8
8
 
9
9
  /**
@@ -150,29 +150,35 @@ function logHttpRequest(_ref) {
150
150
  isAuthed,
151
151
  statusMessage
152
152
  } = _ref;
153
- const authorizationData = extractAuthorizationData({
154
- req,
155
- clientId
156
- });
157
- const headers = req.headers;
158
- const _statusMessage = statusMessage ?? res.statusMessage;
159
- console.log(JSON.stringify({
160
- source,
161
- pathname: req.url,
162
- hasSecretKey: !!authorizationData.secretKey,
163
- hasClientId: !!authorizationData.clientId,
164
- hasJwt: !!authorizationData.jwt,
165
- clientId: authorizationData.clientId,
166
- isAuthed: !!isAuthed ?? null,
167
- status: res.statusCode,
168
- statusMessage: _statusMessage,
169
- sdkName: headers["x-sdk-name"] ?? "unknown",
170
- sdkVersion: headers["x-sdk-version"] ?? "unknown",
171
- platform: headers["x-sdk-platform"] ?? "unknown"
172
- }));
173
- console.log(`statusMessage=${_statusMessage}`);
153
+ try {
154
+ const authorizationData = extractAuthorizationData({
155
+ req,
156
+ clientId
157
+ });
158
+ const headers = req.headers;
159
+ const _statusMessage = statusMessage ?? res.statusMessage;
160
+ console.log(JSON.stringify({
161
+ source,
162
+ pathname: req.url,
163
+ hasSecretKey: !!authorizationData.secretKey,
164
+ hasClientId: !!authorizationData.clientId,
165
+ hasJwt: !!authorizationData.jwt,
166
+ clientId: authorizationData.clientId,
167
+ isAuthed: !!isAuthed ?? null,
168
+ status: res.statusCode,
169
+ statusMessage: _statusMessage,
170
+ sdkName: headers["x-sdk-name"] ?? "unknown",
171
+ sdkVersion: headers["x-sdk-version"] ?? "unknown",
172
+ platform: headers["x-sdk-platform"] ?? "unknown"
173
+ }));
174
+ console.log(`statusMessage=${_statusMessage}`);
175
+ } catch (err) {
176
+ console.error("Failed to log HTTP request:", err);
177
+ }
174
178
  }
175
179
 
180
+ exports.rateLimit = index.rateLimit;
181
+ exports.usageLimit = index.usageLimit;
176
182
  exports.SERVICES = services.SERVICES;
177
183
  exports.SERVICE_DEFINITIONS = services.SERVICE_DEFINITIONS;
178
184
  exports.SERVICE_NAMES = services.SERVICE_NAMES;
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var node_crypto = require('node:crypto');
6
- var index = require('../../dist/index-6e0ecc5f.cjs.prod.js');
6
+ var index = require('../../dist/index-cfc8027b.cjs.prod.js');
7
7
  var services = require('../../dist/services-9e185105.cjs.prod.js');
8
8
 
9
9
  /**
@@ -150,29 +150,35 @@ function logHttpRequest(_ref) {
150
150
  isAuthed,
151
151
  statusMessage
152
152
  } = _ref;
153
- const authorizationData = extractAuthorizationData({
154
- req,
155
- clientId
156
- });
157
- const headers = req.headers;
158
- const _statusMessage = statusMessage ?? res.statusMessage;
159
- console.log(JSON.stringify({
160
- source,
161
- pathname: req.url,
162
- hasSecretKey: !!authorizationData.secretKey,
163
- hasClientId: !!authorizationData.clientId,
164
- hasJwt: !!authorizationData.jwt,
165
- clientId: authorizationData.clientId,
166
- isAuthed: !!isAuthed ?? null,
167
- status: res.statusCode,
168
- statusMessage: _statusMessage,
169
- sdkName: headers["x-sdk-name"] ?? "unknown",
170
- sdkVersion: headers["x-sdk-version"] ?? "unknown",
171
- platform: headers["x-sdk-platform"] ?? "unknown"
172
- }));
173
- console.log(`statusMessage=${_statusMessage}`);
153
+ try {
154
+ const authorizationData = extractAuthorizationData({
155
+ req,
156
+ clientId
157
+ });
158
+ const headers = req.headers;
159
+ const _statusMessage = statusMessage ?? res.statusMessage;
160
+ console.log(JSON.stringify({
161
+ source,
162
+ pathname: req.url,
163
+ hasSecretKey: !!authorizationData.secretKey,
164
+ hasClientId: !!authorizationData.clientId,
165
+ hasJwt: !!authorizationData.jwt,
166
+ clientId: authorizationData.clientId,
167
+ isAuthed: !!isAuthed ?? null,
168
+ status: res.statusCode,
169
+ statusMessage: _statusMessage,
170
+ sdkName: headers["x-sdk-name"] ?? "unknown",
171
+ sdkVersion: headers["x-sdk-version"] ?? "unknown",
172
+ platform: headers["x-sdk-platform"] ?? "unknown"
173
+ }));
174
+ console.log(`statusMessage=${_statusMessage}`);
175
+ } catch (err) {
176
+ console.error("Failed to log HTTP request:", err);
177
+ }
174
178
  }
175
179
 
180
+ exports.rateLimit = index.rateLimit;
181
+ exports.usageLimit = index.usageLimit;
176
182
  exports.SERVICES = services.SERVICES;
177
183
  exports.SERVICE_DEFINITIONS = services.SERVICE_DEFINITIONS;
178
184
  exports.SERVICE_NAMES = services.SERVICE_NAMES;