@coinbase/agentkit 0.8.2 → 0.9.0

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 (65) hide show
  1. package/README.md +373 -234
  2. package/dist/action-providers/cdp/cdpApiActionProvider.d.ts +15 -15
  3. package/dist/action-providers/cdp/cdpApiActionProvider.js +110 -63
  4. package/dist/action-providers/cdp/cdpApiActionProvider.test.js +205 -124
  5. package/dist/action-providers/cdp/index.d.ts +0 -1
  6. package/dist/action-providers/cdp/index.js +0 -1
  7. package/dist/action-providers/cdp/schemas.d.ts +9 -70
  8. package/dist/action-providers/cdp/schemas.js +12 -61
  9. package/dist/action-providers/cdp-legacy/index.d.ts +3 -0
  10. package/dist/action-providers/{cdp-v2 → cdp-legacy}/index.js +2 -1
  11. package/dist/action-providers/cdp-legacy/legacyCdpApiActionProvider.d.ts +45 -0
  12. package/dist/action-providers/cdp-legacy/legacyCdpApiActionProvider.js +130 -0
  13. package/dist/action-providers/cdp-legacy/legacyCdpApiActionProvider.test.js +146 -0
  14. package/dist/action-providers/{cdp/cdpWalletActionProvider.d.ts → cdp-legacy/legacyCdpWalletActionProvider.d.ts} +8 -8
  15. package/dist/action-providers/{cdp/cdpWalletActionProvider.js → cdp-legacy/legacyCdpWalletActionProvider.js} +14 -14
  16. package/dist/action-providers/{cdp/cdpWalletActionProvider.test.js → cdp-legacy/legacyCdpWalletActionProvider.test.js} +3 -3
  17. package/dist/action-providers/cdp-legacy/schemas.d.ts +91 -0
  18. package/dist/action-providers/cdp-legacy/schemas.js +77 -0
  19. package/dist/action-providers/erc20/erc20ActionProvider.js +1 -1
  20. package/dist/action-providers/index.d.ts +1 -1
  21. package/dist/action-providers/index.js +1 -1
  22. package/dist/action-providers/jupiter/jupiterActionProvider.test.js +2 -4
  23. package/dist/action-providers/x402/schemas.d.ts +58 -11
  24. package/dist/action-providers/x402/schemas.js +60 -8
  25. package/dist/action-providers/x402/x402ActionProvider.d.ts +33 -16
  26. package/dist/action-providers/x402/x402ActionProvider.js +203 -153
  27. package/dist/action-providers/x402/x402ActionProvider.test.js +78 -225
  28. package/dist/agentkit.d.ts +1 -0
  29. package/dist/agentkit.js +3 -2
  30. package/dist/wallet-providers/{cdpV2EvmWalletProvider.d.ts → cdpEvmWalletProvider.d.ts} +16 -7
  31. package/dist/wallet-providers/{cdpV2EvmWalletProvider.js → cdpEvmWalletProvider.js} +50 -39
  32. package/dist/wallet-providers/{cdpV2EvmWalletProvider.test.js → cdpEvmWalletProvider.test.js} +7 -7
  33. package/dist/wallet-providers/{cdpV2Shared.d.ts → cdpShared.d.ts} +15 -4
  34. package/dist/wallet-providers/cdpSmartWalletProvider.d.ts +115 -0
  35. package/dist/wallet-providers/cdpSmartWalletProvider.js +263 -0
  36. package/dist/wallet-providers/cdpSmartWalletProvider.test.js +287 -0
  37. package/dist/wallet-providers/{cdpV2SolanaWalletProvider.d.ts → cdpSolanaWalletProvider.d.ts} +16 -7
  38. package/dist/wallet-providers/{cdpV2SolanaWalletProvider.js → cdpSolanaWalletProvider.js} +43 -32
  39. package/dist/wallet-providers/{cdpV2SolanaWalletProvider.test.js → cdpSolanaWalletProvider.test.js} +7 -7
  40. package/dist/wallet-providers/index.d.ts +6 -6
  41. package/dist/wallet-providers/index.js +6 -6
  42. package/dist/wallet-providers/{smartWalletProvider.d.ts → legacyCdpSmartWalletProvider.d.ts} +3 -3
  43. package/dist/wallet-providers/{smartWalletProvider.js → legacyCdpSmartWalletProvider.js} +21 -21
  44. package/dist/wallet-providers/legacyCdpSmartWalletProvider.test.d.ts +1 -0
  45. package/dist/wallet-providers/{smartWalletProvider.test.js → legacyCdpSmartWalletProvider.test.js} +2 -2
  46. package/dist/wallet-providers/{cdpWalletProvider.d.ts → legacyCdpWalletProvider.d.ts} +15 -11
  47. package/dist/wallet-providers/{cdpWalletProvider.js → legacyCdpWalletProvider.js} +72 -70
  48. package/dist/wallet-providers/legacyCdpWalletProvider.test.d.ts +1 -0
  49. package/dist/wallet-providers/{cdpWalletProvider.test.js → legacyCdpWalletProvider.test.js} +10 -10
  50. package/package.json +3 -2
  51. package/dist/action-providers/cdp-v2/cdpApiV2ActionProvider.d.ts +0 -34
  52. package/dist/action-providers/cdp-v2/cdpApiV2ActionProvider.js +0 -98
  53. package/dist/action-providers/cdp-v2/index.d.ts +0 -2
  54. package/dist/action-providers/cdp-v2/schemas.d.ts +0 -11
  55. package/dist/action-providers/cdp-v2/schemas.js +0 -13
  56. package/dist/wallet-providers/cdpV2WalletProvider.d.ts +0 -35
  57. package/dist/wallet-providers/cdpV2WalletProvider.js +0 -42
  58. /package/dist/action-providers/{cdp → cdp-legacy}/constants.d.ts +0 -0
  59. /package/dist/action-providers/{cdp → cdp-legacy}/constants.js +0 -0
  60. /package/dist/action-providers/{cdp/cdpWalletActionProvider.test.d.ts → cdp-legacy/legacyCdpApiActionProvider.test.d.ts} +0 -0
  61. /package/dist/{wallet-providers/cdpV2EvmWalletProvider.test.d.ts → action-providers/cdp-legacy/legacyCdpWalletActionProvider.test.d.ts} +0 -0
  62. /package/dist/wallet-providers/{cdpV2SolanaWalletProvider.test.d.ts → cdpEvmWalletProvider.test.d.ts} +0 -0
  63. /package/dist/wallet-providers/{cdpV2Shared.js → cdpShared.js} +0 -0
  64. /package/dist/wallet-providers/{cdpWalletProvider.test.d.ts → cdpSmartWalletProvider.test.d.ts} +0 -0
  65. /package/dist/wallet-providers/{smartWalletProvider.test.d.ts → cdpSolanaWalletProvider.test.d.ts} +0 -0
@@ -1,27 +1,19 @@
1
1
  import { z } from "zod";
2
- import { ActionProvider } from "../actionProvider";
3
2
  import { Network } from "../../network";
4
- import { CdpProviderConfig, WalletProvider } from "../../wallet-providers";
5
- import { AddressReputationSchema, RequestFaucetFundsSchema } from "./schemas";
3
+ import { WalletProvider } from "../../wallet-providers";
4
+ import { ActionProvider } from "../actionProvider";
5
+ import { RequestFaucetFundsV2Schema, SwapSchema } from "./schemas";
6
6
  /**
7
7
  * CdpApiActionProvider is an action provider for CDP API.
8
8
  *
9
9
  * This provider is used for any action that uses the CDP API, but does not require a CDP Wallet.
10
10
  */
11
11
  export declare class CdpApiActionProvider extends ActionProvider<WalletProvider> {
12
+ #private;
12
13
  /**
13
14
  * Constructor for the CdpApiActionProvider class.
14
- *
15
- * @param config - The configuration options for the CdpApiActionProvider.
16
- */
17
- constructor(config?: CdpProviderConfig);
18
- /**
19
- * Check the reputation of an address.
20
- *
21
- * @param args - The input arguments for the action
22
- * @returns A string containing reputation data or error message
23
15
  */
24
- addressReputation(args: z.infer<typeof AddressReputationSchema>): Promise<string>;
16
+ constructor();
25
17
  /**
26
18
  * Requests test tokens from the faucet for the default address in the wallet.
27
19
  *
@@ -29,7 +21,15 @@ export declare class CdpApiActionProvider extends ActionProvider<WalletProvider>
29
21
  * @param args - The input arguments for the action.
30
22
  * @returns A confirmation message with transaction details.
31
23
  */
32
- faucet(walletProvider: WalletProvider, args: z.infer<typeof RequestFaucetFundsSchema>): Promise<string>;
24
+ faucet(walletProvider: WalletProvider, args: z.infer<typeof RequestFaucetFundsV2Schema>): Promise<string>;
25
+ /**
26
+ * Swaps tokens using the CDP client.
27
+ *
28
+ * @param walletProvider - The wallet provider to perform the swap with.
29
+ * @param args - The input arguments for the swap action.
30
+ * @returns A confirmation message with transaction details.
31
+ */
32
+ swap(walletProvider: WalletProvider, args: z.infer<typeof SwapSchema>): Promise<string>;
33
33
  /**
34
34
  * Checks if the Cdp action provider supports the given network.
35
35
  *
@@ -40,4 +40,4 @@ export declare class CdpApiActionProvider extends ActionProvider<WalletProvider>
40
40
  */
41
41
  supportsNetwork: (_: Network) => boolean;
42
42
  }
43
- export declare const cdpApiActionProvider: (config?: CdpProviderConfig) => CdpApiActionProvider;
43
+ export declare const cdpApiActionProvider: () => CdpApiActionProvider;
@@ -8,14 +8,19 @@ 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 _CdpApiActionProvider_instances, _CdpApiActionProvider_getCdpSdkNetwork;
11
17
  Object.defineProperty(exports, "__esModule", { value: true });
12
18
  exports.cdpApiActionProvider = exports.CdpApiActionProvider = void 0;
13
- const package_json_1 = require("../../../package.json");
14
- const coinbase_sdk_1 = require("@coinbase/coinbase-sdk");
15
19
  const zod_1 = require("zod");
20
+ const wallet_providers_1 = require("../../wallet-providers");
21
+ const cdpShared_1 = require("../../wallet-providers/cdpShared");
16
22
  const actionDecorator_1 = require("../actionDecorator");
17
23
  const actionProvider_1 = require("../actionProvider");
18
- const wallet_providers_1 = require("../../wallet-providers");
19
24
  const schemas_1 = require("./schemas");
20
25
  /**
21
26
  * CdpApiActionProvider is an action provider for CDP API.
@@ -25,11 +30,10 @@ const schemas_1 = require("./schemas");
25
30
  class CdpApiActionProvider extends actionProvider_1.ActionProvider {
26
31
  /**
27
32
  * Constructor for the CdpApiActionProvider class.
28
- *
29
- * @param config - The configuration options for the CdpApiActionProvider.
30
33
  */
31
- constructor(config = {}) {
34
+ constructor() {
32
35
  super("cdp_api", []);
36
+ _CdpApiActionProvider_instances.add(this);
33
37
  /**
34
38
  * Checks if the Cdp action provider supports the given network.
35
39
  *
@@ -39,90 +43,133 @@ class CdpApiActionProvider extends actionProvider_1.ActionProvider {
39
43
  * @returns True if the Cdp action provider supports the network, false otherwise.
40
44
  */
41
45
  this.supportsNetwork = (_) => true;
42
- if (config.apiKeyId && config.apiKeySecret) {
43
- coinbase_sdk_1.Coinbase.configure({
44
- apiKeyName: config.apiKeyId,
45
- privateKey: config.apiKeySecret?.replace(/\\n/g, "\n"),
46
- source: "agentkit",
47
- sourceVersion: package_json_1.version,
48
- });
49
- }
50
- else {
51
- coinbase_sdk_1.Coinbase.configureFromJson({ source: "agentkit", sourceVersion: package_json_1.version });
52
- }
53
46
  }
54
47
  /**
55
- * Check the reputation of an address.
48
+ * Requests test tokens from the faucet for the default address in the wallet.
56
49
  *
57
- * @param args - The input arguments for the action
58
- * @returns A string containing reputation data or error message
50
+ * @param walletProvider - The wallet provider to request funds from.
51
+ * @param args - The input arguments for the action.
52
+ * @returns A confirmation message with transaction details.
59
53
  */
60
- async addressReputation(args) {
61
- if (args.network.includes("solana")) {
62
- return "Address reputation is only supported on Ethereum networks.";
63
- }
64
- try {
65
- const address = new coinbase_sdk_1.ExternalAddress(args.network, args.address);
66
- const reputation = await address.reputation();
67
- return reputation.toString();
54
+ async faucet(walletProvider, args) {
55
+ const network = walletProvider.getNetwork();
56
+ const networkId = network.networkId;
57
+ if ((0, cdpShared_1.isWalletProviderWithClient)(walletProvider)) {
58
+ if (network.protocolFamily === "evm") {
59
+ if (networkId !== "base-sepolia" && networkId !== "ethereum-sepolia") {
60
+ throw new Error("Faucet is only supported on 'base-sepolia' or 'ethereum-sepolia' evm networks.");
61
+ }
62
+ const faucetTx = await walletProvider.getClient().evm.requestFaucet({
63
+ address: walletProvider.getAddress(),
64
+ token: (args.assetId || "eth"),
65
+ network: networkId,
66
+ });
67
+ return `Received ${args.assetId || "ETH"} from the faucet. Transaction hash: ${faucetTx.transactionHash}`;
68
+ }
69
+ else if (network.protocolFamily === "svm") {
70
+ if (networkId !== "solana-devnet") {
71
+ throw new Error("Faucet is only supported on 'solana-devnet' solana networks.");
72
+ }
73
+ const faucetTx = await walletProvider.getClient().solana.requestFaucet({
74
+ address: walletProvider.getAddress(),
75
+ token: (args.assetId || "sol"),
76
+ });
77
+ return `Received ${args.assetId || "SOL"} from the faucet. Transaction signature hash: ${faucetTx.signature}`;
78
+ }
79
+ else {
80
+ throw new Error("Faucet is only supported on Ethereum and Solana protocol families.");
81
+ }
68
82
  }
69
- catch (error) {
70
- return `Error checking address reputation: ${error}`;
83
+ else {
84
+ throw new Error("Wallet provider is not a CDP Wallet Provider.");
71
85
  }
72
86
  }
73
87
  /**
74
- * Requests test tokens from the faucet for the default address in the wallet.
88
+ * Swaps tokens using the CDP client.
75
89
  *
76
- * @param walletProvider - The wallet provider to request funds from.
77
- * @param args - The input arguments for the action.
90
+ * @param walletProvider - The wallet provider to perform the swap with.
91
+ * @param args - The input arguments for the swap action.
78
92
  * @returns A confirmation message with transaction details.
79
93
  */
80
- async faucet(walletProvider, args) {
94
+ async swap(walletProvider, args) {
81
95
  const network = walletProvider.getNetwork();
82
- if (network.networkId !== "base-sepolia" && network.networkId !== "solana-devnet") {
83
- return `Faucet is only allowed on 'base-sepolia' or 'solana-devnet'.`;
84
- }
85
- try {
86
- const address = new coinbase_sdk_1.ExternalAddress(walletProvider.getNetwork().networkId, walletProvider.getAddress());
87
- const faucetTx = await address.faucet(args.assetId || undefined);
88
- const result = await faucetTx.wait({ timeoutSeconds: 60 });
89
- return `Received ${args.assetId || "ETH"} from the faucet. Transaction: ${result.getTransactionLink()}`;
96
+ const networkId = network.networkId;
97
+ if ((0, cdpShared_1.isWalletProviderWithClient)(walletProvider)) {
98
+ if (network.protocolFamily === "evm") {
99
+ try {
100
+ const cdpNetwork = __classPrivateFieldGet(this, _CdpApiActionProvider_instances, "m", _CdpApiActionProvider_getCdpSdkNetwork).call(this, networkId);
101
+ // Get the account for the wallet address
102
+ const account = await walletProvider.getClient().evm.getAccount({
103
+ address: walletProvider.getAddress(),
104
+ });
105
+ // Execute swap using the all-in-one pattern
106
+ const swapResult = await account.swap({
107
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
108
+ network: cdpNetwork,
109
+ from: args.fromAssetId,
110
+ to: args.toAssetId,
111
+ amount: args.amount,
112
+ slippageBps: 100, // 1% slippage tolerance
113
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
114
+ });
115
+ return `Successfully swapped ${args.amount} ${args.fromAssetId.toUpperCase()} to ${args.toAssetId.toUpperCase()}. Transaction hash: ${swapResult.transactionHash}`;
116
+ }
117
+ catch (error) {
118
+ throw new Error(`Swap failed: ${error}`);
119
+ }
120
+ }
121
+ else {
122
+ throw new Error("Swap is currently only supported on EVM networks.");
123
+ }
90
124
  }
91
- catch (error) {
92
- return `Error requesting faucet funds: ${error}`;
125
+ else {
126
+ throw new Error("Wallet provider is not a CDP Wallet Provider.");
93
127
  }
94
128
  }
95
129
  }
96
130
  exports.CdpApiActionProvider = CdpApiActionProvider;
97
- __decorate([
98
- (0, actionDecorator_1.CreateAction)({
99
- name: "address_reputation",
100
- description: `
101
- This tool checks the reputation of an address on a given network. It takes:
102
-
103
- - network: The network to check the address on (e.g. "base-mainnet")
104
- - address: The Ethereum address to check
105
- `,
106
- schema: schemas_1.AddressReputationSchema,
107
- }),
108
- __metadata("design:type", Function),
109
- __metadata("design:paramtypes", [void 0]),
110
- __metadata("design:returntype", Promise)
111
- ], CdpApiActionProvider.prototype, "addressReputation", null);
131
+ _CdpApiActionProvider_instances = new WeakSet(), _CdpApiActionProvider_getCdpSdkNetwork = function _CdpApiActionProvider_getCdpSdkNetwork(networkId) {
132
+ switch (networkId) {
133
+ case "base-sepolia":
134
+ return "base-sepolia";
135
+ case "base-mainnet":
136
+ return "base";
137
+ case "ethereum-sepolia":
138
+ return "ethereum-sepolia";
139
+ case "ethereum-mainnet":
140
+ return "ethereum";
141
+ default:
142
+ return networkId; // For other networks, use as-is
143
+ }
144
+ };
112
145
  __decorate([
113
146
  (0, actionDecorator_1.CreateAction)({
114
147
  name: "request_faucet_funds",
115
148
  description: `This tool will request test tokens from the faucet for the default address in the wallet. It takes the wallet and asset ID as input.
116
149
  Faucet is only allowed on 'base-sepolia' or 'solana-devnet'.
117
- If fauceting on 'base-sepolia', user can only provide asset ID 'eth' or 'usdc', if no asset ID is provided, the faucet will default to 'eth'.
118
- If fauceting on 'solana-devnet', user can only provide asset ID 'sol', if no asset ID is provided, the faucet will default to 'sol'.
150
+ If fauceting on 'base-sepolia', user can only provide asset ID 'eth', 'usdc', 'eurc' or 'cbbtc', if no asset ID is provided, the faucet will default to 'eth'.
151
+ If fauceting on 'solana-devnet', user can only provide asset ID 'sol' or 'usdc', if no asset ID is provided, the faucet will default to 'sol'.
119
152
  You are not allowed to faucet with any other network or asset ID. If you are on another network, suggest that the user sends you some ETH
120
153
  from another wallet and provide the user with your wallet details.`,
121
- schema: schemas_1.RequestFaucetFundsSchema,
154
+ schema: schemas_1.RequestFaucetFundsV2Schema,
122
155
  }),
123
156
  __metadata("design:type", Function),
124
157
  __metadata("design:paramtypes", [wallet_providers_1.WalletProvider, void 0]),
125
158
  __metadata("design:returntype", Promise)
126
159
  ], CdpApiActionProvider.prototype, "faucet", null);
127
- const cdpApiActionProvider = (config = {}) => new CdpApiActionProvider(config);
160
+ __decorate([
161
+ (0, actionDecorator_1.CreateAction)({
162
+ name: "swap",
163
+ description: `This tool swaps tokens using the CDP API. It takes the wallet, from asset ID, to asset ID, and amount as input.
164
+ Swaps are currently supported on EVM networks like Base and Ethereum.
165
+ Example usage:
166
+ - Swap 0.1 ETH to USDC: { fromAssetId: "eth", toAssetId: "usdc", amount: "0.1" }
167
+ - Swap 100 USDC to ETH: { fromAssetId: "usdc", toAssetId: "eth", amount: "100" }`,
168
+ schema: schemas_1.SwapSchema,
169
+ }),
170
+ __metadata("design:type", Function),
171
+ __metadata("design:paramtypes", [wallet_providers_1.WalletProvider, void 0]),
172
+ __metadata("design:returntype", Promise)
173
+ ], CdpApiActionProvider.prototype, "swap", null);
174
+ const cdpApiActionProvider = () => new CdpApiActionProvider();
128
175
  exports.cdpApiActionProvider = cdpApiActionProvider;
@@ -2,145 +2,226 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const cdpApiActionProvider_1 = require("./cdpApiActionProvider");
4
4
  const schemas_1 = require("./schemas");
5
- jest.mock("@coinbase/coinbase-sdk");
6
- const { ExternalAddress } = jest.requireMock("@coinbase/coinbase-sdk");
7
- describe("CDP API Action Provider Input Schemas", () => {
8
- describe("Address Reputation Schema", () => {
9
- it("should successfully parse valid input", () => {
10
- const validInput = {
11
- address: "0xe6b2af36b3bb8d47206a129ff11d5a2de2a63c83",
12
- network: "base-mainnet",
13
- };
14
- const result = schemas_1.AddressReputationSchema.safeParse(validInput);
15
- expect(result.success).toBe(true);
16
- expect(result.data).toEqual(validInput);
5
+ // Mock the CDP SDK
6
+ jest.mock("@coinbase/cdp-sdk");
7
+ describe("CDP API Action Provider", () => {
8
+ let actionProvider;
9
+ let mockWalletProvider;
10
+ let mockCdpClient;
11
+ beforeEach(() => {
12
+ jest.clearAllMocks();
13
+ const mockAccount = {
14
+ swap: jest.fn(),
15
+ };
16
+ mockCdpClient = {
17
+ evm: {
18
+ requestFaucet: jest.fn(),
19
+ getAccount: jest.fn(),
20
+ },
21
+ solana: {
22
+ requestFaucet: jest.fn(),
23
+ },
24
+ };
25
+ // Set up default mock behavior
26
+ mockCdpClient.evm.getAccount.mockResolvedValue(mockAccount);
27
+ mockWalletProvider = {
28
+ getNetwork: jest.fn(),
29
+ getAddress: jest.fn(),
30
+ getClient: jest.fn(),
31
+ };
32
+ actionProvider = new cdpApiActionProvider_1.CdpApiActionProvider();
33
+ });
34
+ describe("initialization", () => {
35
+ it("should initialize with correct provider name", () => {
36
+ expect(actionProvider.name).toBe("cdp_api");
17
37
  });
18
- it("should fail parsing invalid address", () => {
19
- const invalidInput = {
20
- address: "invalid-address",
21
- network: "base-mainnet",
38
+ it("should support all networks", () => {
39
+ const mockNetwork = { protocolFamily: "evm", networkId: "base-sepolia" };
40
+ expect(actionProvider.supportsNetwork(mockNetwork)).toBe(true);
41
+ });
42
+ });
43
+ describe("faucet", () => {
44
+ it("should request faucet funds on base-sepolia", async () => {
45
+ const mockNetwork = { protocolFamily: "evm", networkId: "base-sepolia" };
46
+ mockWalletProvider.getNetwork.mockReturnValue(mockNetwork);
47
+ mockWalletProvider.getAddress.mockReturnValue("0x123456789");
48
+ mockWalletProvider.getClient.mockReturnValue(mockCdpClient);
49
+ mockCdpClient.evm.requestFaucet.mockResolvedValue({
50
+ transactionHash: "0xabcdef123456",
51
+ });
52
+ const result = await actionProvider.faucet(mockWalletProvider, { assetId: "eth" });
53
+ expect(mockCdpClient.evm.requestFaucet).toHaveBeenCalledWith({
54
+ address: "0x123456789",
55
+ token: "eth",
56
+ network: "base-sepolia",
57
+ });
58
+ expect(result).toContain("Received eth from the faucet");
59
+ expect(result).toContain("0xabcdef123456");
60
+ });
61
+ it("should request faucet funds on solana-devnet", async () => {
62
+ const mockNetwork = { protocolFamily: "svm", networkId: "solana-devnet" };
63
+ mockWalletProvider.getNetwork.mockReturnValue(mockNetwork);
64
+ mockWalletProvider.getAddress.mockReturnValue("address123");
65
+ mockWalletProvider.getClient.mockReturnValue(mockCdpClient);
66
+ mockCdpClient.solana.requestFaucet.mockResolvedValue({
67
+ signature: "signature123",
68
+ });
69
+ const result = await actionProvider.faucet(mockWalletProvider, { assetId: "sol" });
70
+ expect(mockCdpClient.solana.requestFaucet).toHaveBeenCalledWith({
71
+ address: "address123",
72
+ token: "sol",
73
+ });
74
+ expect(result).toContain("Received sol from the faucet");
75
+ expect(result).toContain("signature123");
76
+ });
77
+ it("should throw error for unsupported EVM network", async () => {
78
+ const mockNetwork = { protocolFamily: "evm", networkId: "ethereum-mainnet" };
79
+ mockWalletProvider.getNetwork.mockReturnValue(mockNetwork);
80
+ mockWalletProvider.getClient.mockReturnValue(mockCdpClient);
81
+ await expect(actionProvider.faucet(mockWalletProvider, { assetId: "eth" })).rejects.toThrow("Faucet is only supported on 'base-sepolia' or 'ethereum-sepolia' evm networks");
82
+ });
83
+ it("should throw error for unsupported Solana network", async () => {
84
+ const mockNetwork = { protocolFamily: "svm", networkId: "solana-mainnet" };
85
+ mockWalletProvider.getNetwork.mockReturnValue(mockNetwork);
86
+ mockWalletProvider.getClient.mockReturnValue(mockCdpClient);
87
+ await expect(actionProvider.faucet(mockWalletProvider, { assetId: "sol" })).rejects.toThrow("Faucet is only supported on 'solana-devnet' solana networks");
88
+ });
89
+ it("should throw error for wallet provider without client", async () => {
90
+ const mockWalletWithoutClient = {
91
+ getNetwork: jest.fn().mockReturnValue({ protocolFamily: "evm", networkId: "base-sepolia" }),
22
92
  };
23
- const result = schemas_1.AddressReputationSchema.safeParse(invalidInput);
24
- expect(result.success).toBe(false);
93
+ await expect(actionProvider.faucet(mockWalletWithoutClient, { assetId: "eth" })).rejects.toThrow("Wallet provider is not a CDP Wallet Provider");
25
94
  });
26
95
  });
27
- describe("Request Faucet Funds Schema", () => {
28
- it("should successfully parse with optional assetId", () => {
29
- const validInput = {
30
- assetId: "eth",
96
+ describe("swap", () => {
97
+ it("should perform swap on base-sepolia", async () => {
98
+ const mockNetwork = { protocolFamily: "evm", networkId: "base-sepolia" };
99
+ mockWalletProvider.getNetwork.mockReturnValue(mockNetwork);
100
+ mockWalletProvider.getAddress.mockReturnValue("0x123456789");
101
+ mockWalletProvider.getClient.mockReturnValue(mockCdpClient);
102
+ const mockAccount = { swap: jest.fn() };
103
+ mockCdpClient.evm.getAccount.mockResolvedValue(mockAccount);
104
+ mockAccount.swap.mockResolvedValue({
105
+ transactionHash: "0xswap123456",
106
+ });
107
+ const result = await actionProvider.swap(mockWalletProvider, {
108
+ fromAssetId: "eth",
109
+ toAssetId: "usdc",
110
+ amount: "0.1",
111
+ });
112
+ expect(mockCdpClient.evm.getAccount).toHaveBeenCalledWith({
113
+ address: "0x123456789",
114
+ });
115
+ expect(mockAccount.swap).toHaveBeenCalledWith({
116
+ network: "base-sepolia",
117
+ from: "eth",
118
+ to: "usdc",
119
+ amount: "0.1",
120
+ slippageBps: 100,
121
+ });
122
+ expect(result).toContain("Successfully swapped 0.1 ETH to USDC");
123
+ expect(result).toContain("0xswap123456");
124
+ });
125
+ it("should perform swap on base-mainnet", async () => {
126
+ const mockNetwork = { protocolFamily: "evm", networkId: "base-mainnet" };
127
+ mockWalletProvider.getNetwork.mockReturnValue(mockNetwork);
128
+ mockWalletProvider.getAddress.mockReturnValue("0x123456789");
129
+ mockWalletProvider.getClient.mockReturnValue(mockCdpClient);
130
+ const mockAccount = { swap: jest.fn() };
131
+ mockCdpClient.evm.getAccount.mockResolvedValue(mockAccount);
132
+ mockAccount.swap.mockResolvedValue({
133
+ transactionHash: "0xswap789",
134
+ });
135
+ const result = await actionProvider.swap(mockWalletProvider, {
136
+ fromAssetId: "usdc",
137
+ toAssetId: "eth",
138
+ amount: "100",
139
+ });
140
+ expect(mockAccount.swap).toHaveBeenCalledWith({
141
+ network: "base", // Should convert base-mainnet to base
142
+ from: "usdc",
143
+ to: "eth",
144
+ amount: "100",
145
+ slippageBps: 100,
146
+ });
147
+ expect(result).toContain("Successfully swapped 100 USDC to ETH");
148
+ });
149
+ it("should throw error for non-EVM networks", async () => {
150
+ const mockNetwork = { protocolFamily: "svm", networkId: "solana-devnet" };
151
+ mockWalletProvider.getNetwork.mockReturnValue(mockNetwork);
152
+ mockWalletProvider.getClient.mockReturnValue(mockCdpClient);
153
+ await expect(actionProvider.swap(mockWalletProvider, {
154
+ fromAssetId: "sol",
155
+ toAssetId: "usdc",
156
+ amount: "1",
157
+ })).rejects.toThrow("Swap is currently only supported on EVM networks");
158
+ });
159
+ it("should throw error for wallet provider without client", async () => {
160
+ const mockWalletWithoutClient = {
161
+ getNetwork: jest.fn().mockReturnValue({ protocolFamily: "evm", networkId: "base-sepolia" }),
31
162
  };
32
- const result = schemas_1.RequestFaucetFundsSchema.safeParse(validInput);
163
+ await expect(actionProvider.swap(mockWalletWithoutClient, {
164
+ fromAssetId: "eth",
165
+ toAssetId: "usdc",
166
+ amount: "0.1",
167
+ })).rejects.toThrow("Wallet provider is not a CDP Wallet Provider");
168
+ });
169
+ it("should handle swap errors", async () => {
170
+ const mockNetwork = { protocolFamily: "evm", networkId: "base-sepolia" };
171
+ mockWalletProvider.getNetwork.mockReturnValue(mockNetwork);
172
+ mockWalletProvider.getAddress.mockReturnValue("0x123456789");
173
+ mockWalletProvider.getClient.mockReturnValue(mockCdpClient);
174
+ const mockAccount = { swap: jest.fn() };
175
+ mockCdpClient.evm.getAccount.mockResolvedValue(mockAccount);
176
+ mockAccount.swap.mockRejectedValue(new Error("Insufficient liquidity"));
177
+ await expect(actionProvider.swap(mockWalletProvider, {
178
+ fromAssetId: "eth",
179
+ toAssetId: "usdc",
180
+ amount: "1000",
181
+ })).rejects.toThrow("Swap failed: Error: Insufficient liquidity");
182
+ });
183
+ });
184
+ describe("RequestFaucetFundsV2Schema", () => {
185
+ it("should validate correct input", () => {
186
+ const validInput = { assetId: "eth" };
187
+ const result = schemas_1.RequestFaucetFundsV2Schema.safeParse(validInput);
33
188
  expect(result.success).toBe(true);
34
- expect(result.data).toEqual(validInput);
35
189
  });
36
- it("should successfully parse without assetId", () => {
190
+ it("should allow missing assetId", () => {
37
191
  const validInput = {};
38
- const result = schemas_1.RequestFaucetFundsSchema.safeParse(validInput);
192
+ const result = schemas_1.RequestFaucetFundsV2Schema.safeParse(validInput);
39
193
  expect(result.success).toBe(true);
40
- expect(result.data).toEqual(validInput);
41
194
  });
42
195
  });
43
- });
44
- describe("CDP API Action Provider", () => {
45
- let actionProvider;
46
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
47
- let mockExternalAddressInstance;
48
- let mockWallet;
49
- beforeEach(() => {
50
- // Reset all mocks before each test
51
- jest.clearAllMocks();
52
- actionProvider = new cdpApiActionProvider_1.CdpApiActionProvider();
53
- mockExternalAddressInstance = {
54
- reputation: jest.fn(),
55
- faucet: jest.fn(),
56
- };
57
- // Mock the constructor to return our mock instance
58
- ExternalAddress.mockImplementation(() => mockExternalAddressInstance);
59
- mockWallet = {
60
- deployToken: jest.fn(),
61
- deployContract: jest.fn(),
62
- getAddress: jest.fn().mockReturnValue("0xe6b2af36b3bb8d47206a129ff11d5a2de2a63c83"),
63
- getNetwork: jest.fn().mockReturnValue({ networkId: "base-sepolia" }),
64
- };
65
- });
66
- describe("addressReputation", () => {
67
- it("should successfully check address reputation", async () => {
68
- const args = {
69
- address: "0xe6b2af36b3bb8d47206a129ff11d5a2de2a63c83",
70
- network: "base-mainnet",
71
- };
72
- mockExternalAddressInstance.reputation.mockResolvedValue("Good reputation");
73
- const result = await actionProvider.addressReputation(args);
74
- expect(ExternalAddress).toHaveBeenCalledWith(args.network, args.address);
75
- expect(ExternalAddress).toHaveBeenCalledTimes(1);
76
- expect(mockExternalAddressInstance.reputation).toHaveBeenCalled();
77
- expect(mockExternalAddressInstance.reputation).toHaveBeenCalledTimes(1);
78
- expect(result).toBe("Good reputation");
79
- });
80
- it("should handle errors when checking reputation", async () => {
81
- const args = {
82
- address: "0xe6b2af36b3bb8d47206a129ff11d5a2de2a63c83",
83
- network: "base-mainnet",
84
- };
85
- const error = new Error("Reputation check failed");
86
- mockExternalAddressInstance.reputation.mockRejectedValue(error);
87
- const result = await actionProvider.addressReputation(args);
88
- expect(ExternalAddress).toHaveBeenCalledWith(args.network, args.address);
89
- expect(ExternalAddress).toHaveBeenCalledTimes(1);
90
- expect(mockExternalAddressInstance.reputation).toHaveBeenCalled();
91
- expect(mockExternalAddressInstance.reputation).toHaveBeenCalledTimes(1);
92
- expect(result).toBe(`Error checking address reputation: ${error}`);
93
- });
94
- it("should return error if not on Ethereum network", async () => {
95
- const args = {
96
- address: "0xe6b2af36b3bb8d47206a129ff11d5a2de2a63c83",
97
- network: "solana-devnet",
196
+ describe("SwapSchema", () => {
197
+ it("should validate correct swap input", () => {
198
+ const validInput = {
199
+ fromAssetId: "eth",
200
+ toAssetId: "usdc",
201
+ amount: "0.1",
98
202
  };
99
- const result = await actionProvider.addressReputation(args);
100
- expect(result).toBe("Address reputation is only supported on Ethereum networks.");
203
+ const result = schemas_1.SwapSchema.safeParse(validInput);
204
+ expect(result.success).toBe(true);
205
+ expect(result.data).toEqual(validInput);
101
206
  });
102
- });
103
- describe("faucet", () => {
104
- beforeEach(() => {
105
- mockExternalAddressInstance.faucet.mockResolvedValue({
106
- wait: jest.fn().mockResolvedValue({
107
- getTransactionLink: jest.fn().mockReturnValue("tx-link"),
108
- }),
109
- });
207
+ it("should validate swap input with network", () => {
208
+ const validInput = {
209
+ fromAssetId: "usdc",
210
+ toAssetId: "eth",
211
+ amount: "100",
212
+ network: "base-sepolia",
213
+ };
214
+ const result = schemas_1.SwapSchema.safeParse(validInput);
215
+ expect(result.success).toBe(true);
216
+ expect(result.data).toEqual(validInput);
110
217
  });
111
- it("should successfully request faucet funds with assetId", async () => {
112
- const args = {
113
- assetId: "eth",
218
+ it("should fail validation when missing required fields", () => {
219
+ const invalidInput = {
220
+ fromAssetId: "eth",
221
+ // missing toAssetId and amount
114
222
  };
115
- const result = await actionProvider.faucet(mockWallet, args);
116
- expect(ExternalAddress).toHaveBeenCalledWith("base-sepolia", mockWallet.getAddress());
117
- expect(ExternalAddress).toHaveBeenCalledTimes(1);
118
- expect(mockExternalAddressInstance.faucet).toHaveBeenCalledWith("eth");
119
- expect(mockExternalAddressInstance.faucet).toHaveBeenCalledTimes(1);
120
- expect(result).toContain("Received eth from the faucet");
121
- expect(result).toContain("tx-link");
122
- });
123
- it("should successfully request faucet funds without assetId", async () => {
124
- const args = {};
125
- const result = await actionProvider.faucet(mockWallet, args);
126
- expect(ExternalAddress).toHaveBeenCalledWith("base-sepolia", mockWallet.getAddress());
127
- expect(ExternalAddress).toHaveBeenCalledTimes(1);
128
- expect(mockExternalAddressInstance.faucet).toHaveBeenCalledWith(undefined);
129
- expect(mockExternalAddressInstance.faucet).toHaveBeenCalledTimes(1);
130
- expect(result).toContain("Received ETH from the faucet");
131
- });
132
- it("should handle faucet errors", async () => {
133
- const args = {};
134
- const error = new Error("Faucet request failed");
135
- mockExternalAddressInstance.faucet.mockRejectedValue(error);
136
- const result = await actionProvider.faucet(mockWallet, args);
137
- expect(result).toBe(`Error requesting faucet funds: ${error}`);
138
- });
139
- it("should return error if not on base-sepolia or solana-devnet", async () => {
140
- mockWallet.getNetwork.mockReturnValue({ networkId: "solana-mainnet", protocolFamily: "svm" });
141
- const args = {};
142
- const result = await actionProvider.faucet(mockWallet, args);
143
- expect(result).toBe("Faucet is only allowed on 'base-sepolia' or 'solana-devnet'.");
223
+ const result = schemas_1.SwapSchema.safeParse(invalidInput);
224
+ expect(result.success).toBe(false);
144
225
  });
145
226
  });
146
227
  });
@@ -1,3 +1,2 @@
1
1
  export * from "./schemas";
2
2
  export * from "./cdpApiActionProvider";
3
- export * from "./cdpWalletActionProvider";
@@ -16,4 +16,3 @@ 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("./cdpWalletActionProvider"), exports);