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
clientId
with your PSG Self serve accountReplace
token
with 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
host
to 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
policyName
with arbitrary policy nameReplace
hexPubKey
public key in hex format. The policy allows only the holder of associatedsecret key
to the provided public key to mint/burnReplace
beforeSlot
- optional - if specified it defines theend
of time window in which the policy allows to burn/mintReplace
afterSlot
- optional - if specified it defines thestart
of 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
policyName
with arbitrary policy nameReplace
hexSecKey
the secret key in hex format. The policy allows only the holder of this key to mint/burnReplace
beforeSlot
- optional - if specified it defines theend
of time window in which the policy allows to burn/mintReplace
afterSlot
- optional - if specified it defines thestart
of 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
policyId
with 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
policyByName
with 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
assetName
with the name of NFTReplace
policyId
the Id of PolicyReplace
paymentAddress
the 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
assetName
with the name of Native AssetReplace
policyId
the Id of PolicyReplace
paymentAddress
the 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
assetName
with the name of Native AssetReplace
policyId
the Id of PolicyReplace
fromAddress
with the address from which the asset will be transferred outReplace
toAddress
with the address to which the asset will be transferred inReplace
amount
with 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
policyId
the Id of PolicyReplace
assetName
with 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
txId
with the Id TransactionReplace
secretKeyHex
with 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
txId
with the Id TransactionReplace
publicKeyHex
with the public key in Hex format, which is used for verification of signature providedReplace
signatureHex
with 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
txId
with 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
policyId
with 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
txId
with 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
txId
with the Id TransactionReplace
depth
with 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
hexPubKey
with 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
hexSecKey
with 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();
}