@@ -31,6 +31,7 @@ import Control.Monad.Trans.Class (lift)
3131import Control.Monad.Trans.Either (eitherT , firstEitherT , newEitherT )
3232import Data.Aeson (ToJSON , Value )
3333import Data.Aeson.Extras (encodeByteString )
34+ import Data.Either (fromRight )
3435import Data.Kind (Type )
3536import Data.Map qualified as Map
3637import Data.Row (Row )
@@ -44,7 +45,8 @@ import Ledger.Slot (Slot (Slot))
4445import Ledger.TimeSlot (posixTimeRangeToContainedSlotRange , posixTimeToEnclosingSlot , slotToEndPOSIXTime )
4546import Ledger.Tx (CardanoTx )
4647import Ledger.Tx qualified as Tx
47- import Plutus.ChainIndex.Types (RollbackState (Committed ), TxStatus , TxValidity (.. ))
48+ import Plutus.ChainIndex.TxIdState (fromTx , transactionStatus )
49+ import Plutus.ChainIndex.Types (RollbackState (.. ), TxIdState , TxStatus )
4850import Plutus.Contract.Checkpoint (Checkpoint (.. ))
4951import Plutus.Contract.Effects (
5052 BalanceTxResponse (.. ),
@@ -152,7 +154,7 @@ handlePABReq contractEnv req = do
152154 PosixTimeRangeToContainedSlotRangeResp $
153155 Right $
154156 posixTimeRangeToContainedSlotRange contractEnv. cePABConfig. pcSlotConfig posixTimeRange
155- AwaitTxStatusChangeReq txId -> AwaitTxStatusChangeResp txId <$> getTxUpdate @ w contractEnv txId
157+ AwaitTxStatusChangeReq txId -> AwaitTxStatusChangeResp txId <$> awaitTxStatusChange @ w contractEnv txId
156158 ------------------------
157159 -- Unhandled requests --
158160 ------------------------
@@ -167,32 +169,51 @@ handlePABReq contractEnv req = do
167169 printLog @ w Debug $ show resp
168170 pure resp
169171
170- getTxUpdate ::
172+ awaitTxStatusChange ::
171173 forall (w :: Type ) (effs :: [Type -> Type ]).
172174 Member (PABEffect w ) effs =>
173175 ContractEnvironment w ->
174176 Ledger. TxId ->
175177 Eff effs TxStatus
176- getTxUpdate contractEnv txId = do
177- let minBlockHeight = 3
178- _ <- findTxByIdOrLoop
179- printLog @ w Debug $ " Found tx in chain index. Waiting for " ++ show minBlockHeight ++ " blocks"
180- _ <- awaitNBlocks @ w contractEnv minBlockHeight
181- printLog @ w Debug " Waited, checking once more for tx rollback"
182- _ <- findTxByIdOrLoop
183- printLog @ w Debug " Tx is confirmed"
184- pure $ Committed TxValid ()
178+ awaitTxStatusChange contractEnv txId = do
179+ -- The depth (in blocks) after which a transaction cannot be rolled back anymore (from Plutus.ChainIndex.TxIdState)
180+ let chainConstant = 8
181+
182+ ciTxState <- findChainIndexTxLoop
183+ case ciTxState of
184+ Nothing -> pure Unknown
185+ Just txState -> do
186+ awaitNBlocks @ w contractEnv chainConstant
187+ -- Check if the tx is still present in chain-index, in case of a rollback
188+ -- we might not find it anymore.
189+ ciTxState' <- findChainIndexTxLoop
190+ case ciTxState' of
191+ Nothing -> pure Unknown
192+ Just _ -> do
193+ blk <- fromInteger <$> currentBlock contractEnv
194+ -- This will set the validity correctly based on the txState.
195+ -- The tx will always be committed, as we wait for chainConstant blocks
196+ let status = transactionStatus blk txState txId
197+ pure $ fromRight Unknown status
185198 where
186- findTxByIdOrLoop :: Eff effs ()
187- findTxByIdOrLoop = do
188- mTx <- join . preview _TxIdResponse <$> (queryChainIndex @ w $ TxFromTxId txId)
189- case mTx of
190- Just _ -> pure ()
191- Nothing -> do
192- printLog @ w Debug " Tx not found... looping"
193- -- Wait for 1 block and try again
194- _ <- awaitNBlocks @ w contractEnv 1
195- void $ getTxUpdate @ w contractEnv txId
199+ -- Attempts to find the tx in chain index. If the tx does not appear after
200+ -- 5 blocks we give up
201+ findChainIndexTxLoop :: Eff effs (Maybe TxIdState )
202+ findChainIndexTxLoop = go 0
203+ where
204+ go :: Int -> Eff effs (Maybe TxIdState )
205+ go n = do
206+ mTx <- join . preview _TxIdResponse <$> (queryChainIndex @ w $ TxFromTxId txId)
207+ case mTx of
208+ Just tx -> do
209+ blk <- fromInteger <$> currentBlock contractEnv
210+ pure . Just $ fromTx blk tx
211+ Nothing -> do
212+ if n >= 5
213+ then pure Nothing
214+ else do
215+ _ <- awaitNBlocks @ w contractEnv 1
216+ go (n + 1 )
196217
197218-- | This will FULLY balance a transaction
198219balanceTx ::
@@ -294,7 +315,7 @@ awaitNBlocks contractEnv n = do
294315 tip <- CardanoCLI. queryTip @ w contractEnv. cePABConfig
295316 case tip of
296317 Right tip'
297- | start + n > = tip'. block -> pure ()
318+ | start + n < = tip'. block -> pure ()
298319 _ -> go start
299320
300321{- | Wait at least until the given time. Uses the awaitSlot under the hood, so the same constraints
0 commit comments