A simple method for extracting the essential history of a Daml ledger from the transaction tree

We often want to focus on a certain aspect of the ledger history to demonstrate and/or test a workflow.

The existing tools are not optimized for this:

  • Navigator displays a static view of the active contract set (and, if selected, the archived contracts), not the ledger history.
  • Daml Studio can display the transaction view of the ledger, which contains all the information we need, but it can only be used for inspecting the result of a certain Daml Script and this view is not very easy to understand for large ledgers.
  • The raw information we need is contained in the transaction tree, but again, many people will have a hard time to understand it by inspection (see the last cell of this notebook).

I’m using Google Colab, which can combine Python code with Bash scripts. I’m connecting it to a local runtime so that I can use the app against Sandbox running locally and invoke grpcurl from within the notebook. (This is not necessary, you can also use Colab connected to a hosted runtime. This makes sense if your ledger is running in the cloud, e.g. on Daml Hub. In this case you will run grpcurl separately.)

Prerequisits:

  • grpcurl
  • JSONPath for Python for extracting information from the transaction tree json. You need to install it locally if you want to run Colab connected to a local runtime, or install it for the notebook it you run Colab connected to a hosted runtime.
  • Python Pandas for displaying the end result as a nice table. For the installation options see the point above.

Steps:

  1. We extract the transaction tree from a running ledger using grpcurl.
  2. The extract is not a valid json, but contains json objects printed one after the other. So we have to convert it to a list.
  3. From the transformed extract, we get the json representing the list of ledger transactions.
  4. Using JSONPath, we extract the relevant pieces of information from the json and assemble a list of all the contract creation and consuming exercise events, containing all relevant contract info.
  5. We create custom function(s) for extracting the relevant information from the contract payload.
  6. Filter, transform and sort the event list as needed for our demo or test.
  7. Display the result as a nice table using Pandas.

Our example below shows how this method can be applied to the Skeleton template, displaying a list of events when Alice and Bob give the Asset to each other back and forth. The events contained in the same offset are events composed atomically in a transaction. Remember, the consequences of exercising the consuming “Give” choice are 1) the archival of an existing Asset contract, and 2) the creation of a new Asset contract with the new owner, composed atomically.

For tracking the history of a certain unique business object in more complex scenarios, we can filter the event list for the template name and contract key of the contract instances representing the states of the business object, displaying the changes of any relevant field(s) of its payload.

3 Likes