@coinbase/agentkit 0.10.2 → 0.10.4
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 +89 -10
- package/dist/action-providers/across/acrossActionProvider.js +2 -4
- package/dist/action-providers/across/acrossActionProvider.test.js +10 -5
- package/dist/action-providers/baseAccount/baseAccountActionProvider.js +5 -7
- package/dist/action-providers/cdp/cdpApiActionProvider.js +7 -30
- package/dist/action-providers/cdp/cdpApiActionProvider.test.js +2 -8
- package/dist/action-providers/cdp/faucetUtils.d.ts +38 -0
- package/dist/action-providers/cdp/faucetUtils.js +81 -0
- package/dist/action-providers/clanker/schemas.d.ts +4 -4
- package/dist/action-providers/clanker/utils.d.ts +2 -1
- package/dist/action-providers/clanker/utils.js +2 -2
- package/dist/action-providers/enso/constants.d.ts +4 -0
- package/dist/action-providers/enso/constants.js +10 -0
- package/dist/action-providers/enso/ensoActionProvider.d.ts +34 -0
- package/dist/action-providers/enso/ensoActionProvider.js +125 -0
- package/dist/action-providers/enso/ensoActionProvider.test.d.ts +1 -0
- package/dist/action-providers/enso/ensoActionProvider.test.js +141 -0
- package/dist/action-providers/enso/index.d.ts +1 -0
- package/dist/action-providers/enso/index.js +17 -0
- package/dist/action-providers/enso/schemas.d.ts +23 -0
- package/dist/action-providers/enso/schemas.js +22 -0
- package/dist/action-providers/erc20/constants.d.ts +2 -0
- package/dist/action-providers/erc20/constants.js +2 -0
- package/dist/action-providers/erc20/erc20ActionProvider.d.ts +17 -1
- package/dist/action-providers/erc20/erc20ActionProvider.js +103 -1
- package/dist/action-providers/erc20/erc20ActionProvider.test.js +201 -0
- package/dist/action-providers/erc20/schemas.d.ts +29 -0
- package/dist/action-providers/erc20/schemas.js +34 -1
- package/dist/action-providers/index.d.ts +4 -1
- package/dist/action-providers/index.js +4 -1
- package/dist/action-providers/jupiter/jupiterActionProvider.js +2 -2
- package/dist/action-providers/spl/splActionProvider.js +12 -13
- package/dist/action-providers/superfluid/graphQueries/superfluidGraphQueries.js +2 -2
- package/dist/action-providers/sushi/constants.d.ts +35 -0
- package/dist/action-providers/sushi/constants.js +7 -0
- package/dist/action-providers/sushi/index.d.ts +4 -0
- package/dist/action-providers/sushi/index.js +20 -0
- package/dist/action-providers/sushi/sushiDataActionProvider.d.ts +32 -0
- package/dist/action-providers/sushi/sushiDataActionProvider.js +113 -0
- package/dist/action-providers/sushi/sushiDataSchemas.d.ts +11 -0
- package/dist/action-providers/sushi/sushiDataSchemas.js +16 -0
- package/dist/action-providers/sushi/sushiRouterActionProvider.d.ts +40 -0
- package/dist/action-providers/sushi/sushiRouterActionProvider.js +386 -0
- package/dist/action-providers/sushi/sushiRouterActionProvider.test.d.ts +1 -0
- package/dist/action-providers/sushi/sushiRouterActionProvider.test.js +392 -0
- package/dist/action-providers/sushi/sushiRouterSchemas.d.ts +36 -0
- package/dist/action-providers/sushi/sushiRouterSchemas.js +55 -0
- package/dist/action-providers/vaultsfyi/constants.d.ts +8 -12
- package/dist/action-providers/vaultsfyi/constants.js +47 -13
- package/dist/action-providers/vaultsfyi/schemas.d.ts +120 -65
- package/dist/action-providers/vaultsfyi/schemas.js +72 -38
- package/dist/action-providers/vaultsfyi/sdk.d.ts +8 -0
- package/dist/action-providers/vaultsfyi/sdk.js +15 -0
- package/dist/action-providers/vaultsfyi/utils.d.ts +151 -55
- package/dist/action-providers/vaultsfyi/utils.js +29 -75
- package/dist/action-providers/vaultsfyi/vaultsfyiActionProvider.d.ts +55 -16
- package/dist/action-providers/vaultsfyi/vaultsfyiActionProvider.js +413 -217
- package/dist/action-providers/vaultsfyi/vaultsfyiActionProvider.test.js +509 -316
- package/dist/action-providers/wallet/walletActionProvider.js +1 -1
- package/dist/action-providers/weth/constants.d.ts +0 -1
- package/dist/action-providers/weth/constants.js +1 -2
- package/dist/action-providers/weth/schemas.js +6 -2
- package/dist/action-providers/weth/wethActionProvider.d.ts +7 -0
- package/dist/action-providers/weth/wethActionProvider.js +57 -32
- package/dist/action-providers/weth/wethActionProvider.test.js +60 -11
- package/dist/action-providers/x402/constants.d.ts +67 -0
- package/dist/action-providers/x402/constants.js +37 -0
- package/dist/action-providers/x402/schemas.d.ts +45 -5
- package/dist/action-providers/x402/schemas.js +81 -11
- package/dist/action-providers/x402/utils.d.ts +89 -14
- package/dist/action-providers/x402/utils.js +335 -31
- package/dist/action-providers/x402/x402ActionProvider.d.ts +21 -7
- package/dist/action-providers/x402/x402ActionProvider.js +250 -184
- package/dist/action-providers/x402/x402ActionProvider.test.js +240 -236
- package/dist/action-providers/yelay/constants.d.ts +64 -0
- package/dist/action-providers/yelay/constants.js +137 -0
- package/dist/action-providers/yelay/index.d.ts +2 -0
- package/dist/action-providers/yelay/index.js +18 -0
- package/dist/action-providers/yelay/schemas.d.ts +47 -0
- package/dist/action-providers/yelay/schemas.js +59 -0
- package/dist/action-providers/yelay/types.d.ts +24 -0
- package/dist/action-providers/yelay/yelayActionProvider.d.ts +70 -0
- package/dist/action-providers/yelay/yelayActionProvider.js +329 -0
- package/dist/action-providers/yelay/yelayActionProvider.test.d.ts +1 -0
- package/dist/action-providers/yelay/yelayActionProvider.test.js +302 -0
- package/dist/action-providers/zora/zoraActionProvider.js +4 -5
- package/dist/wallet-providers/cdpSmartWalletProvider.js +1 -3
- package/dist/wallet-providers/cdpSolanaWalletProvider.d.ts +14 -0
- package/dist/wallet-providers/cdpSolanaWalletProvider.js +39 -3
- package/dist/wallet-providers/cdpSolanaWalletProvider.test.js +16 -0
- package/dist/wallet-providers/privySvmWalletProvider.d.ts +14 -0
- package/dist/wallet-providers/privySvmWalletProvider.js +17 -0
- package/dist/wallet-providers/privySvmWalletProvider.test.js +10 -0
- package/dist/wallet-providers/solanaKeypairWalletProvider.d.ts +14 -0
- package/dist/wallet-providers/solanaKeypairWalletProvider.js +17 -0
- package/dist/wallet-providers/svmWalletProvider.d.ts +34 -0
- package/dist/wallet-providers/svmWalletProvider.js +43 -0
- package/dist/wallet-providers/svmWalletProvider.test.js +10 -0
- package/package.json +11 -6
- package/dist/action-providers/vaultsfyi/api/actions.d.ts +0 -41
- package/dist/action-providers/vaultsfyi/api/actions.js +0 -28
- package/dist/action-providers/vaultsfyi/api/historicalData.d.ts +0 -31
- package/dist/action-providers/vaultsfyi/api/historicalData.js +0 -44
- package/dist/action-providers/vaultsfyi/api/types.d.ts +0 -34
- package/dist/action-providers/vaultsfyi/api/vaults.d.ts +0 -66
- package/dist/action-providers/vaultsfyi/api/vaults.js +0 -57
- /package/dist/action-providers/{vaultsfyi/api → yelay}/types.js +0 -0
|
@@ -8,9 +8,6 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
8
8
|
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
9
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
10
|
};
|
|
11
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
-
};
|
|
14
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
12
|
exports.x402ActionProvider = exports.X402ActionProvider = void 0;
|
|
16
13
|
const zod_1 = require("zod");
|
|
@@ -18,12 +15,11 @@ const actionProvider_1 = require("../actionProvider");
|
|
|
18
15
|
const actionDecorator_1 = require("../actionDecorator");
|
|
19
16
|
const schemas_1 = require("./schemas");
|
|
20
17
|
const wallet_providers_1 = require("../../wallet-providers");
|
|
21
|
-
const
|
|
22
|
-
const
|
|
23
|
-
const
|
|
24
|
-
const x402_1 = require("@coinbase/x402");
|
|
18
|
+
const fetch_1 = require("@x402/fetch");
|
|
19
|
+
const client_1 = require("@x402/evm/exact/client");
|
|
20
|
+
const client_2 = require("@x402/svm/exact/client");
|
|
25
21
|
const utils_1 = require("./utils");
|
|
26
|
-
const
|
|
22
|
+
const constants_1 = require("./constants");
|
|
27
23
|
/**
|
|
28
24
|
* X402ActionProvider provides actions for making HTTP requests, with optional x402 payment handling.
|
|
29
25
|
*/
|
|
@@ -40,107 +36,50 @@ class X402ActionProvider extends actionProvider_1.ActionProvider {
|
|
|
40
36
|
* @param network - The network to check support for
|
|
41
37
|
* @returns True if the network is supported, false otherwise
|
|
42
38
|
*/
|
|
43
|
-
this.supportsNetwork = (network) =>
|
|
39
|
+
this.supportsNetwork = (network) => constants_1.SUPPORTED_NETWORKS.includes(network.networkId);
|
|
44
40
|
}
|
|
45
41
|
/**
|
|
46
42
|
* Discovers available x402 services with optional filtering.
|
|
47
43
|
*
|
|
48
44
|
* @param walletProvider - The wallet provider to use for network filtering
|
|
49
|
-
* @param args - Optional filters: maxUsdcPrice
|
|
45
|
+
* @param args - Optional filters: discoveryUrl, maxUsdcPrice
|
|
50
46
|
* @returns JSON string with the list of services (filtered by network and description)
|
|
51
47
|
*/
|
|
52
48
|
async discoverX402Services(walletProvider, args) {
|
|
53
49
|
try {
|
|
54
|
-
|
|
55
|
-
const
|
|
56
|
-
|
|
50
|
+
console.log("args", args);
|
|
51
|
+
const facilitatorUrl = (0, schemas_1.resolveFacilitatorUrl)(args.facilitator);
|
|
52
|
+
const discoveryUrl = facilitatorUrl + "/discovery/resources";
|
|
53
|
+
// Fetch all resources with pagination
|
|
54
|
+
const allResources = await (0, utils_1.fetchAllDiscoveryResources)(discoveryUrl);
|
|
55
|
+
if (allResources.length === 0) {
|
|
57
56
|
return JSON.stringify({
|
|
58
57
|
error: true,
|
|
59
58
|
message: "No services found",
|
|
60
59
|
});
|
|
61
60
|
}
|
|
62
|
-
// Get the
|
|
63
|
-
const
|
|
64
|
-
//
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
const hasMatchingNetwork = accepts.some(req => req.network === walletNetwork);
|
|
72
|
-
// Filter out services with empty or default descriptions
|
|
73
|
-
const hasDescription = accepts.some(req => req.description &&
|
|
74
|
-
req.description.trim() !== "" &&
|
|
75
|
-
req.description.trim() !== "Access to protected content");
|
|
76
|
-
return hasMatchingNetwork && hasDescription;
|
|
77
|
-
});
|
|
78
|
-
// Apply USDC price filtering if maxUsdcPrice is provided (only consider USDC assets)
|
|
79
|
-
let priceFilteredServices = filteredServices;
|
|
80
|
-
if (hasValidMaxUsdcPrice) {
|
|
81
|
-
priceFilteredServices = [];
|
|
82
|
-
for (const item of filteredServices) {
|
|
83
|
-
const accepts = Array.isArray(item.accepts) ? item.accepts : [];
|
|
84
|
-
let shouldInclude = false;
|
|
85
|
-
for (const req of accepts) {
|
|
86
|
-
if (req.network === walletNetwork && req.asset && req.maxAmountRequired) {
|
|
87
|
-
// Only consider USDC assets when maxUsdcPrice filter is applied
|
|
88
|
-
if ((0, utils_1.isUsdcAsset)(req.asset, walletProvider)) {
|
|
89
|
-
try {
|
|
90
|
-
const maxUsdcPriceAtomic = await (0, utils_1.convertWholeUnitsToAtomic)(args.maxUsdcPrice, req.asset, walletProvider);
|
|
91
|
-
if (maxUsdcPriceAtomic) {
|
|
92
|
-
const requirement = BigInt(req.maxAmountRequired);
|
|
93
|
-
const maxUsdcPriceAtomicBigInt = BigInt(maxUsdcPriceAtomic);
|
|
94
|
-
if (requirement <= maxUsdcPriceAtomicBigInt) {
|
|
95
|
-
shouldInclude = true;
|
|
96
|
-
break;
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
catch {
|
|
101
|
-
// If conversion fails, skip this requirement
|
|
102
|
-
continue;
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
if (shouldInclude) {
|
|
108
|
-
priceFilteredServices.push(item);
|
|
109
|
-
}
|
|
110
|
-
}
|
|
61
|
+
// Get the wallet's network identifiers (both v1 and v2 formats)
|
|
62
|
+
const walletNetworks = (0, utils_1.getX402Networks)(walletProvider.getNetwork());
|
|
63
|
+
// Apply filter pipeline
|
|
64
|
+
let filteredResources = (0, utils_1.filterByNetwork)(allResources, walletNetworks);
|
|
65
|
+
filteredResources = (0, utils_1.filterByDescription)(filteredResources);
|
|
66
|
+
filteredResources = (0, utils_1.filterByX402Version)(filteredResources, args.x402Versions);
|
|
67
|
+
// Apply keyword filter if provided
|
|
68
|
+
if (args.keyword) {
|
|
69
|
+
filteredResources = (0, utils_1.filterByKeyword)(filteredResources, args.keyword);
|
|
111
70
|
}
|
|
112
|
-
//
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
if (matchingAccept?.maxAmountRequired && matchingAccept?.asset) {
|
|
119
|
-
formattedMaxAmount = await (0, utils_1.formatPaymentOption)({
|
|
120
|
-
asset: matchingAccept.asset,
|
|
121
|
-
maxAmountRequired: matchingAccept.maxAmountRequired,
|
|
122
|
-
network: matchingAccept.network,
|
|
123
|
-
}, walletProvider);
|
|
124
|
-
}
|
|
125
|
-
return {
|
|
126
|
-
resource: item.resource,
|
|
127
|
-
description: matchingAccept?.description || "",
|
|
128
|
-
cost: formattedMaxAmount,
|
|
129
|
-
...(matchingAccept?.outputSchema?.input && {
|
|
130
|
-
input: matchingAccept.outputSchema.input,
|
|
131
|
-
}),
|
|
132
|
-
...(matchingAccept?.outputSchema?.output && {
|
|
133
|
-
output: matchingAccept.outputSchema.output,
|
|
134
|
-
}),
|
|
135
|
-
...(item.metadata && item.metadata.length > 0 && { metadata: item.metadata }),
|
|
136
|
-
};
|
|
137
|
-
}));
|
|
71
|
+
// Apply price filter if maxUsdcPrice is provided
|
|
72
|
+
if (args.maxUsdcPrice !== undefined) {
|
|
73
|
+
filteredResources = await (0, utils_1.filterByMaxPrice)(filteredResources, args.maxUsdcPrice, walletProvider, walletNetworks);
|
|
74
|
+
}
|
|
75
|
+
// Format simplified output
|
|
76
|
+
const simplifiedResources = await (0, utils_1.formatSimplifiedResources)(filteredResources, walletNetworks, walletProvider);
|
|
138
77
|
return JSON.stringify({
|
|
139
78
|
success: true,
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
79
|
+
services: simplifiedResources,
|
|
80
|
+
walletNetworks,
|
|
81
|
+
total: allResources.length,
|
|
82
|
+
returned: simplifiedResources.length,
|
|
144
83
|
}, null, 2);
|
|
145
84
|
}
|
|
146
85
|
catch (error) {
|
|
@@ -161,42 +100,89 @@ class X402ActionProvider extends actionProvider_1.ActionProvider {
|
|
|
161
100
|
*/
|
|
162
101
|
async makeHttpRequest(walletProvider, args) {
|
|
163
102
|
try {
|
|
164
|
-
const
|
|
165
|
-
|
|
166
|
-
|
|
103
|
+
const finalUrl = (0, utils_1.buildUrlWithParams)(args.url, args.queryParams);
|
|
104
|
+
let method = args.method ?? "GET";
|
|
105
|
+
let canHaveBody = ["POST", "PUT", "PATCH"].includes(method);
|
|
106
|
+
let response = await fetch(finalUrl, {
|
|
107
|
+
method,
|
|
167
108
|
headers: args.headers ?? undefined,
|
|
168
|
-
|
|
169
|
-
validateStatus: status => status === 402 || (status >= 200 && status < 300),
|
|
109
|
+
body: canHaveBody && args.body ? JSON.stringify(args.body) : undefined,
|
|
170
110
|
});
|
|
111
|
+
// Retry with other http method for 404 status code
|
|
112
|
+
if (response.status === 404) {
|
|
113
|
+
method = method === "GET" ? "POST" : "GET";
|
|
114
|
+
canHaveBody = ["POST", "PUT", "PATCH"].includes(method);
|
|
115
|
+
response = await fetch(finalUrl, {
|
|
116
|
+
method,
|
|
117
|
+
headers: args.headers ?? undefined,
|
|
118
|
+
body: canHaveBody && args.body ? JSON.stringify(args.body) : undefined,
|
|
119
|
+
});
|
|
120
|
+
}
|
|
171
121
|
if (response.status !== 402) {
|
|
122
|
+
const data = await this.parseResponseData(response);
|
|
172
123
|
return JSON.stringify({
|
|
173
124
|
success: true,
|
|
174
|
-
url:
|
|
175
|
-
method
|
|
125
|
+
url: finalUrl,
|
|
126
|
+
method,
|
|
176
127
|
status: response.status,
|
|
177
|
-
data
|
|
128
|
+
data,
|
|
178
129
|
}, null, 2);
|
|
179
130
|
}
|
|
180
|
-
//
|
|
181
|
-
|
|
182
|
-
const
|
|
183
|
-
|
|
184
|
-
let
|
|
185
|
-
//
|
|
131
|
+
// Handle 402 Payment Required
|
|
132
|
+
// v2 sends requirements in PAYMENT-REQUIRED header; v1 sends in body
|
|
133
|
+
const walletNetworks = (0, utils_1.getX402Networks)(walletProvider.getNetwork());
|
|
134
|
+
let acceptsArray = [];
|
|
135
|
+
let paymentData = {};
|
|
136
|
+
// Check for v2 header-based payment requirements
|
|
137
|
+
const paymentRequiredHeader = response.headers.get("payment-required");
|
|
138
|
+
if (paymentRequiredHeader) {
|
|
139
|
+
try {
|
|
140
|
+
const decoded = JSON.parse(atob(paymentRequiredHeader));
|
|
141
|
+
acceptsArray = decoded.accepts ?? [];
|
|
142
|
+
paymentData = decoded;
|
|
143
|
+
}
|
|
144
|
+
catch {
|
|
145
|
+
// Header parsing failed, fall back to body
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
// Fall back to v1 body-based requirements if header not present or empty
|
|
149
|
+
if (acceptsArray.length === 0) {
|
|
150
|
+
paymentData = await response.json();
|
|
151
|
+
acceptsArray = paymentData.accepts ?? [];
|
|
152
|
+
}
|
|
153
|
+
const availableNetworks = acceptsArray.map(option => option.network);
|
|
154
|
+
const hasMatchingNetwork = availableNetworks.some((net) => walletNetworks.includes(net));
|
|
155
|
+
let paymentOptionsText = `The wallet networks ${walletNetworks.join(", ")} do not match any available payment options (${availableNetworks.join(", ")}).`;
|
|
186
156
|
if (hasMatchingNetwork) {
|
|
187
|
-
const matchingOptions =
|
|
188
|
-
const formattedOptions = await Promise.all(matchingOptions.map(option => (0, utils_1.formatPaymentOption)(
|
|
157
|
+
const matchingOptions = acceptsArray.filter(option => walletNetworks.includes(option.network));
|
|
158
|
+
const formattedOptions = await Promise.all(matchingOptions.map(option => (0, utils_1.formatPaymentOption)({
|
|
159
|
+
asset: option.asset,
|
|
160
|
+
maxAmountRequired: option.maxAmountRequired ?? option.amount ?? "0",
|
|
161
|
+
network: option.network,
|
|
162
|
+
}, walletProvider)));
|
|
189
163
|
paymentOptionsText = `The payment options are: ${formattedOptions.join(", ")}`;
|
|
190
164
|
}
|
|
165
|
+
// Extract discovery info from v2 response (description, mimeType, extensions)
|
|
166
|
+
const discoveryInfo = {};
|
|
167
|
+
if (paymentData.description)
|
|
168
|
+
discoveryInfo.description = paymentData.description;
|
|
169
|
+
if (paymentData.mimeType)
|
|
170
|
+
discoveryInfo.mimeType = paymentData.mimeType;
|
|
171
|
+
if (paymentData.extensions)
|
|
172
|
+
discoveryInfo.extensions = paymentData.extensions;
|
|
191
173
|
return JSON.stringify({
|
|
192
174
|
status: "error_402_payment_required",
|
|
193
|
-
acceptablePaymentOptions:
|
|
175
|
+
acceptablePaymentOptions: acceptsArray,
|
|
176
|
+
...(Object.keys(discoveryInfo).length > 0 && { discoveryInfo }),
|
|
194
177
|
nextSteps: [
|
|
195
178
|
"Inform the user that the requested server replied with a 402 Payment Required response.",
|
|
196
179
|
paymentOptionsText,
|
|
180
|
+
"Include the description of the service in the response.",
|
|
181
|
+
"IMPORTANT: Identify required or optional query or body parameters based on this response. If there are any, you must inform the user and request them to provide the values. Always suggest example values.",
|
|
182
|
+
"CRITICAL: For POST/PUT/PATCH requests, you MUST use the 'body' parameter (NOT queryParams) to send data.",
|
|
197
183
|
hasMatchingNetwork ? "Ask the user if they want to retry the request with payment." : "",
|
|
198
184
|
hasMatchingNetwork
|
|
199
|
-
?
|
|
185
|
+
? "Use retry_http_request_with_x402 to retry the request with payment. IMPORTANT: You must retry_http_request_with_x402 with the correct Http method. "
|
|
200
186
|
: "",
|
|
201
187
|
],
|
|
202
188
|
});
|
|
@@ -214,68 +200,87 @@ class X402ActionProvider extends actionProvider_1.ActionProvider {
|
|
|
214
200
|
*/
|
|
215
201
|
async retryWithX402(walletProvider, args) {
|
|
216
202
|
try {
|
|
203
|
+
console.log("args", args);
|
|
217
204
|
// Check network compatibility before attempting payment
|
|
218
|
-
const
|
|
205
|
+
const walletNetworks = (0, utils_1.getX402Networks)(walletProvider.getNetwork());
|
|
219
206
|
const selectedNetwork = args.selectedPaymentOption.network;
|
|
220
|
-
if (
|
|
207
|
+
if (!walletNetworks.includes(selectedNetwork)) {
|
|
221
208
|
return JSON.stringify({
|
|
222
209
|
error: true,
|
|
223
210
|
message: "Network mismatch",
|
|
224
|
-
details: `Wallet is on ${
|
|
211
|
+
details: `Wallet is on ${walletNetworks.join(", ")} but payment requires ${selectedNetwork}`,
|
|
212
|
+
}, null, 2);
|
|
213
|
+
}
|
|
214
|
+
// Check if wallet provider is supported
|
|
215
|
+
if (!(walletProvider instanceof wallet_providers_1.SvmWalletProvider || walletProvider instanceof wallet_providers_1.EvmWalletProvider)) {
|
|
216
|
+
return JSON.stringify({
|
|
217
|
+
error: true,
|
|
218
|
+
message: "Unsupported wallet provider",
|
|
219
|
+
details: "Only SvmWalletProvider and EvmWalletProvider are supported",
|
|
225
220
|
}, null, 2);
|
|
226
221
|
}
|
|
222
|
+
// Create x402 client with appropriate signer
|
|
223
|
+
const client = await this.createX402Client(walletProvider);
|
|
224
|
+
const fetchWithPayment = (0, fetch_1.wrapFetchWithPayment)(fetch, client);
|
|
225
|
+
// Build URL with query params and determine if body is allowed
|
|
226
|
+
const finalUrl = (0, utils_1.buildUrlWithParams)(args.url, args.queryParams);
|
|
227
|
+
const method = args.method ?? "GET";
|
|
228
|
+
const canHaveBody = ["POST", "PUT", "PATCH"].includes(method);
|
|
229
|
+
// Build headers, adding Content-Type for JSON body
|
|
230
|
+
const headers = { ...(args.headers ?? {}) };
|
|
231
|
+
if (canHaveBody && args.body) {
|
|
232
|
+
headers["Content-Type"] = "application/json";
|
|
233
|
+
}
|
|
227
234
|
// Make the request with payment handling
|
|
228
|
-
const
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
235
|
+
const response = await fetchWithPayment(finalUrl, {
|
|
236
|
+
method,
|
|
237
|
+
headers,
|
|
238
|
+
body: canHaveBody && args.body ? JSON.stringify(args.body) : undefined,
|
|
239
|
+
});
|
|
240
|
+
const data = await this.parseResponseData(response);
|
|
241
|
+
// Check for payment proof in headers (v2: payment-response, v1: x-payment-response)
|
|
242
|
+
const paymentResponseHeader = response.headers.get("payment-response") ?? response.headers.get("x-payment-response");
|
|
243
|
+
let paymentProof = null;
|
|
244
|
+
if (paymentResponseHeader) {
|
|
245
|
+
try {
|
|
246
|
+
paymentProof = JSON.parse(atob(paymentResponseHeader));
|
|
237
247
|
}
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
accept.asset === asset);
|
|
242
|
-
if (paymentRequirements) {
|
|
243
|
-
return paymentRequirements;
|
|
248
|
+
catch {
|
|
249
|
+
// If parsing fails, include raw header
|
|
250
|
+
paymentProof = { raw: paymentResponseHeader };
|
|
244
251
|
}
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
const
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
252
|
+
}
|
|
253
|
+
// Get the amount used (supports both v1 and v2 formats)
|
|
254
|
+
const amountUsed = args.selectedPaymentOption.maxAmountRequired ??
|
|
255
|
+
args.selectedPaymentOption.amount ??
|
|
256
|
+
args.selectedPaymentOption.price;
|
|
257
|
+
// Check if the response was successful
|
|
258
|
+
// Payment is only settled on 200 status
|
|
259
|
+
if (response.status !== 200) {
|
|
260
|
+
return JSON.stringify({
|
|
261
|
+
status: "error",
|
|
262
|
+
message: `Request failed with status ${response.status}. Payment was not settled.`,
|
|
263
|
+
httpStatus: response.status,
|
|
264
|
+
data,
|
|
265
|
+
details: {
|
|
266
|
+
url: finalUrl,
|
|
267
|
+
method,
|
|
268
|
+
},
|
|
269
|
+
});
|
|
270
|
+
}
|
|
260
271
|
return JSON.stringify({
|
|
261
272
|
status: "success",
|
|
262
|
-
data
|
|
273
|
+
data,
|
|
263
274
|
message: "Request completed successfully with payment",
|
|
264
275
|
details: {
|
|
265
|
-
url:
|
|
266
|
-
method
|
|
276
|
+
url: finalUrl,
|
|
277
|
+
method,
|
|
267
278
|
paymentUsed: {
|
|
268
279
|
network: args.selectedPaymentOption.network,
|
|
269
280
|
asset: args.selectedPaymentOption.asset,
|
|
270
|
-
amount:
|
|
281
|
+
amount: amountUsed,
|
|
271
282
|
},
|
|
272
|
-
paymentProof
|
|
273
|
-
? {
|
|
274
|
-
transaction: paymentProof.transaction,
|
|
275
|
-
network: paymentProof.network,
|
|
276
|
-
payer: paymentProof.payer,
|
|
277
|
-
}
|
|
278
|
-
: null,
|
|
283
|
+
paymentProof,
|
|
279
284
|
},
|
|
280
285
|
});
|
|
281
286
|
}
|
|
@@ -292,49 +297,110 @@ class X402ActionProvider extends actionProvider_1.ActionProvider {
|
|
|
292
297
|
*/
|
|
293
298
|
async makeHttpRequestWithX402(walletProvider, args) {
|
|
294
299
|
try {
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
300
|
+
if (!(walletProvider instanceof wallet_providers_1.SvmWalletProvider || walletProvider instanceof wallet_providers_1.EvmWalletProvider)) {
|
|
301
|
+
return JSON.stringify({
|
|
302
|
+
error: true,
|
|
303
|
+
message: "Unsupported wallet provider",
|
|
304
|
+
details: "Only SvmWalletProvider and EvmWalletProvider are supported",
|
|
305
|
+
}, null, 2);
|
|
306
|
+
}
|
|
307
|
+
// Create x402 client with appropriate signer
|
|
308
|
+
const client = await this.createX402Client(walletProvider);
|
|
309
|
+
const fetchWithPayment = (0, fetch_1.wrapFetchWithPayment)(fetch, client);
|
|
310
|
+
// Build URL with query params and determine if body is allowed
|
|
311
|
+
const finalUrl = (0, utils_1.buildUrlWithParams)(args.url, args.queryParams);
|
|
312
|
+
const method = args.method ?? "GET";
|
|
313
|
+
const canHaveBody = ["POST", "PUT", "PATCH"].includes(method);
|
|
314
|
+
// Build headers, adding Content-Type for JSON body
|
|
315
|
+
const headers = { ...(args.headers ?? {}) };
|
|
316
|
+
if (canHaveBody && args.body) {
|
|
317
|
+
headers["Content-Type"] = "application/json";
|
|
318
|
+
}
|
|
319
|
+
const response = await fetchWithPayment(finalUrl, {
|
|
320
|
+
method,
|
|
321
|
+
headers,
|
|
322
|
+
body: canHaveBody && args.body ? JSON.stringify(args.body) : undefined,
|
|
303
323
|
});
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
324
|
+
const data = await this.parseResponseData(response);
|
|
325
|
+
// Check for payment proof in headers (v2: payment-response, v1: x-payment-response)
|
|
326
|
+
const paymentResponseHeader = response.headers.get("payment-response") ?? response.headers.get("x-payment-response");
|
|
327
|
+
let paymentProof = null;
|
|
328
|
+
if (paymentResponseHeader) {
|
|
329
|
+
try {
|
|
330
|
+
paymentProof = JSON.parse(atob(paymentResponseHeader));
|
|
331
|
+
}
|
|
332
|
+
catch {
|
|
333
|
+
// If parsing fails, include raw header
|
|
334
|
+
paymentProof = { raw: paymentResponseHeader };
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
// Check if the response was successful
|
|
338
|
+
// Payment is only settled on 200 status
|
|
339
|
+
if (response.status !== 200) {
|
|
340
|
+
return JSON.stringify({
|
|
341
|
+
success: false,
|
|
342
|
+
message: `Request failed with status ${response.status}. Payment was not settled.`,
|
|
343
|
+
url: finalUrl,
|
|
344
|
+
method,
|
|
345
|
+
status: response.status,
|
|
346
|
+
data,
|
|
347
|
+
}, null, 2);
|
|
348
|
+
}
|
|
308
349
|
return JSON.stringify({
|
|
309
350
|
success: true,
|
|
310
351
|
message: "Request completed successfully (payment handled automatically if required)",
|
|
311
|
-
url:
|
|
312
|
-
method
|
|
352
|
+
url: finalUrl,
|
|
353
|
+
method,
|
|
313
354
|
status: response.status,
|
|
314
|
-
data
|
|
315
|
-
paymentProof
|
|
316
|
-
? {
|
|
317
|
-
transaction: paymentProof.transaction,
|
|
318
|
-
network: paymentProof.network,
|
|
319
|
-
payer: paymentProof.payer,
|
|
320
|
-
}
|
|
321
|
-
: null,
|
|
355
|
+
data,
|
|
356
|
+
paymentProof,
|
|
322
357
|
}, null, 2);
|
|
323
358
|
}
|
|
324
359
|
catch (error) {
|
|
325
360
|
return (0, utils_1.handleHttpError)(error, args.url);
|
|
326
361
|
}
|
|
327
362
|
}
|
|
363
|
+
/**
|
|
364
|
+
* Creates an x402 client configured for the given wallet provider.
|
|
365
|
+
*
|
|
366
|
+
* @param walletProvider - The wallet provider to configure the client for
|
|
367
|
+
* @returns Configured x402Client
|
|
368
|
+
*/
|
|
369
|
+
async createX402Client(walletProvider) {
|
|
370
|
+
const client = new fetch_1.x402Client();
|
|
371
|
+
if (walletProvider instanceof wallet_providers_1.EvmWalletProvider) {
|
|
372
|
+
const signer = walletProvider.toSigner();
|
|
373
|
+
(0, client_1.registerExactEvmScheme)(client, { signer });
|
|
374
|
+
}
|
|
375
|
+
else if (walletProvider instanceof wallet_providers_1.SvmWalletProvider) {
|
|
376
|
+
const signer = await walletProvider.toSigner();
|
|
377
|
+
(0, client_2.registerExactSvmScheme)(client, { signer });
|
|
378
|
+
}
|
|
379
|
+
return client;
|
|
380
|
+
}
|
|
381
|
+
/**
|
|
382
|
+
* Parses response data based on content type.
|
|
383
|
+
*
|
|
384
|
+
* @param response - The fetch Response object
|
|
385
|
+
* @returns Parsed response data
|
|
386
|
+
*/
|
|
387
|
+
async parseResponseData(response) {
|
|
388
|
+
const contentType = response.headers.get("content-type") ?? "";
|
|
389
|
+
if (contentType.includes("application/json")) {
|
|
390
|
+
return response.json();
|
|
391
|
+
}
|
|
392
|
+
return response.text();
|
|
393
|
+
}
|
|
328
394
|
}
|
|
329
395
|
exports.X402ActionProvider = X402ActionProvider;
|
|
330
396
|
__decorate([
|
|
331
397
|
(0, actionDecorator_1.CreateAction)({
|
|
332
398
|
name: "discover_x402_services",
|
|
333
|
-
description: "Discover available x402 services. Optionally filter by a maximum price in whole units of USDC (only USDC payment options will be considered when filter is applied).",
|
|
399
|
+
description: "Discover available x402 services. Only services available on the current network will be returned. Optionally filter by a maximum price in whole units of USDC (only USDC payment options will be considered when filter is applied).",
|
|
334
400
|
schema: schemas_1.ListX402ServicesSchema,
|
|
335
401
|
}),
|
|
336
402
|
__metadata("design:type", Function),
|
|
337
|
-
__metadata("design:paramtypes", [wallet_providers_1.
|
|
403
|
+
__metadata("design:paramtypes", [wallet_providers_1.WalletProvider, void 0]),
|
|
338
404
|
__metadata("design:returntype", Promise)
|
|
339
405
|
], X402ActionProvider.prototype, "discoverX402Services", null);
|
|
340
406
|
__decorate([
|
|
@@ -347,13 +413,13 @@ it will return payment details that can be used with retry_http_request_with_x40
|
|
|
347
413
|
EXAMPLES:
|
|
348
414
|
- Production API: make_http_request("https://api.example.com/weather")
|
|
349
415
|
- Local development: make_http_request("http://localhost:3000/api/data")
|
|
350
|
-
- Testing x402: make_http_request("http://localhost:3000/protected")
|
|
351
416
|
|
|
352
|
-
If you receive a 402 Payment Required response, use retry_http_request_with_x402 to handle the payment
|
|
417
|
+
If you receive a 402 Payment Required response, use retry_http_request_with_x402 to handle the payment.
|
|
418
|
+
`,
|
|
353
419
|
schema: schemas_1.HttpRequestSchema,
|
|
354
420
|
}),
|
|
355
421
|
__metadata("design:type", Function),
|
|
356
|
-
__metadata("design:paramtypes", [wallet_providers_1.
|
|
422
|
+
__metadata("design:paramtypes", [wallet_providers_1.WalletProvider, void 0]),
|
|
357
423
|
__metadata("design:returntype", Promise)
|
|
358
424
|
], X402ActionProvider.prototype, "makeHttpRequest", null);
|
|
359
425
|
__decorate([
|
|
@@ -372,14 +438,14 @@ DO NOT use this action directly without first trying make_http_request!`,
|
|
|
372
438
|
schema: schemas_1.RetryWithX402Schema,
|
|
373
439
|
}),
|
|
374
440
|
__metadata("design:type", Function),
|
|
375
|
-
__metadata("design:paramtypes", [wallet_providers_1.
|
|
441
|
+
__metadata("design:paramtypes", [wallet_providers_1.WalletProvider, void 0]),
|
|
376
442
|
__metadata("design:returntype", Promise)
|
|
377
443
|
], X402ActionProvider.prototype, "retryWithX402", null);
|
|
378
444
|
__decorate([
|
|
379
445
|
(0, actionDecorator_1.CreateAction)({
|
|
380
446
|
name: "make_http_request_with_x402",
|
|
381
447
|
description: `
|
|
382
|
-
|
|
448
|
+
WARNING: This action automatically handles payments without asking for confirmation!
|
|
383
449
|
Only use this when explicitly told to skip the confirmation flow.
|
|
384
450
|
|
|
385
451
|
For most cases, you should:
|
|
@@ -400,7 +466,7 @@ Unless specifically instructed otherwise, prefer the two-step approach with make
|
|
|
400
466
|
schema: schemas_1.DirectX402RequestSchema,
|
|
401
467
|
}),
|
|
402
468
|
__metadata("design:type", Function),
|
|
403
|
-
__metadata("design:paramtypes", [wallet_providers_1.
|
|
469
|
+
__metadata("design:paramtypes", [wallet_providers_1.WalletProvider, void 0]),
|
|
404
470
|
__metadata("design:returntype", Promise)
|
|
405
471
|
], X402ActionProvider.prototype, "makeHttpRequestWithX402", null);
|
|
406
472
|
const x402ActionProvider = () => new X402ActionProvider();
|