import { interpret } from 'xstate' ; import { firstState , calculateChannelId , createSignatureEntry , ChannelConstants , Outcome , State , SignedState , BN } from '@statechannels/wallet-core' ; import { Store } from '../../store' ; import { FakeChain } from '../../chain' ; import { TestStore } from '../../test-store' ; import { machine as concludeChannel } from '../conclude-channel' ; import { Init , machine as createChannel } from '../create-and-fund' ; import { zeroAddress } from '../../config' ; import { subscribeToMessages } from './message-service' ; import { wallet1 , wallet2 , participants , TEST_APP_DOMAIN } from './data' ; jest . setTimeout ( 5000 ) ; const chainId = '0x01' ; const challengeDuration = 10 ; const appDefinition = zeroAddress ; const targetChannel = { channelNonce : 0 , chainId , challengeDuration , participants , appDefinition } ; const targetChannelId = calculateChannelId ( targetChannel ) ; const destinations = participants . map ( p => p . destination ) ; const amounts = [ BN . from ( 7 ) , BN . from ( 5 ) ] ; const allocation = { type : 'SimpleAllocation' , asset : zeroAddress , allocationItems : [ 0 , 1 ] . map ( i => ( { destination : destinations [ i ] , amount : amounts [ i ] } ) ) } ; const context = { channelId : targetChannelId , funding : 'Direct' } ; const allSignedState = ( state ) => ( { ... state , signatures : [ wallet1 , wallet2 ] . map ( ( { privateKey } ) => createSignatureEntry ( state , privateKey ) ) } ) ; const ASignedStateOnly = ( state ) => ( { ... state , signatures : [ createSignatureEntry ( state , wallet1 . privateKey ) ] } ) ; const BSignedStateOnly = ( state ) => ( { ... state , signatures : [ createSignatureEntry ( state , wallet2 . privateKey ) ] } ) ; const noSignedState = ( state ) => ( { ... state , signatures : [ ] } ) ; const runUntilSuccess = async ( machine , stores ) => { const runMachine = ( store ) => interpret ( machine ( store ) . withContext ( context ) ) . start ( ) ; const services = stores . map ( runMachine ) ; await Promise . all ( services . map ( service => new Promise < void > ( resolve => service . onTransition ( state => state . matches ( 'success' ) && service . stop ( ) && resolve ( ) ) ) ) ) ; } ; const concludeAndAssert = async ( stores ) => { const [ aStore , bStore ] = stores ; await runUntilSuccess ( concludeChannel , stores ) ; const entryA1 = await aStore . getEntry ( targetChannelId ) ; const entryB1 = await bStore . getEntry ( targetChannelId ) ; expect ( entryA1 . hasConclusionProof ) . toBe ( true ) ; expect ( entryB1 . hasConclusionProof ) . toBe ( true ) ; } ; const setupStores = async ( entryState ) => { const chain = new FakeChain ( ) ; const aStore = new TestStore ( chain ) ; await aStore . initialize ( [ wallet1 . privateKey ] ) ; const bStore = new TestStore ( chain ) ; await bStore . initialize ( [ wallet2 . privateKey ] ) ; await aStore . createEntry ( entryState , { applicationDomain : TEST_APP_DOMAIN } ) ; await bStore . createEntry ( entryState , { applicationDomain : TEST_APP_DOMAIN } ) ; subscribeToMessages ( { [ participants [ 0 ] . participantId ] : aStore , [ participants [ 1 ] . participantId ] : bStore } ) ; return [ aStore , bStore ] ; } ; const finalState = ( outcome , targetChannel ) => ( { ... firstState ( outcome , targetChannel ) , isFinal : true } ) ; describe ( 'supportState machine is idempotent' , ( ) => { it . skip ( 'concludes correctly when starting with all signed states' , async ( ) => { const entryState = allSignedState ( finalState ( allocation , targetChannel ) ) ; const stores = await setupStores ( entryState ) ; await runUntilSuccess ( createChannel , stores ) ; await concludeAndAssert ( stores ) ; } ) ; it . skip ( 'concludes correctly when starting with A signed state only' , async ( ) => { const entryState = ASignedStateOnly ( finalState ( allocation , targetChannel ) ) ; const stores = await setupStores ( entryState ) ; await runUntilSuccess ( createChannel , stores ) ; await concludeAndAssert ( stores ) ; } ) ; it . skip ( 'concludes correctly when starting with B signed state only' , async ( ) => { const entryState = BSignedStateOnly ( finalState ( allocation , targetChannel ) ) ; const stores = await setupStores ( entryState ) ; await runUntilSuccess ( createChannel , stores ) ; await concludeAndAssert ( stores ) ; } ) ; it . skip ( 'concludes correctly when starting with no signed state' , async ( ) => { const entryState = noSignedState ( finalState ( allocation , targetChannel ) ) ; const stores = await setupStores ( entryState ) ; await runUntilSuccess ( createChannel , stores ) ; await concludeAndAssert ( stores ) ; } ) ; } ) ;