@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
package/README.md
ADDED
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
# @t402/a2a
|
|
2
|
+
|
|
3
|
+
A2A (Agent-to-Agent) transport implementation for the t402 payment protocol. Enables AI agents to monetize their services through on-chain cryptocurrency payments using the A2A protocol.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @t402/a2a
|
|
9
|
+
# or
|
|
10
|
+
pnpm add @t402/a2a
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Overview
|
|
14
|
+
|
|
15
|
+
This package provides tools for implementing t402 payments over the A2A (Agent-to-Agent) protocol:
|
|
16
|
+
|
|
17
|
+
- **A2APaymentClient**: Client-side payment handling for AI agents requesting services
|
|
18
|
+
- **A2APaymentServer**: Server-side payment processing for AI agents providing services
|
|
19
|
+
- **Type definitions**: Complete TypeScript types for A2A payment flows
|
|
20
|
+
- **Helper functions**: Utilities for creating and parsing payment messages
|
|
21
|
+
|
|
22
|
+
## Usage
|
|
23
|
+
|
|
24
|
+
### Client-Side (Requesting Services)
|
|
25
|
+
|
|
26
|
+
```typescript
|
|
27
|
+
import { A2APaymentClient } from "@t402/a2a";
|
|
28
|
+
import { ExactEVMClient } from "@t402/evm/exact/client";
|
|
29
|
+
|
|
30
|
+
// Create a payment client
|
|
31
|
+
const paymentClient = new A2APaymentClient({
|
|
32
|
+
onPaymentRequired: (requirements) =>
|
|
33
|
+
console.log("Payment required:", requirements),
|
|
34
|
+
onPaymentSubmitted: (payload) =>
|
|
35
|
+
console.log("Payment submitted:", payload),
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
// Create your mechanism client (e.g., EVM)
|
|
39
|
+
const mechanism = new ExactEVMClient({ signer: yourSigner });
|
|
40
|
+
|
|
41
|
+
// Handle payment flow
|
|
42
|
+
async function handleTask(task: A2ATask) {
|
|
43
|
+
// Check if payment is required
|
|
44
|
+
if (paymentClient.requiresPayment(task)) {
|
|
45
|
+
// Get requirements and create payment
|
|
46
|
+
const requirements = paymentClient.getRequirements(task);
|
|
47
|
+
const payload = await paymentClient.createPayload(mechanism, requirements!);
|
|
48
|
+
|
|
49
|
+
// Create message with payment
|
|
50
|
+
const message = paymentClient.createPaymentMessage(payload);
|
|
51
|
+
|
|
52
|
+
// Send message via A2A protocol
|
|
53
|
+
return message;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Or use the convenience method
|
|
58
|
+
const paymentMessage = await paymentClient.handlePayment(task, mechanism);
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Server-Side (Providing Services)
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
import { A2APaymentServer } from "@t402/a2a";
|
|
65
|
+
import { HTTPFacilitatorClient } from "@t402/core/server";
|
|
66
|
+
|
|
67
|
+
// Create a payment server
|
|
68
|
+
const paymentServer = new A2APaymentServer({
|
|
69
|
+
facilitator: new HTTPFacilitatorClient(),
|
|
70
|
+
defaultRequirements: {
|
|
71
|
+
resource: { url: "agent://my-agent/skill" },
|
|
72
|
+
},
|
|
73
|
+
onPaymentReceived: (payload) => console.log("Payment received:", payload),
|
|
74
|
+
onPaymentSettled: (receipts) => console.log("Payment settled:", receipts),
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
// Create payment-required task for a new request
|
|
78
|
+
function createPaymentTask(taskId: string): A2ATask {
|
|
79
|
+
const requirements = paymentServer.createRequirements({
|
|
80
|
+
accepts: [
|
|
81
|
+
{
|
|
82
|
+
scheme: "exact",
|
|
83
|
+
network: "eip155:8453",
|
|
84
|
+
amount: "1000000", // 1 USDC
|
|
85
|
+
asset: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
|
|
86
|
+
payTo: "0xYourAddress",
|
|
87
|
+
maxTimeoutSeconds: 3600,
|
|
88
|
+
extra: {},
|
|
89
|
+
},
|
|
90
|
+
],
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
return paymentServer.createPaymentRequiredTask(taskId, requirements);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Process payment when received
|
|
97
|
+
async function processPayment(
|
|
98
|
+
task: A2ATask,
|
|
99
|
+
message: A2AMessage,
|
|
100
|
+
requirements: PaymentRequired,
|
|
101
|
+
): Promise<A2ATask> {
|
|
102
|
+
const result = await paymentServer.processPayment(message, requirements);
|
|
103
|
+
|
|
104
|
+
if (result.success) {
|
|
105
|
+
// Payment successful, continue with task execution
|
|
106
|
+
return {
|
|
107
|
+
...task,
|
|
108
|
+
status: {
|
|
109
|
+
state: "working",
|
|
110
|
+
message: { kind: "message", role: "agent", parts: [{ kind: "text", text: "Processing..." }] },
|
|
111
|
+
},
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Payment failed
|
|
116
|
+
return paymentServer.updateTaskWithPaymentResult(task, result);
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## API Reference
|
|
121
|
+
|
|
122
|
+
### A2APaymentClient
|
|
123
|
+
|
|
124
|
+
Client for handling payments in A2A client agents.
|
|
125
|
+
|
|
126
|
+
| Method | Description |
|
|
127
|
+
|--------|-------------|
|
|
128
|
+
| `requiresPayment(task)` | Check if a task requires payment |
|
|
129
|
+
| `getRequirements(task)` | Extract payment requirements from a task |
|
|
130
|
+
| `selectPaymentOption(requirements, network?, scheme?)` | Select the best payment option |
|
|
131
|
+
| `createPayload(mechanism, requirements)` | Create a signed payment payload |
|
|
132
|
+
| `createPaymentMessage(payload, text?)` | Create an A2A message with payment |
|
|
133
|
+
| `handlePayment(task, mechanism, network?, scheme?)` | Handle complete payment flow |
|
|
134
|
+
|
|
135
|
+
### A2APaymentServer
|
|
136
|
+
|
|
137
|
+
Server for processing payments in A2A server agents.
|
|
138
|
+
|
|
139
|
+
| Method | Description |
|
|
140
|
+
|--------|-------------|
|
|
141
|
+
| `createRequirements(requirements)` | Create requirements with defaults |
|
|
142
|
+
| `createPaymentRequiredTask(taskId, requirements, text?)` | Create a payment-required task |
|
|
143
|
+
| `extractPaymentPayload(message)` | Extract payment from a message |
|
|
144
|
+
| `hasPaymentPayload(message)` | Check if message contains payment |
|
|
145
|
+
| `processPayment(message, requirements)` | Process a payment submission |
|
|
146
|
+
| `handlePayment(task, message, requirements)` | Handle payment and update task |
|
|
147
|
+
| `updateTaskWithPaymentResult(task, result)` | Update task with payment result |
|
|
148
|
+
|
|
149
|
+
### Re-exported Types
|
|
150
|
+
|
|
151
|
+
All A2A types from `@t402/core/types` are re-exported:
|
|
152
|
+
|
|
153
|
+
- `A2ATask`, `A2AMessage`, `A2ATaskStatus`
|
|
154
|
+
- `A2APaymentStatus`, `A2APaymentMetadata`
|
|
155
|
+
- `A2AAgentCard`, `A2ASkill`, `A2ACapabilities`
|
|
156
|
+
- `isPaymentRequired()`, `isPaymentCompleted()`, `isPaymentFailed()`
|
|
157
|
+
- `createPaymentRequiredMessage()`, `createPaymentSubmissionMessage()`
|
|
158
|
+
- `createPaymentCompletedMessage()`, `createPaymentFailedMessage()`
|
|
159
|
+
- `T402_A2A_EXTENSION_URI`, `A2A_EXTENSIONS_HEADER`
|
|
160
|
+
|
|
161
|
+
## A2A Extension
|
|
162
|
+
|
|
163
|
+
When advertising t402 payment support in your agent card:
|
|
164
|
+
|
|
165
|
+
```typescript
|
|
166
|
+
import { createT402Extension } from "@t402/a2a";
|
|
167
|
+
|
|
168
|
+
const agentCard: A2AAgentCard = {
|
|
169
|
+
name: "My AI Agent",
|
|
170
|
+
url: "https://my-agent.example.com",
|
|
171
|
+
capabilities: {
|
|
172
|
+
extensions: [
|
|
173
|
+
createT402Extension(true), // required = true
|
|
174
|
+
],
|
|
175
|
+
},
|
|
176
|
+
// ...
|
|
177
|
+
};
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
## License
|
|
181
|
+
|
|
182
|
+
Apache-2.0
|
|
@@ -0,0 +1,147 @@
|
|
|
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/client.ts
|
|
21
|
+
var client_exports = {};
|
|
22
|
+
__export(client_exports, {
|
|
23
|
+
A2APaymentClient: () => A2APaymentClient
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(client_exports);
|
|
26
|
+
var import_types = require("@t402/core/types");
|
|
27
|
+
var A2APaymentClient = class {
|
|
28
|
+
options;
|
|
29
|
+
constructor(options = {}) {
|
|
30
|
+
this.options = options;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Check if a task requires payment
|
|
34
|
+
*/
|
|
35
|
+
requiresPayment(task) {
|
|
36
|
+
const requires = (0, import_types.isPaymentRequired)(task);
|
|
37
|
+
if (requires) {
|
|
38
|
+
const requirements = (0, import_types.getPaymentRequired)(task);
|
|
39
|
+
if (requirements && this.options.onPaymentRequired) {
|
|
40
|
+
this.options.onPaymentRequired(requirements);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return requires;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Get payment requirements from a task
|
|
47
|
+
*/
|
|
48
|
+
getRequirements(task) {
|
|
49
|
+
return (0, import_types.getPaymentRequired)(task);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Select the best payment option from requirements
|
|
53
|
+
*
|
|
54
|
+
* @param requirements - Payment requirements with accepts array
|
|
55
|
+
* @param preferredNetwork - Preferred network (CAIP-2 format)
|
|
56
|
+
* @param preferredScheme - Preferred scheme (e.g., 'exact', 'upto')
|
|
57
|
+
* @returns The best matching payment option or undefined
|
|
58
|
+
*/
|
|
59
|
+
selectPaymentOption(requirements, preferredNetwork, preferredScheme) {
|
|
60
|
+
const accepts = requirements.accepts;
|
|
61
|
+
if (!accepts || accepts.length === 0) {
|
|
62
|
+
return void 0;
|
|
63
|
+
}
|
|
64
|
+
if (preferredNetwork && preferredScheme) {
|
|
65
|
+
const exact = accepts.find(
|
|
66
|
+
(a) => a.network === preferredNetwork && a.scheme === preferredScheme
|
|
67
|
+
);
|
|
68
|
+
if (exact) return exact;
|
|
69
|
+
}
|
|
70
|
+
if (preferredNetwork) {
|
|
71
|
+
const byNetwork = accepts.find((a) => a.network === preferredNetwork);
|
|
72
|
+
if (byNetwork) return byNetwork;
|
|
73
|
+
}
|
|
74
|
+
if (preferredScheme) {
|
|
75
|
+
const byScheme = accepts.find((a) => a.scheme === preferredScheme);
|
|
76
|
+
if (byScheme) return byScheme;
|
|
77
|
+
}
|
|
78
|
+
return accepts[0];
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Create a payment payload using a mechanism client
|
|
82
|
+
*
|
|
83
|
+
* @param mechanism - The scheme/network client to use
|
|
84
|
+
* @param requirements - Payment requirements to fulfill
|
|
85
|
+
* @returns Promise resolving to the payment payload
|
|
86
|
+
*/
|
|
87
|
+
async createPayload(mechanism, requirements) {
|
|
88
|
+
const selected = this.selectPaymentOption(requirements);
|
|
89
|
+
if (!selected) {
|
|
90
|
+
throw new Error("No payment options available");
|
|
91
|
+
}
|
|
92
|
+
const basePayload = await mechanism.createPaymentPayload(
|
|
93
|
+
requirements.t402Version,
|
|
94
|
+
selected
|
|
95
|
+
);
|
|
96
|
+
const payload = {
|
|
97
|
+
...basePayload,
|
|
98
|
+
resource: requirements.resource,
|
|
99
|
+
accepted: selected
|
|
100
|
+
};
|
|
101
|
+
if (this.options.onPaymentSubmitted) {
|
|
102
|
+
this.options.onPaymentSubmitted(payload);
|
|
103
|
+
}
|
|
104
|
+
return payload;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Create a payment submission message
|
|
108
|
+
*
|
|
109
|
+
* @param payload - The payment payload to submit
|
|
110
|
+
* @param text - Optional text message
|
|
111
|
+
* @returns A2A message with payment metadata
|
|
112
|
+
*/
|
|
113
|
+
createPaymentMessage(payload, text = "Here is the payment authorization.") {
|
|
114
|
+
return (0, import_types.createPaymentSubmissionMessage)(payload, text);
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Handle a complete payment flow for a task
|
|
118
|
+
*
|
|
119
|
+
* This is a convenience method that checks for payment requirements,
|
|
120
|
+
* creates a payload, and returns a payment message.
|
|
121
|
+
*
|
|
122
|
+
* @param task - The A2A task that may require payment
|
|
123
|
+
* @param mechanism - The mechanism client to use for signing
|
|
124
|
+
* @param preferredNetwork - Optional preferred network
|
|
125
|
+
* @param preferredScheme - Optional preferred scheme
|
|
126
|
+
* @returns A2A message with payment, or undefined if no payment needed
|
|
127
|
+
*/
|
|
128
|
+
async handlePayment(task, mechanism, preferredNetwork, preferredScheme) {
|
|
129
|
+
if (!this.requiresPayment(task)) {
|
|
130
|
+
return void 0;
|
|
131
|
+
}
|
|
132
|
+
const requirements = this.getRequirements(task);
|
|
133
|
+
if (!requirements) {
|
|
134
|
+
return void 0;
|
|
135
|
+
}
|
|
136
|
+
const selected = this.selectPaymentOption(requirements, preferredNetwork, preferredScheme);
|
|
137
|
+
if (!selected) {
|
|
138
|
+
throw new Error("No compatible payment option found");
|
|
139
|
+
}
|
|
140
|
+
const payload = await this.createPayload(mechanism, requirements);
|
|
141
|
+
return this.createPaymentMessage(payload);
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
145
|
+
0 && (module.exports = {
|
|
146
|
+
A2APaymentClient
|
|
147
|
+
});
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { PaymentRequired, PaymentPayload, A2ATask, SchemeNetworkClient, A2AMessage } from '@t402/core/types';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* A2A Payment Client
|
|
5
|
+
*
|
|
6
|
+
* Handles payment flows for A2A client agents, including detecting
|
|
7
|
+
* payment-required states and submitting payment payloads.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Options for A2APaymentClient
|
|
12
|
+
*/
|
|
13
|
+
interface A2APaymentClientOptions {
|
|
14
|
+
/**
|
|
15
|
+
* Optional callback when payment is required
|
|
16
|
+
*/
|
|
17
|
+
onPaymentRequired?: (requirements: PaymentRequired) => void;
|
|
18
|
+
/**
|
|
19
|
+
* Optional callback when payment is submitted
|
|
20
|
+
*/
|
|
21
|
+
onPaymentSubmitted?: (payload: PaymentPayload) => void;
|
|
22
|
+
/**
|
|
23
|
+
* Optional callback when payment is completed
|
|
24
|
+
*/
|
|
25
|
+
onPaymentCompleted?: (task: A2ATask) => void;
|
|
26
|
+
/**
|
|
27
|
+
* Optional callback when payment fails
|
|
28
|
+
*/
|
|
29
|
+
onPaymentFailed?: (error: string, task: A2ATask) => void;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* A2A Payment Client
|
|
33
|
+
*
|
|
34
|
+
* Provides methods for handling t402 payments in A2A client agents.
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```typescript
|
|
38
|
+
* const client = new A2APaymentClient({
|
|
39
|
+
* onPaymentRequired: (req) => console.log('Payment required:', req),
|
|
40
|
+
* });
|
|
41
|
+
*
|
|
42
|
+
* // Check if task requires payment
|
|
43
|
+
* if (client.requiresPayment(task)) {
|
|
44
|
+
* const requirements = client.getRequirements(task);
|
|
45
|
+
* const payload = await mechanism.createPaymentPayload(requirements);
|
|
46
|
+
* const message = client.createPaymentMessage(payload);
|
|
47
|
+
* // Send message via A2A
|
|
48
|
+
* }
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
51
|
+
declare class A2APaymentClient {
|
|
52
|
+
private options;
|
|
53
|
+
constructor(options?: A2APaymentClientOptions);
|
|
54
|
+
/**
|
|
55
|
+
* Check if a task requires payment
|
|
56
|
+
*/
|
|
57
|
+
requiresPayment(task: A2ATask): boolean;
|
|
58
|
+
/**
|
|
59
|
+
* Get payment requirements from a task
|
|
60
|
+
*/
|
|
61
|
+
getRequirements(task: A2ATask): PaymentRequired | undefined;
|
|
62
|
+
/**
|
|
63
|
+
* Select the best payment option from requirements
|
|
64
|
+
*
|
|
65
|
+
* @param requirements - Payment requirements with accepts array
|
|
66
|
+
* @param preferredNetwork - Preferred network (CAIP-2 format)
|
|
67
|
+
* @param preferredScheme - Preferred scheme (e.g., 'exact', 'upto')
|
|
68
|
+
* @returns The best matching payment option or undefined
|
|
69
|
+
*/
|
|
70
|
+
selectPaymentOption(requirements: PaymentRequired, preferredNetwork?: string, preferredScheme?: string): PaymentRequired["accepts"][0] | undefined;
|
|
71
|
+
/**
|
|
72
|
+
* Create a payment payload using a mechanism client
|
|
73
|
+
*
|
|
74
|
+
* @param mechanism - The scheme/network client to use
|
|
75
|
+
* @param requirements - Payment requirements to fulfill
|
|
76
|
+
* @returns Promise resolving to the payment payload
|
|
77
|
+
*/
|
|
78
|
+
createPayload(mechanism: SchemeNetworkClient, requirements: PaymentRequired): Promise<PaymentPayload>;
|
|
79
|
+
/**
|
|
80
|
+
* Create a payment submission message
|
|
81
|
+
*
|
|
82
|
+
* @param payload - The payment payload to submit
|
|
83
|
+
* @param text - Optional text message
|
|
84
|
+
* @returns A2A message with payment metadata
|
|
85
|
+
*/
|
|
86
|
+
createPaymentMessage(payload: PaymentPayload, text?: string): A2AMessage;
|
|
87
|
+
/**
|
|
88
|
+
* Handle a complete payment flow for a task
|
|
89
|
+
*
|
|
90
|
+
* This is a convenience method that checks for payment requirements,
|
|
91
|
+
* creates a payload, and returns a payment message.
|
|
92
|
+
*
|
|
93
|
+
* @param task - The A2A task that may require payment
|
|
94
|
+
* @param mechanism - The mechanism client to use for signing
|
|
95
|
+
* @param preferredNetwork - Optional preferred network
|
|
96
|
+
* @param preferredScheme - Optional preferred scheme
|
|
97
|
+
* @returns A2A message with payment, or undefined if no payment needed
|
|
98
|
+
*/
|
|
99
|
+
handlePayment(task: A2ATask, mechanism: SchemeNetworkClient, preferredNetwork?: string, preferredScheme?: string): Promise<A2AMessage | undefined>;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export { A2APaymentClient, type A2APaymentClientOptions };
|