Skip to content

Commit

Permalink
Change My earnings chart timeframes
Browse files Browse the repository at this point in the history
  • Loading branch information
yivlad committed Dec 19, 2024
1 parent 6b0129d commit aa52251
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 91 deletions.
Original file line number Diff line number Diff line change
@@ -1,77 +1,23 @@
import { SavingsInfo } from '@/domain/savings-info/types'
import { range } from '@/utils/array'
import { assertNever } from '@/utils/assertNever'
import { NormalizedUnitNumber } from '@marsfoundation/common-universal'
import { MyEarningsTimeframe } from './common'
import { MyEarningsInfoItem } from './types'

const SECONDS_PER_DAY = 24 * 60 * 60

export interface CalculatePredictionsParams {
timestamp: number // in seconds
shares: NormalizedUnitNumber
savingsInfo: SavingsInfo
timeframe: MyEarningsTimeframe
dataLength: number
}

export function calculatePredictions({
timestamp,
shares,
savingsInfo,
timeframe,
dataLength,
}: CalculatePredictionsParams): MyEarningsInfoItem[] {
const optimalPredictionsLength = Math.floor(dataLength * 1.66)

switch (timeframe) {
case '7D':
return calculatePredictionsIncomeByDays({
days: Math.max(optimalPredictionsLength, 7),
shares,
timestamp,
savingsInfo,
step: 1,
})

case '1M':
return calculatePredictionsIncomeByDays({
days: Math.max(optimalPredictionsLength, 30),
shares,
timestamp,
savingsInfo,
step: 1,
})

case '1Y':
case 'All':
return calculatePredictionsIncomeByDays({
// setting upper bounds due to visible performance problems
days: Math.max(Math.min(optimalPredictionsLength, 360), 90),
shares,
timestamp,
savingsInfo,
step: 3,
})

default:
assertNever(timeframe)
}
}

function calculatePredictionsIncomeByDays({
days,
savingsInfo,
shares,
timestamp,
step,
}: {
days: number
savingsInfo: SavingsInfo
shares: NormalizedUnitNumber
timestamp: number
step: number
}): MyEarningsInfoItem[] {
const step = days > 366 ? 3 : 1

// @note For today we have only current balance (with slight delay) but we need also balance for next data-point
return range(0, days, step).map((day) => {
const dayTimestamp = timestamp + day * SECONDS_PER_DAY
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Timeframe } from '@/ui/charts/defaults'

export const MY_EARNINGS_TIMEFRAMES = ['7D', '1M', '1Y', 'All'] as const satisfies Timeframe[]
export const MY_EARNINGS_TIMEFRAMES = ['1M', '1Y', '3Y', 'All'] as const satisfies Timeframe[]
export type MyEarningsTimeframe = (typeof MY_EARNINGS_TIMEFRAMES)[number]
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { TokenWithBalance } from '@/domain/common/types'
import { SavingsInfo } from '@/domain/savings-info/types'
import { filterDataByTimeframe } from '@/ui/charts/utils'
import { assertNever } from '@marsfoundation/common-universal'
import { calculatePredictions } from './calculatePredictions'
import { MyEarningsTimeframe } from './common'
import { MyEarningsInfoItem } from './types'
Expand Down Expand Up @@ -42,12 +43,28 @@ export function getFilteredEarningsWithPredictions({
balance: savingsInfo.convertToAssets({ shares: savingsTokenWithBalance.balance }),
}

const predictionsLength = Math.ceil(
(() => {
switch (timeframe) {
case '1M':
return 30 * 0.5
case '1Y':
return 365 * 0.5
case '3Y':
return 365 * 1.5
case 'All':
return 365 * 3
default:
assertNever(timeframe)
}
})(),
)

const calculatedPredictions = calculatePredictions({
savingsInfo,
timeframe,
timestamp: Math.floor(getEndOfDayTimestamp(todaysItem.date) / 1000),
shares: savingsTokenWithBalance.balance,
dataLength: filteredData.length,
days: predictionsLength,
})

filteredData.push(todaysItem)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ const myEarningsInfo = {
error: null,
},
shouldDisplayMyEarnings: true,
selectedTimeframe: '7D',
selectedTimeframe: '1M',
setSelectedTimeframe: () => {},
availableTimeframes: MY_EARNINGS_TIMEFRAMES,
} satisfies UseMyEarningsInfoResult
Expand Down
67 changes: 36 additions & 31 deletions packages/app/src/ui/charts/utils.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { USD_MOCK_TOKEN } from '@/domain/types/Token'
import { NormalizedUnitNumber } from '@marsfoundation/common-universal'
import { NormalizedUnitNumber, assertNever } from '@marsfoundation/common-universal'
import { Timeframe } from './defaults'

export function formatTooltipDate(date: Date): string {
Expand Down Expand Up @@ -34,40 +34,45 @@ export function filterDataByTimeframe<Data extends { date: Date }>({
}: FilterDataByTimeframeParams<Data>): Data[] {
const now = new Date(currentTimestamp * 1000)

switch (timeframe) {
case '7D': {
const sevenDaysAgo = new Date(now)
sevenDaysAgo.setDate(now.getDate() - 7)
return data.filter((d) => new Date(d.date) >= sevenDaysAgo)
}

case '1M': {
const oneMonthAgo = new Date(now)
oneMonthAgo.setMonth(now.getMonth() - 1)
return data.filter((d) => new Date(d.date) >= oneMonthAgo)
}

case '3M': {
const threeMonthsAgo = new Date(now)
threeMonthsAgo.setMonth(now.getMonth() - 3)
return data.filter((d) => new Date(d.date) >= threeMonthsAgo)
}
if (timeframe === 'All') {
return data
}

case '1Y': {
const oneYearAgo = new Date(now)
oneYearAgo.setFullYear(now.getFullYear() - 1)
return data.filter((d) => new Date(d.date) >= oneYearAgo)
const cutoff = (() => {
switch (timeframe) {
case '7D': {
const sevenDaysAgo = new Date(now)
sevenDaysAgo.setDate(now.getDate() - 7)
return sevenDaysAgo
}
case '1M': {
const oneMonthAgo = new Date(now)
oneMonthAgo.setMonth(now.getMonth() - 1)
return oneMonthAgo
}
case '3M': {
const threeMonthsAgo = new Date(now)
threeMonthsAgo.setMonth(now.getMonth() - 3)
return threeMonthsAgo
}
case '1Y': {
const oneYearAgo = new Date(now)
oneYearAgo.setFullYear(now.getFullYear() - 1)
return oneYearAgo
}
case '3Y': {
const threeYearsAgo = new Date(now)
threeYearsAgo.setFullYear(now.getFullYear() - 3)
return threeYearsAgo
}
default:
assertNever(timeframe)
}
})()

case '3Y': {
const threeYearsAgo = new Date(now)
threeYearsAgo.setFullYear(now.getFullYear() - 3)
return data.filter((d) => new Date(d.date) >= threeYearsAgo)
}
const filteredData = data.filter((d) => new Date(d.date) >= cutoff)

case 'All':
return data
}
return filteredData
}

export function getVerticalDomainWithPadding(min: number, max: number): [number, number] {
Expand Down

0 comments on commit aa52251

Please sign in to comment.