Cardano

Cardano-client-lib: Transaction with Metadata in Java — Part II

In this post, we will see how you can create and post a transaction with metadata to Cardano network in a Java application using cardano-client-lib.

Cardano-client-lib is a Java library which provides support to create, sign and submit transaction to the Cardano network. Check Part-I of this series to know more about Cardano-client-lib and the other functionalities provided by this library.

In this post we will be using Blockfrost backend Api.

Cardano Metadata as defined in this blog :-

Metadata tells the story of a transaction and there are many ways to interact with this story. Developers can take advantage of metadata by embedding details directly into a transaction, and ada users can search for specific information in the Cardano Explorer. The data can be added directly, or, for larger amounts, it is possible to create a Merkle tree of the data and put the root hash of the Merkle tree on the blockchain. Once this is done, it can be proved that the data existed at a specific point of time and that it remains permanently on the chain for future reference.

Cardano-client-lib provides simple apis to create metadata. It also provides helpers to convert metadata to JSON and vice versa.

Let’s create a payment transaction and add some metadata to it.

  1. Project and account setup

If you have not setup your project yet, please follow the step-1 to step-6 from Part I.

2. Create a metadata object

To create a metadata object, you have to start with CBORMetadata class. You can also use CBORMetadataMap and CBORMetadataList if you want to set the value as Map or List.

CBORMetadataMap productDetailsMap
        = new CBORMetadataMap()
        .put("code", "PROD-800")
        .put("slno", "SL20000039484");

CBORMetadataList tagList
        = new CBORMetadataList()
        .add("laptop")
        .add("computer");

Metadata metadata = new CBORMetadata()
        .put(new BigInteger("670001"), productDetailsMap)
        .put(new BigInteger("670002"), tagList);

In the above example, we are first creating a Map which contains code and serial no. We are then creating a List to hold multiple tags.

Finally, we are creating a Metadata object and setting productDetailsMap and tagList with metadata labels 670001, 670002 respectively.

You can create a multi-level nested structure, but the top-level object should be Metadata.

3. Create a transaction request object

As explained in the Part I, let’s create a transaction with PaymentTransaction class.

PaymentTransaction paymentTransaction =
          PaymentTransaction.builder()
                .sender(sender)
                .receiver(receiver)
                .amount(BigInteger.valueOf(20000000))
                .unit(LOVELACE)
                .build();

4. Calculate TTL (Time-to-Live)

Use BlockService to get the latest slot number and then calculate ttl.

long ttl = blockService.getLastestBlock().getValue().getSlot() + 1000;
TransactionDetailsParams detailsParams =
        TransactionDetailsParams.builder()
                .ttl(ttl)
                .build();

5. Calculate Fee

Use FeeCalculatorService to calculate fee. Make sure to send all three parameters “PaymentTransaction, TransactionDetailsParams and Metadata” to FeeCalculatorService.

Set the calculated fee in PaymentTransaction request.

BigInteger fee 
         = feeCalculationService.calculateFee(paymentTransaction,                   detailsParams, metadata);

paymentTransaction.setFee(fee);

6. Submit Transaction with Metadata

Now submit the transaction request to the network using TransactionHelperService.

Note: Make sure to pass “metadata” parameter in the transfer call.

Result result
          = transactionHelperService.transfer(paymentTransaction,    detailsParams, metadata);
if(result.isSuccessful())
    System.out.println("Transaction Id: " + result.getValue());
else
    System.out.println("Transaction failed: " + result);

7. Check transaction details in Cardano Explorer

Now go to Cardano Testnet Explorer and check the transaction details.

It may take some time for the transaction to be mined.

Now you can see the metadata in Cardano explorer.

Metadata can be added to a Native token transfer in similar ways.

Metadata Helper Class

There are few helper classes which can be used to convert a JSON (No Schema) object to metadata format and vice-versa.

But the Json payload has to follow the format mentioned in this wiki.

JsonNoSchemaToMetadataConverter
MetadataToJsonNoSchemaConverter

Check also:

Resources

Full Source code

public void transferWithMetadata() throws ApiException, AddressExcepion, CborSerializationException {
        BackendService backendService =
                BackendFactory.getBlockfrostBackendService(Constants.BLOCKFROST_TESTNET_URL, Constant.BF_PROJECT_KEY);
        FeeCalculationService feeCalculationService = backendService.getFeeCalculationService();
        TransactionHelperService transactionHelperService = backendService.getTransactionHelperService();
        BlockService blockService = backendService.getBlockService();

        String senderMnemonic = "kit color frog trick speak employ suit sort bomb goddess jewel primary spoil fade person useless measure manage warfare reduce few scrub beyond era";
        Account sender = new Account(Networks.testnet(), senderMnemonic);

        String receiver = "addr_test1qqwpl7h3g84mhr36wpetk904p7fchx2vst0z696lxk8ujsjyruqwmlsm344gfux3nsj6njyzj3ppvrqtt36cp9xyydzqzumz82";

        CBORMetadataMap productDetailsMap
                = new CBORMetadataMap()
                .put("code", "PROD-800")
                .put("slno", "SL20000039484");

        CBORMetadataList tagList
                = new CBORMetadataList()
                .add("laptop")
                .add("computer");

        Metadata metadata = new CBORMetadata()
                .put(new BigInteger("670001"), productDetailsMap)
                .put(new BigInteger("670002"), tagList);

        PaymentTransaction paymentTransaction =
                PaymentTransaction.builder()
                        .sender(sender)
                        .receiver(receiver)
                        .amount(BigInteger.valueOf(20000000))
                        .unit(LOVELACE)
                        .build();

        long ttl = blockService.getLastestBlock().getValue().getSlot() + 1000;
        TransactionDetailsParams detailsParams =
                TransactionDetailsParams.builder()
                        .ttl(ttl)
                        .build();

        BigInteger fee
                = feeCalculationService.calculateFee(paymentTransaction, detailsParams, metadata);
        paymentTransaction.setFee(fee);

        Result<String> result
                = transactionHelperService.transfer(paymentTransaction, detailsParams, metadata);

        if(result.isSuccessful())
            System.out.println("Transaction Id: " + result.getValue());
        else
            System.out.println("Transaction failed: " + result);

    }

Published on Java Code Geeks with permission by Satya Ranjan, partner at our JCG program. See the original article here: Cardano-client-lib: Transaction with Metadata in Java — Part II

Opinions expressed by Java Code Geeks contributors are their own.

Satya

Satya is a solution architect and developer with more than 20 years of experience who has worked in a wide variety of organizations from product development, banking to IT consultancy. He is also a blockchain enthusiast.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Back to top button