UNPKG

@five-vm/cli

Version:

High-performance CLI for Five VM development with WebAssembly integration

380 lines (376 loc) 16.3 kB
/** * Five SDK - Basic Usage Examples * * This file demonstrates the core Five SDK functionality with correct terminology: * - Five scripts (not contracts) * - Script accounts (not program IDs) * - Bytecode compilation and deployment * - Script function execution */ import { FiveSDK, compileAndExecuteLocally } from '../index.js'; // No Solana client imports needed in client-agnostic SDK! // ==================== Example 1: Basic SDK Setup ==================== async function example1_BasicSetup() { console.log('=== Example 1: Basic SDK Setup ==='); // Method 1: Use convenience factory methods const devnetSDK = FiveSDK.devnet(); const mainnetSDK = FiveSDK.mainnet(); const localSDK = FiveSDK.localnet(); // Method 2: Manual configuration const customSDK = new FiveSDK({ fiveVMProgramId: '7wVkyXsUiRcZtAHGZcXbTPCXnE7DBP6juN35H6FEUUZo', debug: true, network: 'devnet' }); console.log('SDK Configuration:', customSDK.getConfig()); } // ==================== Example 2: Script Compilation ==================== async function example2_ScriptCompilation() { console.log('=== Example 2: Script Compilation ==='); const sdk = FiveSDK.devnet(); // Five script source code const scriptSource = ` script SimpleCalculator { // Add two numbers add(a: u64, b: u64) -> u64 { return a + b; } // Main entry point (0 parameters) test() -> u64 { return add(5, 3); } } `; try { // Compile the script using static method const compilation = await FiveSDK.compile(scriptSource, { optimize: true, debug: false }); if (compilation.success) { console.log('✓ Compilation successful!'); console.log(` Bytecode size: ${compilation.bytecode?.length} bytes`); console.log(` Functions found: ${compilation.metadata?.functions.length}`); console.log(` Compilation time: ${compilation.metadata?.compilationTime}ms`); // Show function information compilation.metadata?.functions.forEach(func => { console.log(` Function: ${func.name}(${func.parameters.map(p => `${p.name}: ${p.type}`).join(', ')})`); }); } else { console.log('✗ Compilation failed:'); compilation.errors?.forEach(error => { console.log(` ${error.severity}: ${error.message} (line ${error.line})`); }); } } catch (error) { console.error('Compilation error:', error); } } // ==================== Example 3: Deployment Instruction Generation ==================== async function example3_DeploymentInstructionGeneration() { console.log('=== Example 3: Deployment Instruction Generation ==='); const scriptSource = ` script HelloWorld { test() -> u64 { return 42; } } `; try { console.log('Compiling script...'); // First compile the script const compilation = await FiveSDK.compile(scriptSource, { optimize: true }); if (compilation.success && compilation.bytecode) { console.log('✓ Script compiled successfully!'); console.log(` Bytecode size: ${compilation.bytecode.length} bytes`); // Generate deployment instruction (client-agnostic) const deployerAddress = 'DeployerPublicKey1111111111111111111111111'; const deploymentData = await FiveSDK.generateDeployInstruction(compilation.bytecode, deployerAddress, { debug: true }); console.log('✓ Deployment instruction generated!'); console.log(` Script account (PDA): ${deploymentData.scriptAccount}`); console.log(` Required signers: ${deploymentData.requiredSigners.join(', ')}`); console.log(` Estimated cost: ${(deploymentData.estimatedCost / 1e9).toFixed(6)} SOL`); console.log(` Instruction data size: ${deploymentData.instruction.data.length} chars (base64)`); console.log(` Account count: ${deploymentData.instruction.accounts.length}`); return deploymentData.scriptAccount; } else { console.log('✗ Compilation failed'); compilation.errors?.forEach(error => { console.log(` ${error.severity}: ${error.message} (line ${error.line})`); }); } } catch (error) { console.error('Deployment instruction generation error:', error); } return null; } // ==================== Example 4: Execution Instruction Generation ==================== async function example4_ExecutionInstructionGeneration() { console.log('=== Example 4: Execution Instruction Generation ==='); // First, get a script account from deployment example const scriptAccount = await example3_DeploymentInstructionGeneration(); if (!scriptAccount) { console.log('Skipping execution example - no script account'); return; } try { console.log(`Generating execution instruction for script: ${scriptAccount}`); // Generate execution instruction (client-agnostic) const executionData = await FiveSDK.generateExecuteInstruction(scriptAccount, 'test', // Function name [], // No parameters [], // No additional accounts { debug: true, computeUnitLimit: 50000 }); console.log('✓ Execution instruction generated!'); console.log(` Script account: ${executionData.scriptAccount}`); console.log(` Function: ${executionData.parameters.function}`); console.log(` Parameter count: ${executionData.parameters.count}`); console.log(` Estimated compute units: ${executionData.estimatedComputeUnits}`); console.log(` Instruction data size: ${executionData.instruction.data.length} chars (base64)`); console.log(` Account count: ${executionData.instruction.accounts.length}`); // Show how to use the instruction with any Solana client console.log('\n📝 Usage with any Solana client:'); console.log(' 1. Decode base64 instruction data'); console.log(' 2. Create transaction with accounts and program ID'); console.log(' 3. Submit transaction to Solana network'); console.log(' 4. Parse transaction logs for execution results'); } catch (error) { console.error('Execution instruction generation error:', error); } } // ==================== Example 5: Parameter Handling ==================== async function example5_ParameterHandling() { console.log('=== Example 5: Parameter Handling ==='); const sdk = FiveSDK.devnet(); // Script with parameters const scriptSource = ` script MathOperations { // Function that requires parameters multiply(a: u64, b: u64) -> u64 { return a * b; } // Function with mixed parameter types process(number: u32, flag: bool, name: string) -> u64 { if (flag) { return number * 2; } else { return number; } } } `; try { // Compile the script using static method const compilation = await FiveSDK.compile(scriptSource); if (compilation.success && compilation.bytecode) { console.log('✓ Script compiled successfully!'); // Direct bytecode execution with parameters (for testing) console.log('Testing parameter handling...'); // Test multiply function with parameters const multiplyResult = await FiveSDK.executeLocally(compilation.bytecode, 'multiply', // Function name [10, 5], // Parameters { debug: true, trace: true }); if (multiplyResult.success) { console.log('✓ Multiply function executed successfully!'); console.log(` Result: ${JSON.stringify(multiplyResult.result)}`); } // Test process function with mixed types const processResult = await FiveSDK.executeLocally(compilation.bytecode, 'process', // Function name [42, true, "test"], // u32, bool, string parameters { debug: true, trace: true }); if (processResult.success) { console.log('✓ Process function executed successfully!'); console.log(` Result: ${JSON.stringify(processResult.result)}`); } } else { console.log('✗ Script compilation failed'); } } catch (error) { console.error('Parameter handling error:', error); } } // ==================== Example 6: Error Handling ==================== async function example6_ErrorHandling() { console.log('=== Example 6: Error Handling ==='); const sdk = FiveSDK.devnet(); // Intentionally broken script const brokenScript = ` script BrokenScript { test() -> u64 { return unknown_function(); // This will cause a compilation error } } `; try { const compilation = await FiveSDK.compile(brokenScript); if (!compilation.success) { console.log('✓ Compilation errors caught correctly:'); compilation.errors?.forEach(error => { console.log(` ${error.severity}: ${error.message}`); if (error.line) { console.log(` at line ${error.line}${error.column ? `:${error.column}` : ''}`); } }); } } catch (error) { console.log('SDK Error handling:'); if (error instanceof Error) { console.log(` Type: ${error.constructor.name}`); console.log(` Message: ${error.message}`); } } // Test execution error handling try { const result = await FiveSDK.executeLocally(new Uint8Array([1, 2, 3]), // Invalid bytecode 0, // Function index [] // No parameters ); console.log('Execution result:', result.success ? 'success' : 'failed'); } catch (error) { console.log('✓ Execution error caught:', error instanceof Error ? error.message : error); } } // ==================== Example 7: Local WASM VM Execution ==================== async function example7_LocalWASMExecution() { console.log('=== Example 7: Local WASM VM Execution ==='); const scriptSource = ` script LocalTesting { // Test basic arithmetic add(a: u64, b: u64) -> u64 { return a + b; } // Test with no parameters getAnswer() -> u64 { return 42; } // Test complex logic fibonacci(n: u64) -> u64 { if (n <= 1) { return n; } else { return fibonacci(n - 1) + fibonacci(n - 2); } } } `; try { console.log('🚀 Testing local WASM VM execution (no blockchain needed!)...'); // Method 1: Compile and execute in one step (easiest for testing) console.log('\n📝 Method 1: Compile and execute in one step'); const quickResult = await compileAndExecuteLocally(scriptSource, 'getAnswer', // Function name [], // No parameters { debug: true, trace: true }); if (quickResult.success) { console.log('✅ Quick execution successful!'); if ('result' in quickResult) { console.log(` Result: ${quickResult.result}`); } if ('executionTime' in quickResult) { console.log(` Execution time: ${quickResult.executionTime}ms`); } if ('computeUnitsUsed' in quickResult) { console.log(` Compute units: ${quickResult.computeUnitsUsed}`); } if ('bytecodeSize' in quickResult) { console.log(` Bytecode size: ${quickResult.bytecodeSize} bytes`); } } else { console.log('❌ Quick execution failed:', quickResult.error); } // Method 2: Two-step process (more control) console.log('\n🔧 Method 2: Separate compilation and execution'); const compilation = await FiveSDK.compile(scriptSource, { debug: true }); if (compilation.success && compilation.bytecode) { console.log('✅ Compilation successful!'); // Execute different functions with different parameters const functions = [ { name: 'add', params: [10, 5] }, { name: 'getAnswer', params: [] }, { name: 'fibonacci', params: [8] } ]; for (const func of functions) { console.log(`\n🎯 Testing function: ${func.name}(${func.params.join(', ')})`); const result = await FiveSDK.executeLocally(compilation.bytecode, func.name, func.params, { debug: true, trace: false, computeUnitLimit: 100000 }); if (result.success) { console.log(` ✅ Result: ${result.result}`); console.log(` ⏱️ Time: ${result.executionTime}ms`); console.log(` ⚡ CU: ${result.computeUnitsUsed}`); } else { console.log(` ❌ Failed: ${result.error}`); } } // Method 3: Validate bytecode console.log('\n🔍 Method 3: Bytecode validation'); const validation = await FiveSDK.validateBytecode(compilation.bytecode, { debug: true }); if (validation.valid) { console.log('✅ Bytecode validation passed!'); console.log(` Functions found: ${validation.functions?.length || 0}`); } else { console.log('❌ Bytecode validation failed:', validation.errors); } } else { console.log('❌ Compilation failed:', compilation.errors); } console.log('\n🎉 Local WASM execution benefits:'); console.log('• No blockchain connection needed'); console.log('• Instant feedback for development'); console.log('• Perfect for unit testing'); console.log('• Debug bytecode before deployment'); console.log('• Trace execution with detailed logs'); } catch (error) { console.error('Local execution error:', error); } } // ==================== Run All Examples ==================== async function runAllExamples() { console.log('Five SDK - Usage Examples'); console.log('='.repeat(50)); try { await example1_BasicSetup(); console.log(); await example2_ScriptCompilation(); console.log(); await example3_DeploymentInstructionGeneration(); console.log(); await example4_ExecutionInstructionGeneration(); console.log(); await example5_ParameterHandling(); console.log(); await example6_ErrorHandling(); console.log(); await example7_LocalWASMExecution(); console.log(); console.log('✅ All client-agnostic examples completed successfully!'); console.log(''); console.log('Key Features Demonstrated:'); console.log('• Client-agnostic SDK design (no Solana client dependencies)'); console.log('• Static methods for compilation and instruction generation'); console.log('• ABI-driven automatic parameter type coercion'); console.log('• Serialized instruction data for any Solana client library'); console.log('• Direct WASM VM execution for local testing'); console.log('• Works in Node.js, browser, and mobile environments'); } catch (error) { console.error('Example failed:', error); } } // Export examples for individual testing export { example1_BasicSetup, example2_ScriptCompilation, example3_DeploymentInstructionGeneration, example4_ExecutionInstructionGeneration, example5_ParameterHandling, example6_ErrorHandling, example7_LocalWASMExecution, runAllExamples }; // Run examples if this file is executed directly if (import.meta.url === `file://${process.argv[1]}`) { runAllExamples().catch(console.error); } //# sourceMappingURL=basic-usage.js.map