@acedatacloud/sdk 2026.418.3 → 2026.420.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/README.md CHANGED
@@ -120,6 +120,49 @@ const client = new AceDataCloud({
120
120
 
121
121
  The token can also be set via the `ACEDATACLOUD_API_TOKEN` environment variable.
122
122
 
123
+ ## Paying with X402 Instead of a Bearer Token
124
+
125
+ The SDK supports a pluggable `paymentHandler` that is invoked when the
126
+ API returns `402 Payment Required`. Combine it with
127
+ [`@acedatacloud/x402-client`](https://github.com/AceDataCloud/X402Client)
128
+ to pay for requests on-chain (Base, Solana, SKALE) instead of using a
129
+ Bearer token:
130
+
131
+ ```bash
132
+ npm install @acedatacloud/sdk @acedatacloud/x402-client
133
+ ```
134
+
135
+ ```typescript
136
+ import { AceDataCloud } from '@acedatacloud/sdk';
137
+ import { createX402PaymentHandler } from '@acedatacloud/x402-client';
138
+
139
+ const client = new AceDataCloud({
140
+ // No apiToken needed — the x402 handler pays per request.
141
+ paymentHandler: createX402PaymentHandler({
142
+ network: 'base', // or 'solana' | 'skale'
143
+ evmProvider: window.ethereum,
144
+ evmAddress: '0xYourAddress...',
145
+ }),
146
+ });
147
+
148
+ const result = await client.openai.chat.completions.create({
149
+ model: 'gpt-4o-mini',
150
+ messages: [{ role: 'user', content: 'Say hi in 3 words' }],
151
+ max_tokens: 10,
152
+ });
153
+ ```
154
+
155
+ On each API call, the SDK first sends the request unauthenticated. If
156
+ the server replies with `402`, the SDK passes the `accepts` list to
157
+ the handler, which signs and returns an `X-Payment` header. The SDK
158
+ retries the request once with that header. Everything else — task
159
+ polling, streaming, retries, error mapping — keeps working exactly the
160
+ same.
161
+
162
+ You can still pass a Bearer token alongside the handler if you want a
163
+ mixed mode (some endpoints via subscription, others via x402) — the
164
+ SDK only invokes the handler when it actually sees a `402`.
165
+
123
166
  ## License
124
167
 
125
168
  MIT
package/dist/index.d.mts CHANGED
@@ -1,4 +1,92 @@
1
+ /**
2
+ * Pluggable payment handler hook for the SDK transport.
3
+ *
4
+ * When the API returns `402 Payment Required`, the transport calls the
5
+ * configured `PaymentHandler` to produce the extra headers (typically
6
+ * `X-Payment`) to attach to the retry. This keeps the SDK free of any
7
+ * chain-specific signing logic, and lets callers plug in a real x402
8
+ * implementation such as `@acedatacloud/x402-client`.
9
+ */
10
+ /** Payment requirement as returned by the server in a 402 response. */
11
+ interface PaymentRequirement {
12
+ scheme: string;
13
+ network: string;
14
+ maxAmountRequired: string;
15
+ maxTimeoutSeconds?: number;
16
+ resource?: string;
17
+ description?: string;
18
+ payTo: string;
19
+ asset: string;
20
+ extra?: Record<string, unknown>;
21
+ }
22
+ /** Shape of a 402 response body. */
23
+ interface PaymentRequiredBody {
24
+ x402Version?: number;
25
+ accepts: PaymentRequirement[];
26
+ error?: string;
27
+ }
28
+ /** Context passed to a payment handler when a 402 is observed. */
29
+ interface PaymentHandlerContext {
30
+ url: string;
31
+ method: string;
32
+ body?: unknown;
33
+ accepts: PaymentRequirement[];
34
+ }
35
+ /** Result a payment handler must return. */
36
+ interface PaymentHandlerResult {
37
+ /** Extra headers to attach to the retry (must include `X-Payment`). */
38
+ headers: Record<string, string>;
39
+ }
40
+ /** A callable that signs/settles a payment and returns retry headers. */
41
+ type PaymentHandler = (ctx: PaymentHandlerContext) => Promise<PaymentHandlerResult> | PaymentHandlerResult;
42
+
43
+ /** AceDataCloud SDK errors. */
44
+ declare class AceDataCloudError extends Error {
45
+ constructor(message: string);
46
+ }
47
+ declare class TransportError extends AceDataCloudError {
48
+ constructor(message: string);
49
+ }
50
+ declare class APIError extends AceDataCloudError {
51
+ statusCode: number;
52
+ code: string;
53
+ traceId?: string;
54
+ body: Record<string, unknown>;
55
+ constructor(opts: {
56
+ message: string;
57
+ statusCode: number;
58
+ code: string;
59
+ traceId?: string;
60
+ body?: Record<string, unknown>;
61
+ });
62
+ }
63
+ declare class AuthenticationError extends APIError {
64
+ constructor(opts: ConstructorParameters<typeof APIError>[0]);
65
+ }
66
+ declare class TokenMismatchError extends APIError {
67
+ constructor(opts: ConstructorParameters<typeof APIError>[0]);
68
+ }
69
+ declare class RateLimitError extends APIError {
70
+ constructor(opts: ConstructorParameters<typeof APIError>[0]);
71
+ }
72
+ declare class ValidationError extends APIError {
73
+ constructor(opts: ConstructorParameters<typeof APIError>[0]);
74
+ }
75
+ declare class InsufficientBalanceError extends APIError {
76
+ constructor(opts: ConstructorParameters<typeof APIError>[0]);
77
+ }
78
+ declare class ResourceDisabledError extends APIError {
79
+ constructor(opts: ConstructorParameters<typeof APIError>[0]);
80
+ }
81
+ declare class ModerationError extends APIError {
82
+ constructor(opts: ConstructorParameters<typeof APIError>[0]);
83
+ }
84
+ declare class TimeoutError extends APIError {
85
+ constructor(opts: ConstructorParameters<typeof APIError>[0]);
86
+ }
87
+
1
88
  /** HTTP transport for AceDataCloud SDK. Uses native fetch (Node 18+). */
89
+
2
90
  interface TransportOptions {
3
91
  apiToken?: string;
4
92
  baseURL?: string;
@@ -6,6 +94,14 @@ interface TransportOptions {
6
94
  timeout?: number;
7
95
  maxRetries?: number;
8
96
  headers?: Record<string, string>;
97
+ /**
98
+ * Optional handler invoked when a request returns `402 Payment Required`.
99
+ * The handler receives the parsed `accepts` list and must return the extra
100
+ * headers (typically `X-Payment`) to attach to the automatic retry.
101
+ *
102
+ * See `@acedatacloud/x402-client` for a drop-in implementation.
103
+ */
104
+ paymentHandler?: PaymentHandler;
9
105
  }
10
106
  declare class Transport {
11
107
  private baseURL;
@@ -13,6 +109,7 @@ declare class Transport {
13
109
  private timeout;
14
110
  private maxRetries;
15
111
  private headers;
112
+ private paymentHandler?;
16
113
  constructor(opts?: TransportOptions);
17
114
  request(method: string, path: string, opts?: {
18
115
  json?: Record<string, unknown>;
@@ -273,6 +370,12 @@ interface AceDataCloudOptions {
273
370
  timeout?: number;
274
371
  maxRetries?: number;
275
372
  headers?: Record<string, string>;
373
+ /**
374
+ * Optional payment handler invoked when the API returns `402 Payment
375
+ * Required`. Use `createX402PaymentHandler` from
376
+ * `@acedatacloud/x402-client` to enable on-chain payments via X402.
377
+ */
378
+ paymentHandler?: PaymentHandler;
276
379
  }
277
380
  declare class AceDataCloud {
278
381
  readonly chat: Chat;
@@ -288,49 +391,4 @@ declare class AceDataCloud {
288
391
  constructor(opts?: AceDataCloudOptions);
289
392
  }
290
393
 
291
- /** AceDataCloud SDK errors. */
292
- declare class AceDataCloudError extends Error {
293
- constructor(message: string);
294
- }
295
- declare class TransportError extends AceDataCloudError {
296
- constructor(message: string);
297
- }
298
- declare class APIError extends AceDataCloudError {
299
- statusCode: number;
300
- code: string;
301
- traceId?: string;
302
- body: Record<string, unknown>;
303
- constructor(opts: {
304
- message: string;
305
- statusCode: number;
306
- code: string;
307
- traceId?: string;
308
- body?: Record<string, unknown>;
309
- });
310
- }
311
- declare class AuthenticationError extends APIError {
312
- constructor(opts: ConstructorParameters<typeof APIError>[0]);
313
- }
314
- declare class TokenMismatchError extends APIError {
315
- constructor(opts: ConstructorParameters<typeof APIError>[0]);
316
- }
317
- declare class RateLimitError extends APIError {
318
- constructor(opts: ConstructorParameters<typeof APIError>[0]);
319
- }
320
- declare class ValidationError extends APIError {
321
- constructor(opts: ConstructorParameters<typeof APIError>[0]);
322
- }
323
- declare class InsufficientBalanceError extends APIError {
324
- constructor(opts: ConstructorParameters<typeof APIError>[0]);
325
- }
326
- declare class ResourceDisabledError extends APIError {
327
- constructor(opts: ConstructorParameters<typeof APIError>[0]);
328
- }
329
- declare class ModerationError extends APIError {
330
- constructor(opts: ConstructorParameters<typeof APIError>[0]);
331
- }
332
- declare class TimeoutError extends APIError {
333
- constructor(opts: ConstructorParameters<typeof APIError>[0]);
334
- }
335
-
336
- export { APIError, AceDataCloud, AceDataCloudError, type AceDataCloudOptions, type AudioProvider, AuthenticationError, type ImageProvider, InsufficientBalanceError, ModerationError, RateLimitError, ResourceDisabledError, TaskHandle, type TaskHandleOptions, TimeoutError, TokenMismatchError, TransportError, ValidationError, type VideoProvider };
394
+ export { APIError, AceDataCloud, AceDataCloudError, type AceDataCloudOptions, type AudioProvider, AuthenticationError, type ImageProvider, InsufficientBalanceError, ModerationError, type PaymentHandler, type PaymentHandlerContext, type PaymentHandlerResult, type PaymentRequiredBody, type PaymentRequirement, RateLimitError, ResourceDisabledError, TaskHandle, type TaskHandleOptions, TimeoutError, TokenMismatchError, TransportError, ValidationError, type VideoProvider };
package/dist/index.d.ts CHANGED
@@ -1,4 +1,92 @@
1
+ /**
2
+ * Pluggable payment handler hook for the SDK transport.
3
+ *
4
+ * When the API returns `402 Payment Required`, the transport calls the
5
+ * configured `PaymentHandler` to produce the extra headers (typically
6
+ * `X-Payment`) to attach to the retry. This keeps the SDK free of any
7
+ * chain-specific signing logic, and lets callers plug in a real x402
8
+ * implementation such as `@acedatacloud/x402-client`.
9
+ */
10
+ /** Payment requirement as returned by the server in a 402 response. */
11
+ interface PaymentRequirement {
12
+ scheme: string;
13
+ network: string;
14
+ maxAmountRequired: string;
15
+ maxTimeoutSeconds?: number;
16
+ resource?: string;
17
+ description?: string;
18
+ payTo: string;
19
+ asset: string;
20
+ extra?: Record<string, unknown>;
21
+ }
22
+ /** Shape of a 402 response body. */
23
+ interface PaymentRequiredBody {
24
+ x402Version?: number;
25
+ accepts: PaymentRequirement[];
26
+ error?: string;
27
+ }
28
+ /** Context passed to a payment handler when a 402 is observed. */
29
+ interface PaymentHandlerContext {
30
+ url: string;
31
+ method: string;
32
+ body?: unknown;
33
+ accepts: PaymentRequirement[];
34
+ }
35
+ /** Result a payment handler must return. */
36
+ interface PaymentHandlerResult {
37
+ /** Extra headers to attach to the retry (must include `X-Payment`). */
38
+ headers: Record<string, string>;
39
+ }
40
+ /** A callable that signs/settles a payment and returns retry headers. */
41
+ type PaymentHandler = (ctx: PaymentHandlerContext) => Promise<PaymentHandlerResult> | PaymentHandlerResult;
42
+
43
+ /** AceDataCloud SDK errors. */
44
+ declare class AceDataCloudError extends Error {
45
+ constructor(message: string);
46
+ }
47
+ declare class TransportError extends AceDataCloudError {
48
+ constructor(message: string);
49
+ }
50
+ declare class APIError extends AceDataCloudError {
51
+ statusCode: number;
52
+ code: string;
53
+ traceId?: string;
54
+ body: Record<string, unknown>;
55
+ constructor(opts: {
56
+ message: string;
57
+ statusCode: number;
58
+ code: string;
59
+ traceId?: string;
60
+ body?: Record<string, unknown>;
61
+ });
62
+ }
63
+ declare class AuthenticationError extends APIError {
64
+ constructor(opts: ConstructorParameters<typeof APIError>[0]);
65
+ }
66
+ declare class TokenMismatchError extends APIError {
67
+ constructor(opts: ConstructorParameters<typeof APIError>[0]);
68
+ }
69
+ declare class RateLimitError extends APIError {
70
+ constructor(opts: ConstructorParameters<typeof APIError>[0]);
71
+ }
72
+ declare class ValidationError extends APIError {
73
+ constructor(opts: ConstructorParameters<typeof APIError>[0]);
74
+ }
75
+ declare class InsufficientBalanceError extends APIError {
76
+ constructor(opts: ConstructorParameters<typeof APIError>[0]);
77
+ }
78
+ declare class ResourceDisabledError extends APIError {
79
+ constructor(opts: ConstructorParameters<typeof APIError>[0]);
80
+ }
81
+ declare class ModerationError extends APIError {
82
+ constructor(opts: ConstructorParameters<typeof APIError>[0]);
83
+ }
84
+ declare class TimeoutError extends APIError {
85
+ constructor(opts: ConstructorParameters<typeof APIError>[0]);
86
+ }
87
+
1
88
  /** HTTP transport for AceDataCloud SDK. Uses native fetch (Node 18+). */
89
+
2
90
  interface TransportOptions {
3
91
  apiToken?: string;
4
92
  baseURL?: string;
@@ -6,6 +94,14 @@ interface TransportOptions {
6
94
  timeout?: number;
7
95
  maxRetries?: number;
8
96
  headers?: Record<string, string>;
97
+ /**
98
+ * Optional handler invoked when a request returns `402 Payment Required`.
99
+ * The handler receives the parsed `accepts` list and must return the extra
100
+ * headers (typically `X-Payment`) to attach to the automatic retry.
101
+ *
102
+ * See `@acedatacloud/x402-client` for a drop-in implementation.
103
+ */
104
+ paymentHandler?: PaymentHandler;
9
105
  }
10
106
  declare class Transport {
11
107
  private baseURL;
@@ -13,6 +109,7 @@ declare class Transport {
13
109
  private timeout;
14
110
  private maxRetries;
15
111
  private headers;
112
+ private paymentHandler?;
16
113
  constructor(opts?: TransportOptions);
17
114
  request(method: string, path: string, opts?: {
18
115
  json?: Record<string, unknown>;
@@ -273,6 +370,12 @@ interface AceDataCloudOptions {
273
370
  timeout?: number;
274
371
  maxRetries?: number;
275
372
  headers?: Record<string, string>;
373
+ /**
374
+ * Optional payment handler invoked when the API returns `402 Payment
375
+ * Required`. Use `createX402PaymentHandler` from
376
+ * `@acedatacloud/x402-client` to enable on-chain payments via X402.
377
+ */
378
+ paymentHandler?: PaymentHandler;
276
379
  }
277
380
  declare class AceDataCloud {
278
381
  readonly chat: Chat;
@@ -288,49 +391,4 @@ declare class AceDataCloud {
288
391
  constructor(opts?: AceDataCloudOptions);
289
392
  }
290
393
 
291
- /** AceDataCloud SDK errors. */
292
- declare class AceDataCloudError extends Error {
293
- constructor(message: string);
294
- }
295
- declare class TransportError extends AceDataCloudError {
296
- constructor(message: string);
297
- }
298
- declare class APIError extends AceDataCloudError {
299
- statusCode: number;
300
- code: string;
301
- traceId?: string;
302
- body: Record<string, unknown>;
303
- constructor(opts: {
304
- message: string;
305
- statusCode: number;
306
- code: string;
307
- traceId?: string;
308
- body?: Record<string, unknown>;
309
- });
310
- }
311
- declare class AuthenticationError extends APIError {
312
- constructor(opts: ConstructorParameters<typeof APIError>[0]);
313
- }
314
- declare class TokenMismatchError extends APIError {
315
- constructor(opts: ConstructorParameters<typeof APIError>[0]);
316
- }
317
- declare class RateLimitError extends APIError {
318
- constructor(opts: ConstructorParameters<typeof APIError>[0]);
319
- }
320
- declare class ValidationError extends APIError {
321
- constructor(opts: ConstructorParameters<typeof APIError>[0]);
322
- }
323
- declare class InsufficientBalanceError extends APIError {
324
- constructor(opts: ConstructorParameters<typeof APIError>[0]);
325
- }
326
- declare class ResourceDisabledError extends APIError {
327
- constructor(opts: ConstructorParameters<typeof APIError>[0]);
328
- }
329
- declare class ModerationError extends APIError {
330
- constructor(opts: ConstructorParameters<typeof APIError>[0]);
331
- }
332
- declare class TimeoutError extends APIError {
333
- constructor(opts: ConstructorParameters<typeof APIError>[0]);
334
- }
335
-
336
- export { APIError, AceDataCloud, AceDataCloudError, type AceDataCloudOptions, type AudioProvider, AuthenticationError, type ImageProvider, InsufficientBalanceError, ModerationError, RateLimitError, ResourceDisabledError, TaskHandle, type TaskHandleOptions, TimeoutError, TokenMismatchError, TransportError, ValidationError, type VideoProvider };
394
+ export { APIError, AceDataCloud, AceDataCloudError, type AceDataCloudOptions, type AudioProvider, AuthenticationError, type ImageProvider, InsufficientBalanceError, ModerationError, type PaymentHandler, type PaymentHandlerContext, type PaymentHandlerResult, type PaymentRequiredBody, type PaymentRequirement, RateLimitError, ResourceDisabledError, TaskHandle, type TaskHandleOptions, TimeoutError, TokenMismatchError, TransportError, ValidationError, type VideoProvider };
package/dist/index.js CHANGED
@@ -135,10 +135,10 @@ var ERROR_CODE_MAP = {
135
135
  };
136
136
  var RETRY_STATUS_CODES = /* @__PURE__ */ new Set([408, 409, 429, 500, 502, 503, 504]);
137
137
  function mapError(statusCode, body) {
138
- const errorData = body.error ?? {};
138
+ const errorData = body && typeof body === "object" ? body.error ?? {} : {};
139
139
  const code = errorData.code ?? "";
140
140
  const message = errorData.message ?? "";
141
- const traceId = body.trace_id;
141
+ const traceId = body && typeof body === "object" ? body.trace_id : void 0;
142
142
  let ErrorClass = ERROR_CODE_MAP[code];
143
143
  if (!ErrorClass) {
144
144
  if (statusCode === 403) ErrorClass = ModerationError;
@@ -162,11 +162,12 @@ var Transport = class {
162
162
  timeout;
163
163
  maxRetries;
164
164
  headers;
165
+ paymentHandler;
165
166
  constructor(opts = {}) {
166
167
  const token = opts.apiToken ?? process.env.ACEDATACLOUD_API_TOKEN ?? "";
167
- if (!token) {
168
+ if (!token && !opts.paymentHandler) {
168
169
  throw new AuthenticationError({
169
- message: "apiToken is required. Pass it to the client or set ACEDATACLOUD_API_TOKEN.",
170
+ message: "apiToken is required (or provide a paymentHandler, e.g. from @acedatacloud/x402-client). Pass it to the client or set ACEDATACLOUD_API_TOKEN.",
170
171
  statusCode: 0,
171
172
  code: "no_token"
172
173
  });
@@ -175,13 +176,17 @@ var Transport = class {
175
176
  this.platformBaseURL = (opts.platformBaseURL ?? "https://platform.acedata.cloud").replace(/\/+$/, "");
176
177
  this.timeout = opts.timeout ?? 3e5;
177
178
  this.maxRetries = opts.maxRetries ?? 2;
178
- this.headers = {
179
+ this.paymentHandler = opts.paymentHandler;
180
+ const baseHeaders = {
179
181
  accept: "application/json",
180
- authorization: `Bearer ${token}`,
181
182
  "content-type": "application/json",
182
183
  "user-agent": "acedatacloud-node/0.1.0",
183
184
  ...opts.headers ?? {}
184
185
  };
186
+ if (token) {
187
+ baseHeaders.authorization = `Bearer ${token}`;
188
+ }
189
+ this.headers = baseHeaders;
185
190
  }
186
191
  async request(method, path2, opts = {}) {
187
192
  const base = opts.platform ? this.platformBaseURL : this.baseURL;
@@ -193,17 +198,40 @@ var Transport = class {
193
198
  const headers = { ...this.headers, ...opts.headers ?? {} };
194
199
  const timeoutMs = opts.timeout ?? this.timeout;
195
200
  let lastError = null;
201
+ let paymentAttempted = false;
202
+ let extraHeaders = {};
196
203
  for (let attempt = 0; attempt <= this.maxRetries; attempt++) {
197
204
  const controller = new AbortController();
198
205
  const timer = setTimeout(() => controller.abort(), timeoutMs);
199
206
  try {
200
207
  const resp = await fetch(url, {
201
208
  method,
202
- headers,
209
+ headers: { ...headers, ...extraHeaders },
203
210
  body: opts.json ? JSON.stringify(opts.json) : void 0,
204
211
  signal: controller.signal
205
212
  });
206
213
  clearTimeout(timer);
214
+ if (resp.status === 402 && this.paymentHandler && !paymentAttempted) {
215
+ const text = await resp.text();
216
+ let body;
217
+ try {
218
+ body = JSON.parse(text);
219
+ } catch {
220
+ throw mapError(402, { error: { code: "invalid_402", message: text } });
221
+ }
222
+ if (!body.accepts?.length) {
223
+ throw mapError(402, { error: { code: "invalid_402", message: "No payment requirements" } });
224
+ }
225
+ const result = await this.paymentHandler({
226
+ url,
227
+ method,
228
+ body: opts.json,
229
+ accepts: body.accepts
230
+ });
231
+ extraHeaders = { ...extraHeaders, ...result.headers };
232
+ paymentAttempted = true;
233
+ continue;
234
+ }
207
235
  if (resp.status >= 400) {
208
236
  const text = await resp.text();
209
237
  let body;
@@ -683,7 +711,8 @@ var AceDataCloud = class {
683
711
  platformBaseURL: opts.platformBaseURL,
684
712
  timeout: opts.timeout,
685
713
  maxRetries: opts.maxRetries,
686
- headers: opts.headers
714
+ headers: opts.headers,
715
+ paymentHandler: opts.paymentHandler
687
716
  });
688
717
  this.chat = new Chat(this.transport);
689
718
  this.images = new Images(this.transport);