- 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.
369 lines
13 KiB
Swift
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()
|
|
}
|
|
}
|