import { BigNumber , utils } from 'ethers' ; import BalanceTree from './balance-tree' ; const { isAddress , getAddress } = utils ; interface MerkleDistributorInfo { merkleRoot : string ; tokenTotal : string ; claims : { [ account ] : { index : number ; amount : string ; proof : string [ ] ; flags ? : { [ flag ] : boolean ; } ; } ; } ; } type OldFormat = { [ account ] : number | string ; } ; type NewFormat = { address : string ; earnings : string ; reasons : string ; } ; export function parseBalanceMap ( balances ) { const balancesInNewFormat = Array . isArray ( balances ) ? balances : Object . keys ( balances ) . map ( ( account ) : NewFormat => ( { address : account , earnings : `0x${ balances [ account ] . toString ( 16 ) }` , reasons : '' , } ) ) ; const dataByAddress = balancesInNewFormat . reduce < { [ address ] : { amount : BigNumber ; flags ? : { [ flag ] : boolean ; } ; } ; } > ( ( memo , { address : account , earnings , reasons } ) => { if ( ! isAddress ( account ) ) { throw new Error ( `Found invalid address: ${ account }` ) ; } const parsed = getAddress ( account ) ; if ( memo [ parsed ] ) throw new Error ( `Duplicate address: ${ parsed }` ) ; const parsedNum = BigNumber . from ( earnings ) ; if ( parsedNum . lte ( 0 ) ) throw new Error ( `Invalid amount for account: ${ account }` ) ; const flags = { isSOCKS : reasons . includes ( 'socks' ) , isLP : reasons . includes ( 'lp' ) , isUser : reasons . includes ( 'user' ) , } ; memo [ parsed ] = { amount : parsedNum , ... ( reasons === '' ? { } : { flags } ) } ; return memo ; } , { } ) ; const sortedAddresses = Object . keys ( dataByAddress ) . sort ( ) ; const tree = new BalanceTree ( sortedAddresses . map ( ( address ) => ( { account : address , amount : dataByAddress [ address ] . amount } ) ) ) ; const claims = sortedAddresses . reduce < { [ address ] : { amount : string ; index : number ; proof : string [ ] ; flags ? : { [ flag ] : boolean ; } ; } ; } > ( ( memo , address , index ) => { const { amount , flags } = dataByAddress [ address ] ; memo [ address ] = { index , amount : amount . toHexString ( ) , proof : tree . getProof ( index , address , amount ) , ... ( flags ? { flags } : { } ) , } ; return memo ; } , { } ) ; const tokenTotal = sortedAddresses . reduce < BigNumber > ( ( memo , key ) => memo . add ( dataByAddress [ key ] . amount ) , BigNumber . from ( 0 ) ) ; return { merkleRoot : tree . getHexRoot ( ) , tokenTotal : tokenTotal . toHexString ( ) , claims , } ; }