Multisig Native assets Service - JAVA SDK¶
maven dependency¶
Replace
${latest.version}with latest version from maven central (https://central.sonatype.dev/artifact/solutions.iog/native-assets-client_2.13/0.3.1/versions)
<dependency>
<groupId>solutions.iog</groupId>
<artifactId>native-assets-client_2.13</artifactId>
<version>${latest.version}</version>
</dependency>
Create the api¶
Make sure, that you have registered an account in PSG Self Serve UI, purchased a package and generated API Token
Replace
clientIdwith your PSG Self serve accountReplace
tokenwith your PSG Self Serve generated API tokenBy default, client will connect to psg.iog.services, which is operating on Cardano mainnet. There are additional methods on the builder that allows you to specify
hostto connect to different environments (like one operating on preprod Cardano network).
// Creates client that connects to MAINNET by default.
public NativeAssetsMultisigApi nativeAssetsMultisigApi() {
return NativeAssetsBuilder
.create(apiKey, clientId)
.buildMultisig();
}
Create the Policy which allows to burn/mint the holders of secret keys associated with provided public keys¶
Replace
policyNamewith arbitrary policy nameReplace
hexPubKeypublic key in hex format. The policy allows only the holder of associatedsecret keyto the provided public key to mint/burnReplace
beforeSlot- optional - if specified it defines theendof time window in which the policy allows to burn/mintReplace
afterSlot- optional - if specified it defines thestartof time window in which the policy allows to burn/mint
public CompletionStage<Policy> createPolicyWithPublicKeys() throws CborSerializationException {
String policyName = "policy";
String hexPubKey1 = "ac3c4";
String hexPubKey1 = "bd4d5";
Optional<Integer> beforeSlot = Optional.of(8231864);
Optional<Integer> afterSlot = Optional.of(8200864);
VerificationKey pubKey = VerificationKey.create(HexUtil.decodeHexString(hexPubKey));
return nativeAssetsMultisigApi.createPolicy(policyName, beforeSlot, afterSlot, Arrays.asList(pubKey))
.thenApply(response -> {
if (response.hasProblem())
return response.getPolicy();
else {
throw new RuntimeException(response.getProblem().getMsg());
}
});
}
Create the Policy with secret keys¶
Replace
policyNamewith arbitrary policy nameReplace
hexSecKeythe secret key in hex format. The policy allows only the holder of this key to mint/burnReplace
beforeSlot- optional - if specified it defines theendof time window in which the policy allows to burn/mintReplace
afterSlot- optional - if specified it defines thestartof time window in which the policy allows to burn/mint
public CompletionStage<Policy> createPolicyWithSecKeys() throws CborSerializationException {
String policyName = "policy";
String hexSecKey = "ac3c4";
Optional<Integer> beforeSlot = Optional.of(8231864);
Optional<Integer> afterSlot = Optional.of(8200864);
SecretKey secKey = SecretKey.create(HexUtil.decodeHexString(hexSecKey));
return nativeAssetsMultisigApi.createPolicyUsingPrivateKeys(policyName, beforeSlot, afterSlot, Arrays.asList(secKey))
.thenApply(response -> {
if (response.hasProblem())
return response.getPolicy();
else {
throw new RuntimeException(response.getProblem().getMsg());
}
});
}
Get the Policy by policy id¶
Replace
policyIdwith Id of Policy
public CompletionStage<Policy> getPolicyById() {
String policyId = "policyId";
return nativeAssetsMultisigApi.getPolicyById(policyId)
.thenApply(response -> {
if (response.hasProblem())
return response.getPolicy();
else {
throw new RuntimeException(response.getProblem().getMsg());
}
});
}
Get the Policy by policy name¶
Replace
policyByNamewith policy name
public CompletionStage<Policy> getPolicyByName() {
String policyByName = "PolicyByName";
return nativeAssetsMultisigApi.getPolicyByName(policyByName)
.thenApply(response -> {
if (response.hasProblem())
return response.getPolicy();
else {
throw new RuntimeException(response.getProblem().getMsg());
}
});
}
List all created policies¶
public CompletionStage<List<Policy>> listPolices() {
return nativeAssetsMultisigApi.listPolices()
.thenApply(response -> {
if (response.hasProblem())
return JavaConverters.seqAsJavaList(response.policies());
else {
throw new RuntimeException(response.getProblem().getMsg());
}
});
}
Create mint transaction for NFT¶
Replace
assetNamewith the name of NFTReplace
policyIdthe Id of PolicyReplace
paymentAddressthe address from which the mint fee will be deductedReplace
mintTargetAddress- the address to which the asset will be minted
public CompletionStage<String> createMintTransaction() {
String assetName = "assetName";
String policyId = "policyId";
String paymentAddress = "ad23424a23424";
String mintTargetAddress = "ad23424a23424";
Nft nativeNft = Nft$.MODULE$.defaultInstance()
.withName(assetName)
.withAssetName(assetName);
AddressedNft addressedNft = AddressedNft$.MODULE$.defaultInstance()
.withNft(nativeNft)
.withAddress(mintTargetAddress);
return nativeAssetsMultisigApi.createMintTransaction(policyId, paymentAddress, addressedNft)
.thenApply(response -> {
if (response.hasProblem())
return response.getTx().tx();
else {
throw new RuntimeException(response.getProblem().getMsg());
}
});
}
Create mint transaction native asset¶
Replace
assetNamewith the name of Native AssetReplace
policyIdthe Id of PolicyReplace
paymentAddressthe address from which the mint fee will be deductedReplace
mintTargetAddress- the address to which the asset will be mintedReplace
amount- with amount of Native Asset you want to mintReplace
json- in the form of Java Map. This json/map should correspond with (https://developers.cardano.org/docs/transaction-metadata/)
public CompletionStage<String> createMintTransaction() {
String assetName = "assetName";
String policyId = "policyId";
Long amount = 1000l;
String paymentAddress = "ad23424a23424";
String mintTargetAddress = "bbcd2124389096753424a23424";
Map json = new HashMap();
Struct struct = com.google.protobuf.struct.Struct.of(
CollectionConverters.MapHasAsScala(json).
asScala()
.toMap($less$colon$less$.MODULE$.refl())
);
NativeAssetId nativeAssetId = NativeAssetId$.MODULE$
.defaultInstance()
.withName(assetName)
.withPolicyId(policyId);
NativeAsset nativeAsset = NativeAsset$.MODULE$
.defaultInstance()
.withAmount(amount)
.withId(nativeAssetId);
AddressedNativeAsset addressedNativeAsset = AddressedNativeAsset$.MODULE$
.defaultInstance()
.withAddress(mintTargetAddress)
.withNativeAsset(nativeAsset);
AddressedNativeAssets assets = AddressedNativeAssets$.MODULE$
.defaultInstance()
.withPaymentAddress(paymentAddress)
.withMetadata(struct)
.withNativeAssets(JavaConverters.asScala(Arrays.asList(addressedNativeAsset)).toSeq());
return nativeAssetsMultisigApi.createMintTransaction(assets)
.thenApply(response -> {
if (response.hasProblem())
return response.getTx().tx();
else {
throw new RuntimeException(response.getProblem().getMsg());
}
});
}
Create transfer transaction¶
Replace
assetNamewith the name of Native AssetReplace
policyIdthe Id of PolicyReplace
fromAddresswith the address from which the asset will be transferred outReplace
toAddresswith the address to which the asset will be transferred inReplace
amountwith amount of Native Asset you want to transferr
public CompletionStage<String> createTransferTransaction() {
String policyId = "policyId";
String assetName = "assetName";
String fromAddress = "ad23424a23424";
String toAddress = "cc4a23424";
Long amount = 10l;
return nativeAssetsMultisigApi.createTransferTransaction(policyId, assetName, fromAddress, toAddress, amount)
.thenApply(response -> {
if (response.hasProblem())
return response.getTx().tx();
else {
throw new RuntimeException(response.getProblem().getMsg());
}
});
}
Create burn transaction¶
Replace
policyIdthe Id of PolicyReplace
assetNamewith the name of Native AssetReplace
targetAddress- the address from which the asset will be burntReplace
amount- with amount of Native Asset you want to burn
public CompletionStage<String> createBurnTransaction() {
String policyId = "policyId";
String assetName = "assetName";
String targetAddress = "ad23424a23424";
Long amount = 10l;
return nativeAssetsMultisigApi.createBurnTransaction(policyId, assetName, targetAddress, amount)
.thenApply(response -> {
if (response.hasProblem())
return response.getTx().tx();
else {
throw new RuntimeException(response.getProblem().getMsg());
}
});
}
Add witness with secret key¶
Replace
txIdwith the Id TransactionReplace
secretKeyHexwith the private key in Hex format, which will be used to sign the transaction with
public CompletionStage<String> addWitnessWithSecretKey() throws CborSerializationException {
String txId = "ab2343245";
String secretKeyHex = "cccc232c";
SecretKey privateKey = SecretKey.create(HexUtil.decodeHexString(secretKeyHex));
return nativeAssetsMultisigApi.addWitness(txId, privateKey)
.thenApply(response -> {
if (response.hasProblem())
return "signature added";
else {
throw new RuntimeException(response.getProblem().getMsg());
}
});
}
Add witness with public key and signature¶
Replace
txIdwith the Id TransactionReplace
publicKeyHexwith the public key in Hex format, which is used for verification of signature providedReplace
signatureHexwith signature in Hex format. This signature must be created with secret key that corresponds to public key above
public CompletionStage<String> addWitnessWithPublicKey() throws CborSerializationException {
String txId = "ab2343245";
String publicKeyHex = "cccc232c";
String signatureHex = "ccadcc2c";
VerificationKey publicKey = VerificationKey.create(HexUtil.decodeHexString(publicKeyHex));
return nativeAssetsMultisigApi.addWitness(txId, publicKey, HexUtil.decodeHexString(signatureHex))
.thenApply(response -> {
if (response.hasProblem())
return "signature added";
else {
throw new RuntimeException(response.getProblem().getMsg());
}
});
}
Get Transaction by ID¶
Replace
txIdwith the Id Transaction
public CompletionStage<Long> getTx() throws CborSerializationException {
String txId = "ab2343245";
return nativeAssetsMultisigApi.getTx(txId)
.thenApply(response -> {
if (response.hasProblem())
return response.getTx().confirmations();
else {
throw new RuntimeException(response.getProblem().getMsg());
}
});
}
List all Transactions¶
public CompletionStage<List<String>> listTxs() {
return nativeAssetsMultisigApi.listTxs()
.thenApply(response -> {
if (response.hasProblem())
return JavaConverters.asJava(response.transactions()).stream().map(ur -> ur.txId()).collect(Collectors.toList());
else {
throw new RuntimeException(response.getProblem().getMsg());
}
});
}
List all Transactions belonging to policy with ID¶
Replace
policyIdwith the Policy id
public CompletionStage<List<String>> listTxsByPolicyId() {
String policyId = "ab2343245";
return nativeAssetsMultisigApi.listTxs(policyId)
.thenApply(response -> {
if (response.hasProblem())
return JavaConverters.asJava(response.transactions()).stream().map(ur -> ur.txId()).collect(Collectors.toList());
else {
throw new RuntimeException(response.getProblem().getMsg());
}
});
}
List all witnesses¶
Replace
txIdwith the Id Transaction
public CompletionStage<List<String>> listWitnesses() {
String txId = "ab2343245";
return nativeAssetsMultisigApi.listWitnesses(txId)
.thenApply(response -> {
if (response.hasProblem())
return JavaConverters.asJava(response.verKeyHashes());
else {
throw new RuntimeException(response.getProblem().getMsg());
}
});
}
Submit the transaction to the blockchain¶
Replace
txIdwith the Id TransactionReplace
depthwith the Integer - specifies the number of network Confirmations required to treat the transaction as Confirmed
public CompletionStage<String> sendTransaction() {
String txId = "ab2343245";
Integer depth = 4;
CompletableFuture<String> completableFuture = new CompletableFuture();
nativeAssetsMultisigApi.sendTransaction(txId, depth, streamObserver(completableFuture, (r -> r.getSendTx().toString())));
return completableFuture;
}
The Observer¶
The example of observer. This might be used in the example above. It gets the events about the transaction sent details.
private <V> StreamObserver<V> streamObserver(CompletableFuture<String> completableFuture,
Function<V, String> converter) {
return new StreamObserver<V>() {
List<String> buffer = new ArrayList();
@Override
public void onNext(V res) {
buffer.add(converter.apply(res));
}
@Override
public void onError(Throwable throwable) {
buffer.add(throwable.toString());
}
@Override
public void onCompleted() {
String res = buffer
.stream()
.collect(Collectors.joining("\n"));
completableFuture.complete(res);
}
};
}
Generate cardano enterprise address¶
Replace
hexPubKeywith the public key in Hex format, for which the Cardano Address will be generated
public Address generateAddress() throws CborSerializationException {
String hexPubKey = "ac3c4";
return nativeAssetsMultisigApi.generateAddress(VerificationKey.create(HexUtil.decodeHexString(hexPubKey)), Networks.preprod());
}
Generate public key¶
Replace
hexSecKeywith the secret key in Hex format, for which the Public Key will be generated
public VerificationKey generateVerKey() throws CborSerializationException {
String hexSecKey = "ac3c4";
return nativeAssetsMultisigApi.generateVerificationKey(SecretKey.create(HexUtil.decodeHexString(hexSecKey)));
}
Generate key pair (secret key and associated public key)¶
public Keys generateKeys() throws CborSerializationException {
return nativeAssetsMultisigApi.generateKeys();
}