synor/sdk/c/examples/ibc_example.c
Gulshan Yadav cf5130d9e4 feat(sdk): Add comprehensive examples for C, C++, C#, and Ruby SDKs
Add example code demonstrating all SDK services (Crypto, DEX, ZK, IBC,
Compiler) for the remaining languages:

- C SDK (5 examples): Using synor_* C API with explicit memory management
- C++ SDK (5 examples): Modern C++17 with RAII and designated initializers
- C# SDK (5 examples): Async/await patterns with .NET conventions
- Ruby SDK (5 examples): Ruby idioms with blocks and symbols

Each example covers:
- Crypto: Hybrid signatures, mnemonics, Falcon, SPHINCS+, KDF, hashing
- DEX: Markets, spot trading, perpetuals, liquidity, portfolio
- ZK: Circuits, Groth16, PLONK, STARK, recursive proofs, ceremonies
- IBC: Chains, channels, transfers, packets, relayer, monitoring
- Compiler: Compilation, optimization, ABI, analysis, validation, security
2026-01-28 14:44:04 +05:30

545 lines
21 KiB
C

/**
* Synor IBC SDK Examples for C
*
* Demonstrates Inter-Blockchain Communication operations:
* - Cross-chain transfers and messages
* - Channel lifecycle management
* - Packet handling and acknowledgments
* - Relayer operations
* - Connection monitoring
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <synor/ibc.h>
void chains_example(synor_ibc_t* ibc) {
printf("=== Chain Discovery ===\n");
synor_error_t err;
// Get all connected chains
synor_chain_list_t* chains = NULL;
err = synor_chains_list(ibc, &chains);
if (err != SYNOR_OK) {
fprintf(stderr, "Failed to get chains\n");
return;
}
printf("Connected chains: %zu\n", synor_chain_list_count(chains));
for (size_t i = 0; i < 5 && i < synor_chain_list_count(chains); i++) {
synor_chain_t* chain = synor_chain_list_get(chains, i);
printf("\n %s:\n", synor_chain_get_id(chain));
printf(" Name: %s\n", synor_chain_get_name(chain));
printf(" Type: %s\n", synor_chain_get_type(chain));
printf(" Status: %s\n", synor_chain_get_status(chain));
printf(" Block height: %lu\n", synor_chain_get_latest_height(chain));
printf(" Light client: %s\n", synor_chain_get_light_client(chain));
}
synor_chain_list_free(chains);
// Get specific chain info
synor_chain_t* synor_chain = NULL;
err = synor_chains_get(ibc, "synor-mainnet-1", &synor_chain);
if (err == SYNOR_OK) {
printf("\nSynor chain details:\n");
printf(" Bech32 prefix: %s\n", synor_chain_get_bech32_prefix(synor_chain));
printf(" Gas price: %s\n", synor_chain_get_gas_price(synor_chain));
char** features;
size_t feature_count;
synor_chain_get_features(synor_chain, &features, &feature_count);
printf(" Supported features: ");
for (size_t i = 0; i < feature_count; i++) {
printf("%s%s", features[i], i < feature_count - 1 ? ", " : "");
}
printf("\n");
synor_string_array_free(features, feature_count);
synor_chain_free(synor_chain);
}
// Get chain connections
synor_connection_list_t* connections = NULL;
err = synor_chains_get_connections(ibc, "synor-mainnet-1", &connections);
if (err == SYNOR_OK) {
printf("\nChain connections: %zu\n", synor_connection_list_count(connections));
for (size_t i = 0; i < 3 && i < synor_connection_list_count(connections); i++) {
synor_connection_t* conn = synor_connection_list_get(connections, i);
printf(" %s -> %s\n",
synor_connection_get_id(conn),
synor_connection_get_counterparty_chain_id(conn));
}
synor_connection_list_free(connections);
}
printf("\n");
}
void channels_example(synor_ibc_t* ibc) {
printf("=== Channel Management ===\n");
synor_error_t err;
// List existing channels
synor_channel_list_t* channels = NULL;
err = synor_channels_list(ibc, &channels);
if (err == SYNOR_OK) {
printf("Active channels: %zu\n", synor_channel_list_count(channels));
for (size_t i = 0; i < 3 && i < synor_channel_list_count(channels); i++) {
synor_channel_t* channel = synor_channel_list_get(channels, i);
printf("\n Channel %s:\n", synor_channel_get_id(channel));
printf(" Port: %s\n", synor_channel_get_port_id(channel));
printf(" State: %s\n", synor_channel_get_state(channel));
printf(" Order: %s\n", synor_channel_get_ordering(channel));
printf(" Counterparty: %s on %s\n",
synor_channel_get_counterparty_channel_id(channel),
synor_channel_get_counterparty_chain_id(channel));
printf(" Version: %s\n", synor_channel_get_version(channel));
}
synor_channel_list_free(channels);
}
// Create a new channel (4-step handshake)
printf("\nInitiating channel creation...\n");
// Step 1: ChanOpenInit
synor_channel_init_request_t init_req = {
.port_id = "transfer",
.counterparty_chain_id = "cosmos-hub-4",
.counterparty_port_id = "transfer",
.version = "ics20-1",
.ordering = SYNOR_CHANNEL_ORDERING_UNORDERED
};
synor_channel_init_result_t* init_result = NULL;
err = synor_channels_open_init(ibc, &init_req, &init_result);
if (err != SYNOR_OK) {
fprintf(stderr, "Failed to init channel\n");
return;
}
printf("Channel init:\n");
printf(" Channel ID: %s\n", synor_channel_init_result_get_id(init_result));
printf(" State: %s\n", synor_channel_init_result_get_state(init_result));
printf(" TX hash: %s\n", synor_channel_init_result_get_tx_hash(init_result));
// Step 2: Wait for ChanOpenTry (counterparty)
printf("\nWaiting for counterparty ChanOpenTry...\n");
synor_channel_state_t try_state;
err = synor_channels_wait_for_state(ibc, synor_channel_init_result_get_id(init_result),
SYNOR_CHANNEL_STATE_TRYOPEN, 300, &try_state);
printf("Channel state: %d\n", try_state);
// Step 3: ChanOpenAck
printf("\nSending ChanOpenAck...\n");
synor_channel_ack_request_t ack_req = {
.channel_id = synor_channel_init_result_get_id(init_result),
.counterparty_channel_id = "channel-0",
.counterparty_version = "ics20-1"
};
synor_channel_ack_result_t* ack_result = NULL;
err = synor_channels_open_ack(ibc, &ack_req, &ack_result);
if (err == SYNOR_OK) {
printf("Ack TX: %s\n", synor_channel_ack_result_get_tx_hash(ack_result));
synor_channel_ack_result_free(ack_result);
}
// Step 4: Wait for ChanOpenConfirm (counterparty)
printf("\nWaiting for channel to open...\n");
synor_channel_state_t open_state;
err = synor_channels_wait_for_state(ibc, synor_channel_init_result_get_id(init_result),
SYNOR_CHANNEL_STATE_OPEN, 300, &open_state);
printf("Channel is now: %d\n", open_state);
// Get channel details
synor_channel_t* channel = NULL;
err = synor_channels_get(ibc, synor_channel_init_result_get_id(init_result), &channel);
if (err == SYNOR_OK) {
printf("\nChannel details:\n");
printf(" Sequences - Send: %lu, Recv: %lu, Ack: %lu\n",
synor_channel_get_next_sequence_send(channel),
synor_channel_get_next_sequence_recv(channel),
synor_channel_get_next_sequence_ack(channel));
synor_channel_free(channel);
}
synor_channel_init_result_free(init_result);
printf("\n");
}
void transfer_example(synor_ibc_t* ibc) {
printf("=== Cross-Chain Transfers ===\n");
synor_error_t err;
// Get supported tokens for transfer
synor_transferable_token_list_t* tokens = NULL;
err = synor_transfers_get_supported_tokens(ibc, "cosmos-hub-4", &tokens);
if (err == SYNOR_OK) {
printf("Transferable tokens to Cosmos Hub:\n");
for (size_t i = 0; i < 5 && i < synor_transferable_token_list_count(tokens); i++) {
synor_transferable_token_t* token = synor_transferable_token_list_get(tokens, i);
printf(" %s (%s)\n",
synor_transferable_token_get_symbol(token),
synor_transferable_token_get_denom(token));
}
synor_transferable_token_list_free(tokens);
}
// Initiate a cross-chain transfer
printf("\nInitiating transfer...\n");
synor_transfer_request_t transfer_req = {
.source_channel = "channel-0",
.denom = "usynor",
.amount = "1000000",
.receiver = "cosmos1...",
.timeout_height = 0, // Use timestamp instead
.timeout_timestamp = (uint64_t)(time(NULL) + 600) * 1000000000ULL,
.memo = "IBC transfer from Synor"
};
synor_transfer_result_t* transfer = NULL;
err = synor_transfers_send(ibc, &transfer_req, &transfer);
if (err != SYNOR_OK) {
fprintf(stderr, "Failed to send transfer\n");
return;
}
printf("Transfer initiated:\n");
printf(" TX hash: %s\n", synor_transfer_result_get_tx_hash(transfer));
printf(" Sequence: %lu\n", synor_transfer_result_get_sequence(transfer));
printf(" Packet ID: %s\n", synor_transfer_result_get_packet_id(transfer));
printf(" Status: %s\n", synor_transfer_result_get_status(transfer));
// Track transfer progress
printf("\nTracking transfer...\n");
synor_transfer_status_t* status = NULL;
err = synor_transfers_track(ibc, synor_transfer_result_get_packet_id(transfer), &status);
if (err == SYNOR_OK) {
printf("Current status: %s\n", synor_transfer_status_get_state(status));
printf("Source TX: %s\n", synor_transfer_status_get_source_tx_hash(status));
const char* dest_tx = synor_transfer_status_get_dest_tx_hash(status);
if (dest_tx) {
printf("Dest TX: %s\n", dest_tx);
}
synor_transfer_status_free(status);
}
// Wait for completion
printf("\nWaiting for transfer completion...\n");
synor_transfer_status_t* final_status = NULL;
err = synor_transfers_wait_for_completion(ibc, synor_transfer_result_get_packet_id(transfer),
600, &final_status);
if (err == SYNOR_OK) {
printf("Transfer completed:\n");
printf(" Final status: %s\n", synor_transfer_status_get_state(final_status));
printf(" Acknowledgment: %s\n", synor_transfer_status_get_acknowledgment(final_status));
synor_transfer_status_free(final_status);
}
// Get transfer history
synor_transfer_list_t* history = NULL;
err = synor_transfers_get_history(ibc, 10, &history);
if (err == SYNOR_OK) {
printf("\nRecent transfers: %zu\n", synor_transfer_list_count(history));
for (size_t i = 0; i < 3 && i < synor_transfer_list_count(history); i++) {
synor_transfer_t* t = synor_transfer_list_get(history, i);
printf(" %s %s -> %s (%s)\n",
synor_transfer_get_amount(t),
synor_transfer_get_denom(t),
synor_transfer_get_dest_chain(t),
synor_transfer_get_status(t));
}
synor_transfer_list_free(history);
}
synor_transfer_result_free(transfer);
printf("\n");
}
void packet_example(synor_ibc_t* ibc) {
printf("=== Packet Operations ===\n");
synor_error_t err;
// List pending packets
synor_packet_list_t* pending = NULL;
err = synor_packets_list_pending(ibc, "channel-0", &pending);
if (err == SYNOR_OK) {
printf("Pending packets on channel-0: %zu\n", synor_packet_list_count(pending));
for (size_t i = 0; i < 3 && i < synor_packet_list_count(pending); i++) {
synor_packet_t* packet = synor_packet_list_get(pending, i);
printf("\n Packet #%lu:\n", synor_packet_get_sequence(packet));
printf(" Source: %s/%s\n",
synor_packet_get_source_port(packet),
synor_packet_get_source_channel(packet));
printf(" Dest: %s/%s\n",
synor_packet_get_dest_port(packet),
synor_packet_get_dest_channel(packet));
printf(" State: %s\n", synor_packet_get_state(packet));
printf(" Timeout: %lu\n", synor_packet_get_timeout_timestamp(packet));
}
synor_packet_list_free(pending);
}
// Get specific packet
synor_packet_t* packet = NULL;
err = synor_packets_get(ibc, "channel-0", 1, &packet);
if (err == SYNOR_OK) {
printf("\nPacket details:\n");
const char* data_hex = synor_packet_get_data_hex(packet);
printf(" Data (hex): %.40s...\n", data_hex);
printf(" Created: %s\n", synor_packet_get_created_at(packet));
synor_packet_free(packet);
}
// Get packet commitment proof
synor_packet_proof_t* proof = NULL;
err = synor_packets_get_commitment_proof(ibc, "channel-0", 1, &proof);
if (err == SYNOR_OK) {
printf("\nCommitment proof:\n");
printf(" Height: %lu\n", synor_packet_proof_get_height(proof));
printf(" Proof size: %zu bytes\n", synor_packet_proof_get_size(proof));
synor_packet_proof_free(proof);
}
// Get acknowledgment
synor_packet_ack_t* ack = NULL;
err = synor_packets_get_acknowledgment(ibc, "channel-0", 1, &ack);
if (err == SYNOR_OK) {
printf("\nAcknowledgment:\n");
printf(" Result: %s\n", synor_packet_ack_is_success(ack) ? "Success" :
synor_packet_ack_get_error(ack));
printf(" TX hash: %s\n", synor_packet_ack_get_tx_hash(ack));
synor_packet_ack_free(ack);
}
// List timed-out packets
synor_packet_list_t* timed_out = NULL;
err = synor_packets_list_timed_out(ibc, &timed_out);
if (err == SYNOR_OK) {
printf("\nTimed-out packets: %zu\n", synor_packet_list_count(timed_out));
// Timeout a packet manually
if (synor_packet_list_count(timed_out) > 0) {
synor_packet_t* to_timeout = synor_packet_list_get(timed_out, 0);
printf("\nProcessing timeout for packet #%lu\n", synor_packet_get_sequence(to_timeout));
synor_timeout_result_t* timeout = NULL;
err = synor_packets_timeout(ibc, synor_packet_get_source_channel(to_timeout),
synor_packet_get_sequence(to_timeout), &timeout);
if (err == SYNOR_OK) {
printf("Timeout TX: %s\n", synor_timeout_result_get_tx_hash(timeout));
synor_timeout_result_free(timeout);
}
}
synor_packet_list_free(timed_out);
}
printf("\n");
}
void relayer_example(synor_ibc_t* ibc) {
printf("=== Relayer Operations ===\n");
synor_error_t err;
// Get relayer status
synor_relayer_status_t* status = NULL;
err = synor_relayer_get_status(ibc, &status);
if (err == SYNOR_OK) {
printf("Relayer status:\n");
printf(" Running: %s\n", synor_relayer_status_is_running(status) ? "true" : "false");
printf(" Uptime: %s\n", synor_relayer_status_get_uptime(status));
printf(" Packets relayed: %lu\n", synor_relayer_status_get_packets_relayed(status));
printf(" Errors: %lu\n", synor_relayer_status_get_error_count(status));
synor_relayer_status_free(status);
}
// List active paths
synor_relay_path_list_t* paths = NULL;
err = synor_relayer_list_paths(ibc, &paths);
if (err == SYNOR_OK) {
printf("\nActive relay paths: %zu\n", synor_relay_path_list_count(paths));
for (size_t i = 0; i < synor_relay_path_list_count(paths); i++) {
synor_relay_path_t* path = synor_relay_path_list_get(paths, i);
printf("\n %s:\n", synor_relay_path_get_id(path));
printf(" %s <-> %s\n",
synor_relay_path_get_source_chain(path),
synor_relay_path_get_dest_chain(path));
printf(" Channel: %s <-> %s\n",
synor_relay_path_get_source_channel(path),
synor_relay_path_get_dest_channel(path));
printf(" Status: %s\n", synor_relay_path_get_status(path));
printf(" Pending packets: %zu\n", synor_relay_path_get_pending_packets(path));
}
synor_relay_path_list_free(paths);
}
// Configure a new path
printf("\nConfiguring new relay path...\n");
const char* filter_denoms[] = {"usynor", "uosmo"};
synor_path_config_t path_config = {
.source_chain = "synor-mainnet-1",
.dest_chain = "osmosis-1",
.source_channel = "channel-1",
.dest_channel = "channel-100",
.filter_denoms = filter_denoms,
.filter_denoms_count = 2,
.min_relay_amount = "1000",
.max_relay_amount = "1000000000"
};
synor_relay_path_t* new_path = NULL;
err = synor_relayer_add_path(ibc, &path_config, &new_path);
if (err == SYNOR_OK) {
printf("Path created: %s\n", synor_relay_path_get_id(new_path));
// Start relaying on path
printf("\nStarting relayer on path...\n");
err = synor_relayer_start_path(ibc, synor_relay_path_get_id(new_path));
if (err == SYNOR_OK) {
printf("Relayer started\n");
}
// Manually relay pending packets
printf("\nRelaying pending packets...\n");
synor_relay_result_t* relay_result = NULL;
err = synor_relayer_relay_pending(ibc, synor_relay_path_get_id(new_path), &relay_result);
if (err == SYNOR_OK) {
printf("Relayed %zu packets\n", synor_relay_result_get_packet_count(relay_result));
printf("TX hashes: %zu\n", synor_relay_result_get_tx_hash_count(relay_result));
synor_relay_result_free(relay_result);
}
// Get relay history
synor_relay_event_list_t* history = NULL;
err = synor_relayer_get_history(ibc, synor_relay_path_get_id(new_path), 10, &history);
if (err == SYNOR_OK) {
printf("\nRelay history:\n");
for (size_t i = 0; i < 3 && i < synor_relay_event_list_count(history); i++) {
synor_relay_event_t* event = synor_relay_event_list_get(history, i);
printf(" %s: %s - %zu packets\n",
synor_relay_event_get_timestamp(event),
synor_relay_event_get_type(event),
synor_relay_event_get_packet_count(event));
}
synor_relay_event_list_free(history);
}
synor_relay_path_free(new_path);
}
printf("\n");
}
void monitoring_example(synor_ibc_t* ibc) {
printf("=== IBC Monitoring ===\n");
synor_error_t err;
// Get IBC metrics
synor_ibc_metrics_t* metrics = NULL;
err = synor_monitoring_get_metrics(ibc, &metrics);
if (err == SYNOR_OK) {
printf("IBC metrics:\n");
printf(" Total channels: %lu\n", synor_ibc_metrics_get_total_channels(metrics));
printf(" Active channels: %lu\n", synor_ibc_metrics_get_active_channels(metrics));
printf(" Total packets: %lu\n", synor_ibc_metrics_get_total_packets(metrics));
printf(" Pending packets: %lu\n", synor_ibc_metrics_get_pending_packets(metrics));
printf(" Failed packets: %lu\n", synor_ibc_metrics_get_failed_packets(metrics));
printf(" Avg relay time: %lums\n", synor_ibc_metrics_get_avg_relay_time(metrics));
synor_ibc_metrics_free(metrics);
}
// Get chain health
synor_chain_health_list_t* chain_health = NULL;
err = synor_monitoring_get_chain_health(ibc, &chain_health);
if (err == SYNOR_OK) {
printf("\nChain health:\n");
for (size_t i = 0; i < 3 && i < synor_chain_health_list_count(chain_health); i++) {
synor_chain_health_t* health = synor_chain_health_list_get(chain_health, i);
printf(" %s:\n", synor_chain_health_get_chain_id(health));
printf(" Status: %s\n", synor_chain_health_get_status(health));
printf(" Block lag: %lu\n", synor_chain_health_get_block_lag(health));
printf(" Last update: %s\n", synor_chain_health_get_last_update(health));
}
synor_chain_health_list_free(chain_health);
}
// Get channel statistics
synor_channel_stats_t* stats = NULL;
err = synor_monitoring_get_channel_stats(ibc, "channel-0", &stats);
if (err == SYNOR_OK) {
printf("\nChannel-0 statistics:\n");
printf(" Packets sent: %lu\n", synor_channel_stats_get_packets_sent(stats));
printf(" Packets received: %lu\n", synor_channel_stats_get_packets_received(stats));
printf(" Success rate: %s%%\n", synor_channel_stats_get_success_rate(stats));
printf(" Avg confirmation time: %lums\n", synor_channel_stats_get_avg_confirmation_time(stats));
synor_channel_stats_free(stats);
}
// Get alerts
synor_ibc_alert_list_t* alerts = NULL;
err = synor_monitoring_get_alerts(ibc, &alerts);
if (err == SYNOR_OK) {
printf("\nActive alerts: %zu\n", synor_ibc_alert_list_count(alerts));
for (size_t i = 0; i < synor_ibc_alert_list_count(alerts); i++) {
synor_ibc_alert_t* alert = synor_ibc_alert_list_get(alerts, i);
printf(" [%s] %s\n",
synor_ibc_alert_get_severity(alert),
synor_ibc_alert_get_message(alert));
}
synor_ibc_alert_list_free(alerts);
}
printf("\n");
}
int main(int argc, char** argv) {
synor_error_t err;
// Initialize client
synor_ibc_config_t config = {
.api_key = getenv("SYNOR_API_KEY") ? getenv("SYNOR_API_KEY") : "your-api-key",
.endpoint = "https://ibc.synor.io/v1",
.timeout_ms = 30000,
.retries = 3,
.debug = false,
.default_chain = "synor-mainnet-1",
.confirmations = 1
};
synor_ibc_t* ibc = NULL;
err = synor_ibc_init(&config, &ibc);
if (err != SYNOR_OK) {
fprintf(stderr, "Failed to initialize IBC client: %s\n", synor_error_string(err));
return 1;
}
// Check service health
bool healthy;
err = synor_ibc_health_check(ibc, &healthy);
printf("Service healthy: %s\n\n", healthy ? "true" : "false");
// Run examples
chains_example(ibc);
channels_example(ibc);
transfer_example(ibc);
packet_example(ibc);
relayer_example(ibc);
monitoring_example(ibc);
// Cleanup
synor_ibc_free(ibc);
return 0;
}