Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Infer templateId and choiceName in daml trigger commands #2945

Merged
merged 9 commits into from
Sep 18, 2019

Conversation

aherrmann-da
Copy link
Contributor

Closes #2914

  • Infers templateId from templateArg in createCmd.
  • Infers choiceName from choiceArg in exerciseCmd.
  • Introduces AnyContractId, which carries templateId and contractId.
  • Infers templateId from contractId: AnyContractId in exerciseCmd.
  • The template type still needs to be passed explicitly in exerciseCmd.
    In future we may wish to pass ContractId t instead of AnyContractId. This would require something like fromAnyContractId : AnyContractId -> Option (ContractId t)
  • Extends the ACS test-case to use exerciseCmd.
    Introduces an indirection, where the trigger first creates AssetMirrorProposal and then exercises the Accept choice that creates the actual AssetMirror.

Pull Request Checklist

  • Read and understand the contribution guidelines
  • Include appropriate tests
  • Set a descriptive title and thorough description
  • Add a reference to the issue this PR will solve, if appropriate
  • Add a line to the release notes, if appropriate
  • Normal production system change, include purpose of change in description

NOTE: CI is not automatically run on non-members pull-requests for security
reasons. The reviewer will have to comment with /AzurePipelines run to
trigger the build.

Add a layer of indirection to test `exerciseCmd` in the ACS test.

The trigger first creates a `AssetMirrorProposal`, only when the
proposal has been created, will it exercise the `Accept` choice to
create the actual `AssetMirror` contract.
Copy link
Contributor

@cocreature cocreature left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great with some minor comments, thank you!

@@ -24,6 +24,11 @@ data Identifier = Identifier
, entityName : Text
} deriving (Show, Eq)

data AnyContractId = AnyContractId
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn’t we expose this type (but not the constructors). I also wonder if we might just want to keep calling this ContractId for now until we have a variant with a phantom type parameter but I guess changing it now is better for backwards compatibility.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, we should expose it. I overlooked that, good catch!

Even if we introduce a ContractId t with a phantom type parameter, we'd still need something like AnyContractId for the Created and Archived events. I figured once we introduce ContractId t we need to change exerciseCmd anyway, but we can keep Created and Archived untouched.

I have no strong opinion on the name, though, so happy to rename it if you prefer.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let’s keep AnyContractId for now.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn’t we expose this type (but not the constructors)

For now we need access to the templateId field in ACS.daml updateEvent.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems reasonable 👍

createCmd : Template t => TemplateId -> t -> Command
createCmd templateId templateArg =
CreateCommand templateId (toLedgerValue templateArg)
createCmd : Template t => t -> Command
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very nice, this is starting to look very usable!

@@ -177,13 +181,21 @@ object Converter {
("name", SText(id.entityName)))
}

private def fromAnyContractId(triggerIds: TriggerIds, templateId: value.Identifier, contractId: String): SValue = {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this take a value of type AnyContractId? Seems more consistent with toAnyContractId.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In principle that would be more consistent, yes. It's a bit noisy, though, because here we have a value.Identifier, but AnyContractId holds an Identifier. So, we'd be converting back and forth between the two identifier types.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah I see, makes sense to keep it this way then. There are clearly too many things called Identifier here 🙂

updateAcs acs (Created _ cId tId)
| tId.entityName == "Asset" = TM.insert cId tId acs
updateAcs acs (Created _ cId)
| cId.templateId.entityName == "Asset" = TM.insert cId.contractId cId.templateId acs
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I’m confused, it looks like you don’t expose AnyContractId (or more likely I’m too stupid to see it) but you can still access the fields?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, that's why I didn't notice that I hadn't exposed it. I don't know how the field is accessible without export. The code still compiles, even if I explicitly export the type without the constructors.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh I think that might be because of how our record desugaring (the dot syntax used here) works. That does seem rather confusing and potentially problematic since it removes the ability to have abstract record types.

@mergify mergify bot merged commit df7262e into master Sep 18, 2019
@mergify mergify bot deleted the trigger-infer-ids branch September 18, 2019 10:06
Copy link
Contributor

@hurryabit hurryabit left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice. Thanks.

@@ -24,6 +25,11 @@ data Identifier = Identifier
, entityName : Text
} deriving (Show, Eq)

data AnyContractId = AnyContractId
{ templateId : Identifier
, contractId : Text
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we use something like ContractId () here? There as a DAML-LF function coerce_contract_id : ContractId a -> ContractId b which we could use then.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could but I think it makes more sense to keep this consistent with AnyTemplate. I also deliberately don’t want to use the DAML-LF ContractId type to avoid annoyances around the absence of things like Ord instances.

@cocreature cocreature added this to the DAML Triggers milestone Oct 9, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Remove TemplateIdentifier and ChoiceName arguments from DAML trigger commands
4 participants