vega-frontend-monorepo/apps/governance/src/hooks/use-get-association-breakdown.ts

99 lines
2.9 KiB
TypeScript

import React from 'react';
import type { ethers } from 'ethers';
import * as Sentry from '@sentry/react';
import { addDecimal } from '@vegaprotocol/utils';
import type {
StakingBridge,
TokenVesting,
} from '@vegaprotocol/smart-contracts';
import { useAppState } from '../contexts/app-state/app-state-context';
import BigNumber from 'bignumber.js';
import { useBalances } from '../lib/balances/balances-store';
export enum StakingEventType {
Stake_Removed = 'Stake_Removed',
Stake_Deposited = 'Stake_Deposited',
}
export function useGetAssociationBreakdown(
ethAddress: string,
staking: StakingBridge,
vesting: TokenVesting
): () => Promise<void> {
const {
appState: { decimals },
} = useAppState();
const { setAssociationBreakdown } = useBalances();
const getAssociationBreakdown = React.useCallback(async () => {
try {
const [stakingAssociations, vestingAssociations] = await Promise.all([
userTotalStakedByVegaKey(staking, ethAddress, decimals),
userTotalStakedByVegaKey(vesting, ethAddress, decimals),
]);
setAssociationBreakdown({
stakingAssociations,
vestingAssociations,
});
} catch (err) {
Sentry.captureException(err);
}
}, [ethAddress, staking, vesting, decimals, setAssociationBreakdown]);
return getAssociationBreakdown;
}
async function userTotalStakedByVegaKey(
contract: StakingBridge | TokenVesting,
ethereumAccount: string,
decimals: number
): Promise<{ [vegaKey: string]: BigNumber }> {
const addFilter = contract.contract.filters.Stake_Deposited(ethereumAccount);
const removeFilter = contract.contract.filters.Stake_Removed(ethereumAccount);
const addEvents = await contract.contract.queryFilter(addFilter);
const removeEvents = await contract.contract.queryFilter(removeFilter);
const res = combineStakeEventsByVegaKey(
[...addEvents, ...removeEvents],
decimals
);
return res;
}
function combineStakeEventsByVegaKey(
events: ethers.Event[],
decimals: number
): { [vegaKey: string]: BigNumber } {
const res = events.reduce((obj, e) => {
const vegaKey = e.args?.vega_public_key;
const amount = parseEventAmount(e, decimals);
const isDeposit = e.event === StakingEventType.Stake_Deposited;
const isRemove = e.event === StakingEventType.Stake_Removed;
if (!isDeposit && !isRemove) return obj;
if (Object.prototype.hasOwnProperty.call(obj, vegaKey)) {
if (isDeposit) {
obj[vegaKey] = obj[vegaKey].plus(amount);
} else {
obj[vegaKey] = obj[vegaKey].minus(amount);
}
} else {
if (isDeposit) {
obj[vegaKey] = amount;
} else {
obj[vegaKey] = new BigNumber(0);
}
}
return obj;
}, {} as { [vegaKey: string]: BigNumber });
return res;
}
function parseEventAmount(e: ethers.Event, decimals: number) {
const rawAmount = new BigNumber(e.args?.amount.toString() || 0);
return new BigNumber(addDecimal(rawAmount.toString(), decimals));
}