feat(token): 1823 tranches service (#2742)
This commit is contained in:
parent
56b5214dbf
commit
92ec7166bc
32
.github/workflows/process-tranches.yml
vendored
32
.github/workflows/process-tranches.yml
vendored
@ -1,32 +0,0 @@
|
|||||||
name: Generate tranches
|
|
||||||
|
|
||||||
on:
|
|
||||||
schedule:
|
|
||||||
- cron: '0 */6 * * *'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
master:
|
|
||||||
name: Generate Queries
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v2
|
|
||||||
with:
|
|
||||||
token: ${{ secrets.VEGA_CI_BOT_GITHUB_TOKEN }}
|
|
||||||
fetch-depth: 0
|
|
||||||
- name: Use Node.js 16
|
|
||||||
id: Node
|
|
||||||
uses: actions/setup-node@v2
|
|
||||||
with:
|
|
||||||
node-version: 16.15.1
|
|
||||||
- name: Install root dependencies
|
|
||||||
run: yarn install
|
|
||||||
- name: Generate queries
|
|
||||||
run: node ./scripts/get-tranches.js
|
|
||||||
- uses: stefanzweifel/git-auto-commit-action@v4
|
|
||||||
with:
|
|
||||||
commit_message: 'chore: update tranches'
|
|
||||||
commit_options: '--no-verify --signoff'
|
|
||||||
skip_fetch: true
|
|
||||||
skip_checkout: true
|
|
@ -1 +0,0 @@
|
|||||||
[]
|
|
File diff suppressed because it is too large
Load Diff
@ -1 +0,0 @@
|
|||||||
[]
|
|
@ -1 +0,0 @@
|
|||||||
[]
|
|
@ -1 +0,0 @@
|
|||||||
[]
|
|
@ -1 +0,0 @@
|
|||||||
[]
|
|
@ -1 +0,0 @@
|
|||||||
[]
|
|
@ -12,6 +12,7 @@ NX_ETH_WALLET_MNEMONIC=ozone access unlock valid olympic save include omit suppl
|
|||||||
NX_LOCAL_PROVIDER_URL=http://localhost:8545/
|
NX_LOCAL_PROVIDER_URL=http://localhost:8545/
|
||||||
NX_VEGA_WALLET_URL=http://localhost:1789
|
NX_VEGA_WALLET_URL=http://localhost:1789
|
||||||
NX_VEGA_DOCS_URL=https://docs.vega.xyz/mainnet
|
NX_VEGA_DOCS_URL=https://docs.vega.xyz/mainnet
|
||||||
|
NX_TRANCHES_SERVICE_URL=https://tranches-stagnet3-k8s.ops.vega.xyz
|
||||||
|
|
||||||
#Test configuration variables
|
#Test configuration variables
|
||||||
CYPRESS_FAIRGROUND=false
|
CYPRESS_FAIRGROUND=false
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
const connectPrompt = '[data-testid="eth-connect-prompt"]';
|
|
||||||
const connectButton = '[data-testid="connect-to-eth-btn"]';
|
const connectButton = '[data-testid="connect-to-eth-btn"]';
|
||||||
|
|
||||||
context(
|
context(
|
||||||
@ -18,7 +17,7 @@ context(
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should have connect Eth wallet info', function () {
|
it('should have connect Eth wallet info', function () {
|
||||||
cy.get(connectPrompt).should('be.visible');
|
cy.get(connectButton).should('be.visible');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should have connect Eth wallet button', function () {
|
it('should have connect Eth wallet button', function () {
|
||||||
|
@ -12,6 +12,7 @@ NX_VEGA_EXPLORER_URL=https://explorer.fairground.wtf
|
|||||||
NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
|
NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
|
||||||
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
|
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
|
||||||
NX_DELEGATIONS_PAGINATION=50
|
NX_DELEGATIONS_PAGINATION=50
|
||||||
|
NX_TRANCHES_SERVICE_URL=https://tranches-stagnet3-k8s.ops.vega.xyz
|
||||||
|
|
||||||
#Test configuration variables
|
#Test configuration variables
|
||||||
CYPRESS_FAIRGROUND=false
|
CYPRESS_FAIRGROUND=false
|
||||||
|
@ -15,6 +15,7 @@ NX_LOCAL_PROVIDER_URL=http://localhost:8545/
|
|||||||
NX_VEGA_WALLET_URL=http://localhost:1789
|
NX_VEGA_WALLET_URL=http://localhost:1789
|
||||||
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
|
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
|
||||||
NX_DELEGATIONS_PAGINATION=50
|
NX_DELEGATIONS_PAGINATION=50
|
||||||
|
NX_TRANCHES_SERVICE_URL=https://tranches-stagnet3-k8s.ops.vega.xyz
|
||||||
|
|
||||||
#Test configuration variables
|
#Test configuration variables
|
||||||
CYPRESS_FAIRGROUND=false
|
CYPRESS_FAIRGROUND=false
|
||||||
|
@ -9,3 +9,4 @@ NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
|
|||||||
NX_VEGA_EXPLORER_URL=https://dev.explorer.vega.xyz
|
NX_VEGA_EXPLORER_URL=https://dev.explorer.vega.xyz
|
||||||
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
|
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
|
||||||
NX_DELEGATIONS_PAGINATION=50
|
NX_DELEGATIONS_PAGINATION=50
|
||||||
|
NX_TRANCHES_SERVICE_URL=https://tranches-devnet1-k8s.ops.vega.xyz
|
@ -10,3 +10,4 @@ NX_VEGA_EXPLORER_URL=https://explorer.vega.xyz
|
|||||||
NX_VEGA_DOCS_URL=https://docs.vega.xyz/mainnet
|
NX_VEGA_DOCS_URL=https://docs.vega.xyz/mainnet
|
||||||
NX_SENTRY_DSN=https://4b8c8a8ba07742648aa4dfe1b8d17e40:87edc2605e544f888305d7fc4a9141bd@o286262.ingest.sentry.io/5882996
|
NX_SENTRY_DSN=https://4b8c8a8ba07742648aa4dfe1b8d17e40:87edc2605e544f888305d7fc4a9141bd@o286262.ingest.sentry.io/5882996
|
||||||
NX_DELEGATIONS_PAGINATION=50
|
NX_DELEGATIONS_PAGINATION=50
|
||||||
|
NX_TRANCHES_SERVICE_URL=https://tranches-mainnet-k8s.ops.vega.xyz
|
@ -6,3 +6,4 @@ NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/stagnet1-network.json
|
|||||||
NX_VEGA_EXPLORER_URL=https://stagnet1.explorer.vega.xyz
|
NX_VEGA_EXPLORER_URL=https://stagnet1.explorer.vega.xyz
|
||||||
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
|
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
|
||||||
NX_DELEGATIONS_PAGINATION=50
|
NX_DELEGATIONS_PAGINATION=50
|
||||||
|
NX_TRANCHES_SERVICE_URL=https://tranches-stagnet1-k8s.ops.vega.xyz
|
@ -7,3 +7,4 @@ NX_VEGA_EXPLORER_URL=https://stagnet3.explorer.vega.xyz
|
|||||||
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
|
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
|
||||||
NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
|
NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
|
||||||
NX_DELEGATIONS_PAGINATION=50
|
NX_DELEGATIONS_PAGINATION=50
|
||||||
|
NX_TRANCHES_SERVICE_URL=https://tranches-stagnet3-k8s.ops.vega.xyz
|
@ -10,3 +10,4 @@ NX_VEGA_EXPLORER_URL=https://explorer.fairground.wtf
|
|||||||
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
|
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
|
||||||
NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
|
NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
|
||||||
NX_DELEGATIONS_PAGINATION=50
|
NX_DELEGATIONS_PAGINATION=50
|
||||||
|
NX_TRANCHES_SERVICE_URL=https://tranches-testnet-k8s.ops.vega.xyz
|
@ -1,17 +1,17 @@
|
|||||||
import * as Sentry from '@sentry/react';
|
|
||||||
import { toBigNum } from '@vegaprotocol/react-helpers';
|
|
||||||
import { useEthereumConfig } from '@vegaprotocol/web3';
|
|
||||||
import { useWeb3React } from '@web3-react/core';
|
import { useWeb3React } from '@web3-react/core';
|
||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
|
|
||||||
import { useAppState } from '../../contexts/app-state/app-state-context';
|
import { useAppState } from '../../contexts/app-state/app-state-context';
|
||||||
import { useContracts } from '../../contexts/contracts/contracts-context';
|
import { useContracts } from '../../contexts/contracts/contracts-context';
|
||||||
import { useGetAssociationBreakdown } from '../../hooks/use-get-association-breakdown';
|
import { useGetAssociationBreakdown } from '../../hooks/use-get-association-breakdown';
|
||||||
import { useGetUserTrancheBalances } from '../../hooks/use-get-user-tranche-balances';
|
import { useGetUserBalances } from '../../hooks/use-get-user-balances';
|
||||||
import { useBalances } from '../../lib/balances/balances-store';
|
import { useBalances } from '../../lib/balances/balances-store';
|
||||||
import type { ReactElement } from 'react';
|
import type { ReactElement } from 'react';
|
||||||
import { useVegaWallet } from '@vegaprotocol/wallet';
|
import { useVegaWallet } from '@vegaprotocol/wallet';
|
||||||
import { useListenForStakingEvents as useListenForAssociationEvents } from '../../hooks/use-listen-for-staking-events';
|
import { useListenForStakingEvents as useListenForAssociationEvents } from '../../hooks/use-listen-for-staking-events';
|
||||||
|
import { useTranches } from '../../lib/tranches/tranches-store';
|
||||||
|
import { useUserTrancheBalances } from '../../routes/redemption/hooks';
|
||||||
|
import { useEthereumConfig } from '@vegaprotocol/web3';
|
||||||
|
|
||||||
interface BalanceManagerProps {
|
interface BalanceManagerProps {
|
||||||
children: ReactElement;
|
children: ReactElement;
|
||||||
@ -24,7 +24,13 @@ export const BalanceManager = ({ children }: BalanceManagerProps) => {
|
|||||||
const {
|
const {
|
||||||
appState: { decimals },
|
appState: { decimals },
|
||||||
} = useAppState();
|
} = useAppState();
|
||||||
const { updateBalances: updateStoreBalances } = useBalances();
|
const updateStoreBalances = useBalances((state) => state.updateBalances);
|
||||||
|
const setTranchesBalances = useBalances((state) => state.setTranchesBalances);
|
||||||
|
const getUserBalances = useGetUserBalances(account);
|
||||||
|
const userTrancheBalances = useUserTrancheBalances(account);
|
||||||
|
useEffect(() => {
|
||||||
|
setTranchesBalances(userTrancheBalances);
|
||||||
|
}, [setTranchesBalances, userTrancheBalances]);
|
||||||
const { config } = useEthereumConfig();
|
const { config } = useEthereumConfig();
|
||||||
|
|
||||||
const numberOfConfirmations = config?.confirmations || 0;
|
const numberOfConfirmations = config?.confirmations || 0;
|
||||||
@ -41,10 +47,10 @@ export const BalanceManager = ({ children }: BalanceManagerProps) => {
|
|||||||
numberOfConfirmations
|
numberOfConfirmations
|
||||||
);
|
);
|
||||||
|
|
||||||
const getUserTrancheBalances = useGetUserTrancheBalances(
|
const getTranches = useTranches((state) => state.getTranches);
|
||||||
account || '',
|
useEffect(() => {
|
||||||
contracts?.vesting
|
getTranches(decimals);
|
||||||
);
|
}, [decimals, getTranches]);
|
||||||
const getAssociationBreakdown = useGetAssociationBreakdown(
|
const getAssociationBreakdown = useGetAssociationBreakdown(
|
||||||
account || '',
|
account || '',
|
||||||
contracts?.staking,
|
contracts?.staking,
|
||||||
@ -54,50 +60,14 @@ export const BalanceManager = ({ children }: BalanceManagerProps) => {
|
|||||||
// update balances on connect to Ethereum
|
// update balances on connect to Ethereum
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const updateBalances = async () => {
|
const updateBalances = async () => {
|
||||||
if (!account || !config) return;
|
const balances = await getUserBalances();
|
||||||
try {
|
if (balances) {
|
||||||
const [b, w, stats, a] = await Promise.all([
|
updateStoreBalances(balances);
|
||||||
contracts.vesting.user_total_all_tranches(account),
|
|
||||||
contracts.token.balanceOf(account),
|
|
||||||
contracts.vesting.user_stats(account),
|
|
||||||
contracts.token.allowance(
|
|
||||||
account,
|
|
||||||
config.staking_bridge_contract.address
|
|
||||||
),
|
|
||||||
]);
|
|
||||||
|
|
||||||
const balance = toBigNum(b, decimals);
|
|
||||||
const walletBalance = toBigNum(w, decimals);
|
|
||||||
const lien = toBigNum(stats.lien, decimals);
|
|
||||||
const allowance = toBigNum(a, decimals);
|
|
||||||
|
|
||||||
updateStoreBalances({
|
|
||||||
balanceFormatted: balance,
|
|
||||||
walletBalance,
|
|
||||||
lien,
|
|
||||||
allowance,
|
|
||||||
});
|
|
||||||
} catch (err) {
|
|
||||||
Sentry.captureException(err);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
updateBalances();
|
updateBalances();
|
||||||
}, [
|
}, [getUserBalances, updateStoreBalances]);
|
||||||
decimals,
|
|
||||||
contracts.token,
|
|
||||||
contracts.vesting,
|
|
||||||
account,
|
|
||||||
config,
|
|
||||||
updateStoreBalances,
|
|
||||||
]);
|
|
||||||
|
|
||||||
// This use effect hook is very expensive and is kept separate to prevent expensive reloading of data.
|
|
||||||
useEffect(() => {
|
|
||||||
if (account) {
|
|
||||||
getUserTrancheBalances();
|
|
||||||
}
|
|
||||||
}, [account, getUserTrancheBalances]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (account) {
|
if (account) {
|
||||||
|
@ -6,27 +6,22 @@ import {
|
|||||||
useAppState,
|
useAppState,
|
||||||
} from '../../contexts/app-state/app-state-context';
|
} from '../../contexts/app-state/app-state-context';
|
||||||
|
|
||||||
interface EthConnectPrompProps {
|
export const EthConnectPrompt = () => {
|
||||||
children?: React.ReactNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const EthConnectPrompt = ({ children }: EthConnectPrompProps) => {
|
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { appDispatch } = useAppState();
|
const { appDispatch } = useAppState();
|
||||||
return (
|
return (
|
||||||
<>
|
<Button
|
||||||
{children}
|
variant="primary"
|
||||||
<Button
|
onClick={() =>
|
||||||
onClick={() =>
|
appDispatch({
|
||||||
appDispatch({
|
type: AppStateActionType.SET_ETH_WALLET_OVERLAY,
|
||||||
type: AppStateActionType.SET_ETH_WALLET_OVERLAY,
|
isOpen: true,
|
||||||
isOpen: true,
|
})
|
||||||
})
|
}
|
||||||
}
|
fill={true}
|
||||||
data-testid="connect-to-eth-btn"
|
data-testid="connect-to-eth-btn"
|
||||||
>
|
>
|
||||||
{t('connectEthWallet')}
|
{t('connectEthWallet')}
|
||||||
</Button>
|
</Button>
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -58,6 +58,7 @@ const envName = windowOrDefault('NX_VEGA_ENV') ?? 'local';
|
|||||||
|
|
||||||
export const ENV = {
|
export const ENV = {
|
||||||
// Environment
|
// Environment
|
||||||
|
tranchesServiceUrl: windowOrDefault('NX_TRANCHES_SERVICE_URL'),
|
||||||
dsn: windowOrDefault('NX_SENTRY_DSN'),
|
dsn: windowOrDefault('NX_SENTRY_DSN'),
|
||||||
urlConnect: TRUTHY.includes(windowOrDefault('NX_ETH_URL_CONNECT')),
|
urlConnect: TRUTHY.includes(windowOrDefault('NX_ETH_URL_CONNECT')),
|
||||||
explorerUrl: windowOrDefault('NX_VEGA_EXPLORER'),
|
explorerUrl: windowOrDefault('NX_VEGA_EXPLORER'),
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import type { Tranche } from '@vegaprotocol/smart-contracts';
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import type { BigNumber } from '../../lib/bignumber';
|
import type { BigNumber } from '../../lib/bignumber';
|
||||||
@ -19,21 +18,7 @@ export interface VegaKey {
|
|||||||
meta: Array<{ key: string; value: string }> | null;
|
meta: Array<{ key: string; value: string }> | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface UserTrancheBalance {
|
|
||||||
/** ID of tranche */
|
|
||||||
id: number;
|
|
||||||
|
|
||||||
/** Users vesting tokens on tranche */
|
|
||||||
locked: BigNumber;
|
|
||||||
|
|
||||||
/** Users vested tokens on tranche */
|
|
||||||
vested: BigNumber;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface AppState {
|
export interface AppState {
|
||||||
/** Array of tranche objects */
|
|
||||||
tranches: Tranche[] | null;
|
|
||||||
|
|
||||||
/** Number of decimal places of the VEGA token (18 on Mainnet, 5 on Testnet) */
|
/** Number of decimal places of the VEGA token (18 on Mainnet, 5 on Testnet) */
|
||||||
decimals: number;
|
decimals: number;
|
||||||
|
|
||||||
@ -52,9 +37,6 @@ export interface AppState {
|
|||||||
/** Whether or not the connect to Ethereum wallet overlay is open */
|
/** Whether or not the connect to Ethereum wallet overlay is open */
|
||||||
ethConnectOverlay: boolean;
|
ethConnectOverlay: boolean;
|
||||||
|
|
||||||
/** The error if one was thrown during retrieval of tranche data */
|
|
||||||
trancheError: Error | null;
|
|
||||||
|
|
||||||
/** Whether or not the mobile drawer is open. Only relevant on screens smaller than 960 */
|
/** Whether or not the mobile drawer is open. Only relevant on screens smaller than 960 */
|
||||||
drawerOpen: boolean;
|
drawerOpen: boolean;
|
||||||
|
|
||||||
@ -71,12 +53,10 @@ export enum AppStateActionType {
|
|||||||
SET_TOKEN,
|
SET_TOKEN,
|
||||||
SET_ALLOWANCE,
|
SET_ALLOWANCE,
|
||||||
REFRESH_BALANCES,
|
REFRESH_BALANCES,
|
||||||
SET_TRANCHE_DATA,
|
|
||||||
SET_VEGA_WALLET_OVERLAY,
|
SET_VEGA_WALLET_OVERLAY,
|
||||||
SET_VEGA_WALLET_MANAGE_OVERLAY,
|
SET_VEGA_WALLET_MANAGE_OVERLAY,
|
||||||
SET_ETH_WALLET_OVERLAY,
|
SET_ETH_WALLET_OVERLAY,
|
||||||
SET_DRAWER,
|
SET_DRAWER,
|
||||||
SET_TRANCHE_ERROR,
|
|
||||||
REFRESH_ASSOCIATED_BALANCES,
|
REFRESH_ASSOCIATED_BALANCES,
|
||||||
SET_ASSOCIATION_BREAKDOWN,
|
SET_ASSOCIATION_BREAKDOWN,
|
||||||
SET_TRANSACTION_OVERLAY,
|
SET_TRANSACTION_OVERLAY,
|
||||||
@ -90,14 +70,6 @@ export type AppStateAction =
|
|||||||
totalSupply: BigNumber;
|
totalSupply: BigNumber;
|
||||||
totalAssociated: BigNumber;
|
totalAssociated: BigNumber;
|
||||||
}
|
}
|
||||||
| {
|
|
||||||
type: AppStateActionType.SET_TRANCHE_DATA;
|
|
||||||
tranches: Tranche[];
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
type: AppStateActionType.SET_TRANCHE_ERROR;
|
|
||||||
error: Error | null;
|
|
||||||
}
|
|
||||||
| {
|
| {
|
||||||
type: AppStateActionType.SET_VEGA_WALLET_OVERLAY;
|
type: AppStateActionType.SET_VEGA_WALLET_OVERLAY;
|
||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
|
@ -14,11 +14,9 @@ const initialAppState: AppState = {
|
|||||||
totalAssociated: new BigNumber(0),
|
totalAssociated: new BigNumber(0),
|
||||||
decimals: 0,
|
decimals: 0,
|
||||||
totalSupply: new BigNumber(0),
|
totalSupply: new BigNumber(0),
|
||||||
tranches: null,
|
|
||||||
vegaWalletOverlay: false,
|
vegaWalletOverlay: false,
|
||||||
vegaWalletManageOverlay: false,
|
vegaWalletManageOverlay: false,
|
||||||
ethConnectOverlay: false,
|
ethConnectOverlay: false,
|
||||||
trancheError: null,
|
|
||||||
drawerOpen: false,
|
drawerOpen: false,
|
||||||
transactionOverlay: false,
|
transactionOverlay: false,
|
||||||
bannerMessage: '',
|
bannerMessage: '',
|
||||||
@ -34,17 +32,6 @@ function appStateReducer(state: AppState, action: AppStateAction): AppState {
|
|||||||
totalAssociated: action.totalAssociated,
|
totalAssociated: action.totalAssociated,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
case AppStateActionType.SET_TRANCHE_DATA:
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
tranches: action.tranches,
|
|
||||||
};
|
|
||||||
case AppStateActionType.SET_TRANCHE_ERROR: {
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
trancheError: action.error,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
case AppStateActionType.SET_VEGA_WALLET_OVERLAY: {
|
case AppStateActionType.SET_VEGA_WALLET_OVERLAY: {
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
|
@ -1,666 +0,0 @@
|
|||||||
import parseJSON from 'date-fns/parseJSON';
|
|
||||||
import { BigNumber } from '../../lib/bignumber';
|
|
||||||
import type { Tranche } from '@vegaprotocol/smart-contracts';
|
|
||||||
|
|
||||||
const json: Tranche[] = [
|
|
||||||
{
|
|
||||||
tranche_id: 1,
|
|
||||||
tranche_start: parseJSON('2022-03-05T00:00:00.000Z'),
|
|
||||||
tranche_end: parseJSON('2023-06-05T00:00:00.000Z'),
|
|
||||||
total_added: new BigNumber('3505372.53445'),
|
|
||||||
total_removed: new BigNumber('0'),
|
|
||||||
locked_amount: new BigNumber('3505372.53445'),
|
|
||||||
deposits: [
|
|
||||||
{
|
|
||||||
amount: new BigNumber('187637.95'),
|
|
||||||
user: '0xE6CacAE56Cca8dFdB7910b5A13578719D4E57DA0',
|
|
||||||
tx: '0xc4491908e3347b05f2394ac7e1006f573fe8cbc490a57cd1dadad70785e95024',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
amount: new BigNumber('200000'),
|
|
||||||
user: '0x93b478148FF792B00076B7EdC89Db1FdE7772079',
|
|
||||||
tx: '0xcc8fba855a0d965044d4cc587701fe9ee9f5863852cede017382ffe02963d9b8',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
amount: new BigNumber('21666.5743'),
|
|
||||||
user: '0xB523235B6c7C74DDB26b10E78bFb2d0Cb63Ae289',
|
|
||||||
tx: '0x8cc5159f3d665dd33a2bdac6e990cf1b65dc18b6b5e37a07b37dd54495a8d33c',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
amount: new BigNumber('200000'),
|
|
||||||
user: '0x7227e17101E6C70F4dAfC7DDB77BB7D83DdfC1C8',
|
|
||||||
tx: '0x0cdef6868bd6b977362396fd06525e1e757e827659c5d75cd512db121947e6f7',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
amount: new BigNumber('137998.56'),
|
|
||||||
user: '0x69eFc5642CfcCB1777bc663433640531F044D1F5',
|
|
||||||
tx: '0xaa9b3b39836a69f760f5d1d2fdba44ad348b27c8f31eb094ad6f779b39d7949c',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
amount: new BigNumber('16249.93'),
|
|
||||||
user: '0x006B59DD3bC838A74476c0F4a33C1565831dA0DD',
|
|
||||||
tx: '0xda9bdc846300600c0d360edcaf4a5ed40fa2586ba7872f2bf68251a669adff0e',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
withdrawals: [],
|
|
||||||
users: [
|
|
||||||
{
|
|
||||||
address: '0xE6CacAE56Cca8dFdB7910b5A13578719D4E57DA0',
|
|
||||||
deposits: [
|
|
||||||
{
|
|
||||||
amount: new BigNumber('187637.95'),
|
|
||||||
user: '0xE6CacAE56Cca8dFdB7910b5A13578719D4E57DA0',
|
|
||||||
tranche_id: 1,
|
|
||||||
tx: '0xc4491908e3347b05f2394ac7e1006f573fe8cbc490a57cd1dadad70785e95024',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
withdrawals: [],
|
|
||||||
total_tokens: new BigNumber('187637.95'),
|
|
||||||
withdrawn_tokens: new BigNumber('0'),
|
|
||||||
remaining_tokens: new BigNumber('187637.95'),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
address: '0x1A71e3ED1996CAbB91bB043f880CE963D601707e',
|
|
||||||
deposits: [
|
|
||||||
{
|
|
||||||
amount: new BigNumber('112323.67'),
|
|
||||||
user: '0x1A71e3ED1996CAbB91bB043f880CE963D601707e',
|
|
||||||
tranche_id: 1,
|
|
||||||
tx: '0xaa378d2d0d4d7b964a675bb19f19c4f7401deec6ce66b1bd98ad5b812026e53e',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
withdrawals: [],
|
|
||||||
total_tokens: new BigNumber('112323.67'),
|
|
||||||
withdrawn_tokens: new BigNumber('0'),
|
|
||||||
remaining_tokens: new BigNumber('112323.67'),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
tranche_id: 2,
|
|
||||||
tranche_start: parseJSON('2022-06-05T00:00:00.000Z'),
|
|
||||||
tranche_end: parseJSON('2023-12-05T00:00:00.000Z'),
|
|
||||||
total_added: new BigNumber('15464357.550320999700000001'),
|
|
||||||
total_removed: new BigNumber('0'),
|
|
||||||
locked_amount: new BigNumber('15464357.550320999700000001'),
|
|
||||||
deposits: [
|
|
||||||
{
|
|
||||||
amount: new BigNumber('1'),
|
|
||||||
user: '0x7fff551249D223f723557a96a0e1a469C79cC934',
|
|
||||||
tx: '0x55fa59d71aac37428a5804442c48da677a4426a4e92447919a8199520ce20f53',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
amount: new BigNumber('100000'),
|
|
||||||
user: '0xe20D4d4fFb165e4b9926467d82d03c0e9ab66D89',
|
|
||||||
tx: '0xabf2cc96c41c8b4f0cff8d8ff7448e241ff83e296a7b7dea79d9d9868f33b7ad',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
amount: new BigNumber('500000'),
|
|
||||||
user: '0x5f01A497e4033E4812ba5D494bCBc2220cd510Ed',
|
|
||||||
tx: '0xe3a1a74378a42eace12c21c24889d8b0da6a3736ca7987720e70f59886caa5a3',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
amount: new BigNumber('59228.95'),
|
|
||||||
user: '0x1d20f66eF3889aa48Bb4Badbbf993dE965BDb029',
|
|
||||||
tx: '0xf31eab593b86aac54f5fa9fe24bb26105ff52386be60bc24617dd362df7c6f15',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
amount: new BigNumber('206374.1211'),
|
|
||||||
user: '0x1b979e8AE3BbbaF96Dd1bbbC0060b360A23f2EBE',
|
|
||||||
tx: '0x2983daa9acf6da5fba0debc2aaaaf47389b92aea0de0c27b20809fb69a63ce69',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
amount: new BigNumber('200000'),
|
|
||||||
user: '0xe45993F39183E148bC35BA02ba8C289111181c0f',
|
|
||||||
tx: '0xbda7b70ab8ac629617e74daaaa5451b04d7830bc0da516e10d533efc2eef1530',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
withdrawals: [
|
|
||||||
{
|
|
||||||
amount: new BigNumber('0'),
|
|
||||||
user: '0x4527F5A12bbbbb7c88c5863F8AB9a708928Fe702',
|
|
||||||
tx: '0xbaa8632cd162265ca46baaaad746ec3d283a474e344727854d962e057380a51',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
users: [
|
|
||||||
{
|
|
||||||
address: '0x7fff551249D223f723557a96a0e1aCCCC79cC934',
|
|
||||||
deposits: [
|
|
||||||
{
|
|
||||||
amount: new BigNumber('1'),
|
|
||||||
user: '0x7fff551249D223f723557a96a0e1aCCCC79cC934',
|
|
||||||
tranche_id: 2,
|
|
||||||
tx: '0x55fa59d71aac37428a0000042c48da677a4426a4e92447919a8199520ce20f53',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
withdrawals: [],
|
|
||||||
total_tokens: new BigNumber('1'),
|
|
||||||
withdrawn_tokens: new BigNumber('0'),
|
|
||||||
remaining_tokens: new BigNumber('1'),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
address: '0xCc5CAFD3daA3bb2c1168521F35d1eBEB6cf7c051',
|
|
||||||
deposits: [
|
|
||||||
{
|
|
||||||
amount: new BigNumber('200000'),
|
|
||||||
user: '0xCc5CAFD3daA3bb2c1168521F35d1eBEB6cf7c051',
|
|
||||||
tranche_id: 2,
|
|
||||||
tx: '0x8168230eb08320a7a874ebeeea20f0def842b8059a2b05a036870e00ca624c88',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
withdrawals: [],
|
|
||||||
total_tokens: new BigNumber('200000'),
|
|
||||||
withdrawn_tokens: new BigNumber('0'),
|
|
||||||
remaining_tokens: new BigNumber('200000'),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
address: '0x9cd59376F896a5F2084232E386A65c17EEA4Fe9f',
|
|
||||||
deposits: [
|
|
||||||
{
|
|
||||||
amount: new BigNumber('200000'),
|
|
||||||
user: '0x9cd59376F896a5F2084232E386A65c17EEA4Fe9f',
|
|
||||||
tranche_id: 2,
|
|
||||||
tx: '0x2eb27449e08a245314faaaaf0d93fafc70733586495f18cf2fb69ef979459efd',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
withdrawals: [],
|
|
||||||
total_tokens: new BigNumber('200000'),
|
|
||||||
withdrawn_tokens: new BigNumber('0'),
|
|
||||||
remaining_tokens: new BigNumber('200000'),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
address: '0xe45993F39183E148bC35BA02ba8aaaa807981caa',
|
|
||||||
deposits: [
|
|
||||||
{
|
|
||||||
amount: new BigNumber('200000'),
|
|
||||||
user: '0xe45993F39183E148bC35BA02ba8aaaa07981caa',
|
|
||||||
tranche_id: 2,
|
|
||||||
tx: '0xbda7b70ab8ac629617e74d33575451b04d7830bc0da516e10d533efc2eef1530',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
withdrawals: [],
|
|
||||||
total_tokens: new BigNumber('200000'),
|
|
||||||
withdrawn_tokens: new BigNumber('0'),
|
|
||||||
remaining_tokens: new BigNumber('200000'),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
tranche_id: 3,
|
|
||||||
tranche_start: parseJSON('2021-11-05T00:00:00.000Z'),
|
|
||||||
tranche_end: parseJSON('2023-05-05T00:00:00.000Z'),
|
|
||||||
total_added: new BigNumber('14597706.0446472999'),
|
|
||||||
total_removed: new BigNumber('0'),
|
|
||||||
locked_amount: new BigNumber('14445316.74229298796336861823365303'),
|
|
||||||
deposits: [
|
|
||||||
{
|
|
||||||
amount: new BigNumber('129284.449'),
|
|
||||||
user: '0x26100B2C8168Cb0A6c869a5698265086A3Dfeaaa',
|
|
||||||
tx: '0xcc67a776a2e3b48864470aaa9e0940c1814663b4fde6df60c1a099a636dcae79',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
amount: new BigNumber('1151405.093'),
|
|
||||||
user: '0x777Ec2e2beaB6a63c1E763D0dc4120AF60BEe39F',
|
|
||||||
tx: '0x1237d45a40aacc5dff7f8f69e8a4c0536fd0460b915de576bd3f0fdf5892c0a4',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
amount: new BigNumber('1151073.595'),
|
|
||||||
user: '0x5CD0Ec63687588817044794bF15d4e37991efAB3',
|
|
||||||
tx: '0xb4eaca7d8abeaf7e1d9d28b1f1fa09fc1933af0e11bff4b0120dcef7d2dfc64d',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
amount: new BigNumber('54034.5'),
|
|
||||||
user: '0xc01F2E57554Bb392384feCA6a54c8E3A3Ca94E42',
|
|
||||||
tx: '0xf33289a2a73a65b132accdddd600a8d2c7556c2d80784d5f8d4eea1ecacf93cc',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
amount: new BigNumber('115049.22'),
|
|
||||||
user: '0x01a8055A97b461b58ba8e37cd349721FeAe77A8D',
|
|
||||||
tx: '0xf650c3599b24d01dfa1f3e19b22f870ff8ac8dfac529893f0b22d548c3535eda',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
withdrawals: [
|
|
||||||
{
|
|
||||||
amount: new BigNumber('0'),
|
|
||||||
user: '0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b',
|
|
||||||
tx: '0x1af894d1f9ce5ea79aa52d180fbff5f30b8b456e43b76ca5d7d73366e422ea37',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
users: [
|
|
||||||
{
|
|
||||||
address: '0x26100B2C8168Cb0A6c869a5698265086A3DfeF98',
|
|
||||||
deposits: [
|
|
||||||
{
|
|
||||||
amount: new BigNumber('129284.449'),
|
|
||||||
user: '0x26100B2C8168Cb0A6c869a5698265086A3DfeF98',
|
|
||||||
tranche_id: 3,
|
|
||||||
tx: '0xcc67a776a2e3b48864470eff9e0940c1814663b4fde6df60c1a099a636dcae79',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
withdrawals: [],
|
|
||||||
total_tokens: new BigNumber('129284.449'),
|
|
||||||
withdrawn_tokens: new BigNumber('0'),
|
|
||||||
remaining_tokens: new BigNumber('129284.449'),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
address: '0xd4632B682228Db5f38E2283869AEe8c29ee6Eec8',
|
|
||||||
deposits: [
|
|
||||||
{
|
|
||||||
amount: new BigNumber('44499.2'),
|
|
||||||
user: '0xd4632B682228Db5f38E2283869AEe8c29ee6Eec8',
|
|
||||||
tranche_id: 3,
|
|
||||||
tx: '0x57019840d1ce05e0ef65c45801d6699e5eb1032bd8ad56493594d4866996ea82',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
withdrawals: [],
|
|
||||||
total_tokens: new BigNumber('44499.2'),
|
|
||||||
withdrawn_tokens: new BigNumber('0'),
|
|
||||||
remaining_tokens: new BigNumber('44499.2'),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
address: '0xe2E6F37cb1f1980418012BF69f43910d6Bc73e73',
|
|
||||||
deposits: [
|
|
||||||
{
|
|
||||||
amount: new BigNumber('66748.8'),
|
|
||||||
user: '0xe2E6F37cb1f1980418012BF69f43910d6Bc73e73',
|
|
||||||
tranche_id: 3,
|
|
||||||
tx: '0xd257a3aacd5bdf86cbea0ed3db3697f55dff9092129db6baedacaf00b50af936',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
withdrawals: [],
|
|
||||||
total_tokens: new BigNumber('66748.8'),
|
|
||||||
withdrawn_tokens: new BigNumber('0'),
|
|
||||||
remaining_tokens: new BigNumber('66748.8'),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
address: '0xc01F2E57554Bb392384feCA6a54c8E3A3Ca94E42',
|
|
||||||
deposits: [
|
|
||||||
{
|
|
||||||
amount: new BigNumber('54034.5'),
|
|
||||||
user: '0xc01F2E57554Bb392384feCA6a54c8E3A3Ca94E42',
|
|
||||||
tranche_id: 3,
|
|
||||||
tx: '0xf33289a2a73a65b132accdddd600a8d2c7556c2d80784d5f8d4eea1ecacf93cc',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
withdrawals: [],
|
|
||||||
total_tokens: new BigNumber('54034.5'),
|
|
||||||
withdrawn_tokens: new BigNumber('0'),
|
|
||||||
remaining_tokens: new BigNumber('54034.5'),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
tranche_id: 4,
|
|
||||||
tranche_start: parseJSON('2021-10-05T00:00:00.000Z'),
|
|
||||||
tranche_end: parseJSON('2023-04-05T00:00:00.000Z'),
|
|
||||||
total_added: new BigNumber('5198082.8647159303'),
|
|
||||||
total_removed: new BigNumber('12706.1452878164044708'),
|
|
||||||
locked_amount: new BigNumber('4849328.20502099651595959714823613'),
|
|
||||||
deposits: [
|
|
||||||
{
|
|
||||||
amount: new BigNumber('110499.5291'),
|
|
||||||
user: '0xa8679b60612Fb2e19d68964326CA02dCe6a08D08',
|
|
||||||
tx: '0x9d3432b818054796489848c415af5c523acb16c1540e5865010baf71964c03a7',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
amount: new BigNumber('331498.5873'),
|
|
||||||
user: '0x39fEc2e2beaB6a63c1E763D0dc4120AF60BEe39F',
|
|
||||||
tx: '0xdf5c6e44ef0763e785721802704e5fd186fa3964302a566899027447d0dda57b',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
amount: new BigNumber('27624.032275'),
|
|
||||||
user: '0xF5Fb27b912D987B5b6e02A1B1BE0C1F0740E2c6f',
|
|
||||||
tx: '0x1860d39ae3e9ad710da9e2a9bf9606eedc1b176fca673473d6854ea91ed8beb5',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
amount: new BigNumber('73666.3527333333'),
|
|
||||||
user: '0x2895059cB5a492BEd58D1fB22713006EfaD465eA',
|
|
||||||
tx: '0x260619e2129cc58ae03f6b4ecfc5a6eeab29b5998de69875accb3cb945beed04',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
withdrawals: [
|
|
||||||
{
|
|
||||||
amount: new BigNumber('1290.014571009862016'),
|
|
||||||
user: '0xBc934494675a6ceB639B9EfEe5b9C0f017D35a75',
|
|
||||||
tx: '0x637c3648ce941a77e08e741f981806a5d56275db6d280f041902386ae8567d06',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
amount: new BigNumber('5197.621879605058623'),
|
|
||||||
user: '0xafa64cCa337eFEE0AD827F6C2684e69275226e90',
|
|
||||||
tx: '0xe8b8c1a38d3ae809dcaae54a11adeeba0f46be03924e91d8f251f3f2d48c3553',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
amount: new BigNumber('376.2625308599198808'),
|
|
||||||
user: '0x1dD2718fd01d05C9F50Fce8Bb723A4C7483A1E15',
|
|
||||||
tx: '0x78af737235f1123bb1c6a607a0b4b7a3c5ed6859a4e8912f45bb7c812724b1de',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
amount: new BigNumber('4162.301372742020875'),
|
|
||||||
user: '0xBc934494675a6ceB639B9EfEe5b9C0f017D35a75',
|
|
||||||
tx: '0x85c7d9979f0e3a3660dc5952732eaf9414f7c28a1c00a9a10f449843f91d85e0',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
amount: new BigNumber('1679.944933599543076'),
|
|
||||||
user: '0x9058e12e2F32cB1cD4D3123359963D77786477FC',
|
|
||||||
tx: '0xd92083f2e90e84cb70ef27ac410ed1144200c41b1714fb54d29f5f23ca086ecb',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
users: [
|
|
||||||
{
|
|
||||||
address: '0xa8679b60612Fb2e19d68964326CA02dCe6a08D08',
|
|
||||||
deposits: [
|
|
||||||
{
|
|
||||||
amount: new BigNumber('110499.5291'),
|
|
||||||
user: '0xa8679b60612Fb2e19d68964326CA02dCe6a08D08',
|
|
||||||
tranche_id: 4,
|
|
||||||
tx: '0x9d3432b818054796489848c415af5c523acb16c1540e5865010baf71964c03a7',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
withdrawals: [],
|
|
||||||
total_tokens: new BigNumber('110499.5291'),
|
|
||||||
withdrawn_tokens: new BigNumber('0'),
|
|
||||||
remaining_tokens: new BigNumber('110499.5291'),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
address: '0x8767d65677Cabaa2050b764AEf40610f2f9796F5',
|
|
||||||
deposits: [
|
|
||||||
{
|
|
||||||
amount: new BigNumber('1104995.291'),
|
|
||||||
user: '0x8767d65677Cabaa2050b764AEf40610f2f9796F5',
|
|
||||||
tranche_id: 4,
|
|
||||||
tx: '0xc6298f52c173a837abd051ed810b01eb5731be307376b73df6e31b4de39d0122',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
withdrawals: [],
|
|
||||||
total_tokens: new BigNumber('1104995.291'),
|
|
||||||
withdrawn_tokens: new BigNumber('0'),
|
|
||||||
remaining_tokens: new BigNumber('1104995.291'),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
address: '0x91715128a71c9C734CDC20E5EdaaeA02E72e422E',
|
|
||||||
deposits: [
|
|
||||||
{
|
|
||||||
amount: new BigNumber('165749.29365'),
|
|
||||||
user: '0x91715128a71c9C734CDC20E5EdEEeA02E72e422E',
|
|
||||||
tranche_id: 4,
|
|
||||||
tx: '0xf828cea685a0689f27446f02d3376c3afa4398182d3b5bf1c81e949f5965d1c1',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
withdrawals: [],
|
|
||||||
total_tokens: new BigNumber('165749.29365'),
|
|
||||||
withdrawn_tokens: new BigNumber('0'),
|
|
||||||
remaining_tokens: new BigNumber('165749.29365'),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
address: '0x2895059cB5a492BEd58D1fB22713006EfaD465eA',
|
|
||||||
deposits: [
|
|
||||||
{
|
|
||||||
amount: new BigNumber('73666.3527333333'),
|
|
||||||
user: '0x2895059cB5a492BEd58D1fB22713006EfaD465eA',
|
|
||||||
tranche_id: 4,
|
|
||||||
tx: '0x260619e2129cc58ae03f6b4ecfc5a6eeab29b5998de69875accb3cb945beed04',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
withdrawals: [],
|
|
||||||
total_tokens: new BigNumber('73666.3527333333'),
|
|
||||||
withdrawn_tokens: new BigNumber('0'),
|
|
||||||
remaining_tokens: new BigNumber('73666.3527333333'),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
tranche_id: 23,
|
|
||||||
tranche_start: parseJSON('2022-04-30T00:00:00.000Z'),
|
|
||||||
tranche_end: parseJSON('2022-04-30T00:00:00.000Z'),
|
|
||||||
total_added: new BigNumber('10833.29'),
|
|
||||||
total_removed: new BigNumber('0'),
|
|
||||||
locked_amount: new BigNumber('10833.29'),
|
|
||||||
deposits: [
|
|
||||||
{
|
|
||||||
amount: new BigNumber('10833.29'),
|
|
||||||
user: '0xF3359E5B89f7804c8c9283781Aaaa33BBd979c9D',
|
|
||||||
tx: '0x65f904ef34d6992b52f449a709d7a24411a501fd07f90aaa9255eacc994bc229',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
withdrawals: [],
|
|
||||||
users: [
|
|
||||||
{
|
|
||||||
address: '0xF3359E5B89f7804c8c9283781Aaaa33BBd979c9D',
|
|
||||||
deposits: [
|
|
||||||
{
|
|
||||||
amount: new BigNumber('10833.29'),
|
|
||||||
user: '0xF3359E5B89f7804c8c9283781Aaaa33BBd979c9D',
|
|
||||||
tranche_id: 23,
|
|
||||||
tx: '0x65f904ef34d6992b52f449a709d7a24411a501fd07f90aaa9255eacc994bc229',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
withdrawals: [],
|
|
||||||
total_tokens: new BigNumber('10833.29'),
|
|
||||||
withdrawn_tokens: new BigNumber('0'),
|
|
||||||
remaining_tokens: new BigNumber('10833.29'),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
tranche_id: 24,
|
|
||||||
tranche_start: parseJSON('2022-09-26T00:00:00.000Z'),
|
|
||||||
tranche_end: parseJSON('2022-09-26T00:00:00.000Z'),
|
|
||||||
total_added: new BigNumber('16249.93'),
|
|
||||||
total_removed: new BigNumber('0'),
|
|
||||||
locked_amount: new BigNumber('16249.93'),
|
|
||||||
deposits: [
|
|
||||||
{
|
|
||||||
amount: new BigNumber('16249.93'),
|
|
||||||
user: '0xcE96670971ec2E1E79D0d96688adbA2FfD6F6C7f',
|
|
||||||
tx: '0x3dbd991b7914986505d89a7c1562278dffffa2f5f444bdbf5d6bbd838e3d8d5d',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
withdrawals: [],
|
|
||||||
users: [
|
|
||||||
{
|
|
||||||
address: '0xcE96670971ec2E1E79D0d96688adbA2FfD6F6C7f',
|
|
||||||
deposits: [
|
|
||||||
{
|
|
||||||
amount: new BigNumber('16249.93'),
|
|
||||||
user: '0xcE96670971ec2E1E79D0d96688adbA2FfD6F6C7f',
|
|
||||||
tranche_id: 24,
|
|
||||||
tx: '0x3dbd991b7914986505d89a7c1562278dffffa2f5f444bdbf5d6bbd838e3d8d5d',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
withdrawals: [],
|
|
||||||
total_tokens: new BigNumber('16249.93'),
|
|
||||||
withdrawn_tokens: new BigNumber('0'),
|
|
||||||
remaining_tokens: new BigNumber('16249.93'),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
tranche_id: 25,
|
|
||||||
tranche_start: parseJSON('2022-02-10T00:00:00.000Z'),
|
|
||||||
tranche_end: parseJSON('2023-04-05T00:00:00.000Z'),
|
|
||||||
total_added: new BigNumber('0'),
|
|
||||||
total_removed: new BigNumber('0'),
|
|
||||||
locked_amount: new BigNumber('0'),
|
|
||||||
deposits: [],
|
|
||||||
withdrawals: [],
|
|
||||||
users: [],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
tranche_id: 26,
|
|
||||||
tranche_start: parseJSON('2022-02-04T00:00:00.000Z'),
|
|
||||||
tranche_end: parseJSON('2023-04-05T00:00:00.000Z'),
|
|
||||||
total_added: new BigNumber('135173.4239508'),
|
|
||||||
total_removed: new BigNumber('0'),
|
|
||||||
locked_amount: new BigNumber('135173.4239508'),
|
|
||||||
deposits: [
|
|
||||||
{
|
|
||||||
amount: new BigNumber('135173.4239508'),
|
|
||||||
user: '0xc90eA4d8D214D548221EE3622a8BE1D61f7077A2',
|
|
||||||
tx: '0x123fb1e293a8246b92d85a47c8d33def9fb6468c7cbb70f1754d78914b12dbf8',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
withdrawals: [],
|
|
||||||
users: [
|
|
||||||
{
|
|
||||||
address: '0x222eA4d8D214D548221EE3622a8BE1D61f7077A2',
|
|
||||||
deposits: [
|
|
||||||
{
|
|
||||||
amount: new BigNumber('135173.4239508'),
|
|
||||||
user: '0x222eA4d8D214D548221EE3622a8BE1D61f7077A2',
|
|
||||||
tranche_id: 26,
|
|
||||||
tx: '0x9fafb1e293a8246b92d85a47c8d33def9fb6468c7cbb70f1754d78914b12dbf8',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
withdrawals: [],
|
|
||||||
total_tokens: new BigNumber('135173.4239508'),
|
|
||||||
withdrawn_tokens: new BigNumber('0'),
|
|
||||||
remaining_tokens: new BigNumber('135173.4239508'),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
tranche_id: 27,
|
|
||||||
tranche_start: parseJSON('2022-05-09T00:00:00.000Z'),
|
|
||||||
tranche_end: parseJSON('2023-04-05T00:00:00.000Z'),
|
|
||||||
total_added: new BigNumber('32499.86'),
|
|
||||||
total_removed: new BigNumber('0'),
|
|
||||||
locked_amount: new BigNumber('32499.86'),
|
|
||||||
deposits: [
|
|
||||||
{
|
|
||||||
amount: new BigNumber('32499.86'),
|
|
||||||
user: '0x1E7c4E57A1dc4dD4bBE81b833e3E437f69619DaB',
|
|
||||||
tx: '0x25a3dd4852ce8ac1c15fe42123cfab14e4bf8a5c1cb97167cb4d6fe20bd319ae',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
withdrawals: [],
|
|
||||||
users: [
|
|
||||||
{
|
|
||||||
address: '0x3E7c4E57A1dc4dD4bBE81bbEFBe3Eaaaf69619Da9',
|
|
||||||
deposits: [
|
|
||||||
{
|
|
||||||
amount: new BigNumber('32499.86'),
|
|
||||||
user: '0x3E7c4E57A1dc4dD4bBE81bbEFBe3Eaaaf69619Da9',
|
|
||||||
tranche_id: 27,
|
|
||||||
tx: '0x75a3dd4852ce8ac1c15fe42ff6cfab1455bf8a5c1cb97167cb4d6fe20bd319ae',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
withdrawals: [],
|
|
||||||
total_tokens: new BigNumber('32499.86'),
|
|
||||||
withdrawn_tokens: new BigNumber('0'),
|
|
||||||
remaining_tokens: new BigNumber('32499.86'),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
tranche_id: 28,
|
|
||||||
tranche_start: parseJSON('2022-04-30T00:00:00.000Z'),
|
|
||||||
tranche_end: parseJSON('2023-04-05T00:00:00.000Z'),
|
|
||||||
total_added: new BigNumber('10833.29'),
|
|
||||||
total_removed: new BigNumber('0'),
|
|
||||||
locked_amount: new BigNumber('10833.29'),
|
|
||||||
deposits: [
|
|
||||||
{
|
|
||||||
amount: new BigNumber('10833.29'),
|
|
||||||
user: '0xF3359E5B89f7804c8c9283781Aaa133BBd979c9D',
|
|
||||||
tx: '0x166d235eff44e7bcc63597c0d6e698552e4440fe90ec7cf07a1d510c275cf3e0',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
withdrawals: [],
|
|
||||||
users: [
|
|
||||||
{
|
|
||||||
address: '0x12349E5B89f7804c8c9283781A23133BBd979c22',
|
|
||||||
deposits: [
|
|
||||||
{
|
|
||||||
amount: new BigNumber('10833.29'),
|
|
||||||
user: '0x12349E5B89f7804c8c9283781A23133BBd979c22',
|
|
||||||
tranche_id: 28,
|
|
||||||
tx: '0x166d235eff44e7baa6359712345698552e6150fe90ec7cf07a1d510c275cf3e0',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
withdrawals: [],
|
|
||||||
total_tokens: new BigNumber('10833.29'),
|
|
||||||
withdrawn_tokens: new BigNumber('0'),
|
|
||||||
remaining_tokens: new BigNumber('10833.29'),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
tranche_id: 29,
|
|
||||||
tranche_start: parseJSON('2022-09-26T00:00:00.000Z'),
|
|
||||||
tranche_end: parseJSON('2023-04-05T00:00:00.000Z'),
|
|
||||||
total_added: new BigNumber('16249.93'),
|
|
||||||
total_removed: new BigNumber('0'),
|
|
||||||
locked_amount: new BigNumber('16249.93'),
|
|
||||||
deposits: [
|
|
||||||
{
|
|
||||||
amount: new BigNumber('16249.93'),
|
|
||||||
user: '0xcE96670971ec2E1E79D0d12388adbA2FfD6F6C7f',
|
|
||||||
tx: '0xa770ab2d05e6c81be46b73ac2326e81a111da4ce55a2d8544bd95b48ad530674',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
withdrawals: [],
|
|
||||||
users: [
|
|
||||||
{
|
|
||||||
address: '0xcE96670971ec2E1E79D0d96688adbA2FfD6F6C7f',
|
|
||||||
deposits: [
|
|
||||||
{
|
|
||||||
amount: new BigNumber('16249.93'),
|
|
||||||
user: '0xcE96670971ec212379D0d12388adbA2Ffc6F6C7f',
|
|
||||||
tranche_id: 29,
|
|
||||||
tx: '0xa220ab2d05e6c81be12373ac2326e81a912da4ce55a2d8544bd95b48ad530674',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
withdrawals: [],
|
|
||||||
total_tokens: new BigNumber('16249.93'),
|
|
||||||
withdrawn_tokens: new BigNumber('0'),
|
|
||||||
remaining_tokens: new BigNumber('16249.93'),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
tranche_id: 30,
|
|
||||||
tranche_start: parseJSON('2021-11-01T00:00:00.000Z'),
|
|
||||||
tranche_end: parseJSON('2022-05-01T00:00:00.000Z'),
|
|
||||||
total_added: new BigNumber('0'),
|
|
||||||
total_removed: new BigNumber('0'),
|
|
||||||
locked_amount: new BigNumber('0'),
|
|
||||||
deposits: [],
|
|
||||||
withdrawals: [],
|
|
||||||
users: [],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
tranche_id: 31,
|
|
||||||
tranche_start: parseJSON('2022-02-01T00:00:00.000Z'),
|
|
||||||
tranche_end: parseJSON('2022-08-01T00:00:00.000Z'),
|
|
||||||
total_added: new BigNumber('0'),
|
|
||||||
total_removed: new BigNumber('0'),
|
|
||||||
locked_amount: new BigNumber('0'),
|
|
||||||
deposits: [],
|
|
||||||
withdrawals: [],
|
|
||||||
users: [],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
tranche_id: 32,
|
|
||||||
tranche_start: parseJSON('2022-05-01T00:00:00.000Z'),
|
|
||||||
tranche_end: parseJSON('2022-11-01T00:00:00.000Z'),
|
|
||||||
total_added: new BigNumber('0'),
|
|
||||||
total_removed: new BigNumber('0'),
|
|
||||||
locked_amount: new BigNumber('0'),
|
|
||||||
deposits: [],
|
|
||||||
withdrawals: [],
|
|
||||||
users: [],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
tranche_id: 33,
|
|
||||||
tranche_start: parseJSON('2022-11-01T00:00:00.000Z'),
|
|
||||||
tranche_end: parseJSON('2023-05-01T00:00:00.000Z'),
|
|
||||||
total_added: new BigNumber('0'),
|
|
||||||
total_removed: new BigNumber('0'),
|
|
||||||
locked_amount: new BigNumber('0'),
|
|
||||||
deposits: [],
|
|
||||||
withdrawals: [],
|
|
||||||
users: [],
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
export default json;
|
|
@ -1,21 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import mock from './tranches-mock';
|
|
||||||
import type { Tranche } from '@vegaprotocol/smart-contracts';
|
|
||||||
|
|
||||||
export function useTranches() {
|
|
||||||
const [tranches, setTranches] = React.useState<Tranche[] | null>(null);
|
|
||||||
const [error, setError] = React.useState<string | null>(null);
|
|
||||||
|
|
||||||
React.useEffect(() => {
|
|
||||||
const run = async () => {
|
|
||||||
try {
|
|
||||||
setTranches(mock);
|
|
||||||
} catch (err) {
|
|
||||||
setError((err as Error).message);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
run();
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return { tranches, error };
|
|
||||||
}
|
|
41
apps/token/src/hooks/use-get-user-balances.ts
Normal file
41
apps/token/src/hooks/use-get-user-balances.ts
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
import { useCallback } from 'react';
|
||||||
|
import * as Sentry from '@sentry/react';
|
||||||
|
import { toBigNum } from '@vegaprotocol/react-helpers';
|
||||||
|
import { useContracts } from '../contexts/contracts/contracts-context';
|
||||||
|
import { useAppState } from '../contexts/app-state/app-state-context';
|
||||||
|
import { useEthereumConfig } from '@vegaprotocol/web3';
|
||||||
|
|
||||||
|
export const useGetUserBalances = (account: string | undefined) => {
|
||||||
|
const { token, vesting } = useContracts();
|
||||||
|
const { config } = useEthereumConfig();
|
||||||
|
const {
|
||||||
|
appState: { decimals },
|
||||||
|
} = useAppState();
|
||||||
|
return useCallback(async () => {
|
||||||
|
if (!account || !config) return;
|
||||||
|
try {
|
||||||
|
const [b, w, stats, a] = await Promise.all([
|
||||||
|
vesting.user_total_all_tranches(account),
|
||||||
|
token.balanceOf(account),
|
||||||
|
vesting.user_stats(account),
|
||||||
|
token.allowance(account, config.staking_bridge_contract.address),
|
||||||
|
]);
|
||||||
|
|
||||||
|
const balance = toBigNum(b, decimals);
|
||||||
|
const walletBalance = toBigNum(w, decimals);
|
||||||
|
const lien = toBigNum(stats.lien, decimals);
|
||||||
|
const allowance = toBigNum(a, decimals);
|
||||||
|
|
||||||
|
return {
|
||||||
|
balanceFormatted: balance,
|
||||||
|
walletBalance,
|
||||||
|
lien,
|
||||||
|
allowance,
|
||||||
|
balance,
|
||||||
|
};
|
||||||
|
} catch (err) {
|
||||||
|
Sentry.captureException(err);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}, [account, config, decimals, token, vesting]);
|
||||||
|
};
|
@ -1,70 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import * as Sentry from '@sentry/react';
|
|
||||||
import type { TokenVesting } from '@vegaprotocol/smart-contracts';
|
|
||||||
|
|
||||||
import {
|
|
||||||
AppStateActionType,
|
|
||||||
useAppState,
|
|
||||||
} from '../contexts/app-state/app-state-context';
|
|
||||||
import { BigNumber } from '../lib/bignumber';
|
|
||||||
import { useTranches } from './use-tranches';
|
|
||||||
import { toBigNum } from '@vegaprotocol/react-helpers';
|
|
||||||
import { useBalances } from '../lib/balances/balances-store';
|
|
||||||
|
|
||||||
export const useGetUserTrancheBalances = (
|
|
||||||
address: string,
|
|
||||||
vesting: TokenVesting
|
|
||||||
) => {
|
|
||||||
const {
|
|
||||||
appState: { decimals },
|
|
||||||
appDispatch,
|
|
||||||
} = useAppState();
|
|
||||||
const { setTranchesBalances } = useBalances();
|
|
||||||
const { tranches } = useTranches();
|
|
||||||
return React.useCallback(async () => {
|
|
||||||
appDispatch({
|
|
||||||
type: AppStateActionType.SET_TRANCHE_ERROR,
|
|
||||||
error: null,
|
|
||||||
});
|
|
||||||
try {
|
|
||||||
if (!tranches) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const userTranches = tranches?.filter((t) =>
|
|
||||||
t.users.some(
|
|
||||||
({ address: a }) =>
|
|
||||||
a && address && a.toLowerCase() === address.toLowerCase()
|
|
||||||
)
|
|
||||||
);
|
|
||||||
const trancheIds = [0, ...userTranches.map((t) => t.tranche_id)];
|
|
||||||
const promises = trancheIds.map(async (tId) => {
|
|
||||||
const [t, v] = await Promise.all([
|
|
||||||
vesting.get_tranche_balance(address, tId),
|
|
||||||
vesting.get_vested_for_tranche(address, tId),
|
|
||||||
]);
|
|
||||||
|
|
||||||
const total = toBigNum(t, decimals);
|
|
||||||
const vested = toBigNum(v, decimals);
|
|
||||||
|
|
||||||
return {
|
|
||||||
id: tId,
|
|
||||||
locked: tId === 0 ? total : total.minus(vested),
|
|
||||||
vested: tId === 0 ? new BigNumber(0) : vested,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
const trancheBalances = await Promise.all(promises);
|
|
||||||
setTranchesBalances(trancheBalances);
|
|
||||||
appDispatch({
|
|
||||||
type: AppStateActionType.SET_TRANCHE_DATA,
|
|
||||||
tranches,
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
Sentry.captureException(e);
|
|
||||||
appDispatch({
|
|
||||||
type: AppStateActionType.SET_TRANCHE_ERROR,
|
|
||||||
error: e as Error,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, [appDispatch, tranches, setTranchesBalances, address, vesting, decimals]);
|
|
||||||
};
|
|
@ -1,70 +0,0 @@
|
|||||||
import { useFetch } from '@vegaprotocol/react-helpers';
|
|
||||||
import type { Tranche } from '@vegaprotocol/smart-contracts';
|
|
||||||
import React, { useEffect } from 'react';
|
|
||||||
import type { Networks } from '@vegaprotocol/environment';
|
|
||||||
import { useEnvironment } from '@vegaprotocol/environment';
|
|
||||||
|
|
||||||
import { BigNumber } from '../lib/bignumber';
|
|
||||||
|
|
||||||
const TRANCHES_URLS: { [N in Networks]: string } = {
|
|
||||||
MAINNET: 'https://static.vega.xyz/assets/mainnet-tranches.json',
|
|
||||||
MIRROR: 'https://static.vega.xyz/assets/mirror-tranches.json',
|
|
||||||
TESTNET: 'https://static.vega.xyz/assets/testnet-tranches.json',
|
|
||||||
SANDBOX: 'https://static.vega.xyz/assets/sandbox-tranches.json',
|
|
||||||
STAGNET1: 'https://static.vega.xyz/assets/stagnet1-tranches.json',
|
|
||||||
STAGNET3: 'https://static.vega.xyz/assets/stagnet3-tranches.json',
|
|
||||||
DEVNET: 'https://static.vega.xyz/assets/devnet-tranches.json',
|
|
||||||
CUSTOM: 'https://static.vega.xyz/assets/testnet-tranches.json',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function useTranches() {
|
|
||||||
const { VEGA_ENV } = useEnvironment();
|
|
||||||
const [tranches, setTranches] = React.useState<Tranche[] | null>(null);
|
|
||||||
const url = React.useMemo(() => TRANCHES_URLS[VEGA_ENV], [VEGA_ENV]);
|
|
||||||
const {
|
|
||||||
state: { data, loading, error },
|
|
||||||
} = useFetch<Tranche[] | null>(url);
|
|
||||||
useEffect(() => {
|
|
||||||
const processedTrances = data
|
|
||||||
?.map((t) => ({
|
|
||||||
...t,
|
|
||||||
tranche_start: new Date(t.tranche_start),
|
|
||||||
tranche_end: new Date(t.tranche_end),
|
|
||||||
total_added: new BigNumber(t.total_added),
|
|
||||||
total_removed: new BigNumber(t.total_removed),
|
|
||||||
locked_amount: new BigNumber(t.locked_amount),
|
|
||||||
deposits: t.deposits.map((d) => ({
|
|
||||||
...d,
|
|
||||||
amount: new BigNumber(d.amount),
|
|
||||||
})),
|
|
||||||
withdrawals: t.withdrawals.map((w) => ({
|
|
||||||
...w,
|
|
||||||
amount: new BigNumber(w.amount),
|
|
||||||
})),
|
|
||||||
users: t.users.map((u) => ({
|
|
||||||
...u,
|
|
||||||
// @ts-ignore - types are incorrect in the SDK lib
|
|
||||||
deposits: u.deposits.map((d) => ({
|
|
||||||
...d,
|
|
||||||
amount: new BigNumber(d.amount),
|
|
||||||
})),
|
|
||||||
// @ts-ignore - types are incorrect in the SDK lib
|
|
||||||
withdrawals: u.withdrawals.map((w) => ({
|
|
||||||
...w,
|
|
||||||
amount: new BigNumber(w.amount),
|
|
||||||
})),
|
|
||||||
total_tokens: new BigNumber(u.total_tokens),
|
|
||||||
withdrawn_tokens: new BigNumber(u.withdrawn_tokens),
|
|
||||||
remaining_tokens: new BigNumber(u.remaining_tokens),
|
|
||||||
})),
|
|
||||||
}))
|
|
||||||
.sort((a: Tranche, b: Tranche) => a.tranche_id - b.tranche_id);
|
|
||||||
setTranches(processedTrances ? processedTrances : null);
|
|
||||||
}, [data]);
|
|
||||||
|
|
||||||
return {
|
|
||||||
tranches,
|
|
||||||
loading,
|
|
||||||
error,
|
|
||||||
};
|
|
||||||
}
|
|
@ -1,21 +0,0 @@
|
|||||||
import type { Tranche } from '@vegaprotocol/smart-contracts';
|
|
||||||
|
|
||||||
import { BigNumber } from '../bignumber';
|
|
||||||
|
|
||||||
export function generateTranche(id: number): Tranche {
|
|
||||||
return {
|
|
||||||
tranche_id: id,
|
|
||||||
tranche_start: new Date(),
|
|
||||||
tranche_end: new Date(),
|
|
||||||
total_added: new BigNumber(0),
|
|
||||||
total_removed: new BigNumber(0),
|
|
||||||
locked_amount: new BigNumber(0),
|
|
||||||
deposits: [],
|
|
||||||
withdrawals: [],
|
|
||||||
users: [],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function generateTranches(count = 1) {
|
|
||||||
return new Array(count).fill(null).map((_, i) => generateTranche(i));
|
|
||||||
}
|
|
@ -1,6 +1,11 @@
|
|||||||
import BigNumber from 'bignumber.js';
|
import BigNumber from 'bignumber.js';
|
||||||
import { create } from 'zustand';
|
import { create } from 'zustand';
|
||||||
import type { UserTrancheBalance } from '../../contexts/app-state/app-state-context';
|
|
||||||
|
interface UserTrancheBalance {
|
||||||
|
id: number;
|
||||||
|
locked: BigNumber;
|
||||||
|
vested: BigNumber;
|
||||||
|
}
|
||||||
|
|
||||||
export interface AssociationBreakdown {
|
export interface AssociationBreakdown {
|
||||||
stakingAssociations: { [vegaKey: string]: BigNumber };
|
stakingAssociations: { [vegaKey: string]: BigNumber };
|
||||||
@ -13,8 +18,8 @@ export type BalancesStore = {
|
|||||||
balanceFormatted: BigNumber;
|
balanceFormatted: BigNumber;
|
||||||
totalVestedBalance: BigNumber;
|
totalVestedBalance: BigNumber;
|
||||||
totalLockedBalance: BigNumber;
|
totalLockedBalance: BigNumber;
|
||||||
walletBalance: BigNumber;
|
|
||||||
trancheBalances: UserTrancheBalance[];
|
trancheBalances: UserTrancheBalance[];
|
||||||
|
walletBalance: BigNumber;
|
||||||
lien: BigNumber;
|
lien: BigNumber;
|
||||||
walletAssociatedBalance: BigNumber;
|
walletAssociatedBalance: BigNumber;
|
||||||
vestingAssociatedBalance: BigNumber;
|
vestingAssociatedBalance: BigNumber;
|
||||||
@ -38,8 +43,8 @@ export const useBalances = create<BalancesStore>((set) => ({
|
|||||||
stakingAssociations: {},
|
stakingAssociations: {},
|
||||||
vestingAssociations: {},
|
vestingAssociations: {},
|
||||||
},
|
},
|
||||||
trancheBalances: [],
|
|
||||||
allowance: new BigNumber(0),
|
allowance: new BigNumber(0),
|
||||||
|
trancheBalances: [],
|
||||||
totalVestedBalance: new BigNumber(0),
|
totalVestedBalance: new BigNumber(0),
|
||||||
totalLockedBalance: new BigNumber(0),
|
totalLockedBalance: new BigNumber(0),
|
||||||
balanceFormatted: new BigNumber(0),
|
balanceFormatted: new BigNumber(0),
|
80
apps/token/src/lib/tranches/tranches-store.tsx
Normal file
80
apps/token/src/lib/tranches/tranches-store.tsx
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
import { toBigNum } from '@vegaprotocol/react-helpers';
|
||||||
|
import type { TrancheServiceResponse } from '@vegaprotocol/smart-contracts';
|
||||||
|
import type BigNumber from 'bignumber.js';
|
||||||
|
import create from 'zustand';
|
||||||
|
import { ENV } from '../../config';
|
||||||
|
|
||||||
|
export interface Tranche {
|
||||||
|
tranche_id: number;
|
||||||
|
tranche_start: Date;
|
||||||
|
tranche_end: Date;
|
||||||
|
total_added: BigNumber;
|
||||||
|
total_removed: BigNumber;
|
||||||
|
locked_amount: BigNumber;
|
||||||
|
users: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
const URL = `${ENV.tranchesServiceUrl}/tranches/stats`;
|
||||||
|
|
||||||
|
export interface UserTrancheBalance {
|
||||||
|
/** ID of tranche */
|
||||||
|
id: number;
|
||||||
|
|
||||||
|
/** Users vesting tokens on tranche */
|
||||||
|
locked: BigNumber;
|
||||||
|
|
||||||
|
/** Users vested tokens on tranche */
|
||||||
|
vested: BigNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type TranchesStore = {
|
||||||
|
tranches: Tranche[] | null;
|
||||||
|
loading: boolean;
|
||||||
|
error: Error | null;
|
||||||
|
getTranches: (decimals: number) => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
const secondsToDate = (seconds: number) => new Date(seconds * 1000);
|
||||||
|
|
||||||
|
export const useTranches = create<TranchesStore>((set) => ({
|
||||||
|
tranches: null,
|
||||||
|
loading: false,
|
||||||
|
error: null,
|
||||||
|
getTranches: async (decimals: number) => {
|
||||||
|
set({ loading: true, error: null });
|
||||||
|
try {
|
||||||
|
const res = await fetch(URL);
|
||||||
|
const data = (await res.json()) as TrancheServiceResponse;
|
||||||
|
const now = Math.round(Date.now() / 1000);
|
||||||
|
const tranches = Object.values(data.tranches)
|
||||||
|
?.map((t) => {
|
||||||
|
const tranche_progress =
|
||||||
|
t.duration !== 0 ? (now - t.cliff_start) / t.duration : 0;
|
||||||
|
const lockedDecimal = tranche_progress < 0 ? 1 : 1 - tranche_progress;
|
||||||
|
return {
|
||||||
|
tranche_id: t.tranche_id,
|
||||||
|
tranche_start: secondsToDate(t.cliff_start),
|
||||||
|
tranche_end: secondsToDate(t.cliff_start + t.duration),
|
||||||
|
total_added: toBigNum(t.initial_balance, decimals),
|
||||||
|
total_removed: toBigNum(t.initial_balance, decimals).minus(
|
||||||
|
toBigNum(t.current_balance, decimals)
|
||||||
|
),
|
||||||
|
locked_amount: toBigNum(t.initial_balance, decimals).times(
|
||||||
|
lockedDecimal
|
||||||
|
),
|
||||||
|
users: t.users,
|
||||||
|
};
|
||||||
|
})
|
||||||
|
.sort((a, b) => a.tranche_id - b.tranche_id);
|
||||||
|
set({
|
||||||
|
tranches,
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
set({ error: e as unknown as Error });
|
||||||
|
} finally {
|
||||||
|
set({
|
||||||
|
loading: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}));
|
@ -4,7 +4,6 @@ import { format } from 'date-fns';
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Trans, useTranslation } from 'react-i18next';
|
import { Trans, useTranslation } from 'react-i18next';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import type { Tranche } from '@vegaprotocol/smart-contracts';
|
|
||||||
|
|
||||||
import { KeyValueTable, KeyValueTableRow } from '@vegaprotocol/ui-toolkit';
|
import { KeyValueTable, KeyValueTableRow } from '@vegaprotocol/ui-toolkit';
|
||||||
import { useContracts } from '../../contexts/contracts/contracts-context';
|
import { useContracts } from '../../contexts/contracts/contracts-context';
|
||||||
@ -22,6 +21,7 @@ import { TrancheNotFound } from './tranche-not-found';
|
|||||||
import { UntargetedClaim } from './untargeted-claim';
|
import { UntargetedClaim } from './untargeted-claim';
|
||||||
import { Verifying } from './verifying';
|
import { Verifying } from './verifying';
|
||||||
import type { ClaimAction, ClaimState } from './claim-reducer';
|
import type { ClaimAction, ClaimState } from './claim-reducer';
|
||||||
|
import type { Tranche } from '../../lib/tranches/tranches-store';
|
||||||
|
|
||||||
interface ClaimFlowProps {
|
interface ClaimFlowProps {
|
||||||
state: ClaimState;
|
state: ClaimState;
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { format } from 'date-fns';
|
import { format } from 'date-fns';
|
||||||
import type { Tranche } from '@vegaprotocol/smart-contracts';
|
|
||||||
|
|
||||||
import { DATE_FORMAT_LONG } from '../../lib/date-formats';
|
import { DATE_FORMAT_LONG } from '../../lib/date-formats';
|
||||||
|
import type { Tranche } from '../../lib/tranches/tranches-store';
|
||||||
|
|
||||||
interface ClaimInfoProps {
|
interface ClaimInfoProps {
|
||||||
tranche: Tranche;
|
tranche: Tranche;
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { useAppState } from '../../contexts/app-state/app-state-context';
|
import { useAppState } from '../../contexts/app-state/app-state-context';
|
||||||
import { useContracts } from '../../contexts/contracts/contracts-context';
|
|
||||||
import { useGetUserTrancheBalances } from '../../hooks/use-get-user-tranche-balances';
|
|
||||||
import { useRefreshBalances } from '../../hooks/use-refresh-balances';
|
import { useRefreshBalances } from '../../hooks/use-refresh-balances';
|
||||||
import { useSearchParams } from '../../hooks/use-search-params';
|
import { useSearchParams } from '../../hooks/use-search-params';
|
||||||
import { ClaimError } from './claim-error';
|
import { ClaimError } from './claim-error';
|
||||||
@ -13,7 +11,7 @@ import {
|
|||||||
initialClaimState,
|
initialClaimState,
|
||||||
} from './claim-reducer';
|
} from './claim-reducer';
|
||||||
|
|
||||||
import type { Tranche } from '@vegaprotocol/smart-contracts';
|
import type { Tranche } from '../../lib/tranches/tranches-store';
|
||||||
|
|
||||||
const Claim = ({
|
const Claim = ({
|
||||||
address,
|
address,
|
||||||
@ -23,10 +21,8 @@ const Claim = ({
|
|||||||
tranches: Tranche[];
|
tranches: Tranche[];
|
||||||
}) => {
|
}) => {
|
||||||
const params = useSearchParams();
|
const params = useSearchParams();
|
||||||
const { vesting } = useContracts();
|
|
||||||
const { appState } = useAppState();
|
const { appState } = useAppState();
|
||||||
const [state, dispatch] = React.useReducer(claimReducer, initialClaimState);
|
const [state, dispatch] = React.useReducer(claimReducer, initialClaimState);
|
||||||
const getUserTrancheBalances = useGetUserTrancheBalances(address, vesting);
|
|
||||||
const refreshBalances = useRefreshBalances(address);
|
const refreshBalances = useRefreshBalances(address);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
@ -48,10 +44,9 @@ const Claim = ({
|
|||||||
// If the claim has been committed refetch the new VEGA balance
|
// If the claim has been committed refetch the new VEGA balance
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (state.claimStatus === ClaimStatus.Finished && address) {
|
if (state.claimStatus === ClaimStatus.Finished && address) {
|
||||||
getUserTrancheBalances();
|
|
||||||
refreshBalances();
|
refreshBalances();
|
||||||
}
|
}
|
||||||
}, [address, getUserTrancheBalances, refreshBalances, state.claimStatus]);
|
}, [address, refreshBalances, state.claimStatus]);
|
||||||
|
|
||||||
if (state.error) {
|
if (state.error) {
|
||||||
return <ClaimError />;
|
return <ClaimError />;
|
||||||
|
@ -5,7 +5,7 @@ import { EthConnectPrompt } from '../../components/eth-connect-prompt';
|
|||||||
import { Heading } from '../../components/heading';
|
import { Heading } from '../../components/heading';
|
||||||
import { SplashLoader } from '../../components/splash-loader';
|
import { SplashLoader } from '../../components/splash-loader';
|
||||||
import { useDocumentTitle } from '../../hooks/use-document-title';
|
import { useDocumentTitle } from '../../hooks/use-document-title';
|
||||||
import { useTranches } from '../../hooks/use-tranches';
|
import { useTranches } from '../../lib/tranches/tranches-store';
|
||||||
import type { RouteChildProps } from '..';
|
import type { RouteChildProps } from '..';
|
||||||
import Claim from './claim';
|
import Claim from './claim';
|
||||||
import { ClaimRestricted } from './claim-restricted';
|
import { ClaimRestricted } from './claim-restricted';
|
||||||
@ -16,7 +16,11 @@ const ClaimIndex = ({ name }: RouteChildProps) => {
|
|||||||
useDocumentTitle(name);
|
useDocumentTitle(name);
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { account } = useWeb3React();
|
const { account } = useWeb3React();
|
||||||
const { tranches, loading, error } = useTranches();
|
const { tranches, loading, error } = useTranches((state) => ({
|
||||||
|
loading: state.loading,
|
||||||
|
error: state.error,
|
||||||
|
tranches: state.tranches,
|
||||||
|
}));
|
||||||
|
|
||||||
if (loading || !tranches) {
|
if (loading || !tranches) {
|
||||||
return (
|
return (
|
||||||
@ -38,13 +42,14 @@ const ClaimIndex = ({ name }: RouteChildProps) => {
|
|||||||
|
|
||||||
if (!account) {
|
if (!account) {
|
||||||
content = (
|
content = (
|
||||||
<EthConnectPrompt>
|
<>
|
||||||
<p data-testid="eth-connect-prompt">
|
<p data-testid="eth-connect-prompt">
|
||||||
{t(
|
{t(
|
||||||
"Use the Ethereum wallet you want to send your tokens to. You'll also need enough Ethereum to pay gas."
|
"Use the Ethereum wallet you want to send your tokens to. You'll also need enough Ethereum to pay gas."
|
||||||
)}
|
)}
|
||||||
</p>
|
</p>
|
||||||
</EthConnectPrompt>
|
<EthConnectPrompt />
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
content = isRestricted() ? (
|
content = isRestricted() ? (
|
||||||
|
@ -51,11 +51,9 @@ const mockAppState: AppState = {
|
|||||||
totalAssociated: new BigNumber('50063005'),
|
totalAssociated: new BigNumber('50063005'),
|
||||||
decimals: 18,
|
decimals: 18,
|
||||||
totalSupply: new BigNumber(65000000),
|
totalSupply: new BigNumber(65000000),
|
||||||
tranches: null,
|
|
||||||
vegaWalletOverlay: false,
|
vegaWalletOverlay: false,
|
||||||
vegaWalletManageOverlay: false,
|
vegaWalletManageOverlay: false,
|
||||||
ethConnectOverlay: false,
|
ethConnectOverlay: false,
|
||||||
trancheError: null,
|
|
||||||
drawerOpen: false,
|
drawerOpen: false,
|
||||||
transactionOverlay: false,
|
transactionOverlay: false,
|
||||||
bannerMessage: '',
|
bannerMessage: '',
|
||||||
|
@ -14,11 +14,9 @@ const mockAppState: AppState = {
|
|||||||
totalAssociated: new BigNumber('50063005'),
|
totalAssociated: new BigNumber('50063005'),
|
||||||
decimals: 18,
|
decimals: 18,
|
||||||
totalSupply: mockTotalSupply,
|
totalSupply: mockTotalSupply,
|
||||||
tranches: null,
|
|
||||||
vegaWalletOverlay: false,
|
vegaWalletOverlay: false,
|
||||||
vegaWalletManageOverlay: false,
|
vegaWalletManageOverlay: false,
|
||||||
ethConnectOverlay: false,
|
ethConnectOverlay: false,
|
||||||
trancheError: null,
|
|
||||||
drawerOpen: false,
|
drawerOpen: false,
|
||||||
transactionOverlay: false,
|
transactionOverlay: false,
|
||||||
bannerMessage: '',
|
bannerMessage: '',
|
||||||
|
@ -1,56 +1,81 @@
|
|||||||
import { Callout, Intent } from '@vegaprotocol/ui-toolkit';
|
import { Callout, Intent } from '@vegaprotocol/ui-toolkit';
|
||||||
import { useBalances } from '../../../lib/balances/balances-store';
|
import { useEffect, useMemo, useState } from 'react';
|
||||||
import React from 'react';
|
|
||||||
import { Trans, useTranslation } from 'react-i18next';
|
import { Trans, useTranslation } from 'react-i18next';
|
||||||
import { Link, useNavigate, useOutletContext } from 'react-router-dom';
|
import { Link, useNavigate, useParams } from 'react-router-dom';
|
||||||
|
|
||||||
import { AddLockedTokenAddress } from '../../../components/add-locked-token';
|
import { AddLockedTokenAddress } from '../../../components/add-locked-token';
|
||||||
import { formatNumber } from '../../../lib/format-number';
|
import { formatNumber } from '../../../lib/format-number';
|
||||||
import { truncateMiddle } from '../../../lib/truncate-middle';
|
import { truncateMiddle } from '../../../lib/truncate-middle';
|
||||||
import Routes from '../../routes';
|
import Routes from '../../routes';
|
||||||
import type { RedemptionState } from '../redemption-reducer';
|
|
||||||
import { Tranche0Table, TrancheTable } from '../tranche-table';
|
import { Tranche0Table, TrancheTable } from '../tranche-table';
|
||||||
import { VestingTable } from './vesting-table';
|
import { VestingTable } from './vesting-table';
|
||||||
|
import { useTranches } from '../../../lib/tranches/tranches-store';
|
||||||
|
import { useGetUserBalances } from '../../../hooks/use-get-user-balances';
|
||||||
|
import BigNumber from 'bignumber.js';
|
||||||
|
import { useUserTrancheBalances } from '../hooks';
|
||||||
|
|
||||||
|
interface UserBalances {
|
||||||
|
balanceFormatted: BigNumber;
|
||||||
|
walletBalance: BigNumber;
|
||||||
|
lien: BigNumber;
|
||||||
|
allowance: BigNumber;
|
||||||
|
balance: BigNumber;
|
||||||
|
}
|
||||||
|
|
||||||
export const RedemptionInformation = () => {
|
export const RedemptionInformation = () => {
|
||||||
const { state, account } = useOutletContext<{
|
|
||||||
state: RedemptionState;
|
|
||||||
account: string;
|
|
||||||
}>();
|
|
||||||
const navigate = useNavigate();
|
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const {
|
const navigate = useNavigate();
|
||||||
balanceFormatted,
|
const tranches = useTranches((state) => state.tranches);
|
||||||
lien,
|
const { address } = useParams<{ address: string }>();
|
||||||
totalVestedBalance,
|
const [userBalances, setUserBalances] = useState<null | UserBalances>();
|
||||||
totalLockedBalance,
|
const getUsersBalances = useGetUserBalances(address);
|
||||||
trancheBalances,
|
useEffect(() => {
|
||||||
} = useBalances();
|
getUsersBalances().then(setUserBalances);
|
||||||
|
}, [getUsersBalances]);
|
||||||
const { userTranches } = state;
|
const userTrancheBalances = useUserTrancheBalances(address);
|
||||||
|
const filteredTranches = useMemo(
|
||||||
const filteredTranches = React.useMemo(
|
|
||||||
() =>
|
() =>
|
||||||
userTranches.filter((tr) => {
|
tranches?.filter((tr) => {
|
||||||
const balance = trancheBalances.find(
|
const balance = userTrancheBalances.find(
|
||||||
({ id }) => id.toString() === tr.tranche_id.toString()
|
({ id }) => id.toString() === tr.tranche_id.toString()
|
||||||
);
|
);
|
||||||
return (
|
return (
|
||||||
balance?.locked.isGreaterThan(0) || balance?.vested.isGreaterThan(0)
|
balance?.locked.isGreaterThan(0) || balance?.vested.isGreaterThan(0)
|
||||||
);
|
);
|
||||||
}),
|
}) || [],
|
||||||
[trancheBalances, userTranches]
|
[userTrancheBalances, tranches]
|
||||||
);
|
);
|
||||||
|
const { totalLocked, totalVested } = useMemo(() => {
|
||||||
|
return {
|
||||||
|
totalLocked: BigNumber.sum.apply(null, [
|
||||||
|
new BigNumber(0),
|
||||||
|
...userTrancheBalances.map(({ locked }) => locked),
|
||||||
|
]),
|
||||||
|
totalVested: BigNumber.sum.apply(null, [
|
||||||
|
new BigNumber(0),
|
||||||
|
...userTrancheBalances.map(({ vested }) => vested),
|
||||||
|
]),
|
||||||
|
};
|
||||||
|
}, [userTrancheBalances]);
|
||||||
|
|
||||||
const zeroTranche = React.useMemo(() => {
|
const zeroTranche = useMemo(() => {
|
||||||
const zeroTranche = trancheBalances.find((t) => t.id === 0);
|
const zeroTranche = userTrancheBalances.find((t) => t.id === 0);
|
||||||
if (zeroTranche && zeroTranche.locked.isGreaterThan(0)) {
|
if (zeroTranche && zeroTranche.locked.isGreaterThan(0)) {
|
||||||
return zeroTranche;
|
return zeroTranche;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}, [trancheBalances]);
|
}, [userTrancheBalances]);
|
||||||
|
|
||||||
if (!filteredTranches.length) {
|
const isAccountValid = useMemo(
|
||||||
|
() => address && address.length === 42 && address.startsWith('0x'),
|
||||||
|
[address]
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!isAccountValid || !address) {
|
||||||
|
return <div>The address {address} is not a valid Ethereum address</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!filteredTranches.length || !userBalances) {
|
||||||
return (
|
return (
|
||||||
<section data-testid="redemption-page">
|
<section data-testid="redemption-page">
|
||||||
<div className="mb-8">
|
<div className="mb-8">
|
||||||
@ -79,17 +104,17 @@ export const RedemptionInformation = () => {
|
|||||||
{t(
|
{t(
|
||||||
'{{address}} has {{balance}} VEGA tokens in {{tranches}} tranches of the vesting contract.',
|
'{{address}} has {{balance}} VEGA tokens in {{tranches}} tranches of the vesting contract.',
|
||||||
{
|
{
|
||||||
address: truncateMiddle(account),
|
address: truncateMiddle(address),
|
||||||
balance: formatNumber(balanceFormatted),
|
balance: formatNumber(userBalances.balanceFormatted),
|
||||||
tranches: filteredTranches.length,
|
tranches: filteredTranches.length,
|
||||||
}
|
}
|
||||||
)}
|
)}
|
||||||
</p>
|
</p>
|
||||||
<div className="mb-24">
|
<div className="mb-24">
|
||||||
<VestingTable
|
<VestingTable
|
||||||
associated={lien}
|
associated={userBalances.lien}
|
||||||
locked={totalLockedBalance}
|
locked={totalLocked}
|
||||||
vested={totalVestedBalance}
|
vested={totalVested}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{filteredTranches.length ? <h2>{t('Tranche breakdown')}</h2> : null}
|
{filteredTranches.length ? <h2>{t('Tranche breakdown')}</h2> : null}
|
||||||
@ -98,7 +123,7 @@ export const RedemptionInformation = () => {
|
|||||||
trancheId={0}
|
trancheId={0}
|
||||||
total={
|
total={
|
||||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||||
trancheBalances.find(
|
userTrancheBalances.find(
|
||||||
({ id }) => id.toString() === zeroTranche.id.toString()
|
({ id }) => id.toString() === zeroTranche.id.toString()
|
||||||
)!.locked
|
)!.locked
|
||||||
}
|
}
|
||||||
@ -108,22 +133,25 @@ export const RedemptionInformation = () => {
|
|||||||
<TrancheTable
|
<TrancheTable
|
||||||
key={tr.tranche_id}
|
key={tr.tranche_id}
|
||||||
tranche={tr}
|
tranche={tr}
|
||||||
lien={lien}
|
lien={userBalances.lien}
|
||||||
locked={
|
locked={
|
||||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||||
trancheBalances.find(
|
userTrancheBalances.find(
|
||||||
({ id }) => id.toString() === tr.tranche_id.toString()
|
({ id }) => id.toString() === tr.tranche_id.toString()
|
||||||
)!.locked
|
)!.locked
|
||||||
}
|
}
|
||||||
vested={
|
vested={
|
||||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||||
trancheBalances.find(
|
userTrancheBalances.find(
|
||||||
({ id }) => id.toString() === tr.tranche_id.toString()
|
({ id }) => id.toString() === tr.tranche_id.toString()
|
||||||
)!.vested
|
)!.vested
|
||||||
}
|
}
|
||||||
totalVested={totalVestedBalance}
|
totalVested={totalVested}
|
||||||
totalLocked={totalLockedBalance}
|
totalLocked={totalLocked}
|
||||||
onClick={() => navigate(`/vesting/${tr.tranche_id}`)}
|
onClick={() =>
|
||||||
|
navigate(`${Routes.REDEEM}/${address}/${tr.tranche_id}`)
|
||||||
|
}
|
||||||
|
address={address}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
<Callout
|
<Callout
|
||||||
@ -132,7 +160,7 @@ export const RedemptionInformation = () => {
|
|||||||
intent={Intent.Warning}
|
intent={Intent.Warning}
|
||||||
>
|
>
|
||||||
<p>{t('Find out more about Staking.')}</p>
|
<p>{t('Find out more about Staking.')}</p>
|
||||||
<Link to="/staking" className="underline text-white">
|
<Link to={Routes.VALIDATORS} className="underline text-white">
|
||||||
{t('Stake VEGA tokens')}
|
{t('Stake VEGA tokens')}
|
||||||
</Link>
|
</Link>
|
||||||
</Callout>
|
</Callout>
|
||||||
|
@ -12,7 +12,7 @@ export interface VestingTableProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const VestingTableIndicatorSquare = ({ colour }: { colour: string }) => (
|
const VestingTableIndicatorSquare = ({ colour }: { colour: string }) => (
|
||||||
<span className={`bg-${colour} inline-block h-12 w-12 mr-4`} />
|
<span className={`bg-${colour} inline-block h-4 w-4 mr-1`} />
|
||||||
);
|
);
|
||||||
|
|
||||||
export const VestingTable = ({
|
export const VestingTable = ({
|
||||||
@ -65,17 +65,17 @@ export const VestingTable = ({
|
|||||||
</KeyValueTable>
|
</KeyValueTable>
|
||||||
<div className="flex border-white border">
|
<div className="flex border-white border">
|
||||||
<div
|
<div
|
||||||
className="bg-vega-pink h-16"
|
className="bg-vega-pink h-4"
|
||||||
style={{ flex: lockedPercentage.toNumber() }}
|
style={{ flex: lockedPercentage.toNumber() }}
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
className="bg-vega-green h-16"
|
className="bg-vega-green h-4"
|
||||||
style={{ flex: vestedPercentage.toNumber() }}
|
style={{ flex: vestedPercentage.toNumber() }}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex h-4 mt-4">
|
<div className="flex h-1 mt-1">
|
||||||
<div
|
<div
|
||||||
className="bg-vega-yellow h-4"
|
className="bg-vega-yellow h-1"
|
||||||
style={{ flex: stakedPercentage.toNumber() }}
|
style={{ flex: stakedPercentage.toNumber() }}
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
|
54
apps/token/src/routes/redemption/hooks.ts
Normal file
54
apps/token/src/routes/redemption/hooks.ts
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
import { useCallback, useEffect, useState } from 'react';
|
||||||
|
|
||||||
|
import { useTranches } from '../../lib/tranches/tranches-store';
|
||||||
|
import { useContracts } from '../../contexts/contracts/contracts-context';
|
||||||
|
import BigNumber from 'bignumber.js';
|
||||||
|
import { toBigNum } from '@vegaprotocol/react-helpers';
|
||||||
|
import { useAppState } from '../../contexts/app-state/app-state-context';
|
||||||
|
|
||||||
|
export const useUserTrancheBalances = (address: string | undefined) => {
|
||||||
|
const [userTrancheBalances, setUserTrancheBalances] = useState<
|
||||||
|
{
|
||||||
|
id: number;
|
||||||
|
locked: BigNumber;
|
||||||
|
vested: BigNumber;
|
||||||
|
}[]
|
||||||
|
>([]);
|
||||||
|
const {
|
||||||
|
appState: { decimals },
|
||||||
|
} = useAppState();
|
||||||
|
const { vesting } = useContracts();
|
||||||
|
const tranches = useTranches((state) => state.tranches);
|
||||||
|
const loadUserTrancheBalances = useCallback(async () => {
|
||||||
|
if (!address) return;
|
||||||
|
const userTranches =
|
||||||
|
tranches?.filter((t) =>
|
||||||
|
t.users.some(
|
||||||
|
(a) => a && address && a.toLowerCase() === address.toLowerCase()
|
||||||
|
)
|
||||||
|
) || [];
|
||||||
|
const trancheIds = [0, ...userTranches.map((t) => t.tranche_id)];
|
||||||
|
const promises = trancheIds.map(async (tId) => {
|
||||||
|
const [t, v] = await Promise.all([
|
||||||
|
vesting.get_tranche_balance(address, tId),
|
||||||
|
vesting.get_vested_for_tranche(address, tId),
|
||||||
|
]);
|
||||||
|
|
||||||
|
const total = toBigNum(t, decimals);
|
||||||
|
const vested = toBigNum(v, decimals);
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: tId,
|
||||||
|
locked: tId === 0 ? total : total.minus(vested),
|
||||||
|
vested: tId === 0 ? new BigNumber(0) : vested,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const trancheBalances = await Promise.all(promises);
|
||||||
|
setUserTrancheBalances(trancheBalances);
|
||||||
|
}, [address, decimals, tranches, vesting]);
|
||||||
|
useEffect(() => {
|
||||||
|
loadUserTrancheBalances();
|
||||||
|
}, [loadUserTrancheBalances]);
|
||||||
|
return userTrancheBalances;
|
||||||
|
};
|
@ -1,38 +0,0 @@
|
|||||||
import type { Tranche } from '@vegaprotocol/smart-contracts';
|
|
||||||
import type { BigNumber } from '../../lib/bignumber';
|
|
||||||
|
|
||||||
export interface TrancheBalance {
|
|
||||||
id: number;
|
|
||||||
locked: BigNumber;
|
|
||||||
vested: BigNumber;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface RedemptionState {
|
|
||||||
userTranches: Tranche[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export const initialRedemptionState: RedemptionState = {
|
|
||||||
userTranches: [],
|
|
||||||
};
|
|
||||||
|
|
||||||
export enum RedemptionActionType {
|
|
||||||
SET_USER_TRANCHES,
|
|
||||||
}
|
|
||||||
|
|
||||||
export type RedemptionAction = {
|
|
||||||
type: RedemptionActionType.SET_USER_TRANCHES;
|
|
||||||
userTranches: Tranche[];
|
|
||||||
};
|
|
||||||
|
|
||||||
export function redemptionReducer(
|
|
||||||
state: RedemptionState,
|
|
||||||
action: RedemptionAction
|
|
||||||
): RedemptionState {
|
|
||||||
switch (action.type) {
|
|
||||||
case RedemptionActionType.SET_USER_TRANCHES:
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
userTranches: action.userTranches,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,51 +1,62 @@
|
|||||||
import { Callout, Intent, Splash } from '@vegaprotocol/ui-toolkit';
|
import {
|
||||||
|
Button,
|
||||||
|
Callout,
|
||||||
|
FormGroup,
|
||||||
|
Input,
|
||||||
|
InputError,
|
||||||
|
Intent,
|
||||||
|
Splash,
|
||||||
|
} from '@vegaprotocol/ui-toolkit';
|
||||||
import { useWeb3React } from '@web3-react/core';
|
import { useWeb3React } from '@web3-react/core';
|
||||||
import React from 'react';
|
import { useCallback } from 'react';
|
||||||
|
import { useForm } from 'react-hook-form';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { Outlet } from 'react-router-dom';
|
import { Outlet, useNavigate, useParams } from 'react-router-dom';
|
||||||
import { Link } from 'react-router-dom';
|
|
||||||
|
|
||||||
import { EthConnectPrompt } from '../../components/eth-connect-prompt';
|
import { EthConnectPrompt } from '../../components/eth-connect-prompt';
|
||||||
import { SplashLoader } from '../../components/splash-loader';
|
import { SplashLoader } from '../../components/splash-loader';
|
||||||
import { useTranches } from '../../hooks/use-tranches';
|
import { useTranches } from '../../lib/tranches/tranches-store';
|
||||||
import { useBalances } from '../../lib/balances/balances-store';
|
|
||||||
import RoutesConfig from '../routes';
|
import RoutesConfig from '../routes';
|
||||||
import {
|
|
||||||
initialRedemptionState,
|
interface FormFields {
|
||||||
RedemptionActionType,
|
address: string;
|
||||||
redemptionReducer,
|
}
|
||||||
} from './redemption-reducer';
|
|
||||||
|
|
||||||
const RedemptionRouter = () => {
|
const RedemptionRouter = () => {
|
||||||
|
const { address } = useParams<{ address: string }>();
|
||||||
|
const navigate = useNavigate();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [state, dispatch] = React.useReducer(
|
const validatePubkey = useCallback(
|
||||||
redemptionReducer,
|
(value: string) => {
|
||||||
initialRedemptionState
|
if (!value.startsWith('0x')) {
|
||||||
);
|
return t('Address must begin with 0x');
|
||||||
const { trancheBalances } = useBalances();
|
} else if (value.length !== 42) {
|
||||||
const { account } = useWeb3React();
|
return t('Pubkey must be 42 characters in length');
|
||||||
const { tranches, error, loading } = useTranches();
|
} else if (Number.isNaN(+value)) {
|
||||||
|
return t('Pubkey must be be valid hex');
|
||||||
React.useEffect(() => {
|
|
||||||
const run = (address: string) => {
|
|
||||||
const userTranches = tranches?.filter((t) =>
|
|
||||||
t.users.some(
|
|
||||||
({ address: a }) => a.toLowerCase() === address.toLowerCase()
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
if (userTranches) {
|
|
||||||
dispatch({
|
|
||||||
type: RedemptionActionType.SET_USER_TRANCHES,
|
|
||||||
userTranches,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
};
|
return true;
|
||||||
|
},
|
||||||
|
[t]
|
||||||
|
);
|
||||||
|
const { account } = useWeb3React();
|
||||||
|
const { tranches, error, loading } = useTranches((state) => ({
|
||||||
|
loading: state.loading,
|
||||||
|
error: state.error,
|
||||||
|
tranches: state.tranches,
|
||||||
|
}));
|
||||||
|
const {
|
||||||
|
register,
|
||||||
|
handleSubmit,
|
||||||
|
formState: { errors },
|
||||||
|
} = useForm<FormFields>();
|
||||||
|
|
||||||
if (account) {
|
const onSubmit = useCallback(
|
||||||
run(account);
|
(fields: FormFields) => {
|
||||||
}
|
navigate(`${RoutesConfig.REDEEM}/${fields.address}`);
|
||||||
}, [account, tranches]);
|
},
|
||||||
|
[navigate]
|
||||||
|
);
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
return (
|
return (
|
||||||
@ -63,30 +74,48 @@ const RedemptionRouter = () => {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!account) {
|
if (!address) {
|
||||||
return (
|
return (
|
||||||
<EthConnectPrompt>
|
<div className="max-w-md">
|
||||||
<p data-testid="eth-connect-prompt">
|
{!account ? (
|
||||||
{t(
|
<EthConnectPrompt />
|
||||||
"Use the Ethereum wallet you want to send your tokens to. You'll also need enough Ethereum to pay gas."
|
) : (
|
||||||
)}
|
<Button
|
||||||
</p>
|
fill={true}
|
||||||
</EthConnectPrompt>
|
variant="primary"
|
||||||
|
onClick={() => navigate(`${RoutesConfig.REDEEM}/${account}`)}
|
||||||
|
>
|
||||||
|
{t('View connected Eth Wallet')}
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
<p className="py-4 flex justify-center">{t('OR')}</p>
|
||||||
|
<form
|
||||||
|
onSubmit={handleSubmit(onSubmit)}
|
||||||
|
data-testid="view-connector-form"
|
||||||
|
>
|
||||||
|
<FormGroup label={'View Ethereum as user:'} labelFor="address">
|
||||||
|
<Input
|
||||||
|
{...register('address', {
|
||||||
|
required: t('Required'),
|
||||||
|
validate: validatePubkey,
|
||||||
|
})}
|
||||||
|
id="address"
|
||||||
|
data-testid="address"
|
||||||
|
type="text"
|
||||||
|
/>
|
||||||
|
{errors.address?.message && (
|
||||||
|
<InputError intent="danger">{errors.address.message}</InputError>
|
||||||
|
)}
|
||||||
|
</FormGroup>
|
||||||
|
<Button data-testid="connect" type="submit" fill={true}>
|
||||||
|
{t('View Ethereum user')}
|
||||||
|
</Button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!trancheBalances.length) {
|
return <Outlet />;
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Callout>
|
|
||||||
<p>{t('You have no VEGA tokens currently vesting.')}</p>
|
|
||||||
</Callout>
|
|
||||||
<Link to={RoutesConfig.SUPPLY}>{t('viewAllTranches')}</Link>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return <Outlet context={{ state, account }} />;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default RedemptionRouter;
|
export default RedemptionRouter;
|
||||||
|
@ -33,10 +33,10 @@ export const TrancheItem = ({
|
|||||||
}: TrancheItemProps) => {
|
}: TrancheItemProps) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const labelClasses =
|
const labelClasses =
|
||||||
'inline-block uppercase bg-white text-black py-4 px-8 font-mono';
|
'inline-block uppercase bg-white text-black py-1 px-2 font-mono';
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section data-testid="tranche-item" className="mb-40">
|
<section data-testid="tranche-item" className="mb-8">
|
||||||
<div className="flex border-b">
|
<div className="flex border-b">
|
||||||
{link ? (
|
{link ? (
|
||||||
<Link to={link}>
|
<Link to={link}>
|
||||||
|
@ -8,6 +8,7 @@ import { formatNumber } from '../../lib/format-number';
|
|||||||
import Routes from '../routes';
|
import Routes from '../routes';
|
||||||
import { TrancheItem } from './tranche-item';
|
import { TrancheItem } from './tranche-item';
|
||||||
import { Button } from '@vegaprotocol/ui-toolkit';
|
import { Button } from '@vegaprotocol/ui-toolkit';
|
||||||
|
import { useWeb3React } from '@web3-react/core';
|
||||||
|
|
||||||
export interface TrancheTableProps {
|
export interface TrancheTableProps {
|
||||||
tranche: {
|
tranche: {
|
||||||
@ -22,6 +23,7 @@ export interface TrancheTableProps {
|
|||||||
totalLocked: BigNumber;
|
totalLocked: BigNumber;
|
||||||
onClick: () => void;
|
onClick: () => void;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
|
address: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Tranche0Table = ({
|
export const Tranche0Table = ({
|
||||||
@ -65,9 +67,11 @@ export const TrancheTable = ({
|
|||||||
totalVested,
|
totalVested,
|
||||||
totalLocked,
|
totalLocked,
|
||||||
disabled = false,
|
disabled = false,
|
||||||
|
address,
|
||||||
}: TrancheTableProps) => {
|
}: TrancheTableProps) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const total = vested.plus(locked);
|
const total = vested.plus(locked);
|
||||||
|
const { account: connectedAddress } = useWeb3React();
|
||||||
const trancheFullyLocked =
|
const trancheFullyLocked =
|
||||||
tranche.tranche_start.getTime() > new Date().getTime();
|
tranche.tranche_start.getTime() > new Date().getTime();
|
||||||
const totalAllTranches = totalVested.plus(totalLocked);
|
const totalAllTranches = totalVested.plus(totalLocked);
|
||||||
@ -93,13 +97,20 @@ export const TrancheTable = ({
|
|||||||
amount: reduceAmount,
|
amount: reduceAmount,
|
||||||
}}
|
}}
|
||||||
components={{
|
components={{
|
||||||
stakeLink: <Link to={`/staking`} />,
|
stakeLink: <Link className="underline" to={Routes.VALIDATORS} />,
|
||||||
disassociateLink: <Link to={`/staking/disassociate`} />,
|
disassociateLink: (
|
||||||
|
<Link className="underline" to={Routes.DISASSOCIATE} />
|
||||||
|
),
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
} else if (!trancheFullyLocked && redeemable) {
|
} else if (
|
||||||
|
!trancheFullyLocked &&
|
||||||
|
redeemable &&
|
||||||
|
connectedAddress &&
|
||||||
|
address === connectedAddress
|
||||||
|
) {
|
||||||
message = (
|
message = (
|
||||||
<Button onClick={onClick} disabled={disabled}>
|
<Button onClick={onClick} disabled={disabled}>
|
||||||
{t('Redeem unlocked VEGA from tranche {{id}}', {
|
{t('Redeem unlocked VEGA from tranche {{id}}', {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { useBalances } from '../../../lib/balances/balances-store';
|
import { useBalances } from '../../../lib/balances/balances-store';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Trans, useTranslation } from 'react-i18next';
|
import { Trans, useTranslation } from 'react-i18next';
|
||||||
import { Link, useParams, useOutletContext } from 'react-router-dom';
|
import { Link, useParams } from 'react-router-dom';
|
||||||
|
|
||||||
import { TransactionCallout } from '../../../components/transaction-callout';
|
import { TransactionCallout } from '../../../components/transaction-callout';
|
||||||
import { useContracts } from '../../../contexts/contracts/contracts-context';
|
import { useContracts } from '../../../contexts/contracts/contracts-context';
|
||||||
@ -9,32 +9,36 @@ import {
|
|||||||
TransactionActionType,
|
TransactionActionType,
|
||||||
TxState,
|
TxState,
|
||||||
} from '../../../hooks/transaction-reducer';
|
} from '../../../hooks/transaction-reducer';
|
||||||
import { useGetUserTrancheBalances } from '../../../hooks/use-get-user-tranche-balances';
|
|
||||||
import { useRefreshBalances } from '../../../hooks/use-refresh-balances';
|
import { useRefreshBalances } from '../../../hooks/use-refresh-balances';
|
||||||
import { useTransaction } from '../../../hooks/use-transaction';
|
import { useTransaction } from '../../../hooks/use-transaction';
|
||||||
import { BigNumber } from '../../../lib/bignumber';
|
import { BigNumber } from '../../../lib/bignumber';
|
||||||
import { formatNumber } from '../../../lib/format-number';
|
import { formatNumber } from '../../../lib/format-number';
|
||||||
import Routes from '../../routes';
|
import Routes from '../../routes';
|
||||||
import type { RedemptionState } from '../redemption-reducer';
|
|
||||||
import { TrancheTable } from '../tranche-table';
|
import { TrancheTable } from '../tranche-table';
|
||||||
|
import { useTranches } from '../../../lib/tranches/tranches-store';
|
||||||
|
import { useWeb3React } from '@web3-react/core';
|
||||||
|
import { EthConnectPrompt } from '../../../components/eth-connect-prompt';
|
||||||
|
import { useUserTrancheBalances } from '../hooks';
|
||||||
|
import { useAppState } from '../../../contexts/app-state/app-state-context';
|
||||||
|
|
||||||
export const RedeemFromTranche = () => {
|
export const RedeemFromTranche = () => {
|
||||||
const { state, address } = useOutletContext<{
|
const { account: address } = useWeb3React();
|
||||||
state: RedemptionState;
|
|
||||||
address: string;
|
|
||||||
}>();
|
|
||||||
const { vesting } = useContracts();
|
const { vesting } = useContracts();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { lien, totalVestedBalance, trancheBalances, totalLockedBalance } =
|
const {
|
||||||
useBalances();
|
appState: { decimals },
|
||||||
const refreshBalances = useRefreshBalances(address);
|
} = useAppState();
|
||||||
const getUserTrancheBalances = useGetUserTrancheBalances(address, vesting);
|
const { lien, totalVestedBalance, totalLockedBalance } = useBalances();
|
||||||
|
const refreshBalances = useRefreshBalances(address || '');
|
||||||
|
const { tranches, getTranches } = useTranches((state) => ({
|
||||||
|
tranches: state.tranches,
|
||||||
|
getTranches: state.getTranches,
|
||||||
|
}));
|
||||||
const { id } = useParams<{ id: string }>();
|
const { id } = useParams<{ id: string }>();
|
||||||
const numberId = Number(id);
|
const numberId = Number(id);
|
||||||
const { userTranches } = state;
|
|
||||||
const tranche = React.useMemo(
|
const tranche = React.useMemo(
|
||||||
() => userTranches.find(({ tranche_id }) => tranche_id === numberId),
|
() => tranches?.find(({ tranche_id }) => tranche_id === numberId) || null,
|
||||||
[numberId, userTranches]
|
[numberId, tranches]
|
||||||
);
|
);
|
||||||
const {
|
const {
|
||||||
state: txState,
|
state: txState,
|
||||||
@ -42,7 +46,7 @@ export const RedeemFromTranche = () => {
|
|||||||
dispatch: txDispatch,
|
dispatch: txDispatch,
|
||||||
} = useTransaction(() => vesting.withdraw_from_tranche(numberId));
|
} = useTransaction(() => vesting.withdraw_from_tranche(numberId));
|
||||||
const { token } = useContracts();
|
const { token } = useContracts();
|
||||||
|
const trancheBalances = useUserTrancheBalances(address || '');
|
||||||
const redeemedAmount = React.useMemo(() => {
|
const redeemedAmount = React.useMemo(() => {
|
||||||
return (
|
return (
|
||||||
trancheBalances.find(({ id: bId }) => bId.toString() === id?.toString())
|
trancheBalances.find(({ id: bId }) => bId.toString() === id?.toString())
|
||||||
@ -55,10 +59,10 @@ export const RedeemFromTranche = () => {
|
|||||||
// If the claim has been committed refetch the new VEGA balance
|
// If the claim has been committed refetch the new VEGA balance
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (txState.txState === TxState.Complete && address) {
|
if (txState.txState === TxState.Complete && address) {
|
||||||
getUserTrancheBalances();
|
|
||||||
refreshBalances();
|
refreshBalances();
|
||||||
|
getTranches(decimals);
|
||||||
}
|
}
|
||||||
}, [address, getUserTrancheBalances, refreshBalances, txState.txState]);
|
}, [address, decimals, getTranches, refreshBalances, txState.txState]);
|
||||||
|
|
||||||
const trancheBalance = React.useMemo(() => {
|
const trancheBalance = React.useMemo(() => {
|
||||||
return trancheBalances.find(
|
return trancheBalances.find(
|
||||||
@ -66,6 +70,10 @@ export const RedeemFromTranche = () => {
|
|||||||
);
|
);
|
||||||
}, [id, trancheBalances]);
|
}, [id, trancheBalances]);
|
||||||
|
|
||||||
|
if (!address) {
|
||||||
|
return <EthConnectPrompt />;
|
||||||
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
!tranche ||
|
!tranche ||
|
||||||
tranche.total_removed.isEqualTo(tranche.total_added) ||
|
tranche.total_removed.isEqualTo(tranche.total_added) ||
|
||||||
@ -147,6 +155,7 @@ export const RedeemFromTranche = () => {
|
|||||||
locked={trancheBalance.locked}
|
locked={trancheBalance.locked}
|
||||||
vested={trancheBalance.vested}
|
vested={trancheBalance.vested}
|
||||||
onClick={perform}
|
onClick={perform}
|
||||||
|
address={address || ''}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</section>
|
</section>
|
||||||
|
@ -300,12 +300,17 @@ const routerConfig = [
|
|||||||
element: <LazyRedemption name="Vesting" />,
|
element: <LazyRedemption name="Vesting" />,
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
index: true,
|
path: ':address',
|
||||||
element: <LazyRedemptionIndex />,
|
children: [
|
||||||
},
|
{
|
||||||
{
|
index: true,
|
||||||
path: ':id',
|
element: <LazyRedemptionIndex />,
|
||||||
element: <LazyRedemptionTranche />,
|
},
|
||||||
|
{
|
||||||
|
path: ':id',
|
||||||
|
element: <LazyRedemptionTranche />,
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
@ -16,10 +16,11 @@ export const StakingWalletsContainer = ({
|
|||||||
|
|
||||||
if (!account) {
|
if (!account) {
|
||||||
return (
|
return (
|
||||||
<EthConnectPrompt>
|
<>
|
||||||
<p>{t('associateInfo1')}</p>
|
<p>{t('associateInfo1')}</p>
|
||||||
<p>{t('associateInfo2')}</p>
|
<p>{t('associateInfo2')}</p>
|
||||||
</EthConnectPrompt>
|
<EthConnectPrompt />
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,35 +1,34 @@
|
|||||||
import { BigNumber } from '../../../lib/bignumber';
|
import { BigNumber } from '../../../lib/bignumber';
|
||||||
import { sumCirculatingTokens } from './token-details-circulating';
|
import { sumCirculatingTokens } from './token-details-circulating';
|
||||||
import type { Tranche } from '@vegaprotocol/smart-contracts';
|
|
||||||
|
|
||||||
it('It sums some easy tranches correctly', () => {
|
it('It sums some easy tranches correctly', () => {
|
||||||
const tranches: Partial<Tranche>[] = [
|
const tranches = [
|
||||||
{ total_added: new BigNumber('100'), locked_amount: new BigNumber(0) },
|
{ total_added: new BigNumber(100), locked_amount: new BigNumber(0) },
|
||||||
{ total_added: new BigNumber('100'), locked_amount: new BigNumber(0) },
|
{ total_added: new BigNumber(100), locked_amount: new BigNumber(0) },
|
||||||
{ total_added: new BigNumber('100'), locked_amount: new BigNumber(0) },
|
{ total_added: new BigNumber(100), locked_amount: new BigNumber(0) },
|
||||||
];
|
];
|
||||||
|
|
||||||
const result = sumCirculatingTokens(tranches as Tranche[]);
|
const result = sumCirculatingTokens(tranches);
|
||||||
expect(result.toString()).toEqual('300');
|
expect(result.toString()).toEqual('300');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('It sums some longer tranches correctly', () => {
|
it('It sums some longer tranches correctly', () => {
|
||||||
const tranches: Partial<Tranche>[] = [
|
const tranches = [
|
||||||
{
|
{
|
||||||
total_added: new BigNumber('10000000000'),
|
total_added: new BigNumber(10000000000),
|
||||||
locked_amount: new BigNumber(0),
|
locked_amount: new BigNumber(0),
|
||||||
},
|
},
|
||||||
{ total_added: new BigNumber('20'), locked_amount: new BigNumber(0) },
|
{ total_added: new BigNumber(20), locked_amount: new BigNumber(0) },
|
||||||
{ total_added: new BigNumber('3000'), locked_amount: new BigNumber(3020) },
|
{ total_added: new BigNumber(3000), locked_amount: new BigNumber(3020) },
|
||||||
];
|
];
|
||||||
|
|
||||||
const result = sumCirculatingTokens(tranches as Tranche[]);
|
const result = sumCirculatingTokens(tranches);
|
||||||
expect(result.toString()).toEqual('10000000000');
|
expect(result.toString()).toEqual('10000000000');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Handles null tranche array', () => {
|
it('Handles null tranche array', () => {
|
||||||
const tranches = null;
|
const tranches = null;
|
||||||
|
|
||||||
const result = sumCirculatingTokens(tranches as unknown as Tranche[]);
|
const result = sumCirculatingTokens(tranches);
|
||||||
expect(result.toString()).toEqual('0');
|
expect(result.toString()).toEqual('0');
|
||||||
});
|
});
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { BigNumber } from '../../../lib/bignumber';
|
import { BigNumber } from '../../../lib/bignumber';
|
||||||
import { formatNumber } from '../../../lib/format-number';
|
import { formatNumber } from '../../../lib/format-number';
|
||||||
import type { Tranche } from '@vegaprotocol/smart-contracts';
|
import type { Tranche } from '../../../lib/tranches/tranches-store';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add together the circulating tokens from all tranches
|
* Add together the circulating tokens from all tranches
|
||||||
@ -9,7 +9,9 @@ import type { Tranche } from '@vegaprotocol/smart-contracts';
|
|||||||
* @param decimals decimal places for the formatted result
|
* @param decimals decimal places for the formatted result
|
||||||
* @return The total circulating tokens from all tranches
|
* @return The total circulating tokens from all tranches
|
||||||
*/
|
*/
|
||||||
export function sumCirculatingTokens(tranches: Tranche[] | null): BigNumber {
|
export function sumCirculatingTokens(
|
||||||
|
tranches: { total_added: BigNumber; locked_amount: BigNumber }[] | null
|
||||||
|
): BigNumber {
|
||||||
let totalCirculating: BigNumber = new BigNumber(0);
|
let totalCirculating: BigNumber = new BigNumber(0);
|
||||||
|
|
||||||
tranches?.forEach(
|
tranches?.forEach(
|
||||||
|
@ -7,7 +7,7 @@ import {
|
|||||||
KeyValueTableRow,
|
KeyValueTableRow,
|
||||||
RoundedWrapper,
|
RoundedWrapper,
|
||||||
} from '@vegaprotocol/ui-toolkit';
|
} from '@vegaprotocol/ui-toolkit';
|
||||||
import { useTranches } from '../../../hooks/use-tranches';
|
import { useTranches } from '../../../lib/tranches/tranches-store';
|
||||||
import type { BigNumber } from '../../../lib/bignumber';
|
import type { BigNumber } from '../../../lib/bignumber';
|
||||||
import { formatNumber } from '../../../lib/format-number';
|
import { formatNumber } from '../../../lib/format-number';
|
||||||
import { TokenDetailsCirculating } from './token-details-circulating';
|
import { TokenDetailsCirculating } from './token-details-circulating';
|
||||||
@ -25,7 +25,11 @@ export const TokenDetails = ({
|
|||||||
const { ETHERSCAN_URL } = useEnvironment();
|
const { ETHERSCAN_URL } = useEnvironment();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const { tranches, loading, error } = useTranches();
|
const { tranches, loading, error } = useTranches((state) => ({
|
||||||
|
loading: state.loading,
|
||||||
|
error: state.error,
|
||||||
|
tranches: state.tranches,
|
||||||
|
}));
|
||||||
const { config } = useEthereumConfig();
|
const { config } = useEthereumConfig();
|
||||||
const { token } = useContracts();
|
const { token } = useContracts();
|
||||||
|
|
||||||
|
@ -4,14 +4,18 @@ import { Outlet } from 'react-router-dom';
|
|||||||
import { Heading } from '../../components/heading';
|
import { Heading } from '../../components/heading';
|
||||||
import { SplashLoader } from '../../components/splash-loader';
|
import { SplashLoader } from '../../components/splash-loader';
|
||||||
import { useDocumentTitle } from '../../hooks/use-document-title';
|
import { useDocumentTitle } from '../../hooks/use-document-title';
|
||||||
import { useTranches } from '../../hooks/use-tranches';
|
|
||||||
import type { RouteChildProps } from '..';
|
import type { RouteChildProps } from '..';
|
||||||
import { Callout, Intent, Splash } from '@vegaprotocol/ui-toolkit';
|
import { Callout, Intent, Splash } from '@vegaprotocol/ui-toolkit';
|
||||||
|
import { useTranches } from '../../lib/tranches/tranches-store';
|
||||||
|
|
||||||
const TrancheRouter = ({ name }: RouteChildProps) => {
|
const TrancheRouter = ({ name }: RouteChildProps) => {
|
||||||
useDocumentTitle(name);
|
useDocumentTitle(name);
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { tranches, error, loading } = useTranches();
|
const { tranches, error, loading } = useTranches((state) => ({
|
||||||
|
loading: state.loading,
|
||||||
|
error: state.error,
|
||||||
|
tranches: state.tranches,
|
||||||
|
}));
|
||||||
|
|
||||||
if (!tranches || loading) {
|
if (!tranches || loading) {
|
||||||
return (
|
return (
|
||||||
|
@ -1,48 +1,32 @@
|
|||||||
import type { Tranche as ITranche } from '@vegaprotocol/smart-contracts';
|
import {
|
||||||
import { Link } from '@vegaprotocol/ui-toolkit';
|
KeyValueTable,
|
||||||
|
KeyValueTableRow,
|
||||||
|
Link,
|
||||||
|
RoundedWrapper,
|
||||||
|
} from '@vegaprotocol/ui-toolkit';
|
||||||
|
import { Link as RouterLink } from 'react-router-dom';
|
||||||
import { useWeb3React } from '@web3-react/core';
|
import { useWeb3React } from '@web3-react/core';
|
||||||
import React from 'react';
|
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useParams } from 'react-router';
|
import { useParams } from 'react-router';
|
||||||
import { Navigate } from 'react-router-dom';
|
import { Navigate } from 'react-router-dom';
|
||||||
|
import { formatNumber } from '@vegaprotocol/react-helpers';
|
||||||
|
|
||||||
import { useOutletContext } from 'react-router-dom';
|
|
||||||
import { useEnvironment } from '@vegaprotocol/environment';
|
import { useEnvironment } from '@vegaprotocol/environment';
|
||||||
import { BigNumber } from '../../lib/bignumber';
|
|
||||||
import { formatNumber } from '../../lib/format-number';
|
|
||||||
import { TrancheItem } from '../redemption/tranche-item';
|
import { TrancheItem } from '../redemption/tranche-item';
|
||||||
import Routes from '../routes';
|
import Routes from '../routes';
|
||||||
import { TrancheLabel } from './tranche-label';
|
import { TrancheLabel } from './tranche-label';
|
||||||
|
import { useTranches } from '../../lib/tranches/tranches-store';
|
||||||
const TrancheProgressContents = ({
|
|
||||||
children,
|
|
||||||
}: {
|
|
||||||
children: React.ReactNode;
|
|
||||||
}) => (
|
|
||||||
<div className="flex justify-between gap-4 font-mono py-2 px-4">
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
|
|
||||||
export const Tranche = () => {
|
export const Tranche = () => {
|
||||||
const tranches = useOutletContext<ITranche[]>();
|
const tranches = useTranches((state) => state.tranches);
|
||||||
const { ETHERSCAN_URL } = useEnvironment();
|
const { ETHERSCAN_URL } = useEnvironment();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { trancheId } = useParams<{ trancheId: string }>();
|
const { trancheId } = useParams<{ trancheId: string; address: string }>();
|
||||||
const { chainId } = useWeb3React();
|
const { chainId } = useWeb3React();
|
||||||
const tranche = tranches.find(
|
const tranche = tranches?.find(
|
||||||
(tranche) => trancheId && parseInt(trancheId) === tranche.tranche_id
|
(tranche) => trancheId && parseInt(trancheId) === tranche.tranche_id
|
||||||
);
|
);
|
||||||
|
|
||||||
const lockedData = React.useMemo(() => {
|
|
||||||
if (!tranche) return null;
|
|
||||||
const locked = tranche.locked_amount.div(tranche.total_added);
|
|
||||||
return {
|
|
||||||
locked,
|
|
||||||
unlocked: new BigNumber(1).minus(locked),
|
|
||||||
};
|
|
||||||
}, [tranche]);
|
|
||||||
|
|
||||||
if (!tranche) {
|
if (!tranche) {
|
||||||
return <Navigate to={Routes.NOT_FOUND} />;
|
return <Navigate to={Routes.NOT_FOUND} />;
|
||||||
}
|
}
|
||||||
@ -67,33 +51,36 @@ export const Tranche = () => {
|
|||||||
</div>
|
</div>
|
||||||
<h2>{t('Holders')}</h2>
|
<h2>{t('Holders')}</h2>
|
||||||
{tranche.users.length ? (
|
{tranche.users.length ? (
|
||||||
<ul role="list">
|
<RoundedWrapper>
|
||||||
{tranche.users.map((user, i) => {
|
<KeyValueTable>
|
||||||
const unlocked = user.remaining_tokens.times(
|
<KeyValueTableRow>
|
||||||
lockedData?.unlocked || 0
|
<h1>{t('Ethereum Address')}</h1>
|
||||||
);
|
<h1>{t('View tranche data')}</h1>
|
||||||
const locked = user.remaining_tokens.times(lockedData?.locked || 0);
|
</KeyValueTableRow>
|
||||||
return (
|
{tranche.users.map((user) => (
|
||||||
<li className="pb-4" key={i}>
|
<KeyValueTableRow key={user}>
|
||||||
<Link
|
{
|
||||||
title={t('View on Etherscan (opens in a new tab)')}
|
<Link
|
||||||
href={`${ETHERSCAN_URL}/tx/${user.address}`}
|
title={t('View on Etherscan (opens in a new tab)')}
|
||||||
target="_blank"
|
href={`${ETHERSCAN_URL}/address/${user}`}
|
||||||
>
|
target="_blank"
|
||||||
{user.address}
|
>
|
||||||
</Link>
|
{user}
|
||||||
<TrancheProgressContents>
|
</Link>
|
||||||
<span>{t('Locked')}</span>
|
}
|
||||||
<span>{t('Unlocked')}</span>
|
{
|
||||||
</TrancheProgressContents>
|
<RouterLink
|
||||||
<TrancheProgressContents>
|
className="underline"
|
||||||
<span>{formatNumber(locked)}</span>
|
title={t('View vesting information')}
|
||||||
<span>{formatNumber(unlocked)}</span>
|
to={`${Routes.REDEEM}/${user}`}
|
||||||
</TrancheProgressContents>
|
>
|
||||||
</li>
|
{t('View vesting information')}
|
||||||
);
|
</RouterLink>
|
||||||
})}
|
}
|
||||||
</ul>
|
</KeyValueTableRow>
|
||||||
|
))}
|
||||||
|
</KeyValueTable>
|
||||||
|
</RoundedWrapper>
|
||||||
) : (
|
) : (
|
||||||
<p>{t('No users')}</p>
|
<p>{t('No users')}</p>
|
||||||
)}
|
)}
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
import { useOutletContext } from 'react-router-dom';
|
|
||||||
import type { Tranche } from '@vegaprotocol/smart-contracts';
|
|
||||||
import { useWeb3React } from '@web3-react/core';
|
import { useWeb3React } from '@web3-react/core';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
@ -10,6 +8,8 @@ import { TrancheLabel } from './tranche-label';
|
|||||||
import { VestingChart } from './vesting-chart';
|
import { VestingChart } from './vesting-chart';
|
||||||
import { ButtonLink } from '@vegaprotocol/ui-toolkit';
|
import { ButtonLink } from '@vegaprotocol/ui-toolkit';
|
||||||
import { useEthereumConfig } from '@vegaprotocol/web3';
|
import { useEthereumConfig } from '@vegaprotocol/web3';
|
||||||
|
import type { Tranche } from '../../lib/tranches/tranches-store';
|
||||||
|
import { useTranches } from '../../lib/tranches/tranches-store';
|
||||||
|
|
||||||
const trancheMinimum = 10;
|
const trancheMinimum = 10;
|
||||||
|
|
||||||
@ -17,7 +17,7 @@ const shouldShowTranche = (t: Tranche) =>
|
|||||||
!t.total_added.isLessThanOrEqualTo(trancheMinimum);
|
!t.total_added.isLessThanOrEqualTo(trancheMinimum);
|
||||||
|
|
||||||
export const Tranches = () => {
|
export const Tranches = () => {
|
||||||
const tranches = useOutletContext<Tranche[]>();
|
const tranches = useTranches((state) => state.tranches);
|
||||||
const [showAll, setShowAll] = React.useState<boolean>(false);
|
const [showAll, setShowAll] = React.useState<boolean>(false);
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { chainId } = useWeb3React();
|
const { chainId } = useWeb3React();
|
||||||
@ -38,25 +38,24 @@ export const Tranches = () => {
|
|||||||
<ul role="list">
|
<ul role="list">
|
||||||
{(showAll ? tranches : filteredTranches).map((tranche) => {
|
{(showAll ? tranches : filteredTranches).map((tranche) => {
|
||||||
return (
|
return (
|
||||||
<React.Fragment key={tranche.tranche_id}>
|
<TrancheItem
|
||||||
<TrancheItem
|
key={tranche.tranche_id}
|
||||||
link={`${tranche.tranche_id}`}
|
link={`${tranche.tranche_id}`}
|
||||||
tranche={tranche}
|
tranche={tranche}
|
||||||
locked={tranche.locked_amount}
|
locked={tranche.locked_amount}
|
||||||
unlocked={tranche.total_added.minus(tranche.locked_amount)}
|
unlocked={tranche.total_added.minus(tranche.locked_amount)}
|
||||||
total={tranche.total_added}
|
total={tranche.total_added}
|
||||||
secondaryHeader={
|
secondaryHeader={
|
||||||
<TrancheLabel chainId={chainId} id={tranche.tranche_id} />
|
<TrancheLabel chainId={chainId} id={tranche.tranche_id} />
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</React.Fragment>
|
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</ul>
|
</ul>
|
||||||
) : (
|
) : (
|
||||||
<p>{t('No tranches')}</p>
|
<p>{t('No tranches')}</p>
|
||||||
)}
|
)}
|
||||||
<section className="text-center mt-32">
|
<section className="text-center mt-4">
|
||||||
<ButtonLink onClick={() => setShowAll(!showAll)}>
|
<ButtonLink onClick={() => setShowAll(!showAll)}>
|
||||||
{showAll
|
{showAll
|
||||||
? t(
|
? t(
|
||||||
|
@ -2,51 +2,15 @@ import type BigNumber from 'bignumber.js';
|
|||||||
|
|
||||||
export interface Tranche {
|
export interface Tranche {
|
||||||
tranche_id: number;
|
tranche_id: number;
|
||||||
tranche_start: Date;
|
users: string[];
|
||||||
tranche_end: Date;
|
initial_balance: number;
|
||||||
total_added: BigNumber;
|
current_balance: number;
|
||||||
total_removed: BigNumber;
|
cliff_start: number;
|
||||||
locked_amount: BigNumber;
|
duration: number;
|
||||||
deposits: Array<TrancheDeposit>;
|
|
||||||
withdrawals: Array<TrancheWithdrawal>;
|
|
||||||
users: Array<TrancheUser>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TrancheDeposit {
|
export interface TrancheServiceResponse {
|
||||||
amount: BigNumber;
|
tranches: Tranche[];
|
||||||
user: string;
|
|
||||||
tx: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface TrancheWithdrawal {
|
|
||||||
amount: BigNumber;
|
|
||||||
user: string;
|
|
||||||
tx: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface TrancheUser {
|
|
||||||
address: string;
|
|
||||||
deposits: Array<{
|
|
||||||
amount: BigNumber;
|
|
||||||
user: string;
|
|
||||||
tx: string;
|
|
||||||
tranche_id: number;
|
|
||||||
}>;
|
|
||||||
withdrawals: Array<{
|
|
||||||
amount: BigNumber;
|
|
||||||
user: string;
|
|
||||||
tx: string;
|
|
||||||
tranche_id: number;
|
|
||||||
}>;
|
|
||||||
total_tokens: BigNumber;
|
|
||||||
withdrawn_tokens: BigNumber;
|
|
||||||
remaining_tokens: BigNumber;
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum TrancheEvents {
|
|
||||||
Created = 'Tranche_Created',
|
|
||||||
BalanceAdded = 'Tranche_Balance_Added',
|
|
||||||
BalanceRemoved = 'Tranche_Balance_Removed',
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IVegaClaimData {
|
export interface IVegaClaimData {
|
||||||
@ -67,9 +31,3 @@ export interface IClaimTokenParams {
|
|||||||
signature: IVegaClaimSignature;
|
signature: IVegaClaimSignature;
|
||||||
country: string | null;
|
country: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface EpochDetails {
|
|
||||||
id: string;
|
|
||||||
startSeconds: BigNumber;
|
|
||||||
endSeconds: BigNumber;
|
|
||||||
}
|
|
||||||
|
@ -1,986 +0,0 @@
|
|||||||
const ethers = require('ethers');
|
|
||||||
const BigNumber = require('bignumber.js');
|
|
||||||
const uniq = require('lodash/uniq');
|
|
||||||
const fs = require('fs');
|
|
||||||
|
|
||||||
const MAX_ATTEMPTS = 5;
|
|
||||||
|
|
||||||
const CONFIG = [
|
|
||||||
{
|
|
||||||
env: 'mainnet',
|
|
||||||
contract: '0x23d1bfe8fa50a167816fbd79d7932577c06011f4',
|
|
||||||
provider: 'https://mainnet.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8',
|
|
||||||
startBlock: 12834524,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
env: 'testnet',
|
|
||||||
contract: '0xe2deBB240b43EDfEBc9c38B67c0894B9A92Bf07c',
|
|
||||||
provider: 'https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8',
|
|
||||||
startBlock: 11340808,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
env: 'stagnet3',
|
|
||||||
contract: '0x9F10cBeEf03A564Fb914c2010c0Cd55E9BB11406',
|
|
||||||
provider: 'https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8',
|
|
||||||
startBlock: 11790009,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
env: 'devnet',
|
|
||||||
contract: '0xd1216AAb948f5FC706Df73df6d71c64CcaA8550a',
|
|
||||||
provider: 'https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8',
|
|
||||||
startBlock: 11790003,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const vestingAbi = [
|
|
||||||
{
|
|
||||||
inputs: [
|
|
||||||
{
|
|
||||||
internalType: 'address',
|
|
||||||
name: 'token_v1_address',
|
|
||||||
type: 'address',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
internalType: 'address',
|
|
||||||
name: 'token_v2_address',
|
|
||||||
type: 'address',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
internalType: 'address[]',
|
|
||||||
name: 'old_addresses',
|
|
||||||
type: 'address[]',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
internalType: 'address[]',
|
|
||||||
name: 'new_addresses',
|
|
||||||
type: 'address[]',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
stateMutability: 'nonpayable',
|
|
||||||
type: 'constructor',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
anonymous: false,
|
|
||||||
inputs: [
|
|
||||||
{
|
|
||||||
indexed: true,
|
|
||||||
internalType: 'address',
|
|
||||||
name: 'new_controller',
|
|
||||||
type: 'address',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
name: 'Controller_Set',
|
|
||||||
type: 'event',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
anonymous: false,
|
|
||||||
inputs: [
|
|
||||||
{
|
|
||||||
indexed: true,
|
|
||||||
internalType: 'address',
|
|
||||||
name: 'issuer',
|
|
||||||
type: 'address',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
indexed: false,
|
|
||||||
internalType: 'uint256',
|
|
||||||
name: 'amount',
|
|
||||||
type: 'uint256',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
name: 'Issuer_Permitted',
|
|
||||||
type: 'event',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
anonymous: false,
|
|
||||||
inputs: [
|
|
||||||
{
|
|
||||||
indexed: true,
|
|
||||||
internalType: 'address',
|
|
||||||
name: 'issuer',
|
|
||||||
type: 'address',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
name: 'Issuer_Revoked',
|
|
||||||
type: 'event',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
anonymous: false,
|
|
||||||
inputs: [
|
|
||||||
{
|
|
||||||
indexed: true,
|
|
||||||
internalType: 'address',
|
|
||||||
name: 'user',
|
|
||||||
type: 'address',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
indexed: false,
|
|
||||||
internalType: 'uint256',
|
|
||||||
name: 'amount',
|
|
||||||
type: 'uint256',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
indexed: true,
|
|
||||||
internalType: 'bytes32',
|
|
||||||
name: 'vega_public_key',
|
|
||||||
type: 'bytes32',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
name: 'Stake_Deposited',
|
|
||||||
type: 'event',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
anonymous: false,
|
|
||||||
inputs: [
|
|
||||||
{
|
|
||||||
indexed: true,
|
|
||||||
internalType: 'address',
|
|
||||||
name: 'user',
|
|
||||||
type: 'address',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
indexed: false,
|
|
||||||
internalType: 'uint256',
|
|
||||||
name: 'amount',
|
|
||||||
type: 'uint256',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
indexed: true,
|
|
||||||
internalType: 'bytes32',
|
|
||||||
name: 'vega_public_key',
|
|
||||||
type: 'bytes32',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
name: 'Stake_Removed',
|
|
||||||
type: 'event',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
anonymous: false,
|
|
||||||
inputs: [
|
|
||||||
{
|
|
||||||
indexed: true,
|
|
||||||
internalType: 'address',
|
|
||||||
name: 'from',
|
|
||||||
type: 'address',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
indexed: false,
|
|
||||||
internalType: 'uint256',
|
|
||||||
name: 'amount',
|
|
||||||
type: 'uint256',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
indexed: true,
|
|
||||||
internalType: 'address',
|
|
||||||
name: 'to',
|
|
||||||
type: 'address',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
indexed: true,
|
|
||||||
internalType: 'bytes32',
|
|
||||||
name: 'vega_public_key',
|
|
||||||
type: 'bytes32',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
name: 'Stake_Transferred',
|
|
||||||
type: 'event',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
anonymous: false,
|
|
||||||
inputs: [
|
|
||||||
{
|
|
||||||
indexed: true,
|
|
||||||
internalType: 'address',
|
|
||||||
name: 'user',
|
|
||||||
type: 'address',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
indexed: true,
|
|
||||||
internalType: 'uint8',
|
|
||||||
name: 'tranche_id',
|
|
||||||
type: 'uint8',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
indexed: false,
|
|
||||||
internalType: 'uint256',
|
|
||||||
name: 'amount',
|
|
||||||
type: 'uint256',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
name: 'Tranche_Balance_Added',
|
|
||||||
type: 'event',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
anonymous: false,
|
|
||||||
inputs: [
|
|
||||||
{
|
|
||||||
indexed: true,
|
|
||||||
internalType: 'address',
|
|
||||||
name: 'user',
|
|
||||||
type: 'address',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
indexed: true,
|
|
||||||
internalType: 'uint8',
|
|
||||||
name: 'tranche_id',
|
|
||||||
type: 'uint8',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
indexed: false,
|
|
||||||
internalType: 'uint256',
|
|
||||||
name: 'amount',
|
|
||||||
type: 'uint256',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
name: 'Tranche_Balance_Removed',
|
|
||||||
type: 'event',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
anonymous: false,
|
|
||||||
inputs: [
|
|
||||||
{
|
|
||||||
indexed: true,
|
|
||||||
internalType: 'uint8',
|
|
||||||
name: 'tranche_id',
|
|
||||||
type: 'uint8',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
indexed: false,
|
|
||||||
internalType: 'uint256',
|
|
||||||
name: 'cliff_start',
|
|
||||||
type: 'uint256',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
indexed: false,
|
|
||||||
internalType: 'uint256',
|
|
||||||
name: 'duration',
|
|
||||||
type: 'uint256',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
name: 'Tranche_Created',
|
|
||||||
type: 'event',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
inputs: [],
|
|
||||||
name: 'accuracy_scale',
|
|
||||||
outputs: [
|
|
||||||
{
|
|
||||||
internalType: 'uint256',
|
|
||||||
name: '',
|
|
||||||
type: 'uint256',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
stateMutability: 'view',
|
|
||||||
type: 'function',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
inputs: [
|
|
||||||
{
|
|
||||||
internalType: 'address',
|
|
||||||
name: '',
|
|
||||||
type: 'address',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
name: 'address_migration',
|
|
||||||
outputs: [
|
|
||||||
{
|
|
||||||
internalType: 'address',
|
|
||||||
name: '',
|
|
||||||
type: 'address',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
stateMutability: 'view',
|
|
||||||
type: 'function',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
inputs: [
|
|
||||||
{
|
|
||||||
internalType: 'uint8',
|
|
||||||
name: 'tranche_id',
|
|
||||||
type: 'uint8',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
internalType: 'address',
|
|
||||||
name: 'target',
|
|
||||||
type: 'address',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
name: 'assisted_withdraw_from_tranche',
|
|
||||||
outputs: [],
|
|
||||||
stateMutability: 'nonpayable',
|
|
||||||
type: 'function',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
inputs: [],
|
|
||||||
name: 'controller',
|
|
||||||
outputs: [
|
|
||||||
{
|
|
||||||
internalType: 'address',
|
|
||||||
name: '',
|
|
||||||
type: 'address',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
stateMutability: 'view',
|
|
||||||
type: 'function',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
inputs: [
|
|
||||||
{
|
|
||||||
internalType: 'uint256',
|
|
||||||
name: 'cliff_start',
|
|
||||||
type: 'uint256',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
internalType: 'uint256',
|
|
||||||
name: 'duration',
|
|
||||||
type: 'uint256',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
name: 'create_tranche',
|
|
||||||
outputs: [],
|
|
||||||
stateMutability: 'nonpayable',
|
|
||||||
type: 'function',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
inputs: [],
|
|
||||||
name: 'default_tranche_id',
|
|
||||||
outputs: [
|
|
||||||
{
|
|
||||||
internalType: 'uint8',
|
|
||||||
name: '',
|
|
||||||
type: 'uint8',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
stateMutability: 'view',
|
|
||||||
type: 'function',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
inputs: [
|
|
||||||
{
|
|
||||||
internalType: 'address',
|
|
||||||
name: 'user',
|
|
||||||
type: 'address',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
internalType: 'uint8',
|
|
||||||
name: 'tranche_id',
|
|
||||||
type: 'uint8',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
name: 'get_tranche_balance',
|
|
||||||
outputs: [
|
|
||||||
{
|
|
||||||
internalType: 'uint256',
|
|
||||||
name: '',
|
|
||||||
type: 'uint256',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
stateMutability: 'view',
|
|
||||||
type: 'function',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
inputs: [
|
|
||||||
{
|
|
||||||
internalType: 'address',
|
|
||||||
name: 'user',
|
|
||||||
type: 'address',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
internalType: 'uint8',
|
|
||||||
name: 'tranche_id',
|
|
||||||
type: 'uint8',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
name: 'get_vested_for_tranche',
|
|
||||||
outputs: [
|
|
||||||
{
|
|
||||||
internalType: 'uint256',
|
|
||||||
name: '',
|
|
||||||
type: 'uint256',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
stateMutability: 'view',
|
|
||||||
type: 'function',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
inputs: [
|
|
||||||
{
|
|
||||||
internalType: 'address',
|
|
||||||
name: 'user',
|
|
||||||
type: 'address',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
internalType: 'uint8',
|
|
||||||
name: 'tranche_id',
|
|
||||||
type: 'uint8',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
internalType: 'uint256',
|
|
||||||
name: 'amount',
|
|
||||||
type: 'uint256',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
name: 'issue_into_tranche',
|
|
||||||
outputs: [],
|
|
||||||
stateMutability: 'nonpayable',
|
|
||||||
type: 'function',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
inputs: [
|
|
||||||
{
|
|
||||||
internalType: 'address',
|
|
||||||
name: 'user',
|
|
||||||
type: 'address',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
internalType: 'uint8',
|
|
||||||
name: 'tranche_id',
|
|
||||||
type: 'uint8',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
internalType: 'uint256',
|
|
||||||
name: 'amount',
|
|
||||||
type: 'uint256',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
name: 'move_into_tranche',
|
|
||||||
outputs: [],
|
|
||||||
stateMutability: 'nonpayable',
|
|
||||||
type: 'function',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
inputs: [
|
|
||||||
{
|
|
||||||
internalType: 'address',
|
|
||||||
name: 'issuer',
|
|
||||||
type: 'address',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
internalType: 'uint256',
|
|
||||||
name: 'amount',
|
|
||||||
type: 'uint256',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
name: 'permit_issuer',
|
|
||||||
outputs: [],
|
|
||||||
stateMutability: 'nonpayable',
|
|
||||||
type: 'function',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
inputs: [
|
|
||||||
{
|
|
||||||
internalType: 'address',
|
|
||||||
name: '',
|
|
||||||
type: 'address',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
name: 'permitted_issuance',
|
|
||||||
outputs: [
|
|
||||||
{
|
|
||||||
internalType: 'uint256',
|
|
||||||
name: '',
|
|
||||||
type: 'uint256',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
stateMutability: 'view',
|
|
||||||
type: 'function',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
inputs: [
|
|
||||||
{
|
|
||||||
internalType: 'uint256',
|
|
||||||
name: 'amount',
|
|
||||||
type: 'uint256',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
internalType: 'bytes32',
|
|
||||||
name: 'vega_public_key',
|
|
||||||
type: 'bytes32',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
name: 'remove_stake',
|
|
||||||
outputs: [],
|
|
||||||
stateMutability: 'nonpayable',
|
|
||||||
type: 'function',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
inputs: [
|
|
||||||
{
|
|
||||||
internalType: 'address',
|
|
||||||
name: 'issuer',
|
|
||||||
type: 'address',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
name: 'revoke_issuer',
|
|
||||||
outputs: [],
|
|
||||||
stateMutability: 'nonpayable',
|
|
||||||
type: 'function',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
inputs: [
|
|
||||||
{
|
|
||||||
internalType: 'address',
|
|
||||||
name: 'new_controller',
|
|
||||||
type: 'address',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
name: 'set_controller',
|
|
||||||
outputs: [],
|
|
||||||
stateMutability: 'nonpayable',
|
|
||||||
type: 'function',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
inputs: [
|
|
||||||
{
|
|
||||||
internalType: 'address',
|
|
||||||
name: 'target',
|
|
||||||
type: 'address',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
internalType: 'bytes32',
|
|
||||||
name: 'vega_public_key',
|
|
||||||
type: 'bytes32',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
name: 'stake_balance',
|
|
||||||
outputs: [
|
|
||||||
{
|
|
||||||
internalType: 'uint256',
|
|
||||||
name: '',
|
|
||||||
type: 'uint256',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
stateMutability: 'view',
|
|
||||||
type: 'function',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
inputs: [
|
|
||||||
{
|
|
||||||
internalType: 'uint256',
|
|
||||||
name: 'amount',
|
|
||||||
type: 'uint256',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
internalType: 'bytes32',
|
|
||||||
name: 'vega_public_key',
|
|
||||||
type: 'bytes32',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
name: 'stake_tokens',
|
|
||||||
outputs: [],
|
|
||||||
stateMutability: 'nonpayable',
|
|
||||||
type: 'function',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
inputs: [],
|
|
||||||
name: 'staking_token',
|
|
||||||
outputs: [
|
|
||||||
{
|
|
||||||
internalType: 'address',
|
|
||||||
name: '',
|
|
||||||
type: 'address',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
stateMutability: 'view',
|
|
||||||
type: 'function',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
inputs: [],
|
|
||||||
name: 'total_locked',
|
|
||||||
outputs: [
|
|
||||||
{
|
|
||||||
internalType: 'uint256',
|
|
||||||
name: '',
|
|
||||||
type: 'uint256',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
stateMutability: 'view',
|
|
||||||
type: 'function',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
inputs: [],
|
|
||||||
name: 'total_staked',
|
|
||||||
outputs: [
|
|
||||||
{
|
|
||||||
internalType: 'uint256',
|
|
||||||
name: '',
|
|
||||||
type: 'uint256',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
stateMutability: 'view',
|
|
||||||
type: 'function',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
inputs: [],
|
|
||||||
name: 'tranche_count',
|
|
||||||
outputs: [
|
|
||||||
{
|
|
||||||
internalType: 'uint8',
|
|
||||||
name: '',
|
|
||||||
type: 'uint8',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
stateMutability: 'view',
|
|
||||||
type: 'function',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
inputs: [
|
|
||||||
{
|
|
||||||
internalType: 'uint8',
|
|
||||||
name: '',
|
|
||||||
type: 'uint8',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
name: 'tranches',
|
|
||||||
outputs: [
|
|
||||||
{
|
|
||||||
internalType: 'uint256',
|
|
||||||
name: 'cliff_start',
|
|
||||||
type: 'uint256',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
internalType: 'uint256',
|
|
||||||
name: 'duration',
|
|
||||||
type: 'uint256',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
stateMutability: 'view',
|
|
||||||
type: 'function',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
inputs: [
|
|
||||||
{
|
|
||||||
internalType: 'address',
|
|
||||||
name: '',
|
|
||||||
type: 'address',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
name: 'user_stats',
|
|
||||||
outputs: [
|
|
||||||
{
|
|
||||||
internalType: 'uint256',
|
|
||||||
name: 'total_in_all_tranches',
|
|
||||||
type: 'uint256',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
internalType: 'uint256',
|
|
||||||
name: 'lien',
|
|
||||||
type: 'uint256',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
stateMutability: 'view',
|
|
||||||
type: 'function',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
inputs: [
|
|
||||||
{
|
|
||||||
internalType: 'address',
|
|
||||||
name: 'user',
|
|
||||||
type: 'address',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
name: 'user_total_all_tranches',
|
|
||||||
outputs: [
|
|
||||||
{
|
|
||||||
internalType: 'uint256',
|
|
||||||
name: '',
|
|
||||||
type: 'uint256',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
stateMutability: 'view',
|
|
||||||
type: 'function',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
inputs: [],
|
|
||||||
name: 'v1_address',
|
|
||||||
outputs: [
|
|
||||||
{
|
|
||||||
internalType: 'address',
|
|
||||||
name: '',
|
|
||||||
type: 'address',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
stateMutability: 'view',
|
|
||||||
type: 'function',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
inputs: [
|
|
||||||
{
|
|
||||||
internalType: 'address',
|
|
||||||
name: '',
|
|
||||||
type: 'address',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
name: 'v1_migrated',
|
|
||||||
outputs: [
|
|
||||||
{
|
|
||||||
internalType: 'bool',
|
|
||||||
name: '',
|
|
||||||
type: 'bool',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
stateMutability: 'view',
|
|
||||||
type: 'function',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
inputs: [],
|
|
||||||
name: 'v2_address',
|
|
||||||
outputs: [
|
|
||||||
{
|
|
||||||
internalType: 'address',
|
|
||||||
name: '',
|
|
||||||
type: 'address',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
stateMutability: 'view',
|
|
||||||
type: 'function',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
inputs: [
|
|
||||||
{
|
|
||||||
internalType: 'uint8',
|
|
||||||
name: 'tranche_id',
|
|
||||||
type: 'uint8',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
name: 'withdraw_from_tranche',
|
|
||||||
outputs: [],
|
|
||||||
stateMutability: 'nonpayable',
|
|
||||||
type: 'function',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
function addDecimal(value, decimals) {
|
|
||||||
return value.dividedBy(Math.pow(10, decimals)).decimalPlaces(decimals);
|
|
||||||
}
|
|
||||||
|
|
||||||
function createUserTransactions(events, decimals) {
|
|
||||||
return events.map((event) => {
|
|
||||||
return {
|
|
||||||
amount: addDecimal(
|
|
||||||
new BigNumber(event.args?.amount.toString()),
|
|
||||||
decimals
|
|
||||||
),
|
|
||||||
user: event.args?.user,
|
|
||||||
tranche_id: event.args?.tranche_id,
|
|
||||||
tx: event.transactionHash,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function getUsersInTranche(
|
|
||||||
balanceAddedEvents,
|
|
||||||
balanceRemovedEvents,
|
|
||||||
addresses,
|
|
||||||
decimals
|
|
||||||
) {
|
|
||||||
return addresses.map((address) => {
|
|
||||||
const userDeposits = balanceAddedEvents.filter(
|
|
||||||
(event) => event.args?.user === address
|
|
||||||
);
|
|
||||||
const userWithdraws = balanceRemovedEvents.filter(
|
|
||||||
(event) => event.args?.user === address
|
|
||||||
);
|
|
||||||
const deposits = createUserTransactions(userDeposits, decimals);
|
|
||||||
const withdrawals = createUserTransactions(userWithdraws, decimals);
|
|
||||||
const total_tokens = deposits.reduce(
|
|
||||||
(pre, cur) => pre.plus(cur.amount),
|
|
||||||
new BigNumber(0)
|
|
||||||
);
|
|
||||||
const withdrawn_tokens = withdrawals.reduce(
|
|
||||||
(pre, cur) => pre.plus(cur.amount),
|
|
||||||
new BigNumber(0)
|
|
||||||
);
|
|
||||||
const remaining_tokens = total_tokens.minus(withdrawn_tokens);
|
|
||||||
|
|
||||||
return {
|
|
||||||
address,
|
|
||||||
deposits,
|
|
||||||
withdrawals,
|
|
||||||
total_tokens,
|
|
||||||
withdrawn_tokens,
|
|
||||||
remaining_tokens,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function sumFromEvents(events, decimals) {
|
|
||||||
const amounts = events.map((e) =>
|
|
||||||
addDecimal(new BigNumber(e.args?.amount.toString()), decimals)
|
|
||||||
);
|
|
||||||
// Start with a 0 so if there are none there is no NaN
|
|
||||||
return BigNumber.sum.apply(null, [new BigNumber(0), ...amounts]);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getLockedAmount(totalAdded, cliffStart, trancheDuration) {
|
|
||||||
let amount = new BigNumber(0);
|
|
||||||
const ts = Math.round(new Date().getTime() / 1000);
|
|
||||||
const tranche_progress = (ts - cliffStart) / trancheDuration;
|
|
||||||
|
|
||||||
if (tranche_progress < 0) {
|
|
||||||
amount = totalAdded;
|
|
||||||
} else if (tranche_progress < 1) {
|
|
||||||
amount = totalAdded.times(1 - tranche_progress);
|
|
||||||
}
|
|
||||||
|
|
||||||
return amount;
|
|
||||||
}
|
|
||||||
|
|
||||||
function createTransactions(events, decimals) {
|
|
||||||
return events.map((event) => {
|
|
||||||
return {
|
|
||||||
amount: addDecimal(
|
|
||||||
new BigNumber(event.args?.amount.toString()),
|
|
||||||
decimals
|
|
||||||
),
|
|
||||||
user: event.args?.user,
|
|
||||||
tx: event.transactionHash,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function getTranchesFromHistory(
|
|
||||||
createEvents,
|
|
||||||
addEvents,
|
|
||||||
removeEvents,
|
|
||||||
decimals
|
|
||||||
) {
|
|
||||||
return createEvents.map((event) => {
|
|
||||||
const tranche_id = event.args?.tranche_id;
|
|
||||||
const balanceAddedEvents = addEvents.filter(
|
|
||||||
(e) =>
|
|
||||||
e.event === 'Tranche_Balance_Added' && e.args?.tranche_id === tranche_id
|
|
||||||
);
|
|
||||||
const balanceRemovedEvents = removeEvents.filter(
|
|
||||||
(e) =>
|
|
||||||
e.event === 'Tranche_Balance_Removed' &&
|
|
||||||
e.args?.tranche_id === tranche_id
|
|
||||||
);
|
|
||||||
|
|
||||||
//get tranche start and end dates
|
|
||||||
const tranche_duration = event.args?.duration;
|
|
||||||
const cliff_start = event.args?.cliff_start;
|
|
||||||
const tranche_start = new Date(cliff_start.mul(1000).toNumber());
|
|
||||||
const tranche_end = new Date(
|
|
||||||
cliff_start.add(tranche_duration).mul(1000).toNumber()
|
|
||||||
);
|
|
||||||
|
|
||||||
// get added and removed values
|
|
||||||
const total_added = sumFromEvents(balanceAddedEvents, decimals);
|
|
||||||
const total_removed = sumFromEvents(balanceRemovedEvents, decimals);
|
|
||||||
// get locked amount
|
|
||||||
const locked_amount = getLockedAmount(
|
|
||||||
total_added,
|
|
||||||
cliff_start,
|
|
||||||
tranche_duration
|
|
||||||
);
|
|
||||||
|
|
||||||
// get all deposits and withdrawals
|
|
||||||
const deposits = createTransactions(balanceAddedEvents, decimals);
|
|
||||||
const withdrawals = createTransactions(balanceRemovedEvents, decimals);
|
|
||||||
|
|
||||||
// get all users
|
|
||||||
const uniqueAddresses = uniq(
|
|
||||||
balanceAddedEvents.map((event) => event.args?.user)
|
|
||||||
);
|
|
||||||
const users = getUsersInTranche(
|
|
||||||
balanceAddedEvents,
|
|
||||||
balanceRemovedEvents,
|
|
||||||
uniqueAddresses,
|
|
||||||
decimals
|
|
||||||
);
|
|
||||||
|
|
||||||
return {
|
|
||||||
tranche_id: parseInt(tranche_id),
|
|
||||||
tranche_start,
|
|
||||||
tranche_end,
|
|
||||||
total_added,
|
|
||||||
total_removed,
|
|
||||||
locked_amount,
|
|
||||||
deposits,
|
|
||||||
withdrawals,
|
|
||||||
users,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const getBatched = async (filter, contract, provider, startblock) => {
|
|
||||||
const batchSize = 100000;
|
|
||||||
const currentBlockNumber = await provider.getBlockNumber();
|
|
||||||
const batches = Math.ceil(currentBlockNumber / batchSize);
|
|
||||||
const startIndex = Math.floor(startblock / batchSize);
|
|
||||||
|
|
||||||
console.log(
|
|
||||||
`Processing batches of size ${batches} starting at batch ${startIndex}`
|
|
||||||
);
|
|
||||||
let res = [];
|
|
||||||
for (let index = startIndex; index < batches; index++) {
|
|
||||||
let events = [];
|
|
||||||
let attempts = 1;
|
|
||||||
// Sometimes the queries fail for timeout even on small batch sizes. Some basic retry logic.
|
|
||||||
while (attempts < MAX_ATTEMPTS) {
|
|
||||||
try {
|
|
||||||
events = await contract.queryFilter(
|
|
||||||
filter,
|
|
||||||
index * batchSize,
|
|
||||||
(index + 1) * batchSize - 1
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
} catch {
|
|
||||||
console.log('retry batch', index);
|
|
||||||
++attempts;
|
|
||||||
if (attempts >= MAX_ATTEMPTS) {
|
|
||||||
throw new Error('Could not get in 4 attempts');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
res = [...events, ...res];
|
|
||||||
|
|
||||||
console.log(
|
|
||||||
`Processed blocks ${index * batchSize} to ${
|
|
||||||
(index + 1) * batchSize - 1
|
|
||||||
} as part of batch ${index}`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
};
|
|
||||||
|
|
||||||
const run = async (c) => {
|
|
||||||
const provider = new ethers.providers.JsonRpcProvider({
|
|
||||||
url: c.provider,
|
|
||||||
timeout: 1000 * 60 * 1000,
|
|
||||||
});
|
|
||||||
|
|
||||||
const contract = new ethers.Contract(c.contract, vestingAbi, provider);
|
|
||||||
const [created, added, removed] = await Promise.all([
|
|
||||||
getBatched(
|
|
||||||
contract.filters.Tranche_Created(),
|
|
||||||
contract,
|
|
||||||
provider,
|
|
||||||
c.startBlock
|
|
||||||
),
|
|
||||||
getBatched(
|
|
||||||
contract.filters.Tranche_Balance_Added(),
|
|
||||||
contract,
|
|
||||||
provider,
|
|
||||||
c.startBlock
|
|
||||||
),
|
|
||||||
getBatched(
|
|
||||||
contract.filters.Tranche_Balance_Removed(),
|
|
||||||
contract,
|
|
||||||
provider,
|
|
||||||
c.startBlock
|
|
||||||
),
|
|
||||||
]);
|
|
||||||
fs.writeFileSync(
|
|
||||||
`./apps/static/src/assets/${c.env}-tranches.json`,
|
|
||||||
JSON.stringify(
|
|
||||||
getTranchesFromHistory(created, added, removed, 18),
|
|
||||||
null,
|
|
||||||
2
|
|
||||||
),
|
|
||||||
{ encoding: 'UTF-8' }
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
CONFIG.forEach((c) => run(c));
|
|
Loading…
Reference in New Issue
Block a user