/WavesJ

Java library for interacting with the Waves blockchain.

Primary LanguageJavaMIT LicenseMIT

Maven Central

WavesJ

A Java library for interacting with the Waves blockchain.

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.

Requirements:
  • JDK 1.8 or above
Maven:
<dependency>
    <groupId>com.wavesplatform</groupId>
    <artifactId>wavesj</artifactId>
    <version>1.3.0</version>
</dependency>
Gradle:
compile group: 'com.wavesplatform', name: 'wavesj', version: '1.3.0'
SBT:
libraryDependencies += "com.wavesplatform" % "wavesj" % "1.3.0"

This library's page at Maven Central

Getting started

Create an account from a private key ('T' for testnet) from random seed phrase:

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:

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));

Send some money to a buddy:

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!

Base64String script = node
    .compile("{-# CONTENT_TYPE EXPRESSION #-} sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey)")
    .script();
node.broadcast(new SetScriptTransaction(publicKey, script).addProof(privateKey));

Reading transaction info

Same transaction from REST API

Id ethTxId = new Id("CWuFY42te67sLmc5gwt4NxwHmFjVfJdHkKuLyshTwEct");
EthereumTransactionInfo ethInvokeTxInfo = node.getTransactionInfo(ethTxId, EthereumTransactionInfo.class);

EthereumTransaction ethInvokeTx = ethInvokeTxInfo.tx();
EthereumTransaction.Invocation payload = (EthereumTransaction.Invocation) ethInvokeTx.payload();

System.out.println("is ethereum invoke transaction: " + ethInvokeTxInfo.isInvokeTransaction());

System.out.println("type: " + ethInvokeTx.type());
System.out.println("id: " + ethInvokeTx.id().encoded());
System.out.println("fee: " + ethInvokeTx.fee().value());
System.out.println("feeAssetId: " + ethInvokeTx.fee().assetId().encoded());
System.out.println("timestamp: " + ethInvokeTx.timestamp());
System.out.println("version: " + ethInvokeTx.version());
System.out.println("chainId: " + ethInvokeTx.chainId());
System.out.println("bytes: " + ethInvokeTxInfo.getBytes());
System.out.println("sender: " + ethInvokeTx.sender().address().encoded());
System.out.println("senderPublicKey: " + ethInvokeTx.sender().encoded());
System.out.println("height: " + ethInvokeTxInfo.height());
System.out.println("applicationStatus: " + ethInvokeTxInfo.applicationStatus());
System.out.println("payload dApp: " + payload.dApp().encoded());
System.out.println("payload call function: " + payload.function().name());
List<Arg> args = payload.function().args();
System.out.println("payload call function arguments type: " + args.get(0).type());
System.out.println("payload call function arguments value: " + ((StringArg) args.get(0)).value());
DataEntry dataEntry = ethInvokeTxInfo.getStateChanges().data().get(0);
System.out.println("state changes data key: " + dataEntry.key());
System.out.println("state changes data type: " + dataEntry.type().name());
System.out.println("state changes data value: " + ((StringEntry) dataEntry).value());

Broadcasting transactions

Creating accounts (see Getting started for more info about account creation)

PrivateKey alice = createAccountWithBalance(10_00000000);
PrivateKey bob = createAccountWithBalance(10_00000000);

Broadcasting exchange transaction

AssetId assetId = node.waitForTransaction(node.broadcast(
        IssueTransaction.builder("Asset", 1000, 2).getSignedWith(alice)).id(),
        IssueTransactionInfo.class).tx().assetId();

Amount amount = Amount.of(1);
Amount price = Amount.of(100, assetId);
long matcherFee = 300000;
Order buy = Order.builder(OrderType.BUY, amount, price, alice.publicKey()).getSignedWith(alice);
Order sell = Order.builder(OrderType.SELL, amount, price, alice.publicKey()).getSignedWith(bob);

ExchangeTransaction tx = ExchangeTransaction
        .builder(buy, sell, amount.value(), price.value(), matcherFee, matcherFee).getSignedWith(alice);
node.waitForTransaction(node.broadcast(tx).id());

TransactionInfo commonInfo = node.getTransactionInfo(tx.id());
ExchangeTransactionInfo txInfo = node.getTransactionInfo(tx.id(), ExchangeTransactionInfo.class);

Working with dApp

Creating accounts (see Getting started for more info about account creation)

PrivateKey alice = createAccountWithBalance(10_00000000);
PrivateKey bob = createAccountWithBalance(10_00000000);

Broadcasting issue transaction

AssetId assetId = node.waitForTransaction(node.broadcast(
        IssueTransaction.builder("Asset", 1000, 2).getSignedWith(alice)).id(),
        IssueTransactionInfo.class).tx().assetId();

Compiling and broadcasting RIDE script

Base64String script = node.compileScript(
        "{-# STDLIB_VERSION 5 #-}\n" +
        "{-# CONTENT_TYPE DAPP #-}\n" +
        "{-# SCRIPT_TYPE ACCOUNT #-}\n" +
        "@Callable(inv)\n" +
        "func call(bv: ByteVector, b: Boolean, int: Int, str: String, list: List[Int]) = {\n" +
        "  let asset = Issue(\"Asset\", \"\", 1, 0, true)\n" +
        "  let assetId = asset.calculateAssetId()\n" +
        "  let lease = Lease(inv.caller, 7)\n" +
        "  let leaseId = lease.calculateLeaseId()\n" +
        "  [\n" +
        "    BinaryEntry(\"bin\", assetId),\n" +
        "    BooleanEntry(\"bool\", true),\n" +
        "    IntegerEntry(\"int\", 100500),\n" +
        "    StringEntry(\"assetId\", assetId.toBase58String()),\n" +
        "    StringEntry(\"leaseId\", leaseId.toBase58String()),\n" +
        "    StringEntry(\"del\", \"\"),\n" +
        "    DeleteEntry(\"del\"),\n" +
        "    asset,\n" +
        "    SponsorFee(assetId, 1),\n" +
        "    Reissue(assetId, 4, false),\n" +
        "    Burn(assetId, 3),\n" +
        "    ScriptTransfer(inv.caller, 2, assetId),\n" +
        "    lease,\n" +
        "    LeaseCancel(lease.calculateLeaseId())\n" +
        "  ]\n" +
        "}").script();
node.waitForTransaction(node.broadcast(
        SetScriptTransaction.builder(script).getSignedWith(bob)).id());

Calling dApp

InvokeScriptTransaction tx = InvokeScriptTransaction
        .builder(bob.address(), Function.as("call",
                BinaryArg.as(alice.address().bytes()),
                BooleanArg.as(true),
                IntegerArg.as(100500),
                StringArg.as(alice.address().toString()),
                ListArg.as(IntegerArg.as(100500))
        )).payments(
                Amount.of(1, assetId),
                Amount.of(2, assetId),
                Amount.of(3, assetId),
                Amount.of(4, assetId),
                Amount.of(5, assetId),
                Amount.of(6, assetId),
                Amount.of(7, assetId),
                Amount.of(8, assetId),
                Amount.of(9, assetId),
                Amount.of(10, assetId)
        ).extraFee(1_00000000)
        .getSignedWith(alice);
node.waitForTransaction(node.broadcast(tx).id());

Receiving invoke script transaction info

TransactionInfo commonInfo = node.getTransactionInfo(tx.id());
InvokeScriptTransactionInfo txInfo = node.getTransactionInfo(tx.id(), InvokeScriptTransactionInfo.class);