ValueDecoder for tuple and contract IDs

As you noticed over here, using the new strongly-typed command submission methods is the best way to get a choice exercise result decoded for you.

Otherwise, if you look at the code generated for CHOICE_Instruct, you can see how the return-type decoder used in the aforementioned command submission methods is assembled. With regard to concrete contract ID types, it should look something like

value -> new Batch.ContractId(
  value.asContractId()
    .orElseThrow(() -> new IllegalArgumentException("Batch"))
    .getValue())

Concrete contract-IDs are surely a missing piece of the combinator-library puzzle for assembling value decoders, but given the above pattern you can define a general-purpose decoder like so:

  // use like concreteContractIdValueDecoder(Batch.COMPANION)
  public static final <ContractType, Id>
      ValueDecoder<Id> concreteContractIdValueDecoder(
          ContractTypeCompanion<?, Id, ContractType, ?> companion) {
    return value ->
        companion.toContractId(
            new ContractId<>(
                value
                    .asContractId()
                    .orElseThrow(
                        () ->
                            new IllegalArgumentException(
                                companion.TEMPLATE_ID.getEntityName() + ".ContractId"))
                    .getValue()));
  }