@coinbase/agentkit 0.8.1 → 0.8.2
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 +14 -1
- package/dist/action-providers/index.d.ts +1 -0
- package/dist/action-providers/index.js +1 -0
- package/dist/action-providers/vaultsfyi/api/historicalData.d.ts +31 -0
- package/dist/action-providers/vaultsfyi/api/historicalData.js +44 -0
- package/dist/action-providers/vaultsfyi/api/vaults.d.ts +38 -10
- package/dist/action-providers/vaultsfyi/api/vaults.js +19 -1
- package/dist/action-providers/vaultsfyi/schemas.d.ts +38 -3
- package/dist/action-providers/vaultsfyi/schemas.js +35 -3
- package/dist/action-providers/vaultsfyi/utils.d.ts +64 -0
- package/dist/action-providers/vaultsfyi/utils.js +53 -0
- package/dist/action-providers/vaultsfyi/vaultsfyiActionProvider.d.ts +18 -2
- package/dist/action-providers/vaultsfyi/vaultsfyiActionProvider.js +87 -20
- package/dist/action-providers/vaultsfyi/vaultsfyiActionProvider.test.js +165 -0
- package/dist/action-providers/x402/index.d.ts +1 -0
- package/dist/action-providers/x402/index.js +17 -0
- package/dist/action-providers/x402/schemas.d.ts +30 -0
- package/dist/action-providers/x402/schemas.js +27 -0
- package/dist/action-providers/x402/x402ActionProvider.d.ts +38 -0
- package/dist/action-providers/x402/x402ActionProvider.js +238 -0
- package/dist/action-providers/x402/x402ActionProvider.test.d.ts +1 -0
- package/dist/action-providers/x402/x402ActionProvider.test.js +469 -0
- package/package.json +6 -4
|
@@ -0,0 +1,469 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
const x402ActionProvider_1 = require("./x402ActionProvider");
|
|
40
|
+
const axios_1 = __importDefault(require("axios"));
|
|
41
|
+
const x402axios = __importStar(require("x402-axios"));
|
|
42
|
+
// Mock modules
|
|
43
|
+
jest.mock("axios");
|
|
44
|
+
jest.mock("x402-axios");
|
|
45
|
+
// Create mock functions
|
|
46
|
+
const mockRequest = jest.fn();
|
|
47
|
+
// Create a complete mock axios instance
|
|
48
|
+
const mockAxiosInstance = {
|
|
49
|
+
request: mockRequest,
|
|
50
|
+
get: jest.fn(),
|
|
51
|
+
delete: jest.fn(),
|
|
52
|
+
head: jest.fn(),
|
|
53
|
+
options: jest.fn(),
|
|
54
|
+
post: jest.fn(),
|
|
55
|
+
put: jest.fn(),
|
|
56
|
+
patch: jest.fn(),
|
|
57
|
+
getUri: jest.fn(),
|
|
58
|
+
defaults: {},
|
|
59
|
+
interceptors: {
|
|
60
|
+
request: { use: jest.fn(), eject: jest.fn(), clear: jest.fn() },
|
|
61
|
+
response: { use: jest.fn(), eject: jest.fn(), clear: jest.fn() },
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
// Create a complete mock axios static
|
|
65
|
+
const mockAxios = {
|
|
66
|
+
create: jest.fn().mockReturnValue(mockAxiosInstance),
|
|
67
|
+
request: mockRequest,
|
|
68
|
+
get: jest.fn(),
|
|
69
|
+
delete: jest.fn(),
|
|
70
|
+
head: jest.fn(),
|
|
71
|
+
options: jest.fn(),
|
|
72
|
+
post: jest.fn(),
|
|
73
|
+
put: jest.fn(),
|
|
74
|
+
patch: jest.fn(),
|
|
75
|
+
all: jest.fn(),
|
|
76
|
+
spread: jest.fn(),
|
|
77
|
+
isAxiosError: jest.fn(),
|
|
78
|
+
isCancel: jest.fn(),
|
|
79
|
+
CancelToken: {
|
|
80
|
+
source: jest.fn(),
|
|
81
|
+
},
|
|
82
|
+
VERSION: "1.x",
|
|
83
|
+
};
|
|
84
|
+
const mockWithPaymentInterceptor = jest.fn().mockReturnValue(mockAxiosInstance);
|
|
85
|
+
const mockDecodeXPaymentResponse = jest.fn();
|
|
86
|
+
// Override the mocked modules
|
|
87
|
+
axios_1.default.create = mockAxios.create;
|
|
88
|
+
axios_1.default.request = mockRequest;
|
|
89
|
+
axios_1.default.isAxiosError = mockAxios.isAxiosError;
|
|
90
|
+
// Mock x402-axios functions
|
|
91
|
+
jest.mocked(x402axios.withPaymentInterceptor).mockImplementation(mockWithPaymentInterceptor);
|
|
92
|
+
jest.mocked(x402axios.decodeXPaymentResponse).mockImplementation(mockDecodeXPaymentResponse);
|
|
93
|
+
// Mock wallet provider
|
|
94
|
+
const mockWalletProvider = {
|
|
95
|
+
toSigner: jest.fn().mockReturnValue("mock-signer"),
|
|
96
|
+
};
|
|
97
|
+
// Sample responses based on real examples
|
|
98
|
+
const MOCK_PAYMENT_INFO_RESPONSE = {
|
|
99
|
+
paymentRequired: true,
|
|
100
|
+
url: "https://www.x402.org/protected",
|
|
101
|
+
status: 402,
|
|
102
|
+
data: {
|
|
103
|
+
x402Version: 1,
|
|
104
|
+
error: "X-PAYMENT header is required",
|
|
105
|
+
accepts: [
|
|
106
|
+
{
|
|
107
|
+
scheme: "exact",
|
|
108
|
+
network: "base-sepolia",
|
|
109
|
+
maxAmountRequired: "10000",
|
|
110
|
+
resource: "https://www.x402.org/protected",
|
|
111
|
+
description: "Access to protected content",
|
|
112
|
+
mimeType: "application/json",
|
|
113
|
+
payTo: "0x209693Bc6afc0C5328bA36FaF03C514EF312287C",
|
|
114
|
+
maxTimeoutSeconds: 300,
|
|
115
|
+
asset: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
|
|
116
|
+
extra: {
|
|
117
|
+
name: "USDC",
|
|
118
|
+
version: "2",
|
|
119
|
+
},
|
|
120
|
+
},
|
|
121
|
+
],
|
|
122
|
+
},
|
|
123
|
+
};
|
|
124
|
+
const MOCK_PAYMENT_RESPONSE = {
|
|
125
|
+
success: true,
|
|
126
|
+
transaction: "0xcbc385789d3744b52af5106c32809534f64adcbe097e050ec03d6b53fed5d305",
|
|
127
|
+
network: "base-sepolia",
|
|
128
|
+
payer: "0xa8c1a5D3C372C65c04f91f87a43F549619A9483f",
|
|
129
|
+
};
|
|
130
|
+
const MOCK_PAID_REQUEST_RESPONSE = {
|
|
131
|
+
success: true,
|
|
132
|
+
url: "https://www.x402.org/protected",
|
|
133
|
+
method: "GET",
|
|
134
|
+
status: 200,
|
|
135
|
+
data: "<!DOCTYPE html><html>...</html>",
|
|
136
|
+
paymentResponse: MOCK_PAYMENT_RESPONSE,
|
|
137
|
+
};
|
|
138
|
+
describe("X402ActionProvider", () => {
|
|
139
|
+
let provider;
|
|
140
|
+
beforeEach(() => {
|
|
141
|
+
provider = new x402ActionProvider_1.X402ActionProvider();
|
|
142
|
+
jest.clearAllMocks();
|
|
143
|
+
// Setup mocks
|
|
144
|
+
mockAxios.create.mockReturnValue(mockAxiosInstance);
|
|
145
|
+
mockWithPaymentInterceptor.mockReturnValue(mockAxiosInstance);
|
|
146
|
+
// Setup axios.isAxiosError mock
|
|
147
|
+
jest
|
|
148
|
+
.mocked(axios_1.default.isAxiosError)
|
|
149
|
+
.mockImplementation((error) => Boolean(error &&
|
|
150
|
+
typeof error === "object" &&
|
|
151
|
+
("isAxiosError" in error || "response" in error || "request" in error)));
|
|
152
|
+
});
|
|
153
|
+
afterEach(() => {
|
|
154
|
+
jest.clearAllMocks();
|
|
155
|
+
});
|
|
156
|
+
describe("supportsNetwork", () => {
|
|
157
|
+
it("should support base-mainnet", () => {
|
|
158
|
+
const network = { protocolFamily: "evm", networkId: "base-mainnet" };
|
|
159
|
+
expect(provider.supportsNetwork(network)).toBe(true);
|
|
160
|
+
});
|
|
161
|
+
it("should support base-sepolia", () => {
|
|
162
|
+
const network = { protocolFamily: "evm", networkId: "base-sepolia" };
|
|
163
|
+
expect(provider.supportsNetwork(network)).toBe(true);
|
|
164
|
+
});
|
|
165
|
+
it("should not support unsupported EVM networks", () => {
|
|
166
|
+
const network = { protocolFamily: "evm", networkId: "ethereum" };
|
|
167
|
+
expect(provider.supportsNetwork(network)).toBe(false);
|
|
168
|
+
});
|
|
169
|
+
it("should not support non-EVM networks", () => {
|
|
170
|
+
const network = { protocolFamily: "solana", networkId: "mainnet" };
|
|
171
|
+
expect(provider.supportsNetwork(network)).toBe(false);
|
|
172
|
+
});
|
|
173
|
+
});
|
|
174
|
+
describe("fetchPaymentInfo", () => {
|
|
175
|
+
it("should successfully fetch payment info for 402 response", async () => {
|
|
176
|
+
mockRequest.mockResolvedValue({
|
|
177
|
+
status: 402,
|
|
178
|
+
statusText: "Payment Required",
|
|
179
|
+
data: MOCK_PAYMENT_INFO_RESPONSE.data,
|
|
180
|
+
headers: {},
|
|
181
|
+
config: {},
|
|
182
|
+
});
|
|
183
|
+
const result = await provider.fetchPaymentInfo(mockWalletProvider, {
|
|
184
|
+
url: "https://www.x402.org/protected",
|
|
185
|
+
method: "GET",
|
|
186
|
+
});
|
|
187
|
+
expect(mockRequest).toHaveBeenCalledWith({
|
|
188
|
+
url: "https://www.x402.org/protected",
|
|
189
|
+
method: "GET",
|
|
190
|
+
headers: undefined,
|
|
191
|
+
validateStatus: expect.any(Function),
|
|
192
|
+
});
|
|
193
|
+
const parsedResult = JSON.parse(result);
|
|
194
|
+
expect(parsedResult.paymentRequired).toBe(true);
|
|
195
|
+
expect(parsedResult.status).toBe(402);
|
|
196
|
+
expect(parsedResult.data).toEqual(MOCK_PAYMENT_INFO_RESPONSE.data);
|
|
197
|
+
});
|
|
198
|
+
it("should handle non-payment-protected endpoints", async () => {
|
|
199
|
+
mockRequest.mockResolvedValue({
|
|
200
|
+
status: 200,
|
|
201
|
+
statusText: "OK",
|
|
202
|
+
data: { message: "No payment required" },
|
|
203
|
+
headers: {},
|
|
204
|
+
config: {},
|
|
205
|
+
});
|
|
206
|
+
const result = await provider.fetchPaymentInfo(mockWalletProvider, {
|
|
207
|
+
url: "https://api.example.com/free",
|
|
208
|
+
method: "GET",
|
|
209
|
+
});
|
|
210
|
+
const parsedResult = JSON.parse(result);
|
|
211
|
+
expect(parsedResult.paymentRequired).toBe(false);
|
|
212
|
+
expect(parsedResult.status).toBe(200);
|
|
213
|
+
expect(parsedResult.data).toEqual({ message: "No payment required" });
|
|
214
|
+
});
|
|
215
|
+
it("should handle 402 errors with payment details in headers", async () => {
|
|
216
|
+
mockDecodeXPaymentResponse.mockReturnValue(MOCK_PAYMENT_RESPONSE);
|
|
217
|
+
const error = new Error("Payment required");
|
|
218
|
+
error.isAxiosError = true;
|
|
219
|
+
error.response = {
|
|
220
|
+
status: 402,
|
|
221
|
+
statusText: "Payment Required",
|
|
222
|
+
headers: {
|
|
223
|
+
"x-payment-response": "encoded-payment-data",
|
|
224
|
+
},
|
|
225
|
+
data: MOCK_PAYMENT_INFO_RESPONSE.data,
|
|
226
|
+
config: {},
|
|
227
|
+
};
|
|
228
|
+
mockRequest.mockRejectedValue(error);
|
|
229
|
+
const result = await provider.fetchPaymentInfo(mockWalletProvider, {
|
|
230
|
+
url: "https://www.x402.org/protected",
|
|
231
|
+
method: "GET",
|
|
232
|
+
});
|
|
233
|
+
expect(mockDecodeXPaymentResponse).toHaveBeenCalledWith("encoded-payment-data");
|
|
234
|
+
const parsedResult = JSON.parse(result);
|
|
235
|
+
expect(parsedResult.paymentRequired).toBe(true);
|
|
236
|
+
expect(parsedResult.status).toBe(402);
|
|
237
|
+
expect(parsedResult.paymentDetails).toEqual(MOCK_PAYMENT_RESPONSE);
|
|
238
|
+
});
|
|
239
|
+
it("should fallback to JSON.parse when decodeXPaymentResponse fails", async () => {
|
|
240
|
+
const paymentDetailsJson = '{"amount": "10000"}';
|
|
241
|
+
mockDecodeXPaymentResponse.mockImplementation(() => {
|
|
242
|
+
throw new Error("Decode failed");
|
|
243
|
+
});
|
|
244
|
+
const error = new Error("Payment required");
|
|
245
|
+
error.isAxiosError = true;
|
|
246
|
+
error.response = {
|
|
247
|
+
status: 402,
|
|
248
|
+
statusText: "Payment Required",
|
|
249
|
+
headers: {
|
|
250
|
+
"x-payment-response": paymentDetailsJson,
|
|
251
|
+
},
|
|
252
|
+
data: MOCK_PAYMENT_INFO_RESPONSE.data,
|
|
253
|
+
config: {},
|
|
254
|
+
};
|
|
255
|
+
mockRequest.mockRejectedValue(error);
|
|
256
|
+
const result = await provider.fetchPaymentInfo(mockWalletProvider, {
|
|
257
|
+
url: "https://www.x402.org/protected",
|
|
258
|
+
method: "GET",
|
|
259
|
+
});
|
|
260
|
+
const parsedResult = JSON.parse(result);
|
|
261
|
+
expect(parsedResult.paymentDetails).toEqual({ amount: "10000" });
|
|
262
|
+
});
|
|
263
|
+
it("should handle payment header parsing failures", async () => {
|
|
264
|
+
mockDecodeXPaymentResponse.mockImplementation(() => {
|
|
265
|
+
throw new Error("Decode failed");
|
|
266
|
+
});
|
|
267
|
+
const error = new Error("Payment required");
|
|
268
|
+
error.isAxiosError = true;
|
|
269
|
+
error.response = {
|
|
270
|
+
status: 402,
|
|
271
|
+
statusText: "Payment Required",
|
|
272
|
+
headers: {
|
|
273
|
+
"x-payment-response": "invalid-json",
|
|
274
|
+
},
|
|
275
|
+
data: MOCK_PAYMENT_INFO_RESPONSE.data,
|
|
276
|
+
config: {},
|
|
277
|
+
};
|
|
278
|
+
mockRequest.mockRejectedValue(error);
|
|
279
|
+
const result = await provider.fetchPaymentInfo(mockWalletProvider, {
|
|
280
|
+
url: "https://www.x402.org/protected",
|
|
281
|
+
method: "GET",
|
|
282
|
+
});
|
|
283
|
+
const parsedResult = JSON.parse(result);
|
|
284
|
+
expect(parsedResult.paymentDetails.error).toBe("Failed to decode payment response");
|
|
285
|
+
expect(parsedResult.paymentDetails.rawHeader).toBe("invalid-json");
|
|
286
|
+
});
|
|
287
|
+
it("should handle non-402 HTTP errors", async () => {
|
|
288
|
+
const error = new Error("Server error");
|
|
289
|
+
error.isAxiosError = true;
|
|
290
|
+
error.response = {
|
|
291
|
+
status: 500,
|
|
292
|
+
statusText: "Internal Server Error",
|
|
293
|
+
headers: {},
|
|
294
|
+
data: { error: "Internal server error" },
|
|
295
|
+
config: {},
|
|
296
|
+
};
|
|
297
|
+
mockRequest.mockRejectedValue(error);
|
|
298
|
+
const result = await provider.fetchPaymentInfo(mockWalletProvider, {
|
|
299
|
+
url: "https://api.example.com/endpoint",
|
|
300
|
+
method: "GET",
|
|
301
|
+
});
|
|
302
|
+
expect(result).toContain("Error fetching payment info");
|
|
303
|
+
expect(result).toContain("HTTP 500");
|
|
304
|
+
expect(result).toContain("Internal server error");
|
|
305
|
+
});
|
|
306
|
+
it("should handle network errors", async () => {
|
|
307
|
+
const error = new Error("Network error");
|
|
308
|
+
error.isAxiosError = true;
|
|
309
|
+
error.request = {};
|
|
310
|
+
mockRequest.mockRejectedValue(error);
|
|
311
|
+
const result = await provider.fetchPaymentInfo(mockWalletProvider, {
|
|
312
|
+
url: "https://api.example.com/endpoint",
|
|
313
|
+
method: "GET",
|
|
314
|
+
});
|
|
315
|
+
expect(result).toContain("Error fetching payment info");
|
|
316
|
+
expect(result).toContain("Network error");
|
|
317
|
+
});
|
|
318
|
+
});
|
|
319
|
+
describe("paidRequest", () => {
|
|
320
|
+
it("should successfully make a paid request with payment response", async () => {
|
|
321
|
+
mockDecodeXPaymentResponse.mockReturnValue(MOCK_PAYMENT_RESPONSE);
|
|
322
|
+
mockRequest.mockResolvedValue({
|
|
323
|
+
status: 200,
|
|
324
|
+
statusText: "OK",
|
|
325
|
+
data: MOCK_PAID_REQUEST_RESPONSE.data,
|
|
326
|
+
headers: {
|
|
327
|
+
"x-payment-response": "encoded-payment-response",
|
|
328
|
+
},
|
|
329
|
+
config: {},
|
|
330
|
+
});
|
|
331
|
+
const result = await provider.paidRequest(mockWalletProvider, {
|
|
332
|
+
url: "https://www.x402.org/protected",
|
|
333
|
+
method: "GET",
|
|
334
|
+
});
|
|
335
|
+
expect(mockWithPaymentInterceptor).toHaveBeenCalledWith(mockAxiosInstance, "mock-signer");
|
|
336
|
+
expect(mockRequest).toHaveBeenCalledWith({
|
|
337
|
+
url: "https://www.x402.org/protected",
|
|
338
|
+
method: "GET",
|
|
339
|
+
headers: undefined,
|
|
340
|
+
data: undefined,
|
|
341
|
+
});
|
|
342
|
+
const parsedResult = JSON.parse(result);
|
|
343
|
+
expect(parsedResult.success).toBe(true);
|
|
344
|
+
expect(parsedResult.status).toBe(200);
|
|
345
|
+
expect(parsedResult.paymentResponse).toEqual(MOCK_PAYMENT_RESPONSE);
|
|
346
|
+
});
|
|
347
|
+
it("should handle successful request without payment", async () => {
|
|
348
|
+
mockRequest.mockResolvedValue({
|
|
349
|
+
status: 200,
|
|
350
|
+
statusText: "OK",
|
|
351
|
+
data: { message: "Success" },
|
|
352
|
+
headers: {},
|
|
353
|
+
config: {},
|
|
354
|
+
});
|
|
355
|
+
const result = await provider.paidRequest(mockWalletProvider, {
|
|
356
|
+
url: "https://api.example.com/free",
|
|
357
|
+
method: "GET",
|
|
358
|
+
});
|
|
359
|
+
const parsedResult = JSON.parse(result);
|
|
360
|
+
expect(parsedResult.success).toBe(true);
|
|
361
|
+
expect(parsedResult.status).toBe(200);
|
|
362
|
+
expect(parsedResult.paymentResponse).toBe(null);
|
|
363
|
+
});
|
|
364
|
+
it("should fallback to JSON.parse when decodeXPaymentResponse fails", async () => {
|
|
365
|
+
const paymentResponseJson = '{"transaction": "0x123"}';
|
|
366
|
+
mockDecodeXPaymentResponse.mockImplementation(() => {
|
|
367
|
+
throw new Error("Decode failed");
|
|
368
|
+
});
|
|
369
|
+
mockRequest.mockResolvedValue({
|
|
370
|
+
status: 200,
|
|
371
|
+
statusText: "OK",
|
|
372
|
+
data: "Success",
|
|
373
|
+
headers: {
|
|
374
|
+
"x-payment-response": paymentResponseJson,
|
|
375
|
+
},
|
|
376
|
+
config: {},
|
|
377
|
+
});
|
|
378
|
+
const result = await provider.paidRequest(mockWalletProvider, {
|
|
379
|
+
url: "https://www.x402.org/protected",
|
|
380
|
+
method: "GET",
|
|
381
|
+
});
|
|
382
|
+
const parsedResult = JSON.parse(result);
|
|
383
|
+
expect(parsedResult.paymentResponse).toEqual({ transaction: "0x123" });
|
|
384
|
+
});
|
|
385
|
+
it("should handle payment response parsing failures", async () => {
|
|
386
|
+
mockDecodeXPaymentResponse.mockImplementation(() => {
|
|
387
|
+
throw new Error("Decode failed");
|
|
388
|
+
});
|
|
389
|
+
mockRequest.mockResolvedValue({
|
|
390
|
+
status: 200,
|
|
391
|
+
statusText: "OK",
|
|
392
|
+
data: "Success",
|
|
393
|
+
headers: {
|
|
394
|
+
"x-payment-response": "invalid-json",
|
|
395
|
+
},
|
|
396
|
+
config: {},
|
|
397
|
+
});
|
|
398
|
+
const result = await provider.paidRequest(mockWalletProvider, {
|
|
399
|
+
url: "https://www.x402.org/protected",
|
|
400
|
+
method: "GET",
|
|
401
|
+
});
|
|
402
|
+
const parsedResult = JSON.parse(result);
|
|
403
|
+
expect(parsedResult.paymentResponse.error).toBe("Failed to decode payment response");
|
|
404
|
+
expect(parsedResult.paymentResponse.rawHeader).toBe("invalid-json");
|
|
405
|
+
});
|
|
406
|
+
it("should handle HTTP errors", async () => {
|
|
407
|
+
const error = new Error("Bad request");
|
|
408
|
+
error.isAxiosError = true;
|
|
409
|
+
error.response = {
|
|
410
|
+
status: 400,
|
|
411
|
+
statusText: "Bad Request",
|
|
412
|
+
headers: {},
|
|
413
|
+
data: { error: "Invalid parameters" },
|
|
414
|
+
config: {},
|
|
415
|
+
};
|
|
416
|
+
mockRequest.mockRejectedValue(error);
|
|
417
|
+
const result = await provider.paidRequest(mockWalletProvider, {
|
|
418
|
+
url: "https://api.example.com/endpoint",
|
|
419
|
+
method: "POST",
|
|
420
|
+
body: { test: "data" },
|
|
421
|
+
});
|
|
422
|
+
expect(result).toContain("Error making paid request");
|
|
423
|
+
expect(result).toContain("HTTP 400");
|
|
424
|
+
expect(result).toContain("Invalid parameters");
|
|
425
|
+
});
|
|
426
|
+
it("should handle network errors", async () => {
|
|
427
|
+
const error = new Error("Connection timeout");
|
|
428
|
+
error.isAxiosError = true;
|
|
429
|
+
error.request = {};
|
|
430
|
+
mockRequest.mockRejectedValue(error);
|
|
431
|
+
const result = await provider.paidRequest(mockWalletProvider, {
|
|
432
|
+
url: "https://api.example.com/endpoint",
|
|
433
|
+
method: "GET",
|
|
434
|
+
});
|
|
435
|
+
expect(result).toContain("Error making paid request");
|
|
436
|
+
expect(result).toContain("Network error");
|
|
437
|
+
expect(result).toContain("Connection timeout");
|
|
438
|
+
});
|
|
439
|
+
it("should handle generic errors", async () => {
|
|
440
|
+
const error = new Error("Something went wrong");
|
|
441
|
+
mockRequest.mockRejectedValue(error);
|
|
442
|
+
const result = await provider.paidRequest(mockWalletProvider, {
|
|
443
|
+
url: "https://api.example.com/endpoint",
|
|
444
|
+
method: "GET",
|
|
445
|
+
});
|
|
446
|
+
expect(result).toContain("Error making paid request");
|
|
447
|
+
expect(result).toContain("Something went wrong");
|
|
448
|
+
});
|
|
449
|
+
it("should pass through all request parameters", async () => {
|
|
450
|
+
mockRequest.mockResolvedValue({
|
|
451
|
+
status: 200,
|
|
452
|
+
data: "Success",
|
|
453
|
+
headers: {},
|
|
454
|
+
});
|
|
455
|
+
await provider.paidRequest(mockWalletProvider, {
|
|
456
|
+
url: "https://api.example.com/endpoint",
|
|
457
|
+
method: "POST",
|
|
458
|
+
headers: { "Content-Type": "application/json" },
|
|
459
|
+
body: { key: "value" },
|
|
460
|
+
});
|
|
461
|
+
expect(mockRequest).toHaveBeenCalledWith({
|
|
462
|
+
url: "https://api.example.com/endpoint",
|
|
463
|
+
method: "POST",
|
|
464
|
+
headers: { "Content-Type": "application/json" },
|
|
465
|
+
data: { key: "value" },
|
|
466
|
+
});
|
|
467
|
+
});
|
|
468
|
+
});
|
|
469
|
+
});
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@coinbase/agentkit",
|
|
3
3
|
"description": "Coinbase AgentKit core primitives",
|
|
4
4
|
"repository": "https://github.com/coinbase/agentkit",
|
|
5
|
-
"version": "0.8.
|
|
5
|
+
"version": "0.8.2",
|
|
6
6
|
"author": "Coinbase Inc.",
|
|
7
7
|
"license": "Apache-2.0",
|
|
8
8
|
"main": "dist/index.js",
|
|
@@ -31,18 +31,20 @@
|
|
|
31
31
|
"@privy-io/server-auth": "1.18.4",
|
|
32
32
|
"@solana/spl-token": "^0.4.12",
|
|
33
33
|
"@solana/web3.js": "^1.98.1",
|
|
34
|
+
"@zerodev/ecdsa-validator": "^5.4.5",
|
|
35
|
+
"@zerodev/intent": "^0.0.24",
|
|
36
|
+
"@zerodev/sdk": "^5.4.28",
|
|
37
|
+
"axios": "^1.9.0",
|
|
34
38
|
"bs58": "^4.0.1",
|
|
35
39
|
"canonicalize": "^2.1.0",
|
|
36
40
|
"decimal.js": "^10.5.0",
|
|
37
41
|
"ethers": "^6.13.5",
|
|
38
|
-
"@zerodev/ecdsa-validator": "^5.4.5",
|
|
39
|
-
"@zerodev/intent": "^0.0.24",
|
|
40
|
-
"@zerodev/sdk": "^5.4.28",
|
|
41
42
|
"md5": "^2.3.0",
|
|
42
43
|
"opensea-js": "^7.1.18",
|
|
43
44
|
"reflect-metadata": "^0.2.2",
|
|
44
45
|
"twitter-api-v2": "^1.18.2",
|
|
45
46
|
"viem": "^2.22.16",
|
|
47
|
+
"x402-axios": "^0.3.3",
|
|
46
48
|
"zod": "^3.23.8"
|
|
47
49
|
},
|
|
48
50
|
"devDependencies": {
|