@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 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 };