Skip to content
Discussions/App Development/Canton Console how to represent DA.Set & DA.MapForum ↗

Canton Console how to represent DA.Set & DA.Map

App Development15 posts353 views4 likesLast activity May 2022
DO
Dorrit_DuOP
May 2022

Hi team,

I am trying to follow tutorials under link to create the IOU contract in canton console.

However, I have difficulty on presenting DA.Set and DA.Map as shown in below modified Iou template. Can you please share me an example on how to construct the createIouCmd ?


template Iou
  with
    payer: Party
    owner: Party
    amount: Amount
    observers: Set Party
    referenceId:  Map.Map Party Text
  where

    ensure (amount.value >= 0.0)

    signatory payer
    observer observers

many thanks in advanced!

Cheers,
Dorrit

GA
Gary_Verhaegen
May 2022

Hi @Dorrit_Du,

Can you share a bit more information on what you’re trying to accomplish and what error message you’re getting, or what behaviour you’re seeing that is unexpected?

Your code, unchanged, seems to compile fine for me. Here is the full code I have:

module Main where

import DA.Set
import DA.Map as Map

data Amount = Amount { value: Decimal }
  deriving (Eq, Show)

template Iou
  with
    payer: Party
    owner: Party
    amount: Amount
    observers: Set Party
    referenceId:  Map.Map Party Text
  where

    ensure (amount.value >= 0.0)

    signatory payer
    observer observers
DO
Dorrit_Du
May 2022

Hi Gary,

Apologies for unclear description. I am able to deployethe dar file consisting the above IOU template on my canton setup. Now I am trying to create an IOU contract under canton console but I am not sure how to construct observers and referenceId fields(i.e Set and Map)

Here is the error I got when creating the contract.

@ active_participant2.ledger_api.commands.submit(Seq(party), Seq(createIouCmd))
ERROR c.d.c.c.EnterpriseConsoleEnvironment - Request failed for participant_2a.
  GrpcClientError: INVALID_ARGUMENT/INVALID_ARGUMENT(8,8414cf93):

thanks,
Dorrit

GA
Gary_Verhaegen
May 2022

Ah, I have no experience with the Canton console at all. I’ll reach out to the Canton team and make sure they see this thread.

GA
Gary_Verhaegen
May 2022

In the meantime it may be worth giving a little bit more context on that Console error: could you share the entire Console session? I’m especially interested in how you constructed party and createIouCmd.

DA
danilofaria
May 2022

Hey @Dorrit_Du,
If you’re still having this issue, could you please share the whole error message as well as the whole console session as Gary suggested?

DO
Dorrit_Du
May 2022

Hi, I have shared the error message to Gary via slack.
Can anyone show the examples how to construct DA.Set and DA.Map? this will solve my problem, thanks!

DO
Dorrit_Du
May 2022

I am having another test for Map type only

template PartyInfo2
  with
    operator : Party -- party onboarding --
    referenceId : Map.Map Text Text
  where
    signatory operator

here is the command I put in canton console:
step 1
val createIouCmd2 = ledger_api_utils.create(pkgIou.packageId,"PartyInfo","PartyInfo2",Map("operator" -> bank,"referenceId" -> Map("testKey" -> "testValue")))

step2

@ participant1.ledger_api.commands.submit(Seq(bank), Seq(createIouCmd2 ))
ERROR c.d.c.c.EnterpriseConsoleEnvironment - Request failed for participant1.
  GrpcClientError: INVALID_ARGUMENT/COMMAND_PREPROCESSING_FAILED(8,062dbf94): mismatching type: GenMap Text Text and value: ValueRecord(None,ImmArray((Some(testKey),ValueText(testValue))))
  Request: SubmitAndWaitTransactionTree(actAs = Bank::122085663808..., commandId = '', workflowId = '', submissionId = '', deduplicationPeriod = None(), ledgerId = 'participant1', commands = ...)
  CorrelationId: 062dbf94-69cd-4f50-93b7-76040b991100
  Context: HashMap(participant -> 'participant1', err -> TypeMismatch(TApp(TApp(TBuiltin(BTGenMap),TBuiltin(BTText)),TBuiltin(BTText)),ValueRecord(None,ImmArray((Some(testKey),ValueText(testValue)))),mismatching type: GenMap Text Text and value: ValueRecord(None,ImmArray((Some(testKey),ValueText(testValue))))), definite_answer -> false, commands -> {readAs: [], deduplicationPeriod: {duration: 'PT168H'}, submittedAt: '2022-05-06T04:54:08.235587Z', ledgerId: 'participant1', applicationId: 'CantonConsole', actAs: ['Bank::122085663808764779236ac9539e7295c5534020dfb860023200d389dd0ca828ef02'], commandId: '19b84dcb-80a5-4ce3-8cb1-a3680611b92a', workflowId: })
  Command BaseLedgerApiAdministration$ledger_api$commands$.submit invoked from cmd25.sc:1
com.digitalasset.canton.console.CommandFailure: Command execution failed.
CO
cocreature
May 2022

A Scala map maps to a Daml-LF record. There doesn’t seem to be any convenience helpers for building a Daml-LF map so you have to build it somewhat verbosely:

val createCmd = ledger_api_utils.create(
  pkgId,
  "PartyInfo",
  "PartyInfo2",
  Map(
    "operator" -> bank,
      "referenceId" -> Value.Sum.GenMap(GenMap(Seq(GenMap.Entry(Some(Value(Value.Sum.Text("testKey"))), Some(Value(Value.Sum.Text("testValue")))))))))
DO
Dorrit_Du
May 2022

Thanks, @cocreature . It will be great if you can share us the DA.SET example as well.

From the above solution that you gave, now I am getting below error. Do I miss any import?

val createCmd = ledger_api_utils.create(pkgIou.packageId,"PartyInfo","PartyInfo2",Map("operator" -> bank,"referenceId" -> Value.Sum.GenMap(GenMap(Seq(GenMap.Entry(Some(Value(Value.Sum.Text("testKey"))), Some(Value(Value.Sum.Text("testValue")))))))))
cmd10.sc:1: not found: value Value
val createCmd = ledger_api_utils.create(pkgIou.packageId,"PartyInfo","PartyInfo2",Map("operator" -> bank,"referenceId" -> Value.Sum.GenMap(GenMap(Seq(GenMap.Entry(Some(Value(Value.Sum.Text("testKey"))), Some(Value(Value.Sum.Text("testValue")))))))))
                                                                                                                          ^
cmd10.sc:1: not found: value GenMap
val createCmd = ledger_api_utils.create(pkgIou.packageId,"PartyInfo","PartyInfo2",Map("operator" -> bank,"referenceId" -> Value.Sum.GenMap(GenMap(Seq(GenMap.Entry(Some(Value(Value.Sum.Text("testKey"))), Some(Value(Value.Sum.Text("testValue")))))))))
                                                                                                                                           ^
cmd10.sc:1: not found: value GenMap
val createCmd = ledger_api_utils.create(pkgIou.packageId,"PartyInfo","PartyInfo2",Map("operator" -> bank,"referenceId" -> Value.Sum.GenMap(GenMap(Seq(GenMap.Entry(Some(Value(Value.Sum.Text("testKey"))), Some(Value(Value.Sum.Text("testValue")))))))))
                                                                                                                                                      ^
cmd10.sc:1: not found: value Value
val createCmd = ledger_api_utils.create(pkgIou.packageId,"PartyInfo","PartyInfo2",Map("operator" -> bank,"referenceId" -> Value.Sum.GenMap(GenMap(Seq(GenMap.Entry(Some(Value(Value.Sum.Text("testKey"))), Some(Value(Value.Sum.Text("testValue")))))))))
                                                                                                                                                                        ^
cmd10.sc:1: not found: value Value
val createCmd = ledger_api_utils.create(pkgIou.packageId,"PartyInfo","PartyInfo2",Map("operator" -> bank,"referenceId" -> Value.Sum.GenMap(GenMap(Seq(GenMap.Entry(Some(Value(Value.Sum.Text("testKey"))), Some(Value(Value.Sum.Text("testValue")))))))))
                                                                                                                                                                              ^
cmd10.sc:1: not found: value Value
val createCmd = ledger_api_utils.create(pkgIou.packageId,"PartyInfo","PartyInfo2",Map("operator" -> bank,"referenceId" -> Value.Sum.GenMap(GenMap(Seq(GenMap.Entry(Some(Value(Value.Sum.Text("testKey"))), Some(Value(Value.Sum.Text("testValue")))))))))
CO
cocreature
May 2022

Ah right, I forgot to paste the imports:

import com.daml.ledger.api.v1.value.{GenMap, Value}

should to the trick.

Set k is not a primitive Daml-LF value, it’s defined as a wrapper around Map k v, see daml/Types.daml at 5d8ebd7a08761ac4a8bc848eb0ff8e6871492b4a · digital-asset/daml · GitHub

So if you build a map as described above with unit values and then wrap it in Map("map" -> genmapexpression) you should get a valid set.

DO
Dorrit_Du
May 2022

Finally, it works for the Map!

However, trying the Set one

template PartyInfo1
  with
    operator : Party -- party onboarding --
    legalEntityId: Text
    observers : Set Party
  where
    signatory operator

here is the way I did:

var mapvalue = Map("map" -> Value.Sum.GenMap(GenMap(Seq(GenMap.Entry(Some(Value(Value.Sum.Party("Bank::1220db907e2de9c35f5a665eb42c418235fa39ee231758ed14b05a75803d24c81107"))), Some(Value(Value.Sum.Party(null)))))))

val createCmd = ledger_api_utils.create(pkgIou.packageId,"PartyInfo","PartyInfo1",Map("operator" -> bank,"legalEntityId" -> "hello","observers" -> mapvalue))

createCmd: com.daml.ledger.api.v1.commands.Command = Command(
  command = Create(
    value = CreateCommand(
      templateId = Some(
        value = Identifier(
          packageId = "df14a3a49cfbf399df880613d84eea51cdbc67c403e49246212dda0b7a4c6df6",
          moduleName = "PartyInfo",
          entityName = "PartyInfo1"
        )
      ),
      createArguments = Some(
        value = Record(
          recordId = None,
          fields = List(
            RecordField(
              label = "operator",
              value = Some(value = Value(sum = Party(value = "Bank::1220db907e2de9c35f5a665eb42c418235fa39ee231758ed14b05a75803d24c81107")))
            ),
            RecordField(label = "legalEntityId", value = Some(value = Value(sum = Text(value = "hello")))),
            RecordField(
              label = "observers",
              value = Some(
                value = Value(
                  sum = Record(
                    value = Record(
                      recordId = None,
                      fields = List(
                        RecordField(
                          label = "map",
                          value = Some(
                            value = Value(
                              sum = GenMap(
                                value = GenMap(
                                  entries = List(
                                    Entry(
                                      key = Some(
                                        value = Value(
                                          sum = Party(value = "Bank::1220db907e2de9c35f5a665eb42c418235fa39ee231758ed14b05a75803d24c81107")
                                        )
                                      ),
                                      value = Some(value = Value(sum = Party(value = null)))
                                    )
                                  )
                                )
                              )
                            )
                          )
                        )
                      )
                    )
                  )
                )
              )
            )
          )
        )
      )
    )
  )
)

@ participant1.ledger_api.commands.submit(Seq(bank), Seq(createCmd))
ERROR c.d.c.c.EnterpriseConsoleEnvironment - Request failed for participant1.
  GrpcClientGaveUp: CANCELLED/Failed to stream message
  Request: SubmitAndWaitTransactionTree(actAs = Bank::1220db907e2d..., commandId = '', workflowId = '', submissionId = '', deduplicationPeriod = None(), ledgerId = 'participant1', commands = ...)
  Causes: null
  Command BaseLedgerApiAdministration$ledger_api$commands$.submit invoked from cmd21.sc:1
com.digitalasset.canton.console.CommandFailure: Command execution failed.

what wrong with above? thanks so much!

GA
Gary_Verhaegen
May 2022

Can you try replacing null with ()?

Both in the mapvalue definition:

var mapvalue = Map("map" -> Value.Sum.GenMap(GenMap(Seq(GenMap.Entry(Some(Value(Value.Sum.Party("Bank::1220db907e2de9c35f5a665eb42c418235fa39ee231758ed14b05a75803d24c81107"))), Some(Value(Value.Sum.Party(())))))))

and in the nested observers field:

value = Some(value = Value(sum = Party(value = ())))
CO
cocreature
May 2022

There is no magic conversion from null or () to Daml-LF unit here, you have to specify it verbosely:

val createCmd = ledger_api_utils.create(pkgId,"PartyInfo","PartyInfo1",Map("operator" -> bank,"legalEntityId" -> "foobar", "observers" -> Map("map" -> Value.Sum.GenMap(GenMap(Seq(GenMap.Entry(Some(Value(Value.Sum.Party(bank.toProtoPrimitive))), Some(Value(Value.Sum.Unit(Empty()))))))))))

This requires an import: import com.google.protobuf.empty.Empty

DO
Dorrit_Du
May 2022

thanks @cocreature ! it works!

← Back to Discussions