Skip to main content
Glama
sui.test.ts7.69 kB
import { SuiClient } from '@mysten/sui/client'; import { jest } from '@jest/globals'; import { batchTransferSUI } from '../../src/utils/sui.js'; import { Ed25519Keypair } from '@mysten/sui/keypairs/ed25519'; // Mock the required modules jest.mock('@mysten/sui/client'); jest.mock('@mysten/sui/transactions'); // Mock console.error to keep test output clean console.error = jest.fn(); describe('batchTransferSUI', () => { let mockSuiClient: jest.Mocked<SuiClient>; let mockKeypair: Ed25519Keypair; beforeEach(() => { // Reset all mocks jest.clearAllMocks(); // Create mock client mockSuiClient = { signAndExecuteTransaction: jest.fn(), waitForTransaction: jest.fn(), getBalance: jest.fn(), } as unknown as jest.Mocked<SuiClient>; // Create mock keypair mockKeypair = new Ed25519Keypair(); }); it('should successfully transfer SUI and return digest', async () => { const expectedDigest = '0x123456'; const amounts = [BigInt(1000000)]; const recipients = [new Ed25519Keypair().toSuiAddress()]; // Mock the balance responses mockSuiClient.getBalance.mockResolvedValueOnce({ totalBalance: '1000000000', coinType: '0x2::sui::SUI', coinObjectCount: Number.MAX_SAFE_INTEGER, lockedBalance: { number: '0' }, }); // Mock successful transaction mockSuiClient.signAndExecuteTransaction.mockResolvedValue({ digest: expectedDigest }); mockSuiClient.waitForTransaction.mockResolvedValue({ digest: expectedDigest }); const digest = await batchTransferSUI(amounts, recipients, mockKeypair, mockSuiClient); expect(digest).toBe(expectedDigest); expect(mockSuiClient.signAndExecuteTransaction).toHaveBeenCalledTimes(1); expect(mockSuiClient.waitForTransaction).toHaveBeenCalledTimes(1); }); it('should return error when balance is insufficient', async () => { const amounts = [BigInt(2000000)]; const recipients = [new Ed25519Keypair().toSuiAddress()]; // Mock low balance mockSuiClient.getBalance.mockResolvedValueOnce({ totalBalance: '1000000', coinType: '0x2::sui::SUI', coinObjectCount: Number.MAX_SAFE_INTEGER, lockedBalance: { number: '0' }, }); try { await batchTransferSUI(amounts, recipients, mockKeypair, mockSuiClient); // Should not reach here expect(true).toBe(false); } catch (error) { expect(error instanceof Error).toBe(true); expect((error as Error).message).toContain('Insufficient balance'); } }); it('should return error when amounts and recipients length mismatch', async () => { const amounts = [BigInt(1000000), BigInt(2000000)]; const recipients = [new Ed25519Keypair().toSuiAddress()]; try { await batchTransferSUI(amounts, recipients, mockKeypair, mockSuiClient); // Should not reach here expect(true).toBe(false); } catch (error) { expect(error instanceof Error).toBe(true); expect((error as Error).message).toBe('Amounts and recipients must have the same length'); } }); it('should successfully transfer SUI to multiple recipients', async () => { const expectedDigest = '0x123456'; const amounts = [BigInt(1000000), BigInt(2000000)]; const recipients = [new Ed25519Keypair().toSuiAddress(), new Ed25519Keypair().toSuiAddress()]; // Mock sufficient balance mockSuiClient.getBalance.mockResolvedValueOnce({ totalBalance: '10000000000', coinType: '0x2::sui::SUI', coinObjectCount: Number.MAX_SAFE_INTEGER, lockedBalance: { number: '0' }, }); // Mock successful transaction mockSuiClient.signAndExecuteTransaction.mockResolvedValue({ digest: expectedDigest }); mockSuiClient.waitForTransaction.mockResolvedValue({ digest: expectedDigest }); const digest = await batchTransferSUI(amounts, recipients, mockKeypair, mockSuiClient); expect(digest).toBe(expectedDigest); expect(mockSuiClient.signAndExecuteTransaction).toHaveBeenCalledTimes(1); expect(mockSuiClient.waitForTransaction).toHaveBeenCalledTimes(1); }); it('should handle transaction failure', async () => { const amounts = [BigInt(1000000)]; const recipients = [new Ed25519Keypair().toSuiAddress()]; // Mock sufficient balance mockSuiClient.getBalance.mockResolvedValueOnce({ totalBalance: '10000000000', coinType: '0x2::sui::SUI', coinObjectCount: Number.MAX_SAFE_INTEGER, lockedBalance: { number: '0' }, }); // Mock transaction failure mockSuiClient.signAndExecuteTransaction.mockRejectedValue(new Error('Transaction failed')); try { await batchTransferSUI(amounts, recipients, mockKeypair, mockSuiClient); // Should not reach here expect(true).toBe(false); } catch (error) { expect(error instanceof Error).toBe(true); expect((error as Error).message).toBe('Transaction failed'); } }); // 测试用例6: balance check failure it('should handle balance check failure', async () => { const amounts = [BigInt(1000000)]; const recipients = [new Ed25519Keypair().toSuiAddress()]; // Mock balance check failure mockSuiClient.getBalance.mockRejectedValue(new Error('Failed to get balance')); try { await batchTransferSUI(amounts, recipients, mockKeypair, mockSuiClient); // Should not reach here expect(true).toBe(false); } catch (error) { expect(error instanceof Error).toBe(true); expect((error as Error).message).toBe('Failed to get balance'); } }); it('should validate recipient address format', async () => { const amounts = [BigInt(1000000)]; const recipients = ['invalid_address']; // Invalid address format // Mock sufficient balance mockSuiClient.getBalance.mockResolvedValueOnce({ totalBalance: '10000000000', coinType: '0x2::sui::SUI', coinObjectCount: Number.MAX_SAFE_INTEGER, lockedBalance: { number: '0' }, }); try { await batchTransferSUI(amounts, recipients, mockKeypair, mockSuiClient); // Should not reach here expect(true).toBe(false); } catch (error) { expect(error instanceof Error).toBe(true); expect((error as Error).message).toContain('Invalid recipient address'); } }); it('should validate non-zero amount', async () => { const amounts = [BigInt(0)]; const recipients = [new Ed25519Keypair().toSuiAddress()]; try { await batchTransferSUI(amounts, recipients, mockKeypair, mockSuiClient); // Should not reach here expect(true).toBe(false); } catch (error) { expect(error instanceof Error).toBe(true); expect((error as Error).message).toContain('Amount must be greater than 0'); } }); it('should handle transaction timeout', async () => { const amounts = [BigInt(1000000)]; const recipients = [new Ed25519Keypair().toSuiAddress()]; // Mock sufficient balance mockSuiClient.getBalance.mockResolvedValueOnce({ totalBalance: '10000000000', coinType: '0x2::sui::SUI', coinObjectCount: Number.MAX_SAFE_INTEGER, lockedBalance: { number: '0' }, }); // Mock transaction timeout mockSuiClient.signAndExecuteTransaction.mockResolvedValue({ digest: '0x123456' }); mockSuiClient.waitForTransaction.mockRejectedValue(new Error('Transaction timeout')); try { await batchTransferSUI(amounts, recipients, mockKeypair, mockSuiClient); // Should not reach here expect(true).toBe(false); } catch (error) { expect(error instanceof Error).toBe(true); expect((error as Error).message).toContain('Transaction timeout'); } }); });

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/0xdwong/sui-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server