/** * Synor IBC SDK Examples for JavaScript/TypeScript * * Demonstrates Inter-Blockchain Communication operations: * - Cross-chain token transfers * - Channel management * - Packet handling * - Relayer operations */ import { SynorIbc, IbcConfig, Network, ChannelState, PacketState, } from '../src/ibc'; async function main() { // Initialize client const config: IbcConfig = { apiKey: process.env.SYNOR_API_KEY || 'your-api-key', endpoint: 'https://ibc.synor.io/v1', timeout: 30000, retries: 3, debug: false, defaultNetwork: Network.Mainnet, }; const ibc = new SynorIbc(config); try { // Check service health const healthy = await ibc.healthCheck(); console.log(`Service healthy: ${healthy}\n`); // Example 1: Connected chains await chainsExample(ibc); // Example 2: Channel management await channelsExample(ibc); // Example 3: Token transfers await transferExample(ibc); // Example 4: Packet tracking await packetExample(ibc); // Example 5: Relayer operations await relayerExample(ibc); // Example 6: Connection info await connectionExample(ibc); } finally { ibc.close(); } } /** * Connected chains information */ async function chainsExample(ibc: SynorIbc): Promise { console.log('=== Connected Chains ==='); // Get all connected chains const chains = await ibc.chains.list(); console.log(`Connected chains: ${chains.length}`); for (const chain of chains) { console.log(` ${chain.chainId}:`); console.log(` Name: ${chain.name}`); console.log(` Status: ${chain.status}`); console.log(` Block height: ${chain.latestHeight}`); console.log(` Channels: ${chain.channelCount}`); } // Get specific chain info const cosmos = await ibc.chains.get('cosmoshub-4'); console.log(`\nCosmos Hub details:`); console.log(` RPC: ${cosmos.rpcEndpoint}`); console.log(` Rest: ${cosmos.restEndpoint}`); console.log(` Native denom: ${cosmos.nativeDenom}`); console.log(` Prefix: ${cosmos.bech32Prefix}`); // Get supported assets on a chain const assets = await ibc.chains.getAssets('cosmoshub-4'); console.log(`\nSupported assets on Cosmos Hub:`); for (const asset of assets.slice(0, 5)) { console.log(` ${asset.symbol}: ${asset.denom}`); console.log(` Origin: ${asset.originChain}`); console.log(` Decimals: ${asset.decimals}`); } // Get chain paths (routes) const paths = await ibc.chains.getPaths('synor-1', 'cosmoshub-4'); console.log(`\nPaths from Synor to Cosmos Hub:`); for (const path of paths) { console.log(` ${path.sourceChannel} -> ${path.destChannel}`); console.log(` Hops: ${path.hops}`); console.log(` Avg time: ${path.avgTransferTime}s`); } console.log(''); } /** * Channel management */ async function channelsExample(ibc: SynorIbc): Promise { console.log('=== Channel Management ==='); // List all channels const channels = await ibc.channels.list(); console.log(`Total channels: ${channels.length}`); // Filter by state const openChannels = channels.filter(c => c.state === ChannelState.Open); console.log(`Open channels: ${openChannels.length}`); for (const channel of openChannels.slice(0, 3)) { console.log(`\n Channel ${channel.channelId}:`); console.log(` Port: ${channel.portId}`); console.log(` Counterparty: ${channel.counterpartyChannelId} on ${channel.counterpartyChainId}`); console.log(` Ordering: ${channel.ordering}`); console.log(` Version: ${channel.version}`); console.log(` State: ${channel.state}`); } // Get specific channel const channel = await ibc.channels.get('channel-0'); console.log(`\nChannel-0 details:`); console.log(` Connection: ${channel.connectionId}`); console.log(` Counterparty port: ${channel.counterpartyPortId}`); // Get channel statistics const stats = await ibc.channels.getStats('channel-0'); console.log(`\nChannel-0 statistics:`); console.log(` Total packets sent: ${stats.packetsSent}`); console.log(` Total packets received: ${stats.packetsReceived}`); console.log(` Pending packets: ${stats.pendingPackets}`); console.log(` Success rate: ${stats.successRate}%`); console.log(` Avg relay time: ${stats.avgRelayTime}s`); // Get channel capacity const capacity = await ibc.channels.getCapacity('channel-0'); console.log(`\nChannel-0 capacity:`); console.log(` Max throughput: ${capacity.maxPacketsPerBlock} packets/block`); console.log(` Current utilization: ${capacity.utilization}%`); console.log(''); } /** * Cross-chain token transfers */ async function transferExample(ibc: SynorIbc): Promise { console.log('=== Cross-Chain Transfers ==='); // Estimate transfer fee const estimate = await ibc.transfers.estimateFee({ sourceChain: 'synor-1', destChain: 'cosmoshub-4', denom: 'usyn', amount: '1000000', // 1 SYN (6 decimals) }); console.log('Transfer fee estimate:'); console.log(` Gas: ${estimate.gas}`); console.log(` Fee: ${estimate.fee} ${estimate.feeDenom}`); console.log(` Timeout: ${estimate.timeout}s`); // Initiate a transfer console.log('\nInitiating transfer...'); const transfer = await ibc.transfers.send({ sourceChain: 'synor-1', destChain: 'cosmoshub-4', channel: 'channel-0', sender: 'synor1abc...', // Your address receiver: 'cosmos1xyz...', // Recipient address denom: 'usyn', amount: '1000000', // 1 SYN memo: 'Cross-chain transfer example', timeoutHeight: 0, // Use timestamp instead timeoutTimestamp: Date.now() + 600000, // 10 minutes }); console.log(`Transfer initiated:`); console.log(` TX Hash: ${transfer.txHash}`); console.log(` Sequence: ${transfer.sequence}`); console.log(` Status: ${transfer.status}`); // Track transfer status console.log('\nTracking transfer...'); const status = await ibc.transfers.getStatus(transfer.txHash); console.log(`Current status: ${status.state}`); console.log(` Source confirmed: ${status.sourceConfirmed}`); console.log(` Relayed: ${status.relayed}`); console.log(` Dest confirmed: ${status.destConfirmed}`); // Get transfer history const history = await ibc.transfers.getHistory({ address: 'synor1abc...', limit: 5, }); console.log(`\nTransfer history (last 5):`); for (const tx of history) { const direction = tx.sender === 'synor1abc...' ? 'OUT' : 'IN'; console.log(` ${direction} ${tx.amount} ${tx.denom} (${tx.status})`); } // Get pending transfers const pending = await ibc.transfers.getPending('synor1abc...'); console.log(`\nPending transfers: ${pending.length}`); console.log(''); } /** * Packet handling */ async function packetExample(ibc: SynorIbc): Promise { console.log('=== Packet Handling ==='); // Get pending packets const packets = await ibc.packets.getPending('channel-0'); console.log(`Pending packets on channel-0: ${packets.length}`); for (const packet of packets.slice(0, 3)) { console.log(`\n Packet ${packet.sequence}:`); console.log(` Source: ${packet.sourcePort}/${packet.sourceChannel}`); console.log(` Dest: ${packet.destPort}/${packet.destChannel}`); console.log(` State: ${packet.state}`); console.log(` Data size: ${packet.data.length} bytes`); console.log(` Timeout height: ${packet.timeoutHeight}`); console.log(` Timeout timestamp: ${new Date(packet.timeoutTimestamp).toISOString()}`); } // Get packet by sequence const packet = await ibc.packets.get('channel-0', 1); console.log(`\nPacket details:`); console.log(` Commitment: ${packet.commitment}`); console.log(` Receipt: ${packet.receipt}`); console.log(` Acknowledgement: ${packet.acknowledgement}`); // Get packet receipts const receipts = await ibc.packets.getReceipts('channel-0', [1, 2, 3]); console.log(`\nPacket receipts:`); for (const [seq, receipt] of Object.entries(receipts)) { console.log(` Sequence ${seq}: ${receipt ? 'received' : 'not received'}`); } // Get timed out packets const timedOut = await ibc.packets.getTimedOut('channel-0'); console.log(`\nTimed out packets: ${timedOut.length}`); for (const p of timedOut) { console.log(` Sequence ${p.sequence}: timeout at ${new Date(p.timeoutTimestamp).toISOString()}`); } // Get unreceived packets const unreceived = await ibc.packets.getUnreceived('channel-0'); console.log(`\nUnreceived packet sequences: ${unreceived.join(', ') || 'none'}`); // Get unacknowledged packets const unacked = await ibc.packets.getUnacknowledged('channel-0'); console.log(`Unacknowledged packet sequences: ${unacked.join(', ') || 'none'}`); console.log(''); } /** * Relayer operations */ async function relayerExample(ibc: SynorIbc): Promise { console.log('=== Relayer Operations ==='); // Get active relayers const relayers = await ibc.relayers.list(); console.log(`Active relayers: ${relayers.length}`); for (const relayer of relayers.slice(0, 3)) { console.log(`\n ${relayer.address}:`); console.log(` Chains: ${relayer.chains.join(', ')}`); console.log(` Packets relayed: ${relayer.packetsRelayed}`); console.log(` Success rate: ${relayer.successRate}%`); console.log(` Avg latency: ${relayer.avgLatency}ms`); console.log(` Fee rate: ${relayer.feeRate}%`); } // Get relayer statistics const stats = await ibc.relayers.getStats(); console.log('\nGlobal relayer statistics:'); console.log(` Total relayers: ${stats.totalRelayers}`); console.log(` Active relayers: ${stats.activeRelayers}`); console.log(` Packets relayed (24h): ${stats.packetsRelayed24h}`); console.log(` Total fees earned: ${stats.totalFeesEarned}`); // Register as a relayer console.log('\nRegistering as relayer...'); const registration = await ibc.relayers.register({ chains: ['synor-1', 'cosmoshub-4'], feeRate: 0.1, // 0.1% fee minPacketSize: 0, maxPacketSize: 1000000, }); console.log(`Registered with address: ${registration.relayerAddress}`); // Start relaying (in background) console.log('\nStarting relay service...'); const relaySession = await ibc.relayers.startRelay({ channels: ['channel-0'], autoAck: true, batchSize: 10, pollInterval: 5000, }); console.log(`Relay session started: ${relaySession.sessionId}`); // Get relay queue const queue = await ibc.relayers.getQueue('channel-0'); console.log(`\nRelay queue for channel-0: ${queue.length} packets`); // Manually relay a packet if (queue.length > 0) { console.log('\nRelaying packet...'); const relayResult = await ibc.relayers.relayPacket(queue[0].sequence, 'channel-0'); console.log(`Relay result: ${relayResult.status}`); console.log(` TX Hash: ${relayResult.txHash}`); console.log(` Fee earned: ${relayResult.feeEarned}`); } // Stop relay session await ibc.relayers.stopRelay(relaySession.sessionId); console.log('\nRelay session stopped'); console.log(''); } /** * Connection information */ async function connectionExample(ibc: SynorIbc): Promise { console.log('=== Connection Information ==='); // List connections const connections = await ibc.connections.list(); console.log(`Total connections: ${connections.length}`); for (const conn of connections.slice(0, 3)) { console.log(`\n ${conn.connectionId}:`); console.log(` Client: ${conn.clientId}`); console.log(` Counterparty: ${conn.counterpartyConnectionId}`); console.log(` State: ${conn.state}`); console.log(` Versions: ${conn.versions.join(', ')}`); } // Get connection details const connection = await ibc.connections.get('connection-0'); console.log(`\nConnection-0 details:`); console.log(` Delay period: ${connection.delayPeriod}ns`); console.log(` Counterparty client: ${connection.counterpartyClientId}`); console.log(` Counterparty prefix: ${connection.counterpartyPrefix}`); // Get client state const client = await ibc.clients.get(connection.clientId); console.log(`\nClient state:`); console.log(` Chain ID: ${client.chainId}`); console.log(` Trust level: ${client.trustLevel}`); console.log(` Trusting period: ${client.trustingPeriod}`); console.log(` Unbonding period: ${client.unbondingPeriod}`); console.log(` Latest height: ${client.latestHeight}`); console.log(` Frozen: ${client.frozen}`); // Get consensus state const consensus = await ibc.clients.getConsensusState(connection.clientId, client.latestHeight); console.log(`\nConsensus state at height ${client.latestHeight}:`); console.log(` Timestamp: ${new Date(consensus.timestamp).toISOString()}`); console.log(` Root: ${consensus.root.slice(0, 20)}...`); console.log(` Next validators hash: ${consensus.nextValidatorsHash.slice(0, 20)}...`); console.log(''); } // Run examples main().catch(console.error);