- 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.
374 lines
16 KiB
Java
374 lines
16 KiB
Java
package io.synor.examples;
|
|
|
|
import io.synor.ibc.*;
|
|
import io.synor.ibc.types.*;
|
|
|
|
import java.time.Duration;
|
|
import java.time.Instant;
|
|
import java.util.List;
|
|
import java.util.concurrent.CompletableFuture;
|
|
|
|
/**
|
|
* Synor IBC SDK Examples for Java
|
|
*
|
|
* Demonstrates Inter-Blockchain Communication operations:
|
|
* - Cross-chain transfers and messages
|
|
* - Channel lifecycle management
|
|
* - Packet handling and acknowledgments
|
|
* - Relayer operations
|
|
* - Connection monitoring
|
|
*/
|
|
public class IbcExample {
|
|
|
|
public static void main(String[] args) throws Exception {
|
|
// Initialize client
|
|
IbcConfig config = IbcConfig.builder()
|
|
.apiKey(System.getenv("SYNOR_API_KEY") != null ?
|
|
System.getenv("SYNOR_API_KEY") : "your-api-key")
|
|
.endpoint("https://ibc.synor.io/v1")
|
|
.timeout(30000)
|
|
.retries(3)
|
|
.debug(false)
|
|
.defaultChain("synor-mainnet-1")
|
|
.confirmations(1)
|
|
.build();
|
|
|
|
SynorIbc ibc = new SynorIbc(config);
|
|
|
|
try {
|
|
// Check service health
|
|
boolean healthy = ibc.healthCheck().get();
|
|
System.out.println("Service healthy: " + healthy + "\n");
|
|
|
|
// Run examples
|
|
chainsExample(ibc);
|
|
channelsExample(ibc);
|
|
transferExample(ibc);
|
|
packetExample(ibc);
|
|
relayerExample(ibc);
|
|
monitoringExample(ibc);
|
|
} finally {
|
|
ibc.close();
|
|
}
|
|
}
|
|
|
|
static void chainsExample(SynorIbc ibc) throws Exception {
|
|
System.out.println("=== Chain Discovery ===");
|
|
|
|
// Get all connected chains
|
|
List<Chain> chains = ibc.chains().list().get();
|
|
System.out.println("Connected chains: " + chains.size());
|
|
|
|
for (Chain chain : chains.subList(0, Math.min(5, chains.size()))) {
|
|
System.out.println("\n " + chain.getChainId() + ":");
|
|
System.out.println(" Name: " + chain.getName());
|
|
System.out.println(" Type: " + chain.getChainType());
|
|
System.out.println(" Status: " + chain.getStatus());
|
|
System.out.println(" Block height: " + chain.getLatestHeight());
|
|
System.out.println(" Light client: " + chain.getLightClient());
|
|
}
|
|
|
|
// Get specific chain info
|
|
Chain synorChain = ibc.chains().get("synor-mainnet-1").get();
|
|
System.out.println("\nSynor chain details:");
|
|
System.out.println(" Bech32 prefix: " + synorChain.getBech32Prefix());
|
|
System.out.println(" Gas price: " + synorChain.getGasPrice());
|
|
System.out.println(" Supported features: " + String.join(", ", synorChain.getFeatures()));
|
|
|
|
// Get chain connections
|
|
List<Connection> connections = ibc.chains().getConnections("synor-mainnet-1").get();
|
|
System.out.println("\nChain connections: " + connections.size());
|
|
for (Connection conn : connections.subList(0, Math.min(3, connections.size()))) {
|
|
System.out.println(" " + conn.getConnectionId() + " -> " + conn.getCounterpartyChainId());
|
|
}
|
|
|
|
System.out.println();
|
|
}
|
|
|
|
static void channelsExample(SynorIbc ibc) throws Exception {
|
|
System.out.println("=== Channel Management ===");
|
|
|
|
// List existing channels
|
|
List<Channel> channels = ibc.channels().list().get();
|
|
System.out.println("Active channels: " + channels.size());
|
|
|
|
for (Channel channel : channels.subList(0, Math.min(3, channels.size()))) {
|
|
System.out.println("\n Channel " + channel.getChannelId() + ":");
|
|
System.out.println(" Port: " + channel.getPortId());
|
|
System.out.println(" State: " + channel.getState());
|
|
System.out.println(" Order: " + channel.getOrdering());
|
|
System.out.println(" Counterparty: " + channel.getCounterpartyChannelId() +
|
|
" on " + channel.getCounterpartyChainId());
|
|
System.out.println(" Version: " + channel.getVersion());
|
|
}
|
|
|
|
// Create a new channel (4-step handshake)
|
|
System.out.println("\nInitiating channel creation...");
|
|
|
|
// Step 1: ChanOpenInit
|
|
ChannelInitResult initResult = ibc.channels().openInit(ChannelInitRequest.builder()
|
|
.portId("transfer")
|
|
.counterpartyChainId("cosmos-hub-4")
|
|
.counterpartyPortId("transfer")
|
|
.version("ics20-1")
|
|
.ordering(ChannelOrdering.UNORDERED)
|
|
.build()).get();
|
|
|
|
System.out.println("Channel init:");
|
|
System.out.println(" Channel ID: " + initResult.getChannelId());
|
|
System.out.println(" State: " + initResult.getState());
|
|
System.out.println(" TX hash: " + initResult.getTxHash());
|
|
|
|
// Step 2: Wait for ChanOpenTry (counterparty)
|
|
System.out.println("\nWaiting for counterparty ChanOpenTry...");
|
|
ChannelState tryState = ibc.channels().waitForState(
|
|
initResult.getChannelId(),
|
|
ChannelState.TRYOPEN,
|
|
Duration.ofMinutes(5)
|
|
).get();
|
|
System.out.println("Channel state: " + tryState);
|
|
|
|
// Step 3: ChanOpenAck
|
|
System.out.println("\nSending ChanOpenAck...");
|
|
ChannelAckResult ackResult = ibc.channels().openAck(ChannelAckRequest.builder()
|
|
.channelId(initResult.getChannelId())
|
|
.counterpartyChannelId("channel-0")
|
|
.counterpartyVersion("ics20-1")
|
|
.build()).get();
|
|
System.out.println("Ack TX: " + ackResult.getTxHash());
|
|
|
|
// Step 4: Wait for ChanOpenConfirm (counterparty)
|
|
System.out.println("\nWaiting for channel to open...");
|
|
ChannelState openState = ibc.channels().waitForState(
|
|
initResult.getChannelId(),
|
|
ChannelState.OPEN,
|
|
Duration.ofMinutes(5)
|
|
).get();
|
|
System.out.println("Channel is now: " + openState);
|
|
|
|
// Get channel details
|
|
Channel channel = ibc.channels().get(initResult.getChannelId()).get();
|
|
System.out.println("\nChannel details:");
|
|
System.out.println(" Sequences - Send: " + channel.getNextSequenceSend() +
|
|
", Recv: " + channel.getNextSequenceRecv() +
|
|
", Ack: " + channel.getNextSequenceAck());
|
|
|
|
System.out.println();
|
|
}
|
|
|
|
static void transferExample(SynorIbc ibc) throws Exception {
|
|
System.out.println("=== Cross-Chain Transfers ===");
|
|
|
|
// Get supported tokens for transfer
|
|
List<TransferableToken> tokens = ibc.transfers().getSupportedTokens("cosmos-hub-4").get();
|
|
System.out.println("Transferable tokens to Cosmos Hub:");
|
|
for (TransferableToken token : tokens.subList(0, Math.min(5, tokens.size()))) {
|
|
System.out.println(" " + token.getSymbol() + " (" + token.getDenom() + ")");
|
|
}
|
|
|
|
// Initiate a cross-chain transfer
|
|
System.out.println("\nInitiating transfer...");
|
|
TransferResult transfer = ibc.transfers().send(TransferRequest.builder()
|
|
.sourceChannel("channel-0")
|
|
.denom("usynor")
|
|
.amount("1000000")
|
|
.receiver("cosmos1...")
|
|
.timeoutHeight(0) // Use timestamp instead
|
|
.timeoutTimestamp(Instant.now().plusSeconds(600).toEpochMilli() * 1_000_000L)
|
|
.memo("IBC transfer from Synor")
|
|
.build()).get();
|
|
|
|
System.out.println("Transfer initiated:");
|
|
System.out.println(" TX hash: " + transfer.getTxHash());
|
|
System.out.println(" Sequence: " + transfer.getSequence());
|
|
System.out.println(" Packet ID: " + transfer.getPacketId());
|
|
System.out.println(" Status: " + transfer.getStatus());
|
|
|
|
// Track transfer progress
|
|
System.out.println("\nTracking transfer...");
|
|
TransferStatus status = ibc.transfers().track(transfer.getPacketId()).get();
|
|
System.out.println("Current status: " + status.getState());
|
|
System.out.println("Source TX: " + status.getSourceTxHash());
|
|
if (status.getDestTxHash() != null) {
|
|
System.out.println("Dest TX: " + status.getDestTxHash());
|
|
}
|
|
|
|
// Wait for completion
|
|
System.out.println("\nWaiting for transfer completion...");
|
|
TransferStatus finalStatus = ibc.transfers().waitForCompletion(
|
|
transfer.getPacketId(),
|
|
Duration.ofMinutes(10)
|
|
).get();
|
|
|
|
System.out.println("Transfer completed:");
|
|
System.out.println(" Final status: " + finalStatus.getState());
|
|
System.out.println(" Acknowledgment: " + finalStatus.getAcknowledgment());
|
|
|
|
// Get transfer history
|
|
List<Transfer> history = ibc.transfers().getHistory(10).get();
|
|
System.out.println("\nRecent transfers: " + history.size());
|
|
for (Transfer t : history.subList(0, Math.min(3, history.size()))) {
|
|
System.out.println(" " + t.getAmount() + " " + t.getDenom() +
|
|
" -> " + t.getDestChain() + " (" + t.getStatus() + ")");
|
|
}
|
|
|
|
System.out.println();
|
|
}
|
|
|
|
static void packetExample(SynorIbc ibc) throws Exception {
|
|
System.out.println("=== Packet Operations ===");
|
|
|
|
// List pending packets
|
|
List<Packet> pending = ibc.packets().listPending("channel-0").get();
|
|
System.out.println("Pending packets on channel-0: " + pending.size());
|
|
|
|
for (Packet packet : pending.subList(0, Math.min(3, pending.size()))) {
|
|
System.out.println("\n Packet #" + packet.getSequence() + ":");
|
|
System.out.println(" Source: " + packet.getSourcePort() + "/" + packet.getSourceChannel());
|
|
System.out.println(" Dest: " + packet.getDestPort() + "/" + packet.getDestChannel());
|
|
System.out.println(" State: " + packet.getState());
|
|
System.out.println(" Timeout: " + packet.getTimeoutTimestamp());
|
|
}
|
|
|
|
// Get specific packet
|
|
Packet packet = ibc.packets().get("channel-0", 1).get();
|
|
System.out.println("\nPacket details:");
|
|
System.out.println(" Data (hex): " + packet.getDataHex().substring(0, 40) + "...");
|
|
System.out.println(" Created: " + packet.getCreatedAt());
|
|
|
|
// Get packet commitment proof
|
|
PacketProof proof = ibc.packets().getCommitmentProof("channel-0", 1).get();
|
|
System.out.println("\nCommitment proof:");
|
|
System.out.println(" Height: " + proof.getProofHeight());
|
|
System.out.println(" Proof size: " + proof.getProof().length + " bytes");
|
|
|
|
// Get acknowledgment
|
|
PacketAck ack = ibc.packets().getAcknowledgment("channel-0", 1).get();
|
|
System.out.println("\nAcknowledgment:");
|
|
System.out.println(" Result: " + (ack.isSuccess() ? "Success" : "Error: " + ack.getError()));
|
|
System.out.println(" TX hash: " + ack.getTxHash());
|
|
|
|
// List timed-out packets
|
|
List<Packet> timedOut = ibc.packets().listTimedOut().get();
|
|
System.out.println("\nTimed-out packets: " + timedOut.size());
|
|
|
|
// Timeout a packet manually
|
|
if (!timedOut.isEmpty()) {
|
|
Packet toTimeout = timedOut.get(0);
|
|
System.out.println("\nProcessing timeout for packet #" + toTimeout.getSequence());
|
|
TimeoutResult timeout = ibc.packets().timeout(
|
|
toTimeout.getSourceChannel(),
|
|
toTimeout.getSequence()
|
|
).get();
|
|
System.out.println("Timeout TX: " + timeout.getTxHash());
|
|
}
|
|
|
|
System.out.println();
|
|
}
|
|
|
|
static void relayerExample(SynorIbc ibc) throws Exception {
|
|
System.out.println("=== Relayer Operations ===");
|
|
|
|
// Get relayer status
|
|
RelayerStatus status = ibc.relayer().getStatus().get();
|
|
System.out.println("Relayer status:");
|
|
System.out.println(" Running: " + status.isRunning());
|
|
System.out.println(" Uptime: " + status.getUptime());
|
|
System.out.println(" Packets relayed: " + status.getPacketsRelayed());
|
|
System.out.println(" Errors: " + status.getErrorCount());
|
|
|
|
// List active paths
|
|
List<RelayPath> paths = ibc.relayer().listPaths().get();
|
|
System.out.println("\nActive relay paths: " + paths.size());
|
|
|
|
for (RelayPath path : paths) {
|
|
System.out.println("\n " + path.getPathId() + ":");
|
|
System.out.println(" " + path.getSourceChain() + " <-> " + path.getDestChain());
|
|
System.out.println(" Channel: " + path.getSourceChannel() + " <-> " + path.getDestChannel());
|
|
System.out.println(" Status: " + path.getStatus());
|
|
System.out.println(" Pending packets: " + path.getPendingPackets());
|
|
}
|
|
|
|
// Configure a new path
|
|
System.out.println("\nConfiguring new relay path...");
|
|
RelayPath newPath = ibc.relayer().addPath(PathConfig.builder()
|
|
.sourceChain("synor-mainnet-1")
|
|
.destChain("osmosis-1")
|
|
.sourceChannel("channel-1")
|
|
.destChannel("channel-100")
|
|
.filterDenoms(List.of("usynor", "uosmo"))
|
|
.minRelayAmount("1000")
|
|
.maxRelayAmount("1000000000")
|
|
.build()).get();
|
|
|
|
System.out.println("Path created: " + newPath.getPathId());
|
|
|
|
// Start relaying on path
|
|
System.out.println("\nStarting relayer on path...");
|
|
ibc.relayer().startPath(newPath.getPathId()).get();
|
|
System.out.println("Relayer started");
|
|
|
|
// Manually relay pending packets
|
|
System.out.println("\nRelaying pending packets...");
|
|
RelayResult relayResult = ibc.relayer().relayPending(newPath.getPathId()).get();
|
|
System.out.println("Relayed " + relayResult.getPacketCount() + " packets");
|
|
System.out.println("TX hashes: " + relayResult.getTxHashes().size());
|
|
|
|
// Get relay history
|
|
List<RelayEvent> history = ibc.relayer().getHistory(newPath.getPathId(), 10).get();
|
|
System.out.println("\nRelay history:");
|
|
for (RelayEvent event : history.subList(0, Math.min(3, history.size()))) {
|
|
System.out.println(" " + event.getTimestamp() + ": " +
|
|
event.getEventType() + " - " + event.getPacketCount() + " packets");
|
|
}
|
|
|
|
System.out.println();
|
|
}
|
|
|
|
static void monitoringExample(SynorIbc ibc) throws Exception {
|
|
System.out.println("=== IBC Monitoring ===");
|
|
|
|
// Get IBC metrics
|
|
IbcMetrics metrics = ibc.monitoring().getMetrics().get();
|
|
System.out.println("IBC metrics:");
|
|
System.out.println(" Total channels: " + metrics.getTotalChannels());
|
|
System.out.println(" Active channels: " + metrics.getActiveChannels());
|
|
System.out.println(" Total packets: " + metrics.getTotalPackets());
|
|
System.out.println(" Pending packets: " + metrics.getPendingPackets());
|
|
System.out.println(" Failed packets: " + metrics.getFailedPackets());
|
|
System.out.println(" Avg relay time: " + metrics.getAvgRelayTime() + "ms");
|
|
|
|
// Get chain health
|
|
List<ChainHealth> chainHealth = ibc.monitoring().getChainHealth().get();
|
|
System.out.println("\nChain health:");
|
|
for (ChainHealth health : chainHealth.subList(0, Math.min(3, chainHealth.size()))) {
|
|
System.out.println(" " + health.getChainId() + ":");
|
|
System.out.println(" Status: " + health.getStatus());
|
|
System.out.println(" Block lag: " + health.getBlockLag());
|
|
System.out.println(" Last update: " + health.getLastUpdate());
|
|
}
|
|
|
|
// Get channel statistics
|
|
ChannelStats stats = ibc.monitoring().getChannelStats("channel-0").get();
|
|
System.out.println("\nChannel-0 statistics:");
|
|
System.out.println(" Packets sent: " + stats.getPacketsSent());
|
|
System.out.println(" Packets received: " + stats.getPacketsReceived());
|
|
System.out.println(" Success rate: " + stats.getSuccessRate() + "%");
|
|
System.out.println(" Avg confirmation time: " + stats.getAvgConfirmationTime() + "ms");
|
|
|
|
// Subscribe to IBC events
|
|
System.out.println("\nSubscribing to IBC events...");
|
|
ibc.monitoring().subscribe(event -> {
|
|
System.out.println("Event: " + event.getType() + " on " + event.getChannelId());
|
|
}).get();
|
|
|
|
// Get alerts
|
|
List<IbcAlert> alerts = ibc.monitoring().getAlerts().get();
|
|
System.out.println("\nActive alerts: " + alerts.size());
|
|
for (IbcAlert alert : alerts) {
|
|
System.out.println(" [" + alert.getSeverity() + "] " + alert.getMessage());
|
|
}
|
|
|
|
System.out.println();
|
|
}
|
|
}
|