Installation and usage of the platform
Constructing smart contracts with Java/Kotlin Contract SDK¶
This section describes Java/Kotlin Сontract SDK Toolkit – a toolkit for development, testing and deploying Docker smart contracts in Waves Enterprise public blockchain networks. Use the toolkit to fast take off with the Waves Enterprise ecosystem using any of the JVM programming languages, since smart contracts are deployed in a Docker container. You can create a smart contract using any of the JVM languages, such as Java.
Smart contracts are often deployed into different environments and networks. For example, you can scaffold local environment based on a sandbox node and deploy contracts to this network for test use-cases.
All the transaction handling is done via methods of a single class marked with @ContractHandler
annotation. The methods which implement handling logic are marked with @ContractInit
(for CreateContractTx) and @ContractAction
(for CallContractTx).
To deploy your contract, issue 103 и 104 transactions.
Requirements¶
Before you start developing your smart contracts, make sure that the following software is installed:
Docker
JDK 8 or higher
To deploy your smart contracts, the following software should be installed:
Docker
JRE 8 or higher
Dependencies¶
<dependency>
<groupId>com.wavesenterprise</groupId>
<artifactId>we-contract-sdk-grpc</artifactId>
<version>1.0.0</version>
</dependency>
dependencies {
implementation("com.wavesenterprise:we-contract-sdk-grpc:1.0.0")
}
Quickstart¶
Take the following steps to create your new contract:
Note
All examples below are taken from the Samples .
1. Create contract handler¶
@ContractHandler
public class SampleContractHandler {
private final ContractState contractState;
private final ContractTransaction tx;
private final Mapping<List<MySampleContractDto>> mapping;
public SampleContractHandler(ContractState contractState, ContractTransaction tx) {
this.contractState = contractState;
mapping = contractState.getMapping(
new TypeReference<List<MySampleContractDto>>() {
}, "SOME_PREFIX");
this.tx = tx;
}
}
2. Add @ContractInit and @ContractAction methods to handle contract transactions¶
public class SampleContractHandler {
// ...
@ContractInit
public void createContract(String initialParam) {
contractState.put("INITIAL_PARAM", initialParam);
}
@ContractAction
public void doSomeAction(String dtoId) {
contractState.put("INITIAL_PARAM", Instant.ofEpochMilli(tx.getTimestamp().getUtcTimestampMillis()));
if (mapping.has(dtoId)) {
throw new IllegalArgumentException("Already has " + dtoId + " on state");
}
mapping.put(dtoId,
Arrays.asList(
new MySampleContractDto("john", 18),
new MySampleContractDto("harry", 54)
));
}
}
3. Dispatch the contract with the specified contract handler and settings¶
public class MainDispatch {
public static void main(String[] args) {
ContractDispatcher contractDispatcher = GrpcJacksonContractDispatcherBuilder.builder()
.contractHandlerType(SampleContractHandler.class)
.objectMapper(getObjectMapper())
.build();
contractDispatcher.dispatch();
}
private static ObjectMapper getObjectMapper() {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new JavaTimeModule());
return objectMapper;
}
}
4. Create Docker image¶
FROM openjdk:8-alpine
MAINTAINER Waves Enterprise <>
ENV JAVA_MEM="-Xmx256M"
ENV JAVA_OPTS=""
ADD build/libs/*-all.jar app.jar
RUN chmod +x app.jar
RUN eval $SET_ENV_CMD
CMD ["/bin/sh", "-c", "eval ${SET_ENV_CMD} ; java $JAVA_MEM $JAVA_OPTS -jar app.jar"]
5. Push the image to the Docker repository used by WE node mining contract transactions¶
Publish the image to the registry used by the Waves Enterprise blockchain node. For convenience, you can use the build_and_push_to_docker.sh bash script which builds your smart contract image, pushes it to the specified registry and displays image
and imageHash
.
./build_and_push_to_docker.sh my.registry.com/contracts/my-awesome-docker-contract:1.0.0
6. Sign and broadcast transactions for creating and invoking the published contract¶
You will need image
and imageHash
of the published contract to create it.
CreateContractTx example:
{
"image": "my.registry.com/contracts/my-awesome-docker-contract:1.0.0",
"fee": 0,
"imageHash": "d17f6c1823176aa56e0e8184f9c45bc852ee9b076b06a586e40c23abde4d7dfa",
"type": 103,
"params": [
{
"type": "string",
"value": "createContract",
"key": "action"
},
{
"type": "string",
"value": "initialValue",
"key": "createContract"
}
],
"version": 2,
"sender": "3M3ybNZvLG7o7rnM4F7ViRPnDTfVggdfmRX",
"feeAssetId": null,
"contractName": "myAwesomeContract"
}
To call contract you will need contractId = CreateContractTx.id
.
CallContractTx example:
{
"contractId": "7sVc6ybnqZr523xWK5Sg7xADsX597qga8iQNAS9f1D3c",
"fee": 0,
"type": 104,
"params": [
{
"type": "string",
"value": "doSomeAction",
"key": "action"
},
{
"type": "string",
"value": "someValue",
"key": "createContract"
}
],
"version": 2,
"sender": "3M3ybNZvLG7o7rnM4F7ViRPnDTfVggdfmRX",
"feeAssetId": null,
"contractVersion": 1
}
Notes on usage¶
Usage with Java 11 and higher¶
The library has been tested against Java 8, 11 and 17. When using with Java 11 and higher, additional Java options should be specified for the io.grpc to enable optimizations:
--add-opens java.base/jdk.internal.misc=ALL-UNNAMED --add-opens=java.base/java.nio=ALL-UNNAMED -Dio.netty.tryReflectionSetAccessible=true
A complete example can be found in Dockerfile for Java 17.