Hi,
I’m trying to create an Observation
where the submitter is a party distinct from the issuer. I’ve taken the test on Daml.Finance.Instrument.Bond.Test.FloatingRate
where the issuer
submits the Observation
. In the test bellow I create a dataProvider
party which submits the Observation
, and additionally I set the publicParty
as an observer in the Observation
.
I get this error:
Script execution failed on commit at Daml.Finance.Test.Util.Lifecycle:39:33:
7: fetch of Daml.Finance.Data.Numeric.Observation:Observation at Daml.Finance.Data.Numeric.Observation:35:14
failed since none of the stakeholders ‘DataProvider’, ‘PublicParty’
is in the authorizing set ‘Issuer’
-- Copyright (c) 2023 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
-- SPDX-License-Identifier: Apache-2.0
module Daml.Finance.Instrument.Bond.Test.FloatingRate where
import DA.Date (DayOfWeek(..), Month(..), addDays, date, subtractDays)
import DA.Map qualified as M (empty, fromList)
import DA.Set qualified as S (singleton)
import Daml.Finance.Data.Numeric.Observation (Observation(..))
import Daml.Finance.Data.Reference.HolidayCalendar (HolidayCalendar(..))
import Daml.Finance.Instrument.Bond.Test.Util (originateFloatingRateBond)
import Daml.Finance.Interface.Types.Common.Types (Id(..))
import Daml.Finance.Interface.Types.Date.Calendar (BusinessDayConventionEnum(..), HolidayCalendarData(..))
import Daml.Finance.Interface.Types.Date.DayCount (DayCountConventionEnum(..))
import Daml.Finance.Interface.Types.Date.RollConvention (PeriodEnum(..))
import Daml.Finance.Interface.Util.Common (qty)
import Daml.Finance.Test.Util.Common (createParties)
import Daml.Finance.Test.Util.Instrument (originate)
import Daml.Finance.Test.Util.Lifecycle (lifecycleAndVerifyPaymentEffects, verifyNoLifecycleEffects)
import Daml.Finance.Test.Util.Time (dateToDateClockTime)
import Daml.Script
-- Penultimate coupon payment on a bond showing creation of new instrument version
run : Script ()
run = script do
[depository, custodian, issuer, calendarDataProvider, settler, publicParty, dataProvider] <-
createParties ["CSD", "Custodian", "Issuer", "Calendar Data Provider", "Settler", "PublicParty", "DataProvider"]
let settlers = S.singleton settler
-- Distribute commercial-bank cash
now <- getTime
let pp = [("PublicParty", S.singleton publicParty)]
cashInstrument <- originate depository issuer "EUR" "Euro" pp now
-- Create and distribute bond
-- Floating rate bond: Euribor 3M + 1.1% p.a. coupon every 3M
-- CREATE_FLOATING_RATE_BOND_VARIABLES_BEGIN
let
issueDate = date 2019 Jan 16
firstCouponDate = date 2019 Feb 15
maturityDate = date 2019 May 15
referenceRateId = "EUR/EURIBOR/3M"
notional = 1.0
couponSpread = 0.011
couponPeriod = M
couponPeriodMultiplier = 3
dayCountConvention = Act365Fixed
businessDayConvention = Following
-- CREATE_FLOATING_RATE_BOND_VARIABLES_END
observations = M.fromList
[ (dateToDateClockTime $ date 2019 Jan 16, -0.00311)
, (dateToDateClockTime $ date 2019 Feb 15, -0.00266)
]
cal = HolidayCalendarData with
id = "EUR"
weekend = [Saturday, Sunday]
holidays = [date 2019 Dec 19]
holidayCalendarIds = [cal.id]
-- A reference data provider publishes the holiday calendar on the ledger
calendarCid <- submit calendarDataProvider do
createCmd HolidayCalendar with
provider = calendarDataProvider
calendar = cal
observers = M.fromList pp
observableCid <- toInterfaceContractId <$> submit dataProvider do
createCmd Observation with
provider = dataProvider; id = Id referenceRateId; observations; observers = M.fromList pp
bondInstrument <- originateFloatingRateBond issuer issuer "BONDTEST1" "Floating Rate Bond" pp
now issueDate holidayCalendarIds calendarDataProvider firstCouponDate maturityDate
dayCountConvention businessDayConvention couponSpread couponPeriod couponPeriodMultiplier
cashInstrument notional referenceRateId
-- One day before the first coupon date: try to lifecycle and verify that there are no lifecycle
-- effects.
verifyNoLifecycleEffects [publicParty] (subtractDays firstCouponDate 1) bondInstrument issuer
[observableCid]
pure ()
I guess the issue comes from here. (I’ve played a little with the code and by using GetView
from NumericObservable.I
I was able to make it work)
collectObservables : [ContractId NumericObservable.I] -> Update
(Observable -> Time -> Update Decimal)
collectObservables observableCids = do
os <- M.fromList <$> forA observableCids \cid -> do
observation <- fetch cid -- <-------------------------------- !!!
pure (show (view observation).id, observation)
pure \key t -> case M.lookup key os of
Some o -> NumericObservable.observe o t
None -> do abort $ "Missing observable" <> show key <> " at time " <> show t
The only way I could make it work (without changing the codebase) was by adding issuer
as an observer in the Observation
.
observableCid <- toInterfaceContractId <$> submit dataProvider do
createCmd Observation with
provider = dataProvider
id = Id referenceRateId
observations
observers = M.fromList [("PublicParty", S.singleton publicParty), ("Issuer", S.singleton issuer)]
Is that the way to go?
Thanks!
Jose