Add Swift examples for Synor DEX, IBC, and ZK SDKs
- Introduced DexExample.swift demonstrating decentralized exchange operations including spot trading, perpetual futures, liquidity provision, order book management, and portfolio tracking. - Added IbcExample.swift showcasing inter-blockchain communication operations such as cross-chain transfers, channel management, packet handling, and relayer operations. - Created ZkExample.swift illustrating zero-knowledge proof operations including circuit compilation, proof generation and verification, and trusted setup ceremonies.
This commit is contained in:
parent
9416d76108
commit
e169c492aa
15 changed files with 5430 additions and 0 deletions
391
sdk/c/examples/crypto_example.c
Normal file
391
sdk/c/examples/crypto_example.c
Normal file
|
|
@ -0,0 +1,391 @@
|
||||||
|
/**
|
||||||
|
* 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 <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <synor/crypto.h>
|
||||||
|
|
||||||
|
// Helper function to print hex
|
||||||
|
void print_hex(const uint8_t* data, size_t len, size_t max_len) {
|
||||||
|
size_t print_len = len < max_len ? len : max_len;
|
||||||
|
for (size_t i = 0; i < print_len; i++) {
|
||||||
|
printf("%02x", data[i]);
|
||||||
|
}
|
||||||
|
if (len > max_len) {
|
||||||
|
printf("...");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void mnemonic_example(synor_crypto_t* crypto) {
|
||||||
|
printf("=== Mnemonic Operations ===\n");
|
||||||
|
|
||||||
|
synor_error_t err;
|
||||||
|
synor_mnemonic_t* mnemonic = NULL;
|
||||||
|
|
||||||
|
// Generate a 24-word mnemonic (256-bit entropy)
|
||||||
|
err = synor_mnemonic_generate(crypto, 24, &mnemonic);
|
||||||
|
if (err != SYNOR_OK) {
|
||||||
|
fprintf(stderr, "Failed to generate mnemonic: %s\n", synor_error_string(err));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Generated mnemonic: %s\n", synor_mnemonic_get_phrase(mnemonic));
|
||||||
|
printf("Word count: %d\n", synor_mnemonic_get_word_count(mnemonic));
|
||||||
|
|
||||||
|
// Validate a mnemonic
|
||||||
|
synor_validation_result_t validation;
|
||||||
|
err = synor_mnemonic_validate(crypto, synor_mnemonic_get_phrase(mnemonic), &validation);
|
||||||
|
if (err == SYNOR_OK) {
|
||||||
|
printf("Valid: %s\n", validation.is_valid ? "true" : "false");
|
||||||
|
if (!validation.is_valid && validation.error) {
|
||||||
|
printf("Error: %s\n", validation.error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert mnemonic to seed
|
||||||
|
uint8_t seed[64];
|
||||||
|
size_t seed_len;
|
||||||
|
err = synor_mnemonic_to_seed(crypto, synor_mnemonic_get_phrase(mnemonic),
|
||||||
|
"optional-passphrase", seed, &seed_len);
|
||||||
|
if (err == SYNOR_OK) {
|
||||||
|
printf("Seed (hex): ");
|
||||||
|
print_hex(seed, seed_len, 16);
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Word suggestions for autocomplete
|
||||||
|
char** suggestions;
|
||||||
|
size_t suggestion_count;
|
||||||
|
err = synor_mnemonic_suggest_words(crypto, "aban", 5, &suggestions, &suggestion_count);
|
||||||
|
if (err == SYNOR_OK) {
|
||||||
|
printf("Suggestions for 'aban': ");
|
||||||
|
for (size_t i = 0; i < suggestion_count; i++) {
|
||||||
|
printf("%s%s", suggestions[i], i < suggestion_count - 1 ? ", " : "");
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
synor_string_array_free(suggestions, suggestion_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
synor_mnemonic_free(mnemonic);
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void keypair_example(synor_crypto_t* crypto) {
|
||||||
|
printf("=== Keypair Operations ===\n");
|
||||||
|
|
||||||
|
synor_error_t err;
|
||||||
|
synor_hybrid_keypair_t* keypair = NULL;
|
||||||
|
|
||||||
|
// Generate a random keypair
|
||||||
|
err = synor_keypair_generate(crypto, &keypair);
|
||||||
|
if (err != SYNOR_OK) {
|
||||||
|
fprintf(stderr, "Failed to generate keypair: %s\n", synor_error_string(err));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Generated hybrid keypair:\n");
|
||||||
|
printf(" Ed25519 public key size: %zu bytes\n",
|
||||||
|
synor_keypair_get_ed25519_pubkey_size(keypair));
|
||||||
|
printf(" Dilithium public key size: %zu bytes\n",
|
||||||
|
synor_keypair_get_dilithium_pubkey_size(keypair));
|
||||||
|
printf(" Total public key size: %zu bytes\n",
|
||||||
|
synor_keypair_get_pubkey_size(keypair));
|
||||||
|
|
||||||
|
// Get addresses for different networks
|
||||||
|
char address[128];
|
||||||
|
printf("\nAddresses:\n");
|
||||||
|
|
||||||
|
synor_keypair_get_address(keypair, SYNOR_NETWORK_MAINNET, address, sizeof(address));
|
||||||
|
printf(" Mainnet: %s\n", address);
|
||||||
|
|
||||||
|
synor_keypair_get_address(keypair, SYNOR_NETWORK_TESTNET, address, sizeof(address));
|
||||||
|
printf(" Testnet: %s\n", address);
|
||||||
|
|
||||||
|
synor_keypair_get_address(keypair, SYNOR_NETWORK_DEVNET, address, sizeof(address));
|
||||||
|
printf(" Devnet: %s\n", address);
|
||||||
|
|
||||||
|
// Create keypair from mnemonic (deterministic)
|
||||||
|
synor_mnemonic_t* mnemonic = NULL;
|
||||||
|
synor_mnemonic_generate(crypto, 24, &mnemonic);
|
||||||
|
|
||||||
|
synor_hybrid_keypair_t* keypair2 = NULL;
|
||||||
|
err = synor_keypair_from_mnemonic(crypto, synor_mnemonic_get_phrase(mnemonic), "", &keypair2);
|
||||||
|
if (err == SYNOR_OK) {
|
||||||
|
synor_keypair_get_address(keypair2, SYNOR_NETWORK_MAINNET, address, sizeof(address));
|
||||||
|
printf("\nKeypair from mnemonic: %.20s...\n", address);
|
||||||
|
synor_keypair_free(keypair2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Derive child keypair using BIP-44 path
|
||||||
|
printf("Derivation path: m/44'/21337'/0'/0/0\n");
|
||||||
|
|
||||||
|
synor_mnemonic_free(mnemonic);
|
||||||
|
synor_keypair_free(keypair);
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void signing_example(synor_crypto_t* crypto) {
|
||||||
|
printf("=== Hybrid Signing ===\n");
|
||||||
|
|
||||||
|
synor_error_t err;
|
||||||
|
synor_hybrid_keypair_t* keypair = NULL;
|
||||||
|
|
||||||
|
// Generate keypair
|
||||||
|
err = synor_keypair_generate(crypto, &keypair);
|
||||||
|
if (err != SYNOR_OK) {
|
||||||
|
fprintf(stderr, "Failed to generate keypair\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sign a message
|
||||||
|
const char* message = "Hello, quantum-resistant world!";
|
||||||
|
synor_hybrid_signature_t* signature = NULL;
|
||||||
|
|
||||||
|
err = synor_sign(crypto, keypair, (const uint8_t*)message, strlen(message), &signature);
|
||||||
|
if (err != SYNOR_OK) {
|
||||||
|
fprintf(stderr, "Failed to sign message\n");
|
||||||
|
synor_keypair_free(keypair);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Signature created:\n");
|
||||||
|
printf(" Ed25519 component: %zu bytes\n", synor_signature_get_ed25519_size(signature));
|
||||||
|
printf(" Dilithium component: %zu bytes\n", synor_signature_get_dilithium_size(signature));
|
||||||
|
printf(" Total signature size: %zu bytes\n", synor_signature_get_size(signature));
|
||||||
|
|
||||||
|
// Verify the signature
|
||||||
|
bool valid;
|
||||||
|
err = synor_verify(crypto, keypair, (const uint8_t*)message, strlen(message), signature, &valid);
|
||||||
|
printf("\nVerification result: %s\n", valid ? "true" : "false");
|
||||||
|
|
||||||
|
// Verify with tampered message fails
|
||||||
|
const char* tampered = "Hello, tampered message!";
|
||||||
|
err = synor_verify(crypto, keypair, (const uint8_t*)tampered, strlen(tampered), signature, &valid);
|
||||||
|
printf("Tampered message verification: %s\n", valid ? "true" : "false");
|
||||||
|
|
||||||
|
synor_signature_free(signature);
|
||||||
|
synor_keypair_free(keypair);
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void falcon_example(synor_crypto_t* crypto) {
|
||||||
|
printf("=== Falcon Post-Quantum Signatures ===\n");
|
||||||
|
|
||||||
|
synor_error_t err;
|
||||||
|
|
||||||
|
// Generate Falcon-512 keypair (128-bit security)
|
||||||
|
synor_falcon_keypair_t* falcon512 = NULL;
|
||||||
|
err = synor_falcon_generate(crypto, SYNOR_FALCON_512, &falcon512);
|
||||||
|
if (err == SYNOR_OK) {
|
||||||
|
printf("Falcon-512 keypair:\n");
|
||||||
|
printf(" Public key: %zu bytes\n", synor_falcon_get_pubkey_size(falcon512));
|
||||||
|
printf(" Security level: 128-bit\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate Falcon-1024 keypair (256-bit security)
|
||||||
|
synor_falcon_keypair_t* falcon1024 = NULL;
|
||||||
|
err = synor_falcon_generate(crypto, SYNOR_FALCON_1024, &falcon1024);
|
||||||
|
if (err == SYNOR_OK) {
|
||||||
|
printf("\nFalcon-1024 keypair:\n");
|
||||||
|
printf(" Public key: %zu bytes\n", synor_falcon_get_pubkey_size(falcon1024));
|
||||||
|
printf(" Security level: 256-bit\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sign with Falcon-512
|
||||||
|
const char* message = "Post-quantum secure message";
|
||||||
|
synor_falcon_signature_t* signature = NULL;
|
||||||
|
|
||||||
|
err = synor_falcon_sign(crypto, falcon512, (const uint8_t*)message, strlen(message), &signature);
|
||||||
|
if (err == SYNOR_OK) {
|
||||||
|
printf("\nFalcon-512 signature: %zu bytes\n", synor_falcon_signature_size(signature));
|
||||||
|
|
||||||
|
// Verify
|
||||||
|
bool valid;
|
||||||
|
err = synor_falcon_verify(crypto, falcon512, (const uint8_t*)message, strlen(message),
|
||||||
|
signature, &valid);
|
||||||
|
printf("Verification: %s\n", valid ? "true" : "false");
|
||||||
|
synor_falcon_signature_free(signature);
|
||||||
|
}
|
||||||
|
|
||||||
|
synor_falcon_keypair_free(falcon512);
|
||||||
|
synor_falcon_keypair_free(falcon1024);
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void sphincs_example(synor_crypto_t* crypto) {
|
||||||
|
printf("=== SPHINCS+ Hash-Based Signatures ===\n");
|
||||||
|
|
||||||
|
synor_error_t err;
|
||||||
|
|
||||||
|
// SPHINCS+ variants with different security levels
|
||||||
|
struct {
|
||||||
|
synor_sphincs_variant_t variant;
|
||||||
|
int security;
|
||||||
|
int sig_size;
|
||||||
|
const char* name;
|
||||||
|
} variants[] = {
|
||||||
|
{SYNOR_SPHINCS_SHAKE128S, 128, 7856, "SHAKE128S"},
|
||||||
|
{SYNOR_SPHINCS_SHAKE192S, 192, 16224, "SHAKE192S"},
|
||||||
|
{SYNOR_SPHINCS_SHAKE256S, 256, 29792, "SHAKE256S"},
|
||||||
|
};
|
||||||
|
|
||||||
|
const char* message = "Hash-based quantum security";
|
||||||
|
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
synor_sphincs_keypair_t* keypair = NULL;
|
||||||
|
err = synor_sphincs_generate(crypto, variants[i].variant, &keypair);
|
||||||
|
if (err != SYNOR_OK) continue;
|
||||||
|
|
||||||
|
printf("SPHINCS+ %s:\n", variants[i].name);
|
||||||
|
printf(" Security level: %d-bit\n", variants[i].security);
|
||||||
|
printf(" Expected signature size: %d bytes\n", variants[i].sig_size);
|
||||||
|
|
||||||
|
// Sign a message
|
||||||
|
synor_sphincs_signature_t* signature = NULL;
|
||||||
|
err = synor_sphincs_sign(crypto, keypair, (const uint8_t*)message, strlen(message), &signature);
|
||||||
|
if (err == SYNOR_OK) {
|
||||||
|
printf(" Actual signature size: %zu bytes\n", synor_sphincs_signature_size(signature));
|
||||||
|
|
||||||
|
// Verify
|
||||||
|
bool valid;
|
||||||
|
synor_sphincs_verify(crypto, keypair, (const uint8_t*)message, strlen(message),
|
||||||
|
signature, &valid);
|
||||||
|
printf(" Verification: %s\n\n", valid ? "true" : "false");
|
||||||
|
synor_sphincs_signature_free(signature);
|
||||||
|
}
|
||||||
|
|
||||||
|
synor_sphincs_keypair_free(keypair);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void kdf_example(synor_crypto_t* crypto) {
|
||||||
|
printf("=== Key Derivation Functions ===\n");
|
||||||
|
|
||||||
|
synor_error_t err;
|
||||||
|
|
||||||
|
// HKDF (HMAC-based Key Derivation Function)
|
||||||
|
const char* seed = "master-secret-key-material-here";
|
||||||
|
const char* salt = "application-salt";
|
||||||
|
const char* info = "encryption-key";
|
||||||
|
|
||||||
|
uint8_t derived_key[32];
|
||||||
|
synor_derivation_config_t hkdf_config = {
|
||||||
|
.salt = (const uint8_t*)salt,
|
||||||
|
.salt_len = strlen(salt),
|
||||||
|
.info = (const uint8_t*)info,
|
||||||
|
.info_len = strlen(info),
|
||||||
|
.output_length = 32
|
||||||
|
};
|
||||||
|
|
||||||
|
err = synor_kdf_derive(crypto, (const uint8_t*)seed, strlen(seed), &hkdf_config,
|
||||||
|
derived_key, sizeof(derived_key));
|
||||||
|
if (err == SYNOR_OK) {
|
||||||
|
printf("HKDF derived key: ");
|
||||||
|
print_hex(derived_key, 32, 32);
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// PBKDF2 (Password-Based Key Derivation Function)
|
||||||
|
const char* password = "user-password";
|
||||||
|
const char* pbkdf2_salt = "random-salt-value";
|
||||||
|
|
||||||
|
uint8_t password_key[32];
|
||||||
|
synor_password_config_t pbkdf2_config = {
|
||||||
|
.salt = (const uint8_t*)pbkdf2_salt,
|
||||||
|
.salt_len = strlen(pbkdf2_salt),
|
||||||
|
.iterations = 100000,
|
||||||
|
.output_length = 32
|
||||||
|
};
|
||||||
|
|
||||||
|
err = synor_kdf_derive_password(crypto, (const uint8_t*)password, strlen(password),
|
||||||
|
&pbkdf2_config, password_key, sizeof(password_key));
|
||||||
|
if (err == SYNOR_OK) {
|
||||||
|
printf("PBKDF2 derived key: ");
|
||||||
|
print_hex(password_key, 32, 32);
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void hash_example(synor_crypto_t* crypto) {
|
||||||
|
printf("=== Hash Functions ===\n");
|
||||||
|
|
||||||
|
synor_error_t err;
|
||||||
|
const char* data = "Data to hash";
|
||||||
|
uint8_t hash[32];
|
||||||
|
|
||||||
|
// SHA3-256 (FIPS 202)
|
||||||
|
err = synor_hash_sha3_256(crypto, (const uint8_t*)data, strlen(data), hash);
|
||||||
|
if (err == SYNOR_OK) {
|
||||||
|
printf("SHA3-256: ");
|
||||||
|
print_hex(hash, 32, 32);
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// BLAKE3 (fast, parallel)
|
||||||
|
err = synor_hash_blake3(crypto, (const uint8_t*)data, strlen(data), hash);
|
||||||
|
if (err == SYNOR_OK) {
|
||||||
|
printf("BLAKE3: ");
|
||||||
|
print_hex(hash, 32, 32);
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keccak-256 (Ethereum compatible)
|
||||||
|
err = synor_hash_keccak256(crypto, (const uint8_t*)data, strlen(data), hash);
|
||||||
|
if (err == SYNOR_OK) {
|
||||||
|
printf("Keccak: ");
|
||||||
|
print_hex(hash, 32, 32);
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
synor_error_t err;
|
||||||
|
|
||||||
|
// Initialize client
|
||||||
|
synor_crypto_config_t config = {
|
||||||
|
.api_key = getenv("SYNOR_API_KEY") ? getenv("SYNOR_API_KEY") : "your-api-key",
|
||||||
|
.endpoint = "https://crypto.synor.io/v1",
|
||||||
|
.timeout_ms = 30000,
|
||||||
|
.retries = 3,
|
||||||
|
.debug = false,
|
||||||
|
.default_network = SYNOR_NETWORK_MAINNET
|
||||||
|
};
|
||||||
|
|
||||||
|
synor_crypto_t* crypto = NULL;
|
||||||
|
err = synor_crypto_init(&config, &crypto);
|
||||||
|
if (err != SYNOR_OK) {
|
||||||
|
fprintf(stderr, "Failed to initialize crypto client: %s\n", synor_error_string(err));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check service health
|
||||||
|
bool healthy;
|
||||||
|
err = synor_crypto_health_check(crypto, &healthy);
|
||||||
|
printf("Service healthy: %s\n\n", healthy ? "true" : "false");
|
||||||
|
|
||||||
|
// Run examples
|
||||||
|
mnemonic_example(crypto);
|
||||||
|
keypair_example(crypto);
|
||||||
|
signing_example(crypto);
|
||||||
|
falcon_example(crypto);
|
||||||
|
sphincs_example(crypto);
|
||||||
|
kdf_example(crypto);
|
||||||
|
hash_example(crypto);
|
||||||
|
|
||||||
|
// Cleanup
|
||||||
|
synor_crypto_free(crypto);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
399
sdk/java/examples/CompilerExample.java
Normal file
399
sdk/java/examples/CompilerExample.java
Normal file
|
|
@ -0,0 +1,399 @@
|
||||||
|
package io.synor.examples;
|
||||||
|
|
||||||
|
import io.synor.compiler.*;
|
||||||
|
import io.synor.compiler.types.*;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Synor Compiler SDK Examples for Java
|
||||||
|
*
|
||||||
|
* Demonstrates smart contract compilation and analysis:
|
||||||
|
* - WASM contract compilation and optimization
|
||||||
|
* - ABI extraction and encoding
|
||||||
|
* - Contract analysis and security scanning
|
||||||
|
* - Validation and verification
|
||||||
|
*/
|
||||||
|
public class CompilerExample {
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
// Initialize client
|
||||||
|
CompilerConfig config = CompilerConfig.builder()
|
||||||
|
.apiKey(System.getenv("SYNOR_API_KEY") != null ?
|
||||||
|
System.getenv("SYNOR_API_KEY") : "your-api-key")
|
||||||
|
.endpoint("https://compiler.synor.io/v1")
|
||||||
|
.timeout(60000)
|
||||||
|
.retries(3)
|
||||||
|
.debug(false)
|
||||||
|
.defaultOptimizationLevel(OptimizationLevel.SIZE)
|
||||||
|
.maxContractSize(256 * 1024)
|
||||||
|
.useWasmOpt(true)
|
||||||
|
.validate(true)
|
||||||
|
.extractMetadata(true)
|
||||||
|
.generateAbi(true)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
SynorCompiler compiler = new SynorCompiler(config);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Check service health
|
||||||
|
boolean healthy = compiler.healthCheck().get();
|
||||||
|
System.out.println("Service healthy: " + healthy + "\n");
|
||||||
|
|
||||||
|
// Run examples
|
||||||
|
compileContractExample(compiler);
|
||||||
|
compilationModesExample(compiler);
|
||||||
|
abiExample(compiler);
|
||||||
|
analysisExample(compiler);
|
||||||
|
validationExample(compiler);
|
||||||
|
securityExample(compiler);
|
||||||
|
} finally {
|
||||||
|
compiler.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a minimal valid WASM module for testing.
|
||||||
|
*/
|
||||||
|
static byte[] createMinimalWasm() {
|
||||||
|
return new byte[] {
|
||||||
|
0x00, 0x61, 0x73, 0x6d, // Magic: \0asm
|
||||||
|
0x01, 0x00, 0x00, 0x00, // Version: 1
|
||||||
|
// Type section
|
||||||
|
0x01, 0x07, 0x01, 0x60, 0x02, 0x7f, 0x7f, 0x01, 0x7f,
|
||||||
|
// Function section
|
||||||
|
0x03, 0x02, 0x01, 0x00,
|
||||||
|
// Export section
|
||||||
|
0x07, 0x08, 0x01, 0x04, 0x61, 0x64, 0x64, 0x00, 0x00,
|
||||||
|
// Code section
|
||||||
|
0x0a, 0x09, 0x01, 0x07, 0x00, 0x20, 0x00, 0x20, 0x01, 0x6a, 0x0b
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static void compileContractExample(SynorCompiler compiler) throws Exception {
|
||||||
|
System.out.println("=== Contract Compilation ===");
|
||||||
|
|
||||||
|
byte[] wasm = createMinimalWasm();
|
||||||
|
|
||||||
|
CompileResult result = compiler.compile(wasm, CompileOptions.builder()
|
||||||
|
.optimizationLevel(OptimizationLevel.SIZE)
|
||||||
|
.useWasmOpt(true)
|
||||||
|
.validate(true)
|
||||||
|
.extractMetadata(true)
|
||||||
|
.generateAbi(true)
|
||||||
|
.stripOptions(StripOptions.builder()
|
||||||
|
.stripDebug(true)
|
||||||
|
.stripProducers(true)
|
||||||
|
.stripNames(true)
|
||||||
|
.stripCustom(true)
|
||||||
|
.stripUnused(true)
|
||||||
|
.preserveSections(List.of())
|
||||||
|
.build())
|
||||||
|
.build()).get();
|
||||||
|
|
||||||
|
System.out.println("Compilation result:");
|
||||||
|
System.out.println(" Contract ID: " + result.getContractId());
|
||||||
|
System.out.println(" Code hash: " + result.getCodeHash());
|
||||||
|
System.out.println(" Original size: " + result.getOriginalSize() + " bytes");
|
||||||
|
System.out.println(" Optimized size: " + result.getOptimizedSize() + " bytes");
|
||||||
|
System.out.println(" Size reduction: " + String.format("%.1f", result.getSizeReduction()) + "%");
|
||||||
|
System.out.println(" Estimated deploy gas: " + result.getEstimatedDeployGas());
|
||||||
|
|
||||||
|
if (result.getMetadata() != null) {
|
||||||
|
System.out.println("\nMetadata:");
|
||||||
|
System.out.println(" Name: " + result.getMetadata().getName());
|
||||||
|
System.out.println(" Version: " + result.getMetadata().getVersion());
|
||||||
|
System.out.println(" SDK Version: " + result.getMetadata().getSdkVersion());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.getAbi() != null) {
|
||||||
|
System.out.println("\nABI:");
|
||||||
|
System.out.println(" Functions: " + (result.getAbi().getFunctions() != null ?
|
||||||
|
result.getAbi().getFunctions().size() : 0));
|
||||||
|
System.out.println(" Events: " + (result.getAbi().getEvents() != null ?
|
||||||
|
result.getAbi().getEvents().size() : 0));
|
||||||
|
System.out.println(" Errors: " + (result.getAbi().getErrors() != null ?
|
||||||
|
result.getAbi().getErrors().size() : 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void compilationModesExample(SynorCompiler compiler) throws Exception {
|
||||||
|
System.out.println("=== Compilation Modes ===");
|
||||||
|
|
||||||
|
byte[] wasm = createMinimalWasm();
|
||||||
|
|
||||||
|
// Development mode: fast compilation, debugging support
|
||||||
|
System.out.println("Development mode:");
|
||||||
|
CompileResult devResult = compiler.contracts().compileDev(wasm).get();
|
||||||
|
System.out.println(" Size: " + devResult.getOptimizedSize() + " bytes");
|
||||||
|
System.out.println(" Optimization: none");
|
||||||
|
|
||||||
|
// Production mode: maximum optimization
|
||||||
|
System.out.println("\nProduction mode:");
|
||||||
|
CompileResult prodResult = compiler.contracts().compileProduction(wasm).get();
|
||||||
|
System.out.println(" Size: " + prodResult.getOptimizedSize() + " bytes");
|
||||||
|
System.out.println(" Optimization: aggressive");
|
||||||
|
System.out.println(" Size savings: " + (devResult.getOptimizedSize() - prodResult.getOptimizedSize()) + " bytes");
|
||||||
|
|
||||||
|
// Custom optimization levels
|
||||||
|
System.out.println("\nOptimization levels:");
|
||||||
|
OptimizationLevel[] levels = {
|
||||||
|
OptimizationLevel.NONE,
|
||||||
|
OptimizationLevel.BASIC,
|
||||||
|
OptimizationLevel.SIZE,
|
||||||
|
OptimizationLevel.AGGRESSIVE
|
||||||
|
};
|
||||||
|
|
||||||
|
for (OptimizationLevel level : levels) {
|
||||||
|
CompileResult result = compiler.compile(wasm, CompileOptions.builder()
|
||||||
|
.optimizationLevel(level)
|
||||||
|
.build()).get();
|
||||||
|
System.out.println(" " + level + ": " + result.getOptimizedSize() + " bytes");
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void abiExample(SynorCompiler compiler) throws Exception {
|
||||||
|
System.out.println("=== ABI Operations ===");
|
||||||
|
|
||||||
|
byte[] wasm = createMinimalWasm();
|
||||||
|
|
||||||
|
// Extract ABI from WASM
|
||||||
|
ContractAbi abi = compiler.abi().extract(wasm).get();
|
||||||
|
System.out.println("Contract: " + abi.getName());
|
||||||
|
System.out.println("Version: " + abi.getVersion());
|
||||||
|
|
||||||
|
// List functions
|
||||||
|
if (abi.getFunctions() != null && !abi.getFunctions().isEmpty()) {
|
||||||
|
System.out.println("\nFunctions:");
|
||||||
|
for (AbiFunction func : abi.getFunctions()) {
|
||||||
|
StringBuilder inputs = new StringBuilder();
|
||||||
|
if (func.getInputs() != null) {
|
||||||
|
for (int i = 0; i < func.getInputs().size(); i++) {
|
||||||
|
AbiParam param = func.getInputs().get(i);
|
||||||
|
if (i > 0) inputs.append(", ");
|
||||||
|
inputs.append(param.getName()).append(": ").append(param.getType().getTypeName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuilder outputs = new StringBuilder();
|
||||||
|
if (func.getOutputs() != null && !func.getOutputs().isEmpty()) {
|
||||||
|
for (int i = 0; i < func.getOutputs().size(); i++) {
|
||||||
|
if (i > 0) outputs.append(", ");
|
||||||
|
outputs.append(func.getOutputs().get(i).getType().getTypeName());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
outputs.append("void");
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuilder modifiers = new StringBuilder();
|
||||||
|
if (func.isView()) modifiers.append("view ");
|
||||||
|
if (func.isPayable()) modifiers.append("payable");
|
||||||
|
|
||||||
|
System.out.println(" " + func.getName() + "(" + inputs + ") -> " + outputs + " " + modifiers);
|
||||||
|
System.out.println(" Selector: " + func.getSelector());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// List events
|
||||||
|
if (abi.getEvents() != null && !abi.getEvents().isEmpty()) {
|
||||||
|
System.out.println("\nEvents:");
|
||||||
|
for (AbiEvent event : abi.getEvents()) {
|
||||||
|
StringBuilder params = new StringBuilder();
|
||||||
|
if (event.getParams() != null) {
|
||||||
|
for (int i = 0; i < event.getParams().size(); i++) {
|
||||||
|
AbiEventParam param = event.getParams().get(i);
|
||||||
|
if (i > 0) params.append(", ");
|
||||||
|
if (param.isIndexed()) params.append("indexed ");
|
||||||
|
params.append(param.getName()).append(": ").append(param.getType().getTypeName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
System.out.println(" " + event.getName() + "(" + params + ")");
|
||||||
|
System.out.println(" Topic: " + event.getTopic());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Encode a function call
|
||||||
|
if (abi.getFunctions() != null && !abi.getFunctions().isEmpty()) {
|
||||||
|
AbiFunction func = abi.getFunctions().get(0);
|
||||||
|
byte[] encoded = compiler.abi().encodeCall(func, List.of("arg1", "arg2")).get();
|
||||||
|
System.out.println("\nEncoded call to " + func.getName() + ": " + bytesToHex(encoded));
|
||||||
|
|
||||||
|
// Decode a result
|
||||||
|
Object decoded = compiler.abi().decodeResult(func, encoded).get();
|
||||||
|
System.out.println("Decoded result: " + decoded);
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void analysisExample(SynorCompiler compiler) throws Exception {
|
||||||
|
System.out.println("=== Contract Analysis ===");
|
||||||
|
|
||||||
|
byte[] wasm = createMinimalWasm();
|
||||||
|
|
||||||
|
// Full analysis
|
||||||
|
ContractAnalysis analysis = compiler.analysis().analyze(wasm).get();
|
||||||
|
|
||||||
|
// Size breakdown
|
||||||
|
if (analysis.getSizeBreakdown() != null) {
|
||||||
|
SizeBreakdown size = analysis.getSizeBreakdown();
|
||||||
|
System.out.println("Size breakdown:");
|
||||||
|
System.out.println(" Code: " + size.getCode() + " bytes");
|
||||||
|
System.out.println(" Data: " + size.getData() + " bytes");
|
||||||
|
System.out.println(" Functions: " + size.getFunctions() + " bytes");
|
||||||
|
System.out.println(" Memory: " + size.getMemory() + " bytes");
|
||||||
|
System.out.println(" Exports: " + size.getExports() + " bytes");
|
||||||
|
System.out.println(" Imports: " + size.getImports() + " bytes");
|
||||||
|
System.out.println(" Total: " + size.getTotal() + " bytes");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function analysis
|
||||||
|
if (analysis.getFunctions() != null && !analysis.getFunctions().isEmpty()) {
|
||||||
|
System.out.println("\nFunction analysis:");
|
||||||
|
for (FunctionAnalysis func : analysis.getFunctions().subList(0,
|
||||||
|
Math.min(5, analysis.getFunctions().size()))) {
|
||||||
|
System.out.println(" " + func.getName() + ":");
|
||||||
|
System.out.println(" Size: " + func.getSize() + " bytes");
|
||||||
|
System.out.println(" Instructions: " + func.getInstructionCount());
|
||||||
|
System.out.println(" Locals: " + func.getLocalCount());
|
||||||
|
System.out.println(" Exported: " + func.isExported());
|
||||||
|
System.out.println(" Estimated gas: " + func.getEstimatedGas());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Import analysis
|
||||||
|
if (analysis.getImports() != null && !analysis.getImports().isEmpty()) {
|
||||||
|
System.out.println("\nImports:");
|
||||||
|
for (ImportAnalysis imp : analysis.getImports()) {
|
||||||
|
System.out.println(" " + imp.getModule() + "." + imp.getName() + " (" + imp.getKind() + ")");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gas analysis
|
||||||
|
if (analysis.getGasAnalysis() != null) {
|
||||||
|
GasAnalysis gas = analysis.getGasAnalysis();
|
||||||
|
System.out.println("\nGas analysis:");
|
||||||
|
System.out.println(" Deployment: " + gas.getDeploymentGas());
|
||||||
|
System.out.println(" Memory init: " + gas.getMemoryInitGas());
|
||||||
|
System.out.println(" Data section: " + gas.getDataSectionGas());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract metadata
|
||||||
|
ContractMetadata metadata = compiler.analysis().extractMetadata(wasm).get();
|
||||||
|
System.out.println("\nContract metadata:");
|
||||||
|
System.out.println(" Name: " + metadata.getName());
|
||||||
|
System.out.println(" Version: " + metadata.getVersion());
|
||||||
|
System.out.println(" Build timestamp: " + metadata.getBuildTimestamp());
|
||||||
|
|
||||||
|
// Estimate deployment gas
|
||||||
|
long gasEstimate = compiler.analysis().estimateDeployGas(wasm).get();
|
||||||
|
System.out.println("\nEstimated deployment gas: " + gasEstimate);
|
||||||
|
|
||||||
|
System.out.println();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void validationExample(SynorCompiler compiler) throws Exception {
|
||||||
|
System.out.println("=== Contract Validation ===");
|
||||||
|
|
||||||
|
byte[] wasm = createMinimalWasm();
|
||||||
|
|
||||||
|
// Full validation
|
||||||
|
ValidationResult result = compiler.validation().validate(wasm).get();
|
||||||
|
System.out.println("Valid: " + result.isValid());
|
||||||
|
System.out.println("Exports: " + result.getExportCount());
|
||||||
|
System.out.println("Imports: " + result.getImportCount());
|
||||||
|
System.out.println("Functions: " + result.getFunctionCount());
|
||||||
|
System.out.println("Memory pages: " + result.getMemoryPages());
|
||||||
|
|
||||||
|
if (result.getErrors() != null && !result.getErrors().isEmpty()) {
|
||||||
|
System.out.println("\nValidation errors:");
|
||||||
|
for (ValidationError error : result.getErrors()) {
|
||||||
|
System.out.println(" [" + error.getCode() + "] " + error.getMessage());
|
||||||
|
if (error.getLocation() != null) {
|
||||||
|
System.out.println(" at " + error.getLocation());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.getWarnings() != null && !result.getWarnings().isEmpty()) {
|
||||||
|
System.out.println("\nWarnings:");
|
||||||
|
for (String warning : result.getWarnings()) {
|
||||||
|
System.out.println(" " + warning);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Quick validation
|
||||||
|
boolean isValid = compiler.validation().isValid(wasm).get();
|
||||||
|
System.out.println("\nQuick validation: " + isValid);
|
||||||
|
|
||||||
|
// Get validation errors only
|
||||||
|
List<ValidationError> errors = compiler.validation().getErrors(wasm).get();
|
||||||
|
System.out.println("Error count: " + errors.size());
|
||||||
|
|
||||||
|
// Validate required exports
|
||||||
|
boolean hasRequired = compiler.validation().validateExports(
|
||||||
|
wasm,
|
||||||
|
List.of("init", "execute", "query")
|
||||||
|
).get();
|
||||||
|
System.out.println("Has required exports: " + hasRequired);
|
||||||
|
|
||||||
|
// Validate memory constraints
|
||||||
|
boolean memoryValid = compiler.validation().validateMemory(wasm, 16).get();
|
||||||
|
System.out.println("Memory within 16 pages: " + memoryValid);
|
||||||
|
|
||||||
|
System.out.println();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void securityExample(SynorCompiler compiler) throws Exception {
|
||||||
|
System.out.println("=== Security Scanning ===");
|
||||||
|
|
||||||
|
byte[] wasm = createMinimalWasm();
|
||||||
|
|
||||||
|
SecurityScanResult security = compiler.analysis().securityScan(wasm).get();
|
||||||
|
|
||||||
|
System.out.println("Security score: " + security.getScore() + "/100");
|
||||||
|
|
||||||
|
if (security.getIssues() != null && !security.getIssues().isEmpty()) {
|
||||||
|
System.out.println("\nSecurity issues:");
|
||||||
|
for (SecurityIssue issue : security.getIssues()) {
|
||||||
|
String icon;
|
||||||
|
switch (issue.getSeverity().toLowerCase()) {
|
||||||
|
case "critical": icon = "[CRIT]"; break;
|
||||||
|
case "high": icon = "[HIGH]"; break;
|
||||||
|
case "medium": icon = "[MED]"; break;
|
||||||
|
case "low": icon = "[LOW]"; break;
|
||||||
|
default: icon = "[???]";
|
||||||
|
}
|
||||||
|
System.out.println(icon + " [" + issue.getSeverity().toUpperCase() + "] " + issue.getType());
|
||||||
|
System.out.println(" " + issue.getDescription());
|
||||||
|
if (issue.getLocation() != null) {
|
||||||
|
System.out.println(" at " + issue.getLocation());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
System.out.println("No security issues found!");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (security.getRecommendations() != null && !security.getRecommendations().isEmpty()) {
|
||||||
|
System.out.println("\nRecommendations:");
|
||||||
|
for (String rec : security.getRecommendations()) {
|
||||||
|
System.out.println(" • " + rec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String bytesToHex(byte[] bytes) {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (byte b : bytes) {
|
||||||
|
sb.append(String.format("%02x", b));
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
352
sdk/java/examples/DexExample.java
Normal file
352
sdk/java/examples/DexExample.java
Normal file
|
|
@ -0,0 +1,352 @@
|
||||||
|
package io.synor.examples;
|
||||||
|
|
||||||
|
import io.synor.dex.*;
|
||||||
|
import io.synor.dex.types.*;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Synor DEX SDK Examples for Java
|
||||||
|
*
|
||||||
|
* Demonstrates decentralized exchange operations:
|
||||||
|
* - Spot trading (limit/market orders)
|
||||||
|
* - Perpetual futures trading
|
||||||
|
* - Liquidity provision (AMM pools)
|
||||||
|
* - Order book management
|
||||||
|
* - Portfolio tracking
|
||||||
|
*/
|
||||||
|
public class DexExample {
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
// Initialize client
|
||||||
|
DexConfig config = DexConfig.builder()
|
||||||
|
.apiKey(System.getenv("SYNOR_API_KEY") != null ?
|
||||||
|
System.getenv("SYNOR_API_KEY") : "your-api-key")
|
||||||
|
.endpoint("https://dex.synor.io/v1")
|
||||||
|
.timeout(30000)
|
||||||
|
.retries(3)
|
||||||
|
.debug(false)
|
||||||
|
.defaultMarket("SYN-USDC")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
SynorDex dex = new SynorDex(config);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Check service health
|
||||||
|
boolean healthy = dex.healthCheck().get();
|
||||||
|
System.out.println("Service healthy: " + healthy + "\n");
|
||||||
|
|
||||||
|
// Run examples
|
||||||
|
marketsExample(dex);
|
||||||
|
spotTradingExample(dex);
|
||||||
|
perpsTradingExample(dex);
|
||||||
|
liquidityExample(dex);
|
||||||
|
orderbookExample(dex);
|
||||||
|
portfolioExample(dex);
|
||||||
|
} finally {
|
||||||
|
dex.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void marketsExample(SynorDex dex) throws Exception {
|
||||||
|
System.out.println("=== Markets ===");
|
||||||
|
|
||||||
|
// Get all markets
|
||||||
|
List<Market> markets = dex.markets().list().get();
|
||||||
|
System.out.println("Available markets: " + markets.size());
|
||||||
|
|
||||||
|
for (Market market : markets.subList(0, Math.min(5, markets.size()))) {
|
||||||
|
System.out.println("\n " + market.getSymbol() + ":");
|
||||||
|
System.out.println(" Base: " + market.getBaseAsset() + ", Quote: " + market.getQuoteAsset());
|
||||||
|
System.out.println(" Price: " + market.getLastPrice());
|
||||||
|
System.out.println(" 24h Volume: " + market.getVolume24h());
|
||||||
|
System.out.println(" 24h Change: " + market.getChange24h() + "%");
|
||||||
|
System.out.println(" Status: " + market.getStatus());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get specific market
|
||||||
|
Market market = dex.markets().get("SYN-USDC").get();
|
||||||
|
System.out.println("\nSYN-USDC details:");
|
||||||
|
System.out.println(" Min order size: " + market.getMinOrderSize());
|
||||||
|
System.out.println(" Tick size: " + market.getTickSize());
|
||||||
|
System.out.println(" Maker fee: " + market.getMakerFee() + "%");
|
||||||
|
System.out.println(" Taker fee: " + market.getTakerFee() + "%");
|
||||||
|
|
||||||
|
// Get market statistics
|
||||||
|
MarketStats stats = dex.markets().getStats("SYN-USDC").get();
|
||||||
|
System.out.println("\nMarket statistics:");
|
||||||
|
System.out.println(" High 24h: " + stats.getHigh24h());
|
||||||
|
System.out.println(" Low 24h: " + stats.getLow24h());
|
||||||
|
System.out.println(" Open interest: " + stats.getOpenInterest());
|
||||||
|
System.out.println(" Funding rate: " + stats.getFundingRate() + "%");
|
||||||
|
|
||||||
|
System.out.println();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void spotTradingExample(SynorDex dex) throws Exception {
|
||||||
|
System.out.println("=== Spot Trading ===");
|
||||||
|
|
||||||
|
// Place a limit order
|
||||||
|
System.out.println("Placing limit buy order...");
|
||||||
|
OrderResult limitOrder = dex.spot().placeOrder(OrderRequest.builder()
|
||||||
|
.market("SYN-USDC")
|
||||||
|
.side(OrderSide.BUY)
|
||||||
|
.orderType(OrderType.LIMIT)
|
||||||
|
.price("1.50")
|
||||||
|
.quantity("100")
|
||||||
|
.timeInForce(TimeInForce.GTC)
|
||||||
|
.build()).get();
|
||||||
|
|
||||||
|
System.out.println("Limit order placed:");
|
||||||
|
System.out.println(" Order ID: " + limitOrder.getOrderId());
|
||||||
|
System.out.println(" Status: " + limitOrder.getStatus());
|
||||||
|
System.out.println(" Price: " + limitOrder.getPrice());
|
||||||
|
System.out.println(" Quantity: " + limitOrder.getQuantity());
|
||||||
|
|
||||||
|
// Place a market order
|
||||||
|
System.out.println("\nPlacing market sell order...");
|
||||||
|
OrderResult marketOrder = dex.spot().placeOrder(OrderRequest.builder()
|
||||||
|
.market("SYN-USDC")
|
||||||
|
.side(OrderSide.SELL)
|
||||||
|
.orderType(OrderType.MARKET)
|
||||||
|
.quantity("50")
|
||||||
|
.build()).get();
|
||||||
|
|
||||||
|
System.out.println("Market order executed:");
|
||||||
|
System.out.println(" Order ID: " + marketOrder.getOrderId());
|
||||||
|
System.out.println(" Status: " + marketOrder.getStatus());
|
||||||
|
System.out.println(" Filled: " + marketOrder.getFilledQuantity());
|
||||||
|
System.out.println(" Avg price: " + marketOrder.getAveragePrice());
|
||||||
|
|
||||||
|
// Get order status
|
||||||
|
OrderStatus status = dex.spot().getOrder(limitOrder.getOrderId()).get();
|
||||||
|
System.out.println("\nOrder status:");
|
||||||
|
System.out.println(" Status: " + status.getStatus());
|
||||||
|
System.out.println(" Filled: " + status.getFilledQuantity() + " / " + status.getQuantity());
|
||||||
|
System.out.println(" Remaining: " + status.getRemainingQuantity());
|
||||||
|
|
||||||
|
// Cancel order
|
||||||
|
System.out.println("\nCancelling order...");
|
||||||
|
dex.spot().cancelOrder(limitOrder.getOrderId()).get();
|
||||||
|
System.out.println("Order cancelled successfully");
|
||||||
|
|
||||||
|
// Get open orders
|
||||||
|
List<Order> openOrders = dex.spot().getOpenOrders("SYN-USDC").get();
|
||||||
|
System.out.println("\nOpen orders: " + openOrders.size());
|
||||||
|
|
||||||
|
// Get trade history
|
||||||
|
List<Trade> trades = dex.spot().getTradeHistory("SYN-USDC", 10).get();
|
||||||
|
System.out.println("\nRecent trades: " + trades.size());
|
||||||
|
for (Trade trade : trades.subList(0, Math.min(3, trades.size()))) {
|
||||||
|
System.out.println(" " + trade.getSide() + " " + trade.getQuantity() +
|
||||||
|
" @ " + trade.getPrice() + " (" + trade.getTimestamp() + ")");
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void perpsTradingExample(SynorDex dex) throws Exception {
|
||||||
|
System.out.println("=== Perpetual Futures Trading ===");
|
||||||
|
|
||||||
|
// Get available perps markets
|
||||||
|
List<PerpsMarket> perpsMarkets = dex.perps().listMarkets().get();
|
||||||
|
System.out.println("Available perps markets: " + perpsMarkets.size());
|
||||||
|
|
||||||
|
for (PerpsMarket market : perpsMarkets.subList(0, Math.min(3, perpsMarkets.size()))) {
|
||||||
|
System.out.println(" " + market.getSymbol() + ": " + market.getMarkPrice() +
|
||||||
|
" (funding: " + market.getFundingRate() + "%)");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open a long position
|
||||||
|
System.out.println("\nOpening long position...");
|
||||||
|
Position position = dex.perps().openPosition(PerpsOrderRequest.builder()
|
||||||
|
.market("SYN-USDC-PERP")
|
||||||
|
.side(OrderSide.BUY)
|
||||||
|
.orderType(OrderType.LIMIT)
|
||||||
|
.price("1.50")
|
||||||
|
.size("1000")
|
||||||
|
.leverage(10)
|
||||||
|
.reduceOnly(false)
|
||||||
|
.build()).get();
|
||||||
|
|
||||||
|
System.out.println("Position opened:");
|
||||||
|
System.out.println(" Position ID: " + position.getPositionId());
|
||||||
|
System.out.println(" Size: " + position.getSize());
|
||||||
|
System.out.println(" Entry price: " + position.getEntryPrice());
|
||||||
|
System.out.println(" Leverage: " + position.getLeverage() + "x");
|
||||||
|
System.out.println(" Liquidation price: " + position.getLiquidationPrice());
|
||||||
|
|
||||||
|
// Get position details
|
||||||
|
PositionDetails details = dex.perps().getPosition(position.getPositionId()).get();
|
||||||
|
System.out.println("\nPosition details:");
|
||||||
|
System.out.println(" Unrealized PnL: " + details.getUnrealizedPnL());
|
||||||
|
System.out.println(" Margin: " + details.getMargin());
|
||||||
|
System.out.println(" Margin ratio: " + details.getMarginRatio() + "%");
|
||||||
|
|
||||||
|
// Set stop loss and take profit
|
||||||
|
System.out.println("\nSetting stop loss and take profit...");
|
||||||
|
dex.perps().setStopLoss(position.getPositionId(), "1.40").get();
|
||||||
|
System.out.println("Stop loss set at 1.40");
|
||||||
|
|
||||||
|
dex.perps().setTakeProfit(position.getPositionId(), "1.80").get();
|
||||||
|
System.out.println("Take profit set at 1.80");
|
||||||
|
|
||||||
|
// Close position
|
||||||
|
System.out.println("\nClosing position...");
|
||||||
|
CloseResult closeResult = dex.perps().closePosition(position.getPositionId()).get();
|
||||||
|
System.out.println("Position closed:");
|
||||||
|
System.out.println(" Realized PnL: " + closeResult.getRealizedPnL());
|
||||||
|
System.out.println(" Close price: " + closeResult.getClosePrice());
|
||||||
|
|
||||||
|
// Get all positions
|
||||||
|
List<Position> positions = dex.perps().getPositions().get();
|
||||||
|
System.out.println("\nOpen positions: " + positions.size());
|
||||||
|
|
||||||
|
// Get funding history
|
||||||
|
List<FundingPayment> funding = dex.perps().getFundingHistory("SYN-USDC-PERP", 10).get();
|
||||||
|
System.out.println("Funding payments: " + funding.size());
|
||||||
|
|
||||||
|
System.out.println();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void liquidityExample(SynorDex dex) throws Exception {
|
||||||
|
System.out.println("=== Liquidity Provision ===");
|
||||||
|
|
||||||
|
// Get available pools
|
||||||
|
List<Pool> pools = dex.liquidity().listPools().get();
|
||||||
|
System.out.println("Available pools: " + pools.size());
|
||||||
|
|
||||||
|
for (Pool pool : pools.subList(0, Math.min(3, pools.size()))) {
|
||||||
|
System.out.println("\n " + pool.getName() + ":");
|
||||||
|
System.out.println(" TVL: $" + pool.getTvl());
|
||||||
|
System.out.println(" APR: " + pool.getApr() + "%");
|
||||||
|
System.out.println(" Volume 24h: $" + pool.getVolume24h());
|
||||||
|
System.out.println(" Fee tier: " + pool.getFeeTier() + "%");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get pool details
|
||||||
|
PoolDetails pool = dex.liquidity().getPool("SYN-USDC").get();
|
||||||
|
System.out.println("\nSYN-USDC pool details:");
|
||||||
|
System.out.println(" Token0: " + pool.getToken0().getSymbol() + " (" + pool.getToken0Reserve() + ")");
|
||||||
|
System.out.println(" Token1: " + pool.getToken1().getSymbol() + " (" + pool.getToken1Reserve() + ")");
|
||||||
|
System.out.println(" Price: " + pool.getPrice());
|
||||||
|
System.out.println(" Total LP tokens: " + pool.getTotalLPTokens());
|
||||||
|
|
||||||
|
// Add liquidity
|
||||||
|
System.out.println("\nAdding liquidity...");
|
||||||
|
AddLiquidityResult addResult = dex.liquidity().addLiquidity(AddLiquidityRequest.builder()
|
||||||
|
.pool("SYN-USDC")
|
||||||
|
.amount0("100")
|
||||||
|
.amount1("150")
|
||||||
|
.slippageBps(50) // 0.5%
|
||||||
|
.build()).get();
|
||||||
|
|
||||||
|
System.out.println("Liquidity added:");
|
||||||
|
System.out.println(" LP tokens received: " + addResult.getLpTokens());
|
||||||
|
System.out.println(" Position ID: " + addResult.getPositionId());
|
||||||
|
System.out.println(" Share of pool: " + addResult.getShareOfPool() + "%");
|
||||||
|
|
||||||
|
// Get LP positions
|
||||||
|
List<LPPosition> lpPositions = dex.liquidity().getPositions().get();
|
||||||
|
System.out.println("\nLP positions: " + lpPositions.size());
|
||||||
|
for (LPPosition pos : lpPositions) {
|
||||||
|
System.out.println(" " + pos.getPool() + ": " + pos.getLpTokens() +
|
||||||
|
" LP tokens (value: $" + pos.getValue() + ")");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Claim fees
|
||||||
|
System.out.println("\nClaiming fees...");
|
||||||
|
ClaimFeesResult fees = dex.liquidity().claimFees(addResult.getPositionId()).get();
|
||||||
|
System.out.println("Fees claimed:");
|
||||||
|
System.out.println(" Token0: " + fees.getAmount0());
|
||||||
|
System.out.println(" Token1: " + fees.getAmount1());
|
||||||
|
|
||||||
|
// Remove liquidity
|
||||||
|
System.out.println("\nRemoving liquidity...");
|
||||||
|
RemoveLiquidityResult removeResult = dex.liquidity().removeLiquidity(RemoveLiquidityRequest.builder()
|
||||||
|
.positionId(addResult.getPositionId())
|
||||||
|
.lpTokens(addResult.getLpTokens())
|
||||||
|
.slippageBps(50)
|
||||||
|
.build()).get();
|
||||||
|
|
||||||
|
System.out.println("Liquidity removed:");
|
||||||
|
System.out.println(" Token0 received: " + removeResult.getAmount0());
|
||||||
|
System.out.println(" Token1 received: " + removeResult.getAmount1());
|
||||||
|
|
||||||
|
System.out.println();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void orderbookExample(SynorDex dex) throws Exception {
|
||||||
|
System.out.println("=== Order Book ===");
|
||||||
|
|
||||||
|
// Get order book snapshot
|
||||||
|
Orderbook orderbook = dex.orderbook().getSnapshot("SYN-USDC", 10).get();
|
||||||
|
|
||||||
|
System.out.println("Order book for SYN-USDC:");
|
||||||
|
System.out.println("\nAsks (sells):");
|
||||||
|
for (OrderbookEntry ask : orderbook.getAsks().subList(0, Math.min(5, orderbook.getAsks().size()))) {
|
||||||
|
System.out.println(" " + ask.getQuantity() + " @ " + ask.getPrice());
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println("\nBids (buys):");
|
||||||
|
for (OrderbookEntry bid : orderbook.getBids().subList(0, Math.min(5, orderbook.getBids().size()))) {
|
||||||
|
System.out.println(" " + bid.getQuantity() + " @ " + bid.getPrice());
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println("\nSpread: " + orderbook.getSpread() + " (" + orderbook.getSpreadPercent() + "%)");
|
||||||
|
System.out.println("Mid price: " + orderbook.getMidPrice());
|
||||||
|
|
||||||
|
// Get recent trades
|
||||||
|
List<Trade> recentTrades = dex.orderbook().getRecentTrades("SYN-USDC", 10).get();
|
||||||
|
System.out.println("\nRecent trades:");
|
||||||
|
for (Trade trade : recentTrades.subList(0, Math.min(5, recentTrades.size()))) {
|
||||||
|
System.out.println(" " + trade.getSide() + " " + trade.getQuantity() + " @ " + trade.getPrice());
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void portfolioExample(SynorDex dex) throws Exception {
|
||||||
|
System.out.println("=== Portfolio ===");
|
||||||
|
|
||||||
|
// Get portfolio overview
|
||||||
|
Portfolio portfolio = dex.portfolio().getOverview().get();
|
||||||
|
|
||||||
|
System.out.println("Portfolio overview:");
|
||||||
|
System.out.println(" Total value: $" + portfolio.getTotalValue());
|
||||||
|
System.out.println(" Available balance: $" + portfolio.getAvailableBalance());
|
||||||
|
System.out.println(" In orders: $" + portfolio.getInOrders());
|
||||||
|
System.out.println(" In positions: $" + portfolio.getInPositions());
|
||||||
|
System.out.println(" Unrealized PnL: $" + portfolio.getUnrealizedPnL());
|
||||||
|
|
||||||
|
// Get balances
|
||||||
|
List<Balance> balances = dex.portfolio().getBalances().get();
|
||||||
|
System.out.println("\nBalances:");
|
||||||
|
for (Balance balance : balances) {
|
||||||
|
System.out.println(" " + balance.getAsset() + ": " + balance.getTotal() +
|
||||||
|
" (available: " + balance.getAvailable() + ", in orders: " + balance.getInOrders() + ")");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get PnL history
|
||||||
|
List<PnLEntry> pnlHistory = dex.portfolio().getPnLHistory(30).get(); // Last 30 days
|
||||||
|
System.out.println("\nPnL history (last " + pnlHistory.size() + " days):");
|
||||||
|
if (!pnlHistory.isEmpty()) {
|
||||||
|
System.out.println(" Total PnL: $" + pnlHistory.get(pnlHistory.size() - 1).getCumulativePnL());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get trade statistics
|
||||||
|
TradeStats stats = dex.portfolio().getStats().get();
|
||||||
|
System.out.println("\nTrade statistics:");
|
||||||
|
System.out.println(" Total trades: " + stats.getTotalTrades());
|
||||||
|
System.out.println(" Win rate: " + stats.getWinRate() + "%");
|
||||||
|
System.out.println(" Avg profit: $" + stats.getAvgProfit());
|
||||||
|
System.out.println(" Avg loss: $" + stats.getAvgLoss());
|
||||||
|
System.out.println(" Best trade: $" + stats.getBestTrade());
|
||||||
|
System.out.println(" Worst trade: $" + stats.getWorstTrade());
|
||||||
|
|
||||||
|
System.out.println();
|
||||||
|
}
|
||||||
|
}
|
||||||
374
sdk/java/examples/IbcExample.java
Normal file
374
sdk/java/examples/IbcExample.java
Normal file
|
|
@ -0,0 +1,374 @@
|
||||||
|
package io.synor.examples;
|
||||||
|
|
||||||
|
import io.synor.ibc.*;
|
||||||
|
import io.synor.ibc.types.*;
|
||||||
|
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Synor IBC SDK Examples for Java
|
||||||
|
*
|
||||||
|
* Demonstrates Inter-Blockchain Communication operations:
|
||||||
|
* - Cross-chain transfers and messages
|
||||||
|
* - Channel lifecycle management
|
||||||
|
* - Packet handling and acknowledgments
|
||||||
|
* - Relayer operations
|
||||||
|
* - Connection monitoring
|
||||||
|
*/
|
||||||
|
public class IbcExample {
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
// Initialize client
|
||||||
|
IbcConfig config = IbcConfig.builder()
|
||||||
|
.apiKey(System.getenv("SYNOR_API_KEY") != null ?
|
||||||
|
System.getenv("SYNOR_API_KEY") : "your-api-key")
|
||||||
|
.endpoint("https://ibc.synor.io/v1")
|
||||||
|
.timeout(30000)
|
||||||
|
.retries(3)
|
||||||
|
.debug(false)
|
||||||
|
.defaultChain("synor-mainnet-1")
|
||||||
|
.confirmations(1)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
SynorIbc ibc = new SynorIbc(config);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Check service health
|
||||||
|
boolean healthy = ibc.healthCheck().get();
|
||||||
|
System.out.println("Service healthy: " + healthy + "\n");
|
||||||
|
|
||||||
|
// Run examples
|
||||||
|
chainsExample(ibc);
|
||||||
|
channelsExample(ibc);
|
||||||
|
transferExample(ibc);
|
||||||
|
packetExample(ibc);
|
||||||
|
relayerExample(ibc);
|
||||||
|
monitoringExample(ibc);
|
||||||
|
} finally {
|
||||||
|
ibc.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void chainsExample(SynorIbc ibc) throws Exception {
|
||||||
|
System.out.println("=== Chain Discovery ===");
|
||||||
|
|
||||||
|
// Get all connected chains
|
||||||
|
List<Chain> chains = ibc.chains().list().get();
|
||||||
|
System.out.println("Connected chains: " + chains.size());
|
||||||
|
|
||||||
|
for (Chain chain : chains.subList(0, Math.min(5, chains.size()))) {
|
||||||
|
System.out.println("\n " + chain.getChainId() + ":");
|
||||||
|
System.out.println(" Name: " + chain.getName());
|
||||||
|
System.out.println(" Type: " + chain.getChainType());
|
||||||
|
System.out.println(" Status: " + chain.getStatus());
|
||||||
|
System.out.println(" Block height: " + chain.getLatestHeight());
|
||||||
|
System.out.println(" Light client: " + chain.getLightClient());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get specific chain info
|
||||||
|
Chain synorChain = ibc.chains().get("synor-mainnet-1").get();
|
||||||
|
System.out.println("\nSynor chain details:");
|
||||||
|
System.out.println(" Bech32 prefix: " + synorChain.getBech32Prefix());
|
||||||
|
System.out.println(" Gas price: " + synorChain.getGasPrice());
|
||||||
|
System.out.println(" Supported features: " + String.join(", ", synorChain.getFeatures()));
|
||||||
|
|
||||||
|
// Get chain connections
|
||||||
|
List<Connection> connections = ibc.chains().getConnections("synor-mainnet-1").get();
|
||||||
|
System.out.println("\nChain connections: " + connections.size());
|
||||||
|
for (Connection conn : connections.subList(0, Math.min(3, connections.size()))) {
|
||||||
|
System.out.println(" " + conn.getConnectionId() + " -> " + conn.getCounterpartyChainId());
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void channelsExample(SynorIbc ibc) throws Exception {
|
||||||
|
System.out.println("=== Channel Management ===");
|
||||||
|
|
||||||
|
// List existing channels
|
||||||
|
List<Channel> channels = ibc.channels().list().get();
|
||||||
|
System.out.println("Active channels: " + channels.size());
|
||||||
|
|
||||||
|
for (Channel channel : channels.subList(0, Math.min(3, channels.size()))) {
|
||||||
|
System.out.println("\n Channel " + channel.getChannelId() + ":");
|
||||||
|
System.out.println(" Port: " + channel.getPortId());
|
||||||
|
System.out.println(" State: " + channel.getState());
|
||||||
|
System.out.println(" Order: " + channel.getOrdering());
|
||||||
|
System.out.println(" Counterparty: " + channel.getCounterpartyChannelId() +
|
||||||
|
" on " + channel.getCounterpartyChainId());
|
||||||
|
System.out.println(" Version: " + channel.getVersion());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new channel (4-step handshake)
|
||||||
|
System.out.println("\nInitiating channel creation...");
|
||||||
|
|
||||||
|
// Step 1: ChanOpenInit
|
||||||
|
ChannelInitResult initResult = ibc.channels().openInit(ChannelInitRequest.builder()
|
||||||
|
.portId("transfer")
|
||||||
|
.counterpartyChainId("cosmos-hub-4")
|
||||||
|
.counterpartyPortId("transfer")
|
||||||
|
.version("ics20-1")
|
||||||
|
.ordering(ChannelOrdering.UNORDERED)
|
||||||
|
.build()).get();
|
||||||
|
|
||||||
|
System.out.println("Channel init:");
|
||||||
|
System.out.println(" Channel ID: " + initResult.getChannelId());
|
||||||
|
System.out.println(" State: " + initResult.getState());
|
||||||
|
System.out.println(" TX hash: " + initResult.getTxHash());
|
||||||
|
|
||||||
|
// Step 2: Wait for ChanOpenTry (counterparty)
|
||||||
|
System.out.println("\nWaiting for counterparty ChanOpenTry...");
|
||||||
|
ChannelState tryState = ibc.channels().waitForState(
|
||||||
|
initResult.getChannelId(),
|
||||||
|
ChannelState.TRYOPEN,
|
||||||
|
Duration.ofMinutes(5)
|
||||||
|
).get();
|
||||||
|
System.out.println("Channel state: " + tryState);
|
||||||
|
|
||||||
|
// Step 3: ChanOpenAck
|
||||||
|
System.out.println("\nSending ChanOpenAck...");
|
||||||
|
ChannelAckResult ackResult = ibc.channels().openAck(ChannelAckRequest.builder()
|
||||||
|
.channelId(initResult.getChannelId())
|
||||||
|
.counterpartyChannelId("channel-0")
|
||||||
|
.counterpartyVersion("ics20-1")
|
||||||
|
.build()).get();
|
||||||
|
System.out.println("Ack TX: " + ackResult.getTxHash());
|
||||||
|
|
||||||
|
// Step 4: Wait for ChanOpenConfirm (counterparty)
|
||||||
|
System.out.println("\nWaiting for channel to open...");
|
||||||
|
ChannelState openState = ibc.channels().waitForState(
|
||||||
|
initResult.getChannelId(),
|
||||||
|
ChannelState.OPEN,
|
||||||
|
Duration.ofMinutes(5)
|
||||||
|
).get();
|
||||||
|
System.out.println("Channel is now: " + openState);
|
||||||
|
|
||||||
|
// Get channel details
|
||||||
|
Channel channel = ibc.channels().get(initResult.getChannelId()).get();
|
||||||
|
System.out.println("\nChannel details:");
|
||||||
|
System.out.println(" Sequences - Send: " + channel.getNextSequenceSend() +
|
||||||
|
", Recv: " + channel.getNextSequenceRecv() +
|
||||||
|
", Ack: " + channel.getNextSequenceAck());
|
||||||
|
|
||||||
|
System.out.println();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void transferExample(SynorIbc ibc) throws Exception {
|
||||||
|
System.out.println("=== Cross-Chain Transfers ===");
|
||||||
|
|
||||||
|
// Get supported tokens for transfer
|
||||||
|
List<TransferableToken> tokens = ibc.transfers().getSupportedTokens("cosmos-hub-4").get();
|
||||||
|
System.out.println("Transferable tokens to Cosmos Hub:");
|
||||||
|
for (TransferableToken token : tokens.subList(0, Math.min(5, tokens.size()))) {
|
||||||
|
System.out.println(" " + token.getSymbol() + " (" + token.getDenom() + ")");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initiate a cross-chain transfer
|
||||||
|
System.out.println("\nInitiating transfer...");
|
||||||
|
TransferResult transfer = ibc.transfers().send(TransferRequest.builder()
|
||||||
|
.sourceChannel("channel-0")
|
||||||
|
.denom("usynor")
|
||||||
|
.amount("1000000")
|
||||||
|
.receiver("cosmos1...")
|
||||||
|
.timeoutHeight(0) // Use timestamp instead
|
||||||
|
.timeoutTimestamp(Instant.now().plusSeconds(600).toEpochMilli() * 1_000_000L)
|
||||||
|
.memo("IBC transfer from Synor")
|
||||||
|
.build()).get();
|
||||||
|
|
||||||
|
System.out.println("Transfer initiated:");
|
||||||
|
System.out.println(" TX hash: " + transfer.getTxHash());
|
||||||
|
System.out.println(" Sequence: " + transfer.getSequence());
|
||||||
|
System.out.println(" Packet ID: " + transfer.getPacketId());
|
||||||
|
System.out.println(" Status: " + transfer.getStatus());
|
||||||
|
|
||||||
|
// Track transfer progress
|
||||||
|
System.out.println("\nTracking transfer...");
|
||||||
|
TransferStatus status = ibc.transfers().track(transfer.getPacketId()).get();
|
||||||
|
System.out.println("Current status: " + status.getState());
|
||||||
|
System.out.println("Source TX: " + status.getSourceTxHash());
|
||||||
|
if (status.getDestTxHash() != null) {
|
||||||
|
System.out.println("Dest TX: " + status.getDestTxHash());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for completion
|
||||||
|
System.out.println("\nWaiting for transfer completion...");
|
||||||
|
TransferStatus finalStatus = ibc.transfers().waitForCompletion(
|
||||||
|
transfer.getPacketId(),
|
||||||
|
Duration.ofMinutes(10)
|
||||||
|
).get();
|
||||||
|
|
||||||
|
System.out.println("Transfer completed:");
|
||||||
|
System.out.println(" Final status: " + finalStatus.getState());
|
||||||
|
System.out.println(" Acknowledgment: " + finalStatus.getAcknowledgment());
|
||||||
|
|
||||||
|
// Get transfer history
|
||||||
|
List<Transfer> history = ibc.transfers().getHistory(10).get();
|
||||||
|
System.out.println("\nRecent transfers: " + history.size());
|
||||||
|
for (Transfer t : history.subList(0, Math.min(3, history.size()))) {
|
||||||
|
System.out.println(" " + t.getAmount() + " " + t.getDenom() +
|
||||||
|
" -> " + t.getDestChain() + " (" + t.getStatus() + ")");
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void packetExample(SynorIbc ibc) throws Exception {
|
||||||
|
System.out.println("=== Packet Operations ===");
|
||||||
|
|
||||||
|
// List pending packets
|
||||||
|
List<Packet> pending = ibc.packets().listPending("channel-0").get();
|
||||||
|
System.out.println("Pending packets on channel-0: " + pending.size());
|
||||||
|
|
||||||
|
for (Packet packet : pending.subList(0, Math.min(3, pending.size()))) {
|
||||||
|
System.out.println("\n Packet #" + packet.getSequence() + ":");
|
||||||
|
System.out.println(" Source: " + packet.getSourcePort() + "/" + packet.getSourceChannel());
|
||||||
|
System.out.println(" Dest: " + packet.getDestPort() + "/" + packet.getDestChannel());
|
||||||
|
System.out.println(" State: " + packet.getState());
|
||||||
|
System.out.println(" Timeout: " + packet.getTimeoutTimestamp());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get specific packet
|
||||||
|
Packet packet = ibc.packets().get("channel-0", 1).get();
|
||||||
|
System.out.println("\nPacket details:");
|
||||||
|
System.out.println(" Data (hex): " + packet.getDataHex().substring(0, 40) + "...");
|
||||||
|
System.out.println(" Created: " + packet.getCreatedAt());
|
||||||
|
|
||||||
|
// Get packet commitment proof
|
||||||
|
PacketProof proof = ibc.packets().getCommitmentProof("channel-0", 1).get();
|
||||||
|
System.out.println("\nCommitment proof:");
|
||||||
|
System.out.println(" Height: " + proof.getProofHeight());
|
||||||
|
System.out.println(" Proof size: " + proof.getProof().length + " bytes");
|
||||||
|
|
||||||
|
// Get acknowledgment
|
||||||
|
PacketAck ack = ibc.packets().getAcknowledgment("channel-0", 1).get();
|
||||||
|
System.out.println("\nAcknowledgment:");
|
||||||
|
System.out.println(" Result: " + (ack.isSuccess() ? "Success" : "Error: " + ack.getError()));
|
||||||
|
System.out.println(" TX hash: " + ack.getTxHash());
|
||||||
|
|
||||||
|
// List timed-out packets
|
||||||
|
List<Packet> timedOut = ibc.packets().listTimedOut().get();
|
||||||
|
System.out.println("\nTimed-out packets: " + timedOut.size());
|
||||||
|
|
||||||
|
// Timeout a packet manually
|
||||||
|
if (!timedOut.isEmpty()) {
|
||||||
|
Packet toTimeout = timedOut.get(0);
|
||||||
|
System.out.println("\nProcessing timeout for packet #" + toTimeout.getSequence());
|
||||||
|
TimeoutResult timeout = ibc.packets().timeout(
|
||||||
|
toTimeout.getSourceChannel(),
|
||||||
|
toTimeout.getSequence()
|
||||||
|
).get();
|
||||||
|
System.out.println("Timeout TX: " + timeout.getTxHash());
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void relayerExample(SynorIbc ibc) throws Exception {
|
||||||
|
System.out.println("=== Relayer Operations ===");
|
||||||
|
|
||||||
|
// Get relayer status
|
||||||
|
RelayerStatus status = ibc.relayer().getStatus().get();
|
||||||
|
System.out.println("Relayer status:");
|
||||||
|
System.out.println(" Running: " + status.isRunning());
|
||||||
|
System.out.println(" Uptime: " + status.getUptime());
|
||||||
|
System.out.println(" Packets relayed: " + status.getPacketsRelayed());
|
||||||
|
System.out.println(" Errors: " + status.getErrorCount());
|
||||||
|
|
||||||
|
// List active paths
|
||||||
|
List<RelayPath> paths = ibc.relayer().listPaths().get();
|
||||||
|
System.out.println("\nActive relay paths: " + paths.size());
|
||||||
|
|
||||||
|
for (RelayPath path : paths) {
|
||||||
|
System.out.println("\n " + path.getPathId() + ":");
|
||||||
|
System.out.println(" " + path.getSourceChain() + " <-> " + path.getDestChain());
|
||||||
|
System.out.println(" Channel: " + path.getSourceChannel() + " <-> " + path.getDestChannel());
|
||||||
|
System.out.println(" Status: " + path.getStatus());
|
||||||
|
System.out.println(" Pending packets: " + path.getPendingPackets());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configure a new path
|
||||||
|
System.out.println("\nConfiguring new relay path...");
|
||||||
|
RelayPath newPath = ibc.relayer().addPath(PathConfig.builder()
|
||||||
|
.sourceChain("synor-mainnet-1")
|
||||||
|
.destChain("osmosis-1")
|
||||||
|
.sourceChannel("channel-1")
|
||||||
|
.destChannel("channel-100")
|
||||||
|
.filterDenoms(List.of("usynor", "uosmo"))
|
||||||
|
.minRelayAmount("1000")
|
||||||
|
.maxRelayAmount("1000000000")
|
||||||
|
.build()).get();
|
||||||
|
|
||||||
|
System.out.println("Path created: " + newPath.getPathId());
|
||||||
|
|
||||||
|
// Start relaying on path
|
||||||
|
System.out.println("\nStarting relayer on path...");
|
||||||
|
ibc.relayer().startPath(newPath.getPathId()).get();
|
||||||
|
System.out.println("Relayer started");
|
||||||
|
|
||||||
|
// Manually relay pending packets
|
||||||
|
System.out.println("\nRelaying pending packets...");
|
||||||
|
RelayResult relayResult = ibc.relayer().relayPending(newPath.getPathId()).get();
|
||||||
|
System.out.println("Relayed " + relayResult.getPacketCount() + " packets");
|
||||||
|
System.out.println("TX hashes: " + relayResult.getTxHashes().size());
|
||||||
|
|
||||||
|
// Get relay history
|
||||||
|
List<RelayEvent> history = ibc.relayer().getHistory(newPath.getPathId(), 10).get();
|
||||||
|
System.out.println("\nRelay history:");
|
||||||
|
for (RelayEvent event : history.subList(0, Math.min(3, history.size()))) {
|
||||||
|
System.out.println(" " + event.getTimestamp() + ": " +
|
||||||
|
event.getEventType() + " - " + event.getPacketCount() + " packets");
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void monitoringExample(SynorIbc ibc) throws Exception {
|
||||||
|
System.out.println("=== IBC Monitoring ===");
|
||||||
|
|
||||||
|
// Get IBC metrics
|
||||||
|
IbcMetrics metrics = ibc.monitoring().getMetrics().get();
|
||||||
|
System.out.println("IBC metrics:");
|
||||||
|
System.out.println(" Total channels: " + metrics.getTotalChannels());
|
||||||
|
System.out.println(" Active channels: " + metrics.getActiveChannels());
|
||||||
|
System.out.println(" Total packets: " + metrics.getTotalPackets());
|
||||||
|
System.out.println(" Pending packets: " + metrics.getPendingPackets());
|
||||||
|
System.out.println(" Failed packets: " + metrics.getFailedPackets());
|
||||||
|
System.out.println(" Avg relay time: " + metrics.getAvgRelayTime() + "ms");
|
||||||
|
|
||||||
|
// Get chain health
|
||||||
|
List<ChainHealth> chainHealth = ibc.monitoring().getChainHealth().get();
|
||||||
|
System.out.println("\nChain health:");
|
||||||
|
for (ChainHealth health : chainHealth.subList(0, Math.min(3, chainHealth.size()))) {
|
||||||
|
System.out.println(" " + health.getChainId() + ":");
|
||||||
|
System.out.println(" Status: " + health.getStatus());
|
||||||
|
System.out.println(" Block lag: " + health.getBlockLag());
|
||||||
|
System.out.println(" Last update: " + health.getLastUpdate());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get channel statistics
|
||||||
|
ChannelStats stats = ibc.monitoring().getChannelStats("channel-0").get();
|
||||||
|
System.out.println("\nChannel-0 statistics:");
|
||||||
|
System.out.println(" Packets sent: " + stats.getPacketsSent());
|
||||||
|
System.out.println(" Packets received: " + stats.getPacketsReceived());
|
||||||
|
System.out.println(" Success rate: " + stats.getSuccessRate() + "%");
|
||||||
|
System.out.println(" Avg confirmation time: " + stats.getAvgConfirmationTime() + "ms");
|
||||||
|
|
||||||
|
// Subscribe to IBC events
|
||||||
|
System.out.println("\nSubscribing to IBC events...");
|
||||||
|
ibc.monitoring().subscribe(event -> {
|
||||||
|
System.out.println("Event: " + event.getType() + " on " + event.getChannelId());
|
||||||
|
}).get();
|
||||||
|
|
||||||
|
// Get alerts
|
||||||
|
List<IbcAlert> alerts = ibc.monitoring().getAlerts().get();
|
||||||
|
System.out.println("\nActive alerts: " + alerts.size());
|
||||||
|
for (IbcAlert alert : alerts) {
|
||||||
|
System.out.println(" [" + alert.getSeverity() + "] " + alert.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println();
|
||||||
|
}
|
||||||
|
}
|
||||||
537
sdk/java/examples/ZkExample.java
Normal file
537
sdk/java/examples/ZkExample.java
Normal file
|
|
@ -0,0 +1,537 @@
|
||||||
|
package io.synor.examples;
|
||||||
|
|
||||||
|
import io.synor.zk.*;
|
||||||
|
import io.synor.zk.types.*;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Synor ZK SDK Examples for Java
|
||||||
|
*
|
||||||
|
* Demonstrates Zero-Knowledge proof operations:
|
||||||
|
* - Circuit compilation
|
||||||
|
* - Proof generation and verification
|
||||||
|
* - Groth16, PLONK, and STARK proving systems
|
||||||
|
* - Recursive proofs
|
||||||
|
* - On-chain verification
|
||||||
|
*/
|
||||||
|
public class ZkExample {
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
// Initialize client
|
||||||
|
ZkConfig config = ZkConfig.builder()
|
||||||
|
.apiKey(System.getenv("SYNOR_API_KEY") != null ?
|
||||||
|
System.getenv("SYNOR_API_KEY") : "your-api-key")
|
||||||
|
.endpoint("https://zk.synor.io/v1")
|
||||||
|
.timeout(120000) // ZK ops can be slow
|
||||||
|
.retries(3)
|
||||||
|
.debug(false)
|
||||||
|
.defaultProvingSystem(ProvingSystem.GROTH16)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
SynorZk zk = new SynorZk(config);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Check service health
|
||||||
|
boolean healthy = zk.healthCheck().get();
|
||||||
|
System.out.println("Service healthy: " + healthy + "\n");
|
||||||
|
|
||||||
|
// Run examples
|
||||||
|
circuitExample(zk);
|
||||||
|
proofExample(zk);
|
||||||
|
provingSystemsExample(zk);
|
||||||
|
recursiveProofExample(zk);
|
||||||
|
onChainVerificationExample(zk);
|
||||||
|
setupExample(zk);
|
||||||
|
} finally {
|
||||||
|
zk.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void circuitExample(SynorZk zk) throws Exception {
|
||||||
|
System.out.println("=== Circuit Compilation ===");
|
||||||
|
|
||||||
|
// Circom circuit example: prove knowledge of preimage
|
||||||
|
String circomCircuit = """
|
||||||
|
pragma circom 2.1.0;
|
||||||
|
|
||||||
|
template HashPreimage() {
|
||||||
|
signal input preimage;
|
||||||
|
signal input hash;
|
||||||
|
|
||||||
|
// Simplified hash computation (in reality, use proper hash)
|
||||||
|
signal preimageSquared;
|
||||||
|
preimageSquared <== preimage * preimage;
|
||||||
|
|
||||||
|
// Constrain that hash matches
|
||||||
|
hash === preimageSquared;
|
||||||
|
}
|
||||||
|
|
||||||
|
component main {public [hash]} = HashPreimage();
|
||||||
|
""";
|
||||||
|
|
||||||
|
// Compile circuit
|
||||||
|
System.out.println("Compiling Circom circuit...");
|
||||||
|
CompiledCircuit compiled = zk.circuits().compile(CompileRequest.builder()
|
||||||
|
.code(circomCircuit)
|
||||||
|
.format(CircuitFormat.CIRCOM)
|
||||||
|
.name("hash_preimage")
|
||||||
|
.provingSystem(ProvingSystem.GROTH16)
|
||||||
|
.build()).get();
|
||||||
|
|
||||||
|
System.out.println("Circuit compiled:");
|
||||||
|
System.out.println(" Circuit ID: " + compiled.getCircuitId());
|
||||||
|
System.out.println(" Constraints: " + compiled.getConstraintCount());
|
||||||
|
System.out.println(" Public inputs: " + compiled.getPublicInputCount());
|
||||||
|
System.out.println(" Private inputs: " + compiled.getPrivateInputCount());
|
||||||
|
System.out.println(" Proving key size: " + compiled.getProvingKeySize() + " bytes");
|
||||||
|
System.out.println(" Verification key size: " + compiled.getVerificationKeySize() + " bytes");
|
||||||
|
|
||||||
|
// List circuits
|
||||||
|
List<Circuit> circuits = zk.circuits().list().get();
|
||||||
|
System.out.println("\nYour circuits: " + circuits.size());
|
||||||
|
for (Circuit circuit : circuits) {
|
||||||
|
System.out.println(" " + circuit.getName() + " (" + circuit.getCircuitId() + ")");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get circuit details
|
||||||
|
CircuitDetails details = zk.circuits().get(compiled.getCircuitId()).get();
|
||||||
|
System.out.println("\nCircuit details:");
|
||||||
|
System.out.println(" Format: " + details.getFormat());
|
||||||
|
System.out.println(" Proving system: " + details.getProvingSystem());
|
||||||
|
System.out.println(" Created: " + details.getCreatedAt());
|
||||||
|
|
||||||
|
// Download proving key
|
||||||
|
byte[] provingKey = zk.circuits().getProvingKey(compiled.getCircuitId()).get();
|
||||||
|
System.out.println("\nProving key downloaded: " + provingKey.length + " bytes");
|
||||||
|
|
||||||
|
// Download verification key
|
||||||
|
byte[] verificationKey = zk.circuits().getVerificationKey(compiled.getCircuitId()).get();
|
||||||
|
System.out.println("Verification key downloaded: " + verificationKey.length + " bytes");
|
||||||
|
|
||||||
|
System.out.println();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void proofExample(SynorZk zk) throws Exception {
|
||||||
|
System.out.println("=== Proof Generation ===");
|
||||||
|
|
||||||
|
// First, compile a simple circuit
|
||||||
|
String circuit = """
|
||||||
|
pragma circom 2.1.0;
|
||||||
|
|
||||||
|
template Multiplier() {
|
||||||
|
signal input a;
|
||||||
|
signal input b;
|
||||||
|
signal output c;
|
||||||
|
|
||||||
|
c <== a * b;
|
||||||
|
}
|
||||||
|
|
||||||
|
component main {public [c]} = Multiplier();
|
||||||
|
""";
|
||||||
|
|
||||||
|
CompiledCircuit compiled = zk.circuits().compile(CompileRequest.builder()
|
||||||
|
.code(circuit)
|
||||||
|
.format(CircuitFormat.CIRCOM)
|
||||||
|
.name("multiplier")
|
||||||
|
.provingSystem(ProvingSystem.GROTH16)
|
||||||
|
.build()).get();
|
||||||
|
|
||||||
|
// Generate proof
|
||||||
|
System.out.println("Generating proof...");
|
||||||
|
long startTime = System.currentTimeMillis();
|
||||||
|
|
||||||
|
Map<String, String> inputs = new HashMap<>();
|
||||||
|
inputs.put("a", "3");
|
||||||
|
inputs.put("b", "7");
|
||||||
|
|
||||||
|
Proof proof = zk.proofs().generate(GenerateProofRequest.builder()
|
||||||
|
.circuitId(compiled.getCircuitId())
|
||||||
|
.inputs(inputs)
|
||||||
|
.build()).get();
|
||||||
|
|
||||||
|
long proofTime = System.currentTimeMillis() - startTime;
|
||||||
|
System.out.println("Proof generated in " + proofTime + "ms");
|
||||||
|
System.out.println(" Proof ID: " + proof.getProofId());
|
||||||
|
System.out.println(" Proof size: " + proof.getProof().length() + " bytes");
|
||||||
|
System.out.println(" Public signals: " + proof.getPublicSignals());
|
||||||
|
|
||||||
|
// Verify proof
|
||||||
|
System.out.println("\nVerifying proof...");
|
||||||
|
long verifyStart = System.currentTimeMillis();
|
||||||
|
|
||||||
|
boolean isValid = zk.proofs().verify(VerifyRequest.builder()
|
||||||
|
.circuitId(compiled.getCircuitId())
|
||||||
|
.proof(proof.getProof())
|
||||||
|
.publicSignals(proof.getPublicSignals())
|
||||||
|
.build()).get();
|
||||||
|
|
||||||
|
long verifyTime = System.currentTimeMillis() - verifyStart;
|
||||||
|
System.out.println("Verification completed in " + verifyTime + "ms");
|
||||||
|
System.out.println(" Valid: " + isValid);
|
||||||
|
|
||||||
|
// Verify with wrong public signals (should fail)
|
||||||
|
System.out.println("\nVerifying with wrong signals...");
|
||||||
|
boolean invalidResult = zk.proofs().verify(VerifyRequest.builder()
|
||||||
|
.circuitId(compiled.getCircuitId())
|
||||||
|
.proof(proof.getProof())
|
||||||
|
.publicSignals(List.of("42")) // Wrong answer
|
||||||
|
.build()).get();
|
||||||
|
System.out.println(" Valid: " + invalidResult + " (expected false)");
|
||||||
|
|
||||||
|
// Get proof status
|
||||||
|
ProofStatus status = zk.proofs().getStatus(proof.getProofId()).get();
|
||||||
|
System.out.println("\nProof status:");
|
||||||
|
System.out.println(" State: " + status.getState());
|
||||||
|
System.out.println(" Verified: " + status.isVerified());
|
||||||
|
System.out.println(" Created: " + status.getCreatedAt());
|
||||||
|
|
||||||
|
// List proofs
|
||||||
|
List<ProofInfo> proofs = zk.proofs().list(compiled.getCircuitId()).get();
|
||||||
|
System.out.println("\nProofs for circuit: " + proofs.size());
|
||||||
|
|
||||||
|
System.out.println();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void provingSystemsExample(SynorZk zk) throws Exception {
|
||||||
|
System.out.println("=== Proving Systems Comparison ===");
|
||||||
|
|
||||||
|
// Simple circuit for comparison
|
||||||
|
String circuit = """
|
||||||
|
pragma circom 2.1.0;
|
||||||
|
|
||||||
|
template Comparison() {
|
||||||
|
signal input x;
|
||||||
|
signal input y;
|
||||||
|
signal output sum;
|
||||||
|
|
||||||
|
sum <== x + y;
|
||||||
|
}
|
||||||
|
|
||||||
|
component main {public [sum]} = Comparison();
|
||||||
|
""";
|
||||||
|
|
||||||
|
ProvingSystem[] systems = {
|
||||||
|
ProvingSystem.GROTH16,
|
||||||
|
ProvingSystem.PLONK,
|
||||||
|
ProvingSystem.STARK
|
||||||
|
};
|
||||||
|
|
||||||
|
System.out.println("Comparing proving systems:\n");
|
||||||
|
|
||||||
|
for (ProvingSystem system : systems) {
|
||||||
|
System.out.println(system + ":");
|
||||||
|
|
||||||
|
// Compile for this system
|
||||||
|
CompiledCircuit compiled = zk.circuits().compile(CompileRequest.builder()
|
||||||
|
.code(circuit)
|
||||||
|
.format(CircuitFormat.CIRCOM)
|
||||||
|
.name("comparison_" + system.toString().toLowerCase())
|
||||||
|
.provingSystem(system)
|
||||||
|
.build()).get();
|
||||||
|
|
||||||
|
// Generate proof
|
||||||
|
long proofStart = System.currentTimeMillis();
|
||||||
|
Map<String, String> inputs = new HashMap<>();
|
||||||
|
inputs.put("x", "10");
|
||||||
|
inputs.put("y", "20");
|
||||||
|
|
||||||
|
Proof proof = zk.proofs().generate(GenerateProofRequest.builder()
|
||||||
|
.circuitId(compiled.getCircuitId())
|
||||||
|
.inputs(inputs)
|
||||||
|
.build()).get();
|
||||||
|
long proofTime = System.currentTimeMillis() - proofStart;
|
||||||
|
|
||||||
|
// Verify proof
|
||||||
|
long verifyStart = System.currentTimeMillis();
|
||||||
|
zk.proofs().verify(VerifyRequest.builder()
|
||||||
|
.circuitId(compiled.getCircuitId())
|
||||||
|
.proof(proof.getProof())
|
||||||
|
.publicSignals(proof.getPublicSignals())
|
||||||
|
.build()).get();
|
||||||
|
long verifyTime = System.currentTimeMillis() - verifyStart;
|
||||||
|
|
||||||
|
System.out.println(" Setup: " + compiled.getSetupTime() + "ms");
|
||||||
|
System.out.println(" Proof time: " + proofTime + "ms");
|
||||||
|
System.out.println(" Verify time: " + verifyTime + "ms");
|
||||||
|
System.out.println(" Proof size: " + proof.getProof().length() + " bytes");
|
||||||
|
System.out.println(" Verification key: " + compiled.getVerificationKeySize() + " bytes");
|
||||||
|
System.out.println();
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println("Summary:");
|
||||||
|
System.out.println(" Groth16: Smallest proofs, fast verification, trusted setup required");
|
||||||
|
System.out.println(" PLONK: Universal setup, flexible, moderate proof size");
|
||||||
|
System.out.println(" STARK: No trusted setup, largest proofs, quantum resistant");
|
||||||
|
|
||||||
|
System.out.println();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void recursiveProofExample(SynorZk zk) throws Exception {
|
||||||
|
System.out.println("=== Recursive Proofs ===");
|
||||||
|
|
||||||
|
// Inner circuit
|
||||||
|
String innerCircuit = """
|
||||||
|
pragma circom 2.1.0;
|
||||||
|
|
||||||
|
template Inner() {
|
||||||
|
signal input x;
|
||||||
|
signal output y;
|
||||||
|
y <== x * x;
|
||||||
|
}
|
||||||
|
|
||||||
|
component main {public [y]} = Inner();
|
||||||
|
""";
|
||||||
|
|
||||||
|
// Compile inner circuit
|
||||||
|
CompiledCircuit inner = zk.circuits().compile(CompileRequest.builder()
|
||||||
|
.code(innerCircuit)
|
||||||
|
.format(CircuitFormat.CIRCOM)
|
||||||
|
.name("inner_circuit")
|
||||||
|
.provingSystem(ProvingSystem.GROTH16)
|
||||||
|
.build()).get();
|
||||||
|
|
||||||
|
// Generate multiple proofs to aggregate
|
||||||
|
System.out.println("Generating proofs to aggregate...");
|
||||||
|
List<ProofData> proofsToAggregate = new ArrayList<>();
|
||||||
|
for (int i = 1; i <= 4; i++) {
|
||||||
|
Map<String, String> inputs = new HashMap<>();
|
||||||
|
inputs.put("x", String.valueOf(i));
|
||||||
|
|
||||||
|
Proof proof = zk.proofs().generate(GenerateProofRequest.builder()
|
||||||
|
.circuitId(inner.getCircuitId())
|
||||||
|
.inputs(inputs)
|
||||||
|
.build()).get();
|
||||||
|
|
||||||
|
proofsToAggregate.add(ProofData.builder()
|
||||||
|
.proof(proof.getProof())
|
||||||
|
.publicSignals(proof.getPublicSignals())
|
||||||
|
.build());
|
||||||
|
System.out.println(" Proof " + i + ": y = " + proof.getPublicSignals().get(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Aggregate proofs recursively
|
||||||
|
System.out.println("\nAggregating proofs...");
|
||||||
|
AggregatedProof aggregated = zk.proofs().aggregate(AggregateRequest.builder()
|
||||||
|
.circuitId(inner.getCircuitId())
|
||||||
|
.proofs(proofsToAggregate)
|
||||||
|
.aggregationType("recursive")
|
||||||
|
.build()).get();
|
||||||
|
|
||||||
|
int originalSize = proofsToAggregate.stream()
|
||||||
|
.mapToInt(p -> p.getProof().length())
|
||||||
|
.sum();
|
||||||
|
|
||||||
|
System.out.println("Aggregated proof:");
|
||||||
|
System.out.println(" Proof ID: " + aggregated.getProofId());
|
||||||
|
System.out.println(" Aggregated count: " + aggregated.getAggregatedCount());
|
||||||
|
System.out.println(" Proof size: " + aggregated.getProof().length() + " bytes");
|
||||||
|
System.out.println(" Size reduction: " +
|
||||||
|
String.format("%.1f", (1 - (double) aggregated.getProof().length() / originalSize) * 100) + "%");
|
||||||
|
|
||||||
|
// Verify aggregated proof
|
||||||
|
List<List<String>> publicSignalsList = proofsToAggregate.stream()
|
||||||
|
.map(ProofData::getPublicSignals)
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
boolean isValid = zk.proofs().verifyAggregated(VerifyAggregatedRequest.builder()
|
||||||
|
.circuitId(inner.getCircuitId())
|
||||||
|
.proof(aggregated.getProof())
|
||||||
|
.publicSignalsList(publicSignalsList)
|
||||||
|
.build()).get();
|
||||||
|
System.out.println("\nAggregated proof valid: " + isValid);
|
||||||
|
|
||||||
|
// Batch verification
|
||||||
|
System.out.println("\nBatch verification...");
|
||||||
|
BatchVerifyResult batchResult = zk.proofs().batchVerify(BatchVerifyRequest.builder()
|
||||||
|
.circuitId(inner.getCircuitId())
|
||||||
|
.proofs(proofsToAggregate)
|
||||||
|
.build()).get();
|
||||||
|
System.out.println(" All valid: " + batchResult.isAllValid());
|
||||||
|
System.out.println(" Results: " + batchResult.getResults());
|
||||||
|
|
||||||
|
System.out.println();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void onChainVerificationExample(SynorZk zk) throws Exception {
|
||||||
|
System.out.println("=== On-Chain Verification ===");
|
||||||
|
|
||||||
|
// Compile circuit
|
||||||
|
String circuit = """
|
||||||
|
pragma circom 2.1.0;
|
||||||
|
|
||||||
|
template VoteCommitment() {
|
||||||
|
signal input vote;
|
||||||
|
signal input nullifier;
|
||||||
|
signal input commitment;
|
||||||
|
|
||||||
|
signal computed;
|
||||||
|
computed <== vote * nullifier;
|
||||||
|
commitment === computed;
|
||||||
|
}
|
||||||
|
|
||||||
|
component main {public [commitment]} = VoteCommitment();
|
||||||
|
""";
|
||||||
|
|
||||||
|
CompiledCircuit compiled = zk.circuits().compile(CompileRequest.builder()
|
||||||
|
.code(circuit)
|
||||||
|
.format(CircuitFormat.CIRCOM)
|
||||||
|
.name("vote_commitment")
|
||||||
|
.provingSystem(ProvingSystem.GROTH16)
|
||||||
|
.build()).get();
|
||||||
|
|
||||||
|
// Generate Solidity verifier
|
||||||
|
System.out.println("Generating Solidity verifier...");
|
||||||
|
GeneratedVerifier solidityVerifier = zk.contracts().generateVerifier(GenerateVerifierRequest.builder()
|
||||||
|
.circuitId(compiled.getCircuitId())
|
||||||
|
.language("solidity")
|
||||||
|
.optimized(true)
|
||||||
|
.build()).get();
|
||||||
|
System.out.println("Solidity verifier generated: " + solidityVerifier.getCode().length() + " bytes");
|
||||||
|
System.out.println(" Contract name: " + solidityVerifier.getContractName());
|
||||||
|
System.out.println(" Gas estimate: " + solidityVerifier.getGasEstimate());
|
||||||
|
|
||||||
|
// Generate proof
|
||||||
|
Map<String, String> inputs = new HashMap<>();
|
||||||
|
inputs.put("vote", "1");
|
||||||
|
inputs.put("nullifier", "12345");
|
||||||
|
inputs.put("commitment", "12345");
|
||||||
|
|
||||||
|
Proof proof = zk.proofs().generate(GenerateProofRequest.builder()
|
||||||
|
.circuitId(compiled.getCircuitId())
|
||||||
|
.inputs(inputs)
|
||||||
|
.build()).get();
|
||||||
|
|
||||||
|
// Format proof for on-chain verification
|
||||||
|
System.out.println("\nFormatting proof for on-chain...");
|
||||||
|
FormattedProof onChainProof = zk.contracts().formatProof(FormatProofRequest.builder()
|
||||||
|
.circuitId(compiled.getCircuitId())
|
||||||
|
.proof(proof.getProof())
|
||||||
|
.publicSignals(proof.getPublicSignals())
|
||||||
|
.format("calldata")
|
||||||
|
.build()).get();
|
||||||
|
String calldataPreview = onChainProof.getCalldata().substring(0,
|
||||||
|
Math.min(100, onChainProof.getCalldata().length()));
|
||||||
|
System.out.println(" Calldata: " + calldataPreview + "...");
|
||||||
|
System.out.println(" Estimated gas: " + onChainProof.getGasEstimate());
|
||||||
|
|
||||||
|
// Deploy verifier contract
|
||||||
|
System.out.println("\nDeploying verifier contract...");
|
||||||
|
Deployment deployment = zk.contracts().deployVerifier(DeployRequest.builder()
|
||||||
|
.circuitId(compiled.getCircuitId())
|
||||||
|
.network("synor-testnet")
|
||||||
|
.build()).get();
|
||||||
|
System.out.println(" Contract address: " + deployment.getAddress());
|
||||||
|
System.out.println(" TX hash: " + deployment.getTxHash());
|
||||||
|
System.out.println(" Gas used: " + deployment.getGasUsed());
|
||||||
|
|
||||||
|
// Verify on-chain
|
||||||
|
System.out.println("\nVerifying on-chain...");
|
||||||
|
OnChainVerifyResult onChainResult = zk.contracts().verifyOnChain(OnChainVerifyRequest.builder()
|
||||||
|
.contractAddress(deployment.getAddress())
|
||||||
|
.proof(proof.getProof())
|
||||||
|
.publicSignals(proof.getPublicSignals())
|
||||||
|
.network("synor-testnet")
|
||||||
|
.build()).get();
|
||||||
|
System.out.println(" TX hash: " + onChainResult.getTxHash());
|
||||||
|
System.out.println(" Verified: " + onChainResult.isVerified());
|
||||||
|
System.out.println(" Gas used: " + onChainResult.getGasUsed());
|
||||||
|
|
||||||
|
// Generate verifier for other targets
|
||||||
|
System.out.println("\nGenerating verifiers for other targets:");
|
||||||
|
String[] targets = {"cairo", "noir", "ink"};
|
||||||
|
for (String target : targets) {
|
||||||
|
GeneratedVerifier verifier = zk.contracts().generateVerifier(GenerateVerifierRequest.builder()
|
||||||
|
.circuitId(compiled.getCircuitId())
|
||||||
|
.language(target)
|
||||||
|
.build()).get();
|
||||||
|
System.out.println(" " + target + ": " + verifier.getCode().length() + " bytes");
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void setupExample(SynorZk zk) throws Exception {
|
||||||
|
System.out.println("=== Trusted Setup ===");
|
||||||
|
|
||||||
|
// Get available ceremonies
|
||||||
|
List<Ceremony> ceremonies = zk.setup().listCeremonies().get();
|
||||||
|
System.out.println("Active ceremonies: " + ceremonies.size());
|
||||||
|
for (Ceremony ceremony : ceremonies) {
|
||||||
|
System.out.println(" " + ceremony.getName() + ":");
|
||||||
|
System.out.println(" Status: " + ceremony.getStatus());
|
||||||
|
System.out.println(" Participants: " + ceremony.getParticipantCount());
|
||||||
|
System.out.println(" Current round: " + ceremony.getCurrentRound());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new circuit setup
|
||||||
|
String circuit = """
|
||||||
|
pragma circom 2.1.0;
|
||||||
|
|
||||||
|
template NewCircuit() {
|
||||||
|
signal input a;
|
||||||
|
signal output b;
|
||||||
|
b <== a + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
component main {public [b]} = NewCircuit();
|
||||||
|
""";
|
||||||
|
|
||||||
|
System.out.println("\nInitializing setup for new circuit...");
|
||||||
|
SetupResult setup = zk.setup().initialize(SetupInitRequest.builder()
|
||||||
|
.circuit(circuit)
|
||||||
|
.format(CircuitFormat.CIRCOM)
|
||||||
|
.name("new_circuit_setup")
|
||||||
|
.provingSystem(ProvingSystem.GROTH16)
|
||||||
|
.ceremonyType("powers_of_tau")
|
||||||
|
.build()).get();
|
||||||
|
System.out.println("Setup initialized:");
|
||||||
|
System.out.println(" Ceremony ID: " + setup.getCeremonyId());
|
||||||
|
System.out.println(" Powers of Tau required: " + setup.getPowersRequired());
|
||||||
|
System.out.println(" Current phase: " + setup.getPhase());
|
||||||
|
|
||||||
|
// Contribute to ceremony
|
||||||
|
System.out.println("\nContributing to ceremony...");
|
||||||
|
Contribution contribution = zk.setup().contribute(ContributeRequest.builder()
|
||||||
|
.ceremonyId(setup.getCeremonyId())
|
||||||
|
.entropy(bytesToHex("random-entropy-from-user".getBytes()))
|
||||||
|
.build()).get();
|
||||||
|
System.out.println("Contribution submitted:");
|
||||||
|
System.out.println(" Participant: " + contribution.getParticipantId());
|
||||||
|
System.out.println(" Contribution hash: " + contribution.getHash());
|
||||||
|
System.out.println(" Verification status: " + contribution.isVerified());
|
||||||
|
|
||||||
|
// Get ceremony status
|
||||||
|
CeremonyStatus status = zk.setup().getStatus(setup.getCeremonyId()).get();
|
||||||
|
System.out.println("\nCeremony status:");
|
||||||
|
System.out.println(" Phase: " + status.getPhase());
|
||||||
|
System.out.println(" Total contributions: " + status.getTotalContributions());
|
||||||
|
System.out.println(" Verified contributions: " + status.getVerifiedContributions());
|
||||||
|
System.out.println(" Ready for finalization: " + status.isReadyForFinalization());
|
||||||
|
|
||||||
|
// Finalize setup (when enough contributions)
|
||||||
|
if (status.isReadyForFinalization()) {
|
||||||
|
System.out.println("\nFinalizing setup...");
|
||||||
|
FinalizedSetup finalized = zk.setup().finalize(setup.getCeremonyId()).get();
|
||||||
|
System.out.println("Setup finalized:");
|
||||||
|
System.out.println(" Proving key hash: " + finalized.getProvingKeyHash());
|
||||||
|
System.out.println(" Verification key hash: " + finalized.getVerificationKeyHash());
|
||||||
|
System.out.println(" Contribution transcript: " + finalized.getTranscriptCid());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Download ceremony transcript
|
||||||
|
byte[] transcript = zk.setup().getTranscript(setup.getCeremonyId()).get();
|
||||||
|
System.out.println("\nCeremony transcript: " + transcript.length + " bytes");
|
||||||
|
|
||||||
|
System.out.println();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String bytesToHex(byte[] bytes) {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (byte b : bytes) {
|
||||||
|
sb.append(String.format("%02x", b));
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
353
sdk/kotlin/examples/CompilerExample.kt
Normal file
353
sdk/kotlin/examples/CompilerExample.kt
Normal file
|
|
@ -0,0 +1,353 @@
|
||||||
|
package io.synor.examples
|
||||||
|
|
||||||
|
import io.synor.compiler.*
|
||||||
|
import io.synor.compiler.types.*
|
||||||
|
import kotlinx.coroutines.runBlocking
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Synor Compiler SDK Examples for Kotlin
|
||||||
|
*
|
||||||
|
* Demonstrates smart contract compilation and analysis:
|
||||||
|
* - WASM contract compilation and optimization
|
||||||
|
* - ABI extraction and encoding
|
||||||
|
* - Contract analysis and security scanning
|
||||||
|
* - Validation and verification
|
||||||
|
*/
|
||||||
|
fun main() = runBlocking {
|
||||||
|
// Initialize client
|
||||||
|
val config = CompilerConfig(
|
||||||
|
apiKey = System.getenv("SYNOR_API_KEY") ?: "your-api-key",
|
||||||
|
endpoint = "https://compiler.synor.io/v1",
|
||||||
|
timeout = 60_000,
|
||||||
|
retries = 3,
|
||||||
|
debug = false,
|
||||||
|
defaultOptimizationLevel = OptimizationLevel.SIZE,
|
||||||
|
maxContractSize = 256 * 1024,
|
||||||
|
useWasmOpt = true,
|
||||||
|
validate = true,
|
||||||
|
extractMetadata = true,
|
||||||
|
generateAbi = true
|
||||||
|
)
|
||||||
|
|
||||||
|
val compiler = SynorCompiler(config)
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Check service health
|
||||||
|
val healthy = compiler.healthCheck()
|
||||||
|
println("Service healthy: $healthy\n")
|
||||||
|
|
||||||
|
// Run examples
|
||||||
|
compileContractExample(compiler)
|
||||||
|
compilationModesExample(compiler)
|
||||||
|
abiExample(compiler)
|
||||||
|
analysisExample(compiler)
|
||||||
|
validationExample(compiler)
|
||||||
|
securityExample(compiler)
|
||||||
|
} finally {
|
||||||
|
compiler.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a minimal valid WASM module for testing.
|
||||||
|
*/
|
||||||
|
fun createMinimalWasm(): ByteArray {
|
||||||
|
return byteArrayOf(
|
||||||
|
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
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun compileContractExample(compiler: SynorCompiler) {
|
||||||
|
println("=== Contract Compilation ===")
|
||||||
|
|
||||||
|
val wasm = createMinimalWasm()
|
||||||
|
|
||||||
|
val result = compiler.compile(
|
||||||
|
wasm,
|
||||||
|
CompileOptions(
|
||||||
|
optimizationLevel = OptimizationLevel.SIZE,
|
||||||
|
useWasmOpt = true,
|
||||||
|
validate = true,
|
||||||
|
extractMetadata = true,
|
||||||
|
generateAbi = true,
|
||||||
|
stripOptions = StripOptions(
|
||||||
|
stripDebug = true,
|
||||||
|
stripProducers = true,
|
||||||
|
stripNames = true,
|
||||||
|
stripCustom = true,
|
||||||
|
stripUnused = true,
|
||||||
|
preserveSections = emptyList()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
println("Compilation result:")
|
||||||
|
println(" Contract ID: ${result.contractId}")
|
||||||
|
println(" Code hash: ${result.codeHash}")
|
||||||
|
println(" Original size: ${result.originalSize} bytes")
|
||||||
|
println(" Optimized size: ${result.optimizedSize} bytes")
|
||||||
|
println(" Size reduction: ${"%.1f".format(result.sizeReduction)}%")
|
||||||
|
println(" Estimated deploy gas: ${result.estimatedDeployGas}")
|
||||||
|
|
||||||
|
result.metadata?.let { metadata ->
|
||||||
|
println("\nMetadata:")
|
||||||
|
println(" Name: ${metadata.name}")
|
||||||
|
println(" Version: ${metadata.version}")
|
||||||
|
println(" SDK Version: ${metadata.sdkVersion}")
|
||||||
|
}
|
||||||
|
|
||||||
|
result.abi?.let { abi ->
|
||||||
|
println("\nABI:")
|
||||||
|
println(" Functions: ${abi.functions?.size ?: 0}")
|
||||||
|
println(" Events: ${abi.events?.size ?: 0}")
|
||||||
|
println(" Errors: ${abi.errors?.size ?: 0}")
|
||||||
|
}
|
||||||
|
|
||||||
|
println()
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun compilationModesExample(compiler: SynorCompiler) {
|
||||||
|
println("=== Compilation Modes ===")
|
||||||
|
|
||||||
|
val wasm = createMinimalWasm()
|
||||||
|
|
||||||
|
// Development mode: fast compilation, debugging support
|
||||||
|
println("Development mode:")
|
||||||
|
val devResult = compiler.contracts.compileDev(wasm)
|
||||||
|
println(" Size: ${devResult.optimizedSize} bytes")
|
||||||
|
println(" Optimization: none")
|
||||||
|
|
||||||
|
// Production mode: maximum optimization
|
||||||
|
println("\nProduction mode:")
|
||||||
|
val prodResult = compiler.contracts.compileProduction(wasm)
|
||||||
|
println(" Size: ${prodResult.optimizedSize} bytes")
|
||||||
|
println(" Optimization: aggressive")
|
||||||
|
println(" Size savings: ${devResult.optimizedSize - prodResult.optimizedSize} bytes")
|
||||||
|
|
||||||
|
// Custom optimization levels
|
||||||
|
println("\nOptimization levels:")
|
||||||
|
val levels = listOf(
|
||||||
|
OptimizationLevel.NONE,
|
||||||
|
OptimizationLevel.BASIC,
|
||||||
|
OptimizationLevel.SIZE,
|
||||||
|
OptimizationLevel.AGGRESSIVE
|
||||||
|
)
|
||||||
|
|
||||||
|
for (level in levels) {
|
||||||
|
val result = compiler.compile(
|
||||||
|
wasm,
|
||||||
|
CompileOptions(optimizationLevel = level)
|
||||||
|
)
|
||||||
|
println(" $level: ${result.optimizedSize} bytes")
|
||||||
|
}
|
||||||
|
|
||||||
|
println()
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun abiExample(compiler: SynorCompiler) {
|
||||||
|
println("=== ABI Operations ===")
|
||||||
|
|
||||||
|
val wasm = createMinimalWasm()
|
||||||
|
|
||||||
|
// Extract ABI from WASM
|
||||||
|
val abi = compiler.abi.extract(wasm)
|
||||||
|
println("Contract: ${abi.name}")
|
||||||
|
println("Version: ${abi.version}")
|
||||||
|
|
||||||
|
// List functions
|
||||||
|
abi.functions?.takeIf { it.isNotEmpty() }?.let { functions ->
|
||||||
|
println("\nFunctions:")
|
||||||
|
for (func in functions) {
|
||||||
|
val inputs = func.inputs?.joinToString(", ") { "${it.name}: ${it.type.typeName}" } ?: ""
|
||||||
|
val outputs = func.outputs?.joinToString(", ") { it.type.typeName } ?: "void"
|
||||||
|
val modifiers = buildList {
|
||||||
|
if (func.view) add("view")
|
||||||
|
if (func.payable) add("payable")
|
||||||
|
}.joinToString(" ")
|
||||||
|
|
||||||
|
println(" ${func.name}($inputs) -> $outputs $modifiers")
|
||||||
|
println(" Selector: ${func.selector}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// List events
|
||||||
|
abi.events?.takeIf { it.isNotEmpty() }?.let { events ->
|
||||||
|
println("\nEvents:")
|
||||||
|
for (event in events) {
|
||||||
|
val params = event.params?.joinToString(", ") {
|
||||||
|
"${if (it.indexed) "indexed " else ""}${it.name}: ${it.type.typeName}"
|
||||||
|
} ?: ""
|
||||||
|
println(" ${event.name}($params)")
|
||||||
|
println(" Topic: ${event.topic}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Encode a function call
|
||||||
|
abi.functions?.firstOrNull()?.let { func ->
|
||||||
|
val encoded = compiler.abi.encodeCall(func, listOf("arg1", "arg2"))
|
||||||
|
println("\nEncoded call to ${func.name}: $encoded")
|
||||||
|
|
||||||
|
// Decode a result
|
||||||
|
val decoded = compiler.abi.decodeResult(func, encoded)
|
||||||
|
println("Decoded result: $decoded")
|
||||||
|
}
|
||||||
|
|
||||||
|
println()
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun analysisExample(compiler: SynorCompiler) {
|
||||||
|
println("=== Contract Analysis ===")
|
||||||
|
|
||||||
|
val wasm = createMinimalWasm()
|
||||||
|
|
||||||
|
// Full analysis
|
||||||
|
val analysis = compiler.analysis.analyze(wasm)
|
||||||
|
|
||||||
|
// Size breakdown
|
||||||
|
analysis.sizeBreakdown?.let { size ->
|
||||||
|
println("Size breakdown:")
|
||||||
|
println(" Code: ${size.code} bytes")
|
||||||
|
println(" Data: ${size.data} bytes")
|
||||||
|
println(" Functions: ${size.functions} bytes")
|
||||||
|
println(" Memory: ${size.memory} bytes")
|
||||||
|
println(" Exports: ${size.exports} bytes")
|
||||||
|
println(" Imports: ${size.imports} bytes")
|
||||||
|
println(" Total: ${size.total} bytes")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function analysis
|
||||||
|
analysis.functions?.takeIf { it.isNotEmpty() }?.let { functions ->
|
||||||
|
println("\nFunction analysis:")
|
||||||
|
for (func in functions.take(5)) {
|
||||||
|
println(" ${func.name}:")
|
||||||
|
println(" Size: ${func.size} bytes")
|
||||||
|
println(" Instructions: ${func.instructionCount}")
|
||||||
|
println(" Locals: ${func.localCount}")
|
||||||
|
println(" Exported: ${func.exported}")
|
||||||
|
println(" Estimated gas: ${func.estimatedGas}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Import analysis
|
||||||
|
analysis.imports?.takeIf { it.isNotEmpty() }?.let { imports ->
|
||||||
|
println("\nImports:")
|
||||||
|
for (imp in imports) {
|
||||||
|
println(" ${imp.module}.${imp.name} (${imp.kind})")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gas analysis
|
||||||
|
analysis.gasAnalysis?.let { gas ->
|
||||||
|
println("\nGas analysis:")
|
||||||
|
println(" Deployment: ${gas.deploymentGas}")
|
||||||
|
println(" Memory init: ${gas.memoryInitGas}")
|
||||||
|
println(" Data section: ${gas.dataSectionGas}")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract metadata
|
||||||
|
val metadata = compiler.analysis.extractMetadata(wasm)
|
||||||
|
println("\nContract metadata:")
|
||||||
|
println(" Name: ${metadata.name}")
|
||||||
|
println(" Version: ${metadata.version}")
|
||||||
|
println(" Build timestamp: ${metadata.buildTimestamp}")
|
||||||
|
|
||||||
|
// Estimate deployment gas
|
||||||
|
val gasEstimate = compiler.analysis.estimateDeployGas(wasm)
|
||||||
|
println("\nEstimated deployment gas: $gasEstimate")
|
||||||
|
|
||||||
|
println()
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun validationExample(compiler: SynorCompiler) {
|
||||||
|
println("=== Contract Validation ===")
|
||||||
|
|
||||||
|
val wasm = createMinimalWasm()
|
||||||
|
|
||||||
|
// Full validation
|
||||||
|
val result = compiler.validation.validate(wasm)
|
||||||
|
println("Valid: ${result.valid}")
|
||||||
|
println("Exports: ${result.exportCount}")
|
||||||
|
println("Imports: ${result.importCount}")
|
||||||
|
println("Functions: ${result.functionCount}")
|
||||||
|
println("Memory pages: ${result.memoryPages}")
|
||||||
|
|
||||||
|
result.errors?.takeIf { it.isNotEmpty() }?.let { errors ->
|
||||||
|
println("\nValidation errors:")
|
||||||
|
for (error in errors) {
|
||||||
|
println(" [${error.code}] ${error.message}")
|
||||||
|
error.location?.let { println(" at $it") }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result.warnings?.takeIf { it.isNotEmpty() }?.let { warnings ->
|
||||||
|
println("\nWarnings:")
|
||||||
|
for (warning in warnings) {
|
||||||
|
println(" $warning")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Quick validation
|
||||||
|
val isValid = compiler.validation.isValid(wasm)
|
||||||
|
println("\nQuick validation: $isValid")
|
||||||
|
|
||||||
|
// Get validation errors only
|
||||||
|
val errors = compiler.validation.getErrors(wasm)
|
||||||
|
println("Error count: ${errors.size}")
|
||||||
|
|
||||||
|
// Validate required exports
|
||||||
|
val hasRequired = compiler.validation.validateExports(
|
||||||
|
wasm,
|
||||||
|
listOf("init", "execute", "query")
|
||||||
|
)
|
||||||
|
println("Has required exports: $hasRequired")
|
||||||
|
|
||||||
|
// Validate memory constraints
|
||||||
|
val memoryValid = compiler.validation.validateMemory(wasm, maxPages = 16)
|
||||||
|
println("Memory within 16 pages: $memoryValid")
|
||||||
|
|
||||||
|
println()
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun securityExample(compiler: SynorCompiler) {
|
||||||
|
println("=== Security Scanning ===")
|
||||||
|
|
||||||
|
val wasm = createMinimalWasm()
|
||||||
|
|
||||||
|
val security = compiler.analysis.securityScan(wasm)
|
||||||
|
|
||||||
|
println("Security score: ${security.score}/100")
|
||||||
|
|
||||||
|
security.issues?.takeIf { it.isNotEmpty() }?.let { issues ->
|
||||||
|
println("\nSecurity issues:")
|
||||||
|
val severityIcons = mapOf(
|
||||||
|
"critical" to "[CRIT]",
|
||||||
|
"high" to "[HIGH]",
|
||||||
|
"medium" to "[MED]",
|
||||||
|
"low" to "[LOW]"
|
||||||
|
)
|
||||||
|
for (issue in issues) {
|
||||||
|
val icon = severityIcons[issue.severity.lowercase()] ?: "[???]"
|
||||||
|
println("$icon [${issue.severity.uppercase()}] ${issue.type}")
|
||||||
|
println(" ${issue.description}")
|
||||||
|
issue.location?.let { println(" at $it") }
|
||||||
|
}
|
||||||
|
} ?: println("No security issues found!")
|
||||||
|
|
||||||
|
security.recommendations?.takeIf { it.isNotEmpty() }?.let { recommendations ->
|
||||||
|
println("\nRecommendations:")
|
||||||
|
for (rec in recommendations) {
|
||||||
|
println(" • $rec")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
println()
|
||||||
|
}
|
||||||
233
sdk/kotlin/examples/CryptoExample.kt
Normal file
233
sdk/kotlin/examples/CryptoExample.kt
Normal file
|
|
@ -0,0 +1,233 @@
|
||||||
|
package io.synor.examples
|
||||||
|
|
||||||
|
import io.synor.crypto.*
|
||||||
|
import io.synor.crypto.types.*
|
||||||
|
import kotlinx.coroutines.runBlocking
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Synor Crypto SDK Examples for Kotlin
|
||||||
|
*
|
||||||
|
* Demonstrates quantum-resistant cryptographic operations:
|
||||||
|
* - Hybrid Ed25519 + Dilithium3 signatures
|
||||||
|
* - BIP-39 mnemonic generation and validation
|
||||||
|
* - Post-quantum algorithms (Falcon, SPHINCS+)
|
||||||
|
* - Key derivation functions
|
||||||
|
*/
|
||||||
|
fun main() = runBlocking {
|
||||||
|
// Initialize client
|
||||||
|
val config = CryptoConfig(
|
||||||
|
apiKey = System.getenv("SYNOR_API_KEY") ?: "your-api-key",
|
||||||
|
endpoint = "https://crypto.synor.io/v1",
|
||||||
|
timeout = 30_000,
|
||||||
|
retries = 3,
|
||||||
|
debug = false,
|
||||||
|
defaultNetwork = Network.MAINNET
|
||||||
|
)
|
||||||
|
|
||||||
|
val crypto = SynorCrypto(config)
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Check service health
|
||||||
|
val healthy = crypto.healthCheck()
|
||||||
|
println("Service healthy: $healthy\n")
|
||||||
|
|
||||||
|
// Run examples
|
||||||
|
mnemonicExample(crypto)
|
||||||
|
keypairExample(crypto)
|
||||||
|
signingExample(crypto)
|
||||||
|
falconExample(crypto)
|
||||||
|
sphincsExample(crypto)
|
||||||
|
kdfExample(crypto)
|
||||||
|
hashExample(crypto)
|
||||||
|
} finally {
|
||||||
|
crypto.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun mnemonicExample(crypto: SynorCrypto) {
|
||||||
|
println("=== Mnemonic Operations ===")
|
||||||
|
|
||||||
|
// Generate a 24-word mnemonic (256-bit entropy)
|
||||||
|
val mnemonic = crypto.mnemonic.generate(24)
|
||||||
|
println("Generated mnemonic: ${mnemonic.phrase}")
|
||||||
|
println("Word count: ${mnemonic.wordCount}")
|
||||||
|
|
||||||
|
// Validate a mnemonic
|
||||||
|
val validation = crypto.mnemonic.validate(mnemonic.phrase)
|
||||||
|
println("Valid: ${validation.isValid}")
|
||||||
|
if (!validation.isValid) {
|
||||||
|
println("Error: ${validation.error}")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert mnemonic to seed
|
||||||
|
val seed = crypto.mnemonic.toSeed(mnemonic.phrase, "optional-passphrase")
|
||||||
|
println("Seed (hex): ${seed.toHex().take(32)}...")
|
||||||
|
|
||||||
|
// Word suggestions for autocomplete
|
||||||
|
val suggestions = crypto.mnemonic.suggestWords("aban", limit = 5)
|
||||||
|
println("Suggestions for 'aban': ${suggestions.joinToString(", ")}")
|
||||||
|
|
||||||
|
println()
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun keypairExample(crypto: SynorCrypto) {
|
||||||
|
println("=== Keypair Operations ===")
|
||||||
|
|
||||||
|
// Generate a random keypair
|
||||||
|
val keypair = crypto.keypairs.generate()
|
||||||
|
println("Generated hybrid keypair:")
|
||||||
|
println(" Ed25519 public key size: ${keypair.publicKey.ed25519Bytes.size} bytes")
|
||||||
|
println(" Dilithium public key size: ${keypair.publicKey.dilithiumBytes.size} bytes")
|
||||||
|
println(" Total public key size: ${keypair.publicKey.size} bytes")
|
||||||
|
|
||||||
|
// Get addresses for different networks
|
||||||
|
println("\nAddresses:")
|
||||||
|
println(" Mainnet: ${keypair.getAddress(Network.MAINNET)}")
|
||||||
|
println(" Testnet: ${keypair.getAddress(Network.TESTNET)}")
|
||||||
|
println(" Devnet: ${keypair.getAddress(Network.DEVNET)}")
|
||||||
|
|
||||||
|
// Create keypair from mnemonic (deterministic)
|
||||||
|
val mnemonic = crypto.mnemonic.generate(24)
|
||||||
|
val keypair2 = crypto.keypairs.fromMnemonic(mnemonic.phrase, "")
|
||||||
|
val addr = keypair2.getAddress(Network.MAINNET)
|
||||||
|
println("\nKeypair from mnemonic: ${addr.take(20)}...")
|
||||||
|
|
||||||
|
// Derive child keypair using BIP-44 path
|
||||||
|
val path = DerivationPath.external(0, 0) // m/44'/21337'/0'/0/0
|
||||||
|
println("Derivation path: $path")
|
||||||
|
|
||||||
|
println()
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun signingExample(crypto: SynorCrypto) {
|
||||||
|
println("=== Hybrid Signing ===")
|
||||||
|
|
||||||
|
// Generate keypair
|
||||||
|
val keypair = crypto.keypairs.generate()
|
||||||
|
|
||||||
|
// Sign a message
|
||||||
|
val message = "Hello, quantum-resistant world!".toByteArray()
|
||||||
|
val signature = crypto.signing.sign(keypair, message)
|
||||||
|
|
||||||
|
println("Signature created:")
|
||||||
|
println(" Ed25519 component: ${signature.ed25519Bytes.size} bytes")
|
||||||
|
println(" Dilithium component: ${signature.dilithiumBytes.size} bytes")
|
||||||
|
println(" Total signature size: ${signature.size} bytes")
|
||||||
|
|
||||||
|
// Verify the signature
|
||||||
|
val valid = crypto.signing.verify(keypair.publicKey, message, signature)
|
||||||
|
println("\nVerification result: $valid")
|
||||||
|
|
||||||
|
// Verify with tampered message fails
|
||||||
|
val tamperedMessage = "Hello, tampered message!".toByteArray()
|
||||||
|
val invalidResult = crypto.signing.verify(keypair.publicKey, tamperedMessage, signature)
|
||||||
|
println("Tampered message verification: $invalidResult")
|
||||||
|
|
||||||
|
println()
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun falconExample(crypto: SynorCrypto) {
|
||||||
|
println("=== Falcon Post-Quantum Signatures ===")
|
||||||
|
|
||||||
|
// Generate Falcon-512 keypair (128-bit security)
|
||||||
|
val falcon512 = crypto.falcon.generate(FalconVariant.FALCON512)
|
||||||
|
println("Falcon-512 keypair:")
|
||||||
|
println(" Public key: ${falcon512.publicKey.keyBytes.size} bytes")
|
||||||
|
println(" Security level: 128-bit")
|
||||||
|
|
||||||
|
// Generate Falcon-1024 keypair (256-bit security)
|
||||||
|
val falcon1024 = crypto.falcon.generate(FalconVariant.FALCON1024)
|
||||||
|
println("\nFalcon-1024 keypair:")
|
||||||
|
println(" Public key: ${falcon1024.publicKey.keyBytes.size} bytes")
|
||||||
|
println(" Security level: 256-bit")
|
||||||
|
|
||||||
|
// Sign with Falcon-512
|
||||||
|
val message = "Post-quantum secure message".toByteArray()
|
||||||
|
val signature = crypto.falcon.sign(falcon512, message)
|
||||||
|
println("\nFalcon-512 signature: ${signature.signatureBytes.size} bytes")
|
||||||
|
|
||||||
|
// Verify
|
||||||
|
val valid = crypto.falcon.verify(falcon512.publicKey.keyBytes, message, signature)
|
||||||
|
println("Verification: $valid")
|
||||||
|
|
||||||
|
println()
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun sphincsExample(crypto: SynorCrypto) {
|
||||||
|
println("=== SPHINCS+ Hash-Based Signatures ===")
|
||||||
|
|
||||||
|
// SPHINCS+ variants with different security levels
|
||||||
|
val variants = listOf(
|
||||||
|
Triple(SphincsVariant.SHAKE128S, 128, 7856),
|
||||||
|
Triple(SphincsVariant.SHAKE192S, 192, 16224),
|
||||||
|
Triple(SphincsVariant.SHAKE256S, 256, 29792)
|
||||||
|
)
|
||||||
|
|
||||||
|
// Generate and demonstrate each variant
|
||||||
|
for ((variant, security, sigSize) in variants) {
|
||||||
|
val keypair = crypto.sphincs.generate(variant)
|
||||||
|
println("SPHINCS+ $variant:")
|
||||||
|
println(" Security level: $security-bit")
|
||||||
|
println(" Expected signature size: $sigSize bytes")
|
||||||
|
|
||||||
|
// Sign a message
|
||||||
|
val message = "Hash-based quantum security".toByteArray()
|
||||||
|
val signature = crypto.sphincs.sign(keypair, message)
|
||||||
|
println(" Actual signature size: ${signature.signatureBytes.size} bytes")
|
||||||
|
|
||||||
|
// Verify
|
||||||
|
val valid = crypto.sphincs.verify(keypair.publicKey.keyBytes, message, signature)
|
||||||
|
println(" Verification: $valid\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun kdfExample(crypto: SynorCrypto) {
|
||||||
|
println("=== Key Derivation Functions ===")
|
||||||
|
|
||||||
|
// HKDF (HMAC-based Key Derivation Function)
|
||||||
|
val seed = "master-secret-key-material-here".toByteArray()
|
||||||
|
val hkdfConfig = DerivationConfig(
|
||||||
|
salt = "application-salt".toByteArray(),
|
||||||
|
info = "encryption-key".toByteArray(),
|
||||||
|
outputLength = 32
|
||||||
|
)
|
||||||
|
|
||||||
|
val derivedKey = crypto.kdf.deriveKey(seed, hkdfConfig)
|
||||||
|
println("HKDF derived key: ${derivedKey.toHex()}")
|
||||||
|
|
||||||
|
// PBKDF2 (Password-Based Key Derivation Function)
|
||||||
|
val password = "user-password".toByteArray()
|
||||||
|
val pbkdf2Config = PasswordDerivationConfig(
|
||||||
|
salt = "random-salt-value".toByteArray(),
|
||||||
|
iterations = 100_000,
|
||||||
|
outputLength = 32
|
||||||
|
)
|
||||||
|
|
||||||
|
val passwordKey = crypto.kdf.deriveFromPassword(password, pbkdf2Config)
|
||||||
|
println("PBKDF2 derived key: ${passwordKey.toHex()}")
|
||||||
|
|
||||||
|
println()
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun hashExample(crypto: SynorCrypto) {
|
||||||
|
println("=== Hash Functions ===")
|
||||||
|
|
||||||
|
val data = "Data to hash".toByteArray()
|
||||||
|
|
||||||
|
// SHA3-256 (FIPS 202)
|
||||||
|
val sha3 = crypto.hash.sha3_256(data)
|
||||||
|
println("SHA3-256: ${sha3.hex}")
|
||||||
|
|
||||||
|
// BLAKE3 (fast, parallel)
|
||||||
|
val blake3 = crypto.hash.blake3(data)
|
||||||
|
println("BLAKE3: ${blake3.hex}")
|
||||||
|
|
||||||
|
// Keccak-256 (Ethereum compatible)
|
||||||
|
val keccak = crypto.hash.keccak256(data)
|
||||||
|
println("Keccak: ${keccak.hex}")
|
||||||
|
|
||||||
|
println()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extension function to convert ByteArray to hex string
|
||||||
|
fun ByteArray.toHex(): String = joinToString("") { "%02x".format(it) }
|
||||||
351
sdk/kotlin/examples/DexExample.kt
Normal file
351
sdk/kotlin/examples/DexExample.kt
Normal file
|
|
@ -0,0 +1,351 @@
|
||||||
|
package io.synor.examples
|
||||||
|
|
||||||
|
import io.synor.dex.*
|
||||||
|
import io.synor.dex.types.*
|
||||||
|
import kotlinx.coroutines.runBlocking
|
||||||
|
import java.math.BigDecimal
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Synor DEX SDK Examples for Kotlin
|
||||||
|
*
|
||||||
|
* Demonstrates decentralized exchange operations:
|
||||||
|
* - Spot trading (limit/market orders)
|
||||||
|
* - Perpetual futures trading
|
||||||
|
* - Liquidity provision (AMM pools)
|
||||||
|
* - Order book management
|
||||||
|
* - Portfolio tracking
|
||||||
|
*/
|
||||||
|
fun main() = runBlocking {
|
||||||
|
// Initialize client
|
||||||
|
val config = DexConfig(
|
||||||
|
apiKey = System.getenv("SYNOR_API_KEY") ?: "your-api-key",
|
||||||
|
endpoint = "https://dex.synor.io/v1",
|
||||||
|
timeout = 30_000,
|
||||||
|
retries = 3,
|
||||||
|
debug = false,
|
||||||
|
defaultMarket = "SYN-USDC"
|
||||||
|
)
|
||||||
|
|
||||||
|
val dex = SynorDex(config)
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Check service health
|
||||||
|
val healthy = dex.healthCheck()
|
||||||
|
println("Service healthy: $healthy\n")
|
||||||
|
|
||||||
|
// Run examples
|
||||||
|
marketsExample(dex)
|
||||||
|
spotTradingExample(dex)
|
||||||
|
perpsTradingExample(dex)
|
||||||
|
liquidityExample(dex)
|
||||||
|
orderbookExample(dex)
|
||||||
|
portfolioExample(dex)
|
||||||
|
} finally {
|
||||||
|
dex.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun marketsExample(dex: SynorDex) {
|
||||||
|
println("=== Markets ===")
|
||||||
|
|
||||||
|
// Get all markets
|
||||||
|
val markets = dex.markets.list()
|
||||||
|
println("Available markets: ${markets.size}")
|
||||||
|
|
||||||
|
markets.take(5).forEach { market ->
|
||||||
|
println("\n ${market.symbol}:")
|
||||||
|
println(" Base: ${market.baseAsset}, Quote: ${market.quoteAsset}")
|
||||||
|
println(" Price: ${market.lastPrice}")
|
||||||
|
println(" 24h Volume: ${market.volume24h}")
|
||||||
|
println(" 24h Change: ${market.change24h}%")
|
||||||
|
println(" Status: ${market.status}")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get specific market
|
||||||
|
val market = dex.markets.get("SYN-USDC")
|
||||||
|
println("\nSYN-USDC details:")
|
||||||
|
println(" Min order size: ${market.minOrderSize}")
|
||||||
|
println(" Tick size: ${market.tickSize}")
|
||||||
|
println(" Maker fee: ${market.makerFee}%")
|
||||||
|
println(" Taker fee: ${market.takerFee}%")
|
||||||
|
|
||||||
|
// Get market statistics
|
||||||
|
val stats = dex.markets.getStats("SYN-USDC")
|
||||||
|
println("\nMarket statistics:")
|
||||||
|
println(" High 24h: ${stats.high24h}")
|
||||||
|
println(" Low 24h: ${stats.low24h}")
|
||||||
|
println(" Open interest: ${stats.openInterest}")
|
||||||
|
println(" Funding rate: ${stats.fundingRate}%")
|
||||||
|
|
||||||
|
println()
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun spotTradingExample(dex: SynorDex) {
|
||||||
|
println("=== Spot Trading ===")
|
||||||
|
|
||||||
|
// Place a limit order
|
||||||
|
println("Placing limit buy order...")
|
||||||
|
val limitOrder = dex.spot.placeOrder(
|
||||||
|
OrderRequest(
|
||||||
|
market = "SYN-USDC",
|
||||||
|
side = OrderSide.BUY,
|
||||||
|
orderType = OrderType.LIMIT,
|
||||||
|
price = "1.50",
|
||||||
|
quantity = "100",
|
||||||
|
timeInForce = TimeInForce.GTC
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
println("Limit order placed:")
|
||||||
|
println(" Order ID: ${limitOrder.orderId}")
|
||||||
|
println(" Status: ${limitOrder.status}")
|
||||||
|
println(" Price: ${limitOrder.price}")
|
||||||
|
println(" Quantity: ${limitOrder.quantity}")
|
||||||
|
|
||||||
|
// Place a market order
|
||||||
|
println("\nPlacing market sell order...")
|
||||||
|
val marketOrder = dex.spot.placeOrder(
|
||||||
|
OrderRequest(
|
||||||
|
market = "SYN-USDC",
|
||||||
|
side = OrderSide.SELL,
|
||||||
|
orderType = OrderType.MARKET,
|
||||||
|
quantity = "50"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
println("Market order executed:")
|
||||||
|
println(" Order ID: ${marketOrder.orderId}")
|
||||||
|
println(" Status: ${marketOrder.status}")
|
||||||
|
println(" Filled: ${marketOrder.filledQuantity}")
|
||||||
|
println(" Avg price: ${marketOrder.averagePrice}")
|
||||||
|
|
||||||
|
// Get order status
|
||||||
|
val status = dex.spot.getOrder(limitOrder.orderId)
|
||||||
|
println("\nOrder status:")
|
||||||
|
println(" Status: ${status.status}")
|
||||||
|
println(" Filled: ${status.filledQuantity} / ${status.quantity}")
|
||||||
|
println(" Remaining: ${status.remainingQuantity}")
|
||||||
|
|
||||||
|
// Cancel order
|
||||||
|
println("\nCancelling order...")
|
||||||
|
dex.spot.cancelOrder(limitOrder.orderId)
|
||||||
|
println("Order cancelled successfully")
|
||||||
|
|
||||||
|
// Get open orders
|
||||||
|
val openOrders = dex.spot.getOpenOrders("SYN-USDC")
|
||||||
|
println("\nOpen orders: ${openOrders.size}")
|
||||||
|
|
||||||
|
// Get trade history
|
||||||
|
val trades = dex.spot.getTradeHistory("SYN-USDC", limit = 10)
|
||||||
|
println("\nRecent trades: ${trades.size}")
|
||||||
|
trades.take(3).forEach { trade ->
|
||||||
|
println(" ${trade.side} ${trade.quantity} @ ${trade.price} (${trade.timestamp})")
|
||||||
|
}
|
||||||
|
|
||||||
|
println()
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun perpsTradingExample(dex: SynorDex) {
|
||||||
|
println("=== Perpetual Futures Trading ===")
|
||||||
|
|
||||||
|
// Get available perps markets
|
||||||
|
val perpsMarkets = dex.perps.listMarkets()
|
||||||
|
println("Available perps markets: ${perpsMarkets.size}")
|
||||||
|
|
||||||
|
perpsMarkets.take(3).forEach { market ->
|
||||||
|
println(" ${market.symbol}: ${market.markPrice} (funding: ${market.fundingRate}%)")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open a long position
|
||||||
|
println("\nOpening long position...")
|
||||||
|
val position = dex.perps.openPosition(
|
||||||
|
PerpsOrderRequest(
|
||||||
|
market = "SYN-USDC-PERP",
|
||||||
|
side = OrderSide.BUY,
|
||||||
|
orderType = OrderType.LIMIT,
|
||||||
|
price = "1.50",
|
||||||
|
size = "1000",
|
||||||
|
leverage = 10,
|
||||||
|
reduceOnly = false
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
println("Position opened:")
|
||||||
|
println(" Position ID: ${position.positionId}")
|
||||||
|
println(" Size: ${position.size}")
|
||||||
|
println(" Entry price: ${position.entryPrice}")
|
||||||
|
println(" Leverage: ${position.leverage}x")
|
||||||
|
println(" Liquidation price: ${position.liquidationPrice}")
|
||||||
|
|
||||||
|
// Get position details
|
||||||
|
val details = dex.perps.getPosition(position.positionId)
|
||||||
|
println("\nPosition details:")
|
||||||
|
println(" Unrealized PnL: ${details.unrealizedPnL}")
|
||||||
|
println(" Margin: ${details.margin}")
|
||||||
|
println(" Margin ratio: ${details.marginRatio}%")
|
||||||
|
|
||||||
|
// Set stop loss and take profit
|
||||||
|
println("\nSetting stop loss and take profit...")
|
||||||
|
dex.perps.setStopLoss(position.positionId, "1.40")
|
||||||
|
println("Stop loss set at 1.40")
|
||||||
|
|
||||||
|
dex.perps.setTakeProfit(position.positionId, "1.80")
|
||||||
|
println("Take profit set at 1.80")
|
||||||
|
|
||||||
|
// Close position
|
||||||
|
println("\nClosing position...")
|
||||||
|
val closeResult = dex.perps.closePosition(position.positionId)
|
||||||
|
println("Position closed:")
|
||||||
|
println(" Realized PnL: ${closeResult.realizedPnL}")
|
||||||
|
println(" Close price: ${closeResult.closePrice}")
|
||||||
|
|
||||||
|
// Get all positions
|
||||||
|
val positions = dex.perps.getPositions()
|
||||||
|
println("\nOpen positions: ${positions.size}")
|
||||||
|
|
||||||
|
// Get funding history
|
||||||
|
val funding = dex.perps.getFundingHistory("SYN-USDC-PERP", limit = 10)
|
||||||
|
println("Funding payments: ${funding.size}")
|
||||||
|
|
||||||
|
println()
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun liquidityExample(dex: SynorDex) {
|
||||||
|
println("=== Liquidity Provision ===")
|
||||||
|
|
||||||
|
// Get available pools
|
||||||
|
val pools = dex.liquidity.listPools()
|
||||||
|
println("Available pools: ${pools.size}")
|
||||||
|
|
||||||
|
pools.take(3).forEach { pool ->
|
||||||
|
println("\n ${pool.name}:")
|
||||||
|
println(" TVL: \$${pool.tvl}")
|
||||||
|
println(" APR: ${pool.apr}%")
|
||||||
|
println(" Volume 24h: \$${pool.volume24h}")
|
||||||
|
println(" Fee tier: ${pool.feeTier}%")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get pool details
|
||||||
|
val pool = dex.liquidity.getPool("SYN-USDC")
|
||||||
|
println("\nSYN-USDC pool details:")
|
||||||
|
println(" Token0: ${pool.token0.symbol} (${pool.token0Reserve})")
|
||||||
|
println(" Token1: ${pool.token1.symbol} (${pool.token1Reserve})")
|
||||||
|
println(" Price: ${pool.price}")
|
||||||
|
println(" Total LP tokens: ${pool.totalLPTokens}")
|
||||||
|
|
||||||
|
// Add liquidity
|
||||||
|
println("\nAdding liquidity...")
|
||||||
|
val addResult = dex.liquidity.addLiquidity(
|
||||||
|
AddLiquidityRequest(
|
||||||
|
pool = "SYN-USDC",
|
||||||
|
amount0 = "100",
|
||||||
|
amount1 = "150",
|
||||||
|
slippageBps = 50 // 0.5%
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
println("Liquidity added:")
|
||||||
|
println(" LP tokens received: ${addResult.lpTokens}")
|
||||||
|
println(" Position ID: ${addResult.positionId}")
|
||||||
|
println(" Share of pool: ${addResult.shareOfPool}%")
|
||||||
|
|
||||||
|
// Get LP positions
|
||||||
|
val lpPositions = dex.liquidity.getPositions()
|
||||||
|
println("\nLP positions: ${lpPositions.size}")
|
||||||
|
lpPositions.forEach { pos ->
|
||||||
|
println(" ${pos.pool}: ${pos.lpTokens} LP tokens (value: \$${pos.value})")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Claim fees
|
||||||
|
println("\nClaiming fees...")
|
||||||
|
val fees = dex.liquidity.claimFees(addResult.positionId)
|
||||||
|
println("Fees claimed:")
|
||||||
|
println(" Token0: ${fees.amount0}")
|
||||||
|
println(" Token1: ${fees.amount1}")
|
||||||
|
|
||||||
|
// Remove liquidity
|
||||||
|
println("\nRemoving liquidity...")
|
||||||
|
val removeResult = dex.liquidity.removeLiquidity(
|
||||||
|
RemoveLiquidityRequest(
|
||||||
|
positionId = addResult.positionId,
|
||||||
|
lpTokens = addResult.lpTokens,
|
||||||
|
slippageBps = 50
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
println("Liquidity removed:")
|
||||||
|
println(" Token0 received: ${removeResult.amount0}")
|
||||||
|
println(" Token1 received: ${removeResult.amount1}")
|
||||||
|
|
||||||
|
println()
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun orderbookExample(dex: SynorDex) {
|
||||||
|
println("=== Order Book ===")
|
||||||
|
|
||||||
|
// Get order book snapshot
|
||||||
|
val orderbook = dex.orderbook.getSnapshot("SYN-USDC", depth = 10)
|
||||||
|
|
||||||
|
println("Order book for SYN-USDC:")
|
||||||
|
println("\nAsks (sells):")
|
||||||
|
orderbook.asks.take(5).forEach { ask ->
|
||||||
|
println(" ${ask.quantity} @ ${ask.price}")
|
||||||
|
}
|
||||||
|
|
||||||
|
println("\nBids (buys):")
|
||||||
|
orderbook.bids.take(5).forEach { bid ->
|
||||||
|
println(" ${bid.quantity} @ ${bid.price}")
|
||||||
|
}
|
||||||
|
|
||||||
|
println("\nSpread: ${orderbook.spread} (${orderbook.spreadPercent}%)")
|
||||||
|
println("Mid price: ${orderbook.midPrice}")
|
||||||
|
|
||||||
|
// Get recent trades
|
||||||
|
val recentTrades = dex.orderbook.getRecentTrades("SYN-USDC", limit = 10)
|
||||||
|
println("\nRecent trades:")
|
||||||
|
recentTrades.take(5).forEach { trade ->
|
||||||
|
println(" ${trade.side} ${trade.quantity} @ ${trade.price}")
|
||||||
|
}
|
||||||
|
|
||||||
|
println()
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun portfolioExample(dex: SynorDex) {
|
||||||
|
println("=== Portfolio ===")
|
||||||
|
|
||||||
|
// Get portfolio overview
|
||||||
|
val portfolio = dex.portfolio.getOverview()
|
||||||
|
|
||||||
|
println("Portfolio overview:")
|
||||||
|
println(" Total value: \$${portfolio.totalValue}")
|
||||||
|
println(" Available balance: \$${portfolio.availableBalance}")
|
||||||
|
println(" In orders: \$${portfolio.inOrders}")
|
||||||
|
println(" In positions: \$${portfolio.inPositions}")
|
||||||
|
println(" Unrealized PnL: \$${portfolio.unrealizedPnL}")
|
||||||
|
|
||||||
|
// Get balances
|
||||||
|
val balances = dex.portfolio.getBalances()
|
||||||
|
println("\nBalances:")
|
||||||
|
balances.forEach { balance ->
|
||||||
|
println(" ${balance.asset}: ${balance.total} (available: ${balance.available}, in orders: ${balance.inOrders})")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get PnL history
|
||||||
|
val pnlHistory = dex.portfolio.getPnLHistory(days = 30) // Last 30 days
|
||||||
|
println("\nPnL history (last ${pnlHistory.size} days):")
|
||||||
|
if (pnlHistory.isNotEmpty()) {
|
||||||
|
println(" Total PnL: \$${pnlHistory.last().cumulativePnL}")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get trade statistics
|
||||||
|
val stats = dex.portfolio.getStats()
|
||||||
|
println("\nTrade statistics:")
|
||||||
|
println(" Total trades: ${stats.totalTrades}")
|
||||||
|
println(" Win rate: ${stats.winRate}%")
|
||||||
|
println(" Avg profit: \$${stats.avgProfit}")
|
||||||
|
println(" Avg loss: \$${stats.avgLoss}")
|
||||||
|
println(" Best trade: \$${stats.bestTrade}")
|
||||||
|
println(" Worst trade: \$${stats.worstTrade}")
|
||||||
|
|
||||||
|
println()
|
||||||
|
}
|
||||||
366
sdk/kotlin/examples/IbcExample.kt
Normal file
366
sdk/kotlin/examples/IbcExample.kt
Normal file
|
|
@ -0,0 +1,366 @@
|
||||||
|
package io.synor.examples
|
||||||
|
|
||||||
|
import io.synor.ibc.*
|
||||||
|
import io.synor.ibc.types.*
|
||||||
|
import kotlinx.coroutines.runBlocking
|
||||||
|
import java.time.Duration
|
||||||
|
import java.time.Instant
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Synor IBC SDK Examples for Kotlin
|
||||||
|
*
|
||||||
|
* Demonstrates Inter-Blockchain Communication operations:
|
||||||
|
* - Cross-chain transfers and messages
|
||||||
|
* - Channel lifecycle management
|
||||||
|
* - Packet handling and acknowledgments
|
||||||
|
* - Relayer operations
|
||||||
|
* - Connection monitoring
|
||||||
|
*/
|
||||||
|
fun main() = runBlocking {
|
||||||
|
// Initialize client
|
||||||
|
val config = IbcConfig(
|
||||||
|
apiKey = System.getenv("SYNOR_API_KEY") ?: "your-api-key",
|
||||||
|
endpoint = "https://ibc.synor.io/v1",
|
||||||
|
timeout = 30_000,
|
||||||
|
retries = 3,
|
||||||
|
debug = false,
|
||||||
|
defaultChain = "synor-mainnet-1",
|
||||||
|
confirmations = 1
|
||||||
|
)
|
||||||
|
|
||||||
|
val ibc = SynorIbc(config)
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Check service health
|
||||||
|
val healthy = ibc.healthCheck()
|
||||||
|
println("Service healthy: $healthy\n")
|
||||||
|
|
||||||
|
// Run examples
|
||||||
|
chainsExample(ibc)
|
||||||
|
channelsExample(ibc)
|
||||||
|
transferExample(ibc)
|
||||||
|
packetExample(ibc)
|
||||||
|
relayerExample(ibc)
|
||||||
|
monitoringExample(ibc)
|
||||||
|
} finally {
|
||||||
|
ibc.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun chainsExample(ibc: SynorIbc) {
|
||||||
|
println("=== Chain Discovery ===")
|
||||||
|
|
||||||
|
// Get all connected chains
|
||||||
|
val chains = ibc.chains.list()
|
||||||
|
println("Connected chains: ${chains.size}")
|
||||||
|
|
||||||
|
chains.take(5).forEach { chain ->
|
||||||
|
println("\n ${chain.chainId}:")
|
||||||
|
println(" Name: ${chain.name}")
|
||||||
|
println(" Type: ${chain.chainType}")
|
||||||
|
println(" Status: ${chain.status}")
|
||||||
|
println(" Block height: ${chain.latestHeight}")
|
||||||
|
println(" Light client: ${chain.lightClient}")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get specific chain info
|
||||||
|
val synorChain = ibc.chains.get("synor-mainnet-1")
|
||||||
|
println("\nSynor chain details:")
|
||||||
|
println(" Bech32 prefix: ${synorChain.bech32Prefix}")
|
||||||
|
println(" Gas price: ${synorChain.gasPrice}")
|
||||||
|
println(" Supported features: ${synorChain.features.joinToString(", ")}")
|
||||||
|
|
||||||
|
// Get chain connections
|
||||||
|
val connections = ibc.chains.getConnections("synor-mainnet-1")
|
||||||
|
println("\nChain connections: ${connections.size}")
|
||||||
|
connections.take(3).forEach { conn ->
|
||||||
|
println(" ${conn.connectionId} -> ${conn.counterpartyChainId}")
|
||||||
|
}
|
||||||
|
|
||||||
|
println()
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun channelsExample(ibc: SynorIbc) {
|
||||||
|
println("=== Channel Management ===")
|
||||||
|
|
||||||
|
// List existing channels
|
||||||
|
val channels = ibc.channels.list()
|
||||||
|
println("Active channels: ${channels.size}")
|
||||||
|
|
||||||
|
channels.take(3).forEach { channel ->
|
||||||
|
println("\n Channel ${channel.channelId}:")
|
||||||
|
println(" Port: ${channel.portId}")
|
||||||
|
println(" State: ${channel.state}")
|
||||||
|
println(" Order: ${channel.ordering}")
|
||||||
|
println(" Counterparty: ${channel.counterpartyChannelId} on ${channel.counterpartyChainId}")
|
||||||
|
println(" Version: ${channel.version}")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new channel (4-step handshake)
|
||||||
|
println("\nInitiating channel creation...")
|
||||||
|
|
||||||
|
// Step 1: ChanOpenInit
|
||||||
|
val initResult = ibc.channels.openInit(
|
||||||
|
ChannelInitRequest(
|
||||||
|
portId = "transfer",
|
||||||
|
counterpartyChainId = "cosmos-hub-4",
|
||||||
|
counterpartyPortId = "transfer",
|
||||||
|
version = "ics20-1",
|
||||||
|
ordering = ChannelOrdering.UNORDERED
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
println("Channel init:")
|
||||||
|
println(" Channel ID: ${initResult.channelId}")
|
||||||
|
println(" State: ${initResult.state}")
|
||||||
|
println(" TX hash: ${initResult.txHash}")
|
||||||
|
|
||||||
|
// Step 2: Wait for ChanOpenTry (counterparty)
|
||||||
|
println("\nWaiting for counterparty ChanOpenTry...")
|
||||||
|
val tryState = ibc.channels.waitForState(
|
||||||
|
initResult.channelId,
|
||||||
|
ChannelState.TRYOPEN,
|
||||||
|
Duration.ofMinutes(5)
|
||||||
|
)
|
||||||
|
println("Channel state: $tryState")
|
||||||
|
|
||||||
|
// Step 3: ChanOpenAck
|
||||||
|
println("\nSending ChanOpenAck...")
|
||||||
|
val ackResult = ibc.channels.openAck(
|
||||||
|
ChannelAckRequest(
|
||||||
|
channelId = initResult.channelId,
|
||||||
|
counterpartyChannelId = "channel-0",
|
||||||
|
counterpartyVersion = "ics20-1"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
println("Ack TX: ${ackResult.txHash}")
|
||||||
|
|
||||||
|
// Step 4: Wait for ChanOpenConfirm (counterparty)
|
||||||
|
println("\nWaiting for channel to open...")
|
||||||
|
val openState = ibc.channels.waitForState(
|
||||||
|
initResult.channelId,
|
||||||
|
ChannelState.OPEN,
|
||||||
|
Duration.ofMinutes(5)
|
||||||
|
)
|
||||||
|
println("Channel is now: $openState")
|
||||||
|
|
||||||
|
// Get channel details
|
||||||
|
val channel = ibc.channels.get(initResult.channelId)
|
||||||
|
println("\nChannel details:")
|
||||||
|
println(" Sequences - Send: ${channel.nextSequenceSend}, Recv: ${channel.nextSequenceRecv}, Ack: ${channel.nextSequenceAck}")
|
||||||
|
|
||||||
|
println()
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun transferExample(ibc: SynorIbc) {
|
||||||
|
println("=== Cross-Chain Transfers ===")
|
||||||
|
|
||||||
|
// Get supported tokens for transfer
|
||||||
|
val tokens = ibc.transfers.getSupportedTokens("cosmos-hub-4")
|
||||||
|
println("Transferable tokens to Cosmos Hub:")
|
||||||
|
tokens.take(5).forEach { token ->
|
||||||
|
println(" ${token.symbol} (${token.denom})")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initiate a cross-chain transfer
|
||||||
|
println("\nInitiating transfer...")
|
||||||
|
val transfer = ibc.transfers.send(
|
||||||
|
TransferRequest(
|
||||||
|
sourceChannel = "channel-0",
|
||||||
|
denom = "usynor",
|
||||||
|
amount = "1000000",
|
||||||
|
receiver = "cosmos1...",
|
||||||
|
timeoutHeight = 0, // Use timestamp instead
|
||||||
|
timeoutTimestamp = Instant.now().plusSeconds(600).toEpochMilli() * 1_000_000L,
|
||||||
|
memo = "IBC transfer from Synor"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
println("Transfer initiated:")
|
||||||
|
println(" TX hash: ${transfer.txHash}")
|
||||||
|
println(" Sequence: ${transfer.sequence}")
|
||||||
|
println(" Packet ID: ${transfer.packetId}")
|
||||||
|
println(" Status: ${transfer.status}")
|
||||||
|
|
||||||
|
// Track transfer progress
|
||||||
|
println("\nTracking transfer...")
|
||||||
|
val status = ibc.transfers.track(transfer.packetId)
|
||||||
|
println("Current status: ${status.state}")
|
||||||
|
println("Source TX: ${status.sourceTxHash}")
|
||||||
|
status.destTxHash?.let { println("Dest TX: $it") }
|
||||||
|
|
||||||
|
// Wait for completion
|
||||||
|
println("\nWaiting for transfer completion...")
|
||||||
|
val finalStatus = ibc.transfers.waitForCompletion(
|
||||||
|
transfer.packetId,
|
||||||
|
Duration.ofMinutes(10)
|
||||||
|
)
|
||||||
|
|
||||||
|
println("Transfer completed:")
|
||||||
|
println(" Final status: ${finalStatus.state}")
|
||||||
|
println(" Acknowledgment: ${finalStatus.acknowledgment}")
|
||||||
|
|
||||||
|
// Get transfer history
|
||||||
|
val history = ibc.transfers.getHistory(limit = 10)
|
||||||
|
println("\nRecent transfers: ${history.size}")
|
||||||
|
history.take(3).forEach { t ->
|
||||||
|
println(" ${t.amount} ${t.denom} -> ${t.destChain} (${t.status})")
|
||||||
|
}
|
||||||
|
|
||||||
|
println()
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun packetExample(ibc: SynorIbc) {
|
||||||
|
println("=== Packet Operations ===")
|
||||||
|
|
||||||
|
// List pending packets
|
||||||
|
val pending = ibc.packets.listPending("channel-0")
|
||||||
|
println("Pending packets on channel-0: ${pending.size}")
|
||||||
|
|
||||||
|
pending.take(3).forEach { packet ->
|
||||||
|
println("\n Packet #${packet.sequence}:")
|
||||||
|
println(" Source: ${packet.sourcePort}/${packet.sourceChannel}")
|
||||||
|
println(" Dest: ${packet.destPort}/${packet.destChannel}")
|
||||||
|
println(" State: ${packet.state}")
|
||||||
|
println(" Timeout: ${packet.timeoutTimestamp}")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get specific packet
|
||||||
|
val packet = ibc.packets.get("channel-0", 1)
|
||||||
|
println("\nPacket details:")
|
||||||
|
println(" Data (hex): ${packet.dataHex.take(40)}...")
|
||||||
|
println(" Created: ${packet.createdAt}")
|
||||||
|
|
||||||
|
// Get packet commitment proof
|
||||||
|
val proof = ibc.packets.getCommitmentProof("channel-0", 1)
|
||||||
|
println("\nCommitment proof:")
|
||||||
|
println(" Height: ${proof.proofHeight}")
|
||||||
|
println(" Proof size: ${proof.proof.size} bytes")
|
||||||
|
|
||||||
|
// Get acknowledgment
|
||||||
|
val ack = ibc.packets.getAcknowledgment("channel-0", 1)
|
||||||
|
println("\nAcknowledgment:")
|
||||||
|
println(" Result: ${if (ack.success) "Success" else "Error: ${ack.error}"}")
|
||||||
|
println(" TX hash: ${ack.txHash}")
|
||||||
|
|
||||||
|
// List timed-out packets
|
||||||
|
val timedOut = ibc.packets.listTimedOut()
|
||||||
|
println("\nTimed-out packets: ${timedOut.size}")
|
||||||
|
|
||||||
|
// Timeout a packet manually
|
||||||
|
if (timedOut.isNotEmpty()) {
|
||||||
|
val toTimeout = timedOut.first()
|
||||||
|
println("\nProcessing timeout for packet #${toTimeout.sequence}")
|
||||||
|
val timeout = ibc.packets.timeout(toTimeout.sourceChannel, toTimeout.sequence)
|
||||||
|
println("Timeout TX: ${timeout.txHash}")
|
||||||
|
}
|
||||||
|
|
||||||
|
println()
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun relayerExample(ibc: SynorIbc) {
|
||||||
|
println("=== Relayer Operations ===")
|
||||||
|
|
||||||
|
// Get relayer status
|
||||||
|
val status = ibc.relayer.getStatus()
|
||||||
|
println("Relayer status:")
|
||||||
|
println(" Running: ${status.running}")
|
||||||
|
println(" Uptime: ${status.uptime}")
|
||||||
|
println(" Packets relayed: ${status.packetsRelayed}")
|
||||||
|
println(" Errors: ${status.errorCount}")
|
||||||
|
|
||||||
|
// List active paths
|
||||||
|
val paths = ibc.relayer.listPaths()
|
||||||
|
println("\nActive relay paths: ${paths.size}")
|
||||||
|
|
||||||
|
paths.forEach { path ->
|
||||||
|
println("\n ${path.pathId}:")
|
||||||
|
println(" ${path.sourceChain} <-> ${path.destChain}")
|
||||||
|
println(" Channel: ${path.sourceChannel} <-> ${path.destChannel}")
|
||||||
|
println(" Status: ${path.status}")
|
||||||
|
println(" Pending packets: ${path.pendingPackets}")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configure a new path
|
||||||
|
println("\nConfiguring new relay path...")
|
||||||
|
val newPath = ibc.relayer.addPath(
|
||||||
|
PathConfig(
|
||||||
|
sourceChain = "synor-mainnet-1",
|
||||||
|
destChain = "osmosis-1",
|
||||||
|
sourceChannel = "channel-1",
|
||||||
|
destChannel = "channel-100",
|
||||||
|
filterDenoms = listOf("usynor", "uosmo"),
|
||||||
|
minRelayAmount = "1000",
|
||||||
|
maxRelayAmount = "1000000000"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
println("Path created: ${newPath.pathId}")
|
||||||
|
|
||||||
|
// Start relaying on path
|
||||||
|
println("\nStarting relayer on path...")
|
||||||
|
ibc.relayer.startPath(newPath.pathId)
|
||||||
|
println("Relayer started")
|
||||||
|
|
||||||
|
// Manually relay pending packets
|
||||||
|
println("\nRelaying pending packets...")
|
||||||
|
val relayResult = ibc.relayer.relayPending(newPath.pathId)
|
||||||
|
println("Relayed ${relayResult.packetCount} packets")
|
||||||
|
println("TX hashes: ${relayResult.txHashes.size}")
|
||||||
|
|
||||||
|
// Get relay history
|
||||||
|
val history = ibc.relayer.getHistory(newPath.pathId, limit = 10)
|
||||||
|
println("\nRelay history:")
|
||||||
|
history.take(3).forEach { event ->
|
||||||
|
println(" ${event.timestamp}: ${event.eventType} - ${event.packetCount} packets")
|
||||||
|
}
|
||||||
|
|
||||||
|
println()
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun monitoringExample(ibc: SynorIbc) {
|
||||||
|
println("=== IBC Monitoring ===")
|
||||||
|
|
||||||
|
// Get IBC metrics
|
||||||
|
val metrics = ibc.monitoring.getMetrics()
|
||||||
|
println("IBC metrics:")
|
||||||
|
println(" Total channels: ${metrics.totalChannels}")
|
||||||
|
println(" Active channels: ${metrics.activeChannels}")
|
||||||
|
println(" Total packets: ${metrics.totalPackets}")
|
||||||
|
println(" Pending packets: ${metrics.pendingPackets}")
|
||||||
|
println(" Failed packets: ${metrics.failedPackets}")
|
||||||
|
println(" Avg relay time: ${metrics.avgRelayTime}ms")
|
||||||
|
|
||||||
|
// Get chain health
|
||||||
|
val chainHealth = ibc.monitoring.getChainHealth()
|
||||||
|
println("\nChain health:")
|
||||||
|
chainHealth.take(3).forEach { health ->
|
||||||
|
println(" ${health.chainId}:")
|
||||||
|
println(" Status: ${health.status}")
|
||||||
|
println(" Block lag: ${health.blockLag}")
|
||||||
|
println(" Last update: ${health.lastUpdate}")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get channel statistics
|
||||||
|
val stats = ibc.monitoring.getChannelStats("channel-0")
|
||||||
|
println("\nChannel-0 statistics:")
|
||||||
|
println(" Packets sent: ${stats.packetsSent}")
|
||||||
|
println(" Packets received: ${stats.packetsReceived}")
|
||||||
|
println(" Success rate: ${stats.successRate}%")
|
||||||
|
println(" Avg confirmation time: ${stats.avgConfirmationTime}ms")
|
||||||
|
|
||||||
|
// Subscribe to IBC events
|
||||||
|
println("\nSubscribing to IBC events...")
|
||||||
|
ibc.monitoring.subscribe { event ->
|
||||||
|
println("Event: ${event.type} on ${event.channelId}")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get alerts
|
||||||
|
val alerts = ibc.monitoring.getAlerts()
|
||||||
|
println("\nActive alerts: ${alerts.size}")
|
||||||
|
alerts.forEach { alert ->
|
||||||
|
println(" [${alert.severity}] ${alert.message}")
|
||||||
|
}
|
||||||
|
|
||||||
|
println()
|
||||||
|
}
|
||||||
369
sdk/kotlin/examples/ZkExample.kt
Normal file
369
sdk/kotlin/examples/ZkExample.kt
Normal file
|
|
@ -0,0 +1,369 @@
|
||||||
|
package io.synor.examples
|
||||||
|
|
||||||
|
import io.synor.zk.*
|
||||||
|
import io.synor.zk.types.*
|
||||||
|
import kotlinx.coroutines.runBlocking
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Synor ZK SDK Examples for Kotlin
|
||||||
|
*
|
||||||
|
* Demonstrates zero-knowledge proof operations:
|
||||||
|
* - Circuit compilation (Circom)
|
||||||
|
* - Proof generation and verification
|
||||||
|
* - Multiple proving systems (Groth16, PLONK, STARK)
|
||||||
|
* - Recursive proof composition
|
||||||
|
* - Trusted setup ceremonies
|
||||||
|
*/
|
||||||
|
fun main() = runBlocking {
|
||||||
|
// Initialize client
|
||||||
|
val config = ZkConfig(
|
||||||
|
apiKey = System.getenv("SYNOR_API_KEY") ?: "your-api-key",
|
||||||
|
endpoint = "https://zk.synor.io/v1",
|
||||||
|
timeout = 120_000, // ZK operations can be slow
|
||||||
|
retries = 3,
|
||||||
|
debug = false,
|
||||||
|
defaultProvingSystem = ProvingSystem.GROTH16,
|
||||||
|
proveTimeout = 300_000,
|
||||||
|
verifyTimeout = 30_000
|
||||||
|
)
|
||||||
|
|
||||||
|
val zk = SynorZk(config)
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Check service health
|
||||||
|
val healthy = zk.healthCheck()
|
||||||
|
println("Service healthy: $healthy\n")
|
||||||
|
|
||||||
|
// Run examples
|
||||||
|
circuitExample(zk)
|
||||||
|
groth16Example(zk)
|
||||||
|
plonkExample(zk)
|
||||||
|
starkExample(zk)
|
||||||
|
recursiveExample(zk)
|
||||||
|
ceremonyExample(zk)
|
||||||
|
} finally {
|
||||||
|
zk.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun circuitExample(zk: SynorZk) {
|
||||||
|
println("=== Circuit Compilation ===")
|
||||||
|
|
||||||
|
// Simple Circom circuit: prove knowledge of factors
|
||||||
|
val circomCode = """
|
||||||
|
pragma circom 2.1.0;
|
||||||
|
|
||||||
|
template Multiplier() {
|
||||||
|
signal input a;
|
||||||
|
signal input b;
|
||||||
|
signal output c;
|
||||||
|
|
||||||
|
c <== a * b;
|
||||||
|
}
|
||||||
|
|
||||||
|
component main = Multiplier();
|
||||||
|
""".trimIndent()
|
||||||
|
|
||||||
|
// Compile the circuit
|
||||||
|
println("Compiling circuit...")
|
||||||
|
val circuit = zk.circuits.compile(
|
||||||
|
CircuitSource(
|
||||||
|
code = circomCode,
|
||||||
|
language = CircuitLanguage.CIRCOM
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
println("Circuit compiled:")
|
||||||
|
println(" Circuit ID: ${circuit.circuitId}")
|
||||||
|
println(" Constraints: ${circuit.constraints}")
|
||||||
|
println(" Public inputs: ${circuit.publicInputs}")
|
||||||
|
println(" Private inputs: ${circuit.privateInputs}")
|
||||||
|
println(" Outputs: ${circuit.outputs}")
|
||||||
|
|
||||||
|
// Get circuit info
|
||||||
|
val info = zk.circuits.get(circuit.circuitId)
|
||||||
|
println("\nCircuit info:")
|
||||||
|
println(" Name: ${info.name}")
|
||||||
|
println(" Version: ${info.version}")
|
||||||
|
println(" Wires: ${info.wireCount}")
|
||||||
|
println(" Labels: ${info.labelCount}")
|
||||||
|
|
||||||
|
// List available circuits
|
||||||
|
val circuits = zk.circuits.list()
|
||||||
|
println("\nAvailable circuits: ${circuits.size}")
|
||||||
|
circuits.take(3).forEach { c ->
|
||||||
|
println(" ${c.circuitId}: ${c.name} (${c.constraints} constraints)")
|
||||||
|
}
|
||||||
|
|
||||||
|
println()
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun groth16Example(zk: SynorZk) {
|
||||||
|
println("=== Groth16 Proving System ===")
|
||||||
|
|
||||||
|
// Use a pre-compiled circuit
|
||||||
|
val circuitId = "multiplier-v1"
|
||||||
|
|
||||||
|
// Generate proving/verification keys (trusted setup)
|
||||||
|
println("Generating keys...")
|
||||||
|
val keys = zk.groth16.setup(circuitId)
|
||||||
|
println("Keys generated:")
|
||||||
|
println(" Proving key size: ${keys.provingKey.size} bytes")
|
||||||
|
println(" Verification key size: ${keys.verificationKey.size} bytes")
|
||||||
|
|
||||||
|
// Prepare witness (private inputs)
|
||||||
|
val witness = mapOf(
|
||||||
|
"a" to "3",
|
||||||
|
"b" to "7"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Generate proof
|
||||||
|
println("\nGenerating proof...")
|
||||||
|
val proof = zk.groth16.prove(
|
||||||
|
ProveRequest(
|
||||||
|
circuitId = circuitId,
|
||||||
|
witness = witness,
|
||||||
|
provingKey = keys.provingKey
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
println("Proof generated:")
|
||||||
|
println(" Proof size: ${proof.proofBytes.size} bytes")
|
||||||
|
println(" Public signals: ${proof.publicSignals}")
|
||||||
|
println(" Proving time: ${proof.provingTimeMs}ms")
|
||||||
|
|
||||||
|
// Verify proof
|
||||||
|
println("\nVerifying proof...")
|
||||||
|
val verified = zk.groth16.verify(
|
||||||
|
VerifyRequest(
|
||||||
|
proof = proof.proofBytes,
|
||||||
|
publicSignals = proof.publicSignals,
|
||||||
|
verificationKey = keys.verificationKey
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
println("Verification result: $verified")
|
||||||
|
|
||||||
|
// Export proof for on-chain verification
|
||||||
|
val solidityCalldata = zk.groth16.exportCalldata(proof)
|
||||||
|
println("\nSolidity calldata: ${solidityCalldata.take(100)}...")
|
||||||
|
|
||||||
|
println()
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun plonkExample(zk: SynorZk) {
|
||||||
|
println("=== PLONK Proving System ===")
|
||||||
|
|
||||||
|
val circuitId = "multiplier-v1"
|
||||||
|
|
||||||
|
// PLONK uses universal trusted setup
|
||||||
|
println("Getting universal setup...")
|
||||||
|
val srs = zk.plonk.getUniversalSetup(powersOfTau = 14) // 2^14 constraints
|
||||||
|
println("SRS loaded: ${srs.size} bytes")
|
||||||
|
|
||||||
|
// Generate circuit-specific keys
|
||||||
|
println("\nGenerating circuit keys...")
|
||||||
|
val keys = zk.plonk.setup(circuitId, srs)
|
||||||
|
println("Keys generated")
|
||||||
|
|
||||||
|
// Generate proof
|
||||||
|
val witness = mapOf("a" to "5", "b" to "9")
|
||||||
|
println("\nGenerating PLONK proof...")
|
||||||
|
val proof = zk.plonk.prove(
|
||||||
|
PlonkProveRequest(
|
||||||
|
circuitId = circuitId,
|
||||||
|
witness = witness,
|
||||||
|
provingKey = keys.provingKey
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
println("Proof generated:")
|
||||||
|
println(" Proof size: ${proof.proofBytes.size} bytes")
|
||||||
|
println(" Proving time: ${proof.provingTimeMs}ms")
|
||||||
|
|
||||||
|
// Verify proof
|
||||||
|
val verified = zk.plonk.verify(
|
||||||
|
PlonkVerifyRequest(
|
||||||
|
proof = proof.proofBytes,
|
||||||
|
publicSignals = proof.publicSignals,
|
||||||
|
verificationKey = keys.verificationKey
|
||||||
|
)
|
||||||
|
)
|
||||||
|
println("Verification result: $verified")
|
||||||
|
|
||||||
|
// Compare with Groth16
|
||||||
|
println("\nPLONK advantages:")
|
||||||
|
println(" - Universal trusted setup")
|
||||||
|
println(" - Larger proofs (~2.5 KB vs ~200 bytes)")
|
||||||
|
println(" - Faster proving for some circuits")
|
||||||
|
|
||||||
|
println()
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun starkExample(zk: SynorZk) {
|
||||||
|
println("=== STARK Proving System ===")
|
||||||
|
|
||||||
|
val circuitId = "multiplier-v1"
|
||||||
|
|
||||||
|
// STARKs don't need trusted setup
|
||||||
|
println("Configuring STARK parameters...")
|
||||||
|
val config = StarkConfig(
|
||||||
|
fieldSize = 256,
|
||||||
|
hashFunction = HashFunction.POSEIDON,
|
||||||
|
blowupFactor = 8,
|
||||||
|
numQueries = 30,
|
||||||
|
foldingFactor = 8
|
||||||
|
)
|
||||||
|
|
||||||
|
// Generate proof
|
||||||
|
val witness = mapOf("a" to "11", "b" to "13")
|
||||||
|
println("\nGenerating STARK proof...")
|
||||||
|
val proof = zk.stark.prove(
|
||||||
|
StarkProveRequest(
|
||||||
|
circuitId = circuitId,
|
||||||
|
witness = witness,
|
||||||
|
config = config
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
println("Proof generated:")
|
||||||
|
println(" Proof size: ${proof.proofBytes.size} bytes")
|
||||||
|
println(" Proving time: ${proof.provingTimeMs}ms")
|
||||||
|
println(" FRI layers: ${proof.friLayers}")
|
||||||
|
|
||||||
|
// Verify proof
|
||||||
|
println("\nVerifying STARK proof...")
|
||||||
|
val verified = zk.stark.verify(
|
||||||
|
StarkVerifyRequest(
|
||||||
|
proof = proof.proofBytes,
|
||||||
|
publicSignals = proof.publicSignals,
|
||||||
|
config = config
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
println("Verification result: $verified")
|
||||||
|
|
||||||
|
// Compare with SNARKs
|
||||||
|
println("\nSTARK advantages:")
|
||||||
|
println(" - No trusted setup needed")
|
||||||
|
println(" - Post-quantum secure")
|
||||||
|
println(" - Larger proofs (~100 KB)")
|
||||||
|
println(" - Faster proving for complex computations")
|
||||||
|
|
||||||
|
println()
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun recursiveExample(zk: SynorZk) {
|
||||||
|
println("=== Recursive Proof Composition ===")
|
||||||
|
|
||||||
|
// Create inner proofs
|
||||||
|
println("Generating inner proofs...")
|
||||||
|
val innerProofs = mutableListOf<RecursiveProof>()
|
||||||
|
|
||||||
|
for (i in 1..3) {
|
||||||
|
val witness = mapOf("a" to i.toString(), "b" to (i + 1).toString())
|
||||||
|
val proof = zk.recursive.proveInner(
|
||||||
|
RecursiveProveRequest(
|
||||||
|
circuitId = "multiplier-v1",
|
||||||
|
witness = witness,
|
||||||
|
level = 0
|
||||||
|
)
|
||||||
|
)
|
||||||
|
innerProofs.add(proof)
|
||||||
|
println(" Inner proof $i generated")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Aggregate proofs recursively
|
||||||
|
println("\nAggregating proofs...")
|
||||||
|
val aggregatedProof = zk.recursive.aggregate(
|
||||||
|
AggregateRequest(
|
||||||
|
proofs = innerProofs,
|
||||||
|
aggregationCircuit = "recursive-aggregator-v1"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
println("Aggregated proof:")
|
||||||
|
println(" Proof size: ${aggregatedProof.proofBytes.size} bytes")
|
||||||
|
println(" Proofs aggregated: ${aggregatedProof.proofsAggregated}")
|
||||||
|
println(" Recursion depth: ${aggregatedProof.recursionDepth}")
|
||||||
|
|
||||||
|
// Verify aggregated proof (verifies all inner proofs at once)
|
||||||
|
println("\nVerifying aggregated proof...")
|
||||||
|
val verified = zk.recursive.verifyAggregated(aggregatedProof)
|
||||||
|
println("Verification result: $verified")
|
||||||
|
|
||||||
|
// Use cases
|
||||||
|
println("\nRecursive proof use cases:")
|
||||||
|
println(" - Rollup batch verification")
|
||||||
|
println(" - Incremental computation proofs")
|
||||||
|
println(" - Cross-chain state proofs")
|
||||||
|
|
||||||
|
println()
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun ceremonyExample(zk: SynorZk) {
|
||||||
|
println("=== Trusted Setup Ceremony ===")
|
||||||
|
|
||||||
|
// List active ceremonies
|
||||||
|
val ceremonies = zk.ceremony.list(status = CeremonyStatus.ACTIVE)
|
||||||
|
println("Active ceremonies: ${ceremonies.size}")
|
||||||
|
|
||||||
|
ceremonies.take(3).forEach { ceremony ->
|
||||||
|
println("\n ${ceremony.ceremonyId}:")
|
||||||
|
println(" Circuit: ${ceremony.circuitId}")
|
||||||
|
println(" Participants: ${ceremony.participantCount}")
|
||||||
|
println(" Current round: ${ceremony.currentRound}")
|
||||||
|
println(" Status: ${ceremony.status}")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new ceremony
|
||||||
|
println("\nCreating new ceremony...")
|
||||||
|
val newCeremony = zk.ceremony.create(
|
||||||
|
CeremonyConfig(
|
||||||
|
circuitId = "new-circuit-v1",
|
||||||
|
minParticipants = 10,
|
||||||
|
maxParticipants = 100,
|
||||||
|
roundDuration = 3600, // 1 hour per round
|
||||||
|
verifyContributions = true
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
println("Ceremony created:")
|
||||||
|
println(" Ceremony ID: ${newCeremony.ceremonyId}")
|
||||||
|
println(" Join URL: ${newCeremony.joinUrl}")
|
||||||
|
|
||||||
|
// Participate in a ceremony
|
||||||
|
println("\nParticipating in ceremony...")
|
||||||
|
val contribution = zk.ceremony.contribute(
|
||||||
|
ContributionRequest(
|
||||||
|
ceremonyId = newCeremony.ceremonyId,
|
||||||
|
entropy = generateEntropy()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
println("Contribution made:")
|
||||||
|
println(" Contribution ID: ${contribution.contributionId}")
|
||||||
|
println(" Position: ${contribution.position}")
|
||||||
|
println(" Hash: ${contribution.hash}")
|
||||||
|
|
||||||
|
// Verify a contribution
|
||||||
|
println("\nVerifying contribution...")
|
||||||
|
val valid = zk.ceremony.verifyContribution(contribution.contributionId)
|
||||||
|
println("Contribution valid: $valid")
|
||||||
|
|
||||||
|
// Get ceremony transcript (for auditability)
|
||||||
|
val transcript = zk.ceremony.getTranscript(newCeremony.ceremonyId)
|
||||||
|
println("\nCeremony transcript:")
|
||||||
|
println(" Total contributions: ${transcript.contributions.size}")
|
||||||
|
println(" Start time: ${transcript.startTime}")
|
||||||
|
println(" Final hash: ${transcript.finalHash ?: "pending"}")
|
||||||
|
|
||||||
|
println()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper function to generate random entropy
|
||||||
|
fun generateEntropy(): ByteArray {
|
||||||
|
val entropy = ByteArray(32)
|
||||||
|
java.security.SecureRandom().nextBytes(entropy)
|
||||||
|
return entropy
|
||||||
|
}
|
||||||
352
sdk/swift/Examples/CompilerExample.swift
Normal file
352
sdk/swift/Examples/CompilerExample.swift
Normal file
|
|
@ -0,0 +1,352 @@
|
||||||
|
import Foundation
|
||||||
|
import SynorCompiler
|
||||||
|
|
||||||
|
/// Synor Compiler SDK Examples for Swift
|
||||||
|
///
|
||||||
|
/// Demonstrates smart contract compilation and analysis:
|
||||||
|
/// - WASM contract compilation and optimization
|
||||||
|
/// - ABI extraction and encoding
|
||||||
|
/// - Contract analysis and security scanning
|
||||||
|
/// - Validation and verification
|
||||||
|
|
||||||
|
@main
|
||||||
|
struct CompilerExample {
|
||||||
|
static func main() async throws {
|
||||||
|
// Initialize client
|
||||||
|
let config = CompilerConfig(
|
||||||
|
apiKey: ProcessInfo.processInfo.environment["SYNOR_API_KEY"] ?? "your-api-key",
|
||||||
|
endpoint: "https://compiler.synor.io/v1",
|
||||||
|
timeout: 60,
|
||||||
|
retries: 3,
|
||||||
|
debug: false,
|
||||||
|
defaultOptimizationLevel: .size,
|
||||||
|
maxContractSize: 256 * 1024,
|
||||||
|
useWasmOpt: true,
|
||||||
|
validate: true,
|
||||||
|
extractMetadata: true,
|
||||||
|
generateAbi: true
|
||||||
|
)
|
||||||
|
|
||||||
|
let compiler = SynorCompiler(config: config)
|
||||||
|
|
||||||
|
do {
|
||||||
|
// Check service health
|
||||||
|
let healthy = try await compiler.healthCheck()
|
||||||
|
print("Service healthy: \(healthy)\n")
|
||||||
|
|
||||||
|
// Run examples
|
||||||
|
try await compileContractExample(compiler: compiler)
|
||||||
|
try await compilationModesExample(compiler: compiler)
|
||||||
|
try await abiExample(compiler: compiler)
|
||||||
|
try await analysisExample(compiler: compiler)
|
||||||
|
try await validationExample(compiler: compiler)
|
||||||
|
try await securityExample(compiler: compiler)
|
||||||
|
} catch {
|
||||||
|
print("Error: \(error)")
|
||||||
|
}
|
||||||
|
|
||||||
|
await compiler.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a minimal valid WASM module for testing.
|
||||||
|
static func createMinimalWasm() -> Data {
|
||||||
|
return Data([
|
||||||
|
0x00, 0x61, 0x73, 0x6d, // Magic: \0asm
|
||||||
|
0x01, 0x00, 0x00, 0x00, // Version: 1
|
||||||
|
// Type section
|
||||||
|
0x01, 0x07, 0x01, 0x60, 0x02, 0x7f, 0x7f, 0x01, 0x7f,
|
||||||
|
// Function section
|
||||||
|
0x03, 0x02, 0x01, 0x00,
|
||||||
|
// Export section
|
||||||
|
0x07, 0x08, 0x01, 0x04, 0x61, 0x64, 0x64, 0x00, 0x00,
|
||||||
|
// Code section
|
||||||
|
0x0a, 0x09, 0x01, 0x07, 0x00, 0x20, 0x00, 0x20, 0x01, 0x6a, 0x0b
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
static func compileContractExample(compiler: SynorCompiler) async throws {
|
||||||
|
print("=== Contract Compilation ===")
|
||||||
|
|
||||||
|
let wasm = createMinimalWasm()
|
||||||
|
|
||||||
|
let result = try await compiler.compile(
|
||||||
|
wasm: wasm,
|
||||||
|
options: CompileOptions(
|
||||||
|
optimizationLevel: .size,
|
||||||
|
useWasmOpt: true,
|
||||||
|
validate: true,
|
||||||
|
extractMetadata: true,
|
||||||
|
generateAbi: true,
|
||||||
|
stripOptions: StripOptions(
|
||||||
|
stripDebug: true,
|
||||||
|
stripProducers: true,
|
||||||
|
stripNames: true,
|
||||||
|
stripCustom: true,
|
||||||
|
stripUnused: true,
|
||||||
|
preserveSections: []
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
print("Compilation result:")
|
||||||
|
print(" Contract ID: \(result.contractId)")
|
||||||
|
print(" Code hash: \(result.codeHash)")
|
||||||
|
print(" Original size: \(result.originalSize) bytes")
|
||||||
|
print(" Optimized size: \(result.optimizedSize) bytes")
|
||||||
|
print(" Size reduction: \(String(format: "%.1f", result.sizeReduction))%")
|
||||||
|
print(" Estimated deploy gas: \(result.estimatedDeployGas)")
|
||||||
|
|
||||||
|
if let metadata = result.metadata {
|
||||||
|
print("\nMetadata:")
|
||||||
|
print(" Name: \(metadata.name)")
|
||||||
|
print(" Version: \(metadata.version)")
|
||||||
|
print(" SDK Version: \(metadata.sdkVersion)")
|
||||||
|
}
|
||||||
|
|
||||||
|
if let abi = result.abi {
|
||||||
|
print("\nABI:")
|
||||||
|
print(" Functions: \(abi.functions?.count ?? 0)")
|
||||||
|
print(" Events: \(abi.events?.count ?? 0)")
|
||||||
|
print(" Errors: \(abi.errors?.count ?? 0)")
|
||||||
|
}
|
||||||
|
|
||||||
|
print()
|
||||||
|
}
|
||||||
|
|
||||||
|
static func compilationModesExample(compiler: SynorCompiler) async throws {
|
||||||
|
print("=== Compilation Modes ===")
|
||||||
|
|
||||||
|
let wasm = createMinimalWasm()
|
||||||
|
|
||||||
|
// Development mode: fast compilation, debugging support
|
||||||
|
print("Development mode:")
|
||||||
|
let devResult = try await compiler.contracts.compileDev(wasm: wasm)
|
||||||
|
print(" Size: \(devResult.optimizedSize) bytes")
|
||||||
|
print(" Optimization: none")
|
||||||
|
|
||||||
|
// Production mode: maximum optimization
|
||||||
|
print("\nProduction mode:")
|
||||||
|
let prodResult = try await compiler.contracts.compileProduction(wasm: wasm)
|
||||||
|
print(" Size: \(prodResult.optimizedSize) bytes")
|
||||||
|
print(" Optimization: aggressive")
|
||||||
|
print(" Size savings: \(devResult.optimizedSize - prodResult.optimizedSize) bytes")
|
||||||
|
|
||||||
|
// Custom optimization levels
|
||||||
|
print("\nOptimization levels:")
|
||||||
|
let levels: [OptimizationLevel] = [.none, .basic, .size, .aggressive]
|
||||||
|
|
||||||
|
for level in levels {
|
||||||
|
let result = try await compiler.compile(
|
||||||
|
wasm: wasm,
|
||||||
|
options: CompileOptions(optimizationLevel: level)
|
||||||
|
)
|
||||||
|
print(" \(level): \(result.optimizedSize) bytes")
|
||||||
|
}
|
||||||
|
|
||||||
|
print()
|
||||||
|
}
|
||||||
|
|
||||||
|
static func abiExample(compiler: SynorCompiler) async throws {
|
||||||
|
print("=== ABI Operations ===")
|
||||||
|
|
||||||
|
let wasm = createMinimalWasm()
|
||||||
|
|
||||||
|
// Extract ABI from WASM
|
||||||
|
let abi = try await compiler.abi.extract(wasm: wasm)
|
||||||
|
print("Contract: \(abi.name)")
|
||||||
|
print("Version: \(abi.version)")
|
||||||
|
|
||||||
|
// List functions
|
||||||
|
if let functions = abi.functions, !functions.isEmpty {
|
||||||
|
print("\nFunctions:")
|
||||||
|
for function in functions {
|
||||||
|
let inputs = function.inputs?.map { "\($0.name): \($0.type.typeName)" }.joined(separator: ", ") ?? ""
|
||||||
|
let outputs = function.outputs?.map { $0.type.typeName }.joined(separator: ", ") ?? "void"
|
||||||
|
var modifiers: [String] = []
|
||||||
|
if function.view { modifiers.append("view") }
|
||||||
|
if function.payable { modifiers.append("payable") }
|
||||||
|
|
||||||
|
print(" \(function.name)(\(inputs)) -> \(outputs) \(modifiers.joined(separator: " "))")
|
||||||
|
print(" Selector: \(function.selector)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// List events
|
||||||
|
if let events = abi.events, !events.isEmpty {
|
||||||
|
print("\nEvents:")
|
||||||
|
for event in events {
|
||||||
|
let params = event.params?.map { p in
|
||||||
|
"\(p.indexed ? "indexed " : "")\(p.name): \(p.type.typeName)"
|
||||||
|
}.joined(separator: ", ") ?? ""
|
||||||
|
print(" \(event.name)(\(params))")
|
||||||
|
print(" Topic: \(event.topic)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Encode a function call
|
||||||
|
if let function = abi.functions?.first {
|
||||||
|
let encoded = try await compiler.abi.encodeCall(function: function, args: ["arg1", "arg2"])
|
||||||
|
print("\nEncoded call to \(function.name): \(encoded)")
|
||||||
|
|
||||||
|
// Decode a result
|
||||||
|
let decoded = try await compiler.abi.decodeResult(function: function, data: encoded)
|
||||||
|
print("Decoded result: \(decoded)")
|
||||||
|
}
|
||||||
|
|
||||||
|
print()
|
||||||
|
}
|
||||||
|
|
||||||
|
static func analysisExample(compiler: SynorCompiler) async throws {
|
||||||
|
print("=== Contract Analysis ===")
|
||||||
|
|
||||||
|
let wasm = createMinimalWasm()
|
||||||
|
|
||||||
|
// Full analysis
|
||||||
|
let analysis = try await compiler.analysis.analyze(wasm: wasm)
|
||||||
|
|
||||||
|
// Size breakdown
|
||||||
|
if let size = analysis.sizeBreakdown {
|
||||||
|
print("Size breakdown:")
|
||||||
|
print(" Code: \(size.code) bytes")
|
||||||
|
print(" Data: \(size.data) bytes")
|
||||||
|
print(" Functions: \(size.functions) bytes")
|
||||||
|
print(" Memory: \(size.memory) bytes")
|
||||||
|
print(" Exports: \(size.exports) bytes")
|
||||||
|
print(" Imports: \(size.imports) bytes")
|
||||||
|
print(" Total: \(size.total) bytes")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function analysis
|
||||||
|
if let functions = analysis.functions, !functions.isEmpty {
|
||||||
|
print("\nFunction analysis:")
|
||||||
|
for function in functions.prefix(5) {
|
||||||
|
print(" \(function.name):")
|
||||||
|
print(" Size: \(function.size) bytes")
|
||||||
|
print(" Instructions: \(function.instructionCount)")
|
||||||
|
print(" Locals: \(function.localCount)")
|
||||||
|
print(" Exported: \(function.exported)")
|
||||||
|
print(" Estimated gas: \(function.estimatedGas)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Import analysis
|
||||||
|
if let imports = analysis.imports, !imports.isEmpty {
|
||||||
|
print("\nImports:")
|
||||||
|
for imp in imports {
|
||||||
|
print(" \(imp.module).\(imp.name) (\(imp.kind))")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gas analysis
|
||||||
|
if let gas = analysis.gasAnalysis {
|
||||||
|
print("\nGas analysis:")
|
||||||
|
print(" Deployment: \(gas.deploymentGas)")
|
||||||
|
print(" Memory init: \(gas.memoryInitGas)")
|
||||||
|
print(" Data section: \(gas.dataSectionGas)")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract metadata
|
||||||
|
let metadata = try await compiler.analysis.extractMetadata(wasm: wasm)
|
||||||
|
print("\nContract metadata:")
|
||||||
|
print(" Name: \(metadata.name)")
|
||||||
|
print(" Version: \(metadata.version)")
|
||||||
|
print(" Build timestamp: \(metadata.buildTimestamp)")
|
||||||
|
|
||||||
|
// Estimate deployment gas
|
||||||
|
let gasEstimate = try await compiler.analysis.estimateDeployGas(wasm: wasm)
|
||||||
|
print("\nEstimated deployment gas: \(gasEstimate)")
|
||||||
|
|
||||||
|
print()
|
||||||
|
}
|
||||||
|
|
||||||
|
static func validationExample(compiler: SynorCompiler) async throws {
|
||||||
|
print("=== Contract Validation ===")
|
||||||
|
|
||||||
|
let wasm = createMinimalWasm()
|
||||||
|
|
||||||
|
// Full validation
|
||||||
|
let result = try await compiler.validation.validate(wasm: wasm)
|
||||||
|
print("Valid: \(result.valid)")
|
||||||
|
print("Exports: \(result.exportCount)")
|
||||||
|
print("Imports: \(result.importCount)")
|
||||||
|
print("Functions: \(result.functionCount)")
|
||||||
|
print("Memory pages: \(result.memoryPages)")
|
||||||
|
|
||||||
|
if let errors = result.errors, !errors.isEmpty {
|
||||||
|
print("\nValidation errors:")
|
||||||
|
for error in errors {
|
||||||
|
print(" [\(error.code)] \(error.message)")
|
||||||
|
if let location = error.location {
|
||||||
|
print(" at \(location)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let warnings = result.warnings, !warnings.isEmpty {
|
||||||
|
print("\nWarnings:")
|
||||||
|
for warning in warnings {
|
||||||
|
print(" \(warning)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Quick validation
|
||||||
|
let isValid = try await compiler.validation.isValid(wasm: wasm)
|
||||||
|
print("\nQuick validation: \(isValid)")
|
||||||
|
|
||||||
|
// Get validation errors only
|
||||||
|
let errors = try await compiler.validation.getErrors(wasm: wasm)
|
||||||
|
print("Error count: \(errors.count)")
|
||||||
|
|
||||||
|
// Validate required exports
|
||||||
|
let hasRequired = try await compiler.validation.validateExports(
|
||||||
|
wasm: wasm,
|
||||||
|
required: ["init", "execute", "query"]
|
||||||
|
)
|
||||||
|
print("Has required exports: \(hasRequired)")
|
||||||
|
|
||||||
|
// Validate memory constraints
|
||||||
|
let memoryValid = try await compiler.validation.validateMemory(wasm: wasm, maxPages: 16)
|
||||||
|
print("Memory within 16 pages: \(memoryValid)")
|
||||||
|
|
||||||
|
print()
|
||||||
|
}
|
||||||
|
|
||||||
|
static func securityExample(compiler: SynorCompiler) async throws {
|
||||||
|
print("=== Security Scanning ===")
|
||||||
|
|
||||||
|
let wasm = createMinimalWasm()
|
||||||
|
|
||||||
|
let security = try await compiler.analysis.securityScan(wasm: wasm)
|
||||||
|
|
||||||
|
print("Security score: \(security.score)/100")
|
||||||
|
|
||||||
|
if let issues = security.issues, !issues.isEmpty {
|
||||||
|
print("\nSecurity issues:")
|
||||||
|
let severityIcons: [String: String] = [
|
||||||
|
"critical": "[CRIT]",
|
||||||
|
"high": "[HIGH]",
|
||||||
|
"medium": "[MED]",
|
||||||
|
"low": "[LOW]"
|
||||||
|
]
|
||||||
|
for issue in issues {
|
||||||
|
let icon = severityIcons[issue.severity.lowercased()] ?? "[???]"
|
||||||
|
print("\(icon) [\(issue.severity.uppercased())] \(issue.type)")
|
||||||
|
print(" \(issue.description)")
|
||||||
|
if let location = issue.location {
|
||||||
|
print(" at \(location)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
print("No security issues found!")
|
||||||
|
}
|
||||||
|
|
||||||
|
if let recommendations = security.recommendations, !recommendations.isEmpty {
|
||||||
|
print("\nRecommendations:")
|
||||||
|
for rec in recommendations {
|
||||||
|
print(" • \(rec)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
print()
|
||||||
|
}
|
||||||
|
}
|
||||||
260
sdk/swift/Examples/CryptoExample.swift
Normal file
260
sdk/swift/Examples/CryptoExample.swift
Normal file
|
|
@ -0,0 +1,260 @@
|
||||||
|
import Foundation
|
||||||
|
import SynorCrypto
|
||||||
|
|
||||||
|
/// Synor Crypto SDK Examples for Swift
|
||||||
|
///
|
||||||
|
/// Demonstrates quantum-resistant cryptographic operations:
|
||||||
|
/// - Hybrid Ed25519 + Dilithium3 signatures
|
||||||
|
/// - BIP-39 mnemonic generation and validation
|
||||||
|
/// - Post-quantum algorithms (Falcon, SPHINCS+)
|
||||||
|
/// - Key derivation functions
|
||||||
|
|
||||||
|
@main
|
||||||
|
struct CryptoExample {
|
||||||
|
static func main() async throws {
|
||||||
|
// Initialize client
|
||||||
|
let config = CryptoConfig(
|
||||||
|
apiKey: ProcessInfo.processInfo.environment["SYNOR_API_KEY"] ?? "your-api-key",
|
||||||
|
endpoint: "https://crypto.synor.io/v1",
|
||||||
|
timeout: 30,
|
||||||
|
retries: 3,
|
||||||
|
debug: false,
|
||||||
|
defaultNetwork: .mainnet
|
||||||
|
)
|
||||||
|
|
||||||
|
let crypto = SynorCrypto(config: config)
|
||||||
|
|
||||||
|
do {
|
||||||
|
// Check service health
|
||||||
|
let healthy = try await crypto.healthCheck()
|
||||||
|
print("Service healthy: \(healthy)\n")
|
||||||
|
|
||||||
|
// Run examples
|
||||||
|
try await mnemonicExample(crypto: crypto)
|
||||||
|
try await keypairExample(crypto: crypto)
|
||||||
|
try await signingExample(crypto: crypto)
|
||||||
|
try await falconExample(crypto: crypto)
|
||||||
|
try await sphincsExample(crypto: crypto)
|
||||||
|
try await kdfExample(crypto: crypto)
|
||||||
|
try await hashExample(crypto: crypto)
|
||||||
|
} catch {
|
||||||
|
print("Error: \(error)")
|
||||||
|
}
|
||||||
|
|
||||||
|
await crypto.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
static func mnemonicExample(crypto: SynorCrypto) async throws {
|
||||||
|
print("=== Mnemonic Operations ===")
|
||||||
|
|
||||||
|
// Generate a 24-word mnemonic (256-bit entropy)
|
||||||
|
let mnemonic = try await crypto.mnemonic.generate(wordCount: 24)
|
||||||
|
print("Generated mnemonic: \(mnemonic.phrase)")
|
||||||
|
print("Word count: \(mnemonic.wordCount)")
|
||||||
|
|
||||||
|
// Validate a mnemonic
|
||||||
|
let validation = try await crypto.mnemonic.validate(phrase: mnemonic.phrase)
|
||||||
|
print("Valid: \(validation.isValid)")
|
||||||
|
if !validation.isValid {
|
||||||
|
print("Error: \(validation.error ?? "unknown")")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert mnemonic to seed
|
||||||
|
let seed = try await crypto.mnemonic.toSeed(
|
||||||
|
phrase: mnemonic.phrase,
|
||||||
|
passphrase: "optional-passphrase"
|
||||||
|
)
|
||||||
|
print("Seed (hex): \(seed.toHex().prefix(32))...")
|
||||||
|
|
||||||
|
// Word suggestions for autocomplete
|
||||||
|
let suggestions = try await crypto.mnemonic.suggestWords(prefix: "aban", limit: 5)
|
||||||
|
print("Suggestions for 'aban': \(suggestions.joined(separator: ", "))")
|
||||||
|
|
||||||
|
print()
|
||||||
|
}
|
||||||
|
|
||||||
|
static func keypairExample(crypto: SynorCrypto) async throws {
|
||||||
|
print("=== Keypair Operations ===")
|
||||||
|
|
||||||
|
// Generate a random keypair
|
||||||
|
let keypair = try await crypto.keypairs.generate()
|
||||||
|
print("Generated hybrid keypair:")
|
||||||
|
print(" Ed25519 public key size: \(keypair.publicKey.ed25519Bytes.count) bytes")
|
||||||
|
print(" Dilithium public key size: \(keypair.publicKey.dilithiumBytes.count) bytes")
|
||||||
|
print(" Total public key size: \(keypair.publicKey.size) bytes")
|
||||||
|
|
||||||
|
// Get addresses for different networks
|
||||||
|
print("\nAddresses:")
|
||||||
|
print(" Mainnet: \(keypair.getAddress(network: .mainnet))")
|
||||||
|
print(" Testnet: \(keypair.getAddress(network: .testnet))")
|
||||||
|
print(" Devnet: \(keypair.getAddress(network: .devnet))")
|
||||||
|
|
||||||
|
// Create keypair from mnemonic (deterministic)
|
||||||
|
let mnemonic = try await crypto.mnemonic.generate(wordCount: 24)
|
||||||
|
let keypair2 = try await crypto.keypairs.fromMnemonic(phrase: mnemonic.phrase, passphrase: "")
|
||||||
|
let addr = keypair2.getAddress(network: .mainnet)
|
||||||
|
print("\nKeypair from mnemonic: \(addr.prefix(20))...")
|
||||||
|
|
||||||
|
// Derive child keypair using BIP-44 path
|
||||||
|
let path = DerivationPath.external(account: 0, index: 0) // m/44'/21337'/0'/0/0
|
||||||
|
print("Derivation path: \(path)")
|
||||||
|
|
||||||
|
print()
|
||||||
|
}
|
||||||
|
|
||||||
|
static func signingExample(crypto: SynorCrypto) async throws {
|
||||||
|
print("=== Hybrid Signing ===")
|
||||||
|
|
||||||
|
// Generate keypair
|
||||||
|
let keypair = try await crypto.keypairs.generate()
|
||||||
|
|
||||||
|
// Sign a message
|
||||||
|
let message = "Hello, quantum-resistant world!".data(using: .utf8)!
|
||||||
|
let signature = try await crypto.signing.sign(keypair: keypair, message: message)
|
||||||
|
|
||||||
|
print("Signature created:")
|
||||||
|
print(" Ed25519 component: \(signature.ed25519Bytes.count) bytes")
|
||||||
|
print(" Dilithium component: \(signature.dilithiumBytes.count) bytes")
|
||||||
|
print(" Total signature size: \(signature.size) bytes")
|
||||||
|
|
||||||
|
// Verify the signature
|
||||||
|
let valid = try await crypto.signing.verify(
|
||||||
|
publicKey: keypair.publicKey,
|
||||||
|
message: message,
|
||||||
|
signature: signature
|
||||||
|
)
|
||||||
|
print("\nVerification result: \(valid)")
|
||||||
|
|
||||||
|
// Verify with tampered message fails
|
||||||
|
let tamperedMessage = "Hello, tampered message!".data(using: .utf8)!
|
||||||
|
let invalidResult = try await crypto.signing.verify(
|
||||||
|
publicKey: keypair.publicKey,
|
||||||
|
message: tamperedMessage,
|
||||||
|
signature: signature
|
||||||
|
)
|
||||||
|
print("Tampered message verification: \(invalidResult)")
|
||||||
|
|
||||||
|
print()
|
||||||
|
}
|
||||||
|
|
||||||
|
static func falconExample(crypto: SynorCrypto) async throws {
|
||||||
|
print("=== Falcon Post-Quantum Signatures ===")
|
||||||
|
|
||||||
|
// Generate Falcon-512 keypair (128-bit security)
|
||||||
|
let falcon512 = try await crypto.falcon.generate(variant: .falcon512)
|
||||||
|
print("Falcon-512 keypair:")
|
||||||
|
print(" Public key: \(falcon512.publicKey.keyBytes.count) bytes")
|
||||||
|
print(" Security level: 128-bit")
|
||||||
|
|
||||||
|
// Generate Falcon-1024 keypair (256-bit security)
|
||||||
|
let falcon1024 = try await crypto.falcon.generate(variant: .falcon1024)
|
||||||
|
print("\nFalcon-1024 keypair:")
|
||||||
|
print(" Public key: \(falcon1024.publicKey.keyBytes.count) bytes")
|
||||||
|
print(" Security level: 256-bit")
|
||||||
|
|
||||||
|
// Sign with Falcon-512
|
||||||
|
let message = "Post-quantum secure message".data(using: .utf8)!
|
||||||
|
let signature = try await crypto.falcon.sign(keypair: falcon512, message: message)
|
||||||
|
print("\nFalcon-512 signature: \(signature.signatureBytes.count) bytes")
|
||||||
|
|
||||||
|
// Verify
|
||||||
|
let valid = try await crypto.falcon.verify(
|
||||||
|
publicKey: falcon512.publicKey.keyBytes,
|
||||||
|
message: message,
|
||||||
|
signature: signature
|
||||||
|
)
|
||||||
|
print("Verification: \(valid)")
|
||||||
|
|
||||||
|
print()
|
||||||
|
}
|
||||||
|
|
||||||
|
static func sphincsExample(crypto: SynorCrypto) async throws {
|
||||||
|
print("=== SPHINCS+ Hash-Based Signatures ===")
|
||||||
|
|
||||||
|
// SPHINCS+ variants with different security levels
|
||||||
|
let variants: [(SphincsVariant, Int, Int)] = [
|
||||||
|
(.shake128s, 128, 7856),
|
||||||
|
(.shake192s, 192, 16224),
|
||||||
|
(.shake256s, 256, 29792)
|
||||||
|
]
|
||||||
|
|
||||||
|
// Generate and demonstrate each variant
|
||||||
|
for (variant, security, sigSize) in variants {
|
||||||
|
let keypair = try await crypto.sphincs.generate(variant: variant)
|
||||||
|
print("SPHINCS+ \(variant):")
|
||||||
|
print(" Security level: \(security)-bit")
|
||||||
|
print(" Expected signature size: \(sigSize) bytes")
|
||||||
|
|
||||||
|
// Sign a message
|
||||||
|
let message = "Hash-based quantum security".data(using: .utf8)!
|
||||||
|
let signature = try await crypto.sphincs.sign(keypair: keypair, message: message)
|
||||||
|
print(" Actual signature size: \(signature.signatureBytes.count) bytes")
|
||||||
|
|
||||||
|
// Verify
|
||||||
|
let valid = try await crypto.sphincs.verify(
|
||||||
|
publicKey: keypair.publicKey.keyBytes,
|
||||||
|
message: message,
|
||||||
|
signature: signature
|
||||||
|
)
|
||||||
|
print(" Verification: \(valid)\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static func kdfExample(crypto: SynorCrypto) async throws {
|
||||||
|
print("=== Key Derivation Functions ===")
|
||||||
|
|
||||||
|
// HKDF (HMAC-based Key Derivation Function)
|
||||||
|
let seed = "master-secret-key-material-here".data(using: .utf8)!
|
||||||
|
let hkdfConfig = DerivationConfig(
|
||||||
|
salt: "application-salt".data(using: .utf8)!,
|
||||||
|
info: "encryption-key".data(using: .utf8)!,
|
||||||
|
outputLength: 32
|
||||||
|
)
|
||||||
|
|
||||||
|
let derivedKey = try await crypto.kdf.deriveKey(seed: seed, config: hkdfConfig)
|
||||||
|
print("HKDF derived key: \(derivedKey.toHex())")
|
||||||
|
|
||||||
|
// PBKDF2 (Password-Based Key Derivation Function)
|
||||||
|
let password = "user-password".data(using: .utf8)!
|
||||||
|
let pbkdf2Config = PasswordDerivationConfig(
|
||||||
|
salt: "random-salt-value".data(using: .utf8)!,
|
||||||
|
iterations: 100_000,
|
||||||
|
outputLength: 32
|
||||||
|
)
|
||||||
|
|
||||||
|
let passwordKey = try await crypto.kdf.deriveFromPassword(
|
||||||
|
password: password,
|
||||||
|
config: pbkdf2Config
|
||||||
|
)
|
||||||
|
print("PBKDF2 derived key: \(passwordKey.toHex())")
|
||||||
|
|
||||||
|
print()
|
||||||
|
}
|
||||||
|
|
||||||
|
static func hashExample(crypto: SynorCrypto) async throws {
|
||||||
|
print("=== Hash Functions ===")
|
||||||
|
|
||||||
|
let data = "Data to hash".data(using: .utf8)!
|
||||||
|
|
||||||
|
// SHA3-256 (FIPS 202)
|
||||||
|
let sha3 = try await crypto.hash.sha3_256(data: data)
|
||||||
|
print("SHA3-256: \(sha3.hex)")
|
||||||
|
|
||||||
|
// BLAKE3 (fast, parallel)
|
||||||
|
let blake3 = try await crypto.hash.blake3(data: data)
|
||||||
|
print("BLAKE3: \(blake3.hex)")
|
||||||
|
|
||||||
|
// Keccak-256 (Ethereum compatible)
|
||||||
|
let keccak = try await crypto.hash.keccak256(data: data)
|
||||||
|
print("Keccak: \(keccak.hex)")
|
||||||
|
|
||||||
|
print()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extension to convert Data to hex string
|
||||||
|
extension Data {
|
||||||
|
func toHex() -> String {
|
||||||
|
return map { String(format: "%02x", $0) }.joined()
|
||||||
|
}
|
||||||
|
}
|
||||||
351
sdk/swift/Examples/DexExample.swift
Normal file
351
sdk/swift/Examples/DexExample.swift
Normal file
|
|
@ -0,0 +1,351 @@
|
||||||
|
import Foundation
|
||||||
|
import SynorDex
|
||||||
|
|
||||||
|
/// Synor DEX SDK Examples for Swift
|
||||||
|
///
|
||||||
|
/// Demonstrates decentralized exchange operations:
|
||||||
|
/// - Spot trading (limit/market orders)
|
||||||
|
/// - Perpetual futures trading
|
||||||
|
/// - Liquidity provision (AMM pools)
|
||||||
|
/// - Order book management
|
||||||
|
/// - Portfolio tracking
|
||||||
|
|
||||||
|
@main
|
||||||
|
struct DexExample {
|
||||||
|
static func main() async throws {
|
||||||
|
// Initialize client
|
||||||
|
let config = DexConfig(
|
||||||
|
apiKey: ProcessInfo.processInfo.environment["SYNOR_API_KEY"] ?? "your-api-key",
|
||||||
|
endpoint: "https://dex.synor.io/v1",
|
||||||
|
timeout: 30,
|
||||||
|
retries: 3,
|
||||||
|
debug: false,
|
||||||
|
defaultMarket: "SYN-USDC"
|
||||||
|
)
|
||||||
|
|
||||||
|
let dex = SynorDex(config: config)
|
||||||
|
|
||||||
|
do {
|
||||||
|
// Check service health
|
||||||
|
let healthy = try await dex.healthCheck()
|
||||||
|
print("Service healthy: \(healthy)\n")
|
||||||
|
|
||||||
|
// Run examples
|
||||||
|
try await marketsExample(dex: dex)
|
||||||
|
try await spotTradingExample(dex: dex)
|
||||||
|
try await perpsTradingExample(dex: dex)
|
||||||
|
try await liquidityExample(dex: dex)
|
||||||
|
try await orderbookExample(dex: dex)
|
||||||
|
try await portfolioExample(dex: dex)
|
||||||
|
} catch {
|
||||||
|
print("Error: \(error)")
|
||||||
|
}
|
||||||
|
|
||||||
|
await dex.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
static func marketsExample(dex: SynorDex) async throws {
|
||||||
|
print("=== Markets ===")
|
||||||
|
|
||||||
|
// Get all markets
|
||||||
|
let markets = try await dex.markets.list()
|
||||||
|
print("Available markets: \(markets.count)")
|
||||||
|
|
||||||
|
for market in markets.prefix(5) {
|
||||||
|
print("\n \(market.symbol):")
|
||||||
|
print(" Base: \(market.baseAsset), Quote: \(market.quoteAsset)")
|
||||||
|
print(" Price: \(market.lastPrice)")
|
||||||
|
print(" 24h Volume: \(market.volume24h)")
|
||||||
|
print(" 24h Change: \(market.change24h)%")
|
||||||
|
print(" Status: \(market.status)")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get specific market
|
||||||
|
let market = try await dex.markets.get(symbol: "SYN-USDC")
|
||||||
|
print("\nSYN-USDC details:")
|
||||||
|
print(" Min order size: \(market.minOrderSize)")
|
||||||
|
print(" Tick size: \(market.tickSize)")
|
||||||
|
print(" Maker fee: \(market.makerFee)%")
|
||||||
|
print(" Taker fee: \(market.takerFee)%")
|
||||||
|
|
||||||
|
// Get market statistics
|
||||||
|
let stats = try await dex.markets.getStats(symbol: "SYN-USDC")
|
||||||
|
print("\nMarket statistics:")
|
||||||
|
print(" High 24h: \(stats.high24h)")
|
||||||
|
print(" Low 24h: \(stats.low24h)")
|
||||||
|
print(" Open interest: \(stats.openInterest)")
|
||||||
|
print(" Funding rate: \(stats.fundingRate)%")
|
||||||
|
|
||||||
|
print()
|
||||||
|
}
|
||||||
|
|
||||||
|
static func spotTradingExample(dex: SynorDex) async throws {
|
||||||
|
print("=== Spot Trading ===")
|
||||||
|
|
||||||
|
// Place a limit order
|
||||||
|
print("Placing limit buy order...")
|
||||||
|
let limitOrder = try await dex.spot.placeOrder(
|
||||||
|
OrderRequest(
|
||||||
|
market: "SYN-USDC",
|
||||||
|
side: .buy,
|
||||||
|
orderType: .limit,
|
||||||
|
price: "1.50",
|
||||||
|
quantity: "100",
|
||||||
|
timeInForce: .gtc
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
print("Limit order placed:")
|
||||||
|
print(" Order ID: \(limitOrder.orderId)")
|
||||||
|
print(" Status: \(limitOrder.status)")
|
||||||
|
print(" Price: \(limitOrder.price)")
|
||||||
|
print(" Quantity: \(limitOrder.quantity)")
|
||||||
|
|
||||||
|
// Place a market order
|
||||||
|
print("\nPlacing market sell order...")
|
||||||
|
let marketOrder = try await dex.spot.placeOrder(
|
||||||
|
OrderRequest(
|
||||||
|
market: "SYN-USDC",
|
||||||
|
side: .sell,
|
||||||
|
orderType: .market,
|
||||||
|
quantity: "50"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
print("Market order executed:")
|
||||||
|
print(" Order ID: \(marketOrder.orderId)")
|
||||||
|
print(" Status: \(marketOrder.status)")
|
||||||
|
print(" Filled: \(marketOrder.filledQuantity)")
|
||||||
|
print(" Avg price: \(marketOrder.averagePrice)")
|
||||||
|
|
||||||
|
// Get order status
|
||||||
|
let status = try await dex.spot.getOrder(orderId: limitOrder.orderId)
|
||||||
|
print("\nOrder status:")
|
||||||
|
print(" Status: \(status.status)")
|
||||||
|
print(" Filled: \(status.filledQuantity) / \(status.quantity)")
|
||||||
|
print(" Remaining: \(status.remainingQuantity)")
|
||||||
|
|
||||||
|
// Cancel order
|
||||||
|
print("\nCancelling order...")
|
||||||
|
try await dex.spot.cancelOrder(orderId: limitOrder.orderId)
|
||||||
|
print("Order cancelled successfully")
|
||||||
|
|
||||||
|
// Get open orders
|
||||||
|
let openOrders = try await dex.spot.getOpenOrders(market: "SYN-USDC")
|
||||||
|
print("\nOpen orders: \(openOrders.count)")
|
||||||
|
|
||||||
|
// Get trade history
|
||||||
|
let trades = try await dex.spot.getTradeHistory(market: "SYN-USDC", limit: 10)
|
||||||
|
print("\nRecent trades: \(trades.count)")
|
||||||
|
for trade in trades.prefix(3) {
|
||||||
|
print(" \(trade.side) \(trade.quantity) @ \(trade.price) (\(trade.timestamp))")
|
||||||
|
}
|
||||||
|
|
||||||
|
print()
|
||||||
|
}
|
||||||
|
|
||||||
|
static func perpsTradingExample(dex: SynorDex) async throws {
|
||||||
|
print("=== Perpetual Futures Trading ===")
|
||||||
|
|
||||||
|
// Get available perps markets
|
||||||
|
let perpsMarkets = try await dex.perps.listMarkets()
|
||||||
|
print("Available perps markets: \(perpsMarkets.count)")
|
||||||
|
|
||||||
|
for market in perpsMarkets.prefix(3) {
|
||||||
|
print(" \(market.symbol): \(market.markPrice) (funding: \(market.fundingRate)%)")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open a long position
|
||||||
|
print("\nOpening long position...")
|
||||||
|
let position = try await dex.perps.openPosition(
|
||||||
|
PerpsOrderRequest(
|
||||||
|
market: "SYN-USDC-PERP",
|
||||||
|
side: .buy,
|
||||||
|
orderType: .limit,
|
||||||
|
price: "1.50",
|
||||||
|
size: "1000",
|
||||||
|
leverage: 10,
|
||||||
|
reduceOnly: false
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
print("Position opened:")
|
||||||
|
print(" Position ID: \(position.positionId)")
|
||||||
|
print(" Size: \(position.size)")
|
||||||
|
print(" Entry price: \(position.entryPrice)")
|
||||||
|
print(" Leverage: \(position.leverage)x")
|
||||||
|
print(" Liquidation price: \(position.liquidationPrice)")
|
||||||
|
|
||||||
|
// Get position details
|
||||||
|
let details = try await dex.perps.getPosition(positionId: position.positionId)
|
||||||
|
print("\nPosition details:")
|
||||||
|
print(" Unrealized PnL: \(details.unrealizedPnL)")
|
||||||
|
print(" Margin: \(details.margin)")
|
||||||
|
print(" Margin ratio: \(details.marginRatio)%")
|
||||||
|
|
||||||
|
// Set stop loss and take profit
|
||||||
|
print("\nSetting stop loss and take profit...")
|
||||||
|
try await dex.perps.setStopLoss(positionId: position.positionId, price: "1.40")
|
||||||
|
print("Stop loss set at 1.40")
|
||||||
|
|
||||||
|
try await dex.perps.setTakeProfit(positionId: position.positionId, price: "1.80")
|
||||||
|
print("Take profit set at 1.80")
|
||||||
|
|
||||||
|
// Close position
|
||||||
|
print("\nClosing position...")
|
||||||
|
let closeResult = try await dex.perps.closePosition(positionId: position.positionId)
|
||||||
|
print("Position closed:")
|
||||||
|
print(" Realized PnL: \(closeResult.realizedPnL)")
|
||||||
|
print(" Close price: \(closeResult.closePrice)")
|
||||||
|
|
||||||
|
// Get all positions
|
||||||
|
let positions = try await dex.perps.getPositions()
|
||||||
|
print("\nOpen positions: \(positions.count)")
|
||||||
|
|
||||||
|
// Get funding history
|
||||||
|
let funding = try await dex.perps.getFundingHistory(market: "SYN-USDC-PERP", limit: 10)
|
||||||
|
print("Funding payments: \(funding.count)")
|
||||||
|
|
||||||
|
print()
|
||||||
|
}
|
||||||
|
|
||||||
|
static func liquidityExample(dex: SynorDex) async throws {
|
||||||
|
print("=== Liquidity Provision ===")
|
||||||
|
|
||||||
|
// Get available pools
|
||||||
|
let pools = try await dex.liquidity.listPools()
|
||||||
|
print("Available pools: \(pools.count)")
|
||||||
|
|
||||||
|
for pool in pools.prefix(3) {
|
||||||
|
print("\n \(pool.name):")
|
||||||
|
print(" TVL: $\(pool.tvl)")
|
||||||
|
print(" APR: \(pool.apr)%")
|
||||||
|
print(" Volume 24h: $\(pool.volume24h)")
|
||||||
|
print(" Fee tier: \(pool.feeTier)%")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get pool details
|
||||||
|
let pool = try await dex.liquidity.getPool(poolId: "SYN-USDC")
|
||||||
|
print("\nSYN-USDC pool details:")
|
||||||
|
print(" Token0: \(pool.token0.symbol) (\(pool.token0Reserve))")
|
||||||
|
print(" Token1: \(pool.token1.symbol) (\(pool.token1Reserve))")
|
||||||
|
print(" Price: \(pool.price)")
|
||||||
|
print(" Total LP tokens: \(pool.totalLPTokens)")
|
||||||
|
|
||||||
|
// Add liquidity
|
||||||
|
print("\nAdding liquidity...")
|
||||||
|
let addResult = try await dex.liquidity.addLiquidity(
|
||||||
|
AddLiquidityRequest(
|
||||||
|
pool: "SYN-USDC",
|
||||||
|
amount0: "100",
|
||||||
|
amount1: "150",
|
||||||
|
slippageBps: 50 // 0.5%
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
print("Liquidity added:")
|
||||||
|
print(" LP tokens received: \(addResult.lpTokens)")
|
||||||
|
print(" Position ID: \(addResult.positionId)")
|
||||||
|
print(" Share of pool: \(addResult.shareOfPool)%")
|
||||||
|
|
||||||
|
// Get LP positions
|
||||||
|
let lpPositions = try await dex.liquidity.getPositions()
|
||||||
|
print("\nLP positions: \(lpPositions.count)")
|
||||||
|
for pos in lpPositions {
|
||||||
|
print(" \(pos.pool): \(pos.lpTokens) LP tokens (value: $\(pos.value))")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Claim fees
|
||||||
|
print("\nClaiming fees...")
|
||||||
|
let fees = try await dex.liquidity.claimFees(positionId: addResult.positionId)
|
||||||
|
print("Fees claimed:")
|
||||||
|
print(" Token0: \(fees.amount0)")
|
||||||
|
print(" Token1: \(fees.amount1)")
|
||||||
|
|
||||||
|
// Remove liquidity
|
||||||
|
print("\nRemoving liquidity...")
|
||||||
|
let removeResult = try await dex.liquidity.removeLiquidity(
|
||||||
|
RemoveLiquidityRequest(
|
||||||
|
positionId: addResult.positionId,
|
||||||
|
lpTokens: addResult.lpTokens,
|
||||||
|
slippageBps: 50
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
print("Liquidity removed:")
|
||||||
|
print(" Token0 received: \(removeResult.amount0)")
|
||||||
|
print(" Token1 received: \(removeResult.amount1)")
|
||||||
|
|
||||||
|
print()
|
||||||
|
}
|
||||||
|
|
||||||
|
static func orderbookExample(dex: SynorDex) async throws {
|
||||||
|
print("=== Order Book ===")
|
||||||
|
|
||||||
|
// Get order book snapshot
|
||||||
|
let orderbook = try await dex.orderbook.getSnapshot(market: "SYN-USDC", depth: 10)
|
||||||
|
|
||||||
|
print("Order book for SYN-USDC:")
|
||||||
|
print("\nAsks (sells):")
|
||||||
|
for ask in orderbook.asks.prefix(5) {
|
||||||
|
print(" \(ask.quantity) @ \(ask.price)")
|
||||||
|
}
|
||||||
|
|
||||||
|
print("\nBids (buys):")
|
||||||
|
for bid in orderbook.bids.prefix(5) {
|
||||||
|
print(" \(bid.quantity) @ \(bid.price)")
|
||||||
|
}
|
||||||
|
|
||||||
|
print("\nSpread: \(orderbook.spread) (\(orderbook.spreadPercent)%)")
|
||||||
|
print("Mid price: \(orderbook.midPrice)")
|
||||||
|
|
||||||
|
// Get recent trades
|
||||||
|
let recentTrades = try await dex.orderbook.getRecentTrades(market: "SYN-USDC", limit: 10)
|
||||||
|
print("\nRecent trades:")
|
||||||
|
for trade in recentTrades.prefix(5) {
|
||||||
|
print(" \(trade.side) \(trade.quantity) @ \(trade.price)")
|
||||||
|
}
|
||||||
|
|
||||||
|
print()
|
||||||
|
}
|
||||||
|
|
||||||
|
static func portfolioExample(dex: SynorDex) async throws {
|
||||||
|
print("=== Portfolio ===")
|
||||||
|
|
||||||
|
// Get portfolio overview
|
||||||
|
let portfolio = try await dex.portfolio.getOverview()
|
||||||
|
|
||||||
|
print("Portfolio overview:")
|
||||||
|
print(" Total value: $\(portfolio.totalValue)")
|
||||||
|
print(" Available balance: $\(portfolio.availableBalance)")
|
||||||
|
print(" In orders: $\(portfolio.inOrders)")
|
||||||
|
print(" In positions: $\(portfolio.inPositions)")
|
||||||
|
print(" Unrealized PnL: $\(portfolio.unrealizedPnL)")
|
||||||
|
|
||||||
|
// Get balances
|
||||||
|
let balances = try await dex.portfolio.getBalances()
|
||||||
|
print("\nBalances:")
|
||||||
|
for balance in balances {
|
||||||
|
print(" \(balance.asset): \(balance.total) (available: \(balance.available), in orders: \(balance.inOrders))")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get PnL history
|
||||||
|
let pnlHistory = try await dex.portfolio.getPnLHistory(days: 30)
|
||||||
|
print("\nPnL history (last \(pnlHistory.count) days):")
|
||||||
|
if let last = pnlHistory.last {
|
||||||
|
print(" Total PnL: $\(last.cumulativePnL)")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get trade statistics
|
||||||
|
let stats = try await dex.portfolio.getStats()
|
||||||
|
print("\nTrade statistics:")
|
||||||
|
print(" Total trades: \(stats.totalTrades)")
|
||||||
|
print(" Win rate: \(stats.winRate)%")
|
||||||
|
print(" Avg profit: $\(stats.avgProfit)")
|
||||||
|
print(" Avg loss: $\(stats.avgLoss)")
|
||||||
|
print(" Best trade: $\(stats.bestTrade)")
|
||||||
|
print(" Worst trade: $\(stats.worstTrade)")
|
||||||
|
|
||||||
|
print()
|
||||||
|
}
|
||||||
|
}
|
||||||
369
sdk/swift/Examples/IbcExample.swift
Normal file
369
sdk/swift/Examples/IbcExample.swift
Normal file
|
|
@ -0,0 +1,369 @@
|
||||||
|
import Foundation
|
||||||
|
import SynorIbc
|
||||||
|
|
||||||
|
/// Synor IBC SDK Examples for Swift
|
||||||
|
///
|
||||||
|
/// Demonstrates Inter-Blockchain Communication operations:
|
||||||
|
/// - Cross-chain transfers and messages
|
||||||
|
/// - Channel lifecycle management
|
||||||
|
/// - Packet handling and acknowledgments
|
||||||
|
/// - Relayer operations
|
||||||
|
/// - Connection monitoring
|
||||||
|
|
||||||
|
@main
|
||||||
|
struct IbcExample {
|
||||||
|
static func main() async throws {
|
||||||
|
// Initialize client
|
||||||
|
let config = IbcConfig(
|
||||||
|
apiKey: ProcessInfo.processInfo.environment["SYNOR_API_KEY"] ?? "your-api-key",
|
||||||
|
endpoint: "https://ibc.synor.io/v1",
|
||||||
|
timeout: 30,
|
||||||
|
retries: 3,
|
||||||
|
debug: false,
|
||||||
|
defaultChain: "synor-mainnet-1",
|
||||||
|
confirmations: 1
|
||||||
|
)
|
||||||
|
|
||||||
|
let ibc = SynorIbc(config: config)
|
||||||
|
|
||||||
|
do {
|
||||||
|
// Check service health
|
||||||
|
let healthy = try await ibc.healthCheck()
|
||||||
|
print("Service healthy: \(healthy)\n")
|
||||||
|
|
||||||
|
// Run examples
|
||||||
|
try await chainsExample(ibc: ibc)
|
||||||
|
try await channelsExample(ibc: ibc)
|
||||||
|
try await transferExample(ibc: ibc)
|
||||||
|
try await packetExample(ibc: ibc)
|
||||||
|
try await relayerExample(ibc: ibc)
|
||||||
|
try await monitoringExample(ibc: ibc)
|
||||||
|
} catch {
|
||||||
|
print("Error: \(error)")
|
||||||
|
}
|
||||||
|
|
||||||
|
await ibc.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
static func chainsExample(ibc: SynorIbc) async throws {
|
||||||
|
print("=== Chain Discovery ===")
|
||||||
|
|
||||||
|
// Get all connected chains
|
||||||
|
let chains = try await ibc.chains.list()
|
||||||
|
print("Connected chains: \(chains.count)")
|
||||||
|
|
||||||
|
for chain in chains.prefix(5) {
|
||||||
|
print("\n \(chain.chainId):")
|
||||||
|
print(" Name: \(chain.name)")
|
||||||
|
print(" Type: \(chain.chainType)")
|
||||||
|
print(" Status: \(chain.status)")
|
||||||
|
print(" Block height: \(chain.latestHeight)")
|
||||||
|
print(" Light client: \(chain.lightClient)")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get specific chain info
|
||||||
|
let synorChain = try await ibc.chains.get(chainId: "synor-mainnet-1")
|
||||||
|
print("\nSynor chain details:")
|
||||||
|
print(" Bech32 prefix: \(synorChain.bech32Prefix)")
|
||||||
|
print(" Gas price: \(synorChain.gasPrice)")
|
||||||
|
print(" Supported features: \(synorChain.features.joined(separator: ", "))")
|
||||||
|
|
||||||
|
// Get chain connections
|
||||||
|
let connections = try await ibc.chains.getConnections(chainId: "synor-mainnet-1")
|
||||||
|
print("\nChain connections: \(connections.count)")
|
||||||
|
for conn in connections.prefix(3) {
|
||||||
|
print(" \(conn.connectionId) -> \(conn.counterpartyChainId)")
|
||||||
|
}
|
||||||
|
|
||||||
|
print()
|
||||||
|
}
|
||||||
|
|
||||||
|
static func channelsExample(ibc: SynorIbc) async throws {
|
||||||
|
print("=== Channel Management ===")
|
||||||
|
|
||||||
|
// List existing channels
|
||||||
|
let channels = try await ibc.channels.list()
|
||||||
|
print("Active channels: \(channels.count)")
|
||||||
|
|
||||||
|
for channel in channels.prefix(3) {
|
||||||
|
print("\n Channel \(channel.channelId):")
|
||||||
|
print(" Port: \(channel.portId)")
|
||||||
|
print(" State: \(channel.state)")
|
||||||
|
print(" Order: \(channel.ordering)")
|
||||||
|
print(" Counterparty: \(channel.counterpartyChannelId) on \(channel.counterpartyChainId)")
|
||||||
|
print(" Version: \(channel.version)")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new channel (4-step handshake)
|
||||||
|
print("\nInitiating channel creation...")
|
||||||
|
|
||||||
|
// Step 1: ChanOpenInit
|
||||||
|
let initResult = try await ibc.channels.openInit(
|
||||||
|
ChannelInitRequest(
|
||||||
|
portId: "transfer",
|
||||||
|
counterpartyChainId: "cosmos-hub-4",
|
||||||
|
counterpartyPortId: "transfer",
|
||||||
|
version: "ics20-1",
|
||||||
|
ordering: .unordered
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
print("Channel init:")
|
||||||
|
print(" Channel ID: \(initResult.channelId)")
|
||||||
|
print(" State: \(initResult.state)")
|
||||||
|
print(" TX hash: \(initResult.txHash)")
|
||||||
|
|
||||||
|
// Step 2: Wait for ChanOpenTry (counterparty)
|
||||||
|
print("\nWaiting for counterparty ChanOpenTry...")
|
||||||
|
let tryState = try await ibc.channels.waitForState(
|
||||||
|
channelId: initResult.channelId,
|
||||||
|
state: .tryopen,
|
||||||
|
timeout: 300 // 5 minutes
|
||||||
|
)
|
||||||
|
print("Channel state: \(tryState)")
|
||||||
|
|
||||||
|
// Step 3: ChanOpenAck
|
||||||
|
print("\nSending ChanOpenAck...")
|
||||||
|
let ackResult = try await ibc.channels.openAck(
|
||||||
|
ChannelAckRequest(
|
||||||
|
channelId: initResult.channelId,
|
||||||
|
counterpartyChannelId: "channel-0",
|
||||||
|
counterpartyVersion: "ics20-1"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
print("Ack TX: \(ackResult.txHash)")
|
||||||
|
|
||||||
|
// Step 4: Wait for ChanOpenConfirm (counterparty)
|
||||||
|
print("\nWaiting for channel to open...")
|
||||||
|
let openState = try await ibc.channels.waitForState(
|
||||||
|
channelId: initResult.channelId,
|
||||||
|
state: .open,
|
||||||
|
timeout: 300
|
||||||
|
)
|
||||||
|
print("Channel is now: \(openState)")
|
||||||
|
|
||||||
|
// Get channel details
|
||||||
|
let channel = try await ibc.channels.get(channelId: initResult.channelId)
|
||||||
|
print("\nChannel details:")
|
||||||
|
print(" Sequences - Send: \(channel.nextSequenceSend), Recv: \(channel.nextSequenceRecv), Ack: \(channel.nextSequenceAck)")
|
||||||
|
|
||||||
|
print()
|
||||||
|
}
|
||||||
|
|
||||||
|
static func transferExample(ibc: SynorIbc) async throws {
|
||||||
|
print("=== Cross-Chain Transfers ===")
|
||||||
|
|
||||||
|
// Get supported tokens for transfer
|
||||||
|
let tokens = try await ibc.transfers.getSupportedTokens(targetChain: "cosmos-hub-4")
|
||||||
|
print("Transferable tokens to Cosmos Hub:")
|
||||||
|
for token in tokens.prefix(5) {
|
||||||
|
print(" \(token.symbol) (\(token.denom))")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initiate a cross-chain transfer
|
||||||
|
print("\nInitiating transfer...")
|
||||||
|
let transfer = try await ibc.transfers.send(
|
||||||
|
TransferRequest(
|
||||||
|
sourceChannel: "channel-0",
|
||||||
|
denom: "usynor",
|
||||||
|
amount: "1000000",
|
||||||
|
receiver: "cosmos1...",
|
||||||
|
timeoutHeight: 0, // Use timestamp instead
|
||||||
|
timeoutTimestamp: UInt64(Date().timeIntervalSince1970 + 600) * 1_000_000_000,
|
||||||
|
memo: "IBC transfer from Synor"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
print("Transfer initiated:")
|
||||||
|
print(" TX hash: \(transfer.txHash)")
|
||||||
|
print(" Sequence: \(transfer.sequence)")
|
||||||
|
print(" Packet ID: \(transfer.packetId)")
|
||||||
|
print(" Status: \(transfer.status)")
|
||||||
|
|
||||||
|
// Track transfer progress
|
||||||
|
print("\nTracking transfer...")
|
||||||
|
let status = try await ibc.transfers.track(packetId: transfer.packetId)
|
||||||
|
print("Current status: \(status.state)")
|
||||||
|
print("Source TX: \(status.sourceTxHash)")
|
||||||
|
if let destTx = status.destTxHash {
|
||||||
|
print("Dest TX: \(destTx)")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for completion
|
||||||
|
print("\nWaiting for transfer completion...")
|
||||||
|
let finalStatus = try await ibc.transfers.waitForCompletion(
|
||||||
|
packetId: transfer.packetId,
|
||||||
|
timeout: 600 // 10 minutes
|
||||||
|
)
|
||||||
|
|
||||||
|
print("Transfer completed:")
|
||||||
|
print(" Final status: \(finalStatus.state)")
|
||||||
|
print(" Acknowledgment: \(finalStatus.acknowledgment)")
|
||||||
|
|
||||||
|
// Get transfer history
|
||||||
|
let history = try await ibc.transfers.getHistory(limit: 10)
|
||||||
|
print("\nRecent transfers: \(history.count)")
|
||||||
|
for t in history.prefix(3) {
|
||||||
|
print(" \(t.amount) \(t.denom) -> \(t.destChain) (\(t.status))")
|
||||||
|
}
|
||||||
|
|
||||||
|
print()
|
||||||
|
}
|
||||||
|
|
||||||
|
static func packetExample(ibc: SynorIbc) async throws {
|
||||||
|
print("=== Packet Operations ===")
|
||||||
|
|
||||||
|
// List pending packets
|
||||||
|
let pending = try await ibc.packets.listPending(channelId: "channel-0")
|
||||||
|
print("Pending packets on channel-0: \(pending.count)")
|
||||||
|
|
||||||
|
for packet in pending.prefix(3) {
|
||||||
|
print("\n Packet #\(packet.sequence):")
|
||||||
|
print(" Source: \(packet.sourcePort)/\(packet.sourceChannel)")
|
||||||
|
print(" Dest: \(packet.destPort)/\(packet.destChannel)")
|
||||||
|
print(" State: \(packet.state)")
|
||||||
|
print(" Timeout: \(packet.timeoutTimestamp)")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get specific packet
|
||||||
|
let packet = try await ibc.packets.get(channelId: "channel-0", sequence: 1)
|
||||||
|
print("\nPacket details:")
|
||||||
|
print(" Data (hex): \(packet.dataHex.prefix(40))...")
|
||||||
|
print(" Created: \(packet.createdAt)")
|
||||||
|
|
||||||
|
// Get packet commitment proof
|
||||||
|
let proof = try await ibc.packets.getCommitmentProof(channelId: "channel-0", sequence: 1)
|
||||||
|
print("\nCommitment proof:")
|
||||||
|
print(" Height: \(proof.proofHeight)")
|
||||||
|
print(" Proof size: \(proof.proof.count) bytes")
|
||||||
|
|
||||||
|
// Get acknowledgment
|
||||||
|
let ack = try await ibc.packets.getAcknowledgment(channelId: "channel-0", sequence: 1)
|
||||||
|
print("\nAcknowledgment:")
|
||||||
|
print(" Result: \(ack.success ? "Success" : "Error: \(ack.error ?? "unknown")")")
|
||||||
|
print(" TX hash: \(ack.txHash)")
|
||||||
|
|
||||||
|
// List timed-out packets
|
||||||
|
let timedOut = try await ibc.packets.listTimedOut()
|
||||||
|
print("\nTimed-out packets: \(timedOut.count)")
|
||||||
|
|
||||||
|
// Timeout a packet manually
|
||||||
|
if let toTimeout = timedOut.first {
|
||||||
|
print("\nProcessing timeout for packet #\(toTimeout.sequence)")
|
||||||
|
let timeout = try await ibc.packets.timeout(
|
||||||
|
channelId: toTimeout.sourceChannel,
|
||||||
|
sequence: toTimeout.sequence
|
||||||
|
)
|
||||||
|
print("Timeout TX: \(timeout.txHash)")
|
||||||
|
}
|
||||||
|
|
||||||
|
print()
|
||||||
|
}
|
||||||
|
|
||||||
|
static func relayerExample(ibc: SynorIbc) async throws {
|
||||||
|
print("=== Relayer Operations ===")
|
||||||
|
|
||||||
|
// Get relayer status
|
||||||
|
let status = try await ibc.relayer.getStatus()
|
||||||
|
print("Relayer status:")
|
||||||
|
print(" Running: \(status.running)")
|
||||||
|
print(" Uptime: \(status.uptime)")
|
||||||
|
print(" Packets relayed: \(status.packetsRelayed)")
|
||||||
|
print(" Errors: \(status.errorCount)")
|
||||||
|
|
||||||
|
// List active paths
|
||||||
|
let paths = try await ibc.relayer.listPaths()
|
||||||
|
print("\nActive relay paths: \(paths.count)")
|
||||||
|
|
||||||
|
for path in paths {
|
||||||
|
print("\n \(path.pathId):")
|
||||||
|
print(" \(path.sourceChain) <-> \(path.destChain)")
|
||||||
|
print(" Channel: \(path.sourceChannel) <-> \(path.destChannel)")
|
||||||
|
print(" Status: \(path.status)")
|
||||||
|
print(" Pending packets: \(path.pendingPackets)")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configure a new path
|
||||||
|
print("\nConfiguring new relay path...")
|
||||||
|
let newPath = try await ibc.relayer.addPath(
|
||||||
|
PathConfig(
|
||||||
|
sourceChain: "synor-mainnet-1",
|
||||||
|
destChain: "osmosis-1",
|
||||||
|
sourceChannel: "channel-1",
|
||||||
|
destChannel: "channel-100",
|
||||||
|
filterDenoms: ["usynor", "uosmo"],
|
||||||
|
minRelayAmount: "1000",
|
||||||
|
maxRelayAmount: "1000000000"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
print("Path created: \(newPath.pathId)")
|
||||||
|
|
||||||
|
// Start relaying on path
|
||||||
|
print("\nStarting relayer on path...")
|
||||||
|
try await ibc.relayer.startPath(pathId: newPath.pathId)
|
||||||
|
print("Relayer started")
|
||||||
|
|
||||||
|
// Manually relay pending packets
|
||||||
|
print("\nRelaying pending packets...")
|
||||||
|
let relayResult = try await ibc.relayer.relayPending(pathId: newPath.pathId)
|
||||||
|
print("Relayed \(relayResult.packetCount) packets")
|
||||||
|
print("TX hashes: \(relayResult.txHashes.count)")
|
||||||
|
|
||||||
|
// Get relay history
|
||||||
|
let history = try await ibc.relayer.getHistory(pathId: newPath.pathId, limit: 10)
|
||||||
|
print("\nRelay history:")
|
||||||
|
for event in history.prefix(3) {
|
||||||
|
print(" \(event.timestamp): \(event.eventType) - \(event.packetCount) packets")
|
||||||
|
}
|
||||||
|
|
||||||
|
print()
|
||||||
|
}
|
||||||
|
|
||||||
|
static func monitoringExample(ibc: SynorIbc) async throws {
|
||||||
|
print("=== IBC Monitoring ===")
|
||||||
|
|
||||||
|
// Get IBC metrics
|
||||||
|
let metrics = try await ibc.monitoring.getMetrics()
|
||||||
|
print("IBC metrics:")
|
||||||
|
print(" Total channels: \(metrics.totalChannels)")
|
||||||
|
print(" Active channels: \(metrics.activeChannels)")
|
||||||
|
print(" Total packets: \(metrics.totalPackets)")
|
||||||
|
print(" Pending packets: \(metrics.pendingPackets)")
|
||||||
|
print(" Failed packets: \(metrics.failedPackets)")
|
||||||
|
print(" Avg relay time: \(metrics.avgRelayTime)ms")
|
||||||
|
|
||||||
|
// Get chain health
|
||||||
|
let chainHealth = try await ibc.monitoring.getChainHealth()
|
||||||
|
print("\nChain health:")
|
||||||
|
for health in chainHealth.prefix(3) {
|
||||||
|
print(" \(health.chainId):")
|
||||||
|
print(" Status: \(health.status)")
|
||||||
|
print(" Block lag: \(health.blockLag)")
|
||||||
|
print(" Last update: \(health.lastUpdate)")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get channel statistics
|
||||||
|
let stats = try await ibc.monitoring.getChannelStats(channelId: "channel-0")
|
||||||
|
print("\nChannel-0 statistics:")
|
||||||
|
print(" Packets sent: \(stats.packetsSent)")
|
||||||
|
print(" Packets received: \(stats.packetsReceived)")
|
||||||
|
print(" Success rate: \(stats.successRate)%")
|
||||||
|
print(" Avg confirmation time: \(stats.avgConfirmationTime)ms")
|
||||||
|
|
||||||
|
// Subscribe to IBC events
|
||||||
|
print("\nSubscribing to IBC events...")
|
||||||
|
try await ibc.monitoring.subscribe { event in
|
||||||
|
print("Event: \(event.type) on \(event.channelId)")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get alerts
|
||||||
|
let alerts = try await ibc.monitoring.getAlerts()
|
||||||
|
print("\nActive alerts: \(alerts.count)")
|
||||||
|
for alert in alerts {
|
||||||
|
print(" [\(alert.severity)] \(alert.message)")
|
||||||
|
}
|
||||||
|
|
||||||
|
print()
|
||||||
|
}
|
||||||
|
}
|
||||||
373
sdk/swift/Examples/ZkExample.swift
Normal file
373
sdk/swift/Examples/ZkExample.swift
Normal file
|
|
@ -0,0 +1,373 @@
|
||||||
|
import Foundation
|
||||||
|
import SynorZk
|
||||||
|
|
||||||
|
/// Synor ZK SDK Examples for Swift
|
||||||
|
///
|
||||||
|
/// Demonstrates zero-knowledge proof operations:
|
||||||
|
/// - Circuit compilation (Circom)
|
||||||
|
/// - Proof generation and verification
|
||||||
|
/// - Multiple proving systems (Groth16, PLONK, STARK)
|
||||||
|
/// - Recursive proof composition
|
||||||
|
/// - Trusted setup ceremonies
|
||||||
|
|
||||||
|
@main
|
||||||
|
struct ZkExample {
|
||||||
|
static func main() async throws {
|
||||||
|
// Initialize client
|
||||||
|
let config = ZkConfig(
|
||||||
|
apiKey: ProcessInfo.processInfo.environment["SYNOR_API_KEY"] ?? "your-api-key",
|
||||||
|
endpoint: "https://zk.synor.io/v1",
|
||||||
|
timeout: 120, // ZK operations can be slow
|
||||||
|
retries: 3,
|
||||||
|
debug: false,
|
||||||
|
defaultProvingSystem: .groth16,
|
||||||
|
proveTimeout: 300,
|
||||||
|
verifyTimeout: 30
|
||||||
|
)
|
||||||
|
|
||||||
|
let zk = SynorZk(config: config)
|
||||||
|
|
||||||
|
do {
|
||||||
|
// Check service health
|
||||||
|
let healthy = try await zk.healthCheck()
|
||||||
|
print("Service healthy: \(healthy)\n")
|
||||||
|
|
||||||
|
// Run examples
|
||||||
|
try await circuitExample(zk: zk)
|
||||||
|
try await groth16Example(zk: zk)
|
||||||
|
try await plonkExample(zk: zk)
|
||||||
|
try await starkExample(zk: zk)
|
||||||
|
try await recursiveExample(zk: zk)
|
||||||
|
try await ceremonyExample(zk: zk)
|
||||||
|
} catch {
|
||||||
|
print("Error: \(error)")
|
||||||
|
}
|
||||||
|
|
||||||
|
await zk.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
static func circuitExample(zk: SynorZk) async throws {
|
||||||
|
print("=== Circuit Compilation ===")
|
||||||
|
|
||||||
|
// Simple Circom circuit: prove knowledge of factors
|
||||||
|
let 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
|
||||||
|
print("Compiling circuit...")
|
||||||
|
let circuit = try await zk.circuits.compile(
|
||||||
|
CircuitSource(
|
||||||
|
code: circomCode,
|
||||||
|
language: .circom
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
print("Circuit compiled:")
|
||||||
|
print(" Circuit ID: \(circuit.circuitId)")
|
||||||
|
print(" Constraints: \(circuit.constraints)")
|
||||||
|
print(" Public inputs: \(circuit.publicInputs)")
|
||||||
|
print(" Private inputs: \(circuit.privateInputs)")
|
||||||
|
print(" Outputs: \(circuit.outputs)")
|
||||||
|
|
||||||
|
// Get circuit info
|
||||||
|
let info = try await zk.circuits.get(circuitId: circuit.circuitId)
|
||||||
|
print("\nCircuit info:")
|
||||||
|
print(" Name: \(info.name)")
|
||||||
|
print(" Version: \(info.version)")
|
||||||
|
print(" Wires: \(info.wireCount)")
|
||||||
|
print(" Labels: \(info.labelCount)")
|
||||||
|
|
||||||
|
// List available circuits
|
||||||
|
let circuits = try await zk.circuits.list()
|
||||||
|
print("\nAvailable circuits: \(circuits.count)")
|
||||||
|
for c in circuits.prefix(3) {
|
||||||
|
print(" \(c.circuitId): \(c.name) (\(c.constraints) constraints)")
|
||||||
|
}
|
||||||
|
|
||||||
|
print()
|
||||||
|
}
|
||||||
|
|
||||||
|
static func groth16Example(zk: SynorZk) async throws {
|
||||||
|
print("=== Groth16 Proving System ===")
|
||||||
|
|
||||||
|
// Use a pre-compiled circuit
|
||||||
|
let circuitId = "multiplier-v1"
|
||||||
|
|
||||||
|
// Generate proving/verification keys (trusted setup)
|
||||||
|
print("Generating keys...")
|
||||||
|
let keys = try await zk.groth16.setup(circuitId: circuitId)
|
||||||
|
print("Keys generated:")
|
||||||
|
print(" Proving key size: \(keys.provingKey.count) bytes")
|
||||||
|
print(" Verification key size: \(keys.verificationKey.count) bytes")
|
||||||
|
|
||||||
|
// Prepare witness (private inputs)
|
||||||
|
let witness: [String: String] = [
|
||||||
|
"a": "3",
|
||||||
|
"b": "7"
|
||||||
|
]
|
||||||
|
|
||||||
|
// Generate proof
|
||||||
|
print("\nGenerating proof...")
|
||||||
|
let proof = try await zk.groth16.prove(
|
||||||
|
ProveRequest(
|
||||||
|
circuitId: circuitId,
|
||||||
|
witness: witness,
|
||||||
|
provingKey: keys.provingKey
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
print("Proof generated:")
|
||||||
|
print(" Proof size: \(proof.proofBytes.count) bytes")
|
||||||
|
print(" Public signals: \(proof.publicSignals)")
|
||||||
|
print(" Proving time: \(proof.provingTimeMs)ms")
|
||||||
|
|
||||||
|
// Verify proof
|
||||||
|
print("\nVerifying proof...")
|
||||||
|
let verified = try await zk.groth16.verify(
|
||||||
|
VerifyRequest(
|
||||||
|
proof: proof.proofBytes,
|
||||||
|
publicSignals: proof.publicSignals,
|
||||||
|
verificationKey: keys.verificationKey
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
print("Verification result: \(verified)")
|
||||||
|
|
||||||
|
// Export proof for on-chain verification
|
||||||
|
let solidityCalldata = try await zk.groth16.exportCalldata(proof: proof)
|
||||||
|
print("\nSolidity calldata: \(solidityCalldata.prefix(100))...")
|
||||||
|
|
||||||
|
print()
|
||||||
|
}
|
||||||
|
|
||||||
|
static func plonkExample(zk: SynorZk) async throws {
|
||||||
|
print("=== PLONK Proving System ===")
|
||||||
|
|
||||||
|
let circuitId = "multiplier-v1"
|
||||||
|
|
||||||
|
// PLONK uses universal trusted setup
|
||||||
|
print("Getting universal setup...")
|
||||||
|
let srs = try await zk.plonk.getUniversalSetup(powersOfTau: 14) // 2^14 constraints
|
||||||
|
print("SRS loaded: \(srs.count) bytes")
|
||||||
|
|
||||||
|
// Generate circuit-specific keys
|
||||||
|
print("\nGenerating circuit keys...")
|
||||||
|
let keys = try await zk.plonk.setup(circuitId: circuitId, srs: srs)
|
||||||
|
print("Keys generated")
|
||||||
|
|
||||||
|
// Generate proof
|
||||||
|
let witness: [String: String] = ["a": "5", "b": "9"]
|
||||||
|
print("\nGenerating PLONK proof...")
|
||||||
|
let proof = try await zk.plonk.prove(
|
||||||
|
PlonkProveRequest(
|
||||||
|
circuitId: circuitId,
|
||||||
|
witness: witness,
|
||||||
|
provingKey: keys.provingKey
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
print("Proof generated:")
|
||||||
|
print(" Proof size: \(proof.proofBytes.count) bytes")
|
||||||
|
print(" Proving time: \(proof.provingTimeMs)ms")
|
||||||
|
|
||||||
|
// Verify proof
|
||||||
|
let verified = try await zk.plonk.verify(
|
||||||
|
PlonkVerifyRequest(
|
||||||
|
proof: proof.proofBytes,
|
||||||
|
publicSignals: proof.publicSignals,
|
||||||
|
verificationKey: keys.verificationKey
|
||||||
|
)
|
||||||
|
)
|
||||||
|
print("Verification result: \(verified)")
|
||||||
|
|
||||||
|
// Compare with Groth16
|
||||||
|
print("\nPLONK advantages:")
|
||||||
|
print(" - Universal trusted setup")
|
||||||
|
print(" - Larger proofs (~2.5 KB vs ~200 bytes)")
|
||||||
|
print(" - Faster proving for some circuits")
|
||||||
|
|
||||||
|
print()
|
||||||
|
}
|
||||||
|
|
||||||
|
static func starkExample(zk: SynorZk) async throws {
|
||||||
|
print("=== STARK Proving System ===")
|
||||||
|
|
||||||
|
let circuitId = "multiplier-v1"
|
||||||
|
|
||||||
|
// STARKs don't need trusted setup
|
||||||
|
print("Configuring STARK parameters...")
|
||||||
|
let config = StarkConfig(
|
||||||
|
fieldSize: 256,
|
||||||
|
hashFunction: .poseidon,
|
||||||
|
blowupFactor: 8,
|
||||||
|
numQueries: 30,
|
||||||
|
foldingFactor: 8
|
||||||
|
)
|
||||||
|
|
||||||
|
// Generate proof
|
||||||
|
let witness: [String: String] = ["a": "11", "b": "13"]
|
||||||
|
print("\nGenerating STARK proof...")
|
||||||
|
let proof = try await zk.stark.prove(
|
||||||
|
StarkProveRequest(
|
||||||
|
circuitId: circuitId,
|
||||||
|
witness: witness,
|
||||||
|
config: config
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
print("Proof generated:")
|
||||||
|
print(" Proof size: \(proof.proofBytes.count) bytes")
|
||||||
|
print(" Proving time: \(proof.provingTimeMs)ms")
|
||||||
|
print(" FRI layers: \(proof.friLayers)")
|
||||||
|
|
||||||
|
// Verify proof
|
||||||
|
print("\nVerifying STARK proof...")
|
||||||
|
let verified = try await zk.stark.verify(
|
||||||
|
StarkVerifyRequest(
|
||||||
|
proof: proof.proofBytes,
|
||||||
|
publicSignals: proof.publicSignals,
|
||||||
|
config: config
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
print("Verification result: \(verified)")
|
||||||
|
|
||||||
|
// Compare with SNARKs
|
||||||
|
print("\nSTARK advantages:")
|
||||||
|
print(" - No trusted setup needed")
|
||||||
|
print(" - Post-quantum secure")
|
||||||
|
print(" - Larger proofs (~100 KB)")
|
||||||
|
print(" - Faster proving for complex computations")
|
||||||
|
|
||||||
|
print()
|
||||||
|
}
|
||||||
|
|
||||||
|
static func recursiveExample(zk: SynorZk) async throws {
|
||||||
|
print("=== Recursive Proof Composition ===")
|
||||||
|
|
||||||
|
// Create inner proofs
|
||||||
|
print("Generating inner proofs...")
|
||||||
|
var innerProofs: [RecursiveProof] = []
|
||||||
|
|
||||||
|
for i in 1...3 {
|
||||||
|
let witness: [String: String] = ["a": "\(i)", "b": "\(i + 1)"]
|
||||||
|
let proof = try await zk.recursive.proveInner(
|
||||||
|
RecursiveProveRequest(
|
||||||
|
circuitId: "multiplier-v1",
|
||||||
|
witness: witness,
|
||||||
|
level: 0
|
||||||
|
)
|
||||||
|
)
|
||||||
|
innerProofs.append(proof)
|
||||||
|
print(" Inner proof \(i) generated")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Aggregate proofs recursively
|
||||||
|
print("\nAggregating proofs...")
|
||||||
|
let aggregatedProof = try await zk.recursive.aggregate(
|
||||||
|
AggregateRequest(
|
||||||
|
proofs: innerProofs,
|
||||||
|
aggregationCircuit: "recursive-aggregator-v1"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
print("Aggregated proof:")
|
||||||
|
print(" Proof size: \(aggregatedProof.proofBytes.count) bytes")
|
||||||
|
print(" Proofs aggregated: \(aggregatedProof.proofsAggregated)")
|
||||||
|
print(" Recursion depth: \(aggregatedProof.recursionDepth)")
|
||||||
|
|
||||||
|
// Verify aggregated proof (verifies all inner proofs at once)
|
||||||
|
print("\nVerifying aggregated proof...")
|
||||||
|
let verified = try await zk.recursive.verifyAggregated(proof: aggregatedProof)
|
||||||
|
print("Verification result: \(verified)")
|
||||||
|
|
||||||
|
// Use cases
|
||||||
|
print("\nRecursive proof use cases:")
|
||||||
|
print(" - Rollup batch verification")
|
||||||
|
print(" - Incremental computation proofs")
|
||||||
|
print(" - Cross-chain state proofs")
|
||||||
|
|
||||||
|
print()
|
||||||
|
}
|
||||||
|
|
||||||
|
static func ceremonyExample(zk: SynorZk) async throws {
|
||||||
|
print("=== Trusted Setup Ceremony ===")
|
||||||
|
|
||||||
|
// List active ceremonies
|
||||||
|
let ceremonies = try await zk.ceremony.list(status: .active)
|
||||||
|
print("Active ceremonies: \(ceremonies.count)")
|
||||||
|
|
||||||
|
for ceremony in ceremonies.prefix(3) {
|
||||||
|
print("\n \(ceremony.ceremonyId):")
|
||||||
|
print(" Circuit: \(ceremony.circuitId)")
|
||||||
|
print(" Participants: \(ceremony.participantCount)")
|
||||||
|
print(" Current round: \(ceremony.currentRound)")
|
||||||
|
print(" Status: \(ceremony.status)")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new ceremony
|
||||||
|
print("\nCreating new ceremony...")
|
||||||
|
let newCeremony = try await zk.ceremony.create(
|
||||||
|
CeremonyConfig(
|
||||||
|
circuitId: "new-circuit-v1",
|
||||||
|
minParticipants: 10,
|
||||||
|
maxParticipants: 100,
|
||||||
|
roundDuration: 3600, // 1 hour per round
|
||||||
|
verifyContributions: true
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
print("Ceremony created:")
|
||||||
|
print(" Ceremony ID: \(newCeremony.ceremonyId)")
|
||||||
|
print(" Join URL: \(newCeremony.joinUrl)")
|
||||||
|
|
||||||
|
// Participate in a ceremony
|
||||||
|
print("\nParticipating in ceremony...")
|
||||||
|
let contribution = try await zk.ceremony.contribute(
|
||||||
|
ContributionRequest(
|
||||||
|
ceremonyId: newCeremony.ceremonyId,
|
||||||
|
entropy: generateEntropy()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
print("Contribution made:")
|
||||||
|
print(" Contribution ID: \(contribution.contributionId)")
|
||||||
|
print(" Position: \(contribution.position)")
|
||||||
|
print(" Hash: \(contribution.hash)")
|
||||||
|
|
||||||
|
// Verify a contribution
|
||||||
|
print("\nVerifying contribution...")
|
||||||
|
let valid = try await zk.ceremony.verifyContribution(contributionId: contribution.contributionId)
|
||||||
|
print("Contribution valid: \(valid)")
|
||||||
|
|
||||||
|
// Get ceremony transcript (for auditability)
|
||||||
|
let transcript = try await zk.ceremony.getTranscript(ceremonyId: newCeremony.ceremonyId)
|
||||||
|
print("\nCeremony transcript:")
|
||||||
|
print(" Total contributions: \(transcript.contributions.count)")
|
||||||
|
print(" Start time: \(transcript.startTime)")
|
||||||
|
print(" Final hash: \(transcript.finalHash ?? "pending")")
|
||||||
|
|
||||||
|
print()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper function to generate random entropy
|
||||||
|
func generateEntropy() -> Data {
|
||||||
|
var bytes = [UInt8](repeating: 0, count: 32)
|
||||||
|
let status = SecRandomCopyBytes(kSecRandomDefault, bytes.count, &bytes)
|
||||||
|
guard status == errSecSuccess else {
|
||||||
|
fatalError("Failed to generate random bytes")
|
||||||
|
}
|
||||||
|
return Data(bytes)
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue