da-syndication-finance-temp.../daml/Scripts/Transfer.daml

155 lines
5.0 KiB
Plaintext
Raw Normal View History

2023-05-08 20:09:16 +00:00
module Scripts.Transfer where
import DA.Map (empty, fromList)
import DA.Set (singleton)
import Daml.Script
-- INTERFACE DEPENDENCIES --
import Daml.Finance.Interface.Account.Factory qualified as Account (F)
import Daml.Finance.Interface.Holding.Base qualified as Holding (I)
import Daml.Finance.Interface.Holding.Factory qualified as Holding (F)
import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (I)
import Daml.Finance.Interface.Types.Common.Types (AccountKey, Id(..), InstrumentKey(..))
-- IMPLEMENTATION DEPENDENCIES --
import Daml.Finance.Account.Account qualified as Account (Factory(..))
import Daml.Finance.Holding.Fungible qualified as Fungible (Factory(..))
import Daml.Finance.Instrument.Token.Instrument (Instrument(..))
import Workflow.CreateAccount qualified as CreateAccount
import Workflow.CreditAccount qualified as CreditAccount
import Workflow.Transfer qualified as Transfer
-- | Helper container used to transfer state from one script to another.
data TransferState = TransferState
with
alice : Party
bank : Party
bob : Party
public : Party
aliceAccount : AccountKey
bobAccount : AccountKey
cashInstrument : InstrumentKey
holdingFactoryCid : ContractId Holding.F
newHoldingCid : ContractId Holding.I
deriving (Eq, Show)
-- | Test script that
-- 1. creates an account for Alice and Bob at the Bank
-- 2. issues a cash instrument
-- 3. credits a cash holding to Alice in her bank account
-- 4. transfers the holding from Alice to Bob
runTransfer : Script TransferState
runTransfer = do
-- Allocate parties
[alice, bank, bob, public] <- mapA createParty $ ["Alice", "Bank", "Bob", "Public"]
-- Account Factory (it is used by the bank to create accounts)
-- CREATE_ACCOUNT_FACTORY_BEGIN
accountFactoryCid <- toInterfaceContractId @Account.F <$> submit bank do
createCmd Account.Factory with provider = bank; observers = empty
-- CREATE_ACCOUNT_FACTORY_END
-- Holding Factory (it is used by the bank to create holdings with the desired implementation)
-- CREATE_HOLDING_FACTORY_BEGIN
holdingFactoryCid <- toInterfaceContractId @Holding.F <$> submit bank do
createCmd Fungible.Factory with
provider = bank
observers = fromList [("PublicObserver", singleton public )]
-- CREATE_HOLDING_FACTORY_END
-- Alice and Bob setup account @Bank
-- SETUP_ALICE_ACCOUNT_BEGIN
aliceRequestCid <- submit alice do
createCmd CreateAccount.Request with owner = alice; custodian = bank
aliceAccount <- submit bank do
exerciseCmd aliceRequestCid CreateAccount.Accept with
label = "Alice@Bank"
description = "Account of Alice at Bank"
accountFactoryCid = accountFactoryCid
holdingFactoryCid = holdingFactoryCid
observers = []
-- SETUP_ALICE_ACCOUNT_END
bobRequestCid <- submit bob do createCmd CreateAccount.Request with owner = bob; custodian = bank
bobAccount <- submit bank do
exerciseCmd bobRequestCid CreateAccount.Accept with
label = "Bob@Bank"
description = "Account of Bob at Bank"
accountFactoryCid = accountFactoryCid
holdingFactoryCid = holdingFactoryCid
observers = [alice]
-- Bank creates the cash instrument
-- ISSUE_CASH_INSTRUMENT_BEGIN
let
instrumentId = Id "USD"
instrumentVersion = "0"
now <- getTime
cashInstrumentCid <- toInterfaceContractId @Instrument.I <$> submit bank do
createCmd Instrument with
depository = bank
issuer = bank
id = instrumentId
version = instrumentVersion
description = "Instrument representing units of USD"
validAsOf = now
observers = empty
-- ISSUE_CASH_INSTRUMENT_END
-- Alice deposits cash at the bank
-- CREATE_ALICE_HOLDING_BEGIN
aliceRequestCid <- submit alice do
createCmd CreditAccount.Request with
account = aliceAccount
instrument = InstrumentKey with
issuer = bank
depository = bank
id = instrumentId
version = instrumentVersion
amount = 1000.0
aliceCashHoldingCid <- submit bank do exerciseCmd aliceRequestCid CreditAccount.Accept
-- CREATE_ALICE_HOLDING_END
-- Bob requests a cash transfer from Alice
-- TRANSFER_BEGIN
let
cashInstrument = InstrumentKey with
issuer = bank
depository = bank
id = instrumentId
version = instrumentVersion
transferRequestCid <- submit bob do
createCmd Transfer.Request with
receiverAccount = bobAccount
instrument = cashInstrument
amount = 1000.0
currentOwner = alice
newHoldingCid <- submitMulti [alice] [public] do
exerciseCmd transferRequestCid Transfer.Accept with holdingCid = aliceCashHoldingCid
-- TRANSFER_END
pure $ TransferState with
alice
bank
bob
public
aliceAccount
bobAccount
cashInstrument
holdingFactoryCid
newHoldingCid
-- | Creates a user + party given a hint
createParty : Text -> Script Party
createParty name = do
party <- allocatePartyWithHint name $ PartyIdHint name
userId <- validateUserId name
createUser (User userId (Some party)) [CanActAs party]
pure party