@@ -56,6 +56,8 @@ module Plutus.PAB.Core
5656 , instanceState
5757 , observableState
5858 , waitForState
59+ , waitForInstanceState
60+ , waitForInstanceStateWithResult
5961 , waitForTxStatusChange
6062 , waitForTxOutStatusChange
6163 , activeEndpoints
@@ -83,7 +85,7 @@ module Plutus.PAB.Core
8385 , timed
8486 ) where
8587
86- import Control.Applicative (Alternative ((<|>) ))
88+ import Control.Applicative (Alternative ((<|>) ), empty )
8789import Control.Concurrent.STM (STM )
8890import Control.Concurrent.STM qualified as STM
8991import Control.Lens (view )
@@ -112,7 +114,8 @@ import Plutus.Contract.Effects (ActiveEndpoint (ActiveEndpoint, aeDescription),
112114import Plutus.Contract.Wallet (ExportTx )
113115import Plutus.PAB.Core.ContractInstance (ContractInstanceMsg , ContractInstanceState )
114116import Plutus.PAB.Core.ContractInstance qualified as ContractInstance
115- import Plutus.PAB.Core.ContractInstance.STM (Activity (Active ), BlockchainEnv , InstancesState , OpenEndpoint )
117+ import Plutus.PAB.Core.ContractInstance.STM (Activity (Active , Done , Stopped ), BlockchainEnv , InstancesState ,
118+ OpenEndpoint )
116119import Plutus.PAB.Core.ContractInstance.STM qualified as Instances
117120import Plutus.PAB.Effects.Contract (ContractDefinition , ContractEffect , ContractStore , PABContract (ContractDef ),
118121 getState )
@@ -133,6 +136,7 @@ import Wallet.Emulator.MultiAgent (EmulatorEvent' (WalletEvent), EmulatorTimeEve
133136import Wallet.Emulator.Wallet (Wallet , WalletEvent (GenericLog , RequestHandlerLog , TxBalanceLog ), mockWalletAddress )
134137import Wallet.Types (ContractActivityStatus , ContractInstanceId , EndpointDescription (EndpointDescription ),
135138 NotificationError )
139+ import Wallet.Types qualified as Wallet
136140
137141-- | Effects that are available in 'PABAction's.
138142type PABEffects t env =
@@ -506,6 +510,42 @@ waitForState extract instanceId = do
506510 state <- stm
507511 maybe STM. retry pure (extract state)
508512
513+
514+ -- | Wait until the instance state of the instance satisfies a predicate and returns the activity status
515+ waitForInstanceState ::
516+ forall t env .
517+ (Instances. InstanceState -> STM (Maybe ContractActivityStatus )) ->
518+ ContractInstanceId ->
519+ PABAction t env ContractActivityStatus
520+ waitForInstanceState extract instanceId = do
521+ is <- instanceStateInternal instanceId
522+ liftIO $ STM. atomically $ do
523+ ms <- extract is
524+ maybe empty pure ms
525+
526+ -- | Wait until the instance state is updated with a response form an invoked endpoint.
527+ -- Note that the waiting is performed only when a contract is expected to end with a Done status, i.e.,
528+ -- no open endpoints available after invocation.
529+ waitForInstanceStateWithResult :: forall t env . ContractInstanceId -> PABAction t env ContractActivityStatus
530+ waitForInstanceStateWithResult instanceId = do
531+ -- retry query when waiting for a response from an invoked endpoint s.t.
532+ -- contract is supposed to end with status Done
533+ let parseStatus :: Activity -> ContractActivityStatus
534+ parseStatus = \ case
535+ Active -> Wallet. Active
536+ Stopped -> Wallet. Stopped
537+ Done _ -> Wallet. Done
538+ let r_check :: Instances. InstanceState -> STM (Maybe ContractActivityStatus )
539+ r_check Instances. InstanceState {Instances. issEndpoints, Instances. issStatus, Instances. issObservableState} = do
540+ status <- STM. readTVar issStatus
541+ ostate <- STM. readTVar issObservableState
542+ currentEndpoints <- STM. readTVar issEndpoints
543+ case (status, ostate) of
544+ (Active , Just JSON. Null ) | Map. null currentEndpoints ->
545+ pure Nothing
546+ _ -> pure $ Just $ parseStatus status
547+ waitForInstanceState r_check instanceId
548+
509549-- | Wait for the transaction to be confirmed on the blockchain.
510550waitForTxStatusChange :: forall t env . TxId -> PABAction t env TxStatus
511551waitForTxStatusChange t = do
0 commit comments