From ecd60413d05eba749deb2dd86cec694272281154 Mon Sep 17 00:00:00 2001 From: alexandermendes Date: Thu, 14 Nov 2024 08:19:24 +0000 Subject: [PATCH] refactor: splut out and test calculateStakedPctOfSupply --- src/provider.tsx | 10 +- src/utils/staking.ts | 13 -- src/utils/supply.ts | 20 +++ .../streams-schedule.ts} | 115 +---------------- tests/specs/utils/apr.test.ts | 116 ++++++++++++++++++ tests/specs/utils/supply.test.ts | 26 ++++ tests/utils/get-number-to-18-decimals.ts | 5 + 7 files changed, 173 insertions(+), 132 deletions(-) create mode 100644 src/utils/supply.ts rename tests/{utils/apr.test.ts => fixtures/streams-schedule.ts} (56%) create mode 100644 tests/specs/utils/apr.test.ts create mode 100644 tests/specs/utils/supply.test.ts create mode 100644 tests/utils/get-number-to-18-decimals.ts diff --git a/src/provider.tsx b/src/provider.tsx index b384743..4ac11a6 100644 --- a/src/provider.tsx +++ b/src/provider.tsx @@ -11,7 +11,6 @@ import { useAccount, useChainId, useSwitchChain } from 'wagmi'; import { parseFixed } from '@ethersproject/bignumber'; import { approveStaking, - calculateStakedPctOfSupply, claim, claimAll, getDeposit, @@ -40,6 +39,7 @@ import { erc20abi } from './abis/erc20.js'; import { AuroraNetwork } from './types/network.js'; import { config } from './config.js'; import { logger } from './logger.js'; +import { calculateStakedPctOfSupply } from './utils/supply.js'; type StakingProviderProps = { network: AuroraNetwork; @@ -319,11 +319,11 @@ export const StakingProvider = ({ return; } - const newStakedPct = calculateStakedPctOfSupply( + const newStakedPct = calculateStakedPctOfSupply({ totalStaked, - newPrice, - newMarketCap, - ); + auroraPrice: newPrice, + auroraMarketCap: newMarketCap, + }); setStakedPct(newStakedPct); }, [ diff --git a/src/utils/staking.ts b/src/utils/staking.ts index ef95c38..cf462c7 100644 --- a/src/utils/staking.ts +++ b/src/utils/staking.ts @@ -220,19 +220,6 @@ export const getVoteSupply = (voteSchedule: StreamSchedule): BigNumber => { return circulatingSupply; }; -export const calculateStakedPctOfSupply = ( - totalStaked: BigNumber, - auroraPrice: number, - auroraMarketCap: number, -): number => { - const circulatingSupply = auroraMarketCap / auroraPrice; - // Compounding staked AURORA - const stakedAurora = Number(ethers.utils.formatUnits(totalStaked, 18)); - const pct = (stakedAurora * 100) / circulatingSupply; - - return pct; -}; - export const getIsPaused = async ( provider: providers.JsonRpcProvider, networkConfig: AuroraNetworkConfig, diff --git a/src/utils/supply.ts b/src/utils/supply.ts new file mode 100644 index 0000000..8996974 --- /dev/null +++ b/src/utils/supply.ts @@ -0,0 +1,20 @@ +import { BigNumber, ethers } from 'ethers'; + +export const calculateStakedPctOfSupply = ({ + totalStaked, + auroraPrice, + auroraMarketCap, +}: { + totalStaked: BigNumber; + auroraPrice: number; + auroraMarketCap: number; +}): number => { + const circulatingSupply = auroraMarketCap / auroraPrice; + const compoundingStakedAurora = Number( + ethers.utils.formatUnits(totalStaked, 18), + ); + + const pct = (compoundingStakedAurora * 100) / circulatingSupply; + + return pct; +}; diff --git a/tests/utils/apr.test.ts b/tests/fixtures/streams-schedule.ts similarity index 56% rename from tests/utils/apr.test.ts rename to tests/fixtures/streams-schedule.ts index a0b00e4..90b4cf5 100644 --- a/tests/utils/apr.test.ts +++ b/tests/fixtures/streams-schedule.ts @@ -1,12 +1,7 @@ import { BigNumber } from 'ethers'; -import { calculateAprs } from '../../src/utils/apr'; - -jest.useFakeTimers(); - -const currentDate = new Date('2024-11-13T12:00:00Z'); // A snapshot of data logged from Aurora Plus -const streamsSchedule = [ +export const streamsSchedule = [ { scheduleTimes: [ BigNumber.from('0x6283b870'), @@ -118,111 +113,3 @@ const streamsSchedule = [ ], }, ]; - -const totalStaked = BigNumber.from('50000000000000000000000000'); -const streamDecimals = [18, 18, 18, 18, 18, 18]; -const streamPrices = [ - 0.135344, 0.00007611, 0.00141883, 0.00000127, 0.245603, 0, -]; - -describe('APR', () => { - beforeEach(() => { - jest.setSystemTime(new Date(currentDate)); - }); - - describe('calculateAprs', () => { - it('returns the expected APR', async () => { - const result = calculateAprs({ - streamsSchedule, - streamPrices, - streamDecimals, - totalStaked, - }); - - expect(result).toEqual({ - aurora: 13.65590130885746, - streams: [0, 0, 0, 0, 0], - total: 13.65590130885746, - }); - }); - - it('modifies the APR according to the total amount staked', async () => { - const result = calculateAprs({ - streamsSchedule, - streamPrices, - streamDecimals, - totalStaked: BigNumber.from('100000000000000000000000000'), - }); - - expect(result).toEqual({ - aurora: 6.82795065442873, - streams: [0, 0, 0, 0, 0], - total: 6.82795065442873, - }); - }); - - it('returns an APR of 0 if all rewards are active after the current date', async () => { - jest.setSystemTime(new Date('2020-01-01T12:00:00Z')); - - const result = calculateAprs({ - streamsSchedule, - streamPrices, - streamDecimals, - totalStaked, - }); - - expect(result).toEqual({ - aurora: 0, - streams: [0, 0, 0, 0, 0], - total: 0, - }); - }); - - it('returns an APR of 0 if all rewards were active before the current date', async () => { - jest.setSystemTime(new Date('2030-01-01T12:00:00Z')); - - const result = calculateAprs({ - streamsSchedule, - streamPrices, - streamDecimals, - totalStaked, - }); - - expect(result).toEqual({ - aurora: 0, - streams: [0, 0, 0, 0, 0], - total: 0, - }); - }); - - it('returns an APR of 0 if all stream prices are zero', async () => { - jest.setSystemTime(new Date('2020-01-01T12:00:00Z')); - - const result = calculateAprs({ - streamsSchedule, - streamPrices: Array(streamPrices.length).fill(0), - streamDecimals, - totalStaked, - }); - - expect(result).toEqual({ - aurora: 0, - streams: [0, 0, 0, 0, 0], - total: 0, - }); - }); - - it('throws if a stream price is missing', async () => { - jest.setSystemTime(new Date('2020-01-01T12:00:00Z')); - - expect(() => { - calculateAprs({ - streamsSchedule, - streamPrices: [], - streamDecimals, - totalStaked, - }); - }).toThrow('No stream price at position 0'); - }); - }); -}); diff --git a/tests/specs/utils/apr.test.ts b/tests/specs/utils/apr.test.ts new file mode 100644 index 0000000..a64fe11 --- /dev/null +++ b/tests/specs/utils/apr.test.ts @@ -0,0 +1,116 @@ +import { BigNumber } from 'ethers'; +import { calculateAprs } from '../../../src/utils/apr'; +import { streamsSchedule } from '../../fixtures/streams-schedule'; +import { getNumberTo18Decimals } from '../../utils/get-number-to-18-decimals'; + +jest.useFakeTimers(); + +const currentDate = new Date('2024-11-13T12:00:00Z'); + +const totalStaked = getNumberTo18Decimals(50000000); +const streamDecimals = [18, 18, 18, 18, 18, 18]; +const streamPrices = [ + 0.135344, 0.00007611, 0.00141883, 0.00000127, 0.245603, 0, +]; + +describe('APR', () => { + beforeEach(() => { + jest.setSystemTime(new Date(currentDate)); + }); + + describe('calculateAprs', () => { + it('returns the expected APR', async () => { + const result = calculateAprs({ + streamsSchedule, + streamPrices, + streamDecimals, + totalStaked, + }); + + expect(result).toEqual({ + aurora: 13.65590130885746, + streams: [0, 0, 0, 0, 0], + total: 13.65590130885746, + }); + }); + + it('modifies the APR according to the total amount staked', async () => { + const result = calculateAprs({ + streamsSchedule, + streamPrices, + streamDecimals, + totalStaked: BigNumber.from('100000000000000000000000000'), + }); + + expect(result).toEqual({ + aurora: 6.82795065442873, + streams: [0, 0, 0, 0, 0], + total: 6.82795065442873, + }); + }); + + it('returns an APR of 0 if all rewards are active after the current date', async () => { + jest.setSystemTime(new Date('2020-01-01T12:00:00Z')); + + const result = calculateAprs({ + streamsSchedule, + streamPrices, + streamDecimals, + totalStaked, + }); + + expect(result).toEqual({ + aurora: 0, + streams: [0, 0, 0, 0, 0], + total: 0, + }); + }); + + it('returns an APR of 0 if all rewards were active before the current date', async () => { + jest.setSystemTime(new Date('2030-01-01T12:00:00Z')); + + const result = calculateAprs({ + streamsSchedule, + streamPrices, + streamDecimals, + totalStaked, + }); + + expect(result).toEqual({ + aurora: 0, + streams: [0, 0, 0, 0, 0], + total: 0, + }); + }); + + it('returns an APR of 0 if all stream prices are zero', async () => { + jest.setSystemTime(new Date('2020-01-01T12:00:00Z')); + + const result = calculateAprs({ + streamsSchedule, + streamPrices: Array(streamPrices.length).fill(0), + streamDecimals, + totalStaked, + }); + + expect(result).toEqual({ + aurora: 0, + streams: [0, 0, 0, 0, 0], + total: 0, + }); + }); + + it('throws if a stream price is missing', async () => { + jest.setSystemTime(new Date('2020-01-01T12:00:00Z')); + + expect(() => { + calculateAprs({ + streamsSchedule, + streamPrices: [], + streamDecimals, + totalStaked, + }); + }).toThrow('No stream price at position 0'); + }); + }); +}); diff --git a/tests/specs/utils/supply.test.ts b/tests/specs/utils/supply.test.ts new file mode 100644 index 0000000..8ce12e8 --- /dev/null +++ b/tests/specs/utils/supply.test.ts @@ -0,0 +1,26 @@ +import { calculateStakedPctOfSupply } from '../../../src/utils/supply'; +import { getNumberTo18Decimals } from '../../utils/get-number-to-18-decimals'; + +describe('APR', () => { + describe('calculateStakedPctOfSupply', () => { + it('returns the expected result with 1% staked', () => { + const result = calculateStakedPctOfSupply({ + totalStaked: getNumberTo18Decimals(1000), + auroraPrice: 0.1, + auroraMarketCap: 10000, + }); + + expect(result).toBe(1); + }); + + it('returns the expected result with 50% staked', () => { + const result = calculateStakedPctOfSupply({ + totalStaked: getNumberTo18Decimals(50000), + auroraPrice: 0.1, + auroraMarketCap: 10000, + }); + + expect(result).toBe(50); + }); + }); +}); diff --git a/tests/utils/get-number-to-18-decimals.ts b/tests/utils/get-number-to-18-decimals.ts new file mode 100644 index 0000000..0873728 --- /dev/null +++ b/tests/utils/get-number-to-18-decimals.ts @@ -0,0 +1,5 @@ +import { BigNumber } from 'ethers'; + +export const getNumberTo18Decimals = (number: number) => { + return BigNumber.from(`${number}${'0'.repeat(18)}`); +};