- Introduced `ibc_example.rs` demonstrating Inter-Blockchain Communication operations including cross-chain transfers, channel management, packet handling, and relayer operations. - Introduced `zk_example.rs` showcasing Zero-Knowledge proof operations such as circuit compilation, proof generation and verification, and on-chain verification with multiple proving systems.
393 lines
12 KiB
TypeScript
393 lines
12 KiB
TypeScript
/**
|
|
* Synor Compiler SDK Examples for JavaScript/TypeScript
|
|
*
|
|
* Demonstrates smart contract compilation and analysis:
|
|
* - WASM contract compilation and optimization
|
|
* - ABI extraction and encoding
|
|
* - Contract analysis and security scanning
|
|
* - Validation and verification
|
|
*/
|
|
|
|
import * as fs from 'fs';
|
|
import {
|
|
SynorCompiler,
|
|
CompilerConfig,
|
|
OptimizationLevel,
|
|
StripOptions,
|
|
} from '../src/compiler';
|
|
|
|
async function main() {
|
|
// Initialize client
|
|
const config: CompilerConfig = {
|
|
apiKey: process.env.SYNOR_API_KEY || 'your-api-key',
|
|
endpoint: 'https://compiler.synor.io/v1',
|
|
timeout: 60000,
|
|
retries: 3,
|
|
debug: false,
|
|
defaultOptimizationLevel: OptimizationLevel.Size,
|
|
maxContractSize: 256 * 1024,
|
|
useWasmOpt: true,
|
|
validate: true,
|
|
extractMetadata: true,
|
|
generateAbi: true,
|
|
};
|
|
|
|
const compiler = new SynorCompiler(config);
|
|
|
|
try {
|
|
// Check service health
|
|
const healthy = await compiler.healthCheck();
|
|
console.log(`Service healthy: ${healthy}\n`);
|
|
|
|
// Example 1: Compile a contract
|
|
await compileContractExample(compiler);
|
|
|
|
// Example 2: Development vs Production compilation
|
|
await compilationModesExample(compiler);
|
|
|
|
// Example 3: ABI operations
|
|
await abiExample(compiler);
|
|
|
|
// Example 4: Contract analysis
|
|
await analysisExample(compiler);
|
|
|
|
// Example 5: Validation
|
|
await validationExample(compiler);
|
|
|
|
// Example 6: Security scanning
|
|
await securityExample(compiler);
|
|
} finally {
|
|
compiler.close();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Basic contract compilation
|
|
*/
|
|
async function compileContractExample(compiler: SynorCompiler): Promise<void> {
|
|
console.log('=== Contract Compilation ===');
|
|
|
|
// In production, load from file:
|
|
// const wasm = fs.readFileSync('my_contract.wasm');
|
|
|
|
// For demonstration, create a minimal WASM module
|
|
const wasm = createMinimalWasm();
|
|
|
|
const result = await compiler.compile(wasm, {
|
|
optimizationLevel: OptimizationLevel.Size,
|
|
useWasmOpt: true,
|
|
validate: true,
|
|
extractMetadata: true,
|
|
generateAbi: true,
|
|
stripOptions: {
|
|
stripDebug: true,
|
|
stripProducers: true,
|
|
stripNames: true,
|
|
stripCustom: true,
|
|
stripUnused: true,
|
|
preserveSections: [],
|
|
},
|
|
});
|
|
|
|
console.log('Compilation result:');
|
|
console.log(` Contract ID: ${result.contractId}`);
|
|
console.log(` Code hash: ${result.codeHash}`);
|
|
console.log(` Original size: ${result.originalSize} bytes`);
|
|
console.log(` Optimized size: ${result.optimizedSize} bytes`);
|
|
console.log(` Size reduction: ${result.sizeReduction.toFixed(1)}%`);
|
|
console.log(` Estimated deploy gas: ${result.estimatedDeployGas}`);
|
|
|
|
if (result.metadata) {
|
|
console.log('\nMetadata:');
|
|
console.log(` Name: ${result.metadata.name}`);
|
|
console.log(` Version: ${result.metadata.version}`);
|
|
console.log(` SDK Version: ${result.metadata.sdkVersion}`);
|
|
}
|
|
|
|
if (result.abi) {
|
|
console.log('\nABI:');
|
|
console.log(` Functions: ${result.abi.functions?.length || 0}`);
|
|
console.log(` Events: ${result.abi.events?.length || 0}`);
|
|
console.log(` Errors: ${result.abi.errors?.length || 0}`);
|
|
}
|
|
|
|
console.log('');
|
|
}
|
|
|
|
/**
|
|
* Development vs Production compilation modes
|
|
*/
|
|
async function compilationModesExample(compiler: SynorCompiler): Promise<void> {
|
|
console.log('=== Compilation Modes ===');
|
|
|
|
const wasm = createMinimalWasm();
|
|
|
|
// Development mode: fast compilation, debugging support
|
|
console.log('Development mode:');
|
|
const devResult = await compiler.contracts.compileDev(wasm);
|
|
console.log(` Size: ${devResult.optimizedSize} bytes`);
|
|
console.log(` Optimization: none`);
|
|
|
|
// Production mode: maximum optimization
|
|
console.log('\nProduction mode:');
|
|
const prodResult = await compiler.contracts.compileProduction(wasm);
|
|
console.log(` Size: ${prodResult.optimizedSize} bytes`);
|
|
console.log(` Optimization: aggressive`);
|
|
console.log(` Size savings: ${(devResult.optimizedSize - prodResult.optimizedSize)} bytes`);
|
|
|
|
// Custom optimization levels
|
|
console.log('\nOptimization levels:');
|
|
const levels = [
|
|
OptimizationLevel.None,
|
|
OptimizationLevel.Basic,
|
|
OptimizationLevel.Size,
|
|
OptimizationLevel.Aggressive,
|
|
];
|
|
|
|
for (const level of levels) {
|
|
const result = await compiler.compile(wasm, { optimizationLevel: level });
|
|
console.log(` ${level}: ${result.optimizedSize} bytes`);
|
|
}
|
|
|
|
console.log('');
|
|
}
|
|
|
|
/**
|
|
* ABI extraction and encoding
|
|
*/
|
|
async function abiExample(compiler: SynorCompiler): Promise<void> {
|
|
console.log('=== ABI Operations ===');
|
|
|
|
const wasm = createMinimalWasm();
|
|
|
|
// Extract ABI from WASM
|
|
const abi = await compiler.abi.extract(wasm);
|
|
console.log(`Contract: ${abi.name}`);
|
|
console.log(`Version: ${abi.version}`);
|
|
|
|
// List functions
|
|
if (abi.functions && abi.functions.length > 0) {
|
|
console.log('\nFunctions:');
|
|
for (const func of abi.functions) {
|
|
const inputs = func.inputs?.map(i => `${i.name}: ${i.type.typeName}`).join(', ') || '';
|
|
const outputs = func.outputs?.map(o => o.type.typeName).join(', ') || 'void';
|
|
const modifiers = [
|
|
func.view ? 'view' : '',
|
|
func.payable ? 'payable' : '',
|
|
].filter(Boolean).join(' ');
|
|
console.log(` ${func.name}(${inputs}) -> ${outputs} ${modifiers}`);
|
|
console.log(` Selector: ${func.selector}`);
|
|
}
|
|
}
|
|
|
|
// List events
|
|
if (abi.events && abi.events.length > 0) {
|
|
console.log('\nEvents:');
|
|
for (const event of abi.events) {
|
|
const params = event.params?.map(p => {
|
|
const indexed = p.indexed ? 'indexed ' : '';
|
|
return `${indexed}${p.name}: ${p.type.typeName}`;
|
|
}).join(', ') || '';
|
|
console.log(` ${event.name}(${params})`);
|
|
console.log(` Topic: ${event.topic}`);
|
|
}
|
|
}
|
|
|
|
// Encode a function call
|
|
if (abi.functions && abi.functions.length > 0) {
|
|
const func = abi.functions[0];
|
|
const encoded = await compiler.abi.encodeCall(func, ['arg1', 'arg2']);
|
|
console.log(`\nEncoded call to ${func.name}: ${encoded}`);
|
|
|
|
// Decode a result
|
|
const decoded = await compiler.abi.decodeResult(func, encoded);
|
|
console.log(`Decoded result: ${JSON.stringify(decoded)}`);
|
|
}
|
|
|
|
console.log('');
|
|
}
|
|
|
|
/**
|
|
* Contract analysis
|
|
*/
|
|
async function analysisExample(compiler: SynorCompiler): Promise<void> {
|
|
console.log('=== Contract Analysis ===');
|
|
|
|
const wasm = createMinimalWasm();
|
|
|
|
// Full analysis
|
|
const analysis = await compiler.analysis.analyze(wasm);
|
|
|
|
// Size breakdown
|
|
if (analysis.sizeBreakdown) {
|
|
console.log('Size breakdown:');
|
|
console.log(` Code: ${analysis.sizeBreakdown.code} bytes`);
|
|
console.log(` Data: ${analysis.sizeBreakdown.data} bytes`);
|
|
console.log(` Functions: ${analysis.sizeBreakdown.functions} bytes`);
|
|
console.log(` Memory: ${analysis.sizeBreakdown.memory} bytes`);
|
|
console.log(` Exports: ${analysis.sizeBreakdown.exports} bytes`);
|
|
console.log(` Imports: ${analysis.sizeBreakdown.imports} bytes`);
|
|
console.log(` Total: ${analysis.sizeBreakdown.total} bytes`);
|
|
}
|
|
|
|
// Function analysis
|
|
if (analysis.functions && analysis.functions.length > 0) {
|
|
console.log('\nFunction analysis:');
|
|
for (const func of analysis.functions.slice(0, 5)) {
|
|
console.log(` ${func.name}:`);
|
|
console.log(` Size: ${func.size} bytes`);
|
|
console.log(` Instructions: ${func.instructionCount}`);
|
|
console.log(` Locals: ${func.localCount}`);
|
|
console.log(` Exported: ${func.exported}`);
|
|
console.log(` Estimated gas: ${func.estimatedGas}`);
|
|
}
|
|
}
|
|
|
|
// Import analysis
|
|
if (analysis.imports && analysis.imports.length > 0) {
|
|
console.log('\nImports:');
|
|
for (const imp of analysis.imports) {
|
|
console.log(` ${imp.module}.${imp.name} (${imp.kind})`);
|
|
}
|
|
}
|
|
|
|
// Gas analysis
|
|
if (analysis.gasAnalysis) {
|
|
console.log('\nGas analysis:');
|
|
console.log(` Deployment: ${analysis.gasAnalysis.deploymentGas}`);
|
|
console.log(` Memory init: ${analysis.gasAnalysis.memoryInitGas}`);
|
|
console.log(` Data section: ${analysis.gasAnalysis.dataSectionGas}`);
|
|
}
|
|
|
|
// Extract metadata
|
|
const metadata = await compiler.analysis.extractMetadata(wasm);
|
|
console.log('\nContract metadata:');
|
|
console.log(` Name: ${metadata.name}`);
|
|
console.log(` Version: ${metadata.version}`);
|
|
console.log(` Build timestamp: ${metadata.buildTimestamp}`);
|
|
|
|
// Estimate deployment gas
|
|
const gas = await compiler.analysis.estimateDeployGas(wasm);
|
|
console.log(`\nEstimated deployment gas: ${gas}`);
|
|
|
|
console.log('');
|
|
}
|
|
|
|
/**
|
|
* Contract validation
|
|
*/
|
|
async function validationExample(compiler: SynorCompiler): Promise<void> {
|
|
console.log('=== Contract Validation ===');
|
|
|
|
const wasm = createMinimalWasm();
|
|
|
|
// Full validation
|
|
const result = await compiler.validation.validate(wasm);
|
|
console.log(`Valid: ${result.valid}`);
|
|
console.log(`Exports: ${result.exportCount}`);
|
|
console.log(`Imports: ${result.importCount}`);
|
|
console.log(`Functions: ${result.functionCount}`);
|
|
console.log(`Memory pages: ${result.memoryPages}`);
|
|
|
|
if (result.errors && result.errors.length > 0) {
|
|
console.log('\nValidation errors:');
|
|
for (const error of result.errors) {
|
|
console.log(` [${error.code}] ${error.message}`);
|
|
if (error.location) {
|
|
console.log(` at ${error.location}`);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (result.warnings && result.warnings.length > 0) {
|
|
console.log('\nWarnings:');
|
|
for (const warning of result.warnings) {
|
|
console.log(` ${warning}`);
|
|
}
|
|
}
|
|
|
|
// Quick validation
|
|
const isValid = await compiler.validation.isValid(wasm);
|
|
console.log(`\nQuick validation: ${isValid}`);
|
|
|
|
// Get validation errors only
|
|
const errors = await compiler.validation.getErrors(wasm);
|
|
console.log(`Error count: ${errors.length}`);
|
|
|
|
// Validate required exports
|
|
const hasRequiredExports = await compiler.validation.validateExports(
|
|
wasm,
|
|
['init', 'execute', 'query']
|
|
);
|
|
console.log(`Has required exports: ${hasRequiredExports}`);
|
|
|
|
// Validate memory constraints
|
|
const memoryValid = await compiler.validation.validateMemory(wasm, 16);
|
|
console.log(`Memory within 16 pages: ${memoryValid}`);
|
|
|
|
console.log('');
|
|
}
|
|
|
|
/**
|
|
* Security scanning
|
|
*/
|
|
async function securityExample(compiler: SynorCompiler): Promise<void> {
|
|
console.log('=== Security Scanning ===');
|
|
|
|
const wasm = createMinimalWasm();
|
|
|
|
const security = await compiler.analysis.securityScan(wasm);
|
|
|
|
console.log(`Security score: ${security.score}/100`);
|
|
|
|
if (security.issues && security.issues.length > 0) {
|
|
console.log('\nSecurity issues:');
|
|
for (const issue of security.issues) {
|
|
const severityIcon = {
|
|
'critical': '🔴',
|
|
'high': '🟠',
|
|
'medium': '🟡',
|
|
'low': '🟢',
|
|
}[issue.severity] || '⚪';
|
|
|
|
console.log(`${severityIcon} [${issue.severity.toUpperCase()}] ${issue.type}`);
|
|
console.log(` ${issue.description}`);
|
|
if (issue.location) {
|
|
console.log(` at ${issue.location}`);
|
|
}
|
|
}
|
|
} else {
|
|
console.log('No security issues found!');
|
|
}
|
|
|
|
if (security.recommendations && security.recommendations.length > 0) {
|
|
console.log('\nRecommendations:');
|
|
for (const rec of security.recommendations) {
|
|
console.log(` • ${rec}`);
|
|
}
|
|
}
|
|
|
|
console.log('');
|
|
}
|
|
|
|
/**
|
|
* Create a minimal valid WASM module for testing
|
|
*/
|
|
function createMinimalWasm(): Buffer {
|
|
// Minimal WASM module with magic number and version
|
|
return Buffer.from([
|
|
0x00, 0x61, 0x73, 0x6d, // Magic: \0asm
|
|
0x01, 0x00, 0x00, 0x00, // Version: 1
|
|
// Type section
|
|
0x01, 0x07, 0x01, 0x60, 0x02, 0x7f, 0x7f, 0x01, 0x7f,
|
|
// Function section
|
|
0x03, 0x02, 0x01, 0x00,
|
|
// Export section
|
|
0x07, 0x08, 0x01, 0x04, 0x61, 0x64, 0x64, 0x00, 0x00,
|
|
// Code section
|
|
0x0a, 0x09, 0x01, 0x07, 0x00, 0x20, 0x00, 0x20, 0x01, 0x6a, 0x0b,
|
|
]);
|
|
}
|
|
|
|
// Run examples
|
|
main().catch(console.error);
|