import { ChannelConstants , Hashed , SignedStateVarsWithHash , State , calculateChannelId , toNitroState , convertToInternalParticipant , deserializeOutcome , SignedState , SignedStateWithHash , wireStateToNitroState , makeAddress , } from '@statechannels/wallet-core' ; import { hashState } from '@statechannels/wasm-utils' ; import _ from 'lodash' ; import { SignedState as WireSignedState } from '@statechannels/wire-format' ; import { recoverAddress as wasmRecoverAddress } from './utilities/signatures' ; import { Bytes32 } from './type-aliases' ; import { Channel } from './models/channel' ; import { recordFunctionMetrics } from './metrics' ; export const dropNonVariables = ( s ) : SignedStateVarsWithHash => _ . pick ( s , 'appData' , 'outcome' , 'isFinal' , 'turnNum' , 'stateHash' , 'signatures' ) ; export const dropNonConstants = ( s ) : ChannelConstants => _ . pick ( s , 'channelNonce' , 'chainId' , 'participants' , 'appDefinition' , 'challengeDuration' ) ; export const addHash = < T extends State = State > ( s ) : T & Hashed => ( { ... s , stateHash : recordFunctionMetrics ( hashState ( toNitroState ( s ) as any ) ) , } ) ; export const addHashes = ( c ) : Channel => _ . assign ( c , { vars : c . vars . map ( v => addHash ( { ... c . channelConstants , ... v } ) ) as any } ) ; export const addChannelId = < T extends ChannelConstants = ChannelConstants > ( c ) : T & { channelId : Bytes32 ; } => { ( c as any ) . channelId = calculateChannelId ( c ) ; return c as any ; } ; param vars param signedState export function addState ( vars , signedState ) { const { stateHash , signatures } = signedState ; const ret = _ . cloneDeep ( vars ) ; const existing = _ . find ( ret , [ 'stateHash' , stateHash ] ) ; if ( existing ) { existing . signatures = _ . uniqBy ( [ ... existing . signatures , ... signatures ] , 'signature' ) ; } else { ret . push ( dropNonVariables ( signedState ) ) ; } return ret ; } param signedStates param support export function clearOldStates ( signedStates , support ) { let sorted = _ . reverse ( _ . sortBy ( signedStates , s => s . turnNum ) ) ; if ( support && support . length > 0 ) { const { stateHash : firstSupportStateHash } = support [ support . length - 1 ] ; const supportIndex = sorted . findIndex ( sv => sv . stateHash === firstSupportStateHash ) ; sorted = sorted . slice ( 0 , supportIndex + 1 ) ; } return sorted ; } param channelId param state returns export function fastDeserializeState ( channelId , state ) { const { outcome , participants , signatures } = state ; const nitroState = wireStateToNitroState ( state ) ; const signatureEntries = signatures . map ( signature => { const signer = wasmRecoverAddress ( signature , nitroState ) ; if ( ! nitroState . channel . participants . includes ( signer ) ) throw new Error ( `Recovered address ${ signer } is not a participant in channel ${ channelId }` ) ; return { signature , signer } ; } ) ; return { ... state , appDefinition : makeAddress ( state . appDefinition ) , outcome : deserializeOutcome ( outcome ) , participants : participants . map ( convertToInternalParticipant ) , signatures : signatureEntries , } ; }