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
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.
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
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 ()
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).