synor/sdk/cpp/examples/ibc_example.cpp
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

389 lines
16 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 <iostream>
#include <iomanip>
#include <cstdlib>
#include <chrono>
#include <synor/ibc.hpp>
using namespace synor::ibc;
void chains_example(SynorIbc& ibc) {
std::cout << "=== Chain Discovery ===" << std::endl;
// Get all connected chains
auto chains = ibc.chains().list();
std::cout << "Connected chains: " << chains.size() << std::endl;
for (size_t i = 0; i < std::min(chains.size(), size_t(5)); ++i) {
const auto& chain = chains[i];
std::cout << "\n " << chain.chain_id() << ":" << std::endl;
std::cout << " Name: " << chain.name() << std::endl;
std::cout << " Type: " << chain.chain_type() << std::endl;
std::cout << " Status: " << chain.status() << std::endl;
std::cout << " Block height: " << chain.latest_height() << std::endl;
std::cout << " Light client: " << chain.light_client() << std::endl;
}
// Get specific chain info
auto synor_chain = ibc.chains().get("synor-mainnet-1");
std::cout << "\nSynor chain details:" << std::endl;
std::cout << " Bech32 prefix: " << synor_chain.bech32_prefix() << std::endl;
std::cout << " Gas price: " << synor_chain.gas_price() << std::endl;
auto features = synor_chain.features();
std::cout << " Supported features: ";
for (size_t i = 0; i < features.size(); ++i) {
std::cout << features[i] << (i < features.size() - 1 ? ", " : "");
}
std::cout << std::endl;
// Get chain connections
auto connections = ibc.chains().get_connections("synor-mainnet-1");
std::cout << "\nChain connections: " << connections.size() << std::endl;
for (size_t i = 0; i < std::min(connections.size(), size_t(3)); ++i) {
const auto& conn = connections[i];
std::cout << " " << conn.connection_id() << " -> " << conn.counterparty_chain_id() << std::endl;
}
std::cout << std::endl;
}
void channels_example(SynorIbc& ibc) {
std::cout << "=== Channel Management ===" << std::endl;
// List existing channels
auto channels = ibc.channels().list();
std::cout << "Active channels: " << channels.size() << std::endl;
for (size_t i = 0; i < std::min(channels.size(), size_t(3)); ++i) {
const auto& channel = channels[i];
std::cout << "\n Channel " << channel.channel_id() << ":" << std::endl;
std::cout << " Port: " << channel.port_id() << std::endl;
std::cout << " State: " << channel.state() << std::endl;
std::cout << " Order: " << channel.ordering() << std::endl;
std::cout << " Counterparty: " << channel.counterparty_channel_id()
<< " on " << channel.counterparty_chain_id() << std::endl;
std::cout << " Version: " << channel.version() << std::endl;
}
// Create a new channel (4-step handshake)
std::cout << "\nInitiating channel creation..." << std::endl;
// Step 1: ChanOpenInit
auto init_result = ibc.channels().open_init({
.port_id = "transfer",
.counterparty_chain_id = "cosmos-hub-4",
.counterparty_port_id = "transfer",
.version = "ics20-1",
.ordering = ChannelOrdering::Unordered
});
std::cout << "Channel init:" << std::endl;
std::cout << " Channel ID: " << init_result.channel_id() << std::endl;
std::cout << " State: " << init_result.state() << std::endl;
std::cout << " TX hash: " << init_result.tx_hash() << std::endl;
// Step 2: Wait for ChanOpenTry (counterparty)
std::cout << "\nWaiting for counterparty ChanOpenTry..." << std::endl;
auto try_state = ibc.channels().wait_for_state(
init_result.channel_id(),
ChannelState::TryOpen,
std::chrono::minutes(5)
);
std::cout << "Channel state: " << try_state << std::endl;
// Step 3: ChanOpenAck
std::cout << "\nSending ChanOpenAck..." << std::endl;
auto ack_result = ibc.channels().open_ack({
.channel_id = init_result.channel_id(),
.counterparty_channel_id = "channel-0",
.counterparty_version = "ics20-1"
});
std::cout << "Ack TX: " << ack_result.tx_hash() << std::endl;
// Step 4: Wait for ChanOpenConfirm (counterparty)
std::cout << "\nWaiting for channel to open..." << std::endl;
auto open_state = ibc.channels().wait_for_state(
init_result.channel_id(),
ChannelState::Open,
std::chrono::minutes(5)
);
std::cout << "Channel is now: " << open_state << std::endl;
// Get channel details
auto channel = ibc.channels().get(init_result.channel_id());
std::cout << "\nChannel details:" << std::endl;
std::cout << " Sequences - Send: " << channel.next_sequence_send()
<< ", Recv: " << channel.next_sequence_recv()
<< ", Ack: " << channel.next_sequence_ack() << std::endl;
std::cout << std::endl;
}
void transfer_example(SynorIbc& ibc) {
std::cout << "=== Cross-Chain Transfers ===" << std::endl;
// Get supported tokens for transfer
auto tokens = ibc.transfers().get_supported_tokens("cosmos-hub-4");
std::cout << "Transferable tokens to Cosmos Hub:" << std::endl;
for (size_t i = 0; i < std::min(tokens.size(), size_t(5)); ++i) {
const auto& token = tokens[i];
std::cout << " " << token.symbol() << " (" << token.denom() << ")" << std::endl;
}
// Initiate a cross-chain transfer
std::cout << "\nInitiating transfer..." << std::endl;
auto now = std::chrono::system_clock::now();
auto timeout = std::chrono::duration_cast<std::chrono::nanoseconds>(
(now + std::chrono::seconds(600)).time_since_epoch()
).count();
auto transfer = ibc.transfers().send({
.source_channel = "channel-0",
.denom = "usynor",
.amount = "1000000",
.receiver = "cosmos1...",
.timeout_height = 0, // Use timestamp instead
.timeout_timestamp = static_cast<uint64_t>(timeout),
.memo = "IBC transfer from Synor"
});
std::cout << "Transfer initiated:" << std::endl;
std::cout << " TX hash: " << transfer.tx_hash() << std::endl;
std::cout << " Sequence: " << transfer.sequence() << std::endl;
std::cout << " Packet ID: " << transfer.packet_id() << std::endl;
std::cout << " Status: " << transfer.status() << std::endl;
// Track transfer progress
std::cout << "\nTracking transfer..." << std::endl;
auto status = ibc.transfers().track(transfer.packet_id());
std::cout << "Current status: " << status.state() << std::endl;
std::cout << "Source TX: " << status.source_tx_hash() << std::endl;
if (!status.dest_tx_hash().empty()) {
std::cout << "Dest TX: " << status.dest_tx_hash() << std::endl;
}
// Wait for completion
std::cout << "\nWaiting for transfer completion..." << std::endl;
auto final_status = ibc.transfers().wait_for_completion(
transfer.packet_id(),
std::chrono::minutes(10)
);
std::cout << "Transfer completed:" << std::endl;
std::cout << " Final status: " << final_status.state() << std::endl;
std::cout << " Acknowledgment: " << final_status.acknowledgment() << std::endl;
// Get transfer history
auto history = ibc.transfers().get_history(10);
std::cout << "\nRecent transfers: " << history.size() << std::endl;
for (size_t i = 0; i < std::min(history.size(), size_t(3)); ++i) {
const auto& t = history[i];
std::cout << " " << t.amount() << " " << t.denom()
<< " -> " << t.dest_chain() << " (" << t.status() << ")" << std::endl;
}
std::cout << std::endl;
}
void packet_example(SynorIbc& ibc) {
std::cout << "=== Packet Operations ===" << std::endl;
// List pending packets
auto pending = ibc.packets().list_pending("channel-0");
std::cout << "Pending packets on channel-0: " << pending.size() << std::endl;
for (size_t i = 0; i < std::min(pending.size(), size_t(3)); ++i) {
const auto& packet = pending[i];
std::cout << "\n Packet #" << packet.sequence() << ":" << std::endl;
std::cout << " Source: " << packet.source_port() << "/" << packet.source_channel() << std::endl;
std::cout << " Dest: " << packet.dest_port() << "/" << packet.dest_channel() << std::endl;
std::cout << " State: " << packet.state() << std::endl;
std::cout << " Timeout: " << packet.timeout_timestamp() << std::endl;
}
// Get specific packet
auto packet = ibc.packets().get("channel-0", 1);
std::cout << "\nPacket details:" << std::endl;
std::cout << " Data (hex): " << packet.data_hex().substr(0, 40) << "..." << std::endl;
std::cout << " Created: " << packet.created_at() << std::endl;
// Get packet commitment proof
auto proof = ibc.packets().get_commitment_proof("channel-0", 1);
std::cout << "\nCommitment proof:" << std::endl;
std::cout << " Height: " << proof.proof_height() << std::endl;
std::cout << " Proof size: " << proof.proof().size() << " bytes" << std::endl;
// Get acknowledgment
auto ack = ibc.packets().get_acknowledgment("channel-0", 1);
std::cout << "\nAcknowledgment:" << std::endl;
std::cout << " Result: " << (ack.success() ? "Success" : std::string("Error: ") + ack.error()) << std::endl;
std::cout << " TX hash: " << ack.tx_hash() << std::endl;
// List timed-out packets
auto timed_out = ibc.packets().list_timed_out();
std::cout << "\nTimed-out packets: " << timed_out.size() << std::endl;
// Timeout a packet manually
if (!timed_out.empty()) {
const auto& to_timeout = timed_out.front();
std::cout << "\nProcessing timeout for packet #" << to_timeout.sequence() << std::endl;
auto timeout = ibc.packets().timeout(to_timeout.source_channel(), to_timeout.sequence());
std::cout << "Timeout TX: " << timeout.tx_hash() << std::endl;
}
std::cout << std::endl;
}
void relayer_example(SynorIbc& ibc) {
std::cout << "=== Relayer Operations ===" << std::endl;
// Get relayer status
auto status = ibc.relayer().get_status();
std::cout << "Relayer status:" << std::endl;
std::cout << " Running: " << (status.running() ? "true" : "false") << std::endl;
std::cout << " Uptime: " << status.uptime() << std::endl;
std::cout << " Packets relayed: " << status.packets_relayed() << std::endl;
std::cout << " Errors: " << status.error_count() << std::endl;
// List active paths
auto paths = ibc.relayer().list_paths();
std::cout << "\nActive relay paths: " << paths.size() << std::endl;
for (const auto& path : paths) {
std::cout << "\n " << path.path_id() << ":" << std::endl;
std::cout << " " << path.source_chain() << " <-> " << path.dest_chain() << std::endl;
std::cout << " Channel: " << path.source_channel() << " <-> " << path.dest_channel() << std::endl;
std::cout << " Status: " << path.status() << std::endl;
std::cout << " Pending packets: " << path.pending_packets() << std::endl;
}
// Configure a new path
std::cout << "\nConfiguring new relay path..." << std::endl;
auto new_path = ibc.relayer().add_path({
.source_chain = "synor-mainnet-1",
.dest_chain = "osmosis-1",
.source_channel = "channel-1",
.dest_channel = "channel-100",
.filter_denoms = {"usynor", "uosmo"},
.min_relay_amount = "1000",
.max_relay_amount = "1000000000"
});
std::cout << "Path created: " << new_path.path_id() << std::endl;
// Start relaying on path
std::cout << "\nStarting relayer on path..." << std::endl;
ibc.relayer().start_path(new_path.path_id());
std::cout << "Relayer started" << std::endl;
// Manually relay pending packets
std::cout << "\nRelaying pending packets..." << std::endl;
auto relay_result = ibc.relayer().relay_pending(new_path.path_id());
std::cout << "Relayed " << relay_result.packet_count() << " packets" << std::endl;
std::cout << "TX hashes: " << relay_result.tx_hashes().size() << std::endl;
// Get relay history
auto history = ibc.relayer().get_history(new_path.path_id(), 10);
std::cout << "\nRelay history:" << std::endl;
for (size_t i = 0; i < std::min(history.size(), size_t(3)); ++i) {
const auto& event = history[i];
std::cout << " " << event.timestamp() << ": " << event.event_type()
<< " - " << event.packet_count() << " packets" << std::endl;
}
std::cout << std::endl;
}
void monitoring_example(SynorIbc& ibc) {
std::cout << "=== IBC Monitoring ===" << std::endl;
// Get IBC metrics
auto metrics = ibc.monitoring().get_metrics();
std::cout << "IBC metrics:" << std::endl;
std::cout << " Total channels: " << metrics.total_channels() << std::endl;
std::cout << " Active channels: " << metrics.active_channels() << std::endl;
std::cout << " Total packets: " << metrics.total_packets() << std::endl;
std::cout << " Pending packets: " << metrics.pending_packets() << std::endl;
std::cout << " Failed packets: " << metrics.failed_packets() << std::endl;
std::cout << " Avg relay time: " << metrics.avg_relay_time() << "ms" << std::endl;
// Get chain health
auto chain_health = ibc.monitoring().get_chain_health();
std::cout << "\nChain health:" << std::endl;
for (size_t i = 0; i < std::min(chain_health.size(), size_t(3)); ++i) {
const auto& health = chain_health[i];
std::cout << " " << health.chain_id() << ":" << std::endl;
std::cout << " Status: " << health.status() << std::endl;
std::cout << " Block lag: " << health.block_lag() << std::endl;
std::cout << " Last update: " << health.last_update() << std::endl;
}
// Get channel statistics
auto stats = ibc.monitoring().get_channel_stats("channel-0");
std::cout << "\nChannel-0 statistics:" << std::endl;
std::cout << " Packets sent: " << stats.packets_sent() << std::endl;
std::cout << " Packets received: " << stats.packets_received() << std::endl;
std::cout << " Success rate: " << stats.success_rate() << "%" << std::endl;
std::cout << " Avg confirmation time: " << stats.avg_confirmation_time() << "ms" << std::endl;
// Subscribe to IBC events
std::cout << "\nSubscribing to IBC events..." << std::endl;
ibc.monitoring().subscribe([](const IbcEvent& event) {
std::cout << "Event: " << event.type() << " on " << event.channel_id() << std::endl;
});
// Get alerts
auto alerts = ibc.monitoring().get_alerts();
std::cout << "\nActive alerts: " << alerts.size() << std::endl;
for (const auto& alert : alerts) {
std::cout << " [" << alert.severity() << "] " << alert.message() << std::endl;
}
std::cout << std::endl;
}
int main(int argc, char** argv) {
// Initialize client
const char* api_key = std::getenv("SYNOR_API_KEY");
IbcConfig config{
.api_key = api_key ? api_key : "your-api-key",
.endpoint = "https://ibc.synor.io/v1",
.timeout = std::chrono::seconds(30),
.retries = 3,
.debug = false,
.default_chain = "synor-mainnet-1",
.confirmations = 1
};
SynorIbc ibc(config);
try {
// Check service health
bool healthy = ibc.health_check();
std::cout << "Service healthy: " << (healthy ? "true" : "false") << std::endl << std::endl;
// Run examples
chains_example(ibc);
channels_example(ibc);
transfer_example(ibc);
packet_example(ibc);
relayer_example(ibc);
monitoring_example(ibc);
} catch (const std::exception& e) {
std::cerr << "Error: " << e.what() << std::endl;
return 1;
}
return 0;
}