@thirdweb-dev/service-utils 0.4.4 → 0.4.5-nightly-903145a4-20230918223433

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 +19 -5
  2. package/cf-worker/dist/thirdweb-dev-service-utils-cf-worker.cjs.prod.js +19 -5
  3. package/cf-worker/dist/thirdweb-dev-service-utils-cf-worker.esm.js +18 -6
  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 +3 -1
  27. package/node/dist/thirdweb-dev-service-utils-node.cjs.prod.js +3 -1
  28. package/node/dist/thirdweb-dev-service-utils-node.esm.js +2 -1
  29. package/package.json +2 -1
@@ -2,10 +2,10 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var index = require('../../dist/index-cd4f96ef.cjs.dev.js');
6
- var services = require('../../dist/services-a3f36057.cjs.dev.js');
5
+ var index = require('../../dist/index-807f6a60.cjs.dev.js');
7
6
  var aws4fetch = require('aws4fetch');
8
7
  var zod = require('zod');
8
+ var services = require('../../dist/services-a3f36057.cjs.dev.js');
9
9
 
10
10
  // Initialize a singleton for aws usage.
11
11
  let _aws;
@@ -20,7 +20,7 @@ function getAws(options) {
20
20
  * Types
21
21
  */
22
22
  const usageEventSchema = zod.z.object({
23
- source: zod.z.enum(["wallet", "rpc", "storage", "bundler", "paymaster", "relayer"]),
23
+ source: zod.z.enum(["embeddedWallets", "rpc", "storage", "bundler", "paymaster", "relayer"]),
24
24
  action: zod.z.string(),
25
25
  accountId: zod.z.string(),
26
26
  // Optional
@@ -33,10 +33,11 @@ const usageEventSchema = zod.z.object({
33
33
  mimeType: zod.z.string().optional(),
34
34
  fileSize: zod.z.number().int().nonnegative().optional(),
35
35
  fileCid: zod.z.string().optional(),
36
- transactionHash: zod.z.string().optional(),
36
+ evmMethod: zod.z.string().optional(),
37
+ userOpHash: zod.z.string().optional(),
37
38
  gasLimit: zod.z.number().nonnegative().optional(),
38
39
  gasPricePerUnit: zod.z.string().optional(),
39
- userOpHash: zod.z.string().optional()
40
+ transactionHash: zod.z.string().optional()
40
41
  });
41
42
  /**
42
43
  * Publish usage events. Provide the relevant fields for your application.
@@ -86,6 +87,8 @@ async function publishUsageEvents(usageEvents, config) {
86
87
  }
87
88
 
88
89
  const DEFAULT_CACHE_TTL_SECONDS = 60;
90
+ // must be > DEFAULT_RATE_LIMIT_WINDOW_SECONDS
91
+ const DEFAULT_RATE_LIMIT_CACHE_TTL_SECONDS = 60;
89
92
  async function authorizeWorker(authInput, serviceConfig) {
90
93
  let authData;
91
94
  try {
@@ -117,6 +120,14 @@ async function authorizeWorker(authInput, serviceConfig) {
117
120
  cacheTtlSeconds: serviceConfig.cacheTtlSeconds ?? DEFAULT_CACHE_TTL_SECONDS
118
121
  });
119
122
  }
123
+ async function rateLimitWorker(authzResult, serviceConfig) {
124
+ return await index.rateLimit(authzResult, serviceConfig, {
125
+ get: async bucketId => serviceConfig.kvStore.get(bucketId),
126
+ put: (bucketId, count) => serviceConfig.kvStore.put(bucketId, count, {
127
+ expirationTtl: DEFAULT_RATE_LIMIT_CACHE_TTL_SECONDS
128
+ })
129
+ });
130
+ }
120
131
  async function extractAuthorizationData(authInput) {
121
132
  const requestUrl = new URL(authInput.req.url);
122
133
  const headers = authInput.req.headers;
@@ -228,6 +239,8 @@ async function logHttpRequest(_ref) {
228
239
  console.log(`statusMessage=${statusMessage ?? res.statusText}`);
229
240
  }
230
241
 
242
+ exports.rateLimit = index.rateLimit;
243
+ exports.usageLimit = index.usageLimit;
231
244
  exports.SERVICES = services.SERVICES;
232
245
  exports.SERVICE_DEFINITIONS = services.SERVICE_DEFINITIONS;
233
246
  exports.SERVICE_NAMES = services.SERVICE_NAMES;
@@ -238,3 +251,4 @@ exports.extractAuthorizationData = extractAuthorizationData;
238
251
  exports.hashSecretKey = hashSecretKey;
239
252
  exports.logHttpRequest = logHttpRequest;
240
253
  exports.publishUsageEvents = publishUsageEvents;
254
+ exports.rateLimitWorker = rateLimitWorker;
@@ -2,10 +2,10 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var index = require('../../dist/index-6e0ecc5f.cjs.prod.js');
6
- var services = require('../../dist/services-9e185105.cjs.prod.js');
5
+ var index = require('../../dist/index-cfc8027b.cjs.prod.js');
7
6
  var aws4fetch = require('aws4fetch');
8
7
  var zod = require('zod');
8
+ var services = require('../../dist/services-9e185105.cjs.prod.js');
9
9
 
10
10
  // Initialize a singleton for aws usage.
11
11
  let _aws;
@@ -20,7 +20,7 @@ function getAws(options) {
20
20
  * Types
21
21
  */
22
22
  const usageEventSchema = zod.z.object({
23
- source: zod.z.enum(["wallet", "rpc", "storage", "bundler", "paymaster", "relayer"]),
23
+ source: zod.z.enum(["embeddedWallets", "rpc", "storage", "bundler", "paymaster", "relayer"]),
24
24
  action: zod.z.string(),
25
25
  accountId: zod.z.string(),
26
26
  // Optional
@@ -33,10 +33,11 @@ const usageEventSchema = zod.z.object({
33
33
  mimeType: zod.z.string().optional(),
34
34
  fileSize: zod.z.number().int().nonnegative().optional(),
35
35
  fileCid: zod.z.string().optional(),
36
- transactionHash: zod.z.string().optional(),
36
+ evmMethod: zod.z.string().optional(),
37
+ userOpHash: zod.z.string().optional(),
37
38
  gasLimit: zod.z.number().nonnegative().optional(),
38
39
  gasPricePerUnit: zod.z.string().optional(),
39
- userOpHash: zod.z.string().optional()
40
+ transactionHash: zod.z.string().optional()
40
41
  });
41
42
  /**
42
43
  * Publish usage events. Provide the relevant fields for your application.
@@ -86,6 +87,8 @@ async function publishUsageEvents(usageEvents, config) {
86
87
  }
87
88
 
88
89
  const DEFAULT_CACHE_TTL_SECONDS = 60;
90
+ // must be > DEFAULT_RATE_LIMIT_WINDOW_SECONDS
91
+ const DEFAULT_RATE_LIMIT_CACHE_TTL_SECONDS = 60;
89
92
  async function authorizeWorker(authInput, serviceConfig) {
90
93
  let authData;
91
94
  try {
@@ -117,6 +120,14 @@ async function authorizeWorker(authInput, serviceConfig) {
117
120
  cacheTtlSeconds: serviceConfig.cacheTtlSeconds ?? DEFAULT_CACHE_TTL_SECONDS
118
121
  });
119
122
  }
123
+ async function rateLimitWorker(authzResult, serviceConfig) {
124
+ return await index.rateLimit(authzResult, serviceConfig, {
125
+ get: async bucketId => serviceConfig.kvStore.get(bucketId),
126
+ put: (bucketId, count) => serviceConfig.kvStore.put(bucketId, count, {
127
+ expirationTtl: DEFAULT_RATE_LIMIT_CACHE_TTL_SECONDS
128
+ })
129
+ });
130
+ }
120
131
  async function extractAuthorizationData(authInput) {
121
132
  const requestUrl = new URL(authInput.req.url);
122
133
  const headers = authInput.req.headers;
@@ -228,6 +239,8 @@ async function logHttpRequest(_ref) {
228
239
  console.log(`statusMessage=${statusMessage ?? res.statusText}`);
229
240
  }
230
241
 
242
+ exports.rateLimit = index.rateLimit;
243
+ exports.usageLimit = index.usageLimit;
231
244
  exports.SERVICES = services.SERVICES;
232
245
  exports.SERVICE_DEFINITIONS = services.SERVICE_DEFINITIONS;
233
246
  exports.SERVICE_NAMES = services.SERVICE_NAMES;
@@ -238,3 +251,4 @@ exports.extractAuthorizationData = extractAuthorizationData;
238
251
  exports.hashSecretKey = hashSecretKey;
239
252
  exports.logHttpRequest = logHttpRequest;
240
253
  exports.publishUsageEvents = publishUsageEvents;
254
+ exports.rateLimitWorker = rateLimitWorker;
@@ -1,7 +1,8 @@
1
- import { a as authorize } from '../../dist/index-ffddf746.esm.js';
2
- export { b as SERVICES, S as SERVICE_DEFINITIONS, a as SERVICE_NAMES, g as getServiceByName } from '../../dist/services-86283509.esm.js';
1
+ import { a as authorize, r as rateLimit } from '../../dist/index-bcf68113.esm.js';
2
+ export { r as rateLimit, u as usageLimit } from '../../dist/index-bcf68113.esm.js';
3
3
  import { AwsClient } from 'aws4fetch';
4
4
  import { z } from 'zod';
5
+ export { b as SERVICES, S as SERVICE_DEFINITIONS, a as SERVICE_NAMES, g as getServiceByName } from '../../dist/services-86283509.esm.js';
5
6
 
6
7
  // Initialize a singleton for aws usage.
7
8
  let _aws;
@@ -16,7 +17,7 @@ function getAws(options) {
16
17
  * Types
17
18
  */
18
19
  const usageEventSchema = z.object({
19
- source: z.enum(["wallet", "rpc", "storage", "bundler", "paymaster", "relayer"]),
20
+ source: z.enum(["embeddedWallets", "rpc", "storage", "bundler", "paymaster", "relayer"]),
20
21
  action: z.string(),
21
22
  accountId: z.string(),
22
23
  // Optional
@@ -29,10 +30,11 @@ const usageEventSchema = z.object({
29
30
  mimeType: z.string().optional(),
30
31
  fileSize: z.number().int().nonnegative().optional(),
31
32
  fileCid: z.string().optional(),
32
- transactionHash: z.string().optional(),
33
+ evmMethod: z.string().optional(),
34
+ userOpHash: z.string().optional(),
33
35
  gasLimit: z.number().nonnegative().optional(),
34
36
  gasPricePerUnit: z.string().optional(),
35
- userOpHash: z.string().optional()
37
+ transactionHash: z.string().optional()
36
38
  });
37
39
  /**
38
40
  * Publish usage events. Provide the relevant fields for your application.
@@ -82,6 +84,8 @@ async function publishUsageEvents(usageEvents, config) {
82
84
  }
83
85
 
84
86
  const DEFAULT_CACHE_TTL_SECONDS = 60;
87
+ // must be > DEFAULT_RATE_LIMIT_WINDOW_SECONDS
88
+ const DEFAULT_RATE_LIMIT_CACHE_TTL_SECONDS = 60;
85
89
  async function authorizeWorker(authInput, serviceConfig) {
86
90
  let authData;
87
91
  try {
@@ -113,6 +117,14 @@ async function authorizeWorker(authInput, serviceConfig) {
113
117
  cacheTtlSeconds: serviceConfig.cacheTtlSeconds ?? DEFAULT_CACHE_TTL_SECONDS
114
118
  });
115
119
  }
120
+ async function rateLimitWorker(authzResult, serviceConfig) {
121
+ return await rateLimit(authzResult, serviceConfig, {
122
+ get: async bucketId => serviceConfig.kvStore.get(bucketId),
123
+ put: (bucketId, count) => serviceConfig.kvStore.put(bucketId, count, {
124
+ expirationTtl: DEFAULT_RATE_LIMIT_CACHE_TTL_SECONDS
125
+ })
126
+ });
127
+ }
116
128
  async function extractAuthorizationData(authInput) {
117
129
  const requestUrl = new URL(authInput.req.url);
118
130
  const headers = authInput.req.headers;
@@ -224,4 +236,4 @@ async function logHttpRequest(_ref) {
224
236
  console.log(`statusMessage=${statusMessage ?? res.statusText}`);
225
237
  }
226
238
 
227
- export { authorizeWorker, deriveClientIdFromSecretKeyHash, extractAuthorizationData, hashSecretKey, logHttpRequest, publishUsageEvents };
239
+ export { authorizeWorker, deriveClientIdFromSecretKeyHash, extractAuthorizationData, hashSecretKey, logHttpRequest, publishUsageEvents, rateLimitWorker };
@@ -3,10 +3,13 @@ import type { CoreServiceConfig } from "../core/api";
3
3
  import type { Request } from "@cloudflare/workers-types";
4
4
  import type { AuthorizationInput } from "../core/authorize";
5
5
  import type { AuthorizationResult } from "../core/authorize/types";
6
+ import type { RateLimitResult } from "../core/rateLimit/types";
6
7
  import type { CoreAuthInput } from "../core/types";
7
- export * from "../core/services";
8
8
  export * from "./usage";
9
- type WorkerServiceConfig = CoreServiceConfig & {
9
+ export * from "../core/services";
10
+ export * from "../core/rateLimit";
11
+ export * from "../core/usageLimit";
12
+ export type WorkerServiceConfig = CoreServiceConfig & {
10
13
  kvStore: KVNamespace;
11
14
  ctx: ExecutionContext;
12
15
  cacheTtlSeconds?: number;
@@ -15,6 +18,7 @@ type AuthInput = CoreAuthInput & {
15
18
  req: Request;
16
19
  };
17
20
  export declare function authorizeWorker(authInput: AuthInput, serviceConfig: WorkerServiceConfig): Promise<AuthorizationResult>;
21
+ export declare function rateLimitWorker(authzResult: AuthorizationResult, serviceConfig: WorkerServiceConfig): Promise<RateLimitResult>;
18
22
  export declare function extractAuthorizationData(authInput: AuthInput): Promise<AuthorizationInput>;
19
23
  export declare function hashSecretKey(secretKey: string): Promise<string>;
20
24
  export declare function deriveClientIdFromSecretKeyHash(secretKeyHash: string): string;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"../../../../src/cf-worker","sources":["index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gBAAgB,EAChB,WAAW,EACX,QAAQ,EACT,MAAM,2BAA2B,CAAC;AACnC,OAAO,KAAK,EAGV,iBAAiB,EAClB,MAAM,aAAa,CAAC;AAGrB,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAEnD,cAAc,kBAAkB,CAAC;AACjC,cAAc,SAAS,CAAC;AAExB,KAAK,mBAAmB,GAAG,iBAAiB,GAAG;IAC7C,OAAO,EAAE,WAAW,CAAC;IACrB,GAAG,EAAE,gBAAgB,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,CAAC;AAIF,KAAK,SAAS,GAAG,aAAa,GAAG;IAC/B,GAAG,EAAE,OAAO,CAAC;CACd,CAAC;AAEF,wBAAsB,eAAe,CACnC,SAAS,EAAE,SAAS,EACpB,aAAa,EAAE,mBAAmB,GACjC,OAAO,CAAC,mBAAmB,CAAC,CA0C9B;AAED,wBAAsB,wBAAwB,CAC5C,SAAS,EAAE,SAAS,GACnB,OAAO,CAAC,kBAAkB,CAAC,CA2E7B;AAED,wBAAsB,aAAa,CAAC,SAAS,EAAE,MAAM,mBAIpD;AAED,wBAAgB,+BAA+B,CAAC,aAAa,EAAE,MAAM,UAEpE;AAQD,wBAAsB,cAAc,CAAC,EACnC,MAAM,EACN,QAAQ,EACR,GAAG,EACH,GAAG,EACH,QAAQ,EACR,aAAa,GACd,EAAE,SAAS,GAAG;IACb,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,QAAQ,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,aAAa,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;CAChC,iBAoBA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"../../../../src/cf-worker","sources":["index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gBAAgB,EAChB,WAAW,EACX,QAAQ,EACT,MAAM,2BAA2B,CAAC;AACnC,OAAO,KAAK,EAGV,iBAAiB,EAClB,MAAM,aAAa,CAAC;AAGrB,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAGnD,cAAc,SAAS,CAAC;AACxB,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AAEnC,MAAM,MAAM,mBAAmB,GAAG,iBAAiB,GAAG;IACpD,OAAO,EAAE,WAAW,CAAC;IACrB,GAAG,EAAE,gBAAgB,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,CAAC;AAMF,KAAK,SAAS,GAAG,aAAa,GAAG;IAC/B,GAAG,EAAE,OAAO,CAAC;CACd,CAAC;AAEF,wBAAsB,eAAe,CACnC,SAAS,EAAE,SAAS,EACpB,aAAa,EAAE,mBAAmB,GACjC,OAAO,CAAC,mBAAmB,CAAC,CA0C9B;AAED,wBAAsB,eAAe,CACnC,WAAW,EAAE,mBAAmB,EAChC,aAAa,EAAE,mBAAmB,GACjC,OAAO,CAAC,eAAe,CAAC,CAQ1B;AAED,wBAAsB,wBAAwB,CAC5C,SAAS,EAAE,SAAS,GACnB,OAAO,CAAC,kBAAkB,CAAC,CA2E7B;AAED,wBAAsB,aAAa,CAAC,SAAS,EAAE,MAAM,mBAIpD;AAED,wBAAgB,+BAA+B,CAAC,aAAa,EAAE,MAAM,UAEpE;AAQD,wBAAsB,cAAc,CAAC,EACnC,MAAM,EACN,QAAQ,EACR,GAAG,EACH,GAAG,EACH,QAAQ,EACR,aAAa,GACd,EAAE,SAAS,GAAG;IACb,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,QAAQ,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,aAAa,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;CAChC,iBAoBA"}
@@ -3,7 +3,7 @@ import { z } from "zod";
3
3
  * Types
4
4
  */
5
5
  declare const usageEventSchema: z.ZodObject<{
6
- source: z.ZodEnum<["wallet", "rpc", "storage", "bundler", "paymaster", "relayer"]>;
6
+ source: z.ZodEnum<["embeddedWallets", "rpc", "storage", "bundler", "paymaster", "relayer"]>;
7
7
  action: z.ZodString;
8
8
  accountId: z.ZodString;
9
9
  apiKeyId: z.ZodOptional<z.ZodString>;
@@ -15,14 +15,15 @@ declare const usageEventSchema: z.ZodObject<{
15
15
  mimeType: z.ZodOptional<z.ZodString>;
16
16
  fileSize: z.ZodOptional<z.ZodNumber>;
17
17
  fileCid: z.ZodOptional<z.ZodString>;
18
- transactionHash: z.ZodOptional<z.ZodString>;
18
+ evmMethod: z.ZodOptional<z.ZodString>;
19
+ userOpHash: z.ZodOptional<z.ZodString>;
19
20
  gasLimit: z.ZodOptional<z.ZodNumber>;
20
21
  gasPricePerUnit: z.ZodOptional<z.ZodString>;
21
- userOpHash: z.ZodOptional<z.ZodString>;
22
+ transactionHash: z.ZodOptional<z.ZodString>;
22
23
  }, "strip", z.ZodTypeAny, {
23
- source: "storage" | "rpc" | "bundler" | "relayer" | "wallet" | "paymaster";
24
- action: string;
24
+ source: "storage" | "rpc" | "bundler" | "relayer" | "embeddedWallets" | "paymaster";
25
25
  accountId: string;
26
+ action: string;
26
27
  apiKeyId?: string | undefined;
27
28
  creatorWalletAddress?: string | undefined;
28
29
  clientId?: string | undefined;
@@ -32,14 +33,15 @@ declare const usageEventSchema: z.ZodObject<{
32
33
  mimeType?: string | undefined;
33
34
  fileSize?: number | undefined;
34
35
  fileCid?: string | undefined;
35
- transactionHash?: string | undefined;
36
+ evmMethod?: string | undefined;
37
+ userOpHash?: string | undefined;
36
38
  gasLimit?: number | undefined;
37
39
  gasPricePerUnit?: string | undefined;
38
- userOpHash?: string | undefined;
40
+ transactionHash?: string | undefined;
39
41
  }, {
40
- source: "storage" | "rpc" | "bundler" | "relayer" | "wallet" | "paymaster";
41
- action: string;
42
+ source: "storage" | "rpc" | "bundler" | "relayer" | "embeddedWallets" | "paymaster";
42
43
  accountId: string;
44
+ action: string;
43
45
  apiKeyId?: string | undefined;
44
46
  creatorWalletAddress?: string | undefined;
45
47
  clientId?: string | undefined;
@@ -49,10 +51,11 @@ declare const usageEventSchema: z.ZodObject<{
49
51
  mimeType?: string | undefined;
50
52
  fileSize?: number | undefined;
51
53
  fileCid?: string | undefined;
52
- transactionHash?: string | undefined;
54
+ evmMethod?: string | undefined;
55
+ userOpHash?: string | undefined;
53
56
  gasLimit?: number | undefined;
54
57
  gasPricePerUnit?: string | undefined;
55
- userOpHash?: string | undefined;
58
+ transactionHash?: string | undefined;
56
59
  }>;
57
60
  export type UsageEvent = z.infer<typeof usageEventSchema>;
58
61
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"usage.d.ts","sourceRoot":"../../../../src/cf-worker","sources":["usage.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAWxB;;GAEG;AACH,QAAA,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA0BpB,CAAC;AACH,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE1D;;;;;;;;;;;;;GAaG;AACH,wBAAsB,kBAAkB,CACtC,WAAW,EAAE,UAAU,EAAE,EACzB,MAAM,EAAE;IACN,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,GACA,OAAO,CAAC,IAAI,CAAC,CAiCf"}
1
+ {"version":3,"file":"usage.d.ts","sourceRoot":"../../../../src/cf-worker","sources":["usage.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAWxB;;GAEG;AACH,QAAA,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA2BpB,CAAC;AACH,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE1D;;;;;;;;;;;;;GAaG;AACH,wBAAsB,kBAAkB,CACtC,WAAW,EAAE,UAAU,EAAE,EACzB,MAAM,EAAE;IACN,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,GACA,OAAO,CAAC,IAAI,CAAC,CAiCf"}
@@ -1,12 +1,20 @@
1
1
  import type { ServiceName } from "./services";
2
2
  export type CoreServiceConfig = {
3
- enforceAuth: boolean;
3
+ enforceAuth?: boolean;
4
4
  apiUrl: string;
5
5
  serviceScope: ServiceName;
6
6
  serviceApiKey: string;
7
7
  serviceAction?: string;
8
8
  useWalletAuth?: boolean;
9
9
  };
10
+ type Usage = {
11
+ storage?: {
12
+ sumFileSizeBytes: number;
13
+ };
14
+ embeddedWallets?: {
15
+ countWalletAddresses: number;
16
+ };
17
+ };
10
18
  export type ApiKeyMetadata = {
11
19
  id: string;
12
20
  key: string;
@@ -23,11 +31,17 @@ export type ApiKeyMetadata = {
23
31
  targetAddresses: string[];
24
32
  actions: string[];
25
33
  }[];
34
+ usage?: Usage;
35
+ limits: Partial<Record<ServiceName, number>>;
36
+ rateLimits: Partial<Record<ServiceName, number>>;
26
37
  };
27
38
  export type AccountMetadata = {
28
39
  id: string;
29
40
  name: string;
30
41
  creatorWalletAddress: string;
42
+ usage?: Usage;
43
+ limits: Partial<Record<ServiceName, number>>;
44
+ rateLimits: Partial<Record<ServiceName, number>>;
31
45
  };
32
46
  export type ApiResponse = {
33
47
  data: ApiKeyMetadata | null;
@@ -47,4 +61,6 @@ export type ApiAccountResponse = {
47
61
  };
48
62
  export declare function fetchKeyMetadataFromApi(clientId: string, config: CoreServiceConfig): Promise<ApiResponse>;
49
63
  export declare function fetchAccountFromApi(jwt: string, config: CoreServiceConfig, useWalletAuth: boolean): Promise<ApiAccountResponse>;
64
+ export declare function updateRateLimitedAt(apiKeyId: string, config: CoreServiceConfig): Promise<void>;
65
+ export {};
50
66
  //# sourceMappingURL=api.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"api.d.ts","sourceRoot":"../../../../src/core","sources":["api.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAG9C,MAAM,MAAM,iBAAiB,GAAG;IAC9B,WAAW,EAAE,OAAO,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,WAAW,CAAC;IAC1B,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,YAAY,GAAG,WAAW,GAAG,cAAc,GAAG,gBAAgB,CAAC;IAC9E,WAAW,EAAE,MAAM,GAAG,YAAY,CAAC;IACnC,oBAAoB,EAAE,MAAM,CAAC;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,QAAQ,EAAE;QACR,IAAI,EAAE,MAAM,CAAC;QACb,eAAe,EAAE,MAAM,EAAE,CAAC;QAC1B,OAAO,EAAE,MAAM,EAAE,CAAC;KACnB,EAAE,CAAC;CACL,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,oBAAoB,EAAE,MAAM,CAAC;CAC9B,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,EAAE,cAAc,GAAG,IAAI,CAAC;IAC5B,KAAK,EAAE;QACL,IAAI,EAAE,MAAM,CAAC;QACb,UAAU,EAAE,MAAM,CAAC;QACnB,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,IAAI,EAAE,eAAe,GAAG,IAAI,CAAC;IAC7B,KAAK,EAAE;QACL,IAAI,EAAE,MAAM,CAAC;QACb,UAAU,EAAE,MAAM,CAAC;QACnB,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;CACH,CAAC;AAEF,wBAAsB,uBAAuB,CAC3C,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,iBAAiB,GACxB,OAAO,CAAC,WAAW,CAAC,CAqBtB;AAED,wBAAsB,mBAAmB,CACvC,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,iBAAiB,EACzB,aAAa,EAAE,OAAO,GACrB,OAAO,CAAC,kBAAkB,CAAC,CAwB7B"}
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"../../../../src/core","sources":["api.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,MAAM,MAAM,iBAAiB,GAAG;IAC9B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,WAAW,CAAC;IAC1B,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB,CAAC;AAEF,KAAK,KAAK,GAAG;IACX,OAAO,CAAC,EAAE;QACR,gBAAgB,EAAE,MAAM,CAAC;KAC1B,CAAC;IACF,eAAe,CAAC,EAAE;QAChB,oBAAoB,EAAE,MAAM,CAAC;KAC9B,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,YAAY,GAAG,WAAW,GAAG,cAAc,GAAG,gBAAgB,CAAC;IAC9E,WAAW,EAAE,MAAM,GAAG,YAAY,CAAC;IACnC,oBAAoB,EAAE,MAAM,CAAC;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,QAAQ,EAAE;QACR,IAAI,EAAE,MAAM,CAAC;QACb,eAAe,EAAE,MAAM,EAAE,CAAC;QAC1B,OAAO,EAAE,MAAM,EAAE,CAAC;KACnB,EAAE,CAAC;IACJ,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC,CAAC;IAC7C,UAAU,EAAE,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC,CAAC;CAClD,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,oBAAoB,EAAE,MAAM,CAAC;IAC7B,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC,CAAC;IAC7C,UAAU,EAAE,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC,CAAC;CAClD,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,EAAE,cAAc,GAAG,IAAI,CAAC;IAC5B,KAAK,EAAE;QACL,IAAI,EAAE,MAAM,CAAC;QACb,UAAU,EAAE,MAAM,CAAC;QACnB,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,IAAI,EAAE,eAAe,GAAG,IAAI,CAAC;IAC7B,KAAK,EAAE;QACL,IAAI,EAAE,MAAM,CAAC;QACb,UAAU,EAAE,MAAM,CAAC;QACnB,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;CACH,CAAC;AAEF,wBAAsB,uBAAuB,CAC3C,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,iBAAiB,GACxB,OAAO,CAAC,WAAW,CAAC,CAqBtB;AAED,wBAAsB,mBAAmB,CACvC,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,iBAAiB,EACzB,aAAa,EAAE,OAAO,GACrB,OAAO,CAAC,kBAAkB,CAAC,CAwB7B;AAED,wBAAsB,mBAAmB,CACvC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,iBAAiB,GACxB,OAAO,CAAC,IAAI,CAAC,CAgBf"}
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"../../../../../src/core/authorize","sources":["client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AAC7C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAEnD,MAAM,MAAM,0BAA0B,GAAG;IACvC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB,CAAC;AAEF,wBAAgB,eAAe,CAC7B,WAAW,EAAE,0BAA0B,EACvC,UAAU,EAAE,cAAc,GACzB,mBAAmB,CAwGrB"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"../../../../../src/core/authorize","sources":["client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AAC7C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAEnD,MAAM,MAAM,0BAA0B,GAAG;IACvC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB,CAAC;AAEF,wBAAgB,eAAe,CAC7B,WAAW,EAAE,0BAA0B,EACvC,UAAU,EAAE,cAAc,GACzB,mBAAmB,CA2GrB"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"../../../../../src/core/authorize","sources":["index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,cAAc,EACd,iBAAiB,EAGlB,MAAM,QAAQ,CAAC;AAGhB,OAAO,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAE9C,MAAM,MAAM,kBAAkB,GAAG;IAC/B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAElC,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B,CAAC;AAEF,KAAK,YAAY,GAAG;IAClB,GAAG,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAClD,GAAG,EAAE,CACH,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,cAAc,GAAG,eAAe,KACnC,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAC1B,eAAe,EAAE,MAAM,CAAC;CACzB,CAAC;AAgBF,wBAAsB,SAAS,CAC7B,QAAQ,EAAE,kBAAkB,EAC5B,aAAa,EAAE,iBAAiB,EAChC,YAAY,CAAC,EAAE,YAAY,GAC1B,OAAO,CAAC,mBAAmB,CAAC,CAmN9B"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"../../../../../src/core/authorize","sources":["index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,cAAc,EACd,iBAAiB,EAGlB,MAAM,QAAQ,CAAC;AAGhB,OAAO,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAE9C,MAAM,MAAM,kBAAkB,GAAG;IAC/B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAElC,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B,CAAC;AAEF,KAAK,YAAY,GAAG;IAClB,GAAG,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAClD,GAAG,EAAE,CACH,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,cAAc,GAAG,eAAe,KACnC,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAC1B,eAAe,EAAE,MAAM,CAAC;CACzB,CAAC;AAgBF,wBAAsB,SAAS,CAC7B,QAAQ,EAAE,kBAAkB,EAC5B,aAAa,EAAE,iBAAiB,EAChC,YAAY,CAAC,EAAE,YAAY,GAC1B,OAAO,CAAC,mBAAmB,CAAC,CAsN9B"}
@@ -1 +1 @@
1
- {"version":3,"file":"service.d.ts","sourceRoot":"../../../../../src/core/authorize","sources":["service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,QAAQ,CAAC;AAC3D,OAAO,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAE9C,MAAM,MAAM,2BAA2B,GAAG;IAAE,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;CAAE,CAAC;AAEhF,wBAAgB,gBAAgB,CAC9B,cAAc,EAAE,cAAc,EAC9B,aAAa,EAAE,iBAAiB,EAChC,oBAAoB,CAAC,EAAE,2BAA2B,GACjD,mBAAmB,CA6DrB"}
1
+ {"version":3,"file":"service.d.ts","sourceRoot":"../../../../../src/core/authorize","sources":["service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,QAAQ,CAAC;AAC3D,OAAO,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAE9C,MAAM,MAAM,2BAA2B,GAAG;IAAE,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;CAAE,CAAC;AAEhF,wBAAgB,gBAAgB,CAC9B,cAAc,EAAE,cAAc,EAC9B,aAAa,EAAE,iBAAiB,EAChC,oBAAoB,CAAC,EAAE,2BAA2B,GACjD,mBAAmB,CAgErB"}
@@ -0,0 +1,10 @@
1
+ import { CoreServiceConfig } from "../api";
2
+ import { AuthorizationResult } from "../authorize/types";
3
+ import { RateLimitResult } from "./types";
4
+ type CacheOptions = {
5
+ get: (bucketId: string) => Promise<string | null>;
6
+ put: (bucketId: string, count: string) => Promise<void> | void;
7
+ };
8
+ export declare function rateLimit(authzResult: AuthorizationResult, serviceConfig: CoreServiceConfig, cacheOptions: CacheOptions): Promise<RateLimitResult>;
9
+ export {};
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"../../../../../src/core/rateLimit","sources":["index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAuB,MAAM,QAAQ,CAAC;AAChE,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAEzD,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAK1C,KAAK,YAAY,GAAG;IAClB,GAAG,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAClD,GAAG,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CAChE,CAAC;AAEF,wBAAsB,SAAS,CAC7B,WAAW,EAAE,mBAAmB,EAChC,aAAa,EAAE,iBAAiB,EAChC,YAAY,EAAE,YAAY,GACzB,OAAO,CAAC,eAAe,CAAC,CAuD1B"}
@@ -0,0 +1,9 @@
1
+ export type RateLimitResult = {
2
+ rateLimited: false;
3
+ } | {
4
+ rateLimited: true;
5
+ status: number;
6
+ errorMessage: string;
7
+ errorCode: string;
8
+ };
9
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"../../../../../src/core/rateLimit","sources":["types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,eAAe,GACvB;IACE,WAAW,EAAE,KAAK,CAAC;CACpB,GACD;IACE,WAAW,EAAE,IAAI,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC"}
@@ -0,0 +1,5 @@
1
+ import { CoreServiceConfig } from "../api";
2
+ import { AuthorizationResult } from "../authorize/types";
3
+ import { UsageLimitResult } from "./types";
4
+ export declare function usageLimit(authzResult: AuthorizationResult, serviceConfig: CoreServiceConfig): Promise<UsageLimitResult>;
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"../../../../../src/core/usageLimit","sources":["index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,QAAQ,CAAC;AAC3C,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAEzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAE3C,wBAAsB,UAAU,CAC9B,WAAW,EAAE,mBAAmB,EAChC,aAAa,EAAE,iBAAiB,GAC/B,OAAO,CAAC,gBAAgB,CAAC,CAwC3B"}
@@ -0,0 +1,9 @@
1
+ export type UsageLimitResult = {
2
+ usageLimited: false;
3
+ } | {
4
+ usageLimited: true;
5
+ status: number;
6
+ errorMessage: string;
7
+ errorCode: string;
8
+ };
9
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"../../../../../src/core/usageLimit","sources":["types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,gBAAgB,GACxB;IACE,YAAY,EAAE,KAAK,CAAC;CACrB,GACD;IACE,YAAY,EAAE,IAAI,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC"}
@@ -6,6 +6,8 @@ import type { AuthorizationInput } from "../core/authorize";
6
6
  import type { AuthorizationResult } from "../core/authorize/types";
7
7
  import type { CoreAuthInput } from "../core/types";
8
8
  export * from "../core/services";
9
+ export * from "../core/rateLimit";
10
+ export * from "../core/usageLimit";
9
11
  type NodeServiceConfig = CoreServiceConfig;
10
12
  export type AuthInput = CoreAuthInput & {
11
13
  req: IncomingMessage;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"../../../../src/node","sources":["index.ts"],"names":[],"mappings":";AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,MAAM,CAAC;AAC3C,OAAO,KAAK,EAAuB,eAAe,EAAE,MAAM,WAAW,CAAC;AACtE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAEnD,cAAc,kBAAkB,CAAC;AAEjC,KAAK,iBAAiB,GAAG,iBAAiB,CAAC;AAE3C,MAAM,MAAM,SAAS,GAAG,aAAa,GAAG;IACtC,GAAG,EAAE,eAAe,CAAC;CACtB,CAAC;AAEF;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,aAAa,CACjC,SAAS,EAAE,SAAS,EACpB,aAAa,EAAE,iBAAiB,GAC/B,OAAO,CAAC,mBAAmB,CAAC,CAsB9B;AAaD,wBAAgB,wBAAwB,CACtC,SAAS,EAAE,SAAS,GACnB,kBAAkB,CA2FpB;AAED,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,UAE9C;AAED,wBAAgB,+BAA+B,CAAC,aAAa,EAAE,MAAM,UAEpE;AAED,wBAAgB,cAAc,CAAC,EAC7B,MAAM,EACN,QAAQ,EACR,GAAG,EACH,GAAG,EACH,QAAQ,EACR,aAAa,GACd,EAAE,SAAS,GAAG;IACb,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,cAAc,CAAC;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,aAAa,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;CAChC,QAsBA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"../../../../src/node","sources":["index.ts"],"names":[],"mappings":";AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,MAAM,CAAC;AAC3C,OAAO,KAAK,EAAuB,eAAe,EAAE,MAAM,WAAW,CAAC;AACtE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAEnD,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AAEnC,KAAK,iBAAiB,GAAG,iBAAiB,CAAC;AAE3C,MAAM,MAAM,SAAS,GAAG,aAAa,GAAG;IACtC,GAAG,EAAE,eAAe,CAAC;CACtB,CAAC;AAEF;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,aAAa,CACjC,SAAS,EAAE,SAAS,EACpB,aAAa,EAAE,iBAAiB,GAC/B,OAAO,CAAC,mBAAmB,CAAC,CAsB9B;AAaD,wBAAgB,wBAAwB,CACtC,SAAS,EAAE,SAAS,GACnB,kBAAkB,CA2FpB;AAED,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,UAE9C;AAED,wBAAgB,+BAA+B,CAAC,aAAa,EAAE,MAAM,UAEpE;AAED,wBAAgB,cAAc,CAAC,EAC7B,MAAM,EACN,QAAQ,EACR,GAAG,EACH,GAAG,EACH,QAAQ,EACR,aAAa,GACd,EAAE,SAAS,GAAG;IACb,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,cAAc,CAAC;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,aAAa,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;CAChC,QAsBA"}
@@ -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
  /**
@@ -173,6 +173,8 @@ function logHttpRequest(_ref) {
173
173
  console.log(`statusMessage=${_statusMessage}`);
174
174
  }
175
175
 
176
+ exports.rateLimit = index.rateLimit;
177
+ exports.usageLimit = index.usageLimit;
176
178
  exports.SERVICES = services.SERVICES;
177
179
  exports.SERVICE_DEFINITIONS = services.SERVICE_DEFINITIONS;
178
180
  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
  /**
@@ -173,6 +173,8 @@ function logHttpRequest(_ref) {
173
173
  console.log(`statusMessage=${_statusMessage}`);
174
174
  }
175
175
 
176
+ exports.rateLimit = index.rateLimit;
177
+ exports.usageLimit = index.usageLimit;
176
178
  exports.SERVICES = services.SERVICES;
177
179
  exports.SERVICE_DEFINITIONS = services.SERVICE_DEFINITIONS;
178
180
  exports.SERVICE_NAMES = services.SERVICE_NAMES;
@@ -1,5 +1,6 @@
1
1
  import { createHash } from 'node:crypto';
2
- import { a as authorize } from '../../dist/index-ffddf746.esm.js';
2
+ import { a as authorize } from '../../dist/index-bcf68113.esm.js';
3
+ export { r as rateLimit, u as usageLimit } from '../../dist/index-bcf68113.esm.js';
3
4
  export { b as SERVICES, S as SERVICE_DEFINITIONS, a as SERVICE_NAMES, g as getServiceByName } from '../../dist/services-86283509.esm.js';
4
5
 
5
6
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thirdweb-dev/service-utils",
3
- "version": "0.4.4",
3
+ "version": "0.4.5-nightly-903145a4-20230918223433",
4
4
  "main": "dist/thirdweb-dev-service-utils.cjs.js",
5
5
  "module": "dist/thirdweb-dev-service-utils.esm.js",
6
6
  "exports": {
@@ -52,6 +52,7 @@
52
52
  "eslint-config-thirdweb": "^0.1.6",
53
53
  "jest": "^29.6.2",
54
54
  "prettier": "^3.0.0",
55
+ "ts-jest": "^29.1.1",
55
56
  "typescript": "^5.1.6"
56
57
  },
57
58
  "dependencies": {