consider the example from:
Here is the example with a test (I have removed the Alias template as it served no purpose in the example):
module MarketOriginal where
import DA.Date
import qualified Daml.Script as S
import qualified DA.List as L
-- MAIN_TEMPLATE_BEGIN
template User with
username: Party
following: [Party]
where
signatory username
observer following
-- MAIN_TEMPLATE_END
key username: Party
maintainer key
-- FOLLOW_BEGIN
nonconsuming choice Follow: ContractId User with
userToFollow: Party
controller username
do
assertMsg "You cannot follow yourself" (userToFollow /= username)
assertMsg "You cannot follow the same user twice" (notElem userToFollow following)
archive self
create this with following = userToFollow :: following
-- FOLLOW_END
nonconsuming choice NewSellOffer : ()
with
observers : [Party]
title : Text
description : Text
price : Int
controller username
do
now <- getTime
create $ SellOffer {seller = username, date = toDateUTC now, ..}
pure ()
nonconsuming choice TakeSellOffer : ()
with
offer : ContractId SellOffer
controller username
do
exercise offer DoTrade with tradePartner = username
pure ()
nonconsuming choice ConfirmPayment : ()
with
invoice : ContractId Invoice
controller username
do
Invoice{..} <- fetch invoice
assert $ owner == username
create $ PaymentConfirmation
with
invoice = invoice
party = username
obligor = obligor
pure ()
template SellOffer
with
observers : [Party]
title : Text
description : Text
price : Int
seller : Party
date : Date
where
signatory seller
observer observers
nonconsuming choice DoTrade : ()
with
tradePartner : Party
controller tradePartner
do
assert $ tradePartner `elem` observers
archive self
create $ Invoice {owner = seller, obligor = tradePartner, amount = price, description = title}
pure ()
template Invoice
with
owner : Party
obligor : Party
amount : Int
description : Text
where
signatory obligor
observer owner
template PaymentConfirmation
with
invoice : ContractId Invoice
party : Party
obligor : Party
where
signatory party
observer obligor
nonconsuming choice ArchiveInvoice : ()
controller obligor
do
archive invoice
archive self
normalFlow = do
[alice, bob] <- mapA S.allocateParty ["Alice", "Bob"]
userAlice <- submit alice do
S.createCmd User with
username = alice
following = []
userBob <- submit bob do
S.createCmd User with
username = bob
following = []
submit alice do
S.exerciseCmd userAlice NewSellOffer with
observers = [bob]
title = "My Title"
description = "Some Description"
price = 100
sellOffers <- S.query @SellOffer bob
assertMsg "Only one sell offer should exist" (length sellOffers == 1)
let (soCid, soData) = L.head sellOffers
submit bob do
S.exerciseCmd userBob TakeSellOffer with
offer = soCid
invoices <- S.query @Invoice bob
assertMsg "Only one invoice should exist" (length invoices == 1)
let (invCid, invData) = L.head invoices
submit alice do
S.exerciseCmd userAlice ConfirmPayment with
invoice = invCid
payConf <- S.query @PaymentConfirmation bob
assertMsg "Only one payment confirmation should exist" (length payConf == 1)
return ()
This example shows the use of a “User” template that contains the TakeSellOffer and ConfirmPayment choices.
My question is around the purpose of centralizing choices/commands in the User Template:
- Is there a specific design decision around centralizing these choices into User?
- Why would you not place “TakeSellOffer” choice and place it into the SellOffer template?
- Why would you not place ConfirmPayment and place it into the Invoice template?
- Is this about UI optimizations? where the user contract is used as the central UI hub for the user?
- Is there benefits to centralizing under a “user” type of contract for transaction structures?
- Is there specific design reasons for not returning ContractId for NewSellOffer, TakeSellOffer, and ConfirmPayment choices?
Thanks!