synor/sdk/swift/Examples/IbcExample.swift
Gulshan Yadav e169c492aa 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.
2026-01-28 14:30:19 +05:30

369 lines
13 KiB
Swift

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()
}
}