@coinbase/agentkit 0.10.2 → 0.10.3

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 (62) hide show
  1. package/README.md +42 -0
  2. package/dist/action-providers/cdp/cdpApiActionProvider.js +7 -30
  3. package/dist/action-providers/cdp/cdpApiActionProvider.test.js +2 -8
  4. package/dist/action-providers/cdp/faucetUtils.d.ts +38 -0
  5. package/dist/action-providers/cdp/faucetUtils.js +81 -0
  6. package/dist/action-providers/clanker/schemas.d.ts +4 -4
  7. package/dist/action-providers/enso/constants.d.ts +4 -0
  8. package/dist/action-providers/enso/constants.js +10 -0
  9. package/dist/action-providers/enso/ensoActionProvider.d.ts +34 -0
  10. package/dist/action-providers/enso/ensoActionProvider.js +125 -0
  11. package/dist/action-providers/enso/ensoActionProvider.test.d.ts +1 -0
  12. package/dist/action-providers/enso/ensoActionProvider.test.js +141 -0
  13. package/dist/action-providers/enso/index.d.ts +1 -0
  14. package/dist/action-providers/enso/index.js +17 -0
  15. package/dist/action-providers/enso/schemas.d.ts +23 -0
  16. package/dist/action-providers/enso/schemas.js +22 -0
  17. package/dist/action-providers/erc20/constants.d.ts +2 -0
  18. package/dist/action-providers/erc20/constants.js +2 -0
  19. package/dist/action-providers/erc20/erc20ActionProvider.d.ts +17 -1
  20. package/dist/action-providers/erc20/erc20ActionProvider.js +103 -1
  21. package/dist/action-providers/erc20/erc20ActionProvider.test.js +201 -0
  22. package/dist/action-providers/erc20/schemas.d.ts +29 -0
  23. package/dist/action-providers/erc20/schemas.js +34 -1
  24. package/dist/action-providers/index.d.ts +3 -1
  25. package/dist/action-providers/index.js +3 -1
  26. package/dist/action-providers/wallet/walletActionProvider.js +1 -1
  27. package/dist/action-providers/weth/constants.d.ts +0 -1
  28. package/dist/action-providers/weth/constants.js +1 -2
  29. package/dist/action-providers/weth/schemas.js +6 -2
  30. package/dist/action-providers/weth/wethActionProvider.d.ts +7 -0
  31. package/dist/action-providers/weth/wethActionProvider.js +57 -32
  32. package/dist/action-providers/weth/wethActionProvider.test.js +60 -11
  33. package/dist/action-providers/x402/utils.d.ts +4 -4
  34. package/dist/action-providers/x402/utils.js +42 -5
  35. package/dist/action-providers/x402/x402ActionProvider.d.ts +6 -6
  36. package/dist/action-providers/x402/x402ActionProvider.js +23 -8
  37. package/dist/action-providers/x402/x402ActionProvider.test.js +50 -6
  38. package/dist/action-providers/yelay/constants.d.ts +64 -0
  39. package/dist/action-providers/yelay/constants.js +137 -0
  40. package/dist/action-providers/yelay/index.d.ts +2 -0
  41. package/dist/action-providers/yelay/index.js +18 -0
  42. package/dist/action-providers/yelay/schemas.d.ts +47 -0
  43. package/dist/action-providers/yelay/schemas.js +59 -0
  44. package/dist/action-providers/yelay/types.d.ts +24 -0
  45. package/dist/action-providers/yelay/types.js +2 -0
  46. package/dist/action-providers/yelay/yelayActionProvider.d.ts +70 -0
  47. package/dist/action-providers/yelay/yelayActionProvider.js +329 -0
  48. package/dist/action-providers/yelay/yelayActionProvider.test.d.ts +1 -0
  49. package/dist/action-providers/yelay/yelayActionProvider.test.js +302 -0
  50. package/dist/wallet-providers/cdpSmartWalletProvider.js +1 -3
  51. package/dist/wallet-providers/cdpSolanaWalletProvider.d.ts +14 -0
  52. package/dist/wallet-providers/cdpSolanaWalletProvider.js +39 -3
  53. package/dist/wallet-providers/cdpSolanaWalletProvider.test.js +16 -0
  54. package/dist/wallet-providers/privySvmWalletProvider.d.ts +14 -0
  55. package/dist/wallet-providers/privySvmWalletProvider.js +17 -0
  56. package/dist/wallet-providers/privySvmWalletProvider.test.js +10 -0
  57. package/dist/wallet-providers/solanaKeypairWalletProvider.d.ts +14 -0
  58. package/dist/wallet-providers/solanaKeypairWalletProvider.js +17 -0
  59. package/dist/wallet-providers/svmWalletProvider.d.ts +34 -0
  60. package/dist/wallet-providers/svmWalletProvider.js +43 -0
  61. package/dist/wallet-providers/svmWalletProvider.test.js +10 -0
  62. package/package.json +3 -1
@@ -0,0 +1,329 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.yelayActionProvider = exports.YelayActionProvider = void 0;
13
+ const zod_1 = require("zod");
14
+ const actionProvider_1 = require("../actionProvider");
15
+ const actionDecorator_1 = require("../actionDecorator");
16
+ const wallet_providers_1 = require("../../wallet-providers");
17
+ const schemas_1 = require("./schemas");
18
+ const constants_1 = require("./constants");
19
+ const viem_1 = require("viem");
20
+ const utils_1 = require("../../utils");
21
+ // Mainnet, Sonic, Base, Arbitrum, Avalanche
22
+ const SUPPORTED_CHAIN_IDS = ["1", "146", "8453", "42161", "43114"];
23
+ /**
24
+ * YelayActionProvider provides actions for yelay operations.
25
+ *
26
+ * @description
27
+ * This provider is designed to work with EvmWalletProvider for blockchain interactions.
28
+ * It supports all evm networks.
29
+ */
30
+ class YelayActionProvider extends actionProvider_1.ActionProvider {
31
+ /**
32
+ * Constructor for the YelayActionProvider.
33
+ */
34
+ constructor() {
35
+ super("yelay", []);
36
+ }
37
+ /**
38
+ * Gets the details of the Yelay vaults with their last week APY.
39
+ *
40
+ * @param wallet - The wallet instance to get chainId
41
+ * @returns A formatted string containing the list of vaults with their APY.
42
+ */
43
+ async getVaults(wallet) {
44
+ let vaultsResponse;
45
+ let vaultAPYsResponse;
46
+ try {
47
+ const chainId = wallet.getNetwork().chainId;
48
+ [vaultsResponse, vaultAPYsResponse] = await Promise.all([
49
+ fetch(`${constants_1.YELAY_BACKEND_URL}/vaults?chainId=${chainId}`),
50
+ fetch(`${constants_1.YELAY_BACKEND_URL}/interest/vaults?chainId=${chainId}`),
51
+ ]);
52
+ if (!vaultsResponse.ok || !vaultAPYsResponse.ok) {
53
+ const errorMessage = !vaultsResponse.ok
54
+ ? `Failed to fetch vaults: ${vaultsResponse.status} ${vaultsResponse.statusText}`
55
+ : `Failed to fetch APYs: ${vaultAPYsResponse.status} ${vaultAPYsResponse.statusText}`;
56
+ throw new Error(errorMessage);
57
+ }
58
+ const [vaults, vaultAPYs] = await Promise.all([
59
+ vaultsResponse.json(),
60
+ vaultAPYsResponse.json(),
61
+ ]);
62
+ const vaultsDetails = vaults.map(vault => ({
63
+ ...vault,
64
+ apy: vaultAPYs.find(apy => apy.vault === vault.address)?.apy,
65
+ }));
66
+ return vaultsDetails
67
+ .map(vault => `
68
+ ${vault.name}:
69
+ Address: ${vault.address}
70
+ APY: ${vault.apy}%
71
+ `)
72
+ .join("----------------");
73
+ }
74
+ catch (error) {
75
+ return `Error fetching vault data: ${error}`;
76
+ }
77
+ }
78
+ /**
79
+ * Deposits assets into a Yelay Vault
80
+ *
81
+ * @param wallet - The wallet instance to execute the transaction
82
+ * @param args - The input arguments for the action
83
+ * @returns A success message with transaction details or an error message
84
+ */
85
+ async deposit(wallet, args) {
86
+ try {
87
+ const chainId = wallet.getNetwork().chainId;
88
+ const vaultsResponse = await fetch(`${constants_1.YELAY_BACKEND_URL}/vaults?chainId=${chainId}`);
89
+ const vaults = (await vaultsResponse.json());
90
+ const vault = vaults.find(vault => vault.address === args.vaultAddress);
91
+ if (!vault) {
92
+ return "Error: Vault not found";
93
+ }
94
+ const atomicAssets = (0, viem_1.parseUnits)(args.assets, vault.decimals);
95
+ if (atomicAssets <= 0) {
96
+ return "Error: Assets amount must be greater than 0";
97
+ }
98
+ await (0, utils_1.approve)(wallet, vault.underlying, args.vaultAddress, atomicAssets);
99
+ const data = (0, viem_1.encodeFunctionData)({
100
+ abi: constants_1.YELAY_VAULT_ABI,
101
+ functionName: "deposit",
102
+ args: [atomicAssets, constants_1.RETAIL_POOL_ID, wallet.getAddress()],
103
+ });
104
+ const txHash = await wallet.sendTransaction({ to: args.vaultAddress, data });
105
+ await wallet.waitForTransactionReceipt(txHash);
106
+ return `Deposited ${args.assets} to Yelay Vault ${args.vaultAddress} with transaction hash: ${txHash}`;
107
+ }
108
+ catch (error) {
109
+ return `Error depositing to Yelay Vault: ${error}`;
110
+ }
111
+ }
112
+ /**
113
+ * Redeems assets from a Yelay Vault
114
+ *
115
+ * @param wallet - The wallet instance to execute the transaction
116
+ * @param args - The input arguments for the action
117
+ * @returns A success message with transaction details or an error message
118
+ */
119
+ async redeem(wallet, args) {
120
+ try {
121
+ const chainId = wallet.getNetwork().chainId;
122
+ const vaultsResponse = await fetch(`${constants_1.YELAY_BACKEND_URL}/vaults?chainId=${chainId}`);
123
+ const vaults = (await vaultsResponse.json());
124
+ const vault = vaults.find(vault => vault.address === args.vaultAddress);
125
+ if (!vault) {
126
+ return "Error: Vault not found";
127
+ }
128
+ const atomicAssets = (0, viem_1.parseUnits)(args.assets, vault.decimals);
129
+ if (atomicAssets <= 0) {
130
+ return "Error: Assets amount must be greater than 0";
131
+ }
132
+ const data = (0, viem_1.encodeFunctionData)({
133
+ abi: constants_1.YELAY_VAULT_ABI,
134
+ functionName: "redeem",
135
+ args: [atomicAssets, constants_1.RETAIL_POOL_ID, wallet.getAddress()],
136
+ });
137
+ const txHash = await wallet.sendTransaction({ to: args.vaultAddress, data });
138
+ await wallet.waitForTransactionReceipt(txHash);
139
+ return `Redeemed ${args.assets} from Yelay Vault ${args.vaultAddress} with transaction hash: ${txHash}`;
140
+ }
141
+ catch (error) {
142
+ return `Error redeeming from Yelay Vault: ${error}`;
143
+ }
144
+ }
145
+ /**
146
+ * Claims yield from Yelay
147
+ *
148
+ * @param wallet - The wallet instance to execute the transaction
149
+ * @param args - The input arguments for the action
150
+ * @returns A success message with transaction details or an error message
151
+ */
152
+ async claim(wallet, args) {
153
+ try {
154
+ const chainId = wallet.getNetwork().chainId;
155
+ const claimRequestResponse = await fetch(`${constants_1.YELAY_BACKEND_URL}/claim-proof?chainId=${chainId}&u=${wallet.getAddress()}&p=${constants_1.RETAIL_POOL_ID}&v=${args.vaultAddress}`);
156
+ const claimRequests = await claimRequestResponse.json();
157
+ if (claimRequests.length === 0) {
158
+ return "Error: No claim requests found";
159
+ }
160
+ try {
161
+ const data = (0, viem_1.encodeFunctionData)({
162
+ abi: constants_1.YIELD_EXTRACTOR_ABI,
163
+ functionName: "claim",
164
+ args: [claimRequests],
165
+ });
166
+ const txHash = await wallet.sendTransaction({
167
+ to: constants_1.CONTRACTS_BY_CHAIN[chainId].YieldExtractor,
168
+ data,
169
+ });
170
+ await wallet.waitForTransactionReceipt(txHash);
171
+ return claimRequests
172
+ .map(c => `Claimed ${c.yieldSharesTotal} from Yelay Vault ${args.vaultAddress} with transaction hash: ${txHash}`)
173
+ .join("\n");
174
+ }
175
+ catch (error) {
176
+ return `Error claiming yield from Yelay Vault: ${error}`;
177
+ }
178
+ }
179
+ catch (error) {
180
+ return `Error obtaining proof for yield to claim from Yelay Vault: ${error}`;
181
+ }
182
+ }
183
+ /**
184
+ * Gets user balance from Yelay
185
+ *
186
+ * @param wallet - The wallet instance to execute the transaction
187
+ * @param args - The input arguments for the action
188
+ * @returns A success message with user postion, generated and claimedyield
189
+ */
190
+ async getBalance(wallet, args) {
191
+ try {
192
+ const chainId = wallet.getNetwork().chainId;
193
+ const vaultsResponse = await fetch(`${constants_1.YELAY_BACKEND_URL}/vaults?chainId=${chainId}`);
194
+ const vaults = (await vaultsResponse.json());
195
+ const vault = vaults.find(vault => vault.address === args.vaultAddress);
196
+ if (!vault) {
197
+ return "Error: Vault not found";
198
+ }
199
+ const balance = (await wallet.readContract({
200
+ address: args.vaultAddress,
201
+ abi: constants_1.YELAY_VAULT_ABI,
202
+ functionName: "balanceOf",
203
+ args: [wallet.getAddress(), constants_1.RETAIL_POOL_ID],
204
+ }));
205
+ const balanceInWholeUnits = (0, viem_1.formatUnits)(balance, vault.decimals);
206
+ const balanceResponse = await fetch(`${constants_1.YELAY_BACKEND_URL}/claim-proof?chainId=${chainId}&u=${wallet.getAddress()}&p=${constants_1.RETAIL_POOL_ID}&v=${args.vaultAddress}`);
207
+ if (!balanceResponse.ok) {
208
+ throw new Error("Claim proof failed");
209
+ }
210
+ const claimRequests = await balanceResponse.json();
211
+ if (claimRequests.length === 0) {
212
+ return `User balance from Yelay Vault ${args.vaultAddress}: ${balanceInWholeUnits}`;
213
+ }
214
+ const claimRequest = claimRequests[0];
215
+ const yieldSharesClaimed = (await wallet.readContract({
216
+ address: constants_1.CONTRACTS_BY_CHAIN[chainId].YieldExtractor,
217
+ abi: constants_1.YIELD_EXTRACTOR_ABI,
218
+ functionName: "yieldSharesClaimed",
219
+ args: [wallet.getAddress(), args.vaultAddress, constants_1.RETAIL_POOL_ID],
220
+ }));
221
+ return `
222
+ User balance from Yelay Vault ${args.vaultAddress}: ${balanceInWholeUnits}
223
+ Yield shares generated: ${claimRequest.yieldSharesTotal}
224
+ Yield shares claimed: ${yieldSharesClaimed}`;
225
+ }
226
+ catch (error) {
227
+ return `Error getting balance from Yelay Vault: ${error}`;
228
+ }
229
+ }
230
+ /**
231
+ * Checks if this provider supports the given network.
232
+ *
233
+ * @param network - The network to check support for
234
+ * @returns True if the network is supported
235
+ */
236
+ supportsNetwork(network) {
237
+ return (network.protocolFamily === "evm" &&
238
+ (network.chainId ? SUPPORTED_CHAIN_IDS.includes(network.chainId) : false));
239
+ }
240
+ }
241
+ exports.YelayActionProvider = YelayActionProvider;
242
+ __decorate([
243
+ (0, actionDecorator_1.CreateAction)({
244
+ name: "get_vaults",
245
+ description: `Getting Yelay vaults for the base network`,
246
+ schema: zod_1.z.object({}),
247
+ }),
248
+ __metadata("design:type", Function),
249
+ __metadata("design:paramtypes", [wallet_providers_1.EvmWalletProvider]),
250
+ __metadata("design:returntype", Promise)
251
+ ], YelayActionProvider.prototype, "getVaults", null);
252
+ __decorate([
253
+ (0, actionDecorator_1.CreateAction)({
254
+ name: "deposit",
255
+ description: `
256
+ This action deposits assets into a specified Yelay Vault.
257
+
258
+ It takes:
259
+ - assets: The amount of assets to deposit in whole units
260
+ Examples for WETH:
261
+ - 1 WETH
262
+ - 0.1 WETH
263
+ - 0.01 WETH
264
+ - vaultAddress: The address of the Yelay Vault to deposit to
265
+
266
+ Important notes:
267
+ - Make sure to use the exact amount provided. Do not convert units for assets for this action.
268
+ `,
269
+ schema: schemas_1.YelayDepositSchema,
270
+ }),
271
+ __metadata("design:type", Function),
272
+ __metadata("design:paramtypes", [wallet_providers_1.EvmWalletProvider, void 0]),
273
+ __metadata("design:returntype", Promise)
274
+ ], YelayActionProvider.prototype, "deposit", null);
275
+ __decorate([
276
+ (0, actionDecorator_1.CreateAction)({
277
+ name: "redeem",
278
+ description: `
279
+ This tool allows redeeming assets from a Yelay Vault.
280
+ It takes:
281
+ - assets: The amount of assets to redeem in atomic units (wei)
282
+ - vaultAddress: The address of the vault to redeem from
283
+
284
+ Important notes:
285
+ - Make sure to use the exact amount provided. Do not convert units for assets for this action.
286
+ `,
287
+ schema: schemas_1.YelayRedeemSchema,
288
+ }),
289
+ __metadata("design:type", Function),
290
+ __metadata("design:paramtypes", [wallet_providers_1.EvmWalletProvider, void 0]),
291
+ __metadata("design:returntype", Promise)
292
+ ], YelayActionProvider.prototype, "redeem", null);
293
+ __decorate([
294
+ (0, actionDecorator_1.CreateAction)({
295
+ name: "claim",
296
+ description: `
297
+ This tool allows claiming yield from a Yelay Vault.
298
+ It takes:
299
+ - vaultAddress: The address of the Yelay Vault to claim yield from
300
+ `,
301
+ schema: schemas_1.YelayClaimSchema,
302
+ }),
303
+ __metadata("design:type", Function),
304
+ __metadata("design:paramtypes", [wallet_providers_1.EvmWalletProvider, void 0]),
305
+ __metadata("design:returntype", Promise)
306
+ ], YelayActionProvider.prototype, "claim", null);
307
+ __decorate([
308
+ (0, actionDecorator_1.CreateAction)({
309
+ name: "get_balance",
310
+ description: `
311
+ This tool allows getting user balance from Yelay.
312
+ It takes:
313
+ - vaultAddress: The address of the Yelay Vault to get balance from
314
+ `,
315
+ schema: schemas_1.YelayBalanceSchema,
316
+ }),
317
+ __metadata("design:type", Function),
318
+ __metadata("design:paramtypes", [wallet_providers_1.EvmWalletProvider, void 0]),
319
+ __metadata("design:returntype", Promise)
320
+ ], YelayActionProvider.prototype, "getBalance", null);
321
+ /**
322
+ * Creates a new YelayActionProvider instance
323
+ *
324
+ * @returns A new YelayActionProvider instance
325
+ */
326
+ const yelayActionProvider = () => {
327
+ return new YelayActionProvider();
328
+ };
329
+ exports.yelayActionProvider = yelayActionProvider;
@@ -0,0 +1,302 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const yelayActionProvider_1 = require("./yelayActionProvider");
4
+ const constants_1 = require("./constants");
5
+ const viem_1 = require("viem");
6
+ const mockFetchResult = (status, data) => {
7
+ return {
8
+ json: async () => data,
9
+ status,
10
+ ok: status >= 200 && status < 400,
11
+ };
12
+ };
13
+ const MOCK_VAULT_ADDRESS = "0x1234567890123456789012345678901234567890";
14
+ const MOCK_WHOLE_ASSETS = "1";
15
+ const MOCK_RECEIVER_ID = "0x9876543210987654321098765432109876543210";
16
+ const MOCK_TX_HASH = "0xabcdef1234567890";
17
+ const MOCK_RECEIPT = { status: 1, blockNumber: 1234567 };
18
+ const MOCK_DECIMALS = 18;
19
+ const BASE_CHAIN_ID = "8453";
20
+ const mockVaults = [
21
+ {
22
+ address: MOCK_VAULT_ADDRESS,
23
+ name: "Base WETH Vault",
24
+ decimals: 18,
25
+ chainId: BASE_CHAIN_ID,
26
+ underlying: "0x123...",
27
+ },
28
+ {
29
+ address: "0x456...",
30
+ name: "Base USDC Vault",
31
+ decimals: 6,
32
+ chainId: BASE_CHAIN_ID,
33
+ underlying: "0x456...",
34
+ },
35
+ ];
36
+ const mockAPYs = [
37
+ {
38
+ vault: MOCK_VAULT_ADDRESS,
39
+ startBlock: 1000,
40
+ finishBlock: 2000,
41
+ startTimestamp: 1234567890,
42
+ finishTimestamp: 1234667890,
43
+ yield: "100",
44
+ apy: "3.4",
45
+ },
46
+ {
47
+ vault: "0x456...",
48
+ startBlock: 1000,
49
+ finishBlock: 2000,
50
+ startTimestamp: 1234567890,
51
+ finishTimestamp: 1234667890,
52
+ yield: "50",
53
+ apy: "5.2",
54
+ },
55
+ ];
56
+ const mockClaimProof = [
57
+ {
58
+ yelayLiteVault: MOCK_VAULT_ADDRESS,
59
+ projectId: constants_1.RETAIL_POOL_ID,
60
+ cycle: 1,
61
+ yieldSharesTotal: "100",
62
+ proof: ["0x1234567890123456789012345678901234567890123456789012345678901234"], // 32 bites string,
63
+ },
64
+ ];
65
+ describe("YelayActionProvider", () => {
66
+ const provider = new yelayActionProvider_1.YelayActionProvider();
67
+ let mockWallet;
68
+ let mockedFetch;
69
+ const originalFetch = global.fetch;
70
+ beforeAll(() => {
71
+ global.fetch = mockedFetch = jest.fn();
72
+ });
73
+ afterAll(() => {
74
+ global.fetch = originalFetch;
75
+ });
76
+ beforeEach(() => {
77
+ mockWallet = {
78
+ getAddress: jest.fn().mockReturnValue(MOCK_RECEIVER_ID),
79
+ getNetwork: jest.fn().mockReturnValue({ protocolFamily: "evm", chainId: BASE_CHAIN_ID }),
80
+ sendTransaction: jest.fn().mockResolvedValue(MOCK_TX_HASH),
81
+ waitForTransactionReceipt: jest.fn().mockResolvedValue(MOCK_RECEIPT),
82
+ readContract: jest.fn().mockResolvedValue(MOCK_DECIMALS),
83
+ };
84
+ });
85
+ describe("network support", () => {
86
+ it("should support the protocol EVM family", () => {
87
+ expect(provider.supportsNetwork({
88
+ protocolFamily: "evm",
89
+ chainId: "8453",
90
+ })).toBe(true);
91
+ });
92
+ it("should support the Base, Mainnet, Sonic, Arbitrum and Avalanche networks", () => {
93
+ const networks = ["1", "146", "8453", "42161", "43114"];
94
+ networks.forEach(network => {
95
+ expect(provider.supportsNetwork({
96
+ protocolFamily: "evm",
97
+ chainId: network,
98
+ })).toBe(true);
99
+ });
100
+ });
101
+ it("should not support other networks", () => {
102
+ expect(provider.supportsNetwork({
103
+ protocolFamily: "evm",
104
+ chainId: "10",
105
+ })).toBe(false);
106
+ });
107
+ it("should not support other protocol families", () => {
108
+ expect(provider.supportsNetwork({
109
+ protocolFamily: "other-protocol-family",
110
+ chainId: "8453",
111
+ })).toBe(false);
112
+ });
113
+ });
114
+ describe("getVaults action", () => {
115
+ it("returns list of vaults with their APYs", async () => {
116
+ mockedFetch
117
+ .mockResolvedValueOnce(mockFetchResult(200, mockVaults))
118
+ .mockResolvedValueOnce(mockFetchResult(200, mockAPYs));
119
+ const result = await provider.getVaults(mockWallet);
120
+ expect(result).toBe(`
121
+ Base WETH Vault:
122
+ Address: ${MOCK_VAULT_ADDRESS}
123
+ APY: 3.4%
124
+ ----------------
125
+ Base USDC Vault:
126
+ Address: 0x456...
127
+ APY: 5.2%
128
+ `);
129
+ });
130
+ it("returns error message when vaults API fails", async () => {
131
+ mockedFetch.mockResolvedValue(mockFetchResult(500, mockVaults));
132
+ const result = await provider.getVaults(mockWallet);
133
+ expect(result).toContain(`Error fetching vault data:`);
134
+ });
135
+ it("returns error message when APY API fails", async () => {
136
+ mockedFetch.mockResolvedValue(mockFetchResult(500, mockAPYs));
137
+ const result = await provider.getVaults(mockWallet);
138
+ expect(result).toContain(`Error fetching vault data:`);
139
+ });
140
+ });
141
+ describe("deposit action", () => {
142
+ it("should deposit assets into a specified Yelay Vault", async () => {
143
+ const args = {
144
+ assets: MOCK_WHOLE_ASSETS,
145
+ vaultAddress: MOCK_VAULT_ADDRESS,
146
+ };
147
+ mockedFetch.mockResolvedValueOnce(mockFetchResult(200, mockVaults));
148
+ const atomicAssets = (0, viem_1.parseEther)(MOCK_WHOLE_ASSETS);
149
+ const response = await provider.deposit(mockWallet, args);
150
+ expect(mockWallet.sendTransaction).toHaveBeenCalledWith({
151
+ to: args.vaultAddress,
152
+ data: (0, viem_1.encodeFunctionData)({
153
+ abi: constants_1.YELAY_VAULT_ABI,
154
+ functionName: "deposit",
155
+ args: [atomicAssets, constants_1.RETAIL_POOL_ID, MOCK_RECEIVER_ID],
156
+ }),
157
+ });
158
+ expect(mockWallet.waitForTransactionReceipt).toHaveBeenCalledWith(MOCK_TX_HASH);
159
+ expect(response).toContain(`Deposited ${MOCK_WHOLE_ASSETS}`);
160
+ expect(response).toContain(MOCK_TX_HASH);
161
+ });
162
+ it("should return error message when deposit fails", async () => {
163
+ mockedFetch.mockResolvedValueOnce(mockFetchResult(200, mockVaults));
164
+ mockWallet.sendTransaction.mockRejectedValue(new Error("Deposit failed"));
165
+ const args = {
166
+ assets: MOCK_WHOLE_ASSETS,
167
+ vaultAddress: MOCK_VAULT_ADDRESS,
168
+ };
169
+ const response = await provider.deposit(mockWallet, args);
170
+ expect(response).toContain("Deposit failed");
171
+ });
172
+ });
173
+ describe("redeem action", () => {
174
+ it("should redeem assets from a specified Yelay Vault", async () => {
175
+ const args = {
176
+ assets: MOCK_WHOLE_ASSETS,
177
+ vaultAddress: MOCK_VAULT_ADDRESS,
178
+ };
179
+ mockedFetch.mockResolvedValueOnce(mockFetchResult(200, mockVaults));
180
+ const response = await provider.redeem(mockWallet, args);
181
+ const atomicAssets = (0, viem_1.parseEther)(MOCK_WHOLE_ASSETS);
182
+ expect(mockWallet.sendTransaction).toHaveBeenCalledWith({
183
+ to: args.vaultAddress,
184
+ data: (0, viem_1.encodeFunctionData)({
185
+ abi: constants_1.YELAY_VAULT_ABI,
186
+ functionName: "redeem",
187
+ args: [atomicAssets, constants_1.RETAIL_POOL_ID, MOCK_RECEIVER_ID],
188
+ }),
189
+ });
190
+ expect(mockWallet.waitForTransactionReceipt).toHaveBeenCalledWith(MOCK_TX_HASH);
191
+ expect(response).toContain(`Redeemed ${MOCK_WHOLE_ASSETS}`);
192
+ expect(response).toContain(MOCK_TX_HASH);
193
+ });
194
+ it("should return error message when redeem fails", async () => {
195
+ mockedFetch.mockResolvedValueOnce(mockFetchResult(200, mockVaults));
196
+ mockWallet.sendTransaction.mockRejectedValue(new Error("Redeem failed"));
197
+ const args = {
198
+ assets: MOCK_WHOLE_ASSETS,
199
+ vaultAddress: MOCK_VAULT_ADDRESS,
200
+ };
201
+ const response = await provider.redeem(mockWallet, args);
202
+ expect(response).toContain("Redeem failed");
203
+ });
204
+ });
205
+ describe("claim action", () => {
206
+ it("should claim yield from a specified Yelay Vault", async () => {
207
+ const args = {
208
+ vaultAddress: MOCK_VAULT_ADDRESS,
209
+ };
210
+ mockedFetch.mockResolvedValue(mockFetchResult(200, mockClaimProof));
211
+ const response = await provider.claim(mockWallet, args);
212
+ expect(mockWallet.sendTransaction).toHaveBeenCalledWith({
213
+ to: constants_1.CONTRACTS_BY_CHAIN[BASE_CHAIN_ID].YieldExtractor,
214
+ data: (0, viem_1.encodeFunctionData)({
215
+ abi: constants_1.YIELD_EXTRACTOR_ABI,
216
+ functionName: "claim",
217
+ args: [mockClaimProof],
218
+ }),
219
+ });
220
+ expect(mockWallet.waitForTransactionReceipt).toHaveBeenCalledWith(MOCK_TX_HASH);
221
+ expect(response).toContain(`Claimed ${mockClaimProof[0].yieldSharesTotal}`);
222
+ expect(response).toContain(`Yelay Vault ${MOCK_VAULT_ADDRESS}`);
223
+ expect(response).toContain(MOCK_TX_HASH);
224
+ });
225
+ it("should return error message when claim fails", async () => {
226
+ mockWallet.sendTransaction.mockRejectedValue(new Error("Claim failed"));
227
+ const args = {
228
+ vaultAddress: MOCK_VAULT_ADDRESS,
229
+ };
230
+ const response = await provider.claim(mockWallet, args);
231
+ expect(response).toContain("Claim failed");
232
+ });
233
+ });
234
+ describe("balance action", () => {
235
+ it("should get balance from a specified Yelay Vault", async () => {
236
+ const args = {
237
+ vaultAddress: MOCK_VAULT_ADDRESS,
238
+ };
239
+ const balance = BigInt("1000000000000000000"); // 1 ETH in wei
240
+ const yieldSharesClaimed = BigInt("50");
241
+ const expectedBalanceInWholeUnits = (0, viem_1.formatUnits)(balance, MOCK_DECIMALS);
242
+ mockWallet.readContract
243
+ .mockResolvedValueOnce(balance)
244
+ .mockResolvedValueOnce(yieldSharesClaimed);
245
+ mockedFetch
246
+ .mockResolvedValueOnce(mockFetchResult(200, mockVaults))
247
+ .mockResolvedValueOnce(mockFetchResult(200, mockClaimProof));
248
+ const response = await provider.getBalance(mockWallet, args);
249
+ expect(response).toContain(`User balance from Yelay Vault ${MOCK_VAULT_ADDRESS}: ${expectedBalanceInWholeUnits}`);
250
+ expect(response).toContain(`Yield shares generated: ${mockClaimProof[0].yieldSharesTotal}`);
251
+ expect(response).toContain(`Yield shares claimed: ${yieldSharesClaimed}`);
252
+ });
253
+ it("should return only user balance when there is no claimable yield", async () => {
254
+ const balance = BigInt("1000000000000000000"); // 1 ETH in wei
255
+ const expectedBalanceInWholeUnits = (0, viem_1.formatUnits)(balance, MOCK_DECIMALS);
256
+ mockWallet.readContract.mockResolvedValueOnce(balance);
257
+ mockedFetch
258
+ .mockResolvedValueOnce(mockFetchResult(200, mockVaults))
259
+ .mockResolvedValueOnce(mockFetchResult(200, []));
260
+ const args = {
261
+ vaultAddress: MOCK_VAULT_ADDRESS,
262
+ };
263
+ const response = await provider.getBalance(mockWallet, args);
264
+ expect(response).toContain(`User balance from Yelay Vault ${MOCK_VAULT_ADDRESS}: ${expectedBalanceInWholeUnits}`);
265
+ });
266
+ it("should return error message when vault doesn't match", async () => {
267
+ mockedFetch.mockResolvedValueOnce(mockFetchResult(200, []));
268
+ const args = {
269
+ vaultAddress: MOCK_VAULT_ADDRESS,
270
+ };
271
+ const response = await provider.getBalance(mockWallet, args);
272
+ expect(response).toContain("Vault not found");
273
+ });
274
+ it("should return error message when balance fails", async () => {
275
+ mockedFetch.mockResolvedValueOnce(mockFetchResult(200, mockVaults));
276
+ mockWallet.readContract.mockRejectedValue(new Error("Balance failed"));
277
+ const args = {
278
+ vaultAddress: MOCK_VAULT_ADDRESS,
279
+ };
280
+ const response = await provider.getBalance(mockWallet, args);
281
+ expect(response).toContain("Balance failed");
282
+ });
283
+ it("should return error message when claim proof fails", async () => {
284
+ mockedFetch.mockResolvedValueOnce(mockFetchResult(200, mockVaults));
285
+ mockedFetch.mockResolvedValue(mockFetchResult(500, mockClaimProof));
286
+ const args = {
287
+ vaultAddress: MOCK_VAULT_ADDRESS,
288
+ };
289
+ const response = await provider.getBalance(mockWallet, args);
290
+ expect(response).toContain("Claim proof failed");
291
+ });
292
+ it("should return error message when yield shares claimed fails", async () => {
293
+ mockedFetch.mockResolvedValueOnce(mockFetchResult(200, mockVaults));
294
+ mockWallet.readContract.mockRejectedValue(new Error("Yield shares claimed failed"));
295
+ const args = {
296
+ vaultAddress: MOCK_VAULT_ADDRESS,
297
+ };
298
+ const response = await provider.getBalance(mockWallet, args);
299
+ expect(response).toContain("Yield shares claimed failed");
300
+ });
301
+ });
302
+ });
@@ -246,15 +246,13 @@ class CdpSmartWalletProvider extends evmWalletProvider_1.EvmWalletProvider {
246
246
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
247
247
  async waitForTransactionReceipt(userOpHash) {
248
248
  // For smart wallets, we need to wait for the user operation to be confirmed
249
- // This is a simplified implementation - in practice you might want to poll
250
- // the CDP API for user operation status
251
249
  const receipt = await __classPrivateFieldGet(this, _CdpSmartWalletProvider_cdp, "f").evm.waitForUserOperation({
252
250
  smartAccountAddress: this.smartAccount.address,
253
251
  userOpHash,
254
252
  });
255
253
  // Append transaction logs if available
256
254
  if (receipt.status === "complete") {
257
- const receiptTx = await __classPrivateFieldGet(this, _CdpSmartWalletProvider_publicClient, "f").getTransactionReceipt({
255
+ const receiptTx = await __classPrivateFieldGet(this, _CdpSmartWalletProvider_publicClient, "f").waitForTransactionReceipt({
258
256
  hash: receipt.transactionHash,
259
257
  });
260
258
  if (receiptTx.logs)
@@ -1,4 +1,5 @@
1
1
  import { CdpClient } from "@coinbase/cdp-sdk";
2
+ import type { KeyPairSigner } from "@solana/kit";
2
3
  import { Connection, PublicKey, RpcResponseAndContext, SignatureResult, SignatureStatus, SignatureStatusConfig, VersionedTransaction } from "@solana/web3.js";
3
4
  import { Network } from "../network";
4
5
  import { WalletProviderWithClient, CdpWalletProviderConfig } from "./cdpShared";
@@ -109,6 +110,13 @@ export declare class CdpSolanaWalletProvider extends SvmWalletProvider implement
109
110
  * @returns The CDP client.
110
111
  */
111
112
  getClient(): CdpClient;
113
+ /**
114
+ * Sign a message.
115
+ *
116
+ * @param message - The message to sign as a Uint8Array
117
+ * @returns The signature as a Uint8Array
118
+ */
119
+ signMessage(message: Uint8Array): Promise<Uint8Array>;
112
120
  /**
113
121
  * Transfer SOL from the wallet to another address
114
122
  *
@@ -117,4 +125,10 @@ export declare class CdpSolanaWalletProvider extends SvmWalletProvider implement
117
125
  * @returns The signature
118
126
  */
119
127
  nativeTransfer(to: string, value: string): Promise<string>;
128
+ /**
129
+ * Get the keypair signer for this wallet.
130
+ *
131
+ * @returns The KeyPairSigner
132
+ */
133
+ getKeyPairSigner(): Promise<KeyPairSigner>;
120
134
  }