@coinbase/agentkit 0.10.0 → 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 (131) hide show
  1. package/README.md +75 -0
  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 -81
  5. package/dist/action-providers/cdp/cdpApiActionProvider.test.js +0 -125
  6. package/dist/action-providers/cdp/cdpEvmWalletActionProvider.d.ts +18 -3
  7. package/dist/action-providers/cdp/cdpEvmWalletActionProvider.js +223 -23
  8. package/dist/action-providers/cdp/cdpEvmWalletActionProvider.test.js +278 -0
  9. package/dist/action-providers/cdp/cdpSmartWalletActionProvider.d.ts +17 -2
  10. package/dist/action-providers/cdp/cdpSmartWalletActionProvider.js +223 -18
  11. package/dist/action-providers/cdp/cdpSmartWalletActionProvider.test.js +265 -1
  12. package/dist/action-providers/cdp/schemas.d.ts +12 -12
  13. package/dist/action-providers/cdp/schemas.js +17 -5
  14. package/dist/action-providers/cdp/swapUtils.d.ts +32 -0
  15. package/dist/action-providers/cdp/swapUtils.js +142 -0
  16. package/dist/action-providers/clanker/clankerActionProvider.d.ts +43 -0
  17. package/dist/action-providers/clanker/clankerActionProvider.js +130 -0
  18. package/dist/action-providers/clanker/clankerActionProvider.test.d.ts +4 -0
  19. package/dist/action-providers/clanker/clankerActionProvider.test.js +119 -0
  20. package/dist/action-providers/clanker/index.d.ts +2 -0
  21. package/dist/action-providers/clanker/index.js +18 -0
  22. package/dist/action-providers/clanker/schemas.d.ts +56 -0
  23. package/dist/action-providers/clanker/schemas.js +47 -0
  24. package/dist/action-providers/clanker/utils.d.ts +9 -0
  25. package/dist/action-providers/clanker/utils.js +23 -0
  26. package/dist/action-providers/compound/constants.d.ts +1 -1
  27. package/dist/action-providers/compound/constants.js +2 -2
  28. package/dist/action-providers/erc20/constants.d.ts +35 -135
  29. package/dist/action-providers/erc20/constants.js +37 -189
  30. package/dist/action-providers/erc20/erc20ActionProvider.d.ts +9 -1
  31. package/dist/action-providers/erc20/erc20ActionProvider.js +87 -35
  32. package/dist/action-providers/erc20/erc20ActionProvider.test.js +115 -52
  33. package/dist/action-providers/erc20/schemas.d.ts +25 -12
  34. package/dist/action-providers/erc20/schemas.js +34 -6
  35. package/dist/action-providers/erc20/utils.d.ts +19 -0
  36. package/dist/action-providers/erc20/utils.js +54 -0
  37. package/dist/action-providers/flaunch/constants.d.ts +1 -1
  38. package/dist/action-providers/flaunch/constants.js +2 -2
  39. package/dist/action-providers/flaunch/flaunchActionProvider.js +3 -11
  40. package/dist/action-providers/flaunch/flaunchActionProvider.test.js +5 -0
  41. package/dist/action-providers/index.d.ts +3 -0
  42. package/dist/action-providers/index.js +3 -0
  43. package/dist/action-providers/jupiter/schemas.d.ts +1 -1
  44. package/dist/action-providers/moonwell/schemas.d.ts +2 -2
  45. package/dist/action-providers/morpho/morphoActionProvider.js +5 -5
  46. package/dist/action-providers/morpho/schemas.d.ts +2 -2
  47. package/dist/action-providers/pyth/pythActionProvider.js +5 -0
  48. package/dist/action-providers/pyth/pythActionProvider.test.js +5 -1
  49. package/dist/action-providers/superfluid/constants.d.ts +814 -0
  50. package/dist/action-providers/superfluid/constants.js +2826 -0
  51. package/dist/action-providers/superfluid/graphQueries/endpoints.d.ts +2 -0
  52. package/dist/action-providers/superfluid/graphQueries/endpoints.js +5 -0
  53. package/dist/action-providers/superfluid/graphQueries/queries.d.ts +1 -0
  54. package/dist/action-providers/superfluid/graphQueries/queries.js +35 -0
  55. package/dist/action-providers/superfluid/graphQueries/superfluidGraphQueries.d.ts +8 -0
  56. package/dist/action-providers/superfluid/graphQueries/superfluidGraphQueries.js +24 -0
  57. package/dist/action-providers/superfluid/graphQueries/types.d.ts +27 -0
  58. package/dist/action-providers/superfluid/graphQueries/types.js +2 -0
  59. package/dist/action-providers/superfluid/index.d.ts +7 -0
  60. package/dist/action-providers/superfluid/index.js +23 -0
  61. package/dist/action-providers/superfluid/schemas.d.ts +86 -0
  62. package/dist/action-providers/superfluid/schemas.js +103 -0
  63. package/dist/action-providers/superfluid/superfluidActionProvider.d.ts +20 -0
  64. package/dist/action-providers/superfluid/superfluidActionProvider.js +36 -0
  65. package/dist/action-providers/superfluid/superfluidPoolActionProvider.d.ts +46 -0
  66. package/dist/action-providers/superfluid/superfluidPoolActionProvider.js +143 -0
  67. package/dist/action-providers/superfluid/superfluidPoolActionProvider.test.d.ts +1 -0
  68. package/dist/action-providers/superfluid/superfluidPoolActionProvider.test.js +92 -0
  69. package/dist/action-providers/superfluid/superfluidQueryActionProvider.d.ts +27 -0
  70. package/dist/action-providers/superfluid/superfluidQueryActionProvider.js +71 -0
  71. package/dist/action-providers/superfluid/superfluidQueryActionProvider.test.d.ts +1 -0
  72. package/dist/action-providers/superfluid/superfluidQueryActionProvider.test.js +57 -0
  73. package/dist/action-providers/superfluid/superfluidStreamActionProvider.d.ts +56 -0
  74. package/dist/action-providers/superfluid/superfluidStreamActionProvider.js +191 -0
  75. package/dist/action-providers/superfluid/superfluidStreamActionProvider.test.d.ts +1 -0
  76. package/dist/action-providers/superfluid/superfluidStreamActionProvider.test.js +80 -0
  77. package/dist/action-providers/superfluid/superfluidSuperTokenCreatorActionProvider.d.ts +30 -0
  78. package/dist/action-providers/superfluid/superfluidSuperTokenCreatorActionProvider.js +108 -0
  79. package/dist/action-providers/superfluid/superfluidSuperTokenCreatorActionProvider.test.d.ts +1 -0
  80. package/dist/action-providers/superfluid/superfluidSuperTokenCreatorActionProvider.test.js +75 -0
  81. package/dist/action-providers/superfluid/superfluidWrapperActionProvider.d.ts +32 -0
  82. package/dist/action-providers/superfluid/superfluidWrapperActionProvider.js +101 -0
  83. package/dist/action-providers/superfluid/superfluidWrapperActionProvider.test.d.ts +1 -0
  84. package/dist/action-providers/superfluid/superfluidWrapperActionProvider.test.js +85 -0
  85. package/dist/action-providers/superfluid/utils/parseLogs.d.ts +18 -0
  86. package/dist/action-providers/superfluid/utils/parseLogs.js +78 -0
  87. package/dist/action-providers/truemarkets/truemarketsActionProvider.d.ts +4 -16
  88. package/dist/action-providers/truemarkets/truemarketsActionProvider.js +20 -41
  89. package/dist/action-providers/truemarkets/truemarketsActionProvider.test.js +11 -33
  90. package/dist/action-providers/wallet/walletActionProvider.js +21 -10
  91. package/dist/action-providers/wallet/walletActionProvider.test.js +6 -2
  92. package/dist/action-providers/zeroX/index.d.ts +1 -0
  93. package/dist/action-providers/zeroX/index.js +17 -0
  94. package/dist/action-providers/zeroX/schemas.d.ts +51 -0
  95. package/dist/action-providers/zeroX/schemas.js +82 -0
  96. package/dist/action-providers/zeroX/utils.d.ts +23 -0
  97. package/dist/action-providers/zeroX/utils.js +106 -0
  98. package/dist/action-providers/zeroX/zeroXActionProvider.d.ts +57 -0
  99. package/dist/action-providers/zeroX/zeroXActionProvider.js +407 -0
  100. package/dist/action-providers/zeroX/zeroXActionProvider.test.d.ts +1 -0
  101. package/dist/action-providers/zeroX/zeroXActionProvider.test.js +445 -0
  102. package/dist/wallet-providers/cdpEvmWalletProvider.d.ts +20 -2
  103. package/dist/wallet-providers/cdpEvmWalletProvider.js +40 -15
  104. package/dist/wallet-providers/cdpShared.d.ts +5 -0
  105. package/dist/wallet-providers/cdpSmartWalletProvider.d.ts +22 -3
  106. package/dist/wallet-providers/cdpSmartWalletProvider.js +43 -19
  107. package/dist/wallet-providers/cdpSolanaWalletProvider.d.ts +1 -1
  108. package/dist/wallet-providers/cdpSolanaWalletProvider.js +7 -7
  109. package/dist/wallet-providers/cdpSolanaWalletProvider.test.js +15 -12
  110. package/dist/wallet-providers/evmWalletProvider.d.ts +5 -1
  111. package/dist/wallet-providers/legacyCdpSmartWalletProvider.d.ts +9 -2
  112. package/dist/wallet-providers/legacyCdpSmartWalletProvider.js +12 -2
  113. package/dist/wallet-providers/legacyCdpWalletProvider.d.ts +12 -2
  114. package/dist/wallet-providers/legacyCdpWalletProvider.js +11 -2
  115. package/dist/wallet-providers/privyEvmDelegatedEmbeddedWalletProvider.d.ts +10 -2
  116. package/dist/wallet-providers/privyEvmDelegatedEmbeddedWalletProvider.js +12 -3
  117. package/dist/wallet-providers/privyEvmDelegatedEmbeddedWalletProvider.test.js +1 -1
  118. package/dist/wallet-providers/privyEvmWalletProvider.d.ts +2 -0
  119. package/dist/wallet-providers/privyEvmWalletProvider.js +2 -1
  120. package/dist/wallet-providers/privyEvmWalletProvider.test.js +1 -1
  121. package/dist/wallet-providers/solanaKeypairWalletProvider.d.ts +1 -1
  122. package/dist/wallet-providers/solanaKeypairWalletProvider.js +3 -4
  123. package/dist/wallet-providers/solanaKeypairWalletProvider.test.js +4 -2
  124. package/dist/wallet-providers/viemWalletProvider.d.ts +12 -2
  125. package/dist/wallet-providers/viemWalletProvider.js +12 -3
  126. package/dist/wallet-providers/viemWalletProvider.test.js +6 -5
  127. package/dist/wallet-providers/walletProvider.d.ts +1 -1
  128. package/dist/wallet-providers/zeroDevWalletProvider.d.ts +10 -2
  129. package/dist/wallet-providers/zeroDevWalletProvider.js +14 -5
  130. package/dist/wallet-providers/zeroDevWalletProvider.test.js +2 -2
  131. package/package.json +4 -2
@@ -1,7 +1,7 @@
1
1
  import { z } from "zod";
2
2
  import { CdpSmartWalletProvider } from "../../wallet-providers/cdpSmartWalletProvider";
3
3
  import { ActionProvider } from "../actionProvider";
4
- import { UseSpendPermissionSchema, ListSpendPermissionsSchema } from "./schemas";
4
+ import { UseSpendPermissionSchema, ListSpendPermissionsSchema, SwapSchema } from "./schemas";
5
5
  import type { Network } from "../../network";
6
6
  /**
7
7
  * CdpSmartWalletActionProvider is an action provider for CDP Smart Wallet specific actions.
@@ -10,7 +10,6 @@ import type { Network } from "../../network";
10
10
  * that are optimized for smart wallet functionality.
11
11
  */
12
12
  export declare class CdpSmartWalletActionProvider extends ActionProvider<CdpSmartWalletProvider> {
13
- #private;
14
13
  /**
15
14
  * Constructor for the CdpSmartWalletActionProvider class.
16
15
  */
@@ -31,6 +30,22 @@ export declare class CdpSmartWalletActionProvider extends ActionProvider<CdpSmar
31
30
  * @returns A confirmation message with transaction details.
32
31
  */
33
32
  useSpendPermission(walletProvider: CdpSmartWalletProvider, args: z.infer<typeof UseSpendPermissionSchema>): Promise<string>;
33
+ /**
34
+ * Gets a price quote for swapping tokens using the CDP Swap API.
35
+ *
36
+ * @param walletProvider - The smart wallet provider to get the quote for.
37
+ * @param args - The input arguments for the swap price action.
38
+ * @returns A JSON string with detailed swap price quote information.
39
+ */
40
+ getSwapPrice(walletProvider: CdpSmartWalletProvider, args: z.infer<typeof SwapSchema>): Promise<string>;
41
+ /**
42
+ * Swaps tokens using the CDP client.
43
+ *
44
+ * @param walletProvider - The smart wallet provider to perform the swap with.
45
+ * @param args - The input arguments for the swap action.
46
+ * @returns A JSON string with detailed swap execution information.
47
+ */
48
+ swap(walletProvider: CdpSmartWalletProvider, args: z.infer<typeof SwapSchema>): Promise<string>;
34
49
  /**
35
50
  * Checks if the smart wallet action provider supports the given network.
36
51
  *
@@ -8,12 +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 __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
12
- if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
13
- if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
14
- return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
15
- };
16
- var _CdpSmartWalletActionProvider_instances, _CdpSmartWalletActionProvider_getCdpSdkNetwork;
17
11
  Object.defineProperty(exports, "__esModule", { value: true });
18
12
  exports.cdpSmartWalletActionProvider = exports.CdpSmartWalletActionProvider = void 0;
19
13
  const zod_1 = require("zod");
@@ -22,6 +16,8 @@ const actionDecorator_1 = require("../actionDecorator");
22
16
  const actionProvider_1 = require("../actionProvider");
23
17
  const schemas_1 = require("./schemas");
24
18
  const spendPermissionUtils_1 = require("./spendPermissionUtils");
19
+ const swapUtils_1 = require("./swapUtils");
20
+ const viem_1 = require("viem");
25
21
  /**
26
22
  * CdpSmartWalletActionProvider is an action provider for CDP Smart Wallet specific actions.
27
23
  *
@@ -34,7 +30,6 @@ class CdpSmartWalletActionProvider extends actionProvider_1.ActionProvider {
34
30
  */
35
31
  constructor() {
36
32
  super("cdp_smart_wallet", []);
37
- _CdpSmartWalletActionProvider_instances.add(this);
38
33
  /**
39
34
  * Checks if the smart wallet action provider supports the given network.
40
35
  *
@@ -71,7 +66,7 @@ class CdpSmartWalletActionProvider extends actionProvider_1.ActionProvider {
71
66
  */
72
67
  async useSpendPermission(walletProvider, args) {
73
68
  const network = walletProvider.getNetwork();
74
- const cdpNetwork = __classPrivateFieldGet(this, _CdpSmartWalletActionProvider_instances, "m", _CdpSmartWalletActionProvider_getCdpSdkNetwork).call(this, network.networkId);
69
+ const cdpNetwork = walletProvider.getCdpSdkNetwork();
75
70
  if (network.protocolFamily === "evm") {
76
71
  try {
77
72
  const permission = await (0, spendPermissionUtils_1.findLatestSpendPermission)(walletProvider.getClient(), args.smartAccountAddress, walletProvider.getAddress());
@@ -90,18 +85,185 @@ class CdpSmartWalletActionProvider extends actionProvider_1.ActionProvider {
90
85
  throw new Error("Spend permissions are currently only supported on EVM networks.");
91
86
  }
92
87
  }
88
+ /**
89
+ * Gets a price quote for swapping tokens using the CDP Swap API.
90
+ *
91
+ * @param walletProvider - The smart wallet provider to get the quote for.
92
+ * @param args - The input arguments for the swap price action.
93
+ * @returns A JSON string with detailed swap price quote information.
94
+ */
95
+ async getSwapPrice(walletProvider, args) {
96
+ const network = walletProvider.getNetwork();
97
+ const networkId = network.networkId;
98
+ // Check if the network is supported
99
+ if (networkId !== "base-mainnet" && networkId !== "base-sepolia") {
100
+ return JSON.stringify({
101
+ success: false,
102
+ error: "CDP Swap API for smart wallets is currently only supported on Base networks.",
103
+ });
104
+ }
105
+ try {
106
+ const cdpNetwork = walletProvider.getCdpSdkNetwork();
107
+ // Get token details
108
+ const { fromTokenDecimals, toTokenDecimals, fromTokenName, toTokenName } = await (0, swapUtils_1.getTokenDetails)(walletProvider, args.fromToken, args.toToken);
109
+ // Get swap price quote
110
+ const swapPrice = (await walletProvider.getClient().evm.getSwapPrice({
111
+ fromToken: args.fromToken,
112
+ toToken: args.toToken,
113
+ fromAmount: (0, viem_1.parseUnits)(args.fromAmount, fromTokenDecimals),
114
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
115
+ network: cdpNetwork,
116
+ taker: walletProvider.getAddress(),
117
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
118
+ }));
119
+ const formattedResponse = {
120
+ success: true,
121
+ fromAmount: args.fromAmount,
122
+ fromTokenName: fromTokenName,
123
+ fromToken: args.fromToken,
124
+ toAmount: (0, viem_1.formatUnits)(swapPrice.toAmount, toTokenDecimals),
125
+ minToAmount: (0, viem_1.formatUnits)(swapPrice.minToAmount, toTokenDecimals),
126
+ toTokenName: toTokenName,
127
+ toToken: args.toToken,
128
+ slippageBps: args.slippageBps,
129
+ liquidityAvailable: swapPrice.liquidityAvailable,
130
+ balanceEnough: swapPrice.issues.balance === undefined,
131
+ priceOfBuyTokenInSellToken: (Number(args.fromAmount) / Number((0, viem_1.formatUnits)(swapPrice.toAmount, toTokenDecimals))).toString(),
132
+ priceOfSellTokenInBuyToken: (Number((0, viem_1.formatUnits)(swapPrice.toAmount, toTokenDecimals)) / Number(args.fromAmount)).toString(),
133
+ };
134
+ return JSON.stringify(formattedResponse);
135
+ }
136
+ catch (error) {
137
+ return JSON.stringify({
138
+ success: false,
139
+ error: `Error fetching swap price: ${error}`,
140
+ });
141
+ }
142
+ }
143
+ /**
144
+ * Swaps tokens using the CDP client.
145
+ *
146
+ * @param walletProvider - The smart wallet provider to perform the swap with.
147
+ * @param args - The input arguments for the swap action.
148
+ * @returns A JSON string with detailed swap execution information.
149
+ */
150
+ async swap(walletProvider, args) {
151
+ const network = walletProvider.getNetwork();
152
+ const networkId = network.networkId;
153
+ // Check if the network is supported
154
+ if (networkId !== "base-mainnet" && networkId !== "base-sepolia") {
155
+ return JSON.stringify({
156
+ success: false,
157
+ error: "CDP Swap API for smart wallets is currently only supported on Base networks.",
158
+ });
159
+ }
160
+ // Check if the owner account is a CDP server account
161
+ if (walletProvider.ownerAccount.type === "local") {
162
+ throw new Error("Smart wallet owner account is not a CDP server account.");
163
+ }
164
+ try {
165
+ const cdpNetwork = walletProvider.getCdpSdkNetwork();
166
+ // Get token details
167
+ const { fromTokenDecimals, fromTokenName, toTokenName, toTokenDecimals } = await (0, swapUtils_1.getTokenDetails)(walletProvider, args.fromToken, args.toToken);
168
+ // Estimate swap price first to check liquidity, token balance and permit2 approval status
169
+ const swapPrice = await walletProvider.getClient().evm.getSwapPrice({
170
+ fromToken: args.fromToken,
171
+ toToken: args.toToken,
172
+ fromAmount: (0, viem_1.parseUnits)(args.fromAmount, fromTokenDecimals),
173
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
174
+ network: cdpNetwork,
175
+ taker: walletProvider.smartAccount.address,
176
+ });
177
+ // Check if liquidity is available
178
+ if (!swapPrice.liquidityAvailable) {
179
+ return JSON.stringify({
180
+ success: false,
181
+ error: `No liquidity available to swap ${args.fromAmount} ${fromTokenName} (${args.fromToken}) to ${toTokenName} (${args.toToken})`,
182
+ });
183
+ }
184
+ // Check if balance is enough
185
+ if (swapPrice.issues.balance) {
186
+ return JSON.stringify({
187
+ success: false,
188
+ error: `Balance is not enough to perform swap. Required: ${args.fromAmount} ${fromTokenName}, but only have ${(0, viem_1.formatUnits)(swapPrice.issues.balance.currentBalance, fromTokenDecimals)} ${fromTokenName} (${args.fromToken})`,
189
+ });
190
+ }
191
+ // Check if allowance is enough
192
+ let approvalTxHash = null;
193
+ if (swapPrice.issues.allowance) {
194
+ try {
195
+ approvalTxHash = await walletProvider.sendTransaction({
196
+ to: args.fromToken,
197
+ data: (0, viem_1.encodeFunctionData)({
198
+ abi: viem_1.erc20Abi,
199
+ functionName: "approve",
200
+ args: [swapUtils_1.PERMIT2_ADDRESS, viem_1.maxUint256],
201
+ }),
202
+ });
203
+ const receipt = await walletProvider.waitForTransactionReceipt(approvalTxHash);
204
+ if (receipt.status !== "complete") {
205
+ return JSON.stringify({
206
+ success: false,
207
+ error: `Approval transaction failed`,
208
+ });
209
+ }
210
+ }
211
+ catch (error) {
212
+ return JSON.stringify({
213
+ success: false,
214
+ error: `Error approving token: ${error}`,
215
+ });
216
+ }
217
+ }
218
+ // Execute swap using the all-in-one pattern with retry logic
219
+ const swapResult = await (0, swapUtils_1.retryWithExponentialBackoff)(async () => {
220
+ return (await walletProvider.smartAccount.swap({
221
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
222
+ network: cdpNetwork,
223
+ fromToken: args.fromToken,
224
+ toToken: args.toToken,
225
+ fromAmount: (0, viem_1.parseUnits)(args.fromAmount, fromTokenDecimals),
226
+ slippageBps: args.slippageBps,
227
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
228
+ paymasterUrl: walletProvider.getPaymasterUrl(),
229
+ signerAddress: walletProvider.ownerAccount.address,
230
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
231
+ }));
232
+ }, 3, 5000); // Max 3 retries with 5s base delay
233
+ // Check if swap was successful
234
+ const swapReceipt = await walletProvider.waitForTransactionReceipt(swapResult.userOpHash);
235
+ if (swapReceipt.status !== "complete") {
236
+ return JSON.stringify({
237
+ success: false,
238
+ error: `Swap transaction failed`,
239
+ });
240
+ }
241
+ // Format the successful response
242
+ const formattedResponse = {
243
+ success: true,
244
+ ...(approvalTxHash ? { approvalTxHash } : {}),
245
+ transactionHash: swapResult.userOpHash,
246
+ fromAmount: args.fromAmount,
247
+ fromTokenName: fromTokenName,
248
+ fromToken: args.fromToken,
249
+ toAmount: (0, viem_1.formatUnits)(swapPrice.toAmount, toTokenDecimals),
250
+ minToAmount: (0, viem_1.formatUnits)(swapPrice.minToAmount, toTokenDecimals),
251
+ toTokenName: toTokenName,
252
+ toToken: args.toToken,
253
+ slippageBps: args.slippageBps,
254
+ network: networkId,
255
+ };
256
+ return JSON.stringify(formattedResponse);
257
+ }
258
+ catch (error) {
259
+ return JSON.stringify({
260
+ success: false,
261
+ error: `Swap failed: ${error}`,
262
+ });
263
+ }
264
+ }
93
265
  }
94
266
  exports.CdpSmartWalletActionProvider = CdpSmartWalletActionProvider;
95
- _CdpSmartWalletActionProvider_instances = new WeakSet(), _CdpSmartWalletActionProvider_getCdpSdkNetwork = function _CdpSmartWalletActionProvider_getCdpSdkNetwork(networkId) {
96
- switch (networkId) {
97
- case "base-sepolia":
98
- return "base-sepolia";
99
- case "base-mainnet":
100
- return "base";
101
- default:
102
- throw new Error(`Unsupported network for smart wallets: ${networkId}`);
103
- }
104
- };
105
267
  __decorate([
106
268
  (0, actionDecorator_1.CreateAction)({
107
269
  name: "list_spend_permissions",
@@ -128,5 +290,48 @@ This action is specifically designed for smart wallets and uses the smart accoun
128
290
  __metadata("design:paramtypes", [cdpSmartWalletProvider_1.CdpSmartWalletProvider, void 0]),
129
291
  __metadata("design:returntype", Promise)
130
292
  ], CdpSmartWalletActionProvider.prototype, "useSpendPermission", null);
293
+ __decorate([
294
+ (0, actionDecorator_1.CreateAction)({
295
+ name: "get_swap_price",
296
+ description: `
297
+ This tool fetches a price quote for swapping (trading) between two tokens using the CDP Swap API but does not execute a swap.
298
+ It takes the following inputs:
299
+ - fromToken: The contract address of the token to sell
300
+ - toToken: The contract address of the token to buy
301
+ - fromAmount: The amount of fromToken to swap in whole units (e.g. 1 ETH or 10.5 USDC)
302
+ - slippageBps: (Optional) Maximum allowed slippage in basis points (100 = 1%)
303
+ Important notes:
304
+ - The contract address for native ETH is "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"
305
+ - Use fromAmount units exactly as provided, do not convert to wei or any other units
306
+ - Never assume token or address, they have to be provided as inputs. If only token symbol is provided, use the get_token_address tool if available to get the token address first
307
+ `,
308
+ schema: schemas_1.SwapSchema,
309
+ }),
310
+ __metadata("design:type", Function),
311
+ __metadata("design:paramtypes", [cdpSmartWalletProvider_1.CdpSmartWalletProvider, void 0]),
312
+ __metadata("design:returntype", Promise)
313
+ ], CdpSmartWalletActionProvider.prototype, "getSwapPrice", null);
314
+ __decorate([
315
+ (0, actionDecorator_1.CreateAction)({
316
+ name: "swap",
317
+ description: `
318
+ This tool executes a token swap (trade) using the CDP Swap API.
319
+ It takes the following inputs:
320
+ - fromToken: The contract address of the token to sell
321
+ - toToken: The contract address of the token to buy
322
+ - fromAmount: The amount of fromToken to swap in whole units (e.g. 1 ETH or 10.5 USDC)
323
+ - slippageBps: (Optional) Maximum allowed slippage in basis points (100 = 1%)
324
+ Important notes:
325
+ - The contract address for native ETH is "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"
326
+ - If needed, it will automatically approve the permit2 contract to spend the fromToken
327
+ - Use fromAmount units exactly as provided, do not convert to wei or any other units
328
+ - Never assume token or address, they have to be provided as inputs. If only token symbol is provided, use the get_token_address tool if available to get the token address first
329
+ `,
330
+ schema: schemas_1.SwapSchema,
331
+ }),
332
+ __metadata("design:type", Function),
333
+ __metadata("design:paramtypes", [cdpSmartWalletProvider_1.CdpSmartWalletProvider, void 0]),
334
+ __metadata("design:returntype", Promise)
335
+ ], CdpSmartWalletActionProvider.prototype, "swap", null);
131
336
  const cdpSmartWalletActionProvider = () => new CdpSmartWalletActionProvider();
132
337
  exports.cdpSmartWalletActionProvider = cdpSmartWalletActionProvider;
@@ -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,19 @@ 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(),
76
+ getCdpSdkNetwork: jest.fn(),
63
77
  };
78
+ // Default setup for utility functions
79
+ mockRetryWithExponentialBackoff.mockImplementation(async (fn) => {
80
+ return await fn();
81
+ });
64
82
  actionProvider = new cdpSmartWalletActionProvider_1.CdpSmartWalletActionProvider();
65
83
  });
66
84
  describe("listSpendPermissions", () => {
@@ -74,6 +92,7 @@ describe("CDP Smart Wallet Action Provider", () => {
74
92
  });
75
93
  mockWalletProvider.getAddress.mockReturnValue("0x1234567890123456789012345678901234567890");
76
94
  mockWalletProvider.getClient.mockReturnValue(mockCdpClient);
95
+ mockWalletProvider.getCdpSdkNetwork.mockReturnValue("base-sepolia");
77
96
  });
78
97
  it("should successfully list spend permissions for EVM networks", async () => {
79
98
  const expectedResult = "Found 1 spend permission(s):\n1. Token: ETH, Allowance: 1000, Period: 3600 seconds, Start: 123456, End: 234567";
@@ -110,6 +129,7 @@ describe("CDP Smart Wallet Action Provider", () => {
110
129
  });
111
130
  mockWalletProvider.getAddress.mockReturnValue("0x1234567890123456789012345678901234567890");
112
131
  mockWalletProvider.getClient.mockReturnValue(mockCdpClient);
132
+ mockWalletProvider.getCdpSdkNetwork.mockReturnValue("base-sepolia");
113
133
  });
114
134
  it("should successfully use spend permission for EVM networks", async () => {
115
135
  const mockPermission = {
@@ -140,6 +160,7 @@ describe("CDP Smart Wallet Action Provider", () => {
140
160
  protocolFamily: "evm",
141
161
  networkId: "base-mainnet",
142
162
  });
163
+ mockWalletProvider.getCdpSdkNetwork.mockReturnValue("base");
143
164
  const mockPermission = { spender: "0x1234", token: "ETH" };
144
165
  const mockSpendResult = { status: "completed" };
145
166
  spendPermissionUtils.findLatestSpendPermission.mockResolvedValue(mockPermission);
@@ -156,6 +177,9 @@ describe("CDP Smart Wallet Action Provider", () => {
156
177
  protocolFamily: "evm",
157
178
  networkId: "ethereum-mainnet",
158
179
  });
180
+ mockWalletProvider.getCdpSdkNetwork.mockImplementation(() => {
181
+ throw new Error("Unsupported network for smart wallets: ethereum-mainnet");
182
+ });
159
183
  await expect(actionProvider.useSpendPermission(mockWalletProvider, mockArgs)).rejects.toThrow("Unsupported network for smart wallets: ethereum-mainnet");
160
184
  });
161
185
  it("should return error message for non-EVM networks", async () => {
@@ -163,7 +187,7 @@ describe("CDP Smart Wallet Action Provider", () => {
163
187
  protocolFamily: "svm",
164
188
  networkId: "solana-devnet",
165
189
  });
166
- await expect(actionProvider.useSpendPermission(mockWalletProvider, mockArgs)).rejects.toThrow("Unsupported network for smart wallets: solana-devnet");
190
+ await expect(actionProvider.useSpendPermission(mockWalletProvider, mockArgs)).rejects.toThrow("Spend permissions are currently only supported on EVM networks.");
167
191
  });
168
192
  it("should handle spend permission not found error", async () => {
169
193
  spendPermissionUtils.findLatestSpendPermission.mockRejectedValue(new Error("No spend permissions found"));
@@ -188,6 +212,246 @@ describe("CDP Smart Wallet Action Provider", () => {
188
212
  expect(() => schemas_1.UseSpendPermissionSchema.parse(invalidInput)).toThrow();
189
213
  });
190
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
+ });
191
455
  describe("supportsNetwork", () => {
192
456
  it("should return true for any network", () => {
193
457
  const evmNetwork = { protocolFamily: "evm", networkId: "base-sepolia" };