@rlajous/sdk-core 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +96 -0
- package/dist/cjs/client-base.js +155 -0
- package/dist/cjs/client-base.js.map +1 -0
- package/dist/cjs/config.js +30 -0
- package/dist/cjs/config.js.map +1 -0
- package/dist/cjs/errors/authentication.js +35 -0
- package/dist/cjs/errors/authentication.js.map +1 -0
- package/dist/cjs/errors/base.js +76 -0
- package/dist/cjs/errors/base.js.map +1 -0
- package/dist/cjs/errors/index.js +16 -0
- package/dist/cjs/errors/index.js.map +1 -0
- package/dist/cjs/errors/network.js +45 -0
- package/dist/cjs/errors/network.js.map +1 -0
- package/dist/cjs/errors/not-found.js +38 -0
- package/dist/cjs/errors/not-found.js.map +1 -0
- package/dist/cjs/errors/rate-limit.js +53 -0
- package/dist/cjs/errors/rate-limit.js.map +1 -0
- package/dist/cjs/errors/validation.js +49 -0
- package/dist/cjs/errors/validation.js.map +1 -0
- package/dist/cjs/http/client.js +335 -0
- package/dist/cjs/http/client.js.map +1 -0
- package/dist/cjs/http/index.js +11 -0
- package/dist/cjs/http/index.js.map +1 -0
- package/dist/cjs/http/retry.js +43 -0
- package/dist/cjs/http/retry.js.map +1 -0
- package/dist/cjs/index.js +48 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/types/chain.js +114 -0
- package/dist/cjs/types/chain.js.map +1 -0
- package/dist/cjs/types/common.js +49 -0
- package/dist/cjs/types/common.js.map +1 -0
- package/dist/cjs/types/index.js +18 -0
- package/dist/cjs/types/index.js.map +1 -0
- package/dist/cjs/types/modules.js +64 -0
- package/dist/cjs/types/modules.js.map +1 -0
- package/dist/cjs/utils/address-validation.js +124 -0
- package/dist/cjs/utils/address-validation.js.map +1 -0
- package/dist/cjs/utils/index.js +14 -0
- package/dist/cjs/utils/index.js.map +1 -0
- package/dist/esm/client-base.js +151 -0
- package/dist/esm/client-base.js.map +1 -0
- package/dist/esm/config.js +26 -0
- package/dist/esm/config.js.map +1 -0
- package/dist/esm/errors/authentication.js +31 -0
- package/dist/esm/errors/authentication.js.map +1 -0
- package/dist/esm/errors/base.js +72 -0
- package/dist/esm/errors/base.js.map +1 -0
- package/dist/esm/errors/index.js +7 -0
- package/dist/esm/errors/index.js.map +1 -0
- package/dist/esm/errors/network.js +41 -0
- package/dist/esm/errors/network.js.map +1 -0
- package/dist/esm/errors/not-found.js +34 -0
- package/dist/esm/errors/not-found.js.map +1 -0
- package/dist/esm/errors/rate-limit.js +49 -0
- package/dist/esm/errors/rate-limit.js.map +1 -0
- package/dist/esm/errors/validation.js +45 -0
- package/dist/esm/errors/validation.js.map +1 -0
- package/dist/esm/http/client.js +331 -0
- package/dist/esm/http/client.js.map +1 -0
- package/dist/esm/http/index.js +3 -0
- package/dist/esm/http/index.js.map +1 -0
- package/dist/esm/http/retry.js +37 -0
- package/dist/esm/http/retry.js.map +1 -0
- package/dist/esm/index.js +13 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/package.json +1 -0
- package/dist/esm/types/chain.js +109 -0
- package/dist/esm/types/chain.js.map +1 -0
- package/dist/esm/types/common.js +46 -0
- package/dist/esm/types/common.js.map +1 -0
- package/dist/esm/types/index.js +4 -0
- package/dist/esm/types/index.js.map +1 -0
- package/dist/esm/types/modules.js +61 -0
- package/dist/esm/types/modules.js.map +1 -0
- package/dist/esm/utils/address-validation.js +113 -0
- package/dist/esm/utils/address-validation.js.map +1 -0
- package/dist/esm/utils/index.js +2 -0
- package/dist/esm/utils/index.js.map +1 -0
- package/dist/types/client-base.d.ts +94 -0
- package/dist/types/client-base.d.ts.map +1 -0
- package/dist/types/config.d.ts +124 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/errors/authentication.d.ts +24 -0
- package/dist/types/errors/authentication.d.ts.map +1 -0
- package/dist/types/errors/base.d.ts +53 -0
- package/dist/types/errors/base.d.ts.map +1 -0
- package/dist/types/errors/index.d.ts +7 -0
- package/dist/types/errors/index.d.ts.map +1 -0
- package/dist/types/errors/network.d.ts +30 -0
- package/dist/types/errors/network.d.ts.map +1 -0
- package/dist/types/errors/not-found.d.ts +27 -0
- package/dist/types/errors/not-found.d.ts.map +1 -0
- package/dist/types/errors/rate-limit.d.ts +37 -0
- package/dist/types/errors/rate-limit.d.ts.map +1 -0
- package/dist/types/errors/validation.d.ts +34 -0
- package/dist/types/errors/validation.d.ts.map +1 -0
- package/dist/types/http/client.d.ts +147 -0
- package/dist/types/http/client.d.ts.map +1 -0
- package/dist/types/http/index.d.ts +3 -0
- package/dist/types/http/index.d.ts.map +1 -0
- package/dist/types/http/retry.d.ts +32 -0
- package/dist/types/http/retry.d.ts.map +1 -0
- package/dist/types/index.d.ts +7 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/types/chain.d.ts +60 -0
- package/dist/types/types/chain.d.ts.map +1 -0
- package/dist/types/types/common.d.ts +251 -0
- package/dist/types/types/common.d.ts.map +1 -0
- package/dist/types/types/index.d.ts +5 -0
- package/dist/types/types/index.d.ts.map +1 -0
- package/dist/types/types/modules.d.ts +51 -0
- package/dist/types/types/modules.d.ts.map +1 -0
- package/dist/types/utils/address-validation.d.ts +50 -0
- package/dist/types/utils/address-validation.d.ts.map +1 -0
- package/dist/types/utils/index.d.ts +2 -0
- package/dist/types/utils/index.d.ts.map +1 -0
- package/package.json +64 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { WebacyError } from './base';
|
|
2
|
+
/**
|
|
3
|
+
* Thrown when rate limit is exceeded
|
|
4
|
+
*
|
|
5
|
+
* The SDK automatically retries rate-limited requests with exponential backoff.
|
|
6
|
+
* If you're seeing this error frequently, consider reducing request frequency
|
|
7
|
+
* or upgrading your API plan.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```typescript
|
|
11
|
+
* try {
|
|
12
|
+
* await client.addresses.analyze(address, { chain: Chain.ETH });
|
|
13
|
+
* } catch (error) {
|
|
14
|
+
* if (error instanceof RateLimitError) {
|
|
15
|
+
* console.error('Rate limited:', error.message);
|
|
16
|
+
* if (error.retryAfter) {
|
|
17
|
+
* console.log(`Retry after ${error.retryAfter} seconds`);
|
|
18
|
+
* }
|
|
19
|
+
* }
|
|
20
|
+
* }
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export class RateLimitError extends WebacyError {
|
|
24
|
+
/** When the rate limit resets (Unix timestamp) */
|
|
25
|
+
resetAt;
|
|
26
|
+
/** Number of seconds until reset */
|
|
27
|
+
retryAfter;
|
|
28
|
+
constructor(message = 'Rate limit exceeded', options = {}) {
|
|
29
|
+
super(message, {
|
|
30
|
+
status: 429,
|
|
31
|
+
code: 'RATE_LIMIT_ERROR',
|
|
32
|
+
requestId: options.requestId,
|
|
33
|
+
endpoint: options.endpoint,
|
|
34
|
+
});
|
|
35
|
+
this.name = 'RateLimitError';
|
|
36
|
+
this.resetAt = options.resetAt;
|
|
37
|
+
this.retryAfter = options.retryAfter;
|
|
38
|
+
}
|
|
39
|
+
isRetryable() {
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
getRecoverySuggestion() {
|
|
43
|
+
if (this.retryAfter) {
|
|
44
|
+
return `Wait ${this.retryAfter} seconds before retrying. Consider implementing request throttling or upgrading your API plan for higher limits.`;
|
|
45
|
+
}
|
|
46
|
+
return 'Wait a moment before retrying. Consider implementing request throttling or upgrading your API plan for higher limits.';
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=rate-limit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rate-limit.js","sourceRoot":"","sources":["../../../src/errors/rate-limit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAErC;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,OAAO,cAAe,SAAQ,WAAW;IAC7C,kDAAkD;IAClC,OAAO,CAAU;IAEjC,oCAAoC;IACpB,UAAU,CAAU;IAEpC,YACE,OAAO,GAAG,qBAAqB,EAC/B,UAA4F,EAAE;QAE9F,KAAK,CAAC,OAAO,EAAE;YACb,MAAM,EAAE,GAAG;YACX,IAAI,EAAE,kBAAkB;YACxB,SAAS,EAAE,OAAO,CAAC,SAAS;YAC5B,QAAQ,EAAE,OAAO,CAAC,QAAQ;SAC3B,CAAC,CAAC;QACH,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAC;QAC7B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;QAC/B,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;IACvC,CAAC;IAEQ,WAAW;QAClB,OAAO,IAAI,CAAC;IACd,CAAC;IAEQ,qBAAqB;QAC5B,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACpB,OAAO,QAAQ,IAAI,CAAC,UAAU,kHAAkH,CAAC;QACnJ,CAAC;QACD,OAAO,uHAAuH,CAAC;IACjI,CAAC;CACF"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { WebacyError } from './base';
|
|
2
|
+
/**
|
|
3
|
+
* Thrown when request validation fails
|
|
4
|
+
*
|
|
5
|
+
* This error occurs when the provided input doesn't meet the API requirements.
|
|
6
|
+
* Common causes include invalid addresses, unsupported chains, or missing parameters.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* try {
|
|
11
|
+
* await client.addresses.analyze(address, { chain: Chain.ETH });
|
|
12
|
+
* } catch (error) {
|
|
13
|
+
* if (error instanceof ValidationError) {
|
|
14
|
+
* console.error('Validation failed:', error.message);
|
|
15
|
+
* if (error.errors) {
|
|
16
|
+
* for (const [field, messages] of Object.entries(error.errors)) {
|
|
17
|
+
* console.error(` ${field}: ${messages.join(', ')}`);
|
|
18
|
+
* }
|
|
19
|
+
* }
|
|
20
|
+
* }
|
|
21
|
+
* }
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
export class ValidationError extends WebacyError {
|
|
25
|
+
/** Field-level validation errors */
|
|
26
|
+
errors;
|
|
27
|
+
constructor(message = 'Validation failed', options = {}) {
|
|
28
|
+
super(message, {
|
|
29
|
+
status: 400,
|
|
30
|
+
code: 'VALIDATION_ERROR',
|
|
31
|
+
requestId: options.requestId,
|
|
32
|
+
endpoint: options.endpoint,
|
|
33
|
+
});
|
|
34
|
+
this.name = 'ValidationError';
|
|
35
|
+
this.errors = options.errors;
|
|
36
|
+
}
|
|
37
|
+
getRecoverySuggestion() {
|
|
38
|
+
if (this.errors && Object.keys(this.errors).length > 0) {
|
|
39
|
+
const fields = Object.keys(this.errors).join(', ');
|
|
40
|
+
return `Check the following fields: ${fields}. Ensure address formats match the specified blockchain and all required parameters are provided.`;
|
|
41
|
+
}
|
|
42
|
+
return 'Check your input parameters. Ensure address formats match the specified blockchain (e.g., 0x... for EVM chains, base58 for Solana).';
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=validation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.js","sourceRoot":"","sources":["../../../src/errors/validation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAErC;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,OAAO,eAAgB,SAAQ,WAAW;IAC9C,oCAAoC;IACpB,MAAM,CAA4B;IAElD,YACE,OAAO,GAAG,mBAAmB,EAC7B,UAAwF,EAAE;QAE1F,KAAK,CAAC,OAAO,EAAE;YACb,MAAM,EAAE,GAAG;YACX,IAAI,EAAE,kBAAkB;YACxB,SAAS,EAAE,OAAO,CAAC,SAAS;YAC5B,QAAQ,EAAE,OAAO,CAAC,QAAQ;SAC3B,CAAC,CAAC;QACH,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;QAC9B,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAC/B,CAAC;IAEQ,qBAAqB;QAC5B,IAAI,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvD,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACnD,OAAO,+BAA+B,MAAM,mGAAmG,CAAC;QAClJ,CAAC;QACD,OAAO,qIAAqI,CAAC;IAC/I,CAAC;CACF"}
|
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
import { WebacyError, AuthenticationError, RateLimitError, ValidationError, NotFoundError, NetworkError, } from '../errors';
|
|
2
|
+
import { DEFAULT_RETRY_CONFIG, calculateRetryDelay, isRetryableStatusCode, sleep, } from './retry';
|
|
3
|
+
import { defaultLogger } from '../config';
|
|
4
|
+
/**
|
|
5
|
+
* HTTP client with retry support and interceptors
|
|
6
|
+
*/
|
|
7
|
+
export class HttpClient {
|
|
8
|
+
baseUrl;
|
|
9
|
+
defaultHeaders;
|
|
10
|
+
defaultTimeout;
|
|
11
|
+
retryConfig;
|
|
12
|
+
requestInterceptors = [];
|
|
13
|
+
responseInterceptors = [];
|
|
14
|
+
errorInterceptors = [];
|
|
15
|
+
debug;
|
|
16
|
+
logger;
|
|
17
|
+
constructor(config) {
|
|
18
|
+
this.baseUrl = config.baseUrl.replace(/\/$/, ''); // Remove trailing slash
|
|
19
|
+
this.defaultHeaders = {
|
|
20
|
+
'Content-Type': 'application/json',
|
|
21
|
+
Accept: 'application/json',
|
|
22
|
+
...config.headers,
|
|
23
|
+
};
|
|
24
|
+
this.defaultTimeout = config.timeout ?? 30000;
|
|
25
|
+
this.retryConfig = { ...DEFAULT_RETRY_CONFIG, ...config.retry };
|
|
26
|
+
this.debug = config.debug ?? false;
|
|
27
|
+
this.logger = config.logger ?? defaultLogger;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Check if request logging is enabled
|
|
31
|
+
*/
|
|
32
|
+
shouldLogRequests() {
|
|
33
|
+
return this.debug === true || this.debug === 'all' || this.debug === 'requests';
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Check if response logging is enabled
|
|
37
|
+
*/
|
|
38
|
+
shouldLogResponses() {
|
|
39
|
+
return this.debug === true || this.debug === 'all' || this.debug === 'responses';
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Check if error logging is enabled
|
|
43
|
+
*/
|
|
44
|
+
shouldLogErrors() {
|
|
45
|
+
return this.debug === true || this.debug === 'all' || this.debug === 'errors';
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Log a request
|
|
49
|
+
*/
|
|
50
|
+
logRequest(method, url, body) {
|
|
51
|
+
if (this.shouldLogRequests()) {
|
|
52
|
+
this.logger.debug(`→ ${method} ${url}`, body ? { body: this.sanitizeBody(body) } : undefined);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Log a response
|
|
57
|
+
*/
|
|
58
|
+
logResponse(method, url, status, duration) {
|
|
59
|
+
if (this.shouldLogResponses()) {
|
|
60
|
+
this.logger.debug(`← ${method} ${url} ${status} (${duration}ms)`);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Log an error
|
|
65
|
+
*/
|
|
66
|
+
logError(method, url, error) {
|
|
67
|
+
if (this.shouldLogErrors()) {
|
|
68
|
+
this.logger.error(`✗ ${method} ${url} - ${error.code}: ${error.message}`, {
|
|
69
|
+
code: error.code,
|
|
70
|
+
status: error.status,
|
|
71
|
+
requestId: error.requestId,
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Sanitize request body for logging (remove sensitive data)
|
|
77
|
+
*/
|
|
78
|
+
sanitizeBody(body) {
|
|
79
|
+
if (typeof body !== 'object' || body === null) {
|
|
80
|
+
return body;
|
|
81
|
+
}
|
|
82
|
+
// Remove potentially sensitive fields from logs
|
|
83
|
+
const sanitized = { ...body };
|
|
84
|
+
const sensitiveKeys = ['apiKey', 'api_key', 'secret', 'password', 'token'];
|
|
85
|
+
for (const key of sensitiveKeys) {
|
|
86
|
+
if (key in sanitized) {
|
|
87
|
+
sanitized[key] = '[REDACTED]';
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return sanitized;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Add a request interceptor
|
|
94
|
+
*/
|
|
95
|
+
addRequestInterceptor(interceptor) {
|
|
96
|
+
this.requestInterceptors.push(interceptor);
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Add a response interceptor
|
|
100
|
+
*/
|
|
101
|
+
addResponseInterceptor(interceptor) {
|
|
102
|
+
this.responseInterceptors.push(interceptor);
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Add an error interceptor
|
|
106
|
+
*/
|
|
107
|
+
addErrorInterceptor(interceptor) {
|
|
108
|
+
this.errorInterceptors.push(interceptor);
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Make a GET request
|
|
112
|
+
*/
|
|
113
|
+
async get(path, config) {
|
|
114
|
+
return this.request(path, { ...config, method: 'GET' });
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Make a POST request
|
|
118
|
+
*/
|
|
119
|
+
async post(path, body, config) {
|
|
120
|
+
return this.request(path, { ...config, method: 'POST', body });
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Make a PUT request
|
|
124
|
+
*/
|
|
125
|
+
async put(path, body, config) {
|
|
126
|
+
return this.request(path, { ...config, method: 'PUT', body });
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Make a PATCH request
|
|
130
|
+
*/
|
|
131
|
+
async patch(path, body, config) {
|
|
132
|
+
return this.request(path, { ...config, method: 'PATCH', body });
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Make a DELETE request
|
|
136
|
+
*/
|
|
137
|
+
async delete(path, config) {
|
|
138
|
+
return this.request(path, { ...config, method: 'DELETE' });
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Make an HTTP request with retry support
|
|
142
|
+
*/
|
|
143
|
+
async request(path, config = {}) {
|
|
144
|
+
const url = `${this.baseUrl}${path.startsWith('/') ? path : `/${path}`}`;
|
|
145
|
+
// Apply request interceptors
|
|
146
|
+
let finalConfig = { ...config };
|
|
147
|
+
for (const interceptor of this.requestInterceptors) {
|
|
148
|
+
finalConfig = await interceptor(url, finalConfig);
|
|
149
|
+
}
|
|
150
|
+
let lastError;
|
|
151
|
+
let attempt = 0;
|
|
152
|
+
while (attempt <= this.retryConfig.maxRetries) {
|
|
153
|
+
try {
|
|
154
|
+
const response = await this.executeRequest(url, finalConfig);
|
|
155
|
+
// Apply response interceptors
|
|
156
|
+
let finalResponse = response;
|
|
157
|
+
for (const interceptor of this.responseInterceptors) {
|
|
158
|
+
finalResponse = (await interceptor(finalResponse));
|
|
159
|
+
}
|
|
160
|
+
return finalResponse;
|
|
161
|
+
}
|
|
162
|
+
catch (error) {
|
|
163
|
+
lastError = error instanceof WebacyError ? error : this.wrapError(error);
|
|
164
|
+
// Apply error interceptors
|
|
165
|
+
for (const interceptor of this.errorInterceptors) {
|
|
166
|
+
lastError = await interceptor(lastError);
|
|
167
|
+
}
|
|
168
|
+
// Check if we should retry
|
|
169
|
+
if (!lastError.isRetryable() || attempt >= this.retryConfig.maxRetries) {
|
|
170
|
+
throw lastError;
|
|
171
|
+
}
|
|
172
|
+
// Calculate retry delay
|
|
173
|
+
const retryAfter = lastError instanceof RateLimitError ? lastError.retryAfter : undefined;
|
|
174
|
+
const delay = calculateRetryDelay(attempt, this.retryConfig, retryAfter);
|
|
175
|
+
await sleep(delay);
|
|
176
|
+
attempt++;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
throw lastError ?? new NetworkError('Request failed after all retries');
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Execute a single HTTP request
|
|
183
|
+
*/
|
|
184
|
+
async executeRequest(url, config) {
|
|
185
|
+
const method = config.method ?? 'GET';
|
|
186
|
+
const timeout = config.timeout ?? this.defaultTimeout;
|
|
187
|
+
const controller = new AbortController();
|
|
188
|
+
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
189
|
+
const startTime = Date.now();
|
|
190
|
+
// Log the outgoing request
|
|
191
|
+
this.logRequest(method, url, config.body);
|
|
192
|
+
// Combine abort signals if user provided one
|
|
193
|
+
const signal = config.signal
|
|
194
|
+
? this.combineAbortSignals(config.signal, controller.signal)
|
|
195
|
+
: controller.signal;
|
|
196
|
+
try {
|
|
197
|
+
const response = await fetch(url, {
|
|
198
|
+
method,
|
|
199
|
+
headers: {
|
|
200
|
+
...this.defaultHeaders,
|
|
201
|
+
...config.headers,
|
|
202
|
+
},
|
|
203
|
+
body: config.body ? JSON.stringify(config.body) : undefined,
|
|
204
|
+
signal,
|
|
205
|
+
});
|
|
206
|
+
clearTimeout(timeoutId);
|
|
207
|
+
const duration = Date.now() - startTime;
|
|
208
|
+
const requestId = response.headers.get('x-request-id') ?? undefined;
|
|
209
|
+
// Handle non-OK responses
|
|
210
|
+
if (!response.ok) {
|
|
211
|
+
const error = await this.createErrorFromResponse(response, requestId, url);
|
|
212
|
+
this.logError(method, url, error);
|
|
213
|
+
throw error;
|
|
214
|
+
}
|
|
215
|
+
// Log successful response
|
|
216
|
+
this.logResponse(method, url, response.status, duration);
|
|
217
|
+
// Parse response body
|
|
218
|
+
const contentType = response.headers.get('content-type');
|
|
219
|
+
let data;
|
|
220
|
+
if (contentType?.includes('application/json')) {
|
|
221
|
+
data = (await response.json());
|
|
222
|
+
}
|
|
223
|
+
else {
|
|
224
|
+
data = (await response.text());
|
|
225
|
+
}
|
|
226
|
+
return {
|
|
227
|
+
data,
|
|
228
|
+
status: response.status,
|
|
229
|
+
headers: response.headers,
|
|
230
|
+
requestId,
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
catch (error) {
|
|
234
|
+
clearTimeout(timeoutId);
|
|
235
|
+
if (error instanceof WebacyError) {
|
|
236
|
+
throw error;
|
|
237
|
+
}
|
|
238
|
+
// Handle fetch errors
|
|
239
|
+
let networkError;
|
|
240
|
+
if (error instanceof Error) {
|
|
241
|
+
if (error.name === 'AbortError') {
|
|
242
|
+
networkError = new NetworkError('Request timed out', { cause: error, endpoint: url });
|
|
243
|
+
}
|
|
244
|
+
else {
|
|
245
|
+
networkError = new NetworkError(error.message, { cause: error, endpoint: url });
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
else {
|
|
249
|
+
networkError = new NetworkError('An unknown error occurred', { endpoint: url });
|
|
250
|
+
}
|
|
251
|
+
this.logError(method, url, networkError);
|
|
252
|
+
throw networkError;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Create an appropriate error from an HTTP response
|
|
257
|
+
*/
|
|
258
|
+
async createErrorFromResponse(response, requestId, endpoint) {
|
|
259
|
+
let errorBody = {};
|
|
260
|
+
try {
|
|
261
|
+
errorBody = (await response.json());
|
|
262
|
+
}
|
|
263
|
+
catch {
|
|
264
|
+
// Ignore JSON parse errors
|
|
265
|
+
}
|
|
266
|
+
const message = errorBody.message ?? errorBody.error ?? response.statusText;
|
|
267
|
+
switch (response.status) {
|
|
268
|
+
case 401:
|
|
269
|
+
case 403:
|
|
270
|
+
return new AuthenticationError(message, { requestId, endpoint });
|
|
271
|
+
case 404:
|
|
272
|
+
return new NotFoundError(message, { requestId, endpoint });
|
|
273
|
+
case 429: {
|
|
274
|
+
const retryAfter = response.headers.get('retry-after');
|
|
275
|
+
const resetAt = response.headers.get('x-ratelimit-reset');
|
|
276
|
+
return new RateLimitError(message, {
|
|
277
|
+
retryAfter: retryAfter ? parseInt(retryAfter, 10) : undefined,
|
|
278
|
+
resetAt: resetAt ? parseInt(resetAt, 10) : undefined,
|
|
279
|
+
requestId,
|
|
280
|
+
endpoint,
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
case 400:
|
|
284
|
+
return new ValidationError(message, {
|
|
285
|
+
errors: errorBody.errors,
|
|
286
|
+
requestId,
|
|
287
|
+
endpoint,
|
|
288
|
+
});
|
|
289
|
+
default:
|
|
290
|
+
if (isRetryableStatusCode(response.status, this.retryConfig)) {
|
|
291
|
+
return new NetworkError(message, {
|
|
292
|
+
cause: new Error(`HTTP ${response.status}`),
|
|
293
|
+
endpoint,
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
return new WebacyError(message, {
|
|
297
|
+
status: response.status,
|
|
298
|
+
code: 'API_ERROR',
|
|
299
|
+
requestId,
|
|
300
|
+
endpoint,
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* Wrap an unknown error in a WebacyError
|
|
306
|
+
*/
|
|
307
|
+
wrapError(error) {
|
|
308
|
+
if (error instanceof WebacyError) {
|
|
309
|
+
return error;
|
|
310
|
+
}
|
|
311
|
+
if (error instanceof Error) {
|
|
312
|
+
return new NetworkError(error.message, { cause: error });
|
|
313
|
+
}
|
|
314
|
+
return new NetworkError('An unknown error occurred');
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* Combine multiple abort signals
|
|
318
|
+
*/
|
|
319
|
+
combineAbortSignals(...signals) {
|
|
320
|
+
const controller = new AbortController();
|
|
321
|
+
for (const signal of signals) {
|
|
322
|
+
if (signal.aborted) {
|
|
323
|
+
controller.abort(signal.reason);
|
|
324
|
+
break;
|
|
325
|
+
}
|
|
326
|
+
signal.addEventListener('abort', () => controller.abort(signal.reason), { once: true });
|
|
327
|
+
}
|
|
328
|
+
return controller.signal;
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../../src/http/client.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,EACX,mBAAmB,EACnB,cAAc,EACd,eAAe,EACf,aAAa,EACb,YAAY,GACb,MAAM,WAAW,CAAC;AACnB,OAAO,EAEL,oBAAoB,EACpB,mBAAmB,EACnB,qBAAqB,EACrB,KAAK,GACN,MAAM,SAAS,CAAC;AACjB,OAAO,EAAqB,aAAa,EAAE,MAAM,WAAW,CAAC;AA6D7D;;GAEG;AACH,MAAM,OAAO,UAAU;IACJ,OAAO,CAAS;IAChB,cAAc,CAAyB;IACvC,cAAc,CAAS;IACvB,WAAW,CAAc;IACzB,mBAAmB,GAAyB,EAAE,CAAC;IAC/C,oBAAoB,GAA0B,EAAE,CAAC;IACjD,iBAAiB,GAAuB,EAAE,CAAC;IAC3C,KAAK,CAAY;IACjB,MAAM,CAAS;IAEhC,YAAY,MAAwB;QAClC,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC,wBAAwB;QAC1E,IAAI,CAAC,cAAc,GAAG;YACpB,cAAc,EAAE,kBAAkB;YAClC,MAAM,EAAE,kBAAkB;YAC1B,GAAG,MAAM,CAAC,OAAO;SAClB,CAAC;QACF,IAAI,CAAC,cAAc,GAAG,MAAM,CAAC,OAAO,IAAI,KAAK,CAAC;QAC9C,IAAI,CAAC,WAAW,GAAG,EAAE,GAAG,oBAAoB,EAAE,GAAG,MAAM,CAAC,KAAK,EAAE,CAAC;QAChE,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,IAAI,KAAK,CAAC;QACnC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,IAAI,aAAa,CAAC;IAC/C,CAAC;IAED;;OAEG;IACK,iBAAiB;QACvB,OAAO,IAAI,CAAC,KAAK,KAAK,IAAI,IAAI,IAAI,CAAC,KAAK,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,KAAK,UAAU,CAAC;IAClF,CAAC;IAED;;OAEG;IACK,kBAAkB;QACxB,OAAO,IAAI,CAAC,KAAK,KAAK,IAAI,IAAI,IAAI,CAAC,KAAK,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,KAAK,WAAW,CAAC;IACnF,CAAC;IAED;;OAEG;IACK,eAAe;QACrB,OAAO,IAAI,CAAC,KAAK,KAAK,IAAI,IAAI,IAAI,CAAC,KAAK,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,KAAK,QAAQ,CAAC;IAChF,CAAC;IAED;;OAEG;IACK,UAAU,CAAC,MAAc,EAAE,GAAW,EAAE,IAAc;QAC5D,IAAI,IAAI,CAAC,iBAAiB,EAAE,EAAE,CAAC;YAC7B,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,MAAM,IAAI,GAAG,EAAE,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;QAChG,CAAC;IACH,CAAC;IAED;;OAEG;IACK,WAAW,CAAC,MAAc,EAAE,GAAW,EAAE,MAAc,EAAE,QAAgB;QAC/E,IAAI,IAAI,CAAC,kBAAkB,EAAE,EAAE,CAAC;YAC9B,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,MAAM,IAAI,GAAG,IAAI,MAAM,KAAK,QAAQ,KAAK,CAAC,CAAC;QACpE,CAAC;IACH,CAAC;IAED;;OAEG;IACK,QAAQ,CAAC,MAAc,EAAE,GAAW,EAAE,KAAkB;QAC9D,IAAI,IAAI,CAAC,eAAe,EAAE,EAAE,CAAC;YAC3B,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,IAAI,KAAK,KAAK,CAAC,OAAO,EAAE,EAAE;gBACxE,IAAI,EAAE,KAAK,CAAC,IAAI;gBAChB,MAAM,EAAE,KAAK,CAAC,MAAM;gBACpB,SAAS,EAAE,KAAK,CAAC,SAAS;aAC3B,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED;;OAEG;IACK,YAAY,CAAC,IAAa;QAChC,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;YAC9C,OAAO,IAAI,CAAC;QACd,CAAC;QACD,gDAAgD;QAChD,MAAM,SAAS,GAAG,EAAE,GAAI,IAAgC,EAAE,CAAC;QAC3D,MAAM,aAAa,GAAG,CAAC,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;QAC3E,KAAK,MAAM,GAAG,IAAI,aAAa,EAAE,CAAC;YAChC,IAAI,GAAG,IAAI,SAAS,EAAE,CAAC;gBACrB,SAAS,CAAC,GAAG,CAAC,GAAG,YAAY,CAAC;YAChC,CAAC;QACH,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IAED;;OAEG;IACH,qBAAqB,CAAC,WAA+B;QACnD,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC7C,CAAC;IAED;;OAEG;IACH,sBAAsB,CAAC,WAAgC;QACrD,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC9C,CAAC;IAED;;OAEG;IACH,mBAAmB,CAAC,WAA6B;QAC/C,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC3C,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,GAAG,CAAI,IAAY,EAAE,MAA0B;QACnD,OAAO,IAAI,CAAC,OAAO,CAAI,IAAI,EAAE,EAAE,GAAG,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;IAC7D,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,IAAI,CACR,IAAY,EACZ,IAAc,EACd,MAA0B;QAE1B,OAAO,IAAI,CAAC,OAAO,CAAI,IAAI,EAAE,EAAE,GAAG,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;IACpE,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,GAAG,CAAI,IAAY,EAAE,IAAc,EAAE,MAA0B;QACnE,OAAO,IAAI,CAAC,OAAO,CAAI,IAAI,EAAE,EAAE,GAAG,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACnE,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,KAAK,CACT,IAAY,EACZ,IAAc,EACd,MAA0B;QAE1B,OAAO,IAAI,CAAC,OAAO,CAAI,IAAI,EAAE,EAAE,GAAG,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;IACrE,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,MAAM,CAAI,IAAY,EAAE,MAA0B;QACtD,OAAO,IAAI,CAAC,OAAO,CAAI,IAAI,EAAE,EAAE,GAAG,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC;IAChE,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,OAAO,CAAI,IAAY,EAAE,SAA4B,EAAE;QACnE,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,EAAE,CAAC;QAEzE,6BAA6B;QAC7B,IAAI,WAAW,GAAG,EAAE,GAAG,MAAM,EAAE,CAAC;QAChC,KAAK,MAAM,WAAW,IAAI,IAAI,CAAC,mBAAmB,EAAE,CAAC;YACnD,WAAW,GAAG,MAAM,WAAW,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;QACpD,CAAC;QAED,IAAI,SAAkC,CAAC;QACvC,IAAI,OAAO,GAAG,CAAC,CAAC;QAEhB,OAAO,OAAO,IAAI,IAAI,CAAC,WAAW,CAAC,UAAU,EAAE,CAAC;YAC9C,IAAI,CAAC;gBACH,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,cAAc,CAAI,GAAG,EAAE,WAAW,CAAC,CAAC;gBAEhE,8BAA8B;gBAC9B,IAAI,aAAa,GAAoB,QAAQ,CAAC;gBAC9C,KAAK,MAAM,WAAW,IAAI,IAAI,CAAC,oBAAoB,EAAE,CAAC;oBACpD,aAAa,GAAG,CAAC,MAAM,WAAW,CAAC,aAAa,CAAC,CAAoB,CAAC;gBACxE,CAAC;gBAED,OAAO,aAAa,CAAC;YACvB,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,SAAS,GAAG,KAAK,YAAY,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;gBAEzE,2BAA2B;gBAC3B,KAAK,MAAM,WAAW,IAAI,IAAI,CAAC,iBAAiB,EAAE,CAAC;oBACjD,SAAS,GAAG,MAAM,WAAW,CAAC,SAAS,CAAC,CAAC;gBAC3C,CAAC;gBAED,2BAA2B;gBAC3B,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE,IAAI,OAAO,IAAI,IAAI,CAAC,WAAW,CAAC,UAAU,EAAE,CAAC;oBACvE,MAAM,SAAS,CAAC;gBAClB,CAAC;gBAED,wBAAwB;gBACxB,MAAM,UAAU,GAAG,SAAS,YAAY,cAAc,CAAC,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC;gBAC1F,MAAM,KAAK,GAAG,mBAAmB,CAAC,OAAO,EAAE,IAAI,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;gBAEzE,MAAM,KAAK,CAAC,KAAK,CAAC,CAAC;gBACnB,OAAO,EAAE,CAAC;YACZ,CAAC;QACH,CAAC;QAED,MAAM,SAAS,IAAI,IAAI,YAAY,CAAC,kCAAkC,CAAC,CAAC;IAC1E,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,cAAc,CAC1B,GAAW,EACX,MAAyB;QAEzB,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,IAAI,KAAK,CAAC;QACtC,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,IAAI,IAAI,CAAC,cAAc,CAAC;QACtD,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;QACzC,MAAM,SAAS,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,OAAO,CAAC,CAAC;QAChE,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAE7B,2BAA2B;QAC3B,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;QAE1C,6CAA6C;QAC7C,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM;YAC1B,CAAC,CAAC,IAAI,CAAC,mBAAmB,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,MAAM,CAAC;YAC5D,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC;QAEtB,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;gBAChC,MAAM;gBACN,OAAO,EAAE;oBACP,GAAG,IAAI,CAAC,cAAc;oBACtB,GAAG,MAAM,CAAC,OAAO;iBAClB;gBACD,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS;gBAC3D,MAAM;aACP,CAAC,CAAC;YAEH,YAAY,CAAC,SAAS,CAAC,CAAC;YACxB,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;YAExC,MAAM,SAAS,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,SAAS,CAAC;YAEpE,0BAA0B;YAC1B,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,uBAAuB,CAAC,QAAQ,EAAE,SAAS,EAAE,GAAG,CAAC,CAAC;gBAC3E,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;gBAClC,MAAM,KAAK,CAAC;YACd,CAAC;YAED,0BAA0B;YAC1B,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,GAAG,EAAE,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;YAEzD,sBAAsB;YACtB,MAAM,WAAW,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;YACzD,IAAI,IAAO,CAAC;YAEZ,IAAI,WAAW,EAAE,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAAC;gBAC9C,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAM,CAAC;YACtC,CAAC;iBAAM,CAAC;gBACN,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAiB,CAAC;YACjD,CAAC;YAED,OAAO;gBACL,IAAI;gBACJ,MAAM,EAAE,QAAQ,CAAC,MAAM;gBACvB,OAAO,EAAE,QAAQ,CAAC,OAAO;gBACzB,SAAS;aACV,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,YAAY,CAAC,SAAS,CAAC,CAAC;YAExB,IAAI,KAAK,YAAY,WAAW,EAAE,CAAC;gBACjC,MAAM,KAAK,CAAC;YACd,CAAC;YAED,sBAAsB;YACtB,IAAI,YAA0B,CAAC;YAC/B,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;gBAC3B,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;oBAChC,YAAY,GAAG,IAAI,YAAY,CAAC,mBAAmB,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,CAAC;gBACxF,CAAC;qBAAM,CAAC;oBACN,YAAY,GAAG,IAAI,YAAY,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,CAAC;gBAClF,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,YAAY,GAAG,IAAI,YAAY,CAAC,2BAA2B,EAAE,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,CAAC;YAClF,CAAC;YAED,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,GAAG,EAAE,YAAY,CAAC,CAAC;YACzC,MAAM,YAAY,CAAC;QACrB,CAAC;IACH,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,uBAAuB,CACnC,QAAkB,EAClB,SAAkB,EAClB,QAAiB;QAEjB,IAAI,SAAS,GAA4E,EAAE,CAAC;QAE5F,IAAI,CAAC;YACH,SAAS,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAqB,CAAC;QAC1D,CAAC;QAAC,MAAM,CAAC;YACP,2BAA2B;QAC7B,CAAC;QAED,MAAM,OAAO,GAAG,SAAS,CAAC,OAAO,IAAI,SAAS,CAAC,KAAK,IAAI,QAAQ,CAAC,UAAU,CAAC;QAE5E,QAAQ,QAAQ,CAAC,MAAM,EAAE,CAAC;YACxB,KAAK,GAAG,CAAC;YACT,KAAK,GAAG;gBACN,OAAO,IAAI,mBAAmB,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,CAAC;YAEnE,KAAK,GAAG;gBACN,OAAO,IAAI,aAAa,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,CAAC;YAE7D,KAAK,GAAG,CAAC,CAAC,CAAC;gBACT,MAAM,UAAU,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;gBACvD,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;gBAC1D,OAAO,IAAI,cAAc,CAAC,OAAO,EAAE;oBACjC,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS;oBAC7D,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS;oBACpD,SAAS;oBACT,QAAQ;iBACT,CAAC,CAAC;YACL,CAAC;YAED,KAAK,GAAG;gBACN,OAAO,IAAI,eAAe,CAAC,OAAO,EAAE;oBAClC,MAAM,EAAE,SAAS,CAAC,MAAM;oBACxB,SAAS;oBACT,QAAQ;iBACT,CAAC,CAAC;YAEL;gBACE,IAAI,qBAAqB,CAAC,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;oBAC7D,OAAO,IAAI,YAAY,CAAC,OAAO,EAAE;wBAC/B,KAAK,EAAE,IAAI,KAAK,CAAC,QAAQ,QAAQ,CAAC,MAAM,EAAE,CAAC;wBAC3C,QAAQ;qBACT,CAAC,CAAC;gBACL,CAAC;gBACD,OAAO,IAAI,WAAW,CAAC,OAAO,EAAE;oBAC9B,MAAM,EAAE,QAAQ,CAAC,MAAM;oBACvB,IAAI,EAAE,WAAW;oBACjB,SAAS;oBACT,QAAQ;iBACT,CAAC,CAAC;QACP,CAAC;IACH,CAAC;IAED;;OAEG;IACK,SAAS,CAAC,KAAc;QAC9B,IAAI,KAAK,YAAY,WAAW,EAAE,CAAC;YACjC,OAAO,KAAK,CAAC;QACf,CAAC;QACD,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;YAC3B,OAAO,IAAI,YAAY,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;QAC3D,CAAC;QACD,OAAO,IAAI,YAAY,CAAC,2BAA2B,CAAC,CAAC;IACvD,CAAC;IAED;;OAEG;IACK,mBAAmB,CAAC,GAAG,OAAsB;QACnD,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;QAEzC,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YAC7B,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;gBACnB,UAAU,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;gBAChC,MAAM;YACR,CAAC;YACD,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QAC1F,CAAC;QAED,OAAO,UAAU,CAAC,MAAM,CAAC;IAC3B,CAAC;CACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/http/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,GAOX,MAAM,UAAU,CAAC;AAElB,OAAO,EAEL,oBAAoB,EACpB,mBAAmB,EACnB,qBAAqB,EACrB,KAAK,GACN,MAAM,SAAS,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Default retry configuration
|
|
3
|
+
*/
|
|
4
|
+
export const DEFAULT_RETRY_CONFIG = {
|
|
5
|
+
maxRetries: 3,
|
|
6
|
+
initialDelay: 1000,
|
|
7
|
+
maxDelay: 30000,
|
|
8
|
+
backoffMultiplier: 2,
|
|
9
|
+
retryableStatusCodes: [408, 429, 500, 502, 503, 504],
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Calculate delay for a retry attempt using exponential backoff with jitter
|
|
13
|
+
*/
|
|
14
|
+
export function calculateRetryDelay(attempt, config, retryAfter) {
|
|
15
|
+
// If server provided Retry-After, use it
|
|
16
|
+
if (retryAfter && retryAfter > 0) {
|
|
17
|
+
return Math.min(retryAfter * 1000, config.maxDelay);
|
|
18
|
+
}
|
|
19
|
+
// Exponential backoff with jitter
|
|
20
|
+
const exponentialDelay = config.initialDelay * Math.pow(config.backoffMultiplier, attempt);
|
|
21
|
+
const jitter = Math.random() * 0.3 * exponentialDelay; // 30% jitter
|
|
22
|
+
const delay = exponentialDelay + jitter;
|
|
23
|
+
return Math.min(delay, config.maxDelay);
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Check if a status code is retryable
|
|
27
|
+
*/
|
|
28
|
+
export function isRetryableStatusCode(statusCode, config) {
|
|
29
|
+
return config.retryableStatusCodes.includes(statusCode);
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Sleep for a given number of milliseconds
|
|
33
|
+
*/
|
|
34
|
+
export function sleep(ms) {
|
|
35
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=retry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retry.js","sourceRoot":"","sources":["../../../src/http/retry.ts"],"names":[],"mappings":"AAgBA;;GAEG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAgB;IAC/C,UAAU,EAAE,CAAC;IACb,YAAY,EAAE,IAAI;IAClB,QAAQ,EAAE,KAAK;IACf,iBAAiB,EAAE,CAAC;IACpB,oBAAoB,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC;CACrD,CAAC;AAEF;;GAEG;AACH,MAAM,UAAU,mBAAmB,CACjC,OAAe,EACf,MAAmB,EACnB,UAAmB;IAEnB,yCAAyC;IACzC,IAAI,UAAU,IAAI,UAAU,GAAG,CAAC,EAAE,CAAC;QACjC,OAAO,IAAI,CAAC,GAAG,CAAC,UAAU,GAAG,IAAI,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;IACtD,CAAC;IAED,kCAAkC;IAClC,MAAM,gBAAgB,GAAG,MAAM,CAAC,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,iBAAiB,EAAE,OAAO,CAAC,CAAC;IAC3F,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE,GAAG,GAAG,GAAG,gBAAgB,CAAC,CAAC,aAAa;IACpE,MAAM,KAAK,GAAG,gBAAgB,GAAG,MAAM,CAAC;IAExC,OAAO,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;AAC1C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,qBAAqB,CAAC,UAAkB,EAAE,MAAmB;IAC3E,OAAO,MAAM,CAAC,oBAAoB,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;AAC1D,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,KAAK,CAAC,EAAU;IAC9B,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AAC3D,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// Configuration
|
|
2
|
+
export { DEFAULT_CONFIG, buildBaseUrl, defaultLogger, } from './config';
|
|
3
|
+
// Base client
|
|
4
|
+
export { BaseClient } from './client-base';
|
|
5
|
+
// HTTP client
|
|
6
|
+
export { HttpClient, DEFAULT_RETRY_CONFIG, } from './http';
|
|
7
|
+
// Errors
|
|
8
|
+
export { WebacyError, AuthenticationError, RateLimitError, ValidationError, NotFoundError, NetworkError, } from './errors';
|
|
9
|
+
// Types
|
|
10
|
+
export { Chain, ChainCompatibility, getChainCompatibility, isEvmChain, CHAIN_IDS, CHAIN_NAMES, RiskModule, RiskScore, RiskLevel, TypeOfAddress, TokenStandard, } from './types';
|
|
11
|
+
// Utilities
|
|
12
|
+
export { isValidAddress, isValidEvmAddress, isValidSolanaAddress, isValidBitcoinAddress, isValidTonAddress, isValidSuiAddress, isValidStellarAddress, normalizeAddress, normalizeEvmAddress, } from './utils';
|
|
13
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,gBAAgB;AAChB,OAAO,EAEL,cAAc,EACd,YAAY,EAGZ,aAAa,GACd,MAAM,UAAU,CAAC;AAElB,cAAc;AACd,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAE3C,cAAc;AACd,OAAO,EACL,UAAU,EAQV,oBAAoB,GACrB,MAAM,QAAQ,CAAC;AAEhB,SAAS;AACT,OAAO,EACL,WAAW,EACX,mBAAmB,EACnB,cAAc,EACd,eAAe,EACf,aAAa,EACb,YAAY,GACb,MAAM,UAAU,CAAC;AAElB,QAAQ;AACR,OAAO,EACL,KAAK,EACL,kBAAkB,EAClB,qBAAqB,EACrB,UAAU,EACV,SAAS,EACT,WAAW,EACX,UAAU,EACV,SAAS,EACT,SAAS,EACT,aAAa,EACb,aAAa,GAgBd,MAAM,SAAS,CAAC;AAEjB,YAAY;AACZ,OAAO,EACL,cAAc,EACd,iBAAiB,EACjB,oBAAoB,EACpB,qBAAqB,EACrB,iBAAiB,EACjB,iBAAiB,EACjB,qBAAqB,EACrB,gBAAgB,EAChB,mBAAmB,GACpB,MAAM,SAAS,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"type":"module"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Supported blockchain networks
|
|
3
|
+
*/
|
|
4
|
+
export var Chain;
|
|
5
|
+
(function (Chain) {
|
|
6
|
+
/** Ethereum Mainnet */
|
|
7
|
+
Chain["ETH"] = "eth";
|
|
8
|
+
/** Ethereum Sepolia Testnet */
|
|
9
|
+
Chain["SEP"] = "sep";
|
|
10
|
+
/** Arbitrum One */
|
|
11
|
+
Chain["ARB"] = "arb";
|
|
12
|
+
/** Polygon (MATIC) */
|
|
13
|
+
Chain["POL"] = "pol";
|
|
14
|
+
/** Solana */
|
|
15
|
+
Chain["SOL"] = "sol";
|
|
16
|
+
/** Optimism */
|
|
17
|
+
Chain["OPT"] = "opt";
|
|
18
|
+
/** Base */
|
|
19
|
+
Chain["BASE"] = "base";
|
|
20
|
+
/** BNB Smart Chain */
|
|
21
|
+
Chain["BSC"] = "bsc";
|
|
22
|
+
/** TON (The Open Network) */
|
|
23
|
+
Chain["TON"] = "ton";
|
|
24
|
+
/** Sei */
|
|
25
|
+
Chain["SEI"] = "sei";
|
|
26
|
+
/** Bitcoin */
|
|
27
|
+
Chain["BTC"] = "btc";
|
|
28
|
+
/** Sui */
|
|
29
|
+
Chain["SUI"] = "sui";
|
|
30
|
+
/** Stellar */
|
|
31
|
+
Chain["STELLAR"] = "stellar";
|
|
32
|
+
})(Chain || (Chain = {}));
|
|
33
|
+
/**
|
|
34
|
+
* Chain compatibility groups for feature detection
|
|
35
|
+
*/
|
|
36
|
+
export var ChainCompatibility;
|
|
37
|
+
(function (ChainCompatibility) {
|
|
38
|
+
ChainCompatibility["EVM"] = "EVM";
|
|
39
|
+
ChainCompatibility["SOLANA"] = "SOLANA";
|
|
40
|
+
ChainCompatibility["TON"] = "TON";
|
|
41
|
+
ChainCompatibility["BTC"] = "BTC";
|
|
42
|
+
ChainCompatibility["SEI"] = "SEI";
|
|
43
|
+
ChainCompatibility["SUI"] = "SUI";
|
|
44
|
+
ChainCompatibility["STELLAR"] = "STELLAR";
|
|
45
|
+
})(ChainCompatibility || (ChainCompatibility = {}));
|
|
46
|
+
/**
|
|
47
|
+
* Get the compatibility group for a chain
|
|
48
|
+
*/
|
|
49
|
+
export function getChainCompatibility(chain) {
|
|
50
|
+
switch (chain) {
|
|
51
|
+
case Chain.ETH:
|
|
52
|
+
case Chain.SEP:
|
|
53
|
+
case Chain.ARB:
|
|
54
|
+
case Chain.POL:
|
|
55
|
+
case Chain.OPT:
|
|
56
|
+
case Chain.BASE:
|
|
57
|
+
case Chain.BSC:
|
|
58
|
+
return ChainCompatibility.EVM;
|
|
59
|
+
case Chain.SOL:
|
|
60
|
+
return ChainCompatibility.SOLANA;
|
|
61
|
+
case Chain.TON:
|
|
62
|
+
return ChainCompatibility.TON;
|
|
63
|
+
case Chain.BTC:
|
|
64
|
+
return ChainCompatibility.BTC;
|
|
65
|
+
case Chain.SEI:
|
|
66
|
+
return ChainCompatibility.SEI;
|
|
67
|
+
case Chain.SUI:
|
|
68
|
+
return ChainCompatibility.SUI;
|
|
69
|
+
case Chain.STELLAR:
|
|
70
|
+
return ChainCompatibility.STELLAR;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Check if a chain is EVM-compatible
|
|
75
|
+
*/
|
|
76
|
+
export function isEvmChain(chain) {
|
|
77
|
+
return getChainCompatibility(chain) === ChainCompatibility.EVM;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Chain ID mapping for EVM chains
|
|
81
|
+
*/
|
|
82
|
+
export const CHAIN_IDS = {
|
|
83
|
+
[Chain.ETH]: 1,
|
|
84
|
+
[Chain.SEP]: 11155111,
|
|
85
|
+
[Chain.BSC]: 56,
|
|
86
|
+
[Chain.POL]: 137,
|
|
87
|
+
[Chain.OPT]: 10,
|
|
88
|
+
[Chain.ARB]: 42161,
|
|
89
|
+
[Chain.BASE]: 8453,
|
|
90
|
+
};
|
|
91
|
+
/**
|
|
92
|
+
* Human-readable chain names
|
|
93
|
+
*/
|
|
94
|
+
export const CHAIN_NAMES = {
|
|
95
|
+
[Chain.ETH]: 'Ethereum',
|
|
96
|
+
[Chain.SEP]: 'Sepolia',
|
|
97
|
+
[Chain.ARB]: 'Arbitrum',
|
|
98
|
+
[Chain.POL]: 'Polygon',
|
|
99
|
+
[Chain.SOL]: 'Solana',
|
|
100
|
+
[Chain.OPT]: 'Optimism',
|
|
101
|
+
[Chain.BASE]: 'Base',
|
|
102
|
+
[Chain.BSC]: 'BNB Smart Chain',
|
|
103
|
+
[Chain.TON]: 'TON',
|
|
104
|
+
[Chain.SEI]: 'Sei',
|
|
105
|
+
[Chain.BTC]: 'Bitcoin',
|
|
106
|
+
[Chain.SUI]: 'Sui',
|
|
107
|
+
[Chain.STELLAR]: 'Stellar',
|
|
108
|
+
};
|
|
109
|
+
//# sourceMappingURL=chain.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chain.js","sourceRoot":"","sources":["../../../src/types/chain.ts"],"names":[],"mappings":"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"}
|