| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496 |
- /**
- * Integration test for multi-platform signing
- *
- * This test verifies the complete multi-platform signing workflow:
- * 1. Load configuration with accounts from different platforms
- * 2. Perform signing operations using platform-specific algorithms
- * 3. Verify signatures using platform-specific verification
- * 4. Test cross-platform compatibility and isolation
- *
- * Platforms tested:
- * - Pacifica (Ed25519)
- * - Aster (EIP-191)
- * - Binance (HMAC-SHA256)
- *
- * Tests MUST FAIL initially until implementation is provided.
- */
- import { describe, test, expect, beforeEach, afterEach } from '@jest/globals';
- import * as fs from 'fs/promises';
- import * as path from 'path';
- import * as os from 'os';
- // Import types (this import will fail until types are implemented)
- import type {
- ICredentialManager,
- SignResult,
- Account,
- Platform,
- ConfigFile
- } from '@/specs/001-credential-manager/contracts/credential-manager';
- describe('Multi-Platform Signing Integration Tests', () => {
- let credentialManager: ICredentialManager;
- let tempDir: string;
- let configPath: string;
- // Test messages for different platforms
- const testMessages = {
- pacifica: new TextEncoder().encode(JSON.stringify({
- order_type: 'market',
- symbol: 'BTC-USD',
- side: 'buy',
- size: '0.1',
- timestamp: Date.now()
- })),
- aster: new TextEncoder().encode('Transfer 100 ETH to 0x1234567890abcdef'),
- binance: new TextEncoder().encode('GET\n/api/v3/account\n\ntimestamp=1234567890000')
- };
- beforeEach(async () => {
- // This will fail until CredentialManager is implemented
- const { CredentialManager } = await import('@/core/credential-manager/CredentialManager');
- credentialManager = new CredentialManager();
- // Create temporary directory
- tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'multi-platform-test-'));
- configPath = path.join(tempDir, 'multi-platform-config.json');
- // Create multi-platform configuration
- const multiPlatformConfig: ConfigFile = {
- version: "1.0",
- accounts: [
- {
- id: "pacifica-test-account",
- platform: Platform.PACIFICA,
- name: "Pacifica Trading Account",
- credentials: {
- type: "ed25519",
- privateKey: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
- }
- },
- {
- id: "aster-test-account",
- platform: Platform.ASTER,
- name: "Aster DeFi Account",
- credentials: {
- type: "eip191",
- privateKey: "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"
- }
- },
- {
- id: "binance-test-account",
- platform: Platform.BINANCE,
- name: "Binance Spot Account",
- credentials: {
- type: "hmac",
- apiKey: "test-binance-api-key",
- secretKey: "test-binance-secret-key"
- }
- }
- ]
- };
- await fs.writeFile(configPath, JSON.stringify(multiPlatformConfig, null, 2));
- await credentialManager.loadConfig(configPath);
- });
- afterEach(async () => {
- // Clean up
- credentialManager.stopWatching();
- try {
- await fs.rm(tempDir, { recursive: true, force: true });
- } catch (error) {
- // Ignore cleanup errors
- }
- });
- describe('Platform Account Loading', () => {
- test('should load accounts from all supported platforms', () => {
- // Act
- const allAccounts = credentialManager.listAccounts();
- // Assert
- expect(allAccounts).toHaveLength(3);
- const platforms = allAccounts.map(account => account.platform);
- expect(platforms).toContain(Platform.PACIFICA);
- expect(platforms).toContain(Platform.ASTER);
- expect(platforms).toContain(Platform.BINANCE);
- });
- test('should retrieve specific accounts by ID', () => {
- // Act & Assert
- const pacificaAccount = credentialManager.getAccount("pacifica-test-account");
- expect(pacificaAccount).not.toBeNull();
- expect(pacificaAccount!.platform).toBe(Platform.PACIFICA);
- expect(pacificaAccount!.credentials.type).toBe("ed25519");
- const asterAccount = credentialManager.getAccount("aster-test-account");
- expect(asterAccount).not.toBeNull();
- expect(asterAccount!.platform).toBe(Platform.ASTER);
- expect(asterAccount!.credentials.type).toBe("eip191");
- const binanceAccount = credentialManager.getAccount("binance-test-account");
- expect(binanceAccount).not.toBeNull();
- expect(binanceAccount!.platform).toBe(Platform.BINANCE);
- expect(binanceAccount!.credentials.type).toBe("hmac");
- });
- });
- describe('Pacifica (Ed25519) Signing', () => {
- test('should sign Pacifica order message successfully', async () => {
- // Act
- const result: SignResult = await credentialManager.sign(
- "pacifica-test-account",
- testMessages.pacifica
- );
- // Assert
- expect(result.success).toBe(true);
- expect(result.algorithm).toBe('ed25519');
- expect(typeof result.signature).toBe('string');
- expect(result.signature!.length).toBe(88); // base64 encoded Ed25519 signature
- expect(result.timestamp).toBeInstanceOf(Date);
- });
- test('should verify Pacifica signature correctly', async () => {
- // Arrange - create signature
- const signResult = await credentialManager.sign(
- "pacifica-test-account",
- testMessages.pacifica
- );
- expect(signResult.success).toBe(true);
- // Act - verify signature
- const isValid = await credentialManager.verify(
- "pacifica-test-account",
- testMessages.pacifica,
- signResult.signature!
- );
- // Assert
- expect(isValid).toBe(true);
- });
- test('should reject invalid Pacifica signature', async () => {
- // Act - verify invalid signature
- const isValid = await credentialManager.verify(
- "pacifica-test-account",
- testMessages.pacifica,
- "invalid-signature"
- );
- // Assert
- expect(isValid).toBe(false);
- });
- });
- describe('Aster (EIP-191) Signing', () => {
- test('should sign Aster message successfully', async () => {
- // Act
- const result: SignResult = await credentialManager.sign(
- "aster-test-account",
- testMessages.aster
- );
- // Assert
- expect(result.success).toBe(true);
- expect(result.algorithm).toBe('eip191');
- expect(typeof result.signature).toBe('string');
- expect(result.signature!.startsWith('0x')).toBe(true); // Ethereum-style signature
- expect(result.signature!.length).toBe(132); // 0x + 130 hex chars for EIP-191
- });
- test('should verify Aster signature correctly', async () => {
- // Arrange
- const signResult = await credentialManager.sign(
- "aster-test-account",
- testMessages.aster
- );
- expect(signResult.success).toBe(true);
- // Act
- const isValid = await credentialManager.verify(
- "aster-test-account",
- testMessages.aster,
- signResult.signature!
- );
- // Assert
- expect(isValid).toBe(true);
- });
- test('should handle Ethereum personal message prefix', async () => {
- // Arrange - message that requires Ethereum personal message prefix
- const personalMessage = new TextEncoder().encode("Hello, Ethereum!");
- // Act
- const result = await credentialManager.sign(
- "aster-test-account",
- personalMessage
- );
- // Assert
- expect(result.success).toBe(true);
- expect(result.algorithm).toBe('eip191');
- // Verify the signature
- const isValid = await credentialManager.verify(
- "aster-test-account",
- personalMessage,
- result.signature!
- );
- expect(isValid).toBe(true);
- });
- });
- describe('Binance (HMAC-SHA256) Signing', () => {
- test('should sign Binance API request successfully', async () => {
- // Act
- const result: SignResult = await credentialManager.sign(
- "binance-test-account",
- testMessages.binance
- );
- // Assert
- expect(result.success).toBe(true);
- expect(result.algorithm).toBe('hmac-sha256');
- expect(typeof result.signature).toBe('string');
- expect(result.signature!.length).toBe(64); // HMAC-SHA256 produces 64 hex chars
- });
- test('should verify Binance signature correctly', async () => {
- // Arrange
- const signResult = await credentialManager.sign(
- "binance-test-account",
- testMessages.binance
- );
- expect(signResult.success).toBe(true);
- // Act
- const isValid = await credentialManager.verify(
- "binance-test-account",
- testMessages.binance,
- signResult.signature!
- );
- // Assert
- expect(isValid).toBe(true);
- });
- test('should handle Binance API query string format', async () => {
- // Arrange - typical Binance API query string
- const queryString = "symbol=BTCUSDT&side=BUY&type=MARKET&quantity=0.1×tamp=1234567890000";
- const queryMessage = new TextEncoder().encode(queryString);
- // Act
- const result = await credentialManager.sign(
- "binance-test-account",
- queryMessage
- );
- // Assert
- expect(result.success).toBe(true);
- expect(result.algorithm).toBe('hmac-sha256');
- // Verify signature
- const isValid = await credentialManager.verify(
- "binance-test-account",
- queryMessage,
- result.signature!
- );
- expect(isValid).toBe(true);
- });
- });
- describe('Cross-Platform Isolation', () => {
- test('should not allow signing with wrong platform account', async () => {
- // Act & Assert - try to sign Pacifica message with Binance account
- const result = await credentialManager.sign(
- "binance-test-account",
- testMessages.pacifica
- );
- // Should either fail or produce platform-appropriate signature
- if (result.success) {
- expect(result.algorithm).toBe('hmac-sha256'); // Should use Binance algorithm
- } else {
- expect(typeof result.error).toBe('string');
- }
- });
- test('should maintain signature isolation between platforms', async () => {
- // Arrange - same message signed by different platforms
- const commonMessage = new TextEncoder().encode("Common test message");
- // Act - sign with all platforms
- const pacificaResult = await credentialManager.sign("pacifica-test-account", commonMessage);
- const asterResult = await credentialManager.sign("aster-test-account", commonMessage);
- const binanceResult = await credentialManager.sign("binance-test-account", commonMessage);
- // Assert - all should succeed but with different signatures
- expect(pacificaResult.success).toBe(true);
- expect(asterResult.success).toBe(true);
- expect(binanceResult.success).toBe(true);
- expect(pacificaResult.algorithm).toBe('ed25519');
- expect(asterResult.algorithm).toBe('eip191');
- expect(binanceResult.algorithm).toBe('hmac-sha256');
- // Signatures should be different
- expect(pacificaResult.signature).not.toBe(asterResult.signature);
- expect(asterResult.signature).not.toBe(binanceResult.signature);
- expect(pacificaResult.signature).not.toBe(binanceResult.signature);
- });
- test('should reject cross-platform signature verification', async () => {
- // Arrange - sign with one platform
- const message = new TextEncoder().encode("Cross-platform test");
- const pacificaResult = await credentialManager.sign("pacifica-test-account", message);
- expect(pacificaResult.success).toBe(true);
- // Act - try to verify with different platform account
- const isValid = await credentialManager.verify(
- "aster-test-account", // Different platform
- message,
- pacificaResult.signature!
- );
- // Assert - should fail verification
- expect(isValid).toBe(false);
- });
- });
- describe('Concurrent Multi-Platform Operations', () => {
- test('should handle concurrent signing across platforms', async () => {
- // Arrange
- const concurrentOperations = [
- credentialManager.sign("pacifica-test-account", testMessages.pacifica),
- credentialManager.sign("aster-test-account", testMessages.aster),
- credentialManager.sign("binance-test-account", testMessages.binance),
- credentialManager.sign("pacifica-test-account", new TextEncoder().encode("Second Pacifica")),
- credentialManager.sign("aster-test-account", new TextEncoder().encode("Second Aster"))
- ];
- // Act
- const results = await Promise.all(concurrentOperations);
- // Assert - all operations should complete successfully
- results.forEach((result, index) => {
- expect(result.success).toBe(true);
- expect(typeof result.signature).toBe('string');
- });
- // Verify algorithms are correct
- expect(results[0].algorithm).toBe('ed25519'); // Pacifica
- expect(results[1].algorithm).toBe('eip191'); // Aster
- expect(results[2].algorithm).toBe('hmac-sha256'); // Binance
- expect(results[3].algorithm).toBe('ed25519'); // Pacifica again
- expect(results[4].algorithm).toBe('eip191'); // Aster again
- });
- test('should maintain performance across all platforms', async () => {
- // Performance requirement: signing < 50ms per operation
- const performanceTests = [
- { platform: "pacifica-test-account", message: testMessages.pacifica },
- { platform: "aster-test-account", message: testMessages.aster },
- { platform: "binance-test-account", message: testMessages.binance }
- ];
- for (const test of performanceTests) {
- const startTime = Date.now();
- const result = await credentialManager.sign(test.platform, test.message);
- const duration = Date.now() - startTime;
- expect(result.success).toBe(true);
- expect(duration).toBeLessThan(50); // Performance requirement
- }
- });
- });
- describe('Platform-Specific Error Handling', () => {
- test('should handle Pacifica-specific errors gracefully', async () => {
- // Arrange - invalid Pacifica message (too large)
- const oversizedMessage = new Uint8Array(2 * 1024 * 1024); // 2MB
- // Act
- const result = await credentialManager.sign("pacifica-test-account", oversizedMessage);
- // Assert
- expect(result.success).toBe(false);
- expect(typeof result.error).toBe('string');
- expect(result.error!).toContain('size');
- });
- test('should handle Aster-specific errors gracefully', async () => {
- // Arrange - test with malformed Ethereum address format if applicable
- const asterAccount = credentialManager.getAccount("aster-test-account");
- expect(asterAccount).not.toBeNull();
- // Act - attempt operation that might cause Aster-specific error
- const result = await credentialManager.sign("aster-test-account", new Uint8Array(0));
- // Assert - should handle gracefully
- expect(typeof result.success).toBe('boolean');
- if (!result.success) {
- expect(typeof result.error).toBe('string');
- }
- });
- test('should handle Binance-specific errors gracefully', async () => {
- // Arrange - empty message which might be invalid for HMAC
- const emptyMessage = new Uint8Array(0);
- // Act
- const result = await credentialManager.sign("binance-test-account", emptyMessage);
- // Assert - should handle gracefully
- expect(typeof result.success).toBe('boolean');
- if (!result.success) {
- expect(typeof result.error).toBe('string');
- }
- });
- });
- describe('Platform Detection and Validation', () => {
- test('should correctly identify platform for each account', () => {
- // Act & Assert
- const accounts = credentialManager.listAccounts();
- accounts.forEach(account => {
- switch (account.platform) {
- case Platform.PACIFICA:
- expect(account.credentials.type).toBe('ed25519');
- expect(account.credentials.privateKey).toMatch(/^[0-9a-f]{64}$/);
- break;
- case Platform.ASTER:
- expect(account.credentials.type).toBe('eip191');
- expect(account.credentials.privateKey).toMatch(/^0x[0-9a-f]{64}$/);
- break;
- case Platform.BINANCE:
- expect(account.credentials.type).toBe('hmac');
- expect(account.credentials.apiKey).toBeTruthy();
- expect(account.credentials.secretKey).toBeTruthy();
- break;
- default:
- fail(`Unknown platform: ${account.platform}`);
- }
- });
- });
- test('should validate credential format for each platform', () => {
- // This test verifies that the credential manager validates
- // platform-specific credential formats during loading
- const accounts = credentialManager.listAccounts();
- expect(accounts).toHaveLength(3);
- // All accounts should be loaded successfully, indicating valid credential formats
- accounts.forEach(account => {
- expect(account.credentials).toBeDefined();
- expect(typeof account.credentials.type).toBe('string');
- });
- });
- });
- });
|