The primitives provided by Daml LF: How Daml Types are Translated to Daml-LF — Daml SDK 2.3.0 documentation
generally map to language equivalents. But ContractId and Party and mapped into regular String
values instead of a wrapper such as a ContractId.class and Party.class. There is the Value.class implementations of Party and ContractId but these seem to be lower level representations used for grpc transformations.
Is there a design decision around using the String vs a specific class?
I ask because when working with the java-bindings a dev design decision that keeps coming up is understanding what the expected data type that is being sent and returned into/from the grpc channel:
Understanding the intended data format allows downstream interpretation of the data: For example, understanding that a Key is (Party, Party, String)
vs (String, String, String), allows a generation validations (does the Party being created even exist before being sent into the ledger), allows type handling to provide better experiences (allow a key with Parties to have the UI generate lookups for the Display name of that party (without having to hard code the logic of the specific template into the UI). Same concepts for ContractId.
You can have a complex mix of keys as shown in: Input limit on template Key - #3 by cocreature. So when the bindings receive these keys, they are just a mix of “String, String, String, String
”, and the bindings have ~no-way to understand them (yes we could parse the content for string patterns such as a party starting with the word party, but lots of weak points to deal with in that solution).
Additionally, It is easy to mix/typo your way into mixing contractId and party values (as they are both strings and use heavily in the same methods) (similar for workflowId, commandId, and transactionId, but much less common usage).
It looks like it would be valuable to wrap Party and ContractId into its own class wrappers just as the Value Interface has Party and ContractId values.
Some notes:
- generated Contract classes always wrap the contract id in the ContractId class, but when you receive the contract id it is in a String format:
public class TransactionTree {
private final String transactionId;
...
CreatedEvent:
...
public @NonNull String getContractId() {
return this.contractId;
}
...
etc
Now we can say that we know it is the contractId in that case, but as soon as we move it out of that method and into another value, or list of objects we lose the typing on contract Id as it is regular String.
- The most noticeable loss of the typing is in the use of keys when you want the client to understand the structural content of the key and have to hard code it in based a reading of the Daml template.