import { DBAdmin , defaultTestWalletConfig , Wallet as ServerWallet } from '@statechannels/server-wallet' ; import { TEST_ACCOUNTS } from '@statechannels/devtools' ; import { ChannelWallet } from '@statechannels/browser-wallet' ; import { constants , Contract , providers , Wallet } from 'ethers' ; import { Address , BN , Destination , formatAmount , makeAddress , makeDestination , Uint256 } from '@statechannels/wallet-core' ; import { ContractArtifacts } from '@statechannels/nitro-protocol' ; import _ from 'lodash' ; import { CreateChannelParams } from '@statechannels/client-api-schema' ; import { BrowserServerMessageService } from '../message-service' ; jest . setTimeout ( 60000 ) ; const nitroAdjudicatorAddress = makeAddress ( process . env . NITRO_ADJUDICATOR_ADDRESS ! ) ; const rpcEndpoint = process . env . RPC_ENDPOINT ; const chainId = process . env . CHAIN_ID ; if ( ! rpcEndpoint ) throw new Error ( 'RPC_ENDPOINT must be defined' ) ; const serverConfig = defaultTestWalletConfig ( { databaseConfiguration : { connection : { database : 'interop_test' } } , networkConfiguration : { chainNetworkID : chainId ? parseInt ( chainId ) : defaultTestWalletConfig ( ) . networkConfiguration . chainNetworkID } , chainServiceConfiguration : { attachChainService : true , provider : rpcEndpoint , pk : TEST_ACCOUNTS [ 0 ] . privateKey } , syncConfiguration : { pollInterval : 3600000 } } ) ; let provider ; let nitroAdjudicatorContract ; let serverWallet ; let browserWallet ; let serverAddress ; let serverDestination ; let browserAddress ; let browserDestination ; beforeAll ( async ( ) => { provider = new providers . JsonRpcProvider ( rpcEndpoint ) ; nitroAdjudicatorContract = new Contract ( nitroAdjudicatorAddress , ContractArtifacts . NitroAdjudicatorArtifact . abi , provider ) ; mineOnEvent ( nitroAdjudicatorContract ) ; await DBAdmin . truncateDatabase ( serverConfig ) ; browserWallet = await ChannelWallet . create ( makeAddress ( new Wallet ( TEST_ACCOUNTS [ 1 ] . privateKey ) . address ) ) ; const factory = BrowserServerMessageService . createFactory ( browserWallet ) ; serverWallet = await ServerWallet . create ( serverConfig , factory ) ; serverAddress = await serverWallet . getSigningAddress ( ) ; serverDestination = makeDestination ( serverAddress ) ; browserAddress = makeAddress ( await browserWallet . getAddress ( ) ) ; browserDestination = makeDestination ( browserAddress ) ; } ) ; afterAll ( async ( ) => { browserWallet . destroy ( ) ; await serverWallet . destroy ( ) ; provider . polling = false ; provider . removeAllListeners ( ) ; nitroAdjudicatorContract . removeAllListeners ( ) ; } ) ; async function mineBlocks ( confirmations = 5 ) { for ( const _i in _ . range ( confirmations ) ) { await provider . send ( 'evm_mine' , [ ] ) ; } } const mineBlocksForEvent = ( ) => mineBlocks ( ) ; function mineOnEvent ( contract ) { contract . on ( 'Deposited' , mineBlocksForEvent ) ; } it ( 'server wallet creates channel + cooperates with browser wallet to fund channel' , async ( ) => { const [ createResult ] = await serverWallet . createChannels ( [ { appData : '0x' , appDefinition : constants . AddressZero , fundingStrategy : 'Direct' , challengeDuration : 86400 , participants : [ { participantId : 'server' , signingAddress : serverAddress , destination : serverDestination } , { participantId : browserAddress , signingAddress : browserAddress , destination : browserDestination } ] , allocations : [ { asset : constants . AddressZero , allocationItems : [ { amount : BN . from ( 3 ) , destination : serverDestination } , { amount : BN . from ( 5 ) , destination : browserDestination } ] } ] } ] ) ; const { channelId } = createResult ; await browserWallet . pushMessage ( { jsonrpc : '2.0' , id : 2 , method : 'JoinChannel' , params : { channelId } } , 'dummyDomain' ) ; const result = await createResult . done ; expect ( result . type ) . toBe ( 'Success' ) ; } ) ; it ( 'browser wallet creates channel + cooperates with server wallet to fund channel' , async ( ) => { const createChannelParams = { participants : [ { participantId : browserAddress , signingAddress : browserAddress , destination : browserDestination } , { participantId : 'server' , signingAddress : serverAddress , destination : serverDestination } ] , allocations : [ { asset : constants . AddressZero , allocationItems : [ { amount : formatAmount ( '0x5' as Uint256 ) , destination : browserDestination } , { amount : formatAmount ( '0x3' as Uint256 ) , destination : serverDestination } ] } ] , appDefinition : constants . AddressZero , appData : '0x' , fundingStrategy : 'Direct' , challengeDuration : 86400 } ; await browserWallet . pushMessage ( { jsonrpc : '2.0' , id : 1 , method : 'CreateChannel' , params : createChannelParams } , 'dummyDomain' ) ; const channelId = Object . keys ( browserWallet . getRichObjectives ( ) ) [ 0 ] ; await browserWallet . approveRichObjective ( channelId ) ; const objectiveId = `OpenChannel-${ channelId }` ; const [ approveResult ] = await serverWallet . approveObjectives ( [ objectiveId ] ) ; const result = await approveResult . done ; expect ( result . type ) . toBe ( 'Success' ) ; } ) ;