- Introduced `ibc_example.rs` demonstrating Inter-Blockchain Communication operations including cross-chain transfers, channel management, packet handling, and relayer operations. - Introduced `zk_example.rs` showcasing Zero-Knowledge proof operations such as circuit compilation, proof generation and verification, and on-chain verification with multiple proving systems.
380 lines
13 KiB
TypeScript
380 lines
13 KiB
TypeScript
/**
|
|
* 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<void> {
|
|
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<void> {
|
|
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<void> {
|
|
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<void> {
|
|
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<void> {
|
|
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<void> {
|
|
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);
|