diff --git a/CHANGELOG.md b/CHANGELOG.md index 85ba806..df3a681 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,9 @@ # Changelog +## 1.1.0 +CHAIN UPGRADE +* [\#88](https://github.com/binance-chain/java-sdk/pull/88) [RPC] [API] enable side chain governance transaction +* [\#89](https://github.com/binance-chain/java-sdk/pull/89) [RPC] [API] enable side chain unbind transaction, and modify the structure of claimMsg + ## 1.0.7 CHAIN UPGRADE * [\#86](https://github.com/binance-chain/java-sdk/pull/86) [RPC] [API] Add Pending match flag to Depth API response diff --git a/README.md b/README.md index 65b56a1..cb8f17f 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,8 @@ The Binance Chain Java SDK works as a lightweight Java library for interacting w * **[client](https://github.com/binance-chain/java-sdk/tree/master/src/main/java/com/binance/dex/api/client/impl)** - implementations of API rest client, supporting synchronous and asynchronous access to Binance Chain's REST APIs. * **[wallet](https://github.com/binance-chain/java-sdk/blob/master/src/main/java/com/binance/dex/api/client/Wallet.java)** - management of accounts, including seed and encrypted mnemonic generation. +## Disclaimer +**This branch is under active development, all subject to potential future change without notification and not ready for production use. The code and security audit have not been fully completed and not ready for any bug bounty.** # Installation @@ -17,7 +19,7 @@ The Binance Chain Java SDK works as a lightweight Java library for interacting w com.binance.dex.api binance-dex-api-client - 1.0.7 + 1.1.0 ``` # Protobuf diff --git a/pom.xml b/pom.xml index d5616d3..60bdb1d 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.binance.dex.api binance-dex-api-client - 1.0.7 + 1.1.0-SNAPSHOT 2.6.0 @@ -102,6 +102,28 @@ javax.annotation-api 1.3.2 + + + + org.ethereum + ethereumj-core + 1.12.0-RELEASE + + + org.ethereum + rocksdbjni + + + org.ethereum + solcJ-all + + + org.iq80.leveldb + leveldb + + + + @@ -139,5 +161,40 @@ + + + + + dev + + + bijie-releases + Internal Releases + http://nexus.k8s.qa1fdg.net/repository/maven-releases + + + bijie-snapshots + Internal Releases + http://nexus.k8s.qa1fdg.net/repository/maven-snapshots + + + + + + server + + + bijie-releases + Internal Releases + http://10.99.41.221:8081/repository/maven-releases + + + bijie-snapshots + Internal Releases + http://10.99.41.221:8081/repository/maven-snapshots + + + + \ No newline at end of file diff --git a/src/main/java/com/binance/dex/api/client/BinanceDexApiClientFactory.java b/src/main/java/com/binance/dex/api/client/BinanceDexApiClientFactory.java index 523e18a..f503b55 100644 --- a/src/main/java/com/binance/dex/api/client/BinanceDexApiClientFactory.java +++ b/src/main/java/com/binance/dex/api/client/BinanceDexApiClientFactory.java @@ -26,11 +26,11 @@ public BinanceDexApiRestClient newRestClient(String baseUrl,String apiKey){ } public BinanceDexApiNodeClient newNodeRpcClient() { - return newNodeRpcClient(BinanceDexEnvironment.PROD.getNodeUrl(), BinanceDexEnvironment.PROD.getHrp()); + return newNodeRpcClient(BinanceDexEnvironment.PROD.getNodeUrl(), BinanceDexEnvironment.PROD.getHrp(), BinanceDexEnvironment.PROD.getValHrp()); } - public BinanceDexApiNodeClient newNodeRpcClient(String baseUrl, String hrp) { - return new BinanceDexApiNodeClientImpl(baseUrl, hrp); + public BinanceDexApiNodeClient newNodeRpcClient(String baseUrl, String hrp, String valHrp) { + return new BinanceDexApiNodeClientImpl(baseUrl, hrp, valHrp); } public BinanceDexApiAsyncRestClient newAsyncRestClient() { diff --git a/src/main/java/com/binance/dex/api/client/BinanceDexApiNodeClient.java b/src/main/java/com/binance/dex/api/client/BinanceDexApiNodeClient.java index be20e33..4829ee0 100644 --- a/src/main/java/com/binance/dex/api/client/BinanceDexApiNodeClient.java +++ b/src/main/java/com/binance/dex/api/client/BinanceDexApiNodeClient.java @@ -1,13 +1,18 @@ package com.binance.dex.api.client; import com.binance.dex.api.client.domain.*; +import com.binance.dex.api.client.domain.bridge.TransferIn; import com.binance.dex.api.client.domain.broadcast.*; import com.binance.dex.api.client.domain.broadcast.Transaction; +import com.binance.dex.api.client.domain.oracle.Prophecy; import com.binance.dex.api.client.domain.request.ClosedOrdersRequest; import com.binance.dex.api.client.domain.request.OpenOrdersRequest; import com.binance.dex.api.client.domain.request.TradesRequest; import com.binance.dex.api.client.domain.request.TransactionsRequest; +import com.binance.dex.api.client.domain.stake.Pool; +import com.binance.dex.api.client.domain.stake.sidechain.*; +import javax.annotation.Nullable; import java.io.IOException; import java.security.NoSuchAlgorithmException; import java.util.List; @@ -28,6 +33,8 @@ public interface BinanceDexApiNodeClient extends BinanceDexApiRestClient { Proposal getProposalById(String proposalId); + Proposal getSideProposalById(String proposalId, String sideChainId); + Account getCommittedAccount(String address); AtomicSwap getSwapByID(String swapID); @@ -224,4 +231,52 @@ default List freeze(TokenFreeze freeze, Wallet wallet, Tran default List unfreeze(TokenUnfreeze unfreeze, Wallet wallet, TransactionOption options, boolean sync) throws IOException, NoSuchAlgorithmException { throw new UnsupportedOperationException(); } + + List createSideChainValidator(CreateSideChainValidator createSideChainValidator, Wallet wallet, TransactionOption options, boolean sync) throws IOException, NoSuchAlgorithmException; + + List editSideChainValidator(EditSideChainValidator editSideChainValidator, Wallet wallet, TransactionOption option, boolean synv) throws IOException, NoSuchAlgorithmException ; + + List sideChainDelegate(SideChainDelegate sideChainDelegate, Wallet wallet, TransactionOption options, boolean sync) throws IOException, NoSuchAlgorithmException; + + List sideChainRedelagate(SideChainRedelegate sideChainRedelegate, Wallet wallet, TransactionOption options, boolean sync) throws IOException, NoSuchAlgorithmException; + + List sideChainUnbond(SideChainUnBond sideChainUndelegate, Wallet wallet, TransactionOption options, boolean sync) throws IOException, NoSuchAlgorithmException; + + SideChainValidator getSideChainValidator(String sideChainId, String validatorAddress) throws IOException; + + List getSideChainTopValidators(String sideChainId, int top) throws IOException ; + + SideChainDelegation getSideChainDelegation(String sideChainId, String delegatorAddress, String validatorAddress) throws IOException; + + List getSideChainDelegations(String sideChainId, String delegatorAddress) throws IOException; + + SideChainRedelegation getSideChainRedelegation(String sideChainId, String delegatorAddress, String srcValidatorAddress, String dstValidatorAddress) throws IOException; + + List getSideChainRedelegations(String sideChainId, String delegatorAddress) throws IOException; + + UnBondingDelegation getSideChainUnBondingDelegation(String sideChainId, String delegatorAddress, String validatorAddress) throws IOException; + + List getSideChainUnBondingDelegations(String sideChainId, String delegatorAddress) throws IOException; + + List getSideChainUnBondingDelegationsByValidator(String sideChainId, String validatorAddress) throws IOException ; + + List getSideChainRedelegationsByValidator(String sideChainId, String validatorAddress) throws IOException; + + Pool getSideChainPool(String sideChainId) throws IOException; + + long getAllSideChainValidatorsCount(String sideChainId, boolean jailInvolved) throws IOException; + + List claim(int chainId, byte[] payload, long sequence, Wallet wallet, TransactionOption options, boolean sync) throws IOException, NoSuchAlgorithmException; + + @Nullable + Prophecy getProphecy(int claimType, long sequence) throws IOException; + + long getCurrentSequence(int claimType); + + List transferOut(String toAddress, com.binance.dex.api.client.encoding.message.Token amount, long expireTimeInSeconds, Wallet wallet, TransactionOption options, boolean sync) throws IOException, NoSuchAlgorithmException; + + List bind(String symbol, long amount, String contractAddress, int contractDecimal, long expireTimeInSeconds, Wallet wallet, TransactionOption options, boolean sync) throws IOException, NoSuchAlgorithmException; + + List unBind(String symbol, Wallet wallet, TransactionOption options, boolean sync) throws IOException, NoSuchAlgorithmException; + } diff --git a/src/main/java/com/binance/dex/api/client/BinanceDexApiRestClient.java b/src/main/java/com/binance/dex/api/client/BinanceDexApiRestClient.java index 5f8203c..d9d97c4 100644 --- a/src/main/java/com/binance/dex/api/client/BinanceDexApiRestClient.java +++ b/src/main/java/com/binance/dex/api/client/BinanceDexApiRestClient.java @@ -91,6 +91,8 @@ List newOrder(NewOrder newOrder, Wallet wallet, Transaction List vote(Vote vote,Wallet wallet, TransactionOption options, boolean sync) throws IOException, NoSuchAlgorithmException; + List sideVote(SideVote vote,Wallet wallet, TransactionOption options, boolean sync) throws IOException, NoSuchAlgorithmException; + List cancelOrder(CancelOrder cancelOrder, Wallet wallet, TransactionOption options, boolean sync) throws IOException, NoSuchAlgorithmException; diff --git a/src/main/java/com/binance/dex/api/client/BinanceDexEnvironment.java b/src/main/java/com/binance/dex/api/client/BinanceDexEnvironment.java index 5c8c2ac..3fb1e96 100644 --- a/src/main/java/com/binance/dex/api/client/BinanceDexEnvironment.java +++ b/src/main/java/com/binance/dex/api/client/BinanceDexEnvironment.java @@ -9,14 +9,16 @@ public class BinanceDexEnvironment { "wss://dex.binance.org/api", "https://dataseed1.ninicoin.io", "wss://dataseed1.ninicoin.io/websocket", - "bnb" + "bnb", + "bva" ); public static final BinanceDexEnvironment TEST_NET = new BinanceDexEnvironment( "https://testnet-dex.binance.org", "wss://testnet-dex.binance.org/api", "http://data-seed-pre-0-s3.binance.org", "wss://data-seed-pre-0-s3.binance.org/websocket", - "tbnb" + "tbnb", + "bva" ); // Rest API base URL @@ -29,13 +31,16 @@ public class BinanceDexEnvironment { private String wsBaseUrl; // Address human readable part prefix private String hrp; + // Address human readable part prefix for validator + private String valHrp; - public BinanceDexEnvironment(String baseUrl, String streamUrl, String nodeUrl, String wsBaseUrl, String hrp) { + public BinanceDexEnvironment(String baseUrl, String streamUrl, String nodeUrl, String wsBaseUrl, String hrp, String valHrp) { this.baseUrl = baseUrl; this.streamUrl = streamUrl; this.nodeUrl = nodeUrl; this.wsBaseUrl = wsBaseUrl; this.hrp = hrp; + this.valHrp = valHrp; } public String getBaseUrl() { @@ -54,6 +59,10 @@ public String getHrp() { return hrp; } + public String getValHrp() { + return valHrp; + } + @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/src/main/java/com/binance/dex/api/client/BinanceDexNodeApi.java b/src/main/java/com/binance/dex/api/client/BinanceDexNodeApi.java index 7d5bc71..edab597 100644 --- a/src/main/java/com/binance/dex/api/client/BinanceDexNodeApi.java +++ b/src/main/java/com/binance/dex/api/client/BinanceDexNodeApi.java @@ -50,4 +50,10 @@ public interface BinanceDexNodeApi { @GET("/block_by_hash") Call> getBlock(@Query("hash") String hash); + @GET("/abci_query?height=0&prove=false") + Call> abciQuery(@Query("path") String path, @Query("data") String data); + + @GET("/abci_query") + Call> abciQueryWithOptions(@Query("path") String path, @Query("data") String data, @Query("height") long height, @Query("prove") boolean prove); + } diff --git a/src/main/java/com/binance/dex/api/client/TransactionConverter.java b/src/main/java/com/binance/dex/api/client/TransactionConverter.java index 7e7d6a2..6bce540 100644 --- a/src/main/java/com/binance/dex/api/client/TransactionConverter.java +++ b/src/main/java/com/binance/dex/api/client/TransactionConverter.java @@ -1,6 +1,10 @@ package com.binance.dex.api.client; +import com.binance.dex.api.client.crosschain.Package; import com.binance.dex.api.client.domain.*; +import com.binance.dex.api.client.domain.bridge.Bind; +import com.binance.dex.api.client.domain.bridge.TransferOut; +import com.binance.dex.api.client.domain.bridge.Unbind; import com.binance.dex.api.client.domain.broadcast.*; import com.binance.dex.api.client.domain.broadcast.Burn; import com.binance.dex.api.client.domain.broadcast.CancelOrder; @@ -13,6 +17,9 @@ import com.binance.dex.api.client.domain.broadcast.Mint; import com.binance.dex.api.client.domain.broadcast.NewOrder; import com.binance.dex.api.client.domain.broadcast.SetAccountFlag; +import com.binance.dex.api.client.domain.broadcast.SideDeposit; +import com.binance.dex.api.client.domain.broadcast.SideSubmitProposal; +import com.binance.dex.api.client.domain.broadcast.SideVote; import com.binance.dex.api.client.domain.broadcast.SubmitProposal; import com.binance.dex.api.client.domain.broadcast.TinyTokenIssue; import com.binance.dex.api.client.domain.broadcast.TokenFreeze; @@ -20,10 +27,25 @@ import com.binance.dex.api.client.domain.broadcast.Transaction; import com.binance.dex.api.client.domain.broadcast.Vote; import com.binance.dex.api.client.domain.jsonrpc.TxResult; +import com.binance.dex.api.client.domain.oracle.ClaimMsg; +import com.binance.dex.api.client.domain.slash.BscSubmitEvidence; +import com.binance.dex.api.client.domain.slash.SideChainUnJail; +import com.binance.dex.api.client.domain.stake.Commission; +import com.binance.dex.api.client.domain.stake.Description; +import com.binance.dex.api.client.domain.stake.sidechain.*; +import com.binance.dex.api.client.encoding.ByteUtil; import com.binance.dex.api.client.encoding.Crypto; +import com.binance.dex.api.client.encoding.EncodeUtils; +import com.binance.dex.api.client.encoding.amino.Amino; import com.binance.dex.api.client.encoding.message.InputOutput; import com.binance.dex.api.client.encoding.message.MessageType; import com.binance.dex.api.client.encoding.message.Token; +import com.binance.dex.api.client.encoding.message.bridge.BindMsgMessage; +import com.binance.dex.api.client.encoding.message.bridge.ClaimMsgMessage; +import com.binance.dex.api.client.encoding.message.bridge.TransferOutMsgMessage; +import com.binance.dex.api.client.encoding.message.bridge.UnbindMsgMessage; +import com.binance.dex.api.client.encoding.message.sidechain.transaction.*; +import com.binance.dex.api.client.rlp.Decoder; import com.binance.dex.api.proto.*; import com.binance.dex.api.proto.TimeLock; import com.binance.dex.api.proto.TimeRelock; @@ -31,6 +53,7 @@ import com.google.protobuf.InvalidProtocolBufferException; import org.bouncycastle.util.encoders.Hex; +import java.io.IOException; import java.time.Instant; import java.util.*; import java.util.List; @@ -40,8 +63,13 @@ public class TransactionConverter { private String hrp; - public TransactionConverter(String hrp) { + private String valHrp; + + private final Amino amino = new Amino(); + + public TransactionConverter(String hrp, String valHrp) { this.hrp = hrp; + this.valHrp = valHrp; } public List convert(com.binance.dex.api.client.domain.jsonrpc.BlockInfoResult.Transaction txMessage) { @@ -135,6 +163,8 @@ public Transaction convert(byte[] bytes) { return convertTokenUnfreeze(bytes); case Vote: return convertVote(bytes); + case SideVote: + return convertSideVote(bytes); case Issue: return convertIssue(bytes); case Burn: @@ -143,8 +173,12 @@ public Transaction convert(byte[] bytes) { return convertMint(bytes); case SubmitProposal: return convertSubmitProposal(bytes); + case SideSubmitProposal: + return convertSideSubmitProposal(bytes); case Deposit: return convertDeposit(bytes); + case SideDeposit: + return convertSideDeposit(bytes); case CreateValidator: return convertCreateValidator(bytes); case RemoveValidator: @@ -167,6 +201,29 @@ public Transaction convert(byte[] bytes) { return convertClaimHashTimerLock(bytes); case RefundHashTimerLockMsg: return convertRefundHashTimerLock(bytes); + case CreateSideChainValidator: + return convertCreateSideChainValidator(bytes); + case EditSideChainValidator: + return convertEditSideChainValidator(bytes); + case SideChainDelegate: + return convertSideChainDelegate(bytes); + case SideChainRedelegate: + return convertSideChainRedelegate(bytes); + case SideChainUndelegate: + return convertSideChainUnBond(bytes); + case Claim: + //transfer in, update transfer out, update bind + return convertClaimMsg(bytes); + case TransferOut: + return convertTransferOutMsg(bytes); + case Bind: + return convertBindMsg(bytes); + case UnBind: + return convertUnBindMsg(bytes); + case BscSubmitEvidence: + return convertBscSubmitEvidence(bytes); + case SideChainUnJail: + return convertSideChainUnJail(bytes); case TinyTokenIssue: return convertTinyTokenIssue(bytes); case MiniTokenIssue: @@ -175,7 +232,6 @@ public Transaction convert(byte[] bytes) { return convertMiniTokenSetURI(bytes); case MiniTokenList: return convertMiniTokenList(bytes); - } return null; } catch (Exception e) { @@ -183,6 +239,344 @@ public Transaction convert(byte[] bytes) { } } + private Transaction convertSideChainUnJail(byte[] value) throws IOException { + byte[] raw = ByteUtil.cut(value, 4); + SideChainUnJailMsg message = SideChainUnJailMsg.parseFrom(raw); + + SideChainUnJail unJail = new SideChainUnJail(); + unJail.setSideChainId(message.getSideChainId()); + unJail.setValidatorAddr(Crypto.encodeAddress(valHrp, message.getAddress().toByteArray())); + + Transaction transaction = new Transaction(); + transaction.setTxType(TxType.SIDECHAIN_UNJAIL); + transaction.setRealTx(unJail); + return transaction; + } + + private Transaction convertBscSubmitEvidence(byte[] value) throws IOException { + byte[] raw = ByteUtil.cut(value, 4); + SubmitEvidenceMsg message = SubmitEvidenceMsg.parseFrom(raw); + + BscSubmitEvidence bscSubmitEvidence = new BscSubmitEvidence(); + if (message.getSubmitter() != null && raw != null) { + bscSubmitEvidence.setSubmitter(Crypto.encodeAddress(hrp, message.getSubmitter().toByteArray())); + } + + List headers = message.getHeadersList(); + if (headers != null && headers.size() > 0) { + com.binance.dex.api.client.domain.slash.BscHeader[] bscHeaders = new com.binance.dex.api.client.domain.slash.BscHeader[headers.size()]; + com.binance.dex.api.client.domain.slash.BscHeader bscHeader; + for (int i = 0; i < headers.size(); i++) { + bscHeader = new com.binance.dex.api.client.domain.slash.BscHeader(); + bscHeader.setParentHash(headers.get(i).getParentHash().toByteArray()); + bscHeader.setSha3Uncles(headers.get(i).getSha3Uncles().toByteArray()); + bscHeader.setMiner(headers.get(i).getMiner().toByteArray()); + bscHeader.setStateRoot(headers.get(i).getStateRoot().toByteArray()); + bscHeader.setTransactionsRoot(headers.get(i).getTransactionsRoot().toByteArray()); + bscHeader.setReceiptsRoot(headers.get(i).getReceiptsRoot().toByteArray()); + bscHeader.setLogsBloom(headers.get(i).getLogsBloom().toByteArray()); + bscHeader.setDifficulty(headers.get(i).getDifficulty()); + bscHeader.setNumber(headers.get(i).getNumber()); + bscHeader.setGasLimit(headers.get(i).getGasLimit()); + bscHeader.setGasUsed(headers.get(i).getGasUsed()); + bscHeader.setTimestamp(headers.get(i).getTimestamp()); + bscHeader.setExtra(headers.get(i).getExtraData().toByteArray()); + bscHeader.setMixHash(headers.get(i).getMixHash().toByteArray()); + bscHeader.setNonce(headers.get(i).getNonce().toByteArray()); + bscHeaders[i] = bscHeader; + } + bscSubmitEvidence.setHeaders(bscHeaders); + } + + Transaction transaction = new Transaction(); + transaction.setTxType(TxType.BSC_SUBMIT_EVIDENCE); + transaction.setRealTx(bscSubmitEvidence); + return transaction; + } + + private Transaction convertBindMsg(byte[] value) throws IOException { + byte[] raw = ByteUtil.cut(value, 4); + BindMsgMessage message = new BindMsgMessage(); + amino.decodeBare(raw, message); + + Bind bind = new Bind(); + if (message.getFrom() != null && message.getFrom().getRaw() != null) { + bind.setFrom(Crypto.encodeAddress(hrp, message.getFrom().getRaw())); + } + bind.setSymbol(message.getSymbol()); + bind.setAmount(message.getAmount()); + if (message.getContractAddress() != null) { + bind.setContractAddress(message.getContractAddress().getAddress()); + } + bind.setContractDecimal(message.getContractDecimal()); + bind.setExpireTime(message.getExpireTime()); + + Transaction transaction = new Transaction(); + transaction.setTxType(TxType.BIND); + transaction.setRealTx(bind); + + return transaction; + } + + private Transaction convertUnBindMsg(byte[] value) throws IOException { + byte[] raw = ByteUtil.cut(value, 4); + UnbindMsgMessage message = new UnbindMsgMessage(); + amino.decodeBare(raw, message); + + Unbind bind = new Unbind(); + if (message.getFrom() != null && message.getFrom().getRaw() != null) { + bind.setFrom(Crypto.encodeAddress(hrp, message.getFrom().getRaw())); + } + bind.setSymbol(message.getSymbol()); + + + Transaction transaction = new Transaction(); + transaction.setTxType(TxType.UNBIND); + transaction.setRealTx(bind); + + return transaction; + } + + private Transaction convertTransferOutMsg(byte[] value) throws IOException { + byte[] raw = ByteUtil.cut(value, 4); + TransferOutMsgMessage message = new TransferOutMsgMessage(); + amino.decodeBare(raw, message); + + TransferOut transferOut = new TransferOut(); + if (message.getFrom() != null && message.getFrom().getRaw() != null) { + transferOut.setFrom(Crypto.encodeAddress(hrp, message.getFrom().getRaw())); + } + if (message.getToAddress() != null) { + transferOut.setToAddress(message.getToAddress().getAddress()); + } + + Token token = new Token(); + if (message.getAmount() != null) { + token.setAmount(message.getAmount().getAmount()); + token.setDenom(message.getAmount().getDenom()); + } + transferOut.setAmount(token); + + transferOut.setExpireTime(message.getExpireTime()); + + Transaction transaction = new Transaction(); + transaction.setTxType(TxType.TRANSFER_OUT); + transaction.setRealTx(transferOut); + + return transaction; + } + + private Transaction convertClaimMsg(byte[] value) throws Exception { + byte[] raw = ByteUtil.cut(value, 4); + ClaimMsgMessage message = new ClaimMsgMessage(); + amino.decodeBare(raw, message); + ClaimMsg claimMsg = new ClaimMsg(); + claimMsg.setChainId(message.getChainId()); + claimMsg.setSequence(message.getSequence()); + List packages = Decoder.decodeList(message.getPayload(), Package.class); + packages.forEach(pack -> pack.setHrp(this.hrp)); + claimMsg.setPayload(packages); + if (message.getValidatorAddress().getRaw() != null) { + claimMsg.setValidatorAddress(Crypto.encodeAddress(valHrp, message.getValidatorAddress().getRaw())); + } + Transaction transaction = new Transaction(); + transaction.setTxType(TxType.CLAIM); + transaction.setRealTx(claimMsg); + + return transaction; + } + + private Transaction convertSideChainUnBond(byte[] value) throws IOException { + byte[] raw = ByteUtil.cut(value, 4); + SideChainUndelegateMessage message = new SideChainUndelegateMessage(); + amino.decodeBare(raw, message); + + SideChainUnBond unBond = new SideChainUnBond(); + + if (message.getDelegatorAddress() != null && message.getDelegatorAddress().getRaw() != null) { + unBond.setDelegatorAddress(Crypto.encodeAddress(hrp, message.getDelegatorAddress().getRaw())); + } + + if (message.getValidatorAddress() != null && message.getValidatorAddress().getRaw() != null) { + unBond.setValidatorAddress(Crypto.encodeAddress(valHrp, message.getValidatorAddress().getRaw())); + } + + Token amount = new Token(); + if (message.getAmount() != null) { + amount.setAmount(message.getAmount().getAmount()); + amount.setDenom(message.getAmount().getDenom()); + } + unBond.setAmount(amount); + + unBond.setSideChainId(message.getSideChainId()); + + Transaction transaction = new Transaction(); + transaction.setTxType(TxType.SIDECHAIN_UNBOND); + transaction.setRealTx(unBond); + + return transaction; + } + + private Transaction convertSideChainRedelegate(byte[] value) throws IOException { + byte[] raw = ByteUtil.cut(value, 4); + SideChainRedelegateMessage message = new SideChainRedelegateMessage(); + amino.decodeBare(raw, message); + + SideChainRedelegate redelegate = new SideChainRedelegate(); + if (message.getDelegatorAddress() != null && message.getDelegatorAddress().getRaw() != null) { + redelegate.setDelegatorAddress(Crypto.encodeAddress(hrp, message.getDelegatorAddress().getRaw())); + } + + if (message.getSrcValidatorAddress() != null && message.getSrcValidatorAddress().getRaw() != null) { + redelegate.setSrcValidatorAddress(Crypto.encodeAddress(valHrp, message.getSrcValidatorAddress().getRaw())); + } + + if (message.getDstValidatorAddress() != null && message.getDstValidatorAddress().getRaw() != null) { + redelegate.setDstValidatorAddress(Crypto.encodeAddress(valHrp, message.getDstValidatorAddress().getRaw())); + } + + Token amount = new Token(); + if (message.getAmount() != null) { + amount.setAmount(message.getAmount().getAmount()); + amount.setDenom(message.getAmount().getDenom()); + } + redelegate.setAmount(amount); + + redelegate.setSideChainId(message.getSideChainId()); + + Transaction transaction = new Transaction(); + transaction.setTxType(TxType.SIDECHAIN_REDELEGATE); + transaction.setRealTx(redelegate); + + return transaction; + } + + private Transaction convertSideChainDelegate(byte[] value) throws IOException { + byte[] raw = ByteUtil.cut(value, 4); + SideChainDelegateMessage message = new SideChainDelegateMessage(); + amino.decodeBare(raw, message); + + SideChainDelegate sideChainDelegate = new SideChainDelegate(); + if (message.getDelegatorAddress() != null && message.getDelegatorAddress().getRaw() != null) { + sideChainDelegate.setDelegatorAddress(Crypto.encodeAddress(hrp, message.getDelegatorAddress().getRaw())); + } + + if (message.getValidatorAddress() != null && message.getValidatorAddress().getRaw() != null) { + sideChainDelegate.setValidatorAddress(Crypto.encodeAddress(valHrp, message.getValidatorAddress().getRaw())); + } + + Token token = new Token(); + if (message.getDelegation() != null) { + token.setDenom(message.getDelegation().getDenom()); + token.setAmount(message.getDelegation().getAmount()); + } + sideChainDelegate.setDelegation(token); + + sideChainDelegate.setSideChainId(message.getSideChainId()); + + Transaction transaction = new Transaction(); + transaction.setTxType(TxType.SIDECHAIN_DELEGATE); + transaction.setRealTx(sideChainDelegate); + + return transaction; + } + + private Transaction convertEditSideChainValidator(byte[] value) throws IOException { + byte[] raw = ByteUtil.cut(value, 4); + EditSideChainValidatorMessage message = new EditSideChainValidatorMessage(); + amino.decodeBare(raw, message); + + EditSideChainValidator editSideChainValidator = new EditSideChainValidator(); + + Description description = new Description(); + if (message.getDescription() != null) { + description.setMoniker(message.getDescription().getMoniker()); + description.setDetails(message.getDescription().getDetails()); + description.setIdentity(message.getDescription().getIdentity()); + description.setWebsite(message.getDescription().getWebsite()); + } + editSideChainValidator.setDescription(description); + + if (message.getValidatorOperatorAddress() != null && message.getValidatorOperatorAddress().getRaw() != null) { + editSideChainValidator.setValidatorAddress(Crypto.encodeAddress(valHrp, message.getValidatorOperatorAddress().getRaw())); + } + + if (message.getCommissionRate() != null) { + editSideChainValidator.setCommissionRate(message.getCommissionRate().getValue()); + } + + editSideChainValidator.setSideChainId(message.getSideChainId()); + + if (message.getSideFeeAddr() != null) { + editSideChainValidator.setSideFeeAddr("0x" + Hex.toHexString(message.getSideFeeAddr())); + } + + Transaction transaction = new Transaction(); + transaction.setTxType(TxType.EDIT_SIDECHAIN_VALIDATOR); + transaction.setRealTx(editSideChainValidator); + + return transaction; + } + + private Transaction convertCreateSideChainValidator(byte[] value) throws IOException { + byte[] raw = ByteUtil.cut(value, 4); + CreateSideChainValidatorMessage message = new CreateSideChainValidatorMessage(); + amino.decodeBare(raw, message); + + CreateSideChainValidator createSideChainValidator = new CreateSideChainValidator(); + + Description description = new Description(); + if (message.getDescription() != null) { + description.setMoniker(message.getDescription().getMoniker()); + description.setDetails(message.getDescription().getDetails()); + description.setIdentity(message.getDescription().getIdentity()); + description.setWebsite(message.getDescription().getWebsite()); + } + createSideChainValidator.setDescription(description); + + Commission commission = new Commission(); + if (message.getCommission() != null) { + try { + commission.setRate(message.getCommission().getRate().getValue()); + commission.setMaxRate(message.getCommission().getMaxRate().getValue()); + commission.setMaxChangeRate(message.getCommission().getMaxChangeRate().getValue()); + } catch (NullPointerException e) { + //ignore + } + } + createSideChainValidator.setCommission(commission); + + if (message.getDelegatorAddr() != null && message.getDelegatorAddr().getRaw() != null) { + createSideChainValidator.setDelegatorAddr(Crypto.encodeAddress(hrp, message.getDelegatorAddr().getRaw())); + } + + if (message.getValidatorOperatorAddr() != null && message.getValidatorOperatorAddr().getRaw() != null) { + createSideChainValidator.setValidatorAddr(Crypto.encodeAddress(valHrp, message.getValidatorOperatorAddr().getRaw())); + } + + Token delegation = new Token(); + if (message.getDelegation() != null) { + delegation.setAmount(message.getDelegation().getAmount()); + delegation.setDenom(message.getDelegation().getDenom()); + } + createSideChainValidator.setDelegation(delegation); + + createSideChainValidator.setSideChainId(message.getSideChainId()); + + if (message.getSideConsAddr() != null) { + createSideChainValidator.setSideConsAddr("0x" + Hex.toHexString(message.getSideConsAddr())); + } + + if (message.getSideFeeAddr() != null) { + createSideChainValidator.setSideFeeAddr("0x" + Hex.toHexString(message.getSideFeeAddr())); + } + + Transaction transaction = new Transaction(); + transaction.setTxType(TxType.CREATE_SIDECHAIN_VALIDATOR); + transaction.setRealTx(createSideChainValidator); + return transaction; + } + private Transaction convertRefundHashTimerLock(byte[] value) throws InvalidProtocolBufferException { byte[] array = new byte[value.length - 4]; @@ -439,6 +833,24 @@ protected Transaction convertVote(byte[] value) throws InvalidProtocolBufferExce return transaction; } + protected Transaction convertSideVote(byte[] value) throws InvalidProtocolBufferException { + byte[] array = new byte[value.length - 4]; + System.arraycopy(value, 4, array, 0, array.length); + com.binance.dex.api.proto.SideVote voteMessage = com.binance.dex.api.proto.SideVote.parseFrom(array); + + SideVote vote = new SideVote(); + + vote.setVoter(Crypto.encodeAddress(hrp, voteMessage.getVoter().toByteArray())); + vote.setOption((int) voteMessage.getOption()); + vote.setProposalId(voteMessage.getProposalId()); + vote.setSideChainId(voteMessage.getSideChainId()); + + Transaction transaction = new Transaction(); + transaction.setTxType(TxType.SIDE_VOTE); + transaction.setRealTx(vote); + return transaction; + } + protected Transaction convertIssue(byte[] value) throws InvalidProtocolBufferException { byte[] array = new byte[value.length - 4]; System.arraycopy(value, 4, array, 0, array.length); @@ -512,6 +924,30 @@ protected Transaction convertSubmitProposal(byte[] value) throws InvalidProtocol return transaction; } + protected Transaction convertSideSubmitProposal(byte[] value) throws InvalidProtocolBufferException { + byte[] array = new byte[value.length - 4]; + System.arraycopy(value, 4, array, 0, array.length); + com.binance.dex.api.proto.SideSubmitProposal proposalMessage = com.binance.dex.api.proto.SideSubmitProposal.parseFrom(array); + + SideSubmitProposal proposal = new SideSubmitProposal(); + proposal.setTitle(proposalMessage.getTitle()); + proposal.setDescription(proposalMessage.getDescription()); + proposal.setProposalType(ProposalType.fromValue(proposalMessage.getProposalType())); + proposal.setProposer(Crypto.encodeAddress(hrp, proposalMessage.getProposer().toByteArray())); + + if (null != proposalMessage.getInitialDepositList()) { + proposal.setInitDeposit(proposalMessage.getInitialDepositList().stream() + .map(com.binance.dex.api.client.encoding.message.Token::of).collect(Collectors.toList())); + } + proposal.setVotingPeriod(proposalMessage.getVotingPeriod()); + + Transaction transaction = new Transaction(); + transaction.setTxType(TxType.SIDE_SUBMIT_PROPOSAL); + transaction.setRealTx(proposal); + proposal.setSideChainId(proposalMessage.getSideChainId()); + return transaction; + } + private Transaction convertDeposit(byte[] value) throws InvalidProtocolBufferException { byte[] array = new byte[value.length - 4]; System.arraycopy(value, 4, array, 0, array.length); @@ -530,6 +966,25 @@ private Transaction convertDeposit(byte[] value) throws InvalidProtocolBufferExc return transaction; } + private Transaction convertSideDeposit(byte[] value) throws InvalidProtocolBufferException { + byte[] array = new byte[value.length - 4]; + System.arraycopy(value, 4, array, 0, array.length); + com.binance.dex.api.proto.SideDeposit depositMessage = com.binance.dex.api.proto.SideDeposit.parseFrom(array); + + SideDeposit deposit = new SideDeposit(); + deposit.setProposalId(depositMessage.getProposalId()); + deposit.setDepositer(Crypto.encodeAddress(hrp, depositMessage.getDepositer().toByteArray())); + if (null != depositMessage.getAmountList()) { + deposit.setAmount(depositMessage.getAmountList().stream() + .map(com.binance.dex.api.client.encoding.message.Token::of).collect(Collectors.toList())); + } + deposit.setSideChainId(depositMessage.getSideChainId()); + Transaction transaction = new Transaction(); + transaction.setTxType(TxType.SIDE_DEPOSIT); + transaction.setRealTx(deposit); + return transaction; + } + private Transaction convertCreateValidator(byte[] value) throws InvalidProtocolBufferException { byte[] array = new byte[value.length - 4]; System.arraycopy(value, 4, array, 0, array.length); diff --git a/src/main/java/com/binance/dex/api/client/crosschain/Content.java b/src/main/java/com/binance/dex/api/client/crosschain/Content.java new file mode 100644 index 0000000..ac62b29 --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/crosschain/Content.java @@ -0,0 +1,7 @@ +package com.binance.dex.api.client.crosschain; + +public abstract class Content { + + protected abstract void setHrp(String hrp); + +} diff --git a/src/main/java/com/binance/dex/api/client/crosschain/ContentEnum.java b/src/main/java/com/binance/dex/api/client/crosschain/ContentEnum.java new file mode 100644 index 0000000..9cb6ce0 --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/crosschain/ContentEnum.java @@ -0,0 +1,34 @@ +package com.binance.dex.api.client.crosschain; + +import com.binance.dex.api.client.crosschain.content.*; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; +import java.util.Optional; + +@Getter +@AllArgsConstructor +public enum ContentEnum { + ApproveBindSynPack(1, 0, ApproveBindSyn.class), + BindSynPack(1, 2, BindSyn.class), + TransferOutRefundPack(2, 1, TransferOutRefund.class), + TransferOutSynPack(2, 2, TransferOutSyn.class), + TransferInSynPack(3, 0, TransferInSyn.class), + StakingCommonAckPack(8, 1, CommonAck.class), + IbcValidatorSetPack(8, 2, IbcValidatorSet.class), + GovCommonAckPack(9, 1, CommonAck.class), + SideDowntimeSlashPack(11, 0, com.binance.dex.api.client.crosschain.content.SideDowntimeSlash.class), + ; + + private Integer channelId; + private Integer packType; + private Class clazz; + + public static Class getClass(Integer channelId, Integer packType) { + Optional optional = Arrays.stream(ContentEnum.values()) + .filter(contentEnum -> channelId.equals(contentEnum.channelId) && packType.equals(contentEnum.packType)) + .findAny(); + return optional.>map(ContentEnum::getClazz).orElse(null); + } +} diff --git a/src/main/java/com/binance/dex/api/client/crosschain/Package.java b/src/main/java/com/binance/dex/api/client/crosschain/Package.java new file mode 100644 index 0000000..9982146 --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/crosschain/Package.java @@ -0,0 +1,16 @@ +package com.binance.dex.api.client.crosschain; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class Package { + private UnsignedInt channelId; + private UnsignedLong sequence; + private Payload payload; + + public void setHrp(String hrp) { + payload.getContent().setHrp(hrp); + } +} diff --git a/src/main/java/com/binance/dex/api/client/crosschain/Payload.java b/src/main/java/com/binance/dex/api/client/crosschain/Payload.java new file mode 100644 index 0000000..97f026c --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/crosschain/Payload.java @@ -0,0 +1,44 @@ +package com.binance.dex.api.client.crosschain; + +import com.binance.dex.api.client.encoding.ByteUtil; +import com.binance.dex.api.client.rlp.Decoder; +import com.binance.dex.api.client.rlp.RlpDecodable; +import lombok.Getter; +import lombok.Setter; + +import java.math.BigInteger; + +@Getter +@Setter +public class Payload implements RlpDecodable { + + private Integer packageType; + private BigInteger crossChainFee; + private Content content; + + public Payload(){} + + @Override + public void decode(byte[] raw, Object superInstance) throws Exception { + if (raw.length < 33) { + throw new RuntimeException("Failed to code: too less length for payload"); + } + this.setPackageType((int) ByteUtil.pick(raw, 0, 1)[0]); + this.setCrossChainFee(new BigInteger(ByteUtil.pick(raw, 1, 32))); + + Integer channelId; + if (superInstance instanceof Package) { + Package pack = (Package) superInstance; + channelId = pack.getChannelId().getValue(); + } else { + throw new RuntimeException("Failed to code: superInstance's class should be Package"); + } + + Class clazz = ContentEnum.getClass(channelId, this.getPackageType()); + if (clazz == null) { + throw new RuntimeException(String.format("unknown content of channel id = %s, package type = %s", channelId, this.getPackageType())); + } + Content instance = Decoder.decodeObject(ByteUtil.cut(raw, 33), clazz); + this.setContent(instance); + } +} diff --git a/src/main/java/com/binance/dex/api/client/crosschain/TokenSymbol.java b/src/main/java/com/binance/dex/api/client/crosschain/TokenSymbol.java new file mode 100644 index 0000000..ffbe2c3 --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/crosschain/TokenSymbol.java @@ -0,0 +1,23 @@ +package com.binance.dex.api.client.crosschain; + +import com.binance.dex.api.client.encoding.ByteUtil; +import com.binance.dex.api.client.encoding.serializer.TokenSymbolSerializer; +import com.binance.dex.api.client.rlp.RlpDecodable; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@JsonSerialize(using = TokenSymbolSerializer.class) +public class TokenSymbol implements RlpDecodable { + + private byte[] raw; + private String symbol; + + @Override + public void decode(byte[] raw, Object superInstance) { + this.setRaw(raw); + this.setSymbol(new String(ByteUtil.trim(raw,(byte)0))); + } +} diff --git a/src/main/java/com/binance/dex/api/client/crosschain/UnsignedInt.java b/src/main/java/com/binance/dex/api/client/crosschain/UnsignedInt.java new file mode 100644 index 0000000..3aec1e9 --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/crosschain/UnsignedInt.java @@ -0,0 +1,13 @@ +package com.binance.dex.api.client.crosschain; + +public class UnsignedInt extends UnsignedNumber { + + public UnsignedInt(){ + super(); + } + + public int getValue(){ + return super.getNumber().intValue(); + } + +} diff --git a/src/main/java/com/binance/dex/api/client/crosschain/UnsignedLong.java b/src/main/java/com/binance/dex/api/client/crosschain/UnsignedLong.java new file mode 100644 index 0000000..20906b9 --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/crosschain/UnsignedLong.java @@ -0,0 +1,13 @@ +package com.binance.dex.api.client.crosschain; + +public class UnsignedLong extends UnsignedNumber { + + public UnsignedLong(){ + super(); + } + + public long getValue(){ + return super.getNumber().longValue(); + } + +} diff --git a/src/main/java/com/binance/dex/api/client/crosschain/UnsignedNumber.java b/src/main/java/com/binance/dex/api/client/crosschain/UnsignedNumber.java new file mode 100644 index 0000000..43d16c6 --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/crosschain/UnsignedNumber.java @@ -0,0 +1,34 @@ +package com.binance.dex.api.client.crosschain; + +import com.binance.dex.api.client.encoding.serializer.UnsignedNumberSerializer; +import com.binance.dex.api.client.rlp.RlpDecodable; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; + +import java.math.BigInteger; + +@JsonSerialize(using = UnsignedNumberSerializer.class) +public class UnsignedNumber implements RlpDecodable { + + private BigInteger value; + + public UnsignedNumber() { + this.value = BigInteger.ZERO; + } + + public UnsignedNumber(BigInteger value) { + this.value = value; + } + + @Override + public void decode(byte[] raw, Object superInstance) { + this.value = new BigInteger(1, raw); + } + + public BigInteger getNumber() { + return value; + } + + public void setValue(BigInteger value) { + this.value = value; + } +} diff --git a/src/main/java/com/binance/dex/api/client/crosschain/ValidatorSet.java b/src/main/java/com/binance/dex/api/client/crosschain/ValidatorSet.java new file mode 100644 index 0000000..6964000 --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/crosschain/ValidatorSet.java @@ -0,0 +1,30 @@ +package com.binance.dex.api.client.crosschain; + +import com.binance.dex.api.client.encoding.serializer.BytesToPrefixedHexStringSerializer; +import com.binance.dex.api.client.rlp.Decoder; +import com.binance.dex.api.client.rlp.RlpDecodable; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class ValidatorSet implements RlpDecodable { + + @JsonSerialize(using = BytesToPrefixedHexStringSerializer.class) + private byte[] sideConsAddr; + @JsonSerialize(using = BytesToPrefixedHexStringSerializer.class) + private byte[] feeAddr; + @JsonSerialize(using = BytesToPrefixedHexStringSerializer.class) + private byte[] distAddr; + private Long power; + + @Override + public void decode(byte[] raw, Object superInstance) throws Exception { + ValidatorSet vs = Decoder.decodeObject(raw, ValidatorSet.class); + this.sideConsAddr = vs.sideConsAddr; + this.feeAddr = vs.feeAddr; + this.distAddr = vs.distAddr; + this.power = vs.power; + } +} diff --git a/src/main/java/com/binance/dex/api/client/crosschain/content/ApproveBindSyn.java b/src/main/java/com/binance/dex/api/client/crosschain/content/ApproveBindSyn.java new file mode 100644 index 0000000..740e759 --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/crosschain/content/ApproveBindSyn.java @@ -0,0 +1,22 @@ +package com.binance.dex.api.client.crosschain.content; + +import com.binance.dex.api.client.crosschain.TokenSymbol; +import com.binance.dex.api.client.crosschain.Content; +import com.binance.dex.api.client.crosschain.UnsignedInt; +import lombok.Getter; +import lombok.Setter; + + +@Getter +@Setter +public class ApproveBindSyn extends Content { + + private UnsignedInt status; + + private TokenSymbol symbol; + + @Override + protected void setHrp(String hrp) { + + } +} diff --git a/src/main/java/com/binance/dex/api/client/crosschain/content/BindSyn.java b/src/main/java/com/binance/dex/api/client/crosschain/content/BindSyn.java new file mode 100644 index 0000000..0241b99 --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/crosschain/content/BindSyn.java @@ -0,0 +1,23 @@ +package com.binance.dex.api.client.crosschain.content; + +import com.binance.dex.api.client.crosschain.*; +import com.binance.dex.api.client.encoding.message.common.EthAddressValue; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class BindSyn extends Content { + + private UnsignedInt packageType; + private TokenSymbol symbol; + private EthAddressValue contractAddr; + private UnsignedNumber totalSupply; + private UnsignedNumber peggyAmount; + private UnsignedInt decimals; + private UnsignedLong expireTime; + + @Override + protected void setHrp(String hrp) { + } +} diff --git a/src/main/java/com/binance/dex/api/client/crosschain/content/CSCParamChange.java b/src/main/java/com/binance/dex/api/client/crosschain/content/CSCParamChange.java new file mode 100644 index 0000000..f95cf1a --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/crosschain/content/CSCParamChange.java @@ -0,0 +1,23 @@ +package com.binance.dex.api.client.crosschain.content; + +import com.binance.dex.api.client.crosschain.Content; +import com.binance.dex.api.client.encoding.serializer.BytesToPrefixedHexStringSerializer; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class CSCParamChange extends Content { + + private String key; + @JsonSerialize(using = BytesToPrefixedHexStringSerializer.class) + private byte[] value; + @JsonSerialize(using = BytesToPrefixedHexStringSerializer.class) + private byte[] target; + + @Override + protected void setHrp(String hrp) { + + } +} diff --git a/src/main/java/com/binance/dex/api/client/crosschain/content/CommonAck.java b/src/main/java/com/binance/dex/api/client/crosschain/content/CommonAck.java new file mode 100644 index 0000000..584a77a --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/crosschain/content/CommonAck.java @@ -0,0 +1,18 @@ +package com.binance.dex.api.client.crosschain.content; + +import com.binance.dex.api.client.crosschain.Content; +import com.binance.dex.api.client.crosschain.UnsignedInt; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class CommonAck extends Content { + + private UnsignedInt code; + + @Override + protected void setHrp(String hrp) { + + } +} diff --git a/src/main/java/com/binance/dex/api/client/crosschain/content/IbcValidatorSet.java b/src/main/java/com/binance/dex/api/client/crosschain/content/IbcValidatorSet.java new file mode 100644 index 0000000..e680430 --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/crosschain/content/IbcValidatorSet.java @@ -0,0 +1,22 @@ +package com.binance.dex.api.client.crosschain.content; + +import com.binance.dex.api.client.crosschain.Content; +import com.binance.dex.api.client.crosschain.UnsignedInt; +import com.binance.dex.api.client.crosschain.ValidatorSet; +import lombok.Getter; +import lombok.Setter; + +import java.util.List; + +@Getter +@Setter +public class IbcValidatorSet extends Content { + + private UnsignedInt type; + private List ibcValidator; + + @Override + protected void setHrp(String hrp) { + + } +} diff --git a/src/main/java/com/binance/dex/api/client/crosschain/content/SideDowntimeSlash.java b/src/main/java/com/binance/dex/api/client/crosschain/content/SideDowntimeSlash.java new file mode 100644 index 0000000..5bee5a3 --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/crosschain/content/SideDowntimeSlash.java @@ -0,0 +1,23 @@ +package com.binance.dex.api.client.crosschain.content; + +import com.binance.dex.api.client.crosschain.Content; +import com.binance.dex.api.client.crosschain.UnsignedInt; +import com.binance.dex.api.client.crosschain.UnsignedLong; +import com.binance.dex.api.client.encoding.serializer.BytesToPrefixedHexStringSerializer; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class SideDowntimeSlash extends Content { + + @JsonSerialize(using = BytesToPrefixedHexStringSerializer.class) + private byte[] sideConsAddr; + private UnsignedLong sideHeight; + private UnsignedInt sideChainId; + private UnsignedLong sideTimestamp; + + @Override + protected void setHrp(String hrp) {} +} diff --git a/src/main/java/com/binance/dex/api/client/crosschain/content/TransferInSyn.java b/src/main/java/com/binance/dex/api/client/crosschain/content/TransferInSyn.java new file mode 100644 index 0000000..8ca4a0b --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/crosschain/content/TransferInSyn.java @@ -0,0 +1,31 @@ +package com.binance.dex.api.client.crosschain.content; + +import com.binance.dex.api.client.crosschain.TokenSymbol; +import com.binance.dex.api.client.crosschain.Content; +import com.binance.dex.api.client.crosschain.UnsignedLong; +import com.binance.dex.api.client.crosschain.UnsignedNumber; +import com.binance.dex.api.client.encoding.message.common.Bech32AddressValue; +import com.binance.dex.api.client.encoding.message.common.EthAddressValue; +import lombok.Getter; +import lombok.Setter; + +import java.util.List; + +@Getter +@Setter +public class TransferInSyn extends Content { + + private TokenSymbol symbol; + private EthAddressValue contractAddress; + private List amounts; + private List receiverAddresses; + private List refundAddresses; + private UnsignedLong expireTime; + + @Override + protected void setHrp(String hrp) { + if (receiverAddresses != null) { + receiverAddresses.forEach(addr -> addr.setHrp(hrp)); + } + } +} diff --git a/src/main/java/com/binance/dex/api/client/crosschain/content/TransferOutRefund.java b/src/main/java/com/binance/dex/api/client/crosschain/content/TransferOutRefund.java new file mode 100644 index 0000000..e88ed92 --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/crosschain/content/TransferOutRefund.java @@ -0,0 +1,26 @@ +package com.binance.dex.api.client.crosschain.content; + +import com.binance.dex.api.client.crosschain.TokenSymbol; +import com.binance.dex.api.client.crosschain.Content; +import com.binance.dex.api.client.crosschain.UnsignedInt; +import com.binance.dex.api.client.crosschain.UnsignedNumber; +import com.binance.dex.api.client.encoding.message.common.Bech32AddressValue; +import lombok.Getter; +import lombok.Setter; + + +@Getter +@Setter +public class TransferOutRefund extends Content { + + private TokenSymbol symbol; + private UnsignedNumber refundAmount; + private Bech32AddressValue refundAddr; + private UnsignedInt refundReason; + + + @Override + protected void setHrp(String hrp) { + this.refundAddr.setHrp(hrp); + } +} diff --git a/src/main/java/com/binance/dex/api/client/crosschain/content/TransferOutSyn.java b/src/main/java/com/binance/dex/api/client/crosschain/content/TransferOutSyn.java new file mode 100644 index 0000000..7cc19de --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/crosschain/content/TransferOutSyn.java @@ -0,0 +1,27 @@ +package com.binance.dex.api.client.crosschain.content; + +import com.binance.dex.api.client.crosschain.TokenSymbol; +import com.binance.dex.api.client.crosschain.Content; +import com.binance.dex.api.client.crosschain.UnsignedLong; +import com.binance.dex.api.client.crosschain.UnsignedNumber; +import com.binance.dex.api.client.encoding.message.common.Bech32AddressValue; +import lombok.Getter; +import lombok.Setter; + + +@Getter +@Setter +public class TransferOutSyn extends Content { + + private TokenSymbol symbol; + private Bech32AddressValue contractAddress; + private UnsignedNumber amount; + private Bech32AddressValue recipient; + private Bech32AddressValue refundAddress; + private UnsignedLong expireTime; + + @Override + protected void setHrp(String hrp) { + this.refundAddress.setHrp(hrp); + } +} diff --git a/src/main/java/com/binance/dex/api/client/domain/ProposalType.java b/src/main/java/com/binance/dex/api/client/domain/ProposalType.java index 889179f..57b06e9 100644 --- a/src/main/java/com/binance/dex/api/client/domain/ProposalType.java +++ b/src/main/java/com/binance/dex/api/client/domain/ProposalType.java @@ -14,7 +14,9 @@ public enum ProposalType { FeeChange(5L), CreateValidator(6L), RemoveValidator(7L), - DelistTradingPair(8L); + DelistTradingPair(8L), + SideChainParamsChange(129L), + CrossSideChainParamsChange(130L); private long value; diff --git a/src/main/java/com/binance/dex/api/client/domain/bridge/Bind.java b/src/main/java/com/binance/dex/api/client/domain/bridge/Bind.java new file mode 100644 index 0000000..ee84a8e --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/domain/bridge/Bind.java @@ -0,0 +1,82 @@ +package com.binance.dex.api.client.domain.bridge; + +/** + * @author Fitz.Lu + **/ +public class Bind { + + private String from; + + private String symbol; + + private long amount; + + private String contractAddress; + + private int contractDecimal; + + private long expireTime; + + public Bind() { + } + + public String getFrom() { + return from; + } + + public void setFrom(String from) { + this.from = from; + } + + public String getSymbol() { + return symbol; + } + + public void setSymbol(String symbol) { + this.symbol = symbol; + } + + public long getAmount() { + return amount; + } + + public void setAmount(long amount) { + this.amount = amount; + } + + public String getContractAddress() { + return contractAddress; + } + + public void setContractAddress(String contractAddress) { + this.contractAddress = contractAddress; + } + + public int getContractDecimal() { + return contractDecimal; + } + + public void setContractDecimal(int contractDecimal) { + this.contractDecimal = contractDecimal; + } + + public long getExpireTime() { + return expireTime; + } + + public void setExpireTime(long expireTime) { + this.expireTime = expireTime; + } + + @Override + public String toString() { + return "Bind{" + + "from='" + from + '\'' + + ", symbol='" + symbol + '\'' + + ", amount=" + amount + + ", contractAddress='" + contractAddress + '\'' + + ", contractDecimal=" + contractDecimal + + ", expireTime=" + expireTime + + '}'; + } +} diff --git a/src/main/java/com/binance/dex/api/client/domain/bridge/TransferIn.java b/src/main/java/com/binance/dex/api/client/domain/bridge/TransferIn.java new file mode 100644 index 0000000..40dd2fe --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/domain/bridge/TransferIn.java @@ -0,0 +1,81 @@ +package com.binance.dex.api.client.domain.bridge; + +import com.binance.dex.api.client.encoding.message.Token; + +import java.util.List; + +/** + * @author Fitz.Lu + **/ +public class TransferIn { + + private String contractAddress; + + private List refundAddresses; + + private List receiverAddresses; + + private List amounts; + + private String symbol; + + private Token relayFee; + + private long expireTime; + + public String getContractAddress() { + return contractAddress; + } + + public void setContractAddress(String contractAddress) { + this.contractAddress = contractAddress; + } + + public List getRefundAddresses() { + return refundAddresses; + } + + public void setRefundAddresses(List refundAddresses) { + this.refundAddresses = refundAddresses; + } + + public List getReceiverAddresses() { + return receiverAddresses; + } + + public void setReceiverAddresses(List receiverAddresses) { + this.receiverAddresses = receiverAddresses; + } + + public List getAmounts() { + return amounts; + } + + public void setAmounts(List amounts) { + this.amounts = amounts; + } + + public String getSymbol() { + return symbol; + } + + public void setSymbol(String symbol) { + this.symbol = symbol; + } + + public Token getRelayFee() { + return relayFee; + } + + public void setRelayFee(Token relayFee) { + this.relayFee = relayFee; + } + + public long getExpireTime() { + return expireTime; + } + + public void setExpireTime(long expireTime) { + this.expireTime = expireTime; + } +} diff --git a/src/main/java/com/binance/dex/api/client/domain/bridge/TransferOut.java b/src/main/java/com/binance/dex/api/client/domain/bridge/TransferOut.java new file mode 100644 index 0000000..589d42d --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/domain/bridge/TransferOut.java @@ -0,0 +1,62 @@ +package com.binance.dex.api.client.domain.bridge; + +import com.binance.dex.api.client.encoding.message.Token; + +/** + * @author Fitz.Lu + **/ +public class TransferOut { + + private String from; + + private String toAddress; + + private Token amount; + + private long expireTime; + + public TransferOut() { + } + + public String getFrom() { + return from; + } + + public void setFrom(String from) { + this.from = from; + } + + public String getToAddress() { + return toAddress; + } + + public void setToAddress(String toAddress) { + this.toAddress = toAddress; + } + + public Token getAmount() { + return amount; + } + + public void setAmount(Token amount) { + this.amount = amount; + } + + public long getExpireTime() { + return expireTime; + } + + public void setExpireTime(long expireTime) { + this.expireTime = expireTime; + } + + @Override + public String toString() { + return "TransferOut{" + + "from='" + from + '\'' + + ", toAddress='" + toAddress + '\'' + + ", amount=" + amount + + ", expireTime=" + expireTime + + '}'; + } +} diff --git a/src/main/java/com/binance/dex/api/client/domain/bridge/Unbind.java b/src/main/java/com/binance/dex/api/client/domain/bridge/Unbind.java new file mode 100644 index 0000000..f2cff44 --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/domain/bridge/Unbind.java @@ -0,0 +1,32 @@ +package com.binance.dex.api.client.domain.bridge; + +public class Unbind { + + private String from; + + private String symbol; + + public String getFrom() { + return from; + } + + public void setFrom(String from) { + this.from = from; + } + + public String getSymbol() { + return symbol; + } + + public void setSymbol(String symbol) { + this.symbol = symbol; + } + + @Override + public String toString() { + return "UnBind{" + + "from='" + from + '\'' + + ", symbol='" + symbol + '\'' + + '}'; + } +} diff --git a/src/main/java/com/binance/dex/api/client/domain/broadcast/SideDeposit.java b/src/main/java/com/binance/dex/api/client/domain/broadcast/SideDeposit.java new file mode 100644 index 0000000..ecea7dc --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/domain/broadcast/SideDeposit.java @@ -0,0 +1,47 @@ +package com.binance.dex.api.client.domain.broadcast; + +import java.util.List; + +import com.binance.dex.api.client.encoding.message.Token; +/** + * + * Created by fletcher on 2019/5/13. + */ +public class SideDeposit { + + private Long proposalId; + private String depositer; + private List amount; + private String sideChainId; + + public String getSideChainId() { + return sideChainId; + } + + public void setSideChainId(String sideChainId) { + this.sideChainId = sideChainId; + } + public Long getProposalId() { + return proposalId; + } + + public void setProposalId(Long proposalId) { + this.proposalId = proposalId; + } + + public String getDepositer() { + return depositer; + } + + public void setDepositer(String depositer) { + this.depositer = depositer; + } + + public List getAmount() { + return amount; + } + + public void setAmount(List amount) { + this.amount = amount; + } +} diff --git a/src/main/java/com/binance/dex/api/client/domain/broadcast/SideSubmitProposal.java b/src/main/java/com/binance/dex/api/client/domain/broadcast/SideSubmitProposal.java new file mode 100644 index 0000000..919850d --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/domain/broadcast/SideSubmitProposal.java @@ -0,0 +1,85 @@ +package com.binance.dex.api.client.domain.broadcast; + +import java.util.List; + +import com.binance.dex.api.client.domain.ProposalType; +import com.binance.dex.api.client.encoding.message.Token; + +public class SideSubmitProposal { + private String title; + private String description; + private ProposalType proposalType; + private String proposer; + private List initDeposit; + private Long votingPeriod; + private String sideChainId; + + public String getSideChainId() { + return sideChainId; + } + + public void setSideChainId(String sideChainId) { + this.sideChainId = sideChainId; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public ProposalType getProposalType() { + return proposalType; + } + + public void setProposalType(ProposalType proposalType) { + this.proposalType = proposalType; + } + + public String getProposer() { + return proposer; + } + + public void setProposer(String proposer) { + this.proposer = proposer; + } + + public List getInitDeposit() { + return initDeposit; + } + + public void setInitDeposit(List initDeposit) { + this.initDeposit = initDeposit; + } + + public Long getVotingPeriod() { + return votingPeriod; + } + + public void setVotingPeriod(Long votingPeriod) { + this.votingPeriod = votingPeriod; + } + + @Override + public String toString() { + return "SubmitProposal{" + + "title='" + title + '\'' + + ", description='" + description + '\'' + + ", proposalType=" + proposalType + + ", proposer='" + proposer + '\'' + + ", initDeposit=" + initDeposit + + ", votingPeriod=" + votingPeriod + + ", sideChainId=" + sideChainId + + '}'; + } +} diff --git a/src/main/java/com/binance/dex/api/client/domain/broadcast/SideVote.java b/src/main/java/com/binance/dex/api/client/domain/broadcast/SideVote.java new file mode 100644 index 0000000..c4e36f5 --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/domain/broadcast/SideVote.java @@ -0,0 +1,54 @@ +package com.binance.dex.api.client.domain.broadcast; + +public class SideVote { + + private Long proposalId; + + private Integer option; + + private String voter; + + private String sideChainId; + + public String getSideChainId() { + return sideChainId; + } + + public void setSideChainId(String sideChainId) { + this.sideChainId = sideChainId; + } + + public Long getProposalId() { + return proposalId; + } + + public void setProposalId(Long proposalId) { + this.proposalId = proposalId; + } + + public Integer getOption() { + return option; + } + + public void setOption(Integer option) { + this.option = option; + } + + public String getVoter() { + return voter; + } + + public void setVoter(String voter) { + this.voter = voter; + } + + @Override + public String toString() { + return "Vote{" + + "proposalId=" + proposalId + + ", option=" + option + + ", sideChainId=" + sideChainId + + ", voter='" + voter + '\'' + + '}'; + } +} diff --git a/src/main/java/com/binance/dex/api/client/domain/broadcast/TxType.java b/src/main/java/com/binance/dex/api/client/domain/broadcast/TxType.java index 03107b2..e49b9fb 100644 --- a/src/main/java/com/binance/dex/api/client/domain/broadcast/TxType.java +++ b/src/main/java/com/binance/dex/api/client/domain/broadcast/TxType.java @@ -7,11 +7,14 @@ public enum TxType { UNFREEZE_TOKEN, TRANSFER, VOTE, + SIDE_VOTE, ISSUE, BURN, MINT, SUBMIT_PROPOSAL, + SIDE_SUBMIT_PROPOSAL, DEPOSIT, + SIDE_DEPOSIT, CREATE_VALIDATOR, REMOVE_VALIDATOR, LISTING, @@ -23,6 +26,17 @@ public enum TxType { CLAIM_HTL, REFUND_HTL, DEPOSIT_HTL, + CREATE_SIDECHAIN_VALIDATOR, + EDIT_SIDECHAIN_VALIDATOR, + SIDECHAIN_DELEGATE, + SIDECHAIN_REDELEGATE, + SIDECHAIN_UNBOND, + CLAIM, + TRANSFER_OUT, + BIND, + UNBIND, + BSC_SUBMIT_EVIDENCE, + SIDECHAIN_UNJAIL, TINY_TOKEN_ISSUE, MINI_TOKEN_ISSUE, MINI_TOKEN_SET_URI, diff --git a/src/main/java/com/binance/dex/api/client/domain/jsonrpc/TxResult.java b/src/main/java/com/binance/dex/api/client/domain/jsonrpc/TxResult.java index 21cc36c..6ce5c0a 100644 --- a/src/main/java/com/binance/dex/api/client/domain/jsonrpc/TxResult.java +++ b/src/main/java/com/binance/dex/api/client/domain/jsonrpc/TxResult.java @@ -74,6 +74,9 @@ public void setValue(byte[] value) { } public static class Event{ + + private String type; + private List attributes; public List getAttributes() { @@ -83,6 +86,14 @@ public List getAttributes() { public void setAttributes(List attributes) { this.attributes = attributes; } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } } public static class Attribute{ diff --git a/src/main/java/com/binance/dex/api/client/domain/oracle/ClaimMsg.java b/src/main/java/com/binance/dex/api/client/domain/oracle/ClaimMsg.java new file mode 100644 index 0000000..c7bcbf8 --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/domain/oracle/ClaimMsg.java @@ -0,0 +1,67 @@ +package com.binance.dex.api.client.domain.oracle; + +import com.binance.dex.api.client.crosschain.Package; +import com.binance.dex.api.client.encoding.EncodeUtils; +import com.fasterxml.jackson.core.JsonProcessingException; + +import java.util.List; + +/** + * @author Fitz.Lu + **/ +public class ClaimMsg { + + private int chainId; + + private long sequence; + + private List payload; + + private String validatorAddress; + + public int getChainId() { + return chainId; + } + + public void setChainId(int chainId) { + this.chainId = chainId; + } + + public long getSequence() { + return sequence; + } + + public void setSequence(long sequence) { + this.sequence = sequence; + } + + public List getPayload() { + return payload; + } + + public void setPayload(List payload) { + this.payload = payload; + } + + public String getValidatorAddress() { + return validatorAddress; + } + + public void setValidatorAddress(String validatorAddress) { + this.validatorAddress = validatorAddress; + } + + @Override + public String toString() { + try { + return "ClaimMsg{" + + "chainId=" + chainId + + ", sequence=" + sequence + + ", payload='" + EncodeUtils.toJsonStringSortKeys(payload) + '\'' + + ", validatorAddress='" + validatorAddress + '\'' + + '}'; + } catch (JsonProcessingException e) { + throw new RuntimeException("failed to encode payload", e); + } + } +} diff --git a/src/main/java/com/binance/dex/api/client/domain/oracle/Prophecy.java b/src/main/java/com/binance/dex/api/client/domain/oracle/Prophecy.java new file mode 100644 index 0000000..c7ca9f1 --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/domain/oracle/Prophecy.java @@ -0,0 +1,59 @@ +package com.binance.dex.api.client.domain.oracle; + +import java.util.Map; + +/** + * @author Fitz.Lu + **/ +public class Prophecy { + + private String id; + + private Status status; + + private Map claimValidators; + + private Map validatorClaims; + + public Prophecy() { + } + + public Prophecy(String id, Status status, Map claimValidators, Map validatorClaims) { + this.id = id; + this.status = status; + this.claimValidators = claimValidators; + this.validatorClaims = validatorClaims; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public Status getStatus() { + return status; + } + + public void setStatus(Status status) { + this.status = status; + } + + public Map getClaimValidators() { + return claimValidators; + } + + public void setClaimValidators(Map claimValidators) { + this.claimValidators = claimValidators; + } + + public Map getValidatorClaims() { + return validatorClaims; + } + + public void setValidatorClaims(Map validatorClaims) { + this.validatorClaims = validatorClaims; + } +} diff --git a/src/main/java/com/binance/dex/api/client/domain/oracle/Status.java b/src/main/java/com/binance/dex/api/client/domain/oracle/Status.java new file mode 100644 index 0000000..450e457 --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/domain/oracle/Status.java @@ -0,0 +1,35 @@ +package com.binance.dex.api.client.domain.oracle; + +/** + * @author Fitz.Lu + **/ +public class Status { + + private int text; + + private String finalClaim; + + public Status() { + } + + public Status(int text, String finalClaim) { + this.text = text; + this.finalClaim = finalClaim; + } + + public int getText() { + return text; + } + + public void setText(int text) { + this.text = text; + } + + public String getFinalClaim() { + return finalClaim; + } + + public void setFinalClaim(String finalClaim) { + this.finalClaim = finalClaim; + } +} diff --git a/src/main/java/com/binance/dex/api/client/domain/slash/BscHeader.java b/src/main/java/com/binance/dex/api/client/domain/slash/BscHeader.java new file mode 100644 index 0000000..4b8f087 --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/domain/slash/BscHeader.java @@ -0,0 +1,57 @@ +package com.binance.dex.api.client.domain.slash; + +import com.binance.dex.api.client.encoding.serializer.BytesToPrefixedHexStringSerializer; +import com.binance.dex.api.client.encoding.serializer.LongToHexStringSerializer; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class BscHeader { + + @JsonSerialize(using = BytesToPrefixedHexStringSerializer.class) + private byte[] parentHash; + + @JsonSerialize(using = BytesToPrefixedHexStringSerializer.class) + private byte[] sha3Uncles; + + @JsonSerialize(using = BytesToPrefixedHexStringSerializer.class) + private byte[] miner; + + @JsonSerialize(using = BytesToPrefixedHexStringSerializer.class) + private byte[] stateRoot; + + @JsonSerialize(using = BytesToPrefixedHexStringSerializer.class) + private byte[] transactionsRoot; + + @JsonSerialize(using = BytesToPrefixedHexStringSerializer.class) + private byte[] receiptsRoot; + + @JsonSerialize(using = BytesToPrefixedHexStringSerializer.class) + private byte[] logsBloom; + + @JsonSerialize(using = LongToHexStringSerializer.class) + private Long difficulty; + + @JsonSerialize(using = LongToHexStringSerializer.class) + private Long number; + + @JsonSerialize(using = LongToHexStringSerializer.class) + private Long gasLimit; + + @JsonSerialize(using = LongToHexStringSerializer.class) + private Long gasUsed; + + @JsonSerialize(using = LongToHexStringSerializer.class) + private Long timestamp; + + @JsonSerialize(using = BytesToPrefixedHexStringSerializer.class) + private byte[] extra; + + @JsonSerialize(using = BytesToPrefixedHexStringSerializer.class) + private byte[] mixHash; + + @JsonSerialize(using = BytesToPrefixedHexStringSerializer.class) + private byte[] nonce; +} diff --git a/src/main/java/com/binance/dex/api/client/domain/slash/BscSubmitEvidence.java b/src/main/java/com/binance/dex/api/client/domain/slash/BscSubmitEvidence.java new file mode 100644 index 0000000..02f0961 --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/domain/slash/BscSubmitEvidence.java @@ -0,0 +1,13 @@ +package com.binance.dex.api.client.domain.slash; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class BscSubmitEvidence { + + private String submitter; + + private BscHeader[] headers; +} diff --git a/src/main/java/com/binance/dex/api/client/domain/slash/SideChainUnJail.java b/src/main/java/com/binance/dex/api/client/domain/slash/SideChainUnJail.java new file mode 100644 index 0000000..89426e2 --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/domain/slash/SideChainUnJail.java @@ -0,0 +1,14 @@ +package com.binance.dex.api.client.domain.slash; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class SideChainUnJail { + + private String validatorAddr; + + private String sideChainId; + +} diff --git a/src/main/java/com/binance/dex/api/client/domain/stake/Commission.java b/src/main/java/com/binance/dex/api/client/domain/stake/Commission.java new file mode 100644 index 0000000..9b76af8 --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/domain/stake/Commission.java @@ -0,0 +1,67 @@ +package com.binance.dex.api.client.domain.stake; + +/** + * @author Fitz.Lu + **/ +public class Commission { + + private long rate; + + private long maxRate; + + private long maxChangeRate; + + private long updateTimeInMs; + + public long getRate() { + return rate; + } + + public void setRate(long rate) { + this.rate = rate; + } + + public long getMaxRate() { + return maxRate; + } + + public void setMaxRate(long maxRate) { + this.maxRate = maxRate; + } + + public long getMaxChangeRate() { + return maxChangeRate; + } + + public void setMaxChangeRate(long maxChangeRate) { + this.maxChangeRate = maxChangeRate; + } + + public long getUpdateTimeInMs() { + return updateTimeInMs; + } + + public void setUpdateTimeInMs(long updateTimeInMs) { + this.updateTimeInMs = updateTimeInMs; + } + + public Commission() { + } + + public Commission(long rate, long maxRate, long maxChangeRate, long updateTimeInMs) { + this.rate = rate; + this.maxRate = maxRate; + this.maxChangeRate = maxChangeRate; + this.updateTimeInMs = updateTimeInMs; + } + + @Override + public String toString() { + return "Commission{" + + "rate=" + rate + + ", maxRate=" + maxRate + + ", maxChangeRate=" + maxChangeRate + + ", updateTimeInMs=" + updateTimeInMs + + '}'; + } +} diff --git a/src/main/java/com/binance/dex/api/client/domain/stake/Description.java b/src/main/java/com/binance/dex/api/client/domain/stake/Description.java new file mode 100644 index 0000000..dd09ce9 --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/domain/stake/Description.java @@ -0,0 +1,71 @@ +package com.binance.dex.api.client.domain.stake; + +/** + * @author Fitz.Lu + **/ +public class Description { + + private String moniker; + + private String identity; + + private String website; + + private String details; + + public Description() { + this.moniker = ""; + this.identity = ""; + this.website = ""; + this.details = ""; + } + + public Description(String moniker, String identity, String website, String details) { + this.moniker = moniker; + this.identity = identity; + this.website = website; + this.details = details; + } + + public String getMoniker() { + return moniker; + } + + public void setMoniker(String moniker) { + this.moniker = moniker; + } + + public String getIdentity() { + return identity; + } + + public void setIdentity(String identity) { + this.identity = identity; + } + + public String getWebsite() { + return website; + } + + public void setWebsite(String website) { + this.website = website; + } + + public String getDetails() { + return details; + } + + public void setDetails(String details) { + this.details = details; + } + + @Override + public String toString() { + return "Description{" + + "moniker='" + moniker + '\'' + + ", identity='" + identity + '\'' + + ", website='" + website + '\'' + + ", details='" + details + '\'' + + '}'; + } +} diff --git a/src/main/java/com/binance/dex/api/client/domain/stake/Pool.java b/src/main/java/com/binance/dex/api/client/domain/stake/Pool.java new file mode 100644 index 0000000..9113240 --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/domain/stake/Pool.java @@ -0,0 +1,38 @@ +package com.binance.dex.api.client.domain.stake; + +/** + * @author Fitz.Lu + **/ +public class Pool { + + private long looseTokens; + + private long bondedTokens; + + public Pool() { + } + + public long getLooseTokens() { + return looseTokens; + } + + public void setLooseTokens(long looseTokens) { + this.looseTokens = looseTokens; + } + + public long getBondedTokens() { + return bondedTokens; + } + + public void setBondedTokens(long bondedTokens) { + this.bondedTokens = bondedTokens; + } + + @Override + public String toString() { + return "Pool{" + + "looseTokens=" + looseTokens + + ", bondedTokens=" + bondedTokens + + '}'; + } +} diff --git a/src/main/java/com/binance/dex/api/client/domain/stake/sidechain/CreateSideChainValidator.java b/src/main/java/com/binance/dex/api/client/domain/stake/sidechain/CreateSideChainValidator.java new file mode 100644 index 0000000..2f35a2e --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/domain/stake/sidechain/CreateSideChainValidator.java @@ -0,0 +1,108 @@ +package com.binance.dex.api.client.domain.stake.sidechain; + +import com.binance.dex.api.client.domain.stake.Commission; +import com.binance.dex.api.client.domain.stake.Description; +import com.binance.dex.api.client.encoding.message.Token; + +/** + * @author Fitz.Lu + **/ +public class CreateSideChainValidator { + + private Description description; + + private Commission commission; + + private String delegatorAddr; + + private String validatorAddr; + + private Token delegation; + + private String sideChainId; + + private String sideConsAddr; + + private String sideFeeAddr; + + public CreateSideChainValidator() { + } + + public Description getDescription() { + return description; + } + + public void setDescription(Description description) { + this.description = description; + } + + public Commission getCommission() { + return commission; + } + + public void setCommission(Commission commission) { + this.commission = commission; + } + + public String getDelegatorAddr() { + return delegatorAddr; + } + + public void setDelegatorAddr(String delegatorAddr) { + this.delegatorAddr = delegatorAddr; + } + + public Token getDelegation() { + return delegation; + } + + public void setDelegation(Token delegation) { + this.delegation = delegation; + } + + public String getSideChainId() { + return sideChainId; + } + + public void setSideChainId(String sideChainId) { + this.sideChainId = sideChainId; + } + + public String getSideConsAddr() { + return sideConsAddr; + } + + public void setSideConsAddr(String sideConsAddr) { + this.sideConsAddr = sideConsAddr; + } + + public String getSideFeeAddr() { + return sideFeeAddr; + } + + public void setSideFeeAddr(String sideFeeAddr) { + this.sideFeeAddr = sideFeeAddr; + } + + public String getValidatorAddr() { + return validatorAddr; + } + + public void setValidatorAddr(String validatorAddr) { + this.validatorAddr = validatorAddr; + } + + @Override + public String toString() { + return "CreateSideChainValidator{" + '\n' + + "description=" + description + '\n' + + ", commission=" + commission + '\n' + + ", delegatorAddr='" + delegatorAddr + '\'' + '\n' + + ", validatorAddr='" + validatorAddr + '\'' + '\n' + + ", delegation=" + delegation + '\n' + + ", sideChainId='" + sideChainId + '\'' + '\n' + + ", sideConsAddr='" + sideConsAddr + '\'' + '\n' + + ", sideFeeAddr='" + sideFeeAddr + '\'' + '\n' + + '}'; + } +} diff --git a/src/main/java/com/binance/dex/api/client/domain/stake/sidechain/Delegation.java b/src/main/java/com/binance/dex/api/client/domain/stake/sidechain/Delegation.java new file mode 100644 index 0000000..94b3ef5 --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/domain/stake/sidechain/Delegation.java @@ -0,0 +1,40 @@ +package com.binance.dex.api.client.domain.stake.sidechain; + +/** + * @author Fitz.Lu + **/ +public class Delegation { + + private String delegatorAddress; + + private String validatorAddress; + + private long shares; + + public Delegation() { + } + + public String getDelegatorAddress() { + return delegatorAddress; + } + + public void setDelegatorAddress(String delegatorAddress) { + this.delegatorAddress = delegatorAddress; + } + + public String getValidatorAddress() { + return validatorAddress; + } + + public void setValidatorAddress(String validatorAddress) { + this.validatorAddress = validatorAddress; + } + + public long getShares() { + return shares; + } + + public void setShares(long shares) { + this.shares = shares; + } +} diff --git a/src/main/java/com/binance/dex/api/client/domain/stake/sidechain/EditSideChainValidator.java b/src/main/java/com/binance/dex/api/client/domain/stake/sidechain/EditSideChainValidator.java new file mode 100644 index 0000000..f06051c --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/domain/stake/sidechain/EditSideChainValidator.java @@ -0,0 +1,73 @@ +package com.binance.dex.api.client.domain.stake.sidechain; + +import com.binance.dex.api.client.domain.stake.Description; + +/** + * @author Fitz.Lu + **/ +public class EditSideChainValidator { + + private Description description; + + private String validatorAddress; + + private long commissionRate; + + private String sideChainId; + + private String sideFeeAddr; + + public EditSideChainValidator() { + } + + public Description getDescription() { + return description; + } + + public void setDescription(Description description) { + this.description = description; + } + + public String getValidatorAddress() { + return validatorAddress; + } + + public void setValidatorAddress(String validatorAddress) { + this.validatorAddress = validatorAddress; + } + + public long getCommissionRate() { + return commissionRate; + } + + public void setCommissionRate(long commissionRate) { + this.commissionRate = commissionRate; + } + + public String getSideChainId() { + return sideChainId; + } + + public void setSideChainId(String sideChainId) { + this.sideChainId = sideChainId; + } + + public String getSideFeeAddr() { + return sideFeeAddr; + } + + public void setSideFeeAddr(String sideFeeAddr) { + this.sideFeeAddr = sideFeeAddr; + } + + @Override + public String toString() { + return "EditSideChainValidator{" + + "description=" + description + "\n" + + ", validatorAddress='" + validatorAddress + '\'' + "\n" + + ", commissionRate=" + commissionRate + "\n" + + ", sideChainId='" + sideChainId + '\'' + "\n" + + ", sideFeeAddr='" + sideFeeAddr + '\'' + "\n" + + '}'; + } +} diff --git a/src/main/java/com/binance/dex/api/client/domain/stake/sidechain/SideChainDelegate.java b/src/main/java/com/binance/dex/api/client/domain/stake/sidechain/SideChainDelegate.java new file mode 100644 index 0000000..85c8aaf --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/domain/stake/sidechain/SideChainDelegate.java @@ -0,0 +1,70 @@ +package com.binance.dex.api.client.domain.stake.sidechain; + +import com.binance.dex.api.client.encoding.message.Token; + +/** + * @author Fitz.Lu + **/ +public class SideChainDelegate { + + private String delegatorAddress; + + private String validatorAddress; + + private Token delegation; + + private String sideChainId; + + public SideChainDelegate() { + sideChainId = ""; + } + + public SideChainDelegate(String delegatorAddress, String validatorAddress, Token delegation, String sideChainId) { + this.delegatorAddress = delegatorAddress; + this.validatorAddress = validatorAddress; + this.delegation = delegation; + this.sideChainId = sideChainId; + } + + public String getDelegatorAddress() { + return delegatorAddress; + } + + public void setDelegatorAddress(String delegatorAddress) { + this.delegatorAddress = delegatorAddress; + } + + public String getValidatorAddress() { + return validatorAddress; + } + + public void setValidatorAddress(String validatorAddress) { + this.validatorAddress = validatorAddress; + } + + public Token getDelegation() { + return delegation; + } + + public void setDelegation(Token delegation) { + this.delegation = delegation; + } + + public String getSideChainId() { + return sideChainId; + } + + public void setSideChainId(String sideChainId) { + this.sideChainId = sideChainId; + } + + @Override + public String toString() { + return "SideChainDelegate{" + + "delegatorAddress='" + delegatorAddress + '\'' + + ", validatorAddress='" + validatorAddress + '\'' + + ", delegation=" + delegation + + ", sideChainId='" + sideChainId + '\'' + + '}'; + } +} diff --git a/src/main/java/com/binance/dex/api/client/domain/stake/sidechain/SideChainDelegation.java b/src/main/java/com/binance/dex/api/client/domain/stake/sidechain/SideChainDelegation.java new file mode 100644 index 0000000..9a07436 --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/domain/stake/sidechain/SideChainDelegation.java @@ -0,0 +1,37 @@ +package com.binance.dex.api.client.domain.stake.sidechain; + +import com.binance.dex.api.client.encoding.message.Token; + +/** + * @author Fitz.Lu + **/ +public class SideChainDelegation { + + private Delegation delegation; + + private Token balance; + + public SideChainDelegation() { + } + + public SideChainDelegation(Delegation delegation, Token balance) { + this.delegation = delegation; + this.balance = balance; + } + + public Delegation getDelegation() { + return delegation; + } + + public void setDelegation(Delegation delegation) { + this.delegation = delegation; + } + + public Token getBalance() { + return balance; + } + + public void setBalance(Token balance) { + this.balance = balance; + } +} diff --git a/src/main/java/com/binance/dex/api/client/domain/stake/sidechain/SideChainRedelegate.java b/src/main/java/com/binance/dex/api/client/domain/stake/sidechain/SideChainRedelegate.java new file mode 100644 index 0000000..329a7fa --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/domain/stake/sidechain/SideChainRedelegate.java @@ -0,0 +1,73 @@ +package com.binance.dex.api.client.domain.stake.sidechain; + +import com.binance.dex.api.client.encoding.message.Token; + +/** + * @author Fitz.Lu + **/ +public class SideChainRedelegate { + + private String delegatorAddress; + + private String srcValidatorAddress; + + private String dstValidatorAddress; + + private Token amount; + + private String sideChainId; + + public SideChainRedelegate() { + } + + public String getDelegatorAddress() { + return delegatorAddress; + } + + public void setDelegatorAddress(String delegatorAddress) { + this.delegatorAddress = delegatorAddress; + } + + public String getSrcValidatorAddress() { + return srcValidatorAddress; + } + + public void setSrcValidatorAddress(String srcValidatorAddress) { + this.srcValidatorAddress = srcValidatorAddress; + } + + public String getDstValidatorAddress() { + return dstValidatorAddress; + } + + public void setDstValidatorAddress(String dstValidatorAddress) { + this.dstValidatorAddress = dstValidatorAddress; + } + + public Token getAmount() { + return amount; + } + + public void setAmount(Token amount) { + this.amount = amount; + } + + public String getSideChainId() { + return sideChainId; + } + + public void setSideChainId(String sideChainId) { + this.sideChainId = sideChainId; + } + + @Override + public String toString() { + return "SideChainRedelegate{" + + "delegatorAddress='" + delegatorAddress + '\'' + + ", srcValidatorAddress='" + srcValidatorAddress + '\'' + + ", dstValidatorAddress='" + dstValidatorAddress + '\'' + + ", amount=" + amount + + ", sideChainId='" + sideChainId + '\'' + + '}'; + } +} diff --git a/src/main/java/com/binance/dex/api/client/domain/stake/sidechain/SideChainRedelegation.java b/src/main/java/com/binance/dex/api/client/domain/stake/sidechain/SideChainRedelegation.java new file mode 100644 index 0000000..94bd09e --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/domain/stake/sidechain/SideChainRedelegation.java @@ -0,0 +1,138 @@ +package com.binance.dex.api.client.domain.stake.sidechain; + + +import com.binance.dex.api.client.encoding.message.Token; + +/** + * @author Fitz.Lu + **/ +public class SideChainRedelegation { + + //delegator address + private String delegatorAddress; + + //validator redelegation source operator address + private String srcValidatorAddress; + + //validator redelegation destination operator address + private String dstValidatorAddress; + + //height which the redelegation took place + private long createHeight; + + //unix time for redelegation completion + private String minTime; + + private long minTimeInMs; + + //initial balance when redelegation started + private Token initialBalance; + + //current balance + private Token balance; + + //amount of source shares redelegating + private long srcShares; + + //amount of destination shares redelegating + private long dstShare; + + public SideChainRedelegation() { + } + + public String getDelegatorAddress() { + return delegatorAddress; + } + + public void setDelegatorAddress(String delegatorAddress) { + this.delegatorAddress = delegatorAddress; + } + + public String getSrcValidatorAddress() { + return srcValidatorAddress; + } + + public void setSrcValidatorAddress(String srcValidatorAddress) { + this.srcValidatorAddress = srcValidatorAddress; + } + + public String getDstValidatorAddress() { + return dstValidatorAddress; + } + + public void setDstValidatorAddress(String dstValidatorAddress) { + this.dstValidatorAddress = dstValidatorAddress; + } + + public long getCreateHeight() { + return createHeight; + } + + public void setCreateHeight(long createHeight) { + this.createHeight = createHeight; + } + + public String getMinTime() { + return minTime; + } + + public void setMinTime(String minTime) { + this.minTime = minTime; + } + + public long getMinTimeInMs() { + return minTimeInMs; + } + + public void setMinTimeInMs(long minTimeInMs) { + this.minTimeInMs = minTimeInMs; + } + + public Token getInitialBalance() { + return initialBalance; + } + + public void setInitialBalance(Token initialBalance) { + this.initialBalance = initialBalance; + } + + public Token getBalance() { + return balance; + } + + public void setBalance(Token balance) { + this.balance = balance; + } + + public long getSrcShares() { + return srcShares; + } + + public void setSrcShares(long srcShares) { + this.srcShares = srcShares; + } + + public long getDstShare() { + return dstShare; + } + + public void setDstShare(long dstShare) { + this.dstShare = dstShare; + } + + @Override + public String toString() { + return "SideChainRedelegation{" + + "delegatorAddress='" + delegatorAddress + '\'' + + ", srcValidatorAddress='" + srcValidatorAddress + '\'' + + ", dstValidatorAddress='" + dstValidatorAddress + '\'' + + ", createHeight=" + createHeight + + ", minTime='" + minTime + '\'' + + ", minTimeInMs=" + minTimeInMs + + ", initialBalance=" + initialBalance + + ", balance=" + balance + + ", srcShares=" + srcShares + + ", dstShare=" + dstShare + + '}'; + } +} diff --git a/src/main/java/com/binance/dex/api/client/domain/stake/sidechain/SideChainUnBond.java b/src/main/java/com/binance/dex/api/client/domain/stake/sidechain/SideChainUnBond.java new file mode 100644 index 0000000..18922f3 --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/domain/stake/sidechain/SideChainUnBond.java @@ -0,0 +1,62 @@ +package com.binance.dex.api.client.domain.stake.sidechain; + +import com.binance.dex.api.client.encoding.message.Token; + +/** + * @author Fitz.Lu + **/ +public class SideChainUnBond { + + private String delegatorAddress; + + private String validatorAddress; + + private Token amount; + + private String sideChainId; + + public SideChainUnBond() { + } + + public String getDelegatorAddress() { + return delegatorAddress; + } + + public void setDelegatorAddress(String delegatorAddress) { + this.delegatorAddress = delegatorAddress; + } + + public String getValidatorAddress() { + return validatorAddress; + } + + public void setValidatorAddress(String validatorAddress) { + this.validatorAddress = validatorAddress; + } + + public Token getAmount() { + return amount; + } + + public void setAmount(Token amount) { + this.amount = amount; + } + + public String getSideChainId() { + return sideChainId; + } + + public void setSideChainId(String sideChainId) { + this.sideChainId = sideChainId; + } + + @Override + public String toString() { + return "SideChainUnBond{" + + "delegatorAddress='" + delegatorAddress + '\'' + + ", validatorAddress='" + validatorAddress + '\'' + + ", amount=" + amount + + ", sideChainId='" + sideChainId + '\'' + + '}'; + } +} diff --git a/src/main/java/com/binance/dex/api/client/domain/stake/sidechain/SideChainValidator.java b/src/main/java/com/binance/dex/api/client/domain/stake/sidechain/SideChainValidator.java new file mode 100644 index 0000000..c691268 --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/domain/stake/sidechain/SideChainValidator.java @@ -0,0 +1,209 @@ +package com.binance.dex.api.client.domain.stake.sidechain; + +import com.binance.dex.api.client.domain.stake.Commission; +import com.binance.dex.api.client.domain.stake.Description; + +import java.util.Arrays; + +/** + * @author Fitz.Lu + **/ +public class SideChainValidator { + + private String feeAddr; + + private String operatorAddr; + + private byte[] consPubKey; + + private boolean jailed; + + private int status; + + private long tokens; + + private long delegatorShares; + + private Description description; + + private long bondHeight; + + private int bondIntraTxCounter; + + private long unBondingHeight; + + private long unBondingMinTime; + + private Commission commission; + + private String distributionAddr; + + private String sideChainId; + + private String sideConsAddr; + + private String sideFeeAddr; + + public SideChainValidator() { + } + + public String getFeeAddr() { + return feeAddr; + } + + public void setFeeAddr(String feeAddr) { + this.feeAddr = feeAddr; + } + + public String getOperatorAddr() { + return operatorAddr; + } + + public void setOperatorAddr(String operatorAddr) { + this.operatorAddr = operatorAddr; + } + + public byte[] getConsPubKey() { + return consPubKey; + } + + public void setConsPubKey(byte[] consPubKey) { + this.consPubKey = consPubKey; + } + + public boolean isJailed() { + return jailed; + } + + public void setJailed(boolean jailed) { + this.jailed = jailed; + } + + public int getStatus() { + return status; + } + + public void setStatus(int status) { + this.status = status; + } + + public long getTokens() { + return tokens; + } + + public void setTokens(long tokens) { + this.tokens = tokens; + } + + public long getDelegatorShares() { + return delegatorShares; + } + + public void setDelegatorShares(long delegatorShares) { + this.delegatorShares = delegatorShares; + } + + public Description getDescription() { + return description; + } + + public void setDescription(Description description) { + this.description = description; + } + + public long getBondHeight() { + return bondHeight; + } + + public void setBondHeight(long bondHeight) { + this.bondHeight = bondHeight; + } + + public int getBondIntraTxCounter() { + return bondIntraTxCounter; + } + + public void setBondIntraTxCounter(int bondIntraTxCounter) { + this.bondIntraTxCounter = bondIntraTxCounter; + } + + public long getUnBondingHeight() { + return unBondingHeight; + } + + public void setUnBondingHeight(long unBondingHeight) { + this.unBondingHeight = unBondingHeight; + } + + public long getUnBondingMinTime() { + return unBondingMinTime; + } + + public void setUnBondingMinTime(long unBondingMinTime) { + this.unBondingMinTime = unBondingMinTime; + } + + public Commission getCommission() { + return commission; + } + + public void setCommission(Commission commission) { + this.commission = commission; + } + + public String getDistributionAddr() { + return distributionAddr; + } + + public void setDistributionAddr(String distributionAddr) { + this.distributionAddr = distributionAddr; + } + + public String getSideChainId() { + return sideChainId; + } + + public void setSideChainId(String sideChainId) { + this.sideChainId = sideChainId; + } + + public String getSideConsAddr() { + return sideConsAddr; + } + + public void setSideConsAddr(String sideConsAddr) { + this.sideConsAddr = sideConsAddr; + } + + public String getSideFeeAddr() { + return sideFeeAddr; + } + + public void setSideFeeAddr(String sideFeeAddr) { + this.sideFeeAddr = sideFeeAddr; + } + + @Override + public String toString() { + return "SideChainValidator{" + + "feeAddr=" + feeAddr + '\n' + + ", operatorAddr=" + operatorAddr + '\n' + + ", consPubKey='" + consPubKey + '\'' + '\n' + + ", jailed=" + jailed + '\n' + + ", status=" + status + '\n' + + ", tokens=" + tokens + '\n' + + ", delegatorShares=" + delegatorShares + '\n' + + ", description=" + description + '\n' + + ", bondHeight=" + bondHeight + '\n' + + ", bondIntraTxCounter=" + bondIntraTxCounter + '\n' + + ", unBondingHeight=" + unBondingHeight + '\n' + + ", unBondingMinTime=" + unBondingMinTime + '\n' + + ", commission=" + commission + '\n' + + ", distributionAddr=" + distributionAddr + '\n' + + ", sideChainId='" + sideChainId + '\'' + '\n' + + ", sideConsAddr=" + sideConsAddr + '\n' + + ", sideFeeAddr=" + sideFeeAddr + '\n' + + '}'; + } + +} diff --git a/src/main/java/com/binance/dex/api/client/domain/stake/sidechain/UnBondingDelegation.java b/src/main/java/com/binance/dex/api/client/domain/stake/sidechain/UnBondingDelegation.java new file mode 100644 index 0000000..b7ba0f8 --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/domain/stake/sidechain/UnBondingDelegation.java @@ -0,0 +1,92 @@ +package com.binance.dex.api.client.domain.stake.sidechain; + +import com.binance.dex.api.client.encoding.message.Token; + +/** + * @author Fitz.Lu + **/ +public class UnBondingDelegation { + + private String delegatorAddress; + + private String validatorAddress; + + private long createHeight; + + private long minTimeInMs; + + private String minTime; + + private Token initialBalance; + + private Token balance; + + public String getDelegatorAddress() { + return delegatorAddress; + } + + public void setDelegatorAddress(String delegatorAddress) { + this.delegatorAddress = delegatorAddress; + } + + public String getValidatorAddress() { + return validatorAddress; + } + + public void setValidatorAddress(String validatorAddress) { + this.validatorAddress = validatorAddress; + } + + public long getCreateHeight() { + return createHeight; + } + + public void setCreateHeight(long createHeight) { + this.createHeight = createHeight; + } + + public long getMinTimeInMs() { + return minTimeInMs; + } + + public void setMinTimeInMs(long minTimeInMs) { + this.minTimeInMs = minTimeInMs; + } + + public String getMinTime() { + return minTime; + } + + public void setMinTime(String minTime) { + this.minTime = minTime; + } + + public Token getInitialBalance() { + return initialBalance; + } + + public void setInitialBalance(Token initialBalance) { + this.initialBalance = initialBalance; + } + + public Token getBalance() { + return balance; + } + + public void setBalance(Token balance) { + this.balance = balance; + } + + @Override + public String toString() { + return "UnBondingDelegation{" + + "delegatorAddress='" + delegatorAddress + '\'' + + ", validatorAddress='" + validatorAddress + '\'' + + ", createHeight=" + createHeight + + ", minTimeInMs=" + minTimeInMs + + ", minTime='" + minTime + '\'' + + ", initialBalance=" + initialBalance + + ", balance=" + balance + + '}'; + } +} diff --git a/src/main/java/com/binance/dex/api/client/encoding/ByteUtil.java b/src/main/java/com/binance/dex/api/client/encoding/ByteUtil.java new file mode 100644 index 0000000..a12c44e --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/encoding/ByteUtil.java @@ -0,0 +1,83 @@ +package com.binance.dex.api.client.encoding; + +import java.util.Arrays; + +/** + * @author Fitz.Lu + **/ +public class ByteUtil { + + public static boolean isEmpty(byte[] bytes){ + return bytes == null || bytes.length == 0; + } + + public static byte[] read(byte[] bytes, int length){ + requireByteArrayNotEmpty(bytes); + + byte[] newBytes = new byte[length]; + System.arraycopy(bytes, 0, newBytes, 0, length); + return newBytes; + } + + public static byte[] cut(byte[] bytes, int length){ + requireByteArrayNotEmpty(bytes); + requireByteArrayLengthNotLessThan(bytes, length); + + byte[] newBytes = new byte[bytes.length - length]; + System.arraycopy(bytes, length, newBytes, 0, newBytes.length); + return newBytes; + } + + public static byte[] pick(byte[] bytes, int start, int length){ + requireByteArrayNotEmpty(bytes); + requireByteArrayLengthNotLessThan(bytes, length); + + byte[] newBytes = new byte[length]; + System.arraycopy(bytes, start, newBytes, 0, length); + return newBytes; + } + + public static byte[] trim(byte[] bytes, byte b){ + requireByteArrayNotEmpty(bytes); + byte[] newBytes = new byte[0]; + for(byte bb : bytes){ + if (bb != b){ + newBytes = appendByte(newBytes,bb); + } + } + return newBytes; + } + + public static byte[] appendByte(byte[] bytes, byte b) { + byte[] result = Arrays.copyOf(bytes, bytes.length + 1); + result[result.length - 1] = b; + return result; + } + + public static byte[] appendBytesArray(byte[] first, byte[] second){ + if (first == null){ + throw new NullPointerException("first byte array is null"); + } + if (second == null){ + throw new NullPointerException("second byte array is null"); + } + + byte[] newArray = new byte[first.length + second.length]; + System.arraycopy(first, 0, newArray, 0, first.length); + System.arraycopy(second, 0, newArray, first.length, second.length); + return newArray; + } + + public static void requireByteArrayNotEmpty(byte[] bytes){ + if (isEmpty(bytes)){ + throw new IllegalArgumentException("Input byte array is null or empty"); + } + } + + public static void requireByteArrayLengthNotLessThan(byte[] bytes, int length){ + if (bytes.length < length){ + throw new IllegalArgumentException("Input byte array length is less than " + length); + } + } + +} diff --git a/src/main/java/com/binance/dex/api/client/encoding/Crypto.java b/src/main/java/com/binance/dex/api/client/encoding/Crypto.java index 1e69709..e9b08fc 100644 --- a/src/main/java/com/binance/dex/api/client/encoding/Crypto.java +++ b/src/main/java/com/binance/dex/api/client/encoding/Crypto.java @@ -5,6 +5,7 @@ import org.bitcoinj.core.Sha256Hash; import org.bitcoinj.core.Utils; import org.bitcoinj.crypto.*; +import org.bouncycastle.util.encoders.Hex; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -183,4 +184,5 @@ public static class SegwitAddressException extends IllegalArgumentException { super(s); } } + } diff --git a/src/main/java/com/binance/dex/api/client/encoding/EncodeUtils.java b/src/main/java/com/binance/dex/api/client/encoding/EncodeUtils.java index 2d0c6c7..8a24a04 100644 --- a/src/main/java/com/binance/dex/api/client/encoding/EncodeUtils.java +++ b/src/main/java/com/binance/dex/api/client/encoding/EncodeUtils.java @@ -2,12 +2,15 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.common.base.Charsets; import com.google.protobuf.CodedOutputStream; +import org.bouncycastle.jcajce.provider.digest.Keccak; import org.bouncycastle.util.encoders.Hex; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.security.MessageDigest; public class EncodeUtils { @@ -25,6 +28,17 @@ public static String bytesToHex(byte[] bytes) { return Hex.toHexString(bytes); } + public static String bytesToPrefixHex(byte[] bytes) { + return "0x" + bytesToHex(bytes); + } + + public static String cleanHexPrefix(String s){ + if (s.startsWith("0x")){ + s = s.substring(2); + } + return s; + } + public static String toJsonStringSortKeys(Object object) throws JsonProcessingException { return OBJECT_MAPPER.writeValueAsString(object); } @@ -34,7 +48,7 @@ public static T toObjectFromJsonString(String jsonString,Class tClass) th } public static byte[] toJsonEncodeBytes(Object object) throws JsonProcessingException { - return toJsonStringSortKeys(object).getBytes(Charset.forName("UTF-8")); + return toJsonStringSortKeys(object).getBytes(Charsets.UTF_8); } public static byte[] aminoWrap(byte[] raw, byte[] typePrefix, boolean isPrefixLength) throws IOException { @@ -68,4 +82,20 @@ public static byte[] long2Bytes(long x){ return buffer.array(); } + public static ObjectMapper getObjectMapper() { + return OBJECT_MAPPER; + } + + public static String sha3String(String utf8String) { + return bytesToHex(sha3(utf8String.getBytes(StandardCharsets.UTF_8))); + } + public static byte[] sha3(byte[] input) { + return sha3(input, 0, input.length); + } + public static byte[] sha3(byte[] input, int offset, int length) { + Keccak.DigestKeccak kecc = new Keccak.Digest256(); + kecc.update(input, offset, length); + return kecc.digest(); + } + } diff --git a/src/main/java/com/binance/dex/api/client/encoding/amino/Amino.java b/src/main/java/com/binance/dex/api/client/encoding/amino/Amino.java new file mode 100644 index 0000000..5e66f4c --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/encoding/amino/Amino.java @@ -0,0 +1,445 @@ +package com.binance.dex.api.client.encoding.amino; + +import com.binance.dex.api.client.encoding.ByteUtil; +import com.google.protobuf.CodedInputStream; +import com.google.protobuf.CodedOutputStream; +import org.bouncycastle.util.encoders.Hex; + +import java.io.IOException; +import java.security.NoSuchAlgorithmException; +import java.util.Arrays; + +/** + * @author Fitz.Lu + **/ +public class Amino { + + private static final int disambiguationByteSize = 3; + + private static final int prefixByteSize = 4; + + /** + * > Amino Disamb and Prefix + * > hash := sha256("com.tendermint.consensus/MyConcreteName") + * > hex.EncodeBytes(hash) // 0x{00 00 A8 FC 54 00 00 00 BB 9C 83 DD ...} (example) + * > rest = dropLeadingZeroBytes(hash) // 0x{A8 FC 54 00 00 00 BB 9C 83 DD ...} + * > disamb = rest[0:3] + * > rest = dropLeadingZeroBytes(rest[3:]) + * > prefix = rest[0:4] + * > <0xA8 0xFC 0x54> [0xBB 0x9C 9x83 9xDD] // and [Prefix Bytes] + **/ + + /** + * Return disambiguation bytes from given name, the first three non-zero bytes + * + * @param name the name + */ + public byte[] nameToDisamb(String name) throws NoSuchAlgorithmException { + return nameToDisambPrefix(name).getDisamb(); + } + + /** + * Return prefix bytes from given name, the first four non-zero bytes + * + * @param name the name + */ + public byte[] nameToPrefix(String name) throws NoSuchAlgorithmException { + return nameToDisambPrefix(name).getPrefix(); + } + + public String nameToPrefixString(String name) throws NoSuchAlgorithmException { + return Hex.toHexString(nameToDisambPrefix(name).getPrefix()); + } + + /** + * Return disambiguation and prefix bytes pair from given name + * + * @param name the name + * @see DisambPrefix + */ + public DisambPrefix nameToDisambPrefix(String name) throws NoSuchAlgorithmException { + DisambPrefix disambPrefix = new DisambPrefix(); + byte[] nameHash = new byte[0]; + nameHash = dropLeadingZero(AminoHashing.sha256(name)); + disambPrefix.setDisamb(Arrays.copyOfRange(nameHash, 0, disambiguationByteSize)); + + byte[] rest = Arrays.copyOfRange(nameHash, disambiguationByteSize, nameHash.length); + disambPrefix.setPrefix(Arrays.copyOfRange(dropLeadingZero(rest), 0, prefixByteSize)); + + byte[] dp = new byte[disambiguationByteSize + prefixByteSize]; + System.arraycopy(disambPrefix.getDisamb(), 0, dp, 0, disambiguationByteSize); + System.arraycopy(disambPrefix.getPrefix(), 0, dp, disambiguationByteSize, prefixByteSize); + + disambPrefix.setDisambPrefix(dp); + + return disambPrefix; + } + + private byte[] dropLeadingZero(byte[] byteArray) { + int offset = 0; + for (byte oneByte : byteArray) { + if (oneByte != 0) { + break; + } + offset++; + } + return Arrays.copyOfRange(byteArray, offset, byteArray.length); + + } + + /** + * > Amino encode + * */ + public byte[] encode(AminoSerializable message, byte[] typePrefix, boolean lengthPrefix) throws IOException { + boolean writeTypePrefix = false; + boolean writeLengthPrefix = false; + int length = computeSerializedSize(message); + + if (typePrefix != null && typePrefix.length > 0){ + length += typePrefix.length; + writeTypePrefix = true; + } + + int bufSize = length; + + if (lengthPrefix){ + bufSize += computeLengthByteSize(length); + writeLengthPrefix = true; + } + byte[] buf = new byte[bufSize]; + CodedOutputStream outputStream = CodedOutputStream.newInstance(buf); + + if (writeLengthPrefix){ + encodeLengthByte(length, outputStream); + } + + if (writeTypePrefix) { + outputStream.writeRawBytes(typePrefix); + } + + encodeAminoMessageBare(message, outputStream); + + outputStream.flush(); + + return buf; + } + + private void encodeAminoMessageBare(AminoSerializable message, CodedOutputStream outputStream) throws IOException { + int index = 0; + for (AminoField field : message.IterateFields()) { + index ++; + + if (field.isSkipWhenEncode() || field.getT() == null){ + continue; + } + + if (field.getT() instanceof AminoCustomSerialized){ + encodeAminoSerialized(index, (AminoCustomSerialized) field.getT(), outputStream); + continue; + } + + if (field.getT() instanceof AminoSerializable) { + outputStream.writeTag(index, WireType.LENGTH_DELIMITED); + int length = computeSerializedSize(((AminoSerializable) field.getT())); + encodeLengthByte(length, outputStream); + encodeAminoMessageBare(((AminoSerializable) field.getT()), outputStream); + continue; + } + + if (field.getT() instanceof String){ + encodeString(index, (String) field.getT(), outputStream); + continue; + } + + if (field.getT() instanceof byte[]){ + encodeByteArray(index, ((byte[]) field.getT()), outputStream); + continue; + } + + if (field.getT() instanceof Long){ + encodeInt64(index, ((Long) field.getT()), outputStream); + continue; + } + + if (field.getT() instanceof Integer){ + encodeInt32(index, (Integer) field.getT(), outputStream); + continue; + } + } + } + + public void decodeBare(byte[] data, AminoSerializable message) throws IOException, AminoDecodeException { + CodedInputStream input = CodedInputStream.newInstance(data); + try { + decode(input, message); + } catch (IllegalAccessException | InstantiationException e) { + throw new AminoDecodeException(e); + } + } + + public void decodeWithLengthPrefix(byte[] data, AminoSerializable message) throws IOException, AminoDecodeException { + CodedInputStream input = CodedInputStream.newInstance(data); + if (input.isAtEnd()){ + return; + } + + int length = input.readRawVarint32(); + if (length == 0){ + return; + } + + try { + decode(input, message); + } catch (IllegalAccessException | InstantiationException e) { + throw new AminoDecodeException(e); + } + } + + public static byte[] getByteArrayAfterTypePrefix(byte[] data) throws IllegalStateException { + byte[] typePrefix = ByteUtil.read(data, prefixByteSize); + //todo match type prefix from registered map + int length = Byte.toUnsignedInt(data[4]); + if (data.length - prefixByteSize - 1 != length){ + throw new IllegalStateException("Invalid Amino buffer"); + } + return ByteUtil.pick(data, prefixByteSize + 1, length); + } + + private void decode(CodedInputStream input, AminoSerializable message) throws IOException, IllegalAccessException, InstantiationException { + int index = 0; + int tag = 0; + boolean pendTag = false; + for (AminoField iterateField : message.IterateFields()) { + index ++; + + if (!pendTag) { + tag = input.readTag(); + } + + int currentFieldTag = computeTag(index, iterateField.getClazz()); + + if (currentFieldTag != tag){ + pendTag = true; + continue; + }else{ + pendTag = false; + } + + if (AminoCustomSerialized.class.isAssignableFrom(iterateField.getClazz())){ + Object obj; + if (iterateField.getT() != null){ + ((AminoCustomSerialized) iterateField.getT()).decode(input); + obj = iterateField.getT(); + }else{ + Object serializedObj = iterateField.getClazz().newInstance(); + ((AminoCustomSerialized) serializedObj).decode(input); + obj = serializedObj; + } + message.setValueByFieldIndex(index, obj); + continue; + } + + if (AminoSerializable.class.isAssignableFrom(iterateField.getClazz())){ + int length = input.readRawVarint32(); + if (length == 0){ + continue; + } + Object msg; + if (iterateField.getT() != null){ + msg = iterateField.getT(); + }else{ + msg = iterateField.getClazz().newInstance(); + } + + final int oldLimit = input.pushLimit(length); + decode(input, ((AminoSerializable) msg)); + //update lastTag in input stream + int emptyTag = input.readTag(); + //check is at the end + if (emptyTag != 0){ + throw new AminoDecodeException("Embedded message tag did not match expected tag"); + } + //double check + input.checkLastTagWas(0); + input.popLimit(oldLimit); + + message.setValueByFieldIndex(index, msg); + continue; + } + + if (iterateField.getClazz().isAssignableFrom(Boolean.class)){ + message.setValueByFieldIndex(index, input.readBool()); + continue; + } + + if (iterateField.getClazz().isAssignableFrom(Integer.class)){ + message.setValueByFieldIndex(index, input.readInt32()); + continue; + } + + if (iterateField.getClazz().isAssignableFrom(Long.class)){ + message.setValueByFieldIndex(index, input.readInt64()); + continue; + } + + if (iterateField.getClazz().isAssignableFrom(String.class)){ + message.setValueByFieldIndex(index, input.readStringRequireUtf8()); + continue; + } + + if (iterateField.getClazz().isAssignableFrom(byte[].class)){ + byte[] value = input.readByteArray(); + message.setValueByFieldIndex(index, value); + continue; + } + } + } + + private void encodeAminoSerialized(int fieldIndex, AminoCustomSerialized aminoCustomSerialized, CodedOutputStream outputStream) throws IOException { + if (!aminoCustomSerialized.isDefaultOrEmpty()) { + outputStream.writeTag(fieldIndex, aminoCustomSerialized.getWireType()); + aminoCustomSerialized.encode(outputStream); + } + } + + private void encodeString(int fieldIndex, String value, CodedOutputStream outputStream) throws IOException { + outputStream.writeTag(fieldIndex, WireType.LENGTH_DELIMITED); + outputStream.writeStringNoTag(value); + } + + private void encodeByteArray(int fieldIndex, byte[] array, CodedOutputStream outputStream) throws IOException { + outputStream.writeTag(fieldIndex, WireType.LENGTH_DELIMITED); + outputStream.writeByteArrayNoTag(array); + } + + private void encodeInt64(int fieldIndex, long value, CodedOutputStream outputStream) throws IOException { + outputStream.writeTag(fieldIndex, WireType.VARINT); + outputStream.writeInt64NoTag(value); + } + + private void encodeInt32(int fieldIndex, int value, CodedOutputStream outputStream) throws IOException { + outputStream.writeTag(fieldIndex, WireType.VARINT); + outputStream.writeInt32NoTag(value); + } + + private void encodeUInt32Bare(int value, CodedOutputStream codedOutputStream) throws IOException { + codedOutputStream.writeUInt32NoTag(value); + } + + private void encodeLengthByte(int length, CodedOutputStream codedOutputStream) throws IOException { + codedOutputStream.writeUInt32NoTag(length); + } + + public int computeSerializedSize(AminoSerializable message){ + int size = 0; + int index = 0; + for (AminoField iterateField : message.IterateFields()) { + index ++; + + if (iterateField.isSkipWhenEncode() || iterateField.getT() == null){ + continue; + } + + if (iterateField.getT() instanceof AminoCustomSerialized){ + size += computeTagSize(index, ((AminoCustomSerialized) iterateField.getT()).getWireType()); + size += ((AminoCustomSerialized) iterateField.getT()).getSerializedSize(); + continue; + } + + if (iterateField.getT() instanceof AminoSerializable){ + size += computeTagSize(index, WireType.LENGTH_DELIMITED); + int embeddedSize = computeSerializedSize(((AminoSerializable) iterateField.getT())); + size += computeLengthByteSize(embeddedSize); + size += embeddedSize; + continue; + } + + if (iterateField.getT() instanceof String){ + size += computeTagSize(index, WireType.LENGTH_DELIMITED); + size += computeStringSize(((String)iterateField.getT())); + continue; + } + + if (iterateField.getT() instanceof byte[]) { + size += computeTagSize(index, WireType.LENGTH_DELIMITED); + size += computeByteArraySize(((byte[]) iterateField.getT())); + continue; + } + + if (iterateField.getT() instanceof Long){ + size += computeTagSize(index, WireType.VARINT); + size += computeInt64Size(((Long) iterateField.getT())); + continue; + } + + if (iterateField.getT() instanceof Integer){ + size += computeTagSize(index, WireType.VARINT); + size += computeInt32Size((Integer) iterateField.getT()); + continue; + } + } + + return size; + } + + private int computeTagSize(final int fieldNumber, final int wireType){ + return CodedOutputStream.computeUInt32SizeNoTag(makeTag(fieldNumber, wireType)); + } + + private int computeByteArraySize(final byte[] bytes){ + return CodedOutputStream.computeByteArraySizeNoTag(bytes); + } + + private int computeStringSize(final String str){ + return CodedOutputStream.computeStringSizeNoTag(str); + } + + private int computeInt32Size(final int value){ + return CodedOutputStream.computeInt32SizeNoTag(value); + } + + private int computeUInt32Size(final int value){ + return CodedOutputStream.computeUInt32SizeNoTag(value); + } + + private int computeLengthByteSize(final int length){ + return CodedOutputStream.computeUInt32SizeNoTag(length); + } + + private int computeInt64Size(final long value){ + return CodedOutputStream.computeInt64SizeNoTag(value); + } + + private int computeUInt64Size(final long value){ + return CodedOutputStream.computeUInt64SizeNoTag(value); + } + + private int computeTag(int fieldIndex, Class clazz){ + if (AminoCustomSerialized.class.isAssignableFrom(clazz) || + AminoSerializable.class.isAssignableFrom(clazz) || + clazz.isAssignableFrom(byte[].class) || + clazz.isAssignableFrom(String.class)){ + return makeTag(fieldIndex, WireType.LENGTH_DELIMITED); + } + + if (clazz.isAssignableFrom(Long.class) || + clazz.isAssignableFrom(Integer.class) || + clazz.isAssignableFrom(Boolean.class)) { + return makeTag(fieldIndex, WireType.VARINT); + } + + throw new IllegalArgumentException("Unsupported class " + clazz.getCanonicalName()); + } + + private int makeTag(final int fieldNumber, final int wireType){ + return (fieldNumber << 3) | wireType; + } + + private byte[] appendBytesArray(byte[] first, byte[] second){ + byte[] newArray = new byte[first.length + second.length]; + System.arraycopy(first, 0, newArray, 0, first.length); + System.arraycopy(second, 0, newArray, first.length, second.length); + return newArray; + } + +} diff --git a/src/main/java/com/binance/dex/api/client/encoding/amino/AminoCustomSerialized.java b/src/main/java/com/binance/dex/api/client/encoding/amino/AminoCustomSerialized.java new file mode 100644 index 0000000..ac949fd --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/encoding/amino/AminoCustomSerialized.java @@ -0,0 +1,25 @@ +package com.binance.dex.api.client.encoding.amino; + +import com.google.protobuf.CodedInputStream; +import com.google.protobuf.CodedOutputStream; + +import java.io.IOException; + +/** + * @author Fitz.Lu + **/ +public interface AminoCustomSerialized { + + AminoCustomSerialized newAminoSerInstance(); + + boolean isDefaultOrEmpty(); + + void encode(CodedOutputStream outputStream) throws IOException; + + int getWireType(); + + void decode(CodedInputStream inputStream) throws IOException; + + int getSerializedSize(); + +} diff --git a/src/main/java/com/binance/dex/api/client/encoding/amino/AminoDecodeException.java b/src/main/java/com/binance/dex/api/client/encoding/amino/AminoDecodeException.java new file mode 100644 index 0000000..eec8006 --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/encoding/amino/AminoDecodeException.java @@ -0,0 +1,26 @@ +package com.binance.dex.api.client.encoding.amino; + +/** + * @author Fitz.Lu + **/ +public class AminoDecodeException extends RuntimeException { + + public AminoDecodeException() { + } + + public AminoDecodeException(String message) { + super(message); + } + + public AminoDecodeException(String message, Throwable cause) { + super(message, cause); + } + + public AminoDecodeException(Throwable cause) { + super(cause); + } + + public AminoDecodeException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { + super(message, cause, enableSuppression, writableStackTrace); + } +} diff --git a/src/main/java/com/binance/dex/api/client/encoding/amino/AminoField.java b/src/main/java/com/binance/dex/api/client/encoding/amino/AminoField.java new file mode 100644 index 0000000..d3c2a44 --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/encoding/amino/AminoField.java @@ -0,0 +1,70 @@ +package com.binance.dex.api.client.encoding.amino; + +import javax.annotation.Nullable; +import java.util.ArrayList; + +/** + * @author Fitz.Lu + **/ +public class AminoField { + + public static AminoFieldsBuilder newFieldsBuilder(){ + return new AminoFieldsBuilder(); + } + + private Class clazz; + + private T t; + + private boolean skipWhenEncode = false; + + public AminoField(Class clazz, @Nullable T t, boolean skipWhenEncode) { + this.clazz = clazz; + this.t = t; + this.skipWhenEncode = skipWhenEncode; + } + + public Class getClazz() { + return clazz; + } + + public void setClazz(Class clazz) { + this.clazz = clazz; + } + + public T getT() { + return t; + } + + public void setT(T t) { + this.t = t; + } + + public boolean isSkipWhenEncode() { + return skipWhenEncode; + } + + public void setSkipWhenEncode(boolean skipWhenEncode) { + this.skipWhenEncode = skipWhenEncode; + } + + public static class AminoFieldsBuilder { + + private final ArrayList> fields; + + public AminoFieldsBuilder(){ + fields = new ArrayList<>(); + } + + public AminoFieldsBuilder addField(Class clazz, T2 value, boolean skipWhenEncode){ + fields.add(new AminoField<>(clazz, value, skipWhenEncode)); + return this; + } + + public ArrayList> build(){ + return fields; + } + + } + +} diff --git a/src/main/java/com/binance/dex/api/client/encoding/amino/AminoHashing.java b/src/main/java/com/binance/dex/api/client/encoding/amino/AminoHashing.java new file mode 100644 index 0000000..9f769cb --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/encoding/amino/AminoHashing.java @@ -0,0 +1,44 @@ +package com.binance.dex.api.client.encoding.amino; + +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +/** + * author: Fitz + **/ +class AminoHashing { + + private final static char[] hexArray = "0123456789ABCDEF".toCharArray(); + private final static String SHA256 = "SHA-256"; + + public static byte[] sha256(byte[] arg) throws NoSuchAlgorithmException { + MessageDigest digest = MessageDigest.getInstance(SHA256); + return digest.digest(arg); + } + + public static byte[] sha256(String arg) throws NoSuchAlgorithmException { + MessageDigest digest = MessageDigest.getInstance(SHA256); + return digest.digest(arg.getBytes(StandardCharsets.UTF_8)); + } + + public static String bytesToHex(byte[] bytes) { + char[] hexChars = new char[bytes.length * 2]; + for ( int i = 0; i < bytes.length; i++ ) { + int v = bytes[i] & 0xFF; + hexChars[i * 2] = hexArray[v >>> 4]; + hexChars[i * 2 + 1] = hexArray[v & 0x0F]; + } + return new String(hexChars); + } + + public static byte[] hexToBytes(String s) { + int len = s.length(); + byte[] data = new byte[len / 2]; + for (int i = 0; i < len; i += 2) { + data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i+1), 16)); + } + return data; + } + +} diff --git a/src/main/java/com/binance/dex/api/client/encoding/amino/AminoSerializable.java b/src/main/java/com/binance/dex/api/client/encoding/amino/AminoSerializable.java new file mode 100644 index 0000000..122552d --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/encoding/amino/AminoSerializable.java @@ -0,0 +1,16 @@ +package com.binance.dex.api.client.encoding.amino; + +import java.util.ArrayList; + +/** + * @author Fitz.Lu + **/ +public interface AminoSerializable { + + AminoSerializable newAminoMessage(); + + ArrayList> IterateFields(); + + void setValueByFieldIndex(int fieldIndex, Object value); + +} diff --git a/src/main/java/com/binance/dex/api/client/encoding/amino/DisambPrefix.java b/src/main/java/com/binance/dex/api/client/encoding/amino/DisambPrefix.java new file mode 100644 index 0000000..f987823 --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/encoding/amino/DisambPrefix.java @@ -0,0 +1,65 @@ +package com.binance.dex.api.client.encoding.amino; + +import java.util.Arrays; + +/** + * Disambiguation and prefix pair + * */ +public class DisambPrefix { + + /** + * The first three non-zero bytes + * */ + private byte[] disamb; + + /** + * The first four non-zero bytes + * */ + private byte[] prefix; + + /** + * disamb bytes append prefix bytes + * */ + private byte[] disambPrefix; + + public DisambPrefix() { } + + public DisambPrefix(byte[] disamb, byte[] prefix, byte[] disambPrefix) { + this.disamb = disamb; + this.prefix = prefix; + this.disambPrefix = disambPrefix; + } + + public byte[] getDisamb() { + return disamb; + } + + public void setDisamb(byte[] disamb) { + this.disamb = disamb; + } + + public byte[] getPrefix() { + return prefix; + } + + public void setPrefix(byte[] prefix) { + this.prefix = prefix; + } + + public byte[] getDisambPrefix() { + return disambPrefix; + } + + public void setDisambPrefix(byte[] disambPrefix) { + this.disambPrefix = disambPrefix; + } + + @Override + public String toString() { + return "DisambPrefixPair{" + + "disamb=" + Arrays.toString(disamb) + + ", prefix=" + Arrays.toString(prefix) + + ", disambPrefix=" + Arrays.toString(disambPrefix) + + '}'; + } +} diff --git a/src/main/java/com/binance/dex/api/client/encoding/amino/InternalAmino.java b/src/main/java/com/binance/dex/api/client/encoding/amino/InternalAmino.java new file mode 100644 index 0000000..d85f506 --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/encoding/amino/InternalAmino.java @@ -0,0 +1,14 @@ +package com.binance.dex.api.client.encoding.amino; + +/** + * @author Fitz.Lu + **/ +public class InternalAmino { + + private static final Amino ins = new Amino(); + + public static Amino get(){ + return ins; + } + +} \ No newline at end of file diff --git a/src/main/java/com/binance/dex/api/client/encoding/amino/WireType.java b/src/main/java/com/binance/dex/api/client/encoding/amino/WireType.java new file mode 100644 index 0000000..9c0f885 --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/encoding/amino/WireType.java @@ -0,0 +1,72 @@ +package com.binance.dex.api.client.encoding.amino; + +import com.binance.dex.api.client.encoding.amino.types.PubKeyEd25519; +import com.binance.dex.api.client.encoding.message.bridge.BindMsgMessage; +import com.binance.dex.api.client.encoding.message.bridge.ClaimMsgMessage; +import com.binance.dex.api.client.encoding.message.bridge.TransferOutMsgMessage; +import com.binance.dex.api.client.encoding.message.bridge.UnbindMsgMessage; +import com.binance.dex.api.client.encoding.message.sidechain.transaction.*; +import org.bouncycastle.util.encoders.Hex; + +import java.security.NoSuchAlgorithmException; +import java.util.HashMap; + +/** + * @author Fitz.Lu + * @see {https://developers.google.com/protocol-buffers/docs/encoding#structure} + **/ +public class WireType { + + private static final HashMap, String> classToTypeName = new HashMap<>(); + + static { + classToTypeName.put(PubKeyEd25519.class, "tendermint/PubKeyEd25519"); + + classToTypeName.put(CreateSideChainValidatorMessage.class, "cosmos-sdk/MsgCreateSideChainValidator"); + classToTypeName.put(EditSideChainValidatorMessage.class, "cosmos-sdk/MsgEditSideChainValidator"); + classToTypeName.put(SideChainDelegateMessage.class, "cosmos-sdk/MsgSideChainDelegate"); + classToTypeName.put(SideChainRedelegateMessage.class, "cosmos-sdk/MsgSideChainRedelegate"); + classToTypeName.put(SideChainUndelegateMessage.class, "cosmos-sdk/MsgSideChainUndelegate"); + + classToTypeName.put(TransferOutMsgMessage.class, "bridge/TransferOutMsg"); + classToTypeName.put(BindMsgMessage.class, "bridge/BindMsg"); + classToTypeName.put(UnbindMsgMessage.class, "bridge/UnbindMsg"); + classToTypeName.put(ClaimMsgMessage.class, "oracle/ClaimMsg"); + } + + public static int VARINT = 0; //int32, int64, uint32, uint64, sint32, sint64, bool, enum + + public static int BIT64 = 1; //fixed64, sfixed64, double + + public static int LENGTH_DELIMITED = 2; //string, bytes, embedded messages, packed repeated fields + + public static int BIT_32 = 5; // fixed32, sfixed32, float + + + public static boolean isRegistered(Class clazz){ + return classToTypeName.containsKey(clazz); + } + + public static boolean isRegistered(byte[] typePrefix){ + String typeHex = Hex.toHexString(typePrefix); + for (String value : classToTypeName.values()) { + if (typeHex.equals(value)){ + return true; + } + } + + return false; + } + + public static String getRegisteredTypeName(Class clazz) { + return classToTypeName.get(clazz); + } + + public static byte[] getTypePrefix(Class clazz) throws IllegalStateException, NoSuchAlgorithmException { + if (!isRegistered(clazz)){ + throw new IllegalStateException("class " + clazz.getCanonicalName() + " has not been registered into amino"); + } + return InternalAmino.get().nameToPrefix(getRegisteredTypeName(clazz)); + } + +} diff --git a/src/main/java/com/binance/dex/api/client/encoding/amino/types/PubKey.java b/src/main/java/com/binance/dex/api/client/encoding/amino/types/PubKey.java new file mode 100644 index 0000000..9d20220 --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/encoding/amino/types/PubKey.java @@ -0,0 +1,10 @@ +package com.binance.dex.api.client.encoding.amino.types; + +/** + * @author Fitz.Lu + **/ +public interface PubKey { + + byte[] getBytes(); + +} diff --git a/src/main/java/com/binance/dex/api/client/encoding/amino/types/PubKeyEd25519.java b/src/main/java/com/binance/dex/api/client/encoding/amino/types/PubKeyEd25519.java new file mode 100644 index 0000000..2aaaefc --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/encoding/amino/types/PubKeyEd25519.java @@ -0,0 +1,28 @@ +package com.binance.dex.api.client.encoding.amino.types; + +/** + * @author Fitz.Lu + **/ +public class PubKeyEd25519 implements PubKey { + + private final int keySize = 32; + + private byte[] raw; + + public PubKeyEd25519(byte[] raw) { + this.raw = raw; + } + + public byte[] getRaw() { + return raw; + } + + public void setRaw(byte[] raw) { + this.raw = raw; + } + + @Override + public byte[] getBytes() { + return raw; + } +} diff --git a/src/main/java/com/binance/dex/api/client/encoding/message/BinanceDexTransactionMessage.java b/src/main/java/com/binance/dex/api/client/encoding/message/BinanceDexTransactionMessage.java index d293be0..ea31b31 100644 --- a/src/main/java/com/binance/dex/api/client/encoding/message/BinanceDexTransactionMessage.java +++ b/src/main/java/com/binance/dex/api/client/encoding/message/BinanceDexTransactionMessage.java @@ -1,4 +1,11 @@ package com.binance.dex.api.client.encoding.message; public interface BinanceDexTransactionMessage { + + default boolean useAminoJson(){ + return false; + } + + default void validateBasic(){} + } diff --git a/src/main/java/com/binance/dex/api/client/encoding/message/MessageType.java b/src/main/java/com/binance/dex/api/client/encoding/message/MessageType.java index 7690ee2..19decf9 100644 --- a/src/main/java/com/binance/dex/api/client/encoding/message/MessageType.java +++ b/src/main/java/com/binance/dex/api/client/encoding/message/MessageType.java @@ -17,11 +17,14 @@ public enum MessageType { PubKey("EB5AE987"), StdTx("F0625DEE"), Vote("A1CADD36"), + SideVote("E26BA13D"), Issue("17EFAB80"), Burn("7ED2D2A0"), Mint("467E0829"), SubmitProposal("B42D614E"), + SideSubmitProposal("4ACBF03C"), Deposit("A18A56E5"), + SideDeposit("140F2DB4"), CreateValidator("DB6A19FD"), RemoveValidator("C1AFE85F"), Listing("B41DE13F"), @@ -33,6 +36,17 @@ public enum MessageType { DepositHashTimerLockMsg("63986496"), ClaimHashTimerLockMsg("C1665300"), RefundHashTimerLockMsg("3454A27C"), + CreateSideChainValidator("D17201E5"), + EditSideChainValidator("264CC57B"), + SideChainDelegate("E3A07FD2"), + SideChainRedelegate("E3CED364"), + SideChainUndelegate("514F7E0E"), + Claim("175A0521"), + TransferOut("800819C0"), + Bind("B9AE640C"), + UnBind("E9EEC508"), + BscSubmitEvidence("A38F1399"), + SideChainUnJail("5681EC54"), //mini token TinyTokenIssue("ED2832D4"), diff --git a/src/main/java/com/binance/dex/api/client/encoding/message/SideVoteMessage.java b/src/main/java/com/binance/dex/api/client/encoding/message/SideVoteMessage.java new file mode 100644 index 0000000..11b0f6a --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/encoding/message/SideVoteMessage.java @@ -0,0 +1,67 @@ +package com.binance.dex.api.client.encoding.message; + +import com.binance.dex.api.client.BinanceDexConstants; +import com.binance.dex.api.client.encoding.VoteOptionSerializer; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import org.apache.commons.lang3.builder.ToStringBuilder; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonPropertyOrder(alphabetic = true) +public class SideVoteMessage implements BinanceDexTransactionMessage { + + @JsonProperty("proposal_id") + @JsonSerialize(using = ToStringSerializer.class) + private Long proposalId; + private String voter; + @JsonSerialize(using = VoteOptionSerializer.class) + private Integer option; + @JsonProperty("side_chain_id") + private String sideChainId; + + public Long getProposalId() { + return proposalId; + } + + public void setProposalId(Long proposalId) { + this.proposalId = proposalId; + } + + public Integer getOption() { + return option; + } + + public void setOption(Integer option) { + this.option = option; + } + + public String getVoter() { + return voter; + } + + public void setVoter(String voter) { + this.voter = voter; + } + + public String getSideChainId() { + return sideChainId; + } + + public void setSideChainId(String sideChainId) { + this.sideChainId = sideChainId; + } + + @Override + public String toString() { + return new ToStringBuilder(this, BinanceDexConstants.BINANCE_DEX_TO_STRING_STYLE) + .append("proposalId", proposalId) + .append("option", option) + .append("sideChainId",sideChainId) + .toString(); + } + + +} diff --git a/src/main/java/com/binance/dex/api/client/encoding/message/Token.java b/src/main/java/com/binance/dex/api/client/encoding/message/Token.java index ddf47e9..39df5c2 100644 --- a/src/main/java/com/binance/dex/api/client/encoding/message/Token.java +++ b/src/main/java/com/binance/dex/api/client/encoding/message/Token.java @@ -3,13 +3,16 @@ import com.binance.dex.api.client.BinanceDexConstants; import com.binance.dex.api.proto.Send; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonPropertyOrder; import org.apache.commons.lang3.builder.ToStringBuilder; @JsonIgnoreProperties(ignoreUnknown = true) @JsonPropertyOrder(alphabetic = true) public class Token { + @JsonProperty(value = "denom") private String denom; + @JsonProperty(value = "amount") private Long amount; public static Token of(com.binance.dex.api.proto.Token source) { @@ -26,6 +29,14 @@ public static Token of(Send.Token sendToken){ return token; } + public Token() { + } + + public Token(String denom, Long amount) { + this.denom = denom; + this.amount = amount; + } + public String getDenom() { return denom; } diff --git a/src/main/java/com/binance/dex/api/client/encoding/message/TransactionMessageWithType.java b/src/main/java/com/binance/dex/api/client/encoding/message/TransactionMessageWithType.java new file mode 100644 index 0000000..aad1931 --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/encoding/message/TransactionMessageWithType.java @@ -0,0 +1,43 @@ +package com.binance.dex.api.client.encoding.message; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + +/** + * @author Fitz.Lu + **/ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonPropertyOrder(alphabetic = true) +public class TransactionMessageWithType implements BinanceDexTransactionMessage { + + @JsonProperty(value = "type") + private String type; + + @JsonProperty(value = "value") + private T value; + + public TransactionMessageWithType() { + } + + public TransactionMessageWithType(String type, T value) { + this.type = type; + this.value = value; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public T getValue() { + return value; + } + + public void setValue(T value) { + this.value = value; + } +} diff --git a/src/main/java/com/binance/dex/api/client/encoding/message/TransactionRequestAssembler.java b/src/main/java/com/binance/dex/api/client/encoding/message/TransactionRequestAssembler.java index 626a71a..16b134e 100644 --- a/src/main/java/com/binance/dex/api/client/encoding/message/TransactionRequestAssembler.java +++ b/src/main/java/com/binance/dex/api/client/encoding/message/TransactionRequestAssembler.java @@ -4,6 +4,10 @@ import com.binance.dex.api.client.domain.broadcast.*; import com.binance.dex.api.client.encoding.Crypto; import com.binance.dex.api.client.encoding.EncodeUtils; +import com.binance.dex.api.client.encoding.amino.Amino; +import com.binance.dex.api.client.encoding.amino.AminoSerializable; +import com.binance.dex.api.client.encoding.amino.InternalAmino; +import com.binance.dex.api.client.encoding.amino.WireType; import com.binance.dex.api.proto.StdSignature; import com.binance.dex.api.proto.StdTx; import com.google.common.annotations.VisibleForTesting; @@ -28,9 +32,12 @@ public class TransactionRequestAssembler { private Wallet wallet; private TransactionOption options; + private final Amino amino; + public TransactionRequestAssembler(Wallet wallet, TransactionOption options) { this.wallet = wallet; this.options = options; + this.amino = InternalAmino.get(); } public static long doubleToLong(String d) { @@ -49,6 +56,23 @@ public static String longToDouble(long l) { return BigDecimal.valueOf(l).divide(MULTIPLY_FACTOR).toString(); } + @VisibleForTesting + byte[] signTx(BinanceDexTransactionMessage msg) throws IOException, NoSuchAlgorithmException { + return sign(assembleMessage4Sign(msg)); + } + + private BinanceDexTransactionMessage assembleMessage4Sign(T t){ + if (t.useAminoJson()){ + if (WireType.isRegistered(t.getClass())){ + return new TransactionMessageWithType(WireType.getRegisteredTypeName(t.getClass()), t); + }else{ + throw new IllegalStateException("Class " + t.getClass().getCanonicalName() + " has not been registered into amino"); + } + }else{ + return t; + } + } + @VisibleForTesting byte[] sign(BinanceDexTransactionMessage msg) throws NoSuchAlgorithmException, IOException { @@ -64,6 +88,7 @@ byte[] sign(BinanceDexTransactionMessage msg) if (wallet.getEcKey() == null && wallet.getLedgerKey() != null) { return Crypto.sign(EncodeUtils.toJsonEncodeBytes(sd), wallet.getLedgerKey()); } + return Crypto.sign(EncodeUtils.toJsonEncodeBytes(sd), wallet.getEcKey()); } @@ -125,6 +150,16 @@ VoteMessage createVoteMessage(Vote vote){ return voteMessage; } + @VisibleForTesting + SideVoteMessage createSideVoteMessage(SideVote vote){ + SideVoteMessage voteMessage = new SideVoteMessage(); + voteMessage.setProposalId(vote.getProposalId()); + voteMessage.setOption(vote.getOption()); + voteMessage.setVoter(wallet.getAddress()); + voteMessage.setSideChainId(vote.getSideChainId()); + return voteMessage; + } + @VisibleForTesting byte[] encodeNewOrderMessage(NewOrderMessage newOrder) throws IOException { @@ -152,6 +187,18 @@ byte[] encodeVoteMessage(VoteMessage voteMessage) return EncodeUtils.aminoWrap(proto.toByteArray(), MessageType.Vote.getTypePrefixBytes(), false); } + @VisibleForTesting + byte[] encodeSideVoteMessage(SideVoteMessage voteMessage) + throws IOException { + com.binance.dex.api.proto.SideVote proto = com.binance.dex.api.proto.SideVote.newBuilder() + .setVoter(ByteString.copyFrom(wallet.getAddressBytes())) + .setProposalId(voteMessage.getProposalId()) + .setOption(voteMessage.getOption()) + .setSideChainId(voteMessage.getSideChainId()) + .build(); + return EncodeUtils.aminoWrap(proto.toByteArray(), MessageType.SideVote.getTypePrefixBytes(), false); + } + public RequestBody buildNewOrder(com.binance.dex.api.client.domain.broadcast.NewOrder newOrder) throws IOException, NoSuchAlgorithmException { return createRequestBody(buildNewOrderPayload(newOrder)); @@ -178,6 +225,18 @@ public String buildVotePayload(Vote vote) throws IOException, NoSuchAlgorithmExc return EncodeUtils.bytesToHex(stdTx); } + public RequestBody buildSideVote(SideVote vote) throws IOException, NoSuchAlgorithmException { + return createRequestBody(buildSideVotePayload(vote)); + } + + public String buildSideVotePayload(SideVote vote) throws IOException, NoSuchAlgorithmException { + SideVoteMessage msgBean = createSideVoteMessage(vote); + byte[] msg = encodeSideVoteMessage(msgBean); + byte[] signature = encodeSignature(sign(msgBean)); + byte[] stdTx = encodeStdTx(msg, signature); + return EncodeUtils.bytesToHex(stdTx); + } + @VisibleForTesting CancelOrderMessage createCancelOrderMessage( com.binance.dex.api.client.domain.broadcast.CancelOrder cancelOrder) { @@ -551,4 +610,19 @@ public byte[] encodeRefundHtltMessage(RefundHtltMessage msg) throws IOException return EncodeUtils.aminoWrap(proto.toByteArray(), MessageType.RefundHashTimerLockMsg.getTypePrefixBytes(), false); } + /** + * Used for amino serializable message + * */ + public String buildTxPayload(BinanceDexTransactionMessage message) throws IOException, NoSuchAlgorithmException { + if (!AminoSerializable.class.isAssignableFrom(message.getClass())){ + throw new IllegalArgumentException("Class " + message.getClass() + " should also implement AminoSerializable to support amino encoding"); + } + + byte[] typePrefix = WireType.getTypePrefix(message.getClass()); + byte[] msg = amino.encode(((AminoSerializable) message), typePrefix, false); + byte[] signature = encodeSignature(signTx(message)); + byte[] stdTx = encodeStdTx(msg, signature); + return EncodeUtils.bytesToHex(stdTx); + } + } diff --git a/src/main/java/com/binance/dex/api/client/encoding/message/bridge/BindMsgMessage.java b/src/main/java/com/binance/dex/api/client/encoding/message/bridge/BindMsgMessage.java new file mode 100644 index 0000000..c9eb880 --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/encoding/message/bridge/BindMsgMessage.java @@ -0,0 +1,159 @@ +package com.binance.dex.api.client.encoding.message.bridge; + +import com.binance.dex.api.client.encoding.amino.AminoField; +import com.binance.dex.api.client.encoding.amino.AminoSerializable; +import com.binance.dex.api.client.encoding.message.BinanceDexTransactionMessage; +import com.binance.dex.api.client.encoding.message.common.Bech32AddressValue; +import com.binance.dex.api.client.encoding.message.common.EthAddressValue; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import org.apache.commons.lang3.StringUtils; + +import java.util.ArrayList; + +/** + * @author Fitz.Lu + **/ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonPropertyOrder(alphabetic = true) +public class BindMsgMessage implements BinanceDexTransactionMessage, AminoSerializable { + + @JsonProperty(value = "from") + private Bech32AddressValue from; + + @JsonProperty(value = "symbol") + private String symbol; + + @JsonProperty(value = "amount") + private long amount; + + @JsonProperty(value = "contract_address") + private EthAddressValue contractAddress; + + @JsonProperty(value = "contract_decimals") + private int contractDecimal; + + @JsonProperty(value = "expire_time") + private long expireTime; + + public BindMsgMessage() { + } + + public BindMsgMessage(Bech32AddressValue from, String symbol, long amount, EthAddressValue contractAddress, int contractDecimal, long expireTime) { + this.from = from; + this.symbol = symbol; + this.amount = amount; + this.contractAddress = contractAddress; + this.contractDecimal = contractDecimal; + this.expireTime = expireTime; + } + + public Bech32AddressValue getFrom() { + return from; + } + + public void setFrom(Bech32AddressValue from) { + this.from = from; + } + + public String getSymbol() { + return symbol; + } + + public void setSymbol(String symbol) { + this.symbol = symbol; + } + + public long getAmount() { + return amount; + } + + public void setAmount(long amount) { + this.amount = amount; + } + + public EthAddressValue getContractAddress() { + return contractAddress; + } + + public void setContractAddress(EthAddressValue contractAddress) { + this.contractAddress = contractAddress; + } + + public int getContractDecimal() { + return contractDecimal; + } + + public void setContractDecimal(int contractDecimal) { + this.contractDecimal = contractDecimal; + } + + public long getExpireTime() { + return expireTime; + } + + public void setExpireTime(long expireTime) { + this.expireTime = expireTime; + } + + @Override + public void validateBasic() { + if (StringUtils.isEmpty(symbol)){ + throw new IllegalArgumentException("symbol should not be empty"); + } + if (amount <= 0){ + throw new IllegalArgumentException("amount should be larger than 0"); + } + if (contractAddress == null || contractAddress.isDefaultOrEmpty()){ + throw new IllegalArgumentException("contract address should not be empty"); + } + if (contractDecimal < 0){ + throw new IllegalArgumentException("decimal should be no less than 0"); + } + if (expireTime <= 0){ + throw new IllegalArgumentException("expire time should be larger than 0"); + } + } + + @Override + public AminoSerializable newAminoMessage() { + return new BindMsgMessage(); + } + + @Override + public ArrayList> IterateFields() { + return AminoField.newFieldsBuilder() + .addField(Bech32AddressValue.class, from, from == null || from.isDefaultOrEmpty()) + .addField(String.class, symbol, StringUtils.isEmpty(symbol)) + .addField(Long.class, amount, amount == 0) + .addField(EthAddressValue.class, contractAddress, contractAddress == null || contractAddress.isDefaultOrEmpty()) + .addField(Integer.class, contractDecimal, contractDecimal == 0) + .addField(Long.class, expireTime, expireTime == 0) + .build(); + } + + @Override + public void setValueByFieldIndex(int fieldIndex, Object value) { + switch (fieldIndex) { + case 1: + from = ((Bech32AddressValue) value); + break; + case 2: + symbol = ((String) value); + break; + case 3: + amount = ((long) value); + break; + case 4: + contractAddress = ((EthAddressValue) value); + break; + case 5: + contractDecimal = ((int) value); + break; + case 6: + expireTime = ((long) value); + break; + } + } +} diff --git a/src/main/java/com/binance/dex/api/client/encoding/message/bridge/BindStatus.java b/src/main/java/com/binance/dex/api/client/encoding/message/bridge/BindStatus.java new file mode 100644 index 0000000..e1caf54 --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/encoding/message/bridge/BindStatus.java @@ -0,0 +1,13 @@ +package com.binance.dex.api.client.encoding.message.bridge; + +/** + * @author Fitz.Lu + **/ +public class BindStatus { + + public static final int bindStatusSuccess = 0; + public static final int bindStatusRejected = 1; + public static final int bindStatusTimeout = 2; + public static final int bindStatusInvalidParameter = 3; + +} diff --git a/src/main/java/com/binance/dex/api/client/encoding/message/bridge/ClaimMsgMessage.java b/src/main/java/com/binance/dex/api/client/encoding/message/bridge/ClaimMsgMessage.java new file mode 100644 index 0000000..ddecd3c --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/encoding/message/bridge/ClaimMsgMessage.java @@ -0,0 +1,121 @@ +package com.binance.dex.api.client.encoding.message.bridge; + +import com.binance.dex.api.client.encoding.amino.AminoField; +import com.binance.dex.api.client.encoding.amino.AminoSerializable; +import com.binance.dex.api.client.encoding.message.BinanceDexTransactionMessage; +import com.binance.dex.api.client.encoding.message.common.Bech32AddressValue; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + +import java.util.ArrayList; + +/** + * @author Fitz.Lu + **/ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonPropertyOrder(alphabetic = true) +public class ClaimMsgMessage implements BinanceDexTransactionMessage, AminoSerializable { + + @JsonProperty(value = "chain_id") + private int chainId; + + @JsonProperty(value = "sequence") + private long sequence; + + @JsonProperty(value = "payload") + private byte[] payload; + + @JsonProperty(value = "validator_address") + private Bech32AddressValue validatorAddress; + + public ClaimMsgMessage() { + } + + public ClaimMsgMessage(int chainId, long sequence, byte[] payload, Bech32AddressValue validatorAddress) { + this.chainId = chainId; + this.sequence = sequence; + this.payload = payload; + this.validatorAddress = validatorAddress; + } + + public int getChainId() { + return chainId; + } + + public void setChainId(int chainId) { + this.chainId = chainId; + } + + public long getSequence() { + return sequence; + } + + public void setSequence(long sequence) { + this.sequence = sequence; + } + + public byte[] getPayload() { + return payload; + } + + public void setPayload(byte[] payload) { + this.payload = payload; + } + + public Bech32AddressValue getValidatorAddress() { + return validatorAddress; + } + + public void setValidatorAddress(Bech32AddressValue validatorAddress) { + this.validatorAddress = validatorAddress; + } + + @Override + public void validateBasic() { + if (!ClaimTypes.IsValidClaimType(chainId)) { + throw new IllegalArgumentException(String.format("claim type %s does not exist, see class ClaimTypes", chainId)); + } + if (sequence < 0) { + throw new IllegalArgumentException("sequence should not be less than 0"); + } + if (payload == null || payload.length == 0) { + throw new IllegalArgumentException("payload should not be empty"); + } + } + + @Override + public AminoSerializable newAminoMessage() { + return new ClaimMsgMessage(); + } + + @Override + public ArrayList> IterateFields() { + return AminoField.newFieldsBuilder() + .addField(Integer.class, chainId, false) + .addField(Long.class, sequence, false) + .addField(byte[].class, payload, (payload == null || payload.length == 0)) + .addField(Bech32AddressValue.class, validatorAddress, validatorAddress == null || validatorAddress.isDefaultOrEmpty()) + .build(); + } + + @Override + public void setValueByFieldIndex(int fieldIndex, Object value) { + switch (fieldIndex) { + case 1: + chainId = ((int) value); + break; + case 2: + sequence = ((long) value); + break; + case 3: + payload = (byte[]) value; + break; + case 4: + validatorAddress = (Bech32AddressValue) value; + break; + default: + break; + } + } +} diff --git a/src/main/java/com/binance/dex/api/client/encoding/message/bridge/ClaimType.java b/src/main/java/com/binance/dex/api/client/encoding/message/bridge/ClaimType.java new file mode 100644 index 0000000..ed9ec21 --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/encoding/message/bridge/ClaimType.java @@ -0,0 +1,14 @@ +package com.binance.dex.api.client.encoding.message.bridge; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * @author Fitz.Lu + **/ +@Target(ElementType.FIELD) +@Retention(RetentionPolicy.SOURCE) +public @interface ClaimType { +} diff --git a/src/main/java/com/binance/dex/api/client/encoding/message/bridge/ClaimTypes.java b/src/main/java/com/binance/dex/api/client/encoding/message/bridge/ClaimTypes.java new file mode 100644 index 0000000..3021a28 --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/encoding/message/bridge/ClaimTypes.java @@ -0,0 +1,42 @@ +package com.binance.dex.api.client.encoding.message.bridge; + +import java.util.HashMap; +import java.util.Map; + +/** + * @author Fitz.Lu + **/ +public class ClaimTypes { + + public static final int ClaimTypeSkipSequence = 0x1; + public static final int ClaimTypeUpdateBind = 0x2; + public static final int ClaimTypeUpdateTransferOut = 0x3; + public static final int ClaimTypeTransferIn = 0x4; + + private static final String ClaimTypeSkipSequenceName = "SkipSequence"; + private static final String ClaimTypeUpdateBindName = "UpdateBind"; + private static final String ClaimTypeUpdateTransferOutName = "UpdateTransferOut"; + private static final String ClaimTypeTransferInName = "TransferIn"; + + private static final Map claimTypeToName; + private static final Map claimNameToType; + + static { + claimTypeToName = new HashMap<>(); + claimTypeToName.put(ClaimTypeSkipSequence, ClaimTypeSkipSequenceName); + claimTypeToName.put(ClaimTypeUpdateBind, ClaimTypeUpdateBindName); + claimTypeToName.put(ClaimTypeUpdateTransferOut, ClaimTypeUpdateTransferOutName); + claimTypeToName.put(ClaimTypeTransferIn, ClaimTypeTransferInName); + + claimNameToType = new HashMap<>(); + claimNameToType.put(ClaimTypeSkipSequenceName, ClaimTypeSkipSequence); + claimNameToType.put(ClaimTypeUpdateBindName, ClaimTypeUpdateBind); + claimNameToType.put(ClaimTypeUpdateTransferOutName, ClaimTypeUpdateTransferOut); + claimNameToType.put(ClaimTypeTransferInName, ClaimTypeTransferIn); + } + + public static boolean IsValidClaimType(int type){ + return claimTypeToName.containsKey(type); + } + +} diff --git a/src/main/java/com/binance/dex/api/client/encoding/message/bridge/DBProphecy.java b/src/main/java/com/binance/dex/api/client/encoding/message/bridge/DBProphecy.java new file mode 100644 index 0000000..f4919eb --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/encoding/message/bridge/DBProphecy.java @@ -0,0 +1,84 @@ +package com.binance.dex.api.client.encoding.message.bridge; + +import com.binance.dex.api.client.encoding.ByteUtil; +import com.binance.dex.api.client.encoding.amino.AminoField; +import com.binance.dex.api.client.encoding.amino.AminoSerializable; +import org.apache.commons.lang3.StringUtils; + +import java.util.ArrayList; + +/** + * @author Fitz.Lu + **/ +public class DBProphecy implements AminoSerializable { + + private String id; + + private StatusValue status; + + private byte[] validatorClaims; + + public DBProphecy() { + } + + public DBProphecy(String id, StatusValue status, byte[] validatorClaims) { + this.id = id; + this.status = status; + this.validatorClaims = validatorClaims; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public StatusValue getStatus() { + return status; + } + + public void setStatus(StatusValue status) { + this.status = status; + } + + public byte[] getValidatorClaims() { + return validatorClaims; + } + + public void setValidatorClaims(byte[] validatorClaims) { + this.validatorClaims = validatorClaims; + } + + @Override + public AminoSerializable newAminoMessage() { + return new DBProphecy(); + } + + @Override + public ArrayList> IterateFields() { + return AminoField.newFieldsBuilder() + .addField(String.class, id, StringUtils.isEmpty(id)) + .addField(StatusValue.class, status, status == null) + .addField(byte[].class, validatorClaims, ByteUtil.isEmpty(validatorClaims)) + .build(); + } + + @Override + public void setValueByFieldIndex(int fieldIndex, Object value) { + switch (fieldIndex) { + case 1: + id = ((String) value); + break; + case 2: + status = ((StatusValue) value); + break; + case 3: + validatorClaims = ((byte[]) value); + break; + default: + break; + } + } +} diff --git a/src/main/java/com/binance/dex/api/client/encoding/message/bridge/RefundReason.java b/src/main/java/com/binance/dex/api/client/encoding/message/bridge/RefundReason.java new file mode 100644 index 0000000..09f41f7 --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/encoding/message/bridge/RefundReason.java @@ -0,0 +1,13 @@ +package com.binance.dex.api.client.encoding.message.bridge; + +/** + * @author Fitz.Lu + **/ +public class RefundReason { + + public static final int unboundToken = 1; + public static final int timeout = 2; + public static final int insufficientBalance = 3; + public static final int unknown = 4; + +} diff --git a/src/main/java/com/binance/dex/api/client/encoding/message/bridge/StatusValue.java b/src/main/java/com/binance/dex/api/client/encoding/message/bridge/StatusValue.java new file mode 100644 index 0000000..2cd8ef9 --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/encoding/message/bridge/StatusValue.java @@ -0,0 +1,58 @@ +package com.binance.dex.api.client.encoding.message.bridge; + +import com.binance.dex.api.client.encoding.amino.AminoField; +import com.binance.dex.api.client.encoding.amino.AminoSerializable; +import org.apache.commons.lang3.StringUtils; + +import java.util.ArrayList; + +/** + * @author Fitz.Lu + **/ +public class StatusValue implements AminoSerializable { + + private int text; + + private String finalClaim; + + public int getText() { + return text; + } + + public void setText(int text) { + this.text = text; + } + + public String getFinalClaim() { + return finalClaim; + } + + public void setFinalClaim(String finalClaim) { + this.finalClaim = finalClaim; + } + + @Override + public AminoSerializable newAminoMessage() { + return new StatusValue(); + } + + @Override + public ArrayList> IterateFields() { + return AminoField.newFieldsBuilder() + .addField(Integer.class, text, false) + .addField(String.class, finalClaim, StringUtils.isEmpty(finalClaim)) + .build(); + } + + @Override + public void setValueByFieldIndex(int fieldIndex, Object value) { + switch (fieldIndex) { + case 1: + text = ((Integer) value); + break; + case 2: + finalClaim = ((String) value); + break; + } + } +} diff --git a/src/main/java/com/binance/dex/api/client/encoding/message/bridge/TransferInClaimMessage.java b/src/main/java/com/binance/dex/api/client/encoding/message/bridge/TransferInClaimMessage.java new file mode 100644 index 0000000..c693249 --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/encoding/message/bridge/TransferInClaimMessage.java @@ -0,0 +1,93 @@ +package com.binance.dex.api.client.encoding.message.bridge; + +import com.binance.dex.api.client.encoding.message.common.CoinValue; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + +import java.util.List; + +/** + * @author Fitz.Lu + **/ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonPropertyOrder(alphabetic = true) +public class TransferInClaimMessage { + + @JsonProperty(value = "contract_address") + private String contractAddress; + + @JsonProperty(value = "refund_addresses") + private List refundAddresses; + + @JsonProperty(value = "receiver_addresses") + private List receiverAddresses; + + @JsonProperty(value = "amounts") + private List amounts; + + @JsonProperty(value = "symbol") + private String symbol; + + @JsonProperty(value = "relay_fee") + private CoinValue relayFee; + + @JsonProperty(value = "expire_time") + private long expireTime; + + public String getContractAddress() { + return contractAddress; + } + + public void setContractAddress(String contractAddress) { + this.contractAddress = contractAddress; + } + + public List getRefundAddresses() { + return refundAddresses; + } + + public void setRefundAddresses(List refundAddresses) { + this.refundAddresses = refundAddresses; + } + + public List getReceiverAddresses() { + return receiverAddresses; + } + + public void setReceiverAddresses(List receiverAddresses) { + this.receiverAddresses = receiverAddresses; + } + + public List getAmounts() { + return amounts; + } + + public void setAmounts(List amounts) { + this.amounts = amounts; + } + + public String getSymbol() { + return symbol; + } + + public void setSymbol(String symbol) { + this.symbol = symbol; + } + + public CoinValue getRelayFee() { + return relayFee; + } + + public void setRelayFee(CoinValue relayFee) { + this.relayFee = relayFee; + } + + public long getExpireTime() { + return expireTime; + } + + public void setExpireTime(long expireTime) { + this.expireTime = expireTime; + } +} diff --git a/src/main/java/com/binance/dex/api/client/encoding/message/bridge/TransferOutMsgMessage.java b/src/main/java/com/binance/dex/api/client/encoding/message/bridge/TransferOutMsgMessage.java new file mode 100644 index 0000000..c512793 --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/encoding/message/bridge/TransferOutMsgMessage.java @@ -0,0 +1,112 @@ +package com.binance.dex.api.client.encoding.message.bridge; + +import com.binance.dex.api.client.encoding.amino.AminoField; +import com.binance.dex.api.client.encoding.amino.AminoSerializable; +import com.binance.dex.api.client.encoding.message.BinanceDexTransactionMessage; +import com.binance.dex.api.client.encoding.message.common.Bech32AddressValue; +import com.binance.dex.api.client.encoding.message.common.CoinValue; +import com.binance.dex.api.client.encoding.message.common.EthAddressValue; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + +import java.util.ArrayList; + +/** + * @author Fitz.Lu + **/ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonPropertyOrder(alphabetic = true) +public class TransferOutMsgMessage implements BinanceDexTransactionMessage, AminoSerializable { + + @JsonProperty(value = "from") + private Bech32AddressValue from; + + @JsonProperty(value = "to") + private EthAddressValue toAddress; + + @JsonProperty(value = "amount") + private CoinValue amount; + + @JsonProperty(value = "expire_time") + private long expireTime; + + public Bech32AddressValue getFrom() { + return from; + } + + public void setFrom(Bech32AddressValue from) { + this.from = from; + } + + public EthAddressValue getToAddress() { + return toAddress; + } + + public void setToAddress(EthAddressValue toAddress) { + this.toAddress = toAddress; + } + + public CoinValue getAmount() { + return amount; + } + + public void setAmount(CoinValue amount) { + this.amount = amount; + } + + public long getExpireTime() { + return expireTime; + } + + public void setExpireTime(long expireTime) { + this.expireTime = expireTime; + } + + @Override + public void validateBasic() { + if (toAddress == null || toAddress.isDefaultOrEmpty()){ + throw new IllegalArgumentException("to address should not be empty"); + } + if (amount == null || amount.getAmount() <= 0){ + throw new IllegalArgumentException("amount should be positive"); + } + if (expireTime <= 0){ + throw new IllegalArgumentException("expire time should be larger than 0"); + } + } + + @Override + public AminoSerializable newAminoMessage() { + return new TransferOutMsgMessage(); + } + + @Override + public ArrayList> IterateFields() { + return AminoField.newFieldsBuilder() + .addField(Bech32AddressValue.class, from, from == null) + .addField(EthAddressValue.class, toAddress, toAddress == null) + .addField(CoinValue.class, amount, amount == null) + .addField(Long.class, expireTime, expireTime == 0) + .build(); + } + + @Override + public void setValueByFieldIndex(int fieldIndex, Object value) { + switch (fieldIndex) { + case 1: + from = ((Bech32AddressValue) value); + break; + case 2: + toAddress = ((EthAddressValue) value); + break; + case 3: + amount = ((CoinValue) value); + break; + case 4: + expireTime = ((long) value); + break; + } + } + +} diff --git a/src/main/java/com/binance/dex/api/client/encoding/message/bridge/UnbindMsgMessage.java b/src/main/java/com/binance/dex/api/client/encoding/message/bridge/UnbindMsgMessage.java new file mode 100644 index 0000000..891947f --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/encoding/message/bridge/UnbindMsgMessage.java @@ -0,0 +1,79 @@ +package com.binance.dex.api.client.encoding.message.bridge; + +import com.binance.dex.api.client.encoding.amino.AminoField; +import com.binance.dex.api.client.encoding.amino.AminoSerializable; +import com.binance.dex.api.client.encoding.message.BinanceDexTransactionMessage; +import com.binance.dex.api.client.encoding.message.common.Bech32AddressValue; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import org.apache.commons.lang3.StringUtils; + +import java.util.ArrayList; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonPropertyOrder(alphabetic = true) +public class UnbindMsgMessage implements BinanceDexTransactionMessage, AminoSerializable { + + @JsonProperty(value = "from") + private Bech32AddressValue from; + + @JsonProperty(value = "symbol") + private String symbol; + + public UnbindMsgMessage() { + } + + public UnbindMsgMessage(Bech32AddressValue from, String symbol) { + this.from = from; + this.symbol = symbol; + } + + @Override + public AminoSerializable newAminoMessage() { + return new UnbindMsgMessage(); + } + + @Override + public ArrayList> IterateFields() { + return AminoField.newFieldsBuilder() + .addField(Bech32AddressValue.class, from, from == null || from.isDefaultOrEmpty()) + .addField(String.class, symbol, StringUtils.isEmpty(symbol)) + .build(); + } + + @Override + public void setValueByFieldIndex(int fieldIndex, Object value) { + switch (fieldIndex) { + case 1: + from = ((Bech32AddressValue) value); + break; + case 2: + symbol = ((String) value); + break; + } + } + + @Override + public void validateBasic() { + if (StringUtils.isEmpty(symbol)){ + throw new IllegalArgumentException("symbol should not be empty"); + } + } + + public Bech32AddressValue getFrom() { + return from; + } + + public void setFrom(Bech32AddressValue from) { + this.from = from; + } + + public String getSymbol() { + return symbol; + } + + public void setSymbol(String symbol) { + this.symbol = symbol; + } +} diff --git a/src/main/java/com/binance/dex/api/client/encoding/message/bridge/UpdateBindClaimMessage.java b/src/main/java/com/binance/dex/api/client/encoding/message/bridge/UpdateBindClaimMessage.java new file mode 100644 index 0000000..6a2952e --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/encoding/message/bridge/UpdateBindClaimMessage.java @@ -0,0 +1,84 @@ +package com.binance.dex.api.client.encoding.message.bridge; + +import com.binance.dex.api.client.encoding.amino.AminoField; +import com.binance.dex.api.client.encoding.amino.AminoSerializable; +import com.binance.dex.api.client.encoding.message.BinanceDexTransactionMessage; +import com.binance.dex.api.client.encoding.message.common.EthAddressValue; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import org.apache.commons.lang3.StringUtils; + +import java.util.ArrayList; + +/** + * @author Fitz.Lu + **/ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonPropertyOrder(alphabetic = true) +public class UpdateBindClaimMessage implements BinanceDexTransactionMessage, AminoSerializable { + + @JsonProperty(value = "status") + private int status; + + @JsonProperty(value = "symbol") + private String symbol; + + @JsonProperty(value = "contract_address") + private EthAddressValue contractAddress; + + public int getStatus() { + return status; + } + + public void setStatus(int status) { + this.status = status; + } + + public String getSymbol() { + return symbol; + } + + public void setSymbol(String symbol) { + this.symbol = symbol; + } + + public EthAddressValue getContractAddress() { + return contractAddress; + } + + public void setContractAddress(EthAddressValue contractAddress) { + this.contractAddress = contractAddress; + } + + @Override + public AminoSerializable newAminoMessage() { + return new UpdateBindClaimMessage(); + } + + @Override + public ArrayList> IterateFields() { + return AminoField.newFieldsBuilder() + .addField(Integer.class, status, false) + .addField(String.class, symbol, StringUtils.isEmpty(symbol)) + .addField(EthAddressValue.class, contractAddress, contractAddress == null || contractAddress.isDefaultOrEmpty()) + .build(); + } + + @Override + public void setValueByFieldIndex(int fieldIndex, Object value) { + switch (fieldIndex) { + case 1: + status = ((int) value); + break; + case 2: + symbol = ((String) value); + break; + case 3: + contractAddress = ((EthAddressValue) value); + break; + default: + break; + } + } +} diff --git a/src/main/java/com/binance/dex/api/client/encoding/message/bridge/UpdateTransferOutClaimMessage.java b/src/main/java/com/binance/dex/api/client/encoding/message/bridge/UpdateTransferOutClaimMessage.java new file mode 100644 index 0000000..17c549b --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/encoding/message/bridge/UpdateTransferOutClaimMessage.java @@ -0,0 +1,84 @@ +package com.binance.dex.api.client.encoding.message.bridge; + +import com.binance.dex.api.client.encoding.amino.AminoField; +import com.binance.dex.api.client.encoding.amino.AminoSerializable; +import com.binance.dex.api.client.encoding.message.BinanceDexTransactionMessage; +import com.binance.dex.api.client.encoding.message.common.Bech32AddressValue; +import com.binance.dex.api.client.encoding.message.common.CoinValue; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + +import java.util.ArrayList; + +/** + * @author Fitz.Lu + **/ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonPropertyOrder(alphabetic = true) +public class UpdateTransferOutClaimMessage implements BinanceDexTransactionMessage, AminoSerializable { + + @JsonProperty(value = "refund_address") + private Bech32AddressValue refundAddress; + + @JsonProperty(value = "amount") + private CoinValue amount; + + @JsonProperty(value = "refund_reason") + private int refundReason; + + public Bech32AddressValue getRefundAddress() { + return refundAddress; + } + + public void setRefundAddress(Bech32AddressValue refundAddress) { + this.refundAddress = refundAddress; + } + + public CoinValue getAmount() { + return amount; + } + + public void setAmount(CoinValue amount) { + this.amount = amount; + } + + public int getRefundReason() { + return refundReason; + } + + public void setRefundReason(int refundReason) { + this.refundReason = refundReason; + } + + @Override + public AminoSerializable newAminoMessage() { + return new UpdateTransferOutClaimMessage(); + } + + @Override + public ArrayList> IterateFields() { + return AminoField.newFieldsBuilder() + .addField(Bech32AddressValue.class, refundAddress, refundAddress == null || refundAddress.isDefaultOrEmpty()) + .addField(CoinValue.class, amount, amount == null) + .addField(Integer.class, refundReason, false) + .build(); + } + + @Override + public void setValueByFieldIndex(int fieldIndex, Object value) { + switch (fieldIndex) { + case 1: + refundAddress = ((Bech32AddressValue) value); + break; + case 2: + amount = ((CoinValue) value); + break; + case 3: + refundReason = ((int) value); + break; + default: + break; + } + } +} diff --git a/src/main/java/com/binance/dex/api/client/encoding/message/common/Bech32AddressValue.java b/src/main/java/com/binance/dex/api/client/encoding/message/common/Bech32AddressValue.java new file mode 100644 index 0000000..fafb951 --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/encoding/message/common/Bech32AddressValue.java @@ -0,0 +1,102 @@ +package com.binance.dex.api.client.encoding.message.common; + +import com.binance.dex.api.client.encoding.Bech32; +import com.binance.dex.api.client.encoding.ByteUtil; +import com.binance.dex.api.client.encoding.Crypto; +import com.binance.dex.api.client.encoding.amino.AminoCustomSerialized; +import com.binance.dex.api.client.encoding.amino.WireType; +import com.binance.dex.api.client.encoding.serializer.Bech32AddressValueToStringSerializer; +import com.binance.dex.api.client.rlp.RlpDecodable; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.google.protobuf.CodedInputStream; +import com.google.protobuf.CodedOutputStream; + +import java.io.IOException; + +/** + * @author Fitz.Lu + **/ +@JsonSerialize(using = Bech32AddressValueToStringSerializer.class) +public class Bech32AddressValue implements AminoCustomSerialized, RlpDecodable { + + private String hrp; + + private byte[] raw; + + public static Bech32AddressValue fromBech32String(String address){ + return new Bech32AddressValue(address); + } + + public static Bech32AddressValue fromBech32StringWithNewHrp(String originalAddress, String hrp){ + return new Bech32AddressValue(originalAddress, hrp); + } + + public Bech32AddressValue() { } + + public Bech32AddressValue(String address) { + this.hrp = Bech32.decode(address).getHrp(); + this.raw = Crypto.decodeAddress(address); + } + + public Bech32AddressValue(String originalAddress, String hrp){ + this.hrp = hrp; + this.raw = Crypto.decodeAddress(originalAddress); + } + + public String getHrp() { + return hrp; + } + + public void setHrp(String hrp) { + this.hrp = hrp; + } + + public void setRaw(byte[] raw) { + this.raw = raw; + } + + public byte[] getRaw(){ + return raw; + } + + @Override + public AminoCustomSerialized newAminoSerInstance() { + return new Bech32AddressValue(); + } + + @Override + public boolean isDefaultOrEmpty() { + return ByteUtil.isEmpty(raw); + } + + @Override + public int getWireType() { + return WireType.LENGTH_DELIMITED; + } + + @Override + public void encode(CodedOutputStream outputStream) throws IOException { + if (raw != null) { + outputStream.writeByteArrayNoTag(raw); + } + } + + @Override + public void decode(CodedInputStream inputStream) throws IOException { + raw = inputStream.readByteArray(); + } + + @Override + public int getSerializedSize() { + if (ByteUtil.isEmpty(raw)) { + return 0; + }else{ + return CodedOutputStream.computeByteArraySizeNoTag(raw); + } + } + + @Override + public void decode(byte[] raw, Object superInstance) { + this.raw = raw; + } +} diff --git a/src/main/java/com/binance/dex/api/client/encoding/message/common/CoinValue.java b/src/main/java/com/binance/dex/api/client/encoding/message/common/CoinValue.java new file mode 100644 index 0000000..9002d64 --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/encoding/message/common/CoinValue.java @@ -0,0 +1,84 @@ +package com.binance.dex.api.client.encoding.message.common; + +import com.binance.dex.api.client.encoding.amino.AminoField; +import com.binance.dex.api.client.encoding.amino.AminoSerializable; +import com.binance.dex.api.client.encoding.message.Token; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import org.apache.commons.lang3.StringUtils; + +import java.util.ArrayList; + +/** + * @author Fitz.Lu + **/ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonPropertyOrder(alphabetic = true) +public class CoinValue implements AminoSerializable { + + @JsonProperty(value = "denom") + private String denom; + + @JsonProperty(value = "amount") + private long amount; + + public CoinValue() { + } + + public CoinValue(String denom, Long amount) { + this.denom = denom; + this.amount = amount; + } + + public Token toToken(){ + Token token = new Token(); + token.setDenom(denom); + token.setAmount(amount); + return token; + } + + public String getDenom() { + return denom; + } + + public void setDenom(String denom) { + this.denom = denom; + } + + public long getAmount() { + return amount; + } + + public void setAmount(long amount) { + this.amount = amount; + } + + @Override + public AminoSerializable newAminoMessage() { + return new CoinValueStr(); + } + + @Override + public ArrayList> IterateFields() { + return AminoField.newFieldsBuilder() + .addField(String.class, denom, StringUtils.isEmpty(denom)) + .addField(Long.class, amount, amount == 0) + .build(); + } + + @Override + public void setValueByFieldIndex(int fieldIndex, Object value) { + switch (fieldIndex) { + case 1: + denom = ((String) value); + break; + case 2: + amount = ((long) value); + break; + default: + break; + } + } + +} diff --git a/src/main/java/com/binance/dex/api/client/encoding/message/common/CoinValueStr.java b/src/main/java/com/binance/dex/api/client/encoding/message/common/CoinValueStr.java new file mode 100644 index 0000000..84613ec --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/encoding/message/common/CoinValueStr.java @@ -0,0 +1,86 @@ +package com.binance.dex.api.client.encoding.message.common; + +import com.binance.dex.api.client.encoding.amino.AminoField; +import com.binance.dex.api.client.encoding.amino.AminoSerializable; +import com.binance.dex.api.client.encoding.message.Token; +import com.binance.dex.api.client.encoding.serializer.LongToStringSerializer; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import org.apache.commons.lang3.StringUtils; + +import java.util.ArrayList; + +/** + * @author Fitz.Lu + **/ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonPropertyOrder(alphabetic = true) +public class CoinValueStr implements AminoSerializable { + + @JsonProperty(value = "denom") + private String denom; + + @JsonProperty(value = "amount") + @JsonSerialize(using = LongToStringSerializer.class) + private long amount; + + public CoinValueStr() { + } + + public CoinValueStr(String denom, Long amount) { + this.denom = denom; + this.amount = amount; + } + + public Token toToken(){ + Token token = new Token(); + token.setDenom(denom); + token.setAmount(amount); + return token; + } + + public String getDenom() { + return denom; + } + + public void setDenom(String denom) { + this.denom = denom; + } + + public long getAmount() { + return amount; + } + + public void setAmount(long amount) { + this.amount = amount; + } + + @Override + public AminoSerializable newAminoMessage() { + return new CoinValueStr(); + } + + @Override + public ArrayList> IterateFields() { + return AminoField.newFieldsBuilder() + .addField(String.class, denom, StringUtils.isEmpty(denom)) + .addField(Long.class, amount, amount == 0) + .build(); + } + + @Override + public void setValueByFieldIndex(int fieldIndex, Object value) { + switch (fieldIndex) { + case 1: + denom = ((String) value); + break; + case 2: + amount = ((long) value); + break; + default: + break; + } + } +} diff --git a/src/main/java/com/binance/dex/api/client/encoding/message/common/Dec.java b/src/main/java/com/binance/dex/api/client/encoding/message/common/Dec.java new file mode 100644 index 0000000..32e9f50 --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/encoding/message/common/Dec.java @@ -0,0 +1,61 @@ +package com.binance.dex.api.client.encoding.message.common; + +import com.binance.dex.api.client.encoding.amino.AminoCustomSerialized; +import com.binance.dex.api.client.encoding.amino.WireType; +import com.google.protobuf.CodedInputStream; +import com.google.protobuf.CodedOutputStream; + +import java.io.IOException; + +/** + * @author Fitz.Lu + **/ +@Deprecated +public class Dec implements AminoCustomSerialized { + + private long value; + + public long getValue() { + return value; + } + + public void setValue(long value) { + this.value = value; + } + + public static Dec newInstance(long v){ + Dec dec = new Dec(); + dec.setValue(v); + return dec; + } + + @Override + public AminoCustomSerialized newAminoSerInstance() { + return new Dec(); + } + + @Override + public boolean isDefaultOrEmpty() { + return value == 0L; + } + + @Override + public int getWireType() { + return WireType.LENGTH_DELIMITED; + } + + @Override + public void encode(CodedOutputStream outputStream) throws IOException { + outputStream.writeInt64NoTag(value); + } + + @Override + public void decode(CodedInputStream inputStream) throws IOException { + value = inputStream.readInt64(); + } + + @Override + public int getSerializedSize() { + return CodedOutputStream.computeInt64SizeNoTag(value); + } +} diff --git a/src/main/java/com/binance/dex/api/client/encoding/message/common/EthAddressValue.java b/src/main/java/com/binance/dex/api/client/encoding/message/common/EthAddressValue.java new file mode 100644 index 0000000..e7ceefe --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/encoding/message/common/EthAddressValue.java @@ -0,0 +1,109 @@ +package com.binance.dex.api.client.encoding.message.common; + +import com.binance.dex.api.client.encoding.EncodeUtils; +import com.binance.dex.api.client.encoding.amino.AminoCustomSerialized; +import com.binance.dex.api.client.encoding.amino.WireType; +import com.binance.dex.api.client.encoding.serializer.EthAddressValueToStringSerializer; +import com.binance.dex.api.client.rlp.RlpDecodable; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.google.protobuf.CodedInputStream; +import com.google.protobuf.CodedOutputStream; +import org.apache.commons.lang3.StringUtils; +import org.bouncycastle.util.encoders.Hex; + +import java.io.IOException; + +/** + * @author Fitz.Lu + **/ +@JsonSerialize(using = EthAddressValueToStringSerializer.class) +public class EthAddressValue implements AminoCustomSerialized, RlpDecodable { + + private String address; + + public static EthAddressValue from(String addr){ + return new EthAddressValue(toChecksumAddress(addr)); + } + + public EthAddressValue() { + } + + public EthAddressValue(String address) { + this.address = address; + } + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + + @Override + public AminoCustomSerialized newAminoSerInstance() { + return new EthAddressValue(); + } + + @Override + public boolean isDefaultOrEmpty() { + return StringUtils.isEmpty(address); + } + + @Override + public void encode(CodedOutputStream outputStream) throws IOException { + outputStream.writeByteArrayNoTag(getValueBytes()); + } + + @Override + public int getWireType() { + return WireType.LENGTH_DELIMITED; + } + + @Override + public void decode(CodedInputStream inputStream) throws IOException { + byte[] bytes = inputStream.readByteArray(); + address = Hex.toHexString(bytes); + address = "0x" + address; + } + + @Override + public int getSerializedSize() { + if (StringUtils.isEmpty(address)){ + return 0; + }else{ + return CodedOutputStream.computeByteArraySizeNoTag(getValueBytes()); + } + } + + private byte[] getValueBytes(){ + String addr = address; + if (addr.startsWith("0x")){ + addr = address.substring(2); + } + return Hex.decode(addr); + } + + @Override + public void decode(byte[] raw, Object superInstance) { + address = Hex.toHexString(raw); + address = "0x" + address; + } + + public static String toChecksumAddress(String address) { + String lowercaseAddress = EncodeUtils.cleanHexPrefix(address).toLowerCase(); + String addressHash = EncodeUtils.cleanHexPrefix(EncodeUtils.sha3String(lowercaseAddress)); + StringBuilder result = new StringBuilder(lowercaseAddress.length() + 2); + result.append("0x"); + + for(int i = 0; i < lowercaseAddress.length(); ++i) { + if (Integer.parseInt(String.valueOf(addressHash.charAt(i)), 16) >= 8) { + result.append(String.valueOf(lowercaseAddress.charAt(i)).toUpperCase()); + } else { + result.append(lowercaseAddress.charAt(i)); + } + } + + return result.toString(); + } +} diff --git a/src/main/java/com/binance/dex/api/client/encoding/message/sidechain/SideChainIds.java b/src/main/java/com/binance/dex/api/client/encoding/message/sidechain/SideChainIds.java new file mode 100644 index 0000000..eef2139 --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/encoding/message/sidechain/SideChainIds.java @@ -0,0 +1,10 @@ +package com.binance.dex.api.client.encoding.message.sidechain; + +/** + * @author Fitz.Lu + **/ +public class SideChainIds { + + public static final String RIALTO = "rialto"; + +} diff --git a/src/main/java/com/binance/dex/api/client/encoding/message/sidechain/query/BaseQueryParams.java b/src/main/java/com/binance/dex/api/client/encoding/message/sidechain/query/BaseQueryParams.java new file mode 100644 index 0000000..fe72e8f --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/encoding/message/sidechain/query/BaseQueryParams.java @@ -0,0 +1,27 @@ +package com.binance.dex.api.client.encoding.message.sidechain.query; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * @author Fitz.Lu + **/ +public class BaseQueryParams { + + @JsonProperty(value = "SideChainId") + protected String sideChainId; + + public BaseQueryParams() { + } + + public BaseQueryParams(String sideChainId) { + this.sideChainId = sideChainId; + } + + public String getSideChainId() { + return sideChainId; + } + + public void setSideChainId(String sideChainId) { + this.sideChainId = sideChainId; + } +} diff --git a/src/main/java/com/binance/dex/api/client/encoding/message/sidechain/query/BechValidator.java b/src/main/java/com/binance/dex/api/client/encoding/message/sidechain/query/BechValidator.java new file mode 100644 index 0000000..9244f23 --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/encoding/message/sidechain/query/BechValidator.java @@ -0,0 +1,316 @@ +package com.binance.dex.api.client.encoding.message.sidechain.query; + +import com.binance.dex.api.client.domain.stake.Commission; +import com.binance.dex.api.client.domain.stake.Description; +import com.binance.dex.api.client.domain.stake.sidechain.SideChainValidator; +import com.binance.dex.api.client.encoding.Crypto; +import com.binance.dex.api.client.encoding.amino.Amino; +import com.binance.dex.api.client.encoding.message.sidechain.value.DescriptionValue; +import com.fasterxml.jackson.annotation.JsonProperty; +import org.apache.commons.lang3.StringUtils; + +/** + * @author Fitz.Lu + **/ +public class BechValidator { + + static class CommissionForDecode { + + @JsonProperty(value = "rate") + private long rate; + + @JsonProperty(value = "max_rate") + private long maxRate; + + @JsonProperty(value = "max_change_rate") + private long maxChangeRate; + + @JsonProperty(value = "update_time") + private String updateTime; + + public CommissionForDecode() { + } + + public long getRate() { + return rate; + } + + public void setRate(long rate) { + this.rate = rate; + } + + public long getMaxRate() { + return maxRate; + } + + public void setMaxRate(long maxRate) { + this.maxRate = maxRate; + } + + public long getMaxChangeRate() { + return maxChangeRate; + } + + public void setMaxChangeRate(long maxChangeRate) { + this.maxChangeRate = maxChangeRate; + } + + public String getUpdateTime() { + return updateTime; + } + + public void setUpdateTime(String updateTime) { + this.updateTime = updateTime; + } + } + + @JsonProperty(value = "fee_addr") + private String feeAddr; + + @JsonProperty(value = "operator_address") + private String operatorAddr; + + @JsonProperty(value = "consensus_pubkey") + private String consPubKey; + + @JsonProperty(value = "jailed") + private boolean jailed; + + @JsonProperty(value = "status") + private int status; + + @JsonProperty(value = "tokens") + private long tokens; + + @JsonProperty(value = "delegator_shares") + private long delegatorShares; + + @JsonProperty(value = "description") + private DescriptionValue description; + + @JsonProperty(value = "bond_height") + private long bondHeight; + + @JsonProperty(value = "bond_intra_tx_counter") + private int bondIntraTxCounter; + + @JsonProperty(value = "unbonding_height") + private long unBondingHeight; + + @JsonProperty(value = "unbonding_time") + private String unBondingMinTime; + + @JsonProperty(value = "commission") + private CommissionForDecode commission; + + @JsonProperty(value = "distribution_addr") + private String distributionAddr; + + @JsonProperty(value = "side_chain_id") + private String sideChainId; + + @JsonProperty(value = "side_cons_addr") + private String sideConsAddr; + + @JsonProperty(value = "side_fee_addr") + private String sideFeeAddr; + + public BechValidator() { + } + + + public SideChainValidator toSideChainValidator() { + SideChainValidator validator = new SideChainValidator(); + if (feeAddr != null) { + validator.setFeeAddr(feeAddr); + } + if (operatorAddr != null) { + validator.setOperatorAddr(operatorAddr); + } + if (consPubKey != null) { + try { + validator.setConsPubKey(Amino.getByteArrayAfterTypePrefix(consPubKey.getBytes())); + }catch (IllegalStateException e){ + validator.setConsPubKey(consPubKey.getBytes()); + } + } + validator.setJailed(jailed); + validator.setStatus(status); + validator.setTokens(tokens); + validator.setDelegatorShares(delegatorShares); + + Description descript = new Description(); + if (description != null) { + descript.setMoniker(description.getMoniker()); + descript.setWebsite(description.getWebsite()); + descript.setDetails(description.getDetails()); + descript.setIdentity(description.getIdentity()); + } + validator.setDescription(descript); + + validator.setBondHeight(bondHeight); + validator.setBondIntraTxCounter(bondIntraTxCounter); + validator.setUnBondingHeight(unBondingHeight); +// validator.setUnBondingMinTime(unBondingMinTime); + + Commission comm = new Commission(); + if (commission != null) { + comm.setRate(commission.getRate()); + comm.setMaxRate(commission.getMaxRate()); + comm.setMaxChangeRate(commission.getMaxChangeRate()); +// comm.setUpdateTimeInMs(commission.getUpdateTime()); + } + validator.setCommission(comm); + + if (!StringUtils.isEmpty(sideChainId)) { + if (distributionAddr != null) { + validator.setDistributionAddr(distributionAddr); + } + validator.setSideChainId(sideChainId); + if (sideConsAddr != null) { + validator.setSideConsAddr(sideConsAddr); + } + if (sideFeeAddr != null) { + validator.setSideFeeAddr(sideFeeAddr); + } + } + + return validator; + } + + public String getConsPubKey() { + return consPubKey; + } + + public void setConsPubKey(String consPubKey) { + this.consPubKey = consPubKey; + } + + public boolean isJailed() { + return jailed; + } + + public void setJailed(boolean jailed) { + this.jailed = jailed; + } + + public int getStatus() { + return status; + } + + public void setStatus(int status) { + this.status = status; + } + + public long getTokens() { + return tokens; + } + + public void setTokens(long tokens) { + this.tokens = tokens; + } + + public long getDelegatorShares() { + return delegatorShares; + } + + public void setDelegatorShares(long delegatorShares) { + this.delegatorShares = delegatorShares; + } + + public long getBondHeight() { + return bondHeight; + } + + public void setBondHeight(long bondHeight) { + this.bondHeight = bondHeight; + } + + public int getBondIntraTxCounter() { + return bondIntraTxCounter; + } + + public void setBondIntraTxCounter(int bondIntraTxCounter) { + this.bondIntraTxCounter = bondIntraTxCounter; + } + + public long getUnBondingHeight() { + return unBondingHeight; + } + + public void setUnBondingHeight(long unBondingHeight) { + this.unBondingHeight = unBondingHeight; + } + + public String getUnBondingMinTime() { + return unBondingMinTime; + } + + public void setUnBondingMinTime(String unBondingMinTime) { + this.unBondingMinTime = unBondingMinTime; + } + + public DescriptionValue getDescription() { + return description; + } + + public void setDescription(DescriptionValue description) { + this.description = description; + } + + public CommissionForDecode getCommission() { + return commission; + } + + public void setCommission(CommissionForDecode commission) { + this.commission = commission; + } + + public String getSideChainId() { + return sideChainId; + } + + public void setSideChainId(String sideChainId) { + this.sideChainId = sideChainId; + } + + public String getSideConsAddr() { + return sideConsAddr; + } + + public void setSideConsAddr(String sideConsAddr) { + this.sideConsAddr = sideConsAddr; + } + + public String getSideFeeAddr() { + return sideFeeAddr; + } + + public void setSideFeeAddr(String sideFeeAddr) { + this.sideFeeAddr = sideFeeAddr; + } + + public String getFeeAddr() { + return feeAddr; + } + + public void setFeeAddr(String feeAddr) { + this.feeAddr = feeAddr; + } + + public String getOperatorAddr() { + return operatorAddr; + } + + public void setOperatorAddr(String operatorAddr) { + this.operatorAddr = operatorAddr; + } + + public String getDistributionAddr() { + return distributionAddr; + } + + public void setDistributionAddr(String distributionAddr) { + this.distributionAddr = distributionAddr; + } +} diff --git a/src/main/java/com/binance/dex/api/client/encoding/message/sidechain/query/Delegation.java b/src/main/java/com/binance/dex/api/client/encoding/message/sidechain/query/Delegation.java new file mode 100644 index 0000000..f6a3d8e --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/encoding/message/sidechain/query/Delegation.java @@ -0,0 +1,55 @@ +package com.binance.dex.api.client.encoding.message.sidechain.query; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + +/** + * @author Fitz.Lu + **/ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonPropertyOrder(alphabetic = true) +public class Delegation { + + @JsonProperty(value = "delegator_addr") + private String delegatorAddress; + + @JsonProperty(value = "validator_addr") + private String validatorAddress; + + @JsonProperty(value = "shares") + private long shares; + + public Delegation() { + } + + public Delegation(String delegatorAddress, String validatorAddress, long shares) { + this.delegatorAddress = delegatorAddress; + this.validatorAddress = validatorAddress; + this.shares = shares; + } + + public String getDelegatorAddress() { + return delegatorAddress; + } + + public void setDelegatorAddress(String delegatorAddress) { + this.delegatorAddress = delegatorAddress; + } + + public String getValidatorAddress() { + return validatorAddress; + } + + public void setValidatorAddress(String validatorAddress) { + this.validatorAddress = validatorAddress; + } + + public long getShares() { + return shares; + } + + public void setShares(long shares) { + this.shares = shares; + } +} diff --git a/src/main/java/com/binance/dex/api/client/encoding/message/sidechain/query/DelegationResponse.java b/src/main/java/com/binance/dex/api/client/encoding/message/sidechain/query/DelegationResponse.java new file mode 100644 index 0000000..fe2c785 --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/encoding/message/sidechain/query/DelegationResponse.java @@ -0,0 +1,44 @@ +package com.binance.dex.api.client.encoding.message.sidechain.query; + +import com.binance.dex.api.client.encoding.message.common.CoinValue; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + +/** + * @author Fitz.Lu + **/ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonPropertyOrder(alphabetic = true) +public class DelegationResponse { + + @JsonProperty(value = "Delegation") + private Delegation delegation; + + @JsonProperty(value = "balance") + private CoinValue balance; + + public DelegationResponse() { + } + + public DelegationResponse(Delegation delegation, CoinValue balance) { + this.delegation = delegation; + this.balance = balance; + } + + public Delegation getDelegation() { + return delegation; + } + + public void setDelegation(Delegation delegation) { + this.delegation = delegation; + } + + public CoinValue getBalance() { + return balance; + } + + public void setBalance(CoinValue balance) { + this.balance = balance; + } +} diff --git a/src/main/java/com/binance/dex/api/client/encoding/message/sidechain/query/PoolMessage.java b/src/main/java/com/binance/dex/api/client/encoding/message/sidechain/query/PoolMessage.java new file mode 100644 index 0000000..254f36b --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/encoding/message/sidechain/query/PoolMessage.java @@ -0,0 +1,60 @@ +package com.binance.dex.api.client.encoding.message.sidechain.query; + +import com.binance.dex.api.client.encoding.amino.AminoField; +import com.binance.dex.api.client.encoding.amino.AminoSerializable; +import com.binance.dex.api.client.encoding.message.common.Dec; + +import java.util.ArrayList; + +/** + * @author Fitz.Lu + **/ +public class PoolMessage implements AminoSerializable { + + private Dec looseTokens; + + private Dec bondedTokens; + + public Dec getLooseTokens() { + return looseTokens; + } + + public void setLooseTokens(Dec looseTokens) { + this.looseTokens = looseTokens; + } + + public Dec getBondedTokens() { + return bondedTokens; + } + + public void setBondedTokens(Dec bondedTokens) { + this.bondedTokens = bondedTokens; + } + + @Override + public AminoSerializable newAminoMessage() { + return new PoolMessage(); + } + + @Override + public ArrayList> IterateFields() { + return AminoField.newFieldsBuilder() + .addField(Dec.class, looseTokens, looseTokens == null) + .addField(Dec.class, bondedTokens, bondedTokens == null) + .build(); + } + + @Override + public void setValueByFieldIndex(int fieldIndex, Object value) { + switch (fieldIndex) { + case 1: + looseTokens = ((Dec) value); + break; + case 2: + bondedTokens = ((Dec) value); + break; + default: + break; + } + } +} diff --git a/src/main/java/com/binance/dex/api/client/encoding/message/sidechain/query/QueryBondsParams.java b/src/main/java/com/binance/dex/api/client/encoding/message/sidechain/query/QueryBondsParams.java new file mode 100644 index 0000000..ff5a905 --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/encoding/message/sidechain/query/QueryBondsParams.java @@ -0,0 +1,46 @@ +package com.binance.dex.api.client.encoding.message.sidechain.query; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + +/** + * @author Fitz.Lu + **/ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonPropertyOrder(alphabetic = true) +public class QueryBondsParams extends BaseQueryParams { + + @JsonProperty(value = "DelegatorAddr") + private String delegatorAddr; + + @JsonProperty(value = "ValidatorAddr") + private String validatorAddr; + + public QueryBondsParams() { + } + + public String getSideChainId() { + return sideChainId; + } + + public void setSideChainId(String sideChainId) { + this.sideChainId = sideChainId; + } + + public String getDelegatorAddr() { + return delegatorAddr; + } + + public void setDelegatorAddr(String delegatorAddr) { + this.delegatorAddr = delegatorAddr; + } + + public String getValidatorAddr() { + return validatorAddr; + } + + public void setValidatorAddr(String validatorAddr) { + this.validatorAddr = validatorAddr; + } +} diff --git a/src/main/java/com/binance/dex/api/client/encoding/message/sidechain/query/QueryDelegatorParams.java b/src/main/java/com/binance/dex/api/client/encoding/message/sidechain/query/QueryDelegatorParams.java new file mode 100644 index 0000000..ce4bf3f --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/encoding/message/sidechain/query/QueryDelegatorParams.java @@ -0,0 +1,20 @@ +package com.binance.dex.api.client.encoding.message.sidechain.query; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * @author Fitz.Lu + **/ +public class QueryDelegatorParams extends BaseQueryParams { + + @JsonProperty(value = "DelegatorAddr") + private String delegatorAddr; + + public String getDelegatorAddr() { + return delegatorAddr; + } + + public void setDelegatorAddr(String delegatorAddr) { + this.delegatorAddr = delegatorAddr; + } +} diff --git a/src/main/java/com/binance/dex/api/client/encoding/message/sidechain/query/QuerySideProposal.java b/src/main/java/com/binance/dex/api/client/encoding/message/sidechain/query/QuerySideProposal.java new file mode 100644 index 0000000..b6c411b --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/encoding/message/sidechain/query/QuerySideProposal.java @@ -0,0 +1,33 @@ +package com.binance.dex.api.client.encoding.message.sidechain.query; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonPropertyOrder(alphabetic = true) +public class QuerySideProposal extends BaseQueryParams { + + @JsonProperty(value = "ProposalID") + private String proposalID; + + public QuerySideProposal() { + } + + public String getProposalID() { + return proposalID; + } + + public void setProposalID(String proposalID) { + this.proposalID = proposalID; + } + + public String getSideChainId() { + return sideChainId; + } + + public void setSideChainId(String sideChainId) { + this.sideChainId = sideChainId; + } + +} diff --git a/src/main/java/com/binance/dex/api/client/encoding/message/sidechain/query/QueryTopValidatorParams.java b/src/main/java/com/binance/dex/api/client/encoding/message/sidechain/query/QueryTopValidatorParams.java new file mode 100644 index 0000000..44dfacf --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/encoding/message/sidechain/query/QueryTopValidatorParams.java @@ -0,0 +1,23 @@ +package com.binance.dex.api.client.encoding.message.sidechain.query; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * @author Fitz.Lu + **/ +public class QueryTopValidatorParams extends BaseQueryParams { + + @JsonProperty(value = "Top") + private int top; + + public QueryTopValidatorParams() { + } + + public int getTop() { + return top; + } + + public void setTop(int top) { + this.top = top; + } +} diff --git a/src/main/java/com/binance/dex/api/client/encoding/message/sidechain/query/QueryValidatorParams.java b/src/main/java/com/binance/dex/api/client/encoding/message/sidechain/query/QueryValidatorParams.java new file mode 100644 index 0000000..476c168 --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/encoding/message/sidechain/query/QueryValidatorParams.java @@ -0,0 +1,29 @@ +package com.binance.dex.api.client.encoding.message.sidechain.query; + +import com.binance.dex.api.client.encoding.message.common.Bech32AddressValue; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * @author Fitz.Lu + **/ +public class QueryValidatorParams extends BaseQueryParams { + + @JsonProperty(value = "ValidatorAddr") + private Bech32AddressValue ValidatorAddress; + + public QueryValidatorParams() { + } + + public QueryValidatorParams(String sideChainId, Bech32AddressValue validatorAddress) { + this.sideChainId = sideChainId; + ValidatorAddress = validatorAddress; + } + + public Bech32AddressValue getValidatorAddress() { + return ValidatorAddress; + } + + public void setValidatorAddress(Bech32AddressValue validatorAddress) { + ValidatorAddress = validatorAddress; + } +} diff --git a/src/main/java/com/binance/dex/api/client/encoding/message/sidechain/query/SideChainRedelegationMessage.java b/src/main/java/com/binance/dex/api/client/encoding/message/sidechain/query/SideChainRedelegationMessage.java new file mode 100644 index 0000000..1ac0559 --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/encoding/message/sidechain/query/SideChainRedelegationMessage.java @@ -0,0 +1,116 @@ +package com.binance.dex.api.client.encoding.message.sidechain.query; + +import com.binance.dex.api.client.encoding.message.common.CoinValue; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + +/** + * @author Fitz.Lu + **/ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonPropertyOrder(alphabetic = true) +public class SideChainRedelegationMessage { + + @JsonProperty(value = "delegator_addr") + private String delegatorAddress; + + @JsonProperty(value = "validator_src_addr") + private String srcValidatorAddress; + + @JsonProperty(value = "validator_dst_addr") + private String dstValidatorAddress; + + @JsonProperty(value = "creation_height") + private long createHeight; + + @JsonProperty(value = "min_time") + private String minTime; + + @JsonProperty(value = "initial_balance") + private CoinValue initialBalance; + + @JsonProperty(value = "balance") + private CoinValue balance; + + @JsonProperty(value = "shares_src") + private long srcShares; + + @JsonProperty(value = "shares_dst") + private long dstShare; + + public SideChainRedelegationMessage() { + } + + public String getDelegatorAddress() { + return delegatorAddress; + } + + public void setDelegatorAddress(String delegatorAddress) { + this.delegatorAddress = delegatorAddress; + } + + public String getSrcValidatorAddress() { + return srcValidatorAddress; + } + + public void setSrcValidatorAddress(String srcValidatorAddress) { + this.srcValidatorAddress = srcValidatorAddress; + } + + public String getDstValidatorAddress() { + return dstValidatorAddress; + } + + public void setDstValidatorAddress(String dstValidatorAddress) { + this.dstValidatorAddress = dstValidatorAddress; + } + + public long getCreateHeight() { + return createHeight; + } + + public void setCreateHeight(long createHeight) { + this.createHeight = createHeight; + } + + public String getMinTime() { + return minTime; + } + + public void setMinTime(String minTime) { + this.minTime = minTime; + } + + public CoinValue getInitialBalance() { + return initialBalance; + } + + public void setInitialBalance(CoinValue initialBalance) { + this.initialBalance = initialBalance; + } + + public CoinValue getBalance() { + return balance; + } + + public void setBalance(CoinValue balance) { + this.balance = balance; + } + + public long getSrcShares() { + return srcShares; + } + + public void setSrcShares(long srcShares) { + this.srcShares = srcShares; + } + + public long getDstShare() { + return dstShare; + } + + public void setDstShare(long dstShare) { + this.dstShare = dstShare; + } +} diff --git a/src/main/java/com/binance/dex/api/client/encoding/message/sidechain/query/SideChainValidatorMessage.java b/src/main/java/com/binance/dex/api/client/encoding/message/sidechain/query/SideChainValidatorMessage.java new file mode 100644 index 0000000..decea6a --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/encoding/message/sidechain/query/SideChainValidatorMessage.java @@ -0,0 +1,298 @@ +package com.binance.dex.api.client.encoding.message.sidechain.query; + +import com.binance.dex.api.client.encoding.amino.AminoField; +import com.binance.dex.api.client.encoding.amino.AminoSerializable; +import com.binance.dex.api.client.encoding.message.sidechain.value.CommissionValue; +import com.binance.dex.api.client.encoding.message.common.Dec; +import com.binance.dex.api.client.encoding.message.sidechain.value.DescriptionValue; +import org.apache.commons.lang3.StringUtils; +import org.bouncycastle.util.encoders.Hex; + +import java.util.ArrayList; +import java.util.Arrays; + +/** + * @author Fitz.Lu + **/ +public class SideChainValidatorMessage implements AminoSerializable { + + private byte[] feeAddr; + + private byte[] operatorAddr; + + private byte[] consPubKey; + + private boolean jailed; + + private int status; + + private Dec tokens = Dec.newInstance(0L); + + private Dec delegatorShares = Dec.newInstance(0L); + + private DescriptionValue description = new DescriptionValue(); + + private long bondHeight; + + private int bondIntraTxCounter; + + private long unBondingHeight; + + private long unBondingMinTime; + + private CommissionValue commission = new CommissionValue(); + + private byte[] distributionAddr; + + private String sideChainId; + + private byte[] sideConsAddr; + + private byte[] sideFeeAddr; + + public byte[] getFeeAddr() { + return feeAddr; + } + + public void setFeeAddr(byte[] feeAddr) { + this.feeAddr = feeAddr; + } + + public byte[] getOperatorAddr() { + return operatorAddr; + } + + public void setOperatorAddr(byte[] operatorAddr) { + this.operatorAddr = operatorAddr; + } + + public byte[] getConsPubKey() { + return consPubKey; + } + + public void setConsPubKey(byte[] consPubKey) { + this.consPubKey = consPubKey; + } + + public boolean isJailed() { + return jailed; + } + + public void setJailed(boolean jailed) { + this.jailed = jailed; + } + + public int getStatus() { + return status; + } + + public void setStatus(int status) { + this.status = status; + } + + public Dec getTokens() { + return tokens; + } + + public void setTokens(Dec tokens) { + this.tokens = tokens; + } + + public Dec getDelegatorShares() { + return delegatorShares; + } + + public void setDelegatorShares(Dec delegatorShares) { + this.delegatorShares = delegatorShares; + } + + public DescriptionValue getDescription() { + return description; + } + + public void setDescription(DescriptionValue description) { + this.description = description; + } + + public long getBondHeight() { + return bondHeight; + } + + public void setBondHeight(long bondHeight) { + this.bondHeight = bondHeight; + } + + public int getBondIntraTxCounter() { + return bondIntraTxCounter; + } + + public void setBondIntraTxCounter(int bondIntraTxCounter) { + this.bondIntraTxCounter = bondIntraTxCounter; + } + + public long getUnBondingHeight() { + return unBondingHeight; + } + + public void setUnBondingHeight(long unBondingHeight) { + this.unBondingHeight = unBondingHeight; + } + + public long getUnBondingMinTime() { + return unBondingMinTime; + } + + public void setUnBondingMinTime(long unBondingMinTime) { + this.unBondingMinTime = unBondingMinTime; + } + + public CommissionValue getCommission() { + return commission; + } + + public void setCommission(CommissionValue commission) { + this.commission = commission; + } + + public byte[] getDistributionAddr() { + return distributionAddr; + } + + public void setDistributionAddr(byte[] distributionAddr) { + this.distributionAddr = distributionAddr; + } + + public String getSideChainId() { + return sideChainId; + } + + public void setSideChainId(String sideChainId) { + this.sideChainId = sideChainId; + } + + public byte[] getSideConsAddr() { + return sideConsAddr; + } + + public void setSideConsAddr(byte[] sideConsAddr) { + this.sideConsAddr = sideConsAddr; + } + + public byte[] getSideFeeAddr() { + return sideFeeAddr; + } + + public void setSideFeeAddr(byte[] sideFeeAddr) { + this.sideFeeAddr = sideFeeAddr; + } + + @Override + public AminoSerializable newAminoMessage() { + return new SideChainValidatorMessage(); + } + + @Override + public void setValueByFieldIndex(int fieldIndex, Object value) { + switch (fieldIndex) { + case 1: + feeAddr = (byte[]) value; + break; + case 2: + operatorAddr = (byte[]) value; + break; + case 3: + consPubKey = (byte[]) value; + break; + case 4: + jailed = ((boolean) value); + break; + case 5: + status = ((Integer) value); + break; + case 6: + tokens = ((Dec) value); + break; + case 7: + delegatorShares = ((Dec) value); + break; + case 8: + description = ((DescriptionValue) value); + break; + case 9: + bondHeight = ((long) value); + break; + case 10: + bondIntraTxCounter = ((int) value); + break; + case 11: + unBondingHeight = ((long) value); + break; + case 12: + unBondingMinTime = ((long) value); + break; + case 13: + commission = ((CommissionValue) value); + break; + case 14: + distributionAddr = ((byte[]) value); + break; + case 15: + sideChainId = ((String) value); + break; + case 16: + sideConsAddr = ((byte[]) value); + break; + case 17: + sideFeeAddr = ((byte[]) value); + break; + default: + break; + } + } + + @Override + public ArrayList> IterateFields() { + return AminoField.newFieldsBuilder() + .addField(byte[].class, feeAddr, feeAddr == null || feeAddr.length == 0) + .addField(byte[].class, operatorAddr, operatorAddr == null || operatorAddr.length == 0) + .addField(byte[].class, consPubKey, consPubKey == null || consPubKey.length == 0) + .addField(Boolean.class, jailed, !jailed) + .addField(Integer.class, status, status == 0) + .addField(Dec.class, tokens, tokens == null) + .addField(Dec.class, delegatorShares, delegatorShares == null) + .addField(DescriptionValue.class, description, description == null) + .addField(Long.class, bondHeight, bondHeight == 0) + .addField(Integer.class, bondIntraTxCounter, bondIntraTxCounter == 0) + .addField(Long.class, unBondingHeight, unBondingHeight == 0) + .addField(Long.class, unBondingMinTime, unBondingMinTime == 0) + .addField(CommissionValue.class, commission, commission == null) + .addField(byte[].class, distributionAddr, distributionAddr == null || distributionAddr.length == 0) + .addField(String.class, sideChainId, StringUtils.isEmpty(sideChainId)) + .addField(byte[].class, sideConsAddr, sideConsAddr == null || sideConsAddr.length == 0) + .addField(byte[].class, sideFeeAddr, sideFeeAddr == null || sideFeeAddr.length == 0) + .build(); + } + + @Override + public String toString() { + return "SideChainValidatorMessage{" + '\n' + + "feeAddr=" + Hex.toHexString(feeAddr)+ '\n' + + ", operatorAddr=" + Hex.toHexString(operatorAddr) + '\n' + + ", consPubKey=" + Hex.toHexString(consPubKey) + '\n' + + ", jailed=" + jailed + '\n' + + ", status=" + status + '\n' + + ", tokens=" + tokens + '\n' + + ", delegatorShares=" + delegatorShares + '\n' + + ", description=" + description + '\n' + + ", bondHeight=" + bondHeight + '\n' + + ", bondIntraTxCounter=" + bondIntraTxCounter + '\n' + + ", unBondingHeight=" + unBondingHeight + '\n' + + ", unBondingMinTime=" + unBondingMinTime + '\n' + + ", commission=" + commission + '\n' + + ", distributionAddr=" + Arrays.toString(distributionAddr) + '\n' + + ", sideChainId='" + sideChainId + '\'' + '\n' + + ", sideConsAddr=" + Arrays.toString(sideConsAddr) + '\n' + + ", sideFeeAddr=" + Arrays.toString(sideFeeAddr) + '\n' + + '}'; + } +} diff --git a/src/main/java/com/binance/dex/api/client/encoding/message/sidechain/query/UnBondingDelegationMessage.java b/src/main/java/com/binance/dex/api/client/encoding/message/sidechain/query/UnBondingDelegationMessage.java new file mode 100644 index 0000000..f1baa0f --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/encoding/message/sidechain/query/UnBondingDelegationMessage.java @@ -0,0 +1,83 @@ +package com.binance.dex.api.client.encoding.message.sidechain.query; + +import com.binance.dex.api.client.encoding.message.Token; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + +/** + * @author Fitz.Lu + **/ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonPropertyOrder(alphabetic = true) +public class UnBondingDelegationMessage { + + @JsonProperty(value = "delegator_addr") + private String delegatorAddress; + + @JsonProperty(value = "validator_addr") + private String validatorAddress; + + @JsonProperty(value = "creation_height") + private long createHeight; + + @JsonProperty(value = "min_time") + private String minTime; + + @JsonProperty(value = "initial_balance") + private Token initialBalance; + + @JsonProperty(value = "balance") + private Token balance; + + public UnBondingDelegationMessage() { + } + + public String getDelegatorAddress() { + return delegatorAddress; + } + + public void setDelegatorAddress(String delegatorAddress) { + this.delegatorAddress = delegatorAddress; + } + + public String getValidatorAddress() { + return validatorAddress; + } + + public void setValidatorAddress(String validatorAddress) { + this.validatorAddress = validatorAddress; + } + + public long getCreateHeight() { + return createHeight; + } + + public void setCreateHeight(long createHeight) { + this.createHeight = createHeight; + } + + public String getMinTime() { + return minTime; + } + + public void setMinTime(String minTime) { + this.minTime = minTime; + } + + public Token getInitialBalance() { + return initialBalance; + } + + public void setInitialBalance(Token initialBalance) { + this.initialBalance = initialBalance; + } + + public Token getBalance() { + return balance; + } + + public void setBalance(Token balance) { + this.balance = balance; + } +} diff --git a/src/main/java/com/binance/dex/api/client/encoding/message/sidechain/transaction/CreateSideChainValidatorMessage.java b/src/main/java/com/binance/dex/api/client/encoding/message/sidechain/transaction/CreateSideChainValidatorMessage.java new file mode 100644 index 0000000..4220eca --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/encoding/message/sidechain/transaction/CreateSideChainValidatorMessage.java @@ -0,0 +1,164 @@ +package com.binance.dex.api.client.encoding.message.sidechain.transaction; + +import com.binance.dex.api.client.encoding.amino.AminoField; +import com.binance.dex.api.client.encoding.amino.AminoSerializable; +import com.binance.dex.api.client.encoding.message.BinanceDexTransactionMessage; +import com.binance.dex.api.client.encoding.message.common.Bech32AddressValue; +import com.binance.dex.api.client.encoding.message.common.CoinValueStr; +import com.binance.dex.api.client.encoding.message.sidechain.value.*; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import org.apache.commons.lang3.StringUtils; + +import java.util.ArrayList; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonPropertyOrder(alphabetic = true) +public class CreateSideChainValidatorMessage implements BinanceDexTransactionMessage, AminoSerializable { + + @JsonProperty(value = "description") + private DescriptionValue description = new DescriptionValue(); + + @JsonProperty(value = "commission") + private CommissionMsgValue commission = new CommissionMsgValue(); + + @JsonProperty(value = "delegator_address") + private Bech32AddressValue delegatorAddr; + + @JsonProperty(value = "validator_address") + private Bech32AddressValue validatorOperatorAddr; + + @JsonProperty(value = "delegation") + private CoinValueStr delegation; + + @JsonProperty(value = "side_chain_id") + private String sideChainId; + + @JsonProperty(value = "side_cons_addr") + private byte[] sideConsAddr; + + @JsonProperty(value = "side_fee_addr") + private byte[] sideFeeAddr; + + @Override + public boolean useAminoJson() { + return true; + } + + @Override + public void setValueByFieldIndex(int fieldIndex, Object value) { + switch (fieldIndex) { + case 1: + description = ((DescriptionValue) value); + break; + case 2: + commission = ((CommissionMsgValue) value); + break; + case 3: + delegatorAddr = ((Bech32AddressValue) value); + break; + case 4: + validatorOperatorAddr = ((Bech32AddressValue) value); + break; + case 5: + delegation = ((CoinValueStr) value); + break; + case 6: + sideChainId = ((String) value); + break; + case 7: + sideConsAddr = ((byte[]) value); + break; + case 8: + sideFeeAddr = ((byte[]) value); + break; + default: + break; + } + } + + @Override + public AminoSerializable newAminoMessage() { + return new CreateSideChainValidatorMessage(); + } + + @Override + public ArrayList> IterateFields() { + ArrayList> fields = new ArrayList<>(); + fields.add(new AminoField<>(DescriptionValue.class, description, description == null)); + fields.add(new AminoField<>(CommissionMsgValue.class, commission, commission == null)); + fields.add(new AminoField<>(Bech32AddressValue.class, delegatorAddr, delegatorAddr == null || delegatorAddr.isDefaultOrEmpty())); + fields.add(new AminoField<>(Bech32AddressValue.class, validatorOperatorAddr, validatorOperatorAddr == null || validatorOperatorAddr.isDefaultOrEmpty())); + fields.add(new AminoField<>(CoinValueStr.class, delegation, delegation == null)); + fields.add(new AminoField<>(String.class, sideChainId, StringUtils.isEmpty(sideChainId))); + fields.add(new AminoField<>(byte[].class, sideConsAddr, sideConsAddr == null || sideConsAddr.length == 0)); + fields.add(new AminoField<>(byte[].class, sideFeeAddr, sideFeeAddr == null || sideFeeAddr.length == 0)); + return fields; + } + + public DescriptionValue getDescription() { + return description; + } + + public void setDescription(DescriptionValue description) { + this.description = description; + } + + public CommissionMsgValue getCommission() { + return commission; + } + + public void setCommission(CommissionMsgValue commission) { + this.commission = commission; + } + + public Bech32AddressValue getDelegatorAddr() { + return delegatorAddr; + } + + public void setDelegatorAddr(Bech32AddressValue delegatorAddr) { + this.delegatorAddr = delegatorAddr; + } + + public Bech32AddressValue getValidatorOperatorAddr() { + return validatorOperatorAddr; + } + + public void setValidatorOperatorAddr(Bech32AddressValue validatorOperatorAddr) { + this.validatorOperatorAddr = validatorOperatorAddr; + } + + public CoinValueStr getDelegation() { + return delegation; + } + + public void setDelegation(CoinValueStr delegation) { + this.delegation = delegation; + } + + public String getSideChainId() { + return sideChainId; + } + + public void setSideChainId(String sideChainId) { + this.sideChainId = sideChainId; + } + + public byte[] getSideConsAddr() { + return sideConsAddr; + } + + public void setSideConsAddr(byte[] sideConsAddr) { + this.sideConsAddr = sideConsAddr; + } + + public byte[] getSideFeeAddr() { + return sideFeeAddr; + } + + public void setSideFeeAddr(byte[] sideFeeAddr) { + this.sideFeeAddr = sideFeeAddr; + } + +} \ No newline at end of file diff --git a/src/main/java/com/binance/dex/api/client/encoding/message/sidechain/transaction/EditSideChainValidatorMessage.java b/src/main/java/com/binance/dex/api/client/encoding/message/sidechain/transaction/EditSideChainValidatorMessage.java new file mode 100644 index 0000000..b8d3374 --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/encoding/message/sidechain/transaction/EditSideChainValidatorMessage.java @@ -0,0 +1,128 @@ +package com.binance.dex.api.client.encoding.message.sidechain.transaction; + +import com.binance.dex.api.client.encoding.amino.AminoField; +import com.binance.dex.api.client.encoding.amino.AminoSerializable; +import com.binance.dex.api.client.encoding.message.BinanceDexTransactionMessage; +import com.binance.dex.api.client.encoding.message.common.Bech32AddressValue; +import com.binance.dex.api.client.encoding.message.common.Dec; +import com.binance.dex.api.client.encoding.message.sidechain.value.DescriptionValue; +import com.binance.dex.api.client.encoding.serializer.DecToStringSerializer; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import org.apache.commons.lang3.StringUtils; + +import java.util.ArrayList; + +/** + * @author Fitz.Lu + **/ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonPropertyOrder(alphabetic = true) +public class EditSideChainValidatorMessage implements BinanceDexTransactionMessage, AminoSerializable { + + @JsonProperty(value = "description") + private DescriptionValue description; + + @JsonProperty(value = "address") + private Bech32AddressValue validatorOperatorAddress; + + @JsonProperty(value = "commission_rate") + @JsonSerialize(using = DecToStringSerializer.class) + private Dec commissionRate; + + @JsonProperty(value = "side_chain_id") + private String sideChainId; + + @JsonProperty(value = "side_fee_addr") + private byte[] sideFeeAddr; + + @Override + public void setValueByFieldIndex(int fieldIndex, Object value) { + switch (fieldIndex) { + case 1: + description = ((DescriptionValue) value); + break; + case 2: + validatorOperatorAddress = ((Bech32AddressValue) value); + break; + case 3: + commissionRate = ((Dec) value); + break; + case 4: + sideChainId = ((String) value); + break; + case 5: + sideFeeAddr = ((byte[]) value); + break; + default: + break; + } + } + + public EditSideChainValidatorMessage() { + } + + public DescriptionValue getDescription() { + return description; + } + + public void setDescription(DescriptionValue description) { + this.description = description; + } + + public Bech32AddressValue getValidatorOperatorAddress() { + return validatorOperatorAddress; + } + + public void setValidatorOperatorAddress(Bech32AddressValue validatorOperatorAddress) { + this.validatorOperatorAddress = validatorOperatorAddress; + } + + public Dec getCommissionRate() { + return commissionRate; + } + + public void setCommissionRate(Dec commissionRate) { + this.commissionRate = commissionRate; + } + + public String getSideChainId() { + return sideChainId; + } + + public void setSideChainId(String sideChainId) { + this.sideChainId = sideChainId; + } + + public byte[] getSideFeeAddr() { + return sideFeeAddr; + } + + public void setSideFeeAddr(byte[] sideFeeAddr) { + this.sideFeeAddr = sideFeeAddr; + } + + @Override + public boolean useAminoJson() { + return true; + } + + @Override + public AminoSerializable newAminoMessage() { + return new EditSideChainValidatorMessage(); + } + + @Override + public ArrayList> IterateFields() { + return AminoField.newFieldsBuilder() + .addField(DescriptionValue.class, description, description == null) + .addField(Bech32AddressValue.class, validatorOperatorAddress, validatorOperatorAddress == null || validatorOperatorAddress.isDefaultOrEmpty()) + .addField(Dec.class, commissionRate, commissionRate == null || commissionRate.isDefaultOrEmpty()) + .addField(String.class, sideChainId, StringUtils.isEmpty(sideChainId)) + .addField(byte[].class, sideFeeAddr, sideFeeAddr == null || sideFeeAddr.length == 0) + .build(); + } + +} diff --git a/src/main/java/com/binance/dex/api/client/encoding/message/sidechain/transaction/SideChainDelegateMessage.java b/src/main/java/com/binance/dex/api/client/encoding/message/sidechain/transaction/SideChainDelegateMessage.java new file mode 100644 index 0000000..7f2825c --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/encoding/message/sidechain/transaction/SideChainDelegateMessage.java @@ -0,0 +1,108 @@ +package com.binance.dex.api.client.encoding.message.sidechain.transaction; + +import com.binance.dex.api.client.encoding.amino.AminoField; +import com.binance.dex.api.client.encoding.amino.AminoSerializable; +import com.binance.dex.api.client.encoding.message.BinanceDexTransactionMessage; +import com.binance.dex.api.client.encoding.message.common.Bech32AddressValue; +import com.binance.dex.api.client.encoding.message.common.CoinValueStr; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import org.apache.commons.lang3.StringUtils; + +import java.util.ArrayList; + +/** + * @author Fitz.Lu + **/ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonPropertyOrder(alphabetic = true) +public class SideChainDelegateMessage implements BinanceDexTransactionMessage, AminoSerializable { + + @JsonProperty(value = "delegator_addr") + private Bech32AddressValue delegatorAddress; + + @JsonProperty(value = "validator_addr") + private Bech32AddressValue validatorAddress; + + @JsonProperty(value = "delegation") + private CoinValueStr delegation; + + @JsonProperty(value = "side_chain_id") + private String sideChainId; + + public SideChainDelegateMessage() { } + + public Bech32AddressValue getDelegatorAddress() { + return delegatorAddress; + } + + public void setDelegatorAddress(Bech32AddressValue delegatorAddress) { + this.delegatorAddress = delegatorAddress; + } + + public Bech32AddressValue getValidatorAddress() { + return validatorAddress; + } + + public void setValidatorAddress(Bech32AddressValue validatorAddress) { + this.validatorAddress = validatorAddress; + } + + public CoinValueStr getDelegation() { + return delegation; + } + + public void setDelegation(CoinValueStr delegation) { + this.delegation = delegation; + } + + public String getSideChainId() { + return sideChainId; + } + + public void setSideChainId(String sideChainId) { + this.sideChainId = sideChainId; + } + + @Override + public AminoSerializable newAminoMessage() { + return new SideChainDelegateMessage(); + } + + @Override + public ArrayList> IterateFields() { + return AminoField.newFieldsBuilder() + .addField(Bech32AddressValue.class, delegatorAddress, delegatorAddress == null || delegatorAddress.isDefaultOrEmpty()) + .addField(Bech32AddressValue.class, validatorAddress, validatorAddress == null || validatorAddress.isDefaultOrEmpty()) + .addField(CoinValueStr.class, delegation, delegation == null) + .addField(String.class, sideChainId, StringUtils.isEmpty(sideChainId)) + .build(); + } + + @Override + public void setValueByFieldIndex(int fieldIndex, Object value) { + switch (fieldIndex) { + case 1: + delegatorAddress = ((Bech32AddressValue) value); + break; + case 2: + validatorAddress = ((Bech32AddressValue) value); + break; + case 3: + delegation = ((CoinValueStr) value); + break; + case 4: + sideChainId = ((String) value); + break; + default: + break; + } + } + + @Override + public boolean useAminoJson() { + return true; + } + +} diff --git a/src/main/java/com/binance/dex/api/client/encoding/message/sidechain/transaction/SideChainRedelegateMessage.java b/src/main/java/com/binance/dex/api/client/encoding/message/sidechain/transaction/SideChainRedelegateMessage.java new file mode 100644 index 0000000..6705ed8 --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/encoding/message/sidechain/transaction/SideChainRedelegateMessage.java @@ -0,0 +1,123 @@ +package com.binance.dex.api.client.encoding.message.sidechain.transaction; + +import com.binance.dex.api.client.encoding.amino.AminoField; +import com.binance.dex.api.client.encoding.amino.AminoSerializable; +import com.binance.dex.api.client.encoding.message.BinanceDexTransactionMessage; +import com.binance.dex.api.client.encoding.message.common.Bech32AddressValue; +import com.binance.dex.api.client.encoding.message.common.CoinValueStr; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import org.apache.commons.lang3.StringUtils; + +import java.util.ArrayList; + +/** + * @author Fitz.Lu + **/ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonPropertyOrder(alphabetic = true) +public class SideChainRedelegateMessage implements BinanceDexTransactionMessage, AminoSerializable { + + @JsonProperty(value = "delegator_addr") + private Bech32AddressValue delegatorAddress; + + @JsonProperty(value = "validator_src_addr") + private Bech32AddressValue srcValidatorAddress; + + @JsonProperty(value = "validator_dst_addr") + private Bech32AddressValue dstValidatorAddress; + + @JsonProperty(value = "amount") + private CoinValueStr amount; + + @JsonProperty(value = "side_chain_id") + private String sideChainId; + + public SideChainRedelegateMessage() { + } + + @Override + public AminoSerializable newAminoMessage() { + return new SideChainRedelegateMessage(); + } + + @Override + public ArrayList> IterateFields() { + return AminoField.newFieldsBuilder() + .addField(Bech32AddressValue.class, delegatorAddress, delegatorAddress == null || delegatorAddress.isDefaultOrEmpty()) + .addField(Bech32AddressValue.class, srcValidatorAddress, srcValidatorAddress == null || srcValidatorAddress.isDefaultOrEmpty()) + .addField(Bech32AddressValue.class, dstValidatorAddress, dstValidatorAddress == null || dstValidatorAddress.isDefaultOrEmpty()) + .addField(CoinValueStr.class, amount, amount == null) + .addField(String.class, sideChainId, StringUtils.isEmpty(sideChainId)) + .build(); + } + + @Override + public void setValueByFieldIndex(int fieldIndex, Object value) { + switch (fieldIndex) { + case 1: + delegatorAddress = ((Bech32AddressValue) value); + break; + case 2: + srcValidatorAddress = ((Bech32AddressValue) value); + break; + case 3: + dstValidatorAddress = ((Bech32AddressValue) value); + break; + case 4: + amount = ((CoinValueStr) value); + break; + case 5: + sideChainId = ((String) value); + break; + default: + break; + } + } + + @Override + public boolean useAminoJson() { + return true; + } + + public Bech32AddressValue getDelegatorAddress() { + return delegatorAddress; + } + + public void setDelegatorAddress(Bech32AddressValue delegatorAddress) { + this.delegatorAddress = delegatorAddress; + } + + public Bech32AddressValue getSrcValidatorAddress() { + return srcValidatorAddress; + } + + public void setSrcValidatorAddress(Bech32AddressValue srcValidatorAddress) { + this.srcValidatorAddress = srcValidatorAddress; + } + + public Bech32AddressValue getDstValidatorAddress() { + return dstValidatorAddress; + } + + public void setDstValidatorAddress(Bech32AddressValue dstValidatorAddress) { + this.dstValidatorAddress = dstValidatorAddress; + } + + public CoinValueStr getAmount() { + return amount; + } + + public void setAmount(CoinValueStr amount) { + this.amount = amount; + } + + public String getSideChainId() { + return sideChainId; + } + + public void setSideChainId(String sideChainId) { + this.sideChainId = sideChainId; + } +} diff --git a/src/main/java/com/binance/dex/api/client/encoding/message/sidechain/transaction/SideChainUndelegateMessage.java b/src/main/java/com/binance/dex/api/client/encoding/message/sidechain/transaction/SideChainUndelegateMessage.java new file mode 100644 index 0000000..f36823d --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/encoding/message/sidechain/transaction/SideChainUndelegateMessage.java @@ -0,0 +1,108 @@ +package com.binance.dex.api.client.encoding.message.sidechain.transaction; + +import com.binance.dex.api.client.encoding.amino.AminoField; +import com.binance.dex.api.client.encoding.amino.AminoSerializable; +import com.binance.dex.api.client.encoding.message.BinanceDexTransactionMessage; +import com.binance.dex.api.client.encoding.message.common.Bech32AddressValue; +import com.binance.dex.api.client.encoding.message.common.CoinValueStr; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import org.apache.commons.lang3.StringUtils; + +import java.util.ArrayList; + +/** + * @author Fitz.Lu + **/ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonPropertyOrder(alphabetic = true) +public class SideChainUndelegateMessage implements BinanceDexTransactionMessage, AminoSerializable { + + @JsonProperty(value = "delegator_addr") + private Bech32AddressValue delegatorAddress; + + @JsonProperty(value = "validator_addr") + private Bech32AddressValue validatorAddress; + + @JsonProperty(value = "amount") + private CoinValueStr amount; + + @JsonProperty(value = "side_chain_id") + private String sideChainId; + + public SideChainUndelegateMessage() { + } + + @Override + public boolean useAminoJson() { + return true; + } + + @Override + public AminoSerializable newAminoMessage() { + return new SideChainUndelegateMessage(); + } + + @Override + public ArrayList> IterateFields() { + return AminoField.newFieldsBuilder() + .addField(Bech32AddressValue.class, delegatorAddress, delegatorAddress == null || delegatorAddress.isDefaultOrEmpty()) + .addField(Bech32AddressValue.class, validatorAddress, validatorAddress == null || validatorAddress.isDefaultOrEmpty()) + .addField(CoinValueStr.class, amount, amount == null) + .addField(String.class, sideChainId, StringUtils.isEmpty(sideChainId)) + .build(); + } + + @Override + public void setValueByFieldIndex(int fieldIndex, Object value) { + switch (fieldIndex) { + case 1: + delegatorAddress = ((Bech32AddressValue) value); + break; + case 2: + validatorAddress = ((Bech32AddressValue) value); + break; + case 3: + amount = ((CoinValueStr) value); + break; + case 4: + sideChainId = ((String) value); + break; + default: + break; + } + } + + public Bech32AddressValue getDelegatorAddress() { + return delegatorAddress; + } + + public void setDelegatorAddress(Bech32AddressValue delegatorAddress) { + this.delegatorAddress = delegatorAddress; + } + + public Bech32AddressValue getValidatorAddress() { + return validatorAddress; + } + + public void setValidatorAddress(Bech32AddressValue validatorAddress) { + this.validatorAddress = validatorAddress; + } + + public CoinValueStr getAmount() { + return amount; + } + + public void setAmount(CoinValueStr amount) { + this.amount = amount; + } + + public String getSideChainId() { + return sideChainId; + } + + public void setSideChainId(String sideChainId) { + this.sideChainId = sideChainId; + } +} diff --git a/src/main/java/com/binance/dex/api/client/encoding/message/sidechain/value/CommissionMsgValue.java b/src/main/java/com/binance/dex/api/client/encoding/message/sidechain/value/CommissionMsgValue.java new file mode 100644 index 0000000..9cf9aa5 --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/encoding/message/sidechain/value/CommissionMsgValue.java @@ -0,0 +1,90 @@ +package com.binance.dex.api.client.encoding.message.sidechain.value; + +import com.binance.dex.api.client.encoding.amino.AminoField; +import com.binance.dex.api.client.encoding.amino.AminoSerializable; +import com.binance.dex.api.client.encoding.message.common.Dec; +import com.binance.dex.api.client.encoding.serializer.DecToStringSerializer; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; + +import java.util.ArrayList; + +/** + * @author Fitz.Lu + **/ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonPropertyOrder(alphabetic = true) +public class CommissionMsgValue implements AminoSerializable { + + @JsonProperty(value = "rate") + @JsonSerialize(using = DecToStringSerializer.class) + private Dec rate = new Dec(); + + @JsonProperty(value = "max_rate") + @JsonSerialize(using = DecToStringSerializer.class) + private Dec maxRate = new Dec(); + + @JsonProperty(value = "max_change_rate") + @JsonSerialize(using = DecToStringSerializer.class) + private Dec maxChangeRate = new Dec(); + + public CommissionMsgValue() { + } + + public Dec getRate() { + return rate; + } + + public void setRate(Dec rate) { + this.rate = rate; + } + + public Dec getMaxRate() { + return maxRate; + } + + public void setMaxRate(Dec maxRate) { + this.maxRate = maxRate; + } + + public Dec getMaxChangeRate() { + return maxChangeRate; + } + + public void setMaxChangeRate(Dec maxChangeRate) { + this.maxChangeRate = maxChangeRate; + } + + @Override + public AminoSerializable newAminoMessage() { + return new CommissionMsgValue(); + } + + @Override + public ArrayList> IterateFields() { + ArrayList> fields = new ArrayList<>(); + fields.add(new AminoField(Dec.class, rate, rate == null || rate.isDefaultOrEmpty())); + fields.add(new AminoField(Dec.class, maxRate, rate == null || rate.isDefaultOrEmpty())); + fields.add(new AminoField(Dec.class, maxChangeRate, rate == null || rate.isDefaultOrEmpty())); + return fields; + } + + @Override + public void setValueByFieldIndex(int fieldIndex, Object value) { + switch (fieldIndex) { + case 1: + rate = ((Dec) value); + break; + case 2: + maxRate = ((Dec) value); + break; + case 3: + maxChangeRate = ((Dec) value); + break; + default: + break; + } + } +} diff --git a/src/main/java/com/binance/dex/api/client/encoding/message/sidechain/value/CommissionValue.java b/src/main/java/com/binance/dex/api/client/encoding/message/sidechain/value/CommissionValue.java new file mode 100644 index 0000000..f760a51 --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/encoding/message/sidechain/value/CommissionValue.java @@ -0,0 +1,114 @@ +package com.binance.dex.api.client.encoding.message.sidechain.value; + +import com.binance.dex.api.client.encoding.amino.AminoField; +import com.binance.dex.api.client.encoding.amino.AminoSerializable; +import com.binance.dex.api.client.encoding.message.BinanceDexTransactionMessage; +import com.binance.dex.api.client.encoding.message.common.Dec; +import com.binance.dex.api.client.encoding.serializer.DecToStringSerializer; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; + +import java.util.ArrayList; + +/** + * @author Fitz.Lu + **/ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonPropertyOrder(alphabetic = true) +public class CommissionValue implements BinanceDexTransactionMessage, AminoSerializable { + + @JsonProperty(value = "rate") + @JsonSerialize(using = DecToStringSerializer.class) + private Dec rate = Dec.newInstance(0L); + + @JsonProperty(value = "max_rate") + @JsonSerialize(using = DecToStringSerializer.class) + private Dec maxRate = Dec.newInstance(0L); + + @JsonProperty(value = "max_change_rate") + @JsonSerialize(using = DecToStringSerializer.class) + private Dec maxChangeRate = Dec.newInstance(0L); + + @JsonProperty(value = "update_time") + private TimestampValue updateTime; + + public Dec getRate() { + return rate; + } + + public void setRate(Dec rate) { + this.rate = rate; + } + + public Dec getMaxRate() { + return maxRate; + } + + public void setMaxRate(Dec maxRate) { + this.maxRate = maxRate; + } + + public Dec getMaxChangeRate() { + return maxChangeRate; + } + + public void setMaxChangeRate(Dec maxChangeRate) { + this.maxChangeRate = maxChangeRate; + } + + public TimestampValue getUpdateTime() { + return updateTime; + } + + public void setUpdateTime(TimestampValue updateTime) { + this.updateTime = updateTime; + } + + @Override + public String toString() { + return "Commission{" + + "rate=" + rate + + ", maxRate=" + maxRate + + ", maxChangeRate=" + maxChangeRate + + ", updateTime=" + updateTime + + '}'; + } + + + @Override + public AminoSerializable newAminoMessage() { + return new CommissionValue(); + } + + @Override + public ArrayList> IterateFields() { + return AminoField.newFieldsBuilder() + .addField(Dec.class, rate, rate == null || rate.isDefaultOrEmpty()) + .addField(Dec.class, maxRate, maxRate == null || maxRate.isDefaultOrEmpty()) + .addField(Dec.class, maxChangeRate, maxChangeRate == null || maxChangeRate.isDefaultOrEmpty()) + .addField(TimestampValue.class, updateTime, false) + .build(); + } + + @Override + public void setValueByFieldIndex(int fieldIndex, Object value) { + switch (fieldIndex) { + case 1: + rate = ((Dec) value); + break; + case 2: + maxRate = ((Dec) value); + break; + case 3: + maxChangeRate = ((Dec) value); + break; + case 4: + updateTime = ((TimestampValue) value); + break; + default: + break; + } + } +} diff --git a/src/main/java/com/binance/dex/api/client/encoding/message/sidechain/value/DelegationValue.java b/src/main/java/com/binance/dex/api/client/encoding/message/sidechain/value/DelegationValue.java new file mode 100644 index 0000000..17ceab4 --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/encoding/message/sidechain/value/DelegationValue.java @@ -0,0 +1,63 @@ +package com.binance.dex.api.client.encoding.message.sidechain.value; + +import com.binance.dex.api.client.encoding.amino.AminoField; +import com.binance.dex.api.client.encoding.amino.AminoSerializable; +import com.binance.dex.api.client.encoding.message.common.Dec; + +import java.util.ArrayList; + +/** + * @author Fitz.Lu + **/ +public class DelegationValue implements AminoSerializable { + + private Dec shares = new Dec(); + + private long height; + + public DelegationValue() { + } + + public Dec getShares() { + return shares; + } + + public void setShares(Dec shares) { + this.shares = shares; + } + + public long getHeight() { + return height; + } + + public void setHeight(long height) { + this.height = height; + } + + @Override + public AminoSerializable newAminoMessage() { + return new DelegationValue(); + } + + @Override + public ArrayList> IterateFields() { + return AminoField.newFieldsBuilder() + .addField(Dec.class, shares, shares == null || shares.isDefaultOrEmpty()) + .addField(Long.class, height, height == 0) + .build(); + } + + @Override + public void setValueByFieldIndex(int fieldIndex, Object value) { + switch (fieldIndex) { + case 1: + shares = ((Dec) value); + break; + case 2: + height = ((Long) value); + break; + default: + break; + } + } +} diff --git a/src/main/java/com/binance/dex/api/client/encoding/message/sidechain/value/DescriptionValue.java b/src/main/java/com/binance/dex/api/client/encoding/message/sidechain/value/DescriptionValue.java new file mode 100644 index 0000000..425674a --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/encoding/message/sidechain/value/DescriptionValue.java @@ -0,0 +1,118 @@ +package com.binance.dex.api.client.encoding.message.sidechain.value; + +import com.binance.dex.api.client.encoding.amino.AminoField; +import com.binance.dex.api.client.encoding.amino.AminoSerializable; +import com.binance.dex.api.client.encoding.message.BinanceDexTransactionMessage; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import org.apache.commons.lang3.StringUtils; + +import java.util.ArrayList; + +/** + * @author Fitz.Lu + **/ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonPropertyOrder(alphabetic = true) +public class DescriptionValue implements BinanceDexTransactionMessage, AminoSerializable { + + @JsonProperty(value = "moniker") + private String moniker = ""; + + @JsonProperty(value = "identity") + private String identity = ""; + + @JsonProperty(value = "website") + private String website = ""; + + @JsonProperty(value = "details") + private String details = ""; + + public DescriptionValue() { + } + + public DescriptionValue(String moniker, String identity, String website, String details) { + this.moniker = moniker; + this.identity = identity; + this.website = website; + this.details = details; + } + + public String getMoniker() { + return moniker; + } + + public void setMoniker(String moniker) { + this.moniker = moniker; + } + + public String getIdentity() { + return identity; + } + + public void setIdentity(String identity) { + this.identity = identity; + } + + public String getWebsite() { + return website; + } + + public void setWebsite(String website) { + this.website = website; + } + + public String getDetails() { + return details; + } + + public void setDetails(String details) { + this.details = details; + } + + @Override + public String toString() { + return "Description{" + + "moniker='" + moniker + '\'' + + ", identity='" + identity + '\'' + + ", website='" + website + '\'' + + ", details='" + details + '\'' + + '}'; + } + + @Override + public AminoSerializable newAminoMessage() { + return new DescriptionValue(); + } + + @Override + public void setValueByFieldIndex(int fieldIndex, Object value) { + switch (fieldIndex) { + case 1: + moniker = ((String) value); + break; + case 2: + identity = ((String) value); + break; + case 3: + website = ((String) value); + break; + case 4: + details = ((String) value); + break; + default: + break; + } + } + + @Override + public ArrayList> IterateFields() { + ArrayList> fields = new ArrayList<>(); + fields.add(new AminoField<>(String.class, moniker, StringUtils.isEmpty(moniker))); + fields.add(new AminoField<>(String.class, identity, StringUtils.isEmpty(identity))); + fields.add(new AminoField<>(String.class, website, StringUtils.isEmpty(website))); + fields.add(new AminoField<>(String.class, details, StringUtils.isEmpty(details))); + return fields; + } +} diff --git a/src/main/java/com/binance/dex/api/client/encoding/message/sidechain/value/RedelegationValue.java b/src/main/java/com/binance/dex/api/client/encoding/message/sidechain/value/RedelegationValue.java new file mode 100644 index 0000000..1ae3822 --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/encoding/message/sidechain/value/RedelegationValue.java @@ -0,0 +1,120 @@ +package com.binance.dex.api.client.encoding.message.sidechain.value; + +import com.binance.dex.api.client.encoding.amino.AminoField; +import com.binance.dex.api.client.encoding.amino.AminoSerializable; +import com.binance.dex.api.client.encoding.message.common.CoinValueStr; +import com.binance.dex.api.client.encoding.message.common.Dec; + +import java.util.ArrayList; + +/** + * @author Fitz.Lu + **/ +public class RedelegationValue implements AminoSerializable { + + private long creationHeight; + + private TimestampValue minTime = new TimestampValue(); + + private CoinValueStr initialBalance = new CoinValueStr(); + + private CoinValueStr balance = new CoinValueStr(); + + private Dec sharesSrc = new Dec(); + + private Dec sharesDst = new Dec(); + + public RedelegationValue() { + } + + public long getCreationHeight() { + return creationHeight; + } + + public void setCreationHeight(long creationHeight) { + this.creationHeight = creationHeight; + } + + public TimestampValue getMinTime() { + return minTime; + } + + public void setMinTime(TimestampValue minTime) { + this.minTime = minTime; + } + + public CoinValueStr getInitialBalance() { + return initialBalance; + } + + public void setInitialBalance(CoinValueStr initialBalance) { + this.initialBalance = initialBalance; + } + + public CoinValueStr getBalance() { + return balance; + } + + public void setBalance(CoinValueStr balance) { + this.balance = balance; + } + + public Dec getSharesSrc() { + return sharesSrc; + } + + public void setSharesSrc(Dec sharesSrc) { + this.sharesSrc = sharesSrc; + } + + public Dec getSharesDst() { + return sharesDst; + } + + public void setSharesDst(Dec sharesDst) { + this.sharesDst = sharesDst; + } + + @Override + public AminoSerializable newAminoMessage() { + return new RedelegationValue(); + } + + @Override + public ArrayList> IterateFields() { + return AminoField.newFieldsBuilder() + .addField(Long.class, creationHeight, creationHeight == 0) + .addField(TimestampValue.class, minTime, minTime == null) + .addField(CoinValueStr.class, initialBalance, initialBalance == null) + .addField(CoinValueStr.class, balance, balance == null) + .addField(Dec.class, sharesSrc, sharesSrc == null) + .addField(Dec.class, sharesDst, sharesDst == null) + .build(); + } + + @Override + public void setValueByFieldIndex(int fieldIndex, Object value) { + switch (fieldIndex) { + case 1: + creationHeight = ((long) value); + break; + case 2: + minTime = ((TimestampValue) value); + break; + case 3: + initialBalance = ((CoinValueStr) value); + break; + case 4: + balance = ((CoinValueStr) value); + break; + case 5: + sharesSrc = ((Dec) value); + break; + case 6: + sharesDst = ((Dec) value); + break; + default: + break; + } + } +} diff --git a/src/main/java/com/binance/dex/api/client/encoding/message/sidechain/value/TimestampValue.java b/src/main/java/com/binance/dex/api/client/encoding/message/sidechain/value/TimestampValue.java new file mode 100644 index 0000000..7f3581f --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/encoding/message/sidechain/value/TimestampValue.java @@ -0,0 +1,66 @@ +package com.binance.dex.api.client.encoding.message.sidechain.value; + +import com.binance.dex.api.client.encoding.amino.AminoField; +import com.binance.dex.api.client.encoding.amino.AminoSerializable; + +import java.util.ArrayList; + +/** + * @author Fitz.Lu + **/ +public class TimestampValue implements AminoSerializable { + + private long seconds; + + private int nano; + + public TimestampValue() { + } + + public long getSeconds() { + return seconds; + } + + public void setSeconds(long seconds) { + this.seconds = seconds; + } + + public int getNano() { + return nano; + } + + public void setNano(int nano) { + this.nano = nano; + } + + public long getTimeInMilliseconds(){ + return seconds * 1000; + } + + @Override + public AminoSerializable newAminoMessage() { + return new TimestampValue(); + } + + @Override + public ArrayList> IterateFields() { + return AminoField.newFieldsBuilder() + .addField(Long.class, seconds, false) + .addField(Integer.class, nano, false) + .build(); + } + + @Override + public void setValueByFieldIndex(int fieldIndex, Object value) { + switch (fieldIndex) { + case 1: + seconds = ((Long) value); + break; + case 2: + nano = ((Integer) value); + break; + default: + break; + } + } +} diff --git a/src/main/java/com/binance/dex/api/client/encoding/message/sidechain/value/UnBondingValue.java b/src/main/java/com/binance/dex/api/client/encoding/message/sidechain/value/UnBondingValue.java new file mode 100644 index 0000000..db2eba8 --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/encoding/message/sidechain/value/UnBondingValue.java @@ -0,0 +1,91 @@ +package com.binance.dex.api.client.encoding.message.sidechain.value; + +import com.binance.dex.api.client.encoding.amino.AminoField; +import com.binance.dex.api.client.encoding.amino.AminoSerializable; +import com.binance.dex.api.client.encoding.message.common.CoinValueStr; + +import java.util.ArrayList; + +/** + * @author Fitz.Lu + **/ +public class UnBondingValue implements AminoSerializable { + + private long creationHeight; + + private TimestampValue minTime = new TimestampValue(); + + private CoinValueStr initialBalance = new CoinValueStr(); + + private CoinValueStr balance = new CoinValueStr(); + + public UnBondingValue() { + } + + public long getCreationHeight() { + return creationHeight; + } + + public void setCreationHeight(long creationHeight) { + this.creationHeight = creationHeight; + } + + public TimestampValue getMinTime() { + return minTime; + } + + public void setMinTime(TimestampValue minTime) { + this.minTime = minTime; + } + + public CoinValueStr getInitialBalance() { + return initialBalance; + } + + public void setInitialBalance(CoinValueStr initialBalance) { + this.initialBalance = initialBalance; + } + + public CoinValueStr getBalance() { + return balance; + } + + public void setBalance(CoinValueStr balance) { + this.balance = balance; + } + + @Override + public AminoSerializable newAminoMessage() { + return new UnBondingValue(); + } + + @Override + public ArrayList> IterateFields() { + return AminoField.newFieldsBuilder() + .addField(Long.class, creationHeight, creationHeight == 0) + .addField(TimestampValue.class, minTime, minTime == null) + .addField(CoinValueStr.class, initialBalance, initialBalance == null) + .addField(CoinValueStr.class, balance, balance == null) + .build(); + } + + @Override + public void setValueByFieldIndex(int fieldIndex, Object value) { + switch (fieldIndex) { + case 1: + creationHeight = ((Long) value); + break; + case 2: + minTime = ((TimestampValue) value); + break; + case 3: + initialBalance = ((CoinValueStr) value); + break; + case 4: + balance = ((CoinValueStr) value); + break; + default: + break; + } + } +} diff --git a/src/main/java/com/binance/dex/api/client/encoding/serializer/Bech32AddressValueToStringSerializer.java b/src/main/java/com/binance/dex/api/client/encoding/serializer/Bech32AddressValueToStringSerializer.java new file mode 100644 index 0000000..2f44607 --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/encoding/serializer/Bech32AddressValueToStringSerializer.java @@ -0,0 +1,37 @@ +package com.binance.dex.api.client.encoding.serializer; + +import com.binance.dex.api.client.encoding.Crypto; +import com.binance.dex.api.client.encoding.EncodeUtils; +import com.binance.dex.api.client.encoding.message.common.Bech32AddressValue; +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.ser.std.StdSerializer; +import org.apache.commons.lang3.StringUtils; + +import java.io.IOException; + +/** + * @author Fitz.Lu + **/ +public class Bech32AddressValueToStringSerializer extends StdSerializer { + + protected Bech32AddressValueToStringSerializer(){ + this(null); + } + + protected Bech32AddressValueToStringSerializer(Class t) { + super(t); + } + + @Override + public void serialize(Bech32AddressValue addressValue, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException { + if (addressValue != null && addressValue.getRaw() != null) { + if (StringUtils.isNotBlank(addressValue.getHrp())){ + jsonGenerator.writeString(Crypto.encodeAddress(addressValue.getHrp(), addressValue.getRaw())); + } else { + jsonGenerator.writeString(EncodeUtils.bytesToHex(addressValue.getRaw())); + } + } + } +} \ No newline at end of file diff --git a/src/main/java/com/binance/dex/api/client/encoding/serializer/Bech32AddressValuesToStringSerializer.java b/src/main/java/com/binance/dex/api/client/encoding/serializer/Bech32AddressValuesToStringSerializer.java new file mode 100644 index 0000000..5276dc2 --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/encoding/serializer/Bech32AddressValuesToStringSerializer.java @@ -0,0 +1,29 @@ +package com.binance.dex.api.client.encoding.serializer; + +import com.binance.dex.api.client.encoding.Crypto; +import com.binance.dex.api.client.encoding.message.common.Bech32AddressValue; +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; +import org.apache.commons.lang3.StringUtils; + +import java.io.IOException; +import java.util.List; +import java.util.stream.Collectors; + +public class Bech32AddressValuesToStringSerializer extends JsonSerializer> { + + @Override + public void serialize(List bech32AddressValues, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException { + if (bech32AddressValues != null) { + List msg = bech32AddressValues.stream().map(value -> { + if (value.getRaw() != null && StringUtils.isNotBlank(value.getHrp())) { + return Crypto.encodeAddress(value.getHrp(), value.getRaw()); + } else { + throw new RuntimeException("raw and hrp must not be empty"); + } + }).collect(Collectors.toList()); + jsonGenerator.writeObject(msg); + } + } +} diff --git a/src/main/java/com/binance/dex/api/client/encoding/serializer/ByteArrayToStringSerializer.java b/src/main/java/com/binance/dex/api/client/encoding/serializer/ByteArrayToStringSerializer.java new file mode 100644 index 0000000..f693298 --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/encoding/serializer/ByteArrayToStringSerializer.java @@ -0,0 +1,21 @@ +package com.binance.dex.api.client.encoding.serializer; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; + +import java.io.IOException; + +/** + * @author Fitz.Lu + **/ +public class ByteArrayToStringSerializer extends JsonSerializer { + + @Override + public void serialize(byte[] bytes, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException { + if(bytes != null){ + jsonGenerator.writeString(new String(bytes)); + } + } + +} diff --git a/src/main/java/com/binance/dex/api/client/encoding/serializer/BytesToPrefixedHexStringSerializer.java b/src/main/java/com/binance/dex/api/client/encoding/serializer/BytesToPrefixedHexStringSerializer.java new file mode 100644 index 0000000..67d2eda --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/encoding/serializer/BytesToPrefixedHexStringSerializer.java @@ -0,0 +1,18 @@ +package com.binance.dex.api.client.encoding.serializer; + +import com.binance.dex.api.client.encoding.EncodeUtils; +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; + +import java.io.IOException; + +public class BytesToPrefixedHexStringSerializer extends JsonSerializer { + + @Override + public void serialize(byte[] bytes, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException { + if(bytes != null){ + jsonGenerator.writeString(EncodeUtils.bytesToPrefixHex(bytes)); + } + } +} diff --git a/src/main/java/com/binance/dex/api/client/encoding/serializer/DecToStringSerializer.java b/src/main/java/com/binance/dex/api/client/encoding/serializer/DecToStringSerializer.java new file mode 100644 index 0000000..92a478e --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/encoding/serializer/DecToStringSerializer.java @@ -0,0 +1,20 @@ +package com.binance.dex.api.client.encoding.serializer; + +import com.binance.dex.api.client.encoding.message.common.Dec; +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; + +import java.io.IOException; + +/** + * @author Fitz.Lu + **/ +public class DecToStringSerializer extends JsonSerializer { + @Override + public void serialize(Dec dec, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException { + if (dec != null) { + jsonGenerator.writeString(String.valueOf(dec.getValue())); + } + } +} diff --git a/src/main/java/com/binance/dex/api/client/encoding/serializer/EthAddressValueToStringSerializer.java b/src/main/java/com/binance/dex/api/client/encoding/serializer/EthAddressValueToStringSerializer.java new file mode 100644 index 0000000..5268b6c --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/encoding/serializer/EthAddressValueToStringSerializer.java @@ -0,0 +1,30 @@ +package com.binance.dex.api.client.encoding.serializer; + +import com.binance.dex.api.client.encoding.message.common.EthAddressValue; +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.ser.std.StdSerializer; + +import java.io.IOException; + +/** + * @author Fitz.Lu + **/ +public class EthAddressValueToStringSerializer extends StdSerializer { + + protected EthAddressValueToStringSerializer(){ + this(null); + } + + protected EthAddressValueToStringSerializer(Class t) { + super(t); + } + + @Override + public void serialize(EthAddressValue ethAddressValue, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException { + if (ethAddressValue != null && ethAddressValue.getAddress() != null){ + jsonGenerator.writeString(ethAddressValue.getAddress()); + } + } +} diff --git a/src/main/java/com/binance/dex/api/client/encoding/serializer/LongToHexStringSerializer.java b/src/main/java/com/binance/dex/api/client/encoding/serializer/LongToHexStringSerializer.java new file mode 100644 index 0000000..5f2a433 --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/encoding/serializer/LongToHexStringSerializer.java @@ -0,0 +1,17 @@ +package com.binance.dex.api.client.encoding.serializer; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; + +import java.io.IOException; + +public class LongToHexStringSerializer extends JsonSerializer { + + @Override + public void serialize(Long aLong, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException { + if (aLong != null) { + jsonGenerator.writeString("0x" + Long.toHexString(aLong)); + } + } +} diff --git a/src/main/java/com/binance/dex/api/client/encoding/serializer/LongToStringSerializer.java b/src/main/java/com/binance/dex/api/client/encoding/serializer/LongToStringSerializer.java new file mode 100644 index 0000000..a7b4d3a --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/encoding/serializer/LongToStringSerializer.java @@ -0,0 +1,17 @@ +package com.binance.dex.api.client.encoding.serializer; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; + +import java.io.IOException; + +/** + * @author Fitz.Lu + **/ +public class LongToStringSerializer extends JsonSerializer { + @Override + public void serialize(Long aLong, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException { + jsonGenerator.writeString(String.valueOf(aLong)); + } +} diff --git a/src/main/java/com/binance/dex/api/client/encoding/serializer/TokenSymbolSerializer.java b/src/main/java/com/binance/dex/api/client/encoding/serializer/TokenSymbolSerializer.java new file mode 100644 index 0000000..f093829 --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/encoding/serializer/TokenSymbolSerializer.java @@ -0,0 +1,27 @@ +package com.binance.dex.api.client.encoding.serializer; + +import com.binance.dex.api.client.crosschain.TokenSymbol; +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.ser.std.StdSerializer; +import org.apache.commons.lang3.StringUtils; + +import java.io.IOException; + +public class TokenSymbolSerializer extends StdSerializer { + + protected TokenSymbolSerializer(){ + this(null); + } + + protected TokenSymbolSerializer(Class t) { + super(t); + } + + @Override + public void serialize(TokenSymbol tokenSymbol, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException { + if (tokenSymbol != null && StringUtils.isNotBlank(tokenSymbol.getSymbol())){ + jsonGenerator.writeString(tokenSymbol.getSymbol()); + } + } +} diff --git a/src/main/java/com/binance/dex/api/client/encoding/serializer/UnsignedNumberSerializer.java b/src/main/java/com/binance/dex/api/client/encoding/serializer/UnsignedNumberSerializer.java new file mode 100644 index 0000000..66dfe04 --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/encoding/serializer/UnsignedNumberSerializer.java @@ -0,0 +1,25 @@ +package com.binance.dex.api.client.encoding.serializer; + +import com.binance.dex.api.client.crosschain.UnsignedNumber; +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.ser.std.StdSerializer; + +import java.io.IOException; + +public class UnsignedNumberSerializer extends StdSerializer { + + protected UnsignedNumberSerializer() { + this(null); + } + + + protected UnsignedNumberSerializer(Class t) { + super(t); + } + + @Override + public void serialize(UnsignedNumber unsignedNumber, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException { + jsonGenerator.writeNumber(unsignedNumber.getNumber()); + } +} diff --git a/src/main/java/com/binance/dex/api/client/impl/BinanceDexApiNodeClientImpl.java b/src/main/java/com/binance/dex/api/client/impl/BinanceDexApiNodeClientImpl.java index f820b44..b8fd8e6 100644 --- a/src/main/java/com/binance/dex/api/client/impl/BinanceDexApiNodeClientImpl.java +++ b/src/main/java/com/binance/dex/api/client/impl/BinanceDexApiNodeClientImpl.java @@ -2,13 +2,20 @@ import com.binance.dex.api.client.*; import com.binance.dex.api.client.domain.*; +import com.binance.dex.api.client.domain.bridge.TransferIn; +import com.binance.dex.api.client.domain.broadcast.SideVote; +import com.binance.dex.api.client.domain.oracle.Prophecy; import com.binance.dex.api.client.domain.StakeValidator; +import com.binance.dex.api.client.domain.stake.Pool; +import com.binance.dex.api.client.domain.stake.sidechain.*; import com.binance.dex.api.client.domain.broadcast.Transaction; import com.binance.dex.api.client.domain.broadcast.*; import com.binance.dex.api.client.domain.jsonrpc.*; import com.binance.dex.api.client.encoding.Crypto; import com.binance.dex.api.client.encoding.EncodeUtils; import com.binance.dex.api.client.encoding.message.TransactionRequestAssembler; +import com.binance.dex.api.client.encoding.message.sidechain.query.QuerySideProposal; +import com.binance.dex.api.client.impl.node.*; import com.binance.dex.api.proto.*; import com.binance.dex.api.proto.Token; import com.google.common.collect.Lists; @@ -28,10 +35,12 @@ public class BinanceDexApiNodeClientImpl implements BinanceDexApiNodeClient { - private BinanceDexNodeApi binanceDexNodeApi; + protected BinanceDexNodeApi binanceDexNodeApi; private String hrp; + private String valHrp; + private TransactionConverter transactionConverter; private FeeConverter feeConverter; @@ -42,11 +51,25 @@ public class BinanceDexApiNodeClientImpl implements BinanceDexApiNodeClient { private final static int TX_SEARCH_PERPAGE = 10000; - public BinanceDexApiNodeClientImpl(String nodeUrl, String hrp) { + private final NodeTxDelegateSideChainStaking sideChainStakingTxDelegate; + + private final NodeTxDelegateBridge bridgeTxDelegate; + + private final NodeQueryDelegateSideChainStaking sideChainQueryDelegate; + + private final NodeQueryDelegateOracle oracleQueryDelegate; + + public BinanceDexApiNodeClientImpl(String nodeUrl, String hrp, String valHrp) { this.binanceDexNodeApi = BinanceDexApiClientGenerator.createService(BinanceDexNodeApi.class, nodeUrl); this.hrp = hrp; - transactionConverter = new TransactionConverter(hrp); + this.valHrp = valHrp; + transactionConverter = new TransactionConverter(hrp, valHrp); feeConverter = new FeeConverter(); + + sideChainStakingTxDelegate = new NodeTxDelegateSideChainStaking(binanceDexNodeApi, hrp, valHrp); + bridgeTxDelegate = new NodeTxDelegateBridge(binanceDexNodeApi, hrp, valHrp); + sideChainQueryDelegate = new NodeQueryDelegateSideChainStaking(binanceDexNodeApi, hrp, valHrp); + oracleQueryDelegate = new NodeQueryDelegateOracle(binanceDexNodeApi, hrp, valHrp); } @Override @@ -86,11 +109,11 @@ public List getFees() { @Override public Account getAccount(String address) { try { - String queryPath = String.format("\"/account/%s\"",address); + String queryPath = String.format("\"/account/%s\"", address); JsonRpcResponse response = BinanceDexApiClientGenerator.executeSync(binanceDexNodeApi.getAccount(queryPath)); checkRpcResult(response); byte[] value = response.getResult().getResponse().getValue(); - if(value != null && value.length > 0){ + if (value != null && value.length > 0) { byte[] array = new byte[value.length - 4]; System.arraycopy(value, 4, array, 0, array.length); AppAccount account = AppAccount.parseFrom(array); @@ -109,7 +132,7 @@ public Account getCommittedAccount(String address) { JsonRpcResponse response = BinanceDexApiClientGenerator.executeSync(binanceDexNodeApi.getCommittedAccount(encodedAddress)); checkRpcResult(response); byte[] value = response.getResult().getResponse().getValue(); - if(value != null && value.length > 0){ + if (value != null && value.length > 0) { byte[] array = new byte[value.length - 4]; System.arraycopy(value, 4, array, 0, array.length); AppAccount account = AppAccount.parseFrom(array); @@ -122,7 +145,7 @@ public Account getCommittedAccount(String address) { } @Override - public AtomicSwap getSwapByID(String swapID){ + public AtomicSwap getSwapByID(String swapID) { try { Map.Entry swapIdEntry = Maps.immutableEntry("SwapID", swapID); String requestData = "0x" + Hex.toHexString(EncodeUtils.toJsonStringSortKeys(swapIdEntry).getBytes()); @@ -145,7 +168,7 @@ public AtomicSwap getSwapByID(String swapID){ @Override public List getBlockTransactions(Long height) { JsonRpcResponse response = BinanceDexApiClientGenerator.executeSync(binanceDexNodeApi - .getBlockTransactions("\"tx.height=" + height.toString() + "\"",TX_SEARCH_PAGE,TX_SEARCH_PERPAGE)); + .getBlockTransactions("\"tx.height=" + height.toString() + "\"", TX_SEARCH_PAGE, TX_SEARCH_PERPAGE)); checkRpcResult(response); return response.getResult().getTxs().stream() .map(transactionConverter::convert) @@ -178,7 +201,7 @@ public Transaction getTransaction(String hash) { transactions.get(0).setHash(transactionResult.getHash()); transactions.get(0).setCode(transactionResult.getTxResult().getCode()); transactions.get(0).setLog(transactionResult.getTxResult().getLog()); - transactionConverter.fillTagsAndEvents(transactionResult.getTxResult(),transactions.get(0)); + transactionConverter.fillTagsAndEvents(transactionResult.getTxResult(), transactions.get(0)); return transactions.get(0); } @@ -254,6 +277,31 @@ public Proposal getProposalById(String proposalId) { } } + @Override + public Proposal getSideProposalById(String proposalId, String sideChainId) { + try { + QuerySideProposal params = new QuerySideProposal(); + params.setSideChainId(sideChainId); + params.setProposalID(proposalId); + + byte[] paramsBytes = EncodeUtils.toJsonEncodeBytes(params); + String requestData = "0x" + Hex.toHexString(paramsBytes); + JsonRpcResponse rpcResponse = BinanceDexApiClientGenerator.executeSync(binanceDexNodeApi.getProposalById(requestData)); + checkRpcResult(rpcResponse); + ABCIQueryResult.Response response = rpcResponse.getResult().getResponse(); + if (response.getCode() != null) { + BinanceDexApiError binanceDexApiError = new BinanceDexApiError(); + binanceDexApiError.setCode(response.getCode()); + binanceDexApiError.setMessage(response.getLog()); + throw new BinanceDexApiException(binanceDexApiError); + } + String proposalJson = new String(response.getValue()); + return EncodeUtils.toObjectFromJsonString(proposalJson, Proposal.class); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + @Override public List transfer(Transfer transfer, Wallet wallet, TransactionOption options, boolean sync) @@ -304,7 +352,7 @@ public List depositHtlt(String swapId, List claimHtlt(String swapId, byte[] randomNumber, W synchronized (wallet) { wallet.ensureWalletIsReady(this); TransactionRequestAssembler assembler = new TransactionRequestAssembler(wallet, options); - String requestPayload = "0x" + assembler.buildClaimHtltPayload(swapId,randomNumber); + String requestPayload = "0x" + assembler.buildClaimHtltPayload(swapId, randomNumber); if (sync) { return syncBroadcast(requestPayload, wallet); } else { @@ -341,6 +389,162 @@ public List refundHtlt(String swapId, Wallet wallet, Transa } } + @Override + public List createSideChainValidator(CreateSideChainValidator createSideChainValidator, Wallet wallet, TransactionOption options, boolean sync) throws IOException, NoSuchAlgorithmException { + synchronized (wallet) { + wallet.ensureWalletIsReady(this); + return sideChainStakingTxDelegate.createSideChainValidator(createSideChainValidator, wallet, options, sync); + } + } + + @Override + public List editSideChainValidator(EditSideChainValidator editSideChainValidator, Wallet wallet, TransactionOption options, boolean sync) throws IOException, NoSuchAlgorithmException { + synchronized (wallet) { + wallet.ensureWalletIsReady(this); + return sideChainStakingTxDelegate.editSideChainValidator(editSideChainValidator, wallet, options, sync); + } + } + + @Override + public List sideChainDelegate(SideChainDelegate sideChainDelegate, Wallet wallet, TransactionOption options, boolean sync) throws IOException, NoSuchAlgorithmException { + synchronized (wallet) { + wallet.ensureWalletIsReady(this); + return sideChainStakingTxDelegate.sideChainDelegate(sideChainDelegate, wallet, options, sync); + } + } + + @Override + public List sideChainRedelagate(SideChainRedelegate sideChainRedelegate, Wallet wallet, TransactionOption options, boolean sync) throws IOException, NoSuchAlgorithmException { + synchronized (wallet) { + wallet.ensureWalletIsReady(this); + return sideChainStakingTxDelegate.sideChainRedelagate(sideChainRedelegate, wallet, options, sync); + } + } + + @Override + public List sideChainUnbond(SideChainUnBond sideChainUndelegate, Wallet wallet, TransactionOption options, boolean sync) throws IOException, NoSuchAlgorithmException { + synchronized (wallet) { + wallet.ensureWalletIsReady(this); + return sideChainStakingTxDelegate.sideChainUnbond(sideChainUndelegate, wallet, options, sync); + } + } + + @Override + public SideChainValidator getSideChainValidator(String sideChainId, String validatorAddress) throws IOException { + return sideChainQueryDelegate.querySideChainValidator(sideChainId, validatorAddress); + } + + @Override + public List getSideChainTopValidators(String sideChainId, int top) throws IOException { + return sideChainQueryDelegate.querySideChainTopValidators(sideChainId, top); + } + + @Override + public SideChainDelegation getSideChainDelegation(String sideChainId, String delegatorAddress, String validatorAddress) throws IOException { + return sideChainQueryDelegate.querySideChainDelegation(sideChainId, delegatorAddress, validatorAddress); + } + + @Override + public List getSideChainDelegations(String sideChainId, String delegatorAddress) throws IOException { + return sideChainQueryDelegate.querySideChainDelegations(sideChainId, delegatorAddress); + } + + @Override + public SideChainRedelegation getSideChainRedelegation(String sideChainId, String delegatorAddress, String srcValidatorAddress, String dstValidatorAddress) throws IOException { + return sideChainQueryDelegate.querySideChainRedelegation(sideChainId, delegatorAddress, srcValidatorAddress, dstValidatorAddress); + } + + @Override + public List getSideChainRedelegations(String sideChainId, String delegatorAddress) throws IOException { + return sideChainQueryDelegate.querySideChainRedelegations(sideChainId, delegatorAddress); + } + + @Override + public UnBondingDelegation getSideChainUnBondingDelegation(String sideChainId, String delegatorAddress, String validatorAddress) throws IOException { + return sideChainQueryDelegate.querySideChainUnBondingDelegation(sideChainId, delegatorAddress, validatorAddress); + } + + @Override + public List getSideChainUnBondingDelegations(String sideChainId, String delegatorAddress) throws IOException { + return sideChainQueryDelegate.querySideChainUnBondingDelegations(sideChainId, delegatorAddress); + } + + @Override + public List getSideChainUnBondingDelegationsByValidator(String sideChainId, String validatorAddress) throws IOException{ + return sideChainQueryDelegate.querySideChainUnBondingDelegationsByValidator(sideChainId, validatorAddress); + } + + @Override + public List getSideChainRedelegationsByValidator(String sideChainId, String validatorAddress) throws IOException { + return sideChainQueryDelegate.querySideChainRedelegationsByValidator(sideChainId, validatorAddress); + } + + @Override + public Pool getSideChainPool(String sideChainId) throws IOException { + return sideChainQueryDelegate.querySideChainPool(sideChainId); + } + + @Override + public long getAllSideChainValidatorsCount(String sideChainId, boolean jailInvolved) throws IOException { + return sideChainQueryDelegate.queryAllSideChainValidatorsCount(sideChainId, jailInvolved); + } + + @Override + public List sideVote(SideVote vote, Wallet wallet, TransactionOption options, boolean sync) throws IOException, NoSuchAlgorithmException{ + synchronized (wallet) { + wallet.ensureWalletIsReady(this); + TransactionRequestAssembler assembler = new TransactionRequestAssembler(wallet, options); + String requestPayload = "0x" + assembler.buildSideVotePayload(vote); + if (sync) { + return syncBroadcast(requestPayload, wallet); + } else { + return asyncBroadcast(requestPayload, wallet); + } + } + } + + @Override + public List transferOut(String toAddress, com.binance.dex.api.client.encoding.message.Token amount, long expireTimeInSeconds, Wallet wallet, TransactionOption options, boolean sync) throws IOException, NoSuchAlgorithmException { + synchronized (wallet) { + wallet.ensureWalletIsReady(this); + return bridgeTxDelegate.transferOut(toAddress, amount, expireTimeInSeconds, wallet, options, sync); + } + } + + @Override + public List bind(String symbol, long amount, String contractAddress, int contractDecimal, long expireTimeInSeconds, Wallet wallet, TransactionOption options, boolean sync) throws IOException, NoSuchAlgorithmException { + synchronized (wallet) { + wallet.ensureWalletIsReady(this); + return bridgeTxDelegate.bind(symbol, amount, contractAddress, contractDecimal, expireTimeInSeconds, wallet, options, sync); + } + } + + @Override + public List unBind(String symbol, Wallet wallet, TransactionOption options, boolean sync) throws IOException, NoSuchAlgorithmException { + synchronized (wallet) { + wallet.ensureWalletIsReady(this); + return bridgeTxDelegate.unBind(symbol, wallet, options, sync); + } + } + + @Override + public List claim(int chainId, byte[] payload, long sequence, Wallet wallet, TransactionOption options, boolean sync) throws IOException, NoSuchAlgorithmException { + synchronized (wallet) { + wallet.ensureWalletIsReady(this); + return bridgeTxDelegate.claim(chainId, payload, sequence, wallet, options, sync); + } + } + + @Override + public Prophecy getProphecy(int claimType, long sequence) throws IOException { + return oracleQueryDelegate.getProphecy(claimType, sequence); + } + + @Override + public long getCurrentSequence(int claimType) { + return oracleQueryDelegate.getCurrentSequence(claimType); + } + @Override public List broadcast(String payload, boolean sync) { payload = "0x" + payload; diff --git a/src/main/java/com/binance/dex/api/client/impl/BinanceDexApiRestClientImpl.java b/src/main/java/com/binance/dex/api/client/impl/BinanceDexApiRestClientImpl.java index e6fa28b..3b3501f 100644 --- a/src/main/java/com/binance/dex/api/client/impl/BinanceDexApiRestClientImpl.java +++ b/src/main/java/com/binance/dex/api/client/impl/BinanceDexApiRestClientImpl.java @@ -280,6 +280,14 @@ public List vote(Vote vote, Wallet wallet, TransactionOptio return broadcast(requestBody,sync,wallet); } + @Override + public List sideVote(SideVote vote, Wallet wallet, TransactionOption options, boolean sync) throws IOException, NoSuchAlgorithmException { + wallet.ensureWalletIsReady(this); + TransactionRequestAssembler assembler = new TransactionRequestAssembler(wallet, options); + RequestBody requestBody = assembler.buildSideVote(vote); + return broadcast(requestBody,sync,wallet); + } + public List cancelOrder(CancelOrder cancelOrder, Wallet wallet, TransactionOption options, boolean sync) throws IOException, NoSuchAlgorithmException { wallet.ensureWalletIsReady(this); diff --git a/src/main/java/com/binance/dex/api/client/impl/node/NodeQuery.java b/src/main/java/com/binance/dex/api/client/impl/node/NodeQuery.java new file mode 100644 index 0000000..9343ee3 --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/impl/node/NodeQuery.java @@ -0,0 +1,107 @@ +package com.binance.dex.api.client.impl.node; + +import com.binance.dex.api.client.BinanceDexApiClientGenerator; +import com.binance.dex.api.client.BinanceDexApiError; +import com.binance.dex.api.client.BinanceDexApiException; +import com.binance.dex.api.client.BinanceDexNodeApi; +import com.binance.dex.api.client.domain.jsonrpc.ABCIQueryResult; +import com.binance.dex.api.client.domain.jsonrpc.JsonRpcResponse; +import com.binance.dex.api.client.encoding.ByteUtil; +import com.google.protobuf.CodedInputStream; +import com.google.protobuf.InvalidProtocolBufferException; +import common.Types; +import org.bouncycastle.util.encoders.Hex; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +/** + * @author Fitz.Lu + **/ +class NodeQuery { + + private final BinanceDexNodeApi binanceDexNodeApi; + + protected final String hrp; + + protected final String valHrp; + + public NodeQuery(BinanceDexNodeApi binanceDexNodeApi, String hrp, String valHrp) { + this.binanceDexNodeApi = binanceDexNodeApi; + this.hrp = hrp; + this.valHrp = valHrp; + } + + protected byte[] queryWithData(String path, byte[] data){ + String d = "0x" + Hex.toHexString(data); + JsonRpcResponse rpcResponse = BinanceDexApiClientGenerator.executeSync(binanceDexNodeApi.abciQuery(path, d)); + checkABCIResponse(rpcResponse); + + return rpcResponse.getResult().getResponse().getValue(); + } + + protected byte[] queryStore(String storeName, byte[] key){ + String keyHex = "0x" + Hex.toHexString(key); + String path = String.format("\"/store/%s/%s\"", storeName, "key"); + JsonRpcResponse rpcResponse = BinanceDexApiClientGenerator.executeSync(binanceDexNodeApi.abciQuery(path, keyHex)); + checkABCIResponse(rpcResponse); + + return rpcResponse.getResult().getResponse().getValue(); + } + + protected byte[] queryStoreSubspace(String storeName, byte[] key){ + String keyHex = "0x" + Hex.toHexString(key); + String path = String.format("\"/store/%s/subspace\"", storeName); + JsonRpcResponse rpcResponse = BinanceDexApiClientGenerator.executeSync(binanceDexNodeApi.abciQuery(path, keyHex)); + checkABCIResponse(rpcResponse); + + return rpcResponse.getResult().getResponse().getValue(); + } + + protected List queryStoreSubspaceKVPairs(String storeName, byte[] key) throws IOException { + String keyHex = "0x" + Hex.toHexString(key); + String path = String.format("\"/store/%s/subspace\"", storeName); + JsonRpcResponse rpcResponse = BinanceDexApiClientGenerator.executeSync(binanceDexNodeApi.abciQuery(path, keyHex)); + checkABCIResponse(rpcResponse); + + byte[] result = rpcResponse.getResult().getResponse().getValue(); + + if (!ByteUtil.isEmpty(result)) { + try { + CodedInputStream codedInputStream = CodedInputStream.newInstance(result); + + if (codedInputStream.isAtEnd()){ + return new ArrayList<>(); + } + //read length prefix + int length = codedInputStream.readRawVarint32(); + if (length == 0){ + return new ArrayList<>(); + } + + types.Types.KVPairs kvPairs = types.Types.KVPairs.parseFrom(codedInputStream); + + return kvPairs.getPairsList(); + }catch (InvalidProtocolBufferException e){ + throw new IOException("Decode response failed due to: " + e.getMessage()); + } + }else{ + return new ArrayList<>(); + } + } + + protected void checkABCIResponse(JsonRpcResponse rpcResponse) { + if (null != rpcResponse.getError() && null != rpcResponse.getError().getCode()) { + throw new RuntimeException(rpcResponse.getError().toString()); + } + ABCIQueryResult.Response response = rpcResponse.getResult().getResponse(); + if (response.getCode() != null) { + BinanceDexApiError binanceDexApiError = new BinanceDexApiError(); + binanceDexApiError.setCode(response.getCode()); + binanceDexApiError.setMessage(response.getLog()); + throw new BinanceDexApiException(binanceDexApiError); + } + } + +} diff --git a/src/main/java/com/binance/dex/api/client/impl/node/NodeQueryDelegateOracle.java b/src/main/java/com/binance/dex/api/client/impl/node/NodeQueryDelegateOracle.java new file mode 100644 index 0000000..4bbd1f4 --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/impl/node/NodeQueryDelegateOracle.java @@ -0,0 +1,91 @@ +package com.binance.dex.api.client.impl.node; + +import com.binance.dex.api.client.BinanceDexNodeApi; +import com.binance.dex.api.client.domain.oracle.Prophecy; +import com.binance.dex.api.client.domain.oracle.Status; +import com.binance.dex.api.client.encoding.Bech32; +import com.binance.dex.api.client.encoding.ByteUtil; +import com.binance.dex.api.client.encoding.EncodeUtils; +import com.binance.dex.api.client.encoding.amino.Amino; +import com.binance.dex.api.client.encoding.message.bridge.DBProphecy; +import com.fasterxml.jackson.core.type.TypeReference; +import com.google.common.base.Charsets; + +import javax.annotation.Nullable; +import java.io.IOException; +import java.nio.ByteOrder; +import java.util.HashMap; +import java.util.Map; + +/** + * @author Fitz.Lu + **/ +public class NodeQueryDelegateOracle extends NodeQuery { + + private static final String oracleStoreName = "oracle"; + + private static final String claimTypeSequencePrefix = "claimTypeSeq:"; + + private static final Amino amino = new Amino(); + + public NodeQueryDelegateOracle(BinanceDexNodeApi binanceDexNodeApi, String hrp, String valHrp) { + super(binanceDexNodeApi, hrp, valHrp); + } + + @Nullable + public Prophecy getProphecy(int claimType, long sequence) throws IOException { + byte[] key = getClaimId(claimType, sequence).getBytes(Charsets.UTF_8); + byte[] result = queryStore(oracleStoreName, key); + + if (!ByteUtil.isEmpty(result)){ + DBProphecy prophecy = new DBProphecy(); + amino.decodeBare(result, prophecy); + return convert(prophecy); + } + + return null; + } + + public long getCurrentSequence(int claimType){ + byte[] key = getClaimTypeSequence(claimType); + byte[] result = queryStore(oracleStoreName, key); + if (!ByteUtil.isEmpty(result)){ + return java.nio.ByteBuffer.wrap(result).order(ByteOrder.BIG_ENDIAN).getLong(); + } + + return 0; + } + + private Prophecy convert(DBProphecy dbProphecy) throws IOException { + Prophecy prophecy = new Prophecy(); + HashMap validatorClaims; + validatorClaims = EncodeUtils.getObjectMapper().readValue(new String(dbProphecy.getValidatorClaims()), new TypeReference>(){}); + + HashMap claimValidators = new HashMap<>(); + for (Map.Entry entry : validatorClaims.entrySet()) { + claimValidators.put(entry.getValue(), Bech32.decode(entry.getKey()).getData()); + } + + prophecy.setId(dbProphecy.getId()); + + Status status = new Status(); + if (dbProphecy.getStatus() != null){ + status.setText(dbProphecy.getStatus().getText()); + status.setFinalClaim(dbProphecy.getStatus().getFinalClaim()); + } + prophecy.setStatus(status); + prophecy.setValidatorClaims(validatorClaims); + prophecy.setClaimValidators(claimValidators); + + return prophecy; + } + + private String getClaimId(int claimType, long sequence) { + return String.format("%d:%d", claimType, sequence); + } + + private byte[] getClaimTypeSequence(int claimType){ + return ByteUtil.appendBytesArray(claimTypeSequencePrefix.getBytes(Charsets.UTF_8), new byte[]{((byte) claimType)}); + } + +} diff --git a/src/main/java/com/binance/dex/api/client/impl/node/NodeQueryDelegateSideChainStaking.java b/src/main/java/com/binance/dex/api/client/impl/node/NodeQueryDelegateSideChainStaking.java new file mode 100644 index 0000000..1f7abe7 --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/impl/node/NodeQueryDelegateSideChainStaking.java @@ -0,0 +1,515 @@ +package com.binance.dex.api.client.impl.node; + +import com.binance.dex.api.client.*; +import com.binance.dex.api.client.domain.stake.Commission; +import com.binance.dex.api.client.domain.stake.Description; +import com.binance.dex.api.client.domain.stake.Pool; +import com.binance.dex.api.client.domain.stake.sidechain.*; +import com.binance.dex.api.client.domain.stake.sidechain.Delegation; +import com.binance.dex.api.client.encoding.ByteUtil; +import com.binance.dex.api.client.encoding.Crypto; +import com.binance.dex.api.client.encoding.EncodeUtils; +import com.binance.dex.api.client.encoding.amino.Amino; +import com.binance.dex.api.client.encoding.amino.InternalAmino; +import com.binance.dex.api.client.encoding.amino.WireType; +import com.binance.dex.api.client.encoding.message.Token; +import com.binance.dex.api.client.encoding.message.common.Bech32AddressValue; +import com.binance.dex.api.client.encoding.message.common.CoinValue; +import com.binance.dex.api.client.encoding.message.sidechain.query.*; +import com.binance.dex.api.client.encoding.message.sidechain.value.RedelegationValue; +import com.binance.dex.api.client.encoding.message.sidechain.value.UnBondingValue; +import com.fasterxml.jackson.core.type.TypeReference; +import com.google.common.base.Charsets; + +import java.io.IOException; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.List; + +/** + * @author Fitz.Lu + **/ +public class NodeQueryDelegateSideChainStaking extends NodeQuery { + + private final String stakeStoreName = "stake"; + private final String scStoreKey = "sc"; + + private static final int addressLength = 20; + + private final byte[] sideChainStorePrefixByIdKey = new byte[]{0x01}; + private final byte[] validatorsKey = new byte[]{0x21}; + private final byte[] delegationKey = new byte[]{0x31}; + private final byte[] redelegationKey = new byte[]{0x34}; + private final byte[] unBondingDelegationKey = new byte[]{0x32}; + private final byte[] poolKey = new byte[]{0x01}; + + private final Charset defaultCharset = Charsets.UTF_8; + + private final Amino amino; + + public NodeQueryDelegateSideChainStaking(BinanceDexNodeApi binanceDexNodeApi, String hrp, String valHrp) { + super(binanceDexNodeApi, hrp, valHrp); + amino = InternalAmino.get(); + } + + public SideChainValidator querySideChainValidator(String sideChainId, String validatorAddress) throws IOException { + byte[] storePrefix = getSideChainStorePrefixKey(sideChainId); + byte[] key = ByteUtil.appendBytesArray(storePrefix, getValidatorKey(Crypto.decodeAddress(validatorAddress))); + byte[] result = queryStore(stakeStoreName, key); + + if (result != null) { + SideChainValidatorMessage message = new SideChainValidatorMessage(); + amino.decodeWithLengthPrefix(result, message); + return convert(message); + }else{ + return null; + } + } + + public List querySideChainTopValidators(String sideChainId, int top) throws IOException { + if (top > 50 || top < 1){ + throw new IllegalArgumentException("top must be between 1 and 50"); + } + + QueryTopValidatorParams params = new QueryTopValidatorParams(); + params.setSideChainId(sideChainId); + params.setTop(top); + byte[] data = EncodeUtils.toJsonEncodeBytes(params); + byte[] result = queryWithData("\"custom/stake/topValidators\"", data); + + String jsonStr = new String(result); + + List bechValidator = EncodeUtils.getObjectMapper().readValue(jsonStr, new TypeReference>(){}); + + List sideChainValidators = new ArrayList<>(); + + if (bechValidator != null && !bechValidator.isEmpty()){ + for (BechValidator validator : bechValidator) { + sideChainValidators.add(validator.toSideChainValidator()); + } + } + + return sideChainValidators; + } + + private SideChainValidator convert(SideChainValidatorMessage message){ + SideChainValidator sideChainValidator = new SideChainValidator(); + + if (message.getFeeAddr() != null) { + sideChainValidator.setFeeAddr(EncodeUtils.bytesToPrefixHex(message.getFeeAddr())); + } + if (message.getOperatorAddr() != null) { + sideChainValidator.setOperatorAddr(Crypto.encodeAddress(valHrp, message.getOperatorAddr())); + } + + //TODO consPubKey use amino decode with type prefix + if (message.getConsPubKey() != null) { + boolean fallBack = true; + byte[] typePrefix = ByteUtil.pick(message.getConsPubKey(), 0, 4); + if (WireType.isRegistered(typePrefix)) { + byte length = ByteUtil.pick(message.getConsPubKey(), 4, 1)[0]; + int len = Byte.toUnsignedInt(length); + if (message.getConsPubKey().length - 5 == len) { + sideChainValidator.setConsPubKey(ByteUtil.cut(message.getConsPubKey(), 5)); + fallBack = false; + } + } + if (fallBack) { + sideChainValidator.setConsPubKey(message.getConsPubKey()); + } + } + + if (message.getDistributionAddr() != null){ + sideChainValidator.setDistributionAddr(Crypto.encodeAddress(hrp, message.getDistributionAddr())); + } + + sideChainValidator.setJailed(message.isJailed()); + sideChainValidator.setStatus(message.getStatus()); + sideChainValidator.setTokens(message.getTokens().getValue()); + sideChainValidator.setDelegatorShares(message.getDelegatorShares().getValue()); + + Description description = new Description(); + if (message.getDescription() != null){ + description.setMoniker(message.getDescription().getMoniker()); + description.setWebsite(message.getDescription().getWebsite()); + description.setDetails(message.getDescription().getDetails()); + description.setIdentity(message.getDescription().getIdentity()); + } + sideChainValidator.setDescription(description); + + sideChainValidator.setBondHeight(message.getBondHeight()); + sideChainValidator.setBondIntraTxCounter(message.getBondIntraTxCounter()); + sideChainValidator.setUnBondingHeight(message.getUnBondingHeight()); + sideChainValidator.setUnBondingMinTime(message.getUnBondingMinTime()); + + Commission commission = new Commission(); + if (message.getCommission() != null) { + if (message.getCommission().getRate() != null) { + commission.setRate(message.getCommission().getRate().getValue()); + } + if (message.getCommission().getMaxRate() != null) { + commission.setMaxRate(message.getCommission().getMaxRate().getValue()); + } + if (message.getCommission().getMaxChangeRate() != null) { + commission.setMaxChangeRate(message.getCommission().getMaxChangeRate().getValue()); + } + } + sideChainValidator.setCommission(commission); + + sideChainValidator.setSideChainId(message.getSideChainId()); + + if (message.getSideConsAddr() != null) { + sideChainValidator.setSideConsAddr(EncodeUtils.bytesToPrefixHex(message.getSideConsAddr())); + } + if (message.getSideFeeAddr() != null) { + sideChainValidator.setSideFeeAddr(EncodeUtils.bytesToPrefixHex(message.getSideFeeAddr())); + } + + return sideChainValidator; + } + + public SideChainDelegation querySideChainDelegation(String sideChainId, String delegatorAddress, String validatorAddress) throws IOException { + QueryBondsParams params = new QueryBondsParams(); + params.setSideChainId(sideChainId); + params.setDelegatorAddr(delegatorAddress); + params.setValidatorAddr(validatorAddress); + + byte[] paramsBytes = EncodeUtils.toJsonEncodeBytes(params); + + byte[] response = queryWithData("\"custom/stake/delegation\"", paramsBytes); + if (!ByteUtil.isEmpty(response)){ + DelegationResponse delegationResponse = EncodeUtils.getObjectMapper().readValue(response, DelegationResponse.class); + return convert(delegationResponse); + } + + return null; + } + + public List querySideChainDelegations(String sideChainId, String delegatorAddress) throws IOException { + QueryDelegatorParams params = new QueryDelegatorParams(); + params.setSideChainId(sideChainId); + params.setDelegatorAddr(delegatorAddress); + + byte[] paramsBytes = EncodeUtils.toJsonEncodeBytes(params); + byte[] response = queryWithData("\"custom/stake/delegatorDelegations\"", paramsBytes); + + List results = new ArrayList<>(); + + if (!ByteUtil.isEmpty(response)){ + String a = new String(response); + List delegations = EncodeUtils.getObjectMapper().readValue(response, new TypeReference>(){}); + for (DelegationResponse delegation : delegations) { + results.add(convert(delegation)); + } + } + + return results; + } + + private SideChainDelegation convert(DelegationResponse delegationResponse){ + SideChainDelegation sideChainDelegation = new SideChainDelegation(); + if (delegationResponse.getDelegation() != null) { + Delegation delegation = new Delegation(); + delegation.setDelegatorAddress(delegationResponse.getDelegation().getDelegatorAddress()); + delegation.setValidatorAddress(delegationResponse.getDelegation().getValidatorAddress()); + delegation.setShares(delegationResponse.getDelegation().getShares()); + sideChainDelegation.setDelegation(delegation); + } + if (delegationResponse.getBalance() != null){ + sideChainDelegation.setBalance(convert(delegationResponse.getBalance())); + } + + return sideChainDelegation; + } + + public SideChainRedelegation querySideChainRedelegation(String sideChainId, String delegatorAddress, String srcValidatorAddress, String dstValidatorAddress) throws IOException { + byte[] storePrefix = getSideChainStorePrefixKey(sideChainId); + byte[] redKey = getRedelegationKey(Crypto.decodeAddress(delegatorAddress), Crypto.decodeAddress(srcValidatorAddress), + Crypto.decodeAddress(dstValidatorAddress)); + byte[] key = ByteUtil.appendBytesArray(storePrefix, redKey); + byte[] result = queryStore(stakeStoreName, key); + + if (!ByteUtil.isEmpty(result)){ + RedelegationValue message = new RedelegationValue(); + amino.decodeWithLengthPrefix(result, message); + return convert(message, redKey); + } + + return null; + } + + public List querySideChainRedelegations(String sideChainId, String delegatorAddress) throws IOException { + byte[] storePrefix = getSideChainStorePrefixKey(sideChainId); + byte[] redsKey = getRedelegationsKey(Crypto.decodeAddress(delegatorAddress)); + byte[] key = ByteUtil.appendBytesArray(storePrefix, redsKey); + List result = queryStoreSubspaceKVPairs(stakeStoreName, key); + List redelegations = new ArrayList<>(); + if (result != null && !result.isEmpty()){ + for (common.Types.KVPair kvPair : result) { + byte[] k = ByteUtil.cut(kvPair.getKey().toByteArray(), storePrefix.length); + RedelegationValue message = new RedelegationValue(); + amino.decodeWithLengthPrefix(kvPair.getValue().toByteArray(), message); + redelegations.add(convert(message, k)); + } + } + + return redelegations; + } + + private SideChainRedelegation convert(RedelegationValue value, byte[] key){ + byte[] addresses = ByteUtil.cut(key, 1); + if (addresses.length != addressLength * 3){ + throw new IllegalStateException("unexpected address length for (address, srcValidator, dstValidator)"); + } + + String delAddr = Crypto.encodeAddress(hrp, ByteUtil.pick(addresses, 0, addressLength)); + String srcValAddr = Crypto.encodeAddress(valHrp, ByteUtil.pick(addresses, addressLength, addressLength)); + String dstValAddr = Crypto.encodeAddress(valHrp, ByteUtil.pick(addresses, addressLength * 2, addressLength)); + + SideChainRedelegation redelegation = new SideChainRedelegation(); + redelegation.setDelegatorAddress(delAddr); + redelegation.setSrcValidatorAddress(srcValAddr); + redelegation.setDstValidatorAddress(dstValAddr); + + redelegation.setCreateHeight(value.getCreationHeight()); + if (value.getMinTime() != null) { + redelegation.setMinTimeInMs(value.getMinTime().getTimeInMilliseconds()); + } + if (value.getInitialBalance() != null){ + redelegation.setInitialBalance(value.getInitialBalance().toToken()); + } + if (value.getBalance() != null){ + redelegation.setBalance(value.getBalance().toToken()); + } + + if (value.getSharesSrc() != null){ + redelegation.setSrcShares(value.getSharesSrc().getValue()); + } + + if (value.getSharesDst() != null){ + redelegation.setDstShare(value.getSharesDst().getValue()); + } + + return redelegation; + } + + public UnBondingDelegation querySideChainUnBondingDelegation(String sideChainId, String delegatorAddress, String validatorAddress) throws IOException { + byte[] storePrefix = getSideChainStorePrefixKey(sideChainId); + byte[] ubdKey = getUnBondingDelegationKey(Crypto.decodeAddress(delegatorAddress), Crypto.decodeAddress(validatorAddress)); + byte[] key = ByteUtil.appendBytesArray(storePrefix, ubdKey); + byte[] result = queryStore(stakeStoreName, key); + if (!ByteUtil.isEmpty(result)) { + UnBondingValue unBondingValue = new UnBondingValue(); + amino.decodeWithLengthPrefix(result, unBondingValue); + return convert(unBondingValue, ByteUtil.cut(ubdKey, unBondingDelegationKey.length)); + }else{ + return null; + } + } + + public List querySideChainUnBondingDelegations(String sideChainId, String delegatorAddress) throws IOException { + byte[] storePrefix = getSideChainStorePrefixKey(sideChainId); + byte[] ubdsKey = getUnBondingDelegationsKey(Crypto.decodeAddress(delegatorAddress)); + byte[] key = ByteUtil.appendBytesArray(storePrefix, ubdsKey); + List kvPairs = queryStoreSubspaceKVPairs(stakeStoreName, key); + List unBondingDelegations = new ArrayList<>(); + if (kvPairs != null && !kvPairs.isEmpty()){ + for (common.Types.KVPair kvPair : kvPairs) { + UnBondingValue unBondingValue = new UnBondingValue(); + amino.decodeWithLengthPrefix(kvPair.getValue().toByteArray(), unBondingValue); + unBondingDelegations.add(convert(unBondingValue, ByteUtil.cut(kvPair.getKey().toByteArray(), storePrefix.length + unBondingDelegationKey.length))); + } + } + + return unBondingDelegations; + } + + public List querySideChainUnBondingDelegationsByValidator(String sideChainId, String validatorAddress) throws IOException { + QueryValidatorParams params = new QueryValidatorParams(sideChainId, Bech32AddressValue.fromBech32StringWithNewHrp(validatorAddress, valHrp)); + byte[] data = EncodeUtils.toJsonEncodeBytes(params); + byte[] result = queryWithData("\"custom/stake/validatorUnbondingDelegations\"", data); + + List unBondingDelegations = new ArrayList<>(); + + if (!ByteUtil.isEmpty(result)){ + List messages = EncodeUtils.getObjectMapper().readValue(result, new TypeReference>(){}); + if (messages != null && !messages.isEmpty()){ + for (UnBondingDelegationMessage message : messages) { + unBondingDelegations.add(convert(message)); + } + } + } + + return unBondingDelegations; + } + + public List querySideChainRedelegationsByValidator(String sideChainId, String validatorAddress) throws IOException { + QueryValidatorParams params = new QueryValidatorParams(sideChainId, Bech32AddressValue.fromBech32StringWithNewHrp(validatorAddress, valHrp)); + byte[] data = EncodeUtils.toJsonEncodeBytes(params); + byte[] result = queryWithData("\"custom/stake/validatorRedelegations\"", data); + + List redelegations = new ArrayList<>(); + + if (!ByteUtil.isEmpty(result)){ + List messages = EncodeUtils.getObjectMapper().readValue(result, new TypeReference>(){}); + if (messages != null && !messages.isEmpty()){ + for (SideChainRedelegationMessage message : messages) { + redelegations.add(convert(message)); + } + } + } + + return redelegations; + } + + public Pool querySideChainPool(String sideChainId) throws IOException { + byte[] storePrefix = getSideChainStorePrefixKey(sideChainId); + byte[] key = ByteUtil.appendBytesArray(storePrefix, poolKey); + byte[] result = queryStore(stakeStoreName, key); + + if (!ByteUtil.isEmpty(result)){ + PoolMessage message = new PoolMessage(); + amino.decodeWithLengthPrefix(result, message); + + Pool pool = new Pool(); + if (message.getLooseTokens() != null){ + pool.setLooseTokens(message.getLooseTokens().getValue()); + } + if (message.getBondedTokens() != null){ + pool.setBondedTokens(message.getBondedTokens().getValue()); + } + + return pool; + } + + return null; + } + + public long queryAllSideChainValidatorsCount(String sideChainId, boolean jailInvolved) throws IOException { + BaseQueryParams params = new BaseQueryParams(); + params.setSideChainId(sideChainId); + byte[] data = EncodeUtils.toJsonEncodeBytes(params); + String path = "\"custom/stake/allUnJailValidatorsCount\""; + if (jailInvolved){ + path = "\"custom/stake/allValidatorsCount\""; + } + byte[] result = queryWithData(path, data); + if (!ByteUtil.isEmpty(result)){ + String count = new String(result); + if (count.contains("\"")){ + count = count.replaceAll("\"", ""); + } + return Long.parseLong(count); + } + + return 0L; + } + + private SideChainRedelegation convert(SideChainRedelegationMessage message){ + SideChainRedelegation redelegation = new SideChainRedelegation(); + redelegation.setDelegatorAddress(message.getDelegatorAddress()); + redelegation.setSrcValidatorAddress(message.getSrcValidatorAddress()); + redelegation.setDstValidatorAddress(message.getDstValidatorAddress()); + redelegation.setCreateHeight(message.getCreateHeight()); + redelegation.setMinTime(message.getMinTime()); + if (message.getInitialBalance() != null) { + redelegation.setInitialBalance(convert(message.getInitialBalance())); + } + if (message.getBalance() != null){ + redelegation.setBalance(convert(message.getBalance())); + } + redelegation.setSrcShares(message.getSrcShares()); + redelegation.setDstShare(message.getDstShare()); + + return redelegation; + } + + private Token convert(CoinValue coinValue){ + Token token = new Token(); + token.setDenom(coinValue.getDenom()); + token.setAmount(coinValue.getAmount()); + return token; + } + + private UnBondingDelegation convert(UnBondingDelegationMessage message){ + UnBondingDelegation unBondingDelegation = new UnBondingDelegation(); + unBondingDelegation.setBalance(message.getBalance()); + unBondingDelegation.setCreateHeight(message.getCreateHeight()); + unBondingDelegation.setDelegatorAddress(message.getDelegatorAddress()); + unBondingDelegation.setValidatorAddress(message.getValidatorAddress()); + unBondingDelegation.setInitialBalance(message.getInitialBalance()); + unBondingDelegation.setMinTime(message.getMinTime()); + + return unBondingDelegation; + } + + private UnBondingDelegation convert(UnBondingValue value, byte[] addresses){ + if (addresses.length != addressLength * 2){ + throw new IllegalStateException("unexpected address length for this (address, validator) pair"); + } + + UnBondingDelegation unBondingDelegation = new UnBondingDelegation(); + unBondingDelegation.setDelegatorAddress(Crypto.encodeAddress(hrp, ByteUtil.pick(addresses, 0, addressLength))); + unBondingDelegation.setValidatorAddress(Crypto.encodeAddress(hrp, ByteUtil.pick(addresses, addressLength, addressLength))); + unBondingDelegation.setCreateHeight(value.getCreationHeight()); + if (value.getMinTime() != null){ + unBondingDelegation.setMinTimeInMs(value.getMinTime().getTimeInMilliseconds()); + } + if (value.getInitialBalance() != null){ + unBondingDelegation.setInitialBalance(value.getInitialBalance().toToken()); + } + if (value.getBalance() != null){ + unBondingDelegation.setBalance(value.getBalance().toToken()); + } + + return unBondingDelegation; + } + + private byte[] getSideChainStorePrefixKey(String sideChainId){ + byte[] sideChainIdBytes = sideChainId.getBytes(defaultCharset); + byte[] key = ByteUtil.appendBytesArray(sideChainStorePrefixByIdKey, sideChainIdBytes); + byte[] result = queryStore(scStoreKey, key); + + if (result == null || result.length == 0){ + throw new IllegalArgumentException("Invalid sideChainId: " + sideChainId); + } + + return result; + } + + private byte[] getValidatorKey(byte[] operatorAddress){ + return ByteUtil.appendBytesArray(validatorsKey, operatorAddress); + } + + private byte[] getRedelegationKey(byte[] delAddr, byte[] srcValAddr, byte[] dstValAddr){ + int length = 1 + addressLength * 3; + byte[] key = new byte[length]; + + byte[] redsKey = getRedelegationsKey(delAddr); + System.arraycopy(redsKey, 0, key, 0, redsKey.length); + System.arraycopy(srcValAddr, 0, key, redsKey.length, srcValAddr.length); + System.arraycopy(dstValAddr, 0, key, redsKey.length + srcValAddr.length, dstValAddr.length); + return key; + } + + private byte[] getDelegationKey(byte[] delegateAddress, byte[] validatorAddress){ + return ByteUtil.appendBytesArray(getDelegationsKey(delegateAddress), validatorAddress); + } + + private byte[] getDelegationsKey(byte[] delegateAddress){ + return ByteUtil.appendBytesArray(delegationKey, delegateAddress); + } + + private byte[] getRedelegationsKey(byte[] delAddr){ + return ByteUtil.appendBytesArray(redelegationKey, delAddr); + } + + byte[] getUnBondingDelegationKey(byte[] delegatorAddress, byte[] validatorAddress){ + return ByteUtil.appendBytesArray(getUnBondingDelegationsKey(delegatorAddress), validatorAddress); + } + + byte[] getUnBondingDelegationsKey(byte[] delegatorAddress){ + return ByteUtil.appendBytesArray(unBondingDelegationKey, delegatorAddress); + } + +} diff --git a/src/main/java/com/binance/dex/api/client/impl/node/NodeTx.java b/src/main/java/com/binance/dex/api/client/impl/node/NodeTx.java new file mode 100644 index 0000000..3daa362 --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/impl/node/NodeTx.java @@ -0,0 +1,146 @@ +package com.binance.dex.api.client.impl.node; + +import com.binance.dex.api.client.BinanceDexApiClientGenerator; +import com.binance.dex.api.client.BinanceDexApiException; +import com.binance.dex.api.client.BinanceDexNodeApi; +import com.binance.dex.api.client.Wallet; +import com.binance.dex.api.client.domain.TransactionMetadata; +import com.binance.dex.api.client.domain.broadcast.TransactionOption; +import com.binance.dex.api.client.domain.jsonrpc.AsyncBroadcastResult; +import com.binance.dex.api.client.domain.jsonrpc.CommitBroadcastResult; +import com.binance.dex.api.client.domain.jsonrpc.JsonRpcResponse; +import com.binance.dex.api.client.encoding.message.BinanceDexTransactionMessage; +import com.binance.dex.api.client.encoding.message.TransactionRequestAssembler; +import com.google.common.collect.Lists; +import org.apache.commons.lang3.StringUtils; + +import java.io.IOException; +import java.security.NoSuchAlgorithmException; +import java.util.List; + +/** + * @author Fitz.Lu + **/ +class NodeTx { + + protected final BinanceDexNodeApi binanceDexNodeApi; + + protected final String hrp; + + protected final String valHrp; + + NodeTx(BinanceDexNodeApi binanceDexNodeApi, String hrp, String valHrp){ + this.binanceDexNodeApi = binanceDexNodeApi; + this.hrp = hrp; + this.valHrp = valHrp; + } + + protected List broadcast(BinanceDexTransactionMessage message, Wallet wallet, TransactionOption options, boolean sync) throws IOException, NoSuchAlgorithmException { + message.validateBasic(); + TransactionRequestAssembler assembler = new TransactionRequestAssembler(wallet, options); + String requestPayload = "0x" + assembler.buildTxPayload(message); + if (sync) { + return syncBroadcast(requestPayload, wallet); + } else { + return asyncBroadcast(requestPayload, wallet); + } + } + + protected List syncBroadcast(String requestBody, Wallet wallet) { + try { + JsonRpcResponse rpcResponse = BinanceDexApiClientGenerator.executeSync(binanceDexNodeApi.commitBroadcast(requestBody)); + CommitBroadcastResult commitBroadcastResult = rpcResponse.getResult(); + TransactionMetadata transactionMetadata = new TransactionMetadata(); + transactionMetadata.setCode(commitBroadcastResult.getCheckTx().getCode()); + if (commitBroadcastResult.getHeight() != null && StringUtils.isNoneBlank(commitBroadcastResult.getHash()) && transactionMetadata.getCode() == 0) { + wallet.increaseAccountSequence(); + transactionMetadata.setHash(commitBroadcastResult.getHash()); + transactionMetadata.setHeight(commitBroadcastResult.getHeight()); + transactionMetadata.setLog(commitBroadcastResult.getCheckTx().getLog()); + transactionMetadata.setOk(true); + } else { + wallet.invalidAccountSequence(); + transactionMetadata.setLog(commitBroadcastResult.getCheckTx().getLog()); + transactionMetadata.setOk(false); + } + + return Lists.newArrayList(transactionMetadata); + } catch (BinanceDexApiException e) { + wallet.invalidAccountSequence(); + throw new RuntimeException(e); + } + } + + protected List syncBroadcast(String requestBody) { + try { + JsonRpcResponse rpcResponse = BinanceDexApiClientGenerator.executeSync(binanceDexNodeApi.commitBroadcast(requestBody)); + CommitBroadcastResult commitBroadcastResult = rpcResponse.getResult(); + TransactionMetadata transactionMetadata = new TransactionMetadata(); + transactionMetadata.setCode(commitBroadcastResult.getCheckTx().getCode()); + if (commitBroadcastResult.getHeight() != null && StringUtils.isNoneBlank(commitBroadcastResult.getHash()) && transactionMetadata.getCode() == 0) { + transactionMetadata.setHash(commitBroadcastResult.getHash()); + transactionMetadata.setHeight(commitBroadcastResult.getHeight()); + transactionMetadata.setLog(commitBroadcastResult.getCheckTx().getLog()); + transactionMetadata.setOk(true); + } else { + transactionMetadata.setLog(commitBroadcastResult.getCheckTx().getLog()); + transactionMetadata.setOk(false); + } + + return Lists.newArrayList(transactionMetadata); + } catch (BinanceDexApiException e) { + throw new RuntimeException(e); + } + } + + protected List asyncBroadcast(String requestBody) { + try { + JsonRpcResponse rpcResponse = BinanceDexApiClientGenerator.executeSync(binanceDexNodeApi.asyncBroadcast(requestBody)); + AsyncBroadcastResult asyncBroadcastResult = rpcResponse.getResult(); + TransactionMetadata transactionMetadata = new TransactionMetadata(); + + transactionMetadata.setCode(asyncBroadcastResult.getCode()); + transactionMetadata.setLog(asyncBroadcastResult.getLog()); + + if (asyncBroadcastResult.getCode() == 0) { + transactionMetadata.setHash(asyncBroadcastResult.getHash()); + transactionMetadata.setData(asyncBroadcastResult.getData()); + transactionMetadata.setOk(true); + } else { + transactionMetadata.setOk(false); + } + + return Lists.newArrayList(transactionMetadata); + } catch (BinanceDexApiException e) { + throw new RuntimeException(e); + } + } + + + protected List asyncBroadcast(String requestBody, Wallet wallet) { + try { + JsonRpcResponse rpcResponse = BinanceDexApiClientGenerator.executeSync(binanceDexNodeApi.asyncBroadcast(requestBody)); + AsyncBroadcastResult asyncBroadcastResult = rpcResponse.getResult(); + TransactionMetadata transactionMetadata = new TransactionMetadata(); + + transactionMetadata.setCode(asyncBroadcastResult.getCode()); + transactionMetadata.setLog(asyncBroadcastResult.getLog()); + + if (asyncBroadcastResult.getCode() == 0) { + wallet.increaseAccountSequence(); + transactionMetadata.setHash(asyncBroadcastResult.getHash()); + transactionMetadata.setData(asyncBroadcastResult.getData()); + transactionMetadata.setOk(true); + } else { + wallet.invalidAccountSequence(); + transactionMetadata.setOk(false); + } + + return Lists.newArrayList(transactionMetadata); + } catch (BinanceDexApiException e) { + wallet.invalidAccountSequence(); + throw new RuntimeException(e); + } + } + +} diff --git a/src/main/java/com/binance/dex/api/client/impl/node/NodeTxDelegateBridge.java b/src/main/java/com/binance/dex/api/client/impl/node/NodeTxDelegateBridge.java new file mode 100644 index 0000000..51d5bcb --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/impl/node/NodeTxDelegateBridge.java @@ -0,0 +1,126 @@ +package com.binance.dex.api.client.impl.node; + +import com.binance.dex.api.client.BinanceDexNodeApi; +import com.binance.dex.api.client.Wallet; +import com.binance.dex.api.client.domain.TransactionMetadata; +import com.binance.dex.api.client.domain.bridge.TransferIn; +import com.binance.dex.api.client.domain.broadcast.TransactionOption; +import com.binance.dex.api.client.encoding.EncodeUtils; +import com.binance.dex.api.client.encoding.message.Token; +import com.binance.dex.api.client.encoding.message.common.CoinValue; +import com.binance.dex.api.client.encoding.message.common.EthAddressValue; +import com.binance.dex.api.client.encoding.message.bridge.*; +import com.binance.dex.api.client.encoding.message.common.Bech32AddressValue; + +import java.io.IOException; +import java.security.NoSuchAlgorithmException; +import java.util.List; + +/** + * @author Fitz.Lu + **/ +public class NodeTxDelegateBridge extends NodeTx { + + public NodeTxDelegateBridge(BinanceDexNodeApi binanceDexNodeApi, String hrp, String valHrp) { + super(binanceDexNodeApi, hrp, valHrp); + } + + public List claim(int chainId, byte[] payload, long sequence, Wallet wallet, TransactionOption options, boolean sync) throws IOException, NoSuchAlgorithmException { + ClaimMsgMessage message = new ClaimMsgMessage(); + message.setChainId(chainId); + message.setSequence(sequence); + message.setPayload(payload); + message.setValidatorAddress(Bech32AddressValue.fromBech32String(wallet.getAddress())); + return broadcast(message, wallet, options, sync); + } + + public List transferIn(long sequence, TransferIn transferIn, Wallet wallet, TransactionOption options, boolean sync) throws IOException, NoSuchAlgorithmException { + TransferInClaimMessage message = convert(transferIn); + String claim = EncodeUtils.getObjectMapper().writeValueAsString(message); + ClaimMsgMessage claimMsg = new ClaimMsgMessage(ClaimTypes.ClaimTypeTransferIn, sequence, claim.getBytes(), Bech32AddressValue.fromBech32String(wallet.getAddress())); + + return broadcast(claimMsg, wallet, options, sync); + } + + public List transferOut(String toAddress, Token amount, long expireTimeInSeconds, Wallet wallet, TransactionOption options, boolean sync) throws IOException, NoSuchAlgorithmException { + TransferOutMsgMessage message = new TransferOutMsgMessage(); + message.setFrom(Bech32AddressValue.fromBech32String(wallet.getAddress())); + message.setToAddress(EthAddressValue.from(toAddress)); + message.setAmount(convert(amount)); + message.setExpireTime(expireTimeInSeconds); + + return broadcast(message, wallet, options, sync); + } + + public List bind(String symbol, long amount, String contractAddress, int contractDecimal, long expireTimeInSeconds, Wallet wallet, TransactionOption options, boolean sync) throws IOException, NoSuchAlgorithmException { + BindMsgMessage message = new BindMsgMessage(); + message.setFrom(Bech32AddressValue.fromBech32String(wallet.getAddress())); + message.setSymbol(symbol); + message.setAmount(amount); + message.setContractAddress(EthAddressValue.from(contractAddress)); + message.setContractDecimal(contractDecimal); + message.setExpireTime(expireTimeInSeconds); + + return broadcast(message, wallet, options, sync); + } + + public List unBind(String symbol, Wallet wallet, TransactionOption options, boolean sync) throws IOException, NoSuchAlgorithmException { + UnbindMsgMessage message = new UnbindMsgMessage(); + message.setFrom(Bech32AddressValue.fromBech32String(wallet.getAddress())); + message.setSymbol(symbol); + + return broadcast(message, wallet, options, sync); + } + + public List updateTransferOut(long sequence, String refundAddress, Token amount, int refundReason, Wallet wallet, TransactionOption options, boolean sync) throws IOException, NoSuchAlgorithmException { + UpdateTransferOutClaimMessage message = new UpdateTransferOutClaimMessage(); + message.setAmount(convert(amount)); + message.setRefundAddress(Bech32AddressValue.fromBech32String(refundAddress)); + message.setRefundReason(refundReason); + + ClaimMsgMessage claimMsg = new ClaimMsgMessage(ClaimTypes.ClaimTypeUpdateTransferOut, sequence, + EncodeUtils.getObjectMapper().writeValueAsString(message).getBytes(), Bech32AddressValue.fromBech32String(wallet.getAddress())); + + return broadcast(claimMsg, wallet, options, sync); + } + + public List updateBind(long sequence, String symbol, String contractAddress, int status, Wallet wallet, TransactionOption options, boolean sync) throws IOException, NoSuchAlgorithmException { + UpdateBindClaimMessage message = new UpdateBindClaimMessage(); + message.setStatus(status); + message.setSymbol(symbol); + message.setContractAddress(EthAddressValue.from(contractAddress)); + + ClaimMsgMessage claimMsg = new ClaimMsgMessage(ClaimTypes.ClaimTypeUpdateBind, sequence, + EncodeUtils.getObjectMapper().writeValueAsString(message).getBytes(), Bech32AddressValue.fromBech32String(wallet.getAddress())); + + return broadcast(claimMsg, wallet, options, sync); + } + + private CoinValue convert(Token token){ + CoinValue value = new CoinValue(); + value.setDenom(token.getDenom()); + value.setAmount(token.getAmount()); + return value; + } + + private TransferInClaimMessage convert(TransferIn transferIn){ + TransferInClaimMessage message = new TransferInClaimMessage(); + message.setContractAddress(transferIn.getContractAddress()); + message.setRefundAddresses(transferIn.getRefundAddresses()); + message.setReceiverAddresses(transferIn.getReceiverAddresses()); + message.setAmounts(transferIn.getAmounts()); + message.setSymbol(transferIn.getSymbol()); + + CoinValue coinValue = new CoinValue(); + if (transferIn.getRelayFee() != null){ + coinValue.setDenom(transferIn.getRelayFee().getDenom()); + coinValue.setAmount(transferIn.getRelayFee().getAmount()); + } + message.setRelayFee(coinValue); + + message.setExpireTime(transferIn.getExpireTime()); + + return message; + } + +} diff --git a/src/main/java/com/binance/dex/api/client/impl/node/NodeTxDelegateSideChainStaking.java b/src/main/java/com/binance/dex/api/client/impl/node/NodeTxDelegateSideChainStaking.java new file mode 100644 index 0000000..651080a --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/impl/node/NodeTxDelegateSideChainStaking.java @@ -0,0 +1,175 @@ +package com.binance.dex.api.client.impl.node; + +import com.binance.dex.api.client.BinanceDexNodeApi; +import com.binance.dex.api.client.Wallet; +import com.binance.dex.api.client.domain.TransactionMetadata; +import com.binance.dex.api.client.domain.broadcast.TransactionOption; +import com.binance.dex.api.client.domain.stake.Commission; +import com.binance.dex.api.client.domain.stake.Description; +import com.binance.dex.api.client.domain.stake.sidechain.*; +import com.binance.dex.api.client.encoding.message.Token; +import com.binance.dex.api.client.encoding.message.common.Bech32AddressValue; +import com.binance.dex.api.client.encoding.message.common.CoinValueStr; +import com.binance.dex.api.client.encoding.message.common.Dec; +import com.binance.dex.api.client.encoding.message.sidechain.transaction.*; +import com.binance.dex.api.client.encoding.message.sidechain.value.*; +import com.google.common.annotations.VisibleForTesting; +import org.apache.commons.lang3.StringUtils; +import org.bouncycastle.util.encoders.Hex; + +import java.io.IOException; +import java.security.NoSuchAlgorithmException; +import java.util.List; + +/** + * @author Fitz.Lu + **/ +public class NodeTxDelegateSideChainStaking extends NodeTx { + + public NodeTxDelegateSideChainStaking(BinanceDexNodeApi binanceDexNodeApi, String hrp, String valHrp) { + super(binanceDexNodeApi, hrp, valHrp); + } + + public List createSideChainValidator(CreateSideChainValidator createSideChainValidator, Wallet wallet, TransactionOption options, boolean sync) throws IOException, NoSuchAlgorithmException { + CreateSideChainValidatorMessage message = convert(createSideChainValidator); + if (StringUtils.isEmpty(createSideChainValidator.getValidatorAddr())) { + message.setValidatorOperatorAddr(Bech32AddressValue.fromBech32StringWithNewHrp(wallet.getAddress(), valHrp)); + }else{ + message.setValidatorOperatorAddr(Bech32AddressValue.fromBech32StringWithNewHrp(createSideChainValidator.getValidatorAddr(), valHrp)); + } + return broadcast(message, wallet, options, sync); + } + + public List editSideChainValidator(EditSideChainValidator editSideChainValidator, Wallet wallet, TransactionOption options, boolean sync) throws IOException, NoSuchAlgorithmException { + EditSideChainValidatorMessage message = convert(editSideChainValidator); + if (StringUtils.isEmpty(editSideChainValidator.getValidatorAddress())) { + message.setValidatorOperatorAddress(Bech32AddressValue.fromBech32StringWithNewHrp(wallet.getAddress(), valHrp)); + }else{ + message.setValidatorOperatorAddress(Bech32AddressValue.fromBech32StringWithNewHrp(editSideChainValidator.getValidatorAddress(), valHrp)); + } + return broadcast(message, wallet, options, sync); + } + + public List sideChainDelegate(SideChainDelegate sideChainDelegate, Wallet wallet, TransactionOption options, boolean sync) throws IOException, NoSuchAlgorithmException { + SideChainDelegateMessage message = convert(sideChainDelegate); + return broadcast(message, wallet, options, sync); + } + + public List sideChainRedelagate(SideChainRedelegate sideChainRedelegate, Wallet wallet, TransactionOption options, boolean sync) throws IOException, NoSuchAlgorithmException { + SideChainRedelegateMessage message = convert(sideChainRedelegate); + return broadcast(message, wallet, options, sync); + } + + public List sideChainUnbond(SideChainUnBond sideChainUndelegate, Wallet wallet, TransactionOption options, boolean sync) throws IOException, NoSuchAlgorithmException { + SideChainUndelegateMessage message = convert(sideChainUndelegate); + return broadcast(message, wallet, options, sync); + } + + @VisibleForTesting + CreateSideChainValidatorMessage convert(CreateSideChainValidator createSideChainValidator){ + CreateSideChainValidatorMessage message = new CreateSideChainValidatorMessage(); + + if (createSideChainValidator.getDescription() != null){ + message.setDescription(convert(createSideChainValidator.getDescription())); + } + if (createSideChainValidator.getCommission() != null){ + message.setCommission(convert(createSideChainValidator.getCommission())); + } + + message.setDelegatorAddr(Bech32AddressValue.fromBech32String(createSideChainValidator.getDelegatorAddr())); + + if (createSideChainValidator.getDelegation() != null){ + message.setDelegation(convert(createSideChainValidator.getDelegation())); + } + + message.setSideChainId(createSideChainValidator.getSideChainId()); + message.setSideConsAddr(decodeHexAddress(createSideChainValidator.getSideConsAddr())); + message.setSideFeeAddr(decodeHexAddress(createSideChainValidator.getSideFeeAddr())); + return message; + } + + @VisibleForTesting + EditSideChainValidatorMessage convert(EditSideChainValidator editSideChainValidator){ + EditSideChainValidatorMessage message = new EditSideChainValidatorMessage(); + + if (editSideChainValidator.getDescription() != null){ + message.setDescription(convert(editSideChainValidator.getDescription())); + } + + message.setCommissionRate(Dec.newInstance(editSideChainValidator.getCommissionRate())); + message.setSideChainId(editSideChainValidator.getSideChainId()); + message.setSideFeeAddr(decodeHexAddress(editSideChainValidator.getSideFeeAddr())); + + return message; + } + + private byte[] decodeHexAddress(String address){ + String addr = address; + if (addr.startsWith("0x")){ + addr = address.substring(2); + } + return Hex.decode(addr); + } + + private DescriptionValue convert(Description description){ + DescriptionValue value = new DescriptionValue(); + value.setMoniker(description.getMoniker()); + value.setDetails(description.getDetails()); + value.setIdentity(description.getIdentity()); + value.setWebsite(description.getWebsite()); + return value; + } + + private CommissionMsgValue convert(Commission commission){ + CommissionMsgValue value = new CommissionMsgValue(); + value.setRate(Dec.newInstance(commission.getRate())); + value.setMaxRate(Dec.newInstance(commission.getMaxRate())); + value.setMaxChangeRate(Dec.newInstance(commission.getMaxChangeRate())); + return value; + } + + private CoinValueStr convert(Token token){ + CoinValueStr value = new CoinValueStr(); + value.setDenom(token.getDenom()); + value.setAmount(token.getAmount()); + return value; + } + + private SideChainDelegateMessage convert(SideChainDelegate sideChainDelegate){ + SideChainDelegateMessage message = new SideChainDelegateMessage(); + message.setDelegatorAddress(Bech32AddressValue.fromBech32String(sideChainDelegate.getDelegatorAddress())); + message.setValidatorAddress(Bech32AddressValue.fromBech32StringWithNewHrp(sideChainDelegate.getValidatorAddress(), valHrp)); + + if (sideChainDelegate.getDelegation() != null) { + message.setDelegation(convert(sideChainDelegate.getDelegation())); + } + + message.setSideChainId(sideChainDelegate.getSideChainId()); + return message; + } + + private SideChainRedelegateMessage convert(SideChainRedelegate redelegate){ + SideChainRedelegateMessage message = new SideChainRedelegateMessage(); + message.setDelegatorAddress(Bech32AddressValue.fromBech32String(redelegate.getDelegatorAddress())); + message.setSrcValidatorAddress(Bech32AddressValue.fromBech32StringWithNewHrp(redelegate.getSrcValidatorAddress(), valHrp)); + message.setDstValidatorAddress(Bech32AddressValue.fromBech32StringWithNewHrp(redelegate.getDstValidatorAddress(), valHrp)); + if (redelegate.getAmount() != null) { + message.setAmount(convert(redelegate.getAmount())); + } + message.setSideChainId(redelegate.getSideChainId()); + return message; + } + + private SideChainUndelegateMessage convert(SideChainUnBond unBond){ + SideChainUndelegateMessage message = new SideChainUndelegateMessage(); + message.setDelegatorAddress(Bech32AddressValue.fromBech32String(unBond.getDelegatorAddress())); + message.setValidatorAddress(Bech32AddressValue.fromBech32StringWithNewHrp(unBond.getValidatorAddress(), valHrp)); + if (unBond.getAmount() != null) { + message.setAmount(convert(unBond.getAmount())); + } + message.setSideChainId(unBond.getSideChainId()); + return message; + } + + +} diff --git a/src/main/java/com/binance/dex/api/client/rlp/Decoder.java b/src/main/java/com/binance/dex/api/client/rlp/Decoder.java new file mode 100644 index 0000000..21d2c35 --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/rlp/Decoder.java @@ -0,0 +1,151 @@ +package com.binance.dex.api.client.rlp; + +import com.binance.dex.api.client.crosschain.UnsignedNumber; +import com.binance.dex.api.client.encoding.EncodeUtils; +import org.ethereum.util.DecodeResult; +import org.ethereum.util.RLP; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.List; + +public class Decoder extends RLP { + + public static List decodeList(byte[] raw, Class clazz) throws Exception { + DecodeResult decodeResult = decode(raw, 0); + if (!(decodeResult.getDecoded() instanceof Object[])) { + throw new RuntimeException("not a list"); + } + Object[] objects = (Object[]) decodeResult.getDecoded(); + return decodeList(objects, clazz); + } + + private static List decodeList(Object[] objects, Class clazz) throws Exception { + List list = new ArrayList<>(); + for (Object ob : objects) { + if (ob instanceof byte[]) { + list.add((T) decodeBytes((byte[]) ob, clazz, null)); + } else if (ob instanceof Object[]) { + Object[] fieldValues = (Object[]) ob; + list.add(decodeObject(fieldValues, clazz)); + } + } + return list; + } + + public static T decodeObject(byte[] raw, Class clazz) throws Exception { + DecodeResult decodeResult = decode(raw, 0); + return decodeObject((Object[]) decodeResult.getDecoded(), clazz); + } + + + private static Object decodeBytes(byte[] value, Class type, Object superInstance) throws Exception { + if (type == Integer.class) { + + return decodeInt(value, 0); + + } else if (type == Long.class) { + + return decodeLong(value, 0); + + } else if (type == BigInteger.class) { + + return decodeBigInteger(value, 0); + + } else if (type == String.class) { + + return new String(value); + + } else if (type == byte[].class) { + + return value; + + } else if (isImplement(type, RlpDecodable.class)) { + + Method method = type.getMethod("decode", byte[].class, Object.class); + Object instance = type.newInstance(); + method.invoke(instance, value, superInstance); + return instance; + + } else { + throw new RuntimeException(String.format("unsupported type: %s ", type.getCanonicalName())); + } + } + + private static T decodeObject(Object[] fieldValues, Class clazz) throws Exception { + Field[] fields = clazz.getDeclaredFields(); + T instance = clazz.newInstance(); + if (fieldValues.length != fields.length) { + throw new RuntimeException("failed to decode, inconsistent fields numbers"); + } + for (int i = 0; i < fieldValues.length; i++) { + Object fieldValue = fieldValues[i]; + Field field = fields[i]; + + field.setAccessible(true); + if (fieldValue.equals("")) { + Class fieldType = field.getType(); + if (fieldType == Integer.class) { + field.set(instance, 0); + } else if (fieldType == Long.class) { + field.set(instance, 0L); + } else if (fieldType == UnsignedNumber.class || fieldType.getSuperclass() == UnsignedNumber.class){ + field.set(instance, fieldType.newInstance()); + } else { + throw new RuntimeException(String.format("Failed to decode %s, its type should be Integer or Long or UnsignedNumber", field.getName())); + } + } else if (fieldValue instanceof byte[]) { + Class fieldType = field.getType(); + field.set(instance, decodeBytes((byte[]) fieldValue, fieldType, instance)); + } else if (fieldValue instanceof Object[]) { + + Class fieldType = field.getType(); + if (fieldType == List.class) { + Type genericType = field.getGenericType(); + if (!(genericType instanceof ParameterizedType)) { + throw new RuntimeException(String.format("Failed to decode %s, can not decode List without generic type", field.getName())); + } + ParameterizedType pt = (ParameterizedType) genericType; + Class genericClazz = (Class) pt.getActualTypeArguments()[0]; + field.set(instance, decodeList((Object[]) fieldValue, genericClazz)); + } else { + throw new RuntimeException(String.format("Failed to decode %s, only List is supported as an array type", field.getName())); + } + } else { + throw new RuntimeException("ERROR: unrecognised type for RLP encoded bytes"); + } + } + + return instance; + } + + private static boolean isImplement(Class clazz, Class interfaceClass) { + for (Class item : clazz.getInterfaces()) { + if (item == interfaceClass) { + return true; + } + } + for (Class item : clazz.getSuperclass().getInterfaces()) { + if (item == interfaceClass) { + return true; + } + } + return false; + } + + + public static void main(String[] args) throws Exception { + byte[] bz = encodeInt(-100); + System.out.printf("result: %s\n", EncodeUtils.bytesToHex(bz)); + + byte[] bz1 = EncodeUtils.hexStringToByteArray("100000"); + + int r = decodeInt(bz1, 0); + System.out.println(r); + } + +} diff --git a/src/main/java/com/binance/dex/api/client/rlp/RlpDecodable.java b/src/main/java/com/binance/dex/api/client/rlp/RlpDecodable.java new file mode 100644 index 0000000..dbca877 --- /dev/null +++ b/src/main/java/com/binance/dex/api/client/rlp/RlpDecodable.java @@ -0,0 +1,7 @@ +package com.binance.dex.api.client.rlp; + +public interface RlpDecodable { + + void decode(byte[] raw, Object superInstance) throws Exception; + +} diff --git a/src/main/java/com/binance/dex/api/client/websocket/BinanceDexClientWSFactory.java b/src/main/java/com/binance/dex/api/client/websocket/BinanceDexClientWSFactory.java index 8d4d267..ddb3c80 100644 --- a/src/main/java/com/binance/dex/api/client/websocket/BinanceDexClientWSFactory.java +++ b/src/main/java/com/binance/dex/api/client/websocket/BinanceDexClientWSFactory.java @@ -32,12 +32,12 @@ public static BinanceDexWSApiImpl getWSApiImpl(BinanceDexEnvironment env){ } return binanceDexWSApiImplMap.get(env.getWsBaseUrl()); } - public static BinanceDexWSApiImpl getWSApiImpl(String url,String hrp){ + public static BinanceDexWSApiImpl getWSApiImpl(String url,String hrp, String valHrp){ synchronized (lock){ binanceDexWSApiImplMap.computeIfAbsent(url,(k)->{ BinanceDexClientEndpoint endpoint = newDefaultClientEndpoint(url); WebsocketLauncher.startUp(endpoint); - return new BinanceDexWSApiImpl(hrp,endpoint); + return new BinanceDexWSApiImpl(hrp, valHrp, endpoint); }); } return binanceDexWSApiImplMap.get(url); diff --git a/src/main/java/com/binance/dex/api/client/websocket/BinanceDexWSApiImpl.java b/src/main/java/com/binance/dex/api/client/websocket/BinanceDexWSApiImpl.java index 3551f54..37dbe74 100644 --- a/src/main/java/com/binance/dex/api/client/websocket/BinanceDexWSApiImpl.java +++ b/src/main/java/com/binance/dex/api/client/websocket/BinanceDexWSApiImpl.java @@ -37,12 +37,12 @@ public class BinanceDexWSApiImpl extends IdGenerator implements BinanceDexWSApi BinanceDexWSApiImpl(BinanceDexEnvironment env,BinanceDexClientEndpoint endpoint){ this.endpoint = endpoint; - this.transactionConverter = new TransactionConverter(env.getHrp()); + this.transactionConverter = new TransactionConverter(env.getHrp(), env.getValHrp()); } - BinanceDexWSApiImpl(String hrp,BinanceDexClientEndpoint endpoint){ + BinanceDexWSApiImpl(String hrp, String valHrp, BinanceDexClientEndpoint endpoint){ this.endpoint = endpoint; - this.transactionConverter = new TransactionConverter(hrp); + this.transactionConverter = new TransactionConverter(hrp, valHrp); } diff --git a/src/main/proto/dex.proto b/src/main/proto/dex.proto index 0f2df31..cce4e29 100644 --- a/src/main/proto/dex.proto +++ b/src/main/proto/dex.proto @@ -7,6 +7,7 @@ option java_outer_classname = "Transaction"; package transaction; import "types.proto"; +import "google/protobuf/timestamp.proto"; // please note the field name is the JSON name. message StdTx { @@ -101,6 +102,14 @@ message Vote { int64 option = 3; // option from OptionSet chosen by the voter, } +message SideVote { + // 0xE26BA13D // hardcoded, object type prefix in 4 bytes + int64 proposal_id = 1; // ID of the proposal + bytes voter = 2; // address of the voter + int64 option = 3; // option from OptionSet chosen by the voter, + string side_chain_id = 4; +} + message Token { string denom = 1; int64 amount = 2; @@ -233,6 +242,17 @@ message SubmitProposal { int64 voting_period = 6; } +message SideSubmitProposal { + // 0x4ACBF03C + string title = 1; + string description = 2; + int64 proposal_type = 3; + bytes proposer = 4; + repeated Token initial_deposit = 5; + int64 voting_period = 6; + string side_chain_id = 7; +} + message Deposit { // 0xA18A56E5 int64 proposal_id = 1; @@ -240,6 +260,14 @@ message Deposit { repeated Token amount = 3; } +message SideDeposit { + // 0x140F2DB4 + int64 proposal_id = 1; + bytes depositer = 2; + repeated Token amount = 3; + string side_chain_id = 4; +} + message Description { string moniker = 1; string identity = 2; @@ -351,12 +379,55 @@ message ClaimHashTimerLockMsg { bytes random_number = 3; } +message SubmitEvidenceMsg { + // A38F1399 + bytes submitter = 1; + repeated BscHeader headers = 2; +} + +message BscHeader { + bytes parentHash = 1; + bytes sha3Uncles = 2; + bytes miner = 3; + bytes stateRoot = 4; + bytes transactionsRoot = 5; + bytes receiptsRoot = 6; + bytes logsBloom = 7; + int64 difficulty = 8; + int64 number = 9; + int64 gasLimit = 10; + int64 gasUsed = 11; + int64 timestamp = 12; + bytes extraData = 13; + bytes mixHash = 14; + bytes nonce = 15; +} + +message SideChainUnJailMsg { + // 5681EC54 + bytes address = 1; + string side_chain_id = 2; +} + message RefundHashTimerLockMsg { // bytes from = 1; bytes swap_id = 2; } +message Status { + int32 text = 1; + string finalClaim = 2; +} + +message Prophecy { + string id = 1; + Status status = 2; + + map claimValidators = 3; + map validatorClaims = 4; +} + //mini token issue message TinyTokenIssue { // ED2832D4 // hardcoded, object type prefix in 4 bytes diff --git a/src/main/proto/types.proto b/src/main/proto/types.proto index b48ff1e..680026c 100644 --- a/src/main/proto/types.proto +++ b/src/main/proto/types.proto @@ -315,6 +315,10 @@ message Evidence { int64 total_voting_power = 5; } +message KVPairs { + repeated common.KVPair pairs = 1; +} + //---------------------------------------- // Service Definition diff --git a/src/test/java/com/binance/dex/api/client/encoding/AminoTest.java b/src/test/java/com/binance/dex/api/client/encoding/AminoTest.java new file mode 100644 index 0000000..8d91392 --- /dev/null +++ b/src/test/java/com/binance/dex/api/client/encoding/AminoTest.java @@ -0,0 +1,340 @@ +package com.binance.dex.api.client.encoding; + +import com.binance.dex.api.client.BinanceDexEnvironment; +import com.binance.dex.api.client.TransactionConverter; +import com.binance.dex.api.client.Wallet; +import com.binance.dex.api.client.domain.broadcast.Transaction; +import com.binance.dex.api.client.domain.stake.Commission; +import com.binance.dex.api.client.domain.stake.Description; +import com.binance.dex.api.client.domain.stake.sidechain.*; +import com.binance.dex.api.client.encoding.amino.Amino; +import com.binance.dex.api.client.encoding.message.MessageType; +import com.binance.dex.api.client.encoding.message.Token; +import com.binance.dex.api.client.encoding.message.bridge.*; +import com.binance.dex.api.client.encoding.message.common.*; +import com.binance.dex.api.client.encoding.message.sidechain.transaction.*; +import com.binance.dex.api.client.encoding.message.sidechain.value.CommissionMsgValue; +import com.binance.dex.api.client.encoding.message.sidechain.value.DescriptionValue; +import com.binance.dex.api.client.encoding.message.sidechain.value.RedelegationValue; +import org.bouncycastle.util.encoders.Hex; +import org.junit.Assert; +import org.junit.Test; + +import java.io.IOException; + +/** + * @author Fitz.Lu + **/ +public class AminoTest { + + private final Amino amino = new Amino(); + + private final Wallet wallet = new Wallet("bce1c934173e84cb4a0abf06b371f7568d3c4686da8f3ea7e1e8d230ae681920", BinanceDexEnvironment.PROD); + private final TransactionConverter transactionConverter = new TransactionConverter("bnb", "bva"); + + @Test + public void testDecodeRedelegation() throws IOException { + String hex = "2a08a554120c08c08994f50510a0b0df93011a080a03424e4210904e22090a03424e4210d099052a0a3232"; + RedelegationValue value = new RedelegationValue(); + amino.decodeWithLengthPrefix(Hex.decode(hex), value); + Assert.assertNotNull(value.getSharesDst()); + } + + public void testClaim() throws IOException { + ClaimMsgMessage message = new ClaimMsgMessage(); + message.setChainId(ClaimTypes.ClaimTypeTransferIn); + message.setPayload("claim content".getBytes()); + message.setSequence(1); + message.setValidatorAddress(Bech32AddressValue.fromBech32String("bva1337r5pk3r6kvs4a8kc3u5yhdjc79c5lg78343t")); + byte[] data = amino.encode(message, MessageType.Claim.getTypePrefixBytes(), false); + Transaction transaction = transactionConverter.convert(data); + Assert.assertNotNull(transaction.getRealTx()); + } + + @Test + public void testTransferOut() throws IOException { + TransferOutMsgMessage message = new TransferOutMsgMessage(); + message.setAmount(new CoinValue("BNB", 1000000L)); + message.setExpireTime(System.currentTimeMillis()); + message.setFrom(Bech32AddressValue.fromBech32StringWithNewHrp("bva1337r5pk3r6kvs4a8kc3u5yhdjc79c5lg78343t", "bnb")); + message.setToAddress(EthAddressValue.from("0xd1B22dCC24C55f4d728E7aaA5c9b5a22e1512C08")); + byte[] data = amino.encode(message, MessageType.TransferOut.getTypePrefixBytes(), false); + Transaction transaction = transactionConverter.convert(data); + Assert.assertNotNull(transaction.getRealTx()); + } + + @Test + public void testBind() throws IOException { + BindMsgMessage message = new BindMsgMessage(); + message.setAmount(1000000L); + message.setContractAddress(EthAddressValue.from("0xd1B22dCC24C55f4d728E7aaA5c9b5a22e1512C08")); + message.setContractDecimal(8); + message.setExpireTime(System.currentTimeMillis()); + message.setFrom(Bech32AddressValue.fromBech32StringWithNewHrp("bva1337r5pk3r6kvs4a8kc3u5yhdjc79c5lg78343t", "bnb")); + message.setSymbol("BNB"); + byte[] data = amino.encode(message, MessageType.Bind.getTypePrefixBytes(), false); + Transaction transaction = transactionConverter.convert(data); + Assert.assertNotNull(transaction.getRealTx()); + } + + @Test + public void testUnBind() throws IOException { + UnbindMsgMessage message = new UnbindMsgMessage(); + message.setFrom(Bech32AddressValue.fromBech32StringWithNewHrp("bva1337r5pk3r6kvs4a8kc3u5yhdjc79c5lg78343t", "bnb")); + message.setSymbol("BNB"); + byte[] data = amino.encode(message, MessageType.UnBind.getTypePrefixBytes(), false); + Transaction transaction = transactionConverter.convert(data); + Assert.assertNotNull(transaction.getRealTx()); + } + + @Test + public void testCreateSideChainValidator() throws IOException { + CreateSideChainValidator createSideChainValidator = new CreateSideChainValidator(); + + //create and set description + Description validatorDescription = new Description(); + validatorDescription.setMoniker("custom-moniker"); + validatorDescription.setIdentity("ide"); + validatorDescription.setWebsite("https://www.website.com"); + validatorDescription.setDetails("This is a side-chain validator"); + + createSideChainValidator.setDescription(validatorDescription); + + //create and set commission + Commission commission = new Commission(); + commission.setRate(5L); + commission.setMaxRate(100L); + commission.setMaxChangeRate(5L); + + createSideChainValidator.setCommission(commission); + + //set delegator address, here use self address + createSideChainValidator.setDelegatorAddr(wallet.getAddress()); + + createSideChainValidator.setValidatorAddr(wallet.getAddress()); + + //set delegation token, here use 1000000 BNB + Token delegationToken = new Token(); + delegationToken.setDenom("BNB"); + delegationToken.setAmount(10000000000L); + createSideChainValidator.setDelegation(delegationToken); + + //set side-chain id + createSideChainValidator.setSideChainId("bsc"); + + //set side-chain validator cons address + createSideChainValidator.setSideConsAddr("0xd1B22dCC24C55f4d728E7aaA5c9b5a22e1512C08"); + + //set side-chain validator fee address + createSideChainValidator.setSideFeeAddr("0x9fB29AAc15b9A4B7F17c3385939b007540f4d791"); + + byte[] msg = amino.encode(convert(createSideChainValidator), MessageType.CreateSideChainValidator.getTypePrefixBytes(), false); + + Transaction tx = transactionConverter.convert(msg); + Assert.assertNotNull(tx.getRealTx()); + } + + @Test + public void testDecodeEditSideChainValidator() throws IOException { + EditSideChainValidator editSideChainValidator = new EditSideChainValidator(); + + //set new description if needed + Description description = new Description(); + description.setMoniker("new Moniker"); + editSideChainValidator.setDescription(description); + + editSideChainValidator.setValidatorAddress(wallet.getAddress()); + + //set new rate if needed + editSideChainValidator.setCommissionRate(1L); + + //set new fee address if needed + editSideChainValidator.setSideFeeAddr("0xd1B22dCC24C55f4d728E7aaA5c9b5a22e1512C08"); + + editSideChainValidator.setSideChainId("bsc"); + + EditSideChainValidatorMessage message = new EditSideChainValidatorMessage(); + byte[] msg = amino.encode(convert(editSideChainValidator), MessageType.EditSideChainValidator.getTypePrefixBytes(), false); + + Transaction tx = transactionConverter.convert(msg); + Assert.assertNotNull(tx.getRealTx()); + } + + @Test + public void testDecodeSideChainDelegate() throws IOException { + SideChainDelegate sideChainDelegate = new SideChainDelegate(); + + //set delegate token + Token delegation = new Token("BNB", 100000000L); + sideChainDelegate.setDelegation(delegation); + + //set delegator address, here is self + sideChainDelegate.setDelegatorAddress(wallet.getAddress()); + + //set validator address + sideChainDelegate.setValidatorAddress("bva1337r5pk3r6kvs4a8kc3u5yhdjc79c5lg78343t"); + + //set side-chain id + sideChainDelegate.setSideChainId("bsc"); + + byte[] msg = amino.encode(convert(sideChainDelegate), MessageType.SideChainDelegate.getTypePrefixBytes(), false); + + Transaction tx = transactionConverter.convert(msg); + Assert.assertNotNull(tx.getRealTx()); + } + + @Test + public void testDecodeSideChainRedelegate() throws IOException { + SideChainRedelegate redelegate = new SideChainRedelegate(); + + //set redelegate amount + redelegate.setAmount(new Token("bnb".toUpperCase(), 100000000L)); + + //set delegator address + redelegate.setDelegatorAddress(wallet.getAddress()); + + //set source validator address + redelegate.setSrcValidatorAddress("bva1337r5pk3r6kvs4a8kc3u5yhdjc79c5lg78343t"); + + //set destination validator address + redelegate.setDstValidatorAddress("bva10l34nul25nfxyurfkvkyn7z5kumrg0rjun409e"); + + //set side-chain id + redelegate.setSideChainId("bsc"); + + byte[] msg = amino.encode(convert(redelegate), MessageType.SideChainRedelegate.getTypePrefixBytes(), false); + + Transaction tx = transactionConverter.convert(msg); + Assert.assertNotNull(tx.getRealTx()); + } + + @Test + public void testDecodeSideChainUnBond() throws IOException { + SideChainUnBond sideChainUndelegate = new SideChainUnBond(); + + //set unbond amount + sideChainUndelegate.setAmount(new Token("BNB", 5000L)); + + //set delegator address + sideChainUndelegate.setDelegatorAddress(wallet.getAddress()); + + //set validator address + sideChainUndelegate.setValidatorAddress("bva1337r5pk3r6kvs4a8kc3u5yhdjc79c5lg78343t"); + + //set side-chain id + sideChainUndelegate.setSideChainId("bsc"); + + byte[] msg = amino.encode(convert(sideChainUndelegate), MessageType.SideChainUndelegate.getTypePrefixBytes(), false); + + Transaction tx = transactionConverter.convert(msg); + Assert.assertNotNull(tx.getRealTx()); + } + + EditSideChainValidatorMessage convert(EditSideChainValidator editSideChainValidator){ + EditSideChainValidatorMessage message = new EditSideChainValidatorMessage(); + + if (editSideChainValidator.getDescription() != null){ + message.setDescription(convert(editSideChainValidator.getDescription())); + } + + message.setValidatorOperatorAddress(Bech32AddressValue.fromBech32String(editSideChainValidator.getValidatorAddress())); + + message.setCommissionRate(Dec.newInstance(editSideChainValidator.getCommissionRate())); + message.setSideChainId(editSideChainValidator.getSideChainId()); + message.setSideFeeAddr(decodeHexAddress(editSideChainValidator.getSideFeeAddr())); + + return message; + } + + CreateSideChainValidatorMessage convert(CreateSideChainValidator createSideChainValidator){ + CreateSideChainValidatorMessage message = new CreateSideChainValidatorMessage(); + + if (createSideChainValidator.getDescription() != null){ + message.setDescription(convert(createSideChainValidator.getDescription())); + } + if (createSideChainValidator.getCommission() != null){ + message.setCommission(convert(createSideChainValidator.getCommission())); + } + + message.setDelegatorAddr(Bech32AddressValue.fromBech32String(createSideChainValidator.getDelegatorAddr())); + message.setValidatorOperatorAddr(Bech32AddressValue.fromBech32String(createSideChainValidator.getValidatorAddr())); + + if (createSideChainValidator.getDelegation() != null){ + message.setDelegation(convert(createSideChainValidator.getDelegation())); + } + + message.setSideChainId(createSideChainValidator.getSideChainId()); + message.setSideConsAddr(decodeHexAddress(createSideChainValidator.getSideConsAddr())); + message.setSideFeeAddr(decodeHexAddress(createSideChainValidator.getSideFeeAddr())); + return message; + } + + private DescriptionValue convert(Description description){ + DescriptionValue value = new DescriptionValue(); + value.setMoniker(description.getMoniker()); + value.setDetails(description.getDetails()); + value.setIdentity(description.getIdentity()); + value.setWebsite(description.getWebsite()); + return value; + } + + private CommissionMsgValue convert(Commission commission){ + CommissionMsgValue value = new CommissionMsgValue(); + value.setRate(Dec.newInstance(commission.getRate())); + value.setMaxRate(Dec.newInstance(commission.getMaxRate())); + value.setMaxChangeRate(Dec.newInstance(commission.getMaxChangeRate())); + return value; + } + + private CoinValueStr convert(Token token){ + CoinValueStr value = new CoinValueStr(); + value.setDenom(token.getDenom()); + value.setAmount(token.getAmount()); + return value; + } + + private SideChainDelegateMessage convert(SideChainDelegate sideChainDelegate){ + SideChainDelegateMessage message = new SideChainDelegateMessage(); + message.setDelegatorAddress(Bech32AddressValue.fromBech32String(sideChainDelegate.getDelegatorAddress())); + message.setValidatorAddress(Bech32AddressValue.fromBech32String(sideChainDelegate.getValidatorAddress())); + + if (sideChainDelegate.getDelegation() != null) { + message.setDelegation(convert(sideChainDelegate.getDelegation())); + } + + message.setSideChainId(sideChainDelegate.getSideChainId()); + return message; + } + + private SideChainRedelegateMessage convert(SideChainRedelegate redelegate){ + SideChainRedelegateMessage message = new SideChainRedelegateMessage(); + message.setDelegatorAddress(Bech32AddressValue.fromBech32String(redelegate.getDelegatorAddress())); + message.setSrcValidatorAddress(Bech32AddressValue.fromBech32String(redelegate.getSrcValidatorAddress())); + message.setDstValidatorAddress(Bech32AddressValue.fromBech32String(redelegate.getDstValidatorAddress())); + if (redelegate.getAmount() != null) { + message.setAmount(convert(redelegate.getAmount())); + } + message.setSideChainId(redelegate.getSideChainId()); + return message; + } + + private SideChainUndelegateMessage convert(SideChainUnBond unBond){ + SideChainUndelegateMessage message = new SideChainUndelegateMessage(); + message.setDelegatorAddress(Bech32AddressValue.fromBech32String(unBond.getDelegatorAddress())); + message.setValidatorAddress(Bech32AddressValue.fromBech32String(unBond.getValidatorAddress())); + if (unBond.getAmount() != null) { + message.setAmount(convert(unBond.getAmount())); + } + message.setSideChainId(unBond.getSideChainId()); + return message; + } + + private byte[] decodeHexAddress(String address){ + String addr = address; + if (addr.startsWith("0x")){ + addr = address.substring(2); + } + return Hex.decode(addr); + } + +} diff --git a/src/test/java/com/binance/dex/api/client/encoding/rlp/RLPTest.java b/src/test/java/com/binance/dex/api/client/encoding/rlp/RLPTest.java new file mode 100644 index 0000000..d787e11 --- /dev/null +++ b/src/test/java/com/binance/dex/api/client/encoding/rlp/RLPTest.java @@ -0,0 +1,101 @@ +package com.binance.dex.api.client.encoding.rlp; + + +import com.binance.dex.api.client.crosschain.Package; +import com.binance.dex.api.client.crosschain.Payload; +import com.binance.dex.api.client.crosschain.content.ApproveBindSyn; +import com.binance.dex.api.client.crosschain.content.SideDowntimeSlash; +import com.binance.dex.api.client.crosschain.content.TransferInSyn; +import com.binance.dex.api.client.crosschain.content.TransferOutRefund; +import com.binance.dex.api.client.encoding.Crypto; +import com.binance.dex.api.client.encoding.EncodeUtils; +import com.binance.dex.api.client.rlp.Decoder; +import org.bouncycastle.util.encoders.Hex; +import org.junit.Assert; +import org.junit.Test; + + +import java.math.BigInteger; +import java.util.List; + +public class RLPTest { + + @Test + public void testApproveBindSynDecode() throws Exception { + byte[] raw = Hex.decode("f84af8480110b8440000000000000000000000000000000000000000000000000000000000000f4240e280a04142432d44453700000000000000000000000000000000000000000000000000"); + List result = Decoder.decodeList(raw, Package.class); + Assert.assertEquals(1, result.size()); + Assert.assertEquals(1, result.get(0).getChannelId().getValue()); + Assert.assertEquals(16, result.get(0).getSequence().getNumber().longValue()); + Payload payload = result.get(0).getPayload(); + Assert.assertEquals(0, (int) payload.getPackageType()); + Assert.assertEquals(new BigInteger("1000000"), payload.getCrossChainFee()); + Assert.assertTrue(payload.getContent() instanceof ApproveBindSyn); + ApproveBindSyn approveBindSyn = (ApproveBindSyn) payload.getContent(); + Assert.assertEquals(0, approveBindSyn.getStatus().getValue()); + Assert.assertEquals("ABC-DE7", approveBindSyn.getSymbol().getSymbol()); + } + + @Test + public void testTransferOutRefundDecode() throws Exception { + byte[] raw = Hex.decode("f865f8630280b85f010000000000000000000000000000000000000000000000000000000000000000f83ca0424e4200000000000000000000000000000000000000000000000000000000008401312d009425016278faceb917ed90ec5d940352965ac096ad01"); + List result = Decoder.decodeList(raw, Package.class); + result.forEach(pack -> pack.setHrp("tbnb")); + Assert.assertEquals(1, result.size()); + Assert.assertEquals(2, result.get(0).getChannelId().getValue()); + Assert.assertEquals(0, result.get(0).getSequence().getNumber().longValue()); + Payload payload = result.get(0).getPayload(); + Assert.assertEquals(1, (int) payload.getPackageType()); + Assert.assertEquals(new BigInteger("0"), payload.getCrossChainFee()); + Assert.assertTrue(payload.getContent() instanceof TransferOutRefund); + TransferOutRefund transferOutRefund = (TransferOutRefund) payload.getContent(); + Assert.assertEquals("BNB", transferOutRefund.getSymbol().getSymbol()); + Assert.assertEquals(20000000L, transferOutRefund.getRefundAmount().getNumber().longValue()); + Assert.assertEquals("tbnb1y5qky786e6u30mvsa3wegq6jjedvp94dfeyvkw", Crypto.encodeAddress("tbnb", transferOutRefund.getRefundAddr().getRaw())); + Assert.assertEquals(1, transferOutRefund.getRefundReason().getValue()); + } + + @Test + public void testTransferInSyncDecode() throws Exception { + byte[] raw = Hex.decode("f8c7f8c5038306985ab8be0000000000000000000000000000000000000000000000000000000000001e8480f89ba0424e420000000000000000000000000000000000000000000000000000000000940000000000000000000000000000000000000000c9831e84808401312d00ea9425016278faceb917ed90ec5d940352965ac096ad943ece21ac0d97a24d004a6778babda59bbb167deaea9456ec2590d32b63a04f0a8613a85ab829dfc0ef259456ec2590d32b63a04f0a8613a85ab829dfc0ef25845f0415ea"); + List result = Decoder.decodeList(raw, Package.class); + result.forEach(pack -> pack.setHrp("tbnb")); + Assert.assertEquals(1, result.size()); + Assert.assertEquals(3, result.get(0).getChannelId().getValue()); + Assert.assertEquals(432218, result.get(0).getSequence().getNumber().longValue()); + Payload payload = result.get(0).getPayload(); + Assert.assertEquals(0, (int) payload.getPackageType()); + Assert.assertEquals(new BigInteger("2000000"), payload.getCrossChainFee()); + Assert.assertTrue(payload.getContent() instanceof TransferInSyn); + TransferInSyn transferInSyn = (TransferInSyn) payload.getContent(); + Assert.assertEquals("BNB", transferInSyn.getSymbol().getSymbol()); + Assert.assertEquals("0x0000000000000000000000000000000000000000", transferInSyn.getContractAddress().getAddress()); + Assert.assertEquals(2000000, transferInSyn.getAmounts().get(0).getNumber().longValue()); + Assert.assertEquals(20000000, transferInSyn.getAmounts().get(1).getNumber().longValue()); + Assert.assertEquals("tbnb1y5qky786e6u30mvsa3wegq6jjedvp94dfeyvkw", Crypto.encodeAddress("tbnb", transferInSyn.getReceiverAddresses().get(0).getRaw())); + Assert.assertEquals("tbnb18m8zrtqdj73y6qz2vaut40d9nwa3vl02vmyvez", Crypto.encodeAddress("tbnb", transferInSyn.getReceiverAddresses().get(1).getRaw())); + Assert.assertEquals("0x56ec2590d32b63a04f0a8613a85ab829dfc0ef25", transferInSyn.getRefundAddresses().get(0).getAddress()); + Assert.assertEquals("0x56ec2590d32b63a04f0a8613a85ab829dfc0ef25", transferInSyn.getRefundAddresses().get(1).getAddress()); + Assert.assertEquals(1594103274L, transferInSyn.getExpireTime().getValue()); + } + + @Test + public void testSlashDowntimeDecode() throws Exception { + byte[] raw = Hex.decode("f847f8450b80b841000000000000000000000000000000000000000000000000000000000000000000df940dd11a413972d8b1e1367c4b9196f75348424e708301c23c60845f02fca7"); + List result = Decoder.decodeList(raw, Package.class); + result.forEach(pack -> pack.setHrp("tbnb")); + Assert.assertEquals(1, result.size()); + Assert.assertEquals(11, result.get(0).getChannelId().getValue()); + Assert.assertEquals(0, result.get(0).getSequence().getNumber().longValue()); + Payload payload = result.get(0).getPayload(); + Assert.assertEquals(0, (int) payload.getPackageType()); + Assert.assertEquals(new BigInteger("0"), payload.getCrossChainFee()); + Assert.assertTrue(payload.getContent() instanceof SideDowntimeSlash); + SideDowntimeSlash sideDowntimeSlash = (SideDowntimeSlash) payload.getContent(); + Assert.assertEquals("0x0dd11a413972d8b1e1367c4b9196f75348424e70", EncodeUtils.bytesToPrefixHex(sideDowntimeSlash.getSideConsAddr())); + Assert.assertEquals(115260, sideDowntimeSlash.getSideHeight().getValue()); + Assert.assertEquals(96, sideDowntimeSlash.getSideChainId().getValue()); + Assert.assertEquals(1594031271, sideDowntimeSlash.getSideTimestamp().getValue()); + } + +} diff --git a/src/test/java/com/binance/dex/api/client/examples/BridgeNodeExample.java b/src/test/java/com/binance/dex/api/client/examples/BridgeNodeExample.java new file mode 100644 index 0000000..8fc2a96 --- /dev/null +++ b/src/test/java/com/binance/dex/api/client/examples/BridgeNodeExample.java @@ -0,0 +1,142 @@ +package com.binance.dex.api.client.examples; + +import com.binance.dex.api.client.BinanceDexApiClientFactory; +import com.binance.dex.api.client.BinanceDexApiNodeClient; +import com.binance.dex.api.client.BinanceDexEnvironment; +import com.binance.dex.api.client.Wallet; +import com.binance.dex.api.client.crosschain.Package; +import com.binance.dex.api.client.domain.TransactionMetadata; +import com.binance.dex.api.client.domain.bridge.TransferIn; +import com.binance.dex.api.client.domain.broadcast.Transaction; +import com.binance.dex.api.client.domain.broadcast.TransactionOption; +import com.binance.dex.api.client.domain.oracle.ClaimMsg; +import com.binance.dex.api.client.domain.oracle.Prophecy; +import com.binance.dex.api.client.encoding.EncodeUtils; +import com.binance.dex.api.client.encoding.message.Token; +import com.binance.dex.api.client.encoding.message.bridge.BindStatus; +import com.binance.dex.api.client.encoding.message.bridge.ClaimMsgMessage; +import com.binance.dex.api.client.encoding.message.bridge.ClaimTypes; +import com.binance.dex.api.client.encoding.message.bridge.RefundReason; +import com.fasterxml.jackson.core.JsonProcessingException; +import org.apache.commons.codec.binary.Hex; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; +import java.security.NoSuchAlgorithmException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * @author Fitz.Lu + **/ +public class BridgeNodeExample { + + private BinanceDexApiNodeClient nodeClient = null; + private Wallet wallet = null; + + @Before + public void setup() throws IOException { + nodeClient = BinanceDexApiClientFactory.newInstance().newNodeRpcClient("http://dex-qa-s1-bsc-dev-validator-alb-501442930.ap-northeast-1.elb.amazonaws.com:27147",BinanceDexEnvironment.TEST_NET.getHrp(), BinanceDexEnvironment.TEST_NET.getValHrp()); + String mnemonic = "ten spring excite fluid pizza amused goat equal language cinnamon change drive alien second table onion obscure culture void science renew scrub capable wet"; + wallet = Wallet.createWalletFromMnemonicCode(Arrays.asList(mnemonic.split(" ")), BinanceDexEnvironment.TEST_NET); + } + + @Test + public void t() throws JsonProcessingException { + System.out.println(); + Transaction transaction = nodeClient.getTransaction("0757F090A88F99436A6E1B138EA5ED1A5F2A8CC46BF03912F663119A5924DF62"); + ClaimMsg msg = (ClaimMsg)transaction.getRealTx(); + List packages = msg.getPayload(); + System.out.println(EncodeUtils.toJsonStringSortKeys(packages)); + + System.out.println(); + + transaction = nodeClient.getTransaction("59619D76EAB7B5D3FCE17589B6735869A49B77B5A059168731EA31ACE5A3119D"); + msg = (ClaimMsg)transaction.getRealTx(); + packages = msg.getPayload(); + System.out.println(EncodeUtils.toJsonStringSortKeys(packages)); + + System.out.println(); + + transaction = nodeClient.getTransaction("35568AB9D81409A54B38C11924C8B3BB374B8A57A4FF2070EF71BB393E94EE02"); + msg = (ClaimMsg)transaction.getRealTx(); + packages = msg.getPayload(); + System.out.println(EncodeUtils.toJsonStringSortKeys(packages)); + + System.out.println(); + + transaction = nodeClient.getTransaction("29FE859C0B40F73996346FBD9261B4F8B28C8381F13F3D3DCAE87ED3C6EE0A72"); + msg = (ClaimMsg)transaction.getRealTx(); + packages = msg.getPayload(); + System.out.println(EncodeUtils.toJsonStringSortKeys(packages)); + + System.out.println(); + + transaction = nodeClient.getTransaction("362BA6ACD9A831AC30D1C83AAD02F954C38940DCB91610DA4EA43CF7DCEAE0EA"); + msg = (ClaimMsg)transaction.getRealTx(); + packages = msg.getPayload(); + System.out.println(EncodeUtils.toJsonStringSortKeys(packages)); + } + + @Test + public void transferOut() throws IOException, NoSuchAlgorithmException { + String toAddress = "0x9fB29AAc15b9A4B7F17c3385939b007540f4d791"; + Token token = new Token("BNB", 100000L); + long expireTime = System.currentTimeMillis() + 1000 * 60 * 60 * 24 * 3; + + TransactionOption options = new TransactionOption("", 0, null); + + List results = nodeClient.transferOut(toAddress, token, expireTime / 1000, wallet, options, true); + Assert.assertEquals(1, results.size()); + } + + @Test + public void bind() throws IOException, NoSuchAlgorithmException { + String symbol = "BNB"; + long amount = 1000000L; + String contractAddress = "0xd1B22dCC24C55f4d728E7aaA5c9b5a22e1512C08"; + int contractDecimal = 2; + long expireTime = System.currentTimeMillis() + 1000 * 60 * 60 * 24 * 3; + + TransactionOption options = new TransactionOption("", 0, null); + + List results = nodeClient.bind(symbol, amount, contractAddress, contractDecimal, expireTime / 1000, wallet, options, true); + Assert.assertEquals(1, results.size()); + } + + @Test + public void unBind() throws IOException, NoSuchAlgorithmException { + String symbol = "ABC-196"; + TransactionOption options = new TransactionOption("", 0, null); + List results = nodeClient.unBind(symbol, wallet, options, true); + System.out.println(EncodeUtils.toJsonStringSortKeys(results)); + Assert.assertEquals(1, results.size()); + Assert.assertTrue(results.get(0).isOk()); + } + + @Test + public void claim() throws IOException, NoSuchAlgorithmException { + TransactionOption options = new TransactionOption("", 0, null); + List results = nodeClient.claim(2, "test claim message message message message message".getBytes(), 0, wallet, options, true); + Assert.assertEquals(1, results.size()); + Assert.assertTrue(results.get(0).isOk()); + } + + @Test + public void getProphecy() throws IOException { + Prophecy prophecy = nodeClient.getProphecy(ClaimTypes.ClaimTypeTransferIn, 1); + if (prophecy != null){ + Assert.assertNotNull(prophecy.getClaimValidators()); + } + } + + @Test + public void getCurrentSequence(){ + long sequence = nodeClient.getCurrentSequence(ClaimTypes.ClaimTypeTransferIn); + Assert.assertTrue(sequence >= 0); + } + +} diff --git a/src/test/java/com/binance/dex/api/client/examples/NodeClientExample.java b/src/test/java/com/binance/dex/api/client/examples/NodeClientExample.java index c9ef431..f6a4157 100644 --- a/src/test/java/com/binance/dex/api/client/examples/NodeClientExample.java +++ b/src/test/java/com/binance/dex/api/client/examples/NodeClientExample.java @@ -28,7 +28,7 @@ public class NodeClientExample { @Before public void setup() { - binanceDexNodeApi = BinanceDexApiClientFactory.newInstance().newNodeRpcClient(BinanceDexEnvironment.TEST_NET.getNodeUrl(),BinanceDexEnvironment.TEST_NET.getHrp()); + binanceDexNodeApi = BinanceDexApiClientFactory.newInstance().newNodeRpcClient(BinanceDexEnvironment.TEST_NET.getNodeUrl(),BinanceDexEnvironment.TEST_NET.getHrp(), BinanceDexEnvironment.TEST_NET.getValHrp()); } @Test @@ -232,9 +232,9 @@ public void testNodeInfo() { @Test public void testGetTransaction() { - Transaction transaction = binanceDexNodeApi.getTransaction("A1D07086EC08E983A47157FEACC1CF42179C37FCCDD56E7A4460CD1E4C82E51F"); + Transaction transaction = binanceDexNodeApi.getTransaction("1218DC0B64E3A128790AD8697CC9EC19F840D1D4202A5FA6EC64C4424793F5F0"); Assert.assertNotNull(transaction); - Assert.assertEquals("A1D07086EC08E983A47157FEACC1CF42179C37FCCDD56E7A4460CD1E4C82E51F", transaction.getHash()); + Assert.assertEquals("1218DC0B64E3A128790AD8697CC9EC19F840D1D4202A5FA6EC64C4424793F5F0", transaction.getHash()); Assert.assertEquals(0, transaction.getCode().intValue()); } @@ -285,4 +285,10 @@ public void testGetProposalById(){ Proposal proposal = binanceDexNodeApi.getProposalById("1"); Assert.assertEquals("1",proposal.getValue().getProposalId()); } + + @Test + public void testGetSideProposalById(){ + Proposal proposal = binanceDexNodeApi.getSideProposalById("4", "rialto"); + Assert.assertEquals("4",proposal.getValue().getProposalId()); + } } diff --git a/src/test/java/com/binance/dex/api/client/examples/SideChainStakingNodeExample.java b/src/test/java/com/binance/dex/api/client/examples/SideChainStakingNodeExample.java new file mode 100644 index 0000000..d9b924a --- /dev/null +++ b/src/test/java/com/binance/dex/api/client/examples/SideChainStakingNodeExample.java @@ -0,0 +1,277 @@ +package com.binance.dex.api.client.examples; + +import com.binance.dex.api.client.BinanceDexApiClientFactory; +import com.binance.dex.api.client.BinanceDexApiNodeClient; +import com.binance.dex.api.client.BinanceDexEnvironment; +import com.binance.dex.api.client.Wallet; +import com.binance.dex.api.client.domain.TransactionMetadata; +import com.binance.dex.api.client.domain.broadcast.*; +import com.binance.dex.api.client.domain.stake.Commission; +import com.binance.dex.api.client.domain.stake.Description; +import com.binance.dex.api.client.domain.stake.Pool; +import com.binance.dex.api.client.domain.stake.sidechain.*; +import com.binance.dex.api.client.encoding.message.*; +import com.binance.dex.api.client.encoding.message.sidechain.SideChainIds; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; +import java.security.NoSuchAlgorithmException; +import java.util.List; + +/** + * @author Fitz.Lu + **/ +public class SideChainStakingNodeExample { + + private BinanceDexApiNodeClient nodeClient = null; + + private String jackPrivKey = "bce1c934173e84cb4a0abf06b371f7568d3c4686da8f3ea7e1e8d230ae681920"; + private String rosePrivKey = "50111155e4d9adca98c3f9318e896aedeac7fbec8c9f416af076ff042c56b4c5"; + private String markPrivKey = "68931b8fe68ebec5b8fe81420b8de3d47f4ad1dd01619c7e0c93ce9c3a0e3d22"; + + private String jackValidator = "bva1lrzg56jhtkqu7fmca3394vdx00r7apx4gjdzy2"; + private String roseValidator = "bva1rxnydtfjccaz2tck7wrentntdylrnnqzmspush"; + + private final Wallet wallet = new Wallet(markPrivKey, BinanceDexEnvironment.PROD); + + @Before + public void setup() { + nodeClient = BinanceDexApiClientFactory.newInstance().newNodeRpcClient(BinanceDexEnvironment.TEST_NET.getNodeUrl() + ,BinanceDexEnvironment.TEST_NET.getHrp(), BinanceDexEnvironment.TEST_NET.getValHrp()); + } + + @Test + public void testCreateSideChainValidator() throws IOException, NoSuchAlgorithmException { + CreateSideChainValidator createSideChainValidator = new CreateSideChainValidator(); + + //create and set description + Description validatorDescription = new Description(); + validatorDescription.setMoniker("rose-moniker"); + validatorDescription.setIdentity("rose id"); + validatorDescription.setWebsite("https://www.rose.com"); + validatorDescription.setDetails("This is rose validator"); + + createSideChainValidator.setDescription(validatorDescription); + + //create and set commission + Commission commission = new Commission(); + commission.setRate(5L); + commission.setMaxRate(1000L); + commission.setMaxChangeRate(10L); + + createSideChainValidator.setCommission(commission); + + //set delegator address, here use self address + createSideChainValidator.setDelegatorAddr(wallet.getAddress()); + + //set delegation token, here use 1000000 BNB + Token delegationToken = new Token(); + delegationToken.setDenom("BNB"); + delegationToken.setAmount(1000000000000L); + createSideChainValidator.setDelegation(delegationToken); + + //set side-chain id + createSideChainValidator.setSideChainId(SideChainIds.RIALTO); + + //set side-chain validator cons address + createSideChainValidator.setSideConsAddr("0x9fB29AAc15b9A4B7F17c3385939b007540f4d791"); + + //set side-chain validator fee address + createSideChainValidator.setSideFeeAddr("0xd1B22dCC24C55f4d728E7aaA5c9b5a22e1512C08"); + + TransactionOption options = new TransactionOption("", 0, null); + + List transactionMetadatas = nodeClient.createSideChainValidator(createSideChainValidator, wallet, options, true); + Assert.assertEquals(1, transactionMetadatas.size()); + } + + @Test + public void testEditSideChainValidator() throws IOException, NoSuchAlgorithmException { + EditSideChainValidator editSideChainValidator = new EditSideChainValidator(); + + //set new description if needed + Description description = new Description(); + description.setMoniker("new Moniker"); + editSideChainValidator.setDescription(description); + + //set new rate if needed + editSideChainValidator.setCommissionRate(1L); + + //set new fee address if needed + editSideChainValidator.setSideFeeAddr("0xd1B22dCC24C55f4d728E7aaA5c9b5a22e1512C08"); + + editSideChainValidator.setSideChainId(SideChainIds.RIALTO); + + List transactionMetadatas = nodeClient.editSideChainValidator(editSideChainValidator, wallet, createTransactionOptionForTest(), true); + Assert.assertEquals(1, transactionMetadatas.size()); + } + + @Test + public void testSideChainDelegate() throws IOException, NoSuchAlgorithmException { + SideChainDelegate sideChainDelegate = new SideChainDelegate(); + + //set delegate token + Token delegation = new Token("BNB", 123456700L); + sideChainDelegate.setDelegation(delegation); + + //set delegator address, here is self + sideChainDelegate.setDelegatorAddress(wallet.getAddress()); + + //set validator address + sideChainDelegate.setValidatorAddress(roseValidator); + + //set side-chain id + sideChainDelegate.setSideChainId(SideChainIds.RIALTO); + + List transactionMetadatas = nodeClient.sideChainDelegate(sideChainDelegate, wallet, createTransactionOptionForTest(), true); + Assert.assertEquals(1, transactionMetadatas.size()); + } + + @Test + public void testSideChainRedelegate() throws IOException, NoSuchAlgorithmException { + SideChainRedelegate redelegate = new SideChainRedelegate(); + + //set redelegate amount + redelegate.setAmount(new Token("bnb".toUpperCase(), 100000000L)); + + //set delegator address + redelegate.setDelegatorAddress(wallet.getAddress()); + + //set source validator address + redelegate.setSrcValidatorAddress(jackValidator); + + //set destination validator address + redelegate.setDstValidatorAddress(roseValidator); + + //set side-chain id + redelegate.setSideChainId(SideChainIds.RIALTO); + + List transactionMetadatas = nodeClient.sideChainRedelagate(redelegate, wallet, createTransactionOptionForTest(), true); + Assert.assertEquals(1, transactionMetadatas.size()); + } + + @Test + public void testSideChainUnbond() throws IOException, NoSuchAlgorithmException { + SideChainUnBond sideChainUndelegate = new SideChainUnBond(); + + //set unbond amount + sideChainUndelegate.setAmount(new Token("BNB", 1000L)); + + //set delegator address + sideChainUndelegate.setDelegatorAddress(wallet.getAddress()); + + //set validator address + sideChainUndelegate.setValidatorAddress(jackValidator); + + //set side-chain id + sideChainUndelegate.setSideChainId(SideChainIds.RIALTO); + + List transactionMetadatas = nodeClient.sideChainUnbond(sideChainUndelegate, wallet, createTransactionOptionForTest(), true); + Assert.assertEquals(1, transactionMetadatas.size()); + } + + @Test + public void testGetSideChainValidator() throws IOException { + SideChainValidator validator = nodeClient.getSideChainValidator(SideChainIds.RIALTO, jackValidator); + if (validator != null){ + Assert.assertNotNull(validator.getOperatorAddr()); + } + } + + @Test + public void testGetSideChainTopValidators() throws IOException { + List validators = nodeClient.getSideChainTopValidators(SideChainIds.RIALTO, 5); + Assert.assertNotNull(validators); + } + + @Test + public void testGetSideChainDelegation() throws IOException { + SideChainDelegation delegation = nodeClient.getSideChainDelegation(SideChainIds.RIALTO, wallet.getAddress(), roseValidator); + if (delegation != null) { + Assert.assertNotNull(delegation.getDelegation()); + Assert.assertNotNull(delegation.getBalance()); + } + } + + @Test + public void testGetSideChainDelegations() throws IOException { + List delegations = nodeClient.getSideChainDelegations(SideChainIds.RIALTO, wallet.getAddress()); + Assert.assertNotNull(delegations); + } + + @Test + public void getSideChainRedelegation() throws IOException { + SideChainRedelegation redelegation = nodeClient.getSideChainRedelegation(SideChainIds.RIALTO, wallet.getAddress(), jackValidator, roseValidator); + if (redelegation != null) { + Assert.assertNotNull(redelegation.getDelegatorAddress()); + } + } + + @Test + public void getSideChainRedelegations() throws IOException { + List redelegations = nodeClient.getSideChainRedelegations(SideChainIds.RIALTO, wallet.getAddress()); + Assert.assertNotNull(redelegations); + } + + @Test + public void getSideChainUnBondingDelegation() throws IOException { + UnBondingDelegation unBondingDelegation = nodeClient.getSideChainUnBondingDelegation(SideChainIds.RIALTO, wallet.getAddress(), jackValidator); + if (unBondingDelegation != null) { + Assert.assertNotNull(unBondingDelegation.getDelegatorAddress()); + } + } + + @Test + public void getSideChainUnBondingDelegations() throws IOException { + List unBondingDelegations = nodeClient.getSideChainUnBondingDelegations(SideChainIds.RIALTO, wallet.getAddress()); + Assert.assertNotNull(unBondingDelegations); + } + + @Test + public void testGetSideChainUnBondingDelegationsByValidator() throws IOException { + List unBondingDelegations = nodeClient.getSideChainUnBondingDelegationsByValidator(SideChainIds.RIALTO, jackValidator); + Assert.assertNotNull(unBondingDelegations); + } + + @Test + public void testGetSideChainRedelegationsByValidator() throws IOException { + List redelegations = nodeClient.getSideChainRedelegationsByValidator(SideChainIds.RIALTO, jackValidator); + Assert.assertNotNull(redelegations); + } + + @Test + public void testGetSideChainPool() throws IOException { + Pool pool = nodeClient.getSideChainPool(SideChainIds.RIALTO); + if (pool != null){ + Assert.assertTrue(pool.getBondedTokens() >= 0L); + } + } + + @Test + public void testGetSideChainValidatorsCount() throws IOException { + long count = nodeClient.getAllSideChainValidatorsCount(SideChainIds.RIALTO, false); + Assert.assertTrue(count >= 0); + } + + /** + * Print message to console for debug, call + * its toString() method. + * + * @param message the specify message object + * */ + private void consolePrintln(Object message){ + System.out.println(message.toString()); + } + + /** + * Create a transaction option for test + * + * @return TransactionOption + * */ + private TransactionOption createTransactionOptionForTest(){ + return new TransactionOption("", 0, null); + } + +} diff --git a/src/test/java/com/binance/dex/api/client/examples/SideVoteExample.java b/src/test/java/com/binance/dex/api/client/examples/SideVoteExample.java new file mode 100644 index 0000000..c667dcc --- /dev/null +++ b/src/test/java/com/binance/dex/api/client/examples/SideVoteExample.java @@ -0,0 +1,31 @@ +package com.binance.dex.api.client.examples; + +import java.io.IOException; +import java.util.List; + +import com.binance.dex.api.client.*; +import com.binance.dex.api.client.domain.TransactionMetadata; +import com.binance.dex.api.client.domain.broadcast.SideVote; +import com.binance.dex.api.client.domain.broadcast.TransactionOption; + +public class SideVoteExample { + + public static void main(String[] args) throws IOException { + Wallet wallet = Wallet.createRandomWallet(BinanceDexEnvironment.TEST_NET); + BinanceDexApiNodeClient binanceDexNodeApi = BinanceDexApiClientFactory.newInstance().newNodeRpcClient(BinanceDexEnvironment.TEST_NET.getNodeUrl(),BinanceDexEnvironment.TEST_NET.getHrp(), BinanceDexEnvironment.TEST_NET.getValHrp()); + + + TransactionOption options = TransactionOption.DEFAULT_INSTANCE; + SideVote vote = new SideVote(); + vote.setOption(1); + vote.setProposalId(2L); + vote.setSideChainId("rialto"); + try{ + List resp = binanceDexNodeApi.sideVote(vote,wallet,options,true); + System.out.println(resp.get(0)); + }catch (Exception e){ + e.printStackTrace(); + } + } + +}