@dtelecom/x402-client 0.1.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 +133 -0
- package/dist/index.d.mts +231 -0
- package/dist/index.d.ts +231 -0
- package/dist/index.js +403 -0
- package/dist/index.mjs +369 -0
- package/package.json +54 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,403 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
ConcurrencyLimitError: () => ConcurrencyLimitError,
|
|
24
|
+
DtelecomGateway: () => DtelecomGateway,
|
|
25
|
+
GatewayError: () => GatewayError,
|
|
26
|
+
InsufficientCreditsError: () => InsufficientCreditsError,
|
|
27
|
+
NoCapacityError: () => NoCapacityError,
|
|
28
|
+
PaymentError: () => PaymentError,
|
|
29
|
+
RateLimitError: () => RateLimitError,
|
|
30
|
+
createAuthHeaders: () => createAuthHeaders
|
|
31
|
+
});
|
|
32
|
+
module.exports = __toCommonJS(index_exports);
|
|
33
|
+
|
|
34
|
+
// src/client.ts
|
|
35
|
+
var import_viem = require("viem");
|
|
36
|
+
var import_chains = require("viem/chains");
|
|
37
|
+
var import_fetch = require("@x402/fetch");
|
|
38
|
+
var import_client = require("@x402/evm/exact/client");
|
|
39
|
+
var import_evm = require("@x402/evm");
|
|
40
|
+
|
|
41
|
+
// src/auth.ts
|
|
42
|
+
async function createAuthHeaders(account, method, path) {
|
|
43
|
+
const timestamp = Math.floor(Date.now() / 1e3).toString();
|
|
44
|
+
const pathname = path.split("?")[0];
|
|
45
|
+
const message = `${method}
|
|
46
|
+
${pathname}
|
|
47
|
+
${timestamp}`;
|
|
48
|
+
const signature = await account.signMessage({ message });
|
|
49
|
+
return {
|
|
50
|
+
Authorization: `evm:${signature}`,
|
|
51
|
+
"X-Wallet-Address": account.address,
|
|
52
|
+
"X-Wallet-Chain": "evm",
|
|
53
|
+
"X-Timestamp": timestamp
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// src/errors.ts
|
|
58
|
+
var GatewayError = class extends Error {
|
|
59
|
+
status;
|
|
60
|
+
constructor(message, status) {
|
|
61
|
+
super(message);
|
|
62
|
+
this.name = "GatewayError";
|
|
63
|
+
this.status = status;
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
var InsufficientCreditsError = class extends GatewayError {
|
|
67
|
+
constructor(message) {
|
|
68
|
+
super(message, 402);
|
|
69
|
+
this.name = "InsufficientCreditsError";
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
var ConcurrencyLimitError = class extends GatewayError {
|
|
73
|
+
constructor(message) {
|
|
74
|
+
super(message, 429);
|
|
75
|
+
this.name = "ConcurrencyLimitError";
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
var RateLimitError = class extends GatewayError {
|
|
79
|
+
constructor(message) {
|
|
80
|
+
super(message, 429);
|
|
81
|
+
this.name = "RateLimitError";
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
var NoCapacityError = class extends GatewayError {
|
|
85
|
+
service;
|
|
86
|
+
constructor(message, service) {
|
|
87
|
+
super(message, 503);
|
|
88
|
+
this.name = "NoCapacityError";
|
|
89
|
+
this.service = service;
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
var PaymentError = class extends GatewayError {
|
|
93
|
+
constructor(message) {
|
|
94
|
+
super(message, 402);
|
|
95
|
+
this.name = "PaymentError";
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
// src/client.ts
|
|
100
|
+
var DtelecomGateway = class {
|
|
101
|
+
baseUrl;
|
|
102
|
+
account;
|
|
103
|
+
fetchWithPayment;
|
|
104
|
+
constructor(config) {
|
|
105
|
+
this.baseUrl = config.gatewayUrl.replace(/\/+$/, "");
|
|
106
|
+
this.account = config.account;
|
|
107
|
+
const publicClient = (0, import_viem.createPublicClient)({ chain: import_chains.base, transport: (0, import_viem.http)() });
|
|
108
|
+
const signer = (0, import_evm.toClientEvmSigner)(config.account, publicClient);
|
|
109
|
+
const x402 = new import_fetch.x402Client();
|
|
110
|
+
(0, import_client.registerExactEvmScheme)(x402, { signer });
|
|
111
|
+
this.fetchWithPayment = (0, import_fetch.wrapFetchWithPayment)(fetch, x402);
|
|
112
|
+
}
|
|
113
|
+
// --- Credits ---
|
|
114
|
+
async buyCredits(options) {
|
|
115
|
+
const r = await this.requestWithPayment("/v1/credits/purchase", {
|
|
116
|
+
wallet_address: this.account.address,
|
|
117
|
+
wallet_chain: "evm",
|
|
118
|
+
amount_usd: options.amountUsd
|
|
119
|
+
});
|
|
120
|
+
return {
|
|
121
|
+
accountId: r.account_id,
|
|
122
|
+
creditedMicrocredits: r.credited_microcredits,
|
|
123
|
+
amountUsd: r.amount_usd
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
// --- Account ---
|
|
127
|
+
async getAccount() {
|
|
128
|
+
const r = await this.request("GET", "/v1/account");
|
|
129
|
+
return {
|
|
130
|
+
id: r.id,
|
|
131
|
+
walletAddress: r.wallet_address,
|
|
132
|
+
walletChain: r.wallet_chain,
|
|
133
|
+
creditBalance: r.credit_balance,
|
|
134
|
+
availableBalance: r.available_balance,
|
|
135
|
+
maxConcurrentSessions: r.max_concurrent_sessions,
|
|
136
|
+
maxApiRate: r.max_api_rate,
|
|
137
|
+
createdAt: r.created_at
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
async getTransactions(options) {
|
|
141
|
+
const params = new URLSearchParams();
|
|
142
|
+
if (options?.limit !== void 0) params.set("limit", String(options.limit));
|
|
143
|
+
if (options?.offset !== void 0)
|
|
144
|
+
params.set("offset", String(options.offset));
|
|
145
|
+
const qs = params.toString();
|
|
146
|
+
const r = await this.request(
|
|
147
|
+
"GET",
|
|
148
|
+
`/v1/account/transactions${qs ? `?${qs}` : ""}`
|
|
149
|
+
);
|
|
150
|
+
return {
|
|
151
|
+
transactions: r.transactions.map(mapTransaction),
|
|
152
|
+
limit: r.limit,
|
|
153
|
+
offset: r.offset
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
async getSessions(options) {
|
|
157
|
+
const params = new URLSearchParams();
|
|
158
|
+
if (options?.limit !== void 0) params.set("limit", String(options.limit));
|
|
159
|
+
if (options?.offset !== void 0)
|
|
160
|
+
params.set("offset", String(options.offset));
|
|
161
|
+
if (options?.status) params.set("status", options.status);
|
|
162
|
+
const qs = params.toString();
|
|
163
|
+
const r = await this.request(
|
|
164
|
+
"GET",
|
|
165
|
+
`/v1/account/sessions${qs ? `?${qs}` : ""}`
|
|
166
|
+
);
|
|
167
|
+
return {
|
|
168
|
+
sessions: r.sessions.map(mapSession),
|
|
169
|
+
limit: r.limit,
|
|
170
|
+
offset: r.offset
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
// --- Bundled Agent Session ---
|
|
174
|
+
async createAgentSession(options) {
|
|
175
|
+
const r = await this.request("POST", "/v1/agent-session", {
|
|
176
|
+
room_name: options.roomName,
|
|
177
|
+
participant_identity: options.participantIdentity,
|
|
178
|
+
duration_minutes: options.durationMinutes,
|
|
179
|
+
language: options.language,
|
|
180
|
+
tts_max_characters: options.ttsMaxCharacters,
|
|
181
|
+
metadata: options.metadata
|
|
182
|
+
});
|
|
183
|
+
return {
|
|
184
|
+
bundleId: r.bundle_id,
|
|
185
|
+
webrtc: {
|
|
186
|
+
sessionId: r.webrtc.session_id,
|
|
187
|
+
token: r.webrtc.token,
|
|
188
|
+
wsUrl: r.webrtc.ws_url
|
|
189
|
+
},
|
|
190
|
+
stt: {
|
|
191
|
+
sessionId: r.stt.session_id,
|
|
192
|
+
token: r.stt.token,
|
|
193
|
+
serverUrl: r.stt.server_url
|
|
194
|
+
},
|
|
195
|
+
tts: {
|
|
196
|
+
sessionId: r.tts.session_id,
|
|
197
|
+
token: r.tts.token,
|
|
198
|
+
serverUrl: r.tts.server_url
|
|
199
|
+
},
|
|
200
|
+
expiresAt: r.expires_at
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
async extendAgentSession(options) {
|
|
204
|
+
const r = await this.request("POST", "/v1/agent-session/extend", {
|
|
205
|
+
bundle_id: options.bundleId,
|
|
206
|
+
additional_minutes: options.additionalMinutes,
|
|
207
|
+
additional_tts_characters: options.additionalTtsCharacters
|
|
208
|
+
});
|
|
209
|
+
const result = {};
|
|
210
|
+
if (r.webrtc) {
|
|
211
|
+
result.webrtc = {
|
|
212
|
+
token: r.webrtc.token,
|
|
213
|
+
newExpiresAt: r.webrtc.new_expires_at
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
if (r.stt) {
|
|
217
|
+
result.stt = {
|
|
218
|
+
token: r.stt.token,
|
|
219
|
+
newExpiresAt: r.stt.new_expires_at
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
if (r.tts) {
|
|
223
|
+
result.tts = {
|
|
224
|
+
token: r.tts.token,
|
|
225
|
+
newExpiresAt: r.tts.new_expires_at
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
return result;
|
|
229
|
+
}
|
|
230
|
+
// --- Standalone WebRTC ---
|
|
231
|
+
async createWebRTCToken(options) {
|
|
232
|
+
const r = await this.request("POST", "/v1/webrtc/token", {
|
|
233
|
+
room_name: options.roomName,
|
|
234
|
+
participant_identity: options.participantIdentity,
|
|
235
|
+
duration_minutes: options.durationMinutes,
|
|
236
|
+
metadata: options.metadata
|
|
237
|
+
});
|
|
238
|
+
return {
|
|
239
|
+
sessionId: r.session_id,
|
|
240
|
+
token: r.token,
|
|
241
|
+
wsUrl: r.ws_url,
|
|
242
|
+
expiresAt: r.expires_at
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
async extendWebRTCToken(options) {
|
|
246
|
+
const r = await this.request("POST", "/v1/webrtc/token/extend", {
|
|
247
|
+
session_id: options.sessionId,
|
|
248
|
+
additional_minutes: options.additionalMinutes
|
|
249
|
+
});
|
|
250
|
+
return {
|
|
251
|
+
token: r.token,
|
|
252
|
+
wsUrl: r.ws_url,
|
|
253
|
+
newExpiresAt: r.new_expires_at
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
// --- Standalone STT ---
|
|
257
|
+
async createSTTSession(options) {
|
|
258
|
+
const r = await this.request("POST", "/v1/stt/session", {
|
|
259
|
+
duration_minutes: options.durationMinutes,
|
|
260
|
+
language: options.language
|
|
261
|
+
});
|
|
262
|
+
return {
|
|
263
|
+
sessionId: r.session_id,
|
|
264
|
+
token: r.token,
|
|
265
|
+
serverUrl: r.server_url,
|
|
266
|
+
expiresAt: r.expires_at
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
async extendSTTSession(options) {
|
|
270
|
+
const r = await this.request("POST", "/v1/stt/session/extend", {
|
|
271
|
+
session_id: options.sessionId,
|
|
272
|
+
additional_minutes: options.additionalMinutes
|
|
273
|
+
});
|
|
274
|
+
return {
|
|
275
|
+
token: r.token,
|
|
276
|
+
newExpiresAt: r.new_expires_at
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
// --- Standalone TTS ---
|
|
280
|
+
async createTTSSession(options) {
|
|
281
|
+
const r = await this.request("POST", "/v1/tts/session", {
|
|
282
|
+
max_characters: options.maxCharacters,
|
|
283
|
+
language: options.language
|
|
284
|
+
});
|
|
285
|
+
return {
|
|
286
|
+
sessionId: r.session_id,
|
|
287
|
+
token: r.token,
|
|
288
|
+
serverUrl: r.server_url,
|
|
289
|
+
expiresAt: r.expires_at
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
async extendTTSSession(options) {
|
|
293
|
+
const r = await this.request("POST", "/v1/tts/session/extend", {
|
|
294
|
+
session_id: options.sessionId,
|
|
295
|
+
additional_characters: options.additionalCharacters
|
|
296
|
+
});
|
|
297
|
+
return {
|
|
298
|
+
token: r.token,
|
|
299
|
+
maxCharacters: r.max_characters,
|
|
300
|
+
newExpiresAt: r.new_expires_at
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
// --- Internal: authenticated request ---
|
|
304
|
+
async request(method, path, body) {
|
|
305
|
+
const headers = await createAuthHeaders(this.account, method, path);
|
|
306
|
+
const init = {
|
|
307
|
+
method,
|
|
308
|
+
headers: {
|
|
309
|
+
...headers,
|
|
310
|
+
...body !== void 0 ? { "Content-Type": "application/json" } : {}
|
|
311
|
+
},
|
|
312
|
+
...body !== void 0 ? { body: JSON.stringify(body) } : {}
|
|
313
|
+
};
|
|
314
|
+
const resp = await fetch(`${this.baseUrl}${path}`, init);
|
|
315
|
+
return this.handleResponse(resp, path);
|
|
316
|
+
}
|
|
317
|
+
// --- Internal: x402 payment request (for buyCredits) ---
|
|
318
|
+
async requestWithPayment(path, body) {
|
|
319
|
+
let resp;
|
|
320
|
+
try {
|
|
321
|
+
resp = await this.fetchWithPayment(`${this.baseUrl}${path}`, {
|
|
322
|
+
method: "POST",
|
|
323
|
+
headers: { "Content-Type": "application/json" },
|
|
324
|
+
body: JSON.stringify(body)
|
|
325
|
+
});
|
|
326
|
+
} catch (err) {
|
|
327
|
+
throw new PaymentError(
|
|
328
|
+
`Payment failed: ${err instanceof Error ? err.message : String(err)}`
|
|
329
|
+
);
|
|
330
|
+
}
|
|
331
|
+
return this.handleResponse(resp, path);
|
|
332
|
+
}
|
|
333
|
+
// --- Internal: response handling ---
|
|
334
|
+
async handleResponse(resp, path) {
|
|
335
|
+
if (resp.ok) {
|
|
336
|
+
return await resp.json();
|
|
337
|
+
}
|
|
338
|
+
const text = await resp.text().catch(() => "");
|
|
339
|
+
let errorMessage;
|
|
340
|
+
try {
|
|
341
|
+
const parsed = JSON.parse(text);
|
|
342
|
+
errorMessage = parsed.error ?? text;
|
|
343
|
+
} catch {
|
|
344
|
+
errorMessage = text || resp.statusText;
|
|
345
|
+
}
|
|
346
|
+
switch (resp.status) {
|
|
347
|
+
case 402:
|
|
348
|
+
throw new InsufficientCreditsError(errorMessage);
|
|
349
|
+
case 429: {
|
|
350
|
+
if (errorMessage.toLowerCase().includes("concurrent")) {
|
|
351
|
+
throw new ConcurrencyLimitError(errorMessage);
|
|
352
|
+
}
|
|
353
|
+
throw new RateLimitError(errorMessage);
|
|
354
|
+
}
|
|
355
|
+
case 503: {
|
|
356
|
+
const service = path.split("/")[2] ?? "unknown";
|
|
357
|
+
throw new NoCapacityError(errorMessage, service);
|
|
358
|
+
}
|
|
359
|
+
default:
|
|
360
|
+
throw new GatewayError(errorMessage, resp.status);
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
};
|
|
364
|
+
function mapTransaction(r) {
|
|
365
|
+
return {
|
|
366
|
+
id: r.id,
|
|
367
|
+
amount: r.amount,
|
|
368
|
+
balanceAfter: r.balance_after,
|
|
369
|
+
type: r.type,
|
|
370
|
+
referenceId: r.reference_id,
|
|
371
|
+
service: r.service,
|
|
372
|
+
description: r.description,
|
|
373
|
+
createdAt: r.created_at
|
|
374
|
+
};
|
|
375
|
+
}
|
|
376
|
+
function mapSession(r) {
|
|
377
|
+
return {
|
|
378
|
+
id: r.id,
|
|
379
|
+
service: r.service,
|
|
380
|
+
bundleId: r.bundle_id,
|
|
381
|
+
status: r.status,
|
|
382
|
+
roomName: r.room_name,
|
|
383
|
+
serverUrl: r.server_url,
|
|
384
|
+
reservedMicrocredits: r.reserved_microcredits,
|
|
385
|
+
chargedMicrocredits: r.charged_microcredits,
|
|
386
|
+
tokenExpiresAt: r.token_expires_at,
|
|
387
|
+
startedAt: r.started_at,
|
|
388
|
+
endedAt: r.ended_at,
|
|
389
|
+
settlementMethod: r.settlement_method,
|
|
390
|
+
createdAt: r.created_at
|
|
391
|
+
};
|
|
392
|
+
}
|
|
393
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
394
|
+
0 && (module.exports = {
|
|
395
|
+
ConcurrencyLimitError,
|
|
396
|
+
DtelecomGateway,
|
|
397
|
+
GatewayError,
|
|
398
|
+
InsufficientCreditsError,
|
|
399
|
+
NoCapacityError,
|
|
400
|
+
PaymentError,
|
|
401
|
+
RateLimitError,
|
|
402
|
+
createAuthHeaders
|
|
403
|
+
});
|