@coinbase/agentkit 0.9.1 → 0.10.1

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 (151) hide show
  1. package/README.md +181 -54
  2. package/dist/action-providers/across/acrossActionProvider.js +3 -3
  3. package/dist/action-providers/cdp/cdpApiActionProvider.d.ts +3 -12
  4. package/dist/action-providers/cdp/cdpApiActionProvider.js +2 -79
  5. package/dist/action-providers/cdp/cdpApiActionProvider.test.js +0 -125
  6. package/dist/action-providers/cdp/cdpEvmWalletActionProvider.d.ts +58 -0
  7. package/dist/action-providers/cdp/cdpEvmWalletActionProvider.js +351 -0
  8. package/dist/action-providers/cdp/cdpEvmWalletActionProvider.test.d.ts +1 -0
  9. package/dist/action-providers/cdp/cdpEvmWalletActionProvider.test.js +520 -0
  10. package/dist/action-providers/cdp/cdpSmartWalletActionProvider.d.ts +57 -0
  11. package/dist/action-providers/cdp/cdpSmartWalletActionProvider.js +337 -0
  12. package/dist/action-providers/cdp/cdpSmartWalletActionProvider.test.d.ts +1 -0
  13. package/dist/action-providers/cdp/cdpSmartWalletActionProvider.test.js +463 -0
  14. package/dist/action-providers/cdp/index.d.ts +3 -0
  15. package/dist/action-providers/cdp/index.js +3 -0
  16. package/dist/action-providers/cdp/schemas.d.ts +38 -9
  17. package/dist/action-providers/cdp/schemas.js +49 -6
  18. package/dist/action-providers/cdp/spendPermissionUtils.d.ts +24 -0
  19. package/dist/action-providers/cdp/spendPermissionUtils.js +66 -0
  20. package/dist/action-providers/cdp/swapUtils.d.ts +32 -0
  21. package/dist/action-providers/cdp/swapUtils.js +142 -0
  22. package/dist/action-providers/clanker/clankerActionProvider.d.ts +43 -0
  23. package/dist/action-providers/clanker/clankerActionProvider.js +130 -0
  24. package/dist/action-providers/clanker/clankerActionProvider.test.d.ts +4 -0
  25. package/dist/action-providers/clanker/clankerActionProvider.test.js +119 -0
  26. package/dist/action-providers/clanker/index.d.ts +2 -0
  27. package/dist/action-providers/clanker/index.js +18 -0
  28. package/dist/action-providers/clanker/schemas.d.ts +56 -0
  29. package/dist/action-providers/clanker/schemas.js +47 -0
  30. package/dist/action-providers/clanker/utils.d.ts +9 -0
  31. package/dist/action-providers/clanker/utils.js +23 -0
  32. package/dist/action-providers/compound/constants.d.ts +1 -1
  33. package/dist/action-providers/compound/constants.js +2 -2
  34. package/dist/action-providers/erc20/constants.d.ts +35 -135
  35. package/dist/action-providers/erc20/constants.js +37 -189
  36. package/dist/action-providers/erc20/erc20ActionProvider.d.ts +9 -1
  37. package/dist/action-providers/erc20/erc20ActionProvider.js +87 -35
  38. package/dist/action-providers/erc20/erc20ActionProvider.test.js +115 -52
  39. package/dist/action-providers/erc20/schemas.d.ts +25 -12
  40. package/dist/action-providers/erc20/schemas.js +34 -6
  41. package/dist/action-providers/erc20/utils.d.ts +19 -0
  42. package/dist/action-providers/erc20/utils.js +54 -0
  43. package/dist/action-providers/flaunch/constants.d.ts +1 -1
  44. package/dist/action-providers/flaunch/constants.js +2 -2
  45. package/dist/action-providers/flaunch/flaunchActionProvider.js +3 -11
  46. package/dist/action-providers/flaunch/flaunchActionProvider.test.js +5 -0
  47. package/dist/action-providers/index.d.ts +4 -0
  48. package/dist/action-providers/index.js +4 -0
  49. package/dist/action-providers/jupiter/schemas.d.ts +1 -1
  50. package/dist/action-providers/moonwell/schemas.d.ts +2 -2
  51. package/dist/action-providers/morpho/morphoActionProvider.js +5 -5
  52. package/dist/action-providers/morpho/schemas.d.ts +2 -2
  53. package/dist/action-providers/pyth/pythActionProvider.js +5 -0
  54. package/dist/action-providers/pyth/pythActionProvider.test.js +5 -1
  55. package/dist/action-providers/superfluid/constants.d.ts +814 -0
  56. package/dist/action-providers/superfluid/constants.js +2826 -0
  57. package/dist/action-providers/superfluid/graphQueries/endpoints.d.ts +2 -0
  58. package/dist/action-providers/superfluid/graphQueries/endpoints.js +5 -0
  59. package/dist/action-providers/superfluid/graphQueries/queries.d.ts +1 -0
  60. package/dist/action-providers/superfluid/graphQueries/queries.js +35 -0
  61. package/dist/action-providers/superfluid/graphQueries/superfluidGraphQueries.d.ts +8 -0
  62. package/dist/action-providers/superfluid/graphQueries/superfluidGraphQueries.js +24 -0
  63. package/dist/action-providers/superfluid/graphQueries/types.d.ts +27 -0
  64. package/dist/action-providers/superfluid/graphQueries/types.js +2 -0
  65. package/dist/action-providers/superfluid/index.d.ts +7 -0
  66. package/dist/action-providers/superfluid/index.js +23 -0
  67. package/dist/action-providers/superfluid/schemas.d.ts +86 -0
  68. package/dist/action-providers/superfluid/schemas.js +103 -0
  69. package/dist/action-providers/superfluid/superfluidActionProvider.d.ts +20 -0
  70. package/dist/action-providers/superfluid/superfluidActionProvider.js +36 -0
  71. package/dist/action-providers/superfluid/superfluidPoolActionProvider.d.ts +46 -0
  72. package/dist/action-providers/superfluid/superfluidPoolActionProvider.js +143 -0
  73. package/dist/action-providers/superfluid/superfluidPoolActionProvider.test.d.ts +1 -0
  74. package/dist/action-providers/superfluid/superfluidPoolActionProvider.test.js +92 -0
  75. package/dist/action-providers/superfluid/superfluidQueryActionProvider.d.ts +27 -0
  76. package/dist/action-providers/superfluid/superfluidQueryActionProvider.js +71 -0
  77. package/dist/action-providers/superfluid/superfluidQueryActionProvider.test.d.ts +1 -0
  78. package/dist/action-providers/superfluid/superfluidQueryActionProvider.test.js +57 -0
  79. package/dist/action-providers/superfluid/superfluidStreamActionProvider.d.ts +56 -0
  80. package/dist/action-providers/superfluid/superfluidStreamActionProvider.js +191 -0
  81. package/dist/action-providers/superfluid/superfluidStreamActionProvider.test.d.ts +1 -0
  82. package/dist/action-providers/superfluid/superfluidStreamActionProvider.test.js +80 -0
  83. package/dist/action-providers/superfluid/superfluidSuperTokenCreatorActionProvider.d.ts +30 -0
  84. package/dist/action-providers/superfluid/superfluidSuperTokenCreatorActionProvider.js +108 -0
  85. package/dist/action-providers/superfluid/superfluidSuperTokenCreatorActionProvider.test.d.ts +1 -0
  86. package/dist/action-providers/superfluid/superfluidSuperTokenCreatorActionProvider.test.js +75 -0
  87. package/dist/action-providers/superfluid/superfluidWrapperActionProvider.d.ts +32 -0
  88. package/dist/action-providers/superfluid/superfluidWrapperActionProvider.js +101 -0
  89. package/dist/action-providers/superfluid/superfluidWrapperActionProvider.test.d.ts +1 -0
  90. package/dist/action-providers/superfluid/superfluidWrapperActionProvider.test.js +85 -0
  91. package/dist/action-providers/superfluid/utils/parseLogs.d.ts +18 -0
  92. package/dist/action-providers/superfluid/utils/parseLogs.js +78 -0
  93. package/dist/action-providers/truemarkets/truemarketsActionProvider.d.ts +4 -16
  94. package/dist/action-providers/truemarkets/truemarketsActionProvider.js +20 -41
  95. package/dist/action-providers/truemarkets/truemarketsActionProvider.test.js +11 -33
  96. package/dist/action-providers/wallet/walletActionProvider.js +21 -10
  97. package/dist/action-providers/wallet/walletActionProvider.test.js +6 -2
  98. package/dist/action-providers/zerion/constants.d.ts +1 -0
  99. package/dist/action-providers/zerion/constants.js +4 -0
  100. package/dist/action-providers/zerion/index.d.ts +2 -0
  101. package/dist/action-providers/zerion/index.js +18 -0
  102. package/dist/action-providers/zerion/schemas.d.ts +11 -0
  103. package/dist/action-providers/zerion/schemas.js +15 -0
  104. package/dist/action-providers/zerion/types.d.ts +125 -0
  105. package/dist/action-providers/zerion/types.js +16 -0
  106. package/dist/action-providers/zerion/utils.d.ts +3 -0
  107. package/dist/action-providers/zerion/utils.js +45 -0
  108. package/dist/action-providers/zerion/zerionActionProvider.d.ts +57 -0
  109. package/dist/action-providers/zerion/zerionActionProvider.js +159 -0
  110. package/dist/action-providers/zerion/zerionActionProvider.test.d.ts +1 -0
  111. package/dist/action-providers/zerion/zerionActionProvider.test.js +213 -0
  112. package/dist/action-providers/zeroX/index.d.ts +1 -0
  113. package/dist/action-providers/zeroX/index.js +17 -0
  114. package/dist/action-providers/zeroX/schemas.d.ts +51 -0
  115. package/dist/action-providers/zeroX/schemas.js +82 -0
  116. package/dist/action-providers/zeroX/utils.d.ts +23 -0
  117. package/dist/action-providers/zeroX/utils.js +106 -0
  118. package/dist/action-providers/zeroX/zeroXActionProvider.d.ts +57 -0
  119. package/dist/action-providers/zeroX/zeroXActionProvider.js +407 -0
  120. package/dist/action-providers/zeroX/zeroXActionProvider.test.d.ts +1 -0
  121. package/dist/action-providers/zeroX/zeroXActionProvider.test.js +445 -0
  122. package/dist/wallet-providers/cdpEvmWalletProvider.d.ts +20 -2
  123. package/dist/wallet-providers/cdpEvmWalletProvider.js +40 -15
  124. package/dist/wallet-providers/cdpShared.d.ts +9 -0
  125. package/dist/wallet-providers/cdpSmartWalletProvider.d.ts +29 -3
  126. package/dist/wallet-providers/cdpSmartWalletProvider.js +64 -28
  127. package/dist/wallet-providers/cdpSolanaWalletProvider.d.ts +1 -1
  128. package/dist/wallet-providers/cdpSolanaWalletProvider.js +7 -7
  129. package/dist/wallet-providers/cdpSolanaWalletProvider.test.js +15 -12
  130. package/dist/wallet-providers/evmWalletProvider.d.ts +5 -1
  131. package/dist/wallet-providers/legacyCdpSmartWalletProvider.d.ts +9 -2
  132. package/dist/wallet-providers/legacyCdpSmartWalletProvider.js +12 -2
  133. package/dist/wallet-providers/legacyCdpWalletProvider.d.ts +12 -2
  134. package/dist/wallet-providers/legacyCdpWalletProvider.js +11 -2
  135. package/dist/wallet-providers/privyEvmDelegatedEmbeddedWalletProvider.d.ts +10 -2
  136. package/dist/wallet-providers/privyEvmDelegatedEmbeddedWalletProvider.js +12 -3
  137. package/dist/wallet-providers/privyEvmDelegatedEmbeddedWalletProvider.test.js +1 -1
  138. package/dist/wallet-providers/privyEvmWalletProvider.d.ts +2 -0
  139. package/dist/wallet-providers/privyEvmWalletProvider.js +2 -1
  140. package/dist/wallet-providers/privyEvmWalletProvider.test.js +1 -1
  141. package/dist/wallet-providers/solanaKeypairWalletProvider.d.ts +1 -1
  142. package/dist/wallet-providers/solanaKeypairWalletProvider.js +3 -4
  143. package/dist/wallet-providers/solanaKeypairWalletProvider.test.js +4 -2
  144. package/dist/wallet-providers/viemWalletProvider.d.ts +12 -2
  145. package/dist/wallet-providers/viemWalletProvider.js +12 -3
  146. package/dist/wallet-providers/viemWalletProvider.test.js +6 -5
  147. package/dist/wallet-providers/walletProvider.d.ts +1 -1
  148. package/dist/wallet-providers/zeroDevWalletProvider.d.ts +10 -2
  149. package/dist/wallet-providers/zeroDevWalletProvider.js +14 -5
  150. package/dist/wallet-providers/zeroDevWalletProvider.test.js +2 -2
  151. package/package.json +4 -2
@@ -0,0 +1,463 @@
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
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ const cdpSmartWalletActionProvider_1 = require("./cdpSmartWalletActionProvider");
37
+ const schemas_1 = require("./schemas");
38
+ const spendPermissionUtils = __importStar(require("./spendPermissionUtils"));
39
+ const swapUtils = __importStar(require("./swapUtils"));
40
+ // Mock the CDP SDK and utility functions
41
+ jest.mock("@coinbase/cdp-sdk");
42
+ jest.mock("./spendPermissionUtils");
43
+ jest.mock("./swapUtils");
44
+ describe("CDP Smart Wallet Action Provider", () => {
45
+ let actionProvider;
46
+ let mockWalletProvider;
47
+ let mockCdpClient;
48
+ let mockSmartAccount;
49
+ const mockGetTokenDetails = swapUtils.getTokenDetails;
50
+ const mockRetryWithExponentialBackoff = swapUtils.retryWithExponentialBackoff;
51
+ beforeEach(() => {
52
+ jest.clearAllMocks();
53
+ mockSmartAccount = {
54
+ useSpendPermission: jest.fn(),
55
+ swap: jest.fn(),
56
+ address: "0x1234567890123456789012345678901234567890",
57
+ };
58
+ mockCdpClient = {
59
+ evm: {
60
+ listSpendPermissions: jest.fn(),
61
+ getSwapPrice: jest.fn(),
62
+ },
63
+ };
64
+ mockWalletProvider = {
65
+ getNetwork: jest.fn(),
66
+ getAddress: jest.fn(),
67
+ getClient: jest.fn(),
68
+ smartAccount: mockSmartAccount,
69
+ ownerAccount: {
70
+ type: "server",
71
+ address: "0xowner123",
72
+ },
73
+ sendTransaction: jest.fn(),
74
+ waitForTransactionReceipt: jest.fn(),
75
+ getPaymasterUrl: jest.fn(),
76
+ getCdpSdkNetwork: jest.fn(),
77
+ };
78
+ // Default setup for utility functions
79
+ mockRetryWithExponentialBackoff.mockImplementation(async (fn) => {
80
+ return await fn();
81
+ });
82
+ actionProvider = new cdpSmartWalletActionProvider_1.CdpSmartWalletActionProvider();
83
+ });
84
+ describe("listSpendPermissions", () => {
85
+ const mockArgs = {
86
+ smartAccountAddress: "0xabcd1234567890123456789012345678901234567890",
87
+ };
88
+ beforeEach(() => {
89
+ mockWalletProvider.getNetwork.mockReturnValue({
90
+ protocolFamily: "evm",
91
+ networkId: "base-sepolia",
92
+ });
93
+ mockWalletProvider.getAddress.mockReturnValue("0x1234567890123456789012345678901234567890");
94
+ mockWalletProvider.getClient.mockReturnValue(mockCdpClient);
95
+ mockWalletProvider.getCdpSdkNetwork.mockReturnValue("base-sepolia");
96
+ });
97
+ it("should successfully list spend permissions for EVM networks", async () => {
98
+ const expectedResult = "Found 1 spend permission(s):\n1. Token: ETH, Allowance: 1000, Period: 3600 seconds, Start: 123456, End: 234567";
99
+ spendPermissionUtils.listSpendPermissionsForSpender.mockResolvedValue(expectedResult);
100
+ const result = await actionProvider.listSpendPermissions(mockWalletProvider, mockArgs);
101
+ expect(spendPermissionUtils.listSpendPermissionsForSpender).toHaveBeenCalledWith(mockCdpClient, mockArgs.smartAccountAddress, "0x1234567890123456789012345678901234567890");
102
+ expect(result).toBe(expectedResult);
103
+ });
104
+ it("should return error message for non-EVM networks", async () => {
105
+ mockWalletProvider.getNetwork.mockReturnValue({
106
+ protocolFamily: "svm",
107
+ networkId: "solana-devnet",
108
+ });
109
+ const result = await actionProvider.listSpendPermissions(mockWalletProvider, mockArgs);
110
+ expect(result).toBe("Spend permissions are currently only supported on EVM networks.");
111
+ expect(spendPermissionUtils.listSpendPermissionsForSpender).not.toHaveBeenCalled();
112
+ });
113
+ it("should validate input schema", () => {
114
+ const validInput = { smartAccountAddress: "0xabcd1234567890123456789012345678901234567890" };
115
+ const invalidInput = { invalidField: "invalid" };
116
+ expect(() => schemas_1.ListSpendPermissionsSchema.parse(validInput)).not.toThrow();
117
+ expect(() => schemas_1.ListSpendPermissionsSchema.parse(invalidInput)).toThrow();
118
+ });
119
+ });
120
+ describe("useSpendPermission", () => {
121
+ const mockArgs = {
122
+ smartAccountAddress: "0xabcd1234567890123456789012345678901234567890",
123
+ value: "1000",
124
+ };
125
+ beforeEach(() => {
126
+ mockWalletProvider.getNetwork.mockReturnValue({
127
+ protocolFamily: "evm",
128
+ networkId: "base-sepolia",
129
+ });
130
+ mockWalletProvider.getAddress.mockReturnValue("0x1234567890123456789012345678901234567890");
131
+ mockWalletProvider.getClient.mockReturnValue(mockCdpClient);
132
+ mockWalletProvider.getCdpSdkNetwork.mockReturnValue("base-sepolia");
133
+ });
134
+ it("should successfully use spend permission for EVM networks", async () => {
135
+ const mockPermission = {
136
+ spender: "0x1234567890123456789012345678901234567890",
137
+ token: "ETH",
138
+ allowance: "1000",
139
+ period: 3600,
140
+ start: 123456,
141
+ end: 234567,
142
+ };
143
+ const mockSpendResult = {
144
+ status: "completed",
145
+ transactionHash: "0xabcd1234",
146
+ };
147
+ spendPermissionUtils.findLatestSpendPermission.mockResolvedValue(mockPermission);
148
+ mockSmartAccount.useSpendPermission.mockResolvedValue(mockSpendResult);
149
+ const result = await actionProvider.useSpendPermission(mockWalletProvider, mockArgs);
150
+ expect(spendPermissionUtils.findLatestSpendPermission).toHaveBeenCalledWith(mockCdpClient, mockArgs.smartAccountAddress, "0x1234567890123456789012345678901234567890");
151
+ expect(mockSmartAccount.useSpendPermission).toHaveBeenCalledWith({
152
+ spendPermission: mockPermission,
153
+ value: BigInt(1000),
154
+ network: "base-sepolia",
155
+ });
156
+ expect(result).toBe("Successfully spent 1000 tokens using spend permission. Status: completed");
157
+ });
158
+ it("should handle base-mainnet network conversion", async () => {
159
+ mockWalletProvider.getNetwork.mockReturnValue({
160
+ protocolFamily: "evm",
161
+ networkId: "base-mainnet",
162
+ });
163
+ mockWalletProvider.getCdpSdkNetwork.mockReturnValue("base");
164
+ const mockPermission = { spender: "0x1234", token: "ETH" };
165
+ const mockSpendResult = { status: "completed" };
166
+ spendPermissionUtils.findLatestSpendPermission.mockResolvedValue(mockPermission);
167
+ mockSmartAccount.useSpendPermission.mockResolvedValue(mockSpendResult);
168
+ await actionProvider.useSpendPermission(mockWalletProvider, mockArgs);
169
+ expect(mockSmartAccount.useSpendPermission).toHaveBeenCalledWith({
170
+ spendPermission: mockPermission,
171
+ value: BigInt(1000),
172
+ network: "base",
173
+ });
174
+ });
175
+ it("should throw error for unsupported networks", async () => {
176
+ mockWalletProvider.getNetwork.mockReturnValue({
177
+ protocolFamily: "evm",
178
+ networkId: "ethereum-mainnet",
179
+ });
180
+ mockWalletProvider.getCdpSdkNetwork.mockImplementation(() => {
181
+ throw new Error("Unsupported network for smart wallets: ethereum-mainnet");
182
+ });
183
+ await expect(actionProvider.useSpendPermission(mockWalletProvider, mockArgs)).rejects.toThrow("Unsupported network for smart wallets: ethereum-mainnet");
184
+ });
185
+ it("should return error message for non-EVM networks", async () => {
186
+ mockWalletProvider.getNetwork.mockReturnValue({
187
+ protocolFamily: "svm",
188
+ networkId: "solana-devnet",
189
+ });
190
+ await expect(actionProvider.useSpendPermission(mockWalletProvider, mockArgs)).rejects.toThrow("Spend permissions are currently only supported on EVM networks.");
191
+ });
192
+ it("should handle spend permission not found error", async () => {
193
+ spendPermissionUtils.findLatestSpendPermission.mockRejectedValue(new Error("No spend permissions found"));
194
+ await expect(actionProvider.useSpendPermission(mockWalletProvider, mockArgs)).rejects.toThrow("Failed to use spend permission: Error: No spend permissions found");
195
+ });
196
+ it("should handle smart account use permission failure", async () => {
197
+ const mockPermission = { spender: "0x1234", token: "ETH" };
198
+ spendPermissionUtils.findLatestSpendPermission.mockResolvedValue(mockPermission);
199
+ mockSmartAccount.useSpendPermission.mockRejectedValue(new Error("Transaction failed"));
200
+ await expect(actionProvider.useSpendPermission(mockWalletProvider, mockArgs)).rejects.toThrow("Failed to use spend permission: Error: Transaction failed");
201
+ });
202
+ it("should validate input schema", () => {
203
+ const validInput = {
204
+ smartAccountAddress: "0xabcd1234567890123456789012345678901234567890",
205
+ value: "1000",
206
+ };
207
+ const invalidInput = {
208
+ wrongField: "0xabcd1234567890123456789012345678901234567890",
209
+ // Missing required fields
210
+ };
211
+ expect(() => schemas_1.UseSpendPermissionSchema.parse(validInput)).not.toThrow();
212
+ expect(() => schemas_1.UseSpendPermissionSchema.parse(invalidInput)).toThrow();
213
+ });
214
+ });
215
+ describe("getSwapPrice", () => {
216
+ const mockArgs = {
217
+ fromToken: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", // ETH
218
+ toToken: "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913", // USDC on Base
219
+ fromAmount: "0.1",
220
+ slippageBps: 100,
221
+ };
222
+ beforeEach(() => {
223
+ mockWalletProvider.getClient.mockReturnValue(mockCdpClient);
224
+ mockWalletProvider.getAddress.mockReturnValue("0x1234567890123456789012345678901234567890");
225
+ mockWalletProvider.getCdpSdkNetwork.mockReturnValue("base");
226
+ mockGetTokenDetails.mockResolvedValue({
227
+ fromTokenDecimals: 18,
228
+ toTokenDecimals: 6,
229
+ fromTokenName: "ETH",
230
+ toTokenName: "USDC",
231
+ });
232
+ });
233
+ it("should get swap price quote on base-mainnet", async () => {
234
+ mockWalletProvider.getNetwork.mockReturnValue({
235
+ protocolFamily: "evm",
236
+ networkId: "base-mainnet",
237
+ });
238
+ mockCdpClient.evm.getSwapPrice.mockResolvedValue({
239
+ toAmount: "990000", // 0.99 USDC
240
+ minToAmount: "980000", // 0.98 USDC
241
+ liquidityAvailable: true,
242
+ issues: {},
243
+ });
244
+ const result = await actionProvider.getSwapPrice(mockWalletProvider, mockArgs);
245
+ const parsedResult = JSON.parse(result);
246
+ expect(mockCdpClient.evm.getSwapPrice).toHaveBeenCalledWith({
247
+ fromToken: mockArgs.fromToken,
248
+ toToken: mockArgs.toToken,
249
+ fromAmount: 100000000000000000n, // 0.1 ETH in wei
250
+ network: "base",
251
+ taker: "0x1234567890123456789012345678901234567890",
252
+ });
253
+ expect(parsedResult.success).toBe(true);
254
+ expect(parsedResult.fromAmount).toBe("0.1");
255
+ expect(parsedResult.toAmount).toBe("0.99");
256
+ expect(parsedResult.liquidityAvailable).toBe(true);
257
+ });
258
+ it("should get swap price quote on base-sepolia", async () => {
259
+ mockWalletProvider.getNetwork.mockReturnValue({
260
+ protocolFamily: "evm",
261
+ networkId: "base-sepolia",
262
+ });
263
+ mockWalletProvider.getCdpSdkNetwork.mockReturnValue("base-sepolia");
264
+ mockCdpClient.evm.getSwapPrice.mockResolvedValue({
265
+ toAmount: "990000",
266
+ minToAmount: "980000",
267
+ liquidityAvailable: true,
268
+ issues: {},
269
+ });
270
+ const result = await actionProvider.getSwapPrice(mockWalletProvider, mockArgs);
271
+ const parsedResult = JSON.parse(result);
272
+ expect(mockCdpClient.evm.getSwapPrice).toHaveBeenCalledWith({
273
+ fromToken: mockArgs.fromToken,
274
+ toToken: mockArgs.toToken,
275
+ fromAmount: 100000000000000000n,
276
+ network: "base-sepolia",
277
+ taker: "0x1234567890123456789012345678901234567890",
278
+ });
279
+ expect(parsedResult.success).toBe(true);
280
+ });
281
+ it("should return error for unsupported networks", async () => {
282
+ mockWalletProvider.getNetwork.mockReturnValue({
283
+ protocolFamily: "evm",
284
+ networkId: "ethereum-mainnet",
285
+ });
286
+ const result = await actionProvider.getSwapPrice(mockWalletProvider, mockArgs);
287
+ const parsedResult = JSON.parse(result);
288
+ expect(parsedResult.success).toBe(false);
289
+ expect(parsedResult.error).toContain("CDP Swap API for smart wallets is currently only supported on Base networks");
290
+ });
291
+ it("should handle swap price API errors", async () => {
292
+ mockWalletProvider.getNetwork.mockReturnValue({
293
+ protocolFamily: "evm",
294
+ networkId: "base-mainnet",
295
+ });
296
+ mockCdpClient.evm.getSwapPrice.mockRejectedValue(new Error("API Error"));
297
+ const result = await actionProvider.getSwapPrice(mockWalletProvider, mockArgs);
298
+ const parsedResult = JSON.parse(result);
299
+ expect(parsedResult.success).toBe(false);
300
+ expect(parsedResult.error).toContain("Error fetching swap price: Error: API Error");
301
+ });
302
+ });
303
+ describe("swap", () => {
304
+ const mockArgs = {
305
+ fromToken: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", // ETH
306
+ toToken: "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913", // USDC on Base
307
+ fromAmount: "0.1",
308
+ slippageBps: 100,
309
+ };
310
+ beforeEach(() => {
311
+ mockWalletProvider.getClient.mockReturnValue(mockCdpClient);
312
+ mockWalletProvider.getAddress.mockReturnValue("0x1234567890123456789012345678901234567890");
313
+ mockWalletProvider.getCdpSdkNetwork.mockReturnValue("base");
314
+ mockWalletProvider.waitForTransactionReceipt.mockResolvedValue({ status: "complete" });
315
+ mockWalletProvider.getPaymasterUrl.mockReturnValue("https://paymaster.example");
316
+ mockGetTokenDetails.mockResolvedValue({
317
+ fromTokenDecimals: 18,
318
+ toTokenDecimals: 6,
319
+ fromTokenName: "ETH",
320
+ toTokenName: "USDC",
321
+ });
322
+ });
323
+ it("should execute swap on base-mainnet", async () => {
324
+ mockWalletProvider.getNetwork.mockReturnValue({
325
+ protocolFamily: "evm",
326
+ networkId: "base-mainnet",
327
+ });
328
+ mockCdpClient.evm.getSwapPrice.mockResolvedValue({
329
+ liquidityAvailable: true,
330
+ issues: {},
331
+ toAmount: "990000", // 0.99 USDC
332
+ minToAmount: "980000", // 0.98 USDC
333
+ });
334
+ mockSmartAccount.swap.mockResolvedValue({ userOpHash: "0xswap789" });
335
+ const result = await actionProvider.swap(mockWalletProvider, mockArgs);
336
+ const parsedResult = JSON.parse(result);
337
+ expect(mockSmartAccount.swap).toHaveBeenCalledWith({
338
+ network: "base",
339
+ fromToken: mockArgs.fromToken,
340
+ toToken: mockArgs.toToken,
341
+ fromAmount: 100000000000000000n, // 0.1 ETH in wei
342
+ slippageBps: 100,
343
+ paymasterUrl: "https://paymaster.example",
344
+ signerAddress: "0xowner123",
345
+ });
346
+ expect(parsedResult.success).toBe(true);
347
+ expect(parsedResult.transactionHash).toBe("0xswap789");
348
+ expect(parsedResult.fromAmount).toBe("0.1");
349
+ expect(parsedResult.toAmount).toBe("0.99");
350
+ });
351
+ it("should return error for unsupported networks", async () => {
352
+ mockWalletProvider.getNetwork.mockReturnValue({
353
+ protocolFamily: "evm",
354
+ networkId: "ethereum-mainnet",
355
+ });
356
+ const result = await actionProvider.swap(mockWalletProvider, mockArgs);
357
+ const parsedResult = JSON.parse(result);
358
+ expect(parsedResult.success).toBe(false);
359
+ expect(parsedResult.error).toContain("CDP Swap API for smart wallets is currently only supported on Base networks");
360
+ });
361
+ it("should throw error for local owner account", async () => {
362
+ mockWalletProvider.getNetwork.mockReturnValue({
363
+ protocolFamily: "evm",
364
+ networkId: "base-mainnet",
365
+ });
366
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
367
+ mockWalletProvider.ownerAccount = {
368
+ type: "local",
369
+ address: "0xlocal123",
370
+ };
371
+ await expect(actionProvider.swap(mockWalletProvider, mockArgs)).rejects.toThrow("Smart wallet owner account is not a CDP server account");
372
+ });
373
+ it("should return error when liquidity is not available", async () => {
374
+ mockWalletProvider.getNetwork.mockReturnValue({
375
+ protocolFamily: "evm",
376
+ networkId: "base-mainnet",
377
+ });
378
+ mockCdpClient.evm.getSwapPrice.mockResolvedValue({
379
+ liquidityAvailable: false,
380
+ issues: {},
381
+ toAmount: "0",
382
+ minToAmount: "0",
383
+ });
384
+ const result = await actionProvider.swap(mockWalletProvider, mockArgs);
385
+ const parsedResult = JSON.parse(result);
386
+ expect(parsedResult.success).toBe(false);
387
+ expect(parsedResult.error).toContain("No liquidity available to swap");
388
+ });
389
+ it("should return error when balance is insufficient", async () => {
390
+ mockWalletProvider.getNetwork.mockReturnValue({
391
+ protocolFamily: "evm",
392
+ networkId: "base-mainnet",
393
+ });
394
+ mockCdpClient.evm.getSwapPrice.mockResolvedValue({
395
+ liquidityAvailable: true,
396
+ issues: {
397
+ balance: {
398
+ currentBalance: "50000000000000000", // 0.05 ETH
399
+ },
400
+ },
401
+ toAmount: "990000",
402
+ minToAmount: "980000",
403
+ });
404
+ const result = await actionProvider.swap(mockWalletProvider, mockArgs);
405
+ const parsedResult = JSON.parse(result);
406
+ expect(parsedResult.success).toBe(false);
407
+ expect(parsedResult.error).toContain("Balance is not enough to perform swap");
408
+ expect(parsedResult.error).toContain("but only have 0.05 ETH");
409
+ });
410
+ it("should handle approval transaction when allowance is insufficient", async () => {
411
+ mockWalletProvider.getNetwork.mockReturnValue({
412
+ protocolFamily: "evm",
413
+ networkId: "base-mainnet",
414
+ });
415
+ mockCdpClient.evm.getSwapPrice.mockResolvedValue({
416
+ liquidityAvailable: true,
417
+ issues: {
418
+ allowance: {
419
+ requiredAllowance: "100000000000000000",
420
+ currentAllowance: "0",
421
+ },
422
+ },
423
+ toAmount: "990000",
424
+ minToAmount: "980000",
425
+ });
426
+ mockWalletProvider.sendTransaction.mockResolvedValue("0xapproval123");
427
+ mockWalletProvider.waitForTransactionReceipt.mockResolvedValueOnce({ status: "complete" }); // For approval
428
+ mockWalletProvider.waitForTransactionReceipt.mockResolvedValueOnce({ status: "complete" }); // For swap
429
+ mockSmartAccount.swap.mockResolvedValue({ userOpHash: "0xswap789" });
430
+ const result = await actionProvider.swap(mockWalletProvider, mockArgs);
431
+ const parsedResult = JSON.parse(result);
432
+ expect(mockWalletProvider.sendTransaction).toHaveBeenCalled();
433
+ expect(parsedResult.success).toBe(true);
434
+ expect(parsedResult.approvalTxHash).toBe("0xapproval123");
435
+ expect(parsedResult.transactionHash).toBe("0xswap789");
436
+ });
437
+ it("should handle swap execution errors", async () => {
438
+ mockWalletProvider.getNetwork.mockReturnValue({
439
+ protocolFamily: "evm",
440
+ networkId: "base-mainnet",
441
+ });
442
+ mockCdpClient.evm.getSwapPrice.mockResolvedValue({
443
+ liquidityAvailable: true,
444
+ issues: {},
445
+ toAmount: "990000",
446
+ minToAmount: "980000",
447
+ });
448
+ mockSmartAccount.swap.mockRejectedValue(new Error("Swap execution failed"));
449
+ const result = await actionProvider.swap(mockWalletProvider, mockArgs);
450
+ const parsedResult = JSON.parse(result);
451
+ expect(parsedResult.success).toBe(false);
452
+ expect(parsedResult.error).toContain("Swap failed: Error: Swap execution failed");
453
+ });
454
+ });
455
+ describe("supportsNetwork", () => {
456
+ it("should return true for any network", () => {
457
+ const evmNetwork = { protocolFamily: "evm", networkId: "base-sepolia" };
458
+ const svmNetwork = { protocolFamily: "svm", networkId: "solana-devnet" };
459
+ expect(actionProvider.supportsNetwork(evmNetwork)).toBe(true);
460
+ expect(actionProvider.supportsNetwork(svmNetwork)).toBe(true);
461
+ });
462
+ });
463
+ });
@@ -1,2 +1,5 @@
1
1
  export * from "./schemas";
2
2
  export * from "./cdpApiActionProvider";
3
+ export * from "./cdpSmartWalletActionProvider";
4
+ export * from "./cdpEvmWalletActionProvider";
5
+ export * from "./spendPermissionUtils";
@@ -16,3 +16,6 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./schemas"), exports);
18
18
  __exportStar(require("./cdpApiActionProvider"), exports);
19
+ __exportStar(require("./cdpSmartWalletActionProvider"), exports);
20
+ __exportStar(require("./cdpEvmWalletActionProvider"), exports);
21
+ __exportStar(require("./spendPermissionUtils"), exports);
@@ -13,18 +13,47 @@ 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
- fromAssetId: z.ZodString;
17
- toAssetId: z.ZodString;
18
- amount: z.ZodString;
16
+ fromToken: z.ZodString;
17
+ toToken: z.ZodString;
18
+ fromAmount: z.ZodString;
19
+ slippageBps: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
20
+ }, "strip", z.ZodTypeAny, {
21
+ fromToken: string;
22
+ toToken: string;
23
+ fromAmount: string;
24
+ slippageBps: number;
25
+ }, {
26
+ fromToken: string;
27
+ toToken: string;
28
+ fromAmount: string;
29
+ slippageBps?: number | undefined;
30
+ }>;
31
+ /**
32
+ * Input schema for listing spend permissions action.
33
+ */
34
+ export declare const ListSpendPermissionsSchema: z.ZodObject<{
35
+ smartAccountAddress: z.ZodString;
36
+ network: z.ZodOptional<z.ZodString>;
37
+ }, "strip", z.ZodTypeAny, {
38
+ smartAccountAddress: string;
39
+ network?: string | undefined;
40
+ }, {
41
+ smartAccountAddress: string;
42
+ network?: string | undefined;
43
+ }>;
44
+ /**
45
+ * Input schema for using a spend permission action.
46
+ */
47
+ export declare const UseSpendPermissionSchema: z.ZodObject<{
48
+ smartAccountAddress: z.ZodString;
49
+ value: z.ZodString;
19
50
  network: z.ZodOptional<z.ZodString>;
20
51
  }, "strip", z.ZodTypeAny, {
21
- amount: string;
22
- fromAssetId: string;
23
- toAssetId: string;
52
+ value: string;
53
+ smartAccountAddress: string;
24
54
  network?: string | undefined;
25
55
  }, {
26
- amount: string;
27
- fromAssetId: string;
28
- toAssetId: string;
56
+ value: string;
57
+ smartAccountAddress: string;
29
58
  network?: string | undefined;
30
59
  }>;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.SwapSchema = exports.RequestFaucetFundsV2Schema = void 0;
3
+ exports.UseSpendPermissionSchema = exports.ListSpendPermissionsSchema = exports.SwapSchema = exports.RequestFaucetFundsV2Schema = void 0;
4
4
  const zod_1 = require("zod");
5
5
  /**
6
6
  * Input schema for request faucet funds action.
@@ -16,13 +16,56 @@ exports.RequestFaucetFundsV2Schema = zod_1.z
16
16
  */
17
17
  exports.SwapSchema = zod_1.z
18
18
  .object({
19
- fromAssetId: zod_1.z.string().describe("The asset ID to swap from (e.g., 'eth', 'usdc')"),
20
- toAssetId: zod_1.z.string().describe("The asset ID to swap to (e.g., 'eth', 'usdc')"),
21
- amount: zod_1.z.string().describe("The amount to swap (in the from asset's units)"),
22
- network: zod_1.z
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
- .describe("The network to perform the swap on (defaults to wallet's network)"),
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");
41
+ /**
42
+ * Input schema for listing spend permissions action.
43
+ */
44
+ exports.ListSpendPermissionsSchema = zod_1.z
45
+ .object({
46
+ smartAccountAddress: zod_1.z
47
+ .string()
48
+ .describe("The smart account address that has granted spend permissions"),
49
+ network: zod_1.z
50
+ .string()
51
+ .optional()
52
+ .describe("The network to list permissions on (defaults to wallet's network)"),
53
+ })
54
+ .strip()
55
+ .describe("Instructions for listing spend permissions for a smart account");
56
+ /**
57
+ * Input schema for using a spend permission action.
58
+ */
59
+ exports.UseSpendPermissionSchema = zod_1.z
60
+ .object({
61
+ smartAccountAddress: zod_1.z
62
+ .string()
63
+ .describe("The smart account address that has granted the spend permission"),
64
+ value: zod_1.z.string().describe("The amount to spend (in the token's units)"),
65
+ network: zod_1.z
66
+ .string()
67
+ .optional()
68
+ .describe("The network to perform the spend on (defaults to wallet's network)"),
69
+ })
70
+ .strip()
71
+ .describe("Instructions for using a spend permission");
@@ -0,0 +1,24 @@
1
+ import { CdpClient, type SpendPermission } from "@coinbase/cdp-sdk";
2
+ import type { Address } from "viem";
3
+ /**
4
+ * Shared utility functions for spend permission operations.
5
+ */
6
+ /**
7
+ * Lists and formats spend permissions for a given smart account and spender.
8
+ *
9
+ * @param cdpClient - The CDP client to use for API calls
10
+ * @param smartAccountAddress - The smart account address to check permissions for
11
+ * @param spenderAddress - The spender address to filter permissions by
12
+ * @returns A formatted string containing the spend permissions or an error message
13
+ */
14
+ export declare function listSpendPermissionsForSpender(cdpClient: CdpClient, smartAccountAddress: Address, spenderAddress: Address): Promise<string>;
15
+ /**
16
+ * Finds and retrieves the latest valid spend permission for a given spender from a smart account.
17
+ *
18
+ * @param cdpClient - The CDP client to use for API calls
19
+ * @param smartAccountAddress - The smart account address to check permissions for
20
+ * @param spenderAddress - The spender address to find permissions for
21
+ * @returns The latest spend permission or throws an error if none found
22
+ * @throws Error if no permissions found or permission is invalid
23
+ */
24
+ export declare function findLatestSpendPermission(cdpClient: CdpClient, smartAccountAddress: Address, spenderAddress: Address): Promise<SpendPermission>;