DAML: Error "failed due to that some parties are maintainers but not signatories: 'Bob' "

Here what I do
Admin wants to create users with a key in User that who create it
So I create Admin with signatory admin
and User template with signatory is admin and observer is user
and choice with a controller is admin to create a user.
but it gives me an error
“failed due to that some parties are maintainers but not signatories:”

What is the preferable way of doing this?
Thanks in advance.

Here is my code

template Admin
     with
         name : Text
         admin : Party
     where
          signatory admin
 
          key admin: Party
          maintainer key

template User
  with 
    name : Text
    user : Party  
    admin : Party

  where 
    signatory  admin 
    observer user

    key  user   : Party 
    maintainer key 
 
    choice CreateUser : ContractId User
      controller admin 
      do create this  

 setup = do 
       admin <- getParty "Alice"
       user  <- getParty "Bob"

       uid <- submit admin do
            create Admin 
                with 
                    name = "Alice" 
                    admin    

       submit admin $ create User 
        with 
           name = "Bob" 
           user
           admin
2 Likes

Hi @Muhammad_Moiz, welcome to the forum!

Could you describe what you want to use the key for? For the scenario you posted, the key isn’t required at all.

In general, the maintainers always need to be signatories. What you could do is to add a signatory to the key and make it the maintainer, so something like:

key (admin, user) : (Party, Party)
maintainer key._1

or maybe even key admin : Party depending on your usecase.

There also appears to be a typo somewhere in our example, Your key is a single party but your definition of maintainers assume that you have a tuple (._1 extracts the first elements from a tuple). Maybe you already tried to add the admin to the key?

2 Likes

Yes there is a typo error, Which I correct it.

2 Likes

Actually I want to save the Admin key in User contract so that User know whos create it. Can you suggest me the better way for doing this.

1 Like

The User contract already stores the admin party. What do you want to use the key to the Admin contract for?

1 Like

I am a beginner.
I update

    key  admin   : Party 
    maintainer key

in User template and its works.
I understand what I am doing wrong.
I used keys here because an Admin can create multiple Users so admin should know how many user he created. So I just create a key in User and make admin as a maintainer.

1 Like

Contract keys enforce uniqueness: There can only be one contract with a given key. If one admin should be able to create multiple users, you cannot just use the admin as the key.

If your goal is to know how many users an admin has created or more generally, keep track of the User contracts they created, then you need to store that somewhere. One option would be something like the following where you store the list of created contracts in the Admin contract. If you do not need the list in DAML itself, you can instead query the list of User contracts on the client side via the HTTP JSON API or the gRPC Ledger API.

template Admin
     with
         name : Text
         admin : Party
         createdUsers: [ContractId User]
     where
          signatory admin
 
          key admin: Party
          maintainer key
          choice CreateUser : ContractId User
            with
              name : Text
              user : Party
           controller admin
           do newUser <- create User with ..
              create this with createdUsers = newUser :: this.createdUsers
              pure newUser

template User
  with 
    name : Text
    user : Party  
    admin : Party

  where 
    signatory  admin 
    observer user
1 Like