From ada89d2df9895cfb0adea98d6a8564ecd69b9e43 Mon Sep 17 00:00:00 2001 From: Georg Schneider Date: Tue, 13 Dec 2022 01:45:52 +0100 Subject: [PATCH 01/31] Add base service interface --- .../Finance/App/Interface/Base/Offer.daml | 47 +++++++++++++++++++ .../Finance/App/Interface/Base/Request.daml | 47 +++++++++++++++++++ .../Finance/App/Interface/Base/Service.daml | 35 ++++++++++++++ ui/src/pages/defi/Exchanges.tsx | 3 +- 4 files changed, 130 insertions(+), 2 deletions(-) create mode 100644 src/daml/Daml/Finance/App/Interface/Base/Offer.daml create mode 100644 src/daml/Daml/Finance/App/Interface/Base/Request.daml create mode 100644 src/daml/Daml/Finance/App/Interface/Base/Service.daml diff --git a/src/daml/Daml/Finance/App/Interface/Base/Offer.daml b/src/daml/Daml/Finance/App/Interface/Base/Offer.daml new file mode 100644 index 00000000..e517ffbd --- /dev/null +++ b/src/daml/Daml/Finance/App/Interface/Base/Offer.daml @@ -0,0 +1,47 @@ +-- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +-- SPDX-License-Identifier: Apache-2.0 + +module Daml.Finance.App.Interface.Base.Offer where + +import Daml.Finance.App.Interface.Base.Service qualified as Service (I) + +type I = Offer + +type V = View + +data View = View + with + operator : Party + provider : Party + customer : Party + deriving (Eq, Show) + +interface Offer where + viewtype V + + accept : Update (ContractId Service.I) + -- ^ Implementation of the `Accept` choice. + reject : Update () + -- ^ Implementation of the `Reject` choice. + withdraw : Update () + -- ^ Implementation of the `Withdraw` choice. + + choice Accept : ContractId Service.I + controller (view this).customer + do + accept this + + choice Reject : () + controller (view this).customer + do + reject this + + choice Withdraw : () + controller (view this).provider + do + withdraw this + +-- | Type constraint for requiring templates to implement `Offer`. +type Implementation t = HasToInterface t Offer +class (Implementation t) => HasImplementation t +instance HasImplementation Offer diff --git a/src/daml/Daml/Finance/App/Interface/Base/Request.daml b/src/daml/Daml/Finance/App/Interface/Base/Request.daml new file mode 100644 index 00000000..0c1df34d --- /dev/null +++ b/src/daml/Daml/Finance/App/Interface/Base/Request.daml @@ -0,0 +1,47 @@ +-- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +-- SPDX-License-Identifier: Apache-2.0 + +module Daml.Finance.App.Interface.Base.Request where + +import Daml.Finance.App.Interface.Base.Service qualified as Service (I) + +type I = Request + +type V = View + +data View = View + with + operator : Party + provider : Party + customer : Party + deriving (Eq, Show) + +interface Request where + viewtype V + + accept : Update (ContractId Service.I) + -- ^ Implementation of the `Accept` choice. + reject : Update () + -- ^ Implementation of the `Reject` choice. + withdraw : Update () + -- ^ Implementation of the `Withdraw` choice. + + choice Accept : ContractId Service.I + controller (view this).operator, (view this).provider + do + accept this + + choice Reject : () + controller (view this).provider + do + reject this + + choice Withdraw : () + controller (view this).customer + do + withdraw this + +-- | Type constraint for requiring templates to implement `Request`. +type Implementation t = HasToInterface t Request +class (Implementation t) => HasImplementation t +instance HasImplementation Request diff --git a/src/daml/Daml/Finance/App/Interface/Base/Service.daml b/src/daml/Daml/Finance/App/Interface/Base/Service.daml new file mode 100644 index 00000000..58525cc8 --- /dev/null +++ b/src/daml/Daml/Finance/App/Interface/Base/Service.daml @@ -0,0 +1,35 @@ +-- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +-- SPDX-License-Identifier: Apache-2.0 + +module Daml.Finance.App.Interface.Base.Service where + +type I = Service + +type V = View + +data View = View + with + operator : Party + provider : Party + customer : Party + deriving (Eq, Show) + +interface Service where + viewtype V + + terminate : Update () + -- ^ Implementation of the `terminate` choice. + + choice Terminate : () + with + actor : Party + controller actor + do + let v = view this + assert $ actor == v.operator || actor == v.provider || actor == v.customer + terminate this + +-- | Type constraint for requiring templates to implement `Service`. +type Implementation t = HasToInterface t Service +class (Implementation t) => HasImplementation t +instance HasImplementation Service diff --git a/ui/src/pages/defi/Exchanges.tsx b/ui/src/pages/defi/Exchanges.tsx index 55bc24ff..6e868200 100644 --- a/ui/src/pages/defi/Exchanges.tsx +++ b/ui/src/pages/defi/Exchanges.tsx @@ -13,12 +13,11 @@ export const Exchanges : React.FC = () => { const { loading: l1, decentralizedExchange } = useServices(); if (l1) return (); - console.log(decentralizedExchange); return ( - {decentralizedExchange.map((c, i) => )} + {decentralizedExchange.map(c => c.payload).sort((a, b) => a.id.unpack.localeCompare(b.id.unpack)).map((p, i) => )} From f77cc7d1a4ceb73e5c2cb4bddcb235e587c1c001 Mon Sep 17 00:00:00 2001 From: Georg Schneider Date: Tue, 13 Dec 2022 11:38:07 +0100 Subject: [PATCH 02/31] Add custody service interfaces --- .../Custody/CloseAccountRequest.daml | 26 ++++ .../App/Interface/Custody/DepositRequest.daml | 38 ++++++ .../Interface/Custody/OpenAccountRequest.daml | 30 +++++ .../App/Interface/Custody/Service.daml | 116 ++++++++++++++++++ .../Interface/Custody/WithdrawRequest.daml | 26 ++++ 5 files changed, 236 insertions(+) create mode 100644 src/daml/Daml/Finance/App/Interface/Custody/CloseAccountRequest.daml create mode 100644 src/daml/Daml/Finance/App/Interface/Custody/DepositRequest.daml create mode 100644 src/daml/Daml/Finance/App/Interface/Custody/OpenAccountRequest.daml create mode 100644 src/daml/Daml/Finance/App/Interface/Custody/Service.daml create mode 100644 src/daml/Daml/Finance/App/Interface/Custody/WithdrawRequest.daml diff --git a/src/daml/Daml/Finance/App/Interface/Custody/CloseAccountRequest.daml b/src/daml/Daml/Finance/App/Interface/Custody/CloseAccountRequest.daml new file mode 100644 index 00000000..833dc94f --- /dev/null +++ b/src/daml/Daml/Finance/App/Interface/Custody/CloseAccountRequest.daml @@ -0,0 +1,26 @@ +-- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +-- SPDX-License-Identifier: Apache-2.0 + +module Daml.Finance.App.Interface.Custody.CloseAccountRequest where + +import Daml.Finance.Interface.Types.Common (AccountKey) + +type I = CloseAccountRequest + +type V = View + +data View = View + with + operator : Party + provider : Party + customer : Party + account : AccountKey + deriving (Eq, Show) + +interface CloseAccountRequest where + viewtype View + +-- | Type constraint for requiring templates to implement `CloseAccountRequest`. +type Implementation t = HasToInterface t CloseAccountRequest +class (Implementation t) => HasImplementation t +instance HasImplementation CloseAccountRequest diff --git a/src/daml/Daml/Finance/App/Interface/Custody/DepositRequest.daml b/src/daml/Daml/Finance/App/Interface/Custody/DepositRequest.daml new file mode 100644 index 00000000..03357604 --- /dev/null +++ b/src/daml/Daml/Finance/App/Interface/Custody/DepositRequest.daml @@ -0,0 +1,38 @@ +-- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +-- SPDX-License-Identifier: Apache-2.0 + +module Daml.Finance.App.Interface.Custody.DepositRequest where + +import Daml.Finance.Interface.Holding.Base qualified as Holding (I) +import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (Q) +import Daml.Finance.Interface.Types.Common (AccountKey) + +type I = DepositRequest + +type V = View + +data View = View + with + operator : Party + provider : Party + customer : Party + quantity : Instrument.Q + account : AccountKey + deriving (Eq, Show) + +interface DepositRequest where + viewtype View + +template WithdrawalRequest + with + operator : Party + provider : Party + customer : Party + holdingCid : ContractId Holding.I + where + signatory operator, provider, customer + +-- | Type constraint for requiring templates to implement `Service`. +type Implementation t = HasToInterface t DepositRequest +class (Implementation t) => HasImplementation t +instance HasImplementation DepositRequest diff --git a/src/daml/Daml/Finance/App/Interface/Custody/OpenAccountRequest.daml b/src/daml/Daml/Finance/App/Interface/Custody/OpenAccountRequest.daml new file mode 100644 index 00000000..e90726bb --- /dev/null +++ b/src/daml/Daml/Finance/App/Interface/Custody/OpenAccountRequest.daml @@ -0,0 +1,30 @@ +-- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +-- SPDX-License-Identifier: Apache-2.0 + +module Daml.Finance.App.Interface.Custody.OpenAccountRequest where + +import Daml.Finance.Interface.Account.Account qualified as Account (Controllers) +import Daml.Finance.Interface.Types.Common (Id, PartiesMap) + +type I = OpenAccountRequest + +type V = View + +data View = View + with + operator : Party + provider : Party + customer : Party + id : Id + description : Text + controllers : Account.Controllers + observers : PartiesMap + deriving (Eq, Show) + +interface OpenAccountRequest where + viewtype View + +-- | Type constraint for requiring templates to implement `CloseAccountRequest`. +type Implementation t = HasToInterface t OpenAccountRequest +class (Implementation t) => HasImplementation t +instance HasImplementation OpenAccountRequest diff --git a/src/daml/Daml/Finance/App/Interface/Custody/Service.daml b/src/daml/Daml/Finance/App/Interface/Custody/Service.daml new file mode 100644 index 00000000..788285d6 --- /dev/null +++ b/src/daml/Daml/Finance/App/Interface/Custody/Service.daml @@ -0,0 +1,116 @@ +-- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +-- SPDX-License-Identifier: Apache-2.0 + +module Daml.Finance.App.Interface.Custody.Service where + +import Daml.Finance.Interface.Account.Account qualified as Account (Controllers) +import Daml.Finance.Interface.Account.Factory qualified as Account (F) +import Daml.Finance.Interface.Holding.Factory qualified as Holding (F) +import Daml.Finance.Interface.Holding.Base qualified as Holding (I) +import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (K, Q) +import Daml.Finance.Interface.Lifecycle.Rule.Claim qualified as Lifecycle (Claim) +import Daml.Finance.Interface.Types.Common (AccountKey, Id, PartiesMap) +import Daml.Finance.App.Interface.Base.Service qualified as Base (I) +import Daml.Finance.App.Interface.Custody.OpenAccountRequest qualified as OpenAccountRequest (I) +import Daml.Finance.App.Interface.Custody.CloseAccountRequest qualified as CloseAccountRequest (I) +import Daml.Finance.App.Interface.Custody.DepositRequest qualified as DepositRequest (I) +import Daml.Finance.App.Interface.Custody.WithdrawRequest qualified as WithdrawRequest (I) + +type I = Service + +type V = View + +data View = View + with + claimRuleCid : ContractId Lifecycle.Claim + accountFactoryCid : ContractId Account.F + holdingFactoryCid : ContractId Holding.F + deriving (Eq, Show) + +interface Service where + viewtype V + + asBase : Base.I + -- ^ Conversion to base `Service` interface. + requestOpenAccount : RequestOpenAccount -> Update (ContractId OpenAccountRequest.I) + -- ^ Implementation of the `RequestOpenAccount` choice. + requestCloseAccount : RequestCloseAccount -> Update (ContractId CloseAccountRequest.I) + -- ^ Implementation of the `RequestCloseAccount` choice. + requestDeposit : RequestDeposit -> Update (ContractId DepositRequest.I) + -- ^ Implementation of the `RequestDeposit` choice. + requestWithdrawal : RequestWithdrawal -> Update (ContractId WithdrawRequest.I) + -- ^ Implementation of the `RequestWithdrawal` choice. + openAccount : OpenAccount -> Update AccountKey + -- ^ Implementation of the `OpenAccount` choice. + closeAccount : CloseAccount -> Update () + -- ^ Implementation of the `CloseAccount` choice. + deposit : Deposit -> Update (ContractId Holding.I) + -- ^ Implementation of the `Deposit` choice. + withdraw : Withdraw -> Update () + -- ^ Implementation of the `Withdraw` choice. + + nonconsuming choice RequestOpenAccount : ContractId OpenAccountRequest.I + with + id : Id + description : Text + controllers : Account.Controllers + observers : PartiesMap + controller (view $ asBase this).customer + do + requestOpenAccount this arg + + nonconsuming choice RequestCloseAccount : ContractId CloseAccountRequest.I + with + account : AccountKey + controller (view $ asBase this).customer + do + requestCloseAccount this arg + + nonconsuming choice RequestDeposit : ContractId DepositRequest.I + with + quantity : Instrument.Q + account : AccountKey + controller (view $ asBase this).customer + do + requestDeposit this arg + + nonconsuming choice RequestWithdrawal : ContractId WithdrawRequest.I + with + instrument : Instrument.K + holdingCid : ContractId Holding.I + controller (view $ asBase this).customer + do + requestWithdrawal this arg + + nonconsuming choice OpenAccount : AccountKey + with + openAccountRequestCid : ContractId OpenAccountRequest.I + controller (view $ asBase this).provider + do + openAccount this arg + + nonconsuming choice CloseAccount : () + with + closeAccountRequestCid : ContractId CloseAccountRequest.I + controller (view $ asBase this).provider + do + closeAccount this arg + + nonconsuming choice Deposit : ContractId Holding.I + with + depositRequestCid : ContractId DepositRequest.I + controller (view $ asBase this).provider + do + deposit this arg + + nonconsuming choice Withdraw : () + with + withdrawRequestCid : ContractId WithdrawRequest.I + controller (view $ asBase this).provider + do + withdraw this arg + +-- | Type constraint for requiring templates to implement `Service`. +type Implementation t = HasToInterface t Service +class (Implementation t) => HasImplementation t +instance HasImplementation Service diff --git a/src/daml/Daml/Finance/App/Interface/Custody/WithdrawRequest.daml b/src/daml/Daml/Finance/App/Interface/Custody/WithdrawRequest.daml new file mode 100644 index 00000000..d64c15d2 --- /dev/null +++ b/src/daml/Daml/Finance/App/Interface/Custody/WithdrawRequest.daml @@ -0,0 +1,26 @@ +-- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +-- SPDX-License-Identifier: Apache-2.0 + +module Daml.Finance.App.Interface.Custody.WithdrawRequest where + +import Daml.Finance.Interface.Holding.Base qualified as Holding (I) + +type I = WithdrawRequest + +type V = View + +data View = View + with + operator : Party + provider : Party + customer : Party + holdingCid : ContractId Holding.I + deriving (Eq, Show) + +interface WithdrawRequest where + viewtype View + +-- | Type constraint for requiring templates to implement `Service`. +type Implementation t = HasToInterface t WithdrawRequest +class (Implementation t) => HasImplementation t +instance HasImplementation WithdrawRequest From 8ccd9d2aebe8db8748d0d137ec5aa6f3f9495d76 Mon Sep 17 00:00:00 2001 From: Georg Schneider Date: Tue, 13 Dec 2022 20:12:17 +0100 Subject: [PATCH 03/31] Implement custody service interfaces --- src/daml/Daml/Finance/App/Custody/Model.daml | 54 ++++++++ .../Daml/Finance/App/Custody/Service.daml | 128 ++++++++---------- .../App/Interface/Common/Removable.daml | 28 ++++ .../Finance/App/Interface/Common/Util.daml | 13 ++ .../Custody/CloseAccountRequest.daml | 7 +- .../App/Interface/Custody/DepositRequest.daml | 19 +-- .../Interface/Custody/OpenAccountRequest.daml | 9 +- .../Interface/Custody/WithdrawRequest.daml | 7 +- 8 files changed, 180 insertions(+), 85 deletions(-) create mode 100644 src/daml/Daml/Finance/App/Interface/Common/Removable.daml create mode 100644 src/daml/Daml/Finance/App/Interface/Common/Util.daml diff --git a/src/daml/Daml/Finance/App/Custody/Model.daml b/src/daml/Daml/Finance/App/Custody/Model.daml index 11d75566..c7fe482d 100644 --- a/src/daml/Daml/Finance/App/Custody/Model.daml +++ b/src/daml/Daml/Finance/App/Custody/Model.daml @@ -3,6 +3,12 @@ module Daml.Finance.App.Custody.Model where +import DA.Set (fromList) +import Daml.Finance.App.Interface.Common.Removable qualified as Removable (I, View(..)) +import Daml.Finance.App.Interface.Custody.OpenAccountRequest qualified as OpenAccountRequest (I, View(..)) +import Daml.Finance.App.Interface.Custody.CloseAccountRequest qualified as CloseAccountRequest (I, View(..)) +import Daml.Finance.App.Interface.Custody.DepositRequest qualified as DepositRequest (I, View(..)) +import Daml.Finance.App.Interface.Custody.WithdrawRequest qualified as WithdrawalRequest (I, View(..)) import Daml.Finance.Interface.Account.Account qualified as Account (Controllers, K) import Daml.Finance.Interface.Holding.Base qualified as Holding (I) import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (Q) @@ -20,6 +26,20 @@ template OpenAccountRequest where signatory operator, provider, customer + interface instance Removable.I for OpenAccountRequest where + view = Removable.View with removers = fromList [operator, provider, customer] + + interface instance OpenAccountRequest.I for OpenAccountRequest where + view = OpenAccountRequest.View with + operator + provider + customer + id + description + controllers + observers + asRemovable = toInterface @Removable.I this + template CloseAccountRequest with operator : Party @@ -29,6 +49,17 @@ template CloseAccountRequest where signatory operator, provider, customer + interface instance Removable.I for CloseAccountRequest where + view = Removable.View with removers = fromList [operator, provider, customer] + + interface instance CloseAccountRequest.I for CloseAccountRequest where + view = CloseAccountRequest.View with + operator + provider + customer + account + asRemovable = toInterface @Removable.I this + template DepositRequest with operator : Party @@ -39,6 +70,18 @@ template DepositRequest where signatory operator, provider, customer + interface instance Removable.I for DepositRequest where + view = Removable.View with removers = fromList [operator, provider, customer] + + interface instance DepositRequest.I for DepositRequest where + view = DepositRequest.View with + operator + provider + customer + quantity + account + asRemovable = toInterface @Removable.I this + template WithdrawalRequest with operator : Party @@ -47,3 +90,14 @@ template WithdrawalRequest holdingCid : ContractId Holding.I where signatory operator, provider, customer + + interface instance Removable.I for WithdrawalRequest where + view = Removable.View with removers = fromList [operator, provider, customer] + + interface instance WithdrawalRequest.I for WithdrawalRequest where + view = WithdrawalRequest.View with + operator + provider + customer + holdingCid + asRemovable = toInterface @Removable.I this diff --git a/src/daml/Daml/Finance/App/Custody/Service.daml b/src/daml/Daml/Finance/App/Custody/Service.daml index 91e28c80..390904e9 100644 --- a/src/daml/Daml/Finance/App/Custody/Service.daml +++ b/src/daml/Daml/Finance/App/Custody/Service.daml @@ -3,16 +3,21 @@ module Daml.Finance.App.Custody.Service where -import Daml.Finance.Interface.Account.Account qualified as Account (Controllers, Credit(..), Debit(..), K, R) +import DA.Assert ((===)) +import Daml.Finance.App.Interface.Common.Util (fetchAndRemove) +import Daml.Finance.App.Interface.Custody.OpenAccountRequest qualified as OpenAccountRequest (View(..)) +import Daml.Finance.App.Interface.Custody.CloseAccountRequest qualified as CloseAccountRequest (View(..)) +import Daml.Finance.App.Interface.Custody.DepositRequest qualified as DepositRequest (View(..)) +import Daml.Finance.App.Interface.Custody.WithdrawRequest qualified as WithdrawalRequest (View(..)) +import Daml.Finance.Interface.Account.Account qualified as Account (Credit(..), Debit(..), I, exerciseInterfaceByKey) import Daml.Finance.Interface.Account.Factory qualified as Account (F, Create(..), Remove(..)) import Daml.Finance.Interface.Holding.Factory qualified as Holding (F) -import Daml.Finance.Interface.Holding.Base qualified as Holding (I) import Daml.Finance.Interface.Account.Util (getAccount) -import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (K, Q) import Daml.Finance.Interface.Lifecycle.Rule.Claim qualified as Lifecycle (Claim) -import Daml.Finance.Interface.Types.Common (AccountKey(..), Id, PartiesMap) +import Daml.Finance.Interface.Types.Common (AccountKey(..)) +import Daml.Finance.App.Interface.Base.Service qualified as Base (I, View(..)) +import Daml.Finance.App.Interface.Custody.Service qualified as Service import Daml.Finance.App.Custody.Model qualified as Custody -import Daml.Finance.App.Util (fetchAndArchive) template Service with @@ -28,76 +33,61 @@ template Service key (operator, provider, customer) : (Party, Party, Party) maintainer key._1 - nonconsuming choice RequestOpenAccount : ContractId Custody.OpenAccountRequest - with - id : Id - description : Text - controllers : Account.Controllers - observers : PartiesMap - controller customer - do - create Custody.OpenAccountRequest with .. - - nonconsuming choice RequestCloseAccount : ContractId Custody.CloseAccountRequest - with - account : Account.K - controller customer - do - create Custody.CloseAccountRequest with .. - - nonconsuming choice RequestDeposit : ContractId Custody.DepositRequest - with - quantity : Instrument.Q - account : Account.K - controller customer - do - create Custody.DepositRequest with .. - - nonconsuming choice RequestWithdrawal : ContractId Custody.WithdrawalRequest - with - instrument : Instrument.K - holdingCid : ContractId Holding.I - controller customer - do - create Custody.WithdrawalRequest with .. - - nonconsuming choice OpenAccount : Account.K - with - openAccountRequestCid : ContractId Custody.OpenAccountRequest - controller provider - do - Custody.OpenAccountRequest{id; description; controllers; observers} <- fetchAndArchive openAccountRequestCid + interface instance Base.I for Service where + view = Base.View with operator; provider; customer + terminate = pure () + + interface instance Service.I for Service where + view = Service.View with claimRuleCid; accountFactoryCid; holdingFactoryCid + asBase = toInterface @Base.I this + requestOpenAccount Service.RequestOpenAccount{id; description; controllers; observers} = do + toInterfaceContractId <$> create Custody.OpenAccountRequest with + operator + provider + customer + id + description + controllers + observers + requestCloseAccount Service.RequestCloseAccount{account} = do + toInterfaceContractId <$> create Custody.CloseAccountRequest with + operator + provider + customer + account + requestDeposit Service.RequestDeposit{quantity; account} = do + toInterfaceContractId <$> create Custody.DepositRequest with + operator + provider + customer + quantity + account + requestWithdrawal Service.RequestWithdrawal{holdingCid} = do + toInterfaceContractId <$> create Custody.WithdrawalRequest with + operator + provider + customer + holdingCid + openAccount Service.OpenAccount{openAccountRequestCid} = do + OpenAccountRequest.View{id; description; controllers; observers} <- view <$> fetchAndRemove openAccountRequestCid let account = AccountKey with custodian = provider; owner = customer; id exercise accountFactoryCid Account.Create with account; description; controllers; holdingFactoryCid; observers pure account - - nonconsuming choice CloseAccount : () - with - closeAccountRequestCid : ContractId Custody.CloseAccountRequest - controller provider - do - Custody.CloseAccountRequest{account} <- fetchAndArchive closeAccountRequestCid + closeAccount Service.CloseAccount{closeAccountRequestCid} = do + CloseAccountRequest.View{account} <- view <$> fetchAndRemove closeAccountRequestCid exercise accountFactoryCid Account.Remove with account - - nonconsuming choice Deposit : ContractId Holding.I - with - depositRequestCid : ContractId Custody.DepositRequest - controller provider - do - Custody.DepositRequest{quantity; account} <- fetchAndArchive depositRequestCid - (_, ref) <- fetchByKey @Account.R account - exercise ref.cid Account.Credit with quantity - - nonconsuming choice Withdrawal : () - with - withdrawalRequestCid : ContractId Custody.WithdrawalRequest - controller provider - do - Custody.WithdrawalRequest{holdingCid} <- fetchAndArchive withdrawalRequestCid + deposit Service.Deposit{depositRequestCid} = do + DepositRequest.View{quantity; account} <- view <$> fetchAndRemove depositRequestCid + account.custodian === provider + account.owner === customer + Account.exerciseInterfaceByKey @Account.I account provider Account.Credit with quantity + withdraw Service.Withdraw{withdrawRequestCid} = do + WithdrawalRequest.View{holdingCid} <- view <$> fetchAndRemove withdrawRequestCid holding <- fetch holdingCid let account = getAccount holding - (_, ref) <- fetchByKey @Account.R account - exercise ref.cid Account.Debit with holdingCid + account.custodian === provider + account.owner === customer + Account.exerciseInterfaceByKey @Account.I account provider Account.Debit with holdingCid choice Terminate : () with diff --git a/src/daml/Daml/Finance/App/Interface/Common/Removable.daml b/src/daml/Daml/Finance/App/Interface/Common/Removable.daml new file mode 100644 index 00000000..941b2ada --- /dev/null +++ b/src/daml/Daml/Finance/App/Interface/Common/Removable.daml @@ -0,0 +1,28 @@ +-- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +-- SPDX-License-Identifier: Apache-2.0 + +module Daml.Finance.App.Interface.Common.Removable where + +import Daml.Finance.Interface.Types.Common (Parties) + +type I = Removable + +type V = View + +data View = View + with + removers : Parties + deriving (Eq, Show) + +interface Removable where + viewtype V + + choice Remove : () + controller (view this).removers + do + pure () + +-- | Type constraint for requiring templates to implement `Removable`. +type Implementation t = HasToInterface t Removable +class (Implementation t) => HasImplementation t +instance HasImplementation Removable diff --git a/src/daml/Daml/Finance/App/Interface/Common/Util.daml b/src/daml/Daml/Finance/App/Interface/Common/Util.daml new file mode 100644 index 00000000..99a4cb0c --- /dev/null +++ b/src/daml/Daml/Finance/App/Interface/Common/Util.daml @@ -0,0 +1,13 @@ +-- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +-- SPDX-License-Identifier: Apache-2.0 + +module Daml.Finance.App.Interface.Common.Util where + +import Daml.Finance.App.Interface.Common.Removable qualified as Removable (I, Remove(..)) + +-- | Fetches a contract, removes it and returns its value. +fetchAndRemove : (HasFetch a, HasToInterface a Removable.I) => ContractId a -> Update a +fetchAndRemove cid = do + c <- fetch cid + exercise (toInterfaceContractId @Removable.I cid) Removable.Remove + return c diff --git a/src/daml/Daml/Finance/App/Interface/Custody/CloseAccountRequest.daml b/src/daml/Daml/Finance/App/Interface/Custody/CloseAccountRequest.daml index 833dc94f..aab010b7 100644 --- a/src/daml/Daml/Finance/App/Interface/Custody/CloseAccountRequest.daml +++ b/src/daml/Daml/Finance/App/Interface/Custody/CloseAccountRequest.daml @@ -3,6 +3,7 @@ module Daml.Finance.App.Interface.Custody.CloseAccountRequest where +import Daml.Finance.App.Interface.Common.Removable qualified as Removable (I, Implementation) import Daml.Finance.Interface.Types.Common (AccountKey) type I = CloseAccountRequest @@ -19,8 +20,12 @@ data View = View interface CloseAccountRequest where viewtype View + -- ^ Interface view types. + asRemovable : Removable.I + -- ^ Conversion to the `Removable` interface. -- | Type constraint for requiring templates to implement `CloseAccountRequest`. -type Implementation t = HasToInterface t CloseAccountRequest +type Implementation t = (HasToInterface t CloseAccountRequest, Removable.Implementation t) class (Implementation t) => HasImplementation t instance HasImplementation CloseAccountRequest +instance HasToInterface CloseAccountRequest Removable.I where _toInterface = asRemovable diff --git a/src/daml/Daml/Finance/App/Interface/Custody/DepositRequest.daml b/src/daml/Daml/Finance/App/Interface/Custody/DepositRequest.daml index 03357604..d5258e06 100644 --- a/src/daml/Daml/Finance/App/Interface/Custody/DepositRequest.daml +++ b/src/daml/Daml/Finance/App/Interface/Custody/DepositRequest.daml @@ -3,7 +3,7 @@ module Daml.Finance.App.Interface.Custody.DepositRequest where -import Daml.Finance.Interface.Holding.Base qualified as Holding (I) +import Daml.Finance.App.Interface.Common.Removable qualified as Removable (I, Implementation) import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (Q) import Daml.Finance.Interface.Types.Common (AccountKey) @@ -22,17 +22,12 @@ data View = View interface DepositRequest where viewtype View + -- ^ Interface view types. + asRemovable : Removable.I + -- ^ Conversion to the `Removable` interface. -template WithdrawalRequest - with - operator : Party - provider : Party - customer : Party - holdingCid : ContractId Holding.I - where - signatory operator, provider, customer - --- | Type constraint for requiring templates to implement `Service`. -type Implementation t = HasToInterface t DepositRequest +-- | Type constraint for requiring templates to implement `DepositRequest`. +type Implementation t = (HasToInterface t DepositRequest, Removable.Implementation t) class (Implementation t) => HasImplementation t instance HasImplementation DepositRequest +instance HasToInterface DepositRequest Removable.I where _toInterface = asRemovable diff --git a/src/daml/Daml/Finance/App/Interface/Custody/OpenAccountRequest.daml b/src/daml/Daml/Finance/App/Interface/Custody/OpenAccountRequest.daml index e90726bb..29912c79 100644 --- a/src/daml/Daml/Finance/App/Interface/Custody/OpenAccountRequest.daml +++ b/src/daml/Daml/Finance/App/Interface/Custody/OpenAccountRequest.daml @@ -3,6 +3,7 @@ module Daml.Finance.App.Interface.Custody.OpenAccountRequest where +import Daml.Finance.App.Interface.Common.Removable qualified as Removable (I, Implementation) import Daml.Finance.Interface.Account.Account qualified as Account (Controllers) import Daml.Finance.Interface.Types.Common (Id, PartiesMap) @@ -23,8 +24,12 @@ data View = View interface OpenAccountRequest where viewtype View + -- ^ Interface view types. + asRemovable : Removable.I + -- ^ Conversion to the `Removable` interface. --- | Type constraint for requiring templates to implement `CloseAccountRequest`. -type Implementation t = HasToInterface t OpenAccountRequest +-- | Type constraint for requiring templates to implement `OpenAccountRequest`. +type Implementation t = (HasToInterface t OpenAccountRequest, Removable.Implementation t) class (Implementation t) => HasImplementation t instance HasImplementation OpenAccountRequest +instance HasToInterface OpenAccountRequest Removable.I where _toInterface = asRemovable diff --git a/src/daml/Daml/Finance/App/Interface/Custody/WithdrawRequest.daml b/src/daml/Daml/Finance/App/Interface/Custody/WithdrawRequest.daml index d64c15d2..3c21bb01 100644 --- a/src/daml/Daml/Finance/App/Interface/Custody/WithdrawRequest.daml +++ b/src/daml/Daml/Finance/App/Interface/Custody/WithdrawRequest.daml @@ -3,6 +3,7 @@ module Daml.Finance.App.Interface.Custody.WithdrawRequest where +import Daml.Finance.App.Interface.Common.Removable qualified as Removable (I, Implementation) import Daml.Finance.Interface.Holding.Base qualified as Holding (I) type I = WithdrawRequest @@ -19,8 +20,12 @@ data View = View interface WithdrawRequest where viewtype View + -- ^ Interface view types. + asRemovable : Removable.I + -- ^ Conversion to the `Removable` interface. -- | Type constraint for requiring templates to implement `Service`. -type Implementation t = HasToInterface t WithdrawRequest +type Implementation t = (HasToInterface t WithdrawRequest, Removable.Implementation t) class (Implementation t) => HasImplementation t instance HasImplementation WithdrawRequest +instance HasToInterface WithdrawRequest Removable.I where _toInterface = asRemovable From 25f95bbcd638dc1d3cfecc23678a11730ffc4bcc Mon Sep 17 00:00:00 2001 From: Georg Schneider Date: Tue, 13 Dec 2022 22:05:21 +0100 Subject: [PATCH 04/31] Add interfaces for custody auto service --- src/daml/Daml/Finance/App/Custody/Auto.daml | 140 ++++++++++++++++++ .../Finance/App/Custody/Auto/Service.daml | 111 -------------- src/daml/Daml/Finance/App/Custody/Model.daml | 10 +- .../Daml/Finance/App/Custody/Service.daml | 48 ++---- .../Finance/App/Interface/Custody/Auto.daml | 72 +++++++++ .../App/Interface/Custody/Service.daml | 24 +-- .../Daml/Finance/Setup/Util/Workflow.daml | 21 +-- 7 files changed, 256 insertions(+), 170 deletions(-) create mode 100644 src/daml/Daml/Finance/App/Custody/Auto.daml delete mode 100644 src/daml/Daml/Finance/App/Custody/Auto/Service.daml create mode 100644 src/daml/Daml/Finance/App/Interface/Custody/Auto.daml diff --git a/src/daml/Daml/Finance/App/Custody/Auto.daml b/src/daml/Daml/Finance/App/Custody/Auto.daml new file mode 100644 index 00000000..31d0a55c --- /dev/null +++ b/src/daml/Daml/Finance/App/Custody/Auto.daml @@ -0,0 +1,140 @@ +-- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +-- SPDX-License-Identifier: Apache-2.0 + +module Daml.Finance.App.Custody.Auto where + +import DA.Assert ((===)) +import Daml.Finance.App.Custody.Model qualified as Model +import Daml.Finance.App.Interface.Base.Service qualified as Base (I, View(..)) +import Daml.Finance.App.Interface.Common.Util (fetchAndRemove) +import Daml.Finance.App.Interface.Custody.Auto qualified as Auto (HasImplementation, I, View(..), RequestAndCloseAccount(..), RequestAndDeposit(..), RequestAndOpenAccount(..), RequestAndWithdraw(..)) +import Daml.Finance.App.Interface.Custody.CloseAccountRequest qualified as CloseAccountRequest (View(..)) +import Daml.Finance.App.Interface.Custody.DepositRequest qualified as DepositRequest (View(..)) +import Daml.Finance.App.Interface.Custody.OpenAccountRequest qualified as OpenAccountRequest (View(..)) +import Daml.Finance.App.Interface.Custody.WithdrawRequest qualified as WithdrawRequest (View(..)) +import Daml.Finance.App.Interface.Custody.Service qualified as Service (CloseAccount(..), Deposit(..), I, OpenAccount(..), RequestCloseAccount(..), RequestDeposit(..), RequestOpenAccount(..), RequestWithdraw(..), View(..), Withdraw(..)) +import Daml.Finance.Interface.Account.Account qualified as Account (Credit(..), Debit(..), I, exerciseInterfaceByKey) +import Daml.Finance.Interface.Account.Factory qualified as Account (Create(..), F, Remove(..)) +import Daml.Finance.Interface.Account.Util (getAccount) +import Daml.Finance.Interface.Holding.Factory qualified as Holding (F) +import Daml.Finance.Interface.Lifecycle.Rule.Claim qualified as Lifecycle (Claim) +import Daml.Finance.Interface.Types.Common (AccountKey(..)) + +instance Auto.HasImplementation Service + +template Service + with + operator : Party + provider : Party + customer : Party + claimRuleCid : ContractId Lifecycle.Claim + accountFactoryCid : ContractId Account.F + holdingFactoryCid : ContractId Holding.F + where + signatory operator, provider, customer + + key (operator, provider, customer) : (Party, Party, Party) + maintainer key._1 + + interface instance Base.I for Service where + view = Base.View with operator; provider; customer + terminate = pure () + + interface instance Service.I for Service where + view = Service.View with claimRuleCid; accountFactoryCid; holdingFactoryCid + asBase = toInterface @Base.I this + requestOpenAccount Service.RequestOpenAccount{id; description; controllers; observers} = do + toInterfaceContractId <$> create Model.OpenAccountRequest with operator; provider; customer; id; description; controllers; observers + requestCloseAccount Service.RequestCloseAccount{account} = do + toInterfaceContractId <$> create Model.CloseAccountRequest with operator; provider; customer; account + requestDeposit Service.RequestDeposit{quantity; account} = do + toInterfaceContractId <$> create Model.DepositRequest with operator; provider; customer; quantity; account + requestWithdraw Service.RequestWithdraw{holdingCid} = do + toInterfaceContractId <$> create Model.WithdrawRequest with operator; provider; customer; holdingCid + openAccount Service.OpenAccount{openAccountRequestCid} = do + OpenAccountRequest.View{id; description; controllers; observers} <- view <$> fetchAndRemove openAccountRequestCid + let account = AccountKey with custodian = provider; owner = customer; id + accountCid <- exercise accountFactoryCid Account.Create with account; description; controllers; holdingFactoryCid; observers + pure (accountCid, account) + closeAccount Service.CloseAccount{closeAccountRequestCid} = do + CloseAccountRequest.View{account} <- view <$> fetchAndRemove closeAccountRequestCid + exercise accountFactoryCid Account.Remove with account + deposit Service.Deposit{depositRequestCid} = do + DepositRequest.View{quantity; account} <- view <$> fetchAndRemove depositRequestCid + account.custodian === provider + account.owner === customer + Account.exerciseInterfaceByKey @Account.I account provider Account.Credit with quantity + withdraw Service.Withdraw{withdrawRequestCid} = do + WithdrawRequest.View{holdingCid} <- view <$> fetchAndRemove withdrawRequestCid + holding <- fetch holdingCid + let account = getAccount holding + account.custodian === provider + account.owner === customer + Account.exerciseInterfaceByKey @Account.I account provider Account.Debit with holdingCid + + interface instance Auto.I for Service where + view = Auto.View + asService = toInterface @Service.I this + requestAndOpenAccount self Auto.RequestAndOpenAccount{id; description; controllers; observers} = do + openAccountRequestCid <- exercise self Service.RequestOpenAccount with id; description; controllers; observers + exercise self Service.OpenAccount with openAccountRequestCid + requestAndCloseAccount self Auto.RequestAndCloseAccount{account} = do + closeAccountRequestCid <- exercise self Service.RequestCloseAccount with account + exercise self Service.CloseAccount with closeAccountRequestCid + requestAndDeposit self Auto.RequestAndDeposit{account; quantity} = do + depositRequestCid <- exercise self Service.RequestDeposit with quantity; account + exercise self Service.Deposit with depositRequestCid + requestAndWithdraw self Auto.RequestAndWithdraw{holdingCid} = do + withdrawRequestCid <- exercise self Service.RequestWithdraw with holdingCid + exercise self Service.Withdraw with withdrawRequestCid + +template Offer + with + operator : Party + provider : Party + customer : Party + claimRuleCid : ContractId Lifecycle.Claim + accountFactoryCid : ContractId Account.F + holdingFactoryCid : ContractId Holding.F + where + signatory operator, provider + observer customer + + choice Accept : ContractId Service + controller customer + do + create Service with operator; provider; customer; claimRuleCid; accountFactoryCid; holdingFactoryCid + + choice Decline : () + controller customer + do pure () + + choice Withdraw : () + controller provider + do pure () + +template Request + with + customer : Party + provider : Party + where + signatory customer + observer provider + + choice Cancel : () + controller customer + do pure () + + choice Reject : () + controller provider + do pure () + + choice Approve : ContractId Service + with + operator : Party + claimRuleCid : ContractId Lifecycle.Claim + accountFactoryCid : ContractId Account.F + holdingFactoryCid : ContractId Holding.F + controller operator, provider + do + create Service with operator; provider; customer; claimRuleCid; accountFactoryCid; holdingFactoryCid diff --git a/src/daml/Daml/Finance/App/Custody/Auto/Service.daml b/src/daml/Daml/Finance/App/Custody/Auto/Service.daml deleted file mode 100644 index fa900337..00000000 --- a/src/daml/Daml/Finance/App/Custody/Auto/Service.daml +++ /dev/null @@ -1,111 +0,0 @@ --- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. --- SPDX-License-Identifier: Apache-2.0 - -module Daml.Finance.App.Custody.Auto.Service where - -import Daml.Finance.Interface.Account.Account qualified as Account (Controllers, K) -import Daml.Finance.Interface.Holding.Base qualified as Holding (I) -import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (K, Q) -import Daml.Finance.Interface.Types.Common (Id, PartiesMap) -import Daml.Finance.App.Custody.Service qualified as S - -template Service - with - operator : Party - provider : Party - customer : Party - where - signatory operator, provider, customer - - key (operator, provider, customer) : (Party, Party, Party) - maintainer key._1 - - nonconsuming choice RequestAndOpenAccount : Account.K - with - id : Id - description : Text - controllers : Account.Controllers - observers : PartiesMap - controller customer - do - openAccountRequestCid <- exerciseByKey @S.Service (operator, provider, customer) S.RequestOpenAccount with id; description; controllers; observers - exerciseByKey @S.Service (operator, provider, customer) S.OpenAccount with openAccountRequestCid - - nonconsuming choice RequestAndCloseAccount : () - with - account : Account.K - controller customer - do - closeAccountRequestCid <- exerciseByKey @S.Service (operator, provider, customer) S.RequestCloseAccount with account - exerciseByKey @S.Service (operator, provider, customer) S.CloseAccount with closeAccountRequestCid - - nonconsuming choice RequestAndDeposit : ContractId Holding.I - with - quantity : Instrument.Q - account : Account.K - controller customer - do - depositRequestCid <- exerciseByKey @S.Service (operator, provider, customer) S.RequestDeposit with quantity; account - exerciseByKey @S.Service (operator, provider, customer) S.Deposit with depositRequestCid - - nonconsuming choice RequestAndWithdraw : () - with - instrument : Instrument.K - holdingCid : ContractId Holding.I - controller customer - do - withdrawalRequestCid <- exerciseByKey @S.Service (operator, provider, customer) S.RequestWithdrawal with instrument; holdingCid - exerciseByKey @S.Service (operator, provider, customer) S.Withdrawal with withdrawalRequestCid - - choice Terminate : () - with - actor : Party - controller actor - do - assert $ actor == operator || actor == provider || actor == customer - pure () - -template Offer - with - operator : Party - provider : Party - customer : Party - where - signatory operator, provider - observer customer - - choice Accept : ContractId Service - controller customer - do - create Service with operator; provider; customer - - choice Decline : () - controller customer - do pure () - - choice Withdraw : () - controller provider - do pure () - -template Request - with - customer : Party - provider : Party - where - signatory customer - observer provider - - choice Cancel : () - controller customer - do pure () - - choice Reject : () - controller provider - do pure () - - choice Approve : ContractId Service - with - operator : Party - controller operator, provider - do - create Service with operator; provider; customer \ No newline at end of file diff --git a/src/daml/Daml/Finance/App/Custody/Model.daml b/src/daml/Daml/Finance/App/Custody/Model.daml index c7fe482d..c62b75c2 100644 --- a/src/daml/Daml/Finance/App/Custody/Model.daml +++ b/src/daml/Daml/Finance/App/Custody/Model.daml @@ -8,7 +8,7 @@ import Daml.Finance.App.Interface.Common.Removable qualified as Removable (I, Vi import Daml.Finance.App.Interface.Custody.OpenAccountRequest qualified as OpenAccountRequest (I, View(..)) import Daml.Finance.App.Interface.Custody.CloseAccountRequest qualified as CloseAccountRequest (I, View(..)) import Daml.Finance.App.Interface.Custody.DepositRequest qualified as DepositRequest (I, View(..)) -import Daml.Finance.App.Interface.Custody.WithdrawRequest qualified as WithdrawalRequest (I, View(..)) +import Daml.Finance.App.Interface.Custody.WithdrawRequest qualified as WithdrawRequest (I, View(..)) import Daml.Finance.Interface.Account.Account qualified as Account (Controllers, K) import Daml.Finance.Interface.Holding.Base qualified as Holding (I) import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (Q) @@ -82,7 +82,7 @@ template DepositRequest account asRemovable = toInterface @Removable.I this -template WithdrawalRequest +template WithdrawRequest with operator : Party provider : Party @@ -91,11 +91,11 @@ template WithdrawalRequest where signatory operator, provider, customer - interface instance Removable.I for WithdrawalRequest where + interface instance Removable.I for WithdrawRequest where view = Removable.View with removers = fromList [operator, provider, customer] - interface instance WithdrawalRequest.I for WithdrawalRequest where - view = WithdrawalRequest.View with + interface instance WithdrawRequest.I for WithdrawRequest where + view = WithdrawRequest.View with operator provider customer diff --git a/src/daml/Daml/Finance/App/Custody/Service.daml b/src/daml/Daml/Finance/App/Custody/Service.daml index 390904e9..9feb2209 100644 --- a/src/daml/Daml/Finance/App/Custody/Service.daml +++ b/src/daml/Daml/Finance/App/Custody/Service.daml @@ -4,20 +4,22 @@ module Daml.Finance.App.Custody.Service where import DA.Assert ((===)) +import Daml.Finance.App.Custody.Model qualified as Model +import Daml.Finance.App.Interface.Base.Service qualified as Base (I, View(..)) import Daml.Finance.App.Interface.Common.Util (fetchAndRemove) -import Daml.Finance.App.Interface.Custody.OpenAccountRequest qualified as OpenAccountRequest (View(..)) import Daml.Finance.App.Interface.Custody.CloseAccountRequest qualified as CloseAccountRequest (View(..)) import Daml.Finance.App.Interface.Custody.DepositRequest qualified as DepositRequest (View(..)) -import Daml.Finance.App.Interface.Custody.WithdrawRequest qualified as WithdrawalRequest (View(..)) +import Daml.Finance.App.Interface.Custody.OpenAccountRequest qualified as OpenAccountRequest (View(..)) +import Daml.Finance.App.Interface.Custody.Service qualified as Service +import Daml.Finance.App.Interface.Custody.WithdrawRequest qualified as WithdrawRequest (View(..)) import Daml.Finance.Interface.Account.Account qualified as Account (Credit(..), Debit(..), I, exerciseInterfaceByKey) import Daml.Finance.Interface.Account.Factory qualified as Account (F, Create(..), Remove(..)) import Daml.Finance.Interface.Holding.Factory qualified as Holding (F) import Daml.Finance.Interface.Account.Util (getAccount) import Daml.Finance.Interface.Lifecycle.Rule.Claim qualified as Lifecycle (Claim) import Daml.Finance.Interface.Types.Common (AccountKey(..)) -import Daml.Finance.App.Interface.Base.Service qualified as Base (I, View(..)) -import Daml.Finance.App.Interface.Custody.Service qualified as Service -import Daml.Finance.App.Custody.Model qualified as Custody + +instance Service.HasImplementation Service template Service with @@ -41,38 +43,18 @@ template Service view = Service.View with claimRuleCid; accountFactoryCid; holdingFactoryCid asBase = toInterface @Base.I this requestOpenAccount Service.RequestOpenAccount{id; description; controllers; observers} = do - toInterfaceContractId <$> create Custody.OpenAccountRequest with - operator - provider - customer - id - description - controllers - observers + toInterfaceContractId <$> create Model.OpenAccountRequest with operator; provider; customer; id; description; controllers; observers requestCloseAccount Service.RequestCloseAccount{account} = do - toInterfaceContractId <$> create Custody.CloseAccountRequest with - operator - provider - customer - account + toInterfaceContractId <$> create Model.CloseAccountRequest with operator; provider; customer; account requestDeposit Service.RequestDeposit{quantity; account} = do - toInterfaceContractId <$> create Custody.DepositRequest with - operator - provider - customer - quantity - account - requestWithdrawal Service.RequestWithdrawal{holdingCid} = do - toInterfaceContractId <$> create Custody.WithdrawalRequest with - operator - provider - customer - holdingCid + toInterfaceContractId <$> create Model.DepositRequest with operator; provider; customer; quantity; account + requestWithdraw Service.RequestWithdraw{holdingCid} = do + toInterfaceContractId <$> create Model.WithdrawRequest with operator; provider; customer; holdingCid openAccount Service.OpenAccount{openAccountRequestCid} = do OpenAccountRequest.View{id; description; controllers; observers} <- view <$> fetchAndRemove openAccountRequestCid let account = AccountKey with custodian = provider; owner = customer; id - exercise accountFactoryCid Account.Create with account; description; controllers; holdingFactoryCid; observers - pure account + accountCid <- exercise accountFactoryCid Account.Create with account; description; controllers; holdingFactoryCid; observers + pure (accountCid, account) closeAccount Service.CloseAccount{closeAccountRequestCid} = do CloseAccountRequest.View{account} <- view <$> fetchAndRemove closeAccountRequestCid exercise accountFactoryCid Account.Remove with account @@ -82,7 +64,7 @@ template Service account.owner === customer Account.exerciseInterfaceByKey @Account.I account provider Account.Credit with quantity withdraw Service.Withdraw{withdrawRequestCid} = do - WithdrawalRequest.View{holdingCid} <- view <$> fetchAndRemove withdrawRequestCid + WithdrawRequest.View{holdingCid} <- view <$> fetchAndRemove withdrawRequestCid holding <- fetch holdingCid let account = getAccount holding account.custodian === provider diff --git a/src/daml/Daml/Finance/App/Interface/Custody/Auto.daml b/src/daml/Daml/Finance/App/Interface/Custody/Auto.daml new file mode 100644 index 00000000..6d2ab863 --- /dev/null +++ b/src/daml/Daml/Finance/App/Interface/Custody/Auto.daml @@ -0,0 +1,72 @@ +-- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +-- SPDX-License-Identifier: Apache-2.0 + +module Daml.Finance.App.Interface.Custody.Auto where + +import Daml.Finance.App.Interface.Base.Service qualified as Base (I) +import Daml.Finance.App.Interface.Custody.Service qualified as Service (I, Implementation, asBase) +import Daml.Finance.Interface.Account.Account qualified as Account (Controllers, I) +import Daml.Finance.Interface.Holding.Base qualified as Holding (I) +import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (K, Q) +import Daml.Finance.Interface.Types.Common (AccountKey, Id, PartiesMap) + +type I = Service + +type V = View + +data View = View {} + deriving (Eq, Show) + +interface Service where + viewtype V + + asService : Service.I + -- ^ Conversion to custody `Service` interface. + requestAndOpenAccount : ContractId Service.I -> RequestAndOpenAccount -> Update (ContractId Account.I, AccountKey) + -- ^ Implementation of the `RequestOpenAccount` choice. + requestAndCloseAccount : ContractId Service.I -> RequestAndCloseAccount -> Update () + -- ^ Implementation of the `RequestCloseAccount` choice. + requestAndDeposit : ContractId Service.I -> RequestAndDeposit -> Update (ContractId Holding.I) + -- ^ Implementation of the `RequestDeposit` choice. + requestAndWithdraw : ContractId Service.I -> RequestAndWithdraw -> Update () + -- ^ Implementation of the `RequestAndWithdraw` choice. + + nonconsuming choice RequestAndOpenAccount : (ContractId Account.I, AccountKey) + with + id : Id + description : Text + controllers : Account.Controllers + observers : PartiesMap + controller (view $ Service.asBase $ asService this).customer + do + requestAndOpenAccount this (toInterfaceContractId self) arg + + nonconsuming choice RequestAndCloseAccount : () + with + account : AccountKey + controller (view $ Service.asBase $ asService this).customer + do + requestAndCloseAccount this (toInterfaceContractId self) arg + + nonconsuming choice RequestAndDeposit : (ContractId Holding.I) + with + quantity : Instrument.Q + account : AccountKey + controller (view $ Service.asBase $ asService this).customer + do + requestAndDeposit this (toInterfaceContractId self) arg + + nonconsuming choice RequestAndWithdraw : () + with + instrument : Instrument.K + holdingCid : ContractId Holding.I + controller (view $ Service.asBase $ asService this).customer + do + requestAndWithdraw this (toInterfaceContractId self) arg + +-- | Type constraint for requiring templates to implement `Service`. +type Implementation t = (HasToInterface t Service, Service.Implementation t) +class (Implementation t) => HasImplementation t +instance HasImplementation Service +instance HasToInterface Service Service.I where _toInterface = asService +instance HasToInterface Service Base.I where _toInterface = Service.asBase . asService diff --git a/src/daml/Daml/Finance/App/Interface/Custody/Service.daml b/src/daml/Daml/Finance/App/Interface/Custody/Service.daml index 788285d6..184ceaa1 100644 --- a/src/daml/Daml/Finance/App/Interface/Custody/Service.daml +++ b/src/daml/Daml/Finance/App/Interface/Custody/Service.daml @@ -3,14 +3,14 @@ module Daml.Finance.App.Interface.Custody.Service where -import Daml.Finance.Interface.Account.Account qualified as Account (Controllers) +import Daml.Finance.Interface.Account.Account qualified as Account (Controllers, I) import Daml.Finance.Interface.Account.Factory qualified as Account (F) import Daml.Finance.Interface.Holding.Factory qualified as Holding (F) import Daml.Finance.Interface.Holding.Base qualified as Holding (I) -import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (K, Q) +import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (Q) import Daml.Finance.Interface.Lifecycle.Rule.Claim qualified as Lifecycle (Claim) import Daml.Finance.Interface.Types.Common (AccountKey, Id, PartiesMap) -import Daml.Finance.App.Interface.Base.Service qualified as Base (I) +import Daml.Finance.App.Interface.Base.Service qualified as Base (I, Implementation) import Daml.Finance.App.Interface.Custody.OpenAccountRequest qualified as OpenAccountRequest (I) import Daml.Finance.App.Interface.Custody.CloseAccountRequest qualified as CloseAccountRequest (I) import Daml.Finance.App.Interface.Custody.DepositRequest qualified as DepositRequest (I) @@ -31,16 +31,16 @@ interface Service where viewtype V asBase : Base.I - -- ^ Conversion to base `Service` interface. + -- ^ Conversion to base `Service` interface. requestOpenAccount : RequestOpenAccount -> Update (ContractId OpenAccountRequest.I) -- ^ Implementation of the `RequestOpenAccount` choice. requestCloseAccount : RequestCloseAccount -> Update (ContractId CloseAccountRequest.I) -- ^ Implementation of the `RequestCloseAccount` choice. requestDeposit : RequestDeposit -> Update (ContractId DepositRequest.I) -- ^ Implementation of the `RequestDeposit` choice. - requestWithdrawal : RequestWithdrawal -> Update (ContractId WithdrawRequest.I) - -- ^ Implementation of the `RequestWithdrawal` choice. - openAccount : OpenAccount -> Update AccountKey + requestWithdraw : RequestWithdraw -> Update (ContractId WithdrawRequest.I) + -- ^ Implementation of the `RequestWithdraw` choice. + openAccount : OpenAccount -> Update (ContractId Account.I, AccountKey) -- ^ Implementation of the `OpenAccount` choice. closeAccount : CloseAccount -> Update () -- ^ Implementation of the `CloseAccount` choice. @@ -74,15 +74,14 @@ interface Service where do requestDeposit this arg - nonconsuming choice RequestWithdrawal : ContractId WithdrawRequest.I + nonconsuming choice RequestWithdraw : ContractId WithdrawRequest.I with - instrument : Instrument.K holdingCid : ContractId Holding.I controller (view $ asBase this).customer do - requestWithdrawal this arg + requestWithdraw this arg - nonconsuming choice OpenAccount : AccountKey + nonconsuming choice OpenAccount : (ContractId Account.I, AccountKey) with openAccountRequestCid : ContractId OpenAccountRequest.I controller (view $ asBase this).provider @@ -111,6 +110,7 @@ interface Service where withdraw this arg -- | Type constraint for requiring templates to implement `Service`. -type Implementation t = HasToInterface t Service +type Implementation t = (HasToInterface t Service, Base.Implementation t) class (Implementation t) => HasImplementation t instance HasImplementation Service +instance HasToInterface Service Base.I where _toInterface = asBase diff --git a/src/daml/Daml/Finance/Setup/Util/Workflow.daml b/src/daml/Daml/Finance/Setup/Util/Workflow.daml index 3c1f508b..2b5ebc71 100644 --- a/src/daml/Daml/Finance/Setup/Util/Workflow.daml +++ b/src/daml/Daml/Finance/Setup/Util/Workflow.daml @@ -8,7 +8,7 @@ import DA.List (head) import DA.Map qualified as M (Map, fromList) import DA.Set (fromList, singleton) import DA.Text (parseInt) -import Daml.Finance.App.Custody.Service qualified as Custody (Deposit(..), OpenAccount(..), RequestDeposit(..), RequestOpenAccount(..), Service) +import Daml.Finance.App.Custody.Service qualified as Custody (Service) import Daml.Finance.App.Data.AccountDirectory (AccountDirectory(..)) import Daml.Finance.App.Distribution.Auction.Model qualified as Auction (T) import Daml.Finance.App.Distribution.Auction.Service qualified as Auction (CreateAuction(..), ProcessAuction(..), RequestCreateAuction(..), S) @@ -18,6 +18,7 @@ import Daml.Finance.App.Distribution.Fund.Model qualified as Fund (PooledInvestm import Daml.Finance.App.Distribution.Fund.Service qualified as Fund (FulfillPooledInvestmentRequest(..), PoolInvestmentRequests(..), S) import Daml.Finance.App.Distribution.Investment.Model qualified as Investment (InvestmentRequest) import Daml.Finance.App.Distribution.Investment.Service qualified as Investment (RequestInvestment(..), S) +import Daml.Finance.App.Interface.Custody.Service qualified as Custody (Deposit(..), I, OpenAccount(..), RequestDeposit(..), RequestOpenAccount(..)) import Daml.Finance.App.Issuance.Model qualified as Issuance (T) import Daml.Finance.App.Issuance.Service qualified as Issuance (CreateIssuance(..), RequestCreateIssuance(..), Service) import Daml.Finance.App.Lifecycle.Service qualified as Lifecycle (Service, DeclareDividend(..), DeclareStockSplit(..), DeclareReplacement(..)) @@ -51,7 +52,7 @@ import Daml.Finance.Interface.Settlement.Batch qualified as Batch (I) import Daml.Finance.Interface.Settlement.Factory qualified as SettlementFactory (I) import Daml.Finance.Interface.Settlement.Instruction qualified as Instruction (I, Allocate(..), Approve(..)) import Daml.Finance.Interface.Settlement.Types qualified as Settlement (Allocation, Approval) -import Daml.Finance.Interface.Types.Common (Id(..), Parties, PartiesMap) +import Daml.Finance.Interface.Types.Common (AccountKey, Id(..), Parties, PartiesMap) import Daml.Finance.Interface.Types.Date.Calendar (BusinessDayAdjustment(..), BusinessDayConventionEnum, HolidayCalendarData(..)) import Daml.Finance.Interface.Types.Date.DayCount (DayCountConventionEnum) import Daml.Finance.Interface.Types.Date.RollConvention (PeriodEnum, RollConventionEnum(..)) @@ -63,11 +64,12 @@ import Daml.Finance.Settlement.Instruction qualified as Instruction (T) import Daml.Finance.Setup.Util.Common (getHolding) import Daml.Script -createAccount : Party -> Party -> Party -> Party -> Text -> PartiesMap -> Script Account.K -createAccount operator custodian owner public id observers = do - let controllers = Account.Controllers with instructors = singleton owner; approvers = singleton owner - openAccountRequestCid <- submit owner do exerciseByKeyCmd @Custody.Service (operator, custodian, owner) Custody.RequestOpenAccount with id = Id id; description = id; controllers; observers - submitMulti [custodian] [public] do exerciseByKeyCmd @Custody.Service (operator, custodian, owner) Custody.OpenAccount with openAccountRequestCid +createAccount : Party -> Party -> Party -> Party -> Text -> PartiesMap -> Script AccountKey +createAccount operator provider customer public id observers = do + let controllers = Account.Controllers with instructors = singleton customer; approvers = singleton customer + Some (custodyServiceCid, _) <- queryContractKey @Custody.Service customer (operator, provider, customer) + openAccountRequestCid <- submit customer do exerciseCmd (toInterfaceContractId @Custody.I custodyServiceCid) Custody.RequestOpenAccount with id = Id id; description = id; controllers; observers + snd <$> submitMulti [provider] [public] do exerciseCmd (toInterfaceContractId @Custody.I custodyServiceCid) Custody.OpenAccount with openAccountRequestCid createAccountDirectory : Party -> [(Instrument.K, Account.K)] -> Parties -> Script (ContractId AccountDirectory) createAccountDirectory provider mapping observers = do @@ -189,8 +191,9 @@ transfer from toAccount public depositCid = do deposit : Party -> Party -> Party -> Party -> Instrument.Q -> Account.K -> Script (ContractId Holding.I) deposit operator provider customer public quantity account = do - depositRequestCid <- submit customer do exerciseByKeyCmd @Custody.Service (operator, provider, customer) Custody.RequestDeposit with quantity; account - submitMulti [provider] [public] do exerciseByKeyCmd @Custody.Service (operator, provider, customer) Custody.Deposit with depositRequestCid + Some (custodyServiceCid, _) <- queryContractKey @Custody.Service customer (operator, provider, customer) + depositRequestCid <- submit customer do exerciseCmd (toInterfaceContractId @Custody.I custodyServiceCid) Custody.RequestDeposit with quantity; account + submitMulti [provider] [public] do exerciseCmd (toInterfaceContractId @Custody.I custodyServiceCid) Custody.Deposit with depositRequestCid issue : Party -> Party -> Party -> Party -> Instrument.Q -> Account.K -> Script (ContractId Issuance.T, ContractId Holding.I) issue operator provider customer public quantity account = do From 5db5674c13388c93b6b0f4984f2f74eed8fb691c Mon Sep 17 00:00:00 2001 From: Georg Schneider Date: Sat, 17 Dec 2022 09:27:40 +0100 Subject: [PATCH 05/31] Use custody services interfaces in UI --- ui/src/Root.tsx | 2 +- ui/src/apps/Distribution.tsx | 2 +- ui/src/components/Instrument/Aggregate.tsx | 2 +- ...ServiceContext.tsx => ServicesContext.tsx} | 144 +++++++++++------- ui/src/hooks/Network.tsx | 4 +- ui/src/pages/defi/Exchange.tsx | 2 +- ui/src/pages/defi/Exchanges.tsx | 2 +- ui/src/pages/distribution/auction/Auction.tsx | 2 +- ui/src/pages/distribution/auction/Bidding.tsx | 2 +- ui/src/pages/distribution/auction/New.tsx | 2 +- .../pages/distribution/auction/Requests.tsx | 2 +- .../pages/distribution/investment/Funds.tsx | 2 +- ui/src/pages/distribution/investment/New.tsx | 2 +- .../investment/PooledRequests.tsx | 2 +- .../distribution/investment/Requests.tsx | 2 +- ui/src/pages/distribution/offering/New.tsx | 2 +- .../pages/distribution/offering/Offering.tsx | 2 +- ui/src/pages/issuance/New.tsx | 2 +- ui/src/pages/issuance/Requests.tsx | 2 +- ui/src/pages/lending/New.tsx | 2 +- ui/src/pages/lending/Offers.tsx | 2 +- ui/src/pages/lending/Request.tsx | 2 +- ui/src/pages/lending/Trades.tsx | 2 +- ui/src/pages/listing/Listings.tsx | 2 +- ui/src/pages/listing/New.tsx | 2 +- ui/src/pages/listing/Requests.tsx | 2 +- ui/src/pages/login/Login.tsx | 2 +- ui/src/pages/servicing/Effect.tsx | 10 +- ui/src/pages/servicing/Instrument.tsx | 2 +- ui/src/pages/servicing/Instruments.tsx | 2 +- ui/src/pages/simulation/Scenario.tsx | 2 +- .../structuring/bond/NewFixedRateBond.tsx | 2 +- .../structuring/bond/NewFloatingRateBond.tsx | 2 +- .../bond/NewInflationLinkedBond.tsx | 2 +- .../structuring/bond/NewZeroCouponBond.tsx | 2 +- ui/src/pages/structuring/equity/NewStock.tsx | 2 +- ui/src/pages/structuring/other/NewGeneric.tsx | 2 +- ui/src/pages/structuring/other/NewToken.tsx | 2 +- ui/src/pages/trading/Market.tsx | 2 +- 39 files changed, 133 insertions(+), 97 deletions(-) rename ui/src/context/{ServiceContext.tsx => ServicesContext.tsx} (60%) diff --git a/ui/src/Root.tsx b/ui/src/Root.tsx index 03bade5a..e7a615f9 100644 --- a/ui/src/Root.tsx +++ b/ui/src/Root.tsx @@ -15,7 +15,7 @@ import { Lending } from "./apps/Lending"; import { Settlement } from "./apps/Settlement"; import { Route, Routes } from "react-router-dom"; import { Overview } from "./apps/Overview"; -import { ServicesProvider } from "./context/ServiceContext"; +import { ServicesProvider } from "./context/ServicesContext"; import { InstrumentProvider } from "./context/InstrumentContext"; import { HoldingProvider } from "./context/HoldingContext"; import { AccountProvider } from "./context/AccountContext"; diff --git a/ui/src/apps/Distribution.tsx b/ui/src/apps/Distribution.tsx index 7e3daf3d..d83e86f7 100644 --- a/ui/src/apps/Distribution.tsx +++ b/ui/src/apps/Distribution.tsx @@ -16,7 +16,7 @@ import { New as NewInvestment} from "../pages/distribution/investment/New"; import { Spinner } from "../components/Spinner/Spinner"; import { Offerings } from "../pages/distribution/offering/Offerings"; import { Offering } from "../pages/distribution/offering/Offering"; -import { useServices } from "../context/ServiceContext"; +import { useServices } from "../context/ServicesContext"; import { App } from "./App"; import { PooledRequests } from "../pages/distribution/investment/PooledRequests"; import { Funds } from "../pages/distribution/investment/Funds"; diff --git a/ui/src/components/Instrument/Aggregate.tsx b/ui/src/components/Instrument/Aggregate.tsx index ddcd91b4..438be9aa 100644 --- a/ui/src/components/Instrument/Aggregate.tsx +++ b/ui/src/components/Instrument/Aggregate.tsx @@ -13,7 +13,7 @@ import { Service as Lifecycle } from "@daml.js/daml-finance-app/lib/Daml/Finance import { useParties } from "../../context/PartiesContext"; import { shorten } from "../../util"; import { Spinner } from "../Spinner/Spinner"; -import { useServices } from "../../context/ServiceContext"; +import { useServices } from "../../context/ServicesContext"; import { NumericObservable } from "@daml.js/daml-finance-interface-data/lib/Daml/Finance/Interface/Data/NumericObservable"; import { VerticalTable } from "../Table/VerticalTable"; diff --git a/ui/src/context/ServiceContext.tsx b/ui/src/context/ServicesContext.tsx similarity index 60% rename from ui/src/context/ServiceContext.tsx rename to ui/src/context/ServicesContext.tsx index 88b44909..76b892a5 100644 --- a/ui/src/context/ServiceContext.tsx +++ b/ui/src/context/ServicesContext.tsx @@ -4,8 +4,10 @@ import React from "react"; import { CreateEvent } from "@daml/ledger"; import { useStreamQueries } from "@daml/react"; +import { Service as BaseService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Interface/Base/Service" import { Service as BackToBackService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/BackToBack/Service" -import { Service as CustodyService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Custody/Service" +import { Service as CustodyService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Interface/Custody/Service" +import { Service as CustodyAutoService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Interface/Custody/Auto" import { Service as DecentralizedExchangeService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Decentralized/Exchange/Service" import { Service as AuctionService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Distribution/Auction/Service" import { Service as AuctionAutoService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Distribution/Auction/Auto/Service" @@ -26,10 +28,20 @@ import { Service as SettlementService } from "@daml.js/daml-finance-app/lib/Daml import { Service as TradingService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Trading/Service" import { Service as TradingAutoService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Trading/Auto/Service" +type ServicesAggregate = { + services : ServiceAggregate[] + getService : (custodian : string, owner : string) => ServiceAggregate | undefined +}; + +type ServiceAggregate = CreateEvent & { + service : CreateEvent + auto : CreateEvent | undefined +}; + export type ServicesState = { loading : boolean backToBack : readonly CreateEvent[] - custody : readonly CreateEvent[] + custody : ServicesAggregate decentralizedExchange : readonly CreateEvent[] auctionAuto : readonly CreateEvent[] auction : readonly CreateEvent[] @@ -51,10 +63,15 @@ export type ServicesState = { trading : readonly CreateEvent[] }; +const emptyAggregate = { + services: [], + getService: (custodian : string, owner : string) => { throw new Error("Not implemented"); } +}; + const empty = { loading: true, backToBack: [], - custody: [], + custody: emptyAggregate, decentralizedExchange: [], auctionAuto: [], auction: [], @@ -80,59 +97,78 @@ const ServicesContext = React.createContext(empty); export const ServicesProvider : React.FC = ({ children }) => { - const { loading: l1, contracts: backToBack } = useStreamQueries(BackToBackService); - const { loading: l2, contracts: custody } = useStreamQueries(CustodyService); - const { loading: l3, contracts: decentralizedExchange } = useStreamQueries(DecentralizedExchangeService); - const { loading: l4, contracts: auctionAuto } = useStreamQueries(AuctionAutoService); - const { loading: l5, contracts: auction } = useStreamQueries(AuctionService); - const { loading: l6, contracts: biddingAuto } = useStreamQueries(BiddingAutoService); - const { loading: l7, contracts: bidding } = useStreamQueries(BiddingService); - const { loading: l8, contracts: fund } = useStreamQueries(FundService); - const { loading: l9, contracts: investment } = useStreamQueries(InvestmentService); - const { loading: l10, contracts: issuanceAuto } = useStreamQueries(IssuanceAutoService); - const { loading: l11, contracts: issuance } = useStreamQueries(IssuanceService); - const { loading: l12, contracts: lending } = useStreamQueries(LendingService); - const { loading: l13, contracts: lifecycle } = useStreamQueries(LifecycleService); - const { loading: l14, contracts: listingAuto } = useStreamQueries(ListingAutoService); - const { loading: l15, contracts: listing } = useStreamQueries(ListingService); - const { loading: l16, contracts: settlement } = useStreamQueries(SettlementService); - const { loading: l17, contracts: structuringAuto } = useStreamQueries(StructuringAutoService); - const { loading: l18, contracts: structuring } = useStreamQueries(StructuringService); - const { loading: l19, contracts: subscription } = useStreamQueries(SubscriptionService); - const { loading: l20, contracts: tradingAuto } = useStreamQueries(TradingAutoService); - const { loading: l21, contracts: trading } = useStreamQueries(TradingService); - const loading = l1 || l2 || l3 || l4 || l5 || l6 || l7 || l8 || l9 || l10 || l11 || l12 || l13 || l14 || l15 || l16 || l17 || l18 || l19 || l20 || l21; + const { loading: l1, contracts: base } = useStreamQueries(BaseService); + const { loading: l2, contracts: backToBack } = useStreamQueries(BackToBackService); + const { loading: l3, contracts: custody } = useStreamQueries(CustodyService); + const { loading: l4, contracts: custodyAuto } = useStreamQueries(CustodyAutoService); + const { loading: l5, contracts: decentralizedExchange } = useStreamQueries(DecentralizedExchangeService); + const { loading: l6, contracts: auctionAuto } = useStreamQueries(AuctionAutoService); + const { loading: l7, contracts: auction } = useStreamQueries(AuctionService); + const { loading: l8, contracts: biddingAuto } = useStreamQueries(BiddingAutoService); + const { loading: l9, contracts: bidding } = useStreamQueries(BiddingService); + const { loading: l10, contracts: fund } = useStreamQueries(FundService); + const { loading: l11, contracts: investment } = useStreamQueries(InvestmentService); + const { loading: l12, contracts: issuanceAuto } = useStreamQueries(IssuanceAutoService); + const { loading: l13, contracts: issuance } = useStreamQueries(IssuanceService); + const { loading: l14, contracts: lending } = useStreamQueries(LendingService); + const { loading: l15, contracts: lifecycle } = useStreamQueries(LifecycleService); + const { loading: l16, contracts: listingAuto } = useStreamQueries(ListingAutoService); + const { loading: l17, contracts: listing } = useStreamQueries(ListingService); + const { loading: l18, contracts: settlement } = useStreamQueries(SettlementService); + const { loading: l19, contracts: structuringAuto } = useStreamQueries(StructuringAutoService); + const { loading: l20, contracts: structuring } = useStreamQueries(StructuringService); + const { loading: l21, contracts: subscription } = useStreamQueries(SubscriptionService); + const { loading: l22, contracts: tradingAuto } = useStreamQueries(TradingAutoService); + const { loading: l23, contracts: trading } = useStreamQueries(TradingService); + const loading = l1 || l2 || l3 || l4 || l5 || l6 || l7 || l8 || l9 || l10 || l11 || l12 || l13 || l14 || l15 || l16 || l17 || l18 || l19 || l20 || l21 || l22 || l23; + + if (loading) { + return ( + + {children} + + ); + } else { + const custodyByCid : Map> = new Map(custody.map(c => [c.contractId, c])); + const custodyAutoByCid : Map> = new Map(custodyAuto.map(c => [c.contractId, c])); + const custodyAggregates : ServiceAggregate[] = base.map(c => ({ ...c, service: custodyByCid.get(c.contractId)!, auto: custodyAutoByCid.get(c.contractId) })); + const getCustodyService = (provider : string, customer : string) => { return custodyAggregates.find(c => c.payload.provider === provider && c.payload.customer === customer) }; + const custodyAggregate = { + services: custodyAggregates, + getService: getCustodyService + }; - const value = { - loading, - backToBack, - custody, - decentralizedExchange, - auctionAuto, - auction, - biddingAuto, - bidding, - fund, - investment, - issuanceAuto, - issuance, - lending, - lifecycle, - listingAuto, - listing, - settlement, - structuringAuto, - structuring, - subscription, - tradingAuto, - trading, - }; + const value = { + loading, + backToBack, + custody: custodyAggregate, + decentralizedExchange, + auctionAuto, + auction, + biddingAuto, + bidding, + fund, + investment, + issuanceAuto, + issuance, + lending, + lifecycle, + listingAuto, + listing, + settlement, + structuringAuto, + structuring, + subscription, + tradingAuto, + trading, + }; - return ( - - {children} - - ); + return ( + + {children} + + ); + } } export const useServices = () => { diff --git a/ui/src/hooks/Network.tsx b/ui/src/hooks/Network.tsx index 2d722aa4..607d77f3 100644 --- a/ui/src/hooks/Network.tsx +++ b/ui/src/hooks/Network.tsx @@ -7,7 +7,7 @@ import { Edge, EdgeChange, MarkerType, Node, NodeChange, useEdgesState, useNodes import { useEffect, useState } from "react"; import { useParties } from "../context/PartiesContext"; import { useScenario } from "../context/ScenarioContext"; -import { useServices } from "../context/ServiceContext"; +import { useServices } from "../context/ServicesContext"; export type Network = { nodes : Node[], @@ -34,7 +34,7 @@ export const useNetwork = () : Network => { const services : CreateEvent[] = Array.prototype.concat.apply([], [ svc.auction, svc.backToBack, - svc.custody, + svc.custody.services, svc.bidding, svc.fund, svc.investment, diff --git a/ui/src/pages/defi/Exchange.tsx b/ui/src/pages/defi/Exchange.tsx index b18f5d8c..c9244ec1 100644 --- a/ui/src/pages/defi/Exchange.tsx +++ b/ui/src/pages/defi/Exchange.tsx @@ -11,7 +11,7 @@ import { Percentage } from "../../components/Slider/Percentage"; import useStyles from "../styles"; import { Bonding } from "../../components/Curve/Bonding"; import { Service } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Decentralized/Exchange/Service"; -import { useServices } from "../../context/ServiceContext"; +import { useServices } from "../../context/ServicesContext"; import { useHoldings } from "../../context/HoldingContext"; import { useAccounts } from "../../context/AccountContext"; import { Message } from "../../components/Message/Message"; diff --git a/ui/src/pages/defi/Exchanges.tsx b/ui/src/pages/defi/Exchanges.tsx index 6e868200..a8e37bf0 100644 --- a/ui/src/pages/defi/Exchanges.tsx +++ b/ui/src/pages/defi/Exchanges.tsx @@ -6,7 +6,7 @@ import { Grid, Theme } from "@mui/material"; import { Spinner } from "../../components/Spinner/Spinner"; import { makeStyles, createStyles } from "@mui/styles"; import { Dex } from "../../components/Card/Dex"; -import { useServices } from "../../context/ServiceContext"; +import { useServices } from "../../context/ServicesContext"; export const Exchanges : React.FC = () => { const classes = useStyles(); diff --git a/ui/src/pages/distribution/auction/Auction.tsx b/ui/src/pages/distribution/auction/Auction.tsx index 6203fc3b..63c50e79 100644 --- a/ui/src/pages/distribution/auction/Auction.tsx +++ b/ui/src/pages/distribution/auction/Auction.tsx @@ -16,7 +16,7 @@ import { Spinner } from "../../../components/Spinner/Spinner"; import { fmt } from "../../../util"; import { Message } from "../../../components/Message/Message"; import { useParties } from "../../../context/PartiesContext"; -import { useServices } from "../../../context/ServiceContext"; +import { useServices } from "../../../context/ServicesContext"; import { Factory } from "@daml.js/daml-finance-interface-settlement/lib/Daml/Finance/Interface/Settlement/Factory"; export const Auction: React.FC = () => { diff --git a/ui/src/pages/distribution/auction/Bidding.tsx b/ui/src/pages/distribution/auction/Bidding.tsx index fa423f9f..2053c35b 100644 --- a/ui/src/pages/distribution/auction/Bidding.tsx +++ b/ui/src/pages/distribution/auction/Bidding.tsx @@ -18,7 +18,7 @@ import { Reference } from "@daml.js/daml-finance-interface-account/lib/Daml/Fina import { Message } from "../../../components/Message/Message"; import { useParties } from "../../../context/PartiesContext"; import { useInstruments } from "../../../context/InstrumentContext"; -import { useServices } from "../../../context/ServiceContext"; +import { useServices } from "../../../context/ServicesContext"; import { Aggregate } from "../../../components/Instrument/Aggregate"; import { useHoldings } from "../../../context/HoldingContext"; diff --git a/ui/src/pages/distribution/auction/New.tsx b/ui/src/pages/distribution/auction/New.tsx index e113a4ee..fb52774e 100644 --- a/ui/src/pages/distribution/auction/New.tsx +++ b/ui/src/pages/distribution/auction/New.tsx @@ -12,7 +12,7 @@ import { Reference } from "@daml.js/daml-finance-interface-account/lib/Daml/Fina import { createSet } from "../../../util"; import { useParties } from "../../../context/PartiesContext"; import { useInstruments } from "../../../context/InstrumentContext"; -import { useServices } from "../../../context/ServiceContext"; +import { useServices } from "../../../context/ServicesContext"; import { Service as Auction } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Distribution/Auction/Service"; import { Service as AuctionAuto } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Distribution/Auction/Auto/Service"; import { Message } from "../../../components/Message/Message"; diff --git a/ui/src/pages/distribution/auction/Requests.tsx b/ui/src/pages/distribution/auction/Requests.tsx index 87aa0a25..e40c54d0 100644 --- a/ui/src/pages/distribution/auction/Requests.tsx +++ b/ui/src/pages/distribution/auction/Requests.tsx @@ -12,7 +12,7 @@ import { Service } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Distribu import { Spinner } from "../../../components/Spinner/Spinner"; import { fmt } from "../../../util"; import { useParties } from "../../../context/PartiesContext"; -import { useServices } from "../../../context/ServiceContext"; +import { useServices } from "../../../context/ServicesContext"; export const Requests : React.FC = () => { const classes = useStyles(); diff --git a/ui/src/pages/distribution/investment/Funds.tsx b/ui/src/pages/distribution/investment/Funds.tsx index edd8615f..90d22747 100644 --- a/ui/src/pages/distribution/investment/Funds.tsx +++ b/ui/src/pages/distribution/investment/Funds.tsx @@ -12,7 +12,7 @@ import { fmt } from "../../../util"; import { useParties } from "../../../context/PartiesContext"; import { Alignment, HorizontalTable } from "../../../components/Table/HorizontalTable"; import { Fund } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Distribution/Fund/Model"; -import { useServices } from "../../../context/ServiceContext"; +import { useServices } from "../../../context/ServicesContext"; export const Funds : React.FC = () => { const classes = useStyles(); diff --git a/ui/src/pages/distribution/investment/New.tsx b/ui/src/pages/distribution/investment/New.tsx index 561bf9f7..1b87d67c 100644 --- a/ui/src/pages/distribution/investment/New.tsx +++ b/ui/src/pages/distribution/investment/New.tsx @@ -8,7 +8,7 @@ import { useLedger, useParty, useStreamQueries } from "@daml/react"; import { Typography, Grid, Paper, Button } from "@mui/material"; import useStyles from "../../styles"; import { Spinner } from "../../../components/Spinner/Spinner"; -import { useServices } from "../../../context/ServiceContext"; +import { useServices } from "../../../context/ServicesContext"; import { Service as Investment } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Distribution/Investment/Service"; import { Message } from "../../../components/Message/Message"; import { useHoldings } from "../../../context/HoldingContext"; diff --git a/ui/src/pages/distribution/investment/PooledRequests.tsx b/ui/src/pages/distribution/investment/PooledRequests.tsx index fdb6f786..9c892c77 100644 --- a/ui/src/pages/distribution/investment/PooledRequests.tsx +++ b/ui/src/pages/distribution/investment/PooledRequests.tsx @@ -7,7 +7,7 @@ import { useLedger, useParty, useStreamQueries } from "@daml/react"; import { Spinner } from "../../../components/Spinner/Spinner"; import { fmt } from "../../../util"; import { useParties } from "../../../context/PartiesContext"; -import { useServices } from "../../../context/ServiceContext"; +import { useServices } from "../../../context/ServicesContext"; import { Alignment, HorizontalTable } from "../../../components/Table/HorizontalTable"; import { Service as FundService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Distribution/Fund/Service"; import { Fund, PooledInvestmentRequest } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Distribution/Fund/Model"; diff --git a/ui/src/pages/distribution/investment/Requests.tsx b/ui/src/pages/distribution/investment/Requests.tsx index 4e16541a..67cfbc6f 100644 --- a/ui/src/pages/distribution/investment/Requests.tsx +++ b/ui/src/pages/distribution/investment/Requests.tsx @@ -8,7 +8,7 @@ import { useLedger, useParty, useStreamQueries } from "@daml/react"; import { Spinner } from "../../../components/Spinner/Spinner"; import { dedup, fmt } from "../../../util"; import { useParties } from "../../../context/PartiesContext"; -import { useServices } from "../../../context/ServiceContext"; +import { useServices } from "../../../context/ServicesContext"; import { InvestmentRequest } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Distribution/Investment/Model"; import { Alignment, HorizontalTable } from "../../../components/Table/HorizontalTable"; import { SelectionTable } from "../../../components/Table/SelectionTable"; diff --git a/ui/src/pages/distribution/offering/New.tsx b/ui/src/pages/distribution/offering/New.tsx index 86d31938..1e002be1 100644 --- a/ui/src/pages/distribution/offering/New.tsx +++ b/ui/src/pages/distribution/offering/New.tsx @@ -12,7 +12,7 @@ import { Spinner } from "../../../components/Spinner/Spinner"; import { Reference } from "@daml.js/daml-finance-interface-account/lib/Daml/Finance/Interface/Account/Account"; import { dedup } from "../../../util"; import { BackToBack } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Distribution/Subscription/Model"; -import { useServices } from "../../../context/ServiceContext"; +import { useServices } from "../../../context/ServicesContext"; import { useInstruments } from "../../../context/InstrumentContext"; import { Message } from "../../../components/Message/Message"; import { Aggregate } from "../../../components/Instrument/Aggregate"; diff --git a/ui/src/pages/distribution/offering/Offering.tsx b/ui/src/pages/distribution/offering/Offering.tsx index e8e399d6..64e50d56 100644 --- a/ui/src/pages/distribution/offering/Offering.tsx +++ b/ui/src/pages/distribution/offering/Offering.tsx @@ -15,7 +15,7 @@ import { Reference } from "@daml.js/daml-finance-interface-account/lib/Daml/Fina import { fmt } from "../../../util"; import { Message } from "../../../components/Message/Message"; import { useParties } from "../../../context/PartiesContext"; -import { useServices } from "../../../context/ServiceContext"; +import { useServices } from "../../../context/ServicesContext"; import { Factory } from "@daml.js/daml-finance-interface-settlement/lib/Daml/Finance/Interface/Settlement/Factory"; import { useHoldings } from "../../../context/HoldingContext"; diff --git a/ui/src/pages/issuance/New.tsx b/ui/src/pages/issuance/New.tsx index ed9cd2ef..40c48059 100644 --- a/ui/src/pages/issuance/New.tsx +++ b/ui/src/pages/issuance/New.tsx @@ -9,7 +9,7 @@ import { Typography, Grid, Paper, Button, Checkbox, FormGroup, FormControlLabel import useStyles from "../styles"; import { Spinner } from "../../components/Spinner/Spinner"; import { Reference } from "@daml.js/daml-finance-interface-account/lib/Daml/Finance/Interface/Account/Account"; -import { useServices } from "../../context/ServiceContext"; +import { useServices } from "../../context/ServicesContext"; import { useInstruments } from "../../context/InstrumentContext"; import { Service as BackToBack } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/BackToBack/Service"; import { Service as IssuanceAuto } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Issuance/Auto/Service"; diff --git a/ui/src/pages/issuance/Requests.tsx b/ui/src/pages/issuance/Requests.tsx index 3ec31d00..7739762b 100644 --- a/ui/src/pages/issuance/Requests.tsx +++ b/ui/src/pages/issuance/Requests.tsx @@ -13,7 +13,7 @@ import { CreateIssuanceRequest, ReduceIssuanceRequest } from "@daml.js/daml-fina import { Service } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Issuance/Service"; import { Spinner } from "../../components/Spinner/Spinner"; import { useParties } from "../../context/PartiesContext"; -import { useServices } from "../../context/ServiceContext"; +import { useServices } from "../../context/ServicesContext"; import { Message } from "../../components/Message/Message"; export const Requests : React.FC = () => { diff --git a/ui/src/pages/lending/New.tsx b/ui/src/pages/lending/New.tsx index 054b2192..c8f4f4c6 100644 --- a/ui/src/pages/lending/New.tsx +++ b/ui/src/pages/lending/New.tsx @@ -9,7 +9,7 @@ import { useLedger } from "@daml/react"; import { Button } from "@mui/material"; import useStyles from "../styles"; import { Spinner } from "../../components/Spinner/Spinner"; -import { useServices } from "../../context/ServiceContext"; +import { useServices } from "../../context/ServicesContext"; import { useInstruments } from "../../context/InstrumentContext"; import { Service as Lending } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Lending/Service"; import { Message } from "../../components/Message/Message"; diff --git a/ui/src/pages/lending/Offers.tsx b/ui/src/pages/lending/Offers.tsx index 542801b1..2c2f57cb 100644 --- a/ui/src/pages/lending/Offers.tsx +++ b/ui/src/pages/lending/Offers.tsx @@ -10,7 +10,7 @@ import { Spinner } from "../../components/Spinner/Spinner"; import { useParties } from "../../context/PartiesContext"; import { BorrowOffer } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Lending/Model"; import { fmt } from "../../util"; -import { useServices } from "../../context/ServiceContext"; +import { useServices } from "../../context/ServicesContext"; import { Service as Lending } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Lending/Service"; import { Reference } from "@daml.js/daml-finance-interface-account/lib/Daml/Finance/Interface/Account/Account"; import { CreateEvent } from "@daml/ledger"; diff --git a/ui/src/pages/lending/Request.tsx b/ui/src/pages/lending/Request.tsx index f55ae5de..ca9c3d14 100644 --- a/ui/src/pages/lending/Request.tsx +++ b/ui/src/pages/lending/Request.tsx @@ -13,7 +13,7 @@ import { Reference } from "@daml.js/daml-finance-interface-account/lib/Daml/Fina import { Message } from "../../components/Message/Message"; import { useParties } from "../../context/PartiesContext"; import { useInstruments } from "../../context/InstrumentContext"; -import { useServices } from "../../context/ServiceContext"; +import { useServices } from "../../context/ServicesContext"; import { BorrowOfferRequest } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Lending/Model"; import { fmt } from "../../util"; import { useHoldings } from "../../context/HoldingContext"; diff --git a/ui/src/pages/lending/Trades.tsx b/ui/src/pages/lending/Trades.tsx index b3107dca..b50c3747 100644 --- a/ui/src/pages/lending/Trades.tsx +++ b/ui/src/pages/lending/Trades.tsx @@ -9,7 +9,7 @@ import { Spinner } from "../../components/Spinner/Spinner"; import { useParties } from "../../context/PartiesContext"; import { BorrowAgreement } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Lending/Model"; import { fmt } from "../../util"; -import { useServices } from "../../context/ServiceContext"; +import { useServices } from "../../context/ServicesContext"; import { CreateEvent } from "@daml/ledger"; import { useHoldings } from "../../context/HoldingContext"; import { ContractId } from "@daml/types"; diff --git a/ui/src/pages/listing/Listings.tsx b/ui/src/pages/listing/Listings.tsx index a7105ccc..7a42df48 100644 --- a/ui/src/pages/listing/Listings.tsx +++ b/ui/src/pages/listing/Listings.tsx @@ -11,7 +11,7 @@ import { Service as AutoService } from "@daml.js/daml-finance-app/lib/Daml/Finan import { Listing } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Listing/Model"; import { Spinner } from "../../components/Spinner/Spinner"; import { useParties } from "../../context/PartiesContext"; -import { useServices } from "../../context/ServiceContext"; +import { useServices } from "../../context/ServicesContext"; import { HorizontalTable } from "../../components/Table/HorizontalTable"; export const Listings : React.FC = () => { diff --git a/ui/src/pages/listing/New.tsx b/ui/src/pages/listing/New.tsx index f3038902..22e7b3f6 100644 --- a/ui/src/pages/listing/New.tsx +++ b/ui/src/pages/listing/New.tsx @@ -14,7 +14,7 @@ import { Message } from "../../components/Message/Message"; import { Spinner } from "../../components/Spinner/Spinner"; import { useInstruments } from "../../context/InstrumentContext"; import { useParties } from "../../context/PartiesContext"; -import { useServices } from "../../context/ServiceContext"; +import { useServices } from "../../context/ServicesContext"; import { createSet } from "../../util"; import useStyles from "../styles"; diff --git a/ui/src/pages/listing/Requests.tsx b/ui/src/pages/listing/Requests.tsx index c4f08a39..c498ef24 100644 --- a/ui/src/pages/listing/Requests.tsx +++ b/ui/src/pages/listing/Requests.tsx @@ -13,7 +13,7 @@ import { Service } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Listing/ import { CreateListingRequest, DeleteListingRequest, Listing } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Listing/Model"; import { Spinner } from "../../components/Spinner/Spinner"; import { useParties } from "../../context/PartiesContext"; -import { useServices } from "../../context/ServiceContext"; +import { useServices } from "../../context/ServicesContext"; export const Requests : React.FC = () => { const classes = useStyles(); diff --git a/ui/src/pages/login/Login.tsx b/ui/src/pages/login/Login.tsx index 1b08c578..9b4e0946 100644 --- a/ui/src/pages/login/Login.tsx +++ b/ui/src/pages/login/Login.tsx @@ -6,7 +6,7 @@ import React from "react"; import { Route, Routes } from "react-router-dom"; import { httpBaseUrl, wsBaseUrl } from "../../config"; import { useParties } from "../../context/PartiesContext"; -import { ServicesProvider } from "../../context/ServiceContext"; +import { ServicesProvider } from "../../context/ServicesContext"; import { Form } from "./Form"; import { Network } from "./Network"; diff --git a/ui/src/pages/servicing/Effect.tsx b/ui/src/pages/servicing/Effect.tsx index 9780cb3d..c29cf466 100644 --- a/ui/src/pages/servicing/Effect.tsx +++ b/ui/src/pages/servicing/Effect.tsx @@ -15,7 +15,7 @@ import { Effect as EffectI } from "@daml.js/daml-finance-interface-lifecycle/lib import { useParties } from "../../context/PartiesContext"; import { Message } from "../../components/Message/Message"; import { Claim } from "@daml.js/daml-finance-interface-lifecycle/lib/Daml/Finance/Interface/Lifecycle/Rule/Claim"; -import { useServices } from "../../context/ServiceContext"; +import { useServices } from "../../context/ServicesContext"; import { HoldingAggregate, useHoldings } from "../../context/HoldingContext"; import { Batch } from "@daml.js/daml-finance-interface-settlement/lib/Daml/Finance/Interface/Settlement/Batch"; @@ -36,22 +36,22 @@ export const Effect : React.FC = () => { if (loading) return ; if (!effect) return ; - if (custody.length === 0) return ; + if (custody.services.length === 0) return ; const filteredHoldings = holdings.filter(c => keyEquals(c.payload.instrument, effect.payload.targetInstrument)); const filteredBatches = batches.filter(c => !!c.payload.contextId && c.payload.contextId.unpack === effect.payload.id.unpack); const claimEffect = async () => { const claimHolding = async (holding : HoldingAggregate) => { - const service = custody.find(c => c.payload.provider === holding.payload.account.custodian && c.payload.customer === holding.payload.account.owner); - if (!service) throw new Error("No custody service found with custodian [" + holding.payload.account.custodian + "] and owner [" + holding.payload.account.owner + "]"); + const aggregate = custody.getService(holding.payload.account.custodian, holding.payload.account.owner); + if (!aggregate) throw new Error("No custody service found with custodian [" + holding.payload.account.custodian + "] and owner [" + holding.payload.account.owner + "]"); const arg = { claimer: party, holdingCids: [holding.contractId], effectCid: effect.contractId, batchId: { unpack: uuidv4() } } - await ledger.exercise(Claim.ClaimEffect, service.payload.claimRuleCid, arg); + await ledger.exercise(Claim.ClaimEffect, aggregate.service.payload.claimRuleCid, arg); }; await Promise.all(filteredHoldings.map(claimHolding)); }; diff --git a/ui/src/pages/servicing/Instrument.tsx b/ui/src/pages/servicing/Instrument.tsx index 57218343..14567337 100644 --- a/ui/src/pages/servicing/Instrument.tsx +++ b/ui/src/pages/servicing/Instrument.tsx @@ -14,7 +14,7 @@ import { ClaimsTreeBuilder, ClaimTreeNode } from "../../components/Claims/Claims import { and, C, claimToNode } from "../../components/Claims/util"; import { useParties } from "../../context/PartiesContext"; import { useInstruments } from "../../context/InstrumentContext"; -import { useServices } from "../../context/ServiceContext"; +import { useServices } from "../../context/ServicesContext"; import { Message } from "../../components/Message/Message"; import { NumericObservable } from "@daml.js/daml-finance-interface-data/lib/Daml/Finance/Interface/Data/NumericObservable"; import { TimeObservable } from "@daml.js/daml-finance-interface-data/lib/Daml/Finance/Interface/Data/TimeObservable"; diff --git a/ui/src/pages/servicing/Instruments.tsx b/ui/src/pages/servicing/Instruments.tsx index f3e650a5..724b6ef8 100644 --- a/ui/src/pages/servicing/Instruments.tsx +++ b/ui/src/pages/servicing/Instruments.tsx @@ -6,7 +6,7 @@ import { useLedger, useParty, useStreamQueries } from "@daml/react"; import { Spinner } from "../../components/Spinner/Spinner"; import { Service } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Lifecycle/Service"; import { useParties } from "../../context/PartiesContext"; -import { useServices } from "../../context/ServiceContext"; +import { useServices } from "../../context/ServicesContext"; import { InstrumentAggregate, useInstruments } from "../../context/InstrumentContext"; import { Event } from "@daml.js/daml-finance-interface-lifecycle/lib/Daml/Finance/Interface/Lifecycle/Event"; import { NumericObservable } from "@daml.js/daml-finance-interface-data/lib/Daml/Finance/Interface/Data/NumericObservable"; diff --git a/ui/src/pages/simulation/Scenario.tsx b/ui/src/pages/simulation/Scenario.tsx index 294de2e5..6b0ab7e2 100644 --- a/ui/src/pages/simulation/Scenario.tsx +++ b/ui/src/pages/simulation/Scenario.tsx @@ -13,7 +13,7 @@ import { and, claimToNode, findObservables } from "../../components/Claims/util" import { render } from "../../components/Claims/renderScenario"; import { ExpandMore } from "@mui/icons-material"; import { dedup } from "../../util"; -import { useServices } from "../../context/ServiceContext"; +import { useServices } from "../../context/ServicesContext"; import { useInstruments } from "../../context/InstrumentContext"; import { Message } from "../../components/Message/Message"; import { NumericObservable } from "@daml.js/daml-finance-interface-data/lib/Daml/Finance/Interface/Data/NumericObservable"; diff --git a/ui/src/pages/structuring/bond/NewFixedRateBond.tsx b/ui/src/pages/structuring/bond/NewFixedRateBond.tsx index c532703b..cf6bd762 100644 --- a/ui/src/pages/structuring/bond/NewFixedRateBond.tsx +++ b/ui/src/pages/structuring/bond/NewFixedRateBond.tsx @@ -17,7 +17,7 @@ import { parseDate, singleton } from "../../../util"; import { businessDayConventions, couponFrequencies, dayCountConventions, holidayCalendars } from "./util"; import { useParties } from "../../../context/PartiesContext"; import { useInstruments } from "../../../context/InstrumentContext"; -import { useServices } from "../../../context/ServiceContext"; +import { useServices } from "../../../context/ServicesContext"; import { Spinner } from "../../../components/Spinner/Spinner"; import { Message } from "../../../components/Message/Message"; import { DateInput } from "../../../components/Form/DateInput"; diff --git a/ui/src/pages/structuring/bond/NewFloatingRateBond.tsx b/ui/src/pages/structuring/bond/NewFloatingRateBond.tsx index bc9a2d09..4293fe02 100644 --- a/ui/src/pages/structuring/bond/NewFloatingRateBond.tsx +++ b/ui/src/pages/structuring/bond/NewFloatingRateBond.tsx @@ -16,7 +16,7 @@ import { DayCountConventionEnum } from "@daml.js/daml-finance-interface-types/li import { BusinessDayConventionEnum } from "@daml.js/daml-finance-interface-types/lib/Daml/Finance/Interface/Types/Date/Calendar"; import { useParties } from "../../../context/PartiesContext"; import { useInstruments } from "../../../context/InstrumentContext"; -import { useServices } from "../../../context/ServiceContext"; +import { useServices } from "../../../context/ServicesContext"; import { Service as Structuring } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Structuring/Service"; import { Service as StructuringAuto } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Structuring/Auto/Service"; import { TextInput } from "../../../components/Form/TextInput"; diff --git a/ui/src/pages/structuring/bond/NewInflationLinkedBond.tsx b/ui/src/pages/structuring/bond/NewInflationLinkedBond.tsx index 38141add..bc5fd154 100644 --- a/ui/src/pages/structuring/bond/NewInflationLinkedBond.tsx +++ b/ui/src/pages/structuring/bond/NewInflationLinkedBond.tsx @@ -16,7 +16,7 @@ import { DayCountConventionEnum } from "@daml.js/daml-finance-interface-types/li import { BusinessDayConventionEnum } from "@daml.js/daml-finance-interface-types/lib/Daml/Finance/Interface/Types/Date/Calendar"; import { useParties } from "../../../context/PartiesContext"; import { useInstruments } from "../../../context/InstrumentContext"; -import { useServices } from "../../../context/ServiceContext"; +import { useServices } from "../../../context/ServicesContext"; import { Service as Structuring } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Structuring/Service"; import { Service as StructuringAuto } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Structuring/Auto/Service"; import { CenteredForm } from "../../../components/CenteredForm/CenteredForm"; diff --git a/ui/src/pages/structuring/bond/NewZeroCouponBond.tsx b/ui/src/pages/structuring/bond/NewZeroCouponBond.tsx index debf7090..1bb6c4ad 100644 --- a/ui/src/pages/structuring/bond/NewZeroCouponBond.tsx +++ b/ui/src/pages/structuring/bond/NewZeroCouponBond.tsx @@ -13,7 +13,7 @@ import { Message } from "../../../components/Message/Message"; import { emptyMap } from "@daml/types"; import { useParties } from "../../../context/PartiesContext"; import { useInstruments } from "../../../context/InstrumentContext"; -import { useServices } from "../../../context/ServiceContext"; +import { useServices } from "../../../context/ServicesContext"; import { Service as Structuring } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Structuring/Service"; import { Service as StructuringAuto } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Structuring/Auto/Service"; import { CenteredForm } from "../../../components/CenteredForm/CenteredForm"; diff --git a/ui/src/pages/structuring/equity/NewStock.tsx b/ui/src/pages/structuring/equity/NewStock.tsx index 6eef845a..8204ae1f 100644 --- a/ui/src/pages/structuring/equity/NewStock.tsx +++ b/ui/src/pages/structuring/equity/NewStock.tsx @@ -12,7 +12,7 @@ import { Spinner } from "../../../components/Spinner/Spinner"; import { Message } from "../../../components/Message/Message"; import { emptyMap } from "@daml/types"; import { useParties } from "../../../context/PartiesContext"; -import { useServices } from "../../../context/ServiceContext"; +import { useServices } from "../../../context/ServicesContext"; import { Service as Structuring } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Structuring/Service"; import { Service as StructuringAuto } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Structuring/Auto/Service"; diff --git a/ui/src/pages/structuring/other/NewGeneric.tsx b/ui/src/pages/structuring/other/NewGeneric.tsx index cc826118..77fc3fb8 100644 --- a/ui/src/pages/structuring/other/NewGeneric.tsx +++ b/ui/src/pages/structuring/other/NewGeneric.tsx @@ -16,7 +16,7 @@ import { emptyMap } from "@daml/types"; import { useParties } from "../../../context/PartiesContext"; import { useInstruments } from "../../../context/InstrumentContext"; import { Message } from "../../../components/Message/Message"; -import { useServices } from "../../../context/ServiceContext"; +import { useServices } from "../../../context/ServicesContext"; import { Service as Structuring } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Structuring/Service"; import { Service as StructuringAuto } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Structuring/Auto/Service"; diff --git a/ui/src/pages/structuring/other/NewToken.tsx b/ui/src/pages/structuring/other/NewToken.tsx index 8ea0eb3a..148c1766 100644 --- a/ui/src/pages/structuring/other/NewToken.tsx +++ b/ui/src/pages/structuring/other/NewToken.tsx @@ -12,7 +12,7 @@ import { Spinner } from "../../../components/Spinner/Spinner"; import { Message } from "../../../components/Message/Message"; import { emptyMap } from "@daml/types"; import { useParties } from "../../../context/PartiesContext"; -import { useServices } from "../../../context/ServiceContext"; +import { useServices } from "../../../context/ServicesContext"; import { Service as Structuring } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Structuring/Service"; import { Service as StructuringAuto } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Structuring/Auto/Service"; diff --git a/ui/src/pages/trading/Market.tsx b/ui/src/pages/trading/Market.tsx index ef8a0169..00aa3fa9 100644 --- a/ui/src/pages/trading/Market.tsx +++ b/ui/src/pages/trading/Market.tsx @@ -18,7 +18,7 @@ import { Spinner } from "../../components/Spinner/Spinner"; import { Percentage } from "../../components/Slider/Percentage"; import { Reference } from "@daml.js/daml-finance-interface-account/lib/Daml/Finance/Interface/Account/Account"; import { useParties } from "../../context/PartiesContext"; -import { useServices } from "../../context/ServiceContext"; +import { useServices } from "../../context/ServicesContext"; import { Message } from "../../components/Message/Message"; import { useHoldings } from "../../context/HoldingContext"; From ffa3e8c09ebb52a793bc62910f1c7c0146846107 Mon Sep 17 00:00:00 2001 From: Georg Schneider Date: Sun, 18 Dec 2022 00:02:31 +0100 Subject: [PATCH 06/31] Add issuance interfaces --- .../Daml/Finance/App/Custody/Service.daml | 8 -- .../Finance/App/Distribution/Fund/Model.daml | 16 ++- .../App/Distribution/Fund/Service.daml | 4 +- .../Finance/App/Interface/Issuance/Auto.daml | 53 ++++++++ .../Interface/Issuance/DeissueRequest.daml | 33 +++++ .../App/Interface/Issuance/Issuance.daml | 34 +++++ .../App/Interface/Issuance/IssueRequest.daml | 35 ++++++ .../App/Interface/Issuance/Service.daml | 71 +++++++++++ src/daml/Daml/Finance/App/Issuance/Auto.daml | 117 ++++++++++++++++++ .../Finance/App/Issuance/Auto/Service.daml | 95 -------------- src/daml/Daml/Finance/App/Issuance/Model.daml | 35 +++++- .../Daml/Finance/App/Issuance/Service.daml | 92 ++++++-------- src/daml/Daml/Finance/App/Role/Custodian.daml | 45 ++++++- .../Setup/Scenario/FundTokenization.daml | 7 +- src/daml/Daml/Finance/Setup/Util/Service.daml | 30 +++-- .../Daml/Finance/Setup/Util/Workflow.daml | 20 +-- ui/src/context/ServicesContext.tsx | 38 +++--- .../investment/PooledRequests.tsx | 7 +- ui/src/pages/issuance/New.tsx | 41 +++--- ui/src/pages/issuance/Requests.tsx | 60 ++++----- 20 files changed, 566 insertions(+), 275 deletions(-) create mode 100644 src/daml/Daml/Finance/App/Interface/Issuance/Auto.daml create mode 100644 src/daml/Daml/Finance/App/Interface/Issuance/DeissueRequest.daml create mode 100644 src/daml/Daml/Finance/App/Interface/Issuance/Issuance.daml create mode 100644 src/daml/Daml/Finance/App/Interface/Issuance/IssueRequest.daml create mode 100644 src/daml/Daml/Finance/App/Interface/Issuance/Service.daml create mode 100644 src/daml/Daml/Finance/App/Issuance/Auto.daml delete mode 100644 src/daml/Daml/Finance/App/Issuance/Auto/Service.daml diff --git a/src/daml/Daml/Finance/App/Custody/Service.daml b/src/daml/Daml/Finance/App/Custody/Service.daml index 9feb2209..803b9692 100644 --- a/src/daml/Daml/Finance/App/Custody/Service.daml +++ b/src/daml/Daml/Finance/App/Custody/Service.daml @@ -71,14 +71,6 @@ template Service account.owner === customer Account.exerciseInterfaceByKey @Account.I account provider Account.Debit with holdingCid - choice Terminate : () - with - actor : Party - controller actor - do - assert $ actor == operator || actor == provider || actor == customer - pure () - template Offer with operator : Party diff --git a/src/daml/Daml/Finance/App/Distribution/Fund/Model.daml b/src/daml/Daml/Finance/App/Distribution/Fund/Model.daml index 3d383f32..f404ed17 100644 --- a/src/daml/Daml/Finance/App/Distribution/Fund/Model.daml +++ b/src/daml/Daml/Finance/App/Distribution/Fund/Model.daml @@ -3,10 +3,11 @@ module Daml.Finance.App.Distribution.Fund.Model where +import DA.Assert ((===)) import DA.Set (singleton) import Daml.Finance.App.Distribution.Investment.Model (InvestmentRequest) -import Daml.Finance.App.Issuance.Model qualified as Issuance (T) -import Daml.Finance.App.Issuance.Service qualified as Issuance (CreateIssuance(..), RequestCreateIssuance(..), Service) +import Daml.Finance.App.Interface.Issuance.Issuance qualified as Issuance (I) +import Daml.Finance.App.Interface.Issuance.Service qualified as IssuanceService (I, Issue(..), RequestIssue(..), asBase) import Daml.Finance.Interface.Account.Account qualified as Account (K) import Daml.Finance.Interface.Holding.Transferable qualified as Transferable (I) import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (K, Q) @@ -43,14 +44,19 @@ template Fund do pure this - choice IssueUnits : (ContractId Issuance.T, ContractId Transferable.I, ContractId Fund) + choice IssueUnits : (ContractId Issuance.I, ContractId Transferable.I, ContractId Fund) with requestId : Id quantity : Instrument.Q + issuanceServiceCid : ContractId IssuanceService.I controller manager do - createIssuanceRequestCid <- exerciseByKey @Issuance.Service (operator, custodian, manager) Issuance.RequestCreateIssuance with id = requestId; description = "Issuance for request " <> show requestId; quantity; account = managerFundAccount - (iss, holdingCid) <- exerciseByKey @Issuance.Service (operator, custodian, manager) Issuance.CreateIssuance with createIssuanceRequestCid + issuanceService <- view . IssuanceService.asBase <$> fetch issuanceServiceCid + issuanceService.operator === operator + issuanceService.provider === custodian + issuanceService.customer === manager + issueRequestCid <- exercise issuanceServiceCid IssuanceService.RequestIssue with issuanceId = requestId; description = "Issuance for request " <> show requestId; quantity; account = managerFundAccount + (iss, holdingCid) <- exercise issuanceServiceCid IssuanceService.Issue with issueRequestCid newCid <- create this with totalUnits = totalUnits + quantity.amount pure (iss, coerceContractId holdingCid, newCid) diff --git a/src/daml/Daml/Finance/App/Distribution/Fund/Service.daml b/src/daml/Daml/Finance/App/Distribution/Fund/Service.daml index 80ad5e15..68f10788 100644 --- a/src/daml/Daml/Finance/App/Distribution/Fund/Service.daml +++ b/src/daml/Daml/Finance/App/Distribution/Fund/Service.daml @@ -12,6 +12,7 @@ import DA.Time (time) import Daml.Finance.App.Data.AccountDirectory (AccountDirectory) import Daml.Finance.App.Distribution.Fund.Model qualified as Fund (ApproveInstruction(..), GetFund(..), IssueUnits(..), PooledInvestmentRequest(..), Remove(..), T) import Daml.Finance.App.Distribution.Investment.Model (AllocateInstruction(..), ApproveInstruction(..), Delete(..), InvestmentRequest(..)) +import Daml.Finance.App.Interface.Issuance.Service qualified as IssuanceService (I) import Daml.Finance.Interface.Data.NumericObservable qualified as NumericObservable (I, Observe(..)) import Daml.Finance.Interface.Holding.Base qualified as Holding (I) import Daml.Finance.Interface.Holding.Transferable qualified as Transferable (I) @@ -69,6 +70,7 @@ template Service fundCid : ContractId Fund.T navObservableCid : ContractId NumericObservable.I settlementFactoryCid : ContractId Settlement.Factory + issuanceServiceCid : ContractId IssuanceService.I controller provider do pir <- fetch pooledInvestmentRequestCid @@ -82,7 +84,7 @@ template Service fundQty = Instrument.qty nrUnits fund.instrument -- Issue units - (_, fundUnitsCid, fundCid) <- exercise fundCid Fund.IssueUnits with requestId = pir.requestId; quantity = fundQty + (_, fundUnitsCid, fundCid) <- exercise fundCid Fund.IssueUnits with requestId = pir.requestId; quantity = fundQty; issuanceServiceCid -- Instruct settlement irs <- mapA fetch pir.investmentRequestCids diff --git a/src/daml/Daml/Finance/App/Interface/Issuance/Auto.daml b/src/daml/Daml/Finance/App/Interface/Issuance/Auto.daml new file mode 100644 index 00000000..d654caae --- /dev/null +++ b/src/daml/Daml/Finance/App/Interface/Issuance/Auto.daml @@ -0,0 +1,53 @@ +-- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +-- SPDX-License-Identifier: Apache-2.0 + +module Daml.Finance.App.Interface.Issuance.Auto where + +import Daml.Finance.App.Interface.Base.Service qualified as Base (I) +import Daml.Finance.App.Interface.Issuance.Issuance qualified as Issuance (I) +import Daml.Finance.App.Interface.Issuance.Service qualified as Service (I, Implementation, asBase) +import Daml.Finance.Interface.Holding.Base qualified as Holding (I) +import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (Q) +import Daml.Finance.Interface.Types.Common (AccountKey, Id) + +type I = Service + +type V = View + +data View = View {} + deriving (Eq, Show) + +interface Service where + viewtype V + + asService : Service.I + -- ^ Conversion to custody `Service` interface. + requestAndIssue : ContractId Service.I -> RequestAndIssue -> Update (ContractId Issuance.I, ContractId Holding.I) + -- ^ Implementation of the `RequestOpenAccount` choice. + requestAndDeissue : ContractId Service.I -> RequestAndDeissue -> Update (ContractId Issuance.I) + -- ^ Implementation of the `RequestCloseAccount` choice. + + nonconsuming choice RequestAndIssue : (ContractId Issuance.I, ContractId Holding.I) + with + issuanceId : Id + description : Text + quantity : Instrument.Q + account : AccountKey + controller (view $ Service.asBase $ asService this).customer + do + requestAndIssue this (toInterfaceContractId self) arg + + nonconsuming choice RequestAndDeissue : (ContractId Issuance.I) + with + issuanceId : Id + holdingCid : ContractId Holding.I + controller (view $ Service.asBase $ asService this).customer + do + requestAndDeissue this (toInterfaceContractId self) arg + +-- | Type constraint for requiring templates to implement `Service`. +type Implementation t = (HasToInterface t Service, Service.Implementation t) +class (Implementation t) => HasImplementation t +instance HasImplementation Service +instance HasToInterface Service Service.I where _toInterface = asService +instance HasToInterface Service Base.I where _toInterface = Service.asBase . asService diff --git a/src/daml/Daml/Finance/App/Interface/Issuance/DeissueRequest.daml b/src/daml/Daml/Finance/App/Interface/Issuance/DeissueRequest.daml new file mode 100644 index 00000000..5282a91e --- /dev/null +++ b/src/daml/Daml/Finance/App/Interface/Issuance/DeissueRequest.daml @@ -0,0 +1,33 @@ +-- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +-- SPDX-License-Identifier: Apache-2.0 + +module Daml.Finance.App.Interface.Issuance.DeissueRequest where + +import Daml.Finance.App.Interface.Common.Removable qualified as Removable (I, Implementation) +import Daml.Finance.Interface.Holding.Base qualified as Holding (I) +import Daml.Finance.Interface.Types.Common (Id) + +type I = DeissueRequest + +type V = View + +data View = View + with + operator : Party + provider : Party + customer : Party + issuanceId : Id + holdingCid : ContractId Holding.I + deriving (Eq, Show) + +interface DeissueRequest where + viewtype View + -- ^ Interface view types. + asRemovable : Removable.I + -- ^ Conversion to the `Removable` interface. + +-- | Type constraint for requiring templates to implement `DeissueRequest`. +type Implementation t = (HasToInterface t DeissueRequest, Removable.Implementation t) +class (Implementation t) => HasImplementation t +instance HasImplementation DeissueRequest +instance HasToInterface DeissueRequest Removable.I where _toInterface = asRemovable diff --git a/src/daml/Daml/Finance/App/Interface/Issuance/Issuance.daml b/src/daml/Daml/Finance/App/Interface/Issuance/Issuance.daml new file mode 100644 index 00000000..1610e95a --- /dev/null +++ b/src/daml/Daml/Finance/App/Interface/Issuance/Issuance.daml @@ -0,0 +1,34 @@ +-- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +-- SPDX-License-Identifier: Apache-2.0 + +module Daml.Finance.App.Interface.Issuance.Issuance where + +import Daml.Finance.App.Interface.Common.Removable qualified as Removable (I, Implementation) +import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (Q) +import Daml.Finance.Interface.Types.Common (Id) + +type I = Issuance + +type V = View + +data View = View + with + operator : Party + provider : Party + customer : Party + id : Id + description : Text + quantity : Instrument.Q + deriving (Eq, Show) + +interface Issuance where + viewtype View + -- ^ Interface view types. + asRemovable : Removable.I + -- ^ Conversion to the `Removable` interface. + +-- | Type constraint for requiring templates to implement `Issuance`. +type Implementation t = (HasToInterface t Issuance, Removable.Implementation t) +class (Implementation t) => HasImplementation t +instance HasImplementation Issuance +instance HasToInterface Issuance Removable.I where _toInterface = asRemovable diff --git a/src/daml/Daml/Finance/App/Interface/Issuance/IssueRequest.daml b/src/daml/Daml/Finance/App/Interface/Issuance/IssueRequest.daml new file mode 100644 index 00000000..eb5ee673 --- /dev/null +++ b/src/daml/Daml/Finance/App/Interface/Issuance/IssueRequest.daml @@ -0,0 +1,35 @@ +-- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +-- SPDX-License-Identifier: Apache-2.0 + +module Daml.Finance.App.Interface.Issuance.IssueRequest where + +import Daml.Finance.App.Interface.Common.Removable qualified as Removable (I, Implementation) +import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (Q) +import Daml.Finance.Interface.Types.Common (AccountKey, Id) + +type I = IssueRequest + +type V = View + +data View = View + with + operator : Party + provider : Party + customer : Party + issuanceId : Id + description : Text + quantity : Instrument.Q + account : AccountKey + deriving (Eq, Show) + +interface IssueRequest where + viewtype View + -- ^ Interface view types. + asRemovable : Removable.I + -- ^ Conversion to the `Removable` interface. + +-- | Type constraint for requiring templates to implement `IssueRequest`. +type Implementation t = (HasToInterface t IssueRequest, Removable.Implementation t) +class (Implementation t) => HasImplementation t +instance HasImplementation IssueRequest +instance HasToInterface IssueRequest Removable.I where _toInterface = asRemovable diff --git a/src/daml/Daml/Finance/App/Interface/Issuance/Service.daml b/src/daml/Daml/Finance/App/Interface/Issuance/Service.daml new file mode 100644 index 00000000..9e769441 --- /dev/null +++ b/src/daml/Daml/Finance/App/Interface/Issuance/Service.daml @@ -0,0 +1,71 @@ +-- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +-- SPDX-License-Identifier: Apache-2.0 + +module Daml.Finance.App.Interface.Issuance.Service where + +import Daml.Finance.Interface.Holding.Base qualified as Holding (I) +import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (Q) +import Daml.Finance.Interface.Types.Common (AccountKey, Id) +import Daml.Finance.App.Interface.Base.Service qualified as Base (I, Implementation) +import Daml.Finance.App.Interface.Issuance.Issuance qualified as Issuance (I) +import Daml.Finance.App.Interface.Issuance.IssueRequest qualified as IssueRequest (I) +import Daml.Finance.App.Interface.Issuance.DeissueRequest qualified as DeissueRequest (I) + +type I = Service + +type V = View + +data View = View {} + deriving (Eq, Show) + +interface Service where + viewtype V + + asBase : Base.I + -- ^ Conversion to base `Service` interface. + requestIssue : RequestIssue -> Update (ContractId IssueRequest.I) + -- ^ Implementation of the `RequestIssue` choice. + requestDeissue : RequestDeissue -> Update (ContractId DeissueRequest.I) + -- ^ Implementation of the `RequestDeissue` choice. + issue : Issue -> Update (ContractId Issuance.I, ContractId Holding.I) + -- ^ Implementation of the `Issue` choice. + deissue : Deissue -> Update (ContractId Issuance.I) + -- ^ Implementation of the `Deissue` choice. + + nonconsuming choice RequestIssue : ContractId IssueRequest.I + with + issuanceId : Id + description : Text + quantity : Instrument.Q + account : AccountKey + controller (view $ asBase this).customer + do + requestIssue this arg + + nonconsuming choice RequestDeissue : ContractId DeissueRequest.I + with + issuanceId : Id + holdingCid : ContractId Holding.I + controller (view $ asBase this).customer + do + requestDeissue this arg + + nonconsuming choice Issue : (ContractId Issuance.I, ContractId Holding.I) + with + issueRequestCid : ContractId IssueRequest.I + controller (view $ asBase this).provider + do + issue this arg + + nonconsuming choice Deissue : (ContractId Issuance.I) + with + deissueRequestCid : ContractId DeissueRequest.I + controller (view $ asBase this).provider + do + deissue this arg + +-- | Type constraint for requiring templates to implement `Service`. +type Implementation t = (HasToInterface t Service, Base.Implementation t) +class (Implementation t) => HasImplementation t +instance HasImplementation Service +instance HasToInterface Service Base.I where _toInterface = asBase diff --git a/src/daml/Daml/Finance/App/Issuance/Auto.daml b/src/daml/Daml/Finance/App/Issuance/Auto.daml new file mode 100644 index 00000000..4ba1cd05 --- /dev/null +++ b/src/daml/Daml/Finance/App/Issuance/Auto.daml @@ -0,0 +1,117 @@ +-- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +-- SPDX-License-Identifier: Apache-2.0 + +module Daml.Finance.App.Issuance.Auto where + +import DA.Assert ((===)) +import Daml.Finance.App.Issuance.Model qualified as Model +import Daml.Finance.App.Interface.Base.Service qualified as Base (I, View(..)) +import Daml.Finance.App.Interface.Common.Util (fetchAndRemove) +import Daml.Finance.App.Interface.Issuance.Auto qualified as Auto (HasImplementation, I, View(..), RequestAndDeissue(..), RequestAndIssue(..)) +import Daml.Finance.App.Interface.Issuance.DeissueRequest qualified as DeissueRequest (View(..)) +import Daml.Finance.App.Interface.Issuance.IssueRequest qualified as IssueRequest (View(..)) +import Daml.Finance.App.Interface.Issuance.Service qualified as Service (Deissue(..), Issue(..), I, RequestDeissue(..), RequestIssue(..), View(..)) +import Daml.Finance.Interface.Account.Account qualified as Account (Credit(..), Debit(..), I, exerciseInterfaceByKey) +import Daml.Finance.Interface.Account.Util (getAccount) +import Daml.Finance.Interface.Holding.Util (getAmount) +import Daml.Finance.App.Issuance.Model (DeissueRequest(..), Issuance(..), IssueRequest(..)) + +instance Auto.HasImplementation Service + +template Service + with + operator : Party + provider : Party + customer : Party + where + signatory operator, provider, customer + + key (operator, provider, customer) : (Party, Party, Party) + maintainer key._1 + + interface instance Base.I for Service where + view = Base.View with operator; provider; customer + terminate = pure () + + interface instance Service.I for Service where + view = Service.View + asBase = toInterface @Base.I this + requestIssue Service.RequestIssue{issuanceId; description; quantity; account} = do + toInterfaceContractId <$> create Model.IssueRequest with operator; provider; customer; issuanceId; description; quantity; account + requestDeissue Service.RequestDeissue{issuanceId; holdingCid} = do + toInterfaceContractId <$> create Model.DeissueRequest with operator; provider; customer; issuanceId; holdingCid + issue Service.Issue{issueRequestCid} = do + IssueRequest.View{issuanceId; description; quantity; account} <- view <$> fetchAndRemove issueRequestCid + issuanceCid <- toInterfaceContractId <$> create Issuance with operator; provider; customer; id = issuanceId; description; quantity + account.custodian === provider + account.owner === customer + holdingCid <- Account.exerciseInterfaceByKey @Account.I account provider Account.Credit with quantity + pure (issuanceCid, holdingCid) + deissue Service.Deissue{deissueRequestCid} = do + DeissueRequest.View{issuanceId; holdingCid} <- view <$> fetchAndRemove deissueRequestCid + holding <- fetch holdingCid + let + account = getAccount holding + amount = getAmount holding + account.custodian === provider + account.owner === customer + Account.exerciseInterfaceByKey @Account.I account provider Account.Debit with holdingCid + (issuanceCid, issuance) <- fetchByKey @Issuance (operator, provider, issuanceId) + archive issuanceCid + toInterfaceContractId <$> create issuance with quantity = (issuance.quantity with amount = issuance.quantity.amount - amount) + + interface instance Auto.I for Service where + view = Auto.View + asService = toInterface @Service.I this + requestAndIssue self Auto.RequestAndIssue{issuanceId; description; quantity; account} = do + issueRequestCid <- exercise self Service.RequestIssue with issuanceId; description; quantity; account + exercise self Service.Issue with issueRequestCid + requestAndDeissue self Auto.RequestAndDeissue{issuanceId; holdingCid} = do + deissueRequestCid <- exercise self Service.RequestDeissue with issuanceId; holdingCid + exercise self Service.Deissue with deissueRequestCid + + +template Offer + with + operator : Party + provider : Party + customer : Party + where + signatory operator, provider + observer customer + + choice Accept : ContractId Service + controller customer + do + create Service with .. + + choice Decline : () + controller customer + do pure () + + choice Withdraw : () + controller provider + do pure () + +template Request + with + customer : Party + provider : Party + where + signatory customer + observer provider + + choice Cancel : () + controller customer + do pure () + + choice Reject : () + controller provider + do pure () + + choice Approve : ContractId Service + with + operator : Party + controller operator, provider + do + create Service with .. diff --git a/src/daml/Daml/Finance/App/Issuance/Auto/Service.daml b/src/daml/Daml/Finance/App/Issuance/Auto/Service.daml deleted file mode 100644 index 997b2ed2..00000000 --- a/src/daml/Daml/Finance/App/Issuance/Auto/Service.daml +++ /dev/null @@ -1,95 +0,0 @@ --- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. --- SPDX-License-Identifier: Apache-2.0 - -module Daml.Finance.App.Issuance.Auto.Service where - -import Daml.Finance.App.Issuance.Model (Issuance) -import Daml.Finance.App.Issuance.Service qualified as S (CreateIssuance(..), ReduceIssuance(..), RequestCreateIssuance(..), RequestReduceIssuance(..), Service) -import Daml.Finance.Interface.Account.Account qualified as Account (K) -import Daml.Finance.Interface.Holding.Base qualified as Holding (I) -import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (Q) -import Daml.Finance.Interface.Types.Common (Id) - -template Service - with - operator : Party - provider : Party - customer : Party - where - signatory operator, provider, customer - - key (operator, provider, customer) : (Party, Party, Party) - maintainer key._1 - - nonconsuming choice RequestAndCreateIssuance : (ContractId Issuance, ContractId Holding.I) - with - id : Id - description : Text - quantity : Instrument.Q - account : Account.K - controller customer - do - createIssuanceRequestCid <- exerciseByKey @S.Service (operator, provider, customer) S.RequestCreateIssuance with id; description; quantity; account - exerciseByKey @S.Service (operator, provider, customer) S.CreateIssuance with createIssuanceRequestCid - - nonconsuming choice RequestAndReduceIssuance : ContractId Issuance - with - id : Id - holdingCid : ContractId Holding.I - controller customer - do - reduceIssuanceRequestCid <- exerciseByKey @S.Service (operator, provider, customer) S.RequestReduceIssuance with id; holdingCid - exerciseByKey @S.Service (operator, provider, customer) S.ReduceIssuance with reduceIssuanceRequestCid - - choice Terminate : () - with - actor : Party - controller actor - do - assert $ actor == operator || actor == provider || actor == customer - pure () - -template Offer - with - operator : Party - provider : Party - customer : Party - where - signatory operator, provider - observer customer - - choice Accept : ContractId Service - controller customer - do - create Service with .. - - choice Decline : () - controller customer - do pure () - - choice Withdraw : () - controller provider - do pure () - -template Request - with - customer : Party - provider : Party - where - signatory customer - observer provider - - choice Cancel : () - controller customer - do pure () - - choice Reject : () - controller provider - do pure () - - choice Approve : ContractId Service - with - operator : Party - controller operator, provider - do - create Service with .. diff --git a/src/daml/Daml/Finance/App/Issuance/Model.daml b/src/daml/Daml/Finance/App/Issuance/Model.daml index 74294f00..ead314a6 100644 --- a/src/daml/Daml/Finance/App/Issuance/Model.daml +++ b/src/daml/Daml/Finance/App/Issuance/Model.daml @@ -3,6 +3,11 @@ module Daml.Finance.App.Issuance.Model where +import DA.Set (fromList) +import Daml.Finance.App.Interface.Common.Removable qualified as Removable (I, View(..)) +import Daml.Finance.App.Interface.Issuance.DeissueRequest qualified as DeissueRequest (I, View(..)) +import Daml.Finance.App.Interface.Issuance.Issuance qualified as Issuance (I, View(..)) +import Daml.Finance.App.Interface.Issuance.IssueRequest qualified as IssueRequest (I, View(..)) import Daml.Finance.Interface.Account.Account qualified as Account (K) import Daml.Finance.Interface.Holding.Base qualified as Holding (I) import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (Q) @@ -24,24 +29,46 @@ template Issuance key (operator, provider, id) : (Party, Party, Id) maintainer key._1 -template CreateIssuanceRequest + interface instance Removable.I for Issuance where + view = Removable.View with removers = fromList [operator, provider, customer] + + interface instance Issuance.I for Issuance where + view = Issuance.View with operator; provider; customer; id; description; quantity + asRemovable = toInterface @Removable.I this + +template IssueRequest with operator : Party provider : Party customer : Party - id : Id + issuanceId : Id description : Text quantity : Instrument.Q account : Account.K where signatory operator, provider, customer -template ReduceIssuanceRequest + interface instance Removable.I for IssueRequest where + view = Removable.View with removers = fromList [operator, provider, customer] + + interface instance IssueRequest.I for IssueRequest where + view = IssueRequest.View with operator; provider; customer; issuanceId; description; quantity; account + asRemovable = toInterface @Removable.I this + +template DeissueRequest with operator : Party provider : Party customer : Party - id : Id + issuanceId : Id holdingCid : ContractId Holding.I where signatory operator, provider, customer + + interface instance Removable.I for DeissueRequest where + view = Removable.View with removers = fromList [operator, provider, customer] + + interface instance DeissueRequest.I for DeissueRequest where + view = DeissueRequest.View with operator; provider; customer; issuanceId; holdingCid + asRemovable = toInterface @Removable.I this + diff --git a/src/daml/Daml/Finance/App/Issuance/Service.daml b/src/daml/Daml/Finance/App/Issuance/Service.daml index f77cfecc..021f5c20 100644 --- a/src/daml/Daml/Finance/App/Issuance/Service.daml +++ b/src/daml/Daml/Finance/App/Issuance/Service.daml @@ -3,14 +3,19 @@ module Daml.Finance.App.Issuance.Service where -import Daml.Finance.Interface.Account.Account qualified as Account (Credit(..), Debit(..), K, R) +import DA.Assert ((===)) +import Daml.Finance.App.Issuance.Model qualified as Model +import Daml.Finance.App.Interface.Base.Service qualified as Base (I, View(..)) +import Daml.Finance.App.Interface.Common.Util (fetchAndRemove) +import Daml.Finance.App.Interface.Issuance.IssueRequest qualified as IssueRequest (View(..)) +import Daml.Finance.App.Interface.Issuance.DeissueRequest qualified as DeissueRequest (View(..)) +import Daml.Finance.App.Interface.Issuance.Service qualified as Service +import Daml.Finance.Interface.Account.Account qualified as Account (Credit(..), Debit(..), I, exerciseInterfaceByKey) import Daml.Finance.Interface.Account.Util (getAccount) -import Daml.Finance.Interface.Holding.Base qualified as Holding (I) import Daml.Finance.Interface.Holding.Util (getAmount) -import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (Q) -import Daml.Finance.Interface.Types.Common (Id) -import Daml.Finance.App.Issuance.Model (CreateIssuanceRequest(..), ReduceIssuanceRequest(..), Issuance(..)) -import Daml.Finance.App.Util (fetchAndArchive) +import Daml.Finance.App.Issuance.Model (DeissueRequest(..), Issuance(..), IssueRequest(..)) + +instance Service.HasImplementation Service template Service with @@ -23,59 +28,36 @@ template Service key (operator, provider, customer) : (Party, Party, Party) maintainer key._1 - nonconsuming choice RequestCreateIssuance : ContractId CreateIssuanceRequest - with - id : Id - description : Text - quantity : Instrument.Q - account : Account.K - controller customer - do - create CreateIssuanceRequest with .. - - nonconsuming choice RequestReduceIssuance : ContractId ReduceIssuanceRequest - with - id : Id - holdingCid : ContractId Holding.I - controller customer - do - create ReduceIssuanceRequest with .. - - nonconsuming choice CreateIssuance : (ContractId Issuance, ContractId Holding.I) - with - createIssuanceRequestCid : ContractId CreateIssuanceRequest - controller provider - do - CreateIssuanceRequest{id; description; account; quantity} <- fetchAndArchive createIssuanceRequestCid - issuanceCid <- create Issuance with operator; provider; customer; id; description; quantity - - (_, ref) <- fetchByKey @Account.R account - transferableCid <- exercise ref.cid Account.Credit with quantity - pure (issuanceCid, transferableCid) - - nonconsuming choice ReduceIssuance : ContractId Issuance - with - reduceIssuanceRequestCid : ContractId ReduceIssuanceRequest - controller provider - do - ReduceIssuanceRequest{id; holdingCid} <- fetchAndArchive reduceIssuanceRequestCid + interface instance Base.I for Service where + view = Base.View with operator; provider; customer + terminate = pure () + + interface instance Service.I for Service where + view = Service.View + asBase = toInterface @Base.I this + requestIssue Service.RequestIssue{issuanceId; description; quantity; account} = do + toInterfaceContractId <$> create Model.IssueRequest with operator; provider; customer; issuanceId; description; quantity; account + requestDeissue Service.RequestDeissue{issuanceId; holdingCid} = do + toInterfaceContractId <$> create Model.DeissueRequest with operator; provider; customer; issuanceId; holdingCid + issue Service.Issue{issueRequestCid} = do + IssueRequest.View{issuanceId; description; quantity; account} <- view <$> fetchAndRemove issueRequestCid + issuanceCid <- toInterfaceContractId <$> create Issuance with operator; provider; customer; id = issuanceId; description; quantity + account.custodian === provider + account.owner === customer + holdingCid <- Account.exerciseInterfaceByKey @Account.I account provider Account.Credit with quantity + pure (issuanceCid, holdingCid) + deissue Service.Deissue{deissueRequestCid} = do + DeissueRequest.View{issuanceId; holdingCid} <- view <$> fetchAndRemove deissueRequestCid holding <- fetch holdingCid let - amount = getAmount holding account = getAccount holding - (_, ref) <- fetchByKey @Account.R account - exercise ref.cid Account.Debit with holdingCid - (issuanceCid, issuance) <- fetchByKey @Issuance (operator, provider, id) + amount = getAmount holding + account.custodian === provider + account.owner === customer + Account.exerciseInterfaceByKey @Account.I account provider Account.Debit with holdingCid + (issuanceCid, issuance) <- fetchByKey @Issuance (operator, provider, issuanceId) archive issuanceCid - create issuance with quantity = (issuance.quantity with amount = issuance.quantity.amount - amount) - - choice Terminate : () - with - actor : Party - controller actor - do - assert $ actor == operator || actor == provider || actor == customer - pure () + toInterfaceContractId <$> create issuance with quantity = (issuance.quantity with amount = issuance.quantity.amount - amount) template Offer with diff --git a/src/daml/Daml/Finance/App/Role/Custodian.daml b/src/daml/Daml/Finance/App/Role/Custodian.daml index 248e1eef..ba41457e 100644 --- a/src/daml/Daml/Finance/App/Role/Custodian.daml +++ b/src/daml/Daml/Finance/App/Role/Custodian.daml @@ -4,9 +4,11 @@ module Daml.Finance.App.Role.Custodian where import Daml.Finance.App.BackToBack.Service qualified as BackToBack (Approve(..), Offer(..), Request, Service, Terminate(..)) -import Daml.Finance.App.Custody.Service qualified as Custody (Approve(..), Offer(..), Request, Service, Terminate(..)) -import Daml.Finance.App.Issuance.Auto.Service qualified as IssuanceAuto (Approve(..), Offer(..), Request, Service, Terminate(..)) -import Daml.Finance.App.Issuance.Service qualified as Issuance (Approve(..), Offer(..), Request, Service, Terminate(..)) +import Daml.Finance.App.Custody.Auto qualified as CustodyAuto (Approve(..), Offer(..), Request, Service) +import Daml.Finance.App.Custody.Service qualified as Custody (Approve(..), Offer(..), Request, Service) +import Daml.Finance.App.Interface.Base.Service qualified as Base (I, Terminate(..)) +import Daml.Finance.App.Issuance.Auto qualified as IssuanceAuto (Approve(..), Offer(..), Request, Service) +import Daml.Finance.App.Issuance.Service qualified as Issuance (Approve(..), Offer(..), Request, Service) import Daml.Finance.App.Lending.Service qualified as Lending (Approve(..), Offer(..), Request, Service, Terminate(..)) import Daml.Finance.App.Lifecycle.Service qualified as Lifecycle (Approve(..), Offer(..), Request, Service, Terminate(..)) import Daml.Finance.App.Settlement.Service qualified as Settlement (Approve(..), Offer(..), Request, Service, Terminate(..)) @@ -52,7 +54,36 @@ template Role customer : Party controller provider do - exerciseByKey @Custody.Service (operator, provider, customer) Custody.Terminate with actor = provider + (serviceCid, _) <- fetchByKey @Custody.Service (operator, provider, customer) + exercise (toInterfaceContractId @Base.I serviceCid) Base.Terminate with actor = provider + + nonconsuming choice OfferCustodyAutoService : ContractId CustodyAuto.Offer + with + customer : Party + claimRuleCid : ContractId Lifecycle.Claim + accountFactoryCid : ContractId Account.F + holdingFactoryCid : ContractId Holding.F + controller provider + do + create CustodyAuto.Offer with operator; provider; customer; claimRuleCid; accountFactoryCid; holdingFactoryCid + + nonconsuming choice ApproveCustodyAutoRequest : ContractId CustodyAuto.Service + with + custodyRequestCid : ContractId CustodyAuto.Request + claimRuleCid : ContractId Lifecycle.Claim + accountFactoryCid : ContractId Account.F + holdingFactoryCid : ContractId Holding.F + controller provider + do + exercise custodyRequestCid CustodyAuto.Approve with operator; claimRuleCid; accountFactoryCid; holdingFactoryCid + + nonconsuming choice TerminateCustodyAutoService : () + with + customer : Party + controller provider + do + (serviceCid, _) <- fetchByKey @CustodyAuto.Service (operator, provider, customer) + exercise (toInterfaceContractId @Base.I serviceCid) Base.Terminate with actor = provider nonconsuming choice OfferIssuanceService : ContractId Issuance.Offer with @@ -73,7 +104,8 @@ template Role customer : Party controller provider do - exerciseByKey @Issuance.Service (operator, provider, customer) Issuance.Terminate with actor = provider + (serviceCid, _) <- fetchByKey @Issuance.Service (operator, provider, customer) + exercise (toInterfaceContractId @Base.I serviceCid) Base.Terminate with actor = provider nonconsuming choice OfferIssuanceAutoService : ContractId IssuanceAuto.Offer with @@ -94,7 +126,8 @@ template Role customer : Party controller provider do - exerciseByKey @IssuanceAuto.Service (operator, provider, customer) IssuanceAuto.Terminate with actor = provider + (serviceCid, _) <- fetchByKey @IssuanceAuto.Service (operator, provider, customer) + exercise (toInterfaceContractId @Base.I serviceCid) Base.Terminate with actor = provider nonconsuming choice OfferBackToBackService : ContractId BackToBack.Offer with diff --git a/src/daml/Daml/Finance/Setup/Scenario/FundTokenization.daml b/src/daml/Daml/Finance/Setup/Scenario/FundTokenization.daml index 17448fd9..acec17f9 100644 --- a/src/daml/Daml/Finance/Setup/Scenario/FundTokenization.daml +++ b/src/daml/Daml/Finance/Setup/Scenario/FundTokenization.daml @@ -55,8 +55,7 @@ run = do createCustodyService operator am inv3 settlementFactoryCid accountFactoryCid holdingFactoryCid createCustodyService operator custodian am settlementFactoryCid accountFactoryCid holdingFactoryCid createCustodyService operator custodian pm settlementFactoryCid accountFactoryCid holdingFactoryCid - createIssuanceService operator custodian pm - createIssuanceAutoService operator custodian pm + issuanceServiceCid <- toInterfaceContractId <$> createIssuanceAutoService operator custodian pm createStructuringService operator custodian pm createStructuringAutoService operator custodian pm createInvestmentService operator am inv1 @@ -117,7 +116,7 @@ run = do ir2Cid <- createInvestmentRequest operator am inv2 public "REQ-FUND1-INV2" today fund1Cid (coerceContractId inv2CashCid) ir3Cid <- createInvestmentRequest operator am inv3 public "REQ-FUND1-INV3" today fund1Cid (coerceContractId inv3CashCid) pirCid <- poolInvestmentRequests operator pm am public "REQ-FUND1-POOLED" today fund1Cid (coerceContractId amCashCid) [ir1Cid, ir2Cid, ir3Cid] - fulfillPooledInvestmentRequest operator pm am public fund1Cid pirCid navFund1Cid settlementFactoryCid - -- doDistribution + fulfillPooledInvestmentRequest operator pm am public fund1Cid pirCid navFund1Cid settlementFactoryCid issuanceServiceCid + --doDistribution pure parties diff --git a/src/daml/Daml/Finance/Setup/Util/Service.daml b/src/daml/Daml/Finance/Setup/Util/Service.daml index a04e3fef..5ff7d8c5 100644 --- a/src/daml/Daml/Finance/Setup/Util/Service.daml +++ b/src/daml/Daml/Finance/Setup/Util/Service.daml @@ -5,11 +5,16 @@ module Daml.Finance.Setup.Util.Service where import DA.Map qualified as M (fromList) import DA.Set (fromList, singleton) -import Daml.Finance.App.Custody.Service qualified as Custody (Accept(..), Service) +import Daml.Finance.App.Custody.Auto qualified as CustodyAuto (Accept(..)) +import Daml.Finance.App.Custody.Service qualified as Custody (Accept(..)) import Daml.Finance.App.Decentralized.Exchange.Model qualified as DecentralizedExchange (Pool(..)) import Daml.Finance.App.Decentralized.Exchange.Service qualified as DecentralizedExchange (Service(..)) -import Daml.Finance.App.Issuance.Auto.Service qualified as IssuanceAuto (Accept(..), Service) -import Daml.Finance.App.Issuance.Service qualified as Issuance (Accept(..), Service) +import Daml.Finance.App.Interface.Custody.Auto qualified as CustodyAuto (I) +import Daml.Finance.App.Interface.Custody.Service qualified as Custody (I) +import Daml.Finance.App.Interface.Issuance.Auto qualified as IssuanceAuto (I) +import Daml.Finance.App.Interface.Issuance.Service qualified as Issuance (I) +import Daml.Finance.App.Issuance.Auto qualified as IssuanceAuto (Accept(..)) +import Daml.Finance.App.Issuance.Service qualified as Issuance (Accept(..)) import Daml.Finance.App.BackToBack.Service qualified as BackToBack (Accept(..), Service) import Daml.Finance.App.Lifecycle.Service qualified as Lifecycle (Accept(..), Service) import Daml.Finance.App.Trading.Auto.Service qualified as TradingAuto (Accept(..), Service) @@ -50,22 +55,29 @@ import Daml.Finance.Lifecycle.Rule.Distribution qualified as Distribution (Rule( import Daml.Finance.Lifecycle.Rule.Replacement qualified as Replacement (Rule(..)) import Daml.Script -createCustodyService : Party -> Party -> Party -> ContractId Settlement.Factory -> ContractId Account.F -> ContractId Holding.F -> Script (ContractId Custody.Service) +createCustodyService : Party -> Party -> Party -> ContractId Settlement.Factory -> ContractId Account.F -> ContractId Holding.F -> Script (ContractId Custody.I) createCustodyService operator custodian customer settlementFactoryCid accountFactoryCid holdingFactoryCid = do let providers = fromList [custodian, customer] claimRuleCid <- toInterfaceContractId <$> submitMulti [custodian, customer] [] do createCmd Claim.Rule with providers = fromList [custodian, customer]; claimers = providers; settlers = providers; settlementFactoryCid; netInstructions = False offerCid <- submit custodian do exerciseByKeyCmd @Custodian.Role (operator, custodian) Custodian.OfferCustodyService with customer; claimRuleCid; accountFactoryCid; holdingFactoryCid - submit customer do exerciseCmd offerCid Custody.Accept + toInterfaceContractId <$> submit customer do exerciseCmd offerCid Custody.Accept -createIssuanceService : Party -> Party -> Party -> Script (ContractId Issuance.Service) +createCustodyAutoService : Party -> Party -> Party -> ContractId Settlement.Factory -> ContractId Account.F -> ContractId Holding.F -> Script (ContractId CustodyAuto.I) +createCustodyAutoService operator custodian customer settlementFactoryCid accountFactoryCid holdingFactoryCid = do + let providers = fromList [custodian, customer] + claimRuleCid <- toInterfaceContractId <$> submitMulti [custodian, customer] [] do createCmd Claim.Rule with providers = fromList [custodian, customer]; claimers = providers; settlers = providers; settlementFactoryCid; netInstructions = False + offerCid <- submit custodian do exerciseByKeyCmd @Custodian.Role (operator, custodian) Custodian.OfferCustodyAutoService with customer; claimRuleCid; accountFactoryCid; holdingFactoryCid + toInterfaceContractId <$> submit customer do exerciseCmd offerCid CustodyAuto.Accept + +createIssuanceService : Party -> Party -> Party -> Script (ContractId Issuance.I) createIssuanceService operator custodian customer = do offerCid <- submit custodian do exerciseByKeyCmd @Custodian.Role (operator, custodian) Custodian.OfferIssuanceService with .. - submit customer do exerciseCmd offerCid Issuance.Accept + toInterfaceContractId <$> submit customer do exerciseCmd offerCid Issuance.Accept -createIssuanceAutoService : Party -> Party -> Party -> Script (ContractId IssuanceAuto.Service) +createIssuanceAutoService : Party -> Party -> Party -> Script (ContractId IssuanceAuto.I) createIssuanceAutoService operator custodian customer = do offerCid <- submit custodian do exerciseByKeyCmd @Custodian.Role (operator, custodian) Custodian.OfferIssuanceAutoService with .. - submit customer do exerciseCmd offerCid IssuanceAuto.Accept + toInterfaceContractId <$> submit customer do exerciseCmd offerCid IssuanceAuto.Accept createStructuringService : Party -> Party -> Party -> Script (ContractId Structuring.Service) createStructuringService operator custodian customer = do diff --git a/src/daml/Daml/Finance/Setup/Util/Workflow.daml b/src/daml/Daml/Finance/Setup/Util/Workflow.daml index 2b5ebc71..11c7db57 100644 --- a/src/daml/Daml/Finance/Setup/Util/Workflow.daml +++ b/src/daml/Daml/Finance/Setup/Util/Workflow.daml @@ -19,8 +19,9 @@ import Daml.Finance.App.Distribution.Fund.Service qualified as Fund (FulfillPool import Daml.Finance.App.Distribution.Investment.Model qualified as Investment (InvestmentRequest) import Daml.Finance.App.Distribution.Investment.Service qualified as Investment (RequestInvestment(..), S) import Daml.Finance.App.Interface.Custody.Service qualified as Custody (Deposit(..), I, OpenAccount(..), RequestDeposit(..), RequestOpenAccount(..)) -import Daml.Finance.App.Issuance.Model qualified as Issuance (T) -import Daml.Finance.App.Issuance.Service qualified as Issuance (CreateIssuance(..), RequestCreateIssuance(..), Service) +import Daml.Finance.App.Interface.Issuance.Issuance qualified as Issuance (I) +import Daml.Finance.App.Interface.Issuance.Service qualified as IssuanceService (I, Issue(..), RequestIssue(..)) +import Daml.Finance.App.Issuance.Service qualified as Issuance (Service) import Daml.Finance.App.Lifecycle.Service qualified as Lifecycle (Service, DeclareDividend(..), DeclareStockSplit(..), DeclareReplacement(..)) import Daml.Finance.App.Listing.Model qualified as Listing (T) import Daml.Finance.App.Listing.Service qualified as Listing (CreateListing(..), RequestCreateListing(..), Service) @@ -195,13 +196,14 @@ deposit operator provider customer public quantity account = do depositRequestCid <- submit customer do exerciseCmd (toInterfaceContractId @Custody.I custodyServiceCid) Custody.RequestDeposit with quantity; account submitMulti [provider] [public] do exerciseCmd (toInterfaceContractId @Custody.I custodyServiceCid) Custody.Deposit with depositRequestCid -issue : Party -> Party -> Party -> Party -> Instrument.Q -> Account.K -> Script (ContractId Issuance.T, ContractId Holding.I) +issue : Party -> Party -> Party -> Party -> Instrument.Q -> Account.K -> Script (ContractId Issuance.I, ContractId Holding.I) issue operator provider customer public quantity account = do let - id = Id $ "ISSUANCE-" <> show quantity.unit.id + issuanceId = Id $ "ISSUANCE-" <> show quantity.unit.id description = "Issuance of " <> show quantity.amount <> " " <> show quantity.unit.id - createIssuanceRequestCid <- submit customer do exerciseByKeyCmd @Issuance.Service (operator, provider, customer) Issuance.RequestCreateIssuance with id; description; quantity; account - submitMulti [provider] [public] do exerciseByKeyCmd @Issuance.Service (operator, provider, customer) Issuance.CreateIssuance with .. + Some (issuanceServiceCid, _) <- queryContractKey @Issuance.Service customer (operator, provider, customer) + issueRequestCid <- submit customer do exerciseCmd (toInterfaceContractId @IssuanceService.I issuanceServiceCid) IssuanceService.RequestIssue with issuanceId; description; quantity; account + submitMulti [provider] [public] do exerciseCmd (toInterfaceContractId @IssuanceService.I issuanceServiceCid) IssuanceService.Issue with issueRequestCid list : Party -> Party -> Party -> Text -> Instrument.K -> Instrument.K -> Parties -> Script (ContractId Listing.T) list operator provider customer id tradedInstrument quotedInstrument observers = do @@ -314,6 +316,6 @@ poolInvestmentRequests : Party -> Party -> Party -> Party -> Text -> Date -> Con poolInvestmentRequests operator provider customer public id asOfDate fundCid cashCid investmentRequestCids = submitMulti [customer] [public] do exerciseByKeyCmd @Fund.S (operator, provider, customer) Fund.PoolInvestmentRequests with requestId = Id id; asOfDate; fundCid; cashCid; investmentRequestCids -fulfillPooledInvestmentRequest : Party -> Party -> Party -> Party -> ContractId Fund.T -> ContractId Fund.PooledInvestmentRequest -> ContractId NumericObservable.I -> ContractId SettlementFactory.I -> Script [ContractId Holding.I] -fulfillPooledInvestmentRequest operator provider customer public fundCid pooledInvestmentRequestCid navObservableCid settlementFactoryCid = - submitMulti [provider] [public] do exerciseByKeyCmd @Fund.S (operator, provider, customer) Fund.FulfillPooledInvestmentRequest with fundCid; pooledInvestmentRequestCid; navObservableCid; settlementFactoryCid +fulfillPooledInvestmentRequest : Party -> Party -> Party -> Party -> ContractId Fund.T -> ContractId Fund.PooledInvestmentRequest -> ContractId NumericObservable.I -> ContractId SettlementFactory.I -> ContractId IssuanceService.I -> Script [ContractId Holding.I] +fulfillPooledInvestmentRequest operator provider customer public fundCid pooledInvestmentRequestCid navObservableCid settlementFactoryCid issuanceServiceCid = + submitMulti [provider] [public] do exerciseByKeyCmd @Fund.S (operator, provider, customer) Fund.FulfillPooledInvestmentRequest with fundCid; pooledInvestmentRequestCid; navObservableCid; settlementFactoryCid; issuanceServiceCid diff --git a/ui/src/context/ServicesContext.tsx b/ui/src/context/ServicesContext.tsx index 76b892a5..65786936 100644 --- a/ui/src/context/ServicesContext.tsx +++ b/ui/src/context/ServicesContext.tsx @@ -16,8 +16,8 @@ import { Service as BiddingAutoService } from "@daml.js/daml-finance-app/lib/Dam import { Service as SubscriptionService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Distribution/Subscription/Service" import { Service as FundService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Distribution/Fund/Service" import { Service as InvestmentService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Distribution/Investment/Service" -import { Service as IssuanceService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Issuance/Service" -import { Service as IssuanceAutoService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Issuance/Auto/Service" +import { Service as IssuanceService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Interface/Issuance/Service" +import { Service as IssuanceAutoService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Interface/Issuance/Auto" import { Service as LendingService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Lending/Service" import { Service as LifecycleService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Lifecycle/Service" import { Service as StructuringService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Structuring/Service" @@ -49,8 +49,7 @@ export type ServicesState = { bidding : readonly CreateEvent[] fund : readonly CreateEvent[] investment : readonly CreateEvent[] - issuanceAuto : readonly CreateEvent[] - issuance : readonly CreateEvent[] + issuance : ServicesAggregate lending : readonly CreateEvent[] lifecycle : readonly CreateEvent[] listingAuto : readonly CreateEvent[] @@ -80,7 +79,7 @@ const empty = { fund: [], investment: [], issuanceAuto: [], - issuance: [], + issuance: emptyAggregate, lending: [], lifecycle: [], listingAuto: [], @@ -106,10 +105,10 @@ export const ServicesProvider : React.FC = ({ children }) => { const { loading: l7, contracts: auction } = useStreamQueries(AuctionService); const { loading: l8, contracts: biddingAuto } = useStreamQueries(BiddingAutoService); const { loading: l9, contracts: bidding } = useStreamQueries(BiddingService); - const { loading: l10, contracts: fund } = useStreamQueries(FundService); - const { loading: l11, contracts: investment } = useStreamQueries(InvestmentService); - const { loading: l12, contracts: issuanceAuto } = useStreamQueries(IssuanceAutoService); - const { loading: l13, contracts: issuance } = useStreamQueries(IssuanceService); + const { loading: l10, contracts: fund } = useStreamQueries(FundService); + const { loading: l11, contracts: investment } = useStreamQueries(InvestmentService); + const { loading: l12, contracts: issuance } = useStreamQueries(IssuanceService); + const { loading: l13, contracts: issuanceAuto } = useStreamQueries(IssuanceAutoService); const { loading: l14, contracts: lending } = useStreamQueries(LendingService); const { loading: l15, contracts: lifecycle } = useStreamQueries(LifecycleService); const { loading: l16, contracts: listingAuto } = useStreamQueries(ListingAutoService); @@ -122,6 +121,15 @@ export const ServicesProvider : React.FC = ({ children }) => { const { loading: l23, contracts: trading } = useStreamQueries(TradingService); const loading = l1 || l2 || l3 || l4 || l5 || l6 || l7 || l8 || l9 || l10 || l11 || l12 || l13 || l14 || l15 || l16 || l17 || l18 || l19 || l20 || l21 || l22 || l23; + const createServicesAggregate = (services : readonly CreateEvent[], autoServices : readonly CreateEvent[]) : ServicesAggregate => { + const serviceByCid : Map> = new Map(services.map(c => [c.contractId, c])); + const autoByCid : Map> = new Map(autoServices.map(c => [c.contractId, c])); + const filteredBase = base.filter(c => serviceByCid.has(c.contractId as string)); + const aggregates : ServiceAggregate[] = filteredBase.map(c => ({ ...c, service: serviceByCid.get(c.contractId)!, auto: autoByCid.get(c.contractId) })); + const getService = (provider : string, customer : string) => { return aggregates.find(c => c.payload.provider === provider && c.payload.customer === customer) }; + return { services: aggregates, getService }; + }; + if (loading) { return ( @@ -129,19 +137,11 @@ export const ServicesProvider : React.FC = ({ children }) => { ); } else { - const custodyByCid : Map> = new Map(custody.map(c => [c.contractId, c])); - const custodyAutoByCid : Map> = new Map(custodyAuto.map(c => [c.contractId, c])); - const custodyAggregates : ServiceAggregate[] = base.map(c => ({ ...c, service: custodyByCid.get(c.contractId)!, auto: custodyAutoByCid.get(c.contractId) })); - const getCustodyService = (provider : string, customer : string) => { return custodyAggregates.find(c => c.payload.provider === provider && c.payload.customer === customer) }; - const custodyAggregate = { - services: custodyAggregates, - getService: getCustodyService - }; const value = { loading, backToBack, - custody: custodyAggregate, + custody : createServicesAggregate(custody, custodyAuto), decentralizedExchange, auctionAuto, auction, @@ -150,7 +150,7 @@ export const ServicesProvider : React.FC = ({ children }) => { fund, investment, issuanceAuto, - issuance, + issuance : createServicesAggregate(issuance, issuanceAuto), lending, lifecycle, listingAuto, diff --git a/ui/src/pages/distribution/investment/PooledRequests.tsx b/ui/src/pages/distribution/investment/PooledRequests.tsx index 9c892c77..08658738 100644 --- a/ui/src/pages/distribution/investment/PooledRequests.tsx +++ b/ui/src/pages/distribution/investment/PooledRequests.tsx @@ -22,7 +22,7 @@ export const PooledRequests : React.FC = () => { const party = useParty(); const ledger = useLedger(); - const { loading: l1, fund } = useServices(); + const { loading: l1, fund, issuance } = useServices(); const { loading: l2, contracts: funds } = useStreamQueries(Fund); const { loading: l3, contracts: requests } = useStreamQueries(PooledInvestmentRequest); const { loading: l4, contracts: observables } = useStreamQueries(NumericObservable); @@ -42,11 +42,14 @@ export const PooledRequests : React.FC = () => { if (!observable) throw new Error("NAV observable for [" + fundId + "] not found"); const factory = factories[0]; if (!factory) throw new Error("Settlement factory not found"); + const svc = issuance.getService(fundContract.payload.custodian, party); + if (!svc) throw new Error("No issuance service found for provider [" + fundContract.payload.custodian + "] and customer [" + party + "]"); const arg = { pooledInvestmentRequestCid: pir.contractId, fundCid: fundContract.contractId, navObservableCid: observable.contractId, - settlementFactoryCid: factory.contractId + settlementFactoryCid: factory.contractId, + issuanceServiceCid: svc.service.contractId }; await ledger.exercise(FundService.FulfillPooledInvestmentRequest, service.contractId, arg); } diff --git a/ui/src/pages/issuance/New.tsx b/ui/src/pages/issuance/New.tsx index 40c48059..f7ba60bb 100644 --- a/ui/src/pages/issuance/New.tsx +++ b/ui/src/pages/issuance/New.tsx @@ -3,6 +3,7 @@ import React, { useState } from "react"; import { useNavigate } from "react-router-dom"; +import { v4 as uuidv4 } from "uuid"; import classnames from "classnames"; import { useLedger, useParty, useStreamQueries } from "@daml/react"; import { Typography, Grid, Paper, Button, Checkbox, FormGroup, FormControlLabel } from "@mui/material"; @@ -12,47 +13,47 @@ import { Reference } from "@daml.js/daml-finance-interface-account/lib/Daml/Fina import { useServices } from "../../context/ServicesContext"; import { useInstruments } from "../../context/InstrumentContext"; import { Service as BackToBack } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/BackToBack/Service"; -import { Service as IssuanceAuto } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Issuance/Auto/Service"; -import { Service as Issuance } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Issuance/Service"; +import { Service as IssuanceAuto } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Interface/Issuance/Auto"; +import { Service as Issuance } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Interface/Issuance/Service"; import { Message } from "../../components/Message/Message"; import { TextInput } from "../../components/Form/TextInput"; import { SelectInput, toValues } from "../../components/Form/SelectInput"; +import { fmt } from "../../util"; export const New : React.FC = () => { const cls = useStyles(); const navigate = useNavigate(); - const [ id, setId ] = useState(""); const [ instrumentLabel, setInstrumentLabel ] = useState(""); const [ isB2B, setIsB2B ] = useState(false); const [ amount, setAmount ] = useState(""); const ledger = useLedger(); const party = useParty(); - const { loading: l1, backToBack, issuance, issuanceAuto } = useServices(); + const { loading: l1, backToBack, issuance } = useServices(); const { loading: l2, latests } = useInstruments(); - const { contracts: accounts, loading: l3 } = useStreamQueries(Reference); + const { loading: l3, contracts: accounts } = useStreamQueries(Reference); const aggregates = latests.filter(c => c.payload.issuer === party); const aggregate = aggregates.find(c => c.payload.id.unpack === instrumentLabel); if (l1 || l2 || l3) return ; - if (!issuance) return (); + if (issuance.services.length === 0) return (); const myB2BServices = backToBack.filter(s => s.payload.customer === party); const hasB2B = myB2BServices.length > 0; const canRequest = !!instrumentLabel && !!aggregate && !!amount; - const hasAuto = issuanceAuto.length > 0; - const requestIssuance = async () => { + const requestIssue = async () => { // TODO: Accounts should be selectable if (hasB2B && isB2B) { const customerAccount = accounts.find(c => c.payload.accountView.custodian === party && c.payload.accountView.owner === party); const providerAccount = accounts.find(c => c.payload.accountView.custodian === myB2BServices[0].payload.provider && c.payload.accountView.owner === myB2BServices[0].payload.provider); if (!aggregate || !customerAccount || !providerAccount) return; + const id = uuidv4(); const arg = { id: { unpack : id }, - description: id, + description: "Issuance of " + fmt(amount, 0) + " " + aggregate.key.id.unpack, quantity: { amount: amount, unit: aggregate.key }, customerAccount: customerAccount.key, providerAccount: providerAccount.key @@ -60,19 +61,20 @@ export const New : React.FC = () => { await ledger.exercise(BackToBack.CreateIssuance, myB2BServices[0].contractId, arg); navigate("/app/issuance/issuances"); } else { - const myAutoSvc = issuanceAuto.filter(s => s.payload.customer === party)[0]; - const mySvc = issuance.filter(s => s.payload.customer === party)[0]; - const custodian = hasAuto ? myAutoSvc.payload.provider : mySvc.payload.provider; - const account = accounts.find(c => c.payload.accountView.custodian === custodian && c.payload.accountView.owner === party); - if (!aggregate || !account) return; + if (!aggregate) throw new Error("Aggregate with label [" + instrumentLabel + "] not found"); + const account = accounts.find(c => c.payload.accountView.custodian === aggregate.payload.depository && c.payload.accountView.owner === party); + const svc = issuance.getService(aggregate.payload.depository, party); // TODO: Assumes depository is custodian + if (!svc) throw new Error("No issuance service found for provider [" + aggregate.payload.depository + "] and customer [" + party + "]"); + if (!account) throw new Error("No account found for custodian " + aggregate.payload.depository + " and owner " + party); + const id = uuidv4(); const arg = { - id: { unpack : id }, - description: id, + issuanceId: { unpack : id }, + description: "Issuance of " + fmt(amount, 0) + " " + aggregate.key.id.unpack, quantity: { amount: amount, unit: aggregate.key }, account: account.key, }; - if (hasAuto) await ledger.exercise(IssuanceAuto.RequestAndCreateIssuance, myAutoSvc.contractId, arg); - else await ledger.exercise(Issuance.RequestCreateIssuance, mySvc.contractId, arg); + if (!!svc.auto) await ledger.exercise(IssuanceAuto.RequestAndIssue, svc.auto.contractId, arg); + else await ledger.exercise(Issuance.RequestIssue, svc.service.contractId, arg); navigate("/app/issuance/issuances"); } } @@ -87,11 +89,10 @@ export const New : React.FC = () => { - {hasB2B && setIsB2B(e.target.checked)}/>} label="Issue back-to-back" />} - + diff --git a/ui/src/pages/issuance/Requests.tsx b/ui/src/pages/issuance/Requests.tsx index 7739762b..424fe38a 100644 --- a/ui/src/pages/issuance/Requests.tsx +++ b/ui/src/pages/issuance/Requests.tsx @@ -9,12 +9,12 @@ import { KeyboardArrowRight } from "@mui/icons-material"; import { CreateEvent } from "@daml/ledger"; import { useLedger, useParty, useStreamQueries } from "@daml/react"; import useStyles from "../styles"; -import { CreateIssuanceRequest, ReduceIssuanceRequest } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Issuance/Model"; -import { Service } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Issuance/Service"; +import { Service } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Interface/Issuance/Service"; import { Spinner } from "../../components/Spinner/Spinner"; import { useParties } from "../../context/PartiesContext"; import { useServices } from "../../context/ServicesContext"; -import { Message } from "../../components/Message/Message"; +import { IssueRequest } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Interface/Issuance/IssueRequest"; +import { DeissueRequest } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Interface/Issuance/DeissueRequest"; export const Requests : React.FC = () => { const classes = useStyles(); @@ -23,25 +23,21 @@ export const Requests : React.FC = () => { const ledger = useLedger(); const { getName } = useParties(); const { loading: l1, issuance } = useServices(); - const { loading: l2, contracts: createRequests } = useStreamQueries(CreateIssuanceRequest); - const { loading: l3, contracts: reduceRequests } = useStreamQueries(ReduceIssuanceRequest); - - const providerServices = issuance.filter(s => s.payload.provider === party); - + const { loading: l2, contracts: issueRequests } = useStreamQueries(IssueRequest); + const { loading: l3, contracts: deissueRequests } = useStreamQueries(DeissueRequest); if (l1 || l2 || l3) return ; - if (providerServices.length === 0) return - const createIssuance = async (c : CreateEvent) => { - const service = providerServices.find(s => s.payload.customer === c.payload.customer); - if (!service) return; - await ledger.exercise(Service.CreateIssuance, service.contractId, { createIssuanceRequestCid: c.contractId }); + const issue = async (c : CreateEvent) => { + const svc = issuance.getService(party, c.payload.customer); + if (!svc) throw new Error("No issuance service found for provider " + party + " and customer " + c.payload.customer); + await ledger.exercise(Service.Issue, svc.service.contractId, { issueRequestCid: c.contractId }); navigate("/app/issuance/issuances"); } - const deleteIssuance = async (c : CreateEvent) => { - const service = providerServices.find(s => s.payload.customer === c.payload.customer); - if (!service) return; - await ledger.exercise(Service.ReduceIssuance, service.contractId, { reduceIssuanceRequestCid: c.contractId }); + const deissue = async (c : CreateEvent) => { + const svc = issuance.getService(party, c.payload.customer); + if (!svc) throw new Error("No issuance service found for provider " + party + " and customer " + c.payload.customer); + await ledger.exercise(Service.Deissue, svc.service.contractId, { deissueRequestCid: c.contractId }); navigate("/app/issuance/issuances"); } @@ -51,36 +47,30 @@ export const Requests : React.FC = () => { - Issuance Requests + Issue Requests Issuing Agent Issuer - Issuance ID + Issuance Id Instrument Quantity Action - Details - {createRequests.map((c, i) => ( + {issueRequests.map((c, i) => ( {getName(c.payload.provider)} {getName(c.payload.customer)} - {c.payload.id} + {c.payload.issuanceId.unpack} {c.payload.quantity.unit.id.unpack} {c.payload.quantity.amount} - {party === c.payload.provider && } + {party === c.payload.provider && } {/* {party === c.payload.client && } */} - - navigate("/app/issuance/createrequest/" + c.contractId)}> - - - ))} @@ -89,7 +79,7 @@ export const Requests : React.FC = () => { - Deissuance Requests + Deissue Requests
@@ -101,28 +91,22 @@ export const Requests : React.FC = () => { {/* Asset Quantity */} Action - Details - {reduceRequests.map((c, i) => ( + {deissueRequests.map((c, i) => ( {getName(c.payload.provider)} {getName(c.payload.customer)} {party === c.payload.provider ? "Provider" : "Client"} - {c.payload.id} + {c.payload.issuanceId} {/* {c.payload.accountId.label} */} {/* {c.payload.assetId.label} {c.payload.quotedAssetId.label} */} - {party === c.payload.provider && } + {party === c.payload.provider && } {/* {party === c.payload.client && } */} - - navigate("/app/issuance/deleterequest/" + c.contractId)}> - - - ))} From fb1d36598f0bd151220f14f22a1cd4317dec9092 Mon Sep 17 00:00:00 2001 From: Georg Schneider Date: Mon, 19 Dec 2022 11:59:17 +0100 Subject: [PATCH 07/31] Add interfaces for listing --- .../Finance/App/Interface/Issuance/Auto.daml | 4 +- .../Finance/App/Interface/Listing/Auto.daml | 52 +++++++ .../Interface/Listing/DelistingRequest.daml | 31 ++++ .../App/Interface/Listing/Listing.daml | 36 +++++ .../App/Interface/Listing/ListingRequest.daml | 36 +++++ .../App/Interface/Listing/Service.daml | 71 +++++++++ src/daml/Daml/Finance/App/Issuance/Auto.daml | 5 +- src/daml/Daml/Finance/App/Listing/Auto.daml | 99 ++++++++++++ .../Finance/App/Listing/Auto/Service.daml | 92 ----------- src/daml/Daml/Finance/App/Listing/Model.daml | 42 ++++- .../Daml/Finance/App/Listing/Service.daml | 68 +++----- src/daml/Daml/Finance/App/Role/Exchange.daml | 11 +- .../Finance/App/Trading/Auto/Service.daml | 2 +- src/daml/Daml/Finance/App/Trading/Model.daml | 4 +- .../Daml/Finance/App/Trading/Service.daml | 2 +- .../Daml/Finance/Setup/Scenario/Default.daml | 2 +- src/daml/Daml/Finance/Setup/Util/Service.daml | 14 +- .../Daml/Finance/Setup/Util/Workflow.daml | 13 +- ui/src/context/ServicesContext.tsx | 19 +-- ui/src/pages/issuance/New.tsx | 6 +- ui/src/pages/issuance/Requests.tsx | 117 +++++--------- ui/src/pages/listing/Listings.tsx | 25 ++- ui/src/pages/listing/New.tsx | 43 +++--- ui/src/pages/listing/Requests.tsx | 145 ++++++------------ ui/src/pages/trading/Market.tsx | 4 +- 25 files changed, 541 insertions(+), 402 deletions(-) create mode 100644 src/daml/Daml/Finance/App/Interface/Listing/Auto.daml create mode 100644 src/daml/Daml/Finance/App/Interface/Listing/DelistingRequest.daml create mode 100644 src/daml/Daml/Finance/App/Interface/Listing/Listing.daml create mode 100644 src/daml/Daml/Finance/App/Interface/Listing/ListingRequest.daml create mode 100644 src/daml/Daml/Finance/App/Interface/Listing/Service.daml create mode 100644 src/daml/Daml/Finance/App/Listing/Auto.daml delete mode 100644 src/daml/Daml/Finance/App/Listing/Auto/Service.daml diff --git a/src/daml/Daml/Finance/App/Interface/Issuance/Auto.daml b/src/daml/Daml/Finance/App/Interface/Issuance/Auto.daml index d654caae..e0914f16 100644 --- a/src/daml/Daml/Finance/App/Interface/Issuance/Auto.daml +++ b/src/daml/Daml/Finance/App/Interface/Issuance/Auto.daml @@ -23,9 +23,9 @@ interface Service where asService : Service.I -- ^ Conversion to custody `Service` interface. requestAndIssue : ContractId Service.I -> RequestAndIssue -> Update (ContractId Issuance.I, ContractId Holding.I) - -- ^ Implementation of the `RequestOpenAccount` choice. + -- ^ Implementation of the `RequestAndIssue` choice. requestAndDeissue : ContractId Service.I -> RequestAndDeissue -> Update (ContractId Issuance.I) - -- ^ Implementation of the `RequestCloseAccount` choice. + -- ^ Implementation of the `RequestAndDeissue` choice. nonconsuming choice RequestAndIssue : (ContractId Issuance.I, ContractId Holding.I) with diff --git a/src/daml/Daml/Finance/App/Interface/Listing/Auto.daml b/src/daml/Daml/Finance/App/Interface/Listing/Auto.daml new file mode 100644 index 00000000..0e4b1ebd --- /dev/null +++ b/src/daml/Daml/Finance/App/Interface/Listing/Auto.daml @@ -0,0 +1,52 @@ +-- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +-- SPDX-License-Identifier: Apache-2.0 + +module Daml.Finance.App.Interface.Listing.Auto where + +import Daml.Finance.App.Interface.Base.Service qualified as Base (I) +import Daml.Finance.App.Interface.Listing.Listing qualified as Listing (I) +import Daml.Finance.App.Interface.Listing.Service qualified as Service (I, Implementation, asBase) +import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (K) +import Daml.Finance.Interface.Types.Common (Id, Parties) + +type I = Service + +type V = View + +data View = View {} + deriving (Eq, Show) + +interface Service where + viewtype V + + asService : Service.I + -- ^ Conversion to custody `Service` interface. + requestAndList : ContractId Service.I -> RequestAndList -> Update (ContractId Listing.I) + -- ^ Implementation of the `RequestAndList` choice. + requestAndDelist : ContractId Service.I -> RequestAndDelist -> Update () + -- ^ Implementation of the `RequestAndDelist` choice. + + nonconsuming choice RequestAndList : (ContractId Listing.I) + with + listingId : Id + description : Text + tradedInstrument : Instrument.K + quotedInstrument : Instrument.K + observers : Parties + controller (view $ Service.asBase $ asService this).customer + do + requestAndList this (toInterfaceContractId self) arg + + nonconsuming choice RequestAndDelist : () + with + listingCid : ContractId Listing.I + controller (view $ Service.asBase $ asService this).customer + do + requestAndDelist this (toInterfaceContractId self) arg + +-- | Type constraint for requiring templates to implement `Service`. +type Implementation t = (HasToInterface t Service, Service.Implementation t) +class (Implementation t) => HasImplementation t +instance HasImplementation Service +instance HasToInterface Service Service.I where _toInterface = asService +instance HasToInterface Service Base.I where _toInterface = Service.asBase . asService diff --git a/src/daml/Daml/Finance/App/Interface/Listing/DelistingRequest.daml b/src/daml/Daml/Finance/App/Interface/Listing/DelistingRequest.daml new file mode 100644 index 00000000..ee43cfa1 --- /dev/null +++ b/src/daml/Daml/Finance/App/Interface/Listing/DelistingRequest.daml @@ -0,0 +1,31 @@ +-- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +-- SPDX-License-Identifier: Apache-2.0 + +module Daml.Finance.App.Interface.Listing.DelistingRequest where + +import Daml.Finance.App.Interface.Common.Removable qualified as Removable (I, Implementation) +import Daml.Finance.App.Interface.Listing.Listing qualified as Listing (I) + +type I = DelistingRequest + +type V = View + +data View = View + with + operator : Party + provider : Party + customer : Party + listingCid : ContractId Listing.I + deriving (Eq, Show) + +interface DelistingRequest where + viewtype View + -- ^ Interface view types. + asRemovable : Removable.I + -- ^ Conversion to the `Removable` interface. + +-- | Type constraint for requiring templates to implement `DelistingRequest`. +type Implementation t = (HasToInterface t DelistingRequest, Removable.Implementation t) +class (Implementation t) => HasImplementation t +instance HasImplementation DelistingRequest +instance HasToInterface DelistingRequest Removable.I where _toInterface = asRemovable diff --git a/src/daml/Daml/Finance/App/Interface/Listing/Listing.daml b/src/daml/Daml/Finance/App/Interface/Listing/Listing.daml new file mode 100644 index 00000000..ff496350 --- /dev/null +++ b/src/daml/Daml/Finance/App/Interface/Listing/Listing.daml @@ -0,0 +1,36 @@ +-- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +-- SPDX-License-Identifier: Apache-2.0 + +module Daml.Finance.App.Interface.Listing.Listing where + +import Daml.Finance.App.Interface.Common.Removable qualified as Removable (I, Implementation) +import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (K) +import Daml.Finance.Interface.Types.Common (Id, Parties) + +type I = Listing + +type V = View + +data View = View + with + operator : Party + provider : Party + customer : Party + id : Id + description : Text + tradedInstrument : Instrument.K + quotedInstrument : Instrument.K + observers : Parties + deriving (Eq, Show) + +interface Listing where + viewtype View + -- ^ Interface view types. + asRemovable : Removable.I + -- ^ Conversion to the `Removable` interface. + +-- | Type constraint for requiring templates to implement `Listing`. +type Implementation t = (HasToInterface t Listing, Removable.Implementation t) +class (Implementation t) => HasImplementation t +instance HasImplementation Listing +instance HasToInterface Listing Removable.I where _toInterface = asRemovable diff --git a/src/daml/Daml/Finance/App/Interface/Listing/ListingRequest.daml b/src/daml/Daml/Finance/App/Interface/Listing/ListingRequest.daml new file mode 100644 index 00000000..94a99dff --- /dev/null +++ b/src/daml/Daml/Finance/App/Interface/Listing/ListingRequest.daml @@ -0,0 +1,36 @@ +-- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +-- SPDX-License-Identifier: Apache-2.0 + +module Daml.Finance.App.Interface.Listing.ListingRequest where + +import Daml.Finance.App.Interface.Common.Removable qualified as Removable (I, Implementation) +import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (K) +import Daml.Finance.Interface.Types.Common (Id, Parties) + +type I = ListingRequest + +type V = View + +data View = View + with + operator : Party + provider : Party + customer : Party + listingId : Id + description : Text + tradedInstrument : Instrument.K + quotedInstrument : Instrument.K + observers : Parties + deriving (Eq, Show) + +interface ListingRequest where + viewtype View + -- ^ Interface view types. + asRemovable : Removable.I + -- ^ Conversion to the `Removable` interface. + +-- | Type constraint for requiring templates to implement `ListingRequest`. +type Implementation t = (HasToInterface t ListingRequest, Removable.Implementation t) +class (Implementation t) => HasImplementation t +instance HasImplementation ListingRequest +instance HasToInterface ListingRequest Removable.I where _toInterface = asRemovable diff --git a/src/daml/Daml/Finance/App/Interface/Listing/Service.daml b/src/daml/Daml/Finance/App/Interface/Listing/Service.daml new file mode 100644 index 00000000..c7b837cb --- /dev/null +++ b/src/daml/Daml/Finance/App/Interface/Listing/Service.daml @@ -0,0 +1,71 @@ +-- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +-- SPDX-License-Identifier: Apache-2.0 + +module Daml.Finance.App.Interface.Listing.Service where + +import Daml.Finance.App.Interface.Base.Service qualified as Base (I, Implementation) +import Daml.Finance.App.Interface.Listing.Listing qualified as Listing (I) +import Daml.Finance.App.Interface.Listing.ListingRequest qualified as ListingRequest (I) +import Daml.Finance.App.Interface.Listing.DelistingRequest qualified as DelistingRequest (I) +import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (K) +import Daml.Finance.Interface.Types.Common (Id, Parties) +import Prelude hiding (List) + +type I = Service + +type V = View + +data View = View {} + deriving (Eq, Show) + +interface Service where + viewtype V + + asBase : Base.I + -- ^ Conversion to base `Service` interface. + requestListing : RequestListing -> Update (ContractId ListingRequest.I) + -- ^ Implementation of the `RequestListing` choice. + requestDelisting : RequestDelisting -> Update (ContractId DelistingRequest.I) + -- ^ Implementation of the `RequestDelisting` choice. + list : List -> Update (ContractId Listing.I) + -- ^ Implementation of the `List` choice. + delist : Delist -> Update () + -- ^ Implementation of the `Delist` choice. + + nonconsuming choice RequestListing : ContractId ListingRequest.I + with + listingId : Id + description : Text + tradedInstrument : Instrument.K + quotedInstrument : Instrument.K + observers : Parties + controller (view $ asBase this).customer + do + requestListing this arg + + nonconsuming choice RequestDelisting : ContractId DelistingRequest.I + with + listingCid : ContractId Listing.I + controller (view $ asBase this).customer + do + requestDelisting this arg + + nonconsuming choice List : ContractId Listing.I + with + listingRequestCid : ContractId ListingRequest.I + controller (view $ asBase this).provider + do + list this arg + + nonconsuming choice Delist : () + with + delistingRequestCid : ContractId DelistingRequest.I + controller (view $ asBase this).provider + do + delist this arg + +-- | Type constraint for requiring templates to implement `Service`. +type Implementation t = (HasToInterface t Service, Base.Implementation t) +class (Implementation t) => HasImplementation t +instance HasImplementation Service +instance HasToInterface Service Base.I where _toInterface = asBase diff --git a/src/daml/Daml/Finance/App/Issuance/Auto.daml b/src/daml/Daml/Finance/App/Issuance/Auto.daml index 4ba1cd05..255326ab 100644 --- a/src/daml/Daml/Finance/App/Issuance/Auto.daml +++ b/src/daml/Daml/Finance/App/Issuance/Auto.daml @@ -14,7 +14,6 @@ import Daml.Finance.App.Interface.Issuance.Service qualified as Service (Deissue import Daml.Finance.Interface.Account.Account qualified as Account (Credit(..), Debit(..), I, exerciseInterfaceByKey) import Daml.Finance.Interface.Account.Util (getAccount) import Daml.Finance.Interface.Holding.Util (getAmount) -import Daml.Finance.App.Issuance.Model (DeissueRequest(..), Issuance(..), IssueRequest(..)) instance Auto.HasImplementation Service @@ -42,7 +41,7 @@ template Service toInterfaceContractId <$> create Model.DeissueRequest with operator; provider; customer; issuanceId; holdingCid issue Service.Issue{issueRequestCid} = do IssueRequest.View{issuanceId; description; quantity; account} <- view <$> fetchAndRemove issueRequestCid - issuanceCid <- toInterfaceContractId <$> create Issuance with operator; provider; customer; id = issuanceId; description; quantity + issuanceCid <- toInterfaceContractId <$> create Model.Issuance with operator; provider; customer; id = issuanceId; description; quantity account.custodian === provider account.owner === customer holdingCid <- Account.exerciseInterfaceByKey @Account.I account provider Account.Credit with quantity @@ -56,7 +55,7 @@ template Service account.custodian === provider account.owner === customer Account.exerciseInterfaceByKey @Account.I account provider Account.Debit with holdingCid - (issuanceCid, issuance) <- fetchByKey @Issuance (operator, provider, issuanceId) + (issuanceCid, issuance) <- fetchByKey @Model.Issuance (operator, provider, issuanceId) archive issuanceCid toInterfaceContractId <$> create issuance with quantity = (issuance.quantity with amount = issuance.quantity.amount - amount) diff --git a/src/daml/Daml/Finance/App/Listing/Auto.daml b/src/daml/Daml/Finance/App/Listing/Auto.daml new file mode 100644 index 00000000..616c2053 --- /dev/null +++ b/src/daml/Daml/Finance/App/Listing/Auto.daml @@ -0,0 +1,99 @@ +-- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +-- SPDX-License-Identifier: Apache-2.0 + +module Daml.Finance.App.Listing.Auto where + +import Daml.Finance.App.Listing.Model qualified as Model +import Daml.Finance.App.Interface.Base.Service qualified as Base (I, View(..)) +import Daml.Finance.App.Interface.Common.Removable qualified as Removable (I, Remove(..)) +import Daml.Finance.App.Interface.Common.Util (fetchAndRemove) +import Daml.Finance.App.Interface.Listing.Auto qualified as Auto (HasImplementation, I, View(..), RequestAndDelist(..), RequestAndList(..)) +import Daml.Finance.App.Interface.Listing.DelistingRequest qualified as DelistingRequest (View(..)) +import Daml.Finance.App.Interface.Listing.ListingRequest qualified as ListingRequest (View(..)) +import Daml.Finance.App.Interface.Listing.Service qualified as Service (Delist(..), List(..), I, RequestDelisting(..), RequestListing(..), View(..)) + +instance Auto.HasImplementation Service + +template Service + with + operator : Party + provider : Party + customer : Party + where + signatory operator, provider, customer + + key (operator, provider, customer) : (Party, Party, Party) + maintainer key._1 + + interface instance Base.I for Service where + view = Base.View with operator; provider; customer + terminate = pure () + + interface instance Service.I for Service where + view = Service.View + asBase = toInterface @Base.I this + requestListing Service.RequestListing{listingId; description; tradedInstrument; quotedInstrument; observers} = do + toInterfaceContractId <$> create Model.ListingRequest with operator; provider; customer; listingId; description; tradedInstrument; quotedInstrument; observers + requestDelisting Service.RequestDelisting{listingCid} = do + toInterfaceContractId <$> create Model.DelistingRequest with operator; provider; customer; listingCid + list Service.List{listingRequestCid} = do + ListingRequest.View{listingId; description; tradedInstrument; quotedInstrument; observers} <- view <$> fetchAndRemove listingRequestCid + toInterfaceContractId <$> create Model.Listing with operator; provider; customer; id = listingId; description; tradedInstrument; quotedInstrument; observers + delist Service.Delist{delistingRequestCid} = do + DelistingRequest.View{listingCid} <- view <$> fetchAndRemove delistingRequestCid + exercise (toInterfaceContractId @Removable.I listingCid) Removable.Remove + + interface instance Auto.I for Service where + view = Auto.View + asService = toInterface @Service.I this + requestAndList self Auto.RequestAndList{listingId; description; tradedInstrument; quotedInstrument; observers} = do + listingRequestCid <- exercise self Service.RequestListing with listingId; description; tradedInstrument; quotedInstrument; observers + exercise self Service.List with listingRequestCid + requestAndDelist self Auto.RequestAndDelist{listingCid} = do + delistingRequestCid <- exercise self Service.RequestDelisting with listingCid + exercise self Service.Delist with delistingRequestCid + +template Offer + with + operator : Party + provider : Party + customer : Party + where + signatory operator, provider + observer customer + + choice Accept : ContractId Service + controller customer + do + create Service with .. + + choice Decline : () + controller customer + do pure () + + choice Withdraw : () + controller provider + do pure () + +template Request + with + customer : Party + provider : Party + where + signatory customer + observer provider + + choice Cancel : () + controller customer + do pure () + + choice Reject : () + controller provider + do pure () + + choice Approve : ContractId Service + with + operator : Party + controller operator, provider + do + create Service with .. diff --git a/src/daml/Daml/Finance/App/Listing/Auto/Service.daml b/src/daml/Daml/Finance/App/Listing/Auto/Service.daml deleted file mode 100644 index 14c9b87c..00000000 --- a/src/daml/Daml/Finance/App/Listing/Auto/Service.daml +++ /dev/null @@ -1,92 +0,0 @@ --- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. --- SPDX-License-Identifier: Apache-2.0 - -module Daml.Finance.App.Listing.Auto.Service where - -import Daml.Finance.App.Listing.Service qualified as S (CreateListing(..), DeleteListing(..), RequestCreateListing(..), RequestDeleteListing(..), Service) -import Daml.Finance.App.Listing.Model (Listing) -import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (K) -import Daml.Finance.Interface.Types.Common (Parties) - -template Service - with - operator : Party - provider : Party - customer : Party - where - signatory operator, provider, customer - - key (operator, provider, customer) : (Party, Party, Party) - maintainer key._1 - - nonconsuming choice RequestAndCreateListing : ContractId Listing - with - id : Text - tradedInstrument : Instrument.K - quotedInstrument : Instrument.K - observers : Parties - controller customer - do - createListingRequestCid <- exerciseByKey @S.Service (operator, provider, customer) S.RequestCreateListing with id; tradedInstrument; quotedInstrument; observers - exerciseByKey @S.Service (operator, provider, customer) S.CreateListing with createListingRequestCid - - nonconsuming choice RequestAndDeleteListing : () - with - listingCid : ContractId Listing - controller customer - do - deleteListingRequestCid <- exerciseByKey @S.Service (operator, provider, customer) S.RequestDeleteListing with listingCid - exerciseByKey @S.Service (operator, provider, customer) S.DeleteListing with deleteListingRequestCid - - choice Terminate : () - with - actor : Party - controller actor - do - assert $ actor == operator || actor == provider || actor == customer - pure () - -template Offer - with - operator : Party - provider : Party - customer : Party - where - signatory operator, provider - observer customer - - choice Accept : ContractId Service - controller customer - do - create Service with .. - - choice Decline : () - controller customer - do pure () - - choice Withdraw : () - controller provider - do pure () - -template Request - with - customer : Party - provider : Party - where - signatory customer - observer provider - - choice Cancel : () - controller customer - do pure () - - choice Reject : () - controller provider - do pure () - - choice Approve : ContractId Service - with - operator : Party - controller operator, provider - do - create Service with .. diff --git a/src/daml/Daml/Finance/App/Listing/Model.daml b/src/daml/Daml/Finance/App/Listing/Model.daml index 68a29ce4..3747a735 100644 --- a/src/daml/Daml/Finance/App/Listing/Model.daml +++ b/src/daml/Daml/Finance/App/Listing/Model.daml @@ -3,8 +3,13 @@ module Daml.Finance.App.Listing.Model where +import DA.Set (fromList) +import Daml.Finance.App.Interface.Common.Removable qualified as Removable (I, View(..)) +import Daml.Finance.App.Interface.Listing.DelistingRequest qualified as DelistingRequest (I, View(..)) +import Daml.Finance.App.Interface.Listing.Listing qualified as Listing (I, View(..)) +import Daml.Finance.App.Interface.Listing.ListingRequest qualified as ListingRequest (I, View(..)) import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (K) -import Daml.Finance.Interface.Types.Common (Parties) +import Daml.Finance.Interface.Types.Common (Id, Parties) type T = Listing @@ -13,7 +18,8 @@ template Listing operator : Party provider : Party customer : Party - id : Text + id : Id + description : Text tradedInstrument : Instrument.K quotedInstrument : Instrument.K observers : Parties @@ -21,26 +27,48 @@ template Listing signatory operator, provider, customer observer observers - key (operator, provider, id) : (Party, Party, Text) + key (operator, provider, id) : (Party, Party, Id) maintainer key._1, key._2 -template CreateListingRequest + interface instance Removable.I for Listing where + view = Removable.View with removers = fromList [operator, provider, customer] + + interface instance Listing.I for Listing where + view = Listing.View with operator; provider; customer; id; description; tradedInstrument; quotedInstrument; observers + asRemovable = toInterface @Removable.I this + +template ListingRequest with operator : Party provider : Party customer : Party - id : Text + listingId : Id + description : Text tradedInstrument : Instrument.K quotedInstrument : Instrument.K observers : Parties where signatory operator, provider, customer -template DeleteListingRequest + interface instance Removable.I for ListingRequest where + view = Removable.View with removers = fromList [operator, provider, customer] + + interface instance ListingRequest.I for ListingRequest where + view = ListingRequest.View with operator; provider; customer; listingId; description; tradedInstrument; quotedInstrument; observers + asRemovable = toInterface @Removable.I this + +template DelistingRequest with operator : Party provider : Party customer : Party - listingCid : ContractId Listing + listingCid : ContractId Listing.I where signatory operator, provider, customer + + interface instance Removable.I for DelistingRequest where + view = Removable.View with removers = fromList [operator, provider, customer] + + interface instance DelistingRequest.I for DelistingRequest where + view = DelistingRequest.View with operator; provider; customer; listingCid + asRemovable = toInterface @Removable.I this diff --git a/src/daml/Daml/Finance/App/Listing/Service.daml b/src/daml/Daml/Finance/App/Listing/Service.daml index 5de309dc..2106d21b 100644 --- a/src/daml/Daml/Finance/App/Listing/Service.daml +++ b/src/daml/Daml/Finance/App/Listing/Service.daml @@ -3,10 +3,13 @@ module Daml.Finance.App.Listing.Service where -import Daml.Finance.App.Listing.Model (CreateListingRequest(..), DeleteListingRequest(..), Listing(..)) -import Daml.Finance.App.Util (fetchAndArchive) -import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (K) -import Daml.Finance.Interface.Types.Common (Parties) +import Daml.Finance.App.Interface.Base.Service qualified as Base (I, View(..)) +import Daml.Finance.App.Interface.Common.Removable qualified as Removable (I, Remove(..)) +import Daml.Finance.App.Interface.Common.Util (fetchAndRemove) +import Daml.Finance.App.Interface.Listing.ListingRequest qualified as ListingRequest (View(..)) +import Daml.Finance.App.Interface.Listing.DelistingRequest qualified as DelistingRequest (View(..)) +import Daml.Finance.App.Interface.Listing.Service qualified as Service +import Daml.Finance.App.Listing.Model qualified as Model template Service with @@ -19,46 +22,23 @@ template Service key (operator, provider, customer) : (Party, Party, Party) maintainer key._1 - nonconsuming choice RequestCreateListing : ContractId CreateListingRequest - with - id : Text - tradedInstrument : Instrument.K - quotedInstrument : Instrument.K - observers : Parties - controller customer - do - create CreateListingRequest with operator; provider; customer; id; tradedInstrument; quotedInstrument; observers - - nonconsuming choice RequestDeleteListing : ContractId DeleteListingRequest - with - listingCid : ContractId Listing - controller customer - do - create DeleteListingRequest with operator; provider; customer; listingCid - - nonconsuming choice CreateListing : ContractId Listing - with - createListingRequestCid : ContractId CreateListingRequest - controller provider - do - CreateListingRequest{operator; provider; customer; id; tradedInstrument; quotedInstrument; observers} <- fetchAndArchive createListingRequestCid - create Listing with operator; provider; customer; id; tradedInstrument; quotedInstrument; observers - - nonconsuming choice DeleteListing : () - with - deleteListingRequestCid : ContractId DeleteListingRequest - controller provider - do - DeleteListingRequest{operator; provider; customer; listingCid} <- fetchAndArchive deleteListingRequestCid - archive listingCid - - choice Terminate : () - with - actor : Party - controller actor - do - assert $ actor == operator || actor == provider || actor == customer - pure () + interface instance Base.I for Service where + view = Base.View with operator; provider; customer + terminate = pure () + + interface instance Service.I for Service where + view = Service.View + asBase = toInterface @Base.I this + requestListing Service.RequestListing{listingId; description; tradedInstrument; quotedInstrument; observers} = do + toInterfaceContractId <$> create Model.ListingRequest with operator; provider; customer; listingId; description; tradedInstrument; quotedInstrument; observers + requestDelisting Service.RequestDelisting{listingCid} = do + toInterfaceContractId <$> create Model.DelistingRequest with operator; provider; customer; listingCid + list Service.List{listingRequestCid} = do + ListingRequest.View{listingId; description; tradedInstrument; quotedInstrument; observers} <- view <$> fetchAndRemove listingRequestCid + toInterfaceContractId <$> create Model.Listing with operator; provider; customer; id = listingId; description; tradedInstrument; quotedInstrument; observers + delist Service.Delist{delistingRequestCid} = do + DelistingRequest.View{listingCid} <- view <$> fetchAndRemove delistingRequestCid + exercise (toInterfaceContractId @Removable.I listingCid) Removable.Remove template Offer with diff --git a/src/daml/Daml/Finance/App/Role/Exchange.daml b/src/daml/Daml/Finance/App/Role/Exchange.daml index 122af388..3ad34cca 100644 --- a/src/daml/Daml/Finance/App/Role/Exchange.daml +++ b/src/daml/Daml/Finance/App/Role/Exchange.daml @@ -3,8 +3,9 @@ module Daml.Finance.App.Role.Exchange where -import Daml.Finance.App.Listing.Auto.Service qualified as ListingAuto (Approve(..), Offer(..), Request, Service, Terminate(..)) -import Daml.Finance.App.Listing.Service qualified as Listing (Approve(..), Offer(..), Request, Service, Terminate(..)) +import Daml.Finance.App.Interface.Base.Service qualified as Base (I, Terminate(..)) +import Daml.Finance.App.Listing.Auto qualified as ListingAuto (Approve(..), Offer(..), Request, Service) +import Daml.Finance.App.Listing.Service qualified as Listing (Approve(..), Offer(..), Request, Service) import Daml.Finance.App.Trading.Auto.Service qualified as TradingAuto (Approve(..), Offer(..), Request, Service, Terminate(..)) import Daml.Finance.App.Trading.Service qualified as Trading (Approve(..), Offer(..), Request, Service, Terminate(..)) import Daml.Finance.Interface.Settlement.Factory qualified as Factory (I) @@ -82,7 +83,8 @@ template Role customer : Party controller provider do - exerciseByKey @Listing.Service (operator, provider, customer) Listing.Terminate with actor = provider + (serviceCid, _) <- fetchByKey @Listing.Service (operator, provider, customer) + exercise (toInterfaceContractId @Base.I serviceCid) Base.Terminate with actor = provider nonconsuming choice OfferListingAutoService : ContractId ListingAuto.Offer with @@ -103,7 +105,8 @@ template Role customer : Party controller provider do - exerciseByKey @ListingAuto.Service (operator, provider, customer) ListingAuto.Terminate with actor = provider + (serviceCid, _) <- fetchByKey @ListingAuto.Service (operator, provider, customer) + exercise (toInterfaceContractId @Base.I serviceCid) Base.Terminate with actor = provider choice TerminateRole : () controller operator diff --git a/src/daml/Daml/Finance/App/Trading/Auto/Service.daml b/src/daml/Daml/Finance/App/Trading/Auto/Service.daml index 577d544f..a14edc46 100644 --- a/src/daml/Daml/Finance/App/Trading/Auto/Service.daml +++ b/src/daml/Daml/Finance/App/Trading/Auto/Service.daml @@ -24,7 +24,7 @@ template Service nonconsuming choice RequestAndCreateOrder : Optional (ContractId Order, Order) with id : Id - listingId : Text + listingId : Id quantity : Instrument.Q price : Instrument.Q side : Side diff --git a/src/daml/Daml/Finance/App/Trading/Model.daml b/src/daml/Daml/Finance/App/Trading/Model.daml index b7e87d36..f755f327 100644 --- a/src/daml/Daml/Finance/App/Trading/Model.daml +++ b/src/daml/Daml/Finance/App/Trading/Model.daml @@ -32,7 +32,7 @@ template Order customer : Party id : Id timestamp : Time - listingId : Text + listingId : Id quantity : Instrument.Q side : Side price : Instrument.Q @@ -89,7 +89,7 @@ template CreateOrderRequest customer : Party id : Id timestamp : Time - listingId : Text + listingId : Id quantity : Instrument.Q side : Side price : Instrument.Q diff --git a/src/daml/Daml/Finance/App/Trading/Service.daml b/src/daml/Daml/Finance/App/Trading/Service.daml index 329ef6e9..17e05bdb 100644 --- a/src/daml/Daml/Finance/App/Trading/Service.daml +++ b/src/daml/Daml/Finance/App/Trading/Service.daml @@ -35,7 +35,7 @@ template Service nonconsuming choice RequestCreateOrder : ContractId CreateOrderRequest with id : Id - listingId : Text + listingId : Id quantity : Instrument.Q price : Instrument.Q side : Side diff --git a/src/daml/Daml/Finance/Setup/Scenario/Default.daml b/src/daml/Daml/Finance/Setup/Scenario/Default.daml index 948828f7..5ada4fdc 100644 --- a/src/daml/Daml/Finance/Setup/Scenario/Default.daml +++ b/src/daml/Daml/Finance/Setup/Scenario/Default.daml @@ -152,7 +152,7 @@ run = do processAuction operator agent issuer public auctionCid [inv1BidCid, inv2BidCid, inv3BidCid] doTrade = do - list operator exchange issuer "SWAP/USD" swp usd $ singleton public + list operator exchange issuer (Id "SWAP/USD") "SWAP vs USD" swp usd $ singleton public createAskOrder operator exchange issuer public (Id "1") (Instrument.qty 250_000.0 swp) (Instrument.qty 1.00 usd) $ singleton public createAskOrder operator exchange issuer public (Id "2") (Instrument.qty 250_000.0 swp) (Instrument.qty 1.00 usd) $ singleton public createBidOrder operator exchange inv1 public (Id "3") (Instrument.qty 400_000.0 swp) (Instrument.qty 1.00 usd) $ singleton public diff --git a/src/daml/Daml/Finance/Setup/Util/Service.daml b/src/daml/Daml/Finance/Setup/Util/Service.daml index 5ff7d8c5..81942c84 100644 --- a/src/daml/Daml/Finance/Setup/Util/Service.daml +++ b/src/daml/Daml/Finance/Setup/Util/Service.daml @@ -13,15 +13,17 @@ import Daml.Finance.App.Interface.Custody.Auto qualified as CustodyAuto (I) import Daml.Finance.App.Interface.Custody.Service qualified as Custody (I) import Daml.Finance.App.Interface.Issuance.Auto qualified as IssuanceAuto (I) import Daml.Finance.App.Interface.Issuance.Service qualified as Issuance (I) +import Daml.Finance.App.Interface.Listing.Auto qualified as ListingAuto (I) +import Daml.Finance.App.Interface.Listing.Service qualified as Listing (I) import Daml.Finance.App.Issuance.Auto qualified as IssuanceAuto (Accept(..)) import Daml.Finance.App.Issuance.Service qualified as Issuance (Accept(..)) +import Daml.Finance.App.Listing.Auto qualified as ListingAuto (Accept(..)) +import Daml.Finance.App.Listing.Service qualified as Listing (Accept(..)) import Daml.Finance.App.BackToBack.Service qualified as BackToBack (Accept(..), Service) import Daml.Finance.App.Lifecycle.Service qualified as Lifecycle (Accept(..), Service) import Daml.Finance.App.Trading.Auto.Service qualified as TradingAuto (Accept(..), Service) import Daml.Finance.App.Trading.Service qualified as Trading (Accept(..), Service) import Daml.Finance.App.Lending.Service qualified as Lending (Accept(..), Service) -import Daml.Finance.App.Listing.Auto.Service qualified as ListingAuto (Accept(..), Service) -import Daml.Finance.App.Listing.Service qualified as Listing (Accept(..), Service) import Daml.Finance.App.Distribution.Auction.Auto.Service qualified as AuctionAuto (Accept(..), Service) import Daml.Finance.App.Distribution.Auction.Service qualified as Auction (Accept(..), Service) import Daml.Finance.App.Distribution.Bidding.Auto.Service qualified as BiddingAuto (Accept(..), Service) @@ -119,15 +121,15 @@ createTradingAutoService operator exchange customer = do offerCid <- submit exchange do exerciseByKeyCmd @Exchange.Role (operator, exchange) Exchange.OfferTradingAutoService with .. submit customer do exerciseCmd offerCid TradingAuto.Accept -createListingService : Party -> Party -> Party -> Script (ContractId Listing.Service) +createListingService : Party -> Party -> Party -> Script (ContractId Listing.I) createListingService operator exchange customer = do offerCid <- submit exchange do exerciseByKeyCmd @Exchange.Role (operator, exchange) Exchange.OfferListingService with .. - submit customer do exerciseCmd offerCid Listing.Accept + toInterfaceContractId <$> submit customer do exerciseCmd offerCid Listing.Accept -createListingAutoService : Party -> Party -> Party -> Script (ContractId ListingAuto.Service) +createListingAutoService : Party -> Party -> Party -> Script (ContractId ListingAuto.I) createListingAutoService operator exchange customer = do offerCid <- submit exchange do exerciseByKeyCmd @Exchange.Role (operator, exchange) Exchange.OfferListingAutoService with .. - submit customer do exerciseCmd offerCid ListingAuto.Accept + toInterfaceContractId <$> submit customer do exerciseCmd offerCid ListingAuto.Accept createAuctionService : Party -> Party -> Party -> Script (ContractId Auction.Service) createAuctionService operator distributor customer = do diff --git a/src/daml/Daml/Finance/Setup/Util/Workflow.daml b/src/daml/Daml/Finance/Setup/Util/Workflow.daml index 11c7db57..9b07cb54 100644 --- a/src/daml/Daml/Finance/Setup/Util/Workflow.daml +++ b/src/daml/Daml/Finance/Setup/Util/Workflow.daml @@ -21,10 +21,12 @@ import Daml.Finance.App.Distribution.Investment.Service qualified as Investment import Daml.Finance.App.Interface.Custody.Service qualified as Custody (Deposit(..), I, OpenAccount(..), RequestDeposit(..), RequestOpenAccount(..)) import Daml.Finance.App.Interface.Issuance.Issuance qualified as Issuance (I) import Daml.Finance.App.Interface.Issuance.Service qualified as IssuanceService (I, Issue(..), RequestIssue(..)) +import Daml.Finance.App.Interface.Listing.Listing qualified as Listing (I) +import Daml.Finance.App.Interface.Listing.Service qualified as ListingService (I, List(..), RequestListing(..)) import Daml.Finance.App.Issuance.Service qualified as Issuance (Service) import Daml.Finance.App.Lifecycle.Service qualified as Lifecycle (Service, DeclareDividend(..), DeclareStockSplit(..), DeclareReplacement(..)) import Daml.Finance.App.Listing.Model qualified as Listing (T) -import Daml.Finance.App.Listing.Service qualified as Listing (CreateListing(..), RequestCreateListing(..), Service) +import Daml.Finance.App.Listing.Service qualified as Listing (Service) import Daml.Finance.App.Trading.Model qualified as Trading (Order, Side(..)) import Daml.Finance.App.Trading.Service qualified as Trading (CreateOrder(..), RequestCreateOrder(..), Service) import Daml.Finance.Data.Observable.Observation qualified as Data (Observation(..)) @@ -205,10 +207,11 @@ issue operator provider customer public quantity account = do issueRequestCid <- submit customer do exerciseCmd (toInterfaceContractId @IssuanceService.I issuanceServiceCid) IssuanceService.RequestIssue with issuanceId; description; quantity; account submitMulti [provider] [public] do exerciseCmd (toInterfaceContractId @IssuanceService.I issuanceServiceCid) IssuanceService.Issue with issueRequestCid -list : Party -> Party -> Party -> Text -> Instrument.K -> Instrument.K -> Parties -> Script (ContractId Listing.T) -list operator provider customer id tradedInstrument quotedInstrument observers = do - createListingRequestCid <- submit customer do exerciseByKeyCmd @Listing.Service (operator, provider, customer) Listing.RequestCreateListing with id; tradedInstrument; quotedInstrument; observers - submit provider do exerciseByKeyCmd @Listing.Service (operator, provider, customer) Listing.CreateListing with createListingRequestCid +list : Party -> Party -> Party -> Id -> Text -> Instrument.K -> Instrument.K -> Parties -> Script (ContractId Listing.I) +list operator provider customer listingId description tradedInstrument quotedInstrument observers = do + Some (listingServiceCid, _) <- queryContractKey @Listing.Service customer (operator, provider, customer) + listingRequestCid <- submit customer do exerciseCmd (toInterfaceContractId @ListingService.I listingServiceCid) ListingService.RequestListing with listingId; description; tradedInstrument; quotedInstrument; observers + submit provider do exerciseCmd (toInterfaceContractId @ListingService.I listingServiceCid) ListingService.List with listingRequestCid createOrder : Party -> Party -> Party -> Party -> Id -> Trading.Side -> Instrument.Q -> Instrument.Q -> Parties -> Script (Optional (ContractId Trading.Order, Trading.Order)) createOrder operator provider customer public id side quantity price observers = do diff --git a/ui/src/context/ServicesContext.tsx b/ui/src/context/ServicesContext.tsx index 65786936..a46fa538 100644 --- a/ui/src/context/ServicesContext.tsx +++ b/ui/src/context/ServicesContext.tsx @@ -22,15 +22,15 @@ import { Service as LendingService } from "@daml.js/daml-finance-app/lib/Daml/Fi import { Service as LifecycleService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Lifecycle/Service" import { Service as StructuringService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Structuring/Service" import { Service as StructuringAutoService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Structuring/Auto/Service" -import { Service as ListingService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Listing/Service" -import { Service as ListingAutoService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Listing/Auto/Service" +import { Service as ListingService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Interface/Listing/Service" +import { Service as ListingAutoService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Interface/Listing/Auto" import { Service as SettlementService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Settlement/Service" import { Service as TradingService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Trading/Service" import { Service as TradingAutoService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Trading/Auto/Service" type ServicesAggregate = { services : ServiceAggregate[] - getService : (custodian : string, owner : string) => ServiceAggregate | undefined + getService : (provider : string, customer : string) => ServiceAggregate | undefined }; type ServiceAggregate = CreateEvent & { @@ -52,8 +52,7 @@ export type ServicesState = { issuance : ServicesAggregate lending : readonly CreateEvent[] lifecycle : readonly CreateEvent[] - listingAuto : readonly CreateEvent[] - listing : readonly CreateEvent[] + listing : ServicesAggregate settlement : readonly CreateEvent[] structuringAuto : readonly CreateEvent[] structuring : readonly CreateEvent[] @@ -64,7 +63,7 @@ export type ServicesState = { const emptyAggregate = { services: [], - getService: (custodian : string, owner : string) => { throw new Error("Not implemented"); } + getService: (provider : string, customer : string) => { throw new Error("Not implemented"); } }; const empty = { @@ -78,12 +77,10 @@ const empty = { bidding: [], fund: [], investment: [], - issuanceAuto: [], issuance: emptyAggregate, lending: [], lifecycle: [], - listingAuto: [], - listing: [], + listing: emptyAggregate, settlement: [], structuringAuto: [], structuring: [], @@ -149,12 +146,10 @@ export const ServicesProvider : React.FC = ({ children }) => { bidding, fund, investment, - issuanceAuto, issuance : createServicesAggregate(issuance, issuanceAuto), lending, lifecycle, - listingAuto, - listing, + listing : createServicesAggregate(listing, listingAuto), settlement, structuringAuto, structuring, diff --git a/ui/src/pages/issuance/New.tsx b/ui/src/pages/issuance/New.tsx index f7ba60bb..0e8fdb7d 100644 --- a/ui/src/pages/issuance/New.tsx +++ b/ui/src/pages/issuance/New.tsx @@ -50,9 +50,8 @@ export const New : React.FC = () => { const customerAccount = accounts.find(c => c.payload.accountView.custodian === party && c.payload.accountView.owner === party); const providerAccount = accounts.find(c => c.payload.accountView.custodian === myB2BServices[0].payload.provider && c.payload.accountView.owner === myB2BServices[0].payload.provider); if (!aggregate || !customerAccount || !providerAccount) return; - const id = uuidv4(); const arg = { - id: { unpack : id }, + id: { unpack : uuidv4() }, description: "Issuance of " + fmt(amount, 0) + " " + aggregate.key.id.unpack, quantity: { amount: amount, unit: aggregate.key }, customerAccount: customerAccount.key, @@ -66,9 +65,8 @@ export const New : React.FC = () => { const svc = issuance.getService(aggregate.payload.depository, party); // TODO: Assumes depository is custodian if (!svc) throw new Error("No issuance service found for provider [" + aggregate.payload.depository + "] and customer [" + party + "]"); if (!account) throw new Error("No account found for custodian " + aggregate.payload.depository + " and owner " + party); - const id = uuidv4(); const arg = { - issuanceId: { unpack : id }, + issuanceId: { unpack : uuidv4() }, description: "Issuance of " + fmt(amount, 0) + " " + aggregate.key.id.unpack, quantity: { amount: amount, unit: aggregate.key }, account: account.key, diff --git a/ui/src/pages/issuance/Requests.tsx b/ui/src/pages/issuance/Requests.tsx index 424fe38a..efc1db9b 100644 --- a/ui/src/pages/issuance/Requests.tsx +++ b/ui/src/pages/issuance/Requests.tsx @@ -3,9 +3,7 @@ import React from "react"; import { useNavigate } from "react-router-dom"; -import { Table, TableBody, TableCell, TableRow, TableHead, Button, Grid, Paper, Typography } from "@mui/material"; -import { IconButton } from "@mui/material"; -import { KeyboardArrowRight } from "@mui/icons-material"; +import { Button } from "@mui/material"; import { CreateEvent } from "@daml/ledger"; import { useLedger, useParty, useStreamQueries } from "@daml/react"; import useStyles from "../styles"; @@ -15,6 +13,10 @@ import { useParties } from "../../context/PartiesContext"; import { useServices } from "../../context/ServicesContext"; import { IssueRequest } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Interface/Issuance/IssueRequest"; import { DeissueRequest } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Interface/Issuance/DeissueRequest"; +import { fmt } from "../../util"; +import { useHoldings } from "../../context/HoldingContext"; +import { Issuance } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Interface/Issuance/Issuance"; +import { HorizontalTable } from "../../components/Table/HorizontalTable"; export const Requests : React.FC = () => { const classes = useStyles(); @@ -23,9 +25,11 @@ export const Requests : React.FC = () => { const ledger = useLedger(); const { getName } = useParties(); const { loading: l1, issuance } = useServices(); - const { loading: l2, contracts: issueRequests } = useStreamQueries(IssueRequest); - const { loading: l3, contracts: deissueRequests } = useStreamQueries(DeissueRequest); - if (l1 || l2 || l3) return ; + const { loading: l2, holdings } = useHoldings(); + const { loading: l3, contracts: issuances } = useStreamQueries(Issuance); + const { loading: l4, contracts: issueRequests } = useStreamQueries(IssueRequest); + const { loading: l5, contracts: deissueRequests } = useStreamQueries(DeissueRequest); + if (l1 || l2 || l3 || l4 || l5) return ; const issue = async (c : CreateEvent) => { const svc = issuance.getService(party, c.payload.customer); @@ -41,80 +45,37 @@ export const Requests : React.FC = () => { navigate("/app/issuance/issuances"); } + const headers = ["Provider", "Customer", "Id", "Description", "Instrument", "Amount", "Action"] + const createIssueRow = (c : CreateEvent) : any[] => { + return [ + getName(c.payload.provider), + getName(c.payload.customer), + c.payload.issuanceId, + c.payload.description, + c.payload.quantity.unit.id.unpack, + fmt(c.payload.quantity.amount, 0), + + ]; + }; + const createDeissueRow = (c : CreateEvent) : any[] => { + const issuance = issuances.find(i => i.payload.id.unpack === c.payload.issuanceId.unpack)!; + const holding = holdings.find(h => h.contractId === c.payload.holdingCid)!; + return [ + getName(c.payload.provider), + getName(c.payload.customer), + c.payload.issuanceId, + issuance.payload.description, + holding.payload.instrument.id.unpack, + fmt(holding.payload.amount, 0), + + ]; + }; + const valuesIssuance : any[] = issueRequests.map(createIssueRow); + const valuesDeissuance : any[] = deissueRequests.map(createDeissueRow); return ( <> - - - - - Issue Requests -
- - - Issuing Agent - Issuer - Issuance Id - Instrument - Quantity - Action - - - - {issueRequests.map((c, i) => ( - - {getName(c.payload.provider)} - {getName(c.payload.customer)} - {c.payload.issuanceId.unpack} - {c.payload.quantity.unit.id.unpack} - {c.payload.quantity.amount} - - {party === c.payload.provider && } - {/* {party === c.payload.client && } */} - - - ))} - -
-
-
- - - Deissue Requests - - - - Provider - Client - Role - Issuance ID - {/* Account */} - {/* Asset - Quantity */} - Action - - - - {deissueRequests.map((c, i) => ( - - {getName(c.payload.provider)} - {getName(c.payload.customer)} - {party === c.payload.provider ? "Provider" : "Client"} - {c.payload.issuanceId} - {/* {c.payload.accountId.label} */} - {/* {c.payload.assetId.label} - {c.payload.quotedAssetId.label} */} - - {party === c.payload.provider && } - {/* {party === c.payload.client && } */} - - - ))} - -
-
-
-
-
+ + ); }; diff --git a/ui/src/pages/listing/Listings.tsx b/ui/src/pages/listing/Listings.tsx index 7a42df48..250b4d31 100644 --- a/ui/src/pages/listing/Listings.tsx +++ b/ui/src/pages/listing/Listings.tsx @@ -6,34 +6,31 @@ import { Button } from "@mui/material"; import { CreateEvent } from "@daml/ledger"; import { useLedger, useParty, useStreamQueries } from "@daml/react"; import useStyles from "../styles"; -import { Service } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Listing/Service"; -import { Service as AutoService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Listing/Auto/Service"; -import { Listing } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Listing/Model"; import { Spinner } from "../../components/Spinner/Spinner"; import { useParties } from "../../context/PartiesContext"; import { useServices } from "../../context/ServicesContext"; import { HorizontalTable } from "../../components/Table/HorizontalTable"; +import { Listing } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Interface/Listing/Listing"; +import { Service as Auto } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Interface/Listing/Auto"; +import { Service } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Interface/Listing/Service"; export const Listings : React.FC = () => { const classes = useStyles(); const party = useParty(); const ledger = useLedger(); const { getName } = useParties(); - const { loading: l1, listing, listingAuto } = useServices(); + const { loading: l1, listing } = useServices(); const { loading: l2, contracts: listings } = useStreamQueries(Listing); if (l1 || l2) return ; - const myServices = listing.filter(s => s.payload.customer === party); - const myAutoServices = listingAuto.filter(s => s.payload.customer === party); const requestDelisting = async (c : CreateEvent) => { - if (myServices.length === 0) throw new Error("No listing service found"); - if (myAutoServices.length > 0) { - await ledger.exercise(AutoService.RequestAndDeleteListing, myAutoServices[0].contractId, { listingCid: c.contractId }); - } else { - await ledger.exercise(Service.RequestDeleteListing, myServices[0].contractId, { listingCid: c.contractId }); - } - } + const svc = listing.getService(c.payload.provider, party); + if (!svc) throw new Error("No listing service found for provider [" + c.payload.provider + "] and customer [" + party + "]"); + const arg = { listingCid: c.contractId } + if (!!svc.auto) await ledger.exercise(Auto.RequestAndDelist, svc.auto.contractId, arg); + else await ledger.exercise(Service.RequestDelisting, svc.service.contractId, arg); + }; const createRow = (c : CreateEvent) : any[] => { return [ @@ -44,7 +41,7 @@ export const Listings : React.FC = () => { c.payload.quotedInstrument.id.unpack, ]; - } + }; const headers = ["Exchange", "Issuer", "Id", "Traded Asset", "Quoted Asset", "Action"] const values : any[] = listings.map(createRow); return ( diff --git a/ui/src/pages/listing/New.tsx b/ui/src/pages/listing/New.tsx index 22e7b3f6..e9c74862 100644 --- a/ui/src/pages/listing/New.tsx +++ b/ui/src/pages/listing/New.tsx @@ -1,22 +1,22 @@ // Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. // SPDX-License-Identifier: Apache-2.0 -import { Service as AutoService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Listing/Auto/Service"; -import { Service } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Listing/Service"; import { useLedger, useParty } from "@daml/react"; +import { v4 as uuidv4 } from "uuid"; import { Button, Grid, Paper, Typography } from "@mui/material"; import classnames from "classnames"; import React, { useState } from "react"; import { useNavigate } from "react-router-dom"; import { SelectInput, toValues } from "../../components/Form/SelectInput"; import { TextInput } from "../../components/Form/TextInput"; -import { Message } from "../../components/Message/Message"; import { Spinner } from "../../components/Spinner/Spinner"; import { useInstruments } from "../../context/InstrumentContext"; import { useParties } from "../../context/PartiesContext"; import { useServices } from "../../context/ServicesContext"; import { createSet } from "../../util"; import useStyles from "../styles"; +import { Service as Auto } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Interface/Listing/Auto"; +import { Service } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Interface/Listing/Service"; export const New : React.FC = () => { const cls = useStyles(); @@ -24,40 +24,37 @@ export const New : React.FC = () => { const [ instrument, setInstrument ] = useState(""); const [ currency, setCurrency ] = useState(""); - const [ id, setId ] = useState(""); + const [ description, setDescription ] = useState(""); const { getParty } = useParties(); const ledger = useLedger(); const party = useParty(); - const { loading: l1, listing, listingAuto } = useServices(); + const { loading: l1, listing } = useServices(); const { loading: l2, latests, tokens } = useInstruments(); - const myListingServices = listing.filter(s => s.payload.customer === party); - const myAutoListingServices = listingAuto.filter(s => s.payload.customer === party); const tradableInstruments = latests; const tradedInstrument = tradableInstruments.find(c => c.payload.id.unpack === instrument); const quotedInstrument = tokens.find(c => c.payload.id.unpack === currency); - const canRequest = !!instrument && !!tradedInstrument && !!currency && !!quotedInstrument && !!id; + const canRequest = !!instrument && !!tradedInstrument && !!currency && !!quotedInstrument && !!description; if (l1 || l2) return ; - if (myListingServices.length === 0) return ; - const hasAuto = myAutoListingServices.length > 0; + const requestListing = async () => { - if (!tradedInstrument || !quotedInstrument) return; + const exchange = getParty("Exchange"); // TODO: Hard-coded exchange party + const svc = listing.getService(exchange, party); + if (!svc) throw new Error("No listing service found for provider [" + exchange + "] and customer [" + party + "]"); + if (!tradedInstrument || !quotedInstrument) throw new Error("Traded or quoted instrument not found"); const arg = { - id, + listingId : { unpack: uuidv4() }, + description, tradedInstrument: tradedInstrument.key, quotedInstrument: quotedInstrument.key, - observers : createSet([ getParty("Public") ]) + observers : createSet([ getParty("Public") ]) // TODO: Hard-coded public party }; - if (hasAuto) { - await ledger.exercise(AutoService.RequestAndCreateListing, myAutoListingServices[0].contractId, arg); - navigate("/app/listing/listings"); - } else { - await ledger.exercise(Service.RequestCreateListing, myListingServices[0].contractId, arg); - navigate("/app/listing/requests"); - } - } + if (!!svc.auto) await ledger.exercise(Auto.RequestAndList, svc.auto.contractId, arg); + else await ledger.exercise(Service.RequestListing, svc.service.contractId, arg); + navigate("/app/listing/listings"); + }; return ( @@ -69,10 +66,10 @@ export const New : React.FC = () => { - + - + diff --git a/ui/src/pages/listing/Requests.tsx b/ui/src/pages/listing/Requests.tsx index c498ef24..4847542c 100644 --- a/ui/src/pages/listing/Requests.tsx +++ b/ui/src/pages/listing/Requests.tsx @@ -3,17 +3,18 @@ import React from "react"; import { useNavigate } from "react-router-dom"; -import { Table, TableBody, TableCell, TableRow, TableHead, Button, Grid, Paper, Typography } from "@mui/material"; -import { IconButton } from "@mui/material"; -import { KeyboardArrowRight } from "@mui/icons-material"; +import { Button } from "@mui/material"; import { CreateEvent } from "@daml/ledger"; import { useLedger, useParty, useStreamQueries } from "@daml/react"; import useStyles from "../styles"; -import { Service } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Listing/Service"; -import { CreateListingRequest, DeleteListingRequest, Listing } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Listing/Model"; +import { Service } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Interface/Listing/Service"; +import { Listing } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Interface/Listing/Listing"; +import { ListingRequest } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Interface/Listing/ListingRequest"; +import { DelistingRequest } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Interface/Listing/DelistingRequest"; import { Spinner } from "../../components/Spinner/Spinner"; import { useParties } from "../../context/PartiesContext"; import { useServices } from "../../context/ServicesContext"; +import { HorizontalTable } from "../../components/Table/HorizontalTable"; export const Requests : React.FC = () => { const classes = useStyles(); @@ -23,113 +24,55 @@ export const Requests : React.FC = () => { const { getName } = useParties(); const { loading: l1, listing } = useServices(); - const { loading: l2, contracts: createRequests } = useStreamQueries(CreateListingRequest); - const { loading: l3, contracts: disableRequests } = useStreamQueries(DeleteListingRequest); + const { loading: l2, contracts: listingRequests } = useStreamQueries(ListingRequest); + const { loading: l3, contracts: delistingRequests } = useStreamQueries(DelistingRequest); const { loading: l4, contracts: listings } = useStreamQueries(Listing); if (l1 || l2 || l3 || l4) return ; - const providerServices = listing.filter(s => s.payload.provider === party); - const deleteEntries = disableRequests.map(dr => ({ request: dr, listing: listings.find(l => l.contractId === dr.payload.listingCid)?.payload })); - const createListing = async (c : CreateEvent) => { - const service = providerServices.find(s => s.payload.customer === c.payload.customer); - if (!service) throw new Error("No listing service found"); - await ledger.exercise(Service.CreateListing, service.contractId, { createListingRequestCid: c.contractId }); + const list = async (c : CreateEvent) => { + const svc = listing.getService(party, c.payload.customer); + if (!svc) throw new Error("No listing service found for provider " + party + " and customer " + c.payload.customer); + await ledger.exercise(Service.List, svc.service.contractId, { listingRequestCid: c.contractId }); navigate("/app/listing/listings"); } - const deleteListing = async (c : CreateEvent) => { - const service = providerServices.find(s => s.payload.customer === c.payload.customer); - if (!service) throw new Error("No listing service found"); - await ledger.exercise(Service.DeleteListing, service.contractId, { deleteListingRequestCid: c.contractId }); + const delist = async (c : CreateEvent) => { + const svc = listing.getService(party, c.payload.customer); + if (!svc) throw new Error("No listing service found for provider " + party + " and customer " + c.payload.customer); + await ledger.exercise(Service.Delist, svc.service.contractId, { delistingRequestCid: c.contractId }); navigate("/app/listing/listings"); } + const headers = ["Provider", "Customer", "Id", "Description", "Traded Instrument", "Quoted Instrument", "Action"] + const createListingRow = (c : CreateEvent) : any[] => { + return [ + getName(c.payload.provider), + getName(c.payload.customer), + c.payload.listingId.unpack, + c.payload.description, + c.payload.tradedInstrument.id.unpack, + c.payload.quotedInstrument.id.unpack, + + ]; + }; + const createDelistingRow = (c : CreateEvent) : any[] => { + const listing = listings.find(l => l.contractId === c.payload.listingCid)!; + return [ + getName(c.payload.provider), + getName(c.payload.customer), + listing.payload.id.unpack, + listing.payload.description, + listing.payload.tradedInstrument.id.unpack, + listing.payload.quotedInstrument.id.unpack, + + ]; + }; + const valuesListing : any[] = listingRequests.map(createListingRow); + const valuesDelisting : any[] = delistingRequests.map(createDelistingRow); return ( <> - - - - - Listing Requests - - - - Provider - Customer - Role - Id - Traded Instrument - Quoted Instrument - Action - Details - - - - {createRequests.map((c, i) => ( - - {getName(c.payload.provider)} - {getName(c.payload.customer)} - {party === c.payload.provider ? "Provider" : "Client"} - {c.payload.id} - {c.payload.tradedInstrument.id.unpack} - {c.payload.quotedInstrument.id.unpack} - - {party === c.payload.provider && } - {/* {party === c.payload.client && } */} - - - navigate("/app/listing/createrequest/" + c.contractId)}> - - - - - ))} - -
-
-
- - - Delisting Requests - - - - Provider - Customer - Role - Id - Traded Instrument - Quoted Instrument - Action - Details - - - - {deleteEntries.map((c, i) => ( - - {getName(c.request.payload.provider)} - {getName(c.request.payload.customer)} - {party === c.request.payload.provider ? "Provider" : "Client"} - {c.listing?.id} - {c.listing?.tradedInstrument.id.unpack} - {c.listing?.quotedInstrument.id.unpack} - - {party === c.request.payload.provider && } - {/* {party === c.payload.client && } */} - - - navigate("/app/listing/deleterequest/" + c.request.contractId)}> - - - - - ))} - -
-
-
-
-
+ + ); }; diff --git a/ui/src/pages/trading/Market.tsx b/ui/src/pages/trading/Market.tsx index 00aa3fa9..13b5ba56 100644 --- a/ui/src/pages/trading/Market.tsx +++ b/ui/src/pages/trading/Market.tsx @@ -79,7 +79,7 @@ export const Market : React.FC = () => { if (myServices.length === 0) return ; if (!listing) return ; - const limits = orders.filter(c => c.payload.listingId === listing.payload.id && parseFloat(c.payload.quantity.amount) !== 0); + const limits = orders.filter(c => c.payload.listingId.unpack === listing.payload.id.unpack && parseFloat(c.payload.quantity.amount) !== 0); const bids = limits.filter(c => c.payload.side === Side.Buy).sort((a, b) => parseFloat(b.payload.price.amount) - parseFloat(a.payload.price.amount)); const asks = limits.filter(c => c.payload.side === Side.Sell).sort((a, b) => parseFloat(b.payload.price.amount) - parseFloat(a.payload.price.amount)); const myOrders = limits.filter(c => c.payload.customer === party); @@ -210,7 +210,7 @@ export const Market : React.FC = () => { {myOrders.map((c, i) => ( - {c.payload.listingId} + {c.payload.listingId.unpack} {c.payload.id.unpack} Limit {c.payload.side} From c5d8d90f8f52096dc924e97f7cf969c76fbee973 Mon Sep 17 00:00:00 2001 From: Georg Schneider Date: Tue, 20 Dec 2022 00:48:10 +0100 Subject: [PATCH 08/31] Add auction and bidding service interfaces --- .../App/Distribution/Auction/Auto.daml | 178 ++++++++++++++++++ .../Distribution/Auction/Auto/Service.daml | 92 --------- .../App/Distribution/Auction/Model.daml | 51 ++--- .../App/Distribution/Auction/Service.daml | 135 +++++-------- .../App/Distribution/Auction/Utils.daml | 28 +-- .../App/Distribution/Bidding/Auto.daml | 152 +++++++++++++++ .../Distribution/Bidding/Auto/Service.daml | 89 --------- .../App/Distribution/Bidding/Model.daml | 86 +++------ .../App/Distribution/Bidding/Service.daml | 103 ++++------ .../Custody/CloseAccountRequest.daml | 4 +- .../App/Interface/Custody/DepositRequest.daml | 4 +- .../Interface/Custody/OpenAccountRequest.daml | 4 +- .../Interface/Custody/WithdrawRequest.daml | 4 +- .../Distribution/Auction/Auction.daml | 59 ++++++ .../Interface/Distribution/Auction/Auto.daml | 47 +++++ .../Auction/CreateAuctionRequest.daml | 40 ++++ .../Distribution/Auction/Service.daml | 68 +++++++ .../Interface/Distribution/Bidding/Auto.daml | 44 +++++ .../Interface/Distribution/Bidding/Bid.daml | 100 ++++++++++ .../Bidding/CreateBidRequest.daml | 38 ++++ .../Distribution/Bidding/Service.daml | 73 +++++++ .../Interface/Issuance/DeissueRequest.daml | 2 +- .../App/Interface/Issuance/Issuance.daml | 2 +- .../App/Interface/Issuance/IssueRequest.daml | 2 +- .../Interface/Listing/DelistingRequest.daml | 2 +- .../App/Interface/Listing/Listing.daml | 2 +- .../App/Interface/Listing/ListingRequest.daml | 2 +- .../Daml/Finance/App/Role/Distributor.daml | 21 ++- .../Daml/Finance/Setup/Scenario/Default.daml | 6 +- src/daml/Daml/Finance/Setup/Util/Service.daml | 28 +-- .../Daml/Finance/Setup/Util/Workflow.daml | 67 ++++--- ui/src/apps/Distribution.tsx | 4 +- ui/src/components/Instrument/Aggregate.tsx | 2 +- ui/src/context/ServicesContext.tsx | 42 ++--- ui/src/hooks/Network.tsx | 8 +- ui/src/pages/distribution/auction/Auction.tsx | 35 ++-- .../pages/distribution/auction/Auctions.tsx | 4 +- ui/src/pages/distribution/auction/Bidding.tsx | 34 ++-- ui/src/pages/distribution/auction/New.tsx | 97 ++++------ .../pages/distribution/auction/Requests.tsx | 70 +++---- .../pages/distribution/bidding/Auctions.tsx | 6 +- ui/src/pages/issuance/New.tsx | 28 +-- 42 files changed, 1174 insertions(+), 689 deletions(-) create mode 100644 src/daml/Daml/Finance/App/Distribution/Auction/Auto.daml delete mode 100644 src/daml/Daml/Finance/App/Distribution/Auction/Auto/Service.daml create mode 100644 src/daml/Daml/Finance/App/Distribution/Bidding/Auto.daml delete mode 100644 src/daml/Daml/Finance/App/Distribution/Bidding/Auto/Service.daml create mode 100644 src/daml/Daml/Finance/App/Interface/Distribution/Auction/Auction.daml create mode 100644 src/daml/Daml/Finance/App/Interface/Distribution/Auction/Auto.daml create mode 100644 src/daml/Daml/Finance/App/Interface/Distribution/Auction/CreateAuctionRequest.daml create mode 100644 src/daml/Daml/Finance/App/Interface/Distribution/Auction/Service.daml create mode 100644 src/daml/Daml/Finance/App/Interface/Distribution/Bidding/Auto.daml create mode 100644 src/daml/Daml/Finance/App/Interface/Distribution/Bidding/Bid.daml create mode 100644 src/daml/Daml/Finance/App/Interface/Distribution/Bidding/CreateBidRequest.daml create mode 100644 src/daml/Daml/Finance/App/Interface/Distribution/Bidding/Service.daml diff --git a/src/daml/Daml/Finance/App/Distribution/Auction/Auto.daml b/src/daml/Daml/Finance/App/Distribution/Auction/Auto.daml new file mode 100644 index 00000000..828eb977 --- /dev/null +++ b/src/daml/Daml/Finance/App/Distribution/Auction/Auto.daml @@ -0,0 +1,178 @@ +-- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +-- SPDX-License-Identifier: Apache-2.0 + +{-# LANGUAGE MultiWayIf #-} + +module Daml.Finance.App.Distribution.Auction.Auto where + +import DA.Action (foldlA) +import DA.Either (partitionEithers) +import DA.Foldable (forA_) +import DA.List (sortOn, mapAccumL) +import DA.Optional (whenSome) +import DA.Set (fromList, singleton) +import Daml.Finance.App.Distribution.Auction.Model qualified as Model (Auction, CreateAuctionRequest(..)) +import Daml.Finance.App.Distribution.Bidding.Service qualified as BiddingService (T) +import Daml.Finance.App.Interface.Base.Service qualified as Base (I, View(..)) +import Daml.Finance.App.Interface.Common.Util (fetchAndRemove) +import Daml.Finance.App.Interface.Distribution.Auction.Auction qualified as Auction (Status(..)) +import Daml.Finance.App.Interface.Distribution.Auction.Auto qualified as Auto (I, HasImplementation, RequestAndCreateAuction(..), View(..)) +import Daml.Finance.App.Interface.Distribution.Auction.CreateAuctionRequest qualified as CreateAuctionRequest (View(..)) +import Daml.Finance.App.Interface.Distribution.Auction.Service qualified as Service (CreateAuction(..), I, ProcessAuction(..), RequestCreateAuction(..), View(..)) +import Daml.Finance.App.Interface.Distribution.Bidding.Service qualified as BiddingService (I, RejectBid(..)) +import Daml.Finance.Interface.Account.Account qualified as Account (R, exerciseInterfaceByKey) +import Daml.Finance.Interface.Holding.Base qualified as Holding (Acquire(..), I, LockType(..), Release(..)) +import Daml.Finance.Interface.Account.Util (getAccount) +import Daml.Finance.Interface.Util.Disclosure qualified as Disclosure (AddObservers(..), I, RemoveObservers(..)) +import Daml.Finance.Interface.Settlement.Batch qualified as Batch (Settle(..)) +import Daml.Finance.App.Distribution.Auction.Model (Auction(..), CreateAuctionRequest(..)) +import Daml.Finance.App.Distribution.Auction.Utils (dutchAuction, splitList, generateSettlementInstruction) +import Daml.Finance.App.Interface.Distribution.Bidding.Bid qualified as Bid (Allocation(..), SettleAllocation(..), Status(..)) + +type T = Service + +instance Auto.HasImplementation Service + +template Service + with + operator : Party + provider : Party + customer : Party + where + signatory operator, provider, customer + + key (operator, provider, customer) : (Party, Party, Party) + maintainer key._1 + + interface instance Base.I for Service where + view = Base.View with operator; provider; customer + terminate = pure () + + interface instance Service.I for Service where + view = Service.View + asBase = toInterface @Base.I this + requestCreateAuction Service.RequestCreateAuction{auctionId; description; quantity; currency; floor; collateralCid; receivableAccount; observers} = do + -- Disclose holding + collateral <- fetch collateralCid + collateralCid <- coerceContractId <$> exercise (coerceContractId collateralCid : ContractId Disclosure.I) Disclosure.AddObservers with disclosers = singleton customer; observersToAdd = (show auctionId, fromList [provider]) + + -- Disclose delivering securities account + (_, delRef) <- fetchByKey @Account.R $ getAccount collateral + exercise (coerceContractId delRef.cid : ContractId Disclosure.I) Disclosure.AddObservers with disclosers = singleton customer; observersToAdd = (show auctionId, fromList [provider]) + + -- Disclose receiving cash account + (_, recRef) <- fetchByKey @Account.R receivableAccount + exercise (coerceContractId recRef.cid : ContractId Disclosure.I) Disclosure.AddObservers with disclosers = singleton customer; observersToAdd = (show auctionId, singleton provider) + + toInterfaceContractId <$> create Model.CreateAuctionRequest with operator; provider; customer; auctionId; description; quantity; currency; floor; collateralCid; receivableAccount; observers + createAuction Service.CreateAuction{createAuctionRequestCid} = do + CreateAuctionRequest.View{auctionId; description; quantity; currency; floor; collateralCid; receivableAccount; observers} <- view <$> fetchAndRemove createAuctionRequestCid + collateralCid <- coerceContractId <$> exercise (toInterfaceContractId collateralCid : ContractId Holding.I) Holding.Acquire with newLockers = fromList [ provider ]; context = show auctionId; lockType = Holding.Semaphore + toInterfaceContractId <$> create Auction with operator; provider; customer; id = auctionId; description; quantity; currency; floor; collateralCid; receivableAccount; status = Auction.Open; observers + processAuction Service.ProcessAuction{settlementFactoryCid; auctionCid; bidCids} = do + let auctionTCid = fromInterfaceContractId @Model.Auction auctionCid + auction <- fetch auctionTCid + collateral <- fetch auction.collateralCid + bids <- zip bidCids <$> forA bidCids (fmap view . fetch) + collaterals <- mapA (\(_, bidView) -> fetch bidView.collateralCid) bids + assertMsg "Auction already successfully processed" (auction.status `elem` [Auction.Open, Auction.NoValidBids]) + + -- Split bids on those above / below the floor price -> Sort valid bids descendingly -> Execute Auction -> Split auction result on allocated / unallocated (ie, zero allocation) + let + collateralAccount = getAccount collateral + collateralAccounts = map getAccount collaterals + receivableAccounts = map ((.receivableAccount) . snd) bids + (invalidBids, validBids) = partitionEithers $ splitList (\(_, bid) -> bid.details.price.amount >= auction.floor) bids + sortedBids = sortOn (\(_, bid) -> Down bid.details) validBids + ((remaining, finalPrice), allocations) = mapAccumL dutchAuction (auction.quantity.amount, 0.0) sortedBids + (allocatedBids, unallocatedBids) = partitionEithers $ splitList (\allocation -> allocation.amount == 0.0) allocations + + -- Return assets of all invalid and unallocated bids. Also update their bid status accordingly + forA_ invalidBids (\(bidCid, bid) -> do + (serviceCid, _) <- fetchByKey @BiddingService.T (bid.operator, bid.provider, bid.customer) + exercise (toInterfaceContractId @BiddingService.I serviceCid) BiddingService.RejectBid with bidCid; newStatus = Bid.Invalid) + forA_ unallocatedBids (\Bid.Allocation{bidCid, bid} -> do + (serviceCid, _) <- fetchByKey @BiddingService.T (bid.operator, bid.provider, bid.customer) + exercise (toInterfaceContractId @BiddingService.I serviceCid) BiddingService.RejectBid with bidCid; newStatus = Bid.NoAllocation) + + -- Unlock auction collateral + auctionCollateralClid <- coerceContractId <$> exercise (toInterfaceContractId auction.collateralCid : ContractId Holding.I) Holding.Release with context = show auction.id + + -- Generate Settlement instructions for allocated bids + let settleAllocations = (\allocation -> Bid.SettleAllocation with allocation; price = finalPrice; issuer = customer) <$> allocatedBids + (remainingDepositCidOpt, batchCids) <- foldlA (generateSettlementInstruction settlementFactoryCid provider auction.receivableAccount) (Some auctionCollateralClid, []) settleAllocations + + -- Settle transfers + forA_ batchCids (`exercise` Batch.Settle with actors = singleton provider) + + -- Undisclose unallocated deposit + whenSome remainingDepositCidOpt \depositCid -> do + exercise (coerceContractId depositCid : ContractId Disclosure.I) Disclosure.RemoveObservers with disclosers = singleton customer; observersToRemove = (show auction.id, singleton provider) + pure () + + -- Undisclose accounts + Account.exerciseInterfaceByKey @Disclosure.I auction.receivableAccount provider Disclosure.RemoveObservers with disclosers = singleton provider; observersToRemove = (show auction.id, singleton provider) + Account.exerciseInterfaceByKey @Disclosure.I collateralAccount provider Disclosure.RemoveObservers with disclosers = singleton provider; observersToRemove = (show auction.id, singleton provider) + forA_ receivableAccounts (\a -> Account.exerciseInterfaceByKey @Disclosure.I a provider Disclosure.RemoveObservers with disclosers = singleton provider; observersToRemove = (show auction.id, singleton provider)) + forA_ collateralAccounts (\a -> Account.exerciseInterfaceByKey @Disclosure.I a provider Disclosure.RemoveObservers with disclosers = singleton provider; observersToRemove = (show auction.id, singleton provider)) + + -- Update Auction contract with the outcome of the auction processing + let newStatus = if + | remaining == auction.quantity.amount -> Auction.NoValidBids + | remaining > 0.0 -> Auction.PartiallyAllocated with finalPrice; remaining + | otherwise -> Auction.FullyAllocated with finalPrice + archive auctionCid + toInterfaceContractId <$> create auction with status = newStatus + + interface instance Auto.I for Service where + view = Auto.View + asService = toInterface @Service.I this + requestAndCreateAuction self Auto.RequestAndCreateAuction{auctionId; description; quantity; currency; floor; collateralCid; receivableAccount; observers} = do + createAuctionRequestCid <- exercise self Service.RequestCreateAuction with auctionId; description; quantity; currency; floor; collateralCid; receivableAccount; observers + exercise self Service.CreateAuction with createAuctionRequestCid + +template Offer + with + operator : Party + provider : Party + customer : Party + where + signatory operator, provider + observer customer + + choice Accept : ContractId Service + controller customer + do + create Service with .. + + choice Decline : () + controller customer + do + return () + + choice Withdraw : () + controller provider + do pure () + +template Request + with + provider : Party + customer : Party + where + signatory customer + observer provider + + choice Cancel : () + controller customer + do pure () + + choice Reject : () + controller provider + do pure () + + choice Approve : ContractId Service + with + operator : Party + controller operator, provider + do + create Service with .. diff --git a/src/daml/Daml/Finance/App/Distribution/Auction/Auto/Service.daml b/src/daml/Daml/Finance/App/Distribution/Auction/Auto/Service.daml deleted file mode 100644 index 4a2c119b..00000000 --- a/src/daml/Daml/Finance/App/Distribution/Auction/Auto/Service.daml +++ /dev/null @@ -1,92 +0,0 @@ --- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. --- SPDX-License-Identifier: Apache-2.0 - -module Daml.Finance.App.Distribution.Auction.Auto.Service where - -import Daml.Finance.Interface.Account.Account qualified as Account (K) -import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (K, Q) -import Daml.Finance.Interface.Holding.Fungible qualified as Fungible (I) -import Daml.Finance.Interface.Types.Common (Parties) -import Daml.Finance.App.Distribution.Auction.Model (Auction) -import Daml.Finance.App.Distribution.Auction.Service qualified as S (CreateAuction(..), RequestCreateAuction(..), Service) - -type S = Service - -template Service - with - operator : Party - provider : Party - customer : Party - where - signatory operator, provider, customer - - key (operator, provider, customer) : (Party, Party, Party) - maintainer key._1 - - nonconsuming choice RequestAndCreateAuction : ContractId Auction - with - id : Text - quantity : Instrument.Q - currency : Instrument.K - floor : Decimal - collateralCid : ContractId Fungible.I - receivableAccount : Account.K - observers : Parties - controller customer - do - createAuctionRequestCid <- exerciseByKey @S.Service (operator, provider, customer) S.RequestCreateAuction with id; quantity; currency; floor; collateralCid; receivableAccount; observers - exerciseByKey @S.Service (operator, provider, customer) S.CreateAuction with createAuctionRequestCid - - choice Terminate : () - with - actor : Party - controller actor - do - assert $ actor == operator || actor == provider || actor == customer - pure () - -template Offer - with - operator : Party - provider : Party - customer : Party - where - signatory operator, provider - observer customer - - choice Accept : ContractId Service - controller customer - do - create Service with .. - - choice Decline : () - controller customer - do - return () - - choice Withdraw : () - controller provider - do pure () - -template Request - with - provider : Party - customer : Party - where - signatory customer - observer provider - - choice Cancel : () - controller customer - do pure () - - choice Reject : () - controller provider - do pure () - - choice Approve : ContractId Service - with - operator : Party - controller operator, provider - do - create Service with .. diff --git a/src/daml/Daml/Finance/App/Distribution/Auction/Model.daml b/src/daml/Daml/Finance/App/Distribution/Auction/Model.daml index 7703fc3c..9457009a 100644 --- a/src/daml/Daml/Finance/App/Distribution/Auction/Model.daml +++ b/src/daml/Daml/Finance/App/Distribution/Auction/Model.daml @@ -3,35 +3,29 @@ module Daml.Finance.App.Distribution.Auction.Model where -import Daml.Finance.Interface.Account.Account qualified as Account (K) +import DA.Set (fromList) +import Daml.Finance.App.Interface.Common.Removable qualified as Removable (I, View(..)) +import Daml.Finance.App.Interface.Distribution.Auction.Auction qualified as Auction (I, Status, View(..)) +import Daml.Finance.App.Interface.Distribution.Auction.CreateAuctionRequest qualified as CreateAuctionRequest (I, View(..)) import Daml.Finance.Interface.Holding.Fungible qualified as Fungible (I) import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (K, Q) -import Daml.Finance.Interface.Types.Common (Parties) +import Daml.Finance.Interface.Types.Common (AccountKey, Id, Parties) type T = Auction -data Status - = Open - | PartiallyAllocated with - finalPrice : Decimal - remaining : Decimal - | FullyAllocated with - finalPrice : Decimal - | NoValidBids - deriving (Eq, Show) - template Auction with operator : Party provider : Party customer : Party - id : Text + id : Id + description : Text quantity : Instrument.Q currency : Instrument.K floor : Decimal collateralCid : ContractId Fungible.I - receivableAccount : Account.K - status : Status + receivableAccount : AccountKey + status : Auction.Status observers : Parties where signatory operator, provider, customer @@ -39,27 +33,36 @@ template Auction ensure quantity.amount > 0.0 - key (operator, provider, id) : (Party, Party, Text) + key (operator, provider, id) : (Party, Party, Id) maintainer key._1 - nonconsuming choice Fetch : Auction - with - actor : Party - controller actor - do - pure this + interface instance Removable.I for Auction where + view = Removable.View with removers = fromList [operator, provider, customer] + + interface instance Auction.I for Auction where + view = Auction.View with operator; provider; customer; id; description; quantity; currency; floor; collateralCid; receivableAccount; status; observers + asRemovable = toInterface @Removable.I this template CreateAuctionRequest with operator : Party provider : Party customer : Party - id : Text + auctionId : Id + description : Text quantity : Instrument.Q currency : Instrument.K floor : Decimal collateralCid : ContractId Fungible.I - receivableAccount : Account.K + receivableAccount : AccountKey observers : Parties where signatory operator, provider, customer + + interface instance Removable.I for CreateAuctionRequest where + view = Removable.View with removers = fromList [operator, provider, customer] + + interface instance CreateAuctionRequest.I for CreateAuctionRequest where + view = CreateAuctionRequest.View with operator; provider; customer; auctionId; description; quantity; currency; floor; collateralCid; receivableAccount; observers + asRemovable = toInterface @Removable.I this + diff --git a/src/daml/Daml/Finance/App/Distribution/Auction/Service.daml b/src/daml/Daml/Finance/App/Distribution/Auction/Service.daml index 9add57f7..04447c3b 100644 --- a/src/daml/Daml/Finance/App/Distribution/Auction/Service.daml +++ b/src/daml/Daml/Finance/App/Distribution/Auction/Service.daml @@ -11,22 +11,23 @@ import DA.Foldable (forA_) import DA.List (sortOn, mapAccumL) import DA.Optional (whenSome) import DA.Set (fromList, singleton) -import Daml.Finance.Interface.Account.Account qualified as Account (K, R, exerciseInterfaceByKey) -import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (K, Q) +import Daml.Finance.App.Distribution.Auction.Model qualified as Model (Auction(..), CreateAuctionRequest(..)) +import Daml.Finance.App.Distribution.Auction.Utils (dutchAuction, splitList, generateSettlementInstruction) +import Daml.Finance.App.Distribution.Bidding.Service qualified as BiddingService (T) +import Daml.Finance.App.Interface.Base.Service qualified as Base (I, View(..)) +import Daml.Finance.App.Interface.Common.Util (fetchAndRemove) +import Daml.Finance.App.Interface.Distribution.Auction.Auction qualified as Auction (Status(..)) +import Daml.Finance.App.Interface.Distribution.Auction.CreateAuctionRequest qualified as CreateAuctionRequest (View(..)) +import Daml.Finance.App.Interface.Distribution.Auction.Service qualified as Service (CreateAuction(..), I, ProcessAuction(..), RequestCreateAuction(..), View(..)) +import Daml.Finance.App.Interface.Distribution.Bidding.Bid qualified as Bid (Allocation(..), SettleAllocation(..), Status(..)) +import Daml.Finance.App.Interface.Distribution.Bidding.Service qualified as BiddingService (I, RejectBid(..)) +import Daml.Finance.Interface.Account.Account qualified as Account (R, exerciseInterfaceByKey) import Daml.Finance.Interface.Holding.Base qualified as Holding (Acquire(..), I, LockType(..), Release(..)) -import Daml.Finance.Interface.Holding.Fungible qualified as Fungible (I) import Daml.Finance.Interface.Account.Util (getAccount) import Daml.Finance.Interface.Util.Disclosure qualified as Disclosure (AddObservers(..), I, RemoveObservers(..)) -import Daml.Finance.Interface.Types.Common (Parties) -import Daml.Finance.Interface.Settlement.Factory qualified as Factory (I) import Daml.Finance.Interface.Settlement.Batch qualified as Batch (Settle(..)) -import Daml.Finance.App.Distribution.Auction.Model (Auction(..), CreateAuctionRequest(..), Status(..)) -import Daml.Finance.App.Distribution.Auction.Utils (dutchAuction, splitList, generateSettlementInstruction) -import Daml.Finance.App.Distribution.Bidding.Model qualified as Bidding (Allocation(..), Bid, SettleAllocation(..), Status(..)) -import Daml.Finance.App.Distribution.Bidding.Service qualified as Bidding (RejectBid(..), S) -import Daml.Finance.App.Util (fetchAndArchive) -type S = Service +type T = Service template Service with @@ -39,66 +40,38 @@ template Service key (operator, provider, customer) : (Party, Party, Party) maintainer key._1 - nonconsuming choice RequestCreateAuction : ContractId CreateAuctionRequest - with - id : Text - quantity : Instrument.Q - currency : Instrument.K - floor : Decimal - collateralCid : ContractId Fungible.I - receivableAccount : Account.K - observers : Parties - controller customer - do + interface instance Base.I for Service where + view = Base.View with operator; provider; customer + terminate = pure () + + interface instance Service.I for Service where + view = Service.View + asBase = toInterface @Base.I this + requestCreateAuction Service.RequestCreateAuction{auctionId; description; quantity; currency; floor; collateralCid; receivableAccount; observers} = do -- Disclose holding collateral <- fetch collateralCid - collateralCid <- coerceContractId <$> exercise (coerceContractId collateralCid : ContractId Disclosure.I) Disclosure.AddObservers with disclosers = singleton customer; observersToAdd = (id, fromList [provider]) + collateralCid <- coerceContractId <$> exercise (coerceContractId collateralCid : ContractId Disclosure.I) Disclosure.AddObservers with disclosers = singleton customer; observersToAdd = (show auctionId, fromList [provider]) -- Disclose delivering securities account (_, delRef) <- fetchByKey @Account.R $ getAccount collateral - exercise (coerceContractId delRef.cid : ContractId Disclosure.I) Disclosure.AddObservers with disclosers = singleton customer; observersToAdd = (id, fromList [provider]) + exercise (coerceContractId delRef.cid : ContractId Disclosure.I) Disclosure.AddObservers with disclosers = singleton customer; observersToAdd = (show auctionId, fromList [provider]) -- Disclose receiving cash account (_, recRef) <- fetchByKey @Account.R receivableAccount - exercise (coerceContractId recRef.cid : ContractId Disclosure.I) Disclosure.AddObservers with disclosers = singleton customer; observersToAdd = (id, singleton provider) - - create CreateAuctionRequest with operator; provider; customer; id; quantity; currency; floor; collateralCid; receivableAccount; observers - - nonconsuming choice CancelAuctionRequest : () - with - createAuctionRequestCid : ContractId CreateAuctionRequest - controller customer - do - archive createAuctionRequestCid - - nonconsuming choice CreateAuction : ContractId Auction - with - createAuctionRequestCid : ContractId CreateAuctionRequest - controller provider - do - CreateAuctionRequest{id; quantity; currency; floor; collateralCid; receivableAccount; observers} <- fetchAndArchive createAuctionRequestCid - collateralCid <- coerceContractId <$> exercise (toInterfaceContractId collateralCid : ContractId Holding.I) Holding.Acquire with newLockers = fromList [ provider ]; context = id; lockType = Holding.Semaphore - create Auction with operator; provider; customer; id; quantity; currency; floor; collateralCid; receivableAccount; status = Open; observers - - nonconsuming choice RejectAuction : () - with - createAuctionRequestCid : ContractId CreateAuctionRequest - controller provider - do - archive createAuctionRequestCid - - nonconsuming choice ProcessAuction : ContractId Auction - with - settlementFactoryCid : ContractId Factory.I - auctionCid : ContractId Auction - bidCids : [ContractId Bidding.Bid] - controller provider - do - auction <- fetch auctionCid + exercise (coerceContractId recRef.cid : ContractId Disclosure.I) Disclosure.AddObservers with disclosers = singleton customer; observersToAdd = (show auctionId, singleton provider) + + toInterfaceContractId <$> create Model.CreateAuctionRequest with operator; provider; customer; auctionId; description; quantity; currency; floor; collateralCid; receivableAccount; observers + createAuction Service.CreateAuction{createAuctionRequestCid} = do + CreateAuctionRequest.View{auctionId; description; quantity; currency; floor; collateralCid; receivableAccount; observers} <- view <$> fetchAndRemove createAuctionRequestCid + collateralCid <- coerceContractId <$> exercise (toInterfaceContractId collateralCid : ContractId Holding.I) Holding.Acquire with newLockers = fromList [ provider ]; context = show auctionId; lockType = Holding.Semaphore + toInterfaceContractId <$> create Model.Auction with operator; provider; customer; id = auctionId; description; quantity; currency; floor; collateralCid; receivableAccount; status = Auction.Open; observers + processAuction Service.ProcessAuction{settlementFactoryCid; auctionCid; bidCids} = do + let auctionTCid = fromInterfaceContractId @Model.Auction auctionCid + auction <- fetch auctionTCid collateral <- fetch auction.collateralCid - bids <- zip bidCids <$> forA bidCids fetch - collaterals <- mapA (fetch . (.collateralCid) . snd) bids - assertMsg "Auction already successfully processed" (auction.status `elem` [Open, NoValidBids]) + bids <- zip bidCids <$> forA bidCids (fmap view . fetch) + collaterals <- mapA (\(_, bidView) -> fetch bidView.collateralCid) bids + assertMsg "Auction already successfully processed" (auction.status `elem` [Auction.Open, Auction.NoValidBids]) -- Split bids on those above / below the floor price -> Sort valid bids descendingly -> Execute Auction -> Split auction result on allocated / unallocated (ie, zero allocation) let @@ -111,14 +84,18 @@ template Service (allocatedBids, unallocatedBids) = partitionEithers $ splitList (\allocation -> allocation.amount == 0.0) allocations -- Return assets of all invalid and unallocated bids. Also update their bid status accordingly - forA_ invalidBids (\(bidCid, bid) -> exerciseByKey @Bidding.S (bid.operator, bid.provider, bid.customer) Bidding.RejectBid with bidCid; newStatus = Bidding.Invalid) - forA_ unallocatedBids (\Bidding.Allocation{bidCid, bid} -> exerciseByKey @Bidding.S (bid.operator, bid.provider, bid.customer) Bidding.RejectBid with bidCid; newStatus = Bidding.NoAllocation) + forA_ invalidBids (\(bidCid, bid) -> do + (serviceCid, _) <- fetchByKey @BiddingService.T (bid.operator, bid.provider, bid.customer) + exercise (toInterfaceContractId @BiddingService.I serviceCid) BiddingService.RejectBid with bidCid; newStatus = Bid.Invalid) + forA_ unallocatedBids (\Bid.Allocation{bidCid, bid} -> do + (serviceCid, _) <- fetchByKey @BiddingService.T (bid.operator, bid.provider, bid.customer) + exercise (toInterfaceContractId @BiddingService.I serviceCid) BiddingService.RejectBid with bidCid; newStatus = Bid.NoAllocation) -- Unlock auction collateral - auctionCollateralClid <- coerceContractId <$> exercise (toInterfaceContractId auction.collateralCid : ContractId Holding.I) Holding.Release with context = auction.id + auctionCollateralClid <- coerceContractId <$> exercise (toInterfaceContractId auction.collateralCid : ContractId Holding.I) Holding.Release with context = show auction.id -- Generate Settlement instructions for allocated bids - let settleAllocations = (\allocation -> Bidding.SettleAllocation with allocation; price = finalPrice; issuer = customer) <$> allocatedBids + let settleAllocations = (\allocation -> Bid.SettleAllocation with allocation; price = finalPrice; issuer = customer) <$> allocatedBids (remainingDepositCidOpt, batchCids) <- foldlA (generateSettlementInstruction settlementFactoryCid provider auction.receivableAccount) (Some auctionCollateralClid, []) settleAllocations -- Settle transfers @@ -126,30 +103,22 @@ template Service -- Undisclose unallocated deposit whenSome remainingDepositCidOpt \depositCid -> do - exercise (coerceContractId depositCid : ContractId Disclosure.I) Disclosure.RemoveObservers with disclosers = singleton customer; observersToRemove = (auction.id, singleton provider) + exercise (coerceContractId depositCid : ContractId Disclosure.I) Disclosure.RemoveObservers with disclosers = singleton customer; observersToRemove = (show auction.id, singleton provider) pure () -- Undisclose accounts - Account.exerciseInterfaceByKey @Disclosure.I auction.receivableAccount provider Disclosure.RemoveObservers with disclosers = singleton provider; observersToRemove = (auction.id, singleton provider) - Account.exerciseInterfaceByKey @Disclosure.I collateralAccount provider Disclosure.RemoveObservers with disclosers = singleton provider; observersToRemove = (auction.id, singleton provider) - forA_ receivableAccounts (\a -> Account.exerciseInterfaceByKey @Disclosure.I a provider Disclosure.RemoveObservers with disclosers = singleton provider; observersToRemove = (auction.id, singleton provider)) - forA_ collateralAccounts (\a -> Account.exerciseInterfaceByKey @Disclosure.I a provider Disclosure.RemoveObservers with disclosers = singleton provider; observersToRemove = (auction.id, singleton provider)) + Account.exerciseInterfaceByKey @Disclosure.I auction.receivableAccount provider Disclosure.RemoveObservers with disclosers = singleton provider; observersToRemove = (show auction.id, singleton provider) + Account.exerciseInterfaceByKey @Disclosure.I collateralAccount provider Disclosure.RemoveObservers with disclosers = singleton provider; observersToRemove = (show auction.id, singleton provider) + forA_ receivableAccounts (\a -> Account.exerciseInterfaceByKey @Disclosure.I a provider Disclosure.RemoveObservers with disclosers = singleton provider; observersToRemove = (show auction.id, singleton provider)) + forA_ collateralAccounts (\a -> Account.exerciseInterfaceByKey @Disclosure.I a provider Disclosure.RemoveObservers with disclosers = singleton provider; observersToRemove = (show auction.id, singleton provider)) -- Update Auction contract with the outcome of the auction processing let newStatus = if - | remaining == auction.quantity.amount -> NoValidBids - | remaining > 0.0 -> PartiallyAllocated with finalPrice; remaining - | otherwise -> FullyAllocated with finalPrice + | remaining == auction.quantity.amount -> Auction.NoValidBids + | remaining > 0.0 -> Auction.PartiallyAllocated with finalPrice; remaining + | otherwise -> Auction.FullyAllocated with finalPrice archive auctionCid - create auction with status = newStatus - - choice Terminate : () - with - actor : Party - controller actor - do - assert $ actor == operator || actor == provider || actor == customer - pure () + toInterfaceContractId <$> create auction with status = newStatus template Offer with diff --git a/src/daml/Daml/Finance/App/Distribution/Auction/Utils.daml b/src/daml/Daml/Finance/App/Distribution/Auction/Utils.daml index c27e6451..76b99758 100644 --- a/src/daml/Daml/Finance/App/Distribution/Auction/Utils.daml +++ b/src/daml/Daml/Finance/App/Distribution/Auction/Utils.daml @@ -4,8 +4,9 @@ module Daml.Finance.App.Distribution.Auction.Utils where import DA.Set (singleton) -import Daml.Finance.App.Distribution.Bidding.Service qualified as Bidding -import Daml.Finance.App.Distribution.Bidding.Model qualified as Bidding (AllocateInstruction(..), Allocation(..), ApproveInstruction(..), Bid(..), SettleAllocation(..)) +import Daml.Finance.App.Distribution.Bidding.Service qualified as Service (T) +import Daml.Finance.App.Interface.Distribution.Bidding.Service qualified as Service (I, ProcessAllocation(..)) +import Daml.Finance.App.Interface.Distribution.Bidding.Bid qualified as Bid (AllocateInstruction(..), Allocation(..), ApproveInstruction(..), I, SettleAllocation(..), View) import Daml.Finance.Interface.Account.Account qualified as Account (K) import Daml.Finance.Interface.Holding.Fungible (Fungible, Split(..)) import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (qty) @@ -34,28 +35,29 @@ splitList p xs = foldr (\x acc -> if p x then Right x :: acc else Left x :: acc) -- | A map/accumulator function for processing a submitted bid. -- Accepts the remaining quantity and price as an accululator along the current Bid as input -- Output is the updated accululator (if applicable) along with the Bid mapped to an Allocation (depending on the accumulator and bid information) -dutchAuction : (Decimal, Decimal) -> (ContractId Bidding.Bid, Bidding.Bid) -> ((Decimal, Decimal), Bidding.Allocation) -dutchAuction acc@(0.0, _) (bidCid, bid) = (acc, Bidding.Allocation with amount = 0.0; bidCid; bid) +dutchAuction : (Decimal, Decimal) -> (ContractId Bid.I, Bid.View) -> ((Decimal, Decimal), Bid.Allocation) +dutchAuction acc@(0.0, _) (bidCid, bid) = (acc, Bid.Allocation with amount = 0.0; bidCid; bid) dutchAuction (remaining, _) (bidCid, bid) = let amount = bid.details.quantity.amount bidPrice = bid.details.price.amount in if remaining >= amount - then ((remaining - amount, bidPrice), Bidding.Allocation with amount; bidCid; bid) - else ((0.0, bidPrice), Bidding.Allocation with amount = remaining; bidCid; bid) + then ((remaining - amount, bidPrice), Bid.Allocation with amount; bidCid; bid) + else ((0.0, bidPrice), Bid.Allocation with amount = remaining; bidCid; bid) -- | An accumulator function which processes generates the settlement instruction for both an issuer and a bidder based of the output of the dutch auction -generateSettlementInstruction : ContractId Factory -> Party -> Account.K -> (Optional (ContractId Fungible), [ContractId Batch]) -> Bidding.SettleAllocation -> Update (Optional (ContractId Fungible), [ContractId Batch]) +generateSettlementInstruction : ContractId Factory -> Party -> Account.K -> (Optional (ContractId Fungible), [ContractId Batch]) -> Bid.SettleAllocation -> Update (Optional (ContractId Fungible), [ContractId Batch]) generateSettlementInstruction _ _ _ (None, _) _ = error "Auction:generateSettlementInstruction - Issuers AssetDeposit has no remaining units to allocate" -generateSettlementInstruction settlementFactoryCid settler issuerAccount (Some issuerDepositCid, batchCids) Bidding.SettleAllocation{allocation, price, issuer} = do +generateSettlementInstruction settlementFactoryCid settler issuerAccount (Some issuerDepositCid, batchCids) Bid.SettleAllocation{allocation, price, issuer} = do let allocatedAmount = allocation.amount allocatedNotional = allocation.amount * price -- | Process bid side - bid <- fetch allocation.bidCid - (bidCid, bidDepositCid) <- exerciseByKey @Bidding.Service (bid.operator, bid.provider, bid.customer) Bidding.ProcessAllocation with bidCid = allocation.bidCid; amount = allocatedAmount; price + bid <- view <$> fetch allocation.bidCid + (serviceCid, _) <- fetchByKey @Service.T (bid.operator, bid.provider, bid.customer) + (bidCid, bidDepositCid) <- exercise (toInterfaceContractId @Service.I serviceCid) Service.ProcessAllocation with bidCid = allocation.bidCid; amount = allocatedAmount; price let buyer = bid.customer payment = Step with sender = bid.customer; receiver = issuer; quantity = (Instrument.qty allocatedNotional bid.details.price.unit) @@ -73,12 +75,12 @@ generateSettlementInstruction settlementFactoryCid settler issuerAccount (Some i allocatedDeposit <- fetch allocatedDepositCid let delivery = Step with sender = issuer; receiver = buyer; quantity = (Instrument.qty (getAmount allocatedDeposit) (getInstrument allocatedDeposit)) - id = bid.auctionId <> "-" <> partyToText buyer + id = show bid.auctionId <> "-" <> partyToText buyer (batchCid, [deliveryCid, paymentCid]) <- exercise settlementFactoryCid Instruct with instructors = singleton settler; settlers = singleton settler; id = Id id; description = "Settlement of auction " <> id; contextId = Some $ Id id; steps = [delivery, payment] deliveryCid <- fst <$> exercise deliveryCid Allocate with actors = singleton settler; allocation = Pledge $ toInterfaceContractId allocatedDepositCid - exercise bidCid Bidding.ApproveInstruction with instructionCid = deliveryCid; account = bid.receivableAccount - paymentCid <- exercise bidCid Bidding.AllocateInstruction with instructionCid = paymentCid; transferableCid = toInterfaceContractId bidDepositCid + exercise bidCid Bid.ApproveInstruction with instructionCid = deliveryCid; account = bid.receivableAccount + paymentCid <- exercise bidCid Bid.AllocateInstruction with instructionCid = paymentCid; holdingCid = bidDepositCid exercise paymentCid Approve with actors = singleton settler; approval = TakeDelivery issuerAccount pure (splitResult.rest, batchCid :: batchCids) diff --git a/src/daml/Daml/Finance/App/Distribution/Bidding/Auto.daml b/src/daml/Daml/Finance/App/Distribution/Bidding/Auto.daml new file mode 100644 index 00000000..5c3432e4 --- /dev/null +++ b/src/daml/Daml/Finance/App/Distribution/Bidding/Auto.daml @@ -0,0 +1,152 @@ +-- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +-- SPDX-License-Identifier: Apache-2.0 + +module Daml.Finance.App.Distribution.Bidding.Auto where + +import DA.Assert ((===)) +import DA.List (head) +import DA.Optional (fromSome) +import DA.Set (singleton) +import Daml.Finance.App.Interface.Base.Service qualified as Base (I, View(..)) +import Daml.Finance.App.Interface.Common.Util (fetchAndRemove) +import Daml.Finance.App.Interface.Distribution.Auction.Auction qualified as Auction (GetView(..)) +import Daml.Finance.App.Interface.Distribution.Bidding.Auto qualified as Auto (I, HasImplementation, RequestAndCreateBid(..), View(..)) +import Daml.Finance.App.Interface.Distribution.Bidding.Bid qualified as Bid (Details(..), Status(..), UpdateStatus(..)) +import Daml.Finance.App.Interface.Distribution.Bidding.CreateBidRequest qualified as CreateBidRequest (View(..)) +import Daml.Finance.App.Interface.Distribution.Bidding.Service qualified as Service (I, CreateBid(..), ProcessAllocation(..), RejectBid(..), RequestCreateBid(..), View(..)) +import Daml.Finance.Interface.Account.Account qualified as Account (R) +import Daml.Finance.Interface.Account.Util (getAccount) +import Daml.Finance.Interface.Holding.Fungible qualified as Fungible (I, Split(..), SplitResult(..)) +import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (qty) +import Daml.Finance.Interface.Holding.Base qualified as Holding (Acquire(..), I, LockType(..), Release(..)) +import Daml.Finance.Interface.Holding.Util (getAmount, getInstrument) +import Daml.Finance.Interface.Util.Disclosure qualified as Disclosure (AddObservers(..), I, RemoveObservers(..)) +import Daml.Finance.App.Distribution.Bidding.Model (Bid(..), CreateBidRequest(..)) + +type T = Service + +instance Auto.HasImplementation Service + +template Service + with + operator : Party + provider : Party + customer : Party + where + signatory operator, provider, customer + + key (operator, provider, customer) : (Party, Party, Party) + maintainer key._1 + + interface instance Base.I for Service where + view = Base.View with operator; provider; customer + terminate = pure () + + interface instance Service.I for Service where + view = Service.View + asBase = toInterface @Base.I this + requestCreateBid Service.RequestCreateBid{auctionCid; amount; price; collateralCid; receivableAccount} = do + auction <- exercise auctionCid Auction.GetView with actor = customer + collateral <- fetch collateralCid + getInstrument collateral === auction.currency + getAmount collateral === price * amount + assertMsg "Bid amount can't be larger than available size" $ amount <= auction.quantity.amount + + -- Disclose holding + investorHolding <- fetch collateralCid + investorHoldingCid : ContractId Fungible.I <- coerceContractId <$> exercise (coerceContractId collateralCid : ContractId Disclosure.I) Disclosure.AddObservers with disclosers = singleton customer; observersToAdd = (show auction.id, singleton provider) + -- Disclose delivering securities account + let investorSendingAccount = getAccount investorHolding + (_, delRef) <- fetchByKey @Account.R investorSendingAccount + exercise (coerceContractId delRef.cid : ContractId Disclosure.I) Disclosure.AddObservers with disclosers = singleton customer; observersToAdd = (show auction.id, singleton provider) + -- Disclose receiving cash account + (_, recRef) <- fetchByKey @Account.R receivableAccount + exercise (coerceContractId recRef.cid : ContractId Disclosure.I) Disclosure.AddObservers with disclosers = singleton customer; observersToAdd = (show auction.id, singleton provider) + -- Lock holding + collateralCid <- coerceContractId <$> exercise (coerceContractId investorHoldingCid : ContractId Holding.I) Holding.Acquire with newLockers = singleton provider; context = show auction.id; lockType = Holding.Semaphore + + let + quantity = Instrument.qty amount auction.quantity.unit + priceQty = Instrument.qty price auction.currency + toInterfaceContractId <$> create CreateBidRequest with operator; provider; customer; issuer = auction.customer; auctionId = auction.id; quantity; price = priceQty; collateralCid; receivableAccount + createBid Service.CreateBid{createBidRequestCid} = do + CreateBidRequest.View{issuer; auctionId; collateralCid; receivableAccount; price; quantity} <- view <$> fetchAndRemove createBidRequestCid + time <- getTime + toInterfaceContractId <$> create Bid with operator; provider; customer; issuer; details = (Bid.Details with price; quantity; time); auctionId; collateralCid; receivableAccount; status = Bid.Pending + processAllocation Service.ProcessAllocation{bidCid; amount; price} = do + -- Fetch Bid -> Extract their deposit -> Split and return unused allocation (if necessary) to the investor -> Update Bid Status + bid <- view <$> fetch bidCid + bidCollateralCid : ContractId Disclosure.I <- coerceContractId <$> exercise (toInterfaceContractId @Holding.I bid.collateralCid) Holding.Release with context = show bid.auctionId + bidCollateralCid <- coerceContractId . fromSome <$> exercise bidCollateralCid Disclosure.RemoveObservers with disclosers = singleton provider; observersToRemove = (show bid.auctionId, singleton provider) + bidCollateral <- fetch bidCollateralCid + bidCollateralCid <- + if getAmount bidCollateral > amount * price + then do + Fungible.SplitResult{splitCids, rest} <- exercise bidCollateralCid Fungible.Split with amounts = [amount * price] + pure $ head splitCids + else do pure bidCollateralCid + let + newStatus = + if bid.details.quantity.amount == amount + then Bid.FullAllocation with price + else Bid.PartialAllocation with price; amount + newBidCid <- exercise bidCid Bid.UpdateStatus with newStatus + pure (newBidCid, bidCollateralCid) + rejectBid Service.RejectBid{bidCid; newStatus} = do + bid <- view <$> fetch bidCid + returnedCollateralCid <- exercise (toInterfaceContractId @Holding.I bid.collateralCid) Holding.Release with context = show bid.auctionId + newBidCid <- exercise bidCid Bid.UpdateStatus with newStatus + pure (newBidCid, coerceContractId returnedCollateralCid) + + interface instance Auto.I for Service where + view = Auto.View + asService = toInterface @Service.I this + requestAndCreateBid self Auto.RequestAndCreateBid{auctionCid; amount; price; collateralCid; receivableAccount} = do + createBidRequestCid <- exercise self Service.RequestCreateBid with auctionCid; amount; price; collateralCid; receivableAccount + exercise self Service.CreateBid with createBidRequestCid + +template Offer + with + operator : Party + provider : Party + customer : Party + where + signatory operator, provider + observer customer + + choice Accept : ContractId Service + controller customer + do + create Service with .. + + choice Decline : () + controller customer + do + return () + + choice Withdraw : () + controller provider + do pure () + +template Request + with + provider : Party + customer : Party + where + signatory customer + observer provider + + choice Cancel : () + controller customer + do pure () + + choice Reject : () + controller provider + do pure () + + choice Approve : ContractId Service + with + operator : Party + controller operator, provider + do + create Service with .. diff --git a/src/daml/Daml/Finance/App/Distribution/Bidding/Auto/Service.daml b/src/daml/Daml/Finance/App/Distribution/Bidding/Auto/Service.daml deleted file mode 100644 index 19a3e20f..00000000 --- a/src/daml/Daml/Finance/App/Distribution/Bidding/Auto/Service.daml +++ /dev/null @@ -1,89 +0,0 @@ --- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. --- SPDX-License-Identifier: Apache-2.0 - -module Daml.Finance.App.Distribution.Bidding.Auto.Service where - -import Daml.Finance.Interface.Account.Account qualified as Account (K) -import Daml.Finance.Interface.Holding.Fungible qualified as Fungible (I) -import Daml.Finance.App.Distribution.Auction.Model qualified as Auction (T) -import Daml.Finance.App.Distribution.Bidding.Model (Bid) -import Daml.Finance.App.Distribution.Bidding.Service qualified as Bidding (CreateBid(..), S, RequestCreateBid(..)) - -type S = Service - -template Service - with - operator : Party - provider : Party - customer : Party - where - signatory operator, provider, customer - - key (operator, provider, customer) : (Party, Party, Party) - maintainer key._1 - - nonconsuming choice RequestAndCreateBid : ContractId Bid - with - auctionCid : ContractId Auction.T - amount : Decimal - price : Decimal - collateralCid : ContractId Fungible.I - receivableAccount : Account.K - controller customer - do - createBidRequestCid <- exerciseByKey @Bidding.S (operator, provider, customer) Bidding.RequestCreateBid with auctionCid; amount; price; collateralCid; receivableAccount - exerciseByKey @Bidding.S (operator, provider, customer) Bidding.CreateBid with createBidRequestCid - - choice Terminate : () - with - actor : Party - controller actor - do - assert $ actor == operator || actor == provider || actor == customer - pure () - -template Offer - with - operator : Party - provider : Party - customer : Party - where - signatory operator, provider - observer customer - - choice Accept : ContractId Service - controller customer - do - create Service with .. - - choice Decline : () - controller customer - do - return () - - choice Withdraw : () - controller provider - do pure () - -template Request - with - provider : Party - customer : Party - where - signatory customer - observer provider - - choice Cancel : () - controller customer - do pure () - - choice Reject : () - controller provider - do pure () - - choice Approve : ContractId Service - with - operator : Party - controller operator, provider - do - create Service with .. diff --git a/src/daml/Daml/Finance/App/Distribution/Bidding/Model.daml b/src/daml/Daml/Finance/App/Distribution/Bidding/Model.daml index a70a178f..ff238b70 100644 --- a/src/daml/Daml/Finance/App/Distribution/Bidding/Model.daml +++ b/src/daml/Daml/Finance/App/Distribution/Bidding/Model.daml @@ -3,34 +3,16 @@ module Daml.Finance.App.Distribution.Bidding.Model where -import DA.Set (singleton) +import DA.Set (fromList, singleton) +import Daml.Finance.App.Interface.Common.Removable qualified as Removable (I, View(..)) +import Daml.Finance.App.Interface.Distribution.Bidding.Bid qualified as Bid (AllocateInstruction(..), ApproveInstruction(..), Details, I, Status, UpdateStatus(..), View(..)) +import Daml.Finance.App.Interface.Distribution.Bidding.CreateBidRequest qualified as CreateBidRequest (I, View(..)) import Daml.Finance.Interface.Account.Account qualified as Account (K) import Daml.Finance.Interface.Holding.Fungible qualified as Fungible (I) import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (Q) -import Daml.Finance.Interface.Holding.Transferable qualified as Transferable (I) -import Daml.Finance.Interface.Settlement.Instruction qualified as Instruction (Allocate(..), Approve(..), I) +import Daml.Finance.Interface.Settlement.Instruction qualified as Instruction (Allocate(..), Approve(..)) import Daml.Finance.Interface.Settlement.Types qualified as T (Allocation(Pledge), Approval(TakeDelivery)) - -data Details = Details with - quantity : Instrument.Q - price : Instrument.Q - time : Time - deriving (Eq, Show) - -instance Ord Details where - compare x y = (x.price.amount, x.quantity.amount, Down x.time) `compare` (y.price.amount, y.quantity.amount, Down y.time) - -data Allocation = Allocation with - bidCid : ContractId Bid - bid : Bid - amount : Decimal - deriving (Eq, Show) - -data SettleAllocation = SettleAllocation with - allocation : Allocation - price : Decimal - issuer : Party - deriving (Eq, Show) +import Daml.Finance.Interface.Types.Common (Id) template CreateBidRequest with @@ -38,7 +20,7 @@ template CreateBidRequest provider : Party customer : Party issuer : Party - auctionId : Text + auctionId : Id quantity : Instrument.Q price : Instrument.Q collateralCid : ContractId Fungible.I @@ -46,16 +28,12 @@ template CreateBidRequest where signatory operator, provider, customer -data Status - = Pending - | FullAllocation with - price : Decimal - | PartialAllocation with - price : Decimal - amount : Decimal - | NoAllocation - | Invalid - deriving (Eq, Show) + interface instance Removable.I for CreateBidRequest where + view = Removable.View with removers = fromList [operator, provider, customer] + + interface instance CreateBidRequest.I for CreateBidRequest where + view = CreateBidRequest.View with operator; provider; customer; issuer; auctionId; quantity; price; collateralCid; receivableAccount + asRemovable = toInterface @Removable.I this template Bid with @@ -63,35 +41,27 @@ template Bid provider : Party customer : Party issuer : Party - details : Details - auctionId : Text + details : Bid.Details + auctionId : Id collateralCid : ContractId Fungible.I receivableAccount : Account.K - status : Status + status : Bid.Status where signatory operator, provider, customer observer issuer ensure details.quantity.amount > 0.0 - choice UpdateStatus : ContractId Bid - with - newStatus : Status - controller provider - do - create this with status = newStatus + interface instance Removable.I for Bid where + view = Removable.View with removers = fromList [operator, provider, customer] - nonconsuming choice ApproveInstruction : ContractId Instruction.I - with - instructionCid : ContractId Instruction.I - account : Account.K - controller provider - do + interface instance Bid.I for Bid where + view = Bid.View with operator; provider; customer; issuer; details; auctionId; collateralCid; receivableAccount; status + asRemovable = toInterface @Removable.I this + updateStatus Bid.UpdateStatus{newStatus} = do + toInterfaceContractId <$> create this with status = newStatus + approveInstruction Bid.ApproveInstruction{instructionCid; account} = do + -- TODO: Assert instruction is for the right auction exercise instructionCid Instruction.Approve with actors = singleton provider; approval = T.TakeDelivery account - - nonconsuming choice AllocateInstruction : ContractId Instruction.I - with - instructionCid : ContractId Instruction.I - transferableCid : ContractId Transferable.I - controller provider - do - fst <$> exercise instructionCid Instruction.Allocate with actors = singleton provider; allocation = T.Pledge $ toInterfaceContractId transferableCid + allocateInstruction Bid.AllocateInstruction{instructionCid; holdingCid} = do + -- TODO: Assert instruction is for the right auction + fst <$> exercise instructionCid Instruction.Allocate with actors = singleton provider; allocation = T.Pledge $ toInterfaceContractId holdingCid diff --git a/src/daml/Daml/Finance/App/Distribution/Bidding/Service.daml b/src/daml/Daml/Finance/App/Distribution/Bidding/Service.daml index e0d4b094..cd117d75 100644 --- a/src/daml/Daml/Finance/App/Distribution/Bidding/Service.daml +++ b/src/daml/Daml/Finance/App/Distribution/Bidding/Service.daml @@ -7,18 +7,22 @@ import DA.Assert ((===)) import DA.List (head) import DA.Optional (fromSome) import DA.Set (singleton) -import Daml.Finance.Interface.Account.Account qualified as Account (K, R) +import Daml.Finance.App.Interface.Base.Service qualified as Base (I, View(..)) +import Daml.Finance.App.Interface.Common.Util (fetchAndRemove) +import Daml.Finance.App.Interface.Distribution.Auction.Auction qualified as Auction (GetView(..)) +import Daml.Finance.App.Interface.Distribution.Bidding.Bid qualified as Bid (Details(..), Status(..), UpdateStatus(..)) +import Daml.Finance.App.Interface.Distribution.Bidding.CreateBidRequest qualified as CreateBidRequest (View(..)) +import Daml.Finance.App.Interface.Distribution.Bidding.Service qualified as Service (I, CreateBid(..), ProcessAllocation(..), RejectBid(..), RequestCreateBid(..), View(..)) +import Daml.Finance.Interface.Account.Account qualified as Account (R) import Daml.Finance.Interface.Account.Util (getAccount) import Daml.Finance.Interface.Holding.Fungible qualified as Fungible (I, Split(..), SplitResult(..)) import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (qty) import Daml.Finance.Interface.Holding.Base qualified as Holding (Acquire(..), I, LockType(..), Release(..)) -import Daml.Finance.Interface.Holding.Transferable qualified as Transferable (I) import Daml.Finance.Interface.Holding.Util (getAmount, getInstrument) import Daml.Finance.Interface.Util.Disclosure qualified as Disclosure (AddObservers(..), I, RemoveObservers(..)) -import Daml.Finance.App.Distribution.Auction.Model qualified as Auction (Fetch(..), T) -import Daml.Finance.App.Distribution.Bidding.Model (Bid(..), CreateBidRequest(..), Details(..), Status(..), UpdateStatus(..)) +import Daml.Finance.App.Distribution.Bidding.Model (Bid(..), CreateBidRequest(..)) -type S = Service +type T = Service template Service with @@ -31,16 +35,15 @@ template Service key (operator, provider, customer) : (Party, Party, Party) maintainer key._1 - nonconsuming choice RequestCreateBid : ContractId CreateBidRequest - with - auctionCid : ContractId Auction.T - amount : Decimal - price : Decimal - collateralCid : ContractId Fungible.I - receivableAccount : Account.K - controller customer - do - auction <- exercise auctionCid Auction.Fetch with actor = customer + interface instance Base.I for Service where + view = Base.View with operator; provider; customer + terminate = pure () + + interface instance Service.I for Service where + view = Service.View + asBase = toInterface @Base.I this + requestCreateBid Service.RequestCreateBid{auctionCid; amount; price; collateralCid; receivableAccount} = do + auction <- exercise auctionCid Auction.GetView with actor = customer collateral <- fetch collateralCid getInstrument collateral === auction.currency getAmount collateral === price * amount @@ -48,43 +51,30 @@ template Service -- Disclose holding investorHolding <- fetch collateralCid - investorHoldingCid : ContractId Fungible.I <- coerceContractId <$> exercise (coerceContractId collateralCid : ContractId Disclosure.I) Disclosure.AddObservers with disclosers = singleton customer; observersToAdd = (auction.id, singleton provider) + investorHoldingCid : ContractId Fungible.I <- coerceContractId <$> exercise (coerceContractId collateralCid : ContractId Disclosure.I) Disclosure.AddObservers with disclosers = singleton customer; observersToAdd = (show auction.id, singleton provider) -- Disclose delivering securities account let investorSendingAccount = getAccount investorHolding (_, delRef) <- fetchByKey @Account.R investorSendingAccount - exercise (coerceContractId delRef.cid : ContractId Disclosure.I) Disclosure.AddObservers with disclosers = singleton customer; observersToAdd = (auction.id, singleton provider) + exercise (coerceContractId delRef.cid : ContractId Disclosure.I) Disclosure.AddObservers with disclosers = singleton customer; observersToAdd = (show auction.id, singleton provider) -- Disclose receiving cash account (_, recRef) <- fetchByKey @Account.R receivableAccount - exercise (coerceContractId recRef.cid : ContractId Disclosure.I) Disclosure.AddObservers with disclosers = singleton customer; observersToAdd = (auction.id, singleton provider) + exercise (coerceContractId recRef.cid : ContractId Disclosure.I) Disclosure.AddObservers with disclosers = singleton customer; observersToAdd = (show auction.id, singleton provider) -- Lock holding - collateralCid <- coerceContractId <$> exercise (coerceContractId investorHoldingCid : ContractId Holding.I) Holding.Acquire with newLockers = singleton provider; context = auction.id; lockType = Holding.Semaphore + collateralCid <- coerceContractId <$> exercise (coerceContractId investorHoldingCid : ContractId Holding.I) Holding.Acquire with newLockers = singleton provider; context = show auction.id; lockType = Holding.Semaphore let quantity = Instrument.qty amount auction.quantity.unit priceQty = Instrument.qty price auction.currency - create CreateBidRequest with operator; provider; customer; issuer = auction.customer; auctionId = auction.id; quantity; price = priceQty; collateralCid; receivableAccount - - nonconsuming choice CreateBid : ContractId Bid - with - createBidRequestCid : ContractId CreateBidRequest - controller provider - do - CreateBidRequest{issuer; auctionId; collateralCid; receivableAccount; price; quantity} <- fetch createBidRequestCid - + toInterfaceContractId <$> create CreateBidRequest with operator; provider; customer; issuer = auction.customer; auctionId = auction.id; quantity; price = priceQty; collateralCid; receivableAccount + createBid Service.CreateBid{createBidRequestCid} = do + CreateBidRequest.View{issuer; auctionId; collateralCid; receivableAccount; price; quantity} <- view <$> fetchAndRemove createBidRequestCid time <- getTime - create Bid with operator; provider; customer; issuer; details = (Details with price; quantity; time); auctionId; collateralCid; receivableAccount; status = Pending - - nonconsuming choice ProcessAllocation : (ContractId Bid, ContractId Fungible.I) - with - bidCid : ContractId Bid - amount : Decimal - price : Decimal - controller provider - do + toInterfaceContractId <$> create Bid with operator; provider; customer; issuer; details = (Bid.Details with price; quantity; time); auctionId; collateralCid; receivableAccount; status = Bid.Pending + processAllocation Service.ProcessAllocation{bidCid; amount; price} = do -- Fetch Bid -> Extract their deposit -> Split and return unused allocation (if necessary) to the investor -> Update Bid Status - bid <- fetch bidCid - bidCollateralCid : ContractId Disclosure.I <- coerceContractId <$> exercise (coerceContractId bid.collateralCid : ContractId Holding.I) Holding.Release with context = bid.auctionId - bidCollateralCid <- coerceContractId . fromSome <$> exercise bidCollateralCid Disclosure.RemoveObservers with disclosers = singleton provider; observersToRemove = (bid.auctionId, singleton provider) + bid <- view <$> fetch bidCid + bidCollateralCid : ContractId Disclosure.I <- coerceContractId <$> exercise (toInterfaceContractId @Holding.I bid.collateralCid) Holding.Release with context = show bid.auctionId + bidCollateralCid <- coerceContractId . fromSome <$> exercise bidCollateralCid Disclosure.RemoveObservers with disclosers = singleton provider; observersToRemove = (show bid.auctionId, singleton provider) bidCollateral <- fetch bidCollateralCid bidCollateralCid <- if getAmount bidCollateral > amount * price @@ -92,32 +82,19 @@ template Service Fungible.SplitResult{splitCids, rest} <- exercise bidCollateralCid Fungible.Split with amounts = [amount * price] pure $ head splitCids else do pure bidCollateralCid - let newStatus = if bid.details.quantity.amount == amount - then FullAllocation with price - else PartialAllocation with price; amount - - newBidCid <- exercise bidCid UpdateStatus with newStatus + let + newStatus = + if bid.details.quantity.amount == amount + then Bid.FullAllocation with price + else Bid.PartialAllocation with price; amount + newBidCid <- exercise bidCid Bid.UpdateStatus with newStatus pure (newBidCid, bidCollateralCid) - - nonconsuming choice RejectBid : (ContractId Bid, ContractId Transferable.I) - with - bidCid : ContractId Bid - newStatus : Status - controller provider - do - bid <- fetch bidCid - returnedCollateralCid <- exercise (coerceContractId bid.collateralCid : ContractId Holding.I) Holding.Release with context = bid.auctionId - newBidCid <- exercise bidCid UpdateStatus with newStatus + rejectBid Service.RejectBid{bidCid; newStatus} = do + bid <- view <$> fetch bidCid + returnedCollateralCid <- exercise (toInterfaceContractId @Holding.I bid.collateralCid) Holding.Release with context = show bid.auctionId + newBidCid <- exercise bidCid Bid.UpdateStatus with newStatus pure (newBidCid, coerceContractId returnedCollateralCid) - choice Terminate : () - with - actor : Party - controller actor - do - assert $ actor == operator || actor == provider || actor == customer - pure () - template Offer with operator : Party diff --git a/src/daml/Daml/Finance/App/Interface/Custody/CloseAccountRequest.daml b/src/daml/Daml/Finance/App/Interface/Custody/CloseAccountRequest.daml index aab010b7..3cadf9fa 100644 --- a/src/daml/Daml/Finance/App/Interface/Custody/CloseAccountRequest.daml +++ b/src/daml/Daml/Finance/App/Interface/Custody/CloseAccountRequest.daml @@ -20,9 +20,9 @@ data View = View interface CloseAccountRequest where viewtype View - -- ^ Interface view types. + -- ^ Interface view type. asRemovable : Removable.I - -- ^ Conversion to the `Removable` interface. + -- ^ Conversion to the `Removable` interface. -- | Type constraint for requiring templates to implement `CloseAccountRequest`. type Implementation t = (HasToInterface t CloseAccountRequest, Removable.Implementation t) diff --git a/src/daml/Daml/Finance/App/Interface/Custody/DepositRequest.daml b/src/daml/Daml/Finance/App/Interface/Custody/DepositRequest.daml index d5258e06..1c46d0f6 100644 --- a/src/daml/Daml/Finance/App/Interface/Custody/DepositRequest.daml +++ b/src/daml/Daml/Finance/App/Interface/Custody/DepositRequest.daml @@ -22,9 +22,9 @@ data View = View interface DepositRequest where viewtype View - -- ^ Interface view types. + -- ^ Interface view type. asRemovable : Removable.I - -- ^ Conversion to the `Removable` interface. + -- ^ Conversion to the `Removable` interface. -- | Type constraint for requiring templates to implement `DepositRequest`. type Implementation t = (HasToInterface t DepositRequest, Removable.Implementation t) diff --git a/src/daml/Daml/Finance/App/Interface/Custody/OpenAccountRequest.daml b/src/daml/Daml/Finance/App/Interface/Custody/OpenAccountRequest.daml index 29912c79..8dcbf28b 100644 --- a/src/daml/Daml/Finance/App/Interface/Custody/OpenAccountRequest.daml +++ b/src/daml/Daml/Finance/App/Interface/Custody/OpenAccountRequest.daml @@ -24,9 +24,9 @@ data View = View interface OpenAccountRequest where viewtype View - -- ^ Interface view types. + -- ^ Interface view type. asRemovable : Removable.I - -- ^ Conversion to the `Removable` interface. + -- ^ Conversion to the `Removable` interface. -- | Type constraint for requiring templates to implement `OpenAccountRequest`. type Implementation t = (HasToInterface t OpenAccountRequest, Removable.Implementation t) diff --git a/src/daml/Daml/Finance/App/Interface/Custody/WithdrawRequest.daml b/src/daml/Daml/Finance/App/Interface/Custody/WithdrawRequest.daml index 3c21bb01..ec5fb83c 100644 --- a/src/daml/Daml/Finance/App/Interface/Custody/WithdrawRequest.daml +++ b/src/daml/Daml/Finance/App/Interface/Custody/WithdrawRequest.daml @@ -20,9 +20,9 @@ data View = View interface WithdrawRequest where viewtype View - -- ^ Interface view types. + -- ^ Interface view type. asRemovable : Removable.I - -- ^ Conversion to the `Removable` interface. + -- ^ Conversion to the `Removable` interface. -- | Type constraint for requiring templates to implement `Service`. type Implementation t = (HasToInterface t WithdrawRequest, Removable.Implementation t) diff --git a/src/daml/Daml/Finance/App/Interface/Distribution/Auction/Auction.daml b/src/daml/Daml/Finance/App/Interface/Distribution/Auction/Auction.daml new file mode 100644 index 00000000..55c0766c --- /dev/null +++ b/src/daml/Daml/Finance/App/Interface/Distribution/Auction/Auction.daml @@ -0,0 +1,59 @@ +-- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +-- SPDX-License-Identifier: Apache-2.0 + +module Daml.Finance.App.Interface.Distribution.Auction.Auction where + +import Daml.Finance.App.Interface.Common.Removable qualified as Removable (I, Implementation) +import Daml.Finance.Interface.Holding.Fungible qualified as Fungible (I) +import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (K, Q) +import Daml.Finance.Interface.Types.Common (AccountKey, Id, Parties) + +type I = Auction + +type V = View + +data View = View + with + operator : Party + provider : Party + customer : Party + id : Id + description : Text + quantity : Instrument.Q + currency : Instrument.K + floor : Decimal + collateralCid : ContractId Fungible.I + receivableAccount : AccountKey + status : Status + observers : Parties + deriving (Eq, Show) + +data Status + = Open + | PartiallyAllocated with + finalPrice : Decimal + remaining : Decimal + | FullyAllocated with + finalPrice : Decimal + | NoValidBids + deriving (Eq, Show) + +interface Auction where + viewtype View + -- ^ Interface view type. + asRemovable : Removable.I + -- ^ Conversion to the `Removable` interface. + + nonconsuming choice GetView : View + with + actor : Party + controller actor + do + pure $ view this + + +-- | Type constraint for requiring templates to implement `Auction`. +type Implementation t = (HasToInterface t Auction, Removable.Implementation t) +class (Implementation t) => HasImplementation t +instance HasImplementation Auction +instance HasToInterface Auction Removable.I where _toInterface = asRemovable diff --git a/src/daml/Daml/Finance/App/Interface/Distribution/Auction/Auto.daml b/src/daml/Daml/Finance/App/Interface/Distribution/Auction/Auto.daml new file mode 100644 index 00000000..b2748012 --- /dev/null +++ b/src/daml/Daml/Finance/App/Interface/Distribution/Auction/Auto.daml @@ -0,0 +1,47 @@ +-- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +-- SPDX-License-Identifier: Apache-2.0 + +module Daml.Finance.App.Interface.Distribution.Auction.Auto where + +import Daml.Finance.App.Interface.Base.Service qualified as Base (I) +import Daml.Finance.App.Interface.Distribution.Auction.Auction qualified as Auction (I) +import Daml.Finance.App.Interface.Distribution.Auction.Service qualified as Service (I, Implementation, asBase) +import Daml.Finance.Interface.Holding.Fungible qualified as Fungible (I) +import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (K, Q) +import Daml.Finance.Interface.Types.Common (AccountKey, Id, Parties) + +type I = Service + +type V = View + +data View = View {} + deriving (Eq, Show) + +interface Service where + viewtype V + + asService : Service.I + -- ^ Conversion to custody `Service` interface. + requestAndCreateAuction : ContractId Service.I -> RequestAndCreateAuction -> Update (ContractId Auction.I) + -- ^ Implementation of the `RequestAndCreateAuction` choice. + + nonconsuming choice RequestAndCreateAuction : (ContractId Auction.I) + with + auctionId : Id + description : Text + quantity : Instrument.Q + currency : Instrument.K + floor : Decimal + collateralCid : ContractId Fungible.I + receivableAccount : AccountKey + observers : Parties + controller (view $ Service.asBase $ asService this).customer + do + requestAndCreateAuction this (toInterfaceContractId self) arg + +-- | Type constraint for requiring templates to implement `Service`. +type Implementation t = (HasToInterface t Service, Service.Implementation t) +class (Implementation t) => HasImplementation t +instance HasImplementation Service +instance HasToInterface Service Service.I where _toInterface = asService +instance HasToInterface Service Base.I where _toInterface = Service.asBase . asService diff --git a/src/daml/Daml/Finance/App/Interface/Distribution/Auction/CreateAuctionRequest.daml b/src/daml/Daml/Finance/App/Interface/Distribution/Auction/CreateAuctionRequest.daml new file mode 100644 index 00000000..6da68912 --- /dev/null +++ b/src/daml/Daml/Finance/App/Interface/Distribution/Auction/CreateAuctionRequest.daml @@ -0,0 +1,40 @@ +-- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +-- SPDX-License-Identifier: Apache-2.0 + +module Daml.Finance.App.Interface.Distribution.Auction.CreateAuctionRequest where + +import Daml.Finance.App.Interface.Common.Removable qualified as Removable (I, Implementation) +import Daml.Finance.Interface.Holding.Fungible qualified as Fungible (I) +import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (K, Q) +import Daml.Finance.Interface.Types.Common (AccountKey, Id, Parties) + +type I = CreateAuctionRequest + +type V = View + +data View = View + with + operator : Party + provider : Party + customer : Party + auctionId : Id + description : Text + quantity : Instrument.Q + currency : Instrument.K + floor : Decimal + collateralCid : ContractId Fungible.I + receivableAccount : AccountKey + observers : Parties + deriving (Eq, Show) + +interface CreateAuctionRequest where + viewtype View + -- ^ Interface view type. + asRemovable : Removable.I + -- ^ Conversion to the `Removable` interface. + +-- | Type constraint for requiring templates to implement `CreateAuctionRequest`. +type Implementation t = (HasToInterface t CreateAuctionRequest, Removable.Implementation t) +class (Implementation t) => HasImplementation t +instance HasImplementation CreateAuctionRequest +instance HasToInterface CreateAuctionRequest Removable.I where _toInterface = asRemovable diff --git a/src/daml/Daml/Finance/App/Interface/Distribution/Auction/Service.daml b/src/daml/Daml/Finance/App/Interface/Distribution/Auction/Service.daml new file mode 100644 index 00000000..c1ec6d9c --- /dev/null +++ b/src/daml/Daml/Finance/App/Interface/Distribution/Auction/Service.daml @@ -0,0 +1,68 @@ +-- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +-- SPDX-License-Identifier: Apache-2.0 + +module Daml.Finance.App.Interface.Distribution.Auction.Service where + +import Daml.Finance.App.Interface.Base.Service qualified as Base (I, Implementation) +import Daml.Finance.App.Interface.Distribution.Auction.Auction qualified as Auction (I) +import Daml.Finance.App.Interface.Distribution.Auction.CreateAuctionRequest qualified as CreateAuctionRequest (I) +import Daml.Finance.App.Interface.Distribution.Bidding.Bid qualified as Bid (I) +import Daml.Finance.Interface.Holding.Fungible qualified as Fungible (I) +import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (K, Q) +import Daml.Finance.Interface.Settlement.Factory qualified as SettlementFactory (I) +import Daml.Finance.Interface.Types.Common (AccountKey, Id, Parties) + +type I = Service + +type V = View + +data View = View {} + deriving (Eq, Show) + +interface Service where + viewtype V + + asBase : Base.I + -- ^ Conversion to base `Service` interface. + requestCreateAuction : RequestCreateAuction -> Update (ContractId CreateAuctionRequest.I) + -- ^ Implementation of the `RequestCreateAuction` choice. + createAuction : CreateAuction -> Update (ContractId Auction.I) + -- ^ Implementation of the `CreateAuction` choice. + processAuction : ProcessAuction -> Update (ContractId Auction.I) + -- ^ Implementation of the `ProcessAuction` choice. + + nonconsuming choice RequestCreateAuction : ContractId CreateAuctionRequest.I + with + auctionId : Id + description : Text + quantity : Instrument.Q + currency : Instrument.K + floor : Decimal + collateralCid : ContractId Fungible.I + receivableAccount : AccountKey + observers : Parties + controller (view $ asBase this).customer + do + requestCreateAuction this arg + + nonconsuming choice CreateAuction : ContractId Auction.I + with + createAuctionRequestCid : ContractId CreateAuctionRequest.I + controller (view $ asBase this).provider + do + createAuction this arg + + nonconsuming choice ProcessAuction : ContractId Auction.I + with + settlementFactoryCid : ContractId SettlementFactory.I + auctionCid : ContractId Auction.I + bidCids : [ContractId Bid.I] + controller (view $ asBase this).provider + do + processAuction this arg + +-- | Type constraint for requiring templates to implement `Service`. +type Implementation t = (HasToInterface t Service, Base.Implementation t) +class (Implementation t) => HasImplementation t +instance HasImplementation Service +instance HasToInterface Service Base.I where _toInterface = asBase diff --git a/src/daml/Daml/Finance/App/Interface/Distribution/Bidding/Auto.daml b/src/daml/Daml/Finance/App/Interface/Distribution/Bidding/Auto.daml new file mode 100644 index 00000000..3152cf34 --- /dev/null +++ b/src/daml/Daml/Finance/App/Interface/Distribution/Bidding/Auto.daml @@ -0,0 +1,44 @@ +-- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +-- SPDX-License-Identifier: Apache-2.0 + +module Daml.Finance.App.Interface.Distribution.Bidding.Auto where + +import Daml.Finance.App.Interface.Base.Service qualified as Base (I) +import Daml.Finance.App.Interface.Distribution.Auction.Auction qualified as Auction (I) +import Daml.Finance.App.Interface.Distribution.Bidding.Bid qualified as Bid (I) +import Daml.Finance.App.Interface.Distribution.Bidding.Service qualified as Service (I, Implementation, asBase) +import Daml.Finance.Interface.Holding.Fungible qualified as Fungible (I) +import Daml.Finance.Interface.Types.Common (AccountKey) + +type I = Service + +type V = View + +data View = View {} + deriving (Eq, Show) + +interface Service where + viewtype V + + asService : Service.I + -- ^ Conversion to custody `Service` interface. + requestAndCreateBid : ContractId Service.I -> RequestAndCreateBid -> Update (ContractId Bid.I) + -- ^ Implementation of the `RequestAndCreateAuction` choice. + + nonconsuming choice RequestAndCreateBid : (ContractId Bid.I) + with + auctionCid : ContractId Auction.I + amount : Decimal + price : Decimal + collateralCid : ContractId Fungible.I + receivableAccount : AccountKey + controller (view $ Service.asBase $ asService this).customer + do + requestAndCreateBid this (toInterfaceContractId self) arg + +-- | Type constraint for requiring templates to implement `Service`. +type Implementation t = (HasToInterface t Service, Service.Implementation t) +class (Implementation t) => HasImplementation t +instance HasImplementation Service +instance HasToInterface Service Service.I where _toInterface = asService +instance HasToInterface Service Base.I where _toInterface = Service.asBase . asService diff --git a/src/daml/Daml/Finance/App/Interface/Distribution/Bidding/Bid.daml b/src/daml/Daml/Finance/App/Interface/Distribution/Bidding/Bid.daml new file mode 100644 index 00000000..c15b80a2 --- /dev/null +++ b/src/daml/Daml/Finance/App/Interface/Distribution/Bidding/Bid.daml @@ -0,0 +1,100 @@ +-- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +-- SPDX-License-Identifier: Apache-2.0 + +module Daml.Finance.App.Interface.Distribution.Bidding.Bid where + +import Daml.Finance.App.Interface.Common.Removable qualified as Removable (I, Implementation) +import Daml.Finance.Interface.Holding.Fungible qualified as Fungible (I) +import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (Q) +import Daml.Finance.Interface.Settlement.Instruction qualified as Instruction (I) +import Daml.Finance.Interface.Types.Common (AccountKey, Id) + +type I = Bid + +type V = View + +data View = View + with + operator : Party + provider : Party + customer : Party + issuer : Party + auctionId : Id + details : Details + collateralCid : ContractId Fungible.I + receivableAccount : AccountKey + status : Status + deriving (Eq, Show) + +data Details = Details with + quantity : Instrument.Q + price : Instrument.Q + time : Time + deriving (Eq, Show) + +instance Ord Details where + compare x y = (x.price.amount, x.quantity.amount, Down x.time) `compare` (y.price.amount, y.quantity.amount, Down y.time) + +data Allocation = Allocation with + bidCid : ContractId Bid + bid : View + amount : Decimal + deriving (Eq, Show) + +data SettleAllocation = SettleAllocation with + allocation : Allocation + price : Decimal + issuer : Party + deriving (Eq, Show) + +data Status + = Pending + | FullAllocation with + price : Decimal + | PartialAllocation with + price : Decimal + amount : Decimal + | NoAllocation + | Invalid + deriving (Eq, Show) + +interface Bid where + viewtype View + -- ^ Interface view type. + asRemovable : Removable.I + -- ^ Conversion to the `Removable` interface. + updateStatus : UpdateStatus -> Update (ContractId Bid) + -- ^ Implementation of the `UpdateStatus` choice. + approveInstruction : ApproveInstruction -> Update (ContractId Instruction.I) + -- ^ Implementation of the `ApproveInstruction` choice. + allocateInstruction : AllocateInstruction -> Update (ContractId Instruction.I) + -- ^ Implementation of the `AllocateInstruction` choice. + + choice UpdateStatus : ContractId Bid + with + newStatus : Status + controller (view this).provider + do + updateStatus this arg + + nonconsuming choice ApproveInstruction : ContractId Instruction.I + with + instructionCid : ContractId Instruction.I + account : AccountKey + controller (view this).provider + do + approveInstruction this arg + + nonconsuming choice AllocateInstruction : ContractId Instruction.I + with + instructionCid : ContractId Instruction.I + holdingCid : ContractId Fungible.I + controller (view this).provider + do + allocateInstruction this arg + +-- | Type constraint for requiring templates to implement `Bid`. +type Implementation t = (HasToInterface t Bid, Removable.Implementation t) +class (Implementation t) => HasImplementation t +instance HasImplementation Bid +instance HasToInterface Bid Removable.I where _toInterface = asRemovable diff --git a/src/daml/Daml/Finance/App/Interface/Distribution/Bidding/CreateBidRequest.daml b/src/daml/Daml/Finance/App/Interface/Distribution/Bidding/CreateBidRequest.daml new file mode 100644 index 00000000..969600d4 --- /dev/null +++ b/src/daml/Daml/Finance/App/Interface/Distribution/Bidding/CreateBidRequest.daml @@ -0,0 +1,38 @@ +-- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +-- SPDX-License-Identifier: Apache-2.0 + +module Daml.Finance.App.Interface.Distribution.Bidding.CreateBidRequest where + +import Daml.Finance.App.Interface.Common.Removable qualified as Removable (I, Implementation) +import Daml.Finance.Interface.Holding.Fungible qualified as Fungible (I) +import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (Q) +import Daml.Finance.Interface.Types.Common (AccountKey, Id) + +type I = CreateBidRequest + +type V = View + +data View = View + with + operator : Party + provider : Party + customer : Party + issuer : Party + auctionId : Id + quantity : Instrument.Q + price : Instrument.Q + collateralCid : ContractId Fungible.I + receivableAccount : AccountKey + deriving (Eq, Show) + +interface CreateBidRequest where + viewtype View + -- ^ Interface view type. + asRemovable : Removable.I + -- ^ Conversion to the `Removable` interface. + +-- | Type constraint for requiring templates to implement `CreateBidRequest`. +type Implementation t = (HasToInterface t CreateBidRequest, Removable.Implementation t) +class (Implementation t) => HasImplementation t +instance HasImplementation CreateBidRequest +instance HasToInterface CreateBidRequest Removable.I where _toInterface = asRemovable diff --git a/src/daml/Daml/Finance/App/Interface/Distribution/Bidding/Service.daml b/src/daml/Daml/Finance/App/Interface/Distribution/Bidding/Service.daml new file mode 100644 index 00000000..9d5d3dd6 --- /dev/null +++ b/src/daml/Daml/Finance/App/Interface/Distribution/Bidding/Service.daml @@ -0,0 +1,73 @@ +-- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +-- SPDX-License-Identifier: Apache-2.0 + +module Daml.Finance.App.Interface.Distribution.Bidding.Service where + +import Daml.Finance.App.Interface.Base.Service qualified as Base (I, Implementation) +import Daml.Finance.App.Interface.Distribution.Auction.Auction qualified as Auction (I) +import Daml.Finance.App.Interface.Distribution.Bidding.CreateBidRequest qualified as CreateBidRequest (I) +import Daml.Finance.App.Interface.Distribution.Bidding.Bid qualified as Bid (I, Status) +import Daml.Finance.Interface.Holding.Fungible qualified as Fungible (I) +import Daml.Finance.Interface.Types.Common (AccountKey) + +type I = Service + +type V = View + +data View = View {} + deriving (Eq, Show) + +interface Service where + viewtype V + + asBase : Base.I + -- ^ Conversion to base `Service` interface. + requestCreateBid : RequestCreateBid -> Update (ContractId CreateBidRequest.I) + -- ^ Implementation of the `RequestCreateBid` choice. + createBid : CreateBid -> Update (ContractId Bid.I) + -- ^ Implementation of the `CreateBid` choice. + processAllocation : ProcessAllocation -> Update (ContractId Bid.I, ContractId Fungible.I) + -- ^ Implementation of the `ProcessAllocation` choice. + rejectBid : RejectBid -> Update (ContractId Bid.I, ContractId Fungible.I) + -- ^ Implementation of the `RejectBid` choice. + + nonconsuming choice RequestCreateBid : ContractId CreateBidRequest.I + with + auctionCid : ContractId Auction.I + amount : Decimal + price : Decimal + collateralCid : ContractId Fungible.I + receivableAccount : AccountKey + controller (view $ asBase this).customer + do + requestCreateBid this arg + + nonconsuming choice CreateBid : ContractId Bid.I + with + createBidRequestCid : ContractId CreateBidRequest.I + controller (view $ asBase this).provider + do + createBid this arg + + nonconsuming choice ProcessAllocation : (ContractId Bid.I, ContractId Fungible.I) + with + bidCid : ContractId Bid.I + amount : Decimal + price : Decimal + controller (view $ asBase this).provider + do + processAllocation this arg + + nonconsuming choice RejectBid : (ContractId Bid.I, ContractId Fungible.I) + with + bidCid : ContractId Bid.I + newStatus : Bid.Status + controller (view $ asBase this).provider + do + rejectBid this arg + +-- | Type constraint for requiring templates to implement `Service`. +type Implementation t = (HasToInterface t Service, Base.Implementation t) +class (Implementation t) => HasImplementation t +instance HasImplementation Service +instance HasToInterface Service Base.I where _toInterface = asBase diff --git a/src/daml/Daml/Finance/App/Interface/Issuance/DeissueRequest.daml b/src/daml/Daml/Finance/App/Interface/Issuance/DeissueRequest.daml index 5282a91e..e132e42c 100644 --- a/src/daml/Daml/Finance/App/Interface/Issuance/DeissueRequest.daml +++ b/src/daml/Daml/Finance/App/Interface/Issuance/DeissueRequest.daml @@ -22,7 +22,7 @@ data View = View interface DeissueRequest where viewtype View - -- ^ Interface view types. + -- ^ Interface view type. asRemovable : Removable.I -- ^ Conversion to the `Removable` interface. diff --git a/src/daml/Daml/Finance/App/Interface/Issuance/Issuance.daml b/src/daml/Daml/Finance/App/Interface/Issuance/Issuance.daml index 1610e95a..897389e7 100644 --- a/src/daml/Daml/Finance/App/Interface/Issuance/Issuance.daml +++ b/src/daml/Daml/Finance/App/Interface/Issuance/Issuance.daml @@ -23,7 +23,7 @@ data View = View interface Issuance where viewtype View - -- ^ Interface view types. + -- ^ Interface view type. asRemovable : Removable.I -- ^ Conversion to the `Removable` interface. diff --git a/src/daml/Daml/Finance/App/Interface/Issuance/IssueRequest.daml b/src/daml/Daml/Finance/App/Interface/Issuance/IssueRequest.daml index eb5ee673..84205959 100644 --- a/src/daml/Daml/Finance/App/Interface/Issuance/IssueRequest.daml +++ b/src/daml/Daml/Finance/App/Interface/Issuance/IssueRequest.daml @@ -24,7 +24,7 @@ data View = View interface IssueRequest where viewtype View - -- ^ Interface view types. + -- ^ Interface view type. asRemovable : Removable.I -- ^ Conversion to the `Removable` interface. diff --git a/src/daml/Daml/Finance/App/Interface/Listing/DelistingRequest.daml b/src/daml/Daml/Finance/App/Interface/Listing/DelistingRequest.daml index ee43cfa1..681923a7 100644 --- a/src/daml/Daml/Finance/App/Interface/Listing/DelistingRequest.daml +++ b/src/daml/Daml/Finance/App/Interface/Listing/DelistingRequest.daml @@ -20,7 +20,7 @@ data View = View interface DelistingRequest where viewtype View - -- ^ Interface view types. + -- ^ Interface view type. asRemovable : Removable.I -- ^ Conversion to the `Removable` interface. diff --git a/src/daml/Daml/Finance/App/Interface/Listing/Listing.daml b/src/daml/Daml/Finance/App/Interface/Listing/Listing.daml index ff496350..5a3e4386 100644 --- a/src/daml/Daml/Finance/App/Interface/Listing/Listing.daml +++ b/src/daml/Daml/Finance/App/Interface/Listing/Listing.daml @@ -25,7 +25,7 @@ data View = View interface Listing where viewtype View - -- ^ Interface view types. + -- ^ Interface view type. asRemovable : Removable.I -- ^ Conversion to the `Removable` interface. diff --git a/src/daml/Daml/Finance/App/Interface/Listing/ListingRequest.daml b/src/daml/Daml/Finance/App/Interface/Listing/ListingRequest.daml index 94a99dff..966df9cd 100644 --- a/src/daml/Daml/Finance/App/Interface/Listing/ListingRequest.daml +++ b/src/daml/Daml/Finance/App/Interface/Listing/ListingRequest.daml @@ -25,7 +25,7 @@ data View = View interface ListingRequest where viewtype View - -- ^ Interface view types. + -- ^ Interface view type. asRemovable : Removable.I -- ^ Conversion to the `Removable` interface. diff --git a/src/daml/Daml/Finance/App/Role/Distributor.daml b/src/daml/Daml/Finance/App/Role/Distributor.daml index 24b98c2d..213e2ea6 100644 --- a/src/daml/Daml/Finance/App/Role/Distributor.daml +++ b/src/daml/Daml/Finance/App/Role/Distributor.daml @@ -3,13 +3,14 @@ module Daml.Finance.App.Role.Distributor where -import Daml.Finance.App.Distribution.Auction.Auto.Service qualified as AuctionAuto (Approve(..), Offer(..), Request, Service, Terminate(..)) -import Daml.Finance.App.Distribution.Auction.Service qualified as Auction (Approve(..), Offer(..), Request, Service, Terminate(..)) -import Daml.Finance.App.Distribution.Bidding.Auto.Service qualified as BiddingAuto (Approve(..), Offer(..), Request, Service, Terminate(..)) -import Daml.Finance.App.Distribution.Bidding.Service qualified as Bidding (Approve(..), Offer(..), Request, Service, Terminate(..)) +import Daml.Finance.App.Distribution.Auction.Auto qualified as AuctionAuto (Approve(..), Offer(..), Request, Service) +import Daml.Finance.App.Distribution.Auction.Service qualified as Auction (Approve(..), Offer(..), Request, Service) +import Daml.Finance.App.Distribution.Bidding.Auto qualified as BiddingAuto (Approve(..), Offer(..), Request, Service) +import Daml.Finance.App.Distribution.Bidding.Service qualified as Bidding (Approve(..), Offer(..), Request, Service) import Daml.Finance.App.Distribution.Fund.Service qualified as Fund (Approve(..), Offer(..), Request, Service, Terminate(..)) import Daml.Finance.App.Distribution.Investment.Service qualified as Investment (Approve(..), Offer(..), Request, Service, Terminate(..)) import Daml.Finance.App.Distribution.Subscription.Service qualified as Subscription (Approve(..), Offer(..), Request, Service, Terminate(..)) +import Daml.Finance.App.Interface.Base.Service qualified as Base (I, Terminate(..)) template Role with @@ -40,7 +41,8 @@ template Role customer : Party controller provider do - exerciseByKey @Auction.Service (operator, provider, customer) Auction.Terminate with actor = provider + (serviceCid, _) <- fetchByKey @Auction.Service (operator, provider, customer) + exercise (toInterfaceContractId @Base.I serviceCid) Base.Terminate with actor = provider nonconsuming choice OfferAuctionAutoService : ContractId AuctionAuto.Offer with @@ -61,7 +63,8 @@ template Role customer : Party controller provider do - exerciseByKey @AuctionAuto.Service (operator, provider, customer) AuctionAuto.Terminate with actor = provider + (serviceCid, _) <- fetchByKey @AuctionAuto.Service (operator, provider, customer) + exercise (toInterfaceContractId @Base.I serviceCid) Base.Terminate with actor = provider nonconsuming choice OfferBiddingService : ContractId Bidding.Offer with @@ -82,7 +85,8 @@ template Role customer : Party controller provider do - exerciseByKey @Bidding.Service (operator, provider, customer) Bidding.Terminate with actor = provider + (serviceCid, _) <- fetchByKey @Bidding.Service (operator, provider, customer) + exercise (toInterfaceContractId @Base.I serviceCid) Base.Terminate with actor = provider nonconsuming choice OfferBiddingAutoService : ContractId BiddingAuto.Offer with @@ -103,7 +107,8 @@ template Role customer : Party controller provider do - exerciseByKey @BiddingAuto.Service (operator, provider, customer) BiddingAuto.Terminate with actor = provider + (serviceCid, _) <- fetchByKey @BiddingAuto.Service (operator, provider, customer) + exercise (toInterfaceContractId @Base.I serviceCid) Base.Terminate with actor = provider nonconsuming choice OfferSubscriptionService : ContractId Subscription.Offer with diff --git a/src/daml/Daml/Finance/Setup/Scenario/Default.daml b/src/daml/Daml/Finance/Setup/Scenario/Default.daml index 5ada4fdc..f69939f4 100644 --- a/src/daml/Daml/Finance/Setup/Scenario/Default.daml +++ b/src/daml/Daml/Finance/Setup/Scenario/Default.daml @@ -71,13 +71,9 @@ run = do createTradingAutoService operator exchange inv2 createTradingService operator exchange inv3 settlementFactoryCid createTradingAutoService operator exchange inv3 - createAuctionService operator agent issuer createAuctionAutoService operator agent issuer - createBiddingService operator agent inv1 createBiddingAutoService operator agent inv1 - createBiddingService operator agent inv2 createBiddingAutoService operator agent inv2 - createBiddingService operator agent inv3 createBiddingAutoService operator agent inv3 -- Accounts @@ -142,7 +138,7 @@ run = do let doAuction = do let quantity = Instrument.qty 1_000_000.0 bnd - auctionCid <- createAuction operator agent issuer public "AUCTION1" quantity usd 0.95 (coerceContractId ad2) issuerCashAccount + auctionCid <- createAuction operator agent issuer public (Id "AUCTION1") "AUCTION1" quantity usd 0.95 (coerceContractId ad2) issuerCashAccount inv1CollateralCid <- coerceContractId <$> getHolding inv1 (Instrument.qty 500_000.0 usd) inv2CollateralCid <- coerceContractId <$> getHolding inv2 (Instrument.qty 392_000.0 usd) inv3CollateralCid <- coerceContractId <$> getHolding inv3 (Instrument.qty 297_000.0 usd) diff --git a/src/daml/Daml/Finance/Setup/Util/Service.daml b/src/daml/Daml/Finance/Setup/Util/Service.daml index 81942c84..10ef71d6 100644 --- a/src/daml/Daml/Finance/Setup/Util/Service.daml +++ b/src/daml/Daml/Finance/Setup/Util/Service.daml @@ -11,6 +11,10 @@ import Daml.Finance.App.Decentralized.Exchange.Model qualified as DecentralizedE import Daml.Finance.App.Decentralized.Exchange.Service qualified as DecentralizedExchange (Service(..)) import Daml.Finance.App.Interface.Custody.Auto qualified as CustodyAuto (I) import Daml.Finance.App.Interface.Custody.Service qualified as Custody (I) +import Daml.Finance.App.Interface.Distribution.Auction.Auto qualified as AuctionAuto (I) +import Daml.Finance.App.Interface.Distribution.Auction.Service qualified as Auction (I) +import Daml.Finance.App.Interface.Distribution.Bidding.Auto qualified as BiddingAuto (I) +import Daml.Finance.App.Interface.Distribution.Bidding.Service qualified as Bidding (I) import Daml.Finance.App.Interface.Issuance.Auto qualified as IssuanceAuto (I) import Daml.Finance.App.Interface.Issuance.Service qualified as Issuance (I) import Daml.Finance.App.Interface.Listing.Auto qualified as ListingAuto (I) @@ -24,10 +28,10 @@ import Daml.Finance.App.Lifecycle.Service qualified as Lifecycle (Accept(..), Se import Daml.Finance.App.Trading.Auto.Service qualified as TradingAuto (Accept(..), Service) import Daml.Finance.App.Trading.Service qualified as Trading (Accept(..), Service) import Daml.Finance.App.Lending.Service qualified as Lending (Accept(..), Service) -import Daml.Finance.App.Distribution.Auction.Auto.Service qualified as AuctionAuto (Accept(..), Service) -import Daml.Finance.App.Distribution.Auction.Service qualified as Auction (Accept(..), Service) -import Daml.Finance.App.Distribution.Bidding.Auto.Service qualified as BiddingAuto (Accept(..), Service) -import Daml.Finance.App.Distribution.Bidding.Service qualified as Bidding (Accept(..), Service) +import Daml.Finance.App.Distribution.Auction.Auto qualified as AuctionAuto (Accept(..)) +import Daml.Finance.App.Distribution.Auction.Service qualified as Auction (Accept(..)) +import Daml.Finance.App.Distribution.Bidding.Auto qualified as BiddingAuto (Accept(..)) +import Daml.Finance.App.Distribution.Bidding.Service qualified as Bidding (Accept(..)) import Daml.Finance.App.Distribution.Fund.Service qualified as Fund (Accept(..), Service) import Daml.Finance.App.Distribution.Investment.Service qualified as Investment (Accept(..), Service) import Daml.Finance.App.Distribution.Subscription.Service qualified as Subscription (Accept(..), Service) @@ -131,25 +135,25 @@ createListingAutoService operator exchange customer = do offerCid <- submit exchange do exerciseByKeyCmd @Exchange.Role (operator, exchange) Exchange.OfferListingAutoService with .. toInterfaceContractId <$> submit customer do exerciseCmd offerCid ListingAuto.Accept -createAuctionService : Party -> Party -> Party -> Script (ContractId Auction.Service) +createAuctionService : Party -> Party -> Party -> Script (ContractId Auction.I) createAuctionService operator distributor customer = do offerCid <- submit distributor do exerciseByKeyCmd @Distributor.Role (operator, distributor) Distributor.OfferAuctionService with customer - submit customer do exerciseCmd offerCid Auction.Accept + toInterfaceContractId <$> submit customer do exerciseCmd offerCid Auction.Accept -createAuctionAutoService : Party -> Party -> Party -> Script (ContractId AuctionAuto.Service) +createAuctionAutoService : Party -> Party -> Party -> Script (ContractId AuctionAuto.I) createAuctionAutoService operator distributor customer = do offerCid <- submit distributor do exerciseByKeyCmd @Distributor.Role (operator, distributor) Distributor.OfferAuctionAutoService with customer - submit customer do exerciseCmd offerCid AuctionAuto.Accept + toInterfaceContractId <$> submit customer do exerciseCmd offerCid AuctionAuto.Accept -createBiddingService : Party -> Party -> Party -> Script (ContractId Bidding.Service) +createBiddingService : Party -> Party -> Party -> Script (ContractId Bidding.I) createBiddingService operator distributor customer = do offerCid <- submit distributor do exerciseByKeyCmd @Distributor.Role (operator, distributor) Distributor.OfferBiddingService with .. - submit customer do exerciseCmd offerCid Bidding.Accept + toInterfaceContractId <$> submit customer do exerciseCmd offerCid Bidding.Accept -createBiddingAutoService : Party -> Party -> Party -> Script (ContractId BiddingAuto.Service) +createBiddingAutoService : Party -> Party -> Party -> Script (ContractId BiddingAuto.I) createBiddingAutoService operator distributor customer = do offerCid <- submit distributor do exerciseByKeyCmd @Distributor.Role (operator, distributor) Distributor.OfferBiddingAutoService with .. - submit customer do exerciseCmd offerCid BiddingAuto.Accept + toInterfaceContractId <$> submit customer do exerciseCmd offerCid BiddingAuto.Accept createSubscriptionService : Party -> Party -> Party -> Party -> Script (ContractId Subscription.Service) createSubscriptionService operator distributor customer public = do diff --git a/src/daml/Daml/Finance/Setup/Util/Workflow.daml b/src/daml/Daml/Finance/Setup/Util/Workflow.daml index 9b07cb54..cd249c40 100644 --- a/src/daml/Daml/Finance/Setup/Util/Workflow.daml +++ b/src/daml/Daml/Finance/Setup/Util/Workflow.daml @@ -10,15 +10,21 @@ import DA.Set (fromList, singleton) import DA.Text (parseInt) import Daml.Finance.App.Custody.Service qualified as Custody (Service) import Daml.Finance.App.Data.AccountDirectory (AccountDirectory(..)) -import Daml.Finance.App.Distribution.Auction.Model qualified as Auction (T) -import Daml.Finance.App.Distribution.Auction.Service qualified as Auction (CreateAuction(..), ProcessAuction(..), RequestCreateAuction(..), S) -import Daml.Finance.App.Distribution.Bidding.Model qualified as Bidding (Bid) -import Daml.Finance.App.Distribution.Bidding.Service qualified as Bidding (CreateBid(..), RequestCreateBid(..), S) +import Daml.Finance.App.Distribution.Auction.Auto qualified as AuctionAuto (Service) +import Daml.Finance.App.Distribution.Auction.Service qualified as Auction (Service) +import Daml.Finance.App.Distribution.Bidding.Auto qualified as BiddingAuto (Service) +import Daml.Finance.App.Distribution.Bidding.Service qualified as Bidding (Service) import Daml.Finance.App.Distribution.Fund.Model qualified as Fund (PooledInvestmentRequest, T) import Daml.Finance.App.Distribution.Fund.Service qualified as Fund (FulfillPooledInvestmentRequest(..), PoolInvestmentRequests(..), S) import Daml.Finance.App.Distribution.Investment.Model qualified as Investment (InvestmentRequest) import Daml.Finance.App.Distribution.Investment.Service qualified as Investment (RequestInvestment(..), S) import Daml.Finance.App.Interface.Custody.Service qualified as Custody (Deposit(..), I, OpenAccount(..), RequestDeposit(..), RequestOpenAccount(..)) +import Daml.Finance.App.Interface.Distribution.Auction.Auction qualified as Auction (I) +import Daml.Finance.App.Interface.Distribution.Auction.Auto qualified as AuctionAutoService (I, RequestAndCreateAuction(..)) +import Daml.Finance.App.Interface.Distribution.Auction.Service qualified as AuctionService (CreateAuction(..), I, ProcessAuction(..), RequestCreateAuction(..)) +import Daml.Finance.App.Interface.Distribution.Bidding.Bid qualified as Bid (I) +import Daml.Finance.App.Interface.Distribution.Bidding.Auto qualified as BiddingAutoService (I, RequestAndCreateBid(..)) +import Daml.Finance.App.Interface.Distribution.Bidding.Service qualified as BiddingService (CreateBid(..), I, RequestCreateBid(..)) import Daml.Finance.App.Interface.Issuance.Issuance qualified as Issuance (I) import Daml.Finance.App.Interface.Issuance.Service qualified as IssuanceService (I, Issue(..), RequestIssue(..)) import Daml.Finance.App.Interface.Listing.Listing qualified as Listing (I) @@ -62,7 +68,7 @@ import Daml.Finance.Interface.Types.Date.RollConvention (PeriodEnum, RollConvent import Daml.Finance.Interface.Types.Date.Schedule (Frequency(..), PeriodicSchedule(..)) import Daml.Finance.Lifecycle.Event.DateClock qualified as DateClock (Event(..)) import Daml.Finance.Lifecycle.Types (Unit(..)) -import Daml.Finance.Settlement.Factory qualified as Settlement (Factory) +import Daml.Finance.Settlement.Factory qualified as Settlement (FactoryWithIntermediaries) import Daml.Finance.Settlement.Instruction qualified as Instruction (T) import Daml.Finance.Setup.Util.Common (getHolding) import Daml.Script @@ -231,25 +237,42 @@ createBidOrder operator provider customer public id = createOrder operator provi createAskOrder : Party -> Party -> Party -> Party -> Id -> Instrument.Q -> Instrument.Q -> Parties -> Script (Optional (ContractId Trading.Order, Trading.Order)) createAskOrder operator provider customer public id = createOrder operator provider customer public id Trading.Sell -createAuction : Party -> Party -> Party -> Party -> Text -> Instrument.Q -> Instrument.K -> Decimal -> ContractId Fungible.I -> Account.K -> Script (ContractId Auction.T) -createAuction operator provider customer public id quantity currency floor collateralCid receivableAccount = do - createAuctionRequestCid <- submit customer do exerciseByKeyCmd @Auction.S (operator, provider, customer) Auction.RequestCreateAuction with id; quantity; currency; floor; collateralCid; receivableAccount; observers = singleton public - submit provider do exerciseByKeyCmd @Auction.S (operator, provider, customer) Auction.CreateAuction with createAuctionRequestCid - -createAuctionBid : Party -> Party -> Party -> Party -> ContractId Auction.T -> Decimal -> Decimal -> ContractId Fungible.I -> Account.K -> Script (ContractId Bidding.Bid) +createAuction : Party -> Party -> Party -> Party -> Id -> Text -> Instrument.Q -> Instrument.K -> Decimal -> ContractId Fungible.I -> AccountKey -> Script (ContractId Auction.I) +createAuction operator provider customer public auctionId description quantity currency floor collateralCid receivableAccount = do + autoOpt <- queryContractKey @AuctionAuto.Service customer (operator, provider, customer) + serviceOpt <- queryContractKey @Auction.Service customer (operator, provider, customer) + case (autoOpt, serviceOpt) of + (Some (serviceCid, _), _) -> do + submit customer do exerciseCmd (toInterfaceContractId @AuctionAutoService.I serviceCid) AuctionAutoService.RequestAndCreateAuction with auctionId; description; quantity; currency; floor; collateralCid; receivableAccount; observers = singleton public + (_, Some (serviceCid, _)) -> do + createAuctionRequestCid <- submit customer do exerciseCmd (toInterfaceContractId @AuctionService.I serviceCid) AuctionService.RequestCreateAuction with auctionId; description; quantity; currency; floor; collateralCid; receivableAccount; observers = singleton public + submit provider do exerciseCmd (toInterfaceContractId @AuctionService.I serviceCid) AuctionService.CreateAuction with createAuctionRequestCid + _ -> fail "No auction service found" + +createAuctionBid : Party -> Party -> Party -> Party -> ContractId Auction.I -> Decimal -> Decimal -> ContractId Fungible.I -> AccountKey -> Script (ContractId Bid.I) createAuctionBid operator provider customer public auctionCid amount price collateralCid receivableAccount = do - createBidRequestCid <- submitMulti [customer] [public] do exerciseByKeyCmd @Bidding.S (operator, provider, customer) Bidding.RequestCreateBid with auctionCid; amount; price; collateralCid; receivableAccount - submit provider do exerciseByKeyCmd @Bidding.S (operator, provider, customer) Bidding.CreateBid with createBidRequestCid - -processAuction : Party -> Party -> Party -> Party -> ContractId Auction.T -> [ContractId Bidding.Bid] -> Script (ContractId Auction.T) + autoOpt <- queryContractKey @BiddingAuto.Service customer (operator, provider, customer) + serviceOpt <- queryContractKey @Bidding.Service customer (operator, provider, customer) + case (autoOpt, serviceOpt) of + (Some (serviceCid, _), _) -> do + submitMulti [customer] [public] do exerciseCmd (toInterfaceContractId @BiddingAutoService.I serviceCid) BiddingAutoService.RequestAndCreateBid with auctionCid; amount; price; collateralCid; receivableAccount + (_, Some (serviceCid, _)) -> do + createBidRequestCid <- submitMulti [customer] [public] do exerciseCmd (toInterfaceContractId @BiddingService.I serviceCid) BiddingService.RequestCreateBid with auctionCid; amount; price; collateralCid; receivableAccount + submit provider do exerciseCmd (toInterfaceContractId @BiddingService.I serviceCid) BiddingService.CreateBid with createBidRequestCid + _ -> fail "No auction service found" + + +processAuction : Party -> Party -> Party -> Party -> ContractId Auction.I -> [ContractId Bid.I] -> Script (ContractId Auction.I) processAuction operator provider customer public auctionCid bidCids = do - [(factoryCid, _)] <- query @Settlement.Factory provider - submitMulti [provider] [public] do - exerciseByKeyCmd @Auction.S (operator, provider, customer) Auction.ProcessAuction - with - settlementFactoryCid = toInterfaceContractId factoryCid - auctionCid - bidCids + [(factoryCid, _)] <- query @Settlement.FactoryWithIntermediaries public + autoOpt <- queryContractKey @AuctionAuto.Service provider (operator, provider, customer) + serviceOpt <- queryContractKey @Auction.Service provider (operator, provider, customer) + case (autoOpt, serviceOpt) of + (Some (serviceCid, _), _) -> do + submitMulti [provider] [public] do exerciseCmd (toInterfaceContractId @AuctionService.I serviceCid) AuctionService.ProcessAuction with settlementFactoryCid = toInterfaceContractId factoryCid; auctionCid; bidCids + (_, Some (serviceCid, _)) -> do + submitMulti [provider] [public] do exerciseCmd (toInterfaceContractId @AuctionService.I serviceCid) AuctionService.ProcessAuction with settlementFactoryCid = toInterfaceContractId factoryCid; auctionCid; bidCids + _ -> fail "No auction service found" declareDividend : Party -> Party -> Party -> Party -> Instrument.K -> Date -> [Instrument.Q] -> Script (ContractId Effect.I) declareDividend operator provider issuer public equity effectiveDate perUnitDistribution = do diff --git a/ui/src/apps/Distribution.tsx b/ui/src/apps/Distribution.tsx index d83e86f7..1760533f 100644 --- a/ui/src/apps/Distribution.tsx +++ b/ui/src/apps/Distribution.tsx @@ -26,8 +26,8 @@ export const Distribution : React.FC = () => { const { loading: l1, auction, fund, investment, subscription } = useServices(); if (l1) return ; - const providerAuctionService = auction.find(c => c.payload.provider === party); - const customerAuctionService = auction.find(c => c.payload.customer === party); + const providerAuctionService = auction.services.find(c => c.payload.provider === party); + const customerAuctionService = auction.services.find(c => c.payload.customer === party); const providerSubscriptionService = subscription.find(c => c.payload.provider === party); const customerSubscriptionService = subscription.find(c => c.payload.customer === party); const providerInvestmentService = investment.find(c => c.payload.provider === party); diff --git a/ui/src/components/Instrument/Aggregate.tsx b/ui/src/components/Instrument/Aggregate.tsx index 438be9aa..f8dbccdc 100644 --- a/ui/src/components/Instrument/Aggregate.tsx +++ b/ui/src/components/Instrument/Aggregate.tsx @@ -37,7 +37,7 @@ export const Aggregate : React.FC = ({ instrument }) => { setNode(claimToNode(claims)); } } - setClaims(); + if (lifecycle.length > 0) setClaims(); }, [lifecycle, instrument, observables, l1, l2, ledger]); if (l1 || l2) return diff --git a/ui/src/context/ServicesContext.tsx b/ui/src/context/ServicesContext.tsx index a46fa538..9479181f 100644 --- a/ui/src/context/ServicesContext.tsx +++ b/ui/src/context/ServicesContext.tsx @@ -9,10 +9,10 @@ import { Service as BackToBackService } from "@daml.js/daml-finance-app/lib/Daml import { Service as CustodyService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Interface/Custody/Service" import { Service as CustodyAutoService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Interface/Custody/Auto" import { Service as DecentralizedExchangeService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Decentralized/Exchange/Service" -import { Service as AuctionService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Distribution/Auction/Service" -import { Service as AuctionAutoService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Distribution/Auction/Auto/Service" -import { Service as BiddingService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Distribution/Bidding/Service" -import { Service as BiddingAutoService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Distribution/Bidding/Auto/Service" +import { Service as AuctionService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Interface/Distribution/Auction/Service" +import { Service as AuctionAutoService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Interface/Distribution/Auction/Auto" +import { Service as BiddingService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Interface/Distribution/Bidding/Service" +import { Service as BiddingAutoService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Interface/Distribution/Bidding/Auto" import { Service as SubscriptionService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Distribution/Subscription/Service" import { Service as FundService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Distribution/Fund/Service" import { Service as InvestmentService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Distribution/Investment/Service" @@ -40,13 +40,11 @@ type ServiceAggregate = CreateEvent backToBack : readonly CreateEvent[] + bidding : ServicesAggregate custody : ServicesAggregate decentralizedExchange : readonly CreateEvent[] - auctionAuto : readonly CreateEvent[] - auction : readonly CreateEvent[] - biddingAuto : readonly CreateEvent[] - bidding : readonly CreateEvent[] fund : readonly CreateEvent[] investment : readonly CreateEvent[] issuance : ServicesAggregate @@ -68,13 +66,11 @@ const emptyAggregate = { const empty = { loading: true, + auction: emptyAggregate, backToBack: [], + bidding: emptyAggregate, custody: emptyAggregate, decentralizedExchange: [], - auctionAuto: [], - auction: [], - biddingAuto: [], - bidding: [], fund: [], investment: [], issuance: emptyAggregate, @@ -94,14 +90,14 @@ const ServicesContext = React.createContext(empty); export const ServicesProvider : React.FC = ({ children }) => { const { loading: l1, contracts: base } = useStreamQueries(BaseService); - const { loading: l2, contracts: backToBack } = useStreamQueries(BackToBackService); - const { loading: l3, contracts: custody } = useStreamQueries(CustodyService); - const { loading: l4, contracts: custodyAuto } = useStreamQueries(CustodyAutoService); - const { loading: l5, contracts: decentralizedExchange } = useStreamQueries(DecentralizedExchangeService); - const { loading: l6, contracts: auctionAuto } = useStreamQueries(AuctionAutoService); - const { loading: l7, contracts: auction } = useStreamQueries(AuctionService); - const { loading: l8, contracts: biddingAuto } = useStreamQueries(BiddingAutoService); - const { loading: l9, contracts: bidding } = useStreamQueries(BiddingService); + const { loading: l2, contracts: auctionAuto } = useStreamQueries(AuctionAutoService); + const { loading: l3, contracts: auction } = useStreamQueries(AuctionService); + const { loading: l4, contracts: backToBack } = useStreamQueries(BackToBackService); + const { loading: l5, contracts: biddingAuto } = useStreamQueries(BiddingAutoService); + const { loading: l6, contracts: bidding } = useStreamQueries(BiddingService); + const { loading: l7, contracts: custody } = useStreamQueries(CustodyService); + const { loading: l8, contracts: custodyAuto } = useStreamQueries(CustodyAutoService); + const { loading: l9, contracts: decentralizedExchange } = useStreamQueries(DecentralizedExchangeService); const { loading: l10, contracts: fund } = useStreamQueries(FundService); const { loading: l11, contracts: investment } = useStreamQueries(InvestmentService); const { loading: l12, contracts: issuance } = useStreamQueries(IssuanceService); @@ -137,13 +133,11 @@ export const ServicesProvider : React.FC = ({ children }) => { const value = { loading, + auction : createServicesAggregate(auction, auctionAuto), backToBack, + bidding : createServicesAggregate(bidding, biddingAuto), custody : createServicesAggregate(custody, custodyAuto), decentralizedExchange, - auctionAuto, - auction, - biddingAuto, - bidding, fund, investment, issuance : createServicesAggregate(issuance, issuanceAuto), diff --git a/ui/src/hooks/Network.tsx b/ui/src/hooks/Network.tsx index 607d77f3..a7d34c3e 100644 --- a/ui/src/hooks/Network.tsx +++ b/ui/src/hooks/Network.tsx @@ -32,19 +32,19 @@ export const useNetwork = () : Network => { const scenario = useScenario(); const svc = useServices(); const services : CreateEvent[] = Array.prototype.concat.apply([], [ - svc.auction, + svc.auction.services, svc.backToBack, + svc.bidding.services, svc.custody.services, - svc.bidding, svc.fund, svc.investment, - svc.issuance, + svc.issuance.services, svc.lending, svc.lifecycle, + svc.listing.services, svc.settlement, svc.structuring, svc.subscription, - svc.listing, svc.trading, ]); diff --git a/ui/src/pages/distribution/auction/Auction.tsx b/ui/src/pages/distribution/auction/Auction.tsx index 63c50e79..3bb6b1cc 100644 --- a/ui/src/pages/distribution/auction/Auction.tsx +++ b/ui/src/pages/distribution/auction/Auction.tsx @@ -8,9 +8,9 @@ import { useLedger, useParty, useStreamQueries } from "@daml/react"; import { Typography, Grid, Table, TableBody, TableCell, TableRow, Button, Paper } from "@mui/material"; import { useParams } from "react-router-dom"; import useStyles from "../../styles"; -import { Auction as AuctionContract, Status as AuctionStatus } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Distribution/Auction/Model"; -import { Service } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Distribution/Auction/Service"; -import { Bid } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Distribution/Bidding/Model"; +import { Auction as AuctionI, Status as AuctionStatus } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Interface/Distribution/Auction/Auction"; +import { Service } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Interface/Distribution/Auction/Service"; +import { Bid } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Interface/Distribution/Bidding/Bid"; import { getBidAllocation } from "../Utils"; import { Spinner } from "../../../components/Spinner/Spinner"; import { fmt } from "../../../util"; @@ -28,31 +28,28 @@ export const Auction: React.FC = () => { const party = useParty(); const ledger = useLedger(); - const svc = useServices(); + const { loading: l1, auction: auctionSvc } = useServices(); + const { loading: l2, contracts: auctions } = useStreamQueries(AuctionI); + const { loading: l3, contracts: bids } = useStreamQueries(Bid); + const { loading: l4, contracts: factories } = useStreamQueries(Factory); - const { contracts: auctions, loading: l1 } = useStreamQueries(AuctionContract); - const { contracts: bids, loading: l2 } = useStreamQueries(Bid); - const { contracts: factories, loading: l3 } = useStreamQueries(Factory); - - const services = svc.auction.filter(s => s.payload.customer === party || s.payload.provider === party); const auction = auctions.find(c => c.contractId === contractId); - if (svc.loading || l1 || l2 || l3) return ; + if (l1 || l2 || l3 || l4) return ; if (!contractId) return ; if (!auction) return ; - if (services.length === 0) return ; - const service = services[0]; - const provider = service.payload.provider; - const filteredBids = bids.filter(c => c.payload.auctionId === auction.payload.id); + const filteredBids = bids.filter(c => c.payload.auctionId.unpack === auction.payload.id.unpack); const filledPerc = 100.0 * filteredBids.reduce((a, b) => a + (parseFloat(b.payload.details.price.amount) >= parseFloat(auction.payload.floor) ? parseFloat(b.payload.details.quantity.amount) : 0), 0) / parseFloat(auction.payload.quantity.amount); const currentPrice = filteredBids.length === 0 ? 0.0 : filteredBids.reduce((a, b) => parseFloat(b.payload.details.price.amount) >= parseFloat(auction.payload.floor) && parseFloat(b.payload.details.price.amount) < a ? parseFloat(b.payload.details.price.amount) : a, Number.MAX_VALUE); - const canClose = auction.payload.status.tag !== "Open" || filteredBids.length === 0 || party !== provider; + const canClose = auction.payload.status.tag !== "Open" || filteredBids.length === 0 || party !== auction.payload.provider; const closeAuction = async () => { if (factories.length === 0) return new Error("No settlement factory found"); + const svc = auctionSvc.getService(party, auction.payload.customer); + if (!svc) throw new Error("No auction service found for provider [" + party + "] and customer [" + auction.payload.customer + "]"); const bidCids = filteredBids.map(c => c.contractId); - const [result, ] = await ledger.exercise(Service.ProcessAuction, service.contractId, { settlementFactoryCid: factories[0].contractId, auctionCid: auction.contractId, bidCids }); + const [result, ] = await ledger.exercise(Service.ProcessAuction, svc.service.contractId, { settlementFactoryCid: factories[0].contractId, auctionCid: auction.contractId, bidCids }); navigate("/app/distribution/auctions/" + result); }; @@ -67,7 +64,7 @@ export const Auction: React.FC = () => { } }; - const getParticallyAllocatedUnits = (auction: AuctionContract): number | undefined => { + const getParticallyAllocatedUnits = (auction: AuctionI): number | undefined => { switch (auction.status.tag) { case 'PartiallyAllocated': return parseFloat(auction.quantity.amount) - parseFloat(auction.status.value.remaining) @@ -79,7 +76,7 @@ export const Auction: React.FC = () => { return ( - {auction.payload.id} + {auction.payload.description} @@ -133,7 +130,7 @@ export const Auction: React.FC = () => { Id - {auction.payload.id} + {auction.payload.id.unpack} Asset diff --git a/ui/src/pages/distribution/auction/Auctions.tsx b/ui/src/pages/distribution/auction/Auctions.tsx index 7d31044c..bc8aee9e 100644 --- a/ui/src/pages/distribution/auction/Auctions.tsx +++ b/ui/src/pages/distribution/auction/Auctions.tsx @@ -3,7 +3,7 @@ import React from "react"; import { useParty, useStreamQueries } from "@daml/react"; -import { Auction } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Distribution/Auction/Model"; +import { Auction } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Interface/Distribution/Auction/Auction"; import { Spinner } from "../../../components/Spinner/Spinner"; import { fmt } from "../../../util"; import { useParties } from "../../../context/PartiesContext"; @@ -20,7 +20,7 @@ export const Auctions : React.FC = () => { const createRow = (c : CreateEvent) : any[] => { const path = (party === c.payload.provider || party === c.payload.customer ? "/app/distribution/auctions/" : "/app/distribution/auction/") + c.contractId; return [ - c.payload.id, + c.payload.id.unpack, getName(c.payload.provider), getName(c.payload.customer), fmt(c.payload.quantity.amount) + " " + c.payload.quantity.unit.id.unpack, diff --git a/ui/src/pages/distribution/auction/Bidding.tsx b/ui/src/pages/distribution/auction/Bidding.tsx index 2053c35b..5f9960e7 100644 --- a/ui/src/pages/distribution/auction/Bidding.tsx +++ b/ui/src/pages/distribution/auction/Bidding.tsx @@ -4,13 +4,13 @@ import React, { useState } from "react"; import useStyles from "../../styles"; import classnames from "classnames"; -import { Auction } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Distribution/Auction/Model"; -import { Bid } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Distribution/Bidding/Model"; +import { Auction } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Interface/Distribution/Auction/Auction"; +import { Bid } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Interface/Distribution/Bidding/Bid"; import { useLedger, useParty, useStreamQueries } from "@daml/react"; import { Grid, Paper, Typography, Table, TableRow, TableCell, TableBody, TextField, Button } from "@mui/material"; import { useParams } from "react-router-dom"; -import { Service } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Distribution/Bidding/Service"; -import { Service as AutoService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Distribution/Bidding/Auto/Service"; +import { Service } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Interface/Distribution/Bidding/Service"; +import { Service as ServiceAuto } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Interface/Distribution/Bidding/Auto"; import { getBidAllocation } from "../Utils"; import { Spinner } from "../../../components/Spinner/Spinner"; import { fmt } from "../../../util"; @@ -31,7 +31,7 @@ export const Bidding : React.FC = () => { const { getName } = useParties(); const party = useParty(); const ledger = useLedger(); - const { loading: l1, bidding, biddingAuto } = useServices(); + const { loading: l1, bidding } = useServices(); const { loading: l2, latests } = useInstruments(); const { loading: l3, getFungible } = useHoldings(); const { loading: l4, contracts: auctions } = useStreamQueries(Auction); @@ -44,14 +44,10 @@ export const Bidding : React.FC = () => { if (l1 || l2 || l3 || l4 || l5 || l6) return ; - const myServices = bidding.filter(c => c.payload.customer === party); - const myAutoServices = biddingAuto.filter(c => c.payload.customer === party); - - if (myServices.length === 0) return if (!auction) return if (!instrument) return - const bid = bids.find(b => b.payload.auctionId === auction.payload.id); + const bid = bids.find(b => b.payload.auctionId.unpack === auction.payload.id.unpack); const requestCreateBid = async () => { const volume = price * amount; @@ -59,6 +55,8 @@ export const Bidding : React.FC = () => { const receivableAccount = accounts.find(c => c.payload.accountView.owner === party && c.payload.accountView.custodian === instrument.payload.depository)?.key; const collateralCid = await getFungible(party, volume, auction.payload.currency); if (!receivableAccount) return; + const svc = bidding.getService(auction.payload.provider, party); + if (!svc) throw new Error("No bidding service found for provider [" + auction.payload.provider + "] and customer [" + party + "]"); const arg = { auctionCid: auction.contractId, price: price.toString(), @@ -66,24 +64,20 @@ export const Bidding : React.FC = () => { collateralCid, receivableAccount }; - if (myAutoServices.length > 0) { - await ledger.exercise(AutoService.RequestAndCreateBid, myAutoServices[0].contractId, arg); - } else { - await ledger.exercise(Service.RequestCreateBid, myServices[0].contractId, arg); - } - + if (!!svc.auto) await ledger.exercise(ServiceAuto.RequestAndCreateBid, svc.auto.contractId, arg); + else await ledger.exercise(Service.RequestCreateBid, svc.service.contractId, arg); }; return ( - {auction.payload.id} + {auction.payload.description} - + Auction Details @@ -98,7 +92,7 @@ export const Bidding : React.FC = () => { Auction Id - {auction.payload.id} + {auction.payload.id.unpack} Instrument @@ -116,7 +110,7 @@ export const Bidding : React.FC = () => {
- + {!!bid && Bid diff --git a/ui/src/pages/distribution/auction/New.tsx b/ui/src/pages/distribution/auction/New.tsx index fb52774e..c531702b 100644 --- a/ui/src/pages/distribution/auction/New.tsx +++ b/ui/src/pages/distribution/auction/New.tsx @@ -3,9 +3,10 @@ import React, { useState } from "react"; import { useNavigate } from "react-router-dom"; +import { v4 as uuidv4 } from "uuid"; import classnames from "classnames"; import { useLedger, useParty, useStreamQueries } from "@daml/react"; -import { Typography, Grid, Paper, Select, MenuItem, TextField, Button, MenuProps, FormControl, InputLabel } from "@mui/material"; +import { Button } from "@mui/material"; import useStyles from "../../styles"; import { Spinner } from "../../../components/Spinner/Spinner"; import { Reference } from "@daml.js/daml-finance-interface-account/lib/Daml/Finance/Interface/Account/Account"; @@ -13,49 +14,51 @@ import { createSet } from "../../../util"; import { useParties } from "../../../context/PartiesContext"; import { useInstruments } from "../../../context/InstrumentContext"; import { useServices } from "../../../context/ServicesContext"; -import { Service as Auction } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Distribution/Auction/Service"; -import { Service as AuctionAuto } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Distribution/Auction/Auto/Service"; -import { Message } from "../../../components/Message/Message"; +import { Service as Auction } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Interface/Distribution/Auction/Service"; +import { Service as AuctionAuto } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Interface/Distribution/Auction/Auto"; import { useHoldings } from "../../../context/HoldingContext"; -import { Aggregate } from "../../../components/Instrument/Aggregate"; +import { CenteredForm } from "../../../components/CenteredForm/CenteredForm"; +import { TextInput } from "../../../components/Form/TextInput"; +import { SelectInput, toValues } from "../../../components/Form/SelectInput"; export const New : React.FC = () => { - const classes = useStyles(); + const cls = useStyles(); const navigate = useNavigate(); const [ instrumentLabel, setInstrumentLabel ] = useState(""); const [ currencyLabel, setCurrencyLabel ] = useState(""); const [ amount, setAmount ] = useState(""); const [ floor, setFloor ] = useState(""); - const [ id, setId ] = useState(""); + const [ description, setDescription ] = useState(""); const ledger = useLedger(); const party = useParty(); const { getParty } = useParties(); - const { loading: l1, auction, auctionAuto } = useServices(); + const { loading: l1, auction } = useServices(); const { loading: l2, latests, tokens } = useInstruments(); const { loading: l3, holdings, getFungible } = useHoldings(); const { loading: l4, contracts: accounts } = useStreamQueries(Reference); if (l1 || l2 || l3 || l4) return ; - const myServices = auction.filter(s => s.payload.customer === party); - const myAutoServices = auctionAuto.filter(s => s.payload.customer === party); const instrument = latests.find(c => c.payload.id.unpack === instrumentLabel); const currency = tokens.find(c => c.payload.id.unpack === currencyLabel); const myHoldings = holdings.filter(c => c.payload.account.owner === party); - const myHoldingLabels = myHoldings.map(c => c.payload.instrument.id.unpack).filter((v, i, a) => a.indexOf(v) === i); - const canRequest = !!instrumentLabel && !!instrument && !!currencyLabel && !!currency && !!id && !!amount && !!floor; - - if (myServices.length === 0) return ; + const myInstrumentLabels = myHoldings.map(c => c.payload.instrument.id.unpack).filter((v, i, a) => a.indexOf(v) === i); + const myInstruments = latests.filter(a => myInstrumentLabels.includes(a.payload.id.unpack)); + const canRequest = !!instrumentLabel && !!instrument && !!currencyLabel && !!currency && !!description && !!amount && !!floor; const requestCreateAuction = async () => { - if (!instrument || !currency) return; + if (!instrument || !currency) throw new Error("Instrument or currency not found"); const collateralCid = await getFungible(party, amount, instrument.key); const receivableAccount = accounts.find(c => c.payload.accountView.custodian === currency.payload.depository && c.payload.accountView.owner === party)?.key; - if (!receivableAccount) return; - const arg = { - id, + if (!receivableAccount) throw new Error("Receivable account not found"); + const agent = getParty("Agent"); // TODO: Hard-coded agent party + const svc = auction.getService(agent, party); + if (!svc) throw new Error("No auction service found for provider [" + agent + "] and customer [" + party + "]"); + const arg = { + auctionId: { unpack: uuidv4() }, + description, quantity: { amount, unit: instrument.key }, currency: currency.key, floor: floor, @@ -63,53 +66,19 @@ export const New : React.FC = () => { receivableAccount, observers: createSet([getParty("Public")]) }; - if (myAutoServices.length > 0) { - await ledger.exercise(AuctionAuto.RequestAndCreateAuction, myAutoServices[0].contractId, arg); - navigate("/app/distribution/auctions"); - } else { - await ledger.exercise(Auction.RequestCreateAuction, myServices[0].contractId, arg); - navigate("/app/distribution/requests"); - } - } + if (!!svc.auto) await ledger.exercise(AuctionAuto.RequestAndCreateAuction, svc.auto.contractId, arg); + else await ledger.exercise(Auction.RequestCreateAuction, svc.service.contractId, arg); + navigate("/app/distribution/auctions"); + }; - const menuProps : Partial = { anchorOrigin: { vertical: "bottom", horizontal: "left" }, transformOrigin: { vertical: "top", horizontal: "left" } }; return ( - - - New Auction - - - - - - - - Details - - Auctioned Asset - - - - Currency - - - setAmount(e.target.value as string)} /> - setFloor(e.target.value as string)} /> - setId(e.target.value as string)} /> - - - - - - - {!!instrument && } - - - - + + + + + + + + ); }; diff --git a/ui/src/pages/distribution/auction/Requests.tsx b/ui/src/pages/distribution/auction/Requests.tsx index e40c54d0..7c358c30 100644 --- a/ui/src/pages/distribution/auction/Requests.tsx +++ b/ui/src/pages/distribution/auction/Requests.tsx @@ -3,16 +3,17 @@ import React from "react"; import { useNavigate } from "react-router-dom"; -import { Table, TableBody, TableCell, TableRow, TableHead, Button, Grid, Paper, Typography } from "@mui/material"; +import { Button } from "@mui/material"; import { CreateEvent } from "@daml/ledger"; import { useLedger, useParty, useStreamQueries } from "@daml/react"; import useStyles from "../../styles"; -import { CreateAuctionRequest } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Distribution/Auction/Model"; -import { Service } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Distribution/Auction/Service"; +import { CreateAuctionRequest } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Interface/Distribution/Auction/CreateAuctionRequest"; +import { Service } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Interface/Distribution/Auction/Service"; import { Spinner } from "../../../components/Spinner/Spinner"; import { fmt } from "../../../util"; import { useParties } from "../../../context/PartiesContext"; import { useServices } from "../../../context/ServicesContext"; +import { Alignment, HorizontalTable } from "../../../components/Table/HorizontalTable"; export const Requests : React.FC = () => { const classes = useStyles(); @@ -25,54 +26,29 @@ export const Requests : React.FC = () => { const { loading: l2, contracts: requests } = useStreamQueries(CreateAuctionRequest); if (l1 || l2) return ; - const providerServices = auction.filter(s => s.payload.provider === party); - const createAuction = async (c : CreateEvent) => { - const service = providerServices.find(s => s.payload.customer === c.payload.customer); - if (!service) throw new Error("No auction service found"); - await ledger.exercise(Service.CreateAuction, service.contractId, { createAuctionRequestCid: c.contractId }); + const svc = auction.getService(party, c.payload.customer); + if (!svc) throw new Error("No auction service found for provider " + party + " and customer " + c.payload.customer); + await ledger.exercise(Service.CreateAuction, svc.service.contractId, { createAuctionRequestCid: c.contractId }); navigate("/app/distribution/auctions"); } + const createRow = (c : CreateEvent) : any[] => { + return [ + getName(c.payload.provider), + getName(c.payload.customer), + c.payload.auctionId.unpack, + c.payload.description, + fmt(c.payload.quantity.amount, 0) + " " + c.payload.quantity.unit.id.unpack, + c.payload.currency.id.unpack, + c.payload.floor + " " + c.payload.currency.id.unpack, + + ]; + } + const headers = ["Agent", "Issuer", "Auction Id", "Description", "Asset", "Currency", "Floor Price", "Action"] + const values : any[] = requests.map(createRow); + const alignment : Alignment[] = ["left", "left", "left", "left", "right", "left", "right", "left"]; return ( - <> - - - - - Auction Requests - - - - Agent - Issuer - Auction ID - Auctioned Asset - Quoted Asset - Floor Price - Action - - - - {requests.map((c, i) => ( - - {getName(c.payload.provider)} - {getName(c.payload.customer)} - {c.payload.id} - {fmt(c.payload.quantity.amount)} {c.payload.quantity.unit.id.unpack} - {c.payload.currency.id.unpack} - {c.payload.floor} {c.payload.currency.id.unpack} - - {party === c.payload.provider && } - - - ))} - -
-
-
-
-
- + ); }; diff --git a/ui/src/pages/distribution/bidding/Auctions.tsx b/ui/src/pages/distribution/bidding/Auctions.tsx index 702c16bd..513b9e85 100644 --- a/ui/src/pages/distribution/bidding/Auctions.tsx +++ b/ui/src/pages/distribution/bidding/Auctions.tsx @@ -22,7 +22,7 @@ export const Auctions: React.FC = () => { const { contracts: auctions, loading: l1 } = useStreamQueries(Auction); const { contracts: bids, loading: l2 } = useStreamQueries(Bid); if (l1 || l2) return ; - + console.log(bids); return ( @@ -43,7 +43,7 @@ export const Auctions: React.FC = () => { {auctions.map((c, i) => - {c.payload.id} + {c.payload.id.unpack} {getName(c.payload.provider)} {getName(c.payload.customer)} {c.payload.quantity.unit.id.unpack} @@ -77,7 +77,7 @@ export const Auctions: React.FC = () => { {bids.map((c, i) => ( - {c.payload.auctionId} + {c.payload.auctionId.unpack} {getName(c.payload.provider)} {getName(c.payload.customer)} {fmt(c.payload.details.quantity.amount)} {c.payload.details.quantity.unit.id.unpack} diff --git a/ui/src/pages/issuance/New.tsx b/ui/src/pages/issuance/New.tsx index 0e8fdb7d..02fba518 100644 --- a/ui/src/pages/issuance/New.tsx +++ b/ui/src/pages/issuance/New.tsx @@ -6,7 +6,7 @@ import { useNavigate } from "react-router-dom"; import { v4 as uuidv4 } from "uuid"; import classnames from "classnames"; import { useLedger, useParty, useStreamQueries } from "@daml/react"; -import { Typography, Grid, Paper, Button, Checkbox, FormGroup, FormControlLabel } from "@mui/material"; +import { Button, Checkbox, FormGroup, FormControlLabel } from "@mui/material"; import useStyles from "../styles"; import { Spinner } from "../../components/Spinner/Spinner"; import { Reference } from "@daml.js/daml-finance-interface-account/lib/Daml/Finance/Interface/Account/Account"; @@ -19,6 +19,7 @@ import { Message } from "../../components/Message/Message"; import { TextInput } from "../../components/Form/TextInput"; import { SelectInput, toValues } from "../../components/Form/SelectInput"; import { fmt } from "../../util"; +import { CenteredForm } from "../../components/CenteredForm/CenteredForm"; export const New : React.FC = () => { const cls = useStyles(); @@ -78,24 +79,11 @@ export const New : React.FC = () => { } return ( - - - New Issuance - - - - - - - - - {hasB2B && setIsB2B(e.target.checked)}/>} label="Issue back-to-back" />} - - - - - - - + + + + {hasB2B && setIsB2B(e.target.checked)}/>} label="Issue back-to-back" />} + + ); }; From 86006146130d32b4c4273ea4a62066944e2c1da3 Mon Sep 17 00:00:00 2001 From: Georg Schneider Date: Wed, 21 Dec 2022 01:41:13 +0100 Subject: [PATCH 09/31] Add interfaces for more services --- src/daml/Daml/Finance/App/Custody/Auto.daml | 84 +++----- .../Daml/Finance/App/Custody/Service.daml | 2 + .../App/Distribution/Auction/Auto.daml | 112 +--------- .../App/Distribution/Auction/Service.daml | 9 +- .../App/Distribution/Bidding/Auto.daml | 84 +------- .../App/Distribution/Bidding/Service.daml | 10 +- .../Finance/App/Distribution/Fund/Model.daml | 66 +++--- .../App/Distribution/Fund/Service.daml | 77 +++---- .../App/Distribution/Investment/Model.daml | 34 +-- .../App/Distribution/Investment/Service.daml | 40 ++-- .../App/Distribution/Subscription/Model.daml | 109 +++++----- .../Distribution/Subscription/Service.daml | 87 ++++---- .../App/Distribution/Subscription/Util.daml | 22 +- .../Finance/App/Interface/Custody/Auto.daml | 34 ++- .../App/Interface/Custody/Service.daml | 8 + .../Distribution/Auction/Auction.daml | 2 +- .../Interface/Distribution/Auction/Auto.daml | 17 +- .../Auction/CreateAuctionRequest.daml | 1 + .../Distribution/Auction/Service.daml | 3 + .../Interface/Distribution/Bidding/Auto.daml | 17 +- .../Distribution/Bidding/Service.daml | 4 + .../App/Interface/Distribution/Fund/Fund.daml | 73 +++++++ .../Fund/PooledInvestmentRequest.daml | 41 ++++ .../Interface/Distribution/Fund/Service.daml | 62 ++++++ .../Investment/InvestmentRequest.daml | 61 ++++++ .../Distribution/Investment/Service.daml | 42 ++++ .../Distribution/Subscription/Offering.daml | 57 +++++ .../Distribution/Subscription/Service.daml | 60 ++++++ .../Subscription/Subscription.daml | 72 +++++++ .../Distribution/Subscription/Types.daml | 22 ++ .../Finance/App/Interface/Issuance/Auto.daml | 24 +-- .../App/Interface/Issuance/BackToBack.daml | 68 ++++++ .../App/Interface/Issuance/Service.daml | 4 + .../Interface/Lending/BorrowAgreement.daml | 53 +++++ .../App/Interface/Lending/BorrowOffer.daml | 41 ++++ .../Interface/Lending/BorrowOfferRequest.daml | 35 ++++ .../App/Interface/Lending/Service.daml | 71 +++++++ .../App/Interface/Lifecycle/Service.daml | 198 ++++++++++++++++++ .../Finance/App/Interface/Listing/Auto.daml | 26 +-- .../Interface/Listing/DelistingRequest.daml | 1 + .../App/Interface/Listing/Listing.daml | 1 + .../App/Interface/Listing/ListingRequest.daml | 1 + .../App/Interface/Listing/Service.daml | 4 + src/daml/Daml/Finance/App/Issuance/Auto.daml | 58 ++--- .../Service.daml => Issuance/BackToBack.daml} | 73 +++---- .../Daml/Finance/App/Issuance/Service.daml | 2 + src/daml/Daml/Finance/App/Lending/Model.daml | 69 ++++-- .../Daml/Finance/App/Lending/Service.daml | 79 +++---- .../Daml/Finance/App/Lifecycle/Service.daml | 165 ++++----------- src/daml/Daml/Finance/App/Listing/Auto.daml | 41 ++-- src/daml/Daml/Finance/App/Listing/Model.daml | 1 + .../Daml/Finance/App/Listing/Service.daml | 12 +- src/daml/Daml/Finance/App/Role/Custodian.daml | 15 +- .../Daml/Finance/App/Role/Distributor.daml | 15 +- .../Daml/Finance/Setup/Scenario/Default.daml | 4 + .../Setup/Scenario/FundTokenization.daml | 4 +- .../Setup/Scenario/SecuritiesLending.daml | 19 +- .../Setup/Scenario/StructuredNotes.daml | 31 +-- src/daml/Daml/Finance/Setup/Util/Service.daml | 42 ++-- .../Daml/Finance/Setup/Util/Workflow.daml | 83 ++++---- 60 files changed, 1617 insertions(+), 935 deletions(-) create mode 100644 src/daml/Daml/Finance/App/Interface/Distribution/Fund/Fund.daml create mode 100644 src/daml/Daml/Finance/App/Interface/Distribution/Fund/PooledInvestmentRequest.daml create mode 100644 src/daml/Daml/Finance/App/Interface/Distribution/Fund/Service.daml create mode 100644 src/daml/Daml/Finance/App/Interface/Distribution/Investment/InvestmentRequest.daml create mode 100644 src/daml/Daml/Finance/App/Interface/Distribution/Investment/Service.daml create mode 100644 src/daml/Daml/Finance/App/Interface/Distribution/Subscription/Offering.daml create mode 100644 src/daml/Daml/Finance/App/Interface/Distribution/Subscription/Service.daml create mode 100644 src/daml/Daml/Finance/App/Interface/Distribution/Subscription/Subscription.daml create mode 100644 src/daml/Daml/Finance/App/Interface/Distribution/Subscription/Types.daml create mode 100644 src/daml/Daml/Finance/App/Interface/Issuance/BackToBack.daml create mode 100644 src/daml/Daml/Finance/App/Interface/Lending/BorrowAgreement.daml create mode 100644 src/daml/Daml/Finance/App/Interface/Lending/BorrowOffer.daml create mode 100644 src/daml/Daml/Finance/App/Interface/Lending/BorrowOfferRequest.daml create mode 100644 src/daml/Daml/Finance/App/Interface/Lending/Service.daml create mode 100644 src/daml/Daml/Finance/App/Interface/Lifecycle/Service.daml rename src/daml/Daml/Finance/App/{BackToBack/Service.daml => Issuance/BackToBack.daml} (74%) diff --git a/src/daml/Daml/Finance/App/Custody/Auto.daml b/src/daml/Daml/Finance/App/Custody/Auto.daml index 31d0a55c..c6028687 100644 --- a/src/daml/Daml/Finance/App/Custody/Auto.daml +++ b/src/daml/Daml/Finance/App/Custody/Auto.daml @@ -3,22 +3,15 @@ module Daml.Finance.App.Custody.Auto where -import DA.Assert ((===)) -import Daml.Finance.App.Custody.Model qualified as Model +import Daml.Finance.App.Custody.Service qualified as Service (T) import Daml.Finance.App.Interface.Base.Service qualified as Base (I, View(..)) -import Daml.Finance.App.Interface.Common.Util (fetchAndRemove) import Daml.Finance.App.Interface.Custody.Auto qualified as Auto (HasImplementation, I, View(..), RequestAndCloseAccount(..), RequestAndDeposit(..), RequestAndOpenAccount(..), RequestAndWithdraw(..)) -import Daml.Finance.App.Interface.Custody.CloseAccountRequest qualified as CloseAccountRequest (View(..)) -import Daml.Finance.App.Interface.Custody.DepositRequest qualified as DepositRequest (View(..)) -import Daml.Finance.App.Interface.Custody.OpenAccountRequest qualified as OpenAccountRequest (View(..)) -import Daml.Finance.App.Interface.Custody.WithdrawRequest qualified as WithdrawRequest (View(..)) -import Daml.Finance.App.Interface.Custody.Service qualified as Service (CloseAccount(..), Deposit(..), I, OpenAccount(..), RequestCloseAccount(..), RequestDeposit(..), RequestOpenAccount(..), RequestWithdraw(..), View(..), Withdraw(..)) -import Daml.Finance.Interface.Account.Account qualified as Account (Credit(..), Debit(..), I, exerciseInterfaceByKey) -import Daml.Finance.Interface.Account.Factory qualified as Account (Create(..), F, Remove(..)) -import Daml.Finance.Interface.Account.Util (getAccount) +import Daml.Finance.App.Interface.Custody.Service qualified as Service (CloseAccount(..), Deposit(..), I, OpenAccount(..), RequestCloseAccount(..), RequestDeposit(..), RequestOpenAccount(..), RequestWithdraw(..), Withdraw(..)) +import Daml.Finance.Interface.Account.Factory qualified as Account (F) import Daml.Finance.Interface.Holding.Factory qualified as Holding (F) import Daml.Finance.Interface.Lifecycle.Rule.Claim qualified as Lifecycle (Claim) -import Daml.Finance.Interface.Types.Common (AccountKey(..)) + +type T = Service instance Auto.HasImplementation Service @@ -40,53 +33,30 @@ template Service view = Base.View with operator; provider; customer terminate = pure () - interface instance Service.I for Service where - view = Service.View with claimRuleCid; accountFactoryCid; holdingFactoryCid - asBase = toInterface @Base.I this - requestOpenAccount Service.RequestOpenAccount{id; description; controllers; observers} = do - toInterfaceContractId <$> create Model.OpenAccountRequest with operator; provider; customer; id; description; controllers; observers - requestCloseAccount Service.RequestCloseAccount{account} = do - toInterfaceContractId <$> create Model.CloseAccountRequest with operator; provider; customer; account - requestDeposit Service.RequestDeposit{quantity; account} = do - toInterfaceContractId <$> create Model.DepositRequest with operator; provider; customer; quantity; account - requestWithdraw Service.RequestWithdraw{holdingCid} = do - toInterfaceContractId <$> create Model.WithdrawRequest with operator; provider; customer; holdingCid - openAccount Service.OpenAccount{openAccountRequestCid} = do - OpenAccountRequest.View{id; description; controllers; observers} <- view <$> fetchAndRemove openAccountRequestCid - let account = AccountKey with custodian = provider; owner = customer; id - accountCid <- exercise accountFactoryCid Account.Create with account; description; controllers; holdingFactoryCid; observers - pure (accountCid, account) - closeAccount Service.CloseAccount{closeAccountRequestCid} = do - CloseAccountRequest.View{account} <- view <$> fetchAndRemove closeAccountRequestCid - exercise accountFactoryCid Account.Remove with account - deposit Service.Deposit{depositRequestCid} = do - DepositRequest.View{quantity; account} <- view <$> fetchAndRemove depositRequestCid - account.custodian === provider - account.owner === customer - Account.exerciseInterfaceByKey @Account.I account provider Account.Credit with quantity - withdraw Service.Withdraw{withdrawRequestCid} = do - WithdrawRequest.View{holdingCid} <- view <$> fetchAndRemove withdrawRequestCid - holding <- fetch holdingCid - let account = getAccount holding - account.custodian === provider - account.owner === customer - Account.exerciseInterfaceByKey @Account.I account provider Account.Debit with holdingCid - interface instance Auto.I for Service where view = Auto.View - asService = toInterface @Service.I this - requestAndOpenAccount self Auto.RequestAndOpenAccount{id; description; controllers; observers} = do - openAccountRequestCid <- exercise self Service.RequestOpenAccount with id; description; controllers; observers - exercise self Service.OpenAccount with openAccountRequestCid - requestAndCloseAccount self Auto.RequestAndCloseAccount{account} = do - closeAccountRequestCid <- exercise self Service.RequestCloseAccount with account - exercise self Service.CloseAccount with closeAccountRequestCid - requestAndDeposit self Auto.RequestAndDeposit{account; quantity} = do - depositRequestCid <- exercise self Service.RequestDeposit with quantity; account - exercise self Service.Deposit with depositRequestCid - requestAndWithdraw self Auto.RequestAndWithdraw{holdingCid} = do - withdrawRequestCid <- exercise self Service.RequestWithdraw with holdingCid - exercise self Service.Withdraw with withdrawRequestCid + + asBase = toInterface @Base.I this + + requestAndOpenAccount Auto.RequestAndOpenAccount{id; description; controllers; observers} = do + serviceCid <- toInterfaceContractId @Service.I . fst <$> fetchByKey @Service.T (operator, provider, customer) + openAccountRequestCid <- exercise serviceCid Service.RequestOpenAccount with id; description; controllers; observers + exercise serviceCid Service.OpenAccount with openAccountRequestCid + + requestAndCloseAccount Auto.RequestAndCloseAccount{account} = do + serviceCid <- toInterfaceContractId @Service.I . fst <$> fetchByKey @Service.T (operator, provider, customer) + closeAccountRequestCid <- exercise serviceCid Service.RequestCloseAccount with account + exercise serviceCid Service.CloseAccount with closeAccountRequestCid + + requestAndDeposit Auto.RequestAndDeposit{account; quantity} = do + serviceCid <- toInterfaceContractId @Service.I . fst <$> fetchByKey @Service.T (operator, provider, customer) + depositRequestCid <- exercise serviceCid Service.RequestDeposit with quantity; account + exercise serviceCid Service.Deposit with depositRequestCid + + requestAndWithdraw Auto.RequestAndWithdraw{holdingCid} = do + serviceCid <- toInterfaceContractId @Service.I . fst <$> fetchByKey @Service.T (operator, provider, customer) + withdrawRequestCid <- exercise serviceCid Service.RequestWithdraw with holdingCid + exercise serviceCid Service.Withdraw with withdrawRequestCid template Offer with diff --git a/src/daml/Daml/Finance/App/Custody/Service.daml b/src/daml/Daml/Finance/App/Custody/Service.daml index 803b9692..c7fee6f9 100644 --- a/src/daml/Daml/Finance/App/Custody/Service.daml +++ b/src/daml/Daml/Finance/App/Custody/Service.daml @@ -19,6 +19,8 @@ import Daml.Finance.Interface.Account.Util (getAccount) import Daml.Finance.Interface.Lifecycle.Rule.Claim qualified as Lifecycle (Claim) import Daml.Finance.Interface.Types.Common (AccountKey(..)) +type T = Service + instance Service.HasImplementation Service template Service diff --git a/src/daml/Daml/Finance/App/Distribution/Auction/Auto.daml b/src/daml/Daml/Finance/App/Distribution/Auction/Auto.daml index 828eb977..a0560cee 100644 --- a/src/daml/Daml/Finance/App/Distribution/Auction/Auto.daml +++ b/src/daml/Daml/Finance/App/Distribution/Auction/Auto.daml @@ -1,33 +1,12 @@ -- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. -- SPDX-License-Identifier: Apache-2.0 -{-# LANGUAGE MultiWayIf #-} - module Daml.Finance.App.Distribution.Auction.Auto where -import DA.Action (foldlA) -import DA.Either (partitionEithers) -import DA.Foldable (forA_) -import DA.List (sortOn, mapAccumL) -import DA.Optional (whenSome) -import DA.Set (fromList, singleton) -import Daml.Finance.App.Distribution.Auction.Model qualified as Model (Auction, CreateAuctionRequest(..)) -import Daml.Finance.App.Distribution.Bidding.Service qualified as BiddingService (T) +import Daml.Finance.App.Distribution.Auction.Service qualified as Service (T) import Daml.Finance.App.Interface.Base.Service qualified as Base (I, View(..)) -import Daml.Finance.App.Interface.Common.Util (fetchAndRemove) -import Daml.Finance.App.Interface.Distribution.Auction.Auction qualified as Auction (Status(..)) import Daml.Finance.App.Interface.Distribution.Auction.Auto qualified as Auto (I, HasImplementation, RequestAndCreateAuction(..), View(..)) -import Daml.Finance.App.Interface.Distribution.Auction.CreateAuctionRequest qualified as CreateAuctionRequest (View(..)) -import Daml.Finance.App.Interface.Distribution.Auction.Service qualified as Service (CreateAuction(..), I, ProcessAuction(..), RequestCreateAuction(..), View(..)) -import Daml.Finance.App.Interface.Distribution.Bidding.Service qualified as BiddingService (I, RejectBid(..)) -import Daml.Finance.Interface.Account.Account qualified as Account (R, exerciseInterfaceByKey) -import Daml.Finance.Interface.Holding.Base qualified as Holding (Acquire(..), I, LockType(..), Release(..)) -import Daml.Finance.Interface.Account.Util (getAccount) -import Daml.Finance.Interface.Util.Disclosure qualified as Disclosure (AddObservers(..), I, RemoveObservers(..)) -import Daml.Finance.Interface.Settlement.Batch qualified as Batch (Settle(..)) -import Daml.Finance.App.Distribution.Auction.Model (Auction(..), CreateAuctionRequest(..)) -import Daml.Finance.App.Distribution.Auction.Utils (dutchAuction, splitList, generateSettlementInstruction) -import Daml.Finance.App.Interface.Distribution.Bidding.Bid qualified as Bid (Allocation(..), SettleAllocation(..), Status(..)) +import Daml.Finance.App.Interface.Distribution.Auction.Service qualified as Service (CreateAuction(..), I, RequestCreateAuction(..)) type T = Service @@ -48,88 +27,15 @@ template Service view = Base.View with operator; provider; customer terminate = pure () - interface instance Service.I for Service where - view = Service.View - asBase = toInterface @Base.I this - requestCreateAuction Service.RequestCreateAuction{auctionId; description; quantity; currency; floor; collateralCid; receivableAccount; observers} = do - -- Disclose holding - collateral <- fetch collateralCid - collateralCid <- coerceContractId <$> exercise (coerceContractId collateralCid : ContractId Disclosure.I) Disclosure.AddObservers with disclosers = singleton customer; observersToAdd = (show auctionId, fromList [provider]) - - -- Disclose delivering securities account - (_, delRef) <- fetchByKey @Account.R $ getAccount collateral - exercise (coerceContractId delRef.cid : ContractId Disclosure.I) Disclosure.AddObservers with disclosers = singleton customer; observersToAdd = (show auctionId, fromList [provider]) - - -- Disclose receiving cash account - (_, recRef) <- fetchByKey @Account.R receivableAccount - exercise (coerceContractId recRef.cid : ContractId Disclosure.I) Disclosure.AddObservers with disclosers = singleton customer; observersToAdd = (show auctionId, singleton provider) - - toInterfaceContractId <$> create Model.CreateAuctionRequest with operator; provider; customer; auctionId; description; quantity; currency; floor; collateralCid; receivableAccount; observers - createAuction Service.CreateAuction{createAuctionRequestCid} = do - CreateAuctionRequest.View{auctionId; description; quantity; currency; floor; collateralCid; receivableAccount; observers} <- view <$> fetchAndRemove createAuctionRequestCid - collateralCid <- coerceContractId <$> exercise (toInterfaceContractId collateralCid : ContractId Holding.I) Holding.Acquire with newLockers = fromList [ provider ]; context = show auctionId; lockType = Holding.Semaphore - toInterfaceContractId <$> create Auction with operator; provider; customer; id = auctionId; description; quantity; currency; floor; collateralCid; receivableAccount; status = Auction.Open; observers - processAuction Service.ProcessAuction{settlementFactoryCid; auctionCid; bidCids} = do - let auctionTCid = fromInterfaceContractId @Model.Auction auctionCid - auction <- fetch auctionTCid - collateral <- fetch auction.collateralCid - bids <- zip bidCids <$> forA bidCids (fmap view . fetch) - collaterals <- mapA (\(_, bidView) -> fetch bidView.collateralCid) bids - assertMsg "Auction already successfully processed" (auction.status `elem` [Auction.Open, Auction.NoValidBids]) - - -- Split bids on those above / below the floor price -> Sort valid bids descendingly -> Execute Auction -> Split auction result on allocated / unallocated (ie, zero allocation) - let - collateralAccount = getAccount collateral - collateralAccounts = map getAccount collaterals - receivableAccounts = map ((.receivableAccount) . snd) bids - (invalidBids, validBids) = partitionEithers $ splitList (\(_, bid) -> bid.details.price.amount >= auction.floor) bids - sortedBids = sortOn (\(_, bid) -> Down bid.details) validBids - ((remaining, finalPrice), allocations) = mapAccumL dutchAuction (auction.quantity.amount, 0.0) sortedBids - (allocatedBids, unallocatedBids) = partitionEithers $ splitList (\allocation -> allocation.amount == 0.0) allocations - - -- Return assets of all invalid and unallocated bids. Also update their bid status accordingly - forA_ invalidBids (\(bidCid, bid) -> do - (serviceCid, _) <- fetchByKey @BiddingService.T (bid.operator, bid.provider, bid.customer) - exercise (toInterfaceContractId @BiddingService.I serviceCid) BiddingService.RejectBid with bidCid; newStatus = Bid.Invalid) - forA_ unallocatedBids (\Bid.Allocation{bidCid, bid} -> do - (serviceCid, _) <- fetchByKey @BiddingService.T (bid.operator, bid.provider, bid.customer) - exercise (toInterfaceContractId @BiddingService.I serviceCid) BiddingService.RejectBid with bidCid; newStatus = Bid.NoAllocation) - - -- Unlock auction collateral - auctionCollateralClid <- coerceContractId <$> exercise (toInterfaceContractId auction.collateralCid : ContractId Holding.I) Holding.Release with context = show auction.id - - -- Generate Settlement instructions for allocated bids - let settleAllocations = (\allocation -> Bid.SettleAllocation with allocation; price = finalPrice; issuer = customer) <$> allocatedBids - (remainingDepositCidOpt, batchCids) <- foldlA (generateSettlementInstruction settlementFactoryCid provider auction.receivableAccount) (Some auctionCollateralClid, []) settleAllocations - - -- Settle transfers - forA_ batchCids (`exercise` Batch.Settle with actors = singleton provider) - - -- Undisclose unallocated deposit - whenSome remainingDepositCidOpt \depositCid -> do - exercise (coerceContractId depositCid : ContractId Disclosure.I) Disclosure.RemoveObservers with disclosers = singleton customer; observersToRemove = (show auction.id, singleton provider) - pure () - - -- Undisclose accounts - Account.exerciseInterfaceByKey @Disclosure.I auction.receivableAccount provider Disclosure.RemoveObservers with disclosers = singleton provider; observersToRemove = (show auction.id, singleton provider) - Account.exerciseInterfaceByKey @Disclosure.I collateralAccount provider Disclosure.RemoveObservers with disclosers = singleton provider; observersToRemove = (show auction.id, singleton provider) - forA_ receivableAccounts (\a -> Account.exerciseInterfaceByKey @Disclosure.I a provider Disclosure.RemoveObservers with disclosers = singleton provider; observersToRemove = (show auction.id, singleton provider)) - forA_ collateralAccounts (\a -> Account.exerciseInterfaceByKey @Disclosure.I a provider Disclosure.RemoveObservers with disclosers = singleton provider; observersToRemove = (show auction.id, singleton provider)) - - -- Update Auction contract with the outcome of the auction processing - let newStatus = if - | remaining == auction.quantity.amount -> Auction.NoValidBids - | remaining > 0.0 -> Auction.PartiallyAllocated with finalPrice; remaining - | otherwise -> Auction.FullyAllocated with finalPrice - archive auctionCid - toInterfaceContractId <$> create auction with status = newStatus - interface instance Auto.I for Service where view = Auto.View - asService = toInterface @Service.I this - requestAndCreateAuction self Auto.RequestAndCreateAuction{auctionId; description; quantity; currency; floor; collateralCid; receivableAccount; observers} = do - createAuctionRequestCid <- exercise self Service.RequestCreateAuction with auctionId; description; quantity; currency; floor; collateralCid; receivableAccount; observers - exercise self Service.CreateAuction with createAuctionRequestCid + + asBase = toInterface @Base.I this + + requestAndCreateAuction Auto.RequestAndCreateAuction{auctionId; description; quantity; currency; floor; collateralCid; receivableAccount; observers} = do + serviceCid <- toInterfaceContractId @Service.I . fst <$> fetchByKey @Service.T (operator, provider, customer) + createAuctionRequestCid <- exercise serviceCid Service.RequestCreateAuction with auctionId; description; quantity; currency; floor; collateralCid; receivableAccount; observers + exercise serviceCid Service.CreateAuction with createAuctionRequestCid template Offer with diff --git a/src/daml/Daml/Finance/App/Distribution/Auction/Service.daml b/src/daml/Daml/Finance/App/Distribution/Auction/Service.daml index 04447c3b..56ef1661 100644 --- a/src/daml/Daml/Finance/App/Distribution/Auction/Service.daml +++ b/src/daml/Daml/Finance/App/Distribution/Auction/Service.daml @@ -18,7 +18,7 @@ import Daml.Finance.App.Interface.Base.Service qualified as Base (I, View(..)) import Daml.Finance.App.Interface.Common.Util (fetchAndRemove) import Daml.Finance.App.Interface.Distribution.Auction.Auction qualified as Auction (Status(..)) import Daml.Finance.App.Interface.Distribution.Auction.CreateAuctionRequest qualified as CreateAuctionRequest (View(..)) -import Daml.Finance.App.Interface.Distribution.Auction.Service qualified as Service (CreateAuction(..), I, ProcessAuction(..), RequestCreateAuction(..), View(..)) +import Daml.Finance.App.Interface.Distribution.Auction.Service qualified as Service (CreateAuction(..), HasImplementation, I, ProcessAuction(..), RequestCreateAuction(..), View(..)) import Daml.Finance.App.Interface.Distribution.Bidding.Bid qualified as Bid (Allocation(..), SettleAllocation(..), Status(..)) import Daml.Finance.App.Interface.Distribution.Bidding.Service qualified as BiddingService (I, RejectBid(..)) import Daml.Finance.Interface.Account.Account qualified as Account (R, exerciseInterfaceByKey) @@ -29,6 +29,8 @@ import Daml.Finance.Interface.Settlement.Batch qualified as Batch (Settle(..)) type T = Service +instance Service.HasImplementation Service + template Service with operator : Party @@ -42,11 +44,14 @@ template Service interface instance Base.I for Service where view = Base.View with operator; provider; customer + terminate = pure () interface instance Service.I for Service where view = Service.View + asBase = toInterface @Base.I this + requestCreateAuction Service.RequestCreateAuction{auctionId; description; quantity; currency; floor; collateralCid; receivableAccount; observers} = do -- Disclose holding collateral <- fetch collateralCid @@ -61,10 +66,12 @@ template Service exercise (coerceContractId recRef.cid : ContractId Disclosure.I) Disclosure.AddObservers with disclosers = singleton customer; observersToAdd = (show auctionId, singleton provider) toInterfaceContractId <$> create Model.CreateAuctionRequest with operator; provider; customer; auctionId; description; quantity; currency; floor; collateralCid; receivableAccount; observers + createAuction Service.CreateAuction{createAuctionRequestCid} = do CreateAuctionRequest.View{auctionId; description; quantity; currency; floor; collateralCid; receivableAccount; observers} <- view <$> fetchAndRemove createAuctionRequestCid collateralCid <- coerceContractId <$> exercise (toInterfaceContractId collateralCid : ContractId Holding.I) Holding.Acquire with newLockers = fromList [ provider ]; context = show auctionId; lockType = Holding.Semaphore toInterfaceContractId <$> create Model.Auction with operator; provider; customer; id = auctionId; description; quantity; currency; floor; collateralCid; receivableAccount; status = Auction.Open; observers + processAuction Service.ProcessAuction{settlementFactoryCid; auctionCid; bidCids} = do let auctionTCid = fromInterfaceContractId @Model.Auction auctionCid auction <- fetch auctionTCid diff --git a/src/daml/Daml/Finance/App/Distribution/Bidding/Auto.daml b/src/daml/Daml/Finance/App/Distribution/Bidding/Auto.daml index 5c3432e4..6da63974 100644 --- a/src/daml/Daml/Finance/App/Distribution/Bidding/Auto.daml +++ b/src/daml/Daml/Finance/App/Distribution/Bidding/Auto.daml @@ -3,25 +3,10 @@ module Daml.Finance.App.Distribution.Bidding.Auto where -import DA.Assert ((===)) -import DA.List (head) -import DA.Optional (fromSome) -import DA.Set (singleton) +import Daml.Finance.App.Distribution.Bidding.Service qualified as Service (T) import Daml.Finance.App.Interface.Base.Service qualified as Base (I, View(..)) -import Daml.Finance.App.Interface.Common.Util (fetchAndRemove) -import Daml.Finance.App.Interface.Distribution.Auction.Auction qualified as Auction (GetView(..)) import Daml.Finance.App.Interface.Distribution.Bidding.Auto qualified as Auto (I, HasImplementation, RequestAndCreateBid(..), View(..)) -import Daml.Finance.App.Interface.Distribution.Bidding.Bid qualified as Bid (Details(..), Status(..), UpdateStatus(..)) -import Daml.Finance.App.Interface.Distribution.Bidding.CreateBidRequest qualified as CreateBidRequest (View(..)) -import Daml.Finance.App.Interface.Distribution.Bidding.Service qualified as Service (I, CreateBid(..), ProcessAllocation(..), RejectBid(..), RequestCreateBid(..), View(..)) -import Daml.Finance.Interface.Account.Account qualified as Account (R) -import Daml.Finance.Interface.Account.Util (getAccount) -import Daml.Finance.Interface.Holding.Fungible qualified as Fungible (I, Split(..), SplitResult(..)) -import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (qty) -import Daml.Finance.Interface.Holding.Base qualified as Holding (Acquire(..), I, LockType(..), Release(..)) -import Daml.Finance.Interface.Holding.Util (getAmount, getInstrument) -import Daml.Finance.Interface.Util.Disclosure qualified as Disclosure (AddObservers(..), I, RemoveObservers(..)) -import Daml.Finance.App.Distribution.Bidding.Model (Bid(..), CreateBidRequest(..)) +import Daml.Finance.App.Interface.Distribution.Bidding.Service qualified as Service (I, CreateBid(..), RequestCreateBid(..)) type T = Service @@ -42,68 +27,13 @@ template Service view = Base.View with operator; provider; customer terminate = pure () - interface instance Service.I for Service where - view = Service.View - asBase = toInterface @Base.I this - requestCreateBid Service.RequestCreateBid{auctionCid; amount; price; collateralCid; receivableAccount} = do - auction <- exercise auctionCid Auction.GetView with actor = customer - collateral <- fetch collateralCid - getInstrument collateral === auction.currency - getAmount collateral === price * amount - assertMsg "Bid amount can't be larger than available size" $ amount <= auction.quantity.amount - - -- Disclose holding - investorHolding <- fetch collateralCid - investorHoldingCid : ContractId Fungible.I <- coerceContractId <$> exercise (coerceContractId collateralCid : ContractId Disclosure.I) Disclosure.AddObservers with disclosers = singleton customer; observersToAdd = (show auction.id, singleton provider) - -- Disclose delivering securities account - let investorSendingAccount = getAccount investorHolding - (_, delRef) <- fetchByKey @Account.R investorSendingAccount - exercise (coerceContractId delRef.cid : ContractId Disclosure.I) Disclosure.AddObservers with disclosers = singleton customer; observersToAdd = (show auction.id, singleton provider) - -- Disclose receiving cash account - (_, recRef) <- fetchByKey @Account.R receivableAccount - exercise (coerceContractId recRef.cid : ContractId Disclosure.I) Disclosure.AddObservers with disclosers = singleton customer; observersToAdd = (show auction.id, singleton provider) - -- Lock holding - collateralCid <- coerceContractId <$> exercise (coerceContractId investorHoldingCid : ContractId Holding.I) Holding.Acquire with newLockers = singleton provider; context = show auction.id; lockType = Holding.Semaphore - - let - quantity = Instrument.qty amount auction.quantity.unit - priceQty = Instrument.qty price auction.currency - toInterfaceContractId <$> create CreateBidRequest with operator; provider; customer; issuer = auction.customer; auctionId = auction.id; quantity; price = priceQty; collateralCid; receivableAccount - createBid Service.CreateBid{createBidRequestCid} = do - CreateBidRequest.View{issuer; auctionId; collateralCid; receivableAccount; price; quantity} <- view <$> fetchAndRemove createBidRequestCid - time <- getTime - toInterfaceContractId <$> create Bid with operator; provider; customer; issuer; details = (Bid.Details with price; quantity; time); auctionId; collateralCid; receivableAccount; status = Bid.Pending - processAllocation Service.ProcessAllocation{bidCid; amount; price} = do - -- Fetch Bid -> Extract their deposit -> Split and return unused allocation (if necessary) to the investor -> Update Bid Status - bid <- view <$> fetch bidCid - bidCollateralCid : ContractId Disclosure.I <- coerceContractId <$> exercise (toInterfaceContractId @Holding.I bid.collateralCid) Holding.Release with context = show bid.auctionId - bidCollateralCid <- coerceContractId . fromSome <$> exercise bidCollateralCid Disclosure.RemoveObservers with disclosers = singleton provider; observersToRemove = (show bid.auctionId, singleton provider) - bidCollateral <- fetch bidCollateralCid - bidCollateralCid <- - if getAmount bidCollateral > amount * price - then do - Fungible.SplitResult{splitCids, rest} <- exercise bidCollateralCid Fungible.Split with amounts = [amount * price] - pure $ head splitCids - else do pure bidCollateralCid - let - newStatus = - if bid.details.quantity.amount == amount - then Bid.FullAllocation with price - else Bid.PartialAllocation with price; amount - newBidCid <- exercise bidCid Bid.UpdateStatus with newStatus - pure (newBidCid, bidCollateralCid) - rejectBid Service.RejectBid{bidCid; newStatus} = do - bid <- view <$> fetch bidCid - returnedCollateralCid <- exercise (toInterfaceContractId @Holding.I bid.collateralCid) Holding.Release with context = show bid.auctionId - newBidCid <- exercise bidCid Bid.UpdateStatus with newStatus - pure (newBidCid, coerceContractId returnedCollateralCid) - interface instance Auto.I for Service where view = Auto.View - asService = toInterface @Service.I this - requestAndCreateBid self Auto.RequestAndCreateBid{auctionCid; amount; price; collateralCid; receivableAccount} = do - createBidRequestCid <- exercise self Service.RequestCreateBid with auctionCid; amount; price; collateralCid; receivableAccount - exercise self Service.CreateBid with createBidRequestCid + asBase = toInterface @Base.I this + requestAndCreateBid Auto.RequestAndCreateBid{auctionCid; amount; price; collateralCid; receivableAccount} = do + serviceCid <- toInterfaceContractId @Service.I . fst <$> fetchByKey @Service.T (operator, provider, customer) + createBidRequestCid <- exercise serviceCid Service.RequestCreateBid with auctionCid; amount; price; collateralCid; receivableAccount + exercise serviceCid Service.CreateBid with createBidRequestCid template Offer with diff --git a/src/daml/Daml/Finance/App/Distribution/Bidding/Service.daml b/src/daml/Daml/Finance/App/Distribution/Bidding/Service.daml index cd117d75..995f3620 100644 --- a/src/daml/Daml/Finance/App/Distribution/Bidding/Service.daml +++ b/src/daml/Daml/Finance/App/Distribution/Bidding/Service.daml @@ -12,7 +12,7 @@ import Daml.Finance.App.Interface.Common.Util (fetchAndRemove) import Daml.Finance.App.Interface.Distribution.Auction.Auction qualified as Auction (GetView(..)) import Daml.Finance.App.Interface.Distribution.Bidding.Bid qualified as Bid (Details(..), Status(..), UpdateStatus(..)) import Daml.Finance.App.Interface.Distribution.Bidding.CreateBidRequest qualified as CreateBidRequest (View(..)) -import Daml.Finance.App.Interface.Distribution.Bidding.Service qualified as Service (I, CreateBid(..), ProcessAllocation(..), RejectBid(..), RequestCreateBid(..), View(..)) +import Daml.Finance.App.Interface.Distribution.Bidding.Service qualified as Service (HasImplementation, I, CreateBid(..), ProcessAllocation(..), RejectBid(..), RequestCreateBid(..), View(..)) import Daml.Finance.Interface.Account.Account qualified as Account (R) import Daml.Finance.Interface.Account.Util (getAccount) import Daml.Finance.Interface.Holding.Fungible qualified as Fungible (I, Split(..), SplitResult(..)) @@ -24,6 +24,8 @@ import Daml.Finance.App.Distribution.Bidding.Model (Bid(..), CreateBidRequest(.. type T = Service +instance Service.HasImplementation Service + template Service with operator : Party @@ -37,11 +39,14 @@ template Service interface instance Base.I for Service where view = Base.View with operator; provider; customer + terminate = pure () interface instance Service.I for Service where view = Service.View + asBase = toInterface @Base.I this + requestCreateBid Service.RequestCreateBid{auctionCid; amount; price; collateralCid; receivableAccount} = do auction <- exercise auctionCid Auction.GetView with actor = customer collateral <- fetch collateralCid @@ -66,10 +71,12 @@ template Service quantity = Instrument.qty amount auction.quantity.unit priceQty = Instrument.qty price auction.currency toInterfaceContractId <$> create CreateBidRequest with operator; provider; customer; issuer = auction.customer; auctionId = auction.id; quantity; price = priceQty; collateralCid; receivableAccount + createBid Service.CreateBid{createBidRequestCid} = do CreateBidRequest.View{issuer; auctionId; collateralCid; receivableAccount; price; quantity} <- view <$> fetchAndRemove createBidRequestCid time <- getTime toInterfaceContractId <$> create Bid with operator; provider; customer; issuer; details = (Bid.Details with price; quantity; time); auctionId; collateralCid; receivableAccount; status = Bid.Pending + processAllocation Service.ProcessAllocation{bidCid; amount; price} = do -- Fetch Bid -> Extract their deposit -> Split and return unused allocation (if necessary) to the investor -> Update Bid Status bid <- view <$> fetch bidCid @@ -89,6 +96,7 @@ template Service else Bid.PartialAllocation with price; amount newBidCid <- exercise bidCid Bid.UpdateStatus with newStatus pure (newBidCid, bidCollateralCid) + rejectBid Service.RejectBid{bidCid; newStatus} = do bid <- view <$> fetch bidCid returnedCollateralCid <- exercise (toInterfaceContractId @Holding.I bid.collateralCid) Holding.Release with context = show bid.auctionId diff --git a/src/daml/Daml/Finance/App/Distribution/Fund/Model.daml b/src/daml/Daml/Finance/App/Distribution/Fund/Model.daml index f404ed17..9023f2dd 100644 --- a/src/daml/Daml/Finance/App/Distribution/Fund/Model.daml +++ b/src/daml/Daml/Finance/App/Distribution/Fund/Model.daml @@ -4,19 +4,23 @@ module Daml.Finance.App.Distribution.Fund.Model where import DA.Assert ((===)) -import DA.Set (singleton) -import Daml.Finance.App.Distribution.Investment.Model (InvestmentRequest) -import Daml.Finance.App.Interface.Issuance.Issuance qualified as Issuance (I) -import Daml.Finance.App.Interface.Issuance.Service qualified as IssuanceService (I, Issue(..), RequestIssue(..), asBase) +import DA.Set (fromList, singleton) +import Daml.Finance.App.Interface.Common.Removable qualified as Removable (I, View(..)) +import Daml.Finance.App.Interface.Distribution.Fund.Fund qualified as Fund (ApproveInstruction(..), HasImplementation, I, IssueUnits(..), View(..)) +import Daml.Finance.App.Interface.Distribution.Fund.PooledInvestmentRequest qualified as PooledInvestmentRequest (HasImplementation, I, View(..)) +import Daml.Finance.App.Interface.Distribution.Investment.InvestmentRequest qualified as InvestmentRequest (I) +import Daml.Finance.App.Interface.Issuance.Service qualified as IssuanceService (Issue(..), RequestIssue(..), asBase) import Daml.Finance.Interface.Account.Account qualified as Account (K) import Daml.Finance.Interface.Holding.Transferable qualified as Transferable (I) import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (K, Q) -import Daml.Finance.Interface.Settlement.Instruction qualified as Instruction (Approve(..), I) +import Daml.Finance.Interface.Settlement.Instruction qualified as Instruction (Approve(..)) import Daml.Finance.Interface.Settlement.Types (Approval(TakeDelivery)) -import Daml.Finance.Interface.Types.Common (Id, Parties) +import Daml.Finance.Interface.Types.Common (AccountKey, Id, Parties) type T = Fund +instance Fund.HasImplementation Fund + template Fund with operator : Party @@ -26,8 +30,8 @@ template Fund description : Text instrument : Instrument.K currency : Instrument.K - custodianCashAccount : Account.K - managerFundAccount : Account.K + custodianCashAccount : AccountKey + managerFundAccount : AccountKey totalUnits : Decimal observers : Parties where @@ -37,36 +41,29 @@ template Fund key (operator, custodian, id) : (Party, Party, Id) maintainer key._1 - nonconsuming choice GetFund : Fund - with - actor : Party - controller actor - do - pure this - - choice IssueUnits : (ContractId Issuance.I, ContractId Transferable.I, ContractId Fund) - with - requestId : Id - quantity : Instrument.Q - issuanceServiceCid : ContractId IssuanceService.I - controller manager - do + interface instance Removable.I for Fund where + view = Removable.View with removers = fromList [operator, custodian, manager] + + interface instance Fund.I for Fund where + view = Fund.View with operator; custodian; manager; id; description; instrument; currency; custodianCashAccount; managerFundAccount; totalUnits; observers + + asRemovable = toInterface @Removable.I this + + issueUnits Fund.IssueUnits{requestId; quantity; issuanceServiceCid} = do issuanceService <- view . IssuanceService.asBase <$> fetch issuanceServiceCid issuanceService.operator === operator issuanceService.provider === custodian issuanceService.customer === manager issueRequestCid <- exercise issuanceServiceCid IssuanceService.RequestIssue with issuanceId = requestId; description = "Issuance for request " <> show requestId; quantity; account = managerFundAccount (iss, holdingCid) <- exercise issuanceServiceCid IssuanceService.Issue with issueRequestCid - newCid <- create this with totalUnits = totalUnits + quantity.amount + newCid <- toInterfaceContractId <$> create this with totalUnits = totalUnits + quantity.amount pure (iss, coerceContractId holdingCid, newCid) - nonconsuming choice ApproveInstruction : ContractId Instruction.I - with - instructionCid : ContractId Instruction.I - controller manager - do + approveInstruction Fund.ApproveInstruction{instructionCid} = do + -- TODO: Assert instruction is the correct one exercise instructionCid Instruction.Approve with actors = singleton manager; approval = TakeDelivery custodianCashAccount +instance PooledInvestmentRequest.HasImplementation PooledInvestmentRequest template PooledInvestmentRequest with @@ -78,11 +75,16 @@ template PooledInvestmentRequest fundId : Id quantity : Instrument.Q cashCid : ContractId Transferable.I - investmentRequestCids : [ContractId InvestmentRequest] + investmentRequestCids : [ContractId InvestmentRequest.I] customerFundAccount : Account.K where signatory operator, provider, customer - choice Remove : () - controller provider - do pure () + interface instance Removable.I for PooledInvestmentRequest where + view = Removable.View with removers = fromList [operator, provider, customer] + + interface instance PooledInvestmentRequest.I for PooledInvestmentRequest where + view = PooledInvestmentRequest.View with operator; provider; customer; requestId; asOfDate; fundId; quantity; cashCid; investmentRequestCids; customerFundAccount + + asRemovable = toInterface @Removable.I this + diff --git a/src/daml/Daml/Finance/App/Distribution/Fund/Service.daml b/src/daml/Daml/Finance/App/Distribution/Fund/Service.daml index 68f10788..084858d8 100644 --- a/src/daml/Daml/Finance/App/Distribution/Fund/Service.daml +++ b/src/daml/Daml/Finance/App/Distribution/Fund/Service.daml @@ -10,21 +10,24 @@ import DA.Optional (fromSome) import DA.Set (singleton) import DA.Time (time) import Daml.Finance.App.Data.AccountDirectory (AccountDirectory) -import Daml.Finance.App.Distribution.Fund.Model qualified as Fund (ApproveInstruction(..), GetFund(..), IssueUnits(..), PooledInvestmentRequest(..), Remove(..), T) -import Daml.Finance.App.Distribution.Investment.Model (AllocateInstruction(..), ApproveInstruction(..), Delete(..), InvestmentRequest(..)) -import Daml.Finance.App.Interface.Issuance.Service qualified as IssuanceService (I) -import Daml.Finance.Interface.Data.NumericObservable qualified as NumericObservable (I, Observe(..)) -import Daml.Finance.Interface.Holding.Base qualified as Holding (I) +import Daml.Finance.App.Distribution.Fund.Model qualified as Model (PooledInvestmentRequest(..)) +import Daml.Finance.App.Interface.Common.Removable qualified as Removable (I, Remove(..)) +import Daml.Finance.App.Interface.Base.Service qualified as Base (I, View(..)) +import Daml.Finance.App.Interface.Distribution.Fund.Fund qualified as Fund (ApproveInstruction(..), GetView(..), IssueUnits(..)) +import Daml.Finance.App.Interface.Distribution.Fund.Service qualified as Service (FulfillPooledInvestmentRequest(..), HasImplementation, I, PoolInvestmentRequests(..), View(..)) +import Daml.Finance.App.Interface.Distribution.Investment.InvestmentRequest qualified as InvestmentRequest (AllocateInstruction(..), ApproveInstruction(..)) +import Daml.Finance.Interface.Data.NumericObservable qualified as NumericObservable (Observe(..)) import Daml.Finance.Interface.Holding.Transferable qualified as Transferable (I) import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (qty) import Daml.Finance.Interface.Settlement.Batch qualified as Batch (Settle(..)) -import Daml.Finance.Interface.Settlement.Factory qualified as Settlement (Factory, Instruct(..)) +import Daml.Finance.Interface.Settlement.Factory qualified as Settlement (Instruct(..)) import Daml.Finance.Interface.Settlement.Instruction qualified as Instruction (Allocate(..), Approve(..)) import Daml.Finance.Interface.Settlement.Types (Allocation(..), Approval(..), Step(..)) -import Daml.Finance.Interface.Types.Common (Id) import Daml.Finance.Interface.Util.Disclosure qualified as Disclosure (AddObservers(..), I) -type S = Service +type T = Service + +instance Service.HasImplementation Service template Service with @@ -37,17 +40,19 @@ template Service key (operator, provider, customer) : (Party, Party, Party) maintainer key._1 - nonconsuming choice PoolInvestmentRequests : ContractId Fund.PooledInvestmentRequest - with - requestId : Id - asOfDate : Date - fundCid : ContractId Fund.T - cashCid : ContractId Transferable.I - investmentRequestCids : [ContractId InvestmentRequest] - controller customer - do - fund <- exercise fundCid Fund.GetFund with actor = customer - irs <- mapA fetch investmentRequestCids + interface instance Base.I for Service where + view = Base.View with operator; provider; customer + + terminate = pure () + + interface instance Service.I for Service where + view = Service.View + + asBase = toInterface @Base.I this + + poolInvestmentRequests Service.PoolInvestmentRequests{requestId; asOfDate; fundCid; cashCid; investmentRequestCids} = do + fund <- exercise fundCid Fund.GetView with actor = customer + irs <- mapA (\cid -> view <$> fetch cid) investmentRequestCids (_, dir) <- fetchByKey @AccountDirectory customer -- Disclose cash to provider @@ -62,19 +67,11 @@ template Service total = sum $ map (.quantity.amount) irs quantity = Instrument.qty total currency customerFundAccount = fromSome $ M.lookup fund.instrument.id dir.accounts - create Fund.PooledInvestmentRequest with operator; provider; customer; requestId; asOfDate; fundId; quantity; cashCid; investmentRequestCids; customerFundAccount + toInterfaceContractId <$> create Model.PooledInvestmentRequest with operator; provider; customer; requestId; asOfDate; fundId; quantity; cashCid; investmentRequestCids; customerFundAccount - nonconsuming choice FulfillPooledInvestmentRequest : [ContractId Holding.I] - with - pooledInvestmentRequestCid : ContractId Fund.PooledInvestmentRequest - fundCid : ContractId Fund.T - navObservableCid : ContractId NumericObservable.I - settlementFactoryCid : ContractId Settlement.Factory - issuanceServiceCid : ContractId IssuanceService.I - controller provider - do - pir <- fetch pooledInvestmentRequestCid - fund <- fetch fundCid + fulfillPooledInvestmentRequest Service.FulfillPooledInvestmentRequest{pooledInvestmentRequestCid; fundCid; navObservableCid; settlementFactoryCid; issuanceServiceCid} = do + pir <- view <$> fetch pooledInvestmentRequestCid + fund <- view <$> fetch fundCid -- Calculate nr of units to issue nav <- exercise navObservableCid NumericObservable.Observe with actors = singleton customer; t = time pir.asOfDate 0 0 0 @@ -87,7 +84,7 @@ template Service (_, fundUnitsCid, fundCid) <- exercise fundCid Fund.IssueUnits with requestId = pir.requestId; quantity = fundQty; issuanceServiceCid -- Instruct settlement - irs <- mapA fetch pir.investmentRequestCids + irs <- mapA (\cid -> view <$> fetch cid) pir.investmentRequestCids let createInvestorCashStep ir = Step with sender = ir.customer; receiver = ir.provider; quantity = ir.quantity createInvestorFundStep ir = Step with sender = ir.provider; receiver = ir.customer; quantity = Instrument.qty (ir.quantity.amount / unitValue) fund.instrument @@ -111,26 +108,18 @@ template Service -- Allocate and approve investor instructions let processCash (irCid, iCid) = do - iCid <- exercise irCid AllocateInstruction with instructionCid = iCid + iCid <- exercise irCid InvestmentRequest.AllocateInstruction with instructionCid = iCid exercise iCid Instruction.Approve with actors = singleton provider; approval = DebitSender processFund (irCid, iCid) = do (iCid, _) <- exercise iCid Instruction.Allocate with actors = singleton provider; allocation = CreditReceiver - exercise irCid ApproveInstruction with instructionCid = iCid + exercise irCid InvestmentRequest.ApproveInstruction with instructionCid = iCid mapA_ processCash reqInstCash mapA_ processFund reqInstFund - mapA_ (\cid -> exercise cid Delete) pir.investmentRequestCids - exercise pooledInvestmentRequestCid Fund.Remove + mapA_ (\cid -> exercise (toInterfaceContractId @Removable.I cid) Removable.Remove) pir.investmentRequestCids + exercise (toInterfaceContractId @Removable.I pooledInvestmentRequestCid) Removable.Remove exercise batchCid Batch.Settle with actors = singleton provider - choice Terminate : () - with - actor : Party - controller actor - do - assert $ actor == operator || actor == provider || actor == customer - pure () - template Offer with operator : Party diff --git a/src/daml/Daml/Finance/App/Distribution/Investment/Model.daml b/src/daml/Daml/Finance/App/Distribution/Investment/Model.daml index ebe1e904..e8ec281b 100644 --- a/src/daml/Daml/Finance/App/Distribution/Investment/Model.daml +++ b/src/daml/Daml/Finance/App/Distribution/Investment/Model.daml @@ -3,14 +3,18 @@ module Daml.Finance.App.Distribution.Investment.Model where -import DA.Set (singleton) +import DA.Set (fromList, singleton) +import Daml.Finance.App.Interface.Common.Removable qualified as Removable (I, View(..)) +import Daml.Finance.App.Interface.Distribution.Investment.InvestmentRequest qualified as InvestmentRequest (AllocateInstruction(..), ApproveInstruction(..), HasImplementation, I, View(..)) import Daml.Finance.Interface.Account.Account qualified as Account (K) import Daml.Finance.Interface.Holding.Transferable qualified as Transferable (I) import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (Q) -import Daml.Finance.Interface.Settlement.Instruction qualified as Instruction (Allocate(..), Approve(..), I) +import Daml.Finance.Interface.Settlement.Instruction qualified as Instruction (Allocate(..), Approve(..)) import Daml.Finance.Interface.Settlement.Types (Allocation(Pledge), Approval(TakeDelivery)) import Daml.Finance.Interface.Types.Common (Id) +instance InvestmentRequest.HasImplementation InvestmentRequest + template InvestmentRequest with operator : Party @@ -27,20 +31,16 @@ template InvestmentRequest signatory operator, provider, customer observer manager - nonconsuming choice AllocateInstruction : ContractId Instruction.I - with - instructionCid : ContractId Instruction.I - controller manager - do - fst <$> exercise instructionCid Instruction.Allocate with actors = singleton manager; allocation = Pledge $ toInterfaceContractId cashCid + interface instance Removable.I for InvestmentRequest where + view = Removable.View with removers = fromList [operator, provider, customer] + + interface instance InvestmentRequest.I for InvestmentRequest where + view = InvestmentRequest.View with operator; provider; customer; manager; requestId; asOfDate; fundId; quantity; cashCid; customerFundAccount - nonconsuming choice ApproveInstruction : ContractId Instruction.I - with - instructionCid : ContractId Instruction.I - controller manager - do - exercise instructionCid Instruction.Approve with actors = singleton manager; approval = TakeDelivery customerFundAccount + asRemovable = toInterface @Removable.I this + + allocateInstruction InvestmentRequest.AllocateInstruction{instructionCid} = do + fst <$> exercise instructionCid Instruction.Allocate with actors = singleton manager; allocation = Pledge $ toInterfaceContractId cashCid - choice Delete : () - controller manager - do pure () + approveInstruction InvestmentRequest.ApproveInstruction{instructionCid} = do + exercise instructionCid Instruction.Approve with actors = singleton manager; approval = TakeDelivery customerFundAccount diff --git a/src/daml/Daml/Finance/App/Distribution/Investment/Service.daml b/src/daml/Daml/Finance/App/Distribution/Investment/Service.daml index e7a9678b..a03176ed 100644 --- a/src/daml/Daml/Finance/App/Distribution/Investment/Service.daml +++ b/src/daml/Daml/Finance/App/Distribution/Investment/Service.daml @@ -7,16 +7,18 @@ import DA.Map qualified as M (lookup) import DA.Optional (fromSome) import DA.Set (singleton) import Daml.Finance.App.Data.AccountDirectory (AccountDirectory) -import Daml.Finance.App.Distribution.Fund.Model (GetFund(..), Fund) import Daml.Finance.App.Distribution.Investment.Model (InvestmentRequest(..)) +import Daml.Finance.App.Interface.Base.Service qualified as Base (I, View(..)) +import Daml.Finance.App.Interface.Distribution.Fund.Fund qualified as Fund (GetView(..)) +import Daml.Finance.App.Interface.Distribution.Investment.Service qualified as Service (HasImplementation, I, RequestInvestment(..), View(..)) import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (qty) import Daml.Finance.Interface.Holding.Transferable qualified as Transferable (I) --- import Daml.Finance.Interface.Holding.Lockable qualified as Lockable (Acquire(..), I, LockType(..)) import Daml.Finance.Interface.Holding.Util (getAmount, getInstrument) -import Daml.Finance.Interface.Types.Common (Id) import Daml.Finance.Interface.Util.Disclosure qualified as Disclosure (AddObservers(..), I) -type S = Service +type T = Service + +instance Service.HasImplementation Service template Service with @@ -29,17 +31,19 @@ template Service key (operator, provider, customer) : (Party, Party, Party) maintainer key._1 - nonconsuming choice RequestInvestment : ContractId InvestmentRequest - with - requestId : Id - asOfDate : Date - fundCid : ContractId Fund - cashCid : ContractId Transferable.I - controller customer - do + interface instance Base.I for Service where + view = Base.View with operator; provider; customer + + terminate = pure () + interface instance Service.I for Service where + view = Service.View + + asBase = toInterface @Base.I this + + requestInvestment Service.RequestInvestment{requestId; asOfDate; fundCid; cashCid} = do -- Disclose holding - fund <- exercise fundCid GetFund with actor = customer + fund <- exercise fundCid Fund.GetView with actor = customer cashCid : ContractId Transferable.I <- coerceContractId <$> exercise (coerceContractId cashCid : ContractId Disclosure.I) Disclosure.AddObservers with disclosers = singleton customer; observersToAdd = (show requestId, singleton fund.manager) cash <- fetch cashCid @@ -47,15 +51,7 @@ template Service let quantity = Instrument.qty (getAmount cash) (getInstrument cash) customerFundAccount = fromSome $ M.lookup fund.instrument.id dir.accounts - create InvestmentRequest with operator; provider; customer; manager = fund.manager; requestId; asOfDate; quantity; fundId = fund.id; cashCid = toInterfaceContractId cashCid; customerFundAccount - - choice Terminate : () - with - actor : Party - controller actor - do - assert $ actor == operator || actor == provider || actor == customer - pure () + toInterfaceContractId <$> create InvestmentRequest with operator; provider; customer; manager = fund.manager; requestId; asOfDate; quantity; fundId = fund.id; cashCid = toInterfaceContractId cashCid; customerFundAccount template Offer with diff --git a/src/daml/Daml/Finance/App/Distribution/Subscription/Model.daml b/src/daml/Daml/Finance/App/Distribution/Subscription/Model.daml index 62ec5d99..80786cf9 100644 --- a/src/daml/Daml/Finance/App/Distribution/Subscription/Model.daml +++ b/src/daml/Daml/Finance/App/Distribution/Subscription/Model.daml @@ -4,30 +4,21 @@ module Daml.Finance.App.Distribution.Subscription.Model where import DA.Set (fromList, singleton) +import Daml.Finance.App.Interface.Common.Removable qualified as Removable (I, View(..)) +import Daml.Finance.App.Interface.Distribution.Subscription.Offering qualified as Offering (HasImplementation, I, Subscribe(..), View(..)) +import Daml.Finance.App.Interface.Distribution.Subscription.Subscription qualified as Subscription (AllocateInstruction(..), ApproveInstruction(..), HasImplementation, I, UnlockHolding(..), View(..)) +import Daml.Finance.App.Interface.Distribution.Subscription.Types (BackToBack, Status) import Daml.Finance.Interface.Account.Account qualified as Account (K, R) import Daml.Finance.Interface.Holding.Fungible qualified as Fungible (I) import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (Q) import Daml.Finance.Interface.Holding.Base qualified as Holding (Acquire(..), I, LockType(..), Release(..)) -import Daml.Finance.Interface.Holding.Transferable qualified as Transferable (I) import Daml.Finance.Interface.Account.Util (getAccount) import Daml.Finance.Interface.Util.Disclosure qualified as Disclosure (AddObservers(..), I) -import Daml.Finance.Interface.Settlement.Instruction qualified as Instruction (Allocate(..), Approve(..), I) +import Daml.Finance.Interface.Settlement.Instruction qualified as Instruction (Allocate(..), Approve(..)) import Daml.Finance.Interface.Settlement.Types (Allocation(Pledge), Approval(TakeDelivery)) +import Daml.Finance.Interface.Types.Common (AccountKey, Id) -data Status - = Open - | Closed - deriving (Eq, Show) - -data BackToBack = BackToBack - with - party : Party - offeringId : Text - issuerReceivableAccount : Account.K - issuerDeliverableCid : ContractId Fungible.I - b2bReceivableAccount : Account.K - b2bDeliverableCid : ContractId Fungible.I - deriving (Eq, Show) +instance Offering.HasImplementation Offering template Offering with @@ -35,7 +26,8 @@ template Offering provider : Party issuer : Party public : Party - offeringId : Text + id : Id + description : Text asset : Instrument.Q price : Instrument.Q issuerHoldingCid : ContractId Fungible.I @@ -46,30 +38,33 @@ template Offering signatory operator, provider, issuer observer public - key (provider, offeringId) : (Party, Text) + key (operator, provider, id) : (Party, Party, Id) maintainer key._1 - nonconsuming choice Subscribe : ContractId Subscription - with - investor : Party - quantity : Decimal - investorHoldingCid : ContractId Fungible.I - investorAccount : Account.K - controller investor - do - -- Disclose holding - investorHolding <- fetch investorHoldingCid - investorHoldingCid : ContractId Fungible.I <- coerceContractId <$> exercise (coerceContractId investorHoldingCid : ContractId Disclosure.I) Disclosure.AddObservers with disclosers = singleton investor; observersToAdd = (offeringId, singleton issuer) - -- Disclose delivering securities account - let investorSendingAccount = getAccount investorHolding - (_, delRef) <- fetchByKey @Account.R investorSendingAccount - exercise (coerceContractId delRef.cid : ContractId Disclosure.I) Disclosure.AddObservers with disclosers = singleton investor; observersToAdd = (offeringId, singleton issuer) - -- Disclose receiving cash account - (_, recRef) <- fetchByKey @Account.R investorAccount - exercise (coerceContractId recRef.cid : ContractId Disclosure.I) Disclosure.AddObservers with disclosers = singleton investor; observersToAdd = (offeringId, singleton issuer) - -- Lock holding - investorHoldingCid <- coerceContractId <$> exercise (toInterfaceContractId investorHoldingCid : ContractId Holding.I) Holding.Acquire with newLockers = singleton issuer; context = offeringId; lockType = Holding.Semaphore - create Subscription with holdingCid = investorHoldingCid; accountKey = investorAccount; .. + interface instance Removable.I for Offering where + view = Removable.View with removers = fromList [operator, provider, issuer] + + interface instance Offering.I for Offering where + view = Offering.View with operator; provider; issuer; public; id; description; asset; price; issuerHoldingCid; issuerAccount; backToBack; status + + asRemovable = toInterface @Removable.I this + + subscribe Offering.Subscribe{investor; quantity; investorHoldingCid; investorAccount} = do + -- Disclose holding + investorHolding <- fetch investorHoldingCid + investorHoldingCid : ContractId Fungible.I <- coerceContractId <$> exercise (coerceContractId investorHoldingCid : ContractId Disclosure.I) Disclosure.AddObservers with disclosers = singleton investor; observersToAdd = (show id, singleton issuer) + -- Disclose delivering securities account + let investorSendingAccount = getAccount investorHolding + (_, delRef) <- fetchByKey @Account.R investorSendingAccount + exercise (coerceContractId delRef.cid : ContractId Disclosure.I) Disclosure.AddObservers with disclosers = singleton investor; observersToAdd = (show id, singleton issuer) + -- Disclose receiving cash account + (_, recRef) <- fetchByKey @Account.R investorAccount + exercise (coerceContractId recRef.cid : ContractId Disclosure.I) Disclosure.AddObservers with disclosers = singleton investor; observersToAdd = (show id, singleton issuer) + -- Lock holding + investorHoldingCid <- coerceContractId <$> exercise (toInterfaceContractId investorHoldingCid : ContractId Holding.I) Holding.Acquire with newLockers = singleton issuer; context = show id; lockType = Holding.Semaphore + toInterfaceContractId <$> create Subscription with operator; provider; issuer; investor; offeringId = id; quantity; holdingCid = investorHoldingCid; account = investorAccount + +instance Subscription.HasImplementation Subscription template Subscription with @@ -77,32 +72,26 @@ template Subscription provider : Party issuer : Party investor : Party - offeringId : Text + offeringId : Id quantity : Decimal holdingCid : ContractId Fungible.I - accountKey : Account.K + account : AccountKey where signatory operator, provider, issuer, investor - nonconsuming choice ApproveInstruction : ContractId Instruction.I - with - instructionCid : ContractId Instruction.I - receiverAccount : Account.K - controller provider - do - exercise instructionCid Instruction.Approve with actors = fromList [provider, investor]; approval = TakeDelivery receiverAccount + interface instance Removable.I for Subscription where + view = Removable.View with removers = fromList [operator, provider, issuer] + + interface instance Subscription.I for Subscription where + view = Subscription.View with operator; provider; issuer; investor; offeringId; quantity; holdingCid; account + + asRemovable = toInterface @Removable.I this - nonconsuming choice AllocateInstruction : ContractId Instruction.I - with - instructionCid : ContractId Instruction.I - transferableCid : ContractId Transferable.I - controller provider - do + allocateInstruction Subscription.AllocateInstruction{instructionCid; transferableCid} = do fst <$> exercise instructionCid Instruction.Allocate with actors = fromList [provider, investor]; allocation = Pledge $ toInterfaceContractId transferableCid - nonconsuming choice UnlockHolding : ContractId Holding.I - with - lockableCid : ContractId Holding.I - controller provider - do - exercise lockableCid Holding.Release with context = offeringId + approveInstruction Subscription.ApproveInstruction{instructionCid; receiverAccount} = do + exercise instructionCid Instruction.Approve with actors = fromList [provider, investor]; approval = TakeDelivery receiverAccount + + unlockHolding Subscription.UnlockHolding{lockableCid} = do + exercise lockableCid Holding.Release with context = show offeringId diff --git a/src/daml/Daml/Finance/App/Distribution/Subscription/Service.daml b/src/daml/Daml/Finance/App/Distribution/Subscription/Service.daml index 11f3a408..f07eb021 100644 --- a/src/daml/Daml/Finance/App/Distribution/Subscription/Service.daml +++ b/src/daml/Daml/Finance/App/Distribution/Subscription/Service.daml @@ -6,16 +6,22 @@ module Daml.Finance.App.Distribution.Subscription.Service where import DA.Action (foldlA) import DA.Optional (whenSome) import DA.Set (fromList, singleton) -import Daml.Finance.App.BackToBack.Service qualified as BackToBack -import Daml.Finance.App.Distribution.Subscription.Model (BackToBack, Offering(..), Status(..), Subscription) +import Daml.Finance.App.Distribution.Subscription.Model qualified as Model (Offering(..)) import Daml.Finance.App.Distribution.Subscription.Util (settleSubscription) +import Daml.Finance.App.Interface.Base.Service qualified as Base (I, View(..)) +import Daml.Finance.App.Interface.Distribution.Subscription.Types (Status(..)) +import Daml.Finance.App.Interface.Distribution.Subscription.Service qualified as Service (CreateOffering(..), HasImplementation, I, ProcessOffering(..), View(..)) +import Daml.Finance.App.Interface.Issuance.BackToBack qualified as BackToBack (I, LockOffering(..), SettleOffering(..)) +import Daml.Finance.App.Issuance.BackToBack qualified as BackToBack (T) import Daml.Finance.Interface.Util.Disclosure qualified as Disclosure (AddObservers(..), I) -import Daml.Finance.Interface.Account.Account qualified as Account (K, R) +import Daml.Finance.Interface.Account.Account qualified as Account (R) import Daml.Finance.Interface.Holding.Base qualified as Holding (Acquire(..), I, LockType(..), Release(..)) import Daml.Finance.Interface.Holding.Fungible qualified as Fungible (I) -import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (Q) import Daml.Finance.Interface.Account.Util (getAccount) -import Daml.Finance.Interface.Settlement.Factory qualified as Factory (I) + +type T = Service + +instance Service.HasImplementation Service template Service with @@ -29,61 +35,61 @@ template Service key (operator, provider, customer) : (Party, Party, Party) maintainer key._1 - nonconsuming choice CreateOffering : ContractId Offering - with - offeringId : Text - asset : Instrument.Q - price : Instrument.Q - customerHoldingCid : ContractId Fungible.I - customerAccount : Account.K - backToBack : Optional BackToBack - controller customer - do + interface instance Base.I for Service where + view = Base.View with operator; provider; customer + + terminate = pure () + + interface instance Service.I for Service where + view = Service.View + + asBase = toInterface @Base.I this + + createOffering Service.CreateOffering{offeringId; description; asset; price; customerHoldingCid; customerAccount; backToBack} = do -- Disclose holding customerHolding <- fetch customerHoldingCid - customerHoldingCid : ContractId Fungible.I <- coerceContractId <$> exercise (coerceContractId customerHoldingCid : ContractId Disclosure.I) Disclosure.AddObservers with disclosers = singleton customer; observersToAdd = (offeringId, singleton provider) + customerHoldingCid : ContractId Fungible.I <- coerceContractId <$> exercise (coerceContractId customerHoldingCid : ContractId Disclosure.I) Disclosure.AddObservers with disclosers = singleton customer; observersToAdd = (show offeringId, singleton provider) -- Disclose delivering securities account let customerSendingAccount = getAccount customerHolding (_, delRef) <- fetchByKey @Account.R customerSendingAccount - exercise (coerceContractId delRef.cid : ContractId Disclosure.I) Disclosure.AddObservers with disclosers = singleton customer; observersToAdd = (offeringId, singleton provider) + exercise (coerceContractId delRef.cid : ContractId Disclosure.I) Disclosure.AddObservers with disclosers = singleton customer; observersToAdd = (show offeringId, singleton provider) -- Disclose receiving cash account (_, recRef) <- fetchByKey @Account.R customerAccount - exercise (coerceContractId recRef.cid : ContractId Disclosure.I) Disclosure.AddObservers with disclosers = singleton customer; observersToAdd = (offeringId, singleton provider) + exercise (coerceContractId recRef.cid : ContractId Disclosure.I) Disclosure.AddObservers with disclosers = singleton customer; observersToAdd = (show offeringId, singleton provider) -- Lock holding - customerHoldingCid <- coerceContractId <$> exercise (toInterfaceContractId customerHoldingCid : ContractId Holding.I) Holding.Acquire with newLockers = fromList [ provider ]; context = offeringId; lockType = Holding.Semaphore + customerHoldingCid <- coerceContractId <$> exercise (toInterfaceContractId customerHoldingCid : ContractId Holding.I) Holding.Acquire with newLockers = fromList [ provider ]; context = show offeringId; lockType = Holding.Semaphore -- Lock back-to-back assets lockedB2b <- case backToBack of - Some b2b -> do Some <$> exerciseByKey @BackToBack.Service (operator, b2b.party, customer) BackToBack.LockOffering with backToBack = b2b + Some b2b -> do + (serviceCid, _) <- fetchByKey @BackToBack.T (operator, b2b.party, customer) + Some <$> exercise (toInterfaceContractId @BackToBack.I serviceCid) BackToBack.LockOffering with backToBack = b2b None -> pure None - create Offering + toInterfaceContractId <$> create Model.Offering with - operator; provider; public; asset; price; offeringId + operator; provider; public; asset; price + id = offeringId + description issuer = customer issuerHoldingCid = customerHoldingCid issuerAccount = customerAccount backToBack = lockedB2b status = Open - nonconsuming choice ProcessOffering : ContractId Offering - with - settlementFactoryCid : ContractId Factory.I - offeringCid : ContractId Offering - subscriptionCids : [ContractId Subscription] - controller provider - do + processOffering Service.ProcessOffering{settlementFactoryCid; offeringCid; subscriptionCids} = do -- Settle subscriptions - offering <- fetch offeringCid - subscriptions <- zip subscriptionCids <$> forA subscriptionCids fetch + offeringI <- fetch offeringCid + let offering = view offeringI + subscriptions <- zip subscriptionCids <$> forA subscriptionCids (\cid -> view <$> fetch cid) (remainingIssuerQuantity, remainingIssuerHoldingCidOpt) <- foldlA (settleSubscription provider settlementFactoryCid offering) (offering.asset.amount, Some offering.issuerHoldingCid) subscriptions -- Settle back-to-back trade whenSome offering.backToBack \b2b -> do - let - totalQuantity = sum $ map ((.quantity) . snd) subscriptions - exerciseByKey @BackToBack.Service (operator, b2b.party, customer) BackToBack.SettleOffering with settlementFactoryCid; offeringCid; totalQuantity + let totalQuantity = sum $ map ((.quantity) . snd) subscriptions + (serviceCid, _) <- fetchByKey @BackToBack.T (operator, b2b.party, customer) + exercise (toInterfaceContractId @BackToBack.I serviceCid) BackToBack.SettleOffering with settlementFactoryCid; offeringCid; totalQuantity pure () -- Archive offer and subscriptions @@ -92,18 +98,11 @@ template Service -- Unlock remaining issuer holding whenSome remainingIssuerHoldingCidOpt \holdingCid -> do - exercise (toInterfaceContractId holdingCid : ContractId Holding.I) Holding.Release with context = offering.offeringId + exercise (toInterfaceContractId holdingCid : ContractId Holding.I) Holding.Release with context = show offering.id pure () - create offering with status = Closed - - choice Terminate : () - with - actor : Party - controller actor - do - assert $ actor == operator || actor == provider || actor == customer - pure () + let Some offeringT = fromInterface @Model.Offering offeringI + toInterfaceContractId <$> create offeringT with status = Closed template Offer with diff --git a/src/daml/Daml/Finance/App/Distribution/Subscription/Util.daml b/src/daml/Daml/Finance/App/Distribution/Subscription/Util.daml index 9b7797f9..afd1df25 100644 --- a/src/daml/Daml/Finance/App/Distribution/Subscription/Util.daml +++ b/src/daml/Daml/Finance/App/Distribution/Subscription/Util.daml @@ -7,18 +7,18 @@ import DA.Foldable (forA_) import DA.Functor (void) import DA.Optional (optionalToList) import DA.Set (singleton) +import Daml.Finance.App.Interface.Distribution.Subscription.Offering qualified as Offering (View) +import Daml.Finance.App.Interface.Distribution.Subscription.Subscription qualified as Subscription (AllocateInstruction(..), ApproveInstruction(..), I, UnlockHolding(..), View) import Daml.Finance.Interface.Account.Account qualified as Account (R) import Daml.Finance.Interface.Holding.Base qualified as Holding (I, Release(..)) import Daml.Finance.Interface.Holding.Fungible qualified as Fungible (I, Split(..)) import Daml.Finance.Interface.Util.Disclosure qualified as Disclosure (I, RemoveObservers(..)) -import Daml.Finance.Interface.Settlement.Factory (Factory, Instruct(..)) +import Daml.Finance.Interface.Settlement.Factory qualified as Factory (I, Instruct(..)) import Daml.Finance.Interface.Settlement.Instruction (Allocate(..), Approve(..)) import Daml.Finance.Interface.Settlement.Batch (Settle(..)) import Daml.Finance.Interface.Settlement.Types (Allocation(Pledge), Approval(TakeDelivery), Step(..)) -import Daml.Finance.App.Distribution.Subscription.Model (AllocateInstruction(..), ApproveInstruction(..), Offering, Subscription, UnlockHolding(..)) -import Daml.Finance.Interface.Types.Common (Id(..)) -settleSubscription : Party -> ContractId Factory -> Offering -> (Decimal, Optional (ContractId Fungible.I)) -> (ContractId Subscription, Subscription) -> Update (Decimal, Optional (ContractId Fungible.I)) +settleSubscription : Party -> ContractId Factory.I -> Offering.View -> (Decimal, Optional (ContractId Fungible.I)) -> (ContractId Subscription.I, Subscription.View) -> Update (Decimal, Optional (ContractId Fungible.I)) settleSubscription actor settlementFactoryCid offering (remainingQuantity, issuerHoldingCidOpt) (subscriptionCid, subscription) = do if remainingQuantity == 0.0 then do pure (remainingQuantity, issuerHoldingCidOpt) @@ -30,7 +30,7 @@ settleSubscription actor settlementFactoryCid offering (remainingQuantity, issue payedQuantity = offering.price with amount = allocatedQuantity.amount * offering.price.amount delivery = Step with sender = offering.issuer; receiver = subscription.investor; quantity = allocatedQuantity payment = Step with sender = subscription.investor; receiver = offering.issuer; quantity = payedQuantity - (batchCid, [deliveryCid, paymentCid]) <- exercise settlementFactoryCid Instruct with instructors = singleton offering.provider; settlers = singleton offering.provider; id = Id offering.offeringId; description = offering.offeringId; contextId = None; steps = [delivery, payment] + (batchCid, [deliveryCid, paymentCid]) <- exercise settlementFactoryCid Factory.Instruct with instructors = singleton offering.provider; settlers = singleton offering.provider; id = offering.id; description = show offering.id; contextId = None; steps = [delivery, payment] -- Settle allocatedHoldingCid :: remainingIssuerHoldingCids <- @@ -44,11 +44,11 @@ settleSubscription actor settlementFactoryCid offering (remainingQuantity, issue -- paymentHolding <- fetch paymentHoldingCid -- paymentAccountCid <- getAccountCid paymentHolding deliveryCid <- fst <$> exercise deliveryCid Allocate with actors = singleton actor; allocation = Pledge $ toInterfaceContractId allocatedHoldingCid - exercise subscriptionCid ApproveInstruction with instructionCid = deliveryCid; receiverAccount = subscription.accountKey - paymentCid <- exercise subscriptionCid AllocateInstruction with instructionCid = paymentCid; transferableCid = toInterfaceContractId paymentHoldingCid + exercise subscriptionCid Subscription.ApproveInstruction with instructionCid = deliveryCid; receiverAccount = subscription.account + paymentCid <- exercise subscriptionCid Subscription.AllocateInstruction with instructionCid = paymentCid; transferableCid = toInterfaceContractId paymentHoldingCid exercise paymentCid Approve with actors = singleton actor; approval = TakeDelivery offering.issuerAccount transferredCids <- exercise batchCid Settle with actors = singleton actor - forA_ transferredCids $ \cid -> exercise subscriptionCid UnlockHolding with lockableCid = toInterfaceContractId cid + forA_ transferredCids $ \cid -> exercise subscriptionCid Subscription.UnlockHolding with lockableCid = toInterfaceContractId cid -- Process remainders let @@ -58,11 +58,11 @@ settleSubscription actor settlementFactoryCid offering (remainingQuantity, issue hCid :: _ -> Some hCid case remainingInvestorHoldingCids of [] -> do pure () - hCid :: _ -> do void $ exercise (coerceContractId hCid : ContractId Holding.I) Holding.Release with context = offering.offeringId + hCid :: _ -> do void $ exercise (coerceContractId hCid : ContractId Holding.I) Holding.Release with context = show offering.id -- Undisclose accounts (doesn't quite work) - (_, accountProxy) <- fetchByKey @Account.R subscription.accountKey - exercise (coerceContractId accountProxy.cid : ContractId Disclosure.I) Disclosure.RemoveObservers with disclosers = singleton actor; observersToRemove = (offering.offeringId, singleton offering.issuer) + (_, accountProxy) <- fetchByKey @Account.R subscription.account + exercise (coerceContractId accountProxy.cid : ContractId Disclosure.I) Disclosure.RemoveObservers with disclosers = singleton actor; observersToRemove = (show offering.id, singleton offering.issuer) -- exercise paymentAccountCid RemoveObserver with observerToRemove = (offering.offeringId, singleton offering.issuer) pure (max 0.0 $ remainingQuantity - subscription.quantity, remainingIssuerHoldingCid) diff --git a/src/daml/Daml/Finance/App/Interface/Custody/Auto.daml b/src/daml/Daml/Finance/App/Interface/Custody/Auto.daml index 6d2ab863..246d0ea1 100644 --- a/src/daml/Daml/Finance/App/Interface/Custody/Auto.daml +++ b/src/daml/Daml/Finance/App/Interface/Custody/Auto.daml @@ -4,7 +4,6 @@ module Daml.Finance.App.Interface.Custody.Auto where import Daml.Finance.App.Interface.Base.Service qualified as Base (I) -import Daml.Finance.App.Interface.Custody.Service qualified as Service (I, Implementation, asBase) import Daml.Finance.Interface.Account.Account qualified as Account (Controllers, I) import Daml.Finance.Interface.Holding.Base qualified as Holding (I) import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (K, Q) @@ -20,15 +19,15 @@ data View = View {} interface Service where viewtype V - asService : Service.I - -- ^ Conversion to custody `Service` interface. - requestAndOpenAccount : ContractId Service.I -> RequestAndOpenAccount -> Update (ContractId Account.I, AccountKey) + asBase : Base.I + -- ^ Conversion to base `Service` interface. + requestAndOpenAccount : RequestAndOpenAccount -> Update (ContractId Account.I, AccountKey) -- ^ Implementation of the `RequestOpenAccount` choice. - requestAndCloseAccount : ContractId Service.I -> RequestAndCloseAccount -> Update () + requestAndCloseAccount : RequestAndCloseAccount -> Update () -- ^ Implementation of the `RequestCloseAccount` choice. - requestAndDeposit : ContractId Service.I -> RequestAndDeposit -> Update (ContractId Holding.I) + requestAndDeposit : RequestAndDeposit -> Update (ContractId Holding.I) -- ^ Implementation of the `RequestDeposit` choice. - requestAndWithdraw : ContractId Service.I -> RequestAndWithdraw -> Update () + requestAndWithdraw : RequestAndWithdraw -> Update () -- ^ Implementation of the `RequestAndWithdraw` choice. nonconsuming choice RequestAndOpenAccount : (ContractId Account.I, AccountKey) @@ -37,36 +36,35 @@ interface Service where description : Text controllers : Account.Controllers observers : PartiesMap - controller (view $ Service.asBase $ asService this).customer + controller (view $ asBase this).customer do - requestAndOpenAccount this (toInterfaceContractId self) arg + requestAndOpenAccount this arg nonconsuming choice RequestAndCloseAccount : () with account : AccountKey - controller (view $ Service.asBase $ asService this).customer + controller (view $ asBase this).customer do - requestAndCloseAccount this (toInterfaceContractId self) arg + requestAndCloseAccount this arg nonconsuming choice RequestAndDeposit : (ContractId Holding.I) with quantity : Instrument.Q account : AccountKey - controller (view $ Service.asBase $ asService this).customer + controller (view $ asBase this).customer do - requestAndDeposit this (toInterfaceContractId self) arg + requestAndDeposit this arg nonconsuming choice RequestAndWithdraw : () with instrument : Instrument.K holdingCid : ContractId Holding.I - controller (view $ Service.asBase $ asService this).customer + controller (view $ asBase this).customer do - requestAndWithdraw this (toInterfaceContractId self) arg + requestAndWithdraw this arg -- | Type constraint for requiring templates to implement `Service`. -type Implementation t = (HasToInterface t Service, Service.Implementation t) +type Implementation t = HasToInterface t Service class (Implementation t) => HasImplementation t instance HasImplementation Service -instance HasToInterface Service Service.I where _toInterface = asService -instance HasToInterface Service Base.I where _toInterface = Service.asBase . asService +instance HasToInterface Service Base.I where _toInterface = asBase diff --git a/src/daml/Daml/Finance/App/Interface/Custody/Service.daml b/src/daml/Daml/Finance/App/Interface/Custody/Service.daml index 184ceaa1..a15d9f08 100644 --- a/src/daml/Daml/Finance/App/Interface/Custody/Service.daml +++ b/src/daml/Daml/Finance/App/Interface/Custody/Service.daml @@ -32,20 +32,28 @@ interface Service where asBase : Base.I -- ^ Conversion to base `Service` interface. + requestOpenAccount : RequestOpenAccount -> Update (ContractId OpenAccountRequest.I) -- ^ Implementation of the `RequestOpenAccount` choice. + requestCloseAccount : RequestCloseAccount -> Update (ContractId CloseAccountRequest.I) -- ^ Implementation of the `RequestCloseAccount` choice. + requestDeposit : RequestDeposit -> Update (ContractId DepositRequest.I) -- ^ Implementation of the `RequestDeposit` choice. + requestWithdraw : RequestWithdraw -> Update (ContractId WithdrawRequest.I) -- ^ Implementation of the `RequestWithdraw` choice. + openAccount : OpenAccount -> Update (ContractId Account.I, AccountKey) -- ^ Implementation of the `OpenAccount` choice. + closeAccount : CloseAccount -> Update () -- ^ Implementation of the `CloseAccount` choice. + deposit : Deposit -> Update (ContractId Holding.I) -- ^ Implementation of the `Deposit` choice. + withdraw : Withdraw -> Update () -- ^ Implementation of the `Withdraw` choice. diff --git a/src/daml/Daml/Finance/App/Interface/Distribution/Auction/Auction.daml b/src/daml/Daml/Finance/App/Interface/Distribution/Auction/Auction.daml index 55c0766c..b8a906e4 100644 --- a/src/daml/Daml/Finance/App/Interface/Distribution/Auction/Auction.daml +++ b/src/daml/Daml/Finance/App/Interface/Distribution/Auction/Auction.daml @@ -41,6 +41,7 @@ data Status interface Auction where viewtype View -- ^ Interface view type. + asRemovable : Removable.I -- ^ Conversion to the `Removable` interface. @@ -51,7 +52,6 @@ interface Auction where do pure $ view this - -- | Type constraint for requiring templates to implement `Auction`. type Implementation t = (HasToInterface t Auction, Removable.Implementation t) class (Implementation t) => HasImplementation t diff --git a/src/daml/Daml/Finance/App/Interface/Distribution/Auction/Auto.daml b/src/daml/Daml/Finance/App/Interface/Distribution/Auction/Auto.daml index b2748012..eb36cc1d 100644 --- a/src/daml/Daml/Finance/App/Interface/Distribution/Auction/Auto.daml +++ b/src/daml/Daml/Finance/App/Interface/Distribution/Auction/Auto.daml @@ -5,7 +5,6 @@ module Daml.Finance.App.Interface.Distribution.Auction.Auto where import Daml.Finance.App.Interface.Base.Service qualified as Base (I) import Daml.Finance.App.Interface.Distribution.Auction.Auction qualified as Auction (I) -import Daml.Finance.App.Interface.Distribution.Auction.Service qualified as Service (I, Implementation, asBase) import Daml.Finance.Interface.Holding.Fungible qualified as Fungible (I) import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (K, Q) import Daml.Finance.Interface.Types.Common (AccountKey, Id, Parties) @@ -20,9 +19,10 @@ data View = View {} interface Service where viewtype V - asService : Service.I - -- ^ Conversion to custody `Service` interface. - requestAndCreateAuction : ContractId Service.I -> RequestAndCreateAuction -> Update (ContractId Auction.I) + asBase : Base.I + -- ^ Conversion to base `Service` interface. + + requestAndCreateAuction : RequestAndCreateAuction -> Update (ContractId Auction.I) -- ^ Implementation of the `RequestAndCreateAuction` choice. nonconsuming choice RequestAndCreateAuction : (ContractId Auction.I) @@ -35,13 +35,12 @@ interface Service where collateralCid : ContractId Fungible.I receivableAccount : AccountKey observers : Parties - controller (view $ Service.asBase $ asService this).customer + controller (view $ asBase this).customer do - requestAndCreateAuction this (toInterfaceContractId self) arg + requestAndCreateAuction this arg -- | Type constraint for requiring templates to implement `Service`. -type Implementation t = (HasToInterface t Service, Service.Implementation t) +type Implementation t = HasToInterface t Service class (Implementation t) => HasImplementation t instance HasImplementation Service -instance HasToInterface Service Service.I where _toInterface = asService -instance HasToInterface Service Base.I where _toInterface = Service.asBase . asService +instance HasToInterface Service Base.I where _toInterface = asBase diff --git a/src/daml/Daml/Finance/App/Interface/Distribution/Auction/CreateAuctionRequest.daml b/src/daml/Daml/Finance/App/Interface/Distribution/Auction/CreateAuctionRequest.daml index 6da68912..48f5debc 100644 --- a/src/daml/Daml/Finance/App/Interface/Distribution/Auction/CreateAuctionRequest.daml +++ b/src/daml/Daml/Finance/App/Interface/Distribution/Auction/CreateAuctionRequest.daml @@ -30,6 +30,7 @@ data View = View interface CreateAuctionRequest where viewtype View -- ^ Interface view type. + asRemovable : Removable.I -- ^ Conversion to the `Removable` interface. diff --git a/src/daml/Daml/Finance/App/Interface/Distribution/Auction/Service.daml b/src/daml/Daml/Finance/App/Interface/Distribution/Auction/Service.daml index c1ec6d9c..5aca2283 100644 --- a/src/daml/Daml/Finance/App/Interface/Distribution/Auction/Service.daml +++ b/src/daml/Daml/Finance/App/Interface/Distribution/Auction/Service.daml @@ -24,10 +24,13 @@ interface Service where asBase : Base.I -- ^ Conversion to base `Service` interface. + requestCreateAuction : RequestCreateAuction -> Update (ContractId CreateAuctionRequest.I) -- ^ Implementation of the `RequestCreateAuction` choice. + createAuction : CreateAuction -> Update (ContractId Auction.I) -- ^ Implementation of the `CreateAuction` choice. + processAuction : ProcessAuction -> Update (ContractId Auction.I) -- ^ Implementation of the `ProcessAuction` choice. diff --git a/src/daml/Daml/Finance/App/Interface/Distribution/Bidding/Auto.daml b/src/daml/Daml/Finance/App/Interface/Distribution/Bidding/Auto.daml index 3152cf34..d5512ebb 100644 --- a/src/daml/Daml/Finance/App/Interface/Distribution/Bidding/Auto.daml +++ b/src/daml/Daml/Finance/App/Interface/Distribution/Bidding/Auto.daml @@ -6,7 +6,6 @@ module Daml.Finance.App.Interface.Distribution.Bidding.Auto where import Daml.Finance.App.Interface.Base.Service qualified as Base (I) import Daml.Finance.App.Interface.Distribution.Auction.Auction qualified as Auction (I) import Daml.Finance.App.Interface.Distribution.Bidding.Bid qualified as Bid (I) -import Daml.Finance.App.Interface.Distribution.Bidding.Service qualified as Service (I, Implementation, asBase) import Daml.Finance.Interface.Holding.Fungible qualified as Fungible (I) import Daml.Finance.Interface.Types.Common (AccountKey) @@ -20,9 +19,10 @@ data View = View {} interface Service where viewtype V - asService : Service.I - -- ^ Conversion to custody `Service` interface. - requestAndCreateBid : ContractId Service.I -> RequestAndCreateBid -> Update (ContractId Bid.I) + asBase : Base.I + -- ^ Conversion to base `Service` interface. + + requestAndCreateBid : RequestAndCreateBid -> Update (ContractId Bid.I) -- ^ Implementation of the `RequestAndCreateAuction` choice. nonconsuming choice RequestAndCreateBid : (ContractId Bid.I) @@ -32,13 +32,12 @@ interface Service where price : Decimal collateralCid : ContractId Fungible.I receivableAccount : AccountKey - controller (view $ Service.asBase $ asService this).customer + controller (view $ asBase this).customer do - requestAndCreateBid this (toInterfaceContractId self) arg + requestAndCreateBid this arg -- | Type constraint for requiring templates to implement `Service`. -type Implementation t = (HasToInterface t Service, Service.Implementation t) +type Implementation t = HasToInterface t Service class (Implementation t) => HasImplementation t instance HasImplementation Service -instance HasToInterface Service Service.I where _toInterface = asService -instance HasToInterface Service Base.I where _toInterface = Service.asBase . asService +instance HasToInterface Service Base.I where _toInterface = asBase diff --git a/src/daml/Daml/Finance/App/Interface/Distribution/Bidding/Service.daml b/src/daml/Daml/Finance/App/Interface/Distribution/Bidding/Service.daml index 9d5d3dd6..1cf24900 100644 --- a/src/daml/Daml/Finance/App/Interface/Distribution/Bidding/Service.daml +++ b/src/daml/Daml/Finance/App/Interface/Distribution/Bidding/Service.daml @@ -22,12 +22,16 @@ interface Service where asBase : Base.I -- ^ Conversion to base `Service` interface. + requestCreateBid : RequestCreateBid -> Update (ContractId CreateBidRequest.I) -- ^ Implementation of the `RequestCreateBid` choice. + createBid : CreateBid -> Update (ContractId Bid.I) -- ^ Implementation of the `CreateBid` choice. + processAllocation : ProcessAllocation -> Update (ContractId Bid.I, ContractId Fungible.I) -- ^ Implementation of the `ProcessAllocation` choice. + rejectBid : RejectBid -> Update (ContractId Bid.I, ContractId Fungible.I) -- ^ Implementation of the `RejectBid` choice. diff --git a/src/daml/Daml/Finance/App/Interface/Distribution/Fund/Fund.daml b/src/daml/Daml/Finance/App/Interface/Distribution/Fund/Fund.daml new file mode 100644 index 00000000..91ccbe98 --- /dev/null +++ b/src/daml/Daml/Finance/App/Interface/Distribution/Fund/Fund.daml @@ -0,0 +1,73 @@ +-- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +-- SPDX-License-Identifier: Apache-2.0 + +module Daml.Finance.App.Interface.Distribution.Fund.Fund where + +import Daml.Finance.App.Interface.Common.Removable qualified as Removable (I, Implementation) +import Daml.Finance.App.Interface.Issuance.Issuance qualified as Issuance (I) +import Daml.Finance.App.Interface.Issuance.Service qualified as IssuanceService (I) +import Daml.Finance.Interface.Holding.Transferable qualified as Transferable (I) +import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (K, Q) +import Daml.Finance.Interface.Settlement.Instruction qualified as Instruction (I) +import Daml.Finance.Interface.Types.Common (AccountKey, Id, Parties) + +type I = Fund + +type V = View + +data View = View + with + operator : Party + custodian : Party + manager : Party + id : Id + description : Text + instrument : Instrument.K + currency : Instrument.K + custodianCashAccount : AccountKey + managerFundAccount : AccountKey + totalUnits : Decimal + observers : Parties + deriving (Eq, Show) + +interface Fund where + viewtype View + -- ^ Interface view type. + + asRemovable : Removable.I + -- ^ Conversion to the `Removable` interface. + + issueUnits : IssueUnits -> Update (ContractId Issuance.I, ContractId Transferable.I, ContractId Fund) + -- ^ Implementation of the `IssueUnits` choice. + + approveInstruction : ApproveInstruction -> Update (ContractId Instruction.I) + -- ^ Implementation of the `ApproveInstruction` choice. + + nonconsuming choice GetView : View + with + actor : Party + controller actor + do + pure $ view this + + choice IssueUnits : (ContractId Issuance.I, ContractId Transferable.I, ContractId Fund) + with + requestId : Id + quantity : Instrument.Q + issuanceServiceCid : ContractId IssuanceService.I + controller (view this).manager + do + issueUnits this arg + + nonconsuming choice ApproveInstruction : ContractId Instruction.I + with + instructionCid : ContractId Instruction.I + controller (view this).manager + do + approveInstruction this arg + +-- | Type constraint for requiring templates to implement `Fund`. +type Implementation t = (HasToInterface t Fund, Removable.Implementation t) +class (Implementation t) => HasImplementation t +instance HasImplementation Fund +instance HasToInterface Fund Removable.I where _toInterface = asRemovable diff --git a/src/daml/Daml/Finance/App/Interface/Distribution/Fund/PooledInvestmentRequest.daml b/src/daml/Daml/Finance/App/Interface/Distribution/Fund/PooledInvestmentRequest.daml new file mode 100644 index 00000000..2e18af4e --- /dev/null +++ b/src/daml/Daml/Finance/App/Interface/Distribution/Fund/PooledInvestmentRequest.daml @@ -0,0 +1,41 @@ +-- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +-- SPDX-License-Identifier: Apache-2.0 + +module Daml.Finance.App.Interface.Distribution.Fund.PooledInvestmentRequest where + +import Daml.Finance.App.Interface.Common.Removable qualified as Removable (I, Implementation) +import Daml.Finance.App.Interface.Distribution.Investment.InvestmentRequest qualified as InvestmentRequest (I) +import Daml.Finance.Interface.Holding.Transferable qualified as Transferable (I) +import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (Q) +import Daml.Finance.Interface.Types.Common (AccountKey, Id) + +type I = PooledInvestmentRequest + +type V = View + +data View = View + with + operator : Party + provider : Party + customer : Party + requestId : Id + asOfDate : Date + fundId : Id + quantity : Instrument.Q + cashCid : ContractId Transferable.I + investmentRequestCids : [ContractId InvestmentRequest.I] + customerFundAccount : AccountKey + deriving (Eq, Show) + +interface PooledInvestmentRequest where + viewtype View + -- ^ Interface view type. + + asRemovable : Removable.I + -- ^ Conversion to the `Removable` interface. + +-- | Type constraint for requiring templates to implement `PooledInvestmentRequest`. +type Implementation t = (HasToInterface t PooledInvestmentRequest, Removable.Implementation t) +class (Implementation t) => HasImplementation t +instance HasImplementation PooledInvestmentRequest +instance HasToInterface PooledInvestmentRequest Removable.I where _toInterface = asRemovable diff --git a/src/daml/Daml/Finance/App/Interface/Distribution/Fund/Service.daml b/src/daml/Daml/Finance/App/Interface/Distribution/Fund/Service.daml new file mode 100644 index 00000000..451148cb --- /dev/null +++ b/src/daml/Daml/Finance/App/Interface/Distribution/Fund/Service.daml @@ -0,0 +1,62 @@ +-- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +-- SPDX-License-Identifier: Apache-2.0 + +module Daml.Finance.App.Interface.Distribution.Fund.Service where + +import Daml.Finance.App.Interface.Base.Service qualified as Base (I, Implementation) +import Daml.Finance.App.Interface.Distribution.Fund.Fund qualified as Fund (I) +import Daml.Finance.App.Interface.Distribution.Fund.PooledInvestmentRequest qualified as PooledInvestmentRequest (I) +import Daml.Finance.App.Interface.Distribution.Investment.InvestmentRequest qualified as InvestmentRequest (I) +import Daml.Finance.App.Interface.Issuance.Service qualified as IssuanceService (I) +import Daml.Finance.Interface.Data.NumericObservable qualified as NumericObservable (I) +import Daml.Finance.Interface.Holding.Base qualified as Holding (I) +import Daml.Finance.Interface.Holding.Transferable qualified as Transferable (I) +import Daml.Finance.Interface.Settlement.Factory qualified as SettlementFactory (I) +import Daml.Finance.Interface.Types.Common (Id) + +type I = Service + +type V = View + +data View = View {} + deriving (Eq, Show) + +interface Service where + viewtype V + + asBase : Base.I + -- ^ Conversion to base `Service` interface. + + poolInvestmentRequests : PoolInvestmentRequests -> Update (ContractId PooledInvestmentRequest.I) + -- ^ Implementation of the `PoolInvestmentRequests` choice. + + fulfillPooledInvestmentRequest : FulfillPooledInvestmentRequest -> Update [ContractId Holding.I] + -- ^ Implementation of the `FulfillPooledInvestmentRequest` choice. + + nonconsuming choice PoolInvestmentRequests : ContractId PooledInvestmentRequest.I + with + requestId : Id + asOfDate : Date + fundCid : ContractId Fund.I + cashCid : ContractId Transferable.I + investmentRequestCids : [ContractId InvestmentRequest.I] + controller (view $ asBase this).customer + do + poolInvestmentRequests this arg + + nonconsuming choice FulfillPooledInvestmentRequest : [ContractId Holding.I] + with + pooledInvestmentRequestCid : ContractId PooledInvestmentRequest.I + fundCid : ContractId Fund.I + navObservableCid : ContractId NumericObservable.I + settlementFactoryCid : ContractId SettlementFactory.I + issuanceServiceCid : ContractId IssuanceService.I + controller (view $ asBase this).provider + do + fulfillPooledInvestmentRequest this arg + +-- | Type constraint for requiring templates to implement `Service`. +type Implementation t = (HasToInterface t Service, Base.Implementation t) +class (Implementation t) => HasImplementation t +instance HasImplementation Service +instance HasToInterface Service Base.I where _toInterface = asBase diff --git a/src/daml/Daml/Finance/App/Interface/Distribution/Investment/InvestmentRequest.daml b/src/daml/Daml/Finance/App/Interface/Distribution/Investment/InvestmentRequest.daml new file mode 100644 index 00000000..d5e30bd7 --- /dev/null +++ b/src/daml/Daml/Finance/App/Interface/Distribution/Investment/InvestmentRequest.daml @@ -0,0 +1,61 @@ +-- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +-- SPDX-License-Identifier: Apache-2.0 + +module Daml.Finance.App.Interface.Distribution.Investment.InvestmentRequest where + +import Daml.Finance.App.Interface.Common.Removable qualified as Removable (I, Implementation) +import Daml.Finance.Interface.Holding.Transferable qualified as Transferable (I) +import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (Q) +import Daml.Finance.Interface.Settlement.Instruction qualified as Instruction (I) +import Daml.Finance.Interface.Types.Common (AccountKey, Id) + +type I = InvestmentRequest + +type V = View + +data View = View + with + operator : Party + provider : Party + customer : Party + manager : Party + requestId : Id + asOfDate : Date + fundId : Id + quantity : Instrument.Q + cashCid : ContractId Transferable.I + customerFundAccount : AccountKey + deriving (Eq, Show) + +interface InvestmentRequest where + viewtype View + -- ^ Interface view type. + + asRemovable : Removable.I + -- ^ Conversion to the `Removable` interface. + + allocateInstruction : AllocateInstruction -> Update (ContractId Instruction.I) + -- ^ Implementation of the `AllocateInstruction` choice. + + approveInstruction : ApproveInstruction -> Update (ContractId Instruction.I) + -- ^ Implementation of the `ApproveInstruction` choice. + + nonconsuming choice AllocateInstruction : ContractId Instruction.I + with + instructionCid : ContractId Instruction.I + controller (view this).manager + do + allocateInstruction this arg + + nonconsuming choice ApproveInstruction : ContractId Instruction.I + with + instructionCid : ContractId Instruction.I + controller (view this).manager + do + approveInstruction this arg + +-- | Type constraint for requiring templates to implement `InvestmentRequest`. +type Implementation t = (HasToInterface t InvestmentRequest, Removable.Implementation t) +class (Implementation t) => HasImplementation t +instance HasImplementation InvestmentRequest +instance HasToInterface InvestmentRequest Removable.I where _toInterface = asRemovable diff --git a/src/daml/Daml/Finance/App/Interface/Distribution/Investment/Service.daml b/src/daml/Daml/Finance/App/Interface/Distribution/Investment/Service.daml new file mode 100644 index 00000000..f3758e28 --- /dev/null +++ b/src/daml/Daml/Finance/App/Interface/Distribution/Investment/Service.daml @@ -0,0 +1,42 @@ +-- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +-- SPDX-License-Identifier: Apache-2.0 + +module Daml.Finance.App.Interface.Distribution.Investment.Service where + +import Daml.Finance.App.Interface.Base.Service qualified as Base (I, Implementation) +import Daml.Finance.App.Interface.Distribution.Fund.Fund qualified as Fund (I) +import Daml.Finance.App.Interface.Distribution.Investment.InvestmentRequest qualified as InvestmentRequest (I) +import Daml.Finance.Interface.Holding.Transferable qualified as Transferable (I) +import Daml.Finance.Interface.Types.Common (Id) + +type I = Service + +type V = View + +data View = View {} + deriving (Eq, Show) + +interface Service where + viewtype V + + asBase : Base.I + -- ^ Conversion to base `Service` interface. + + requestInvestment : RequestInvestment -> Update (ContractId InvestmentRequest.I) + -- ^ Implementation of the `RequestInvestment` choice. + + nonconsuming choice RequestInvestment : ContractId InvestmentRequest.I + with + requestId : Id + asOfDate : Date + fundCid : ContractId Fund.I + cashCid : ContractId Transferable.I + controller (view $ asBase this).customer + do + requestInvestment this arg + +-- | Type constraint for requiring templates to implement `Service`. +type Implementation t = (HasToInterface t Service, Base.Implementation t) +class (Implementation t) => HasImplementation t +instance HasImplementation Service +instance HasToInterface Service Base.I where _toInterface = asBase diff --git a/src/daml/Daml/Finance/App/Interface/Distribution/Subscription/Offering.daml b/src/daml/Daml/Finance/App/Interface/Distribution/Subscription/Offering.daml new file mode 100644 index 00000000..c95893e7 --- /dev/null +++ b/src/daml/Daml/Finance/App/Interface/Distribution/Subscription/Offering.daml @@ -0,0 +1,57 @@ +-- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +-- SPDX-License-Identifier: Apache-2.0 + +module Daml.Finance.App.Interface.Distribution.Subscription.Offering where + +import Daml.Finance.App.Interface.Common.Removable qualified as Removable (I, Implementation) +import Daml.Finance.App.Interface.Distribution.Subscription.Subscription qualified as Subscription (I) +import Daml.Finance.App.Interface.Distribution.Subscription.Types (BackToBack, Status) +import Daml.Finance.Interface.Holding.Fungible qualified as Fungible (I) +import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (Q) +import Daml.Finance.Interface.Types.Common (AccountKey, Id) + +type I = Offering + +type V = View + +data View = View + with + operator : Party + provider : Party + issuer : Party + public : Party + id : Id + description : Text + asset : Instrument.Q + price : Instrument.Q + issuerHoldingCid : ContractId Fungible.I + issuerAccount : AccountKey + backToBack : Optional BackToBack + status : Status + deriving (Eq, Show) + +interface Offering where + viewtype View + -- ^ Interface view type. + + asRemovable : Removable.I + -- ^ Conversion to the `Removable` interface. + + subscribe : Subscribe -> Update (ContractId Subscription.I) + -- ^ Implementation of the `Subscribe` choice. + + nonconsuming choice Subscribe : ContractId Subscription.I + with + investor : Party + quantity : Decimal + investorHoldingCid : ContractId Fungible.I + investorAccount : AccountKey + controller investor + do + subscribe this arg + +-- | Type constraint for requiring templates to implement `Offering`. +type Implementation t = (HasToInterface t Offering, Removable.Implementation t) +class (Implementation t) => HasImplementation t +instance HasImplementation Offering +instance HasToInterface Offering Removable.I where _toInterface = asRemovable diff --git a/src/daml/Daml/Finance/App/Interface/Distribution/Subscription/Service.daml b/src/daml/Daml/Finance/App/Interface/Distribution/Subscription/Service.daml new file mode 100644 index 00000000..5a60d336 --- /dev/null +++ b/src/daml/Daml/Finance/App/Interface/Distribution/Subscription/Service.daml @@ -0,0 +1,60 @@ +-- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +-- SPDX-License-Identifier: Apache-2.0 + +module Daml.Finance.App.Interface.Distribution.Subscription.Service where + +import Daml.Finance.App.Interface.Base.Service qualified as Base (I, Implementation) +import Daml.Finance.App.Interface.Distribution.Subscription.Offering qualified as Offering (I) +import Daml.Finance.App.Interface.Distribution.Subscription.Subscription qualified as Subscription (I) +import Daml.Finance.App.Interface.Distribution.Subscription.Types (BackToBack) +import Daml.Finance.Interface.Holding.Fungible qualified as Fungible (I) +import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (Q) +import Daml.Finance.Interface.Settlement.Factory qualified as Factory (I) +import Daml.Finance.Interface.Types.Common (AccountKey, Id) + +type I = Service + +type V = View + +data View = View {} + deriving (Eq, Show) + +interface Service where + viewtype V + + asBase : Base.I + -- ^ Conversion to base `Service` interface. + + createOffering : CreateOffering -> Update (ContractId Offering.I) + -- ^ Implementation of the `CreateOffering` choice. + + processOffering : ProcessOffering -> Update (ContractId Offering.I) + -- ^ Implementation of the `ProcessOffering` choice. + + nonconsuming choice CreateOffering : ContractId Offering.I + with + offeringId : Id + description : Text + asset : Instrument.Q + price : Instrument.Q + customerHoldingCid : ContractId Fungible.I + customerAccount : AccountKey + backToBack : Optional BackToBack + controller (view $ asBase this).customer + do + createOffering this arg + + nonconsuming choice ProcessOffering : ContractId Offering.I + with + settlementFactoryCid : ContractId Factory.I + offeringCid : ContractId Offering.I + subscriptionCids : [ContractId Subscription.I] + controller (view $ asBase this).provider + do + processOffering this arg + +-- | Type constraint for requiring templates to implement `Service`. +type Implementation t = (HasToInterface t Service, Base.Implementation t) +class (Implementation t) => HasImplementation t +instance HasImplementation Service +instance HasToInterface Service Base.I where _toInterface = asBase diff --git a/src/daml/Daml/Finance/App/Interface/Distribution/Subscription/Subscription.daml b/src/daml/Daml/Finance/App/Interface/Distribution/Subscription/Subscription.daml new file mode 100644 index 00000000..54550954 --- /dev/null +++ b/src/daml/Daml/Finance/App/Interface/Distribution/Subscription/Subscription.daml @@ -0,0 +1,72 @@ +-- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +-- SPDX-License-Identifier: Apache-2.0 + +module Daml.Finance.App.Interface.Distribution.Subscription.Subscription where + +import Daml.Finance.App.Interface.Common.Removable qualified as Removable (I, Implementation) +import Daml.Finance.Interface.Holding.Base qualified as Holding (I) +import Daml.Finance.Interface.Holding.Fungible qualified as Fungible (I) +import Daml.Finance.Interface.Holding.Transferable qualified as Transferable (I) +import Daml.Finance.Interface.Settlement.Instruction qualified as Instruction (I) +import Daml.Finance.Interface.Types.Common (AccountKey, Id) + +type I = Subscription + +type V = View + +data View = View + with + operator : Party + provider : Party + issuer : Party + investor : Party + offeringId : Id + quantity : Decimal + holdingCid : ContractId Fungible.I + account : AccountKey + deriving (Eq, Show) + +interface Subscription where + viewtype View + -- ^ Interface view type. + + asRemovable : Removable.I + -- ^ Conversion to the `Removable` interface. + + allocateInstruction : AllocateInstruction -> Update (ContractId Instruction.I) + -- ^ Implementation of the `AllocateInstruction` choice. + + approveInstruction : ApproveInstruction -> Update (ContractId Instruction.I) + -- ^ Implementation of the `ApproveInstruction` choice. + + unlockHolding : UnlockHolding -> Update (ContractId Holding.I) + -- ^ Implementation of the `UnlockHolding` choice. + + nonconsuming choice AllocateInstruction : ContractId Instruction.I + with + instructionCid : ContractId Instruction.I + transferableCid : ContractId Transferable.I + controller (view this).provider + do + allocateInstruction this arg + + nonconsuming choice ApproveInstruction : ContractId Instruction.I + with + instructionCid : ContractId Instruction.I + receiverAccount : AccountKey + controller (view this).provider + do + approveInstruction this arg + + nonconsuming choice UnlockHolding : ContractId Holding.I + with + lockableCid : ContractId Holding.I + controller (view this).provider + do + unlockHolding this arg + +-- | Type constraint for requiring templates to implement `Subscription`. +type Implementation t = (HasToInterface t Subscription, Removable.Implementation t) +class (Implementation t) => HasImplementation t +instance HasImplementation Subscription +instance HasToInterface Subscription Removable.I where _toInterface = asRemovable diff --git a/src/daml/Daml/Finance/App/Interface/Distribution/Subscription/Types.daml b/src/daml/Daml/Finance/App/Interface/Distribution/Subscription/Types.daml new file mode 100644 index 00000000..77b7769b --- /dev/null +++ b/src/daml/Daml/Finance/App/Interface/Distribution/Subscription/Types.daml @@ -0,0 +1,22 @@ +-- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +-- SPDX-License-Identifier: Apache-2.0 + +module Daml.Finance.App.Interface.Distribution.Subscription.Types where + +import Daml.Finance.Interface.Holding.Fungible qualified as Fungible (I) +import Daml.Finance.Interface.Types.Common (AccountKey, Id) + +data Status + = Open + | Closed + deriving (Eq, Show) + +data BackToBack = BackToBack + with + party : Party + offeringId : Id + issuerReceivableAccount : AccountKey + issuerDeliverableCid : ContractId Fungible.I + b2bReceivableAccount : AccountKey + b2bDeliverableCid : ContractId Fungible.I + deriving (Eq, Show) diff --git a/src/daml/Daml/Finance/App/Interface/Issuance/Auto.daml b/src/daml/Daml/Finance/App/Interface/Issuance/Auto.daml index e0914f16..19b60a7a 100644 --- a/src/daml/Daml/Finance/App/Interface/Issuance/Auto.daml +++ b/src/daml/Daml/Finance/App/Interface/Issuance/Auto.daml @@ -5,7 +5,6 @@ module Daml.Finance.App.Interface.Issuance.Auto where import Daml.Finance.App.Interface.Base.Service qualified as Base (I) import Daml.Finance.App.Interface.Issuance.Issuance qualified as Issuance (I) -import Daml.Finance.App.Interface.Issuance.Service qualified as Service (I, Implementation, asBase) import Daml.Finance.Interface.Holding.Base qualified as Holding (I) import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (Q) import Daml.Finance.Interface.Types.Common (AccountKey, Id) @@ -20,11 +19,13 @@ data View = View {} interface Service where viewtype V - asService : Service.I - -- ^ Conversion to custody `Service` interface. - requestAndIssue : ContractId Service.I -> RequestAndIssue -> Update (ContractId Issuance.I, ContractId Holding.I) + asBase : Base.I + -- ^ Conversion to base `Service` interface. + + requestAndIssue : RequestAndIssue -> Update (ContractId Issuance.I, ContractId Holding.I) -- ^ Implementation of the `RequestAndIssue` choice. - requestAndDeissue : ContractId Service.I -> RequestAndDeissue -> Update (ContractId Issuance.I) + + requestAndDeissue : RequestAndDeissue -> Update (ContractId Issuance.I) -- ^ Implementation of the `RequestAndDeissue` choice. nonconsuming choice RequestAndIssue : (ContractId Issuance.I, ContractId Holding.I) @@ -33,21 +34,20 @@ interface Service where description : Text quantity : Instrument.Q account : AccountKey - controller (view $ Service.asBase $ asService this).customer + controller (view $ asBase this).customer do - requestAndIssue this (toInterfaceContractId self) arg + requestAndIssue this arg nonconsuming choice RequestAndDeissue : (ContractId Issuance.I) with issuanceId : Id holdingCid : ContractId Holding.I - controller (view $ Service.asBase $ asService this).customer + controller (view $ asBase this).customer do - requestAndDeissue this (toInterfaceContractId self) arg + requestAndDeissue this arg -- | Type constraint for requiring templates to implement `Service`. -type Implementation t = (HasToInterface t Service, Service.Implementation t) +type Implementation t = HasToInterface t Service class (Implementation t) => HasImplementation t instance HasImplementation Service -instance HasToInterface Service Service.I where _toInterface = asService -instance HasToInterface Service Base.I where _toInterface = Service.asBase . asService +instance HasToInterface Service Base.I where _toInterface = asBase diff --git a/src/daml/Daml/Finance/App/Interface/Issuance/BackToBack.daml b/src/daml/Daml/Finance/App/Interface/Issuance/BackToBack.daml new file mode 100644 index 00000000..166a64d7 --- /dev/null +++ b/src/daml/Daml/Finance/App/Interface/Issuance/BackToBack.daml @@ -0,0 +1,68 @@ +-- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +-- SPDX-License-Identifier: Apache-2.0 + +module Daml.Finance.App.Interface.Issuance.BackToBack where + +import Daml.Finance.App.Interface.Base.Service qualified as Base (I, Implementation) +import Daml.Finance.App.Interface.Distribution.Subscription.Offering qualified as Offering (I) +import Daml.Finance.App.Interface.Distribution.Subscription.Types (BackToBack) +import Daml.Finance.App.Interface.Issuance.Issuance qualified as Issuance (I) +import Daml.Finance.Interface.Holding.Base qualified as Holding (I) +import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (Q) +import Daml.Finance.Interface.Settlement.Factory qualified as Factory (I) +import Daml.Finance.Interface.Types.Common (AccountKey, Id) + +type I = Service + +type V = View + +data View = View {} + deriving (Eq, Show) + +interface Service where + viewtype V + + asBase : Base.I + -- ^ Conversion to base `Service` interface. + + createIssuance : CreateIssuance -> Update (ContractId Issuance.I, ContractId Holding.I, ContractId Holding.I) + -- ^ Implementation of the `CreateIssuance` choice. + + lockOffering : LockOffering -> Update BackToBack + -- ^ Implementation of the `LockOffering` choice. + + settleOffering : SettleOffering -> Update [ContractId Holding.I] + -- ^ Implementation of the `SettleOffering` choice. + + nonconsuming choice CreateIssuance : (ContractId Issuance.I, ContractId Holding.I, ContractId Holding.I) + with + issuanceId : Id + description : Text + quantity : Instrument.Q + customerAccount : AccountKey + providerAccount : AccountKey + controller (view $ asBase this).customer + do + createIssuance this arg + + nonconsuming choice LockOffering : BackToBack + with + backToBack : BackToBack + controller (view $ asBase this).customer + do + lockOffering this arg + + nonconsuming choice SettleOffering : [ContractId Holding.I] + with + settlementFactoryCid : ContractId Factory.I + offeringCid : ContractId Offering.I + totalQuantity : Decimal + controller (view $ asBase this).customer + do + settleOffering this arg + +-- | Type constraint for requiring templates to implement `Service`. +type Implementation t = (HasToInterface t Service, Base.Implementation t) +class (Implementation t) => HasImplementation t +instance HasImplementation Service +instance HasToInterface Service Base.I where _toInterface = asBase diff --git a/src/daml/Daml/Finance/App/Interface/Issuance/Service.daml b/src/daml/Daml/Finance/App/Interface/Issuance/Service.daml index 9e769441..e4ab6c69 100644 --- a/src/daml/Daml/Finance/App/Interface/Issuance/Service.daml +++ b/src/daml/Daml/Finance/App/Interface/Issuance/Service.daml @@ -23,12 +23,16 @@ interface Service where asBase : Base.I -- ^ Conversion to base `Service` interface. + requestIssue : RequestIssue -> Update (ContractId IssueRequest.I) -- ^ Implementation of the `RequestIssue` choice. + requestDeissue : RequestDeissue -> Update (ContractId DeissueRequest.I) -- ^ Implementation of the `RequestDeissue` choice. + issue : Issue -> Update (ContractId Issuance.I, ContractId Holding.I) -- ^ Implementation of the `Issue` choice. + deissue : Deissue -> Update (ContractId Issuance.I) -- ^ Implementation of the `Deissue` choice. diff --git a/src/daml/Daml/Finance/App/Interface/Lending/BorrowAgreement.daml b/src/daml/Daml/Finance/App/Interface/Lending/BorrowAgreement.daml new file mode 100644 index 00000000..f1274ad2 --- /dev/null +++ b/src/daml/Daml/Finance/App/Interface/Lending/BorrowAgreement.daml @@ -0,0 +1,53 @@ +-- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +-- SPDX-License-Identifier: Apache-2.0 + +module Daml.Finance.App.Interface.Lending.BorrowAgreement where + +import Daml.Finance.App.Interface.Common.Removable qualified as Removable (I, Implementation) +import Daml.Finance.Interface.Holding.Transferable qualified as Transferable (I) +import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (Q) +import Daml.Finance.Interface.Types.Common (AccountKey, Id) + +type I = BorrowAgreement + +type V = View + +data View = View + with + operator : Party + provider : Party + customer : Party + dealId : Id + description : Text + borrowed : Instrument.Q + maturity : Date + interest : Instrument.Q + collateral : Instrument.Q + collateralCid : ContractId Transferable.I + lenderBorrowedAccount : AccountKey + lenderInterestAccount : AccountKey + deriving (Eq, Show) + +interface BorrowAgreement where + viewtype View + -- ^ Interface view type. + + asRemovable : Removable.I + -- ^ Conversion to the `Removable` interface. + + repay : Repay -> Update (ContractId Transferable.I, ContractId Transferable.I, ContractId Transferable.I) + -- ^ Implementation of the `Repay` choice. + + choice Repay : (ContractId Transferable.I, ContractId Transferable.I, ContractId Transferable.I) + with + borrowedCid : ContractId Transferable.I + interestCid : ContractId Transferable.I + controller (view this).customer + do + repay this arg + +-- | Type constraint for requiring templates to implement `BorrowAgreement`. +type Implementation t = (HasToInterface t BorrowAgreement, Removable.Implementation t) +class (Implementation t) => HasImplementation t +instance HasImplementation BorrowAgreement +instance HasToInterface BorrowAgreement Removable.I where _toInterface = asRemovable diff --git a/src/daml/Daml/Finance/App/Interface/Lending/BorrowOffer.daml b/src/daml/Daml/Finance/App/Interface/Lending/BorrowOffer.daml new file mode 100644 index 00000000..abdb59a7 --- /dev/null +++ b/src/daml/Daml/Finance/App/Interface/Lending/BorrowOffer.daml @@ -0,0 +1,41 @@ +-- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +-- SPDX-License-Identifier: Apache-2.0 + +module Daml.Finance.App.Interface.Lending.BorrowOffer where + +import Daml.Finance.App.Interface.Common.Removable qualified as Removable (I, Implementation) +import Daml.Finance.Interface.Holding.Transferable qualified as Transferable (I) +import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (Q) +import Daml.Finance.Interface.Types.Common (AccountKey, Id) + +type I = BorrowOffer + +type V = View + +data View = View + with + operator : Party + provider : Party + customer : Party + dealId : Id + description : Text + borrowed : Instrument.Q + maturity : Date + interest : Instrument.Q + collateral : Instrument.Q + borrowedCid : ContractId Transferable.I + lenderBorrowedAccount : AccountKey + lenderInterestAccount : AccountKey + deriving (Eq, Show) + +interface BorrowOffer where + viewtype View + -- ^ Interface view type. + asRemovable : Removable.I + -- ^ Conversion to the `Removable` interface. + +-- | Type constraint for requiring templates to implement `BorrowOffer`. +type Implementation t = (HasToInterface t BorrowOffer, Removable.Implementation t) +class (Implementation t) => HasImplementation t +instance HasImplementation BorrowOffer +instance HasToInterface BorrowOffer Removable.I where _toInterface = asRemovable diff --git a/src/daml/Daml/Finance/App/Interface/Lending/BorrowOfferRequest.daml b/src/daml/Daml/Finance/App/Interface/Lending/BorrowOfferRequest.daml new file mode 100644 index 00000000..d1918336 --- /dev/null +++ b/src/daml/Daml/Finance/App/Interface/Lending/BorrowOfferRequest.daml @@ -0,0 +1,35 @@ +-- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +-- SPDX-License-Identifier: Apache-2.0 + +module Daml.Finance.App.Interface.Lending.BorrowOfferRequest where + +import Daml.Finance.App.Interface.Common.Removable qualified as Removable (I, Implementation) +import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (Q) +import Daml.Finance.Interface.Types.Common (Id) + +type I = BorrowOfferRequest + +type V = View + +data View = View + with + operator : Party + provider : Party + customer : Party + dealId : Id + description : Text + borrowed : Instrument.Q + maturity : Date + deriving (Eq, Show) + +interface BorrowOfferRequest where + viewtype View + -- ^ Interface view type. + asRemovable : Removable.I + -- ^ Conversion to the `Removable` interface. + +-- | Type constraint for requiring templates to implement `BorrowOfferRequest`. +type Implementation t = (HasToInterface t BorrowOfferRequest, Removable.Implementation t) +class (Implementation t) => HasImplementation t +instance HasImplementation BorrowOfferRequest +instance HasToInterface BorrowOfferRequest Removable.I where _toInterface = asRemovable diff --git a/src/daml/Daml/Finance/App/Interface/Lending/Service.daml b/src/daml/Daml/Finance/App/Interface/Lending/Service.daml new file mode 100644 index 00000000..7bfaa25d --- /dev/null +++ b/src/daml/Daml/Finance/App/Interface/Lending/Service.daml @@ -0,0 +1,71 @@ +-- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +-- SPDX-License-Identifier: Apache-2.0 + +module Daml.Finance.App.Interface.Lending.Service where + +import Daml.Finance.App.Interface.Base.Service qualified as Base (I, Implementation) +import Daml.Finance.App.Interface.Lending.BorrowAgreement qualified as BorrowAgreement (I) +import Daml.Finance.App.Interface.Lending.BorrowOffer qualified as BorrowOffer (I) +import Daml.Finance.App.Interface.Lending.BorrowOfferRequest qualified as BorrowOfferRequest (I) +import Daml.Finance.Interface.Holding.Transferable qualified as Transferable (I) +import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (Q) +import Daml.Finance.Interface.Types.Common (AccountKey, Id) + +type I = Service + +type V = View + +data View = View {} + deriving (Eq, Show) + +interface Service where + viewtype V + + asBase : Base.I + -- ^ Conversion to base `Service` interface. + + requestBorrowOffer : RequestBorrowOffer -> Update (ContractId BorrowOfferRequest.I) + -- ^ Implementation of the `RequestBorrowOffer` choice. + + acceptBorrowOffer : AcceptBorrowOffer -> Update (ContractId Transferable.I, ContractId BorrowAgreement.I) + -- ^ Implementation of the `AcceptBorrowOffer` choice. + + createBorrowOffer : CreateBorrowOffer -> Update (ContractId BorrowOffer.I) + -- ^ Implementation of the `CreateBorrowOffer` choice. + + nonconsuming choice RequestBorrowOffer : ContractId BorrowOfferRequest.I + with + dealId : Id + description : Text + borrowed : Instrument.Q + maturity : Date + controller (view $ asBase this).customer + do + requestBorrowOffer this arg + + nonconsuming choice AcceptBorrowOffer : (ContractId Transferable.I, ContractId BorrowAgreement.I) + with + borrowOfferCid : ContractId BorrowOffer.I + collateralCid : ContractId Transferable.I + account : AccountKey + controller (view $ asBase this).customer + do + acceptBorrowOffer this arg + + nonconsuming choice CreateBorrowOffer : ContractId BorrowOffer.I + with + borrowOfferRequestCid : ContractId BorrowOfferRequest.I + interest : Instrument.Q + collateral : Instrument.Q + borrowedCid : ContractId Transferable.I + lenderBorrowedAccount : AccountKey + lenderInterestAccount : AccountKey + controller (view $ asBase this).provider + do + createBorrowOffer this arg + +-- | Type constraint for requiring templates to implement `Service`. +type Implementation t = (HasToInterface t Service, Base.Implementation t) +class (Implementation t) => HasImplementation t +instance HasImplementation Service +instance HasToInterface Service Base.I where _toInterface = asBase diff --git a/src/daml/Daml/Finance/App/Interface/Lifecycle/Service.daml b/src/daml/Daml/Finance/App/Interface/Lifecycle/Service.daml new file mode 100644 index 00000000..39dbf1fd --- /dev/null +++ b/src/daml/Daml/Finance/App/Interface/Lifecycle/Service.daml @@ -0,0 +1,198 @@ +-- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +-- SPDX-License-Identifier: Apache-2.0 + +module Daml.Finance.App.Interface.Lifecycle.Service where + +import Daml.Finance.App.Interface.Base.Service qualified as Base (I, Implementation) +import ContingentClaims.Core.Claim (Claim) +import ContingentClaims.Core.Observation (Observation(..)) +import ContingentClaims.Lifecycle.Lifecycle qualified as Lifecycle +import ContingentClaims.Valuation.Stochastic (Expr) +import Daml.Finance.Interface.Data.NumericObservable qualified as NumericObservable (I) +import Daml.Finance.Interface.Data.TimeObservable qualified as TimeObservable (I) +import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (K, Q) +import Daml.Finance.Interface.Claims.Claim qualified as Claim (Claim) +import Daml.Finance.Interface.Claims.Types (C, Pending, TaggedClaim) +import Daml.Finance.Interface.Lifecycle.Effect qualified as Effect (I) +import Daml.Finance.Interface.Lifecycle.Event qualified as Event (I) +import Daml.Finance.Interface.Lifecycle.Rule.Lifecycle qualified as Lifecycle (I) +import Daml.Finance.Interface.Types.Common (Id) + +type I = Service + +type V = View + +data View = View + with + distributionRuleCid : ContractId Lifecycle.I + replacementRuleCid : ContractId Lifecycle.I + deriving (Eq, Show) + +interface Service where + viewtype V + + asBase : Base.I + -- ^ Conversion to base `Service` interface. + + declareDividend : DeclareDividend -> Update [ContractId Effect.I] + -- ^ Implementation of the `DeclareDividend` choice. + + declareReplacement : DeclareReplacement -> Update [ContractId Effect.I] + -- ^ Implementation of the `DeclareReplacement` choice. + + declareStockSplit : DeclareStockSplit -> Update [ContractId Effect.I] + -- ^ Implementation of the `DeclareStockSplit` choice. + + previewLifecycle : PreviewLifecycle -> Update ([TaggedClaim], [Pending]) + -- ^ Implementation of the `PreviewLifecycle` choice. + + simulateLifecycle : SimulateLifecycle -> Update [[Lifecycle.Pending Time Instrument.K]] + -- ^ Implementation of the `SimulateLifecycle` choice. + + getCurrentClaims : GetCurrentClaims -> Update [TaggedClaim] + -- ^ Implementation of the `GetCurrentClaims` choice. + + lifecycle : Lifecycle -> Update (ContractId Lifecycle.I, [ContractId Effect.I]) + -- ^ Implementation of the `Lifecycle` choice. + + expiry : Expiry -> Update (Optional Time) + -- ^ Implementation of the `Expiry` choice. + + underlyings : Underlyings -> Update [Instrument.K] + -- ^ Implementation of the `Underlyings` choice. + + payoffs : Payoffs -> Update [(Observation Time Decimal Text, Instrument.K)] + -- ^ Implementation of the `Payoffs` choice. + + fixings : Fixings -> Update [Time] + -- ^ Implementation of the `Fixings` choice. + + multipliers : Multipliers -> Update [Decimal] + -- ^ Implementation of the `Multipliers` choice. + + previewPricing : PreviewPricing -> Update (Expr Text, Text) + -- ^ Implementation of the `PreviewPricing` choice. + + nonconsuming choice DeclareDividend : [ContractId Effect.I] + with + timeObservableCid : ContractId TimeObservable.I + equity : Instrument.K + newVersion : Text + id : Id + description : Text + effectiveDate : Date + perUnitDistribution : [ Instrument.Q ] + controller (view $ asBase this).customer + do + declareDividend this arg + + nonconsuming choice DeclareReplacement : [ContractId Effect.I] + with + timeObservableCid : ContractId TimeObservable.I + equity : Instrument.K + id : Id + description : Text + effectiveDate : Date + perUnitReplacement : [ Instrument.Q ] + controller (view $ asBase this).customer + do + declareReplacement this arg + + nonconsuming choice DeclareStockSplit : [ContractId Effect.I] + with + timeObservableCid : ContractId TimeObservable.I + equity : Instrument.K + newVersion : Text + id : Id + description : Text + effectiveDate : Date + adjustmentFactor : Decimal + controller (view $ asBase this).customer + do + declareStockSplit this arg + + nonconsuming choice PreviewLifecycle : ([TaggedClaim], [Pending]) + with + today : Time + observableCids : [ContractId NumericObservable.I] + instrumentCid : ContractId Claim.Claim + controller (view $ asBase this).customer + do + previewLifecycle this arg + + nonconsuming choice SimulateLifecycle : [[Lifecycle.Pending Time Instrument.K]] + with + today : Time + prices : [Decimal] + instrumentCid : ContractId Claim.Claim + controller (view $ asBase this).customer + do + simulateLifecycle this arg + + nonconsuming choice GetCurrentClaims : [TaggedClaim] + with + instrumentCid : ContractId Claim.Claim + observableCids : [ContractId NumericObservable.I] + controller (view $ asBase this).customer + do + getCurrentClaims this arg + + nonconsuming choice Lifecycle : (ContractId Lifecycle.I, [ContractId Effect.I]) + with + ruleName : Text + eventCid : ContractId Event.I + timeObservableCid : ContractId TimeObservable.I + observableCids : [ContractId NumericObservable.I] + lifecyclableCid : ContractId Lifecycle.I + controller (view $ asBase this).customer + do + lifecycle this arg + + nonconsuming choice Expiry : Optional Time + with + claims : C + controller (view $ asBase this).customer + do + expiry this arg + + nonconsuming choice Underlyings : [Instrument.K] + with + claims : C + controller (view $ asBase this).customer + do + underlyings this arg + + nonconsuming choice Payoffs : [(Observation Time Decimal Text, Instrument.K)] + with + claims : C + controller (view $ asBase this).customer + do + payoffs this arg + + nonconsuming choice Fixings : [Time] + with + claims : C + controller (view $ asBase this).customer + do + fixings this arg + + nonconsuming choice Multipliers : [Decimal] + with + claims : C + controller (view $ asBase this).customer + do + multipliers this arg + + nonconsuming choice PreviewPricing : (Expr Text, Text) + with + ccy : Text + claims : Claim Text Decimal Text Text + controller (view $ asBase this).customer + do + previewPricing this arg + +-- | Type constraint for requiring templates to implement `Service`. +type Implementation t = (HasToInterface t Service, Base.Implementation t) +class (Implementation t) => HasImplementation t +instance HasImplementation Service +instance HasToInterface Service Base.I where _toInterface = asBase diff --git a/src/daml/Daml/Finance/App/Interface/Listing/Auto.daml b/src/daml/Daml/Finance/App/Interface/Listing/Auto.daml index 0e4b1ebd..a161db3a 100644 --- a/src/daml/Daml/Finance/App/Interface/Listing/Auto.daml +++ b/src/daml/Daml/Finance/App/Interface/Listing/Auto.daml @@ -5,7 +5,6 @@ module Daml.Finance.App.Interface.Listing.Auto where import Daml.Finance.App.Interface.Base.Service qualified as Base (I) import Daml.Finance.App.Interface.Listing.Listing qualified as Listing (I) -import Daml.Finance.App.Interface.Listing.Service qualified as Service (I, Implementation, asBase) import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (K) import Daml.Finance.Interface.Types.Common (Id, Parties) @@ -19,34 +18,35 @@ data View = View {} interface Service where viewtype V - asService : Service.I - -- ^ Conversion to custody `Service` interface. - requestAndList : ContractId Service.I -> RequestAndList -> Update (ContractId Listing.I) + asBase : Base.I + -- ^ Conversion to base `Service` interface. + + requestAndList : RequestAndList -> Update (ContractId Listing.I) -- ^ Implementation of the `RequestAndList` choice. - requestAndDelist : ContractId Service.I -> RequestAndDelist -> Update () + + requestAndDelist : RequestAndDelist -> Update () -- ^ Implementation of the `RequestAndDelist` choice. - nonconsuming choice RequestAndList : (ContractId Listing.I) + nonconsuming choice RequestAndList : ContractId Listing.I with listingId : Id description : Text tradedInstrument : Instrument.K quotedInstrument : Instrument.K observers : Parties - controller (view $ Service.asBase $ asService this).customer + controller (view $ asBase this).customer do - requestAndList this (toInterfaceContractId self) arg + requestAndList this arg nonconsuming choice RequestAndDelist : () with listingCid : ContractId Listing.I - controller (view $ Service.asBase $ asService this).customer + controller (view $ asBase this).customer do - requestAndDelist this (toInterfaceContractId self) arg + requestAndDelist this arg -- | Type constraint for requiring templates to implement `Service`. -type Implementation t = (HasToInterface t Service, Service.Implementation t) +type Implementation t = HasToInterface t Service class (Implementation t) => HasImplementation t instance HasImplementation Service -instance HasToInterface Service Service.I where _toInterface = asService -instance HasToInterface Service Base.I where _toInterface = Service.asBase . asService +instance HasToInterface Service Base.I where _toInterface = asBase diff --git a/src/daml/Daml/Finance/App/Interface/Listing/DelistingRequest.daml b/src/daml/Daml/Finance/App/Interface/Listing/DelistingRequest.daml index 681923a7..682f1b65 100644 --- a/src/daml/Daml/Finance/App/Interface/Listing/DelistingRequest.daml +++ b/src/daml/Daml/Finance/App/Interface/Listing/DelistingRequest.daml @@ -21,6 +21,7 @@ data View = View interface DelistingRequest where viewtype View -- ^ Interface view type. + asRemovable : Removable.I -- ^ Conversion to the `Removable` interface. diff --git a/src/daml/Daml/Finance/App/Interface/Listing/Listing.daml b/src/daml/Daml/Finance/App/Interface/Listing/Listing.daml index 5a3e4386..d7dc8b77 100644 --- a/src/daml/Daml/Finance/App/Interface/Listing/Listing.daml +++ b/src/daml/Daml/Finance/App/Interface/Listing/Listing.daml @@ -26,6 +26,7 @@ data View = View interface Listing where viewtype View -- ^ Interface view type. + asRemovable : Removable.I -- ^ Conversion to the `Removable` interface. diff --git a/src/daml/Daml/Finance/App/Interface/Listing/ListingRequest.daml b/src/daml/Daml/Finance/App/Interface/Listing/ListingRequest.daml index 966df9cd..ce97a5e8 100644 --- a/src/daml/Daml/Finance/App/Interface/Listing/ListingRequest.daml +++ b/src/daml/Daml/Finance/App/Interface/Listing/ListingRequest.daml @@ -26,6 +26,7 @@ data View = View interface ListingRequest where viewtype View -- ^ Interface view type. + asRemovable : Removable.I -- ^ Conversion to the `Removable` interface. diff --git a/src/daml/Daml/Finance/App/Interface/Listing/Service.daml b/src/daml/Daml/Finance/App/Interface/Listing/Service.daml index c7b837cb..0fc8dbeb 100644 --- a/src/daml/Daml/Finance/App/Interface/Listing/Service.daml +++ b/src/daml/Daml/Finance/App/Interface/Listing/Service.daml @@ -23,12 +23,16 @@ interface Service where asBase : Base.I -- ^ Conversion to base `Service` interface. + requestListing : RequestListing -> Update (ContractId ListingRequest.I) -- ^ Implementation of the `RequestListing` choice. + requestDelisting : RequestDelisting -> Update (ContractId DelistingRequest.I) -- ^ Implementation of the `RequestDelisting` choice. + list : List -> Update (ContractId Listing.I) -- ^ Implementation of the `List` choice. + delist : Delist -> Update () -- ^ Implementation of the `Delist` choice. diff --git a/src/daml/Daml/Finance/App/Issuance/Auto.daml b/src/daml/Daml/Finance/App/Issuance/Auto.daml index 255326ab..3e21db3f 100644 --- a/src/daml/Daml/Finance/App/Issuance/Auto.daml +++ b/src/daml/Daml/Finance/App/Issuance/Auto.daml @@ -3,17 +3,12 @@ module Daml.Finance.App.Issuance.Auto where -import DA.Assert ((===)) -import Daml.Finance.App.Issuance.Model qualified as Model +import Daml.Finance.App.Issuance.Service qualified as Service (T) import Daml.Finance.App.Interface.Base.Service qualified as Base (I, View(..)) -import Daml.Finance.App.Interface.Common.Util (fetchAndRemove) import Daml.Finance.App.Interface.Issuance.Auto qualified as Auto (HasImplementation, I, View(..), RequestAndDeissue(..), RequestAndIssue(..)) -import Daml.Finance.App.Interface.Issuance.DeissueRequest qualified as DeissueRequest (View(..)) -import Daml.Finance.App.Interface.Issuance.IssueRequest qualified as IssueRequest (View(..)) -import Daml.Finance.App.Interface.Issuance.Service qualified as Service (Deissue(..), Issue(..), I, RequestDeissue(..), RequestIssue(..), View(..)) -import Daml.Finance.Interface.Account.Account qualified as Account (Credit(..), Debit(..), I, exerciseInterfaceByKey) -import Daml.Finance.Interface.Account.Util (getAccount) -import Daml.Finance.Interface.Holding.Util (getAmount) +import Daml.Finance.App.Interface.Issuance.Service qualified as Service (Deissue(..), Issue(..), I, RequestDeissue(..), RequestIssue(..)) + +type T = Service instance Auto.HasImplementation Service @@ -32,43 +27,20 @@ template Service view = Base.View with operator; provider; customer terminate = pure () - interface instance Service.I for Service where - view = Service.View - asBase = toInterface @Base.I this - requestIssue Service.RequestIssue{issuanceId; description; quantity; account} = do - toInterfaceContractId <$> create Model.IssueRequest with operator; provider; customer; issuanceId; description; quantity; account - requestDeissue Service.RequestDeissue{issuanceId; holdingCid} = do - toInterfaceContractId <$> create Model.DeissueRequest with operator; provider; customer; issuanceId; holdingCid - issue Service.Issue{issueRequestCid} = do - IssueRequest.View{issuanceId; description; quantity; account} <- view <$> fetchAndRemove issueRequestCid - issuanceCid <- toInterfaceContractId <$> create Model.Issuance with operator; provider; customer; id = issuanceId; description; quantity - account.custodian === provider - account.owner === customer - holdingCid <- Account.exerciseInterfaceByKey @Account.I account provider Account.Credit with quantity - pure (issuanceCid, holdingCid) - deissue Service.Deissue{deissueRequestCid} = do - DeissueRequest.View{issuanceId; holdingCid} <- view <$> fetchAndRemove deissueRequestCid - holding <- fetch holdingCid - let - account = getAccount holding - amount = getAmount holding - account.custodian === provider - account.owner === customer - Account.exerciseInterfaceByKey @Account.I account provider Account.Debit with holdingCid - (issuanceCid, issuance) <- fetchByKey @Model.Issuance (operator, provider, issuanceId) - archive issuanceCid - toInterfaceContractId <$> create issuance with quantity = (issuance.quantity with amount = issuance.quantity.amount - amount) - interface instance Auto.I for Service where view = Auto.View - asService = toInterface @Service.I this - requestAndIssue self Auto.RequestAndIssue{issuanceId; description; quantity; account} = do - issueRequestCid <- exercise self Service.RequestIssue with issuanceId; description; quantity; account - exercise self Service.Issue with issueRequestCid - requestAndDeissue self Auto.RequestAndDeissue{issuanceId; holdingCid} = do - deissueRequestCid <- exercise self Service.RequestDeissue with issuanceId; holdingCid - exercise self Service.Deissue with deissueRequestCid + asBase = toInterface @Base.I this + + requestAndIssue Auto.RequestAndIssue{issuanceId; description; quantity; account} = do + serviceCid <- toInterfaceContractId @Service.I . fst <$> fetchByKey @Service.T (operator, provider, customer) + issueRequestCid <- exercise serviceCid Service.RequestIssue with issuanceId; description; quantity; account + exercise serviceCid Service.Issue with issueRequestCid + + requestAndDeissue Auto.RequestAndDeissue{issuanceId; holdingCid} = do + serviceCid <- toInterfaceContractId @Service.I . fst <$> fetchByKey @Service.T (operator, provider, customer) + deissueRequestCid <- exercise serviceCid Service.RequestDeissue with issuanceId; holdingCid + exercise serviceCid Service.Deissue with deissueRequestCid template Offer with diff --git a/src/daml/Daml/Finance/App/BackToBack/Service.daml b/src/daml/Daml/Finance/App/Issuance/BackToBack.daml similarity index 74% rename from src/daml/Daml/Finance/App/BackToBack/Service.daml rename to src/daml/Daml/Finance/App/Issuance/BackToBack.daml index f6d7261c..0ae716b2 100644 --- a/src/daml/Daml/Finance/App/BackToBack/Service.daml +++ b/src/daml/Daml/Finance/App/Issuance/BackToBack.daml @@ -1,24 +1,27 @@ -- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. -- SPDX-License-Identifier: Apache-2.0 -module Daml.Finance.App.BackToBack.Service where +module Daml.Finance.App.Issuance.BackToBack where import DA.List (head) import DA.Optional (fromSome) import DA.Set (fromList, singleton) -import Daml.Finance.App.Distribution.Subscription.Model (BackToBack, Offering(..)) +import Daml.Finance.App.Interface.Base.Service qualified as Base (I, View(..)) +import Daml.Finance.App.Interface.Issuance.BackToBack qualified as Service (CreateIssuance(..), HasImplementation, I, LockOffering(..), SettleOffering(..), View(..)) import Daml.Finance.App.Issuance.Model (Issuance(..)) -import Daml.Finance.Interface.Account.Account qualified as Account (Credit(..), K, R) +import Daml.Finance.Interface.Account.Account qualified as Account (Credit(..), R) import Daml.Finance.Interface.Holding.Fungible qualified as Fungible (Split(..), SplitResult(..)) import Daml.Finance.Interface.Holding.Base qualified as Holding (I, Acquire(..), I, LockType(..), Release(..)) import Daml.Finance.Interface.Holding.Util (getAmount) -import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (Q) -import Daml.Finance.Interface.Settlement.Factory qualified as Factory (I, Instruct(..)) +import Daml.Finance.Interface.Settlement.Factory qualified as Factory (Instruct(..)) import Daml.Finance.Interface.Settlement.Instruction qualified as Instruction (Allocate(..), Approve(..)) import Daml.Finance.Interface.Settlement.Batch qualified as Batch (Settle(..)) import Daml.Finance.Interface.Settlement.Types (Allocation(Pledge), Approval(TakeDelivery), Step(..)) import Daml.Finance.Interface.Util.Disclosure qualified as Disclosure (AddObservers(..), I) -import Daml.Finance.Interface.Types.Common (Id(..)) + +type T = Service + +instance Service.HasImplementation Service template Service with @@ -32,53 +35,45 @@ template Service key (operator, provider, customer) : (Party, Party, Party) maintainer key._1 - nonconsuming choice CreateIssuance : (ContractId Issuance, ContractId Holding.I, ContractId Holding.I) - with - id : Id - description : Text - quantity : Instrument.Q - customerAccount : Account.K - providerAccount : Account.K - controller customer - do + interface instance Base.I for Service where + view = Base.View with operator; provider; customer + + terminate = pure () + + interface instance Service.I for Service where + view = Service.View + + asBase = toInterface @Base.I this + + createIssuance Service.CreateIssuance{issuanceId; description; quantity; customerAccount; providerAccount} = do (_, customerRef) <- fetchByKey @Account.R customerAccount customerHoldingCid <- exercise customerRef.cid Account.Credit with quantity (_, providerRef) <- fetchByKey @Account.R providerAccount providerHoldingCid <- exercise providerRef.cid Account.Credit with quantity - providerHoldingCid <- coerceContractId <$> exercise (coerceContractId providerHoldingCid : ContractId Disclosure.I) Disclosure.AddObservers with disclosers = singleton provider; observersToAdd = (show id, singleton customer) - issuanceCid <- create Issuance with operator; provider; customer; id; description; quantity + providerHoldingCid <- coerceContractId <$> exercise (coerceContractId providerHoldingCid : ContractId Disclosure.I) Disclosure.AddObservers with disclosers = singleton provider; observersToAdd = (show issuanceId, singleton customer) + issuanceCid <- toInterfaceContractId <$> create Issuance with operator; provider; customer; id = issuanceId; description; quantity pure (issuanceCid, customerHoldingCid, providerHoldingCid) - nonconsuming choice LockOffering : BackToBack - with - backToBack : BackToBack - controller customer - do - b2bDeliverableCid <- coerceContractId <$> exercise (toInterfaceContractId backToBack.b2bDeliverableCid : ContractId Holding.I) Holding.Acquire with newLockers = fromList [customer]; context = backToBack.offeringId; lockType = Holding.Semaphore - issuerDeliverableCid <- coerceContractId <$> exercise (toInterfaceContractId backToBack.issuerDeliverableCid : ContractId Holding.I) Holding.Acquire with newLockers = fromList [provider]; context = backToBack.offeringId; lockType = Holding.Semaphore + lockOffering Service.LockOffering{backToBack} = do + b2bDeliverableCid <- coerceContractId <$> exercise (toInterfaceContractId backToBack.b2bDeliverableCid : ContractId Holding.I) Holding.Acquire with newLockers = fromList [customer]; context = show backToBack.offeringId; lockType = Holding.Semaphore + issuerDeliverableCid <- coerceContractId <$> exercise (toInterfaceContractId backToBack.issuerDeliverableCid : ContractId Holding.I) Holding.Acquire with newLockers = fromList [provider]; context = show backToBack.offeringId; lockType = Holding.Semaphore pure backToBack with b2bDeliverableCid; issuerDeliverableCid - nonconsuming choice SettleOffering : [ContractId Holding.I] - with - settlementFactoryCid : ContractId Factory.I - offeringCid : ContractId Offering - totalQuantity : Decimal - controller customer - do - offering <- fetch offeringCid + settleOffering Service.SettleOffering{settlementFactoryCid; offeringCid; totalQuantity} = do + offering <- view <$> fetch offeringCid let Some b2b = offering.backToBack totalNotional = totalQuantity * offering.price.amount delivery = Step with sender = b2b.party; receiver = offering.issuer; quantity = (offering.asset with amount = totalQuantity) payment = Step with sender = offering.issuer; receiver = b2b.party; quantity = (offering.price with amount = totalNotional) - (batchCid, [deliveryCid, paymentCid]) <- exercise settlementFactoryCid Factory.Instruct with instructors = singleton customer; settlers = singleton offering.issuer; id = Id offering.offeringId; contextId = None; steps = [ delivery, payment ]; description = "Settlement for offering " <> offering.offeringId + (batchCid, [deliveryCid, paymentCid]) <- exercise settlementFactoryCid Factory.Instruct with instructors = singleton customer; settlers = singleton offering.issuer; id = offering.id; contextId = None; steps = [ delivery, payment ]; description = "Settlement for offering " <> show offering.id b2bDeliverable <- fetch b2b.b2bDeliverableCid b2bSizedDeliverableCid <- if getAmount b2bDeliverable > totalQuantity then do Fungible.SplitResult{splitCids, rest} <- exercise b2b.b2bDeliverableCid Fungible.Split with amounts = [ totalQuantity ] - exercise (toInterfaceContractId (fromSome rest) : ContractId Holding.I) Holding.Release with context = offering.offeringId + exercise (toInterfaceContractId (fromSome rest) : ContractId Holding.I) Holding.Release with context = show offering.id pure $ head splitCids else pure b2b.b2bDeliverableCid issuerDeliverable <- fetch b2b.issuerDeliverableCid @@ -91,15 +86,7 @@ template Service paymentCid <- fst <$> exercise paymentCid Instruction.Allocate with actors = fromList [provider, customer]; allocation = Pledge $ coerceContractId issuerSizedDeliverableCid paymentCid <- exercise paymentCid Instruction.Approve with actors = fromList [provider, customer]; approval = TakeDelivery b2b.b2bReceivableAccount deliveredCids <- exercise batchCid Batch.Settle with actors = singleton customer - mapA (\cid -> exercise (toInterfaceContractId cid : ContractId Holding.I) Holding.Release with context = offering.offeringId) deliveredCids - - choice Terminate : () - with - actor : Party - controller actor - do - assert $ actor == operator || actor == customer || actor == provider - pure () + mapA (\cid -> exercise (toInterfaceContractId cid : ContractId Holding.I) Holding.Release with context = show offering.id) deliveredCids template Offer with diff --git a/src/daml/Daml/Finance/App/Issuance/Service.daml b/src/daml/Daml/Finance/App/Issuance/Service.daml index 021f5c20..74b3833d 100644 --- a/src/daml/Daml/Finance/App/Issuance/Service.daml +++ b/src/daml/Daml/Finance/App/Issuance/Service.daml @@ -15,6 +15,8 @@ import Daml.Finance.Interface.Account.Util (getAccount) import Daml.Finance.Interface.Holding.Util (getAmount) import Daml.Finance.App.Issuance.Model (DeissueRequest(..), Issuance(..), IssueRequest(..)) +type T = Service + instance Service.HasImplementation Service template Service diff --git a/src/daml/Daml/Finance/App/Lending/Model.daml b/src/daml/Daml/Finance/App/Lending/Model.daml index 3ecc8c8b..e77c8fe2 100644 --- a/src/daml/Daml/Finance/App/Lending/Model.daml +++ b/src/daml/Daml/Finance/App/Lending/Model.daml @@ -3,74 +3,101 @@ module Daml.Finance.App.Lending.Model where -import DA.Set (singleton) -import Daml.Finance.Interface.Account.Account qualified as Account (K, exerciseInterfaceByKey) +import DA.Set (fromList, singleton) +import Daml.Finance.App.Interface.Common.Removable qualified as Removable (I, View(..)) +import Daml.Finance.App.Interface.Lending.BorrowAgreement qualified as BorrowAgreement (I, Repay(..), View(..)) +import Daml.Finance.App.Interface.Lending.BorrowOffer qualified as BorrowOffer (I, View(..)) +import Daml.Finance.App.Interface.Lending.BorrowOfferRequest qualified as BorrowOfferRequest (I, View(..)) +import Daml.Finance.Interface.Account.Account qualified as Account (exerciseInterfaceByKey) import Daml.Finance.Interface.Holding.Base qualified as Holding (I, Release(..)) import Daml.Finance.Interface.Holding.Transferable qualified as Transferable (I, Transfer(..)) import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (Q) import Daml.Finance.Interface.Util.Disclosure qualified as Disclosure (I, RemoveObservers(..)) +import Daml.Finance.Interface.Types.Common (AccountKey, Id) template BorrowOfferRequest with operator : Party provider : Party customer : Party - id : Text + dealId : Id + description : Text borrowed : Instrument.Q maturity : Date where signatory operator, provider, customer - key (operator, provider, id) : (Party, Party, Text) + key (operator, provider, dealId) : (Party, Party, Id) maintainer key._1 + interface instance Removable.I for BorrowOfferRequest where + view = Removable.View with removers = fromList [operator, provider, customer] + + interface instance BorrowOfferRequest.I for BorrowOfferRequest where + view = BorrowOfferRequest.View with operator; provider; customer; dealId; description; borrowed; maturity + + asRemovable = toInterface @Removable.I this + template BorrowOffer with operator : Party provider : Party customer : Party - id : Text + dealId : Id + description : Text borrowed : Instrument.Q maturity : Date interest : Instrument.Q collateral : Instrument.Q borrowedCid : ContractId Transferable.I - lenderBorrowedAccount : Account.K - lenderInterestAccount : Account.K + lenderBorrowedAccount : AccountKey + lenderInterestAccount : AccountKey where signatory operator, provider, customer - key (operator, provider, id) : (Party, Party, Text) + key (operator, provider, dealId) : (Party, Party, Id) maintainer key._1 + interface instance Removable.I for BorrowOffer where + view = Removable.View with removers = fromList [operator, provider, customer] + + interface instance BorrowOffer.I for BorrowOffer where + view = BorrowOffer.View with operator; provider; customer; dealId; description; borrowed; maturity; interest; collateral; borrowedCid; lenderBorrowedAccount; lenderInterestAccount + + asRemovable = toInterface @Removable.I this + template BorrowAgreement with operator : Party provider : Party customer : Party - id : Text + dealId : Id + description : Text borrowed : Instrument.Q maturity : Date interest : Instrument.Q collateral : Instrument.Q collateralCid : ContractId Transferable.I - lenderBorrowedAccount : Account.K - lenderInterestAccount : Account.K + lenderBorrowedAccount : AccountKey + lenderInterestAccount : AccountKey where signatory operator, provider, customer - key (operator, provider, id) : (Party, Party, Text) + key (operator, provider, dealId) : (Party, Party, Id) maintainer key._1 - choice Repay : (ContractId Transferable.I, ContractId Transferable.I, ContractId Transferable.I) - with - borrowedCid : ContractId Transferable.I - interestCid : ContractId Transferable.I - controller customer - do + interface instance Removable.I for BorrowAgreement where + view = Removable.View with removers = fromList [operator, provider, customer] + + interface instance BorrowAgreement.I for BorrowAgreement where + view = BorrowAgreement.View with operator; provider; customer; dealId; description; borrowed; maturity; interest; collateral; collateralCid; lenderBorrowedAccount; lenderInterestAccount + + asRemovable = toInterface @Removable.I this + + repay BorrowAgreement.Repay{borrowedCid; interestCid} = do borrowedCid <- exercise borrowedCid Transferable.Transfer with actors = singleton customer; newOwnerAccount = lenderBorrowedAccount interestCid <- exercise interestCid Transferable.Transfer with actors = singleton customer; newOwnerAccount = lenderInterestAccount - unlockedCid <- coerceContractId <$> exercise (toInterfaceContractId collateralCid : ContractId Holding.I) Holding.Release with context = id - Account.exerciseInterfaceByKey @Disclosure.I lenderBorrowedAccount provider Disclosure.RemoveObservers with disclosers = singleton customer; observersToRemove = (id, singleton customer) - Account.exerciseInterfaceByKey @Disclosure.I lenderInterestAccount provider Disclosure.RemoveObservers with disclosers = singleton customer; observersToRemove = (id, singleton customer) + unlockedCid <- coerceContractId <$> exercise (toInterfaceContractId collateralCid : ContractId Holding.I) Holding.Release with context = show dealId + Account.exerciseInterfaceByKey @Disclosure.I lenderBorrowedAccount provider Disclosure.RemoveObservers with disclosers = singleton customer; observersToRemove = (show dealId, singleton customer) + Account.exerciseInterfaceByKey @Disclosure.I lenderInterestAccount provider Disclosure.RemoveObservers with disclosers = singleton customer; observersToRemove = (show dealId, singleton customer) pure (unlockedCid, borrowedCid, interestCid) diff --git a/src/daml/Daml/Finance/App/Lending/Service.daml b/src/daml/Daml/Finance/App/Lending/Service.daml index 5c6c5b7e..3930f478 100644 --- a/src/daml/Daml/Finance/App/Lending/Service.daml +++ b/src/daml/Daml/Finance/App/Lending/Service.daml @@ -4,14 +4,21 @@ module Daml.Finance.App.Lending.Service where import DA.Set (singleton) -import Daml.Finance.App.Lending.Model (BorrowAgreement(..), BorrowOffer(..), BorrowOfferRequest(..)) -import Daml.Finance.App.Util (fetchAndArchive) -import Daml.Finance.Interface.Account.Account qualified as Account (K, exerciseInterfaceByKey) +import Daml.Finance.App.Lending.Model qualified as Model (BorrowAgreement(..), BorrowOffer(..), BorrowOfferRequest(..)) +import Daml.Finance.App.Interface.Base.Service qualified as Base (I, View(..)) +import Daml.Finance.App.Interface.Common.Util (fetchAndRemove) +import Daml.Finance.App.Interface.Lending.BorrowOffer qualified as BorrowOffer (View(..)) +import Daml.Finance.App.Interface.Lending.BorrowOfferRequest qualified as BorrowOfferRequest (View(..)) +import Daml.Finance.App.Interface.Lending.Service qualified as Service (AcceptBorrowOffer(..), CreateBorrowOffer(..), HasImplementation, I, RequestBorrowOffer(..), View(..)) +import Daml.Finance.Interface.Account.Account qualified as Account (exerciseInterfaceByKey) import Daml.Finance.Interface.Holding.Transferable qualified as Transferable (I, Transfer(..)) -import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (Q) import Daml.Finance.Interface.Holding.Base qualified as Holding (Acquire(..), I, LockType(..), Release(..)) import Daml.Finance.Interface.Util.Disclosure qualified as Disclosure (I, AddObservers(..)) +type T = Service + +instance Service.HasImplementation Service + template Service with operator : Party @@ -23,52 +30,32 @@ template Service key (operator, provider, customer) : (Party, Party, Party) maintainer key._1 - nonconsuming choice RequestBorrowOffer : ContractId BorrowOfferRequest - with - id : Text - borrowed : Instrument.Q - maturity : Date - controller customer - do - create BorrowOfferRequest with operator; provider; customer; id; borrowed; maturity + interface instance Base.I for Service where + view = Base.View with operator; provider; customer + terminate = pure () - nonconsuming choice AcceptBorrowOffer : (ContractId Transferable.I, ContractId BorrowAgreement) - with - borrowOfferCid : ContractId BorrowOffer - collateralCid : ContractId Transferable.I - account : Account.K - controller customer - do - BorrowOffer{operator; provider; customer; id; borrowed; maturity; interest; collateral; borrowedCid; lenderBorrowedAccount; lenderInterestAccount} <- fetchAndArchive borrowOfferCid - unlockedBorrowedCid <- exercise (coerceContractId borrowedCid : ContractId Holding.I) Holding.Release with context = id + interface instance Service.I for Service where + view = Service.View + + asBase = toInterface @Base.I this + + requestBorrowOffer Service.RequestBorrowOffer{dealId; description; borrowed; maturity} = do + toInterfaceContractId <$> create Model.BorrowOfferRequest with operator; provider; customer; dealId; description; borrowed; maturity + + acceptBorrowOffer Service.AcceptBorrowOffer{borrowOfferCid; collateralCid; account} = do + BorrowOffer.View{operator; provider; customer; dealId; description; borrowed; maturity; interest; collateral; borrowedCid; lenderBorrowedAccount; lenderInterestAccount} <- view <$> fetchAndRemove borrowOfferCid + unlockedBorrowedCid <- exercise (coerceContractId borrowedCid : ContractId Holding.I) Holding.Release with context = show dealId transferredCid <- exercise (coerceContractId unlockedBorrowedCid : ContractId Transferable.I) Transferable.Transfer with actors = singleton customer; newOwnerAccount = account - lockedCollateralCid : ContractId Transferable.I <- coerceContractId <$> exercise (toInterfaceContractId collateralCid : ContractId Holding.I) Holding.Acquire with newLockers = (singleton provider); context = id; lockType = Holding.Semaphore - borrowAgreementCid <- create BorrowAgreement with operator; provider; customer; id; borrowed; maturity; interest; collateral; collateralCid = lockedCollateralCid; lenderBorrowedAccount; lenderInterestAccount + lockedCollateralCid : ContractId Transferable.I <- coerceContractId <$> exercise (toInterfaceContractId collateralCid : ContractId Holding.I) Holding.Acquire with newLockers = (singleton provider); context = show dealId; lockType = Holding.Semaphore + borrowAgreementCid <- toInterfaceContractId <$> create Model.BorrowAgreement with operator; provider; customer; dealId; description; borrowed; maturity; interest; collateral; collateralCid = lockedCollateralCid; lenderBorrowedAccount; lenderInterestAccount pure (transferredCid, borrowAgreementCid) - nonconsuming choice CreateBorrowOffer : ContractId BorrowOffer - with - borrowOfferRequestCid : ContractId BorrowOfferRequest - interest : Instrument.Q - collateral : Instrument.Q - borrowedCid : ContractId Transferable.I - lenderBorrowedAccount : Account.K - lenderInterestAccount : Account.K - controller provider - do - BorrowOfferRequest{operator; provider; customer; id; borrowed; maturity} <- fetchAndArchive borrowOfferRequestCid - Account.exerciseInterfaceByKey @Disclosure.I lenderBorrowedAccount customer Disclosure.AddObservers with disclosers = singleton provider; observersToAdd = (id, singleton customer) - Account.exerciseInterfaceByKey @Disclosure.I lenderInterestAccount customer Disclosure.AddObservers with disclosers = singleton provider; observersToAdd = (id, singleton customer) - lockedBorrowedCid : ContractId Transferable.I <- coerceContractId <$> exercise (toInterfaceContractId borrowedCid : ContractId Holding.I) Holding.Acquire with newLockers = (singleton customer); context = id; lockType = Holding.Semaphore - create BorrowOffer with operator; provider; customer; id; borrowed; maturity; interest; collateral; borrowedCid = lockedBorrowedCid; lenderBorrowedAccount; lenderInterestAccount - - choice Terminate : () - with - actor : Party - controller actor - do - assert $ actor == operator || actor == provider || actor == customer - pure () + createBorrowOffer Service.CreateBorrowOffer{borrowOfferRequestCid; interest; collateral; borrowedCid; lenderBorrowedAccount; lenderInterestAccount} = do + BorrowOfferRequest.View{operator; provider; customer; dealId; description; borrowed; maturity} <- view <$> fetchAndRemove borrowOfferRequestCid + Account.exerciseInterfaceByKey @Disclosure.I lenderBorrowedAccount customer Disclosure.AddObservers with disclosers = singleton provider; observersToAdd = (show dealId, singleton customer) + Account.exerciseInterfaceByKey @Disclosure.I lenderInterestAccount customer Disclosure.AddObservers with disclosers = singleton provider; observersToAdd = (show dealId, singleton customer) + lockedBorrowedCid : ContractId Transferable.I <- coerceContractId <$> exercise (toInterfaceContractId borrowedCid : ContractId Holding.I) Holding.Acquire with newLockers = (singleton customer); context = show dealId; lockType = Holding.Semaphore + toInterfaceContractId <$> create Model.BorrowOffer with operator; provider; customer; dealId; description; borrowed; maturity; interest; collateral; borrowedCid = lockedBorrowedCid; lenderBorrowedAccount; lenderInterestAccount template Offer with diff --git a/src/daml/Daml/Finance/App/Lifecycle/Service.daml b/src/daml/Daml/Finance/App/Lifecycle/Service.daml index 9c6d3b24..3ac11883 100644 --- a/src/daml/Daml/Finance/App/Lifecycle/Service.daml +++ b/src/daml/Daml/Finance/App/Lifecycle/Service.daml @@ -3,25 +3,24 @@ module Daml.Finance.App.Lifecycle.Service where -import ContingentClaims.Core.Claim (Claim) import ContingentClaims.Core.Observation (Observation(..)) import ContingentClaims.Lifecycle.Lifecycle qualified as Lifecycle -import ContingentClaims.Lifecycle.Util (expiry, fixings, payoffs) -import ContingentClaims.Valuation.Stochastic (Expr) +import ContingentClaims.Lifecycle.Util qualified as Util (expiry, fixings, payoffs) +import Daml.Finance.App.Interface.Base.Service qualified as Base (I, View(..)) +import Daml.Finance.App.Interface.Lifecycle.Service qualified as Service (DeclareDividend(..), DeclareReplacement(..), DeclareStockSplit(..), Expiry(..), Fixings(..), GetCurrentClaims(..), HasImplementation, I, Lifecycle(..), Multipliers(..), Payoffs(..), PreviewLifecycle(..), PreviewPricing(..), SimulateLifecycle(..), Underlyings(..), View(..)) +import Daml.Finance.App.Lifecycle.Pricing qualified as Pricing +import Daml.Finance.App.Structuring.Auto.Service qualified as Structuring import Daml.Finance.Claims.Util.Lifecycle qualified as Claim (lifecycle, lifecycleClaims, timeEvent) -import Daml.Finance.Interface.Data.NumericObservable qualified as NumericObservable (I) -import Daml.Finance.Interface.Data.TimeObservable qualified as TimeObservable (I) -import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (I, K, Q, R) +import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (I, R) import Daml.Finance.Interface.Instrument.Equity.Instrument qualified as Equity (I, DeclareDividend(..), DeclareReplacement(..), DeclareStockSplit(..)) -import Daml.Finance.Interface.Claims.Claim qualified as Claim (Claim, getClaims, GetClaims(..)) -import Daml.Finance.Interface.Claims.Types (C, Pending, TaggedClaim) -import Daml.Finance.Interface.Lifecycle.Effect qualified as Effect (I) -import Daml.Finance.Interface.Lifecycle.Event qualified as Event (I) +import Daml.Finance.Interface.Claims.Claim qualified as Claim (getClaims, GetClaims(..)) import Daml.Finance.Interface.Lifecycle.Rule.Lifecycle qualified as Lifecycle (I, Evolve(..)) import Daml.Finance.Interface.Util.Disclosure qualified as Disclosure (I) -import Daml.Finance.Interface.Types.Common (Id, InstrumentKey(..)) -import Daml.Finance.App.Lifecycle.Pricing qualified as Pricing -import Daml.Finance.App.Structuring.Auto.Service qualified as Structuring +import Daml.Finance.Interface.Types.Common (InstrumentKey(..)) + +type T = Service + +instance Service.HasImplementation Service template Service with @@ -36,17 +35,17 @@ template Service key (operator, provider, customer) : (Party, Party, Party) maintainer key._1 - nonconsuming choice DeclareDividend : [ContractId Effect.I] - with - timeObservableCid : ContractId TimeObservable.I - equity : Instrument.K - newVersion : Text - id : Id - description : Text - effectiveDate : Date - perUnitDistribution : [ Instrument.Q ] - controller customer - do + interface instance Base.I for Service where + view = Base.View with operator; provider; customer + + terminate = pure () + + interface instance Service.I for Service where + view = Service.View with distributionRuleCid; replacementRuleCid + + asBase = toInterface @Base.I this + + declareDividend Service.DeclareDividend{timeObservableCid; equity; newVersion; id; description; effectiveDate; perUnitDistribution} = do now <- getTime (_, equityRef) <- fetchByKey @Instrument.R equity equity <- fetch equityRef.cid @@ -59,31 +58,12 @@ template Service eventCid <- exercise (coerceContractId equityRef.cid : ContractId Equity.I) Equity.DeclareDividend with id; description; effectiveDate; newInstrument; perUnitDistribution snd <$> exercise distributionRuleCid Lifecycle.Evolve with ruleName = "Dividend"; eventCid; timeObservableCid; observableCids = [] - nonconsuming choice DeclareReplacement : [ContractId Effect.I] - with - timeObservableCid : ContractId TimeObservable.I - equity : Instrument.K - id : Id - description : Text - effectiveDate : Date - perUnitReplacement : [ Instrument.Q ] - controller customer - do + declareReplacement Service.DeclareReplacement{timeObservableCid; equity; id; description; effectiveDate; perUnitReplacement} = do (_, equityRef) <- fetchByKey @Instrument.R equity eventCid <- exercise (coerceContractId equityRef.cid : ContractId Equity.I) Equity.DeclareReplacement with id; description; effectiveDate; perUnitReplacement snd <$> exercise replacementRuleCid Lifecycle.Evolve with ruleName = "StockSplit"; eventCid; timeObservableCid; observableCids = [] - nonconsuming choice DeclareStockSplit : [ContractId Effect.I] - with - timeObservableCid : ContractId TimeObservable.I - equity : Instrument.K - newVersion : Text - id : Id - description : Text - effectiveDate : Date - adjustmentFactor : Decimal - controller customer - do + declareStockSplit Service.DeclareStockSplit{timeObservableCid; equity; newVersion; id; description; effectiveDate; adjustmentFactor} = do now <- getTime (_, equityRef) <- fetchByKey @Instrument.R equity equity <- fetch equityRef.cid @@ -96,24 +76,13 @@ template Service eventCid <- exercise (coerceContractId equityRef.cid : ContractId Equity.I) Equity.DeclareStockSplit with id; description; effectiveDate; newInstrument; adjustmentFactor snd <$> exercise replacementRuleCid Lifecycle.Evolve with ruleName = "StockSplit"; eventCid; timeObservableCid; observableCids = [] - nonconsuming choice PreviewLifecycle : ([TaggedClaim], [Pending]) - with - today : Time - observableCids : [ContractId NumericObservable.I] - instrumentCid : ContractId Claim.Claim - controller customer - do - instrument <- fetch instrumentCid - claims <- exercise self GetCurrentClaims with instrumentCid; observableCids - Claim.lifecycleClaims observableCids ((view instrument).acquisitionTime) claims [Claim.timeEvent today] + previewLifecycle Service.PreviewLifecycle{today; observableCids; instrumentCid} = do + hasClaims <- fetch instrumentCid + instrument <- fetch (coerceContractId instrumentCid : ContractId Instrument.I) + claims <- fst <$> Claim.lifecycle customer observableCids hasClaims [Claim.timeEvent (view instrument).validAsOf] + Claim.lifecycleClaims observableCids ((view hasClaims).acquisitionTime) claims [Claim.timeEvent today] - nonconsuming choice SimulateLifecycle : [[Lifecycle.Pending Time Instrument.K]] - with - today : Time - prices : [Decimal] - instrumentCid : ContractId Claim.Claim - controller customer - do + simulateLifecycle Service.SimulateLifecycle{today; prices; instrumentCid} = do instrument <- fetch instrumentCid taggedClaims <- Claim.getClaims instrument $ Claim.GetClaims with actor = customer let @@ -123,82 +92,36 @@ template Service pure result.pending mapA simulate prices - nonconsuming choice GetCurrentClaims : [TaggedClaim] - with - instrumentCid : ContractId Claim.Claim - observableCids : [ContractId NumericObservable.I] - controller customer - do + getCurrentClaims Service.GetCurrentClaims{instrumentCid; observableCids} = do hasClaims <- fetch instrumentCid instrument <- fetch (coerceContractId instrumentCid : ContractId Instrument.I) fst <$> Claim.lifecycle customer observableCids hasClaims [Claim.timeEvent (view instrument).validAsOf] - nonconsuming choice Lifecycle : (ContractId Lifecycle.I, [ContractId Effect.I]) - with - ruleName : Text - eventCid : ContractId Event.I - timeObservableCid : ContractId TimeObservable.I - observableCids : [ContractId NumericObservable.I] - lifecyclableCid : ContractId Lifecycle.I - controller customer - do + lifecycle Service.Lifecycle{ruleName; eventCid; timeObservableCid; observableCids; lifecyclableCid} = do exercise lifecyclableCid Lifecycle.Evolve with ruleName; eventCid; timeObservableCid; observableCids - nonconsuming choice Expiry : Optional Time - with - claims : C - controller customer - do - pure $ expiry claims + expiry Service.Expiry{claims} = do + pure $ Util.expiry claims - nonconsuming choice Underlying : [Instrument.K] - with - claims : C - controller customer - do - pure $ snd <$> payoffs claims + underlyings Service.Underlyings{claims} = do + pure $ snd <$> Util.payoffs claims - nonconsuming choice Payoffs : [(Observation Time Decimal Text, Instrument.K)] - with - claims : C - controller customer - do - pure $ payoffs claims + payoffs Service.Payoffs{claims} = do + pure $ Util.payoffs claims - nonconsuming choice Fixings : [Time] - with - claims : C - controller customer - do - pure $ fixings claims + fixings Service.Fixings{claims} = do + pure $ Util.fixings claims - nonconsuming choice Multipliers : [Decimal] - with - claims : C - controller customer - do + multipliers Service.Multipliers{claims} = do let getConst : (Observation Time Decimal a, b) -> [Decimal] getConst (Const x, _) = [x] getConst _ = [] - return $ concatMap getConst $ payoffs claims + return $ concatMap getConst $ Util.payoffs claims - nonconsuming choice PreviewPricing : (Expr Text, Text) - with - ccy : Text - claims : Claim Text Decimal Text Text - controller customer - do + previewPricing Service.PreviewPricing{ccy; claims} = do let formula = Pricing.valueClaim ccy claims pure (formula, Pricing.print formula) - choice Terminate : () - with - actor : Party - controller actor - do - assert $ actor == operator || actor == provider || actor == customer - pure () - template Offer with operator : Party diff --git a/src/daml/Daml/Finance/App/Listing/Auto.daml b/src/daml/Daml/Finance/App/Listing/Auto.daml index 616c2053..235a65d6 100644 --- a/src/daml/Daml/Finance/App/Listing/Auto.daml +++ b/src/daml/Daml/Finance/App/Listing/Auto.daml @@ -3,14 +3,10 @@ module Daml.Finance.App.Listing.Auto where -import Daml.Finance.App.Listing.Model qualified as Model +import Daml.Finance.App.Listing.Service qualified as Service (T) import Daml.Finance.App.Interface.Base.Service qualified as Base (I, View(..)) -import Daml.Finance.App.Interface.Common.Removable qualified as Removable (I, Remove(..)) -import Daml.Finance.App.Interface.Common.Util (fetchAndRemove) import Daml.Finance.App.Interface.Listing.Auto qualified as Auto (HasImplementation, I, View(..), RequestAndDelist(..), RequestAndList(..)) -import Daml.Finance.App.Interface.Listing.DelistingRequest qualified as DelistingRequest (View(..)) -import Daml.Finance.App.Interface.Listing.ListingRequest qualified as ListingRequest (View(..)) -import Daml.Finance.App.Interface.Listing.Service qualified as Service (Delist(..), List(..), I, RequestDelisting(..), RequestListing(..), View(..)) +import Daml.Finance.App.Interface.Listing.Service qualified as Service (Delist(..), List(..), I, RequestDelisting(..), RequestListing(..)) instance Auto.HasImplementation Service @@ -29,29 +25,20 @@ template Service view = Base.View with operator; provider; customer terminate = pure () - interface instance Service.I for Service where - view = Service.View - asBase = toInterface @Base.I this - requestListing Service.RequestListing{listingId; description; tradedInstrument; quotedInstrument; observers} = do - toInterfaceContractId <$> create Model.ListingRequest with operator; provider; customer; listingId; description; tradedInstrument; quotedInstrument; observers - requestDelisting Service.RequestDelisting{listingCid} = do - toInterfaceContractId <$> create Model.DelistingRequest with operator; provider; customer; listingCid - list Service.List{listingRequestCid} = do - ListingRequest.View{listingId; description; tradedInstrument; quotedInstrument; observers} <- view <$> fetchAndRemove listingRequestCid - toInterfaceContractId <$> create Model.Listing with operator; provider; customer; id = listingId; description; tradedInstrument; quotedInstrument; observers - delist Service.Delist{delistingRequestCid} = do - DelistingRequest.View{listingCid} <- view <$> fetchAndRemove delistingRequestCid - exercise (toInterfaceContractId @Removable.I listingCid) Removable.Remove - interface instance Auto.I for Service where view = Auto.View - asService = toInterface @Service.I this - requestAndList self Auto.RequestAndList{listingId; description; tradedInstrument; quotedInstrument; observers} = do - listingRequestCid <- exercise self Service.RequestListing with listingId; description; tradedInstrument; quotedInstrument; observers - exercise self Service.List with listingRequestCid - requestAndDelist self Auto.RequestAndDelist{listingCid} = do - delistingRequestCid <- exercise self Service.RequestDelisting with listingCid - exercise self Service.Delist with delistingRequestCid + + asBase = toInterface @Base.I this + + requestAndList Auto.RequestAndList{listingId; description; tradedInstrument; quotedInstrument; observers} = do + serviceCid <- toInterfaceContractId @Service.I . fst <$> fetchByKey @Service.T (operator, provider, customer) + listingRequestCid <- exercise serviceCid Service.RequestListing with listingId; description; tradedInstrument; quotedInstrument; observers + exercise serviceCid Service.List with listingRequestCid + + requestAndDelist Auto.RequestAndDelist{listingCid} = do + serviceCid <- toInterfaceContractId @Service.I . fst <$> fetchByKey @Service.T (operator, provider, customer) + delistingRequestCid <- exercise serviceCid Service.RequestDelisting with listingCid + exercise serviceCid Service.Delist with delistingRequestCid template Offer with diff --git a/src/daml/Daml/Finance/App/Listing/Model.daml b/src/daml/Daml/Finance/App/Listing/Model.daml index 3747a735..94e21c07 100644 --- a/src/daml/Daml/Finance/App/Listing/Model.daml +++ b/src/daml/Daml/Finance/App/Listing/Model.daml @@ -35,6 +35,7 @@ template Listing interface instance Listing.I for Listing where view = Listing.View with operator; provider; customer; id; description; tradedInstrument; quotedInstrument; observers + asRemovable = toInterface @Removable.I this template ListingRequest diff --git a/src/daml/Daml/Finance/App/Listing/Service.daml b/src/daml/Daml/Finance/App/Listing/Service.daml index 2106d21b..b5751b16 100644 --- a/src/daml/Daml/Finance/App/Listing/Service.daml +++ b/src/daml/Daml/Finance/App/Listing/Service.daml @@ -8,9 +8,13 @@ import Daml.Finance.App.Interface.Common.Removable qualified as Removable (I, Re import Daml.Finance.App.Interface.Common.Util (fetchAndRemove) import Daml.Finance.App.Interface.Listing.ListingRequest qualified as ListingRequest (View(..)) import Daml.Finance.App.Interface.Listing.DelistingRequest qualified as DelistingRequest (View(..)) -import Daml.Finance.App.Interface.Listing.Service qualified as Service +import Daml.Finance.App.Interface.Listing.Service qualified as Service (Delist(..), HasImplementation, I, List(..), RequestDelisting(..), RequestListing(..), View(..)) import Daml.Finance.App.Listing.Model qualified as Model +type T = Service + +instance Service.HasImplementation Service + template Service with operator : Party @@ -24,18 +28,24 @@ template Service interface instance Base.I for Service where view = Base.View with operator; provider; customer + terminate = pure () interface instance Service.I for Service where view = Service.View + asBase = toInterface @Base.I this + requestListing Service.RequestListing{listingId; description; tradedInstrument; quotedInstrument; observers} = do toInterfaceContractId <$> create Model.ListingRequest with operator; provider; customer; listingId; description; tradedInstrument; quotedInstrument; observers + requestDelisting Service.RequestDelisting{listingCid} = do toInterfaceContractId <$> create Model.DelistingRequest with operator; provider; customer; listingCid + list Service.List{listingRequestCid} = do ListingRequest.View{listingId; description; tradedInstrument; quotedInstrument; observers} <- view <$> fetchAndRemove listingRequestCid toInterfaceContractId <$> create Model.Listing with operator; provider; customer; id = listingId; description; tradedInstrument; quotedInstrument; observers + delist Service.Delist{delistingRequestCid} = do DelistingRequest.View{listingCid} <- view <$> fetchAndRemove delistingRequestCid exercise (toInterfaceContractId @Removable.I listingCid) Removable.Remove diff --git a/src/daml/Daml/Finance/App/Role/Custodian.daml b/src/daml/Daml/Finance/App/Role/Custodian.daml index ba41457e..415f77ab 100644 --- a/src/daml/Daml/Finance/App/Role/Custodian.daml +++ b/src/daml/Daml/Finance/App/Role/Custodian.daml @@ -3,14 +3,14 @@ module Daml.Finance.App.Role.Custodian where -import Daml.Finance.App.BackToBack.Service qualified as BackToBack (Approve(..), Offer(..), Request, Service, Terminate(..)) import Daml.Finance.App.Custody.Auto qualified as CustodyAuto (Approve(..), Offer(..), Request, Service) import Daml.Finance.App.Custody.Service qualified as Custody (Approve(..), Offer(..), Request, Service) import Daml.Finance.App.Interface.Base.Service qualified as Base (I, Terminate(..)) import Daml.Finance.App.Issuance.Auto qualified as IssuanceAuto (Approve(..), Offer(..), Request, Service) +import Daml.Finance.App.Issuance.BackToBack qualified as BackToBack (Approve(..), Offer(..), Request, Service) import Daml.Finance.App.Issuance.Service qualified as Issuance (Approve(..), Offer(..), Request, Service) -import Daml.Finance.App.Lending.Service qualified as Lending (Approve(..), Offer(..), Request, Service, Terminate(..)) -import Daml.Finance.App.Lifecycle.Service qualified as Lifecycle (Approve(..), Offer(..), Request, Service, Terminate(..)) +import Daml.Finance.App.Lending.Service qualified as Lending (Approve(..), Offer(..), Request, Service) +import Daml.Finance.App.Lifecycle.Service qualified as Lifecycle (Approve(..), Offer(..), Request, Service) import Daml.Finance.App.Settlement.Service qualified as Settlement (Approve(..), Offer(..), Request, Service, Terminate(..)) import Daml.Finance.App.Structuring.Auto.Service qualified as StructuringAuto (Approve(..), Offer(..), Request, Service, Terminate(..)) import Daml.Finance.App.Structuring.Service qualified as Structuring (Approve(..), Factories, Offer(..), Request, Service, Terminate(..)) @@ -149,7 +149,8 @@ template Role customer : Party controller provider do - exerciseByKey @BackToBack.Service (operator, provider, customer) BackToBack.Terminate with actor = provider + (serviceCid, _) <- fetchByKey @BackToBack.Service (operator, provider, customer) + exercise (toInterfaceContractId @Base.I serviceCid) Base.Terminate with actor = provider nonconsuming choice OfferSettlementService : ContractId Settlement.Offer with @@ -239,7 +240,8 @@ template Role customer : Party controller provider do - exerciseByKey @Lifecycle.Service (operator, provider, customer) Lifecycle.Terminate with actor = provider + (serviceCid, _) <- fetchByKey @Lifecycle.Service (operator, provider, customer) + exercise (toInterfaceContractId @Base.I serviceCid) Base.Terminate with actor = provider nonconsuming choice OfferLendingService : ContractId Lending.Offer with @@ -260,7 +262,8 @@ template Role customer : Party controller provider do - exerciseByKey @Lending.Service (operator, provider, customer) Lending.Terminate with actor = provider + (serviceCid, _) <- fetchByKey @Lending.Service (operator, provider, customer) + exercise (toInterfaceContractId @Base.I serviceCid) Base.Terminate with actor = provider choice TerminateRole: () controller operator diff --git a/src/daml/Daml/Finance/App/Role/Distributor.daml b/src/daml/Daml/Finance/App/Role/Distributor.daml index 213e2ea6..2d6d7711 100644 --- a/src/daml/Daml/Finance/App/Role/Distributor.daml +++ b/src/daml/Daml/Finance/App/Role/Distributor.daml @@ -7,9 +7,9 @@ import Daml.Finance.App.Distribution.Auction.Auto qualified as AuctionAuto (Appr import Daml.Finance.App.Distribution.Auction.Service qualified as Auction (Approve(..), Offer(..), Request, Service) import Daml.Finance.App.Distribution.Bidding.Auto qualified as BiddingAuto (Approve(..), Offer(..), Request, Service) import Daml.Finance.App.Distribution.Bidding.Service qualified as Bidding (Approve(..), Offer(..), Request, Service) -import Daml.Finance.App.Distribution.Fund.Service qualified as Fund (Approve(..), Offer(..), Request, Service, Terminate(..)) -import Daml.Finance.App.Distribution.Investment.Service qualified as Investment (Approve(..), Offer(..), Request, Service, Terminate(..)) -import Daml.Finance.App.Distribution.Subscription.Service qualified as Subscription (Approve(..), Offer(..), Request, Service, Terminate(..)) +import Daml.Finance.App.Distribution.Fund.Service qualified as Fund (Approve(..), Offer(..), Request, Service) +import Daml.Finance.App.Distribution.Investment.Service qualified as Investment (Approve(..), Offer(..), Request, Service) +import Daml.Finance.App.Distribution.Subscription.Service qualified as Subscription (Approve(..), Offer(..), Request, Service) import Daml.Finance.App.Interface.Base.Service qualified as Base (I, Terminate(..)) template Role @@ -130,7 +130,8 @@ template Role customer : Party controller provider do - exerciseByKey @Subscription.Service (operator, provider, customer) Subscription.Terminate with actor = provider + (serviceCid, _) <- fetchByKey @Subscription.Service (operator, provider, customer) + exercise (toInterfaceContractId @Base.I serviceCid) Base.Terminate with actor = provider nonconsuming choice OfferInvestmentService : ContractId Investment.Offer with @@ -151,7 +152,8 @@ template Role customer : Party controller provider do - exerciseByKey @Investment.Service (operator, provider, customer) Investment.Terminate with actor = provider + (serviceCid, _) <- fetchByKey @Investment.Service (operator, provider, customer) + exercise (toInterfaceContractId @Base.I serviceCid) Base.Terminate with actor = provider nonconsuming choice OfferFundService : ContractId Fund.Offer with @@ -172,7 +174,8 @@ template Role customer : Party controller provider do - exerciseByKey @Fund.Service (operator, provider, customer) Fund.Terminate with actor = provider + (serviceCid, _) <- fetchByKey @Fund.Service (operator, provider, customer) + exercise (toInterfaceContractId @Base.I serviceCid) Base.Terminate with actor = provider choice Terminate : () with diff --git a/src/daml/Daml/Finance/Setup/Scenario/Default.daml b/src/daml/Daml/Finance/Setup/Scenario/Default.daml index f69939f4..1b7ab468 100644 --- a/src/daml/Daml/Finance/Setup/Scenario/Default.daml +++ b/src/daml/Daml/Finance/Setup/Scenario/Default.daml @@ -71,9 +71,13 @@ run = do createTradingAutoService operator exchange inv2 createTradingService operator exchange inv3 settlementFactoryCid createTradingAutoService operator exchange inv3 + createAuctionService operator agent issuer createAuctionAutoService operator agent issuer + createBiddingService operator agent inv1 createBiddingAutoService operator agent inv1 + createBiddingService operator agent inv2 createBiddingAutoService operator agent inv2 + createBiddingService operator agent inv3 createBiddingAutoService operator agent inv3 -- Accounts diff --git a/src/daml/Daml/Finance/Setup/Scenario/FundTokenization.daml b/src/daml/Daml/Finance/Setup/Scenario/FundTokenization.daml index acec17f9..96e89fb9 100644 --- a/src/daml/Daml/Finance/Setup/Scenario/FundTokenization.daml +++ b/src/daml/Daml/Finance/Setup/Scenario/FundTokenization.daml @@ -55,7 +55,7 @@ run = do createCustodyService operator am inv3 settlementFactoryCid accountFactoryCid holdingFactoryCid createCustodyService operator custodian am settlementFactoryCid accountFactoryCid holdingFactoryCid createCustodyService operator custodian pm settlementFactoryCid accountFactoryCid holdingFactoryCid - issuanceServiceCid <- toInterfaceContractId <$> createIssuanceAutoService operator custodian pm + issuanceServiceCid <- toInterfaceContractId <$> createIssuanceService operator custodian pm createStructuringService operator custodian pm createStructuringAutoService operator custodian pm createInvestmentService operator am inv1 @@ -96,7 +96,7 @@ run = do inv3CashCid <- deposit operator am inv3 public (Instrument.qty 1_000_000.0 usd) inv3CashAccount -- Data - fund1Cid <- submitMulti [operator, custodian, pm] [] do createCmd Fund with operator; custodian; manager = pm; id = Id "FUND1"; description = "Fund 1"; instrument = fund1; currency = usd; custodianCashAccount; managerFundAccount = pmSecAccount; totalUnits = 1_000_000.0; observers = singleton public + fund1Cid <- toInterfaceContractId <$> submitMulti [operator, custodian, pm] [] do createCmd Fund with operator; custodian; manager = pm; id = Id "FUND1"; description = "Fund 1"; instrument = fund1; currency = usd; custodianCashAccount; managerFundAccount = pmSecAccount; totalUnits = 1_000_000.0; observers = singleton public fund2Cid <- submitMulti [operator, custodian, pm] [] do createCmd Fund with operator; custodian; manager = pm; id = Id "FUND2"; description = "Fund 2"; instrument = fund2; currency = usd; custodianCashAccount; managerFundAccount = pmSecAccount; totalUnits = 5_000_000.0; observers = singleton public fund3Cid <- submitMulti [operator, custodian, pm] [] do createCmd Fund with operator; custodian; manager = pm; id = Id "FUND3"; description = "Fund 3"; instrument = fund3; currency = usd; custodianCashAccount; managerFundAccount = pmSecAccount; totalUnits = 15_000_000.0; observers = singleton public navFund1Cid <- createObservation pm "NAV_FUND1_USD" [ (todayTime, 1_000_000.0) ] pub diff --git a/src/daml/Daml/Finance/Setup/Scenario/SecuritiesLending.daml b/src/daml/Daml/Finance/Setup/Scenario/SecuritiesLending.daml index 3e75382e..2c269f6c 100644 --- a/src/daml/Daml/Finance/Setup/Scenario/SecuritiesLending.daml +++ b/src/daml/Daml/Finance/Setup/Scenario/SecuritiesLending.daml @@ -3,15 +3,17 @@ module Daml.Finance.Setup.Scenario.SecuritiesLending where -import DA.Date (Month(..), addDays, date, toDateUTC, toGregorian) +import DA.Date (addDays, toDateUTC, toGregorian) import DA.Map (empty, fromList) import DA.Set (singleton) import DA.Time (time) -import Daml.Finance.App.Lending.Model qualified as Lending (Repay(..)) -import Daml.Finance.App.Lending.Service qualified as Lending (AcceptBorrowOffer(..), CreateBorrowOffer(..), RequestBorrowOffer(..), Service) +import Daml.Finance.App.Interface.Lending.BorrowAgreement qualified as BorrowAgreement (Repay(..)) +import Daml.Finance.App.Interface.Lending.Service qualified as Lending (AcceptBorrowOffer(..), CreateBorrowOffer(..), I, RequestBorrowOffer(..)) +import Daml.Finance.App.Lending.Service qualified as Lending (T) import Daml.Finance.Account.Account qualified as Account (Factory(..)) import Daml.Finance.Holding.Fungible qualified as Fungible (Factory(..)) import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (qty) +import Daml.Finance.Interface.Types.Common (Id(..)) import Daml.Finance.Settlement.Factory qualified as Settlement (FactoryWithIntermediaries(..)) import Daml.Finance.Settlement.Hierarchy qualified as Settlement (Hierarchy(..)) import Daml.Finance.Setup.Payoff @@ -94,11 +96,12 @@ run = do interest = Instrument.qty 1_000.0 usd collateral = Instrument.qty 1_000_000.0 usd - borrowOfferRequestCid <- submit borrower do exerciseByKeyCmd @Lending.Service (operator, lender, borrower) Lending.RequestBorrowOffer with id = "BORROW"; borrowed; maturity = date 2022 Sep 14 - borrowOfferCid <- submit lender do exerciseByKeyCmd @Lending.Service (operator, lender, borrower) Lending.CreateBorrowOffer with borrowOfferRequestCid; interest; collateral; borrowedCid; lenderBorrowedAccount = lenderSecAccount; lenderInterestAccount = lenderCashAccount - (borrowedCid, borrowAgreementCid) <- submitMulti [borrower] [public] do exerciseByKeyCmd @Lending.Service (operator, lender, borrower) Lending.AcceptBorrowOffer with borrowOfferCid; collateralCid; account = borrowerSecAccount - submitMulti [borrower] [public] do exerciseCmd borrowAgreementCid Lending.Repay with borrowedCid; interestCid + Some (serviceCid, _) <- queryContractKey @Lending.T borrower (operator, lender, borrower) + borrowOfferRequestCid <- submit borrower do exerciseCmd (toInterfaceContractId @Lending.I serviceCid) Lending.RequestBorrowOffer with dealId = Id "BORROW1"; description = "Loan of 1000 TSLA until " <> show today; borrowed; maturity = today + borrowOfferCid <- submit lender do exerciseCmd (toInterfaceContractId @Lending.I serviceCid) Lending.CreateBorrowOffer with borrowOfferRequestCid; interest; collateral; borrowedCid; lenderBorrowedAccount = lenderSecAccount; lenderInterestAccount = lenderCashAccount + (borrowedCid, borrowAgreementCid) <- submitMulti [borrower] [public] do exerciseCmd (toInterfaceContractId @Lending.I serviceCid) Lending.AcceptBorrowOffer with borrowOfferCid; collateralCid; account = borrowerSecAccount + submitMulti [borrower] [public] do exerciseCmd borrowAgreementCid BorrowAgreement.Repay with borrowedCid; interestCid - -- doLoan + --doLoan pure parties diff --git a/src/daml/Daml/Finance/Setup/Scenario/StructuredNotes.daml b/src/daml/Daml/Finance/Setup/Scenario/StructuredNotes.daml index 2f65c1ff..abde9e2f 100644 --- a/src/daml/Daml/Finance/Setup/Scenario/StructuredNotes.daml +++ b/src/daml/Daml/Finance/Setup/Scenario/StructuredNotes.daml @@ -8,10 +8,11 @@ import DA.Date (Month(..), addDays, date, toDateUTC, toGregorian) import DA.Map (empty, fromList) import DA.Set (singleton) import DA.Time (time) -import Daml.Finance.App.BackToBack.Service qualified as BackToBack -import Daml.Finance.App.Distribution.Subscription.Model qualified as Subscription -import Daml.Finance.App.Distribution.Subscription.Service qualified as Subscription import Daml.Finance.Account.Account qualified as Account (Factory(..)) +import Daml.Finance.App.Interface.Distribution.Subscription.Types (BackToBack(..)) +import Daml.Finance.App.Interface.Distribution.Subscription.Offering qualified as Offering (Subscribe(..)) +import Daml.Finance.App.Interface.Distribution.Subscription.Service qualified as SubscriptionService (CreateOffering(..), ProcessOffering(..)) +import Daml.Finance.App.Interface.Issuance.BackToBack qualified as BackToBack (CreateIssuance(..)) import Daml.Finance.Holding.Fungible qualified as Fungible (Factory(..)) import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (qty) import Daml.Finance.Interface.Types.Common (Id(..)) @@ -65,10 +66,10 @@ run = do createStructuringService operator issuer issuer createIssuanceService operator issuer issuer createIssuanceService operator riskTaker riskTaker - createBackToBackIssuanceService operator riskTaker issuer public + b2bServiceCid <- createBackToBackIssuanceService operator riskTaker issuer public createLifecycleService operator riskTaker riskTaker public createLifecycleService operator issuer issuer public - createSubscriptionService operator issuer issuer public + subscriptionServiceCid <- createSubscriptionService operator issuer issuer public -- Accounts riskTakerCashAccount <- createAccount operator centralBank riskTaker public "RiskTaker@CentralBank" $ fromList [("b2b", singleton issuer)] @@ -137,9 +138,9 @@ run = do let issuance quantity = do submitMulti [issuer] [public] do - exerciseByKeyCmd @BackToBack.Service (operator, riskTaker, issuer) BackToBack.CreateIssuance + exerciseCmd b2bServiceCid BackToBack.CreateIssuance with - id = Id $ "ISSUANCE-" <> show quantity.unit.id + issuanceId = Id $ "ISSUANCE-" <> show quantity.unit.id description = "Issuance of " <> show quantity.amount <> " " <> show quantity.unit.id quantity customerAccount = issuerOwnAccount @@ -148,8 +149,9 @@ run = do subscription asset price issuerCashCid issuerAssetCid riskTakerAssetCid inv1CashCid inv2CashCid inv3CashCid = do offeringCid <- submit issuer do let - offeringId = "OFFERING-" <> show asset.unit.id - backToBack = Some Subscription.BackToBack + offeringId = Id $ "OFFERING-" <> show asset.unit.id + description = "Offer for " <> show asset.amount <> " " <> show asset.unit.id + backToBack = Some BackToBack with party = riskTaker offeringId @@ -157,21 +159,22 @@ run = do issuerDeliverableCid = issuerCashCid b2bReceivableAccount = riskTakerCashAccount b2bDeliverableCid = coerceContractId riskTakerAssetCid - exerciseByKeyCmd @Subscription.Service (operator, issuer, issuer) Subscription.CreateOffering + exerciseCmd subscriptionServiceCid SubscriptionService.CreateOffering with offeringId + description asset price customerHoldingCid = coerceContractId issuerAssetCid customerAccount = issuerCashAccount backToBack - inv1SubscriptionCid <- submitMulti [inv1] [public] do exerciseCmd offeringCid Subscription.Subscribe with investor = inv1; quantity = 10_000.0; investorHoldingCid = inv1CashCid; investorAccount = inv1SecAccount - inv2SubscriptionCid <- submitMulti [inv2] [public] do exerciseCmd offeringCid Subscription.Subscribe with investor = inv2; quantity = 10_000.0; investorHoldingCid = inv2CashCid; investorAccount = inv2SecAccount - inv3SubscriptionCid <- submitMulti [inv3] [public] do exerciseCmd offeringCid Subscription.Subscribe with investor = inv3; quantity = 10_000.0; investorHoldingCid = inv3CashCid; investorAccount = inv3SecAccount + inv1SubscriptionCid <- submitMulti [inv1] [public] do exerciseCmd offeringCid Offering.Subscribe with investor = inv1; quantity = 10_000.0; investorHoldingCid = inv1CashCid; investorAccount = inv1SecAccount + inv2SubscriptionCid <- submitMulti [inv2] [public] do exerciseCmd offeringCid Offering.Subscribe with investor = inv2; quantity = 10_000.0; investorHoldingCid = inv2CashCid; investorAccount = inv2SecAccount + inv3SubscriptionCid <- submitMulti [inv3] [public] do exerciseCmd offeringCid Offering.Subscribe with investor = inv3; quantity = 10_000.0; investorHoldingCid = inv3CashCid; investorAccount = inv3SecAccount submitMulti [issuer] [public] do - exerciseByKeyCmd @Subscription.Service (operator, issuer, issuer) Subscription.ProcessOffering + exerciseCmd subscriptionServiceCid SubscriptionService.ProcessOffering with settlementFactoryCid offeringCid diff --git a/src/daml/Daml/Finance/Setup/Util/Service.daml b/src/daml/Daml/Finance/Setup/Util/Service.daml index 10ef71d6..d1b0d27d 100644 --- a/src/daml/Daml/Finance/Setup/Util/Service.daml +++ b/src/daml/Daml/Finance/Setup/Util/Service.daml @@ -15,26 +15,32 @@ import Daml.Finance.App.Interface.Distribution.Auction.Auto qualified as Auction import Daml.Finance.App.Interface.Distribution.Auction.Service qualified as Auction (I) import Daml.Finance.App.Interface.Distribution.Bidding.Auto qualified as BiddingAuto (I) import Daml.Finance.App.Interface.Distribution.Bidding.Service qualified as Bidding (I) +import Daml.Finance.App.Interface.Distribution.Fund.Service qualified as Fund (I) +import Daml.Finance.App.Interface.Distribution.Investment.Service qualified as Investment (I) +import Daml.Finance.App.Interface.Distribution.Subscription.Service qualified as Subscription (I) import Daml.Finance.App.Interface.Issuance.Auto qualified as IssuanceAuto (I) +import Daml.Finance.App.Interface.Issuance.BackToBack qualified as BackToBack (I) import Daml.Finance.App.Interface.Issuance.Service qualified as Issuance (I) +import Daml.Finance.App.Interface.Lending.Service qualified as Lending (I) +import Daml.Finance.App.Interface.Lifecycle.Service qualified as Lifecycle (I) import Daml.Finance.App.Interface.Listing.Auto qualified as ListingAuto (I) import Daml.Finance.App.Interface.Listing.Service qualified as Listing (I) import Daml.Finance.App.Issuance.Auto qualified as IssuanceAuto (Accept(..)) +import Daml.Finance.App.Issuance.BackToBack qualified as BackToBack (Accept(..)) import Daml.Finance.App.Issuance.Service qualified as Issuance (Accept(..)) import Daml.Finance.App.Listing.Auto qualified as ListingAuto (Accept(..)) import Daml.Finance.App.Listing.Service qualified as Listing (Accept(..)) -import Daml.Finance.App.BackToBack.Service qualified as BackToBack (Accept(..), Service) -import Daml.Finance.App.Lifecycle.Service qualified as Lifecycle (Accept(..), Service) +import Daml.Finance.App.Lifecycle.Service qualified as Lifecycle (Accept(..)) import Daml.Finance.App.Trading.Auto.Service qualified as TradingAuto (Accept(..), Service) import Daml.Finance.App.Trading.Service qualified as Trading (Accept(..), Service) -import Daml.Finance.App.Lending.Service qualified as Lending (Accept(..), Service) +import Daml.Finance.App.Lending.Service qualified as Lending (Accept(..)) import Daml.Finance.App.Distribution.Auction.Auto qualified as AuctionAuto (Accept(..)) import Daml.Finance.App.Distribution.Auction.Service qualified as Auction (Accept(..)) import Daml.Finance.App.Distribution.Bidding.Auto qualified as BiddingAuto (Accept(..)) import Daml.Finance.App.Distribution.Bidding.Service qualified as Bidding (Accept(..)) -import Daml.Finance.App.Distribution.Fund.Service qualified as Fund (Accept(..), Service) -import Daml.Finance.App.Distribution.Investment.Service qualified as Investment (Accept(..), Service) -import Daml.Finance.App.Distribution.Subscription.Service qualified as Subscription (Accept(..), Service) +import Daml.Finance.App.Distribution.Fund.Service qualified as Fund (Accept(..)) +import Daml.Finance.App.Distribution.Investment.Service qualified as Investment (Accept(..)) +import Daml.Finance.App.Distribution.Subscription.Service qualified as Subscription (Accept(..)) import Daml.Finance.App.Role.Custodian qualified as Custodian import Daml.Finance.App.Role.Distributor qualified as Distributor import Daml.Finance.App.Role.Exchange qualified as Exchange @@ -103,17 +109,17 @@ createStructuringAutoService operator custodian customer = do offerCid <- submit custodian do exerciseByKeyCmd @Custodian.Role (operator, custodian) Custodian.OfferStructuringAutoService with .. submit customer do exerciseCmd offerCid StructuringAuto.Accept -createBackToBackIssuanceService : Party -> Party -> Party -> Party -> Script (ContractId BackToBack.Service) +createBackToBackIssuanceService : Party -> Party -> Party -> Party -> Script (ContractId BackToBack.I) createBackToBackIssuanceService operator custodian customer public = do offerCid <- submit custodian do exerciseByKeyCmd @Custodian.Role (operator, custodian) Custodian.OfferBackToBackService with .. - submit customer do exerciseCmd offerCid BackToBack.Accept + toInterfaceContractId <$> submit customer do exerciseCmd offerCid BackToBack.Accept -createLifecycleService : Party -> Party -> Party -> Party -> Script (ContractId Lifecycle.Service) +createLifecycleService : Party -> Party -> Party -> Party -> Script (ContractId Lifecycle.I) createLifecycleService operator custodian customer public = do distributionRuleCid <- toInterfaceContractId <$> submit custodian do createCmd Distribution.Rule with providers = singleton custodian; lifecycler = customer; observers = singleton public replacementRuleCid <- toInterfaceContractId <$> submit custodian do createCmd Replacement.Rule with providers = singleton custodian; lifecycler = customer; observers = singleton public offerCid <- submit custodian do exerciseByKeyCmd @Custodian.Role (operator, custodian) Custodian.OfferLifecycleService with .. - submit customer do exerciseCmd offerCid Lifecycle.Accept + toInterfaceContractId <$> submit customer do exerciseCmd offerCid Lifecycle.Accept createTradingService : Party -> Party -> Party -> ContractId Settlement.Factory -> Script (ContractId Trading.Service) createTradingService operator exchange customer settlementFactoryCid = do @@ -155,30 +161,30 @@ createBiddingAutoService operator distributor customer = do offerCid <- submit distributor do exerciseByKeyCmd @Distributor.Role (operator, distributor) Distributor.OfferBiddingAutoService with .. toInterfaceContractId <$> submit customer do exerciseCmd offerCid BiddingAuto.Accept -createSubscriptionService : Party -> Party -> Party -> Party -> Script (ContractId Subscription.Service) +createSubscriptionService : Party -> Party -> Party -> Party -> Script (ContractId Subscription.I) createSubscriptionService operator distributor customer public = do offerCid <- submit distributor do exerciseByKeyCmd @Distributor.Role (operator, distributor) Distributor.OfferSubscriptionService with customer; public - submit customer do exerciseCmd offerCid Subscription.Accept + toInterfaceContractId <$> submit customer do exerciseCmd offerCid Subscription.Accept -createLendingService : Party -> Party -> Party -> Script (ContractId Lending.Service) +createLendingService : Party -> Party -> Party -> Script (ContractId Lending.I) createLendingService operator lender borrower = do offerCid <- submit lender do exerciseByKeyCmd @Custodian.Role (operator, lender) Custodian.OfferLendingService with customer = borrower - submit borrower do exerciseCmd offerCid Lending.Accept + toInterfaceContractId <$> submit borrower do exerciseCmd offerCid Lending.Accept createSettlementService : Party -> Party -> Party -> Script (ContractId Settlement.Service) createSettlementService operator custodian customer = do offerCid <- submit custodian do exerciseByKeyCmd @Custodian.Role (operator, custodian) Custodian.OfferSettlementService with customer submit customer do exerciseCmd offerCid Settlement.Accept -createInvestmentService : Party -> Party -> Party -> Script (ContractId Investment.Service) +createInvestmentService : Party -> Party -> Party -> Script (ContractId Investment.I) createInvestmentService operator provider customer = do offerCid <- submit provider do exerciseByKeyCmd @Distributor.Role (operator, provider) Distributor.OfferInvestmentService with customer - submit customer do exerciseCmd offerCid Investment.Accept + toInterfaceContractId <$> submit customer do exerciseCmd offerCid Investment.Accept -createFundService : Party -> Party -> Party -> Script (ContractId Fund.Service) +createFundService : Party -> Party -> Party -> Script (ContractId Fund.I) createFundService operator provider customer = do offerCid <- submit provider do exerciseByKeyCmd @Distributor.Role (operator, provider) Distributor.OfferFundService with customer - submit customer do exerciseCmd offerCid Fund.Accept + toInterfaceContractId <$> submit customer do exerciseCmd offerCid Fund.Accept createDecentralizedExchangeService : Party -> Party -> Text -> Instrument.Q -> Instrument.Q -> Account.K -> ContractId Fungible.I -> Instrument.Q -> Account.K -> ContractId Fungible.I -> Script (ContractId DecentralizedExchange.Service) createDecentralizedExchangeService consortium public id shares quantity1 account1 fungible1Cid quantity2 account2 fungible2Cid = do diff --git a/src/daml/Daml/Finance/Setup/Util/Workflow.daml b/src/daml/Daml/Finance/Setup/Util/Workflow.daml index cd249c40..09ec4c4f 100644 --- a/src/daml/Daml/Finance/Setup/Util/Workflow.daml +++ b/src/daml/Daml/Finance/Setup/Util/Workflow.daml @@ -10,27 +10,27 @@ import DA.Set (fromList, singleton) import DA.Text (parseInt) import Daml.Finance.App.Custody.Service qualified as Custody (Service) import Daml.Finance.App.Data.AccountDirectory (AccountDirectory(..)) -import Daml.Finance.App.Distribution.Auction.Auto qualified as AuctionAuto (Service) import Daml.Finance.App.Distribution.Auction.Service qualified as Auction (Service) -import Daml.Finance.App.Distribution.Bidding.Auto qualified as BiddingAuto (Service) import Daml.Finance.App.Distribution.Bidding.Service qualified as Bidding (Service) -import Daml.Finance.App.Distribution.Fund.Model qualified as Fund (PooledInvestmentRequest, T) -import Daml.Finance.App.Distribution.Fund.Service qualified as Fund (FulfillPooledInvestmentRequest(..), PoolInvestmentRequests(..), S) -import Daml.Finance.App.Distribution.Investment.Model qualified as Investment (InvestmentRequest) -import Daml.Finance.App.Distribution.Investment.Service qualified as Investment (RequestInvestment(..), S) +import Daml.Finance.App.Distribution.Fund.Service qualified as Fund (Service) +import Daml.Finance.App.Distribution.Investment.Service qualified as Investment (Service) import Daml.Finance.App.Interface.Custody.Service qualified as Custody (Deposit(..), I, OpenAccount(..), RequestDeposit(..), RequestOpenAccount(..)) import Daml.Finance.App.Interface.Distribution.Auction.Auction qualified as Auction (I) -import Daml.Finance.App.Interface.Distribution.Auction.Auto qualified as AuctionAutoService (I, RequestAndCreateAuction(..)) import Daml.Finance.App.Interface.Distribution.Auction.Service qualified as AuctionService (CreateAuction(..), I, ProcessAuction(..), RequestCreateAuction(..)) import Daml.Finance.App.Interface.Distribution.Bidding.Bid qualified as Bid (I) -import Daml.Finance.App.Interface.Distribution.Bidding.Auto qualified as BiddingAutoService (I, RequestAndCreateBid(..)) import Daml.Finance.App.Interface.Distribution.Bidding.Service qualified as BiddingService (CreateBid(..), I, RequestCreateBid(..)) +import Daml.Finance.App.Interface.Distribution.Fund.Fund qualified as Fund (I) +import Daml.Finance.App.Interface.Distribution.Fund.PooledInvestmentRequest qualified as PooledInvestmentRequest (I) +import Daml.Finance.App.Interface.Distribution.Fund.Service qualified as FundService (FulfillPooledInvestmentRequest(..), I, PoolInvestmentRequests(..)) +import Daml.Finance.App.Interface.Distribution.Investment.InvestmentRequest qualified as InvestmentRequest (I) +import Daml.Finance.App.Interface.Distribution.Investment.Service qualified as InvestmentService (I, RequestInvestment(..),) import Daml.Finance.App.Interface.Issuance.Issuance qualified as Issuance (I) import Daml.Finance.App.Interface.Issuance.Service qualified as IssuanceService (I, Issue(..), RequestIssue(..)) +import Daml.Finance.App.Interface.Lifecycle.Service qualified as LifecycleService (I, DeclareDividend(..), DeclareStockSplit(..), DeclareReplacement(..)) import Daml.Finance.App.Interface.Listing.Listing qualified as Listing (I) import Daml.Finance.App.Interface.Listing.Service qualified as ListingService (I, List(..), RequestListing(..)) import Daml.Finance.App.Issuance.Service qualified as Issuance (Service) -import Daml.Finance.App.Lifecycle.Service qualified as Lifecycle (Service, DeclareDividend(..), DeclareStockSplit(..), DeclareReplacement(..)) +import Daml.Finance.App.Lifecycle.Service qualified as Lifecycle (Service) import Daml.Finance.App.Listing.Model qualified as Listing (T) import Daml.Finance.App.Listing.Service qualified as Listing (Service) import Daml.Finance.App.Trading.Model qualified as Trading (Order, Side(..)) @@ -239,40 +239,21 @@ createAskOrder operator provider customer public id = createOrder operator provi createAuction : Party -> Party -> Party -> Party -> Id -> Text -> Instrument.Q -> Instrument.K -> Decimal -> ContractId Fungible.I -> AccountKey -> Script (ContractId Auction.I) createAuction operator provider customer public auctionId description quantity currency floor collateralCid receivableAccount = do - autoOpt <- queryContractKey @AuctionAuto.Service customer (operator, provider, customer) - serviceOpt <- queryContractKey @Auction.Service customer (operator, provider, customer) - case (autoOpt, serviceOpt) of - (Some (serviceCid, _), _) -> do - submit customer do exerciseCmd (toInterfaceContractId @AuctionAutoService.I serviceCid) AuctionAutoService.RequestAndCreateAuction with auctionId; description; quantity; currency; floor; collateralCid; receivableAccount; observers = singleton public - (_, Some (serviceCid, _)) -> do - createAuctionRequestCid <- submit customer do exerciseCmd (toInterfaceContractId @AuctionService.I serviceCid) AuctionService.RequestCreateAuction with auctionId; description; quantity; currency; floor; collateralCid; receivableAccount; observers = singleton public - submit provider do exerciseCmd (toInterfaceContractId @AuctionService.I serviceCid) AuctionService.CreateAuction with createAuctionRequestCid - _ -> fail "No auction service found" + Some (serviceCid, _) <- queryContractKey @Auction.Service customer (operator, provider, customer) + createAuctionRequestCid <- submit customer do exerciseCmd (toInterfaceContractId @AuctionService.I serviceCid) AuctionService.RequestCreateAuction with auctionId; description; quantity; currency; floor; collateralCid; receivableAccount; observers = singleton public + submit provider do exerciseCmd (toInterfaceContractId @AuctionService.I serviceCid) AuctionService.CreateAuction with createAuctionRequestCid createAuctionBid : Party -> Party -> Party -> Party -> ContractId Auction.I -> Decimal -> Decimal -> ContractId Fungible.I -> AccountKey -> Script (ContractId Bid.I) createAuctionBid operator provider customer public auctionCid amount price collateralCid receivableAccount = do - autoOpt <- queryContractKey @BiddingAuto.Service customer (operator, provider, customer) - serviceOpt <- queryContractKey @Bidding.Service customer (operator, provider, customer) - case (autoOpt, serviceOpt) of - (Some (serviceCid, _), _) -> do - submitMulti [customer] [public] do exerciseCmd (toInterfaceContractId @BiddingAutoService.I serviceCid) BiddingAutoService.RequestAndCreateBid with auctionCid; amount; price; collateralCid; receivableAccount - (_, Some (serviceCid, _)) -> do - createBidRequestCid <- submitMulti [customer] [public] do exerciseCmd (toInterfaceContractId @BiddingService.I serviceCid) BiddingService.RequestCreateBid with auctionCid; amount; price; collateralCid; receivableAccount - submit provider do exerciseCmd (toInterfaceContractId @BiddingService.I serviceCid) BiddingService.CreateBid with createBidRequestCid - _ -> fail "No auction service found" - + Some (serviceCid, _) <- queryContractKey @Bidding.Service customer (operator, provider, customer) + createBidRequestCid <- submitMulti [customer] [public] do exerciseCmd (toInterfaceContractId @BiddingService.I serviceCid) BiddingService.RequestCreateBid with auctionCid; amount; price; collateralCid; receivableAccount + submit provider do exerciseCmd (toInterfaceContractId @BiddingService.I serviceCid) BiddingService.CreateBid with createBidRequestCid processAuction : Party -> Party -> Party -> Party -> ContractId Auction.I -> [ContractId Bid.I] -> Script (ContractId Auction.I) processAuction operator provider customer public auctionCid bidCids = do [(factoryCid, _)] <- query @Settlement.FactoryWithIntermediaries public - autoOpt <- queryContractKey @AuctionAuto.Service provider (operator, provider, customer) - serviceOpt <- queryContractKey @Auction.Service provider (operator, provider, customer) - case (autoOpt, serviceOpt) of - (Some (serviceCid, _), _) -> do - submitMulti [provider] [public] do exerciseCmd (toInterfaceContractId @AuctionService.I serviceCid) AuctionService.ProcessAuction with settlementFactoryCid = toInterfaceContractId factoryCid; auctionCid; bidCids - (_, Some (serviceCid, _)) -> do - submitMulti [provider] [public] do exerciseCmd (toInterfaceContractId @AuctionService.I serviceCid) AuctionService.ProcessAuction with settlementFactoryCid = toInterfaceContractId factoryCid; auctionCid; bidCids - _ -> fail "No auction service found" + Some (serviceCid, _) <- queryContractKey @Auction.Service provider (operator, provider, customer) + submitMulti [provider] [public] do exerciseCmd (toInterfaceContractId @AuctionService.I serviceCid) AuctionService.ProcessAuction with settlementFactoryCid = toInterfaceContractId factoryCid; auctionCid; bidCids declareDividend : Party -> Party -> Party -> Party -> Instrument.K -> Date -> [Instrument.Q] -> Script (ContractId Effect.I) declareDividend operator provider issuer public equity effectiveDate perUnitDistribution = do @@ -280,8 +261,9 @@ declareDividend operator provider issuer public equity effectiveDate perUnitDist let id = "Dividend-" <> show equity.id <> "-" <> equity.version Some version = parseInt equity.version + Some (serviceCid, _) <- queryContractKey @Lifecycle.Service provider (operator, provider, issuer) head <$> submitMulti [issuer] [public] do - exerciseByKeyCmd @Lifecycle.Service (operator, provider, issuer) Lifecycle.DeclareDividend + exerciseCmd (toInterfaceContractId @LifecycleService.I serviceCid) LifecycleService.DeclareDividend with timeObservableCid = toInterfaceContractId clockCid equity @@ -295,8 +277,9 @@ declareReplacement : Party -> Party -> Party -> Party -> Instrument.K -> Date -> declareReplacement operator provider issuer public equity effectiveDate perUnitReplacement = do [(clockCid, _)] <- query @Data.DateClock issuer let id = "Replacement-" <> show equity.id <> "-" <> equity.version + Some (serviceCid, _) <- queryContractKey @Lifecycle.Service provider (operator, provider, issuer) head <$> submitMulti [issuer] [public] do - exerciseByKeyCmd @Lifecycle.Service (operator, provider, issuer) Lifecycle.DeclareReplacement + exerciseCmd (toInterfaceContractId @LifecycleService.I serviceCid) LifecycleService.DeclareReplacement with timeObservableCid = toInterfaceContractId clockCid equity @@ -311,8 +294,9 @@ declareStockSplit operator provider issuer public equity effectiveDate adjustmen let id = "StockSplit-" <> show equity.id <> "-" <> equity.version Some version = parseInt equity.version + Some (serviceCid, _) <- queryContractKey @Lifecycle.Service provider (operator, provider, issuer) head <$> submitMulti [issuer] [public] do - exerciseByKeyCmd @Lifecycle.Service (operator, provider, issuer) Lifecycle.DeclareStockSplit + exerciseCmd (toInterfaceContractId @LifecycleService.I serviceCid) LifecycleService.DeclareStockSplit with timeObservableCid = toInterfaceContractId clockCid equity @@ -334,14 +318,17 @@ allocateAndApprove operator settler instructionCid allocation approval = do instructionCid <- fst <$> submit i.routedStep.sender do exerciseCmd instructionCid Instruction.Allocate with actors = singleton settler; allocation submit i.routedStep.receiver do exerciseCmd instructionCid Instruction.Approve with actors = singleton settler; approval -createInvestmentRequest : Party -> Party -> Party -> Party -> Text -> Date -> ContractId Fund.T -> ContractId Transferable.I -> Script (ContractId Investment.InvestmentRequest) -createInvestmentRequest operator provider customer public id asOfDate fundCid cashCid = - submitMulti [customer] [public] do exerciseByKeyCmd @Investment.S (operator, provider, customer) Investment.RequestInvestment with requestId = Id id; asOfDate; fundCid; cashCid +createInvestmentRequest : Party -> Party -> Party -> Party -> Text -> Date -> ContractId Fund.I -> ContractId Transferable.I -> Script (ContractId InvestmentRequest.I) +createInvestmentRequest operator provider customer public id asOfDate fundCid cashCid = do + Some (serviceCid, _) <- queryContractKey @Investment.Service customer (operator, provider, customer) + submitMulti [customer] [public] do exerciseCmd (toInterfaceContractId @InvestmentService.I serviceCid) InvestmentService.RequestInvestment with requestId = Id id; asOfDate; fundCid; cashCid -poolInvestmentRequests : Party -> Party -> Party -> Party -> Text -> Date -> ContractId Fund.T -> ContractId Transferable.I -> [ContractId Investment.InvestmentRequest] -> Script (ContractId Fund.PooledInvestmentRequest) -poolInvestmentRequests operator provider customer public id asOfDate fundCid cashCid investmentRequestCids = - submitMulti [customer] [public] do exerciseByKeyCmd @Fund.S (operator, provider, customer) Fund.PoolInvestmentRequests with requestId = Id id; asOfDate; fundCid; cashCid; investmentRequestCids +poolInvestmentRequests : Party -> Party -> Party -> Party -> Text -> Date -> ContractId Fund.I -> ContractId Transferable.I -> [ContractId InvestmentRequest.I] -> Script (ContractId PooledInvestmentRequest.I) +poolInvestmentRequests operator provider customer public id asOfDate fundCid cashCid investmentRequestCids = do + Some (serviceCid, _) <- queryContractKey @Fund.Service customer (operator, provider, customer) + submitMulti [customer] [public] do exerciseCmd (toInterfaceContractId @FundService.I serviceCid) FundService.PoolInvestmentRequests with requestId = Id id; asOfDate; fundCid; cashCid; investmentRequestCids -fulfillPooledInvestmentRequest : Party -> Party -> Party -> Party -> ContractId Fund.T -> ContractId Fund.PooledInvestmentRequest -> ContractId NumericObservable.I -> ContractId SettlementFactory.I -> ContractId IssuanceService.I -> Script [ContractId Holding.I] -fulfillPooledInvestmentRequest operator provider customer public fundCid pooledInvestmentRequestCid navObservableCid settlementFactoryCid issuanceServiceCid = - submitMulti [provider] [public] do exerciseByKeyCmd @Fund.S (operator, provider, customer) Fund.FulfillPooledInvestmentRequest with fundCid; pooledInvestmentRequestCid; navObservableCid; settlementFactoryCid; issuanceServiceCid +fulfillPooledInvestmentRequest : Party -> Party -> Party -> Party -> ContractId Fund.I -> ContractId PooledInvestmentRequest.I -> ContractId NumericObservable.I -> ContractId SettlementFactory.I -> ContractId IssuanceService.I -> Script [ContractId Holding.I] +fulfillPooledInvestmentRequest operator provider customer public fundCid pooledInvestmentRequestCid navObservableCid settlementFactoryCid issuanceServiceCid = do + Some (serviceCid, _) <- queryContractKey @Fund.Service customer (operator, provider, customer) + submitMulti [provider] [public] do exerciseCmd (toInterfaceContractId @FundService.I serviceCid) FundService.FulfillPooledInvestmentRequest with fundCid; pooledInvestmentRequestCid; navObservableCid; settlementFactoryCid; issuanceServiceCid From ef3835ba9f452913bb62b39d12bce316792e803b Mon Sep 17 00:00:00 2001 From: Georg Schneider Date: Wed, 21 Dec 2022 01:52:35 +0100 Subject: [PATCH 10/31] Instrument.K -> InstrumentKey --- .../Finance/App/Data/AccountDirectory.daml | 1 - .../App/Distribution/Auction/Model.daml | 8 +- .../Finance/App/Distribution/Fund/Model.daml | 8 +- .../Finance/App/Interface/Custody/Auto.daml | 6 +- .../Distribution/Auction/Auction.daml | 6 +- .../Interface/Distribution/Auction/Auto.daml | 6 +- .../Auction/CreateAuctionRequest.daml | 6 +- .../Distribution/Auction/Service.daml | 6 +- .../App/Interface/Distribution/Fund/Fund.daml | 8 +- .../App/Interface/Lifecycle/Service.daml | 22 ++--- .../Finance/App/Interface/Listing/Auto.daml | 7 +- .../App/Interface/Listing/Listing.daml | 7 +- .../App/Interface/Listing/ListingRequest.daml | 7 +- .../App/Interface/Listing/Service.daml | 7 +- src/daml/Daml/Finance/App/Listing/Model.daml | 11 ++- .../Finance/App/Structuring/Auto/Service.daml | 12 +-- .../Daml/Finance/App/Structuring/Model.daml | 11 ++- .../Daml/Finance/App/Structuring/Service.daml | 10 +-- src/daml/Daml/Finance/Setup/Payoff.daml | 89 ++++++++++--------- src/daml/Daml/Finance/Setup/Util/Common.daml | 5 +- .../Daml/Finance/Setup/Util/Workflow.daml | 34 +++---- 21 files changed, 136 insertions(+), 141 deletions(-) diff --git a/src/daml/Daml/Finance/App/Data/AccountDirectory.daml b/src/daml/Daml/Finance/App/Data/AccountDirectory.daml index dfdbee93..2fac4878 100644 --- a/src/daml/Daml/Finance/App/Data/AccountDirectory.daml +++ b/src/daml/Daml/Finance/App/Data/AccountDirectory.daml @@ -26,4 +26,3 @@ template AccountDirectory controller actor do pure this - \ No newline at end of file diff --git a/src/daml/Daml/Finance/App/Distribution/Auction/Model.daml b/src/daml/Daml/Finance/App/Distribution/Auction/Model.daml index 9457009a..86b9f2d8 100644 --- a/src/daml/Daml/Finance/App/Distribution/Auction/Model.daml +++ b/src/daml/Daml/Finance/App/Distribution/Auction/Model.daml @@ -8,8 +8,8 @@ import Daml.Finance.App.Interface.Common.Removable qualified as Removable (I, Vi import Daml.Finance.App.Interface.Distribution.Auction.Auction qualified as Auction (I, Status, View(..)) import Daml.Finance.App.Interface.Distribution.Auction.CreateAuctionRequest qualified as CreateAuctionRequest (I, View(..)) import Daml.Finance.Interface.Holding.Fungible qualified as Fungible (I) -import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (K, Q) -import Daml.Finance.Interface.Types.Common (AccountKey, Id, Parties) +import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (Q) +import Daml.Finance.Interface.Types.Common (AccountKey, Id, InstrumentKey, Parties) type T = Auction @@ -21,7 +21,7 @@ template Auction id : Id description : Text quantity : Instrument.Q - currency : Instrument.K + currency : InstrumentKey floor : Decimal collateralCid : ContractId Fungible.I receivableAccount : AccountKey @@ -51,7 +51,7 @@ template CreateAuctionRequest auctionId : Id description : Text quantity : Instrument.Q - currency : Instrument.K + currency : InstrumentKey floor : Decimal collateralCid : ContractId Fungible.I receivableAccount : AccountKey diff --git a/src/daml/Daml/Finance/App/Distribution/Fund/Model.daml b/src/daml/Daml/Finance/App/Distribution/Fund/Model.daml index 9023f2dd..dd4c2c44 100644 --- a/src/daml/Daml/Finance/App/Distribution/Fund/Model.daml +++ b/src/daml/Daml/Finance/App/Distribution/Fund/Model.daml @@ -12,10 +12,10 @@ import Daml.Finance.App.Interface.Distribution.Investment.InvestmentRequest qual import Daml.Finance.App.Interface.Issuance.Service qualified as IssuanceService (Issue(..), RequestIssue(..), asBase) import Daml.Finance.Interface.Account.Account qualified as Account (K) import Daml.Finance.Interface.Holding.Transferable qualified as Transferable (I) -import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (K, Q) +import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (Q) import Daml.Finance.Interface.Settlement.Instruction qualified as Instruction (Approve(..)) import Daml.Finance.Interface.Settlement.Types (Approval(TakeDelivery)) -import Daml.Finance.Interface.Types.Common (AccountKey, Id, Parties) +import Daml.Finance.Interface.Types.Common (AccountKey, Id, InstrumentKey, Parties) type T = Fund @@ -28,8 +28,8 @@ template Fund manager : Party id : Id description : Text - instrument : Instrument.K - currency : Instrument.K + instrument : InstrumentKey + currency : InstrumentKey custodianCashAccount : AccountKey managerFundAccount : AccountKey totalUnits : Decimal diff --git a/src/daml/Daml/Finance/App/Interface/Custody/Auto.daml b/src/daml/Daml/Finance/App/Interface/Custody/Auto.daml index 246d0ea1..371adc8a 100644 --- a/src/daml/Daml/Finance/App/Interface/Custody/Auto.daml +++ b/src/daml/Daml/Finance/App/Interface/Custody/Auto.daml @@ -6,8 +6,8 @@ module Daml.Finance.App.Interface.Custody.Auto where import Daml.Finance.App.Interface.Base.Service qualified as Base (I) import Daml.Finance.Interface.Account.Account qualified as Account (Controllers, I) import Daml.Finance.Interface.Holding.Base qualified as Holding (I) -import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (K, Q) -import Daml.Finance.Interface.Types.Common (AccountKey, Id, PartiesMap) +import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (Q) +import Daml.Finance.Interface.Types.Common (AccountKey, Id, InstrumentKey, PartiesMap) type I = Service @@ -57,7 +57,7 @@ interface Service where nonconsuming choice RequestAndWithdraw : () with - instrument : Instrument.K + instrument : InstrumentKey holdingCid : ContractId Holding.I controller (view $ asBase this).customer do diff --git a/src/daml/Daml/Finance/App/Interface/Distribution/Auction/Auction.daml b/src/daml/Daml/Finance/App/Interface/Distribution/Auction/Auction.daml index b8a906e4..ed5a6972 100644 --- a/src/daml/Daml/Finance/App/Interface/Distribution/Auction/Auction.daml +++ b/src/daml/Daml/Finance/App/Interface/Distribution/Auction/Auction.daml @@ -5,8 +5,8 @@ module Daml.Finance.App.Interface.Distribution.Auction.Auction where import Daml.Finance.App.Interface.Common.Removable qualified as Removable (I, Implementation) import Daml.Finance.Interface.Holding.Fungible qualified as Fungible (I) -import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (K, Q) -import Daml.Finance.Interface.Types.Common (AccountKey, Id, Parties) +import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (Q) +import Daml.Finance.Interface.Types.Common (AccountKey, Id, InstrumentKey, Parties) type I = Auction @@ -20,7 +20,7 @@ data View = View id : Id description : Text quantity : Instrument.Q - currency : Instrument.K + currency : InstrumentKey floor : Decimal collateralCid : ContractId Fungible.I receivableAccount : AccountKey diff --git a/src/daml/Daml/Finance/App/Interface/Distribution/Auction/Auto.daml b/src/daml/Daml/Finance/App/Interface/Distribution/Auction/Auto.daml index eb36cc1d..ed264c98 100644 --- a/src/daml/Daml/Finance/App/Interface/Distribution/Auction/Auto.daml +++ b/src/daml/Daml/Finance/App/Interface/Distribution/Auction/Auto.daml @@ -6,8 +6,8 @@ module Daml.Finance.App.Interface.Distribution.Auction.Auto where import Daml.Finance.App.Interface.Base.Service qualified as Base (I) import Daml.Finance.App.Interface.Distribution.Auction.Auction qualified as Auction (I) import Daml.Finance.Interface.Holding.Fungible qualified as Fungible (I) -import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (K, Q) -import Daml.Finance.Interface.Types.Common (AccountKey, Id, Parties) +import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (Q) +import Daml.Finance.Interface.Types.Common (AccountKey, Id, InstrumentKey, Parties) type I = Service @@ -30,7 +30,7 @@ interface Service where auctionId : Id description : Text quantity : Instrument.Q - currency : Instrument.K + currency : InstrumentKey floor : Decimal collateralCid : ContractId Fungible.I receivableAccount : AccountKey diff --git a/src/daml/Daml/Finance/App/Interface/Distribution/Auction/CreateAuctionRequest.daml b/src/daml/Daml/Finance/App/Interface/Distribution/Auction/CreateAuctionRequest.daml index 48f5debc..367702bd 100644 --- a/src/daml/Daml/Finance/App/Interface/Distribution/Auction/CreateAuctionRequest.daml +++ b/src/daml/Daml/Finance/App/Interface/Distribution/Auction/CreateAuctionRequest.daml @@ -5,8 +5,8 @@ module Daml.Finance.App.Interface.Distribution.Auction.CreateAuctionRequest wher import Daml.Finance.App.Interface.Common.Removable qualified as Removable (I, Implementation) import Daml.Finance.Interface.Holding.Fungible qualified as Fungible (I) -import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (K, Q) -import Daml.Finance.Interface.Types.Common (AccountKey, Id, Parties) +import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (Q) +import Daml.Finance.Interface.Types.Common (AccountKey, Id, InstrumentKey, Parties) type I = CreateAuctionRequest @@ -20,7 +20,7 @@ data View = View auctionId : Id description : Text quantity : Instrument.Q - currency : Instrument.K + currency : InstrumentKey floor : Decimal collateralCid : ContractId Fungible.I receivableAccount : AccountKey diff --git a/src/daml/Daml/Finance/App/Interface/Distribution/Auction/Service.daml b/src/daml/Daml/Finance/App/Interface/Distribution/Auction/Service.daml index 5aca2283..7b740c2e 100644 --- a/src/daml/Daml/Finance/App/Interface/Distribution/Auction/Service.daml +++ b/src/daml/Daml/Finance/App/Interface/Distribution/Auction/Service.daml @@ -8,9 +8,9 @@ import Daml.Finance.App.Interface.Distribution.Auction.Auction qualified as Auct import Daml.Finance.App.Interface.Distribution.Auction.CreateAuctionRequest qualified as CreateAuctionRequest (I) import Daml.Finance.App.Interface.Distribution.Bidding.Bid qualified as Bid (I) import Daml.Finance.Interface.Holding.Fungible qualified as Fungible (I) -import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (K, Q) +import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (Q) import Daml.Finance.Interface.Settlement.Factory qualified as SettlementFactory (I) -import Daml.Finance.Interface.Types.Common (AccountKey, Id, Parties) +import Daml.Finance.Interface.Types.Common (AccountKey, Id, InstrumentKey, Parties) type I = Service @@ -39,7 +39,7 @@ interface Service where auctionId : Id description : Text quantity : Instrument.Q - currency : Instrument.K + currency : InstrumentKey floor : Decimal collateralCid : ContractId Fungible.I receivableAccount : AccountKey diff --git a/src/daml/Daml/Finance/App/Interface/Distribution/Fund/Fund.daml b/src/daml/Daml/Finance/App/Interface/Distribution/Fund/Fund.daml index 91ccbe98..8206ed3c 100644 --- a/src/daml/Daml/Finance/App/Interface/Distribution/Fund/Fund.daml +++ b/src/daml/Daml/Finance/App/Interface/Distribution/Fund/Fund.daml @@ -7,9 +7,9 @@ import Daml.Finance.App.Interface.Common.Removable qualified as Removable (I, Im import Daml.Finance.App.Interface.Issuance.Issuance qualified as Issuance (I) import Daml.Finance.App.Interface.Issuance.Service qualified as IssuanceService (I) import Daml.Finance.Interface.Holding.Transferable qualified as Transferable (I) -import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (K, Q) +import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (Q) import Daml.Finance.Interface.Settlement.Instruction qualified as Instruction (I) -import Daml.Finance.Interface.Types.Common (AccountKey, Id, Parties) +import Daml.Finance.Interface.Types.Common (AccountKey, Id, InstrumentKey, Parties) type I = Fund @@ -22,8 +22,8 @@ data View = View manager : Party id : Id description : Text - instrument : Instrument.K - currency : Instrument.K + instrument : InstrumentKey + currency : InstrumentKey custodianCashAccount : AccountKey managerFundAccount : AccountKey totalUnits : Decimal diff --git a/src/daml/Daml/Finance/App/Interface/Lifecycle/Service.daml b/src/daml/Daml/Finance/App/Interface/Lifecycle/Service.daml index 39dbf1fd..f914525c 100644 --- a/src/daml/Daml/Finance/App/Interface/Lifecycle/Service.daml +++ b/src/daml/Daml/Finance/App/Interface/Lifecycle/Service.daml @@ -10,13 +10,13 @@ import ContingentClaims.Lifecycle.Lifecycle qualified as Lifecycle import ContingentClaims.Valuation.Stochastic (Expr) import Daml.Finance.Interface.Data.NumericObservable qualified as NumericObservable (I) import Daml.Finance.Interface.Data.TimeObservable qualified as TimeObservable (I) -import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (K, Q) +import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (Q) import Daml.Finance.Interface.Claims.Claim qualified as Claim (Claim) import Daml.Finance.Interface.Claims.Types (C, Pending, TaggedClaim) import Daml.Finance.Interface.Lifecycle.Effect qualified as Effect (I) import Daml.Finance.Interface.Lifecycle.Event qualified as Event (I) import Daml.Finance.Interface.Lifecycle.Rule.Lifecycle qualified as Lifecycle (I) -import Daml.Finance.Interface.Types.Common (Id) +import Daml.Finance.Interface.Types.Common (Id, InstrumentKey) type I = Service @@ -46,7 +46,7 @@ interface Service where previewLifecycle : PreviewLifecycle -> Update ([TaggedClaim], [Pending]) -- ^ Implementation of the `PreviewLifecycle` choice. - simulateLifecycle : SimulateLifecycle -> Update [[Lifecycle.Pending Time Instrument.K]] + simulateLifecycle : SimulateLifecycle -> Update [[Lifecycle.Pending Time InstrumentKey]] -- ^ Implementation of the `SimulateLifecycle` choice. getCurrentClaims : GetCurrentClaims -> Update [TaggedClaim] @@ -58,10 +58,10 @@ interface Service where expiry : Expiry -> Update (Optional Time) -- ^ Implementation of the `Expiry` choice. - underlyings : Underlyings -> Update [Instrument.K] + underlyings : Underlyings -> Update [InstrumentKey] -- ^ Implementation of the `Underlyings` choice. - payoffs : Payoffs -> Update [(Observation Time Decimal Text, Instrument.K)] + payoffs : Payoffs -> Update [(Observation Time Decimal Text, InstrumentKey)] -- ^ Implementation of the `Payoffs` choice. fixings : Fixings -> Update [Time] @@ -76,7 +76,7 @@ interface Service where nonconsuming choice DeclareDividend : [ContractId Effect.I] with timeObservableCid : ContractId TimeObservable.I - equity : Instrument.K + equity : InstrumentKey newVersion : Text id : Id description : Text @@ -89,7 +89,7 @@ interface Service where nonconsuming choice DeclareReplacement : [ContractId Effect.I] with timeObservableCid : ContractId TimeObservable.I - equity : Instrument.K + equity : InstrumentKey id : Id description : Text effectiveDate : Date @@ -101,7 +101,7 @@ interface Service where nonconsuming choice DeclareStockSplit : [ContractId Effect.I] with timeObservableCid : ContractId TimeObservable.I - equity : Instrument.K + equity : InstrumentKey newVersion : Text id : Id description : Text @@ -120,7 +120,7 @@ interface Service where do previewLifecycle this arg - nonconsuming choice SimulateLifecycle : [[Lifecycle.Pending Time Instrument.K]] + nonconsuming choice SimulateLifecycle : [[Lifecycle.Pending Time InstrumentKey]] with today : Time prices : [Decimal] @@ -155,14 +155,14 @@ interface Service where do expiry this arg - nonconsuming choice Underlyings : [Instrument.K] + nonconsuming choice Underlyings : [InstrumentKey] with claims : C controller (view $ asBase this).customer do underlyings this arg - nonconsuming choice Payoffs : [(Observation Time Decimal Text, Instrument.K)] + nonconsuming choice Payoffs : [(Observation Time Decimal Text, InstrumentKey)] with claims : C controller (view $ asBase this).customer diff --git a/src/daml/Daml/Finance/App/Interface/Listing/Auto.daml b/src/daml/Daml/Finance/App/Interface/Listing/Auto.daml index a161db3a..33f56ffb 100644 --- a/src/daml/Daml/Finance/App/Interface/Listing/Auto.daml +++ b/src/daml/Daml/Finance/App/Interface/Listing/Auto.daml @@ -5,8 +5,7 @@ module Daml.Finance.App.Interface.Listing.Auto where import Daml.Finance.App.Interface.Base.Service qualified as Base (I) import Daml.Finance.App.Interface.Listing.Listing qualified as Listing (I) -import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (K) -import Daml.Finance.Interface.Types.Common (Id, Parties) +import Daml.Finance.Interface.Types.Common (Id, InstrumentKey, Parties) type I = Service @@ -31,8 +30,8 @@ interface Service where with listingId : Id description : Text - tradedInstrument : Instrument.K - quotedInstrument : Instrument.K + tradedInstrument : InstrumentKey + quotedInstrument : InstrumentKey observers : Parties controller (view $ asBase this).customer do diff --git a/src/daml/Daml/Finance/App/Interface/Listing/Listing.daml b/src/daml/Daml/Finance/App/Interface/Listing/Listing.daml index d7dc8b77..b8c05e0d 100644 --- a/src/daml/Daml/Finance/App/Interface/Listing/Listing.daml +++ b/src/daml/Daml/Finance/App/Interface/Listing/Listing.daml @@ -4,8 +4,7 @@ module Daml.Finance.App.Interface.Listing.Listing where import Daml.Finance.App.Interface.Common.Removable qualified as Removable (I, Implementation) -import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (K) -import Daml.Finance.Interface.Types.Common (Id, Parties) +import Daml.Finance.Interface.Types.Common (Id, InstrumentKey, Parties) type I = Listing @@ -18,8 +17,8 @@ data View = View customer : Party id : Id description : Text - tradedInstrument : Instrument.K - quotedInstrument : Instrument.K + tradedInstrument : InstrumentKey + quotedInstrument : InstrumentKey observers : Parties deriving (Eq, Show) diff --git a/src/daml/Daml/Finance/App/Interface/Listing/ListingRequest.daml b/src/daml/Daml/Finance/App/Interface/Listing/ListingRequest.daml index ce97a5e8..2bdc6ff7 100644 --- a/src/daml/Daml/Finance/App/Interface/Listing/ListingRequest.daml +++ b/src/daml/Daml/Finance/App/Interface/Listing/ListingRequest.daml @@ -4,8 +4,7 @@ module Daml.Finance.App.Interface.Listing.ListingRequest where import Daml.Finance.App.Interface.Common.Removable qualified as Removable (I, Implementation) -import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (K) -import Daml.Finance.Interface.Types.Common (Id, Parties) +import Daml.Finance.Interface.Types.Common (Id, InstrumentKey, Parties) type I = ListingRequest @@ -18,8 +17,8 @@ data View = View customer : Party listingId : Id description : Text - tradedInstrument : Instrument.K - quotedInstrument : Instrument.K + tradedInstrument : InstrumentKey + quotedInstrument : InstrumentKey observers : Parties deriving (Eq, Show) diff --git a/src/daml/Daml/Finance/App/Interface/Listing/Service.daml b/src/daml/Daml/Finance/App/Interface/Listing/Service.daml index 0fc8dbeb..bd1f76ff 100644 --- a/src/daml/Daml/Finance/App/Interface/Listing/Service.daml +++ b/src/daml/Daml/Finance/App/Interface/Listing/Service.daml @@ -7,8 +7,7 @@ import Daml.Finance.App.Interface.Base.Service qualified as Base (I, Implementat import Daml.Finance.App.Interface.Listing.Listing qualified as Listing (I) import Daml.Finance.App.Interface.Listing.ListingRequest qualified as ListingRequest (I) import Daml.Finance.App.Interface.Listing.DelistingRequest qualified as DelistingRequest (I) -import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (K) -import Daml.Finance.Interface.Types.Common (Id, Parties) +import Daml.Finance.Interface.Types.Common (Id, InstrumentKey, Parties) import Prelude hiding (List) type I = Service @@ -40,8 +39,8 @@ interface Service where with listingId : Id description : Text - tradedInstrument : Instrument.K - quotedInstrument : Instrument.K + tradedInstrument : InstrumentKey + quotedInstrument : InstrumentKey observers : Parties controller (view $ asBase this).customer do diff --git a/src/daml/Daml/Finance/App/Listing/Model.daml b/src/daml/Daml/Finance/App/Listing/Model.daml index 94e21c07..bfa1d022 100644 --- a/src/daml/Daml/Finance/App/Listing/Model.daml +++ b/src/daml/Daml/Finance/App/Listing/Model.daml @@ -8,8 +8,7 @@ import Daml.Finance.App.Interface.Common.Removable qualified as Removable (I, Vi import Daml.Finance.App.Interface.Listing.DelistingRequest qualified as DelistingRequest (I, View(..)) import Daml.Finance.App.Interface.Listing.Listing qualified as Listing (I, View(..)) import Daml.Finance.App.Interface.Listing.ListingRequest qualified as ListingRequest (I, View(..)) -import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (K) -import Daml.Finance.Interface.Types.Common (Id, Parties) +import Daml.Finance.Interface.Types.Common (Id, InstrumentKey, Parties) type T = Listing @@ -20,8 +19,8 @@ template Listing customer : Party id : Id description : Text - tradedInstrument : Instrument.K - quotedInstrument : Instrument.K + tradedInstrument : InstrumentKey + quotedInstrument : InstrumentKey observers : Parties where signatory operator, provider, customer @@ -45,8 +44,8 @@ template ListingRequest customer : Party listingId : Id description : Text - tradedInstrument : Instrument.K - quotedInstrument : Instrument.K + tradedInstrument : InstrumentKey + quotedInstrument : InstrumentKey observers : Parties where signatory operator, provider, customer diff --git a/src/daml/Daml/Finance/App/Structuring/Auto/Service.daml b/src/daml/Daml/Finance/App/Structuring/Auto/Service.daml index 0f813640..503753f5 100644 --- a/src/daml/Daml/Finance/App/Structuring/Auto/Service.daml +++ b/src/daml/Daml/Finance/App/Structuring/Auto/Service.daml @@ -5,8 +5,8 @@ module Daml.Finance.App.Structuring.Auto.Service where import Daml.Finance.App.Structuring.Service qualified as S import Daml.Finance.Interface.Claims.Types (C) -import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (I, K) -import Daml.Finance.Interface.Types.Common (Id, PartiesMap) +import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (I) +import Daml.Finance.Interface.Types.Common (Id, InstrumentKey, PartiesMap) import Daml.Finance.Interface.Types.Date.Calendar (BusinessDayConventionEnum) import Daml.Finance.Interface.Types.Date.DayCount (DayCountConventionEnum) import Daml.Finance.Interface.Types.Date.RollConvention (PeriodEnum) @@ -72,7 +72,7 @@ template Service businessDayConvention : BusinessDayConventionEnum couponPeriod : PeriodEnum couponPeriodMultiplier : Int - currency : Instrument.K + currency : InstrumentKey observers : PartiesMap lastEventTimestamp : Time controller customer @@ -95,7 +95,7 @@ template Service businessDayConvention : BusinessDayConventionEnum couponPeriod : PeriodEnum couponPeriodMultiplier : Int - currency : Instrument.K + currency : InstrumentKey observers : PartiesMap lastEventTimestamp : Time controller customer @@ -119,7 +119,7 @@ template Service businessDayConvention : BusinessDayConventionEnum couponPeriod : PeriodEnum couponPeriodMultiplier : Int - currency : Instrument.K + currency : InstrumentKey observers : PartiesMap lastEventTimestamp : Time controller customer @@ -133,7 +133,7 @@ template Service description : Text issueDate : Date maturityDate : Date - currency : Instrument.K + currency : InstrumentKey observers : PartiesMap lastEventTimestamp : Time controller customer diff --git a/src/daml/Daml/Finance/App/Structuring/Model.daml b/src/daml/Daml/Finance/App/Structuring/Model.daml index a41bc09a..4a9b22e2 100644 --- a/src/daml/Daml/Finance/App/Structuring/Model.daml +++ b/src/daml/Daml/Finance/App/Structuring/Model.daml @@ -3,9 +3,8 @@ module Daml.Finance.App.Structuring.Model where -import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (K) import Daml.Finance.Interface.Claims.Types (C) -import Daml.Finance.Interface.Types.Common (Id, PartiesMap) +import Daml.Finance.Interface.Types.Common (Id, InstrumentKey, PartiesMap) import Daml.Finance.Interface.Types.Date.Calendar (BusinessDayConventionEnum) import Daml.Finance.Interface.Types.Date.DayCount (DayCountConventionEnum) import Daml.Finance.Interface.Types.Date.RollConvention (PeriodEnum) @@ -66,7 +65,7 @@ template CreateFixedRateBondRequest businessDayConvention : BusinessDayConventionEnum couponPeriod : PeriodEnum couponPeriodMultiplier : Int - currency : Instrument.K + currency : InstrumentKey observers : PartiesMap lastEventTimestamp : Time where @@ -90,7 +89,7 @@ template CreateFloatingRateBondRequest businessDayConvention : BusinessDayConventionEnum couponPeriod : PeriodEnum couponPeriodMultiplier : Int - currency : Instrument.K + currency : InstrumentKey observers : PartiesMap lastEventTimestamp : Time where @@ -115,7 +114,7 @@ template CreateInflationLinkedBondRequest businessDayConvention : BusinessDayConventionEnum couponPeriod : PeriodEnum couponPeriodMultiplier : Int - currency : Instrument.K + currency : InstrumentKey observers : PartiesMap lastEventTimestamp : Time where @@ -130,7 +129,7 @@ template CreateZeroCouponBondRequest description : Text issueDate : Date maturityDate : Date - currency : Instrument.K + currency : InstrumentKey observers : PartiesMap lastEventTimestamp : Time where diff --git a/src/daml/Daml/Finance/App/Structuring/Service.daml b/src/daml/Daml/Finance/App/Structuring/Service.daml index c0e17ae2..918a8318 100644 --- a/src/daml/Daml/Finance/App/Structuring/Service.daml +++ b/src/daml/Daml/Finance/App/Structuring/Service.daml @@ -7,7 +7,7 @@ import DA.Date (toGregorian) import Daml.Finance.App.Structuring.Model import Daml.Finance.App.Util (fetchAndArchive) import Daml.Finance.Interface.Claims.Types (C) -import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (I, K) +import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (I) import Daml.Finance.Interface.Instrument.Bond.FixedRate.Factory qualified as FixedRateBond (Factory, Create(..)) import Daml.Finance.Interface.Instrument.Bond.FixedRate.Types (FixedRate(..)) import Daml.Finance.Interface.Instrument.Bond.FloatingRate.Factory qualified as FloatingRateBond (Factory, Create(..)) @@ -96,7 +96,7 @@ template Service businessDayConvention : BusinessDayConventionEnum couponPeriod : PeriodEnum couponPeriodMultiplier : Int - currency : Instrument.K + currency : InstrumentKey observers : PartiesMap lastEventTimestamp : Time controller customer @@ -118,7 +118,7 @@ template Service businessDayConvention : BusinessDayConventionEnum couponPeriod : PeriodEnum couponPeriodMultiplier : Int - currency : Instrument.K + currency : InstrumentKey observers : PartiesMap lastEventTimestamp : Time controller customer @@ -141,7 +141,7 @@ template Service businessDayConvention : BusinessDayConventionEnum couponPeriod : PeriodEnum couponPeriodMultiplier : Int - currency : Instrument.K + currency : InstrumentKey observers : PartiesMap lastEventTimestamp : Time controller customer @@ -154,7 +154,7 @@ template Service description : Text issueDate : Date maturityDate : Date - currency : Instrument.K + currency : InstrumentKey observers : PartiesMap lastEventTimestamp : Time controller customer diff --git a/src/daml/Daml/Finance/Setup/Payoff.daml b/src/daml/Daml/Finance/Setup/Payoff.daml index e96ebb76..493c19d1 100644 --- a/src/daml/Daml/Finance/Setup/Payoff.daml +++ b/src/daml/Daml/Finance/Setup/Payoff.daml @@ -10,88 +10,89 @@ import ContingentClaims.Core.Builders (forward, fixed, floating, swap, european, import DA.Date (DayOfWeek(..), Month(..), addDays, date, monthDayCount, toGregorian) import DA.List (last) import DA.Time (time) +import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (Q) +import Daml.Finance.Interface.Types.Common (InstrumentKey) import Daml.Finance.Interface.Types.Date.Calendar import Daml.Finance.Interface.Types.Date.DayCount import Daml.Finance.Interface.Types.Date.RollConvention import Daml.Finance.Interface.Types.Date.Schedule -import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (K, Q) import Daml.Finance.Util.Date.DayCount import Daml.Finance.Util.Date.Schedule import Prelude hiding (and, or, (<=)) -type C = Claim Time Decimal Instrument.K Text +type C = Claim Time Decimal InstrumentKey Text t : Date -> Time t d = time d 12 00 00 -payment : Instrument.K -> Decimal -> C +payment : InstrumentKey -> Decimal -> C payment ccy qty = scale (Const qty) (one ccy) -delivery : Instrument.K -> Decimal -> C +delivery : InstrumentKey -> Decimal -> C delivery asset qty = give $ scale (Const qty) (one asset) -futurePayment : Instrument.K -> Decimal -> Date -> C +futurePayment : InstrumentKey -> Decimal -> Date -> C futurePayment ccy qty d = when (at $ t d) $ payment ccy qty -futureDelivery : Instrument.K -> Decimal -> Date -> C +futureDelivery : InstrumentKey -> Decimal -> Date -> C futureDelivery asset qty d = when (at $ t d) $ delivery asset qty -dvp : Instrument.K -> Decimal -> Instrument.K -> Decimal -> C +dvp : InstrumentKey -> Decimal -> InstrumentKey -> Decimal -> C dvp asset assetQty ccy ccyQty = delivery asset assetQty `and` payment ccy ccyQty -futureDvp : Instrument.K -> Decimal -> Instrument.K -> Decimal -> Date -> C +futureDvp : InstrumentKey -> Decimal -> InstrumentKey -> Decimal -> Date -> C futureDvp asset assetQty ccy ccyQty d = when (at $ t d) $ dvp asset assetQty ccy ccyQty -floatingStream : Observation Time Decimal Text -> Instrument.K -> [Time] -> C +floatingStream : Observation Time Decimal Text -> InstrumentKey -> [Time] -> C floatingStream rate ccy dates = case dates of d :: rest -> forward d rate (one ccy) `and` floatingStream rate ccy rest [] -> zero -fixedStream : Decimal -> Instrument.K -> [Time] -> C +fixedStream : Decimal -> InstrumentKey -> [Time] -> C fixedStream rate ccy dates = floatingStream (Const rate) ccy dates -bond : Instrument.K -> Decimal -> Decimal -> [Date] -> C +bond : InstrumentKey -> Decimal -> Decimal -> [Date] -> C bond ccy notional coupon dates = fixed notional (notional * coupon) ccy (map t dates) -callOptionPhysical : Instrument.K -> Decimal -> Instrument.K -> Decimal -> Date -> C +callOptionPhysical : InstrumentKey -> Decimal -> InstrumentKey -> Decimal -> Date -> C callOptionPhysical asset assetQty ccy ccyQty maturity = european (t maturity) $ dvp ccy ccyQty asset assetQty -putOptionPhysical : Instrument.K -> Decimal -> Instrument.K -> Decimal -> Date -> C +putOptionPhysical : InstrumentKey -> Decimal -> InstrumentKey -> Decimal -> Date -> C putOptionPhysical asset assetQty ccy ccyQty maturity = european (t maturity) $ dvp asset assetQty ccy ccyQty -callOptionCash : Text -> Instrument.K -> Decimal -> Date -> C +callOptionCash : Text -> InstrumentKey -> Decimal -> Date -> C callOptionCash underlying ccy strike maturity = european (t maturity) $ scale (observe underlying - Const strike) (one ccy) -putOptionCash : Text -> Instrument.K -> Decimal -> Date -> C +putOptionCash : Text -> InstrumentKey -> Decimal -> Date -> C putOptionCash underlying ccy strike maturity = european (t maturity) $ scale (Const strike - observe underlying) (one ccy) -callOptionCashAuto : Text -> Instrument.K -> Decimal -> Date -> C +callOptionCashAuto : Text -> InstrumentKey -> Decimal -> Date -> C callOptionCashAuto underlying ccy strike maturity = let predicate = Const strike <= observe underlying cash = (observe underlying) - Const strike in when (at $ t maturity) $ cond predicate (scale cash $ one ccy) zero -putOptionCashAuto : Text -> Instrument.K -> Decimal -> Date -> C +putOptionCashAuto : Text -> InstrumentKey -> Decimal -> Date -> C putOptionCashAuto underlying ccy strike maturity = let predicate = observe underlying <= Const strike cash = (Const strike) - (observe underlying) in when (at $ t maturity) $ cond predicate (scale cash $ one ccy) zero -kiPutOptionCashAuto : Text -> Instrument.K -> Decimal -> Decimal -> Date -> Date -> C +kiPutOptionCashAuto : Text -> InstrumentKey -> Decimal -> Decimal -> Date -> Date -> C kiPutOptionCashAuto underlying ccy strike barrier barrierStartDate maturity = let und = observe underlying @@ -100,21 +101,21 @@ kiPutOptionCashAuto underlying ccy strike barrier barrierStartDate maturity = barrierPredicate = und <= (Const barrier) in when (at $ t barrierStartDate) $ when barrierPredicate $ when (at $ t maturity) $ cond optionPredicate (scale cash $ one ccy) zero -callOptionPhysicalAuto : Text -> Instrument.K -> Decimal -> Instrument.K -> Decimal -> Decimal -> Date -> C +callOptionPhysicalAuto : Text -> InstrumentKey -> Decimal -> InstrumentKey -> Decimal -> Decimal -> Date -> C callOptionPhysicalAuto assetObs asset assetQty ccy ccyQty strike maturity = let predicate = Const strike <= observe assetObs payoff = dvp ccy ccyQty asset assetQty in when (at $ t maturity) $ cond predicate payoff zero -putOptionPhysicalAuto : Text -> Instrument.K -> Decimal -> Instrument.K -> Decimal -> Decimal -> Date -> C +putOptionPhysicalAuto : Text -> InstrumentKey -> Decimal -> InstrumentKey -> Decimal -> Decimal -> Date -> C putOptionPhysicalAuto assetObs asset assetQty ccy ccyQty strike maturity = let predicate = observe assetObs <= Const strike payoff = dvp asset assetQty ccy ccyQty in when (at $ t maturity) $ cond predicate payoff zero -reverseConvertibleExplicit : Text -> Instrument.K -> Instrument.K -> Decimal -> Decimal -> Decimal -> Date -> C +reverseConvertibleExplicit : Text -> InstrumentKey -> InstrumentKey -> Decimal -> Decimal -> Decimal -> Date -> C reverseConvertibleExplicit assetObs asset ccy notional strike interest maturity = let payment = (1.0 + interest) * notional @@ -122,7 +123,7 @@ reverseConvertibleExplicit assetObs asset ccy notional strike interest maturity put = putOptionPhysicalAuto assetObs asset (notional / strike) ccy payment strike maturity in deposit `and` (give put) -reverseConvertible : Text -> Instrument.K -> Instrument.K -> Decimal -> Decimal -> Decimal -> Date -> C +reverseConvertible : Text -> InstrumentKey -> InstrumentKey -> Decimal -> Decimal -> Decimal -> Date -> C reverseConvertible assetObs asset ccy notional strike interest maturity = let conversioncondition = observe assetObs <= Const strike @@ -130,42 +131,42 @@ reverseConvertible assetObs asset ccy notional strike interest maturity = principalPayout = scale (Const (notional * (1.0 + interest))) (one ccy) in when (at $ t maturity) $ cond conversioncondition conversionPayout principalPayout -rc : Text -> Instrument.K -> Decimal -> Decimal -> [Date] -> C +rc : Text -> InstrumentKey -> Decimal -> Decimal -> [Date] -> C rc asset ccy coupon strike dates = let bondLeg = bond ccy strike coupon dates put = putOptionCash asset ccy strike (last dates) in And (give put) bondLeg [] -brc : Text -> Instrument.K -> Decimal -> Decimal -> Decimal -> Date -> [Date] -> C +brc : Text -> InstrumentKey -> Decimal -> Decimal -> Decimal -> Date -> [Date] -> C brc asset ccy coupon strike barrier barrierStartDate dates = let bondLeg = bond ccy strike coupon dates kiPut = kiPutOptionCashAuto asset ccy strike barrier barrierStartDate (last dates) in bondLeg `and` give kiPut -call : Instrument.K -> Text -> Decimal -> C +call : InstrumentKey -> Text -> Decimal -> C call ccy underlying strike = let payoff = (observe underlying) - (Const strike) payout = scale payoff (one ccy) in payout `or` zero -put : Instrument.K -> Text -> Decimal -> C +put : InstrumentKey -> Text -> Decimal -> C put ccy underlying strike = let payoff = Const strike - observe underlying payout = scale payoff (one ccy) in payout `or` zero -turboCall : Instrument.K -> Text -> Decimal -> Decimal -> Date -> C +turboCall : InstrumentKey -> Text -> Decimal -> Decimal -> Date -> C turboCall ccy underlying strike barrier startDate = let option = call ccy underlying strike barriercondition = observe underlying <= Const barrier in until barriercondition $ anytime (at $ t startDate) option -inverseConvertibleExplicit : Text -> Instrument.K -> Instrument.K -> Decimal -> Decimal -> Decimal -> Date -> C +inverseConvertibleExplicit : Text -> InstrumentKey -> InstrumentKey -> Decimal -> Decimal -> Decimal -> Date -> C inverseConvertibleExplicit assetObs asset ccy notional strike interest maturity = let interestAmount = notional * strike * interest @@ -173,7 +174,7 @@ inverseConvertibleExplicit assetObs asset ccy notional strike interest maturity call = callOptionPhysicalAuto assetObs asset notional ccy (notional * strike + interestAmount) strike maturity in deposit `and` (give call) -inverseConvertible : Text -> Instrument.K -> Instrument.K -> Decimal -> Decimal -> Decimal -> Date -> C +inverseConvertible : Text -> InstrumentKey -> InstrumentKey -> Decimal -> Decimal -> Decimal -> Date -> C inverseConvertible assetObs asset ccy notional strike interest maturity = let interestAmount = notional * strike * interest @@ -182,19 +183,19 @@ inverseConvertible assetObs asset ccy notional strike interest maturity = principalPayout = scale (Const notional) (one asset) `and` scale (Const interestAmount) (one ccy) in when (at $ t maturity) $ cond conversioncondition conversionPayout principalPayout -binaryCallOption : Text -> Instrument.K -> Decimal -> Date -> C +binaryCallOption : Text -> InstrumentKey -> Decimal -> Date -> C binaryCallOption underlying ccy strike expiry = when (at $ t expiry) $ cond (Const strike <= observe underlying) (one ccy) zero `or` zero -koPutWarrant : Decimal -> Decimal -> Text -> Instrument.K -> C +koPutWarrant : Decimal -> Decimal -> Text -> InstrumentKey -> C koPutWarrant barrier strike underlying ccy = cond (observe underlying <= Const barrier) (scale (Const strike + (observe underlying)) (one ccy) `or` zero) zero -convertibleShare : Instrument.K -> Instrument.K -> Date -> C +convertibleShare : InstrumentKey -> InstrumentKey -> Date -> C convertibleShare from to conversionDate = when (at $ t conversionDate) $ (give (one from) `and` (one to)) `or` (one from) -interestRateSwap : Text -> Decimal -> Instrument.K -> [Date] -> C +interestRateSwap : Text -> Decimal -> InstrumentKey -> [Date] -> C interestRateSwap floatingRateId fixedRate ccyId fixingDates = let floatObs = observe floatingRateId @@ -202,7 +203,7 @@ interestRateSwap floatingRateId fixedRate ccyId fixingDates = fixedLeg = fixedStream fixedRate ccyId in swap floatingLeg fixedLeg (map t fixingDates) -basisSwap : Text -> Text -> Decimal -> Instrument.K -> [Date] -> C +basisSwap : Text -> Text -> Decimal -> InstrumentKey -> [Date] -> C basisSwap floatingRateId1 floatingRateId2 spread ccyId fixingDates = let floatObs1 = observe floatingRateId1 @@ -211,7 +212,7 @@ basisSwap floatingRateId1 floatingRateId2 spread ccyId fixingDates = floatingLeg2 = floatingStream floatObs2 ccyId in swap floatingLeg1 floatingLeg2 (map t fixingDates) -bermudanSwaption : Text -> Decimal -> Instrument.K -> Decimal -> [Date] -> [Date] -> C +bermudanSwaption : Text -> Decimal -> InstrumentKey -> Decimal -> [Date] -> [Date] -> C bermudanSwaption floatingRateId fixedRate fixedCcyId principal fixingDates exerciseDates = let floatObs = observe floatingRateId @@ -219,7 +220,7 @@ bermudanSwaption floatingRateId fixedRate fixedCcyId principal fixingDates exerc fixedLeg = fixed principal fixedRate fixedCcyId in bermudan (map t exerciseDates) $ swap floatingLeg fixedLeg (map t fixingDates) -convertibleNote : Text -> Instrument.K -> Instrument.K -> Decimal -> Decimal -> Date -> Decimal -> Decimal -> C +convertibleNote : Text -> InstrumentKey -> InstrumentKey -> Decimal -> Decimal -> Date -> Decimal -> Decimal -> C convertibleNote underlyingObs underlying ccy principal discount maturity interest cap = let conversioncondition = observe underlyingObs <= Const cap @@ -227,7 +228,7 @@ convertibleNote underlyingObs underlying ccy principal discount maturity interes cappedPayout = scale (Const (principal * (1.0 + interest)) / (Const cap * Const (1.0 - discount))) (one underlying) in when (at $ t maturity) $ cond conversioncondition conversionPayout cappedPayout -accumulator : Text -> Instrument.K -> Instrument.K -> Decimal -> Decimal -> Decimal -> Decimal -> [Date] -> C +accumulator : Text -> InstrumentKey -> InstrumentKey -> Decimal -> Decimal -> Decimal -> Decimal -> [Date] -> C accumulator assetObs asset ccy strike aboveBuyQty belowBuyQty knockOutLevel dates = let kocondition = Const knockOutLevel <= observe assetObs @@ -245,7 +246,7 @@ accumulator assetObs asset ccy strike aboveBuyQty belowBuyQty knockOutLevel date claims = foldr accumulator first t in until kocondition claims -decumulator : Text -> Instrument.K -> Instrument.K -> Decimal -> Decimal -> Decimal -> Decimal -> [Date] -> C +decumulator : Text -> InstrumentKey -> InstrumentKey -> Decimal -> Decimal -> Decimal -> Decimal -> [Date] -> C decumulator assetObs asset ccy strike aboveSellQty belowSellQty knockOutLevel dates = let kocondition = observe assetObs <= Const knockOutLevel @@ -263,7 +264,7 @@ decumulator assetObs asset ccy strike aboveSellQty belowSellQty knockOutLevel da claims = foldr accumulator first t in until kocondition claims -buyWriteNote : Date -> Date -> Date -> Text -> Instrument.K -> Decimal -> Decimal -> Decimal -> C +buyWriteNote : Date -> Date -> Date -> Text -> InstrumentKey -> Decimal -> Decimal -> Decimal -> C buyWriteNote issueDate endDate maturityDate und ccy couponRatePerAnnum denominationCcy capPrice = let (iy, im, id) = toGregorian issueDate @@ -329,7 +330,7 @@ buyWriteNote issueDate endDate maturityDate und ccy couponRatePerAnnum denominat in cCoupon `and` cPayoff -- | Multiple delivery locations -ngMultiLocation : Date -> Date -> [Instrument.Q] -> Decimal -> Instrument.K -> C +ngMultiLocation : Date -> Date -> [Instrument.Q] -> Decimal -> InstrumentKey -> C ngMultiLocation startDate endDate deliveries price ccy = let total = sum $ map (.amount) deliveries @@ -343,7 +344,7 @@ ngMultiLocation startDate endDate deliveries price ccy = in claim -- | Location / Pricing options -ngLocationPricingOption : Date -> Date -> Decimal -> Instrument.K -> Text -> Instrument.K -> Text -> Instrument.K -> C +ngLocationPricingOption : Date -> Date -> Decimal -> InstrumentKey -> Text -> InstrumentKey -> Text -> InstrumentKey -> C ngLocationPricingOption startDate endDate quantity location1 price1 location2 price2 ccy = let dates = rollDaily startDate endDate @@ -353,7 +354,7 @@ ngLocationPricingOption startDate endDate quantity location1 price1 location2 pr in claim -- | Capped price -ngCapped : Date -> Date -> Decimal -> Instrument.K -> Text -> Decimal -> Instrument.K -> C +ngCapped : Date -> Date -> Decimal -> InstrumentKey -> Text -> Decimal -> InstrumentKey -> C ngCapped startDate endDate quantity asset price cap ccy = let dates = rollDaily startDate endDate @@ -367,7 +368,7 @@ ngCapped startDate endDate quantity asset price cap ccy = in claim -- | Price-conditional location -ngConditionalLocation : Date -> Date -> Decimal -> Instrument.K -> Text -> Decimal -> Instrument.K -> Text -> Instrument.K -> C +ngConditionalLocation : Date -> Date -> Decimal -> InstrumentKey -> Text -> Decimal -> InstrumentKey -> Text -> InstrumentKey -> C ngConditionalLocation startDate endDate quantity location1 price1 price1Cap location2 price2 ccy = let dates = rollDaily startDate endDate @@ -376,7 +377,7 @@ ngConditionalLocation startDate endDate quantity location1 price1 price1Cap loca claim = mconcat $ map (\date -> when (at $ t date) $ cond (observe price1 <= Const price1Cap) c1 c2) dates in claim -loan : Date -> Date -> Instrument.K -> Decimal -> Instrument.K -> [Date] -> C +loan : Date -> Date -> InstrumentKey -> Decimal -> InstrumentKey -> [Date] -> C loan startDate endDate underlying interestAmount interestCurrency interestDates = let initial = when (at $ t startDate) $ one underlying diff --git a/src/daml/Daml/Finance/Setup/Util/Common.daml b/src/daml/Daml/Finance/Setup/Util/Common.daml index e4e59059..ed54ad16 100644 --- a/src/daml/Daml/Finance/Setup/Util/Common.daml +++ b/src/daml/Daml/Finance/Setup/Util/Common.daml @@ -10,7 +10,8 @@ import DA.Optional (fromOptional) import Daml.Finance.Holding.Fungible qualified as Fungible (T) import Daml.Finance.Interface.Holding.Fungible qualified as Fungible (I, Split(..), SplitResult(..)) import Daml.Finance.Interface.Holding.Base qualified as Holding (I) -import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (GetCid(..), K, Q, R) +import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (GetCid(..), Q, R) +import Daml.Finance.Interface.Types.Common (InstrumentKey) import Daml.Script data PartyInfo = PartyInfo @@ -52,5 +53,5 @@ submitExerciseInterfaceByKeyCmdHelper actAs readAs k arg1 arg2 = do submitMulti actAs readAs do exerciseCmd cid' arg2 -- | Utility for exercising an interface by key. -submitExerciseInterfaceByKeyCmd : forall t2 c2 b . HasTemplateTypeRep t2 => HasToAnyTemplate t2 => HasFromAnyTemplate t2 => HasFromAnyChoice t2 c2 b => HasToAnyChoice t2 c2 b => HasExercise t2 c2 b => [Party] -> [Party] -> Instrument.K -> c2 -> Script b +submitExerciseInterfaceByKeyCmd : forall t2 c2 b . HasTemplateTypeRep t2 => HasToAnyTemplate t2 => HasFromAnyTemplate t2 => HasFromAnyChoice t2 c2 b => HasToAnyChoice t2 c2 b => HasExercise t2 c2 b => [Party] -> [Party] -> InstrumentKey -> c2 -> Script b submitExerciseInterfaceByKeyCmd actAs readAs k arg = submitExerciseInterfaceByKeyCmdHelper @Instrument.R @t2 actAs readAs k (Instrument.GetCid with viewer = head actAs) arg diff --git a/src/daml/Daml/Finance/Setup/Util/Workflow.daml b/src/daml/Daml/Finance/Setup/Util/Workflow.daml index 09ec4c4f..5203349f 100644 --- a/src/daml/Daml/Finance/Setup/Util/Workflow.daml +++ b/src/daml/Daml/Finance/Setup/Util/Workflow.daml @@ -53,7 +53,7 @@ import Daml.Finance.Interface.Data.TimeObservable qualified as TimeObservable (I import Daml.Finance.Interface.Holding.Base qualified as Holding (I) import Daml.Finance.Interface.Holding.Fungible qualified as Fungible (I) import Daml.Finance.Interface.Holding.Transferable qualified as Transferable (I, Transfer(..)) -import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (GetView(..), I, K, Q, Reference(..)) +import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (GetView(..), I, Q, Reference(..)) import Daml.Finance.Interface.Lifecycle.Event qualified as Event (I) import Daml.Finance.Interface.Lifecycle.Effect qualified as Effect (I) import Daml.Finance.Interface.Lifecycle.Rule.Claim qualified as Claim (ClaimEffect(..), ClaimResult(..)) @@ -61,7 +61,7 @@ import Daml.Finance.Interface.Settlement.Batch qualified as Batch (I) import Daml.Finance.Interface.Settlement.Factory qualified as SettlementFactory (I) import Daml.Finance.Interface.Settlement.Instruction qualified as Instruction (I, Allocate(..), Approve(..)) import Daml.Finance.Interface.Settlement.Types qualified as Settlement (Allocation, Approval) -import Daml.Finance.Interface.Types.Common (AccountKey, Id(..), Parties, PartiesMap) +import Daml.Finance.Interface.Types.Common (AccountKey, Id(..), InstrumentKey, Parties, PartiesMap) import Daml.Finance.Interface.Types.Date.Calendar (BusinessDayAdjustment(..), BusinessDayConventionEnum, HolidayCalendarData(..)) import Daml.Finance.Interface.Types.Date.DayCount (DayCountConventionEnum) import Daml.Finance.Interface.Types.Date.RollConvention (PeriodEnum, RollConventionEnum(..)) @@ -80,13 +80,13 @@ createAccount operator provider customer public id observers = do openAccountRequestCid <- submit customer do exerciseCmd (toInterfaceContractId @Custody.I custodyServiceCid) Custody.RequestOpenAccount with id = Id id; description = id; controllers; observers snd <$> submitMulti [provider] [public] do exerciseCmd (toInterfaceContractId @Custody.I custodyServiceCid) Custody.OpenAccount with openAccountRequestCid -createAccountDirectory : Party -> [(Instrument.K, Account.K)] -> Parties -> Script (ContractId AccountDirectory) +createAccountDirectory : Party -> [(InstrumentKey, Account.K)] -> Parties -> Script (ContractId AccountDirectory) createAccountDirectory provider mapping observers = do submit provider do createCmd AccountDirectory with provider; accounts = M.fromList (map (\(i, a) -> (i.id, a)) mapping); observers -- | Create a `Reference` for an instrument. -- Note: This should only be called together with an instrument creation -createReference : ContractId Instrument.I -> Party -> Party -> PartiesMap -> Script Instrument.K +createReference : ContractId Instrument.I -> Party -> Party -> PartiesMap -> Script InstrumentKey createReference cid depository issuer observers = do instrumentView <- submitMulti [depository, issuer] [] do exerciseCmd cid Instrument.GetView with viewer = issuer let ref = Instrument.Reference with instrumentView; cid; observers @@ -138,25 +138,25 @@ createCalendar provider id weekend holidays observers = do calendar = HolidayCalendarData with id; weekend; holidays submit provider do createCmd Data.HolidayCalendar with agency = provider; entity = calendar.id; calendar; observers -originateToken : Party -> Party -> PartiesMap -> Time -> Text -> Text -> Script Instrument.K +originateToken : Party -> Party -> PartiesMap -> Time -> Text -> Text -> Script InstrumentKey originateToken depository issuer observers validAsOf id description = do cid <- coerceContractId <$> submitMulti [depository, issuer] [] do createCmd Token.Instrument with depository; issuer; id = Id id; version = "0"; observers; validAsOf; description createReference cid depository issuer observers -originateEquity : Party -> Party -> PartiesMap -> Time -> Text -> Text -> Script Instrument.K +originateEquity : Party -> Party -> PartiesMap -> Time -> Text -> Text -> Script InstrumentKey originateEquity depository issuer observers validAsOf id description = do cid <- coerceContractId <$> submitMulti [depository, issuer] [] do createCmd Equity.Instrument with depository; issuer; id = Id id; version = "0"; observers; validAsOf; description createReference cid depository issuer observers -originateGeneric : Party -> Party -> PartiesMap -> Time -> Text -> Text -> C -> Script Instrument.K +originateGeneric : Party -> Party -> PartiesMap -> Time -> Text -> Text -> C -> Script InstrumentKey originateGeneric depository issuer observers acquisitionTime id description claims = do cid <- coerceContractId <$> submitMulti [depository, issuer] [] do createCmd Generic.Instrument with depository; issuer; id = Id id; description; version = "0"; acquisitionTime; claims; observers; lastEventTimestamp = acquisitionTime createReference cid depository issuer observers -originateFixedRateBond : Party -> Party -> Text -> Text -> PartiesMap -> Time -> Date -> [Text] -> Party -> Date-> Date -> DayCountConventionEnum -> BusinessDayConventionEnum -> Decimal -> PeriodEnum -> Int -> Instrument.K -> Script Instrument.K +originateFixedRateBond : Party -> Party -> Text -> Text -> PartiesMap -> Time -> Date -> [Text] -> Party -> Date-> Date -> DayCountConventionEnum -> BusinessDayConventionEnum -> Decimal -> PeriodEnum -> Int -> InstrumentKey -> Script InstrumentKey originateFixedRateBond depository issuer id description observers lastEventTimestamp issueDate holidayCalendarIds calendarDataProvider firstCouponDate maturityDate dayCountConvention businessDayConvention couponRate couponPeriod couponPeriodMultiplier currency = do let periodicSchedule = createPaymentPeriodicSchedule firstCouponDate holidayCalendarIds businessDayConvention couponPeriod couponPeriodMultiplier issueDate maturityDate @@ -164,13 +164,13 @@ originateFixedRateBond depository issuer id description observers lastEventTimes createCmd FixedRate.Instrument with depository; issuer; id = Id id; version = "0"; description; observers; lastEventTimestamp; periodicSchedule; holidayCalendarIds; calendarDataProvider; dayCountConvention; couponRate; currency createReference cid depository issuer observers -originateZeroCouponBond : Party -> Party -> Text -> Text -> PartiesMap -> Time -> Date -> Date -> Instrument.K -> Script Instrument.K +originateZeroCouponBond : Party -> Party -> Text -> Text -> PartiesMap -> Time -> Date -> Date -> InstrumentKey -> Script InstrumentKey originateZeroCouponBond depository issuer id description observers lastEventTimestamp issueDate maturityDate currency = do cid <- toInterfaceContractId <$> submitMulti [depository, issuer] [] do createCmd ZeroCoupon.Instrument with depository; issuer; id = Id id; version = "0"; description; observers; lastEventTimestamp; issueDate; maturityDate; currency createReference cid depository issuer observers -originateFloatingRateBond : Party -> Party -> Text -> Text -> PartiesMap -> Time -> Date -> [Text] -> Party -> Date -> Date -> DayCountConventionEnum -> BusinessDayConventionEnum -> Decimal -> PeriodEnum -> Int -> Instrument.K -> Text -> Script Instrument.K +originateFloatingRateBond : Party -> Party -> Text -> Text -> PartiesMap -> Time -> Date -> [Text] -> Party -> Date -> Date -> DayCountConventionEnum -> BusinessDayConventionEnum -> Decimal -> PeriodEnum -> Int -> InstrumentKey -> Text -> Script InstrumentKey originateFloatingRateBond depository issuer id description observers lastEventTimestamp issueDate holidayCalendarIds calendarDataProvider firstCouponDate maturityDate dayCountConvention businessDayConvention couponRate couponPeriod couponPeriodMultiplier currency referenceRateId = do let periodicSchedule = createPaymentPeriodicSchedule firstCouponDate holidayCalendarIds businessDayConvention couponPeriod couponPeriodMultiplier issueDate maturityDate @@ -178,7 +178,7 @@ originateFloatingRateBond depository issuer id description observers lastEventTi createCmd FloatingRate.Instrument with depository; issuer; id = Id id; version = "0"; description; observers; lastEventTimestamp; periodicSchedule; holidayCalendarIds; calendarDataProvider; dayCountConvention; couponSpread=couponRate; referenceRateId; currency createReference cid depository issuer observers -originateInflationLinkedBond : Party -> Party -> Text -> Text -> PartiesMap -> Time -> Date -> [Text] -> Party -> Date -> Date -> DayCountConventionEnum -> BusinessDayConventionEnum -> Decimal -> PeriodEnum -> Int -> Instrument.K -> Text -> Decimal -> Script Instrument.K +originateInflationLinkedBond : Party -> Party -> Text -> Text -> PartiesMap -> Time -> Date -> [Text] -> Party -> Date -> Date -> DayCountConventionEnum -> BusinessDayConventionEnum -> Decimal -> PeriodEnum -> Int -> InstrumentKey -> Text -> Decimal -> Script InstrumentKey originateInflationLinkedBond depository issuer id description observers lastEventTimestamp issueDate holidayCalendarIds calendarDataProvider firstCouponDate maturityDate dayCountConvention businessDayConvention couponRate couponPeriod couponPeriodMultiplier currency inflationIndexId inflationIndexBaseValue = do let periodicSchedule = createPaymentPeriodicSchedule firstCouponDate holidayCalendarIds businessDayConvention couponPeriod couponPeriodMultiplier issueDate maturityDate @@ -186,7 +186,7 @@ originateInflationLinkedBond depository issuer id description observers lastEven createCmd InflationLinked.Instrument with depository; issuer; id = Id id; version = "0"; description; observers; lastEventTimestamp; periodicSchedule; holidayCalendarIds; calendarDataProvider; dayCountConvention; couponRate; inflationIndexId; currency; inflationIndexBaseValue createReference cid depository issuer observers -originateCreditDefaultSwap : Party -> Party -> Text -> Text -> PartiesMap -> Time -> Date -> [Text] -> Party -> Date -> Date -> DayCountConventionEnum -> BusinessDayConventionEnum -> Decimal -> PeriodEnum -> Int -> Instrument.K -> Text -> Text -> Bool -> Script Instrument.K +originateCreditDefaultSwap : Party -> Party -> Text -> Text -> PartiesMap -> Time -> Date -> [Text] -> Party -> Date -> Date -> DayCountConventionEnum -> BusinessDayConventionEnum -> Decimal -> PeriodEnum -> Int -> InstrumentKey -> Text -> Text -> Bool -> Script InstrumentKey originateCreditDefaultSwap depository issuer id description observers lastEventTimestamp issueDate holidayCalendarIds calendarDataProvider firstCouponDate maturityDate dayCountConvention businessDayConvention fixRate couponPeriod couponPeriodMultiplier currency defaultProbabilityReferenceId recoveryRateReferenceId issuerPaysFix = do let periodicSchedule = createPaymentPeriodicSchedule firstCouponDate holidayCalendarIds businessDayConvention couponPeriod couponPeriodMultiplier issueDate maturityDate @@ -213,7 +213,7 @@ issue operator provider customer public quantity account = do issueRequestCid <- submit customer do exerciseCmd (toInterfaceContractId @IssuanceService.I issuanceServiceCid) IssuanceService.RequestIssue with issuanceId; description; quantity; account submitMulti [provider] [public] do exerciseCmd (toInterfaceContractId @IssuanceService.I issuanceServiceCid) IssuanceService.Issue with issueRequestCid -list : Party -> Party -> Party -> Id -> Text -> Instrument.K -> Instrument.K -> Parties -> Script (ContractId Listing.I) +list : Party -> Party -> Party -> Id -> Text -> InstrumentKey -> InstrumentKey -> Parties -> Script (ContractId Listing.I) list operator provider customer listingId description tradedInstrument quotedInstrument observers = do Some (listingServiceCid, _) <- queryContractKey @Listing.Service customer (operator, provider, customer) listingRequestCid <- submit customer do exerciseCmd (toInterfaceContractId @ListingService.I listingServiceCid) ListingService.RequestListing with listingId; description; tradedInstrument; quotedInstrument; observers @@ -237,7 +237,7 @@ createBidOrder operator provider customer public id = createOrder operator provi createAskOrder : Party -> Party -> Party -> Party -> Id -> Instrument.Q -> Instrument.Q -> Parties -> Script (Optional (ContractId Trading.Order, Trading.Order)) createAskOrder operator provider customer public id = createOrder operator provider customer public id Trading.Sell -createAuction : Party -> Party -> Party -> Party -> Id -> Text -> Instrument.Q -> Instrument.K -> Decimal -> ContractId Fungible.I -> AccountKey -> Script (ContractId Auction.I) +createAuction : Party -> Party -> Party -> Party -> Id -> Text -> Instrument.Q -> InstrumentKey -> Decimal -> ContractId Fungible.I -> AccountKey -> Script (ContractId Auction.I) createAuction operator provider customer public auctionId description quantity currency floor collateralCid receivableAccount = do Some (serviceCid, _) <- queryContractKey @Auction.Service customer (operator, provider, customer) createAuctionRequestCid <- submit customer do exerciseCmd (toInterfaceContractId @AuctionService.I serviceCid) AuctionService.RequestCreateAuction with auctionId; description; quantity; currency; floor; collateralCid; receivableAccount; observers = singleton public @@ -255,7 +255,7 @@ processAuction operator provider customer public auctionCid bidCids = do Some (serviceCid, _) <- queryContractKey @Auction.Service provider (operator, provider, customer) submitMulti [provider] [public] do exerciseCmd (toInterfaceContractId @AuctionService.I serviceCid) AuctionService.ProcessAuction with settlementFactoryCid = toInterfaceContractId factoryCid; auctionCid; bidCids -declareDividend : Party -> Party -> Party -> Party -> Instrument.K -> Date -> [Instrument.Q] -> Script (ContractId Effect.I) +declareDividend : Party -> Party -> Party -> Party -> InstrumentKey -> Date -> [Instrument.Q] -> Script (ContractId Effect.I) declareDividend operator provider issuer public equity effectiveDate perUnitDistribution = do [(clockCid, _)] <- query @Data.DateClock public let @@ -273,7 +273,7 @@ declareDividend operator provider issuer public equity effectiveDate perUnitDist effectiveDate perUnitDistribution -declareReplacement : Party -> Party -> Party -> Party -> Instrument.K -> Date -> [Instrument.Q] -> Script (ContractId Effect.I) +declareReplacement : Party -> Party -> Party -> Party -> InstrumentKey -> Date -> [Instrument.Q] -> Script (ContractId Effect.I) declareReplacement operator provider issuer public equity effectiveDate perUnitReplacement = do [(clockCid, _)] <- query @Data.DateClock issuer let id = "Replacement-" <> show equity.id <> "-" <> equity.version @@ -288,7 +288,7 @@ declareReplacement operator provider issuer public equity effectiveDate perUnitR effectiveDate perUnitReplacement -declareStockSplit : Party -> Party -> Party -> Party -> Instrument.K -> Date -> Decimal -> Script (ContractId Effect.I) +declareStockSplit : Party -> Party -> Party -> Party -> InstrumentKey -> Date -> Decimal -> Script (ContractId Effect.I) declareStockSplit operator provider issuer public equity effectiveDate adjustmentFactor = do [(clockCid, _)] <- query @Data.DateClock issuer let From 5dad8f30ecf625ddbe902b1513c4138d0e9b8a03 Mon Sep 17 00:00:00 2001 From: Georg Schneider Date: Wed, 21 Dec 2022 12:22:03 +0100 Subject: [PATCH 11/31] Add interfaces for settlement and structuring services --- src/daml/Daml/Finance/App/Custody/Model.daml | 20 +- .../Daml/Finance/App/Custody/Service.daml | 10 + .../Finance/App/Interface/Custody/Auto.daml | 4 + .../Custody/CloseAccountRequest.daml | 1 + .../App/Interface/Custody/DepositRequest.daml | 1 + .../Interface/Custody/OpenAccountRequest.daml | 1 + .../Interface/Custody/WithdrawRequest.daml | 1 + .../App/Interface/Settlement/Service.daml | 51 ++++ .../App/Interface/Structuring/Auto.daml | 182 +++++++++++ .../Structuring/CreateEquityRequest.daml | 35 +++ .../CreateFixedRateBondRequest.daml | 48 +++ .../CreateFloatingRateBondRequest.daml | 50 +++ .../Structuring/CreateFpmlSwapRequest.daml | 39 +++ .../Structuring/CreateGenericRequest.daml | 37 +++ .../CreateInflationLinkedBondRequest.daml | 50 +++ .../Structuring/CreateTokenRequest.daml | 34 +++ .../CreateZeroCouponBondRequest.daml | 37 +++ .../App/Interface/Structuring/Service.daml | 287 ++++++++++++++++++ .../Daml/Finance/App/Lifecycle/Service.daml | 11 +- src/daml/Daml/Finance/App/Role/Custodian.daml | 41 ++- .../Daml/Finance/App/Settlement/Service.daml | 39 +-- .../Daml/Finance/App/Structuring/Auto.daml | 118 +++++++ .../Finance/App/Structuring/Auto/Service.daml | 195 ------------ .../Daml/Finance/App/Structuring/Model.daml | 221 +++++++++++++- .../Daml/Finance/App/Structuring/Service.daml | 283 ++++++----------- src/daml/Daml/Finance/Setup/Util/Service.daml | 24 +- 26 files changed, 1385 insertions(+), 435 deletions(-) create mode 100644 src/daml/Daml/Finance/App/Interface/Settlement/Service.daml create mode 100644 src/daml/Daml/Finance/App/Interface/Structuring/Auto.daml create mode 100644 src/daml/Daml/Finance/App/Interface/Structuring/CreateEquityRequest.daml create mode 100644 src/daml/Daml/Finance/App/Interface/Structuring/CreateFixedRateBondRequest.daml create mode 100644 src/daml/Daml/Finance/App/Interface/Structuring/CreateFloatingRateBondRequest.daml create mode 100644 src/daml/Daml/Finance/App/Interface/Structuring/CreateFpmlSwapRequest.daml create mode 100644 src/daml/Daml/Finance/App/Interface/Structuring/CreateGenericRequest.daml create mode 100644 src/daml/Daml/Finance/App/Interface/Structuring/CreateInflationLinkedBondRequest.daml create mode 100644 src/daml/Daml/Finance/App/Interface/Structuring/CreateTokenRequest.daml create mode 100644 src/daml/Daml/Finance/App/Interface/Structuring/CreateZeroCouponBondRequest.daml create mode 100644 src/daml/Daml/Finance/App/Interface/Structuring/Service.daml create mode 100644 src/daml/Daml/Finance/App/Structuring/Auto.daml delete mode 100644 src/daml/Daml/Finance/App/Structuring/Auto/Service.daml diff --git a/src/daml/Daml/Finance/App/Custody/Model.daml b/src/daml/Daml/Finance/App/Custody/Model.daml index c62b75c2..021ed35b 100644 --- a/src/daml/Daml/Finance/App/Custody/Model.daml +++ b/src/daml/Daml/Finance/App/Custody/Model.daml @@ -5,15 +5,17 @@ module Daml.Finance.App.Custody.Model where import DA.Set (fromList) import Daml.Finance.App.Interface.Common.Removable qualified as Removable (I, View(..)) -import Daml.Finance.App.Interface.Custody.OpenAccountRequest qualified as OpenAccountRequest (I, View(..)) -import Daml.Finance.App.Interface.Custody.CloseAccountRequest qualified as CloseAccountRequest (I, View(..)) -import Daml.Finance.App.Interface.Custody.DepositRequest qualified as DepositRequest (I, View(..)) -import Daml.Finance.App.Interface.Custody.WithdrawRequest qualified as WithdrawRequest (I, View(..)) +import Daml.Finance.App.Interface.Custody.OpenAccountRequest qualified as OpenAccountRequest (HasImplementation, I, View(..)) +import Daml.Finance.App.Interface.Custody.CloseAccountRequest qualified as CloseAccountRequest (HasImplementation, I, View(..)) +import Daml.Finance.App.Interface.Custody.DepositRequest qualified as DepositRequest (HasImplementation, I, View(..)) +import Daml.Finance.App.Interface.Custody.WithdrawRequest qualified as WithdrawRequest (HasImplementation, I, View(..)) import Daml.Finance.Interface.Account.Account qualified as Account (Controllers, K) import Daml.Finance.Interface.Holding.Base qualified as Holding (I) import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (Q) import Daml.Finance.Interface.Types.Common (Id, PartiesMap) +instance OpenAccountRequest.HasImplementation OpenAccountRequest + template OpenAccountRequest with operator : Party @@ -38,8 +40,11 @@ template OpenAccountRequest description controllers observers + asRemovable = toInterface @Removable.I this +instance CloseAccountRequest.HasImplementation CloseAccountRequest + template CloseAccountRequest with operator : Party @@ -58,8 +63,11 @@ template CloseAccountRequest provider customer account + asRemovable = toInterface @Removable.I this +instance DepositRequest.HasImplementation DepositRequest + template DepositRequest with operator : Party @@ -80,8 +88,11 @@ template DepositRequest customer quantity account + asRemovable = toInterface @Removable.I this +instance WithdrawRequest.HasImplementation WithdrawRequest + template WithdrawRequest with operator : Party @@ -100,4 +111,5 @@ template WithdrawRequest provider customer holdingCid + asRemovable = toInterface @Removable.I this diff --git a/src/daml/Daml/Finance/App/Custody/Service.daml b/src/daml/Daml/Finance/App/Custody/Service.daml index c7fee6f9..9d93534e 100644 --- a/src/daml/Daml/Finance/App/Custody/Service.daml +++ b/src/daml/Daml/Finance/App/Custody/Service.daml @@ -39,32 +39,42 @@ template Service interface instance Base.I for Service where view = Base.View with operator; provider; customer + terminate = pure () interface instance Service.I for Service where view = Service.View with claimRuleCid; accountFactoryCid; holdingFactoryCid + asBase = toInterface @Base.I this + requestOpenAccount Service.RequestOpenAccount{id; description; controllers; observers} = do toInterfaceContractId <$> create Model.OpenAccountRequest with operator; provider; customer; id; description; controllers; observers + requestCloseAccount Service.RequestCloseAccount{account} = do toInterfaceContractId <$> create Model.CloseAccountRequest with operator; provider; customer; account + requestDeposit Service.RequestDeposit{quantity; account} = do toInterfaceContractId <$> create Model.DepositRequest with operator; provider; customer; quantity; account + requestWithdraw Service.RequestWithdraw{holdingCid} = do toInterfaceContractId <$> create Model.WithdrawRequest with operator; provider; customer; holdingCid + openAccount Service.OpenAccount{openAccountRequestCid} = do OpenAccountRequest.View{id; description; controllers; observers} <- view <$> fetchAndRemove openAccountRequestCid let account = AccountKey with custodian = provider; owner = customer; id accountCid <- exercise accountFactoryCid Account.Create with account; description; controllers; holdingFactoryCid; observers pure (accountCid, account) + closeAccount Service.CloseAccount{closeAccountRequestCid} = do CloseAccountRequest.View{account} <- view <$> fetchAndRemove closeAccountRequestCid exercise accountFactoryCid Account.Remove with account + deposit Service.Deposit{depositRequestCid} = do DepositRequest.View{quantity; account} <- view <$> fetchAndRemove depositRequestCid account.custodian === provider account.owner === customer Account.exerciseInterfaceByKey @Account.I account provider Account.Credit with quantity + withdraw Service.Withdraw{withdrawRequestCid} = do WithdrawRequest.View{holdingCid} <- view <$> fetchAndRemove withdrawRequestCid holding <- fetch holdingCid diff --git a/src/daml/Daml/Finance/App/Interface/Custody/Auto.daml b/src/daml/Daml/Finance/App/Interface/Custody/Auto.daml index 371adc8a..c016e5cc 100644 --- a/src/daml/Daml/Finance/App/Interface/Custody/Auto.daml +++ b/src/daml/Daml/Finance/App/Interface/Custody/Auto.daml @@ -21,12 +21,16 @@ interface Service where asBase : Base.I -- ^ Conversion to base `Service` interface. + requestAndOpenAccount : RequestAndOpenAccount -> Update (ContractId Account.I, AccountKey) -- ^ Implementation of the `RequestOpenAccount` choice. + requestAndCloseAccount : RequestAndCloseAccount -> Update () -- ^ Implementation of the `RequestCloseAccount` choice. + requestAndDeposit : RequestAndDeposit -> Update (ContractId Holding.I) -- ^ Implementation of the `RequestDeposit` choice. + requestAndWithdraw : RequestAndWithdraw -> Update () -- ^ Implementation of the `RequestAndWithdraw` choice. diff --git a/src/daml/Daml/Finance/App/Interface/Custody/CloseAccountRequest.daml b/src/daml/Daml/Finance/App/Interface/Custody/CloseAccountRequest.daml index 3cadf9fa..907ef18f 100644 --- a/src/daml/Daml/Finance/App/Interface/Custody/CloseAccountRequest.daml +++ b/src/daml/Daml/Finance/App/Interface/Custody/CloseAccountRequest.daml @@ -21,6 +21,7 @@ data View = View interface CloseAccountRequest where viewtype View -- ^ Interface view type. + asRemovable : Removable.I -- ^ Conversion to the `Removable` interface. diff --git a/src/daml/Daml/Finance/App/Interface/Custody/DepositRequest.daml b/src/daml/Daml/Finance/App/Interface/Custody/DepositRequest.daml index 1c46d0f6..414cf02d 100644 --- a/src/daml/Daml/Finance/App/Interface/Custody/DepositRequest.daml +++ b/src/daml/Daml/Finance/App/Interface/Custody/DepositRequest.daml @@ -23,6 +23,7 @@ data View = View interface DepositRequest where viewtype View -- ^ Interface view type. + asRemovable : Removable.I -- ^ Conversion to the `Removable` interface. diff --git a/src/daml/Daml/Finance/App/Interface/Custody/OpenAccountRequest.daml b/src/daml/Daml/Finance/App/Interface/Custody/OpenAccountRequest.daml index 8dcbf28b..e48b4077 100644 --- a/src/daml/Daml/Finance/App/Interface/Custody/OpenAccountRequest.daml +++ b/src/daml/Daml/Finance/App/Interface/Custody/OpenAccountRequest.daml @@ -25,6 +25,7 @@ data View = View interface OpenAccountRequest where viewtype View -- ^ Interface view type. + asRemovable : Removable.I -- ^ Conversion to the `Removable` interface. diff --git a/src/daml/Daml/Finance/App/Interface/Custody/WithdrawRequest.daml b/src/daml/Daml/Finance/App/Interface/Custody/WithdrawRequest.daml index ec5fb83c..89b03565 100644 --- a/src/daml/Daml/Finance/App/Interface/Custody/WithdrawRequest.daml +++ b/src/daml/Daml/Finance/App/Interface/Custody/WithdrawRequest.daml @@ -21,6 +21,7 @@ data View = View interface WithdrawRequest where viewtype View -- ^ Interface view type. + asRemovable : Removable.I -- ^ Conversion to the `Removable` interface. diff --git a/src/daml/Daml/Finance/App/Interface/Settlement/Service.daml b/src/daml/Daml/Finance/App/Interface/Settlement/Service.daml new file mode 100644 index 00000000..749925a8 --- /dev/null +++ b/src/daml/Daml/Finance/App/Interface/Settlement/Service.daml @@ -0,0 +1,51 @@ +-- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +-- SPDX-License-Identifier: Apache-2.0 + +module Daml.Finance.App.Interface.Settlement.Service where + +import Daml.Finance.App.Interface.Base.Service qualified as Base (I, Implementation) +import Daml.Finance.Interface.Settlement.Instruction qualified as Instruction (I) +import Daml.Finance.Interface.Settlement.Types (Allocation, Approval) + +type I = Service + +type V = View + +data View = View {} + deriving (Eq, Show) + +interface Service where + viewtype V + + asBase : Base.I + -- ^ Conversion to base `Service` interface. + + allocateInstruction : AllocateInstruction -> Update (ContractId Instruction.I) + -- ^ Implementation of the `AllocationInstruction` choice. + + approveInstruction : ApproveInstruction -> Update (ContractId Instruction.I) + -- ^ Implementation of the `ApproveInstruction` choice. + + nonconsuming choice AllocateInstruction : ContractId Instruction.I + with + actor : Party + instructionCid : ContractId Instruction.I + allocation : Allocation + controller actor + do + allocateInstruction this arg + + nonconsuming choice ApproveInstruction : ContractId Instruction.I + with + actor : Party + instructionCid : ContractId Instruction.I + approval : Approval + controller actor + do + approveInstruction this arg + +-- | Type constraint for requiring templates to implement `Service`. +type Implementation t = (HasToInterface t Service, Base.Implementation t) +class (Implementation t) => HasImplementation t +instance HasImplementation Service +instance HasToInterface Service Base.I where _toInterface = asBase diff --git a/src/daml/Daml/Finance/App/Interface/Structuring/Auto.daml b/src/daml/Daml/Finance/App/Interface/Structuring/Auto.daml new file mode 100644 index 00000000..3e3f6ec9 --- /dev/null +++ b/src/daml/Daml/Finance/App/Interface/Structuring/Auto.daml @@ -0,0 +1,182 @@ +-- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +-- SPDX-License-Identifier: Apache-2.0 + +module Daml.Finance.App.Interface.Structuring.Auto where + +import Daml.Finance.App.Interface.Base.Service qualified as Base (I) +import Daml.Finance.Interface.Claims.Types (C) +import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (I) +import Daml.Finance.Interface.Instrument.Swap.Fpml.FpmlTypes (SwapStream) +import Daml.Finance.Interface.Types.Common (Id, InstrumentKey, PartiesMap) +import Daml.Finance.Interface.Types.Date.Calendar (BusinessDayConventionEnum) +import Daml.Finance.Interface.Types.Date.DayCount (DayCountConventionEnum) +import Daml.Finance.Interface.Types.Date.RollConvention (PeriodEnum) + +type I = Service + +type V = View + +data View = View {} + deriving (Eq, Show) + +interface Service where + viewtype V + + asBase : Base.I + -- ^ Conversion to base `Service` interface. + + requestAndCreateToken : RequestAndCreateToken -> Update (ContractId Instrument.I) + -- ^ Implementation of the `RequestCreateFpmlSwapBond` choice. + + requestAndCreateEquity : RequestAndCreateEquity -> Update (ContractId Instrument.I) + -- ^ Implementation of the `RequestCreateFpmlSwapBond` choice. + + requestAndCreateGeneric : RequestAndCreateGeneric -> Update (ContractId Instrument.I) + -- ^ Implementation of the `RequestCreateFpmlSwapBond` choice. + + requestAndCreateFixedRateBond : RequestAndCreateFixedRateBond -> Update (ContractId Instrument.I) + -- ^ Implementation of the `RequestCreateFpmlSwapBond` choice. + + requestAndCreateFloatingRateBond : RequestAndCreateFloatingRateBond -> Update (ContractId Instrument.I) + -- ^ Implementation of the `RequestCreateFpmlSwapBond` choice. + + requestAndCreateInflationLinkedBond : RequestAndCreateInflationLinkedBond -> Update (ContractId Instrument.I) + -- ^ Implementation of the `RequestCreateFpmlSwapBond` choice. + + requestAndCreateZeroCouponBond : RequestAndCreateZeroCouponBond -> Update (ContractId Instrument.I) + -- ^ Implementation of the `RequestCreateFpmlSwapBond` choice. + + requestAndCreateFpmlSwap : RequestAndCreateFpmlSwap -> Update (ContractId Instrument.I) + -- ^ Implementation of the `RequestCreateFpmlSwapBond` choice. + + nonconsuming choice RequestAndCreateToken : ContractId Instrument.I + with + id : Id + description : Text + validAsOf : Time + observers : PartiesMap + controller (view $ asBase this).provider + do + requestAndCreateToken this arg + + nonconsuming choice RequestAndCreateEquity : ContractId Instrument.I + with + id : Id + description : Text + version : Text + validAsOf : Time + observers : PartiesMap + controller (view $ asBase this).provider + do + requestAndCreateEquity this arg + + nonconsuming choice RequestAndCreateGeneric : ContractId Instrument.I + with + id : Id + description : Text + claims : C + acquisitionTime : Time + lastEventTimestamp : Time + observers : PartiesMap + controller (view $ asBase this).provider + do + requestAndCreateGeneric this arg + + nonconsuming choice RequestAndCreateFixedRateBond : ContractId Instrument.I + with + id : Id + description : Text + couponRate : Decimal + issueDate : Date + firstCouponDate : Date + maturityDate : Date + holidayCalendarIds : [Text] + calendarDataProvider : Party + dayCountConvention : DayCountConventionEnum + businessDayConvention : BusinessDayConventionEnum + couponPeriod : PeriodEnum + couponPeriodMultiplier : Int + currency : InstrumentKey + observers : PartiesMap + lastEventTimestamp : Time + controller (view $ asBase this).provider + do + requestAndCreateFixedRateBond this arg + + nonconsuming choice RequestAndCreateFloatingRateBond : ContractId Instrument.I + with + id : Id + description : Text + referenceRateId : Text + couponSpread : Decimal + issueDate : Date + firstCouponDate : Date + maturityDate : Date + holidayCalendarIds : [Text] + calendarDataProvider : Party + dayCountConvention : DayCountConventionEnum + businessDayConvention : BusinessDayConventionEnum + couponPeriod : PeriodEnum + couponPeriodMultiplier : Int + currency : InstrumentKey + observers : PartiesMap + lastEventTimestamp : Time + controller (view $ asBase this).provider + do + requestAndCreateFloatingRateBond this arg + + nonconsuming choice RequestAndCreateInflationLinkedBond : ContractId Instrument.I + with + id : Id + description : Text + inflationIndexId : Text + inflationIndexBaseValue : Decimal + couponRate : Decimal + issueDate : Date + firstCouponDate : Date + maturityDate : Date + holidayCalendarIds : [Text] + calendarDataProvider : Party + dayCountConvention : DayCountConventionEnum + businessDayConvention : BusinessDayConventionEnum + couponPeriod : PeriodEnum + couponPeriodMultiplier : Int + currency : InstrumentKey + observers : PartiesMap + lastEventTimestamp : Time + controller (view $ asBase this).provider + do + requestAndCreateInflationLinkedBond this arg + + nonconsuming choice RequestAndCreateZeroCouponBond : ContractId Instrument.I + with + id : Id + description : Text + issueDate : Date + maturityDate : Date + currency : InstrumentKey + observers : PartiesMap + lastEventTimestamp : Time + controller (view $ asBase this).provider + do + requestAndCreateZeroCouponBond this arg + + nonconsuming choice RequestAndCreateFpmlSwap : ContractId Instrument.I + with + id : Id + description : Text + swapStreams : [SwapStream] + issuerPartyRef : Text + calendarDataProvider : Party + currencies : [InstrumentKey] + observers : PartiesMap + lastEventTimestamp : Time + controller (view $ asBase this).provider + do + requestAndCreateFpmlSwap this arg + +-- | Type constraint for requiring templates to implement `Service`. +type Implementation t = HasToInterface t Service +class (Implementation t) => HasImplementation t +instance HasImplementation Service +instance HasToInterface Service Base.I where _toInterface = asBase diff --git a/src/daml/Daml/Finance/App/Interface/Structuring/CreateEquityRequest.daml b/src/daml/Daml/Finance/App/Interface/Structuring/CreateEquityRequest.daml new file mode 100644 index 00000000..39df87ae --- /dev/null +++ b/src/daml/Daml/Finance/App/Interface/Structuring/CreateEquityRequest.daml @@ -0,0 +1,35 @@ +-- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +-- SPDX-License-Identifier: Apache-2.0 + +module Daml.Finance.App.Interface.Structuring.CreateEquityRequest where + +import Daml.Finance.App.Interface.Common.Removable qualified as Removable (I, Implementation) +import Daml.Finance.Interface.Types.Common (Id, PartiesMap) + +type I = CreateEquityRequest + +type V = View + +data View = View + with + operator : Party + provider : Party + customer : Party + id : Id + description : Text + version : Text + observers : PartiesMap + validAsOf : Time + deriving (Eq, Show) + +interface CreateEquityRequest where + viewtype View + -- ^ Interface view type. + asRemovable : Removable.I + -- ^ Conversion to the `Removable` interface. + +-- | Type constraint for requiring templates to implement `CreateEquityRequest`. +type Implementation t = (HasToInterface t CreateEquityRequest, Removable.Implementation t) +class (Implementation t) => HasImplementation t +instance HasImplementation CreateEquityRequest +instance HasToInterface CreateEquityRequest Removable.I where _toInterface = asRemovable diff --git a/src/daml/Daml/Finance/App/Interface/Structuring/CreateFixedRateBondRequest.daml b/src/daml/Daml/Finance/App/Interface/Structuring/CreateFixedRateBondRequest.daml new file mode 100644 index 00000000..64741660 --- /dev/null +++ b/src/daml/Daml/Finance/App/Interface/Structuring/CreateFixedRateBondRequest.daml @@ -0,0 +1,48 @@ +-- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +-- SPDX-License-Identifier: Apache-2.0 + +module Daml.Finance.App.Interface.Structuring.CreateFixedRateBondRequest where + +import Daml.Finance.App.Interface.Common.Removable qualified as Removable (I, Implementation) +import Daml.Finance.Interface.Types.Common (Id, InstrumentKey, PartiesMap) +import Daml.Finance.Interface.Types.Date.Calendar (BusinessDayConventionEnum) +import Daml.Finance.Interface.Types.Date.DayCount (DayCountConventionEnum) +import Daml.Finance.Interface.Types.Date.RollConvention (PeriodEnum) + +type I = CreateFixedRateBondRequest + +type V = View + +data View = View + with + operator : Party + provider : Party + customer : Party + id : Id + description : Text + couponRate : Decimal + issueDate : Date + firstCouponDate : Date + maturityDate : Date + holidayCalendarIds : [Text] + calendarDataProvider : Party + dayCountConvention : DayCountConventionEnum + businessDayConvention : BusinessDayConventionEnum + couponPeriod : PeriodEnum + couponPeriodMultiplier : Int + currency : InstrumentKey + observers : PartiesMap + lastEventTimestamp : Time + deriving (Eq, Show) + +interface CreateFixedRateBondRequest where + viewtype View + -- ^ Interface view type. + asRemovable : Removable.I + -- ^ Conversion to the `Removable` interface. + +-- | Type constraint for requiring templates to implement `CreateFixedRateBondRequest`. +type Implementation t = (HasToInterface t CreateFixedRateBondRequest, Removable.Implementation t) +class (Implementation t) => HasImplementation t +instance HasImplementation CreateFixedRateBondRequest +instance HasToInterface CreateFixedRateBondRequest Removable.I where _toInterface = asRemovable diff --git a/src/daml/Daml/Finance/App/Interface/Structuring/CreateFloatingRateBondRequest.daml b/src/daml/Daml/Finance/App/Interface/Structuring/CreateFloatingRateBondRequest.daml new file mode 100644 index 00000000..6e5b9784 --- /dev/null +++ b/src/daml/Daml/Finance/App/Interface/Structuring/CreateFloatingRateBondRequest.daml @@ -0,0 +1,50 @@ +-- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +-- SPDX-License-Identifier: Apache-2.0 + +module Daml.Finance.App.Interface.Structuring.CreateFloatingRateBondRequest where + +import Daml.Finance.App.Interface.Common.Removable qualified as Removable (I, Implementation) +import Daml.Finance.Interface.Types.Common (Id, InstrumentKey, PartiesMap) +import Daml.Finance.Interface.Types.Date.Calendar (BusinessDayConventionEnum) +import Daml.Finance.Interface.Types.Date.DayCount (DayCountConventionEnum) +import Daml.Finance.Interface.Types.Date.RollConvention (PeriodEnum) + +type I = CreateFloatingRateBondRequest + +type V = View + +data View = View + with + operator : Party + provider : Party + customer : Party + id : Id + description : Text + referenceRateId : Text + couponSpread : Decimal + issueDate : Date + firstCouponDate : Date + maturityDate : Date + holidayCalendarIds : [Text] + calendarDataProvider : Party + dayCountConvention : DayCountConventionEnum + businessDayConvention : BusinessDayConventionEnum + couponPeriod : PeriodEnum + couponPeriodMultiplier : Int + currency : InstrumentKey + observers : PartiesMap + lastEventTimestamp : Time + deriving (Eq, Show) + +interface CreateFloatingRateBondRequest where + viewtype View + -- ^ Interface view type. + + asRemovable : Removable.I + -- ^ Conversion to the `Removable` interface. + +-- | Type constraint for requiring templates to implement `CreateFloatingRateBondRequest`. +type Implementation t = (HasToInterface t CreateFloatingRateBondRequest, Removable.Implementation t) +class (Implementation t) => HasImplementation t +instance HasImplementation CreateFloatingRateBondRequest +instance HasToInterface CreateFloatingRateBondRequest Removable.I where _toInterface = asRemovable diff --git a/src/daml/Daml/Finance/App/Interface/Structuring/CreateFpmlSwapRequest.daml b/src/daml/Daml/Finance/App/Interface/Structuring/CreateFpmlSwapRequest.daml new file mode 100644 index 00000000..111a6014 --- /dev/null +++ b/src/daml/Daml/Finance/App/Interface/Structuring/CreateFpmlSwapRequest.daml @@ -0,0 +1,39 @@ +-- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +-- SPDX-License-Identifier: Apache-2.0 + +module Daml.Finance.App.Interface.Structuring.CreateFpmlSwapRequest where + +import Daml.Finance.App.Interface.Common.Removable qualified as Removable (I, Implementation) +import Daml.Finance.Interface.Instrument.Swap.Fpml.FpmlTypes (SwapStream) +import Daml.Finance.Interface.Types.Common (Id, InstrumentKey, PartiesMap) + +type I = CreateFpmlSwapRequest + +type V = View + +data View = View + with + operator : Party + provider : Party + customer : Party + id : Id + description : Text + swapStreams : [SwapStream] + issuerPartyRef : Text + calendarDataProvider : Party + currencies : [InstrumentKey] + observers : PartiesMap + lastEventTimestamp : Time + deriving (Eq, Show) + +interface CreateFpmlSwapRequest where + viewtype View + -- ^ Interface view type. + asRemovable : Removable.I + -- ^ Conversion to the `Removable` interface. + +-- | Type constraint for requiring templates to implement `CreateFpmlSwapRequest`. +type Implementation t = (HasToInterface t CreateFpmlSwapRequest, Removable.Implementation t) +class (Implementation t) => HasImplementation t +instance HasImplementation CreateFpmlSwapRequest +instance HasToInterface CreateFpmlSwapRequest Removable.I where _toInterface = asRemovable diff --git a/src/daml/Daml/Finance/App/Interface/Structuring/CreateGenericRequest.daml b/src/daml/Daml/Finance/App/Interface/Structuring/CreateGenericRequest.daml new file mode 100644 index 00000000..343f97c5 --- /dev/null +++ b/src/daml/Daml/Finance/App/Interface/Structuring/CreateGenericRequest.daml @@ -0,0 +1,37 @@ +-- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +-- SPDX-License-Identifier: Apache-2.0 + +module Daml.Finance.App.Interface.Structuring.CreateGenericRequest where + +import Daml.Finance.App.Interface.Common.Removable qualified as Removable (I, Implementation) +import Daml.Finance.Interface.Claims.Types (C) +import Daml.Finance.Interface.Types.Common (Id, PartiesMap) + +type I = CreateGenericRequest + +type V = View + +data View = View + with + operator : Party + provider : Party + customer : Party + id : Id + description : Text + claims : C + acquisitionTime : Time + observers : PartiesMap + lastEventTimestamp : Time + deriving (Eq, Show) + +interface CreateGenericRequest where + viewtype View + -- ^ Interface view type. + asRemovable : Removable.I + -- ^ Conversion to the `Removable` interface. + +-- | Type constraint for requiring templates to implement `CreateGenericRequest`. +type Implementation t = (HasToInterface t CreateGenericRequest, Removable.Implementation t) +class (Implementation t) => HasImplementation t +instance HasImplementation CreateGenericRequest +instance HasToInterface CreateGenericRequest Removable.I where _toInterface = asRemovable diff --git a/src/daml/Daml/Finance/App/Interface/Structuring/CreateInflationLinkedBondRequest.daml b/src/daml/Daml/Finance/App/Interface/Structuring/CreateInflationLinkedBondRequest.daml new file mode 100644 index 00000000..2b85b51b --- /dev/null +++ b/src/daml/Daml/Finance/App/Interface/Structuring/CreateInflationLinkedBondRequest.daml @@ -0,0 +1,50 @@ +-- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +-- SPDX-License-Identifier: Apache-2.0 + +module Daml.Finance.App.Interface.Structuring.CreateInflationLinkedBondRequest where + +import Daml.Finance.App.Interface.Common.Removable qualified as Removable (I, Implementation) +import Daml.Finance.Interface.Types.Common (Id, InstrumentKey, PartiesMap) +import Daml.Finance.Interface.Types.Date.Calendar (BusinessDayConventionEnum) +import Daml.Finance.Interface.Types.Date.DayCount (DayCountConventionEnum) +import Daml.Finance.Interface.Types.Date.RollConvention (PeriodEnum) + +type I = CreateInflationLinkedBondRequest + +type V = View + +data View = View + with + operator : Party + provider : Party + customer : Party + id : Id + description : Text + inflationIndexId : Text + inflationIndexBaseValue : Decimal + couponRate : Decimal + issueDate : Date + firstCouponDate : Date + maturityDate : Date + holidayCalendarIds : [Text] + calendarDataProvider : Party + dayCountConvention : DayCountConventionEnum + businessDayConvention : BusinessDayConventionEnum + couponPeriod : PeriodEnum + couponPeriodMultiplier : Int + currency : InstrumentKey + observers : PartiesMap + lastEventTimestamp : Time + deriving (Eq, Show) + +interface CreateInflationLinkedBondRequest where + viewtype View + -- ^ Interface view type. + asRemovable : Removable.I + -- ^ Conversion to the `Removable` interface. + +-- | Type constraint for requiring templates to implement `CreateInflationLinkedBondRequest`. +type Implementation t = (HasToInterface t CreateInflationLinkedBondRequest, Removable.Implementation t) +class (Implementation t) => HasImplementation t +instance HasImplementation CreateInflationLinkedBondRequest +instance HasToInterface CreateInflationLinkedBondRequest Removable.I where _toInterface = asRemovable diff --git a/src/daml/Daml/Finance/App/Interface/Structuring/CreateTokenRequest.daml b/src/daml/Daml/Finance/App/Interface/Structuring/CreateTokenRequest.daml new file mode 100644 index 00000000..4a80d330 --- /dev/null +++ b/src/daml/Daml/Finance/App/Interface/Structuring/CreateTokenRequest.daml @@ -0,0 +1,34 @@ +-- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +-- SPDX-License-Identifier: Apache-2.0 + +module Daml.Finance.App.Interface.Structuring.CreateTokenRequest where + +import Daml.Finance.App.Interface.Common.Removable qualified as Removable (I, Implementation) +import Daml.Finance.Interface.Types.Common (Id, PartiesMap) + +type I = CreateTokenRequest + +type V = View + +data View = View + with + operator : Party + provider : Party + customer : Party + id : Id + description : Text + observers : PartiesMap + validAsOf : Time + deriving (Eq, Show) + +interface CreateTokenRequest where + viewtype View + -- ^ Interface view type. + asRemovable : Removable.I + -- ^ Conversion to the `Removable` interface. + +-- | Type constraint for requiring templates to implement `CreateTokenRequest`. +type Implementation t = (HasToInterface t CreateTokenRequest, Removable.Implementation t) +class (Implementation t) => HasImplementation t +instance HasImplementation CreateTokenRequest +instance HasToInterface CreateTokenRequest Removable.I where _toInterface = asRemovable diff --git a/src/daml/Daml/Finance/App/Interface/Structuring/CreateZeroCouponBondRequest.daml b/src/daml/Daml/Finance/App/Interface/Structuring/CreateZeroCouponBondRequest.daml new file mode 100644 index 00000000..db5d0496 --- /dev/null +++ b/src/daml/Daml/Finance/App/Interface/Structuring/CreateZeroCouponBondRequest.daml @@ -0,0 +1,37 @@ +-- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +-- SPDX-License-Identifier: Apache-2.0 + +module Daml.Finance.App.Interface.Structuring.CreateZeroCouponBondRequest where + +import Daml.Finance.App.Interface.Common.Removable qualified as Removable (I, Implementation) +import Daml.Finance.Interface.Types.Common (Id, InstrumentKey, PartiesMap) + +type I = CreateZeroCouponBondRequest + +type V = View + +data View = View + with + operator : Party + provider : Party + customer : Party + id : Id + description : Text + issueDate : Date + maturityDate : Date + currency : InstrumentKey + observers : PartiesMap + lastEventTimestamp : Time + deriving (Eq, Show) + +interface CreateZeroCouponBondRequest where + viewtype View + -- ^ Interface view type. + asRemovable : Removable.I + -- ^ Conversion to the `Removable` interface. + +-- | Type constraint for requiring templates to implement `CreateZeroCouponBondRequest`. +type Implementation t = (HasToInterface t CreateZeroCouponBondRequest, Removable.Implementation t) +class (Implementation t) => HasImplementation t +instance HasImplementation CreateZeroCouponBondRequest +instance HasToInterface CreateZeroCouponBondRequest Removable.I where _toInterface = asRemovable diff --git a/src/daml/Daml/Finance/App/Interface/Structuring/Service.daml b/src/daml/Daml/Finance/App/Interface/Structuring/Service.daml new file mode 100644 index 00000000..9438cbd5 --- /dev/null +++ b/src/daml/Daml/Finance/App/Interface/Structuring/Service.daml @@ -0,0 +1,287 @@ +-- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +-- SPDX-License-Identifier: Apache-2.0 + +module Daml.Finance.App.Interface.Structuring.Service where + +import Daml.Finance.App.Interface.Base.Service qualified as Base (I, Implementation) +import Daml.Finance.App.Interface.Structuring.CreateTokenRequest qualified as CreateTokenRequest (I) +import Daml.Finance.App.Interface.Structuring.CreateEquityRequest qualified as CreateEquityRequest (I) +import Daml.Finance.App.Interface.Structuring.CreateGenericRequest qualified as CreateGenericRequest (I) +import Daml.Finance.App.Interface.Structuring.CreateFixedRateBondRequest qualified as CreateFixedRateBondRequest (I) +import Daml.Finance.App.Interface.Structuring.CreateFloatingRateBondRequest qualified as CreateFloatingRateBondRequest (I) +import Daml.Finance.App.Interface.Structuring.CreateInflationLinkedBondRequest qualified as CreateInflationLinkedBondRequest (I) +import Daml.Finance.App.Interface.Structuring.CreateZeroCouponBondRequest qualified as CreateZeroCouponBondRequest (I) +import Daml.Finance.App.Interface.Structuring.CreateFpmlSwapRequest qualified as CreateFpmlSwapRequest (I) +import Daml.Finance.Interface.Claims.Types (C) +import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (I) +import Daml.Finance.Interface.Instrument.Bond.FixedRate.Factory qualified as FixedRateBond (Factory) +import Daml.Finance.Interface.Instrument.Bond.FloatingRate.Factory qualified as FloatingRateBond (Factory) +import Daml.Finance.Interface.Instrument.Bond.InflationLinked.Factory qualified as InflationLinkedBond (Factory) +import Daml.Finance.Interface.Instrument.Bond.ZeroCoupon.Factory qualified as ZeroCouponBond (Factory) +import Daml.Finance.Interface.Instrument.Equity.Factory qualified as Equity (Factory) +import Daml.Finance.Interface.Instrument.Generic.Factory qualified as Generic (Factory) +import Daml.Finance.Interface.Instrument.Swap.Fpml.Factory qualified as FpmlSwap (Factory) +import Daml.Finance.Interface.Instrument.Swap.Fpml.FpmlTypes (SwapStream) +import Daml.Finance.Interface.Instrument.Token.Factory qualified as Token (Factory) +import Daml.Finance.Interface.Types.Common (Id, InstrumentKey, PartiesMap) +import Daml.Finance.Interface.Types.Date.Calendar (BusinessDayConventionEnum) +import Daml.Finance.Interface.Types.Date.DayCount (DayCountConventionEnum) +import Daml.Finance.Interface.Types.Date.RollConvention (PeriodEnum) + +type I = Service + +type V = View + +data View = View + with + token : ContractId Token.Factory + equity : ContractId Equity.Factory + generic : ContractId Generic.Factory + fixedRateBond : ContractId FixedRateBond.Factory + floatingRateBond : ContractId FloatingRateBond.Factory + inflationLinkedBond : ContractId InflationLinkedBond.Factory + zeroCouponBond : ContractId ZeroCouponBond.Factory + fpmlSwap : ContractId FpmlSwap.Factory + deriving (Eq, Show) + +interface Service where + viewtype V + + asBase : Base.I + -- ^ Conversion to base `Service` interface. + + requestCreateToken : RequestCreateToken -> Update (ContractId CreateTokenRequest.I) + -- ^ Implementation of the `RequestCreateToken` choice. + + requestCreateEquity : RequestCreateEquity -> Update (ContractId CreateEquityRequest.I) + -- ^ Implementation of the `RequestCreateEquity` choice. + + requestCreateGeneric : RequestCreateGeneric -> Update (ContractId CreateGenericRequest.I) + -- ^ Implementation of the `RequestCreateGeneric` choice. + + requestCreateFixedRateBond : RequestCreateFixedRateBond -> Update (ContractId CreateFixedRateBondRequest.I) + -- ^ Implementation of the `RequestCreateFixedRateBond` choice. + + requestCreateFloatingRateBond : RequestCreateFloatingRateBond -> Update (ContractId CreateFloatingRateBondRequest.I) + -- ^ Implementation of the `RequestCreateFloatingRateBond` choice. + + requestCreateInflationLinkedBond : RequestCreateInflationLinkedBond -> Update (ContractId CreateInflationLinkedBondRequest.I) + -- ^ Implementation of the `RequestCreateInflationLinkedBond` choice. + + requestCreateZeroCouponBond : RequestCreateZeroCouponBond -> Update (ContractId CreateZeroCouponBondRequest.I) + -- ^ Implementation of the `RequestCreateZeroCouponBond` choice. + + requestCreateFpmlSwap : RequestCreateFpmlSwap -> Update (ContractId CreateFpmlSwapRequest.I) + -- ^ Implementation of the `RequestCreateFpmlSwap` choice. + + createToken : CreateToken -> Update (ContractId Instrument.I) + -- ^ Implementation of the `RequestCreateFpmlSwapBond` choice. + + createEquity : CreateEquity -> Update (ContractId Instrument.I) + -- ^ Implementation of the `RequestCreateFpmlSwapBond` choice. + + createGeneric : CreateGeneric -> Update (ContractId Instrument.I) + -- ^ Implementation of the `RequestCreateFpmlSwapBond` choice. + + createFixedRateBond : CreateFixedRateBond -> Update (ContractId Instrument.I) + -- ^ Implementation of the `RequestCreateFpmlSwapBond` choice. + + createFloatingRateBond : CreateFloatingRateBond -> Update (ContractId Instrument.I) + -- ^ Implementation of the `RequestCreateFpmlSwapBond` choice. + + createInflationLinkedBond : CreateInflationLinkedBond -> Update (ContractId Instrument.I) + -- ^ Implementation of the `RequestCreateFpmlSwapBond` choice. + + createZeroCouponBond : CreateZeroCouponBond -> Update (ContractId Instrument.I) + -- ^ Implementation of the `RequestCreateFpmlSwapBond` choice. + + createFpmlSwap : CreateFpmlSwap -> Update (ContractId Instrument.I) + -- ^ Implementation of the `RequestCreateFpmlSwapBond` choice. + + nonconsuming choice RequestCreateToken : ContractId CreateTokenRequest.I + with + id : Id + description : Text + validAsOf : Time + observers : PartiesMap + controller (view $ asBase this).customer + do + requestCreateToken this arg + + nonconsuming choice RequestCreateEquity : ContractId CreateEquityRequest.I + with + id : Id + description : Text + version : Text + validAsOf : Time + observers : PartiesMap + controller (view $ asBase this).customer + do + requestCreateEquity this arg + + nonconsuming choice RequestCreateGeneric : ContractId CreateGenericRequest.I + with + id : Id + description : Text + claims : C + acquisitionTime : Time + lastEventTimestamp : Time + observers : PartiesMap + controller (view $ asBase this).customer + do + requestCreateGeneric this arg + + nonconsuming choice RequestCreateFixedRateBond : ContractId CreateFixedRateBondRequest.I + with + id : Id + description : Text + couponRate : Decimal + issueDate : Date + firstCouponDate : Date + maturityDate : Date + holidayCalendarIds : [Text] + calendarDataProvider : Party + dayCountConvention : DayCountConventionEnum + businessDayConvention : BusinessDayConventionEnum + couponPeriod : PeriodEnum + couponPeriodMultiplier : Int + currency : InstrumentKey + observers : PartiesMap + lastEventTimestamp : Time + controller (view $ asBase this).customer + do + requestCreateFixedRateBond this arg + + nonconsuming choice RequestCreateFloatingRateBond : ContractId CreateFloatingRateBondRequest.I + with + id : Id + description : Text + referenceRateId : Text + couponSpread : Decimal + issueDate : Date + firstCouponDate : Date + maturityDate : Date + holidayCalendarIds : [Text] + calendarDataProvider : Party + dayCountConvention : DayCountConventionEnum + businessDayConvention : BusinessDayConventionEnum + couponPeriod : PeriodEnum + couponPeriodMultiplier : Int + currency : InstrumentKey + observers : PartiesMap + lastEventTimestamp : Time + controller (view $ asBase this).customer + do + requestCreateFloatingRateBond this arg + + nonconsuming choice RequestCreateInflationLinkedBond : ContractId CreateInflationLinkedBondRequest.I + with + id : Id + description : Text + inflationIndexId : Text + inflationIndexBaseValue : Decimal + couponRate : Decimal + issueDate : Date + firstCouponDate : Date + maturityDate : Date + holidayCalendarIds : [Text] + calendarDataProvider : Party + dayCountConvention : DayCountConventionEnum + businessDayConvention : BusinessDayConventionEnum + couponPeriod : PeriodEnum + couponPeriodMultiplier : Int + currency : InstrumentKey + observers : PartiesMap + lastEventTimestamp : Time + controller (view $ asBase this).customer + do + requestCreateInflationLinkedBond this arg + + nonconsuming choice RequestCreateZeroCouponBond : ContractId CreateZeroCouponBondRequest.I + with + id : Id + description : Text + issueDate : Date + maturityDate : Date + currency : InstrumentKey + observers : PartiesMap + lastEventTimestamp : Time + controller (view $ asBase this).customer + do + requestCreateZeroCouponBond this arg + + nonconsuming choice RequestCreateFpmlSwap : ContractId CreateFpmlSwapRequest.I + with + id : Id + description : Text + swapStreams : [SwapStream] + issuerPartyRef : Text + calendarDataProvider : Party + currencies : [InstrumentKey] + observers : PartiesMap + lastEventTimestamp : Time + controller (view $ asBase this).customer + do + requestCreateFpmlSwap this arg + + nonconsuming choice CreateToken : ContractId Instrument.I + with + createTokenRequestCid : ContractId CreateTokenRequest.I + controller (view $ asBase this).provider + do + createToken this arg + + nonconsuming choice CreateEquity : ContractId Instrument.I + with + createEquityRequestCid : ContractId CreateEquityRequest.I + controller (view $ asBase this).provider + do + createEquity this arg + + nonconsuming choice CreateGeneric : ContractId Instrument.I + with + createGenericRequestCid : ContractId CreateGenericRequest.I + controller (view $ asBase this).provider + do + createGeneric this arg + + nonconsuming choice CreateFixedRateBond : ContractId Instrument.I + with + createFixedRateBondRequestCid : ContractId CreateFixedRateBondRequest.I + controller (view $ asBase this).provider + do + createFixedRateBond this arg + + nonconsuming choice CreateFloatingRateBond : ContractId Instrument.I + with + createFloatingRateBondRequestCid : ContractId CreateFloatingRateBondRequest.I + controller (view $ asBase this).provider + do + createFloatingRateBond this arg + + nonconsuming choice CreateInflationLinkedBond : ContractId Instrument.I + with + createInflationLinkedBondRequestCid : ContractId CreateInflationLinkedBondRequest.I + controller (view $ asBase this).provider + do + createInflationLinkedBond this arg + + nonconsuming choice CreateZeroCouponBond : ContractId Instrument.I + with + createZeroCouponBondRequestCid : ContractId CreateZeroCouponBondRequest.I + controller (view $ asBase this).provider + do + createZeroCouponBond this arg + + nonconsuming choice CreateFpmlSwap : ContractId Instrument.I + with + createFpmlSwapRequestCid : ContractId CreateFpmlSwapRequest.I + controller (view $ asBase this).provider + do + createFpmlSwap this arg + +-- | Type constraint for requiring templates to implement `Service`. +type Implementation t = (HasToInterface t Service, Base.Implementation t) +class (Implementation t) => HasImplementation t +instance HasImplementation Service +instance HasToInterface Service Base.I where _toInterface = asBase diff --git a/src/daml/Daml/Finance/App/Lifecycle/Service.daml b/src/daml/Daml/Finance/App/Lifecycle/Service.daml index 3ac11883..227d1936 100644 --- a/src/daml/Daml/Finance/App/Lifecycle/Service.daml +++ b/src/daml/Daml/Finance/App/Lifecycle/Service.daml @@ -7,9 +7,10 @@ import ContingentClaims.Core.Observation (Observation(..)) import ContingentClaims.Lifecycle.Lifecycle qualified as Lifecycle import ContingentClaims.Lifecycle.Util qualified as Util (expiry, fixings, payoffs) import Daml.Finance.App.Interface.Base.Service qualified as Base (I, View(..)) -import Daml.Finance.App.Interface.Lifecycle.Service qualified as Service (DeclareDividend(..), DeclareReplacement(..), DeclareStockSplit(..), Expiry(..), Fixings(..), GetCurrentClaims(..), HasImplementation, I, Lifecycle(..), Multipliers(..), Payoffs(..), PreviewLifecycle(..), PreviewPricing(..), SimulateLifecycle(..), Underlyings(..), View(..)) +import Daml.Finance.App.Interface.Lifecycle.Service qualified as Service +import Daml.Finance.App.Interface.Structuring.Auto qualified as Structuring (I, RequestAndCreateEquity(..)) import Daml.Finance.App.Lifecycle.Pricing qualified as Pricing -import Daml.Finance.App.Structuring.Auto.Service qualified as Structuring +import Daml.Finance.App.Structuring.Auto qualified as Structuring (T) import Daml.Finance.Claims.Util.Lifecycle qualified as Claim (lifecycle, lifecycleClaims, timeEvent) import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (I, R) import Daml.Finance.Interface.Instrument.Equity.Instrument qualified as Equity (I, DeclareDividend(..), DeclareReplacement(..), DeclareStockSplit(..)) @@ -54,7 +55,8 @@ template Service v = view equity dv = view disclosure newInstrument = InstrumentKey with depository = provider; issuer = customer; id = v.id; version = newVersion - exerciseByKey @Structuring.Service (operator, provider, customer) Structuring.RequestAndCreateEquity with id = v.id; description = v.description; version = newVersion; validAsOf = now; observers = dv.observers + serviceCid <- toInterfaceContractId @Structuring.I . fst <$> fetchByKey @Structuring.T (operator, provider, customer) + exercise serviceCid Structuring.RequestAndCreateEquity with id = v.id; description = v.description; version = newVersion; validAsOf = now; observers = dv.observers eventCid <- exercise (coerceContractId equityRef.cid : ContractId Equity.I) Equity.DeclareDividend with id; description; effectiveDate; newInstrument; perUnitDistribution snd <$> exercise distributionRuleCid Lifecycle.Evolve with ruleName = "Dividend"; eventCid; timeObservableCid; observableCids = [] @@ -72,7 +74,8 @@ template Service v = view equity dv = view disclosure newInstrument = InstrumentKey with depository = provider; issuer = customer; id = v.id; version = newVersion - exerciseByKey @Structuring.Service (operator, provider, customer) Structuring.RequestAndCreateEquity with id = v.id; description = v.description; version = newVersion; validAsOf = now; observers = dv.observers + serviceCid <- toInterfaceContractId @Structuring.I . fst <$> fetchByKey @Structuring.T (operator, provider, customer) + exercise serviceCid Structuring.RequestAndCreateEquity with id = v.id; description = v.description; version = newVersion; validAsOf = now; observers = dv.observers eventCid <- exercise (coerceContractId equityRef.cid : ContractId Equity.I) Equity.DeclareStockSplit with id; description; effectiveDate; newInstrument; adjustmentFactor snd <$> exercise replacementRuleCid Lifecycle.Evolve with ruleName = "StockSplit"; eventCid; timeObservableCid; observableCids = [] diff --git a/src/daml/Daml/Finance/App/Role/Custodian.daml b/src/daml/Daml/Finance/App/Role/Custodian.daml index 415f77ab..d8e6df3d 100644 --- a/src/daml/Daml/Finance/App/Role/Custodian.daml +++ b/src/daml/Daml/Finance/App/Role/Custodian.daml @@ -11,11 +11,19 @@ import Daml.Finance.App.Issuance.BackToBack qualified as BackToBack (Approve(..) import Daml.Finance.App.Issuance.Service qualified as Issuance (Approve(..), Offer(..), Request, Service) import Daml.Finance.App.Lending.Service qualified as Lending (Approve(..), Offer(..), Request, Service) import Daml.Finance.App.Lifecycle.Service qualified as Lifecycle (Approve(..), Offer(..), Request, Service) -import Daml.Finance.App.Settlement.Service qualified as Settlement (Approve(..), Offer(..), Request, Service, Terminate(..)) -import Daml.Finance.App.Structuring.Auto.Service qualified as StructuringAuto (Approve(..), Offer(..), Request, Service, Terminate(..)) -import Daml.Finance.App.Structuring.Service qualified as Structuring (Approve(..), Factories, Offer(..), Request, Service, Terminate(..)) +import Daml.Finance.App.Settlement.Service qualified as Settlement (Approve(..), Offer(..), Request, Service) +import Daml.Finance.App.Structuring.Auto qualified as StructuringAuto (Approve(..), Offer(..), Request, Service) +import Daml.Finance.App.Structuring.Service qualified as Structuring (Approve(..), Offer(..), Request, Service) import Daml.Finance.Interface.Account.Factory qualified as Account (F) import Daml.Finance.Interface.Holding.Factory qualified as Holding (F) +import Daml.Finance.Interface.Instrument.Bond.FixedRate.Factory qualified as FixedRateBond (Factory) +import Daml.Finance.Interface.Instrument.Bond.FloatingRate.Factory qualified as FloatingRateBond (Factory) +import Daml.Finance.Interface.Instrument.Bond.InflationLinked.Factory qualified as InflationLinkedBond (Factory) +import Daml.Finance.Interface.Instrument.Bond.ZeroCoupon.Factory qualified as ZeroCouponBond (Factory) +import Daml.Finance.Interface.Instrument.Equity.Factory qualified as Equity (Factory) +import Daml.Finance.Interface.Instrument.Generic.Factory qualified as Generic (Factory) +import Daml.Finance.Interface.Instrument.Swap.Fpml.Factory qualified as FpmlSwap (Factory) +import Daml.Finance.Interface.Instrument.Token.Factory qualified as Token (Factory) import Daml.Finance.Interface.Lifecycle.Rule.Claim qualified as Lifecycle (Claim) import Daml.Finance.Interface.Lifecycle.Rule.Lifecycle qualified as Lifecycle (I) @@ -171,12 +179,20 @@ template Role customer : Party controller provider do - exerciseByKey @Settlement.Service (operator, provider, customer) Settlement.Terminate with actor = provider + (serviceCid, _) <- fetchByKey @Settlement.Service (operator, provider, customer) + exercise (toInterfaceContractId @Base.I serviceCid) Base.Terminate with actor = provider nonconsuming choice OfferStructuringService : ContractId Structuring.Offer with customer : Party - factories : Structuring.Factories + token : ContractId Token.Factory + equity : ContractId Equity.Factory + generic : ContractId Generic.Factory + fixedRateBond : ContractId FixedRateBond.Factory + floatingRateBond : ContractId FloatingRateBond.Factory + inflationLinkedBond : ContractId InflationLinkedBond.Factory + zeroCouponBond : ContractId ZeroCouponBond.Factory + fpmlSwap : ContractId FpmlSwap.Factory controller provider do create Structuring.Offer with .. @@ -184,7 +200,14 @@ template Role nonconsuming choice ApproveStructuringRequest : ContractId Structuring.Service with structuringServiceRequestCid : ContractId Structuring.Request - factories : Structuring.Factories + token : ContractId Token.Factory + equity : ContractId Equity.Factory + generic : ContractId Generic.Factory + fixedRateBond : ContractId FixedRateBond.Factory + floatingRateBond : ContractId FloatingRateBond.Factory + inflationLinkedBond : ContractId InflationLinkedBond.Factory + zeroCouponBond : ContractId ZeroCouponBond.Factory + fpmlSwap : ContractId FpmlSwap.Factory controller provider do exercise structuringServiceRequestCid Structuring.Approve with .. @@ -194,7 +217,8 @@ template Role customer : Party controller provider do - exerciseByKey @Structuring.Service (operator, provider, customer) Structuring.Terminate with actor = provider + (serviceCid, _) <- fetchByKey @Structuring.Service (operator, provider, customer) + exercise (toInterfaceContractId @Base.I serviceCid) Base.Terminate with actor = provider nonconsuming choice OfferStructuringAutoService : ContractId StructuringAuto.Offer with @@ -215,7 +239,8 @@ template Role customer : Party controller provider do - exerciseByKey @StructuringAuto.Service (operator, provider, customer) StructuringAuto.Terminate with actor = provider + (serviceCid, _) <- fetchByKey @StructuringAuto.Service (operator, provider, customer) + exercise (toInterfaceContractId @Base.I serviceCid) Base.Terminate with actor = provider nonconsuming choice OfferLifecycleService : ContractId Lifecycle.Offer with diff --git a/src/daml/Daml/Finance/App/Settlement/Service.daml b/src/daml/Daml/Finance/App/Settlement/Service.daml index e4aceec7..7076c75f 100644 --- a/src/daml/Daml/Finance/App/Settlement/Service.daml +++ b/src/daml/Daml/Finance/App/Settlement/Service.daml @@ -4,8 +4,9 @@ module Daml.Finance.App.Settlement.Service where import DA.Set (singleton) -import Daml.Finance.Interface.Settlement.Types qualified as Settlement (Allocation, Approval) -import Daml.Finance.Interface.Settlement.Instruction qualified as Instruction (I, Allocate(..), Approve(..)) +import Daml.Finance.App.Interface.Base.Service qualified as Base (I, View(..)) +import Daml.Finance.App.Interface.Settlement.Service qualified as Service (AllocateInstruction(..), ApproveInstruction(..), I, View(..)) +import Daml.Finance.Interface.Settlement.Instruction qualified as Instruction (Allocate(..), Approve(..)) template Service with @@ -18,34 +19,24 @@ template Service key (operator, provider, customer) : (Party, Party, Party) maintainer key._1 - nonconsuming choice AllocateInstruction : ContractId Instruction.I - with - actor : Party - instructionCid : ContractId Instruction.I - allocation : Settlement.Allocation - controller actor - do + interface instance Base.I for Service where + view = Base.View with operator; provider; customer + + terminate = pure () + + interface instance Service.I for Service where + view = Service.View + + asBase = toInterface @Base.I this + + allocateInstruction Service.AllocateInstruction{actor; instructionCid; allocation} = do assertMsg "Actor must be provider or customer" $ actor == customer || actor == provider fst <$> exercise instructionCid Instruction.Allocate with actors = singleton actor; allocation - nonconsuming choice ApproveInstruction : ContractId Instruction.I - with - actor : Party - instructionCid : ContractId Instruction.I - approval : Settlement.Approval - controller actor - do + approveInstruction Service.ApproveInstruction{actor; instructionCid; approval} = do assertMsg "Actor must be provider or customer" $ actor == customer || actor == provider exercise instructionCid Instruction.Approve with actors = singleton actor; approval - choice Terminate : () - with - actor : Party - controller actor - do - assert $ actor == operator || actor == provider || actor == customer - pure () - template Offer with operator : Party diff --git a/src/daml/Daml/Finance/App/Structuring/Auto.daml b/src/daml/Daml/Finance/App/Structuring/Auto.daml new file mode 100644 index 00000000..b55becf9 --- /dev/null +++ b/src/daml/Daml/Finance/App/Structuring/Auto.daml @@ -0,0 +1,118 @@ +-- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +-- SPDX-License-Identifier: Apache-2.0 + +module Daml.Finance.App.Structuring.Auto where + +import Daml.Finance.App.Interface.Base.Service qualified as Base (I, View(..)) +import Daml.Finance.App.Interface.Structuring.Auto qualified as Auto +import Daml.Finance.App.Interface.Structuring.Service qualified as Service +import Daml.Finance.App.Structuring.Service qualified as Service (T) + +type T = Service + +instance Auto.HasImplementation Service + +template Service + with + operator : Party + provider : Party + customer : Party + where + signatory operator, provider, customer + + key (operator, provider, customer) : (Party, Party, Party) + maintainer key._1 + + interface instance Base.I for Service where + view = Base.View with operator; provider; customer + terminate = pure () + + interface instance Auto.I for Service where + view = Auto.View + + asBase = toInterface @Base.I this + + requestAndCreateToken Auto.RequestAndCreateToken{..} = do + serviceCid <- toInterfaceContractId @Service.I . fst <$> fetchByKey @Service.T (operator, provider, customer) + createTokenRequestCid <- exercise serviceCid Service.RequestCreateToken with .. + exercise serviceCid Service.CreateToken with createTokenRequestCid + + requestAndCreateEquity Auto.RequestAndCreateEquity{..} = do + serviceCid <- toInterfaceContractId @Service.I . fst <$> fetchByKey @Service.T (operator, provider, customer) + createEquityRequestCid <- exercise serviceCid Service.RequestCreateEquity with .. + exercise serviceCid Service.CreateEquity with createEquityRequestCid + + requestAndCreateGeneric Auto.RequestAndCreateGeneric{..} = do + serviceCid <- toInterfaceContractId @Service.I . fst <$> fetchByKey @Service.T (operator, provider, customer) + createGenericRequestCid <- exercise serviceCid Service.RequestCreateGeneric with .. + exercise serviceCid Service.CreateGeneric with createGenericRequestCid + + requestAndCreateFixedRateBond Auto.RequestAndCreateFixedRateBond{..} = do + serviceCid <- toInterfaceContractId @Service.I . fst <$> fetchByKey @Service.T (operator, provider, customer) + createFixedRateBondRequestCid <- exercise serviceCid Service.RequestCreateFixedRateBond with .. + exercise serviceCid Service.CreateFixedRateBond with createFixedRateBondRequestCid + + requestAndCreateFloatingRateBond Auto.RequestAndCreateFloatingRateBond{..} = do + serviceCid <- toInterfaceContractId @Service.I . fst <$> fetchByKey @Service.T (operator, provider, customer) + createFloatingRateBondRequestCid <- exercise serviceCid Service.RequestCreateFloatingRateBond with .. + exercise serviceCid Service.CreateFloatingRateBond with createFloatingRateBondRequestCid + + requestAndCreateInflationLinkedBond Auto.RequestAndCreateInflationLinkedBond{..} = do + serviceCid <- toInterfaceContractId @Service.I . fst <$> fetchByKey @Service.T (operator, provider, customer) + createInflationLinkedBondRequestCid <- exercise serviceCid Service.RequestCreateInflationLinkedBond with .. + exercise serviceCid Service.CreateInflationLinkedBond with createInflationLinkedBondRequestCid + + requestAndCreateZeroCouponBond Auto.RequestAndCreateZeroCouponBond{..} = do + serviceCid <- toInterfaceContractId @Service.I . fst <$> fetchByKey @Service.T (operator, provider, customer) + createZeroCouponBondRequestCid <- exercise serviceCid Service.RequestCreateZeroCouponBond with .. + exercise serviceCid Service.CreateZeroCouponBond with createZeroCouponBondRequestCid + + requestAndCreateFpmlSwap Auto.RequestAndCreateFpmlSwap{..} = do + serviceCid <- toInterfaceContractId @Service.I . fst <$> fetchByKey @Service.T (operator, provider, customer) + createFpmlSwapRequestCid <- exercise serviceCid Service.RequestCreateFpmlSwap with .. + exercise serviceCid Service.CreateFpmlSwap with createFpmlSwapRequestCid + +template Offer + with + operator : Party + provider : Party + customer : Party + where + signatory operator, provider + observer customer + + choice Accept : ContractId Service + controller customer + do + create Service with .. + + choice Decline : () + controller customer + do pure () + + choice Withdraw : () + controller provider + do pure () + +template Request + with + customer : Party + provider : Party + where + signatory customer + observer provider + + choice Cancel : () + controller customer + do pure () + + choice Reject : () + controller provider + do pure () + + choice Approve : ContractId Service + with + operator : Party + controller operator, provider + do + create Service with .. diff --git a/src/daml/Daml/Finance/App/Structuring/Auto/Service.daml b/src/daml/Daml/Finance/App/Structuring/Auto/Service.daml deleted file mode 100644 index 503753f5..00000000 --- a/src/daml/Daml/Finance/App/Structuring/Auto/Service.daml +++ /dev/null @@ -1,195 +0,0 @@ --- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. --- SPDX-License-Identifier: Apache-2.0 - -module Daml.Finance.App.Structuring.Auto.Service where - -import Daml.Finance.App.Structuring.Service qualified as S -import Daml.Finance.Interface.Claims.Types (C) -import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (I) -import Daml.Finance.Interface.Types.Common (Id, InstrumentKey, PartiesMap) -import Daml.Finance.Interface.Types.Date.Calendar (BusinessDayConventionEnum) -import Daml.Finance.Interface.Types.Date.DayCount (DayCountConventionEnum) -import Daml.Finance.Interface.Types.Date.RollConvention (PeriodEnum) - -template Service - with - operator : Party - provider : Party - customer : Party - where - signatory operator, provider, customer - - key (operator, provider, customer) : (Party, Party, Party) - maintainer key._1 - - nonconsuming choice RequestAndCreateToken : ContractId Instrument.I - with - id : Text - description : Text - validAsOf : Time - observers : PartiesMap - controller customer - do - createTokenRequestCid <- exerciseByKey @S.Service (operator, provider, customer) S.RequestCreateToken with .. - exerciseByKey @S.Service (operator, provider, customer) S.CreateToken with createTokenRequestCid - - nonconsuming choice RequestAndCreateEquity : ContractId Instrument.I - with - id : Id - description : Text - version : Text - validAsOf : Time - observers : PartiesMap - controller customer - do - createEquityRequestCid <- exerciseByKey @S.Service (operator, provider, customer) S.RequestCreateEquity with .. - exerciseByKey @S.Service (operator, provider, customer) S.CreateEquity with createEquityRequestCid - - nonconsuming choice RequestAndCreateGeneric : ContractId Instrument.I - with - id : Text - description : Text - claims : C - acquisitionTime : Time - lastEventTimestamp : Time - observers : PartiesMap - controller customer - do - createGenericRequestCid <- exerciseByKey @S.Service (operator, provider, customer) S.RequestCreateGeneric with .. - exerciseByKey @S.Service (operator, provider, customer) S.CreateGeneric with createGenericRequestCid - - nonconsuming choice RequestAndCreateFixedRateBond : ContractId Instrument.I - with - id : Text - description : Text - couponRate : Decimal - issueDate : Date - firstCouponDate : Date - maturityDate : Date - holidayCalendarIds : [Text] - calendarDataProvider : Party - dayCountConvention : DayCountConventionEnum - businessDayConvention : BusinessDayConventionEnum - couponPeriod : PeriodEnum - couponPeriodMultiplier : Int - currency : InstrumentKey - observers : PartiesMap - lastEventTimestamp : Time - controller customer - do - createFixedRateBondRequestCid <- exerciseByKey @S.Service (operator, provider, customer) S.RequestCreateFixedRateBond with .. - exerciseByKey @S.Service (operator, provider, customer) S.CreateFixedRateBond with createFixedRateBondRequestCid - - nonconsuming choice RequestAndCreateFloatingRateBond : ContractId Instrument.I - with - id : Text - description : Text - referenceRateId : Text - couponSpread : Decimal - issueDate : Date - firstCouponDate : Date - maturityDate : Date - holidayCalendarIds : [Text] - calendarDataProvider : Party - dayCountConvention : DayCountConventionEnum - businessDayConvention : BusinessDayConventionEnum - couponPeriod : PeriodEnum - couponPeriodMultiplier : Int - currency : InstrumentKey - observers : PartiesMap - lastEventTimestamp : Time - controller customer - do - createFloatingRateBondRequestCid <- exerciseByKey @S.Service (operator, provider, customer) S.RequestCreateFloatingRateBond with .. - exerciseByKey @S.Service (operator, provider, customer) S.CreateFloatingRateBond with createFloatingRateBondRequestCid - - nonconsuming choice RequestAndCreateInflationLinkedBond : ContractId Instrument.I - with - id : Text - description : Text - inflationIndexId : Text - inflationIndexBaseValue : Decimal - couponRate : Decimal - issueDate : Date - firstCouponDate : Date - maturityDate : Date - holidayCalendarIds : [Text] - calendarDataProvider : Party - dayCountConvention : DayCountConventionEnum - businessDayConvention : BusinessDayConventionEnum - couponPeriod : PeriodEnum - couponPeriodMultiplier : Int - currency : InstrumentKey - observers : PartiesMap - lastEventTimestamp : Time - controller customer - do - createInflationLinkedBondRequestCid <- exerciseByKey @S.Service (operator, provider, customer) S.RequestCreateInflationLinkedBond with .. - exerciseByKey @S.Service (operator, provider, customer) S.CreateInflationLinkedBond with createInflationLinkedBondRequestCid - - nonconsuming choice RequestAndCreateZeroCouponBond : ContractId Instrument.I - with - id : Text - description : Text - issueDate : Date - maturityDate : Date - currency : InstrumentKey - observers : PartiesMap - lastEventTimestamp : Time - controller customer - do - createZeroCouponBondRequestCid <- exerciseByKey @S.Service (operator, provider, customer) S.RequestCreateZeroCouponBond with .. - exerciseByKey @S.Service (operator, provider, customer) S.CreateZeroCouponBond with createZeroCouponBondRequestCid - - choice Terminate : () - with - actor : Party - controller actor - do - assert $ actor == operator || actor == provider || actor == customer - pure () - -template Offer - with - operator : Party - provider : Party - customer : Party - where - signatory operator, provider - observer customer - - choice Accept : ContractId Service - controller customer - do - create Service with .. - - choice Decline : () - controller customer - do pure () - - choice Withdraw : () - controller provider - do pure () - -template Request - with - customer : Party - provider : Party - where - signatory customer - observer provider - - choice Cancel : () - controller customer - do pure () - - choice Reject : () - controller provider - do pure () - - choice Approve : ContractId Service - with - operator : Party - controller operator, provider - do - create Service with .. diff --git a/src/daml/Daml/Finance/App/Structuring/Model.daml b/src/daml/Daml/Finance/App/Structuring/Model.daml index 4a9b22e2..9e9a65f7 100644 --- a/src/daml/Daml/Finance/App/Structuring/Model.daml +++ b/src/daml/Daml/Finance/App/Structuring/Model.daml @@ -3,24 +3,54 @@ module Daml.Finance.App.Structuring.Model where +import DA.Set(fromList) +import Daml.Finance.App.Interface.Common.Removable qualified as Removable (I, View(..)) +import Daml.Finance.App.Interface.Structuring.CreateTokenRequest qualified as CreateTokenRequest (HasImplementation, I, View(..)) +import Daml.Finance.App.Interface.Structuring.CreateEquityRequest qualified as CreateEquityRequest (HasImplementation, I, View(..)) +import Daml.Finance.App.Interface.Structuring.CreateGenericRequest qualified as CreateGenericRequest (HasImplementation, I, View(..)) +import Daml.Finance.App.Interface.Structuring.CreateFixedRateBondRequest qualified as CreateFixedRateBondRequest (HasImplementation, I, View(..)) +import Daml.Finance.App.Interface.Structuring.CreateFloatingRateBondRequest qualified as CreateFloatingRateBondRequest (HasImplementation, I, View(..)) +import Daml.Finance.App.Interface.Structuring.CreateInflationLinkedBondRequest qualified as CreateInflationLinkedBondRequest (HasImplementation, I, View(..)) +import Daml.Finance.App.Interface.Structuring.CreateZeroCouponBondRequest qualified as CreateZeroCouponBondRequest (HasImplementation, I, View(..)) +import Daml.Finance.App.Interface.Structuring.CreateFpmlSwapRequest qualified as CreateFpmlSwapRequest (HasImplementation, I, View(..)) import Daml.Finance.Interface.Claims.Types (C) +import Daml.Finance.Interface.Instrument.Swap.Fpml.FpmlTypes (SwapStream) import Daml.Finance.Interface.Types.Common (Id, InstrumentKey, PartiesMap) import Daml.Finance.Interface.Types.Date.Calendar (BusinessDayConventionEnum) import Daml.Finance.Interface.Types.Date.DayCount (DayCountConventionEnum) import Daml.Finance.Interface.Types.Date.RollConvention (PeriodEnum) +instance CreateTokenRequest.HasImplementation CreateTokenRequest + template CreateTokenRequest with operator : Party provider : Party customer : Party - id : Text + id : Id description : Text observers : PartiesMap validAsOf : Time where signatory operator, provider, customer + interface instance Removable.I for CreateTokenRequest where + view = Removable.View with removers = fromList [operator, provider, customer] + + interface instance CreateTokenRequest.I for CreateTokenRequest where + view = CreateTokenRequest.View with + operator + provider + customer + id + description + observers + validAsOf + + asRemovable = toInterface @Removable.I this + +instance CreateEquityRequest.HasImplementation CreateEquityRequest + template CreateEquityRequest with operator : Party @@ -34,12 +64,30 @@ template CreateEquityRequest where signatory operator, provider, customer + interface instance Removable.I for CreateEquityRequest where + view = Removable.View with removers = fromList [operator, provider, customer] + + interface instance CreateEquityRequest.I for CreateEquityRequest where + view = CreateEquityRequest.View with + operator + provider + customer + id + description + version + observers + validAsOf + + asRemovable = toInterface @Removable.I this + +instance CreateGenericRequest.HasImplementation CreateGenericRequest + template CreateGenericRequest with operator : Party provider : Party customer : Party - id : Text + id : Id description : Text claims : C acquisitionTime : Time @@ -48,12 +96,31 @@ template CreateGenericRequest where signatory operator, provider, customer + interface instance Removable.I for CreateGenericRequest where + view = Removable.View with removers = fromList [operator, provider, customer] + + interface instance CreateGenericRequest.I for CreateGenericRequest where + view = CreateGenericRequest.View with + operator + provider + customer + id + description + claims + acquisitionTime + observers + lastEventTimestamp + + asRemovable = toInterface @Removable.I this + +instance CreateFixedRateBondRequest.HasImplementation CreateFixedRateBondRequest + template CreateFixedRateBondRequest with operator : Party provider : Party customer : Party - id : Text + id : Id description : Text couponRate : Decimal issueDate : Date @@ -71,12 +138,40 @@ template CreateFixedRateBondRequest where signatory operator, provider, customer + interface instance Removable.I for CreateFixedRateBondRequest where + view = Removable.View with removers = fromList [operator, provider, customer] + + interface instance CreateFixedRateBondRequest.I for CreateFixedRateBondRequest where + view = CreateFixedRateBondRequest.View with + operator + provider + customer + id + description + couponRate + issueDate + firstCouponDate + maturityDate + holidayCalendarIds + calendarDataProvider + dayCountConvention + businessDayConvention + couponPeriod + couponPeriodMultiplier + currency + observers + lastEventTimestamp + + asRemovable = toInterface @Removable.I this + +instance CreateFloatingRateBondRequest.HasImplementation CreateFloatingRateBondRequest + template CreateFloatingRateBondRequest with operator : Party provider : Party customer : Party - id : Text + id : Id description : Text referenceRateId : Text couponSpread : Decimal @@ -95,12 +190,41 @@ template CreateFloatingRateBondRequest where signatory operator, provider, customer + interface instance Removable.I for CreateFloatingRateBondRequest where + view = Removable.View with removers = fromList [operator, provider, customer] + + interface instance CreateFloatingRateBondRequest.I for CreateFloatingRateBondRequest where + view = CreateFloatingRateBondRequest.View with + operator + provider + customer + id + description + referenceRateId + couponSpread + issueDate + firstCouponDate + maturityDate + holidayCalendarIds + calendarDataProvider + dayCountConvention + businessDayConvention + couponPeriod + couponPeriodMultiplier + currency + observers + lastEventTimestamp + + asRemovable = toInterface @Removable.I this + +instance CreateInflationLinkedBondRequest.HasImplementation CreateInflationLinkedBondRequest + template CreateInflationLinkedBondRequest with operator : Party provider : Party customer : Party - id : Text + id : Id description : Text inflationIndexId : Text inflationIndexBaseValue : Decimal @@ -120,12 +244,42 @@ template CreateInflationLinkedBondRequest where signatory operator, provider, customer + interface instance Removable.I for CreateInflationLinkedBondRequest where + view = Removable.View with removers = fromList [operator, provider, customer] + + interface instance CreateInflationLinkedBondRequest.I for CreateInflationLinkedBondRequest where + view = CreateInflationLinkedBondRequest.View with + operator + provider + customer + id + description + inflationIndexId + inflationIndexBaseValue + couponRate + issueDate + firstCouponDate + maturityDate + holidayCalendarIds + calendarDataProvider + dayCountConvention + businessDayConvention + couponPeriod + couponPeriodMultiplier + currency + observers + lastEventTimestamp + + asRemovable = toInterface @Removable.I this + +instance CreateZeroCouponBondRequest.HasImplementation CreateZeroCouponBondRequest + template CreateZeroCouponBondRequest with operator : Party provider : Party customer : Party - id : Text + id : Id description : Text issueDate : Date maturityDate : Date @@ -135,3 +289,58 @@ template CreateZeroCouponBondRequest where signatory operator, provider, customer + interface instance Removable.I for CreateZeroCouponBondRequest where + view = Removable.View with removers = fromList [operator, provider, customer] + + interface instance CreateZeroCouponBondRequest.I for CreateZeroCouponBondRequest where + view = CreateZeroCouponBondRequest.View with + operator + provider + customer + id + description + issueDate + maturityDate + currency + observers + lastEventTimestamp + + asRemovable = toInterface @Removable.I this + +instance CreateFpmlSwapRequest.HasImplementation CreateFpmlSwapRequest + +template CreateFpmlSwapRequest + with + operator : Party + provider : Party + customer : Party + id : Id + description : Text + swapStreams : [SwapStream] + issuerPartyRef : Text + calendarDataProvider : Party + currencies : [InstrumentKey] + observers : PartiesMap + lastEventTimestamp : Time + where + signatory operator, provider, customer + + interface instance Removable.I for CreateFpmlSwapRequest where + view = Removable.View with removers = fromList [operator, provider, customer] + + interface instance CreateFpmlSwapRequest.I for CreateFpmlSwapRequest where + view = CreateFpmlSwapRequest.View with + operator + provider + customer + id + description + swapStreams + issuerPartyRef + calendarDataProvider + currencies + observers + lastEventTimestamp + + asRemovable = toInterface @Removable.I this + diff --git a/src/daml/Daml/Finance/App/Structuring/Service.daml b/src/daml/Daml/Finance/App/Structuring/Service.daml index 918a8318..41cf3234 100644 --- a/src/daml/Daml/Finance/App/Structuring/Service.daml +++ b/src/daml/Daml/Finance/App/Structuring/Service.daml @@ -4,10 +4,18 @@ module Daml.Finance.App.Structuring.Service where import DA.Date (toGregorian) +import Daml.Finance.App.Interface.Base.Service qualified as Base (I, View(..)) +import Daml.Finance.App.Interface.Common.Util (fetchAndRemove) +import Daml.Finance.App.Interface.Structuring.CreateTokenRequest qualified as CreateTokenRequest (View(..)) +import Daml.Finance.App.Interface.Structuring.CreateEquityRequest qualified as CreateEquityRequest (View(..)) +import Daml.Finance.App.Interface.Structuring.CreateGenericRequest qualified as CreateGenericRequest (View(..)) +import Daml.Finance.App.Interface.Structuring.CreateFixedRateBondRequest qualified as CreateFixedRateBondRequest (View(..)) +import Daml.Finance.App.Interface.Structuring.CreateFloatingRateBondRequest qualified as CreateFloatingRateBondRequest (View(..)) +import Daml.Finance.App.Interface.Structuring.CreateInflationLinkedBondRequest qualified as CreateInflationLinkedBondRequest (View(..)) +import Daml.Finance.App.Interface.Structuring.CreateZeroCouponBondRequest qualified as CreateZeroCouponBondRequest (View(..)) +import Daml.Finance.App.Interface.Structuring.CreateFpmlSwapRequest qualified as CreateFpmlSwapRequest (View(..)) +import Daml.Finance.App.Interface.Structuring.Service qualified as Service import Daml.Finance.App.Structuring.Model -import Daml.Finance.App.Util (fetchAndArchive) -import Daml.Finance.Interface.Claims.Types (C) -import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (I) import Daml.Finance.Interface.Instrument.Bond.FixedRate.Factory qualified as FixedRateBond (Factory, Create(..)) import Daml.Finance.Interface.Instrument.Bond.FixedRate.Types (FixedRate(..)) import Daml.Finance.Interface.Instrument.Bond.FloatingRate.Factory qualified as FloatingRateBond (Factory, Create(..)) @@ -18,16 +26,24 @@ import Daml.Finance.Interface.Instrument.Bond.ZeroCoupon.Factory qualified as Ze import Daml.Finance.Interface.Instrument.Bond.ZeroCoupon.Types (ZeroCoupon(..)) import Daml.Finance.Interface.Instrument.Equity.Factory qualified as Equity (Factory, Create(..)) import Daml.Finance.Interface.Instrument.Generic.Factory qualified as Generic (Factory, Create(..)) +import Daml.Finance.Interface.Instrument.Swap.Fpml.Factory qualified as FpmlSwap (Factory, Create(..)) +import Daml.Finance.Interface.Instrument.Swap.Fpml.Types (Fpml(..)) import Daml.Finance.Interface.Instrument.Token.Factory qualified as Token (Factory, Create(..)) import Daml.Finance.Interface.Instrument.Token.Types (Token(..)) import Daml.Finance.Interface.Types.Date.Calendar (BusinessDayAdjustment(..), BusinessDayConventionEnum) -import Daml.Finance.Interface.Types.Date.DayCount (DayCountConventionEnum) import Daml.Finance.Interface.Types.Date.RollConvention (PeriodEnum, RollConventionEnum(..)) import Daml.Finance.Interface.Types.Date.Schedule (Frequency(..), PeriodicSchedule(..)) -import Daml.Finance.Interface.Types.Common (Id(..), InstrumentKey(..), PartiesMap) +import Daml.Finance.Interface.Types.Common (InstrumentKey(..)) -data Factories = Factories +type T = Service + +instance Service.HasImplementation Service + +template Service with + operator : Party + provider : Party + customer : Party token : ContractId Token.Factory equity : ContractId Equity.Factory generic : ContractId Generic.Factory @@ -35,224 +51,116 @@ data Factories = Factories floatingRateBond : ContractId FloatingRateBond.Factory inflationLinkedBond : ContractId InflationLinkedBond.Factory zeroCouponBond : ContractId ZeroCouponBond.Factory - deriving (Eq, Show) - -template Service - with - operator : Party - provider : Party - customer : Party - factories : Factories + fpmlSwap : ContractId FpmlSwap.Factory where signatory operator, provider, customer key (operator, provider, customer) : (Party, Party, Party) maintainer key._1 - nonconsuming choice RequestCreateToken : ContractId CreateTokenRequest - with - id : Text - description : Text - validAsOf : Time - observers : PartiesMap - controller customer - do - create CreateTokenRequest with .. + interface instance Base.I for Service where + view = Base.View with operator; provider; customer + terminate = pure () - nonconsuming choice RequestCreateEquity : ContractId CreateEquityRequest - with - id : Id - description : Text - version : Text - validAsOf : Time - observers : PartiesMap - controller customer - do - create CreateEquityRequest with .. + interface instance Service.I for Service where + view = Service.View with token; equity; generic; fixedRateBond; floatingRateBond; inflationLinkedBond; zeroCouponBond; fpmlSwap - nonconsuming choice RequestCreateGeneric : ContractId CreateGenericRequest - with - id : Text - description : Text - claims : C - acquisitionTime : Time - lastEventTimestamp : Time - observers : PartiesMap - controller customer - do - create CreateGenericRequest with .. + asBase = toInterface @Base.I this - nonconsuming choice RequestCreateFixedRateBond : ContractId CreateFixedRateBondRequest - with - id : Text - description : Text - couponRate : Decimal - issueDate : Date - firstCouponDate : Date - maturityDate : Date - holidayCalendarIds : [Text] - calendarDataProvider : Party - dayCountConvention : DayCountConventionEnum - businessDayConvention : BusinessDayConventionEnum - couponPeriod : PeriodEnum - couponPeriodMultiplier : Int - currency : InstrumentKey - observers : PartiesMap - lastEventTimestamp : Time - controller customer - do - create CreateFixedRateBondRequest with .. + requestCreateToken Service.RequestCreateToken{..} = do + toInterfaceContractId <$> create CreateTokenRequest with .. - nonconsuming choice RequestCreateFloatingRateBond : ContractId CreateFloatingRateBondRequest - with - id : Text - description : Text - referenceRateId : Text - couponSpread : Decimal - issueDate : Date - firstCouponDate : Date - maturityDate : Date - holidayCalendarIds : [Text] - calendarDataProvider : Party - dayCountConvention : DayCountConventionEnum - businessDayConvention : BusinessDayConventionEnum - couponPeriod : PeriodEnum - couponPeriodMultiplier : Int - currency : InstrumentKey - observers : PartiesMap - lastEventTimestamp : Time - controller customer - do - create CreateFloatingRateBondRequest with .. + requestCreateEquity Service.RequestCreateEquity{..} = do + toInterfaceContractId <$> create CreateEquityRequest with .. - nonconsuming choice RequestCreateInflationLinkedBond : ContractId CreateInflationLinkedBondRequest - with - id : Text - description : Text - inflationIndexId : Text - inflationIndexBaseValue : Decimal - couponRate : Decimal - issueDate : Date - firstCouponDate : Date - maturityDate : Date - holidayCalendarIds : [Text] - calendarDataProvider : Party - dayCountConvention : DayCountConventionEnum - businessDayConvention : BusinessDayConventionEnum - couponPeriod : PeriodEnum - couponPeriodMultiplier : Int - currency : InstrumentKey - observers : PartiesMap - lastEventTimestamp : Time - controller customer - do - create CreateInflationLinkedBondRequest with .. + requestCreateGeneric Service.RequestCreateGeneric{..} = do + toInterfaceContractId <$> create CreateGenericRequest with .. - nonconsuming choice RequestCreateZeroCouponBond : ContractId CreateZeroCouponBondRequest - with - id : Text - description : Text - issueDate : Date - maturityDate : Date - currency : InstrumentKey - observers : PartiesMap - lastEventTimestamp : Time - controller customer - do - create CreateZeroCouponBondRequest with .. + requestCreateFixedRateBond Service.RequestCreateFixedRateBond{..} = do + toInterfaceContractId <$> create CreateFixedRateBondRequest with .. - nonconsuming choice CreateToken : ContractId Instrument.I - with - createTokenRequestCid : ContractId CreateTokenRequest - controller provider - do - CreateTokenRequest{..} <- fetchAndArchive createTokenRequestCid + requestCreateFloatingRateBond Service.RequestCreateFloatingRateBond{..} = do + toInterfaceContractId <$> create CreateFloatingRateBondRequest with .. + + requestCreateInflationLinkedBond Service.RequestCreateInflationLinkedBond{..} = do + toInterfaceContractId <$> create CreateInflationLinkedBondRequest with .. + + requestCreateZeroCouponBond Service.RequestCreateZeroCouponBond{..} = do + toInterfaceContractId <$> create CreateZeroCouponBondRequest with .. + + requestCreateFpmlSwap Service.RequestCreateFpmlSwap{..} = do + toInterfaceContractId <$> create CreateFpmlSwapRequest with .. + + createToken Service.CreateToken{createTokenRequestCid} = do + CreateTokenRequest.View{..} <- view <$> fetchAndRemove createTokenRequestCid let - instrument = InstrumentKey with depository = provider; issuer = customer; id = Id id; version = "0" - token = Token with .. - exercise factories.token Token.Create with token; observers + instrument = InstrumentKey with depository = provider; issuer = customer; id; version = "0" + tokenData = Token with .. + exercise token Token.Create with token = tokenData; observers - nonconsuming choice CreateEquity : ContractId Instrument.I - with - createEquityRequestCid : ContractId CreateEquityRequest - controller provider - do - CreateEquityRequest{..} <- fetchAndArchive createEquityRequestCid + createEquity Service.CreateEquity{createEquityRequestCid} = do + CreateEquityRequest.View{..} <- view <$> fetchAndRemove createEquityRequestCid let instrument = InstrumentKey with depository = provider; issuer = customer; id; version - exercise factories.equity Equity.Create with .. + exercise equity Equity.Create with .. - nonconsuming choice CreateGeneric : ContractId Instrument.I - with - createGenericRequestCid : ContractId CreateGenericRequest - controller provider - do - CreateGenericRequest{..} <- fetchAndArchive createGenericRequestCid + createGeneric Service.CreateGeneric{createGenericRequestCid} = do + CreateGenericRequest.View{..} <- view <$> fetchAndRemove createGenericRequestCid let - instrument = InstrumentKey with depository = provider; issuer = customer; id = Id id; version = "0" - exercise factories.generic Generic.Create with .. + instrument = InstrumentKey with depository = provider; issuer = customer; id; version = "0" + exercise generic Generic.Create with .. - nonconsuming choice CreateFixedRateBond : ContractId Instrument.I - with - createFixedRateBondRequestCid : ContractId CreateFixedRateBondRequest - controller provider - do - CreateFixedRateBondRequest{..} <- fetchAndArchive createFixedRateBondRequestCid + createFixedRateBond Service.CreateFixedRateBond{createFixedRateBondRequestCid} = do + CreateFixedRateBondRequest.View{..} <- view <$> fetchAndRemove createFixedRateBondRequestCid let - instrument = InstrumentKey with depository = provider; issuer = customer; id = Id id; version = "0" + instrument = InstrumentKey with depository = provider; issuer = customer; id; version = "0" periodicSchedule = createCouponPeriodicSchedule firstCouponDate holidayCalendarIds businessDayConvention couponPeriod couponPeriodMultiplier issueDate maturityDate fixedRate = FixedRate with .. - exercise factories.fixedRateBond FixedRateBond.Create with fixedRate; observers + exercise fixedRateBond FixedRateBond.Create with fixedRate; observers - nonconsuming choice CreateFloatingRateBond : ContractId Instrument.I - with - createFloatingRateBondRequestCid : ContractId CreateFloatingRateBondRequest - controller provider - do - CreateFloatingRateBondRequest{..} <- fetchAndArchive createFloatingRateBondRequestCid + createFloatingRateBond Service.CreateFloatingRateBond{createFloatingRateBondRequestCid} = do + CreateFloatingRateBondRequest.View{..} <- view <$> fetchAndRemove createFloatingRateBondRequestCid let - instrument = InstrumentKey with depository = provider; issuer = customer; id = Id id; version = "0" + instrument = InstrumentKey with depository = provider; issuer = customer; id; version = "0" periodicSchedule = createCouponPeriodicSchedule firstCouponDate holidayCalendarIds businessDayConvention couponPeriod couponPeriodMultiplier issueDate maturityDate floatingRate = FloatingRate with .. - exercise factories.floatingRateBond FloatingRateBond.Create with floatingRate; observers + exercise floatingRateBond FloatingRateBond.Create with floatingRate; observers - nonconsuming choice CreateInflationLinkedBond : ContractId Instrument.I - with - createInflationLinkedBondRequestCid : ContractId CreateInflationLinkedBondRequest - controller provider - do - CreateInflationLinkedBondRequest{..} <- fetchAndArchive createInflationLinkedBondRequestCid + createInflationLinkedBond Service.CreateInflationLinkedBond{createInflationLinkedBondRequestCid} = do + CreateInflationLinkedBondRequest.View{..} <- view <$> fetchAndRemove createInflationLinkedBondRequestCid let - instrument = InstrumentKey with depository = provider; issuer = customer; id = Id id; version = "0" + instrument = InstrumentKey with depository = provider; issuer = customer; id; version = "0" periodicSchedule = createCouponPeriodicSchedule firstCouponDate holidayCalendarIds businessDayConvention couponPeriod couponPeriodMultiplier issueDate maturityDate inflationLinked = InflationLinked with .. - exercise factories.inflationLinkedBond InflationLinkedBond.Create with inflationLinked; observers + exercise inflationLinkedBond InflationLinkedBond.Create with inflationLinked; observers - nonconsuming choice CreateZeroCouponBond : ContractId Instrument.I - with - createZeroCouponBondRequestCid : ContractId CreateZeroCouponBondRequest - controller provider - do - CreateZeroCouponBondRequest{..} <- fetchAndArchive createZeroCouponBondRequestCid + createZeroCouponBond Service.CreateZeroCouponBond{createZeroCouponBondRequestCid} = do + CreateZeroCouponBondRequest.View{..} <- view <$> fetchAndRemove createZeroCouponBondRequestCid let - instrument = InstrumentKey with depository = provider; issuer = customer; id = Id id; version = "0" + instrument = InstrumentKey with depository = provider; issuer = customer; id; version = "0" zeroCoupon = ZeroCoupon with .. - exercise factories.zeroCouponBond ZeroCouponBond.Create with zeroCoupon; observers + exercise zeroCouponBond ZeroCouponBond.Create with zeroCoupon; observers - choice Terminate : () - with - actor : Party - controller actor - do - assert $ actor == operator || actor == provider || actor == customer - pure () + createFpmlSwap Service.CreateFpmlSwap{createFpmlSwapRequestCid} = do + CreateFpmlSwapRequest.View{..} <- view <$> fetchAndRemove createFpmlSwapRequestCid + let + instrument = InstrumentKey with depository = provider; issuer = customer; id; version = "0" + fpml = Fpml with .. + exercise fpmlSwap FpmlSwap.Create with fpml; observers template Offer with operator : Party provider : Party customer : Party - factories : Factories + token : ContractId Token.Factory + equity : ContractId Equity.Factory + generic : ContractId Generic.Factory + fixedRateBond : ContractId FixedRateBond.Factory + floatingRateBond : ContractId FloatingRateBond.Factory + inflationLinkedBond : ContractId InflationLinkedBond.Factory + zeroCouponBond : ContractId ZeroCouponBond.Factory + fpmlSwap : ContractId FpmlSwap.Factory where signatory operator, provider observer customer @@ -289,7 +197,14 @@ template Request choice Approve : ContractId Service with operator : Party - factories : Factories + token : ContractId Token.Factory + equity : ContractId Equity.Factory + generic : ContractId Generic.Factory + fixedRateBond : ContractId FixedRateBond.Factory + floatingRateBond : ContractId FloatingRateBond.Factory + inflationLinkedBond : ContractId InflationLinkedBond.Factory + zeroCouponBond : ContractId ZeroCouponBond.Factory + fpmlSwap : ContractId FpmlSwap.Factory controller operator, provider do create Service with .. diff --git a/src/daml/Daml/Finance/Setup/Util/Service.daml b/src/daml/Daml/Finance/Setup/Util/Service.daml index d1b0d27d..002f485c 100644 --- a/src/daml/Daml/Finance/Setup/Util/Service.daml +++ b/src/daml/Daml/Finance/Setup/Util/Service.daml @@ -25,6 +25,9 @@ import Daml.Finance.App.Interface.Lending.Service qualified as Lending (I) import Daml.Finance.App.Interface.Lifecycle.Service qualified as Lifecycle (I) import Daml.Finance.App.Interface.Listing.Auto qualified as ListingAuto (I) import Daml.Finance.App.Interface.Listing.Service qualified as Listing (I) +import Daml.Finance.App.Interface.Settlement.Service qualified as Settlement (I) +import Daml.Finance.App.Interface.Structuring.Auto qualified as StructuringAuto (I) +import Daml.Finance.App.Interface.Structuring.Service qualified as Structuring (I) import Daml.Finance.App.Issuance.Auto qualified as IssuanceAuto (Accept(..)) import Daml.Finance.App.Issuance.BackToBack qualified as BackToBack (Accept(..)) import Daml.Finance.App.Issuance.Service qualified as Issuance (Accept(..)) @@ -44,15 +47,16 @@ import Daml.Finance.App.Distribution.Subscription.Service qualified as Subscript import Daml.Finance.App.Role.Custodian qualified as Custodian import Daml.Finance.App.Role.Distributor qualified as Distributor import Daml.Finance.App.Role.Exchange qualified as Exchange -import Daml.Finance.App.Settlement.Service qualified as Settlement (Accept(..), Service) -import Daml.Finance.App.Structuring.Auto.Service qualified as StructuringAuto (Accept(..), Service) -import Daml.Finance.App.Structuring.Service qualified as Structuring (Accept(..), Factories(..), Service) +import Daml.Finance.App.Settlement.Service qualified as Settlement (Accept(..)) +import Daml.Finance.App.Structuring.Auto qualified as StructuringAuto (Accept(..)) +import Daml.Finance.App.Structuring.Service qualified as Structuring (Accept(..)) import Daml.Finance.Instrument.Bond.FixedRate.Factory qualified as FixedRateBond (Factory(..)) import Daml.Finance.Instrument.Bond.FloatingRate.Factory qualified as FloatingRateBond (Factory(..)) import Daml.Finance.Instrument.Bond.InflationLinked.Factory qualified as InflationLinkedBond (Factory(..)) import Daml.Finance.Instrument.Bond.ZeroCoupon.Factory qualified as ZeroCouponBond (Factory(..)) import Daml.Finance.Instrument.Equity.Factory qualified as Equity (Factory(..)) import Daml.Finance.Instrument.Generic.Factory qualified as Generic (Factory(..)) +import Daml.Finance.Instrument.Swap.Fpml.Factory qualified as FpmlSwap (Factory(..)) import Daml.Finance.Instrument.Token.Factory qualified as Token (Factory(..)) import Daml.Finance.Interface.Account.Account qualified as Account (K) import Daml.Finance.Interface.Account.Factory qualified as Account (F) @@ -91,7 +95,7 @@ createIssuanceAutoService operator custodian customer = do offerCid <- submit custodian do exerciseByKeyCmd @Custodian.Role (operator, custodian) Custodian.OfferIssuanceAutoService with .. toInterfaceContractId <$> submit customer do exerciseCmd offerCid IssuanceAuto.Accept -createStructuringService : Party -> Party -> Party -> Script (ContractId Structuring.Service) +createStructuringService : Party -> Party -> Party -> Script (ContractId Structuring.I) createStructuringService operator custodian customer = do token <- toInterfaceContractId <$> submit custodian do createCmd Token.Factory with provider = custodian; observers = M.fromList [("Default", singleton customer)] equity <- toInterfaceContractId <$> submit custodian do createCmd Equity.Factory with provider = custodian; observers = M.fromList [("Default", singleton customer)] @@ -100,14 +104,14 @@ createStructuringService operator custodian customer = do floatingRateBond <- toInterfaceContractId <$> submit custodian do createCmd FloatingRateBond.Factory with provider = custodian; observers = M.fromList [("Default", singleton customer)] inflationLinkedBond <- toInterfaceContractId <$> submit custodian do createCmd InflationLinkedBond.Factory with provider = custodian; observers = M.fromList [("Default", singleton customer)] zeroCouponBond <- toInterfaceContractId <$> submit custodian do createCmd ZeroCouponBond.Factory with provider = custodian; observers = M.fromList [("Default", singleton customer)] - let factories = Structuring.Factories with token; equity; generic; fixedRateBond; floatingRateBond; inflationLinkedBond; zeroCouponBond + fpmlSwap <- toInterfaceContractId <$> submit custodian do createCmd FpmlSwap.Factory with provider = custodian; observers = M.fromList [("Default", singleton customer)] offerCid <- submit custodian do exerciseByKeyCmd @Custodian.Role (operator, custodian) Custodian.OfferStructuringService with .. - submit customer do exerciseCmd offerCid Structuring.Accept + toInterfaceContractId <$> submit customer do exerciseCmd offerCid Structuring.Accept -createStructuringAutoService : Party -> Party -> Party -> Script (ContractId StructuringAuto.Service) +createStructuringAutoService : Party -> Party -> Party -> Script (ContractId StructuringAuto.I) createStructuringAutoService operator custodian customer = do offerCid <- submit custodian do exerciseByKeyCmd @Custodian.Role (operator, custodian) Custodian.OfferStructuringAutoService with .. - submit customer do exerciseCmd offerCid StructuringAuto.Accept + toInterfaceContractId <$> submit customer do exerciseCmd offerCid StructuringAuto.Accept createBackToBackIssuanceService : Party -> Party -> Party -> Party -> Script (ContractId BackToBack.I) createBackToBackIssuanceService operator custodian customer public = do @@ -171,10 +175,10 @@ createLendingService operator lender borrower = do offerCid <- submit lender do exerciseByKeyCmd @Custodian.Role (operator, lender) Custodian.OfferLendingService with customer = borrower toInterfaceContractId <$> submit borrower do exerciseCmd offerCid Lending.Accept -createSettlementService : Party -> Party -> Party -> Script (ContractId Settlement.Service) +createSettlementService : Party -> Party -> Party -> Script (ContractId Settlement.I) createSettlementService operator custodian customer = do offerCid <- submit custodian do exerciseByKeyCmd @Custodian.Role (operator, custodian) Custodian.OfferSettlementService with customer - submit customer do exerciseCmd offerCid Settlement.Accept + toInterfaceContractId <$> submit customer do exerciseCmd offerCid Settlement.Accept createInvestmentService : Party -> Party -> Party -> Script (ContractId Investment.I) createInvestmentService operator provider customer = do From 7d2adb4633ce03d17baf2f8ac8c2a374a34eb2c1 Mon Sep 17 00:00:00 2001 From: Georg Schneider Date: Wed, 21 Dec 2022 13:32:30 +0100 Subject: [PATCH 12/31] Add interfaces for trading service --- .../App/Distribution/Fund/Service.daml | 4 +- .../Distribution/Subscription/Service.daml | 2 +- .../Finance/App/Interface/Trading/Auto.daml | 57 +++++++++ .../Interface/Trading/CancelOrderRequest.daml | 32 +++++ .../Interface/Trading/CreateOrderRequest.daml | 45 +++++++ .../Finance/App/Interface/Trading/Order.daml | 80 +++++++++++++ .../App/Interface/Trading/Service.daml | 93 +++++++++++++++ src/daml/Daml/Finance/App/Role/Exchange.daml | 10 +- src/daml/Daml/Finance/App/Trading/Auto.daml | 88 ++++++++++++++ .../Finance/App/Trading/Auto/Service.daml | 99 ---------------- src/daml/Daml/Finance/App/Trading/Model.daml | 112 ++++++++++++------ .../Daml/Finance/App/Trading/Service.daml | 102 +++++++--------- src/daml/Daml/Finance/App/Util.daml | 11 -- src/daml/Daml/Finance/Setup/Util/Service.daml | 14 ++- .../Daml/Finance/Setup/Util/Workflow.daml | 27 +++-- 15 files changed, 544 insertions(+), 232 deletions(-) create mode 100644 src/daml/Daml/Finance/App/Interface/Trading/Auto.daml create mode 100644 src/daml/Daml/Finance/App/Interface/Trading/CancelOrderRequest.daml create mode 100644 src/daml/Daml/Finance/App/Interface/Trading/CreateOrderRequest.daml create mode 100644 src/daml/Daml/Finance/App/Interface/Trading/Order.daml create mode 100644 src/daml/Daml/Finance/App/Interface/Trading/Service.daml create mode 100644 src/daml/Daml/Finance/App/Trading/Auto.daml delete mode 100644 src/daml/Daml/Finance/App/Trading/Auto/Service.daml delete mode 100644 src/daml/Daml/Finance/App/Util.daml diff --git a/src/daml/Daml/Finance/App/Distribution/Fund/Service.daml b/src/daml/Daml/Finance/App/Distribution/Fund/Service.daml index 084858d8..6f3ee40a 100644 --- a/src/daml/Daml/Finance/App/Distribution/Fund/Service.daml +++ b/src/daml/Daml/Finance/App/Distribution/Fund/Service.daml @@ -52,7 +52,7 @@ template Service poolInvestmentRequests Service.PoolInvestmentRequests{requestId; asOfDate; fundCid; cashCid; investmentRequestCids} = do fund <- exercise fundCid Fund.GetView with actor = customer - irs <- mapA (\cid -> view <$> fetch cid) investmentRequestCids + irs <- mapA (fmap view . fetch) investmentRequestCids (_, dir) <- fetchByKey @AccountDirectory customer -- Disclose cash to provider @@ -84,7 +84,7 @@ template Service (_, fundUnitsCid, fundCid) <- exercise fundCid Fund.IssueUnits with requestId = pir.requestId; quantity = fundQty; issuanceServiceCid -- Instruct settlement - irs <- mapA (\cid -> view <$> fetch cid) pir.investmentRequestCids + irs <- mapA (fmap view . fetch) pir.investmentRequestCids let createInvestorCashStep ir = Step with sender = ir.customer; receiver = ir.provider; quantity = ir.quantity createInvestorFundStep ir = Step with sender = ir.provider; receiver = ir.customer; quantity = Instrument.qty (ir.quantity.amount / unitValue) fund.instrument diff --git a/src/daml/Daml/Finance/App/Distribution/Subscription/Service.daml b/src/daml/Daml/Finance/App/Distribution/Subscription/Service.daml index f07eb021..9f7a427a 100644 --- a/src/daml/Daml/Finance/App/Distribution/Subscription/Service.daml +++ b/src/daml/Daml/Finance/App/Distribution/Subscription/Service.daml @@ -82,7 +82,7 @@ template Service -- Settle subscriptions offeringI <- fetch offeringCid let offering = view offeringI - subscriptions <- zip subscriptionCids <$> forA subscriptionCids (\cid -> view <$> fetch cid) + subscriptions <- zip subscriptionCids <$> forA subscriptionCids (fmap view . fetch) (remainingIssuerQuantity, remainingIssuerHoldingCidOpt) <- foldlA (settleSubscription provider settlementFactoryCid offering) (offering.asset.amount, Some offering.issuerHoldingCid) subscriptions -- Settle back-to-back trade diff --git a/src/daml/Daml/Finance/App/Interface/Trading/Auto.daml b/src/daml/Daml/Finance/App/Interface/Trading/Auto.daml new file mode 100644 index 00000000..3ea03378 --- /dev/null +++ b/src/daml/Daml/Finance/App/Interface/Trading/Auto.daml @@ -0,0 +1,57 @@ +-- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +-- SPDX-License-Identifier: Apache-2.0 + +module Daml.Finance.App.Interface.Trading.Auto where + +import Daml.Finance.App.Interface.Base.Service qualified as Base (I) +import Daml.Finance.App.Interface.Trading.Order qualified as Order (I, Side, View) +import Daml.Finance.Interface.Holding.Fungible qualified as Fungible (I) +import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (Q) +import Daml.Finance.Interface.Types.Common (AccountKey, Id, Parties) + +type I = Service + +type V = View + +data View = View {} + deriving (Eq, Show) + +interface Service where + viewtype V + + asBase : Base.I + -- ^ Conversion to base `Service` interface. + + requestAndCreateOrder : RequestAndCreateOrder -> Update (Optional (ContractId Order.I, Order.View)) + -- ^ Implementation of the `RequestAndCreateOrder` choice. + + requestAndCancelOrder : RequestAndCancelOrder -> Update () + -- ^ Implementation of the `RequestAndCancelOrder` choice. + + nonconsuming choice RequestAndCreateOrder : Optional (ContractId Order.I, Order.View) + with + id : Id + listingId : Id + quantity : Instrument.Q + price : Instrument.Q + side : Order.Side + collateralCid : ContractId Fungible.I + account : AccountKey + orderCids : [ContractId Order.I] + observers : Parties + controller (view $ asBase this).customer + do + requestAndCreateOrder this arg + + nonconsuming choice RequestAndCancelOrder : () + with + orderCid : ContractId Order.I + controller (view $ asBase this).customer + do + requestAndCancelOrder this arg + +-- | Type constraint for requiring templates to implement `Service`. +type Implementation t = HasToInterface t Service +class (Implementation t) => HasImplementation t +instance HasImplementation Service +instance HasToInterface Service Base.I where _toInterface = asBase diff --git a/src/daml/Daml/Finance/App/Interface/Trading/CancelOrderRequest.daml b/src/daml/Daml/Finance/App/Interface/Trading/CancelOrderRequest.daml new file mode 100644 index 00000000..56d2d7ae --- /dev/null +++ b/src/daml/Daml/Finance/App/Interface/Trading/CancelOrderRequest.daml @@ -0,0 +1,32 @@ +-- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +-- SPDX-License-Identifier: Apache-2.0 + +module Daml.Finance.App.Interface.Trading.CancelOrderRequest where + +import Daml.Finance.App.Interface.Common.Removable qualified as Removable (I, Implementation) +import Daml.Finance.App.Interface.Trading.Order qualified as Order (I) + +type I = CancelOrderRequest + +type V = View + +data View = View + with + operator : Party + provider : Party + customer : Party + orderCid : ContractId Order.I + deriving (Eq, Show) + +interface CancelOrderRequest where + viewtype View + -- ^ Interface view type. + + asRemovable : Removable.I + -- ^ Conversion to the `Removable` interface. + +-- | Type constraint for requiring templates to implement `CancelOrderRequest`. +type Implementation t = (HasToInterface t CancelOrderRequest, Removable.Implementation t) +class (Implementation t) => HasImplementation t +instance HasImplementation CancelOrderRequest +instance HasToInterface CancelOrderRequest Removable.I where _toInterface = asRemovable diff --git a/src/daml/Daml/Finance/App/Interface/Trading/CreateOrderRequest.daml b/src/daml/Daml/Finance/App/Interface/Trading/CreateOrderRequest.daml new file mode 100644 index 00000000..280bbd17 --- /dev/null +++ b/src/daml/Daml/Finance/App/Interface/Trading/CreateOrderRequest.daml @@ -0,0 +1,45 @@ +-- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +-- SPDX-License-Identifier: Apache-2.0 + +module Daml.Finance.App.Interface.Trading.CreateOrderRequest where + +import Daml.Finance.App.Interface.Common.Removable qualified as Removable (I, Implementation) +import Daml.Finance.App.Interface.Trading.Order qualified as Order (I, Side) +import Daml.Finance.Interface.Account.Account qualified as Account (K) +import Daml.Finance.Interface.Holding.Fungible qualified as Fungible (I) +import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (Q) +import Daml.Finance.Interface.Types.Common (Id, Parties) + +type I = CreateOrderRequest + +type V = View + +data View = View + with + operator : Party + provider : Party + customer : Party + id : Id + timestamp : Time + listingId : Id + quantity : Instrument.Q + side : Order.Side + price : Instrument.Q + collateralCid : ContractId Fungible.I + account : Account.K + orderCids : [ContractId Order.I] + observers : Parties + deriving (Eq, Show) + +interface CreateOrderRequest where + viewtype View + -- ^ Interface view type. + + asRemovable : Removable.I + -- ^ Conversion to the `Removable` interface. + +-- | Type constraint for requiring templates to implement `CreateOrderRequest`. +type Implementation t = (HasToInterface t CreateOrderRequest, Removable.Implementation t) +class (Implementation t) => HasImplementation t +instance HasImplementation CreateOrderRequest +instance HasToInterface CreateOrderRequest Removable.I where _toInterface = asRemovable diff --git a/src/daml/Daml/Finance/App/Interface/Trading/Order.daml b/src/daml/Daml/Finance/App/Interface/Trading/Order.daml new file mode 100644 index 00000000..cf40de86 --- /dev/null +++ b/src/daml/Daml/Finance/App/Interface/Trading/Order.daml @@ -0,0 +1,80 @@ +-- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +-- SPDX-License-Identifier: Apache-2.0 + +module Daml.Finance.App.Interface.Trading.Order where + +import Daml.Finance.App.Interface.Common.Removable qualified as Removable (I, Implementation) +import Daml.Finance.Interface.Account.Account qualified as Account (K) +import Daml.Finance.Interface.Holding.Fungible qualified as Fungible (I) +import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (Q) +import Daml.Finance.Interface.Settlement.Batch qualified as Batch (I) +import Daml.Finance.Interface.Settlement.Factory qualified as Factory (I) +import Daml.Finance.Interface.Settlement.Instruction qualified as Instruction (I) +import Daml.Finance.Interface.Types.Common (Id, Parties) + +type I = Order + +type V = View + +data Side + = Buy + | Sell + deriving (Eq, Show) + +data FillResult = FillResult + with + orderOpt : Optional (ContractId Order, View) + batchCid : ContractId Batch.I + instructionCid : ContractId Instruction.I + deriving (Eq, Show) + +data View = View + with + operator : Party + provider : Party + customer : Party + id : Id + timestamp : Time + listingId : Id + quantity : Instrument.Q + side : Side + price : Instrument.Q + collateralCid : ContractId Fungible.I + account : Account.K + observers : Parties + deriving (Eq, Show) + +interface Order where + viewtype View + -- ^ Interface view type. + + asRemovable : Removable.I + -- ^ Conversion to the `Removable` interface. + + fill : Fill -> Update FillResult + -- ^ Implementation of the `Fill` choice. + + approveInstruction : ApproveInstruction -> Update (ContractId Instruction.I) + -- ^ Implementation of the `ApproveInstruction` choice. + + choice Fill : FillResult + with + settlementFactoryCid : ContractId Factory.I + other : View + isResting : Bool + controller (view this).provider + do + fill this arg + + nonconsuming choice ApproveInstruction : ContractId Instruction.I + with + instructionCid : ContractId Instruction.I + controller (view this).provider + do + approveInstruction this arg + +-- | Type constraint for requiring templates to implement `Order`. +type Implementation t = (HasToInterface t Order, Removable.Implementation t) +class (Implementation t) => HasImplementation t +instance HasImplementation Order +instance HasToInterface Order Removable.I where _toInterface = asRemovable diff --git a/src/daml/Daml/Finance/App/Interface/Trading/Service.daml b/src/daml/Daml/Finance/App/Interface/Trading/Service.daml new file mode 100644 index 00000000..c5ece243 --- /dev/null +++ b/src/daml/Daml/Finance/App/Interface/Trading/Service.daml @@ -0,0 +1,93 @@ +-- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +-- SPDX-License-Identifier: Apache-2.0 + +module Daml.Finance.App.Interface.Trading.Service where + +import Daml.Finance.App.Interface.Base.Service qualified as Base (I, Implementation) +import Daml.Finance.App.Interface.Trading.Order qualified as Order (I, Side, View) +import Daml.Finance.App.Interface.Trading.CreateOrderRequest qualified as CreateOrderRequest (I) +import Daml.Finance.App.Interface.Trading.CancelOrderRequest qualified as CancelOrderRequest (I) +import Daml.Finance.Interface.Holding.Fungible qualified as Fungible (I) +import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (Q) +import Daml.Finance.Interface.Settlement.Factory qualified as Factory (I) +import Daml.Finance.Interface.Types.Common (AccountKey, Id, Parties) + +type I = Service + +type V = View + +data View = View + with + settlementFactoryCid : ContractId Factory.I + deriving (Eq, Show) + +interface Service where + viewtype V + + asBase : Base.I + -- ^ Conversion to base `Service` interface. + + requestCreateOrder : RequestCreateOrder -> Update (ContractId CreateOrderRequest.I) + -- ^ Implementation of the `RequestCreateOrder` choice. + + requestCancelOrder : RequestCancelOrder -> Update (ContractId CancelOrderRequest.I) + -- ^ Implementation of the `RequestCancelOrder` choice. + + createOrder : ContractId Service -> CreateOrder -> Update (Optional (ContractId Order.I, Order.View)) + -- ^ Implementation of the `CreateOrder` choice. + + cancelOrder : CancelOrder -> Update () + -- ^ Implementation of the `CancelOrder` choice. + + executeOrder : ExecuteOrder -> Update (Optional (ContractId Order.I, Order.View)) + -- ^ Implementation of the `ExecuteOrder` choice. + + nonconsuming choice RequestCreateOrder : ContractId CreateOrderRequest.I + with + id : Id + listingId : Id + quantity : Instrument.Q + price : Instrument.Q + side : Order.Side + collateralCid : ContractId Fungible.I + account : AccountKey + orderCids : [ContractId Order.I] + observers : Parties + controller (view $ asBase this).customer + do + requestCreateOrder this arg + + nonconsuming choice RequestCancelOrder : ContractId CancelOrderRequest.I + with + orderCid : ContractId Order.I + controller (view $ asBase this).customer + do + requestCancelOrder this arg + + nonconsuming choice CreateOrder : Optional (ContractId Order.I, Order.View) + with + createOrderRequestCid : ContractId CreateOrderRequest.I + controller (view $ asBase this).provider + do + createOrder this self arg + + nonconsuming choice CancelOrder : () + with + cancelOrderRequestCid : ContractId CancelOrderRequest.I + controller (view $ asBase this).provider + do + cancelOrder this arg + + nonconsuming choice ExecuteOrder : Optional (ContractId Order.I, Order.View) + with + orderCid : ContractId Order.I + orderCids : [ContractId Order.I] + controller (view $ asBase this).provider + do + executeOrder this arg + +-- | Type constraint for requiring templates to implement `Service`. +type Implementation t = (HasToInterface t Service, Base.Implementation t) +class (Implementation t) => HasImplementation t +instance HasImplementation Service +instance HasToInterface Service Base.I where _toInterface = asBase diff --git a/src/daml/Daml/Finance/App/Role/Exchange.daml b/src/daml/Daml/Finance/App/Role/Exchange.daml index 3ad34cca..b4734a2b 100644 --- a/src/daml/Daml/Finance/App/Role/Exchange.daml +++ b/src/daml/Daml/Finance/App/Role/Exchange.daml @@ -6,8 +6,8 @@ module Daml.Finance.App.Role.Exchange where import Daml.Finance.App.Interface.Base.Service qualified as Base (I, Terminate(..)) import Daml.Finance.App.Listing.Auto qualified as ListingAuto (Approve(..), Offer(..), Request, Service) import Daml.Finance.App.Listing.Service qualified as Listing (Approve(..), Offer(..), Request, Service) -import Daml.Finance.App.Trading.Auto.Service qualified as TradingAuto (Approve(..), Offer(..), Request, Service, Terminate(..)) -import Daml.Finance.App.Trading.Service qualified as Trading (Approve(..), Offer(..), Request, Service, Terminate(..)) +import Daml.Finance.App.Trading.Auto qualified as TradingAuto (Approve(..), Offer(..), Request, Service) +import Daml.Finance.App.Trading.Service qualified as Trading (Approve(..), Offer(..), Request, Service) import Daml.Finance.Interface.Settlement.Factory qualified as Factory (I) template Role @@ -41,7 +41,8 @@ template Role customer : Party controller provider do - exerciseByKey @Trading.Service (operator, provider, customer) Trading.Terminate with actor = provider + (serviceCid, _) <- fetchByKey @Trading.Service (operator, provider, customer) + exercise (toInterfaceContractId @Base.I serviceCid) Base.Terminate with actor = provider nonconsuming choice OfferTradingAutoService : ContractId TradingAuto.Offer with @@ -62,7 +63,8 @@ template Role customer : Party controller provider do - exerciseByKey @TradingAuto.Service (operator, provider, customer) TradingAuto.Terminate with actor = provider + (serviceCid, _) <- fetchByKey @TradingAuto.Service (operator, provider, customer) + exercise (toInterfaceContractId @Base.I serviceCid) Base.Terminate with actor = provider nonconsuming choice OfferListingService : ContractId Listing.Offer with diff --git a/src/daml/Daml/Finance/App/Trading/Auto.daml b/src/daml/Daml/Finance/App/Trading/Auto.daml new file mode 100644 index 00000000..442fa843 --- /dev/null +++ b/src/daml/Daml/Finance/App/Trading/Auto.daml @@ -0,0 +1,88 @@ +-- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +-- SPDX-License-Identifier: Apache-2.0 + +module Daml.Finance.App.Trading.Auto where + +import Daml.Finance.App.Interface.Base.Service qualified as Base (I, View(..)) +import Daml.Finance.App.Interface.Trading.Auto qualified as Auto (HasImplementation, I, RequestAndCancelOrder(..), RequestAndCreateOrder(..), View(..)) +import Daml.Finance.App.Interface.Trading.Service qualified as Service (CancelOrder(..), CreateOrder(..), I, RequestCancelOrder(..), RequestCreateOrder(..)) +import Daml.Finance.App.Trading.Service qualified as Service (T) + +type T = Service + +instance Auto.HasImplementation Service + +template Service + with + operator : Party + provider : Party + customer : Party + where + signatory operator, provider, customer + + key (operator, provider, customer) : (Party, Party, Party) + maintainer key._1 + + interface instance Base.I for Service where + view = Base.View with operator; provider; customer + terminate = pure () + + interface instance Auto.I for Service where + view = Auto.View + + asBase = toInterface @Base.I this + + requestAndCreateOrder Auto.RequestAndCreateOrder{id; listingId; quantity; price; side; collateralCid; account; orderCids; observers} = do + serviceCid <- toInterfaceContractId @Service.I . fst <$> fetchByKey @Service.T (operator, provider, customer) + createOrderRequestCid <- exercise serviceCid Service.RequestCreateOrder with id; listingId; quantity; price; side; collateralCid; account; orderCids; observers + exercise serviceCid Service.CreateOrder with createOrderRequestCid + + requestAndCancelOrder Auto.RequestAndCancelOrder{orderCid} = do + serviceCid <- toInterfaceContractId @Service.I . fst <$> fetchByKey @Service.T (operator, provider, customer) + cancelOrderRequestCid <- exercise serviceCid Service.RequestCancelOrder with orderCid + exercise serviceCid Service.CancelOrder with cancelOrderRequestCid + +template Offer + with + operator : Party + provider : Party + customer : Party + where + signatory operator, provider + observer customer + + choice Accept : ContractId Service + controller customer + do + create Service with .. + + choice Decline : () + controller customer + do + return () + + choice Withdraw : () + controller provider + do pure () + +template Request + with + customer : Party + provider : Party + where + signatory customer + + choice Cancel : () + controller customer + do pure () + + choice Reject : () + controller provider + do pure () + + choice Approve : ContractId Service + with + operator : Party + controller operator, provider + do + create Service with .. diff --git a/src/daml/Daml/Finance/App/Trading/Auto/Service.daml b/src/daml/Daml/Finance/App/Trading/Auto/Service.daml deleted file mode 100644 index a14edc46..00000000 --- a/src/daml/Daml/Finance/App/Trading/Auto/Service.daml +++ /dev/null @@ -1,99 +0,0 @@ --- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. --- SPDX-License-Identifier: Apache-2.0 - -module Daml.Finance.App.Trading.Auto.Service where - -import Daml.Finance.App.Trading.Model (Order, Side) -import Daml.Finance.App.Trading.Service qualified as S (CancelOrder(..), CreateOrder(..), RequestCancelOrder(..), RequestCreateOrder(..), Service) -import Daml.Finance.Interface.Account.Account qualified as Account (K) -import Daml.Finance.Interface.Holding.Fungible qualified as Fungible (I) -import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (Q) -import Daml.Finance.Interface.Types.Common (Id, Parties) - -template Service - with - operator : Party - provider : Party - customer : Party - where - signatory operator, provider, customer - - key (operator, provider, customer) : (Party, Party, Party) - maintainer key._1 - - nonconsuming choice RequestAndCreateOrder : Optional (ContractId Order, Order) - with - id : Id - listingId : Id - quantity : Instrument.Q - price : Instrument.Q - side : Side - collateralCid : ContractId Fungible.I - account : Account.K - orderCids : [ContractId Order] - observers : Parties - controller customer - do - createOrderRequestCid <- exerciseByKey @S.Service (operator, provider, customer) S.RequestCreateOrder with id; listingId; quantity; price; side; collateralCid; account; orderCids; observers - exerciseByKey @S.Service (operator, provider, customer) S.CreateOrder with createOrderRequestCid - - nonconsuming choice RequestAndCancelOrder : () - with - orderCid : ContractId Order - controller customer - do - cancelOrderRequestCid <- exerciseByKey @S.Service (operator, provider, customer) S.RequestCancelOrder with orderCid - exerciseByKey @S.Service (operator, provider, customer) S.CancelOrder with cancelOrderRequestCid - - choice Terminate : () - with - actor : Party - controller actor - do - assert $ actor == operator || actor == provider || actor == customer - pure () - -template Offer - with - operator : Party - provider : Party - customer : Party - where - signatory operator, provider - observer customer - - choice Accept : ContractId Service - controller customer - do - create Service with .. - - choice Decline : () - controller customer - do - return () - - choice Withdraw : () - controller provider - do pure () - -template Request - with - customer : Party - provider : Party - where - signatory customer - - choice Cancel : () - controller customer - do pure () - - choice Reject : () - controller provider - do pure () - - choice Approve : ContractId Service - with - operator : Party - controller operator, provider - do - create Service with .. diff --git a/src/daml/Daml/Finance/App/Trading/Model.daml b/src/daml/Daml/Finance/App/Trading/Model.daml index f755f327..5e1300c2 100644 --- a/src/daml/Daml/Finance/App/Trading/Model.daml +++ b/src/daml/Daml/Finance/App/Trading/Model.daml @@ -3,27 +3,20 @@ module Daml.Finance.App.Trading.Model where -import DA.Set (singleton) +import DA.Set (fromList, singleton) +import Daml.Finance.App.Interface.Common.Removable qualified as Removable (I, View(..)) +import Daml.Finance.App.Interface.Trading.CancelOrderRequest qualified as CancelOrderRequest (HasImplementation, I, View(..)) +import Daml.Finance.App.Interface.Trading.CreateOrderRequest qualified as CreateOrderRequest (HasImplementation, I, View(..)) +import Daml.Finance.App.Interface.Trading.Order qualified as Order (ApproveInstruction(..), Fill(..), FillResult(..), HasImplementation, I, Side(..), View(..)) import Daml.Finance.Interface.Account.Account qualified as Account (K) import Daml.Finance.Interface.Holding.Fungible qualified as Fungible (I, Split(..), SplitResult(..)) import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (Q, qty) -import Daml.Finance.Interface.Settlement.Factory qualified as Factory (I, Instruct(..)) -import Daml.Finance.Interface.Settlement.Instruction qualified as Instruction (I, Allocate(..), Approve(..)) -import Daml.Finance.Interface.Settlement.Batch qualified as Batch (I) +import Daml.Finance.Interface.Settlement.Factory qualified as Factory (Instruct(..)) +import Daml.Finance.Interface.Settlement.Instruction qualified as Instruction (Allocate(..), Approve(..)) import Daml.Finance.Interface.Settlement.Types (Allocation(Pledge), Approval(TakeDelivery), Step(..)) import Daml.Finance.Interface.Types.Common (Id(..), Parties) -data Side - = Buy - | Sell - deriving (Eq, Show) - -data FillResult = FillResult - with - orderOpt : Optional (ContractId Order, Order) - batchCid : ContractId Batch.I - instructionCid : ContractId Instruction.I - deriving (Eq, Show) +instance Order.HasImplementation Order template Order with @@ -34,7 +27,7 @@ template Order timestamp : Time listingId : Id quantity : Instrument.Q - side : Side + side : Order.Side price : Instrument.Q collateralCid : ContractId Fungible.I account : Account.K @@ -46,42 +39,54 @@ template Order key (operator, provider, id) : (Party, Party, Id) maintainer key._1 - choice Fill : FillResult - with - settlementFactoryCid : ContractId Factory.I - other : Order - isResting : Bool - controller provider - do + interface instance Removable.I for Order where + view = Removable.View with removers = fromList [operator, provider, customer] + + interface instance Order.I for Order where + view = Order.View with + operator + provider + customer + id + timestamp + listingId + quantity + side + price + collateralCid + account + observers + + asRemovable = toInterface @Removable.I this + + fill Order.Fill{settlementFactoryCid; other; isResting} = do let paid = if isResting then price.amount else other.price.amount delivered = min quantity.amount other.quantity.amount - amount = if side == Buy then paid * delivered else delivered + amount = if side == Order.Buy then paid * delivered else delivered remaining = quantity.amount - min quantity.amount other.quantity.amount - deliverable = if side == Buy then price.unit else quantity.unit + deliverable = if side == Order.Buy then price.unit else quantity.unit step = Step with sender = customer; receiver = other.customer; quantity = Instrument.qty amount deliverable (batchCid, [instructionCid]) <- exercise settlementFactoryCid Factory.Instruct with instructors = singleton provider; id; settlers = singleton provider; steps = [step]; contextId = Some id; description = show id Fungible.SplitResult [splitCid] restCidOpt <- exercise collateralCid Fungible.Split with amounts = [ amount ] if remaining == 0.0 then do instructionCid <- fst <$> exercise instructionCid Instruction.Allocate with actors = singleton provider; allocation = Pledge $ toInterfaceContractId splitCid - pure FillResult with orderOpt = None; batchCid; instructionCid + pure Order.FillResult with orderOpt = None; batchCid; instructionCid else do instructionCid <- fst <$> exercise instructionCid Instruction.Allocate with actors = singleton provider; allocation = Pledge $ toInterfaceContractId splitCid case restCidOpt of Some restCid -> do let new = this with quantity.amount = remaining; collateralCid = restCid - newCid <- create new - pure FillResult with orderOpt = Some (newCid, new); batchCid; instructionCid + newCid <- toInterfaceContractId <$> create new + pure Order.FillResult with orderOpt = Some (newCid, view $ toInterface @Order.I new); batchCid; instructionCid None -> fail "Insufficient collateral - this should never happen" - nonconsuming choice ApproveInstruction : ContractId Instruction.I - with - instructionCid : ContractId Instruction.I - controller provider - do + approveInstruction Order.ApproveInstruction{instructionCid} = do exercise instructionCid Instruction.Approve with actors = singleton provider; approval = TakeDelivery account +instance CreateOrderRequest.HasImplementation CreateOrderRequest + template CreateOrderRequest with operator : Party @@ -91,11 +96,11 @@ template CreateOrderRequest timestamp : Time listingId : Id quantity : Instrument.Q - side : Side + side : Order.Side price : Instrument.Q collateralCid : ContractId Fungible.I account : Account.K - orderCids : [ContractId Order] + orderCids : [ContractId Order.I] observers : Parties where signatory operator, provider, customer @@ -103,11 +108,46 @@ template CreateOrderRequest key (operator, provider, id) : (Party, Party, Id) maintainer key._1 + interface instance Removable.I for CreateOrderRequest where + view = Removable.View with removers = fromList [operator, provider, customer] + + interface instance CreateOrderRequest.I for CreateOrderRequest where + view = CreateOrderRequest.View with + operator + provider + customer + id + timestamp + listingId + quantity + side + price + collateralCid + account + orderCids + observers + + asRemovable = toInterface @Removable.I this + +instance CancelOrderRequest.HasImplementation CancelOrderRequest + template CancelOrderRequest with provider : Party customer : Party operator : Party - orderCid : ContractId Order + orderCid : ContractId Order.I where signatory provider, customer + + interface instance Removable.I for CancelOrderRequest where + view = Removable.View with removers = fromList [operator, provider, customer] + + interface instance CancelOrderRequest.I for CancelOrderRequest where + view = CancelOrderRequest.View with + operator + provider + customer + orderCid + + asRemovable = toInterface @Removable.I this diff --git a/src/daml/Daml/Finance/App/Trading/Service.daml b/src/daml/Daml/Finance/App/Trading/Service.daml index 17e05bdb..5b3faab7 100644 --- a/src/daml/Daml/Finance/App/Trading/Service.daml +++ b/src/daml/Daml/Finance/App/Trading/Service.daml @@ -6,11 +6,15 @@ module Daml.Finance.App.Trading.Service where import DA.Action (foldlA, when) import DA.Optional (isNone) import DA.Set (insert, singleton) -import Daml.Finance.App.Trading.Model (ApproveInstruction(..), CreateOrderRequest(..), CancelOrderRequest(..), Fill(..), FillResult(..), Order(..), Side(..)) -import Daml.Finance.App.Util (fetchAndArchive) -import Daml.Finance.Interface.Account.Account qualified as Account (K, exerciseInterfaceByKey) +import Daml.Finance.App.Interface.Common.Util (fetchAndRemove) +import Daml.Finance.App.Interface.Base.Service qualified as Base (I, View(..)) +import Daml.Finance.App.Interface.Trading.CancelOrderRequest qualified as CancelOrderRequest (View(..)) +import Daml.Finance.App.Interface.Trading.CreateOrderRequest qualified as CreateOrderRequest (View(..)) +import Daml.Finance.App.Interface.Trading.Order qualified as Order (ApproveInstruction(..), Fill(..), FillResult(..), I, Side(..), View(..)) +import Daml.Finance.App.Interface.Trading.Service qualified as Service (CancelOrder(..), CreateOrder(..), ExecuteOrder(..), HasImplementation, I, RequestCancelOrder(..), RequestCreateOrder(..), View(..)) +import Daml.Finance.App.Trading.Model qualified as Model (CancelOrderRequest(..), CreateOrderRequest(..), Order(..)) +import Daml.Finance.Interface.Account.Account qualified as Account (exerciseInterfaceByKey) import Daml.Finance.Interface.Holding.Fungible qualified as Fungible (I) -import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (Q) import Daml.Finance.Interface.Holding.Base qualified as Holding (Acquire(..), I, LockType(..), Release(..)) import Daml.Finance.Interface.Account.Util (getAccount) import Daml.Finance.Interface.Util.Disclosure qualified as Disclosure (I, AddObservers(..), RemoveObservers(..)) @@ -18,7 +22,10 @@ import Daml.Finance.Interface.Settlement.Factory qualified as Factory (I) import Daml.Finance.Interface.Settlement.Instruction qualified as Instruction (Approve(..)) import Daml.Finance.Interface.Settlement.Batch qualified as Batch (Settle(..)) import Daml.Finance.Interface.Settlement.Types (Approval(TakeDelivery)) -import Daml.Finance.Interface.Types.Common (Id, Parties) + +type T = Service + +instance Service.HasImplementation Service template Service with @@ -32,77 +39,58 @@ template Service key (operator, provider, customer) : (Party, Party, Party) maintainer key._1 - nonconsuming choice RequestCreateOrder : ContractId CreateOrderRequest - with - id : Id - listingId : Id - quantity : Instrument.Q - price : Instrument.Q - side : Side - collateralCid : ContractId Fungible.I - account : Account.K - observers : Parties - orderCids : [ContractId Order] - controller customer - do + interface instance Base.I for Service where + view = Base.View with operator; provider; customer + terminate = pure () + + interface instance Service.I for Service where + view = Service.View with settlementFactoryCid + + asBase = toInterface @Base.I this + + requestCreateOrder Service.RequestCreateOrder{id; listingId; quantity; price; side; collateralCid; account; orderCids; observers} = do timestamp <- getTime collateral <- fetch collateralCid disclosedCollateralCid <- coerceContractId <$> exercise (coerceContractId collateralCid : ContractId Disclosure.I) Disclosure.AddObservers with disclosers = singleton customer; observersToAdd = (show id, provider `insert` observers) Account.exerciseInterfaceByKey @Disclosure.I (getAccount collateral) customer Disclosure.AddObservers with disclosers = singleton customer; observersToAdd = (show id, provider `insert` observers) Account.exerciseInterfaceByKey @Disclosure.I account customer Disclosure.AddObservers with disclosers = singleton customer; observersToAdd = (show id, provider `insert` observers) - create CreateOrderRequest with operator; provider; customer; id; timestamp; listingId; quantity; price; side; collateralCid = disclosedCollateralCid; account; orderCids; observers + toInterfaceContractId <$> create Model.CreateOrderRequest with operator; provider; customer; id; timestamp; listingId; quantity; price; side; collateralCid = disclosedCollateralCid; account; orderCids; observers - nonconsuming choice RequestCancelOrder : ContractId CancelOrderRequest - with - orderCid : ContractId Order - controller customer - do - create CancelOrderRequest with operator; provider; customer; orderCid + requestCancelOrder Service.RequestCancelOrder{orderCid} = do + toInterfaceContractId <$> create Model.CancelOrderRequest with operator; provider; customer; orderCid - nonconsuming choice CreateOrder : Optional (ContractId Order, Order) - with - createOrderRequestCid : ContractId CreateOrderRequest - controller provider - do - CreateOrderRequest{operator; provider; customer; id; timestamp; listingId; quantity; price; side; collateralCid; account; orderCids; observers} <- fetchAndArchive createOrderRequestCid + createOrder self Service.CreateOrder{createOrderRequestCid} = do + CreateOrderRequest.View{operator; provider; customer; id; timestamp; listingId; quantity; price; side; collateralCid; account; orderCids; observers} <- view <$> fetchAndRemove createOrderRequestCid lockedCollateralCid : ContractId Fungible.I <- coerceContractId <$> exercise (toInterfaceContractId collateralCid : ContractId Holding.I) Holding.Acquire with newLockers = singleton provider; context = show id; lockType = Holding.Semaphore - orderCid <- create Order with operator; provider; customer; id; timestamp; listingId; quantity; price; side; collateralCid = lockedCollateralCid; account; observers - exercise self ExecuteOrder with orderCid; orderCids + orderCid <- toInterfaceContractId <$> create Model.Order with operator; provider; customer; id; timestamp; listingId; quantity; price; side; collateralCid = lockedCollateralCid; account; observers + exercise self Service.ExecuteOrder with orderCid; orderCids - nonconsuming choice CancelOrder : () - with - cancelOrderRequestCid : ContractId CancelOrderRequest - controller provider - do - CancelOrderRequest{orderCid} <- fetchAndArchive cancelOrderRequestCid - order <- fetchAndArchive orderCid + cancelOrder Service.CancelOrder{cancelOrderRequestCid} = do + CancelOrderRequest.View{orderCid} <- view <$> fetchAndRemove cancelOrderRequestCid + order <- view <$> fetchAndRemove orderCid exercise (toInterfaceContractId order.collateralCid : ContractId Holding.I) Holding.Release with context = show order.id pure () - nonconsuming choice ExecuteOrder : Optional (ContractId Order, Order) - with - orderCid : ContractId Order - orderCids : [ContractId Order] - controller provider - do - order <- fetch orderCid - orders <- filter (\(_, o) -> o.customer /= customer && if order.side == Buy then o.side == Sell && o.price.amount <= order.price.amount else o.side == Buy && o.price.amount >= order.price.amount) . zip orderCids <$> mapA fetch orderCids + executeOrder Service.ExecuteOrder{orderCid; orderCids} = do + order <- view <$> fetch orderCid + orderViews <- zip orderCids <$> mapA (fmap view . fetch) orderCids + let orders = filter (\(_, o) -> o.customer /= customer && if order.side == Order.Buy then o.side == Order.Sell && o.price.amount <= order.price.amount else o.side == Order.Buy && o.price.amount >= order.price.amount) orderViews let - match : Optional (ContractId Order, Order) -> (ContractId Order, Order) -> Update (Optional (ContractId Order, Order)) + match : Optional (ContractId Order.I, Order.View) -> (ContractId Order.I, Order.View) -> Update (Optional (ContractId Order.I, Order.View)) match myOpt (otherCid, other) = case myOpt of None -> do pure None - Some (myCid, my) | my.side == Buy && my.price.amount < other.price.amount || my.side == Sell && my.price.amount > other.price.amount -> do + Some (myCid, my) | my.side == Order.Buy && my.price.amount < other.price.amount || my.side == Order.Sell && my.price.amount > other.price.amount -> do pure myOpt Some (myCid, my) -> do myCollateral <- fetch my.collateralCid otherCollateral <- fetch other.collateralCid - FillResult{orderOpt; batchCid; instructionCid} <- exercise myCid Fill with settlementFactoryCid; other; isResting = False - exercise otherCid ApproveInstruction with instructionCid + Order.FillResult{orderOpt; batchCid; instructionCid} <- exercise myCid Order.Fill with settlementFactoryCid; other; isResting = False + exercise otherCid Order.ApproveInstruction with instructionCid [transferableCid] <- exercise batchCid Batch.Settle with actors = singleton provider exercise (toInterfaceContractId transferableCid : ContractId Holding.I) Holding.Release with context = show my.id - FillResult{orderOpt = otherOpt; batchCid; instructionCid} <- exercise otherCid Fill with settlementFactoryCid; other = my; isResting = True + Order.FillResult{orderOpt = otherOpt; batchCid; instructionCid} <- exercise otherCid Order.Fill with settlementFactoryCid; other = my; isResting = True exercise instructionCid Instruction.Approve with actors = singleton provider; approval = TakeDelivery my.account [transferableCid] <- exercise batchCid Batch.Settle with actors = singleton provider exercise (toInterfaceContractId transferableCid : ContractId Holding.I) Holding.Release with context = show other.id @@ -117,14 +105,6 @@ template Service pure orderOpt foldlA match (Some (orderCid, order)) orders - choice Terminate : () - with - actor : Party - controller actor - do - assert $ actor == operator || actor == provider || actor == customer - pure () - template Offer with operator : Party diff --git a/src/daml/Daml/Finance/App/Util.daml b/src/daml/Daml/Finance/App/Util.daml deleted file mode 100644 index e14e91cc..00000000 --- a/src/daml/Daml/Finance/App/Util.daml +++ /dev/null @@ -1,11 +0,0 @@ --- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. --- SPDX-License-Identifier: Apache-2.0 - -module Daml.Finance.App.Util where - --- | Fetches a contract, archives it and returns its value. -fetchAndArchive : Template a => ContractId a -> Update a -fetchAndArchive cid = do - c <- fetch cid - archive cid - return c diff --git a/src/daml/Daml/Finance/Setup/Util/Service.daml b/src/daml/Daml/Finance/Setup/Util/Service.daml index 002f485c..f24f1178 100644 --- a/src/daml/Daml/Finance/Setup/Util/Service.daml +++ b/src/daml/Daml/Finance/Setup/Util/Service.daml @@ -28,14 +28,16 @@ import Daml.Finance.App.Interface.Listing.Service qualified as Listing (I) import Daml.Finance.App.Interface.Settlement.Service qualified as Settlement (I) import Daml.Finance.App.Interface.Structuring.Auto qualified as StructuringAuto (I) import Daml.Finance.App.Interface.Structuring.Service qualified as Structuring (I) +import Daml.Finance.App.Interface.Trading.Auto qualified as TradingAuto (I) +import Daml.Finance.App.Interface.Trading.Service qualified as Trading (I) import Daml.Finance.App.Issuance.Auto qualified as IssuanceAuto (Accept(..)) import Daml.Finance.App.Issuance.BackToBack qualified as BackToBack (Accept(..)) import Daml.Finance.App.Issuance.Service qualified as Issuance (Accept(..)) import Daml.Finance.App.Listing.Auto qualified as ListingAuto (Accept(..)) import Daml.Finance.App.Listing.Service qualified as Listing (Accept(..)) import Daml.Finance.App.Lifecycle.Service qualified as Lifecycle (Accept(..)) -import Daml.Finance.App.Trading.Auto.Service qualified as TradingAuto (Accept(..), Service) -import Daml.Finance.App.Trading.Service qualified as Trading (Accept(..), Service) +import Daml.Finance.App.Trading.Auto qualified as TradingAuto (Accept(..)) +import Daml.Finance.App.Trading.Service qualified as Trading (Accept(..)) import Daml.Finance.App.Lending.Service qualified as Lending (Accept(..)) import Daml.Finance.App.Distribution.Auction.Auto qualified as AuctionAuto (Accept(..)) import Daml.Finance.App.Distribution.Auction.Service qualified as Auction (Accept(..)) @@ -125,15 +127,15 @@ createLifecycleService operator custodian customer public = do offerCid <- submit custodian do exerciseByKeyCmd @Custodian.Role (operator, custodian) Custodian.OfferLifecycleService with .. toInterfaceContractId <$> submit customer do exerciseCmd offerCid Lifecycle.Accept -createTradingService : Party -> Party -> Party -> ContractId Settlement.Factory -> Script (ContractId Trading.Service) +createTradingService : Party -> Party -> Party -> ContractId Settlement.Factory -> Script (ContractId Trading.I) createTradingService operator exchange customer settlementFactoryCid = do offerCid <- submit exchange do exerciseByKeyCmd @Exchange.Role (operator, exchange) Exchange.OfferTradingService with customer; settlementFactoryCid - submit customer do exerciseCmd offerCid Trading.Accept + toInterfaceContractId <$> submit customer do exerciseCmd offerCid Trading.Accept -createTradingAutoService : Party -> Party -> Party -> Script (ContractId TradingAuto.Service) +createTradingAutoService : Party -> Party -> Party -> Script (ContractId TradingAuto.I) createTradingAutoService operator exchange customer = do offerCid <- submit exchange do exerciseByKeyCmd @Exchange.Role (operator, exchange) Exchange.OfferTradingAutoService with .. - submit customer do exerciseCmd offerCid TradingAuto.Accept + toInterfaceContractId <$> submit customer do exerciseCmd offerCid TradingAuto.Accept createListingService : Party -> Party -> Party -> Script (ContractId Listing.I) createListingService operator exchange customer = do diff --git a/src/daml/Daml/Finance/Setup/Util/Workflow.daml b/src/daml/Daml/Finance/Setup/Util/Workflow.daml index 5203349f..7f87bf6b 100644 --- a/src/daml/Daml/Finance/Setup/Util/Workflow.daml +++ b/src/daml/Daml/Finance/Setup/Util/Workflow.daml @@ -29,12 +29,14 @@ import Daml.Finance.App.Interface.Issuance.Service qualified as IssuanceService import Daml.Finance.App.Interface.Lifecycle.Service qualified as LifecycleService (I, DeclareDividend(..), DeclareStockSplit(..), DeclareReplacement(..)) import Daml.Finance.App.Interface.Listing.Listing qualified as Listing (I) import Daml.Finance.App.Interface.Listing.Service qualified as ListingService (I, List(..), RequestListing(..)) +import Daml.Finance.App.Interface.Trading.Order qualified as Order (I, Side(..), View) +import Daml.Finance.App.Interface.Trading.Service qualified as Trading (CreateOrder(..), I, RequestCreateOrder(..)) import Daml.Finance.App.Issuance.Service qualified as Issuance (Service) import Daml.Finance.App.Lifecycle.Service qualified as Lifecycle (Service) import Daml.Finance.App.Listing.Model qualified as Listing (T) import Daml.Finance.App.Listing.Service qualified as Listing (Service) -import Daml.Finance.App.Trading.Model qualified as Trading (Order, Side(..)) -import Daml.Finance.App.Trading.Service qualified as Trading (CreateOrder(..), RequestCreateOrder(..), Service) +import Daml.Finance.App.Trading.Model qualified as Trading (Order) +import Daml.Finance.App.Trading.Service qualified as Trading (T) import Daml.Finance.Data.Observable.Observation qualified as Data (Observation(..)) import Daml.Finance.Data.Reference.HolidayCalendar qualified as Data (HolidayCalendar(..)) import Daml.Finance.Data.Time.DateClock qualified as Data (DateClock(..)) @@ -219,23 +221,24 @@ list operator provider customer listingId description tradedInstrument quotedIns listingRequestCid <- submit customer do exerciseCmd (toInterfaceContractId @ListingService.I listingServiceCid) ListingService.RequestListing with listingId; description; tradedInstrument; quotedInstrument; observers submit provider do exerciseCmd (toInterfaceContractId @ListingService.I listingServiceCid) ListingService.List with listingRequestCid -createOrder : Party -> Party -> Party -> Party -> Id -> Trading.Side -> Instrument.Q -> Instrument.Q -> Parties -> Script (Optional (ContractId Trading.Order, Trading.Order)) +createOrder : Party -> Party -> Party -> Party -> Id -> Order.Side -> Instrument.Q -> Instrument.Q -> Parties -> Script (Optional (ContractId Order.I, Order.View)) createOrder operator provider customer public id side quantity price observers = do listingId <- (.id) . snd . head <$> queryFilter @Listing.T observers (\l -> l.tradedInstrument == quantity.unit && l.quotedInstrument == price.unit) let - depository = if side == Trading.Buy then quantity.unit.depository else price.unit.depository - requiredQuantity = if side == Trading.Buy then price with amount = price.amount * quantity.amount else quantity + depository = if side == Order.Buy then quantity.unit.depository else price.unit.depository + requiredQuantity = if side == Order.Buy then price with amount = price.amount * quantity.amount else quantity account <- key . snd . head <$> queryFilter @Account.R customer (\a -> a.accountView.custodian == depository) holdingCid <- coerceContractId <$> getHolding customer requiredQuantity - orderCids <- map fst <$> queryFilter @Trading.Order observers (\o -> o.listingId == listingId) - createOrderRequestCid <- submit customer do exerciseByKeyCmd @Trading.Service (operator, provider, customer) Trading.RequestCreateOrder with id; listingId; quantity; price; side; collateralCid = holdingCid; account; orderCids; observers - submitMulti [provider] [public] do exerciseByKeyCmd @Trading.Service (operator, provider, customer) Trading.CreateOrder with createOrderRequestCid + orderCids <- map (toInterfaceContractId @Order.I . fst) <$> queryFilter @Trading.Order observers (\o -> o.listingId == listingId) + Some (serviceCid, _) <- queryContractKey @Trading.T customer (operator, provider, customer) + createOrderRequestCid <- submit customer do exerciseCmd (toInterfaceContractId @Trading.I serviceCid) Trading.RequestCreateOrder with id; listingId; quantity; price; side; collateralCid = holdingCid; account; orderCids; observers + submitMulti [provider] [public] do exerciseCmd (toInterfaceContractId @Trading.I serviceCid) Trading.CreateOrder with createOrderRequestCid -createBidOrder : Party -> Party -> Party -> Party -> Id -> Instrument.Q -> Instrument.Q -> Parties -> Script (Optional (ContractId Trading.Order, Trading.Order)) -createBidOrder operator provider customer public id = createOrder operator provider customer public id Trading.Buy +createBidOrder : Party -> Party -> Party -> Party -> Id -> Instrument.Q -> Instrument.Q -> Parties -> Script (Optional (ContractId Order.I, Order.View)) +createBidOrder operator provider customer public id = createOrder operator provider customer public id Order.Buy -createAskOrder : Party -> Party -> Party -> Party -> Id -> Instrument.Q -> Instrument.Q -> Parties -> Script (Optional (ContractId Trading.Order, Trading.Order)) -createAskOrder operator provider customer public id = createOrder operator provider customer public id Trading.Sell +createAskOrder : Party -> Party -> Party -> Party -> Id -> Instrument.Q -> Instrument.Q -> Parties -> Script (Optional (ContractId Order.I, Order.View)) +createAskOrder operator provider customer public id = createOrder operator provider customer public id Order.Sell createAuction : Party -> Party -> Party -> Party -> Id -> Text -> Instrument.Q -> InstrumentKey -> Decimal -> ContractId Fungible.I -> AccountKey -> Script (ContractId Auction.I) createAuction operator provider customer public auctionId description quantity currency floor collateralCid receivableAccount = do From 4c84a6d8cfba3c0d2ac7409a517320ab5a5a106a Mon Sep 17 00:00:00 2001 From: Georg Schneider Date: Wed, 21 Dec 2022 13:33:34 +0100 Subject: [PATCH 13/31] SDK update --- daml.yaml | 2 +- package/main/daml/Daml.Finance.App/daml.yaml | 2 +- package/main/daml/Daml.Finance.Setup/daml.yaml | 2 +- ui/package.json | 6 +++--- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/daml.yaml b/daml.yaml index 9a8ed828..26bcd701 100644 --- a/daml.yaml +++ b/daml.yaml @@ -1,7 +1,7 @@ # Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. # SPDX-License-Identifier: Apache-2.0 -sdk-version: 2.5.0-snapshot.20221010.10736.0.2f453a14 +sdk-version: 2.6.0-snapshot.20221218.11169.0.9d007b31 name: daml-finance-app version: 0.1.5 source: src/daml diff --git a/package/main/daml/Daml.Finance.App/daml.yaml b/package/main/daml/Daml.Finance.App/daml.yaml index 5c6b3665..2add6bac 100644 --- a/package/main/daml/Daml.Finance.App/daml.yaml +++ b/package/main/daml/Daml.Finance.App/daml.yaml @@ -1,7 +1,7 @@ # Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. # SPDX-License-Identifier: Apache-2.0 -sdk-version: 2.5.0-snapshot.20221010.10736.0.2f453a14 +sdk-version: 2.6.0-snapshot.20221218.11169.0.9d007b31 name: daml-finance-app version: 0.0.1 source: daml diff --git a/package/main/daml/Daml.Finance.Setup/daml.yaml b/package/main/daml/Daml.Finance.Setup/daml.yaml index b17efa67..03dd4c69 100644 --- a/package/main/daml/Daml.Finance.Setup/daml.yaml +++ b/package/main/daml/Daml.Finance.Setup/daml.yaml @@ -1,7 +1,7 @@ # Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. # SPDX-License-Identifier: Apache-2.0 -sdk-version: 2.5.0-snapshot.20221010.10736.0.2f453a14 +sdk-version: 2.6.0-snapshot.20221218.11169.0.9d007b31 name: daml-finance-app-setup version: 0.0.1 source: daml diff --git a/ui/package.json b/ui/package.json index f284b552..57b7401b 100644 --- a/ui/package.json +++ b/ui/package.json @@ -19,9 +19,9 @@ "@daml.js/daml-finance-interface-settlement": "file:daml.js/eee5de887daab47f57f46612c0e12c196cb24d89cf3fce319143088fa2765c64", "@daml.js/daml-finance-interface-types": "file:daml.js/87cb7a623037fd06919af3cba15bc4a9430d315bbb02294a54cad7b61d48f01f", "@daml.js/daml-finance-interface-util": "file:daml.js/200ca261e5eb1d239e728fc65421e5b2f693c6f738d5ccb8c6a5a40966a27ac5", - "@daml/ledger": "2.5.0-snapshot.20221010.10736.0.2f453a14", - "@daml/react": "2.5.0-snapshot.20221010.10736.0.2f453a14", - "@daml/types": "2.5.0-snapshot.20221010.10736.0.2f453a14", + "@daml/ledger": "2.6.0-snapshot.20221218.11169.0.9d007b31", + "@daml/react": "2.6.0-snapshot.20221218.11169.0.9d007b31", + "@daml/types": "2.6.0-snapshot.20221218.11169.0.9d007b31", "@emotion/react": "^11.5.0", "@emotion/styled": "^11.3.0", "@mui/icons-material": "^5.0.5", From 374058f55725379cc86a43659fe0f45460e5c63b Mon Sep 17 00:00:00 2001 From: Georg Schneider Date: Wed, 21 Dec 2022 15:32:55 +0100 Subject: [PATCH 14/31] Add interfaces for dex service --- .../Decentralized/Exchange/FlashSwapPipe.daml | 21 +++++ .../App/Decentralized/Exchange/Service.daml | 74 +++++++-------- .../Exchange/FlashSwapAction.daml} | 18 ++-- .../Decentralized/Exchange/Service.daml | 90 +++++++++++++++++++ .../Decentralized/Exchange/Types.daml} | 6 +- .../Setup/Scenario/DecentralizedFinance.daml | 10 +-- src/daml/Daml/Finance/Setup/Util/Service.daml | 12 +-- 7 files changed, 162 insertions(+), 69 deletions(-) create mode 100644 src/daml/Daml/Finance/App/Decentralized/Exchange/FlashSwapPipe.daml rename src/daml/Daml/Finance/App/{Decentralized/Exchange/Interface.daml => Interface/Decentralized/Exchange/FlashSwapAction.daml} (85%) create mode 100644 src/daml/Daml/Finance/App/Interface/Decentralized/Exchange/Service.daml rename src/daml/Daml/Finance/App/{Decentralized/Exchange/Model.daml => Interface/Decentralized/Exchange/Types.daml} (78%) diff --git a/src/daml/Daml/Finance/App/Decentralized/Exchange/FlashSwapPipe.daml b/src/daml/Daml/Finance/App/Decentralized/Exchange/FlashSwapPipe.daml new file mode 100644 index 00000000..45dbc31d --- /dev/null +++ b/src/daml/Daml/Finance/App/Decentralized/Exchange/FlashSwapPipe.daml @@ -0,0 +1,21 @@ +-- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +-- SPDX-License-Identifier: Apache-2.0 + +module Daml.Finance.App.Decentralized.Exchange.FlashSwapPipe where + +import Daml.Finance.App.Interface.Decentralized.Exchange.FlashSwapAction qualified as FlashSwapAction (I, View(..)) +import Daml.Finance.Interface.Holding.Base qualified as Holding (I) + +type T = FlashSwapPipe + +-- Example of a FlashSwapAction template (used for a normal DEX Swap) +template FlashSwapPipe with + provider : Party + outCid : ContractId Holding.I + where + signatory provider + + interface instance FlashSwapAction.I for FlashSwapPipe where + view = FlashSwapAction.View {} + executeAction holdingCid = pure (outCid, [holdingCid]) + diff --git a/src/daml/Daml/Finance/App/Decentralized/Exchange/Service.daml b/src/daml/Daml/Finance/App/Decentralized/Exchange/Service.daml index 15d540d8..aab1e16b 100644 --- a/src/daml/Daml/Finance/App/Decentralized/Exchange/Service.daml +++ b/src/daml/Daml/Finance/App/Decentralized/Exchange/Service.daml @@ -3,11 +3,14 @@ module Daml.Finance.App.Decentralized.Exchange.Service where -import Daml.Finance.App.Decentralized.Exchange.Interface (ExecuteAction(..), FlashSwapAction, FlashSwapPipe(..)) -import Daml.Finance.App.Decentralized.Exchange.Model (Pool, switchIf) +import Daml.Finance.App.Decentralized.Exchange.FlashSwapPipe (FlashSwapPipe(..)) +import Daml.Finance.App.Interface.Base.Service qualified as Base (I, View(..)) +import Daml.Finance.App.Interface.Decentralized.Exchange.Service qualified as Service (Deposit(..), FlashSwap(..), HasImplementation, I, Swap(..), View(..), Withdraw(..)) +import Daml.Finance.App.Interface.Decentralized.Exchange.FlashSwapAction qualified as FlashSwapAction (ExecuteAction(..), I) +import Daml.Finance.App.Interface.Decentralized.Exchange.Types (Pool) import Daml.Finance.Interface.Account.Account qualified as Account (Credit(..), Debit(..), I, exerciseInterfaceByKey) import Daml.Finance.Interface.Holding.Base qualified as Holding (I) -import Daml.Finance.Interface.Holding.Fungible qualified as Fungible (I, Merge(..), Split(..), SplitResult(..)) +import Daml.Finance.Interface.Holding.Fungible qualified as Fungible (Merge(..), Split(..), SplitResult(..)) import Daml.Finance.Interface.Holding.Transferable qualified as Transferable (I, Transfer(..)) import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (Q, qty) import Daml.Finance.Interface.Types.Common (AccountKey, Id) @@ -59,6 +62,10 @@ import DA.Set (fromList, singleton) -} +type T = Service + +instance Service.HasImplementation Service + template Service with consortium : Party @@ -78,6 +85,8 @@ template Service ensure p1.quantity.amount > 0.0 && p2.quantity.amount > 0.0 && shares.amount > 0.0 let + switchIf cond (x, y) = if cond then (y, x) else (x, y) + -- AMM rule constantProductFormula delta_x x y: (Decimal, Decimal, Decimal) = let @@ -94,7 +103,7 @@ template Service (xAsset : Instrument.Q) (xLP : Pool) (yLP : Pool) - (flashSwapActionCid : ContractId FlashSwapAction) = + (flashSwapActionCid : ContractId FlashSwapAction.I) = do -- AMM let (x_new, y_new, y_delta) = constantProductFormula xAsset.amount xLP.quantity.amount yLP.quantity.amount @@ -107,7 +116,7 @@ template Service yHolding <- view <$> fetch yHoldingCid -- execute flashSwapAction and get X - (xFungibleCid, sideEffectCids) <- exercise flashSwapActionCid ExecuteAction with + (xFungibleCid, sideEffectCids) <- exercise flashSwapActionCid FlashSwapAction.ExecuteAction with actors = singleton actor consumedQuantity = Instrument.qty yHolding.amount yHolding.instrument producedQuantity = xAsset @@ -128,14 +137,17 @@ template Service fungibleCid = yFungibleCid_new return (xLP_new, yLP_new, sideEffectCids) - postconsuming choice Deposit : (ContractId Service, ContractId Holding.I) - with - actor : Party - fungible1Cid: ContractId Fungible.I - fungible2Cid: ContractId Fungible.I - shareAccount : AccountKey - controller actor - do + interface instance Base.I for Service where + view = Base.View with operator = consortium; provider = consortium; customer = consortium + + terminate = pure () + + interface instance Service.I for Service where + view = Service.View with consortium; public; id; description; shares; p1; p2 + + asBase = toInterface @Base.I this + + deposit self Service.Deposit{actor; fungible1Cid; fungible2Cid; shareAccount} = do t1 <- view <$> fetch (toInterfaceContractId @Holding.I fungible1Cid) t2 <- view <$> fetch (toInterfaceContractId @Holding.I fungible2Cid) assertMsg "custodians must match" $ t1.account.custodian == p1.account.custodian && t2.account.custodian == p2.account.custodian @@ -165,20 +177,14 @@ template Service shareCid <- Account.exerciseInterfaceByKey @Account.I shareAccount actor Account.Credit with quantity = (shares with amount = newShareAmount - shares.amount) -- recreate Dex - dexCid <- create this with + archive $ fromInterfaceContractId @Service self + dexCid <- toInterfaceContractId <$> create this with shares = shares with amount = newShareAmount p1 = p1 with quantity.amount = p1.quantity.amount + t1.amount; fungibleCid = lp1_cid p2 = p2 with quantity.amount = p2.quantity.amount + quantity2_needed; fungibleCid = lp2_cid return (dexCid, shareCid) - postconsuming choice Withdraw : (ContractId Service, ContractId Fungible.I, ContractId Fungible.I) - with - actor : Party - shareCid : ContractId Fungible.I - p1Account : AccountKey - p2Account : AccountKey - controller actor - do + withdraw self Service.Withdraw{actor; shareCid; p1Account; p2Account} = do share <- view <$> fetch (toInterfaceContractId @Holding.I shareCid) assertMsg "liquidity share matches" (share.instrument == shares.unit && share.account.custodian == consortium) @@ -198,20 +204,14 @@ template Service -- split2Cid <- exercise fungible2Cid SetObservers with newObservers = S.empty -- TODO: check if necessary p2HoldingCid <- coerceContractId <$> exercise (toInterfaceContractId @Transferable.I fungible2Cid) Transferable.Transfer with actors = singleton consortium; newOwnerAccount = p2Account -- recreate dex (not allowing to drain) - dexCid <- create this with + archive $ fromInterfaceContractId @Service self + dexCid <- toInterfaceContractId <$> create this with shares = shares with amount = newShareAmount p1 = p1 with quantity.amount = p1.quantity.amount - p1Amount; fungibleCid = lp1_cid p2 = p2 with quantity.amount = p2.quantity.amount - p2Amount; fungibleCid = lp2_cid return (dexCid, p1HoldingCid, p2HoldingCid) - nonconsuming choice FlashSwap : (ContractId Service, [ContractId Holding.I]) - with - actor : Party - xAsset : Instrument.Q - yAccount : AccountKey - actionCid : ContractId FlashSwapAction - controller actor - do + flashSwap self Service.FlashSwap{actor; xAsset; yAccount; actionCid} = do assertMsg "asset matches" $ xAsset.unit == p1.quantity.unit || xAsset.unit == p2.quantity.unit -- switch to X and Y @@ -222,22 +222,16 @@ template Service let (new_lp1, new_lp2) = switchIf (xAsset.unit == p2.quantity.unit) (xLP_new, yLP_new) -- recreate dex archive self - dexCid <- create this with p1 = new_lp1; p2 = new_lp2 + dexCid <- toInterfaceContractId <$> create this with p1 = new_lp1; p2 = new_lp2 return (dexCid, sideEffectCids) - nonconsuming choice Swap : (ContractId Service, [ContractId Holding.I]) - with - actor : Party - xFungibleCid : ContractId Fungible.I - yAccount : AccountKey - controller actor - do + swap self Service.Swap{actor; xFungibleCid; yAccount} = do -- making use of a FlashSwapPipe, which is a FlashSwapAction which -- simply takes Y as input and returns (X,[Some(Y)]), where X is (this) -- xTokenCid and Y a yTokenCid from one of the DEX liquidity pools. pipeCid <- create FlashSwapPipe with provider = actor; outCid = toInterfaceContractId xFungibleCid xHolding <- view <$> fetch (toInterfaceContractId @Holding.I xFungibleCid) - exercise self FlashSwap with + exercise self Service.FlashSwap with actor xAsset = Instrument.qty xHolding.amount xHolding.instrument yAccount diff --git a/src/daml/Daml/Finance/App/Decentralized/Exchange/Interface.daml b/src/daml/Daml/Finance/App/Interface/Decentralized/Exchange/FlashSwapAction.daml similarity index 85% rename from src/daml/Daml/Finance/App/Decentralized/Exchange/Interface.daml rename to src/daml/Daml/Finance/App/Interface/Decentralized/Exchange/FlashSwapAction.daml index 36a5ad0b..b725b7bc 100644 --- a/src/daml/Daml/Finance/App/Decentralized/Exchange/Interface.daml +++ b/src/daml/Daml/Finance/App/Interface/Decentralized/Exchange/FlashSwapAction.daml @@ -1,7 +1,7 @@ -- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. -- SPDX-License-Identifier: Apache-2.0 -module Daml.Finance.App.Decentralized.Exchange.Interface where +module Daml.Finance.App.Interface.Decentralized.Exchange.FlashSwapAction where import DA.Assert ((===)) import Daml.Finance.Interface.Holding.Base qualified as Holding (I) @@ -9,10 +9,14 @@ import Daml.Finance.Interface.Holding.Base qualified as Holding (I) import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (Q) import Daml.Finance.Interface.Types.Common (Parties) +type I = FlashSwapAction + data View = View {} + deriving (Eq, Show) interface FlashSwapAction where viewtype View + executeAction : ContractId Holding.I -> Update (ContractId Holding.I, [ContractId Holding.I]) choice ExecuteAction: (ContractId Holding.I, [ContractId Holding.I]) @@ -45,15 +49,3 @@ interface FlashSwapAction where producedHolding.instrument === producedQuantity.unit producedHolding.amount === producedQuantity.amount return (producedHoldingCid, extraHoldingCids) -- <> optionalToList consumedHoldingRest <> optionalToList producedHoldingRest) - --- Example of a FlashSwapAction template (used for a normal DEX Swap) -template FlashSwapPipe with - provider : Party - outCid : ContractId Holding.I - where - signatory provider - - interface instance FlashSwapAction for FlashSwapPipe where - view = View {} - executeAction holdingCid = pure (outCid, [holdingCid]) - diff --git a/src/daml/Daml/Finance/App/Interface/Decentralized/Exchange/Service.daml b/src/daml/Daml/Finance/App/Interface/Decentralized/Exchange/Service.daml new file mode 100644 index 00000000..b6132dd9 --- /dev/null +++ b/src/daml/Daml/Finance/App/Interface/Decentralized/Exchange/Service.daml @@ -0,0 +1,90 @@ +-- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +-- SPDX-License-Identifier: Apache-2.0 + +module Daml.Finance.App.Interface.Decentralized.Exchange.Service where + +import Daml.Finance.App.Interface.Decentralized.Exchange.FlashSwapAction qualified as FlashSwapAction (I) +import Daml.Finance.App.Interface.Decentralized.Exchange.Types (Pool) +import Daml.Finance.Interface.Holding.Base qualified as Holding (I) +import Daml.Finance.Interface.Holding.Fungible qualified as Fungible (I) +import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (Q) +import Daml.Finance.Interface.Types.Common (AccountKey, Id) +import Daml.Finance.App.Interface.Base.Service qualified as Base (I, Implementation) + +type I = Service + +type V = View + +data View = View + with + consortium : Party + public : Party + id : Id + description : Text + shares : Instrument.Q -- share + p1 : Pool -- pool1 + p2 : Pool -- pool2 + deriving (Eq, Show) + +interface Service where + viewtype V + + asBase : Base.I + -- ^ Conversion to base `Service` interface. + + deposit : ContractId Service -> Deposit -> Update (ContractId Service, ContractId Holding.I) + -- ^ Implementation of the `Deposit` choice. + + withdraw : ContractId Service -> Withdraw -> Update (ContractId Service, ContractId Fungible.I, ContractId Fungible.I) + -- ^ Implementation of the `Withdraw` choice. + + flashSwap : ContractId Service -> FlashSwap -> Update (ContractId Service, [ContractId Holding.I]) + -- ^ Implementation of the `FlashSwap` choice. + + swap : ContractId Service -> Swap -> Update (ContractId Service, [ContractId Holding.I]) + -- ^ Implementation of the `Swap` choice. + + nonconsuming choice Deposit : (ContractId Service, ContractId Holding.I) + with + actor : Party + fungible1Cid: ContractId Fungible.I + fungible2Cid: ContractId Fungible.I + shareAccount : AccountKey + controller actor + do + deposit this self arg + + nonconsuming choice Withdraw : (ContractId Service, ContractId Fungible.I, ContractId Fungible.I) + with + actor : Party + shareCid : ContractId Fungible.I + p1Account : AccountKey + p2Account : AccountKey + controller actor + do + withdraw this self arg + + nonconsuming choice FlashSwap : (ContractId Service, [ContractId Holding.I]) + with + actor : Party + xAsset : Instrument.Q + yAccount : AccountKey + actionCid : ContractId FlashSwapAction.I + controller actor + do + flashSwap this self arg + + nonconsuming choice Swap : (ContractId Service, [ContractId Holding.I]) + with + actor : Party + xFungibleCid : ContractId Fungible.I + yAccount : AccountKey + controller actor + do + swap this self arg + +-- | Type constraint for requiring templates to implement `Service`. +type Implementation t = (HasToInterface t Service, Base.Implementation t) +class (Implementation t) => HasImplementation t +instance HasImplementation Service +instance HasToInterface Service Base.I where _toInterface = asBase diff --git a/src/daml/Daml/Finance/App/Decentralized/Exchange/Model.daml b/src/daml/Daml/Finance/App/Interface/Decentralized/Exchange/Types.daml similarity index 78% rename from src/daml/Daml/Finance/App/Decentralized/Exchange/Model.daml rename to src/daml/Daml/Finance/App/Interface/Decentralized/Exchange/Types.daml index 85f8efbd..81bc25e2 100644 --- a/src/daml/Daml/Finance/App/Decentralized/Exchange/Model.daml +++ b/src/daml/Daml/Finance/App/Interface/Decentralized/Exchange/Types.daml @@ -1,19 +1,15 @@ -- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. -- SPDX-License-Identifier: Apache-2.0 -module Daml.Finance.App.Decentralized.Exchange.Model where +module Daml.Finance.App.Interface.Decentralized.Exchange.Types where import Daml.Finance.Interface.Holding.Fungible qualified as Fungible (I) import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (Q) import Daml.Finance.Interface.Types.Common (AccountKey) -switchIf : Bool -> (b, b) -> (b, b) -switchIf cond (x, y) = if cond then (y, x) else (x, y) - data Pool = Pool with quantity : Instrument.Q account : AccountKey -- TODO: Might not need this, but instead derive it from holding fungibleCid : ContractId Fungible.I deriving (Eq, Show) - diff --git a/src/daml/Daml/Finance/Setup/Scenario/DecentralizedFinance.daml b/src/daml/Daml/Finance/Setup/Scenario/DecentralizedFinance.daml index d08a7b10..1cad4b63 100644 --- a/src/daml/Daml/Finance/Setup/Scenario/DecentralizedFinance.daml +++ b/src/daml/Daml/Finance/Setup/Scenario/DecentralizedFinance.daml @@ -8,7 +8,7 @@ import DA.Map (empty, fromList) import DA.Set (singleton) import DA.Time (time) import Daml.Finance.Account.Account qualified as Account (Factory(..)) -import Daml.Finance.App.Decentralized.Exchange.Service as Dex (Swap(..)) +import Daml.Finance.App.Interface.Decentralized.Exchange.Service qualified as Dex (Swap(..)) import Daml.Finance.Holding.Fungible qualified as Fungible (Factory(..)) import Daml.Finance.Interface.Instrument.Base.Instrument (qty) import Daml.Finance.Settlement.Factory qualified as Settlement (FactoryWithIntermediaries(..)) @@ -119,10 +119,10 @@ run = do let doRoundTrip = do - (dex1Cid, [trdEurCid]) <- submitMulti [trd] [public] do exerciseCmd dex1Cid Swap with actor = trd; xFungibleCid = trdUsdCid; yAccount = trdEcbAccount - (dex4Cid, [trdChfCid]) <- submitMulti [trd] [public] do exerciseCmd dex4Cid Swap with actor = trd; xFungibleCid = coerceContractId trdEurCid; yAccount = trdSnbAccount - (dex6Cid, [trdGbpCid]) <- submitMulti [trd] [public] do exerciseCmd dex6Cid Swap with actor = trd; xFungibleCid = coerceContractId trdChfCid; yAccount = trdBoeAccount - (dex3Cid, [trdUsdCid]) <- submitMulti [trd] [public] do exerciseCmd dex3Cid Swap with actor = trd; xFungibleCid = coerceContractId trdGbpCid; yAccount = trdFedAccount + (dex1Cid, [trdEurCid]) <- submitMulti [trd] [public] do exerciseCmd dex1Cid Dex.Swap with actor = trd; xFungibleCid = trdUsdCid; yAccount = trdEcbAccount + (dex4Cid, [trdChfCid]) <- submitMulti [trd] [public] do exerciseCmd dex4Cid Dex.Swap with actor = trd; xFungibleCid = coerceContractId trdEurCid; yAccount = trdSnbAccount + (dex6Cid, [trdGbpCid]) <- submitMulti [trd] [public] do exerciseCmd dex6Cid Dex.Swap with actor = trd; xFungibleCid = coerceContractId trdChfCid; yAccount = trdBoeAccount + (dex3Cid, [trdUsdCid]) <- submitMulti [trd] [public] do exerciseCmd dex3Cid Dex.Swap with actor = trd; xFungibleCid = coerceContractId trdGbpCid; yAccount = trdFedAccount pure () -- doRoundTrip diff --git a/src/daml/Daml/Finance/Setup/Util/Service.daml b/src/daml/Daml/Finance/Setup/Util/Service.daml index f24f1178..a3f903b9 100644 --- a/src/daml/Daml/Finance/Setup/Util/Service.daml +++ b/src/daml/Daml/Finance/Setup/Util/Service.daml @@ -7,10 +7,11 @@ import DA.Map qualified as M (fromList) import DA.Set (fromList, singleton) import Daml.Finance.App.Custody.Auto qualified as CustodyAuto (Accept(..)) import Daml.Finance.App.Custody.Service qualified as Custody (Accept(..)) -import Daml.Finance.App.Decentralized.Exchange.Model qualified as DecentralizedExchange (Pool(..)) import Daml.Finance.App.Decentralized.Exchange.Service qualified as DecentralizedExchange (Service(..)) import Daml.Finance.App.Interface.Custody.Auto qualified as CustodyAuto (I) import Daml.Finance.App.Interface.Custody.Service qualified as Custody (I) +import Daml.Finance.App.Interface.Decentralized.Exchange.Service qualified as DecentralizedExchange (I) +import Daml.Finance.App.Interface.Decentralized.Exchange.Types (Pool(..)) import Daml.Finance.App.Interface.Distribution.Auction.Auto qualified as AuctionAuto (I) import Daml.Finance.App.Interface.Distribution.Auction.Service qualified as Auction (I) import Daml.Finance.App.Interface.Distribution.Bidding.Auto qualified as BiddingAuto (I) @@ -192,12 +193,11 @@ createFundService operator provider customer = do offerCid <- submit provider do exerciseByKeyCmd @Distributor.Role (operator, provider) Distributor.OfferFundService with customer toInterfaceContractId <$> submit customer do exerciseCmd offerCid Fund.Accept -createDecentralizedExchangeService : Party -> Party -> Text -> Instrument.Q -> Instrument.Q -> Account.K -> ContractId Fungible.I -> Instrument.Q -> Account.K -> ContractId Fungible.I -> Script (ContractId DecentralizedExchange.Service) +createDecentralizedExchangeService : Party -> Party -> Text -> Instrument.Q -> Instrument.Q -> Account.K -> ContractId Fungible.I -> Instrument.Q -> Account.K -> ContractId Fungible.I -> Script (ContractId DecentralizedExchange.I) createDecentralizedExchangeService consortium public id shares quantity1 account1 fungible1Cid quantity2 account2 fungible2Cid = do fungible1Cid <- coerceContractId <$> submit consortium do exerciseCmd (toInterfaceContractId @Disclosure.I fungible1Cid) Disclosure.AddObservers with disclosers = singleton consortium; observersToAdd = (id, singleton public) fungible2Cid <- coerceContractId <$> submit consortium do exerciseCmd (toInterfaceContractId @Disclosure.I fungible2Cid) Disclosure.AddObservers with disclosers = singleton consortium; observersToAdd = (id, singleton public) let - p1 = DecentralizedExchange.Pool with quantity = quantity1; account = account1; fungibleCid = fungible1Cid - p2 = DecentralizedExchange.Pool with quantity = quantity2; account = account2; fungibleCid = fungible2Cid - submit consortium do createCmd DecentralizedExchange.Service with consortium; public; id = Id id; description = id; shares; p1; p2 - + p1 = Pool with quantity = quantity1; account = account1; fungibleCid = fungible1Cid + p2 = Pool with quantity = quantity2; account = account2; fungibleCid = fungible2Cid + toInterfaceContractId <$> submit consortium do createCmd DecentralizedExchange.Service with consortium; public; id = Id id; description = id; shares; p1; p2 From 363d1853eb2032d65a606785f57fc4c50ac0ab83 Mon Sep 17 00:00:00 2001 From: Georg Schneider Date: Wed, 21 Dec 2022 17:17:43 +0100 Subject: [PATCH 15/31] Update UI for new service interfaces --- ui/package-lock.json | 113 +++++++------ ui/src/apps/Distribution.tsx | 10 +- ui/src/components/Instrument/Aggregate.tsx | 6 +- ui/src/context/ServicesContext.tsx | 155 ++++++++++-------- ui/src/pages/defi/Exchange.tsx | 4 +- ui/src/pages/defi/Exchanges.tsx | 2 +- ui/src/pages/distribution/auction/Bidding.tsx | 9 +- ui/src/pages/distribution/auction/New.tsx | 11 +- .../pages/distribution/investment/Funds.tsx | 2 +- ui/src/pages/distribution/investment/New.tsx | 11 +- .../investment/PooledRequests.tsx | 19 ++- .../distribution/investment/Requests.tsx | 14 +- ui/src/pages/distribution/offering/New.tsx | 29 ++-- .../pages/distribution/offering/Offering.tsx | 21 +-- .../pages/distribution/offering/Offerings.tsx | 2 +- ui/src/pages/issuance/New.tsx | 18 +- ui/src/pages/lending/New.tsx | 15 +- ui/src/pages/lending/Offers.tsx | 15 +- ui/src/pages/lending/Request.tsx | 21 +-- ui/src/pages/lending/Requests.tsx | 2 +- ui/src/pages/lending/Trades.tsx | 25 ++- ui/src/pages/listing/Listings.tsx | 9 +- ui/src/pages/listing/New.tsx | 11 +- ui/src/pages/servicing/Instrument.tsx | 22 +-- ui/src/pages/servicing/Instruments.tsx | 25 +-- ui/src/pages/simulation/Scenario.tsx | 24 +-- .../structuring/bond/NewFixedRateBond.tsx | 20 ++- .../structuring/bond/NewFloatingRateBond.tsx | 20 ++- .../bond/NewInflationLinkedBond.tsx | 20 ++- .../structuring/bond/NewZeroCouponBond.tsx | 29 ++-- ui/src/pages/structuring/equity/NewStock.tsx | 49 +++--- ui/src/pages/structuring/other/NewGeneric.tsx | 28 ++-- ui/src/pages/structuring/other/NewToken.tsx | 51 +++--- ui/src/pages/trading/Market.tsx | 21 +-- 34 files changed, 436 insertions(+), 397 deletions(-) diff --git a/ui/package-lock.json b/ui/package-lock.json index 7c15fd7e..17aefcbf 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -24,9 +24,9 @@ "@daml.js/daml-finance-interface-settlement": "file:daml.js/eee5de887daab47f57f46612c0e12c196cb24d89cf3fce319143088fa2765c64", "@daml.js/daml-finance-interface-types": "file:daml.js/87cb7a623037fd06919af3cba15bc4a9430d315bbb02294a54cad7b61d48f01f", "@daml.js/daml-finance-interface-util": "file:daml.js/200ca261e5eb1d239e728fc65421e5b2f693c6f738d5ccb8c6a5a40966a27ac5", - "@daml/ledger": "2.5.0-snapshot.20221010.10736.0.2f453a14", - "@daml/react": "2.5.0-snapshot.20221010.10736.0.2f453a14", - "@daml/types": "2.5.0-snapshot.20221010.10736.0.2f453a14", + "@daml/ledger": "2.6.0-snapshot.20221218.11169.0.9d007b31", + "@daml/react": "2.6.0-snapshot.20221218.11169.0.9d007b31", + "@daml/types": "2.6.0-snapshot.20221218.11169.0.9d007b31", "@emotion/react": "^11.5.0", "@emotion/styled": "^11.3.0", "@mui/icons-material": "^5.0.5", @@ -63,7 +63,7 @@ }, "daml.js/086db20b6f52db9260ca9d87c2092e8fa21619f62c7687a63bcdfb9c7a6bd670": { "name": "@daml.js/086db20b6f52db9260ca9d87c2092e8fa21619f62c7687a63bcdfb9c7a6bd670", - "version": "2.5.0-snapshot.20221010.10736.0.2f453a14", + "version": "2.6.0-snapshot.20221218.11169.0.9d007b31", "license": "UNLICENSED", "dependencies": { "@daml.js/87c62e83e3c0b9d2230c503992749abb45fea0ed0fad4a10f2b64b1cd63f5e9a": "file:../87c62e83e3c0b9d2230c503992749abb45fea0ed0fad4a10f2b64b1cd63f5e9a", @@ -86,7 +86,7 @@ }, "daml.js/200ca261e5eb1d239e728fc65421e5b2f693c6f738d5ccb8c6a5a40966a27ac5": { "name": "@daml.js/200ca261e5eb1d239e728fc65421e5b2f693c6f738d5ccb8c6a5a40966a27ac5", - "version": "2.5.0-snapshot.20221010.10736.0.2f453a14", + "version": "2.6.0-snapshot.20221218.11169.0.9d007b31", "license": "UNLICENSED", "dependencies": { "@daml.js/40f452260bef3f29dede136108fc08a88d5a5250310281067087da6f0baddff7": "file:../40f452260bef3f29dede136108fc08a88d5a5250310281067087da6f0baddff7", @@ -96,7 +96,7 @@ }, "daml.js/238c34f053632bfb2a4c53c730b7074dc169521d642c3d4abb3ae1d10c5653a6": { "name": "@daml.js/238c34f053632bfb2a4c53c730b7074dc169521d642c3d4abb3ae1d10c5653a6", - "version": "2.5.0-snapshot.20221010.10736.0.2f453a14", + "version": "2.6.0-snapshot.20221218.11169.0.9d007b31", "license": "UNLICENSED", "dependencies": { "@daml.js/c2e9bd7da480b0050c8e42f609ad533695f8359c6018dec2731111e9a8efb841": "file:../c2e9bd7da480b0050c8e42f609ad533695f8359c6018dec2731111e9a8efb841", @@ -105,7 +105,7 @@ }, "daml.js/2dfa9b3847d9ffd6d5115afd409efad4015655b9080ba5c87e8500d52e457e54": { "name": "@daml.js/2dfa9b3847d9ffd6d5115afd409efad4015655b9080ba5c87e8500d52e457e54", - "version": "2.5.0-snapshot.20221010.10736.0.2f453a14", + "version": "2.6.0-snapshot.20221218.11169.0.9d007b31", "license": "UNLICENSED", "dependencies": { "@daml.js/87cb7a623037fd06919af3cba15bc4a9430d315bbb02294a54cad7b61d48f01f": "file:../87cb7a623037fd06919af3cba15bc4a9430d315bbb02294a54cad7b61d48f01f", @@ -115,7 +115,7 @@ }, "daml.js/37b3f85c4fb25b306db2d2d8de588a755dfebe2d8353ce37bee72160942f2cd2": { "name": "@daml.js/37b3f85c4fb25b306db2d2d8de588a755dfebe2d8353ce37bee72160942f2cd2", - "version": "2.5.0-snapshot.20221010.10736.0.2f453a14", + "version": "2.6.0-snapshot.20221218.11169.0.9d007b31", "license": "UNLICENSED", "dependencies": { "@daml.js/7998f3f7ddf0f0dc4735502c5de61806765cb2295ef8ee6cc432782d64823ed3": "file:../7998f3f7ddf0f0dc4735502c5de61806765cb2295ef8ee6cc432782d64823ed3", @@ -127,7 +127,7 @@ }, "daml.js/3bce4883d8470953ecbc13ee0872803052091ba372743c1f81a56ef0a12343c1": { "name": "@daml.js/3bce4883d8470953ecbc13ee0872803052091ba372743c1f81a56ef0a12343c1", - "version": "2.5.0-snapshot.20221010.10736.0.2f453a14", + "version": "2.6.0-snapshot.20221218.11169.0.9d007b31", "license": "UNLICENSED", "dependencies": { "@daml.js/87cb7a623037fd06919af3cba15bc4a9430d315bbb02294a54cad7b61d48f01f": "file:../87cb7a623037fd06919af3cba15bc4a9430d315bbb02294a54cad7b61d48f01f", @@ -137,7 +137,7 @@ }, "daml.js/3c84d16a44aec5940e513f7d84a99507b2d05c9583afa8c91347e0a6e3e55d36": { "name": "@daml.js/3c84d16a44aec5940e513f7d84a99507b2d05c9583afa8c91347e0a6e3e55d36", - "version": "2.5.0-snapshot.20221010.10736.0.2f453a14", + "version": "2.6.0-snapshot.20221218.11169.0.9d007b31", "license": "UNLICENSED", "dependencies": { "@daml.js/40f452260bef3f29dede136108fc08a88d5a5250310281067087da6f0baddff7": "file:../40f452260bef3f29dede136108fc08a88d5a5250310281067087da6f0baddff7", @@ -146,7 +146,7 @@ }, "daml.js/3f9983437e5f1768480818fc6995adbc656aa8d061aa72ab99e4777759b36164": { "name": "@daml.js/3f9983437e5f1768480818fc6995adbc656aa8d061aa72ab99e4777759b36164", - "version": "2.5.0-snapshot.20221010.10736.0.2f453a14", + "version": "2.6.0-snapshot.20221218.11169.0.9d007b31", "license": "UNLICENSED", "dependencies": { "@daml.js/87c62e83e3c0b9d2230c503992749abb45fea0ed0fad4a10f2b64b1cd63f5e9a": "file:../87c62e83e3c0b9d2230c503992749abb45fea0ed0fad4a10f2b64b1cd63f5e9a", @@ -158,7 +158,7 @@ }, "daml.js/40f452260bef3f29dede136108fc08a88d5a5250310281067087da6f0baddff7": { "name": "@daml.js/40f452260bef3f29dede136108fc08a88d5a5250310281067087da6f0baddff7", - "version": "2.5.0-snapshot.20221010.10736.0.2f453a14", + "version": "2.6.0-snapshot.20221218.11169.0.9d007b31", "license": "UNLICENSED", "dependencies": { "@mojotech/json-type-validation": "^3.1.0" @@ -189,7 +189,7 @@ }, "daml.js/5bd335c5c8ae980ec8907e066da3eda5e0d57a983f59a5873684b9aa26ea0aa9": { "name": "@daml.js/5bd335c5c8ae980ec8907e066da3eda5e0d57a983f59a5873684b9aa26ea0aa9", - "version": "2.5.0-snapshot.20221010.10736.0.2f453a14", + "version": "2.6.0-snapshot.20221218.11169.0.9d007b31", "license": "UNLICENSED", "dependencies": { "@daml.js/87c62e83e3c0b9d2230c503992749abb45fea0ed0fad4a10f2b64b1cd63f5e9a": "file:../87c62e83e3c0b9d2230c503992749abb45fea0ed0fad4a10f2b64b1cd63f5e9a", @@ -222,7 +222,7 @@ }, "daml.js/7998f3f7ddf0f0dc4735502c5de61806765cb2295ef8ee6cc432782d64823ed3": { "name": "@daml.js/7998f3f7ddf0f0dc4735502c5de61806765cb2295ef8ee6cc432782d64823ed3", - "version": "2.5.0-snapshot.20221010.10736.0.2f453a14", + "version": "2.6.0-snapshot.20221218.11169.0.9d007b31", "license": "UNLICENSED", "dependencies": { "@daml.js/87cb7a623037fd06919af3cba15bc4a9430d315bbb02294a54cad7b61d48f01f": "file:../87cb7a623037fd06919af3cba15bc4a9430d315bbb02294a54cad7b61d48f01f", @@ -245,7 +245,7 @@ }, "daml.js/87c62e83e3c0b9d2230c503992749abb45fea0ed0fad4a10f2b64b1cd63f5e9a": { "name": "@daml.js/87c62e83e3c0b9d2230c503992749abb45fea0ed0fad4a10f2b64b1cd63f5e9a", - "version": "2.5.0-snapshot.20221010.10736.0.2f453a14", + "version": "2.6.0-snapshot.20221218.11169.0.9d007b31", "license": "UNLICENSED", "dependencies": { "@daml.js/87cb7a623037fd06919af3cba15bc4a9430d315bbb02294a54cad7b61d48f01f": "file:../87cb7a623037fd06919af3cba15bc4a9430d315bbb02294a54cad7b61d48f01f", @@ -256,7 +256,7 @@ }, "daml.js/87cb7a623037fd06919af3cba15bc4a9430d315bbb02294a54cad7b61d48f01f": { "name": "@daml.js/87cb7a623037fd06919af3cba15bc4a9430d315bbb02294a54cad7b61d48f01f", - "version": "2.5.0-snapshot.20221010.10736.0.2f453a14", + "version": "2.6.0-snapshot.20221218.11169.0.9d007b31", "license": "UNLICENSED", "dependencies": { "@daml.js/bfcd37bd6b84768e86e432f5f6c33e25d9e7724a9d42e33875ff74f6348e733f": "file:../bfcd37bd6b84768e86e432f5f6c33e25d9e7724a9d42e33875ff74f6348e733f", @@ -265,7 +265,7 @@ }, "daml.js/880aab1dc6c2daeff038c4bc4b84c9e98acbf777a1061cfe8ae5517acac50008": { "name": "@daml.js/880aab1dc6c2daeff038c4bc4b84c9e98acbf777a1061cfe8ae5517acac50008", - "version": "2.5.0-snapshot.20221010.10736.0.2f453a14", + "version": "2.6.0-snapshot.20221218.11169.0.9d007b31", "license": "UNLICENSED", "dependencies": { "@daml.js/2dfa9b3847d9ffd6d5115afd409efad4015655b9080ba5c87e8500d52e457e54": "file:../2dfa9b3847d9ffd6d5115afd409efad4015655b9080ba5c87e8500d52e457e54", @@ -290,7 +290,7 @@ }, "daml.js/97b883cd8a2b7f49f90d5d39c981cf6e110cf1f1c64427a28a6d58ec88c43657": { "name": "@daml.js/97b883cd8a2b7f49f90d5d39c981cf6e110cf1f1c64427a28a6d58ec88c43657", - "version": "2.5.0-snapshot.20221010.10736.0.2f453a14", + "version": "2.6.0-snapshot.20221218.11169.0.9d007b31", "license": "UNLICENSED", "dependencies": { "@mojotech/json-type-validation": "^3.1.0" @@ -320,7 +320,7 @@ }, "daml.js/a224d4f3a6226dc2920282c1e6a5f0335c38d3d8588e5810c2d33ad5cbf0ca2b": { "name": "@daml.js/a224d4f3a6226dc2920282c1e6a5f0335c38d3d8588e5810c2d33ad5cbf0ca2b", - "version": "2.5.0-snapshot.20221010.10736.0.2f453a14", + "version": "2.6.0-snapshot.20221218.11169.0.9d007b31", "license": "UNLICENSED", "dependencies": { "@daml.js/2dfa9b3847d9ffd6d5115afd409efad4015655b9080ba5c87e8500d52e457e54": "file:../2dfa9b3847d9ffd6d5115afd409efad4015655b9080ba5c87e8500d52e457e54", @@ -348,7 +348,7 @@ }, "daml.js/a74b723696c4cfa214bf96090c62d92cba77f45ac6b0670d88c79e4850a2a826": { "name": "@daml.js/a74b723696c4cfa214bf96090c62d92cba77f45ac6b0670d88c79e4850a2a826", - "version": "2.5.0-snapshot.20221010.10736.0.2f453a14", + "version": "2.6.0-snapshot.20221218.11169.0.9d007b31", "license": "UNLICENSED", "dependencies": { "@daml.js/87c62e83e3c0b9d2230c503992749abb45fea0ed0fad4a10f2b64b1cd63f5e9a": "file:../87c62e83e3c0b9d2230c503992749abb45fea0ed0fad4a10f2b64b1cd63f5e9a", @@ -387,7 +387,7 @@ }, "daml.js/bfcd37bd6b84768e86e432f5f6c33e25d9e7724a9d42e33875ff74f6348e733f": { "name": "@daml.js/bfcd37bd6b84768e86e432f5f6c33e25d9e7724a9d42e33875ff74f6348e733f", - "version": "2.5.0-snapshot.20221010.10736.0.2f453a14", + "version": "2.6.0-snapshot.20221218.11169.0.9d007b31", "license": "UNLICENSED", "dependencies": { "@mojotech/json-type-validation": "^3.1.0" @@ -395,7 +395,7 @@ }, "daml.js/c2e9bd7da480b0050c8e42f609ad533695f8359c6018dec2731111e9a8efb841": { "name": "@daml.js/c2e9bd7da480b0050c8e42f609ad533695f8359c6018dec2731111e9a8efb841", - "version": "2.5.0-snapshot.20221010.10736.0.2f453a14", + "version": "2.6.0-snapshot.20221218.11169.0.9d007b31", "license": "UNLICENSED", "dependencies": { "@daml.js/40f452260bef3f29dede136108fc08a88d5a5250310281067087da6f0baddff7": "file:../40f452260bef3f29dede136108fc08a88d5a5250310281067087da6f0baddff7", @@ -404,7 +404,7 @@ }, "daml.js/d14e08374fc7197d6a0de468c968ae8ba3aadbf9315476fd39071831f5923662": { "name": "@daml.js/d14e08374fc7197d6a0de468c968ae8ba3aadbf9315476fd39071831f5923662", - "version": "2.5.0-snapshot.20221010.10736.0.2f453a14", + "version": "2.6.0-snapshot.20221218.11169.0.9d007b31", "license": "UNLICENSED", "dependencies": { "@mojotech/json-type-validation": "^3.1.0" @@ -412,9 +412,10 @@ }, "daml.js/daml-finance-app-0.1.5": { "name": "@daml.js/daml-finance-app-0.1.5", - "version": "2.5.0-snapshot.20221010.10736.0.2f453a14", + "version": "2.6.0-snapshot.20221218.11169.0.9d007b31", "license": "UNLICENSED", "dependencies": { + "@daml.js/086db20b6f52db9260ca9d87c2092e8fa21619f62c7687a63bcdfb9c7a6bd670": "file:../086db20b6f52db9260ca9d87c2092e8fa21619f62c7687a63bcdfb9c7a6bd670", "@daml.js/238c34f053632bfb2a4c53c730b7074dc169521d642c3d4abb3ae1d10c5653a6": "file:../238c34f053632bfb2a4c53c730b7074dc169521d642c3d4abb3ae1d10c5653a6", "@daml.js/2dfa9b3847d9ffd6d5115afd409efad4015655b9080ba5c87e8500d52e457e54": "file:../2dfa9b3847d9ffd6d5115afd409efad4015655b9080ba5c87e8500d52e457e54", "@daml.js/37b3f85c4fb25b306db2d2d8de588a755dfebe2d8353ce37bee72160942f2cd2": "file:../37b3f85c4fb25b306db2d2d8de588a755dfebe2d8353ce37bee72160942f2cd2", @@ -438,7 +439,7 @@ }, "daml.js/eee5de887daab47f57f46612c0e12c196cb24d89cf3fce319143088fa2765c64": { "name": "@daml.js/eee5de887daab47f57f46612c0e12c196cb24d89cf3fce319143088fa2765c64", - "version": "2.5.0-snapshot.20221010.10736.0.2f453a14", + "version": "2.6.0-snapshot.20221218.11169.0.9d007b31", "license": "UNLICENSED", "dependencies": { "@daml.js/40f452260bef3f29dede136108fc08a88d5a5250310281067087da6f0baddff7": "file:../40f452260bef3f29dede136108fc08a88d5a5250310281067087da6f0baddff7", @@ -2671,6 +2672,10 @@ "postcss-selector-parser": "^6.0.10" } }, + "node_modules/@daml.js/086db20b6f52db9260ca9d87c2092e8fa21619f62c7687a63bcdfb9c7a6bd670": { + "resolved": "daml.js/086db20b6f52db9260ca9d87c2092e8fa21619f62c7687a63bcdfb9c7a6bd670", + "link": true + }, "node_modules/@daml.js/238c34f053632bfb2a4c53c730b7074dc169521d642c3d4abb3ae1d10c5653a6": { "resolved": "daml.js/238c34f053632bfb2a4c53c730b7074dc169521d642c3d4abb3ae1d10c5653a6", "link": true @@ -2812,11 +2817,11 @@ "link": true }, "node_modules/@daml/ledger": { - "version": "2.5.0-snapshot.20221010.10736.0.2f453a14", - "resolved": "https://registry.npmjs.org/@daml/ledger/-/ledger-2.5.0-snapshot.20221010.10736.0.2f453a14.tgz", - "integrity": "sha512-eB0Z7Md8huD7L/c1DE7AuOVDtUaH90oNa7uAvd2UH9WnN3H+oRtV2xYOR6ZceZQhgKar4/S5nXat/aRcgH3k3Q==", + "version": "2.6.0-snapshot.20221218.11169.0.9d007b31", + "resolved": "https://registry.npmjs.org/@daml/ledger/-/ledger-2.6.0-snapshot.20221218.11169.0.9d007b31.tgz", + "integrity": "sha512-71M6+87bnRuCxFpQLfzaDojq+gWAH4/m+f6c/lc4uBA9+GFpcbVLvGjUdEa6Fe5D1HjRSD3Zik1Ges2RmUqM0w==", "dependencies": { - "@daml/types": "2.5.0-snapshot.20221010.10736.0.2f453a14", + "@daml/types": "2.6.0-snapshot.20221218.11169.0.9d007b31", "@mojotech/json-type-validation": "^3.1.0", "cross-fetch": "^3.0.4", "events": "^3.1.0", @@ -2825,21 +2830,21 @@ } }, "node_modules/@daml/react": { - "version": "2.5.0-snapshot.20221010.10736.0.2f453a14", - "resolved": "https://registry.npmjs.org/@daml/react/-/react-2.5.0-snapshot.20221010.10736.0.2f453a14.tgz", - "integrity": "sha512-Y5L9QBr1Iyfjp4SJvQ094Xd6uZDC00PRuP1RoqwyaakAA9n+AmPdg0gM8NCIX/Z8efurcojx6p3GOMEHRYKQmA==", + "version": "2.6.0-snapshot.20221218.11169.0.9d007b31", + "resolved": "https://registry.npmjs.org/@daml/react/-/react-2.6.0-snapshot.20221218.11169.0.9d007b31.tgz", + "integrity": "sha512-OHkCtcv1CTx0eIU8OUTKsb6frRYzdRDLK4AQiTlj9ueQRbzdlGYMmQHVjjPswJbV96MI1n9UePmbhUuYU8oIPA==", "dependencies": { - "@daml/ledger": "2.5.0-snapshot.20221010.10736.0.2f453a14", - "@daml/types": "2.5.0-snapshot.20221010.10736.0.2f453a14" + "@daml/ledger": "2.6.0-snapshot.20221218.11169.0.9d007b31", + "@daml/types": "2.6.0-snapshot.20221218.11169.0.9d007b31" }, "peerDependencies": { "react": "^16.12.0 || ^17.0.0" } }, "node_modules/@daml/types": { - "version": "2.5.0-snapshot.20221010.10736.0.2f453a14", - "resolved": "https://registry.npmjs.org/@daml/types/-/types-2.5.0-snapshot.20221010.10736.0.2f453a14.tgz", - "integrity": "sha512-bBdGuTtr1ZhFBpb/paqk5jeNK0nV2/v+UBbNwA6M6aLzm6ze9PTtdAn4wz5+oe8wp1D6jv6zllwrjSrBNRM5/A==", + "version": "2.6.0-snapshot.20221218.11169.0.9d007b31", + "resolved": "https://registry.npmjs.org/@daml/types/-/types-2.6.0-snapshot.20221218.11169.0.9d007b31.tgz", + "integrity": "sha512-bcD4kIfuuGKhvVzluI6hSp4HZqojdJe9wvv2ci0lJH3tbm/3b+YTG7KterVhL+MhklpP0X7pTCqTYsUVBXvF3g==", "dependencies": { "@mojotech/json-type-validation": "^3.1.0" } @@ -21953,6 +21958,15 @@ "dev": true, "requires": {} }, + "@daml.js/086db20b6f52db9260ca9d87c2092e8fa21619f62c7687a63bcdfb9c7a6bd670": { + "version": "file:daml.js/086db20b6f52db9260ca9d87c2092e8fa21619f62c7687a63bcdfb9c7a6bd670", + "requires": { + "@daml.js/87c62e83e3c0b9d2230c503992749abb45fea0ed0fad4a10f2b64b1cd63f5e9a": "file:../87c62e83e3c0b9d2230c503992749abb45fea0ed0fad4a10f2b64b1cd63f5e9a", + "@daml.js/87cb7a623037fd06919af3cba15bc4a9430d315bbb02294a54cad7b61d48f01f": "file:../87cb7a623037fd06919af3cba15bc4a9430d315bbb02294a54cad7b61d48f01f", + "@daml.js/97b883cd8a2b7f49f90d5d39c981cf6e110cf1f1c64427a28a6d58ec88c43657": "file:../97b883cd8a2b7f49f90d5d39c981cf6e110cf1f1c64427a28a6d58ec88c43657", + "@mojotech/json-type-validation": "^3.1.0" + } + }, "@daml.js/238c34f053632bfb2a4c53c730b7074dc169521d642c3d4abb3ae1d10c5653a6": { "version": "file:daml.js/238c34f053632bfb2a4c53c730b7074dc169521d642c3d4abb3ae1d10c5653a6", "requires": { @@ -22111,6 +22125,7 @@ "@daml.js/daml-finance-app": { "version": "file:daml.js/daml-finance-app-0.1.5", "requires": { + "@daml.js/086db20b6f52db9260ca9d87c2092e8fa21619f62c7687a63bcdfb9c7a6bd670": "file:../086db20b6f52db9260ca9d87c2092e8fa21619f62c7687a63bcdfb9c7a6bd670", "@daml.js/238c34f053632bfb2a4c53c730b7074dc169521d642c3d4abb3ae1d10c5653a6": "file:../238c34f053632bfb2a4c53c730b7074dc169521d642c3d4abb3ae1d10c5653a6", "@daml.js/2dfa9b3847d9ffd6d5115afd409efad4015655b9080ba5c87e8500d52e457e54": "file:../2dfa9b3847d9ffd6d5115afd409efad4015655b9080ba5c87e8500d52e457e54", "@daml.js/37b3f85c4fb25b306db2d2d8de588a755dfebe2d8353ce37bee72160942f2cd2": "file:../37b3f85c4fb25b306db2d2d8de588a755dfebe2d8353ce37bee72160942f2cd2", @@ -22273,11 +22288,11 @@ } }, "@daml/ledger": { - "version": "2.5.0-snapshot.20221010.10736.0.2f453a14", - "resolved": "https://registry.npmjs.org/@daml/ledger/-/ledger-2.5.0-snapshot.20221010.10736.0.2f453a14.tgz", - "integrity": "sha512-eB0Z7Md8huD7L/c1DE7AuOVDtUaH90oNa7uAvd2UH9WnN3H+oRtV2xYOR6ZceZQhgKar4/S5nXat/aRcgH3k3Q==", + "version": "2.6.0-snapshot.20221218.11169.0.9d007b31", + "resolved": "https://registry.npmjs.org/@daml/ledger/-/ledger-2.6.0-snapshot.20221218.11169.0.9d007b31.tgz", + "integrity": "sha512-71M6+87bnRuCxFpQLfzaDojq+gWAH4/m+f6c/lc4uBA9+GFpcbVLvGjUdEa6Fe5D1HjRSD3Zik1Ges2RmUqM0w==", "requires": { - "@daml/types": "2.5.0-snapshot.20221010.10736.0.2f453a14", + "@daml/types": "2.6.0-snapshot.20221218.11169.0.9d007b31", "@mojotech/json-type-validation": "^3.1.0", "cross-fetch": "^3.0.4", "events": "^3.1.0", @@ -22286,18 +22301,18 @@ } }, "@daml/react": { - "version": "2.5.0-snapshot.20221010.10736.0.2f453a14", - "resolved": "https://registry.npmjs.org/@daml/react/-/react-2.5.0-snapshot.20221010.10736.0.2f453a14.tgz", - "integrity": "sha512-Y5L9QBr1Iyfjp4SJvQ094Xd6uZDC00PRuP1RoqwyaakAA9n+AmPdg0gM8NCIX/Z8efurcojx6p3GOMEHRYKQmA==", + "version": "2.6.0-snapshot.20221218.11169.0.9d007b31", + "resolved": "https://registry.npmjs.org/@daml/react/-/react-2.6.0-snapshot.20221218.11169.0.9d007b31.tgz", + "integrity": "sha512-OHkCtcv1CTx0eIU8OUTKsb6frRYzdRDLK4AQiTlj9ueQRbzdlGYMmQHVjjPswJbV96MI1n9UePmbhUuYU8oIPA==", "requires": { - "@daml/ledger": "2.5.0-snapshot.20221010.10736.0.2f453a14", - "@daml/types": "2.5.0-snapshot.20221010.10736.0.2f453a14" + "@daml/ledger": "2.6.0-snapshot.20221218.11169.0.9d007b31", + "@daml/types": "2.6.0-snapshot.20221218.11169.0.9d007b31" } }, "@daml/types": { - "version": "2.5.0-snapshot.20221010.10736.0.2f453a14", - "resolved": "https://registry.npmjs.org/@daml/types/-/types-2.5.0-snapshot.20221010.10736.0.2f453a14.tgz", - "integrity": "sha512-bBdGuTtr1ZhFBpb/paqk5jeNK0nV2/v+UBbNwA6M6aLzm6ze9PTtdAn4wz5+oe8wp1D6jv6zllwrjSrBNRM5/A==", + "version": "2.6.0-snapshot.20221218.11169.0.9d007b31", + "resolved": "https://registry.npmjs.org/@daml/types/-/types-2.6.0-snapshot.20221218.11169.0.9d007b31.tgz", + "integrity": "sha512-bcD4kIfuuGKhvVzluI6hSp4HZqojdJe9wvv2ci0lJH3tbm/3b+YTG7KterVhL+MhklpP0X7pTCqTYsUVBXvF3g==", "requires": { "@mojotech/json-type-validation": "^3.1.0" } diff --git a/ui/src/apps/Distribution.tsx b/ui/src/apps/Distribution.tsx index 1760533f..0c5b700e 100644 --- a/ui/src/apps/Distribution.tsx +++ b/ui/src/apps/Distribution.tsx @@ -28,11 +28,11 @@ export const Distribution : React.FC = () => { const providerAuctionService = auction.services.find(c => c.payload.provider === party); const customerAuctionService = auction.services.find(c => c.payload.customer === party); - const providerSubscriptionService = subscription.find(c => c.payload.provider === party); - const customerSubscriptionService = subscription.find(c => c.payload.customer === party); - const providerInvestmentService = investment.find(c => c.payload.provider === party); - const customerInvestmentService = investment.find(c => c.payload.customer === party); - const providerFundService = fund.find(c => c.payload.provider === party); + const providerSubscriptionService = subscription.services.find(c => c.payload.provider === party); + const customerSubscriptionService = subscription.services.find(c => c.payload.customer === party); + const providerInvestmentService = investment.services.find(c => c.payload.provider === party); + const customerInvestmentService = investment.services.find(c => c.payload.customer === party); + const providerFundService = fund.services.find(c => c.payload.provider === party); const isAgent = !!providerAuctionService || !!providerSubscriptionService; const isIssuer = !!customerAuctionService || !!customerSubscriptionService; const isInvestor = !!customerInvestmentService; diff --git a/ui/src/components/Instrument/Aggregate.tsx b/ui/src/components/Instrument/Aggregate.tsx index f8dbccdc..0dd90212 100644 --- a/ui/src/components/Instrument/Aggregate.tsx +++ b/ui/src/components/Instrument/Aggregate.tsx @@ -9,7 +9,7 @@ import useStyles from "./styles"; import { ClaimsTreeBuilder, ClaimTreeNode } from "../../components/Claims/ClaimsTreeBuilder"; import { and, claimToNode } from "../../components/Claims/util"; import { InstrumentAggregate } from "../../context/InstrumentContext"; -import { Service as Lifecycle } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Lifecycle/Service"; +import { Service as Lifecycle } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Interface/Lifecycle/Service"; import { useParties } from "../../context/PartiesContext"; import { shorten } from "../../util"; import { Spinner } from "../Spinner/Spinner"; @@ -32,12 +32,12 @@ export const Aggregate : React.FC = ({ instrument }) => { useEffect(() => { const setClaims = async () => { if (!l1 && !l2 && !!instrument.claim) { - const [res, ] = await ledger.exercise(Lifecycle.GetCurrentClaims, lifecycle[0].contractId, { instrumentCid: instrument.claim.contractId, observableCids: observables.map(c => c.contractId) }) + const [res, ] = await ledger.exercise(Lifecycle.GetCurrentClaims, lifecycle.services[0].service.contractId, { instrumentCid: instrument.claim.contractId, observableCids: observables.map(c => c.contractId) }) const claims = res.length > 1 ? and(res.map(r => r.claim)) : res[0].claim; setNode(claimToNode(claims)); } } - if (lifecycle.length > 0) setClaims(); + if (lifecycle.services.length > 0) setClaims(); }, [lifecycle, instrument, observables, l1, l2, ledger]); if (l1 || l2) return diff --git a/ui/src/context/ServicesContext.tsx b/ui/src/context/ServicesContext.tsx index 9479181f..0a31d626 100644 --- a/ui/src/context/ServicesContext.tsx +++ b/ui/src/context/ServicesContext.tsx @@ -5,58 +5,62 @@ import React from "react"; import { CreateEvent } from "@daml/ledger"; import { useStreamQueries } from "@daml/react"; import { Service as BaseService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Interface/Base/Service" -import { Service as BackToBackService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/BackToBack/Service" +import { Service as BackToBackService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Interface/Issuance/BackToBack" import { Service as CustodyService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Interface/Custody/Service" import { Service as CustodyAutoService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Interface/Custody/Auto" -import { Service as DecentralizedExchangeService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Decentralized/Exchange/Service" +import { Service as DecentralizedExchangeService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Interface/Decentralized/Exchange/Service" import { Service as AuctionService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Interface/Distribution/Auction/Service" import { Service as AuctionAutoService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Interface/Distribution/Auction/Auto" import { Service as BiddingService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Interface/Distribution/Bidding/Service" import { Service as BiddingAutoService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Interface/Distribution/Bidding/Auto" -import { Service as SubscriptionService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Distribution/Subscription/Service" -import { Service as FundService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Distribution/Fund/Service" -import { Service as InvestmentService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Distribution/Investment/Service" +import { Service as SubscriptionService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Interface/Distribution/Subscription/Service" +import { Service as FundService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Interface/Distribution/Fund/Service" +import { Service as InvestmentService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Interface/Distribution/Investment/Service" import { Service as IssuanceService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Interface/Issuance/Service" import { Service as IssuanceAutoService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Interface/Issuance/Auto" -import { Service as LendingService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Lending/Service" -import { Service as LifecycleService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Lifecycle/Service" -import { Service as StructuringService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Structuring/Service" -import { Service as StructuringAutoService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Structuring/Auto/Service" +import { Service as LendingService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Interface/Lending/Service" +import { Service as LifecycleService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Interface/Lifecycle/Service" +import { Service as StructuringService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Interface/Structuring/Service" +import { Service as StructuringAutoService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Interface/Structuring/Auto" import { Service as ListingService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Interface/Listing/Service" import { Service as ListingAutoService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Interface/Listing/Auto" -import { Service as SettlementService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Settlement/Service" -import { Service as TradingService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Trading/Service" -import { Service as TradingAutoService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Trading/Auto/Service" +import { Service as SettlementService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Interface/Settlement/Service" +import { Service as TradingService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Interface/Trading/Service" +import { Service as TradingAutoService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Interface/Trading/Auto" -type ServicesAggregate = { - services : ServiceAggregate[] - getService : (provider : string, customer : string) => ServiceAggregate | undefined +type ServicesAggregate = { + services : ServiceAggregate[] + getService : (provider : string, customer : string) => ServiceAggregate | undefined }; -type ServiceAggregate = CreateEvent & { +type ServiceAggregate = CreateEvent & { service : CreateEvent - auto : CreateEvent | undefined }; export type ServicesState = { loading : boolean - auction : ServicesAggregate - backToBack : readonly CreateEvent[] - bidding : ServicesAggregate - custody : ServicesAggregate - decentralizedExchange : readonly CreateEvent[] - fund : readonly CreateEvent[] - investment : readonly CreateEvent[] - issuance : ServicesAggregate - lending : readonly CreateEvent[] - lifecycle : readonly CreateEvent[] - listing : ServicesAggregate - settlement : readonly CreateEvent[] - structuringAuto : readonly CreateEvent[] - structuring : readonly CreateEvent[] - subscription : readonly CreateEvent[] - tradingAuto : readonly CreateEvent[] - trading : readonly CreateEvent[] + auction : ServicesAggregate + auctionAuto : ServicesAggregate + backToBack : ServicesAggregate + bidding : ServicesAggregate + biddingAuto : ServicesAggregate + custody : ServicesAggregate + custodyAuto : ServicesAggregate + decentralizedExchange : ServicesAggregate + fund : ServicesAggregate + investment : ServicesAggregate + issuance : ServicesAggregate + issuanceAuto : ServicesAggregate + lending : ServicesAggregate + lifecycle : ServicesAggregate + listing : ServicesAggregate + listingAuto : ServicesAggregate + settlement : ServicesAggregate + structuring : ServicesAggregate + structuringAuto : ServicesAggregate + subscription : ServicesAggregate + trading : ServicesAggregate + tradingAuto : ServicesAggregate }; const emptyAggregate = { @@ -66,23 +70,28 @@ const emptyAggregate = { const empty = { loading: true, - auction: emptyAggregate, - backToBack: [], - bidding: emptyAggregate, - custody: emptyAggregate, - decentralizedExchange: [], - fund: [], - investment: [], - issuance: emptyAggregate, - lending: [], - lifecycle: [], - listing: emptyAggregate, - settlement: [], - structuringAuto: [], - structuring: [], - subscription: [], - tradingAuto: [], - trading: [] + auction : emptyAggregate, + auctionAuto : emptyAggregate, + backToBack : emptyAggregate, + bidding : emptyAggregate, + biddingAuto : emptyAggregate, + custody : emptyAggregate, + custodyAuto : emptyAggregate, + decentralizedExchange : emptyAggregate, + fund : emptyAggregate, + investment : emptyAggregate, + issuance : emptyAggregate, + issuanceAuto : emptyAggregate, + lending : emptyAggregate, + lifecycle : emptyAggregate, + listing : emptyAggregate, + listingAuto : emptyAggregate, + settlement : emptyAggregate, + structuring : emptyAggregate, + structuringAuto : emptyAggregate, + subscription : emptyAggregate, + trading : emptyAggregate, + tradingAuto : emptyAggregate, }; const ServicesContext = React.createContext(empty); @@ -114,11 +123,10 @@ export const ServicesProvider : React.FC = ({ children }) => { const { loading: l23, contracts: trading } = useStreamQueries(TradingService); const loading = l1 || l2 || l3 || l4 || l5 || l6 || l7 || l8 || l9 || l10 || l11 || l12 || l13 || l14 || l15 || l16 || l17 || l18 || l19 || l20 || l21 || l22 || l23; - const createServicesAggregate = (services : readonly CreateEvent[], autoServices : readonly CreateEvent[]) : ServicesAggregate => { + const createServicesAggregate = (services : readonly CreateEvent[]) : ServicesAggregate => { const serviceByCid : Map> = new Map(services.map(c => [c.contractId, c])); - const autoByCid : Map> = new Map(autoServices.map(c => [c.contractId, c])); const filteredBase = base.filter(c => serviceByCid.has(c.contractId as string)); - const aggregates : ServiceAggregate[] = filteredBase.map(c => ({ ...c, service: serviceByCid.get(c.contractId)!, auto: autoByCid.get(c.contractId) })); + const aggregates : ServiceAggregate[] = filteredBase.map(c => ({ ...c, service: serviceByCid.get(c.contractId)! })); const getService = (provider : string, customer : string) => { return aggregates.find(c => c.payload.provider === provider && c.payload.customer === customer) }; return { services: aggregates, getService }; }; @@ -133,23 +141,28 @@ export const ServicesProvider : React.FC = ({ children }) => { const value = { loading, - auction : createServicesAggregate(auction, auctionAuto), - backToBack, - bidding : createServicesAggregate(bidding, biddingAuto), - custody : createServicesAggregate(custody, custodyAuto), - decentralizedExchange, - fund, - investment, - issuance : createServicesAggregate(issuance, issuanceAuto), - lending, - lifecycle, - listing : createServicesAggregate(listing, listingAuto), - settlement, - structuringAuto, - structuring, - subscription, - tradingAuto, - trading, + auction : createServicesAggregate(auction), + auctionAuto : createServicesAggregate(auctionAuto), + backToBack : createServicesAggregate(backToBack), + bidding : createServicesAggregate(bidding), + biddingAuto : createServicesAggregate(biddingAuto), + custody : createServicesAggregate(custody), + custodyAuto : createServicesAggregate(custodyAuto), + decentralizedExchange : createServicesAggregate(decentralizedExchange), + fund : createServicesAggregate(fund), + investment : createServicesAggregate(investment), + issuance : createServicesAggregate(issuance), + issuanceAuto : createServicesAggregate(issuanceAuto), + lending : createServicesAggregate(lending), + lifecycle : createServicesAggregate(lifecycle), + listing : createServicesAggregate(listing), + listingAuto : createServicesAggregate(listingAuto), + settlement : createServicesAggregate(settlement), + structuring : createServicesAggregate(structuring), + structuringAuto : createServicesAggregate(structuringAuto), + subscription : createServicesAggregate(subscription), + trading : createServicesAggregate(trading), + tradingAuto : createServicesAggregate(tradingAuto), }; return ( diff --git a/ui/src/pages/defi/Exchange.tsx b/ui/src/pages/defi/Exchange.tsx index c9244ec1..a88bb86c 100644 --- a/ui/src/pages/defi/Exchange.tsx +++ b/ui/src/pages/defi/Exchange.tsx @@ -10,7 +10,7 @@ import { Button, Grid, Paper, Table, TableBody, TableCell, TableRow, TextField, import { Percentage } from "../../components/Slider/Percentage"; import useStyles from "../styles"; import { Bonding } from "../../components/Curve/Bonding"; -import { Service } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Decentralized/Exchange/Service"; +import { Service } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Interface/Decentralized/Exchange/Service"; import { useServices } from "../../context/ServicesContext"; import { useHoldings } from "../../context/HoldingContext"; import { useAccounts } from "../../context/AccountContext"; @@ -32,7 +32,7 @@ export const Exchange : React.FC = () => { const { loading: l1, decentralizedExchange } = useServices(); const { loading: l2, getFungible, holdings } = useHoldings(); const { loading: l3, getAccount } = useAccounts(); - const dex = decentralizedExchange.find(c => c.payload.id.unpack === dexId); + const dex = decentralizedExchange.services.find(c => c.service.payload.id.unpack === dexId)?.service; useEffect(() => { if (!dex) return; diff --git a/ui/src/pages/defi/Exchanges.tsx b/ui/src/pages/defi/Exchanges.tsx index a8e37bf0..57132a26 100644 --- a/ui/src/pages/defi/Exchanges.tsx +++ b/ui/src/pages/defi/Exchanges.tsx @@ -17,7 +17,7 @@ export const Exchanges : React.FC = () => { - {decentralizedExchange.map(c => c.payload).sort((a, b) => a.id.unpack.localeCompare(b.id.unpack)).map((p, i) => )} + {decentralizedExchange.services.map(c => c.service.payload).sort((a, b) => a.id.unpack.localeCompare(b.id.unpack)).map((p, i) => )} diff --git a/ui/src/pages/distribution/auction/Bidding.tsx b/ui/src/pages/distribution/auction/Bidding.tsx index 5f9960e7..14da8c73 100644 --- a/ui/src/pages/distribution/auction/Bidding.tsx +++ b/ui/src/pages/distribution/auction/Bidding.tsx @@ -31,7 +31,7 @@ export const Bidding : React.FC = () => { const { getName } = useParties(); const party = useParty(); const ledger = useLedger(); - const { loading: l1, bidding } = useServices(); + const { loading: l1, bidding, biddingAuto } = useServices(); const { loading: l2, latests } = useInstruments(); const { loading: l3, getFungible } = useHoldings(); const { loading: l4, contracts: auctions } = useStreamQueries(Auction); @@ -55,8 +55,6 @@ export const Bidding : React.FC = () => { const receivableAccount = accounts.find(c => c.payload.accountView.owner === party && c.payload.accountView.custodian === instrument.payload.depository)?.key; const collateralCid = await getFungible(party, volume, auction.payload.currency); if (!receivableAccount) return; - const svc = bidding.getService(auction.payload.provider, party); - if (!svc) throw new Error("No bidding service found for provider [" + auction.payload.provider + "] and customer [" + party + "]"); const arg = { auctionCid: auction.contractId, price: price.toString(), @@ -64,7 +62,10 @@ export const Bidding : React.FC = () => { collateralCid, receivableAccount }; - if (!!svc.auto) await ledger.exercise(ServiceAuto.RequestAndCreateBid, svc.auto.contractId, arg); + const svc = bidding.getService(auction.payload.provider, party); + const auto = biddingAuto.getService(auction.payload.provider, party); + if (!svc) throw new Error("No bidding service found for provider [" + auction.payload.provider + "] and customer [" + party + "]"); + if (!!auto) await ledger.exercise(ServiceAuto.RequestAndCreateBid, auto.service.contractId, arg); else await ledger.exercise(Service.RequestCreateBid, svc.service.contractId, arg); }; diff --git a/ui/src/pages/distribution/auction/New.tsx b/ui/src/pages/distribution/auction/New.tsx index c531702b..552d4b4f 100644 --- a/ui/src/pages/distribution/auction/New.tsx +++ b/ui/src/pages/distribution/auction/New.tsx @@ -34,7 +34,7 @@ export const New : React.FC = () => { const ledger = useLedger(); const party = useParty(); const { getParty } = useParties(); - const { loading: l1, auction } = useServices(); + const { loading: l1, auction, auctionAuto } = useServices(); const { loading: l2, latests, tokens } = useInstruments(); const { loading: l3, holdings, getFungible } = useHoldings(); const { loading: l4, contracts: accounts } = useStreamQueries(Reference); @@ -53,9 +53,6 @@ export const New : React.FC = () => { const collateralCid = await getFungible(party, amount, instrument.key); const receivableAccount = accounts.find(c => c.payload.accountView.custodian === currency.payload.depository && c.payload.accountView.owner === party)?.key; if (!receivableAccount) throw new Error("Receivable account not found"); - const agent = getParty("Agent"); // TODO: Hard-coded agent party - const svc = auction.getService(agent, party); - if (!svc) throw new Error("No auction service found for provider [" + agent + "] and customer [" + party + "]"); const arg = { auctionId: { unpack: uuidv4() }, description, @@ -66,7 +63,11 @@ export const New : React.FC = () => { receivableAccount, observers: createSet([getParty("Public")]) }; - if (!!svc.auto) await ledger.exercise(AuctionAuto.RequestAndCreateAuction, svc.auto.contractId, arg); + // TODO: Assumes single service + const svc = auction.services[0]; + const auto = auctionAuto.services[0]; + if (!svc) throw new Error("No structuring service found for customer [" + party + "]"); + if (!!auto) await ledger.exercise(AuctionAuto.RequestAndCreateAuction, auto.service.contractId, arg); else await ledger.exercise(Auction.RequestCreateAuction, svc.service.contractId, arg); navigate("/app/distribution/auctions"); }; diff --git a/ui/src/pages/distribution/investment/Funds.tsx b/ui/src/pages/distribution/investment/Funds.tsx index 90d22747..89befe28 100644 --- a/ui/src/pages/distribution/investment/Funds.tsx +++ b/ui/src/pages/distribution/investment/Funds.tsx @@ -23,7 +23,7 @@ export const Funds : React.FC = () => { const { loading: l1, investment } = useServices(); const { loading: l2, contracts: requests } = useStreamQueries(Fund); if (l1 || l2) return ; - const isInvestor = !!investment.find(c => c.payload.customer === party); + const isInvestor = !!investment.services.find(c => c.payload.customer === party); const createRow = (c : CreateEvent) : any[] => { return [ diff --git a/ui/src/pages/distribution/investment/New.tsx b/ui/src/pages/distribution/investment/New.tsx index 1b87d67c..ee17e689 100644 --- a/ui/src/pages/distribution/investment/New.tsx +++ b/ui/src/pages/distribution/investment/New.tsx @@ -9,12 +9,12 @@ import { Typography, Grid, Paper, Button } from "@mui/material"; import useStyles from "../../styles"; import { Spinner } from "../../../components/Spinner/Spinner"; import { useServices } from "../../../context/ServicesContext"; -import { Service as Investment } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Distribution/Investment/Service"; +import { Service as Investment } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Interface/Distribution/Investment/Service"; import { Message } from "../../../components/Message/Message"; import { useHoldings } from "../../../context/HoldingContext"; import { TextInput } from "../../../components/Form/TextInput"; import { SelectInput } from "../../../components/Form/SelectInput"; -import { Fund } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Distribution/Fund/Model"; +import { Fund } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Interface/Distribution/Fund/Fund"; import { ContractId } from "@daml/types"; import { Transferable } from "@daml.js/daml-finance-interface-holding/lib/Daml/Finance/Interface/Holding/Transferable"; import { useParties } from "../../../context/PartiesContext"; @@ -35,12 +35,13 @@ export const New : React.FC = () => { const { loading: l3, contracts: funds } = useStreamQueries(Fund); if (l1 || l2 || l3) return ; - const myServices = investment.filter(s => s.payload.customer === party); + const myServices = investment.services.filter(s => s.payload.customer === party); + const svc = myServices[0]; const fund = funds.find(c => c.payload.id.unpack === fundId); const canRequest = !!fundId && !!amount; const amountLabel = "Amount (" + (!!fund ? fund.payload.currency.id.unpack : "CCY") + ")"; const fundValues = funds.map(c => ({ value: c.payload.id.unpack, display: c.payload.id.unpack + " - " + c.payload.description })); - if (myServices.length === 0) return ; + if (!svc) return ; const requestInvestment = async () => { if (!fund) return; @@ -53,7 +54,7 @@ export const New : React.FC = () => { fundCid: fund.contractId, cashCid: cashCid as string as ContractId }; - await ledger.exercise(Investment.RequestInvestment, myServices[0].contractId, arg); + await ledger.exercise(Investment.RequestInvestment, svc.service.contractId, arg); navigate("/app/distribution/investmentrequests"); } diff --git a/ui/src/pages/distribution/investment/PooledRequests.tsx b/ui/src/pages/distribution/investment/PooledRequests.tsx index 08658738..7bb318cf 100644 --- a/ui/src/pages/distribution/investment/PooledRequests.tsx +++ b/ui/src/pages/distribution/investment/PooledRequests.tsx @@ -9,8 +9,9 @@ import { fmt } from "../../../util"; import { useParties } from "../../../context/PartiesContext"; import { useServices } from "../../../context/ServicesContext"; import { Alignment, HorizontalTable } from "../../../components/Table/HorizontalTable"; -import { Service as FundService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Distribution/Fund/Service"; -import { Fund, PooledInvestmentRequest } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Distribution/Fund/Model"; +import { Service as FundService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Interface/Distribution/Fund/Service"; +import { Fund } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Interface/Distribution/Fund/Fund"; +import { PooledInvestmentRequest } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Interface/Distribution/Fund/PooledInvestmentRequest"; import { Button } from "@mui/material"; import useStyles from "../../styles"; import { NumericObservable } from "@daml.js/daml-finance-interface-data/lib/Daml/Finance/Interface/Data/NumericObservable"; @@ -29,12 +30,12 @@ export const PooledRequests : React.FC = () => { const { loading: l5, contracts: factories } = useStreamQueries(Factory); if (l1 || l2 || l3 || l4 || l5) return ; - const myServices = fund.filter(s => s.payload.provider === party); + const myServices = fund.services.filter(s => s.payload.provider === party); const canFulFill = myServices.length > 0; const fulfillRequest = async (pir : CreateEvent) => { - const service = myServices[0]; - if (!service) throw new Error("No fund service found"); + const svc = myServices[0]; + if (!svc) throw new Error("No fund service found"); const fundId = pir.payload.fundId.unpack; const fundContract = funds.find(c => c.payload.id.unpack === fundId); if (!fundContract) throw new Error("Fund [" + fundId + "] not found"); @@ -42,16 +43,16 @@ export const PooledRequests : React.FC = () => { if (!observable) throw new Error("NAV observable for [" + fundId + "] not found"); const factory = factories[0]; if (!factory) throw new Error("Settlement factory not found"); - const svc = issuance.getService(fundContract.payload.custodian, party); - if (!svc) throw new Error("No issuance service found for provider [" + fundContract.payload.custodian + "] and customer [" + party + "]"); + const issuanceSvc = issuance.getService(fundContract.payload.custodian, party); + if (!issuanceSvc) throw new Error("No issuance service found for provider [" + fundContract.payload.custodian + "] and customer [" + party + "]"); const arg = { pooledInvestmentRequestCid: pir.contractId, fundCid: fundContract.contractId, navObservableCid: observable.contractId, settlementFactoryCid: factory.contractId, - issuanceServiceCid: svc.service.contractId + issuanceServiceCid: issuanceSvc.service.contractId }; - await ledger.exercise(FundService.FulfillPooledInvestmentRequest, service.contractId, arg); + await ledger.exercise(FundService.FulfillPooledInvestmentRequest, svc.service.contractId, arg); } const createRow = (c : CreateEvent) : any[] => { diff --git a/ui/src/pages/distribution/investment/Requests.tsx b/ui/src/pages/distribution/investment/Requests.tsx index 67cfbc6f..00221e83 100644 --- a/ui/src/pages/distribution/investment/Requests.tsx +++ b/ui/src/pages/distribution/investment/Requests.tsx @@ -9,14 +9,14 @@ import { Spinner } from "../../../components/Spinner/Spinner"; import { dedup, fmt } from "../../../util"; import { useParties } from "../../../context/PartiesContext"; import { useServices } from "../../../context/ServicesContext"; -import { InvestmentRequest } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Distribution/Investment/Model"; +import { InvestmentRequest } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Interface/Distribution/Investment/InvestmentRequest"; import { Alignment, HorizontalTable } from "../../../components/Table/HorizontalTable"; import { SelectionTable } from "../../../components/Table/SelectionTable"; import { ContractId } from "@daml/types"; -import { Service as FundService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Distribution/Fund/Service"; +import { Service as FundService } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Interface/Distribution/Fund/Service"; import { useHoldings } from "../../../context/HoldingContext"; import { Transferable } from "@daml.js/daml-finance-interface-holding/lib/Daml/Finance/Interface/Holding/Transferable"; -import { Fund } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Distribution/Fund/Model"; +import { Fund } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Interface/Distribution/Fund/Fund"; export const Requests : React.FC = () => { const navigate = useNavigate(); @@ -30,12 +30,12 @@ export const Requests : React.FC = () => { const { loading: l4, contracts: requests } = useStreamQueries(InvestmentRequest); if (l1 || l2 || l3 || l4) return ; - const myServices = fund.filter(s => s.payload.customer === party); + const myServices = fund.services.filter(s => s.payload.customer === party); const canPool = myServices.length > 0; const poolRequests = async (cs : CreateEvent[]) => { - const service = myServices[0]; - if (!service) throw new Error("No fund service found"); + const svc = myServices[0]; + if (!svc) throw new Error("No fund service found"); const total = cs.reduce((a, b) => a + parseFloat(b.payload.quantity.amount), 0); const fundIds = dedup(cs.map(c => c.payload.fundId.unpack)); if (fundIds.length > 1) throw new Error("Investment requests for more than one fund selected"); @@ -51,7 +51,7 @@ export const Requests : React.FC = () => { cashCid: cashCid as string as ContractId, investmentRequestCids: cs.map(c => c.contractId) }; - await ledger.exercise(FundService.PoolInvestmentRequests, service.contractId, arg); + await ledger.exercise(FundService.PoolInvestmentRequests, svc.service.contractId, arg); navigate("../pooledrequests"); } diff --git a/ui/src/pages/distribution/offering/New.tsx b/ui/src/pages/distribution/offering/New.tsx index 1e002be1..92d6b6e8 100644 --- a/ui/src/pages/distribution/offering/New.tsx +++ b/ui/src/pages/distribution/offering/New.tsx @@ -3,15 +3,16 @@ import React, { useState } from "react"; import { useNavigate } from "react-router-dom"; +import { v4 as uuidv4 } from "uuid"; import classnames from "classnames"; import { useLedger, useParty, useStreamQueries } from "@daml/react"; import { Typography, Grid, Paper, Select, MenuItem, TextField, Button, MenuProps, FormControl, InputLabel, Box } from "@mui/material"; import useStyles from "../../styles"; -import { CreateOffering, Service } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Distribution/Subscription/Service"; +import { Service } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Interface/Distribution/Subscription/Service"; import { Spinner } from "../../../components/Spinner/Spinner"; import { Reference } from "@daml.js/daml-finance-interface-account/lib/Daml/Finance/Interface/Account/Account"; import { dedup } from "../../../util"; -import { BackToBack } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Distribution/Subscription/Model"; +import { BackToBack } from "@daml.js/daml-finance-app/lib/Daml/Finance/App/Interface/Distribution/Subscription/Types"; import { useServices } from "../../../context/ServicesContext"; import { useInstruments } from "../../../context/InstrumentContext"; import { Message } from "../../../components/Message/Message"; @@ -22,7 +23,7 @@ export const New : React.FC = () => { const classes = useStyles(); const navigate = useNavigate(); - const [ id, setId ] = useState(""); + const [ description, setDescription ] = useState(""); const [ offeredInstLabel, setOfferedInstLabel ] = useState(""); const [ priceInstLabel, setPriceInstLabel ] = useState(""); const [ amount, setAmount ] = useState(""); @@ -36,9 +37,9 @@ export const New : React.FC = () => { const { contracts: accounts, loading: l4 } = useStreamQueries(Reference); - const myServices = subscription.filter(s => s.payload.customer === party); - const myB2BServices = backToBack.filter(s => s.payload.customer === party); - const hasB2B = backToBack.length > 0; + const myServices = subscription.services.filter(s => s.payload.customer === party); + const myB2BServices = backToBack.services.filter(s => s.payload.customer === party); + const hasB2B = backToBack.services.length > 0; const offeredInst = latests.find(c => c.payload.id.unpack === offeredInstLabel); const priceInst = tokens.find(c => c.payload.id.unpack === priceInstLabel); @@ -55,6 +56,7 @@ export const New : React.FC = () => { const customerAccount = accounts.find(c => c.payload.accountView.custodian === priceInst.payload.depository && c.payload.accountView.owner === party)?.key; const holdingCid = await getFungible(party, amount, offeredInst.key); if (!customerAccount) return; + const offeringId = { unpack: uuidv4() }; if (hasB2B) { const notional = parseFloat(amount) * parseFloat(price); const b2b = myB2BServices[0].payload.provider; @@ -63,7 +65,6 @@ export const New : React.FC = () => { if (!b2bReceivableAccount || !issuerReceivableAccount) return; const b2bDeliverableCid = await getFungible(b2b, amount, offeredInst.key); const issuerDeliverableCid = await getFungible(party, notional, priceInst.key); - const offeringId = id; const backToBack : BackToBack = { party: b2b, offeringId, @@ -72,25 +73,27 @@ export const New : React.FC = () => { b2bReceivableAccount, b2bDeliverableCid }; - const arg : CreateOffering = { + const arg = { offeringId, + description, asset: { amount: amount, unit: offeredInst.key }, price: { amount: price, unit: priceInst.key }, customerHoldingCid: holdingCid, customerAccount, backToBack }; - await ledger.exercise(Service.CreateOffering, myServices[0].contractId, arg); + await ledger.exercise(Service.CreateOffering, myServices[0].service.contractId, arg); } else { - const arg : CreateOffering = { - offeringId: id, + const arg = { + offeringId, + description, asset: { amount: amount, unit: offeredInst.key }, price: { amount: price, unit: priceInst.key }, customerHoldingCid: holdingCid, customerAccount, backToBack: null }; - await ledger.exercise(Service.CreateOffering, myServices[0].contractId, arg); + await ledger.exercise(Service.CreateOffering, myServices[0].service.contractId, arg); } navigate("/app/distribution/offerings"); } @@ -108,7 +111,7 @@ export const New : React.FC = () => { Details - setId(e.target.value as string)} /> + setDescription(e.target.value as string)} /> Offered Asset