java4ever is a Java 19 suite for smart-contracts development, testing & accessing DApps for Everscale blockchain network much like web3j for Ethereum and close to Truffle, Hardhat & locklift.
With java4ever you can connect your enterprise services on Java to most scalable smart-contract network. It is also suitable for any Everscale forks like GOSH or Venom.
With java4ever you get:
- Complete implementation of Everscale EVER-SDK JSON-RPC API
- All main Multisig Wallets variations support (easy deploy & calls)
- Pluggable EVER-SDK client library support (no rebuild needed, just plug-in SDK lib you like)
- Maven/Gradle support (deployed to Maven Central)
- TIP 3.2 Fungible Tokens helpers (easy deploy & calls)
- EverNodeSE Giver helpers (and you can polymorph to Multisig Givers with no code change or implement custom)
- Powerful auto-conversion between Java types & ABI expectations
- Transaction tree of a complex call can be accessed
java4ever uses blocking code (that is now a best practice due to Loom Structured Concurrency). Framework internally uses JSON-RPC connection to native EVER-SDK library binded to Java (java4ever-binding).
- Install JDK 19 or higher (link)
- Build EVER-SDK binary lib "ton_client"(.so/.dll) (or get precomiled one)
- Gradle
dependencies {
implementation 'tech.deplant.java4ever:java4ever-framework:1.6.2'
}
- Maven
<dependency>
<groupId>tech.deplant.java4ever</groupId>
<artifactId>java4ever-framework</artifactId>
<version>1.6.2</version>
</dependency>
You can add "ton_client" lib by multiple ways:
- Specify absolute path to your library in code:
var sdk1 = new SdkBuilder().create(new AbsolutePathLoader("c:/opt/sdk/ton_client.dll"));
- Specify absolute path in system env variables:
var sdk2 = new SdkBuilder().create(AbsolutePathLoader.ofSystemEnv("TON_CLIENT_LIB_PATH"));
- Place it in build current dir and specify filename in code:
var sdk3 = new SdkBuilder().create(AbsolutePathLoader.ofUserDir("ton_client.so"));
- Use
-Djava.library.path
parameter to VM and then specify only lib name:
var sdk4 = new SdkBuilder().create(new JavaLibraryPathLoader("ton_client"));
var sdkDev = new SdkBuilder()
.networkEndpoints("https://devnet-sandbox.evercloud.dev/graphql")
.create(JavaLibraryPathLoader.TON_CLIENT);
var keys = Credentials.RANDOM(sdk);
String sk = keys.secretKey();
String pk = keys.publicKey();
var seed = Seed.RANDOM(sdk);
String wordsPhrase = seed.phrase();
int wordsCount = seed.words();
var keys = Credentials.ofSeed(sdk,seed);
String sk = keys.secretKey();
String pk = keys.publicKey();
var keysOfContract = new Credentials("1fae0df1eee24bc61fbb9230bdac07503b77ceac7700651bec8250df97b6f94f",
"8b55abc280dd0b741d78961b0f8f4d8d235f30f122bc5829b6e598e71331c01c");
OwnedContract myContract = new OwnedContract(sdk,
new Address("0:273642fe57e282432bda8f16c69ea19a94b13db05986e11585a5121bcfec3fe0"),
ContractAbi.ofFile("~/MyContract.abi.json"),
keysOfContract);
Map<String, Object> functionInputs = Map.of();
Abi.FunctionHeader header = null;
myContract.runGetter("getOwner",functionInputs,header).get("value0");
Map<String, Object> functionInputs = Map.of();
Abi.FunctionHeader header = null;
myContract.callExternal("getOwner",functionInputs,header).get("value0");
Map<String, Object> functionInputs = Map.of();
Abi.FunctionHeader header = null;
String payload = myContract.encodeInternalPayload("publishCustomTask",functionInputs,header);
var addressOfMsig = new Address("0:273642fe57e282432bda8f16c69ea19a94b13db05986e11585a5121bcfec3fe0");
var keysOfMsig = new Credentials("1fae0df1eee24bc61fbb9230bdac07503b77ceac7700651bec8250df97b6f94f",
"8b55abc280dd0b741d78961b0f8f4d8d235f30f122bc5829b6e598e71331c01c");
BigInteger sendValue = EVER.amount();
Msig msig = new Msig(sdk,addressOfMsig,keysOfMsig);
msig.send(myContract.address(),sendValue,true,0,payload); // sends internal message with payload
ContractTemplate template = new ContractTemplate(ContractAbi.ofFile("~/MyContract.abi.json"),
ContractTvc.ofFile("~/MyContract.tvc"));
MsigTemplate safeTemplate = MsigTemplate.SAFE(); // msig templates are included
Credentials keys = Credentials.RANDOM(sdk);
Map<String, Object> initialData = Map.of("initDataParam1","helloWorld!"); // one static initData var
Map<String, Object> constructorInputs = Map.of(); // no inputs
OwnedContract contract = template.deploy(sdk,0,initialData,keys,constructorInputs);
MsigTemplate safeTemplate = MsigTemplate.SAFE();
Giver giver = null;
if(isEverOsNet()){
giver = new EverOSGiver(SDK);
}else{
giver = Msig.ofSafe(SDK,
new Address("0:bd7a935b78f85929bc870e466a948f5b9927ac17299f9e45213c598979b83bef"),
keysOfMsig);
}
safeTemplate.deploySingleSig(SDK,
Credentials.RANDOM(SDK),
giver,
EVER.amount());
ContractAbi abi1 = template.abi();
ContractAbi abi2 = ContractAbi.ofFile("~/MyContract.abi.json");
boolean hasSend = abi1.hasFunction("sendTransaction");
String abiType = abi2.functionOutputType("getBalance","value0").type();
ContractTvc tvc1 = template.tvc();
ContractTvc tvc2 = ContractTvc.ofFile("~/MyContract.tvc");
Credentials keys = Credentials.RANDOM(sdk);
Map<String, Object> initialData = Map.of("initDataParam1","helloWorld!"); // one static initData var
ContractTvc tvc1update = tvc1.withUpdatedInitialData(sdk,template.abi(),initialData,keys.publicKey());
java4ever-framework uses the JDK Platform Loggging (JEP 264: Platform Logging API and Service), so can be easily bridged to any logging framework.