@t402/a2a 2.4.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 +182 -0
- package/dist/cjs/client.cjs +147 -0
- package/dist/cjs/client.d.cts +102 -0
- package/dist/cjs/index.cjs +388 -0
- package/dist/cjs/index.d.cts +4 -0
- package/dist/cjs/server.cjs +239 -0
- package/dist/cjs/server.d.cts +177 -0
- package/dist/esm/chunk-6TJQKXTN.mjs +219 -0
- package/dist/esm/chunk-IPWV3JOP.mjs +127 -0
- package/dist/esm/client.d.ts +102 -0
- package/dist/esm/client.mjs +6 -0
- package/dist/esm/index.d.ts +4 -0
- package/dist/esm/index.mjs +38 -0
- package/dist/esm/server.d.ts +177 -0
- package/dist/esm/server.mjs +6 -0
- package/package.json +86 -0
|
@@ -0,0 +1,388 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
A2APaymentClient: () => A2APaymentClient,
|
|
24
|
+
A2APaymentServer: () => A2APaymentServer,
|
|
25
|
+
A2A_EXTENSIONS_HEADER: () => import_types3.A2A_EXTENSIONS_HEADER,
|
|
26
|
+
T402_A2A_EXTENSION_URI: () => import_types3.T402_A2A_EXTENSION_URI,
|
|
27
|
+
createPaymentCompletedMessage: () => import_types3.createPaymentCompletedMessage,
|
|
28
|
+
createPaymentFailedMessage: () => import_types3.createPaymentFailedMessage,
|
|
29
|
+
createPaymentRequiredMessage: () => import_types3.createPaymentRequiredMessage,
|
|
30
|
+
createPaymentSubmissionMessage: () => import_types3.createPaymentSubmissionMessage,
|
|
31
|
+
createT402Extension: () => import_types3.createT402Extension,
|
|
32
|
+
getPaymentReceipts: () => import_types3.getPaymentReceipts,
|
|
33
|
+
getPaymentRequired: () => import_types3.getPaymentRequired,
|
|
34
|
+
isPaymentCompleted: () => import_types3.isPaymentCompleted,
|
|
35
|
+
isPaymentFailed: () => import_types3.isPaymentFailed,
|
|
36
|
+
isPaymentRequired: () => import_types3.isPaymentRequired
|
|
37
|
+
});
|
|
38
|
+
module.exports = __toCommonJS(index_exports);
|
|
39
|
+
var import_types3 = require("@t402/core/types");
|
|
40
|
+
|
|
41
|
+
// src/client.ts
|
|
42
|
+
var import_types = require("@t402/core/types");
|
|
43
|
+
var A2APaymentClient = class {
|
|
44
|
+
options;
|
|
45
|
+
constructor(options = {}) {
|
|
46
|
+
this.options = options;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Check if a task requires payment
|
|
50
|
+
*/
|
|
51
|
+
requiresPayment(task) {
|
|
52
|
+
const requires = (0, import_types.isPaymentRequired)(task);
|
|
53
|
+
if (requires) {
|
|
54
|
+
const requirements = (0, import_types.getPaymentRequired)(task);
|
|
55
|
+
if (requirements && this.options.onPaymentRequired) {
|
|
56
|
+
this.options.onPaymentRequired(requirements);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return requires;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Get payment requirements from a task
|
|
63
|
+
*/
|
|
64
|
+
getRequirements(task) {
|
|
65
|
+
return (0, import_types.getPaymentRequired)(task);
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Select the best payment option from requirements
|
|
69
|
+
*
|
|
70
|
+
* @param requirements - Payment requirements with accepts array
|
|
71
|
+
* @param preferredNetwork - Preferred network (CAIP-2 format)
|
|
72
|
+
* @param preferredScheme - Preferred scheme (e.g., 'exact', 'upto')
|
|
73
|
+
* @returns The best matching payment option or undefined
|
|
74
|
+
*/
|
|
75
|
+
selectPaymentOption(requirements, preferredNetwork, preferredScheme) {
|
|
76
|
+
const accepts = requirements.accepts;
|
|
77
|
+
if (!accepts || accepts.length === 0) {
|
|
78
|
+
return void 0;
|
|
79
|
+
}
|
|
80
|
+
if (preferredNetwork && preferredScheme) {
|
|
81
|
+
const exact = accepts.find(
|
|
82
|
+
(a) => a.network === preferredNetwork && a.scheme === preferredScheme
|
|
83
|
+
);
|
|
84
|
+
if (exact) return exact;
|
|
85
|
+
}
|
|
86
|
+
if (preferredNetwork) {
|
|
87
|
+
const byNetwork = accepts.find((a) => a.network === preferredNetwork);
|
|
88
|
+
if (byNetwork) return byNetwork;
|
|
89
|
+
}
|
|
90
|
+
if (preferredScheme) {
|
|
91
|
+
const byScheme = accepts.find((a) => a.scheme === preferredScheme);
|
|
92
|
+
if (byScheme) return byScheme;
|
|
93
|
+
}
|
|
94
|
+
return accepts[0];
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Create a payment payload using a mechanism client
|
|
98
|
+
*
|
|
99
|
+
* @param mechanism - The scheme/network client to use
|
|
100
|
+
* @param requirements - Payment requirements to fulfill
|
|
101
|
+
* @returns Promise resolving to the payment payload
|
|
102
|
+
*/
|
|
103
|
+
async createPayload(mechanism, requirements) {
|
|
104
|
+
const selected = this.selectPaymentOption(requirements);
|
|
105
|
+
if (!selected) {
|
|
106
|
+
throw new Error("No payment options available");
|
|
107
|
+
}
|
|
108
|
+
const basePayload = await mechanism.createPaymentPayload(
|
|
109
|
+
requirements.t402Version,
|
|
110
|
+
selected
|
|
111
|
+
);
|
|
112
|
+
const payload = {
|
|
113
|
+
...basePayload,
|
|
114
|
+
resource: requirements.resource,
|
|
115
|
+
accepted: selected
|
|
116
|
+
};
|
|
117
|
+
if (this.options.onPaymentSubmitted) {
|
|
118
|
+
this.options.onPaymentSubmitted(payload);
|
|
119
|
+
}
|
|
120
|
+
return payload;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Create a payment submission message
|
|
124
|
+
*
|
|
125
|
+
* @param payload - The payment payload to submit
|
|
126
|
+
* @param text - Optional text message
|
|
127
|
+
* @returns A2A message with payment metadata
|
|
128
|
+
*/
|
|
129
|
+
createPaymentMessage(payload, text = "Here is the payment authorization.") {
|
|
130
|
+
return (0, import_types.createPaymentSubmissionMessage)(payload, text);
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Handle a complete payment flow for a task
|
|
134
|
+
*
|
|
135
|
+
* This is a convenience method that checks for payment requirements,
|
|
136
|
+
* creates a payload, and returns a payment message.
|
|
137
|
+
*
|
|
138
|
+
* @param task - The A2A task that may require payment
|
|
139
|
+
* @param mechanism - The mechanism client to use for signing
|
|
140
|
+
* @param preferredNetwork - Optional preferred network
|
|
141
|
+
* @param preferredScheme - Optional preferred scheme
|
|
142
|
+
* @returns A2A message with payment, or undefined if no payment needed
|
|
143
|
+
*/
|
|
144
|
+
async handlePayment(task, mechanism, preferredNetwork, preferredScheme) {
|
|
145
|
+
if (!this.requiresPayment(task)) {
|
|
146
|
+
return void 0;
|
|
147
|
+
}
|
|
148
|
+
const requirements = this.getRequirements(task);
|
|
149
|
+
if (!requirements) {
|
|
150
|
+
return void 0;
|
|
151
|
+
}
|
|
152
|
+
const selected = this.selectPaymentOption(requirements, preferredNetwork, preferredScheme);
|
|
153
|
+
if (!selected) {
|
|
154
|
+
throw new Error("No compatible payment option found");
|
|
155
|
+
}
|
|
156
|
+
const payload = await this.createPayload(mechanism, requirements);
|
|
157
|
+
return this.createPaymentMessage(payload);
|
|
158
|
+
}
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
// src/server.ts
|
|
162
|
+
var import_types2 = require("@t402/core/types");
|
|
163
|
+
var A2APaymentServer = class {
|
|
164
|
+
options;
|
|
165
|
+
constructor(options = {}) {
|
|
166
|
+
this.options = options;
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Create payment requirements with defaults
|
|
170
|
+
*
|
|
171
|
+
* @param requirements - Partial requirements to merge with defaults
|
|
172
|
+
* @returns Complete payment requirements
|
|
173
|
+
*/
|
|
174
|
+
createRequirements(requirements) {
|
|
175
|
+
return {
|
|
176
|
+
t402Version: 2,
|
|
177
|
+
...this.options.defaultRequirements,
|
|
178
|
+
...requirements
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Create a payment-required task status
|
|
183
|
+
*
|
|
184
|
+
* @param requirements - Payment requirements
|
|
185
|
+
* @param text - Optional text message
|
|
186
|
+
* @returns A2A task status
|
|
187
|
+
*/
|
|
188
|
+
createPaymentRequiredStatus(requirements, text) {
|
|
189
|
+
return {
|
|
190
|
+
state: "input-required",
|
|
191
|
+
message: (0, import_types2.createPaymentRequiredMessage)(requirements, text),
|
|
192
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Create a payment-required task
|
|
197
|
+
*
|
|
198
|
+
* @param taskId - Task identifier
|
|
199
|
+
* @param requirements - Payment requirements
|
|
200
|
+
* @param text - Optional text message
|
|
201
|
+
* @returns A2A task in input-required state
|
|
202
|
+
*/
|
|
203
|
+
createPaymentRequiredTask(taskId, requirements, text) {
|
|
204
|
+
return {
|
|
205
|
+
kind: "task",
|
|
206
|
+
id: taskId,
|
|
207
|
+
status: this.createPaymentRequiredStatus(requirements, text)
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Extract payment payload from an A2A message
|
|
212
|
+
*
|
|
213
|
+
* @param message - A2A message that may contain payment
|
|
214
|
+
* @returns Payment payload or undefined
|
|
215
|
+
*/
|
|
216
|
+
extractPaymentPayload(message) {
|
|
217
|
+
return message.metadata?.["t402.payment.payload"];
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Check if a message contains a payment submission
|
|
221
|
+
*
|
|
222
|
+
* @param message - A2A message to check
|
|
223
|
+
* @returns Whether the message contains a payment
|
|
224
|
+
*/
|
|
225
|
+
hasPaymentPayload(message) {
|
|
226
|
+
return message.metadata?.["t402.payment.status"] === "payment-submitted" && message.metadata?.["t402.payment.payload"] !== void 0;
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Process a payment submission
|
|
230
|
+
*
|
|
231
|
+
* @param message - A2A message containing payment payload
|
|
232
|
+
* @param requirements - Original payment requirements
|
|
233
|
+
* @returns Payment processing result
|
|
234
|
+
*/
|
|
235
|
+
async processPayment(message, requirements) {
|
|
236
|
+
const payload = this.extractPaymentPayload(message);
|
|
237
|
+
if (!payload) {
|
|
238
|
+
const error = "No payment payload in message";
|
|
239
|
+
this.options.onPaymentFailed?.(error);
|
|
240
|
+
return {
|
|
241
|
+
success: false,
|
|
242
|
+
error,
|
|
243
|
+
message: (0, import_types2.createPaymentFailedMessage)([], "T402-1001", error)
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
this.options.onPaymentReceived?.(payload);
|
|
247
|
+
if (this.options.paymentHandler) {
|
|
248
|
+
return this.options.paymentHandler(payload, requirements);
|
|
249
|
+
}
|
|
250
|
+
if (!this.options.facilitator) {
|
|
251
|
+
const error = "No facilitator or payment handler configured";
|
|
252
|
+
this.options.onPaymentFailed?.(error, payload);
|
|
253
|
+
return {
|
|
254
|
+
success: false,
|
|
255
|
+
error,
|
|
256
|
+
message: (0, import_types2.createPaymentFailedMessage)([], "T402-5001", error)
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
try {
|
|
260
|
+
const paymentRequirements = payload.accepted;
|
|
261
|
+
const verifyResponse = await this.options.facilitator.verify(
|
|
262
|
+
payload,
|
|
263
|
+
paymentRequirements
|
|
264
|
+
);
|
|
265
|
+
if (!verifyResponse.isValid) {
|
|
266
|
+
const error = verifyResponse.invalidReason || "Payment verification failed";
|
|
267
|
+
this.options.onPaymentFailed?.(error, payload);
|
|
268
|
+
return {
|
|
269
|
+
success: false,
|
|
270
|
+
error,
|
|
271
|
+
message: (0, import_types2.createPaymentFailedMessage)([], "T402-2001", error)
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
this.options.onPaymentVerified?.(payload);
|
|
275
|
+
const settleResponse = await this.options.facilitator.settle(
|
|
276
|
+
payload,
|
|
277
|
+
paymentRequirements
|
|
278
|
+
);
|
|
279
|
+
const receipts = [settleResponse];
|
|
280
|
+
if (!settleResponse.success) {
|
|
281
|
+
const error = settleResponse.errorReason || "Payment settlement failed";
|
|
282
|
+
this.options.onPaymentFailed?.(error, payload);
|
|
283
|
+
return {
|
|
284
|
+
success: false,
|
|
285
|
+
receipts,
|
|
286
|
+
error,
|
|
287
|
+
message: (0, import_types2.createPaymentFailedMessage)(receipts, "T402-3001", error)
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
this.options.onPaymentSettled?.(receipts);
|
|
291
|
+
return {
|
|
292
|
+
success: true,
|
|
293
|
+
receipts,
|
|
294
|
+
message: (0, import_types2.createPaymentCompletedMessage)(receipts)
|
|
295
|
+
};
|
|
296
|
+
} catch (err) {
|
|
297
|
+
const error = err instanceof Error ? err.message : "Payment processing error";
|
|
298
|
+
this.options.onPaymentFailed?.(error, payload);
|
|
299
|
+
return {
|
|
300
|
+
success: false,
|
|
301
|
+
error,
|
|
302
|
+
message: (0, import_types2.createPaymentFailedMessage)([], "T402-5002", error)
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* Create a completed task status with payment receipts
|
|
308
|
+
*
|
|
309
|
+
* @param receipts - Settlement receipts
|
|
310
|
+
* @param text - Optional text message
|
|
311
|
+
* @returns A2A task status
|
|
312
|
+
*/
|
|
313
|
+
createPaymentCompletedStatus(receipts, text) {
|
|
314
|
+
return {
|
|
315
|
+
state: "completed",
|
|
316
|
+
message: (0, import_types2.createPaymentCompletedMessage)(receipts, text),
|
|
317
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
321
|
+
* Create a failed task status with payment error
|
|
322
|
+
*
|
|
323
|
+
* @param error - Error message
|
|
324
|
+
* @param receipts - Optional settlement receipts
|
|
325
|
+
* @param errorCode - Optional error code
|
|
326
|
+
* @returns A2A task status
|
|
327
|
+
*/
|
|
328
|
+
createPaymentFailedStatus(error, receipts = [], errorCode = "T402-5000") {
|
|
329
|
+
return {
|
|
330
|
+
state: "failed",
|
|
331
|
+
message: (0, import_types2.createPaymentFailedMessage)(receipts, errorCode, error),
|
|
332
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* Update a task with payment completion
|
|
337
|
+
*
|
|
338
|
+
* @param task - Original task
|
|
339
|
+
* @param result - Payment processing result
|
|
340
|
+
* @returns Updated task
|
|
341
|
+
*/
|
|
342
|
+
updateTaskWithPaymentResult(task, result) {
|
|
343
|
+
if (result.success) {
|
|
344
|
+
return {
|
|
345
|
+
...task,
|
|
346
|
+
status: this.createPaymentCompletedStatus(result.receipts || []),
|
|
347
|
+
history: [...task.history || [], result.message]
|
|
348
|
+
};
|
|
349
|
+
}
|
|
350
|
+
return {
|
|
351
|
+
...task,
|
|
352
|
+
status: this.createPaymentFailedStatus(result.error || "Payment failed", result.receipts),
|
|
353
|
+
history: [...task.history || [], result.message]
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
/**
|
|
357
|
+
* Handle a complete payment flow for a task
|
|
358
|
+
*
|
|
359
|
+
* This is a convenience method that processes a payment submission
|
|
360
|
+
* and returns an updated task.
|
|
361
|
+
*
|
|
362
|
+
* @param task - The current A2A task
|
|
363
|
+
* @param message - The message containing payment payload
|
|
364
|
+
* @param requirements - Payment requirements
|
|
365
|
+
* @returns Updated task with payment result
|
|
366
|
+
*/
|
|
367
|
+
async handlePayment(task, message, requirements) {
|
|
368
|
+
const result = await this.processPayment(message, requirements);
|
|
369
|
+
return this.updateTaskWithPaymentResult(task, result);
|
|
370
|
+
}
|
|
371
|
+
};
|
|
372
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
373
|
+
0 && (module.exports = {
|
|
374
|
+
A2APaymentClient,
|
|
375
|
+
A2APaymentServer,
|
|
376
|
+
A2A_EXTENSIONS_HEADER,
|
|
377
|
+
T402_A2A_EXTENSION_URI,
|
|
378
|
+
createPaymentCompletedMessage,
|
|
379
|
+
createPaymentFailedMessage,
|
|
380
|
+
createPaymentRequiredMessage,
|
|
381
|
+
createPaymentSubmissionMessage,
|
|
382
|
+
createT402Extension,
|
|
383
|
+
getPaymentReceipts,
|
|
384
|
+
getPaymentRequired,
|
|
385
|
+
isPaymentCompleted,
|
|
386
|
+
isPaymentFailed,
|
|
387
|
+
isPaymentRequired
|
|
388
|
+
});
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { A2AAgentCard, A2AArtifact, A2ACapabilities, A2ADataPart, A2AError, A2AExtension, A2AFilePart, A2AMessage, A2AMessagePart, A2APaymentMetadata, A2APaymentStatus, A2ARequest, A2AResponse, A2ASkill, A2ATask, A2ATaskState, A2ATaskStatus, A2ATextPart, A2A_EXTENSIONS_HEADER, T402_A2A_EXTENSION_URI, createPaymentCompletedMessage, createPaymentFailedMessage, createPaymentRequiredMessage, createPaymentSubmissionMessage, createT402Extension, getPaymentReceipts, getPaymentRequired, isPaymentCompleted, isPaymentFailed, isPaymentRequired } from '@t402/core/types';
|
|
2
|
+
export { A2APaymentClient, A2APaymentClientOptions } from './client.cjs';
|
|
3
|
+
export { A2APaymentHandler, A2APaymentResult, A2APaymentServer, A2APaymentServerOptions } from './server.cjs';
|
|
4
|
+
import '@t402/core/server';
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/server.ts
|
|
21
|
+
var server_exports = {};
|
|
22
|
+
__export(server_exports, {
|
|
23
|
+
A2APaymentServer: () => A2APaymentServer
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(server_exports);
|
|
26
|
+
var import_types = require("@t402/core/types");
|
|
27
|
+
var A2APaymentServer = class {
|
|
28
|
+
options;
|
|
29
|
+
constructor(options = {}) {
|
|
30
|
+
this.options = options;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Create payment requirements with defaults
|
|
34
|
+
*
|
|
35
|
+
* @param requirements - Partial requirements to merge with defaults
|
|
36
|
+
* @returns Complete payment requirements
|
|
37
|
+
*/
|
|
38
|
+
createRequirements(requirements) {
|
|
39
|
+
return {
|
|
40
|
+
t402Version: 2,
|
|
41
|
+
...this.options.defaultRequirements,
|
|
42
|
+
...requirements
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Create a payment-required task status
|
|
47
|
+
*
|
|
48
|
+
* @param requirements - Payment requirements
|
|
49
|
+
* @param text - Optional text message
|
|
50
|
+
* @returns A2A task status
|
|
51
|
+
*/
|
|
52
|
+
createPaymentRequiredStatus(requirements, text) {
|
|
53
|
+
return {
|
|
54
|
+
state: "input-required",
|
|
55
|
+
message: (0, import_types.createPaymentRequiredMessage)(requirements, text),
|
|
56
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Create a payment-required task
|
|
61
|
+
*
|
|
62
|
+
* @param taskId - Task identifier
|
|
63
|
+
* @param requirements - Payment requirements
|
|
64
|
+
* @param text - Optional text message
|
|
65
|
+
* @returns A2A task in input-required state
|
|
66
|
+
*/
|
|
67
|
+
createPaymentRequiredTask(taskId, requirements, text) {
|
|
68
|
+
return {
|
|
69
|
+
kind: "task",
|
|
70
|
+
id: taskId,
|
|
71
|
+
status: this.createPaymentRequiredStatus(requirements, text)
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Extract payment payload from an A2A message
|
|
76
|
+
*
|
|
77
|
+
* @param message - A2A message that may contain payment
|
|
78
|
+
* @returns Payment payload or undefined
|
|
79
|
+
*/
|
|
80
|
+
extractPaymentPayload(message) {
|
|
81
|
+
return message.metadata?.["t402.payment.payload"];
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Check if a message contains a payment submission
|
|
85
|
+
*
|
|
86
|
+
* @param message - A2A message to check
|
|
87
|
+
* @returns Whether the message contains a payment
|
|
88
|
+
*/
|
|
89
|
+
hasPaymentPayload(message) {
|
|
90
|
+
return message.metadata?.["t402.payment.status"] === "payment-submitted" && message.metadata?.["t402.payment.payload"] !== void 0;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Process a payment submission
|
|
94
|
+
*
|
|
95
|
+
* @param message - A2A message containing payment payload
|
|
96
|
+
* @param requirements - Original payment requirements
|
|
97
|
+
* @returns Payment processing result
|
|
98
|
+
*/
|
|
99
|
+
async processPayment(message, requirements) {
|
|
100
|
+
const payload = this.extractPaymentPayload(message);
|
|
101
|
+
if (!payload) {
|
|
102
|
+
const error = "No payment payload in message";
|
|
103
|
+
this.options.onPaymentFailed?.(error);
|
|
104
|
+
return {
|
|
105
|
+
success: false,
|
|
106
|
+
error,
|
|
107
|
+
message: (0, import_types.createPaymentFailedMessage)([], "T402-1001", error)
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
this.options.onPaymentReceived?.(payload);
|
|
111
|
+
if (this.options.paymentHandler) {
|
|
112
|
+
return this.options.paymentHandler(payload, requirements);
|
|
113
|
+
}
|
|
114
|
+
if (!this.options.facilitator) {
|
|
115
|
+
const error = "No facilitator or payment handler configured";
|
|
116
|
+
this.options.onPaymentFailed?.(error, payload);
|
|
117
|
+
return {
|
|
118
|
+
success: false,
|
|
119
|
+
error,
|
|
120
|
+
message: (0, import_types.createPaymentFailedMessage)([], "T402-5001", error)
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
try {
|
|
124
|
+
const paymentRequirements = payload.accepted;
|
|
125
|
+
const verifyResponse = await this.options.facilitator.verify(
|
|
126
|
+
payload,
|
|
127
|
+
paymentRequirements
|
|
128
|
+
);
|
|
129
|
+
if (!verifyResponse.isValid) {
|
|
130
|
+
const error = verifyResponse.invalidReason || "Payment verification failed";
|
|
131
|
+
this.options.onPaymentFailed?.(error, payload);
|
|
132
|
+
return {
|
|
133
|
+
success: false,
|
|
134
|
+
error,
|
|
135
|
+
message: (0, import_types.createPaymentFailedMessage)([], "T402-2001", error)
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
this.options.onPaymentVerified?.(payload);
|
|
139
|
+
const settleResponse = await this.options.facilitator.settle(
|
|
140
|
+
payload,
|
|
141
|
+
paymentRequirements
|
|
142
|
+
);
|
|
143
|
+
const receipts = [settleResponse];
|
|
144
|
+
if (!settleResponse.success) {
|
|
145
|
+
const error = settleResponse.errorReason || "Payment settlement failed";
|
|
146
|
+
this.options.onPaymentFailed?.(error, payload);
|
|
147
|
+
return {
|
|
148
|
+
success: false,
|
|
149
|
+
receipts,
|
|
150
|
+
error,
|
|
151
|
+
message: (0, import_types.createPaymentFailedMessage)(receipts, "T402-3001", error)
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
this.options.onPaymentSettled?.(receipts);
|
|
155
|
+
return {
|
|
156
|
+
success: true,
|
|
157
|
+
receipts,
|
|
158
|
+
message: (0, import_types.createPaymentCompletedMessage)(receipts)
|
|
159
|
+
};
|
|
160
|
+
} catch (err) {
|
|
161
|
+
const error = err instanceof Error ? err.message : "Payment processing error";
|
|
162
|
+
this.options.onPaymentFailed?.(error, payload);
|
|
163
|
+
return {
|
|
164
|
+
success: false,
|
|
165
|
+
error,
|
|
166
|
+
message: (0, import_types.createPaymentFailedMessage)([], "T402-5002", error)
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Create a completed task status with payment receipts
|
|
172
|
+
*
|
|
173
|
+
* @param receipts - Settlement receipts
|
|
174
|
+
* @param text - Optional text message
|
|
175
|
+
* @returns A2A task status
|
|
176
|
+
*/
|
|
177
|
+
createPaymentCompletedStatus(receipts, text) {
|
|
178
|
+
return {
|
|
179
|
+
state: "completed",
|
|
180
|
+
message: (0, import_types.createPaymentCompletedMessage)(receipts, text),
|
|
181
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Create a failed task status with payment error
|
|
186
|
+
*
|
|
187
|
+
* @param error - Error message
|
|
188
|
+
* @param receipts - Optional settlement receipts
|
|
189
|
+
* @param errorCode - Optional error code
|
|
190
|
+
* @returns A2A task status
|
|
191
|
+
*/
|
|
192
|
+
createPaymentFailedStatus(error, receipts = [], errorCode = "T402-5000") {
|
|
193
|
+
return {
|
|
194
|
+
state: "failed",
|
|
195
|
+
message: (0, import_types.createPaymentFailedMessage)(receipts, errorCode, error),
|
|
196
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Update a task with payment completion
|
|
201
|
+
*
|
|
202
|
+
* @param task - Original task
|
|
203
|
+
* @param result - Payment processing result
|
|
204
|
+
* @returns Updated task
|
|
205
|
+
*/
|
|
206
|
+
updateTaskWithPaymentResult(task, result) {
|
|
207
|
+
if (result.success) {
|
|
208
|
+
return {
|
|
209
|
+
...task,
|
|
210
|
+
status: this.createPaymentCompletedStatus(result.receipts || []),
|
|
211
|
+
history: [...task.history || [], result.message]
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
return {
|
|
215
|
+
...task,
|
|
216
|
+
status: this.createPaymentFailedStatus(result.error || "Payment failed", result.receipts),
|
|
217
|
+
history: [...task.history || [], result.message]
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Handle a complete payment flow for a task
|
|
222
|
+
*
|
|
223
|
+
* This is a convenience method that processes a payment submission
|
|
224
|
+
* and returns an updated task.
|
|
225
|
+
*
|
|
226
|
+
* @param task - The current A2A task
|
|
227
|
+
* @param message - The message containing payment payload
|
|
228
|
+
* @param requirements - Payment requirements
|
|
229
|
+
* @returns Updated task with payment result
|
|
230
|
+
*/
|
|
231
|
+
async handlePayment(task, message, requirements) {
|
|
232
|
+
const result = await this.processPayment(message, requirements);
|
|
233
|
+
return this.updateTaskWithPaymentResult(task, result);
|
|
234
|
+
}
|
|
235
|
+
};
|
|
236
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
237
|
+
0 && (module.exports = {
|
|
238
|
+
A2APaymentServer
|
|
239
|
+
});
|