From cf5130d9e419b092d6e622982b21b832503d9817 Mon Sep 17 00:00:00 2001 From: Gulshan Yadav Date: Wed, 28 Jan 2026 14:44:04 +0530 Subject: [PATCH] feat(sdk): Add comprehensive examples for C, C++, C#, and Ruby SDKs Add example code demonstrating all SDK services (Crypto, DEX, ZK, IBC, Compiler) for the remaining languages: - C SDK (5 examples): Using synor_* C API with explicit memory management - C++ SDK (5 examples): Modern C++17 with RAII and designated initializers - C# SDK (5 examples): Async/await patterns with .NET conventions - Ruby SDK (5 examples): Ruby idioms with blocks and symbols Each example covers: - Crypto: Hybrid signatures, mnemonics, Falcon, SPHINCS+, KDF, hashing - DEX: Markets, spot trading, perpetuals, liquidity, portfolio - ZK: Circuits, Groth16, PLONK, STARK, recursive proofs, ceremonies - IBC: Chains, channels, transfers, packets, relayer, monitoring - Compiler: Compilation, optimization, ABI, analysis, validation, security --- sdk/c/examples/compiler_example.c | 553 +++++++++++++++++++++++++ sdk/c/examples/dex_example.c | 489 ++++++++++++++++++++++ sdk/c/examples/ibc_example.c | 545 ++++++++++++++++++++++++ sdk/c/examples/zk_example.c | 495 ++++++++++++++++++++++ sdk/cpp/examples/compiler_example.cpp | 377 +++++++++++++++++ sdk/cpp/examples/crypto_example.cpp | 273 ++++++++++++ sdk/cpp/examples/dex_example.cpp | 358 ++++++++++++++++ sdk/cpp/examples/ibc_example.cpp | 389 +++++++++++++++++ sdk/cpp/examples/zk_example.cpp | 359 ++++++++++++++++ sdk/csharp/examples/CompilerExample.cs | 415 +++++++++++++++++++ sdk/csharp/examples/CryptoExample.cs | 272 ++++++++++++ sdk/csharp/examples/DexExample.cs | 324 +++++++++++++++ sdk/csharp/examples/IbcExample.cs | 326 +++++++++++++++ sdk/csharp/examples/ZkExample.cs | 399 ++++++++++++++++++ sdk/ruby/examples/compiler_example.rb | 353 ++++++++++++++++ sdk/ruby/examples/crypto_example.rb | 241 +++++++++++ sdk/ruby/examples/dex_example.rb | 288 +++++++++++++ sdk/ruby/examples/ibc_example.rb | 290 +++++++++++++ sdk/ruby/examples/zk_example.rb | 345 +++++++++++++++ 19 files changed, 7091 insertions(+) create mode 100644 sdk/c/examples/compiler_example.c create mode 100644 sdk/c/examples/dex_example.c create mode 100644 sdk/c/examples/ibc_example.c create mode 100644 sdk/c/examples/zk_example.c create mode 100644 sdk/cpp/examples/compiler_example.cpp create mode 100644 sdk/cpp/examples/crypto_example.cpp create mode 100644 sdk/cpp/examples/dex_example.cpp create mode 100644 sdk/cpp/examples/ibc_example.cpp create mode 100644 sdk/cpp/examples/zk_example.cpp create mode 100644 sdk/csharp/examples/CompilerExample.cs create mode 100644 sdk/csharp/examples/CryptoExample.cs create mode 100644 sdk/csharp/examples/DexExample.cs create mode 100644 sdk/csharp/examples/IbcExample.cs create mode 100644 sdk/csharp/examples/ZkExample.cs create mode 100644 sdk/ruby/examples/compiler_example.rb create mode 100644 sdk/ruby/examples/crypto_example.rb create mode 100644 sdk/ruby/examples/dex_example.rb create mode 100644 sdk/ruby/examples/ibc_example.rb create mode 100644 sdk/ruby/examples/zk_example.rb diff --git a/sdk/c/examples/compiler_example.c b/sdk/c/examples/compiler_example.c new file mode 100644 index 0000000..e0b0a2a --- /dev/null +++ b/sdk/c/examples/compiler_example.c @@ -0,0 +1,553 @@ +/** + * Synor Compiler SDK Examples for C + * + * Demonstrates smart contract compilation and analysis: + * - WASM contract compilation and optimization + * - ABI extraction and encoding + * - Contract analysis and security scanning + * - Validation and verification + */ + +#include +#include +#include +#include + +// Helper function to create a minimal valid WASM module for testing +void create_minimal_wasm(uint8_t** wasm, size_t* wasm_len) { + static const uint8_t minimal_wasm[] = { + 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 + }; + + *wasm_len = sizeof(minimal_wasm); + *wasm = (uint8_t*)malloc(*wasm_len); + memcpy(*wasm, minimal_wasm, *wasm_len); +} + +void compile_contract_example(synor_compiler_t* compiler) { + printf("=== Contract Compilation ===\n"); + + synor_error_t err; + uint8_t* wasm; + size_t wasm_len; + create_minimal_wasm(&wasm, &wasm_len); + + synor_compile_options_t options = { + .optimization_level = SYNOR_OPTIMIZATION_SIZE, + .use_wasm_opt = true, + .validate = true, + .extract_metadata = true, + .generate_abi = true, + .strip_options = { + .strip_debug = true, + .strip_producers = true, + .strip_names = true, + .strip_custom = true, + .strip_unused = true + } + }; + + synor_compile_result_t* result = NULL; + err = synor_compile(compiler, wasm, wasm_len, &options, &result); + free(wasm); + + if (err != SYNOR_OK) { + fprintf(stderr, "Failed to compile contract\n"); + return; + } + + printf("Compilation result:\n"); + printf(" Contract ID: %s\n", synor_compile_result_get_contract_id(result)); + printf(" Code hash: %s\n", synor_compile_result_get_code_hash(result)); + printf(" Original size: %zu bytes\n", synor_compile_result_get_original_size(result)); + printf(" Optimized size: %zu bytes\n", synor_compile_result_get_optimized_size(result)); + printf(" Size reduction: %.1f%%\n", synor_compile_result_get_size_reduction(result)); + printf(" Estimated deploy gas: %lu\n", synor_compile_result_get_estimated_deploy_gas(result)); + + // Get metadata if available + synor_contract_metadata_t* metadata = synor_compile_result_get_metadata(result); + if (metadata) { + printf("\nMetadata:\n"); + printf(" Name: %s\n", synor_metadata_get_name(metadata)); + printf(" Version: %s\n", synor_metadata_get_version(metadata)); + printf(" SDK Version: %s\n", synor_metadata_get_sdk_version(metadata)); + } + + // Get ABI if available + synor_contract_abi_t* abi = synor_compile_result_get_abi(result); + if (abi) { + printf("\nABI:\n"); + printf(" Functions: %zu\n", synor_abi_get_function_count(abi)); + printf(" Events: %zu\n", synor_abi_get_event_count(abi)); + printf(" Errors: %zu\n", synor_abi_get_error_count(abi)); + } + + synor_compile_result_free(result); + printf("\n"); +} + +void compilation_modes_example(synor_compiler_t* compiler) { + printf("=== Compilation Modes ===\n"); + + synor_error_t err; + uint8_t* wasm; + size_t wasm_len; + create_minimal_wasm(&wasm, &wasm_len); + + // Development mode: fast compilation, debugging support + printf("Development mode:\n"); + synor_compile_result_t* dev_result = NULL; + err = synor_contracts_compile_dev(compiler, wasm, wasm_len, &dev_result); + if (err == SYNOR_OK) { + printf(" Size: %zu bytes\n", synor_compile_result_get_optimized_size(dev_result)); + printf(" Optimization: none\n"); + } + + // Production mode: maximum optimization + printf("\nProduction mode:\n"); + synor_compile_result_t* prod_result = NULL; + err = synor_contracts_compile_production(compiler, wasm, wasm_len, &prod_result); + if (err == SYNOR_OK) { + printf(" Size: %zu bytes\n", synor_compile_result_get_optimized_size(prod_result)); + printf(" Optimization: aggressive\n"); + if (dev_result) { + printf(" Size savings: %zu bytes\n", + synor_compile_result_get_optimized_size(dev_result) - + synor_compile_result_get_optimized_size(prod_result)); + } + synor_compile_result_free(prod_result); + } + + if (dev_result) synor_compile_result_free(dev_result); + + // Custom optimization levels + printf("\nOptimization levels:\n"); + synor_optimization_level_t levels[] = { + SYNOR_OPTIMIZATION_NONE, + SYNOR_OPTIMIZATION_BASIC, + SYNOR_OPTIMIZATION_SIZE, + SYNOR_OPTIMIZATION_AGGRESSIVE + }; + const char* level_names[] = {"NONE", "BASIC", "SIZE", "AGGRESSIVE"}; + + for (int i = 0; i < 4; i++) { + synor_compile_options_t options = { + .optimization_level = levels[i] + }; + + synor_compile_result_t* result = NULL; + err = synor_compile(compiler, wasm, wasm_len, &options, &result); + if (err == SYNOR_OK) { + printf(" %s: %zu bytes\n", level_names[i], + synor_compile_result_get_optimized_size(result)); + synor_compile_result_free(result); + } + } + + free(wasm); + printf("\n"); +} + +void abi_example(synor_compiler_t* compiler) { + printf("=== ABI Operations ===\n"); + + synor_error_t err; + uint8_t* wasm; + size_t wasm_len; + create_minimal_wasm(&wasm, &wasm_len); + + // Extract ABI from WASM + synor_contract_abi_t* abi = NULL; + err = synor_abi_extract(compiler, wasm, wasm_len, &abi); + free(wasm); + + if (err != SYNOR_OK) { + fprintf(stderr, "Failed to extract ABI\n"); + return; + } + + printf("Contract: %s\n", synor_abi_get_name(abi)); + printf("Version: %s\n", synor_abi_get_version(abi)); + + // List functions + size_t func_count = synor_abi_get_function_count(abi); + if (func_count > 0) { + printf("\nFunctions:\n"); + for (size_t i = 0; i < func_count; i++) { + synor_abi_function_t* func = synor_abi_get_function(abi, i); + + char inputs[256] = ""; + size_t input_count = synor_abi_function_get_input_count(func); + for (size_t j = 0; j < input_count; j++) { + synor_abi_param_t* param = synor_abi_function_get_input(func, j); + char temp[64]; + snprintf(temp, sizeof(temp), "%s: %s%s", + synor_abi_param_get_name(param), + synor_abi_param_get_type_name(param), + j < input_count - 1 ? ", " : ""); + strncat(inputs, temp, sizeof(inputs) - strlen(inputs) - 1); + } + + char outputs[128] = "void"; + size_t output_count = synor_abi_function_get_output_count(func); + if (output_count > 0) { + outputs[0] = '\0'; + for (size_t j = 0; j < output_count; j++) { + synor_abi_param_t* param = synor_abi_function_get_output(func, j); + char temp[64]; + snprintf(temp, sizeof(temp), "%s%s", + synor_abi_param_get_type_name(param), + j < output_count - 1 ? ", " : ""); + strncat(outputs, temp, sizeof(outputs) - strlen(outputs) - 1); + } + } + + char modifiers[32] = ""; + if (synor_abi_function_is_view(func)) strcat(modifiers, "view "); + if (synor_abi_function_is_payable(func)) strcat(modifiers, "payable"); + + printf(" %s(%s) -> %s %s\n", + synor_abi_function_get_name(func), inputs, outputs, modifiers); + printf(" Selector: %s\n", synor_abi_function_get_selector(func)); + } + } + + // List events + size_t event_count = synor_abi_get_event_count(abi); + if (event_count > 0) { + printf("\nEvents:\n"); + for (size_t i = 0; i < event_count; i++) { + synor_abi_event_t* event = synor_abi_get_event(abi, i); + + char params[256] = ""; + size_t param_count = synor_abi_event_get_param_count(event); + for (size_t j = 0; j < param_count; j++) { + synor_abi_event_param_t* param = synor_abi_event_get_param(event, j); + char temp[64]; + snprintf(temp, sizeof(temp), "%s%s: %s%s", + synor_abi_event_param_is_indexed(param) ? "indexed " : "", + synor_abi_event_param_get_name(param), + synor_abi_event_param_get_type_name(param), + j < param_count - 1 ? ", " : ""); + strncat(params, temp, sizeof(params) - strlen(params) - 1); + } + + printf(" %s(%s)\n", synor_abi_event_get_name(event), params); + printf(" Topic: %s\n", synor_abi_event_get_topic(event)); + } + } + + // Encode a function call + if (func_count > 0) { + synor_abi_function_t* func = synor_abi_get_function(abi, 0); + const char* args[] = {"arg1", "arg2"}; + + uint8_t* encoded; + size_t encoded_len; + err = synor_abi_encode_call(compiler, func, args, 2, &encoded, &encoded_len); + if (err == SYNOR_OK) { + printf("\nEncoded call to %s: ", synor_abi_function_get_name(func)); + for (size_t i = 0; i < encoded_len && i < 20; i++) { + printf("%02x", encoded[i]); + } + printf("...\n"); + + // Decode a result + char** decoded; + size_t decoded_count; + err = synor_abi_decode_result(compiler, func, encoded, encoded_len, + &decoded, &decoded_count); + if (err == SYNOR_OK) { + printf("Decoded result: "); + for (size_t i = 0; i < decoded_count; i++) { + printf("%s%s", decoded[i], i < decoded_count - 1 ? ", " : ""); + } + printf("\n"); + synor_string_array_free(decoded, decoded_count); + } + + free(encoded); + } + } + + synor_abi_free(abi); + printf("\n"); +} + +void analysis_example(synor_compiler_t* compiler) { + printf("=== Contract Analysis ===\n"); + + synor_error_t err; + uint8_t* wasm; + size_t wasm_len; + create_minimal_wasm(&wasm, &wasm_len); + + // Full analysis + synor_contract_analysis_t* analysis = NULL; + err = synor_analysis_analyze(compiler, wasm, wasm_len, &analysis); + if (err != SYNOR_OK) { + fprintf(stderr, "Failed to analyze contract\n"); + free(wasm); + return; + } + + // Size breakdown + synor_size_breakdown_t* size = synor_analysis_get_size_breakdown(analysis); + if (size) { + printf("Size breakdown:\n"); + printf(" Code: %zu bytes\n", synor_size_breakdown_get_code(size)); + printf(" Data: %zu bytes\n", synor_size_breakdown_get_data(size)); + printf(" Functions: %zu bytes\n", synor_size_breakdown_get_functions(size)); + printf(" Memory: %zu bytes\n", synor_size_breakdown_get_memory(size)); + printf(" Exports: %zu bytes\n", synor_size_breakdown_get_exports(size)); + printf(" Imports: %zu bytes\n", synor_size_breakdown_get_imports(size)); + printf(" Total: %zu bytes\n", synor_size_breakdown_get_total(size)); + } + + // Function analysis + size_t func_count = synor_analysis_get_function_count(analysis); + if (func_count > 0) { + printf("\nFunction analysis:\n"); + for (size_t i = 0; i < 5 && i < func_count; i++) { + synor_function_analysis_t* func = synor_analysis_get_function(analysis, i); + printf(" %s:\n", synor_function_analysis_get_name(func)); + printf(" Size: %zu bytes\n", synor_function_analysis_get_size(func)); + printf(" Instructions: %zu\n", synor_function_analysis_get_instruction_count(func)); + printf(" Locals: %zu\n", synor_function_analysis_get_local_count(func)); + printf(" Exported: %s\n", synor_function_analysis_is_exported(func) ? "true" : "false"); + printf(" Estimated gas: %lu\n", synor_function_analysis_get_estimated_gas(func)); + } + } + + // Import analysis + size_t import_count = synor_analysis_get_import_count(analysis); + if (import_count > 0) { + printf("\nImports:\n"); + for (size_t i = 0; i < import_count; i++) { + synor_import_analysis_t* imp = synor_analysis_get_import(analysis, i); + printf(" %s.%s (%s)\n", + synor_import_analysis_get_module(imp), + synor_import_analysis_get_name(imp), + synor_import_analysis_get_kind(imp)); + } + } + + // Gas analysis + synor_gas_analysis_t* gas = synor_analysis_get_gas_analysis(analysis); + if (gas) { + printf("\nGas analysis:\n"); + printf(" Deployment: %lu\n", synor_gas_analysis_get_deployment_gas(gas)); + printf(" Memory init: %lu\n", synor_gas_analysis_get_memory_init_gas(gas)); + printf(" Data section: %lu\n", synor_gas_analysis_get_data_section_gas(gas)); + } + + synor_analysis_free(analysis); + + // Extract metadata + synor_contract_metadata_t* metadata = NULL; + err = synor_analysis_extract_metadata(compiler, wasm, wasm_len, &metadata); + if (err == SYNOR_OK) { + printf("\nContract metadata:\n"); + printf(" Name: %s\n", synor_metadata_get_name(metadata)); + printf(" Version: %s\n", synor_metadata_get_version(metadata)); + printf(" Build timestamp: %s\n", synor_metadata_get_build_timestamp(metadata)); + synor_metadata_free(metadata); + } + + // Estimate deployment gas + uint64_t gas_estimate; + err = synor_analysis_estimate_deploy_gas(compiler, wasm, wasm_len, &gas_estimate); + if (err == SYNOR_OK) { + printf("\nEstimated deployment gas: %lu\n", gas_estimate); + } + + free(wasm); + printf("\n"); +} + +void validation_example(synor_compiler_t* compiler) { + printf("=== Contract Validation ===\n"); + + synor_error_t err; + uint8_t* wasm; + size_t wasm_len; + create_minimal_wasm(&wasm, &wasm_len); + + // Full validation + synor_validation_result_t* result = NULL; + err = synor_validation_validate(compiler, wasm, wasm_len, &result); + if (err == SYNOR_OK) { + printf("Valid: %s\n", synor_validation_result_is_valid(result) ? "true" : "false"); + printf("Exports: %zu\n", synor_validation_result_get_export_count(result)); + printf("Imports: %zu\n", synor_validation_result_get_import_count(result)); + printf("Functions: %zu\n", synor_validation_result_get_function_count(result)); + printf("Memory pages: %zu\n", synor_validation_result_get_memory_pages(result)); + + // Print errors + size_t error_count = synor_validation_result_get_error_count(result); + if (error_count > 0) { + printf("\nValidation errors:\n"); + for (size_t i = 0; i < error_count; i++) { + synor_validation_error_t* error = synor_validation_result_get_error(result, i); + printf(" [%s] %s\n", + synor_validation_error_get_code(error), + synor_validation_error_get_message(error)); + const char* location = synor_validation_error_get_location(error); + if (location) { + printf(" at %s\n", location); + } + } + } + + // Print warnings + size_t warning_count = synor_validation_result_get_warning_count(result); + if (warning_count > 0) { + printf("\nWarnings:\n"); + for (size_t i = 0; i < warning_count; i++) { + printf(" %s\n", synor_validation_result_get_warning(result, i)); + } + } + + synor_validation_result_free(result); + } + + // Quick validation + bool is_valid; + err = synor_validation_is_valid(compiler, wasm, wasm_len, &is_valid); + printf("\nQuick validation: %s\n", is_valid ? "true" : "false"); + + // Get validation errors only + synor_validation_error_list_t* errors = NULL; + err = synor_validation_get_errors(compiler, wasm, wasm_len, &errors); + if (err == SYNOR_OK) { + printf("Error count: %zu\n", synor_validation_error_list_count(errors)); + synor_validation_error_list_free(errors); + } + + // Validate required exports + const char* required[] = {"init", "execute", "query"}; + bool has_required; + err = synor_validation_validate_exports(compiler, wasm, wasm_len, + required, 3, &has_required); + printf("Has required exports: %s\n", has_required ? "true" : "false"); + + // Validate memory constraints + bool memory_valid; + err = synor_validation_validate_memory(compiler, wasm, wasm_len, 16, &memory_valid); + printf("Memory within 16 pages: %s\n", memory_valid ? "true" : "false"); + + free(wasm); + printf("\n"); +} + +void security_example(synor_compiler_t* compiler) { + printf("=== Security Scanning ===\n"); + + synor_error_t err; + uint8_t* wasm; + size_t wasm_len; + create_minimal_wasm(&wasm, &wasm_len); + + synor_security_scan_result_t* security = NULL; + err = synor_analysis_security_scan(compiler, wasm, wasm_len, &security); + free(wasm); + + if (err != SYNOR_OK) { + fprintf(stderr, "Failed to scan contract\n"); + return; + } + + printf("Security score: %d/100\n", synor_security_scan_get_score(security)); + + size_t issue_count = synor_security_scan_get_issue_count(security); + if (issue_count > 0) { + printf("\nSecurity issues:\n"); + for (size_t i = 0; i < issue_count; i++) { + synor_security_issue_t* issue = synor_security_scan_get_issue(security, i); + const char* severity = synor_security_issue_get_severity(issue); + const char* icon; + + if (strcmp(severity, "critical") == 0) icon = "[CRIT]"; + else if (strcmp(severity, "high") == 0) icon = "[HIGH]"; + else if (strcmp(severity, "medium") == 0) icon = "[MED]"; + else if (strcmp(severity, "low") == 0) icon = "[LOW]"; + else icon = "[???]"; + + printf("%s [%s] %s\n", icon, + synor_security_issue_get_severity(issue), + synor_security_issue_get_type(issue)); + printf(" %s\n", synor_security_issue_get_description(issue)); + + const char* location = synor_security_issue_get_location(issue); + if (location) { + printf(" at %s\n", location); + } + } + } else { + printf("No security issues found!\n"); + } + + size_t rec_count = synor_security_scan_get_recommendation_count(security); + if (rec_count > 0) { + printf("\nRecommendations:\n"); + for (size_t i = 0; i < rec_count; i++) { + printf(" • %s\n", synor_security_scan_get_recommendation(security, i)); + } + } + + synor_security_scan_result_free(security); + printf("\n"); +} + +int main(int argc, char** argv) { + synor_error_t err; + + // Initialize client + synor_compiler_config_t config = { + .api_key = getenv("SYNOR_API_KEY") ? getenv("SYNOR_API_KEY") : "your-api-key", + .endpoint = "https://compiler.synor.io/v1", + .timeout_ms = 60000, + .retries = 3, + .debug = false, + .default_optimization_level = SYNOR_OPTIMIZATION_SIZE, + .max_contract_size = 256 * 1024, + .use_wasm_opt = true, + .validate = true, + .extract_metadata = true, + .generate_abi = true + }; + + synor_compiler_t* compiler = NULL; + err = synor_compiler_init(&config, &compiler); + if (err != SYNOR_OK) { + fprintf(stderr, "Failed to initialize compiler client: %s\n", synor_error_string(err)); + return 1; + } + + // Check service health + bool healthy; + err = synor_compiler_health_check(compiler, &healthy); + printf("Service healthy: %s\n\n", healthy ? "true" : "false"); + + // Run examples + compile_contract_example(compiler); + compilation_modes_example(compiler); + abi_example(compiler); + analysis_example(compiler); + validation_example(compiler); + security_example(compiler); + + // Cleanup + synor_compiler_free(compiler); + + return 0; +} diff --git a/sdk/c/examples/dex_example.c b/sdk/c/examples/dex_example.c new file mode 100644 index 0000000..dd0504a --- /dev/null +++ b/sdk/c/examples/dex_example.c @@ -0,0 +1,489 @@ +/** + * Synor DEX SDK Examples for C + * + * Demonstrates decentralized exchange operations: + * - Spot trading (limit/market orders) + * - Perpetual futures trading + * - Liquidity provision (AMM pools) + * - Order book management + * - Portfolio tracking + */ + +#include +#include +#include +#include + +void markets_example(synor_dex_t* dex) { + printf("=== Markets ===\n"); + + synor_error_t err; + synor_market_list_t* markets = NULL; + + // Get all markets + err = synor_markets_list(dex, &markets); + if (err != SYNOR_OK) { + fprintf(stderr, "Failed to get markets\n"); + return; + } + + printf("Available markets: %zu\n", synor_market_list_count(markets)); + + for (size_t i = 0; i < 5 && i < synor_market_list_count(markets); i++) { + synor_market_t* market = synor_market_list_get(markets, i); + printf("\n %s:\n", synor_market_get_symbol(market)); + printf(" Base: %s, Quote: %s\n", + synor_market_get_base_asset(market), + synor_market_get_quote_asset(market)); + printf(" Price: %s\n", synor_market_get_last_price(market)); + printf(" 24h Volume: %s\n", synor_market_get_volume_24h(market)); + printf(" 24h Change: %s%%\n", synor_market_get_change_24h(market)); + printf(" Status: %s\n", synor_market_get_status(market)); + } + + // Get specific market + synor_market_t* market = NULL; + err = synor_markets_get(dex, "SYN-USDC", &market); + if (err == SYNOR_OK) { + printf("\nSYN-USDC details:\n"); + printf(" Min order size: %s\n", synor_market_get_min_order_size(market)); + printf(" Tick size: %s\n", synor_market_get_tick_size(market)); + printf(" Maker fee: %s%%\n", synor_market_get_maker_fee(market)); + printf(" Taker fee: %s%%\n", synor_market_get_taker_fee(market)); + synor_market_free(market); + } + + // Get market statistics + synor_market_stats_t* stats = NULL; + err = synor_markets_get_stats(dex, "SYN-USDC", &stats); + if (err == SYNOR_OK) { + printf("\nMarket statistics:\n"); + printf(" High 24h: %s\n", synor_stats_get_high_24h(stats)); + printf(" Low 24h: %s\n", synor_stats_get_low_24h(stats)); + printf(" Open interest: %s\n", synor_stats_get_open_interest(stats)); + printf(" Funding rate: %s%%\n", synor_stats_get_funding_rate(stats)); + synor_market_stats_free(stats); + } + + synor_market_list_free(markets); + printf("\n"); +} + +void spot_trading_example(synor_dex_t* dex) { + printf("=== Spot Trading ===\n"); + + synor_error_t err; + + // Place a limit order + printf("Placing limit buy order...\n"); + synor_order_request_t limit_req = { + .market = "SYN-USDC", + .side = SYNOR_ORDER_SIDE_BUY, + .order_type = SYNOR_ORDER_TYPE_LIMIT, + .price = "1.50", + .quantity = "100", + .time_in_force = SYNOR_TIME_IN_FORCE_GTC + }; + + synor_order_result_t* limit_order = NULL; + err = synor_spot_place_order(dex, &limit_req, &limit_order); + if (err != SYNOR_OK) { + fprintf(stderr, "Failed to place limit order\n"); + return; + } + + printf("Limit order placed:\n"); + printf(" Order ID: %s\n", synor_order_get_id(limit_order)); + printf(" Status: %s\n", synor_order_get_status(limit_order)); + printf(" Price: %s\n", synor_order_get_price(limit_order)); + printf(" Quantity: %s\n", synor_order_get_quantity(limit_order)); + + // Place a market order + printf("\nPlacing market sell order...\n"); + synor_order_request_t market_req = { + .market = "SYN-USDC", + .side = SYNOR_ORDER_SIDE_SELL, + .order_type = SYNOR_ORDER_TYPE_MARKET, + .quantity = "50" + }; + + synor_order_result_t* market_order = NULL; + err = synor_spot_place_order(dex, &market_req, &market_order); + if (err == SYNOR_OK) { + printf("Market order executed:\n"); + printf(" Order ID: %s\n", synor_order_get_id(market_order)); + printf(" Status: %s\n", synor_order_get_status(market_order)); + printf(" Filled: %s\n", synor_order_get_filled_quantity(market_order)); + printf(" Avg price: %s\n", synor_order_get_avg_price(market_order)); + synor_order_result_free(market_order); + } + + // Get order status + synor_order_status_t* status = NULL; + err = synor_spot_get_order(dex, synor_order_get_id(limit_order), &status); + if (err == SYNOR_OK) { + printf("\nOrder status:\n"); + printf(" Status: %s\n", synor_order_status_get_status(status)); + printf(" Filled: %s / %s\n", + synor_order_status_get_filled(status), + synor_order_status_get_quantity(status)); + printf(" Remaining: %s\n", synor_order_status_get_remaining(status)); + synor_order_status_free(status); + } + + // Cancel order + printf("\nCancelling order...\n"); + err = synor_spot_cancel_order(dex, synor_order_get_id(limit_order)); + if (err == SYNOR_OK) { + printf("Order cancelled successfully\n"); + } + + // Get open orders + synor_order_list_t* open_orders = NULL; + err = synor_spot_get_open_orders(dex, "SYN-USDC", &open_orders); + if (err == SYNOR_OK) { + printf("\nOpen orders: %zu\n", synor_order_list_count(open_orders)); + synor_order_list_free(open_orders); + } + + // Get trade history + synor_trade_list_t* trades = NULL; + err = synor_spot_get_trade_history(dex, "SYN-USDC", 10, &trades); + if (err == SYNOR_OK) { + printf("\nRecent trades: %zu\n", synor_trade_list_count(trades)); + for (size_t i = 0; i < 3 && i < synor_trade_list_count(trades); i++) { + synor_trade_t* trade = synor_trade_list_get(trades, i); + printf(" %s %s @ %s (%s)\n", + synor_trade_get_side(trade), + synor_trade_get_quantity(trade), + synor_trade_get_price(trade), + synor_trade_get_timestamp(trade)); + } + synor_trade_list_free(trades); + } + + synor_order_result_free(limit_order); + printf("\n"); +} + +void perps_trading_example(synor_dex_t* dex) { + printf("=== Perpetual Futures Trading ===\n"); + + synor_error_t err; + + // Get available perps markets + synor_perps_market_list_t* perps_markets = NULL; + err = synor_perps_list_markets(dex, &perps_markets); + if (err == SYNOR_OK) { + printf("Available perps markets: %zu\n", synor_perps_market_list_count(perps_markets)); + for (size_t i = 0; i < 3 && i < synor_perps_market_list_count(perps_markets); i++) { + synor_perps_market_t* market = synor_perps_market_list_get(perps_markets, i); + printf(" %s: %s (funding: %s%%)\n", + synor_perps_market_get_symbol(market), + synor_perps_market_get_mark_price(market), + synor_perps_market_get_funding_rate(market)); + } + synor_perps_market_list_free(perps_markets); + } + + // Open a long position + printf("\nOpening long position...\n"); + synor_perps_order_request_t perps_req = { + .market = "SYN-USDC-PERP", + .side = SYNOR_ORDER_SIDE_BUY, + .order_type = SYNOR_ORDER_TYPE_LIMIT, + .price = "1.50", + .size = "1000", + .leverage = 10, + .reduce_only = false + }; + + synor_position_t* position = NULL; + err = synor_perps_open_position(dex, &perps_req, &position); + if (err != SYNOR_OK) { + fprintf(stderr, "Failed to open position\n"); + return; + } + + printf("Position opened:\n"); + printf(" Position ID: %s\n", synor_position_get_id(position)); + printf(" Size: %s\n", synor_position_get_size(position)); + printf(" Entry price: %s\n", synor_position_get_entry_price(position)); + printf(" Leverage: %dx\n", synor_position_get_leverage(position)); + printf(" Liquidation price: %s\n", synor_position_get_liquidation_price(position)); + + // Get position details + synor_position_details_t* details = NULL; + err = synor_perps_get_position(dex, synor_position_get_id(position), &details); + if (err == SYNOR_OK) { + printf("\nPosition details:\n"); + printf(" Unrealized PnL: %s\n", synor_position_details_get_unrealized_pnl(details)); + printf(" Margin: %s\n", synor_position_details_get_margin(details)); + printf(" Margin ratio: %s%%\n", synor_position_details_get_margin_ratio(details)); + synor_position_details_free(details); + } + + // Set stop loss and take profit + printf("\nSetting stop loss and take profit...\n"); + err = synor_perps_set_stop_loss(dex, synor_position_get_id(position), "1.40"); + if (err == SYNOR_OK) printf("Stop loss set at 1.40\n"); + + err = synor_perps_set_take_profit(dex, synor_position_get_id(position), "1.80"); + if (err == SYNOR_OK) printf("Take profit set at 1.80\n"); + + // Close position + printf("\nClosing position...\n"); + synor_close_result_t* close_result = NULL; + err = synor_perps_close_position(dex, synor_position_get_id(position), &close_result); + if (err == SYNOR_OK) { + printf("Position closed:\n"); + printf(" Realized PnL: %s\n", synor_close_result_get_realized_pnl(close_result)); + printf(" Close price: %s\n", synor_close_result_get_close_price(close_result)); + synor_close_result_free(close_result); + } + + // Get all positions + synor_position_list_t* positions = NULL; + err = synor_perps_get_positions(dex, &positions); + if (err == SYNOR_OK) { + printf("\nOpen positions: %zu\n", synor_position_list_count(positions)); + synor_position_list_free(positions); + } + + synor_position_free(position); + printf("\n"); +} + +void liquidity_example(synor_dex_t* dex) { + printf("=== Liquidity Provision ===\n"); + + synor_error_t err; + + // Get available pools + synor_pool_list_t* pools = NULL; + err = synor_liquidity_list_pools(dex, &pools); + if (err == SYNOR_OK) { + printf("Available pools: %zu\n", synor_pool_list_count(pools)); + for (size_t i = 0; i < 3 && i < synor_pool_list_count(pools); i++) { + synor_pool_t* pool = synor_pool_list_get(pools, i); + printf("\n %s:\n", synor_pool_get_name(pool)); + printf(" TVL: $%s\n", synor_pool_get_tvl(pool)); + printf(" APR: %s%%\n", synor_pool_get_apr(pool)); + printf(" Volume 24h: $%s\n", synor_pool_get_volume_24h(pool)); + printf(" Fee tier: %s%%\n", synor_pool_get_fee_tier(pool)); + } + synor_pool_list_free(pools); + } + + // Get pool details + synor_pool_details_t* pool = NULL; + err = synor_liquidity_get_pool(dex, "SYN-USDC", &pool); + if (err == SYNOR_OK) { + printf("\nSYN-USDC pool details:\n"); + printf(" Token0: %s (%s)\n", + synor_pool_details_get_token0_symbol(pool), + synor_pool_details_get_token0_reserve(pool)); + printf(" Token1: %s (%s)\n", + synor_pool_details_get_token1_symbol(pool), + synor_pool_details_get_token1_reserve(pool)); + printf(" Price: %s\n", synor_pool_details_get_price(pool)); + printf(" Total LP tokens: %s\n", synor_pool_details_get_total_lp_tokens(pool)); + synor_pool_details_free(pool); + } + + // Add liquidity + printf("\nAdding liquidity...\n"); + synor_add_liquidity_request_t add_req = { + .pool = "SYN-USDC", + .amount0 = "100", + .amount1 = "150", + .slippage_bps = 50 // 0.5% + }; + + synor_add_liquidity_result_t* add_result = NULL; + err = synor_liquidity_add(dex, &add_req, &add_result); + if (err == SYNOR_OK) { + printf("Liquidity added:\n"); + printf(" LP tokens received: %s\n", synor_add_result_get_lp_tokens(add_result)); + printf(" Position ID: %s\n", synor_add_result_get_position_id(add_result)); + printf(" Share of pool: %s%%\n", synor_add_result_get_share_of_pool(add_result)); + + // Claim fees + printf("\nClaiming fees...\n"); + synor_claim_fees_result_t* fees = NULL; + err = synor_liquidity_claim_fees(dex, synor_add_result_get_position_id(add_result), &fees); + if (err == SYNOR_OK) { + printf("Fees claimed:\n"); + printf(" Token0: %s\n", synor_claim_fees_get_amount0(fees)); + printf(" Token1: %s\n", synor_claim_fees_get_amount1(fees)); + synor_claim_fees_result_free(fees); + } + + // Remove liquidity + printf("\nRemoving liquidity...\n"); + synor_remove_liquidity_request_t remove_req = { + .position_id = synor_add_result_get_position_id(add_result), + .lp_tokens = synor_add_result_get_lp_tokens(add_result), + .slippage_bps = 50 + }; + + synor_remove_liquidity_result_t* remove_result = NULL; + err = synor_liquidity_remove(dex, &remove_req, &remove_result); + if (err == SYNOR_OK) { + printf("Liquidity removed:\n"); + printf(" Token0 received: %s\n", synor_remove_result_get_amount0(remove_result)); + printf(" Token1 received: %s\n", synor_remove_result_get_amount1(remove_result)); + synor_remove_liquidity_result_free(remove_result); + } + + synor_add_liquidity_result_free(add_result); + } + + printf("\n"); +} + +void orderbook_example(synor_dex_t* dex) { + printf("=== Order Book ===\n"); + + synor_error_t err; + + // Get order book snapshot + synor_orderbook_t* orderbook = NULL; + err = synor_orderbook_get_snapshot(dex, "SYN-USDC", 10, &orderbook); + if (err != SYNOR_OK) { + fprintf(stderr, "Failed to get orderbook\n"); + return; + } + + printf("Order book for SYN-USDC:\n"); + + printf("\nAsks (sells):\n"); + for (size_t i = 0; i < 5 && i < synor_orderbook_get_ask_count(orderbook); i++) { + synor_orderbook_entry_t* ask = synor_orderbook_get_ask(orderbook, i); + printf(" %s @ %s\n", + synor_orderbook_entry_get_quantity(ask), + synor_orderbook_entry_get_price(ask)); + } + + printf("\nBids (buys):\n"); + for (size_t i = 0; i < 5 && i < synor_orderbook_get_bid_count(orderbook); i++) { + synor_orderbook_entry_t* bid = synor_orderbook_get_bid(orderbook, i); + printf(" %s @ %s\n", + synor_orderbook_entry_get_quantity(bid), + synor_orderbook_entry_get_price(bid)); + } + + printf("\nSpread: %s (%s%%)\n", + synor_orderbook_get_spread(orderbook), + synor_orderbook_get_spread_percent(orderbook)); + printf("Mid price: %s\n", synor_orderbook_get_mid_price(orderbook)); + + synor_orderbook_free(orderbook); + + // Get recent trades + synor_trade_list_t* recent_trades = NULL; + err = synor_orderbook_get_recent_trades(dex, "SYN-USDC", 10, &recent_trades); + if (err == SYNOR_OK) { + printf("\nRecent trades:\n"); + for (size_t i = 0; i < 5 && i < synor_trade_list_count(recent_trades); i++) { + synor_trade_t* trade = synor_trade_list_get(recent_trades, i); + printf(" %s %s @ %s\n", + synor_trade_get_side(trade), + synor_trade_get_quantity(trade), + synor_trade_get_price(trade)); + } + synor_trade_list_free(recent_trades); + } + + printf("\n"); +} + +void portfolio_example(synor_dex_t* dex) { + printf("=== Portfolio ===\n"); + + synor_error_t err; + + // Get portfolio overview + synor_portfolio_t* portfolio = NULL; + err = synor_portfolio_get_overview(dex, &portfolio); + if (err == SYNOR_OK) { + printf("Portfolio overview:\n"); + printf(" Total value: $%s\n", synor_portfolio_get_total_value(portfolio)); + printf(" Available balance: $%s\n", synor_portfolio_get_available_balance(portfolio)); + printf(" In orders: $%s\n", synor_portfolio_get_in_orders(portfolio)); + printf(" In positions: $%s\n", synor_portfolio_get_in_positions(portfolio)); + printf(" Unrealized PnL: $%s\n", synor_portfolio_get_unrealized_pnl(portfolio)); + synor_portfolio_free(portfolio); + } + + // Get balances + synor_balance_list_t* balances = NULL; + err = synor_portfolio_get_balances(dex, &balances); + if (err == SYNOR_OK) { + printf("\nBalances:\n"); + for (size_t i = 0; i < synor_balance_list_count(balances); i++) { + synor_balance_t* balance = synor_balance_list_get(balances, i); + printf(" %s: %s (available: %s, in orders: %s)\n", + synor_balance_get_asset(balance), + synor_balance_get_total(balance), + synor_balance_get_available(balance), + synor_balance_get_in_orders(balance)); + } + synor_balance_list_free(balances); + } + + // Get trade statistics + synor_trade_stats_t* stats = NULL; + err = synor_portfolio_get_stats(dex, &stats); + if (err == SYNOR_OK) { + printf("\nTrade statistics:\n"); + printf(" Total trades: %d\n", synor_trade_stats_get_total_trades(stats)); + printf(" Win rate: %s%%\n", synor_trade_stats_get_win_rate(stats)); + printf(" Avg profit: $%s\n", synor_trade_stats_get_avg_profit(stats)); + printf(" Avg loss: $%s\n", synor_trade_stats_get_avg_loss(stats)); + printf(" Best trade: $%s\n", synor_trade_stats_get_best_trade(stats)); + printf(" Worst trade: $%s\n", synor_trade_stats_get_worst_trade(stats)); + synor_trade_stats_free(stats); + } + + printf("\n"); +} + +int main(int argc, char** argv) { + synor_error_t err; + + // Initialize client + synor_dex_config_t config = { + .api_key = getenv("SYNOR_API_KEY") ? getenv("SYNOR_API_KEY") : "your-api-key", + .endpoint = "https://dex.synor.io/v1", + .timeout_ms = 30000, + .retries = 3, + .debug = false, + .default_market = "SYN-USDC" + }; + + synor_dex_t* dex = NULL; + err = synor_dex_init(&config, &dex); + if (err != SYNOR_OK) { + fprintf(stderr, "Failed to initialize DEX client: %s\n", synor_error_string(err)); + return 1; + } + + // Check service health + bool healthy; + err = synor_dex_health_check(dex, &healthy); + printf("Service healthy: %s\n\n", healthy ? "true" : "false"); + + // Run examples + markets_example(dex); + spot_trading_example(dex); + perps_trading_example(dex); + liquidity_example(dex); + orderbook_example(dex); + portfolio_example(dex); + + // Cleanup + synor_dex_free(dex); + + return 0; +} diff --git a/sdk/c/examples/ibc_example.c b/sdk/c/examples/ibc_example.c new file mode 100644 index 0000000..a217b85 --- /dev/null +++ b/sdk/c/examples/ibc_example.c @@ -0,0 +1,545 @@ +/** + * Synor IBC SDK Examples for C + * + * Demonstrates Inter-Blockchain Communication operations: + * - Cross-chain transfers and messages + * - Channel lifecycle management + * - Packet handling and acknowledgments + * - Relayer operations + * - Connection monitoring + */ + +#include +#include +#include +#include +#include + +void chains_example(synor_ibc_t* ibc) { + printf("=== Chain Discovery ===\n"); + + synor_error_t err; + + // Get all connected chains + synor_chain_list_t* chains = NULL; + err = synor_chains_list(ibc, &chains); + if (err != SYNOR_OK) { + fprintf(stderr, "Failed to get chains\n"); + return; + } + + printf("Connected chains: %zu\n", synor_chain_list_count(chains)); + + for (size_t i = 0; i < 5 && i < synor_chain_list_count(chains); i++) { + synor_chain_t* chain = synor_chain_list_get(chains, i); + printf("\n %s:\n", synor_chain_get_id(chain)); + printf(" Name: %s\n", synor_chain_get_name(chain)); + printf(" Type: %s\n", synor_chain_get_type(chain)); + printf(" Status: %s\n", synor_chain_get_status(chain)); + printf(" Block height: %lu\n", synor_chain_get_latest_height(chain)); + printf(" Light client: %s\n", synor_chain_get_light_client(chain)); + } + synor_chain_list_free(chains); + + // Get specific chain info + synor_chain_t* synor_chain = NULL; + err = synor_chains_get(ibc, "synor-mainnet-1", &synor_chain); + if (err == SYNOR_OK) { + printf("\nSynor chain details:\n"); + printf(" Bech32 prefix: %s\n", synor_chain_get_bech32_prefix(synor_chain)); + printf(" Gas price: %s\n", synor_chain_get_gas_price(synor_chain)); + + char** features; + size_t feature_count; + synor_chain_get_features(synor_chain, &features, &feature_count); + printf(" Supported features: "); + for (size_t i = 0; i < feature_count; i++) { + printf("%s%s", features[i], i < feature_count - 1 ? ", " : ""); + } + printf("\n"); + synor_string_array_free(features, feature_count); + + synor_chain_free(synor_chain); + } + + // Get chain connections + synor_connection_list_t* connections = NULL; + err = synor_chains_get_connections(ibc, "synor-mainnet-1", &connections); + if (err == SYNOR_OK) { + printf("\nChain connections: %zu\n", synor_connection_list_count(connections)); + for (size_t i = 0; i < 3 && i < synor_connection_list_count(connections); i++) { + synor_connection_t* conn = synor_connection_list_get(connections, i); + printf(" %s -> %s\n", + synor_connection_get_id(conn), + synor_connection_get_counterparty_chain_id(conn)); + } + synor_connection_list_free(connections); + } + + printf("\n"); +} + +void channels_example(synor_ibc_t* ibc) { + printf("=== Channel Management ===\n"); + + synor_error_t err; + + // List existing channels + synor_channel_list_t* channels = NULL; + err = synor_channels_list(ibc, &channels); + if (err == SYNOR_OK) { + printf("Active channels: %zu\n", synor_channel_list_count(channels)); + + for (size_t i = 0; i < 3 && i < synor_channel_list_count(channels); i++) { + synor_channel_t* channel = synor_channel_list_get(channels, i); + printf("\n Channel %s:\n", synor_channel_get_id(channel)); + printf(" Port: %s\n", synor_channel_get_port_id(channel)); + printf(" State: %s\n", synor_channel_get_state(channel)); + printf(" Order: %s\n", synor_channel_get_ordering(channel)); + printf(" Counterparty: %s on %s\n", + synor_channel_get_counterparty_channel_id(channel), + synor_channel_get_counterparty_chain_id(channel)); + printf(" Version: %s\n", synor_channel_get_version(channel)); + } + synor_channel_list_free(channels); + } + + // Create a new channel (4-step handshake) + printf("\nInitiating channel creation...\n"); + + // Step 1: ChanOpenInit + synor_channel_init_request_t init_req = { + .port_id = "transfer", + .counterparty_chain_id = "cosmos-hub-4", + .counterparty_port_id = "transfer", + .version = "ics20-1", + .ordering = SYNOR_CHANNEL_ORDERING_UNORDERED + }; + + synor_channel_init_result_t* init_result = NULL; + err = synor_channels_open_init(ibc, &init_req, &init_result); + if (err != SYNOR_OK) { + fprintf(stderr, "Failed to init channel\n"); + return; + } + + printf("Channel init:\n"); + printf(" Channel ID: %s\n", synor_channel_init_result_get_id(init_result)); + printf(" State: %s\n", synor_channel_init_result_get_state(init_result)); + printf(" TX hash: %s\n", synor_channel_init_result_get_tx_hash(init_result)); + + // Step 2: Wait for ChanOpenTry (counterparty) + printf("\nWaiting for counterparty ChanOpenTry...\n"); + synor_channel_state_t try_state; + err = synor_channels_wait_for_state(ibc, synor_channel_init_result_get_id(init_result), + SYNOR_CHANNEL_STATE_TRYOPEN, 300, &try_state); + printf("Channel state: %d\n", try_state); + + // Step 3: ChanOpenAck + printf("\nSending ChanOpenAck...\n"); + synor_channel_ack_request_t ack_req = { + .channel_id = synor_channel_init_result_get_id(init_result), + .counterparty_channel_id = "channel-0", + .counterparty_version = "ics20-1" + }; + + synor_channel_ack_result_t* ack_result = NULL; + err = synor_channels_open_ack(ibc, &ack_req, &ack_result); + if (err == SYNOR_OK) { + printf("Ack TX: %s\n", synor_channel_ack_result_get_tx_hash(ack_result)); + synor_channel_ack_result_free(ack_result); + } + + // Step 4: Wait for ChanOpenConfirm (counterparty) + printf("\nWaiting for channel to open...\n"); + synor_channel_state_t open_state; + err = synor_channels_wait_for_state(ibc, synor_channel_init_result_get_id(init_result), + SYNOR_CHANNEL_STATE_OPEN, 300, &open_state); + printf("Channel is now: %d\n", open_state); + + // Get channel details + synor_channel_t* channel = NULL; + err = synor_channels_get(ibc, synor_channel_init_result_get_id(init_result), &channel); + if (err == SYNOR_OK) { + printf("\nChannel details:\n"); + printf(" Sequences - Send: %lu, Recv: %lu, Ack: %lu\n", + synor_channel_get_next_sequence_send(channel), + synor_channel_get_next_sequence_recv(channel), + synor_channel_get_next_sequence_ack(channel)); + synor_channel_free(channel); + } + + synor_channel_init_result_free(init_result); + printf("\n"); +} + +void transfer_example(synor_ibc_t* ibc) { + printf("=== Cross-Chain Transfers ===\n"); + + synor_error_t err; + + // Get supported tokens for transfer + synor_transferable_token_list_t* tokens = NULL; + err = synor_transfers_get_supported_tokens(ibc, "cosmos-hub-4", &tokens); + if (err == SYNOR_OK) { + printf("Transferable tokens to Cosmos Hub:\n"); + for (size_t i = 0; i < 5 && i < synor_transferable_token_list_count(tokens); i++) { + synor_transferable_token_t* token = synor_transferable_token_list_get(tokens, i); + printf(" %s (%s)\n", + synor_transferable_token_get_symbol(token), + synor_transferable_token_get_denom(token)); + } + synor_transferable_token_list_free(tokens); + } + + // Initiate a cross-chain transfer + printf("\nInitiating transfer...\n"); + synor_transfer_request_t transfer_req = { + .source_channel = "channel-0", + .denom = "usynor", + .amount = "1000000", + .receiver = "cosmos1...", + .timeout_height = 0, // Use timestamp instead + .timeout_timestamp = (uint64_t)(time(NULL) + 600) * 1000000000ULL, + .memo = "IBC transfer from Synor" + }; + + synor_transfer_result_t* transfer = NULL; + err = synor_transfers_send(ibc, &transfer_req, &transfer); + if (err != SYNOR_OK) { + fprintf(stderr, "Failed to send transfer\n"); + return; + } + + printf("Transfer initiated:\n"); + printf(" TX hash: %s\n", synor_transfer_result_get_tx_hash(transfer)); + printf(" Sequence: %lu\n", synor_transfer_result_get_sequence(transfer)); + printf(" Packet ID: %s\n", synor_transfer_result_get_packet_id(transfer)); + printf(" Status: %s\n", synor_transfer_result_get_status(transfer)); + + // Track transfer progress + printf("\nTracking transfer...\n"); + synor_transfer_status_t* status = NULL; + err = synor_transfers_track(ibc, synor_transfer_result_get_packet_id(transfer), &status); + if (err == SYNOR_OK) { + printf("Current status: %s\n", synor_transfer_status_get_state(status)); + printf("Source TX: %s\n", synor_transfer_status_get_source_tx_hash(status)); + const char* dest_tx = synor_transfer_status_get_dest_tx_hash(status); + if (dest_tx) { + printf("Dest TX: %s\n", dest_tx); + } + synor_transfer_status_free(status); + } + + // Wait for completion + printf("\nWaiting for transfer completion...\n"); + synor_transfer_status_t* final_status = NULL; + err = synor_transfers_wait_for_completion(ibc, synor_transfer_result_get_packet_id(transfer), + 600, &final_status); + if (err == SYNOR_OK) { + printf("Transfer completed:\n"); + printf(" Final status: %s\n", synor_transfer_status_get_state(final_status)); + printf(" Acknowledgment: %s\n", synor_transfer_status_get_acknowledgment(final_status)); + synor_transfer_status_free(final_status); + } + + // Get transfer history + synor_transfer_list_t* history = NULL; + err = synor_transfers_get_history(ibc, 10, &history); + if (err == SYNOR_OK) { + printf("\nRecent transfers: %zu\n", synor_transfer_list_count(history)); + for (size_t i = 0; i < 3 && i < synor_transfer_list_count(history); i++) { + synor_transfer_t* t = synor_transfer_list_get(history, i); + printf(" %s %s -> %s (%s)\n", + synor_transfer_get_amount(t), + synor_transfer_get_denom(t), + synor_transfer_get_dest_chain(t), + synor_transfer_get_status(t)); + } + synor_transfer_list_free(history); + } + + synor_transfer_result_free(transfer); + printf("\n"); +} + +void packet_example(synor_ibc_t* ibc) { + printf("=== Packet Operations ===\n"); + + synor_error_t err; + + // List pending packets + synor_packet_list_t* pending = NULL; + err = synor_packets_list_pending(ibc, "channel-0", &pending); + if (err == SYNOR_OK) { + printf("Pending packets on channel-0: %zu\n", synor_packet_list_count(pending)); + + for (size_t i = 0; i < 3 && i < synor_packet_list_count(pending); i++) { + synor_packet_t* packet = synor_packet_list_get(pending, i); + printf("\n Packet #%lu:\n", synor_packet_get_sequence(packet)); + printf(" Source: %s/%s\n", + synor_packet_get_source_port(packet), + synor_packet_get_source_channel(packet)); + printf(" Dest: %s/%s\n", + synor_packet_get_dest_port(packet), + synor_packet_get_dest_channel(packet)); + printf(" State: %s\n", synor_packet_get_state(packet)); + printf(" Timeout: %lu\n", synor_packet_get_timeout_timestamp(packet)); + } + synor_packet_list_free(pending); + } + + // Get specific packet + synor_packet_t* packet = NULL; + err = synor_packets_get(ibc, "channel-0", 1, &packet); + if (err == SYNOR_OK) { + printf("\nPacket details:\n"); + const char* data_hex = synor_packet_get_data_hex(packet); + printf(" Data (hex): %.40s...\n", data_hex); + printf(" Created: %s\n", synor_packet_get_created_at(packet)); + synor_packet_free(packet); + } + + // Get packet commitment proof + synor_packet_proof_t* proof = NULL; + err = synor_packets_get_commitment_proof(ibc, "channel-0", 1, &proof); + if (err == SYNOR_OK) { + printf("\nCommitment proof:\n"); + printf(" Height: %lu\n", synor_packet_proof_get_height(proof)); + printf(" Proof size: %zu bytes\n", synor_packet_proof_get_size(proof)); + synor_packet_proof_free(proof); + } + + // Get acknowledgment + synor_packet_ack_t* ack = NULL; + err = synor_packets_get_acknowledgment(ibc, "channel-0", 1, &ack); + if (err == SYNOR_OK) { + printf("\nAcknowledgment:\n"); + printf(" Result: %s\n", synor_packet_ack_is_success(ack) ? "Success" : + synor_packet_ack_get_error(ack)); + printf(" TX hash: %s\n", synor_packet_ack_get_tx_hash(ack)); + synor_packet_ack_free(ack); + } + + // List timed-out packets + synor_packet_list_t* timed_out = NULL; + err = synor_packets_list_timed_out(ibc, &timed_out); + if (err == SYNOR_OK) { + printf("\nTimed-out packets: %zu\n", synor_packet_list_count(timed_out)); + + // Timeout a packet manually + if (synor_packet_list_count(timed_out) > 0) { + synor_packet_t* to_timeout = synor_packet_list_get(timed_out, 0); + printf("\nProcessing timeout for packet #%lu\n", synor_packet_get_sequence(to_timeout)); + + synor_timeout_result_t* timeout = NULL; + err = synor_packets_timeout(ibc, synor_packet_get_source_channel(to_timeout), + synor_packet_get_sequence(to_timeout), &timeout); + if (err == SYNOR_OK) { + printf("Timeout TX: %s\n", synor_timeout_result_get_tx_hash(timeout)); + synor_timeout_result_free(timeout); + } + } + synor_packet_list_free(timed_out); + } + + printf("\n"); +} + +void relayer_example(synor_ibc_t* ibc) { + printf("=== Relayer Operations ===\n"); + + synor_error_t err; + + // Get relayer status + synor_relayer_status_t* status = NULL; + err = synor_relayer_get_status(ibc, &status); + if (err == SYNOR_OK) { + printf("Relayer status:\n"); + printf(" Running: %s\n", synor_relayer_status_is_running(status) ? "true" : "false"); + printf(" Uptime: %s\n", synor_relayer_status_get_uptime(status)); + printf(" Packets relayed: %lu\n", synor_relayer_status_get_packets_relayed(status)); + printf(" Errors: %lu\n", synor_relayer_status_get_error_count(status)); + synor_relayer_status_free(status); + } + + // List active paths + synor_relay_path_list_t* paths = NULL; + err = synor_relayer_list_paths(ibc, &paths); + if (err == SYNOR_OK) { + printf("\nActive relay paths: %zu\n", synor_relay_path_list_count(paths)); + + for (size_t i = 0; i < synor_relay_path_list_count(paths); i++) { + synor_relay_path_t* path = synor_relay_path_list_get(paths, i); + printf("\n %s:\n", synor_relay_path_get_id(path)); + printf(" %s <-> %s\n", + synor_relay_path_get_source_chain(path), + synor_relay_path_get_dest_chain(path)); + printf(" Channel: %s <-> %s\n", + synor_relay_path_get_source_channel(path), + synor_relay_path_get_dest_channel(path)); + printf(" Status: %s\n", synor_relay_path_get_status(path)); + printf(" Pending packets: %zu\n", synor_relay_path_get_pending_packets(path)); + } + synor_relay_path_list_free(paths); + } + + // Configure a new path + printf("\nConfiguring new relay path...\n"); + const char* filter_denoms[] = {"usynor", "uosmo"}; + synor_path_config_t path_config = { + .source_chain = "synor-mainnet-1", + .dest_chain = "osmosis-1", + .source_channel = "channel-1", + .dest_channel = "channel-100", + .filter_denoms = filter_denoms, + .filter_denoms_count = 2, + .min_relay_amount = "1000", + .max_relay_amount = "1000000000" + }; + + synor_relay_path_t* new_path = NULL; + err = synor_relayer_add_path(ibc, &path_config, &new_path); + if (err == SYNOR_OK) { + printf("Path created: %s\n", synor_relay_path_get_id(new_path)); + + // Start relaying on path + printf("\nStarting relayer on path...\n"); + err = synor_relayer_start_path(ibc, synor_relay_path_get_id(new_path)); + if (err == SYNOR_OK) { + printf("Relayer started\n"); + } + + // Manually relay pending packets + printf("\nRelaying pending packets...\n"); + synor_relay_result_t* relay_result = NULL; + err = synor_relayer_relay_pending(ibc, synor_relay_path_get_id(new_path), &relay_result); + if (err == SYNOR_OK) { + printf("Relayed %zu packets\n", synor_relay_result_get_packet_count(relay_result)); + printf("TX hashes: %zu\n", synor_relay_result_get_tx_hash_count(relay_result)); + synor_relay_result_free(relay_result); + } + + // Get relay history + synor_relay_event_list_t* history = NULL; + err = synor_relayer_get_history(ibc, synor_relay_path_get_id(new_path), 10, &history); + if (err == SYNOR_OK) { + printf("\nRelay history:\n"); + for (size_t i = 0; i < 3 && i < synor_relay_event_list_count(history); i++) { + synor_relay_event_t* event = synor_relay_event_list_get(history, i); + printf(" %s: %s - %zu packets\n", + synor_relay_event_get_timestamp(event), + synor_relay_event_get_type(event), + synor_relay_event_get_packet_count(event)); + } + synor_relay_event_list_free(history); + } + + synor_relay_path_free(new_path); + } + + printf("\n"); +} + +void monitoring_example(synor_ibc_t* ibc) { + printf("=== IBC Monitoring ===\n"); + + synor_error_t err; + + // Get IBC metrics + synor_ibc_metrics_t* metrics = NULL; + err = synor_monitoring_get_metrics(ibc, &metrics); + if (err == SYNOR_OK) { + printf("IBC metrics:\n"); + printf(" Total channels: %lu\n", synor_ibc_metrics_get_total_channels(metrics)); + printf(" Active channels: %lu\n", synor_ibc_metrics_get_active_channels(metrics)); + printf(" Total packets: %lu\n", synor_ibc_metrics_get_total_packets(metrics)); + printf(" Pending packets: %lu\n", synor_ibc_metrics_get_pending_packets(metrics)); + printf(" Failed packets: %lu\n", synor_ibc_metrics_get_failed_packets(metrics)); + printf(" Avg relay time: %lums\n", synor_ibc_metrics_get_avg_relay_time(metrics)); + synor_ibc_metrics_free(metrics); + } + + // Get chain health + synor_chain_health_list_t* chain_health = NULL; + err = synor_monitoring_get_chain_health(ibc, &chain_health); + if (err == SYNOR_OK) { + printf("\nChain health:\n"); + for (size_t i = 0; i < 3 && i < synor_chain_health_list_count(chain_health); i++) { + synor_chain_health_t* health = synor_chain_health_list_get(chain_health, i); + printf(" %s:\n", synor_chain_health_get_chain_id(health)); + printf(" Status: %s\n", synor_chain_health_get_status(health)); + printf(" Block lag: %lu\n", synor_chain_health_get_block_lag(health)); + printf(" Last update: %s\n", synor_chain_health_get_last_update(health)); + } + synor_chain_health_list_free(chain_health); + } + + // Get channel statistics + synor_channel_stats_t* stats = NULL; + err = synor_monitoring_get_channel_stats(ibc, "channel-0", &stats); + if (err == SYNOR_OK) { + printf("\nChannel-0 statistics:\n"); + printf(" Packets sent: %lu\n", synor_channel_stats_get_packets_sent(stats)); + printf(" Packets received: %lu\n", synor_channel_stats_get_packets_received(stats)); + printf(" Success rate: %s%%\n", synor_channel_stats_get_success_rate(stats)); + printf(" Avg confirmation time: %lums\n", synor_channel_stats_get_avg_confirmation_time(stats)); + synor_channel_stats_free(stats); + } + + // Get alerts + synor_ibc_alert_list_t* alerts = NULL; + err = synor_monitoring_get_alerts(ibc, &alerts); + if (err == SYNOR_OK) { + printf("\nActive alerts: %zu\n", synor_ibc_alert_list_count(alerts)); + for (size_t i = 0; i < synor_ibc_alert_list_count(alerts); i++) { + synor_ibc_alert_t* alert = synor_ibc_alert_list_get(alerts, i); + printf(" [%s] %s\n", + synor_ibc_alert_get_severity(alert), + synor_ibc_alert_get_message(alert)); + } + synor_ibc_alert_list_free(alerts); + } + + printf("\n"); +} + +int main(int argc, char** argv) { + synor_error_t err; + + // Initialize client + synor_ibc_config_t config = { + .api_key = getenv("SYNOR_API_KEY") ? getenv("SYNOR_API_KEY") : "your-api-key", + .endpoint = "https://ibc.synor.io/v1", + .timeout_ms = 30000, + .retries = 3, + .debug = false, + .default_chain = "synor-mainnet-1", + .confirmations = 1 + }; + + synor_ibc_t* ibc = NULL; + err = synor_ibc_init(&config, &ibc); + if (err != SYNOR_OK) { + fprintf(stderr, "Failed to initialize IBC client: %s\n", synor_error_string(err)); + return 1; + } + + // Check service health + bool healthy; + err = synor_ibc_health_check(ibc, &healthy); + printf("Service healthy: %s\n\n", healthy ? "true" : "false"); + + // Run examples + chains_example(ibc); + channels_example(ibc); + transfer_example(ibc); + packet_example(ibc); + relayer_example(ibc); + monitoring_example(ibc); + + // Cleanup + synor_ibc_free(ibc); + + return 0; +} diff --git a/sdk/c/examples/zk_example.c b/sdk/c/examples/zk_example.c new file mode 100644 index 0000000..8f441be --- /dev/null +++ b/sdk/c/examples/zk_example.c @@ -0,0 +1,495 @@ +/** + * Synor ZK SDK Examples for C + * + * Demonstrates zero-knowledge proof operations: + * - Circuit compilation (Circom) + * - Proof generation and verification + * - Multiple proving systems (Groth16, PLONK, STARK) + * - Recursive proof composition + * - Trusted setup ceremonies + */ + +#include +#include +#include +#include + +void circuit_example(synor_zk_t* zk) { + printf("=== Circuit Compilation ===\n"); + + synor_error_t err; + + // Simple Circom circuit: prove knowledge of factors + const char* circom_code = + "pragma circom 2.1.0;\n" + "\n" + "template Multiplier() {\n" + " signal input a;\n" + " signal input b;\n" + " signal output c;\n" + "\n" + " c <== a * b;\n" + "}\n" + "\n" + "component main = Multiplier();\n"; + + // Compile the circuit + printf("Compiling circuit...\n"); + synor_circuit_source_t source = { + .code = circom_code, + .language = SYNOR_CIRCUIT_LANGUAGE_CIRCOM + }; + + synor_circuit_t* circuit = NULL; + err = synor_circuits_compile(zk, &source, &circuit); + if (err != SYNOR_OK) { + fprintf(stderr, "Failed to compile circuit\n"); + return; + } + + printf("Circuit compiled:\n"); + printf(" Circuit ID: %s\n", synor_circuit_get_id(circuit)); + printf(" Constraints: %zu\n", synor_circuit_get_constraints(circuit)); + printf(" Public inputs: %zu\n", synor_circuit_get_public_inputs(circuit)); + printf(" Private inputs: %zu\n", synor_circuit_get_private_inputs(circuit)); + printf(" Outputs: %zu\n", synor_circuit_get_outputs(circuit)); + + // Get circuit info + synor_circuit_info_t* info = NULL; + err = synor_circuits_get(zk, synor_circuit_get_id(circuit), &info); + if (err == SYNOR_OK) { + printf("\nCircuit info:\n"); + printf(" Name: %s\n", synor_circuit_info_get_name(info)); + printf(" Version: %s\n", synor_circuit_info_get_version(info)); + printf(" Wires: %zu\n", synor_circuit_info_get_wire_count(info)); + printf(" Labels: %zu\n", synor_circuit_info_get_label_count(info)); + synor_circuit_info_free(info); + } + + // List available circuits + synor_circuit_list_t* circuits = NULL; + err = synor_circuits_list(zk, &circuits); + if (err == SYNOR_OK) { + printf("\nAvailable circuits: %zu\n", synor_circuit_list_count(circuits)); + for (size_t i = 0; i < 3 && i < synor_circuit_list_count(circuits); i++) { + synor_circuit_t* c = synor_circuit_list_get(circuits, i); + printf(" %s: %s (%zu constraints)\n", + synor_circuit_get_id(c), + synor_circuit_get_name(c), + synor_circuit_get_constraints(c)); + } + synor_circuit_list_free(circuits); + } + + synor_circuit_free(circuit); + printf("\n"); +} + +void groth16_example(synor_zk_t* zk) { + printf("=== Groth16 Proving System ===\n"); + + synor_error_t err; + const char* circuit_id = "multiplier-v1"; + + // Generate proving/verification keys (trusted setup) + printf("Generating keys...\n"); + synor_groth16_keys_t* keys = NULL; + err = synor_groth16_setup(zk, circuit_id, &keys); + if (err != SYNOR_OK) { + fprintf(stderr, "Failed to generate keys\n"); + return; + } + + printf("Keys generated:\n"); + printf(" Proving key size: %zu bytes\n", synor_groth16_keys_get_pk_size(keys)); + printf(" Verification key size: %zu bytes\n", synor_groth16_keys_get_vk_size(keys)); + + // Prepare witness (private inputs) + synor_witness_t* witness = synor_witness_create(); + synor_witness_set(witness, "a", "3"); + synor_witness_set(witness, "b", "7"); + + // Generate proof + printf("\nGenerating proof...\n"); + synor_prove_request_t prove_req = { + .circuit_id = circuit_id, + .witness = witness, + .proving_key = synor_groth16_keys_get_pk(keys), + .proving_key_len = synor_groth16_keys_get_pk_size(keys) + }; + + synor_proof_t* proof = NULL; + err = synor_groth16_prove(zk, &prove_req, &proof); + if (err != SYNOR_OK) { + fprintf(stderr, "Failed to generate proof\n"); + synor_witness_free(witness); + synor_groth16_keys_free(keys); + return; + } + + printf("Proof generated:\n"); + printf(" Proof size: %zu bytes\n", synor_proof_get_size(proof)); + printf(" Public signals: %zu\n", synor_proof_get_public_signal_count(proof)); + printf(" Proving time: %lums\n", synor_proof_get_proving_time_ms(proof)); + + // Verify proof + printf("\nVerifying proof...\n"); + synor_verify_request_t verify_req = { + .proof = synor_proof_get_bytes(proof), + .proof_len = synor_proof_get_size(proof), + .public_signals = synor_proof_get_public_signals(proof), + .public_signal_count = synor_proof_get_public_signal_count(proof), + .verification_key = synor_groth16_keys_get_vk(keys), + .verification_key_len = synor_groth16_keys_get_vk_size(keys) + }; + + bool verified; + err = synor_groth16_verify(zk, &verify_req, &verified); + printf("Verification result: %s\n", verified ? "true" : "false"); + + // Export proof for on-chain verification + char* solidity_calldata = NULL; + err = synor_groth16_export_calldata(zk, proof, &solidity_calldata); + if (err == SYNOR_OK && solidity_calldata) { + printf("\nSolidity calldata: %.100s...\n", solidity_calldata); + free(solidity_calldata); + } + + synor_proof_free(proof); + synor_witness_free(witness); + synor_groth16_keys_free(keys); + printf("\n"); +} + +void plonk_example(synor_zk_t* zk) { + printf("=== PLONK Proving System ===\n"); + + synor_error_t err; + const char* circuit_id = "multiplier-v1"; + + // PLONK uses universal trusted setup + printf("Getting universal setup...\n"); + synor_srs_t* srs = NULL; + err = synor_plonk_get_universal_setup(zk, 14, &srs); // 2^14 constraints + if (err != SYNOR_OK) { + fprintf(stderr, "Failed to get SRS\n"); + return; + } + printf("SRS loaded: %zu bytes\n", synor_srs_get_size(srs)); + + // Generate circuit-specific keys + printf("\nGenerating circuit keys...\n"); + synor_plonk_keys_t* keys = NULL; + err = synor_plonk_setup(zk, circuit_id, srs, &keys); + if (err != SYNOR_OK) { + fprintf(stderr, "Failed to generate keys\n"); + synor_srs_free(srs); + return; + } + printf("Keys generated\n"); + + // Generate proof + synor_witness_t* witness = synor_witness_create(); + synor_witness_set(witness, "a", "5"); + synor_witness_set(witness, "b", "9"); + + printf("\nGenerating PLONK proof...\n"); + synor_plonk_prove_request_t prove_req = { + .circuit_id = circuit_id, + .witness = witness, + .proving_key = synor_plonk_keys_get_pk(keys), + .proving_key_len = synor_plonk_keys_get_pk_size(keys) + }; + + synor_proof_t* proof = NULL; + err = synor_plonk_prove(zk, &prove_req, &proof); + if (err == SYNOR_OK) { + printf("Proof generated:\n"); + printf(" Proof size: %zu bytes\n", synor_proof_get_size(proof)); + printf(" Proving time: %lums\n", synor_proof_get_proving_time_ms(proof)); + + // Verify proof + synor_plonk_verify_request_t verify_req = { + .proof = synor_proof_get_bytes(proof), + .proof_len = synor_proof_get_size(proof), + .public_signals = synor_proof_get_public_signals(proof), + .public_signal_count = synor_proof_get_public_signal_count(proof), + .verification_key = synor_plonk_keys_get_vk(keys), + .verification_key_len = synor_plonk_keys_get_vk_size(keys) + }; + + bool verified; + synor_plonk_verify(zk, &verify_req, &verified); + printf("Verification result: %s\n", verified ? "true" : "false"); + + synor_proof_free(proof); + } + + // Compare with Groth16 + printf("\nPLONK advantages:\n"); + printf(" - Universal trusted setup\n"); + printf(" - Larger proofs (~2.5 KB vs ~200 bytes)\n"); + printf(" - Faster proving for some circuits\n"); + + synor_witness_free(witness); + synor_plonk_keys_free(keys); + synor_srs_free(srs); + printf("\n"); +} + +void stark_example(synor_zk_t* zk) { + printf("=== STARK Proving System ===\n"); + + synor_error_t err; + const char* circuit_id = "multiplier-v1"; + + // STARKs don't need trusted setup + printf("Configuring STARK parameters...\n"); + synor_stark_config_t config = { + .field_size = 256, + .hash_function = SYNOR_HASH_FUNCTION_POSEIDON, + .blowup_factor = 8, + .num_queries = 30, + .folding_factor = 8 + }; + + // Generate proof + synor_witness_t* witness = synor_witness_create(); + synor_witness_set(witness, "a", "11"); + synor_witness_set(witness, "b", "13"); + + printf("\nGenerating STARK proof...\n"); + synor_stark_prove_request_t prove_req = { + .circuit_id = circuit_id, + .witness = witness, + .config = &config + }; + + synor_stark_proof_t* proof = NULL; + err = synor_stark_prove(zk, &prove_req, &proof); + if (err == SYNOR_OK) { + printf("Proof generated:\n"); + printf(" Proof size: %zu bytes\n", synor_stark_proof_get_size(proof)); + printf(" Proving time: %lums\n", synor_stark_proof_get_proving_time_ms(proof)); + printf(" FRI layers: %zu\n", synor_stark_proof_get_fri_layers(proof)); + + // Verify proof + printf("\nVerifying STARK proof...\n"); + synor_stark_verify_request_t verify_req = { + .proof = synor_stark_proof_get_bytes(proof), + .proof_len = synor_stark_proof_get_size(proof), + .public_signals = synor_stark_proof_get_public_signals(proof), + .public_signal_count = synor_stark_proof_get_public_signal_count(proof), + .config = &config + }; + + bool verified; + synor_stark_verify(zk, &verify_req, &verified); + printf("Verification result: %s\n", verified ? "true" : "false"); + + synor_stark_proof_free(proof); + } + + // Compare with SNARKs + printf("\nSTARK advantages:\n"); + printf(" - No trusted setup needed\n"); + printf(" - Post-quantum secure\n"); + printf(" - Larger proofs (~100 KB)\n"); + printf(" - Faster proving for complex computations\n"); + + synor_witness_free(witness); + printf("\n"); +} + +void recursive_example(synor_zk_t* zk) { + printf("=== Recursive Proof Composition ===\n"); + + synor_error_t err; + + // Create inner proofs + printf("Generating inner proofs...\n"); + synor_recursive_proof_list_t* inner_proofs = synor_recursive_proof_list_create(); + + for (int i = 1; i <= 3; i++) { + synor_witness_t* witness = synor_witness_create(); + char a_str[16], b_str[16]; + snprintf(a_str, sizeof(a_str), "%d", i); + snprintf(b_str, sizeof(b_str), "%d", i + 1); + synor_witness_set(witness, "a", a_str); + synor_witness_set(witness, "b", b_str); + + synor_recursive_prove_request_t prove_req = { + .circuit_id = "multiplier-v1", + .witness = witness, + .level = 0 + }; + + synor_recursive_proof_t* proof = NULL; + err = synor_recursive_prove_inner(zk, &prove_req, &proof); + if (err == SYNOR_OK) { + synor_recursive_proof_list_add(inner_proofs, proof); + printf(" Inner proof %d generated\n", i); + } + + synor_witness_free(witness); + } + + // Aggregate proofs recursively + printf("\nAggregating proofs...\n"); + synor_aggregate_request_t aggregate_req = { + .proofs = inner_proofs, + .aggregation_circuit = "recursive-aggregator-v1" + }; + + synor_aggregated_proof_t* aggregated = NULL; + err = synor_recursive_aggregate(zk, &aggregate_req, &aggregated); + if (err == SYNOR_OK) { + printf("Aggregated proof:\n"); + printf(" Proof size: %zu bytes\n", synor_aggregated_proof_get_size(aggregated)); + printf(" Proofs aggregated: %zu\n", synor_aggregated_proof_get_count(aggregated)); + printf(" Recursion depth: %zu\n", synor_aggregated_proof_get_depth(aggregated)); + + // Verify aggregated proof + printf("\nVerifying aggregated proof...\n"); + bool verified; + err = synor_recursive_verify_aggregated(zk, aggregated, &verified); + printf("Verification result: %s\n", verified ? "true" : "false"); + + synor_aggregated_proof_free(aggregated); + } + + // Use cases + printf("\nRecursive proof use cases:\n"); + printf(" - Rollup batch verification\n"); + printf(" - Incremental computation proofs\n"); + printf(" - Cross-chain state proofs\n"); + + synor_recursive_proof_list_free(inner_proofs); + printf("\n"); +} + +void ceremony_example(synor_zk_t* zk) { + printf("=== Trusted Setup Ceremony ===\n"); + + synor_error_t err; + + // List active ceremonies + synor_ceremony_list_t* ceremonies = NULL; + err = synor_ceremony_list(zk, SYNOR_CEREMONY_STATUS_ACTIVE, &ceremonies); + if (err == SYNOR_OK) { + printf("Active ceremonies: %zu\n", synor_ceremony_list_count(ceremonies)); + for (size_t i = 0; i < 3 && i < synor_ceremony_list_count(ceremonies); i++) { + synor_ceremony_t* ceremony = synor_ceremony_list_get(ceremonies, i); + printf("\n %s:\n", synor_ceremony_get_id(ceremony)); + printf(" Circuit: %s\n", synor_ceremony_get_circuit_id(ceremony)); + printf(" Participants: %zu\n", synor_ceremony_get_participant_count(ceremony)); + printf(" Current round: %zu\n", synor_ceremony_get_current_round(ceremony)); + printf(" Status: %s\n", synor_ceremony_get_status(ceremony)); + } + synor_ceremony_list_free(ceremonies); + } + + // Create a new ceremony + printf("\nCreating new ceremony...\n"); + synor_ceremony_config_t config = { + .circuit_id = "new-circuit-v1", + .min_participants = 10, + .max_participants = 100, + .round_duration = 3600, // 1 hour per round + .verify_contributions = true + }; + + synor_ceremony_t* new_ceremony = NULL; + err = synor_ceremony_create(zk, &config, &new_ceremony); + if (err == SYNOR_OK) { + printf("Ceremony created:\n"); + printf(" Ceremony ID: %s\n", synor_ceremony_get_id(new_ceremony)); + printf(" Join URL: %s\n", synor_ceremony_get_join_url(new_ceremony)); + + // Participate in ceremony + printf("\nParticipating in ceremony...\n"); + uint8_t entropy[32]; + // In real code, use secure random: arc4random_buf(entropy, sizeof(entropy)); + memset(entropy, 0x42, sizeof(entropy)); // Example only + + synor_contribution_request_t contrib_req = { + .ceremony_id = synor_ceremony_get_id(new_ceremony), + .entropy = entropy, + .entropy_len = sizeof(entropy) + }; + + synor_contribution_t* contribution = NULL; + err = synor_ceremony_contribute(zk, &contrib_req, &contribution); + if (err == SYNOR_OK) { + printf("Contribution made:\n"); + printf(" Contribution ID: %s\n", synor_contribution_get_id(contribution)); + printf(" Position: %zu\n", synor_contribution_get_position(contribution)); + printf(" Hash: %s\n", synor_contribution_get_hash(contribution)); + + // Verify contribution + printf("\nVerifying contribution...\n"); + bool valid; + synor_ceremony_verify_contribution(zk, synor_contribution_get_id(contribution), &valid); + printf("Contribution valid: %s\n", valid ? "true" : "false"); + + synor_contribution_free(contribution); + } + + // Get ceremony transcript + synor_transcript_t* transcript = NULL; + err = synor_ceremony_get_transcript(zk, synor_ceremony_get_id(new_ceremony), &transcript); + if (err == SYNOR_OK) { + printf("\nCeremony transcript:\n"); + printf(" Total contributions: %zu\n", synor_transcript_get_contribution_count(transcript)); + printf(" Start time: %s\n", synor_transcript_get_start_time(transcript)); + const char* final_hash = synor_transcript_get_final_hash(transcript); + printf(" Final hash: %s\n", final_hash ? final_hash : "pending"); + synor_transcript_free(transcript); + } + + synor_ceremony_free(new_ceremony); + } + + printf("\n"); +} + +int main(int argc, char** argv) { + synor_error_t err; + + // Initialize client + synor_zk_config_t config = { + .api_key = getenv("SYNOR_API_KEY") ? getenv("SYNOR_API_KEY") : "your-api-key", + .endpoint = "https://zk.synor.io/v1", + .timeout_ms = 120000, // ZK operations can be slow + .retries = 3, + .debug = false, + .default_proving_system = SYNOR_PROVING_SYSTEM_GROTH16, + .prove_timeout_ms = 300000, + .verify_timeout_ms = 30000 + }; + + synor_zk_t* zk = NULL; + err = synor_zk_init(&config, &zk); + if (err != SYNOR_OK) { + fprintf(stderr, "Failed to initialize ZK client: %s\n", synor_error_string(err)); + return 1; + } + + // Check service health + bool healthy; + err = synor_zk_health_check(zk, &healthy); + printf("Service healthy: %s\n\n", healthy ? "true" : "false"); + + // Run examples + circuit_example(zk); + groth16_example(zk); + plonk_example(zk); + stark_example(zk); + recursive_example(zk); + ceremony_example(zk); + + // Cleanup + synor_zk_free(zk); + + return 0; +} diff --git a/sdk/cpp/examples/compiler_example.cpp b/sdk/cpp/examples/compiler_example.cpp new file mode 100644 index 0000000..20895b8 --- /dev/null +++ b/sdk/cpp/examples/compiler_example.cpp @@ -0,0 +1,377 @@ +/** + * Synor Compiler SDK Examples for C++ + * + * Demonstrates smart contract compilation and analysis: + * - WASM contract compilation and optimization + * - ABI extraction and encoding + * - Contract analysis and security scanning + * - Validation and verification + */ + +#include +#include +#include +#include + +using namespace synor::compiler; + +// Helper function to create a minimal valid WASM module for testing +std::vector create_minimal_wasm() { + return { + 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 + }; +} + +void compile_contract_example(SynorCompiler& compiler) { + std::cout << "=== Contract Compilation ===" << std::endl; + + auto wasm = create_minimal_wasm(); + + auto result = compiler.compile(wasm, { + .optimization_level = OptimizationLevel::Size, + .use_wasm_opt = true, + .validate = true, + .extract_metadata = true, + .generate_abi = true, + .strip_options = { + .strip_debug = true, + .strip_producers = true, + .strip_names = true, + .strip_custom = true, + .strip_unused = true, + .preserve_sections = {} + } + }); + + std::cout << "Compilation result:" << std::endl; + std::cout << " Contract ID: " << result.contract_id() << std::endl; + std::cout << " Code hash: " << result.code_hash() << std::endl; + std::cout << " Original size: " << result.original_size() << " bytes" << std::endl; + std::cout << " Optimized size: " << result.optimized_size() << " bytes" << std::endl; + std::cout << " Size reduction: " << std::fixed << std::setprecision(1) << result.size_reduction() << "%" << std::endl; + std::cout << " Estimated deploy gas: " << result.estimated_deploy_gas() << std::endl; + + if (result.metadata()) { + std::cout << "\nMetadata:" << std::endl; + std::cout << " Name: " << result.metadata()->name() << std::endl; + std::cout << " Version: " << result.metadata()->version() << std::endl; + std::cout << " SDK Version: " << result.metadata()->sdk_version() << std::endl; + } + + if (result.abi()) { + std::cout << "\nABI:" << std::endl; + std::cout << " Functions: " << result.abi()->functions().size() << std::endl; + std::cout << " Events: " << result.abi()->events().size() << std::endl; + std::cout << " Errors: " << result.abi()->errors().size() << std::endl; + } + + std::cout << std::endl; +} + +void compilation_modes_example(SynorCompiler& compiler) { + std::cout << "=== Compilation Modes ===" << std::endl; + + auto wasm = create_minimal_wasm(); + + // Development mode: fast compilation, debugging support + std::cout << "Development mode:" << std::endl; + auto dev_result = compiler.contracts().compile_dev(wasm); + std::cout << " Size: " << dev_result.optimized_size() << " bytes" << std::endl; + std::cout << " Optimization: none" << std::endl; + + // Production mode: maximum optimization + std::cout << "\nProduction mode:" << std::endl; + auto prod_result = compiler.contracts().compile_production(wasm); + std::cout << " Size: " << prod_result.optimized_size() << " bytes" << std::endl; + std::cout << " Optimization: aggressive" << std::endl; + std::cout << " Size savings: " << (dev_result.optimized_size() - prod_result.optimized_size()) << " bytes" << std::endl; + + // Custom optimization levels + std::cout << "\nOptimization levels:" << std::endl; + std::vector> levels = { + {OptimizationLevel::None, "NONE"}, + {OptimizationLevel::Basic, "BASIC"}, + {OptimizationLevel::Size, "SIZE"}, + {OptimizationLevel::Aggressive, "AGGRESSIVE"} + }; + + for (const auto& [level, name] : levels) { + auto result = compiler.compile(wasm, {.optimization_level = level}); + std::cout << " " << name << ": " << result.optimized_size() << " bytes" << std::endl; + } + + std::cout << std::endl; +} + +void abi_example(SynorCompiler& compiler) { + std::cout << "=== ABI Operations ===" << std::endl; + + auto wasm = create_minimal_wasm(); + + // Extract ABI from WASM + auto abi = compiler.abi().extract(wasm); + std::cout << "Contract: " << abi.name() << std::endl; + std::cout << "Version: " << abi.version() << std::endl; + + // List functions + if (!abi.functions().empty()) { + std::cout << "\nFunctions:" << std::endl; + for (const auto& func : abi.functions()) { + std::string inputs; + for (size_t i = 0; i < func.inputs().size(); ++i) { + const auto& param = func.inputs()[i]; + if (i > 0) inputs += ", "; + inputs += param.name() + ": " + param.type().type_name(); + } + + std::string outputs; + if (func.outputs().empty()) { + outputs = "void"; + } else { + for (size_t i = 0; i < func.outputs().size(); ++i) { + if (i > 0) outputs += ", "; + outputs += func.outputs()[i].type().type_name(); + } + } + + std::string modifiers; + if (func.view()) modifiers += "view "; + if (func.payable()) modifiers += "payable"; + + std::cout << " " << func.name() << "(" << inputs << ") -> " << outputs << " " << modifiers << std::endl; + std::cout << " Selector: " << func.selector() << std::endl; + } + } + + // List events + if (!abi.events().empty()) { + std::cout << "\nEvents:" << std::endl; + for (const auto& event : abi.events()) { + std::string params; + for (size_t i = 0; i < event.params().size(); ++i) { + const auto& param = event.params()[i]; + if (i > 0) params += ", "; + if (param.indexed()) params += "indexed "; + params += param.name() + ": " + param.type().type_name(); + } + std::cout << " " << event.name() << "(" << params << ")" << std::endl; + std::cout << " Topic: " << event.topic() << std::endl; + } + } + + // Encode a function call + if (!abi.functions().empty()) { + const auto& func = abi.functions().front(); + auto encoded = compiler.abi().encode_call(func, {"arg1", "arg2"}); + std::cout << "\nEncoded call to " << func.name() << ": " << encoded << std::endl; + + // Decode a result + auto decoded = compiler.abi().decode_result(func, encoded); + std::cout << "Decoded result: " << decoded << std::endl; + } + + std::cout << std::endl; +} + +void analysis_example(SynorCompiler& compiler) { + std::cout << "=== Contract Analysis ===" << std::endl; + + auto wasm = create_minimal_wasm(); + + // Full analysis + auto analysis = compiler.analysis().analyze(wasm); + + // Size breakdown + if (analysis.size_breakdown()) { + const auto& size = *analysis.size_breakdown(); + std::cout << "Size breakdown:" << std::endl; + std::cout << " Code: " << size.code() << " bytes" << std::endl; + std::cout << " Data: " << size.data() << " bytes" << std::endl; + std::cout << " Functions: " << size.functions() << " bytes" << std::endl; + std::cout << " Memory: " << size.memory() << " bytes" << std::endl; + std::cout << " Exports: " << size.exports() << " bytes" << std::endl; + std::cout << " Imports: " << size.imports() << " bytes" << std::endl; + std::cout << " Total: " << size.total() << " bytes" << std::endl; + } + + // Function analysis + if (!analysis.functions().empty()) { + std::cout << "\nFunction analysis:" << std::endl; + for (size_t i = 0; i < std::min(analysis.functions().size(), size_t(5)); ++i) { + const auto& func = analysis.functions()[i]; + std::cout << " " << func.name() << ":" << std::endl; + std::cout << " Size: " << func.size() << " bytes" << std::endl; + std::cout << " Instructions: " << func.instruction_count() << std::endl; + std::cout << " Locals: " << func.local_count() << std::endl; + std::cout << " Exported: " << (func.exported() ? "true" : "false") << std::endl; + std::cout << " Estimated gas: " << func.estimated_gas() << std::endl; + } + } + + // Import analysis + if (!analysis.imports().empty()) { + std::cout << "\nImports:" << std::endl; + for (const auto& imp : analysis.imports()) { + std::cout << " " << imp.module() << "." << imp.name() << " (" << imp.kind() << ")" << std::endl; + } + } + + // Gas analysis + if (analysis.gas_analysis()) { + const auto& gas = *analysis.gas_analysis(); + std::cout << "\nGas analysis:" << std::endl; + std::cout << " Deployment: " << gas.deployment_gas() << std::endl; + std::cout << " Memory init: " << gas.memory_init_gas() << std::endl; + std::cout << " Data section: " << gas.data_section_gas() << std::endl; + } + + // Extract metadata + auto metadata = compiler.analysis().extract_metadata(wasm); + std::cout << "\nContract metadata:" << std::endl; + std::cout << " Name: " << metadata.name() << std::endl; + std::cout << " Version: " << metadata.version() << std::endl; + std::cout << " Build timestamp: " << metadata.build_timestamp() << std::endl; + + // Estimate deployment gas + auto gas_estimate = compiler.analysis().estimate_deploy_gas(wasm); + std::cout << "\nEstimated deployment gas: " << gas_estimate << std::endl; + + std::cout << std::endl; +} + +void validation_example(SynorCompiler& compiler) { + std::cout << "=== Contract Validation ===" << std::endl; + + auto wasm = create_minimal_wasm(); + + // Full validation + auto result = compiler.validation().validate(wasm); + std::cout << "Valid: " << (result.valid() ? "true" : "false") << std::endl; + std::cout << "Exports: " << result.export_count() << std::endl; + std::cout << "Imports: " << result.import_count() << std::endl; + std::cout << "Functions: " << result.function_count() << std::endl; + std::cout << "Memory pages: " << result.memory_pages() << std::endl; + + if (!result.errors().empty()) { + std::cout << "\nValidation errors:" << std::endl; + for (const auto& error : result.errors()) { + std::cout << " [" << error.code() << "] " << error.message() << std::endl; + if (!error.location().empty()) { + std::cout << " at " << error.location() << std::endl; + } + } + } + + if (!result.warnings().empty()) { + std::cout << "\nWarnings:" << std::endl; + for (const auto& warning : result.warnings()) { + std::cout << " " << warning << std::endl; + } + } + + // Quick validation + bool is_valid = compiler.validation().is_valid(wasm); + std::cout << "\nQuick validation: " << (is_valid ? "true" : "false") << std::endl; + + // Get validation errors only + auto errors = compiler.validation().get_errors(wasm); + std::cout << "Error count: " << errors.size() << std::endl; + + // Validate required exports + bool has_required = compiler.validation().validate_exports(wasm, {"init", "execute", "query"}); + std::cout << "Has required exports: " << (has_required ? "true" : "false") << std::endl; + + // Validate memory constraints + bool memory_valid = compiler.validation().validate_memory(wasm, 16); + std::cout << "Memory within 16 pages: " << (memory_valid ? "true" : "false") << std::endl; + + std::cout << std::endl; +} + +void security_example(SynorCompiler& compiler) { + std::cout << "=== Security Scanning ===" << std::endl; + + auto wasm = create_minimal_wasm(); + + auto security = compiler.analysis().security_scan(wasm); + + std::cout << "Security score: " << security.score() << "/100" << std::endl; + + if (!security.issues().empty()) { + std::cout << "\nSecurity issues:" << std::endl; + for (const auto& issue : security.issues()) { + std::string icon; + std::string severity = issue.severity(); + if (severity == "critical") icon = "[CRIT]"; + else if (severity == "high") icon = "[HIGH]"; + else if (severity == "medium") icon = "[MED]"; + else if (severity == "low") icon = "[LOW]"; + else icon = "[???]"; + + std::cout << icon << " [" << issue.severity() << "] " << issue.type() << std::endl; + std::cout << " " << issue.description() << std::endl; + if (!issue.location().empty()) { + std::cout << " at " << issue.location() << std::endl; + } + } + } else { + std::cout << "No security issues found!" << std::endl; + } + + if (!security.recommendations().empty()) { + std::cout << "\nRecommendations:" << std::endl; + for (const auto& rec : security.recommendations()) { + std::cout << " • " << rec << std::endl; + } + } + + std::cout << std::endl; +} + +int main(int argc, char** argv) { + // Initialize client + const char* api_key = std::getenv("SYNOR_API_KEY"); + CompilerConfig config{ + .api_key = api_key ? api_key : "your-api-key", + .endpoint = "https://compiler.synor.io/v1", + .timeout = std::chrono::seconds(60), + .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 + }; + + SynorCompiler compiler(config); + + try { + // Check service health + bool healthy = compiler.health_check(); + std::cout << "Service healthy: " << (healthy ? "true" : "false") << std::endl << std::endl; + + // Run examples + compile_contract_example(compiler); + compilation_modes_example(compiler); + abi_example(compiler); + analysis_example(compiler); + validation_example(compiler); + security_example(compiler); + } catch (const std::exception& e) { + std::cerr << "Error: " << e.what() << std::endl; + return 1; + } + + return 0; +} diff --git a/sdk/cpp/examples/crypto_example.cpp b/sdk/cpp/examples/crypto_example.cpp new file mode 100644 index 0000000..443b7e5 --- /dev/null +++ b/sdk/cpp/examples/crypto_example.cpp @@ -0,0 +1,273 @@ +/** + * Synor Crypto SDK Examples for C++ + * + * Demonstrates quantum-resistant cryptographic operations: + * - Hybrid Ed25519 + Dilithium3 signatures + * - BIP-39 mnemonic generation and validation + * - Post-quantum algorithms (Falcon, SPHINCS+) + * - Key derivation functions + */ + +#include +#include +#include +#include +#include + +using namespace synor::crypto; + +// Helper function to convert bytes to hex string +std::string bytes_to_hex(const std::vector& data, size_t max_len = 0) { + std::stringstream ss; + size_t len = max_len > 0 && max_len < data.size() ? max_len : data.size(); + for (size_t i = 0; i < len; ++i) { + ss << std::hex << std::setw(2) << std::setfill('0') << static_cast(data[i]); + } + if (max_len > 0 && max_len < data.size()) { + ss << "..."; + } + return ss.str(); +} + +void mnemonic_example(SynorCrypto& crypto) { + std::cout << "=== Mnemonic Operations ===" << std::endl; + + // Generate a 24-word mnemonic (256-bit entropy) + auto mnemonic = crypto.mnemonic().generate(24); + std::cout << "Generated mnemonic: " << mnemonic.phrase() << std::endl; + std::cout << "Word count: " << mnemonic.word_count() << std::endl; + + // Validate a mnemonic + auto validation = crypto.mnemonic().validate(mnemonic.phrase()); + std::cout << "Valid: " << (validation.is_valid() ? "true" : "false") << std::endl; + if (!validation.is_valid()) { + std::cout << "Error: " << validation.error() << std::endl; + } + + // Convert mnemonic to seed + auto seed = crypto.mnemonic().to_seed(mnemonic.phrase(), "optional-passphrase"); + std::cout << "Seed (hex): " << bytes_to_hex(seed, 16) << std::endl; + + // Word suggestions for autocomplete + auto suggestions = crypto.mnemonic().suggest_words("aban", 5); + std::cout << "Suggestions for 'aban': "; + for (size_t i = 0; i < suggestions.size(); ++i) { + std::cout << suggestions[i] << (i < suggestions.size() - 1 ? ", " : ""); + } + std::cout << std::endl << std::endl; +} + +void keypair_example(SynorCrypto& crypto) { + std::cout << "=== Keypair Operations ===" << std::endl; + + // Generate a random keypair + auto keypair = crypto.keypairs().generate(); + std::cout << "Generated hybrid keypair:" << std::endl; + std::cout << " Ed25519 public key size: " << keypair.public_key().ed25519_bytes().size() << " bytes" << std::endl; + std::cout << " Dilithium public key size: " << keypair.public_key().dilithium_bytes().size() << " bytes" << std::endl; + std::cout << " Total public key size: " << keypair.public_key().size() << " bytes" << std::endl; + + // Get addresses for different networks + std::cout << "\nAddresses:" << std::endl; + std::cout << " Mainnet: " << keypair.get_address(Network::Mainnet) << std::endl; + std::cout << " Testnet: " << keypair.get_address(Network::Testnet) << std::endl; + std::cout << " Devnet: " << keypair.get_address(Network::Devnet) << std::endl; + + // Create keypair from mnemonic (deterministic) + auto mnemonic = crypto.mnemonic().generate(24); + auto keypair2 = crypto.keypairs().from_mnemonic(mnemonic.phrase(), ""); + auto addr = keypair2.get_address(Network::Mainnet); + std::cout << "\nKeypair from mnemonic: " << addr.substr(0, 20) << "..." << std::endl; + + // Derive child keypair using BIP-44 path + auto path = DerivationPath::external(0, 0); // m/44'/21337'/0'/0/0 + std::cout << "Derivation path: " << path.to_string() << std::endl; + + std::cout << std::endl; +} + +void signing_example(SynorCrypto& crypto) { + std::cout << "=== Hybrid Signing ===" << std::endl; + + // Generate keypair + auto keypair = crypto.keypairs().generate(); + + // Sign a message + std::string message_str = "Hello, quantum-resistant world!"; + std::vector message(message_str.begin(), message_str.end()); + auto signature = crypto.signing().sign(keypair, message); + + std::cout << "Signature created:" << std::endl; + std::cout << " Ed25519 component: " << signature.ed25519_bytes().size() << " bytes" << std::endl; + std::cout << " Dilithium component: " << signature.dilithium_bytes().size() << " bytes" << std::endl; + std::cout << " Total signature size: " << signature.size() << " bytes" << std::endl; + + // Verify the signature + bool valid = crypto.signing().verify(keypair.public_key(), message, signature); + std::cout << "\nVerification result: " << (valid ? "true" : "false") << std::endl; + + // Verify with tampered message fails + std::string tampered_str = "Hello, tampered message!"; + std::vector tampered_message(tampered_str.begin(), tampered_str.end()); + bool invalid_result = crypto.signing().verify(keypair.public_key(), tampered_message, signature); + std::cout << "Tampered message verification: " << (invalid_result ? "true" : "false") << std::endl; + + std::cout << std::endl; +} + +void falcon_example(SynorCrypto& crypto) { + std::cout << "=== Falcon Post-Quantum Signatures ===" << std::endl; + + // Generate Falcon-512 keypair (128-bit security) + auto falcon512 = crypto.falcon().generate(FalconVariant::Falcon512); + std::cout << "Falcon-512 keypair:" << std::endl; + std::cout << " Public key: " << falcon512.public_key().key_bytes().size() << " bytes" << std::endl; + std::cout << " Security level: 128-bit" << std::endl; + + // Generate Falcon-1024 keypair (256-bit security) + auto falcon1024 = crypto.falcon().generate(FalconVariant::Falcon1024); + std::cout << "\nFalcon-1024 keypair:" << std::endl; + std::cout << " Public key: " << falcon1024.public_key().key_bytes().size() << " bytes" << std::endl; + std::cout << " Security level: 256-bit" << std::endl; + + // Sign with Falcon-512 + std::string message_str = "Post-quantum secure message"; + std::vector message(message_str.begin(), message_str.end()); + auto signature = crypto.falcon().sign(falcon512, message); + std::cout << "\nFalcon-512 signature: " << signature.signature_bytes().size() << " bytes" << std::endl; + + // Verify + bool valid = crypto.falcon().verify(falcon512.public_key().key_bytes(), message, signature); + std::cout << "Verification: " << (valid ? "true" : "false") << std::endl; + + std::cout << std::endl; +} + +void sphincs_example(SynorCrypto& crypto) { + std::cout << "=== SPHINCS+ Hash-Based Signatures ===" << std::endl; + + // SPHINCS+ variants with different security levels + struct VariantInfo { + SphincsVariant variant; + int security; + int sig_size; + std::string name; + }; + + std::vector variants = { + {SphincsVariant::Shake128s, 128, 7856, "SHAKE128S"}, + {SphincsVariant::Shake192s, 192, 16224, "SHAKE192S"}, + {SphincsVariant::Shake256s, 256, 29792, "SHAKE256S"}, + }; + + std::string message_str = "Hash-based quantum security"; + std::vector message(message_str.begin(), message_str.end()); + + for (const auto& v : variants) { + auto keypair = crypto.sphincs().generate(v.variant); + std::cout << "SPHINCS+ " << v.name << ":" << std::endl; + std::cout << " Security level: " << v.security << "-bit" << std::endl; + std::cout << " Expected signature size: " << v.sig_size << " bytes" << std::endl; + + // Sign a message + auto signature = crypto.sphincs().sign(keypair, message); + std::cout << " Actual signature size: " << signature.signature_bytes().size() << " bytes" << std::endl; + + // Verify + bool valid = crypto.sphincs().verify(keypair.public_key().key_bytes(), message, signature); + std::cout << " Verification: " << (valid ? "true" : "false") << std::endl << std::endl; + } +} + +void kdf_example(SynorCrypto& crypto) { + std::cout << "=== Key Derivation Functions ===" << std::endl; + + // HKDF (HMAC-based Key Derivation Function) + std::string seed_str = "master-secret-key-material-here"; + std::vector seed(seed_str.begin(), seed_str.end()); + + std::string salt_str = "application-salt"; + std::string info_str = "encryption-key"; + + DerivationConfig hkdf_config{ + .salt = std::vector(salt_str.begin(), salt_str.end()), + .info = std::vector(info_str.begin(), info_str.end()), + .output_length = 32 + }; + + auto derived_key = crypto.kdf().derive_key(seed, hkdf_config); + std::cout << "HKDF derived key: " << bytes_to_hex(derived_key) << std::endl; + + // PBKDF2 (Password-Based Key Derivation Function) + std::string password_str = "user-password"; + std::vector password(password_str.begin(), password_str.end()); + + std::string pbkdf2_salt_str = "random-salt-value"; + + PasswordDerivationConfig pbkdf2_config{ + .salt = std::vector(pbkdf2_salt_str.begin(), pbkdf2_salt_str.end()), + .iterations = 100000, + .output_length = 32 + }; + + auto password_key = crypto.kdf().derive_from_password(password, pbkdf2_config); + std::cout << "PBKDF2 derived key: " << bytes_to_hex(password_key) << std::endl; + + std::cout << std::endl; +} + +void hash_example(SynorCrypto& crypto) { + std::cout << "=== Hash Functions ===" << std::endl; + + std::string data_str = "Data to hash"; + std::vector data(data_str.begin(), data_str.end()); + + // SHA3-256 (FIPS 202) + auto sha3 = crypto.hash().sha3_256(data); + std::cout << "SHA3-256: " << sha3.hex() << std::endl; + + // BLAKE3 (fast, parallel) + auto blake3 = crypto.hash().blake3(data); + std::cout << "BLAKE3: " << blake3.hex() << std::endl; + + // Keccak-256 (Ethereum compatible) + auto keccak = crypto.hash().keccak256(data); + std::cout << "Keccak: " << keccak.hex() << std::endl; + + std::cout << std::endl; +} + +int main(int argc, char** argv) { + // Initialize client + const char* api_key = std::getenv("SYNOR_API_KEY"); + CryptoConfig config{ + .api_key = api_key ? api_key : "your-api-key", + .endpoint = "https://crypto.synor.io/v1", + .timeout = std::chrono::seconds(30), + .retries = 3, + .debug = false, + .default_network = Network::Mainnet + }; + + SynorCrypto crypto(config); + + try { + // Check service health + bool healthy = crypto.health_check(); + std::cout << "Service healthy: " << (healthy ? "true" : "false") << std::endl << std::endl; + + // Run examples + mnemonic_example(crypto); + keypair_example(crypto); + signing_example(crypto); + falcon_example(crypto); + sphincs_example(crypto); + kdf_example(crypto); + hash_example(crypto); + } catch (const std::exception& e) { + std::cerr << "Error: " << e.what() << std::endl; + return 1; + } + + return 0; +} diff --git a/sdk/cpp/examples/dex_example.cpp b/sdk/cpp/examples/dex_example.cpp new file mode 100644 index 0000000..fcba626 --- /dev/null +++ b/sdk/cpp/examples/dex_example.cpp @@ -0,0 +1,358 @@ +/** + * Synor DEX SDK Examples for C++ + * + * Demonstrates decentralized exchange operations: + * - Spot trading (limit/market orders) + * - Perpetual futures trading + * - Liquidity provision (AMM pools) + * - Order book management + * - Portfolio tracking + */ + +#include +#include +#include +#include + +using namespace synor::dex; + +void markets_example(SynorDex& dex) { + std::cout << "=== Markets ===" << std::endl; + + // Get all markets + auto markets = dex.markets().list(); + std::cout << "Available markets: " << markets.size() << std::endl; + + for (size_t i = 0; i < std::min(markets.size(), size_t(5)); ++i) { + const auto& market = markets[i]; + std::cout << "\n " << market.symbol() << ":" << std::endl; + std::cout << " Base: " << market.base_asset() << ", Quote: " << market.quote_asset() << std::endl; + std::cout << " Price: " << market.last_price() << std::endl; + std::cout << " 24h Volume: " << market.volume_24h() << std::endl; + std::cout << " 24h Change: " << market.change_24h() << "%" << std::endl; + std::cout << " Status: " << market.status() << std::endl; + } + + // Get specific market + auto market = dex.markets().get("SYN-USDC"); + std::cout << "\nSYN-USDC details:" << std::endl; + std::cout << " Min order size: " << market.min_order_size() << std::endl; + std::cout << " Tick size: " << market.tick_size() << std::endl; + std::cout << " Maker fee: " << market.maker_fee() << "%" << std::endl; + std::cout << " Taker fee: " << market.taker_fee() << "%" << std::endl; + + // Get market statistics + auto stats = dex.markets().get_stats("SYN-USDC"); + std::cout << "\nMarket statistics:" << std::endl; + std::cout << " High 24h: " << stats.high_24h() << std::endl; + std::cout << " Low 24h: " << stats.low_24h() << std::endl; + std::cout << " Open interest: " << stats.open_interest() << std::endl; + std::cout << " Funding rate: " << stats.funding_rate() << "%" << std::endl; + + std::cout << std::endl; +} + +void spot_trading_example(SynorDex& dex) { + std::cout << "=== Spot Trading ===" << std::endl; + + // Place a limit order + std::cout << "Placing limit buy order..." << std::endl; + auto limit_order = dex.spot().place_order({ + .market = "SYN-USDC", + .side = OrderSide::Buy, + .order_type = OrderType::Limit, + .price = "1.50", + .quantity = "100", + .time_in_force = TimeInForce::GTC + }); + + std::cout << "Limit order placed:" << std::endl; + std::cout << " Order ID: " << limit_order.order_id() << std::endl; + std::cout << " Status: " << limit_order.status() << std::endl; + std::cout << " Price: " << limit_order.price() << std::endl; + std::cout << " Quantity: " << limit_order.quantity() << std::endl; + + // Place a market order + std::cout << "\nPlacing market sell order..." << std::endl; + auto market_order = dex.spot().place_order({ + .market = "SYN-USDC", + .side = OrderSide::Sell, + .order_type = OrderType::Market, + .quantity = "50" + }); + + std::cout << "Market order executed:" << std::endl; + std::cout << " Order ID: " << market_order.order_id() << std::endl; + std::cout << " Status: " << market_order.status() << std::endl; + std::cout << " Filled: " << market_order.filled_quantity() << std::endl; + std::cout << " Avg price: " << market_order.average_price() << std::endl; + + // Get order status + auto status = dex.spot().get_order(limit_order.order_id()); + std::cout << "\nOrder status:" << std::endl; + std::cout << " Status: " << status.status() << std::endl; + std::cout << " Filled: " << status.filled_quantity() << " / " << status.quantity() << std::endl; + std::cout << " Remaining: " << status.remaining_quantity() << std::endl; + + // Cancel order + std::cout << "\nCancelling order..." << std::endl; + dex.spot().cancel_order(limit_order.order_id()); + std::cout << "Order cancelled successfully" << std::endl; + + // Get open orders + auto open_orders = dex.spot().get_open_orders("SYN-USDC"); + std::cout << "\nOpen orders: " << open_orders.size() << std::endl; + + // Get trade history + auto trades = dex.spot().get_trade_history("SYN-USDC", 10); + std::cout << "\nRecent trades: " << trades.size() << std::endl; + for (size_t i = 0; i < std::min(trades.size(), size_t(3)); ++i) { + const auto& trade = trades[i]; + std::cout << " " << trade.side() << " " << trade.quantity() + << " @ " << trade.price() << " (" << trade.timestamp() << ")" << std::endl; + } + + std::cout << std::endl; +} + +void perps_trading_example(SynorDex& dex) { + std::cout << "=== Perpetual Futures Trading ===" << std::endl; + + // Get available perps markets + auto perps_markets = dex.perps().list_markets(); + std::cout << "Available perps markets: " << perps_markets.size() << std::endl; + + for (size_t i = 0; i < std::min(perps_markets.size(), size_t(3)); ++i) { + const auto& market = perps_markets[i]; + std::cout << " " << market.symbol() << ": " << market.mark_price() + << " (funding: " << market.funding_rate() << "%)" << std::endl; + } + + // Open a long position + std::cout << "\nOpening long position..." << std::endl; + auto position = dex.perps().open_position({ + .market = "SYN-USDC-PERP", + .side = OrderSide::Buy, + .order_type = OrderType::Limit, + .price = "1.50", + .size = "1000", + .leverage = 10, + .reduce_only = false + }); + + std::cout << "Position opened:" << std::endl; + std::cout << " Position ID: " << position.position_id() << std::endl; + std::cout << " Size: " << position.size() << std::endl; + std::cout << " Entry price: " << position.entry_price() << std::endl; + std::cout << " Leverage: " << position.leverage() << "x" << std::endl; + std::cout << " Liquidation price: " << position.liquidation_price() << std::endl; + + // Get position details + auto details = dex.perps().get_position(position.position_id()); + std::cout << "\nPosition details:" << std::endl; + std::cout << " Unrealized PnL: " << details.unrealized_pnl() << std::endl; + std::cout << " Margin: " << details.margin() << std::endl; + std::cout << " Margin ratio: " << details.margin_ratio() << "%" << std::endl; + + // Set stop loss and take profit + std::cout << "\nSetting stop loss and take profit..." << std::endl; + dex.perps().set_stop_loss(position.position_id(), "1.40"); + std::cout << "Stop loss set at 1.40" << std::endl; + + dex.perps().set_take_profit(position.position_id(), "1.80"); + std::cout << "Take profit set at 1.80" << std::endl; + + // Close position + std::cout << "\nClosing position..." << std::endl; + auto close_result = dex.perps().close_position(position.position_id()); + std::cout << "Position closed:" << std::endl; + std::cout << " Realized PnL: " << close_result.realized_pnl() << std::endl; + std::cout << " Close price: " << close_result.close_price() << std::endl; + + // Get all positions + auto positions = dex.perps().get_positions(); + std::cout << "\nOpen positions: " << positions.size() << std::endl; + + // Get funding history + auto funding = dex.perps().get_funding_history("SYN-USDC-PERP", 10); + std::cout << "Funding payments: " << funding.size() << std::endl; + + std::cout << std::endl; +} + +void liquidity_example(SynorDex& dex) { + std::cout << "=== Liquidity Provision ===" << std::endl; + + // Get available pools + auto pools = dex.liquidity().list_pools(); + std::cout << "Available pools: " << pools.size() << std::endl; + + for (size_t i = 0; i < std::min(pools.size(), size_t(3)); ++i) { + const auto& pool = pools[i]; + std::cout << "\n " << pool.name() << ":" << std::endl; + std::cout << " TVL: $" << pool.tvl() << std::endl; + std::cout << " APR: " << pool.apr() << "%" << std::endl; + std::cout << " Volume 24h: $" << pool.volume_24h() << std::endl; + std::cout << " Fee tier: " << pool.fee_tier() << "%" << std::endl; + } + + // Get pool details + auto pool = dex.liquidity().get_pool("SYN-USDC"); + std::cout << "\nSYN-USDC pool details:" << std::endl; + std::cout << " Token0: " << pool.token0().symbol() << " (" << pool.token0_reserve() << ")" << std::endl; + std::cout << " Token1: " << pool.token1().symbol() << " (" << pool.token1_reserve() << ")" << std::endl; + std::cout << " Price: " << pool.price() << std::endl; + std::cout << " Total LP tokens: " << pool.total_lp_tokens() << std::endl; + + // Add liquidity + std::cout << "\nAdding liquidity..." << std::endl; + auto add_result = dex.liquidity().add_liquidity({ + .pool = "SYN-USDC", + .amount0 = "100", + .amount1 = "150", + .slippage_bps = 50 // 0.5% + }); + + std::cout << "Liquidity added:" << std::endl; + std::cout << " LP tokens received: " << add_result.lp_tokens() << std::endl; + std::cout << " Position ID: " << add_result.position_id() << std::endl; + std::cout << " Share of pool: " << add_result.share_of_pool() << "%" << std::endl; + + // Get LP positions + auto lp_positions = dex.liquidity().get_positions(); + std::cout << "\nLP positions: " << lp_positions.size() << std::endl; + for (const auto& pos : lp_positions) { + std::cout << " " << pos.pool() << ": " << pos.lp_tokens() + << " LP tokens (value: $" << pos.value() << ")" << std::endl; + } + + // Claim fees + std::cout << "\nClaiming fees..." << std::endl; + auto fees = dex.liquidity().claim_fees(add_result.position_id()); + std::cout << "Fees claimed:" << std::endl; + std::cout << " Token0: " << fees.amount0() << std::endl; + std::cout << " Token1: " << fees.amount1() << std::endl; + + // Remove liquidity + std::cout << "\nRemoving liquidity..." << std::endl; + auto remove_result = dex.liquidity().remove_liquidity({ + .position_id = add_result.position_id(), + .lp_tokens = add_result.lp_tokens(), + .slippage_bps = 50 + }); + + std::cout << "Liquidity removed:" << std::endl; + std::cout << " Token0 received: " << remove_result.amount0() << std::endl; + std::cout << " Token1 received: " << remove_result.amount1() << std::endl; + + std::cout << std::endl; +} + +void orderbook_example(SynorDex& dex) { + std::cout << "=== Order Book ===" << std::endl; + + // Get order book snapshot + auto orderbook = dex.orderbook().get_snapshot("SYN-USDC", 10); + + std::cout << "Order book for SYN-USDC:" << std::endl; + std::cout << "\nAsks (sells):" << std::endl; + for (size_t i = 0; i < std::min(orderbook.asks().size(), size_t(5)); ++i) { + const auto& ask = orderbook.asks()[i]; + std::cout << " " << ask.quantity() << " @ " << ask.price() << std::endl; + } + + std::cout << "\nBids (buys):" << std::endl; + for (size_t i = 0; i < std::min(orderbook.bids().size(), size_t(5)); ++i) { + const auto& bid = orderbook.bids()[i]; + std::cout << " " << bid.quantity() << " @ " << bid.price() << std::endl; + } + + std::cout << "\nSpread: " << orderbook.spread() << " (" << orderbook.spread_percent() << "%)" << std::endl; + std::cout << "Mid price: " << orderbook.mid_price() << std::endl; + + // Get recent trades + auto recent_trades = dex.orderbook().get_recent_trades("SYN-USDC", 10); + std::cout << "\nRecent trades:" << std::endl; + for (size_t i = 0; i < std::min(recent_trades.size(), size_t(5)); ++i) { + const auto& trade = recent_trades[i]; + std::cout << " " << trade.side() << " " << trade.quantity() << " @ " << trade.price() << std::endl; + } + + std::cout << std::endl; +} + +void portfolio_example(SynorDex& dex) { + std::cout << "=== Portfolio ===" << std::endl; + + // Get portfolio overview + auto portfolio = dex.portfolio().get_overview(); + + std::cout << "Portfolio overview:" << std::endl; + std::cout << " Total value: $" << portfolio.total_value() << std::endl; + std::cout << " Available balance: $" << portfolio.available_balance() << std::endl; + std::cout << " In orders: $" << portfolio.in_orders() << std::endl; + std::cout << " In positions: $" << portfolio.in_positions() << std::endl; + std::cout << " Unrealized PnL: $" << portfolio.unrealized_pnl() << std::endl; + + // Get balances + auto balances = dex.portfolio().get_balances(); + std::cout << "\nBalances:" << std::endl; + for (const auto& balance : balances) { + std::cout << " " << balance.asset() << ": " << balance.total() + << " (available: " << balance.available() + << ", in orders: " << balance.in_orders() << ")" << std::endl; + } + + // Get PnL history + auto pnl_history = dex.portfolio().get_pnl_history(30); + std::cout << "\nPnL history (last " << pnl_history.size() << " days):" << std::endl; + if (!pnl_history.empty()) { + std::cout << " Total PnL: $" << pnl_history.back().cumulative_pnl() << std::endl; + } + + // Get trade statistics + auto stats = dex.portfolio().get_stats(); + std::cout << "\nTrade statistics:" << std::endl; + std::cout << " Total trades: " << stats.total_trades() << std::endl; + std::cout << " Win rate: " << stats.win_rate() << "%" << std::endl; + std::cout << " Avg profit: $" << stats.avg_profit() << std::endl; + std::cout << " Avg loss: $" << stats.avg_loss() << std::endl; + std::cout << " Best trade: $" << stats.best_trade() << std::endl; + std::cout << " Worst trade: $" << stats.worst_trade() << std::endl; + + std::cout << std::endl; +} + +int main(int argc, char** argv) { + // Initialize client + const char* api_key = std::getenv("SYNOR_API_KEY"); + DexConfig config{ + .api_key = api_key ? api_key : "your-api-key", + .endpoint = "https://dex.synor.io/v1", + .timeout = std::chrono::seconds(30), + .retries = 3, + .debug = false, + .default_market = "SYN-USDC" + }; + + SynorDex dex(config); + + try { + // Check service health + bool healthy = dex.health_check(); + std::cout << "Service healthy: " << (healthy ? "true" : "false") << std::endl << std::endl; + + // Run examples + markets_example(dex); + spot_trading_example(dex); + perps_trading_example(dex); + liquidity_example(dex); + orderbook_example(dex); + portfolio_example(dex); + } catch (const std::exception& e) { + std::cerr << "Error: " << e.what() << std::endl; + return 1; + } + + return 0; +} diff --git a/sdk/cpp/examples/ibc_example.cpp b/sdk/cpp/examples/ibc_example.cpp new file mode 100644 index 0000000..0740b2f --- /dev/null +++ b/sdk/cpp/examples/ibc_example.cpp @@ -0,0 +1,389 @@ +/** + * Synor IBC SDK Examples for C++ + * + * Demonstrates Inter-Blockchain Communication operations: + * - Cross-chain transfers and messages + * - Channel lifecycle management + * - Packet handling and acknowledgments + * - Relayer operations + * - Connection monitoring + */ + +#include +#include +#include +#include +#include + +using namespace synor::ibc; + +void chains_example(SynorIbc& ibc) { + std::cout << "=== Chain Discovery ===" << std::endl; + + // Get all connected chains + auto chains = ibc.chains().list(); + std::cout << "Connected chains: " << chains.size() << std::endl; + + for (size_t i = 0; i < std::min(chains.size(), size_t(5)); ++i) { + const auto& chain = chains[i]; + std::cout << "\n " << chain.chain_id() << ":" << std::endl; + std::cout << " Name: " << chain.name() << std::endl; + std::cout << " Type: " << chain.chain_type() << std::endl; + std::cout << " Status: " << chain.status() << std::endl; + std::cout << " Block height: " << chain.latest_height() << std::endl; + std::cout << " Light client: " << chain.light_client() << std::endl; + } + + // Get specific chain info + auto synor_chain = ibc.chains().get("synor-mainnet-1"); + std::cout << "\nSynor chain details:" << std::endl; + std::cout << " Bech32 prefix: " << synor_chain.bech32_prefix() << std::endl; + std::cout << " Gas price: " << synor_chain.gas_price() << std::endl; + + auto features = synor_chain.features(); + std::cout << " Supported features: "; + for (size_t i = 0; i < features.size(); ++i) { + std::cout << features[i] << (i < features.size() - 1 ? ", " : ""); + } + std::cout << std::endl; + + // Get chain connections + auto connections = ibc.chains().get_connections("synor-mainnet-1"); + std::cout << "\nChain connections: " << connections.size() << std::endl; + for (size_t i = 0; i < std::min(connections.size(), size_t(3)); ++i) { + const auto& conn = connections[i]; + std::cout << " " << conn.connection_id() << " -> " << conn.counterparty_chain_id() << std::endl; + } + + std::cout << std::endl; +} + +void channels_example(SynorIbc& ibc) { + std::cout << "=== Channel Management ===" << std::endl; + + // List existing channels + auto channels = ibc.channels().list(); + std::cout << "Active channels: " << channels.size() << std::endl; + + for (size_t i = 0; i < std::min(channels.size(), size_t(3)); ++i) { + const auto& channel = channels[i]; + std::cout << "\n Channel " << channel.channel_id() << ":" << std::endl; + std::cout << " Port: " << channel.port_id() << std::endl; + std::cout << " State: " << channel.state() << std::endl; + std::cout << " Order: " << channel.ordering() << std::endl; + std::cout << " Counterparty: " << channel.counterparty_channel_id() + << " on " << channel.counterparty_chain_id() << std::endl; + std::cout << " Version: " << channel.version() << std::endl; + } + + // Create a new channel (4-step handshake) + std::cout << "\nInitiating channel creation..." << std::endl; + + // Step 1: ChanOpenInit + auto init_result = ibc.channels().open_init({ + .port_id = "transfer", + .counterparty_chain_id = "cosmos-hub-4", + .counterparty_port_id = "transfer", + .version = "ics20-1", + .ordering = ChannelOrdering::Unordered + }); + + std::cout << "Channel init:" << std::endl; + std::cout << " Channel ID: " << init_result.channel_id() << std::endl; + std::cout << " State: " << init_result.state() << std::endl; + std::cout << " TX hash: " << init_result.tx_hash() << std::endl; + + // Step 2: Wait for ChanOpenTry (counterparty) + std::cout << "\nWaiting for counterparty ChanOpenTry..." << std::endl; + auto try_state = ibc.channels().wait_for_state( + init_result.channel_id(), + ChannelState::TryOpen, + std::chrono::minutes(5) + ); + std::cout << "Channel state: " << try_state << std::endl; + + // Step 3: ChanOpenAck + std::cout << "\nSending ChanOpenAck..." << std::endl; + auto ack_result = ibc.channels().open_ack({ + .channel_id = init_result.channel_id(), + .counterparty_channel_id = "channel-0", + .counterparty_version = "ics20-1" + }); + std::cout << "Ack TX: " << ack_result.tx_hash() << std::endl; + + // Step 4: Wait for ChanOpenConfirm (counterparty) + std::cout << "\nWaiting for channel to open..." << std::endl; + auto open_state = ibc.channels().wait_for_state( + init_result.channel_id(), + ChannelState::Open, + std::chrono::minutes(5) + ); + std::cout << "Channel is now: " << open_state << std::endl; + + // Get channel details + auto channel = ibc.channels().get(init_result.channel_id()); + std::cout << "\nChannel details:" << std::endl; + std::cout << " Sequences - Send: " << channel.next_sequence_send() + << ", Recv: " << channel.next_sequence_recv() + << ", Ack: " << channel.next_sequence_ack() << std::endl; + + std::cout << std::endl; +} + +void transfer_example(SynorIbc& ibc) { + std::cout << "=== Cross-Chain Transfers ===" << std::endl; + + // Get supported tokens for transfer + auto tokens = ibc.transfers().get_supported_tokens("cosmos-hub-4"); + std::cout << "Transferable tokens to Cosmos Hub:" << std::endl; + for (size_t i = 0; i < std::min(tokens.size(), size_t(5)); ++i) { + const auto& token = tokens[i]; + std::cout << " " << token.symbol() << " (" << token.denom() << ")" << std::endl; + } + + // Initiate a cross-chain transfer + std::cout << "\nInitiating transfer..." << std::endl; + auto now = std::chrono::system_clock::now(); + auto timeout = std::chrono::duration_cast( + (now + std::chrono::seconds(600)).time_since_epoch() + ).count(); + + auto transfer = ibc.transfers().send({ + .source_channel = "channel-0", + .denom = "usynor", + .amount = "1000000", + .receiver = "cosmos1...", + .timeout_height = 0, // Use timestamp instead + .timeout_timestamp = static_cast(timeout), + .memo = "IBC transfer from Synor" + }); + + std::cout << "Transfer initiated:" << std::endl; + std::cout << " TX hash: " << transfer.tx_hash() << std::endl; + std::cout << " Sequence: " << transfer.sequence() << std::endl; + std::cout << " Packet ID: " << transfer.packet_id() << std::endl; + std::cout << " Status: " << transfer.status() << std::endl; + + // Track transfer progress + std::cout << "\nTracking transfer..." << std::endl; + auto status = ibc.transfers().track(transfer.packet_id()); + std::cout << "Current status: " << status.state() << std::endl; + std::cout << "Source TX: " << status.source_tx_hash() << std::endl; + if (!status.dest_tx_hash().empty()) { + std::cout << "Dest TX: " << status.dest_tx_hash() << std::endl; + } + + // Wait for completion + std::cout << "\nWaiting for transfer completion..." << std::endl; + auto final_status = ibc.transfers().wait_for_completion( + transfer.packet_id(), + std::chrono::minutes(10) + ); + + std::cout << "Transfer completed:" << std::endl; + std::cout << " Final status: " << final_status.state() << std::endl; + std::cout << " Acknowledgment: " << final_status.acknowledgment() << std::endl; + + // Get transfer history + auto history = ibc.transfers().get_history(10); + std::cout << "\nRecent transfers: " << history.size() << std::endl; + for (size_t i = 0; i < std::min(history.size(), size_t(3)); ++i) { + const auto& t = history[i]; + std::cout << " " << t.amount() << " " << t.denom() + << " -> " << t.dest_chain() << " (" << t.status() << ")" << std::endl; + } + + std::cout << std::endl; +} + +void packet_example(SynorIbc& ibc) { + std::cout << "=== Packet Operations ===" << std::endl; + + // List pending packets + auto pending = ibc.packets().list_pending("channel-0"); + std::cout << "Pending packets on channel-0: " << pending.size() << std::endl; + + for (size_t i = 0; i < std::min(pending.size(), size_t(3)); ++i) { + const auto& packet = pending[i]; + std::cout << "\n Packet #" << packet.sequence() << ":" << std::endl; + std::cout << " Source: " << packet.source_port() << "/" << packet.source_channel() << std::endl; + std::cout << " Dest: " << packet.dest_port() << "/" << packet.dest_channel() << std::endl; + std::cout << " State: " << packet.state() << std::endl; + std::cout << " Timeout: " << packet.timeout_timestamp() << std::endl; + } + + // Get specific packet + auto packet = ibc.packets().get("channel-0", 1); + std::cout << "\nPacket details:" << std::endl; + std::cout << " Data (hex): " << packet.data_hex().substr(0, 40) << "..." << std::endl; + std::cout << " Created: " << packet.created_at() << std::endl; + + // Get packet commitment proof + auto proof = ibc.packets().get_commitment_proof("channel-0", 1); + std::cout << "\nCommitment proof:" << std::endl; + std::cout << " Height: " << proof.proof_height() << std::endl; + std::cout << " Proof size: " << proof.proof().size() << " bytes" << std::endl; + + // Get acknowledgment + auto ack = ibc.packets().get_acknowledgment("channel-0", 1); + std::cout << "\nAcknowledgment:" << std::endl; + std::cout << " Result: " << (ack.success() ? "Success" : std::string("Error: ") + ack.error()) << std::endl; + std::cout << " TX hash: " << ack.tx_hash() << std::endl; + + // List timed-out packets + auto timed_out = ibc.packets().list_timed_out(); + std::cout << "\nTimed-out packets: " << timed_out.size() << std::endl; + + // Timeout a packet manually + if (!timed_out.empty()) { + const auto& to_timeout = timed_out.front(); + std::cout << "\nProcessing timeout for packet #" << to_timeout.sequence() << std::endl; + auto timeout = ibc.packets().timeout(to_timeout.source_channel(), to_timeout.sequence()); + std::cout << "Timeout TX: " << timeout.tx_hash() << std::endl; + } + + std::cout << std::endl; +} + +void relayer_example(SynorIbc& ibc) { + std::cout << "=== Relayer Operations ===" << std::endl; + + // Get relayer status + auto status = ibc.relayer().get_status(); + std::cout << "Relayer status:" << std::endl; + std::cout << " Running: " << (status.running() ? "true" : "false") << std::endl; + std::cout << " Uptime: " << status.uptime() << std::endl; + std::cout << " Packets relayed: " << status.packets_relayed() << std::endl; + std::cout << " Errors: " << status.error_count() << std::endl; + + // List active paths + auto paths = ibc.relayer().list_paths(); + std::cout << "\nActive relay paths: " << paths.size() << std::endl; + + for (const auto& path : paths) { + std::cout << "\n " << path.path_id() << ":" << std::endl; + std::cout << " " << path.source_chain() << " <-> " << path.dest_chain() << std::endl; + std::cout << " Channel: " << path.source_channel() << " <-> " << path.dest_channel() << std::endl; + std::cout << " Status: " << path.status() << std::endl; + std::cout << " Pending packets: " << path.pending_packets() << std::endl; + } + + // Configure a new path + std::cout << "\nConfiguring new relay path..." << std::endl; + auto new_path = ibc.relayer().add_path({ + .source_chain = "synor-mainnet-1", + .dest_chain = "osmosis-1", + .source_channel = "channel-1", + .dest_channel = "channel-100", + .filter_denoms = {"usynor", "uosmo"}, + .min_relay_amount = "1000", + .max_relay_amount = "1000000000" + }); + + std::cout << "Path created: " << new_path.path_id() << std::endl; + + // Start relaying on path + std::cout << "\nStarting relayer on path..." << std::endl; + ibc.relayer().start_path(new_path.path_id()); + std::cout << "Relayer started" << std::endl; + + // Manually relay pending packets + std::cout << "\nRelaying pending packets..." << std::endl; + auto relay_result = ibc.relayer().relay_pending(new_path.path_id()); + std::cout << "Relayed " << relay_result.packet_count() << " packets" << std::endl; + std::cout << "TX hashes: " << relay_result.tx_hashes().size() << std::endl; + + // Get relay history + auto history = ibc.relayer().get_history(new_path.path_id(), 10); + std::cout << "\nRelay history:" << std::endl; + for (size_t i = 0; i < std::min(history.size(), size_t(3)); ++i) { + const auto& event = history[i]; + std::cout << " " << event.timestamp() << ": " << event.event_type() + << " - " << event.packet_count() << " packets" << std::endl; + } + + std::cout << std::endl; +} + +void monitoring_example(SynorIbc& ibc) { + std::cout << "=== IBC Monitoring ===" << std::endl; + + // Get IBC metrics + auto metrics = ibc.monitoring().get_metrics(); + std::cout << "IBC metrics:" << std::endl; + std::cout << " Total channels: " << metrics.total_channels() << std::endl; + std::cout << " Active channels: " << metrics.active_channels() << std::endl; + std::cout << " Total packets: " << metrics.total_packets() << std::endl; + std::cout << " Pending packets: " << metrics.pending_packets() << std::endl; + std::cout << " Failed packets: " << metrics.failed_packets() << std::endl; + std::cout << " Avg relay time: " << metrics.avg_relay_time() << "ms" << std::endl; + + // Get chain health + auto chain_health = ibc.monitoring().get_chain_health(); + std::cout << "\nChain health:" << std::endl; + for (size_t i = 0; i < std::min(chain_health.size(), size_t(3)); ++i) { + const auto& health = chain_health[i]; + std::cout << " " << health.chain_id() << ":" << std::endl; + std::cout << " Status: " << health.status() << std::endl; + std::cout << " Block lag: " << health.block_lag() << std::endl; + std::cout << " Last update: " << health.last_update() << std::endl; + } + + // Get channel statistics + auto stats = ibc.monitoring().get_channel_stats("channel-0"); + std::cout << "\nChannel-0 statistics:" << std::endl; + std::cout << " Packets sent: " << stats.packets_sent() << std::endl; + std::cout << " Packets received: " << stats.packets_received() << std::endl; + std::cout << " Success rate: " << stats.success_rate() << "%" << std::endl; + std::cout << " Avg confirmation time: " << stats.avg_confirmation_time() << "ms" << std::endl; + + // Subscribe to IBC events + std::cout << "\nSubscribing to IBC events..." << std::endl; + ibc.monitoring().subscribe([](const IbcEvent& event) { + std::cout << "Event: " << event.type() << " on " << event.channel_id() << std::endl; + }); + + // Get alerts + auto alerts = ibc.monitoring().get_alerts(); + std::cout << "\nActive alerts: " << alerts.size() << std::endl; + for (const auto& alert : alerts) { + std::cout << " [" << alert.severity() << "] " << alert.message() << std::endl; + } + + std::cout << std::endl; +} + +int main(int argc, char** argv) { + // Initialize client + const char* api_key = std::getenv("SYNOR_API_KEY"); + IbcConfig config{ + .api_key = api_key ? api_key : "your-api-key", + .endpoint = "https://ibc.synor.io/v1", + .timeout = std::chrono::seconds(30), + .retries = 3, + .debug = false, + .default_chain = "synor-mainnet-1", + .confirmations = 1 + }; + + SynorIbc ibc(config); + + try { + // Check service health + bool healthy = ibc.health_check(); + std::cout << "Service healthy: " << (healthy ? "true" : "false") << std::endl << std::endl; + + // Run examples + chains_example(ibc); + channels_example(ibc); + transfer_example(ibc); + packet_example(ibc); + relayer_example(ibc); + monitoring_example(ibc); + } catch (const std::exception& e) { + std::cerr << "Error: " << e.what() << std::endl; + return 1; + } + + return 0; +} diff --git a/sdk/cpp/examples/zk_example.cpp b/sdk/cpp/examples/zk_example.cpp new file mode 100644 index 0000000..157d9ad --- /dev/null +++ b/sdk/cpp/examples/zk_example.cpp @@ -0,0 +1,359 @@ +/** + * Synor ZK SDK Examples for C++ + * + * Demonstrates zero-knowledge proof operations: + * - Circuit compilation (Circom) + * - Proof generation and verification + * - Multiple proving systems (Groth16, PLONK, STARK) + * - Recursive proof composition + * - Trusted setup ceremonies + */ + +#include +#include +#include +#include +#include + +using namespace synor::zk; + +void circuit_example(SynorZk& zk) { + std::cout << "=== Circuit Compilation ===" << std::endl; + + // Simple Circom circuit: prove knowledge of factors + std::string circom_code = R"( + pragma circom 2.1.0; + + template Multiplier() { + signal input a; + signal input b; + signal output c; + + c <== a * b; + } + + component main = Multiplier(); + )"; + + // Compile the circuit + std::cout << "Compiling circuit..." << std::endl; + auto circuit = zk.circuits().compile({ + .code = circom_code, + .language = CircuitLanguage::Circom + }); + + std::cout << "Circuit compiled:" << std::endl; + std::cout << " Circuit ID: " << circuit.circuit_id() << std::endl; + std::cout << " Constraints: " << circuit.constraints() << std::endl; + std::cout << " Public inputs: " << circuit.public_inputs() << std::endl; + std::cout << " Private inputs: " << circuit.private_inputs() << std::endl; + std::cout << " Outputs: " << circuit.outputs() << std::endl; + + // Get circuit info + auto info = zk.circuits().get(circuit.circuit_id()); + std::cout << "\nCircuit info:" << std::endl; + std::cout << " Name: " << info.name() << std::endl; + std::cout << " Version: " << info.version() << std::endl; + std::cout << " Wires: " << info.wire_count() << std::endl; + std::cout << " Labels: " << info.label_count() << std::endl; + + // List available circuits + auto circuits = zk.circuits().list(); + std::cout << "\nAvailable circuits: " << circuits.size() << std::endl; + for (size_t i = 0; i < std::min(circuits.size(), size_t(3)); ++i) { + const auto& c = circuits[i]; + std::cout << " " << c.circuit_id() << ": " << c.name() + << " (" << c.constraints() << " constraints)" << std::endl; + } + + std::cout << std::endl; +} + +void groth16_example(SynorZk& zk) { + std::cout << "=== Groth16 Proving System ===" << std::endl; + + std::string circuit_id = "multiplier-v1"; + + // Generate proving/verification keys (trusted setup) + std::cout << "Generating keys..." << std::endl; + auto keys = zk.groth16().setup(circuit_id); + std::cout << "Keys generated:" << std::endl; + std::cout << " Proving key size: " << keys.proving_key().size() << " bytes" << std::endl; + std::cout << " Verification key size: " << keys.verification_key().size() << " bytes" << std::endl; + + // Prepare witness (private inputs) + std::map witness = { + {"a", "3"}, + {"b", "7"} + }; + + // Generate proof + std::cout << "\nGenerating proof..." << std::endl; + auto proof = zk.groth16().prove({ + .circuit_id = circuit_id, + .witness = witness, + .proving_key = keys.proving_key() + }); + + std::cout << "Proof generated:" << std::endl; + std::cout << " Proof size: " << proof.proof_bytes().size() << " bytes" << std::endl; + std::cout << " Public signals: " << proof.public_signals().size() << std::endl; + std::cout << " Proving time: " << proof.proving_time_ms() << "ms" << std::endl; + + // Verify proof + std::cout << "\nVerifying proof..." << std::endl; + bool verified = zk.groth16().verify({ + .proof = proof.proof_bytes(), + .public_signals = proof.public_signals(), + .verification_key = keys.verification_key() + }); + + std::cout << "Verification result: " << (verified ? "true" : "false") << std::endl; + + // Export proof for on-chain verification + auto solidity_calldata = zk.groth16().export_calldata(proof); + std::cout << "\nSolidity calldata: " << solidity_calldata.substr(0, 100) << "..." << std::endl; + + std::cout << std::endl; +} + +void plonk_example(SynorZk& zk) { + std::cout << "=== PLONK Proving System ===" << std::endl; + + std::string circuit_id = "multiplier-v1"; + + // PLONK uses universal trusted setup + std::cout << "Getting universal setup..." << std::endl; + auto srs = zk.plonk().get_universal_setup(14); // 2^14 constraints + std::cout << "SRS loaded: " << srs.size() << " bytes" << std::endl; + + // Generate circuit-specific keys + std::cout << "\nGenerating circuit keys..." << std::endl; + auto keys = zk.plonk().setup(circuit_id, srs); + std::cout << "Keys generated" << std::endl; + + // Generate proof + std::map witness = {{"a", "5"}, {"b", "9"}}; + std::cout << "\nGenerating PLONK proof..." << std::endl; + auto proof = zk.plonk().prove({ + .circuit_id = circuit_id, + .witness = witness, + .proving_key = keys.proving_key() + }); + + std::cout << "Proof generated:" << std::endl; + std::cout << " Proof size: " << proof.proof_bytes().size() << " bytes" << std::endl; + std::cout << " Proving time: " << proof.proving_time_ms() << "ms" << std::endl; + + // Verify proof + bool verified = zk.plonk().verify({ + .proof = proof.proof_bytes(), + .public_signals = proof.public_signals(), + .verification_key = keys.verification_key() + }); + std::cout << "Verification result: " << (verified ? "true" : "false") << std::endl; + + // Compare with Groth16 + std::cout << "\nPLONK advantages:" << std::endl; + std::cout << " - Universal trusted setup" << std::endl; + std::cout << " - Larger proofs (~2.5 KB vs ~200 bytes)" << std::endl; + std::cout << " - Faster proving for some circuits" << std::endl; + + std::cout << std::endl; +} + +void stark_example(SynorZk& zk) { + std::cout << "=== STARK Proving System ===" << std::endl; + + std::string circuit_id = "multiplier-v1"; + + // STARKs don't need trusted setup + std::cout << "Configuring STARK parameters..." << std::endl; + StarkConfig config{ + .field_size = 256, + .hash_function = HashFunction::Poseidon, + .blowup_factor = 8, + .num_queries = 30, + .folding_factor = 8 + }; + + // Generate proof + std::map witness = {{"a", "11"}, {"b", "13"}}; + std::cout << "\nGenerating STARK proof..." << std::endl; + auto proof = zk.stark().prove({ + .circuit_id = circuit_id, + .witness = witness, + .config = config + }); + + std::cout << "Proof generated:" << std::endl; + std::cout << " Proof size: " << proof.proof_bytes().size() << " bytes" << std::endl; + std::cout << " Proving time: " << proof.proving_time_ms() << "ms" << std::endl; + std::cout << " FRI layers: " << proof.fri_layers() << std::endl; + + // Verify proof + std::cout << "\nVerifying STARK proof..." << std::endl; + bool verified = zk.stark().verify({ + .proof = proof.proof_bytes(), + .public_signals = proof.public_signals(), + .config = config + }); + + std::cout << "Verification result: " << (verified ? "true" : "false") << std::endl; + + // Compare with SNARKs + std::cout << "\nSTARK advantages:" << std::endl; + std::cout << " - No trusted setup needed" << std::endl; + std::cout << " - Post-quantum secure" << std::endl; + std::cout << " - Larger proofs (~100 KB)" << std::endl; + std::cout << " - Faster proving for complex computations" << std::endl; + + std::cout << std::endl; +} + +void recursive_example(SynorZk& zk) { + std::cout << "=== Recursive Proof Composition ===" << std::endl; + + // Create inner proofs + std::cout << "Generating inner proofs..." << std::endl; + std::vector inner_proofs; + + for (int i = 1; i <= 3; ++i) { + std::map witness = { + {"a", std::to_string(i)}, + {"b", std::to_string(i + 1)} + }; + + auto proof = zk.recursive().prove_inner({ + .circuit_id = "multiplier-v1", + .witness = witness, + .level = 0 + }); + inner_proofs.push_back(proof); + std::cout << " Inner proof " << i << " generated" << std::endl; + } + + // Aggregate proofs recursively + std::cout << "\nAggregating proofs..." << std::endl; + auto aggregated_proof = zk.recursive().aggregate({ + .proofs = inner_proofs, + .aggregation_circuit = "recursive-aggregator-v1" + }); + + std::cout << "Aggregated proof:" << std::endl; + std::cout << " Proof size: " << aggregated_proof.proof_bytes().size() << " bytes" << std::endl; + std::cout << " Proofs aggregated: " << aggregated_proof.proofs_aggregated() << std::endl; + std::cout << " Recursion depth: " << aggregated_proof.recursion_depth() << std::endl; + + // Verify aggregated proof (verifies all inner proofs at once) + std::cout << "\nVerifying aggregated proof..." << std::endl; + bool verified = zk.recursive().verify_aggregated(aggregated_proof); + std::cout << "Verification result: " << (verified ? "true" : "false") << std::endl; + + // Use cases + std::cout << "\nRecursive proof use cases:" << std::endl; + std::cout << " - Rollup batch verification" << std::endl; + std::cout << " - Incremental computation proofs" << std::endl; + std::cout << " - Cross-chain state proofs" << std::endl; + + std::cout << std::endl; +} + +void ceremony_example(SynorZk& zk) { + std::cout << "=== Trusted Setup Ceremony ===" << std::endl; + + // List active ceremonies + auto ceremonies = zk.ceremony().list(CeremonyStatus::Active); + std::cout << "Active ceremonies: " << ceremonies.size() << std::endl; + + for (size_t i = 0; i < std::min(ceremonies.size(), size_t(3)); ++i) { + const auto& ceremony = ceremonies[i]; + std::cout << "\n " << ceremony.ceremony_id() << ":" << std::endl; + std::cout << " Circuit: " << ceremony.circuit_id() << std::endl; + std::cout << " Participants: " << ceremony.participant_count() << std::endl; + std::cout << " Current round: " << ceremony.current_round() << std::endl; + std::cout << " Status: " << ceremony.status() << std::endl; + } + + // Create a new ceremony + std::cout << "\nCreating new ceremony..." << std::endl; + auto new_ceremony = zk.ceremony().create({ + .circuit_id = "new-circuit-v1", + .min_participants = 10, + .max_participants = 100, + .round_duration = 3600, // 1 hour per round + .verify_contributions = true + }); + + std::cout << "Ceremony created:" << std::endl; + std::cout << " Ceremony ID: " << new_ceremony.ceremony_id() << std::endl; + std::cout << " Join URL: " << new_ceremony.join_url() << std::endl; + + // Participate in a ceremony + std::cout << "\nParticipating in ceremony..." << std::endl; + + // Generate entropy + std::vector entropy(32); + std::random_device rd; + std::generate(entropy.begin(), entropy.end(), std::ref(rd)); + + auto contribution = zk.ceremony().contribute({ + .ceremony_id = new_ceremony.ceremony_id(), + .entropy = entropy + }); + + std::cout << "Contribution made:" << std::endl; + std::cout << " Contribution ID: " << contribution.contribution_id() << std::endl; + std::cout << " Position: " << contribution.position() << std::endl; + std::cout << " Hash: " << contribution.hash() << std::endl; + + // Verify a contribution + std::cout << "\nVerifying contribution..." << std::endl; + bool valid = zk.ceremony().verify_contribution(contribution.contribution_id()); + std::cout << "Contribution valid: " << (valid ? "true" : "false") << std::endl; + + // Get ceremony transcript (for auditability) + auto transcript = zk.ceremony().get_transcript(new_ceremony.ceremony_id()); + std::cout << "\nCeremony transcript:" << std::endl; + std::cout << " Total contributions: " << transcript.contributions().size() << std::endl; + std::cout << " Start time: " << transcript.start_time() << std::endl; + std::cout << " Final hash: " << (transcript.final_hash().empty() ? "pending" : transcript.final_hash()) << std::endl; + + std::cout << std::endl; +} + +int main(int argc, char** argv) { + // Initialize client + const char* api_key = std::getenv("SYNOR_API_KEY"); + ZkConfig config{ + .api_key = api_key ? api_key : "your-api-key", + .endpoint = "https://zk.synor.io/v1", + .timeout = std::chrono::seconds(120), // ZK operations can be slow + .retries = 3, + .debug = false, + .default_proving_system = ProvingSystem::Groth16, + .prove_timeout = std::chrono::seconds(300), + .verify_timeout = std::chrono::seconds(30) + }; + + SynorZk zk(config); + + try { + // Check service health + bool healthy = zk.health_check(); + std::cout << "Service healthy: " << (healthy ? "true" : "false") << std::endl << std::endl; + + // Run examples + circuit_example(zk); + groth16_example(zk); + plonk_example(zk); + stark_example(zk); + recursive_example(zk); + ceremony_example(zk); + } catch (const std::exception& e) { + std::cerr << "Error: " << e.what() << std::endl; + return 1; + } + + return 0; +} diff --git a/sdk/csharp/examples/CompilerExample.cs b/sdk/csharp/examples/CompilerExample.cs new file mode 100644 index 0000000..2bd6e6d --- /dev/null +++ b/sdk/csharp/examples/CompilerExample.cs @@ -0,0 +1,415 @@ +/** + * Synor Compiler SDK Examples for C# + * + * Demonstrates smart contract compilation and analysis: + * - WASM contract compilation and optimization + * - ABI extraction and encoding + * - Contract analysis and security scanning + * - Validation and verification + */ + +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Synor.Compiler; + +namespace Synor.Examples; + +public class CompilerExample +{ + private readonly SynorCompiler _compiler; + + public CompilerExample(SynorCompiler compiler) + { + _compiler = compiler; + } + + /// + /// Creates a minimal valid WASM module for testing + /// + private static byte[] CreateMinimalWasm() + { + return new byte[] + { + 0x00, 0x61, 0x73, 0x6d, // Magic: \0asm + 0x01, 0x00, 0x00, 0x00, // Version: 1 + // Type section + 0x01, 0x07, 0x01, 0x60, 0x02, 0x7f, 0x7f, 0x01, 0x7f, + // Function section + 0x03, 0x02, 0x01, 0x00, + // Export section + 0x07, 0x08, 0x01, 0x04, (byte)'a', (byte)'d', (byte)'d', 0x00, 0x00, + // Code section + 0x0a, 0x09, 0x01, 0x07, 0x00, 0x20, 0x00, 0x20, 0x01, 0x6a, 0x0b + }; + } + + public async Task RunCompileContractExample() + { + Console.WriteLine("=== Contract Compilation ==="); + + var wasm = CreateMinimalWasm(); + + var result = await _compiler.CompileAsync(wasm, new CompileOptions + { + OptimizationLevel = OptimizationLevel.Size, + UseWasmOpt = true, + Validate = true, + ExtractMetadata = true, + GenerateAbi = true, + StripOptions = new StripOptions + { + StripDebug = true, + StripProducers = true, + StripNames = true, + StripCustom = true, + StripUnused = true, + PreserveSections = new List() + } + }); + + Console.WriteLine("Compilation result:"); + Console.WriteLine($" Contract ID: {result.ContractId}"); + Console.WriteLine($" Code hash: {result.CodeHash}"); + Console.WriteLine($" Original size: {result.OriginalSize} bytes"); + Console.WriteLine($" Optimized size: {result.OptimizedSize} bytes"); + Console.WriteLine($" Size reduction: {result.SizeReduction:F1}%"); + Console.WriteLine($" Estimated deploy gas: {result.EstimatedDeployGas}"); + + if (result.Metadata != null) + { + Console.WriteLine("\nMetadata:"); + Console.WriteLine($" Name: {result.Metadata.Name}"); + Console.WriteLine($" Version: {result.Metadata.Version}"); + Console.WriteLine($" SDK Version: {result.Metadata.SdkVersion}"); + } + + if (result.Abi != null) + { + Console.WriteLine("\nABI:"); + Console.WriteLine($" Functions: {result.Abi.Functions.Count}"); + Console.WriteLine($" Events: {result.Abi.Events.Count}"); + Console.WriteLine($" Errors: {result.Abi.Errors.Count}"); + } + Console.WriteLine(); + } + + public async Task RunCompilationModesExample() + { + Console.WriteLine("=== Compilation Modes ==="); + + var wasm = CreateMinimalWasm(); + + // Development mode: fast compilation, debugging support + Console.WriteLine("Development mode:"); + var devResult = await _compiler.Contracts.CompileDevAsync(wasm); + Console.WriteLine($" Size: {devResult.OptimizedSize} bytes"); + Console.WriteLine(" Optimization: none"); + + // Production mode: maximum optimization + Console.WriteLine("\nProduction mode:"); + var prodResult = await _compiler.Contracts.CompileProductionAsync(wasm); + Console.WriteLine($" Size: {prodResult.OptimizedSize} bytes"); + Console.WriteLine(" Optimization: aggressive"); + Console.WriteLine($" Size savings: {devResult.OptimizedSize - prodResult.OptimizedSize} bytes"); + + // Custom optimization levels + Console.WriteLine("\nOptimization levels:"); + var levels = new (OptimizationLevel Level, string Name)[] + { + (OptimizationLevel.None, "NONE"), + (OptimizationLevel.Basic, "BASIC"), + (OptimizationLevel.Size, "SIZE"), + (OptimizationLevel.Aggressive, "AGGRESSIVE") + }; + + foreach (var (level, name) in levels) + { + var result = await _compiler.CompileAsync(wasm, new CompileOptions + { + OptimizationLevel = level + }); + Console.WriteLine($" {name}: {result.OptimizedSize} bytes"); + } + Console.WriteLine(); + } + + public async Task RunAbiExample() + { + Console.WriteLine("=== ABI Operations ==="); + + var wasm = CreateMinimalWasm(); + + // Extract ABI from WASM + var abi = await _compiler.Abi.ExtractAsync(wasm); + Console.WriteLine($"Contract: {abi.Name}"); + Console.WriteLine($"Version: {abi.Version}"); + + // List functions + if (abi.Functions.Count > 0) + { + Console.WriteLine("\nFunctions:"); + foreach (var func in abi.Functions) + { + var inputs = string.Join(", ", func.Inputs.ConvertAll(p => $"{p.Name}: {p.Type.TypeName}")); + var outputs = func.Outputs.Count == 0 + ? "void" + : string.Join(", ", func.Outputs.ConvertAll(o => o.Type.TypeName)); + + var modifiers = new List(); + if (func.View) modifiers.Add("view"); + if (func.Payable) modifiers.Add("payable"); + var modifierStr = modifiers.Count > 0 ? string.Join(" ", modifiers) : ""; + + Console.WriteLine($" {func.Name}({inputs}) -> {outputs} {modifierStr}"); + Console.WriteLine($" Selector: {func.Selector}"); + } + } + + // List events + if (abi.Events.Count > 0) + { + Console.WriteLine("\nEvents:"); + foreach (var evt in abi.Events) + { + var paramParts = new List(); + foreach (var param in evt.Params) + { + var prefix = param.Indexed ? "indexed " : ""; + paramParts.Add($"{prefix}{param.Name}: {param.Type.TypeName}"); + } + Console.WriteLine($" {evt.Name}({string.Join(", ", paramParts)})"); + Console.WriteLine($" Topic: {evt.Topic}"); + } + } + + // Encode a function call + if (abi.Functions.Count > 0) + { + var func = abi.Functions[0]; + var encoded = await _compiler.Abi.EncodeCallAsync(func, new[] { "arg1", "arg2" }); + Console.WriteLine($"\nEncoded call to {func.Name}: {encoded}"); + + // Decode a result + var decoded = await _compiler.Abi.DecodeResultAsync(func, encoded); + Console.WriteLine($"Decoded result: {decoded}"); + } + Console.WriteLine(); + } + + public async Task RunAnalysisExample() + { + Console.WriteLine("=== Contract Analysis ==="); + + var wasm = CreateMinimalWasm(); + + // Full analysis + var analysis = await _compiler.Analysis.AnalyzeAsync(wasm); + + // Size breakdown + if (analysis.SizeBreakdown != null) + { + var size = analysis.SizeBreakdown; + Console.WriteLine("Size breakdown:"); + Console.WriteLine($" Code: {size.Code} bytes"); + Console.WriteLine($" Data: {size.Data} bytes"); + Console.WriteLine($" Functions: {size.Functions} bytes"); + Console.WriteLine($" Memory: {size.Memory} bytes"); + Console.WriteLine($" Exports: {size.Exports} bytes"); + Console.WriteLine($" Imports: {size.Imports} bytes"); + Console.WriteLine($" Total: {size.Total} bytes"); + } + + // Function analysis + if (analysis.Functions.Count > 0) + { + Console.WriteLine("\nFunction analysis:"); + foreach (var func in analysis.Functions.GetRange(0, Math.Min(analysis.Functions.Count, 5))) + { + Console.WriteLine($" {func.Name}:"); + Console.WriteLine($" Size: {func.Size} bytes"); + Console.WriteLine($" Instructions: {func.InstructionCount}"); + Console.WriteLine($" Locals: {func.LocalCount}"); + Console.WriteLine($" Exported: {func.Exported}"); + Console.WriteLine($" Estimated gas: {func.EstimatedGas}"); + } + } + + // Import analysis + if (analysis.Imports.Count > 0) + { + Console.WriteLine("\nImports:"); + foreach (var imp in analysis.Imports) + { + Console.WriteLine($" {imp.Module}.{imp.Name} ({imp.Kind})"); + } + } + + // Gas analysis + if (analysis.GasAnalysis != null) + { + var gas = analysis.GasAnalysis; + Console.WriteLine("\nGas analysis:"); + Console.WriteLine($" Deployment: {gas.DeploymentGas}"); + Console.WriteLine($" Memory init: {gas.MemoryInitGas}"); + Console.WriteLine($" Data section: {gas.DataSectionGas}"); + } + + // Extract metadata + var metadata = await _compiler.Analysis.ExtractMetadataAsync(wasm); + Console.WriteLine("\nContract metadata:"); + Console.WriteLine($" Name: {metadata.Name}"); + Console.WriteLine($" Version: {metadata.Version}"); + Console.WriteLine($" Build timestamp: {metadata.BuildTimestamp}"); + + // Estimate deployment gas + var gasEstimate = await _compiler.Analysis.EstimateDeployGasAsync(wasm); + Console.WriteLine($"\nEstimated deployment gas: {gasEstimate}"); + Console.WriteLine(); + } + + public async Task RunValidationExample() + { + Console.WriteLine("=== Contract Validation ==="); + + var wasm = CreateMinimalWasm(); + + // Full validation + var result = await _compiler.Validation.ValidateAsync(wasm); + Console.WriteLine($"Valid: {result.Valid}"); + Console.WriteLine($"Exports: {result.ExportCount}"); + Console.WriteLine($"Imports: {result.ImportCount}"); + Console.WriteLine($"Functions: {result.FunctionCount}"); + Console.WriteLine($"Memory pages: {result.MemoryPages}"); + + if (result.Errors.Count > 0) + { + Console.WriteLine("\nValidation errors:"); + foreach (var error in result.Errors) + { + Console.WriteLine($" [{error.Code}] {error.Message}"); + if (!string.IsNullOrEmpty(error.Location)) + { + Console.WriteLine($" at {error.Location}"); + } + } + } + + if (result.Warnings.Count > 0) + { + Console.WriteLine("\nWarnings:"); + foreach (var warning in result.Warnings) + { + Console.WriteLine($" {warning}"); + } + } + + // Quick validation + var isValid = await _compiler.Validation.IsValidAsync(wasm); + Console.WriteLine($"\nQuick validation: {isValid}"); + + // Get validation errors only + var errors = await _compiler.Validation.GetErrorsAsync(wasm); + Console.WriteLine($"Error count: {errors.Count}"); + + // Validate required exports + var hasRequired = await _compiler.Validation.ValidateExportsAsync(wasm, new[] { "init", "execute", "query" }); + Console.WriteLine($"Has required exports: {hasRequired}"); + + // Validate memory constraints + var memoryValid = await _compiler.Validation.ValidateMemoryAsync(wasm, 16); + Console.WriteLine($"Memory within 16 pages: {memoryValid}"); + Console.WriteLine(); + } + + public async Task RunSecurityExample() + { + Console.WriteLine("=== Security Scanning ==="); + + var wasm = CreateMinimalWasm(); + + var security = await _compiler.Analysis.SecurityScanAsync(wasm); + + Console.WriteLine($"Security score: {security.Score}/100"); + + if (security.Issues.Count > 0) + { + Console.WriteLine("\nSecurity issues:"); + foreach (var issue in security.Issues) + { + var icon = issue.Severity switch + { + "critical" => "[CRIT]", + "high" => "[HIGH]", + "medium" => "[MED]", + "low" => "[LOW]", + _ => "[???]" + }; + + Console.WriteLine($"{icon} [{issue.Severity}] {issue.Type}"); + Console.WriteLine($" {issue.Description}"); + if (!string.IsNullOrEmpty(issue.Location)) + { + Console.WriteLine($" at {issue.Location}"); + } + } + } + else + { + Console.WriteLine("No security issues found!"); + } + + if (security.Recommendations.Count > 0) + { + Console.WriteLine("\nRecommendations:"); + foreach (var rec in security.Recommendations) + { + Console.WriteLine($" • {rec}"); + } + } + Console.WriteLine(); + } + + public static async Task Main(string[] args) + { + // Initialize client + var apiKey = Environment.GetEnvironmentVariable("SYNOR_API_KEY") ?? "your-api-key"; + var config = new CompilerConfig + { + ApiKey = apiKey, + Endpoint = "https://compiler.synor.io/v1", + Timeout = TimeSpan.FromSeconds(60), + Retries = 3, + Debug = false, + DefaultOptimizationLevel = OptimizationLevel.Size, + MaxContractSize = 256 * 1024, + UseWasmOpt = true, + Validate = true, + ExtractMetadata = true, + GenerateAbi = true + }; + + var compiler = new SynorCompiler(config); + var example = new CompilerExample(compiler); + + try + { + // Check service health + var healthy = await compiler.HealthCheckAsync(); + Console.WriteLine($"Service healthy: {healthy}\n"); + + // Run examples + await example.RunCompileContractExample(); + await example.RunCompilationModesExample(); + await example.RunAbiExample(); + await example.RunAnalysisExample(); + await example.RunValidationExample(); + await example.RunSecurityExample(); + } + catch (Exception ex) + { + Console.Error.WriteLine($"Error: {ex.Message}"); + Environment.Exit(1); + } + } +} diff --git a/sdk/csharp/examples/CryptoExample.cs b/sdk/csharp/examples/CryptoExample.cs new file mode 100644 index 0000000..33a80b2 --- /dev/null +++ b/sdk/csharp/examples/CryptoExample.cs @@ -0,0 +1,272 @@ +/** + * Synor Crypto SDK Examples for C# + * + * Demonstrates quantum-resistant cryptographic operations: + * - Hybrid Ed25519 + Dilithium3 signatures + * - BIP-39 mnemonic generation and validation + * - Post-quantum algorithms (Falcon, SPHINCS+) + * - Key derivation functions + */ + +using System; +using System.Text; +using System.Threading.Tasks; +using Synor.Crypto; + +namespace Synor.Examples; + +public class CryptoExample +{ + private readonly SynorCrypto _crypto; + + public CryptoExample(SynorCrypto crypto) + { + _crypto = crypto; + } + + public async Task RunMnemonicExample() + { + Console.WriteLine("=== Mnemonic Operations ==="); + + // Generate a 24-word mnemonic (256-bit entropy) + var mnemonic = await _crypto.Mnemonic.GenerateAsync(24); + Console.WriteLine($"Generated mnemonic: {mnemonic.Phrase}"); + Console.WriteLine($"Word count: {mnemonic.WordCount}"); + + // Validate a mnemonic + var validation = await _crypto.Mnemonic.ValidateAsync(mnemonic.Phrase); + Console.WriteLine($"Valid: {validation.IsValid}"); + if (!validation.IsValid) + { + Console.WriteLine($"Error: {validation.Error}"); + } + + // Convert mnemonic to seed + var seed = await _crypto.Mnemonic.ToSeedAsync(mnemonic.Phrase, "optional-passphrase"); + Console.WriteLine($"Seed (hex): {BytesToHex(seed, 16)}..."); + + // Word suggestions for autocomplete + var suggestions = await _crypto.Mnemonic.SuggestWordsAsync("aban", 5); + Console.WriteLine($"Suggestions for 'aban': {string.Join(", ", suggestions)}"); + Console.WriteLine(); + } + + public async Task RunKeypairExample() + { + Console.WriteLine("=== Keypair Operations ==="); + + // Generate a random keypair + var keypair = await _crypto.Keypairs.GenerateAsync(); + Console.WriteLine("Generated hybrid keypair:"); + Console.WriteLine($" Ed25519 public key size: {keypair.PublicKey.Ed25519Bytes.Length} bytes"); + Console.WriteLine($" Dilithium public key size: {keypair.PublicKey.DilithiumBytes.Length} bytes"); + Console.WriteLine($" Total public key size: {keypair.PublicKey.Size} bytes"); + + // Get addresses for different networks + Console.WriteLine("\nAddresses:"); + Console.WriteLine($" Mainnet: {keypair.GetAddress(Network.Mainnet)}"); + Console.WriteLine($" Testnet: {keypair.GetAddress(Network.Testnet)}"); + Console.WriteLine($" Devnet: {keypair.GetAddress(Network.Devnet)}"); + + // Create keypair from mnemonic (deterministic) + var mnemonic = await _crypto.Mnemonic.GenerateAsync(24); + var keypair2 = await _crypto.Keypairs.FromMnemonicAsync(mnemonic.Phrase); + var addr = keypair2.GetAddress(Network.Mainnet); + Console.WriteLine($"\nKeypair from mnemonic: {addr[..20]}..."); + + // Derive child keypair using BIP-44 path + var path = DerivationPath.External(0, 0); // m/44'/21337'/0'/0/0 + Console.WriteLine($"Derivation path: {path}"); + Console.WriteLine(); + } + + public async Task RunSigningExample() + { + Console.WriteLine("=== Hybrid Signing ==="); + + // Generate keypair + var keypair = await _crypto.Keypairs.GenerateAsync(); + + // Sign a message + var message = Encoding.UTF8.GetBytes("Hello, quantum-resistant world!"); + var signature = await _crypto.Signing.SignAsync(keypair, message); + + Console.WriteLine("Signature created:"); + Console.WriteLine($" Ed25519 component: {signature.Ed25519Bytes.Length} bytes"); + Console.WriteLine($" Dilithium component: {signature.DilithiumBytes.Length} bytes"); + Console.WriteLine($" Total signature size: {signature.Size} bytes"); + + // Verify the signature + var valid = await _crypto.Signing.VerifyAsync(keypair.PublicKey, message, signature); + Console.WriteLine($"\nVerification result: {valid}"); + + // Verify with tampered message fails + var tamperedMessage = Encoding.UTF8.GetBytes("Hello, tampered message!"); + var invalidResult = await _crypto.Signing.VerifyAsync(keypair.PublicKey, tamperedMessage, signature); + Console.WriteLine($"Tampered message verification: {invalidResult}"); + Console.WriteLine(); + } + + public async Task RunFalconExample() + { + Console.WriteLine("=== Falcon Post-Quantum Signatures ==="); + + // Generate Falcon-512 keypair (128-bit security) + var falcon512 = await _crypto.Falcon.GenerateAsync(FalconVariant.Falcon512); + Console.WriteLine("Falcon-512 keypair:"); + Console.WriteLine($" Public key: {falcon512.PublicKey.KeyBytes.Length} bytes"); + Console.WriteLine(" Security level: 128-bit"); + + // Generate Falcon-1024 keypair (256-bit security) + var falcon1024 = await _crypto.Falcon.GenerateAsync(FalconVariant.Falcon1024); + Console.WriteLine("\nFalcon-1024 keypair:"); + Console.WriteLine($" Public key: {falcon1024.PublicKey.KeyBytes.Length} bytes"); + Console.WriteLine(" Security level: 256-bit"); + + // Sign with Falcon-512 + var message = Encoding.UTF8.GetBytes("Post-quantum secure message"); + var signature = await _crypto.Falcon.SignAsync(falcon512, message); + Console.WriteLine($"\nFalcon-512 signature: {signature.SignatureBytes.Length} bytes"); + + // Verify + var valid = await _crypto.Falcon.VerifyAsync(falcon512.PublicKey.KeyBytes, message, signature); + Console.WriteLine($"Verification: {valid}"); + Console.WriteLine(); + } + + public async Task RunSphincsExample() + { + Console.WriteLine("=== SPHINCS+ Hash-Based Signatures ==="); + + // SPHINCS+ variants with different security levels + var variants = new (SphincsVariant Variant, int Security, int SigSize, string Name)[] + { + (SphincsVariant.Shake128s, 128, 7856, "SHAKE128S"), + (SphincsVariant.Shake192s, 192, 16224, "SHAKE192S"), + (SphincsVariant.Shake256s, 256, 29792, "SHAKE256S"), + }; + + var message = Encoding.UTF8.GetBytes("Hash-based quantum security"); + + foreach (var (variant, security, sigSize, name) in variants) + { + var keypair = await _crypto.Sphincs.GenerateAsync(variant); + Console.WriteLine($"SPHINCS+ {name}:"); + Console.WriteLine($" Security level: {security}-bit"); + Console.WriteLine($" Expected signature size: {sigSize} bytes"); + + // Sign a message + var signature = await _crypto.Sphincs.SignAsync(keypair, message); + Console.WriteLine($" Actual signature size: {signature.SignatureBytes.Length} bytes"); + + // Verify + var valid = await _crypto.Sphincs.VerifyAsync(keypair.PublicKey.KeyBytes, message, signature); + Console.WriteLine($" Verification: {valid}"); + Console.WriteLine(); + } + } + + public async Task RunKdfExample() + { + Console.WriteLine("=== Key Derivation Functions ==="); + + // HKDF (HMAC-based Key Derivation Function) + var seed = Encoding.UTF8.GetBytes("master-secret-key-material-here"); + var hkdfConfig = new DerivationConfig + { + Salt = Encoding.UTF8.GetBytes("application-salt"), + Info = Encoding.UTF8.GetBytes("encryption-key"), + OutputLength = 32 + }; + + var derivedKey = await _crypto.Kdf.DeriveKeyAsync(seed, hkdfConfig); + Console.WriteLine($"HKDF derived key: {BytesToHex(derivedKey)}"); + + // PBKDF2 (Password-Based Key Derivation Function) + var password = Encoding.UTF8.GetBytes("user-password"); + var pbkdf2Config = new PasswordDerivationConfig + { + Salt = Encoding.UTF8.GetBytes("random-salt-value"), + Iterations = 100000, + OutputLength = 32 + }; + + var passwordKey = await _crypto.Kdf.DeriveFromPasswordAsync(password, pbkdf2Config); + Console.WriteLine($"PBKDF2 derived key: {BytesToHex(passwordKey)}"); + Console.WriteLine(); + } + + public async Task RunHashExample() + { + Console.WriteLine("=== Hash Functions ==="); + + var data = Encoding.UTF8.GetBytes("Data to hash"); + + // SHA3-256 (FIPS 202) + var sha3 = await _crypto.Hash.Sha3_256Async(data); + Console.WriteLine($"SHA3-256: {sha3.Hex}"); + + // BLAKE3 (fast, parallel) + var blake3 = await _crypto.Hash.Blake3Async(data); + Console.WriteLine($"BLAKE3: {blake3.Hex}"); + + // Keccak-256 (Ethereum compatible) + var keccak = await _crypto.Hash.Keccak256Async(data); + Console.WriteLine($"Keccak: {keccak.Hex}"); + Console.WriteLine(); + } + + private static string BytesToHex(byte[] data, int? maxLen = null) + { + var len = maxLen ?? data.Length; + var sb = new StringBuilder(len * 2); + for (var i = 0; i < Math.Min(len, data.Length); i++) + { + sb.AppendFormat("{0:x2}", data[i]); + } + if (maxLen.HasValue && maxLen.Value < data.Length) + { + sb.Append("..."); + } + return sb.ToString(); + } + + public static async Task Main(string[] args) + { + // Initialize client + var apiKey = Environment.GetEnvironmentVariable("SYNOR_API_KEY") ?? "your-api-key"; + var config = new CryptoConfig + { + ApiKey = apiKey, + Endpoint = "https://crypto.synor.io/v1", + Timeout = TimeSpan.FromSeconds(30), + Retries = 3, + Debug = false, + DefaultNetwork = Network.Mainnet + }; + + var crypto = new SynorCrypto(config); + var example = new CryptoExample(crypto); + + try + { + // Check service health + var healthy = await crypto.HealthCheckAsync(); + Console.WriteLine($"Service healthy: {healthy}\n"); + + // Run examples + await example.RunMnemonicExample(); + await example.RunKeypairExample(); + await example.RunSigningExample(); + await example.RunFalconExample(); + await example.RunSphincsExample(); + await example.RunKdfExample(); + await example.RunHashExample(); + } + catch (Exception ex) + { + Console.Error.WriteLine($"Error: {ex.Message}"); + Environment.Exit(1); + } + } +} diff --git a/sdk/csharp/examples/DexExample.cs b/sdk/csharp/examples/DexExample.cs new file mode 100644 index 0000000..02712cf --- /dev/null +++ b/sdk/csharp/examples/DexExample.cs @@ -0,0 +1,324 @@ +/** + * Synor DEX SDK Examples for C# + * + * Demonstrates decentralized exchange operations: + * - Market data and orderbook queries + * - Spot trading (limit and market orders) + * - Perpetual futures trading + * - Liquidity provision (AMM) + * - Portfolio management + */ + +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Synor.Dex; + +namespace Synor.Examples; + +public class DexExample +{ + private readonly SynorDex _dex; + + public DexExample(SynorDex dex) + { + _dex = dex; + } + + public async Task RunMarketsExample() + { + Console.WriteLine("=== Market Information ==="); + + // List all available markets + var markets = await _dex.Markets.ListAsync(); + Console.WriteLine($"Available markets: {markets.Count}"); + foreach (var market in markets.GetRange(0, Math.Min(markets.Count, 5))) + { + Console.WriteLine($" {market.Symbol}: {market.BaseAsset}/{market.QuoteAsset} ({market.Status})"); + } + + // Get specific market details + var ethUsdc = await _dex.Markets.GetAsync("ETH-USDC"); + Console.WriteLine($"\n{ethUsdc.Symbol} market:"); + Console.WriteLine($" Price: ${ethUsdc.LastPrice:F2}"); + Console.WriteLine($" 24h Change: {ethUsdc.Change24h:F2}%"); + Console.WriteLine($" 24h Volume: ${ethUsdc.Volume24h:N0}"); + Console.WriteLine($" 24h High: ${ethUsdc.High24h:F2}"); + Console.WriteLine($" 24h Low: ${ethUsdc.Low24h:F2}"); + + // Get orderbook + var orderbook = await _dex.Markets.GetOrderbookAsync("ETH-USDC", 10); + Console.WriteLine($"\nOrderbook ({orderbook.Bids.Count} bids, {orderbook.Asks.Count} asks):"); + Console.WriteLine(" Best bid: ${0:F2} ({1:F4} ETH)", orderbook.Bids[0].Price, orderbook.Bids[0].Quantity); + Console.WriteLine(" Best ask: ${0:F2} ({1:F4} ETH)", orderbook.Asks[0].Price, orderbook.Asks[0].Quantity); + Console.WriteLine($" Spread: ${orderbook.Spread:F2} ({orderbook.SpreadPercent:F3}%)"); + + // Get recent trades + var trades = await _dex.Markets.GetTradesAsync("ETH-USDC", 5); + Console.WriteLine("\nRecent trades:"); + foreach (var trade in trades) + { + Console.WriteLine($" {trade.Side}: {trade.Quantity:F4} @ ${trade.Price:F2}"); + } + Console.WriteLine(); + } + + public async Task RunSpotTradingExample() + { + Console.WriteLine("=== Spot Trading ==="); + + // Get account balance + var balances = await _dex.Account.GetBalancesAsync(); + Console.WriteLine("Account balances:"); + foreach (var balance in balances) + { + if (balance.Total > 0) + { + Console.WriteLine($" {balance.Asset}: {balance.Available:F4} available, {balance.Locked:F4} locked"); + } + } + + // Place a limit buy order + Console.WriteLine("\nPlacing limit buy order..."); + var limitOrder = await _dex.Spot.PlaceOrderAsync(new SpotOrderRequest + { + Symbol = "ETH-USDC", + Side = OrderSide.Buy, + Type = OrderType.Limit, + Quantity = 0.1m, + Price = 3000.00m, + TimeInForce = TimeInForce.GoodTillCancel + }); + + Console.WriteLine($"Limit order placed:"); + Console.WriteLine($" Order ID: {limitOrder.OrderId}"); + Console.WriteLine($" Status: {limitOrder.Status}"); + Console.WriteLine($" Price: ${limitOrder.Price:F2}"); + Console.WriteLine($" Quantity: {limitOrder.Quantity:F4}"); + + // Place a market sell order + Console.WriteLine("\nPlacing market sell order..."); + var marketOrder = await _dex.Spot.PlaceOrderAsync(new SpotOrderRequest + { + Symbol = "ETH-USDC", + Side = OrderSide.Sell, + Type = OrderType.Market, + Quantity = 0.05m + }); + + Console.WriteLine($"Market order executed:"); + Console.WriteLine($" Order ID: {marketOrder.OrderId}"); + Console.WriteLine($" Status: {marketOrder.Status}"); + Console.WriteLine($" Filled: {marketOrder.FilledQuantity:F4}"); + Console.WriteLine($" Avg price: ${marketOrder.AveragePrice:F2}"); + + // Get open orders + var openOrders = await _dex.Spot.GetOpenOrdersAsync("ETH-USDC"); + Console.WriteLine($"\nOpen orders: {openOrders.Count}"); + foreach (var order in openOrders) + { + Console.WriteLine($" {order.OrderId}: {order.Side} {order.Quantity:F4} @ ${order.Price:F2}"); + } + + // Cancel an order + if (openOrders.Count > 0) + { + var cancelled = await _dex.Spot.CancelOrderAsync(openOrders[0].OrderId); + Console.WriteLine($"\nCancelled order: {cancelled.OrderId}"); + } + Console.WriteLine(); + } + + public async Task RunPerpsExample() + { + Console.WriteLine("=== Perpetual Futures ==="); + + // Get perpetual markets + var perpMarkets = await _dex.Perps.GetMarketsAsync(); + Console.WriteLine($"Perpetual markets: {perpMarkets.Count}"); + foreach (var market in perpMarkets.GetRange(0, Math.Min(perpMarkets.Count, 3))) + { + Console.WriteLine($" {market.Symbol}: Mark ${market.MarkPrice:F2}, Funding {market.FundingRate:F4}%"); + } + + // Get account position + var positions = await _dex.Perps.GetPositionsAsync(); + Console.WriteLine($"\nOpen positions: {positions.Count}"); + foreach (var position in positions) + { + Console.WriteLine($" {position.Symbol}: {position.Side} {position.Size:F4}"); + Console.WriteLine($" Entry: ${position.EntryPrice:F2}, PnL: ${position.UnrealizedPnl:F2}"); + } + + // Open a long position + Console.WriteLine("\nOpening long position..."); + var longOrder = await _dex.Perps.PlaceOrderAsync(new PerpOrderRequest + { + Symbol = "BTC-USDC-PERP", + Side = OrderSide.Buy, + Type = OrderType.Limit, + Quantity = 0.01m, + Price = 95000.00m, + Leverage = 10, + ReduceOnly = false + }); + + Console.WriteLine($"Position order placed:"); + Console.WriteLine($" Order ID: {longOrder.OrderId}"); + Console.WriteLine($" Leverage: {longOrder.Leverage}x"); + Console.WriteLine($" Margin: ${longOrder.RequiredMargin:F2}"); + + // Set stop-loss and take-profit + Console.WriteLine("\nSetting SL/TP..."); + await _dex.Perps.SetStopLossAsync("BTC-USDC-PERP", 90000.00m); + await _dex.Perps.SetTakeProfitAsync("BTC-USDC-PERP", 100000.00m); + Console.WriteLine(" Stop loss: $90,000"); + Console.WriteLine(" Take profit: $100,000"); + + // Get funding rate history + var fundingHistory = await _dex.Perps.GetFundingHistoryAsync("BTC-USDC-PERP", 5); + Console.WriteLine("\nFunding rate history:"); + foreach (var funding in fundingHistory) + { + Console.WriteLine($" {funding.Timestamp}: {funding.Rate:F4}%"); + } + Console.WriteLine(); + } + + public async Task RunLiquidityExample() + { + Console.WriteLine("=== Liquidity Provision ==="); + + // Get available pools + var pools = await _dex.Liquidity.GetPoolsAsync(); + Console.WriteLine($"Liquidity pools: {pools.Count}"); + foreach (var pool in pools.GetRange(0, Math.Min(pools.Count, 5))) + { + Console.WriteLine($" {pool.Name}: TVL ${pool.TotalValueLocked:N0}, APR {pool.Apr:F2}%"); + } + + // Get pool details + var ethUsdcPool = await _dex.Liquidity.GetPoolAsync("ETH-USDC"); + Console.WriteLine($"\n{ethUsdcPool.Name} pool:"); + Console.WriteLine($" TVL: ${ethUsdcPool.TotalValueLocked:N0}"); + Console.WriteLine($" Volume 24h: ${ethUsdcPool.Volume24h:N0}"); + Console.WriteLine($" Fee tier: {ethUsdcPool.FeeTier:F2}%"); + Console.WriteLine($" APR: {ethUsdcPool.Apr:F2}%"); + Console.WriteLine($" Reserve A: {ethUsdcPool.ReserveA:F4} ETH"); + Console.WriteLine($" Reserve B: {ethUsdcPool.ReserveB:F2} USDC"); + + // Add liquidity + Console.WriteLine("\nAdding liquidity..."); + var addResult = await _dex.Liquidity.AddLiquidityAsync(new AddLiquidityRequest + { + PoolId = "ETH-USDC", + AmountA = 0.1m, + AmountB = 300.0m, + SlippageTolerance = 0.5m + }); + + Console.WriteLine($"Liquidity added:"); + Console.WriteLine($" LP tokens received: {addResult.LpTokensReceived:F8}"); + Console.WriteLine($" Share of pool: {addResult.ShareOfPool:F4}%"); + + // Get LP positions + var lpPositions = await _dex.Liquidity.GetPositionsAsync(); + Console.WriteLine($"\nLP positions: {lpPositions.Count}"); + foreach (var position in lpPositions) + { + Console.WriteLine($" {position.PoolId}: {position.LpTokens:F8} tokens, ${position.Value:F2}"); + Console.WriteLine($" Earned fees: ${position.EarnedFees:F2}"); + } + + // Remove liquidity + Console.WriteLine("\nRemoving liquidity..."); + var removeResult = await _dex.Liquidity.RemoveLiquidityAsync(new RemoveLiquidityRequest + { + PoolId = "ETH-USDC", + LpTokens = addResult.LpTokensReceived, + SlippageTolerance = 0.5m + }); + + Console.WriteLine($"Liquidity removed:"); + Console.WriteLine($" Amount A: {removeResult.AmountA:F4} ETH"); + Console.WriteLine($" Amount B: {removeResult.AmountB:F2} USDC"); + Console.WriteLine(); + } + + public async Task RunPortfolioExample() + { + Console.WriteLine("=== Portfolio Management ==="); + + // Get portfolio summary + var portfolio = await _dex.Portfolio.GetSummaryAsync(); + Console.WriteLine("Portfolio summary:"); + Console.WriteLine($" Total value: ${portfolio.TotalValue:N2}"); + Console.WriteLine($" Available: ${portfolio.AvailableBalance:N2}"); + Console.WriteLine($" In orders: ${portfolio.InOrders:N2}"); + Console.WriteLine($" In positions: ${portfolio.InPositions:N2}"); + Console.WriteLine($" Unrealized PnL: ${portfolio.UnrealizedPnl:N2}"); + + // Get asset allocation + Console.WriteLine("\nAsset allocation:"); + foreach (var allocation in portfolio.Allocations) + { + Console.WriteLine($" {allocation.Asset}: {allocation.Percentage:F1}% (${allocation.Value:N2})"); + } + + // Get trade history + var tradeHistory = await _dex.Portfolio.GetTradeHistoryAsync(new TradeHistoryFilter + { + Limit = 10 + }); + Console.WriteLine($"\nRecent trades: {tradeHistory.Count}"); + foreach (var trade in tradeHistory) + { + Console.WriteLine($" {trade.Timestamp}: {trade.Side} {trade.Quantity:F4} {trade.Symbol} @ ${trade.Price:F2}"); + } + + // Get PnL report + var pnlReport = await _dex.Portfolio.GetPnlReportAsync(Period.Month); + Console.WriteLine($"\nMonthly PnL report:"); + Console.WriteLine($" Realized PnL: ${pnlReport.RealizedPnl:N2}"); + Console.WriteLine($" Unrealized PnL: ${pnlReport.UnrealizedPnl:N2}"); + Console.WriteLine($" Total fees: ${pnlReport.TotalFees:N2}"); + Console.WriteLine($" Net profit: ${pnlReport.NetProfit:N2}"); + Console.WriteLine(); + } + + public static async Task Main(string[] args) + { + // Initialize client + var apiKey = Environment.GetEnvironmentVariable("SYNOR_API_KEY") ?? "your-api-key"; + var config = new DexConfig + { + ApiKey = apiKey, + Endpoint = "https://dex.synor.io/v1", + Timeout = TimeSpan.FromSeconds(30), + Retries = 3, + Debug = false + }; + + var dex = new SynorDex(config); + var example = new DexExample(dex); + + try + { + // Check service health + var healthy = await dex.HealthCheckAsync(); + Console.WriteLine($"Service healthy: {healthy}\n"); + + // Run examples + await example.RunMarketsExample(); + await example.RunSpotTradingExample(); + await example.RunPerpsExample(); + await example.RunLiquidityExample(); + await example.RunPortfolioExample(); + } + catch (Exception ex) + { + Console.Error.WriteLine($"Error: {ex.Message}"); + Environment.Exit(1); + } + } +} diff --git a/sdk/csharp/examples/IbcExample.cs b/sdk/csharp/examples/IbcExample.cs new file mode 100644 index 0000000..725bae8 --- /dev/null +++ b/sdk/csharp/examples/IbcExample.cs @@ -0,0 +1,326 @@ +/** + * Synor IBC SDK Examples for C# + * + * Demonstrates Inter-Blockchain Communication operations: + * - Chain and channel management + * - Cross-chain token transfers + * - Packet lifecycle handling + * - Relayer operations + * - Connection monitoring + */ + +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Synor.Ibc; + +namespace Synor.Examples; + +public class IbcExample +{ + private readonly SynorIbc _ibc; + + public IbcExample(SynorIbc ibc) + { + _ibc = ibc; + } + + public async Task RunChainsExample() + { + Console.WriteLine("=== Chain Information ==="); + + // List connected chains + var chains = await _ibc.Chains.ListAsync(); + Console.WriteLine($"Connected chains: {chains.Count}"); + foreach (var chain in chains.GetRange(0, Math.Min(chains.Count, 5))) + { + Console.WriteLine($" {chain.ChainId}: {chain.Name} ({chain.Status})"); + } + + // Get specific chain info + var cosmosHub = await _ibc.Chains.GetAsync("cosmoshub-4"); + Console.WriteLine($"\n{cosmosHub.Name}:"); + Console.WriteLine($" Chain ID: {cosmosHub.ChainId}"); + Console.WriteLine($" RPC endpoint: {cosmosHub.RpcEndpoint}"); + Console.WriteLine($" Block height: {cosmosHub.LatestHeight}"); + Console.WriteLine($" Active channels: {cosmosHub.ActiveChannels}"); + + // Get chain clients + var clients = await _ibc.Chains.GetClientsAsync("cosmoshub-4"); + Console.WriteLine($"\nIBC clients: {clients.Count}"); + foreach (var client in clients.GetRange(0, Math.Min(clients.Count, 3))) + { + Console.WriteLine($" {client.ClientId}: {client.ChainId} ({client.ClientType})"); + } + Console.WriteLine(); + } + + public async Task RunChannelsExample() + { + Console.WriteLine("=== Channel Management ==="); + + // List channels + var channels = await _ibc.Channels.ListAsync(); + Console.WriteLine($"IBC channels: {channels.Count}"); + foreach (var channel in channels.GetRange(0, Math.Min(channels.Count, 5))) + { + Console.WriteLine($" {channel.ChannelId}: {channel.SourceChain} <-> {channel.DestChain} ({channel.State})"); + } + + // Get channel details + var channelId = "channel-0"; + var channel = await _ibc.Channels.GetAsync(channelId); + Console.WriteLine($"\nChannel {channelId}:"); + Console.WriteLine($" State: {channel.State}"); + Console.WriteLine($" Port: {channel.PortId}"); + Console.WriteLine($" Counterparty: {channel.CounterpartyChannelId}"); + Console.WriteLine($" Connection: {channel.ConnectionId}"); + Console.WriteLine($" Ordering: {channel.Ordering}"); + Console.WriteLine($" Version: {channel.Version}"); + + // Create a new channel (4-step handshake) + Console.WriteLine("\nInitiating channel creation..."); + var initResult = await _ibc.Channels.InitAsync(new ChannelInitRequest + { + SourceChain = "synor-mainnet", + DestChain = "osmosis-1", + PortId = "transfer", + Version = "ics20-1" + }); + Console.WriteLine($" ChanOpenInit sent: {initResult.ChannelId}"); + + // In production, the following steps happen through relayers: + // ChanOpenTry -> ChanOpenAck -> ChanOpenConfirm + + // Get channel statistics + var stats = await _ibc.Channels.GetStatsAsync(channelId); + Console.WriteLine($"\nChannel statistics:"); + Console.WriteLine($" Packets sent: {stats.PacketsSent}"); + Console.WriteLine($" Packets received: {stats.PacketsReceived}"); + Console.WriteLine($" Packets acknowledged: {stats.PacketsAcknowledged}"); + Console.WriteLine($" Packets timed out: {stats.PacketsTimedOut}"); + Console.WriteLine(); + } + + public async Task RunTransferExample() + { + Console.WriteLine("=== Cross-Chain Transfers ==="); + + // Get transfer routes + Console.WriteLine("Available transfer routes:"); + var routes = await _ibc.Transfers.GetRoutesAsync("ATOM", "synor-mainnet"); + foreach (var route in routes) + { + Console.WriteLine($" {route.SourceChain} -> {route.DestChain}: {route.ChannelId}"); + Console.WriteLine($" Estimated time: {route.EstimatedTime}"); + Console.WriteLine($" Fee: {route.Fee} {route.FeeAsset}"); + } + + // Initiate a transfer + Console.WriteLine("\nInitiating transfer..."); + var transfer = await _ibc.Transfers.SendAsync(new TransferRequest + { + SourceChain = "cosmoshub-4", + DestChain = "synor-mainnet", + ChannelId = "channel-0", + Asset = "uatom", + Amount = "1000000", // 1 ATOM + Sender = "cosmos1abc...", + Receiver = "synor1xyz...", + Timeout = TimeSpan.FromMinutes(30), + Memo = "IBC transfer test" + }); + + Console.WriteLine($"Transfer initiated:"); + Console.WriteLine($" Transfer ID: {transfer.TransferId}"); + Console.WriteLine($" Sequence: {transfer.Sequence}"); + Console.WriteLine($" Status: {transfer.Status}"); + + // Track transfer status + Console.WriteLine("\nTracking transfer..."); + var status = await _ibc.Transfers.GetStatusAsync(transfer.TransferId); + Console.WriteLine($" Current status: {status.Status}"); + Console.WriteLine($" Source tx: {status.SourceTxHash}"); + if (!string.IsNullOrEmpty(status.DestTxHash)) + { + Console.WriteLine($" Dest tx: {status.DestTxHash}"); + } + + // Get transfer history + var history = await _ibc.Transfers.GetHistoryAsync(new TransferHistoryFilter + { + Limit = 5 + }); + Console.WriteLine($"\nRecent transfers: {history.Count}"); + foreach (var tx in history) + { + Console.WriteLine($" {tx.TransferId}: {tx.Amount} {tx.Asset} ({tx.Status})"); + } + Console.WriteLine(); + } + + public async Task RunPacketExample() + { + Console.WriteLine("=== Packet Handling ==="); + + // Get pending packets + var pendingPackets = await _ibc.Packets.GetPendingAsync("channel-0"); + Console.WriteLine($"Pending packets: {pendingPackets.Count}"); + foreach (var packet in pendingPackets.GetRange(0, Math.Min(pendingPackets.Count, 5))) + { + Console.WriteLine($" Seq {packet.Sequence}: {packet.SourcePort} -> {packet.DestPort}"); + } + + // Get packet details + if (pendingPackets.Count > 0) + { + var packet = await _ibc.Packets.GetAsync("channel-0", pendingPackets[0].Sequence); + Console.WriteLine($"\nPacket {packet.Sequence}:"); + Console.WriteLine($" Source: {packet.SourcePort}/{packet.SourceChannel}"); + Console.WriteLine($" Dest: {packet.DestPort}/{packet.DestChannel}"); + Console.WriteLine($" Timeout height: {packet.TimeoutHeight}"); + Console.WriteLine($" Timeout timestamp: {packet.TimeoutTimestamp}"); + Console.WriteLine($" Data: {Convert.ToHexString(packet.Data)[..Math.Min(packet.Data.Length * 2, 64)]}..."); + } + + // Query packet commitments + var commitments = await _ibc.Packets.GetCommitmentsAsync("channel-0"); + Console.WriteLine($"\nPacket commitments: {commitments.Count}"); + + // Query unreceived packets + var unreceived = await _ibc.Packets.GetUnreceivedAsync("channel-0", new ulong[] { 1, 2, 3, 4, 5 }); + Console.WriteLine($"Unreceived packets: {string.Join(", ", unreceived)}"); + + // Query acknowledgements + var acks = await _ibc.Packets.GetAcknowledgementsAsync("channel-0"); + Console.WriteLine($"Packet acknowledgements: {acks.Count}"); + Console.WriteLine(); + } + + public async Task RunRelayerExample() + { + Console.WriteLine("=== Relayer Operations ==="); + + // Get relayer status + var relayers = await _ibc.Relayer.ListAsync(); + Console.WriteLine($"Active relayers: {relayers.Count}"); + foreach (var relayer in relayers.GetRange(0, Math.Min(relayers.Count, 3))) + { + Console.WriteLine($" {relayer.Address}: {relayer.PacketsRelayed} packets ({relayer.Status})"); + } + + // Register as a relayer + Console.WriteLine("\nRegistering as relayer..."); + var registration = await _ibc.Relayer.RegisterAsync(new RelayerRegistration + { + Address = "synor1relayer...", + Chains = new List { "synor-mainnet", "cosmoshub-4", "osmosis-1" }, + Commission = 0.1m // 0.1% + }); + Console.WriteLine($" Registered: {registration.RelayerId}"); + + // Start relaying + Console.WriteLine("\nStarting packet relay..."); + var relayConfig = new RelayConfig + { + Channels = new List { "channel-0", "channel-1" }, + BatchSize = 10, + PollInterval = TimeSpan.FromSeconds(5) + }; + + // In production, this would run continuously + var pendingCount = await _ibc.Relayer.GetPendingCountAsync(relayConfig.Channels); + Console.WriteLine($" Pending packets to relay: {pendingCount}"); + + // Relay a batch + var relayResult = await _ibc.Relayer.RelayBatchAsync("channel-0", 5); + Console.WriteLine($" Relayed: {relayResult.PacketsRelayed}"); + Console.WriteLine($" Fees earned: {relayResult.FeesEarned}"); + + // Get relayer earnings + var earnings = await _ibc.Relayer.GetEarningsAsync("synor1relayer..."); + Console.WriteLine($"\nRelayer earnings:"); + Console.WriteLine($" Total earned: {earnings.TotalEarned}"); + Console.WriteLine($" Packets relayed: {earnings.PacketsRelayed}"); + Console.WriteLine($" Success rate: {earnings.SuccessRate:F1}%"); + Console.WriteLine(); + } + + public async Task RunMonitoringExample() + { + Console.WriteLine("=== Connection Monitoring ==="); + + // Get connection health + var connections = await _ibc.Monitoring.GetConnectionsAsync(); + Console.WriteLine("Connection health:"); + foreach (var conn in connections) + { + var healthIcon = conn.Healthy ? "✓" : "✗"; + Console.WriteLine($" [{healthIcon}] {conn.ConnectionId}: {conn.ChainA} <-> {conn.ChainB}"); + Console.WriteLine($" Latency: {conn.Latency}ms, Uptime: {conn.Uptime:F1}%"); + } + + // Get channel metrics + var metrics = await _ibc.Monitoring.GetChannelMetricsAsync("channel-0"); + Console.WriteLine($"\nChannel metrics:"); + Console.WriteLine($" Throughput: {metrics.PacketsPerHour}/hour"); + Console.WriteLine($" Avg latency: {metrics.AvgLatencyMs}ms"); + Console.WriteLine($" Success rate: {metrics.SuccessRate:F1}%"); + Console.WriteLine($" Volume 24h: {metrics.Volume24h}"); + + // Subscribe to events (in production) + Console.WriteLine("\nEvent subscription example:"); + Console.WriteLine(" Subscribing to packet events..."); + // await _ibc.Monitoring.SubscribeAsync("channel-0", (evt) => { + // Console.WriteLine($" Event: {evt.Type} - {evt.Data}"); + // }); + + // Get alerts + var alerts = await _ibc.Monitoring.GetAlertsAsync(); + Console.WriteLine($"\nActive alerts: {alerts.Count}"); + foreach (var alert in alerts) + { + Console.WriteLine($" [{alert.Severity}] {alert.Message}"); + Console.WriteLine($" Channel: {alert.ChannelId}, Time: {alert.Timestamp}"); + } + Console.WriteLine(); + } + + public static async Task Main(string[] args) + { + // Initialize client + var apiKey = Environment.GetEnvironmentVariable("SYNOR_API_KEY") ?? "your-api-key"; + var config = new IbcConfig + { + ApiKey = apiKey, + Endpoint = "https://ibc.synor.io/v1", + Timeout = TimeSpan.FromSeconds(60), + Retries = 3, + Debug = false, + DefaultTimeout = TimeSpan.FromMinutes(30) + }; + + var ibc = new SynorIbc(config); + var example = new IbcExample(ibc); + + try + { + // Check service health + var healthy = await ibc.HealthCheckAsync(); + Console.WriteLine($"Service healthy: {healthy}\n"); + + // Run examples + await example.RunChainsExample(); + await example.RunChannelsExample(); + await example.RunTransferExample(); + await example.RunPacketExample(); + await example.RunRelayerExample(); + await example.RunMonitoringExample(); + } + catch (Exception ex) + { + Console.Error.WriteLine($"Error: {ex.Message}"); + Environment.Exit(1); + } + } +} diff --git a/sdk/csharp/examples/ZkExample.cs b/sdk/csharp/examples/ZkExample.cs new file mode 100644 index 0000000..f40a42b --- /dev/null +++ b/sdk/csharp/examples/ZkExample.cs @@ -0,0 +1,399 @@ +/** + * Synor ZK SDK Examples for C# + * + * Demonstrates zero-knowledge proof operations: + * - Circuit compilation (Circom) + * - Proof generation and verification + * - Multiple proving systems (Groth16, PLONK, STARK) + * - Recursive proof composition + * - Trusted setup ceremonies + */ + +using System; +using System.Collections.Generic; +using System.Security.Cryptography; +using System.Threading.Tasks; +using Synor.Zk; + +namespace Synor.Examples; + +public class ZkExample +{ + private readonly SynorZk _zk; + + public ZkExample(SynorZk zk) + { + _zk = zk; + } + + public async Task RunCircuitExample() + { + Console.WriteLine("=== Circuit Compilation ==="); + + // Simple Circom circuit: prove knowledge of factors + var circomCode = @" + pragma circom 2.1.0; + + template Multiplier() { + signal input a; + signal input b; + signal output c; + + c <== a * b; + } + + component main = Multiplier(); + "; + + // Compile the circuit + Console.WriteLine("Compiling circuit..."); + var circuit = await _zk.Circuits.CompileAsync(new CompileRequest + { + Code = circomCode, + Language = CircuitLanguage.Circom + }); + + Console.WriteLine("Circuit compiled:"); + Console.WriteLine($" Circuit ID: {circuit.CircuitId}"); + Console.WriteLine($" Constraints: {circuit.Constraints}"); + Console.WriteLine($" Public inputs: {circuit.PublicInputs}"); + Console.WriteLine($" Private inputs: {circuit.PrivateInputs}"); + Console.WriteLine($" Outputs: {circuit.Outputs}"); + + // Get circuit info + var info = await _zk.Circuits.GetAsync(circuit.CircuitId); + Console.WriteLine("\nCircuit info:"); + Console.WriteLine($" Name: {info.Name}"); + Console.WriteLine($" Version: {info.Version}"); + Console.WriteLine($" Wires: {info.WireCount}"); + Console.WriteLine($" Labels: {info.LabelCount}"); + + // List available circuits + var circuits = await _zk.Circuits.ListAsync(); + Console.WriteLine($"\nAvailable circuits: {circuits.Count}"); + foreach (var c in circuits.GetRange(0, Math.Min(circuits.Count, 3))) + { + Console.WriteLine($" {c.CircuitId}: {c.Name} ({c.Constraints} constraints)"); + } + Console.WriteLine(); + } + + public async Task RunGroth16Example() + { + Console.WriteLine("=== Groth16 Proving System ==="); + + var circuitId = "multiplier-v1"; + + // Generate proving/verification keys (trusted setup) + Console.WriteLine("Generating keys..."); + var keys = await _zk.Groth16.SetupAsync(circuitId); + Console.WriteLine("Keys generated:"); + Console.WriteLine($" Proving key size: {keys.ProvingKey.Length} bytes"); + Console.WriteLine($" Verification key size: {keys.VerificationKey.Length} bytes"); + + // Prepare witness (private inputs) + var witness = new Dictionary + { + ["a"] = "3", + ["b"] = "7" + }; + + // Generate proof + Console.WriteLine("\nGenerating proof..."); + var proof = await _zk.Groth16.ProveAsync(new ProveRequest + { + CircuitId = circuitId, + Witness = witness, + ProvingKey = keys.ProvingKey + }); + + Console.WriteLine("Proof generated:"); + Console.WriteLine($" Proof size: {proof.ProofBytes.Length} bytes"); + Console.WriteLine($" Public signals: {proof.PublicSignals.Count}"); + Console.WriteLine($" Proving time: {proof.ProvingTimeMs}ms"); + + // Verify proof + Console.WriteLine("\nVerifying proof..."); + var verified = await _zk.Groth16.VerifyAsync(new VerifyRequest + { + Proof = proof.ProofBytes, + PublicSignals = proof.PublicSignals, + VerificationKey = keys.VerificationKey + }); + + Console.WriteLine($"Verification result: {verified}"); + + // Export proof for on-chain verification + var solidityCalldata = await _zk.Groth16.ExportCalldataAsync(proof); + Console.WriteLine($"\nSolidity calldata: {solidityCalldata[..Math.Min(solidityCalldata.Length, 100)]}..."); + Console.WriteLine(); + } + + public async Task RunPlonkExample() + { + Console.WriteLine("=== PLONK Proving System ==="); + + var circuitId = "multiplier-v1"; + + // PLONK uses universal trusted setup + Console.WriteLine("Getting universal setup..."); + var srs = await _zk.Plonk.GetUniversalSetupAsync(14); // 2^14 constraints + Console.WriteLine($"SRS loaded: {srs.Length} bytes"); + + // Generate circuit-specific keys + Console.WriteLine("\nGenerating circuit keys..."); + var keys = await _zk.Plonk.SetupAsync(circuitId, srs); + Console.WriteLine("Keys generated"); + + // Generate proof + var witness = new Dictionary + { + ["a"] = "5", + ["b"] = "9" + }; + + Console.WriteLine("\nGenerating PLONK proof..."); + var proof = await _zk.Plonk.ProveAsync(new ProveRequest + { + CircuitId = circuitId, + Witness = witness, + ProvingKey = keys.ProvingKey + }); + + Console.WriteLine("Proof generated:"); + Console.WriteLine($" Proof size: {proof.ProofBytes.Length} bytes"); + Console.WriteLine($" Proving time: {proof.ProvingTimeMs}ms"); + + // Verify proof + var verified = await _zk.Plonk.VerifyAsync(new VerifyRequest + { + Proof = proof.ProofBytes, + PublicSignals = proof.PublicSignals, + VerificationKey = keys.VerificationKey + }); + Console.WriteLine($"Verification result: {verified}"); + + // Compare with Groth16 + Console.WriteLine("\nPLONK advantages:"); + Console.WriteLine(" - Universal trusted setup"); + Console.WriteLine(" - Larger proofs (~2.5 KB vs ~200 bytes)"); + Console.WriteLine(" - Faster proving for some circuits"); + Console.WriteLine(); + } + + public async Task RunStarkExample() + { + Console.WriteLine("=== STARK Proving System ==="); + + var circuitId = "multiplier-v1"; + + // STARKs don't need trusted setup + Console.WriteLine("Configuring STARK parameters..."); + var config = new StarkConfig + { + FieldSize = 256, + HashFunction = HashFunction.Poseidon, + BlowupFactor = 8, + NumQueries = 30, + FoldingFactor = 8 + }; + + // Generate proof + var witness = new Dictionary + { + ["a"] = "11", + ["b"] = "13" + }; + + Console.WriteLine("\nGenerating STARK proof..."); + var proof = await _zk.Stark.ProveAsync(new StarkProveRequest + { + CircuitId = circuitId, + Witness = witness, + Config = config + }); + + Console.WriteLine("Proof generated:"); + Console.WriteLine($" Proof size: {proof.ProofBytes.Length} bytes"); + Console.WriteLine($" Proving time: {proof.ProvingTimeMs}ms"); + Console.WriteLine($" FRI layers: {proof.FriLayers}"); + + // Verify proof + Console.WriteLine("\nVerifying STARK proof..."); + var verified = await _zk.Stark.VerifyAsync(new StarkVerifyRequest + { + Proof = proof.ProofBytes, + PublicSignals = proof.PublicSignals, + Config = config + }); + + Console.WriteLine($"Verification result: {verified}"); + + // Compare with SNARKs + Console.WriteLine("\nSTARK advantages:"); + Console.WriteLine(" - No trusted setup needed"); + Console.WriteLine(" - Post-quantum secure"); + Console.WriteLine(" - Larger proofs (~100 KB)"); + Console.WriteLine(" - Faster proving for complex computations"); + Console.WriteLine(); + } + + public async Task RunRecursiveExample() + { + Console.WriteLine("=== Recursive Proof Composition ==="); + + // Create inner proofs + Console.WriteLine("Generating inner proofs..."); + var innerProofs = new List(); + + for (var i = 1; i <= 3; i++) + { + var witness = new Dictionary + { + ["a"] = i.ToString(), + ["b"] = (i + 1).ToString() + }; + + var proof = await _zk.Recursive.ProveInnerAsync(new RecursiveProveRequest + { + CircuitId = "multiplier-v1", + Witness = witness, + Level = 0 + }); + innerProofs.Add(proof); + Console.WriteLine($" Inner proof {i} generated"); + } + + // Aggregate proofs recursively + Console.WriteLine("\nAggregating proofs..."); + var aggregatedProof = await _zk.Recursive.AggregateAsync(new AggregateRequest + { + Proofs = innerProofs, + AggregationCircuit = "recursive-aggregator-v1" + }); + + Console.WriteLine("Aggregated proof:"); + Console.WriteLine($" Proof size: {aggregatedProof.ProofBytes.Length} bytes"); + Console.WriteLine($" Proofs aggregated: {aggregatedProof.ProofsAggregated}"); + Console.WriteLine($" Recursion depth: {aggregatedProof.RecursionDepth}"); + + // Verify aggregated proof (verifies all inner proofs at once) + Console.WriteLine("\nVerifying aggregated proof..."); + var verified = await _zk.Recursive.VerifyAggregatedAsync(aggregatedProof); + Console.WriteLine($"Verification result: {verified}"); + + // Use cases + Console.WriteLine("\nRecursive proof use cases:"); + Console.WriteLine(" - Rollup batch verification"); + Console.WriteLine(" - Incremental computation proofs"); + Console.WriteLine(" - Cross-chain state proofs"); + Console.WriteLine(); + } + + public async Task RunCeremonyExample() + { + Console.WriteLine("=== Trusted Setup Ceremony ==="); + + // List active ceremonies + var ceremonies = await _zk.Ceremony.ListAsync(CeremonyStatus.Active); + Console.WriteLine($"Active ceremonies: {ceremonies.Count}"); + + foreach (var ceremony in ceremonies.GetRange(0, Math.Min(ceremonies.Count, 3))) + { + Console.WriteLine($"\n {ceremony.CeremonyId}:"); + Console.WriteLine($" Circuit: {ceremony.CircuitId}"); + Console.WriteLine($" Participants: {ceremony.ParticipantCount}"); + Console.WriteLine($" Current round: {ceremony.CurrentRound}"); + Console.WriteLine($" Status: {ceremony.Status}"); + } + + // Create a new ceremony + Console.WriteLine("\nCreating new ceremony..."); + var newCeremony = await _zk.Ceremony.CreateAsync(new CreateCeremonyRequest + { + CircuitId = "new-circuit-v1", + MinParticipants = 10, + MaxParticipants = 100, + RoundDuration = 3600, // 1 hour per round + VerifyContributions = true + }); + + Console.WriteLine("Ceremony created:"); + Console.WriteLine($" Ceremony ID: {newCeremony.CeremonyId}"); + Console.WriteLine($" Join URL: {newCeremony.JoinUrl}"); + + // Participate in a ceremony + Console.WriteLine("\nParticipating in ceremony..."); + + // Generate entropy + var entropy = new byte[32]; + using (var rng = RandomNumberGenerator.Create()) + { + rng.GetBytes(entropy); + } + + var contribution = await _zk.Ceremony.ContributeAsync(new ContributeRequest + { + CeremonyId = newCeremony.CeremonyId, + Entropy = entropy + }); + + Console.WriteLine("Contribution made:"); + Console.WriteLine($" Contribution ID: {contribution.ContributionId}"); + Console.WriteLine($" Position: {contribution.Position}"); + Console.WriteLine($" Hash: {contribution.Hash}"); + + // Verify a contribution + Console.WriteLine("\nVerifying contribution..."); + var valid = await _zk.Ceremony.VerifyContributionAsync(contribution.ContributionId); + Console.WriteLine($"Contribution valid: {valid}"); + + // Get ceremony transcript (for auditability) + var transcript = await _zk.Ceremony.GetTranscriptAsync(newCeremony.CeremonyId); + Console.WriteLine("\nCeremony transcript:"); + Console.WriteLine($" Total contributions: {transcript.Contributions.Count}"); + Console.WriteLine($" Start time: {transcript.StartTime}"); + Console.WriteLine($" Final hash: {(string.IsNullOrEmpty(transcript.FinalHash) ? "pending" : transcript.FinalHash)}"); + Console.WriteLine(); + } + + public static async Task Main(string[] args) + { + // Initialize client + var apiKey = Environment.GetEnvironmentVariable("SYNOR_API_KEY") ?? "your-api-key"; + var config = new ZkConfig + { + ApiKey = apiKey, + Endpoint = "https://zk.synor.io/v1", + Timeout = TimeSpan.FromSeconds(120), // ZK operations can be slow + Retries = 3, + Debug = false, + DefaultProvingSystem = ProvingSystem.Groth16, + ProveTimeout = TimeSpan.FromSeconds(300), + VerifyTimeout = TimeSpan.FromSeconds(30) + }; + + var zk = new SynorZk(config); + var example = new ZkExample(zk); + + try + { + // Check service health + var healthy = await zk.HealthCheckAsync(); + Console.WriteLine($"Service healthy: {healthy}\n"); + + // Run examples + await example.RunCircuitExample(); + await example.RunGroth16Example(); + await example.RunPlonkExample(); + await example.RunStarkExample(); + await example.RunRecursiveExample(); + await example.RunCeremonyExample(); + } + catch (Exception ex) + { + Console.Error.WriteLine($"Error: {ex.Message}"); + Environment.Exit(1); + } + } +} diff --git a/sdk/ruby/examples/compiler_example.rb b/sdk/ruby/examples/compiler_example.rb new file mode 100644 index 0000000..0290539 --- /dev/null +++ b/sdk/ruby/examples/compiler_example.rb @@ -0,0 +1,353 @@ +# frozen_string_literal: true + +# +# Synor Compiler SDK Examples for Ruby +# +# Demonstrates smart contract compilation and analysis: +# - WASM contract compilation and optimization +# - ABI extraction and encoding +# - Contract analysis and security scanning +# - Validation and verification +# + +require 'synor/compiler' + +class CompilerExample + def initialize(compiler) + @compiler = compiler + end + + # Creates a minimal valid WASM module for testing + def create_minimal_wasm + [ + 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, # "add" + # Code section + 0x0a, 0x09, 0x01, 0x07, 0x00, 0x20, 0x00, 0x20, 0x01, 0x6a, 0x0b + ].pack('C*') + end + + def run_compile_contract_example + puts '=== Contract Compilation ===' + + wasm = create_minimal_wasm + + result = @compiler.compile(wasm, + optimization_level: :size, + use_wasm_opt: true, + validate: true, + extract_metadata: true, + generate_abi: true, + strip_options: { + strip_debug: true, + strip_producers: true, + strip_names: true, + strip_custom: true, + strip_unused: true, + preserve_sections: [] + } + ) + + puts 'Compilation result:' + puts " Contract ID: #{result.contract_id}" + puts " Code hash: #{result.code_hash}" + puts " Original size: #{result.original_size} bytes" + puts " Optimized size: #{result.optimized_size} bytes" + puts " Size reduction: #{format('%.1f', result.size_reduction)}%" + puts " Estimated deploy gas: #{result.estimated_deploy_gas}" + + if result.metadata + puts "\nMetadata:" + puts " Name: #{result.metadata.name}" + puts " Version: #{result.metadata.version}" + puts " SDK Version: #{result.metadata.sdk_version}" + end + + if result.abi + puts "\nABI:" + puts " Functions: #{result.abi.functions.length}" + puts " Events: #{result.abi.events.length}" + puts " Errors: #{result.abi.errors.length}" + end + puts + end + + def run_compilation_modes_example + puts '=== Compilation Modes ===' + + wasm = create_minimal_wasm + + # Development mode: fast compilation, debugging support + puts 'Development mode:' + dev_result = @compiler.contracts.compile_dev(wasm) + puts " Size: #{dev_result.optimized_size} bytes" + puts ' Optimization: none' + + # Production mode: maximum optimization + puts "\nProduction mode:" + prod_result = @compiler.contracts.compile_production(wasm) + puts " Size: #{prod_result.optimized_size} bytes" + puts ' Optimization: aggressive' + puts " Size savings: #{dev_result.optimized_size - prod_result.optimized_size} bytes" + + # Custom optimization levels + puts "\nOptimization levels:" + levels = [ + { level: :none, name: 'NONE' }, + { level: :basic, name: 'BASIC' }, + { level: :size, name: 'SIZE' }, + { level: :aggressive, name: 'AGGRESSIVE' } + ] + + levels.each do |l| + result = @compiler.compile(wasm, optimization_level: l[:level]) + puts " #{l[:name]}: #{result.optimized_size} bytes" + end + puts + end + + def run_abi_example + puts '=== ABI Operations ===' + + wasm = create_minimal_wasm + + # Extract ABI from WASM + abi = @compiler.abi.extract(wasm) + puts "Contract: #{abi.name}" + puts "Version: #{abi.version}" + + # List functions + if abi.functions.any? + puts "\nFunctions:" + abi.functions.each do |func| + inputs = func.inputs.map { |p| "#{p.name}: #{p.type.type_name}" }.join(', ') + outputs = func.outputs.empty? ? 'void' : func.outputs.map { |o| o.type.type_name }.join(', ') + + modifiers = [] + modifiers << 'view' if func.view? + modifiers << 'payable' if func.payable? + modifier_str = modifiers.join(' ') + + puts " #{func.name}(#{inputs}) -> #{outputs} #{modifier_str}" + puts " Selector: #{func.selector}" + end + end + + # List events + if abi.events.any? + puts "\nEvents:" + abi.events.each do |event| + params = event.params.map do |param| + prefix = param.indexed? ? 'indexed ' : '' + "#{prefix}#{param.name}: #{param.type.type_name}" + end.join(', ') + puts " #{event.name}(#{params})" + puts " Topic: #{event.topic}" + end + end + + # Encode a function call + if abi.functions.any? + func = abi.functions.first + encoded = @compiler.abi.encode_call(func, %w[arg1 arg2]) + puts "\nEncoded call to #{func.name}: #{encoded}" + + # Decode a result + decoded = @compiler.abi.decode_result(func, encoded) + puts "Decoded result: #{decoded}" + end + puts + end + + def run_analysis_example + puts '=== Contract Analysis ===' + + wasm = create_minimal_wasm + + # Full analysis + analysis = @compiler.analysis.analyze(wasm) + + # Size breakdown + if analysis.size_breakdown + size = analysis.size_breakdown + puts 'Size breakdown:' + puts " Code: #{size.code} bytes" + puts " Data: #{size.data} bytes" + puts " Functions: #{size.functions} bytes" + puts " Memory: #{size.memory} bytes" + puts " Exports: #{size.exports} bytes" + puts " Imports: #{size.imports} bytes" + puts " Total: #{size.total} bytes" + end + + # Function analysis + if analysis.functions.any? + puts "\nFunction analysis:" + analysis.functions.first(5).each do |func| + puts " #{func.name}:" + puts " Size: #{func.size} bytes" + puts " Instructions: #{func.instruction_count}" + puts " Locals: #{func.local_count}" + puts " Exported: #{func.exported?}" + puts " Estimated gas: #{func.estimated_gas}" + end + end + + # Import analysis + if analysis.imports.any? + puts "\nImports:" + analysis.imports.each do |imp| + puts " #{imp.module}.#{imp.name} (#{imp.kind})" + end + end + + # Gas analysis + if analysis.gas_analysis + gas = analysis.gas_analysis + puts "\nGas analysis:" + puts " Deployment: #{gas.deployment_gas}" + puts " Memory init: #{gas.memory_init_gas}" + puts " Data section: #{gas.data_section_gas}" + end + + # Extract metadata + metadata = @compiler.analysis.extract_metadata(wasm) + puts "\nContract metadata:" + puts " Name: #{metadata.name}" + puts " Version: #{metadata.version}" + puts " Build timestamp: #{metadata.build_timestamp}" + + # Estimate deployment gas + gas_estimate = @compiler.analysis.estimate_deploy_gas(wasm) + puts "\nEstimated deployment gas: #{gas_estimate}" + puts + end + + def run_validation_example + puts '=== Contract Validation ===' + + wasm = create_minimal_wasm + + # Full validation + result = @compiler.validation.validate(wasm) + puts "Valid: #{result.valid?}" + puts "Exports: #{result.export_count}" + puts "Imports: #{result.import_count}" + puts "Functions: #{result.function_count}" + puts "Memory pages: #{result.memory_pages}" + + if result.errors.any? + puts "\nValidation errors:" + result.errors.each do |error| + puts " [#{error.code}] #{error.message}" + puts " at #{error.location}" if error.location + end + end + + if result.warnings.any? + puts "\nWarnings:" + result.warnings.each do |warning| + puts " #{warning}" + end + end + + # Quick validation + is_valid = @compiler.validation.valid?(wasm) + puts "\nQuick validation: #{is_valid}" + + # Get validation errors only + errors = @compiler.validation.get_errors(wasm) + puts "Error count: #{errors.length}" + + # Validate required exports + has_required = @compiler.validation.validate_exports(wasm, %w[init execute query]) + puts "Has required exports: #{has_required}" + + # Validate memory constraints + memory_valid = @compiler.validation.validate_memory(wasm, 16) + puts "Memory within 16 pages: #{memory_valid}" + puts + end + + def run_security_example + puts '=== Security Scanning ===' + + wasm = create_minimal_wasm + + security = @compiler.analysis.security_scan(wasm) + + puts "Security score: #{security.score}/100" + + if security.issues.any? + puts "\nSecurity issues:" + security.issues.each do |issue| + icon = case issue.severity + when 'critical' then '[CRIT]' + when 'high' then '[HIGH]' + when 'medium' then '[MED]' + when 'low' then '[LOW]' + else '[???]' + end + + puts "#{icon} [#{issue.severity}] #{issue.type}" + puts " #{issue.description}" + puts " at #{issue.location}" if issue.location + end + else + puts 'No security issues found!' + end + + if security.recommendations.any? + puts "\nRecommendations:" + security.recommendations.each do |rec| + puts " • #{rec}" + end + end + puts + end +end + +# Main execution +if __FILE__ == $PROGRAM_NAME + # Initialize client + api_key = ENV.fetch('SYNOR_API_KEY', 'your-api-key') + config = Synor::Compiler::Config.new( + api_key: api_key, + endpoint: 'https://compiler.synor.io/v1', + timeout: 60, + retries: 3, + debug: false, + default_optimization_level: :size, + max_contract_size: 256 * 1024, + use_wasm_opt: true, + validate: true, + extract_metadata: true, + generate_abi: true + ) + + compiler = Synor::Compiler::Client.new(config) + example = CompilerExample.new(compiler) + + begin + # Check service health + healthy = compiler.health_check + puts "Service healthy: #{healthy}\n\n" + + # Run examples + example.run_compile_contract_example + example.run_compilation_modes_example + example.run_abi_example + example.run_analysis_example + example.run_validation_example + example.run_security_example + rescue StandardError => e + warn "Error: #{e.message}" + exit 1 + end +end diff --git a/sdk/ruby/examples/crypto_example.rb b/sdk/ruby/examples/crypto_example.rb new file mode 100644 index 0000000..e01d3b1 --- /dev/null +++ b/sdk/ruby/examples/crypto_example.rb @@ -0,0 +1,241 @@ +# frozen_string_literal: true + +# +# Synor Crypto SDK Examples for Ruby +# +# Demonstrates quantum-resistant cryptographic operations: +# - Hybrid Ed25519 + Dilithium3 signatures +# - BIP-39 mnemonic generation and validation +# - Post-quantum algorithms (Falcon, SPHINCS+) +# - Key derivation functions +# + +require 'synor/crypto' + +class CryptoExample + def initialize(crypto) + @crypto = crypto + end + + def run_mnemonic_example + puts '=== Mnemonic Operations ===' + + # Generate a 24-word mnemonic (256-bit entropy) + mnemonic = @crypto.mnemonic.generate(24) + puts "Generated mnemonic: #{mnemonic.phrase}" + puts "Word count: #{mnemonic.word_count}" + + # Validate a mnemonic + validation = @crypto.mnemonic.validate(mnemonic.phrase) + puts "Valid: #{validation.valid?}" + puts "Error: #{validation.error}" unless validation.valid? + + # Convert mnemonic to seed + seed = @crypto.mnemonic.to_seed(mnemonic.phrase, 'optional-passphrase') + puts "Seed (hex): #{bytes_to_hex(seed, 16)}..." + + # Word suggestions for autocomplete + suggestions = @crypto.mnemonic.suggest_words('aban', 5) + puts "Suggestions for 'aban': #{suggestions.join(', ')}" + puts + end + + def run_keypair_example + puts '=== Keypair Operations ===' + + # Generate a random keypair + keypair = @crypto.keypairs.generate + puts 'Generated hybrid keypair:' + puts " Ed25519 public key size: #{keypair.public_key.ed25519_bytes.length} bytes" + puts " Dilithium public key size: #{keypair.public_key.dilithium_bytes.length} bytes" + puts " Total public key size: #{keypair.public_key.size} bytes" + + # Get addresses for different networks + puts "\nAddresses:" + puts " Mainnet: #{keypair.get_address(:mainnet)}" + puts " Testnet: #{keypair.get_address(:testnet)}" + puts " Devnet: #{keypair.get_address(:devnet)}" + + # Create keypair from mnemonic (deterministic) + mnemonic = @crypto.mnemonic.generate(24) + keypair2 = @crypto.keypairs.from_mnemonic(mnemonic.phrase) + addr = keypair2.get_address(:mainnet) + puts "\nKeypair from mnemonic: #{addr[0, 20]}..." + + # Derive child keypair using BIP-44 path + path = Synor::Crypto::DerivationPath.external(0, 0) # m/44'/21337'/0'/0/0 + puts "Derivation path: #{path}" + puts + end + + def run_signing_example + puts '=== Hybrid Signing ===' + + # Generate keypair + keypair = @crypto.keypairs.generate + + # Sign a message + message = 'Hello, quantum-resistant world!'.bytes + signature = @crypto.signing.sign(keypair, message) + + puts 'Signature created:' + puts " Ed25519 component: #{signature.ed25519_bytes.length} bytes" + puts " Dilithium component: #{signature.dilithium_bytes.length} bytes" + puts " Total signature size: #{signature.size} bytes" + + # Verify the signature + valid = @crypto.signing.verify(keypair.public_key, message, signature) + puts "\nVerification result: #{valid}" + + # Verify with tampered message fails + tampered_message = 'Hello, tampered message!'.bytes + invalid_result = @crypto.signing.verify(keypair.public_key, tampered_message, signature) + puts "Tampered message verification: #{invalid_result}" + puts + end + + def run_falcon_example + puts '=== Falcon Post-Quantum Signatures ===' + + # Generate Falcon-512 keypair (128-bit security) + falcon512 = @crypto.falcon.generate(:falcon512) + puts 'Falcon-512 keypair:' + puts " Public key: #{falcon512.public_key.key_bytes.length} bytes" + puts ' Security level: 128-bit' + + # Generate Falcon-1024 keypair (256-bit security) + falcon1024 = @crypto.falcon.generate(:falcon1024) + puts "\nFalcon-1024 keypair:" + puts " Public key: #{falcon1024.public_key.key_bytes.length} bytes" + puts ' Security level: 256-bit' + + # Sign with Falcon-512 + message = 'Post-quantum secure message'.bytes + signature = @crypto.falcon.sign(falcon512, message) + puts "\nFalcon-512 signature: #{signature.signature_bytes.length} bytes" + + # Verify + valid = @crypto.falcon.verify(falcon512.public_key.key_bytes, message, signature) + puts "Verification: #{valid}" + puts + end + + def run_sphincs_example + puts '=== SPHINCS+ Hash-Based Signatures ===' + + # SPHINCS+ variants with different security levels + variants = [ + { variant: :shake128s, security: 128, sig_size: 7856, name: 'SHAKE128S' }, + { variant: :shake192s, security: 192, sig_size: 16_224, name: 'SHAKE192S' }, + { variant: :shake256s, security: 256, sig_size: 29_792, name: 'SHAKE256S' } + ] + + message = 'Hash-based quantum security'.bytes + + variants.each do |v| + keypair = @crypto.sphincs.generate(v[:variant]) + puts "SPHINCS+ #{v[:name]}:" + puts " Security level: #{v[:security]}-bit" + puts " Expected signature size: #{v[:sig_size]} bytes" + + # Sign a message + signature = @crypto.sphincs.sign(keypair, message) + puts " Actual signature size: #{signature.signature_bytes.length} bytes" + + # Verify + valid = @crypto.sphincs.verify(keypair.public_key.key_bytes, message, signature) + puts " Verification: #{valid}" + puts + end + end + + def run_kdf_example + puts '=== Key Derivation Functions ===' + + # HKDF (HMAC-based Key Derivation Function) + seed = 'master-secret-key-material-here'.bytes + hkdf_config = { + salt: 'application-salt'.bytes, + info: 'encryption-key'.bytes, + output_length: 32 + } + + derived_key = @crypto.kdf.derive_key(seed, hkdf_config) + puts "HKDF derived key: #{bytes_to_hex(derived_key)}" + + # PBKDF2 (Password-Based Key Derivation Function) + password = 'user-password'.bytes + pbkdf2_config = { + salt: 'random-salt-value'.bytes, + iterations: 100_000, + output_length: 32 + } + + password_key = @crypto.kdf.derive_from_password(password, pbkdf2_config) + puts "PBKDF2 derived key: #{bytes_to_hex(password_key)}" + puts + end + + def run_hash_example + puts '=== Hash Functions ===' + + data = 'Data to hash'.bytes + + # SHA3-256 (FIPS 202) + sha3 = @crypto.hash.sha3_256(data) + puts "SHA3-256: #{sha3.hex}" + + # BLAKE3 (fast, parallel) + blake3 = @crypto.hash.blake3(data) + puts "BLAKE3: #{blake3.hex}" + + # Keccak-256 (Ethereum compatible) + keccak = @crypto.hash.keccak256(data) + puts "Keccak: #{keccak.hex}" + puts + end + + private + + def bytes_to_hex(data, max_len = nil) + len = max_len || data.length + hex = data[0, len].map { |b| format('%02x', b) }.join + hex += '...' if max_len && max_len < data.length + hex + end +end + +# Main execution +if __FILE__ == $PROGRAM_NAME + # Initialize client + api_key = ENV.fetch('SYNOR_API_KEY', 'your-api-key') + config = Synor::Crypto::Config.new( + api_key: api_key, + endpoint: 'https://crypto.synor.io/v1', + timeout: 30, + retries: 3, + debug: false, + default_network: :mainnet + ) + + crypto = Synor::Crypto::Client.new(config) + example = CryptoExample.new(crypto) + + begin + # Check service health + healthy = crypto.health_check + puts "Service healthy: #{healthy}\n\n" + + # Run examples + example.run_mnemonic_example + example.run_keypair_example + example.run_signing_example + example.run_falcon_example + example.run_sphincs_example + example.run_kdf_example + example.run_hash_example + rescue StandardError => e + warn "Error: #{e.message}" + exit 1 + end +end diff --git a/sdk/ruby/examples/dex_example.rb b/sdk/ruby/examples/dex_example.rb new file mode 100644 index 0000000..6c9492f --- /dev/null +++ b/sdk/ruby/examples/dex_example.rb @@ -0,0 +1,288 @@ +# frozen_string_literal: true + +# +# Synor DEX SDK Examples for Ruby +# +# Demonstrates decentralized exchange operations: +# - Market data and orderbook queries +# - Spot trading (limit and market orders) +# - Perpetual futures trading +# - Liquidity provision (AMM) +# - Portfolio management +# + +require 'synor/dex' + +class DexExample + def initialize(dex) + @dex = dex + end + + def run_markets_example + puts '=== Market Information ===' + + # List all available markets + markets = @dex.markets.list + puts "Available markets: #{markets.length}" + markets.first(5).each do |market| + puts " #{market.symbol}: #{market.base_asset}/#{market.quote_asset} (#{market.status})" + end + + # Get specific market details + eth_usdc = @dex.markets.get('ETH-USDC') + puts "\n#{eth_usdc.symbol} market:" + puts " Price: $#{format('%.2f', eth_usdc.last_price)}" + puts " 24h Change: #{format('%.2f', eth_usdc.change_24h)}%" + puts " 24h Volume: $#{eth_usdc.volume_24h.to_i.to_s.reverse.gsub(/(\d{3})(?=\d)/, '\\1,').reverse}" + puts " 24h High: $#{format('%.2f', eth_usdc.high_24h)}" + puts " 24h Low: $#{format('%.2f', eth_usdc.low_24h)}" + + # Get orderbook + orderbook = @dex.markets.get_orderbook('ETH-USDC', depth: 10) + puts "\nOrderbook (#{orderbook.bids.length} bids, #{orderbook.asks.length} asks):" + puts " Best bid: $#{format('%.2f', orderbook.bids.first.price)} (#{format('%.4f', orderbook.bids.first.quantity)} ETH)" + puts " Best ask: $#{format('%.2f', orderbook.asks.first.price)} (#{format('%.4f', orderbook.asks.first.quantity)} ETH)" + puts " Spread: $#{format('%.2f', orderbook.spread)} (#{format('%.3f', orderbook.spread_percent)}%)" + + # Get recent trades + trades = @dex.markets.get_trades('ETH-USDC', limit: 5) + puts "\nRecent trades:" + trades.each do |trade| + puts " #{trade.side}: #{format('%.4f', trade.quantity)} @ $#{format('%.2f', trade.price)}" + end + puts + end + + def run_spot_trading_example + puts '=== Spot Trading ===' + + # Get account balance + balances = @dex.account.get_balances + puts 'Account balances:' + balances.select { |b| b.total.positive? }.each do |balance| + puts " #{balance.asset}: #{format('%.4f', balance.available)} available, #{format('%.4f', balance.locked)} locked" + end + + # Place a limit buy order + puts "\nPlacing limit buy order..." + limit_order = @dex.spot.place_order( + symbol: 'ETH-USDC', + side: :buy, + type: :limit, + quantity: 0.1, + price: 3000.00, + time_in_force: :gtc + ) + + puts 'Limit order placed:' + puts " Order ID: #{limit_order.order_id}" + puts " Status: #{limit_order.status}" + puts " Price: $#{format('%.2f', limit_order.price)}" + puts " Quantity: #{format('%.4f', limit_order.quantity)}" + + # Place a market sell order + puts "\nPlacing market sell order..." + market_order = @dex.spot.place_order( + symbol: 'ETH-USDC', + side: :sell, + type: :market, + quantity: 0.05 + ) + + puts 'Market order executed:' + puts " Order ID: #{market_order.order_id}" + puts " Status: #{market_order.status}" + puts " Filled: #{format('%.4f', market_order.filled_quantity)}" + puts " Avg price: $#{format('%.2f', market_order.average_price)}" + + # Get open orders + open_orders = @dex.spot.get_open_orders(symbol: 'ETH-USDC') + puts "\nOpen orders: #{open_orders.length}" + open_orders.each do |order| + puts " #{order.order_id}: #{order.side} #{format('%.4f', order.quantity)} @ $#{format('%.2f', order.price)}" + end + + # Cancel an order + if open_orders.any? + cancelled = @dex.spot.cancel_order(open_orders.first.order_id) + puts "\nCancelled order: #{cancelled.order_id}" + end + puts + end + + def run_perps_example + puts '=== Perpetual Futures ===' + + # Get perpetual markets + perp_markets = @dex.perps.get_markets + puts "Perpetual markets: #{perp_markets.length}" + perp_markets.first(3).each do |market| + puts " #{market.symbol}: Mark $#{format('%.2f', market.mark_price)}, Funding #{format('%.4f', market.funding_rate)}%" + end + + # Get account position + positions = @dex.perps.get_positions + puts "\nOpen positions: #{positions.length}" + positions.each do |position| + puts " #{position.symbol}: #{position.side} #{format('%.4f', position.size)}" + puts " Entry: $#{format('%.2f', position.entry_price)}, PnL: $#{format('%.2f', position.unrealized_pnl)}" + end + + # Open a long position + puts "\nOpening long position..." + long_order = @dex.perps.place_order( + symbol: 'BTC-USDC-PERP', + side: :buy, + type: :limit, + quantity: 0.01, + price: 95_000.00, + leverage: 10, + reduce_only: false + ) + + puts 'Position order placed:' + puts " Order ID: #{long_order.order_id}" + puts " Leverage: #{long_order.leverage}x" + puts " Margin: $#{format('%.2f', long_order.required_margin)}" + + # Set stop-loss and take-profit + puts "\nSetting SL/TP..." + @dex.perps.set_stop_loss('BTC-USDC-PERP', 90_000.00) + @dex.perps.set_take_profit('BTC-USDC-PERP', 100_000.00) + puts ' Stop loss: $90,000' + puts ' Take profit: $100,000' + + # Get funding rate history + funding_history = @dex.perps.get_funding_history('BTC-USDC-PERP', limit: 5) + puts "\nFunding rate history:" + funding_history.each do |funding| + puts " #{funding.timestamp}: #{format('%.4f', funding.rate)}%" + end + puts + end + + def run_liquidity_example + puts '=== Liquidity Provision ===' + + # Get available pools + pools = @dex.liquidity.get_pools + puts "Liquidity pools: #{pools.length}" + pools.first(5).each do |pool| + tvl = pool.total_value_locked.to_i.to_s.reverse.gsub(/(\d{3})(?=\d)/, '\\1,').reverse + puts " #{pool.name}: TVL $#{tvl}, APR #{format('%.2f', pool.apr)}%" + end + + # Get pool details + eth_usdc_pool = @dex.liquidity.get_pool('ETH-USDC') + tvl = eth_usdc_pool.total_value_locked.to_i.to_s.reverse.gsub(/(\d{3})(?=\d)/, '\\1,').reverse + vol = eth_usdc_pool.volume_24h.to_i.to_s.reverse.gsub(/(\d{3})(?=\d)/, '\\1,').reverse + puts "\n#{eth_usdc_pool.name} pool:" + puts " TVL: $#{tvl}" + puts " Volume 24h: $#{vol}" + puts " Fee tier: #{format('%.2f', eth_usdc_pool.fee_tier)}%" + puts " APR: #{format('%.2f', eth_usdc_pool.apr)}%" + puts " Reserve A: #{format('%.4f', eth_usdc_pool.reserve_a)} ETH" + puts " Reserve B: #{format('%.2f', eth_usdc_pool.reserve_b)} USDC" + + # Add liquidity + puts "\nAdding liquidity..." + add_result = @dex.liquidity.add_liquidity( + pool_id: 'ETH-USDC', + amount_a: 0.1, + amount_b: 300.0, + slippage_tolerance: 0.5 + ) + + puts 'Liquidity added:' + puts " LP tokens received: #{format('%.8f', add_result.lp_tokens_received)}" + puts " Share of pool: #{format('%.4f', add_result.share_of_pool)}%" + + # Get LP positions + lp_positions = @dex.liquidity.get_positions + puts "\nLP positions: #{lp_positions.length}" + lp_positions.each do |position| + puts " #{position.pool_id}: #{format('%.8f', position.lp_tokens)} tokens, $#{format('%.2f', position.value)}" + puts " Earned fees: $#{format('%.2f', position.earned_fees)}" + end + + # Remove liquidity + puts "\nRemoving liquidity..." + remove_result = @dex.liquidity.remove_liquidity( + pool_id: 'ETH-USDC', + lp_tokens: add_result.lp_tokens_received, + slippage_tolerance: 0.5 + ) + + puts 'Liquidity removed:' + puts " Amount A: #{format('%.4f', remove_result.amount_a)} ETH" + puts " Amount B: #{format('%.2f', remove_result.amount_b)} USDC" + puts + end + + def run_portfolio_example + puts '=== Portfolio Management ===' + + # Get portfolio summary + portfolio = @dex.portfolio.get_summary + puts 'Portfolio summary:' + puts " Total value: $#{format('%.2f', portfolio.total_value)}" + puts " Available: $#{format('%.2f', portfolio.available_balance)}" + puts " In orders: $#{format('%.2f', portfolio.in_orders)}" + puts " In positions: $#{format('%.2f', portfolio.in_positions)}" + puts " Unrealized PnL: $#{format('%.2f', portfolio.unrealized_pnl)}" + + # Get asset allocation + puts "\nAsset allocation:" + portfolio.allocations.each do |allocation| + puts " #{allocation.asset}: #{format('%.1f', allocation.percentage)}% ($#{format('%.2f', allocation.value)})" + end + + # Get trade history + trade_history = @dex.portfolio.get_trade_history(limit: 10) + puts "\nRecent trades: #{trade_history.length}" + trade_history.each do |trade| + puts " #{trade.timestamp}: #{trade.side} #{format('%.4f', trade.quantity)} #{trade.symbol} @ $#{format('%.2f', trade.price)}" + end + + # Get PnL report + pnl_report = @dex.portfolio.get_pnl_report(:month) + puts "\nMonthly PnL report:" + puts " Realized PnL: $#{format('%.2f', pnl_report.realized_pnl)}" + puts " Unrealized PnL: $#{format('%.2f', pnl_report.unrealized_pnl)}" + puts " Total fees: $#{format('%.2f', pnl_report.total_fees)}" + puts " Net profit: $#{format('%.2f', pnl_report.net_profit)}" + puts + end +end + +# Main execution +if __FILE__ == $PROGRAM_NAME + # Initialize client + api_key = ENV.fetch('SYNOR_API_KEY', 'your-api-key') + config = Synor::Dex::Config.new( + api_key: api_key, + endpoint: 'https://dex.synor.io/v1', + timeout: 30, + retries: 3, + debug: false + ) + + dex = Synor::Dex::Client.new(config) + example = DexExample.new(dex) + + begin + # Check service health + healthy = dex.health_check + puts "Service healthy: #{healthy}\n\n" + + # Run examples + example.run_markets_example + example.run_spot_trading_example + example.run_perps_example + example.run_liquidity_example + example.run_portfolio_example + rescue StandardError => e + warn "Error: #{e.message}" + exit 1 + end +end diff --git a/sdk/ruby/examples/ibc_example.rb b/sdk/ruby/examples/ibc_example.rb new file mode 100644 index 0000000..cb9a699 --- /dev/null +++ b/sdk/ruby/examples/ibc_example.rb @@ -0,0 +1,290 @@ +# frozen_string_literal: true + +# +# Synor IBC SDK Examples for Ruby +# +# Demonstrates Inter-Blockchain Communication operations: +# - Chain and channel management +# - Cross-chain token transfers +# - Packet lifecycle handling +# - Relayer operations +# - Connection monitoring +# + +require 'synor/ibc' + +class IbcExample + def initialize(ibc) + @ibc = ibc + end + + def run_chains_example + puts '=== Chain Information ===' + + # List connected chains + chains = @ibc.chains.list + puts "Connected chains: #{chains.length}" + chains.first(5).each do |chain| + puts " #{chain.chain_id}: #{chain.name} (#{chain.status})" + end + + # Get specific chain info + cosmos_hub = @ibc.chains.get('cosmoshub-4') + puts "\n#{cosmos_hub.name}:" + puts " Chain ID: #{cosmos_hub.chain_id}" + puts " RPC endpoint: #{cosmos_hub.rpc_endpoint}" + puts " Block height: #{cosmos_hub.latest_height}" + puts " Active channels: #{cosmos_hub.active_channels}" + + # Get chain clients + clients = @ibc.chains.get_clients('cosmoshub-4') + puts "\nIBC clients: #{clients.length}" + clients.first(3).each do |client| + puts " #{client.client_id}: #{client.chain_id} (#{client.client_type})" + end + puts + end + + def run_channels_example + puts '=== Channel Management ===' + + # List channels + channels = @ibc.channels.list + puts "IBC channels: #{channels.length}" + channels.first(5).each do |channel| + puts " #{channel.channel_id}: #{channel.source_chain} <-> #{channel.dest_chain} (#{channel.state})" + end + + # Get channel details + channel_id = 'channel-0' + channel = @ibc.channels.get(channel_id) + puts "\nChannel #{channel_id}:" + puts " State: #{channel.state}" + puts " Port: #{channel.port_id}" + puts " Counterparty: #{channel.counterparty_channel_id}" + puts " Connection: #{channel.connection_id}" + puts " Ordering: #{channel.ordering}" + puts " Version: #{channel.version}" + + # Create a new channel (4-step handshake) + puts "\nInitiating channel creation..." + init_result = @ibc.channels.init( + source_chain: 'synor-mainnet', + dest_chain: 'osmosis-1', + port_id: 'transfer', + version: 'ics20-1' + ) + puts " ChanOpenInit sent: #{init_result.channel_id}" + + # In production, the following steps happen through relayers: + # ChanOpenTry -> ChanOpenAck -> ChanOpenConfirm + + # Get channel statistics + stats = @ibc.channels.get_stats(channel_id) + puts "\nChannel statistics:" + puts " Packets sent: #{stats.packets_sent}" + puts " Packets received: #{stats.packets_received}" + puts " Packets acknowledged: #{stats.packets_acknowledged}" + puts " Packets timed out: #{stats.packets_timed_out}" + puts + end + + def run_transfer_example + puts '=== Cross-Chain Transfers ===' + + # Get transfer routes + puts 'Available transfer routes:' + routes = @ibc.transfers.get_routes('ATOM', 'synor-mainnet') + routes.each do |route| + puts " #{route.source_chain} -> #{route.dest_chain}: #{route.channel_id}" + puts " Estimated time: #{route.estimated_time}" + puts " Fee: #{route.fee} #{route.fee_asset}" + end + + # Initiate a transfer + puts "\nInitiating transfer..." + transfer = @ibc.transfers.send( + source_chain: 'cosmoshub-4', + dest_chain: 'synor-mainnet', + channel_id: 'channel-0', + asset: 'uatom', + amount: '1000000', # 1 ATOM + sender: 'cosmos1abc...', + receiver: 'synor1xyz...', + timeout: 1800, # 30 minutes in seconds + memo: 'IBC transfer test' + ) + + puts 'Transfer initiated:' + puts " Transfer ID: #{transfer.transfer_id}" + puts " Sequence: #{transfer.sequence}" + puts " Status: #{transfer.status}" + + # Track transfer status + puts "\nTracking transfer..." + status = @ibc.transfers.get_status(transfer.transfer_id) + puts " Current status: #{status.status}" + puts " Source tx: #{status.source_tx_hash}" + puts " Dest tx: #{status.dest_tx_hash}" if status.dest_tx_hash + + # Get transfer history + history = @ibc.transfers.get_history(limit: 5) + puts "\nRecent transfers: #{history.length}" + history.each do |tx| + puts " #{tx.transfer_id}: #{tx.amount} #{tx.asset} (#{tx.status})" + end + puts + end + + def run_packet_example + puts '=== Packet Handling ===' + + # Get pending packets + pending_packets = @ibc.packets.get_pending('channel-0') + puts "Pending packets: #{pending_packets.length}" + pending_packets.first(5).each do |packet| + puts " Seq #{packet.sequence}: #{packet.source_port} -> #{packet.dest_port}" + end + + # Get packet details + if pending_packets.any? + packet = @ibc.packets.get('channel-0', pending_packets.first.sequence) + puts "\nPacket #{packet.sequence}:" + puts " Source: #{packet.source_port}/#{packet.source_channel}" + puts " Dest: #{packet.dest_port}/#{packet.dest_channel}" + puts " Timeout height: #{packet.timeout_height}" + puts " Timeout timestamp: #{packet.timeout_timestamp}" + data_hex = packet.data.unpack1('H*') + puts " Data: #{data_hex[0, 64]}..." + end + + # Query packet commitments + commitments = @ibc.packets.get_commitments('channel-0') + puts "\nPacket commitments: #{commitments.length}" + + # Query unreceived packets + unreceived = @ibc.packets.get_unreceived('channel-0', [1, 2, 3, 4, 5]) + puts "Unreceived packets: #{unreceived.join(', ')}" + + # Query acknowledgements + acks = @ibc.packets.get_acknowledgements('channel-0') + puts "Packet acknowledgements: #{acks.length}" + puts + end + + def run_relayer_example + puts '=== Relayer Operations ===' + + # Get relayer status + relayers = @ibc.relayer.list + puts "Active relayers: #{relayers.length}" + relayers.first(3).each do |relayer| + puts " #{relayer.address}: #{relayer.packets_relayed} packets (#{relayer.status})" + end + + # Register as a relayer + puts "\nRegistering as relayer..." + registration = @ibc.relayer.register( + address: 'synor1relayer...', + chains: %w[synor-mainnet cosmoshub-4 osmosis-1], + commission: 0.1 # 0.1% + ) + puts " Registered: #{registration.relayer_id}" + + # Start relaying + puts "\nStarting packet relay..." + relay_config = { + channels: %w[channel-0 channel-1], + batch_size: 10, + poll_interval: 5 + } + + # In production, this would run continuously + pending_count = @ibc.relayer.get_pending_count(relay_config[:channels]) + puts " Pending packets to relay: #{pending_count}" + + # Relay a batch + relay_result = @ibc.relayer.relay_batch('channel-0', 5) + puts " Relayed: #{relay_result.packets_relayed}" + puts " Fees earned: #{relay_result.fees_earned}" + + # Get relayer earnings + earnings = @ibc.relayer.get_earnings('synor1relayer...') + puts "\nRelayer earnings:" + puts " Total earned: #{earnings.total_earned}" + puts " Packets relayed: #{earnings.packets_relayed}" + puts " Success rate: #{format('%.1f', earnings.success_rate)}%" + puts + end + + def run_monitoring_example + puts '=== Connection Monitoring ===' + + # Get connection health + connections = @ibc.monitoring.get_connections + puts 'Connection health:' + connections.each do |conn| + health_icon = conn.healthy? ? '✓' : '✗' + puts " [#{health_icon}] #{conn.connection_id}: #{conn.chain_a} <-> #{conn.chain_b}" + puts " Latency: #{conn.latency}ms, Uptime: #{format('%.1f', conn.uptime)}%" + end + + # Get channel metrics + metrics = @ibc.monitoring.get_channel_metrics('channel-0') + puts "\nChannel metrics:" + puts " Throughput: #{metrics.packets_per_hour}/hour" + puts " Avg latency: #{metrics.avg_latency_ms}ms" + puts " Success rate: #{format('%.1f', metrics.success_rate)}%" + puts " Volume 24h: #{metrics.volume_24h}" + + # Subscribe to events (in production) + puts "\nEvent subscription example:" + puts ' Subscribing to packet events...' + # @ibc.monitoring.subscribe('channel-0') do |event| + # puts " Event: #{event.type} - #{event.data}" + # end + + # Get alerts + alerts = @ibc.monitoring.get_alerts + puts "\nActive alerts: #{alerts.length}" + alerts.each do |alert| + puts " [#{alert.severity}] #{alert.message}" + puts " Channel: #{alert.channel_id}, Time: #{alert.timestamp}" + end + puts + end +end + +# Main execution +if __FILE__ == $PROGRAM_NAME + # Initialize client + api_key = ENV.fetch('SYNOR_API_KEY', 'your-api-key') + config = Synor::Ibc::Config.new( + api_key: api_key, + endpoint: 'https://ibc.synor.io/v1', + timeout: 60, + retries: 3, + debug: false, + default_timeout: 1800 # 30 minutes + ) + + ibc = Synor::Ibc::Client.new(config) + example = IbcExample.new(ibc) + + begin + # Check service health + healthy = ibc.health_check + puts "Service healthy: #{healthy}\n\n" + + # Run examples + example.run_chains_example + example.run_channels_example + example.run_transfer_example + example.run_packet_example + example.run_relayer_example + example.run_monitoring_example + rescue StandardError => e + warn "Error: #{e.message}" + exit 1 + end +end diff --git a/sdk/ruby/examples/zk_example.rb b/sdk/ruby/examples/zk_example.rb new file mode 100644 index 0000000..dcade2e --- /dev/null +++ b/sdk/ruby/examples/zk_example.rb @@ -0,0 +1,345 @@ +# frozen_string_literal: true + +# +# Synor ZK SDK Examples for Ruby +# +# Demonstrates zero-knowledge proof operations: +# - Circuit compilation (Circom) +# - Proof generation and verification +# - Multiple proving systems (Groth16, PLONK, STARK) +# - Recursive proof composition +# - Trusted setup ceremonies +# + +require 'securerandom' +require 'synor/zk' + +class ZkExample + def initialize(zk) + @zk = zk + end + + def run_circuit_example + puts '=== Circuit Compilation ===' + + # Simple Circom circuit: prove knowledge of factors + circom_code = <<~CIRCOM + pragma circom 2.1.0; + + template Multiplier() { + signal input a; + signal input b; + signal output c; + + c <== a * b; + } + + component main = Multiplier(); + CIRCOM + + # Compile the circuit + puts 'Compiling circuit...' + circuit = @zk.circuits.compile( + code: circom_code, + language: :circom + ) + + puts 'Circuit compiled:' + puts " Circuit ID: #{circuit.circuit_id}" + puts " Constraints: #{circuit.constraints}" + puts " Public inputs: #{circuit.public_inputs}" + puts " Private inputs: #{circuit.private_inputs}" + puts " Outputs: #{circuit.outputs}" + + # Get circuit info + info = @zk.circuits.get(circuit.circuit_id) + puts "\nCircuit info:" + puts " Name: #{info.name}" + puts " Version: #{info.version}" + puts " Wires: #{info.wire_count}" + puts " Labels: #{info.label_count}" + + # List available circuits + circuits = @zk.circuits.list + puts "\nAvailable circuits: #{circuits.length}" + circuits.first(3).each do |c| + puts " #{c.circuit_id}: #{c.name} (#{c.constraints} constraints)" + end + puts + end + + def run_groth16_example + puts '=== Groth16 Proving System ===' + + circuit_id = 'multiplier-v1' + + # Generate proving/verification keys (trusted setup) + puts 'Generating keys...' + keys = @zk.groth16.setup(circuit_id) + puts 'Keys generated:' + puts " Proving key size: #{keys.proving_key.length} bytes" + puts " Verification key size: #{keys.verification_key.length} bytes" + + # Prepare witness (private inputs) + witness = { 'a' => '3', 'b' => '7' } + + # Generate proof + puts "\nGenerating proof..." + proof = @zk.groth16.prove( + circuit_id: circuit_id, + witness: witness, + proving_key: keys.proving_key + ) + + puts 'Proof generated:' + puts " Proof size: #{proof.proof_bytes.length} bytes" + puts " Public signals: #{proof.public_signals.length}" + puts " Proving time: #{proof.proving_time_ms}ms" + + # Verify proof + puts "\nVerifying proof..." + verified = @zk.groth16.verify( + proof: proof.proof_bytes, + public_signals: proof.public_signals, + verification_key: keys.verification_key + ) + + puts "Verification result: #{verified}" + + # Export proof for on-chain verification + solidity_calldata = @zk.groth16.export_calldata(proof) + puts "\nSolidity calldata: #{solidity_calldata[0, 100]}..." + puts + end + + def run_plonk_example + puts '=== PLONK Proving System ===' + + circuit_id = 'multiplier-v1' + + # PLONK uses universal trusted setup + puts 'Getting universal setup...' + srs = @zk.plonk.get_universal_setup(14) # 2^14 constraints + puts "SRS loaded: #{srs.length} bytes" + + # Generate circuit-specific keys + puts "\nGenerating circuit keys..." + keys = @zk.plonk.setup(circuit_id, srs) + puts 'Keys generated' + + # Generate proof + witness = { 'a' => '5', 'b' => '9' } + puts "\nGenerating PLONK proof..." + proof = @zk.plonk.prove( + circuit_id: circuit_id, + witness: witness, + proving_key: keys.proving_key + ) + + puts 'Proof generated:' + puts " Proof size: #{proof.proof_bytes.length} bytes" + puts " Proving time: #{proof.proving_time_ms}ms" + + # Verify proof + verified = @zk.plonk.verify( + proof: proof.proof_bytes, + public_signals: proof.public_signals, + verification_key: keys.verification_key + ) + puts "Verification result: #{verified}" + + # Compare with Groth16 + puts "\nPLONK advantages:" + puts ' - Universal trusted setup' + puts ' - Larger proofs (~2.5 KB vs ~200 bytes)' + puts ' - Faster proving for some circuits' + puts + end + + def run_stark_example + puts '=== STARK Proving System ===' + + circuit_id = 'multiplier-v1' + + # STARKs don't need trusted setup + puts 'Configuring STARK parameters...' + config = { + field_size: 256, + hash_function: :poseidon, + blowup_factor: 8, + num_queries: 30, + folding_factor: 8 + } + + # Generate proof + witness = { 'a' => '11', 'b' => '13' } + puts "\nGenerating STARK proof..." + proof = @zk.stark.prove( + circuit_id: circuit_id, + witness: witness, + config: config + ) + + puts 'Proof generated:' + puts " Proof size: #{proof.proof_bytes.length} bytes" + puts " Proving time: #{proof.proving_time_ms}ms" + puts " FRI layers: #{proof.fri_layers}" + + # Verify proof + puts "\nVerifying STARK proof..." + verified = @zk.stark.verify( + proof: proof.proof_bytes, + public_signals: proof.public_signals, + config: config + ) + + puts "Verification result: #{verified}" + + # Compare with SNARKs + puts "\nSTARK advantages:" + puts ' - No trusted setup needed' + puts ' - Post-quantum secure' + puts ' - Larger proofs (~100 KB)' + puts ' - Faster proving for complex computations' + puts + end + + def run_recursive_example + puts '=== Recursive Proof Composition ===' + + # Create inner proofs + puts 'Generating inner proofs...' + inner_proofs = [] + + (1..3).each do |i| + witness = { 'a' => i.to_s, 'b' => (i + 1).to_s } + + proof = @zk.recursive.prove_inner( + circuit_id: 'multiplier-v1', + witness: witness, + level: 0 + ) + inner_proofs << proof + puts " Inner proof #{i} generated" + end + + # Aggregate proofs recursively + puts "\nAggregating proofs..." + aggregated_proof = @zk.recursive.aggregate( + proofs: inner_proofs, + aggregation_circuit: 'recursive-aggregator-v1' + ) + + puts 'Aggregated proof:' + puts " Proof size: #{aggregated_proof.proof_bytes.length} bytes" + puts " Proofs aggregated: #{aggregated_proof.proofs_aggregated}" + puts " Recursion depth: #{aggregated_proof.recursion_depth}" + + # Verify aggregated proof (verifies all inner proofs at once) + puts "\nVerifying aggregated proof..." + verified = @zk.recursive.verify_aggregated(aggregated_proof) + puts "Verification result: #{verified}" + + # Use cases + puts "\nRecursive proof use cases:" + puts ' - Rollup batch verification' + puts ' - Incremental computation proofs' + puts ' - Cross-chain state proofs' + puts + end + + def run_ceremony_example + puts '=== Trusted Setup Ceremony ===' + + # List active ceremonies + ceremonies = @zk.ceremony.list(:active) + puts "Active ceremonies: #{ceremonies.length}" + + ceremonies.first(3).each do |ceremony| + puts "\n #{ceremony.ceremony_id}:" + puts " Circuit: #{ceremony.circuit_id}" + puts " Participants: #{ceremony.participant_count}" + puts " Current round: #{ceremony.current_round}" + puts " Status: #{ceremony.status}" + end + + # Create a new ceremony + puts "\nCreating new ceremony..." + new_ceremony = @zk.ceremony.create( + circuit_id: 'new-circuit-v1', + min_participants: 10, + max_participants: 100, + round_duration: 3600, # 1 hour per round + verify_contributions: true + ) + + puts 'Ceremony created:' + puts " Ceremony ID: #{new_ceremony.ceremony_id}" + puts " Join URL: #{new_ceremony.join_url}" + + # Participate in a ceremony + puts "\nParticipating in ceremony..." + + # Generate entropy + entropy = SecureRandom.random_bytes(32) + + contribution = @zk.ceremony.contribute( + ceremony_id: new_ceremony.ceremony_id, + entropy: entropy + ) + + puts 'Contribution made:' + puts " Contribution ID: #{contribution.contribution_id}" + puts " Position: #{contribution.position}" + puts " Hash: #{contribution.hash}" + + # Verify a contribution + puts "\nVerifying contribution..." + valid = @zk.ceremony.verify_contribution(contribution.contribution_id) + puts "Contribution valid: #{valid}" + + # Get ceremony transcript (for auditability) + transcript = @zk.ceremony.get_transcript(new_ceremony.ceremony_id) + puts "\nCeremony transcript:" + puts " Total contributions: #{transcript.contributions.length}" + puts " Start time: #{transcript.start_time}" + puts " Final hash: #{transcript.final_hash.empty? ? 'pending' : transcript.final_hash}" + puts + end +end + +# Main execution +if __FILE__ == $PROGRAM_NAME + # Initialize client + api_key = ENV.fetch('SYNOR_API_KEY', 'your-api-key') + config = Synor::Zk::Config.new( + api_key: api_key, + endpoint: 'https://zk.synor.io/v1', + timeout: 120, # ZK operations can be slow + retries: 3, + debug: false, + default_proving_system: :groth16, + prove_timeout: 300, + verify_timeout: 30 + ) + + zk = Synor::Zk::Client.new(config) + example = ZkExample.new(zk) + + begin + # Check service health + healthy = zk.health_check + puts "Service healthy: #{healthy}\n\n" + + # Run examples + example.run_circuit_example + example.run_groth16_example + example.run_plonk_example + example.run_stark_example + example.run_recursive_example + example.run_ceremony_example + rescue StandardError => e + warn "Error: #{e.message}" + exit 1 + end +end