Initial commit
This commit is contained in:
commit
1e6d4aa792
10
README.md
Normal file
10
README.md
Normal file
@ -0,0 +1,10 @@
|
||||
# Code Samples - Getting Started
|
||||
|
||||
This project contains the source code used in the getting-started tutorials.
|
||||
|
||||
Before opening Visual Studio Code you should run `./get-dependencies.sh` (or `get-dependencies.bat`
|
||||
for Windows users) to download the required Daml packages.
|
||||
|
||||
You can then open Daml Studio by running `daml studio`, or build the project using `daml build`.
|
||||
|
||||
To run the project, run `daml start` (which also builds the project).
|
53
daml.yaml
Normal file
53
daml.yaml
Normal file
@ -0,0 +1,53 @@
|
||||
# for config file options, refer to
|
||||
# https://docs.daml.com/tools/assistant.html#project-config-file-daml-yaml
|
||||
|
||||
sdk-version: 2.6.3
|
||||
name: tmp-finance-template
|
||||
source: daml
|
||||
init-script: Scripts.Transfer:runTransfer
|
||||
version: 0.0.2
|
||||
dependencies:
|
||||
- daml-prim
|
||||
- daml-stdlib
|
||||
- daml-script
|
||||
data-dependencies:
|
||||
# INTERFACE DEPENDENCIES
|
||||
- .lib/daml-finance-interface-account.dar
|
||||
- .lib/daml-finance-interface-holding.dar
|
||||
- .lib/daml-finance-interface-instrument-base.dar
|
||||
- .lib/daml-finance-interface-lifecycle.dar
|
||||
- .lib/daml-finance-interface-settlement.dar
|
||||
- .lib/daml-finance-interface-types-common.dar
|
||||
- .lib/daml-finance-interface-util.dar
|
||||
# IMPLEMENTATION DEPENDENCIES
|
||||
- .lib/daml-finance-account.dar
|
||||
- .lib/daml-finance-holding.dar
|
||||
- .lib/daml-finance-instrument-token.dar
|
||||
- .lib/daml-finance-lifecycle.dar
|
||||
- .lib/daml-finance-settlement.dar
|
||||
# UNUSED INTERFACES DEPENDENCIES - UNCOMMENT TO ENABLE
|
||||
# - .lib/daml-finance-interface-claims.dar
|
||||
# - .lib/daml-finance-interface-data.dar
|
||||
# - .lib/daml-finance-interface-instrument-bond.dar
|
||||
# - .lib/daml-finance-interface-instrument-equity.dar
|
||||
# - .lib/daml-finance-interface-instrument-generic.dar
|
||||
# - .lib/daml-finance-interface-instrument-option.dar
|
||||
# - .lib/daml-finance-interface-instrument-swap.dar
|
||||
# - .lib/daml-finance-interface-instrument-token.dar
|
||||
# - .lib/daml-finance-interface-types-date.dar
|
||||
# UNUSED IMPLEMENTATIONS DEPENDENCIES - UNCOMMENT TO ENABLE
|
||||
# - .lib/daml-finance-claims.dar
|
||||
# - .lib/daml-finance-data.dar
|
||||
# - .lib/daml-finance-instrument-bond.dar
|
||||
# - .lib/daml-finance-instrument-equity.dar
|
||||
# - .lib/daml-finance-instrument-generic.dar
|
||||
# - .lib/daml-finance-instrument-option.dar
|
||||
# - .lib/daml-finance-instrument-swap.dar
|
||||
# - .lib/daml-finance-util.dar
|
||||
# UNUSED CONTINGENT CLAIMS DEPENDENCIES - UNCOMMENT TO ENABLE
|
||||
# - .lib/contingent-claims-core.dar
|
||||
# - .lib/contingent-claims-lifecycle.dar
|
||||
# - .lib/contingent-claims-valuation.dar
|
||||
start-navigator: no
|
||||
build-options:
|
||||
- --target=1.15
|
158
daml/Scripts/Lifecycling.daml
Normal file
158
daml/Scripts/Lifecycling.daml
Normal file
@ -0,0 +1,158 @@
|
||||
module Scripts.Lifecycling where
|
||||
|
||||
import DA.Map qualified as M (empty)
|
||||
import DA.Set qualified as S (empty, fromList, singleton)
|
||||
import Daml.Script
|
||||
|
||||
-- INTERFACE DEPENDENCIES --
|
||||
import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Instrument (I)
|
||||
import Daml.Finance.Interface.Lifecycle.Event qualified as Event (I)
|
||||
import Daml.Finance.Interface.Lifecycle.Rule.Claim qualified as Claim (ClaimEffect(..), I)
|
||||
import Daml.Finance.Interface.Lifecycle.Rule.Lifecycle qualified as Lifecycle (Evolve(..), I)
|
||||
import Daml.Finance.Interface.Settlement.Batch qualified as Batch (Settle(..))
|
||||
import Daml.Finance.Interface.Settlement.Instruction qualified as Instruction (Allocate(..), Approve(..))
|
||||
import Daml.Finance.Interface.Settlement.Types (Allocation(..), Approval(..))
|
||||
import Daml.Finance.Interface.Types.Common.Types (Id(..))
|
||||
import Daml.Finance.Interface.Util.Common (qty)
|
||||
|
||||
-- IMPLEMENTATION DEPENDENCIES --
|
||||
import Daml.Finance.Instrument.Token.Instrument (Instrument(..))
|
||||
import Daml.Finance.Lifecycle.Event.Distribution qualified as Distribution (Event(..))
|
||||
import Daml.Finance.Lifecycle.Rule.Claim qualified as Claim (Rule(..))
|
||||
import Daml.Finance.Lifecycle.Rule.Distribution qualified as Distribution (Rule(..))
|
||||
|
||||
import Scripts.Settlement (SettlementState(..), runSettlement)
|
||||
|
||||
-- | Test script that
|
||||
-- 1. executes the `runSettlement` script
|
||||
-- 2. creates a distribution lifecycle rule
|
||||
-- 3. creates a distribution lifecycle event
|
||||
-- 4. lifecycles the distribution event
|
||||
-- 5. processes the lifecycle effect
|
||||
-- 6. settles the distribution
|
||||
runLifecycling : Script()
|
||||
runLifecycling = do
|
||||
|
||||
-- Execute the `runSettlement` script. Bob now holds 10 tokens in his account.
|
||||
SettlementState{alice
|
||||
, bank
|
||||
, bob
|
||||
, public
|
||||
, aliceAccount
|
||||
, bobAccount
|
||||
, usdInstrument
|
||||
, tokenInstrument
|
||||
, routeProviderCid
|
||||
, settlementFactoryCid
|
||||
, aliceHoldingCid
|
||||
, bobHoldingCid} <- runSettlement
|
||||
|
||||
-- The bank creates a new version of the token instrument (the "ex-distribution" version). This is
|
||||
-- the version Bob will hold after claiming the effect further down below.
|
||||
-- NEW_VERSION_BEGIN
|
||||
let newTokenInstrument = tokenInstrument with version = "1"
|
||||
now <- getTime
|
||||
tokenInstrumentCid <- toInterfaceContractId @Instrument.I <$> submit bank do
|
||||
createCmd Instrument with
|
||||
depository = bank
|
||||
issuer = bank
|
||||
id = tokenInstrument.id
|
||||
version = "1"
|
||||
description = "Instrument representing units of a generic token"
|
||||
validAsOf = now
|
||||
observers = M.empty
|
||||
-- NEW_VERSION_END
|
||||
|
||||
-- Create lifecycle rules
|
||||
-- LIFECYCLE_RULES_BEGIN
|
||||
distributionRuleCid <- toInterfaceContractId @Lifecycle.I <$> submit bank do
|
||||
createCmd Distribution.Rule with
|
||||
providers = S.singleton bank
|
||||
lifecycler = bank
|
||||
observers = S.singleton bob
|
||||
id = Id "Lifecycle rule for distribution"
|
||||
description = "Rule contract to lifecycle an instrument following a distribution event"
|
||||
|
||||
lifecycleClaimRuleCid <- toInterfaceContractId @Claim.I <$> submitMulti [bank, bob] [] do
|
||||
createCmd Claim.Rule with
|
||||
providers = S.fromList [bank, bob]
|
||||
claimers = S.singleton bob
|
||||
settlers = S.singleton bob
|
||||
routeProviderCid
|
||||
settlementFactoryCid
|
||||
netInstructions = False
|
||||
-- LIFECYCLE_RULES_END
|
||||
|
||||
-- Create cash distribution event
|
||||
-- CREATE_EVENT_BEGIN
|
||||
distributionEventCid <- toInterfaceContractId @Event.I <$> submit bank do
|
||||
createCmd Distribution.Event with
|
||||
providers = S.singleton bank
|
||||
id = Id "DISTRIBUTION"
|
||||
description = "Profit distribution"
|
||||
effectiveTime = now
|
||||
targetInstrument = tokenInstrument
|
||||
newInstrument = newTokenInstrument
|
||||
perUnitDistribution = [qty 0.02 usdInstrument]
|
||||
observers = S.empty
|
||||
-- CREATE_EVENT_END
|
||||
|
||||
-- Lifecycle distribution event
|
||||
-- LIFECYCLE_EVENT_BEGIN
|
||||
(_, [effectCid]) <- submit bank do
|
||||
exerciseCmd distributionRuleCid Lifecycle.Evolve with
|
||||
eventCid = distributionEventCid
|
||||
observableCids = []
|
||||
instrument = tokenInstrument
|
||||
-- LIFECYCLE_EVENT_END
|
||||
|
||||
-- Claim effect
|
||||
-- CLAIM_EVENT_BEGIN
|
||||
result <- submitMulti [bob] [public] do
|
||||
exerciseCmd lifecycleClaimRuleCid Claim.ClaimEffect with
|
||||
claimer = bob
|
||||
holdingCids = [bobHoldingCid]
|
||||
effectCid
|
||||
batchId = Id "DistributionSettlement"
|
||||
let [bobInstructionCid, bankInstructionCid, couponInstructionCid] = result.instructionCids
|
||||
-- CLAIM_EVENT_END
|
||||
|
||||
-- EFFECT_SETTLEMENT_BEGIN
|
||||
-- Allocate instruction
|
||||
(bobInstructionCid, _) <- submit bob do
|
||||
exerciseCmd bobInstructionCid Instruction.Allocate with
|
||||
actors = S.singleton bob
|
||||
allocation = Pledge bobHoldingCid
|
||||
|
||||
(bankInstructionCid, _) <- submit bank do
|
||||
exerciseCmd bankInstructionCid Instruction.Allocate with
|
||||
actors = S.singleton bank
|
||||
allocation = CreditReceiver
|
||||
|
||||
(couponInstructionCid, _) <- submit bank do
|
||||
exerciseCmd couponInstructionCid Instruction.Allocate with
|
||||
actors = S.singleton bank
|
||||
allocation = CreditReceiver
|
||||
|
||||
-- Approve instruction
|
||||
bobInstructionCid <- submit bank do
|
||||
exerciseCmd bobInstructionCid Instruction.Approve with
|
||||
actors = S.singleton bank
|
||||
approval = DebitSender
|
||||
|
||||
bankInstructionCid <- submit bob do
|
||||
exerciseCmd bankInstructionCid Instruction.Approve with
|
||||
actors = S.singleton bob
|
||||
approval = TakeDelivery bobAccount
|
||||
|
||||
couponInstructionCid <- submit bob do
|
||||
exerciseCmd couponInstructionCid Instruction.Approve with
|
||||
actors = S.singleton bob
|
||||
approval = TakeDelivery bobAccount
|
||||
|
||||
-- Settle batch
|
||||
submitMulti [bob] [public] do
|
||||
exerciseCmd result.batchCid Batch.Settle with actors = S.singleton bob
|
||||
-- EFFECT_SETTLEMENT_END
|
||||
|
||||
pure ()
|
5
daml/Scripts/README.md
Normal file
5
daml/Scripts/README.md
Normal file
@ -0,0 +1,5 @@
|
||||
# Setup scripts
|
||||
|
||||
This folder includes setup scripts that are executed on a one-off basis.
|
||||
|
||||
Files in this folder can reference both interface and implementation packages of `daml-finance`.
|
174
daml/Scripts/Settlement.daml
Normal file
174
daml/Scripts/Settlement.daml
Normal file
@ -0,0 +1,174 @@
|
||||
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
|
154
daml/Scripts/Transfer.daml
Normal file
154
daml/Scripts/Transfer.daml
Normal file
@ -0,0 +1,154 @@
|
||||
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
|
63
daml/Workflow/CreateAccount.daml
Normal file
63
daml/Workflow/CreateAccount.daml
Normal file
@ -0,0 +1,63 @@
|
||||
module Workflow.CreateAccount where
|
||||
|
||||
import DA.Map qualified as M (fromList)
|
||||
import DA.Set qualified as S (fromList, singleton)
|
||||
import Daml.Finance.Interface.Account.Account qualified as Account (Controllers(..))
|
||||
import Daml.Finance.Interface.Account.Factory qualified as Account (Create(..), F)
|
||||
import Daml.Finance.Interface.Holding.Factory qualified as Holding (F)
|
||||
import Daml.Finance.Interface.Types.Common.Types (AccountKey(..), Id(..))
|
||||
|
||||
-- | Initiate / Accept template to open an account.
|
||||
-- The account is created using an `Account.Factory` template. By doing so, our workflow is generic
|
||||
-- and does not depend on the specific account implementation. For the same reason, we need to
|
||||
-- provide a `Holding.Factory` that will be used by the account to create holdings without depending
|
||||
-- on the specific implementation.
|
||||
template Request
|
||||
with
|
||||
custodian : Party
|
||||
-- ^ The account's custodian.
|
||||
owner : Party
|
||||
-- ^ The account's owner.
|
||||
where
|
||||
signatory owner
|
||||
observer custodian
|
||||
|
||||
choice Accept : AccountKey
|
||||
-- ^ Accept the request.
|
||||
with
|
||||
label : Text
|
||||
-- ^ A textual label.
|
||||
description : Text
|
||||
-- ^ An extended textual description.
|
||||
accountFactoryCid : ContractId Account.F
|
||||
-- ^ The account factory. This is used to create the account template.
|
||||
holdingFactoryCid : ContractId Holding.F
|
||||
-- ^ The holding factory. This is used within an account to create holdings.
|
||||
observers : [Party]
|
||||
-- ^ Observers of the account to be created.
|
||||
controller custodian
|
||||
do
|
||||
let
|
||||
observersSet = S.fromList observers
|
||||
accountKey = AccountKey with custodian = custodian, owner = owner, id = Id label
|
||||
|
||||
accountCid <- exercise accountFactoryCid Account.Create with
|
||||
account = accountKey
|
||||
description = description
|
||||
holdingFactoryCid = holdingFactoryCid
|
||||
controllers = Account.Controllers with
|
||||
outgoing = S.singleton owner
|
||||
incoming = S.singleton owner
|
||||
observers = M.fromList [("AccountObservers", observersSet)]
|
||||
|
||||
pure accountKey
|
||||
|
||||
choice Decline : ()
|
||||
-- ^ Decline the request.
|
||||
controller custodian
|
||||
do pure ()
|
||||
|
||||
choice Withdraw : ()
|
||||
-- ^ Withdraw the request.
|
||||
controller owner
|
||||
do pure ()
|
40
daml/Workflow/CreditAccount.daml
Normal file
40
daml/Workflow/CreditAccount.daml
Normal file
@ -0,0 +1,40 @@
|
||||
module Workflow.CreditAccount where
|
||||
|
||||
import Daml.Finance.Interface.Account.Account qualified as Account (Credit(..), I, exerciseInterfaceByKey)
|
||||
import Daml.Finance.Interface.Holding.Base qualified as Holding (I)
|
||||
import Daml.Finance.Interface.Types.Common.Types (AccountKey(..), InstrumentKey)
|
||||
import Daml.Finance.Interface.Util.Common (qty)
|
||||
|
||||
-- | Initiate / Accept template to credit a holding to an existing account.
|
||||
template Request
|
||||
with
|
||||
account : AccountKey
|
||||
-- ^ The account receiving the holding.
|
||||
instrument : InstrumentKey
|
||||
-- ^ The instrument to be credited.
|
||||
amount : Decimal
|
||||
-- ^ The number of units of the specified instrument to be credited.
|
||||
where
|
||||
signatory account.owner
|
||||
observer account.custodian
|
||||
|
||||
ensure amount > 0.0
|
||||
|
||||
choice Accept : ContractId Holding.I
|
||||
-- ^ Accept the request. In the case of physical assets (e.g. paper certificates, banknotes),
|
||||
-- a custodian would generally accept the request once they have got hold of the physical
|
||||
-- asset.
|
||||
controller account.custodian
|
||||
do
|
||||
Account.exerciseInterfaceByKey @Account.I account account.custodian Account.Credit with
|
||||
quantity = qty amount instrument
|
||||
|
||||
choice Decline : ()
|
||||
-- ^ Decline the request.
|
||||
controller account.custodian
|
||||
do pure ()
|
||||
|
||||
choice Withdraw : ()
|
||||
-- ^ Withdraw the request.
|
||||
controller account.owner
|
||||
do pure ()
|
73
daml/Workflow/DvP.daml
Normal file
73
daml/Workflow/DvP.daml
Normal file
@ -0,0 +1,73 @@
|
||||
module Workflow.DvP where
|
||||
|
||||
import DA.Set (fromList, singleton)
|
||||
import Daml.Finance.Interface.Settlement.Batch qualified as Batch (I)
|
||||
import Daml.Finance.Interface.Settlement.Factory qualified as Settlement (F, Instruct(..))
|
||||
import Daml.Finance.Interface.Settlement.Instruction qualified as Instruction (I)
|
||||
import Daml.Finance.Interface.Settlement.RouteProvider qualified as RouteProvider (I, Discover(..))
|
||||
import Daml.Finance.Interface.Settlement.Types (Step(..))
|
||||
import Daml.Finance.Interface.Types.Common.Types (Id(..), InstrumentQuantity)
|
||||
|
||||
-- | Initiate / Accept template to exchange two holdings.
|
||||
template Proposal
|
||||
with
|
||||
recQuantity : InstrumentQuantity
|
||||
-- ^ The receiving leg (instrument and amount).
|
||||
payQuantity : InstrumentQuantity
|
||||
-- ^ The pay leg (instrument and amount).
|
||||
proposer : Party
|
||||
-- ^ The party proposing the trade. They receive the receiving leg in exchange for the pay
|
||||
-- leg.
|
||||
counterparty : Party
|
||||
-- ^ The trade counterparty. They receive the pay leg in exchange for the receiving leg.
|
||||
routeProviderCid : ContractId RouteProvider.I
|
||||
-- ^ The route provider to discover settlement paths.
|
||||
settlementFactoryCid : ContractId Settlement.F
|
||||
-- ^ The factory contract for the settlement batch.
|
||||
id : Text
|
||||
-- ^ A textual identifier.
|
||||
where
|
||||
signatory proposer
|
||||
observer counterparty
|
||||
|
||||
ensure recQuantity.amount > 0.0 && payQuantity.amount > 0.0
|
||||
|
||||
choice Accept : (ContractId Batch.I, ContractId Instruction.I, ContractId Instruction.I)
|
||||
controller counterparty
|
||||
do
|
||||
let
|
||||
-- Settlement of REC leg
|
||||
recStep = Step with sender = counterparty; receiver = proposer; quantity = recQuantity
|
||||
|
||||
-- Settlement of PAY leg
|
||||
payStep = Step with sender = proposer; receiver = counterparty; quantity = payQuantity
|
||||
|
||||
-- Discover settlement routes for the steps
|
||||
routedSteps <- exercise routeProviderCid RouteProvider.Discover with
|
||||
discoverors = fromList [proposer, counterparty]
|
||||
contextId = None
|
||||
steps = [recStep, payStep]
|
||||
|
||||
-- INSTRUCT_BEGIN
|
||||
(containerCid, [recInstructionCid, payInstructionCid]) <-
|
||||
exercise settlementFactoryCid Settlement.Instruct with
|
||||
instructors = fromList [proposer, counterparty]
|
||||
settlers = singleton proposer
|
||||
id = Id id
|
||||
description = "Settlement for " <> id
|
||||
contextId = None
|
||||
routedSteps
|
||||
settlementTime = None -- i.e., immediate settlement
|
||||
-- INSTRUCT_END
|
||||
|
||||
pure (containerCid, recInstructionCid, payInstructionCid)
|
||||
|
||||
choice Decline : ()
|
||||
-- ^ Decline the request.
|
||||
controller counterparty
|
||||
do pure ()
|
||||
|
||||
choice Withdraw : ()
|
||||
-- ^ Withdraw the request.
|
||||
controller proposer
|
||||
do pure ()
|
6
daml/Workflow/README.md
Normal file
6
daml/Workflow/README.md
Normal file
@ -0,0 +1,6 @@
|
||||
# Workflows
|
||||
|
||||
This folder includes user-defined workflows which encapsulate the core business logic of the
|
||||
application.
|
||||
|
||||
Files in this folder can reference only the interface packages of `daml-finance`.
|
55
daml/Workflow/Transfer.daml
Normal file
55
daml/Workflow/Transfer.daml
Normal file
@ -0,0 +1,55 @@
|
||||
module Workflow.Transfer where
|
||||
|
||||
import DA.Assert ((===))
|
||||
import DA.Set (fromList)
|
||||
import Daml.Finance.Interface.Holding.Base qualified as Holding (I)
|
||||
import Daml.Finance.Interface.Holding.Transferable qualified as Transferable (I, Transfer(..))
|
||||
import Daml.Finance.Interface.Holding.Util (getAmount, getInstrument)
|
||||
import Daml.Finance.Interface.Types.Common.Types (AccountKey(..), InstrumentKey)
|
||||
|
||||
-- | Initiate / Accept template to transfer a holding to a new owner.
|
||||
template Request
|
||||
with
|
||||
receiverAccount : AccountKey
|
||||
-- ^ The account where the holding is sent.
|
||||
instrument : InstrumentKey
|
||||
-- ^ The instrument referenced by the holding to be transferred.
|
||||
amount : Decimal
|
||||
-- ^ Number of units to be transferred.
|
||||
currentOwner : Party
|
||||
-- ^ The owner of the holding to be transferred.
|
||||
where
|
||||
signatory receiverAccount.owner
|
||||
observer currentOwner
|
||||
|
||||
ensure amount > 0.0
|
||||
|
||||
choice Accept : ContractId Holding.I
|
||||
with
|
||||
holdingCid : ContractId Holding.I
|
||||
controller currentOwner
|
||||
do
|
||||
-- Sanity checks
|
||||
holding <- fetch holdingCid
|
||||
getAmount holding === amount
|
||||
getInstrument holding === instrument
|
||||
|
||||
-- DO_TRANSFER_BEGIN
|
||||
let transferableCid = coerceInterfaceContractId @Transferable.I holdingCid
|
||||
|
||||
newTransferableCid <- exercise transferableCid Transferable.Transfer with
|
||||
actors = fromList [currentOwner, receiverAccount.owner]
|
||||
newOwnerAccount = receiverAccount
|
||||
|
||||
pure $ toInterfaceContractId @Holding.I newTransferableCid
|
||||
-- DO_TRANSFER_END
|
||||
|
||||
choice Decline : ()
|
||||
-- ^ Decline the request.
|
||||
controller currentOwner
|
||||
do pure ()
|
||||
|
||||
choice Withdraw : ()
|
||||
-- ^ Withdraw the request.
|
||||
controller receiverAccount.owner
|
||||
do pure ()
|
21
get-dependencies.bat
Normal file
21
get-dependencies.bat
Normal file
@ -0,0 +1,21 @@
|
||||
:: Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
|
||||
:: SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
@echo off
|
||||
|
||||
:: Create .lib directory
|
||||
if exist ".\.lib\" rmdir /s /q .lib
|
||||
mkdir .\.lib
|
||||
|
||||
:: Get the dependency list
|
||||
echo Downloading the list of dependencies
|
||||
for /f "tokens=2" %%a IN ('findstr "^version" daml.yaml') DO (set version=%%a)
|
||||
|
||||
curl -Lf# "https://raw.githubusercontent.com/digital-asset/daml-finance/main/docs/code-samples/getting-started-config/%version%.conf" -o .lib/%version%.conf
|
||||
|
||||
for /F "tokens=*" %%a in (.lib/%version%.conf) do (
|
||||
for /F "tokens=1,2" %%b in ("%%a") do (
|
||||
echo Downloading: %%b to %%c
|
||||
curl -Lf# "%%b" -o %%c
|
||||
)
|
||||
)
|
28
get-dependencies.sh
Executable file
28
get-dependencies.sh
Executable file
@ -0,0 +1,28 @@
|
||||
#!/usr/bin/env bash
|
||||
# Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Create .lib directory
|
||||
if [[ -d .lib ]]; then
|
||||
rm -r .lib
|
||||
fi
|
||||
mkdir .lib
|
||||
|
||||
# Get the dependency list
|
||||
echo "Downloading the list of dependencies"
|
||||
version=$(grep '^version' daml.yaml | cut -d " " -f 2)
|
||||
curl -L# \
|
||||
-H 'Cache-Control: no-cache, no-store' \
|
||||
-o .lib/${version}.conf \
|
||||
https://raw.githubusercontent.com/digital-asset/daml-finance/main/docs/code-samples/getting-started-config/${version}.conf
|
||||
|
||||
# For each dependency, download and install
|
||||
while IFS=" " read -r url out
|
||||
do
|
||||
printf "Downloading: %s, to: %s\n" "$url" "$out"
|
||||
curl -Lf# "${url}" -o ${out}
|
||||
done < .lib/${version}.conf
|
||||
|
||||
echo "All dependencies successfully downloaded!"
|
Loading…
Reference in New Issue
Block a user