@coinbase/agentkit 0.0.0-nightly-20250820210426 → 0.0.0-nightly-20250821210420
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 +37 -0
- package/dist/action-providers/cdp/cdpApiActionProvider.d.ts +3 -11
- package/dist/action-providers/cdp/cdpApiActionProvider.js +2 -65
- package/dist/action-providers/cdp/cdpApiActionProvider.test.js +0 -125
- package/dist/action-providers/cdp/cdpEvmWalletActionProvider.d.ts +17 -1
- package/dist/action-providers/cdp/cdpEvmWalletActionProvider.js +219 -0
- package/dist/action-providers/cdp/cdpEvmWalletActionProvider.test.js +270 -0
- package/dist/action-providers/cdp/cdpSmartWalletActionProvider.d.ts +17 -1
- package/dist/action-providers/cdp/cdpSmartWalletActionProvider.js +220 -0
- package/dist/action-providers/cdp/cdpSmartWalletActionProvider.test.js +254 -0
- package/dist/action-providers/cdp/schemas.d.ts +12 -12
- package/dist/action-providers/cdp/schemas.js +17 -5
- package/dist/action-providers/cdp/swapUtils.d.ts +32 -0
- package/dist/action-providers/cdp/swapUtils.js +142 -0
- package/dist/action-providers/index.d.ts +1 -0
- package/dist/action-providers/index.js +1 -0
- package/dist/action-providers/jupiter/schemas.d.ts +1 -1
- package/dist/action-providers/superfluid/constants.d.ts +814 -0
- package/dist/action-providers/superfluid/constants.js +2826 -0
- package/dist/action-providers/superfluid/graphQueries/endpoints.d.ts +2 -0
- package/dist/action-providers/superfluid/graphQueries/endpoints.js +5 -0
- package/dist/action-providers/superfluid/graphQueries/queries.d.ts +1 -0
- package/dist/action-providers/superfluid/graphQueries/queries.js +35 -0
- package/dist/action-providers/superfluid/graphQueries/superfluidGraphQueries.d.ts +8 -0
- package/dist/action-providers/superfluid/graphQueries/superfluidGraphQueries.js +24 -0
- package/dist/action-providers/superfluid/graphQueries/types.d.ts +27 -0
- package/dist/action-providers/superfluid/graphQueries/types.js +2 -0
- package/dist/action-providers/superfluid/index.d.ts +7 -0
- package/dist/action-providers/superfluid/index.js +23 -0
- package/dist/action-providers/superfluid/schemas.d.ts +86 -0
- package/dist/action-providers/superfluid/schemas.js +103 -0
- package/dist/action-providers/superfluid/superfluidActionProvider.d.ts +20 -0
- package/dist/action-providers/superfluid/superfluidActionProvider.js +36 -0
- package/dist/action-providers/superfluid/superfluidPoolActionProvider.d.ts +46 -0
- package/dist/action-providers/superfluid/superfluidPoolActionProvider.js +143 -0
- package/dist/action-providers/superfluid/superfluidPoolActionProvider.test.d.ts +1 -0
- package/dist/action-providers/superfluid/superfluidPoolActionProvider.test.js +92 -0
- package/dist/action-providers/superfluid/superfluidQueryActionProvider.d.ts +27 -0
- package/dist/action-providers/superfluid/superfluidQueryActionProvider.js +71 -0
- package/dist/action-providers/superfluid/superfluidQueryActionProvider.test.d.ts +1 -0
- package/dist/action-providers/superfluid/superfluidQueryActionProvider.test.js +57 -0
- package/dist/action-providers/superfluid/superfluidStreamActionProvider.d.ts +56 -0
- package/dist/action-providers/superfluid/superfluidStreamActionProvider.js +191 -0
- package/dist/action-providers/superfluid/superfluidStreamActionProvider.test.d.ts +1 -0
- package/dist/action-providers/superfluid/superfluidStreamActionProvider.test.js +80 -0
- package/dist/action-providers/superfluid/superfluidSuperTokenCreatorActionProvider.d.ts +30 -0
- package/dist/action-providers/superfluid/superfluidSuperTokenCreatorActionProvider.js +108 -0
- package/dist/action-providers/superfluid/superfluidSuperTokenCreatorActionProvider.test.d.ts +1 -0
- package/dist/action-providers/superfluid/superfluidSuperTokenCreatorActionProvider.test.js +75 -0
- package/dist/action-providers/superfluid/superfluidWrapperActionProvider.d.ts +32 -0
- package/dist/action-providers/superfluid/superfluidWrapperActionProvider.js +101 -0
- package/dist/action-providers/superfluid/superfluidWrapperActionProvider.test.d.ts +1 -0
- package/dist/action-providers/superfluid/superfluidWrapperActionProvider.test.js +85 -0
- package/dist/action-providers/superfluid/utils/parseLogs.d.ts +18 -0
- package/dist/action-providers/superfluid/utils/parseLogs.js +78 -0
- package/dist/wallet-providers/cdpSmartWalletProvider.d.ts +3 -2
- package/dist/wallet-providers/cdpSmartWalletProvider.js +4 -5
- package/dist/wallet-providers/viemWalletProvider.d.ts +4 -0
- package/dist/wallet-providers/viemWalletProvider.js +2 -1
- package/package.json +3 -2
|
@@ -36,23 +36,29 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
36
36
|
const cdpSmartWalletActionProvider_1 = require("./cdpSmartWalletActionProvider");
|
|
37
37
|
const schemas_1 = require("./schemas");
|
|
38
38
|
const spendPermissionUtils = __importStar(require("./spendPermissionUtils"));
|
|
39
|
+
const swapUtils = __importStar(require("./swapUtils"));
|
|
39
40
|
// Mock the CDP SDK and utility functions
|
|
40
41
|
jest.mock("@coinbase/cdp-sdk");
|
|
41
42
|
jest.mock("./spendPermissionUtils");
|
|
43
|
+
jest.mock("./swapUtils");
|
|
42
44
|
describe("CDP Smart Wallet Action Provider", () => {
|
|
43
45
|
let actionProvider;
|
|
44
46
|
let mockWalletProvider;
|
|
45
47
|
let mockCdpClient;
|
|
46
48
|
let mockSmartAccount;
|
|
49
|
+
const mockGetTokenDetails = swapUtils.getTokenDetails;
|
|
50
|
+
const mockRetryWithExponentialBackoff = swapUtils.retryWithExponentialBackoff;
|
|
47
51
|
beforeEach(() => {
|
|
48
52
|
jest.clearAllMocks();
|
|
49
53
|
mockSmartAccount = {
|
|
50
54
|
useSpendPermission: jest.fn(),
|
|
55
|
+
swap: jest.fn(),
|
|
51
56
|
address: "0x1234567890123456789012345678901234567890",
|
|
52
57
|
};
|
|
53
58
|
mockCdpClient = {
|
|
54
59
|
evm: {
|
|
55
60
|
listSpendPermissions: jest.fn(),
|
|
61
|
+
getSwapPrice: jest.fn(),
|
|
56
62
|
},
|
|
57
63
|
};
|
|
58
64
|
mockWalletProvider = {
|
|
@@ -60,7 +66,18 @@ describe("CDP Smart Wallet Action Provider", () => {
|
|
|
60
66
|
getAddress: jest.fn(),
|
|
61
67
|
getClient: jest.fn(),
|
|
62
68
|
smartAccount: mockSmartAccount,
|
|
69
|
+
ownerAccount: {
|
|
70
|
+
type: "server",
|
|
71
|
+
address: "0xowner123",
|
|
72
|
+
},
|
|
73
|
+
sendTransaction: jest.fn(),
|
|
74
|
+
waitForTransactionReceipt: jest.fn(),
|
|
75
|
+
getPaymasterUrl: jest.fn(),
|
|
63
76
|
};
|
|
77
|
+
// Default setup for utility functions
|
|
78
|
+
mockRetryWithExponentialBackoff.mockImplementation(async (fn) => {
|
|
79
|
+
return await fn();
|
|
80
|
+
});
|
|
64
81
|
actionProvider = new cdpSmartWalletActionProvider_1.CdpSmartWalletActionProvider();
|
|
65
82
|
});
|
|
66
83
|
describe("listSpendPermissions", () => {
|
|
@@ -188,6 +205,243 @@ describe("CDP Smart Wallet Action Provider", () => {
|
|
|
188
205
|
expect(() => schemas_1.UseSpendPermissionSchema.parse(invalidInput)).toThrow();
|
|
189
206
|
});
|
|
190
207
|
});
|
|
208
|
+
describe("getSwapPrice", () => {
|
|
209
|
+
const mockArgs = {
|
|
210
|
+
fromToken: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", // ETH
|
|
211
|
+
toToken: "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913", // USDC on Base
|
|
212
|
+
fromAmount: "0.1",
|
|
213
|
+
slippageBps: 100,
|
|
214
|
+
};
|
|
215
|
+
beforeEach(() => {
|
|
216
|
+
mockWalletProvider.getClient.mockReturnValue(mockCdpClient);
|
|
217
|
+
mockWalletProvider.getAddress.mockReturnValue("0x1234567890123456789012345678901234567890");
|
|
218
|
+
mockGetTokenDetails.mockResolvedValue({
|
|
219
|
+
fromTokenDecimals: 18,
|
|
220
|
+
toTokenDecimals: 6,
|
|
221
|
+
fromTokenName: "ETH",
|
|
222
|
+
toTokenName: "USDC",
|
|
223
|
+
});
|
|
224
|
+
});
|
|
225
|
+
it("should get swap price quote on base-mainnet", async () => {
|
|
226
|
+
mockWalletProvider.getNetwork.mockReturnValue({
|
|
227
|
+
protocolFamily: "evm",
|
|
228
|
+
networkId: "base-mainnet",
|
|
229
|
+
});
|
|
230
|
+
mockCdpClient.evm.getSwapPrice.mockResolvedValue({
|
|
231
|
+
toAmount: "990000", // 0.99 USDC
|
|
232
|
+
minToAmount: "980000", // 0.98 USDC
|
|
233
|
+
liquidityAvailable: true,
|
|
234
|
+
issues: {},
|
|
235
|
+
});
|
|
236
|
+
const result = await actionProvider.getSwapPrice(mockWalletProvider, mockArgs);
|
|
237
|
+
const parsedResult = JSON.parse(result);
|
|
238
|
+
expect(mockCdpClient.evm.getSwapPrice).toHaveBeenCalledWith({
|
|
239
|
+
fromToken: mockArgs.fromToken,
|
|
240
|
+
toToken: mockArgs.toToken,
|
|
241
|
+
fromAmount: 100000000000000000n, // 0.1 ETH in wei
|
|
242
|
+
network: "base",
|
|
243
|
+
taker: "0x1234567890123456789012345678901234567890",
|
|
244
|
+
});
|
|
245
|
+
expect(parsedResult.success).toBe(true);
|
|
246
|
+
expect(parsedResult.fromAmount).toBe("0.1");
|
|
247
|
+
expect(parsedResult.toAmount).toBe("0.99");
|
|
248
|
+
expect(parsedResult.liquidityAvailable).toBe(true);
|
|
249
|
+
});
|
|
250
|
+
it("should get swap price quote on base-sepolia", async () => {
|
|
251
|
+
mockWalletProvider.getNetwork.mockReturnValue({
|
|
252
|
+
protocolFamily: "evm",
|
|
253
|
+
networkId: "base-sepolia",
|
|
254
|
+
});
|
|
255
|
+
mockCdpClient.evm.getSwapPrice.mockResolvedValue({
|
|
256
|
+
toAmount: "990000",
|
|
257
|
+
minToAmount: "980000",
|
|
258
|
+
liquidityAvailable: true,
|
|
259
|
+
issues: {},
|
|
260
|
+
});
|
|
261
|
+
const result = await actionProvider.getSwapPrice(mockWalletProvider, mockArgs);
|
|
262
|
+
const parsedResult = JSON.parse(result);
|
|
263
|
+
expect(mockCdpClient.evm.getSwapPrice).toHaveBeenCalledWith({
|
|
264
|
+
fromToken: mockArgs.fromToken,
|
|
265
|
+
toToken: mockArgs.toToken,
|
|
266
|
+
fromAmount: 100000000000000000n,
|
|
267
|
+
network: "base-sepolia",
|
|
268
|
+
taker: "0x1234567890123456789012345678901234567890",
|
|
269
|
+
});
|
|
270
|
+
expect(parsedResult.success).toBe(true);
|
|
271
|
+
});
|
|
272
|
+
it("should return error for unsupported networks", async () => {
|
|
273
|
+
mockWalletProvider.getNetwork.mockReturnValue({
|
|
274
|
+
protocolFamily: "evm",
|
|
275
|
+
networkId: "ethereum-mainnet",
|
|
276
|
+
});
|
|
277
|
+
const result = await actionProvider.getSwapPrice(mockWalletProvider, mockArgs);
|
|
278
|
+
const parsedResult = JSON.parse(result);
|
|
279
|
+
expect(parsedResult.success).toBe(false);
|
|
280
|
+
expect(parsedResult.error).toContain("CDP Swap API for smart wallets is currently only supported on Base networks");
|
|
281
|
+
});
|
|
282
|
+
it("should handle swap price API errors", async () => {
|
|
283
|
+
mockWalletProvider.getNetwork.mockReturnValue({
|
|
284
|
+
protocolFamily: "evm",
|
|
285
|
+
networkId: "base-mainnet",
|
|
286
|
+
});
|
|
287
|
+
mockCdpClient.evm.getSwapPrice.mockRejectedValue(new Error("API Error"));
|
|
288
|
+
const result = await actionProvider.getSwapPrice(mockWalletProvider, mockArgs);
|
|
289
|
+
const parsedResult = JSON.parse(result);
|
|
290
|
+
expect(parsedResult.success).toBe(false);
|
|
291
|
+
expect(parsedResult.error).toContain("Error fetching swap price: Error: API Error");
|
|
292
|
+
});
|
|
293
|
+
});
|
|
294
|
+
describe("swap", () => {
|
|
295
|
+
const mockArgs = {
|
|
296
|
+
fromToken: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", // ETH
|
|
297
|
+
toToken: "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913", // USDC on Base
|
|
298
|
+
fromAmount: "0.1",
|
|
299
|
+
slippageBps: 100,
|
|
300
|
+
};
|
|
301
|
+
beforeEach(() => {
|
|
302
|
+
mockWalletProvider.getClient.mockReturnValue(mockCdpClient);
|
|
303
|
+
mockWalletProvider.getAddress.mockReturnValue("0x1234567890123456789012345678901234567890");
|
|
304
|
+
mockWalletProvider.waitForTransactionReceipt.mockResolvedValue({ status: "complete" });
|
|
305
|
+
mockWalletProvider.getPaymasterUrl.mockReturnValue("https://paymaster.example");
|
|
306
|
+
mockGetTokenDetails.mockResolvedValue({
|
|
307
|
+
fromTokenDecimals: 18,
|
|
308
|
+
toTokenDecimals: 6,
|
|
309
|
+
fromTokenName: "ETH",
|
|
310
|
+
toTokenName: "USDC",
|
|
311
|
+
});
|
|
312
|
+
});
|
|
313
|
+
it("should execute swap on base-mainnet", async () => {
|
|
314
|
+
mockWalletProvider.getNetwork.mockReturnValue({
|
|
315
|
+
protocolFamily: "evm",
|
|
316
|
+
networkId: "base-mainnet",
|
|
317
|
+
});
|
|
318
|
+
mockCdpClient.evm.getSwapPrice.mockResolvedValue({
|
|
319
|
+
liquidityAvailable: true,
|
|
320
|
+
issues: {},
|
|
321
|
+
toAmount: "990000", // 0.99 USDC
|
|
322
|
+
minToAmount: "980000", // 0.98 USDC
|
|
323
|
+
});
|
|
324
|
+
mockSmartAccount.swap.mockResolvedValue({ userOpHash: "0xswap789" });
|
|
325
|
+
const result = await actionProvider.swap(mockWalletProvider, mockArgs);
|
|
326
|
+
const parsedResult = JSON.parse(result);
|
|
327
|
+
expect(mockSmartAccount.swap).toHaveBeenCalledWith({
|
|
328
|
+
network: "base",
|
|
329
|
+
fromToken: mockArgs.fromToken,
|
|
330
|
+
toToken: mockArgs.toToken,
|
|
331
|
+
fromAmount: 100000000000000000n, // 0.1 ETH in wei
|
|
332
|
+
slippageBps: 100,
|
|
333
|
+
paymasterUrl: "https://paymaster.example",
|
|
334
|
+
signerAddress: "0xowner123",
|
|
335
|
+
});
|
|
336
|
+
expect(parsedResult.success).toBe(true);
|
|
337
|
+
expect(parsedResult.transactionHash).toBe("0xswap789");
|
|
338
|
+
expect(parsedResult.fromAmount).toBe("0.1");
|
|
339
|
+
expect(parsedResult.toAmount).toBe("0.99");
|
|
340
|
+
});
|
|
341
|
+
it("should return error for unsupported networks", async () => {
|
|
342
|
+
mockWalletProvider.getNetwork.mockReturnValue({
|
|
343
|
+
protocolFamily: "evm",
|
|
344
|
+
networkId: "ethereum-mainnet",
|
|
345
|
+
});
|
|
346
|
+
const result = await actionProvider.swap(mockWalletProvider, mockArgs);
|
|
347
|
+
const parsedResult = JSON.parse(result);
|
|
348
|
+
expect(parsedResult.success).toBe(false);
|
|
349
|
+
expect(parsedResult.error).toContain("CDP Swap API for smart wallets is currently only supported on Base networks");
|
|
350
|
+
});
|
|
351
|
+
it("should throw error for local owner account", async () => {
|
|
352
|
+
mockWalletProvider.getNetwork.mockReturnValue({
|
|
353
|
+
protocolFamily: "evm",
|
|
354
|
+
networkId: "base-mainnet",
|
|
355
|
+
});
|
|
356
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
357
|
+
mockWalletProvider.ownerAccount = {
|
|
358
|
+
type: "local",
|
|
359
|
+
address: "0xlocal123",
|
|
360
|
+
};
|
|
361
|
+
await expect(actionProvider.swap(mockWalletProvider, mockArgs)).rejects.toThrow("Smart wallet owner account is not a CDP server account");
|
|
362
|
+
});
|
|
363
|
+
it("should return error when liquidity is not available", async () => {
|
|
364
|
+
mockWalletProvider.getNetwork.mockReturnValue({
|
|
365
|
+
protocolFamily: "evm",
|
|
366
|
+
networkId: "base-mainnet",
|
|
367
|
+
});
|
|
368
|
+
mockCdpClient.evm.getSwapPrice.mockResolvedValue({
|
|
369
|
+
liquidityAvailable: false,
|
|
370
|
+
issues: {},
|
|
371
|
+
toAmount: "0",
|
|
372
|
+
minToAmount: "0",
|
|
373
|
+
});
|
|
374
|
+
const result = await actionProvider.swap(mockWalletProvider, mockArgs);
|
|
375
|
+
const parsedResult = JSON.parse(result);
|
|
376
|
+
expect(parsedResult.success).toBe(false);
|
|
377
|
+
expect(parsedResult.error).toContain("No liquidity available to swap");
|
|
378
|
+
});
|
|
379
|
+
it("should return error when balance is insufficient", async () => {
|
|
380
|
+
mockWalletProvider.getNetwork.mockReturnValue({
|
|
381
|
+
protocolFamily: "evm",
|
|
382
|
+
networkId: "base-mainnet",
|
|
383
|
+
});
|
|
384
|
+
mockCdpClient.evm.getSwapPrice.mockResolvedValue({
|
|
385
|
+
liquidityAvailable: true,
|
|
386
|
+
issues: {
|
|
387
|
+
balance: {
|
|
388
|
+
currentBalance: "50000000000000000", // 0.05 ETH
|
|
389
|
+
},
|
|
390
|
+
},
|
|
391
|
+
toAmount: "990000",
|
|
392
|
+
minToAmount: "980000",
|
|
393
|
+
});
|
|
394
|
+
const result = await actionProvider.swap(mockWalletProvider, mockArgs);
|
|
395
|
+
const parsedResult = JSON.parse(result);
|
|
396
|
+
expect(parsedResult.success).toBe(false);
|
|
397
|
+
expect(parsedResult.error).toContain("Balance is not enough to perform swap");
|
|
398
|
+
expect(parsedResult.error).toContain("but only have 0.05 ETH");
|
|
399
|
+
});
|
|
400
|
+
it("should handle approval transaction when allowance is insufficient", async () => {
|
|
401
|
+
mockWalletProvider.getNetwork.mockReturnValue({
|
|
402
|
+
protocolFamily: "evm",
|
|
403
|
+
networkId: "base-mainnet",
|
|
404
|
+
});
|
|
405
|
+
mockCdpClient.evm.getSwapPrice.mockResolvedValue({
|
|
406
|
+
liquidityAvailable: true,
|
|
407
|
+
issues: {
|
|
408
|
+
allowance: {
|
|
409
|
+
requiredAllowance: "100000000000000000",
|
|
410
|
+
currentAllowance: "0",
|
|
411
|
+
},
|
|
412
|
+
},
|
|
413
|
+
toAmount: "990000",
|
|
414
|
+
minToAmount: "980000",
|
|
415
|
+
});
|
|
416
|
+
mockWalletProvider.sendTransaction.mockResolvedValue("0xapproval123");
|
|
417
|
+
mockWalletProvider.waitForTransactionReceipt.mockResolvedValueOnce({ status: "complete" }); // For approval
|
|
418
|
+
mockWalletProvider.waitForTransactionReceipt.mockResolvedValueOnce({ status: "complete" }); // For swap
|
|
419
|
+
mockSmartAccount.swap.mockResolvedValue({ userOpHash: "0xswap789" });
|
|
420
|
+
const result = await actionProvider.swap(mockWalletProvider, mockArgs);
|
|
421
|
+
const parsedResult = JSON.parse(result);
|
|
422
|
+
expect(mockWalletProvider.sendTransaction).toHaveBeenCalled();
|
|
423
|
+
expect(parsedResult.success).toBe(true);
|
|
424
|
+
expect(parsedResult.approvalTxHash).toBe("0xapproval123");
|
|
425
|
+
expect(parsedResult.transactionHash).toBe("0xswap789");
|
|
426
|
+
});
|
|
427
|
+
it("should handle swap execution errors", async () => {
|
|
428
|
+
mockWalletProvider.getNetwork.mockReturnValue({
|
|
429
|
+
protocolFamily: "evm",
|
|
430
|
+
networkId: "base-mainnet",
|
|
431
|
+
});
|
|
432
|
+
mockCdpClient.evm.getSwapPrice.mockResolvedValue({
|
|
433
|
+
liquidityAvailable: true,
|
|
434
|
+
issues: {},
|
|
435
|
+
toAmount: "990000",
|
|
436
|
+
minToAmount: "980000",
|
|
437
|
+
});
|
|
438
|
+
mockSmartAccount.swap.mockRejectedValue(new Error("Swap execution failed"));
|
|
439
|
+
const result = await actionProvider.swap(mockWalletProvider, mockArgs);
|
|
440
|
+
const parsedResult = JSON.parse(result);
|
|
441
|
+
expect(parsedResult.success).toBe(false);
|
|
442
|
+
expect(parsedResult.error).toContain("Swap failed: Error: Swap execution failed");
|
|
443
|
+
});
|
|
444
|
+
});
|
|
191
445
|
describe("supportsNetwork", () => {
|
|
192
446
|
it("should return true for any network", () => {
|
|
193
447
|
const evmNetwork = { protocolFamily: "evm", networkId: "base-sepolia" };
|
|
@@ -13,20 +13,20 @@ export declare const RequestFaucetFundsV2Schema: z.ZodObject<{
|
|
|
13
13
|
* Input schema for swap tokens action.
|
|
14
14
|
*/
|
|
15
15
|
export declare const SwapSchema: z.ZodObject<{
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
fromToken: z.ZodString;
|
|
17
|
+
toToken: z.ZodString;
|
|
18
|
+
fromAmount: z.ZodString;
|
|
19
|
+
slippageBps: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
20
20
|
}, "strip", z.ZodTypeAny, {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
21
|
+
fromToken: string;
|
|
22
|
+
toToken: string;
|
|
23
|
+
fromAmount: string;
|
|
24
|
+
slippageBps: number;
|
|
25
25
|
}, {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
26
|
+
fromToken: string;
|
|
27
|
+
toToken: string;
|
|
28
|
+
fromAmount: string;
|
|
29
|
+
slippageBps?: number | undefined;
|
|
30
30
|
}>;
|
|
31
31
|
/**
|
|
32
32
|
* Input schema for listing spend permissions action.
|
|
@@ -16,13 +16,25 @@ exports.RequestFaucetFundsV2Schema = zod_1.z
|
|
|
16
16
|
*/
|
|
17
17
|
exports.SwapSchema = zod_1.z
|
|
18
18
|
.object({
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
fromToken: zod_1.z
|
|
20
|
+
.string()
|
|
21
|
+
.regex(/^0x[a-fA-F0-9]{40}$/, "Invalid Ethereum address format")
|
|
22
|
+
.describe("The token contract address to swap from"),
|
|
23
|
+
toToken: zod_1.z
|
|
24
|
+
.string()
|
|
25
|
+
.regex(/^0x[a-fA-F0-9]{40}$/, "Invalid Ethereum address format")
|
|
26
|
+
.describe("The token contract address to swap to"),
|
|
27
|
+
fromAmount: zod_1.z
|
|
23
28
|
.string()
|
|
29
|
+
.describe("The amount of fromToken to sell in whole units (e.g., 1.5 WETH, 10.5 USDC)"),
|
|
30
|
+
slippageBps: zod_1.z
|
|
31
|
+
.number()
|
|
32
|
+
.int()
|
|
33
|
+
.min(0)
|
|
34
|
+
.max(10000)
|
|
24
35
|
.optional()
|
|
25
|
-
.
|
|
36
|
+
.default(100)
|
|
37
|
+
.describe("The maximum acceptable slippage in basis points (0-10000, default: 100 = 1%)"),
|
|
26
38
|
})
|
|
27
39
|
.strip()
|
|
28
40
|
.describe("Instructions for swapping tokens");
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { EvmWalletProvider } from "../../wallet-providers";
|
|
2
|
+
export declare const PERMIT2_ADDRESS = "0x000000000022D473030F116dDEE9F6B43aC78BA3";
|
|
3
|
+
/**
|
|
4
|
+
* Checks if a token is native ETH.
|
|
5
|
+
*
|
|
6
|
+
* @param token - The token address to check.
|
|
7
|
+
* @returns True if the token is native ETH, false otherwise.
|
|
8
|
+
*/
|
|
9
|
+
export declare function isNativeEth(token: string): boolean;
|
|
10
|
+
/**
|
|
11
|
+
* Gets the details (decimals and name) for both fromToken and toToken
|
|
12
|
+
*
|
|
13
|
+
* @param walletProvider - The EVM wallet provider to read contracts
|
|
14
|
+
* @param fromToken - The contract address of the from token
|
|
15
|
+
* @param toToken - The contract address of the to token
|
|
16
|
+
* @returns Promise<{fromTokenDecimals: number, toTokenDecimals: number, fromTokenName: string, toTokenName: string}>
|
|
17
|
+
*/
|
|
18
|
+
export declare function getTokenDetails(walletProvider: EvmWalletProvider, fromToken: string, toToken: string): Promise<{
|
|
19
|
+
fromTokenDecimals: number;
|
|
20
|
+
toTokenDecimals: number;
|
|
21
|
+
fromTokenName: string;
|
|
22
|
+
toTokenName: string;
|
|
23
|
+
}>;
|
|
24
|
+
/**
|
|
25
|
+
* Retry function with exponential backoff
|
|
26
|
+
*
|
|
27
|
+
* @param fn - The function to retry
|
|
28
|
+
* @param maxRetries - Maximum number of retries (default: 3)
|
|
29
|
+
* @param baseDelay - Base delay in milliseconds (default: 1000)
|
|
30
|
+
* @returns Promise that resolves with the function result or rejects with the last error
|
|
31
|
+
*/
|
|
32
|
+
export declare function retryWithExponentialBackoff<T>(fn: () => Promise<T>, maxRetries?: number, baseDelay?: number): Promise<T>;
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PERMIT2_ADDRESS = void 0;
|
|
4
|
+
exports.isNativeEth = isNativeEth;
|
|
5
|
+
exports.getTokenDetails = getTokenDetails;
|
|
6
|
+
exports.retryWithExponentialBackoff = retryWithExponentialBackoff;
|
|
7
|
+
const viem_1 = require("viem");
|
|
8
|
+
// Permit2 contract address is the same across all networks
|
|
9
|
+
exports.PERMIT2_ADDRESS = "0x000000000022D473030F116dDEE9F6B43aC78BA3";
|
|
10
|
+
/**
|
|
11
|
+
* Checks if a token is native ETH.
|
|
12
|
+
*
|
|
13
|
+
* @param token - The token address to check.
|
|
14
|
+
* @returns True if the token is native ETH, false otherwise.
|
|
15
|
+
*/
|
|
16
|
+
function isNativeEth(token) {
|
|
17
|
+
return token.toLowerCase() === "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee";
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Gets the details (decimals and name) for both fromToken and toToken
|
|
21
|
+
*
|
|
22
|
+
* @param walletProvider - The EVM wallet provider to read contracts
|
|
23
|
+
* @param fromToken - The contract address of the from token
|
|
24
|
+
* @param toToken - The contract address of the to token
|
|
25
|
+
* @returns Promise<{fromTokenDecimals: number, toTokenDecimals: number, fromTokenName: string, toTokenName: string}>
|
|
26
|
+
*/
|
|
27
|
+
async function getTokenDetails(walletProvider, fromToken, toToken) {
|
|
28
|
+
// Initialize default values for native ETH
|
|
29
|
+
let fromTokenDecimals = 18;
|
|
30
|
+
let fromTokenName = "ETH";
|
|
31
|
+
let toTokenDecimals = 18;
|
|
32
|
+
let toTokenName = "ETH";
|
|
33
|
+
// Prepare multicall contracts array
|
|
34
|
+
const contracts = [];
|
|
35
|
+
const contractIndexMap = {
|
|
36
|
+
fromDecimals: -1,
|
|
37
|
+
fromName: -1,
|
|
38
|
+
toDecimals: -1,
|
|
39
|
+
toName: -1,
|
|
40
|
+
};
|
|
41
|
+
// Add from token contracts if not native ETH
|
|
42
|
+
if (!isNativeEth(fromToken)) {
|
|
43
|
+
contractIndexMap.fromDecimals = contracts.length;
|
|
44
|
+
contracts.push({
|
|
45
|
+
address: fromToken,
|
|
46
|
+
abi: viem_1.erc20Abi,
|
|
47
|
+
functionName: "decimals",
|
|
48
|
+
});
|
|
49
|
+
contractIndexMap.fromName = contracts.length;
|
|
50
|
+
contracts.push({
|
|
51
|
+
address: fromToken,
|
|
52
|
+
abi: viem_1.erc20Abi,
|
|
53
|
+
functionName: "name",
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
// Add to token contracts if not native ETH
|
|
57
|
+
if (!isNativeEth(toToken)) {
|
|
58
|
+
contractIndexMap.toDecimals = contracts.length;
|
|
59
|
+
contracts.push({
|
|
60
|
+
address: toToken,
|
|
61
|
+
abi: viem_1.erc20Abi,
|
|
62
|
+
functionName: "decimals",
|
|
63
|
+
});
|
|
64
|
+
contractIndexMap.toName = contracts.length;
|
|
65
|
+
contracts.push({
|
|
66
|
+
address: toToken,
|
|
67
|
+
abi: viem_1.erc20Abi,
|
|
68
|
+
functionName: "name",
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
// Execute multicall if there are contracts to call
|
|
72
|
+
if (contracts.length > 0) {
|
|
73
|
+
try {
|
|
74
|
+
const results = await walletProvider.getPublicClient().multicall({
|
|
75
|
+
contracts,
|
|
76
|
+
});
|
|
77
|
+
// Extract from token details
|
|
78
|
+
if (contractIndexMap.fromDecimals !== -1) {
|
|
79
|
+
const decimalsResult = results[contractIndexMap.fromDecimals];
|
|
80
|
+
const nameResult = results[contractIndexMap.fromName];
|
|
81
|
+
if (decimalsResult.status === "success" && nameResult.status === "success") {
|
|
82
|
+
fromTokenDecimals = decimalsResult.result;
|
|
83
|
+
fromTokenName = nameResult.result;
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
throw new Error(`Failed to read details for fromToken ${fromToken}. This address may not be a valid ERC20 contract.`);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
// Extract to token details
|
|
90
|
+
if (contractIndexMap.toDecimals !== -1) {
|
|
91
|
+
const decimalsResult = results[contractIndexMap.toDecimals];
|
|
92
|
+
const nameResult = results[contractIndexMap.toName];
|
|
93
|
+
if (decimalsResult.status === "success" && nameResult.status === "success") {
|
|
94
|
+
toTokenDecimals = decimalsResult.result;
|
|
95
|
+
toTokenName = nameResult.result;
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
throw new Error(`Failed to read details for toToken ${toToken}. This address may not be a valid ERC20 contract.`);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
catch (error) {
|
|
103
|
+
throw new Error(`Failed to read token details via multicall. Error: ${error}`);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return { fromTokenDecimals, toTokenDecimals, fromTokenName, toTokenName };
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Utility function to sleep for a given number of milliseconds
|
|
110
|
+
*
|
|
111
|
+
* @param ms - Number of milliseconds to sleep
|
|
112
|
+
* @returns Promise that resolves after the specified delay
|
|
113
|
+
*/
|
|
114
|
+
const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));
|
|
115
|
+
/**
|
|
116
|
+
* Retry function with exponential backoff
|
|
117
|
+
*
|
|
118
|
+
* @param fn - The function to retry
|
|
119
|
+
* @param maxRetries - Maximum number of retries (default: 3)
|
|
120
|
+
* @param baseDelay - Base delay in milliseconds (default: 1000)
|
|
121
|
+
* @returns Promise that resolves with the function result or rejects with the last error
|
|
122
|
+
*/
|
|
123
|
+
async function retryWithExponentialBackoff(fn, maxRetries = 3, baseDelay = 1000) {
|
|
124
|
+
let lastError;
|
|
125
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
126
|
+
// Wait before each attempt
|
|
127
|
+
// Calculate delay with exponential backoff: baseDelay * 2^attempt
|
|
128
|
+
const delay = baseDelay * Math.pow(2, attempt);
|
|
129
|
+
await sleep(delay);
|
|
130
|
+
try {
|
|
131
|
+
return await fn();
|
|
132
|
+
}
|
|
133
|
+
catch (error) {
|
|
134
|
+
lastError = error;
|
|
135
|
+
// If this was the last attempt, throw the error
|
|
136
|
+
if (attempt === maxRetries) {
|
|
137
|
+
throw lastError;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
throw lastError;
|
|
142
|
+
}
|
|
@@ -34,6 +34,7 @@ __exportStar(require("./moonwell"), exports);
|
|
|
34
34
|
__exportStar(require("./morpho"), exports);
|
|
35
35
|
__exportStar(require("./opensea"), exports);
|
|
36
36
|
__exportStar(require("./spl"), exports);
|
|
37
|
+
__exportStar(require("./superfluid"), exports);
|
|
37
38
|
__exportStar(require("./truemarkets"), exports);
|
|
38
39
|
__exportStar(require("./twitter"), exports);
|
|
39
40
|
__exportStar(require("./wallet"), exports);
|
|
@@ -9,9 +9,9 @@ export declare const SwapTokenSchema: z.ZodObject<{
|
|
|
9
9
|
slippageBps: z.ZodDefault<z.ZodNumber>;
|
|
10
10
|
}, "strip", z.ZodTypeAny, {
|
|
11
11
|
amount: number;
|
|
12
|
+
slippageBps: number;
|
|
12
13
|
inputMint: string;
|
|
13
14
|
outputMint: string;
|
|
14
|
-
slippageBps: number;
|
|
15
15
|
}, {
|
|
16
16
|
amount: number;
|
|
17
17
|
inputMint: string;
|