Archived contracts can only be retrieved from the full transaction stream on the gRPC API, and this is fairly expensive since you have to traverse the ledger from genesis. It’s really mostly intended for “forensic” purposes, for example, if you have to provide an audit trail for a particular contract to verify its provenance.
I see DamlLedgerClient.getTransactionsClient and TransactionsClient might be the way, but I don’t know what getTransactions to use and what LedgerOffset to give. Is 0 the beginning of the ledger and will I be able to retrieve archived contracts that way?
If you’re only interested in contracts that have been actually recorded on the ledger at some point you can use getTransactions, which represents a stream of updates that can be rolled up into a set of contracts that were active at a given offset (e.g. it can be used in conjuction with the active contract service to keep the active contract set on your application without constantly fetching it from the ledger). To get the most detail the method you want to use is getTransactionTrees (i.e. all the events, including non-consuming exercises and the creation of ephemeral contracts that are created and consumed within the same transaction). The offset you want to pass to read from the beginning of the ledger is LedgerOffset.LedgerBegin.
There’s no way to convert directly between the two. Possibly you may want to use the ledger effective time which can be accessed in the transaction trees through getEffectiveAt but consider that in a distributed system clocks can be skewed and the absence of a single reference of time makes this conversion unreliable at best. I would also add that if you care about time as part of your application you should explicitly make it part of your domain model and use that.
One final note: from a first look at the kind of problems you are trying to solve, it looks like tapping directly into the Daml Ledger API could not be your best choice. Consider it the API that allows you to tap into the ledger data, but in a very generic way, which doesn’t support rich querying. One common pattern to build Daml applications is to materialize the state that you need in a secondary data store that is purposed towards your application’s specific needs (e.g. indexing by time if you need to make time-based queries).
Hi Simon. I just thought that you could also look in the SDK source code for the navigator backend to see in practice how archived contracts are fetched.
You can grep for archived.
The navigator is typically started when you run daml start, and you can display archived contracts by ticking the “show archived” box in the top right corner.
The only thing is that I’m not entirely certain which API navigator is using. It’s quite an old codebase.
The Navigator uses the Scala bindings, which are currently deprecated as part of the SDK. But if @Simon_Alexe can read through the codebase they’ll see a practical example of the standard approach of creating a Daml application by using a secondary data store (sqlite in Navigator’s case) to answer to the application’s needs. Thanks for pointing that out, @Luciano!