Read complete documentation here https://docs.ic4j.com.
IC4J Java open source libraries provide a range of tools and interfaces for Java developers to interact with the Internet Computer network and build decentralized applications on top of it.
https://dfinity.org/The code is implementation of the Internet Computer Interface protocol
https://sdk.dfinity.org/docs/interface-spec/index.htmland it's using Dfinity Rust agent as an inspiration, using similar package structures and naming conventions.
https://github.com/dfinity/agent-rsIC4J Agent is available under Apache License 2.0.
Candid | Java |
---|---|
bool | Boolean |
int | BigInteger |
int8 | Byte |
int16 | Short |
int32 | Integer |
int64 | Long |
nat | BigInteger |
nat8 | Byte |
nat16 | Short |
nat32 | Integer |
nat64 | Long |
float32 | Float |
float64 | Double |
text | String |
opt | Optional |
principal | Principal |
vec | array, List |
record | Map, Class |
variant | Map, Enum |
func | Func |
service | Service |
null | Null |
Anonymous Implicit by default
Either generate Key Pair
KeyPair keyPair = KeyPairGenerator.getInstance("Ed25519").generateKeyPair();
Identity identity = BasicIdentity.fromKeyPair(keyPair);
Or use PEM file
Identity identity = BasicIdentity.fromPEMFile(path);
Get Key Pair from PEM file
Identity identity = Secp256k1Identity.fromPEMFile(path);
For Basic and Identities we are using Bouncy Castle open source libraries. To add it to your Java code you can use this code
Security.addProvider(new BouncyCastleProvider());
ReplicaTransport transport = ReplicaApacheHttpTransport.create("http://localhost:8000");
or for Android
ReplicaTransport transport = ReplicaOkHttpTransport.create("http://localhost:8000");
Create Agent object
Agent agent = new AgentBuilder().transport(transport).identity(identity).build();
To pass arguments to the Internet Computer Canister methods
List<IDLValue> args = new ArrayList<IDLValue>();
BigInteger intValue =new BigInteger("10000");
args.add(IDLValue.create(intValue));
IDLArgs idlArgs = IDLArgs.create(args);
byte[] buf = idlArgs.toBytes();
To call query method
CompletableFuture<byte[]> response = agent.queryRaw(Principal.fromString(canister_id),
Principal.fromString(canister_id), "echoInt", buf, ingressExpiryDatetime);
byte[] output = response.get();
IDLArgs outArgs = IDLArgs.fromBytes(output);
To call update method
CompletableFuture<RequestId> response = agent.updateRaw(Principal.fromString(canister_id),
Principal.fromString(canister_id), "greet", buf, ingressExpiryDatetime);
To call getState method to retrieve result of update method
RequestId requestId = response.get();
CompletableFuture<RequestStatusResponse> statusResponse = agent.requestStatusRaw(requestId,
Principal.fromString(canister_id));
CompletableFuture<byte[]> response = QueryBuilder.create(agent, Principal.fromString(canister_id), "echoInt").expireAfter(Duration.ofMinutes(3)).arg(buf).call();
byte[] output = response.get();
IDLArgs outArgs = IDLArgs.fromBytes(output);
UpdateBuilder updateBuilder = UpdateBuilder
.create(agent, Principal.fromString(canister_id), "greet").arg(buf);
CompletableFuture<byte[]> builderResponse = updateBuilder.callAndWait(com.scaleton.dfinity.agent.Waiter.create(60, 5));
byte[] output = builderResponse.get();
IDLArgs outArgs = IDLArgs.fromBytes(output);
Additionally you can also use Dynamic Proxy Class with facade Java interface that maps methods in the Internet Computer Canister. Agent values can be replaced with Agent Java object
@Agent(identity = @Identity(type = IdentityType.BASIC, pem_file = "./src/test/resources/Ed25519_identity.pem"), transport = @Transport(url = "http://localhost:8001"))
@Canister("rrkah-fqaaa-aaaaa-aaaaq-cai")
@EffectiveCanister("rrkah-fqaaa-aaaaa-aaaaq-cai")
public interface HelloProxy {
@QUERY
public String peek(@Argument(Type.TEXT)String name, @Argument(Type.INT) BigInteger value);
@QUERY
@Name("echoInt")
public BigInteger getInt(BigInteger value);
@QUERY
public CompletableFuture<Double> getFloat(Double value);
@UPDATE
@Name("greet")
@Waiter(timeout = 30)
public CompletableFuture<String> greet(@Argument(Type.TEXT)String name);
}
Then create Dynamic Proxy object and call the method
HelloProxy hello = ProxyBuilder.create().getProxy(HelloProxy.class);
String result = hello.peek(value, intValue);
Use Dynamic Proxy with POJO Java Object mapped to Candid RECORD type
POJO Java class with Candid annotations
import java.math.BigInteger;
import org.ic4j.candid.annotations.Field;
import org.ic4j.candid.annotations.Name;
import org.ic4j.candid.types.Type;
public class Pojo {
@Field(Type.BOOL)
@Name("bar")
public Boolean bar;
@Field(Type.INT)
@Name("foo")
public BigInteger foo;
}
Pojo pojoValue = new Pojo();
pojoValue.bar = new Boolean(false);
pojoValue.foo = BigInteger.valueOf(43);
Pojo pojoResult = hello.getPojo(pojoValue);
Use JacksonSerializer to serialize Jackson JsonNode or Jackson compatible Pojo class to Candid
JsonNode jsonValue;
IDLType idlType;
IDLValue idlValue = IDLValue.create(jsonValue, JacksonSerializer.create(idlType));
List<IDLValue> args = new ArrayList<IDLValue>();
args.add(idlValue);
IDLArgs idlArgs = IDLArgs.create(args);
byte[] buf = idlArgs.toBytes();
Use JacksonDeserializer to deserialize Candid to Jackson JsonNode or Jackson compatible Pojo class
JsonNode jsonResult = IDLArgs.fromBytes(buf).getArgs().get(0)
.getValue(JacksonDeserializer.create(idlValue.getIDLType()), JsonNode.class);
Use DOMSerializer to serialize DOM Node to Candid
Node domValue;
IDLValue idlValue = IDLValue.create(domValue,DOMSerializer.create());
List<IDLValue> args = new ArrayList<IDLValue>();
args.add(idlValue);
IDLArgs idlArgs = IDLArgs.create(args);
byte[] buf = idlArgs.toBytes();
Use DOMDeserializer to deserialize Candid to DOM Node
DOMDeserializer domDeserializer = DOMDeserializer.create(idlValue.getIDLType()).rootElement("http://scaleton.com/dfinity/candid","data");
Node domResult = IDLArgs.fromBytes(buf).getArgs().get(0).getValue(domDeserializer, Node.class);
Use JDBCSerializer to serialize JDBC ResultSet to Candid
ResultSet result = statement.executeQuery(sql);
IDLValue idlValue = IDLValue.create(result, JDBCSerializer.create());
List<IDLValue> args = new ArrayList<IDLValue>();
args.add(idlValue);
IDLArgs idlArgs = IDLArgs.create(args);
byte[] buf = idlArgs.toBytes();
To add IC4J Agent library to your Java project use Maven or Gradle import from Maven Central.
https://search.maven.org/artifact/org.ic4j/ic4j-agent/0.7.4/jar<dependency>
<groupId>org.ic4j</groupId>
<artifactId>ic4j-agent</artifactId>
<version>0.7.4</version>
</dependency>
<dependency>
<groupId>org.ic4j</groupId>
<artifactId>ic4j-candid</artifactId>
<version>0.7.4</version>
</dependency>
implementation 'org.ic4j:ic4j-agent:0.7.4'
implementation 'org.ic4j:ic4j-candid:0.7.4'
This this is using these open source libraries
To provide HTTP POST and GET operations.
To provide HTTP POST and GET operations for Android.
To manage CBOR payloads.
To manage Ed25519 and Secp256k1 signatures.
To manage Ed25519 and Secp256k1 signatures.
To manage BLS12381 algorithm.
You need JDK 8+ to build Dfinity Agent.