Add IBC and ZK SDK examples for Rust
- 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.
This commit is contained in:
parent
08a55aa80e
commit
9416d76108
27 changed files with 10690 additions and 1 deletions
|
|
@ -1 +1 @@
|
|||
{"version":2,"entries":[{"package":"synor_compute","rootUri":"../","packageUri":"lib/"}]}
|
||||
{"version":2,"entries":[{"package":"synor_sdk","rootUri":"../","packageUri":"lib/"}]}
|
||||
359
sdk/flutter/example/compiler_example.dart
Normal file
359
sdk/flutter/example/compiler_example.dart
Normal file
|
|
@ -0,0 +1,359 @@
|
|||
/// Synor Compiler SDK Examples for Flutter/Dart
|
||||
///
|
||||
/// Demonstrates smart contract compilation and analysis:
|
||||
/// - WASM contract compilation and optimization
|
||||
/// - ABI extraction and encoding
|
||||
/// - Contract analysis and security scanning
|
||||
/// - Validation and verification
|
||||
|
||||
import 'dart:io';
|
||||
import 'dart:typed_data';
|
||||
import 'package:synor_compiler/synor_compiler.dart';
|
||||
|
||||
Future<void> main() async {
|
||||
// Initialize client
|
||||
final config = CompilerConfig(
|
||||
apiKey: Platform.environment['SYNOR_API_KEY'] ?? 'your-api-key',
|
||||
endpoint: 'https://compiler.synor.io/v1',
|
||||
timeout: const Duration(seconds: 60),
|
||||
retries: 3,
|
||||
debug: false,
|
||||
defaultOptimizationLevel: OptimizationLevel.size,
|
||||
maxContractSize: 256 * 1024,
|
||||
useWasmOpt: true,
|
||||
validate: true,
|
||||
extractMetadata: true,
|
||||
generateAbi: true,
|
||||
);
|
||||
|
||||
final compiler = SynorCompiler(config);
|
||||
|
||||
try {
|
||||
// Check service health
|
||||
final healthy = await compiler.healthCheck();
|
||||
print('Service healthy: $healthy\n');
|
||||
|
||||
// Run examples
|
||||
await compileContractExample(compiler);
|
||||
await compilationModesExample(compiler);
|
||||
await abiExample(compiler);
|
||||
await analysisExample(compiler);
|
||||
await validationExample(compiler);
|
||||
await securityExample(compiler);
|
||||
} finally {
|
||||
await compiler.close();
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a minimal valid WASM module for testing.
|
||||
Uint8List createMinimalWasm() {
|
||||
return Uint8List.fromList([
|
||||
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,
|
||||
]);
|
||||
}
|
||||
|
||||
Future<void> compileContractExample(SynorCompiler compiler) async {
|
||||
print('=== Contract Compilation ===');
|
||||
|
||||
final wasm = createMinimalWasm();
|
||||
|
||||
final result = await compiler.compile(
|
||||
wasm,
|
||||
options: CompileOptions(
|
||||
optimizationLevel: OptimizationLevel.size,
|
||||
useWasmOpt: true,
|
||||
validate: true,
|
||||
extractMetadata: true,
|
||||
generateAbi: true,
|
||||
stripOptions: StripOptions(
|
||||
stripDebug: true,
|
||||
stripProducers: true,
|
||||
stripNames: true,
|
||||
stripCustom: true,
|
||||
stripUnused: true,
|
||||
preserveSections: [],
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
print('Compilation result:');
|
||||
print(' Contract ID: ${result.contractId}');
|
||||
print(' Code hash: ${result.codeHash}');
|
||||
print(' Original size: ${result.originalSize} bytes');
|
||||
print(' Optimized size: ${result.optimizedSize} bytes');
|
||||
print(' Size reduction: ${result.sizeReduction.toStringAsFixed(1)}%');
|
||||
print(' Estimated deploy gas: ${result.estimatedDeployGas}');
|
||||
|
||||
if (result.metadata != null) {
|
||||
print('\nMetadata:');
|
||||
print(' Name: ${result.metadata!.name}');
|
||||
print(' Version: ${result.metadata!.version}');
|
||||
print(' SDK Version: ${result.metadata!.sdkVersion}');
|
||||
}
|
||||
|
||||
if (result.abi != null) {
|
||||
print('\nABI:');
|
||||
print(' Functions: ${result.abi!.functions?.length ?? 0}');
|
||||
print(' Events: ${result.abi!.events?.length ?? 0}');
|
||||
print(' Errors: ${result.abi!.errors?.length ?? 0}');
|
||||
}
|
||||
|
||||
print('');
|
||||
}
|
||||
|
||||
Future<void> compilationModesExample(SynorCompiler compiler) async {
|
||||
print('=== Compilation Modes ===');
|
||||
|
||||
final wasm = createMinimalWasm();
|
||||
|
||||
// Development mode: fast compilation, debugging support
|
||||
print('Development mode:');
|
||||
final devResult = await compiler.contracts.compileDev(wasm);
|
||||
print(' Size: ${devResult.optimizedSize} bytes');
|
||||
print(' Optimization: none');
|
||||
|
||||
// Production mode: maximum optimization
|
||||
print('\nProduction mode:');
|
||||
final prodResult = await compiler.contracts.compileProduction(wasm);
|
||||
print(' Size: ${prodResult.optimizedSize} bytes');
|
||||
print(' Optimization: aggressive');
|
||||
print(' Size savings: ${devResult.optimizedSize - prodResult.optimizedSize} bytes');
|
||||
|
||||
// Custom optimization levels
|
||||
print('\nOptimization levels:');
|
||||
final levels = [
|
||||
OptimizationLevel.none,
|
||||
OptimizationLevel.basic,
|
||||
OptimizationLevel.size,
|
||||
OptimizationLevel.aggressive,
|
||||
];
|
||||
|
||||
for (final level in levels) {
|
||||
final result = await compiler.compile(
|
||||
wasm,
|
||||
options: CompileOptions(optimizationLevel: level),
|
||||
);
|
||||
print(' $level: ${result.optimizedSize} bytes');
|
||||
}
|
||||
|
||||
print('');
|
||||
}
|
||||
|
||||
Future<void> abiExample(SynorCompiler compiler) async {
|
||||
print('=== ABI Operations ===');
|
||||
|
||||
final wasm = createMinimalWasm();
|
||||
|
||||
// Extract ABI from WASM
|
||||
final abi = await compiler.abi.extract(wasm);
|
||||
print('Contract: ${abi.name}');
|
||||
print('Version: ${abi.version}');
|
||||
|
||||
// List functions
|
||||
if (abi.functions != null && abi.functions!.isNotEmpty) {
|
||||
print('\nFunctions:');
|
||||
for (final func in abi.functions!) {
|
||||
final inputs = func.inputs
|
||||
?.map((i) => '${i.name}: ${i.type.typeName}')
|
||||
.join(', ') ??
|
||||
'';
|
||||
final outputs = func.outputs?.map((o) => o.type.typeName).join(', ') ?? 'void';
|
||||
final modifiers = [
|
||||
if (func.view) 'view',
|
||||
if (func.payable) 'payable',
|
||||
].join(' ');
|
||||
print(' ${func.name}($inputs) -> $outputs $modifiers');
|
||||
print(' Selector: ${func.selector}');
|
||||
}
|
||||
}
|
||||
|
||||
// List events
|
||||
if (abi.events != null && abi.events!.isNotEmpty) {
|
||||
print('\nEvents:');
|
||||
for (final event in abi.events!) {
|
||||
final params = event.params
|
||||
?.map((p) =>
|
||||
'${p.indexed ? "indexed " : ""}${p.name}: ${p.type.typeName}')
|
||||
.join(', ') ??
|
||||
'';
|
||||
print(' ${event.name}($params)');
|
||||
print(' Topic: ${event.topic}');
|
||||
}
|
||||
}
|
||||
|
||||
// Encode a function call
|
||||
if (abi.functions != null && abi.functions!.isNotEmpty) {
|
||||
final func = abi.functions!.first;
|
||||
final encoded = await compiler.abi.encodeCall(func, ['arg1', 'arg2']);
|
||||
print('\nEncoded call to ${func.name}: $encoded');
|
||||
|
||||
// Decode a result
|
||||
final decoded = await compiler.abi.decodeResult(func, encoded);
|
||||
print('Decoded result: $decoded');
|
||||
}
|
||||
|
||||
print('');
|
||||
}
|
||||
|
||||
Future<void> analysisExample(SynorCompiler compiler) async {
|
||||
print('=== Contract Analysis ===');
|
||||
|
||||
final wasm = createMinimalWasm();
|
||||
|
||||
// Full analysis
|
||||
final analysis = await compiler.analysis.analyze(wasm);
|
||||
|
||||
// Size breakdown
|
||||
if (analysis.sizeBreakdown != null) {
|
||||
print('Size breakdown:');
|
||||
print(' Code: ${analysis.sizeBreakdown!.code} bytes');
|
||||
print(' Data: ${analysis.sizeBreakdown!.data} bytes');
|
||||
print(' Functions: ${analysis.sizeBreakdown!.functions} bytes');
|
||||
print(' Memory: ${analysis.sizeBreakdown!.memory} bytes');
|
||||
print(' Exports: ${analysis.sizeBreakdown!.exports} bytes');
|
||||
print(' Imports: ${analysis.sizeBreakdown!.imports} bytes');
|
||||
print(' Total: ${analysis.sizeBreakdown!.total} bytes');
|
||||
}
|
||||
|
||||
// Function analysis
|
||||
if (analysis.functions != null && analysis.functions!.isNotEmpty) {
|
||||
print('\nFunction analysis:');
|
||||
for (final func in analysis.functions!.take(5)) {
|
||||
print(' ${func.name}:');
|
||||
print(' Size: ${func.size} bytes');
|
||||
print(' Instructions: ${func.instructionCount}');
|
||||
print(' Locals: ${func.localCount}');
|
||||
print(' Exported: ${func.exported}');
|
||||
print(' Estimated gas: ${func.estimatedGas}');
|
||||
}
|
||||
}
|
||||
|
||||
// Import analysis
|
||||
if (analysis.imports != null && analysis.imports!.isNotEmpty) {
|
||||
print('\nImports:');
|
||||
for (final imp in analysis.imports!) {
|
||||
print(' ${imp.module}.${imp.name} (${imp.kind})');
|
||||
}
|
||||
}
|
||||
|
||||
// Gas analysis
|
||||
if (analysis.gasAnalysis != null) {
|
||||
print('\nGas analysis:');
|
||||
print(' Deployment: ${analysis.gasAnalysis!.deploymentGas}');
|
||||
print(' Memory init: ${analysis.gasAnalysis!.memoryInitGas}');
|
||||
print(' Data section: ${analysis.gasAnalysis!.dataSectionGas}');
|
||||
}
|
||||
|
||||
// Extract metadata
|
||||
final metadata = await compiler.analysis.extractMetadata(wasm);
|
||||
print('\nContract metadata:');
|
||||
print(' Name: ${metadata.name}');
|
||||
print(' Version: ${metadata.version}');
|
||||
print(' Build timestamp: ${metadata.buildTimestamp}');
|
||||
|
||||
// Estimate deployment gas
|
||||
final gas = await compiler.analysis.estimateDeployGas(wasm);
|
||||
print('\nEstimated deployment gas: $gas');
|
||||
|
||||
print('');
|
||||
}
|
||||
|
||||
Future<void> validationExample(SynorCompiler compiler) async {
|
||||
print('=== Contract Validation ===');
|
||||
|
||||
final wasm = createMinimalWasm();
|
||||
|
||||
// Full validation
|
||||
final result = await compiler.validation.validate(wasm);
|
||||
print('Valid: ${result.valid}');
|
||||
print('Exports: ${result.exportCount}');
|
||||
print('Imports: ${result.importCount}');
|
||||
print('Functions: ${result.functionCount}');
|
||||
print('Memory pages: ${result.memoryPages}');
|
||||
|
||||
if (result.errors != null && result.errors!.isNotEmpty) {
|
||||
print('\nValidation errors:');
|
||||
for (final error in result.errors!) {
|
||||
print(' [${error.code}] ${error.message}');
|
||||
if (error.location != null) {
|
||||
print(' at ${error.location}');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (result.warnings != null && result.warnings!.isNotEmpty) {
|
||||
print('\nWarnings:');
|
||||
for (final warning in result.warnings!) {
|
||||
print(' $warning');
|
||||
}
|
||||
}
|
||||
|
||||
// Quick validation
|
||||
final isValid = await compiler.validation.isValid(wasm);
|
||||
print('\nQuick validation: $isValid');
|
||||
|
||||
// Get validation errors only
|
||||
final errors = await compiler.validation.getErrors(wasm);
|
||||
print('Error count: ${errors.length}');
|
||||
|
||||
// Validate required exports
|
||||
final hasRequired = await compiler.validation.validateExports(
|
||||
wasm,
|
||||
['init', 'execute', 'query'],
|
||||
);
|
||||
print('Has required exports: $hasRequired');
|
||||
|
||||
// Validate memory constraints
|
||||
final memoryValid = await compiler.validation.validateMemory(wasm, 16);
|
||||
print('Memory within 16 pages: $memoryValid');
|
||||
|
||||
print('');
|
||||
}
|
||||
|
||||
Future<void> securityExample(SynorCompiler compiler) async {
|
||||
print('=== Security Scanning ===');
|
||||
|
||||
final wasm = createMinimalWasm();
|
||||
|
||||
final security = await compiler.analysis.securityScan(wasm);
|
||||
|
||||
print('Security score: ${security.score}/100');
|
||||
|
||||
if (security.issues != null && security.issues!.isNotEmpty) {
|
||||
print('\nSecurity issues:');
|
||||
final severityIcons = {
|
||||
'critical': '[CRIT]',
|
||||
'high': '[HIGH]',
|
||||
'medium': '[MED]',
|
||||
'low': '[LOW]',
|
||||
};
|
||||
for (final issue in security.issues!) {
|
||||
final icon = severityIcons[issue.severity] ?? '[???]';
|
||||
print('$icon [${issue.severity.toUpperCase()}] ${issue.type}');
|
||||
print(' ${issue.description}');
|
||||
if (issue.location != null) {
|
||||
print(' at ${issue.location}');
|
||||
}
|
||||
}
|
||||
} else {
|
||||
print('No security issues found!');
|
||||
}
|
||||
|
||||
if (security.recommendations != null && security.recommendations!.isNotEmpty) {
|
||||
print('\nRecommendations:');
|
||||
for (final rec in security.recommendations!) {
|
||||
print(' • $rec');
|
||||
}
|
||||
}
|
||||
|
||||
print('');
|
||||
}
|
||||
247
sdk/flutter/example/crypto_example.dart
Normal file
247
sdk/flutter/example/crypto_example.dart
Normal file
|
|
@ -0,0 +1,247 @@
|
|||
/// Synor Crypto SDK Examples for Flutter/Dart
|
||||
///
|
||||
/// Demonstrates quantum-resistant cryptographic operations:
|
||||
/// - Hybrid Ed25519 + Dilithium3 signatures
|
||||
/// - BIP-39 mnemonic generation and validation
|
||||
/// - Post-quantum algorithms (Falcon, SPHINCS+)
|
||||
/// - Key derivation functions
|
||||
|
||||
import 'dart:io';
|
||||
import 'package:synor_crypto/synor_crypto.dart';
|
||||
|
||||
Future<void> main() async {
|
||||
// Initialize client
|
||||
final config = CryptoConfig(
|
||||
apiKey: Platform.environment['SYNOR_API_KEY'] ?? 'your-api-key',
|
||||
endpoint: 'https://crypto.synor.io/v1',
|
||||
timeout: const Duration(seconds: 30),
|
||||
retries: 3,
|
||||
debug: false,
|
||||
defaultNetwork: Network.mainnet,
|
||||
);
|
||||
|
||||
final crypto = SynorCrypto(config);
|
||||
|
||||
try {
|
||||
// Check service health
|
||||
final healthy = await crypto.healthCheck();
|
||||
print('Service healthy: $healthy\n');
|
||||
|
||||
// Run examples
|
||||
await mnemonicExample(crypto);
|
||||
await keypairExample(crypto);
|
||||
await signingExample(crypto);
|
||||
await falconExample(crypto);
|
||||
await sphincsExample(crypto);
|
||||
await kdfExample(crypto);
|
||||
await hashExample(crypto);
|
||||
} finally {
|
||||
await crypto.close();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> mnemonicExample(SynorCrypto crypto) async {
|
||||
print('=== Mnemonic Operations ===');
|
||||
|
||||
// Generate a 24-word mnemonic (256-bit entropy)
|
||||
final mnemonic = await crypto.mnemonic.generate(24);
|
||||
print('Generated mnemonic: ${mnemonic.phrase}');
|
||||
print('Word count: ${mnemonic.wordCount}');
|
||||
|
||||
// Validate a mnemonic
|
||||
final validation = await crypto.mnemonic.validate(mnemonic.phrase);
|
||||
print('Valid: ${validation.valid}');
|
||||
if (!validation.valid) {
|
||||
print('Error: ${validation.error}');
|
||||
}
|
||||
|
||||
// Convert mnemonic to seed
|
||||
final seed = await crypto.mnemonic.toSeed(
|
||||
mnemonic.phrase,
|
||||
passphrase: 'optional-passphrase',
|
||||
);
|
||||
print('Seed (hex): ${seed.toHex().substring(0, 32)}...');
|
||||
|
||||
// Word suggestions for autocomplete
|
||||
final suggestions = await crypto.mnemonic.suggestWords('aban', limit: 5);
|
||||
print('Suggestions for "aban": ${suggestions.join(", ")}');
|
||||
|
||||
print('');
|
||||
}
|
||||
|
||||
Future<void> keypairExample(SynorCrypto crypto) async {
|
||||
print('=== Keypair Operations ===');
|
||||
|
||||
// Generate a random keypair
|
||||
final keypair = await crypto.keypairs.generate();
|
||||
print('Generated hybrid keypair:');
|
||||
print(' Ed25519 public key size: ${keypair.publicKey.ed25519Bytes.length} bytes');
|
||||
print(' Dilithium public key size: ${keypair.publicKey.dilithiumBytes.length} bytes');
|
||||
print(' Total public key size: ${keypair.publicKey.size} bytes');
|
||||
|
||||
// Get addresses for different networks
|
||||
print('\nAddresses:');
|
||||
print(' Mainnet: ${keypair.getAddress(Network.mainnet)}');
|
||||
print(' Testnet: ${keypair.getAddress(Network.testnet)}');
|
||||
print(' Devnet: ${keypair.getAddress(Network.devnet)}');
|
||||
|
||||
// Create keypair from mnemonic (deterministic)
|
||||
final mnemonic = await crypto.mnemonic.generate(24);
|
||||
final keypair2 = await crypto.keypairs.fromMnemonic(mnemonic.phrase, '');
|
||||
final addr = keypair2.getAddress(Network.mainnet);
|
||||
print('\nKeypair from mnemonic: ${addr.substring(0, 20)}...');
|
||||
|
||||
// Derive child keypair using BIP-44 path
|
||||
final path = DerivationPath.external(0, 0); // m/44'/21337'/0'/0/0
|
||||
print('Derivation path: $path');
|
||||
|
||||
print('');
|
||||
}
|
||||
|
||||
Future<void> signingExample(SynorCrypto crypto) async {
|
||||
print('=== Hybrid Signing ===');
|
||||
|
||||
// Generate keypair
|
||||
final keypair = await crypto.keypairs.generate();
|
||||
|
||||
// Sign a message
|
||||
final message = 'Hello, quantum-resistant world!'.codeUnits;
|
||||
final signature = await crypto.signing.sign(keypair, message);
|
||||
|
||||
print('Signature created:');
|
||||
print(' Ed25519 component: ${signature.ed25519Bytes.length} bytes');
|
||||
print(' Dilithium component: ${signature.dilithiumBytes.length} bytes');
|
||||
print(' Total signature size: ${signature.size} bytes');
|
||||
|
||||
// Verify the signature
|
||||
final valid = await crypto.signing.verify(keypair.publicKey, message, signature);
|
||||
print('\nVerification result: $valid');
|
||||
|
||||
// Verify with tampered message fails
|
||||
final tamperedMessage = 'Hello, tampered message!'.codeUnits;
|
||||
final invalidResult = await crypto.signing.verify(
|
||||
keypair.publicKey,
|
||||
tamperedMessage,
|
||||
signature,
|
||||
);
|
||||
print('Tampered message verification: $invalidResult');
|
||||
|
||||
print('');
|
||||
}
|
||||
|
||||
Future<void> falconExample(SynorCrypto crypto) async {
|
||||
print('=== Falcon Post-Quantum Signatures ===');
|
||||
|
||||
// Generate Falcon-512 keypair (128-bit security)
|
||||
final falcon512 = await crypto.falcon.generate(FalconVariant.falcon512);
|
||||
print('Falcon-512 keypair:');
|
||||
print(' Public key: ${falcon512.publicKey.keyBytes.length} bytes');
|
||||
print(' Security level: 128-bit');
|
||||
|
||||
// Generate Falcon-1024 keypair (256-bit security)
|
||||
final falcon1024 = await crypto.falcon.generate(FalconVariant.falcon1024);
|
||||
print('\nFalcon-1024 keypair:');
|
||||
print(' Public key: ${falcon1024.publicKey.keyBytes.length} bytes');
|
||||
print(' Security level: 256-bit');
|
||||
|
||||
// Sign with Falcon-512
|
||||
final message = 'Post-quantum secure message'.codeUnits;
|
||||
final signature = await crypto.falcon.sign(falcon512, message);
|
||||
print('\nFalcon-512 signature: ${signature.signatureBytes.length} bytes');
|
||||
|
||||
// Verify
|
||||
final valid = await crypto.falcon.verify(
|
||||
falcon512.publicKey.keyBytes,
|
||||
message,
|
||||
signature,
|
||||
);
|
||||
print('Verification: $valid');
|
||||
|
||||
print('');
|
||||
}
|
||||
|
||||
Future<void> sphincsExample(SynorCrypto crypto) async {
|
||||
print('=== SPHINCS+ Hash-Based Signatures ===');
|
||||
|
||||
// SPHINCS+ variants with different security levels
|
||||
final variants = [
|
||||
(SphincsVariant.shake128s, 128, 7856),
|
||||
(SphincsVariant.shake192s, 192, 16224),
|
||||
(SphincsVariant.shake256s, 256, 29792),
|
||||
];
|
||||
|
||||
// Generate and demonstrate each variant
|
||||
for (final (variant, security, sigSize) in variants) {
|
||||
final keypair = await crypto.sphincs.generate(variant);
|
||||
print('SPHINCS+ $variant:');
|
||||
print(' Security level: $security-bit');
|
||||
print(' Expected signature size: $sigSize bytes');
|
||||
|
||||
// Sign a message
|
||||
final message = 'Hash-based quantum security'.codeUnits;
|
||||
final signature = await crypto.sphincs.sign(keypair, message);
|
||||
print(' Actual signature size: ${signature.signatureBytes.length} bytes');
|
||||
|
||||
// Verify
|
||||
final valid = await crypto.sphincs.verify(
|
||||
keypair.publicKey.keyBytes,
|
||||
message,
|
||||
signature,
|
||||
);
|
||||
print(' Verification: $valid\n');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> kdfExample(SynorCrypto crypto) async {
|
||||
print('=== Key Derivation Functions ===');
|
||||
|
||||
// HKDF (HMAC-based Key Derivation Function)
|
||||
final seed = 'master-secret-key-material-here'.codeUnits;
|
||||
final hkdfConfig = DerivationConfig(
|
||||
salt: 'application-salt'.codeUnits,
|
||||
info: 'encryption-key'.codeUnits,
|
||||
outputLength: 32,
|
||||
);
|
||||
|
||||
final derivedKey = await crypto.kdf.deriveKey(seed, hkdfConfig);
|
||||
print('HKDF derived key: ${derivedKey.toHex()}');
|
||||
|
||||
// PBKDF2 (Password-Based Key Derivation Function)
|
||||
final password = 'user-password'.codeUnits;
|
||||
final pbkdf2Config = PasswordDerivationConfig(
|
||||
salt: 'random-salt-value'.codeUnits,
|
||||
iterations: 100000,
|
||||
outputLength: 32,
|
||||
);
|
||||
|
||||
final passwordKey = await crypto.kdf.deriveFromPassword(password, pbkdf2Config);
|
||||
print('PBKDF2 derived key: ${passwordKey.toHex()}');
|
||||
|
||||
print('');
|
||||
}
|
||||
|
||||
Future<void> hashExample(SynorCrypto crypto) async {
|
||||
print('=== Hash Functions ===');
|
||||
|
||||
final data = 'Data to hash'.codeUnits;
|
||||
|
||||
// SHA3-256 (FIPS 202)
|
||||
final sha3 = await crypto.hash.sha3_256(data);
|
||||
print('SHA3-256: ${sha3.hex}');
|
||||
|
||||
// BLAKE3 (fast, parallel)
|
||||
final blake3 = await crypto.hash.blake3(data);
|
||||
print('BLAKE3: ${blake3.hex}');
|
||||
|
||||
// Keccak-256 (Ethereum compatible)
|
||||
final keccak = await crypto.hash.keccak256(data);
|
||||
print('Keccak: ${keccak.hex}');
|
||||
|
||||
print('');
|
||||
}
|
||||
|
||||
extension on List<int> {
|
||||
String toHex() {
|
||||
return map((b) => b.toRadixString(16).padLeft(2, '0')).join();
|
||||
}
|
||||
}
|
||||
349
sdk/flutter/example/dex_example.dart
Normal file
349
sdk/flutter/example/dex_example.dart
Normal file
|
|
@ -0,0 +1,349 @@
|
|||
/// Synor DEX SDK Examples for Flutter/Dart
|
||||
///
|
||||
/// Demonstrates decentralized exchange operations:
|
||||
/// - Spot trading (limit/market orders)
|
||||
/// - Perpetual futures trading
|
||||
/// - Liquidity provision (AMM pools)
|
||||
/// - Order book management
|
||||
/// - Portfolio tracking
|
||||
|
||||
import 'dart:io';
|
||||
import 'dart:math';
|
||||
import 'package:synor_dex/synor_dex.dart';
|
||||
|
||||
Future<void> main() async {
|
||||
// Initialize client
|
||||
final config = DexConfig(
|
||||
apiKey: Platform.environment['SYNOR_API_KEY'] ?? 'your-api-key',
|
||||
endpoint: 'https://dex.synor.io/v1',
|
||||
timeout: const Duration(seconds: 30),
|
||||
retries: 3,
|
||||
debug: false,
|
||||
defaultMarket: 'SYN-USDC',
|
||||
);
|
||||
|
||||
final dex = SynorDex(config);
|
||||
|
||||
try {
|
||||
// Check service health
|
||||
final healthy = await dex.healthCheck();
|
||||
print('Service healthy: $healthy\n');
|
||||
|
||||
// Run examples
|
||||
await marketsExample(dex);
|
||||
await spotTradingExample(dex);
|
||||
await perpsTradingExample(dex);
|
||||
await liquidityExample(dex);
|
||||
await orderbookExample(dex);
|
||||
await portfolioExample(dex);
|
||||
} finally {
|
||||
await dex.close();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> marketsExample(SynorDex dex) async {
|
||||
print('=== Markets ===');
|
||||
|
||||
// Get all markets
|
||||
final markets = await dex.markets.list();
|
||||
print('Available markets: ${markets.length}');
|
||||
|
||||
for (final market in markets.take(5)) {
|
||||
print('\n ${market.symbol}:');
|
||||
print(' Base: ${market.baseAsset}, Quote: ${market.quoteAsset}');
|
||||
print(' Price: ${market.lastPrice}');
|
||||
print(' 24h Volume: ${market.volume24h}');
|
||||
print(' 24h Change: ${market.change24h}%');
|
||||
print(' Status: ${market.status}');
|
||||
}
|
||||
|
||||
// Get specific market
|
||||
final market = await dex.markets.get('SYN-USDC');
|
||||
print('\nSYN-USDC details:');
|
||||
print(' Min order size: ${market.minOrderSize}');
|
||||
print(' Tick size: ${market.tickSize}');
|
||||
print(' Maker fee: ${market.makerFee}%');
|
||||
print(' Taker fee: ${market.takerFee}%');
|
||||
|
||||
// Get market statistics
|
||||
final stats = await dex.markets.getStats('SYN-USDC');
|
||||
print('\nMarket statistics:');
|
||||
print(' High 24h: ${stats.high24h}');
|
||||
print(' Low 24h: ${stats.low24h}');
|
||||
print(' Open interest: ${stats.openInterest}');
|
||||
print(' Funding rate: ${stats.fundingRate}%');
|
||||
|
||||
print('');
|
||||
}
|
||||
|
||||
Future<void> spotTradingExample(SynorDex dex) async {
|
||||
print('=== Spot Trading ===');
|
||||
|
||||
// Place a limit order
|
||||
print('Placing limit buy order...');
|
||||
final limitOrder = await dex.spot.placeOrder(OrderRequest(
|
||||
market: 'SYN-USDC',
|
||||
side: OrderSide.buy,
|
||||
orderType: OrderType.limit,
|
||||
price: '1.50',
|
||||
quantity: '100',
|
||||
timeInForce: TimeInForce.gtc,
|
||||
));
|
||||
|
||||
print('Limit order placed:');
|
||||
print(' Order ID: ${limitOrder.orderId}');
|
||||
print(' Status: ${limitOrder.status}');
|
||||
print(' Price: ${limitOrder.price}');
|
||||
print(' Quantity: ${limitOrder.quantity}');
|
||||
|
||||
// Place a market order
|
||||
print('\nPlacing market sell order...');
|
||||
final marketOrder = await dex.spot.placeOrder(OrderRequest(
|
||||
market: 'SYN-USDC',
|
||||
side: OrderSide.sell,
|
||||
orderType: OrderType.market,
|
||||
quantity: '50',
|
||||
));
|
||||
|
||||
print('Market order executed:');
|
||||
print(' Order ID: ${marketOrder.orderId}');
|
||||
print(' Status: ${marketOrder.status}');
|
||||
print(' Filled: ${marketOrder.filledQuantity}');
|
||||
print(' Avg price: ${marketOrder.averagePrice}');
|
||||
|
||||
// Get order status
|
||||
final status = await dex.spot.getOrder(limitOrder.orderId);
|
||||
print('\nOrder status:');
|
||||
print(' Status: ${status.status}');
|
||||
print(' Filled: ${status.filledQuantity} / ${status.quantity}');
|
||||
print(' Remaining: ${status.remainingQuantity}');
|
||||
|
||||
// Cancel order
|
||||
print('\nCancelling order...');
|
||||
await dex.spot.cancelOrder(limitOrder.orderId);
|
||||
print('Order cancelled successfully');
|
||||
|
||||
// Get open orders
|
||||
final openOrders = await dex.spot.getOpenOrders('SYN-USDC');
|
||||
print('\nOpen orders: ${openOrders.length}');
|
||||
|
||||
// Get trade history
|
||||
final trades = await dex.spot.getTradeHistory('SYN-USDC', limit: 10);
|
||||
print('\nRecent trades: ${trades.length}');
|
||||
for (final trade in trades.take(3)) {
|
||||
print(' ${trade.side} ${trade.quantity} @ ${trade.price} (${trade.timestamp})');
|
||||
}
|
||||
|
||||
print('');
|
||||
}
|
||||
|
||||
Future<void> perpsTradingExample(SynorDex dex) async {
|
||||
print('=== Perpetual Futures Trading ===');
|
||||
|
||||
// Get available perps markets
|
||||
final perpsMarkets = await dex.perps.listMarkets();
|
||||
print('Available perps markets: ${perpsMarkets.length}');
|
||||
|
||||
for (final market in perpsMarkets.take(3)) {
|
||||
print(' ${market.symbol}: ${market.markPrice} (funding: ${market.fundingRate}%)');
|
||||
}
|
||||
|
||||
// Open a long position
|
||||
print('\nOpening long position...');
|
||||
final position = await dex.perps.openPosition(PerpsOrderRequest(
|
||||
market: 'SYN-USDC-PERP',
|
||||
side: OrderSide.buy,
|
||||
orderType: OrderType.limit,
|
||||
price: '1.50',
|
||||
size: '1000',
|
||||
leverage: 10,
|
||||
reduceOnly: false,
|
||||
));
|
||||
|
||||
print('Position opened:');
|
||||
print(' Position ID: ${position.positionId}');
|
||||
print(' Size: ${position.size}');
|
||||
print(' Entry price: ${position.entryPrice}');
|
||||
print(' Leverage: ${position.leverage}x');
|
||||
print(' Liquidation price: ${position.liquidationPrice}');
|
||||
|
||||
// Get position details
|
||||
final details = await dex.perps.getPosition(position.positionId);
|
||||
print('\nPosition details:');
|
||||
print(' Unrealized PnL: ${details.unrealizedPnL}');
|
||||
print(' Margin: ${details.margin}');
|
||||
print(' Margin ratio: ${details.marginRatio}%');
|
||||
|
||||
// Set stop loss and take profit
|
||||
print('\nSetting stop loss and take profit...');
|
||||
await dex.perps.setStopLoss(position.positionId, '1.40');
|
||||
print('Stop loss set at 1.40');
|
||||
|
||||
await dex.perps.setTakeProfit(position.positionId, '1.80');
|
||||
print('Take profit set at 1.80');
|
||||
|
||||
// Close position
|
||||
print('\nClosing position...');
|
||||
final closeResult = await dex.perps.closePosition(position.positionId);
|
||||
print('Position closed:');
|
||||
print(' Realized PnL: ${closeResult.realizedPnL}');
|
||||
print(' Close price: ${closeResult.closePrice}');
|
||||
|
||||
// Get all positions
|
||||
final positions = await dex.perps.getPositions();
|
||||
print('\nOpen positions: ${positions.length}');
|
||||
|
||||
// Get funding history
|
||||
final funding = await dex.perps.getFundingHistory('SYN-USDC-PERP', limit: 10);
|
||||
print('Funding payments: ${funding.length}');
|
||||
|
||||
print('');
|
||||
}
|
||||
|
||||
Future<void> liquidityExample(SynorDex dex) async {
|
||||
print('=== Liquidity Provision ===');
|
||||
|
||||
// Get available pools
|
||||
final pools = await dex.liquidity.listPools();
|
||||
print('Available pools: ${pools.length}');
|
||||
|
||||
for (final pool in pools.take(3)) {
|
||||
print('\n ${pool.name}:');
|
||||
print(' TVL: \$${pool.tvl}');
|
||||
print(' APR: ${pool.apr}%');
|
||||
print(' Volume 24h: \$${pool.volume24h}');
|
||||
print(' Fee tier: ${pool.feeTier}%');
|
||||
}
|
||||
|
||||
// Get pool details
|
||||
final pool = await dex.liquidity.getPool('SYN-USDC');
|
||||
print('\nSYN-USDC pool details:');
|
||||
print(' Token0: ${pool.token0.symbol} (${pool.token0Reserve})');
|
||||
print(' Token1: ${pool.token1.symbol} (${pool.token1Reserve})');
|
||||
print(' Price: ${pool.price}');
|
||||
print(' Total LP tokens: ${pool.totalLPTokens}');
|
||||
|
||||
// Add liquidity
|
||||
print('\nAdding liquidity...');
|
||||
final addResult = await dex.liquidity.addLiquidity(AddLiquidityRequest(
|
||||
pool: 'SYN-USDC',
|
||||
amount0: '100',
|
||||
amount1: '150',
|
||||
slippageBps: 50, // 0.5%
|
||||
));
|
||||
|
||||
print('Liquidity added:');
|
||||
print(' LP tokens received: ${addResult.lpTokens}');
|
||||
print(' Position ID: ${addResult.positionId}');
|
||||
print(' Share of pool: ${addResult.shareOfPool}%');
|
||||
|
||||
// Get LP positions
|
||||
final lpPositions = await dex.liquidity.getPositions();
|
||||
print('\nLP positions: ${lpPositions.length}');
|
||||
for (final pos in lpPositions) {
|
||||
print(' ${pos.pool}: ${pos.lpTokens} LP tokens (value: \$${pos.value})');
|
||||
}
|
||||
|
||||
// Claim fees
|
||||
print('\nClaiming fees...');
|
||||
final fees = await dex.liquidity.claimFees(addResult.positionId);
|
||||
print('Fees claimed:');
|
||||
print(' Token0: ${fees.amount0}');
|
||||
print(' Token1: ${fees.amount1}');
|
||||
|
||||
// Remove liquidity
|
||||
print('\nRemoving liquidity...');
|
||||
final removeResult = await dex.liquidity.removeLiquidity(RemoveLiquidityRequest(
|
||||
positionId: addResult.positionId,
|
||||
lpTokens: addResult.lpTokens,
|
||||
slippageBps: 50,
|
||||
));
|
||||
|
||||
print('Liquidity removed:');
|
||||
print(' Token0 received: ${removeResult.amount0}');
|
||||
print(' Token1 received: ${removeResult.amount1}');
|
||||
|
||||
print('');
|
||||
}
|
||||
|
||||
Future<void> orderbookExample(SynorDex dex) async {
|
||||
print('=== Order Book ===');
|
||||
|
||||
// Get order book snapshot
|
||||
final orderbook = await dex.orderbook.getSnapshot('SYN-USDC', depth: 10);
|
||||
|
||||
print('Order book for SYN-USDC:');
|
||||
print('\nAsks (sells):');
|
||||
for (final ask in orderbook.asks.take(5)) {
|
||||
print(' ${ask.quantity} @ ${ask.price}');
|
||||
}
|
||||
|
||||
print('\nBids (buys):');
|
||||
for (final bid in orderbook.bids.take(5)) {
|
||||
print(' ${bid.quantity} @ ${bid.price}');
|
||||
}
|
||||
|
||||
print('\nSpread: ${orderbook.spread} (${orderbook.spreadPercent}%)');
|
||||
print('Mid price: ${orderbook.midPrice}');
|
||||
|
||||
// Get recent trades
|
||||
final recentTrades = await dex.orderbook.getRecentTrades('SYN-USDC', limit: 10);
|
||||
print('\nRecent trades:');
|
||||
for (final trade in recentTrades.take(5)) {
|
||||
print(' ${trade.side} ${trade.quantity} @ ${trade.price}');
|
||||
}
|
||||
|
||||
// Subscribe to orderbook updates (simulated)
|
||||
print('\nSubscribing to orderbook updates...');
|
||||
final subscription = dex.orderbook.subscribe('SYN-USDC');
|
||||
|
||||
// Process a few updates
|
||||
int count = 0;
|
||||
await for (final update in subscription) {
|
||||
print(' Update: ${update.side} ${update.quantity} @ ${update.price}');
|
||||
count++;
|
||||
if (count >= 3) break;
|
||||
}
|
||||
|
||||
print('');
|
||||
}
|
||||
|
||||
Future<void> portfolioExample(SynorDex dex) async {
|
||||
print('=== Portfolio ===');
|
||||
|
||||
// Get portfolio overview
|
||||
final portfolio = await dex.portfolio.getOverview();
|
||||
|
||||
print('Portfolio overview:');
|
||||
print(' Total value: \$${portfolio.totalValue}');
|
||||
print(' Available balance: \$${portfolio.availableBalance}');
|
||||
print(' In orders: \$${portfolio.inOrders}');
|
||||
print(' In positions: \$${portfolio.inPositions}');
|
||||
print(' Unrealized PnL: \$${portfolio.unrealizedPnL}');
|
||||
|
||||
// Get balances
|
||||
final balances = await dex.portfolio.getBalances();
|
||||
print('\nBalances:');
|
||||
for (final balance in balances) {
|
||||
print(' ${balance.asset}: ${balance.total} (available: ${balance.available}, in orders: ${balance.inOrders})');
|
||||
}
|
||||
|
||||
// Get PnL history
|
||||
final pnlHistory = await dex.portfolio.getPnLHistory(days: 30); // Last 30 days
|
||||
print('\nPnL history (last ${pnlHistory.length} days):');
|
||||
if (pnlHistory.isNotEmpty) {
|
||||
print(' Total PnL: \$${pnlHistory.last.cumulativePnL}');
|
||||
}
|
||||
|
||||
// Get trade statistics
|
||||
final stats = await dex.portfolio.getStats();
|
||||
print('\nTrade statistics:');
|
||||
print(' Total trades: ${stats.totalTrades}');
|
||||
print(' Win rate: ${stats.winRate}%');
|
||||
print(' Avg profit: \$${stats.avgProfit}');
|
||||
print(' Avg loss: \$${stats.avgLoss}');
|
||||
print(' Best trade: \$${stats.bestTrade}');
|
||||
print(' Worst trade: \$${stats.worstTrade}');
|
||||
|
||||
print('');
|
||||
}
|
||||
355
sdk/flutter/example/ibc_example.dart
Normal file
355
sdk/flutter/example/ibc_example.dart
Normal file
|
|
@ -0,0 +1,355 @@
|
|||
/// Synor IBC SDK Examples for Flutter/Dart
|
||||
///
|
||||
/// Demonstrates Inter-Blockchain Communication operations:
|
||||
/// - Cross-chain token transfers
|
||||
/// - Channel management
|
||||
/// - Packet handling
|
||||
/// - Relayer operations
|
||||
|
||||
import 'dart:io';
|
||||
import 'package:synor_ibc/synor_ibc.dart';
|
||||
|
||||
Future<void> main() async {
|
||||
// Initialize client
|
||||
final config = IbcConfig(
|
||||
apiKey: Platform.environment['SYNOR_API_KEY'] ?? 'your-api-key',
|
||||
endpoint: 'https://ibc.synor.io/v1',
|
||||
timeout: const Duration(seconds: 30),
|
||||
retries: 3,
|
||||
debug: false,
|
||||
defaultNetwork: Network.mainnet,
|
||||
);
|
||||
|
||||
final ibc = SynorIbc(config);
|
||||
|
||||
try {
|
||||
// Check service health
|
||||
final healthy = await ibc.healthCheck();
|
||||
print('Service healthy: $healthy\n');
|
||||
|
||||
// Run examples
|
||||
await chainsExample(ibc);
|
||||
await channelsExample(ibc);
|
||||
await transferExample(ibc);
|
||||
await packetExample(ibc);
|
||||
await relayerExample(ibc);
|
||||
await connectionExample(ibc);
|
||||
} finally {
|
||||
await ibc.close();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> chainsExample(SynorIbc ibc) async {
|
||||
print('=== Connected Chains ===');
|
||||
|
||||
// Get all connected chains
|
||||
final chains = await ibc.chains.list();
|
||||
print('Connected chains: ${chains.length}');
|
||||
|
||||
for (final chain in chains) {
|
||||
print(' ${chain.chainId}:');
|
||||
print(' Name: ${chain.name}');
|
||||
print(' Status: ${chain.status}');
|
||||
print(' Block height: ${chain.latestHeight}');
|
||||
print(' Channels: ${chain.channelCount}');
|
||||
}
|
||||
|
||||
// Get specific chain info
|
||||
final cosmos = await ibc.chains.get('cosmoshub-4');
|
||||
print('\nCosmos Hub details:');
|
||||
print(' RPC: ${cosmos.rpcEndpoint}');
|
||||
print(' Rest: ${cosmos.restEndpoint}');
|
||||
print(' Native denom: ${cosmos.nativeDenom}');
|
||||
print(' Prefix: ${cosmos.bech32Prefix}');
|
||||
|
||||
// Get supported assets on a chain
|
||||
final assets = await ibc.chains.getAssets('cosmoshub-4');
|
||||
print('\nSupported assets on Cosmos Hub:');
|
||||
for (final asset in assets.take(5)) {
|
||||
print(' ${asset.symbol}: ${asset.denom}');
|
||||
print(' Origin: ${asset.originChain}');
|
||||
print(' Decimals: ${asset.decimals}');
|
||||
}
|
||||
|
||||
// Get chain paths (routes)
|
||||
final paths = await ibc.chains.getPaths('synor-1', 'cosmoshub-4');
|
||||
print('\nPaths from Synor to Cosmos Hub:');
|
||||
for (final path in paths) {
|
||||
print(' ${path.sourceChannel} -> ${path.destChannel}');
|
||||
print(' Hops: ${path.hops}');
|
||||
print(' Avg time: ${path.avgTransferTime}s');
|
||||
}
|
||||
|
||||
print('');
|
||||
}
|
||||
|
||||
Future<void> channelsExample(SynorIbc ibc) async {
|
||||
print('=== Channel Management ===');
|
||||
|
||||
// List all channels
|
||||
final channels = await ibc.channels.list();
|
||||
print('Total channels: ${channels.length}');
|
||||
|
||||
// Filter by state
|
||||
final openChannels =
|
||||
channels.where((c) => c.state == ChannelState.open).toList();
|
||||
print('Open channels: ${openChannels.length}');
|
||||
|
||||
for (final channel in openChannels.take(3)) {
|
||||
print('\n Channel ${channel.channelId}:');
|
||||
print(' Port: ${channel.portId}');
|
||||
print(' Counterparty: ${channel.counterpartyChannelId} on ${channel.counterpartyChainId}');
|
||||
print(' Ordering: ${channel.ordering}');
|
||||
print(' Version: ${channel.version}');
|
||||
print(' State: ${channel.state}');
|
||||
}
|
||||
|
||||
// Get specific channel
|
||||
final channel = await ibc.channels.get('channel-0');
|
||||
print('\nChannel-0 details:');
|
||||
print(' Connection: ${channel.connectionId}');
|
||||
print(' Counterparty port: ${channel.counterpartyPortId}');
|
||||
|
||||
// Get channel statistics
|
||||
final stats = await ibc.channels.getStats('channel-0');
|
||||
print('\nChannel-0 statistics:');
|
||||
print(' Total packets sent: ${stats.packetsSent}');
|
||||
print(' Total packets received: ${stats.packetsReceived}');
|
||||
print(' Pending packets: ${stats.pendingPackets}');
|
||||
print(' Success rate: ${stats.successRate}%');
|
||||
print(' Avg relay time: ${stats.avgRelayTime}s');
|
||||
|
||||
// Get channel capacity
|
||||
final capacity = await ibc.channels.getCapacity('channel-0');
|
||||
print('\nChannel-0 capacity:');
|
||||
print(' Max throughput: ${capacity.maxPacketsPerBlock} packets/block');
|
||||
print(' Current utilization: ${capacity.utilization}%');
|
||||
|
||||
print('');
|
||||
}
|
||||
|
||||
Future<void> transferExample(SynorIbc ibc) async {
|
||||
print('=== Cross-Chain Transfers ===');
|
||||
|
||||
// Estimate transfer fee
|
||||
final estimate = await ibc.transfers.estimateFee(FeeEstimateRequest(
|
||||
sourceChain: 'synor-1',
|
||||
destChain: 'cosmoshub-4',
|
||||
denom: 'usyn',
|
||||
amount: '1000000', // 1 SYN (6 decimals)
|
||||
));
|
||||
|
||||
print('Transfer fee estimate:');
|
||||
print(' Gas: ${estimate.gas}');
|
||||
print(' Fee: ${estimate.fee} ${estimate.feeDenom}');
|
||||
print(' Timeout: ${estimate.timeout}s');
|
||||
|
||||
// Initiate a transfer
|
||||
print('\nInitiating transfer...');
|
||||
final transfer = await ibc.transfers.send(TransferRequest(
|
||||
sourceChain: 'synor-1',
|
||||
destChain: 'cosmoshub-4',
|
||||
channel: 'channel-0',
|
||||
sender: 'synor1abc...', // Your address
|
||||
receiver: 'cosmos1xyz...', // Recipient address
|
||||
denom: 'usyn',
|
||||
amount: '1000000', // 1 SYN
|
||||
memo: 'Cross-chain transfer example',
|
||||
timeoutHeight: 0, // Use timestamp instead
|
||||
timeoutTimestamp: DateTime.now().add(const Duration(minutes: 10)).millisecondsSinceEpoch,
|
||||
));
|
||||
|
||||
print('Transfer initiated:');
|
||||
print(' TX Hash: ${transfer.txHash}');
|
||||
print(' Sequence: ${transfer.sequence}');
|
||||
print(' Status: ${transfer.status}');
|
||||
|
||||
// Track transfer status
|
||||
print('\nTracking transfer...');
|
||||
final status = await ibc.transfers.getStatus(transfer.txHash);
|
||||
print('Current status: ${status.state}');
|
||||
print(' Source confirmed: ${status.sourceConfirmed}');
|
||||
print(' Relayed: ${status.relayed}');
|
||||
print(' Dest confirmed: ${status.destConfirmed}');
|
||||
|
||||
// Get transfer history
|
||||
final history = await ibc.transfers.getHistory('synor1abc...', limit: 5);
|
||||
print('\nTransfer history (last 5):');
|
||||
for (final tx in history) {
|
||||
final direction = tx.sender == 'synor1abc...' ? 'OUT' : 'IN';
|
||||
print(' $direction ${tx.amount} ${tx.denom} (${tx.status})');
|
||||
}
|
||||
|
||||
// Get pending transfers
|
||||
final pending = await ibc.transfers.getPending('synor1abc...');
|
||||
print('\nPending transfers: ${pending.length}');
|
||||
|
||||
print('');
|
||||
}
|
||||
|
||||
Future<void> packetExample(SynorIbc ibc) async {
|
||||
print('=== Packet Handling ===');
|
||||
|
||||
// Get pending packets
|
||||
final packets = await ibc.packets.getPending('channel-0');
|
||||
print('Pending packets on channel-0: ${packets.length}');
|
||||
|
||||
for (final packet in packets.take(3)) {
|
||||
print('\n Packet ${packet.sequence}:');
|
||||
print(' Source: ${packet.sourcePort}/${packet.sourceChannel}');
|
||||
print(' Dest: ${packet.destPort}/${packet.destChannel}');
|
||||
print(' State: ${packet.state}');
|
||||
print(' Data size: ${packet.data.length} bytes');
|
||||
print(' Timeout height: ${packet.timeoutHeight}');
|
||||
print(' Timeout timestamp: ${packet.timeoutTimestamp}');
|
||||
}
|
||||
|
||||
// Get packet by sequence
|
||||
final packet = await ibc.packets.get('channel-0', 1);
|
||||
print('\nPacket details:');
|
||||
print(' Commitment: ${packet.commitment}');
|
||||
print(' Receipt: ${packet.receipt}');
|
||||
print(' Acknowledgement: ${packet.acknowledgement}');
|
||||
|
||||
// Get packet receipts
|
||||
final receipts = await ibc.packets.getReceipts('channel-0', [1, 2, 3]);
|
||||
print('\nPacket receipts:');
|
||||
for (final entry in receipts.entries) {
|
||||
final status = entry.value ? 'received' : 'not received';
|
||||
print(' Sequence ${entry.key}: $status');
|
||||
}
|
||||
|
||||
// Get timed out packets
|
||||
final timedOut = await ibc.packets.getTimedOut('channel-0');
|
||||
print('\nTimed out packets: ${timedOut.length}');
|
||||
for (final p in timedOut) {
|
||||
print(' Sequence ${p.sequence}: timeout at ${p.timeoutTimestamp}');
|
||||
}
|
||||
|
||||
// Get unreceived packets
|
||||
final unreceived = await ibc.packets.getUnreceived('channel-0');
|
||||
final unreceivedStr = unreceived.isEmpty ? 'none' : unreceived.join(', ');
|
||||
print('\nUnreceived packet sequences: $unreceivedStr');
|
||||
|
||||
// Get unacknowledged packets
|
||||
final unacked = await ibc.packets.getUnacknowledged('channel-0');
|
||||
final unackedStr = unacked.isEmpty ? 'none' : unacked.join(', ');
|
||||
print('Unacknowledged packet sequences: $unackedStr');
|
||||
|
||||
print('');
|
||||
}
|
||||
|
||||
Future<void> relayerExample(SynorIbc ibc) async {
|
||||
print('=== Relayer Operations ===');
|
||||
|
||||
// Get active relayers
|
||||
final relayers = await ibc.relayers.list();
|
||||
print('Active relayers: ${relayers.length}');
|
||||
|
||||
for (final relayer in relayers.take(3)) {
|
||||
print('\n ${relayer.address}:');
|
||||
print(' Chains: ${relayer.chains.join(", ")}');
|
||||
print(' Packets relayed: ${relayer.packetsRelayed}');
|
||||
print(' Success rate: ${relayer.successRate}%');
|
||||
print(' Avg latency: ${relayer.avgLatency}ms');
|
||||
print(' Fee rate: ${relayer.feeRate}%');
|
||||
}
|
||||
|
||||
// Get relayer statistics
|
||||
final stats = await ibc.relayers.getStats();
|
||||
print('\nGlobal relayer statistics:');
|
||||
print(' Total relayers: ${stats.totalRelayers}');
|
||||
print(' Active relayers: ${stats.activeRelayers}');
|
||||
print(' Packets relayed (24h): ${stats.packetsRelayed24h}');
|
||||
print(' Total fees earned: ${stats.totalFeesEarned}');
|
||||
|
||||
// Register as a relayer
|
||||
print('\nRegistering as relayer...');
|
||||
final registration = await ibc.relayers.register(RelayerRegistration(
|
||||
chains: ['synor-1', 'cosmoshub-4'],
|
||||
feeRate: 0.1, // 0.1% fee
|
||||
minPacketSize: 0,
|
||||
maxPacketSize: 1000000,
|
||||
));
|
||||
print('Registered with address: ${registration.relayerAddress}');
|
||||
|
||||
// Start relaying (in background)
|
||||
print('\nStarting relay service...');
|
||||
final relaySession = await ibc.relayers.startRelay(RelayConfig(
|
||||
channels: ['channel-0'],
|
||||
autoAck: true,
|
||||
batchSize: 10,
|
||||
pollInterval: 5000,
|
||||
));
|
||||
print('Relay session started: ${relaySession.sessionId}');
|
||||
|
||||
// Get relay queue
|
||||
final queue = await ibc.relayers.getQueue('channel-0');
|
||||
print('\nRelay queue for channel-0: ${queue.length} packets');
|
||||
|
||||
// Manually relay a packet
|
||||
if (queue.isNotEmpty) {
|
||||
print('\nRelaying packet...');
|
||||
final relayResult = await ibc.relayers.relayPacket(queue.first.sequence, 'channel-0');
|
||||
print('Relay result: ${relayResult.status}');
|
||||
print(' TX Hash: ${relayResult.txHash}');
|
||||
print(' Fee earned: ${relayResult.feeEarned}');
|
||||
}
|
||||
|
||||
// Stop relay session
|
||||
await ibc.relayers.stopRelay(relaySession.sessionId);
|
||||
print('\nRelay session stopped');
|
||||
|
||||
print('');
|
||||
}
|
||||
|
||||
Future<void> connectionExample(SynorIbc ibc) async {
|
||||
print('=== Connection Information ===');
|
||||
|
||||
// List connections
|
||||
final connections = await ibc.connections.list();
|
||||
print('Total connections: ${connections.length}');
|
||||
|
||||
for (final conn in connections.take(3)) {
|
||||
print('\n ${conn.connectionId}:');
|
||||
print(' Client: ${conn.clientId}');
|
||||
print(' Counterparty: ${conn.counterpartyConnectionId}');
|
||||
print(' State: ${conn.state}');
|
||||
print(' Versions: ${conn.versions.join(", ")}');
|
||||
}
|
||||
|
||||
// Get connection details
|
||||
final connection = await ibc.connections.get('connection-0');
|
||||
print('\nConnection-0 details:');
|
||||
print(' Delay period: ${connection.delayPeriod}ns');
|
||||
print(' Counterparty client: ${connection.counterpartyClientId}');
|
||||
print(' Counterparty prefix: ${connection.counterpartyPrefix}');
|
||||
|
||||
// Get client state
|
||||
final client = await ibc.clients.get(connection.clientId);
|
||||
print('\nClient state:');
|
||||
print(' Chain ID: ${client.chainId}');
|
||||
print(' Trust level: ${client.trustLevel}');
|
||||
print(' Trusting period: ${client.trustingPeriod}');
|
||||
print(' Unbonding period: ${client.unbondingPeriod}');
|
||||
print(' Latest height: ${client.latestHeight}');
|
||||
print(' Frozen: ${client.frozen}');
|
||||
|
||||
// Get consensus state
|
||||
final consensus = await ibc.clients.getConsensusState(
|
||||
connection.clientId,
|
||||
client.latestHeight,
|
||||
);
|
||||
print('\nConsensus state at height ${client.latestHeight}:');
|
||||
print(' Timestamp: ${consensus.timestamp}');
|
||||
final rootPreview = consensus.root.length > 20
|
||||
? consensus.root.substring(0, 20)
|
||||
: consensus.root;
|
||||
print(' Root: $rootPreview...');
|
||||
final validatorsPreview = consensus.nextValidatorsHash.length > 20
|
||||
? consensus.nextValidatorsHash.substring(0, 20)
|
||||
: consensus.nextValidatorsHash;
|
||||
print(' Next validators hash: $validatorsPreview...');
|
||||
|
||||
print('');
|
||||
}
|
||||
504
sdk/flutter/example/zk_example.dart
Normal file
504
sdk/flutter/example/zk_example.dart
Normal file
|
|
@ -0,0 +1,504 @@
|
|||
/// Synor ZK SDK Examples for Flutter/Dart
|
||||
///
|
||||
/// Demonstrates Zero-Knowledge proof operations:
|
||||
/// - Circuit compilation
|
||||
/// - Proof generation and verification
|
||||
/// - Groth16, PLONK, and STARK proving systems
|
||||
/// - Recursive proofs
|
||||
/// - On-chain verification
|
||||
|
||||
import 'dart:io';
|
||||
import 'package:synor_zk/synor_zk.dart';
|
||||
|
||||
Future<void> main() async {
|
||||
// Initialize client
|
||||
final config = ZkConfig(
|
||||
apiKey: Platform.environment['SYNOR_API_KEY'] ?? 'your-api-key',
|
||||
endpoint: 'https://zk.synor.io/v1',
|
||||
timeout: const Duration(seconds: 120), // ZK ops can be slow
|
||||
retries: 3,
|
||||
debug: false,
|
||||
defaultProvingSystem: ProvingSystem.groth16,
|
||||
);
|
||||
|
||||
final zk = SynorZk(config);
|
||||
|
||||
try {
|
||||
// Check service health
|
||||
final healthy = await zk.healthCheck();
|
||||
print('Service healthy: $healthy\n');
|
||||
|
||||
// Run examples
|
||||
await circuitExample(zk);
|
||||
await proofExample(zk);
|
||||
await provingSystemsExample(zk);
|
||||
await recursiveProofExample(zk);
|
||||
await onChainVerificationExample(zk);
|
||||
await setupExample(zk);
|
||||
} finally {
|
||||
await zk.close();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> circuitExample(SynorZk zk) async {
|
||||
print('=== Circuit Compilation ===');
|
||||
|
||||
// Circom circuit example: prove knowledge of preimage
|
||||
const circomCircuit = '''
|
||||
pragma circom 2.1.0;
|
||||
|
||||
template HashPreimage() {
|
||||
signal input preimage;
|
||||
signal input hash;
|
||||
|
||||
// Simplified hash computation (in reality, use proper hash)
|
||||
signal preimageSquared;
|
||||
preimageSquared <== preimage * preimage;
|
||||
|
||||
// Constrain that hash matches
|
||||
hash === preimageSquared;
|
||||
}
|
||||
|
||||
component main {public [hash]} = HashPreimage();
|
||||
''';
|
||||
|
||||
// Compile circuit
|
||||
print('Compiling Circom circuit...');
|
||||
final compiled = await zk.circuits.compile(CompileRequest(
|
||||
code: circomCircuit,
|
||||
format: CircuitFormat.circom,
|
||||
name: 'hash_preimage',
|
||||
provingSystem: ProvingSystem.groth16,
|
||||
));
|
||||
|
||||
print('Circuit compiled:');
|
||||
print(' Circuit ID: ${compiled.circuitId}');
|
||||
print(' Constraints: ${compiled.constraintCount}');
|
||||
print(' Public inputs: ${compiled.publicInputCount}');
|
||||
print(' Private inputs: ${compiled.privateInputCount}');
|
||||
print(' Proving key size: ${compiled.provingKeySize} bytes');
|
||||
print(' Verification key size: ${compiled.verificationKeySize} bytes');
|
||||
|
||||
// List circuits
|
||||
final circuits = await zk.circuits.list();
|
||||
print('\nYour circuits: ${circuits.length}');
|
||||
for (final circuit in circuits) {
|
||||
print(' ${circuit.name} (${circuit.circuitId})');
|
||||
}
|
||||
|
||||
// Get circuit details
|
||||
final details = await zk.circuits.get(compiled.circuitId);
|
||||
print('\nCircuit details:');
|
||||
print(' Format: ${details.format}');
|
||||
print(' Proving system: ${details.provingSystem}');
|
||||
print(' Created: ${details.createdAt}');
|
||||
|
||||
// Download proving key
|
||||
final provingKey = await zk.circuits.getProvingKey(compiled.circuitId);
|
||||
print('\nProving key downloaded: ${provingKey.length} bytes');
|
||||
|
||||
// Download verification key
|
||||
final verificationKey = await zk.circuits.getVerificationKey(compiled.circuitId);
|
||||
print('Verification key downloaded: ${verificationKey.length} bytes');
|
||||
|
||||
print('');
|
||||
}
|
||||
|
||||
Future<void> proofExample(SynorZk zk) async {
|
||||
print('=== Proof Generation ===');
|
||||
|
||||
// First, compile a simple circuit
|
||||
const circuit = '''
|
||||
pragma circom 2.1.0;
|
||||
|
||||
template Multiplier() {
|
||||
signal input a;
|
||||
signal input b;
|
||||
signal output c;
|
||||
|
||||
c <== a * b;
|
||||
}
|
||||
|
||||
component main {public [c]} = Multiplier();
|
||||
''';
|
||||
|
||||
final compiled = await zk.circuits.compile(CompileRequest(
|
||||
code: circuit,
|
||||
format: CircuitFormat.circom,
|
||||
name: 'multiplier',
|
||||
provingSystem: ProvingSystem.groth16,
|
||||
));
|
||||
|
||||
// Generate proof
|
||||
print('Generating proof...');
|
||||
final startTime = DateTime.now();
|
||||
|
||||
final proof = await zk.proofs.generate(GenerateProofRequest(
|
||||
circuitId: compiled.circuitId,
|
||||
inputs: {'a': '3', 'b': '7'},
|
||||
));
|
||||
|
||||
final proofTime = DateTime.now().difference(startTime);
|
||||
print('Proof generated in ${proofTime.inMilliseconds}ms');
|
||||
print(' Proof ID: ${proof.proofId}');
|
||||
print(' Proof size: ${proof.proof.length} bytes');
|
||||
print(' Public signals: ${proof.publicSignals}');
|
||||
|
||||
// Verify proof
|
||||
print('\nVerifying proof...');
|
||||
final verifyStart = DateTime.now();
|
||||
|
||||
final isValid = await zk.proofs.verify(VerifyRequest(
|
||||
circuitId: compiled.circuitId,
|
||||
proof: proof.proof,
|
||||
publicSignals: proof.publicSignals,
|
||||
));
|
||||
|
||||
final verifyTime = DateTime.now().difference(verifyStart);
|
||||
print('Verification completed in ${verifyTime.inMilliseconds}ms');
|
||||
print(' Valid: $isValid');
|
||||
|
||||
// Verify with wrong public signals (should fail)
|
||||
print('\nVerifying with wrong signals...');
|
||||
final invalidResult = await zk.proofs.verify(VerifyRequest(
|
||||
circuitId: compiled.circuitId,
|
||||
proof: proof.proof,
|
||||
publicSignals: ['42'], // Wrong answer
|
||||
));
|
||||
print(' Valid: $invalidResult (expected false)');
|
||||
|
||||
// Get proof status
|
||||
final status = await zk.proofs.getStatus(proof.proofId);
|
||||
print('\nProof status:');
|
||||
print(' State: ${status.state}');
|
||||
print(' Verified: ${status.verified}');
|
||||
print(' Created: ${status.createdAt}');
|
||||
|
||||
// List proofs
|
||||
final proofs = await zk.proofs.list(compiled.circuitId);
|
||||
print('\nProofs for circuit: ${proofs.length}');
|
||||
|
||||
print('');
|
||||
}
|
||||
|
||||
Future<void> provingSystemsExample(SynorZk zk) async {
|
||||
print('=== Proving Systems Comparison ===');
|
||||
|
||||
// Simple circuit for comparison
|
||||
const circuit = '''
|
||||
pragma circom 2.1.0;
|
||||
|
||||
template Comparison() {
|
||||
signal input x;
|
||||
signal input y;
|
||||
signal output sum;
|
||||
|
||||
sum <== x + y;
|
||||
}
|
||||
|
||||
component main {public [sum]} = Comparison();
|
||||
''';
|
||||
|
||||
final systems = [
|
||||
(ProvingSystem.groth16, 'GROTH16'),
|
||||
(ProvingSystem.plonk, 'PLONK'),
|
||||
(ProvingSystem.stark, 'STARK'),
|
||||
];
|
||||
|
||||
print('Comparing proving systems:\n');
|
||||
|
||||
for (final (system, name) in systems) {
|
||||
print('$name:');
|
||||
|
||||
// Compile for this system
|
||||
final compiled = await zk.circuits.compile(CompileRequest(
|
||||
code: circuit,
|
||||
format: CircuitFormat.circom,
|
||||
name: 'comparison_${name.toLowerCase()}',
|
||||
provingSystem: system,
|
||||
));
|
||||
|
||||
// Generate proof
|
||||
final proofStart = DateTime.now();
|
||||
final proof = await zk.proofs.generate(GenerateProofRequest(
|
||||
circuitId: compiled.circuitId,
|
||||
inputs: {'x': '10', 'y': '20'},
|
||||
));
|
||||
final proofTime = DateTime.now().difference(proofStart);
|
||||
|
||||
// Verify proof
|
||||
final verifyStart = DateTime.now();
|
||||
await zk.proofs.verify(VerifyRequest(
|
||||
circuitId: compiled.circuitId,
|
||||
proof: proof.proof,
|
||||
publicSignals: proof.publicSignals,
|
||||
));
|
||||
final verifyTime = DateTime.now().difference(verifyStart);
|
||||
|
||||
print(' Setup: ${compiled.setupTime}ms');
|
||||
print(' Proof time: ${proofTime.inMilliseconds}ms');
|
||||
print(' Verify time: ${verifyTime.inMilliseconds}ms');
|
||||
print(' Proof size: ${proof.proof.length} bytes');
|
||||
print(' Verification key: ${compiled.verificationKeySize} bytes');
|
||||
print('');
|
||||
}
|
||||
|
||||
print('Summary:');
|
||||
print(' Groth16: Smallest proofs, fast verification, trusted setup required');
|
||||
print(' PLONK: Universal setup, flexible, moderate proof size');
|
||||
print(' STARK: No trusted setup, largest proofs, quantum resistant');
|
||||
|
||||
print('');
|
||||
}
|
||||
|
||||
Future<void> recursiveProofExample(SynorZk zk) async {
|
||||
print('=== Recursive Proofs ===');
|
||||
|
||||
// Inner circuit
|
||||
const innerCircuit = '''
|
||||
pragma circom 2.1.0;
|
||||
|
||||
template Inner() {
|
||||
signal input x;
|
||||
signal output y;
|
||||
y <== x * x;
|
||||
}
|
||||
|
||||
component main {public [y]} = Inner();
|
||||
''';
|
||||
|
||||
// Compile inner circuit
|
||||
final inner = await zk.circuits.compile(CompileRequest(
|
||||
code: innerCircuit,
|
||||
format: CircuitFormat.circom,
|
||||
name: 'inner_circuit',
|
||||
provingSystem: ProvingSystem.groth16,
|
||||
));
|
||||
|
||||
// Generate multiple proofs to aggregate
|
||||
print('Generating proofs to aggregate...');
|
||||
final proofsToAggregate = <ProofData>[];
|
||||
for (var i = 1; i <= 4; i++) {
|
||||
final proof = await zk.proofs.generate(GenerateProofRequest(
|
||||
circuitId: inner.circuitId,
|
||||
inputs: {'x': '$i'},
|
||||
));
|
||||
proofsToAggregate.add(ProofData(
|
||||
proof: proof.proof,
|
||||
publicSignals: proof.publicSignals,
|
||||
));
|
||||
print(' Proof $i: y = ${proof.publicSignals[0]}');
|
||||
}
|
||||
|
||||
// Aggregate proofs recursively
|
||||
print('\nAggregating proofs...');
|
||||
final aggregated = await zk.proofs.aggregate(AggregateRequest(
|
||||
circuitId: inner.circuitId,
|
||||
proofs: proofsToAggregate,
|
||||
aggregationType: 'recursive',
|
||||
));
|
||||
|
||||
final originalSize = proofsToAggregate.fold<int>(
|
||||
0,
|
||||
(sum, p) => sum + p.proof.length,
|
||||
);
|
||||
|
||||
print('Aggregated proof:');
|
||||
print(' Proof ID: ${aggregated.proofId}');
|
||||
print(' Aggregated count: ${aggregated.aggregatedCount}');
|
||||
print(' Proof size: ${aggregated.proof.length} bytes');
|
||||
print(' Size reduction: ${((1 - aggregated.proof.length / originalSize) * 100).toStringAsFixed(1)}%');
|
||||
|
||||
// Verify aggregated proof
|
||||
final isValid = await zk.proofs.verifyAggregated(VerifyAggregatedRequest(
|
||||
circuitId: inner.circuitId,
|
||||
proof: aggregated.proof,
|
||||
publicSignalsList: proofsToAggregate.map((p) => p.publicSignals).toList(),
|
||||
));
|
||||
print('\nAggregated proof valid: $isValid');
|
||||
|
||||
// Batch verification (verify multiple proofs in one operation)
|
||||
print('\nBatch verification...');
|
||||
final batchResult = await zk.proofs.batchVerify(BatchVerifyRequest(
|
||||
circuitId: inner.circuitId,
|
||||
proofs: proofsToAggregate,
|
||||
));
|
||||
print(' All valid: ${batchResult.allValid}');
|
||||
print(' Results: ${batchResult.results.join(", ")}');
|
||||
|
||||
print('');
|
||||
}
|
||||
|
||||
Future<void> onChainVerificationExample(SynorZk zk) async {
|
||||
print('=== On-Chain Verification ===');
|
||||
|
||||
// Compile circuit
|
||||
const circuit = '''
|
||||
pragma circom 2.1.0;
|
||||
|
||||
template VoteCommitment() {
|
||||
signal input vote; // Private: actual vote
|
||||
signal input nullifier; // Private: unique identifier
|
||||
signal input commitment; // Public: commitment to verify
|
||||
|
||||
// Simplified commitment (in practice, use Poseidon hash)
|
||||
signal computed;
|
||||
computed <== vote * nullifier;
|
||||
commitment === computed;
|
||||
}
|
||||
|
||||
component main {public [commitment]} = VoteCommitment();
|
||||
''';
|
||||
|
||||
final compiled = await zk.circuits.compile(CompileRequest(
|
||||
code: circuit,
|
||||
format: CircuitFormat.circom,
|
||||
name: 'vote_commitment',
|
||||
provingSystem: ProvingSystem.groth16,
|
||||
));
|
||||
|
||||
// Generate Solidity verifier
|
||||
print('Generating Solidity verifier...');
|
||||
final solidityVerifier = await zk.contracts.generateVerifier(GenerateVerifierRequest(
|
||||
circuitId: compiled.circuitId,
|
||||
language: 'solidity',
|
||||
optimized: true,
|
||||
));
|
||||
print('Solidity verifier generated: ${solidityVerifier.code.length} bytes');
|
||||
print(' Contract name: ${solidityVerifier.contractName}');
|
||||
print(' Gas estimate: ${solidityVerifier.gasEstimate}');
|
||||
|
||||
// Generate proof
|
||||
final proof = await zk.proofs.generate(GenerateProofRequest(
|
||||
circuitId: compiled.circuitId,
|
||||
inputs: {
|
||||
'vote': '1', // Vote YES (1) or NO (0)
|
||||
'nullifier': '12345',
|
||||
'commitment': '12345', // 1 * 12345
|
||||
},
|
||||
));
|
||||
|
||||
// Format proof for on-chain verification
|
||||
print('\nFormatting proof for on-chain...');
|
||||
final onChainProof = await zk.contracts.formatProof(FormatProofRequest(
|
||||
circuitId: compiled.circuitId,
|
||||
proof: proof.proof,
|
||||
publicSignals: proof.publicSignals,
|
||||
format: 'calldata',
|
||||
));
|
||||
final calldataPreview = onChainProof.calldata.length > 100
|
||||
? onChainProof.calldata.substring(0, 100)
|
||||
: onChainProof.calldata;
|
||||
print(' Calldata: $calldataPreview...');
|
||||
print(' Estimated gas: ${onChainProof.gasEstimate}');
|
||||
|
||||
// Deploy verifier contract (simulation)
|
||||
print('\nDeploying verifier contract...');
|
||||
final deployment = await zk.contracts.deployVerifier(DeployRequest(
|
||||
circuitId: compiled.circuitId,
|
||||
network: 'synor-testnet',
|
||||
));
|
||||
print(' Contract address: ${deployment.address}');
|
||||
print(' TX hash: ${deployment.txHash}');
|
||||
print(' Gas used: ${deployment.gasUsed}');
|
||||
|
||||
// Verify on-chain
|
||||
print('\nVerifying on-chain...');
|
||||
final onChainResult = await zk.contracts.verifyOnChain(OnChainVerifyRequest(
|
||||
contractAddress: deployment.address,
|
||||
proof: proof.proof,
|
||||
publicSignals: proof.publicSignals,
|
||||
network: 'synor-testnet',
|
||||
));
|
||||
print(' TX hash: ${onChainResult.txHash}');
|
||||
print(' Verified: ${onChainResult.verified}');
|
||||
print(' Gas used: ${onChainResult.gasUsed}');
|
||||
|
||||
// Generate verifier for other targets
|
||||
print('\nGenerating verifiers for other targets:');
|
||||
final targets = ['cairo', 'noir', 'ink'];
|
||||
for (final target in targets) {
|
||||
final verifier = await zk.contracts.generateVerifier(GenerateVerifierRequest(
|
||||
circuitId: compiled.circuitId,
|
||||
language: target,
|
||||
));
|
||||
print(' $target: ${verifier.code.length} bytes');
|
||||
}
|
||||
|
||||
print('');
|
||||
}
|
||||
|
||||
Future<void> setupExample(SynorZk zk) async {
|
||||
print('=== Trusted Setup ===');
|
||||
|
||||
// Get available ceremonies
|
||||
final ceremonies = await zk.setup.listCeremonies();
|
||||
print('Active ceremonies: ${ceremonies.length}');
|
||||
for (final ceremony in ceremonies) {
|
||||
print(' ${ceremony.name}:');
|
||||
print(' Status: ${ceremony.status}');
|
||||
print(' Participants: ${ceremony.participantCount}');
|
||||
print(' Current round: ${ceremony.currentRound}');
|
||||
}
|
||||
|
||||
// Create a new circuit setup
|
||||
const circuit = '''
|
||||
pragma circom 2.1.0;
|
||||
|
||||
template NewCircuit() {
|
||||
signal input a;
|
||||
signal output b;
|
||||
b <== a + 1;
|
||||
}
|
||||
|
||||
component main {public [b]} = NewCircuit();
|
||||
''';
|
||||
|
||||
print('\nInitializing setup for new circuit...');
|
||||
final setup = await zk.setup.initialize(SetupInitRequest(
|
||||
circuit: circuit,
|
||||
format: CircuitFormat.circom,
|
||||
name: 'new_circuit_setup',
|
||||
provingSystem: ProvingSystem.groth16,
|
||||
ceremonyType: 'powers_of_tau', // or 'phase2'
|
||||
));
|
||||
print('Setup initialized:');
|
||||
print(' Ceremony ID: ${setup.ceremonyId}');
|
||||
print(' Powers of Tau required: ${setup.powersRequired}');
|
||||
print(' Current phase: ${setup.phase}');
|
||||
|
||||
// Contribute to ceremony (in practice, generates random entropy)
|
||||
print('\nContributing to ceremony...');
|
||||
final contribution = await zk.setup.contribute(ContributeRequest(
|
||||
ceremonyId: setup.ceremonyId,
|
||||
entropy: 'random-entropy-from-user'.codeUnits.map((b) => b.toRadixString(16).padLeft(2, '0')).join(),
|
||||
));
|
||||
print('Contribution submitted:');
|
||||
print(' Participant: ${contribution.participantId}');
|
||||
print(' Contribution hash: ${contribution.hash}');
|
||||
print(' Verification status: ${contribution.verified}');
|
||||
|
||||
// Get ceremony status
|
||||
final status = await zk.setup.getStatus(setup.ceremonyId);
|
||||
print('\nCeremony status:');
|
||||
print(' Phase: ${status.phase}');
|
||||
print(' Total contributions: ${status.totalContributions}');
|
||||
print(' Verified contributions: ${status.verifiedContributions}');
|
||||
print(' Ready for finalization: ${status.readyForFinalization}');
|
||||
|
||||
// Finalize setup (when enough contributions)
|
||||
if (status.readyForFinalization) {
|
||||
print('\nFinalizing setup...');
|
||||
final finalized = await zk.setup.finalize(setup.ceremonyId);
|
||||
print('Setup finalized:');
|
||||
print(' Proving key hash: ${finalized.provingKeyHash}');
|
||||
print(' Verification key hash: ${finalized.verificationKeyHash}');
|
||||
print(' Contribution transcript: ${finalized.transcriptCid}');
|
||||
}
|
||||
|
||||
// Download ceremony transcript
|
||||
final transcript = await zk.setup.getTranscript(setup.ceremonyId);
|
||||
print('\nCeremony transcript: ${transcript.length} bytes');
|
||||
|
||||
print('');
|
||||
}
|
||||
465
sdk/go/examples/compiler_example.go
Normal file
465
sdk/go/examples/compiler_example.go
Normal file
|
|
@ -0,0 +1,465 @@
|
|||
// Package main demonstrates the Synor Compiler SDK for Go
|
||||
//
|
||||
// This example covers smart contract compilation and analysis:
|
||||
// - WASM contract compilation and optimization
|
||||
// - ABI extraction and encoding
|
||||
// - Contract analysis and security scanning
|
||||
// - Validation and verification
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/synor/sdk-go/compiler"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Initialize client
|
||||
config := compiler.Config{
|
||||
APIKey: getEnv("SYNOR_API_KEY", "your-api-key"),
|
||||
Endpoint: "https://compiler.synor.io/v1",
|
||||
Timeout: 60 * time.Second,
|
||||
Retries: 3,
|
||||
Debug: false,
|
||||
DefaultOptimizationLevel: compiler.OptimizationSize,
|
||||
MaxContractSize: 256 * 1024,
|
||||
UseWasmOpt: true,
|
||||
Validate: true,
|
||||
ExtractMetadata: true,
|
||||
GenerateABI: true,
|
||||
}
|
||||
|
||||
client, err := compiler.NewClient(config)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to create client: %v", err)
|
||||
}
|
||||
defer client.Close()
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
// Check service health
|
||||
healthy, err := client.HealthCheck(ctx)
|
||||
if err != nil {
|
||||
log.Printf("Health check failed: %v", err)
|
||||
} else {
|
||||
fmt.Printf("Service healthy: %v\n\n", healthy)
|
||||
}
|
||||
|
||||
// Run examples
|
||||
compileContractExample(ctx, client)
|
||||
compilationModesExample(ctx, client)
|
||||
abiExample(ctx, client)
|
||||
analysisExample(ctx, client)
|
||||
validationExample(ctx, client)
|
||||
securityExample(ctx, client)
|
||||
}
|
||||
|
||||
// createMinimalWasm creates a minimal valid WASM module for testing.
|
||||
func createMinimalWasm() []byte {
|
||||
return []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,
|
||||
}
|
||||
}
|
||||
|
||||
func compileContractExample(ctx context.Context, client *compiler.Client) {
|
||||
fmt.Println("=== Contract Compilation ===")
|
||||
|
||||
wasm := createMinimalWasm()
|
||||
|
||||
result, err := client.Compile(ctx, wasm, &compiler.CompileOptions{
|
||||
OptimizationLevel: compiler.OptimizationSize,
|
||||
UseWasmOpt: true,
|
||||
Validate: true,
|
||||
ExtractMetadata: true,
|
||||
GenerateABI: true,
|
||||
StripOptions: &compiler.StripOptions{
|
||||
StripDebug: true,
|
||||
StripProducers: true,
|
||||
StripNames: true,
|
||||
StripCustom: true,
|
||||
StripUnused: true,
|
||||
PreserveSections: []string{},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("Failed to compile contract: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println("Compilation result:")
|
||||
fmt.Printf(" Contract ID: %s\n", result.ContractID)
|
||||
fmt.Printf(" Code hash: %s\n", result.CodeHash)
|
||||
fmt.Printf(" Original size: %d bytes\n", result.OriginalSize)
|
||||
fmt.Printf(" Optimized size: %d bytes\n", result.OptimizedSize)
|
||||
fmt.Printf(" Size reduction: %.1f%%\n", result.SizeReduction)
|
||||
fmt.Printf(" Estimated deploy gas: %d\n", result.EstimatedDeployGas)
|
||||
|
||||
if result.Metadata != nil {
|
||||
fmt.Println("\nMetadata:")
|
||||
fmt.Printf(" Name: %s\n", result.Metadata.Name)
|
||||
fmt.Printf(" Version: %s\n", result.Metadata.Version)
|
||||
fmt.Printf(" SDK Version: %s\n", result.Metadata.SDKVersion)
|
||||
}
|
||||
|
||||
if result.ABI != nil {
|
||||
fmt.Println("\nABI:")
|
||||
fmt.Printf(" Functions: %d\n", len(result.ABI.Functions))
|
||||
fmt.Printf(" Events: %d\n", len(result.ABI.Events))
|
||||
fmt.Printf(" Errors: %d\n", len(result.ABI.Errors))
|
||||
}
|
||||
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
func compilationModesExample(ctx context.Context, client *compiler.Client) {
|
||||
fmt.Println("=== Compilation Modes ===")
|
||||
|
||||
wasm := createMinimalWasm()
|
||||
|
||||
// Development mode: fast compilation, debugging support
|
||||
fmt.Println("Development mode:")
|
||||
devResult, err := client.Contracts.CompileDev(ctx, wasm)
|
||||
if err != nil {
|
||||
log.Printf("Failed to compile in dev mode: %v", err)
|
||||
return
|
||||
}
|
||||
fmt.Printf(" Size: %d bytes\n", devResult.OptimizedSize)
|
||||
fmt.Println(" Optimization: none")
|
||||
|
||||
// Production mode: maximum optimization
|
||||
fmt.Println("\nProduction mode:")
|
||||
prodResult, err := client.Contracts.CompileProduction(ctx, wasm)
|
||||
if err != nil {
|
||||
log.Printf("Failed to compile in production mode: %v", err)
|
||||
return
|
||||
}
|
||||
fmt.Printf(" Size: %d bytes\n", prodResult.OptimizedSize)
|
||||
fmt.Println(" Optimization: aggressive")
|
||||
fmt.Printf(" Size savings: %d bytes\n", devResult.OptimizedSize-prodResult.OptimizedSize)
|
||||
|
||||
// Custom optimization levels
|
||||
fmt.Println("\nOptimization levels:")
|
||||
levels := []compiler.OptimizationLevel{
|
||||
compiler.OptimizationNone,
|
||||
compiler.OptimizationBasic,
|
||||
compiler.OptimizationSize,
|
||||
compiler.OptimizationAggressive,
|
||||
}
|
||||
|
||||
for _, level := range levels {
|
||||
result, err := client.Compile(ctx, wasm, &compiler.CompileOptions{
|
||||
OptimizationLevel: level,
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("Failed to compile with %s: %v", level, err)
|
||||
continue
|
||||
}
|
||||
fmt.Printf(" %s: %d bytes\n", level, result.OptimizedSize)
|
||||
}
|
||||
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
func abiExample(ctx context.Context, client *compiler.Client) {
|
||||
fmt.Println("=== ABI Operations ===")
|
||||
|
||||
wasm := createMinimalWasm()
|
||||
|
||||
// Extract ABI from WASM
|
||||
abi, err := client.ABI.Extract(ctx, wasm)
|
||||
if err != nil {
|
||||
log.Printf("Failed to extract ABI: %v", err)
|
||||
return
|
||||
}
|
||||
fmt.Printf("Contract: %s\n", abi.Name)
|
||||
fmt.Printf("Version: %s\n", abi.Version)
|
||||
|
||||
// List functions
|
||||
if len(abi.Functions) > 0 {
|
||||
fmt.Println("\nFunctions:")
|
||||
for _, fn := range abi.Functions {
|
||||
inputs := ""
|
||||
for i, input := range fn.Inputs {
|
||||
if i > 0 {
|
||||
inputs += ", "
|
||||
}
|
||||
inputs += fmt.Sprintf("%s: %s", input.Name, input.Type.TypeName)
|
||||
}
|
||||
|
||||
outputs := "void"
|
||||
if len(fn.Outputs) > 0 {
|
||||
outputTypes := make([]string, len(fn.Outputs))
|
||||
for i, output := range fn.Outputs {
|
||||
outputTypes[i] = output.Type.TypeName
|
||||
}
|
||||
outputs = fmt.Sprintf("%v", outputTypes)
|
||||
}
|
||||
|
||||
modifiers := ""
|
||||
if fn.View {
|
||||
modifiers += "view "
|
||||
}
|
||||
if fn.Payable {
|
||||
modifiers += "payable"
|
||||
}
|
||||
|
||||
fmt.Printf(" %s(%s) -> %s %s\n", fn.Name, inputs, outputs, modifiers)
|
||||
fmt.Printf(" Selector: %s\n", fn.Selector)
|
||||
}
|
||||
}
|
||||
|
||||
// List events
|
||||
if len(abi.Events) > 0 {
|
||||
fmt.Println("\nEvents:")
|
||||
for _, event := range abi.Events {
|
||||
params := ""
|
||||
for i, param := range event.Params {
|
||||
if i > 0 {
|
||||
params += ", "
|
||||
}
|
||||
indexed := ""
|
||||
if param.Indexed {
|
||||
indexed = "indexed "
|
||||
}
|
||||
params += fmt.Sprintf("%s%s: %s", indexed, param.Name, param.Type.TypeName)
|
||||
}
|
||||
fmt.Printf(" %s(%s)\n", event.Name, params)
|
||||
fmt.Printf(" Topic: %s\n", event.Topic)
|
||||
}
|
||||
}
|
||||
|
||||
// Encode a function call
|
||||
if len(abi.Functions) > 0 {
|
||||
fn := abi.Functions[0]
|
||||
encoded, err := client.ABI.EncodeCall(ctx, fn, []interface{}{"arg1", "arg2"})
|
||||
if err != nil {
|
||||
log.Printf("Failed to encode call: %v", err)
|
||||
} else {
|
||||
fmt.Printf("\nEncoded call to %s: %s\n", fn.Name, encoded)
|
||||
}
|
||||
|
||||
// Decode a result
|
||||
decoded, err := client.ABI.DecodeResult(ctx, fn, encoded)
|
||||
if err != nil {
|
||||
log.Printf("Failed to decode result: %v", err)
|
||||
} else {
|
||||
fmt.Printf("Decoded result: %v\n", decoded)
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
func analysisExample(ctx context.Context, client *compiler.Client) {
|
||||
fmt.Println("=== Contract Analysis ===")
|
||||
|
||||
wasm := createMinimalWasm()
|
||||
|
||||
// Full analysis
|
||||
analysis, err := client.Analysis.Analyze(ctx, wasm)
|
||||
if err != nil {
|
||||
log.Printf("Failed to analyze contract: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
// Size breakdown
|
||||
if analysis.SizeBreakdown != nil {
|
||||
fmt.Println("Size breakdown:")
|
||||
fmt.Printf(" Code: %d bytes\n", analysis.SizeBreakdown.Code)
|
||||
fmt.Printf(" Data: %d bytes\n", analysis.SizeBreakdown.Data)
|
||||
fmt.Printf(" Functions: %d bytes\n", analysis.SizeBreakdown.Functions)
|
||||
fmt.Printf(" Memory: %d bytes\n", analysis.SizeBreakdown.Memory)
|
||||
fmt.Printf(" Exports: %d bytes\n", analysis.SizeBreakdown.Exports)
|
||||
fmt.Printf(" Imports: %d bytes\n", analysis.SizeBreakdown.Imports)
|
||||
fmt.Printf(" Total: %d bytes\n", analysis.SizeBreakdown.Total)
|
||||
}
|
||||
|
||||
// Function analysis
|
||||
if len(analysis.Functions) > 0 {
|
||||
fmt.Println("\nFunction analysis:")
|
||||
limit := 5
|
||||
if len(analysis.Functions) < limit {
|
||||
limit = len(analysis.Functions)
|
||||
}
|
||||
for _, fn := range analysis.Functions[:limit] {
|
||||
fmt.Printf(" %s:\n", fn.Name)
|
||||
fmt.Printf(" Size: %d bytes\n", fn.Size)
|
||||
fmt.Printf(" Instructions: %d\n", fn.InstructionCount)
|
||||
fmt.Printf(" Locals: %d\n", fn.LocalCount)
|
||||
fmt.Printf(" Exported: %v\n", fn.Exported)
|
||||
fmt.Printf(" Estimated gas: %d\n", fn.EstimatedGas)
|
||||
}
|
||||
}
|
||||
|
||||
// Import analysis
|
||||
if len(analysis.Imports) > 0 {
|
||||
fmt.Println("\nImports:")
|
||||
for _, imp := range analysis.Imports {
|
||||
fmt.Printf(" %s.%s (%s)\n", imp.Module, imp.Name, imp.Kind)
|
||||
}
|
||||
}
|
||||
|
||||
// Gas analysis
|
||||
if analysis.GasAnalysis != nil {
|
||||
fmt.Println("\nGas analysis:")
|
||||
fmt.Printf(" Deployment: %d\n", analysis.GasAnalysis.DeploymentGas)
|
||||
fmt.Printf(" Memory init: %d\n", analysis.GasAnalysis.MemoryInitGas)
|
||||
fmt.Printf(" Data section: %d\n", analysis.GasAnalysis.DataSectionGas)
|
||||
}
|
||||
|
||||
// Extract metadata
|
||||
metadata, err := client.Analysis.ExtractMetadata(ctx, wasm)
|
||||
if err != nil {
|
||||
log.Printf("Failed to extract metadata: %v", err)
|
||||
} else {
|
||||
fmt.Println("\nContract metadata:")
|
||||
fmt.Printf(" Name: %s\n", metadata.Name)
|
||||
fmt.Printf(" Version: %s\n", metadata.Version)
|
||||
fmt.Printf(" Build timestamp: %s\n", metadata.BuildTimestamp)
|
||||
}
|
||||
|
||||
// Estimate deployment gas
|
||||
gas, err := client.Analysis.EstimateDeployGas(ctx, wasm)
|
||||
if err != nil {
|
||||
log.Printf("Failed to estimate deploy gas: %v", err)
|
||||
} else {
|
||||
fmt.Printf("\nEstimated deployment gas: %d\n", gas)
|
||||
}
|
||||
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
func validationExample(ctx context.Context, client *compiler.Client) {
|
||||
fmt.Println("=== Contract Validation ===")
|
||||
|
||||
wasm := createMinimalWasm()
|
||||
|
||||
// Full validation
|
||||
result, err := client.Validation.Validate(ctx, wasm)
|
||||
if err != nil {
|
||||
log.Printf("Failed to validate contract: %v", err)
|
||||
return
|
||||
}
|
||||
fmt.Printf("Valid: %v\n", result.Valid)
|
||||
fmt.Printf("Exports: %d\n", result.ExportCount)
|
||||
fmt.Printf("Imports: %d\n", result.ImportCount)
|
||||
fmt.Printf("Functions: %d\n", result.FunctionCount)
|
||||
fmt.Printf("Memory pages: %d\n", result.MemoryPages)
|
||||
|
||||
if len(result.Errors) > 0 {
|
||||
fmt.Println("\nValidation errors:")
|
||||
for _, e := range result.Errors {
|
||||
fmt.Printf(" [%s] %s\n", e.Code, e.Message)
|
||||
if e.Location != "" {
|
||||
fmt.Printf(" at %s\n", e.Location)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(result.Warnings) > 0 {
|
||||
fmt.Println("\nWarnings:")
|
||||
for _, warning := range result.Warnings {
|
||||
fmt.Printf(" %s\n", warning)
|
||||
}
|
||||
}
|
||||
|
||||
// Quick validation
|
||||
isValid, err := client.Validation.IsValid(ctx, wasm)
|
||||
if err != nil {
|
||||
log.Printf("Failed quick validation: %v", err)
|
||||
} else {
|
||||
fmt.Printf("\nQuick validation: %v\n", isValid)
|
||||
}
|
||||
|
||||
// Get validation errors only
|
||||
errors, err := client.Validation.GetErrors(ctx, wasm)
|
||||
if err != nil {
|
||||
log.Printf("Failed to get validation errors: %v", err)
|
||||
} else {
|
||||
fmt.Printf("Error count: %d\n", len(errors))
|
||||
}
|
||||
|
||||
// Validate required exports
|
||||
hasRequired, err := client.Validation.ValidateExports(ctx, wasm, []string{"init", "execute", "query"})
|
||||
if err != nil {
|
||||
log.Printf("Failed to validate exports: %v", err)
|
||||
} else {
|
||||
fmt.Printf("Has required exports: %v\n", hasRequired)
|
||||
}
|
||||
|
||||
// Validate memory constraints
|
||||
memoryValid, err := client.Validation.ValidateMemory(ctx, wasm, 16)
|
||||
if err != nil {
|
||||
log.Printf("Failed to validate memory: %v", err)
|
||||
} else {
|
||||
fmt.Printf("Memory within 16 pages: %v\n", memoryValid)
|
||||
}
|
||||
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
func securityExample(ctx context.Context, client *compiler.Client) {
|
||||
fmt.Println("=== Security Scanning ===")
|
||||
|
||||
wasm := createMinimalWasm()
|
||||
|
||||
security, err := client.Analysis.SecurityScan(ctx, wasm)
|
||||
if err != nil {
|
||||
log.Printf("Failed to perform security scan: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Printf("Security score: %d/100\n", security.Score)
|
||||
|
||||
if len(security.Issues) > 0 {
|
||||
fmt.Println("\nSecurity issues:")
|
||||
severityIcons := map[string]string{
|
||||
"critical": "[CRIT]",
|
||||
"high": "[HIGH]",
|
||||
"medium": "[MED]",
|
||||
"low": "[LOW]",
|
||||
}
|
||||
for _, issue := range security.Issues {
|
||||
icon := severityIcons[issue.Severity]
|
||||
if icon == "" {
|
||||
icon = "[???]"
|
||||
}
|
||||
fmt.Printf("%s [%s] %s\n", icon, issue.Severity, issue.Type)
|
||||
fmt.Printf(" %s\n", issue.Description)
|
||||
if issue.Location != "" {
|
||||
fmt.Printf(" at %s\n", issue.Location)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
fmt.Println("No security issues found!")
|
||||
}
|
||||
|
||||
if len(security.Recommendations) > 0 {
|
||||
fmt.Println("\nRecommendations:")
|
||||
for _, rec := range security.Recommendations {
|
||||
fmt.Printf(" * %s\n", rec)
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
func getEnv(key, defaultValue string) string {
|
||||
if value := os.Getenv(key); value != "" {
|
||||
return value
|
||||
}
|
||||
return defaultValue
|
||||
}
|
||||
344
sdk/go/examples/crypto_example.go
Normal file
344
sdk/go/examples/crypto_example.go
Normal file
|
|
@ -0,0 +1,344 @@
|
|||
// Package main demonstrates the Synor Crypto SDK for Go
|
||||
//
|
||||
// This example covers quantum-resistant cryptographic operations:
|
||||
// - Hybrid Ed25519 + Dilithium3 signatures
|
||||
// - BIP-39 mnemonic generation and validation
|
||||
// - Post-quantum algorithms (Falcon, SPHINCS+)
|
||||
// - Key derivation functions
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/synor/sdk-go/crypto"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Initialize client
|
||||
config := crypto.Config{
|
||||
APIKey: getEnv("SYNOR_API_KEY", "your-api-key"),
|
||||
Endpoint: "https://crypto.synor.io/v1",
|
||||
Timeout: 30 * time.Second,
|
||||
Retries: 3,
|
||||
Debug: false,
|
||||
DefaultNetwork: crypto.NetworkMainnet,
|
||||
}
|
||||
|
||||
client, err := crypto.NewClient(config)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to create client: %v", err)
|
||||
}
|
||||
defer client.Close()
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
// Check service health
|
||||
healthy, err := client.HealthCheck(ctx)
|
||||
if err != nil {
|
||||
log.Printf("Health check failed: %v", err)
|
||||
} else {
|
||||
fmt.Printf("Service healthy: %v\n\n", healthy)
|
||||
}
|
||||
|
||||
// Run examples
|
||||
mnemonicExample(ctx, client)
|
||||
keypairExample(ctx, client)
|
||||
signingExample(ctx, client)
|
||||
falconExample(ctx, client)
|
||||
sphincsExample(ctx, client)
|
||||
kdfExample(ctx, client)
|
||||
hashExample(ctx, client)
|
||||
}
|
||||
|
||||
func mnemonicExample(ctx context.Context, client *crypto.Client) {
|
||||
fmt.Println("=== Mnemonic Operations ===")
|
||||
|
||||
// Generate a 24-word mnemonic (256-bit entropy)
|
||||
mnemonic, err := client.Mnemonic.Generate(ctx, 24)
|
||||
if err != nil {
|
||||
log.Printf("Failed to generate mnemonic: %v", err)
|
||||
return
|
||||
}
|
||||
fmt.Printf("Generated mnemonic: %s\n", mnemonic.Phrase)
|
||||
fmt.Printf("Word count: %d\n", mnemonic.WordCount)
|
||||
|
||||
// Validate a mnemonic
|
||||
validation, err := client.Mnemonic.Validate(ctx, mnemonic.Phrase)
|
||||
if err != nil {
|
||||
log.Printf("Failed to validate mnemonic: %v", err)
|
||||
return
|
||||
}
|
||||
fmt.Printf("Valid: %v\n", validation.Valid)
|
||||
if !validation.Valid {
|
||||
fmt.Printf("Error: %s\n", validation.Error)
|
||||
}
|
||||
|
||||
// Convert mnemonic to seed
|
||||
seed, err := client.Mnemonic.ToSeed(ctx, mnemonic.Phrase, "optional-passphrase")
|
||||
if err != nil {
|
||||
log.Printf("Failed to convert to seed: %v", err)
|
||||
return
|
||||
}
|
||||
fmt.Printf("Seed (hex): %s...\n", fmt.Sprintf("%x", seed)[:32])
|
||||
|
||||
// Word suggestions for autocomplete
|
||||
suggestions, err := client.Mnemonic.SuggestWords(ctx, "aban", 5)
|
||||
if err != nil {
|
||||
log.Printf("Failed to get suggestions: %v", err)
|
||||
return
|
||||
}
|
||||
fmt.Printf("Suggestions for 'aban': %v\n", suggestions)
|
||||
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
func keypairExample(ctx context.Context, client *crypto.Client) {
|
||||
fmt.Println("=== Keypair Operations ===")
|
||||
|
||||
// Generate a random keypair
|
||||
keypair, err := client.Keypairs.Generate(ctx)
|
||||
if err != nil {
|
||||
log.Printf("Failed to generate keypair: %v", err)
|
||||
return
|
||||
}
|
||||
fmt.Println("Generated hybrid keypair:")
|
||||
fmt.Printf(" Ed25519 public key size: %d bytes\n", len(keypair.PublicKey.Ed25519Bytes))
|
||||
fmt.Printf(" Dilithium public key size: %d bytes\n", len(keypair.PublicKey.DilithiumBytes))
|
||||
fmt.Printf(" Total public key size: %d bytes\n", keypair.PublicKey.Size)
|
||||
|
||||
// Get addresses for different networks
|
||||
fmt.Println("\nAddresses:")
|
||||
fmt.Printf(" Mainnet: %s\n", keypair.GetAddress(crypto.NetworkMainnet))
|
||||
fmt.Printf(" Testnet: %s\n", keypair.GetAddress(crypto.NetworkTestnet))
|
||||
fmt.Printf(" Devnet: %s\n", keypair.GetAddress(crypto.NetworkDevnet))
|
||||
|
||||
// Create keypair from mnemonic (deterministic)
|
||||
mnemonic, err := client.Mnemonic.Generate(ctx, 24)
|
||||
if err != nil {
|
||||
log.Printf("Failed to generate mnemonic: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
keypair2, err := client.Keypairs.FromMnemonic(ctx, mnemonic.Phrase, "")
|
||||
if err != nil {
|
||||
log.Printf("Failed to create keypair from mnemonic: %v", err)
|
||||
return
|
||||
}
|
||||
addr := keypair2.GetAddress(crypto.NetworkMainnet)
|
||||
fmt.Printf("\nKeypair from mnemonic: %s...\n", addr[:20])
|
||||
|
||||
// Derive child keypair using BIP-44 path
|
||||
path := crypto.DerivationPathExternal(0, 0) // m/44'/21337'/0'/0/0
|
||||
fmt.Printf("Derivation path: %s\n", path)
|
||||
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
func signingExample(ctx context.Context, client *crypto.Client) {
|
||||
fmt.Println("=== Hybrid Signing ===")
|
||||
|
||||
// Generate keypair
|
||||
keypair, err := client.Keypairs.Generate(ctx)
|
||||
if err != nil {
|
||||
log.Printf("Failed to generate keypair: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
// Sign a message
|
||||
message := []byte("Hello, quantum-resistant world!")
|
||||
signature, err := client.Signing.Sign(ctx, keypair, message)
|
||||
if err != nil {
|
||||
log.Printf("Failed to sign message: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println("Signature created:")
|
||||
fmt.Printf(" Ed25519 component: %d bytes\n", len(signature.Ed25519Bytes))
|
||||
fmt.Printf(" Dilithium component: %d bytes\n", len(signature.DilithiumBytes))
|
||||
fmt.Printf(" Total signature size: %d bytes\n", signature.Size)
|
||||
|
||||
// Verify the signature
|
||||
valid, err := client.Signing.Verify(ctx, keypair.PublicKey, message, signature)
|
||||
if err != nil {
|
||||
log.Printf("Failed to verify signature: %v", err)
|
||||
return
|
||||
}
|
||||
fmt.Printf("\nVerification result: %v\n", valid)
|
||||
|
||||
// Verify with tampered message fails
|
||||
tamperedMessage := []byte("Hello, tampered message!")
|
||||
invalidResult, err := client.Signing.Verify(ctx, keypair.PublicKey, tamperedMessage, signature)
|
||||
if err != nil {
|
||||
log.Printf("Failed to verify tampered signature: %v", err)
|
||||
return
|
||||
}
|
||||
fmt.Printf("Tampered message verification: %v\n", invalidResult)
|
||||
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
func falconExample(ctx context.Context, client *crypto.Client) {
|
||||
fmt.Println("=== Falcon Post-Quantum Signatures ===")
|
||||
|
||||
// Generate Falcon-512 keypair (128-bit security)
|
||||
falcon512, err := client.Falcon.Generate(ctx, crypto.Falcon512)
|
||||
if err != nil {
|
||||
log.Printf("Failed to generate Falcon-512 keypair: %v", err)
|
||||
return
|
||||
}
|
||||
fmt.Println("Falcon-512 keypair:")
|
||||
fmt.Printf(" Public key: %d bytes\n", len(falcon512.PublicKey.KeyBytes))
|
||||
fmt.Println(" Security level: 128-bit")
|
||||
|
||||
// Generate Falcon-1024 keypair (256-bit security)
|
||||
falcon1024, err := client.Falcon.Generate(ctx, crypto.Falcon1024)
|
||||
if err != nil {
|
||||
log.Printf("Failed to generate Falcon-1024 keypair: %v", err)
|
||||
return
|
||||
}
|
||||
fmt.Println("\nFalcon-1024 keypair:")
|
||||
fmt.Printf(" Public key: %d bytes\n", len(falcon1024.PublicKey.KeyBytes))
|
||||
fmt.Println(" Security level: 256-bit")
|
||||
|
||||
// Sign with Falcon-512
|
||||
message := []byte("Post-quantum secure message")
|
||||
signature, err := client.Falcon.Sign(ctx, falcon512, message)
|
||||
if err != nil {
|
||||
log.Printf("Failed to sign with Falcon-512: %v", err)
|
||||
return
|
||||
}
|
||||
fmt.Printf("\nFalcon-512 signature: %d bytes\n", len(signature.SignatureBytes))
|
||||
|
||||
// Verify
|
||||
valid, err := client.Falcon.Verify(ctx, falcon512.PublicKey.KeyBytes, message, signature)
|
||||
if err != nil {
|
||||
log.Printf("Failed to verify Falcon signature: %v", err)
|
||||
return
|
||||
}
|
||||
fmt.Printf("Verification: %v\n", valid)
|
||||
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
func sphincsExample(ctx context.Context, client *crypto.Client) {
|
||||
fmt.Println("=== SPHINCS+ Hash-Based Signatures ===")
|
||||
|
||||
// SPHINCS+ variants with different security levels
|
||||
variants := []struct {
|
||||
variant crypto.SphincsVariant
|
||||
security int
|
||||
sigSize int
|
||||
}{
|
||||
{crypto.Shake128s, 128, 7856},
|
||||
{crypto.Shake192s, 192, 16224},
|
||||
{crypto.Shake256s, 256, 29792},
|
||||
}
|
||||
|
||||
// Generate and demonstrate each variant
|
||||
for _, v := range variants {
|
||||
keypair, err := client.Sphincs.Generate(ctx, v.variant)
|
||||
if err != nil {
|
||||
log.Printf("Failed to generate SPHINCS+ keypair: %v", err)
|
||||
continue
|
||||
}
|
||||
fmt.Printf("SPHINCS+ %s:\n", v.variant)
|
||||
fmt.Printf(" Security level: %d-bit\n", v.security)
|
||||
fmt.Printf(" Expected signature size: %d bytes\n", v.sigSize)
|
||||
|
||||
// Sign a message
|
||||
message := []byte("Hash-based quantum security")
|
||||
signature, err := client.Sphincs.Sign(ctx, keypair, message)
|
||||
if err != nil {
|
||||
log.Printf("Failed to sign with SPHINCS+: %v", err)
|
||||
continue
|
||||
}
|
||||
fmt.Printf(" Actual signature size: %d bytes\n", len(signature.SignatureBytes))
|
||||
|
||||
// Verify
|
||||
valid, err := client.Sphincs.Verify(ctx, keypair.PublicKey.KeyBytes, message, signature)
|
||||
if err != nil {
|
||||
log.Printf("Failed to verify SPHINCS+ signature: %v", err)
|
||||
continue
|
||||
}
|
||||
fmt.Printf(" Verification: %v\n\n", valid)
|
||||
}
|
||||
}
|
||||
|
||||
func kdfExample(ctx context.Context, client *crypto.Client) {
|
||||
fmt.Println("=== Key Derivation Functions ===")
|
||||
|
||||
// HKDF (HMAC-based Key Derivation Function)
|
||||
seed := []byte("master-secret-key-material-here")
|
||||
hkdfConfig := crypto.DerivationConfig{
|
||||
Salt: []byte("application-salt"),
|
||||
Info: []byte("encryption-key"),
|
||||
OutputLength: 32,
|
||||
}
|
||||
|
||||
derivedKey, err := client.KDF.DeriveKey(ctx, seed, hkdfConfig)
|
||||
if err != nil {
|
||||
log.Printf("Failed to derive key with HKDF: %v", err)
|
||||
return
|
||||
}
|
||||
fmt.Printf("HKDF derived key: %x\n", derivedKey)
|
||||
|
||||
// PBKDF2 (Password-Based Key Derivation Function)
|
||||
password := []byte("user-password")
|
||||
pbkdf2Config := crypto.PasswordDerivationConfig{
|
||||
Salt: []byte("random-salt-value"),
|
||||
Iterations: 100000,
|
||||
OutputLength: 32,
|
||||
}
|
||||
|
||||
passwordKey, err := client.KDF.DeriveFromPassword(ctx, password, pbkdf2Config)
|
||||
if err != nil {
|
||||
log.Printf("Failed to derive key with PBKDF2: %v", err)
|
||||
return
|
||||
}
|
||||
fmt.Printf("PBKDF2 derived key: %x\n", passwordKey)
|
||||
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
func hashExample(ctx context.Context, client *crypto.Client) {
|
||||
fmt.Println("=== Hash Functions ===")
|
||||
|
||||
data := []byte("Data to hash")
|
||||
|
||||
// SHA3-256 (FIPS 202)
|
||||
sha3, err := client.Hash.SHA3_256(ctx, data)
|
||||
if err != nil {
|
||||
log.Printf("Failed to compute SHA3-256: %v", err)
|
||||
return
|
||||
}
|
||||
fmt.Printf("SHA3-256: %s\n", sha3.Hex)
|
||||
|
||||
// BLAKE3 (fast, parallel)
|
||||
blake3, err := client.Hash.Blake3(ctx, data)
|
||||
if err != nil {
|
||||
log.Printf("Failed to compute BLAKE3: %v", err)
|
||||
return
|
||||
}
|
||||
fmt.Printf("BLAKE3: %s\n", blake3.Hex)
|
||||
|
||||
// Keccak-256 (Ethereum compatible)
|
||||
keccak, err := client.Hash.Keccak256(ctx, data)
|
||||
if err != nil {
|
||||
log.Printf("Failed to compute Keccak-256: %v", err)
|
||||
return
|
||||
}
|
||||
fmt.Printf("Keccak: %s\n", keccak.Hex)
|
||||
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
func getEnv(key, defaultValue string) string {
|
||||
if value := os.Getenv(key); value != "" {
|
||||
return value
|
||||
}
|
||||
return defaultValue
|
||||
}
|
||||
506
sdk/go/examples/dex_example.go
Normal file
506
sdk/go/examples/dex_example.go
Normal file
|
|
@ -0,0 +1,506 @@
|
|||
// Package main demonstrates the Synor DEX SDK for Go
|
||||
//
|
||||
// This example covers decentralized exchange operations:
|
||||
// - Spot trading (limit/market orders)
|
||||
// - Perpetual futures trading
|
||||
// - Liquidity provision (AMM pools)
|
||||
// - Order book management
|
||||
// - Portfolio tracking
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/synor/sdk-go/dex"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Initialize client
|
||||
config := dex.Config{
|
||||
APIKey: getEnv("SYNOR_API_KEY", "your-api-key"),
|
||||
Endpoint: "https://dex.synor.io/v1",
|
||||
Timeout: 30 * time.Second,
|
||||
Retries: 3,
|
||||
Debug: false,
|
||||
DefaultMarket: "SYN-USDC",
|
||||
}
|
||||
|
||||
client, err := dex.NewClient(config)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to create client: %v", err)
|
||||
}
|
||||
defer client.Close()
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
// Check service health
|
||||
healthy, err := client.HealthCheck(ctx)
|
||||
if err != nil {
|
||||
log.Printf("Health check failed: %v", err)
|
||||
} else {
|
||||
fmt.Printf("Service healthy: %v\n\n", healthy)
|
||||
}
|
||||
|
||||
// Run examples
|
||||
marketsExample(ctx, client)
|
||||
spotTradingExample(ctx, client)
|
||||
perpsTradingExample(ctx, client)
|
||||
liquidityExample(ctx, client)
|
||||
orderbookExample(ctx, client)
|
||||
portfolioExample(ctx, client)
|
||||
}
|
||||
|
||||
func marketsExample(ctx context.Context, client *dex.Client) {
|
||||
fmt.Println("=== Markets ===")
|
||||
|
||||
// Get all markets
|
||||
markets, err := client.Markets.List(ctx)
|
||||
if err != nil {
|
||||
log.Printf("Failed to list markets: %v", err)
|
||||
return
|
||||
}
|
||||
fmt.Printf("Available markets: %d\n", len(markets))
|
||||
|
||||
for _, market := range markets[:min(5, len(markets))] {
|
||||
fmt.Printf("\n %s:\n", market.Symbol)
|
||||
fmt.Printf(" Base: %s, Quote: %s\n", market.BaseAsset, market.QuoteAsset)
|
||||
fmt.Printf(" Price: %s\n", market.LastPrice)
|
||||
fmt.Printf(" 24h Volume: %s\n", market.Volume24h)
|
||||
fmt.Printf(" 24h Change: %s%%\n", market.Change24h)
|
||||
fmt.Printf(" Status: %s\n", market.Status)
|
||||
}
|
||||
|
||||
// Get specific market
|
||||
market, err := client.Markets.Get(ctx, "SYN-USDC")
|
||||
if err != nil {
|
||||
log.Printf("Failed to get market: %v", err)
|
||||
return
|
||||
}
|
||||
fmt.Printf("\nSYN-USDC details:\n")
|
||||
fmt.Printf(" Min order size: %s\n", market.MinOrderSize)
|
||||
fmt.Printf(" Tick size: %s\n", market.TickSize)
|
||||
fmt.Printf(" Maker fee: %s%%\n", market.MakerFee)
|
||||
fmt.Printf(" Taker fee: %s%%\n", market.TakerFee)
|
||||
|
||||
// Get market statistics
|
||||
stats, err := client.Markets.GetStats(ctx, "SYN-USDC")
|
||||
if err != nil {
|
||||
log.Printf("Failed to get market stats: %v", err)
|
||||
return
|
||||
}
|
||||
fmt.Printf("\nMarket statistics:\n")
|
||||
fmt.Printf(" High 24h: %s\n", stats.High24h)
|
||||
fmt.Printf(" Low 24h: %s\n", stats.Low24h)
|
||||
fmt.Printf(" Open interest: %s\n", stats.OpenInterest)
|
||||
fmt.Printf(" Funding rate: %s%%\n", stats.FundingRate)
|
||||
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
func spotTradingExample(ctx context.Context, client *dex.Client) {
|
||||
fmt.Println("=== Spot Trading ===")
|
||||
|
||||
// Place a limit order
|
||||
fmt.Println("Placing limit buy order...")
|
||||
limitOrder, err := client.Spot.PlaceOrder(ctx, &dex.OrderRequest{
|
||||
Market: "SYN-USDC",
|
||||
Side: dex.SideBuy,
|
||||
OrderType: dex.OrderTypeLimit,
|
||||
Price: "1.50",
|
||||
Quantity: "100",
|
||||
TimeInForce: dex.TimeInForceGTC,
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("Failed to place limit order: %v", err)
|
||||
} else {
|
||||
fmt.Printf("Limit order placed:\n")
|
||||
fmt.Printf(" Order ID: %s\n", limitOrder.OrderID)
|
||||
fmt.Printf(" Status: %s\n", limitOrder.Status)
|
||||
fmt.Printf(" Price: %s\n", limitOrder.Price)
|
||||
fmt.Printf(" Quantity: %s\n", limitOrder.Quantity)
|
||||
}
|
||||
|
||||
// Place a market order
|
||||
fmt.Println("\nPlacing market sell order...")
|
||||
marketOrder, err := client.Spot.PlaceOrder(ctx, &dex.OrderRequest{
|
||||
Market: "SYN-USDC",
|
||||
Side: dex.SideSell,
|
||||
OrderType: dex.OrderTypeMarket,
|
||||
Quantity: "50",
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("Failed to place market order: %v", err)
|
||||
} else {
|
||||
fmt.Printf("Market order executed:\n")
|
||||
fmt.Printf(" Order ID: %s\n", marketOrder.OrderID)
|
||||
fmt.Printf(" Status: %s\n", marketOrder.Status)
|
||||
fmt.Printf(" Filled: %s\n", marketOrder.FilledQuantity)
|
||||
fmt.Printf(" Avg price: %s\n", marketOrder.AveragePrice)
|
||||
}
|
||||
|
||||
// Get order status
|
||||
if limitOrder != nil {
|
||||
status, err := client.Spot.GetOrder(ctx, limitOrder.OrderID)
|
||||
if err != nil {
|
||||
log.Printf("Failed to get order status: %v", err)
|
||||
} else {
|
||||
fmt.Printf("\nOrder status:\n")
|
||||
fmt.Printf(" Status: %s\n", status.Status)
|
||||
fmt.Printf(" Filled: %s / %s\n", status.FilledQuantity, status.Quantity)
|
||||
fmt.Printf(" Remaining: %s\n", status.RemainingQuantity)
|
||||
}
|
||||
|
||||
// Cancel order
|
||||
fmt.Println("\nCancelling order...")
|
||||
err = client.Spot.CancelOrder(ctx, limitOrder.OrderID)
|
||||
if err != nil {
|
||||
log.Printf("Failed to cancel order: %v", err)
|
||||
} else {
|
||||
fmt.Println("Order cancelled successfully")
|
||||
}
|
||||
}
|
||||
|
||||
// Get open orders
|
||||
openOrders, err := client.Spot.GetOpenOrders(ctx, "SYN-USDC")
|
||||
if err != nil {
|
||||
log.Printf("Failed to get open orders: %v", err)
|
||||
} else {
|
||||
fmt.Printf("\nOpen orders: %d\n", len(openOrders))
|
||||
}
|
||||
|
||||
// Get trade history
|
||||
trades, err := client.Spot.GetTradeHistory(ctx, "SYN-USDC", 10)
|
||||
if err != nil {
|
||||
log.Printf("Failed to get trade history: %v", err)
|
||||
} else {
|
||||
fmt.Printf("\nRecent trades: %d\n", len(trades))
|
||||
for _, trade := range trades[:min(3, len(trades))] {
|
||||
fmt.Printf(" %s %s @ %s (%s)\n", trade.Side, trade.Quantity, trade.Price, trade.Timestamp.Format(time.RFC3339))
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
func perpsTradingExample(ctx context.Context, client *dex.Client) {
|
||||
fmt.Println("=== Perpetual Futures Trading ===")
|
||||
|
||||
// Get available perps markets
|
||||
perpsMarkets, err := client.Perps.ListMarkets(ctx)
|
||||
if err != nil {
|
||||
log.Printf("Failed to list perps markets: %v", err)
|
||||
return
|
||||
}
|
||||
fmt.Printf("Available perps markets: %d\n", len(perpsMarkets))
|
||||
|
||||
for _, market := range perpsMarkets[:min(3, len(perpsMarkets))] {
|
||||
fmt.Printf(" %s: %s (funding: %s%%)\n", market.Symbol, market.MarkPrice, market.FundingRate)
|
||||
}
|
||||
|
||||
// Open a long position
|
||||
fmt.Println("\nOpening long position...")
|
||||
position, err := client.Perps.OpenPosition(ctx, &dex.PerpsOrderRequest{
|
||||
Market: "SYN-USDC-PERP",
|
||||
Side: dex.SideBuy,
|
||||
OrderType: dex.OrderTypeLimit,
|
||||
Price: "1.50",
|
||||
Size: "1000",
|
||||
Leverage: 10,
|
||||
ReduceOnly: false,
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("Failed to open position: %v", err)
|
||||
} else {
|
||||
fmt.Printf("Position opened:\n")
|
||||
fmt.Printf(" Position ID: %s\n", position.PositionID)
|
||||
fmt.Printf(" Size: %s\n", position.Size)
|
||||
fmt.Printf(" Entry price: %s\n", position.EntryPrice)
|
||||
fmt.Printf(" Leverage: %dx\n", position.Leverage)
|
||||
fmt.Printf(" Liquidation price: %s\n", position.LiquidationPrice)
|
||||
}
|
||||
|
||||
// Get position details
|
||||
if position != nil {
|
||||
details, err := client.Perps.GetPosition(ctx, position.PositionID)
|
||||
if err != nil {
|
||||
log.Printf("Failed to get position: %v", err)
|
||||
} else {
|
||||
fmt.Printf("\nPosition details:\n")
|
||||
fmt.Printf(" Unrealized PnL: %s\n", details.UnrealizedPnL)
|
||||
fmt.Printf(" Margin: %s\n", details.Margin)
|
||||
fmt.Printf(" Margin ratio: %s%%\n", details.MarginRatio)
|
||||
}
|
||||
}
|
||||
|
||||
// Set stop loss and take profit
|
||||
if position != nil {
|
||||
fmt.Println("\nSetting stop loss and take profit...")
|
||||
err = client.Perps.SetStopLoss(ctx, position.PositionID, "1.40")
|
||||
if err != nil {
|
||||
log.Printf("Failed to set stop loss: %v", err)
|
||||
} else {
|
||||
fmt.Println("Stop loss set at 1.40")
|
||||
}
|
||||
|
||||
err = client.Perps.SetTakeProfit(ctx, position.PositionID, "1.80")
|
||||
if err != nil {
|
||||
log.Printf("Failed to set take profit: %v", err)
|
||||
} else {
|
||||
fmt.Println("Take profit set at 1.80")
|
||||
}
|
||||
|
||||
// Close position
|
||||
fmt.Println("\nClosing position...")
|
||||
closeResult, err := client.Perps.ClosePosition(ctx, position.PositionID)
|
||||
if err != nil {
|
||||
log.Printf("Failed to close position: %v", err)
|
||||
} else {
|
||||
fmt.Printf("Position closed:\n")
|
||||
fmt.Printf(" Realized PnL: %s\n", closeResult.RealizedPnL)
|
||||
fmt.Printf(" Close price: %s\n", closeResult.ClosePrice)
|
||||
}
|
||||
}
|
||||
|
||||
// Get all positions
|
||||
positions, err := client.Perps.GetPositions(ctx)
|
||||
if err != nil {
|
||||
log.Printf("Failed to get positions: %v", err)
|
||||
} else {
|
||||
fmt.Printf("\nOpen positions: %d\n", len(positions))
|
||||
}
|
||||
|
||||
// Get funding history
|
||||
funding, err := client.Perps.GetFundingHistory(ctx, "SYN-USDC-PERP", 10)
|
||||
if err != nil {
|
||||
log.Printf("Failed to get funding history: %v", err)
|
||||
} else {
|
||||
fmt.Printf("Funding payments: %d\n", len(funding))
|
||||
}
|
||||
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
func liquidityExample(ctx context.Context, client *dex.Client) {
|
||||
fmt.Println("=== Liquidity Provision ===")
|
||||
|
||||
// Get available pools
|
||||
pools, err := client.Liquidity.ListPools(ctx)
|
||||
if err != nil {
|
||||
log.Printf("Failed to list pools: %v", err)
|
||||
return
|
||||
}
|
||||
fmt.Printf("Available pools: %d\n", len(pools))
|
||||
|
||||
for _, pool := range pools[:min(3, len(pools))] {
|
||||
fmt.Printf("\n %s:\n", pool.Name)
|
||||
fmt.Printf(" TVL: $%s\n", pool.TVL)
|
||||
fmt.Printf(" APR: %s%%\n", pool.APR)
|
||||
fmt.Printf(" Volume 24h: $%s\n", pool.Volume24h)
|
||||
fmt.Printf(" Fee tier: %s%%\n", pool.FeeTier)
|
||||
}
|
||||
|
||||
// Get pool details
|
||||
pool, err := client.Liquidity.GetPool(ctx, "SYN-USDC")
|
||||
if err != nil {
|
||||
log.Printf("Failed to get pool: %v", err)
|
||||
return
|
||||
}
|
||||
fmt.Printf("\nSYN-USDC pool details:\n")
|
||||
fmt.Printf(" Token0: %s (%s)\n", pool.Token0.Symbol, pool.Token0Reserve)
|
||||
fmt.Printf(" Token1: %s (%s)\n", pool.Token1.Symbol, pool.Token1Reserve)
|
||||
fmt.Printf(" Price: %s\n", pool.Price)
|
||||
fmt.Printf(" Total LP tokens: %s\n", pool.TotalLPTokens)
|
||||
|
||||
// Add liquidity
|
||||
fmt.Println("\nAdding liquidity...")
|
||||
addResult, err := client.Liquidity.AddLiquidity(ctx, &dex.AddLiquidityRequest{
|
||||
Pool: "SYN-USDC",
|
||||
Amount0: "100",
|
||||
Amount1: "150",
|
||||
SlippageBps: 50, // 0.5%
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("Failed to add liquidity: %v", err)
|
||||
} else {
|
||||
fmt.Printf("Liquidity added:\n")
|
||||
fmt.Printf(" LP tokens received: %s\n", addResult.LPTokens)
|
||||
fmt.Printf(" Position ID: %s\n", addResult.PositionID)
|
||||
fmt.Printf(" Share of pool: %s%%\n", addResult.ShareOfPool)
|
||||
}
|
||||
|
||||
// Get LP positions
|
||||
lpPositions, err := client.Liquidity.GetPositions(ctx)
|
||||
if err != nil {
|
||||
log.Printf("Failed to get LP positions: %v", err)
|
||||
} else {
|
||||
fmt.Printf("\nLP positions: %d\n", len(lpPositions))
|
||||
for _, pos := range lpPositions {
|
||||
fmt.Printf(" %s: %s LP tokens (value: $%s)\n", pos.Pool, pos.LPTokens, pos.Value)
|
||||
}
|
||||
}
|
||||
|
||||
// Claim fees
|
||||
if addResult != nil {
|
||||
fmt.Println("\nClaiming fees...")
|
||||
fees, err := client.Liquidity.ClaimFees(ctx, addResult.PositionID)
|
||||
if err != nil {
|
||||
log.Printf("Failed to claim fees: %v", err)
|
||||
} else {
|
||||
fmt.Printf("Fees claimed:\n")
|
||||
fmt.Printf(" Token0: %s\n", fees.Amount0)
|
||||
fmt.Printf(" Token1: %s\n", fees.Amount1)
|
||||
}
|
||||
|
||||
// Remove liquidity
|
||||
fmt.Println("\nRemoving liquidity...")
|
||||
removeResult, err := client.Liquidity.RemoveLiquidity(ctx, &dex.RemoveLiquidityRequest{
|
||||
PositionID: addResult.PositionID,
|
||||
LPTokens: addResult.LPTokens,
|
||||
SlippageBps: 50,
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("Failed to remove liquidity: %v", err)
|
||||
} else {
|
||||
fmt.Printf("Liquidity removed:\n")
|
||||
fmt.Printf(" Token0 received: %s\n", removeResult.Amount0)
|
||||
fmt.Printf(" Token1 received: %s\n", removeResult.Amount1)
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
func orderbookExample(ctx context.Context, client *dex.Client) {
|
||||
fmt.Println("=== Order Book ===")
|
||||
|
||||
// Get order book snapshot
|
||||
orderbook, err := client.Orderbook.GetSnapshot(ctx, "SYN-USDC", 10)
|
||||
if err != nil {
|
||||
log.Printf("Failed to get orderbook: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println("Order book for SYN-USDC:")
|
||||
fmt.Println("\nAsks (sells):")
|
||||
for _, ask := range orderbook.Asks[:min(5, len(orderbook.Asks))] {
|
||||
fmt.Printf(" %s @ %s\n", ask.Quantity, ask.Price)
|
||||
}
|
||||
|
||||
fmt.Println("\nBids (buys):")
|
||||
for _, bid := range orderbook.Bids[:min(5, len(orderbook.Bids))] {
|
||||
fmt.Printf(" %s @ %s\n", bid.Quantity, bid.Price)
|
||||
}
|
||||
|
||||
fmt.Printf("\nSpread: %s (%s%%)\n", orderbook.Spread, orderbook.SpreadPercent)
|
||||
fmt.Printf("Mid price: %s\n", orderbook.MidPrice)
|
||||
|
||||
// Get recent trades
|
||||
recentTrades, err := client.Orderbook.GetRecentTrades(ctx, "SYN-USDC", 10)
|
||||
if err != nil {
|
||||
log.Printf("Failed to get recent trades: %v", err)
|
||||
} else {
|
||||
fmt.Println("\nRecent trades:")
|
||||
for _, trade := range recentTrades[:min(5, len(recentTrades))] {
|
||||
fmt.Printf(" %s %s @ %s\n", trade.Side, trade.Quantity, trade.Price)
|
||||
}
|
||||
}
|
||||
|
||||
// Subscribe to orderbook updates (simulated)
|
||||
fmt.Println("\nSubscribing to orderbook updates...")
|
||||
updates := client.Orderbook.Subscribe(ctx, "SYN-USDC")
|
||||
|
||||
// Process a few updates (in real usage, this would be a goroutine)
|
||||
go func() {
|
||||
for i := 0; i < 3; i++ {
|
||||
select {
|
||||
case update := <-updates:
|
||||
fmt.Printf(" Update: %s %s @ %s\n", update.Side, update.Quantity, update.Price)
|
||||
case <-time.After(5 * time.Second):
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
time.Sleep(2 * time.Second) // Wait for some updates
|
||||
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
func portfolioExample(ctx context.Context, client *dex.Client) {
|
||||
fmt.Println("=== Portfolio ===")
|
||||
|
||||
// Get portfolio overview
|
||||
portfolio, err := client.Portfolio.GetOverview(ctx)
|
||||
if err != nil {
|
||||
log.Printf("Failed to get portfolio: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println("Portfolio overview:")
|
||||
fmt.Printf(" Total value: $%s\n", portfolio.TotalValue)
|
||||
fmt.Printf(" Available balance: $%s\n", portfolio.AvailableBalance)
|
||||
fmt.Printf(" In orders: $%s\n", portfolio.InOrders)
|
||||
fmt.Printf(" In positions: $%s\n", portfolio.InPositions)
|
||||
fmt.Printf(" Unrealized PnL: $%s\n", portfolio.UnrealizedPnL)
|
||||
|
||||
// Get balances
|
||||
balances, err := client.Portfolio.GetBalances(ctx)
|
||||
if err != nil {
|
||||
log.Printf("Failed to get balances: %v", err)
|
||||
} else {
|
||||
fmt.Println("\nBalances:")
|
||||
for _, balance := range balances {
|
||||
fmt.Printf(" %s: %s (available: %s, in orders: %s)\n",
|
||||
balance.Asset, balance.Total, balance.Available, balance.InOrders)
|
||||
}
|
||||
}
|
||||
|
||||
// Get PnL history
|
||||
pnlHistory, err := client.Portfolio.GetPnLHistory(ctx, 30) // Last 30 days
|
||||
if err != nil {
|
||||
log.Printf("Failed to get PnL history: %v", err)
|
||||
} else {
|
||||
fmt.Printf("\nPnL history (last %d days):\n", len(pnlHistory))
|
||||
if len(pnlHistory) > 0 {
|
||||
totalPnL := "0"
|
||||
for _, day := range pnlHistory {
|
||||
totalPnL = day.CumulativePnL
|
||||
}
|
||||
fmt.Printf(" Total PnL: $%s\n", totalPnL)
|
||||
}
|
||||
}
|
||||
|
||||
// Get trade statistics
|
||||
stats, err := client.Portfolio.GetStats(ctx)
|
||||
if err != nil {
|
||||
log.Printf("Failed to get trade stats: %v", err)
|
||||
} else {
|
||||
fmt.Println("\nTrade statistics:")
|
||||
fmt.Printf(" Total trades: %d\n", stats.TotalTrades)
|
||||
fmt.Printf(" Win rate: %s%%\n", stats.WinRate)
|
||||
fmt.Printf(" Avg profit: $%s\n", stats.AvgProfit)
|
||||
fmt.Printf(" Avg loss: $%s\n", stats.AvgLoss)
|
||||
fmt.Printf(" Best trade: $%s\n", stats.BestTrade)
|
||||
fmt.Printf(" Worst trade: $%s\n", stats.WorstTrade)
|
||||
}
|
||||
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
func min(a, b int) int {
|
||||
if a < b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func getEnv(key, defaultValue string) string {
|
||||
if value := os.Getenv(key); value != "" {
|
||||
return value
|
||||
}
|
||||
return defaultValue
|
||||
}
|
||||
509
sdk/go/examples/ibc_example.go
Normal file
509
sdk/go/examples/ibc_example.go
Normal file
|
|
@ -0,0 +1,509 @@
|
|||
// Package main demonstrates the Synor IBC SDK for Go
|
||||
//
|
||||
// This example covers Inter-Blockchain Communication operations:
|
||||
// - Cross-chain token transfers
|
||||
// - Channel management
|
||||
// - Packet handling
|
||||
// - Relayer operations
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/synor/sdk-go/ibc"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Initialize client
|
||||
config := ibc.Config{
|
||||
APIKey: getEnv("SYNOR_API_KEY", "your-api-key"),
|
||||
Endpoint: "https://ibc.synor.io/v1",
|
||||
Timeout: 30 * time.Second,
|
||||
Retries: 3,
|
||||
Debug: false,
|
||||
DefaultNetwork: ibc.NetworkMainnet,
|
||||
}
|
||||
|
||||
client, err := ibc.NewClient(config)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to create client: %v", err)
|
||||
}
|
||||
defer client.Close()
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
// Check service health
|
||||
healthy, err := client.HealthCheck(ctx)
|
||||
if err != nil {
|
||||
log.Printf("Health check failed: %v", err)
|
||||
} else {
|
||||
fmt.Printf("Service healthy: %v\n\n", healthy)
|
||||
}
|
||||
|
||||
// Run examples
|
||||
chainsExample(ctx, client)
|
||||
channelsExample(ctx, client)
|
||||
transferExample(ctx, client)
|
||||
packetExample(ctx, client)
|
||||
relayerExample(ctx, client)
|
||||
connectionExample(ctx, client)
|
||||
}
|
||||
|
||||
func chainsExample(ctx context.Context, client *ibc.Client) {
|
||||
fmt.Println("=== Connected Chains ===")
|
||||
|
||||
// Get all connected chains
|
||||
chains, err := client.Chains.List(ctx)
|
||||
if err != nil {
|
||||
log.Printf("Failed to list chains: %v", err)
|
||||
return
|
||||
}
|
||||
fmt.Printf("Connected chains: %d\n", len(chains))
|
||||
|
||||
for _, chain := range chains {
|
||||
fmt.Printf(" %s:\n", chain.ChainID)
|
||||
fmt.Printf(" Name: %s\n", chain.Name)
|
||||
fmt.Printf(" Status: %s\n", chain.Status)
|
||||
fmt.Printf(" Block height: %d\n", chain.LatestHeight)
|
||||
fmt.Printf(" Channels: %d\n", chain.ChannelCount)
|
||||
}
|
||||
|
||||
// Get specific chain info
|
||||
cosmos, err := client.Chains.Get(ctx, "cosmoshub-4")
|
||||
if err != nil {
|
||||
log.Printf("Failed to get Cosmos Hub: %v", err)
|
||||
return
|
||||
}
|
||||
fmt.Println("\nCosmos Hub details:")
|
||||
fmt.Printf(" RPC: %s\n", cosmos.RPCEndpoint)
|
||||
fmt.Printf(" Rest: %s\n", cosmos.RestEndpoint)
|
||||
fmt.Printf(" Native denom: %s\n", cosmos.NativeDenom)
|
||||
fmt.Printf(" Prefix: %s\n", cosmos.Bech32Prefix)
|
||||
|
||||
// Get supported assets on a chain
|
||||
assets, err := client.Chains.GetAssets(ctx, "cosmoshub-4")
|
||||
if err != nil {
|
||||
log.Printf("Failed to get assets: %v", err)
|
||||
return
|
||||
}
|
||||
fmt.Println("\nSupported assets on Cosmos Hub:")
|
||||
for _, asset := range assets[:min(5, len(assets))] {
|
||||
fmt.Printf(" %s: %s\n", asset.Symbol, asset.Denom)
|
||||
fmt.Printf(" Origin: %s\n", asset.OriginChain)
|
||||
fmt.Printf(" Decimals: %d\n", asset.Decimals)
|
||||
}
|
||||
|
||||
// Get chain paths (routes)
|
||||
paths, err := client.Chains.GetPaths(ctx, "synor-1", "cosmoshub-4")
|
||||
if err != nil {
|
||||
log.Printf("Failed to get paths: %v", err)
|
||||
return
|
||||
}
|
||||
fmt.Println("\nPaths from Synor to Cosmos Hub:")
|
||||
for _, path := range paths {
|
||||
fmt.Printf(" %s -> %s\n", path.SourceChannel, path.DestChannel)
|
||||
fmt.Printf(" Hops: %d\n", path.Hops)
|
||||
fmt.Printf(" Avg time: %ds\n", path.AvgTransferTime)
|
||||
}
|
||||
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
func channelsExample(ctx context.Context, client *ibc.Client) {
|
||||
fmt.Println("=== Channel Management ===")
|
||||
|
||||
// List all channels
|
||||
channels, err := client.Channels.List(ctx)
|
||||
if err != nil {
|
||||
log.Printf("Failed to list channels: %v", err)
|
||||
return
|
||||
}
|
||||
fmt.Printf("Total channels: %d\n", len(channels))
|
||||
|
||||
// Filter by state
|
||||
var openChannels []ibc.Channel
|
||||
for _, c := range channels {
|
||||
if c.State == ibc.ChannelStateOpen {
|
||||
openChannels = append(openChannels, c)
|
||||
}
|
||||
}
|
||||
fmt.Printf("Open channels: %d\n", len(openChannels))
|
||||
|
||||
for _, channel := range openChannels[:min(3, len(openChannels))] {
|
||||
fmt.Printf("\n Channel %s:\n", channel.ChannelID)
|
||||
fmt.Printf(" Port: %s\n", channel.PortID)
|
||||
fmt.Printf(" Counterparty: %s on %s\n", channel.CounterpartyChannelID, channel.CounterpartyChainID)
|
||||
fmt.Printf(" Ordering: %s\n", channel.Ordering)
|
||||
fmt.Printf(" Version: %s\n", channel.Version)
|
||||
fmt.Printf(" State: %s\n", channel.State)
|
||||
}
|
||||
|
||||
// Get specific channel
|
||||
channel, err := client.Channels.Get(ctx, "channel-0")
|
||||
if err != nil {
|
||||
log.Printf("Failed to get channel: %v", err)
|
||||
return
|
||||
}
|
||||
fmt.Println("\nChannel-0 details:")
|
||||
fmt.Printf(" Connection: %s\n", channel.ConnectionID)
|
||||
fmt.Printf(" Counterparty port: %s\n", channel.CounterpartyPortID)
|
||||
|
||||
// Get channel statistics
|
||||
stats, err := client.Channels.GetStats(ctx, "channel-0")
|
||||
if err != nil {
|
||||
log.Printf("Failed to get channel stats: %v", err)
|
||||
return
|
||||
}
|
||||
fmt.Println("\nChannel-0 statistics:")
|
||||
fmt.Printf(" Total packets sent: %d\n", stats.PacketsSent)
|
||||
fmt.Printf(" Total packets received: %d\n", stats.PacketsReceived)
|
||||
fmt.Printf(" Pending packets: %d\n", stats.PendingPackets)
|
||||
fmt.Printf(" Success rate: %.1f%%\n", stats.SuccessRate)
|
||||
fmt.Printf(" Avg relay time: %ds\n", stats.AvgRelayTime)
|
||||
|
||||
// Get channel capacity
|
||||
capacity, err := client.Channels.GetCapacity(ctx, "channel-0")
|
||||
if err != nil {
|
||||
log.Printf("Failed to get channel capacity: %v", err)
|
||||
return
|
||||
}
|
||||
fmt.Println("\nChannel-0 capacity:")
|
||||
fmt.Printf(" Max throughput: %d packets/block\n", capacity.MaxPacketsPerBlock)
|
||||
fmt.Printf(" Current utilization: %.1f%%\n", capacity.Utilization)
|
||||
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
func transferExample(ctx context.Context, client *ibc.Client) {
|
||||
fmt.Println("=== Cross-Chain Transfers ===")
|
||||
|
||||
// Estimate transfer fee
|
||||
estimate, err := client.Transfers.EstimateFee(ctx, &ibc.FeeEstimateRequest{
|
||||
SourceChain: "synor-1",
|
||||
DestChain: "cosmoshub-4",
|
||||
Denom: "usyn",
|
||||
Amount: "1000000", // 1 SYN (6 decimals)
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("Failed to estimate fee: %v", err)
|
||||
return
|
||||
}
|
||||
fmt.Println("Transfer fee estimate:")
|
||||
fmt.Printf(" Gas: %d\n", estimate.Gas)
|
||||
fmt.Printf(" Fee: %s %s\n", estimate.Fee, estimate.FeeDenom)
|
||||
fmt.Printf(" Timeout: %ds\n", estimate.Timeout)
|
||||
|
||||
// Initiate a transfer
|
||||
fmt.Println("\nInitiating transfer...")
|
||||
transfer, err := client.Transfers.Send(ctx, &ibc.TransferRequest{
|
||||
SourceChain: "synor-1",
|
||||
DestChain: "cosmoshub-4",
|
||||
Channel: "channel-0",
|
||||
Sender: "synor1abc...", // Your address
|
||||
Receiver: "cosmos1xyz...", // Recipient address
|
||||
Denom: "usyn",
|
||||
Amount: "1000000", // 1 SYN
|
||||
Memo: "Cross-chain transfer example",
|
||||
TimeoutHeight: 0, // Use timestamp instead
|
||||
TimeoutTimestamp: time.Now().Add(10 * time.Minute).UnixMilli(),
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("Failed to initiate transfer: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println("Transfer initiated:")
|
||||
fmt.Printf(" TX Hash: %s\n", transfer.TxHash)
|
||||
fmt.Printf(" Sequence: %d\n", transfer.Sequence)
|
||||
fmt.Printf(" Status: %s\n", transfer.Status)
|
||||
|
||||
// Track transfer status
|
||||
fmt.Println("\nTracking transfer...")
|
||||
status, err := client.Transfers.GetStatus(ctx, transfer.TxHash)
|
||||
if err != nil {
|
||||
log.Printf("Failed to get transfer status: %v", err)
|
||||
return
|
||||
}
|
||||
fmt.Printf("Current status: %s\n", status.State)
|
||||
fmt.Printf(" Source confirmed: %v\n", status.SourceConfirmed)
|
||||
fmt.Printf(" Relayed: %v\n", status.Relayed)
|
||||
fmt.Printf(" Dest confirmed: %v\n", status.DestConfirmed)
|
||||
|
||||
// Get transfer history
|
||||
history, err := client.Transfers.GetHistory(ctx, "synor1abc...", 5)
|
||||
if err != nil {
|
||||
log.Printf("Failed to get transfer history: %v", err)
|
||||
return
|
||||
}
|
||||
fmt.Println("\nTransfer history (last 5):")
|
||||
for _, tx := range history {
|
||||
direction := "OUT"
|
||||
if tx.Sender != "synor1abc..." {
|
||||
direction = "IN"
|
||||
}
|
||||
fmt.Printf(" %s %s %s (%s)\n", direction, tx.Amount, tx.Denom, tx.Status)
|
||||
}
|
||||
|
||||
// Get pending transfers
|
||||
pending, err := client.Transfers.GetPending(ctx, "synor1abc...")
|
||||
if err != nil {
|
||||
log.Printf("Failed to get pending transfers: %v", err)
|
||||
return
|
||||
}
|
||||
fmt.Printf("\nPending transfers: %d\n", len(pending))
|
||||
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
func packetExample(ctx context.Context, client *ibc.Client) {
|
||||
fmt.Println("=== Packet Handling ===")
|
||||
|
||||
// Get pending packets
|
||||
packets, err := client.Packets.GetPending(ctx, "channel-0")
|
||||
if err != nil {
|
||||
log.Printf("Failed to get pending packets: %v", err)
|
||||
return
|
||||
}
|
||||
fmt.Printf("Pending packets on channel-0: %d\n", len(packets))
|
||||
|
||||
for _, packet := range packets[:min(3, len(packets))] {
|
||||
fmt.Printf("\n Packet %d:\n", packet.Sequence)
|
||||
fmt.Printf(" Source: %s/%s\n", packet.SourcePort, packet.SourceChannel)
|
||||
fmt.Printf(" Dest: %s/%s\n", packet.DestPort, packet.DestChannel)
|
||||
fmt.Printf(" State: %s\n", packet.State)
|
||||
fmt.Printf(" Data size: %d bytes\n", len(packet.Data))
|
||||
fmt.Printf(" Timeout height: %d\n", packet.TimeoutHeight)
|
||||
fmt.Printf(" Timeout timestamp: %d\n", packet.TimeoutTimestamp)
|
||||
}
|
||||
|
||||
// Get packet by sequence
|
||||
packet, err := client.Packets.Get(ctx, "channel-0", 1)
|
||||
if err != nil {
|
||||
log.Printf("Failed to get packet: %v", err)
|
||||
return
|
||||
}
|
||||
fmt.Println("\nPacket details:")
|
||||
fmt.Printf(" Commitment: %s\n", packet.Commitment)
|
||||
fmt.Printf(" Receipt: %s\n", packet.Receipt)
|
||||
fmt.Printf(" Acknowledgement: %s\n", packet.Acknowledgement)
|
||||
|
||||
// Get packet receipts
|
||||
receipts, err := client.Packets.GetReceipts(ctx, "channel-0", []uint64{1, 2, 3})
|
||||
if err != nil {
|
||||
log.Printf("Failed to get receipts: %v", err)
|
||||
return
|
||||
}
|
||||
fmt.Println("\nPacket receipts:")
|
||||
for seq, receipt := range receipts {
|
||||
status := "not received"
|
||||
if receipt {
|
||||
status = "received"
|
||||
}
|
||||
fmt.Printf(" Sequence %d: %s\n", seq, status)
|
||||
}
|
||||
|
||||
// Get timed out packets
|
||||
timedOut, err := client.Packets.GetTimedOut(ctx, "channel-0")
|
||||
if err != nil {
|
||||
log.Printf("Failed to get timed out packets: %v", err)
|
||||
return
|
||||
}
|
||||
fmt.Printf("\nTimed out packets: %d\n", len(timedOut))
|
||||
for _, p := range timedOut {
|
||||
fmt.Printf(" Sequence %d: timeout at %d\n", p.Sequence, p.TimeoutTimestamp)
|
||||
}
|
||||
|
||||
// Get unreceived packets
|
||||
unreceived, err := client.Packets.GetUnreceived(ctx, "channel-0")
|
||||
if err != nil {
|
||||
log.Printf("Failed to get unreceived packets: %v", err)
|
||||
return
|
||||
}
|
||||
unreceivedStr := "none"
|
||||
if len(unreceived) > 0 {
|
||||
unreceivedStr = fmt.Sprintf("%v", unreceived)
|
||||
}
|
||||
fmt.Printf("\nUnreceived packet sequences: %s\n", unreceivedStr)
|
||||
|
||||
// Get unacknowledged packets
|
||||
unacked, err := client.Packets.GetUnacknowledged(ctx, "channel-0")
|
||||
if err != nil {
|
||||
log.Printf("Failed to get unacknowledged packets: %v", err)
|
||||
return
|
||||
}
|
||||
unackedStr := "none"
|
||||
if len(unacked) > 0 {
|
||||
unackedStr = fmt.Sprintf("%v", unacked)
|
||||
}
|
||||
fmt.Printf("Unacknowledged packet sequences: %s\n", unackedStr)
|
||||
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
func relayerExample(ctx context.Context, client *ibc.Client) {
|
||||
fmt.Println("=== Relayer Operations ===")
|
||||
|
||||
// Get active relayers
|
||||
relayers, err := client.Relayers.List(ctx)
|
||||
if err != nil {
|
||||
log.Printf("Failed to list relayers: %v", err)
|
||||
return
|
||||
}
|
||||
fmt.Printf("Active relayers: %d\n", len(relayers))
|
||||
|
||||
for _, relayer := range relayers[:min(3, len(relayers))] {
|
||||
fmt.Printf("\n %s:\n", relayer.Address)
|
||||
fmt.Printf(" Chains: %v\n", relayer.Chains)
|
||||
fmt.Printf(" Packets relayed: %d\n", relayer.PacketsRelayed)
|
||||
fmt.Printf(" Success rate: %.1f%%\n", relayer.SuccessRate)
|
||||
fmt.Printf(" Avg latency: %dms\n", relayer.AvgLatency)
|
||||
fmt.Printf(" Fee rate: %.2f%%\n", relayer.FeeRate)
|
||||
}
|
||||
|
||||
// Get relayer statistics
|
||||
stats, err := client.Relayers.GetStats(ctx)
|
||||
if err != nil {
|
||||
log.Printf("Failed to get relayer stats: %v", err)
|
||||
return
|
||||
}
|
||||
fmt.Println("\nGlobal relayer statistics:")
|
||||
fmt.Printf(" Total relayers: %d\n", stats.TotalRelayers)
|
||||
fmt.Printf(" Active relayers: %d\n", stats.ActiveRelayers)
|
||||
fmt.Printf(" Packets relayed (24h): %d\n", stats.PacketsRelayed24h)
|
||||
fmt.Printf(" Total fees earned: %s\n", stats.TotalFeesEarned)
|
||||
|
||||
// Register as a relayer
|
||||
fmt.Println("\nRegistering as relayer...")
|
||||
registration, err := client.Relayers.Register(ctx, &ibc.RelayerRegistration{
|
||||
Chains: []string{"synor-1", "cosmoshub-4"},
|
||||
FeeRate: 0.1, // 0.1% fee
|
||||
MinPacketSize: 0,
|
||||
MaxPacketSize: 1000000,
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("Failed to register as relayer: %v", err)
|
||||
return
|
||||
}
|
||||
fmt.Printf("Registered with address: %s\n", registration.RelayerAddress)
|
||||
|
||||
// Start relaying (in background)
|
||||
fmt.Println("\nStarting relay service...")
|
||||
relaySession, err := client.Relayers.StartRelay(ctx, &ibc.RelayConfig{
|
||||
Channels: []string{"channel-0"},
|
||||
AutoAck: true,
|
||||
BatchSize: 10,
|
||||
PollInterval: 5000,
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("Failed to start relay: %v", err)
|
||||
return
|
||||
}
|
||||
fmt.Printf("Relay session started: %s\n", relaySession.SessionID)
|
||||
|
||||
// Get relay queue
|
||||
queue, err := client.Relayers.GetQueue(ctx, "channel-0")
|
||||
if err != nil {
|
||||
log.Printf("Failed to get relay queue: %v", err)
|
||||
return
|
||||
}
|
||||
fmt.Printf("\nRelay queue for channel-0: %d packets\n", len(queue))
|
||||
|
||||
// Manually relay a packet
|
||||
if len(queue) > 0 {
|
||||
fmt.Println("\nRelaying packet...")
|
||||
relayResult, err := client.Relayers.RelayPacket(ctx, queue[0].Sequence, "channel-0")
|
||||
if err != nil {
|
||||
log.Printf("Failed to relay packet: %v", err)
|
||||
} else {
|
||||
fmt.Printf("Relay result: %s\n", relayResult.Status)
|
||||
fmt.Printf(" TX Hash: %s\n", relayResult.TxHash)
|
||||
fmt.Printf(" Fee earned: %s\n", relayResult.FeeEarned)
|
||||
}
|
||||
}
|
||||
|
||||
// Stop relay session
|
||||
err = client.Relayers.StopRelay(ctx, relaySession.SessionID)
|
||||
if err != nil {
|
||||
log.Printf("Failed to stop relay: %v", err)
|
||||
} else {
|
||||
fmt.Println("\nRelay session stopped")
|
||||
}
|
||||
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
func connectionExample(ctx context.Context, client *ibc.Client) {
|
||||
fmt.Println("=== Connection Information ===")
|
||||
|
||||
// List connections
|
||||
connections, err := client.Connections.List(ctx)
|
||||
if err != nil {
|
||||
log.Printf("Failed to list connections: %v", err)
|
||||
return
|
||||
}
|
||||
fmt.Printf("Total connections: %d\n", len(connections))
|
||||
|
||||
for _, conn := range connections[:min(3, len(connections))] {
|
||||
fmt.Printf("\n %s:\n", conn.ConnectionID)
|
||||
fmt.Printf(" Client: %s\n", conn.ClientID)
|
||||
fmt.Printf(" Counterparty: %s\n", conn.CounterpartyConnectionID)
|
||||
fmt.Printf(" State: %s\n", conn.State)
|
||||
fmt.Printf(" Versions: %v\n", conn.Versions)
|
||||
}
|
||||
|
||||
// Get connection details
|
||||
connection, err := client.Connections.Get(ctx, "connection-0")
|
||||
if err != nil {
|
||||
log.Printf("Failed to get connection: %v", err)
|
||||
return
|
||||
}
|
||||
fmt.Println("\nConnection-0 details:")
|
||||
fmt.Printf(" Delay period: %dns\n", connection.DelayPeriod)
|
||||
fmt.Printf(" Counterparty client: %s\n", connection.CounterpartyClientID)
|
||||
fmt.Printf(" Counterparty prefix: %s\n", connection.CounterpartyPrefix)
|
||||
|
||||
// Get client state
|
||||
clientState, err := client.Clients.Get(ctx, connection.ClientID)
|
||||
if err != nil {
|
||||
log.Printf("Failed to get client state: %v", err)
|
||||
return
|
||||
}
|
||||
fmt.Println("\nClient state:")
|
||||
fmt.Printf(" Chain ID: %s\n", clientState.ChainID)
|
||||
fmt.Printf(" Trust level: %s\n", clientState.TrustLevel)
|
||||
fmt.Printf(" Trusting period: %s\n", clientState.TrustingPeriod)
|
||||
fmt.Printf(" Unbonding period: %s\n", clientState.UnbondingPeriod)
|
||||
fmt.Printf(" Latest height: %d\n", clientState.LatestHeight)
|
||||
fmt.Printf(" Frozen: %v\n", clientState.Frozen)
|
||||
|
||||
// Get consensus state
|
||||
consensus, err := client.Clients.GetConsensusState(ctx, connection.ClientID, clientState.LatestHeight)
|
||||
if err != nil {
|
||||
log.Printf("Failed to get consensus state: %v", err)
|
||||
return
|
||||
}
|
||||
fmt.Printf("\nConsensus state at height %d:\n", clientState.LatestHeight)
|
||||
fmt.Printf(" Timestamp: %s\n", consensus.Timestamp)
|
||||
fmt.Printf(" Root: %s...\n", consensus.Root[:min(20, len(consensus.Root))])
|
||||
fmt.Printf(" Next validators hash: %s...\n", consensus.NextValidatorsHash[:min(20, len(consensus.NextValidatorsHash))])
|
||||
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
func min(a, b int) int {
|
||||
if a < b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func getEnv(key, defaultValue string) string {
|
||||
if value := os.Getenv(key); value != "" {
|
||||
return value
|
||||
}
|
||||
return defaultValue
|
||||
}
|
||||
662
sdk/go/examples/zk_example.go
Normal file
662
sdk/go/examples/zk_example.go
Normal file
|
|
@ -0,0 +1,662 @@
|
|||
// Package main demonstrates the Synor ZK SDK for Go
|
||||
//
|
||||
// This example covers Zero-Knowledge proof operations:
|
||||
// - Circuit compilation
|
||||
// - Proof generation and verification
|
||||
// - Groth16, PLONK, and STARK proving systems
|
||||
// - Recursive proofs
|
||||
// - On-chain verification
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/synor/sdk-go/zk"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Initialize client
|
||||
config := zk.Config{
|
||||
APIKey: getEnv("SYNOR_API_KEY", "your-api-key"),
|
||||
Endpoint: "https://zk.synor.io/v1",
|
||||
Timeout: 120 * time.Second, // ZK ops can be slow
|
||||
Retries: 3,
|
||||
Debug: false,
|
||||
DefaultProvingSystem: zk.ProvingSystemGroth16,
|
||||
}
|
||||
|
||||
client, err := zk.NewClient(config)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to create client: %v", err)
|
||||
}
|
||||
defer client.Close()
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
// Check service health
|
||||
healthy, err := client.HealthCheck(ctx)
|
||||
if err != nil {
|
||||
log.Printf("Health check failed: %v", err)
|
||||
} else {
|
||||
fmt.Printf("Service healthy: %v\n\n", healthy)
|
||||
}
|
||||
|
||||
// Run examples
|
||||
circuitExample(ctx, client)
|
||||
proofExample(ctx, client)
|
||||
provingSystemsExample(ctx, client)
|
||||
recursiveProofExample(ctx, client)
|
||||
onChainVerificationExample(ctx, client)
|
||||
setupExample(ctx, client)
|
||||
}
|
||||
|
||||
func circuitExample(ctx context.Context, client *zk.Client) {
|
||||
fmt.Println("=== Circuit Compilation ===")
|
||||
|
||||
// Circom circuit example: prove knowledge of preimage
|
||||
circomCircuit := `
|
||||
pragma circom 2.1.0;
|
||||
|
||||
template HashPreimage() {
|
||||
signal input preimage;
|
||||
signal input hash;
|
||||
|
||||
// Simplified hash computation (in reality, use proper hash)
|
||||
signal preimageSquared;
|
||||
preimageSquared <== preimage * preimage;
|
||||
|
||||
// Constrain that hash matches
|
||||
hash === preimageSquared;
|
||||
}
|
||||
|
||||
component main {public [hash]} = HashPreimage();
|
||||
`
|
||||
|
||||
// Compile circuit
|
||||
fmt.Println("Compiling Circom circuit...")
|
||||
compiled, err := client.Circuits.Compile(ctx, &zk.CompileRequest{
|
||||
Code: circomCircuit,
|
||||
Format: zk.CircuitFormatCircom,
|
||||
Name: "hash_preimage",
|
||||
ProvingSystem: zk.ProvingSystemGroth16,
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("Failed to compile circuit: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println("Circuit compiled:")
|
||||
fmt.Printf(" Circuit ID: %s\n", compiled.CircuitID)
|
||||
fmt.Printf(" Constraints: %d\n", compiled.ConstraintCount)
|
||||
fmt.Printf(" Public inputs: %d\n", compiled.PublicInputCount)
|
||||
fmt.Printf(" Private inputs: %d\n", compiled.PrivateInputCount)
|
||||
fmt.Printf(" Proving key size: %d bytes\n", compiled.ProvingKeySize)
|
||||
fmt.Printf(" Verification key size: %d bytes\n", compiled.VerificationKeySize)
|
||||
|
||||
// List circuits
|
||||
circuits, err := client.Circuits.List(ctx)
|
||||
if err != nil {
|
||||
log.Printf("Failed to list circuits: %v", err)
|
||||
return
|
||||
}
|
||||
fmt.Printf("\nYour circuits: %d\n", len(circuits))
|
||||
for _, circuit := range circuits {
|
||||
fmt.Printf(" %s (%s)\n", circuit.Name, circuit.CircuitID)
|
||||
}
|
||||
|
||||
// Get circuit details
|
||||
details, err := client.Circuits.Get(ctx, compiled.CircuitID)
|
||||
if err != nil {
|
||||
log.Printf("Failed to get circuit details: %v", err)
|
||||
return
|
||||
}
|
||||
fmt.Println("\nCircuit details:")
|
||||
fmt.Printf(" Format: %s\n", details.Format)
|
||||
fmt.Printf(" Proving system: %s\n", details.ProvingSystem)
|
||||
fmt.Printf(" Created: %s\n", details.CreatedAt)
|
||||
|
||||
// Download proving key
|
||||
provingKey, err := client.Circuits.GetProvingKey(ctx, compiled.CircuitID)
|
||||
if err != nil {
|
||||
log.Printf("Failed to get proving key: %v", err)
|
||||
return
|
||||
}
|
||||
fmt.Printf("\nProving key downloaded: %d bytes\n", len(provingKey))
|
||||
|
||||
// Download verification key
|
||||
verificationKey, err := client.Circuits.GetVerificationKey(ctx, compiled.CircuitID)
|
||||
if err != nil {
|
||||
log.Printf("Failed to get verification key: %v", err)
|
||||
return
|
||||
}
|
||||
fmt.Printf("Verification key downloaded: %d bytes\n", len(verificationKey))
|
||||
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
func proofExample(ctx context.Context, client *zk.Client) {
|
||||
fmt.Println("=== Proof Generation ===")
|
||||
|
||||
// First, compile a simple circuit
|
||||
circuit := `
|
||||
pragma circom 2.1.0;
|
||||
|
||||
template Multiplier() {
|
||||
signal input a;
|
||||
signal input b;
|
||||
signal output c;
|
||||
|
||||
c <== a * b;
|
||||
}
|
||||
|
||||
component main {public [c]} = Multiplier();
|
||||
`
|
||||
|
||||
compiled, err := client.Circuits.Compile(ctx, &zk.CompileRequest{
|
||||
Code: circuit,
|
||||
Format: zk.CircuitFormatCircom,
|
||||
Name: "multiplier",
|
||||
ProvingSystem: zk.ProvingSystemGroth16,
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("Failed to compile circuit: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
// Generate proof
|
||||
fmt.Println("Generating proof...")
|
||||
startTime := time.Now()
|
||||
|
||||
proof, err := client.Proofs.Generate(ctx, &zk.GenerateProofRequest{
|
||||
CircuitID: compiled.CircuitID,
|
||||
Inputs: map[string]string{"a": "3", "b": "7"},
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("Failed to generate proof: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
proofTime := time.Since(startTime)
|
||||
fmt.Printf("Proof generated in %v\n", proofTime)
|
||||
fmt.Printf(" Proof ID: %s\n", proof.ProofID)
|
||||
fmt.Printf(" Proof size: %d bytes\n", len(proof.Proof))
|
||||
fmt.Printf(" Public signals: %v\n", proof.PublicSignals)
|
||||
|
||||
// Verify proof
|
||||
fmt.Println("\nVerifying proof...")
|
||||
verifyStart := time.Now()
|
||||
|
||||
isValid, err := client.Proofs.Verify(ctx, &zk.VerifyRequest{
|
||||
CircuitID: compiled.CircuitID,
|
||||
Proof: proof.Proof,
|
||||
PublicSignals: proof.PublicSignals,
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("Failed to verify proof: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
verifyTime := time.Since(verifyStart)
|
||||
fmt.Printf("Verification completed in %v\n", verifyTime)
|
||||
fmt.Printf(" Valid: %v\n", isValid)
|
||||
|
||||
// Verify with wrong public signals (should fail)
|
||||
fmt.Println("\nVerifying with wrong signals...")
|
||||
invalidResult, err := client.Proofs.Verify(ctx, &zk.VerifyRequest{
|
||||
CircuitID: compiled.CircuitID,
|
||||
Proof: proof.Proof,
|
||||
PublicSignals: []string{"42"}, // Wrong answer
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("Failed to verify with wrong signals: %v", err)
|
||||
return
|
||||
}
|
||||
fmt.Printf(" Valid: %v (expected false)\n", invalidResult)
|
||||
|
||||
// Get proof status
|
||||
status, err := client.Proofs.GetStatus(ctx, proof.ProofID)
|
||||
if err != nil {
|
||||
log.Printf("Failed to get proof status: %v", err)
|
||||
return
|
||||
}
|
||||
fmt.Println("\nProof status:")
|
||||
fmt.Printf(" State: %s\n", status.State)
|
||||
fmt.Printf(" Verified: %v\n", status.Verified)
|
||||
fmt.Printf(" Created: %s\n", status.CreatedAt)
|
||||
|
||||
// List proofs
|
||||
proofs, err := client.Proofs.List(ctx, compiled.CircuitID)
|
||||
if err != nil {
|
||||
log.Printf("Failed to list proofs: %v", err)
|
||||
return
|
||||
}
|
||||
fmt.Printf("\nProofs for circuit: %d\n", len(proofs))
|
||||
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
func provingSystemsExample(ctx context.Context, client *zk.Client) {
|
||||
fmt.Println("=== Proving Systems Comparison ===")
|
||||
|
||||
// Simple circuit for comparison
|
||||
circuit := `
|
||||
pragma circom 2.1.0;
|
||||
|
||||
template Comparison() {
|
||||
signal input x;
|
||||
signal input y;
|
||||
signal output sum;
|
||||
|
||||
sum <== x + y;
|
||||
}
|
||||
|
||||
component main {public [sum]} = Comparison();
|
||||
`
|
||||
|
||||
systems := []struct {
|
||||
system zk.ProvingSystem
|
||||
name string
|
||||
}{
|
||||
{zk.ProvingSystemGroth16, "GROTH16"},
|
||||
{zk.ProvingSystemPLONK, "PLONK"},
|
||||
{zk.ProvingSystemSTARK, "STARK"},
|
||||
}
|
||||
|
||||
fmt.Println("Comparing proving systems:\n")
|
||||
|
||||
for _, s := range systems {
|
||||
fmt.Printf("%s:\n", s.name)
|
||||
|
||||
// Compile for this system
|
||||
compiled, err := client.Circuits.Compile(ctx, &zk.CompileRequest{
|
||||
Code: circuit,
|
||||
Format: zk.CircuitFormatCircom,
|
||||
Name: fmt.Sprintf("comparison_%s", s.name),
|
||||
ProvingSystem: s.system,
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("Failed to compile for %s: %v", s.name, err)
|
||||
continue
|
||||
}
|
||||
|
||||
// Generate proof
|
||||
proofStart := time.Now()
|
||||
proof, err := client.Proofs.Generate(ctx, &zk.GenerateProofRequest{
|
||||
CircuitID: compiled.CircuitID,
|
||||
Inputs: map[string]string{"x": "10", "y": "20"},
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("Failed to generate proof for %s: %v", s.name, err)
|
||||
continue
|
||||
}
|
||||
proofTime := time.Since(proofStart)
|
||||
|
||||
// Verify proof
|
||||
verifyStart := time.Now()
|
||||
_, err = client.Proofs.Verify(ctx, &zk.VerifyRequest{
|
||||
CircuitID: compiled.CircuitID,
|
||||
Proof: proof.Proof,
|
||||
PublicSignals: proof.PublicSignals,
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("Failed to verify proof for %s: %v", s.name, err)
|
||||
continue
|
||||
}
|
||||
verifyTime := time.Since(verifyStart)
|
||||
|
||||
fmt.Printf(" Setup: %dms\n", compiled.SetupTime)
|
||||
fmt.Printf(" Proof time: %v\n", proofTime)
|
||||
fmt.Printf(" Verify time: %v\n", verifyTime)
|
||||
fmt.Printf(" Proof size: %d bytes\n", len(proof.Proof))
|
||||
fmt.Printf(" Verification key: %d bytes\n", compiled.VerificationKeySize)
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
fmt.Println("Summary:")
|
||||
fmt.Println(" Groth16: Smallest proofs, fast verification, trusted setup required")
|
||||
fmt.Println(" PLONK: Universal setup, flexible, moderate proof size")
|
||||
fmt.Println(" STARK: No trusted setup, largest proofs, quantum resistant")
|
||||
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
func recursiveProofExample(ctx context.Context, client *zk.Client) {
|
||||
fmt.Println("=== Recursive Proofs ===")
|
||||
|
||||
// Inner circuit
|
||||
innerCircuit := `
|
||||
pragma circom 2.1.0;
|
||||
|
||||
template Inner() {
|
||||
signal input x;
|
||||
signal output y;
|
||||
y <== x * x;
|
||||
}
|
||||
|
||||
component main {public [y]} = Inner();
|
||||
`
|
||||
|
||||
// Compile inner circuit
|
||||
inner, err := client.Circuits.Compile(ctx, &zk.CompileRequest{
|
||||
Code: innerCircuit,
|
||||
Format: zk.CircuitFormatCircom,
|
||||
Name: "inner_circuit",
|
||||
ProvingSystem: zk.ProvingSystemGroth16,
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("Failed to compile inner circuit: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
// Generate multiple proofs to aggregate
|
||||
fmt.Println("Generating proofs to aggregate...")
|
||||
var proofsToAggregate []zk.ProofData
|
||||
for i := 1; i <= 4; i++ {
|
||||
proof, err := client.Proofs.Generate(ctx, &zk.GenerateProofRequest{
|
||||
CircuitID: inner.CircuitID,
|
||||
Inputs: map[string]string{"x": fmt.Sprintf("%d", i)},
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("Failed to generate proof %d: %v", i, err)
|
||||
continue
|
||||
}
|
||||
proofsToAggregate = append(proofsToAggregate, zk.ProofData{
|
||||
Proof: proof.Proof,
|
||||
PublicSignals: proof.PublicSignals,
|
||||
})
|
||||
fmt.Printf(" Proof %d: y = %s\n", i, proof.PublicSignals[0])
|
||||
}
|
||||
|
||||
// Aggregate proofs recursively
|
||||
fmt.Println("\nAggregating proofs...")
|
||||
aggregated, err := client.Proofs.Aggregate(ctx, &zk.AggregateRequest{
|
||||
CircuitID: inner.CircuitID,
|
||||
Proofs: proofsToAggregate,
|
||||
AggregationType: "recursive",
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("Failed to aggregate proofs: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
originalSize := 0
|
||||
for _, p := range proofsToAggregate {
|
||||
originalSize += len(p.Proof)
|
||||
}
|
||||
|
||||
fmt.Println("Aggregated proof:")
|
||||
fmt.Printf(" Proof ID: %s\n", aggregated.ProofID)
|
||||
fmt.Printf(" Aggregated count: %d\n", aggregated.AggregatedCount)
|
||||
fmt.Printf(" Proof size: %d bytes\n", len(aggregated.Proof))
|
||||
fmt.Printf(" Size reduction: %.1f%%\n", (1-float64(len(aggregated.Proof))/float64(originalSize))*100)
|
||||
|
||||
// Verify aggregated proof
|
||||
publicSignalsList := make([][]string, len(proofsToAggregate))
|
||||
for i, p := range proofsToAggregate {
|
||||
publicSignalsList[i] = p.PublicSignals
|
||||
}
|
||||
|
||||
isValid, err := client.Proofs.VerifyAggregated(ctx, &zk.VerifyAggregatedRequest{
|
||||
CircuitID: inner.CircuitID,
|
||||
Proof: aggregated.Proof,
|
||||
PublicSignalsList: publicSignalsList,
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("Failed to verify aggregated proof: %v", err)
|
||||
return
|
||||
}
|
||||
fmt.Printf("\nAggregated proof valid: %v\n", isValid)
|
||||
|
||||
// Batch verification (verify multiple proofs in one operation)
|
||||
fmt.Println("\nBatch verification...")
|
||||
batchResult, err := client.Proofs.BatchVerify(ctx, &zk.BatchVerifyRequest{
|
||||
CircuitID: inner.CircuitID,
|
||||
Proofs: proofsToAggregate,
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("Failed to batch verify: %v", err)
|
||||
return
|
||||
}
|
||||
fmt.Printf(" All valid: %v\n", batchResult.AllValid)
|
||||
fmt.Printf(" Results: %v\n", batchResult.Results)
|
||||
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
func onChainVerificationExample(ctx context.Context, client *zk.Client) {
|
||||
fmt.Println("=== On-Chain Verification ===")
|
||||
|
||||
// Compile circuit
|
||||
circuit := `
|
||||
pragma circom 2.1.0;
|
||||
|
||||
template VoteCommitment() {
|
||||
signal input vote; // Private: actual vote
|
||||
signal input nullifier; // Private: unique identifier
|
||||
signal input commitment; // Public: commitment to verify
|
||||
|
||||
// Simplified commitment (in practice, use Poseidon hash)
|
||||
signal computed;
|
||||
computed <== vote * nullifier;
|
||||
commitment === computed;
|
||||
}
|
||||
|
||||
component main {public [commitment]} = VoteCommitment();
|
||||
`
|
||||
|
||||
compiled, err := client.Circuits.Compile(ctx, &zk.CompileRequest{
|
||||
Code: circuit,
|
||||
Format: zk.CircuitFormatCircom,
|
||||
Name: "vote_commitment",
|
||||
ProvingSystem: zk.ProvingSystemGroth16,
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("Failed to compile circuit: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
// Generate Solidity verifier
|
||||
fmt.Println("Generating Solidity verifier...")
|
||||
solidityVerifier, err := client.Contracts.GenerateVerifier(ctx, &zk.GenerateVerifierRequest{
|
||||
CircuitID: compiled.CircuitID,
|
||||
Language: "solidity",
|
||||
Optimized: true,
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("Failed to generate verifier: %v", err)
|
||||
return
|
||||
}
|
||||
fmt.Printf("Solidity verifier generated: %d bytes\n", len(solidityVerifier.Code))
|
||||
fmt.Printf(" Contract name: %s\n", solidityVerifier.ContractName)
|
||||
fmt.Printf(" Gas estimate: %d\n", solidityVerifier.GasEstimate)
|
||||
|
||||
// Generate proof
|
||||
proof, err := client.Proofs.Generate(ctx, &zk.GenerateProofRequest{
|
||||
CircuitID: compiled.CircuitID,
|
||||
Inputs: map[string]string{
|
||||
"vote": "1", // Vote YES (1) or NO (0)
|
||||
"nullifier": "12345",
|
||||
"commitment": "12345", // 1 * 12345
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("Failed to generate proof: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
// Format proof for on-chain verification
|
||||
fmt.Println("\nFormatting proof for on-chain...")
|
||||
onChainProof, err := client.Contracts.FormatProof(ctx, &zk.FormatProofRequest{
|
||||
CircuitID: compiled.CircuitID,
|
||||
Proof: proof.Proof,
|
||||
PublicSignals: proof.PublicSignals,
|
||||
Format: "calldata",
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("Failed to format proof: %v", err)
|
||||
return
|
||||
}
|
||||
calldataPreview := onChainProof.Calldata
|
||||
if len(calldataPreview) > 100 {
|
||||
calldataPreview = calldataPreview[:100]
|
||||
}
|
||||
fmt.Printf(" Calldata: %s...\n", calldataPreview)
|
||||
fmt.Printf(" Estimated gas: %d\n", onChainProof.GasEstimate)
|
||||
|
||||
// Deploy verifier contract (simulation)
|
||||
fmt.Println("\nDeploying verifier contract...")
|
||||
deployment, err := client.Contracts.DeployVerifier(ctx, &zk.DeployRequest{
|
||||
CircuitID: compiled.CircuitID,
|
||||
Network: "synor-testnet",
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("Failed to deploy verifier: %v", err)
|
||||
return
|
||||
}
|
||||
fmt.Printf(" Contract address: %s\n", deployment.Address)
|
||||
fmt.Printf(" TX hash: %s\n", deployment.TxHash)
|
||||
fmt.Printf(" Gas used: %d\n", deployment.GasUsed)
|
||||
|
||||
// Verify on-chain
|
||||
fmt.Println("\nVerifying on-chain...")
|
||||
onChainResult, err := client.Contracts.VerifyOnChain(ctx, &zk.OnChainVerifyRequest{
|
||||
ContractAddress: deployment.Address,
|
||||
Proof: proof.Proof,
|
||||
PublicSignals: proof.PublicSignals,
|
||||
Network: "synor-testnet",
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("Failed to verify on-chain: %v", err)
|
||||
return
|
||||
}
|
||||
fmt.Printf(" TX hash: %s\n", onChainResult.TxHash)
|
||||
fmt.Printf(" Verified: %v\n", onChainResult.Verified)
|
||||
fmt.Printf(" Gas used: %d\n", onChainResult.GasUsed)
|
||||
|
||||
// Generate verifier for other targets
|
||||
fmt.Println("\nGenerating verifiers for other targets:")
|
||||
targets := []string{"cairo", "noir", "ink"}
|
||||
for _, target := range targets {
|
||||
verifier, err := client.Contracts.GenerateVerifier(ctx, &zk.GenerateVerifierRequest{
|
||||
CircuitID: compiled.CircuitID,
|
||||
Language: target,
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("Failed to generate %s verifier: %v", target, err)
|
||||
continue
|
||||
}
|
||||
fmt.Printf(" %s: %d bytes\n", target, len(verifier.Code))
|
||||
}
|
||||
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
func setupExample(ctx context.Context, client *zk.Client) {
|
||||
fmt.Println("=== Trusted Setup ===")
|
||||
|
||||
// Get available ceremonies
|
||||
ceremonies, err := client.Setup.ListCeremonies(ctx)
|
||||
if err != nil {
|
||||
log.Printf("Failed to list ceremonies: %v", err)
|
||||
return
|
||||
}
|
||||
fmt.Printf("Active ceremonies: %d\n", len(ceremonies))
|
||||
for _, ceremony := range ceremonies {
|
||||
fmt.Printf(" %s:\n", ceremony.Name)
|
||||
fmt.Printf(" Status: %s\n", ceremony.Status)
|
||||
fmt.Printf(" Participants: %d\n", ceremony.ParticipantCount)
|
||||
fmt.Printf(" Current round: %d\n", ceremony.CurrentRound)
|
||||
}
|
||||
|
||||
// Create a new circuit setup
|
||||
circuit := `
|
||||
pragma circom 2.1.0;
|
||||
|
||||
template NewCircuit() {
|
||||
signal input a;
|
||||
signal output b;
|
||||
b <== a + 1;
|
||||
}
|
||||
|
||||
component main {public [b]} = NewCircuit();
|
||||
`
|
||||
|
||||
fmt.Println("\nInitializing setup for new circuit...")
|
||||
setup, err := client.Setup.Initialize(ctx, &zk.SetupInitRequest{
|
||||
Circuit: circuit,
|
||||
Format: zk.CircuitFormatCircom,
|
||||
Name: "new_circuit_setup",
|
||||
ProvingSystem: zk.ProvingSystemGroth16,
|
||||
CeremonyType: "powers_of_tau", // or 'phase2'
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("Failed to initialize setup: %v", err)
|
||||
return
|
||||
}
|
||||
fmt.Println("Setup initialized:")
|
||||
fmt.Printf(" Ceremony ID: %s\n", setup.CeremonyID)
|
||||
fmt.Printf(" Powers of Tau required: %d\n", setup.PowersRequired)
|
||||
fmt.Printf(" Current phase: %s\n", setup.Phase)
|
||||
|
||||
// Contribute to ceremony (in practice, generates random entropy)
|
||||
fmt.Println("\nContributing to ceremony...")
|
||||
contribution, err := client.Setup.Contribute(ctx, &zk.ContributeRequest{
|
||||
CeremonyID: setup.CeremonyID,
|
||||
Entropy: fmt.Sprintf("%x", []byte("random-entropy-from-user")),
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("Failed to contribute: %v", err)
|
||||
return
|
||||
}
|
||||
fmt.Println("Contribution submitted:")
|
||||
fmt.Printf(" Participant: %s\n", contribution.ParticipantID)
|
||||
fmt.Printf(" Contribution hash: %s\n", contribution.Hash)
|
||||
fmt.Printf(" Verification status: %v\n", contribution.Verified)
|
||||
|
||||
// Get ceremony status
|
||||
status, err := client.Setup.GetStatus(ctx, setup.CeremonyID)
|
||||
if err != nil {
|
||||
log.Printf("Failed to get ceremony status: %v", err)
|
||||
return
|
||||
}
|
||||
fmt.Println("\nCeremony status:")
|
||||
fmt.Printf(" Phase: %s\n", status.Phase)
|
||||
fmt.Printf(" Total contributions: %d\n", status.TotalContributions)
|
||||
fmt.Printf(" Verified contributions: %d\n", status.VerifiedContributions)
|
||||
fmt.Printf(" Ready for finalization: %v\n", status.ReadyForFinalization)
|
||||
|
||||
// Finalize setup (when enough contributions)
|
||||
if status.ReadyForFinalization {
|
||||
fmt.Println("\nFinalizing setup...")
|
||||
finalized, err := client.Setup.Finalize(ctx, setup.CeremonyID)
|
||||
if err != nil {
|
||||
log.Printf("Failed to finalize setup: %v", err)
|
||||
return
|
||||
}
|
||||
fmt.Println("Setup finalized:")
|
||||
fmt.Printf(" Proving key hash: %s\n", finalized.ProvingKeyHash)
|
||||
fmt.Printf(" Verification key hash: %s\n", finalized.VerificationKeyHash)
|
||||
fmt.Printf(" Contribution transcript: %s\n", finalized.TranscriptCID)
|
||||
}
|
||||
|
||||
// Download ceremony transcript
|
||||
transcript, err := client.Setup.GetTranscript(ctx, setup.CeremonyID)
|
||||
if err != nil {
|
||||
log.Printf("Failed to get transcript: %v", err)
|
||||
return
|
||||
}
|
||||
fmt.Printf("\nCeremony transcript: %d bytes\n", len(transcript))
|
||||
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
func getEnv(key, defaultValue string) string {
|
||||
if value := os.Getenv(key); value != "" {
|
||||
return value
|
||||
}
|
||||
return defaultValue
|
||||
}
|
||||
249
sdk/java/examples/CryptoExample.java
Normal file
249
sdk/java/examples/CryptoExample.java
Normal file
|
|
@ -0,0 +1,249 @@
|
|||
package io.synor.examples;
|
||||
|
||||
import io.synor.crypto.*;
|
||||
import io.synor.crypto.types.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
/**
|
||||
* Synor Crypto SDK Examples for Java
|
||||
*
|
||||
* Demonstrates quantum-resistant cryptographic operations:
|
||||
* - Hybrid Ed25519 + Dilithium3 signatures
|
||||
* - BIP-39 mnemonic generation and validation
|
||||
* - Post-quantum algorithms (Falcon, SPHINCS+)
|
||||
* - Key derivation functions
|
||||
*/
|
||||
public class CryptoExample {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
// Initialize client
|
||||
CryptoConfig config = CryptoConfig.builder()
|
||||
.apiKey(System.getenv("SYNOR_API_KEY") != null ?
|
||||
System.getenv("SYNOR_API_KEY") : "your-api-key")
|
||||
.endpoint("https://crypto.synor.io/v1")
|
||||
.timeout(30000)
|
||||
.retries(3)
|
||||
.debug(false)
|
||||
.defaultNetwork(Network.MAINNET)
|
||||
.build();
|
||||
|
||||
SynorCrypto crypto = new SynorCrypto(config);
|
||||
|
||||
try {
|
||||
// Check service health
|
||||
boolean healthy = crypto.healthCheck().get();
|
||||
System.out.println("Service healthy: " + healthy + "\n");
|
||||
|
||||
// Run examples
|
||||
mnemonicExample(crypto);
|
||||
keypairExample(crypto);
|
||||
signingExample(crypto);
|
||||
falconExample(crypto);
|
||||
sphincsExample(crypto);
|
||||
kdfExample(crypto);
|
||||
hashExample(crypto);
|
||||
} finally {
|
||||
crypto.close();
|
||||
}
|
||||
}
|
||||
|
||||
static void mnemonicExample(SynorCrypto crypto) throws Exception {
|
||||
System.out.println("=== Mnemonic Operations ===");
|
||||
|
||||
// Generate a 24-word mnemonic (256-bit entropy)
|
||||
Mnemonic mnemonic = crypto.mnemonic().generate(24).get();
|
||||
System.out.println("Generated mnemonic: " + mnemonic.getPhrase());
|
||||
System.out.println("Word count: " + mnemonic.getWordCount());
|
||||
|
||||
// Validate a mnemonic
|
||||
ValidationResult validation = crypto.mnemonic().validate(mnemonic.getPhrase()).get();
|
||||
System.out.println("Valid: " + validation.isValid());
|
||||
if (!validation.isValid()) {
|
||||
System.out.println("Error: " + validation.getError());
|
||||
}
|
||||
|
||||
// Convert mnemonic to seed
|
||||
byte[] seed = crypto.mnemonic().toSeed(mnemonic.getPhrase(), "optional-passphrase").get();
|
||||
System.out.println("Seed (hex): " + bytesToHex(seed).substring(0, 32) + "...");
|
||||
|
||||
// Word suggestions for autocomplete
|
||||
List<String> suggestions = crypto.mnemonic().suggestWords("aban", 5).get();
|
||||
System.out.println("Suggestions for 'aban': " + String.join(", ", suggestions));
|
||||
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
static void keypairExample(SynorCrypto crypto) throws Exception {
|
||||
System.out.println("=== Keypair Operations ===");
|
||||
|
||||
// Generate a random keypair
|
||||
HybridKeypair keypair = crypto.keypairs().generate().get();
|
||||
System.out.println("Generated hybrid keypair:");
|
||||
System.out.println(" Ed25519 public key size: " + keypair.getPublicKey().getEd25519Bytes().length + " bytes");
|
||||
System.out.println(" Dilithium public key size: " + keypair.getPublicKey().getDilithiumBytes().length + " bytes");
|
||||
System.out.println(" Total public key size: " + keypair.getPublicKey().getSize() + " bytes");
|
||||
|
||||
// Get addresses for different networks
|
||||
System.out.println("\nAddresses:");
|
||||
System.out.println(" Mainnet: " + keypair.getAddress(Network.MAINNET));
|
||||
System.out.println(" Testnet: " + keypair.getAddress(Network.TESTNET));
|
||||
System.out.println(" Devnet: " + keypair.getAddress(Network.DEVNET));
|
||||
|
||||
// Create keypair from mnemonic (deterministic)
|
||||
Mnemonic mnemonic = crypto.mnemonic().generate(24).get();
|
||||
HybridKeypair keypair2 = crypto.keypairs().fromMnemonic(mnemonic.getPhrase(), "").get();
|
||||
String addr = keypair2.getAddress(Network.MAINNET);
|
||||
System.out.println("\nKeypair from mnemonic: " + addr.substring(0, 20) + "...");
|
||||
|
||||
// Derive child keypair using BIP-44 path
|
||||
DerivationPath path = DerivationPath.external(0, 0); // m/44'/21337'/0'/0/0
|
||||
System.out.println("Derivation path: " + path);
|
||||
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
static void signingExample(SynorCrypto crypto) throws Exception {
|
||||
System.out.println("=== Hybrid Signing ===");
|
||||
|
||||
// Generate keypair
|
||||
HybridKeypair keypair = crypto.keypairs().generate().get();
|
||||
|
||||
// Sign a message
|
||||
byte[] message = "Hello, quantum-resistant world!".getBytes();
|
||||
HybridSignature signature = crypto.signing().sign(keypair, message).get();
|
||||
|
||||
System.out.println("Signature created:");
|
||||
System.out.println(" Ed25519 component: " + signature.getEd25519Bytes().length + " bytes");
|
||||
System.out.println(" Dilithium component: " + signature.getDilithiumBytes().length + " bytes");
|
||||
System.out.println(" Total signature size: " + signature.getSize() + " bytes");
|
||||
|
||||
// Verify the signature
|
||||
boolean valid = crypto.signing().verify(keypair.getPublicKey(), message, signature).get();
|
||||
System.out.println("\nVerification result: " + valid);
|
||||
|
||||
// Verify with tampered message fails
|
||||
byte[] tamperedMessage = "Hello, tampered message!".getBytes();
|
||||
boolean invalidResult = crypto.signing().verify(keypair.getPublicKey(), tamperedMessage, signature).get();
|
||||
System.out.println("Tampered message verification: " + invalidResult);
|
||||
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
static void falconExample(SynorCrypto crypto) throws Exception {
|
||||
System.out.println("=== Falcon Post-Quantum Signatures ===");
|
||||
|
||||
// Generate Falcon-512 keypair (128-bit security)
|
||||
FalconKeypair falcon512 = crypto.falcon().generate(FalconVariant.FALCON512).get();
|
||||
System.out.println("Falcon-512 keypair:");
|
||||
System.out.println(" Public key: " + falcon512.getPublicKey().getKeyBytes().length + " bytes");
|
||||
System.out.println(" Security level: 128-bit");
|
||||
|
||||
// Generate Falcon-1024 keypair (256-bit security)
|
||||
FalconKeypair falcon1024 = crypto.falcon().generate(FalconVariant.FALCON1024).get();
|
||||
System.out.println("\nFalcon-1024 keypair:");
|
||||
System.out.println(" Public key: " + falcon1024.getPublicKey().getKeyBytes().length + " bytes");
|
||||
System.out.println(" Security level: 256-bit");
|
||||
|
||||
// Sign with Falcon-512
|
||||
byte[] message = "Post-quantum secure message".getBytes();
|
||||
FalconSignature signature = crypto.falcon().sign(falcon512, message).get();
|
||||
System.out.println("\nFalcon-512 signature: " + signature.getSignatureBytes().length + " bytes");
|
||||
|
||||
// Verify
|
||||
boolean valid = crypto.falcon().verify(falcon512.getPublicKey().getKeyBytes(), message, signature).get();
|
||||
System.out.println("Verification: " + valid);
|
||||
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
static void sphincsExample(SynorCrypto crypto) throws Exception {
|
||||
System.out.println("=== SPHINCS+ Hash-Based Signatures ===");
|
||||
|
||||
// SPHINCS+ variants with different security levels
|
||||
Object[][] variants = {
|
||||
{SphincsVariant.SHAKE128S, 128, 7856},
|
||||
{SphincsVariant.SHAKE192S, 192, 16224},
|
||||
{SphincsVariant.SHAKE256S, 256, 29792},
|
||||
};
|
||||
|
||||
// Generate and demonstrate each variant
|
||||
for (Object[] v : variants) {
|
||||
SphincsVariant variant = (SphincsVariant) v[0];
|
||||
int security = (int) v[1];
|
||||
int sigSize = (int) v[2];
|
||||
|
||||
SphincsKeypair keypair = crypto.sphincs().generate(variant).get();
|
||||
System.out.println("SPHINCS+ " + variant + ":");
|
||||
System.out.println(" Security level: " + security + "-bit");
|
||||
System.out.println(" Expected signature size: " + sigSize + " bytes");
|
||||
|
||||
// Sign a message
|
||||
byte[] message = "Hash-based quantum security".getBytes();
|
||||
SphincsSignature signature = crypto.sphincs().sign(keypair, message).get();
|
||||
System.out.println(" Actual signature size: " + signature.getSignatureBytes().length + " bytes");
|
||||
|
||||
// Verify
|
||||
boolean valid = crypto.sphincs().verify(keypair.getPublicKey().getKeyBytes(), message, signature).get();
|
||||
System.out.println(" Verification: " + valid + "\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void kdfExample(SynorCrypto crypto) throws Exception {
|
||||
System.out.println("=== Key Derivation Functions ===");
|
||||
|
||||
// HKDF (HMAC-based Key Derivation Function)
|
||||
byte[] seed = "master-secret-key-material-here".getBytes();
|
||||
DerivationConfig hkdfConfig = DerivationConfig.builder()
|
||||
.salt("application-salt".getBytes())
|
||||
.info("encryption-key".getBytes())
|
||||
.outputLength(32)
|
||||
.build();
|
||||
|
||||
byte[] derivedKey = crypto.kdf().deriveKey(seed, hkdfConfig).get();
|
||||
System.out.println("HKDF derived key: " + bytesToHex(derivedKey));
|
||||
|
||||
// PBKDF2 (Password-Based Key Derivation Function)
|
||||
byte[] password = "user-password".getBytes();
|
||||
PasswordDerivationConfig pbkdf2Config = PasswordDerivationConfig.builder()
|
||||
.salt("random-salt-value".getBytes())
|
||||
.iterations(100000)
|
||||
.outputLength(32)
|
||||
.build();
|
||||
|
||||
byte[] passwordKey = crypto.kdf().deriveFromPassword(password, pbkdf2Config).get();
|
||||
System.out.println("PBKDF2 derived key: " + bytesToHex(passwordKey));
|
||||
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
static void hashExample(SynorCrypto crypto) throws Exception {
|
||||
System.out.println("=== Hash Functions ===");
|
||||
|
||||
byte[] data = "Data to hash".getBytes();
|
||||
|
||||
// SHA3-256 (FIPS 202)
|
||||
HashResult sha3 = crypto.hash().sha3_256(data).get();
|
||||
System.out.println("SHA3-256: " + sha3.getHex());
|
||||
|
||||
// BLAKE3 (fast, parallel)
|
||||
HashResult blake3 = crypto.hash().blake3(data).get();
|
||||
System.out.println("BLAKE3: " + blake3.getHex());
|
||||
|
||||
// Keccak-256 (Ethereum compatible)
|
||||
HashResult keccak = crypto.hash().keccak256(data).get();
|
||||
System.out.println("Keccak: " + keccak.getHex());
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
393
sdk/js/examples/compiler_example.ts
Normal file
393
sdk/js/examples/compiler_example.ts
Normal file
|
|
@ -0,0 +1,393 @@
|
|||
/**
|
||||
* 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);
|
||||
279
sdk/js/examples/crypto_example.ts
Normal file
279
sdk/js/examples/crypto_example.ts
Normal file
|
|
@ -0,0 +1,279 @@
|
|||
/**
|
||||
* Synor Crypto SDK Examples for JavaScript/TypeScript
|
||||
*
|
||||
* Demonstrates quantum-resistant cryptographic operations including:
|
||||
* - Hybrid Ed25519 + Dilithium3 signatures
|
||||
* - BIP-39 mnemonic generation and validation
|
||||
* - Post-quantum algorithms (Falcon, SPHINCS+)
|
||||
* - Key derivation functions
|
||||
*/
|
||||
|
||||
import {
|
||||
SynorCrypto,
|
||||
CryptoConfig,
|
||||
Network,
|
||||
FalconVariant,
|
||||
SphincsVariant,
|
||||
DerivationConfig,
|
||||
PasswordDerivationConfig,
|
||||
DerivationPath,
|
||||
} from '../src/crypto';
|
||||
|
||||
async function main() {
|
||||
// Initialize client
|
||||
const config: CryptoConfig = {
|
||||
apiKey: process.env.SYNOR_API_KEY || 'your-api-key',
|
||||
endpoint: 'https://crypto.synor.io/v1',
|
||||
timeout: 30000,
|
||||
retries: 3,
|
||||
debug: false,
|
||||
defaultNetwork: Network.Mainnet,
|
||||
};
|
||||
|
||||
const crypto = new SynorCrypto(config);
|
||||
|
||||
try {
|
||||
// Check service health
|
||||
const healthy = await crypto.healthCheck();
|
||||
console.log(`Service healthy: ${healthy}\n`);
|
||||
|
||||
// Example 1: Mnemonic operations
|
||||
await mnemonicExample(crypto);
|
||||
|
||||
// Example 2: Keypair generation
|
||||
await keypairExample(crypto);
|
||||
|
||||
// Example 3: Hybrid signing
|
||||
await signingExample(crypto);
|
||||
|
||||
// Example 4: Falcon post-quantum signatures
|
||||
await falconExample(crypto);
|
||||
|
||||
// Example 5: SPHINCS+ post-quantum signatures
|
||||
await sphincsExample(crypto);
|
||||
|
||||
// Example 6: Key derivation
|
||||
await kdfExample(crypto);
|
||||
|
||||
// Example 7: Hashing
|
||||
await hashExample(crypto);
|
||||
} finally {
|
||||
crypto.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Mnemonic generation and validation
|
||||
*/
|
||||
async function mnemonicExample(crypto: SynorCrypto): Promise<void> {
|
||||
console.log('=== Mnemonic Operations ===');
|
||||
|
||||
// Generate a 24-word mnemonic (256-bit entropy)
|
||||
const mnemonic = await crypto.mnemonic.generate(24);
|
||||
console.log(`Generated mnemonic: ${mnemonic.phrase}`);
|
||||
console.log(`Word count: ${mnemonic.wordCount}`);
|
||||
|
||||
// Validate a mnemonic
|
||||
const validation = await crypto.mnemonic.validate(mnemonic.phrase);
|
||||
console.log(`Valid: ${validation.valid}`);
|
||||
if (!validation.valid) {
|
||||
console.log(`Error: ${validation.error}`);
|
||||
}
|
||||
|
||||
// Convert mnemonic to seed
|
||||
const seed = await crypto.mnemonic.toSeed(mnemonic.phrase, 'optional-passphrase');
|
||||
console.log(`Seed (hex): ${Buffer.from(seed).toString('hex').slice(0, 32)}...`);
|
||||
|
||||
// Word suggestions for autocomplete
|
||||
const suggestions = await crypto.mnemonic.suggestWords('aban', 5);
|
||||
console.log(`Suggestions for "aban": ${suggestions.join(', ')}`);
|
||||
|
||||
console.log('');
|
||||
}
|
||||
|
||||
/**
|
||||
* Keypair generation and address derivation
|
||||
*/
|
||||
async function keypairExample(crypto: SynorCrypto): Promise<void> {
|
||||
console.log('=== Keypair Operations ===');
|
||||
|
||||
// Generate a random keypair
|
||||
const keypair = await crypto.keypairs.generate();
|
||||
console.log('Generated hybrid keypair:');
|
||||
console.log(` Ed25519 public key size: ${keypair.publicKey.ed25519Bytes.length} bytes`);
|
||||
console.log(` Dilithium public key size: ${keypair.publicKey.dilithiumBytes.length} bytes`);
|
||||
console.log(` Total public key size: ${keypair.publicKey.size} bytes`);
|
||||
|
||||
// Get addresses for different networks
|
||||
console.log('\nAddresses:');
|
||||
console.log(` Mainnet: ${keypair.getAddress(Network.Mainnet)}`);
|
||||
console.log(` Testnet: ${keypair.getAddress(Network.Testnet)}`);
|
||||
console.log(` Devnet: ${keypair.getAddress(Network.Devnet)}`);
|
||||
|
||||
// Create keypair from mnemonic (deterministic)
|
||||
const mnemonic = await crypto.mnemonic.generate(24);
|
||||
const keypair2 = await crypto.keypairs.fromMnemonic(mnemonic.phrase, '');
|
||||
console.log(`\nKeypair from mnemonic: ${keypair2.getAddress(Network.Mainnet).slice(0, 20)}...`);
|
||||
|
||||
// Derive child keypair using BIP-44 path
|
||||
const path = DerivationPath.external(0, 0); // m/44'/21337'/0'/0/0
|
||||
console.log(`Derivation path: ${path.toString()}`);
|
||||
|
||||
console.log('');
|
||||
}
|
||||
|
||||
/**
|
||||
* Hybrid signature operations (Ed25519 + Dilithium3)
|
||||
*/
|
||||
async function signingExample(crypto: SynorCrypto): Promise<void> {
|
||||
console.log('=== Hybrid Signing ===');
|
||||
|
||||
// Generate keypair
|
||||
const keypair = await crypto.keypairs.generate();
|
||||
|
||||
// Sign a message
|
||||
const message = Buffer.from('Hello, quantum-resistant world!');
|
||||
const signature = await crypto.signing.sign(keypair, message);
|
||||
|
||||
console.log('Signature created:');
|
||||
console.log(` Ed25519 component: ${signature.ed25519Bytes.length} bytes`);
|
||||
console.log(` Dilithium component: ${signature.dilithiumBytes.length} bytes`);
|
||||
console.log(` Total signature size: ${signature.size} bytes`);
|
||||
|
||||
// Verify the signature
|
||||
const valid = await crypto.signing.verify(keypair.publicKey, message, signature);
|
||||
console.log(`\nVerification result: ${valid}`);
|
||||
|
||||
// Verify with tampered message fails
|
||||
const tamperedMessage = Buffer.from('Hello, tampered message!');
|
||||
const invalidResult = await crypto.signing.verify(keypair.publicKey, tamperedMessage, signature);
|
||||
console.log(`Tampered message verification: ${invalidResult}`);
|
||||
|
||||
console.log('');
|
||||
}
|
||||
|
||||
/**
|
||||
* Falcon post-quantum signature example
|
||||
*/
|
||||
async function falconExample(crypto: SynorCrypto): Promise<void> {
|
||||
console.log('=== Falcon Post-Quantum Signatures ===');
|
||||
|
||||
// Generate Falcon-512 keypair (128-bit security)
|
||||
const falcon512 = await crypto.falcon.generate(FalconVariant.Falcon512);
|
||||
console.log('Falcon-512 keypair:');
|
||||
console.log(` Public key: ${falcon512.publicKey.bytes.length} bytes`);
|
||||
console.log(` Security level: 128-bit`);
|
||||
|
||||
// Generate Falcon-1024 keypair (256-bit security)
|
||||
const falcon1024 = await crypto.falcon.generate(FalconVariant.Falcon1024);
|
||||
console.log('\nFalcon-1024 keypair:');
|
||||
console.log(` Public key: ${falcon1024.publicKey.bytes.length} bytes`);
|
||||
console.log(` Security level: 256-bit`);
|
||||
|
||||
// Sign with Falcon-512
|
||||
const message = Buffer.from('Post-quantum secure message');
|
||||
const signature = await crypto.falcon.sign(falcon512, message);
|
||||
console.log(`\nFalcon-512 signature: ${signature.signatureBytes.length} bytes`);
|
||||
|
||||
// Verify
|
||||
const valid = await crypto.falcon.verify(
|
||||
falcon512.publicKey.bytes,
|
||||
message,
|
||||
signature
|
||||
);
|
||||
console.log(`Verification: ${valid}`);
|
||||
|
||||
console.log('');
|
||||
}
|
||||
|
||||
/**
|
||||
* SPHINCS+ post-quantum signature example (hash-based)
|
||||
*/
|
||||
async function sphincsExample(crypto: SynorCrypto): Promise<void> {
|
||||
console.log('=== SPHINCS+ Hash-Based Signatures ===');
|
||||
|
||||
// SPHINCS+ variants with different security levels
|
||||
const variants = [
|
||||
{ variant: SphincsVariant.Shake128s, security: 128, sigSize: 7856 },
|
||||
{ variant: SphincsVariant.Shake192s, security: 192, sigSize: 16224 },
|
||||
{ variant: SphincsVariant.Shake256s, security: 256, sigSize: 29792 },
|
||||
];
|
||||
|
||||
// Generate and demonstrate each variant
|
||||
for (const { variant, security, sigSize } of variants) {
|
||||
const keypair = await crypto.sphincs.generate(variant);
|
||||
console.log(`SPHINCS+ ${variant}:`);
|
||||
console.log(` Security level: ${security}-bit`);
|
||||
console.log(` Expected signature size: ${sigSize} bytes`);
|
||||
|
||||
// Sign a message
|
||||
const message = Buffer.from('Hash-based quantum security');
|
||||
const signature = await crypto.sphincs.sign(keypair, message);
|
||||
console.log(` Actual signature size: ${signature.signatureBytes.length} bytes`);
|
||||
|
||||
// Verify
|
||||
const valid = await crypto.sphincs.verify(
|
||||
keypair.publicKey.bytes,
|
||||
message,
|
||||
signature
|
||||
);
|
||||
console.log(` Verification: ${valid}\n`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Key derivation functions
|
||||
*/
|
||||
async function kdfExample(crypto: SynorCrypto): Promise<void> {
|
||||
console.log('=== Key Derivation Functions ===');
|
||||
|
||||
// HKDF (HMAC-based Key Derivation Function)
|
||||
const seed = Buffer.from('master-secret-key-material-here');
|
||||
const hkdfConfig: DerivationConfig = {
|
||||
salt: Buffer.from('application-salt'),
|
||||
info: Buffer.from('encryption-key'),
|
||||
outputLength: 32,
|
||||
};
|
||||
|
||||
const derivedKey = await crypto.kdf.deriveKey(seed, hkdfConfig);
|
||||
console.log(`HKDF derived key: ${Buffer.from(derivedKey).toString('hex')}`);
|
||||
|
||||
// PBKDF2 (Password-Based Key Derivation Function)
|
||||
const password = Buffer.from('user-password');
|
||||
const pbkdf2Config: PasswordDerivationConfig = {
|
||||
salt: Buffer.from('random-salt-value'),
|
||||
iterations: 100000,
|
||||
outputLength: 32,
|
||||
};
|
||||
|
||||
const passwordKey = await crypto.kdf.deriveFromPassword(password, pbkdf2Config);
|
||||
console.log(`PBKDF2 derived key: ${Buffer.from(passwordKey).toString('hex')}`);
|
||||
|
||||
console.log('');
|
||||
}
|
||||
|
||||
/**
|
||||
* Cryptographic hash functions
|
||||
*/
|
||||
async function hashExample(crypto: SynorCrypto): Promise<void> {
|
||||
console.log('=== Hash Functions ===');
|
||||
|
||||
const data = Buffer.from('Data to hash');
|
||||
|
||||
// SHA3-256 (FIPS 202)
|
||||
const sha3 = await crypto.hash.sha3_256(data);
|
||||
console.log(`SHA3-256: ${sha3.hex}`);
|
||||
|
||||
// BLAKE3 (fast, parallel)
|
||||
const blake3 = await crypto.hash.blake3(data);
|
||||
console.log(`BLAKE3: ${blake3.hex}`);
|
||||
|
||||
// Keccak-256 (Ethereum compatible)
|
||||
const keccak = await crypto.hash.keccak256(data);
|
||||
console.log(`Keccak: ${keccak.hex}`);
|
||||
|
||||
console.log('');
|
||||
}
|
||||
|
||||
// Run examples
|
||||
main().catch(console.error);
|
||||
488
sdk/js/examples/dex_example.ts
Normal file
488
sdk/js/examples/dex_example.ts
Normal file
|
|
@ -0,0 +1,488 @@
|
|||
/**
|
||||
* Synor DEX SDK Examples for JavaScript/TypeScript
|
||||
*
|
||||
* Demonstrates decentralized exchange operations:
|
||||
* - Spot trading (market/limit orders)
|
||||
* - Perpetual futures trading
|
||||
* - Liquidity provision
|
||||
* - Order management
|
||||
* - Real-time market data
|
||||
*/
|
||||
|
||||
import {
|
||||
SynorDex,
|
||||
DexConfig,
|
||||
Network,
|
||||
OrderSide,
|
||||
OrderType,
|
||||
TimeInForce,
|
||||
PositionSide,
|
||||
MarginType,
|
||||
} from '../src/dex';
|
||||
|
||||
async function main() {
|
||||
// Initialize client
|
||||
const config: DexConfig = {
|
||||
apiKey: process.env.SYNOR_API_KEY || 'your-api-key',
|
||||
endpoint: 'https://dex.synor.io/v1',
|
||||
wsEndpoint: 'wss://dex.synor.io/v1/ws',
|
||||
timeout: 30000,
|
||||
retries: 3,
|
||||
debug: false,
|
||||
defaultNetwork: Network.Mainnet,
|
||||
};
|
||||
|
||||
const dex = new SynorDex(config);
|
||||
|
||||
try {
|
||||
// Check service health
|
||||
const healthy = await dex.healthCheck();
|
||||
console.log(`Service healthy: ${healthy}\n`);
|
||||
|
||||
// Example 1: Market data
|
||||
await marketDataExample(dex);
|
||||
|
||||
// Example 2: Spot trading
|
||||
await spotTradingExample(dex);
|
||||
|
||||
// Example 3: Perpetual futures
|
||||
await perpetualFuturesExample(dex);
|
||||
|
||||
// Example 4: Liquidity provision
|
||||
await liquidityExample(dex);
|
||||
|
||||
// Example 5: Order management
|
||||
await orderManagementExample(dex);
|
||||
|
||||
// Example 6: Account information
|
||||
await accountExample(dex);
|
||||
|
||||
// Example 7: Real-time streaming
|
||||
await streamingExample(dex);
|
||||
} finally {
|
||||
dex.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Market data and orderbook
|
||||
*/
|
||||
async function marketDataExample(dex: SynorDex): Promise<void> {
|
||||
console.log('=== Market Data ===');
|
||||
|
||||
// Get all trading pairs
|
||||
const pairs = await dex.markets.getPairs();
|
||||
console.log(`Available trading pairs: ${pairs.length}`);
|
||||
for (const pair of pairs.slice(0, 5)) {
|
||||
console.log(` ${pair.symbol}: ${pair.baseAsset}/${pair.quoteAsset}`);
|
||||
}
|
||||
|
||||
// Get ticker for a specific pair
|
||||
const ticker = await dex.markets.getTicker('SYN-USDT');
|
||||
console.log(`\nSYN-USDT Ticker:`);
|
||||
console.log(` Last price: $${ticker.lastPrice}`);
|
||||
console.log(` 24h change: ${ticker.priceChangePercent}%`);
|
||||
console.log(` 24h high: $${ticker.highPrice}`);
|
||||
console.log(` 24h low: $${ticker.lowPrice}`);
|
||||
console.log(` 24h volume: ${ticker.volume} SYN`);
|
||||
console.log(` 24h quote volume: $${ticker.quoteVolume}`);
|
||||
|
||||
// Get orderbook
|
||||
const orderbook = await dex.markets.getOrderbook('SYN-USDT', 10);
|
||||
console.log(`\nOrderbook (top 5):`);
|
||||
console.log(' Bids:');
|
||||
for (const bid of orderbook.bids.slice(0, 5)) {
|
||||
console.log(` $${bid.price} - ${bid.quantity} SYN`);
|
||||
}
|
||||
console.log(' Asks:');
|
||||
for (const ask of orderbook.asks.slice(0, 5)) {
|
||||
console.log(` $${ask.price} - ${ask.quantity} SYN`);
|
||||
}
|
||||
|
||||
// Get recent trades
|
||||
const trades = await dex.markets.getTrades('SYN-USDT', 5);
|
||||
console.log(`\nRecent trades:`);
|
||||
for (const trade of trades) {
|
||||
const side = trade.isBuyerMaker ? 'SELL' : 'BUY';
|
||||
console.log(` ${side} ${trade.quantity} @ $${trade.price}`);
|
||||
}
|
||||
|
||||
// Get OHLCV candles
|
||||
const candles = await dex.markets.getCandles('SYN-USDT', '1h', 5);
|
||||
console.log(`\nHourly candles:`);
|
||||
for (const candle of candles) {
|
||||
console.log(` ${new Date(candle.openTime).toISOString()}: O=${candle.open} H=${candle.high} L=${candle.low} C=${candle.close}`);
|
||||
}
|
||||
|
||||
console.log('');
|
||||
}
|
||||
|
||||
/**
|
||||
* Spot trading operations
|
||||
*/
|
||||
async function spotTradingExample(dex: SynorDex): Promise<void> {
|
||||
console.log('=== Spot Trading ===');
|
||||
|
||||
// Place a market buy order
|
||||
console.log('Placing market buy order...');
|
||||
const marketBuy = await dex.spot.createOrder({
|
||||
symbol: 'SYN-USDT',
|
||||
side: OrderSide.Buy,
|
||||
type: OrderType.Market,
|
||||
quantity: 10, // Buy 10 SYN
|
||||
});
|
||||
console.log(`Market buy order: ${marketBuy.orderId}`);
|
||||
console.log(` Status: ${marketBuy.status}`);
|
||||
console.log(` Filled: ${marketBuy.executedQty} SYN`);
|
||||
console.log(` Avg price: $${marketBuy.avgPrice}`);
|
||||
|
||||
// Place a limit sell order
|
||||
console.log('\nPlacing limit sell order...');
|
||||
const limitSell = await dex.spot.createOrder({
|
||||
symbol: 'SYN-USDT',
|
||||
side: OrderSide.Sell,
|
||||
type: OrderType.Limit,
|
||||
quantity: 5,
|
||||
price: 15.50, // Sell at $15.50
|
||||
timeInForce: TimeInForce.GTC, // Good till cancelled
|
||||
});
|
||||
console.log(`Limit sell order: ${limitSell.orderId}`);
|
||||
console.log(` Price: $${limitSell.price}`);
|
||||
console.log(` Status: ${limitSell.status}`);
|
||||
|
||||
// Place a stop-loss order
|
||||
console.log('\nPlacing stop-loss order...');
|
||||
const stopLoss = await dex.spot.createOrder({
|
||||
symbol: 'SYN-USDT',
|
||||
side: OrderSide.Sell,
|
||||
type: OrderType.StopLoss,
|
||||
quantity: 10,
|
||||
stopPrice: 12.00, // Trigger at $12.00
|
||||
});
|
||||
console.log(`Stop-loss order: ${stopLoss.orderId}`);
|
||||
console.log(` Stop price: $${stopLoss.stopPrice}`);
|
||||
|
||||
// Place a take-profit limit order
|
||||
console.log('\nPlacing take-profit order...');
|
||||
const takeProfit = await dex.spot.createOrder({
|
||||
symbol: 'SYN-USDT',
|
||||
side: OrderSide.Sell,
|
||||
type: OrderType.TakeProfitLimit,
|
||||
quantity: 10,
|
||||
price: 20.00, // Sell at $20.00
|
||||
stopPrice: 19.50, // Trigger at $19.50
|
||||
timeInForce: TimeInForce.GTC,
|
||||
});
|
||||
console.log(`Take-profit order: ${takeProfit.orderId}`);
|
||||
|
||||
console.log('');
|
||||
}
|
||||
|
||||
/**
|
||||
* Perpetual futures trading
|
||||
*/
|
||||
async function perpetualFuturesExample(dex: SynorDex): Promise<void> {
|
||||
console.log('=== Perpetual Futures ===');
|
||||
|
||||
// Get perpetual markets
|
||||
const markets = await dex.perpetuals.getMarkets();
|
||||
console.log(`Available perpetual markets: ${markets.length}`);
|
||||
for (const market of markets.slice(0, 3)) {
|
||||
console.log(` ${market.symbol}: ${market.maxLeverage}x max leverage, ${market.maintenanceMarginRate}% MMR`);
|
||||
}
|
||||
|
||||
// Get funding rate
|
||||
const funding = await dex.perpetuals.getFundingRate('SYN-USDT-PERP');
|
||||
console.log(`\nFunding rate for SYN-USDT-PERP:`);
|
||||
console.log(` Current rate: ${(funding.fundingRate * 100).toFixed(4)}%`);
|
||||
console.log(` Predicted rate: ${(funding.predictedRate * 100).toFixed(4)}%`);
|
||||
console.log(` Next funding: ${new Date(funding.nextFundingTime).toISOString()}`);
|
||||
|
||||
// Set leverage
|
||||
await dex.perpetuals.setLeverage('SYN-USDT-PERP', 10);
|
||||
console.log('\nLeverage set to 10x');
|
||||
|
||||
// Set margin type (isolated/cross)
|
||||
await dex.perpetuals.setMarginType('SYN-USDT-PERP', MarginType.Isolated);
|
||||
console.log('Margin type set to Isolated');
|
||||
|
||||
// Open a long position
|
||||
console.log('\nOpening long position...');
|
||||
const longOrder = await dex.perpetuals.createOrder({
|
||||
symbol: 'SYN-USDT-PERP',
|
||||
side: OrderSide.Buy,
|
||||
positionSide: PositionSide.Long,
|
||||
type: OrderType.Market,
|
||||
quantity: 100, // 100 contracts
|
||||
});
|
||||
console.log(`Long position opened: ${longOrder.orderId}`);
|
||||
console.log(` Entry price: $${longOrder.avgPrice}`);
|
||||
console.log(` Position size: ${longOrder.executedQty} contracts`);
|
||||
|
||||
// Set stop-loss and take-profit
|
||||
console.log('\nSetting SL/TP...');
|
||||
await dex.perpetuals.createOrder({
|
||||
symbol: 'SYN-USDT-PERP',
|
||||
side: OrderSide.Sell,
|
||||
positionSide: PositionSide.Long,
|
||||
type: OrderType.StopMarket,
|
||||
quantity: 100,
|
||||
stopPrice: 12.00, // Stop-loss at $12
|
||||
reduceOnly: true,
|
||||
});
|
||||
console.log(' Stop-loss set at $12.00');
|
||||
|
||||
await dex.perpetuals.createOrder({
|
||||
symbol: 'SYN-USDT-PERP',
|
||||
side: OrderSide.Sell,
|
||||
positionSide: PositionSide.Long,
|
||||
type: OrderType.TakeProfitMarket,
|
||||
quantity: 100,
|
||||
stopPrice: 18.00, // Take-profit at $18
|
||||
reduceOnly: true,
|
||||
});
|
||||
console.log(' Take-profit set at $18.00');
|
||||
|
||||
// Get position info
|
||||
const positions = await dex.perpetuals.getPositions('SYN-USDT-PERP');
|
||||
for (const pos of positions) {
|
||||
console.log(`\nPosition info:`);
|
||||
console.log(` Symbol: ${pos.symbol}`);
|
||||
console.log(` Side: ${pos.positionSide}`);
|
||||
console.log(` Size: ${pos.positionAmount} contracts`);
|
||||
console.log(` Entry: $${pos.entryPrice}`);
|
||||
console.log(` Mark: $${pos.markPrice}`);
|
||||
console.log(` PnL: $${pos.unrealizedPnl} (${pos.unrealizedPnlPercent}%)`);
|
||||
console.log(` Leverage: ${pos.leverage}x`);
|
||||
console.log(` Liq. price: $${pos.liquidationPrice}`);
|
||||
}
|
||||
|
||||
// Close position
|
||||
console.log('\nClosing position...');
|
||||
await dex.perpetuals.closePosition('SYN-USDT-PERP', PositionSide.Long);
|
||||
console.log('Position closed');
|
||||
|
||||
console.log('');
|
||||
}
|
||||
|
||||
/**
|
||||
* Liquidity provision
|
||||
*/
|
||||
async function liquidityExample(dex: SynorDex): Promise<void> {
|
||||
console.log('=== Liquidity Provision ===');
|
||||
|
||||
// Get available pools
|
||||
const pools = await dex.liquidity.getPools();
|
||||
console.log(`Available liquidity pools: ${pools.length}`);
|
||||
for (const pool of pools.slice(0, 3)) {
|
||||
console.log(` ${pool.name}:`);
|
||||
console.log(` TVL: $${pool.tvl.toLocaleString()}`);
|
||||
console.log(` APY: ${pool.apy.toFixed(2)}%`);
|
||||
console.log(` Fee tier: ${pool.feeTier}%`);
|
||||
}
|
||||
|
||||
// Get pool details
|
||||
const pool = await dex.liquidity.getPool('SYN-USDT');
|
||||
console.log(`\nSYN-USDT Pool details:`);
|
||||
console.log(` Reserve A: ${pool.reserveA} SYN`);
|
||||
console.log(` Reserve B: ${pool.reserveB} USDT`);
|
||||
console.log(` Total shares: ${pool.totalShares}`);
|
||||
console.log(` Your shares: ${pool.userShares}`);
|
||||
|
||||
// Add liquidity
|
||||
console.log('\nAdding liquidity...');
|
||||
const addResult = await dex.liquidity.addLiquidity({
|
||||
poolId: 'SYN-USDT',
|
||||
amountA: 100, // 100 SYN
|
||||
amountB: 1400, // 1400 USDT
|
||||
slippageTolerance: 0.5, // 0.5% slippage
|
||||
});
|
||||
console.log(`Liquidity added:`);
|
||||
console.log(` Shares received: ${addResult.sharesReceived}`);
|
||||
console.log(` Amount A deposited: ${addResult.amountADeposited}`);
|
||||
console.log(` Amount B deposited: ${addResult.amountBDeposited}`);
|
||||
|
||||
// Get LP positions
|
||||
const lpPositions = await dex.liquidity.getPositions();
|
||||
console.log(`\nYour LP positions:`);
|
||||
for (const lp of lpPositions) {
|
||||
console.log(` ${lp.poolId}: ${lp.shares} shares ($${lp.valueUsd})`);
|
||||
console.log(` Fees earned: $${lp.feesEarned}`);
|
||||
}
|
||||
|
||||
// Remove liquidity
|
||||
console.log('\nRemoving liquidity...');
|
||||
const removeResult = await dex.liquidity.removeLiquidity({
|
||||
poolId: 'SYN-USDT',
|
||||
shares: addResult.sharesReceived * 0.5, // Remove 50%
|
||||
slippageTolerance: 0.5,
|
||||
});
|
||||
console.log(`Liquidity removed:`);
|
||||
console.log(` Amount A received: ${removeResult.amountAReceived}`);
|
||||
console.log(` Amount B received: ${removeResult.amountBReceived}`);
|
||||
|
||||
console.log('');
|
||||
}
|
||||
|
||||
/**
|
||||
* Order management
|
||||
*/
|
||||
async function orderManagementExample(dex: SynorDex): Promise<void> {
|
||||
console.log('=== Order Management ===');
|
||||
|
||||
// Get open orders
|
||||
const openOrders = await dex.orders.getOpenOrders('SYN-USDT');
|
||||
console.log(`Open orders: ${openOrders.length}`);
|
||||
for (const order of openOrders) {
|
||||
console.log(` ${order.orderId}: ${order.side} ${order.quantity} @ $${order.price}`);
|
||||
}
|
||||
|
||||
// Get order history
|
||||
const history = await dex.orders.getOrderHistory({
|
||||
symbol: 'SYN-USDT',
|
||||
limit: 5,
|
||||
});
|
||||
console.log(`\nOrder history (last 5):`);
|
||||
for (const order of history) {
|
||||
console.log(` ${order.orderId}: ${order.side} ${order.quantity} ${order.status}`);
|
||||
}
|
||||
|
||||
// Get specific order
|
||||
if (openOrders.length > 0) {
|
||||
const order = await dex.orders.getOrder(openOrders[0].orderId);
|
||||
console.log(`\nOrder details:`);
|
||||
console.log(` Symbol: ${order.symbol}`);
|
||||
console.log(` Type: ${order.type}`);
|
||||
console.log(` Side: ${order.side}`);
|
||||
console.log(` Quantity: ${order.quantity}`);
|
||||
console.log(` Filled: ${order.executedQty}`);
|
||||
console.log(` Status: ${order.status}`);
|
||||
}
|
||||
|
||||
// Cancel a specific order
|
||||
if (openOrders.length > 0) {
|
||||
console.log('\nCancelling order...');
|
||||
const cancelled = await dex.orders.cancelOrder(openOrders[0].orderId);
|
||||
console.log(`Order ${cancelled.orderId} cancelled`);
|
||||
}
|
||||
|
||||
// Cancel all orders for a symbol
|
||||
console.log('\nCancelling all SYN-USDT orders...');
|
||||
const cancelledOrders = await dex.orders.cancelAllOrders('SYN-USDT');
|
||||
console.log(`Cancelled ${cancelledOrders.length} orders`);
|
||||
|
||||
// Get trade history
|
||||
const trades = await dex.orders.getTradeHistory({
|
||||
symbol: 'SYN-USDT',
|
||||
limit: 5,
|
||||
});
|
||||
console.log(`\nTrade history (last 5):`);
|
||||
for (const trade of trades) {
|
||||
console.log(` ${trade.side} ${trade.quantity} @ $${trade.price} (fee: $${trade.fee})`);
|
||||
}
|
||||
|
||||
console.log('');
|
||||
}
|
||||
|
||||
/**
|
||||
* Account information
|
||||
*/
|
||||
async function accountExample(dex: SynorDex): Promise<void> {
|
||||
console.log('=== Account Information ===');
|
||||
|
||||
// Get account balances
|
||||
const balances = await dex.account.getBalances();
|
||||
console.log('Balances:');
|
||||
for (const balance of balances.filter(b => parseFloat(b.total) > 0)) {
|
||||
console.log(` ${balance.asset}: ${balance.free} free, ${balance.locked} locked`);
|
||||
}
|
||||
|
||||
// Get account summary
|
||||
const summary = await dex.account.getSummary();
|
||||
console.log(`\nAccount summary:`);
|
||||
console.log(` Total equity: $${summary.totalEquity}`);
|
||||
console.log(` Available margin: $${summary.availableMargin}`);
|
||||
console.log(` Used margin: $${summary.usedMargin}`);
|
||||
console.log(` Margin level: ${summary.marginLevel}%`);
|
||||
console.log(` Unrealized PnL: $${summary.unrealizedPnl}`);
|
||||
|
||||
// Get deposit address
|
||||
const depositAddr = await dex.account.getDepositAddress('SYN');
|
||||
console.log(`\nDeposit address for SYN: ${depositAddr.address}`);
|
||||
|
||||
// Get deposit/withdrawal history
|
||||
const deposits = await dex.account.getDepositHistory({ limit: 3 });
|
||||
console.log(`\nRecent deposits:`);
|
||||
for (const dep of deposits) {
|
||||
console.log(` ${dep.asset}: ${dep.amount} (${dep.status})`);
|
||||
}
|
||||
|
||||
const withdrawals = await dex.account.getWithdrawalHistory({ limit: 3 });
|
||||
console.log(`\nRecent withdrawals:`);
|
||||
for (const wd of withdrawals) {
|
||||
console.log(` ${wd.asset}: ${wd.amount} (${wd.status})`);
|
||||
}
|
||||
|
||||
// Get fee rates
|
||||
const fees = await dex.account.getFeeRates('SYN-USDT');
|
||||
console.log(`\nFee rates for SYN-USDT:`);
|
||||
console.log(` Maker: ${fees.makerRate}%`);
|
||||
console.log(` Taker: ${fees.takerRate}%`);
|
||||
|
||||
console.log('');
|
||||
}
|
||||
|
||||
/**
|
||||
* Real-time WebSocket streaming
|
||||
*/
|
||||
async function streamingExample(dex: SynorDex): Promise<void> {
|
||||
console.log('=== Real-time Streaming ===');
|
||||
|
||||
// Subscribe to ticker updates
|
||||
console.log('Subscribing to SYN-USDT ticker...');
|
||||
const tickerUnsub = dex.streams.subscribeTicker('SYN-USDT', (ticker) => {
|
||||
console.log(` Ticker: $${ticker.lastPrice} (${ticker.priceChangePercent}%)`);
|
||||
});
|
||||
|
||||
// Subscribe to orderbook updates
|
||||
console.log('Subscribing to orderbook...');
|
||||
const orderbookUnsub = dex.streams.subscribeOrderbook('SYN-USDT', (orderbook) => {
|
||||
console.log(` Best bid: $${orderbook.bids[0]?.price}, Best ask: $${orderbook.asks[0]?.price}`);
|
||||
});
|
||||
|
||||
// Subscribe to trades
|
||||
console.log('Subscribing to trades...');
|
||||
const tradesUnsub = dex.streams.subscribeTrades('SYN-USDT', (trade) => {
|
||||
const side = trade.isBuyerMaker ? 'SELL' : 'BUY';
|
||||
console.log(` Trade: ${side} ${trade.quantity} @ $${trade.price}`);
|
||||
});
|
||||
|
||||
// Subscribe to user order updates
|
||||
console.log('Subscribing to order updates...');
|
||||
const orderUnsub = dex.streams.subscribeOrders((order) => {
|
||||
console.log(` Order update: ${order.orderId} ${order.status}`);
|
||||
});
|
||||
|
||||
// Subscribe to position updates
|
||||
console.log('Subscribing to position updates...');
|
||||
const positionUnsub = dex.streams.subscribePositions((position) => {
|
||||
console.log(` Position update: ${position.symbol} PnL: $${position.unrealizedPnl}`);
|
||||
});
|
||||
|
||||
// Wait for some updates
|
||||
console.log('\nListening for 5 seconds...');
|
||||
await new Promise(resolve => setTimeout(resolve, 5000));
|
||||
|
||||
// Unsubscribe
|
||||
tickerUnsub();
|
||||
orderbookUnsub();
|
||||
tradesUnsub();
|
||||
orderUnsub();
|
||||
positionUnsub();
|
||||
console.log('Unsubscribed from all streams');
|
||||
|
||||
console.log('');
|
||||
}
|
||||
|
||||
// Run examples
|
||||
main().catch(console.error);
|
||||
380
sdk/js/examples/ibc_example.ts
Normal file
380
sdk/js/examples/ibc_example.ts
Normal file
|
|
@ -0,0 +1,380 @@
|
|||
/**
|
||||
* Synor IBC SDK Examples for JavaScript/TypeScript
|
||||
*
|
||||
* Demonstrates Inter-Blockchain Communication operations:
|
||||
* - Cross-chain token transfers
|
||||
* - Channel management
|
||||
* - Packet handling
|
||||
* - Relayer operations
|
||||
*/
|
||||
|
||||
import {
|
||||
SynorIbc,
|
||||
IbcConfig,
|
||||
Network,
|
||||
ChannelState,
|
||||
PacketState,
|
||||
} from '../src/ibc';
|
||||
|
||||
async function main() {
|
||||
// Initialize client
|
||||
const config: IbcConfig = {
|
||||
apiKey: process.env.SYNOR_API_KEY || 'your-api-key',
|
||||
endpoint: 'https://ibc.synor.io/v1',
|
||||
timeout: 30000,
|
||||
retries: 3,
|
||||
debug: false,
|
||||
defaultNetwork: Network.Mainnet,
|
||||
};
|
||||
|
||||
const ibc = new SynorIbc(config);
|
||||
|
||||
try {
|
||||
// Check service health
|
||||
const healthy = await ibc.healthCheck();
|
||||
console.log(`Service healthy: ${healthy}\n`);
|
||||
|
||||
// Example 1: Connected chains
|
||||
await chainsExample(ibc);
|
||||
|
||||
// Example 2: Channel management
|
||||
await channelsExample(ibc);
|
||||
|
||||
// Example 3: Token transfers
|
||||
await transferExample(ibc);
|
||||
|
||||
// Example 4: Packet tracking
|
||||
await packetExample(ibc);
|
||||
|
||||
// Example 5: Relayer operations
|
||||
await relayerExample(ibc);
|
||||
|
||||
// Example 6: Connection info
|
||||
await connectionExample(ibc);
|
||||
} finally {
|
||||
ibc.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Connected chains information
|
||||
*/
|
||||
async function chainsExample(ibc: SynorIbc): Promise<void> {
|
||||
console.log('=== Connected Chains ===');
|
||||
|
||||
// Get all connected chains
|
||||
const chains = await ibc.chains.list();
|
||||
console.log(`Connected chains: ${chains.length}`);
|
||||
for (const chain of chains) {
|
||||
console.log(` ${chain.chainId}:`);
|
||||
console.log(` Name: ${chain.name}`);
|
||||
console.log(` Status: ${chain.status}`);
|
||||
console.log(` Block height: ${chain.latestHeight}`);
|
||||
console.log(` Channels: ${chain.channelCount}`);
|
||||
}
|
||||
|
||||
// Get specific chain info
|
||||
const cosmos = await ibc.chains.get('cosmoshub-4');
|
||||
console.log(`\nCosmos Hub details:`);
|
||||
console.log(` RPC: ${cosmos.rpcEndpoint}`);
|
||||
console.log(` Rest: ${cosmos.restEndpoint}`);
|
||||
console.log(` Native denom: ${cosmos.nativeDenom}`);
|
||||
console.log(` Prefix: ${cosmos.bech32Prefix}`);
|
||||
|
||||
// Get supported assets on a chain
|
||||
const assets = await ibc.chains.getAssets('cosmoshub-4');
|
||||
console.log(`\nSupported assets on Cosmos Hub:`);
|
||||
for (const asset of assets.slice(0, 5)) {
|
||||
console.log(` ${asset.symbol}: ${asset.denom}`);
|
||||
console.log(` Origin: ${asset.originChain}`);
|
||||
console.log(` Decimals: ${asset.decimals}`);
|
||||
}
|
||||
|
||||
// Get chain paths (routes)
|
||||
const paths = await ibc.chains.getPaths('synor-1', 'cosmoshub-4');
|
||||
console.log(`\nPaths from Synor to Cosmos Hub:`);
|
||||
for (const path of paths) {
|
||||
console.log(` ${path.sourceChannel} -> ${path.destChannel}`);
|
||||
console.log(` Hops: ${path.hops}`);
|
||||
console.log(` Avg time: ${path.avgTransferTime}s`);
|
||||
}
|
||||
|
||||
console.log('');
|
||||
}
|
||||
|
||||
/**
|
||||
* Channel management
|
||||
*/
|
||||
async function channelsExample(ibc: SynorIbc): Promise<void> {
|
||||
console.log('=== Channel Management ===');
|
||||
|
||||
// List all channels
|
||||
const channels = await ibc.channels.list();
|
||||
console.log(`Total channels: ${channels.length}`);
|
||||
|
||||
// Filter by state
|
||||
const openChannels = channels.filter(c => c.state === ChannelState.Open);
|
||||
console.log(`Open channels: ${openChannels.length}`);
|
||||
|
||||
for (const channel of openChannels.slice(0, 3)) {
|
||||
console.log(`\n Channel ${channel.channelId}:`);
|
||||
console.log(` Port: ${channel.portId}`);
|
||||
console.log(` Counterparty: ${channel.counterpartyChannelId} on ${channel.counterpartyChainId}`);
|
||||
console.log(` Ordering: ${channel.ordering}`);
|
||||
console.log(` Version: ${channel.version}`);
|
||||
console.log(` State: ${channel.state}`);
|
||||
}
|
||||
|
||||
// Get specific channel
|
||||
const channel = await ibc.channels.get('channel-0');
|
||||
console.log(`\nChannel-0 details:`);
|
||||
console.log(` Connection: ${channel.connectionId}`);
|
||||
console.log(` Counterparty port: ${channel.counterpartyPortId}`);
|
||||
|
||||
// Get channel statistics
|
||||
const stats = await ibc.channels.getStats('channel-0');
|
||||
console.log(`\nChannel-0 statistics:`);
|
||||
console.log(` Total packets sent: ${stats.packetsSent}`);
|
||||
console.log(` Total packets received: ${stats.packetsReceived}`);
|
||||
console.log(` Pending packets: ${stats.pendingPackets}`);
|
||||
console.log(` Success rate: ${stats.successRate}%`);
|
||||
console.log(` Avg relay time: ${stats.avgRelayTime}s`);
|
||||
|
||||
// Get channel capacity
|
||||
const capacity = await ibc.channels.getCapacity('channel-0');
|
||||
console.log(`\nChannel-0 capacity:`);
|
||||
console.log(` Max throughput: ${capacity.maxPacketsPerBlock} packets/block`);
|
||||
console.log(` Current utilization: ${capacity.utilization}%`);
|
||||
|
||||
console.log('');
|
||||
}
|
||||
|
||||
/**
|
||||
* Cross-chain token transfers
|
||||
*/
|
||||
async function transferExample(ibc: SynorIbc): Promise<void> {
|
||||
console.log('=== Cross-Chain Transfers ===');
|
||||
|
||||
// Estimate transfer fee
|
||||
const estimate = await ibc.transfers.estimateFee({
|
||||
sourceChain: 'synor-1',
|
||||
destChain: 'cosmoshub-4',
|
||||
denom: 'usyn',
|
||||
amount: '1000000', // 1 SYN (6 decimals)
|
||||
});
|
||||
console.log('Transfer fee estimate:');
|
||||
console.log(` Gas: ${estimate.gas}`);
|
||||
console.log(` Fee: ${estimate.fee} ${estimate.feeDenom}`);
|
||||
console.log(` Timeout: ${estimate.timeout}s`);
|
||||
|
||||
// Initiate a transfer
|
||||
console.log('\nInitiating transfer...');
|
||||
const transfer = await ibc.transfers.send({
|
||||
sourceChain: 'synor-1',
|
||||
destChain: 'cosmoshub-4',
|
||||
channel: 'channel-0',
|
||||
sender: 'synor1abc...', // Your address
|
||||
receiver: 'cosmos1xyz...', // Recipient address
|
||||
denom: 'usyn',
|
||||
amount: '1000000', // 1 SYN
|
||||
memo: 'Cross-chain transfer example',
|
||||
timeoutHeight: 0, // Use timestamp instead
|
||||
timeoutTimestamp: Date.now() + 600000, // 10 minutes
|
||||
});
|
||||
|
||||
console.log(`Transfer initiated:`);
|
||||
console.log(` TX Hash: ${transfer.txHash}`);
|
||||
console.log(` Sequence: ${transfer.sequence}`);
|
||||
console.log(` Status: ${transfer.status}`);
|
||||
|
||||
// Track transfer status
|
||||
console.log('\nTracking transfer...');
|
||||
const status = await ibc.transfers.getStatus(transfer.txHash);
|
||||
console.log(`Current status: ${status.state}`);
|
||||
console.log(` Source confirmed: ${status.sourceConfirmed}`);
|
||||
console.log(` Relayed: ${status.relayed}`);
|
||||
console.log(` Dest confirmed: ${status.destConfirmed}`);
|
||||
|
||||
// Get transfer history
|
||||
const history = await ibc.transfers.getHistory({
|
||||
address: 'synor1abc...',
|
||||
limit: 5,
|
||||
});
|
||||
console.log(`\nTransfer history (last 5):`);
|
||||
for (const tx of history) {
|
||||
const direction = tx.sender === 'synor1abc...' ? 'OUT' : 'IN';
|
||||
console.log(` ${direction} ${tx.amount} ${tx.denom} (${tx.status})`);
|
||||
}
|
||||
|
||||
// Get pending transfers
|
||||
const pending = await ibc.transfers.getPending('synor1abc...');
|
||||
console.log(`\nPending transfers: ${pending.length}`);
|
||||
|
||||
console.log('');
|
||||
}
|
||||
|
||||
/**
|
||||
* Packet handling
|
||||
*/
|
||||
async function packetExample(ibc: SynorIbc): Promise<void> {
|
||||
console.log('=== Packet Handling ===');
|
||||
|
||||
// Get pending packets
|
||||
const packets = await ibc.packets.getPending('channel-0');
|
||||
console.log(`Pending packets on channel-0: ${packets.length}`);
|
||||
|
||||
for (const packet of packets.slice(0, 3)) {
|
||||
console.log(`\n Packet ${packet.sequence}:`);
|
||||
console.log(` Source: ${packet.sourcePort}/${packet.sourceChannel}`);
|
||||
console.log(` Dest: ${packet.destPort}/${packet.destChannel}`);
|
||||
console.log(` State: ${packet.state}`);
|
||||
console.log(` Data size: ${packet.data.length} bytes`);
|
||||
console.log(` Timeout height: ${packet.timeoutHeight}`);
|
||||
console.log(` Timeout timestamp: ${new Date(packet.timeoutTimestamp).toISOString()}`);
|
||||
}
|
||||
|
||||
// Get packet by sequence
|
||||
const packet = await ibc.packets.get('channel-0', 1);
|
||||
console.log(`\nPacket details:`);
|
||||
console.log(` Commitment: ${packet.commitment}`);
|
||||
console.log(` Receipt: ${packet.receipt}`);
|
||||
console.log(` Acknowledgement: ${packet.acknowledgement}`);
|
||||
|
||||
// Get packet receipts
|
||||
const receipts = await ibc.packets.getReceipts('channel-0', [1, 2, 3]);
|
||||
console.log(`\nPacket receipts:`);
|
||||
for (const [seq, receipt] of Object.entries(receipts)) {
|
||||
console.log(` Sequence ${seq}: ${receipt ? 'received' : 'not received'}`);
|
||||
}
|
||||
|
||||
// Get timed out packets
|
||||
const timedOut = await ibc.packets.getTimedOut('channel-0');
|
||||
console.log(`\nTimed out packets: ${timedOut.length}`);
|
||||
for (const p of timedOut) {
|
||||
console.log(` Sequence ${p.sequence}: timeout at ${new Date(p.timeoutTimestamp).toISOString()}`);
|
||||
}
|
||||
|
||||
// Get unreceived packets
|
||||
const unreceived = await ibc.packets.getUnreceived('channel-0');
|
||||
console.log(`\nUnreceived packet sequences: ${unreceived.join(', ') || 'none'}`);
|
||||
|
||||
// Get unacknowledged packets
|
||||
const unacked = await ibc.packets.getUnacknowledged('channel-0');
|
||||
console.log(`Unacknowledged packet sequences: ${unacked.join(', ') || 'none'}`);
|
||||
|
||||
console.log('');
|
||||
}
|
||||
|
||||
/**
|
||||
* Relayer operations
|
||||
*/
|
||||
async function relayerExample(ibc: SynorIbc): Promise<void> {
|
||||
console.log('=== Relayer Operations ===');
|
||||
|
||||
// Get active relayers
|
||||
const relayers = await ibc.relayers.list();
|
||||
console.log(`Active relayers: ${relayers.length}`);
|
||||
for (const relayer of relayers.slice(0, 3)) {
|
||||
console.log(`\n ${relayer.address}:`);
|
||||
console.log(` Chains: ${relayer.chains.join(', ')}`);
|
||||
console.log(` Packets relayed: ${relayer.packetsRelayed}`);
|
||||
console.log(` Success rate: ${relayer.successRate}%`);
|
||||
console.log(` Avg latency: ${relayer.avgLatency}ms`);
|
||||
console.log(` Fee rate: ${relayer.feeRate}%`);
|
||||
}
|
||||
|
||||
// Get relayer statistics
|
||||
const stats = await ibc.relayers.getStats();
|
||||
console.log('\nGlobal relayer statistics:');
|
||||
console.log(` Total relayers: ${stats.totalRelayers}`);
|
||||
console.log(` Active relayers: ${stats.activeRelayers}`);
|
||||
console.log(` Packets relayed (24h): ${stats.packetsRelayed24h}`);
|
||||
console.log(` Total fees earned: ${stats.totalFeesEarned}`);
|
||||
|
||||
// Register as a relayer
|
||||
console.log('\nRegistering as relayer...');
|
||||
const registration = await ibc.relayers.register({
|
||||
chains: ['synor-1', 'cosmoshub-4'],
|
||||
feeRate: 0.1, // 0.1% fee
|
||||
minPacketSize: 0,
|
||||
maxPacketSize: 1000000,
|
||||
});
|
||||
console.log(`Registered with address: ${registration.relayerAddress}`);
|
||||
|
||||
// Start relaying (in background)
|
||||
console.log('\nStarting relay service...');
|
||||
const relaySession = await ibc.relayers.startRelay({
|
||||
channels: ['channel-0'],
|
||||
autoAck: true,
|
||||
batchSize: 10,
|
||||
pollInterval: 5000,
|
||||
});
|
||||
console.log(`Relay session started: ${relaySession.sessionId}`);
|
||||
|
||||
// Get relay queue
|
||||
const queue = await ibc.relayers.getQueue('channel-0');
|
||||
console.log(`\nRelay queue for channel-0: ${queue.length} packets`);
|
||||
|
||||
// Manually relay a packet
|
||||
if (queue.length > 0) {
|
||||
console.log('\nRelaying packet...');
|
||||
const relayResult = await ibc.relayers.relayPacket(queue[0].sequence, 'channel-0');
|
||||
console.log(`Relay result: ${relayResult.status}`);
|
||||
console.log(` TX Hash: ${relayResult.txHash}`);
|
||||
console.log(` Fee earned: ${relayResult.feeEarned}`);
|
||||
}
|
||||
|
||||
// Stop relay session
|
||||
await ibc.relayers.stopRelay(relaySession.sessionId);
|
||||
console.log('\nRelay session stopped');
|
||||
|
||||
console.log('');
|
||||
}
|
||||
|
||||
/**
|
||||
* Connection information
|
||||
*/
|
||||
async function connectionExample(ibc: SynorIbc): Promise<void> {
|
||||
console.log('=== Connection Information ===');
|
||||
|
||||
// List connections
|
||||
const connections = await ibc.connections.list();
|
||||
console.log(`Total connections: ${connections.length}`);
|
||||
|
||||
for (const conn of connections.slice(0, 3)) {
|
||||
console.log(`\n ${conn.connectionId}:`);
|
||||
console.log(` Client: ${conn.clientId}`);
|
||||
console.log(` Counterparty: ${conn.counterpartyConnectionId}`);
|
||||
console.log(` State: ${conn.state}`);
|
||||
console.log(` Versions: ${conn.versions.join(', ')}`);
|
||||
}
|
||||
|
||||
// Get connection details
|
||||
const connection = await ibc.connections.get('connection-0');
|
||||
console.log(`\nConnection-0 details:`);
|
||||
console.log(` Delay period: ${connection.delayPeriod}ns`);
|
||||
console.log(` Counterparty client: ${connection.counterpartyClientId}`);
|
||||
console.log(` Counterparty prefix: ${connection.counterpartyPrefix}`);
|
||||
|
||||
// Get client state
|
||||
const client = await ibc.clients.get(connection.clientId);
|
||||
console.log(`\nClient state:`);
|
||||
console.log(` Chain ID: ${client.chainId}`);
|
||||
console.log(` Trust level: ${client.trustLevel}`);
|
||||
console.log(` Trusting period: ${client.trustingPeriod}`);
|
||||
console.log(` Unbonding period: ${client.unbondingPeriod}`);
|
||||
console.log(` Latest height: ${client.latestHeight}`);
|
||||
console.log(` Frozen: ${client.frozen}`);
|
||||
|
||||
// Get consensus state
|
||||
const consensus = await ibc.clients.getConsensusState(connection.clientId, client.latestHeight);
|
||||
console.log(`\nConsensus state at height ${client.latestHeight}:`);
|
||||
console.log(` Timestamp: ${new Date(consensus.timestamp).toISOString()}`);
|
||||
console.log(` Root: ${consensus.root.slice(0, 20)}...`);
|
||||
console.log(` Next validators hash: ${consensus.nextValidatorsHash.slice(0, 20)}...`);
|
||||
|
||||
console.log('');
|
||||
}
|
||||
|
||||
// Run examples
|
||||
main().catch(console.error);
|
||||
537
sdk/js/examples/zk_example.ts
Normal file
537
sdk/js/examples/zk_example.ts
Normal file
|
|
@ -0,0 +1,537 @@
|
|||
/**
|
||||
* Synor ZK SDK Examples for JavaScript/TypeScript
|
||||
*
|
||||
* Demonstrates Zero-Knowledge proof operations:
|
||||
* - Circuit compilation
|
||||
* - Proof generation and verification
|
||||
* - Groth16, PLONK, and STARK proving systems
|
||||
* - Recursive proofs
|
||||
* - On-chain verification
|
||||
*/
|
||||
|
||||
import {
|
||||
SynorZk,
|
||||
ZkConfig,
|
||||
ProvingSystem,
|
||||
CircuitFormat,
|
||||
ProofStatus,
|
||||
} from '../src/zk';
|
||||
|
||||
async function main() {
|
||||
// Initialize client
|
||||
const config: ZkConfig = {
|
||||
apiKey: process.env.SYNOR_API_KEY || 'your-api-key',
|
||||
endpoint: 'https://zk.synor.io/v1',
|
||||
timeout: 120000, // ZK ops can be slow
|
||||
retries: 3,
|
||||
debug: false,
|
||||
defaultProvingSystem: ProvingSystem.Groth16,
|
||||
};
|
||||
|
||||
const zk = new SynorZk(config);
|
||||
|
||||
try {
|
||||
// Check service health
|
||||
const healthy = await zk.healthCheck();
|
||||
console.log(`Service healthy: ${healthy}\n`);
|
||||
|
||||
// Example 1: Circuit compilation
|
||||
await circuitExample(zk);
|
||||
|
||||
// Example 2: Proof generation
|
||||
await proofExample(zk);
|
||||
|
||||
// Example 3: Different proving systems
|
||||
await provingSystemsExample(zk);
|
||||
|
||||
// Example 4: Recursive proofs
|
||||
await recursiveProofExample(zk);
|
||||
|
||||
// Example 5: On-chain verification
|
||||
await onChainVerificationExample(zk);
|
||||
|
||||
// Example 6: Trusted setup
|
||||
await setupExample(zk);
|
||||
} finally {
|
||||
zk.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Circuit compilation
|
||||
*/
|
||||
async function circuitExample(zk: SynorZk): Promise<void> {
|
||||
console.log('=== Circuit Compilation ===');
|
||||
|
||||
// Circom circuit example: prove knowledge of preimage
|
||||
const circomCircuit = `
|
||||
pragma circom 2.1.0;
|
||||
|
||||
template HashPreimage() {
|
||||
signal input preimage;
|
||||
signal input hash;
|
||||
|
||||
// Simplified hash computation (in reality, use proper hash)
|
||||
signal preimageSquared;
|
||||
preimageSquared <== preimage * preimage;
|
||||
|
||||
// Constrain that hash matches
|
||||
hash === preimageSquared;
|
||||
}
|
||||
|
||||
component main {public [hash]} = HashPreimage();
|
||||
`;
|
||||
|
||||
// Compile circuit
|
||||
console.log('Compiling Circom circuit...');
|
||||
const compiled = await zk.circuits.compile({
|
||||
code: circomCircuit,
|
||||
format: CircuitFormat.Circom,
|
||||
name: 'hash_preimage',
|
||||
provingSystem: ProvingSystem.Groth16,
|
||||
});
|
||||
|
||||
console.log(`Circuit compiled:`);
|
||||
console.log(` Circuit ID: ${compiled.circuitId}`);
|
||||
console.log(` Constraints: ${compiled.constraintCount}`);
|
||||
console.log(` Public inputs: ${compiled.publicInputCount}`);
|
||||
console.log(` Private inputs: ${compiled.privateInputCount}`);
|
||||
console.log(` Proving key size: ${compiled.provingKeySize} bytes`);
|
||||
console.log(` Verification key size: ${compiled.verificationKeySize} bytes`);
|
||||
|
||||
// List circuits
|
||||
const circuits = await zk.circuits.list();
|
||||
console.log(`\nYour circuits: ${circuits.length}`);
|
||||
for (const circuit of circuits) {
|
||||
console.log(` ${circuit.name} (${circuit.circuitId})`);
|
||||
}
|
||||
|
||||
// Get circuit details
|
||||
const details = await zk.circuits.get(compiled.circuitId);
|
||||
console.log(`\nCircuit details:`);
|
||||
console.log(` Format: ${details.format}`);
|
||||
console.log(` Proving system: ${details.provingSystem}`);
|
||||
console.log(` Created: ${new Date(details.createdAt).toISOString()}`);
|
||||
|
||||
// Download proving key
|
||||
const provingKey = await zk.circuits.getProvingKey(compiled.circuitId);
|
||||
console.log(`\nProving key downloaded: ${provingKey.length} bytes`);
|
||||
|
||||
// Download verification key
|
||||
const verificationKey = await zk.circuits.getVerificationKey(compiled.circuitId);
|
||||
console.log(`Verification key downloaded: ${verificationKey.length} bytes`);
|
||||
|
||||
console.log('');
|
||||
}
|
||||
|
||||
/**
|
||||
* Proof generation and verification
|
||||
*/
|
||||
async function proofExample(zk: SynorZk): Promise<void> {
|
||||
console.log('=== Proof Generation ===');
|
||||
|
||||
// First, compile a simple circuit
|
||||
const circuit = `
|
||||
pragma circom 2.1.0;
|
||||
|
||||
template Multiplier() {
|
||||
signal input a;
|
||||
signal input b;
|
||||
signal output c;
|
||||
|
||||
c <== a * b;
|
||||
}
|
||||
|
||||
component main {public [c]} = Multiplier();
|
||||
`;
|
||||
|
||||
const compiled = await zk.circuits.compile({
|
||||
code: circuit,
|
||||
format: CircuitFormat.Circom,
|
||||
name: 'multiplier',
|
||||
provingSystem: ProvingSystem.Groth16,
|
||||
});
|
||||
|
||||
// Generate proof
|
||||
console.log('Generating proof...');
|
||||
const startTime = Date.now();
|
||||
|
||||
const proof = await zk.proofs.generate({
|
||||
circuitId: compiled.circuitId,
|
||||
inputs: {
|
||||
a: '3',
|
||||
b: '7',
|
||||
},
|
||||
});
|
||||
|
||||
const proofTime = Date.now() - startTime;
|
||||
console.log(`Proof generated in ${proofTime}ms`);
|
||||
console.log(` Proof ID: ${proof.proofId}`);
|
||||
console.log(` Proof size: ${proof.proof.length} bytes`);
|
||||
console.log(` Public signals: ${proof.publicSignals}`);
|
||||
|
||||
// Verify proof
|
||||
console.log('\nVerifying proof...');
|
||||
const verifyStart = Date.now();
|
||||
|
||||
const isValid = await zk.proofs.verify({
|
||||
circuitId: compiled.circuitId,
|
||||
proof: proof.proof,
|
||||
publicSignals: proof.publicSignals,
|
||||
});
|
||||
|
||||
const verifyTime = Date.now() - verifyStart;
|
||||
console.log(`Verification completed in ${verifyTime}ms`);
|
||||
console.log(` Valid: ${isValid}`);
|
||||
|
||||
// Verify with wrong public signals (should fail)
|
||||
console.log('\nVerifying with wrong signals...');
|
||||
const invalidResult = await zk.proofs.verify({
|
||||
circuitId: compiled.circuitId,
|
||||
proof: proof.proof,
|
||||
publicSignals: ['42'], // Wrong answer
|
||||
});
|
||||
console.log(` Valid: ${invalidResult} (expected false)`);
|
||||
|
||||
// Get proof status
|
||||
const status = await zk.proofs.getStatus(proof.proofId);
|
||||
console.log(`\nProof status:`);
|
||||
console.log(` State: ${status.state}`);
|
||||
console.log(` Verified: ${status.verified}`);
|
||||
console.log(` Created: ${new Date(status.createdAt).toISOString()}`);
|
||||
|
||||
// List proofs
|
||||
const proofs = await zk.proofs.list({ circuitId: compiled.circuitId });
|
||||
console.log(`\nProofs for circuit: ${proofs.length}`);
|
||||
|
||||
console.log('');
|
||||
}
|
||||
|
||||
/**
|
||||
* Different proving systems comparison
|
||||
*/
|
||||
async function provingSystemsExample(zk: SynorZk): Promise<void> {
|
||||
console.log('=== Proving Systems Comparison ===');
|
||||
|
||||
// Simple circuit for comparison
|
||||
const circuit = `
|
||||
pragma circom 2.1.0;
|
||||
|
||||
template Comparison() {
|
||||
signal input x;
|
||||
signal input y;
|
||||
signal output sum;
|
||||
|
||||
sum <== x + y;
|
||||
}
|
||||
|
||||
component main {public [sum]} = Comparison();
|
||||
`;
|
||||
|
||||
const systems = [
|
||||
ProvingSystem.Groth16,
|
||||
ProvingSystem.Plonk,
|
||||
ProvingSystem.Stark,
|
||||
];
|
||||
|
||||
console.log('Comparing proving systems:\n');
|
||||
|
||||
for (const system of systems) {
|
||||
console.log(`${system}:`);
|
||||
|
||||
// Compile for this system
|
||||
const compiled = await zk.circuits.compile({
|
||||
code: circuit,
|
||||
format: CircuitFormat.Circom,
|
||||
name: `comparison_${system.toLowerCase()}`,
|
||||
provingSystem: system,
|
||||
});
|
||||
|
||||
// Generate proof
|
||||
const proofStart = Date.now();
|
||||
const proof = await zk.proofs.generate({
|
||||
circuitId: compiled.circuitId,
|
||||
inputs: { x: '10', y: '20' },
|
||||
});
|
||||
const proofTime = Date.now() - proofStart;
|
||||
|
||||
// Verify proof
|
||||
const verifyStart = Date.now();
|
||||
await zk.proofs.verify({
|
||||
circuitId: compiled.circuitId,
|
||||
proof: proof.proof,
|
||||
publicSignals: proof.publicSignals,
|
||||
});
|
||||
const verifyTime = Date.now() - verifyStart;
|
||||
|
||||
console.log(` Setup: ${compiled.setupTime}ms`);
|
||||
console.log(` Proof time: ${proofTime}ms`);
|
||||
console.log(` Verify time: ${verifyTime}ms`);
|
||||
console.log(` Proof size: ${proof.proof.length} bytes`);
|
||||
console.log(` Verification key: ${compiled.verificationKeySize} bytes`);
|
||||
console.log('');
|
||||
}
|
||||
|
||||
console.log('Summary:');
|
||||
console.log(' Groth16: Smallest proofs, fast verification, trusted setup required');
|
||||
console.log(' PLONK: Universal setup, flexible, moderate proof size');
|
||||
console.log(' STARK: No trusted setup, largest proofs, quantum resistant');
|
||||
|
||||
console.log('');
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursive proof aggregation
|
||||
*/
|
||||
async function recursiveProofExample(zk: SynorZk): Promise<void> {
|
||||
console.log('=== Recursive Proofs ===');
|
||||
|
||||
// Inner circuit
|
||||
const innerCircuit = `
|
||||
pragma circom 2.1.0;
|
||||
|
||||
template Inner() {
|
||||
signal input x;
|
||||
signal output y;
|
||||
y <== x * x;
|
||||
}
|
||||
|
||||
component main {public [y]} = Inner();
|
||||
`;
|
||||
|
||||
// Compile inner circuit
|
||||
const inner = await zk.circuits.compile({
|
||||
code: innerCircuit,
|
||||
format: CircuitFormat.Circom,
|
||||
name: 'inner_circuit',
|
||||
provingSystem: ProvingSystem.Groth16,
|
||||
});
|
||||
|
||||
// Generate multiple proofs to aggregate
|
||||
console.log('Generating proofs to aggregate...');
|
||||
const proofsToAggregate = [];
|
||||
for (let i = 1; i <= 4; i++) {
|
||||
const proof = await zk.proofs.generate({
|
||||
circuitId: inner.circuitId,
|
||||
inputs: { x: i.toString() },
|
||||
});
|
||||
proofsToAggregate.push({
|
||||
proof: proof.proof,
|
||||
publicSignals: proof.publicSignals,
|
||||
});
|
||||
console.log(` Proof ${i}: y = ${proof.publicSignals[0]}`);
|
||||
}
|
||||
|
||||
// Aggregate proofs recursively
|
||||
console.log('\nAggregating proofs...');
|
||||
const aggregated = await zk.proofs.aggregate({
|
||||
circuitId: inner.circuitId,
|
||||
proofs: proofsToAggregate,
|
||||
aggregationType: 'recursive',
|
||||
});
|
||||
|
||||
console.log(`Aggregated proof:`);
|
||||
console.log(` Proof ID: ${aggregated.proofId}`);
|
||||
console.log(` Aggregated count: ${aggregated.aggregatedCount}`);
|
||||
console.log(` Proof size: ${aggregated.proof.length} bytes`);
|
||||
console.log(` Size reduction: ${(1 - aggregated.proof.length / (proofsToAggregate.length * proofsToAggregate[0].proof.length)) * 100}%`);
|
||||
|
||||
// Verify aggregated proof
|
||||
const isValid = await zk.proofs.verifyAggregated({
|
||||
circuitId: inner.circuitId,
|
||||
proof: aggregated.proof,
|
||||
publicSignalsList: proofsToAggregate.map(p => p.publicSignals),
|
||||
});
|
||||
console.log(`\nAggregated proof valid: ${isValid}`);
|
||||
|
||||
// Batch verification (verify multiple proofs in one operation)
|
||||
console.log('\nBatch verification...');
|
||||
const batchResult = await zk.proofs.batchVerify({
|
||||
circuitId: inner.circuitId,
|
||||
proofs: proofsToAggregate,
|
||||
});
|
||||
console.log(` All valid: ${batchResult.allValid}`);
|
||||
console.log(` Results: ${batchResult.results.join(', ')}`);
|
||||
|
||||
console.log('');
|
||||
}
|
||||
|
||||
/**
|
||||
* On-chain verification
|
||||
*/
|
||||
async function onChainVerificationExample(zk: SynorZk): Promise<void> {
|
||||
console.log('=== On-Chain Verification ===');
|
||||
|
||||
// Compile circuit
|
||||
const circuit = `
|
||||
pragma circom 2.1.0;
|
||||
|
||||
template VoteCommitment() {
|
||||
signal input vote; // Private: actual vote
|
||||
signal input nullifier; // Private: unique identifier
|
||||
signal input commitment; // Public: commitment to verify
|
||||
|
||||
// Simplified commitment (in practice, use Poseidon hash)
|
||||
signal computed;
|
||||
computed <== vote * nullifier;
|
||||
commitment === computed;
|
||||
}
|
||||
|
||||
component main {public [commitment]} = VoteCommitment();
|
||||
`;
|
||||
|
||||
const compiled = await zk.circuits.compile({
|
||||
code: circuit,
|
||||
format: CircuitFormat.Circom,
|
||||
name: 'vote_commitment',
|
||||
provingSystem: ProvingSystem.Groth16,
|
||||
});
|
||||
|
||||
// Generate Solidity verifier
|
||||
console.log('Generating Solidity verifier...');
|
||||
const solidityVerifier = await zk.contracts.generateVerifier({
|
||||
circuitId: compiled.circuitId,
|
||||
language: 'solidity',
|
||||
optimized: true,
|
||||
});
|
||||
console.log(`Solidity verifier generated: ${solidityVerifier.code.length} bytes`);
|
||||
console.log(` Contract name: ${solidityVerifier.contractName}`);
|
||||
console.log(` Gas estimate: ${solidityVerifier.gasEstimate}`);
|
||||
|
||||
// Generate proof
|
||||
const proof = await zk.proofs.generate({
|
||||
circuitId: compiled.circuitId,
|
||||
inputs: {
|
||||
vote: '1', // Vote YES (1) or NO (0)
|
||||
nullifier: '12345',
|
||||
commitment: '12345', // 1 * 12345
|
||||
},
|
||||
});
|
||||
|
||||
// Format proof for on-chain verification
|
||||
console.log('\nFormatting proof for on-chain...');
|
||||
const onChainProof = await zk.contracts.formatProof({
|
||||
circuitId: compiled.circuitId,
|
||||
proof: proof.proof,
|
||||
publicSignals: proof.publicSignals,
|
||||
format: 'calldata',
|
||||
});
|
||||
console.log(` Calldata: ${onChainProof.calldata.slice(0, 100)}...`);
|
||||
console.log(` Estimated gas: ${onChainProof.gasEstimate}`);
|
||||
|
||||
// Deploy verifier contract (simulation)
|
||||
console.log('\nDeploying verifier contract...');
|
||||
const deployment = await zk.contracts.deployVerifier({
|
||||
circuitId: compiled.circuitId,
|
||||
network: 'synor-testnet',
|
||||
});
|
||||
console.log(` Contract address: ${deployment.address}`);
|
||||
console.log(` TX hash: ${deployment.txHash}`);
|
||||
console.log(` Gas used: ${deployment.gasUsed}`);
|
||||
|
||||
// Verify on-chain
|
||||
console.log('\nVerifying on-chain...');
|
||||
const onChainResult = await zk.contracts.verifyOnChain({
|
||||
contractAddress: deployment.address,
|
||||
proof: proof.proof,
|
||||
publicSignals: proof.publicSignals,
|
||||
network: 'synor-testnet',
|
||||
});
|
||||
console.log(` TX hash: ${onChainResult.txHash}`);
|
||||
console.log(` Verified: ${onChainResult.verified}`);
|
||||
console.log(` Gas used: ${onChainResult.gasUsed}`);
|
||||
|
||||
// Generate verifier for other targets
|
||||
console.log('\nGenerating verifiers for other targets:');
|
||||
const targets = ['cairo', 'noir', 'ink'];
|
||||
for (const target of targets) {
|
||||
const verifier = await zk.contracts.generateVerifier({
|
||||
circuitId: compiled.circuitId,
|
||||
language: target,
|
||||
});
|
||||
console.log(` ${target}: ${verifier.code.length} bytes`);
|
||||
}
|
||||
|
||||
console.log('');
|
||||
}
|
||||
|
||||
/**
|
||||
* Trusted setup ceremonies
|
||||
*/
|
||||
async function setupExample(zk: SynorZk): Promise<void> {
|
||||
console.log('=== Trusted Setup ===');
|
||||
|
||||
// Get available ceremonies
|
||||
const ceremonies = await zk.setup.listCeremonies();
|
||||
console.log(`Active ceremonies: ${ceremonies.length}`);
|
||||
for (const ceremony of ceremonies) {
|
||||
console.log(` ${ceremony.name}:`);
|
||||
console.log(` Status: ${ceremony.status}`);
|
||||
console.log(` Participants: ${ceremony.participantCount}`);
|
||||
console.log(` Current round: ${ceremony.currentRound}`);
|
||||
}
|
||||
|
||||
// Create a new circuit setup
|
||||
const circuit = `
|
||||
pragma circom 2.1.0;
|
||||
|
||||
template NewCircuit() {
|
||||
signal input a;
|
||||
signal output b;
|
||||
b <== a + 1;
|
||||
}
|
||||
|
||||
component main {public [b]} = NewCircuit();
|
||||
`;
|
||||
|
||||
console.log('\nInitializing setup for new circuit...');
|
||||
const setup = await zk.setup.initialize({
|
||||
circuit,
|
||||
format: CircuitFormat.Circom,
|
||||
name: 'new_circuit_setup',
|
||||
provingSystem: ProvingSystem.Groth16,
|
||||
ceremonyType: 'powers_of_tau', // or 'phase2'
|
||||
});
|
||||
console.log(`Setup initialized:`);
|
||||
console.log(` Ceremony ID: ${setup.ceremonyId}`);
|
||||
console.log(` Powers of Tau required: ${setup.powersRequired}`);
|
||||
console.log(` Current phase: ${setup.phase}`);
|
||||
|
||||
// Contribute to ceremony (in practice, generates random entropy)
|
||||
console.log('\nContributing to ceremony...');
|
||||
const contribution = await zk.setup.contribute({
|
||||
ceremonyId: setup.ceremonyId,
|
||||
entropy: Buffer.from('random-entropy-from-user').toString('hex'),
|
||||
});
|
||||
console.log(`Contribution submitted:`);
|
||||
console.log(` Participant: ${contribution.participantId}`);
|
||||
console.log(` Contribution hash: ${contribution.hash}`);
|
||||
console.log(` Verification status: ${contribution.verified}`);
|
||||
|
||||
// Get ceremony status
|
||||
const status = await zk.setup.getStatus(setup.ceremonyId);
|
||||
console.log(`\nCeremony status:`);
|
||||
console.log(` Phase: ${status.phase}`);
|
||||
console.log(` Total contributions: ${status.totalContributions}`);
|
||||
console.log(` Verified contributions: ${status.verifiedContributions}`);
|
||||
console.log(` Ready for finalization: ${status.readyForFinalization}`);
|
||||
|
||||
// Finalize setup (when enough contributions)
|
||||
if (status.readyForFinalization) {
|
||||
console.log('\nFinalizing setup...');
|
||||
const finalized = await zk.setup.finalize(setup.ceremonyId);
|
||||
console.log(`Setup finalized:`);
|
||||
console.log(` Proving key hash: ${finalized.provingKeyHash}`);
|
||||
console.log(` Verification key hash: ${finalized.verificationKeyHash}`);
|
||||
console.log(` Contribution transcript: ${finalized.transcriptCid}`);
|
||||
}
|
||||
|
||||
// Download ceremony transcript
|
||||
const transcript = await zk.setup.getTranscript(setup.ceremonyId);
|
||||
console.log(`\nCeremony transcript: ${transcript.length} bytes`);
|
||||
|
||||
console.log('');
|
||||
}
|
||||
|
||||
// Run examples
|
||||
main().catch(console.error);
|
||||
354
sdk/python/examples/compiler_example.py
Normal file
354
sdk/python/examples/compiler_example.py
Normal file
|
|
@ -0,0 +1,354 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
Synor Compiler SDK Examples for Python
|
||||
|
||||
Demonstrates smart contract compilation and analysis:
|
||||
- WASM contract compilation and optimization
|
||||
- ABI extraction and encoding
|
||||
- Contract analysis and security scanning
|
||||
- Validation and verification
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import os
|
||||
from synor_compiler import (
|
||||
SynorCompiler,
|
||||
CompilerConfig,
|
||||
OptimizationLevel,
|
||||
StripOptions,
|
||||
)
|
||||
|
||||
|
||||
async def main():
|
||||
"""Main entry point."""
|
||||
# Initialize client
|
||||
config = CompilerConfig(
|
||||
api_key=os.environ.get("SYNOR_API_KEY", "your-api-key"),
|
||||
endpoint="https://compiler.synor.io/v1",
|
||||
timeout=60000,
|
||||
retries=3,
|
||||
debug=False,
|
||||
default_optimization_level=OptimizationLevel.SIZE,
|
||||
max_contract_size=256 * 1024,
|
||||
use_wasm_opt=True,
|
||||
validate=True,
|
||||
extract_metadata=True,
|
||||
generate_abi=True,
|
||||
)
|
||||
|
||||
compiler = SynorCompiler(config)
|
||||
|
||||
try:
|
||||
# Check service health
|
||||
healthy = await compiler.health_check()
|
||||
print(f"Service healthy: {healthy}\n")
|
||||
|
||||
# Example 1: Compile a contract
|
||||
await compile_contract_example(compiler)
|
||||
|
||||
# Example 2: Development vs Production
|
||||
await compilation_modes_example(compiler)
|
||||
|
||||
# Example 3: ABI operations
|
||||
await abi_example(compiler)
|
||||
|
||||
# Example 4: Contract analysis
|
||||
await analysis_example(compiler)
|
||||
|
||||
# Example 5: Validation
|
||||
await validation_example(compiler)
|
||||
|
||||
# Example 6: Security scanning
|
||||
await security_example(compiler)
|
||||
finally:
|
||||
await compiler.close()
|
||||
|
||||
|
||||
def create_minimal_wasm() -> bytes:
|
||||
"""Create a minimal valid WASM module for testing."""
|
||||
return bytes([
|
||||
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,
|
||||
])
|
||||
|
||||
|
||||
async def compile_contract_example(compiler: SynorCompiler):
|
||||
"""Basic contract compilation."""
|
||||
print("=== Contract Compilation ===")
|
||||
|
||||
wasm = create_minimal_wasm()
|
||||
|
||||
result = await compiler.compile(
|
||||
wasm,
|
||||
optimization_level=OptimizationLevel.SIZE,
|
||||
use_wasm_opt=True,
|
||||
validate=True,
|
||||
extract_metadata=True,
|
||||
generate_abi=True,
|
||||
strip_options=StripOptions(
|
||||
strip_debug=True,
|
||||
strip_producers=True,
|
||||
strip_names=True,
|
||||
strip_custom=True,
|
||||
strip_unused=True,
|
||||
preserve_sections=[],
|
||||
),
|
||||
)
|
||||
|
||||
print("Compilation result:")
|
||||
print(f" Contract ID: {result.contract_id}")
|
||||
print(f" Code hash: {result.code_hash}")
|
||||
print(f" Original size: {result.original_size} bytes")
|
||||
print(f" Optimized size: {result.optimized_size} bytes")
|
||||
print(f" Size reduction: {result.size_reduction:.1f}%")
|
||||
print(f" Estimated deploy gas: {result.estimated_deploy_gas}")
|
||||
|
||||
if result.metadata:
|
||||
print("\nMetadata:")
|
||||
print(f" Name: {result.metadata.name}")
|
||||
print(f" Version: {result.metadata.version}")
|
||||
print(f" SDK Version: {result.metadata.sdk_version}")
|
||||
|
||||
if result.abi:
|
||||
print("\nABI:")
|
||||
print(f" Functions: {len(result.abi.functions or [])}")
|
||||
print(f" Events: {len(result.abi.events or [])}")
|
||||
print(f" Errors: {len(result.abi.errors or [])}")
|
||||
|
||||
print()
|
||||
|
||||
|
||||
async def compilation_modes_example(compiler: SynorCompiler):
|
||||
"""Development vs Production compilation modes."""
|
||||
print("=== Compilation Modes ===")
|
||||
|
||||
wasm = create_minimal_wasm()
|
||||
|
||||
# Development mode: fast compilation, debugging support
|
||||
print("Development mode:")
|
||||
dev_result = await compiler.contracts.compile_dev(wasm)
|
||||
print(f" Size: {dev_result.optimized_size} bytes")
|
||||
print(f" Optimization: none")
|
||||
|
||||
# Production mode: maximum optimization
|
||||
print("\nProduction mode:")
|
||||
prod_result = await compiler.contracts.compile_production(wasm)
|
||||
print(f" Size: {prod_result.optimized_size} bytes")
|
||||
print(f" Optimization: aggressive")
|
||||
print(f" Size savings: {dev_result.optimized_size - prod_result.optimized_size} bytes")
|
||||
|
||||
# Custom optimization levels
|
||||
print("\nOptimization levels:")
|
||||
levels = [
|
||||
OptimizationLevel.NONE,
|
||||
OptimizationLevel.BASIC,
|
||||
OptimizationLevel.SIZE,
|
||||
OptimizationLevel.AGGRESSIVE,
|
||||
]
|
||||
|
||||
for level in levels:
|
||||
result = await compiler.compile(wasm, optimization_level=level)
|
||||
print(f" {level.value}: {result.optimized_size} bytes")
|
||||
|
||||
print()
|
||||
|
||||
|
||||
async def abi_example(compiler: SynorCompiler):
|
||||
"""ABI extraction and encoding."""
|
||||
print("=== ABI Operations ===")
|
||||
|
||||
wasm = create_minimal_wasm()
|
||||
|
||||
# Extract ABI from WASM
|
||||
abi = await compiler.abi.extract(wasm)
|
||||
print(f"Contract: {abi.name}")
|
||||
print(f"Version: {abi.version}")
|
||||
|
||||
# List functions
|
||||
if abi.functions:
|
||||
print("\nFunctions:")
|
||||
for func in abi.functions:
|
||||
inputs = ", ".join(
|
||||
f"{i.name}: {i.type.type_name}" for i in (func.inputs or [])
|
||||
)
|
||||
outputs = ", ".join(o.type.type_name for o in (func.outputs or [])) or "void"
|
||||
modifiers = " ".join(
|
||||
filter(None, ["view" if func.view else "", "payable" if func.payable else ""])
|
||||
)
|
||||
print(f" {func.name}({inputs}) -> {outputs} {modifiers}")
|
||||
print(f" Selector: {func.selector}")
|
||||
|
||||
# List events
|
||||
if abi.events:
|
||||
print("\nEvents:")
|
||||
for event in abi.events:
|
||||
params = ", ".join(
|
||||
f"{'indexed ' if p.indexed else ''}{p.name}: {p.type.type_name}"
|
||||
for p in (event.params or [])
|
||||
)
|
||||
print(f" {event.name}({params})")
|
||||
print(f" Topic: {event.topic}")
|
||||
|
||||
# Encode a function call
|
||||
if abi.functions:
|
||||
func = abi.functions[0]
|
||||
encoded = await compiler.abi.encode_call(func, ["arg1", "arg2"])
|
||||
print(f"\nEncoded call to {func.name}: {encoded}")
|
||||
|
||||
# Decode a result
|
||||
decoded = await compiler.abi.decode_result(func, encoded)
|
||||
print(f"Decoded result: {decoded}")
|
||||
|
||||
print()
|
||||
|
||||
|
||||
async def analysis_example(compiler: SynorCompiler):
|
||||
"""Contract analysis."""
|
||||
print("=== Contract Analysis ===")
|
||||
|
||||
wasm = create_minimal_wasm()
|
||||
|
||||
# Full analysis
|
||||
analysis = await compiler.analysis.analyze(wasm)
|
||||
|
||||
# Size breakdown
|
||||
if analysis.size_breakdown:
|
||||
print("Size breakdown:")
|
||||
print(f" Code: {analysis.size_breakdown.code} bytes")
|
||||
print(f" Data: {analysis.size_breakdown.data} bytes")
|
||||
print(f" Functions: {analysis.size_breakdown.functions} bytes")
|
||||
print(f" Memory: {analysis.size_breakdown.memory} bytes")
|
||||
print(f" Exports: {analysis.size_breakdown.exports} bytes")
|
||||
print(f" Imports: {analysis.size_breakdown.imports} bytes")
|
||||
print(f" Total: {analysis.size_breakdown.total} bytes")
|
||||
|
||||
# Function analysis
|
||||
if analysis.functions:
|
||||
print("\nFunction analysis:")
|
||||
for func in analysis.functions[:5]:
|
||||
print(f" {func.name}:")
|
||||
print(f" Size: {func.size} bytes")
|
||||
print(f" Instructions: {func.instruction_count}")
|
||||
print(f" Locals: {func.local_count}")
|
||||
print(f" Exported: {func.exported}")
|
||||
print(f" Estimated gas: {func.estimated_gas}")
|
||||
|
||||
# Import analysis
|
||||
if analysis.imports:
|
||||
print("\nImports:")
|
||||
for imp in analysis.imports:
|
||||
print(f" {imp.module}.{imp.name} ({imp.kind})")
|
||||
|
||||
# Gas analysis
|
||||
if analysis.gas_analysis:
|
||||
print("\nGas analysis:")
|
||||
print(f" Deployment: {analysis.gas_analysis.deployment_gas}")
|
||||
print(f" Memory init: {analysis.gas_analysis.memory_init_gas}")
|
||||
print(f" Data section: {analysis.gas_analysis.data_section_gas}")
|
||||
|
||||
# Extract metadata
|
||||
metadata = await compiler.analysis.extract_metadata(wasm)
|
||||
print("\nContract metadata:")
|
||||
print(f" Name: {metadata.name}")
|
||||
print(f" Version: {metadata.version}")
|
||||
print(f" Build timestamp: {metadata.build_timestamp}")
|
||||
|
||||
# Estimate deployment gas
|
||||
gas = await compiler.analysis.estimate_deploy_gas(wasm)
|
||||
print(f"\nEstimated deployment gas: {gas}")
|
||||
|
||||
print()
|
||||
|
||||
|
||||
async def validation_example(compiler: SynorCompiler):
|
||||
"""Contract validation."""
|
||||
print("=== Contract Validation ===")
|
||||
|
||||
wasm = create_minimal_wasm()
|
||||
|
||||
# Full validation
|
||||
result = await compiler.validation.validate(wasm)
|
||||
print(f"Valid: {result.valid}")
|
||||
print(f"Exports: {result.export_count}")
|
||||
print(f"Imports: {result.import_count}")
|
||||
print(f"Functions: {result.function_count}")
|
||||
print(f"Memory pages: {result.memory_pages}")
|
||||
|
||||
if result.errors:
|
||||
print("\nValidation errors:")
|
||||
for error in result.errors:
|
||||
print(f" [{error.code}] {error.message}")
|
||||
if error.location:
|
||||
print(f" at {error.location}")
|
||||
|
||||
if result.warnings:
|
||||
print("\nWarnings:")
|
||||
for warning in result.warnings:
|
||||
print(f" {warning}")
|
||||
|
||||
# Quick validation
|
||||
is_valid = await compiler.validation.is_valid(wasm)
|
||||
print(f"\nQuick validation: {is_valid}")
|
||||
|
||||
# Get validation errors only
|
||||
errors = await compiler.validation.get_errors(wasm)
|
||||
print(f"Error count: {len(errors)}")
|
||||
|
||||
# Validate required exports
|
||||
has_required = await compiler.validation.validate_exports(
|
||||
wasm, ["init", "execute", "query"]
|
||||
)
|
||||
print(f"Has required exports: {has_required}")
|
||||
|
||||
# Validate memory constraints
|
||||
memory_valid = await compiler.validation.validate_memory(wasm, 16)
|
||||
print(f"Memory within 16 pages: {memory_valid}")
|
||||
|
||||
print()
|
||||
|
||||
|
||||
async def security_example(compiler: SynorCompiler):
|
||||
"""Security scanning."""
|
||||
print("=== Security Scanning ===")
|
||||
|
||||
wasm = create_minimal_wasm()
|
||||
|
||||
security = await compiler.analysis.security_scan(wasm)
|
||||
|
||||
print(f"Security score: {security.score}/100")
|
||||
|
||||
if security.issues:
|
||||
print("\nSecurity issues:")
|
||||
severity_icons = {
|
||||
"critical": "🔴",
|
||||
"high": "🟠",
|
||||
"medium": "🟡",
|
||||
"low": "🟢",
|
||||
}
|
||||
for issue in security.issues:
|
||||
icon = severity_icons.get(issue.severity, "⚪")
|
||||
print(f"{icon} [{issue.severity.upper()}] {issue.type}")
|
||||
print(f" {issue.description}")
|
||||
if issue.location:
|
||||
print(f" at {issue.location}")
|
||||
else:
|
||||
print("No security issues found!")
|
||||
|
||||
if security.recommendations:
|
||||
print("\nRecommendations:")
|
||||
for rec in security.recommendations:
|
||||
print(f" • {rec}")
|
||||
|
||||
print()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
265
sdk/python/examples/crypto_example.py
Normal file
265
sdk/python/examples/crypto_example.py
Normal file
|
|
@ -0,0 +1,265 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
Synor Crypto SDK Examples for Python
|
||||
|
||||
Demonstrates quantum-resistant cryptographic operations including:
|
||||
- Hybrid Ed25519 + Dilithium3 signatures
|
||||
- BIP-39 mnemonic generation and validation
|
||||
- Post-quantum algorithms (Falcon, SPHINCS+)
|
||||
- Key derivation functions
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import os
|
||||
from synor_crypto import (
|
||||
SynorCrypto,
|
||||
CryptoConfig,
|
||||
Network,
|
||||
FalconVariant,
|
||||
SphincsVariant,
|
||||
DerivationConfig,
|
||||
PasswordDerivationConfig,
|
||||
DerivationPath,
|
||||
)
|
||||
|
||||
|
||||
async def main():
|
||||
"""Main entry point."""
|
||||
# Initialize client
|
||||
config = CryptoConfig(
|
||||
api_key=os.environ.get("SYNOR_API_KEY", "your-api-key"),
|
||||
endpoint="https://crypto.synor.io/v1",
|
||||
timeout=30000,
|
||||
retries=3,
|
||||
debug=False,
|
||||
default_network=Network.MAINNET,
|
||||
)
|
||||
|
||||
crypto = SynorCrypto(config)
|
||||
|
||||
try:
|
||||
# Check service health
|
||||
healthy = await crypto.health_check()
|
||||
print(f"Service healthy: {healthy}\n")
|
||||
|
||||
# Example 1: Mnemonic operations
|
||||
await mnemonic_example(crypto)
|
||||
|
||||
# Example 2: Keypair generation
|
||||
await keypair_example(crypto)
|
||||
|
||||
# Example 3: Hybrid signing
|
||||
await signing_example(crypto)
|
||||
|
||||
# Example 4: Falcon post-quantum signatures
|
||||
await falcon_example(crypto)
|
||||
|
||||
# Example 5: SPHINCS+ post-quantum signatures
|
||||
await sphincs_example(crypto)
|
||||
|
||||
# Example 6: Key derivation
|
||||
await kdf_example(crypto)
|
||||
|
||||
# Example 7: Hashing
|
||||
await hash_example(crypto)
|
||||
finally:
|
||||
await crypto.close()
|
||||
|
||||
|
||||
async def mnemonic_example(crypto: SynorCrypto):
|
||||
"""Mnemonic generation and validation."""
|
||||
print("=== Mnemonic Operations ===")
|
||||
|
||||
# Generate a 24-word mnemonic (256-bit entropy)
|
||||
mnemonic = await crypto.mnemonic.generate(24)
|
||||
print(f"Generated mnemonic: {mnemonic.phrase}")
|
||||
print(f"Word count: {mnemonic.word_count}")
|
||||
|
||||
# Validate a mnemonic
|
||||
validation = await crypto.mnemonic.validate(mnemonic.phrase)
|
||||
print(f"Valid: {validation.valid}")
|
||||
if not validation.valid:
|
||||
print(f"Error: {validation.error}")
|
||||
|
||||
# Convert mnemonic to seed
|
||||
seed = await crypto.mnemonic.to_seed(mnemonic.phrase, "optional-passphrase")
|
||||
print(f"Seed (hex): {seed.hex()[:32]}...")
|
||||
|
||||
# Word suggestions for autocomplete
|
||||
suggestions = await crypto.mnemonic.suggest_words("aban", 5)
|
||||
print(f"Suggestions for 'aban': {', '.join(suggestions)}")
|
||||
|
||||
print()
|
||||
|
||||
|
||||
async def keypair_example(crypto: SynorCrypto):
|
||||
"""Keypair generation and address derivation."""
|
||||
print("=== Keypair Operations ===")
|
||||
|
||||
# Generate a random keypair
|
||||
keypair = await crypto.keypairs.generate()
|
||||
print("Generated hybrid keypair:")
|
||||
print(f" Ed25519 public key size: {len(keypair.public_key.ed25519_bytes)} bytes")
|
||||
print(f" Dilithium public key size: {len(keypair.public_key.dilithium_bytes)} bytes")
|
||||
print(f" Total public key size: {keypair.public_key.size} bytes")
|
||||
|
||||
# Get addresses for different networks
|
||||
print("\nAddresses:")
|
||||
print(f" Mainnet: {keypair.get_address(Network.MAINNET)}")
|
||||
print(f" Testnet: {keypair.get_address(Network.TESTNET)}")
|
||||
print(f" Devnet: {keypair.get_address(Network.DEVNET)}")
|
||||
|
||||
# Create keypair from mnemonic (deterministic)
|
||||
mnemonic = await crypto.mnemonic.generate(24)
|
||||
keypair2 = await crypto.keypairs.from_mnemonic(mnemonic.phrase, "")
|
||||
print(f"\nKeypair from mnemonic: {keypair2.get_address(Network.MAINNET)[:20]}...")
|
||||
|
||||
# Derive child keypair using BIP-44 path
|
||||
path = DerivationPath.external(0, 0) # m/44'/21337'/0'/0/0
|
||||
print(f"Derivation path: {path}")
|
||||
|
||||
print()
|
||||
|
||||
|
||||
async def signing_example(crypto: SynorCrypto):
|
||||
"""Hybrid signature operations (Ed25519 + Dilithium3)."""
|
||||
print("=== Hybrid Signing ===")
|
||||
|
||||
# Generate keypair
|
||||
keypair = await crypto.keypairs.generate()
|
||||
|
||||
# Sign a message
|
||||
message = b"Hello, quantum-resistant world!"
|
||||
signature = await crypto.signing.sign(keypair, message)
|
||||
|
||||
print("Signature created:")
|
||||
print(f" Ed25519 component: {len(signature.ed25519_bytes)} bytes")
|
||||
print(f" Dilithium component: {len(signature.dilithium_bytes)} bytes")
|
||||
print(f" Total signature size: {signature.size} bytes")
|
||||
|
||||
# Verify the signature
|
||||
valid = await crypto.signing.verify(keypair.public_key, message, signature)
|
||||
print(f"\nVerification result: {valid}")
|
||||
|
||||
# Verify with tampered message fails
|
||||
tampered_message = b"Hello, tampered message!"
|
||||
invalid_result = await crypto.signing.verify(
|
||||
keypair.public_key, tampered_message, signature
|
||||
)
|
||||
print(f"Tampered message verification: {invalid_result}")
|
||||
|
||||
print()
|
||||
|
||||
|
||||
async def falcon_example(crypto: SynorCrypto):
|
||||
"""Falcon post-quantum signature example."""
|
||||
print("=== Falcon Post-Quantum Signatures ===")
|
||||
|
||||
# Generate Falcon-512 keypair (128-bit security)
|
||||
falcon512 = await crypto.falcon.generate(FalconVariant.FALCON512)
|
||||
print("Falcon-512 keypair:")
|
||||
print(f" Public key: {len(falcon512.public_key.key_bytes)} bytes")
|
||||
print(f" Security level: 128-bit")
|
||||
|
||||
# Generate Falcon-1024 keypair (256-bit security)
|
||||
falcon1024 = await crypto.falcon.generate(FalconVariant.FALCON1024)
|
||||
print("\nFalcon-1024 keypair:")
|
||||
print(f" Public key: {len(falcon1024.public_key.key_bytes)} bytes")
|
||||
print(f" Security level: 256-bit")
|
||||
|
||||
# Sign with Falcon-512
|
||||
message = b"Post-quantum secure message"
|
||||
signature = await crypto.falcon.sign(falcon512, message)
|
||||
print(f"\nFalcon-512 signature: {len(signature.signature_bytes)} bytes")
|
||||
|
||||
# Verify
|
||||
valid = await crypto.falcon.verify(
|
||||
falcon512.public_key.key_bytes, message, signature
|
||||
)
|
||||
print(f"Verification: {valid}")
|
||||
|
||||
print()
|
||||
|
||||
|
||||
async def sphincs_example(crypto: SynorCrypto):
|
||||
"""SPHINCS+ post-quantum signature example (hash-based)."""
|
||||
print("=== SPHINCS+ Hash-Based Signatures ===")
|
||||
|
||||
# SPHINCS+ variants with different security levels
|
||||
variants = [
|
||||
(SphincsVariant.SHAKE128S, 128, 7856),
|
||||
(SphincsVariant.SHAKE192S, 192, 16224),
|
||||
(SphincsVariant.SHAKE256S, 256, 29792),
|
||||
]
|
||||
|
||||
# Generate and demonstrate each variant
|
||||
for variant, security, sig_size in variants:
|
||||
keypair = await crypto.sphincs.generate(variant)
|
||||
print(f"SPHINCS+ {variant.value}:")
|
||||
print(f" Security level: {security}-bit")
|
||||
print(f" Expected signature size: {sig_size} bytes")
|
||||
|
||||
# Sign a message
|
||||
message = b"Hash-based quantum security"
|
||||
signature = await crypto.sphincs.sign(keypair, message)
|
||||
print(f" Actual signature size: {len(signature.signature_bytes)} bytes")
|
||||
|
||||
# Verify
|
||||
valid = await crypto.sphincs.verify(
|
||||
keypair.public_key.key_bytes, message, signature
|
||||
)
|
||||
print(f" Verification: {valid}\n")
|
||||
|
||||
|
||||
async def kdf_example(crypto: SynorCrypto):
|
||||
"""Key derivation functions."""
|
||||
print("=== Key Derivation Functions ===")
|
||||
|
||||
# HKDF (HMAC-based Key Derivation Function)
|
||||
seed = b"master-secret-key-material-here"
|
||||
hkdf_config = DerivationConfig(
|
||||
salt=b"application-salt",
|
||||
info=b"encryption-key",
|
||||
output_length=32,
|
||||
)
|
||||
|
||||
derived_key = await crypto.kdf.derive_key(seed, hkdf_config)
|
||||
print(f"HKDF derived key: {derived_key.hex()}")
|
||||
|
||||
# PBKDF2 (Password-Based Key Derivation Function)
|
||||
password = b"user-password"
|
||||
pbkdf2_config = PasswordDerivationConfig(
|
||||
salt=b"random-salt-value",
|
||||
iterations=100000,
|
||||
output_length=32,
|
||||
)
|
||||
|
||||
password_key = await crypto.kdf.derive_from_password(password, pbkdf2_config)
|
||||
print(f"PBKDF2 derived key: {password_key.hex()}")
|
||||
|
||||
print()
|
||||
|
||||
|
||||
async def hash_example(crypto: SynorCrypto):
|
||||
"""Cryptographic hash functions."""
|
||||
print("=== Hash Functions ===")
|
||||
|
||||
data = b"Data to hash"
|
||||
|
||||
# SHA3-256 (FIPS 202)
|
||||
sha3 = await crypto.hash.sha3_256(data)
|
||||
print(f"SHA3-256: {sha3.hex}")
|
||||
|
||||
# BLAKE3 (fast, parallel)
|
||||
blake3 = await crypto.hash.blake3(data)
|
||||
print(f"BLAKE3: {blake3.hex}")
|
||||
|
||||
# Keccak-256 (Ethereum compatible)
|
||||
keccak = await crypto.hash.keccak256(data)
|
||||
print(f"Keccak: {keccak.hex}")
|
||||
|
||||
print()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
450
sdk/python/examples/dex_example.py
Normal file
450
sdk/python/examples/dex_example.py
Normal file
|
|
@ -0,0 +1,450 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
Synor DEX SDK Examples for Python
|
||||
|
||||
Demonstrates decentralized exchange operations:
|
||||
- Spot trading (market/limit orders)
|
||||
- Perpetual futures trading
|
||||
- Liquidity provision
|
||||
- Order management
|
||||
- Real-time market data
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import os
|
||||
from synor_dex import (
|
||||
SynorDex,
|
||||
DexConfig,
|
||||
Network,
|
||||
OrderSide,
|
||||
OrderType,
|
||||
TimeInForce,
|
||||
PositionSide,
|
||||
MarginType,
|
||||
)
|
||||
|
||||
|
||||
async def main():
|
||||
"""Main entry point."""
|
||||
# Initialize client
|
||||
config = DexConfig(
|
||||
api_key=os.environ.get("SYNOR_API_KEY", "your-api-key"),
|
||||
endpoint="https://dex.synor.io/v1",
|
||||
ws_endpoint="wss://dex.synor.io/v1/ws",
|
||||
timeout=30000,
|
||||
retries=3,
|
||||
debug=False,
|
||||
default_network=Network.MAINNET,
|
||||
)
|
||||
|
||||
dex = SynorDex(config)
|
||||
|
||||
try:
|
||||
# Check service health
|
||||
healthy = await dex.health_check()
|
||||
print(f"Service healthy: {healthy}\n")
|
||||
|
||||
# Example 1: Market data
|
||||
await market_data_example(dex)
|
||||
|
||||
# Example 2: Spot trading
|
||||
await spot_trading_example(dex)
|
||||
|
||||
# Example 3: Perpetual futures
|
||||
await perpetual_futures_example(dex)
|
||||
|
||||
# Example 4: Liquidity provision
|
||||
await liquidity_example(dex)
|
||||
|
||||
# Example 5: Order management
|
||||
await order_management_example(dex)
|
||||
|
||||
# Example 6: Account information
|
||||
await account_example(dex)
|
||||
|
||||
# Example 7: Real-time streaming
|
||||
await streaming_example(dex)
|
||||
finally:
|
||||
await dex.close()
|
||||
|
||||
|
||||
async def market_data_example(dex: SynorDex):
|
||||
"""Market data and orderbook."""
|
||||
print("=== Market Data ===")
|
||||
|
||||
# Get all trading pairs
|
||||
pairs = await dex.markets.get_pairs()
|
||||
print(f"Available trading pairs: {len(pairs)}")
|
||||
for pair in pairs[:5]:
|
||||
print(f" {pair.symbol}: {pair.base_asset}/{pair.quote_asset}")
|
||||
|
||||
# Get ticker for a specific pair
|
||||
ticker = await dex.markets.get_ticker("SYN-USDT")
|
||||
print(f"\nSYN-USDT Ticker:")
|
||||
print(f" Last price: ${ticker.last_price}")
|
||||
print(f" 24h change: {ticker.price_change_percent}%")
|
||||
print(f" 24h high: ${ticker.high_price}")
|
||||
print(f" 24h low: ${ticker.low_price}")
|
||||
print(f" 24h volume: {ticker.volume} SYN")
|
||||
print(f" 24h quote volume: ${ticker.quote_volume}")
|
||||
|
||||
# Get orderbook
|
||||
orderbook = await dex.markets.get_orderbook("SYN-USDT", depth=10)
|
||||
print(f"\nOrderbook (top 5):")
|
||||
print(" Bids:")
|
||||
for bid in orderbook.bids[:5]:
|
||||
print(f" ${bid.price} - {bid.quantity} SYN")
|
||||
print(" Asks:")
|
||||
for ask in orderbook.asks[:5]:
|
||||
print(f" ${ask.price} - {ask.quantity} SYN")
|
||||
|
||||
# Get recent trades
|
||||
trades = await dex.markets.get_trades("SYN-USDT", limit=5)
|
||||
print(f"\nRecent trades:")
|
||||
for trade in trades:
|
||||
side = "SELL" if trade.is_buyer_maker else "BUY"
|
||||
print(f" {side} {trade.quantity} @ ${trade.price}")
|
||||
|
||||
# Get OHLCV candles
|
||||
candles = await dex.markets.get_candles("SYN-USDT", interval="1h", limit=5)
|
||||
print(f"\nHourly candles:")
|
||||
for candle in candles:
|
||||
print(f" {candle.open_time}: O={candle.open} H={candle.high} L={candle.low} C={candle.close}")
|
||||
|
||||
print()
|
||||
|
||||
|
||||
async def spot_trading_example(dex: SynorDex):
|
||||
"""Spot trading operations."""
|
||||
print("=== Spot Trading ===")
|
||||
|
||||
# Place a market buy order
|
||||
print("Placing market buy order...")
|
||||
market_buy = await dex.spot.create_order(
|
||||
symbol="SYN-USDT",
|
||||
side=OrderSide.BUY,
|
||||
order_type=OrderType.MARKET,
|
||||
quantity=10, # Buy 10 SYN
|
||||
)
|
||||
print(f"Market buy order: {market_buy.order_id}")
|
||||
print(f" Status: {market_buy.status}")
|
||||
print(f" Filled: {market_buy.executed_qty} SYN")
|
||||
print(f" Avg price: ${market_buy.avg_price}")
|
||||
|
||||
# Place a limit sell order
|
||||
print("\nPlacing limit sell order...")
|
||||
limit_sell = await dex.spot.create_order(
|
||||
symbol="SYN-USDT",
|
||||
side=OrderSide.SELL,
|
||||
order_type=OrderType.LIMIT,
|
||||
quantity=5,
|
||||
price=15.50, # Sell at $15.50
|
||||
time_in_force=TimeInForce.GTC, # Good till cancelled
|
||||
)
|
||||
print(f"Limit sell order: {limit_sell.order_id}")
|
||||
print(f" Price: ${limit_sell.price}")
|
||||
print(f" Status: {limit_sell.status}")
|
||||
|
||||
# Place a stop-loss order
|
||||
print("\nPlacing stop-loss order...")
|
||||
stop_loss = await dex.spot.create_order(
|
||||
symbol="SYN-USDT",
|
||||
side=OrderSide.SELL,
|
||||
order_type=OrderType.STOP_LOSS,
|
||||
quantity=10,
|
||||
stop_price=12.00, # Trigger at $12.00
|
||||
)
|
||||
print(f"Stop-loss order: {stop_loss.order_id}")
|
||||
print(f" Stop price: ${stop_loss.stop_price}")
|
||||
|
||||
# Place a take-profit limit order
|
||||
print("\nPlacing take-profit order...")
|
||||
take_profit = await dex.spot.create_order(
|
||||
symbol="SYN-USDT",
|
||||
side=OrderSide.SELL,
|
||||
order_type=OrderType.TAKE_PROFIT_LIMIT,
|
||||
quantity=10,
|
||||
price=20.00, # Sell at $20.00
|
||||
stop_price=19.50, # Trigger at $19.50
|
||||
time_in_force=TimeInForce.GTC,
|
||||
)
|
||||
print(f"Take-profit order: {take_profit.order_id}")
|
||||
|
||||
print()
|
||||
|
||||
|
||||
async def perpetual_futures_example(dex: SynorDex):
|
||||
"""Perpetual futures trading."""
|
||||
print("=== Perpetual Futures ===")
|
||||
|
||||
# Get perpetual markets
|
||||
markets = await dex.perpetuals.get_markets()
|
||||
print(f"Available perpetual markets: {len(markets)}")
|
||||
for market in markets[:3]:
|
||||
print(f" {market.symbol}: {market.max_leverage}x max leverage, {market.maintenance_margin_rate}% MMR")
|
||||
|
||||
# Get funding rate
|
||||
funding = await dex.perpetuals.get_funding_rate("SYN-USDT-PERP")
|
||||
print(f"\nFunding rate for SYN-USDT-PERP:")
|
||||
print(f" Current rate: {funding.funding_rate * 100:.4f}%")
|
||||
print(f" Predicted rate: {funding.predicted_rate * 100:.4f}%")
|
||||
print(f" Next funding: {funding.next_funding_time}")
|
||||
|
||||
# Set leverage
|
||||
await dex.perpetuals.set_leverage("SYN-USDT-PERP", 10)
|
||||
print("\nLeverage set to 10x")
|
||||
|
||||
# Set margin type (isolated/cross)
|
||||
await dex.perpetuals.set_margin_type("SYN-USDT-PERP", MarginType.ISOLATED)
|
||||
print("Margin type set to Isolated")
|
||||
|
||||
# Open a long position
|
||||
print("\nOpening long position...")
|
||||
long_order = await dex.perpetuals.create_order(
|
||||
symbol="SYN-USDT-PERP",
|
||||
side=OrderSide.BUY,
|
||||
position_side=PositionSide.LONG,
|
||||
order_type=OrderType.MARKET,
|
||||
quantity=100, # 100 contracts
|
||||
)
|
||||
print(f"Long position opened: {long_order.order_id}")
|
||||
print(f" Entry price: ${long_order.avg_price}")
|
||||
print(f" Position size: {long_order.executed_qty} contracts")
|
||||
|
||||
# Set stop-loss and take-profit
|
||||
print("\nSetting SL/TP...")
|
||||
await dex.perpetuals.create_order(
|
||||
symbol="SYN-USDT-PERP",
|
||||
side=OrderSide.SELL,
|
||||
position_side=PositionSide.LONG,
|
||||
order_type=OrderType.STOP_MARKET,
|
||||
quantity=100,
|
||||
stop_price=12.00, # Stop-loss at $12
|
||||
reduce_only=True,
|
||||
)
|
||||
print(" Stop-loss set at $12.00")
|
||||
|
||||
await dex.perpetuals.create_order(
|
||||
symbol="SYN-USDT-PERP",
|
||||
side=OrderSide.SELL,
|
||||
position_side=PositionSide.LONG,
|
||||
order_type=OrderType.TAKE_PROFIT_MARKET,
|
||||
quantity=100,
|
||||
stop_price=18.00, # Take-profit at $18
|
||||
reduce_only=True,
|
||||
)
|
||||
print(" Take-profit set at $18.00")
|
||||
|
||||
# Get position info
|
||||
positions = await dex.perpetuals.get_positions("SYN-USDT-PERP")
|
||||
for pos in positions:
|
||||
print(f"\nPosition info:")
|
||||
print(f" Symbol: {pos.symbol}")
|
||||
print(f" Side: {pos.position_side}")
|
||||
print(f" Size: {pos.position_amount} contracts")
|
||||
print(f" Entry: ${pos.entry_price}")
|
||||
print(f" Mark: ${pos.mark_price}")
|
||||
print(f" PnL: ${pos.unrealized_pnl} ({pos.unrealized_pnl_percent}%)")
|
||||
print(f" Leverage: {pos.leverage}x")
|
||||
print(f" Liq. price: ${pos.liquidation_price}")
|
||||
|
||||
# Close position
|
||||
print("\nClosing position...")
|
||||
await dex.perpetuals.close_position("SYN-USDT-PERP", PositionSide.LONG)
|
||||
print("Position closed")
|
||||
|
||||
print()
|
||||
|
||||
|
||||
async def liquidity_example(dex: SynorDex):
|
||||
"""Liquidity provision."""
|
||||
print("=== Liquidity Provision ===")
|
||||
|
||||
# Get available pools
|
||||
pools = await dex.liquidity.get_pools()
|
||||
print(f"Available liquidity pools: {len(pools)}")
|
||||
for pool in pools[:3]:
|
||||
print(f" {pool.name}:")
|
||||
print(f" TVL: ${pool.tvl:,.0f}")
|
||||
print(f" APY: {pool.apy:.2f}%")
|
||||
print(f" Fee tier: {pool.fee_tier}%")
|
||||
|
||||
# Get pool details
|
||||
pool = await dex.liquidity.get_pool("SYN-USDT")
|
||||
print(f"\nSYN-USDT Pool details:")
|
||||
print(f" Reserve A: {pool.reserve_a} SYN")
|
||||
print(f" Reserve B: {pool.reserve_b} USDT")
|
||||
print(f" Total shares: {pool.total_shares}")
|
||||
print(f" Your shares: {pool.user_shares}")
|
||||
|
||||
# Add liquidity
|
||||
print("\nAdding liquidity...")
|
||||
add_result = await dex.liquidity.add_liquidity(
|
||||
pool_id="SYN-USDT",
|
||||
amount_a=100, # 100 SYN
|
||||
amount_b=1400, # 1400 USDT
|
||||
slippage_tolerance=0.5, # 0.5% slippage
|
||||
)
|
||||
print(f"Liquidity added:")
|
||||
print(f" Shares received: {add_result.shares_received}")
|
||||
print(f" Amount A deposited: {add_result.amount_a_deposited}")
|
||||
print(f" Amount B deposited: {add_result.amount_b_deposited}")
|
||||
|
||||
# Get LP positions
|
||||
lp_positions = await dex.liquidity.get_positions()
|
||||
print(f"\nYour LP positions:")
|
||||
for lp in lp_positions:
|
||||
print(f" {lp.pool_id}: {lp.shares} shares (${lp.value_usd})")
|
||||
print(f" Fees earned: ${lp.fees_earned}")
|
||||
|
||||
# Remove liquidity
|
||||
print("\nRemoving liquidity...")
|
||||
remove_result = await dex.liquidity.remove_liquidity(
|
||||
pool_id="SYN-USDT",
|
||||
shares=add_result.shares_received * 0.5, # Remove 50%
|
||||
slippage_tolerance=0.5,
|
||||
)
|
||||
print(f"Liquidity removed:")
|
||||
print(f" Amount A received: {remove_result.amount_a_received}")
|
||||
print(f" Amount B received: {remove_result.amount_b_received}")
|
||||
|
||||
print()
|
||||
|
||||
|
||||
async def order_management_example(dex: SynorDex):
|
||||
"""Order management."""
|
||||
print("=== Order Management ===")
|
||||
|
||||
# Get open orders
|
||||
open_orders = await dex.orders.get_open_orders("SYN-USDT")
|
||||
print(f"Open orders: {len(open_orders)}")
|
||||
for order in open_orders:
|
||||
print(f" {order.order_id}: {order.side} {order.quantity} @ ${order.price}")
|
||||
|
||||
# Get order history
|
||||
history = await dex.orders.get_order_history(symbol="SYN-USDT", limit=5)
|
||||
print(f"\nOrder history (last 5):")
|
||||
for order in history:
|
||||
print(f" {order.order_id}: {order.side} {order.quantity} {order.status}")
|
||||
|
||||
# Get specific order
|
||||
if open_orders:
|
||||
order = await dex.orders.get_order(open_orders[0].order_id)
|
||||
print(f"\nOrder details:")
|
||||
print(f" Symbol: {order.symbol}")
|
||||
print(f" Type: {order.order_type}")
|
||||
print(f" Side: {order.side}")
|
||||
print(f" Quantity: {order.quantity}")
|
||||
print(f" Filled: {order.executed_qty}")
|
||||
print(f" Status: {order.status}")
|
||||
|
||||
# Cancel a specific order
|
||||
if open_orders:
|
||||
print("\nCancelling order...")
|
||||
cancelled = await dex.orders.cancel_order(open_orders[0].order_id)
|
||||
print(f"Order {cancelled.order_id} cancelled")
|
||||
|
||||
# Cancel all orders for a symbol
|
||||
print("\nCancelling all SYN-USDT orders...")
|
||||
cancelled_orders = await dex.orders.cancel_all_orders("SYN-USDT")
|
||||
print(f"Cancelled {len(cancelled_orders)} orders")
|
||||
|
||||
# Get trade history
|
||||
trades = await dex.orders.get_trade_history(symbol="SYN-USDT", limit=5)
|
||||
print(f"\nTrade history (last 5):")
|
||||
for trade in trades:
|
||||
print(f" {trade.side} {trade.quantity} @ ${trade.price} (fee: ${trade.fee})")
|
||||
|
||||
print()
|
||||
|
||||
|
||||
async def account_example(dex: SynorDex):
|
||||
"""Account information."""
|
||||
print("=== Account Information ===")
|
||||
|
||||
# Get account balances
|
||||
balances = await dex.account.get_balances()
|
||||
print("Balances:")
|
||||
for balance in balances:
|
||||
if float(balance.total) > 0:
|
||||
print(f" {balance.asset}: {balance.free} free, {balance.locked} locked")
|
||||
|
||||
# Get account summary
|
||||
summary = await dex.account.get_summary()
|
||||
print(f"\nAccount summary:")
|
||||
print(f" Total equity: ${summary.total_equity}")
|
||||
print(f" Available margin: ${summary.available_margin}")
|
||||
print(f" Used margin: ${summary.used_margin}")
|
||||
print(f" Margin level: {summary.margin_level}%")
|
||||
print(f" Unrealized PnL: ${summary.unrealized_pnl}")
|
||||
|
||||
# Get deposit address
|
||||
deposit_addr = await dex.account.get_deposit_address("SYN")
|
||||
print(f"\nDeposit address for SYN: {deposit_addr.address}")
|
||||
|
||||
# Get deposit/withdrawal history
|
||||
deposits = await dex.account.get_deposit_history(limit=3)
|
||||
print(f"\nRecent deposits:")
|
||||
for dep in deposits:
|
||||
print(f" {dep.asset}: {dep.amount} ({dep.status})")
|
||||
|
||||
withdrawals = await dex.account.get_withdrawal_history(limit=3)
|
||||
print(f"\nRecent withdrawals:")
|
||||
for wd in withdrawals:
|
||||
print(f" {wd.asset}: {wd.amount} ({wd.status})")
|
||||
|
||||
# Get fee rates
|
||||
fees = await dex.account.get_fee_rates("SYN-USDT")
|
||||
print(f"\nFee rates for SYN-USDT:")
|
||||
print(f" Maker: {fees.maker_rate}%")
|
||||
print(f" Taker: {fees.taker_rate}%")
|
||||
|
||||
print()
|
||||
|
||||
|
||||
async def streaming_example(dex: SynorDex):
|
||||
"""Real-time WebSocket streaming."""
|
||||
print("=== Real-time Streaming ===")
|
||||
|
||||
received_count = 0
|
||||
|
||||
def on_ticker(ticker):
|
||||
nonlocal received_count
|
||||
received_count += 1
|
||||
print(f" Ticker: ${ticker.last_price} ({ticker.price_change_percent}%)")
|
||||
|
||||
def on_orderbook(orderbook):
|
||||
print(f" Best bid: ${orderbook.bids[0].price if orderbook.bids else 'N/A'}, "
|
||||
f"Best ask: ${orderbook.asks[0].price if orderbook.asks else 'N/A'}")
|
||||
|
||||
def on_trade(trade):
|
||||
side = "SELL" if trade.is_buyer_maker else "BUY"
|
||||
print(f" Trade: {side} {trade.quantity} @ ${trade.price}")
|
||||
|
||||
# Subscribe to ticker updates
|
||||
print("Subscribing to SYN-USDT ticker...")
|
||||
ticker_unsub = await dex.streams.subscribe_ticker("SYN-USDT", on_ticker)
|
||||
|
||||
# Subscribe to orderbook updates
|
||||
print("Subscribing to orderbook...")
|
||||
orderbook_unsub = await dex.streams.subscribe_orderbook("SYN-USDT", on_orderbook)
|
||||
|
||||
# Subscribe to trades
|
||||
print("Subscribing to trades...")
|
||||
trades_unsub = await dex.streams.subscribe_trades("SYN-USDT", on_trade)
|
||||
|
||||
# Wait for some updates
|
||||
print("\nListening for 5 seconds...")
|
||||
await asyncio.sleep(5)
|
||||
|
||||
# Unsubscribe
|
||||
await ticker_unsub()
|
||||
await orderbook_unsub()
|
||||
await trades_unsub()
|
||||
print(f"Unsubscribed from all streams. Received {received_count} ticker updates.")
|
||||
|
||||
print()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
358
sdk/python/examples/ibc_example.py
Normal file
358
sdk/python/examples/ibc_example.py
Normal file
|
|
@ -0,0 +1,358 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
Synor IBC SDK Examples for Python
|
||||
|
||||
Demonstrates Inter-Blockchain Communication operations:
|
||||
- Cross-chain token transfers
|
||||
- Channel management
|
||||
- Packet handling
|
||||
- Relayer operations
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import os
|
||||
from datetime import datetime
|
||||
from synor_ibc import (
|
||||
SynorIbc,
|
||||
IbcConfig,
|
||||
Network,
|
||||
ChannelState,
|
||||
)
|
||||
|
||||
|
||||
async def main():
|
||||
"""Main entry point."""
|
||||
# Initialize client
|
||||
config = IbcConfig(
|
||||
api_key=os.environ.get("SYNOR_API_KEY", "your-api-key"),
|
||||
endpoint="https://ibc.synor.io/v1",
|
||||
timeout=30000,
|
||||
retries=3,
|
||||
debug=False,
|
||||
default_network=Network.MAINNET,
|
||||
)
|
||||
|
||||
ibc = SynorIbc(config)
|
||||
|
||||
try:
|
||||
# Check service health
|
||||
healthy = await ibc.health_check()
|
||||
print(f"Service healthy: {healthy}\n")
|
||||
|
||||
# Example 1: Connected chains
|
||||
await chains_example(ibc)
|
||||
|
||||
# Example 2: Channel management
|
||||
await channels_example(ibc)
|
||||
|
||||
# Example 3: Token transfers
|
||||
await transfer_example(ibc)
|
||||
|
||||
# Example 4: Packet tracking
|
||||
await packet_example(ibc)
|
||||
|
||||
# Example 5: Relayer operations
|
||||
await relayer_example(ibc)
|
||||
|
||||
# Example 6: Connection info
|
||||
await connection_example(ibc)
|
||||
finally:
|
||||
await ibc.close()
|
||||
|
||||
|
||||
async def chains_example(ibc: SynorIbc):
|
||||
"""Connected chains information."""
|
||||
print("=== Connected Chains ===")
|
||||
|
||||
# Get all connected chains
|
||||
chains = await ibc.chains.list()
|
||||
print(f"Connected chains: {len(chains)}")
|
||||
for chain in chains:
|
||||
print(f" {chain.chain_id}:")
|
||||
print(f" Name: {chain.name}")
|
||||
print(f" Status: {chain.status}")
|
||||
print(f" Block height: {chain.latest_height}")
|
||||
print(f" Channels: {chain.channel_count}")
|
||||
|
||||
# Get specific chain info
|
||||
cosmos = await ibc.chains.get("cosmoshub-4")
|
||||
print(f"\nCosmos Hub details:")
|
||||
print(f" RPC: {cosmos.rpc_endpoint}")
|
||||
print(f" Rest: {cosmos.rest_endpoint}")
|
||||
print(f" Native denom: {cosmos.native_denom}")
|
||||
print(f" Prefix: {cosmos.bech32_prefix}")
|
||||
|
||||
# Get supported assets on a chain
|
||||
assets = await ibc.chains.get_assets("cosmoshub-4")
|
||||
print(f"\nSupported assets on Cosmos Hub:")
|
||||
for asset in assets[:5]:
|
||||
print(f" {asset.symbol}: {asset.denom}")
|
||||
print(f" Origin: {asset.origin_chain}")
|
||||
print(f" Decimals: {asset.decimals}")
|
||||
|
||||
# Get chain paths (routes)
|
||||
paths = await ibc.chains.get_paths("synor-1", "cosmoshub-4")
|
||||
print(f"\nPaths from Synor to Cosmos Hub:")
|
||||
for path in paths:
|
||||
print(f" {path.source_channel} -> {path.dest_channel}")
|
||||
print(f" Hops: {path.hops}")
|
||||
print(f" Avg time: {path.avg_transfer_time}s")
|
||||
|
||||
print()
|
||||
|
||||
|
||||
async def channels_example(ibc: SynorIbc):
|
||||
"""Channel management."""
|
||||
print("=== Channel Management ===")
|
||||
|
||||
# List all channels
|
||||
channels = await ibc.channels.list()
|
||||
print(f"Total channels: {len(channels)}")
|
||||
|
||||
# Filter by state
|
||||
open_channels = [c for c in channels if c.state == ChannelState.OPEN]
|
||||
print(f"Open channels: {len(open_channels)}")
|
||||
|
||||
for channel in open_channels[:3]:
|
||||
print(f"\n Channel {channel.channel_id}:")
|
||||
print(f" Port: {channel.port_id}")
|
||||
print(f" Counterparty: {channel.counterparty_channel_id} on {channel.counterparty_chain_id}")
|
||||
print(f" Ordering: {channel.ordering}")
|
||||
print(f" Version: {channel.version}")
|
||||
print(f" State: {channel.state}")
|
||||
|
||||
# Get specific channel
|
||||
channel = await ibc.channels.get("channel-0")
|
||||
print(f"\nChannel-0 details:")
|
||||
print(f" Connection: {channel.connection_id}")
|
||||
print(f" Counterparty port: {channel.counterparty_port_id}")
|
||||
|
||||
# Get channel statistics
|
||||
stats = await ibc.channels.get_stats("channel-0")
|
||||
print(f"\nChannel-0 statistics:")
|
||||
print(f" Total packets sent: {stats.packets_sent}")
|
||||
print(f" Total packets received: {stats.packets_received}")
|
||||
print(f" Pending packets: {stats.pending_packets}")
|
||||
print(f" Success rate: {stats.success_rate}%")
|
||||
print(f" Avg relay time: {stats.avg_relay_time}s")
|
||||
|
||||
# Get channel capacity
|
||||
capacity = await ibc.channels.get_capacity("channel-0")
|
||||
print(f"\nChannel-0 capacity:")
|
||||
print(f" Max throughput: {capacity.max_packets_per_block} packets/block")
|
||||
print(f" Current utilization: {capacity.utilization}%")
|
||||
|
||||
print()
|
||||
|
||||
|
||||
async def transfer_example(ibc: SynorIbc):
|
||||
"""Cross-chain token transfers."""
|
||||
print("=== Cross-Chain Transfers ===")
|
||||
|
||||
# Estimate transfer fee
|
||||
estimate = await ibc.transfers.estimate_fee(
|
||||
source_chain="synor-1",
|
||||
dest_chain="cosmoshub-4",
|
||||
denom="usyn",
|
||||
amount="1000000", # 1 SYN (6 decimals)
|
||||
)
|
||||
print("Transfer fee estimate:")
|
||||
print(f" Gas: {estimate.gas}")
|
||||
print(f" Fee: {estimate.fee} {estimate.fee_denom}")
|
||||
print(f" Timeout: {estimate.timeout}s")
|
||||
|
||||
# Initiate a transfer
|
||||
print("\nInitiating transfer...")
|
||||
transfer = await ibc.transfers.send(
|
||||
source_chain="synor-1",
|
||||
dest_chain="cosmoshub-4",
|
||||
channel="channel-0",
|
||||
sender="synor1abc...", # Your address
|
||||
receiver="cosmos1xyz...", # Recipient address
|
||||
denom="usyn",
|
||||
amount="1000000", # 1 SYN
|
||||
memo="Cross-chain transfer example",
|
||||
timeout_height=0, # Use timestamp instead
|
||||
timeout_timestamp=int(datetime.now().timestamp() * 1000) + 600000, # 10 minutes
|
||||
)
|
||||
|
||||
print(f"Transfer initiated:")
|
||||
print(f" TX Hash: {transfer.tx_hash}")
|
||||
print(f" Sequence: {transfer.sequence}")
|
||||
print(f" Status: {transfer.status}")
|
||||
|
||||
# Track transfer status
|
||||
print("\nTracking transfer...")
|
||||
status = await ibc.transfers.get_status(transfer.tx_hash)
|
||||
print(f"Current status: {status.state}")
|
||||
print(f" Source confirmed: {status.source_confirmed}")
|
||||
print(f" Relayed: {status.relayed}")
|
||||
print(f" Dest confirmed: {status.dest_confirmed}")
|
||||
|
||||
# Get transfer history
|
||||
history = await ibc.transfers.get_history(address="synor1abc...", limit=5)
|
||||
print(f"\nTransfer history (last 5):")
|
||||
for tx in history:
|
||||
direction = "OUT" if tx.sender == "synor1abc..." else "IN"
|
||||
print(f" {direction} {tx.amount} {tx.denom} ({tx.status})")
|
||||
|
||||
# Get pending transfers
|
||||
pending = await ibc.transfers.get_pending("synor1abc...")
|
||||
print(f"\nPending transfers: {len(pending)}")
|
||||
|
||||
print()
|
||||
|
||||
|
||||
async def packet_example(ibc: SynorIbc):
|
||||
"""Packet handling."""
|
||||
print("=== Packet Handling ===")
|
||||
|
||||
# Get pending packets
|
||||
packets = await ibc.packets.get_pending("channel-0")
|
||||
print(f"Pending packets on channel-0: {len(packets)}")
|
||||
|
||||
for packet in packets[:3]:
|
||||
print(f"\n Packet {packet.sequence}:")
|
||||
print(f" Source: {packet.source_port}/{packet.source_channel}")
|
||||
print(f" Dest: {packet.dest_port}/{packet.dest_channel}")
|
||||
print(f" State: {packet.state}")
|
||||
print(f" Data size: {len(packet.data)} bytes")
|
||||
print(f" Timeout height: {packet.timeout_height}")
|
||||
print(f" Timeout timestamp: {packet.timeout_timestamp}")
|
||||
|
||||
# Get packet by sequence
|
||||
packet = await ibc.packets.get("channel-0", 1)
|
||||
print(f"\nPacket details:")
|
||||
print(f" Commitment: {packet.commitment}")
|
||||
print(f" Receipt: {packet.receipt}")
|
||||
print(f" Acknowledgement: {packet.acknowledgement}")
|
||||
|
||||
# Get packet receipts
|
||||
receipts = await ibc.packets.get_receipts("channel-0", [1, 2, 3])
|
||||
print(f"\nPacket receipts:")
|
||||
for seq, receipt in receipts.items():
|
||||
print(f" Sequence {seq}: {'received' if receipt else 'not received'}")
|
||||
|
||||
# Get timed out packets
|
||||
timed_out = await ibc.packets.get_timed_out("channel-0")
|
||||
print(f"\nTimed out packets: {len(timed_out)}")
|
||||
for p in timed_out:
|
||||
print(f" Sequence {p.sequence}: timeout at {p.timeout_timestamp}")
|
||||
|
||||
# Get unreceived packets
|
||||
unreceived = await ibc.packets.get_unreceived("channel-0")
|
||||
print(f"\nUnreceived packet sequences: {', '.join(map(str, unreceived)) or 'none'}")
|
||||
|
||||
# Get unacknowledged packets
|
||||
unacked = await ibc.packets.get_unacknowledged("channel-0")
|
||||
print(f"Unacknowledged packet sequences: {', '.join(map(str, unacked)) or 'none'}")
|
||||
|
||||
print()
|
||||
|
||||
|
||||
async def relayer_example(ibc: SynorIbc):
|
||||
"""Relayer operations."""
|
||||
print("=== Relayer Operations ===")
|
||||
|
||||
# Get active relayers
|
||||
relayers = await ibc.relayers.list()
|
||||
print(f"Active relayers: {len(relayers)}")
|
||||
for relayer in relayers[:3]:
|
||||
print(f"\n {relayer.address}:")
|
||||
print(f" Chains: {', '.join(relayer.chains)}")
|
||||
print(f" Packets relayed: {relayer.packets_relayed}")
|
||||
print(f" Success rate: {relayer.success_rate}%")
|
||||
print(f" Avg latency: {relayer.avg_latency}ms")
|
||||
print(f" Fee rate: {relayer.fee_rate}%")
|
||||
|
||||
# Get relayer statistics
|
||||
stats = await ibc.relayers.get_stats()
|
||||
print("\nGlobal relayer statistics:")
|
||||
print(f" Total relayers: {stats.total_relayers}")
|
||||
print(f" Active relayers: {stats.active_relayers}")
|
||||
print(f" Packets relayed (24h): {stats.packets_relayed_24h}")
|
||||
print(f" Total fees earned: {stats.total_fees_earned}")
|
||||
|
||||
# Register as a relayer
|
||||
print("\nRegistering as relayer...")
|
||||
registration = await ibc.relayers.register(
|
||||
chains=["synor-1", "cosmoshub-4"],
|
||||
fee_rate=0.1, # 0.1% fee
|
||||
min_packet_size=0,
|
||||
max_packet_size=1000000,
|
||||
)
|
||||
print(f"Registered with address: {registration.relayer_address}")
|
||||
|
||||
# Start relaying (in background)
|
||||
print("\nStarting relay service...")
|
||||
relay_session = await ibc.relayers.start_relay(
|
||||
channels=["channel-0"],
|
||||
auto_ack=True,
|
||||
batch_size=10,
|
||||
poll_interval=5000,
|
||||
)
|
||||
print(f"Relay session started: {relay_session.session_id}")
|
||||
|
||||
# Get relay queue
|
||||
queue = await ibc.relayers.get_queue("channel-0")
|
||||
print(f"\nRelay queue for channel-0: {len(queue)} packets")
|
||||
|
||||
# Manually relay a packet
|
||||
if queue:
|
||||
print("\nRelaying packet...")
|
||||
relay_result = await ibc.relayers.relay_packet(queue[0].sequence, "channel-0")
|
||||
print(f"Relay result: {relay_result.status}")
|
||||
print(f" TX Hash: {relay_result.tx_hash}")
|
||||
print(f" Fee earned: {relay_result.fee_earned}")
|
||||
|
||||
# Stop relay session
|
||||
await ibc.relayers.stop_relay(relay_session.session_id)
|
||||
print("\nRelay session stopped")
|
||||
|
||||
print()
|
||||
|
||||
|
||||
async def connection_example(ibc: SynorIbc):
|
||||
"""Connection information."""
|
||||
print("=== Connection Information ===")
|
||||
|
||||
# List connections
|
||||
connections = await ibc.connections.list()
|
||||
print(f"Total connections: {len(connections)}")
|
||||
|
||||
for conn in connections[:3]:
|
||||
print(f"\n {conn.connection_id}:")
|
||||
print(f" Client: {conn.client_id}")
|
||||
print(f" Counterparty: {conn.counterparty_connection_id}")
|
||||
print(f" State: {conn.state}")
|
||||
print(f" Versions: {', '.join(conn.versions)}")
|
||||
|
||||
# Get connection details
|
||||
connection = await ibc.connections.get("connection-0")
|
||||
print(f"\nConnection-0 details:")
|
||||
print(f" Delay period: {connection.delay_period}ns")
|
||||
print(f" Counterparty client: {connection.counterparty_client_id}")
|
||||
print(f" Counterparty prefix: {connection.counterparty_prefix}")
|
||||
|
||||
# Get client state
|
||||
client = await ibc.clients.get(connection.client_id)
|
||||
print(f"\nClient state:")
|
||||
print(f" Chain ID: {client.chain_id}")
|
||||
print(f" Trust level: {client.trust_level}")
|
||||
print(f" Trusting period: {client.trusting_period}")
|
||||
print(f" Unbonding period: {client.unbonding_period}")
|
||||
print(f" Latest height: {client.latest_height}")
|
||||
print(f" Frozen: {client.frozen}")
|
||||
|
||||
# Get consensus state
|
||||
consensus = await ibc.clients.get_consensus_state(connection.client_id, client.latest_height)
|
||||
print(f"\nConsensus state at height {client.latest_height}:")
|
||||
print(f" Timestamp: {consensus.timestamp}")
|
||||
print(f" Root: {consensus.root[:20]}...")
|
||||
print(f" Next validators hash: {consensus.next_validators_hash[:20]}...")
|
||||
|
||||
print()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
521
sdk/python/examples/zk_example.py
Normal file
521
sdk/python/examples/zk_example.py
Normal file
|
|
@ -0,0 +1,521 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
Synor ZK SDK Examples for Python
|
||||
|
||||
Demonstrates Zero-Knowledge proof operations:
|
||||
- Circuit compilation
|
||||
- Proof generation and verification
|
||||
- Groth16, PLONK, and STARK proving systems
|
||||
- Recursive proofs
|
||||
- On-chain verification
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import os
|
||||
import time
|
||||
from synor_zk import (
|
||||
SynorZk,
|
||||
ZkConfig,
|
||||
ProvingSystem,
|
||||
CircuitFormat,
|
||||
)
|
||||
|
||||
|
||||
async def main():
|
||||
"""Main entry point."""
|
||||
# Initialize client
|
||||
config = ZkConfig(
|
||||
api_key=os.environ.get("SYNOR_API_KEY", "your-api-key"),
|
||||
endpoint="https://zk.synor.io/v1",
|
||||
timeout=120000, # ZK ops can be slow
|
||||
retries=3,
|
||||
debug=False,
|
||||
default_proving_system=ProvingSystem.GROTH16,
|
||||
)
|
||||
|
||||
zk = SynorZk(config)
|
||||
|
||||
try:
|
||||
# Check service health
|
||||
healthy = await zk.health_check()
|
||||
print(f"Service healthy: {healthy}\n")
|
||||
|
||||
# Example 1: Circuit compilation
|
||||
await circuit_example(zk)
|
||||
|
||||
# Example 2: Proof generation
|
||||
await proof_example(zk)
|
||||
|
||||
# Example 3: Different proving systems
|
||||
await proving_systems_example(zk)
|
||||
|
||||
# Example 4: Recursive proofs
|
||||
await recursive_proof_example(zk)
|
||||
|
||||
# Example 5: On-chain verification
|
||||
await on_chain_verification_example(zk)
|
||||
|
||||
# Example 6: Trusted setup
|
||||
await setup_example(zk)
|
||||
finally:
|
||||
await zk.close()
|
||||
|
||||
|
||||
async def circuit_example(zk: SynorZk):
|
||||
"""Circuit compilation."""
|
||||
print("=== Circuit Compilation ===")
|
||||
|
||||
# Circom circuit example: prove knowledge of preimage
|
||||
circom_circuit = """
|
||||
pragma circom 2.1.0;
|
||||
|
||||
template HashPreimage() {
|
||||
signal input preimage;
|
||||
signal input hash;
|
||||
|
||||
// Simplified hash computation (in reality, use proper hash)
|
||||
signal preimageSquared;
|
||||
preimageSquared <== preimage * preimage;
|
||||
|
||||
// Constrain that hash matches
|
||||
hash === preimageSquared;
|
||||
}
|
||||
|
||||
component main {public [hash]} = HashPreimage();
|
||||
"""
|
||||
|
||||
# Compile circuit
|
||||
print("Compiling Circom circuit...")
|
||||
compiled = await zk.circuits.compile(
|
||||
code=circom_circuit,
|
||||
format=CircuitFormat.CIRCOM,
|
||||
name="hash_preimage",
|
||||
proving_system=ProvingSystem.GROTH16,
|
||||
)
|
||||
|
||||
print(f"Circuit compiled:")
|
||||
print(f" Circuit ID: {compiled.circuit_id}")
|
||||
print(f" Constraints: {compiled.constraint_count}")
|
||||
print(f" Public inputs: {compiled.public_input_count}")
|
||||
print(f" Private inputs: {compiled.private_input_count}")
|
||||
print(f" Proving key size: {compiled.proving_key_size} bytes")
|
||||
print(f" Verification key size: {compiled.verification_key_size} bytes")
|
||||
|
||||
# List circuits
|
||||
circuits = await zk.circuits.list()
|
||||
print(f"\nYour circuits: {len(circuits)}")
|
||||
for circuit in circuits:
|
||||
print(f" {circuit.name} ({circuit.circuit_id})")
|
||||
|
||||
# Get circuit details
|
||||
details = await zk.circuits.get(compiled.circuit_id)
|
||||
print(f"\nCircuit details:")
|
||||
print(f" Format: {details.format}")
|
||||
print(f" Proving system: {details.proving_system}")
|
||||
print(f" Created: {details.created_at}")
|
||||
|
||||
# Download proving key
|
||||
proving_key = await zk.circuits.get_proving_key(compiled.circuit_id)
|
||||
print(f"\nProving key downloaded: {len(proving_key)} bytes")
|
||||
|
||||
# Download verification key
|
||||
verification_key = await zk.circuits.get_verification_key(compiled.circuit_id)
|
||||
print(f"Verification key downloaded: {len(verification_key)} bytes")
|
||||
|
||||
print()
|
||||
|
||||
|
||||
async def proof_example(zk: SynorZk):
|
||||
"""Proof generation and verification."""
|
||||
print("=== Proof Generation ===")
|
||||
|
||||
# First, compile a simple circuit
|
||||
circuit = """
|
||||
pragma circom 2.1.0;
|
||||
|
||||
template Multiplier() {
|
||||
signal input a;
|
||||
signal input b;
|
||||
signal output c;
|
||||
|
||||
c <== a * b;
|
||||
}
|
||||
|
||||
component main {public [c]} = Multiplier();
|
||||
"""
|
||||
|
||||
compiled = await zk.circuits.compile(
|
||||
code=circuit,
|
||||
format=CircuitFormat.CIRCOM,
|
||||
name="multiplier",
|
||||
proving_system=ProvingSystem.GROTH16,
|
||||
)
|
||||
|
||||
# Generate proof
|
||||
print("Generating proof...")
|
||||
start_time = time.time()
|
||||
|
||||
proof = await zk.proofs.generate(
|
||||
circuit_id=compiled.circuit_id,
|
||||
inputs={"a": "3", "b": "7"},
|
||||
)
|
||||
|
||||
proof_time = (time.time() - start_time) * 1000
|
||||
print(f"Proof generated in {proof_time:.0f}ms")
|
||||
print(f" Proof ID: {proof.proof_id}")
|
||||
print(f" Proof size: {len(proof.proof)} bytes")
|
||||
print(f" Public signals: {proof.public_signals}")
|
||||
|
||||
# Verify proof
|
||||
print("\nVerifying proof...")
|
||||
verify_start = time.time()
|
||||
|
||||
is_valid = await zk.proofs.verify(
|
||||
circuit_id=compiled.circuit_id,
|
||||
proof=proof.proof,
|
||||
public_signals=proof.public_signals,
|
||||
)
|
||||
|
||||
verify_time = (time.time() - verify_start) * 1000
|
||||
print(f"Verification completed in {verify_time:.0f}ms")
|
||||
print(f" Valid: {is_valid}")
|
||||
|
||||
# Verify with wrong public signals (should fail)
|
||||
print("\nVerifying with wrong signals...")
|
||||
invalid_result = await zk.proofs.verify(
|
||||
circuit_id=compiled.circuit_id,
|
||||
proof=proof.proof,
|
||||
public_signals=["42"], # Wrong answer
|
||||
)
|
||||
print(f" Valid: {invalid_result} (expected False)")
|
||||
|
||||
# Get proof status
|
||||
status = await zk.proofs.get_status(proof.proof_id)
|
||||
print(f"\nProof status:")
|
||||
print(f" State: {status.state}")
|
||||
print(f" Verified: {status.verified}")
|
||||
print(f" Created: {status.created_at}")
|
||||
|
||||
# List proofs
|
||||
proofs = await zk.proofs.list(circuit_id=compiled.circuit_id)
|
||||
print(f"\nProofs for circuit: {len(proofs)}")
|
||||
|
||||
print()
|
||||
|
||||
|
||||
async def proving_systems_example(zk: SynorZk):
|
||||
"""Different proving systems comparison."""
|
||||
print("=== Proving Systems Comparison ===")
|
||||
|
||||
# Simple circuit for comparison
|
||||
circuit = """
|
||||
pragma circom 2.1.0;
|
||||
|
||||
template Comparison() {
|
||||
signal input x;
|
||||
signal input y;
|
||||
signal output sum;
|
||||
|
||||
sum <== x + y;
|
||||
}
|
||||
|
||||
component main {public [sum]} = Comparison();
|
||||
"""
|
||||
|
||||
systems = [
|
||||
ProvingSystem.GROTH16,
|
||||
ProvingSystem.PLONK,
|
||||
ProvingSystem.STARK,
|
||||
]
|
||||
|
||||
print("Comparing proving systems:\n")
|
||||
|
||||
for system in systems:
|
||||
print(f"{system.value}:")
|
||||
|
||||
# Compile for this system
|
||||
compiled = await zk.circuits.compile(
|
||||
code=circuit,
|
||||
format=CircuitFormat.CIRCOM,
|
||||
name=f"comparison_{system.value.lower()}",
|
||||
proving_system=system,
|
||||
)
|
||||
|
||||
# Generate proof
|
||||
proof_start = time.time()
|
||||
proof = await zk.proofs.generate(
|
||||
circuit_id=compiled.circuit_id,
|
||||
inputs={"x": "10", "y": "20"},
|
||||
)
|
||||
proof_time = (time.time() - proof_start) * 1000
|
||||
|
||||
# Verify proof
|
||||
verify_start = time.time()
|
||||
await zk.proofs.verify(
|
||||
circuit_id=compiled.circuit_id,
|
||||
proof=proof.proof,
|
||||
public_signals=proof.public_signals,
|
||||
)
|
||||
verify_time = (time.time() - verify_start) * 1000
|
||||
|
||||
print(f" Setup: {compiled.setup_time}ms")
|
||||
print(f" Proof time: {proof_time:.0f}ms")
|
||||
print(f" Verify time: {verify_time:.0f}ms")
|
||||
print(f" Proof size: {len(proof.proof)} bytes")
|
||||
print(f" Verification key: {compiled.verification_key_size} bytes")
|
||||
print()
|
||||
|
||||
print("Summary:")
|
||||
print(" Groth16: Smallest proofs, fast verification, trusted setup required")
|
||||
print(" PLONK: Universal setup, flexible, moderate proof size")
|
||||
print(" STARK: No trusted setup, largest proofs, quantum resistant")
|
||||
|
||||
print()
|
||||
|
||||
|
||||
async def recursive_proof_example(zk: SynorZk):
|
||||
"""Recursive proof aggregation."""
|
||||
print("=== Recursive Proofs ===")
|
||||
|
||||
# Inner circuit
|
||||
inner_circuit = """
|
||||
pragma circom 2.1.0;
|
||||
|
||||
template Inner() {
|
||||
signal input x;
|
||||
signal output y;
|
||||
y <== x * x;
|
||||
}
|
||||
|
||||
component main {public [y]} = Inner();
|
||||
"""
|
||||
|
||||
# Compile inner circuit
|
||||
inner = await zk.circuits.compile(
|
||||
code=inner_circuit,
|
||||
format=CircuitFormat.CIRCOM,
|
||||
name="inner_circuit",
|
||||
proving_system=ProvingSystem.GROTH16,
|
||||
)
|
||||
|
||||
# Generate multiple proofs to aggregate
|
||||
print("Generating proofs to aggregate...")
|
||||
proofs_to_aggregate = []
|
||||
for i in range(1, 5):
|
||||
proof = await zk.proofs.generate(
|
||||
circuit_id=inner.circuit_id,
|
||||
inputs={"x": str(i)},
|
||||
)
|
||||
proofs_to_aggregate.append({
|
||||
"proof": proof.proof,
|
||||
"public_signals": proof.public_signals,
|
||||
})
|
||||
print(f" Proof {i}: y = {proof.public_signals[0]}")
|
||||
|
||||
# Aggregate proofs recursively
|
||||
print("\nAggregating proofs...")
|
||||
aggregated = await zk.proofs.aggregate(
|
||||
circuit_id=inner.circuit_id,
|
||||
proofs=proofs_to_aggregate,
|
||||
aggregation_type="recursive",
|
||||
)
|
||||
|
||||
original_size = sum(len(p["proof"]) for p in proofs_to_aggregate)
|
||||
print(f"Aggregated proof:")
|
||||
print(f" Proof ID: {aggregated.proof_id}")
|
||||
print(f" Aggregated count: {aggregated.aggregated_count}")
|
||||
print(f" Proof size: {len(aggregated.proof)} bytes")
|
||||
print(f" Size reduction: {(1 - len(aggregated.proof) / original_size) * 100:.1f}%")
|
||||
|
||||
# Verify aggregated proof
|
||||
is_valid = await zk.proofs.verify_aggregated(
|
||||
circuit_id=inner.circuit_id,
|
||||
proof=aggregated.proof,
|
||||
public_signals_list=[p["public_signals"] for p in proofs_to_aggregate],
|
||||
)
|
||||
print(f"\nAggregated proof valid: {is_valid}")
|
||||
|
||||
# Batch verification (verify multiple proofs in one operation)
|
||||
print("\nBatch verification...")
|
||||
batch_result = await zk.proofs.batch_verify(
|
||||
circuit_id=inner.circuit_id,
|
||||
proofs=proofs_to_aggregate,
|
||||
)
|
||||
print(f" All valid: {batch_result.all_valid}")
|
||||
print(f" Results: {', '.join(str(r) for r in batch_result.results)}")
|
||||
|
||||
print()
|
||||
|
||||
|
||||
async def on_chain_verification_example(zk: SynorZk):
|
||||
"""On-chain verification."""
|
||||
print("=== On-Chain Verification ===")
|
||||
|
||||
# Compile circuit
|
||||
circuit = """
|
||||
pragma circom 2.1.0;
|
||||
|
||||
template VoteCommitment() {
|
||||
signal input vote; // Private: actual vote
|
||||
signal input nullifier; // Private: unique identifier
|
||||
signal input commitment; // Public: commitment to verify
|
||||
|
||||
// Simplified commitment (in practice, use Poseidon hash)
|
||||
signal computed;
|
||||
computed <== vote * nullifier;
|
||||
commitment === computed;
|
||||
}
|
||||
|
||||
component main {public [commitment]} = VoteCommitment();
|
||||
"""
|
||||
|
||||
compiled = await zk.circuits.compile(
|
||||
code=circuit,
|
||||
format=CircuitFormat.CIRCOM,
|
||||
name="vote_commitment",
|
||||
proving_system=ProvingSystem.GROTH16,
|
||||
)
|
||||
|
||||
# Generate Solidity verifier
|
||||
print("Generating Solidity verifier...")
|
||||
solidity_verifier = await zk.contracts.generate_verifier(
|
||||
circuit_id=compiled.circuit_id,
|
||||
language="solidity",
|
||||
optimized=True,
|
||||
)
|
||||
print(f"Solidity verifier generated: {len(solidity_verifier.code)} bytes")
|
||||
print(f" Contract name: {solidity_verifier.contract_name}")
|
||||
print(f" Gas estimate: {solidity_verifier.gas_estimate}")
|
||||
|
||||
# Generate proof
|
||||
proof = await zk.proofs.generate(
|
||||
circuit_id=compiled.circuit_id,
|
||||
inputs={
|
||||
"vote": "1", # Vote YES (1) or NO (0)
|
||||
"nullifier": "12345",
|
||||
"commitment": "12345", # 1 * 12345
|
||||
},
|
||||
)
|
||||
|
||||
# Format proof for on-chain verification
|
||||
print("\nFormatting proof for on-chain...")
|
||||
on_chain_proof = await zk.contracts.format_proof(
|
||||
circuit_id=compiled.circuit_id,
|
||||
proof=proof.proof,
|
||||
public_signals=proof.public_signals,
|
||||
format="calldata",
|
||||
)
|
||||
print(f" Calldata: {on_chain_proof.calldata[:100]}...")
|
||||
print(f" Estimated gas: {on_chain_proof.gas_estimate}")
|
||||
|
||||
# Deploy verifier contract (simulation)
|
||||
print("\nDeploying verifier contract...")
|
||||
deployment = await zk.contracts.deploy_verifier(
|
||||
circuit_id=compiled.circuit_id,
|
||||
network="synor-testnet",
|
||||
)
|
||||
print(f" Contract address: {deployment.address}")
|
||||
print(f" TX hash: {deployment.tx_hash}")
|
||||
print(f" Gas used: {deployment.gas_used}")
|
||||
|
||||
# Verify on-chain
|
||||
print("\nVerifying on-chain...")
|
||||
on_chain_result = await zk.contracts.verify_on_chain(
|
||||
contract_address=deployment.address,
|
||||
proof=proof.proof,
|
||||
public_signals=proof.public_signals,
|
||||
network="synor-testnet",
|
||||
)
|
||||
print(f" TX hash: {on_chain_result.tx_hash}")
|
||||
print(f" Verified: {on_chain_result.verified}")
|
||||
print(f" Gas used: {on_chain_result.gas_used}")
|
||||
|
||||
# Generate verifier for other targets
|
||||
print("\nGenerating verifiers for other targets:")
|
||||
targets = ["cairo", "noir", "ink"]
|
||||
for target in targets:
|
||||
verifier = await zk.contracts.generate_verifier(
|
||||
circuit_id=compiled.circuit_id,
|
||||
language=target,
|
||||
)
|
||||
print(f" {target}: {len(verifier.code)} bytes")
|
||||
|
||||
print()
|
||||
|
||||
|
||||
async def setup_example(zk: SynorZk):
|
||||
"""Trusted setup ceremonies."""
|
||||
print("=== Trusted Setup ===")
|
||||
|
||||
# Get available ceremonies
|
||||
ceremonies = await zk.setup.list_ceremonies()
|
||||
print(f"Active ceremonies: {len(ceremonies)}")
|
||||
for ceremony in ceremonies:
|
||||
print(f" {ceremony.name}:")
|
||||
print(f" Status: {ceremony.status}")
|
||||
print(f" Participants: {ceremony.participant_count}")
|
||||
print(f" Current round: {ceremony.current_round}")
|
||||
|
||||
# Create a new circuit setup
|
||||
circuit = """
|
||||
pragma circom 2.1.0;
|
||||
|
||||
template NewCircuit() {
|
||||
signal input a;
|
||||
signal output b;
|
||||
b <== a + 1;
|
||||
}
|
||||
|
||||
component main {public [b]} = NewCircuit();
|
||||
"""
|
||||
|
||||
print("\nInitializing setup for new circuit...")
|
||||
setup = await zk.setup.initialize(
|
||||
circuit=circuit,
|
||||
format=CircuitFormat.CIRCOM,
|
||||
name="new_circuit_setup",
|
||||
proving_system=ProvingSystem.GROTH16,
|
||||
ceremony_type="powers_of_tau", # or 'phase2'
|
||||
)
|
||||
print(f"Setup initialized:")
|
||||
print(f" Ceremony ID: {setup.ceremony_id}")
|
||||
print(f" Powers of Tau required: {setup.powers_required}")
|
||||
print(f" Current phase: {setup.phase}")
|
||||
|
||||
# Contribute to ceremony (in practice, generates random entropy)
|
||||
print("\nContributing to ceremony...")
|
||||
contribution = await zk.setup.contribute(
|
||||
ceremony_id=setup.ceremony_id,
|
||||
entropy=b"random-entropy-from-user".hex(),
|
||||
)
|
||||
print(f"Contribution submitted:")
|
||||
print(f" Participant: {contribution.participant_id}")
|
||||
print(f" Contribution hash: {contribution.hash}")
|
||||
print(f" Verification status: {contribution.verified}")
|
||||
|
||||
# Get ceremony status
|
||||
status = await zk.setup.get_status(setup.ceremony_id)
|
||||
print(f"\nCeremony status:")
|
||||
print(f" Phase: {status.phase}")
|
||||
print(f" Total contributions: {status.total_contributions}")
|
||||
print(f" Verified contributions: {status.verified_contributions}")
|
||||
print(f" Ready for finalization: {status.ready_for_finalization}")
|
||||
|
||||
# Finalize setup (when enough contributions)
|
||||
if status.ready_for_finalization:
|
||||
print("\nFinalizing setup...")
|
||||
finalized = await zk.setup.finalize(setup.ceremony_id)
|
||||
print(f"Setup finalized:")
|
||||
print(f" Proving key hash: {finalized.proving_key_hash}")
|
||||
print(f" Verification key hash: {finalized.verification_key_hash}")
|
||||
print(f" Contribution transcript: {finalized.transcript_cid}")
|
||||
|
||||
# Download ceremony transcript
|
||||
transcript = await zk.setup.get_transcript(setup.ceremony_id)
|
||||
print(f"\nCeremony transcript: {len(transcript)} bytes")
|
||||
|
||||
print()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
435
sdk/rust/examples/compiler_example.rs
Normal file
435
sdk/rust/examples/compiler_example.rs
Normal file
|
|
@ -0,0 +1,435 @@
|
|||
//! Synor Compiler SDK Examples for Rust
|
||||
//!
|
||||
//! Demonstrates smart contract compilation and analysis:
|
||||
//! - WASM contract compilation and optimization
|
||||
//! - ABI extraction and encoding
|
||||
//! - Contract analysis and security scanning
|
||||
//! - Validation and verification
|
||||
|
||||
use std::env;
|
||||
use synor_compiler::{
|
||||
CompilerConfig, CompileOptions, OptimizationLevel, StripOptions, SynorCompiler,
|
||||
};
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
// Initialize client
|
||||
let config = CompilerConfig {
|
||||
api_key: env::var("SYNOR_API_KEY").unwrap_or_else(|_| "your-api-key".to_string()),
|
||||
endpoint: "https://compiler.synor.io/v1".to_string(),
|
||||
timeout: 60000,
|
||||
retries: 3,
|
||||
debug: false,
|
||||
default_optimization_level: OptimizationLevel::Size,
|
||||
max_contract_size: 256 * 1024,
|
||||
use_wasm_opt: true,
|
||||
validate: true,
|
||||
extract_metadata: true,
|
||||
generate_abi: true,
|
||||
};
|
||||
|
||||
let compiler = SynorCompiler::new(config)?;
|
||||
|
||||
// Check service health
|
||||
let healthy = compiler.health_check().await?;
|
||||
println!("Service healthy: {}\n", healthy);
|
||||
|
||||
// Run examples
|
||||
compile_contract_example(&compiler).await?;
|
||||
compilation_modes_example(&compiler).await?;
|
||||
abi_example(&compiler).await?;
|
||||
analysis_example(&compiler).await?;
|
||||
validation_example(&compiler).await?;
|
||||
security_example(&compiler).await?;
|
||||
|
||||
compiler.close().await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Create a minimal valid WASM module for testing.
|
||||
fn create_minimal_wasm() -> Vec<u8> {
|
||||
vec![
|
||||
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,
|
||||
]
|
||||
}
|
||||
|
||||
async fn compile_contract_example(compiler: &SynorCompiler) -> Result<(), Box<dyn std::error::Error>> {
|
||||
println!("=== Contract Compilation ===");
|
||||
|
||||
let wasm = create_minimal_wasm();
|
||||
|
||||
let result = compiler
|
||||
.compile(
|
||||
&wasm,
|
||||
Some(CompileOptions {
|
||||
optimization_level: OptimizationLevel::Size,
|
||||
use_wasm_opt: true,
|
||||
validate: true,
|
||||
extract_metadata: true,
|
||||
generate_abi: true,
|
||||
strip_options: Some(StripOptions {
|
||||
strip_debug: true,
|
||||
strip_producers: true,
|
||||
strip_names: true,
|
||||
strip_custom: true,
|
||||
strip_unused: true,
|
||||
preserve_sections: vec![],
|
||||
}),
|
||||
}),
|
||||
)
|
||||
.await?;
|
||||
|
||||
println!("Compilation result:");
|
||||
println!(" Contract ID: {}", result.contract_id);
|
||||
println!(" Code hash: {}", result.code_hash);
|
||||
println!(" Original size: {} bytes", result.original_size);
|
||||
println!(" Optimized size: {} bytes", result.optimized_size);
|
||||
println!(" Size reduction: {:.1}%", result.size_reduction);
|
||||
println!(" Estimated deploy gas: {}", result.estimated_deploy_gas);
|
||||
|
||||
if let Some(metadata) = &result.metadata {
|
||||
println!("\nMetadata:");
|
||||
println!(" Name: {}", metadata.name);
|
||||
println!(" Version: {}", metadata.version);
|
||||
println!(" SDK Version: {}", metadata.sdk_version);
|
||||
}
|
||||
|
||||
if let Some(abi) = &result.abi {
|
||||
println!("\nABI:");
|
||||
println!(" Functions: {}", abi.functions.as_ref().map_or(0, |f| f.len()));
|
||||
println!(" Events: {}", abi.events.as_ref().map_or(0, |e| e.len()));
|
||||
println!(" Errors: {}", abi.errors.as_ref().map_or(0, |e| e.len()));
|
||||
}
|
||||
|
||||
println!();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn compilation_modes_example(compiler: &SynorCompiler) -> Result<(), Box<dyn std::error::Error>> {
|
||||
println!("=== Compilation Modes ===");
|
||||
|
||||
let wasm = create_minimal_wasm();
|
||||
|
||||
// Development mode: fast compilation, debugging support
|
||||
println!("Development mode:");
|
||||
let dev_result = compiler.contracts.compile_dev(&wasm).await?;
|
||||
println!(" Size: {} bytes", dev_result.optimized_size);
|
||||
println!(" Optimization: none");
|
||||
|
||||
// Production mode: maximum optimization
|
||||
println!("\nProduction mode:");
|
||||
let prod_result = compiler.contracts.compile_production(&wasm).await?;
|
||||
println!(" Size: {} bytes", prod_result.optimized_size);
|
||||
println!(" Optimization: aggressive");
|
||||
println!(
|
||||
" Size savings: {} bytes",
|
||||
dev_result.optimized_size - prod_result.optimized_size
|
||||
);
|
||||
|
||||
// Custom optimization levels
|
||||
println!("\nOptimization levels:");
|
||||
let levels = [
|
||||
OptimizationLevel::None,
|
||||
OptimizationLevel::Basic,
|
||||
OptimizationLevel::Size,
|
||||
OptimizationLevel::Aggressive,
|
||||
];
|
||||
|
||||
for level in levels {
|
||||
let result = compiler
|
||||
.compile(
|
||||
&wasm,
|
||||
Some(CompileOptions {
|
||||
optimization_level: level,
|
||||
..Default::default()
|
||||
}),
|
||||
)
|
||||
.await?;
|
||||
println!(" {:?}: {} bytes", level, result.optimized_size);
|
||||
}
|
||||
|
||||
println!();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn abi_example(compiler: &SynorCompiler) -> Result<(), Box<dyn std::error::Error>> {
|
||||
println!("=== ABI Operations ===");
|
||||
|
||||
let wasm = create_minimal_wasm();
|
||||
|
||||
// Extract ABI from WASM
|
||||
let abi = compiler.abi.extract(&wasm).await?;
|
||||
println!("Contract: {}", abi.name);
|
||||
println!("Version: {}", abi.version);
|
||||
|
||||
// List functions
|
||||
if let Some(functions) = &abi.functions {
|
||||
if !functions.is_empty() {
|
||||
println!("\nFunctions:");
|
||||
for func in functions {
|
||||
let inputs = func
|
||||
.inputs
|
||||
.as_ref()
|
||||
.map(|inputs| {
|
||||
inputs
|
||||
.iter()
|
||||
.map(|i| format!("{}: {}", i.name, i.type_info.type_name))
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ")
|
||||
})
|
||||
.unwrap_or_default();
|
||||
|
||||
let outputs = func
|
||||
.outputs
|
||||
.as_ref()
|
||||
.map(|outputs| {
|
||||
outputs
|
||||
.iter()
|
||||
.map(|o| o.type_info.type_name.clone())
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ")
|
||||
})
|
||||
.unwrap_or_else(|| "void".to_string());
|
||||
|
||||
let mut modifiers = vec![];
|
||||
if func.view {
|
||||
modifiers.push("view");
|
||||
}
|
||||
if func.payable {
|
||||
modifiers.push("payable");
|
||||
}
|
||||
|
||||
println!(
|
||||
" {}({}) -> {} {}",
|
||||
func.name,
|
||||
inputs,
|
||||
outputs,
|
||||
modifiers.join(" ")
|
||||
);
|
||||
println!(" Selector: {}", func.selector);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// List events
|
||||
if let Some(events) = &abi.events {
|
||||
if !events.is_empty() {
|
||||
println!("\nEvents:");
|
||||
for event in events {
|
||||
let params = event
|
||||
.params
|
||||
.as_ref()
|
||||
.map(|params| {
|
||||
params
|
||||
.iter()
|
||||
.map(|p| {
|
||||
let indexed = if p.indexed { "indexed " } else { "" };
|
||||
format!("{}{}: {}", indexed, p.name, p.type_info.type_name)
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ")
|
||||
})
|
||||
.unwrap_or_default();
|
||||
|
||||
println!(" {}({})", event.name, params);
|
||||
println!(" Topic: {}", event.topic);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Encode a function call
|
||||
if let Some(functions) = &abi.functions {
|
||||
if let Some(func) = functions.first() {
|
||||
let encoded = compiler
|
||||
.abi
|
||||
.encode_call(func, &["arg1".to_string(), "arg2".to_string()])
|
||||
.await?;
|
||||
println!("\nEncoded call to {}: {}", func.name, encoded);
|
||||
|
||||
// Decode a result
|
||||
let decoded = compiler.abi.decode_result(func, &encoded).await?;
|
||||
println!("Decoded result: {:?}", decoded);
|
||||
}
|
||||
}
|
||||
|
||||
println!();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn analysis_example(compiler: &SynorCompiler) -> Result<(), Box<dyn std::error::Error>> {
|
||||
println!("=== Contract Analysis ===");
|
||||
|
||||
let wasm = create_minimal_wasm();
|
||||
|
||||
// Full analysis
|
||||
let analysis = compiler.analysis.analyze(&wasm).await?;
|
||||
|
||||
// Size breakdown
|
||||
if let Some(breakdown) = &analysis.size_breakdown {
|
||||
println!("Size breakdown:");
|
||||
println!(" Code: {} bytes", breakdown.code);
|
||||
println!(" Data: {} bytes", breakdown.data);
|
||||
println!(" Functions: {} bytes", breakdown.functions);
|
||||
println!(" Memory: {} bytes", breakdown.memory);
|
||||
println!(" Exports: {} bytes", breakdown.exports);
|
||||
println!(" Imports: {} bytes", breakdown.imports);
|
||||
println!(" Total: {} bytes", breakdown.total);
|
||||
}
|
||||
|
||||
// Function analysis
|
||||
if let Some(functions) = &analysis.functions {
|
||||
if !functions.is_empty() {
|
||||
println!("\nFunction analysis:");
|
||||
for func in functions.iter().take(5) {
|
||||
println!(" {}:", func.name);
|
||||
println!(" Size: {} bytes", func.size);
|
||||
println!(" Instructions: {}", func.instruction_count);
|
||||
println!(" Locals: {}", func.local_count);
|
||||
println!(" Exported: {}", func.exported);
|
||||
println!(" Estimated gas: {}", func.estimated_gas);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Import analysis
|
||||
if let Some(imports) = &analysis.imports {
|
||||
if !imports.is_empty() {
|
||||
println!("\nImports:");
|
||||
for imp in imports {
|
||||
println!(" {}.{} ({})", imp.module, imp.name, imp.kind);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Gas analysis
|
||||
if let Some(gas) = &analysis.gas_analysis {
|
||||
println!("\nGas analysis:");
|
||||
println!(" Deployment: {}", gas.deployment_gas);
|
||||
println!(" Memory init: {}", gas.memory_init_gas);
|
||||
println!(" Data section: {}", gas.data_section_gas);
|
||||
}
|
||||
|
||||
// Extract metadata
|
||||
let metadata = compiler.analysis.extract_metadata(&wasm).await?;
|
||||
println!("\nContract metadata:");
|
||||
println!(" Name: {}", metadata.name);
|
||||
println!(" Version: {}", metadata.version);
|
||||
println!(" Build timestamp: {}", metadata.build_timestamp);
|
||||
|
||||
// Estimate deployment gas
|
||||
let gas = compiler.analysis.estimate_deploy_gas(&wasm).await?;
|
||||
println!("\nEstimated deployment gas: {}", gas);
|
||||
|
||||
println!();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn validation_example(compiler: &SynorCompiler) -> Result<(), Box<dyn std::error::Error>> {
|
||||
println!("=== Contract Validation ===");
|
||||
|
||||
let wasm = create_minimal_wasm();
|
||||
|
||||
// Full validation
|
||||
let result = compiler.validation.validate(&wasm).await?;
|
||||
println!("Valid: {}", result.valid);
|
||||
println!("Exports: {}", result.export_count);
|
||||
println!("Imports: {}", result.import_count);
|
||||
println!("Functions: {}", result.function_count);
|
||||
println!("Memory pages: {}", result.memory_pages);
|
||||
|
||||
if let Some(errors) = &result.errors {
|
||||
if !errors.is_empty() {
|
||||
println!("\nValidation errors:");
|
||||
for error in errors {
|
||||
println!(" [{}] {}", error.code, error.message);
|
||||
if let Some(location) = &error.location {
|
||||
println!(" at {}", location);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(warnings) = &result.warnings {
|
||||
if !warnings.is_empty() {
|
||||
println!("\nWarnings:");
|
||||
for warning in warnings {
|
||||
println!(" {}", warning);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Quick validation
|
||||
let is_valid = compiler.validation.is_valid(&wasm).await?;
|
||||
println!("\nQuick validation: {}", is_valid);
|
||||
|
||||
// Get validation errors only
|
||||
let errors = compiler.validation.get_errors(&wasm).await?;
|
||||
println!("Error count: {}", errors.len());
|
||||
|
||||
// Validate required exports
|
||||
let has_required = compiler
|
||||
.validation
|
||||
.validate_exports(&wasm, &["init", "execute", "query"])
|
||||
.await?;
|
||||
println!("Has required exports: {}", has_required);
|
||||
|
||||
// Validate memory constraints
|
||||
let memory_valid = compiler.validation.validate_memory(&wasm, 16).await?;
|
||||
println!("Memory within 16 pages: {}", memory_valid);
|
||||
|
||||
println!();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn security_example(compiler: &SynorCompiler) -> Result<(), Box<dyn std::error::Error>> {
|
||||
println!("=== Security Scanning ===");
|
||||
|
||||
let wasm = create_minimal_wasm();
|
||||
|
||||
let security = compiler.analysis.security_scan(&wasm).await?;
|
||||
|
||||
println!("Security score: {}/100", security.score);
|
||||
|
||||
if let Some(issues) = &security.issues {
|
||||
if !issues.is_empty() {
|
||||
println!("\nSecurity issues:");
|
||||
for issue in issues {
|
||||
let icon = match issue.severity.as_str() {
|
||||
"critical" => "[CRIT]",
|
||||
"high" => "[HIGH]",
|
||||
"medium" => "[MED]",
|
||||
"low" => "[LOW]",
|
||||
_ => "[???]",
|
||||
};
|
||||
println!("{} [{}] {}", icon, issue.severity.to_uppercase(), issue.issue_type);
|
||||
println!(" {}", issue.description);
|
||||
if let Some(location) = &issue.location {
|
||||
println!(" at {}", location);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
println!("No security issues found!");
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(recommendations) = &security.recommendations {
|
||||
if !recommendations.is_empty() {
|
||||
println!("\nRecommendations:");
|
||||
for rec in recommendations {
|
||||
println!(" * {}", rec);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
println!();
|
||||
Ok(())
|
||||
}
|
||||
279
sdk/rust/examples/crypto_example.rs
Normal file
279
sdk/rust/examples/crypto_example.rs
Normal file
|
|
@ -0,0 +1,279 @@
|
|||
//! Synor Crypto SDK Examples for Rust
|
||||
//!
|
||||
//! Demonstrates quantum-resistant cryptographic operations:
|
||||
//! - Hybrid Ed25519 + Dilithium3 signatures
|
||||
//! - BIP-39 mnemonic generation and validation
|
||||
//! - Post-quantum algorithms (Falcon, SPHINCS+)
|
||||
//! - Key derivation functions
|
||||
|
||||
use std::env;
|
||||
use synor_crypto::{
|
||||
CryptoConfig, DerivationConfig, DerivationPath, FalconVariant, Network,
|
||||
PasswordDerivationConfig, SphincsVariant, SynorCrypto,
|
||||
};
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
// Initialize client
|
||||
let config = CryptoConfig {
|
||||
api_key: env::var("SYNOR_API_KEY").unwrap_or_else(|_| "your-api-key".to_string()),
|
||||
endpoint: "https://crypto.synor.io/v1".to_string(),
|
||||
timeout: 30000,
|
||||
retries: 3,
|
||||
debug: false,
|
||||
default_network: Network::Mainnet,
|
||||
};
|
||||
|
||||
let crypto = SynorCrypto::new(config)?;
|
||||
|
||||
// Check service health
|
||||
let healthy = crypto.health_check().await?;
|
||||
println!("Service healthy: {}\n", healthy);
|
||||
|
||||
// Run examples
|
||||
mnemonic_example(&crypto).await?;
|
||||
keypair_example(&crypto).await?;
|
||||
signing_example(&crypto).await?;
|
||||
falcon_example(&crypto).await?;
|
||||
sphincs_example(&crypto).await?;
|
||||
kdf_example(&crypto).await?;
|
||||
hash_example(&crypto).await?;
|
||||
|
||||
crypto.close().await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn mnemonic_example(crypto: &SynorCrypto) -> Result<(), Box<dyn std::error::Error>> {
|
||||
println!("=== Mnemonic Operations ===");
|
||||
|
||||
// Generate a 24-word mnemonic (256-bit entropy)
|
||||
let mnemonic = crypto.mnemonic.generate(24).await?;
|
||||
println!("Generated mnemonic: {}", mnemonic.phrase);
|
||||
println!("Word count: {}", mnemonic.word_count);
|
||||
|
||||
// Validate a mnemonic
|
||||
let validation = crypto.mnemonic.validate(&mnemonic.phrase).await?;
|
||||
println!("Valid: {}", validation.valid);
|
||||
if !validation.valid {
|
||||
println!("Error: {}", validation.error.unwrap_or_default());
|
||||
}
|
||||
|
||||
// Convert mnemonic to seed
|
||||
let seed = crypto
|
||||
.mnemonic
|
||||
.to_seed(&mnemonic.phrase, Some("optional-passphrase"))
|
||||
.await?;
|
||||
println!("Seed (hex): {}...", &hex::encode(&seed)[..32]);
|
||||
|
||||
// Word suggestions for autocomplete
|
||||
let suggestions = crypto.mnemonic.suggest_words("aban", 5).await?;
|
||||
println!("Suggestions for 'aban': {}", suggestions.join(", "));
|
||||
|
||||
println!();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn keypair_example(crypto: &SynorCrypto) -> Result<(), Box<dyn std::error::Error>> {
|
||||
println!("=== Keypair Operations ===");
|
||||
|
||||
// Generate a random keypair
|
||||
let keypair = crypto.keypairs.generate().await?;
|
||||
println!("Generated hybrid keypair:");
|
||||
println!(
|
||||
" Ed25519 public key size: {} bytes",
|
||||
keypair.public_key.ed25519_bytes.len()
|
||||
);
|
||||
println!(
|
||||
" Dilithium public key size: {} bytes",
|
||||
keypair.public_key.dilithium_bytes.len()
|
||||
);
|
||||
println!(" Total public key size: {} bytes", keypair.public_key.size);
|
||||
|
||||
// Get addresses for different networks
|
||||
println!("\nAddresses:");
|
||||
println!(" Mainnet: {}", keypair.get_address(Network::Mainnet));
|
||||
println!(" Testnet: {}", keypair.get_address(Network::Testnet));
|
||||
println!(" Devnet: {}", keypair.get_address(Network::Devnet));
|
||||
|
||||
// Create keypair from mnemonic (deterministic)
|
||||
let mnemonic = crypto.mnemonic.generate(24).await?;
|
||||
let keypair2 = crypto
|
||||
.keypairs
|
||||
.from_mnemonic(&mnemonic.phrase, "")
|
||||
.await?;
|
||||
let addr = keypair2.get_address(Network::Mainnet);
|
||||
println!("\nKeypair from mnemonic: {}...", &addr[..20]);
|
||||
|
||||
// Derive child keypair using BIP-44 path
|
||||
let path = DerivationPath::external(0, 0); // m/44'/21337'/0'/0/0
|
||||
println!("Derivation path: {}", path);
|
||||
|
||||
println!();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn signing_example(crypto: &SynorCrypto) -> Result<(), Box<dyn std::error::Error>> {
|
||||
println!("=== Hybrid Signing ===");
|
||||
|
||||
// Generate keypair
|
||||
let keypair = crypto.keypairs.generate().await?;
|
||||
|
||||
// Sign a message
|
||||
let message = b"Hello, quantum-resistant world!";
|
||||
let signature = crypto.signing.sign(&keypair, message).await?;
|
||||
|
||||
println!("Signature created:");
|
||||
println!(
|
||||
" Ed25519 component: {} bytes",
|
||||
signature.ed25519_bytes.len()
|
||||
);
|
||||
println!(
|
||||
" Dilithium component: {} bytes",
|
||||
signature.dilithium_bytes.len()
|
||||
);
|
||||
println!(" Total signature size: {} bytes", signature.size);
|
||||
|
||||
// Verify the signature
|
||||
let valid = crypto
|
||||
.signing
|
||||
.verify(&keypair.public_key, message, &signature)
|
||||
.await?;
|
||||
println!("\nVerification result: {}", valid);
|
||||
|
||||
// Verify with tampered message fails
|
||||
let tampered_message = b"Hello, tampered message!";
|
||||
let invalid_result = crypto
|
||||
.signing
|
||||
.verify(&keypair.public_key, tampered_message, &signature)
|
||||
.await?;
|
||||
println!("Tampered message verification: {}", invalid_result);
|
||||
|
||||
println!();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn falcon_example(crypto: &SynorCrypto) -> Result<(), Box<dyn std::error::Error>> {
|
||||
println!("=== Falcon Post-Quantum Signatures ===");
|
||||
|
||||
// Generate Falcon-512 keypair (128-bit security)
|
||||
let falcon512 = crypto.falcon.generate(FalconVariant::Falcon512).await?;
|
||||
println!("Falcon-512 keypair:");
|
||||
println!(" Public key: {} bytes", falcon512.public_key.key_bytes.len());
|
||||
println!(" Security level: 128-bit");
|
||||
|
||||
// Generate Falcon-1024 keypair (256-bit security)
|
||||
let falcon1024 = crypto.falcon.generate(FalconVariant::Falcon1024).await?;
|
||||
println!("\nFalcon-1024 keypair:");
|
||||
println!(
|
||||
" Public key: {} bytes",
|
||||
falcon1024.public_key.key_bytes.len()
|
||||
);
|
||||
println!(" Security level: 256-bit");
|
||||
|
||||
// Sign with Falcon-512
|
||||
let message = b"Post-quantum secure message";
|
||||
let signature = crypto.falcon.sign(&falcon512, message).await?;
|
||||
println!(
|
||||
"\nFalcon-512 signature: {} bytes",
|
||||
signature.signature_bytes.len()
|
||||
);
|
||||
|
||||
// Verify
|
||||
let valid = crypto
|
||||
.falcon
|
||||
.verify(&falcon512.public_key.key_bytes, message, &signature)
|
||||
.await?;
|
||||
println!("Verification: {}", valid);
|
||||
|
||||
println!();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn sphincs_example(crypto: &SynorCrypto) -> Result<(), Box<dyn std::error::Error>> {
|
||||
println!("=== SPHINCS+ Hash-Based Signatures ===");
|
||||
|
||||
// SPHINCS+ variants with different security levels
|
||||
let variants = [
|
||||
(SphincsVariant::Shake128s, 128, 7856),
|
||||
(SphincsVariant::Shake192s, 192, 16224),
|
||||
(SphincsVariant::Shake256s, 256, 29792),
|
||||
];
|
||||
|
||||
// Generate and demonstrate each variant
|
||||
for (variant, security, sig_size) in variants {
|
||||
let keypair = crypto.sphincs.generate(variant).await?;
|
||||
println!("SPHINCS+ {:?}:", variant);
|
||||
println!(" Security level: {}-bit", security);
|
||||
println!(" Expected signature size: {} bytes", sig_size);
|
||||
|
||||
// Sign a message
|
||||
let message = b"Hash-based quantum security";
|
||||
let signature = crypto.sphincs.sign(&keypair, message).await?;
|
||||
println!(
|
||||
" Actual signature size: {} bytes",
|
||||
signature.signature_bytes.len()
|
||||
);
|
||||
|
||||
// Verify
|
||||
let valid = crypto
|
||||
.sphincs
|
||||
.verify(&keypair.public_key.key_bytes, message, &signature)
|
||||
.await?;
|
||||
println!(" Verification: {}\n", valid);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn kdf_example(crypto: &SynorCrypto) -> Result<(), Box<dyn std::error::Error>> {
|
||||
println!("=== Key Derivation Functions ===");
|
||||
|
||||
// HKDF (HMAC-based Key Derivation Function)
|
||||
let seed = b"master-secret-key-material-here";
|
||||
let hkdf_config = DerivationConfig {
|
||||
salt: b"application-salt".to_vec(),
|
||||
info: b"encryption-key".to_vec(),
|
||||
output_length: 32,
|
||||
};
|
||||
|
||||
let derived_key = crypto.kdf.derive_key(seed, &hkdf_config).await?;
|
||||
println!("HKDF derived key: {}", hex::encode(&derived_key));
|
||||
|
||||
// PBKDF2 (Password-Based Key Derivation Function)
|
||||
let password = b"user-password";
|
||||
let pbkdf2_config = PasswordDerivationConfig {
|
||||
salt: b"random-salt-value".to_vec(),
|
||||
iterations: 100000,
|
||||
output_length: 32,
|
||||
};
|
||||
|
||||
let password_key = crypto
|
||||
.kdf
|
||||
.derive_from_password(password, &pbkdf2_config)
|
||||
.await?;
|
||||
println!("PBKDF2 derived key: {}", hex::encode(&password_key));
|
||||
|
||||
println!();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn hash_example(crypto: &SynorCrypto) -> Result<(), Box<dyn std::error::Error>> {
|
||||
println!("=== Hash Functions ===");
|
||||
|
||||
let data = b"Data to hash";
|
||||
|
||||
// SHA3-256 (FIPS 202)
|
||||
let sha3 = crypto.hash.sha3_256(data).await?;
|
||||
println!("SHA3-256: {}", sha3.hex);
|
||||
|
||||
// BLAKE3 (fast, parallel)
|
||||
let blake3 = crypto.hash.blake3(data).await?;
|
||||
println!("BLAKE3: {}", blake3.hex);
|
||||
|
||||
// Keccak-256 (Ethereum compatible)
|
||||
let keccak = crypto.hash.keccak256(data).await?;
|
||||
println!("Keccak: {}", keccak.hex);
|
||||
|
||||
println!();
|
||||
Ok(())
|
||||
}
|
||||
387
sdk/rust/examples/dex_example.rs
Normal file
387
sdk/rust/examples/dex_example.rs
Normal file
|
|
@ -0,0 +1,387 @@
|
|||
//! Synor DEX SDK Examples for Rust
|
||||
//!
|
||||
//! Demonstrates decentralized exchange operations:
|
||||
//! - Spot trading (limit/market orders)
|
||||
//! - Perpetual futures trading
|
||||
//! - Liquidity provision (AMM pools)
|
||||
//! - Order book management
|
||||
//! - Portfolio tracking
|
||||
|
||||
use std::env;
|
||||
use synor_dex::{
|
||||
AddLiquidityRequest, DexConfig, OrderRequest, OrderSide, OrderType, PerpsOrderRequest,
|
||||
RemoveLiquidityRequest, SynorDex, TimeInForce,
|
||||
};
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
// Initialize client
|
||||
let config = DexConfig {
|
||||
api_key: env::var("SYNOR_API_KEY").unwrap_or_else(|_| "your-api-key".to_string()),
|
||||
endpoint: "https://dex.synor.io/v1".to_string(),
|
||||
timeout: 30000,
|
||||
retries: 3,
|
||||
debug: false,
|
||||
default_market: "SYN-USDC".to_string(),
|
||||
};
|
||||
|
||||
let dex = SynorDex::new(config)?;
|
||||
|
||||
// Check service health
|
||||
let healthy = dex.health_check().await?;
|
||||
println!("Service healthy: {}\n", healthy);
|
||||
|
||||
// Run examples
|
||||
markets_example(&dex).await?;
|
||||
spot_trading_example(&dex).await?;
|
||||
perps_trading_example(&dex).await?;
|
||||
liquidity_example(&dex).await?;
|
||||
orderbook_example(&dex).await?;
|
||||
portfolio_example(&dex).await?;
|
||||
|
||||
dex.close().await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn markets_example(dex: &SynorDex) -> Result<(), Box<dyn std::error::Error>> {
|
||||
println!("=== Markets ===");
|
||||
|
||||
// Get all markets
|
||||
let markets = dex.markets.list().await?;
|
||||
println!("Available markets: {}", markets.len());
|
||||
|
||||
for market in markets.iter().take(5) {
|
||||
println!("\n {}:", market.symbol);
|
||||
println!(" Base: {}, Quote: {}", market.base_asset, market.quote_asset);
|
||||
println!(" Price: {}", market.last_price);
|
||||
println!(" 24h Volume: {}", market.volume_24h);
|
||||
println!(" 24h Change: {}%", market.change_24h);
|
||||
println!(" Status: {}", market.status);
|
||||
}
|
||||
|
||||
// Get specific market
|
||||
let market = dex.markets.get("SYN-USDC").await?;
|
||||
println!("\nSYN-USDC details:");
|
||||
println!(" Min order size: {}", market.min_order_size);
|
||||
println!(" Tick size: {}", market.tick_size);
|
||||
println!(" Maker fee: {}%", market.maker_fee);
|
||||
println!(" Taker fee: {}%", market.taker_fee);
|
||||
|
||||
// Get market statistics
|
||||
let stats = dex.markets.get_stats("SYN-USDC").await?;
|
||||
println!("\nMarket statistics:");
|
||||
println!(" High 24h: {}", stats.high_24h);
|
||||
println!(" Low 24h: {}", stats.low_24h);
|
||||
println!(" Open interest: {}", stats.open_interest);
|
||||
println!(" Funding rate: {}%", stats.funding_rate);
|
||||
|
||||
println!();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn spot_trading_example(dex: &SynorDex) -> Result<(), Box<dyn std::error::Error>> {
|
||||
println!("=== Spot Trading ===");
|
||||
|
||||
// Place a limit order
|
||||
println!("Placing limit buy order...");
|
||||
let limit_order = dex
|
||||
.spot
|
||||
.place_order(OrderRequest {
|
||||
market: "SYN-USDC".to_string(),
|
||||
side: OrderSide::Buy,
|
||||
order_type: OrderType::Limit,
|
||||
price: Some("1.50".to_string()),
|
||||
quantity: "100".to_string(),
|
||||
time_in_force: Some(TimeInForce::GTC),
|
||||
})
|
||||
.await?;
|
||||
|
||||
println!("Limit order placed:");
|
||||
println!(" Order ID: {}", limit_order.order_id);
|
||||
println!(" Status: {}", limit_order.status);
|
||||
println!(" Price: {}", limit_order.price.unwrap_or_default());
|
||||
println!(" Quantity: {}", limit_order.quantity);
|
||||
|
||||
// Place a market order
|
||||
println!("\nPlacing market sell order...");
|
||||
let market_order = dex
|
||||
.spot
|
||||
.place_order(OrderRequest {
|
||||
market: "SYN-USDC".to_string(),
|
||||
side: OrderSide::Sell,
|
||||
order_type: OrderType::Market,
|
||||
price: None,
|
||||
quantity: "50".to_string(),
|
||||
time_in_force: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
println!("Market order executed:");
|
||||
println!(" Order ID: {}", market_order.order_id);
|
||||
println!(" Status: {}", market_order.status);
|
||||
println!(" Filled: {}", market_order.filled_quantity);
|
||||
println!(" Avg price: {}", market_order.average_price.unwrap_or_default());
|
||||
|
||||
// Get order status
|
||||
let status = dex.spot.get_order(&limit_order.order_id).await?;
|
||||
println!("\nOrder status:");
|
||||
println!(" Status: {}", status.status);
|
||||
println!(" Filled: {} / {}", status.filled_quantity, status.quantity);
|
||||
println!(" Remaining: {}", status.remaining_quantity);
|
||||
|
||||
// Cancel order
|
||||
println!("\nCancelling order...");
|
||||
dex.spot.cancel_order(&limit_order.order_id).await?;
|
||||
println!("Order cancelled successfully");
|
||||
|
||||
// Get open orders
|
||||
let open_orders = dex.spot.get_open_orders("SYN-USDC").await?;
|
||||
println!("\nOpen orders: {}", open_orders.len());
|
||||
|
||||
// Get trade history
|
||||
let trades = dex.spot.get_trade_history("SYN-USDC", 10).await?;
|
||||
println!("\nRecent trades: {}", trades.len());
|
||||
for trade in trades.iter().take(3) {
|
||||
println!(" {:?} {} @ {} ({})", trade.side, trade.quantity, trade.price, trade.timestamp);
|
||||
}
|
||||
|
||||
println!();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn perps_trading_example(dex: &SynorDex) -> Result<(), Box<dyn std::error::Error>> {
|
||||
println!("=== Perpetual Futures Trading ===");
|
||||
|
||||
// Get available perps markets
|
||||
let perps_markets = dex.perps.list_markets().await?;
|
||||
println!("Available perps markets: {}", perps_markets.len());
|
||||
|
||||
for market in perps_markets.iter().take(3) {
|
||||
println!(
|
||||
" {}: {} (funding: {}%)",
|
||||
market.symbol, market.mark_price, market.funding_rate
|
||||
);
|
||||
}
|
||||
|
||||
// Open a long position
|
||||
println!("\nOpening long position...");
|
||||
let position = dex
|
||||
.perps
|
||||
.open_position(PerpsOrderRequest {
|
||||
market: "SYN-USDC-PERP".to_string(),
|
||||
side: OrderSide::Buy,
|
||||
order_type: OrderType::Limit,
|
||||
price: Some("1.50".to_string()),
|
||||
size: "1000".to_string(),
|
||||
leverage: 10,
|
||||
reduce_only: false,
|
||||
})
|
||||
.await?;
|
||||
|
||||
println!("Position opened:");
|
||||
println!(" Position ID: {}", position.position_id);
|
||||
println!(" Size: {}", position.size);
|
||||
println!(" Entry price: {}", position.entry_price);
|
||||
println!(" Leverage: {}x", position.leverage);
|
||||
println!(" Liquidation price: {}", position.liquidation_price);
|
||||
|
||||
// Get position details
|
||||
let details = dex.perps.get_position(&position.position_id).await?;
|
||||
println!("\nPosition details:");
|
||||
println!(" Unrealized PnL: {}", details.unrealized_pnl);
|
||||
println!(" Margin: {}", details.margin);
|
||||
println!(" Margin ratio: {}%", details.margin_ratio);
|
||||
|
||||
// Set stop loss and take profit
|
||||
println!("\nSetting stop loss and take profit...");
|
||||
dex.perps
|
||||
.set_stop_loss(&position.position_id, "1.40")
|
||||
.await?;
|
||||
println!("Stop loss set at 1.40");
|
||||
|
||||
dex.perps
|
||||
.set_take_profit(&position.position_id, "1.80")
|
||||
.await?;
|
||||
println!("Take profit set at 1.80");
|
||||
|
||||
// Close position
|
||||
println!("\nClosing position...");
|
||||
let close_result = dex.perps.close_position(&position.position_id).await?;
|
||||
println!("Position closed:");
|
||||
println!(" Realized PnL: {}", close_result.realized_pnl);
|
||||
println!(" Close price: {}", close_result.close_price);
|
||||
|
||||
// Get all positions
|
||||
let positions = dex.perps.get_positions().await?;
|
||||
println!("\nOpen positions: {}", positions.len());
|
||||
|
||||
// Get funding history
|
||||
let funding = dex.perps.get_funding_history("SYN-USDC-PERP", 10).await?;
|
||||
println!("Funding payments: {}", funding.len());
|
||||
|
||||
println!();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn liquidity_example(dex: &SynorDex) -> Result<(), Box<dyn std::error::Error>> {
|
||||
println!("=== Liquidity Provision ===");
|
||||
|
||||
// Get available pools
|
||||
let pools = dex.liquidity.list_pools().await?;
|
||||
println!("Available pools: {}", pools.len());
|
||||
|
||||
for pool in pools.iter().take(3) {
|
||||
println!("\n {}:", pool.name);
|
||||
println!(" TVL: ${}", pool.tvl);
|
||||
println!(" APR: {}%", pool.apr);
|
||||
println!(" Volume 24h: ${}", pool.volume_24h);
|
||||
println!(" Fee tier: {}%", pool.fee_tier);
|
||||
}
|
||||
|
||||
// Get pool details
|
||||
let pool = dex.liquidity.get_pool("SYN-USDC").await?;
|
||||
println!("\nSYN-USDC pool details:");
|
||||
println!(" Token0: {} ({})", pool.token0.symbol, pool.token0_reserve);
|
||||
println!(" Token1: {} ({})", pool.token1.symbol, pool.token1_reserve);
|
||||
println!(" Price: {}", pool.price);
|
||||
println!(" Total LP tokens: {}", pool.total_lp_tokens);
|
||||
|
||||
// Add liquidity
|
||||
println!("\nAdding liquidity...");
|
||||
let add_result = dex
|
||||
.liquidity
|
||||
.add_liquidity(AddLiquidityRequest {
|
||||
pool: "SYN-USDC".to_string(),
|
||||
amount0: "100".to_string(),
|
||||
amount1: "150".to_string(),
|
||||
slippage_bps: 50, // 0.5%
|
||||
})
|
||||
.await?;
|
||||
|
||||
println!("Liquidity added:");
|
||||
println!(" LP tokens received: {}", add_result.lp_tokens);
|
||||
println!(" Position ID: {}", add_result.position_id);
|
||||
println!(" Share of pool: {}%", add_result.share_of_pool);
|
||||
|
||||
// Get LP positions
|
||||
let lp_positions = dex.liquidity.get_positions().await?;
|
||||
println!("\nLP positions: {}", lp_positions.len());
|
||||
for pos in &lp_positions {
|
||||
println!(" {}: {} LP tokens (value: ${})", pos.pool, pos.lp_tokens, pos.value);
|
||||
}
|
||||
|
||||
// Claim fees
|
||||
println!("\nClaiming fees...");
|
||||
let fees = dex.liquidity.claim_fees(&add_result.position_id).await?;
|
||||
println!("Fees claimed:");
|
||||
println!(" Token0: {}", fees.amount0);
|
||||
println!(" Token1: {}", fees.amount1);
|
||||
|
||||
// Remove liquidity
|
||||
println!("\nRemoving liquidity...");
|
||||
let remove_result = dex
|
||||
.liquidity
|
||||
.remove_liquidity(RemoveLiquidityRequest {
|
||||
position_id: add_result.position_id.clone(),
|
||||
lp_tokens: add_result.lp_tokens.clone(),
|
||||
slippage_bps: 50,
|
||||
})
|
||||
.await?;
|
||||
|
||||
println!("Liquidity removed:");
|
||||
println!(" Token0 received: {}", remove_result.amount0);
|
||||
println!(" Token1 received: {}", remove_result.amount1);
|
||||
|
||||
println!();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn orderbook_example(dex: &SynorDex) -> Result<(), Box<dyn std::error::Error>> {
|
||||
println!("=== Order Book ===");
|
||||
|
||||
// Get order book snapshot
|
||||
let orderbook = dex.orderbook.get_snapshot("SYN-USDC", 10).await?;
|
||||
|
||||
println!("Order book for SYN-USDC:");
|
||||
println!("\nAsks (sells):");
|
||||
for ask in orderbook.asks.iter().take(5) {
|
||||
println!(" {} @ {}", ask.quantity, ask.price);
|
||||
}
|
||||
|
||||
println!("\nBids (buys):");
|
||||
for bid in orderbook.bids.iter().take(5) {
|
||||
println!(" {} @ {}", bid.quantity, bid.price);
|
||||
}
|
||||
|
||||
println!("\nSpread: {} ({}%)", orderbook.spread, orderbook.spread_percent);
|
||||
println!("Mid price: {}", orderbook.mid_price);
|
||||
|
||||
// Get recent trades
|
||||
let recent_trades = dex.orderbook.get_recent_trades("SYN-USDC", 10).await?;
|
||||
println!("\nRecent trades:");
|
||||
for trade in recent_trades.iter().take(5) {
|
||||
println!(" {:?} {} @ {}", trade.side, trade.quantity, trade.price);
|
||||
}
|
||||
|
||||
// Subscribe to orderbook updates (simulated)
|
||||
println!("\nSubscribing to orderbook updates...");
|
||||
let mut updates = dex.orderbook.subscribe("SYN-USDC").await?;
|
||||
|
||||
// Process a few updates
|
||||
tokio::spawn(async move {
|
||||
for _ in 0..3 {
|
||||
if let Some(update) = updates.recv().await {
|
||||
println!(" Update: {:?} {} @ {}", update.side, update.quantity, update.price);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
tokio::time::sleep(std::time::Duration::from_secs(2)).await;
|
||||
|
||||
println!();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn portfolio_example(dex: &SynorDex) -> Result<(), Box<dyn std::error::Error>> {
|
||||
println!("=== Portfolio ===");
|
||||
|
||||
// Get portfolio overview
|
||||
let portfolio = dex.portfolio.get_overview().await?;
|
||||
|
||||
println!("Portfolio overview:");
|
||||
println!(" Total value: ${}", portfolio.total_value);
|
||||
println!(" Available balance: ${}", portfolio.available_balance);
|
||||
println!(" In orders: ${}", portfolio.in_orders);
|
||||
println!(" In positions: ${}", portfolio.in_positions);
|
||||
println!(" Unrealized PnL: ${}", portfolio.unrealized_pnl);
|
||||
|
||||
// Get balances
|
||||
let balances = dex.portfolio.get_balances().await?;
|
||||
println!("\nBalances:");
|
||||
for balance in &balances {
|
||||
println!(
|
||||
" {}: {} (available: {}, in orders: {})",
|
||||
balance.asset, balance.total, balance.available, balance.in_orders
|
||||
);
|
||||
}
|
||||
|
||||
// Get PnL history
|
||||
let pnl_history = dex.portfolio.get_pnl_history(30).await?; // Last 30 days
|
||||
println!("\nPnL history (last {} days):", pnl_history.len());
|
||||
if let Some(last) = pnl_history.last() {
|
||||
println!(" Total PnL: ${}", last.cumulative_pnl);
|
||||
}
|
||||
|
||||
// Get trade statistics
|
||||
let stats = dex.portfolio.get_stats().await?;
|
||||
println!("\nTrade statistics:");
|
||||
println!(" Total trades: {}", stats.total_trades);
|
||||
println!(" Win rate: {}%", stats.win_rate);
|
||||
println!(" Avg profit: ${}", stats.avg_profit);
|
||||
println!(" Avg loss: ${}", stats.avg_loss);
|
||||
println!(" Best trade: ${}", stats.best_trade);
|
||||
println!(" Worst trade: ${}", stats.worst_trade);
|
||||
|
||||
println!();
|
||||
Ok(())
|
||||
}
|
||||
407
sdk/rust/examples/ibc_example.rs
Normal file
407
sdk/rust/examples/ibc_example.rs
Normal file
|
|
@ -0,0 +1,407 @@
|
|||
//! Synor IBC SDK Examples for Rust
|
||||
//!
|
||||
//! Demonstrates Inter-Blockchain Communication operations:
|
||||
//! - Cross-chain token transfers
|
||||
//! - Channel management
|
||||
//! - Packet handling
|
||||
//! - Relayer operations
|
||||
|
||||
use std::env;
|
||||
use std::time::{Duration, SystemTime, UNIX_EPOCH};
|
||||
use synor_ibc::{
|
||||
ChannelState, FeeEstimateRequest, IbcConfig, Network, RelayConfig, RelayerRegistration,
|
||||
SynorIbc, TransferRequest,
|
||||
};
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
// Initialize client
|
||||
let config = IbcConfig {
|
||||
api_key: env::var("SYNOR_API_KEY").unwrap_or_else(|_| "your-api-key".to_string()),
|
||||
endpoint: "https://ibc.synor.io/v1".to_string(),
|
||||
timeout: 30000,
|
||||
retries: 3,
|
||||
debug: false,
|
||||
default_network: Network::Mainnet,
|
||||
};
|
||||
|
||||
let ibc = SynorIbc::new(config)?;
|
||||
|
||||
// Check service health
|
||||
let healthy = ibc.health_check().await?;
|
||||
println!("Service healthy: {}\n", healthy);
|
||||
|
||||
// Run examples
|
||||
chains_example(&ibc).await?;
|
||||
channels_example(&ibc).await?;
|
||||
transfer_example(&ibc).await?;
|
||||
packet_example(&ibc).await?;
|
||||
relayer_example(&ibc).await?;
|
||||
connection_example(&ibc).await?;
|
||||
|
||||
ibc.close().await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn chains_example(ibc: &SynorIbc) -> Result<(), Box<dyn std::error::Error>> {
|
||||
println!("=== Connected Chains ===");
|
||||
|
||||
// Get all connected chains
|
||||
let chains = ibc.chains.list().await?;
|
||||
println!("Connected chains: {}", chains.len());
|
||||
|
||||
for chain in &chains {
|
||||
println!(" {}:", chain.chain_id);
|
||||
println!(" Name: {}", chain.name);
|
||||
println!(" Status: {}", chain.status);
|
||||
println!(" Block height: {}", chain.latest_height);
|
||||
println!(" Channels: {}", chain.channel_count);
|
||||
}
|
||||
|
||||
// Get specific chain info
|
||||
let cosmos = ibc.chains.get("cosmoshub-4").await?;
|
||||
println!("\nCosmos Hub details:");
|
||||
println!(" RPC: {}", cosmos.rpc_endpoint);
|
||||
println!(" Rest: {}", cosmos.rest_endpoint);
|
||||
println!(" Native denom: {}", cosmos.native_denom);
|
||||
println!(" Prefix: {}", cosmos.bech32_prefix);
|
||||
|
||||
// Get supported assets on a chain
|
||||
let assets = ibc.chains.get_assets("cosmoshub-4").await?;
|
||||
println!("\nSupported assets on Cosmos Hub:");
|
||||
for asset in assets.iter().take(5) {
|
||||
println!(" {}: {}", asset.symbol, asset.denom);
|
||||
println!(" Origin: {}", asset.origin_chain);
|
||||
println!(" Decimals: {}", asset.decimals);
|
||||
}
|
||||
|
||||
// Get chain paths (routes)
|
||||
let paths = ibc.chains.get_paths("synor-1", "cosmoshub-4").await?;
|
||||
println!("\nPaths from Synor to Cosmos Hub:");
|
||||
for path in &paths {
|
||||
println!(" {} -> {}", path.source_channel, path.dest_channel);
|
||||
println!(" Hops: {}", path.hops);
|
||||
println!(" Avg time: {}s", path.avg_transfer_time);
|
||||
}
|
||||
|
||||
println!();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn channels_example(ibc: &SynorIbc) -> Result<(), Box<dyn std::error::Error>> {
|
||||
println!("=== Channel Management ===");
|
||||
|
||||
// List all channels
|
||||
let channels = ibc.channels.list().await?;
|
||||
println!("Total channels: {}", channels.len());
|
||||
|
||||
// Filter by state
|
||||
let open_channels: Vec<_> = channels
|
||||
.iter()
|
||||
.filter(|c| c.state == ChannelState::Open)
|
||||
.collect();
|
||||
println!("Open channels: {}", open_channels.len());
|
||||
|
||||
for channel in open_channels.iter().take(3) {
|
||||
println!("\n Channel {}:", channel.channel_id);
|
||||
println!(" Port: {}", channel.port_id);
|
||||
println!(
|
||||
" Counterparty: {} on {}",
|
||||
channel.counterparty_channel_id, channel.counterparty_chain_id
|
||||
);
|
||||
println!(" Ordering: {}", channel.ordering);
|
||||
println!(" Version: {}", channel.version);
|
||||
println!(" State: {:?}", channel.state);
|
||||
}
|
||||
|
||||
// Get specific channel
|
||||
let channel = ibc.channels.get("channel-0").await?;
|
||||
println!("\nChannel-0 details:");
|
||||
println!(" Connection: {}", channel.connection_id);
|
||||
println!(" Counterparty port: {}", channel.counterparty_port_id);
|
||||
|
||||
// Get channel statistics
|
||||
let stats = ibc.channels.get_stats("channel-0").await?;
|
||||
println!("\nChannel-0 statistics:");
|
||||
println!(" Total packets sent: {}", stats.packets_sent);
|
||||
println!(" Total packets received: {}", stats.packets_received);
|
||||
println!(" Pending packets: {}", stats.pending_packets);
|
||||
println!(" Success rate: {:.1}%", stats.success_rate);
|
||||
println!(" Avg relay time: {}s", stats.avg_relay_time);
|
||||
|
||||
// Get channel capacity
|
||||
let capacity = ibc.channels.get_capacity("channel-0").await?;
|
||||
println!("\nChannel-0 capacity:");
|
||||
println!(" Max throughput: {} packets/block", capacity.max_packets_per_block);
|
||||
println!(" Current utilization: {:.1}%", capacity.utilization);
|
||||
|
||||
println!();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn transfer_example(ibc: &SynorIbc) -> Result<(), Box<dyn std::error::Error>> {
|
||||
println!("=== Cross-Chain Transfers ===");
|
||||
|
||||
// Estimate transfer fee
|
||||
let estimate = ibc
|
||||
.transfers
|
||||
.estimate_fee(FeeEstimateRequest {
|
||||
source_chain: "synor-1".to_string(),
|
||||
dest_chain: "cosmoshub-4".to_string(),
|
||||
denom: "usyn".to_string(),
|
||||
amount: "1000000".to_string(), // 1 SYN (6 decimals)
|
||||
})
|
||||
.await?;
|
||||
|
||||
println!("Transfer fee estimate:");
|
||||
println!(" Gas: {}", estimate.gas);
|
||||
println!(" Fee: {} {}", estimate.fee, estimate.fee_denom);
|
||||
println!(" Timeout: {}s", estimate.timeout);
|
||||
|
||||
// Calculate timeout timestamp (10 minutes from now)
|
||||
let timeout_timestamp = SystemTime::now()
|
||||
.duration_since(UNIX_EPOCH)?
|
||||
.as_millis() as u64
|
||||
+ 600000;
|
||||
|
||||
// Initiate a transfer
|
||||
println!("\nInitiating transfer...");
|
||||
let transfer = ibc
|
||||
.transfers
|
||||
.send(TransferRequest {
|
||||
source_chain: "synor-1".to_string(),
|
||||
dest_chain: "cosmoshub-4".to_string(),
|
||||
channel: "channel-0".to_string(),
|
||||
sender: "synor1abc...".to_string(), // Your address
|
||||
receiver: "cosmos1xyz...".to_string(), // Recipient address
|
||||
denom: "usyn".to_string(),
|
||||
amount: "1000000".to_string(), // 1 SYN
|
||||
memo: Some("Cross-chain transfer example".to_string()),
|
||||
timeout_height: 0, // Use timestamp instead
|
||||
timeout_timestamp,
|
||||
})
|
||||
.await?;
|
||||
|
||||
println!("Transfer initiated:");
|
||||
println!(" TX Hash: {}", transfer.tx_hash);
|
||||
println!(" Sequence: {}", transfer.sequence);
|
||||
println!(" Status: {}", transfer.status);
|
||||
|
||||
// Track transfer status
|
||||
println!("\nTracking transfer...");
|
||||
let status = ibc.transfers.get_status(&transfer.tx_hash).await?;
|
||||
println!("Current status: {}", status.state);
|
||||
println!(" Source confirmed: {}", status.source_confirmed);
|
||||
println!(" Relayed: {}", status.relayed);
|
||||
println!(" Dest confirmed: {}", status.dest_confirmed);
|
||||
|
||||
// Get transfer history
|
||||
let history = ibc.transfers.get_history("synor1abc...", 5).await?;
|
||||
println!("\nTransfer history (last 5):");
|
||||
for tx in &history {
|
||||
let direction = if tx.sender == "synor1abc..." {
|
||||
"OUT"
|
||||
} else {
|
||||
"IN"
|
||||
};
|
||||
println!(" {} {} {} ({})", direction, tx.amount, tx.denom, tx.status);
|
||||
}
|
||||
|
||||
// Get pending transfers
|
||||
let pending = ibc.transfers.get_pending("synor1abc...").await?;
|
||||
println!("\nPending transfers: {}", pending.len());
|
||||
|
||||
println!();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn packet_example(ibc: &SynorIbc) -> Result<(), Box<dyn std::error::Error>> {
|
||||
println!("=== Packet Handling ===");
|
||||
|
||||
// Get pending packets
|
||||
let packets = ibc.packets.get_pending("channel-0").await?;
|
||||
println!("Pending packets on channel-0: {}", packets.len());
|
||||
|
||||
for packet in packets.iter().take(3) {
|
||||
println!("\n Packet {}:", packet.sequence);
|
||||
println!(" Source: {}/{}", packet.source_port, packet.source_channel);
|
||||
println!(" Dest: {}/{}", packet.dest_port, packet.dest_channel);
|
||||
println!(" State: {}", packet.state);
|
||||
println!(" Data size: {} bytes", packet.data.len());
|
||||
println!(" Timeout height: {}", packet.timeout_height);
|
||||
println!(" Timeout timestamp: {}", packet.timeout_timestamp);
|
||||
}
|
||||
|
||||
// Get packet by sequence
|
||||
let packet = ibc.packets.get("channel-0", 1).await?;
|
||||
println!("\nPacket details:");
|
||||
println!(" Commitment: {}", packet.commitment);
|
||||
println!(" Receipt: {}", packet.receipt.unwrap_or_default());
|
||||
println!(" Acknowledgement: {}", packet.acknowledgement.unwrap_or_default());
|
||||
|
||||
// Get packet receipts
|
||||
let receipts = ibc.packets.get_receipts("channel-0", &[1, 2, 3]).await?;
|
||||
println!("\nPacket receipts:");
|
||||
for (seq, receipt) in &receipts {
|
||||
let status = if *receipt { "received" } else { "not received" };
|
||||
println!(" Sequence {}: {}", seq, status);
|
||||
}
|
||||
|
||||
// Get timed out packets
|
||||
let timed_out = ibc.packets.get_timed_out("channel-0").await?;
|
||||
println!("\nTimed out packets: {}", timed_out.len());
|
||||
for p in &timed_out {
|
||||
println!(" Sequence {}: timeout at {}", p.sequence, p.timeout_timestamp);
|
||||
}
|
||||
|
||||
// Get unreceived packets
|
||||
let unreceived = ibc.packets.get_unreceived("channel-0").await?;
|
||||
let unreceived_str = if unreceived.is_empty() {
|
||||
"none".to_string()
|
||||
} else {
|
||||
format!("{:?}", unreceived)
|
||||
};
|
||||
println!("\nUnreceived packet sequences: {}", unreceived_str);
|
||||
|
||||
// Get unacknowledged packets
|
||||
let unacked = ibc.packets.get_unacknowledged("channel-0").await?;
|
||||
let unacked_str = if unacked.is_empty() {
|
||||
"none".to_string()
|
||||
} else {
|
||||
format!("{:?}", unacked)
|
||||
};
|
||||
println!("Unacknowledged packet sequences: {}", unacked_str);
|
||||
|
||||
println!();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn relayer_example(ibc: &SynorIbc) -> Result<(), Box<dyn std::error::Error>> {
|
||||
println!("=== Relayer Operations ===");
|
||||
|
||||
// Get active relayers
|
||||
let relayers = ibc.relayers.list().await?;
|
||||
println!("Active relayers: {}", relayers.len());
|
||||
|
||||
for relayer in relayers.iter().take(3) {
|
||||
println!("\n {}:", relayer.address);
|
||||
println!(" Chains: {:?}", relayer.chains);
|
||||
println!(" Packets relayed: {}", relayer.packets_relayed);
|
||||
println!(" Success rate: {:.1}%", relayer.success_rate);
|
||||
println!(" Avg latency: {}ms", relayer.avg_latency);
|
||||
println!(" Fee rate: {:.2}%", relayer.fee_rate);
|
||||
}
|
||||
|
||||
// Get relayer statistics
|
||||
let stats = ibc.relayers.get_stats().await?;
|
||||
println!("\nGlobal relayer statistics:");
|
||||
println!(" Total relayers: {}", stats.total_relayers);
|
||||
println!(" Active relayers: {}", stats.active_relayers);
|
||||
println!(" Packets relayed (24h): {}", stats.packets_relayed_24h);
|
||||
println!(" Total fees earned: {}", stats.total_fees_earned);
|
||||
|
||||
// Register as a relayer
|
||||
println!("\nRegistering as relayer...");
|
||||
let registration = ibc
|
||||
.relayers
|
||||
.register(RelayerRegistration {
|
||||
chains: vec!["synor-1".to_string(), "cosmoshub-4".to_string()],
|
||||
fee_rate: 0.1, // 0.1% fee
|
||||
min_packet_size: 0,
|
||||
max_packet_size: 1000000,
|
||||
})
|
||||
.await?;
|
||||
println!("Registered with address: {}", registration.relayer_address);
|
||||
|
||||
// Start relaying (in background)
|
||||
println!("\nStarting relay service...");
|
||||
let relay_session = ibc
|
||||
.relayers
|
||||
.start_relay(RelayConfig {
|
||||
channels: vec!["channel-0".to_string()],
|
||||
auto_ack: true,
|
||||
batch_size: 10,
|
||||
poll_interval: 5000,
|
||||
})
|
||||
.await?;
|
||||
println!("Relay session started: {}", relay_session.session_id);
|
||||
|
||||
// Get relay queue
|
||||
let queue = ibc.relayers.get_queue("channel-0").await?;
|
||||
println!("\nRelay queue for channel-0: {} packets", queue.len());
|
||||
|
||||
// Manually relay a packet
|
||||
if let Some(first_packet) = queue.first() {
|
||||
println!("\nRelaying packet...");
|
||||
let relay_result = ibc
|
||||
.relayers
|
||||
.relay_packet(first_packet.sequence, "channel-0")
|
||||
.await?;
|
||||
println!("Relay result: {}", relay_result.status);
|
||||
println!(" TX Hash: {}", relay_result.tx_hash);
|
||||
println!(" Fee earned: {}", relay_result.fee_earned);
|
||||
}
|
||||
|
||||
// Stop relay session
|
||||
ibc.relayers.stop_relay(&relay_session.session_id).await?;
|
||||
println!("\nRelay session stopped");
|
||||
|
||||
println!();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn connection_example(ibc: &SynorIbc) -> Result<(), Box<dyn std::error::Error>> {
|
||||
println!("=== Connection Information ===");
|
||||
|
||||
// List connections
|
||||
let connections = ibc.connections.list().await?;
|
||||
println!("Total connections: {}", connections.len());
|
||||
|
||||
for conn in connections.iter().take(3) {
|
||||
println!("\n {}:", conn.connection_id);
|
||||
println!(" Client: {}", conn.client_id);
|
||||
println!(" Counterparty: {}", conn.counterparty_connection_id);
|
||||
println!(" State: {}", conn.state);
|
||||
println!(" Versions: {:?}", conn.versions);
|
||||
}
|
||||
|
||||
// Get connection details
|
||||
let connection = ibc.connections.get("connection-0").await?;
|
||||
println!("\nConnection-0 details:");
|
||||
println!(" Delay period: {}ns", connection.delay_period);
|
||||
println!(" Counterparty client: {}", connection.counterparty_client_id);
|
||||
println!(" Counterparty prefix: {}", connection.counterparty_prefix);
|
||||
|
||||
// Get client state
|
||||
let client = ibc.clients.get(&connection.client_id).await?;
|
||||
println!("\nClient state:");
|
||||
println!(" Chain ID: {}", client.chain_id);
|
||||
println!(" Trust level: {}", client.trust_level);
|
||||
println!(" Trusting period: {}", client.trusting_period);
|
||||
println!(" Unbonding period: {}", client.unbonding_period);
|
||||
println!(" Latest height: {}", client.latest_height);
|
||||
println!(" Frozen: {}", client.frozen);
|
||||
|
||||
// Get consensus state
|
||||
let consensus = ibc
|
||||
.clients
|
||||
.get_consensus_state(&connection.client_id, client.latest_height)
|
||||
.await?;
|
||||
println!("\nConsensus state at height {}:", client.latest_height);
|
||||
println!(" Timestamp: {}", consensus.timestamp);
|
||||
let root_preview = if consensus.root.len() > 20 {
|
||||
&consensus.root[..20]
|
||||
} else {
|
||||
&consensus.root
|
||||
};
|
||||
println!(" Root: {}...", root_preview);
|
||||
let validators_preview = if consensus.next_validators_hash.len() > 20 {
|
||||
&consensus.next_validators_hash[..20]
|
||||
} else {
|
||||
&consensus.next_validators_hash
|
||||
};
|
||||
println!(" Next validators hash: {}...", validators_preview);
|
||||
|
||||
println!();
|
||||
Ok(())
|
||||
}
|
||||
607
sdk/rust/examples/zk_example.rs
Normal file
607
sdk/rust/examples/zk_example.rs
Normal file
|
|
@ -0,0 +1,607 @@
|
|||
//! Synor ZK SDK Examples for Rust
|
||||
//!
|
||||
//! Demonstrates Zero-Knowledge proof operations:
|
||||
//! - Circuit compilation
|
||||
//! - Proof generation and verification
|
||||
//! - Groth16, PLONK, and STARK proving systems
|
||||
//! - Recursive proofs
|
||||
//! - On-chain verification
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::env;
|
||||
use std::time::Instant;
|
||||
use synor_zk::{
|
||||
AggregateRequest, BatchVerifyRequest, CircuitFormat, CompileRequest, ContributeRequest,
|
||||
DeployRequest, FormatProofRequest, GenerateProofRequest, GenerateVerifierRequest,
|
||||
OnChainVerifyRequest, ProofData, ProvingSystem, SetupInitRequest, SynorZk, VerifyAggregatedRequest,
|
||||
VerifyRequest, ZkConfig,
|
||||
};
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
// Initialize client
|
||||
let config = ZkConfig {
|
||||
api_key: env::var("SYNOR_API_KEY").unwrap_or_else(|_| "your-api-key".to_string()),
|
||||
endpoint: "https://zk.synor.io/v1".to_string(),
|
||||
timeout: 120000, // ZK ops can be slow
|
||||
retries: 3,
|
||||
debug: false,
|
||||
default_proving_system: ProvingSystem::Groth16,
|
||||
};
|
||||
|
||||
let zk = SynorZk::new(config)?;
|
||||
|
||||
// Check service health
|
||||
let healthy = zk.health_check().await?;
|
||||
println!("Service healthy: {}\n", healthy);
|
||||
|
||||
// Run examples
|
||||
circuit_example(&zk).await?;
|
||||
proof_example(&zk).await?;
|
||||
proving_systems_example(&zk).await?;
|
||||
recursive_proof_example(&zk).await?;
|
||||
on_chain_verification_example(&zk).await?;
|
||||
setup_example(&zk).await?;
|
||||
|
||||
zk.close().await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn circuit_example(zk: &SynorZk) -> Result<(), Box<dyn std::error::Error>> {
|
||||
println!("=== Circuit Compilation ===");
|
||||
|
||||
// Circom circuit example: prove knowledge of preimage
|
||||
let circom_circuit = r#"
|
||||
pragma circom 2.1.0;
|
||||
|
||||
template HashPreimage() {
|
||||
signal input preimage;
|
||||
signal input hash;
|
||||
|
||||
// Simplified hash computation (in reality, use proper hash)
|
||||
signal preimageSquared;
|
||||
preimageSquared <== preimage * preimage;
|
||||
|
||||
// Constrain that hash matches
|
||||
hash === preimageSquared;
|
||||
}
|
||||
|
||||
component main {public [hash]} = HashPreimage();
|
||||
"#;
|
||||
|
||||
// Compile circuit
|
||||
println!("Compiling Circom circuit...");
|
||||
let compiled = zk
|
||||
.circuits
|
||||
.compile(CompileRequest {
|
||||
code: circom_circuit.to_string(),
|
||||
format: CircuitFormat::Circom,
|
||||
name: "hash_preimage".to_string(),
|
||||
proving_system: ProvingSystem::Groth16,
|
||||
})
|
||||
.await?;
|
||||
|
||||
println!("Circuit compiled:");
|
||||
println!(" Circuit ID: {}", compiled.circuit_id);
|
||||
println!(" Constraints: {}", compiled.constraint_count);
|
||||
println!(" Public inputs: {}", compiled.public_input_count);
|
||||
println!(" Private inputs: {}", compiled.private_input_count);
|
||||
println!(" Proving key size: {} bytes", compiled.proving_key_size);
|
||||
println!(" Verification key size: {} bytes", compiled.verification_key_size);
|
||||
|
||||
// List circuits
|
||||
let circuits = zk.circuits.list().await?;
|
||||
println!("\nYour circuits: {}", circuits.len());
|
||||
for circuit in &circuits {
|
||||
println!(" {} ({})", circuit.name, circuit.circuit_id);
|
||||
}
|
||||
|
||||
// Get circuit details
|
||||
let details = zk.circuits.get(&compiled.circuit_id).await?;
|
||||
println!("\nCircuit details:");
|
||||
println!(" Format: {:?}", details.format);
|
||||
println!(" Proving system: {:?}", details.proving_system);
|
||||
println!(" Created: {}", details.created_at);
|
||||
|
||||
// Download proving key
|
||||
let proving_key = zk.circuits.get_proving_key(&compiled.circuit_id).await?;
|
||||
println!("\nProving key downloaded: {} bytes", proving_key.len());
|
||||
|
||||
// Download verification key
|
||||
let verification_key = zk.circuits.get_verification_key(&compiled.circuit_id).await?;
|
||||
println!("Verification key downloaded: {} bytes", verification_key.len());
|
||||
|
||||
println!();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn proof_example(zk: &SynorZk) -> Result<(), Box<dyn std::error::Error>> {
|
||||
println!("=== Proof Generation ===");
|
||||
|
||||
// First, compile a simple circuit
|
||||
let circuit = r#"
|
||||
pragma circom 2.1.0;
|
||||
|
||||
template Multiplier() {
|
||||
signal input a;
|
||||
signal input b;
|
||||
signal output c;
|
||||
|
||||
c <== a * b;
|
||||
}
|
||||
|
||||
component main {public [c]} = Multiplier();
|
||||
"#;
|
||||
|
||||
let compiled = zk
|
||||
.circuits
|
||||
.compile(CompileRequest {
|
||||
code: circuit.to_string(),
|
||||
format: CircuitFormat::Circom,
|
||||
name: "multiplier".to_string(),
|
||||
proving_system: ProvingSystem::Groth16,
|
||||
})
|
||||
.await?;
|
||||
|
||||
// Generate proof
|
||||
println!("Generating proof...");
|
||||
let start_time = Instant::now();
|
||||
|
||||
let mut inputs = HashMap::new();
|
||||
inputs.insert("a".to_string(), "3".to_string());
|
||||
inputs.insert("b".to_string(), "7".to_string());
|
||||
|
||||
let proof = zk
|
||||
.proofs
|
||||
.generate(GenerateProofRequest {
|
||||
circuit_id: compiled.circuit_id.clone(),
|
||||
inputs,
|
||||
})
|
||||
.await?;
|
||||
|
||||
let proof_time = start_time.elapsed();
|
||||
println!("Proof generated in {:?}", proof_time);
|
||||
println!(" Proof ID: {}", proof.proof_id);
|
||||
println!(" Proof size: {} bytes", proof.proof.len());
|
||||
println!(" Public signals: {:?}", proof.public_signals);
|
||||
|
||||
// Verify proof
|
||||
println!("\nVerifying proof...");
|
||||
let verify_start = Instant::now();
|
||||
|
||||
let is_valid = zk
|
||||
.proofs
|
||||
.verify(VerifyRequest {
|
||||
circuit_id: compiled.circuit_id.clone(),
|
||||
proof: proof.proof.clone(),
|
||||
public_signals: proof.public_signals.clone(),
|
||||
})
|
||||
.await?;
|
||||
|
||||
let verify_time = verify_start.elapsed();
|
||||
println!("Verification completed in {:?}", verify_time);
|
||||
println!(" Valid: {}", is_valid);
|
||||
|
||||
// Verify with wrong public signals (should fail)
|
||||
println!("\nVerifying with wrong signals...");
|
||||
let invalid_result = zk
|
||||
.proofs
|
||||
.verify(VerifyRequest {
|
||||
circuit_id: compiled.circuit_id.clone(),
|
||||
proof: proof.proof.clone(),
|
||||
public_signals: vec!["42".to_string()], // Wrong answer
|
||||
})
|
||||
.await?;
|
||||
println!(" Valid: {} (expected false)", invalid_result);
|
||||
|
||||
// Get proof status
|
||||
let status = zk.proofs.get_status(&proof.proof_id).await?;
|
||||
println!("\nProof status:");
|
||||
println!(" State: {}", status.state);
|
||||
println!(" Verified: {}", status.verified);
|
||||
println!(" Created: {}", status.created_at);
|
||||
|
||||
// List proofs
|
||||
let proofs = zk.proofs.list(&compiled.circuit_id).await?;
|
||||
println!("\nProofs for circuit: {}", proofs.len());
|
||||
|
||||
println!();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn proving_systems_example(zk: &SynorZk) -> Result<(), Box<dyn std::error::Error>> {
|
||||
println!("=== Proving Systems Comparison ===");
|
||||
|
||||
// Simple circuit for comparison
|
||||
let circuit = r#"
|
||||
pragma circom 2.1.0;
|
||||
|
||||
template Comparison() {
|
||||
signal input x;
|
||||
signal input y;
|
||||
signal output sum;
|
||||
|
||||
sum <== x + y;
|
||||
}
|
||||
|
||||
component main {public [sum]} = Comparison();
|
||||
"#;
|
||||
|
||||
let systems = [
|
||||
(ProvingSystem::Groth16, "GROTH16"),
|
||||
(ProvingSystem::PLONK, "PLONK"),
|
||||
(ProvingSystem::STARK, "STARK"),
|
||||
];
|
||||
|
||||
println!("Comparing proving systems:\n");
|
||||
|
||||
for (system, name) in systems {
|
||||
println!("{}:", name);
|
||||
|
||||
// Compile for this system
|
||||
let compiled = zk
|
||||
.circuits
|
||||
.compile(CompileRequest {
|
||||
code: circuit.to_string(),
|
||||
format: CircuitFormat::Circom,
|
||||
name: format!("comparison_{}", name.to_lowercase()),
|
||||
proving_system: system,
|
||||
})
|
||||
.await?;
|
||||
|
||||
// Generate proof
|
||||
let proof_start = Instant::now();
|
||||
let mut inputs = HashMap::new();
|
||||
inputs.insert("x".to_string(), "10".to_string());
|
||||
inputs.insert("y".to_string(), "20".to_string());
|
||||
|
||||
let proof = zk
|
||||
.proofs
|
||||
.generate(GenerateProofRequest {
|
||||
circuit_id: compiled.circuit_id.clone(),
|
||||
inputs,
|
||||
})
|
||||
.await?;
|
||||
let proof_time = proof_start.elapsed();
|
||||
|
||||
// Verify proof
|
||||
let verify_start = Instant::now();
|
||||
zk.proofs
|
||||
.verify(VerifyRequest {
|
||||
circuit_id: compiled.circuit_id.clone(),
|
||||
proof: proof.proof.clone(),
|
||||
public_signals: proof.public_signals.clone(),
|
||||
})
|
||||
.await?;
|
||||
let verify_time = verify_start.elapsed();
|
||||
|
||||
println!(" Setup: {}ms", compiled.setup_time);
|
||||
println!(" Proof time: {:?}", proof_time);
|
||||
println!(" Verify time: {:?}", verify_time);
|
||||
println!(" Proof size: {} bytes", proof.proof.len());
|
||||
println!(" Verification key: {} bytes", compiled.verification_key_size);
|
||||
println!();
|
||||
}
|
||||
|
||||
println!("Summary:");
|
||||
println!(" Groth16: Smallest proofs, fast verification, trusted setup required");
|
||||
println!(" PLONK: Universal setup, flexible, moderate proof size");
|
||||
println!(" STARK: No trusted setup, largest proofs, quantum resistant");
|
||||
|
||||
println!();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn recursive_proof_example(zk: &SynorZk) -> Result<(), Box<dyn std::error::Error>> {
|
||||
println!("=== Recursive Proofs ===");
|
||||
|
||||
// Inner circuit
|
||||
let inner_circuit = r#"
|
||||
pragma circom 2.1.0;
|
||||
|
||||
template Inner() {
|
||||
signal input x;
|
||||
signal output y;
|
||||
y <== x * x;
|
||||
}
|
||||
|
||||
component main {public [y]} = Inner();
|
||||
"#;
|
||||
|
||||
// Compile inner circuit
|
||||
let inner = zk
|
||||
.circuits
|
||||
.compile(CompileRequest {
|
||||
code: inner_circuit.to_string(),
|
||||
format: CircuitFormat::Circom,
|
||||
name: "inner_circuit".to_string(),
|
||||
proving_system: ProvingSystem::Groth16,
|
||||
})
|
||||
.await?;
|
||||
|
||||
// Generate multiple proofs to aggregate
|
||||
println!("Generating proofs to aggregate...");
|
||||
let mut proofs_to_aggregate = Vec::new();
|
||||
for i in 1..=4 {
|
||||
let mut inputs = HashMap::new();
|
||||
inputs.insert("x".to_string(), i.to_string());
|
||||
|
||||
let proof = zk
|
||||
.proofs
|
||||
.generate(GenerateProofRequest {
|
||||
circuit_id: inner.circuit_id.clone(),
|
||||
inputs,
|
||||
})
|
||||
.await?;
|
||||
|
||||
proofs_to_aggregate.push(ProofData {
|
||||
proof: proof.proof,
|
||||
public_signals: proof.public_signals.clone(),
|
||||
});
|
||||
println!(" Proof {}: y = {}", i, proof.public_signals[0]);
|
||||
}
|
||||
|
||||
// Aggregate proofs recursively
|
||||
println!("\nAggregating proofs...");
|
||||
let aggregated = zk
|
||||
.proofs
|
||||
.aggregate(AggregateRequest {
|
||||
circuit_id: inner.circuit_id.clone(),
|
||||
proofs: proofs_to_aggregate.clone(),
|
||||
aggregation_type: "recursive".to_string(),
|
||||
})
|
||||
.await?;
|
||||
|
||||
let original_size: usize = proofs_to_aggregate.iter().map(|p| p.proof.len()).sum();
|
||||
|
||||
println!("Aggregated proof:");
|
||||
println!(" Proof ID: {}", aggregated.proof_id);
|
||||
println!(" Aggregated count: {}", aggregated.aggregated_count);
|
||||
println!(" Proof size: {} bytes", aggregated.proof.len());
|
||||
println!(
|
||||
" Size reduction: {:.1}%",
|
||||
(1.0 - aggregated.proof.len() as f64 / original_size as f64) * 100.0
|
||||
);
|
||||
|
||||
// Verify aggregated proof
|
||||
let public_signals_list: Vec<Vec<String>> = proofs_to_aggregate
|
||||
.iter()
|
||||
.map(|p| p.public_signals.clone())
|
||||
.collect();
|
||||
|
||||
let is_valid = zk
|
||||
.proofs
|
||||
.verify_aggregated(VerifyAggregatedRequest {
|
||||
circuit_id: inner.circuit_id.clone(),
|
||||
proof: aggregated.proof,
|
||||
public_signals_list,
|
||||
})
|
||||
.await?;
|
||||
println!("\nAggregated proof valid: {}", is_valid);
|
||||
|
||||
// Batch verification (verify multiple proofs in one operation)
|
||||
println!("\nBatch verification...");
|
||||
let batch_result = zk
|
||||
.proofs
|
||||
.batch_verify(BatchVerifyRequest {
|
||||
circuit_id: inner.circuit_id.clone(),
|
||||
proofs: proofs_to_aggregate,
|
||||
})
|
||||
.await?;
|
||||
println!(" All valid: {}", batch_result.all_valid);
|
||||
println!(" Results: {:?}", batch_result.results);
|
||||
|
||||
println!();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn on_chain_verification_example(zk: &SynorZk) -> Result<(), Box<dyn std::error::Error>> {
|
||||
println!("=== On-Chain Verification ===");
|
||||
|
||||
// Compile circuit
|
||||
let circuit = r#"
|
||||
pragma circom 2.1.0;
|
||||
|
||||
template VoteCommitment() {
|
||||
signal input vote; // Private: actual vote
|
||||
signal input nullifier; // Private: unique identifier
|
||||
signal input commitment; // Public: commitment to verify
|
||||
|
||||
// Simplified commitment (in practice, use Poseidon hash)
|
||||
signal computed;
|
||||
computed <== vote * nullifier;
|
||||
commitment === computed;
|
||||
}
|
||||
|
||||
component main {public [commitment]} = VoteCommitment();
|
||||
"#;
|
||||
|
||||
let compiled = zk
|
||||
.circuits
|
||||
.compile(CompileRequest {
|
||||
code: circuit.to_string(),
|
||||
format: CircuitFormat::Circom,
|
||||
name: "vote_commitment".to_string(),
|
||||
proving_system: ProvingSystem::Groth16,
|
||||
})
|
||||
.await?;
|
||||
|
||||
// Generate Solidity verifier
|
||||
println!("Generating Solidity verifier...");
|
||||
let solidity_verifier = zk
|
||||
.contracts
|
||||
.generate_verifier(GenerateVerifierRequest {
|
||||
circuit_id: compiled.circuit_id.clone(),
|
||||
language: "solidity".to_string(),
|
||||
optimized: true,
|
||||
})
|
||||
.await?;
|
||||
println!(
|
||||
"Solidity verifier generated: {} bytes",
|
||||
solidity_verifier.code.len()
|
||||
);
|
||||
println!(" Contract name: {}", solidity_verifier.contract_name);
|
||||
println!(" Gas estimate: {}", solidity_verifier.gas_estimate);
|
||||
|
||||
// Generate proof
|
||||
let mut inputs = HashMap::new();
|
||||
inputs.insert("vote".to_string(), "1".to_string()); // Vote YES (1) or NO (0)
|
||||
inputs.insert("nullifier".to_string(), "12345".to_string());
|
||||
inputs.insert("commitment".to_string(), "12345".to_string()); // 1 * 12345
|
||||
|
||||
let proof = zk
|
||||
.proofs
|
||||
.generate(GenerateProofRequest {
|
||||
circuit_id: compiled.circuit_id.clone(),
|
||||
inputs,
|
||||
})
|
||||
.await?;
|
||||
|
||||
// Format proof for on-chain verification
|
||||
println!("\nFormatting proof for on-chain...");
|
||||
let on_chain_proof = zk
|
||||
.contracts
|
||||
.format_proof(FormatProofRequest {
|
||||
circuit_id: compiled.circuit_id.clone(),
|
||||
proof: proof.proof.clone(),
|
||||
public_signals: proof.public_signals.clone(),
|
||||
format: "calldata".to_string(),
|
||||
})
|
||||
.await?;
|
||||
|
||||
let calldata_preview = if on_chain_proof.calldata.len() > 100 {
|
||||
&on_chain_proof.calldata[..100]
|
||||
} else {
|
||||
&on_chain_proof.calldata
|
||||
};
|
||||
println!(" Calldata: {}...", calldata_preview);
|
||||
println!(" Estimated gas: {}", on_chain_proof.gas_estimate);
|
||||
|
||||
// Deploy verifier contract (simulation)
|
||||
println!("\nDeploying verifier contract...");
|
||||
let deployment = zk
|
||||
.contracts
|
||||
.deploy_verifier(DeployRequest {
|
||||
circuit_id: compiled.circuit_id.clone(),
|
||||
network: "synor-testnet".to_string(),
|
||||
})
|
||||
.await?;
|
||||
println!(" Contract address: {}", deployment.address);
|
||||
println!(" TX hash: {}", deployment.tx_hash);
|
||||
println!(" Gas used: {}", deployment.gas_used);
|
||||
|
||||
// Verify on-chain
|
||||
println!("\nVerifying on-chain...");
|
||||
let on_chain_result = zk
|
||||
.contracts
|
||||
.verify_on_chain(OnChainVerifyRequest {
|
||||
contract_address: deployment.address,
|
||||
proof: proof.proof,
|
||||
public_signals: proof.public_signals,
|
||||
network: "synor-testnet".to_string(),
|
||||
})
|
||||
.await?;
|
||||
println!(" TX hash: {}", on_chain_result.tx_hash);
|
||||
println!(" Verified: {}", on_chain_result.verified);
|
||||
println!(" Gas used: {}", on_chain_result.gas_used);
|
||||
|
||||
// Generate verifier for other targets
|
||||
println!("\nGenerating verifiers for other targets:");
|
||||
let targets = ["cairo", "noir", "ink"];
|
||||
for target in targets {
|
||||
let verifier = zk
|
||||
.contracts
|
||||
.generate_verifier(GenerateVerifierRequest {
|
||||
circuit_id: compiled.circuit_id.clone(),
|
||||
language: target.to_string(),
|
||||
optimized: false,
|
||||
})
|
||||
.await?;
|
||||
println!(" {}: {} bytes", target, verifier.code.len());
|
||||
}
|
||||
|
||||
println!();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn setup_example(zk: &SynorZk) -> Result<(), Box<dyn std::error::Error>> {
|
||||
println!("=== Trusted Setup ===");
|
||||
|
||||
// Get available ceremonies
|
||||
let ceremonies = zk.setup.list_ceremonies().await?;
|
||||
println!("Active ceremonies: {}", ceremonies.len());
|
||||
for ceremony in &ceremonies {
|
||||
println!(" {}:", ceremony.name);
|
||||
println!(" Status: {}", ceremony.status);
|
||||
println!(" Participants: {}", ceremony.participant_count);
|
||||
println!(" Current round: {}", ceremony.current_round);
|
||||
}
|
||||
|
||||
// Create a new circuit setup
|
||||
let circuit = r#"
|
||||
pragma circom 2.1.0;
|
||||
|
||||
template NewCircuit() {
|
||||
signal input a;
|
||||
signal output b;
|
||||
b <== a + 1;
|
||||
}
|
||||
|
||||
component main {public [b]} = NewCircuit();
|
||||
"#;
|
||||
|
||||
println!("\nInitializing setup for new circuit...");
|
||||
let setup = zk
|
||||
.setup
|
||||
.initialize(SetupInitRequest {
|
||||
circuit: circuit.to_string(),
|
||||
format: CircuitFormat::Circom,
|
||||
name: "new_circuit_setup".to_string(),
|
||||
proving_system: ProvingSystem::Groth16,
|
||||
ceremony_type: "powers_of_tau".to_string(), // or 'phase2'
|
||||
})
|
||||
.await?;
|
||||
println!("Setup initialized:");
|
||||
println!(" Ceremony ID: {}", setup.ceremony_id);
|
||||
println!(" Powers of Tau required: {}", setup.powers_required);
|
||||
println!(" Current phase: {}", setup.phase);
|
||||
|
||||
// Contribute to ceremony (in practice, generates random entropy)
|
||||
println!("\nContributing to ceremony...");
|
||||
let contribution = zk
|
||||
.setup
|
||||
.contribute(ContributeRequest {
|
||||
ceremony_id: setup.ceremony_id.clone(),
|
||||
entropy: hex::encode(b"random-entropy-from-user"),
|
||||
})
|
||||
.await?;
|
||||
println!("Contribution submitted:");
|
||||
println!(" Participant: {}", contribution.participant_id);
|
||||
println!(" Contribution hash: {}", contribution.hash);
|
||||
println!(" Verification status: {}", contribution.verified);
|
||||
|
||||
// Get ceremony status
|
||||
let status = zk.setup.get_status(&setup.ceremony_id).await?;
|
||||
println!("\nCeremony status:");
|
||||
println!(" Phase: {}", status.phase);
|
||||
println!(" Total contributions: {}", status.total_contributions);
|
||||
println!(" Verified contributions: {}", status.verified_contributions);
|
||||
println!(" Ready for finalization: {}", status.ready_for_finalization);
|
||||
|
||||
// Finalize setup (when enough contributions)
|
||||
if status.ready_for_finalization {
|
||||
println!("\nFinalizing setup...");
|
||||
let finalized = zk.setup.finalize(&setup.ceremony_id).await?;
|
||||
println!("Setup finalized:");
|
||||
println!(" Proving key hash: {}", finalized.proving_key_hash);
|
||||
println!(" Verification key hash: {}", finalized.verification_key_hash);
|
||||
println!(" Contribution transcript: {}", finalized.transcript_cid);
|
||||
}
|
||||
|
||||
// Download ceremony transcript
|
||||
let transcript = zk.setup.get_transcript(&setup.ceremony_id).await?;
|
||||
println!("\nCeremony transcript: {} bytes", transcript.len());
|
||||
|
||||
println!();
|
||||
Ok(())
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue