How to execute a choice that returns Either (ContractA) (ContractB) in a script

Hey DAMLer’s!

I am working on converting my scenario to a script. Our model is based on ex-cdm-swaps.

I am trying to execute this line in my script.

eiCid <- fromRightS "Unknown error" =<< (submit p2.p do exerciseCmd epCid EP.Accept with exerciser = p2.p)

Here is the error I am getting.

C:\Users\James Jaworski\OneDrive\BloqbookV2\sandbox-srm\src\daml\DA\srm\Test\Event.daml:102:12: error:
    • Couldn't match type ‘Scenario’ with ‘Script’
      Expected type: Script (ContractId EventInstance)
        Actual type: Scenario (ContractId EventInstance)
    • In a stmt of a 'do' block:
        eiCid <- fromRightS "Unknown error"
                   =<<
                     (submit
                        (DA.Internal.Record.getField @"p" p2)
                        do exerciseCmd
                             epCid
                             EP.Accept {exerciser = (DA.Internal.Record.getField @"p" p2)})
      In the expression:
        do debug "Starting market setup..."
           let p1 = ...
           let p2 = ...
           let p3 = ...
           ....
      In an equation for ‘setupMarketWithParties’:
          setupMarketWithParties parties@CdmParties {..}
            = do debug "Starting market setup..."
                 let p1 = ...
                 let p2 = ...
                 ....typecheck
C:\Users\James Jaworski\OneDrive\BloqbookV2\sandbox-srm\src\daml\DA\srm\Test\Event.daml:102:54: error:
    • Couldn't match type ‘Script’ with ‘Scenario’
        arising from a functional dependency between:
          constraint ‘HasSubmit Scenario Commands’
            arising from a use of ‘submit’
          instance ‘HasSubmit Script Commands’ at <no location info>
    • In the second argument of ‘(=<<)’, namely
        ‘(submit
            (DA.Internal.Record.getField @"p" p2)
            do exerciseCmd
                 epCid
                 EP.Accept {exerciser = (DA.Internal.Record.getField @"p" p2)})’
      In a stmt of a 'do' block:
        eiCid <- fromRightS "Unknown error"
                   =<<
                     (submit
                        (DA.Internal.Record.getField @"p" p2)
                        do exerciseCmd
                             epCid
                             EP.Accept {exerciser = (DA.Internal.Record.getField @"p" p2)})
      In the expression:
        do debug "Starting market setup..."
           let p1 = ...
           let p2 = ...
           let p3 = ...
           ....typecheck
Peek Problem (Alt+F8)
No quick fixes available

When I start to check this out, I think that it has something to do with the Accept choice of the EventProposal contract returning Either (ContractId EventProposal) (ContractId EventInstance).

In this case, I am looking to return the right side, EventInstance.

From the docs, it looks like step 5 is what I am trying to figure out. If so, what is the best way to specify which return the compiler in the script should expect?

1 Like

Looking at the error, it seems like fromRightS is the culprit here and has a type similar to Either a b -> Scenario b. Could you share the definition of fromRightS with us?

1 Like

You’re correct. It comes from here. As I have learned from this exercise, you can’t return the results of a scenario within a script.

After seeing that, I thought maybe I could do something like this but it threw an error. I assume it’s looking for one output.

( _ , eiCid) <- submit p2.p do exerciseCmd epCid EP.Accept with exerciser = p2.p

So perhaps, I could convert this to a script?

1 Like

You can either use pattern matching (regardless of whether you use scenarios or scripts as follows):

Right eiCid <- submit p2.p do exerciseCmd epCid EP.Accept with exerciser = p2.p

That will crash if you get a Left but contrary to fromRightS it won’t include a (potentially) useful error message so I’d recommend against this outside of test code.

The other option is to make fromRightS work with Script. In this case, this is luckily a pretty small change. abort has the type CanAbort m => Text -> m a. Both Script and Scenario are an instance of CanAbort (Update is as well). So we don’t have to change the definition at all, all we have to do is to generalize the type and it works for both Scenario and Script. Of course, if you only need it for Script, you can also just replace the Scenario in the type by Script:

fromRightS : CanAbort m => Text -> Either a b -> m b
fromRightS msg (Left _) = abort msg
fromRightS _ (Right x) = return x
1 Like

Interesting. Thanks for the help on this.

There are quite a bit of helper functions in the test folder to help make the former scenarios more legible. I have been trying to minimize how many of them I try to change or update, as they’re not critical for us at this stage.

For right now, I just want to update so that we can initialize the ledger and display one workflow using React ui on DABL for demo purposes.

Thanks again for your help working through these and teaching me some new DAML tricks along the way!

1 Like