155 lines
5.0 KiB
Plaintext
155 lines
5.0 KiB
Plaintext
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
|