import { utils , BigNumber , constants } from 'ethers' ; import ExitFormat , { AllocationType } from '@statechannels/exit-format' ; import { parseEventResult } from '../ethers-utils' ; import { decodeGuaranteeData } from './outcome' ; /**
 * Holds rich information about a Deposited event emitted on chain
 */ export interface DepositedEvent { destination : string ; amountDeposited : BigNumber ; destinationHoldings : BigNumber ; } param eventResult returns export function getDepositedEvent ( eventResult ) { const { destination , amountDeposited , destinationHoldings } = parseEventResult ( eventResult ) ; return { destination , amountDeposited : BigNumber . from ( amountDeposited ) , destinationHoldings : BigNumber . from ( destinationHoldings ) , } ; } param bytes32 returns export function convertBytes32ToAddress ( bytes32 ) { const normalized = utils . hexZeroPad ( bytes32 , 32 ) ; return utils . getAddress ( `0x${ normalized . slice ( - 40 ) }` ) ; } param address returns export function convertAddressToBytes32 ( address ) { const normalizedAddress = BigNumber . from ( address ) . toHexString ( ) ; if ( ! utils . isAddress ( address ) ) { throw new Error ( `Input is not a valid Ethereum address.` ) ; } return utils . hexZeroPad ( normalizedAddress , 32 ) ; } param initialHoldings param allocation param indices export function computeClaimEffectsAndInteractions ( initialHoldings , sourceAllocations , targetAllocations , indexOfTargetInSource , targetAllocationIndicesToPayout ) { let totalPayouts = BigNumber . from ( 0 ) ; let k = 0 ; const newSourceAllocations = [ ] ; const newTargetAllocations = [ ] ; const exitAllocations = [ ] ; for ( let i = 0 ; i < sourceAllocations . length ; i ++ ) { newSourceAllocations . push ( { destination : sourceAllocations [ i ] . destination , amount : sourceAllocations [ i ] . amount , metadata : sourceAllocations [ i ] . metadata , allocationType : sourceAllocations [ i ] . allocationType , } ) ; } for ( let i = 0 ; i < targetAllocations . length ; i ++ ) { newTargetAllocations . push ( { destination : targetAllocations [ i ] . destination , amount : targetAllocations [ i ] . amount , metadata : targetAllocations [ i ] . metadata , allocationType : targetAllocations [ i ] . allocationType , } ) ; exitAllocations . push ( { destination : targetAllocations [ i ] . destination , amount : '0x00' , metadata : targetAllocations [ i ] . metadata , allocationType : targetAllocations [ i ] . allocationType , } ) ; } let sourceSurplus = BigNumber . from ( initialHoldings ) ; for ( let sourceAllocationIndex = 0 ; sourceAllocationIndex < indexOfTargetInSource ; sourceAllocationIndex ++ ) { if ( BigNumber . from ( sourceSurplus ) . isZero ( ) ) break ; const affordsForDestination = min ( BigNumber . from ( sourceAllocations [ sourceAllocationIndex ] . amount ) , sourceSurplus ) ; sourceSurplus = sourceSurplus . sub ( affordsForDestination ) ; } let targetSurplus = min ( sourceSurplus , BigNumber . from ( sourceAllocations [ indexOfTargetInSource ] . amount ) ) ; if ( sourceAllocations [ indexOfTargetInSource ] . allocationType !== AllocationType . guarantee ) throw Error ( 'not a guarantee allocation' ) ; const guaranteeDestinations = decodeGuaranteeData ( sourceAllocations [ indexOfTargetInSource ] . metadata ) ; for ( let j = 0 ; j < guaranteeDestinations . length ; j ++ ) { if ( targetSurplus . isZero ( ) ) break ; for ( let i = 0 ; i < newTargetAllocations . length ; i ++ ) { if ( targetSurplus . isZero ( ) ) break ; if ( BigNumber . from ( guaranteeDestinations [ j ] ) . eq ( BigNumber . from ( newTargetAllocations [ i ] . destination ) ) ) { const affordsForDestination = min ( BigNumber . from ( newTargetAllocations [ i ] . amount ) , targetSurplus ) ; targetSurplus = targetSurplus . sub ( affordsForDestination ) ; if ( targetAllocationIndicesToPayout . length === 0 || ( k < targetAllocationIndicesToPayout . length && targetAllocationIndicesToPayout [ k ] === i ) ) { newTargetAllocations [ i ] . amount = BigNumber . from ( newTargetAllocations [ i ] . amount ) . sub ( affordsForDestination ) . toHexString ( ) ; newSourceAllocations [ indexOfTargetInSource ] . amount = BigNumber . from ( newSourceAllocations [ indexOfTargetInSource ] . amount ) . sub ( affordsForDestination ) . toHexString ( ) ; exitAllocations [ i ] . amount = BigNumber . from ( exitAllocations [ i ] . amount ) . add ( affordsForDestination ) . toHexString ( ) ; totalPayouts = totalPayouts . add ( affordsForDestination ) ; ++ k ; } break ; } } } return { newSourceAllocations , newTargetAllocations , exitAllocations , totalPayouts : totalPayouts . toHexString ( ) , } ; } param initialHoldings param allocation param indices export function computeTransferEffectsAndInteractions ( initialHoldings , allocations , indices ) { let totalPayouts = BigNumber . from ( 0 ) ; const newAllocations = [ ] ; const exitAllocations = Array ( indices . length > 0 ? indices . length : allocations . length ) . fill ( { destination : constants . HashZero , amount : '0x00' , metadata : '0x' , allocationType : 0 , } ) ; let allocatesOnlyZeros = true ; let surplus = BigNumber . from ( initialHoldings ) ; let k = 0 ; for ( let i = 0 ; i < allocations . length ; i ++ ) { newAllocations . push ( { destination : allocations [ i ] . destination , amount : BigNumber . from ( 0 ) . toHexString ( ) , metadata : allocations [ i ] . metadata , allocationType : allocations [ i ] . allocationType , } ) ; const affordsForDestination = min ( BigNumber . from ( allocations [ i ] . amount ) , surplus ) ; if ( indices . length == 0 || ( k < indices . length && indices [ k ] === i ) ) { newAllocations [ i ] . amount = BigNumber . from ( allocations [ i ] . amount ) . sub ( affordsForDestination ) . toHexString ( ) ; exitAllocations [ k ] = { destination : allocations [ i ] . destination , amount : affordsForDestination . toHexString ( ) , metadata : allocations [ i ] . metadata , allocationType : allocations [ i ] . allocationType , } ; totalPayouts = totalPayouts . add ( affordsForDestination ) ; ++ k ; } else { newAllocations [ i ] . amount = allocations [ i ] . amount ; } if ( ! BigNumber . from ( newAllocations [ i ] . amount ) . isZero ( ) ) allocatesOnlyZeros = false ; surplus = surplus . sub ( affordsForDestination ) ; } return { newAllocations , allocatesOnlyZeros , exitAllocations , totalPayouts : totalPayouts . toHexString ( ) , } ; } function min ( a , b ) { return a . gt ( b ) ? b : a ; }