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
389 lines
16 KiB
C++
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;
|
|
}
|