import { Signature , ethers } from 'ethers' ; import ForceMoveArtifact from '../../../artifacts/contracts/ForceMove.sol/ForceMove.json' ; import { signChallengeMessage } from '../../signatures' ; import { hashOutcome } from '../outcome' ; import { getFixedPart , getVariablePart , hashAppPart , State } from '../state' ; export const ForceMoveContractInterface = new ethers . utils . Interface ( ForceMoveArtifact . abi ) ; interface CheckpointData { challengeState ? : State ; states : State [ ] ; signatures : Signature [ ] ; whoSignedWhat : number [ ] ; } export function createChallengeTransaction ( states , signatures , whoSignedWhat , challengerPrivateKey ) { if ( states . length === 0 ) { throw new Error ( 'No states provided' ) ; } const { participants } = states [ 0 ] . channel ; if ( participants . length !== signatures . length ) { throw new Error ( `Participants (length:${ participants . length }) and signatures (length:${ signatures . length }) need to be the same length` ) ; } const variableParts = states . map ( s => getVariablePart ( s ) ) ; const fixedPart = getFixedPart ( states [ 0 ] ) ; const largestTurnNum = Math . max ( ... states . map ( s => s . turnNum ) ) ; const isFinalCount = states . filter ( s => s . isFinal === true ) . length ; const signedStates = states . map ( s => ( { state : s , signature : { v : 0 , r : '' , s : '' , _vs : '' , recoveryParam : 0 } , } ) ) ; const challengerSignature = signChallengeMessage ( signedStates , challengerPrivateKey ) ; const data = ForceMoveContractInterface . encodeFunctionData ( 'challenge' , [ fixedPart , largestTurnNum , variableParts , isFinalCount , signatures , whoSignedWhat , challengerSignature , ] ) ; return { data } ; } interface RespondArgs { challengeState : State ; responseState : State ; responseSignature : Signature ; } export function respondArgs ( { challengeState , responseState , responseSignature , } ) { const isFinalAB = [ challengeState . isFinal , responseState . isFinal ] ; const fixedPart = getFixedPart ( responseState ) ; const variablePartAB = [ getVariablePart ( challengeState ) , getVariablePart ( responseState ) ] ; return [ isFinalAB , fixedPart , variablePartAB , responseSignature ] ; } export function createRespondTransaction ( args ) { const data = ForceMoveContractInterface . encodeFunctionData ( 'respond' , respondArgs ( args ) ) ; return { data } ; } export function createCheckpointTransaction ( { states , signatures , whoSignedWhat , } ) { const data = ForceMoveContractInterface . encodeFunctionData ( 'checkpoint' , checkpointArgs ( { states , signatures , whoSignedWhat } ) ) ; return { data } ; } export function checkpointArgs ( { states , signatures , whoSignedWhat } ) { const largestTurnNum = Math . max ( ... states . map ( s => s . turnNum ) ) ; const fixedPart = getFixedPart ( states [ 0 ] ) ; const variableParts = states . map ( s => getVariablePart ( s ) ) ; const isFinalCount = states . filter ( s => s . isFinal ) . length ; return [ fixedPart , largestTurnNum , variableParts , isFinalCount , signatures , whoSignedWhat ] ; } export function createConcludeTransaction ( states , signatures , whoSignedWhat ) { const data = ForceMoveContractInterface . encodeFunctionData ( 'conclude' , concludeArgs ( states , signatures , whoSignedWhat ) ) ; return { data } ; } export function concludeArgs ( states , signatures , whoSignedWhat ) { if ( states . length === 0 ) { throw new Error ( 'No states provided' ) ; } const { participants } = states [ 0 ] . channel ; if ( participants . length !== signatures . length ) { throw new Error ( `Participants (length:${ participants . length }) and signatures (length:${ signatures . length }) need to be the same length` ) ; } const lastState = states . reduce ( ( s1 , s2 ) => ( s1 . turnNum >= s2 . turnNum ? s1 : s2 ) , states [ 0 ] ) ; const largestTurnNum = lastState . turnNum ; const fixedPart = getFixedPart ( lastState ) ; const appPartHash = hashAppPart ( lastState ) ; const outcomeHash = hashOutcome ( lastState . outcome ) ; const numStates = states . length ; return [ largestTurnNum , fixedPart , appPartHash , outcomeHash , numStates , whoSignedWhat , signatures , ] ; }