@coinbase/agentkit 0.10.3 → 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.
Files changed (55) hide show
  1. package/README.md +47 -10
  2. package/dist/action-providers/across/acrossActionProvider.js +2 -4
  3. package/dist/action-providers/across/acrossActionProvider.test.js +10 -5
  4. package/dist/action-providers/baseAccount/baseAccountActionProvider.js +5 -7
  5. package/dist/action-providers/clanker/utils.d.ts +2 -1
  6. package/dist/action-providers/clanker/utils.js +2 -2
  7. package/dist/action-providers/index.d.ts +1 -0
  8. package/dist/action-providers/index.js +1 -0
  9. package/dist/action-providers/jupiter/jupiterActionProvider.js +2 -2
  10. package/dist/action-providers/spl/splActionProvider.js +12 -13
  11. package/dist/action-providers/superfluid/graphQueries/superfluidGraphQueries.js +2 -2
  12. package/dist/action-providers/sushi/constants.d.ts +35 -0
  13. package/dist/action-providers/sushi/constants.js +7 -0
  14. package/dist/action-providers/sushi/index.d.ts +4 -0
  15. package/dist/action-providers/sushi/index.js +20 -0
  16. package/dist/action-providers/sushi/sushiDataActionProvider.d.ts +32 -0
  17. package/dist/action-providers/sushi/sushiDataActionProvider.js +113 -0
  18. package/dist/action-providers/sushi/sushiDataSchemas.d.ts +11 -0
  19. package/dist/action-providers/sushi/sushiDataSchemas.js +16 -0
  20. package/dist/action-providers/sushi/sushiRouterActionProvider.d.ts +40 -0
  21. package/dist/action-providers/sushi/sushiRouterActionProvider.js +386 -0
  22. package/dist/action-providers/sushi/sushiRouterActionProvider.test.d.ts +1 -0
  23. package/dist/action-providers/sushi/sushiRouterActionProvider.test.js +392 -0
  24. package/dist/action-providers/sushi/sushiRouterSchemas.d.ts +36 -0
  25. package/dist/action-providers/sushi/sushiRouterSchemas.js +55 -0
  26. package/dist/action-providers/vaultsfyi/constants.d.ts +8 -12
  27. package/dist/action-providers/vaultsfyi/constants.js +47 -13
  28. package/dist/action-providers/vaultsfyi/schemas.d.ts +120 -65
  29. package/dist/action-providers/vaultsfyi/schemas.js +72 -38
  30. package/dist/action-providers/vaultsfyi/sdk.d.ts +8 -0
  31. package/dist/action-providers/vaultsfyi/sdk.js +15 -0
  32. package/dist/action-providers/vaultsfyi/utils.d.ts +151 -55
  33. package/dist/action-providers/vaultsfyi/utils.js +29 -75
  34. package/dist/action-providers/vaultsfyi/vaultsfyiActionProvider.d.ts +55 -16
  35. package/dist/action-providers/vaultsfyi/vaultsfyiActionProvider.js +413 -217
  36. package/dist/action-providers/vaultsfyi/vaultsfyiActionProvider.test.js +509 -316
  37. package/dist/action-providers/x402/constants.d.ts +67 -0
  38. package/dist/action-providers/x402/constants.js +37 -0
  39. package/dist/action-providers/x402/schemas.d.ts +45 -5
  40. package/dist/action-providers/x402/schemas.js +81 -11
  41. package/dist/action-providers/x402/utils.d.ts +85 -10
  42. package/dist/action-providers/x402/utils.js +302 -35
  43. package/dist/action-providers/x402/x402ActionProvider.d.ts +15 -1
  44. package/dist/action-providers/x402/x402ActionProvider.js +230 -179
  45. package/dist/action-providers/x402/x402ActionProvider.test.js +222 -262
  46. package/dist/action-providers/zora/zoraActionProvider.js +4 -5
  47. package/package.json +10 -7
  48. package/dist/action-providers/vaultsfyi/api/actions.d.ts +0 -41
  49. package/dist/action-providers/vaultsfyi/api/actions.js +0 -28
  50. package/dist/action-providers/vaultsfyi/api/historicalData.d.ts +0 -31
  51. package/dist/action-providers/vaultsfyi/api/historicalData.js +0 -44
  52. package/dist/action-providers/vaultsfyi/api/types.d.ts +0 -34
  53. package/dist/action-providers/vaultsfyi/api/types.js +0 -2
  54. package/dist/action-providers/vaultsfyi/api/vaults.d.ts +0 -66
  55. package/dist/action-providers/vaultsfyi/api/vaults.js +0 -57
@@ -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 axios_1 = __importDefault(require("axios"));
22
- const x402_axios_1 = require("x402-axios");
23
- const verify_1 = require("x402/verify");
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 SUPPORTED_NETWORKS = ["base-mainnet", "base-sepolia", "solana-mainnet", "solana-devnet"];
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) => SUPPORTED_NETWORKS.includes(network.networkId);
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
- const { list } = (0, verify_1.useFacilitator)(x402_1.facilitator);
55
- const services = await list();
56
- if (!services || !services.items) {
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 current wallet network
63
- const walletNetwork = (0, utils_1.getX402Network)(walletProvider.getNetwork());
64
- // Filter services by network, description, and optional USDC price
65
- const hasValidMaxUsdcPrice = typeof args.maxUsdcPrice === "number" &&
66
- Number.isFinite(args.maxUsdcPrice) &&
67
- args.maxUsdcPrice > 0;
68
- const filteredServices = services.items.filter(item => {
69
- // Filter by network - only include services that accept the current wallet network
70
- const accepts = Array.isArray(item.accepts) ? item.accepts : [];
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
- // Format the filtered services
113
- const filtered = await Promise.all(priceFilteredServices.map(async (item) => {
114
- const accepts = Array.isArray(item.accepts) ? item.accepts : [];
115
- const matchingAccept = accepts.find(req => req.network === walletNetwork);
116
- // Format amount if available
117
- let formattedMaxAmount = matchingAccept?.maxAmountRequired;
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
- walletNetwork,
141
- total: services.items.length,
142
- returned: filtered.length,
143
- items: filtered,
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 response = await axios_1.default.request({
165
- url: args.url,
166
- method: args.method ?? "GET",
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
- data: args.body,
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: args.url,
175
- method: args.method,
125
+ url: finalUrl,
126
+ method,
176
127
  status: response.status,
177
- data: response.data,
128
+ data,
178
129
  }, null, 2);
179
130
  }
180
- // Check if wallet network matches any available payment options
181
- const walletNetwork = (0, utils_1.getX402Network)(walletProvider.getNetwork());
182
- const availableNetworks = response.data.accepts.map(option => option.network);
183
- const hasMatchingNetwork = availableNetworks.includes(walletNetwork);
184
- let paymentOptionsText = `The wallet network ${walletNetwork} does not match any available payment options (${availableNetworks.join(", ")}).`;
185
- // Format payment options for matching networks
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 = response.data.accepts.filter(option => option.network === walletNetwork);
188
- const formattedOptions = await Promise.all(matchingOptions.map(option => (0, utils_1.formatPaymentOption)(option, walletProvider)));
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: response.data.accepts,
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
- ? `Use retry_http_request_with_x402 to retry the request with payment.`
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,14 +200,15 @@ 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 walletNetwork = (0, utils_1.getX402Network)(walletProvider.getNetwork());
205
+ const walletNetworks = (0, utils_1.getX402Networks)(walletProvider.getNetwork());
219
206
  const selectedNetwork = args.selectedPaymentOption.network;
220
- if (walletNetwork !== selectedNetwork) {
207
+ if (!walletNetworks.includes(selectedNetwork)) {
221
208
  return JSON.stringify({
222
209
  error: true,
223
210
  message: "Network mismatch",
224
- details: `Wallet is on ${walletNetwork} but payment requires ${selectedNetwork}`,
211
+ details: `Wallet is on ${walletNetworks.join(", ")} but payment requires ${selectedNetwork}`,
225
212
  }, null, 2);
226
213
  }
227
214
  // Check if wallet provider is supported
@@ -232,58 +219,68 @@ class X402ActionProvider extends actionProvider_1.ActionProvider {
232
219
  details: "Only SvmWalletProvider and EvmWalletProvider are supported",
233
220
  }, null, 2);
234
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
+ }
235
234
  // Make the request with payment handling
236
- const account = await walletProvider.toSigner();
237
- const paymentSelector = (accepts) => {
238
- const { scheme, network, maxAmountRequired, asset } = args.selectedPaymentOption;
239
- let paymentRequirements = accepts.find(accept => accept.scheme === scheme &&
240
- accept.network === network &&
241
- accept.maxAmountRequired <= maxAmountRequired &&
242
- accept.asset === asset);
243
- if (paymentRequirements) {
244
- return paymentRequirements;
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));
245
247
  }
246
- paymentRequirements = accepts.find(accept => accept.scheme === scheme &&
247
- accept.network === network &&
248
- accept.maxAmountRequired <= maxAmountRequired &&
249
- accept.asset === asset);
250
- if (paymentRequirements) {
251
- return paymentRequirements;
248
+ catch {
249
+ // If parsing fails, include raw header
250
+ paymentProof = { raw: paymentResponseHeader };
252
251
  }
253
- return accepts[0];
254
- };
255
- const api = (0, x402_axios_1.withPaymentInterceptor)(axios_1.default.create({}),
256
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
257
- account, paymentSelector);
258
- const response = await api.request({
259
- url: args.url,
260
- method: args.method ?? "GET",
261
- headers: args.headers ?? undefined,
262
- data: args.body,
263
- });
264
- // Check for payment proof
265
- const paymentProof = response.headers["x-payment-response"]
266
- ? (0, x402_axios_1.decodeXPaymentResponse)(response.headers["x-payment-response"])
267
- : null;
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
+ }
268
271
  return JSON.stringify({
269
272
  status: "success",
270
- data: response.data,
273
+ data,
271
274
  message: "Request completed successfully with payment",
272
275
  details: {
273
- url: args.url,
274
- method: args.method,
276
+ url: finalUrl,
277
+ method,
275
278
  paymentUsed: {
276
279
  network: args.selectedPaymentOption.network,
277
280
  asset: args.selectedPaymentOption.asset,
278
- amount: args.selectedPaymentOption.maxAmountRequired,
281
+ amount: amountUsed,
279
282
  },
280
- paymentProof: paymentProof
281
- ? {
282
- transaction: paymentProof.transaction,
283
- network: paymentProof.network,
284
- payer: paymentProof.payer,
285
- }
286
- : null,
283
+ paymentProof,
287
284
  },
288
285
  });
289
286
  }
@@ -307,39 +304,93 @@ class X402ActionProvider extends actionProvider_1.ActionProvider {
307
304
  details: "Only SvmWalletProvider and EvmWalletProvider are supported",
308
305
  }, null, 2);
309
306
  }
310
- const account = await walletProvider.toSigner();
311
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
312
- const api = (0, x402_axios_1.withPaymentInterceptor)(axios_1.default.create({}), account);
313
- const response = await api.request({
314
- url: args.url,
315
- method: args.method ?? "GET",
316
- headers: args.headers ?? undefined,
317
- data: args.body,
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,
318
323
  });
319
- // Check for payment proof
320
- const paymentProof = response.headers["x-payment-response"]
321
- ? (0, x402_axios_1.decodeXPaymentResponse)(response.headers["x-payment-response"])
322
- : null;
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
+ }
323
349
  return JSON.stringify({
324
350
  success: true,
325
351
  message: "Request completed successfully (payment handled automatically if required)",
326
- url: args.url,
327
- method: args.method,
352
+ url: finalUrl,
353
+ method,
328
354
  status: response.status,
329
- data: response.data,
330
- paymentProof: paymentProof
331
- ? {
332
- transaction: paymentProof.transaction,
333
- network: paymentProof.network,
334
- payer: paymentProof.payer,
335
- }
336
- : null,
355
+ data,
356
+ paymentProof,
337
357
  }, null, 2);
338
358
  }
339
359
  catch (error) {
340
360
  return (0, utils_1.handleHttpError)(error, args.url);
341
361
  }
342
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
+ }
343
394
  }
344
395
  exports.X402ActionProvider = X402ActionProvider;
345
396
  __decorate([
@@ -362,9 +413,9 @@ it will return payment details that can be used with retry_http_request_with_x40
362
413
  EXAMPLES:
363
414
  - Production API: make_http_request("https://api.example.com/weather")
364
415
  - Local development: make_http_request("http://localhost:3000/api/data")
365
- - Testing x402: make_http_request("http://localhost:3000/protected")
366
416
 
367
- 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
+ `,
368
419
  schema: schemas_1.HttpRequestSchema,
369
420
  }),
370
421
  __metadata("design:type", Function),
@@ -394,7 +445,7 @@ __decorate([
394
445
  (0, actionDecorator_1.CreateAction)({
395
446
  name: "make_http_request_with_x402",
396
447
  description: `
397
- ⚠️ WARNING: This action automatically handles payments without asking for confirmation!
448
+ WARNING: This action automatically handles payments without asking for confirmation!
398
449
  Only use this when explicitly told to skip the confirmation flow.
399
450
 
400
451
  For most cases, you should: