175 lines
5.9 KiB
Plaintext
175 lines
5.9 KiB
Plaintext
module Scripts.Settlement where
|
|
|
|
import DA.Map as M (empty)
|
|
import DA.Set as S (fromList, singleton)
|
|
import Daml.Script
|
|
|
|
-- INTERFACE DEPENDENCIES --
|
|
import Daml.Finance.Interface.Holding.Base qualified as Holding (I)
|
|
import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (I)
|
|
import Daml.Finance.Interface.Settlement.Batch qualified as Batch (Settle(..))
|
|
import Daml.Finance.Interface.Settlement.Factory qualified as Settlement (F)
|
|
import Daml.Finance.Interface.Settlement.Instruction qualified as Instruction (Allocate(..), Approve(..))
|
|
import Daml.Finance.Interface.Settlement.RouteProvider qualified as RouteProvider (I)
|
|
import Daml.Finance.Interface.Settlement.Types (Allocation(..), Approval(..))
|
|
import Daml.Finance.Interface.Types.Common.Types (AccountKey, Id(..), InstrumentKey(..))
|
|
import Daml.Finance.Interface.Util.Common (qty)
|
|
|
|
-- IMPLEMENTATION DEPENDENCIES --
|
|
import Daml.Finance.Instrument.Token.Instrument (Instrument(..))
|
|
import Daml.Finance.Settlement.Factory (Factory(..))
|
|
import Daml.Finance.Settlement.RouteProvider.SingleCustodian (SingleCustodian(..))
|
|
|
|
import Workflow.CreditAccount qualified as CreditAccount
|
|
import Workflow.DvP qualified as DvP
|
|
|
|
import Scripts.Transfer (TransferState(..), runTransfer)
|
|
|
|
-- | Helper container used to transfer state from one script to another.
|
|
data SettlementState = SettlementState
|
|
with
|
|
alice : Party
|
|
bank : Party
|
|
bob : Party
|
|
public : Party
|
|
aliceAccount : AccountKey
|
|
bobAccount : AccountKey
|
|
usdInstrument : InstrumentKey
|
|
tokenInstrument : InstrumentKey
|
|
routeProviderCid : ContractId RouteProvider.I
|
|
settlementFactoryCid : ContractId Settlement.F
|
|
aliceHoldingCid : ContractId Holding.I
|
|
bobHoldingCid : ContractId Holding.I
|
|
deriving (Eq, Show)
|
|
|
|
-- | Test script that
|
|
-- 1. executes the `runTransfer` script
|
|
-- 2. creates a token instrument
|
|
-- 3. credits a token holding to Alice in her bank account
|
|
-- 4. atomically exchanges the token against the cash holding
|
|
runSettlement : Script SettlementState
|
|
runSettlement = do
|
|
|
|
-- Execute the `runTransfer` script. Bob now holds USD 1000 in his account.
|
|
TransferState{alice
|
|
, bank
|
|
, bob
|
|
, public
|
|
, aliceAccount
|
|
, bobAccount
|
|
, cashInstrument = usdInstrument
|
|
, holdingFactoryCid
|
|
, newHoldingCid = bobHoldingCid} <- runTransfer
|
|
|
|
-- Bank creates a token instrument
|
|
let
|
|
instrumentId = Id "TOKEN"
|
|
instrumentVersion = "0"
|
|
tokenInstrument = InstrumentKey with
|
|
issuer = bank
|
|
depository = bank
|
|
id = instrumentId
|
|
version = instrumentVersion
|
|
|
|
now <- getTime
|
|
|
|
tokenInstrumentCid <- toInterfaceContractId @Instrument.I <$> submit bank do
|
|
createCmd Instrument with
|
|
depository = bank
|
|
issuer = bank
|
|
id = instrumentId
|
|
version = instrumentVersion
|
|
description = "Instrument representing units of a generic token"
|
|
validAsOf = now
|
|
observers = empty
|
|
|
|
-- Credit Alice's account with a token holding
|
|
aliceRequestCid <- submit alice do
|
|
createCmd CreditAccount.Request with
|
|
account = aliceAccount
|
|
instrument = tokenInstrument
|
|
amount = 10.0
|
|
aliceHoldingCid <- submit bank do exerciseCmd aliceRequestCid CreditAccount.Accept
|
|
|
|
-- Setup a route provider
|
|
-- This is used transform settlement `Step`s into a `RoutedStep`s using a single custodian
|
|
-- ROUTE_PROVIDER_BEGIN
|
|
routeProviderCid <- toInterfaceContractId @RouteProvider.I <$> submit bank do
|
|
createCmd SingleCustodian with
|
|
provider = bank; observers = S.fromList [alice, bob] ; custodian = bank
|
|
-- ROUTE_PROVIDER_END
|
|
|
|
-- Setup a Settlement Factory facility
|
|
-- This is used to generate settlement instructions from a list of `RoutedStep`s
|
|
-- SETTLEMENT_FACTORY_BEGIN
|
|
settlementFactoryCid <- toInterfaceContractId @Settlement.F <$> submit bank do
|
|
createCmd Factory with
|
|
provider = bank
|
|
observers = S.fromList [alice, bob]
|
|
-- SETTLEMENT_FACTORY_END
|
|
|
|
-- Alice proposes an FX trade to Bob
|
|
-- DVP_PROPOSE_BEGIN
|
|
dvpProposalCid <- submit bob do
|
|
createCmd DvP.Proposal with
|
|
id = "xccy trade"
|
|
recQuantity = qty 10.0 tokenInstrument
|
|
payQuantity = qty 1000.0 usdInstrument
|
|
proposer = bob
|
|
counterparty = alice
|
|
routeProviderCid
|
|
settlementFactoryCid
|
|
-- DVP_PROPOSE_END
|
|
|
|
-- DVP_ACCEPT_BEGIN
|
|
(batchCid, recSettleInstructionCid, paySettleInstructionCid) <- submit alice do
|
|
exerciseCmd dvpProposalCid DvP.Accept
|
|
-- DVP_ACCEPT_END
|
|
|
|
-- Settle the DvP Trade
|
|
|
|
-- i. Bob allocates his asset, Alice approves by providing her account.
|
|
(allocatedPaySettleInstructionCid, _) <- submit bob do
|
|
exerciseCmd paySettleInstructionCid Instruction.Allocate with
|
|
actors = S.singleton bob
|
|
allocation = Pledge bobHoldingCid
|
|
|
|
approvedPaySettleInstructionCid <- submit alice do
|
|
exerciseCmd allocatedPaySettleInstructionCid Instruction.Approve with
|
|
actors = S.singleton alice
|
|
approval = TakeDelivery aliceAccount
|
|
|
|
-- ii. Alice allocates her asset, Bob approves by providing his account.
|
|
-- ALLOCATE_APPROVE_BEGIN
|
|
(allocatedRecSettleInstructionCid, _) <- submit alice do
|
|
exerciseCmd recSettleInstructionCid Instruction.Allocate with
|
|
actors = S.singleton alice
|
|
allocation = Pledge aliceHoldingCid
|
|
|
|
approvedRecSettleInstructionCid <- submit bob do
|
|
exerciseCmd allocatedRecSettleInstructionCid Instruction.Approve with
|
|
actors = S.singleton bob
|
|
approval = TakeDelivery bobAccount
|
|
-- ALLOCATE_APPROVE_END
|
|
|
|
-- iii. Bob executes the settlement.
|
|
-- SETTLE_BEGIN
|
|
[bobHoldingCid, aliceHoldingCid] <- submitMulti [bob] [public] do
|
|
exerciseCmd batchCid Batch.Settle with
|
|
actors = singleton bob
|
|
-- SETTLE_END
|
|
|
|
pure $ SettlementState with
|
|
alice
|
|
bank
|
|
bob
|
|
public
|
|
aliceAccount
|
|
bobAccount
|
|
usdInstrument
|
|
tokenInstrument
|
|
routeProviderCid
|
|
settlementFactoryCid
|
|
aliceHoldingCid = toInterfaceContractId aliceHoldingCid
|
|
bobHoldingCid = toInterfaceContractId bobHoldingCid
|