import { Zero } from "ethers/constants" ; import { bigNumberify } from "ethers/utils" ; import { Node } from "../../src" ; import { toBeEq } from "../engine/integration/bignumber-jest-matcher" ; import { installAndRedeemLink , installLink , makeSimpleTransfer } from "./connext-utils" ; import { initialLinkedState } from "./linked-transfer" ; import { setup , SetupContext } from "./setup" ; import { collateralizeChannel , createChannel } from "./utils" ; jest . setTimeout ( 10000 ) ; expect . extend ( { toBeEq } ) ; function generateInitialLinkedTransferStates ( sender , intermediary , redeemer , numberApps = 3 ) { const linkStatesSender = [ ] ; const linkStatesRedeemer = [ ] ; for ( let i = 0 ; i < numberApps ; i += 1 ) { const { action , state } = initialLinkedState ( intermediary . freeBalanceAddress , redeemer . freeBalanceAddress ) ; linkStatesRedeemer . push ( { action , state } ) ; const hubTransfers = [ { to : sender . freeBalanceAddress , amount : action . amount } , { to : intermediary . freeBalanceAddress , amount : Zero } ] ; linkStatesSender . push ( { action , state : { ... state , transfers : hubTransfers } } ) ; } return { linkStatesRedeemer , linkStatesSender } ; } async function installLinks ( funder , redeemer , statesAndActions ) { const appIds = [ ] ; for ( const { state , action } of statesAndActions ) { appIds . push ( await installLink ( funder , redeemer , state , action ) ) ; } return appIds ; } function redeemLinkPoller ( funder , intermediary , redeemer , statesAndActions , done ) { setTimeout ( async ( ) => { while ( statesAndActions . length > 0 ) { await installAndRedeemLink ( funder , intermediary , redeemer , statesAndActions . pop ( ) ) ; } done ( ) ; } , 200 ) ; } /**
 * The connext team has seen some strange issues in production that
 * only appear when multiple bots are running. This test suite will
 * attempt to recreate them in the simplest context.
 */ describe ( "Can update and install multiple apps simultaneously" , ( ) => { let nodeA ; let nodeB ; let nodeC ; let multisigAddressAB ; let multisigAddressBC ; beforeEach ( async ( ) => { const context = await setup ( global , true ) ; nodeA = context [ "A" ] . node ; nodeB = context [ "B" ] . node ; nodeC = context [ "C" ] . node ; multisigAddressAB = await createChannel ( nodeA , nodeB ) ; multisigAddressBC = await createChannel ( nodeB , nodeC ) ; await collateralizeChannel ( multisigAddressAB , nodeA , undefined , bigNumberify ( 15 ) ) ; await collateralizeChannel ( multisigAddressBC , nodeB , undefined , bigNumberify ( 15 ) ) ; } ) ; /**
     * In production, this flow has resulted in several varying bugs including:
     * - IO send and wait timed out
     * - Validating a signature with expected signer 0xFFF but recovered 0xAAA
     * - cannot find agreement with target hash 0xCCC
     * - hanging on client or node
     */ it ( "should be able to redeem a pregenerated linked payment while simultaneously receiving a direct transfer" , async ( done ) => { const { linkStatesRedeemer , linkStatesSender } = generateInitialLinkedTransferStates ( nodeA , nodeB , nodeC , 2 ) ; await installLinks ( nodeA , nodeB , linkStatesSender ) ; redeemLinkPoller ( nodeA , nodeB , nodeC , linkStatesRedeemer , done ) ; for ( const i of Array ( 2 ) ) { await makeSimpleTransfer ( nodeA , nodeB , nodeC ) ; } } ) ; } ) ;