- Introduced DexExample.swift demonstrating decentralized exchange operations including spot trading, perpetual futures, liquidity provision, order book management, and portfolio tracking. - Added IbcExample.swift showcasing inter-blockchain communication operations such as cross-chain transfers, channel management, packet handling, and relayer operations. - Created ZkExample.swift illustrating zero-knowledge proof operations including circuit compilation, proof generation and verification, and trusted setup ceremonies.
399 lines
16 KiB
Java
399 lines
16 KiB
Java
package io.synor.examples;
|
|
|
|
import io.synor.compiler.*;
|
|
import io.synor.compiler.types.*;
|
|
|
|
import java.util.List;
|
|
import java.util.concurrent.CompletableFuture;
|
|
|
|
/**
|
|
* Synor Compiler SDK Examples for Java
|
|
*
|
|
* Demonstrates smart contract compilation and analysis:
|
|
* - WASM contract compilation and optimization
|
|
* - ABI extraction and encoding
|
|
* - Contract analysis and security scanning
|
|
* - Validation and verification
|
|
*/
|
|
public class CompilerExample {
|
|
|
|
public static void main(String[] args) throws Exception {
|
|
// Initialize client
|
|
CompilerConfig config = CompilerConfig.builder()
|
|
.apiKey(System.getenv("SYNOR_API_KEY") != null ?
|
|
System.getenv("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)
|
|
.build();
|
|
|
|
SynorCompiler compiler = new SynorCompiler(config);
|
|
|
|
try {
|
|
// Check service health
|
|
boolean healthy = compiler.healthCheck().get();
|
|
System.out.println("Service healthy: " + healthy + "\n");
|
|
|
|
// Run examples
|
|
compileContractExample(compiler);
|
|
compilationModesExample(compiler);
|
|
abiExample(compiler);
|
|
analysisExample(compiler);
|
|
validationExample(compiler);
|
|
securityExample(compiler);
|
|
} finally {
|
|
compiler.close();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create a minimal valid WASM module for testing.
|
|
*/
|
|
static byte[] createMinimalWasm() {
|
|
return new byte[] {
|
|
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
|
|
};
|
|
}
|
|
|
|
static void compileContractExample(SynorCompiler compiler) throws Exception {
|
|
System.out.println("=== Contract Compilation ===");
|
|
|
|
byte[] wasm = createMinimalWasm();
|
|
|
|
CompileResult result = compiler.compile(wasm, CompileOptions.builder()
|
|
.optimizationLevel(OptimizationLevel.SIZE)
|
|
.useWasmOpt(true)
|
|
.validate(true)
|
|
.extractMetadata(true)
|
|
.generateAbi(true)
|
|
.stripOptions(StripOptions.builder()
|
|
.stripDebug(true)
|
|
.stripProducers(true)
|
|
.stripNames(true)
|
|
.stripCustom(true)
|
|
.stripUnused(true)
|
|
.preserveSections(List.of())
|
|
.build())
|
|
.build()).get();
|
|
|
|
System.out.println("Compilation result:");
|
|
System.out.println(" Contract ID: " + result.getContractId());
|
|
System.out.println(" Code hash: " + result.getCodeHash());
|
|
System.out.println(" Original size: " + result.getOriginalSize() + " bytes");
|
|
System.out.println(" Optimized size: " + result.getOptimizedSize() + " bytes");
|
|
System.out.println(" Size reduction: " + String.format("%.1f", result.getSizeReduction()) + "%");
|
|
System.out.println(" Estimated deploy gas: " + result.getEstimatedDeployGas());
|
|
|
|
if (result.getMetadata() != null) {
|
|
System.out.println("\nMetadata:");
|
|
System.out.println(" Name: " + result.getMetadata().getName());
|
|
System.out.println(" Version: " + result.getMetadata().getVersion());
|
|
System.out.println(" SDK Version: " + result.getMetadata().getSdkVersion());
|
|
}
|
|
|
|
if (result.getAbi() != null) {
|
|
System.out.println("\nABI:");
|
|
System.out.println(" Functions: " + (result.getAbi().getFunctions() != null ?
|
|
result.getAbi().getFunctions().size() : 0));
|
|
System.out.println(" Events: " + (result.getAbi().getEvents() != null ?
|
|
result.getAbi().getEvents().size() : 0));
|
|
System.out.println(" Errors: " + (result.getAbi().getErrors() != null ?
|
|
result.getAbi().getErrors().size() : 0));
|
|
}
|
|
|
|
System.out.println();
|
|
}
|
|
|
|
static void compilationModesExample(SynorCompiler compiler) throws Exception {
|
|
System.out.println("=== Compilation Modes ===");
|
|
|
|
byte[] wasm = createMinimalWasm();
|
|
|
|
// Development mode: fast compilation, debugging support
|
|
System.out.println("Development mode:");
|
|
CompileResult devResult = compiler.contracts().compileDev(wasm).get();
|
|
System.out.println(" Size: " + devResult.getOptimizedSize() + " bytes");
|
|
System.out.println(" Optimization: none");
|
|
|
|
// Production mode: maximum optimization
|
|
System.out.println("\nProduction mode:");
|
|
CompileResult prodResult = compiler.contracts().compileProduction(wasm).get();
|
|
System.out.println(" Size: " + prodResult.getOptimizedSize() + " bytes");
|
|
System.out.println(" Optimization: aggressive");
|
|
System.out.println(" Size savings: " + (devResult.getOptimizedSize() - prodResult.getOptimizedSize()) + " bytes");
|
|
|
|
// Custom optimization levels
|
|
System.out.println("\nOptimization levels:");
|
|
OptimizationLevel[] levels = {
|
|
OptimizationLevel.NONE,
|
|
OptimizationLevel.BASIC,
|
|
OptimizationLevel.SIZE,
|
|
OptimizationLevel.AGGRESSIVE
|
|
};
|
|
|
|
for (OptimizationLevel level : levels) {
|
|
CompileResult result = compiler.compile(wasm, CompileOptions.builder()
|
|
.optimizationLevel(level)
|
|
.build()).get();
|
|
System.out.println(" " + level + ": " + result.getOptimizedSize() + " bytes");
|
|
}
|
|
|
|
System.out.println();
|
|
}
|
|
|
|
static void abiExample(SynorCompiler compiler) throws Exception {
|
|
System.out.println("=== ABI Operations ===");
|
|
|
|
byte[] wasm = createMinimalWasm();
|
|
|
|
// Extract ABI from WASM
|
|
ContractAbi abi = compiler.abi().extract(wasm).get();
|
|
System.out.println("Contract: " + abi.getName());
|
|
System.out.println("Version: " + abi.getVersion());
|
|
|
|
// List functions
|
|
if (abi.getFunctions() != null && !abi.getFunctions().isEmpty()) {
|
|
System.out.println("\nFunctions:");
|
|
for (AbiFunction func : abi.getFunctions()) {
|
|
StringBuilder inputs = new StringBuilder();
|
|
if (func.getInputs() != null) {
|
|
for (int i = 0; i < func.getInputs().size(); i++) {
|
|
AbiParam param = func.getInputs().get(i);
|
|
if (i > 0) inputs.append(", ");
|
|
inputs.append(param.getName()).append(": ").append(param.getType().getTypeName());
|
|
}
|
|
}
|
|
|
|
StringBuilder outputs = new StringBuilder();
|
|
if (func.getOutputs() != null && !func.getOutputs().isEmpty()) {
|
|
for (int i = 0; i < func.getOutputs().size(); i++) {
|
|
if (i > 0) outputs.append(", ");
|
|
outputs.append(func.getOutputs().get(i).getType().getTypeName());
|
|
}
|
|
} else {
|
|
outputs.append("void");
|
|
}
|
|
|
|
StringBuilder modifiers = new StringBuilder();
|
|
if (func.isView()) modifiers.append("view ");
|
|
if (func.isPayable()) modifiers.append("payable");
|
|
|
|
System.out.println(" " + func.getName() + "(" + inputs + ") -> " + outputs + " " + modifiers);
|
|
System.out.println(" Selector: " + func.getSelector());
|
|
}
|
|
}
|
|
|
|
// List events
|
|
if (abi.getEvents() != null && !abi.getEvents().isEmpty()) {
|
|
System.out.println("\nEvents:");
|
|
for (AbiEvent event : abi.getEvents()) {
|
|
StringBuilder params = new StringBuilder();
|
|
if (event.getParams() != null) {
|
|
for (int i = 0; i < event.getParams().size(); i++) {
|
|
AbiEventParam param = event.getParams().get(i);
|
|
if (i > 0) params.append(", ");
|
|
if (param.isIndexed()) params.append("indexed ");
|
|
params.append(param.getName()).append(": ").append(param.getType().getTypeName());
|
|
}
|
|
}
|
|
System.out.println(" " + event.getName() + "(" + params + ")");
|
|
System.out.println(" Topic: " + event.getTopic());
|
|
}
|
|
}
|
|
|
|
// Encode a function call
|
|
if (abi.getFunctions() != null && !abi.getFunctions().isEmpty()) {
|
|
AbiFunction func = abi.getFunctions().get(0);
|
|
byte[] encoded = compiler.abi().encodeCall(func, List.of("arg1", "arg2")).get();
|
|
System.out.println("\nEncoded call to " + func.getName() + ": " + bytesToHex(encoded));
|
|
|
|
// Decode a result
|
|
Object decoded = compiler.abi().decodeResult(func, encoded).get();
|
|
System.out.println("Decoded result: " + decoded);
|
|
}
|
|
|
|
System.out.println();
|
|
}
|
|
|
|
static void analysisExample(SynorCompiler compiler) throws Exception {
|
|
System.out.println("=== Contract Analysis ===");
|
|
|
|
byte[] wasm = createMinimalWasm();
|
|
|
|
// Full analysis
|
|
ContractAnalysis analysis = compiler.analysis().analyze(wasm).get();
|
|
|
|
// Size breakdown
|
|
if (analysis.getSizeBreakdown() != null) {
|
|
SizeBreakdown size = analysis.getSizeBreakdown();
|
|
System.out.println("Size breakdown:");
|
|
System.out.println(" Code: " + size.getCode() + " bytes");
|
|
System.out.println(" Data: " + size.getData() + " bytes");
|
|
System.out.println(" Functions: " + size.getFunctions() + " bytes");
|
|
System.out.println(" Memory: " + size.getMemory() + " bytes");
|
|
System.out.println(" Exports: " + size.getExports() + " bytes");
|
|
System.out.println(" Imports: " + size.getImports() + " bytes");
|
|
System.out.println(" Total: " + size.getTotal() + " bytes");
|
|
}
|
|
|
|
// Function analysis
|
|
if (analysis.getFunctions() != null && !analysis.getFunctions().isEmpty()) {
|
|
System.out.println("\nFunction analysis:");
|
|
for (FunctionAnalysis func : analysis.getFunctions().subList(0,
|
|
Math.min(5, analysis.getFunctions().size()))) {
|
|
System.out.println(" " + func.getName() + ":");
|
|
System.out.println(" Size: " + func.getSize() + " bytes");
|
|
System.out.println(" Instructions: " + func.getInstructionCount());
|
|
System.out.println(" Locals: " + func.getLocalCount());
|
|
System.out.println(" Exported: " + func.isExported());
|
|
System.out.println(" Estimated gas: " + func.getEstimatedGas());
|
|
}
|
|
}
|
|
|
|
// Import analysis
|
|
if (analysis.getImports() != null && !analysis.getImports().isEmpty()) {
|
|
System.out.println("\nImports:");
|
|
for (ImportAnalysis imp : analysis.getImports()) {
|
|
System.out.println(" " + imp.getModule() + "." + imp.getName() + " (" + imp.getKind() + ")");
|
|
}
|
|
}
|
|
|
|
// Gas analysis
|
|
if (analysis.getGasAnalysis() != null) {
|
|
GasAnalysis gas = analysis.getGasAnalysis();
|
|
System.out.println("\nGas analysis:");
|
|
System.out.println(" Deployment: " + gas.getDeploymentGas());
|
|
System.out.println(" Memory init: " + gas.getMemoryInitGas());
|
|
System.out.println(" Data section: " + gas.getDataSectionGas());
|
|
}
|
|
|
|
// Extract metadata
|
|
ContractMetadata metadata = compiler.analysis().extractMetadata(wasm).get();
|
|
System.out.println("\nContract metadata:");
|
|
System.out.println(" Name: " + metadata.getName());
|
|
System.out.println(" Version: " + metadata.getVersion());
|
|
System.out.println(" Build timestamp: " + metadata.getBuildTimestamp());
|
|
|
|
// Estimate deployment gas
|
|
long gasEstimate = compiler.analysis().estimateDeployGas(wasm).get();
|
|
System.out.println("\nEstimated deployment gas: " + gasEstimate);
|
|
|
|
System.out.println();
|
|
}
|
|
|
|
static void validationExample(SynorCompiler compiler) throws Exception {
|
|
System.out.println("=== Contract Validation ===");
|
|
|
|
byte[] wasm = createMinimalWasm();
|
|
|
|
// Full validation
|
|
ValidationResult result = compiler.validation().validate(wasm).get();
|
|
System.out.println("Valid: " + result.isValid());
|
|
System.out.println("Exports: " + result.getExportCount());
|
|
System.out.println("Imports: " + result.getImportCount());
|
|
System.out.println("Functions: " + result.getFunctionCount());
|
|
System.out.println("Memory pages: " + result.getMemoryPages());
|
|
|
|
if (result.getErrors() != null && !result.getErrors().isEmpty()) {
|
|
System.out.println("\nValidation errors:");
|
|
for (ValidationError error : result.getErrors()) {
|
|
System.out.println(" [" + error.getCode() + "] " + error.getMessage());
|
|
if (error.getLocation() != null) {
|
|
System.out.println(" at " + error.getLocation());
|
|
}
|
|
}
|
|
}
|
|
|
|
if (result.getWarnings() != null && !result.getWarnings().isEmpty()) {
|
|
System.out.println("\nWarnings:");
|
|
for (String warning : result.getWarnings()) {
|
|
System.out.println(" " + warning);
|
|
}
|
|
}
|
|
|
|
// Quick validation
|
|
boolean isValid = compiler.validation().isValid(wasm).get();
|
|
System.out.println("\nQuick validation: " + isValid);
|
|
|
|
// Get validation errors only
|
|
List<ValidationError> errors = compiler.validation().getErrors(wasm).get();
|
|
System.out.println("Error count: " + errors.size());
|
|
|
|
// Validate required exports
|
|
boolean hasRequired = compiler.validation().validateExports(
|
|
wasm,
|
|
List.of("init", "execute", "query")
|
|
).get();
|
|
System.out.println("Has required exports: " + hasRequired);
|
|
|
|
// Validate memory constraints
|
|
boolean memoryValid = compiler.validation().validateMemory(wasm, 16).get();
|
|
System.out.println("Memory within 16 pages: " + memoryValid);
|
|
|
|
System.out.println();
|
|
}
|
|
|
|
static void securityExample(SynorCompiler compiler) throws Exception {
|
|
System.out.println("=== Security Scanning ===");
|
|
|
|
byte[] wasm = createMinimalWasm();
|
|
|
|
SecurityScanResult security = compiler.analysis().securityScan(wasm).get();
|
|
|
|
System.out.println("Security score: " + security.getScore() + "/100");
|
|
|
|
if (security.getIssues() != null && !security.getIssues().isEmpty()) {
|
|
System.out.println("\nSecurity issues:");
|
|
for (SecurityIssue issue : security.getIssues()) {
|
|
String icon;
|
|
switch (issue.getSeverity().toLowerCase()) {
|
|
case "critical": icon = "[CRIT]"; break;
|
|
case "high": icon = "[HIGH]"; break;
|
|
case "medium": icon = "[MED]"; break;
|
|
case "low": icon = "[LOW]"; break;
|
|
default: icon = "[???]";
|
|
}
|
|
System.out.println(icon + " [" + issue.getSeverity().toUpperCase() + "] " + issue.getType());
|
|
System.out.println(" " + issue.getDescription());
|
|
if (issue.getLocation() != null) {
|
|
System.out.println(" at " + issue.getLocation());
|
|
}
|
|
}
|
|
} else {
|
|
System.out.println("No security issues found!");
|
|
}
|
|
|
|
if (security.getRecommendations() != null && !security.getRecommendations().isEmpty()) {
|
|
System.out.println("\nRecommendations:");
|
|
for (String rec : security.getRecommendations()) {
|
|
System.out.println(" • " + rec);
|
|
}
|
|
}
|
|
|
|
System.out.println();
|
|
}
|
|
|
|
private static String bytesToHex(byte[] bytes) {
|
|
StringBuilder sb = new StringBuilder();
|
|
for (byte b : bytes) {
|
|
sb.append(String.format("%02x", b));
|
|
}
|
|
return sb.toString();
|
|
}
|
|
}
|