Features announced to be deprecated: "controller first" choice syntax, contract key uniqueness - anything else?

Some features were announced to be deprecated together with the announcement of Daml 2.0. I have found two such features, is there anything else I have missed?

"Controller first" choice syntax

  • The syntax controller … can will be deprecated in favor of the choice X controller … syntax. If the deprecated syntax is used then the following warning will be shown in the IDE:
    The syntax 'controller ... can' is deprecated, it will be removed in a future version of Daml. Instead, use 'choice ... with ... controller' syntax. Note that 'choice ... with ... controller' syntax does not implicitly add the controller as an observer, so it must be added explicitly as one (or as a signatory).

Contract key uniqueness

contract key uniqueness will soon be deprecated, as uniqueness can not be enforced among multiple domains. We encourage to build your models already anticipating this change.

https://docs.daml.com/canton/usermanual/contract_keys.html

I guess with the deprecation of key uniqueness, some functions like exerciseByKey (used extensively in React UI examples for Daml) will also be deprecated.

Thank you!

I’ve deleted my answer since it contained inaccuracies, I’ll let someone else write down an accurate answer, apologies for the confusion.

1 Like

The only deprecations I’m aware off are the controller … can syntax and the ledger identity service.

Note that both of those are deprecated not removed, you can still use them for now and migrate away from them over time.

Contract key uniqueness is not yet deprecated. In fact, it’s the only supported option atm since multi-domain Canton is not yet GA. It may still be useful to consider where you rely on contract key uniqueness to ease the migration later but for now uniqueness is the only option on GA ledgers.

1 Like

Yes, thank you!

Thank you, Stefano!

Hey I have the same issue but didn’t understand how to fix it. could you please help me?

The syntax ‘controller … can’ is deprecated, it will be removed in a future version of Daml. Instead, use ‘choice … with … controller’ syntax. Note that ‘choice … with … controller’ syntax does not implicitly add the controller as an observer, so it must be added explicitly as one (or as a signatory).

@Nimra_Fatima can you share the example you’re having trouble adjusting?

I got this error in my .daml files

The syntax ‘controller … can’ is deprecated, it will be removed in a future version of Daml. Instead, use ‘choice … with … controller’ syntax. Note that ‘choice … with … controller’ syntax does not implicitly add the controller as an observer, so it must be added explicitly as one (or as a signatory).

please help me to fix this issue

Hi @Nimra_Fatima,

It’s difficult to give you more guidance than what’s already said in the error message without having access to your code. Can you share the template that produces that warning?

@Gary_Verhaegen

Payment.daml

module Payment where

template Payable
with
amount: Decimal
currency: Text
from: Party
to: Party
reference: Text
where
signatory from
observer to

controller from can 
  ClaimPaid: ContractId PaymentClaim 
    with 
      transactionId: Text 
    do 
      create PaymentClaim with ..

template PaymentClaim
with
amount: Decimal
currency: Text
from: Party
to: Party
reference: Text
transactionId: Text
where
signatory from

controller to can 
  Receive: ContractId Receipt 
    do 
      received <- getTime
      create Receipt 
        with ..

template Receipt
with
amount: Decimal
currency: Text
from: Party
to: Party
reference: Text
transactionId: Text
received: Time
where
signatory to, from

controller from can 
  Dismiss: () 
    do return ()

here is the code in which I got this error

Hi @Nimra_Fatima,

As the error message says, the controller ... can syntax is deprecated and needs to be replaced with choice ... controller .... The two syntaxes are explained in the documentation of choices.

As a concrete example, this means replacing:

  controller from can
    ClaimPaid: ContractId PaymentClaim 
      with 
        transactionId: Text 
      do 
        create PaymentClaim with ..

which is in "controller first" form, to the equivalent "choice first" form:

  choice ClaimPaid : ContractId PaymentClaim
    with transactionId: Text
    controller from
    do
      create PaymentClaim with ..

which is the same choice but expressed with the choice keyword first.

The "choice first" form has a couple advantages:

  • It can specificy the consuming behaviour of a choice.
  • It can enable flexible controllers by having the controlling Party as an argument to the choice, as explained in this old blog post.
  • It’s not deprecated.

Importantly, while not all "choice first" choices can be translated to controller first" form, all "controller first" choices can easily be transformed to "choice first" by basically moving the controller X words a couple lines down, with the minor exception that when the controller was neither a signatory nor an observer, it needs to be manually added to the observers.

@Gary_Verhaegen Thank you so much Sir

Hey @Gary_Verhaegen
can you tell me how to add controller keyword in nonconsuming choice

controller issuer can 
  nonconsuming MintToken: ContractId Token 
    with 
      description: Text 
      initialPrice: Decimal 
      currency: Text 
      royaltyRate: Decimal 
      thumbnail: Thumbnail
    do 
      issued <- getTime
      create Token
        with 
          lastPrice = initialPrice
          owner = issuer
          ..

@Nimra_Fatima
Here you go

    nonconsuming choice MintToken: ContractId Token 
       with 
         description: Text 
         InitialPrice: Decimal 
         currency: Text 
         royaltyRate: Decimal 
         thumbnail: Thumbnail
      controller issuer
      do 
         issued <- getTime
         create Token
           with 
             lastPrice = initialPrice
             owner = issuer
             ..

@a_putkov I have already tried this but when I write controller then it gives me the error

nonconsuming choice MintToken: ContractId Token   
    with
      description: Text
      initialPrice: Decimal
      currency: Text
      royaltyRate: Decimal
    
    controller issuer
    do
      issued <- getTime
      create Token
        with
          lastPrice = initialPrice
          owner = issuer
          .. 

error: /home/nimra/private-nft/nft/daml/UserAdmin.daml:27:9: error:
parse error on input ‘controller’parser

@Nimra_Fatima can you share the full file please?

That looks like it should work, but as @cocreature implied, it may depend on the rest of the file, particularly the overall indentation.

@cocreature here is the code

module UserAdmin where

import Token
import Payment

template Issuer
with
userAdmin: Party
issuer: Party
where
signatory userAdmin
ensure userAdmin /= issuer

  nonconsuming choice MintToken: ContractId Token 
    with 
      description: Text 
      initialPrice: Decimal 
      currency: Text 
      royaltyRate: Decimal 
      thumbnail: Thumbnail
        
    controller issuer 
    do 
      issued <- getTime
      create Token
        with 
          lastPrice = initialPrice
          owner = issuer
          ..

controller userAdmin can 
  RevokeIssuer: () 
    do return ()

template IssuerRequest
with
userAdmin: Party
issuer: Party
reason: Text
where
signatory issuer

key (userAdmin, issuer): (Party, Party)
maintainer key._2

controller userAdmin can 
  GrantIssuerRights: ContractId Issuer 
    do 
      create Issuer with ..

  RejectIssuerRequest: () 
    do return ()

template Owner
with
userAdmin: Party
owner: Party
where
signatory userAdmin
ensure userAdmin /= owner

key (userAdmin, owner): (Party, Party)
maintainer key._1

controller owner can 
  nonconsuming AcceptTokenAsNewOwner: (ContractId Token, ContractId Payable, Optional (ContractId Payable))
    with 
      offerId: ContractId TokenOffer 
    do 
      exercise offerId AcceptToken 

  nonconsuming AcceptTokenByKey: (ContractId Token, ContractId Payable, Optional (ContractId Payable))
    with 
      issuer: Party 
      currentOwner: Party 
      description: Text 
    do 
      exerciseByKey @TokenOffer (issuer, currentOwner, description) AcceptToken

controller userAdmin can 
  RevokeOwnerRights: () 
    do return ()

template OwnerRequest
with
userAdmin: Party
owner: Party
reason: Text
where
signatory owner

key (userAdmin, owner): (Party, Party)
maintainer key._2

controller userAdmin can 
  GrantOwnerRights: ContractId Owner 
    do 
      create Owner with ..

  RejectOwnerRequest: () 
    do return ()

Please post this as a code block by wrapping it in triple backticks

```
yourcodehere
```

Otherwise the indentation gets messed up which makes it hard to find issues related to that.

1 Like