Creating Digital Currency using Daml Finance

Hi there,

I was trying to following the Daml Finance Tutorial but I got a few issues. What I was trying to do is

  1. Set up Fungible Factory for Bank
  2. Set up Equity Instrument for Bank (Digital Dollar)
  3. Set up Account Factory for Bank
  4. Created Account for Bank
  5. Deposit (mint) 1000 (Digital Dollar) to Bank

Step 1 to 4 are all good but when I was doing item 5. I got the following response from Navigator. I checked and Account:Reference contract is there.

Did I miss anything?

23:37:02.074 [da-ui-backend-akka.actor.default-dispatcher-10] INFO  c.d.n.s.platform.PlatformSubscriber - Command '84cf3c2f1f09a99a' completed with status 'CommandStatusError(NOT_FOUND,CONTRACT_KEY_NOT_FOUND(11,8702ec93): dependency error: couldn't find key: GloalKey(61b5590cf0b4e5ea01cb08ef577e43d6cfcd816be060ac7a540a100c3f00b11b2:Daml.Finance.Interface.Account.Account:Reference, ValueRecord(None,ImmArray((None,ValueParty(Bank::122013276fc51248214c9bfbafd83c183a6e24b965f879ccb603b93168147abe1c93)),(None,ValueParty(Bank::122013276fc51248214c9bfbafd83c183a6e24b965f879ccb603b93168147abe1c93)),(None,ValueRecord(None,ImmArray((None,ValueText(Minting 5000)))))))))'. akkaAddress=akka://da-ui-backend, sourceThread=da-ui-backend-akka.actor.default-dispatcher-9, akkaTimestamp=13:37:02.074UTC, akkaSource=akka://da-ui-backend/user/$a/party-Bank%3A%3A122013276fc51248214c9bfbafd83c183a6e24b965f879ccb603b93168147abe1c93, sourceActorSystem=da-ui-backend

I found the issue, I didn’t use the correct ID for the account. I fixed the ID. And now I got this…

Looks like the equity Instrument does not support credit account…

15:11:38.590 [da-ui-backend-akka.actor.default-dispatcher-9] INFO  c.d.n.s.platform.PlatformSubscriber - Command '8cf59402dde2034a' completed with status 'CommandStatusError(INVALID_ARGUMENT,DAML_INTERPRETER_INVALID_ARGUMENT(8,4a23d33c): Interpretation error: Error: Update failed due to contract 0016f8f33cefecfb8ac68f1c6c10f7534836feabf01037aab8b95ff4f333a7f9deca0112202cee277a564ac8181b9868a7cdd97e450c032862357464ef4cb23249a207e6ba not implementing an interface
Expected contract to implement interface Daml.Finance.Interface.Holding.Factory:Factory@95644d5c but contract has type Daml.Finance.Instrument.Equity.Instrument:Instrument@39e3bfb6)'. akkaAddress=akka://da-ui-backend, sourceThread=da-ui-backend-akka.actor.default-dispatcher-9, akkaTimestamp=05:11:38.589UTC, akkaSource=akka://da-ui-backend/user/$a/party-Bank%3A%3A122013276fc51248214c9bfbafd83c183a6e24b965f879ccb603b93168147abe1c93, sourceActorSystem=da-ui-backend

I got it working now. Can someone review and make sure I did it right?

  1. Create Fungible Factory for Bank
  2. Create Token.Factory for Bank (Digital Dollar)
  3. Exercise create choice in Token.Factory to create Token.Instrument and Instrument:Reference
  4. Create Account.Factory for Bank
  5. CreatedAccount.Request for Bank
  6. Bank accepts the request
  7. Bank create a HoldingRequest
  8. Bank approve the HoldingRequest

Once Bank approve the HoldingRequest, Bank will receive Holding.Fungible

One thing I found is that Bank can create Instruments with the same ID and version. How does a user tell which DC he/she is holding?

1 Like

Hi @Frankie,

that flow is LGTM.

Fyi, we’ve implemented a workaround for keying Instrument.I (and Account.I) interfaces, given that keys are currently not supported in interfaces. Here’s how it works:

Each instance of an Instrument.I implementation is always created concurrently with a Reference template instance that has a key. This creations occur as a single atomic action. The Reference instance includes a ContractId Instrument.I field, essentially serving as a pointer to the corresponding Instrument.I instance. We also have our own, e.g., exerciseInterfaceByKey, utility functions in place that work using the Reference template instances.

For this to function properly, it’s assumed that the issuer and depository of the Instrument.I will not create Instrument instances without corresponding Reference instances, and it’s crucial that any updates to the Instrument.I instance are mirrored in the Reference to maintain consistency.

You are right that it is indeed possible to create multiple Instrument instances with the same ID and version. However, this is only feasible if you do not create the Reference instance concurrently.

For more details on this workaround, please refer to the the following forum discussion 5374.

I hope that helps,

Johan

Thanks @Johan_Sjodin, thanks for explaining the usage of reference contract. I tried to use instrument factory to create an instrument however I cannot convert it to Daml.Finance.Interface.Instrument.Token.Factory since Daml-Finance-Interface-Instrument-Token is a hidden package. Do I need to manually create the instrument reference in this case?

  tokenFactoryCid <- submit bank do
    createCmd Token.Factory with
      provider = bank
      observers = empty

  instrumentCid <- toInterfaceContractId @CANNOT COVERT  <$> submit bank do  
    exerciseCmd tokenFactoryCid Create

Hi @Frankie,

To exercise the Create choice on your token factory template instance, it must first be cast to the factory interface using toInterfaceContractId. This Create choice returns the base instrument interface instance, which can then be cast to the token instrument interface/template instance using fromInterfaceContractId (as the token instrument interface requires the base instrument interface).

I hope this code makes it clearer:

module Test where

import DA.Map (empty)
import Daml.Finance.Instrument.Token.Factory qualified as Token (Factory(..))
import Daml.Finance.Instrument.Token.Instrument qualified as Token (T)
import Daml.Finance.Interface.Instrument.Base.Instrument qualified as Base (I)
import Daml.Finance.Interface.Instrument.Token.Factory qualified as Token (F, Create(..))
import Daml.Finance.Interface.Instrument.Token.Instrument qualified as Token (I)
import Daml.Finance.Interface.Instrument.Token.Types (Token(..))
import Daml.Finance.Interface.Types.Common.Types (Id(..), InstrumentKey(..))
import Daml.Script

test : Script ()
test = script do
  [bank, depository, issuer] <- mapA allocateParty ["bank", "depository", "issuer"]

  -- use toInterfaceContractId to cast to the token factory interface instance
  tokenFactoryCid <- toInterfaceContractId @Token.F <$> submit bank do
    createCmd Token.Factory with
      provider = bank
      observers = empty

  now <- getTime
  
  -- returns the base intstrument interface instance
  baseInstrumentCid : ContractId Base.I <- submitMulti [depository, issuer] [bank] do
    exerciseCmd tokenFactoryCid Token.Create with
      token = Token with
        instrument = InstrumentKey with depository; issuer; id = Id "test"; version = "test"
        description = "test"
        validAsOf = now
      observers = empty

  -- use fromInterfaceContractId to cast to the token instrument interface/template instance
  let 
    tokenInstrumentCid = fromInterfaceContractId @Token.I baseInstrumentCid    
    instrumentCid = fromInterfaceContractId @Token.T baseInstrumentCid    

  pure ()

I hope that helps,

Johan

1 Like

Thanks @Johan_Sjodin, It worked. The interface Daml.Finance.Interface.Instrument.Token.Factory is a hidden member in the package. Is there a reason for it.

There is nothing special about Daml.Finance.Interface.Instrument.Token.Factory, you would need to add the daml-finance-interface-instrument-token package as a dependency in your .yaml file (for the error to go away).

1 Like