diff --git a/apps/governance-e2e/.env b/apps/governance-e2e/.env
index b61fc86228..bad2c3f30c 100644
--- a/apps/governance-e2e/.env
+++ b/apps/governance-e2e/.env
@@ -24,6 +24,7 @@ NX_SUCCESSOR_MARKETS=true
NX_PRODUCT_PERPETUALS=true
NX_REFERRALS=true
NX_UPDATE_MARKET_STATE=true
+NX_VOLUME_DISCOUNTS=true
NX_VEGA_EXPLORER_URL=https://explorer.fairground.wtf
NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn
diff --git a/apps/governance-e2e/.env.devnet b/apps/governance-e2e/.env.devnet
index b104124da3..9f282982b9 100644
--- a/apps/governance-e2e/.env.devnet
+++ b/apps/governance-e2e/.env.devnet
@@ -7,3 +7,4 @@ NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/m
NX_PRODUCT_PERPETUALS=true
NX_UPDATE_MARKET_STATE=true
NX_REFERRALS=true
+NX_VOLUME_DISCOUNTS=true
diff --git a/apps/governance-e2e/.env.mainnet b/apps/governance-e2e/.env.mainnet
index de9fecb201..23d3520517 100644
--- a/apps/governance-e2e/.env.mainnet
+++ b/apps/governance-e2e/.env.mainnet
@@ -7,3 +7,4 @@ NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/m
NX_PRODUCT_PERPETUALS=false
NX_UPDATE_MARKET_STATE=false
NX_REFERRALS=false
+NX_VOLUME_DISCOUNTS=false
diff --git a/apps/governance-e2e/.env.testnet b/apps/governance-e2e/.env.testnet
index ec606e1014..6c0a4a11ca 100644
--- a/apps/governance-e2e/.env.testnet
+++ b/apps/governance-e2e/.env.testnet
@@ -7,3 +7,4 @@ NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/m
NX_PRODUCT_PERPETUALS=true
NX_UPDATE_MARKET_STATE=true
NX_REFERRALS=true
+NX_VOLUME_DISCOUNTS=true
diff --git a/apps/governance/.env b/apps/governance/.env
index 4016db77b6..97fcb79ea4 100644
--- a/apps/governance/.env
+++ b/apps/governance/.env
@@ -37,3 +37,4 @@ NX_PRODUCT_PERPETUALS=false
NX_UPDATE_MARKET_STATE=false
NX_REFERRALS=false
NX_GOVERNANCE_TRANSFERS=false
+NX_VOLUME_DISCOUNTS=false
diff --git a/apps/governance/.env.capsule b/apps/governance/.env.capsule
index 5dd459a064..e70efca5ec 100644
--- a/apps/governance/.env.capsule
+++ b/apps/governance/.env.capsule
@@ -36,3 +36,4 @@ NX_METAMASK_SNAPS=false
NX_PRODUCT_PERPETUALS=true
NX_UPDATE_MARKET_STATE=true
NX_REFERRALS=true
+NX_VOLUME_DISCOUNTS=true
diff --git a/apps/governance/.env.devnet b/apps/governance/.env.devnet
index 5616a4821c..019dbda7d3 100644
--- a/apps/governance/.env.devnet
+++ b/apps/governance/.env.devnet
@@ -28,3 +28,4 @@ NX_METAMASK_SNAPS=true
NX_PRODUCT_PERPETUALS=true
NX_UPDATE_MARKET_STATE=true
NX_REFERRALS=true
+NX_VOLUME_DISCOUNTS=true
diff --git a/apps/governance/.env.mainnet b/apps/governance/.env.mainnet
index d06633a3c9..4afaabacd4 100644
--- a/apps/governance/.env.mainnet
+++ b/apps/governance/.env.mainnet
@@ -27,3 +27,4 @@ NX_METAMASK_SNAPS=false
NX_PRODUCT_PERPETUALS=false
NX_UPDATE_MARKET_STATE=false
NX_REFERRALS=false
+NX_VOLUME_DISCOUNTS=false
diff --git a/apps/governance/.env.mainnet-mirror b/apps/governance/.env.mainnet-mirror
index f09518a6d4..24af456f41 100644
--- a/apps/governance/.env.mainnet-mirror
+++ b/apps/governance/.env.mainnet-mirror
@@ -26,3 +26,4 @@ NX_METAMASK_SNAPS=false
NX_PRODUCT_PERPETUALS=false
NX_UPDATE_MARKET_STATE=false
NX_REFERRALS=false
+NX_VOLUME_DISCOUNTS=false
diff --git a/apps/governance/.env.stagnet1 b/apps/governance/.env.stagnet1
index b919954478..a67956b478 100644
--- a/apps/governance/.env.stagnet1
+++ b/apps/governance/.env.stagnet1
@@ -25,3 +25,4 @@ NX_PRODUCT_PERPETUALS=true
NX_UPDATE_MARKET_STATE=true
NX_REFERRALS=true
NX_GOVERNANCE_TRANSFERS=true
+NX_VOLUME_DISCOUNTS=true
diff --git a/apps/governance/.env.testnet b/apps/governance/.env.testnet
index 305473b452..ac0d64db94 100644
--- a/apps/governance/.env.testnet
+++ b/apps/governance/.env.testnet
@@ -29,3 +29,4 @@ NX_METAMASK_SNAPS=true
NX_PRODUCT_PERPETUALS=true
NX_UPDATE_MARKET_STATE=true
NX_REFERRALS=true
+NX_VOLUME_DISCOUNTS=true
diff --git a/apps/governance/.env.validators-testnet b/apps/governance/.env.validators-testnet
index 693723078a..f8f57ed8ce 100644
--- a/apps/governance/.env.validators-testnet
+++ b/apps/governance/.env.validators-testnet
@@ -25,3 +25,4 @@ NX_METAMASK_SNAPS=false
NX_PRODUCT_PERPETUALS=false
NX_UPDATE_MARKET_STATE=false
NX_REFERRALS=false
+NX_VOLUME_DISCOUNTS=false
diff --git a/apps/governance/src/i18n/translations/dev.json b/apps/governance/src/i18n/translations/dev.json
index 2ce6aa073b..e2dfc5a796 100644
--- a/apps/governance/src/i18n/translations/dev.json
+++ b/apps/governance/src/i18n/translations/dev.json
@@ -710,6 +710,7 @@
"UpdateMarketProposal": "Update market proposal",
"UpdateMarketStateProposal": "Update market state proposal",
"UpdateReferralProgramProposal": "Update referral program proposal",
+ "UpdateVolumeDiscountProgramProposal": "Update volume discount program proposal",
"MarketChange": "Market change",
"MarketStateChange": "Market state change",
"MarketDetails": "Market details",
@@ -734,6 +735,7 @@
"UpdateMarket": "Update market",
"UpdateMarketState": "Update market state",
"UpdateReferralProgram": "Update referral program",
+ "UpdateVolumeDiscountProgram": "Update volume discount program",
"NewAsset": "New asset",
"UpdateAsset": "Update asset",
"AssetID": "Asset ID",
@@ -910,5 +912,7 @@
"WindowLength": "Window length",
"WindowLengthDescription": "Number of epochs over which to evaluate a referral set's running volume",
"EndOfProgramTimestamp": "End of program",
- "EndOfProgramTimestampDescription": "Time after which when the current epoch ends, the programs will end and benefits will be disabled."
+ "EndOfProgramTimestampDescription": "Time after which when the current epoch ends, the programs will end and benefits will be disabled.",
+ "BenefitTierVolumeDiscountFactor": "Volume discount factor",
+ "BenefitTierVolumeDiscountFactorDescription": "Discount given to those in this benefit tier"
}
diff --git a/apps/governance/src/routes/home/index.tsx b/apps/governance/src/routes/home/index.tsx
index 6ae4df1855..3977a57432 100644
--- a/apps/governance/src/routes/home/index.tsx
+++ b/apps/governance/src/routes/home/index.tsx
@@ -189,6 +189,7 @@ const GovernanceHome = ({ name }: RouteChildProps) => {
includeNewMarketProductFields: !!FLAGS.PRODUCT_PERPETUALS,
includeUpdateMarketStates: !!FLAGS.UPDATE_MARKET_STATE,
includeUpdateReferralPrograms: !!FLAGS.REFERRALS,
+ includeUpdateVolumeDiscountPrograms: !!FLAGS.VOLUME_DISCOUNTS,
},
});
diff --git a/apps/governance/src/routes/proposals/components/proposal-detail-header/proposal-header.tsx b/apps/governance/src/routes/proposals/components/proposal-detail-header/proposal-header.tsx
index d8595b5f82..6ed92e8ce0 100644
--- a/apps/governance/src/routes/proposals/components/proposal-detail-header/proposal-header.tsx
+++ b/apps/governance/src/routes/proposals/components/proposal-detail-header/proposal-header.tsx
@@ -103,6 +103,11 @@ export const ProposalHeader = ({
fallbackTitle = t('UpdateReferralProgramProposal');
break;
}
+ case 'UpdateVolumeDiscountProgram': {
+ proposalType = 'UpdateVolumeDiscountProgram';
+ fallbackTitle = t('UpdateVolumeDiscountProgramProposal');
+ break;
+ }
case 'NewAsset': {
proposalType = 'NewAsset';
fallbackTitle = t('NewAssetProposal');
diff --git a/apps/governance/src/routes/proposals/components/proposal-referral-program-details/proposal-referral-program-details.spec.tsx b/apps/governance/src/routes/proposals/components/proposal-referral-program-details/proposal-referral-program-details.spec.tsx
index 838a8fd8c0..b9382a9c9c 100644
--- a/apps/governance/src/routes/proposals/components/proposal-referral-program-details/proposal-referral-program-details.spec.tsx
+++ b/apps/governance/src/routes/proposals/components/proposal-referral-program-details/proposal-referral-program-details.spec.tsx
@@ -1,6 +1,5 @@
import { render, screen } from '@testing-library/react';
import {
- formatEndOfProgramTimestamp,
formatMinimumRunningNotionalTakerVolume,
formatReferralDiscountFactor,
formatReferralRewardFactor,
@@ -18,13 +17,16 @@ jest.mock('../../../../contexts/app-state/app-state-context', () => ({
}),
}));
-describe('ProposalReferralProgramDetails helper functions', () => {
- it('should format end of program timestamp correctly', () => {
- const input = '2023-01-01T12:00:00Z';
- const formatted = formatEndOfProgramTimestamp(input);
- expect(formatted).toBe('01 January 2023 12:00 (GMT)');
- });
+beforeEach(() => {
+ jest.useFakeTimers();
+ jest.setSystemTime(0);
+});
+afterEach(() => {
+ jest.useRealTimers();
+});
+
+describe('ProposalReferralProgramDetails helper functions', () => {
it('should format minimum running notional taker volume correctly', () => {
const input = '1000';
const formatted = formatMinimumRunningNotionalTakerVolume(input);
diff --git a/apps/governance/src/routes/proposals/components/proposal-volume-discount-program-details/index.tsx b/apps/governance/src/routes/proposals/components/proposal-volume-discount-program-details/index.tsx
new file mode 100644
index 0000000000..bb76a884b7
--- /dev/null
+++ b/apps/governance/src/routes/proposals/components/proposal-volume-discount-program-details/index.tsx
@@ -0,0 +1 @@
+export * from './proposal-volume-discount-program-details';
diff --git a/apps/governance/src/routes/proposals/components/proposal-volume-discount-program-details/proposal-volume-discount-program-details.spec.tsx b/apps/governance/src/routes/proposals/components/proposal-volume-discount-program-details/proposal-volume-discount-program-details.spec.tsx
new file mode 100644
index 0000000000..57a8f0791d
--- /dev/null
+++ b/apps/governance/src/routes/proposals/components/proposal-volume-discount-program-details/proposal-volume-discount-program-details.spec.tsx
@@ -0,0 +1,114 @@
+import { render, screen } from '@testing-library/react';
+import { ProposalVolumeDiscountProgramDetails } from './proposal-volume-discount-program-details';
+import { generateProposal } from '../../test-helpers/generate-proposals';
+
+jest.mock('../../../../contexts/app-state/app-state-context', () => ({
+ useAppState: () => ({
+ appState: {
+ decimals: 2,
+ },
+ }),
+}));
+
+const mockReferralProposal = generateProposal({
+ terms: {
+ change: {
+ __typename: 'UpdateVolumeDiscountProgram',
+ benefitTiers: [
+ {
+ minimumRunningNotionalTakerVolume: '10000',
+ volumeDiscountFactor: '0.05',
+ },
+ {
+ minimumRunningNotionalTakerVolume: '50000',
+ volumeDiscountFactor: '0.1',
+ },
+ {
+ minimumRunningNotionalTakerVolume: '100000',
+ volumeDiscountFactor: '0.15',
+ },
+ {
+ minimumRunningNotionalTakerVolume: '250000',
+ volumeDiscountFactor: '0.2',
+ },
+ {
+ minimumRunningNotionalTakerVolume: '500000',
+ volumeDiscountFactor: '0.25',
+ },
+ {
+ minimumRunningNotionalTakerVolume: '1000000',
+ volumeDiscountFactor: '0.3',
+ },
+ {
+ minimumRunningNotionalTakerVolume: '1500000',
+ volumeDiscountFactor: '0.35',
+ },
+ {
+ minimumRunningNotionalTakerVolume: '2000000',
+ volumeDiscountFactor: '0.4',
+ },
+ ],
+ endOfProgramTimestamp: '1970-01-01T00:00:01.791568493Z',
+ windowLength: 7,
+ },
+ },
+});
+
+describe('ProposalVolumeDiscountProgramDetails', () => {
+ it('should not render if proposal is null', () => {
+ render();
+ expect(
+ screen.queryByTestId('proposal-volume-discount-program-details')
+ ).toBeNull();
+ });
+
+ it('should not render if __typename is not UpdateVolumeDiscountProgram', () => {
+ const updateMarketProposal = generateProposal({
+ terms: {
+ change: {
+ __typename: 'UpdateMarket',
+ },
+ },
+ });
+ render(
+
+ );
+ expect(
+ screen.queryByTestId('proposal-volume-discount-program-details')
+ ).toBeNull();
+ });
+
+ it('should not render if there are no relevant fields', () => {
+ const incompleteProposal = generateProposal({
+ terms: {
+ change: {
+ __typename: 'UpdateVolumeDiscountProgram',
+ },
+ },
+ });
+
+ render(
+
+ );
+ expect(
+ screen.queryByTestId('proposal-volume-discount-program-details')
+ ).toBeNull();
+ });
+
+ it('should render relevant fields if present', () => {
+ render(
+
+ );
+ expect(
+ screen.getByTestId('proposal-volume-discount-program-window-length')
+ ).toBeInTheDocument();
+ expect(
+ screen.getByTestId(
+ 'proposal-volume-discount-program-end-of-program-timestamp'
+ )
+ ).toBeInTheDocument();
+ expect(
+ screen.getByTestId('proposal-volume-discount-program-benefit-tiers')
+ ).toBeInTheDocument();
+ });
+});
diff --git a/apps/governance/src/routes/proposals/components/proposal-volume-discount-program-details/proposal-volume-discount-program-details.tsx b/apps/governance/src/routes/proposals/components/proposal-volume-discount-program-details/proposal-volume-discount-program-details.tsx
new file mode 100644
index 0000000000..48a72b1301
--- /dev/null
+++ b/apps/governance/src/routes/proposals/components/proposal-volume-discount-program-details/proposal-volume-discount-program-details.tsx
@@ -0,0 +1,130 @@
+import { useTranslation } from 'react-i18next';
+import type { ProposalQuery } from '../../proposal/__generated__/Proposal';
+import {
+ KeyValueTable,
+ KeyValueTableRow,
+ RoundedWrapper,
+ Tooltip,
+} from '@vegaprotocol/ui-toolkit';
+import {
+ formatEndOfProgramTimestamp,
+ formatMinimumRunningNotionalTakerVolume,
+} from '../proposal-referral-program-details';
+import { formatNumberPercentage } from '@vegaprotocol/utils';
+import BigNumber from 'bignumber.js';
+
+interface ProposalReferralProgramDetailsProps {
+ proposal: ProposalQuery['proposal'];
+}
+
+export const formatVolumeDiscountFactor = (value: string) => {
+ return formatNumberPercentage(new BigNumber(value).times(100));
+};
+
+export const ProposalVolumeDiscountProgramDetails = ({
+ proposal,
+}: ProposalReferralProgramDetailsProps) => {
+ const { t } = useTranslation();
+ if (proposal?.terms?.change?.__typename !== 'UpdateVolumeDiscountProgram') {
+ return null;
+ }
+
+ const benefitTiers = proposal?.terms?.change?.benefitTiers;
+ const windowLength = proposal?.terms?.change?.windowLength;
+ const endOfProgramTimestamp = proposal?.terms?.change?.endOfProgramTimestamp;
+
+ if (!benefitTiers && !windowLength && !endOfProgramTimestamp) {
+ return null;
+ }
+
+ return (
+
+
+ {windowLength && (
+
+
+
+
+ {t('WindowLength')}
+
+ {windowLength}
+
+
+
+ )}
+
+ {endOfProgramTimestamp && (
+
+
+
+
+ {t('EndOfProgramTimestamp')}
+
+ {formatEndOfProgramTimestamp(endOfProgramTimestamp)}
+
+
+
+ )}
+
+ {benefitTiers && (
+
+
+ {t('BenefitTiers')}
+
+
+ {benefitTiers
+ .sort(
+ (a, b) =>
+ Number(a.minimumRunningNotionalTakerVolume) -
+ Number(b.minimumRunningNotionalTakerVolume)
+ )
+ .map((benefitTier, index) => (
+
+
+ Tier {index + 1}
+
+ {benefitTier.minimumRunningNotionalTakerVolume && (
+
+
+
+ {t('BenefitTierMinimumRunningNotionalTakerVolume')}
+
+
+ {formatMinimumRunningNotionalTakerVolume(
+ benefitTier.minimumRunningNotionalTakerVolume
+ )}
+
+ )}
+ {benefitTier.volumeDiscountFactor && (
+
+
+ {t('BenefitTierVolumeDiscountFactor')}
+
+ {formatVolumeDiscountFactor(
+ benefitTier.volumeDiscountFactor
+ )}
+
+ )}
+
+ ))}
+
+
+ )}
+
+
+ );
+};
diff --git a/apps/governance/src/routes/proposals/components/proposal/proposal.tsx b/apps/governance/src/routes/proposals/components/proposal/proposal.tsx
index 4a18ca2207..e4347fcfaa 100644
--- a/apps/governance/src/routes/proposals/components/proposal/proposal.tsx
+++ b/apps/governance/src/routes/proposals/components/proposal/proposal.tsx
@@ -7,6 +7,7 @@ import { ProposalChangeTable } from '../proposal-change-table';
import { ProposalJson } from '../proposal-json';
import { ProposalAssetDetails } from '../proposal-asset-details';
import { ProposalReferralProgramDetails } from '../proposal-referral-program-details';
+import { ProposalVolumeDiscountProgramDetails } from '../proposal-volume-discount-program-details';
import { UserVote } from '../vote-details';
import { ListAsset } from '../list-asset';
import Routes from '../../../routes';
@@ -119,6 +120,10 @@ export const Proposal = ({
minVoterBalance =
networkParams.governance_proposal_referralProgram_minVoterBalance;
break;
+ case 'UpdateVolumeDiscountProgram':
+ minVoterBalance =
+ networkParams.governance_proposal_VolumeDiscountProgram_minVoterBalance;
+ break;
}
}
@@ -232,6 +237,12 @@ export const Proposal = ({
)}
+ {proposal.terms.change.__typename === 'UpdateVolumeDiscountProgram' && (
+
+ )}
+
{governanceTransferDetails}
diff --git a/apps/governance/src/routes/proposals/hooks/use-proposal-network-params.ts b/apps/governance/src/routes/proposals/hooks/use-proposal-network-params.ts
index 832a5ef013..ba559cdb51 100644
--- a/apps/governance/src/routes/proposals/hooks/use-proposal-network-params.ts
+++ b/apps/governance/src/routes/proposals/hooks/use-proposal-network-params.ts
@@ -28,6 +28,8 @@ export const useProposalNetworkParams = ({
NetworkParams.governance_proposal_updateNetParam_requiredParticipation,
NetworkParams.governance_proposal_freeform_requiredMajority,
NetworkParams.governance_proposal_freeform_requiredParticipation,
+ NetworkParams.governance_proposal_VolumeDiscountProgram_requiredMajority,
+ NetworkParams.governance_proposal_VolumeDiscountProgram_requiredParticipation,
]);
const fallback = {
@@ -101,6 +103,14 @@ export const useProposalNetworkParams = ({
params.governance_proposal_referralProgram_requiredParticipation
),
};
+ case 'UpdateVolumeDiscountProgram':
+ return {
+ requiredMajority:
+ params.governance_proposal_VolumeDiscountProgram_requiredMajority,
+ requiredParticipation: new BigNumber(
+ params.governance_proposal_VolumeDiscountProgram_requiredParticipation
+ ),
+ };
default:
return fallback;
}
diff --git a/apps/governance/src/routes/proposals/proposal/Proposal.graphql b/apps/governance/src/routes/proposals/proposal/Proposal.graphql
index 50739ecd86..3ff49833c0 100644
--- a/apps/governance/src/routes/proposals/proposal/Proposal.graphql
+++ b/apps/governance/src/routes/proposals/proposal/Proposal.graphql
@@ -66,11 +66,27 @@ fragment UpdateReferralProgram on Proposal {
}
}
+fragment UpdateVolumeDiscountProgram on Proposal {
+ terms {
+ change {
+ ... on UpdateVolumeDiscountProgram {
+ benefitTiers {
+ minimumRunningNotionalTakerVolume
+ volumeDiscountFactor
+ }
+ endOfProgramTimestamp
+ windowLength
+ }
+ }
+ }
+}
+
query Proposal(
$proposalId: ID!
$includeNewMarketProductField: Boolean!
$includeUpdateMarketState: Boolean!
$includeUpdateReferralProgram: Boolean!
+ $includeUpdateVolumeDiscountProgram: Boolean!
) {
proposal(id: $proposalId) {
id
@@ -89,6 +105,8 @@ query Proposal(
...NewMarketProductField @include(if: $includeNewMarketProductField)
...UpdateMarketState @include(if: $includeUpdateMarketState)
...UpdateReferralProgram @include(if: $includeUpdateReferralProgram)
+ ...UpdateVolumeDiscountProgram
+ @include(if: $includeUpdateVolumeDiscountProgram)
terms {
closingDatetime
enactmentDatetime
diff --git a/apps/governance/src/routes/proposals/proposal/__generated__/Proposal.ts b/apps/governance/src/routes/proposals/proposal/__generated__/Proposal.ts
index 516d879723..ed05e20558 100644
--- a/apps/governance/src/routes/proposals/proposal/__generated__/Proposal.ts
+++ b/apps/governance/src/routes/proposals/proposal/__generated__/Proposal.ts
@@ -9,15 +9,18 @@ export type UpdateMarketStateFragment = { __typename?: 'Proposal', terms: { __ty
export type UpdateReferralProgramFragment = { __typename?: 'Proposal', terms: { __typename?: 'ProposalTerms', change: { __typename?: 'CancelTransfer' } | { __typename?: 'NewAsset' } | { __typename?: 'NewFreeform' } | { __typename?: 'NewMarket' } | { __typename?: 'NewSpotMarket' } | { __typename?: 'NewTransfer' } | { __typename?: 'UpdateAsset' } | { __typename?: 'UpdateMarket' } | { __typename?: 'UpdateMarketState' } | { __typename?: 'UpdateNetworkParameter' } | { __typename?: 'UpdateReferralProgram', changes: { __typename?: 'ReferralProgram', endOfProgramTimestamp: string, windowLength: number, benefitTiers: Array<{ __typename?: 'BenefitTier', minimumEpochs: number, minimumRunningNotionalTakerVolume: string, referralDiscountFactor: string, referralRewardFactor: string }>, stakingTiers: Array<{ __typename?: 'StakingTier', minimumStakedTokens: string, referralRewardMultiplier: string }> } } | { __typename?: 'UpdateSpotMarket' } | { __typename?: 'UpdateVolumeDiscountProgram' } } };
+export type UpdateVolumeDiscountProgramFragment = { __typename?: 'Proposal', terms: { __typename?: 'ProposalTerms', change: { __typename?: 'CancelTransfer' } | { __typename?: 'NewAsset' } | { __typename?: 'NewFreeform' } | { __typename?: 'NewMarket' } | { __typename?: 'NewSpotMarket' } | { __typename?: 'NewTransfer' } | { __typename?: 'UpdateAsset' } | { __typename?: 'UpdateMarket' } | { __typename?: 'UpdateMarketState' } | { __typename?: 'UpdateNetworkParameter' } | { __typename?: 'UpdateReferralProgram' } | { __typename?: 'UpdateSpotMarket' } | { __typename?: 'UpdateVolumeDiscountProgram', endOfProgramTimestamp: any, windowLength: number, benefitTiers: Array<{ __typename?: 'VolumeBenefitTier', minimumRunningNotionalTakerVolume: string, volumeDiscountFactor: string }> } } };
+
export type ProposalQueryVariables = Types.Exact<{
proposalId: Types.Scalars['ID'];
includeNewMarketProductField: Types.Scalars['Boolean'];
includeUpdateMarketState: Types.Scalars['Boolean'];
includeUpdateReferralProgram: Types.Scalars['Boolean'];
+ includeUpdateVolumeDiscountProgram: Types.Scalars['Boolean'];
}>;
-export type ProposalQuery = { __typename?: 'Query', proposal?: { __typename?: 'Proposal', id?: string | null, reference: string, state: Types.ProposalState, datetime: any, rejectionReason?: Types.ProposalRejectionReason | null, errorDetails?: string | null, rationale: { __typename?: 'ProposalRationale', title: string, description: string }, party: { __typename?: 'Party', id: string }, terms: { __typename?: 'ProposalTerms', closingDatetime: any, enactmentDatetime?: any | null, change: { __typename?: 'CancelTransfer' } | { __typename?: 'NewAsset', name: string, symbol: string, decimals: number, quantum: string, source: { __typename?: 'BuiltinAsset', maxFaucetAmountMint: string } | { __typename?: 'ERC20', contractAddress: string, lifetimeLimit: string, withdrawThreshold: string } } | { __typename?: 'NewFreeform' } | { __typename?: 'NewMarket', decimalPlaces: number, metadata?: Array | null, positionDecimalPlaces: number, linearSlippageFactor: string, quadraticSlippageFactor: string, riskParameters: { __typename?: 'LogNormalRiskModel', riskAversionParameter: number, tau: number, params: { __typename?: 'LogNormalModelParams', mu: number, r: number, sigma: number } } | { __typename?: 'SimpleRiskModel', params: { __typename?: 'SimpleRiskModelParams', factorLong: number, factorShort: number } }, instrument: { __typename?: 'InstrumentConfiguration', name: string, code: string, futureProduct?: { __typename?: 'FutureProduct', quoteName: string, settlementAsset: { __typename?: 'Asset', id: string, name: string, symbol: string, decimals: number, quantum: string }, dataSourceSpecForSettlementData: { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, filters?: Array<{ __typename?: 'Filter', key: { __typename?: 'PropertyKey', name?: string | null, type: Types.PropertyKeyType }, conditions?: Array<{ __typename?: 'Condition', operator: Types.ConditionOperator, value?: string | null }> | null }> | null } | { __typename?: 'EthCallSpec' } } | { __typename?: 'DataSourceDefinitionInternal', sourceType: { __typename?: 'DataSourceSpecConfigurationTime', conditions: Array<{ __typename?: 'Condition', operator: Types.ConditionOperator, value?: string | null } | null> } | { __typename?: 'DataSourceSpecConfigurationTimeTrigger' } } }, dataSourceSpecBinding: { __typename?: 'DataSourceSpecToFutureBinding', settlementDataProperty: string, tradingTerminationProperty: string } } | null, product?: { __typename: 'FutureProduct' } | { __typename: 'PerpetualProduct' } | { __typename: 'SpotProduct' } | null }, priceMonitoringParameters: { __typename?: 'PriceMonitoringParameters', triggers?: Array<{ __typename?: 'PriceMonitoringTrigger', horizonSecs: number, probability: number, auctionExtensionSecs: number }> | null }, liquidityMonitoringParameters: { __typename?: 'LiquidityMonitoringParameters', triggeringRatio: string, targetStakeParameters: { __typename?: 'TargetStakeParameters', timeWindow: number, scalingFactor: number } } } | { __typename?: 'NewSpotMarket' } | { __typename?: 'NewTransfer' } | { __typename?: 'UpdateAsset', quantum: string, assetId: string, source: { __typename?: 'UpdateERC20', lifetimeLimit: string, withdrawThreshold: string } } | { __typename?: 'UpdateMarket', marketId: string, updateMarketConfiguration: { __typename?: 'UpdateMarketConfiguration', metadata?: Array | null, instrument: { __typename?: 'UpdateInstrumentConfiguration', code: string, product: { __typename?: 'UpdateFutureProduct', quoteName: string, dataSourceSpecForSettlementData: { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, filters?: Array<{ __typename?: 'Filter', key: { __typename?: 'PropertyKey', name?: string | null, type: Types.PropertyKeyType }, conditions?: Array<{ __typename?: 'Condition', operator: Types.ConditionOperator, value?: string | null }> | null }> | null } | { __typename?: 'EthCallSpec' } } | { __typename?: 'DataSourceDefinitionInternal', sourceType: { __typename?: 'DataSourceSpecConfigurationTime', conditions: Array<{ __typename?: 'Condition', operator: Types.ConditionOperator, value?: string | null } | null> } | { __typename?: 'DataSourceSpecConfigurationTimeTrigger' } } }, dataSourceSpecBinding: { __typename?: 'DataSourceSpecToFutureBinding', settlementDataProperty: string, tradingTerminationProperty: string } } | { __typename?: 'UpdatePerpetualProduct', quoteName: string, dataSourceSpecForSettlementData: { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, filters?: Array<{ __typename?: 'Filter', key: { __typename?: 'PropertyKey', name?: string | null, type: Types.PropertyKeyType }, conditions?: Array<{ __typename?: 'Condition', operator: Types.ConditionOperator, value?: string | null }> | null }> | null } | { __typename?: 'EthCallSpec' } } | { __typename?: 'DataSourceDefinitionInternal', sourceType: { __typename?: 'DataSourceSpecConfigurationTime', conditions: Array<{ __typename?: 'Condition', operator: Types.ConditionOperator, value?: string | null } | null> } | { __typename?: 'DataSourceSpecConfigurationTimeTrigger' } } }, dataSourceSpecBinding: { __typename?: 'DataSourceSpecPerpetualBinding', settlementDataProperty: string, settlementScheduleProperty: string } } }, priceMonitoringParameters: { __typename?: 'PriceMonitoringParameters', triggers?: Array<{ __typename?: 'PriceMonitoringTrigger', horizonSecs: number, probability: number, auctionExtensionSecs: number }> | null }, liquidityMonitoringParameters: { __typename?: 'LiquidityMonitoringParameters', triggeringRatio: string, targetStakeParameters: { __typename?: 'TargetStakeParameters', timeWindow: number, scalingFactor: number } }, riskParameters: { __typename?: 'UpdateMarketLogNormalRiskModel', logNormal?: { __typename?: 'LogNormalRiskModel', riskAversionParameter: number, tau: number, params: { __typename?: 'LogNormalModelParams', r: number, sigma: number, mu: number } } | null } | { __typename?: 'UpdateMarketSimpleRiskModel', simple?: { __typename?: 'SimpleRiskModelParams', factorLong: number, factorShort: number } | null } } } | { __typename?: 'UpdateMarketState', updateType: Types.MarketUpdateType, price?: string | null, market: { __typename?: 'Market', decimalPlaces: number, id: string, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string, code: string, product: { __typename: 'Future', quoteName: string } | { __typename: 'Perpetual', quoteName: string } | { __typename: 'Spot' } } } } } | { __typename?: 'UpdateNetworkParameter', networkParameter: { __typename?: 'NetworkParameter', key: string, value: string } } | { __typename?: 'UpdateReferralProgram', changes: { __typename?: 'ReferralProgram', endOfProgramTimestamp: string, windowLength: number, benefitTiers: Array<{ __typename?: 'BenefitTier', minimumEpochs: number, minimumRunningNotionalTakerVolume: string, referralDiscountFactor: string, referralRewardFactor: string }>, stakingTiers: Array<{ __typename?: 'StakingTier', minimumStakedTokens: string, referralRewardMultiplier: string }> } } | { __typename?: 'UpdateSpotMarket' } | { __typename?: 'UpdateVolumeDiscountProgram' } }, votes: { __typename?: 'ProposalVotes', yes: { __typename?: 'ProposalVoteSide', totalTokens: string, totalNumber: string, totalEquityLikeShareWeight: string }, no: { __typename?: 'ProposalVoteSide', totalTokens: string, totalNumber: string, totalEquityLikeShareWeight: string } } } | null };
+export type ProposalQuery = { __typename?: 'Query', proposal?: { __typename?: 'Proposal', id?: string | null, reference: string, state: Types.ProposalState, datetime: any, rejectionReason?: Types.ProposalRejectionReason | null, errorDetails?: string | null, rationale: { __typename?: 'ProposalRationale', title: string, description: string }, party: { __typename?: 'Party', id: string }, terms: { __typename?: 'ProposalTerms', closingDatetime: any, enactmentDatetime?: any | null, change: { __typename?: 'CancelTransfer' } | { __typename?: 'NewAsset', name: string, symbol: string, decimals: number, quantum: string, source: { __typename?: 'BuiltinAsset', maxFaucetAmountMint: string } | { __typename?: 'ERC20', contractAddress: string, lifetimeLimit: string, withdrawThreshold: string } } | { __typename?: 'NewFreeform' } | { __typename?: 'NewMarket', decimalPlaces: number, metadata?: Array | null, positionDecimalPlaces: number, linearSlippageFactor: string, quadraticSlippageFactor: string, riskParameters: { __typename?: 'LogNormalRiskModel', riskAversionParameter: number, tau: number, params: { __typename?: 'LogNormalModelParams', mu: number, r: number, sigma: number } } | { __typename?: 'SimpleRiskModel', params: { __typename?: 'SimpleRiskModelParams', factorLong: number, factorShort: number } }, instrument: { __typename?: 'InstrumentConfiguration', name: string, code: string, futureProduct?: { __typename?: 'FutureProduct', quoteName: string, settlementAsset: { __typename?: 'Asset', id: string, name: string, symbol: string, decimals: number, quantum: string }, dataSourceSpecForSettlementData: { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, filters?: Array<{ __typename?: 'Filter', key: { __typename?: 'PropertyKey', name?: string | null, type: Types.PropertyKeyType }, conditions?: Array<{ __typename?: 'Condition', operator: Types.ConditionOperator, value?: string | null }> | null }> | null } | { __typename?: 'EthCallSpec' } } | { __typename?: 'DataSourceDefinitionInternal', sourceType: { __typename?: 'DataSourceSpecConfigurationTime', conditions: Array<{ __typename?: 'Condition', operator: Types.ConditionOperator, value?: string | null } | null> } | { __typename?: 'DataSourceSpecConfigurationTimeTrigger' } } }, dataSourceSpecBinding: { __typename?: 'DataSourceSpecToFutureBinding', settlementDataProperty: string, tradingTerminationProperty: string } } | null, product?: { __typename: 'FutureProduct' } | { __typename: 'PerpetualProduct' } | { __typename: 'SpotProduct' } | null }, priceMonitoringParameters: { __typename?: 'PriceMonitoringParameters', triggers?: Array<{ __typename?: 'PriceMonitoringTrigger', horizonSecs: number, probability: number, auctionExtensionSecs: number }> | null }, liquidityMonitoringParameters: { __typename?: 'LiquidityMonitoringParameters', triggeringRatio: string, targetStakeParameters: { __typename?: 'TargetStakeParameters', timeWindow: number, scalingFactor: number } } } | { __typename?: 'NewSpotMarket' } | { __typename?: 'NewTransfer' } | { __typename?: 'UpdateAsset', quantum: string, assetId: string, source: { __typename?: 'UpdateERC20', lifetimeLimit: string, withdrawThreshold: string } } | { __typename?: 'UpdateMarket', marketId: string, updateMarketConfiguration: { __typename?: 'UpdateMarketConfiguration', metadata?: Array | null, instrument: { __typename?: 'UpdateInstrumentConfiguration', code: string, product: { __typename?: 'UpdateFutureProduct', quoteName: string, dataSourceSpecForSettlementData: { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, filters?: Array<{ __typename?: 'Filter', key: { __typename?: 'PropertyKey', name?: string | null, type: Types.PropertyKeyType }, conditions?: Array<{ __typename?: 'Condition', operator: Types.ConditionOperator, value?: string | null }> | null }> | null } | { __typename?: 'EthCallSpec' } } | { __typename?: 'DataSourceDefinitionInternal', sourceType: { __typename?: 'DataSourceSpecConfigurationTime', conditions: Array<{ __typename?: 'Condition', operator: Types.ConditionOperator, value?: string | null } | null> } | { __typename?: 'DataSourceSpecConfigurationTimeTrigger' } } }, dataSourceSpecBinding: { __typename?: 'DataSourceSpecToFutureBinding', settlementDataProperty: string, tradingTerminationProperty: string } } | { __typename?: 'UpdatePerpetualProduct', quoteName: string, dataSourceSpecForSettlementData: { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, filters?: Array<{ __typename?: 'Filter', key: { __typename?: 'PropertyKey', name?: string | null, type: Types.PropertyKeyType }, conditions?: Array<{ __typename?: 'Condition', operator: Types.ConditionOperator, value?: string | null }> | null }> | null } | { __typename?: 'EthCallSpec' } } | { __typename?: 'DataSourceDefinitionInternal', sourceType: { __typename?: 'DataSourceSpecConfigurationTime', conditions: Array<{ __typename?: 'Condition', operator: Types.ConditionOperator, value?: string | null } | null> } | { __typename?: 'DataSourceSpecConfigurationTimeTrigger' } } }, dataSourceSpecBinding: { __typename?: 'DataSourceSpecPerpetualBinding', settlementDataProperty: string, settlementScheduleProperty: string } } }, priceMonitoringParameters: { __typename?: 'PriceMonitoringParameters', triggers?: Array<{ __typename?: 'PriceMonitoringTrigger', horizonSecs: number, probability: number, auctionExtensionSecs: number }> | null }, liquidityMonitoringParameters: { __typename?: 'LiquidityMonitoringParameters', triggeringRatio: string, targetStakeParameters: { __typename?: 'TargetStakeParameters', timeWindow: number, scalingFactor: number } }, riskParameters: { __typename?: 'UpdateMarketLogNormalRiskModel', logNormal?: { __typename?: 'LogNormalRiskModel', riskAversionParameter: number, tau: number, params: { __typename?: 'LogNormalModelParams', r: number, sigma: number, mu: number } } | null } | { __typename?: 'UpdateMarketSimpleRiskModel', simple?: { __typename?: 'SimpleRiskModelParams', factorLong: number, factorShort: number } | null } } } | { __typename?: 'UpdateMarketState', updateType: Types.MarketUpdateType, price?: string | null, market: { __typename?: 'Market', decimalPlaces: number, id: string, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string, code: string, product: { __typename: 'Future', quoteName: string } | { __typename: 'Perpetual', quoteName: string } | { __typename: 'Spot' } } } } } | { __typename?: 'UpdateNetworkParameter', networkParameter: { __typename?: 'NetworkParameter', key: string, value: string } } | { __typename?: 'UpdateReferralProgram', changes: { __typename?: 'ReferralProgram', endOfProgramTimestamp: string, windowLength: number, benefitTiers: Array<{ __typename?: 'BenefitTier', minimumEpochs: number, minimumRunningNotionalTakerVolume: string, referralDiscountFactor: string, referralRewardFactor: string }>, stakingTiers: Array<{ __typename?: 'StakingTier', minimumStakedTokens: string, referralRewardMultiplier: string }> } } | { __typename?: 'UpdateSpotMarket' } | { __typename?: 'UpdateVolumeDiscountProgram', endOfProgramTimestamp: any, windowLength: number, benefitTiers: Array<{ __typename?: 'VolumeBenefitTier', minimumRunningNotionalTakerVolume: string, volumeDiscountFactor: string }> } }, votes: { __typename?: 'ProposalVotes', yes: { __typename?: 'ProposalVoteSide', totalTokens: string, totalNumber: string, totalEquityLikeShareWeight: string }, no: { __typename?: 'ProposalVoteSide', totalTokens: string, totalNumber: string, totalEquityLikeShareWeight: string } } } | null };
export const NewMarketProductFieldFragmentDoc = gql`
fragment NewMarketProductField on Proposal {
@@ -90,8 +93,24 @@ export const UpdateReferralProgramFragmentDoc = gql`
}
}
`;
+export const UpdateVolumeDiscountProgramFragmentDoc = gql`
+ fragment UpdateVolumeDiscountProgram on Proposal {
+ terms {
+ change {
+ ... on UpdateVolumeDiscountProgram {
+ benefitTiers {
+ minimumRunningNotionalTakerVolume
+ volumeDiscountFactor
+ }
+ endOfProgramTimestamp
+ windowLength
+ }
+ }
+ }
+}
+ `;
export const ProposalDocument = gql`
- query Proposal($proposalId: ID!, $includeNewMarketProductField: Boolean!, $includeUpdateMarketState: Boolean!, $includeUpdateReferralProgram: Boolean!) {
+ query Proposal($proposalId: ID!, $includeNewMarketProductField: Boolean!, $includeUpdateMarketState: Boolean!, $includeUpdateReferralProgram: Boolean!, $includeUpdateVolumeDiscountProgram: Boolean!) {
proposal(id: $proposalId) {
id
rationale {
@@ -109,6 +128,7 @@ export const ProposalDocument = gql`
...NewMarketProductField @include(if: $includeNewMarketProductField)
...UpdateMarketState @include(if: $includeUpdateMarketState)
...UpdateReferralProgram @include(if: $includeUpdateReferralProgram)
+ ...UpdateVolumeDiscountProgram @include(if: $includeUpdateVolumeDiscountProgram)
terms {
closingDatetime
enactmentDatetime
@@ -397,7 +417,8 @@ export const ProposalDocument = gql`
}
${NewMarketProductFieldFragmentDoc}
${UpdateMarketStateFragmentDoc}
-${UpdateReferralProgramFragmentDoc}`;
+${UpdateReferralProgramFragmentDoc}
+${UpdateVolumeDiscountProgramFragmentDoc}`;
/**
* __useProposalQuery__
@@ -415,6 +436,7 @@ ${UpdateReferralProgramFragmentDoc}`;
* includeNewMarketProductField: // value for 'includeNewMarketProductField'
* includeUpdateMarketState: // value for 'includeUpdateMarketState'
* includeUpdateReferralProgram: // value for 'includeUpdateReferralProgram'
+ * includeUpdateVolumeDiscountProgram: // value for 'includeUpdateVolumeDiscountProgram'
* },
* });
*/
diff --git a/apps/governance/src/routes/proposals/proposal/proposal-container.tsx b/apps/governance/src/routes/proposals/proposal/proposal-container.tsx
index 01f4c350b8..5f3ff62d04 100644
--- a/apps/governance/src/routes/proposals/proposal/proposal-container.tsx
+++ b/apps/governance/src/routes/proposals/proposal/proposal-container.tsx
@@ -37,6 +37,7 @@ export const ProposalContainer = () => {
NetworkParams.governance_proposal_updateNetParam_minVoterBalance,
NetworkParams.governance_proposal_freeform_minVoterBalance,
NetworkParams.governance_proposal_referralProgram_minVoterBalance,
+ NetworkParams.governance_proposal_VolumeDiscountProgram_minVoterBalance,
NetworkParams.spam_protection_voting_min_tokens,
NetworkParams.governance_proposal_market_requiredMajority,
NetworkParams.governance_proposal_updateMarket_requiredMajority,
@@ -46,6 +47,7 @@ export const ProposalContainer = () => {
NetworkParams.governance_proposal_updateNetParam_requiredMajority,
NetworkParams.governance_proposal_freeform_requiredMajority,
NetworkParams.governance_proposal_referralProgram_requiredMajority,
+ NetworkParams.governance_proposal_VolumeDiscountProgram_requiredMajority,
]);
const {
@@ -60,6 +62,7 @@ export const ProposalContainer = () => {
includeNewMarketProductField: !!FLAGS.PRODUCT_PERPETUALS,
includeUpdateMarketState: !!FLAGS.UPDATE_MARKET_STATE,
includeUpdateReferralProgram: !!FLAGS.REFERRALS,
+ includeUpdateVolumeDiscountProgram: !!FLAGS.VOLUME_DISCOUNTS,
},
skip: !params.proposalId,
});
diff --git a/apps/governance/src/routes/proposals/proposals/Proposals.graphql b/apps/governance/src/routes/proposals/proposals/Proposals.graphql
index 7029735ce5..24cb96a85a 100644
--- a/apps/governance/src/routes/proposals/proposals/Proposals.graphql
+++ b/apps/governance/src/routes/proposals/proposals/Proposals.graphql
@@ -66,6 +66,21 @@ fragment UpdateReferralPrograms on Proposal {
}
}
+fragment UpdateVolumeDiscountPrograms on Proposal {
+ terms {
+ change {
+ ... on UpdateVolumeDiscountProgram {
+ benefitTiers {
+ minimumRunningNotionalTakerVolume
+ volumeDiscountFactor
+ }
+ endOfProgramTimestamp
+ windowLength
+ }
+ }
+ }
+}
+
fragment ProposalFields on Proposal {
id
rationale {
@@ -151,6 +166,7 @@ query Proposals(
$includeNewMarketProductFields: Boolean!
$includeUpdateMarketStates: Boolean!
$includeUpdateReferralPrograms: Boolean!
+ $includeUpdateVolumeDiscountPrograms: Boolean!
) {
proposalsConnection {
edges {
@@ -159,6 +175,8 @@ query Proposals(
...NewMarketProductFields @include(if: $includeNewMarketProductFields)
...UpdateMarketStates @include(if: $includeUpdateMarketStates)
...UpdateReferralPrograms @include(if: $includeUpdateReferralPrograms)
+ ...UpdateVolumeDiscountPrograms
+ @include(if: $includeUpdateVolumeDiscountPrograms)
}
}
}
diff --git a/apps/governance/src/routes/proposals/proposals/__generated__/Proposals.ts b/apps/governance/src/routes/proposals/proposals/__generated__/Proposals.ts
index 858cd49848..803bc24deb 100644
--- a/apps/governance/src/routes/proposals/proposals/__generated__/Proposals.ts
+++ b/apps/governance/src/routes/proposals/proposals/__generated__/Proposals.ts
@@ -9,16 +9,19 @@ export type UpdateMarketStatesFragment = { __typename?: 'Proposal', terms: { __t
export type UpdateReferralProgramsFragment = { __typename?: 'Proposal', terms: { __typename?: 'ProposalTerms', change: { __typename?: 'CancelTransfer' } | { __typename?: 'NewAsset' } | { __typename?: 'NewFreeform' } | { __typename?: 'NewMarket' } | { __typename?: 'NewSpotMarket' } | { __typename?: 'NewTransfer' } | { __typename?: 'UpdateAsset' } | { __typename?: 'UpdateMarket' } | { __typename?: 'UpdateMarketState' } | { __typename?: 'UpdateNetworkParameter' } | { __typename?: 'UpdateReferralProgram', changes: { __typename?: 'ReferralProgram', endOfProgramTimestamp: string, windowLength: number, benefitTiers: Array<{ __typename?: 'BenefitTier', minimumEpochs: number, minimumRunningNotionalTakerVolume: string, referralDiscountFactor: string, referralRewardFactor: string }>, stakingTiers: Array<{ __typename?: 'StakingTier', minimumStakedTokens: string, referralRewardMultiplier: string }> } } | { __typename?: 'UpdateSpotMarket' } | { __typename?: 'UpdateVolumeDiscountProgram' } } };
+export type UpdateVolumeDiscountProgramsFragment = { __typename?: 'Proposal', terms: { __typename?: 'ProposalTerms', change: { __typename?: 'CancelTransfer' } | { __typename?: 'NewAsset' } | { __typename?: 'NewFreeform' } | { __typename?: 'NewMarket' } | { __typename?: 'NewSpotMarket' } | { __typename?: 'NewTransfer' } | { __typename?: 'UpdateAsset' } | { __typename?: 'UpdateMarket' } | { __typename?: 'UpdateMarketState' } | { __typename?: 'UpdateNetworkParameter' } | { __typename?: 'UpdateReferralProgram' } | { __typename?: 'UpdateSpotMarket' } | { __typename?: 'UpdateVolumeDiscountProgram', endOfProgramTimestamp: any, windowLength: number, benefitTiers: Array<{ __typename?: 'VolumeBenefitTier', minimumRunningNotionalTakerVolume: string, volumeDiscountFactor: string }> } } };
+
export type ProposalFieldsFragment = { __typename?: 'Proposal', id?: string | null, reference: string, state: Types.ProposalState, datetime: any, rejectionReason?: Types.ProposalRejectionReason | null, errorDetails?: string | null, rationale: { __typename?: 'ProposalRationale', title: string, description: string }, party: { __typename?: 'Party', id: string }, terms: { __typename?: 'ProposalTerms', closingDatetime: any, enactmentDatetime?: any | null, change: { __typename?: 'CancelTransfer' } | { __typename: 'NewAsset', name: string, symbol: string, decimals: number, quantum: string, source: { __typename?: 'BuiltinAsset', maxFaucetAmountMint: string } | { __typename?: 'ERC20', contractAddress: string, withdrawThreshold: string, lifetimeLimit: string } } | { __typename?: 'NewFreeform' } | { __typename?: 'NewMarket', instrument: { __typename?: 'InstrumentConfiguration', name: string, code: string, futureProduct?: { __typename?: 'FutureProduct', settlementAsset: { __typename?: 'Asset', symbol: string } } | null } } | { __typename?: 'NewSpotMarket' } | { __typename?: 'NewTransfer' } | { __typename?: 'UpdateAsset', quantum: string, assetId: string, source: { __typename?: 'UpdateERC20', lifetimeLimit: string, withdrawThreshold: string } } | { __typename?: 'UpdateMarket', marketId: string } | { __typename?: 'UpdateMarketState' } | { __typename?: 'UpdateNetworkParameter', networkParameter: { __typename?: 'NetworkParameter', key: string, value: string } } | { __typename?: 'UpdateReferralProgram' } | { __typename?: 'UpdateSpotMarket' } | { __typename?: 'UpdateVolumeDiscountProgram' } }, votes: { __typename?: 'ProposalVotes', yes: { __typename?: 'ProposalVoteSide', totalTokens: string, totalNumber: string, totalEquityLikeShareWeight: string }, no: { __typename?: 'ProposalVoteSide', totalTokens: string, totalNumber: string, totalEquityLikeShareWeight: string } } };
export type ProposalsQueryVariables = Types.Exact<{
includeNewMarketProductFields: Types.Scalars['Boolean'];
includeUpdateMarketStates: Types.Scalars['Boolean'];
includeUpdateReferralPrograms: Types.Scalars['Boolean'];
+ includeUpdateVolumeDiscountPrograms: Types.Scalars['Boolean'];
}>;
-export type ProposalsQuery = { __typename?: 'Query', proposalsConnection?: { __typename?: 'ProposalsConnection', edges?: Array<{ __typename?: 'ProposalEdge', node: { __typename?: 'Proposal', id?: string | null, reference: string, state: Types.ProposalState, datetime: any, rejectionReason?: Types.ProposalRejectionReason | null, errorDetails?: string | null, rationale: { __typename?: 'ProposalRationale', title: string, description: string }, party: { __typename?: 'Party', id: string }, terms: { __typename?: 'ProposalTerms', closingDatetime: any, enactmentDatetime?: any | null, change: { __typename?: 'CancelTransfer' } | { __typename: 'NewAsset', name: string, symbol: string, decimals: number, quantum: string, source: { __typename?: 'BuiltinAsset', maxFaucetAmountMint: string } | { __typename?: 'ERC20', contractAddress: string, withdrawThreshold: string, lifetimeLimit: string } } | { __typename?: 'NewFreeform' } | { __typename?: 'NewMarket', instrument: { __typename?: 'InstrumentConfiguration', name: string, code: string, futureProduct?: { __typename?: 'FutureProduct', settlementAsset: { __typename?: 'Asset', symbol: string } } | null, product?: { __typename: 'FutureProduct' } | { __typename: 'PerpetualProduct' } | { __typename: 'SpotProduct' } | null } } | { __typename?: 'NewSpotMarket' } | { __typename?: 'NewTransfer' } | { __typename?: 'UpdateAsset', quantum: string, assetId: string, source: { __typename?: 'UpdateERC20', lifetimeLimit: string, withdrawThreshold: string } } | { __typename?: 'UpdateMarket', marketId: string } | { __typename?: 'UpdateMarketState', updateType: Types.MarketUpdateType, price?: string | null, market: { __typename?: 'Market', decimalPlaces: number, id: string, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string, code: string, product: { __typename: 'Future', quoteName: string } | { __typename: 'Perpetual', quoteName: string } | { __typename: 'Spot' } } } } } | { __typename?: 'UpdateNetworkParameter', networkParameter: { __typename?: 'NetworkParameter', key: string, value: string } } | { __typename?: 'UpdateReferralProgram', changes: { __typename?: 'ReferralProgram', endOfProgramTimestamp: string, windowLength: number, benefitTiers: Array<{ __typename?: 'BenefitTier', minimumEpochs: number, minimumRunningNotionalTakerVolume: string, referralDiscountFactor: string, referralRewardFactor: string }>, stakingTiers: Array<{ __typename?: 'StakingTier', minimumStakedTokens: string, referralRewardMultiplier: string }> } } | { __typename?: 'UpdateSpotMarket' } | { __typename?: 'UpdateVolumeDiscountProgram' } }, votes: { __typename?: 'ProposalVotes', yes: { __typename?: 'ProposalVoteSide', totalTokens: string, totalNumber: string, totalEquityLikeShareWeight: string }, no: { __typename?: 'ProposalVoteSide', totalTokens: string, totalNumber: string, totalEquityLikeShareWeight: string } } } } | null> | null } | null };
+export type ProposalsQuery = { __typename?: 'Query', proposalsConnection?: { __typename?: 'ProposalsConnection', edges?: Array<{ __typename?: 'ProposalEdge', node: { __typename?: 'Proposal', id?: string | null, reference: string, state: Types.ProposalState, datetime: any, rejectionReason?: Types.ProposalRejectionReason | null, errorDetails?: string | null, rationale: { __typename?: 'ProposalRationale', title: string, description: string }, party: { __typename?: 'Party', id: string }, terms: { __typename?: 'ProposalTerms', closingDatetime: any, enactmentDatetime?: any | null, change: { __typename?: 'CancelTransfer' } | { __typename: 'NewAsset', name: string, symbol: string, decimals: number, quantum: string, source: { __typename?: 'BuiltinAsset', maxFaucetAmountMint: string } | { __typename?: 'ERC20', contractAddress: string, withdrawThreshold: string, lifetimeLimit: string } } | { __typename?: 'NewFreeform' } | { __typename?: 'NewMarket', instrument: { __typename?: 'InstrumentConfiguration', name: string, code: string, futureProduct?: { __typename?: 'FutureProduct', settlementAsset: { __typename?: 'Asset', symbol: string } } | null, product?: { __typename: 'FutureProduct' } | { __typename: 'PerpetualProduct' } | { __typename: 'SpotProduct' } | null } } | { __typename?: 'NewSpotMarket' } | { __typename?: 'NewTransfer' } | { __typename?: 'UpdateAsset', quantum: string, assetId: string, source: { __typename?: 'UpdateERC20', lifetimeLimit: string, withdrawThreshold: string } } | { __typename?: 'UpdateMarket', marketId: string } | { __typename?: 'UpdateMarketState', updateType: Types.MarketUpdateType, price?: string | null, market: { __typename?: 'Market', decimalPlaces: number, id: string, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string, code: string, product: { __typename: 'Future', quoteName: string } | { __typename: 'Perpetual', quoteName: string } | { __typename: 'Spot' } } } } } | { __typename?: 'UpdateNetworkParameter', networkParameter: { __typename?: 'NetworkParameter', key: string, value: string } } | { __typename?: 'UpdateReferralProgram', changes: { __typename?: 'ReferralProgram', endOfProgramTimestamp: string, windowLength: number, benefitTiers: Array<{ __typename?: 'BenefitTier', minimumEpochs: number, minimumRunningNotionalTakerVolume: string, referralDiscountFactor: string, referralRewardFactor: string }>, stakingTiers: Array<{ __typename?: 'StakingTier', minimumStakedTokens: string, referralRewardMultiplier: string }> } } | { __typename?: 'UpdateSpotMarket' } | { __typename?: 'UpdateVolumeDiscountProgram', endOfProgramTimestamp: any, windowLength: number, benefitTiers: Array<{ __typename?: 'VolumeBenefitTier', minimumRunningNotionalTakerVolume: string, volumeDiscountFactor: string }> } }, votes: { __typename?: 'ProposalVotes', yes: { __typename?: 'ProposalVoteSide', totalTokens: string, totalNumber: string, totalEquityLikeShareWeight: string }, no: { __typename?: 'ProposalVoteSide', totalTokens: string, totalNumber: string, totalEquityLikeShareWeight: string } } } } | null> | null } | null };
export const NewMarketProductFieldsFragmentDoc = gql`
fragment NewMarketProductFields on Proposal {
@@ -91,6 +94,22 @@ export const UpdateReferralProgramsFragmentDoc = gql`
}
}
`;
+export const UpdateVolumeDiscountProgramsFragmentDoc = gql`
+ fragment UpdateVolumeDiscountPrograms on Proposal {
+ terms {
+ change {
+ ... on UpdateVolumeDiscountProgram {
+ benefitTiers {
+ minimumRunningNotionalTakerVolume
+ volumeDiscountFactor
+ }
+ endOfProgramTimestamp
+ windowLength
+ }
+ }
+ }
+}
+ `;
export const ProposalFieldsFragmentDoc = gql`
fragment ProposalFields on Proposal {
id
@@ -174,7 +193,7 @@ export const ProposalFieldsFragmentDoc = gql`
}
`;
export const ProposalsDocument = gql`
- query Proposals($includeNewMarketProductFields: Boolean!, $includeUpdateMarketStates: Boolean!, $includeUpdateReferralPrograms: Boolean!) {
+ query Proposals($includeNewMarketProductFields: Boolean!, $includeUpdateMarketStates: Boolean!, $includeUpdateReferralPrograms: Boolean!, $includeUpdateVolumeDiscountPrograms: Boolean!) {
proposalsConnection {
edges {
node {
@@ -182,6 +201,7 @@ export const ProposalsDocument = gql`
...NewMarketProductFields @include(if: $includeNewMarketProductFields)
...UpdateMarketStates @include(if: $includeUpdateMarketStates)
...UpdateReferralPrograms @include(if: $includeUpdateReferralPrograms)
+ ...UpdateVolumeDiscountPrograms @include(if: $includeUpdateVolumeDiscountPrograms)
}
}
}
@@ -189,7 +209,8 @@ export const ProposalsDocument = gql`
${ProposalFieldsFragmentDoc}
${NewMarketProductFieldsFragmentDoc}
${UpdateMarketStatesFragmentDoc}
-${UpdateReferralProgramsFragmentDoc}`;
+${UpdateReferralProgramsFragmentDoc}
+${UpdateVolumeDiscountProgramsFragmentDoc}`;
/**
* __useProposalsQuery__
@@ -206,6 +227,7 @@ ${UpdateReferralProgramsFragmentDoc}`;
* includeNewMarketProductFields: // value for 'includeNewMarketProductFields'
* includeUpdateMarketStates: // value for 'includeUpdateMarketStates'
* includeUpdateReferralPrograms: // value for 'includeUpdateReferralPrograms'
+ * includeUpdateVolumeDiscountPrograms: // value for 'includeUpdateVolumeDiscountPrograms'
* },
* });
*/
diff --git a/apps/governance/src/routes/proposals/proposals/proposals-container.tsx b/apps/governance/src/routes/proposals/proposals/proposals-container.tsx
index 104897726a..187633f4b3 100644
--- a/apps/governance/src/routes/proposals/proposals/proposals-container.tsx
+++ b/apps/governance/src/routes/proposals/proposals/proposals-container.tsx
@@ -50,6 +50,7 @@ export const ProposalsContainer = () => {
includeNewMarketProductFields: !!FLAGS.PRODUCT_PERPETUALS,
includeUpdateMarketStates: !!FLAGS.UPDATE_MARKET_STATE,
includeUpdateReferralPrograms: !!FLAGS.REFERRALS,
+ includeUpdateVolumeDiscountPrograms: !!FLAGS.VOLUME_DISCOUNTS,
},
});
diff --git a/apps/governance/src/routes/proposals/rejected/rejected-proposals-container.tsx b/apps/governance/src/routes/proposals/rejected/rejected-proposals-container.tsx
index 2e78b61d1f..f0d4a4fbbd 100644
--- a/apps/governance/src/routes/proposals/rejected/rejected-proposals-container.tsx
+++ b/apps/governance/src/routes/proposals/rejected/rejected-proposals-container.tsx
@@ -42,6 +42,7 @@ export const RejectedProposalsContainer = () => {
includeNewMarketProductFields: !!FLAGS.PRODUCT_PERPETUALS,
includeUpdateMarketStates: !!FLAGS.UPDATE_MARKET_STATE,
includeUpdateReferralPrograms: !!FLAGS.REFERRALS,
+ includeUpdateVolumeDiscountPrograms: !!FLAGS.VOLUME_DISCOUNTS,
},
});
diff --git a/libs/environment/src/hooks/use-environment.ts b/libs/environment/src/hooks/use-environment.ts
index 2c1ccd4e46..b48c09aca8 100644
--- a/libs/environment/src/hooks/use-environment.ts
+++ b/libs/environment/src/hooks/use-environment.ts
@@ -429,6 +429,12 @@ function compileFeatureFlags(): FeatureFlags {
process.env['NX_GOVERNANCE_TRANSFERS']
) as string
),
+ VOLUME_DISCOUNTS: TRUTHY.includes(
+ windowOrDefault(
+ 'NX_VOLUME_DISCOUNTS',
+ process.env['NX_VOLUME_DISCOUNTS']
+ ) as string
+ ),
};
const EXPLORER_FLAGS = {
EXPLORER_ASSETS: TRUTHY.includes(
diff --git a/libs/environment/src/types.ts b/libs/environment/src/types.ts
index 0f82262220..296adfe22b 100644
--- a/libs/environment/src/types.ts
+++ b/libs/environment/src/types.ts
@@ -26,6 +26,7 @@ export type CosmicElevatorFlags = Pick<
| 'REFERRALS'
| 'UPDATE_MARKET_STATE'
| 'GOVERNANCE_TRANSFERS'
+ | 'VOLUME_DISCOUNTS'
>;
export type Configuration = z.infer;
export const CUSTOM_NODE_KEY = 'custom' as const;
diff --git a/libs/environment/src/utils/validate-environment.ts b/libs/environment/src/utils/validate-environment.ts
index 609faba923..3f6a0af4b9 100644
--- a/libs/environment/src/utils/validate-environment.ts
+++ b/libs/environment/src/utils/validate-environment.ts
@@ -81,6 +81,7 @@ const COSMIC_ELEVATOR_FLAGS = {
REFERRALS: z.optional(z.boolean()),
UPDATE_MARKET_STATE: z.optional(z.boolean()),
GOVERNANCE_TRANSFERS: z.optional(z.boolean()),
+ VOLUME_DISCOUNTS: z.optional(z.boolean()),
};
const EXPLORER_FLAGS = {
diff --git a/libs/network-parameters/src/use-network-params.ts b/libs/network-parameters/src/use-network-params.ts
index a13e30b291..34ab03ba36 100644
--- a/libs/network-parameters/src/use-network-params.ts
+++ b/libs/network-parameters/src/use-network-params.ts
@@ -112,6 +112,22 @@ export const NetworkParams = {
'governance_proposal_referralProgram_requiredMajority',
governance_proposal_referralProgram_requiredParticipation:
'governance_proposal_referralProgram_requiredParticipation',
+ governance_proposal_VolumeDiscountProgram_maxClose:
+ 'governance_proposal_VolumeDiscountProgram_maxClose',
+ governance_proposal_VolumeDiscountProgram_maxEnact:
+ 'governance_proposal_VolumeDiscountProgram_maxEnact',
+ governance_proposal_VolumeDiscountProgram_minClose:
+ 'governance_proposal_VolumeDiscountProgram_minClose',
+ governance_proposal_VolumeDiscountProgram_minEnact:
+ 'governance_proposal_VolumeDiscountProgram_minEnact',
+ governance_proposal_VolumeDiscountProgram_minProposerBalance:
+ 'governance_proposal_VolumeDiscountProgram_minProposerBalance',
+ governance_proposal_VolumeDiscountProgram_minVoterBalance:
+ 'governance_proposal_VolumeDiscountProgram_minVoterBalance',
+ governance_proposal_VolumeDiscountProgram_requiredMajority:
+ 'governance_proposal_VolumeDiscountProgram_requiredMajority',
+ governance_proposal_VolumeDiscountProgram_requiredParticipation:
+ 'governance_proposal_VolumeDiscountProgram_requiredParticipation',
validators_delegation_minAmount: 'validators_delegation_minAmount',
spam_protection_minimumWithdrawalQuantumMultiple:
'spam_protection_minimumWithdrawalQuantumMultiple',