@coinbase/agentkit 0.8.1 → 0.9.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 +382 -230
- package/dist/action-providers/cdp/cdpApiActionProvider.d.ts +15 -15
- package/dist/action-providers/cdp/cdpApiActionProvider.js +110 -63
- package/dist/action-providers/cdp/cdpApiActionProvider.test.js +205 -124
- package/dist/action-providers/cdp/index.d.ts +0 -1
- package/dist/action-providers/cdp/index.js +0 -1
- package/dist/action-providers/cdp/schemas.d.ts +9 -70
- package/dist/action-providers/cdp/schemas.js +12 -61
- package/dist/action-providers/cdp-legacy/index.d.ts +3 -0
- package/dist/action-providers/cdp-legacy/index.js +19 -0
- package/dist/action-providers/cdp-legacy/legacyCdpApiActionProvider.d.ts +45 -0
- package/dist/action-providers/cdp-legacy/legacyCdpApiActionProvider.js +130 -0
- package/dist/action-providers/cdp-legacy/legacyCdpApiActionProvider.test.js +146 -0
- package/dist/action-providers/{cdp/cdpWalletActionProvider.d.ts → cdp-legacy/legacyCdpWalletActionProvider.d.ts} +8 -8
- package/dist/action-providers/{cdp/cdpWalletActionProvider.js → cdp-legacy/legacyCdpWalletActionProvider.js} +14 -14
- package/dist/action-providers/{cdp/cdpWalletActionProvider.test.js → cdp-legacy/legacyCdpWalletActionProvider.test.js} +3 -3
- package/dist/action-providers/cdp-legacy/schemas.d.ts +91 -0
- package/dist/action-providers/cdp-legacy/schemas.js +77 -0
- package/dist/action-providers/erc20/erc20ActionProvider.js +1 -1
- package/dist/action-providers/index.d.ts +2 -1
- package/dist/action-providers/index.js +2 -1
- package/dist/action-providers/jupiter/jupiterActionProvider.test.js +2 -4
- package/dist/action-providers/vaultsfyi/api/historicalData.d.ts +31 -0
- package/dist/action-providers/vaultsfyi/api/historicalData.js +44 -0
- package/dist/action-providers/vaultsfyi/api/vaults.d.ts +38 -10
- package/dist/action-providers/vaultsfyi/api/vaults.js +19 -1
- package/dist/action-providers/vaultsfyi/schemas.d.ts +38 -3
- package/dist/action-providers/vaultsfyi/schemas.js +35 -3
- package/dist/action-providers/vaultsfyi/utils.d.ts +64 -0
- package/dist/action-providers/vaultsfyi/utils.js +53 -0
- package/dist/action-providers/vaultsfyi/vaultsfyiActionProvider.d.ts +18 -2
- package/dist/action-providers/vaultsfyi/vaultsfyiActionProvider.js +87 -20
- package/dist/action-providers/vaultsfyi/vaultsfyiActionProvider.test.js +165 -0
- package/dist/action-providers/x402/index.d.ts +1 -0
- package/dist/action-providers/{cdp-v2 → x402}/index.js +1 -2
- package/dist/action-providers/x402/schemas.d.ts +77 -0
- package/dist/action-providers/x402/schemas.js +79 -0
- package/dist/action-providers/x402/x402ActionProvider.d.ts +55 -0
- package/dist/action-providers/x402/x402ActionProvider.js +288 -0
- package/dist/action-providers/x402/x402ActionProvider.test.js +322 -0
- package/dist/agentkit.d.ts +1 -0
- package/dist/agentkit.js +3 -2
- package/dist/wallet-providers/{cdpV2EvmWalletProvider.d.ts → cdpEvmWalletProvider.d.ts} +16 -7
- package/dist/wallet-providers/{cdpV2EvmWalletProvider.js → cdpEvmWalletProvider.js} +50 -39
- package/dist/wallet-providers/{cdpV2EvmWalletProvider.test.js → cdpEvmWalletProvider.test.js} +7 -7
- package/dist/wallet-providers/{cdpV2Shared.d.ts → cdpShared.d.ts} +15 -4
- package/dist/wallet-providers/cdpSmartWalletProvider.d.ts +115 -0
- package/dist/wallet-providers/cdpSmartWalletProvider.js +263 -0
- package/dist/wallet-providers/cdpSmartWalletProvider.test.js +287 -0
- package/dist/wallet-providers/{cdpV2SolanaWalletProvider.d.ts → cdpSolanaWalletProvider.d.ts} +16 -7
- package/dist/wallet-providers/{cdpV2SolanaWalletProvider.js → cdpSolanaWalletProvider.js} +43 -32
- package/dist/wallet-providers/cdpSolanaWalletProvider.test.d.ts +1 -0
- package/dist/wallet-providers/{cdpV2SolanaWalletProvider.test.js → cdpSolanaWalletProvider.test.js} +7 -7
- package/dist/wallet-providers/index.d.ts +6 -6
- package/dist/wallet-providers/index.js +6 -6
- package/dist/wallet-providers/{smartWalletProvider.d.ts → legacyCdpSmartWalletProvider.d.ts} +3 -3
- package/dist/wallet-providers/{smartWalletProvider.js → legacyCdpSmartWalletProvider.js} +21 -21
- package/dist/wallet-providers/legacyCdpSmartWalletProvider.test.d.ts +1 -0
- package/dist/wallet-providers/{smartWalletProvider.test.js → legacyCdpSmartWalletProvider.test.js} +2 -2
- package/dist/wallet-providers/{cdpWalletProvider.d.ts → legacyCdpWalletProvider.d.ts} +15 -11
- package/dist/wallet-providers/{cdpWalletProvider.js → legacyCdpWalletProvider.js} +72 -70
- package/dist/wallet-providers/legacyCdpWalletProvider.test.d.ts +1 -0
- package/dist/wallet-providers/{cdpWalletProvider.test.js → legacyCdpWalletProvider.test.js} +10 -10
- package/package.json +8 -5
- package/dist/action-providers/cdp-v2/cdpApiV2ActionProvider.d.ts +0 -34
- package/dist/action-providers/cdp-v2/cdpApiV2ActionProvider.js +0 -98
- package/dist/action-providers/cdp-v2/index.d.ts +0 -2
- package/dist/action-providers/cdp-v2/schemas.d.ts +0 -11
- package/dist/action-providers/cdp-v2/schemas.js +0 -13
- package/dist/wallet-providers/cdpV2WalletProvider.d.ts +0 -35
- package/dist/wallet-providers/cdpV2WalletProvider.js +0 -42
- /package/dist/action-providers/{cdp → cdp-legacy}/constants.d.ts +0 -0
- /package/dist/action-providers/{cdp → cdp-legacy}/constants.js +0 -0
- /package/dist/action-providers/{cdp/cdpWalletActionProvider.test.d.ts → cdp-legacy/legacyCdpApiActionProvider.test.d.ts} +0 -0
- /package/dist/{wallet-providers/cdpV2EvmWalletProvider.test.d.ts → action-providers/cdp-legacy/legacyCdpWalletActionProvider.test.d.ts} +0 -0
- /package/dist/{wallet-providers/cdpV2SolanaWalletProvider.test.d.ts → action-providers/x402/x402ActionProvider.test.d.ts} +0 -0
- /package/dist/wallet-providers/{cdpWalletProvider.test.d.ts → cdpEvmWalletProvider.test.d.ts} +0 -0
- /package/dist/wallet-providers/{cdpV2Shared.js → cdpShared.js} +0 -0
- /package/dist/wallet-providers/{smartWalletProvider.test.d.ts → cdpSmartWalletProvider.test.d.ts} +0 -0
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { ActionProvider } from "../actionProvider";
|
|
3
|
+
import { Network } from "../../network";
|
|
4
|
+
import { HttpRequestSchema, RetryWithX402Schema, DirectX402RequestSchema } from "./schemas";
|
|
5
|
+
import { EvmWalletProvider } from "../../wallet-providers";
|
|
6
|
+
/**
|
|
7
|
+
* X402ActionProvider provides actions for making HTTP requests, with optional x402 payment handling.
|
|
8
|
+
*/
|
|
9
|
+
export declare class X402ActionProvider extends ActionProvider<EvmWalletProvider> {
|
|
10
|
+
/**
|
|
11
|
+
* Creates a new instance of X402ActionProvider.
|
|
12
|
+
* Initializes the provider with x402 capabilities.
|
|
13
|
+
*/
|
|
14
|
+
constructor();
|
|
15
|
+
/**
|
|
16
|
+
* Makes a basic HTTP request to an API endpoint.
|
|
17
|
+
*
|
|
18
|
+
* @param walletProvider - The wallet provider to use for potential payments
|
|
19
|
+
* @param args - The request parameters including URL, method, headers, and body
|
|
20
|
+
* @returns A JSON string containing the response or error details
|
|
21
|
+
*/
|
|
22
|
+
makeHttpRequest(walletProvider: EvmWalletProvider, args: z.infer<typeof HttpRequestSchema>): Promise<string>;
|
|
23
|
+
/**
|
|
24
|
+
* Retries a request with x402 payment after receiving a 402 response.
|
|
25
|
+
*
|
|
26
|
+
* @param walletProvider - The wallet provider to use for making the payment
|
|
27
|
+
* @param args - The request parameters including URL, method, headers, body, and payment option
|
|
28
|
+
* @returns A JSON string containing the response with payment details or error information
|
|
29
|
+
*/
|
|
30
|
+
retryWithX402(walletProvider: EvmWalletProvider, args: z.infer<typeof RetryWithX402Schema>): Promise<string>;
|
|
31
|
+
/**
|
|
32
|
+
* Makes an HTTP request with automatic x402 payment handling.
|
|
33
|
+
*
|
|
34
|
+
* @param walletProvider - The wallet provider to use for automatic payments
|
|
35
|
+
* @param args - The request parameters including URL, method, headers, and body
|
|
36
|
+
* @returns A JSON string containing the response with optional payment details or error information
|
|
37
|
+
*/
|
|
38
|
+
makeHttpRequestWithX402(walletProvider: EvmWalletProvider, args: z.infer<typeof DirectX402RequestSchema>): Promise<string>;
|
|
39
|
+
/**
|
|
40
|
+
* Checks if the action provider supports the given network.
|
|
41
|
+
*
|
|
42
|
+
* @param network - The network to check support for
|
|
43
|
+
* @returns True if the network is supported, false otherwise
|
|
44
|
+
*/
|
|
45
|
+
supportsNetwork: (network: Network) => boolean;
|
|
46
|
+
/**
|
|
47
|
+
* Helper method to handle HTTP errors consistently.
|
|
48
|
+
*
|
|
49
|
+
* @param error - The axios error to handle
|
|
50
|
+
* @param url - The URL that was being accessed when the error occurred
|
|
51
|
+
* @returns A JSON string containing formatted error details
|
|
52
|
+
*/
|
|
53
|
+
private handleHttpError;
|
|
54
|
+
}
|
|
55
|
+
export declare const x402ActionProvider: () => X402ActionProvider;
|
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.x402ActionProvider = exports.X402ActionProvider = void 0;
|
|
16
|
+
const zod_1 = require("zod");
|
|
17
|
+
const actionProvider_1 = require("../actionProvider");
|
|
18
|
+
const actionDecorator_1 = require("../actionDecorator");
|
|
19
|
+
const schemas_1 = require("./schemas");
|
|
20
|
+
const wallet_providers_1 = require("../../wallet-providers");
|
|
21
|
+
const axios_1 = __importDefault(require("axios"));
|
|
22
|
+
const x402_axios_1 = require("x402-axios");
|
|
23
|
+
const SUPPORTED_NETWORKS = ["base-mainnet", "base-sepolia"];
|
|
24
|
+
/**
|
|
25
|
+
* X402ActionProvider provides actions for making HTTP requests, with optional x402 payment handling.
|
|
26
|
+
*/
|
|
27
|
+
class X402ActionProvider extends actionProvider_1.ActionProvider {
|
|
28
|
+
/**
|
|
29
|
+
* Creates a new instance of X402ActionProvider.
|
|
30
|
+
* Initializes the provider with x402 capabilities.
|
|
31
|
+
*/
|
|
32
|
+
constructor() {
|
|
33
|
+
super("x402", []);
|
|
34
|
+
/**
|
|
35
|
+
* Checks if the action provider supports the given network.
|
|
36
|
+
*
|
|
37
|
+
* @param network - The network to check support for
|
|
38
|
+
* @returns True if the network is supported, false otherwise
|
|
39
|
+
*/
|
|
40
|
+
this.supportsNetwork = (network) => network.protocolFamily === "evm" && SUPPORTED_NETWORKS.includes(network.networkId);
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Makes a basic HTTP request to an API endpoint.
|
|
44
|
+
*
|
|
45
|
+
* @param walletProvider - The wallet provider to use for potential payments
|
|
46
|
+
* @param args - The request parameters including URL, method, headers, and body
|
|
47
|
+
* @returns A JSON string containing the response or error details
|
|
48
|
+
*/
|
|
49
|
+
async makeHttpRequest(walletProvider, args) {
|
|
50
|
+
try {
|
|
51
|
+
const response = await axios_1.default.request({
|
|
52
|
+
url: args.url,
|
|
53
|
+
method: args.method ?? "GET",
|
|
54
|
+
headers: args.headers ?? undefined,
|
|
55
|
+
data: args.body,
|
|
56
|
+
validateStatus: status => status === 402 || (status >= 200 && status < 300),
|
|
57
|
+
});
|
|
58
|
+
if (response.status !== 402) {
|
|
59
|
+
return JSON.stringify({
|
|
60
|
+
success: true,
|
|
61
|
+
url: args.url,
|
|
62
|
+
method: args.method,
|
|
63
|
+
status: response.status,
|
|
64
|
+
data: response.data,
|
|
65
|
+
}, null, 2);
|
|
66
|
+
}
|
|
67
|
+
return JSON.stringify({
|
|
68
|
+
status: "error_402_payment_required",
|
|
69
|
+
acceptablePaymentOptions: response.data.accepts,
|
|
70
|
+
nextSteps: [
|
|
71
|
+
"Inform the user that the requested server replied with a 402 Payment Required response.",
|
|
72
|
+
`The payment options are: ${response.data.accepts.map(option => `${option.asset} ${option.maxAmountRequired} ${option.network}`).join(", ")}`,
|
|
73
|
+
"Ask the user if they want to retry the request with payment.",
|
|
74
|
+
`Use retry_http_request_with_x402 to retry the request with payment.`,
|
|
75
|
+
],
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
catch (error) {
|
|
79
|
+
return this.handleHttpError(error, args.url);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Retries a request with x402 payment after receiving a 402 response.
|
|
84
|
+
*
|
|
85
|
+
* @param walletProvider - The wallet provider to use for making the payment
|
|
86
|
+
* @param args - The request parameters including URL, method, headers, body, and payment option
|
|
87
|
+
* @returns A JSON string containing the response with payment details or error information
|
|
88
|
+
*/
|
|
89
|
+
async retryWithX402(walletProvider, args) {
|
|
90
|
+
try {
|
|
91
|
+
// Make the request with payment handling
|
|
92
|
+
const account = walletProvider.toSigner();
|
|
93
|
+
const paymentSelector = (accepts) => {
|
|
94
|
+
const { scheme, network, maxAmountRequired, asset } = args.selectedPaymentOption;
|
|
95
|
+
let paymentRequirements = accepts.find(accept => accept.scheme === scheme &&
|
|
96
|
+
accept.network === network &&
|
|
97
|
+
accept.maxAmountRequired <= maxAmountRequired &&
|
|
98
|
+
accept.asset === asset);
|
|
99
|
+
if (paymentRequirements) {
|
|
100
|
+
return paymentRequirements;
|
|
101
|
+
}
|
|
102
|
+
paymentRequirements = accepts.find(accept => accept.scheme === scheme &&
|
|
103
|
+
accept.network === network &&
|
|
104
|
+
accept.maxAmountRequired <= maxAmountRequired &&
|
|
105
|
+
accept.asset === asset);
|
|
106
|
+
if (paymentRequirements) {
|
|
107
|
+
return paymentRequirements;
|
|
108
|
+
}
|
|
109
|
+
return accepts[0];
|
|
110
|
+
};
|
|
111
|
+
const api = (0, x402_axios_1.withPaymentInterceptor)(axios_1.default.create({}), account, paymentSelector);
|
|
112
|
+
const response = await api.request({
|
|
113
|
+
url: args.url,
|
|
114
|
+
method: args.method ?? "GET",
|
|
115
|
+
headers: args.headers ?? undefined,
|
|
116
|
+
data: args.body,
|
|
117
|
+
});
|
|
118
|
+
// Check for payment proof
|
|
119
|
+
const paymentProof = response.headers["x-payment-response"]
|
|
120
|
+
? (0, x402_axios_1.decodeXPaymentResponse)(response.headers["x-payment-response"])
|
|
121
|
+
: null;
|
|
122
|
+
return JSON.stringify({
|
|
123
|
+
status: "success",
|
|
124
|
+
data: response.data,
|
|
125
|
+
message: "Request completed successfully with payment",
|
|
126
|
+
details: {
|
|
127
|
+
url: args.url,
|
|
128
|
+
method: args.method,
|
|
129
|
+
paymentUsed: {
|
|
130
|
+
network: args.selectedPaymentOption.network,
|
|
131
|
+
asset: args.selectedPaymentOption.asset,
|
|
132
|
+
amount: args.selectedPaymentOption.maxAmountRequired,
|
|
133
|
+
},
|
|
134
|
+
paymentProof: paymentProof
|
|
135
|
+
? {
|
|
136
|
+
transaction: paymentProof.transaction,
|
|
137
|
+
network: paymentProof.network,
|
|
138
|
+
payer: paymentProof.payer,
|
|
139
|
+
}
|
|
140
|
+
: null,
|
|
141
|
+
},
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
catch (error) {
|
|
145
|
+
return this.handleHttpError(error, args.url);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Makes an HTTP request with automatic x402 payment handling.
|
|
150
|
+
*
|
|
151
|
+
* @param walletProvider - The wallet provider to use for automatic payments
|
|
152
|
+
* @param args - The request parameters including URL, method, headers, and body
|
|
153
|
+
* @returns A JSON string containing the response with optional payment details or error information
|
|
154
|
+
*/
|
|
155
|
+
async makeHttpRequestWithX402(walletProvider, args) {
|
|
156
|
+
try {
|
|
157
|
+
const account = walletProvider.toSigner();
|
|
158
|
+
const api = (0, x402_axios_1.withPaymentInterceptor)(axios_1.default.create({}), account);
|
|
159
|
+
const response = await api.request({
|
|
160
|
+
url: args.url,
|
|
161
|
+
method: args.method ?? "GET",
|
|
162
|
+
headers: args.headers ?? undefined,
|
|
163
|
+
data: args.body,
|
|
164
|
+
});
|
|
165
|
+
// Check for payment proof
|
|
166
|
+
const paymentProof = response.headers["x-payment-response"]
|
|
167
|
+
? (0, x402_axios_1.decodeXPaymentResponse)(response.headers["x-payment-response"])
|
|
168
|
+
: null;
|
|
169
|
+
return JSON.stringify({
|
|
170
|
+
success: true,
|
|
171
|
+
message: "Request completed successfully (payment handled automatically if required)",
|
|
172
|
+
url: args.url,
|
|
173
|
+
method: args.method,
|
|
174
|
+
status: response.status,
|
|
175
|
+
data: response.data,
|
|
176
|
+
paymentProof: paymentProof
|
|
177
|
+
? {
|
|
178
|
+
transaction: paymentProof.transaction,
|
|
179
|
+
network: paymentProof.network,
|
|
180
|
+
payer: paymentProof.payer,
|
|
181
|
+
}
|
|
182
|
+
: null,
|
|
183
|
+
}, null, 2);
|
|
184
|
+
}
|
|
185
|
+
catch (error) {
|
|
186
|
+
return this.handleHttpError(error, args.url);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Helper method to handle HTTP errors consistently.
|
|
191
|
+
*
|
|
192
|
+
* @param error - The axios error to handle
|
|
193
|
+
* @param url - The URL that was being accessed when the error occurred
|
|
194
|
+
* @returns A JSON string containing formatted error details
|
|
195
|
+
*/
|
|
196
|
+
handleHttpError(error, url) {
|
|
197
|
+
if (error.response) {
|
|
198
|
+
return JSON.stringify({
|
|
199
|
+
error: true,
|
|
200
|
+
message: `HTTP ${error.response.status} error when accessing ${url}`,
|
|
201
|
+
details: error.response.data?.error || error.response.statusText,
|
|
202
|
+
suggestion: "Check if the URL is correct and the API is available.",
|
|
203
|
+
}, null, 2);
|
|
204
|
+
}
|
|
205
|
+
if (error.request) {
|
|
206
|
+
return JSON.stringify({
|
|
207
|
+
error: true,
|
|
208
|
+
message: `Network error when accessing ${url}`,
|
|
209
|
+
details: error.message,
|
|
210
|
+
suggestion: "Check your internet connection and verify the API endpoint is accessible.",
|
|
211
|
+
}, null, 2);
|
|
212
|
+
}
|
|
213
|
+
return JSON.stringify({
|
|
214
|
+
error: true,
|
|
215
|
+
message: `Error making request to ${url}`,
|
|
216
|
+
details: error.message,
|
|
217
|
+
suggestion: "Please check the request parameters and try again.",
|
|
218
|
+
}, null, 2);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
exports.X402ActionProvider = X402ActionProvider;
|
|
222
|
+
__decorate([
|
|
223
|
+
(0, actionDecorator_1.CreateAction)({
|
|
224
|
+
name: "make_http_request",
|
|
225
|
+
description: `
|
|
226
|
+
Makes a basic HTTP request to an API endpoint. If the endpoint requires payment (returns 402),
|
|
227
|
+
it will return payment details that can be used with retry_http_request_with_x402.
|
|
228
|
+
|
|
229
|
+
EXAMPLES:
|
|
230
|
+
- Production API: make_http_request("https://api.example.com/weather")
|
|
231
|
+
- Local development: make_http_request("http://localhost:3000/api/data")
|
|
232
|
+
- Testing x402: make_http_request("http://localhost:3000/protected")
|
|
233
|
+
|
|
234
|
+
If you receive a 402 Payment Required response, use retry_http_request_with_x402 to handle the payment.`,
|
|
235
|
+
schema: schemas_1.HttpRequestSchema,
|
|
236
|
+
}),
|
|
237
|
+
__metadata("design:type", Function),
|
|
238
|
+
__metadata("design:paramtypes", [wallet_providers_1.EvmWalletProvider, void 0]),
|
|
239
|
+
__metadata("design:returntype", Promise)
|
|
240
|
+
], X402ActionProvider.prototype, "makeHttpRequest", null);
|
|
241
|
+
__decorate([
|
|
242
|
+
(0, actionDecorator_1.CreateAction)({
|
|
243
|
+
name: "retry_http_request_with_x402",
|
|
244
|
+
description: `
|
|
245
|
+
Retries an HTTP request with x402 payment after receiving a 402 Payment Required response.
|
|
246
|
+
This should be used after make_http_request returns a 402 response.
|
|
247
|
+
|
|
248
|
+
EXAMPLE WORKFLOW:
|
|
249
|
+
1. First call make_http_request("http://localhost:3000/protected")
|
|
250
|
+
2. If you get a 402 response, use this action to retry with payment
|
|
251
|
+
3. Pass the entire original response to this action
|
|
252
|
+
|
|
253
|
+
DO NOT use this action directly without first trying make_http_request!`,
|
|
254
|
+
schema: schemas_1.RetryWithX402Schema,
|
|
255
|
+
}),
|
|
256
|
+
__metadata("design:type", Function),
|
|
257
|
+
__metadata("design:paramtypes", [wallet_providers_1.EvmWalletProvider, void 0]),
|
|
258
|
+
__metadata("design:returntype", Promise)
|
|
259
|
+
], X402ActionProvider.prototype, "retryWithX402", null);
|
|
260
|
+
__decorate([
|
|
261
|
+
(0, actionDecorator_1.CreateAction)({
|
|
262
|
+
name: "make_http_request_with_x402",
|
|
263
|
+
description: `
|
|
264
|
+
⚠️ WARNING: This action automatically handles payments without asking for confirmation!
|
|
265
|
+
Only use this when explicitly told to skip the confirmation flow.
|
|
266
|
+
|
|
267
|
+
For most cases, you should:
|
|
268
|
+
1. First try make_http_request
|
|
269
|
+
2. Then use retry_http_request_with_x402 if payment is required
|
|
270
|
+
|
|
271
|
+
This action combines both steps into one, which means:
|
|
272
|
+
- No chance to review payment details before paying
|
|
273
|
+
- No confirmation step
|
|
274
|
+
- Automatic payment processing
|
|
275
|
+
|
|
276
|
+
EXAMPLES:
|
|
277
|
+
- Production: make_http_request_with_x402("https://api.example.com/data")
|
|
278
|
+
- Local dev: make_http_request_with_x402("http://localhost:3000/protected")
|
|
279
|
+
|
|
280
|
+
Unless specifically instructed otherwise, prefer the two-step approach with make_http_request first.`,
|
|
281
|
+
schema: schemas_1.DirectX402RequestSchema,
|
|
282
|
+
}),
|
|
283
|
+
__metadata("design:type", Function),
|
|
284
|
+
__metadata("design:paramtypes", [wallet_providers_1.EvmWalletProvider, void 0]),
|
|
285
|
+
__metadata("design:returntype", Promise)
|
|
286
|
+
], X402ActionProvider.prototype, "makeHttpRequestWithX402", null);
|
|
287
|
+
const x402ActionProvider = () => new X402ActionProvider();
|
|
288
|
+
exports.x402ActionProvider = x402ActionProvider;
|
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
const x402ActionProvider_1 = require("./x402ActionProvider");
|
|
40
|
+
const axios_1 = __importDefault(require("axios"));
|
|
41
|
+
const x402axios = __importStar(require("x402-axios"));
|
|
42
|
+
// Mock modules
|
|
43
|
+
jest.mock("axios");
|
|
44
|
+
jest.mock("x402-axios");
|
|
45
|
+
// Create mock functions
|
|
46
|
+
const mockRequest = jest.fn();
|
|
47
|
+
// Create a complete mock axios instance
|
|
48
|
+
const mockAxiosInstance = {
|
|
49
|
+
request: mockRequest,
|
|
50
|
+
get: jest.fn(),
|
|
51
|
+
delete: jest.fn(),
|
|
52
|
+
head: jest.fn(),
|
|
53
|
+
options: jest.fn(),
|
|
54
|
+
post: jest.fn(),
|
|
55
|
+
put: jest.fn(),
|
|
56
|
+
patch: jest.fn(),
|
|
57
|
+
getUri: jest.fn(),
|
|
58
|
+
defaults: {},
|
|
59
|
+
interceptors: {
|
|
60
|
+
request: { use: jest.fn(), eject: jest.fn(), clear: jest.fn() },
|
|
61
|
+
response: { use: jest.fn(), eject: jest.fn(), clear: jest.fn() },
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
// Create a complete mock axios static
|
|
65
|
+
const mockAxios = {
|
|
66
|
+
create: jest.fn().mockReturnValue(mockAxiosInstance),
|
|
67
|
+
request: mockRequest,
|
|
68
|
+
get: jest.fn(),
|
|
69
|
+
delete: jest.fn(),
|
|
70
|
+
head: jest.fn(),
|
|
71
|
+
options: jest.fn(),
|
|
72
|
+
post: jest.fn(),
|
|
73
|
+
put: jest.fn(),
|
|
74
|
+
patch: jest.fn(),
|
|
75
|
+
all: jest.fn(),
|
|
76
|
+
spread: jest.fn(),
|
|
77
|
+
isAxiosError: jest.fn(),
|
|
78
|
+
isCancel: jest.fn(),
|
|
79
|
+
CancelToken: {
|
|
80
|
+
source: jest.fn(),
|
|
81
|
+
},
|
|
82
|
+
VERSION: "1.x",
|
|
83
|
+
};
|
|
84
|
+
const mockWithPaymentInterceptor = jest.fn().mockReturnValue(mockAxiosInstance);
|
|
85
|
+
const mockDecodeXPaymentResponse = jest.fn();
|
|
86
|
+
// Override the mocked modules
|
|
87
|
+
axios_1.default.create = mockAxios.create;
|
|
88
|
+
axios_1.default.request = mockRequest;
|
|
89
|
+
axios_1.default.isAxiosError = mockAxios.isAxiosError;
|
|
90
|
+
// Mock x402-axios functions
|
|
91
|
+
jest.mocked(x402axios.withPaymentInterceptor).mockImplementation(mockWithPaymentInterceptor);
|
|
92
|
+
jest.mocked(x402axios.decodeXPaymentResponse).mockImplementation(mockDecodeXPaymentResponse);
|
|
93
|
+
// Mock wallet provider
|
|
94
|
+
const mockWalletProvider = {
|
|
95
|
+
toSigner: jest.fn().mockReturnValue("mock-signer"),
|
|
96
|
+
};
|
|
97
|
+
// Sample responses based on real examples
|
|
98
|
+
const MOCK_PAYMENT_INFO_RESPONSE = {
|
|
99
|
+
paymentRequired: true,
|
|
100
|
+
url: "https://www.x402.org/protected",
|
|
101
|
+
status: 402,
|
|
102
|
+
data: {
|
|
103
|
+
x402Version: 1,
|
|
104
|
+
error: "X-PAYMENT header is required",
|
|
105
|
+
accepts: [
|
|
106
|
+
{
|
|
107
|
+
scheme: "exact",
|
|
108
|
+
network: "base-sepolia",
|
|
109
|
+
maxAmountRequired: "10000",
|
|
110
|
+
resource: "https://www.x402.org/protected",
|
|
111
|
+
description: "Access to protected content",
|
|
112
|
+
mimeType: "application/json",
|
|
113
|
+
payTo: "0x209693Bc6afc0C5328bA36FaF03C514EF312287C",
|
|
114
|
+
maxTimeoutSeconds: 300,
|
|
115
|
+
asset: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
|
|
116
|
+
extra: {
|
|
117
|
+
name: "USDC",
|
|
118
|
+
version: "2",
|
|
119
|
+
},
|
|
120
|
+
},
|
|
121
|
+
],
|
|
122
|
+
},
|
|
123
|
+
};
|
|
124
|
+
const MOCK_PAYMENT_RESPONSE = {
|
|
125
|
+
success: true,
|
|
126
|
+
transaction: "0xcbc385789d3744b52af5106c32809534f64adcbe097e050ec03d6b53fed5d305",
|
|
127
|
+
network: "base-sepolia",
|
|
128
|
+
payer: "0xa8c1a5D3C372C65c04f91f87a43F549619A9483f",
|
|
129
|
+
};
|
|
130
|
+
describe("X402ActionProvider", () => {
|
|
131
|
+
let provider;
|
|
132
|
+
beforeEach(() => {
|
|
133
|
+
provider = new x402ActionProvider_1.X402ActionProvider();
|
|
134
|
+
jest.clearAllMocks();
|
|
135
|
+
// Setup mocks
|
|
136
|
+
mockAxios.create.mockReturnValue(mockAxiosInstance);
|
|
137
|
+
mockWithPaymentInterceptor.mockReturnValue(mockAxiosInstance);
|
|
138
|
+
// Setup axios.isAxiosError mock
|
|
139
|
+
jest
|
|
140
|
+
.mocked(axios_1.default.isAxiosError)
|
|
141
|
+
.mockImplementation((error) => Boolean(error &&
|
|
142
|
+
typeof error === "object" &&
|
|
143
|
+
("isAxiosError" in error || "response" in error || "request" in error)));
|
|
144
|
+
});
|
|
145
|
+
afterEach(() => {
|
|
146
|
+
jest.clearAllMocks();
|
|
147
|
+
});
|
|
148
|
+
describe("supportsNetwork", () => {
|
|
149
|
+
it("should support base-mainnet", () => {
|
|
150
|
+
const network = { protocolFamily: "evm", networkId: "base-mainnet" };
|
|
151
|
+
expect(provider.supportsNetwork(network)).toBe(true);
|
|
152
|
+
});
|
|
153
|
+
it("should support base-sepolia", () => {
|
|
154
|
+
const network = { protocolFamily: "evm", networkId: "base-sepolia" };
|
|
155
|
+
expect(provider.supportsNetwork(network)).toBe(true);
|
|
156
|
+
});
|
|
157
|
+
it("should not support unsupported EVM networks", () => {
|
|
158
|
+
const network = { protocolFamily: "evm", networkId: "ethereum" };
|
|
159
|
+
expect(provider.supportsNetwork(network)).toBe(false);
|
|
160
|
+
});
|
|
161
|
+
it("should not support non-EVM networks", () => {
|
|
162
|
+
const network = { protocolFamily: "solana", networkId: "mainnet" };
|
|
163
|
+
expect(provider.supportsNetwork(network)).toBe(false);
|
|
164
|
+
});
|
|
165
|
+
});
|
|
166
|
+
describe("makeHttpRequest", () => {
|
|
167
|
+
it("should handle successful non-payment requests", async () => {
|
|
168
|
+
mockRequest.mockResolvedValue({
|
|
169
|
+
status: 200,
|
|
170
|
+
data: { message: "Success" },
|
|
171
|
+
headers: {},
|
|
172
|
+
config: {},
|
|
173
|
+
});
|
|
174
|
+
const result = await provider.makeHttpRequest(mockWalletProvider, {
|
|
175
|
+
url: "https://api.example.com/free",
|
|
176
|
+
method: "GET",
|
|
177
|
+
});
|
|
178
|
+
const parsedResult = JSON.parse(result);
|
|
179
|
+
expect(parsedResult.success).toBe(true);
|
|
180
|
+
expect(parsedResult.status).toBe(200);
|
|
181
|
+
expect(parsedResult.data).toEqual({ message: "Success" });
|
|
182
|
+
});
|
|
183
|
+
it("should handle 402 responses with payment options", async () => {
|
|
184
|
+
mockRequest.mockResolvedValue({
|
|
185
|
+
status: 402,
|
|
186
|
+
data: MOCK_PAYMENT_INFO_RESPONSE.data,
|
|
187
|
+
headers: {},
|
|
188
|
+
config: {},
|
|
189
|
+
});
|
|
190
|
+
const result = await provider.makeHttpRequest(mockWalletProvider, {
|
|
191
|
+
url: "https://www.x402.org/protected",
|
|
192
|
+
method: "GET",
|
|
193
|
+
});
|
|
194
|
+
const parsedResult = JSON.parse(result);
|
|
195
|
+
expect(parsedResult.status).toBe("error_402_payment_required");
|
|
196
|
+
expect(parsedResult.acceptablePaymentOptions).toEqual(MOCK_PAYMENT_INFO_RESPONSE.data.accepts);
|
|
197
|
+
expect(parsedResult.nextSteps).toBeDefined();
|
|
198
|
+
});
|
|
199
|
+
it("should handle network errors", async () => {
|
|
200
|
+
const error = new Error("Network error");
|
|
201
|
+
error.isAxiosError = true;
|
|
202
|
+
error.request = {};
|
|
203
|
+
mockRequest.mockRejectedValue(error);
|
|
204
|
+
const result = await provider.makeHttpRequest(mockWalletProvider, {
|
|
205
|
+
url: "https://api.example.com/endpoint",
|
|
206
|
+
method: "GET",
|
|
207
|
+
});
|
|
208
|
+
const parsedResult = JSON.parse(result);
|
|
209
|
+
expect(parsedResult.error).toBe(true);
|
|
210
|
+
expect(parsedResult.message).toContain("Network error");
|
|
211
|
+
});
|
|
212
|
+
});
|
|
213
|
+
describe("retryHttpRequestWithX402", () => {
|
|
214
|
+
it("should successfully retry with payment", async () => {
|
|
215
|
+
mockDecodeXPaymentResponse.mockReturnValue(MOCK_PAYMENT_RESPONSE);
|
|
216
|
+
mockRequest.mockResolvedValue({
|
|
217
|
+
status: 200,
|
|
218
|
+
statusText: "OK",
|
|
219
|
+
data: { message: "Paid content" },
|
|
220
|
+
headers: {
|
|
221
|
+
"x-payment-response": "encoded-payment-data",
|
|
222
|
+
},
|
|
223
|
+
config: {},
|
|
224
|
+
});
|
|
225
|
+
const result = await provider.retryWithX402(mockWalletProvider, {
|
|
226
|
+
url: "https://www.x402.org/protected",
|
|
227
|
+
method: "GET",
|
|
228
|
+
selectedPaymentOption: {
|
|
229
|
+
scheme: "exact",
|
|
230
|
+
network: "base-sepolia",
|
|
231
|
+
maxAmountRequired: "10000",
|
|
232
|
+
asset: "0x456",
|
|
233
|
+
},
|
|
234
|
+
});
|
|
235
|
+
// Update expectation to accept the payment selector function
|
|
236
|
+
expect(mockWithPaymentInterceptor).toHaveBeenCalledWith(mockAxiosInstance, "mock-signer", expect.any(Function));
|
|
237
|
+
const parsedResult = JSON.parse(result);
|
|
238
|
+
expect(parsedResult.status).toBe("success");
|
|
239
|
+
expect(parsedResult.details.paymentProof).toEqual({
|
|
240
|
+
transaction: MOCK_PAYMENT_RESPONSE.transaction,
|
|
241
|
+
network: MOCK_PAYMENT_RESPONSE.network,
|
|
242
|
+
payer: MOCK_PAYMENT_RESPONSE.payer,
|
|
243
|
+
});
|
|
244
|
+
});
|
|
245
|
+
it("should handle network errors during payment", async () => {
|
|
246
|
+
const error = new Error("Network error");
|
|
247
|
+
error.isAxiosError = true;
|
|
248
|
+
error.request = {};
|
|
249
|
+
mockRequest.mockRejectedValue(error);
|
|
250
|
+
const result = await provider.retryWithX402(mockWalletProvider, {
|
|
251
|
+
url: "https://www.x402.org/protected",
|
|
252
|
+
method: "GET",
|
|
253
|
+
selectedPaymentOption: {
|
|
254
|
+
scheme: "exact",
|
|
255
|
+
network: "base-sepolia",
|
|
256
|
+
maxAmountRequired: "10000",
|
|
257
|
+
asset: "0x456",
|
|
258
|
+
},
|
|
259
|
+
});
|
|
260
|
+
const parsedResult = JSON.parse(result);
|
|
261
|
+
expect(parsedResult.error).toBe(true);
|
|
262
|
+
expect(parsedResult.message).toContain("Network error");
|
|
263
|
+
});
|
|
264
|
+
});
|
|
265
|
+
describe("makeHttpRequestWithX402", () => {
|
|
266
|
+
it("should handle successful direct payment requests", async () => {
|
|
267
|
+
mockDecodeXPaymentResponse.mockReturnValue(MOCK_PAYMENT_RESPONSE);
|
|
268
|
+
mockRequest.mockResolvedValue({
|
|
269
|
+
status: 200,
|
|
270
|
+
statusText: "OK",
|
|
271
|
+
data: { message: "Paid content" },
|
|
272
|
+
headers: {
|
|
273
|
+
"x-payment-response": "encoded-payment-data",
|
|
274
|
+
},
|
|
275
|
+
config: {},
|
|
276
|
+
});
|
|
277
|
+
const result = await provider.makeHttpRequestWithX402(mockWalletProvider, {
|
|
278
|
+
url: "https://www.x402.org/protected",
|
|
279
|
+
method: "GET",
|
|
280
|
+
});
|
|
281
|
+
expect(mockWithPaymentInterceptor).toHaveBeenCalledWith(mockAxiosInstance, "mock-signer");
|
|
282
|
+
const parsedResult = JSON.parse(result);
|
|
283
|
+
expect(parsedResult.success).toBe(true);
|
|
284
|
+
expect(parsedResult.data).toEqual({ message: "Paid content" });
|
|
285
|
+
expect(parsedResult.paymentProof).toEqual({
|
|
286
|
+
transaction: MOCK_PAYMENT_RESPONSE.transaction,
|
|
287
|
+
network: MOCK_PAYMENT_RESPONSE.network,
|
|
288
|
+
payer: MOCK_PAYMENT_RESPONSE.payer,
|
|
289
|
+
});
|
|
290
|
+
});
|
|
291
|
+
it("should handle successful non-payment requests", async () => {
|
|
292
|
+
mockRequest.mockResolvedValue({
|
|
293
|
+
status: 200,
|
|
294
|
+
statusText: "OK",
|
|
295
|
+
data: { message: "Free content" },
|
|
296
|
+
headers: {},
|
|
297
|
+
config: {},
|
|
298
|
+
});
|
|
299
|
+
const result = await provider.makeHttpRequestWithX402(mockWalletProvider, {
|
|
300
|
+
url: "https://api.example.com/free",
|
|
301
|
+
method: "GET",
|
|
302
|
+
});
|
|
303
|
+
const parsedResult = JSON.parse(result);
|
|
304
|
+
expect(parsedResult.success).toBe(true);
|
|
305
|
+
expect(parsedResult.data).toEqual({ message: "Free content" });
|
|
306
|
+
expect(parsedResult.paymentProof).toBeNull();
|
|
307
|
+
});
|
|
308
|
+
it("should handle network errors", async () => {
|
|
309
|
+
const error = new Error("Network error");
|
|
310
|
+
error.isAxiosError = true;
|
|
311
|
+
error.request = {};
|
|
312
|
+
mockRequest.mockRejectedValue(error);
|
|
313
|
+
const result = await provider.makeHttpRequestWithX402(mockWalletProvider, {
|
|
314
|
+
url: "https://api.example.com/endpoint",
|
|
315
|
+
method: "GET",
|
|
316
|
+
});
|
|
317
|
+
const parsedResult = JSON.parse(result);
|
|
318
|
+
expect(parsedResult.error).toBe(true);
|
|
319
|
+
expect(parsedResult.message).toContain("Network error");
|
|
320
|
+
});
|
|
321
|
+
});
|
|
322
|
+
});
|
package/dist/agentkit.d.ts
CHANGED