> ## Documentation Index
> Fetch the complete documentation index at: https://docs.digitalasset.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Transaction History Parsing

> As an app user, how to inspect the ledger to parse transaction history.

This page explains how to inspect the ledger to parse transaction history for a given party, in
order to identify executed mints, burns, and transfers.

<a id="cip-112-tx-parsing" />

## CIP-112 transaction parsing guidelines

CIP-112 introduces a dedicated Daml `EventLog` interface to record transaction events. This
interface exposes a `nonconsuming` choice which is exercised within a transaction to record
relevant events.

A ledger client can query events on this interface to obtain an ordered series of events from the
participant node. You can refer to the relevant pieces of the [Canton Network documentation](https://docs.canton.network/appdev/deep-dives/token-standard#parsing-the-history-v2)
for additional details.

<Note>
  The `EventLog` interface is not implemented in Registry Daml models prior to the **0.14** release. These
  guidelines unfortunately do not apply to these earlier versions.

  As long as you support Registry **0.13** and older, you will need to use the below CIP-56
  transaction parsing guidelines.
</Note>

<Accordion title="Example ledger query">
  Here is an example query, using the JSON API endpoint for paginated updates
  `v2/updates/get-updates-page`.

  ```
  {
      "beginOffsetExclusive": 0,
      "endOffsetInclusive": 3703,
      "maxPageSize": 100,
      "updateFormat": {
          "includeTransactions": {
              "transactionShape": "TRANSACTION_SHAPE_LEDGER_EFFECTS",
              "eventFormat": {
                  "filtersByParty": {
                      "registrar-dLhm20fxdH8_dL17::12205dd5bd685449653161d47d2a7cb01c25d5b0a02dab5c79cafc8dafd811c79895": {
                          "cumulative": [
                              {
                                  "identifierFilter": {
                                      "InterfaceFilter": {
                                          "value": {
                                              "interfaceId": "#splice-api-token-transfer-events-v2:Splice.Api.Token.TransferEventsV2:EventLog"
                                          }
                                      }
                                  }
                              }
                          ]
                      }
                  },
                  "verbose": false
              }
          }
      }
  }
  ```

  You will then need to filter the output events for exercises of the `EventLog_HoldingsChange`
  choice and look at the content of the `choiceArgument` object.
</Accordion>

<Accordion title="Transfer parsing example">
  For a transfer from `issuer` to `holder`, the `choiceArgument` object of the `ExercisedEvent`
  includes the relevant information:

  * instrument admin
  * relevant account
  * transfer leg (`SenderSide` if the relevant account is the sender, `ReceiverSide` otherwise)

  ```json theme={null}
  "admin": "registrar-S92p6Rp513u3mvsg::12205dd5bd685449653161d47d2a7cb01c25d5b0a02dab5c79cafc8dafd811c79895",
  "account": {
      "owner": "issuer-S92p6Rp513u3mvsg::12205dd5bd685449653161d47d2a7cb01c25d5b0a02dab5c79cafc8dafd811c79895",
      "provider": null,
      "id": ""
  },
  "inputHoldingCids": [
      "00bb9c3dc01c7cebc82d29ffcb677a2b50bddbb9a096cde58000ec97ec0eb9abc8ca121220b950163ec54c0b03cd1e1ed19e20d64862aa9dd2cacf02d8884423dd4c266fe8"
  ],
  "transferLegSides": [
      {
          "transferLegId": "",
          "side": "SenderSide",
          "otherside": {
              "owner": "holder-S92p6Rp513u3mvsg::12205dd5bd685449653161d47d2a7cb01c25d5b0a02dab5c79cafc8dafd811c79895",
              "provider": null,
              "id": "holder-account-1"
          },
          "amount": "100.0000000000",
          "instrumentId": "INST",
          "meta": {
              "values": {
                  "splice.lfdecentralizedtrust.org/reason": "reference"
              }
          }
      }
  ],
  ...
  ```

  Note that both the `SenderSide` and `ReceiverSide` are logged separately. The same format is used
  for allocations (where there could be multiple `TransferLegs` for a given event).
</Accordion>

<Accordion title="Mint parsing example">
  Mints only have a `ReceiverSide` leg.

  ```json theme={null}
  "admin": "registrar-dLhm20fxdH8_dL17::12205dd5bd685449653161d47d2a7cb01c25d5b0a02dab5c79cafc8dafd811c79895",
  "account": {
      "owner": "issuer-dLhm20fxdH8_dL17::12205dd5bd685449653161d47d2a7cb01c25d5b0a02dab5c79cafc8dafd811c79895",
      "provider": null,
      "id": ""
  },
  "transferLegSides": [
      {
          "transferLegId": "mint",
          "side": "ReceiverSide",
          "otherside": {
              "owner": null,
              "provider": null,
              "id": "cip-112/mint"
          },
          "amount": "100.0000000000",
          "instrumentId": "burn-mint-request-dLhm20fxdH8_dL17",
          "meta": {
              "values": {}
          }
      }
  ],
  ```

  Likewise, burns only log a `SenderSide` leg.
</Accordion>

<a id="ledger-pruning" />

## A note on ledger pruning

In order to keep a Canton participant node healthy, it should be pruned at regular intervals.
This means that the ledger will generally not retain all of the transaction history.

The methodology described in this guide only applies to data that has not been pruned from the
ledger. If the user needs to retain transaction data for a period of time longer than their pruning
window, they should move the data outside of the Canton participant node before it gets pruned.

For reference, the Registry operator node uses a retention period of 30 days for pruning.

## Other transaction parsing options

If you have been integrating with Registry prior to version 0.14, you are probably using one of the
below options for transaction history parsing.

### CIP-56 transaction parsing guidelines

<Tip>
  CIP-56 transaction parsing works for all workflows across all currently supported Registry versions
  (0.12, 0.13, 0.14). We recommend migrating to CIP-112 transaction parsing only once versions 0.12
  and 0.13 are no longer supported.
</Tip>

The first iteration of the Token Standard introduced a set of transaction history
parsing guidelines. These are documented in the relevant pieces of the
[Canton Network documentation](https://docs.canton.network/appdev/deep-dives/token-standard#parsing-the-history-v1).

#### Mint and Burn workflows

Mint and burn workflows are not part of the Token Standard and use Daml templates rather than
interfaces. Choice exercises resulting in a successful mint or burn are tagged with the appropriate
metadata as part of their choice result.

For instance, the choice result for a successful burn includes

```
"meta": {
    "values": {
        "splice.lfdecentralizedtrust.org/burned": "100.0",
        "splice.lfdecentralizedtrust.org/reason": "",
        "splice.lfdecentralizedtrust.org/tx-kind": "burn"
    }
}
```

### Transaction parsing based on ExecutedTransfer, ExecutedMint, ExecutedBurn

<Warning>
  **DEPRECATED**

  This transaction parsing method is no longer supported from version 0.14 of the Registry. Please
  refer to the [migration guide](#migration-guide-executed-transfers) below to understand how to
  migrate off these contracts.
</Warning>

Versions of Registry prior to 0.14 create an active `Executed*` contract upon a successful transfer, mint,
or burn. Similar contracts are created when a request is rejected by a counterparty.

| Transaction type | Executed contract  |
| ---------------- | ------------------ |
| Transfer         | `ExecutedTransfer` |
| Mint             | `ExecutedMint`     |
| Burn             | `ExecutedBurn`     |

These can be retrieved via an ACS query in order to reconstruct transaction history. They should
however be regularly archived by the corresponding `registrar` in order to prevent excessive ACS
growth.

Batch archival can be performed in order to minimize the cost of this operation.

#### Disable the creation of Executed\* contracts

Parties with the `registrar` role can disable the creation of `Executed*` contracts on versions of
the app prior to `0.14`.

This is controlled by a flag in the `RegistrarService` template, which can be set by calling

```haskell theme={null}
    choice RegistrarService_Set : ContractId RegistrarService
      -- ^ Sets the `enableResultContracts` flag.
      -- This choice is introduced as of version `0.5.0` of this package.
      -- As of version `0.9.0` of this package the value of the `enableResultContracts` flag is ignored.
      with
        enableResultContracts : Optional Bool
          -- ^ New value for the flag.
```

### Template-based transaction parsing

A final transaction parsing option is to rely on concrete template choice exercises, such as
exercises of

```haskell theme={null}
    nonconsuming choice TransferRule_DirectTransfer : TransferRule_DirectTransfer_Result
      -- ^ Used for executing a direct transfer.
      -- This choice was added as of version `0.5.0` of this package.
```

to identify a transfer.

While this mechanism is arguably simpler than the CIP-56 guidelines, it is not very robust: template
choice exercises are subject to change and are not guaranteed to be stable across releases.

<a id="migration-guide-executed-transfers" />

## Migrating from Executed contracts

Up until version `0.13` of the Registry App, an `ExecutedTransfer` contract is created by default
on each transfer transaction. Similar contracts are created for mint and burn operations.

While these contracts are very convenient to use, they are not sustainable as they lead to unbounded
ACS growth unless they get regularly archived by the instrument admin.

Thus, starting with version `0.14`, these "execution" contracts are no longer created.
Tokenizers that rely on these contracts to determine whether a transfer, mint, or burn has occurred
must switch to transaction history parsing based on ledger events before adopting the `0.14`
release.

The following sub-section outlines a migration path, which

* relies on Executed contracts for transactions using the `0.13` DARS or older
* uses [CIP-112 transaction parsing](#cip-112-tx-parsing) for transactions using the `0.14` DARS or
  newer

<Steps>
  <Step title="Determine a storage solution for transaction history">
    It is not the role of the Canton participant node to store your entire transaction history,
    especially if your data retention requirements span a period of months or years.

    You should determine a durable store for the history that you need to retain, such as a
    Postgres DB. See the [note on ledger pruning](#ledger-pruning) for why this data should be
    stored outside the Canton participant node.
  </Step>

  <Step title="Populate storage from Executed* contracts">
    Query the active `ExecutedMint`, `ExecutedBurn`, and `ExecutedTransfer` contracts for the
    parties and instruments whose history you need to retain.

    Copy the relevant contract payloads and transaction identifiers (`updateId`, `recordTime`) into
    the durable store.

    This needs to be an ongoing process, as transactions using Registry versions 0.12 and 0.13 keep
    creating these contracts.

    Archive the ingested `Executed*` contracts to reduce the burden on the participant node. This
    step is optional, but recommended.
    Archival of these contracts can be done in a batched fashion in order to minimize transaction
    cost.
  </Step>

  <Step title="Introduce ledger events-based transaction parsing based on exercises of the `EventLog_HoldingsChange` interface">
    Introduce an additional process that updates the stored transaction history based on the parsing
    guidelines introduced with CIP-112.
  </Step>

  <Step title="Install the 0.14 DARS">
    You can now install the `0.14` DARS. Transactions using these models will be caught only by the
    ingestion process introduced in step 3.
  </Step>

  <Step title="Unvet Registry DARS prior to 0.14">
    Once you (or the Registry operator) no longer support versions of the Registry App prior to
    `0.14`, you can safely unvet the corresponding DARS, so that these can no longer be used for
    transactions involving your assets.
  </Step>

  <Step title="Disable ingestion of Executed contracts">
    Finally, you can switch off the ingestion process introduced in Step 2. Transaction parsing is
    now fully driven by CIP-112 event-based parsing.
  </Step>
</Steps>
