import { AnyEventObject , AssignAction , MachineConfig , assign , spawn , Machine , ActorRef } from 'xstate' ; import { filter , map } from 'rxjs/operators' ; import { statesEqual , calculateChannelId , State } from '@statechannels/wallet-core' ; import { Store } from '../store' ; const WORKFLOW = 'support-state' ; export type Init = { state : State ; observer ? : ActorRef < any , any > ; } ; type HasChannelId = Init & { channelId : string ; } ; export const config = { key : WORKFLOW , initial : 'signState' , states : { signState : { entry : [ assign < HasChannelId > ( { channelId : ( { state } ) => calculateChannelId ( state ) } ) , 'spawnObserver' ] , invoke : { src : 'signState' } , on : { SUPPORTED : 'success' } } , success : { type : 'final' } } } ; type Services = { signState ( ctx , event ) : any ; } ; type Options = { services : Services ; actions : { spawnObserver : AssignAction < HasChannelId , any > ; } ; } ; const signState = ( store ) => async ( { state } ) => store . supportState ( state ) ; const notifyWhenSupported = ( store , { state , channelId } ) => store . channelUpdatedFeed ( channelId ) . pipe ( filter ( ( { isSupported } ) => isSupported ) , filter ( entry => statesEqual ( state , entry . supported ) ) , map ( ( ) => 'SUPPORTED' ) ) ; const options = ( store ) : Options => ( { services : { signState : signState ( store ) } , actions : { spawnObserver : assign < HasChannelId > ( ( ctx ) => ( { ... ctx , observer : ! ctx . observer ? spawn ( notifyWhenSupported ( store , ctx ) ) : ctx . observer } ) ) } } ) ; export const machine = ( store ) => Machine ( config , options ( store ) ) ;