@sly_ai/sdk 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/README.md +346 -0
- package/dist/a2a.d.mts +108 -0
- package/dist/a2a.d.ts +108 -0
- package/dist/a2a.js +173 -0
- package/dist/a2a.js.map +1 -0
- package/dist/a2a.mjs +171 -0
- package/dist/a2a.mjs.map +1 -0
- package/dist/acp.d.mts +201 -0
- package/dist/acp.d.ts +201 -0
- package/dist/acp.js +143 -0
- package/dist/acp.js.map +1 -0
- package/dist/acp.mjs +141 -0
- package/dist/acp.mjs.map +1 -0
- package/dist/ap2.d.mts +188 -0
- package/dist/ap2.d.ts +188 -0
- package/dist/ap2.js +135 -0
- package/dist/ap2.js.map +1 -0
- package/dist/ap2.mjs +133 -0
- package/dist/ap2.mjs.map +1 -0
- package/dist/cards.d.mts +750 -0
- package/dist/cards.d.ts +750 -0
- package/dist/cards.js +373 -0
- package/dist/cards.js.map +1 -0
- package/dist/cards.mjs +369 -0
- package/dist/cards.mjs.map +1 -0
- package/dist/client-Cwe2CLU7.d.mts +41 -0
- package/dist/client-CyJe3uWO.d.ts +41 -0
- package/dist/index.d.mts +662 -0
- package/dist/index.d.ts +662 -0
- package/dist/index.js +2709 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +2700 -0
- package/dist/index.mjs.map +1 -0
- package/dist/langchain.d.mts +11 -0
- package/dist/langchain.d.ts +11 -0
- package/dist/langchain.js +25 -0
- package/dist/langchain.js.map +1 -0
- package/dist/langchain.mjs +23 -0
- package/dist/langchain.mjs.map +1 -0
- package/dist/types-df1EICn_.d.mts +165 -0
- package/dist/types-df1EICn_.d.ts +165 -0
- package/dist/ucp.d.mts +844 -0
- package/dist/ucp.d.ts +844 -0
- package/dist/ucp.js +616 -0
- package/dist/ucp.js.map +1 -0
- package/dist/ucp.mjs +614 -0
- package/dist/ucp.mjs.map +1 -0
- package/dist/vercel.d.mts +178 -0
- package/dist/vercel.d.ts +178 -0
- package/dist/vercel.js +143 -0
- package/dist/vercel.js.map +1 -0
- package/dist/vercel.mjs +138 -0
- package/dist/vercel.mjs.map +1 -0
- package/dist/x402.d.mts +209 -0
- package/dist/x402.d.ts +209 -0
- package/dist/x402.js +476 -0
- package/dist/x402.js.map +1 -0
- package/dist/x402.mjs +471 -0
- package/dist/x402.mjs.map +1 -0
- package/package.json +118 -0
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,2700 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
3
|
+
var __esm = (fn, res) => function __init() {
|
|
4
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
5
|
+
};
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
// src/config.ts
|
|
12
|
+
function inferEnvironmentFromKey(apiKey) {
|
|
13
|
+
if (apiKey.startsWith("pk_test_") || apiKey.startsWith("pk_sandbox_")) {
|
|
14
|
+
return "sandbox";
|
|
15
|
+
}
|
|
16
|
+
if (apiKey.startsWith("pk_live_")) {
|
|
17
|
+
return "production";
|
|
18
|
+
}
|
|
19
|
+
return void 0;
|
|
20
|
+
}
|
|
21
|
+
function getEnvironmentConfig(environment) {
|
|
22
|
+
return ENVIRONMENT_CONFIGS[environment];
|
|
23
|
+
}
|
|
24
|
+
function validateEnvironment(environment, evmPrivateKey) {
|
|
25
|
+
if (environment !== "sandbox" && !evmPrivateKey) {
|
|
26
|
+
throw new Error(
|
|
27
|
+
`EVM private key is required for ${environment} environment. Use sandbox mode for local development without blockchain.`
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
var ENVIRONMENT_CONFIGS;
|
|
32
|
+
var init_config = __esm({
|
|
33
|
+
"src/config.ts"() {
|
|
34
|
+
ENVIRONMENT_CONFIGS = {
|
|
35
|
+
sandbox: {
|
|
36
|
+
apiUrl: "https://sandbox.getsly.ai",
|
|
37
|
+
facilitatorUrl: "https://facilitator.x402.org"
|
|
38
|
+
// x402.org Base Sepolia
|
|
39
|
+
},
|
|
40
|
+
testnet: {
|
|
41
|
+
apiUrl: "https://sandbox.getsly.ai",
|
|
42
|
+
facilitatorUrl: "https://facilitator.x402.org"
|
|
43
|
+
// x402.org Base Sepolia
|
|
44
|
+
},
|
|
45
|
+
production: {
|
|
46
|
+
apiUrl: "https://api.getsly.ai",
|
|
47
|
+
facilitatorUrl: "https://facilitator.coinbase.com"
|
|
48
|
+
// Coinbase CDP Base mainnet
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
// src/client.ts
|
|
55
|
+
var SlyClient;
|
|
56
|
+
var init_client = __esm({
|
|
57
|
+
"src/client.ts"() {
|
|
58
|
+
init_config();
|
|
59
|
+
SlyClient = class {
|
|
60
|
+
constructor(config) {
|
|
61
|
+
this.apiKey = config.apiKey;
|
|
62
|
+
const environment = config.environment ?? inferEnvironmentFromKey(config.apiKey) ?? "sandbox";
|
|
63
|
+
const envConfig = getEnvironmentConfig(environment);
|
|
64
|
+
this.apiUrl = config.apiUrl || envConfig.apiUrl;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Make an authenticated API request
|
|
68
|
+
*/
|
|
69
|
+
async request(path, options = {}) {
|
|
70
|
+
const url = `${this.apiUrl}${path}`;
|
|
71
|
+
const response = await fetch(url, {
|
|
72
|
+
...options,
|
|
73
|
+
headers: {
|
|
74
|
+
"Authorization": `Bearer ${this.apiKey}`,
|
|
75
|
+
"Content-Type": "application/json",
|
|
76
|
+
...options.headers
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
if (!response.ok) {
|
|
80
|
+
const errorData = await response.json().catch(() => ({
|
|
81
|
+
message: response.statusText
|
|
82
|
+
}));
|
|
83
|
+
const error = new Error(errorData.error || errorData.message || `HTTP ${response.status}`);
|
|
84
|
+
error.status = response.status;
|
|
85
|
+
error.data = errorData;
|
|
86
|
+
throw error;
|
|
87
|
+
}
|
|
88
|
+
return response.json();
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Get a settlement quote
|
|
92
|
+
*/
|
|
93
|
+
async getSettlementQuote(request) {
|
|
94
|
+
return this.request("/v1/settlements/quote", {
|
|
95
|
+
method: "POST",
|
|
96
|
+
body: JSON.stringify(request)
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Create a settlement
|
|
101
|
+
*/
|
|
102
|
+
async createSettlement(request) {
|
|
103
|
+
return this.request("/v1/settlements", {
|
|
104
|
+
method: "POST",
|
|
105
|
+
body: JSON.stringify(request)
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Get settlement status
|
|
110
|
+
*/
|
|
111
|
+
async getSettlement(settlementId) {
|
|
112
|
+
return this.request(`/v1/settlements/${settlementId}`);
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Check compliance for a recipient
|
|
116
|
+
*/
|
|
117
|
+
async checkCompliance(request) {
|
|
118
|
+
return this.request("/v1/compliance/check", {
|
|
119
|
+
method: "POST",
|
|
120
|
+
body: JSON.stringify(request)
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Get API capabilities
|
|
125
|
+
*/
|
|
126
|
+
async getCapabilities() {
|
|
127
|
+
return this.request("/v1/capabilities");
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
// src/facilitator/sandbox-facilitator.ts
|
|
134
|
+
var SandboxFacilitator;
|
|
135
|
+
var init_sandbox_facilitator = __esm({
|
|
136
|
+
"src/facilitator/sandbox-facilitator.ts"() {
|
|
137
|
+
SandboxFacilitator = class {
|
|
138
|
+
constructor(config) {
|
|
139
|
+
this.config = {
|
|
140
|
+
apiUrl: config.apiUrl,
|
|
141
|
+
apiKey: config.apiKey,
|
|
142
|
+
settlementDelayMs: config.settlementDelayMs ?? 0,
|
|
143
|
+
failureRate: config.failureRate ?? 0,
|
|
144
|
+
debug: config.debug ?? false,
|
|
145
|
+
supportedSchemes: config.supportedSchemes ?? [
|
|
146
|
+
{
|
|
147
|
+
scheme: "exact-evm",
|
|
148
|
+
networks: ["eip155:8453", "eip155:84532"]
|
|
149
|
+
// Base mainnet and Sepolia
|
|
150
|
+
}
|
|
151
|
+
]
|
|
152
|
+
};
|
|
153
|
+
if (this.config.debug) {
|
|
154
|
+
console.log("[SandboxFacilitator] Initialized with config:", {
|
|
155
|
+
apiUrl: this.config.apiUrl,
|
|
156
|
+
settlementDelayMs: this.config.settlementDelayMs,
|
|
157
|
+
failureRate: this.config.failureRate
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Verify a payment payload
|
|
163
|
+
*
|
|
164
|
+
* In sandbox mode, this validates the structure but skips signature verification
|
|
165
|
+
*/
|
|
166
|
+
async verify(request) {
|
|
167
|
+
const { payment } = request;
|
|
168
|
+
if (this.config.debug) {
|
|
169
|
+
console.log("[SandboxFacilitator] Verifying payment:", payment);
|
|
170
|
+
}
|
|
171
|
+
const requiredFields = ["scheme", "network", "amount", "token", "from", "to"];
|
|
172
|
+
for (const field of requiredFields) {
|
|
173
|
+
if (!payment[field]) {
|
|
174
|
+
return {
|
|
175
|
+
valid: false,
|
|
176
|
+
reason: `Missing required field: ${field}`
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
const schemeSupported = this.config.supportedSchemes.some(
|
|
181
|
+
(s) => s.scheme === payment.scheme
|
|
182
|
+
);
|
|
183
|
+
if (!schemeSupported) {
|
|
184
|
+
return {
|
|
185
|
+
valid: false,
|
|
186
|
+
reason: `Unsupported scheme: ${payment.scheme}`,
|
|
187
|
+
details: {
|
|
188
|
+
supportedSchemes: this.config.supportedSchemes.map((s) => s.scheme)
|
|
189
|
+
}
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
const scheme = this.config.supportedSchemes.find(
|
|
193
|
+
(s) => s.scheme === payment.scheme
|
|
194
|
+
);
|
|
195
|
+
if (scheme && !scheme.networks.includes(payment.network)) {
|
|
196
|
+
return {
|
|
197
|
+
valid: false,
|
|
198
|
+
reason: `Unsupported network: ${payment.network} for scheme: ${payment.scheme}`,
|
|
199
|
+
details: {
|
|
200
|
+
supportedNetworks: scheme.networks
|
|
201
|
+
}
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
const amount = parseFloat(payment.amount);
|
|
205
|
+
if (isNaN(amount) || amount <= 0) {
|
|
206
|
+
return {
|
|
207
|
+
valid: false,
|
|
208
|
+
reason: `Invalid amount: ${payment.amount}`
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
return {
|
|
212
|
+
valid: true
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Settle a payment
|
|
217
|
+
*
|
|
218
|
+
* In sandbox mode, this generates a mock transaction hash and
|
|
219
|
+
* optionally records the payment in PayOS
|
|
220
|
+
*/
|
|
221
|
+
async settle(request) {
|
|
222
|
+
const { payment } = request;
|
|
223
|
+
if (this.config.debug) {
|
|
224
|
+
console.log("[SandboxFacilitator] Settling payment:", payment);
|
|
225
|
+
}
|
|
226
|
+
const verification = await this.verify({ payment });
|
|
227
|
+
if (!verification.valid) {
|
|
228
|
+
throw new Error(`Payment verification failed: ${verification.reason}`);
|
|
229
|
+
}
|
|
230
|
+
if (this.config.failureRate > 0) {
|
|
231
|
+
const random = Math.random() * 100;
|
|
232
|
+
if (random < this.config.failureRate) {
|
|
233
|
+
throw new Error("Simulated settlement failure");
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
if (this.config.settlementDelayMs > 0) {
|
|
237
|
+
await new Promise(
|
|
238
|
+
(resolve) => setTimeout(resolve, this.config.settlementDelayMs)
|
|
239
|
+
);
|
|
240
|
+
}
|
|
241
|
+
const txHash = this.generateMockTxHash();
|
|
242
|
+
if (this.config.debug) {
|
|
243
|
+
console.log("[SandboxFacilitator] Settlement complete:", {
|
|
244
|
+
txHash,
|
|
245
|
+
amount: payment.amount,
|
|
246
|
+
from: payment.from,
|
|
247
|
+
to: payment.to
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
return {
|
|
251
|
+
transactionHash: txHash,
|
|
252
|
+
settled: true,
|
|
253
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Get supported schemes and networks
|
|
258
|
+
*/
|
|
259
|
+
async supported() {
|
|
260
|
+
return {
|
|
261
|
+
schemes: this.config.supportedSchemes
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Generate a realistic-looking mock transaction hash
|
|
266
|
+
*/
|
|
267
|
+
generateMockTxHash() {
|
|
268
|
+
const chars = "0123456789abcdef";
|
|
269
|
+
let hash = "0x";
|
|
270
|
+
for (let i = 0; i < 64; i++) {
|
|
271
|
+
hash += chars[Math.floor(Math.random() * chars.length)];
|
|
272
|
+
}
|
|
273
|
+
return hash;
|
|
274
|
+
}
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
// src/protocols/x402/client.ts
|
|
280
|
+
var SlyX402Client;
|
|
281
|
+
var init_client2 = __esm({
|
|
282
|
+
"src/protocols/x402/client.ts"() {
|
|
283
|
+
init_config();
|
|
284
|
+
init_sandbox_facilitator();
|
|
285
|
+
SlyX402Client = class {
|
|
286
|
+
constructor(config) {
|
|
287
|
+
this.dailySpent = 0;
|
|
288
|
+
validateEnvironment(config.environment, config.evmPrivateKey);
|
|
289
|
+
const envConfig = getEnvironmentConfig(config.environment);
|
|
290
|
+
this.config = {
|
|
291
|
+
apiKey: config.apiKey,
|
|
292
|
+
environment: config.environment,
|
|
293
|
+
evmPrivateKey: config.evmPrivateKey,
|
|
294
|
+
facilitatorUrl: config.facilitatorUrl || envConfig.facilitatorUrl || "",
|
|
295
|
+
maxAutoPayAmount: config.maxAutoPayAmount || "1.00",
|
|
296
|
+
maxDailySpend: config.maxDailySpend || "100.00",
|
|
297
|
+
onPayment: config.onPayment,
|
|
298
|
+
onSettlement: config.onSettlement,
|
|
299
|
+
settleToRail: config.settleToRail
|
|
300
|
+
};
|
|
301
|
+
this.lastResetDate = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
302
|
+
if (this.config.environment === "sandbox") {
|
|
303
|
+
this.sandboxFacilitator = new SandboxFacilitator({
|
|
304
|
+
apiUrl: envConfig.apiUrl,
|
|
305
|
+
apiKey: this.config.apiKey
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
/**
|
|
310
|
+
* Fetch a resource with automatic 402 payment handling
|
|
311
|
+
*/
|
|
312
|
+
async fetch(url, options = {}) {
|
|
313
|
+
const { maxPayment, ...fetchOptions } = options;
|
|
314
|
+
let response = await fetch(url, fetchOptions);
|
|
315
|
+
if (response.status !== 402) {
|
|
316
|
+
return response;
|
|
317
|
+
}
|
|
318
|
+
const paymentRequired = await this.parse402Response(response);
|
|
319
|
+
const acceptedOption = paymentRequired.accepts[0];
|
|
320
|
+
if (!acceptedOption) {
|
|
321
|
+
throw new Error("No acceptable payment options in 402 response");
|
|
322
|
+
}
|
|
323
|
+
const amount = parseFloat(acceptedOption.amount);
|
|
324
|
+
const maxAmount = parseFloat(maxPayment || this.config.maxAutoPayAmount);
|
|
325
|
+
if (amount > maxAmount) {
|
|
326
|
+
throw new Error(
|
|
327
|
+
`Payment amount ${acceptedOption.amount} exceeds max auto-pay amount ${maxPayment || this.config.maxAutoPayAmount}`
|
|
328
|
+
);
|
|
329
|
+
}
|
|
330
|
+
this.resetDailySpendIfNeeded();
|
|
331
|
+
if (this.dailySpent + amount > parseFloat(this.config.maxDailySpend)) {
|
|
332
|
+
throw new Error(
|
|
333
|
+
`Payment would exceed daily limit. Spent: ${this.dailySpent}, Limit: ${this.config.maxDailySpend}`
|
|
334
|
+
);
|
|
335
|
+
}
|
|
336
|
+
const payment = await this.createPayment(acceptedOption);
|
|
337
|
+
if (this.config.onPayment) {
|
|
338
|
+
await this.config.onPayment({
|
|
339
|
+
amount: acceptedOption.amount,
|
|
340
|
+
currency: acceptedOption.token,
|
|
341
|
+
from: payment.from,
|
|
342
|
+
to: payment.to,
|
|
343
|
+
scheme: acceptedOption.scheme,
|
|
344
|
+
network: acceptedOption.network,
|
|
345
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
this.dailySpent += amount;
|
|
349
|
+
response = await fetch(url, {
|
|
350
|
+
...fetchOptions,
|
|
351
|
+
headers: {
|
|
352
|
+
...fetchOptions.headers,
|
|
353
|
+
"X-Payment": JSON.stringify(payment)
|
|
354
|
+
}
|
|
355
|
+
});
|
|
356
|
+
if (this.config.onSettlement && payment.transactionHash) {
|
|
357
|
+
await this.config.onSettlement({
|
|
358
|
+
transactionHash: payment.transactionHash,
|
|
359
|
+
amount: acceptedOption.amount,
|
|
360
|
+
currency: acceptedOption.token,
|
|
361
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
362
|
+
});
|
|
363
|
+
}
|
|
364
|
+
return response;
|
|
365
|
+
}
|
|
366
|
+
/**
|
|
367
|
+
* Get client status
|
|
368
|
+
*/
|
|
369
|
+
getStatus() {
|
|
370
|
+
this.resetDailySpendIfNeeded();
|
|
371
|
+
return {
|
|
372
|
+
environment: this.config.environment,
|
|
373
|
+
dailySpent: this.dailySpent.toFixed(2),
|
|
374
|
+
dailyLimit: this.config.maxDailySpend,
|
|
375
|
+
walletAddress: this.getWalletAddress()
|
|
376
|
+
};
|
|
377
|
+
}
|
|
378
|
+
/**
|
|
379
|
+
* Parse 402 response
|
|
380
|
+
*/
|
|
381
|
+
async parse402Response(response) {
|
|
382
|
+
const body = await response.json();
|
|
383
|
+
if (!body.accepts || !Array.isArray(body.accepts)) {
|
|
384
|
+
throw new Error("Invalid 402 response: missing accepts array");
|
|
385
|
+
}
|
|
386
|
+
return {
|
|
387
|
+
statusCode: 402,
|
|
388
|
+
accepts: body.accepts
|
|
389
|
+
};
|
|
390
|
+
}
|
|
391
|
+
/**
|
|
392
|
+
* Create payment based on environment
|
|
393
|
+
*/
|
|
394
|
+
async createPayment(option) {
|
|
395
|
+
if (this.config.environment === "sandbox") {
|
|
396
|
+
return this.createSandboxPayment(option);
|
|
397
|
+
} else {
|
|
398
|
+
return this.createBlockchainPayment(option);
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
/**
|
|
402
|
+
* Create sandbox payment (mock)
|
|
403
|
+
*/
|
|
404
|
+
async createSandboxPayment(option) {
|
|
405
|
+
if (!this.sandboxFacilitator) {
|
|
406
|
+
throw new Error("Sandbox facilitator not initialized");
|
|
407
|
+
}
|
|
408
|
+
const payment = {
|
|
409
|
+
scheme: option.scheme,
|
|
410
|
+
network: option.network,
|
|
411
|
+
amount: option.amount,
|
|
412
|
+
token: option.token,
|
|
413
|
+
from: "0x0000000000000000000000000000000000000001",
|
|
414
|
+
// Mock address
|
|
415
|
+
to: "0x0000000000000000000000000000000000000002"
|
|
416
|
+
// Mock address
|
|
417
|
+
};
|
|
418
|
+
const settlement = await this.sandboxFacilitator.settle({ payment });
|
|
419
|
+
return {
|
|
420
|
+
...payment,
|
|
421
|
+
transactionHash: settlement.transactionHash
|
|
422
|
+
};
|
|
423
|
+
}
|
|
424
|
+
/**
|
|
425
|
+
* Create blockchain payment (real EVM)
|
|
426
|
+
*/
|
|
427
|
+
async createBlockchainPayment(_option) {
|
|
428
|
+
if (!this.config.evmPrivateKey) {
|
|
429
|
+
throw new Error("EVM private key required for blockchain payments");
|
|
430
|
+
}
|
|
431
|
+
throw new Error("Blockchain payments not yet implemented - use sandbox mode");
|
|
432
|
+
}
|
|
433
|
+
/**
|
|
434
|
+
* Get wallet address based on environment
|
|
435
|
+
*/
|
|
436
|
+
getWalletAddress() {
|
|
437
|
+
if (this.config.environment === "sandbox") {
|
|
438
|
+
return "0x0000000000000000000000000000000000000001";
|
|
439
|
+
}
|
|
440
|
+
return void 0;
|
|
441
|
+
}
|
|
442
|
+
/**
|
|
443
|
+
* Reset daily spend if date has changed
|
|
444
|
+
*/
|
|
445
|
+
resetDailySpendIfNeeded() {
|
|
446
|
+
const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
447
|
+
if (today !== this.lastResetDate) {
|
|
448
|
+
this.dailySpent = 0;
|
|
449
|
+
this.lastResetDate = today;
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
};
|
|
453
|
+
}
|
|
454
|
+
});
|
|
455
|
+
|
|
456
|
+
// src/protocols/x402/provider.ts
|
|
457
|
+
var SlyX402Provider;
|
|
458
|
+
var init_provider = __esm({
|
|
459
|
+
"src/protocols/x402/provider.ts"() {
|
|
460
|
+
init_config();
|
|
461
|
+
init_sandbox_facilitator();
|
|
462
|
+
SlyX402Provider = class {
|
|
463
|
+
constructor(config) {
|
|
464
|
+
const envConfig = getEnvironmentConfig(config.environment);
|
|
465
|
+
this.config = {
|
|
466
|
+
apiKey: config.apiKey,
|
|
467
|
+
environment: config.environment,
|
|
468
|
+
routes: config.routes,
|
|
469
|
+
facilitatorUrl: config.facilitatorUrl || envConfig.facilitatorUrl
|
|
470
|
+
};
|
|
471
|
+
if (this.config.environment === "sandbox") {
|
|
472
|
+
this.sandboxFacilitator = new SandboxFacilitator({
|
|
473
|
+
apiUrl: envConfig.apiUrl,
|
|
474
|
+
apiKey: this.config.apiKey
|
|
475
|
+
});
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
/**
|
|
479
|
+
* Create Express middleware
|
|
480
|
+
*/
|
|
481
|
+
middleware() {
|
|
482
|
+
return async (req, res, next) => {
|
|
483
|
+
try {
|
|
484
|
+
const routeConfig = this.getRouteConfig(req);
|
|
485
|
+
if (!routeConfig) {
|
|
486
|
+
return next();
|
|
487
|
+
}
|
|
488
|
+
const paymentHeader = req.headers["x-payment"];
|
|
489
|
+
if (!paymentHeader) {
|
|
490
|
+
return this.return402(req, res, routeConfig);
|
|
491
|
+
}
|
|
492
|
+
const isValid = await this.verifyPayment(paymentHeader, routeConfig);
|
|
493
|
+
if (!isValid) {
|
|
494
|
+
return this.return402(req, res, routeConfig);
|
|
495
|
+
}
|
|
496
|
+
next();
|
|
497
|
+
} catch (error) {
|
|
498
|
+
res.status(500).json({
|
|
499
|
+
error: "Payment verification failed",
|
|
500
|
+
message: error.message
|
|
501
|
+
});
|
|
502
|
+
}
|
|
503
|
+
};
|
|
504
|
+
}
|
|
505
|
+
/**
|
|
506
|
+
* Get route configuration for request
|
|
507
|
+
*/
|
|
508
|
+
getRouteConfig(req) {
|
|
509
|
+
const routeKey = `${req.method} ${req.path}`;
|
|
510
|
+
if (this.config.routes[routeKey]) {
|
|
511
|
+
return this.config.routes[routeKey];
|
|
512
|
+
}
|
|
513
|
+
for (const [pattern, config] of Object.entries(this.config.routes)) {
|
|
514
|
+
if (this.matchRoute(pattern, routeKey)) {
|
|
515
|
+
return config;
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
return null;
|
|
519
|
+
}
|
|
520
|
+
/**
|
|
521
|
+
* Simple route pattern matching
|
|
522
|
+
*/
|
|
523
|
+
matchRoute(pattern, route) {
|
|
524
|
+
const regexPattern = pattern.replace(/\*/g, ".*").replace(/\//g, "\\/");
|
|
525
|
+
const regex = new RegExp(`^${regexPattern}$`);
|
|
526
|
+
return regex.test(route);
|
|
527
|
+
}
|
|
528
|
+
/**
|
|
529
|
+
* Return 402 Payment Required response
|
|
530
|
+
*/
|
|
531
|
+
return402(_req, res, routeConfig) {
|
|
532
|
+
const scheme = "exact-evm";
|
|
533
|
+
const network = this.config.environment === "sandbox" ? "eip155:8453" : "eip155:8453";
|
|
534
|
+
res.status(402).json({
|
|
535
|
+
statusCode: 402,
|
|
536
|
+
message: "Payment Required",
|
|
537
|
+
accepts: [
|
|
538
|
+
{
|
|
539
|
+
scheme,
|
|
540
|
+
network,
|
|
541
|
+
token: routeConfig.token || "USDC",
|
|
542
|
+
amount: routeConfig.price,
|
|
543
|
+
facilitator: this.config.facilitatorUrl,
|
|
544
|
+
description: routeConfig.description
|
|
545
|
+
}
|
|
546
|
+
]
|
|
547
|
+
});
|
|
548
|
+
}
|
|
549
|
+
/**
|
|
550
|
+
* Verify payment
|
|
551
|
+
*/
|
|
552
|
+
async verifyPayment(paymentHeader, routeConfig) {
|
|
553
|
+
try {
|
|
554
|
+
const payment = JSON.parse(paymentHeader);
|
|
555
|
+
if (payment.amount !== routeConfig.price) {
|
|
556
|
+
return false;
|
|
557
|
+
}
|
|
558
|
+
const expectedToken = routeConfig.token || "USDC";
|
|
559
|
+
if (payment.token !== expectedToken) {
|
|
560
|
+
return false;
|
|
561
|
+
}
|
|
562
|
+
if (this.config.environment === "sandbox") {
|
|
563
|
+
return this.verifySandboxPayment(payment);
|
|
564
|
+
} else {
|
|
565
|
+
return this.verifyBlockchainPayment(payment);
|
|
566
|
+
}
|
|
567
|
+
} catch (error) {
|
|
568
|
+
return false;
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
/**
|
|
572
|
+
* Verify sandbox payment
|
|
573
|
+
*/
|
|
574
|
+
async verifySandboxPayment(payment) {
|
|
575
|
+
if (!this.sandboxFacilitator) {
|
|
576
|
+
return false;
|
|
577
|
+
}
|
|
578
|
+
const result = await this.sandboxFacilitator.verify({ payment });
|
|
579
|
+
return result.valid;
|
|
580
|
+
}
|
|
581
|
+
/**
|
|
582
|
+
* Verify blockchain payment
|
|
583
|
+
*/
|
|
584
|
+
async verifyBlockchainPayment(_payment) {
|
|
585
|
+
throw new Error("Blockchain payment verification not yet implemented - use sandbox mode");
|
|
586
|
+
}
|
|
587
|
+
};
|
|
588
|
+
}
|
|
589
|
+
});
|
|
590
|
+
|
|
591
|
+
// src/protocols/ap2/client.ts
|
|
592
|
+
var AP2Client;
|
|
593
|
+
var init_client3 = __esm({
|
|
594
|
+
"src/protocols/ap2/client.ts"() {
|
|
595
|
+
AP2Client = class {
|
|
596
|
+
constructor(client) {
|
|
597
|
+
this.client = client;
|
|
598
|
+
}
|
|
599
|
+
/**
|
|
600
|
+
* Create a new AP2 mandate
|
|
601
|
+
*
|
|
602
|
+
* @example
|
|
603
|
+
* ```typescript
|
|
604
|
+
* const mandate = await payos.ap2.createMandate({
|
|
605
|
+
* mandate_id: 'mdt_unique_123',
|
|
606
|
+
* mandate_type: 'payment',
|
|
607
|
+
* agent_id: 'agent_ai_assistant',
|
|
608
|
+
* account_id: 'acct_uuid',
|
|
609
|
+
* authorized_amount: 100.00,
|
|
610
|
+
* currency: 'USD',
|
|
611
|
+
* });
|
|
612
|
+
* ```
|
|
613
|
+
*/
|
|
614
|
+
async createMandate(request) {
|
|
615
|
+
const response = await this.client.request(
|
|
616
|
+
"/v1/ap2/mandates",
|
|
617
|
+
{
|
|
618
|
+
method: "POST",
|
|
619
|
+
body: JSON.stringify(request)
|
|
620
|
+
}
|
|
621
|
+
);
|
|
622
|
+
return response.data;
|
|
623
|
+
}
|
|
624
|
+
/**
|
|
625
|
+
* List mandates with optional filtering
|
|
626
|
+
*
|
|
627
|
+
* @example
|
|
628
|
+
* ```typescript
|
|
629
|
+
* const { data, pagination } = await payos.ap2.listMandates({
|
|
630
|
+
* status: 'active',
|
|
631
|
+
* agent_id: 'agent_ai_assistant',
|
|
632
|
+
* limit: 50,
|
|
633
|
+
* });
|
|
634
|
+
* ```
|
|
635
|
+
*/
|
|
636
|
+
async listMandates(options = {}) {
|
|
637
|
+
const params = new URLSearchParams();
|
|
638
|
+
if (options.status) params.append("status", options.status);
|
|
639
|
+
if (options.agent_id) params.append("agent_id", options.agent_id);
|
|
640
|
+
if (options.account_id) params.append("account_id", options.account_id);
|
|
641
|
+
if (options.page) params.append("page", options.page.toString());
|
|
642
|
+
if (options.limit) params.append("limit", options.limit.toString());
|
|
643
|
+
const queryString = params.toString();
|
|
644
|
+
const path = queryString ? `/v1/ap2/mandates?${queryString}` : "/v1/ap2/mandates";
|
|
645
|
+
return this.client.request(path);
|
|
646
|
+
}
|
|
647
|
+
/**
|
|
648
|
+
* Get mandate details with execution history
|
|
649
|
+
*
|
|
650
|
+
* @example
|
|
651
|
+
* ```typescript
|
|
652
|
+
* const mandate = await payos.ap2.getMandate('mdt_id');
|
|
653
|
+
* console.log(mandate.remaining_amount);
|
|
654
|
+
* console.log(mandate.executions.length);
|
|
655
|
+
* ```
|
|
656
|
+
*/
|
|
657
|
+
async getMandate(mandateId) {
|
|
658
|
+
const response = await this.client.request(
|
|
659
|
+
`/v1/ap2/mandates/${mandateId}`
|
|
660
|
+
);
|
|
661
|
+
return response.data;
|
|
662
|
+
}
|
|
663
|
+
/**
|
|
664
|
+
* Execute a payment against a mandate
|
|
665
|
+
*
|
|
666
|
+
* @example
|
|
667
|
+
* ```typescript
|
|
668
|
+
* const result = await payos.ap2.executeMandate('mdt_id', {
|
|
669
|
+
* amount: 25.00,
|
|
670
|
+
* currency: 'USD',
|
|
671
|
+
* description: 'Monthly subscription',
|
|
672
|
+
* });
|
|
673
|
+
*
|
|
674
|
+
* console.log(result.transfer_id);
|
|
675
|
+
* console.log(result.mandate.remaining_amount);
|
|
676
|
+
* ```
|
|
677
|
+
*/
|
|
678
|
+
async executeMandate(mandateId, request) {
|
|
679
|
+
const response = await this.client.request(
|
|
680
|
+
`/v1/ap2/mandates/${mandateId}/execute`,
|
|
681
|
+
{
|
|
682
|
+
method: "POST",
|
|
683
|
+
body: JSON.stringify(request)
|
|
684
|
+
}
|
|
685
|
+
);
|
|
686
|
+
return response.data;
|
|
687
|
+
}
|
|
688
|
+
/**
|
|
689
|
+
* Cancel an active mandate
|
|
690
|
+
*
|
|
691
|
+
* @example
|
|
692
|
+
* ```typescript
|
|
693
|
+
* const result = await payos.ap2.cancelMandate('mdt_id');
|
|
694
|
+
* console.log(result.status); // 'cancelled'
|
|
695
|
+
* ```
|
|
696
|
+
*/
|
|
697
|
+
async cancelMandate(mandateId) {
|
|
698
|
+
const response = await this.client.request(
|
|
699
|
+
`/v1/ap2/mandates/${mandateId}/cancel`,
|
|
700
|
+
{
|
|
701
|
+
method: "PATCH"
|
|
702
|
+
}
|
|
703
|
+
);
|
|
704
|
+
return response.data;
|
|
705
|
+
}
|
|
706
|
+
/**
|
|
707
|
+
* Get AP2 analytics
|
|
708
|
+
*
|
|
709
|
+
* @example
|
|
710
|
+
* ```typescript
|
|
711
|
+
* const analytics = await payos.ap2.getAnalytics('30d');
|
|
712
|
+
* console.log(analytics.summary.totalRevenue);
|
|
713
|
+
* console.log(analytics.summary.activeMandates);
|
|
714
|
+
* ```
|
|
715
|
+
*/
|
|
716
|
+
async getAnalytics(period = "30d") {
|
|
717
|
+
const response = await this.client.request(
|
|
718
|
+
`/v1/ap2/analytics?period=${period}`
|
|
719
|
+
);
|
|
720
|
+
return response.data;
|
|
721
|
+
}
|
|
722
|
+
};
|
|
723
|
+
}
|
|
724
|
+
});
|
|
725
|
+
|
|
726
|
+
// src/protocols/acp/client.ts
|
|
727
|
+
var ACPClient;
|
|
728
|
+
var init_client4 = __esm({
|
|
729
|
+
"src/protocols/acp/client.ts"() {
|
|
730
|
+
ACPClient = class {
|
|
731
|
+
constructor(client) {
|
|
732
|
+
this.client = client;
|
|
733
|
+
}
|
|
734
|
+
/**
|
|
735
|
+
* Create a new ACP checkout session
|
|
736
|
+
*
|
|
737
|
+
* @example
|
|
738
|
+
* ```typescript
|
|
739
|
+
* const checkout = await payos.acp.createCheckout({
|
|
740
|
+
* checkout_id: 'checkout_unique_123',
|
|
741
|
+
* agent_id: 'agent_shopping_assistant',
|
|
742
|
+
* account_id: 'acct_uuid',
|
|
743
|
+
* merchant_id: 'merchant_store',
|
|
744
|
+
* items: [
|
|
745
|
+
* {
|
|
746
|
+
* name: 'Product 1',
|
|
747
|
+
* quantity: 2,
|
|
748
|
+
* unit_price: 50.00,
|
|
749
|
+
* total_price: 100.00,
|
|
750
|
+
* },
|
|
751
|
+
* ],
|
|
752
|
+
* tax_amount: 10.00,
|
|
753
|
+
* shipping_amount: 5.00,
|
|
754
|
+
* });
|
|
755
|
+
* ```
|
|
756
|
+
*/
|
|
757
|
+
async createCheckout(request) {
|
|
758
|
+
const response = await this.client.request(
|
|
759
|
+
"/v1/acp/checkouts",
|
|
760
|
+
{
|
|
761
|
+
method: "POST",
|
|
762
|
+
body: JSON.stringify(request)
|
|
763
|
+
}
|
|
764
|
+
);
|
|
765
|
+
return response.data;
|
|
766
|
+
}
|
|
767
|
+
/**
|
|
768
|
+
* List checkouts with optional filtering
|
|
769
|
+
*
|
|
770
|
+
* @example
|
|
771
|
+
* ```typescript
|
|
772
|
+
* const { data, pagination } = await payos.acp.listCheckouts({
|
|
773
|
+
* status: 'pending',
|
|
774
|
+
* agent_id: 'agent_shopping_assistant',
|
|
775
|
+
* limit: 20,
|
|
776
|
+
* });
|
|
777
|
+
* ```
|
|
778
|
+
*/
|
|
779
|
+
async listCheckouts(options = {}) {
|
|
780
|
+
const params = new URLSearchParams();
|
|
781
|
+
if (options.status) params.append("status", options.status);
|
|
782
|
+
if (options.agent_id) params.append("agent_id", options.agent_id);
|
|
783
|
+
if (options.merchant_id) params.append("merchant_id", options.merchant_id);
|
|
784
|
+
if (options.customer_id) params.append("customer_id", options.customer_id);
|
|
785
|
+
if (options.limit) params.append("limit", options.limit.toString());
|
|
786
|
+
if (options.offset) params.append("offset", options.offset.toString());
|
|
787
|
+
const queryString = params.toString();
|
|
788
|
+
const path = queryString ? `/v1/acp/checkouts?${queryString}` : "/v1/acp/checkouts";
|
|
789
|
+
return this.client.request(path);
|
|
790
|
+
}
|
|
791
|
+
/**
|
|
792
|
+
* Get checkout details with items
|
|
793
|
+
*
|
|
794
|
+
* @example
|
|
795
|
+
* ```typescript
|
|
796
|
+
* const checkout = await payos.acp.getCheckout('checkout_id');
|
|
797
|
+
* console.log(checkout.items);
|
|
798
|
+
* console.log(checkout.total_amount);
|
|
799
|
+
* ```
|
|
800
|
+
*/
|
|
801
|
+
async getCheckout(checkoutId) {
|
|
802
|
+
const response = await this.client.request(
|
|
803
|
+
`/v1/acp/checkouts/${checkoutId}`
|
|
804
|
+
);
|
|
805
|
+
return response.data;
|
|
806
|
+
}
|
|
807
|
+
/**
|
|
808
|
+
* Complete a checkout with SharedPaymentToken
|
|
809
|
+
*
|
|
810
|
+
* @example
|
|
811
|
+
* ```typescript
|
|
812
|
+
* const result = await payos.acp.completeCheckout('checkout_id', {
|
|
813
|
+
* shared_payment_token: 'spt_...',
|
|
814
|
+
* payment_method: 'card',
|
|
815
|
+
* });
|
|
816
|
+
*
|
|
817
|
+
* console.log(result.transfer_id);
|
|
818
|
+
* console.log(result.status); // 'completed'
|
|
819
|
+
* ```
|
|
820
|
+
*/
|
|
821
|
+
async completeCheckout(checkoutId, request) {
|
|
822
|
+
const response = await this.client.request(
|
|
823
|
+
`/v1/acp/checkouts/${checkoutId}/complete`,
|
|
824
|
+
{
|
|
825
|
+
method: "POST",
|
|
826
|
+
body: JSON.stringify(request)
|
|
827
|
+
}
|
|
828
|
+
);
|
|
829
|
+
return response.data;
|
|
830
|
+
}
|
|
831
|
+
/**
|
|
832
|
+
* Cancel a checkout
|
|
833
|
+
*
|
|
834
|
+
* @example
|
|
835
|
+
* ```typescript
|
|
836
|
+
* const result = await payos.acp.cancelCheckout('checkout_id');
|
|
837
|
+
* console.log(result.status); // 'cancelled'
|
|
838
|
+
* ```
|
|
839
|
+
*/
|
|
840
|
+
async cancelCheckout(checkoutId) {
|
|
841
|
+
const response = await this.client.request(
|
|
842
|
+
`/v1/acp/checkouts/${checkoutId}/cancel`,
|
|
843
|
+
{
|
|
844
|
+
method: "PATCH"
|
|
845
|
+
}
|
|
846
|
+
);
|
|
847
|
+
return response.data;
|
|
848
|
+
}
|
|
849
|
+
/**
|
|
850
|
+
* Get ACP analytics
|
|
851
|
+
*
|
|
852
|
+
* @example
|
|
853
|
+
* ```typescript
|
|
854
|
+
* const analytics = await payos.acp.getAnalytics('30d');
|
|
855
|
+
* console.log(analytics.summary.totalRevenue);
|
|
856
|
+
* console.log(analytics.summary.averageOrderValue);
|
|
857
|
+
* ```
|
|
858
|
+
*/
|
|
859
|
+
async getAnalytics(period = "30d") {
|
|
860
|
+
const response = await this.client.request(
|
|
861
|
+
`/v1/acp/analytics?period=${period}`
|
|
862
|
+
);
|
|
863
|
+
return response.data;
|
|
864
|
+
}
|
|
865
|
+
};
|
|
866
|
+
}
|
|
867
|
+
});
|
|
868
|
+
|
|
869
|
+
// src/protocols/ucp/client.ts
|
|
870
|
+
var profileCache, PROFILE_CACHE_TTL_MS, UCPClient;
|
|
871
|
+
var init_client5 = __esm({
|
|
872
|
+
"src/protocols/ucp/client.ts"() {
|
|
873
|
+
profileCache = /* @__PURE__ */ new Map();
|
|
874
|
+
PROFILE_CACHE_TTL_MS = 60 * 60 * 1e3;
|
|
875
|
+
UCPClient = class {
|
|
876
|
+
constructor(client) {
|
|
877
|
+
this.client = client;
|
|
878
|
+
}
|
|
879
|
+
// ===========================================================================
|
|
880
|
+
// Discovery
|
|
881
|
+
// ===========================================================================
|
|
882
|
+
/**
|
|
883
|
+
* Discover a UCP merchant's capabilities
|
|
884
|
+
*
|
|
885
|
+
* Fetches and caches the merchant's UCP profile from /.well-known/ucp
|
|
886
|
+
*
|
|
887
|
+
* @example
|
|
888
|
+
* ```typescript
|
|
889
|
+
* const merchant = await payos.ucp.discover('https://shop.example.com');
|
|
890
|
+
* console.log(merchant.ucp.version);
|
|
891
|
+
* console.log(merchant.payment?.handlers);
|
|
892
|
+
* ```
|
|
893
|
+
*/
|
|
894
|
+
async discover(merchantUrl) {
|
|
895
|
+
const baseUrl = merchantUrl.replace(/\/$/, "");
|
|
896
|
+
const profileUrl = `${baseUrl}/.well-known/ucp`;
|
|
897
|
+
const cached = profileCache.get(profileUrl);
|
|
898
|
+
if (cached && Date.now() - cached.fetchedAt < PROFILE_CACHE_TTL_MS) {
|
|
899
|
+
return cached.profile;
|
|
900
|
+
}
|
|
901
|
+
const response = await fetch(profileUrl, {
|
|
902
|
+
headers: {
|
|
903
|
+
Accept: "application/json",
|
|
904
|
+
"User-Agent": "PayOS-SDK/1.0"
|
|
905
|
+
}
|
|
906
|
+
});
|
|
907
|
+
if (!response.ok) {
|
|
908
|
+
throw new Error(`Failed to discover UCP profile: ${response.status} ${response.statusText}`);
|
|
909
|
+
}
|
|
910
|
+
const profile = await response.json();
|
|
911
|
+
if (!profile.ucp?.version) {
|
|
912
|
+
throw new Error("Invalid UCP profile: missing ucp.version");
|
|
913
|
+
}
|
|
914
|
+
profileCache.set(profileUrl, {
|
|
915
|
+
profile,
|
|
916
|
+
fetchedAt: Date.now()
|
|
917
|
+
});
|
|
918
|
+
return profile;
|
|
919
|
+
}
|
|
920
|
+
/**
|
|
921
|
+
* Get PayOS's own UCP profile
|
|
922
|
+
*
|
|
923
|
+
* @example
|
|
924
|
+
* ```typescript
|
|
925
|
+
* const profile = await payos.ucp.getProfile();
|
|
926
|
+
* console.log(profile.payment?.handlers);
|
|
927
|
+
* ```
|
|
928
|
+
*/
|
|
929
|
+
async getProfile() {
|
|
930
|
+
return this.client.request("/.well-known/ucp");
|
|
931
|
+
}
|
|
932
|
+
/**
|
|
933
|
+
* Get available settlement corridors
|
|
934
|
+
*
|
|
935
|
+
* @example
|
|
936
|
+
* ```typescript
|
|
937
|
+
* const corridors = await payos.ucp.getCorridors();
|
|
938
|
+
* console.log(corridors.find(c => c.rail === 'pix'));
|
|
939
|
+
* ```
|
|
940
|
+
*/
|
|
941
|
+
async getCorridors() {
|
|
942
|
+
const response = await this.client.request(
|
|
943
|
+
"/v1/ucp/corridors"
|
|
944
|
+
);
|
|
945
|
+
return response.corridors;
|
|
946
|
+
}
|
|
947
|
+
/**
|
|
948
|
+
* Get UCP handler info
|
|
949
|
+
*
|
|
950
|
+
* @example
|
|
951
|
+
* ```typescript
|
|
952
|
+
* const info = await payos.ucp.getHandlerInfo();
|
|
953
|
+
* console.log(info.handler.name); // com.payos.latam_settlement
|
|
954
|
+
* ```
|
|
955
|
+
*/
|
|
956
|
+
async getHandlerInfo() {
|
|
957
|
+
return this.client.request("/v1/ucp/info");
|
|
958
|
+
}
|
|
959
|
+
// ===========================================================================
|
|
960
|
+
// Quotes
|
|
961
|
+
// ===========================================================================
|
|
962
|
+
/**
|
|
963
|
+
* Get an FX quote for a settlement corridor
|
|
964
|
+
*
|
|
965
|
+
* @example
|
|
966
|
+
* ```typescript
|
|
967
|
+
* const quote = await payos.ucp.getQuote({
|
|
968
|
+
* corridor: 'pix',
|
|
969
|
+
* amount: 100,
|
|
970
|
+
* currency: 'USD',
|
|
971
|
+
* });
|
|
972
|
+
* console.log(`${quote.from_amount} USD = ${quote.to_amount} BRL`);
|
|
973
|
+
* ```
|
|
974
|
+
*/
|
|
975
|
+
async getQuote(request) {
|
|
976
|
+
return this.client.request("/v1/ucp/quote", {
|
|
977
|
+
method: "POST",
|
|
978
|
+
body: JSON.stringify(request)
|
|
979
|
+
});
|
|
980
|
+
}
|
|
981
|
+
// ===========================================================================
|
|
982
|
+
// Token Acquisition (Payment Handler flow)
|
|
983
|
+
// ===========================================================================
|
|
984
|
+
/**
|
|
985
|
+
* Acquire a settlement token for completing a UCP checkout
|
|
986
|
+
*
|
|
987
|
+
* Tokens are valid for 15 minutes and lock in the FX rate.
|
|
988
|
+
*
|
|
989
|
+
* @example
|
|
990
|
+
* ```typescript
|
|
991
|
+
* const token = await payos.ucp.acquireToken({
|
|
992
|
+
* corridor: 'pix',
|
|
993
|
+
* amount: 100,
|
|
994
|
+
* currency: 'USD',
|
|
995
|
+
* recipient: {
|
|
996
|
+
* type: 'pix',
|
|
997
|
+
* pix_key: '12345678901',
|
|
998
|
+
* pix_key_type: 'cpf',
|
|
999
|
+
* name: 'Maria Silva',
|
|
1000
|
+
* },
|
|
1001
|
+
* });
|
|
1002
|
+
*
|
|
1003
|
+
* console.log(token.token); // ucp_tok_...
|
|
1004
|
+
* console.log(token.quote.to_amount); // 595.00 BRL
|
|
1005
|
+
* ```
|
|
1006
|
+
*/
|
|
1007
|
+
async acquireToken(request) {
|
|
1008
|
+
return this.client.request("/v1/ucp/tokens", {
|
|
1009
|
+
method: "POST",
|
|
1010
|
+
body: JSON.stringify(request)
|
|
1011
|
+
});
|
|
1012
|
+
}
|
|
1013
|
+
// ===========================================================================
|
|
1014
|
+
// Settlement Execution
|
|
1015
|
+
// ===========================================================================
|
|
1016
|
+
/**
|
|
1017
|
+
* Complete settlement using a previously acquired token
|
|
1018
|
+
*
|
|
1019
|
+
* @example
|
|
1020
|
+
* ```typescript
|
|
1021
|
+
* const settlement = await payos.ucp.settle({
|
|
1022
|
+
* token: 'ucp_tok_...',
|
|
1023
|
+
* idempotency_key: 'checkout_12345',
|
|
1024
|
+
* });
|
|
1025
|
+
*
|
|
1026
|
+
* console.log(settlement.status); // pending
|
|
1027
|
+
* console.log(settlement.id); // Use this to track status
|
|
1028
|
+
* ```
|
|
1029
|
+
*/
|
|
1030
|
+
async settle(request) {
|
|
1031
|
+
return this.client.request("/v1/ucp/settle", {
|
|
1032
|
+
method: "POST",
|
|
1033
|
+
body: JSON.stringify(request)
|
|
1034
|
+
});
|
|
1035
|
+
}
|
|
1036
|
+
/**
|
|
1037
|
+
* Get settlement status by ID
|
|
1038
|
+
*
|
|
1039
|
+
* @example
|
|
1040
|
+
* ```typescript
|
|
1041
|
+
* const settlement = await payos.ucp.getSettlement('uuid');
|
|
1042
|
+
* if (settlement.status === 'completed') {
|
|
1043
|
+
* console.log(`Completed at ${settlement.completed_at}`);
|
|
1044
|
+
* }
|
|
1045
|
+
* ```
|
|
1046
|
+
*/
|
|
1047
|
+
async getSettlement(settlementId) {
|
|
1048
|
+
return this.client.request(`/v1/ucp/settlements/${settlementId}`);
|
|
1049
|
+
}
|
|
1050
|
+
/**
|
|
1051
|
+
* List settlements with optional filtering
|
|
1052
|
+
*
|
|
1053
|
+
* @example
|
|
1054
|
+
* ```typescript
|
|
1055
|
+
* const { data, pagination } = await payos.ucp.listSettlements({
|
|
1056
|
+
* status: 'completed',
|
|
1057
|
+
* corridor: 'pix',
|
|
1058
|
+
* limit: 50,
|
|
1059
|
+
* });
|
|
1060
|
+
* ```
|
|
1061
|
+
*/
|
|
1062
|
+
async listSettlements(options = {}) {
|
|
1063
|
+
const params = new URLSearchParams();
|
|
1064
|
+
if (options.status) params.append("status", options.status);
|
|
1065
|
+
if (options.corridor) params.append("corridor", options.corridor);
|
|
1066
|
+
if (options.limit) params.append("limit", options.limit.toString());
|
|
1067
|
+
if (options.offset) params.append("offset", options.offset.toString());
|
|
1068
|
+
const queryString = params.toString();
|
|
1069
|
+
const path = queryString ? `/v1/ucp/settlements?${queryString}` : "/v1/ucp/settlements";
|
|
1070
|
+
return this.client.request(path);
|
|
1071
|
+
}
|
|
1072
|
+
// ===========================================================================
|
|
1073
|
+
// Checkout (Consuming UCP Merchants)
|
|
1074
|
+
// ===========================================================================
|
|
1075
|
+
/**
|
|
1076
|
+
* Create a checkout session with a UCP merchant
|
|
1077
|
+
*
|
|
1078
|
+
* @example
|
|
1079
|
+
* ```typescript
|
|
1080
|
+
* const checkout = await payos.ucp.createCheckout('https://shop.example.com', {
|
|
1081
|
+
* line_items: [
|
|
1082
|
+
* { product_id: 'prod_123', quantity: 2 },
|
|
1083
|
+
* ],
|
|
1084
|
+
* buyer: { email: 'buyer@example.com' },
|
|
1085
|
+
* });
|
|
1086
|
+
*
|
|
1087
|
+
* console.log(checkout.totals.total);
|
|
1088
|
+
* ```
|
|
1089
|
+
*/
|
|
1090
|
+
async createCheckout(merchantUrl, request) {
|
|
1091
|
+
const profile = await this.discover(merchantUrl);
|
|
1092
|
+
if (!profile.checkout?.endpoint) {
|
|
1093
|
+
throw new Error("Merchant does not support UCP checkout");
|
|
1094
|
+
}
|
|
1095
|
+
const response = await fetch(profile.checkout.endpoint, {
|
|
1096
|
+
method: "POST",
|
|
1097
|
+
headers: {
|
|
1098
|
+
"Content-Type": "application/json",
|
|
1099
|
+
"User-Agent": "PayOS-SDK/1.0"
|
|
1100
|
+
},
|
|
1101
|
+
body: JSON.stringify(request)
|
|
1102
|
+
});
|
|
1103
|
+
if (!response.ok) {
|
|
1104
|
+
const error = await response.json().catch(() => ({}));
|
|
1105
|
+
throw new Error(`Failed to create checkout: ${response.status} - ${JSON.stringify(error)}`);
|
|
1106
|
+
}
|
|
1107
|
+
return await response.json();
|
|
1108
|
+
}
|
|
1109
|
+
/**
|
|
1110
|
+
* Complete a checkout with PayOS LATAM settlement
|
|
1111
|
+
*
|
|
1112
|
+
* This is a convenience method that:
|
|
1113
|
+
* 1. Acquires a settlement token
|
|
1114
|
+
* 2. Completes the checkout with the merchant
|
|
1115
|
+
*
|
|
1116
|
+
* @example
|
|
1117
|
+
* ```typescript
|
|
1118
|
+
* const order = await payos.ucp.completeCheckout(
|
|
1119
|
+
* 'https://shop.example.com',
|
|
1120
|
+
* checkout.id,
|
|
1121
|
+
* {
|
|
1122
|
+
* corridor: 'pix',
|
|
1123
|
+
* recipient: {
|
|
1124
|
+
* type: 'pix',
|
|
1125
|
+
* pix_key: '12345678901',
|
|
1126
|
+
* pix_key_type: 'cpf',
|
|
1127
|
+
* name: 'Maria Silva',
|
|
1128
|
+
* },
|
|
1129
|
+
* }
|
|
1130
|
+
* );
|
|
1131
|
+
*
|
|
1132
|
+
* console.log(order.id);
|
|
1133
|
+
* console.log(order.payment.settlement_id);
|
|
1134
|
+
* ```
|
|
1135
|
+
*/
|
|
1136
|
+
async completeCheckout(merchantUrl, checkoutId, settlement) {
|
|
1137
|
+
const profile = await this.discover(merchantUrl);
|
|
1138
|
+
if (!profile.checkout?.endpoint) {
|
|
1139
|
+
throw new Error("Merchant does not support UCP checkout");
|
|
1140
|
+
}
|
|
1141
|
+
const checkoutResponse = await fetch(`${profile.checkout.endpoint}/${checkoutId}`, {
|
|
1142
|
+
headers: {
|
|
1143
|
+
"User-Agent": "PayOS-SDK/1.0"
|
|
1144
|
+
}
|
|
1145
|
+
});
|
|
1146
|
+
if (!checkoutResponse.ok) {
|
|
1147
|
+
throw new Error(`Failed to fetch checkout: ${checkoutResponse.status}`);
|
|
1148
|
+
}
|
|
1149
|
+
const checkout = await checkoutResponse.json();
|
|
1150
|
+
const token = await this.acquireToken({
|
|
1151
|
+
corridor: settlement.corridor,
|
|
1152
|
+
amount: checkout.totals.total,
|
|
1153
|
+
currency: checkout.totals.currency,
|
|
1154
|
+
recipient: settlement.recipient
|
|
1155
|
+
});
|
|
1156
|
+
const completeRequest = {
|
|
1157
|
+
payment_handler: "payos_latam",
|
|
1158
|
+
payment_data: {
|
|
1159
|
+
token: token.token
|
|
1160
|
+
}
|
|
1161
|
+
};
|
|
1162
|
+
const completeResponse = await fetch(`${profile.checkout.endpoint}/${checkoutId}/complete`, {
|
|
1163
|
+
method: "POST",
|
|
1164
|
+
headers: {
|
|
1165
|
+
"Content-Type": "application/json",
|
|
1166
|
+
"User-Agent": "PayOS-SDK/1.0"
|
|
1167
|
+
},
|
|
1168
|
+
body: JSON.stringify(completeRequest)
|
|
1169
|
+
});
|
|
1170
|
+
if (!completeResponse.ok) {
|
|
1171
|
+
const error = await completeResponse.json().catch(() => ({}));
|
|
1172
|
+
throw new Error(`Failed to complete checkout: ${completeResponse.status} - ${JSON.stringify(error)}`);
|
|
1173
|
+
}
|
|
1174
|
+
return await completeResponse.json();
|
|
1175
|
+
}
|
|
1176
|
+
// ===========================================================================
|
|
1177
|
+
// Utilities
|
|
1178
|
+
// ===========================================================================
|
|
1179
|
+
/**
|
|
1180
|
+
* Clear the profile cache (useful for testing)
|
|
1181
|
+
*/
|
|
1182
|
+
clearCache() {
|
|
1183
|
+
profileCache.clear();
|
|
1184
|
+
}
|
|
1185
|
+
/**
|
|
1186
|
+
* Check if PayOS supports a specific corridor
|
|
1187
|
+
*
|
|
1188
|
+
* @example
|
|
1189
|
+
* ```typescript
|
|
1190
|
+
* if (await payos.ucp.supportsCorridors('USD', 'BRL', 'pix')) {
|
|
1191
|
+
* // Can settle via Pix
|
|
1192
|
+
* }
|
|
1193
|
+
* ```
|
|
1194
|
+
*/
|
|
1195
|
+
async supportsCorridor(sourceCurrency, destinationCurrency, rail) {
|
|
1196
|
+
const corridors = await this.getCorridors();
|
|
1197
|
+
return corridors.some(
|
|
1198
|
+
(c) => c.source_currency === sourceCurrency && c.destination_currency === destinationCurrency && c.rail === rail
|
|
1199
|
+
);
|
|
1200
|
+
}
|
|
1201
|
+
/**
|
|
1202
|
+
* Create Pix recipient helper
|
|
1203
|
+
*
|
|
1204
|
+
* @example
|
|
1205
|
+
* ```typescript
|
|
1206
|
+
* const recipient = payos.ucp.createPixRecipient({
|
|
1207
|
+
* pix_key: '12345678901',
|
|
1208
|
+
* pix_key_type: 'cpf',
|
|
1209
|
+
* name: 'Maria Silva',
|
|
1210
|
+
* });
|
|
1211
|
+
* ```
|
|
1212
|
+
*/
|
|
1213
|
+
createPixRecipient(params) {
|
|
1214
|
+
return {
|
|
1215
|
+
type: "pix",
|
|
1216
|
+
...params
|
|
1217
|
+
};
|
|
1218
|
+
}
|
|
1219
|
+
/**
|
|
1220
|
+
* Create SPEI recipient helper
|
|
1221
|
+
*
|
|
1222
|
+
* @example
|
|
1223
|
+
* ```typescript
|
|
1224
|
+
* const recipient = payos.ucp.createSpeiRecipient({
|
|
1225
|
+
* clabe: '012345678901234567',
|
|
1226
|
+
* name: 'Juan Garcia',
|
|
1227
|
+
* });
|
|
1228
|
+
* ```
|
|
1229
|
+
*/
|
|
1230
|
+
createSpeiRecipient(params) {
|
|
1231
|
+
return {
|
|
1232
|
+
type: "spei",
|
|
1233
|
+
...params
|
|
1234
|
+
};
|
|
1235
|
+
}
|
|
1236
|
+
// ===========================================================================
|
|
1237
|
+
// PayOS-Hosted Checkout Sessions (Phase 2)
|
|
1238
|
+
// ===========================================================================
|
|
1239
|
+
/**
|
|
1240
|
+
* Create a PayOS-hosted checkout session
|
|
1241
|
+
*
|
|
1242
|
+
* @example
|
|
1243
|
+
* ```typescript
|
|
1244
|
+
* const checkout = await payos.ucp.checkouts.create({
|
|
1245
|
+
* currency: 'USD',
|
|
1246
|
+
* line_items: [
|
|
1247
|
+
* { id: 'item_1', name: 'Product', quantity: 1, unit_price: 1000, total_price: 1000, currency: 'USD' }
|
|
1248
|
+
* ],
|
|
1249
|
+
* buyer: { email: 'buyer@example.com' },
|
|
1250
|
+
* });
|
|
1251
|
+
* ```
|
|
1252
|
+
*/
|
|
1253
|
+
get checkouts() {
|
|
1254
|
+
return {
|
|
1255
|
+
create: async (request) => {
|
|
1256
|
+
return this.client.request("/v1/ucp/checkouts", {
|
|
1257
|
+
method: "POST",
|
|
1258
|
+
body: JSON.stringify(request)
|
|
1259
|
+
});
|
|
1260
|
+
},
|
|
1261
|
+
get: async (checkoutId) => {
|
|
1262
|
+
return this.client.request(`/v1/ucp/checkouts/${checkoutId}`);
|
|
1263
|
+
},
|
|
1264
|
+
update: async (checkoutId, request) => {
|
|
1265
|
+
return this.client.request(`/v1/ucp/checkouts/${checkoutId}`, {
|
|
1266
|
+
method: "PUT",
|
|
1267
|
+
body: JSON.stringify(request)
|
|
1268
|
+
});
|
|
1269
|
+
},
|
|
1270
|
+
complete: async (checkoutId) => {
|
|
1271
|
+
return this.client.request(`/v1/ucp/checkouts/${checkoutId}/complete`, {
|
|
1272
|
+
method: "POST"
|
|
1273
|
+
});
|
|
1274
|
+
},
|
|
1275
|
+
cancel: async (checkoutId) => {
|
|
1276
|
+
return this.client.request(`/v1/ucp/checkouts/${checkoutId}/cancel`, {
|
|
1277
|
+
method: "POST"
|
|
1278
|
+
});
|
|
1279
|
+
},
|
|
1280
|
+
addPaymentInstrument: async (checkoutId, instrument) => {
|
|
1281
|
+
return this.client.request(`/v1/ucp/checkouts/${checkoutId}/instruments`, {
|
|
1282
|
+
method: "POST",
|
|
1283
|
+
body: JSON.stringify(instrument)
|
|
1284
|
+
});
|
|
1285
|
+
}
|
|
1286
|
+
};
|
|
1287
|
+
}
|
|
1288
|
+
// ===========================================================================
|
|
1289
|
+
// PayOS Orders (Phase 3)
|
|
1290
|
+
// ===========================================================================
|
|
1291
|
+
/**
|
|
1292
|
+
* Manage PayOS orders
|
|
1293
|
+
*
|
|
1294
|
+
* @example
|
|
1295
|
+
* ```typescript
|
|
1296
|
+
* const order = await payos.ucp.orders.get('ord_123');
|
|
1297
|
+
* const orders = await payos.ucp.orders.list({ status: 'processing' });
|
|
1298
|
+
* ```
|
|
1299
|
+
*/
|
|
1300
|
+
get orders() {
|
|
1301
|
+
return {
|
|
1302
|
+
get: async (orderId) => {
|
|
1303
|
+
return this.client.request(`/v1/ucp/orders/${orderId}`);
|
|
1304
|
+
},
|
|
1305
|
+
list: async (options = {}) => {
|
|
1306
|
+
const params = new URLSearchParams();
|
|
1307
|
+
if (options.status) params.append("status", options.status);
|
|
1308
|
+
if (options.limit) params.append("limit", options.limit.toString());
|
|
1309
|
+
if (options.offset) params.append("offset", options.offset.toString());
|
|
1310
|
+
const queryString = params.toString();
|
|
1311
|
+
const path = queryString ? `/v1/ucp/orders?${queryString}` : "/v1/ucp/orders";
|
|
1312
|
+
return this.client.request(path);
|
|
1313
|
+
},
|
|
1314
|
+
updateStatus: async (orderId, status) => {
|
|
1315
|
+
return this.client.request(`/v1/ucp/orders/${orderId}/status`, {
|
|
1316
|
+
method: "PUT",
|
|
1317
|
+
body: JSON.stringify({ status })
|
|
1318
|
+
});
|
|
1319
|
+
},
|
|
1320
|
+
cancel: async (orderId, reason) => {
|
|
1321
|
+
return this.client.request(`/v1/ucp/orders/${orderId}/cancel`, {
|
|
1322
|
+
method: "POST",
|
|
1323
|
+
body: JSON.stringify({ reason })
|
|
1324
|
+
});
|
|
1325
|
+
},
|
|
1326
|
+
addExpectation: async (orderId, expectation) => {
|
|
1327
|
+
return this.client.request(`/v1/ucp/orders/${orderId}/expectations`, {
|
|
1328
|
+
method: "POST",
|
|
1329
|
+
body: JSON.stringify(expectation)
|
|
1330
|
+
});
|
|
1331
|
+
},
|
|
1332
|
+
updateExpectation: async (orderId, expectationId, updates) => {
|
|
1333
|
+
return this.client.request(
|
|
1334
|
+
`/v1/ucp/orders/${orderId}/expectations/${expectationId}`,
|
|
1335
|
+
{
|
|
1336
|
+
method: "PUT",
|
|
1337
|
+
body: JSON.stringify(updates)
|
|
1338
|
+
}
|
|
1339
|
+
);
|
|
1340
|
+
},
|
|
1341
|
+
addEvent: async (orderId, event) => {
|
|
1342
|
+
return this.client.request(`/v1/ucp/orders/${orderId}/events`, {
|
|
1343
|
+
method: "POST",
|
|
1344
|
+
body: JSON.stringify(event)
|
|
1345
|
+
});
|
|
1346
|
+
},
|
|
1347
|
+
getEvents: async (orderId) => {
|
|
1348
|
+
return this.client.request(
|
|
1349
|
+
`/v1/ucp/orders/${orderId}/events`
|
|
1350
|
+
);
|
|
1351
|
+
},
|
|
1352
|
+
addAdjustment: async (orderId, adjustment) => {
|
|
1353
|
+
return this.client.request(`/v1/ucp/orders/${orderId}/adjustments`, {
|
|
1354
|
+
method: "POST",
|
|
1355
|
+
body: JSON.stringify(adjustment)
|
|
1356
|
+
});
|
|
1357
|
+
}
|
|
1358
|
+
};
|
|
1359
|
+
}
|
|
1360
|
+
// ===========================================================================
|
|
1361
|
+
// Identity Linking (Phase 4)
|
|
1362
|
+
// ===========================================================================
|
|
1363
|
+
/**
|
|
1364
|
+
* OAuth 2.0 identity linking for AI agents/platforms
|
|
1365
|
+
*
|
|
1366
|
+
* @example
|
|
1367
|
+
* ```typescript
|
|
1368
|
+
* // Register an OAuth client
|
|
1369
|
+
* const { client, client_secret } = await payos.ucp.identity.registerClient({
|
|
1370
|
+
* name: 'My AI Agent',
|
|
1371
|
+
* redirect_uris: ['https://myagent.com/callback'],
|
|
1372
|
+
* });
|
|
1373
|
+
*
|
|
1374
|
+
* // List linked accounts
|
|
1375
|
+
* const accounts = await payos.ucp.identity.listLinkedAccounts({ buyer_id: 'buyer_123' });
|
|
1376
|
+
* ```
|
|
1377
|
+
*/
|
|
1378
|
+
get identity() {
|
|
1379
|
+
return {
|
|
1380
|
+
/**
|
|
1381
|
+
* Register an OAuth client (platform/agent)
|
|
1382
|
+
*/
|
|
1383
|
+
registerClient: async (request) => {
|
|
1384
|
+
return this.client.request("/v1/ucp/identity/clients", {
|
|
1385
|
+
method: "POST",
|
|
1386
|
+
body: JSON.stringify(request)
|
|
1387
|
+
});
|
|
1388
|
+
},
|
|
1389
|
+
/**
|
|
1390
|
+
* Get authorization info for consent screen
|
|
1391
|
+
*/
|
|
1392
|
+
getAuthorizationInfo: async (params) => {
|
|
1393
|
+
const searchParams = new URLSearchParams();
|
|
1394
|
+
searchParams.append("response_type", params.response_type);
|
|
1395
|
+
searchParams.append("client_id", params.client_id);
|
|
1396
|
+
searchParams.append("redirect_uri", params.redirect_uri);
|
|
1397
|
+
searchParams.append("scope", params.scope);
|
|
1398
|
+
searchParams.append("state", params.state);
|
|
1399
|
+
if (params.code_challenge) {
|
|
1400
|
+
searchParams.append("code_challenge", params.code_challenge);
|
|
1401
|
+
}
|
|
1402
|
+
if (params.code_challenge_method) {
|
|
1403
|
+
searchParams.append("code_challenge_method", params.code_challenge_method);
|
|
1404
|
+
}
|
|
1405
|
+
return this.client.request(
|
|
1406
|
+
`/v1/ucp/identity/authorize?${searchParams.toString()}`
|
|
1407
|
+
);
|
|
1408
|
+
},
|
|
1409
|
+
/**
|
|
1410
|
+
* Submit consent decision (after user authenticates)
|
|
1411
|
+
*/
|
|
1412
|
+
submitConsent: async (request) => {
|
|
1413
|
+
return this.client.request("/v1/ucp/identity/authorize/consent", {
|
|
1414
|
+
method: "POST",
|
|
1415
|
+
body: JSON.stringify(request)
|
|
1416
|
+
});
|
|
1417
|
+
},
|
|
1418
|
+
/**
|
|
1419
|
+
* Exchange authorization code for tokens
|
|
1420
|
+
*/
|
|
1421
|
+
exchangeCode: async (params) => {
|
|
1422
|
+
return this.client.request("/v1/ucp/identity/token", {
|
|
1423
|
+
method: "POST",
|
|
1424
|
+
body: JSON.stringify({
|
|
1425
|
+
grant_type: "authorization_code",
|
|
1426
|
+
...params
|
|
1427
|
+
})
|
|
1428
|
+
});
|
|
1429
|
+
},
|
|
1430
|
+
/**
|
|
1431
|
+
* Refresh tokens
|
|
1432
|
+
*/
|
|
1433
|
+
refreshTokens: async (params) => {
|
|
1434
|
+
return this.client.request("/v1/ucp/identity/token", {
|
|
1435
|
+
method: "POST",
|
|
1436
|
+
body: JSON.stringify({
|
|
1437
|
+
grant_type: "refresh_token",
|
|
1438
|
+
...params
|
|
1439
|
+
})
|
|
1440
|
+
});
|
|
1441
|
+
},
|
|
1442
|
+
/**
|
|
1443
|
+
* Revoke a token
|
|
1444
|
+
*/
|
|
1445
|
+
revokeToken: async (params) => {
|
|
1446
|
+
return this.client.request("/v1/ucp/identity/revoke", {
|
|
1447
|
+
method: "POST",
|
|
1448
|
+
body: JSON.stringify(params)
|
|
1449
|
+
});
|
|
1450
|
+
},
|
|
1451
|
+
/**
|
|
1452
|
+
* List linked accounts
|
|
1453
|
+
*/
|
|
1454
|
+
listLinkedAccounts: async (params) => {
|
|
1455
|
+
const searchParams = new URLSearchParams();
|
|
1456
|
+
if (params.buyer_id) searchParams.append("buyer_id", params.buyer_id);
|
|
1457
|
+
if (params.platform_id) searchParams.append("platform_id", params.platform_id);
|
|
1458
|
+
if (params.limit) searchParams.append("limit", params.limit.toString());
|
|
1459
|
+
if (params.offset) searchParams.append("offset", params.offset.toString());
|
|
1460
|
+
return this.client.request(
|
|
1461
|
+
`/v1/ucp/identity/linked-accounts?${searchParams.toString()}`
|
|
1462
|
+
);
|
|
1463
|
+
},
|
|
1464
|
+
/**
|
|
1465
|
+
* Unlink an account
|
|
1466
|
+
*/
|
|
1467
|
+
unlinkAccount: async (accountId, buyerId) => {
|
|
1468
|
+
return this.client.request(
|
|
1469
|
+
`/v1/ucp/identity/linked-accounts/${accountId}?buyer_id=${buyerId}`,
|
|
1470
|
+
{ method: "DELETE" }
|
|
1471
|
+
);
|
|
1472
|
+
},
|
|
1473
|
+
/**
|
|
1474
|
+
* Get available scopes
|
|
1475
|
+
*/
|
|
1476
|
+
getScopes: async () => {
|
|
1477
|
+
return this.client.request("/v1/ucp/identity/scopes");
|
|
1478
|
+
}
|
|
1479
|
+
};
|
|
1480
|
+
}
|
|
1481
|
+
};
|
|
1482
|
+
}
|
|
1483
|
+
});
|
|
1484
|
+
|
|
1485
|
+
// src/capabilities/formatters.ts
|
|
1486
|
+
var formatters_exports = {};
|
|
1487
|
+
__export(formatters_exports, {
|
|
1488
|
+
getClaudeSystemMessage: () => getClaudeSystemMessage,
|
|
1489
|
+
getOpenAISystemMessage: () => getOpenAISystemMessage,
|
|
1490
|
+
toClaudeTool: () => toClaudeTool,
|
|
1491
|
+
toClaudeTools: () => toClaudeTools,
|
|
1492
|
+
toLangChainTool: () => toLangChainTool,
|
|
1493
|
+
toLangChainTools: () => toLangChainTools,
|
|
1494
|
+
toOpenAIFunction: () => toOpenAIFunction,
|
|
1495
|
+
toOpenAIFunctions: () => toOpenAIFunctions
|
|
1496
|
+
});
|
|
1497
|
+
function createSchemaFromParameterType(paramType) {
|
|
1498
|
+
return {
|
|
1499
|
+
properties: {
|
|
1500
|
+
data: {
|
|
1501
|
+
type: "object",
|
|
1502
|
+
description: `${paramType} object`
|
|
1503
|
+
}
|
|
1504
|
+
},
|
|
1505
|
+
required: ["data"]
|
|
1506
|
+
};
|
|
1507
|
+
}
|
|
1508
|
+
function toOpenAIFunction(capability) {
|
|
1509
|
+
const schema = typeof capability.parameters === "string" ? createSchemaFromParameterType(capability.parameters) : { properties: {}, required: [] };
|
|
1510
|
+
return {
|
|
1511
|
+
name: capability.name,
|
|
1512
|
+
description: `${capability.description}. Endpoint: ${capability.endpoint}. Errors: ${capability.errors.join(", ")}`,
|
|
1513
|
+
parameters: {
|
|
1514
|
+
type: "object",
|
|
1515
|
+
properties: schema.properties,
|
|
1516
|
+
required: schema.required
|
|
1517
|
+
}
|
|
1518
|
+
};
|
|
1519
|
+
}
|
|
1520
|
+
function toClaudeTool(capability) {
|
|
1521
|
+
const schema = typeof capability.parameters === "string" ? createSchemaFromParameterType(capability.parameters) : { properties: {}, required: [] };
|
|
1522
|
+
return {
|
|
1523
|
+
name: capability.name,
|
|
1524
|
+
description: `${capability.description}. Endpoint: ${capability.endpoint}. Possible errors: ${capability.errors.join(", ")}`,
|
|
1525
|
+
input_schema: {
|
|
1526
|
+
type: "object",
|
|
1527
|
+
properties: schema.properties,
|
|
1528
|
+
required: schema.required
|
|
1529
|
+
}
|
|
1530
|
+
};
|
|
1531
|
+
}
|
|
1532
|
+
function toLangChainTool(capability) {
|
|
1533
|
+
const schema = typeof capability.parameters === "string" ? createSchemaFromParameterType(capability.parameters) : { properties: {}, required: [] };
|
|
1534
|
+
return {
|
|
1535
|
+
name: capability.name,
|
|
1536
|
+
description: `${capability.description}. Endpoint: ${capability.endpoint}`,
|
|
1537
|
+
schema: {
|
|
1538
|
+
type: "object",
|
|
1539
|
+
properties: schema.properties,
|
|
1540
|
+
required: schema.required
|
|
1541
|
+
}
|
|
1542
|
+
};
|
|
1543
|
+
}
|
|
1544
|
+
function toOpenAIFunctions(capabilities) {
|
|
1545
|
+
const caps = Array.isArray(capabilities) ? capabilities : capabilities.capabilities;
|
|
1546
|
+
return caps.map(toOpenAIFunction);
|
|
1547
|
+
}
|
|
1548
|
+
function toClaudeTools(capabilities) {
|
|
1549
|
+
const caps = Array.isArray(capabilities) ? capabilities : capabilities.capabilities;
|
|
1550
|
+
return caps.map(toClaudeTool);
|
|
1551
|
+
}
|
|
1552
|
+
function toLangChainTools(capabilities) {
|
|
1553
|
+
const caps = Array.isArray(capabilities) ? capabilities : capabilities.capabilities;
|
|
1554
|
+
return caps.map(toLangChainTool);
|
|
1555
|
+
}
|
|
1556
|
+
function getOpenAISystemMessage() {
|
|
1557
|
+
return `You are a helpful AI assistant with access to PayOS payment operations. You can help users:
|
|
1558
|
+
- Get settlement quotes for cross-border payments
|
|
1559
|
+
- Create settlements and transfers
|
|
1560
|
+
- Check account balances
|
|
1561
|
+
- Verify compliance for recipients
|
|
1562
|
+
|
|
1563
|
+
When a user asks about payments or transfers, use the available functions to help them. Always confirm important actions before executing them.`;
|
|
1564
|
+
}
|
|
1565
|
+
function getClaudeSystemMessage() {
|
|
1566
|
+
return `You are a helpful AI assistant with access to PayOS payment operations. You can help users:
|
|
1567
|
+
- Get settlement quotes for cross-border payments
|
|
1568
|
+
- Create settlements and transfers
|
|
1569
|
+
- Check account balances
|
|
1570
|
+
- Verify compliance for recipients
|
|
1571
|
+
|
|
1572
|
+
When a user asks about payments or transfers, use the available tools to help them. Always confirm important actions before executing them.`;
|
|
1573
|
+
}
|
|
1574
|
+
var init_formatters = __esm({
|
|
1575
|
+
"src/capabilities/formatters.ts"() {
|
|
1576
|
+
}
|
|
1577
|
+
});
|
|
1578
|
+
|
|
1579
|
+
// src/capabilities/client.ts
|
|
1580
|
+
var CapabilitiesClient;
|
|
1581
|
+
var init_client6 = __esm({
|
|
1582
|
+
"src/capabilities/client.ts"() {
|
|
1583
|
+
CapabilitiesClient = class {
|
|
1584
|
+
// 1 hour
|
|
1585
|
+
constructor(client) {
|
|
1586
|
+
this.cachedCapabilities = null;
|
|
1587
|
+
this.cacheTimestamp = 0;
|
|
1588
|
+
this.cacheTTL = 36e5;
|
|
1589
|
+
this.client = client;
|
|
1590
|
+
}
|
|
1591
|
+
/**
|
|
1592
|
+
* Get all PayOS capabilities
|
|
1593
|
+
* Results are cached for 1 hour by default
|
|
1594
|
+
*/
|
|
1595
|
+
async getAll(forceFresh = false) {
|
|
1596
|
+
const now = Date.now();
|
|
1597
|
+
if (!forceFresh && this.cachedCapabilities && now - this.cacheTimestamp < this.cacheTTL) {
|
|
1598
|
+
return this.cachedCapabilities;
|
|
1599
|
+
}
|
|
1600
|
+
const capabilities = await this.client.getCapabilities();
|
|
1601
|
+
this.cachedCapabilities = capabilities;
|
|
1602
|
+
this.cacheTimestamp = now;
|
|
1603
|
+
return capabilities;
|
|
1604
|
+
}
|
|
1605
|
+
/**
|
|
1606
|
+
* Get capabilities filtered by category or name
|
|
1607
|
+
*/
|
|
1608
|
+
async filter(filter) {
|
|
1609
|
+
const all = await this.getAll();
|
|
1610
|
+
return all.capabilities.filter((cap) => {
|
|
1611
|
+
if (filter.category && cap.category !== filter.category) {
|
|
1612
|
+
return false;
|
|
1613
|
+
}
|
|
1614
|
+
if (filter.name && cap.name !== filter.name) {
|
|
1615
|
+
return false;
|
|
1616
|
+
}
|
|
1617
|
+
return true;
|
|
1618
|
+
});
|
|
1619
|
+
}
|
|
1620
|
+
/**
|
|
1621
|
+
* Get a single capability by name
|
|
1622
|
+
*/
|
|
1623
|
+
async get(name) {
|
|
1624
|
+
const all = await this.getAll();
|
|
1625
|
+
return all.capabilities.find((cap) => cap.name === name);
|
|
1626
|
+
}
|
|
1627
|
+
/**
|
|
1628
|
+
* Get all available categories
|
|
1629
|
+
*/
|
|
1630
|
+
async getCategories() {
|
|
1631
|
+
const all = await this.getAll();
|
|
1632
|
+
const categories = new Set(all.capabilities.map((cap) => cap.category));
|
|
1633
|
+
return Array.from(categories);
|
|
1634
|
+
}
|
|
1635
|
+
/**
|
|
1636
|
+
* Clear the capabilities cache
|
|
1637
|
+
*/
|
|
1638
|
+
clearCache() {
|
|
1639
|
+
this.cachedCapabilities = null;
|
|
1640
|
+
this.cacheTimestamp = 0;
|
|
1641
|
+
}
|
|
1642
|
+
/**
|
|
1643
|
+
* Get capabilities in OpenAI function-calling format
|
|
1644
|
+
*/
|
|
1645
|
+
async toOpenAI() {
|
|
1646
|
+
const response = await this.getAll();
|
|
1647
|
+
const { toOpenAIFunctions: toOpenAIFunctions2, getOpenAISystemMessage: getOpenAISystemMessage2 } = await Promise.resolve().then(() => (init_formatters(), formatters_exports));
|
|
1648
|
+
return {
|
|
1649
|
+
functions: toOpenAIFunctions2(response.capabilities),
|
|
1650
|
+
systemMessage: getOpenAISystemMessage2()
|
|
1651
|
+
};
|
|
1652
|
+
}
|
|
1653
|
+
/**
|
|
1654
|
+
* Get capabilities in OpenAI function-calling format (alias)
|
|
1655
|
+
*/
|
|
1656
|
+
async toOpenAIFunctions() {
|
|
1657
|
+
const response = await this.getAll();
|
|
1658
|
+
const { toOpenAIFunctions: toOpenAIFunctions2 } = await Promise.resolve().then(() => (init_formatters(), formatters_exports));
|
|
1659
|
+
return toOpenAIFunctions2(response.capabilities);
|
|
1660
|
+
}
|
|
1661
|
+
/**
|
|
1662
|
+
* Get capabilities in Claude tool format
|
|
1663
|
+
*/
|
|
1664
|
+
async toClaude() {
|
|
1665
|
+
const response = await this.getAll();
|
|
1666
|
+
const { toClaudeTools: toClaudeTools2, getClaudeSystemMessage: getClaudeSystemMessage2 } = await Promise.resolve().then(() => (init_formatters(), formatters_exports));
|
|
1667
|
+
return {
|
|
1668
|
+
tools: toClaudeTools2(response.capabilities),
|
|
1669
|
+
systemMessage: getClaudeSystemMessage2()
|
|
1670
|
+
};
|
|
1671
|
+
}
|
|
1672
|
+
/**
|
|
1673
|
+
* Get capabilities in Claude tool format (alias)
|
|
1674
|
+
*/
|
|
1675
|
+
async toClaudeTools() {
|
|
1676
|
+
const response = await this.getAll();
|
|
1677
|
+
const { toClaudeTools: toClaudeTools2 } = await Promise.resolve().then(() => (init_formatters(), formatters_exports));
|
|
1678
|
+
return toClaudeTools2(response.capabilities);
|
|
1679
|
+
}
|
|
1680
|
+
/**
|
|
1681
|
+
* Get capabilities in LangChain tool format
|
|
1682
|
+
*/
|
|
1683
|
+
async toLangChain() {
|
|
1684
|
+
const response = await this.getAll();
|
|
1685
|
+
const { toLangChainTools: toLangChainTools2 } = await Promise.resolve().then(() => (init_formatters(), formatters_exports));
|
|
1686
|
+
return toLangChainTools2(response.capabilities);
|
|
1687
|
+
}
|
|
1688
|
+
};
|
|
1689
|
+
}
|
|
1690
|
+
});
|
|
1691
|
+
|
|
1692
|
+
// src/capabilities/types.ts
|
|
1693
|
+
var init_types = __esm({
|
|
1694
|
+
"src/capabilities/types.ts"() {
|
|
1695
|
+
}
|
|
1696
|
+
});
|
|
1697
|
+
|
|
1698
|
+
// src/capabilities/index.ts
|
|
1699
|
+
var init_capabilities = __esm({
|
|
1700
|
+
"src/capabilities/index.ts"() {
|
|
1701
|
+
init_client6();
|
|
1702
|
+
init_types();
|
|
1703
|
+
init_formatters();
|
|
1704
|
+
}
|
|
1705
|
+
});
|
|
1706
|
+
|
|
1707
|
+
// src/langchain/tools.ts
|
|
1708
|
+
var LangChainTools;
|
|
1709
|
+
var init_tools = __esm({
|
|
1710
|
+
"src/langchain/tools.ts"() {
|
|
1711
|
+
LangChainTools = class {
|
|
1712
|
+
constructor(payos) {
|
|
1713
|
+
this.payos = payos;
|
|
1714
|
+
}
|
|
1715
|
+
/**
|
|
1716
|
+
* Get all PayOS capabilities as LangChain tools
|
|
1717
|
+
*/
|
|
1718
|
+
async getTools() {
|
|
1719
|
+
return this.payos.capabilities.toLangChain();
|
|
1720
|
+
}
|
|
1721
|
+
/**
|
|
1722
|
+
* Get a specific tool by name
|
|
1723
|
+
*/
|
|
1724
|
+
async getTool(name) {
|
|
1725
|
+
const tools = await this.getTools();
|
|
1726
|
+
return tools.find((tool) => tool.name === name);
|
|
1727
|
+
}
|
|
1728
|
+
};
|
|
1729
|
+
}
|
|
1730
|
+
});
|
|
1731
|
+
|
|
1732
|
+
// src/cards/types.ts
|
|
1733
|
+
var init_types2 = __esm({
|
|
1734
|
+
"src/cards/types.ts"() {
|
|
1735
|
+
}
|
|
1736
|
+
});
|
|
1737
|
+
|
|
1738
|
+
// src/cards/index.ts
|
|
1739
|
+
var VisaClient, MastercardClient, CardsClient;
|
|
1740
|
+
var init_cards = __esm({
|
|
1741
|
+
"src/cards/index.ts"() {
|
|
1742
|
+
init_types2();
|
|
1743
|
+
VisaClient = class {
|
|
1744
|
+
constructor(client) {
|
|
1745
|
+
this.client = client;
|
|
1746
|
+
}
|
|
1747
|
+
/**
|
|
1748
|
+
* Create a Visa VIC payment instruction
|
|
1749
|
+
*/
|
|
1750
|
+
async createInstruction(params) {
|
|
1751
|
+
return this.client.request("/v1/cards/visa/instructions", {
|
|
1752
|
+
method: "POST",
|
|
1753
|
+
body: JSON.stringify(params)
|
|
1754
|
+
});
|
|
1755
|
+
}
|
|
1756
|
+
/**
|
|
1757
|
+
* Get a specific Visa payment instruction
|
|
1758
|
+
*/
|
|
1759
|
+
async getInstruction(instructionId) {
|
|
1760
|
+
return this.client.request(
|
|
1761
|
+
`/v1/cards/visa/instructions/${instructionId}`
|
|
1762
|
+
);
|
|
1763
|
+
}
|
|
1764
|
+
/**
|
|
1765
|
+
* List Visa payment instructions
|
|
1766
|
+
*/
|
|
1767
|
+
async listInstructions(options) {
|
|
1768
|
+
const params = new URLSearchParams();
|
|
1769
|
+
if (options?.status) params.set("status", options.status);
|
|
1770
|
+
if (options?.limit) params.set("limit", String(options.limit));
|
|
1771
|
+
if (options?.offset) params.set("offset", String(options.offset));
|
|
1772
|
+
const query = params.toString();
|
|
1773
|
+
return this.client.request(
|
|
1774
|
+
`/v1/cards/visa/instructions${query ? `?${query}` : ""}`
|
|
1775
|
+
);
|
|
1776
|
+
}
|
|
1777
|
+
/**
|
|
1778
|
+
* Provision a VTS token for an instruction
|
|
1779
|
+
*/
|
|
1780
|
+
async createToken(params) {
|
|
1781
|
+
return this.client.request("/v1/cards/visa/tokens", {
|
|
1782
|
+
method: "POST",
|
|
1783
|
+
body: JSON.stringify(params)
|
|
1784
|
+
});
|
|
1785
|
+
}
|
|
1786
|
+
/**
|
|
1787
|
+
* Get a specific Visa token
|
|
1788
|
+
*/
|
|
1789
|
+
async getToken(tokenId) {
|
|
1790
|
+
return this.client.request(`/v1/cards/visa/tokens/${tokenId}`);
|
|
1791
|
+
}
|
|
1792
|
+
/**
|
|
1793
|
+
* List Visa tokens
|
|
1794
|
+
*/
|
|
1795
|
+
async listTokens(options) {
|
|
1796
|
+
const params = new URLSearchParams();
|
|
1797
|
+
if (options?.status) params.set("status", options.status);
|
|
1798
|
+
if (options?.limit) params.set("limit", String(options.limit));
|
|
1799
|
+
if (options?.offset) params.set("offset", String(options.offset));
|
|
1800
|
+
const query = params.toString();
|
|
1801
|
+
return this.client.request(
|
|
1802
|
+
`/v1/cards/visa/tokens${query ? `?${query}` : ""}`
|
|
1803
|
+
);
|
|
1804
|
+
}
|
|
1805
|
+
/**
|
|
1806
|
+
* Suspend a Visa token
|
|
1807
|
+
*/
|
|
1808
|
+
async suspendToken(tokenId) {
|
|
1809
|
+
return this.client.request(
|
|
1810
|
+
`/v1/cards/visa/tokens/${tokenId}`,
|
|
1811
|
+
{ method: "DELETE" }
|
|
1812
|
+
);
|
|
1813
|
+
}
|
|
1814
|
+
};
|
|
1815
|
+
MastercardClient = class {
|
|
1816
|
+
constructor(client) {
|
|
1817
|
+
this.client = client;
|
|
1818
|
+
}
|
|
1819
|
+
/**
|
|
1820
|
+
* Register an agent with Mastercard Agent Pay
|
|
1821
|
+
*/
|
|
1822
|
+
async registerAgent(params) {
|
|
1823
|
+
return this.client.request("/v1/cards/mastercard/agents", {
|
|
1824
|
+
method: "POST",
|
|
1825
|
+
body: JSON.stringify(params)
|
|
1826
|
+
});
|
|
1827
|
+
}
|
|
1828
|
+
/**
|
|
1829
|
+
* Get a specific Mastercard agent registration
|
|
1830
|
+
*/
|
|
1831
|
+
async getAgent(agentId) {
|
|
1832
|
+
return this.client.request(
|
|
1833
|
+
`/v1/cards/mastercard/agents/${agentId}`
|
|
1834
|
+
);
|
|
1835
|
+
}
|
|
1836
|
+
/**
|
|
1837
|
+
* List registered Mastercard agents
|
|
1838
|
+
*/
|
|
1839
|
+
async listAgents() {
|
|
1840
|
+
return this.client.request(
|
|
1841
|
+
"/v1/cards/mastercard/agents"
|
|
1842
|
+
);
|
|
1843
|
+
}
|
|
1844
|
+
/**
|
|
1845
|
+
* Create a Mastercard agentic token with DTVC
|
|
1846
|
+
*/
|
|
1847
|
+
async createToken(params) {
|
|
1848
|
+
return this.client.request("/v1/cards/mastercard/tokens", {
|
|
1849
|
+
method: "POST",
|
|
1850
|
+
body: JSON.stringify(params)
|
|
1851
|
+
});
|
|
1852
|
+
}
|
|
1853
|
+
/**
|
|
1854
|
+
* Get a Mastercard token, optionally refreshing the DTVC
|
|
1855
|
+
*/
|
|
1856
|
+
async getToken(tokenReference, options) {
|
|
1857
|
+
const query = options?.refresh ? "?refresh=true" : "";
|
|
1858
|
+
return this.client.request(
|
|
1859
|
+
`/v1/cards/mastercard/tokens/${tokenReference}${query}`
|
|
1860
|
+
);
|
|
1861
|
+
}
|
|
1862
|
+
/**
|
|
1863
|
+
* List Mastercard tokens
|
|
1864
|
+
*/
|
|
1865
|
+
async listTokens(options) {
|
|
1866
|
+
const params = new URLSearchParams();
|
|
1867
|
+
if (options?.status) params.set("status", options.status);
|
|
1868
|
+
if (options?.limit) params.set("limit", String(options.limit));
|
|
1869
|
+
if (options?.offset) params.set("offset", String(options.offset));
|
|
1870
|
+
const query = params.toString();
|
|
1871
|
+
return this.client.request(
|
|
1872
|
+
`/v1/cards/mastercard/tokens${query ? `?${query}` : ""}`
|
|
1873
|
+
);
|
|
1874
|
+
}
|
|
1875
|
+
/**
|
|
1876
|
+
* Revoke a Mastercard token
|
|
1877
|
+
*/
|
|
1878
|
+
async revokeToken(tokenReference) {
|
|
1879
|
+
return this.client.request(
|
|
1880
|
+
`/v1/cards/mastercard/tokens/${tokenReference}`,
|
|
1881
|
+
{ method: "DELETE" }
|
|
1882
|
+
);
|
|
1883
|
+
}
|
|
1884
|
+
};
|
|
1885
|
+
CardsClient = class {
|
|
1886
|
+
constructor(client) {
|
|
1887
|
+
this.client = client;
|
|
1888
|
+
this.visa = new VisaClient(client);
|
|
1889
|
+
this.mastercard = new MastercardClient(client);
|
|
1890
|
+
}
|
|
1891
|
+
/**
|
|
1892
|
+
* Verify an AI agent's Web Bot Auth signature
|
|
1893
|
+
*
|
|
1894
|
+
* @example
|
|
1895
|
+
* ```typescript
|
|
1896
|
+
* const result = await payos.cards.verifyAgentSignature({
|
|
1897
|
+
* method: 'POST',
|
|
1898
|
+
* path: '/checkout',
|
|
1899
|
+
* headers: req.headers,
|
|
1900
|
+
* signatureInput: req.headers['signature-input'],
|
|
1901
|
+
* signature: req.headers['signature'],
|
|
1902
|
+
* });
|
|
1903
|
+
*
|
|
1904
|
+
* if (result.valid) {
|
|
1905
|
+
* console.log(`Verified ${result.network} agent from ${result.agentProvider}`);
|
|
1906
|
+
* }
|
|
1907
|
+
* ```
|
|
1908
|
+
*/
|
|
1909
|
+
async verifyAgentSignature(params) {
|
|
1910
|
+
return this.client.request("/v1/cards/verify", {
|
|
1911
|
+
method: "POST",
|
|
1912
|
+
body: JSON.stringify(params)
|
|
1913
|
+
});
|
|
1914
|
+
}
|
|
1915
|
+
/**
|
|
1916
|
+
* Get configured card networks and their status
|
|
1917
|
+
*
|
|
1918
|
+
* @example
|
|
1919
|
+
* ```typescript
|
|
1920
|
+
* const { networks, capabilities } = await payos.cards.getNetworks();
|
|
1921
|
+
*
|
|
1922
|
+
* if (networks.visa.configured) {
|
|
1923
|
+
* console.log(`Visa: ${networks.visa.status}`);
|
|
1924
|
+
* }
|
|
1925
|
+
* ```
|
|
1926
|
+
*/
|
|
1927
|
+
async getNetworks() {
|
|
1928
|
+
return this.client.request("/v1/cards/networks");
|
|
1929
|
+
}
|
|
1930
|
+
/**
|
|
1931
|
+
* Test connection to a card network
|
|
1932
|
+
*/
|
|
1933
|
+
async testNetwork(network) {
|
|
1934
|
+
return this.client.request(`/v1/cards/networks/${network}/test`, {
|
|
1935
|
+
method: "POST"
|
|
1936
|
+
});
|
|
1937
|
+
}
|
|
1938
|
+
/**
|
|
1939
|
+
* Configure Visa VIC credentials
|
|
1940
|
+
*/
|
|
1941
|
+
async configureVisa(params) {
|
|
1942
|
+
return this.client.request("/v1/cards/networks/visa/configure", {
|
|
1943
|
+
method: "POST",
|
|
1944
|
+
body: JSON.stringify(params)
|
|
1945
|
+
});
|
|
1946
|
+
}
|
|
1947
|
+
/**
|
|
1948
|
+
* Configure Mastercard Agent Pay credentials
|
|
1949
|
+
*/
|
|
1950
|
+
async configureMastercard(params) {
|
|
1951
|
+
return this.client.request("/v1/cards/networks/mastercard/configure", {
|
|
1952
|
+
method: "POST",
|
|
1953
|
+
body: JSON.stringify(params)
|
|
1954
|
+
});
|
|
1955
|
+
}
|
|
1956
|
+
/**
|
|
1957
|
+
* Disconnect a card network
|
|
1958
|
+
*/
|
|
1959
|
+
async disconnectNetwork(network) {
|
|
1960
|
+
return this.client.request(
|
|
1961
|
+
`/v1/cards/networks/${network}/disconnect`,
|
|
1962
|
+
{ method: "DELETE" }
|
|
1963
|
+
);
|
|
1964
|
+
}
|
|
1965
|
+
/**
|
|
1966
|
+
* Get comprehensive card network analytics
|
|
1967
|
+
*
|
|
1968
|
+
* @param days - Number of days to analyze (default: 30)
|
|
1969
|
+
*
|
|
1970
|
+
* @example
|
|
1971
|
+
* ```typescript
|
|
1972
|
+
* const analytics = await payos.cards.getAnalytics(30);
|
|
1973
|
+
*
|
|
1974
|
+
* console.log(`Success rate: ${analytics.verifications.successRate}%`);
|
|
1975
|
+
* console.log(`Total volume: $${analytics.transactions.volume}`);
|
|
1976
|
+
* ```
|
|
1977
|
+
*/
|
|
1978
|
+
async getAnalytics(days = 30) {
|
|
1979
|
+
return this.client.request(`/v1/cards/analytics?days=${days}`);
|
|
1980
|
+
}
|
|
1981
|
+
/**
|
|
1982
|
+
* Get verification statistics
|
|
1983
|
+
*
|
|
1984
|
+
* @param days - Number of days to analyze (default: 30)
|
|
1985
|
+
*/
|
|
1986
|
+
async getVerificationStats(days = 30) {
|
|
1987
|
+
return this.client.request(`/v1/cards/verifications/stats?days=${days}`);
|
|
1988
|
+
}
|
|
1989
|
+
/**
|
|
1990
|
+
* List card network transactions
|
|
1991
|
+
*/
|
|
1992
|
+
async listTransactions(options) {
|
|
1993
|
+
const params = new URLSearchParams();
|
|
1994
|
+
if (options?.network) params.set("network", options.network);
|
|
1995
|
+
if (options?.status) params.set("status", options.status);
|
|
1996
|
+
if (options?.limit) params.set("limit", String(options.limit));
|
|
1997
|
+
if (options?.offset) params.set("offset", String(options.offset));
|
|
1998
|
+
const query = params.toString();
|
|
1999
|
+
return this.client.request(
|
|
2000
|
+
`/v1/cards/transactions${query ? `?${query}` : ""}`
|
|
2001
|
+
);
|
|
2002
|
+
}
|
|
2003
|
+
/**
|
|
2004
|
+
* Get a specific transaction
|
|
2005
|
+
*/
|
|
2006
|
+
async getTransaction(transactionId) {
|
|
2007
|
+
return this.client.request(`/v1/cards/transactions/${transactionId}`);
|
|
2008
|
+
}
|
|
2009
|
+
// ============================================
|
|
2010
|
+
// Agent Signing Methods
|
|
2011
|
+
// ============================================
|
|
2012
|
+
/**
|
|
2013
|
+
* Generate a signing key for an agent
|
|
2014
|
+
*
|
|
2015
|
+
* Creates an Ed25519 or RSA-SHA256 key pair for the agent to sign
|
|
2016
|
+
* payment requests according to RFC 9421 (HTTP Message Signatures).
|
|
2017
|
+
*
|
|
2018
|
+
* @example
|
|
2019
|
+
* ```typescript
|
|
2020
|
+
* const key = await payos.cards.generateSigningKey('agent_123');
|
|
2021
|
+
* console.log(`Public key: ${key.publicKey}`);
|
|
2022
|
+
* // Register this public key with card networks (Visa TAP, MC Agent Pay)
|
|
2023
|
+
* ```
|
|
2024
|
+
*/
|
|
2025
|
+
async generateSigningKey(agentId, options) {
|
|
2026
|
+
return this.client.request(
|
|
2027
|
+
`/v1/agents/${agentId}/signing-keys`,
|
|
2028
|
+
{
|
|
2029
|
+
method: "POST",
|
|
2030
|
+
body: JSON.stringify(options || {})
|
|
2031
|
+
}
|
|
2032
|
+
);
|
|
2033
|
+
}
|
|
2034
|
+
/**
|
|
2035
|
+
* Get the signing key status for an agent
|
|
2036
|
+
*
|
|
2037
|
+
* @example
|
|
2038
|
+
* ```typescript
|
|
2039
|
+
* const status = await payos.cards.getSigningKey('agent_123');
|
|
2040
|
+
* if (status.hasKey) {
|
|
2041
|
+
* console.log(`Key: ${status.keyId}, Uses: ${status.stats.useCount}`);
|
|
2042
|
+
* }
|
|
2043
|
+
* ```
|
|
2044
|
+
*/
|
|
2045
|
+
async getSigningKey(agentId) {
|
|
2046
|
+
return this.client.request(`/v1/agents/${agentId}/signing-keys`);
|
|
2047
|
+
}
|
|
2048
|
+
/**
|
|
2049
|
+
* Revoke an agent's signing key
|
|
2050
|
+
*
|
|
2051
|
+
* After revocation, the agent will need a new key to sign requests.
|
|
2052
|
+
*/
|
|
2053
|
+
async revokeSigningKey(agentId) {
|
|
2054
|
+
return this.client.request(
|
|
2055
|
+
`/v1/agents/${agentId}/signing-keys`,
|
|
2056
|
+
{ method: "DELETE" }
|
|
2057
|
+
);
|
|
2058
|
+
}
|
|
2059
|
+
/**
|
|
2060
|
+
* Sign a payment request for an agent
|
|
2061
|
+
*
|
|
2062
|
+
* Signs an HTTP request according to RFC 9421 so the agent can
|
|
2063
|
+
* authenticate with merchants and card networks.
|
|
2064
|
+
*
|
|
2065
|
+
* Requirements:
|
|
2066
|
+
* - Agent must have KYA tier >= 1
|
|
2067
|
+
* - Agent must be active
|
|
2068
|
+
* - Agent must have a signing key
|
|
2069
|
+
* - Payment must be within spending limits
|
|
2070
|
+
*
|
|
2071
|
+
* @example
|
|
2072
|
+
* ```typescript
|
|
2073
|
+
* // Sign a payment request
|
|
2074
|
+
* const signed = await payos.cards.signRequest('agent_123', {
|
|
2075
|
+
* method: 'POST',
|
|
2076
|
+
* path: '/api/checkout',
|
|
2077
|
+
* host: 'merchant.com',
|
|
2078
|
+
* body: JSON.stringify({ items: [...], total: 99.99 }),
|
|
2079
|
+
* payment: {
|
|
2080
|
+
* amount: 99.99,
|
|
2081
|
+
* currency: 'USD',
|
|
2082
|
+
* merchantName: 'Acme Store',
|
|
2083
|
+
* },
|
|
2084
|
+
* });
|
|
2085
|
+
*
|
|
2086
|
+
* // Agent uses signed headers to call merchant
|
|
2087
|
+
* const response = await fetch('https://merchant.com/api/checkout', {
|
|
2088
|
+
* method: 'POST',
|
|
2089
|
+
* headers: {
|
|
2090
|
+
* ...signed.headers,
|
|
2091
|
+
* 'Content-Type': 'application/json',
|
|
2092
|
+
* },
|
|
2093
|
+
* body: JSON.stringify({ items: [...], total: 99.99 }),
|
|
2094
|
+
* });
|
|
2095
|
+
* ```
|
|
2096
|
+
*/
|
|
2097
|
+
async signRequest(agentId, request) {
|
|
2098
|
+
return this.client.request(
|
|
2099
|
+
`/v1/agents/${agentId}/sign-request`,
|
|
2100
|
+
{
|
|
2101
|
+
method: "POST",
|
|
2102
|
+
body: JSON.stringify(request)
|
|
2103
|
+
}
|
|
2104
|
+
);
|
|
2105
|
+
}
|
|
2106
|
+
};
|
|
2107
|
+
}
|
|
2108
|
+
});
|
|
2109
|
+
|
|
2110
|
+
// src/protocols/a2a/client.ts
|
|
2111
|
+
var A2AClient;
|
|
2112
|
+
var init_client7 = __esm({
|
|
2113
|
+
"src/protocols/a2a/client.ts"() {
|
|
2114
|
+
A2AClient = class {
|
|
2115
|
+
constructor(client) {
|
|
2116
|
+
this.client = client;
|
|
2117
|
+
}
|
|
2118
|
+
/**
|
|
2119
|
+
* Discover an agent's capabilities via its Agent Card.
|
|
2120
|
+
*
|
|
2121
|
+
* @example
|
|
2122
|
+
* ```typescript
|
|
2123
|
+
* const card = await sly.a2a.discover('agent-uuid');
|
|
2124
|
+
* console.log(card.skills);
|
|
2125
|
+
* ```
|
|
2126
|
+
*/
|
|
2127
|
+
async discover(agentId) {
|
|
2128
|
+
return this.client.request(
|
|
2129
|
+
`/v1/a2a/${agentId}/.well-known/agent.json`
|
|
2130
|
+
);
|
|
2131
|
+
}
|
|
2132
|
+
/**
|
|
2133
|
+
* Send a message to an agent, creating or continuing a task.
|
|
2134
|
+
*
|
|
2135
|
+
* @example
|
|
2136
|
+
* ```typescript
|
|
2137
|
+
* const task = await sly.a2a.sendMessage('agent-uuid', {
|
|
2138
|
+
* message: 'Check my wallet balance',
|
|
2139
|
+
* });
|
|
2140
|
+
* console.log(task.status.state); // 'submitted' or 'completed'
|
|
2141
|
+
* ```
|
|
2142
|
+
*/
|
|
2143
|
+
async sendMessage(agentId, params) {
|
|
2144
|
+
const parts = typeof params.message === "string" ? [{ text: params.message }] : params.message;
|
|
2145
|
+
const body = {
|
|
2146
|
+
jsonrpc: "2.0",
|
|
2147
|
+
method: "message/send",
|
|
2148
|
+
params: {
|
|
2149
|
+
message: { role: "user", parts, metadata: params.metadata },
|
|
2150
|
+
...params.contextId && { contextId: params.contextId },
|
|
2151
|
+
...params.configuration && { configuration: params.configuration },
|
|
2152
|
+
...params.skillId && { skill_id: params.skillId }
|
|
2153
|
+
},
|
|
2154
|
+
id: crypto.randomUUID()
|
|
2155
|
+
};
|
|
2156
|
+
const response = await this.client.request(
|
|
2157
|
+
`/v1/a2a/${agentId}`,
|
|
2158
|
+
{ method: "POST", body: JSON.stringify(body) }
|
|
2159
|
+
);
|
|
2160
|
+
return response.result;
|
|
2161
|
+
}
|
|
2162
|
+
/**
|
|
2163
|
+
* Get a task by ID.
|
|
2164
|
+
*
|
|
2165
|
+
* @example
|
|
2166
|
+
* ```typescript
|
|
2167
|
+
* const task = await sly.a2a.getTask('agent-uuid', 'task-uuid');
|
|
2168
|
+
* console.log(task.status.state);
|
|
2169
|
+
* ```
|
|
2170
|
+
*/
|
|
2171
|
+
async getTask(agentId, taskId, historyLength) {
|
|
2172
|
+
const body = {
|
|
2173
|
+
jsonrpc: "2.0",
|
|
2174
|
+
method: "tasks/get",
|
|
2175
|
+
params: { id: taskId, ...historyLength && { historyLength } },
|
|
2176
|
+
id: crypto.randomUUID()
|
|
2177
|
+
};
|
|
2178
|
+
const response = await this.client.request(
|
|
2179
|
+
`/v1/a2a/${agentId}`,
|
|
2180
|
+
{ method: "POST", body: JSON.stringify(body) }
|
|
2181
|
+
);
|
|
2182
|
+
return response.result;
|
|
2183
|
+
}
|
|
2184
|
+
/**
|
|
2185
|
+
* Cancel a task.
|
|
2186
|
+
*/
|
|
2187
|
+
async cancelTask(agentId, taskId) {
|
|
2188
|
+
const body = {
|
|
2189
|
+
jsonrpc: "2.0",
|
|
2190
|
+
method: "tasks/cancel",
|
|
2191
|
+
params: { id: taskId },
|
|
2192
|
+
id: crypto.randomUUID()
|
|
2193
|
+
};
|
|
2194
|
+
const response = await this.client.request(
|
|
2195
|
+
`/v1/a2a/${agentId}`,
|
|
2196
|
+
{ method: "POST", body: JSON.stringify(body) }
|
|
2197
|
+
);
|
|
2198
|
+
return response.result;
|
|
2199
|
+
}
|
|
2200
|
+
/**
|
|
2201
|
+
* List tasks for an agent (REST endpoint).
|
|
2202
|
+
*
|
|
2203
|
+
* @example
|
|
2204
|
+
* ```typescript
|
|
2205
|
+
* const { data, pagination } = await sly.a2a.listTasks({
|
|
2206
|
+
* agentId: 'agent-uuid',
|
|
2207
|
+
* state: 'completed',
|
|
2208
|
+
* limit: 20,
|
|
2209
|
+
* });
|
|
2210
|
+
* ```
|
|
2211
|
+
*/
|
|
2212
|
+
async listTasks(options = {}) {
|
|
2213
|
+
const params = new URLSearchParams();
|
|
2214
|
+
if (options.agentId) params.append("agent_id", options.agentId);
|
|
2215
|
+
if (options.state) params.append("state", options.state);
|
|
2216
|
+
if (options.direction) params.append("direction", options.direction);
|
|
2217
|
+
if (options.contextId) params.append("context_id", options.contextId);
|
|
2218
|
+
if (options.page) params.append("page", options.page.toString());
|
|
2219
|
+
if (options.limit) params.append("limit", options.limit.toString());
|
|
2220
|
+
const qs = params.toString();
|
|
2221
|
+
return this.client.request(
|
|
2222
|
+
qs ? `/v1/a2a/tasks?${qs}` : "/v1/a2a/tasks"
|
|
2223
|
+
);
|
|
2224
|
+
}
|
|
2225
|
+
/**
|
|
2226
|
+
* Respond to a task in input-required state (human-in-the-loop).
|
|
2227
|
+
*/
|
|
2228
|
+
async respond(taskId, message) {
|
|
2229
|
+
return this.client.request(
|
|
2230
|
+
`/v1/a2a/tasks/${taskId}/respond`,
|
|
2231
|
+
{ method: "POST", body: JSON.stringify({ message }) }
|
|
2232
|
+
);
|
|
2233
|
+
}
|
|
2234
|
+
// =========================================================================
|
|
2235
|
+
// Custom Tools (Story 58.15)
|
|
2236
|
+
// =========================================================================
|
|
2237
|
+
/**
|
|
2238
|
+
* Register a custom tool for an agent.
|
|
2239
|
+
*
|
|
2240
|
+
* @example
|
|
2241
|
+
* ```typescript
|
|
2242
|
+
* const tool = await sly.a2a.createCustomTool('agent-uuid', {
|
|
2243
|
+
* toolName: 'lookup_inventory',
|
|
2244
|
+
* description: 'Check product inventory levels',
|
|
2245
|
+
* inputSchema: {
|
|
2246
|
+
* type: 'object',
|
|
2247
|
+
* properties: { sku: { type: 'string' } },
|
|
2248
|
+
* required: ['sku'],
|
|
2249
|
+
* },
|
|
2250
|
+
* handlerUrl: 'https://api.example.com/inventory',
|
|
2251
|
+
* });
|
|
2252
|
+
* ```
|
|
2253
|
+
*/
|
|
2254
|
+
async createCustomTool(agentId, request) {
|
|
2255
|
+
const response = await this.client.request(
|
|
2256
|
+
`/v1/a2a/agents/${agentId}/tools`,
|
|
2257
|
+
{ method: "POST", body: JSON.stringify(request) }
|
|
2258
|
+
);
|
|
2259
|
+
return response.data;
|
|
2260
|
+
}
|
|
2261
|
+
/**
|
|
2262
|
+
* List custom tools for an agent.
|
|
2263
|
+
*/
|
|
2264
|
+
async listCustomTools(agentId) {
|
|
2265
|
+
const response = await this.client.request(
|
|
2266
|
+
`/v1/a2a/agents/${agentId}/tools`
|
|
2267
|
+
);
|
|
2268
|
+
return response.data;
|
|
2269
|
+
}
|
|
2270
|
+
/**
|
|
2271
|
+
* Delete a custom tool.
|
|
2272
|
+
*/
|
|
2273
|
+
async deleteCustomTool(agentId, toolId) {
|
|
2274
|
+
await this.client.request(
|
|
2275
|
+
`/v1/a2a/agents/${agentId}/tools/${toolId}`,
|
|
2276
|
+
{ method: "DELETE" }
|
|
2277
|
+
);
|
|
2278
|
+
}
|
|
2279
|
+
};
|
|
2280
|
+
}
|
|
2281
|
+
});
|
|
2282
|
+
|
|
2283
|
+
// src/protocols/agent-wallets/client.ts
|
|
2284
|
+
var AgentWalletsClient;
|
|
2285
|
+
var init_client8 = __esm({
|
|
2286
|
+
"src/protocols/agent-wallets/client.ts"() {
|
|
2287
|
+
AgentWalletsClient = class {
|
|
2288
|
+
constructor(client) {
|
|
2289
|
+
this.client = client;
|
|
2290
|
+
}
|
|
2291
|
+
/**
|
|
2292
|
+
* Evaluate a contract policy in dry-run mode (negotiation guardrails).
|
|
2293
|
+
*
|
|
2294
|
+
* @example
|
|
2295
|
+
* ```typescript
|
|
2296
|
+
* const result = await sly.agentWallets.evaluatePolicy('agent-uuid', {
|
|
2297
|
+
* amount: 150,
|
|
2298
|
+
* actionType: 'payment',
|
|
2299
|
+
* counterpartyAgentId: 'other-agent-uuid',
|
|
2300
|
+
* });
|
|
2301
|
+
* console.log(result.decision); // 'approve' | 'escalate' | 'deny'
|
|
2302
|
+
* ```
|
|
2303
|
+
*/
|
|
2304
|
+
async evaluatePolicy(agentId, request) {
|
|
2305
|
+
const response = await this.client.request(
|
|
2306
|
+
`/v1/agents/${agentId}/wallet/policy/evaluate`,
|
|
2307
|
+
{
|
|
2308
|
+
method: "POST",
|
|
2309
|
+
body: JSON.stringify({
|
|
2310
|
+
amount: request.amount,
|
|
2311
|
+
currency: request.currency || "USDC",
|
|
2312
|
+
action_type: request.actionType,
|
|
2313
|
+
contract_type: request.contractType,
|
|
2314
|
+
counterparty_agent_id: request.counterpartyAgentId,
|
|
2315
|
+
counterparty_address: request.counterpartyAddress,
|
|
2316
|
+
protocol: request.protocol
|
|
2317
|
+
})
|
|
2318
|
+
}
|
|
2319
|
+
);
|
|
2320
|
+
const d = response.data || response;
|
|
2321
|
+
return {
|
|
2322
|
+
decision: d.decision,
|
|
2323
|
+
reasons: d.reasons,
|
|
2324
|
+
checks: d.checks,
|
|
2325
|
+
suggestedCounterOffer: d.suggested_counter_offer ? {
|
|
2326
|
+
maxAmount: d.suggested_counter_offer.max_amount,
|
|
2327
|
+
reason: d.suggested_counter_offer.reason
|
|
2328
|
+
} : null,
|
|
2329
|
+
evaluationMs: d.evaluation_ms
|
|
2330
|
+
};
|
|
2331
|
+
}
|
|
2332
|
+
/**
|
|
2333
|
+
* List counterparty exposures for an agent's wallet.
|
|
2334
|
+
*
|
|
2335
|
+
* @example
|
|
2336
|
+
* ```typescript
|
|
2337
|
+
* const exposures = await sly.agentWallets.getExposures('agent-uuid');
|
|
2338
|
+
* for (const exp of exposures) {
|
|
2339
|
+
* console.log(`${exp.counterpartyAgentId}: ${exp.exposure24h} (24h)`);
|
|
2340
|
+
* }
|
|
2341
|
+
* ```
|
|
2342
|
+
*/
|
|
2343
|
+
async getExposures(agentId) {
|
|
2344
|
+
const response = await this.client.request(
|
|
2345
|
+
`/v1/agents/${agentId}/wallet/exposures`
|
|
2346
|
+
);
|
|
2347
|
+
const items = response.data || [];
|
|
2348
|
+
return items.map((e) => ({
|
|
2349
|
+
id: e.id,
|
|
2350
|
+
walletId: e.wallet_id,
|
|
2351
|
+
counterpartyAgentId: e.counterparty_agent_id,
|
|
2352
|
+
counterpartyAddress: e.counterparty_address,
|
|
2353
|
+
exposure24h: e.exposure_24h,
|
|
2354
|
+
exposure7d: e.exposure_7d,
|
|
2355
|
+
exposure30d: e.exposure_30d,
|
|
2356
|
+
activeContracts: e.active_contracts,
|
|
2357
|
+
activeEscrows: e.active_escrows,
|
|
2358
|
+
totalVolume: e.total_volume,
|
|
2359
|
+
transactionCount: e.transaction_count,
|
|
2360
|
+
currency: e.currency
|
|
2361
|
+
}));
|
|
2362
|
+
}
|
|
2363
|
+
/**
|
|
2364
|
+
* Get policy evaluation audit log for an agent's wallet.
|
|
2365
|
+
*/
|
|
2366
|
+
async getEvaluations(agentId, options) {
|
|
2367
|
+
const params = new URLSearchParams();
|
|
2368
|
+
if (options?.page) params.set("page", options.page.toString());
|
|
2369
|
+
if (options?.limit) params.set("limit", options.limit.toString());
|
|
2370
|
+
const qs = params.toString();
|
|
2371
|
+
const response = await this.client.request(
|
|
2372
|
+
`/v1/agents/${agentId}/wallet/policy/evaluations${qs ? `?${qs}` : ""}`
|
|
2373
|
+
);
|
|
2374
|
+
return {
|
|
2375
|
+
data: (response.data || []).map((e) => ({
|
|
2376
|
+
id: e.id,
|
|
2377
|
+
actionType: e.action_type,
|
|
2378
|
+
amount: e.amount,
|
|
2379
|
+
currency: e.currency,
|
|
2380
|
+
contractType: e.contract_type,
|
|
2381
|
+
counterpartyAgentId: e.counterparty_agent_id,
|
|
2382
|
+
counterpartyAddress: e.counterparty_address,
|
|
2383
|
+
decision: e.decision,
|
|
2384
|
+
decisionReasons: e.decision_reasons,
|
|
2385
|
+
suggestedCounterOffer: e.suggested_counter_offer,
|
|
2386
|
+
checksPerformed: e.checks_performed,
|
|
2387
|
+
evaluationMs: e.evaluation_ms,
|
|
2388
|
+
createdAt: e.created_at
|
|
2389
|
+
})),
|
|
2390
|
+
pagination: response.pagination
|
|
2391
|
+
};
|
|
2392
|
+
}
|
|
2393
|
+
/**
|
|
2394
|
+
* Get an agent's wallet details.
|
|
2395
|
+
*/
|
|
2396
|
+
async getWallet(agentId) {
|
|
2397
|
+
const response = await this.client.request(
|
|
2398
|
+
`/v1/agents/${agentId}/wallet`
|
|
2399
|
+
);
|
|
2400
|
+
return response.data || response;
|
|
2401
|
+
}
|
|
2402
|
+
/**
|
|
2403
|
+
* Freeze an agent's wallet (disables all payments).
|
|
2404
|
+
*/
|
|
2405
|
+
async freezeWallet(agentId) {
|
|
2406
|
+
const response = await this.client.request(
|
|
2407
|
+
`/v1/agents/${agentId}/wallet/freeze`,
|
|
2408
|
+
{ method: "POST" }
|
|
2409
|
+
);
|
|
2410
|
+
return response.data || response;
|
|
2411
|
+
}
|
|
2412
|
+
/**
|
|
2413
|
+
* Unfreeze an agent's wallet (re-enables payments).
|
|
2414
|
+
*/
|
|
2415
|
+
async unfreezeWallet(agentId) {
|
|
2416
|
+
const response = await this.client.request(
|
|
2417
|
+
`/v1/agents/${agentId}/wallet/unfreeze`,
|
|
2418
|
+
{ method: "POST" }
|
|
2419
|
+
);
|
|
2420
|
+
return response.data || response;
|
|
2421
|
+
}
|
|
2422
|
+
/**
|
|
2423
|
+
* Set or update the contract policy on an agent's wallet.
|
|
2424
|
+
*
|
|
2425
|
+
* @example
|
|
2426
|
+
* ```typescript
|
|
2427
|
+
* await sly.agentWallets.setContractPolicy('agent-uuid', {
|
|
2428
|
+
* dailySpendLimit: 500,
|
|
2429
|
+
* contractPolicy: {
|
|
2430
|
+
* counterpartyBlocklist: ['bad-agent-id'],
|
|
2431
|
+
* maxExposure24h: 200,
|
|
2432
|
+
* escalateAbove: 100,
|
|
2433
|
+
* },
|
|
2434
|
+
* });
|
|
2435
|
+
* ```
|
|
2436
|
+
*/
|
|
2437
|
+
async setContractPolicy(agentId, policy) {
|
|
2438
|
+
const response = await this.client.request(
|
|
2439
|
+
`/v1/agents/${agentId}/wallet/policy`,
|
|
2440
|
+
{
|
|
2441
|
+
method: "PUT",
|
|
2442
|
+
body: JSON.stringify(policy)
|
|
2443
|
+
}
|
|
2444
|
+
);
|
|
2445
|
+
return response.data || response;
|
|
2446
|
+
}
|
|
2447
|
+
};
|
|
2448
|
+
}
|
|
2449
|
+
});
|
|
2450
|
+
|
|
2451
|
+
// src/protocols/mpp/client.ts
|
|
2452
|
+
var MPPClient;
|
|
2453
|
+
var init_client9 = __esm({
|
|
2454
|
+
"src/protocols/mpp/client.ts"() {
|
|
2455
|
+
MPPClient = class {
|
|
2456
|
+
constructor(client) {
|
|
2457
|
+
this.client = client;
|
|
2458
|
+
}
|
|
2459
|
+
/**
|
|
2460
|
+
* Make a one-shot MPP payment to a service
|
|
2461
|
+
*
|
|
2462
|
+
* @example
|
|
2463
|
+
* ```typescript
|
|
2464
|
+
* const result = await sly.mpp.pay({
|
|
2465
|
+
* service_url: 'https://api.example.com',
|
|
2466
|
+
* amount: 0.50,
|
|
2467
|
+
* agent_id: 'agent-uuid',
|
|
2468
|
+
* });
|
|
2469
|
+
* ```
|
|
2470
|
+
*/
|
|
2471
|
+
async pay(request) {
|
|
2472
|
+
return this.client.request("/v1/mpp/pay", {
|
|
2473
|
+
method: "POST",
|
|
2474
|
+
body: JSON.stringify(request)
|
|
2475
|
+
});
|
|
2476
|
+
}
|
|
2477
|
+
/**
|
|
2478
|
+
* Open a streaming payment session
|
|
2479
|
+
*
|
|
2480
|
+
* @example
|
|
2481
|
+
* ```typescript
|
|
2482
|
+
* const session = await sly.mpp.openSession({
|
|
2483
|
+
* service_url: 'https://api.example.com',
|
|
2484
|
+
* deposit_amount: 10.00,
|
|
2485
|
+
* agent_id: 'agent-uuid',
|
|
2486
|
+
* wallet_id: 'wallet-uuid',
|
|
2487
|
+
* });
|
|
2488
|
+
* ```
|
|
2489
|
+
*/
|
|
2490
|
+
async openSession(request) {
|
|
2491
|
+
return this.client.request("/v1/mpp/sessions", {
|
|
2492
|
+
method: "POST",
|
|
2493
|
+
body: JSON.stringify(request)
|
|
2494
|
+
});
|
|
2495
|
+
}
|
|
2496
|
+
/**
|
|
2497
|
+
* Get session details with voucher history
|
|
2498
|
+
*/
|
|
2499
|
+
async getSession(sessionId) {
|
|
2500
|
+
return this.client.request(`/v1/mpp/sessions/${sessionId}`);
|
|
2501
|
+
}
|
|
2502
|
+
/**
|
|
2503
|
+
* List MPP sessions with optional filtering
|
|
2504
|
+
*/
|
|
2505
|
+
async listSessions(options = {}) {
|
|
2506
|
+
const params = new URLSearchParams();
|
|
2507
|
+
if (options.agent_id) params.append("agent_id", options.agent_id);
|
|
2508
|
+
if (options.status) params.append("status", options.status);
|
|
2509
|
+
if (options.limit) params.append("limit", options.limit.toString());
|
|
2510
|
+
if (options.offset) params.append("offset", options.offset.toString());
|
|
2511
|
+
const queryString = params.toString();
|
|
2512
|
+
const path = queryString ? `/v1/mpp/sessions?${queryString}` : "/v1/mpp/sessions";
|
|
2513
|
+
return this.client.request(path);
|
|
2514
|
+
}
|
|
2515
|
+
/**
|
|
2516
|
+
* Close an active session
|
|
2517
|
+
*/
|
|
2518
|
+
async closeSession(sessionId) {
|
|
2519
|
+
return this.client.request(`/v1/mpp/sessions/${sessionId}/close`, {
|
|
2520
|
+
method: "POST"
|
|
2521
|
+
});
|
|
2522
|
+
}
|
|
2523
|
+
/**
|
|
2524
|
+
* List MPP payment transfers
|
|
2525
|
+
*/
|
|
2526
|
+
async listTransfers(options = {}) {
|
|
2527
|
+
const params = new URLSearchParams();
|
|
2528
|
+
if (options.service_url) params.append("service_url", options.service_url);
|
|
2529
|
+
if (options.session_id) params.append("session_id", options.session_id);
|
|
2530
|
+
if (options.limit) params.append("limit", options.limit.toString());
|
|
2531
|
+
if (options.offset) params.append("offset", options.offset.toString());
|
|
2532
|
+
const queryString = params.toString();
|
|
2533
|
+
const path = queryString ? `/v1/mpp/transfers?${queryString}` : "/v1/mpp/transfers";
|
|
2534
|
+
return this.client.request(path);
|
|
2535
|
+
}
|
|
2536
|
+
/**
|
|
2537
|
+
* Verify an MPP payment receipt
|
|
2538
|
+
*/
|
|
2539
|
+
async verifyReceipt(receiptId) {
|
|
2540
|
+
return this.client.request("/v1/mpp/receipts/verify", {
|
|
2541
|
+
method: "POST",
|
|
2542
|
+
body: JSON.stringify({ receipt_id: receiptId })
|
|
2543
|
+
});
|
|
2544
|
+
}
|
|
2545
|
+
/**
|
|
2546
|
+
* Provision a wallet for MPP payments
|
|
2547
|
+
*/
|
|
2548
|
+
async provisionWallet(request) {
|
|
2549
|
+
return this.client.request("/v1/mpp/wallets/provision", {
|
|
2550
|
+
method: "POST",
|
|
2551
|
+
body: JSON.stringify(request)
|
|
2552
|
+
});
|
|
2553
|
+
}
|
|
2554
|
+
/**
|
|
2555
|
+
* Browse the MPP service directory
|
|
2556
|
+
*/
|
|
2557
|
+
async browseServices(options) {
|
|
2558
|
+
const params = new URLSearchParams();
|
|
2559
|
+
if (options?.category) params.append("category", options.category);
|
|
2560
|
+
if (options?.limit) params.append("limit", options.limit.toString());
|
|
2561
|
+
const queryString = params.toString();
|
|
2562
|
+
const path = queryString ? `/v1/mpp/services?${queryString}` : "/v1/mpp/services";
|
|
2563
|
+
return this.client.request(path);
|
|
2564
|
+
}
|
|
2565
|
+
/**
|
|
2566
|
+
* Get pricing info for a service
|
|
2567
|
+
*/
|
|
2568
|
+
async getServicePricing(domain) {
|
|
2569
|
+
return this.client.request(`/v1/mpp/services/${domain}/pricing`);
|
|
2570
|
+
}
|
|
2571
|
+
};
|
|
2572
|
+
}
|
|
2573
|
+
});
|
|
2574
|
+
|
|
2575
|
+
// src/types.ts
|
|
2576
|
+
var init_types3 = __esm({
|
|
2577
|
+
"src/types.ts"() {
|
|
2578
|
+
}
|
|
2579
|
+
});
|
|
2580
|
+
|
|
2581
|
+
// src/auth.ts
|
|
2582
|
+
async function loginWithPassword(credentials, apiUrl = "http://localhost:4000") {
|
|
2583
|
+
const response = await fetch(`${apiUrl}/v1/auth/login`, {
|
|
2584
|
+
method: "POST",
|
|
2585
|
+
headers: {
|
|
2586
|
+
"Content-Type": "application/json"
|
|
2587
|
+
},
|
|
2588
|
+
body: JSON.stringify(credentials)
|
|
2589
|
+
});
|
|
2590
|
+
if (!response.ok) {
|
|
2591
|
+
const error = await response.json().catch(() => ({
|
|
2592
|
+
error: response.statusText
|
|
2593
|
+
}));
|
|
2594
|
+
throw new Error(error.error || `Login failed: ${response.status}`);
|
|
2595
|
+
}
|
|
2596
|
+
return response.json();
|
|
2597
|
+
}
|
|
2598
|
+
async function createWithPassword(credentials, environment = "sandbox", apiUrl) {
|
|
2599
|
+
const { PayOS } = await Promise.resolve().then(() => (init_src(), src_exports));
|
|
2600
|
+
const auth = await loginWithPassword(credentials, apiUrl);
|
|
2601
|
+
return new PayOS({
|
|
2602
|
+
apiKey: auth.access_token,
|
|
2603
|
+
environment,
|
|
2604
|
+
apiUrl
|
|
2605
|
+
});
|
|
2606
|
+
}
|
|
2607
|
+
async function verifyApiKey(apiKey, apiUrl = "http://localhost:4000") {
|
|
2608
|
+
try {
|
|
2609
|
+
const response = await fetch(`${apiUrl}/v1/auth/me`, {
|
|
2610
|
+
headers: {
|
|
2611
|
+
"Authorization": `Bearer ${apiKey}`
|
|
2612
|
+
}
|
|
2613
|
+
});
|
|
2614
|
+
return response.ok;
|
|
2615
|
+
} catch {
|
|
2616
|
+
return false;
|
|
2617
|
+
}
|
|
2618
|
+
}
|
|
2619
|
+
var init_auth = __esm({
|
|
2620
|
+
"src/auth.ts"() {
|
|
2621
|
+
}
|
|
2622
|
+
});
|
|
2623
|
+
|
|
2624
|
+
// src/index.ts
|
|
2625
|
+
var src_exports = {};
|
|
2626
|
+
__export(src_exports, {
|
|
2627
|
+
ENVIRONMENT_CONFIGS: () => ENVIRONMENT_CONFIGS,
|
|
2628
|
+
PayOS: () => Sly,
|
|
2629
|
+
PayOSClient: () => SlyClient,
|
|
2630
|
+
Sly: () => Sly,
|
|
2631
|
+
SlyClient: () => SlyClient,
|
|
2632
|
+
createWithPassword: () => createWithPassword,
|
|
2633
|
+
getEnvironmentConfig: () => getEnvironmentConfig,
|
|
2634
|
+
inferEnvironmentFromKey: () => inferEnvironmentFromKey,
|
|
2635
|
+
loginWithPassword: () => loginWithPassword,
|
|
2636
|
+
validateEnvironment: () => validateEnvironment,
|
|
2637
|
+
verifyApiKey: () => verifyApiKey
|
|
2638
|
+
});
|
|
2639
|
+
var Sly;
|
|
2640
|
+
var init_src = __esm({
|
|
2641
|
+
"src/index.ts"() {
|
|
2642
|
+
init_client();
|
|
2643
|
+
init_config();
|
|
2644
|
+
init_client2();
|
|
2645
|
+
init_provider();
|
|
2646
|
+
init_client3();
|
|
2647
|
+
init_client4();
|
|
2648
|
+
init_client5();
|
|
2649
|
+
init_capabilities();
|
|
2650
|
+
init_tools();
|
|
2651
|
+
init_cards();
|
|
2652
|
+
init_client7();
|
|
2653
|
+
init_client8();
|
|
2654
|
+
init_client9();
|
|
2655
|
+
init_types3();
|
|
2656
|
+
init_config();
|
|
2657
|
+
init_client();
|
|
2658
|
+
init_auth();
|
|
2659
|
+
Sly = class extends SlyClient {
|
|
2660
|
+
constructor(config) {
|
|
2661
|
+
if (!config.apiKey || config.apiKey.trim() === "") {
|
|
2662
|
+
throw new Error("API key is required");
|
|
2663
|
+
}
|
|
2664
|
+
const resolvedEnvironment = config.environment ?? inferEnvironmentFromKey(config.apiKey) ?? "sandbox";
|
|
2665
|
+
const resolvedConfig = { ...config, environment: resolvedEnvironment };
|
|
2666
|
+
super(resolvedConfig);
|
|
2667
|
+
this.x402 = {
|
|
2668
|
+
createClient: (overrides) => {
|
|
2669
|
+
return new SlyX402Client({
|
|
2670
|
+
...resolvedConfig,
|
|
2671
|
+
...overrides
|
|
2672
|
+
});
|
|
2673
|
+
},
|
|
2674
|
+
createProvider: (routes) => {
|
|
2675
|
+
return new SlyX402Provider({
|
|
2676
|
+
apiKey: config.apiKey,
|
|
2677
|
+
environment: resolvedEnvironment,
|
|
2678
|
+
routes,
|
|
2679
|
+
facilitatorUrl: config.facilitatorUrl
|
|
2680
|
+
});
|
|
2681
|
+
}
|
|
2682
|
+
};
|
|
2683
|
+
this.ap2 = new AP2Client(this);
|
|
2684
|
+
this.acp = new ACPClient(this);
|
|
2685
|
+
this.ucp = new UCPClient(this);
|
|
2686
|
+
this.capabilities = new CapabilitiesClient(this);
|
|
2687
|
+
this.langchain = new LangChainTools(this);
|
|
2688
|
+
this.cards = new CardsClient(this);
|
|
2689
|
+
this.a2a = new A2AClient(this);
|
|
2690
|
+
this.agentWallets = new AgentWalletsClient(this);
|
|
2691
|
+
this.mpp = new MPPClient(this);
|
|
2692
|
+
}
|
|
2693
|
+
};
|
|
2694
|
+
}
|
|
2695
|
+
});
|
|
2696
|
+
init_src();
|
|
2697
|
+
|
|
2698
|
+
export { ENVIRONMENT_CONFIGS, Sly as PayOS, SlyClient as PayOSClient, Sly, SlyClient, createWithPassword, getEnvironmentConfig, inferEnvironmentFromKey, loginWithPassword, validateEnvironment, verifyApiKey };
|
|
2699
|
+
//# sourceMappingURL=index.mjs.map
|
|
2700
|
+
//# sourceMappingURL=index.mjs.map
|