@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.
Files changed (107) hide show
  1. package/README.md +89 -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/cdp/cdpApiActionProvider.js +7 -30
  6. package/dist/action-providers/cdp/cdpApiActionProvider.test.js +2 -8
  7. package/dist/action-providers/cdp/faucetUtils.d.ts +38 -0
  8. package/dist/action-providers/cdp/faucetUtils.js +81 -0
  9. package/dist/action-providers/clanker/schemas.d.ts +4 -4
  10. package/dist/action-providers/clanker/utils.d.ts +2 -1
  11. package/dist/action-providers/clanker/utils.js +2 -2
  12. package/dist/action-providers/enso/constants.d.ts +4 -0
  13. package/dist/action-providers/enso/constants.js +10 -0
  14. package/dist/action-providers/enso/ensoActionProvider.d.ts +34 -0
  15. package/dist/action-providers/enso/ensoActionProvider.js +125 -0
  16. package/dist/action-providers/enso/ensoActionProvider.test.d.ts +1 -0
  17. package/dist/action-providers/enso/ensoActionProvider.test.js +141 -0
  18. package/dist/action-providers/enso/index.d.ts +1 -0
  19. package/dist/action-providers/enso/index.js +17 -0
  20. package/dist/action-providers/enso/schemas.d.ts +23 -0
  21. package/dist/action-providers/enso/schemas.js +22 -0
  22. package/dist/action-providers/erc20/constants.d.ts +2 -0
  23. package/dist/action-providers/erc20/constants.js +2 -0
  24. package/dist/action-providers/erc20/erc20ActionProvider.d.ts +17 -1
  25. package/dist/action-providers/erc20/erc20ActionProvider.js +103 -1
  26. package/dist/action-providers/erc20/erc20ActionProvider.test.js +201 -0
  27. package/dist/action-providers/erc20/schemas.d.ts +29 -0
  28. package/dist/action-providers/erc20/schemas.js +34 -1
  29. package/dist/action-providers/index.d.ts +4 -1
  30. package/dist/action-providers/index.js +4 -1
  31. package/dist/action-providers/jupiter/jupiterActionProvider.js +2 -2
  32. package/dist/action-providers/spl/splActionProvider.js +12 -13
  33. package/dist/action-providers/superfluid/graphQueries/superfluidGraphQueries.js +2 -2
  34. package/dist/action-providers/sushi/constants.d.ts +35 -0
  35. package/dist/action-providers/sushi/constants.js +7 -0
  36. package/dist/action-providers/sushi/index.d.ts +4 -0
  37. package/dist/action-providers/sushi/index.js +20 -0
  38. package/dist/action-providers/sushi/sushiDataActionProvider.d.ts +32 -0
  39. package/dist/action-providers/sushi/sushiDataActionProvider.js +113 -0
  40. package/dist/action-providers/sushi/sushiDataSchemas.d.ts +11 -0
  41. package/dist/action-providers/sushi/sushiDataSchemas.js +16 -0
  42. package/dist/action-providers/sushi/sushiRouterActionProvider.d.ts +40 -0
  43. package/dist/action-providers/sushi/sushiRouterActionProvider.js +386 -0
  44. package/dist/action-providers/sushi/sushiRouterActionProvider.test.d.ts +1 -0
  45. package/dist/action-providers/sushi/sushiRouterActionProvider.test.js +392 -0
  46. package/dist/action-providers/sushi/sushiRouterSchemas.d.ts +36 -0
  47. package/dist/action-providers/sushi/sushiRouterSchemas.js +55 -0
  48. package/dist/action-providers/vaultsfyi/constants.d.ts +8 -12
  49. package/dist/action-providers/vaultsfyi/constants.js +47 -13
  50. package/dist/action-providers/vaultsfyi/schemas.d.ts +120 -65
  51. package/dist/action-providers/vaultsfyi/schemas.js +72 -38
  52. package/dist/action-providers/vaultsfyi/sdk.d.ts +8 -0
  53. package/dist/action-providers/vaultsfyi/sdk.js +15 -0
  54. package/dist/action-providers/vaultsfyi/utils.d.ts +151 -55
  55. package/dist/action-providers/vaultsfyi/utils.js +29 -75
  56. package/dist/action-providers/vaultsfyi/vaultsfyiActionProvider.d.ts +55 -16
  57. package/dist/action-providers/vaultsfyi/vaultsfyiActionProvider.js +413 -217
  58. package/dist/action-providers/vaultsfyi/vaultsfyiActionProvider.test.js +509 -316
  59. package/dist/action-providers/wallet/walletActionProvider.js +1 -1
  60. package/dist/action-providers/weth/constants.d.ts +0 -1
  61. package/dist/action-providers/weth/constants.js +1 -2
  62. package/dist/action-providers/weth/schemas.js +6 -2
  63. package/dist/action-providers/weth/wethActionProvider.d.ts +7 -0
  64. package/dist/action-providers/weth/wethActionProvider.js +57 -32
  65. package/dist/action-providers/weth/wethActionProvider.test.js +60 -11
  66. package/dist/action-providers/x402/constants.d.ts +67 -0
  67. package/dist/action-providers/x402/constants.js +37 -0
  68. package/dist/action-providers/x402/schemas.d.ts +45 -5
  69. package/dist/action-providers/x402/schemas.js +81 -11
  70. package/dist/action-providers/x402/utils.d.ts +89 -14
  71. package/dist/action-providers/x402/utils.js +335 -31
  72. package/dist/action-providers/x402/x402ActionProvider.d.ts +21 -7
  73. package/dist/action-providers/x402/x402ActionProvider.js +250 -184
  74. package/dist/action-providers/x402/x402ActionProvider.test.js +240 -236
  75. package/dist/action-providers/yelay/constants.d.ts +64 -0
  76. package/dist/action-providers/yelay/constants.js +137 -0
  77. package/dist/action-providers/yelay/index.d.ts +2 -0
  78. package/dist/action-providers/yelay/index.js +18 -0
  79. package/dist/action-providers/yelay/schemas.d.ts +47 -0
  80. package/dist/action-providers/yelay/schemas.js +59 -0
  81. package/dist/action-providers/yelay/types.d.ts +24 -0
  82. package/dist/action-providers/yelay/yelayActionProvider.d.ts +70 -0
  83. package/dist/action-providers/yelay/yelayActionProvider.js +329 -0
  84. package/dist/action-providers/yelay/yelayActionProvider.test.d.ts +1 -0
  85. package/dist/action-providers/yelay/yelayActionProvider.test.js +302 -0
  86. package/dist/action-providers/zora/zoraActionProvider.js +4 -5
  87. package/dist/wallet-providers/cdpSmartWalletProvider.js +1 -3
  88. package/dist/wallet-providers/cdpSolanaWalletProvider.d.ts +14 -0
  89. package/dist/wallet-providers/cdpSolanaWalletProvider.js +39 -3
  90. package/dist/wallet-providers/cdpSolanaWalletProvider.test.js +16 -0
  91. package/dist/wallet-providers/privySvmWalletProvider.d.ts +14 -0
  92. package/dist/wallet-providers/privySvmWalletProvider.js +17 -0
  93. package/dist/wallet-providers/privySvmWalletProvider.test.js +10 -0
  94. package/dist/wallet-providers/solanaKeypairWalletProvider.d.ts +14 -0
  95. package/dist/wallet-providers/solanaKeypairWalletProvider.js +17 -0
  96. package/dist/wallet-providers/svmWalletProvider.d.ts +34 -0
  97. package/dist/wallet-providers/svmWalletProvider.js +43 -0
  98. package/dist/wallet-providers/svmWalletProvider.test.js +10 -0
  99. package/package.json +11 -6
  100. package/dist/action-providers/vaultsfyi/api/actions.d.ts +0 -41
  101. package/dist/action-providers/vaultsfyi/api/actions.js +0 -28
  102. package/dist/action-providers/vaultsfyi/api/historicalData.d.ts +0 -31
  103. package/dist/action-providers/vaultsfyi/api/historicalData.js +0 -44
  104. package/dist/action-providers/vaultsfyi/api/types.d.ts +0 -34
  105. package/dist/action-providers/vaultsfyi/api/vaults.d.ts +0 -66
  106. package/dist/action-providers/vaultsfyi/api/vaults.js +0 -57
  107. /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 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) => network.protocolFamily === "evm" && 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,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 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}`,
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 account = walletProvider.toSigner();
229
- const paymentSelector = (accepts) => {
230
- const { scheme, network, maxAmountRequired, asset } = args.selectedPaymentOption;
231
- let paymentRequirements = accepts.find(accept => accept.scheme === scheme &&
232
- accept.network === network &&
233
- accept.maxAmountRequired <= maxAmountRequired &&
234
- accept.asset === asset);
235
- if (paymentRequirements) {
236
- 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));
237
247
  }
238
- paymentRequirements = accepts.find(accept => accept.scheme === scheme &&
239
- accept.network === network &&
240
- accept.maxAmountRequired <= maxAmountRequired &&
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
- return accepts[0];
246
- };
247
- const api = (0, x402_axios_1.withPaymentInterceptor)(axios_1.default.create({}),
248
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
249
- account, paymentSelector);
250
- const response = await api.request({
251
- url: args.url,
252
- method: args.method ?? "GET",
253
- headers: args.headers ?? undefined,
254
- data: args.body,
255
- });
256
- // Check for payment proof
257
- const paymentProof = response.headers["x-payment-response"]
258
- ? (0, x402_axios_1.decodeXPaymentResponse)(response.headers["x-payment-response"])
259
- : 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
+ }
260
271
  return JSON.stringify({
261
272
  status: "success",
262
- data: response.data,
273
+ data,
263
274
  message: "Request completed successfully with payment",
264
275
  details: {
265
- url: args.url,
266
- method: args.method,
276
+ url: finalUrl,
277
+ method,
267
278
  paymentUsed: {
268
279
  network: args.selectedPaymentOption.network,
269
280
  asset: args.selectedPaymentOption.asset,
270
- amount: args.selectedPaymentOption.maxAmountRequired,
281
+ amount: amountUsed,
271
282
  },
272
- paymentProof: 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
- const account = walletProvider.toSigner();
296
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
297
- const api = (0, x402_axios_1.withPaymentInterceptor)(axios_1.default.create({}), account);
298
- const response = await api.request({
299
- url: args.url,
300
- method: args.method ?? "GET",
301
- headers: args.headers ?? undefined,
302
- data: args.body,
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
- // Check for payment proof
305
- const paymentProof = response.headers["x-payment-response"]
306
- ? (0, x402_axios_1.decodeXPaymentResponse)(response.headers["x-payment-response"])
307
- : 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
+ }
308
349
  return JSON.stringify({
309
350
  success: true,
310
351
  message: "Request completed successfully (payment handled automatically if required)",
311
- url: args.url,
312
- method: args.method,
352
+ url: finalUrl,
353
+ method,
313
354
  status: response.status,
314
- data: response.data,
315
- paymentProof: 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.EvmWalletProvider, void 0]),
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.EvmWalletProvider, void 0]),
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.EvmWalletProvider, void 0]),
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
- ⚠️ WARNING: This action automatically handles payments without asking for confirmation!
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.EvmWalletProvider, void 0]),
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();