import { LastCashoutActionResponse , BeeDebug } from '@ethersphere/bee-js' ; import { useEffect , useState } from 'react' ; import { Token } from '../models/Token' ; import { makeRetriablePromise , unwrapPromiseSettlements } from '../utils' ; import { Balance , Settlements , Settlement } from '../types' ; interface UseAccountingHook { isLoadingUncashed : boolean ; totalUncashed : Token ; accounting : Accounting [ ] | null ; } export interface Accounting { peer : string ; uncashedAmount : Token ; balance : Token ; received : Token ; sent : Token ; total : Token ; } param balances param settlements param uncashedAmounts returns function mergeAccounting ( balances , settlements ? , uncashedAmounts ? ) { if ( ! balances || ! settlements ) return null ; const accounting = { } ; balances . forEach ( ( { peer , balance } ) => ( accounting [ peer ] = { peer , balance , sent : new Token ( '0' ) , received : new Token ( '0' ) , uncashedAmount : new Token ( '0' ) , total : balance , } ) ) ; settlements . forEach ( ( { peer , sent , received } ) => ( accounting [ peer ] = { ... accounting [ peer ] , sent , received , total : new Token ( accounting [ peer ] . balance . toBigNumber . plus ( received . toBigNumber ) . minus ( sent . toBigNumber ) ) , } ) ) ; if ( ! uncashedAmounts ) return Object . values ( accounting ) . sort ( ( a , b ) => ( a . peer < b . peer ? - 1 : 1 ) ) ; uncashedAmounts ?. forEach ( ( { peer , uncashedAmount } ) => { accounting [ peer ] . uncashedAmount = new Token ( uncashedAmount ) ; } ) ; return Object . values ( accounting ) . sort ( ( a , b ) => { const diff = b . uncashedAmount . toBigNumber . minus ( a . uncashedAmount . toBigNumber ) . toNumber ( ) ; if ( diff !== 0 ) return diff ; return a . peer < b . peer ? - 1 : 1 ; } ) ; } export const useAccounting = ( beeDebugApi , settlements , balances ) : UseAccountingHook => { const [ isLoadingUncashed , setIsloadingUncashed ] = useState < boolean > ( false ) ; const [ uncashedAmounts , setUncashedAmounts ] = useState < LastCashoutActionResponse [ ] | undefined > ( undefined ) ; useEffect ( ( ) => { if ( isLoadingUncashed || ! beeDebugApi || ! settlements || uncashedAmounts ) return ; setIsloadingUncashed ( true ) ; const promises = settlements . settlements . filter ( ( { received } ) => received . toBigNumber . gt ( '0' ) ) . map ( ( { peer } ) => makeRetriablePromise ( ( ) => beeDebugApi . getLastCashoutAction ( peer ) ) ) ; Promise . allSettled ( promises ) . then ( settlements => { const results = unwrapPromiseSettlements ( settlements ) ; setUncashedAmounts ( results . fulfilled ) ; setIsloadingUncashed ( false ) ; } ) ; } , [ settlements , isLoadingUncashed , uncashedAmounts , beeDebugApi ] ) ; const accounting = mergeAccounting ( balances , settlements ?. settlements , uncashedAmounts ) ; let totalUncashed = new Token ( '0' ) ; accounting ?. forEach ( ( { uncashedAmount } ) => ( totalUncashed = new Token ( totalUncashed . toBigNumber . plus ( uncashedAmount . toBigNumber ) ) ) ) ; return { isLoadingUncashed , totalUncashed , accounting , } ; } ;