UNPKG

@coinbase/agentkit

Version:

Coinbase AgentKit core primitives

219 lines (218 loc) 11 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const solanaKeypairWalletProvider_1 = require("./solanaKeypairWalletProvider"); const web3_js_1 = require("@solana/web3.js"); const svm_1 = require("../network/svm"); global.fetch = jest.fn(() => Promise.resolve({ ok: true, json: () => Promise.resolve({}), })); jest.mock("../analytics", () => ({ sendAnalyticsEvent: jest.fn().mockImplementation(() => Promise.resolve()), })); jest.mock("@solana/web3.js", () => { const originalModule = jest.requireActual("@solana/web3.js"); return { ...originalModule, Connection: jest.fn().mockImplementation(() => ({ getGenesisHash: jest.fn().mockResolvedValue(svm_1.SOLANA_DEVNET_GENESIS_BLOCK_HASH), getBalance: jest.fn().mockResolvedValue(1000000000), getLatestBlockhash: jest.fn().mockResolvedValue({ blockhash: "test-blockhash", lastValidBlockHeight: 123456, }), sendTransaction: jest.fn().mockResolvedValue("signature123"), getSignatureStatus: jest.fn().mockResolvedValue({ context: { slot: 123 }, value: { slot: 123, confirmations: 10, err: null }, }), confirmTransaction: jest.fn().mockResolvedValue({ context: { slot: 123 }, value: { err: null }, }), requestAirdrop: jest.fn().mockResolvedValue("airdrop-signature"), })), Keypair: { generate: jest.fn().mockReturnValue({ publicKey: new originalModule.PublicKey("AQoKYV7tYpTrFZN6P5oUufbQKAUr9mNYGe1TTJC9wajM"), secretKey: new Uint8Array(32).fill(1), sign: jest.fn(), }), fromSecretKey: jest.fn().mockReturnValue({ publicKey: new originalModule.PublicKey("AQoKYV7tYpTrFZN6P5oUufbQKAUr9mNYGe1TTJC9wajM"), secretKey: new Uint8Array(32).fill(1), sign: jest.fn(), }), }, PublicKey: originalModule.PublicKey, VersionedTransaction: jest.fn().mockImplementation(() => ({ signatures: [], message: { compiledMessage: Buffer.from([]) }, sign: jest.fn(function (signers) { this.signatures = signers.map(() => new Uint8Array(64).fill(1)); return this; }), })), SystemProgram: { transfer: jest.fn().mockReturnValue({ instructions: [{ programId: "system-program" }], }), }, MessageV0: { compile: jest.fn().mockReturnValue({ compiledMessage: Buffer.from([]), }), }, TransactionMessage: { compile: jest.fn().mockReturnValue({ compiledMessage: Buffer.from([]), }), }, clusterApiUrl: jest.fn().mockImplementation(network => `https://api.${network}.solana.com`), }; }); describe("SolanaKeypairWalletProvider", () => { let wallet; beforeEach(async () => { const keypair = web3_js_1.Keypair.generate(); wallet = await solanaKeypairWalletProvider_1.SolanaKeypairWalletProvider.fromRpcUrl("https://api.devnet.solana.com", keypair.secretKey); }); describe("initialization methods", () => { it("should initialize from constructor", async () => { const keypair = web3_js_1.Keypair.generate(); const rpcUrl = "https://api.devnet.solana.com"; const provider = new solanaKeypairWalletProvider_1.SolanaKeypairWalletProvider({ keypair: keypair.secretKey, rpcUrl, genesisHash: svm_1.SOLANA_DEVNET_GENESIS_BLOCK_HASH, }); expect(provider).toBeInstanceOf(solanaKeypairWalletProvider_1.SolanaKeypairWalletProvider); expect(provider.getNetwork()).toEqual(svm_1.SOLANA_NETWORKS[svm_1.SOLANA_DEVNET_GENESIS_BLOCK_HASH]); }); it("should initialize from RPC URL", async () => { const keypair = web3_js_1.Keypair.generate(); const rpcUrl = "https://api.devnet.solana.com"; const provider = await solanaKeypairWalletProvider_1.SolanaKeypairWalletProvider.fromRpcUrl(rpcUrl, keypair.secretKey); expect(provider).toBeInstanceOf(solanaKeypairWalletProvider_1.SolanaKeypairWalletProvider); expect(provider.getNetwork()).toEqual(svm_1.SOLANA_NETWORKS[svm_1.SOLANA_DEVNET_GENESIS_BLOCK_HASH]); }); it("should initialize from network ID", async () => { const keypair = web3_js_1.Keypair.generate(); const networkId = "solana-devnet"; const wallet = await solanaKeypairWalletProvider_1.SolanaKeypairWalletProvider.fromNetwork(networkId, keypair.secretKey); expect(web3_js_1.clusterApiUrl).toHaveBeenCalledWith("devnet"); expect(wallet.getNetwork()).toEqual(svm_1.SOLANA_NETWORKS[svm_1.SOLANA_DEVNET_GENESIS_BLOCK_HASH]); }); it("should initialize from connection", async () => { const keypair = web3_js_1.Keypair.generate(); const connection = new web3_js_1.Connection("https://api.devnet.solana.com"); const provider = await solanaKeypairWalletProvider_1.SolanaKeypairWalletProvider.fromConnection(connection, keypair.secretKey); expect(provider).toBeInstanceOf(solanaKeypairWalletProvider_1.SolanaKeypairWalletProvider); expect(provider.getNetwork()).toEqual(svm_1.SOLANA_NETWORKS[svm_1.SOLANA_DEVNET_GENESIS_BLOCK_HASH]); }); }); describe("wallet methods", () => { it("should get the address", () => { expect(wallet.getAddress()).toBe("AQoKYV7tYpTrFZN6P5oUufbQKAUr9mNYGe1TTJC9wajM"); }); it("should get the public key", () => { const publicKey = wallet.getPublicKey(); expect(publicKey).toBeInstanceOf(web3_js_1.PublicKey); expect(publicKey.toBase58()).toBe("AQoKYV7tYpTrFZN6P5oUufbQKAUr9mNYGe1TTJC9wajM"); }); it("should get the network", () => { expect(wallet.getNetwork()).toEqual(svm_1.SOLANA_NETWORKS[svm_1.SOLANA_DEVNET_GENESIS_BLOCK_HASH]); }); it("should get the connection", () => { expect(wallet.getConnection()).toBeDefined(); }); it("should get the balance", async () => { const balance = await wallet.getBalance(); expect(balance).toBe(BigInt(1000000000)); }); it("should sign a transaction", async () => { const mockTransaction = { message: { compiledMessage: Buffer.from([]) }, signatures: [], sign: jest.fn(function (signers) { this.signatures = signers.map(() => new Uint8Array(64).fill(1)); return this; }), }; const signedTx = await wallet.signTransaction(mockTransaction); expect(mockTransaction.sign).toHaveBeenCalled(); expect(signedTx).toBe(mockTransaction); }); it("should send a transaction", async () => { const mockTransaction = { message: { compiledMessage: Buffer.from([]) }, signatures: [], sign: jest.fn(function (signers) { this.signatures = signers.map(() => new Uint8Array(64).fill(1)); return this; }), }; const signature = await wallet.sendTransaction(mockTransaction); expect(signature).toBe("signature123"); }); it("should sign and send a transaction", async () => { const mockTransaction = { message: { compiledMessage: Buffer.from([]) }, signatures: [], sign: jest.fn(function (signers) { this.signatures = signers.map(() => new Uint8Array(64).fill(1)); return this; }), }; const signature = await wallet.signAndSendTransaction(mockTransaction); expect(mockTransaction.sign).toHaveBeenCalled(); expect(signature).toBe("signature123"); }); it("should get the signature status", async () => { const status = await wallet.getSignatureStatus("signature123"); expect(status.value).toHaveProperty("slot"); expect(status.value).toHaveProperty("confirmations"); }); it("should wait for signature result", async () => { const result = await wallet.waitForSignatureResult("signature123"); expect(result.value).toHaveProperty("err"); }); it("should request an airdrop", async () => { const signature = await wallet.requestAirdrop(1000000000); expect(signature).toBe("airdrop-signature"); }); it("should transfer native tokens", async () => { const destination = "EQJqzeeVEnm8rKWQJ5SMTtQBD4xEgixwgzNWKkpeFRZ9"; const signature = await wallet.nativeTransfer(destination, "0.1"); expect(signature).toBe("signature123"); }); it("should handle insufficient balance when transferring", async () => { const connection = wallet.getConnection(); connection.getBalance.mockResolvedValueOnce(100); const destination = "EQJqzeeVEnm8rKWQJ5SMTtQBD4xEgixwgzNWKkpeFRZ9"; await expect(wallet.nativeTransfer(destination, "1.0")).rejects.toThrow("Insufficient balance"); }); it("should handle transaction failure when sending", async () => { const connection = wallet.getConnection(); connection.sendTransaction.mockRejectedValueOnce(new Error("Transaction failed")); const mockTransaction = { message: { compiledMessage: Buffer.from([]) }, signatures: [], sign: jest.fn(function (signers) { this.signatures = signers.map(() => new Uint8Array(64).fill(1)); return this; }), }; await expect(wallet.sendTransaction(mockTransaction)).rejects.toThrow("Transaction failed"); }); it("should handle confirmation timeout", async () => { const connection = wallet.getConnection(); connection.confirmTransaction.mockRejectedValueOnce(new Error("Timed out waiting for confirmation")); await expect(wallet.waitForSignatureResult("signature123")).rejects.toThrow("Timed out waiting for confirmation"); }); it("should handle invalid address when transferring", async () => { const destination = "invalid-address"; await expect(wallet.nativeTransfer(destination, "0.1")).rejects.toThrow(); }); }); });