@thirdweb-dev/service-utils 0.0.0-dev-d86829b-20230927000710 → 0.0.0-dev-29cb324-20231008112502

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.
@@ -2,7 +2,7 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var index = require('../../dist/index-807f6a60.cjs.dev.js');
5
+ var index = require('../../dist/index-18abcc30.cjs.dev.js');
6
6
  var aws4fetch = require('aws4fetch');
7
7
  var zod = require('zod');
8
8
  var services = require('../../dist/services-79b4664f.cjs.dev.js');
@@ -20,10 +20,14 @@ function getAws(options) {
20
20
  * Types
21
21
  */
22
22
  const usageEventSchema = zod.z.object({
23
- source: zod.z.enum(["embeddedWallets", "rpc", "storage", "bundler", "paymaster", "relayer"]),
23
+ source: zod.z.enum(["embeddedWallets", "rpc", "storage", "bundler", "paymaster", "relayer", "connectWallet"]),
24
24
  action: zod.z.string(),
25
- accountId: zod.z.string(),
26
- // Optional
25
+ /**
26
+ * The following fields are optional.
27
+ */
28
+
29
+ accountId: zod.z.string().optional(),
30
+ isClientEvent: zod.z.boolean().optional(),
27
31
  apiKeyId: zod.z.string().optional(),
28
32
  creatorWalletAddress: zod.z.string().optional(),
29
33
  clientId: zod.z.string().optional(),
@@ -91,8 +95,6 @@ async function publishUsageEvents(usageEvents, config) {
91
95
  }
92
96
 
93
97
  const DEFAULT_CACHE_TTL_SECONDS = 60;
94
- // must be > DEFAULT_RATE_LIMIT_WINDOW_SECONDS
95
- const DEFAULT_RATE_LIMIT_CACHE_TTL_SECONDS = 60;
96
98
  async function authorizeWorker(authInput, serviceConfig) {
97
99
  let authData;
98
100
  try {
@@ -124,14 +126,6 @@ async function authorizeWorker(authInput, serviceConfig) {
124
126
  cacheTtlSeconds: serviceConfig.cacheTtlSeconds ?? DEFAULT_CACHE_TTL_SECONDS
125
127
  });
126
128
  }
127
- async function rateLimitWorker(authzResult, serviceConfig) {
128
- return await index.rateLimit(authzResult, serviceConfig, {
129
- get: async bucketId => serviceConfig.kvStore.get(bucketId),
130
- put: (bucketId, count) => serviceConfig.kvStore.put(bucketId, count, {
131
- expirationTtl: DEFAULT_RATE_LIMIT_CACHE_TTL_SECONDS
132
- })
133
- });
134
- }
135
129
  async function extractAuthorizationData(authInput) {
136
130
  const requestUrl = new URL(authInput.req.url);
137
131
  const headers = authInput.req.headers;
@@ -259,4 +253,3 @@ exports.extractAuthorizationData = extractAuthorizationData;
259
253
  exports.hashSecretKey = hashSecretKey;
260
254
  exports.logHttpRequest = logHttpRequest;
261
255
  exports.publishUsageEvents = publishUsageEvents;
262
- exports.rateLimitWorker = rateLimitWorker;
@@ -2,7 +2,7 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var index = require('../../dist/index-cfc8027b.cjs.prod.js');
5
+ var index = require('../../dist/index-aac16290.cjs.prod.js');
6
6
  var aws4fetch = require('aws4fetch');
7
7
  var zod = require('zod');
8
8
  var services = require('../../dist/services-04997839.cjs.prod.js');
@@ -20,10 +20,14 @@ function getAws(options) {
20
20
  * Types
21
21
  */
22
22
  const usageEventSchema = zod.z.object({
23
- source: zod.z.enum(["embeddedWallets", "rpc", "storage", "bundler", "paymaster", "relayer"]),
23
+ source: zod.z.enum(["embeddedWallets", "rpc", "storage", "bundler", "paymaster", "relayer", "connectWallet"]),
24
24
  action: zod.z.string(),
25
- accountId: zod.z.string(),
26
- // Optional
25
+ /**
26
+ * The following fields are optional.
27
+ */
28
+
29
+ accountId: zod.z.string().optional(),
30
+ isClientEvent: zod.z.boolean().optional(),
27
31
  apiKeyId: zod.z.string().optional(),
28
32
  creatorWalletAddress: zod.z.string().optional(),
29
33
  clientId: zod.z.string().optional(),
@@ -91,8 +95,6 @@ async function publishUsageEvents(usageEvents, config) {
91
95
  }
92
96
 
93
97
  const DEFAULT_CACHE_TTL_SECONDS = 60;
94
- // must be > DEFAULT_RATE_LIMIT_WINDOW_SECONDS
95
- const DEFAULT_RATE_LIMIT_CACHE_TTL_SECONDS = 60;
96
98
  async function authorizeWorker(authInput, serviceConfig) {
97
99
  let authData;
98
100
  try {
@@ -124,14 +126,6 @@ async function authorizeWorker(authInput, serviceConfig) {
124
126
  cacheTtlSeconds: serviceConfig.cacheTtlSeconds ?? DEFAULT_CACHE_TTL_SECONDS
125
127
  });
126
128
  }
127
- async function rateLimitWorker(authzResult, serviceConfig) {
128
- return await index.rateLimit(authzResult, serviceConfig, {
129
- get: async bucketId => serviceConfig.kvStore.get(bucketId),
130
- put: (bucketId, count) => serviceConfig.kvStore.put(bucketId, count, {
131
- expirationTtl: DEFAULT_RATE_LIMIT_CACHE_TTL_SECONDS
132
- })
133
- });
134
- }
135
129
  async function extractAuthorizationData(authInput) {
136
130
  const requestUrl = new URL(authInput.req.url);
137
131
  const headers = authInput.req.headers;
@@ -259,4 +253,3 @@ exports.extractAuthorizationData = extractAuthorizationData;
259
253
  exports.hashSecretKey = hashSecretKey;
260
254
  exports.logHttpRequest = logHttpRequest;
261
255
  exports.publishUsageEvents = publishUsageEvents;
262
- exports.rateLimitWorker = rateLimitWorker;
@@ -1,5 +1,5 @@
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';
1
+ import { a as authorize } from '../../dist/index-b140304d.esm.js';
2
+ export { r as rateLimit, u as usageLimit } from '../../dist/index-b140304d.esm.js';
3
3
  import { AwsClient } from 'aws4fetch';
4
4
  import { z } from 'zod';
5
5
  export { b as SERVICES, S as SERVICE_DEFINITIONS, a as SERVICE_NAMES, g as getServiceByName } from '../../dist/services-bc12a5f6.esm.js';
@@ -17,10 +17,14 @@ function getAws(options) {
17
17
  * Types
18
18
  */
19
19
  const usageEventSchema = z.object({
20
- source: z.enum(["embeddedWallets", "rpc", "storage", "bundler", "paymaster", "relayer"]),
20
+ source: z.enum(["embeddedWallets", "rpc", "storage", "bundler", "paymaster", "relayer", "connectWallet"]),
21
21
  action: z.string(),
22
- accountId: z.string(),
23
- // Optional
22
+ /**
23
+ * The following fields are optional.
24
+ */
25
+
26
+ accountId: z.string().optional(),
27
+ isClientEvent: z.boolean().optional(),
24
28
  apiKeyId: z.string().optional(),
25
29
  creatorWalletAddress: z.string().optional(),
26
30
  clientId: z.string().optional(),
@@ -88,8 +92,6 @@ async function publishUsageEvents(usageEvents, config) {
88
92
  }
89
93
 
90
94
  const DEFAULT_CACHE_TTL_SECONDS = 60;
91
- // must be > DEFAULT_RATE_LIMIT_WINDOW_SECONDS
92
- const DEFAULT_RATE_LIMIT_CACHE_TTL_SECONDS = 60;
93
95
  async function authorizeWorker(authInput, serviceConfig) {
94
96
  let authData;
95
97
  try {
@@ -121,14 +123,6 @@ async function authorizeWorker(authInput, serviceConfig) {
121
123
  cacheTtlSeconds: serviceConfig.cacheTtlSeconds ?? DEFAULT_CACHE_TTL_SECONDS
122
124
  });
123
125
  }
124
- async function rateLimitWorker(authzResult, serviceConfig) {
125
- return await rateLimit(authzResult, serviceConfig, {
126
- get: async bucketId => serviceConfig.kvStore.get(bucketId),
127
- put: (bucketId, count) => serviceConfig.kvStore.put(bucketId, count, {
128
- expirationTtl: DEFAULT_RATE_LIMIT_CACHE_TTL_SECONDS
129
- })
130
- });
131
- }
132
126
  async function extractAuthorizationData(authInput) {
133
127
  const requestUrl = new URL(authInput.req.url);
134
128
  const headers = authInput.req.headers;
@@ -244,4 +238,4 @@ async function logHttpRequest(_ref) {
244
238
  }
245
239
  }
246
240
 
247
- export { authorizeWorker, deriveClientIdFromSecretKeyHash, extractAuthorizationData, hashSecretKey, logHttpRequest, publishUsageEvents, rateLimitWorker };
241
+ export { authorizeWorker, deriveClientIdFromSecretKeyHash, extractAuthorizationData, hashSecretKey, logHttpRequest, publishUsageEvents };
@@ -3,7 +3,6 @@ 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";
7
6
  import type { CoreAuthInput } from "../core/types";
8
7
  export * from "./usage";
9
8
  export * from "../core/services";
@@ -18,7 +17,6 @@ type AuthInput = CoreAuthInput & {
18
17
  req: Request;
19
18
  };
20
19
  export declare function authorizeWorker(authInput: AuthInput, serviceConfig: WorkerServiceConfig): Promise<AuthorizationResult>;
21
- export declare function rateLimitWorker(authzResult: AuthorizationResult, serviceConfig: WorkerServiceConfig): Promise<RateLimitResult>;
22
20
  export declare function extractAuthorizationData(authInput: AuthInput): Promise<AuthorizationInput>;
23
21
  export declare function hashSecretKey(secretKey: string): Promise<string>;
24
22
  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,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,iBAwBA"}
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,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;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,iBAwBA"}
@@ -3,9 +3,13 @@ import { z } from "zod";
3
3
  * Types
4
4
  */
5
5
  declare const usageEventSchema: z.ZodObject<{
6
- source: z.ZodEnum<["embeddedWallets", "rpc", "storage", "bundler", "paymaster", "relayer"]>;
6
+ source: z.ZodEnum<["embeddedWallets", "rpc", "storage", "bundler", "paymaster", "relayer", "connectWallet"]>;
7
7
  action: z.ZodString;
8
- accountId: z.ZodString;
8
+ /**
9
+ * The following fields are optional.
10
+ */
11
+ accountId: z.ZodOptional<z.ZodString>;
12
+ isClientEvent: z.ZodOptional<z.ZodBoolean>;
9
13
  apiKeyId: z.ZodOptional<z.ZodString>;
10
14
  creatorWalletAddress: z.ZodOptional<z.ZodString>;
11
15
  clientId: z.ZodOptional<z.ZodString>;
@@ -25,9 +29,10 @@ declare const usageEventSchema: z.ZodObject<{
25
29
  sdkPlatform: z.ZodOptional<z.ZodString>;
26
30
  productName: z.ZodOptional<z.ZodString>;
27
31
  }, "strip", z.ZodTypeAny, {
28
- source: "storage" | "rpc" | "bundler" | "relayer" | "embeddedWallets" | "paymaster";
29
- accountId: string;
32
+ source: "storage" | "rpc" | "bundler" | "relayer" | "embeddedWallets" | "paymaster" | "connectWallet";
30
33
  action: string;
34
+ accountId?: string | undefined;
35
+ isClientEvent?: boolean | undefined;
31
36
  apiKeyId?: string | undefined;
32
37
  creatorWalletAddress?: string | undefined;
33
38
  clientId?: string | undefined;
@@ -47,9 +52,10 @@ declare const usageEventSchema: z.ZodObject<{
47
52
  sdkPlatform?: string | undefined;
48
53
  productName?: string | undefined;
49
54
  }, {
50
- source: "storage" | "rpc" | "bundler" | "relayer" | "embeddedWallets" | "paymaster";
51
- accountId: string;
55
+ source: "storage" | "rpc" | "bundler" | "relayer" | "embeddedWallets" | "paymaster" | "connectWallet";
52
56
  action: string;
57
+ accountId?: string | undefined;
58
+ isClientEvent?: boolean | undefined;
53
59
  apiKeyId?: string | undefined;
54
60
  creatorWalletAddress?: string | undefined;
55
61
  clientId?: string | undefined;
@@ -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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA+BpB,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;;;IAYpB;;OAEG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAsBH,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,10 +1,20 @@
1
1
  import { CoreServiceConfig } from "../api";
2
2
  import { AuthorizationResult } from "../authorize/types";
3
3
  import { RateLimitResult } from "./types";
4
- type CacheOptions = {
5
- get: (bucketId: string) => Promise<string | null>;
6
- put: (bucketId: string, count: string) => Promise<void> | void;
4
+ type IRedis = {
5
+ incr: (key: string) => Promise<number>;
6
+ expire: (key: string, ttlSeconds: number) => Promise<0 | 1>;
7
7
  };
8
- export declare function rateLimit(authzResult: AuthorizationResult, serviceConfig: CoreServiceConfig, cacheOptions: CacheOptions): Promise<RateLimitResult>;
8
+ export declare function rateLimit(args: {
9
+ authzResult: AuthorizationResult;
10
+ serviceConfig: CoreServiceConfig;
11
+ redis: IRedis;
12
+ /**
13
+ * Sample requests to reduce load on Redis.
14
+ * This scales down the request count and the rate limit threshold.
15
+ * @default 1.0
16
+ */
17
+ sampleRate?: number;
18
+ }): Promise<RateLimitResult>;
9
19
  export {};
10
20
  //# sourceMappingURL=index.d.ts.map
@@ -1 +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"}
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;AACzD,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAK1C,KAAK,MAAM,GAAG;IACZ,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACvC,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;CAC7D,CAAC;AAEF,wBAAsB,SAAS,CAAC,IAAI,EAAE;IACpC,WAAW,EAAE,mBAAmB,CAAC;IACjC,aAAa,EAAE,iBAAiB,CAAC;IACjC,KAAK,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,GAAG,OAAO,CAAC,eAAe,CAAC,CAsE3B"}
@@ -1,7 +1,11 @@
1
1
  export type RateLimitResult = {
2
2
  rateLimited: false;
3
+ requestCount: number;
4
+ rateLimit: number;
3
5
  } | {
4
6
  rateLimited: true;
7
+ requestCount: number;
8
+ rateLimit: number;
5
9
  status: number;
6
10
  errorMessage: string;
7
11
  errorCode: string;
@@ -1 +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"}
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;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;CACnB,GACD;IACE,WAAW,EAAE,IAAI,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC"}
@@ -1 +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"}
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,CAoD3B"}
@@ -449,62 +449,78 @@ async function authorize(authData, serviceConfig, cacheOptions) {
449
449
  };
450
450
  }
451
451
 
452
- const DEFAULT_RATE_LIMIT_WINDOW_SECONDS = 10;
453
- const HARD_LIMIT_MULTIPLE = 2; // 2x of allowed limit
452
+ const RATE_LIMIT_WINDOW_SECONDS = 10;
454
453
 
455
- async function rateLimit(authzResult, serviceConfig, cacheOptions) {
456
- if (!authzResult.authorized) {
454
+ // Redis interface compatible with ioredis (Node) and upstash (Cloudflare Workers).
455
+
456
+ async function rateLimit(args) {
457
+ const {
458
+ authzResult,
459
+ serviceConfig,
460
+ redis,
461
+ sampleRate = 1.0
462
+ } = args;
463
+ const shouldSampleRequest = Math.random() < sampleRate;
464
+ if (!shouldSampleRequest || !authzResult.authorized) {
457
465
  return {
458
- rateLimited: false
466
+ rateLimited: false,
467
+ requestCount: 0,
468
+ rateLimit: 0
459
469
  };
460
470
  }
461
471
  const {
462
472
  apiKeyMeta,
463
473
  accountMeta
464
474
  } = authzResult;
465
- const {
466
- rateLimits
467
- } = apiKeyMeta || accountMeta || {};
468
475
  const accountId = apiKeyMeta?.accountId || accountMeta?.id;
469
476
  const {
470
477
  serviceScope
471
478
  } = serviceConfig;
472
- if (!rateLimits || !(serviceScope in rateLimits)) {
479
+ const limitPerSecond = apiKeyMeta?.rateLimits?.[serviceScope] ?? accountMeta?.rateLimits?.[serviceScope];
480
+ if (!limitPerSecond) {
473
481
  // No rate limit is provided. Assume the request is not rate limited.
474
482
  return {
475
- rateLimited: false
483
+ rateLimited: false,
484
+ requestCount: 0,
485
+ rateLimit: 0
476
486
  };
477
487
  }
478
- const limit = rateLimits[serviceScope];
479
488
 
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;
489
+ // Gets the 10-second window for the current timestamp.
490
+ const timestampWindow = Math.floor(Date.now() / (1000 * RATE_LIMIT_WINDOW_SECONDS)) * RATE_LIMIT_WINDOW_SECONDS;
491
+ const key = `rate-limit:${serviceScope}:${accountId}:${timestampWindow}`;
492
+
493
+ // Increment and get the current request count in this window.
494
+ const requestCount = await redis.incr(key);
495
+ if (requestCount === 1) {
496
+ // For the first increment, set an expiration to clean up this key.
497
+ await redis.expire(key, RATE_LIMIT_WINDOW_SECONDS);
498
+ }
485
499
 
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
500
+ // Get the limit for this window accounting for the sample rate.
501
+ const limitPerWindow = limitPerSecond * sampleRate * RATE_LIMIT_WINDOW_SECONDS;
502
+ if (requestCount > limitPerWindow) {
503
+ // Report rate limit hits.
490
504
  if (apiKeyMeta?.id) {
491
505
  await updateRateLimitedAt(apiKeyMeta.id, serviceConfig);
492
506
  }
493
507
 
494
- // actually rate limit only when reached hard limit
495
- if (current > limitWindow * HARD_LIMIT_MULTIPLE) {
508
+ // Reject requests when they've exceeded 2x the rate limit.
509
+ if (requestCount > 2 * limitPerWindow) {
496
510
  return {
497
511
  rateLimited: true,
512
+ requestCount,
513
+ rateLimit: limitPerWindow,
498
514
  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.`,
515
+ errorMessage: `You've exceeded your ${serviceScope} rate limit at ${limitPerSecond} reqs/sec. To get higher rate limits, contact us at https://thirdweb.com/contact-us.`,
500
516
  errorCode: "RATE_LIMIT_EXCEEDED"
501
517
  };
502
518
  }
503
- } else {
504
- await cacheOptions.put(key, current.toString());
505
519
  }
506
520
  return {
507
- rateLimited: false
521
+ rateLimited: false,
522
+ requestCount,
523
+ rateLimit: limitPerWindow
508
524
  };
509
525
  }
510
526
 
@@ -540,6 +556,14 @@ async function usageLimit(authzResult, serviceConfig) {
540
556
  errorCode: "PAYMENT_METHOD_REQUIRED"
541
557
  };
542
558
  }
559
+ if (serviceScope === "embeddedWallets" && (usage.embeddedWallets?.countWalletAddresses || 0) > limit) {
560
+ return {
561
+ usageLimited: true,
562
+ status: 403,
563
+ errorMessage: `You've used all of your total usage limit for Embedded Wallets. Please add your payment method at https://thirdweb.com/dashboard/settings/billing.`,
564
+ errorCode: "PAYMENT_METHOD_REQUIRED"
565
+ };
566
+ }
543
567
  return {
544
568
  usageLimited: false
545
569
  };
@@ -449,62 +449,78 @@ async function authorize(authData, serviceConfig, cacheOptions) {
449
449
  };
450
450
  }
451
451
 
452
- const DEFAULT_RATE_LIMIT_WINDOW_SECONDS = 10;
453
- const HARD_LIMIT_MULTIPLE = 2; // 2x of allowed limit
452
+ const RATE_LIMIT_WINDOW_SECONDS = 10;
454
453
 
455
- async function rateLimit(authzResult, serviceConfig, cacheOptions) {
456
- if (!authzResult.authorized) {
454
+ // Redis interface compatible with ioredis (Node) and upstash (Cloudflare Workers).
455
+
456
+ async function rateLimit(args) {
457
+ const {
458
+ authzResult,
459
+ serviceConfig,
460
+ redis,
461
+ sampleRate = 1.0
462
+ } = args;
463
+ const shouldSampleRequest = Math.random() < sampleRate;
464
+ if (!shouldSampleRequest || !authzResult.authorized) {
457
465
  return {
458
- rateLimited: false
466
+ rateLimited: false,
467
+ requestCount: 0,
468
+ rateLimit: 0
459
469
  };
460
470
  }
461
471
  const {
462
472
  apiKeyMeta,
463
473
  accountMeta
464
474
  } = authzResult;
465
- const {
466
- rateLimits
467
- } = apiKeyMeta || accountMeta || {};
468
475
  const accountId = apiKeyMeta?.accountId || accountMeta?.id;
469
476
  const {
470
477
  serviceScope
471
478
  } = serviceConfig;
472
- if (!rateLimits || !(serviceScope in rateLimits)) {
479
+ const limitPerSecond = apiKeyMeta?.rateLimits?.[serviceScope] ?? accountMeta?.rateLimits?.[serviceScope];
480
+ if (!limitPerSecond) {
473
481
  // No rate limit is provided. Assume the request is not rate limited.
474
482
  return {
475
- rateLimited: false
483
+ rateLimited: false,
484
+ requestCount: 0,
485
+ rateLimit: 0
476
486
  };
477
487
  }
478
- const limit = rateLimits[serviceScope];
479
488
 
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;
489
+ // Gets the 10-second window for the current timestamp.
490
+ const timestampWindow = Math.floor(Date.now() / (1000 * RATE_LIMIT_WINDOW_SECONDS)) * RATE_LIMIT_WINDOW_SECONDS;
491
+ const key = `rate-limit:${serviceScope}:${accountId}:${timestampWindow}`;
492
+
493
+ // Increment and get the current request count in this window.
494
+ const requestCount = await redis.incr(key);
495
+ if (requestCount === 1) {
496
+ // For the first increment, set an expiration to clean up this key.
497
+ await redis.expire(key, RATE_LIMIT_WINDOW_SECONDS);
498
+ }
485
499
 
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
500
+ // Get the limit for this window accounting for the sample rate.
501
+ const limitPerWindow = limitPerSecond * sampleRate * RATE_LIMIT_WINDOW_SECONDS;
502
+ if (requestCount > limitPerWindow) {
503
+ // Report rate limit hits.
490
504
  if (apiKeyMeta?.id) {
491
505
  await updateRateLimitedAt(apiKeyMeta.id, serviceConfig);
492
506
  }
493
507
 
494
- // actually rate limit only when reached hard limit
495
- if (current > limitWindow * HARD_LIMIT_MULTIPLE) {
508
+ // Reject requests when they've exceeded 2x the rate limit.
509
+ if (requestCount > 2 * limitPerWindow) {
496
510
  return {
497
511
  rateLimited: true,
512
+ requestCount,
513
+ rateLimit: limitPerWindow,
498
514
  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.`,
515
+ errorMessage: `You've exceeded your ${serviceScope} rate limit at ${limitPerSecond} reqs/sec. To get higher rate limits, contact us at https://thirdweb.com/contact-us.`,
500
516
  errorCode: "RATE_LIMIT_EXCEEDED"
501
517
  };
502
518
  }
503
- } else {
504
- await cacheOptions.put(key, current.toString());
505
519
  }
506
520
  return {
507
- rateLimited: false
521
+ rateLimited: false,
522
+ requestCount,
523
+ rateLimit: limitPerWindow
508
524
  };
509
525
  }
510
526
 
@@ -540,6 +556,14 @@ async function usageLimit(authzResult, serviceConfig) {
540
556
  errorCode: "PAYMENT_METHOD_REQUIRED"
541
557
  };
542
558
  }
559
+ if (serviceScope === "embeddedWallets" && (usage.embeddedWallets?.countWalletAddresses || 0) > limit) {
560
+ return {
561
+ usageLimited: true,
562
+ status: 403,
563
+ errorMessage: `You've used all of your total usage limit for Embedded Wallets. Please add your payment method at https://thirdweb.com/dashboard/settings/billing.`,
564
+ errorCode: "PAYMENT_METHOD_REQUIRED"
565
+ };
566
+ }
543
567
  return {
544
568
  usageLimited: false
545
569
  };
@@ -447,62 +447,78 @@ async function authorize(authData, serviceConfig, cacheOptions) {
447
447
  };
448
448
  }
449
449
 
450
- const DEFAULT_RATE_LIMIT_WINDOW_SECONDS = 10;
451
- const HARD_LIMIT_MULTIPLE = 2; // 2x of allowed limit
450
+ const RATE_LIMIT_WINDOW_SECONDS = 10;
452
451
 
453
- async function rateLimit(authzResult, serviceConfig, cacheOptions) {
454
- if (!authzResult.authorized) {
452
+ // Redis interface compatible with ioredis (Node) and upstash (Cloudflare Workers).
453
+
454
+ async function rateLimit(args) {
455
+ const {
456
+ authzResult,
457
+ serviceConfig,
458
+ redis,
459
+ sampleRate = 1.0
460
+ } = args;
461
+ const shouldSampleRequest = Math.random() < sampleRate;
462
+ if (!shouldSampleRequest || !authzResult.authorized) {
455
463
  return {
456
- rateLimited: false
464
+ rateLimited: false,
465
+ requestCount: 0,
466
+ rateLimit: 0
457
467
  };
458
468
  }
459
469
  const {
460
470
  apiKeyMeta,
461
471
  accountMeta
462
472
  } = authzResult;
463
- const {
464
- rateLimits
465
- } = apiKeyMeta || accountMeta || {};
466
473
  const accountId = apiKeyMeta?.accountId || accountMeta?.id;
467
474
  const {
468
475
  serviceScope
469
476
  } = serviceConfig;
470
- if (!rateLimits || !(serviceScope in rateLimits)) {
477
+ const limitPerSecond = apiKeyMeta?.rateLimits?.[serviceScope] ?? accountMeta?.rateLimits?.[serviceScope];
478
+ if (!limitPerSecond) {
471
479
  // No rate limit is provided. Assume the request is not rate limited.
472
480
  return {
473
- rateLimited: false
481
+ rateLimited: false,
482
+ requestCount: 0,
483
+ rateLimit: 0
474
484
  };
475
485
  }
476
- const limit = rateLimits[serviceScope];
477
486
 
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;
487
+ // Gets the 10-second window for the current timestamp.
488
+ const timestampWindow = Math.floor(Date.now() / (1000 * RATE_LIMIT_WINDOW_SECONDS)) * RATE_LIMIT_WINDOW_SECONDS;
489
+ const key = `rate-limit:${serviceScope}:${accountId}:${timestampWindow}`;
490
+
491
+ // Increment and get the current request count in this window.
492
+ const requestCount = await redis.incr(key);
493
+ if (requestCount === 1) {
494
+ // For the first increment, set an expiration to clean up this key.
495
+ await redis.expire(key, RATE_LIMIT_WINDOW_SECONDS);
496
+ }
483
497
 
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
498
+ // Get the limit for this window accounting for the sample rate.
499
+ const limitPerWindow = limitPerSecond * sampleRate * RATE_LIMIT_WINDOW_SECONDS;
500
+ if (requestCount > limitPerWindow) {
501
+ // Report rate limit hits.
488
502
  if (apiKeyMeta?.id) {
489
503
  await updateRateLimitedAt(apiKeyMeta.id, serviceConfig);
490
504
  }
491
505
 
492
- // actually rate limit only when reached hard limit
493
- if (current > limitWindow * HARD_LIMIT_MULTIPLE) {
506
+ // Reject requests when they've exceeded 2x the rate limit.
507
+ if (requestCount > 2 * limitPerWindow) {
494
508
  return {
495
509
  rateLimited: true,
510
+ requestCount,
511
+ rateLimit: limitPerWindow,
496
512
  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.`,
513
+ errorMessage: `You've exceeded your ${serviceScope} rate limit at ${limitPerSecond} reqs/sec. To get higher rate limits, contact us at https://thirdweb.com/contact-us.`,
498
514
  errorCode: "RATE_LIMIT_EXCEEDED"
499
515
  };
500
516
  }
501
- } else {
502
- await cacheOptions.put(key, current.toString());
503
517
  }
504
518
  return {
505
- rateLimited: false
519
+ rateLimited: false,
520
+ requestCount,
521
+ rateLimit: limitPerWindow
506
522
  };
507
523
  }
508
524
 
@@ -538,6 +554,14 @@ async function usageLimit(authzResult, serviceConfig) {
538
554
  errorCode: "PAYMENT_METHOD_REQUIRED"
539
555
  };
540
556
  }
557
+ if (serviceScope === "embeddedWallets" && (usage.embeddedWallets?.countWalletAddresses || 0) > limit) {
558
+ return {
559
+ usageLimited: true,
560
+ status: 403,
561
+ errorMessage: `You've used all of your total usage limit for Embedded Wallets. Please add your payment method at https://thirdweb.com/dashboard/settings/billing.`,
562
+ errorCode: "PAYMENT_METHOD_REQUIRED"
563
+ };
564
+ }
541
565
  return {
542
566
  usageLimited: false
543
567
  };
@@ -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-807f6a60.cjs.dev.js');
6
+ var index = require('../../dist/index-18abcc30.cjs.dev.js');
7
7
  var services = require('../../dist/services-79b4664f.cjs.dev.js');
8
8
 
9
9
  /**
@@ -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-cfc8027b.cjs.prod.js');
6
+ var index = require('../../dist/index-aac16290.cjs.prod.js');
7
7
  var services = require('../../dist/services-04997839.cjs.prod.js');
8
8
 
9
9
  /**
@@ -1,6 +1,6 @@
1
1
  import { createHash } from 'node:crypto';
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';
2
+ import { a as authorize } from '../../dist/index-b140304d.esm.js';
3
+ export { r as rateLimit, u as usageLimit } from '../../dist/index-b140304d.esm.js';
4
4
  export { b as SERVICES, S as SERVICE_DEFINITIONS, a as SERVICE_NAMES, g as getServiceByName } from '../../dist/services-bc12a5f6.esm.js';
5
5
 
6
6
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thirdweb-dev/service-utils",
3
- "version": "0.0.0-dev-d86829b-20230927000710",
3
+ "version": "0.0.0-dev-29cb324-20231008112502",
4
4
  "main": "dist/thirdweb-dev-service-utils.cjs.js",
5
5
  "module": "dist/thirdweb-dev-service-utils.esm.js",
6
6
  "exports": {