Compare commits
10
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e2ed24f529 | ||
|
|
7e4aafcb77 | ||
|
|
643d5408cd | ||
|
|
2a2af3ba9c | ||
|
|
8d4e4a1228 | ||
|
|
84068c8081 | ||
|
|
e1185b9a96 | ||
|
|
f390448c24 | ||
|
|
70943c523c | ||
|
|
dcb79e70d3 |
@@ -7,9 +7,10 @@ query PreviousEpoch($epochId: ID) {
|
||||
id
|
||||
rewardScore {
|
||||
rawValidatorScore
|
||||
performanceScore
|
||||
}
|
||||
rankingScore {
|
||||
performanceScore
|
||||
stakeScore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ export type PreviousEpochQueryVariables = Types.Exact<{
|
||||
}>;
|
||||
|
||||
|
||||
export type PreviousEpochQuery = { __typename?: 'Query', epoch: { __typename?: 'Epoch', id: string, validatorsConnection?: { __typename?: 'NodesConnection', edges?: Array<{ __typename?: 'NodeEdge', node: { __typename?: 'Node', id: string, rewardScore?: { __typename?: 'RewardScore', rawValidatorScore: string } | null, rankingScore: { __typename?: 'RankingScore', performanceScore: string } } } | null> | null } | null } };
|
||||
export type PreviousEpochQuery = { __typename?: 'Query', epoch: { __typename?: 'Epoch', id: string, validatorsConnection?: { __typename?: 'NodesConnection', edges?: Array<{ __typename?: 'NodeEdge', node: { __typename?: 'Node', id: string, rewardScore?: { __typename?: 'RewardScore', rawValidatorScore: string, performanceScore: string } | null, rankingScore: { __typename?: 'RankingScore', stakeScore: string } } } | null> | null } | null } };
|
||||
|
||||
|
||||
export const PreviousEpochDocument = gql`
|
||||
@@ -21,9 +21,10 @@ export const PreviousEpochDocument = gql`
|
||||
id
|
||||
rewardScore {
|
||||
rawValidatorScore
|
||||
performanceScore
|
||||
}
|
||||
rankingScore {
|
||||
performanceScore
|
||||
stakeScore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+6
-3
@@ -81,9 +81,10 @@ const MOCK_PREVIOUS_EPOCH: PreviousEpochQuery = {
|
||||
id: 'ccc022b7e63a4d0a6d3a193c3940c88574060e58a184964c994998d86835a1b4',
|
||||
rewardScore: {
|
||||
rawValidatorScore: '0.25',
|
||||
performanceScore: '0.9998677767864936',
|
||||
},
|
||||
rankingScore: {
|
||||
performanceScore: '0.9998677767864936',
|
||||
stakeScore: '0.2499583402766206',
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -92,9 +93,10 @@ const MOCK_PREVIOUS_EPOCH: PreviousEpochQuery = {
|
||||
id: '966438c6bffac737cfb08173ffcb3f393c4692b099ad80cb45a82e2dc0a8cf99',
|
||||
rewardScore: {
|
||||
rawValidatorScore: '0.3',
|
||||
performanceScore: '1',
|
||||
},
|
||||
rankingScore: {
|
||||
performanceScore: '1',
|
||||
stakeScore: '0.25',
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -103,9 +105,10 @@ const MOCK_PREVIOUS_EPOCH: PreviousEpochQuery = {
|
||||
id: '12c81b738e8051152e1afe44376ec37bca9216466e6d44cdd772194bad0ada81',
|
||||
rewardScore: {
|
||||
rawValidatorScore: '0.35',
|
||||
performanceScore: '0.999629748500531',
|
||||
},
|
||||
rankingScore: {
|
||||
performanceScore: '0.999629748500531',
|
||||
stakeScore: '0.2312',
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
+16
-20
@@ -10,7 +10,6 @@ import {
|
||||
getFormattedPerformanceScore,
|
||||
getLastEpochScoreAndPerformance,
|
||||
getNormalisedVotingPower,
|
||||
getOverstakedAmount,
|
||||
getOverstakingPenalty,
|
||||
getPerformancePenalty,
|
||||
getTotalPenalties,
|
||||
@@ -52,7 +51,6 @@ interface CanonisedConsensusNodeProps {
|
||||
[ValidatorFields.STAKED_BY_OPERATOR]: string;
|
||||
[ValidatorFields.PERFORMANCE_SCORE]: string;
|
||||
[ValidatorFields.PERFORMANCE_PENALTY]: string;
|
||||
[ValidatorFields.OVERSTAKED_AMOUNT]: string;
|
||||
[ValidatorFields.OVERSTAKING_PENALTY]: string;
|
||||
[ValidatorFields.TOTAL_PENALTIES]: string;
|
||||
[ValidatorFields.PENDING_STAKE]: string;
|
||||
@@ -164,14 +162,11 @@ export const ConsensusValidatorsTable = ({
|
||||
pendingUserStake,
|
||||
userStakeShare,
|
||||
}) => {
|
||||
const { rawValidatorScore, performanceScore } =
|
||||
getLastEpochScoreAndPerformance(previousEpochData, id);
|
||||
|
||||
const overstakedAmount = getOverstakedAmount(
|
||||
rawValidatorScore,
|
||||
stakedTotal,
|
||||
totalStake
|
||||
);
|
||||
const {
|
||||
rawValidatorScore: previousEpochValidatorScore,
|
||||
performanceScore: previousEpochPerformanceScore,
|
||||
stakeScore: previousEpochStakeScore,
|
||||
} = getLastEpochScoreAndPerformance(previousEpochData, id);
|
||||
|
||||
return {
|
||||
id,
|
||||
@@ -184,7 +179,7 @@ export const ConsensusValidatorsTable = ({
|
||||
[ValidatorFields.NORMALISED_VOTING_POWER]:
|
||||
getNormalisedVotingPower(votingPower),
|
||||
[ValidatorFields.UNNORMALISED_VOTING_POWER]:
|
||||
getUnnormalisedVotingPower(rawValidatorScore),
|
||||
getUnnormalisedVotingPower(previousEpochValidatorScore),
|
||||
[ValidatorFields.STAKE_SHARE]: stakedTotalPercentage(stakeScore),
|
||||
[ValidatorFields.STAKED_BY_DELEGATES]: formatNumber(
|
||||
toBigNum(stakedByDelegates, decimals),
|
||||
@@ -194,18 +189,19 @@ export const ConsensusValidatorsTable = ({
|
||||
toBigNum(stakedByOperator, decimals),
|
||||
2
|
||||
),
|
||||
[ValidatorFields.PERFORMANCE_SCORE]:
|
||||
getFormattedPerformanceScore(performanceScore).toString(),
|
||||
[ValidatorFields.PERFORMANCE_PENALTY]:
|
||||
getPerformancePenalty(performanceScore),
|
||||
[ValidatorFields.OVERSTAKED_AMOUNT]: overstakedAmount.toString(),
|
||||
[ValidatorFields.PERFORMANCE_SCORE]: getFormattedPerformanceScore(
|
||||
previousEpochPerformanceScore
|
||||
).toString(),
|
||||
[ValidatorFields.PERFORMANCE_PENALTY]: getPerformancePenalty(
|
||||
previousEpochPerformanceScore
|
||||
),
|
||||
[ValidatorFields.OVERSTAKING_PENALTY]: getOverstakingPenalty(
|
||||
overstakedAmount,
|
||||
totalStake
|
||||
previousEpochValidatorScore,
|
||||
previousEpochStakeScore
|
||||
),
|
||||
[ValidatorFields.TOTAL_PENALTIES]: getTotalPenalties(
|
||||
rawValidatorScore,
|
||||
performanceScore,
|
||||
previousEpochValidatorScore,
|
||||
previousEpochPerformanceScore,
|
||||
stakedTotal,
|
||||
totalStake
|
||||
),
|
||||
|
||||
+19
-19
@@ -7,7 +7,6 @@ import { BigNumber } from '../../../../lib/bignumber';
|
||||
import {
|
||||
getFormattedPerformanceScore,
|
||||
getLastEpochScoreAndPerformance,
|
||||
getOverstakedAmount,
|
||||
getOverstakingPenalty,
|
||||
getPerformancePenalty,
|
||||
getTotalPenalties,
|
||||
@@ -82,21 +81,21 @@ export const StandbyPendingValidatorsTable = ({
|
||||
pendingUserStake,
|
||||
userStakeShare,
|
||||
}) => {
|
||||
const { rawValidatorScore, performanceScore } =
|
||||
getLastEpochScoreAndPerformance(previousEpochData, id);
|
||||
const {
|
||||
rawValidatorScore: previousEpochValidatorScore,
|
||||
performanceScore: previousEpochPerformanceScore,
|
||||
stakeScore: previousEpochStakeScore,
|
||||
} = getLastEpochScoreAndPerformance(previousEpochData, id);
|
||||
|
||||
const overstakedAmount = getOverstakedAmount(
|
||||
rawValidatorScore,
|
||||
stakedTotal,
|
||||
totalStake
|
||||
);
|
||||
let individualStakeNeededForPromotion,
|
||||
individualStakeNeededForPromotionDescription;
|
||||
|
||||
if (stakeNeededForPromotion && performanceScore) {
|
||||
if (stakeNeededForPromotion && previousEpochPerformanceScore) {
|
||||
const stakedTotalBigNum = new BigNumber(stakedTotal);
|
||||
const stakeNeededBigNum = new BigNumber(stakeNeededForPromotion);
|
||||
const performanceScoreBigNum = new BigNumber(performanceScore);
|
||||
const performanceScoreBigNum = new BigNumber(
|
||||
previousEpochPerformanceScore
|
||||
);
|
||||
|
||||
const calc = stakeNeededBigNum
|
||||
.dividedBy(performanceScoreBigNum)
|
||||
@@ -142,18 +141,19 @@ export const StandbyPendingValidatorsTable = ({
|
||||
toBigNum(stakedByOperator, decimals),
|
||||
2
|
||||
),
|
||||
[ValidatorFields.PERFORMANCE_SCORE]:
|
||||
getFormattedPerformanceScore(performanceScore).toString(),
|
||||
[ValidatorFields.PERFORMANCE_PENALTY]:
|
||||
getPerformancePenalty(performanceScore),
|
||||
[ValidatorFields.OVERSTAKED_AMOUNT]: overstakedAmount.toString(),
|
||||
[ValidatorFields.PERFORMANCE_SCORE]: getFormattedPerformanceScore(
|
||||
previousEpochPerformanceScore
|
||||
).toString(),
|
||||
[ValidatorFields.PERFORMANCE_PENALTY]: getPerformancePenalty(
|
||||
previousEpochPerformanceScore
|
||||
),
|
||||
[ValidatorFields.OVERSTAKING_PENALTY]: getOverstakingPenalty(
|
||||
overstakedAmount,
|
||||
totalStake
|
||||
previousEpochValidatorScore,
|
||||
previousEpochStakeScore
|
||||
),
|
||||
[ValidatorFields.TOTAL_PENALTIES]: getTotalPenalties(
|
||||
rawValidatorScore,
|
||||
performanceScore,
|
||||
previousEpochValidatorScore,
|
||||
previousEpochPerformanceScore,
|
||||
stakedTotal,
|
||||
totalStake
|
||||
),
|
||||
|
||||
@@ -20,7 +20,6 @@ import { SubHeading } from '../../../components/heading';
|
||||
import {
|
||||
getLastEpochScoreAndPerformance,
|
||||
getNormalisedVotingPower,
|
||||
getOverstakedAmount,
|
||||
getOverstakingPenalty,
|
||||
getPerformancePenalty,
|
||||
getTotalPenalties,
|
||||
@@ -75,15 +74,9 @@ export const ValidatorTable = ({
|
||||
|
||||
const stakedOnNode = toBigNum(node.stakedTotal, decimals);
|
||||
|
||||
const { rawValidatorScore, performanceScore } =
|
||||
const { rawValidatorScore, performanceScore, stakeScore } =
|
||||
getLastEpochScoreAndPerformance(previousEpochData, node.id);
|
||||
|
||||
const overstakedAmount = getOverstakedAmount(
|
||||
rawValidatorScore,
|
||||
stakedTotal,
|
||||
node.stakedTotal
|
||||
);
|
||||
|
||||
const stakePercentage = getStakePercentage(total, stakedOnNode);
|
||||
|
||||
const totalPenaltiesAmount = getTotalPenalties(
|
||||
@@ -245,7 +238,7 @@ export const ValidatorTable = ({
|
||||
|
||||
<Tooltip description={t('OverstakedPenaltyDescription')}>
|
||||
<span data-testid="overstaking-penalty">
|
||||
{getOverstakingPenalty(overstakedAmount, node.stakedTotal)}
|
||||
{getOverstakingPenalty(rawValidatorScore, stakeScore)}
|
||||
</span>
|
||||
</Tooltip>
|
||||
</KeyValueTableRow>
|
||||
|
||||
@@ -4,7 +4,6 @@ import {
|
||||
getNormalisedVotingPower,
|
||||
getUnnormalisedVotingPower,
|
||||
getOverstakingPenalty,
|
||||
getOverstakedAmount,
|
||||
getFormattedPerformanceScore,
|
||||
getPerformancePenalty,
|
||||
getTotalPenalties,
|
||||
@@ -22,9 +21,10 @@ describe('getLastEpochScoreAndPerformance', () => {
|
||||
id: '0x123',
|
||||
rewardScore: {
|
||||
rawValidatorScore: '0.25',
|
||||
performanceScore: '0.75',
|
||||
},
|
||||
rankingScore: {
|
||||
performanceScore: '0.75',
|
||||
stakeScore: '0.25',
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -33,9 +33,10 @@ describe('getLastEpochScoreAndPerformance', () => {
|
||||
id: '0x234',
|
||||
rewardScore: {
|
||||
rawValidatorScore: '0.35',
|
||||
performanceScore: '0.85',
|
||||
},
|
||||
rankingScore: {
|
||||
performanceScore: '0.85',
|
||||
stakeScore: '0.25',
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -50,12 +51,14 @@ describe('getLastEpochScoreAndPerformance', () => {
|
||||
).toEqual({
|
||||
rawValidatorScore: '0.25',
|
||||
performanceScore: '0.75',
|
||||
stakeScore: '0.25',
|
||||
});
|
||||
expect(
|
||||
getLastEpochScoreAndPerformance(mockPreviousEpochData, '0x234')
|
||||
).toEqual({
|
||||
rawValidatorScore: '0.35',
|
||||
performanceScore: '0.85',
|
||||
stakeScore: '0.25',
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -79,40 +82,34 @@ describe('getUnnormalisedVotingPower', () => {
|
||||
});
|
||||
|
||||
describe('getOverstakingPenalty', () => {
|
||||
it('should return the overstaking penalty', () => {
|
||||
expect(
|
||||
getOverstakingPenalty(new BigNumber(100), Number(1000).toString())
|
||||
).toEqual('10.00%');
|
||||
expect(
|
||||
getOverstakingPenalty(new BigNumber(500), Number(2000).toString())
|
||||
).toEqual('25.00%');
|
||||
});
|
||||
});
|
||||
|
||||
describe('getOverstakedAmount', () => {
|
||||
it('should return the overstaked amount', () => {
|
||||
expect(
|
||||
// If a validator score is 0, any amount staked on the node is considered overstaked
|
||||
getOverstakedAmount('0', Number(100).toString(), Number(20).toString())
|
||||
).toEqual(new BigNumber(20));
|
||||
expect(
|
||||
getOverstakedAmount('0.05', Number(100).toString(), Number(20).toString())
|
||||
).toEqual(new BigNumber(15));
|
||||
expect(
|
||||
getOverstakedAmount('0.1', Number(100).toString(), Number(20).toString())
|
||||
).toEqual(new BigNumber(10));
|
||||
expect(
|
||||
getOverstakedAmount('0.15', Number(100).toString(), Number(20).toString())
|
||||
).toEqual(new BigNumber(5));
|
||||
expect(
|
||||
getOverstakedAmount('0.2', Number(100).toString(), Number(20).toString())
|
||||
).toEqual(new BigNumber(0));
|
||||
it('returns "0%" when both arguments are null or undefined', () => {
|
||||
expect(getOverstakingPenalty(null, null)).toBe('0%');
|
||||
expect(getOverstakingPenalty(undefined, undefined)).toBe('0%');
|
||||
expect(getOverstakingPenalty(null, undefined)).toBe('0%');
|
||||
expect(getOverstakingPenalty(undefined, null)).toBe('0%');
|
||||
});
|
||||
|
||||
it('should return 0 if the overstaked amount is negative', () => {
|
||||
expect(
|
||||
getOverstakedAmount('0.8', Number(100).toString(), Number(20).toString())
|
||||
).toEqual(new BigNumber(0));
|
||||
it('returns "0%" when one argument is null or undefined', () => {
|
||||
expect(getOverstakingPenalty('10', null)).toBe('0%');
|
||||
expect(getOverstakingPenalty(null, '20')).toBe('0%');
|
||||
expect(getOverstakingPenalty('10', undefined)).toBe('0%');
|
||||
expect(getOverstakingPenalty(undefined, '20')).toBe('0%');
|
||||
});
|
||||
|
||||
it('returns "0%" when validatorScore or stakeScore is zero', () => {
|
||||
expect(getOverstakingPenalty('0', '20')).toBe('0%');
|
||||
expect(getOverstakingPenalty('10', '0')).toBe('0%');
|
||||
});
|
||||
|
||||
it('returns the correct overstaking penalty', () => {
|
||||
expect(getOverstakingPenalty('0.18', '0.2')).toBe('10.00%');
|
||||
expect(getOverstakingPenalty('0.2', '0.2')).toBe('0.00%');
|
||||
expect(getOverstakingPenalty('0.04', '0.2')).toBe('80.00%');
|
||||
});
|
||||
|
||||
it('handles string numbers with decimals', () => {
|
||||
expect(getOverstakingPenalty('7.5', '15')).toBe('50.00%');
|
||||
expect(getOverstakingPenalty('12.5', '25')).toBe('50.00%');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -15,7 +15,8 @@ export const getLastEpochScoreAndPerformance = (
|
||||
|
||||
return {
|
||||
rawValidatorScore: validator?.rewardScore?.rawValidatorScore,
|
||||
performanceScore: validator?.rankingScore?.performanceScore,
|
||||
performanceScore: validator?.rewardScore?.performanceScore,
|
||||
stakeScore: validator?.rankingScore?.stakeScore,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -42,31 +43,26 @@ export const getPerformancePenalty = (performanceScore?: string) =>
|
||||
2
|
||||
);
|
||||
|
||||
export const getOverstakedAmount = (
|
||||
validatorScore: string | null | undefined,
|
||||
totalStake: string,
|
||||
stakedOnNode: string
|
||||
) => {
|
||||
const toReturn = validatorScore
|
||||
? new BigNumber(stakedOnNode).minus(
|
||||
new BigNumber(validatorScore).times(new BigNumber(totalStake))
|
||||
)
|
||||
: new BigNumber(0);
|
||||
|
||||
return toReturn.isNegative() ? new BigNumber(0) : toReturn;
|
||||
};
|
||||
|
||||
export const getOverstakingPenalty = (
|
||||
overstakedAmount: BigNumber,
|
||||
stakedOnNode: string
|
||||
validatorScore: string | null | undefined,
|
||||
stakeScore: string | null | undefined
|
||||
) => {
|
||||
if (!validatorScore || !stakeScore) {
|
||||
return '0%';
|
||||
}
|
||||
|
||||
// avoid division by zero
|
||||
if (new BigNumber(stakedOnNode).isZero() || overstakedAmount.isZero()) {
|
||||
return '0';
|
||||
if (
|
||||
new BigNumber(validatorScore).isZero() ||
|
||||
new BigNumber(stakeScore).isZero()
|
||||
) {
|
||||
return '0%';
|
||||
}
|
||||
|
||||
return formatNumberPercentage(
|
||||
overstakedAmount.dividedBy(new BigNumber(stakedOnNode)).times(100),
|
||||
new BigNumber(1)
|
||||
.minus(new BigNumber(validatorScore).dividedBy(new BigNumber(stakeScore)))
|
||||
.times(100),
|
||||
2
|
||||
);
|
||||
};
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
"tranche_id": 56,
|
||||
"tranche_start": "2023-04-20T00:00:00.000Z",
|
||||
"tranche_end": "2023-05-20T00:00:00.000Z",
|
||||
"total_added": "10724.25",
|
||||
"total_added": "12533.75",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "10724.25",
|
||||
"locked_amount": "12533.75",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "50",
|
||||
@@ -36,6 +36,26 @@
|
||||
"amount": "51.75",
|
||||
"user": "0x237D23FcA6d7B2530C7614a9cB921CF27924911E",
|
||||
"tx": "0x3e9c304b5ca74d1238cc4ee2f1396812aac6e62eb8674e8be3e01c9ad3e5bcb0"
|
||||
},
|
||||
{
|
||||
"amount": "379.5",
|
||||
"user": "0x6536B87D6a31a37645c2E0E948BB1a2166FAcdaE",
|
||||
"tx": "0x6dc1c78046509fc85f149ad55a0683e059f46d53eab51397ff202c22ee55938f"
|
||||
},
|
||||
{
|
||||
"amount": "138",
|
||||
"user": "0x9f709F2b44e14B2832832FC35aC378e41Bf14bBC",
|
||||
"tx": "0x1b2921c481d2af4dead917173e4fc821ca119bc9408460caff9c25ae09e06a3d"
|
||||
},
|
||||
{
|
||||
"amount": "1154",
|
||||
"user": "0x981D29D939cAa4ADC04A5e44224dBB45539E8730",
|
||||
"tx": "0x3e8baadb612f97fd9fa0b4a8f28c57381d87ff43a083117e19d0332e37869a7f"
|
||||
},
|
||||
{
|
||||
"amount": "138",
|
||||
"user": "0xF2c8658Bad7314c3c3c1FED7e300a1691EC4f98A",
|
||||
"tx": "0xa9db9e09f9841a8cbcaf161bf98d32e67f24c2c162f13c364450487ccaf8ebd6"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
@@ -129,6 +149,66 @@
|
||||
"total_tokens": "51.75",
|
||||
"withdrawn_tokens": "0",
|
||||
"remaining_tokens": "51.75"
|
||||
},
|
||||
{
|
||||
"address": "0x6536B87D6a31a37645c2E0E948BB1a2166FAcdaE",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "379.5",
|
||||
"user": "0x6536B87D6a31a37645c2E0E948BB1a2166FAcdaE",
|
||||
"tranche_id": 56,
|
||||
"tx": "0x6dc1c78046509fc85f149ad55a0683e059f46d53eab51397ff202c22ee55938f"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
"total_tokens": "379.5",
|
||||
"withdrawn_tokens": "0",
|
||||
"remaining_tokens": "379.5"
|
||||
},
|
||||
{
|
||||
"address": "0x9f709F2b44e14B2832832FC35aC378e41Bf14bBC",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "138",
|
||||
"user": "0x9f709F2b44e14B2832832FC35aC378e41Bf14bBC",
|
||||
"tranche_id": 56,
|
||||
"tx": "0x1b2921c481d2af4dead917173e4fc821ca119bc9408460caff9c25ae09e06a3d"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
"total_tokens": "138",
|
||||
"withdrawn_tokens": "0",
|
||||
"remaining_tokens": "138"
|
||||
},
|
||||
{
|
||||
"address": "0x981D29D939cAa4ADC04A5e44224dBB45539E8730",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "1154",
|
||||
"user": "0x981D29D939cAa4ADC04A5e44224dBB45539E8730",
|
||||
"tranche_id": 56,
|
||||
"tx": "0x3e8baadb612f97fd9fa0b4a8f28c57381d87ff43a083117e19d0332e37869a7f"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
"total_tokens": "1154",
|
||||
"withdrawn_tokens": "0",
|
||||
"remaining_tokens": "1154"
|
||||
},
|
||||
{
|
||||
"address": "0xF2c8658Bad7314c3c3c1FED7e300a1691EC4f98A",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "138",
|
||||
"user": "0xF2c8658Bad7314c3c3c1FED7e300a1691EC4f98A",
|
||||
"tranche_id": 56,
|
||||
"tx": "0xa9db9e09f9841a8cbcaf161bf98d32e67f24c2c162f13c364450487ccaf8ebd6"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
"total_tokens": "138",
|
||||
"withdrawn_tokens": "0",
|
||||
"remaining_tokens": "138"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -189,9 +269,9 @@
|
||||
"tranche_id": 54,
|
||||
"tranche_start": "2023-04-06T00:00:00.000Z",
|
||||
"tranche_end": "2023-05-06T00:00:00.000Z",
|
||||
"total_added": "8565",
|
||||
"total_added": "8661",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "8565",
|
||||
"locked_amount": "8515.0394282407400778",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "33",
|
||||
@@ -223,6 +303,11 @@
|
||||
"user": "0xf96afaB11e5617560b9183766470B23F45c38C56",
|
||||
"tx": "0x49ab3f37bda02347cb1966e8fa21885a463f09d0593a890e96b2e36dfb8dec49"
|
||||
},
|
||||
{
|
||||
"amount": "96",
|
||||
"user": "0x6324334064d1d807940191C658d925DA7d323b12",
|
||||
"tx": "0x96b16197328b59556848409bcc4ebf1f71648485fabedde2848461247aa4be32"
|
||||
},
|
||||
{
|
||||
"amount": "111",
|
||||
"user": "0x268070d5EEd5b24E34a5F4C17B5482178b18089D",
|
||||
@@ -396,6 +481,21 @@
|
||||
"withdrawn_tokens": "0",
|
||||
"remaining_tokens": "2523"
|
||||
},
|
||||
{
|
||||
"address": "0x6324334064d1d807940191C658d925DA7d323b12",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "96",
|
||||
"user": "0x6324334064d1d807940191C658d925DA7d323b12",
|
||||
"tranche_id": 54,
|
||||
"tx": "0x96b16197328b59556848409bcc4ebf1f71648485fabedde2848461247aa4be32"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
"total_tokens": "96",
|
||||
"withdrawn_tokens": "0",
|
||||
"remaining_tokens": "96"
|
||||
},
|
||||
{
|
||||
"address": "0x268070d5EEd5b24E34a5F4C17B5482178b18089D",
|
||||
"deposits": [
|
||||
@@ -742,8 +842,8 @@
|
||||
"tranche_start": "2023-03-06T00:00:00.000Z",
|
||||
"tranche_end": "2023-04-06T00:00:00.000Z",
|
||||
"total_added": "14099",
|
||||
"total_removed": "165.10784124668",
|
||||
"locked_amount": "338.514968637992270967",
|
||||
"total_removed": "332.88824447236",
|
||||
"locked_amount": "0",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "30",
|
||||
@@ -1517,6 +1617,16 @@
|
||||
"user": "0x6A228Fffda4D1B3C773b9ce38DA43592581b36FC",
|
||||
"tx": "0x5a8d0a823b77eb011079663279e0f2eaf0bd8773114dd6d5bfe65c2ab47680e6"
|
||||
},
|
||||
{
|
||||
"amount": "27.78040322568",
|
||||
"user": "0x6F32AA5A6198329c16e438512F992a0548C856f9",
|
||||
"tx": "0x47ef65d8ea128dfa3308d25fadf4e3b6b2b95a91f98bd074b268c002babf1edf"
|
||||
},
|
||||
{
|
||||
"amount": "140",
|
||||
"user": "0xF3C6c37B9EBB4D21e8bf119841C0e0e296e3EA04",
|
||||
"tx": "0x3af459fccc854056f4a3a3d0223e5b5fec587f2990c0ec48f0f1be65882e5d96"
|
||||
},
|
||||
{
|
||||
"amount": "14.85013776876",
|
||||
"user": "0x6F32AA5A6198329c16e438512F992a0548C856f9",
|
||||
@@ -1755,6 +1865,12 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "27.78040322568",
|
||||
"user": "0x6F32AA5A6198329c16e438512F992a0548C856f9",
|
||||
"tranche_id": 53,
|
||||
"tx": "0x47ef65d8ea128dfa3308d25fadf4e3b6b2b95a91f98bd074b268c002babf1edf"
|
||||
},
|
||||
{
|
||||
"amount": "14.85013776876",
|
||||
"user": "0x6F32AA5A6198329c16e438512F992a0548C856f9",
|
||||
@@ -1769,8 +1885,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "63",
|
||||
"withdrawn_tokens": "35.00279905878",
|
||||
"remaining_tokens": "27.99720094122"
|
||||
"withdrawn_tokens": "62.78320228446",
|
||||
"remaining_tokens": "0.21679771554"
|
||||
},
|
||||
{
|
||||
"address": "0x8499411Bff99ddE9A02903008F917EEa0E27B42A",
|
||||
@@ -2170,10 +2286,17 @@
|
||||
"tx": "0x46d80a145d2f49ef3152cbfaa6d2bb054deabe21396ab43553a3f076e2db62e1"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "140",
|
||||
"user": "0xF3C6c37B9EBB4D21e8bf119841C0e0e296e3EA04",
|
||||
"tranche_id": 53,
|
||||
"tx": "0x3af459fccc854056f4a3a3d0223e5b5fec587f2990c0ec48f0f1be65882e5d96"
|
||||
}
|
||||
],
|
||||
"total_tokens": "140",
|
||||
"withdrawn_tokens": "0",
|
||||
"remaining_tokens": "140"
|
||||
"withdrawn_tokens": "140",
|
||||
"remaining_tokens": "0"
|
||||
},
|
||||
{
|
||||
"address": "0xEb01fF124D71b6C7E6613fd6E0A86c28C733F008",
|
||||
@@ -3531,7 +3654,7 @@
|
||||
"tranche_end": "2023-12-05T00:00:00.000Z",
|
||||
"total_added": "86666.297",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "57875.1133625658226291517",
|
||||
"locked_amount": "57578.3384572820232579218",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "86666.297",
|
||||
@@ -3597,7 +3720,7 @@
|
||||
"tranche_end": "2023-06-01T00:00:00.000Z",
|
||||
"total_added": "2500",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "779.454746642246625",
|
||||
"locked_amount": "762.286006817256825",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "2500",
|
||||
@@ -3718,7 +3841,7 @@
|
||||
"tranche_end": "2023-09-01T00:00:00.000Z",
|
||||
"total_added": "17500",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "14146.87688707729625",
|
||||
"locked_amount": "14028.00202546296225",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "12500",
|
||||
@@ -3985,7 +4108,7 @@
|
||||
"tranche_end": "2023-08-01T00:00:00.000Z",
|
||||
"total_added": "37500",
|
||||
"total_removed": "11781.2245815",
|
||||
"locked_amount": "24394.53844383057",
|
||||
"locked_amount": "24135.58452271332",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "7500",
|
||||
@@ -4305,7 +4428,7 @@
|
||||
"tranche_end": "2023-12-05T00:00:00.000Z",
|
||||
"total_added": "129999.45",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "57822.30960374848094241",
|
||||
"locked_amount": "57525.8054682240954858435",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "129999.45",
|
||||
@@ -4338,7 +4461,7 @@
|
||||
"tranche_end": "2024-04-01T00:00:00.000Z",
|
||||
"total_added": "54144.7663",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "53515.19367393810504083066",
|
||||
"locked_amount": "53330.29014628881803117649",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "54144.7663",
|
||||
@@ -4371,7 +4494,7 @@
|
||||
"tranche_end": "2023-09-03T00:00:00.000Z",
|
||||
"total_added": "62600",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "25853.68089802130747",
|
||||
"locked_amount": "25639.31718670725918",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "10000",
|
||||
@@ -4564,7 +4687,7 @@
|
||||
"tranche_end": "2023-09-17T00:00:00.000Z",
|
||||
"total_added": "5000",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "2256.7713089802133",
|
||||
"locked_amount": "2239.6496067985795",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "5000",
|
||||
@@ -5083,7 +5206,7 @@
|
||||
"tranche_end": "2023-05-01T00:00:00.000Z",
|
||||
"total_added": "22500",
|
||||
"total_removed": "6357.929999175",
|
||||
"locked_amount": "3200.2589779005528",
|
||||
"locked_amount": "3044.886625230202125",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "7500",
|
||||
@@ -5523,7 +5646,7 @@
|
||||
"tranche_end": "2023-06-02T00:00:00.000Z",
|
||||
"total_added": "1939928.38",
|
||||
"total_removed": "928642.9598472029154",
|
||||
"locked_amount": "306903.608577024413946004",
|
||||
"locked_amount": "300260.63338181247167142",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "1852091.69",
|
||||
@@ -11011,7 +11134,7 @@
|
||||
"tranche_id": 11,
|
||||
"tranche_start": "2021-09-03T00:00:00.000Z",
|
||||
"tranche_end": "2022-09-03T00:00:00.000Z",
|
||||
"total_added": "57213.000000000000000003",
|
||||
"total_added": "57238.000000000000000003",
|
||||
"total_removed": "48157.21518131551",
|
||||
"locked_amount": "0",
|
||||
"deposits": [
|
||||
@@ -11035,6 +11158,11 @@
|
||||
"user": "0x363D3d06d70761c34D6EfEB25E409A9549E6970D",
|
||||
"tx": "0x180cd3aca2d716aa233483a9a52b02e83d9ac88716ca85d998269965c7a01a96"
|
||||
},
|
||||
{
|
||||
"amount": "25",
|
||||
"user": "0x981D29D939cAa4ADC04A5e44224dBB45539E8730",
|
||||
"tx": "0xac528ad2b9d958135e7556c5d9d36ce97eb6fb723dd44b3430374276e0fae9be"
|
||||
},
|
||||
{
|
||||
"amount": "150",
|
||||
"user": "0xEb01fF124D71b6C7E6613fd6E0A86c28C733F008",
|
||||
@@ -22838,6 +22966,21 @@
|
||||
"withdrawn_tokens": "0",
|
||||
"remaining_tokens": "25"
|
||||
},
|
||||
{
|
||||
"address": "0x981D29D939cAa4ADC04A5e44224dBB45539E8730",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "25",
|
||||
"user": "0x981D29D939cAa4ADC04A5e44224dBB45539E8730",
|
||||
"tranche_id": 11,
|
||||
"tx": "0xac528ad2b9d958135e7556c5d9d36ce97eb6fb723dd44b3430374276e0fae9be"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
"total_tokens": "25",
|
||||
"withdrawn_tokens": "0",
|
||||
"remaining_tokens": "25"
|
||||
},
|
||||
{
|
||||
"address": "0xEb01fF124D71b6C7E6613fd6E0A86c28C733F008",
|
||||
"deposits": [
|
||||
@@ -39256,7 +39399,7 @@
|
||||
"tranche_end": "2023-06-05T00:00:00.000Z",
|
||||
"total_added": "3732368.4671",
|
||||
"total_removed": "700133.348465855088393",
|
||||
"locked_amount": "496105.318624601551155638257",
|
||||
"locked_amount": "485897.284061159463725724765",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "1998.95815",
|
||||
@@ -40637,8 +40780,8 @@
|
||||
"tranche_start": "2022-06-05T00:00:00.000Z",
|
||||
"tranche_end": "2023-12-05T00:00:00.000Z",
|
||||
"total_added": "15870102.715470999700000001",
|
||||
"total_removed": "815414.41205294384422952",
|
||||
"locked_amount": "7058845.1924777653448375313192847387510138",
|
||||
"total_removed": "815921.67873801845247952",
|
||||
"locked_amount": "7022648.15733426372108476030466951593836177",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "16249.93",
|
||||
@@ -41182,6 +41325,11 @@
|
||||
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||
"tx": "0xa65322922116e2e0949be9d83e65ef0b1f2d8fe3eb399616a5cbbb7c95593717"
|
||||
},
|
||||
{
|
||||
"amount": "507.26668507460825",
|
||||
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||
"tx": "0x8be0ce3e72ef8b69c5682a9272305c5adfc68fa2d082381f47ae13e917a6cef8"
|
||||
},
|
||||
{
|
||||
"amount": "545.4204142199725",
|
||||
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||
@@ -43218,6 +43366,12 @@
|
||||
"tranche_id": 2,
|
||||
"tx": "0xa65322922116e2e0949be9d83e65ef0b1f2d8fe3eb399616a5cbbb7c95593717"
|
||||
},
|
||||
{
|
||||
"amount": "507.26668507460825",
|
||||
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||
"tranche_id": 2,
|
||||
"tx": "0x8be0ce3e72ef8b69c5682a9272305c5adfc68fa2d082381f47ae13e917a6cef8"
|
||||
},
|
||||
{
|
||||
"amount": "545.4204142199725",
|
||||
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||
@@ -44594,8 +44748,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "259998.8875",
|
||||
"withdrawn_tokens": "143958.431651182737875",
|
||||
"remaining_tokens": "116040.455848817262125"
|
||||
"withdrawn_tokens": "144465.698336257346125",
|
||||
"remaining_tokens": "115533.189163742653875"
|
||||
},
|
||||
{
|
||||
"address": "0x89051CAb67Bc7F8CC44F7e270c6EDaf1EC57676c",
|
||||
@@ -46940,8 +47094,8 @@
|
||||
"tranche_start": "2021-11-05T00:00:00.000Z",
|
||||
"tranche_end": "2023-05-05T00:00:00.000Z",
|
||||
"total_added": "14597706.0446472999",
|
||||
"total_removed": "5807463.612246947184450156",
|
||||
"locked_amount": "795235.584253058282571973568973987",
|
||||
"total_removed": "5808173.326897276766376406",
|
||||
"locked_amount": "761818.71252882815442491758389864",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "129284.449",
|
||||
@@ -47220,6 +47374,11 @@
|
||||
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
|
||||
"tx": "0xcd3480c11e987e702a52413185dcc232b399747ef2fd7529aa46bea02c6f4be5"
|
||||
},
|
||||
{
|
||||
"amount": "709.71465032958192625",
|
||||
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
|
||||
"tx": "0x0464f4416616032385d6cecf639d1b1b8f3d75beab762529d23688456a170602"
|
||||
},
|
||||
{
|
||||
"amount": "755.482067130393772",
|
||||
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
|
||||
@@ -50398,6 +50557,12 @@
|
||||
"tranche_id": 3,
|
||||
"tx": "0xcd3480c11e987e702a52413185dcc232b399747ef2fd7529aa46bea02c6f4be5"
|
||||
},
|
||||
{
|
||||
"amount": "709.71465032958192625",
|
||||
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
|
||||
"tranche_id": 3,
|
||||
"tx": "0x0464f4416616032385d6cecf639d1b1b8f3d75beab762529d23688456a170602"
|
||||
},
|
||||
{
|
||||
"amount": "755.482067130393772",
|
||||
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
|
||||
@@ -53076,8 +53241,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "359123.469575",
|
||||
"withdrawn_tokens": "339010.28213138339642675",
|
||||
"remaining_tokens": "20113.18744361660357325"
|
||||
"withdrawn_tokens": "339719.996781712978353",
|
||||
"remaining_tokens": "19403.472793287021647"
|
||||
},
|
||||
{
|
||||
"address": "0xBdd412797c1B78535Afc5F71503b91fAbD0160fB",
|
||||
@@ -56676,8 +56841,8 @@
|
||||
"tranche_start": "2022-06-05T00:00:00.000Z",
|
||||
"tranche_end": "2023-06-05T00:00:00.000Z",
|
||||
"total_added": "472355.6199999996",
|
||||
"total_removed": "41316.3370079701949",
|
||||
"locked_amount": "78610.723594969487558672821308984",
|
||||
"total_removed": "41511.9808435861949",
|
||||
"locked_amount": "76993.20216677886451988387975646",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "3000",
|
||||
@@ -63366,6 +63531,21 @@
|
||||
"user": "0x9405F540EcC1204801De5C4444D06386BD6693F0",
|
||||
"tx": "0x0df6ec04cbdda41c8649a5e360ec541d14371e3877d82e1404308180024ede02"
|
||||
},
|
||||
{
|
||||
"amount": "152.077625568",
|
||||
"user": "0x7345AaA0D0e4C4A46d921fA9323973956F2b7392",
|
||||
"tx": "0xf2737eb145aea0c573c2f604ae4b840fd56358a89f1470e37a26fff91df2e38d"
|
||||
},
|
||||
{
|
||||
"amount": "11.682496196",
|
||||
"user": "0xcB555C5602cC0b2434A27d277e14Cb5C7bF4Ead1",
|
||||
"tx": "0xc757d9ea4d28133266b723ac41ba64d3bc5e1f4498e08b24745bf84e203009e0"
|
||||
},
|
||||
{
|
||||
"amount": "31.883713852",
|
||||
"user": "0x0e199b123f71f964d6567869B6B849C1f255A855",
|
||||
"tx": "0xf44b1dc9f007be2df82ffea31d470f6f959b19d16d03aff3d4811ed0e065b72e"
|
||||
},
|
||||
{
|
||||
"amount": "154.812094114",
|
||||
"user": "0x27e2254A2A8c9c9D1321E5Fe64cAD88e7A4f0ba7",
|
||||
@@ -81235,6 +81415,12 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "31.883713852",
|
||||
"user": "0x0e199b123f71f964d6567869B6B849C1f255A855",
|
||||
"tranche_id": 5,
|
||||
"tx": "0xf44b1dc9f007be2df82ffea31d470f6f959b19d16d03aff3d4811ed0e065b72e"
|
||||
},
|
||||
{
|
||||
"amount": "32.691171992",
|
||||
"user": "0x0e199b123f71f964d6567869B6B849C1f255A855",
|
||||
@@ -81297,8 +81483,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "400",
|
||||
"withdrawn_tokens": "302.731798576",
|
||||
"remaining_tokens": "97.268201424"
|
||||
"withdrawn_tokens": "334.615512428",
|
||||
"remaining_tokens": "65.384487572"
|
||||
},
|
||||
{
|
||||
"address": "0x74Da54F44975a1C224ABb5CAB8e5fc38a268B425",
|
||||
@@ -81739,6 +81925,12 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "152.077625568",
|
||||
"user": "0x7345AaA0D0e4C4A46d921fA9323973956F2b7392",
|
||||
"tranche_id": 5,
|
||||
"tx": "0xf2737eb145aea0c573c2f604ae4b840fd56358a89f1470e37a26fff91df2e38d"
|
||||
},
|
||||
{
|
||||
"amount": "94.45296804",
|
||||
"user": "0x7345AaA0D0e4C4A46d921fA9323973956F2b7392",
|
||||
@@ -81789,8 +81981,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "1200",
|
||||
"withdrawn_tokens": "850.0164003",
|
||||
"remaining_tokens": "349.9835997"
|
||||
"withdrawn_tokens": "1002.094025868",
|
||||
"remaining_tokens": "197.905974132"
|
||||
},
|
||||
{
|
||||
"address": "0x47181cf36aDFb0b5dB7EfDB123f403D890607841",
|
||||
@@ -81988,6 +82180,12 @@
|
||||
"tranche_id": 5,
|
||||
"tx": "0x9d4c99fdeee2d95caee8d6725f6796f8e02f8a9fd2d911a8e151b2665e192ebc"
|
||||
},
|
||||
{
|
||||
"amount": "11.682496196",
|
||||
"user": "0xcB555C5602cC0b2434A27d277e14Cb5C7bF4Ead1",
|
||||
"tranche_id": 5,
|
||||
"tx": "0xc757d9ea4d28133266b723ac41ba64d3bc5e1f4498e08b24745bf84e203009e0"
|
||||
},
|
||||
{
|
||||
"amount": "19.74474886",
|
||||
"user": "0xcB555C5602cC0b2434A27d277e14Cb5C7bF4Ead1",
|
||||
@@ -82020,8 +82218,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "400",
|
||||
"withdrawn_tokens": "322.776395228",
|
||||
"remaining_tokens": "77.223604772"
|
||||
"withdrawn_tokens": "334.458891424",
|
||||
"remaining_tokens": "65.541108576"
|
||||
},
|
||||
{
|
||||
"address": "0x3738bec36216eA2F11B954891C65AAd1Bc852156",
|
||||
@@ -141708,6 +141906,11 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "0",
|
||||
"user": "0x759C9ABABA492500c4c730bEB568B5b851Dec2c7",
|
||||
"tx": "0x840e84fd087fe976bfc1321c1fd60e63f7820e0d1b247c631ebc7268666945f5"
|
||||
},
|
||||
{
|
||||
"amount": "38999.8338",
|
||||
"user": "0x759C9ABABA492500c4c730bEB568B5b851Dec2c7",
|
||||
@@ -141973,6 +142176,12 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "0",
|
||||
"user": "0x759C9ABABA492500c4c730bEB568B5b851Dec2c7",
|
||||
"tranche_id": 9,
|
||||
"tx": "0x840e84fd087fe976bfc1321c1fd60e63f7820e0d1b247c631ebc7268666945f5"
|
||||
},
|
||||
{
|
||||
"amount": "38999.8338",
|
||||
"user": "0x759C9ABABA492500c4c730bEB568B5b851Dec2c7",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import * as Schema from '@vegaprotocol/types';
|
||||
import { aliasGQLQuery } from '@vegaprotocol/cypress';
|
||||
import { aliasGQLQuery, checkSorting } from '@vegaprotocol/cypress';
|
||||
import { marketsQuery } from '@vegaprotocol/mock';
|
||||
import { getDateTimeFormat } from '@vegaprotocol/utils';
|
||||
|
||||
@@ -85,6 +85,7 @@ describe('markets table', { tags: '@smoke' }, () => {
|
||||
cy.getByTestId('view-market-list-link')
|
||||
.should('have.attr', 'href', '#/markets/all')
|
||||
.click();
|
||||
|
||||
cy.get('[data-testid="All markets"]').should(
|
||||
'have.attr',
|
||||
'data-state',
|
||||
@@ -117,6 +118,85 @@ describe('markets table', { tags: '@smoke' }, () => {
|
||||
`${Cypress.env('VEGA_TOKEN_URL')}/proposals/propose/new-market`
|
||||
);
|
||||
});
|
||||
it('proposed markets tab should be sorted properly', () => {
|
||||
cy.getByTestId('view-market-list-link').click();
|
||||
cy.get('[data-testid="Proposed markets"]').click();
|
||||
const marketColDefault = [
|
||||
'ETHUSD',
|
||||
'LINKUSD',
|
||||
'ETHUSD',
|
||||
'ETHDAI.MF21',
|
||||
'AAPL.MF21',
|
||||
'BTCUSD.MF21',
|
||||
'TSLA.QM21',
|
||||
'AAVEDAI.MF21',
|
||||
'ETHBTC.QM21',
|
||||
'UNIDAI.MF21',
|
||||
];
|
||||
const marketColAsc = [
|
||||
'AAPL.MF21',
|
||||
'AAVEDAI.MF21',
|
||||
'BTCUSD.MF21',
|
||||
'ETHBTC.QM21',
|
||||
'ETHDAI.MF21',
|
||||
'ETHUSD',
|
||||
'ETHUSD',
|
||||
'LINKUSD',
|
||||
'TSLA.QM21',
|
||||
'UNIDAI.MF21',
|
||||
];
|
||||
const marketColDesc = [
|
||||
'UNIDAI.MF21',
|
||||
'TSLA.QM21',
|
||||
'LINKUSD',
|
||||
'ETHUSD',
|
||||
'ETHUSD',
|
||||
'ETHDAI.MF21',
|
||||
'ETHBTC.QM21',
|
||||
'BTCUSD.MF21',
|
||||
'AAVEDAI.MF21',
|
||||
'AAPL.MF21',
|
||||
];
|
||||
checkSorting('market', marketColDefault, marketColAsc, marketColDesc);
|
||||
|
||||
const stateColDefault = [
|
||||
'Open',
|
||||
'Passed',
|
||||
'Waiting for Node Vote',
|
||||
'Open',
|
||||
'Passed',
|
||||
'Open',
|
||||
'Passed',
|
||||
'Open',
|
||||
'Waiting for Node Vote',
|
||||
'Open',
|
||||
];
|
||||
const stateColAsc = [
|
||||
'Open',
|
||||
'Open',
|
||||
'Open',
|
||||
'Open',
|
||||
'Open',
|
||||
'Passed',
|
||||
'Passed',
|
||||
'Passed',
|
||||
'Waiting for Node Vote',
|
||||
'Waiting for Node Vote',
|
||||
];
|
||||
const stateColDesc = [
|
||||
'Waiting for Node Vote',
|
||||
'Waiting for Node Vote',
|
||||
'Passed',
|
||||
'Passed',
|
||||
'Passed',
|
||||
'Open',
|
||||
'Open',
|
||||
'Open',
|
||||
'Open',
|
||||
'Open',
|
||||
];
|
||||
checkSorting('state', stateColDefault, stateColAsc, stateColDesc);
|
||||
});
|
||||
|
||||
it('opening auction subsets should be properly displayed', () => {
|
||||
cy.mockTradingPage(
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
import { tooltipMapping } from '@vegaprotocol/market-info';
|
||||
import {
|
||||
addDecimalsFormatNumber,
|
||||
createDocsLinks,
|
||||
formatNumberPercentage,
|
||||
} from '@vegaprotocol/utils';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
@@ -23,6 +24,7 @@ import {
|
||||
Tabs,
|
||||
Link as UiToolkitLink,
|
||||
Indicator,
|
||||
ExternalLink,
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
import { useVegaWallet } from '@vegaprotocol/wallet';
|
||||
import { memo, useCallback, useEffect, useRef, useState } from 'react';
|
||||
@@ -37,6 +39,7 @@ import { Link, useParams } from 'react-router-dom';
|
||||
import { Links, Routes } from '../../pages/client-router';
|
||||
|
||||
import { useMarket, useStaticMarketData } from '@vegaprotocol/market-list';
|
||||
import { useEnvironment } from '@vegaprotocol/environment';
|
||||
|
||||
const enum LiquidityTabs {
|
||||
Active = 'active',
|
||||
@@ -144,6 +147,7 @@ const LiquidityViewHeader = memo(({ marketId }: { marketId?: string }) => {
|
||||
market?.tradableInstrument.instrument.product.settlementAsset.decimals || 0;
|
||||
const symbol =
|
||||
market?.tradableInstrument.instrument.product.settlementAsset.symbol;
|
||||
const { VEGA_DOCS_URL } = useEnvironment();
|
||||
|
||||
const { params } = useNetworkParams([
|
||||
NetworkParams.market_liquidity_stakeToCcyVolume,
|
||||
@@ -211,6 +215,13 @@ const LiquidityViewHeader = memo(({ marketId }: { marketId?: string }) => {
|
||||
<HeaderStat heading={t('Market ID')}>
|
||||
<div className="break-word">{marketId}</div>
|
||||
</HeaderStat>
|
||||
<HeaderStat heading={t('Learn more')}>
|
||||
{VEGA_DOCS_URL && (
|
||||
<ExternalLink href={createDocsLinks(VEGA_DOCS_URL).LIQUIDITY}>
|
||||
{t('Providing liquidity')}
|
||||
</ExternalLink>
|
||||
)}
|
||||
</HeaderStat>
|
||||
</Header>
|
||||
);
|
||||
});
|
||||
|
||||
@@ -8,6 +8,7 @@ import type { MarketData } from '@vegaprotocol/market-list';
|
||||
import { marketDataProvider, marketProvider } from '@vegaprotocol/market-list';
|
||||
import { HeaderStat } from '../header';
|
||||
import {
|
||||
ExternalLink,
|
||||
Indicator,
|
||||
KeyValueTable,
|
||||
KeyValueTableRow,
|
||||
@@ -18,9 +19,11 @@ import { useCheckLiquidityStatus } from '@vegaprotocol/liquidity';
|
||||
import { AuctionTrigger, MarketTradingMode } from '@vegaprotocol/types';
|
||||
import {
|
||||
addDecimalsFormatNumber,
|
||||
createDocsLinks,
|
||||
formatNumberPercentage,
|
||||
} from '@vegaprotocol/utils';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import { useEnvironment } from '@vegaprotocol/environment';
|
||||
|
||||
interface Props {
|
||||
marketId?: string;
|
||||
@@ -44,6 +47,8 @@ export const MarketLiquiditySupplied = ({
|
||||
params.market_liquidity_targetstake_triggering_ratio
|
||||
);
|
||||
|
||||
const { VEGA_DOCS_URL } = useEnvironment();
|
||||
|
||||
const variables = useMemo(
|
||||
() => ({
|
||||
marketId: marketId || '',
|
||||
@@ -126,6 +131,14 @@ export const MarketLiquiditySupplied = ({
|
||||
<Link href={`/#/liquidity/${marketId}`} data-testid="view-liquidity-link">
|
||||
{t('View liquidity provision table')}
|
||||
</Link>
|
||||
{VEGA_DOCS_URL && (
|
||||
<ExternalLink
|
||||
href={createDocsLinks(VEGA_DOCS_URL).LIQUIDITY}
|
||||
className="mt-2"
|
||||
>
|
||||
{t('Learn about providing liquidity')}
|
||||
</ExternalLink>
|
||||
)}
|
||||
{showMessage && (
|
||||
<p className="mt-4">
|
||||
{t(
|
||||
|
||||
@@ -23,6 +23,7 @@ import {
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
|
||||
import { Links, Routes } from '../../pages/client-router';
|
||||
import { createDocsLinks } from '@vegaprotocol/utils';
|
||||
|
||||
export const Navbar = ({
|
||||
theme = 'system',
|
||||
@@ -37,6 +38,7 @@ export const Navbar = ({
|
||||
const tradingPath = marketId
|
||||
? Links[Routes.MARKET](marketId)
|
||||
: Links[Routes.MARKET]();
|
||||
|
||||
return (
|
||||
<Navigation
|
||||
appName="Console"
|
||||
@@ -89,7 +91,9 @@ export const Navbar = ({
|
||||
<NavigationContent>
|
||||
<NavigationList>
|
||||
<NavigationItem>
|
||||
<NavExternalLink href={VEGA_DOCS_URL}>
|
||||
<NavExternalLink
|
||||
href={createDocsLinks(VEGA_DOCS_URL).NEW_TO_VEGA}
|
||||
>
|
||||
{t('Docs')}
|
||||
</NavExternalLink>
|
||||
</NavigationItem>
|
||||
|
||||
@@ -52,6 +52,9 @@ export const checkSorting = (
|
||||
cy.get(`[col-id="${column}"]`).click();
|
||||
});
|
||||
checkSortChange(orderTabDesc, column);
|
||||
cy.get('.ag-header-container').within(() => {
|
||||
cy.get(`[col-id="${column}"]`).click();
|
||||
});
|
||||
};
|
||||
|
||||
const checkSortChange = (tabsArr: string[], column: string) => {
|
||||
|
||||
@@ -61,6 +61,7 @@ beforeEach(() => {
|
||||
submitDeposit: jest.fn(),
|
||||
submitFaucet: jest.fn(),
|
||||
onDisconnect: jest.fn(),
|
||||
handleAmountChange: jest.fn(),
|
||||
approveTxId: null,
|
||||
faucetTxId: null,
|
||||
isFaucetable: true,
|
||||
|
||||
@@ -25,11 +25,9 @@ import {
|
||||
import { useVegaWallet } from '@vegaprotocol/wallet';
|
||||
import { useWeb3React } from '@web3-react/core';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import type { ButtonHTMLAttributes, ReactNode } from 'react';
|
||||
import { useState } from 'react';
|
||||
import { useMemo } from 'react';
|
||||
import { useWatch } from 'react-hook-form';
|
||||
import { Controller, useForm } from 'react-hook-form';
|
||||
import type { ButtonHTMLAttributes, ChangeEvent, ReactNode } from 'react';
|
||||
import { useMemo, useState } from 'react';
|
||||
import { useWatch, Controller, useForm } from 'react-hook-form';
|
||||
import { DepositLimits } from './deposit-limits';
|
||||
import { useAssetDetailsDialogStore } from '@vegaprotocol/assets';
|
||||
import {
|
||||
@@ -40,6 +38,7 @@ import {
|
||||
import type { DepositBalances } from './use-deposit-balances';
|
||||
import { FaucetNotification } from './faucet-notification';
|
||||
import { ApproveNotification } from './approve-notification';
|
||||
import { usePersistentDeposit } from './use-persistent-deposit';
|
||||
|
||||
interface FormFields {
|
||||
asset: string;
|
||||
@@ -53,6 +52,7 @@ export interface DepositFormProps {
|
||||
selectedAsset?: Asset;
|
||||
balances: DepositBalances | null;
|
||||
onSelectAsset: (assetId: string) => void;
|
||||
handleAmountChange: (amount: string) => void;
|
||||
onDisconnect: () => void;
|
||||
submitApprove: () => void;
|
||||
approveTxId: number | null;
|
||||
@@ -71,6 +71,7 @@ export const DepositForm = ({
|
||||
selectedAsset,
|
||||
balances,
|
||||
onSelectAsset,
|
||||
handleAmountChange,
|
||||
onDisconnect,
|
||||
submitApprove,
|
||||
submitDeposit,
|
||||
@@ -85,6 +86,8 @@ export const DepositForm = ({
|
||||
const { pubKey, pubKeys: _pubKeys } = useVegaWallet();
|
||||
const [approveNotificationIntent, setApproveNotificationIntent] =
|
||||
useState<Intent>(Intent.Warning);
|
||||
const [persistedDeposit] = usePersistentDeposit(selectedAsset?.id);
|
||||
|
||||
const {
|
||||
register,
|
||||
handleSubmit,
|
||||
@@ -95,7 +98,8 @@ export const DepositForm = ({
|
||||
} = useForm<FormFields>({
|
||||
defaultValues: {
|
||||
to: pubKey ? pubKey : undefined,
|
||||
asset: selectedAsset?.id || '',
|
||||
asset: selectedAsset?.id,
|
||||
amount: persistedDeposit.amount,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -333,6 +337,9 @@ export const DepositForm = ({
|
||||
return maxSafe(balances?.balance || new BigNumber(0))(v);
|
||||
},
|
||||
},
|
||||
onChange: (e: ChangeEvent<HTMLInputElement>) => {
|
||||
handleAmountChange(e.target.value || '');
|
||||
},
|
||||
})}
|
||||
/>
|
||||
{errors.amount?.message && (
|
||||
@@ -343,10 +350,9 @@ export const DepositForm = ({
|
||||
{selectedAsset && balances && (
|
||||
<UseButton
|
||||
onClick={() => {
|
||||
setValue(
|
||||
'amount',
|
||||
balances.balance.toFixed(selectedAsset.decimals)
|
||||
);
|
||||
const amount = balances.balance.toFixed(selectedAsset.decimals);
|
||||
setValue('amount', amount);
|
||||
handleAmountChange(amount);
|
||||
clearErrors('amount');
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -5,7 +5,7 @@ import { prepend0x } from '@vegaprotocol/smart-contracts';
|
||||
import sortBy from 'lodash/sortBy';
|
||||
import { useSubmitApproval } from './use-submit-approval';
|
||||
import { useSubmitFaucet } from './use-submit-faucet';
|
||||
import { useState } from 'react';
|
||||
import { useCallback, useState } from 'react';
|
||||
import { useDepositBalances } from './use-deposit-balances';
|
||||
import { useDepositDialog } from './deposit-dialog';
|
||||
import type { Asset } from '@vegaprotocol/assets';
|
||||
@@ -14,6 +14,7 @@ import {
|
||||
useBridgeContract,
|
||||
useEthereumConfig,
|
||||
} from '@vegaprotocol/web3';
|
||||
import { usePersistentDeposit } from './use-persistent-deposit';
|
||||
|
||||
interface DepositManagerProps {
|
||||
assetId?: string;
|
||||
@@ -28,7 +29,9 @@ export const DepositManager = ({
|
||||
}: DepositManagerProps) => {
|
||||
const createEthTransaction = useEthTransactionStore((state) => state.create);
|
||||
const { config } = useEthereumConfig();
|
||||
const [assetId, setAssetId] = useState(initialAssetId);
|
||||
const [persistentDeposit, savePersistentDeposit] =
|
||||
usePersistentDeposit(initialAssetId);
|
||||
const [assetId, setAssetId] = useState(persistentDeposit?.assetId);
|
||||
const asset = assets.find((a) => a.id === assetId);
|
||||
const bridgeContract = useBridgeContract();
|
||||
const closeDepositDialog = useDepositDialog((state) => state.close);
|
||||
@@ -65,17 +68,26 @@ export const DepositManager = ({
|
||||
closeDepositDialog();
|
||||
};
|
||||
|
||||
const onAmountChange = useCallback(
|
||||
(amount: string) => {
|
||||
savePersistentDeposit({ ...persistentDeposit, amount });
|
||||
},
|
||||
[savePersistentDeposit, persistentDeposit]
|
||||
);
|
||||
|
||||
return (
|
||||
<DepositForm
|
||||
selectedAsset={asset}
|
||||
onDisconnect={reset}
|
||||
onSelectAsset={(id) => {
|
||||
setAssetId(id);
|
||||
savePersistentDeposit({ assetId: id });
|
||||
// When we change asset, also clear the tracked faucet/approve transactions so
|
||||
// we dont render stale UI
|
||||
approve.reset();
|
||||
faucet.reset();
|
||||
}}
|
||||
handleAmountChange={onAmountChange}
|
||||
assets={sortBy(assets, 'name')}
|
||||
submitApprove={approve.perform}
|
||||
submitDeposit={submitDeposit}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
import { renderHook, waitFor, act } from '@testing-library/react';
|
||||
import { usePersistentDeposit } from './use-persistent-deposit';
|
||||
|
||||
describe('usePersistenDeposit', () => {
|
||||
it('should return empty data', () => {
|
||||
const { result } = renderHook(() => usePersistentDeposit());
|
||||
expect(result.current).toEqual([{ assetId: '' }, expect.any(Function)]);
|
||||
});
|
||||
it('should return empty and properly saved data', async () => {
|
||||
const aId = 'test';
|
||||
const retObj = { assetId: 'test', amount: '1.00000' };
|
||||
const { result } = renderHook(() => usePersistentDeposit(aId));
|
||||
expect(result.current).toEqual([{ assetId: 'test' }, expect.any(Function)]);
|
||||
await act(() => {
|
||||
result.current[1](retObj);
|
||||
});
|
||||
await waitFor(() => {
|
||||
expect(result.current[0]).toEqual(retObj);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,42 @@
|
||||
import { useMemo } from 'react';
|
||||
import { create } from 'zustand';
|
||||
import { persist } from 'zustand/middleware';
|
||||
import { immer } from 'zustand/middleware/immer';
|
||||
|
||||
const STORAGE_KEY = 'vega_deposit_store';
|
||||
interface PersistedDeposit {
|
||||
assetId: string;
|
||||
amount?: string;
|
||||
}
|
||||
type PersistedDepositData = Record<string, PersistedDeposit>;
|
||||
|
||||
const usePersistentDepositStore = create<{
|
||||
deposits: PersistedDepositData;
|
||||
saveValue: (entry: PersistedDeposit) => void;
|
||||
lastVisited?: PersistedDeposit;
|
||||
}>()(
|
||||
persist(
|
||||
immer((set) => ({
|
||||
deposits: {},
|
||||
saveValue: (entry) =>
|
||||
set((state) => {
|
||||
const oldValue = state.deposits[entry.assetId] || null;
|
||||
state.deposits[entry.assetId] = { ...oldValue, ...entry };
|
||||
state.lastVisited = { ...oldValue, ...entry };
|
||||
return state;
|
||||
}),
|
||||
})),
|
||||
{ name: STORAGE_KEY }
|
||||
)
|
||||
);
|
||||
|
||||
export const usePersistentDeposit = (
|
||||
assetId?: string
|
||||
): [PersistedDeposit, (entry: PersistedDeposit) => void] => {
|
||||
const { deposits, lastVisited, saveValue } = usePersistentDepositStore();
|
||||
const discoveredData = useMemo(() => {
|
||||
return deposits[assetId || ''] || lastVisited || { assetId: assetId || '' };
|
||||
}, [deposits, lastVisited, assetId]);
|
||||
|
||||
return [discoveredData, saveValue];
|
||||
};
|
||||
@@ -11,12 +11,13 @@ import {
|
||||
AgGridDynamic as AgGrid,
|
||||
PriceFlashCell,
|
||||
MarketNameCell,
|
||||
SetFilter,
|
||||
} from '@vegaprotocol/datagrid';
|
||||
import { ButtonLink } from '@vegaprotocol/ui-toolkit';
|
||||
import { AgGridColumn } from 'ag-grid-react';
|
||||
import type { AgGridReact } from 'ag-grid-react';
|
||||
import * as Schema from '@vegaprotocol/types';
|
||||
import type { MarketMaybeWithData, MarketFieldsFragment } from '../../';
|
||||
import type { MarketMaybeWithData } from '../../';
|
||||
import { useAssetDetailsDialogStore } from '@vegaprotocol/assets';
|
||||
|
||||
const { MarketTradingMode, AuctionTrigger } = Schema;
|
||||
@@ -33,7 +34,6 @@ export const MarketListTable = forwardRef<
|
||||
return (
|
||||
<AgGrid
|
||||
style={{ width: '100%', height: '100%' }}
|
||||
overlayNoRowsTemplate={t('No markets')}
|
||||
getRowId={getRowId}
|
||||
ref={ref}
|
||||
defaultColDef={{
|
||||
@@ -43,7 +43,7 @@ export const MarketListTable = forwardRef<
|
||||
filter: true,
|
||||
filterParams: { buttons: ['reset'] },
|
||||
}}
|
||||
suppressCellFocus={true}
|
||||
suppressCellFocus
|
||||
components={{ PriceFlashCell, MarketNameCell }}
|
||||
{...props}
|
||||
>
|
||||
@@ -59,11 +59,11 @@ export const MarketListTable = forwardRef<
|
||||
/>
|
||||
<AgGridColumn
|
||||
headerName={t('Trading mode')}
|
||||
field="data"
|
||||
field="tradingMode"
|
||||
minWidth={170}
|
||||
valueGetter={({
|
||||
valueFormatter={({
|
||||
data,
|
||||
}: VegaValueGetterParams<MarketMaybeWithData, 'data'>) => {
|
||||
}: VegaValueFormatterParams<MarketMaybeWithData, 'data'>) => {
|
||||
if (!data?.data) return undefined;
|
||||
const { trigger } = data.data;
|
||||
const { tradingMode } = data;
|
||||
@@ -75,14 +75,22 @@ export const MarketListTable = forwardRef<
|
||||
- ${Schema.AuctionTriggerMapping[trigger]}`
|
||||
: Schema.MarketTradingModeMapping[tradingMode];
|
||||
}}
|
||||
filter={SetFilter}
|
||||
filterParams={{
|
||||
set: Schema.MarketTradingModeMapping,
|
||||
}}
|
||||
/>
|
||||
<AgGridColumn
|
||||
headerName={t('Status')}
|
||||
field="state"
|
||||
valueGetter={({
|
||||
valueFormatter={({
|
||||
data,
|
||||
}: VegaValueGetterParams<MarketFieldsFragment, 'state'>) => {
|
||||
return data?.state ? Schema.MarketStateMapping[data?.state] : '-';
|
||||
}: VegaValueFormatterParams<MarketMaybeWithData, 'state'>) => {
|
||||
return data?.state ? Schema.MarketStateMapping[data.state] : '-';
|
||||
}}
|
||||
filter={SetFilter}
|
||||
filterParams={{
|
||||
set: Schema.MarketStateMapping,
|
||||
}}
|
||||
/>
|
||||
<AgGridColumn
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import type { MouseEvent } from 'react';
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import type { AgGridReact } from 'ag-grid-react';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
|
||||
import { MarketListTable } from './market-list-table';
|
||||
@@ -12,15 +14,24 @@ interface MarketsContainerProps {
|
||||
}
|
||||
|
||||
export const MarketsContainer = ({ onSelect }: MarketsContainerProps) => {
|
||||
const gridRef = useRef<AgGridReact | null>(null);
|
||||
const [dataCount, setDataCount] = useState(0);
|
||||
const { data, error, loading, reload } = useDataProvider({
|
||||
dataProvider,
|
||||
skipUpdates: true,
|
||||
variables: undefined,
|
||||
});
|
||||
useEffect(() => {
|
||||
setDataCount(gridRef.current?.api?.getModel().getRowCount() ?? 0);
|
||||
}, [data]);
|
||||
const onFilterChanged = useCallback(() => {
|
||||
setDataCount(gridRef.current?.api?.getModel().getRowCount() ?? 0);
|
||||
}, []);
|
||||
return (
|
||||
<div className="h-full relative">
|
||||
<MarketListTable
|
||||
rowData={error ? [] : data}
|
||||
ref={gridRef}
|
||||
rowData={data}
|
||||
suppressLoadingOverlay
|
||||
suppressNoRowsOverlay
|
||||
onCellClicked={(cellEvent: CellClickedEvent) => {
|
||||
@@ -40,6 +51,7 @@ export const MarketsContainer = ({ onSelect }: MarketsContainerProps) => {
|
||||
);
|
||||
}}
|
||||
onMarketClick={onSelect}
|
||||
onFilterChanged={onFilterChanged}
|
||||
/>
|
||||
<div className="pointer-events-none absolute inset-0">
|
||||
<AsyncRenderer
|
||||
@@ -47,6 +59,7 @@ export const MarketsContainer = ({ onSelect }: MarketsContainerProps) => {
|
||||
error={error}
|
||||
data={data}
|
||||
noDataMessage={t('No markets')}
|
||||
noDataCondition={() => !dataCount}
|
||||
reload={reload}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -91,6 +91,6 @@ describe('ProposalsList', () => {
|
||||
await waitFor(() => {
|
||||
expect(container).toBeInTheDocument();
|
||||
});
|
||||
expect(screen.getByText('No Rows To Show')).toBeInTheDocument();
|
||||
expect(screen.getByText('No markets')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,13 +1,21 @@
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
|
||||
import { AgGridDynamic as AgGrid } from '@vegaprotocol/datagrid';
|
||||
import { useDataProvider } from '@vegaprotocol/react-helpers';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import * as Types from '@vegaprotocol/types';
|
||||
import { proposalsDataProvider } from '../proposals-data-provider';
|
||||
import { useCallback, useRef } from 'react';
|
||||
import type { AgGridReact } from 'ag-grid-react';
|
||||
import { useColumnDefs } from './use-column-defs';
|
||||
import type { ProposalListFieldsFragment } from '../proposals-data-provider/__generated__/Proposals';
|
||||
|
||||
// prevent cutting filter windows by auto-height layout
|
||||
const CUSTOM_GRID_STYLES = `
|
||||
.ag-layout-auto-height {
|
||||
min-height: 200px !important;
|
||||
}
|
||||
`;
|
||||
|
||||
export const getNewMarketProposals = (data: ProposalListFieldsFragment[]) =>
|
||||
data.filter((proposal) =>
|
||||
[
|
||||
@@ -19,6 +27,7 @@ export const getNewMarketProposals = (data: ProposalListFieldsFragment[]) =>
|
||||
|
||||
export const ProposalsList = () => {
|
||||
const gridRef = useRef<AgGridReact | null>(null);
|
||||
const [dataCount, setDataCount] = useState(0);
|
||||
const handleOnGridReady = useCallback(() => {
|
||||
gridRef.current?.api?.sizeColumnsToFit();
|
||||
}, [gridRef]);
|
||||
@@ -30,22 +39,37 @@ export const ProposalsList = () => {
|
||||
});
|
||||
const filteredData = getNewMarketProposals(data || []);
|
||||
const { columnDefs, defaultColDef } = useColumnDefs();
|
||||
useEffect(() => {
|
||||
setDataCount(gridRef.current?.api?.getModel().getRowCount() ?? 0);
|
||||
}, [filteredData]);
|
||||
const onFilterChanged = useCallback(() => {
|
||||
setDataCount(gridRef.current?.api?.getModel().getRowCount() ?? 0);
|
||||
}, []);
|
||||
return (
|
||||
<AsyncRenderer
|
||||
loading={loading}
|
||||
error={error}
|
||||
data={filteredData}
|
||||
reload={reload}
|
||||
>
|
||||
<div className="relative">
|
||||
<AgGrid
|
||||
ref={gridRef}
|
||||
className="w-full h-full"
|
||||
domLayout="autoHeight"
|
||||
className="min-w-full"
|
||||
columnDefs={columnDefs}
|
||||
rowData={filteredData}
|
||||
defaultColDef={defaultColDef}
|
||||
onGridReady={handleOnGridReady}
|
||||
suppressLoadingOverlay
|
||||
suppressNoRowsOverlay
|
||||
onFilterChanged={onFilterChanged}
|
||||
customThemeParams={CUSTOM_GRID_STYLES}
|
||||
/>
|
||||
</AsyncRenderer>
|
||||
<div className="pointer-events-none absolute inset-0">
|
||||
<AsyncRenderer
|
||||
loading={loading}
|
||||
error={error}
|
||||
data={filteredData}
|
||||
noDataMessage={t('No markets')}
|
||||
noDataCondition={() => !dataCount}
|
||||
reload={reload}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { useMemo } from 'react';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import type { ColDef } from 'ag-grid-community';
|
||||
import { DateRangeFilter, SetFilter } from '@vegaprotocol/datagrid';
|
||||
import { useEnvironment } from '@vegaprotocol/environment';
|
||||
import { getDateTimeFormat } from '@vegaprotocol/utils';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
@@ -73,6 +74,10 @@ export const useColumnDefs = () => {
|
||||
value,
|
||||
}: VegaValueFormatterParams<ProposalListFieldsFragment, 'state'>) =>
|
||||
value ? ProposalStateMapping[value] : '-',
|
||||
filter: SetFilter,
|
||||
filterParams: {
|
||||
set: ProposalStateMapping,
|
||||
},
|
||||
},
|
||||
{
|
||||
colId: 'voting',
|
||||
@@ -99,6 +104,7 @@ export const useColumnDefs = () => {
|
||||
}
|
||||
return '-';
|
||||
},
|
||||
filter: false,
|
||||
},
|
||||
{
|
||||
colId: 'closing-date',
|
||||
@@ -110,6 +116,7 @@ export const useColumnDefs = () => {
|
||||
ProposalListFieldsFragment,
|
||||
'terms.closingDatetime'
|
||||
>) => (value ? getDateTimeFormat().format(new Date(value)) : '-'),
|
||||
filter: DateRangeFilter,
|
||||
},
|
||||
{
|
||||
colId: 'enactment-date',
|
||||
@@ -121,13 +128,18 @@ export const useColumnDefs = () => {
|
||||
ProposalListFieldsFragment,
|
||||
'terms.enactmentDatetime'
|
||||
>) => (value ? getDateTimeFormat().format(new Date(value)) : '-'),
|
||||
filter: DateRangeFilter,
|
||||
},
|
||||
];
|
||||
}, [VEGA_TOKEN_URL, requiredMajorityPercentage]);
|
||||
const defaultColDef: ColDef = useMemo(() => {
|
||||
return {
|
||||
sortable: false,
|
||||
sortable: true,
|
||||
cellClass: cellCss,
|
||||
flex: 1,
|
||||
resizable: true,
|
||||
filter: true,
|
||||
filterParams: { buttons: ['reset'] },
|
||||
};
|
||||
}, []);
|
||||
return useMemo(
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
*/
|
||||
|
||||
export const createDocsLinks = (docsUrl: string) => ({
|
||||
NEW_TO_VEGA: `${docsUrl}/concepts/new-to-vega`,
|
||||
AUCTION_TYPE_OPENING: `${docsUrl}/concepts/trading-on-vega/trading-modes#auction-type-opening`,
|
||||
AUCTION_TYPE_LIQUIDITY_MONITORING: `${docsUrl}/concepts/trading-on-vega/trading-modes#auction-type-liquidity-monitoring`,
|
||||
AUCTION_TYPE_PRICE_MONITORING: `${docsUrl}/concepts/trading-on-vega/trading-modes#auction-type-price-monitoring`,
|
||||
@@ -14,6 +15,7 @@ export const createDocsLinks = (docsUrl: string) => ({
|
||||
NODE_OPERATORS: `${docsUrl}/node-operators`,
|
||||
LOSS_SOCIALIZATION: `${docsUrl}/concepts/trading-on-vega/market-protections#loss-socialisation`,
|
||||
POSITION_RESOLUTION: `${docsUrl}/concepts/trading-on-vega/market-protections#position-resolution`,
|
||||
LIQUIDITY: `${docsUrl}/concepts/liquidity/provision`,
|
||||
});
|
||||
|
||||
export const ExternalLinks = {
|
||||
|
||||
Reference in New Issue
Block a user