feat: update queries to use window length

This commit is contained in:
Matthew Russell
2023-10-25 12:37:36 -07:00
parent 69bc4c6f31
commit fa26b35e83
5 changed files with 143 additions and 67 deletions
@@ -1,23 +1,32 @@
query Fees($partyId: ID!, $volumeDiscountStatsEpochs: Int!) {
epoch {
id
}
query DiscountPrograms {
currentReferralProgram {
benefitTiers {
minimumEpochs
minimumRunningNotionalTakerVolume
referralDiscountFactor
}
windowLength
}
currentVolumeDiscountProgram {
benefitTiers {
minimumRunningNotionalTakerVolume
volumeDiscountFactor
}
windowLength
}
}
query Fees(
$partyId: ID!
$volumeDiscountEpochs: Int!
$referralDiscountEpochs: Int!
) {
epoch {
id
}
volumeDiscountStats(
partyId: $partyId
pagination: { last: $volumeDiscountStatsEpochs }
pagination: { last: $volumeDiscountEpochs }
) {
edges {
node {
@@ -27,16 +36,20 @@ query Fees($partyId: ID!, $volumeDiscountStatsEpochs: Int!) {
}
}
}
referralSetReferees(referee: $partyId, aggregationDays: 7) {
referralSetReferees(referee: $partyId) {
edges {
node {
atEpoch
}
}
}
referralSetStats(partyId: $partyId) {
referralSetStats(
partyId: $partyId
pagination: { last: $referralDiscountEpochs }
) {
edges {
node {
atEpoch
discountFactor
referralSetRunningNotionalTakerVolume
}
+52 -11
View File
@@ -3,36 +3,75 @@ import * as Types from '@vegaprotocol/types';
import { gql } from '@apollo/client';
import * as Apollo from '@apollo/client';
const defaultOptions = {} as const;
export type DiscountProgramsQueryVariables = Types.Exact<{ [key: string]: never; }>;
export type DiscountProgramsQuery = { __typename?: 'Query', currentReferralProgram?: { __typename?: 'CurrentReferralProgram', windowLength: number, benefitTiers: Array<{ __typename?: 'BenefitTier', minimumEpochs: number, minimumRunningNotionalTakerVolume: string, referralDiscountFactor: string }> } | null, currentVolumeDiscountProgram?: { __typename?: 'VolumeDiscountProgram', windowLength: number, benefitTiers: Array<{ __typename?: 'VolumeBenefitTier', minimumRunningNotionalTakerVolume: string, volumeDiscountFactor: string }> } | null };
export type FeesQueryVariables = Types.Exact<{
partyId: Types.Scalars['ID'];
volumeDiscountStatsEpochs: Types.Scalars['Int'];
volumeDiscountEpochs: Types.Scalars['Int'];
referralDiscountEpochs: Types.Scalars['Int'];
}>;
export type FeesQuery = { __typename?: 'Query', epoch: { __typename?: 'Epoch', id: string }, currentReferralProgram?: { __typename?: 'CurrentReferralProgram', benefitTiers: Array<{ __typename?: 'BenefitTier', minimumEpochs: number, minimumRunningNotionalTakerVolume: string, referralDiscountFactor: string }> } | null, currentVolumeDiscountProgram?: { __typename?: 'VolumeDiscountProgram', benefitTiers: Array<{ __typename?: 'VolumeBenefitTier', minimumRunningNotionalTakerVolume: string, volumeDiscountFactor: string }> } | null, volumeDiscountStats: { __typename?: 'VolumeDiscountStatsConnection', edges: Array<{ __typename?: 'VolumeDiscountStatsEdge', node: { __typename?: 'VolumeDiscountStats', atEpoch: number, discountFactor: string, runningVolume: string } } | null> }, referralSetReferees: { __typename?: 'ReferralSetRefereeConnection', edges: Array<{ __typename?: 'ReferralSetRefereeEdge', node: { __typename?: 'ReferralSetReferee', atEpoch: number } } | null> }, referralSetStats: { __typename?: 'ReferralSetStatsConnection', edges: Array<{ __typename?: 'ReferralSetStatsEdge', node: { __typename?: 'ReferralSetStats', discountFactor: string, referralSetRunningNotionalTakerVolume: string } } | null> } };
export type FeesQuery = { __typename?: 'Query', epoch: { __typename?: 'Epoch', id: string }, volumeDiscountStats: { __typename?: 'VolumeDiscountStatsConnection', edges: Array<{ __typename?: 'VolumeDiscountStatsEdge', node: { __typename?: 'VolumeDiscountStats', atEpoch: number, discountFactor: string, runningVolume: string } } | null> }, referralSetReferees: { __typename?: 'ReferralSetRefereeConnection', edges: Array<{ __typename?: 'ReferralSetRefereeEdge', node: { __typename?: 'ReferralSetReferee', atEpoch: number } } | null> }, referralSetStats: { __typename?: 'ReferralSetStatsConnection', edges: Array<{ __typename?: 'ReferralSetStatsEdge', node: { __typename?: 'ReferralSetStats', atEpoch: number, discountFactor: string, referralSetRunningNotionalTakerVolume: string } } | null> } };
export const FeesDocument = gql`
query Fees($partyId: ID!, $volumeDiscountStatsEpochs: Int!) {
epoch {
id
}
export const DiscountProgramsDocument = gql`
query DiscountPrograms {
currentReferralProgram {
benefitTiers {
minimumEpochs
minimumRunningNotionalTakerVolume
referralDiscountFactor
}
windowLength
}
currentVolumeDiscountProgram {
benefitTiers {
minimumRunningNotionalTakerVolume
volumeDiscountFactor
}
windowLength
}
}
`;
/**
* __useDiscountProgramsQuery__
*
* To run a query within a React component, call `useDiscountProgramsQuery` and pass it any options that fit your needs.
* When your component renders, `useDiscountProgramsQuery` returns an object from Apollo Client that contains loading, error, and data properties
* you can use to render your UI.
*
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
*
* @example
* const { data, loading, error } = useDiscountProgramsQuery({
* variables: {
* },
* });
*/
export function useDiscountProgramsQuery(baseOptions?: Apollo.QueryHookOptions<DiscountProgramsQuery, DiscountProgramsQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useQuery<DiscountProgramsQuery, DiscountProgramsQueryVariables>(DiscountProgramsDocument, options);
}
export function useDiscountProgramsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<DiscountProgramsQuery, DiscountProgramsQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useLazyQuery<DiscountProgramsQuery, DiscountProgramsQueryVariables>(DiscountProgramsDocument, options);
}
export type DiscountProgramsQueryHookResult = ReturnType<typeof useDiscountProgramsQuery>;
export type DiscountProgramsLazyQueryHookResult = ReturnType<typeof useDiscountProgramsLazyQuery>;
export type DiscountProgramsQueryResult = Apollo.QueryResult<DiscountProgramsQuery, DiscountProgramsQueryVariables>;
export const FeesDocument = gql`
query Fees($partyId: ID!, $volumeDiscountEpochs: Int!, $referralDiscountEpochs: Int!) {
epoch {
id
}
volumeDiscountStats(
partyId: $partyId
pagination: {last: $volumeDiscountStatsEpochs}
pagination: {last: $volumeDiscountEpochs}
) {
edges {
node {
@@ -42,16 +81,17 @@ export const FeesDocument = gql`
}
}
}
referralSetReferees(referee: $partyId, aggregationDays: 7) {
referralSetReferees(referee: $partyId) {
edges {
node {
atEpoch
}
}
}
referralSetStats(partyId: $partyId) {
referralSetStats(partyId: $partyId, pagination: {last: $referralDiscountEpochs}) {
edges {
node {
atEpoch
discountFactor
referralSetRunningNotionalTakerVolume
}
@@ -73,7 +113,8 @@ export const FeesDocument = gql`
* const { data, loading, error } = useFeesQuery({
* variables: {
* partyId: // value for 'partyId'
* volumeDiscountStatsEpochs: // value for 'volumeDiscountStatsEpochs'
* volumeDiscountEpochs: // value for 'volumeDiscountEpochs'
* referralDiscountEpochs: // value for 'referralDiscountEpochs'
* },
* });
*/
@@ -3,7 +3,7 @@ import maxBy from 'lodash/maxBy';
import minBy from 'lodash/minBy';
import classNames from 'classnames';
import { t } from '@vegaprotocol/i18n';
import { useFeesQuery } from './__generated__/Fees';
import { useDiscountProgramsQuery, useFeesQuery } from './__generated__/Fees';
import { useVegaWallet } from '@vegaprotocol/wallet';
import {
useNetworkParams,
@@ -27,41 +27,53 @@ import { Splash } from '@vegaprotocol/ui-toolkit';
* - Remove hardcoded partyId
*/
const VOLUME_EPOCHS = 7;
export const FeesContainer = () => {
const { pubKey } = useVegaWallet();
const { params } = useNetworkParams([
NetworkParams.market_fee_factors_makerFee,
NetworkParams.market_fee_factors_infrastructureFee,
]);
const { data: markets } = useMarketList();
const {
data: programData,
loading: programLoading,
error: programError,
} = useDiscountProgramsQuery();
const volumeDiscountEpochs =
programData?.currentVolumeDiscountProgram?.windowLength || 1;
const referralDiscountEpochs =
programData?.currentReferralProgram?.windowLength || 1;
const { data, loading, error } = useFeesQuery({
variables: {
partyId:
// TODO: change for pubkey
'9e2445e0e98c0e0ca1c260baaab1e7a2f1b9c7256c27196be6e614ee44d1a1e7',
volumeDiscountStatsEpochs: VOLUME_EPOCHS,
volumeDiscountEpochs,
referralDiscountEpochs,
},
skip: !pubKey,
skip: !pubKey || !programData,
});
const { data: markets } = useMarketList();
const { volumeDiscount, volumeTierIndex, volumeLastEpoch, volumeTiers } =
const { volumeDiscount, volumeTierIndex, volumeInWindow, volumeTiers } =
useVolumeStats(
data?.volumeDiscountStats,
data?.currentVolumeDiscountProgram
programData?.currentVolumeDiscountProgram
);
const {
referralDiscount,
referralVolume,
referralVolumeInWindow,
referralTierIndex,
referralTiers,
epochsInSet,
} = useReferralStats(
data?.referralSetStats,
data?.referralSetReferees,
data?.currentReferralProgram,
programData?.currentReferralProgram,
data?.epoch
);
@@ -82,7 +94,7 @@ export const FeesContainer = () => {
}
// TODO: skeleton loading states
if (loading || !data) {
if (loading || programLoading) {
return <p>Loading...</p>;
}
@@ -103,13 +115,15 @@ export const FeesContainer = () => {
<CurrentVolume
tiers={volumeTiers}
tierIndex={volumeTierIndex}
lastEpochVolume={volumeLastEpoch}
windowLengthVolume={volumeInWindow}
epochs={volumeDiscountEpochs}
/>
</FeeCard>
<FeeCard title={t('Referral benefits')} className="sm:col-span-2">
<ReferralBenefits
setRunningNotionalTakerVolume={referralVolume}
setRunningNotionalTakerVolume={referralVolumeInWindow}
epochsInSet={epochsInSet}
epochs={referralDiscountEpochs}
/>
</FeeCard>
<FeeCard
@@ -119,7 +133,7 @@ export const FeesContainer = () => {
<VolumeTiers
tiers={volumeTiers}
tierIndex={volumeTierIndex}
lastEpochVolume={volumeLastEpoch}
lastEpochVolume={volumeInWindow}
/>
</FeeCard>
<FeeCard
@@ -234,24 +248,31 @@ const TradingFees = ({
const CurrentVolume = ({
tiers,
tierIndex,
lastEpochVolume,
windowLengthVolume,
epochs,
}: {
tiers?: Array<{ minimumRunningNotionalTakerVolume: string }>;
tierIndex: number;
lastEpochVolume: number;
windowLengthVolume: number;
epochs: number;
}) => {
// TODO sum windowLength volume
let requiredForNextTier = 0;
if (tiers && tierIndex) {
const nextTier = tiers[tierIndex - 1];
requiredForNextTier = nextTier
? Number(nextTier.minimumRunningNotionalTakerVolume) - lastEpochVolume
? Number(nextTier.minimumRunningNotionalTakerVolume) - windowLengthVolume
: 0;
}
return (
<div>
<Stat value={formatNumber(lastEpochVolume)} text={t('Past 7 epochs')} />
<Stat
value={formatNumber(windowLengthVolume)}
text={t('Past %s epochs', epochs.toString())}
/>
{requiredForNextTier > 0 && (
<Stat
value={formatNumber(requiredForNextTier)}
@@ -265,16 +286,21 @@ const CurrentVolume = ({
const ReferralBenefits = ({
epochsInSet,
setRunningNotionalTakerVolume,
epochs,
}: {
epochsInSet: number;
setRunningNotionalTakerVolume: number;
epochs: number;
}) => {
return (
<div>
<Stat
// all sets volume (not just current party)
value={formatNumber(setRunningNotionalTakerVolume)}
text={'Combined running notional over the last epoch'}
text={t(
'Combined running notional over the %s epochs',
epochs.toString()
)}
/>
<Stat value={epochsInSet} text={t('epochs in referral set')} />
</div>
@@ -1,17 +1,18 @@
import compact from 'lodash/compact';
import maxBy from 'lodash/maxBy';
import { getReferralBenefitTier } from './utils';
import type { FeesQuery } from './__generated__/Fees';
import type { DiscountProgramsQuery, FeesQuery } from './__generated__/Fees';
export const useReferralStats = (
setStats?: FeesQuery['referralSetStats'],
setReferees?: FeesQuery['referralSetReferees'],
program?: FeesQuery['currentReferralProgram'],
program?: DiscountProgramsQuery['currentReferralProgram'],
epoch?: FeesQuery['epoch']
) => {
if (!setStats || !setReferees || !program || !epoch) {
return {
referralDiscount: 0,
referralVolume: 0,
referralVolumeInWindow: 0,
referralTierIndex: -1,
referralTiers: [],
epochsInSet: 0,
@@ -21,31 +22,29 @@ export const useReferralStats = (
const referralSetsStats = compact(setStats.edges).map((e) => e.node);
const referralSets = compact(setReferees.edges).map((e) => e.node);
if (referralSets.length > 1 || referralSetsStats.length > 1) {
throw new Error('more than one referral set for user');
}
const referralSet = maxBy(referralSets, (s) => s.atEpoch);
const referralStats = maxBy(referralSetsStats, (s) => s.atEpoch);
const referralSet = referralSets[0];
const referralStats = referralSetsStats[0];
const epochsInSet = referralSet ? Number(epoch.id) - referralSet.atEpoch : 0;
const epochsInSet = Number(epoch.id) - referralSet.atEpoch;
const referralDiscount = Number(referralStats.discountFactor || 0);
const referralDiscount = Number(referralStats?.discountFactor || 0);
const referralVolumeInWindow = Number(
referralStats?.referralSetRunningNotionalTakerVolume || 0
);
const referralTiers = [...program.benefitTiers].reverse();
const referralTierIndex = getReferralBenefitTier(
epochsInSet,
Number(referralStats.referralSetRunningNotionalTakerVolume),
referralTiers
);
const referralVolume = Number(
referralStats.referralSetRunningNotionalTakerVolume
);
const referralTierIndex = referralStats
? getReferralBenefitTier(
epochsInSet,
Number(referralStats.referralSetRunningNotionalTakerVolume),
referralTiers
)
: -1;
return {
referralDiscount,
referralVolume,
referralVolumeInWindow,
referralTierIndex,
referralTiers,
epochsInSet,
@@ -1,17 +1,17 @@
import compact from 'lodash/compact';
import maxBy from 'lodash/maxBy';
import { getVolumeTier } from './utils';
import type { FeesQuery } from './__generated__/Fees';
import type { DiscountProgramsQuery, FeesQuery } from './__generated__/Fees';
export const useVolumeStats = (
stats?: FeesQuery['volumeDiscountStats'],
program?: FeesQuery['currentVolumeDiscountProgram']
program?: DiscountProgramsQuery['currentVolumeDiscountProgram']
) => {
if (!stats || !program) {
return {
volumeDiscount: 0,
volumeTierIndex: -1,
volumeLastEpoch: 0,
volumeInWindow: 0,
volumeTiers: [],
};
}
@@ -20,20 +20,17 @@ export const useVolumeStats = (
const volumeDiscount = Number(volumeStats[0].discountFactor || 0);
const lastEpochVolumeStats = stats
? maxBy(volumeStats, (s) => s.atEpoch)
: undefined;
const volumeLastEpoch = Number(lastEpochVolumeStats?.runningVolume || 0);
const lastEpochStats = maxBy(volumeStats, (s) => s.atEpoch);
const volumeInWindow = Number(lastEpochStats?.runningVolume || 0);
const volumeTiers = [...program.benefitTiers].reverse();
const volumeTierIndex = getVolumeTier(volumeLastEpoch, volumeTiers);
const volumeTierIndex = getVolumeTier(volumeInWindow, volumeTiers);
return {
volumeDiscount,
volumeTierIndex,
volumeLastEpoch,
volumeInWindow,
volumeTiers,
};
};