Web3J
In this walkthrough, we're going to create a simple Java contract and compile it. We're then going to run the compiled contract through the Web3J wrapping tool which will give us a Java class we can import into a standard Java application. Finally, we'll build a simple Java application and import the wrapped Java contract and have it interact with the blockchain.
We’ll be using IntelliJ and the Aion4J plugin.
Prerequisities
This project assumes that you’re already familiar with IntelliJ and how to create Aion contracts using the Aion4j plugin. To find out more on how to do this, check out the IntelliJ section. You will also need to following software installed.
- Java 10 or above.
- IntelliJ
Create the Contract
The contract we’re going to create is a simple getter-setter application. The user can either view the value of a String
variable or change that variable.
- Open IntelliJ and create a new Maven project using the latest AVM archetype.
- Set the
GroupId
field toaionexample
and theArtifactId
field togettersetter
. - Click Next through the rest project creation window and click Finish.
- Click Run Initialize in the pop-up at the bottom right, or right-click within your project and select Aion Virtual Machine > Run Intialize.
- To keep things simple we won’t be using tests in this project. So within the
src
folder of your new project, delete thetest
folder. - Within the
src/main/java/aionexample
folder, right-click onHelloAvm
, select Refactor → Rename, and renameHelloAvm
toGetterSetter
. Depending on your IntelliJ setup, IntelliJ might rename all the instances of
HelloAvm
within the class toGetterSetter
. If it doesn’t however, do this manually. Make sure to set thecontract.main.class
field within yourpom.xml
file to<contract.main.class>aionexample.GetterSetter</contract.main.class>
You should now have the basis of your Java contract project. If you want, you can delete the
greet()
andsayHello()
functions within yourGetterSetter
class since we won’t be using them. But there’s no harm in leaving them in there. You can also copy and paste the contract below:package aionexample; import avm.Blockchain; import org.aion.avm.tooling.abi.Callable; public class GetterSetter { private static String myStr = "Hello AVM"; @Callable public static String getString() { return myStr; } @Callable public static void setString(String newStr) { myStr = newStr; } }
Compile your contract by right-clicking on the
gettersetter
folder in the navigation panel and selecting Aion Virtual Machine → Embedded → Deploy.You should now have a
gettersetter-1.0-SNAPSHOT.abi
andgettersetter-1.0-SNAPSHOT.jar
files within your projectstarget
folder. Copy them to somewhere handy like your desktop. These are the files we’re going to wrap within the Web3J packages.You can close this project now: File → Close Project.
Wrap the Contract
For a standard Java application to interact with your Java contract, you need to wrap the contract within the Web3J wrapper. While the process is the same for any Java contract, the output is different. A wrapper for one Java contract will not work for any other Java contract.
Download the Aion Web3J package from GitHub:
git clone https://github.com/web3j/aion
Move into the new folder:
cd web3j-aion-master
Generate the binary distribution using Gradlew:
./gradlew distZip > Starting a Gradle Daemon (subsequent builds will be faster) > > ... > > BUILD SUCCESSFUL in 5s > 9 actionable tasks: 9 executed
You might see a warning about
Deprecated Gradle features
. You can safely ignore this for now. It will be fixed in a future release.Move into the distributions folder:
cd codegen/build/distributions
Extract the
web3j-aion-0.1.0-SNAPSHOT.zip
file:unzip web3j-aion-0.1.0-SNAPSHOT.zip > Archive: web3j-aion-0.1.0-SNAPSHOT.zip > creating: web3j-aion-0.1.0-SNAPSHOT/ > creating: web3j-aion-0.1.0-SNAPSHOT/lib/ > > ... > > creating: web3j-aion-0.1.0-SNAPSHOT/bin/ > inflating: web3j-aion-0.1.0-SNAPSHOT/bin/web3j-aion.bat > inflating: web3j-aion-0.1.0-SNAPSHOT/bin/web3j-aion
Move into
bin
folder:cd web3j-aion-0.1.0-SNAPSHOT/bin
Web3J now needs the
jar
andabi
files we made in IntelliJ. Copy your.jar
and.abi
files into this folder:cp ~/Desktop/gettersetter-1.0-SNAPSHOT.abi ~/Desktop/gettersetter-1.0-SNAPSHOT.jar .
Generate your Aion contract wrapper:
./web3j-aion -a gettersetter-1.0-SNAPSHOT.abi -b gettersetter-1.0-SNAPSHOT.jar -o ~/Desktop -p gettersetter > Generating gettersetter.GetterSetter ... > > ... > > File written to /Users/aion/Desktop
The
-o ~/Desktop
directory in this command is the location where you wrapper will be saved. To keep thing simple we’ve told the script to save it to the desktop. You can now find yourGetterSetter.java
wrapper in the~/Desktop/gettersetter/
folder.For future reference, the following arguments are available for the
web3j-aion
script:Flag Required Description -a
,--abiFile
true
ABI file in AVM format with a contract definition. -b
,--binFile
false
BIN or JAR file with the contract compiled code in order to generate deploy methods. -o
,--outputDir
true
Destination base directory. -p
,--package
true
Base package name. -t
,--targetVm
false
Target Aion virtual machine (AVM by default). We also need to create a
shadowJar
file. Back in the root of the Web3J repository run:./gradlew shadowJar > <===========--> 90% EXECUTING [2s] > > ... > > BUILD SUCCESSFUL in 9s > 7 actionable tasks: 3 executed, 4 up-to-date
Copy this new
.jar
into thegettersetter
folder on your desktop:
cp avm/build/libs/web3j-aion-avm-0.1.0-SNAPSHOT-all.jar ~/Desktop/gettersetter
We now have the two files we need to include within our Java project. Next up is creating the Java project to house everything.
Set Up your Application and Import the Wrapper
In this step, we’re going to create an incredibly simple Java application that prints out the myStr
variable within our contract. This application will also deploy our contract for us.
- Create a new Java project in IntelliJ called
GetTheString
. - Within your projects root folder create a new directory called
lib
. - Within this new
lib
folder, paste theweb3j-aion-avm-0.1.0-SNAPSHOT-all.jar
file we created and saved into~/Desktop/gettersetter
in the previous step. - Copy the
GetterSetter.java
file from within~/Desktop/gettersetter
into thesrc
folder. Within the
src
folder, create a new Java class calledGetTheString
. Your project folder should look something like this now:GetTheString/ ├── GetTheString.iml ├── lib │ └── web3j-aion-avm-0.1.0-SNAPSHOT-all.jar └── src ├── GetTheString.java └── GetterSetter.java
Lastly, we need to tell IntelliJ that we want to use the lib
folder as this project library location.
- Go to File > Project Structure.
- Select Libraries from the left panel.
- Click the
+
icon and select Java. - In the window that opens, go into the
lib
folder within yourGetTheString
project folder. - Select the
web3j-aion-avm-0.1.0-SNAPSHOT-all.jar
file and click Open. - Click OK on the confirmation window. Then click Apply and OK within the Project Structure window.
Now we have the framework to start interacting with the blockchain. Next up, we’re going to deploy our contract and interact with it using the Aion test network.
Write, Deploy, and Interact
First up we need to tell our Java application to deploy our contract to the Aion test network. To do this you’ll need an Aion node on the Amity testnet, and an account with sufficient balance to deploy and call a contract. You can use Nodesmith to connect to a node, and the Aion Testnet Faucet to get some free test tokens.
Write
Now that you’ve got those two details, we’re ready to start writing our Java application.
- Open the
GetTheString
file. At the very top of the file add the following lines to import the packages we need:
import org.web3j.aion.VirtualMachine; import org.web3j.aion.crypto.Ed25519KeyPair; import org.web3j.aion.protocol.Aion; import org.web3j.aion.tx.AionTransactionManager; import org.web3j.aion.tx.gas.AionGasProvider; import org.web3j.protocol.core.methods.response.TransactionReceipt; import org.web3j.protocol.http.HttpService; import org.web3j.tx.TransactionManager;
Within the
public class GetTheString
class definiton add these two lines, filling in your information:private static String NODE_ENDPOINT = "YOUR_NODE_URL"; private static String PRIVATE_KEY = "YOUR_PRIVATE_KEY";
Create an
Aion
object by adding this line:private static final Aion aion = Aion.build(new HttpService(NODE_ENDPOINT));
This sets up the endpoint to talk to an Aion network.
Create
TranasactionManager
object calledmanager
:private static final TransactionManager manager = new AionTransactionManager(aion, new Ed25519KeyPair(PRIVATE_KEY), VirtualMachine.AVM);
This sets up the account for signing and sending the transactions later.
Create a
main()
class that will house all our further code:public static void main(String [] args) throws Exception { }
Deploy
We can now get to deploying your contract. Since we’ve already set up the scaffolding in the rest of this class, all we need to do is call one function.
Call the
.deploy
function within yourGetterSetter
object:final GetterSetter getterSetterContract = GetterSetter.deploy(aion, manager, AionGasProvider.INSTANCE).send();
You can also request the transaction receipt and contract address once your Java contract has been deployed:
System.out.println("Tx Hash:"+ counterContract.getTransactionReceipt()); System.out.println("Contract Address: " + counterContract.getContractAddress());
Note: Remember to check the status of the of the transaction as well. A contract address will be returned even the deployment fails.
You should now be able to run your application. Click Run > Run… from the title bar.
You may get an error about JDK7 types
. You can safely ignore this. It can take up to 30 seconds to deploy your contract. Once it’s deployed you should be able to see the transaction hash and contract address:
WARNING: Unable to load JDK7 types (annotations, java.nio.file.Path): no Java7 support added
Tx Hash:Optional[TransactionReceipt{transactionHash='0x82ed1b830d5420f4d0ed591f1' ...
Contract Address: 0xa0a6468149676f ...
Interact
So now that we’re able to deploy our contract, we should be able to interact with it. There are two functions within our contract getString
and setString
. Let’s start by calling the getString
method and checking the response.
Create a variable called
result
of typeString
, and have it set to the response of thegetString
method:String firstResult = getterSetterContract.call_getString().send();
Note: We are using
call_getString
instead ofsend_getString
here is becausegetString()
is a constant function, we are only getting information from the blockchain and not change any state.Print out the
result
variable:System.out.println("Current string is: " + firstResult);
Run your project again to see the results.
> WARNING: Unable to load JDK7 types (annotations, java.nio.file.Path): no Java7 support added > > ... > > Current string is: Hello AVM
Next, let’s try setting the string. Since we’re going to change the state of the blockchain this action will use funds from your account, so make sure there is enough AION
in there to facilitate the request.
Create a variable called
transactionReceipt
of typeTransactionReceipt
, and have it set to the response of thesetString
method. Add the string you want to set themyStr
variable to as an argument:TransactionReceipt transactionReceipt = getterSetterContract.send_setString("Hello World!").send();
Print out whether or not the transaction was successful and the string was set:
System.out.println("String Set: " + transactionReceipt.isStatusOK());
Call the
getString
method again using the same code from earlier:String secondResult = getterSetterContract.call_getString().send(); System.out.println("Current string is: " + secondResult);
Run your project again to see the results.
> WARNING: Unable to load JDK7 types (annotations, java.nio.file.Path): no Java7 support added > > ... > > Current string is: Hello AVM > String Set: true > Current string is: Hello World!
And there you have it! You’ve successfully written, deployed, and interacted with a Java contract on the Aion test network using Web3J! Check out the official Web3J documentation for more information on what you can do with the framework.