@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
@@ -8,21 +8,18 @@ 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 _CdpEvmWalletActionProvider_instances, _CdpEvmWalletActionProvider_getCdpSdkNetwork;
17
11
  Object.defineProperty(exports, "__esModule", { value: true });
18
12
  exports.cdpEvmWalletActionProvider = exports.CdpEvmWalletActionProvider = void 0;
19
13
  const zod_1 = require("zod");
20
14
  const wallet_providers_1 = require("../../wallet-providers");
21
15
  const cdpShared_1 = require("../../wallet-providers/cdpShared");
16
+ const cdpEvmWalletProvider_1 = require("../../wallet-providers/cdpEvmWalletProvider");
22
17
  const actionDecorator_1 = require("../actionDecorator");
23
18
  const actionProvider_1 = require("../actionProvider");
24
19
  const schemas_1 = require("./schemas");
25
20
  const spendPermissionUtils_1 = require("./spendPermissionUtils");
21
+ const swapUtils_1 = require("./swapUtils");
22
+ const viem_1 = require("viem");
26
23
  /**
27
24
  * CdpEvmWalletActionProvider is an action provider for CDP EVM Wallet specific actions.
28
25
  *
@@ -35,7 +32,6 @@ class CdpEvmWalletActionProvider extends actionProvider_1.ActionProvider {
35
32
  */
36
33
  constructor() {
37
34
  super("cdp_evm_wallet", []);
38
- _CdpEvmWalletActionProvider_instances.add(this);
39
35
  /**
40
36
  * Checks if the EVM wallet action provider supports the given network.
41
37
  *
@@ -77,7 +73,7 @@ class CdpEvmWalletActionProvider extends actionProvider_1.ActionProvider {
77
73
  */
78
74
  async useSpendPermission(walletProvider, args) {
79
75
  const network = walletProvider.getNetwork();
80
- const cdpNetwork = __classPrivateFieldGet(this, _CdpEvmWalletActionProvider_instances, "m", _CdpEvmWalletActionProvider_getCdpSdkNetwork).call(this, network.networkId);
76
+ const cdpNetwork = walletProvider.getCdpSdkNetwork();
81
77
  if ((0, cdpShared_1.isWalletProviderWithClient)(walletProvider)) {
82
78
  if (network.protocolFamily === "evm") {
83
79
  try {
@@ -105,22 +101,183 @@ class CdpEvmWalletActionProvider extends actionProvider_1.ActionProvider {
105
101
  return "Wallet provider is not a CDP Wallet Provider.";
106
102
  }
107
103
  }
104
+ /**
105
+ * Gets a price quote for swapping tokens using the CDP Swap API.
106
+ *
107
+ * @param walletProvider - The EVM wallet provider to get the quote for.
108
+ * @param args - The input arguments for the swap price action.
109
+ * @returns A JSON string with detailed swap price quote information.
110
+ */
111
+ async getSwapPrice(walletProvider, args) {
112
+ // Get CDP SDK network
113
+ const network = walletProvider.getNetwork();
114
+ const networkId = network.networkId;
115
+ const cdpNetwork = walletProvider.getCdpSdkNetwork();
116
+ // Check if the network is supported
117
+ if (networkId !== "base-mainnet" && networkId !== "ethereum-mainnet")
118
+ return JSON.stringify({
119
+ success: false,
120
+ error: "CDP Swap API is currently only supported on 'base-mainnet' or 'ethereum-mainnet'.",
121
+ });
122
+ try {
123
+ // Get token details
124
+ const { fromTokenDecimals, toTokenDecimals, fromTokenName, toTokenName } = await (0, swapUtils_1.getTokenDetails)(walletProvider, args.fromToken, args.toToken);
125
+ // Get swap price quote
126
+ const swapPrice = (await walletProvider.getClient().evm.getSwapPrice({
127
+ fromToken: args.fromToken,
128
+ toToken: args.toToken,
129
+ fromAmount: (0, viem_1.parseUnits)(args.fromAmount, fromTokenDecimals),
130
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
131
+ network: cdpNetwork,
132
+ taker: walletProvider.getAddress(),
133
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
134
+ }));
135
+ const formattedResponse = {
136
+ success: true,
137
+ fromAmount: args.fromAmount,
138
+ fromTokenName: fromTokenName,
139
+ fromToken: args.fromToken,
140
+ toAmount: (0, viem_1.formatUnits)(swapPrice.toAmount, toTokenDecimals),
141
+ minToAmount: (0, viem_1.formatUnits)(swapPrice.minToAmount, toTokenDecimals),
142
+ toTokenName: toTokenName,
143
+ toToken: args.toToken,
144
+ slippageBps: args.slippageBps,
145
+ liquidityAvailable: swapPrice.liquidityAvailable,
146
+ balanceEnough: swapPrice.issues.balance === undefined,
147
+ priceOfBuyTokenInSellToken: (Number(args.fromAmount) / Number((0, viem_1.formatUnits)(swapPrice.toAmount, toTokenDecimals))).toString(),
148
+ priceOfSellTokenInBuyToken: (Number((0, viem_1.formatUnits)(swapPrice.toAmount, toTokenDecimals)) / Number(args.fromAmount)).toString(),
149
+ };
150
+ return JSON.stringify(formattedResponse);
151
+ }
152
+ catch (error) {
153
+ return JSON.stringify({
154
+ success: false,
155
+ error: `Error fetching swap price: ${error}`,
156
+ });
157
+ }
158
+ }
159
+ /**
160
+ * Swaps tokens using the CDP client.
161
+ *
162
+ * @param walletProvider - The EVM wallet provider to perform the swap with.
163
+ * @param args - The input arguments for the swap action.
164
+ * @returns A JSON string with detailed swap execution information.
165
+ */
166
+ async swap(walletProvider, args) {
167
+ // Get CDP SDK network
168
+ const network = walletProvider.getNetwork();
169
+ const networkId = network.networkId;
170
+ const cdpNetwork = walletProvider.getCdpSdkNetwork();
171
+ // Check if the network is supported
172
+ if (networkId !== "base-mainnet" && networkId !== "ethereum-mainnet")
173
+ return JSON.stringify({
174
+ success: false,
175
+ error: "CDP Swap API is currently only supported on 'base-mainnet' or 'ethereum-mainnet'.",
176
+ });
177
+ try {
178
+ // Get token details
179
+ const { fromTokenDecimals, fromTokenName, toTokenName, toTokenDecimals } = await (0, swapUtils_1.getTokenDetails)(walletProvider, args.fromToken, args.toToken);
180
+ // Get the account
181
+ const account = await walletProvider.getClient().evm.getAccount({
182
+ address: walletProvider.getAddress(),
183
+ });
184
+ // Estimate swap price first to check liquidity, token balance and permit2 approval status
185
+ const swapPrice = await walletProvider.getClient().evm.getSwapPrice({
186
+ fromToken: args.fromToken,
187
+ toToken: args.toToken,
188
+ fromAmount: (0, viem_1.parseUnits)(args.fromAmount, fromTokenDecimals),
189
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
190
+ network: cdpNetwork,
191
+ taker: account.address,
192
+ });
193
+ // Check if liquidity is available
194
+ if (!swapPrice.liquidityAvailable) {
195
+ return JSON.stringify({
196
+ success: false,
197
+ error: `No liquidity available to swap ${args.fromAmount} ${fromTokenName} (${args.fromToken}) to ${toTokenName} (${args.toToken})`,
198
+ });
199
+ }
200
+ // Check if balance is enough
201
+ if (swapPrice.issues.balance) {
202
+ return JSON.stringify({
203
+ success: false,
204
+ 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})`,
205
+ });
206
+ }
207
+ // Check if allowance is enough
208
+ let approvalTxHash = null;
209
+ if (swapPrice.issues.allowance) {
210
+ try {
211
+ approvalTxHash = await walletProvider.sendTransaction({
212
+ to: args.fromToken,
213
+ data: (0, viem_1.encodeFunctionData)({
214
+ abi: viem_1.erc20Abi,
215
+ functionName: "approve",
216
+ args: [swapUtils_1.PERMIT2_ADDRESS, viem_1.maxUint256],
217
+ }),
218
+ });
219
+ const receipt = await walletProvider.waitForTransactionReceipt(approvalTxHash);
220
+ if (receipt.status !== "success") {
221
+ return JSON.stringify({
222
+ success: false,
223
+ error: `Approval transaction failed`,
224
+ });
225
+ }
226
+ }
227
+ catch (error) {
228
+ return JSON.stringify({
229
+ success: false,
230
+ error: `Error approving token: ${error}`,
231
+ });
232
+ }
233
+ }
234
+ // Execute swap using the all-in-one pattern with retry logic
235
+ const swapResult = await (0, swapUtils_1.retryWithExponentialBackoff)(async () => {
236
+ return (await account.swap({
237
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
238
+ network: cdpNetwork,
239
+ fromToken: args.fromToken,
240
+ toToken: args.toToken,
241
+ fromAmount: (0, viem_1.parseUnits)(args.fromAmount, fromTokenDecimals),
242
+ slippageBps: args.slippageBps,
243
+ signerAddress: account.address,
244
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
245
+ }));
246
+ }, 3, 5000); // Max 3 retries with 5s base delay
247
+ // Check if swap was successful
248
+ const swapReceipt = await walletProvider.waitForTransactionReceipt(swapResult.transactionHash);
249
+ if (swapReceipt.status !== "success") {
250
+ return JSON.stringify({
251
+ success: false,
252
+ error: `Swap transaction failed`,
253
+ });
254
+ }
255
+ // Format the successful response
256
+ const formattedResponse = {
257
+ success: true,
258
+ ...(approvalTxHash ? { approvalTxHash } : {}),
259
+ transactionHash: swapResult.transactionHash,
260
+ fromAmount: args.fromAmount,
261
+ fromTokenName: fromTokenName,
262
+ fromToken: args.fromToken,
263
+ toAmount: (0, viem_1.formatUnits)(swapPrice.toAmount, toTokenDecimals),
264
+ minToAmount: (0, viem_1.formatUnits)(swapPrice.minToAmount, toTokenDecimals),
265
+ toTokenName: toTokenName,
266
+ toToken: args.toToken,
267
+ slippageBps: args.slippageBps,
268
+ network: networkId,
269
+ };
270
+ return JSON.stringify(formattedResponse);
271
+ }
272
+ catch (error) {
273
+ return JSON.stringify({
274
+ success: false,
275
+ error: `Swap failed: ${error}`,
276
+ });
277
+ }
278
+ }
108
279
  }
109
280
  exports.CdpEvmWalletActionProvider = CdpEvmWalletActionProvider;
110
- _CdpEvmWalletActionProvider_instances = new WeakSet(), _CdpEvmWalletActionProvider_getCdpSdkNetwork = function _CdpEvmWalletActionProvider_getCdpSdkNetwork(networkId) {
111
- switch (networkId) {
112
- case "base-sepolia":
113
- return "base-sepolia";
114
- case "base-mainnet":
115
- return "base";
116
- case "ethereum-sepolia":
117
- return "ethereum-sepolia";
118
- case "ethereum-mainnet":
119
- return "ethereum";
120
- default:
121
- return networkId; // For other networks, use as-is
122
- }
123
- };
124
281
  __decorate([
125
282
  (0, actionDecorator_1.CreateAction)({
126
283
  name: "list_spend_permissions",
@@ -144,8 +301,51 @@ This action is specifically designed for EVM wallets and uses the EVM wallet for
144
301
  schema: schemas_1.UseSpendPermissionSchema,
145
302
  }),
146
303
  __metadata("design:type", Function),
147
- __metadata("design:paramtypes", [wallet_providers_1.WalletProvider, void 0]),
304
+ __metadata("design:paramtypes", [cdpEvmWalletProvider_1.CdpEvmWalletProvider, void 0]),
148
305
  __metadata("design:returntype", Promise)
149
306
  ], CdpEvmWalletActionProvider.prototype, "useSpendPermission", null);
307
+ __decorate([
308
+ (0, actionDecorator_1.CreateAction)({
309
+ name: "get_swap_price",
310
+ description: `
311
+ This tool fetches a price quote for swapping (trading) between two tokens using the CDP Swap API but does not execute a swap.
312
+ It takes the following inputs:
313
+ - fromToken: The contract address of the token to sell
314
+ - toToken: The contract address of the token to buy
315
+ - fromAmount: The amount of fromToken to swap in whole units (e.g. 1 ETH or 10.5 USDC)
316
+ - slippageBps: (Optional) Maximum allowed slippage in basis points (100 = 1%)
317
+ Important notes:
318
+ - The contract address for native ETH is "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"
319
+ - Use fromAmount units exactly as provided, do not convert to wei or any other units
320
+ - 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
321
+ `,
322
+ schema: schemas_1.SwapSchema,
323
+ }),
324
+ __metadata("design:type", Function),
325
+ __metadata("design:paramtypes", [cdpEvmWalletProvider_1.CdpEvmWalletProvider, void 0]),
326
+ __metadata("design:returntype", Promise)
327
+ ], CdpEvmWalletActionProvider.prototype, "getSwapPrice", null);
328
+ __decorate([
329
+ (0, actionDecorator_1.CreateAction)({
330
+ name: "swap",
331
+ description: `
332
+ This tool executes a token swap (trade) using the CDP Swap API.
333
+ It takes the following inputs:
334
+ - fromToken: The contract address of the token to sell
335
+ - toToken: The contract address of the token to buy
336
+ - fromAmount: The amount of fromToken to swap in whole units (e.g. 1 ETH or 10.5 USDC)
337
+ - slippageBps: (Optional) Maximum allowed slippage in basis points (100 = 1%)
338
+ Important notes:
339
+ - The contract address for native ETH is "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"
340
+ - If needed, it will automatically approve the permit2 contract to spend the fromToken
341
+ - Use fromAmount units exactly as provided, do not convert to wei or any other units.
342
+ - 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
343
+ `,
344
+ schema: schemas_1.SwapSchema,
345
+ }),
346
+ __metadata("design:type", Function),
347
+ __metadata("design:paramtypes", [cdpEvmWalletProvider_1.CdpEvmWalletProvider, void 0]),
348
+ __metadata("design:returntype", Promise)
349
+ ], CdpEvmWalletActionProvider.prototype, "swap", null);
150
350
  const cdpEvmWalletActionProvider = () => new CdpEvmWalletActionProvider();
151
351
  exports.cdpEvmWalletActionProvider = cdpEvmWalletActionProvider;
@@ -36,31 +36,44 @@ Object.defineProperty(exports, "__esModule", { value: true });
36
36
  const cdpEvmWalletActionProvider_1 = require("./cdpEvmWalletActionProvider");
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 EVM Wallet Action Provider", () => {
43
45
  let actionProvider;
44
46
  let mockWalletProvider;
45
47
  let mockCdpClient;
46
48
  let mockAccount;
49
+ const mockGetTokenDetails = swapUtils.getTokenDetails;
50
+ const mockRetryWithExponentialBackoff = swapUtils.retryWithExponentialBackoff;
47
51
  beforeEach(() => {
48
52
  jest.clearAllMocks();
49
53
  mockAccount = {
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(),
56
61
  getAccount: jest.fn(),
62
+ getSwapPrice: jest.fn(),
57
63
  },
58
64
  };
59
65
  mockWalletProvider = {
60
66
  getNetwork: jest.fn(),
61
67
  getAddress: jest.fn(),
62
68
  getClient: jest.fn(),
69
+ sendTransaction: jest.fn(),
70
+ waitForTransactionReceipt: jest.fn(),
71
+ getCdpSdkNetwork: jest.fn(),
63
72
  };
73
+ // Default setup for utility functions
74
+ mockRetryWithExponentialBackoff.mockImplementation(async (fn) => {
75
+ return await fn();
76
+ });
64
77
  actionProvider = new cdpEvmWalletActionProvider_1.CdpEvmWalletActionProvider();
65
78
  });
66
79
  describe("listSpendPermissions", () => {
@@ -74,6 +87,7 @@ describe("CDP EVM Wallet Action Provider", () => {
74
87
  });
75
88
  mockWalletProvider.getAddress.mockReturnValue("0x1234567890123456789012345678901234567890");
76
89
  mockWalletProvider.getClient.mockReturnValue(mockCdpClient);
90
+ mockWalletProvider.getCdpSdkNetwork.mockReturnValue("base-sepolia");
77
91
  });
78
92
  it("should successfully list spend permissions for EVM wallets", async () => {
79
93
  const expectedResult = "Found 2 spend permission(s):\n1. Token: USDC, Allowance: 500, Period: 1800 seconds, Start: 111111, End: 222222\n2. Token: ETH, Allowance: 1000, Period: 3600 seconds, Start: 123456, End: 234567";
@@ -115,6 +129,7 @@ describe("CDP EVM Wallet Action Provider", () => {
115
129
  });
116
130
  mockWalletProvider.getAddress.mockReturnValue("0x1234567890123456789012345678901234567890");
117
131
  mockWalletProvider.getClient.mockReturnValue(mockCdpClient);
132
+ mockWalletProvider.getCdpSdkNetwork.mockReturnValue("base-sepolia");
118
133
  mockCdpClient.evm.getAccount.mockResolvedValue(mockAccount);
119
134
  });
120
135
  it("should successfully use spend permission for EVM wallets", async () => {
@@ -162,6 +177,7 @@ describe("CDP EVM Wallet Action Provider", () => {
162
177
  networkId: testCase.networkId,
163
178
  });
164
179
  mockWalletProvider.getClient.mockReturnValue(mockCdpClient);
180
+ mockWalletProvider.getCdpSdkNetwork.mockReturnValue(testCase.expected);
165
181
  mockCdpClient.evm.getAccount.mockResolvedValue(mockAccount);
166
182
  await actionProvider.useSpendPermission(mockWalletProvider, mockArgs);
167
183
  expect(mockAccount.useSpendPermission).toHaveBeenCalledWith({
@@ -176,6 +192,7 @@ describe("CDP EVM Wallet Action Provider", () => {
176
192
  protocolFamily: "evm",
177
193
  networkId: "polygon-mainnet",
178
194
  });
195
+ mockWalletProvider.getCdpSdkNetwork.mockReturnValue("polygon-mainnet");
179
196
  const mockPermission = { spender: "0x1234", token: "MATIC" };
180
197
  const mockSpendResult = { status: "completed" };
181
198
  spendPermissionUtils.findLatestSpendPermission.mockResolvedValue(mockPermission);
@@ -229,6 +246,236 @@ describe("CDP EVM Wallet Action Provider", () => {
229
246
  expect(() => schemas_1.UseSpendPermissionSchema.parse(invalidInput)).toThrow();
230
247
  });
231
248
  });
249
+ describe("getSwapPrice", () => {
250
+ const mockArgs = {
251
+ fromToken: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", // ETH
252
+ toToken: "0xA0b86991c6218b36c1d19D4a2e9EB0cE3606eB48", // USDC
253
+ fromAmount: "0.1",
254
+ slippageBps: 100,
255
+ };
256
+ beforeEach(() => {
257
+ mockWalletProvider.getClient.mockReturnValue(mockCdpClient);
258
+ mockWalletProvider.getAddress.mockReturnValue("0x1234567890123456789012345678901234567890");
259
+ mockWalletProvider.getCdpSdkNetwork.mockReturnValue("base");
260
+ mockGetTokenDetails.mockResolvedValue({
261
+ fromTokenDecimals: 18,
262
+ toTokenDecimals: 6,
263
+ fromTokenName: "ETH",
264
+ toTokenName: "USDC",
265
+ });
266
+ });
267
+ it("should get swap price quote on base-mainnet", async () => {
268
+ mockWalletProvider.getNetwork.mockReturnValue({
269
+ protocolFamily: "evm",
270
+ networkId: "base-mainnet",
271
+ });
272
+ mockCdpClient.evm.getSwapPrice.mockResolvedValue({
273
+ toAmount: "990000", // 0.99 USDC
274
+ minToAmount: "980000", // 0.98 USDC
275
+ liquidityAvailable: true,
276
+ issues: {},
277
+ });
278
+ const result = await actionProvider.getSwapPrice(mockWalletProvider, mockArgs);
279
+ const parsedResult = JSON.parse(result);
280
+ expect(mockCdpClient.evm.getSwapPrice).toHaveBeenCalledWith({
281
+ fromToken: mockArgs.fromToken,
282
+ toToken: mockArgs.toToken,
283
+ fromAmount: 100000000000000000n, // 0.1 ETH in wei
284
+ network: "base",
285
+ taker: "0x1234567890123456789012345678901234567890",
286
+ });
287
+ expect(parsedResult.success).toBe(true);
288
+ expect(parsedResult.fromAmount).toBe("0.1");
289
+ expect(parsedResult.toAmount).toBe("0.99");
290
+ expect(parsedResult.liquidityAvailable).toBe(true);
291
+ });
292
+ it("should get swap price quote on ethereum-mainnet", async () => {
293
+ mockWalletProvider.getNetwork.mockReturnValue({
294
+ protocolFamily: "evm",
295
+ networkId: "ethereum-mainnet",
296
+ });
297
+ mockWalletProvider.getCdpSdkNetwork.mockReturnValue("ethereum");
298
+ mockCdpClient.evm.getSwapPrice.mockResolvedValue({
299
+ toAmount: "990000",
300
+ minToAmount: "980000",
301
+ liquidityAvailable: true,
302
+ issues: {},
303
+ });
304
+ const result = await actionProvider.getSwapPrice(mockWalletProvider, mockArgs);
305
+ const parsedResult = JSON.parse(result);
306
+ expect(mockCdpClient.evm.getSwapPrice).toHaveBeenCalledWith({
307
+ fromToken: mockArgs.fromToken,
308
+ toToken: mockArgs.toToken,
309
+ fromAmount: 100000000000000000n,
310
+ network: "ethereum",
311
+ taker: "0x1234567890123456789012345678901234567890",
312
+ });
313
+ expect(parsedResult.success).toBe(true);
314
+ });
315
+ it("should return error for unsupported networks", async () => {
316
+ mockWalletProvider.getNetwork.mockReturnValue({
317
+ protocolFamily: "evm",
318
+ networkId: "base-sepolia",
319
+ });
320
+ const result = await actionProvider.getSwapPrice(mockWalletProvider, mockArgs);
321
+ const parsedResult = JSON.parse(result);
322
+ expect(parsedResult.success).toBe(false);
323
+ expect(parsedResult.error).toContain("CDP Swap API is currently only supported on 'base-mainnet' or 'ethereum-mainnet'");
324
+ });
325
+ it("should handle swap price API errors", async () => {
326
+ mockWalletProvider.getNetwork.mockReturnValue({
327
+ protocolFamily: "evm",
328
+ networkId: "base-mainnet",
329
+ });
330
+ mockCdpClient.evm.getSwapPrice.mockRejectedValue(new Error("API Error"));
331
+ const result = await actionProvider.getSwapPrice(mockWalletProvider, mockArgs);
332
+ const parsedResult = JSON.parse(result);
333
+ expect(parsedResult.success).toBe(false);
334
+ expect(parsedResult.error).toContain("Error fetching swap price: Error: API Error");
335
+ });
336
+ });
337
+ describe("swap", () => {
338
+ const mockArgs = {
339
+ fromToken: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", // ETH
340
+ toToken: "0xA0b86991c6218b36c1d19D4a2e9EB0cE3606eB48", // USDC
341
+ fromAmount: "0.1",
342
+ slippageBps: 100,
343
+ };
344
+ beforeEach(() => {
345
+ mockWalletProvider.getClient.mockReturnValue(mockCdpClient);
346
+ mockWalletProvider.getAddress.mockReturnValue("0x1234567890123456789012345678901234567890");
347
+ mockWalletProvider.getCdpSdkNetwork.mockReturnValue("base");
348
+ mockCdpClient.evm.getAccount.mockResolvedValue(mockAccount);
349
+ mockWalletProvider.waitForTransactionReceipt.mockResolvedValue({ status: "success" });
350
+ mockGetTokenDetails.mockResolvedValue({
351
+ fromTokenDecimals: 18,
352
+ toTokenDecimals: 6,
353
+ fromTokenName: "ETH",
354
+ toTokenName: "USDC",
355
+ });
356
+ });
357
+ it("should execute swap on base-mainnet", async () => {
358
+ mockWalletProvider.getNetwork.mockReturnValue({
359
+ protocolFamily: "evm",
360
+ networkId: "base-mainnet",
361
+ });
362
+ mockCdpClient.evm.getSwapPrice.mockResolvedValue({
363
+ liquidityAvailable: true,
364
+ issues: {},
365
+ toAmount: "990000", // 0.99 USDC
366
+ minToAmount: "980000", // 0.98 USDC
367
+ });
368
+ mockAccount.swap.mockResolvedValue({ transactionHash: "0xswap789" });
369
+ const result = await actionProvider.swap(mockWalletProvider, mockArgs);
370
+ const parsedResult = JSON.parse(result);
371
+ expect(mockCdpClient.evm.getAccount).toHaveBeenCalledWith({
372
+ address: "0x1234567890123456789012345678901234567890",
373
+ });
374
+ expect(mockAccount.swap).toHaveBeenCalledWith({
375
+ network: "base",
376
+ fromToken: mockArgs.fromToken,
377
+ toToken: mockArgs.toToken,
378
+ fromAmount: 100000000000000000n, // 0.1 ETH in wei
379
+ slippageBps: 100,
380
+ signerAddress: "0x1234567890123456789012345678901234567890",
381
+ });
382
+ expect(parsedResult.success).toBe(true);
383
+ expect(parsedResult.transactionHash).toBe("0xswap789");
384
+ expect(parsedResult.fromAmount).toBe("0.1");
385
+ expect(parsedResult.toAmount).toBe("0.99");
386
+ });
387
+ it("should return error for unsupported networks", async () => {
388
+ mockWalletProvider.getNetwork.mockReturnValue({
389
+ protocolFamily: "evm",
390
+ networkId: "base-sepolia",
391
+ });
392
+ const result = await actionProvider.swap(mockWalletProvider, mockArgs);
393
+ const parsedResult = JSON.parse(result);
394
+ expect(parsedResult.success).toBe(false);
395
+ expect(parsedResult.error).toContain("CDP Swap API is currently only supported on 'base-mainnet' or 'ethereum-mainnet'");
396
+ });
397
+ it("should return error when liquidity is not available", async () => {
398
+ mockWalletProvider.getNetwork.mockReturnValue({
399
+ protocolFamily: "evm",
400
+ networkId: "base-mainnet",
401
+ });
402
+ mockCdpClient.evm.getSwapPrice.mockResolvedValue({
403
+ liquidityAvailable: false,
404
+ issues: {},
405
+ toAmount: "0",
406
+ minToAmount: "0",
407
+ });
408
+ const result = await actionProvider.swap(mockWalletProvider, mockArgs);
409
+ const parsedResult = JSON.parse(result);
410
+ expect(parsedResult.success).toBe(false);
411
+ expect(parsedResult.error).toContain("No liquidity available to swap");
412
+ });
413
+ it("should return error when balance is insufficient", async () => {
414
+ mockWalletProvider.getNetwork.mockReturnValue({
415
+ protocolFamily: "evm",
416
+ networkId: "base-mainnet",
417
+ });
418
+ mockCdpClient.evm.getSwapPrice.mockResolvedValue({
419
+ liquidityAvailable: true,
420
+ issues: {
421
+ balance: {
422
+ currentBalance: "50000000000000000", // 0.05 ETH
423
+ },
424
+ },
425
+ toAmount: "990000",
426
+ minToAmount: "980000",
427
+ });
428
+ const result = await actionProvider.swap(mockWalletProvider, mockArgs);
429
+ const parsedResult = JSON.parse(result);
430
+ expect(parsedResult.success).toBe(false);
431
+ expect(parsedResult.error).toContain("Balance is not enough to perform swap");
432
+ expect(parsedResult.error).toContain("but only have 0.05 ETH");
433
+ });
434
+ it("should handle approval transaction when allowance is insufficient", async () => {
435
+ mockWalletProvider.getNetwork.mockReturnValue({
436
+ protocolFamily: "evm",
437
+ networkId: "base-mainnet",
438
+ });
439
+ mockCdpClient.evm.getSwapPrice.mockResolvedValue({
440
+ liquidityAvailable: true,
441
+ issues: {
442
+ allowance: {
443
+ requiredAllowance: "100000000000000000",
444
+ currentAllowance: "0",
445
+ },
446
+ },
447
+ toAmount: "990000",
448
+ minToAmount: "980000",
449
+ });
450
+ mockWalletProvider.sendTransaction.mockResolvedValue("0xapproval123");
451
+ mockWalletProvider.waitForTransactionReceipt.mockResolvedValueOnce({ status: "success" }); // For approval
452
+ mockWalletProvider.waitForTransactionReceipt.mockResolvedValueOnce({ status: "success" }); // For swap
453
+ mockAccount.swap.mockResolvedValue({ transactionHash: "0xswap789" });
454
+ const result = await actionProvider.swap(mockWalletProvider, mockArgs);
455
+ const parsedResult = JSON.parse(result);
456
+ expect(mockWalletProvider.sendTransaction).toHaveBeenCalled();
457
+ expect(parsedResult.success).toBe(true);
458
+ expect(parsedResult.approvalTxHash).toBe("0xapproval123");
459
+ expect(parsedResult.transactionHash).toBe("0xswap789");
460
+ });
461
+ it("should handle swap execution errors", async () => {
462
+ mockWalletProvider.getNetwork.mockReturnValue({
463
+ protocolFamily: "evm",
464
+ networkId: "base-mainnet",
465
+ });
466
+ mockCdpClient.evm.getSwapPrice.mockResolvedValue({
467
+ liquidityAvailable: true,
468
+ issues: {},
469
+ toAmount: "990000",
470
+ minToAmount: "980000",
471
+ });
472
+ mockAccount.swap.mockRejectedValue(new Error("Swap execution failed"));
473
+ const result = await actionProvider.swap(mockWalletProvider, mockArgs);
474
+ const parsedResult = JSON.parse(result);
475
+ expect(parsedResult.success).toBe(false);
476
+ expect(parsedResult.error).toContain("Swap failed: Error: Swap execution failed");
477
+ });
478
+ });
232
479
  describe("supportsNetwork", () => {
233
480
  it("should return true for EVM networks", () => {
234
481
  const evmNetwork = { protocolFamily: "evm", networkId: "base-sepolia" };
@@ -239,4 +486,35 @@ describe("CDP EVM Wallet Action Provider", () => {
239
486
  expect(actionProvider.supportsNetwork(svmNetwork)).toBe(false);
240
487
  });
241
488
  });
489
+ describe("SwapSchema", () => {
490
+ it("should validate correct swap input", () => {
491
+ const validInput = {
492
+ fromToken: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
493
+ toToken: "0xA0b86991c6218b36c1d19D4a2e9EB0cE3606eB48",
494
+ fromAmount: "0.1",
495
+ };
496
+ const result = schemas_1.SwapSchema.safeParse(validInput);
497
+ expect(result.success).toBe(true);
498
+ expect(result.data).toEqual({ ...validInput, slippageBps: 100 });
499
+ });
500
+ it("should validate swap input with optional slippageBps", () => {
501
+ const validInput = {
502
+ fromToken: "0xA0b86991c6218b36c1d19D4a2e9EB0cE3606eB48",
503
+ toToken: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
504
+ fromAmount: "100",
505
+ slippageBps: 50,
506
+ };
507
+ const result = schemas_1.SwapSchema.safeParse(validInput);
508
+ expect(result.success).toBe(true);
509
+ expect(result.data).toEqual(validInput);
510
+ });
511
+ it("should fail validation when missing required fields", () => {
512
+ const invalidInput = {
513
+ fromToken: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
514
+ // missing toToken and fromAmount
515
+ };
516
+ const result = schemas_1.SwapSchema.safeParse(invalidInput);
517
+ expect(result.success).toBe(false);
518
+ });
519
+ });
242
520
  });