aiManj is a lightweight, highly modular, reactive, type safe Java and Android library for working with Smart Contracts and integrating with clients (nodes) on the Matrix network:
This allows you to work with the Matrix blockchain, without the additional overhead of having to write your own integration code for the platform.
The Java and the Blockchain talk provides an overview of blockchain, Matrix and aiManj.
- Complete implementation of Matrix's JSON-RPC client API over HTTP and IPC
- Matrix wallet support
- Auto-generation of Java smart contract wrappers to create, deploy, transact with and call smart contracts from native Java code (Solidity and Truffle definition formats supported)
- Reactive-functional API for working with filters
- Matrix Name Service (ENS) support
- Support for Parity's Personal, and Gman's Personal client APIs
- Support for Infura, so you don't have to run an Matrix client yourself
- Comprehensive integration tests demonstrating a number of the above scenarios
- Command line tools
- Android compatible
- Support for JP Morgan's Quorum via aiManj-quorum
It has five runtime dependencies:
- RxJava for its reactive-functional API
- OKHttp for HTTP connections
- Jackson Core for fast JSON serialisation/deserialisation
- Bouncy Castle (Spongy Castle on Android) for crypto
- Jnr-unixsocket for *nix IPC (not available on Android)
It also uses JavaPoet for generating smart contract wrappers.
Full project documentation is available at docs.aiManj.io.
You can help fund the development of aiManj by donating to the following wallet addresses:
Commercial support and training is available from blk.io.
A aiManj sample project is available that demonstrates a number of core features of Matrix with aiManj, including:
- Connecting to a node on the Matrix network
- Loading an Matrix wallet file
- Sending Man from one address to another
- Deploying a smart contract to the network
- Reading a value from the deployed smart contract
- Updating a value in the deployed smart contract
- Viewing an event logged by the smart contract
Typically your application should depend on release versions of aiManj, but you may also use snapshot dependencies for early access to features and fixes, refer to the Snapshot Dependencies section.
Java 8:
<dependency>
<groupId>org.aimanj</groupId>
<artifactId>core</artifactId>
<version>4.2.0</version>
</dependency>
Android:
<dependency>
<groupId>org.aimanj</groupId>
<artifactId>core</artifactId>
<version>4.2.0-android</version>
</dependency>
Java 8:
compile ('org.aimanj:core:4.2.0')
Android:
compile ('org.aimanj:core:4.2.0-android')
There are also gradle and maven plugins to help you generate aiManj Java wrappers for your Solidity smart contracts, thus allowing you to integrate such activities into your project lifecycle.
Take a look at the project homepage for the aiManj-gradle-plugin and aiManj-maven-plugin for details on how to use these plugins.
Start up an Matrix client if you don't already have one running, such as Gman:
$ gman --rpcapi personal,db,man,net,aiMan --rpc --testnet
Or Parity:
$ parity --chain testnet
Or use Infura, which provides free clients running in the cloud:
AiManj aiMan = AiManj.build(new HttpService("https://ropsten.infura.io/your-token"));
For further information refer to Using Infura with aiManj
Instructions on obtaining Man to transact on the network can be found in the testnet section of the docs.
To send synchronous requests:
AiManj aiMan = AiManj.build(new HttpService()); // defaults to http://localhost:8545/
AiManClientVersion aiManClientVersion = aiMan.aiManClientVersion().send();
String clientVersion = aiManClientVersion.getAiManClientVersion();
To send asynchronous requests using a CompletableFuture (Future on Android):
AiManj aiMan = AiManj.build(new HttpService()); // defaults to http://localhost:8545/
AiManClientVersion aiManClientVersion = aiMan.aiManClientVersion().sendAsync().get();
String clientVersion = aiManClientVersion.getAiManClientVersion();
To use an RxJava Flowable:
AiManj aiMan = AiManj.build(new HttpService()); // defaults to http://localhost:8545/
aiMan.aiManClientVersion().flowable().subscribe(x -> {
String clientVersion = x.getAiManClientVersion();
...
});
aiManj also supports fast inter-process communication (IPC) via file sockets to clients running on the same host as aiManj. To connect simply use the relevant IpcService implementation instead of HttpService when you create your service:
// OS X/Linux/Unix:
AiManj aiMan = AiManj.build(new UnixIpcService("/path/to/socketfile"));
...
// Windows
AiManj aiMan = AiManj.build(new WindowsIpcService("/path/to/namedpipefile"));
...
Note: IPC is not currently available on aiManj-android.
aiManj can auto-generate smart contract wrapper code to deploy and interact with smart contracts without leaving the JVM.
To generate the wrapper code, compile your smart contract:
$ solc <contract>.sol --bin --abi --optimize -o <output-dir>/
Then generate the wrapper code using aiManj's Command line tools:
aiManj solidity generate -b /path/to/<smart-contract>.bin -a /path/to/<smart-contract>.abi -o /path/to/src/main/java -p com.your.organisation.name
Now you can create and deploy your smart contract:
AiManj aiMan = AiManj.build(new HttpService()); // defaults to http://localhost:8545/
Credentials credentials = WalletUtils.loadCredentials("password", "/path/to/walletfile");
YourSmartContract contract = YourSmartContract.deploy(
<aiManj>, <credentials>,
GAS_PRICE, GAS_LIMIT,
<param1>, ..., <paramN>).send(); // constructor params
Alternatively, if you use Truffle, you can make use of its .json output files:
# Inside your Truffle project
$ truffle compile
$ truffle deploy
Then generate the wrapper code using aiManj's Command line tools:
$ cd /path/to/your/aiManj/java/project
$ aiManj truffle generate /path/to/<truffle-smart-contract-output>.json -o /path/to/src/main/java -p com.your.organisation.name
Whether using Truffle or solc directly, either way you get a ready-to-use Java wrapper for your contract.
So, to use an existing contract:
YourSmartContract contract = YourSmartContract.load(
"0x<address>|<ensName>", <aiManj>, <credentials>, GAS_PRICE, GAS_LIMIT);
To transact with a smart contract:
TransactionReceipt transactionReceipt = contract.someMethod(
<param1>,
...).send();
To call a smart contract:
Type result = contract.someMethod(<param1>, ...).send();
To fine control your gas price:
contract.setGasProvider(new DefaultGasProvider() {
...
});
For more information refer to Smart Contracts.
aiManj functional-reactive nature makes it really simple to setup observers that notify subscribers of events taking place on the blockchain.
To receive all new blocks as they are added to the blockchain:
Subscription subscription = aiManj.blockFlowable(false).subscribe(block -> {
...
});
To receive all new transactions as they are added to the blockchain:
Subscription subscription = aiManj.transactionFlowable().subscribe(tx -> {
...
});
To receive all pending transactions as they are submitted to the network (i.e. before they have been grouped into a block together):
Subscription subscription = aiManj.pendingTransactionFlowable().subscribe(tx -> {
...
});
Or, if you'd rather replay all blocks to the most current, and be notified of new subsequent blocks being created:
There are a number of other transaction and block replay Flowables described in the docs.
Topic filters are also supported:
ManFilter filter = new ManFilter(DefaultBlockParameterName.EARLIEST,
DefaultBlockParameterName.LATEST, <contract-address>)
.addSingleTopic(...)|.addOptionalTopics(..., ...)|...;
aiManj.manLogFlowable(filter).subscribe(log -> {
...
});
Subscriptions should always be cancelled when no longer required:
subscription.unsubscribe();
Note: filters are not supported on Infura.
For further information refer to Filters and Events and the AiManjRx interface.
aiManj provides support for both working with Matrix wallet files (recommended) and Matrix client admin commands for sending transactions.
To send Man to another party using your Matrix wallet file:
AiManj aiMan = AiManj.build(new HttpService()); // defaults to http://localhost:8545/
Credentials credentials = WalletUtils.loadCredentials("password", "/path/to/walletfile");
TransactionReceipt transactionReceipt = Transfer.sendFunds(
aiMan, credentials, "0x<address>|<ensName>",
BigDecimal.valueOf(1.0), Convert.Unit.Man)
.send();
Or if you wish to create your own custom transaction:
AiManj aiMan = AiManj.build(new HttpService()); // defaults to http://localhost:8545/
Credentials credentials = WalletUtils.loadCredentials("password", "/path/to/walletfile");
// get the next available nonce
ManGetTransactionCount manGetTransactionCount = aiManj.manGetTransactionCount(
address, DefaultBlockParameterName.LATEST).sendAsync().get();
BigInteger nonce = manGetTransactionCount.getTransactionCount();
// create our transaction
RawTransaction rawTransaction = RawTransaction.createManTransaction(
nonce, <gas price>, <gas limit>, <toAddress>, <value>);
// sign & send our transaction
byte[] signedMessage = TransactionEncoder.signMessage(rawTransaction, credentials);
String hexValue = Hex.toHexString(signedMessage);
ManSendTransaction manSendTransaction = aiManj.manSendRawTransaction(hexValue).send();
// ...
Although it's far simpler using aiManj's Transfer for transacting with Man.
Using an Matrix client's admin commands (make sure you have your wallet in the client's keystore):
Admin aiManj = Admin.build(new HttpService()); // defaults to http://localhost:8545/
PersonalUnlockAccount personalUnlockAccount = aiManj.personalUnlockAccount("0x000...", "a password").sendAsync().get();
if (personalUnlockAccount.accountUnlocked()) {
// send a transaction
}
If you want to make use of Parity's Personal or Trace, or Gman's Personal client APIs, you can use the org.aimanj:parity and org.aimanj:gman modules respectively.
A aiManj fat jar is distributed with each release providing command line tools. The command line tools allow you to use some of the functionality of aiManj from the command line:
- Wallet creation
- Wallet password management
- Transfer of funds from one wallet to another
- Generate Solidity smart contract function wrappers
Please refer to the documentation for further information.
In the Java 8 build:
- aiManj provides type safe access to all responses. Optional or null responses are wrapped in Java 8's Optional type.
- Asynchronous requests are wrapped in a Java 8 CompletableFutures. aiManj provides a wrapper around all async requests to ensure that any exceptions during execution will be captured rather then silently discarded. This is due to the lack of support in CompletableFutures for checked exceptions, which are often rethrown as unchecked exception causing problems with detection. See the Async.run() and its associated test for details.
In both the Java 8 and Android builds:
- Quantity payload types are returned as BigIntegers. For simple results, you can obtain the quantity as a String via Response.getResult().
- It's also possible to include the raw JSON payload in responses via the includeRawResponse parameter, present in the HttpService and IpcService classes.
- Gman
- Parity
You can run the integration test class CoreIT to verify clients.
For a .NET implementation, check out Nmatrix.
For a pure Java implementation of the Matrix client, check out MatrixJ and Matrix Harmony.
Please submit a pull request if you wish to include your project on the list:
- ERC-20 RESTful Service
- Man Wallet by @vikulin
- man-contract-api by @adridadou
- Matrix Paper Wallet by @matthiaszimmermann
- Trust Matrix Wallet
- Presto Matrix
- Kundera-Matrix data importer and sync utility by @impetus-opensource
- Matrix JDBC Connector by @impetus-opensource
- Matrix Tool for secure offline key management.
- Matrix Java EE JCA Resource Adapter provides integration of Matrix within Java EE 6+.
- Apache Camel Matrix Component by @bibryam.
- Manlinker for UE4 - interact with Matrix blockchain from Unreal Engine 4.
Please submit a pull request if you wish to include your company on the list:
aiManj includes integration tests for running against a live Matrix client. If you do not have a client running, you can exclude their execution as per the below instructions.
To run a full build (excluding integration tests):
$ ./gradlew check
To run the integration tests:
$ ./gradlew -Pintegration-tests=true :integration-tests:test
Snapshot versions of aiManj follow the <major>.<minor>.<build>-SNAPSHOT
convention, for example: 4.2.0-SNAPSHOT.
https://oss.sonatype.org/content/repositories/snapshots
Please refer to the maven or gradle documentation for further detail.
Sample gradle configuration:
repositories {
maven {
url "https://oss.sonatype.org/content/repositories/snapshots"
}
}
Sample maven configuration:
<repositories>
<repository>
<id>sonatype-snasphots</id>
<name>Sonatype snapshots repo</name>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</repository>
</repositories>
- The Nmatrix project for the inspiration
- Othera for the great things they are building on the platform
- Finhaus guys for putting me onto Nmatrix
- bitcoinj for the reference Elliptic Curve crypto implementation
- Everyone involved in the Matrix project and its surrounding ecosystem
- And of course the users of the library, who've provided valuable input & feedback