@@ -45,41 +45,33 @@ data TwoStepTransfer = TwoStepTransfer with
4545 allowFeaturing : Bool
4646 -- ^ Whether the second step can be featured.
4747
48- -- | The extra amount locked to guard against the transfer fees changing between
49- -- the time of locking the amulet and the time of executing the actual transfer.
50- feeReserveMultiplier : Decimal
51- feeReserveMultiplier = 4.0
52-
5348-- | Converting a set of holding inputs to inputs for an amulet transfer,
5449-- unlocking any expired LockedAmulet holdings on the fly.
55- holdingToTransferInputs : ForOwner -> PaymentTransferContext -> [ContractId Holding] -> Update [TransferInput]
56- holdingToTransferInputs forOwner paymentContext inputHoldingCids =
50+ holdingToTransferInputs : ForOwner -> Either PaymentTransferContext ExternalPartyPaymentTransferContext -> [ContractId Holding] -> Update [TransferInput]
51+ holdingToTransferInputs forOwner paymentContextE inputHoldingCids =
5752 forA inputHoldingCids $ \holdingCid -> do
5853 holding <- fetchCheckedInterface @Holding forOwner holdingCid
5954 case fromInterface holding of
6055 Some (LockedAmulet {}) -> do
6156 let lockedAmuletCid : ContractId LockedAmulet = fromInterfaceContractId holdingCid
6257 -- We assume the lock is expired, and if not then we rely `LockedAmulet_OwnerExpireLock` to fail
63- result <- exercise lockedAmuletCid LockedAmulet_OwnerExpireLock with
64- openRoundCid = paymentContext.context.openMiningRound
65- pure $ InputAmulet result.amuletSum.amulet
58+ case paymentContextE of
59+ Left paymentContext -> do
60+ result <- exercise lockedAmuletCid LockedAmulet_OwnerExpireLock with
61+ openRoundCid = paymentContext.context.openMiningRound
62+ pure $ InputAmulet result.amuletSum.amulet
63+ Right externalPartyPaymentContext -> do
64+ result <- exercise lockedAmuletCid LockedAmulet_ExternalPartyOwnerExpireLock with
65+ externalPartyConfigStateCid = externalPartyPaymentContext.context.externalPartyConfigState
66+ pure $ InputAmulet result.amuletSum.amulet
6667 None -> pure $ InputAmulet $ coerceContractId holdingCid
6768
6869-- | Prepare a two-step transfer of amulet by locking the funds.
6970prepareTwoStepTransfer
70- : TwoStepTransfer -> Time -> [ContractId Holding] -> PaymentTransferContext
71+ : TwoStepTransfer -> Time -> [ContractId Holding] -> Either PaymentTransferContext ExternalPartyPaymentTransferContext
7172 -> Update (ContractId LockedAmulet, [ContractId Holding], Metadata)
7273prepareTwoStepTransfer TwoStepTransfer{..} requestedAt inputHoldingCids paymentContext = do
7374 require "requestedAt < transferBefore" (requestedAt < transferBefore)
74- -- over-approximate fees that will be due on the actual transfer
75- let receiverOutputForActualTransfer = TransferOutput with
76- receiver
77- amount
78- receiverFeeRatio = 0.0 -- all fees are paid by the sender
79- lock = None
80- [expectedTransferFees] <- exerciseComputeFees dso paymentContext sender [receiverOutputForActualTransfer]
81- let feesReserveAmount = expectedTransferFees * feeReserveMultiplier
82-
8375 -- lock the amulet
8476 transferInputs <- holdingToTransferInputs (ForOwner with dso; owner = sender) paymentContext inputHoldingCids
8577 let transfer = Splice.AmuletRules.Transfer with
@@ -88,8 +80,8 @@ prepareTwoStepTransfer TwoStepTransfer{..} requestedAt inputHoldingCids paymentC
8880 outputs =
8981 [ TransferOutput with
9082 receiver = sender
91- amount = amount + feesReserveAmount
92- receiverFeeRatio = 0.0 -- locking fees are paid by the sender
83+ amount = amount
84+ receiverFeeRatio = 0.0 -- irrelevant as fees are always zero
9385 lock = Some TimeLock with
9486 expiresAt = transferBefore
9587 holders = [dso]
@@ -98,7 +90,7 @@ prepareTwoStepTransfer TwoStepTransfer{..} requestedAt inputHoldingCids paymentC
9890 inputs = transferInputs
9991 beneficiaries = None
10092
101- result <- exercisePaymentTransfer dso paymentContext transfer
93+ result <- exerciseExternalPartyPaymentTransferWithFallback dso paymentContext transfer
10294 let [TransferResultLockedAmulet lockedAmulet] = result.createdAmulets
10395 pure
10496 ( lockedAmulet
@@ -121,9 +113,8 @@ executeTwoStepTransfer TwoStepTransfer{..} lockedAmuletCid extraArgs = do
121113 -- ignore beneficiaries in case we are not allowing featuring
122114 context <- unfeaturedPaymentContextFromChoiceContext dso extraArgs.context
123115 pure (context, None)
124- let openRoundCid = paymentContext.context.openMiningRound
125116 -- unlock amulet
126- unlockResult <- exercise lockedAmuletCid LockedAmulet_Unlock with openRoundCid
117+ unlockResult <- unlockAmulet paymentContext lockedAmuletCid
127118 let amuletCid = unlockResult.amuletSum.amulet
128119 -- execute transfer
129120 let receiverOutput = TransferOutput with
@@ -137,7 +128,7 @@ executeTwoStepTransfer TwoStepTransfer{..} lockedAmuletCid extraArgs = do
137128 inputs = [InputAmulet amuletCid]
138129 outputs = [receiverOutput]
139130 beneficiaries
140- result <- exercisePaymentTransfer dso paymentContext amuletRulesTransfer
131+ result <- exerciseExternalPartyPaymentTransferWithFallback dso paymentContext amuletRulesTransfer
141132 pure
142133 ( optionalToList (toInterfaceContractId <$> result.senderChangeAmulet)
143134 , createdAmuletToHolding <$> result.createdAmulets
@@ -149,6 +140,7 @@ abortTwoStepTransfer TwoStepTransfer{..} lockedAmuletCid extraArgs = do
149140 expireLockedAmulet <- getFromContextU @Bool extraArgs.context expireLockKey
150141 if expireLockedAmulet
151142 then do
143+ -- FIXME: switch this to ExternalPartyConfigState
152144 openRoundCid <- getFromContextU @(ContractId OpenMiningRound) extraArgs.context openRoundContextKey
153145 -- prudent engineering: check the DSO party
154146 _ <- fetchChecked (ForDso with dso) openRoundCid
@@ -159,3 +151,10 @@ abortTwoStepTransfer TwoStepTransfer{..} lockedAmuletCid extraArgs = do
159151 assertDeadlineExceeded transferBeforeDeadline transferBefore
160152 pure []
161153
154+ unlockAmulet : Either PaymentTransferContext ExternalPartyPaymentTransferContext -> ContractId LockedAmulet -> Update LockedAmulet_UnlockResult
155+ unlockAmulet transferContextE lockedAmuletCid = do
156+ case transferContextE of
157+ Left paymentContext -> do
158+ exercise lockedAmuletCid LockedAmulet_Unlock with openRoundCid = paymentContext.context.openMiningRound
159+ Right externalPartyPaymentContext -> do
160+ exercise lockedAmuletCid LockedAmulet_ExternalPartyUnlock with externalPartyConfigStateCid = externalPartyPaymentContext.context.externalPartyConfigState
0 commit comments