From 18611f041057cde74df87eb929d3e7e7ac983129 Mon Sep 17 00:00:00 2001 From: Maxim Smolyakov Date: Mon, 7 Sep 2020 15:49:49 +0300 Subject: [PATCH] move state changes actions to separated package; refactoring (#64) * move state changes actions to separated package; refactoring * update to waves-transactions@1.0.0 * Node.compileScript(); upgrade to waves-transactions:1.0.1 * rename api methods * rename TypeRef --- CHANGELOG.md | 6 + README.md | 64 +--- examples/pom.xml | 37 -- examples/src/main/java/GRPCTest.java | 31 -- examples/src/main/java/NodeExample.java | 104 ------ examples/src/main/java/SpreadBot.java | 121 ------- pom.xml | 4 +- .../wavesplatform/wavesj/AssetBalance.java | 8 +- .../wavesplatform/wavesj/AssetDetails.java | 7 +- .../java/com/wavesplatform/wavesj/Block.java | 21 +- .../wavesplatform/wavesj/BlockHeaders.java | 64 ++-- .../com/wavesplatform/wavesj/ByteString.java | 63 ---- .../java/com/wavesplatform/wavesj/Node.java | 179 +++------- .../wavesplatform/wavesj/ScriptDetails.java | 7 +- .../com/wavesplatform/wavesj/ScriptInfo.java | 23 +- .../wavesplatform/wavesj/StateChanges.java | 330 +----------------- .../com/wavesplatform/wavesj/Validation.java | 1 - .../wavesj/actions/BurnAction.java | 50 +++ .../wavesplatform/wavesj/actions/Error.java | 48 +++ .../wavesj/actions/IssueAction.java | 104 ++++++ .../wavesj/actions/ReissueAction.java | 58 +++ .../wavesj/actions/ScriptTransfer.java | 61 ++++ .../wavesj/actions/SponsorFeeAction.java | 50 +++ .../wavesplatform/wavesj/json/TypeRef.java | 2 +- .../wavesj/json/ser/ByteStringSer.java | 18 - 25 files changed, 509 insertions(+), 952 deletions(-) delete mode 100644 examples/pom.xml delete mode 100644 examples/src/main/java/GRPCTest.java delete mode 100644 examples/src/main/java/NodeExample.java delete mode 100644 examples/src/main/java/SpreadBot.java delete mode 100644 src/main/java/com/wavesplatform/wavesj/ByteString.java create mode 100644 src/main/java/com/wavesplatform/wavesj/actions/BurnAction.java create mode 100644 src/main/java/com/wavesplatform/wavesj/actions/Error.java create mode 100644 src/main/java/com/wavesplatform/wavesj/actions/IssueAction.java create mode 100644 src/main/java/com/wavesplatform/wavesj/actions/ReissueAction.java create mode 100644 src/main/java/com/wavesplatform/wavesj/actions/ScriptTransfer.java create mode 100644 src/main/java/com/wavesplatform/wavesj/actions/SponsorFeeAction.java delete mode 100644 src/main/java/com/wavesplatform/wavesj/json/ser/ByteStringSer.java diff --git a/CHANGELOG.md b/CHANGELOG.md index e205a42..1569c0d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## 1.0.0 +- significantly redesigned interface +- based on [Waves Crypto](https://github.com/wavesplatform/waves-crypto-java) and [Waves transactions](https://github.com/wavesplatform/waves-transactions-java) libraries +- supported most of Waves Node API +- feature #15 of Waves Node 1.2 Malibu release is now supported + ## 0.17.0 - new InvokeScriptTransactionStCh with stateChanges attribute was added. It was design to provide an additional information about Invocation transaction and couldn't be used to post invokes into blockchain. That why constructor was marked as package-private - new AllTxIterator class to navigate over all account transactions. It has a generic semantic and can be used for other endpoints and transaction. diff --git a/README.md b/README.md index cfe8954..1afc03c 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # WavesJ A Java library for interacting with the Waves blockchain. -Supports node interaction, offline transaction signing, Matcher orders, and creating addresses and keys. +Supports node interaction, offline transaction signing and creating addresses and keys. ## Using WavesJ in your project Use the codes below to add WavesJ as a dependency for your project. @@ -11,18 +11,18 @@ Use the codes below to add WavesJ as a dependency for your project. com.wavesplatform wavesj - 0.17.0 + 1.0.0 ``` ##### Gradle: ``` -compile group: 'com.wavesplatform', name: 'wavesj', version: '0.17.0' +compile group: 'com.wavesplatform', name: 'wavesj', version: '1.0.0' ``` ##### SBT: ``` -libraryDependencies += "com.wavesplatform" % "wavesj" % "0.17.0" +libraryDependencies += "com.wavesplatform" % "wavesj" % "1.0.0" ``` [This library's page at Maven Central](https://mvnrepository.com/artifact/com.wavesplatform/wavesj) @@ -30,15 +30,15 @@ libraryDependencies += "com.wavesplatform" % "wavesj" % "0.17.0" ## Basic Usage Create an account from a private key ('T' for testnet): ```java -String seed = "health lazy lens fix dwarf salad breeze myself silly december endless rent faculty report beyond"; -PrivateKeyAccount account = PrivateKeyAccount.fromSeed(seed, 0, Account.TESTNET); -byte[] publicKey = account.getPublicKey(); -String address = account.getAddress(); +String seed = Crypto.getRandomSeedPhrase(); +PrivateKey privateKey = PrivateKey.fromSeed(seed); +PublicKey publicKey = PublicKey.from(privateKey); +Address address = Address.from(publicKey); ``` Create a Node and learn a few things about blockchain: ```java -Node node = new Node("https://testnode2.wavesnodes.com/", Account.TESTNET); +Node node = new Node(Profile.MAINNET); System.out.println("Current height is " + node.getHeight()); System.out.println("My balance is " + node.getBalance(address)); System.out.println("With 100 confirmations: " + node.getBalance(address, 100)); @@ -46,48 +46,14 @@ System.out.println("With 100 confirmations: " + node.getBalance(address, 100)); Send some money to a buddy: ```java -String buddy = "3N9gDFq8tKFhBDBTQxR3zqvtpXjw5wW3syA"; -String txId = node.transfer(account, buddy, 1_00000000, 100_000, "Here's for you"); +Address buddy = new Address("3N9gDFq8tKFhBDBTQxR3zqvtpXjw5wW3syA"); +node.broadcast(TransferTransaction.builder(buddy, Amount.of(1_00000000, Asset.WAVES)).getSignedWith(privateKey)); ``` Set a script on an account. Be careful with the script you pass here, as it may lock the account forever! ```java -String setScriptTxId = node.setScript(alice, "tx.type == 13 && height > " + height, Account.TESTNET, SCRIPT_FEE); +Base64String script = node + .compile("{-# CONTENT_TYPE EXPRESSION #-} sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey)") + .script(); +node.broadcast(new SetScriptTransaction(publicKey, script).addProof(privateKey)); ``` - -Sign a transaction offline: -```java -Transaction tx = Transaction.makeTransferTx(account, buddy, 1_00000000, Asset.WAVES, 100_000, Asset.WAVES, ""); -System.out.println("JSON encoded data: " + tx.getJson()); -System.out.println("Server endpoint to send this JSON to: " + tx.getEndpoint()); -``` - -Now send it from an online machine: -```java -node.send(tx); -``` - -Create a DEX order: -```java -Node matcher = new Node("https://testnode2.wavesnodes.com", Account.TESTNET); -String matcherKey = matcher.getMatcherKey(); -String wbtcId = "Fmg13HEHJHuZYbtJq8Da8wifJENq8uBxDuWoP9pVe2Qe"; -Order order = matcher.createOrder(alice, matcherKey, - new AssetPair(Asset.WAVES, wbtcId), - // buy 10 WAVES at 0.00090000 WBTC each - Order.Type.BUY, 90_000, 10 * Asset.TOKEN, - // make order valid for 1 hour - System.currentTimeMillis() + 3_600_000, MATCHER_FEE); -System.out.printf("Filed order " + order.id); -``` -There are some examples under `src/examples/java`. - -## Building the library - -To build from scratch, prepare testnet account with 10 Waves and run - -``` -mvn clean package -DbenzPrivateKey=YourPrivateKeyOnTestnetWith10Waves -``` - -The outputs are placed under the `target` directory. diff --git a/examples/pom.xml b/examples/pom.xml deleted file mode 100644 index b985718..0000000 --- a/examples/pom.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - 4.0.0 - - com.wavesplatform - wavesj-examples - 0.9 - jar - - WavesJ Examples - WavesJ Example Code - https://github.com/wavesplatform/WavesJ - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.7.0 - - 1.8 - 1.8 - - - - - - - - com.wavesplatform - wavesj - 0.9 - - - diff --git a/examples/src/main/java/GRPCTest.java b/examples/src/main/java/GRPCTest.java deleted file mode 100644 index 9573f05..0000000 --- a/examples/src/main/java/GRPCTest.java +++ /dev/null @@ -1,31 +0,0 @@ -import com.wavesplatform.api.grpc.TransactionsApiOuterClass.*; -import com.wavesplatform.api.grpc.TransactionsApiGrpc; -import com.wavesplatform.protobuf.transaction.RecipientOuterClass; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; - -import java.util.Iterator; - -public class GRPCTest { - public static void main(String[] args) { - final ManagedChannel channel = ManagedChannelBuilder.forAddress("mainnet-aws-fr-3.wavesnodes.com", 6870) - .usePlaintext() - .build(); - - final BlocksApiGrpc.BlocksApiBlockingStub blocksApiBlockingStub = BlocksApiGrpc.newBlockingStub(channel); - final BlocksApiOuterClass.BlockWithHeight block = blocksApiBlockingStub.getBlock(BlocksApiOuterClass.BlockRequest.newBuilder().setHeight(1000).build()); - - System.out.println(block); - - final TransactionsApiGrpc.TransactionsApiBlockingStub blockingStub = TransactionsApiGrpc.newBlockingStub(channel); - final TransactionsRequest transactionsRequest = TransactionsRequest.newBuilder() - .setRecipient(RecipientOuterClass.Recipient.newBuilder().setAlias("test_recipient").build()) - .build(); - - final Iterator transactions = blockingStub.getTransactions(transactionsRequest); - for (int i = 0; i < 1000 && transactions.hasNext(); i++) { - final TransactionResponse txResponse = transactions.next(); - System.out.printf("Transaction = %s, height = %d\n", txResponse.getTransaction(), txResponse.getHeight()); - } - } -} diff --git a/examples/src/main/java/NodeExample.java b/examples/src/main/java/NodeExample.java deleted file mode 100644 index a06ade7..0000000 --- a/examples/src/main/java/NodeExample.java +++ /dev/null @@ -1,104 +0,0 @@ -import com.wavesplatform.wavesj.*; -import com.wavesplatform.wavesj.matcher.Order; -import com.wavesplatform.wavesj.transactions.TransferTransaction; -import com.wavesplatform.wavesj.transactions.TransferTransactionV1; - -import java.io.IOException; -import java.net.URISyntaxException; - -import static com.wavesplatform.wavesj.Asset.WAVES; - -public class NodeExample { - - public static void main(String[] args) throws IOException, URISyntaxException { - final long FEE = 100000; - final long ISSUE_FEE = 1 * Asset.TOKEN; - final long SCRIPT_FEE = 400000; - final long MATCHER_FEE = 300000; - - final String WBTC = "Fmg13HEHJHuZYbtJq8Da8wifJENq8uBxDuWoP9pVe2Qe"; - - // Create signing testnet account - String seed = "health lazy lens fix dwarf salad breeze myself silly december endless rent faculty report beyond"; - PrivateKeyAccount alice = PrivateKeyAccount.fromSeed(seed, 0, Account.TESTNET); - // Retrieve its public key - byte[] publicKey = alice.getPublicKey(); - // and its address - String address = alice.getAddress(); - - // Create a Node ("https://testnode1.wavesnodes.com" by default, or you can pass another URL here) - Node node = new Node(); - - // Get blockchain height - int height = node.getHeight(); - System.out.println("height: " + height); - - // Learn address balance - System.out.println("Alice's balance: " + node.getBalance(address)); - // Same, with the specified number of confirmations - System.out.println("With 100 confirmations: " + node.getBalance(address, 100)); - // How much WBTC does Alice have? - System.out.println("Alice's WBTC balance: " + node.getBalance(address, WBTC)); - - - // Transactions - // - String bob = "3N9gDFq8tKFhBDBTQxR3zqvtpXjw5wW3syA"; - - // Create an alias - String txId = node.alias(alice, Account.TESTNET,"alice", FEE); - - // Issue an asset - String assetId = node.issueAsset(alice, Account.TESTNET, "CleanAir", "The first air-backed blockchain asset ever", - 1000000 * Asset.TOKEN, (byte) 8, true, null, ISSUE_FEE); - // Reissuing, making it no longer reissuable - txId = node.reissueAsset(alice, Account.TESTNET, assetId, 100 * Asset.TOKEN, false, ISSUE_FEE); - // Burning some coins - txId = node.burnAsset(alice, Account.TESTNET, assetId, 20 * Asset.TOKEN, ISSUE_FEE); - - // Leasing coins - String leaseTxId = node.lease(alice, bob, 100 * Asset.TOKEN, FEE); - // Canceling a lease by tx ID - String cancelTxId = node.cancelLease(alice, Account.TESTNET, leaseTxId, FEE); - - // Setting a script on an account. - // Be careful with the script you pass here, as it may lock the account forever! - String setScriptTxId = node.setScript(alice, "tx.type == 13 && height > " + height, Account.TESTNET, SCRIPT_FEE); - // Reset the script to default - String rmScriptTxId = node.setScript(alice, "", Account.TESTNET, SCRIPT_FEE); - - // Offline object signing - // - TransferTransaction tx = Transactions.makeTransferTx(alice, bob, - 1 * Asset.TOKEN, WAVES, FEE, WAVES, - "Here's for the coffee"); - // tx.getEndpoint() == "/assets/broadcast/transfer" is the server endpoint to send this object to. - // tx.getJson() is JSON-encoded object data. You can use Swagger UI to send it to the network. - - // Now send the signed object from an online computer - node.send(tx); - - - // Matcher interaction - // - Node matcher = new Node("https://testnode2.wavesnodes.com", 'T'); - String matcherKey = matcher.getMatcherKey(); - - // Create an order - AssetPair market = new AssetPair(Asset.WAVES, WBTC); - Order order = matcher.createOrder(alice, matcherKey, market, - // buy 10 WAVES at 0.00090000 WBTC each - Order.Type.BUY, 90000, 10 * Asset.TOKEN, - // make order valid for 1 hour - System.currentTimeMillis() + 3600000, MATCHER_FEE); - String orderId = order.getId().getBase58String(); - System.out.printf("Filed order %s to %s %d WAVES at %.8f\n", - order.getId(), order.getOrderType(), order.getAmount() / Asset.TOKEN, ((float) order.getPrice()) / Asset.TOKEN); - - // Get order status by id - matcher.getOrderStatus(orderId, market); - - // Cancel order - matcher.cancelOrder(alice, market, orderId); - } -} diff --git a/examples/src/main/java/SpreadBot.java b/examples/src/main/java/SpreadBot.java deleted file mode 100644 index 1fb3750..0000000 --- a/examples/src/main/java/SpreadBot.java +++ /dev/null @@ -1,121 +0,0 @@ -import com.wavesplatform.wavesj.*; -import com.wavesplatform.wavesj.matcher.Order; - -import java.io.IOException; -import java.net.URISyntaxException; -import java.util.Timer; -import java.util.TimerTask; - -public class SpreadBot { - private final long maxOrderSize = 1 * Asset.MILLI; // in priceAsset - private final double halfSpread = 0.01; // 1% - private final long fee = 3 * Asset.MILLI; // in WAVES - private final long period = 60000; // 1 min - - private final PrivateKeyAccount account; - private final AssetPair market; - private final Node node, matcher; - private final String matcherKey; - - public static SpreadBot testnetInstance() throws IOException, URISyntaxException { - return new SpreadBot( - PrivateKeyAccount.fromPrivateKey("25Um7fKYkySZnweUEVAn9RLtxN5xHRd7iqpqYSMNQEeT", Account.TESTNET), - new AssetPair(Asset.WAVES, "Fmg13HEHJHuZYbtJq8Da8wifJENq8uBxDuWoP9pVe2Qe"), - "https://testnode2.wavesnodes.com", - "https://testnode2.wavesnodes.com", 'T'); - } - - public static SpreadBot mainnetInstance() throws IOException, URISyntaxException { - String nodeUrl = "http://dex-aws-ir-1.wavesnodes.com"; - return new SpreadBot( - PrivateKeyAccount.fromSeed( - "abandon ability able about above absent absorb abstract absurd abuse access accident account accuse achieve", - 0, Account.MAINNET), - new AssetPair(Asset.WAVES, "8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS"), - nodeUrl + ":6886", - nodeUrl, 'W'); - } - - private SpreadBot(PrivateKeyAccount account, AssetPair market, String matcherUrl, String nodeUrl, char chainId) throws IOException, URISyntaxException { - this.account = account; - this.market = market; - this.node = new Node(nodeUrl, chainId); - this.matcher = new Node(matcherUrl, chainId); - this.matcherKey = matcher.getMatcherKey(); - } - - private void cancelOrder(String orderId) throws IOException, InterruptedException { - String status = matcher.cancelOrder(account, market, orderId); - System.out.printf("%s %s\n", status, orderId); - } - - private String fileOrder(Order.Type type, long price, long amount) throws IOException, InterruptedException { - long expiration = System.currentTimeMillis() + Math.max(period, 61000); // matcher requires expiration > 1 min in the future - Order order = matcher.createOrder(account, matcherKey, market, type, price, amount, expiration, fee); - System.out.printf("Filed order %s to %s %d at %d\n", order.getId(), type, amount, price); - return order.getId().getBase58String(); - } - - private void round() throws IOException, InterruptedException { - System.out.println(); - - // Cancel all orders filed at our market - for (Order order: matcher.getOrders(account, market)) { - if (order.isActive()) { - cancelOrder(order.getId().getBase58String()); - } - } - - // Read order book - OrderBook book = matcher.getOrderBook(market); - if (book.getBids().size() <= 0) { - System.out.println("There are no bids, skipping this round"); - return; - } - if (book.getAsks().size() <= 0) { - System.out.println("There are no asks, skipping this round"); - return; - } - - // Determine buy and sell prices - long bestBid = book.getBids().get(0).getPrice(); - long bestAsk = book.getAsks().get(0).getPrice(); - System.out.printf("Spread %d : %d\n", bestBid, bestAsk); - long meanPrice = (bestBid + bestAsk) / 2; - long buyPrice = (long) (meanPrice * (1 - halfSpread)); - long sellPrice = (long) (meanPrice * (1 + halfSpread)); - - // Find out how much we want to buy, and file an order - long priceAssetAvail = node.getBalance(account.getAddress(), market.getPriceAsset()) - 2 * fee; - if (priceAssetAvail > 0) { - long buyOrderSize = Math.min(priceAssetAvail, maxOrderSize) * Asset.TOKEN / buyPrice; - fileOrder(Order.Type.BUY, buyPrice, buyOrderSize); - } - - // Same for sell order - long amountAssetAvail = node.getBalance(account.getAddress(), market.getAmountAsset()) - 2 * fee; - if (amountAssetAvail > 0) { - long sellOrderSize = Math.min(amountAssetAvail, maxOrderSize * Asset.TOKEN / sellPrice); - fileOrder(Order.Type.SELL, sellPrice, sellOrderSize); - } - } - - private class RoundTask extends TimerTask { - @Override public void run() { - try { - round(); - } catch (Exception e) { - e.printStackTrace(); - } - } - } - - public void run() { - Timer t = new Timer(); - t.schedule(new RoundTask(), 0, period); - } - - public static void main(String[] args) throws IOException, URISyntaxException { - SpreadBot.testnetInstance().run(); - } -} diff --git a/pom.xml b/pom.xml index d065db1..7d939bd 100644 --- a/pom.xml +++ b/pom.xml @@ -144,11 +144,11 @@ - + im.mak waves-transactions - 1.0.0-rc1 + 1.0.1 com.wavesplatform diff --git a/src/main/java/com/wavesplatform/wavesj/AssetBalance.java b/src/main/java/com/wavesplatform/wavesj/AssetBalance.java index 7022eac..d4eb6c0 100644 --- a/src/main/java/com/wavesplatform/wavesj/AssetBalance.java +++ b/src/main/java/com/wavesplatform/wavesj/AssetBalance.java @@ -3,14 +3,14 @@ import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import im.mak.waves.transactions.Transaction; -import im.mak.waves.transactions.common.Id; +import im.mak.waves.transactions.common.AssetId; import java.util.Objects; @SuppressWarnings("unused") public class AssetBalance { - public final Id assetId; + public final AssetId assetId; public final long balance; public final boolean reissuable; public final long minSponsoredAssetFee; @@ -19,7 +19,7 @@ public class AssetBalance { public final Transaction issueTransaction; @JsonCreator - public AssetBalance(@JsonProperty("assetId") Id assetId, + public AssetBalance(@JsonProperty("assetId") AssetId assetId, @JsonProperty("balance") long balance, @JsonProperty("reissuable") boolean reissuable, @JsonProperty("minSponsoredAssetFee") long minSponsoredAssetFee, @@ -35,7 +35,7 @@ public AssetBalance(@JsonProperty("assetId") Id assetId, this.issueTransaction = issueTransaction; } - public Id assetId() { + public AssetId assetId() { return assetId; } diff --git a/src/main/java/com/wavesplatform/wavesj/AssetDetails.java b/src/main/java/com/wavesplatform/wavesj/AssetDetails.java index 1c3f0db..bf4f09f 100644 --- a/src/main/java/com/wavesplatform/wavesj/AssetDetails.java +++ b/src/main/java/com/wavesplatform/wavesj/AssetDetails.java @@ -4,6 +4,7 @@ import com.fasterxml.jackson.annotation.JsonProperty; import im.mak.waves.transactions.account.Address; import im.mak.waves.transactions.account.PublicKey; +import im.mak.waves.transactions.common.AssetId; import im.mak.waves.transactions.common.Id; import java.util.Objects; @@ -11,7 +12,7 @@ @SuppressWarnings("unused") public class AssetDetails { - private final Id assetId; + private final AssetId assetId; private final int issueHeight; private final long issueTimestamp; private final Address issuer; @@ -27,7 +28,7 @@ public class AssetDetails { private final ScriptDetails scriptDetails; @JsonCreator - public AssetDetails(@JsonProperty("assetId") Id assetId, + public AssetDetails(@JsonProperty("assetId") AssetId assetId, @JsonProperty("issueHeight") int issueHeight, @JsonProperty("issueTimestamp") long issueTimestamp, @JsonProperty("issuer") Address issuer, @@ -57,7 +58,7 @@ public AssetDetails(@JsonProperty("assetId") Id assetId, this.scriptDetails = scriptDetails == null ? new ScriptDetails("", 0) : scriptDetails; } - public Id assetId() { + public AssetId assetId() { return assetId; } diff --git a/src/main/java/com/wavesplatform/wavesj/Block.java b/src/main/java/com/wavesplatform/wavesj/Block.java index 445607c..8135102 100644 --- a/src/main/java/com/wavesplatform/wavesj/Block.java +++ b/src/main/java/com/wavesplatform/wavesj/Block.java @@ -3,8 +3,7 @@ import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import im.mak.waves.transactions.account.Address; -import im.mak.waves.transactions.account.PublicKey; -import im.mak.waves.transactions.common.Id; +import im.mak.waves.transactions.common.Base58String; import java.util.List; import java.util.Objects; @@ -22,28 +21,27 @@ public class Block extends BlockHeaders { public Block( @JsonProperty("version") int version, @JsonProperty("timestamp") long timestamp, - @JsonProperty("reference") Id reference, - @JsonProperty("transactionsRoot") String transactionsRoot, - @JsonProperty("id") Id id, + @JsonProperty("reference") Base58String reference, + @JsonProperty("transactionsRoot") Base58String transactionsRoot, + @JsonProperty("id") Base58String id, @JsonProperty("features") List features, @JsonProperty("desiredReward") long desiredReward, @JsonProperty("generator") Address generator, - @JsonProperty("generatorPublicKey") PublicKey generatorPublicKey, - @JsonProperty("signature") String signature, + @JsonProperty("signature") Base58String signature, @JsonProperty("blocksize") int size, - @JsonProperty("transactionsCount") int transactionsCount, + @JsonProperty("transactionCount") int transactionsCount, @JsonProperty("height") int height, @JsonProperty("totalFee") long totalFee, @JsonProperty("reward") long reward, - @JsonProperty("VRF") Id vrf, + @JsonProperty("VRF") Base58String vrf, @JsonProperty("fee") long fee, @JsonProperty("transactions") List transactions) { super(version, timestamp, reference, transactionsRoot, id, features, desiredReward, generator, - generatorPublicKey, signature, size, transactionsCount, height, totalFee, reward, vrf); + signature, size, transactionsCount, height, totalFee, reward, vrf); this.fee = fee; this.transactions = Common.notNull(transactions, "Transactions"); - //transactions in block don't have height + //transactions in block don't have height field in json for (int i = 0; i < this.transactions.size(); i++) { TransactionInfo info = this.transactions.get(i); if (info.height() == 0) @@ -87,7 +85,6 @@ public String toString() { ", features=" + features() + ", desiredReward=" + desiredReward() + ", generator=" + generator() + - ", generatorPublicKey=" + generatorPublicKey() + ", signature='" + signature() + '\'' + ", size=" + size() + ", transactionsCount=" + transactionsCount() + diff --git a/src/main/java/com/wavesplatform/wavesj/BlockHeaders.java b/src/main/java/com/wavesplatform/wavesj/BlockHeaders.java index 3a52b2b..5fc0aa6 100644 --- a/src/main/java/com/wavesplatform/wavesj/BlockHeaders.java +++ b/src/main/java/com/wavesplatform/wavesj/BlockHeaders.java @@ -3,8 +3,7 @@ import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import im.mak.waves.transactions.account.Address; -import im.mak.waves.transactions.account.PublicKey; -import im.mak.waves.transactions.common.Id; +import im.mak.waves.transactions.common.Base58String; import java.util.ArrayList; import java.util.List; @@ -18,63 +17,60 @@ public class BlockHeaders { private final int version; private final long timestamp; - private final Id reference; + private final Base58String reference; private long baseTarget; - private String generationSignature; - private final String transactionsRoot; //todo common type - private final Id id; + private Base58String generationSignature; + private final Base58String transactionsRoot; + private final Base58String id; private final List features; private final long desiredReward; private final Address generator; - private final PublicKey generatorPublicKey; - private final String signature; //todo common type + private final Base58String signature; private final int size; private final int transactionsCount; private final int height; private final long totalFee; private final long reward; - private final Id vrf; //todo common binary type instead of Id + private final Base58String vrf; @JsonCreator - public BlockHeaders( //todo what about old versions? + public BlockHeaders( //todo test on old versions of block @JsonProperty("version") int version, @JsonProperty("timestamp") long timestamp, - @JsonProperty("reference") Id reference, - @JsonProperty("transactionsRoot") String transactionsRoot, - @JsonProperty("id") Id id, + @JsonProperty("reference") Base58String reference, + @JsonProperty("transactionsRoot") Base58String transactionsRoot, + @JsonProperty("id") Base58String id, @JsonProperty("features") List features, @JsonProperty("desiredReward") long desiredReward, @JsonProperty("generator") Address generator, - @JsonProperty("generatorPublicKey") PublicKey generatorPublicKey, - @JsonProperty("signature") String signature, + @JsonProperty("signature") Base58String signature, @JsonProperty("blocksize") int size, - @JsonProperty("transactionsCount") int transactionsCount, + @JsonProperty("transactionCount") int transactionsCount, @JsonProperty("height") int height, @JsonProperty("totalFee") long totalFee, @JsonProperty("reward") long reward, - @JsonProperty("VRF") Id vrf) { + @JsonProperty("VRF") Base58String vrf) { this.height = height; this.version = version; this.timestamp = timestamp; this.reference = Common.notNull(reference, "Reference"); - this.transactionsRoot = height == 1 ? "" : Common.notNull(transactionsRoot, "TransactionsRoot"); - this.id = height == 1 ? Id.as("11111111111111111111111111111111") : Common.notNull(id, "Id"); - this.features = height == 1 ? new ArrayList<>() : Common.notNull(features, "Features"); - this.desiredReward = desiredReward; this.generator = Common.notNull(generator, "Generator"); - this.generatorPublicKey = Common.notNull(generatorPublicKey, "GeneratorPublicKey"); this.signature = Common.notNull(signature, "Signature"); + this.id = id == null ? this.signature : id; + this.vrf = vrf == null ? Base58String.empty() : vrf; + this.transactionsRoot = transactionsRoot == null ? Base58String.empty() : transactionsRoot; this.size = size; this.transactionsCount = transactionsCount; this.totalFee = totalFee; this.reward = reward; - this.vrf = vrf == null ? Id.as("11111111111111111111111111111111") : vrf; + this.desiredReward = desiredReward; + this.features = features == null ? new ArrayList<>() : features; } @JsonProperty("nxt-consensus") private void nxtConsensus(Map nxtConsensus) { this.baseTarget = (int) nxtConsensus.get("base-target"); - this.generationSignature = (String) nxtConsensus.get("generation-signature"); + this.generationSignature = new Base58String((String) nxtConsensus.get("generation-signature")); } public int version() { @@ -85,7 +81,7 @@ public long timestamp() { return timestamp; } - public Id reference() { + public Base58String reference() { return reference; } @@ -93,15 +89,15 @@ public long baseTarget() { return baseTarget; } - public String generationSignature() { + public Base58String generationSignature() { return generationSignature; } - public String transactionsRoot() { + public Base58String transactionsRoot() { return transactionsRoot; } - public Id id() { + public Base58String id() { return id; } @@ -117,11 +113,7 @@ public Address generator() { return generator; } - public PublicKey generatorPublicKey() { - return generatorPublicKey; - } - - public String signature() { + public Base58String signature() { return signature; } @@ -145,7 +137,7 @@ public long reward() { return reward; } - public Id vrf() { + public Base58String vrf() { return vrf; } @@ -169,14 +161,13 @@ public boolean equals(Object o) { Objects.equals(id, that.id) && Objects.equals(features, that.features) && Objects.equals(generator, that.generator) && - Objects.equals(generatorPublicKey, that.generatorPublicKey) && Objects.equals(signature, that.signature) && Objects.equals(vrf, that.vrf); } @Override public int hashCode() { - return Objects.hash(version, timestamp, reference, baseTarget, generationSignature, transactionsRoot, id, features, desiredReward, generator, generatorPublicKey, signature, size, transactionsCount, height, totalFee, reward, vrf); + return Objects.hash(version, timestamp, reference, baseTarget, generationSignature, transactionsRoot, id, features, desiredReward, generator, signature, size, transactionsCount, height, totalFee, reward, vrf); } @Override @@ -192,7 +183,6 @@ public String toString() { ", features=" + features + ", desiredReward=" + desiredReward + ", generator=" + generator + - ", generatorPublicKey=" + generatorPublicKey + ", signature='" + signature + '\'' + ", size=" + size + ", transactionsCount=" + transactionsCount + diff --git a/src/main/java/com/wavesplatform/wavesj/ByteString.java b/src/main/java/com/wavesplatform/wavesj/ByteString.java deleted file mode 100644 index 928cbe4..0000000 --- a/src/main/java/com/wavesplatform/wavesj/ByteString.java +++ /dev/null @@ -1,63 +0,0 @@ -package com.wavesplatform.wavesj; - -import com.google.common.base.Suppliers; -import im.mak.waves.crypto.base.Base58; - -import java.io.Serializable; -import java.util.Arrays; -import java.util.function.Supplier; - -@SuppressWarnings("unused") -public class ByteString implements Serializable { - private final byte[] bytes; - private final Supplier base58; - - public ByteString(final String base58String) throws IllegalArgumentException { - // to check valid base58 string - if (base58String != null) { - this.bytes = Base58.decode(base58String); - this.base58 = Suppliers.memoize(() -> base58String)::get; - } else { - this.base58 = Suppliers.memoize(() -> "")::get; - this.bytes = EMPTY.bytes; - } - } - - public ByteString(final byte[] bytes) { - this.bytes = bytes; - this.base58 = Suppliers.memoize(() -> (bytes == null) ? "" : Base58.encode(bytes))::get; - } - - public static ByteString EMPTY = new ByteString(new byte[0]); - - public String getBase58String() { - return base58.get(); - } - - public byte[] getBytes() { - return this.bytes; - } - - - @Override - public String toString(){ - return this.getBase58String(); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - final ByteString that = (ByteString) o; - final byte[] leftBytes = getBytes(); - final byte[] rightBytes = that.getBytes(); - return leftBytes != null ? Arrays.equals(leftBytes, rightBytes) : rightBytes == null; - } - - @Override - public int hashCode() { - final byte[] bytes = getBytes(); - return bytes != null ? Arrays.hashCode(bytes) : 0; - } -} diff --git a/src/main/java/com/wavesplatform/wavesj/Node.java b/src/main/java/com/wavesplatform/wavesj/Node.java index d768d25..2f0e208 100644 --- a/src/main/java/com/wavesplatform/wavesj/Node.java +++ b/src/main/java/com/wavesplatform/wavesj/Node.java @@ -7,12 +7,11 @@ import com.wavesplatform.wavesj.exceptions.NodeException; import com.wavesplatform.wavesj.json.TypeRef; import com.wavesplatform.wavesj.json.WavesJMapper; +import im.mak.waves.transactions.WavesConfig; import im.mak.waves.transactions.account.Address; import im.mak.waves.transactions.LeaseTransaction; import im.mak.waves.transactions.Transaction; -import im.mak.waves.transactions.common.Alias; -import im.mak.waves.transactions.common.Amount; -import im.mak.waves.transactions.common.Id; +import im.mak.waves.transactions.common.*; import im.mak.waves.transactions.data.DataEntry; import im.mak.waves.transactions.serializers.json.JsonSerializer; import org.apache.http.HttpResponse; @@ -36,56 +35,9 @@ import static im.mak.waves.transactions.serializers.json.JsonSerializer.JSON_MAPPER; -//todo NodeGRPC @SuppressWarnings("unused") public class Node { - /* Not supported endpoints: - activationStatus - createAddress - deleteAddress - data get or post or form - addresses/publicKey - addresses/seed - addresses/sign - addresses/signText - addresses/validate - addresses/verify - addresses/verifyText - consensus/algo - consensus/basetarget, (blockId) - consensus/generatingbalance - debug/blacklist - debug/blocks/howMany - debug/configInfo - debug/info - debug/minerInfo - debug/portfolios - debug/print - debug/rollback - debug/rollback-to - debug/state - debug/stateWaves - node/status - node/stop - peers - peers/blacklisted - peers/clearblacklist - peers/connect - peers/connected - peers/suspended - transactions/sign, (address) - utils/hash/fast - utils/hash/secure - utils/script/compileCode - utils/script/decompile - utils/script/compileWithImports - utils/seed, (length) - utils/time - utils/transactionSerialize - wallet/seed - */ - private final byte chainId; private final HttpClient client; private final URI uri; @@ -103,8 +55,9 @@ public Node(URI uri) throws IOException, NodeException { .setCookieSpec(CookieSpecs.STANDARD) .build()) .build(); - this.mapper = new WavesJMapper(); //todo make static global? Inherit from waves-transactions? Or get from it? - this.chainId = getAddresses().get(0).bytes()[1]; + this.mapper = new WavesJMapper(); + this.chainId = getAddresses().get(0).chainId(); + WavesConfig.chainId(this.chainId); } public Node(String url) throws URISyntaxException, IOException, NodeException { @@ -127,8 +80,6 @@ public URI uri() { return uri; } - //todo javadoc - //=============== // ADDRESSES //=============== @@ -151,6 +102,8 @@ public long getBalance(Address address, int confirmations) throws IOException, N .get("balance").asLong(); } + //todo getBalances(height, Address...) for several addresses at height + public BalanceDetails getBalanceDetails(Address address) throws IOException, NodeException { return asType(get("/addresses/balance/details/" + address.toString()), TypeRef.BALANCE_DETAILS); } @@ -212,7 +165,7 @@ public List getAliasesByAddress(Address address) throws IOException, Node return asType(get("/alias/by-address/" + address.toString()), TypeRef.ALIASES); } - public Address getAddrByAlias(Alias alias) throws IOException, NodeException { + public Address getAddressByAlias(Alias alias) throws IOException, NodeException { return Address.as(asJson(get("/alias/by-alias/" + alias.name())).get("address").asText()); } @@ -220,15 +173,15 @@ public Address getAddrByAlias(Alias alias) throws IOException, NodeException { // ASSETS //=============== - public AssetDistribution getAssetDistribution(Id assetId, int height) throws IOException, NodeException { + public AssetDistribution getAssetDistribution(AssetId assetId, int height) throws IOException, NodeException { return getAssetDistribution(assetId, height, 10); } - public AssetDistribution getAssetDistribution(Id assetId, int height, int limit) throws IOException, NodeException { + public AssetDistribution getAssetDistribution(AssetId assetId, int height, int limit) throws IOException, NodeException { return getAssetDistribution(assetId, height, limit, null); } - public AssetDistribution getAssetDistribution(Id assetId, int height, int limit, Address after) throws IOException, NodeException { + public AssetDistribution getAssetDistribution(AssetId assetId, int height, int limit, Address after) throws IOException, NodeException { RequestBuilder request = get("/assets/" + assetId.toString() + "/distribution/" + height + "/limit/" + limit); if (after != null) request.addParameter("after", after.toString()); @@ -240,18 +193,18 @@ public List getAssetsBalance(Address address) throws IOException, .readValue(asJson(get("/assets/balance/" + address.toString())).get("balances")); } - public long getAssetBalance(Address address, Id assetId) throws IOException, NodeException { + public long getAssetBalance(Address address, AssetId assetId) throws IOException, NodeException { return asJson(get("/assets/balance/" + address.toString() + "/" + assetId.toString())) .get("balance").asLong(); } - public AssetDetails getAssetDetails(Id assetId) throws IOException, NodeException { + public AssetDetails getAssetDetails(AssetId assetId) throws IOException, NodeException { return asType(get("/assets/details/" + assetId.toString()).addParameter("full", "true"), TypeRef.ASSET_DETAILS); } //todo what if some asset doesn't exist? (error json with code and message) Either in java? - public List getAssetsDetails(List assetIds) throws IOException, NodeException { + public List getAssetsDetails(List assetIds) throws IOException, NodeException { RequestBuilder request = get("/assets/details").addParameter("full", "true"); assetIds.forEach(id -> request.addParameter("id", id.toString())); @@ -266,7 +219,7 @@ public List getNft(Address address, int limit) throws IOException, return this.getNft(address, limit, null); } - public List getNft(Address address, int limit, Id after) throws IOException, NodeException { + public List getNft(Address address, int limit, AssetId after) throws IOException, NodeException { RequestBuilder request = get("/assets/nft/" + address.toString() + "/limit/" + limit); if (after != null) request.addParameter("after", after.toString()); @@ -304,13 +257,13 @@ public int getHeight() throws IOException, NodeException { return asJson(get("/blocks/height")).get("height").asInt(); } - public int getBlockHeight(Id blockId) throws IOException, NodeException { + public int getBlockHeight(Base58String blockId) throws IOException, NodeException { return asJson(get("/blocks/height/" + blockId.toString())) .get("height").asInt(); } - public int getBlocksDelay(Id startBlock, int blocksNum) throws IOException, NodeException { - return asJson(get("/blocks/delay/" + startBlock.toString() + "/" + blocksNum)) + public int getBlocksDelay(Base58String startBlockId, int blocksNum) throws IOException, NodeException { + return asJson(get("/blocks/delay/" + startBlockId.toString() + "/" + blocksNum)) .get("delay").asInt(); } @@ -325,7 +278,7 @@ public BlockHeaders getBlockHeaders(int height) throws IOException, NodeExceptio return asType(get("/blocks/headers/at/" + height), TypeRef.BLOCK_HEADERS); } - public BlockHeaders getBlockHeaders(Id blockId) throws IOException, NodeException { + public BlockHeaders getBlockHeaders(Base58String blockId) throws IOException, NodeException { return asType(get("/blocks/headers/" + blockId.toString()), TypeRef.BLOCK_HEADERS); } @@ -369,7 +322,7 @@ public Block getBlock(int height) throws IOException, NodeException { * @return block object * @throws IOException if no block with the given signature exists */ - public Block getBlock(Id blockId) throws IOException, NodeException { + public Block getBlock(Base58String blockId) throws IOException, NodeException { return asType(get("/blocks/" + blockId.toString()), TypeRef.BLOCK); } @@ -410,20 +363,20 @@ public TransactionDebugInfo getStateChanges(Id txId) throws IOException, NodeExc return asType(get("/debug/stateChanges/info/" + txId.toString()), TypeRef.TRANSACTION_DEBUG_INFO); } - public List getAddressStateChanges(Address address, int limit, Id after) throws IOException, NodeException { + public List getStateChangesByAddress(Address address, int limit, Id afterTxId) throws IOException, NodeException { RequestBuilder request = get("/debug/stateChanges/address/" + address.toString() + "/limit/" + limit); - if (after != null) - request.addParameter("after", after.toString()); + if (afterTxId != null) + request.addParameter("after", afterTxId.toString()); return asType(request, TypeRef.TRANSACTIONS_DEBUG_INFO); } - public List getAddressStateChanges(Address address, int limit) throws IOException, NodeException { - return getAddressStateChanges(address, limit, null); + public List getStateChangesByAddress(Address address, int limit) throws IOException, NodeException { + return getStateChangesByAddress(address, limit, null); } - public List getAddressStateChanges(Address address) throws IOException, NodeException { - return getAddressStateChanges(address, 10); + public List getStateChangesByAddress(Address address) throws IOException, NodeException { + return getStateChangesByAddress(address, 10); } public Validation validateTransaction(T transaction) throws IOException, NodeException { @@ -431,32 +384,6 @@ public Validation validateTransaction(T transaction) thr .setEntity(new StringEntity(transaction.toJson(), ContentType.APPLICATION_JSON)), TypeRef.VALIDATION); } - //todo do the same for all endpoints with pagination - /* - * Returns iterator with dynamic transactions loading to navigate over all account transactions including state changes - * information - * - * Be careful. Some nodes could turn OFF information about state changes. - * Also iterator can throw {@link AllTxIterator.WrappedIOException} in case of any network failures - * - * @param address account address - * @param pageSize page size to navigate over all transactions - * @return iterator which can throw {@link AllTxIterator.WrappedIOException} - * @throws IOException in case of any network failures - */ - /*public Iterable getAllAddressStateChanges(String address, int pageSize) throws IOException, NodeException { - try { - return new AllTxIterator(address, pageSize, new TransactionsLazyLoader>() { - @Override - public List load(String address, int limit, String after) throws IOException, NodeException { - return NewNode.this.getAddressStateChanges(address, limit, after) ; - } - }); - } catch (AllTxIterator.WrappedIOException ex) { - throw ex.unwrap(); - } - }*/ - //=============== // LEASING //=============== @@ -477,11 +404,10 @@ public Amount calculateTransactionFee(T transaction) thr /* example to javadoc: IssueTransaction tx = broadcast(IssueTransaction.with("", 1, 0).get()); */ - //todo throw BroadcastException(code, message, tx, trace, validate) extends NodeException public T broadcast(T transaction) throws IOException, NodeException { //noinspection unchecked return (T) asType(post("/transactions/broadcast") - .setEntity(new StringEntity(transaction.toJson(), ContentType.APPLICATION_JSON)), + .setEntity(new StringEntity(transaction.toJson(), ContentType.APPLICATION_JSON)), TypeRef.TRANSACTION); } @@ -503,8 +429,8 @@ public TransactionInfo getTransactionInfo(Id txId) throws IOException, NodeExcep * @return list of transactions * @throws IOException if something going wrong */ - public List getAddressTransactions(Address address) throws IOException, NodeException { - return getAddressTransactions(address, 10); + public List getTransactionsByAddress(Address address) throws IOException, NodeException { + return getTransactionsByAddress(address, 10); } /** @@ -515,23 +441,23 @@ public List getAddressTransactions(Address address) throws IOEx * @return list of transactions * @throws IOException if something going wrong */ - public List getAddressTransactions(Address address, int limit) throws IOException, NodeException { - return getAddressTransactions(address, limit, null); + public List getTransactionsByAddress(Address address, int limit) throws IOException, NodeException { + return getTransactionsByAddress(address, limit, null); } /** * Returns transactions by address with limit after passed transaction id. * - * @param address address - * @param limit transactions limit - * @param after separate transaction id + * @param address address + * @param limit transactions limit + * @param afterTxId separate transaction id * @return list of transactions * @throws IOException if something going wrong */ - public List getAddressTransactions(Address address, int limit, Id after) throws IOException, NodeException { + public List getTransactionsByAddress(Address address, int limit, Id afterTxId) throws IOException, NodeException { RequestBuilder request = get("/transactions/address/" + address.toString() + "/limit/" + limit); - if (after != null) - request.addParameter("after", after.toString()); + if (afterTxId != null) + request.addParameter("after", afterTxId.toString()); //because there is a bug in the Node api: the array of transactions is nested in another array: // [ [ {}, {}, ... ] ] @@ -540,24 +466,24 @@ public List getAddressTransactions(Address address, int limit, .readValue(asJson(request).get(0)); } - public TransactionStatus getTransactionStatus(Id id) throws IOException, NodeException { - return asType(get("/transactions/status").addParameter("id", id.toString()), - TypeRef.TRANSACTIONS_STATUSES).get(0); + public TransactionStatus getTransactionStatus(Id txId) throws IOException, NodeException { + return asType(get("/transactions/status").addParameter("id", txId.toString()), + TypeRef.TRANSACTIONS_STATUS).get(0); } - public List getTransactionsStatuses(List ids) throws IOException, NodeException { + public List getTransactionsStatus(List txIds) throws IOException, NodeException { ObjectNode jsonBody = JSON_MAPPER.createObjectNode(); ArrayNode jsonIds = jsonBody.putArray("ids"); - ids.forEach(id -> jsonIds.add(id.toString())); + txIds.forEach(id -> jsonIds.add(id.toString())); StringEntity body = new StringEntity(JSON_MAPPER.writeValueAsString(jsonBody), StandardCharsets.UTF_8); return asType(post("/transactions/status") .addHeader("Content-Type", "application/json") - .setEntity(body), TypeRef.TRANSACTIONS_STATUSES); + .setEntity(body), TypeRef.TRANSACTIONS_STATUS); } - public List getTransactionsStatuses(Id... ids) throws IOException, NodeException { - return getTransactionsStatuses(new ArrayList<>(Arrays.asList(ids))); + public List getTransactionsStatus(Id... txIds) throws IOException, NodeException { + return getTransactionsStatus(new ArrayList<>(Arrays.asList(txIds))); } public Transaction getUnconfirmedTransaction(Id txId) throws IOException, NodeException { @@ -572,6 +498,17 @@ public int getUtxSize() throws IOException, NodeException { return asJson(get("/transactions/unconfirmed/size")).get("size").asInt(); } + //=============== + // UTILS + //=============== + + public ScriptInfo compileScript(String source) throws IOException, NodeException { + return asType(post("/utils/script/compileCode") + .addHeader("Content-Type", "text/plain") + .setEntity(new StringEntity(source, StandardCharsets.UTF_8)), + TypeRef.SCRIPT_INFO); + } + //=============== // HTTP REQUESTS //=============== @@ -584,12 +521,10 @@ private RequestBuilder post(String path) { return RequestBuilder.post(uri.resolve(path)); } - //todo error codes enum private HttpResponse exec(HttpUriRequest request) throws IOException, NodeException { HttpResponse r = client.execute(request); if (r.getStatusLine().getStatusCode() != HttpStatus.SC_OK) throw mapper.readValue(r.getEntity().getContent(), NodeException.class); - //todo ...future... return r; } diff --git a/src/main/java/com/wavesplatform/wavesj/ScriptDetails.java b/src/main/java/com/wavesplatform/wavesj/ScriptDetails.java index 6a2ec75..bf82d15 100644 --- a/src/main/java/com/wavesplatform/wavesj/ScriptDetails.java +++ b/src/main/java/com/wavesplatform/wavesj/ScriptDetails.java @@ -2,23 +2,24 @@ import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; +import im.mak.waves.transactions.common.Base64String; import java.util.Objects; @SuppressWarnings("unused") public class ScriptDetails { - private final String script; + private final Base64String script; private final int complexity; @JsonCreator public ScriptDetails(@JsonProperty("script") String script, @JsonProperty("scriptComplexity") int complexity) { - this.script = Common.notNull(script, "Script"); + this.script = new Base64String(Common.notNull(script, "Script")); this.complexity = complexity; } - public String script() { + public Base64String script() { return script; } diff --git a/src/main/java/com/wavesplatform/wavesj/ScriptInfo.java b/src/main/java/com/wavesplatform/wavesj/ScriptInfo.java index c1f603c..56b67b2 100644 --- a/src/main/java/com/wavesplatform/wavesj/ScriptInfo.java +++ b/src/main/java/com/wavesplatform/wavesj/ScriptInfo.java @@ -2,7 +2,7 @@ import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; -import im.mak.waves.transactions.account.Address; +import im.mak.waves.transactions.common.Base64String; import java.util.Map; import java.util.Objects; @@ -11,33 +11,26 @@ @SuppressWarnings("unused") public class ScriptInfo { - private final Address address; - private final String script; + private final Base64String script; private final int complexity; private final int verifierComplexity; private final Map callableComplexities; private final long extraFee; @JsonCreator - public ScriptInfo(@JsonProperty("address") Address address, - @JsonProperty("script") String script, + public ScriptInfo(@JsonProperty("script") Base64String script, @JsonProperty("complexity") int complexity, @JsonProperty("verifierComplexity") int verifierComplexity, @JsonProperty("callableComplexities") Map callableComplexities, @JsonProperty("extraFee") long extraFee) { - this.address = Common.notNull(address, "Address"); - this.script = script == null ? "" : script; + this.script = script == null ? Base64String.empty() : script; this.complexity = complexity; this.verifierComplexity = verifierComplexity; this.callableComplexities = Common.notNull(callableComplexities, "CallableComplexities"); this.extraFee = extraFee; } - public Address address() { - return address; - } - - public String script() { + public Base64String script() { return script; } @@ -65,14 +58,13 @@ public boolean equals(Object o) { return complexity == that.complexity && verifierComplexity == that.verifierComplexity && extraFee == that.extraFee && - address.equals(that.address) && script.equals(that.script) && callableComplexities.equals(that.callableComplexities); } @Override public int hashCode() { - return Objects.hash(address, script, complexity, verifierComplexity, callableComplexities, extraFee); + return Objects.hash(script, complexity, verifierComplexity, callableComplexities, extraFee); } @Override @@ -81,8 +73,7 @@ public String toString() { .map(key -> key + "=" + callableComplexities.get(key)) .collect(Collectors.joining(", ", "{", "}")); return "ScriptInfo{" + - "address=" + address.toString() + - ", script='" + script + '\'' + + "script='" + script + '\'' + ", complexity=" + complexity + ", verifierComplexity=" + verifierComplexity + ", callableComplexities=" + callables + diff --git a/src/main/java/com/wavesplatform/wavesj/StateChanges.java b/src/main/java/com/wavesplatform/wavesj/StateChanges.java index ec1652f..7386bbd 100644 --- a/src/main/java/com/wavesplatform/wavesj/StateChanges.java +++ b/src/main/java/com/wavesplatform/wavesj/StateChanges.java @@ -2,8 +2,8 @@ import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; -import im.mak.waves.transactions.common.AssetId; -import im.mak.waves.transactions.common.Recipient; +import com.wavesplatform.wavesj.actions.*; +import com.wavesplatform.wavesj.actions.Error; import im.mak.waves.transactions.data.DataEntry; import java.util.*; @@ -93,330 +93,4 @@ public Error error() { return error; } - public static class ScriptTransfer { - - private final Recipient recipient; - private final long amount; - private final AssetId assetId; - - @JsonCreator - ScriptTransfer(@JsonProperty("address") Recipient recipient, - @JsonProperty("amount") long amount, - @JsonProperty("asset") AssetId assetId) { - this.recipient = Common.notNull(recipient, "Recipient"); - this.amount = amount; - this.assetId = assetId == null ? AssetId.WAVES : assetId; - } - - public Recipient recipient() { - return recipient; - } - - public long amount() { - return amount; - } - - public AssetId assetId() { - return assetId; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - ScriptTransfer that = (ScriptTransfer) o; - return amount == that.amount && - Objects.equals(recipient, that.recipient) && - Objects.equals(assetId, that.assetId); - } - - @Override - public int hashCode() { - return Objects.hash(recipient, amount, assetId); - } - - @Override - public String toString() { - return "ScriptTransfer{" + - "recipient=" + recipient + - ", amount=" + amount + - ", assetId=" + assetId + - '}'; - } - } - - public static class IssueAction { - private final String assetId; - private final String name; - private final String description; - private final long quantity; - private final int decimals; - private final boolean reissuable; - private final String compiledScript; - private final int nonce; - - @JsonCreator - IssueAction(@JsonProperty("assetId") String assetId, - @JsonProperty("name") String name, - @JsonProperty("description") String description, - @JsonProperty("quantity") long quantity, - @JsonProperty("decimals") int decimals, - @JsonProperty("isReissuable") boolean reissuable, - @JsonProperty("compiledScript") String compiledScript, - @JsonProperty("nonce") int nonce) { - this.assetId = assetId; - this.name = name; - this.description = description; - this.quantity = quantity; - this.decimals = decimals; - this.reissuable = reissuable; - this.compiledScript = compiledScript; - this.nonce = nonce; - } - - public String assetId() { - return assetId; - } - - public String name() { - return name; - } - - public String description() { - return description; - } - - public long quantity() { - return quantity; - } - - public int decimals() { - return decimals; - } - - public boolean isReissuable() { - return reissuable; - } - - public String compiledScript() { - return compiledScript; - } - - public int nonce() { - return nonce; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - IssueAction that = (IssueAction) o; - return quantity == that.quantity && - decimals == that.decimals && - reissuable == that.reissuable && - nonce == that.nonce && - Objects.equals(assetId, that.assetId) && - Objects.equals(name, that.name) && - Objects.equals(description, that.description) && - Objects.equals(compiledScript, that.compiledScript); - } - - @Override - public int hashCode() { - return Objects.hash(assetId, name, description, quantity, decimals, reissuable, compiledScript, nonce); - } - - @Override - public String toString() { - return "IssueAction{" + - "assetId='" + assetId + '\'' + - ", name='" + name + '\'' + - ", description='" + description + '\'' + - ", quantity=" + quantity + - ", decimals=" + decimals + - ", reissuable=" + reissuable + - ", compiledScript='" + compiledScript + '\'' + - ", nonce=" + nonce + - '}'; - } - } - - public static class ReissueAction { - private final String assetId; - private final long quantity; - private final boolean reissuable; - - @JsonCreator - ReissueAction(@JsonProperty("assetId") String assetId, - @JsonProperty("quantity") long quantity, - @JsonProperty("isReissuable") boolean reissuable) { - this.assetId = assetId; - this.quantity = quantity; - this.reissuable = reissuable; - } - - public String assetId() { - return assetId; - } - - public long quantity() { - return quantity; - } - - public boolean isReissuable() { - return reissuable; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - ReissueAction that = (ReissueAction) o; - return quantity == that.quantity && - reissuable == that.reissuable && - Objects.equals(assetId, that.assetId); - } - - @Override - public int hashCode() { - return Objects.hash(assetId, quantity, reissuable); - } - - @Override - public String toString() { - return "ReissueAction{" + - "assetId='" + assetId + '\'' + - ", quantity=" + quantity + - ", reissuable=" + reissuable + - '}'; - } - } - - public static class BurnAction { - private final String assetId; - private final long amount; - - @JsonCreator - BurnAction(@JsonProperty("assetId") String assetId, - @JsonProperty("amount") long amount) { - this.assetId = assetId; - this.amount = amount; - } - - public String assetId() { - return assetId; - } - - public long amount() { - return amount; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - BurnAction that = (BurnAction) o; - return amount == that.amount && - Objects.equals(assetId, that.assetId); - } - - @Override - public int hashCode() { - return Objects.hash(assetId, amount); - } - - @Override - public String toString() { - return "BurnAction{" + - "assetId='" + assetId + '\'' + - ", amount=" + amount + - '}'; - } - - } - - public static class SponsorFeeAction { - private final String assetId; - private final long minSponsoredAssetFee; - - @JsonCreator - SponsorFeeAction(@JsonProperty("assetId") String assetId, - @JsonProperty("minSponsoredAssetFee") long minSponsoredAssetFee) { - this.assetId = assetId; - this.minSponsoredAssetFee = minSponsoredAssetFee; - } - - public String assetId() { - return assetId; - } - - public long minSponsoredAssetFee() { - return minSponsoredAssetFee; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - SponsorFeeAction that = (SponsorFeeAction) o; - return minSponsoredAssetFee == that.minSponsoredAssetFee && - Objects.equals(assetId, that.assetId); - } - - @Override - public int hashCode() { - return Objects.hash(assetId, minSponsoredAssetFee); - } - - @Override - public String toString() { - return "SponsorFeeAction{" + - "assetId='" + assetId + '\'' + - ", minSponsoredAssetFee=" + minSponsoredAssetFee + - '}'; - } - - } - - public static class Error { - private final int code; - private final String text; - - @JsonCreator - public Error(@JsonProperty("code") int code, - @JsonProperty("text") String text) { - this.code = code; - this.text = text; - } - - public int code() { - return code; - } - - public String text() { - return text; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - Error error = (Error) o; - return code == error.code && - Objects.equals(text, error.text); - } - - @Override - public int hashCode() { - return Objects.hash(code, text); - } - - @Override - public String toString() { - return "Error{" + - "code=" + code + - ", text='" + text + '\'' + - '}'; - } - } } diff --git a/src/main/java/com/wavesplatform/wavesj/Validation.java b/src/main/java/com/wavesplatform/wavesj/Validation.java index 494fa4f..0b2b3fd 100644 --- a/src/main/java/com/wavesplatform/wavesj/Validation.java +++ b/src/main/java/com/wavesplatform/wavesj/Validation.java @@ -14,7 +14,6 @@ public class Validation { @JsonCreator public Validation(@JsonProperty("valid") boolean valid, @JsonProperty("validationTime") long validationTime, -//todo NODE-2197 @JsonProperty("trace") List trace, @JsonProperty("error") String error) { this.valid = valid; this.validationTime = validationTime; diff --git a/src/main/java/com/wavesplatform/wavesj/actions/BurnAction.java b/src/main/java/com/wavesplatform/wavesj/actions/BurnAction.java new file mode 100644 index 0000000..ca107de --- /dev/null +++ b/src/main/java/com/wavesplatform/wavesj/actions/BurnAction.java @@ -0,0 +1,50 @@ +package com.wavesplatform.wavesj.actions; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import im.mak.waves.transactions.common.AssetId; + +import java.util.Objects; + +public class BurnAction { + private final AssetId assetId; + private final long amount; + + @JsonCreator + BurnAction(@JsonProperty("assetId") AssetId assetId, + @JsonProperty("amount") long amount) { + this.assetId = assetId; + this.amount = amount; + } + + public AssetId assetId() { + return assetId; + } + + public long amount() { + return amount; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + BurnAction that = (BurnAction) o; + return amount == that.amount && + Objects.equals(assetId, that.assetId); + } + + @Override + public int hashCode() { + return Objects.hash(assetId, amount); + } + + @Override + public String toString() { + return "BurnAction{" + + "assetId='" + assetId + '\'' + + ", amount=" + amount + + '}'; + } + +} diff --git a/src/main/java/com/wavesplatform/wavesj/actions/Error.java b/src/main/java/com/wavesplatform/wavesj/actions/Error.java new file mode 100644 index 0000000..ea611e3 --- /dev/null +++ b/src/main/java/com/wavesplatform/wavesj/actions/Error.java @@ -0,0 +1,48 @@ +package com.wavesplatform.wavesj.actions; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.Objects; + +public class Error { + private final int code; + private final String text; + + @JsonCreator + public Error(@JsonProperty("code") int code, + @JsonProperty("text") String text) { + this.code = code; + this.text = text; + } + + public int code() { + return code; + } + + public String text() { + return text; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Error error = (Error) o; + return code == error.code && + Objects.equals(text, error.text); + } + + @Override + public int hashCode() { + return Objects.hash(code, text); + } + + @Override + public String toString() { + return "Error{" + + "code=" + code + + ", text='" + text + '\'' + + '}'; + } +} diff --git a/src/main/java/com/wavesplatform/wavesj/actions/IssueAction.java b/src/main/java/com/wavesplatform/wavesj/actions/IssueAction.java new file mode 100644 index 0000000..03caf73 --- /dev/null +++ b/src/main/java/com/wavesplatform/wavesj/actions/IssueAction.java @@ -0,0 +1,104 @@ +package com.wavesplatform.wavesj.actions; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import im.mak.waves.transactions.common.AssetId; +import im.mak.waves.transactions.common.Base64String; + +import java.util.Objects; + +public class IssueAction { + private final AssetId assetId; + private final String name; + private final String description; + private final long quantity; + private final int decimals; + private final boolean reissuable; + private final Base64String script; + private final int nonce; + + @JsonCreator + IssueAction(@JsonProperty("assetId") AssetId assetId, + @JsonProperty("name") String name, + @JsonProperty("description") String description, + @JsonProperty("quantity") long quantity, + @JsonProperty("decimals") int decimals, + @JsonProperty("isReissuable") boolean reissuable, + @JsonProperty("compiledScript") Base64String compiledScript, + @JsonProperty("nonce") int nonce) { + this.assetId = assetId; + this.name = name; + this.description = description; + this.quantity = quantity; + this.decimals = decimals; + this.reissuable = reissuable; + this.script = compiledScript; + this.nonce = nonce; + } + + public AssetId assetId() { + return assetId; + } + + public String name() { + return name; + } + + public String description() { + return description; + } + + public long quantity() { + return quantity; + } + + public int decimals() { + return decimals; + } + + public boolean isReissuable() { + return reissuable; + } + + public Base64String script() { + return script; + } + + public int nonce() { + return nonce; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + IssueAction that = (IssueAction) o; + return quantity == that.quantity && + decimals == that.decimals && + reissuable == that.reissuable && + nonce == that.nonce && + Objects.equals(assetId, that.assetId) && + Objects.equals(name, that.name) && + Objects.equals(description, that.description) && + Objects.equals(script, that.script); + } + + @Override + public int hashCode() { + return Objects.hash(assetId, name, description, quantity, decimals, reissuable, script, nonce); + } + + @Override + public String toString() { + return "IssueAction{" + + "assetId='" + assetId + '\'' + + ", name='" + name + '\'' + + ", description='" + description + '\'' + + ", quantity=" + quantity + + ", decimals=" + decimals + + ", reissuable=" + reissuable + + ", compiledScript='" + script + '\'' + + ", nonce=" + nonce + + '}'; + } +} diff --git a/src/main/java/com/wavesplatform/wavesj/actions/ReissueAction.java b/src/main/java/com/wavesplatform/wavesj/actions/ReissueAction.java new file mode 100644 index 0000000..9b90d06 --- /dev/null +++ b/src/main/java/com/wavesplatform/wavesj/actions/ReissueAction.java @@ -0,0 +1,58 @@ +package com.wavesplatform.wavesj.actions; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import im.mak.waves.transactions.common.AssetId; + +import java.util.Objects; + +public class ReissueAction { + private final AssetId assetId; + private final long quantity; + private final boolean reissuable; + + @JsonCreator + ReissueAction(@JsonProperty("assetId") AssetId assetId, + @JsonProperty("quantity") long quantity, + @JsonProperty("isReissuable") boolean reissuable) { + this.assetId = assetId; + this.quantity = quantity; + this.reissuable = reissuable; + } + + public AssetId assetId() { + return assetId; + } + + public long quantity() { + return quantity; + } + + public boolean isReissuable() { + return reissuable; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ReissueAction that = (ReissueAction) o; + return quantity == that.quantity && + reissuable == that.reissuable && + Objects.equals(assetId, that.assetId); + } + + @Override + public int hashCode() { + return Objects.hash(assetId, quantity, reissuable); + } + + @Override + public String toString() { + return "ReissueAction{" + + "assetId='" + assetId + '\'' + + ", quantity=" + quantity + + ", reissuable=" + reissuable + + '}'; + } +} diff --git a/src/main/java/com/wavesplatform/wavesj/actions/ScriptTransfer.java b/src/main/java/com/wavesplatform/wavesj/actions/ScriptTransfer.java new file mode 100644 index 0000000..9da05b0 --- /dev/null +++ b/src/main/java/com/wavesplatform/wavesj/actions/ScriptTransfer.java @@ -0,0 +1,61 @@ +package com.wavesplatform.wavesj.actions; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.wavesplatform.wavesj.Common; +import im.mak.waves.transactions.common.AssetId; +import im.mak.waves.transactions.common.Recipient; + +import java.util.Objects; + +public class ScriptTransfer { + + private final Recipient recipient; + private final long amount; + private final AssetId assetId; + + @JsonCreator + ScriptTransfer(@JsonProperty("address") Recipient recipient, + @JsonProperty("amount") long amount, + @JsonProperty("asset") AssetId assetId) { + this.recipient = Common.notNull(recipient, "Recipient"); + this.amount = amount; + this.assetId = assetId == null ? AssetId.WAVES : assetId; + } + + public Recipient recipient() { + return recipient; + } + + public long amount() { + return amount; + } + + public AssetId assetId() { + return assetId; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ScriptTransfer that = (ScriptTransfer) o; + return amount == that.amount && + Objects.equals(recipient, that.recipient) && + Objects.equals(assetId, that.assetId); + } + + @Override + public int hashCode() { + return Objects.hash(recipient, amount, assetId); + } + + @Override + public String toString() { + return "ScriptTransfer{" + + "recipient=" + recipient + + ", amount=" + amount + + ", assetId=" + assetId + + '}'; + } +} diff --git a/src/main/java/com/wavesplatform/wavesj/actions/SponsorFeeAction.java b/src/main/java/com/wavesplatform/wavesj/actions/SponsorFeeAction.java new file mode 100644 index 0000000..d8bec20 --- /dev/null +++ b/src/main/java/com/wavesplatform/wavesj/actions/SponsorFeeAction.java @@ -0,0 +1,50 @@ +package com.wavesplatform.wavesj.actions; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import im.mak.waves.transactions.common.AssetId; + +import java.util.Objects; + +public class SponsorFeeAction { + private final AssetId assetId; + private final long minSponsoredAssetFee; + + @JsonCreator + SponsorFeeAction(@JsonProperty("assetId") AssetId assetId, + @JsonProperty("minSponsoredAssetFee") long minSponsoredAssetFee) { + this.assetId = assetId; + this.minSponsoredAssetFee = minSponsoredAssetFee; + } + + public AssetId assetId() { + return assetId; + } + + public long minSponsoredAssetFee() { + return minSponsoredAssetFee; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + SponsorFeeAction that = (SponsorFeeAction) o; + return minSponsoredAssetFee == that.minSponsoredAssetFee && + Objects.equals(assetId, that.assetId); + } + + @Override + public int hashCode() { + return Objects.hash(assetId, minSponsoredAssetFee); + } + + @Override + public String toString() { + return "SponsorFeeAction{" + + "assetId='" + assetId + '\'' + + ", minSponsoredAssetFee=" + minSponsoredAssetFee + + '}'; + } + +} diff --git a/src/main/java/com/wavesplatform/wavesj/json/TypeRef.java b/src/main/java/com/wavesplatform/wavesj/json/TypeRef.java index a8ba243..f523984 100644 --- a/src/main/java/com/wavesplatform/wavesj/json/TypeRef.java +++ b/src/main/java/com/wavesplatform/wavesj/json/TypeRef.java @@ -60,7 +60,7 @@ public class TypeRef { public static final TypeReference> TRANSACTIONS = new TypeReference>() {}; - public static final TypeReference> TRANSACTIONS_STATUSES = new TypeReference>() {}; + public static final TypeReference> TRANSACTIONS_STATUS = new TypeReference>() {}; public static final TypeReference VALIDATION = new TypeReference() {}; diff --git a/src/main/java/com/wavesplatform/wavesj/json/ser/ByteStringSer.java b/src/main/java/com/wavesplatform/wavesj/json/ser/ByteStringSer.java deleted file mode 100644 index 1824915..0000000 --- a/src/main/java/com/wavesplatform/wavesj/json/ser/ByteStringSer.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.wavesplatform.wavesj.json.ser; - -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.databind.JsonSerializer; -import com.fasterxml.jackson.databind.SerializerProvider; -import com.wavesplatform.wavesj.ByteString; - -import java.io.IOException; - -public class ByteStringSer extends JsonSerializer { - public ByteStringSer() { - } - - @Override - public void serialize(ByteString byteString, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException { - jsonGenerator.writeString(byteString.getBase58String()); - } -}