From a50ce8437e4c3a5070452084e012700740885799 Mon Sep 17 00:00:00 2001 From: jorbuedo Date: Fri, 20 Sep 2024 12:53:11 +0200 Subject: [PATCH 1/2] feature(wallet-mobile): design improvements in portfolio (#3640) --- .../src/assets/img/chart-placeholder.png | Bin 5329 -> 0 bytes .../src/assets/img/chart-placeholder@2x.png | Bin 12563 -> 0 bytes .../src/assets/img/chart-placeholder@3x.png | Bin 20318 -> 0 bytes .../PairedBalance/PairedBalance.tsx | 2 +- .../common/hooks/useGetPortfolioTokenChart.ts | 106 ++++++++---------- .../DashboardTokenItem.tsx | 2 +- .../PortfolioTokenChart/ChartPlaceholder.tsx | 19 ++++ .../PortfolioTokenChart.tsx | 8 +- .../PortfolioTokenChartSkeleton.tsx | 15 +-- .../PortfolioTokenChart/TokenPerformance.tsx | 42 ++++--- .../PortfolioTokenDetailsScreen.tsx | 14 +-- .../TokenBalanceItem.tsx | 2 +- .../PairedBalance/PairedBalance.json | 4 +- 13 files changed, 107 insertions(+), 107 deletions(-) delete mode 100644 apps/wallet-mobile/src/assets/img/chart-placeholder.png delete mode 100644 apps/wallet-mobile/src/assets/img/chart-placeholder@2x.png delete mode 100644 apps/wallet-mobile/src/assets/img/chart-placeholder@3x.png create mode 100644 apps/wallet-mobile/src/features/Portfolio/useCases/PortfolioTokenDetails/PortfolioTokenChart/ChartPlaceholder.tsx diff --git a/apps/wallet-mobile/src/assets/img/chart-placeholder.png b/apps/wallet-mobile/src/assets/img/chart-placeholder.png deleted file mode 100644 index 383d949c9ff2e98b1c0f310c0fe0e0b85867ae29..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5329 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 { if (isPrivacyActive && !ignorePrivacy) return `${privacyPlaceholder} ${currency}` - if (!isPrimaryToken(amount.info) && tokenPrice == null) return `—— ${currency}` + if (!isPrimaryToken(amount.info) && tokenPrice == null) return `— ${currency}` if (hidePrimaryPair && isPrimaryToken(amount.info) && isPrimaryTokenActive) return '' diff --git a/apps/wallet-mobile/src/features/Portfolio/common/hooks/useGetPortfolioTokenChart.ts b/apps/wallet-mobile/src/features/Portfolio/common/hooks/useGetPortfolioTokenChart.ts index 0ef0471d1c..431878febf 100644 --- a/apps/wallet-mobile/src/features/Portfolio/common/hooks/useGetPortfolioTokenChart.ts +++ b/apps/wallet-mobile/src/features/Portfolio/common/hooks/useGetPortfolioTokenChart.ts @@ -1,12 +1,14 @@ import {isRight} from '@yoroi/common' import {isPrimaryToken} from '@yoroi/portfolio' -import {Chain} from '@yoroi/types' +import {Chain, Portfolio} from '@yoroi/types' import {useQuery, UseQueryOptions} from 'react-query' import {supportedCurrencies, time} from '../../../../kernel/constants' import {useLanguage} from '../../../../kernel/i18n' +import {logger} from '../../../../kernel/logger/logger' import {fetchPtPriceActivity} from '../../../../yoroi-wallets/cardano/usePrimaryTokenActivity' import {useCurrencyPairing} from '../../../Settings/Currency/CurrencyContext' +import {useSelectedNetwork} from '../../../WalletManager/common/hooks/useSelectedNetwork' import {useSelectedWallet} from '../../../WalletManager/common/hooks/useSelectedWallet' import {networkConfigs} from '../../../WalletManager/network-manager/network-manager' import {priceChange} from '../helpers/priceChange' @@ -30,60 +32,6 @@ type TokenChartData = { changeValue: number } -function generateMockChartData(timeInterval: TokenChartInterval = TOKEN_CHART_INTERVAL.DAY): TokenChartData[] { - const dataPoints = 50 - const startValue = 100 - const volatility = 50 - - const startDate = new Date('2024-02-02T15:09:00') - - function getTimeIncrement(interval: TokenChartInterval): number { - switch (interval) { - case TOKEN_CHART_INTERVAL.DAY: - return 60 * 60 * 1000 // 1 hour - case TOKEN_CHART_INTERVAL.WEEK: - return 24 * 60 * 60 * 1000 // 1 day - case TOKEN_CHART_INTERVAL.MONTH: - return 30 * 24 * 60 * 60 * 1000 // 1 month (approximated as 30 days) - case TOKEN_CHART_INTERVAL.SIX_MONTHS: - return 6 * 30 * 24 * 60 * 60 * 1000 // 6 months - case TOKEN_CHART_INTERVAL.YEAR: - return 12 * 30 * 24 * 60 * 60 * 1000 // 1 year (approximated as 360 days) - default: - return 60 * 1000 // Default to 1 minute - } - } - - const increment = getTimeIncrement(timeInterval) - const chartData: TokenChartData[] = [] - - let previousValue = startValue - - for (let i = 0; i < dataPoints; i++) { - const date = new Date(startDate.getTime() + i * increment) - const label = `${date.getDate().toString().padStart(2, '0')}/${(date.getMonth() + 1) - .toString() - .padStart(2, '0')}/${date.getFullYear().toString().substr(-2)} ${date.getHours()}:${date - .getMinutes() - .toString() - .padStart(2, '0')}` - const value = i === 0 ? startValue : previousValue + (Math.random() - 0.5) * volatility - const changeValue = i === 0 ? 0 : value - previousValue - const changePercent = i === 0 ? 0 : (changeValue / previousValue) * 100 - - chartData.push({ - label, - value, - changePercent, - changeValue, - }) - - previousValue = value // Update previousValue for the next iteration - } - - return chartData -} - const getTimestamps = (timeInterval: TokenChartInterval) => { const now = Date.now() const [from, resolution] = { @@ -104,9 +52,9 @@ const ptTicker = networkConfigs[Chain.Network.Mainnet].primaryTokenInfo.ticker export const useGetPortfolioTokenChart = ( timeInterval = TOKEN_CHART_INTERVAL.DAY as TokenChartInterval, options: UseQueryOptions< - TokenChartData[], + TokenChartData[] | null, Error, - TokenChartData[], + TokenChartData[] | null, ['useGetPortfolioTokenChart', string, TokenChartInterval, ReturnType['currency']?] > = {}, ) => { @@ -114,6 +62,9 @@ export const useGetPortfolioTokenChart = ( const { wallet: {balances}, } = useSelectedWallet() + const { + networkManager: {tokenManager}, + } = useSelectedNetwork() const tokenInfo = balances.records.get(tokenId) const {currency} = useCurrencyPairing() const {languageCode} = useLanguage() @@ -135,6 +86,8 @@ export const useGetPortfolioTokenChart = ( if (response.value.data.error) throw new Error(response.value.data.error) const tickers = response.value.data.tickers + if (tickers.length === 0) return null + const validCurrency = currency === ptTicker ? supportedCurrencies.USD : currency ?? supportedCurrencies.USD const initialPrice = tickers[0].prices[validCurrency] @@ -153,7 +106,8 @@ export const useGetPortfolioTokenChart = ( return records } - throw new Error('Failed to fetch token chart data') + logger.error('Failed to fetch token chart data for PT') + return null }, }) @@ -164,10 +118,42 @@ export const useGetPortfolioTokenChart = ( ...options, queryKey: ['useGetPortfolioTokenChart', tokenInfo?.info.id ?? '', timeInterval], queryFn: async () => { - await new Promise((resolve) => setTimeout(resolve, 1)) - return generateMockChartData(timeInterval) + const response = await tokenManager.api.tokenHistory(tokenId, chartIntervalToHistoryPeriod(timeInterval)) + if (isRight(response)) { + const prices = response.value.data.prices + + if (prices.length === 0) return null + + const initialPrice = prices[0].open.toNumber() + const records = prices + .map((price) => { + const value = price.close.toNumber() + if (value === undefined) return undefined + const {changePercent, changeValue} = priceChange(initialPrice, value) + const label = new Date(price.ts).toLocaleString(languageCode, { + dateStyle: 'short', + timeStyle: 'short', + }) + return {label, value, changePercent, changeValue} + }) + .filter(Boolean) as TokenChartData[] + + return records + } + logger.error(`Failed to fetch token chart data for ${tokenId}`) + return null }, }) return tokenInfo && isPrimaryToken(tokenInfo.info) ? ptQuery : otherQuery } + +const chartIntervalToHistoryPeriod = (i: TokenChartInterval): Portfolio.Token.HistoryPeriod => + ({ + [TOKEN_CHART_INTERVAL.DAY]: Portfolio.Token.HistoryPeriod.OneDay, + [TOKEN_CHART_INTERVAL.WEEK]: Portfolio.Token.HistoryPeriod.OneWeek, + [TOKEN_CHART_INTERVAL.MONTH]: Portfolio.Token.HistoryPeriod.OneMonth, + [TOKEN_CHART_INTERVAL.SIX_MONTHS]: Portfolio.Token.HistoryPeriod.SixMonth, + [TOKEN_CHART_INTERVAL.YEAR]: Portfolio.Token.HistoryPeriod.OneYear, + [TOKEN_CHART_INTERVAL.ALL]: Portfolio.Token.HistoryPeriod.All, + }[i] ?? Portfolio.Token.HistoryPeriod.OneDay) diff --git a/apps/wallet-mobile/src/features/Portfolio/useCases/PortfolioDashboard/DashboardTokensList/DashboardTokenItem.tsx b/apps/wallet-mobile/src/features/Portfolio/useCases/PortfolioDashboard/DashboardTokensList/DashboardTokenItem.tsx index 35e5f00441..db49a33b5f 100644 --- a/apps/wallet-mobile/src/features/Portfolio/useCases/PortfolioDashboard/DashboardTokensList/DashboardTokenItem.tsx +++ b/apps/wallet-mobile/src/features/Portfolio/useCases/PortfolioDashboard/DashboardTokensList/DashboardTokenItem.tsx @@ -48,7 +48,7 @@ export const DashboardTokenItem = ({tokenInfo}: Props) => { - {isMissingPrices ? '—— ' : formatPriceChange(changePercent)}% + {isMissingPrices ? '— ' : formatPriceChange(changePercent)}% diff --git a/apps/wallet-mobile/src/features/Portfolio/useCases/PortfolioTokenDetails/PortfolioTokenChart/ChartPlaceholder.tsx b/apps/wallet-mobile/src/features/Portfolio/useCases/PortfolioTokenDetails/PortfolioTokenChart/ChartPlaceholder.tsx new file mode 100644 index 0000000000..d9ac221f88 --- /dev/null +++ b/apps/wallet-mobile/src/features/Portfolio/useCases/PortfolioTokenDetails/PortfolioTokenChart/ChartPlaceholder.tsx @@ -0,0 +1,19 @@ +import {useTheme} from '@yoroi/theme' +import React from 'react' +import {useWindowDimensions} from 'react-native' +import Svg, {Path} from 'react-native-svg' + +export const ChartPlaceholder = () => { + const {width} = useWindowDimensions() + const {color} = useTheme() + + return ( + + + + ) +} diff --git a/apps/wallet-mobile/src/features/Portfolio/useCases/PortfolioTokenDetails/PortfolioTokenChart/PortfolioTokenChart.tsx b/apps/wallet-mobile/src/features/Portfolio/useCases/PortfolioTokenDetails/PortfolioTokenChart/PortfolioTokenChart.tsx index 1f7d11afd6..3bb1067dfb 100644 --- a/apps/wallet-mobile/src/features/Portfolio/useCases/PortfolioTokenDetails/PortfolioTokenChart/PortfolioTokenChart.tsx +++ b/apps/wallet-mobile/src/features/Portfolio/useCases/PortfolioTokenDetails/PortfolioTokenChart/PortfolioTokenChart.tsx @@ -7,6 +7,7 @@ import { TOKEN_CHART_INTERVAL, useGetPortfolioTokenChart, } from '../../../common/hooks/useGetPortfolioTokenChart' +import {ChartPlaceholder} from './ChartPlaceholder' import {PortfolioTokenChartSkeleton} from './PortfolioTokenChartSkeleton' import {TokenChart} from './TokenChart' import {TokenChartToolbar} from './TokenChartToolBar' @@ -29,16 +30,16 @@ export const PortfolioTokenChart = () => { return ( - {isFetching || !data ? ( + {isFetching ? ( ) : ( <> - + {!data ? : } )} @@ -49,6 +50,7 @@ export const PortfolioTokenChart = () => { const useStyles = () => { const {atoms} = useTheme() + const styles = StyleSheet.create({ root: { ...atoms.flex_1, diff --git a/apps/wallet-mobile/src/features/Portfolio/useCases/PortfolioTokenDetails/PortfolioTokenChart/PortfolioTokenChartSkeleton.tsx b/apps/wallet-mobile/src/features/Portfolio/useCases/PortfolioTokenDetails/PortfolioTokenChart/PortfolioTokenChartSkeleton.tsx index 138b6c69f6..c452a0f45c 100644 --- a/apps/wallet-mobile/src/features/Portfolio/useCases/PortfolioTokenDetails/PortfolioTokenChart/PortfolioTokenChartSkeleton.tsx +++ b/apps/wallet-mobile/src/features/Portfolio/useCases/PortfolioTokenDetails/PortfolioTokenChart/PortfolioTokenChartSkeleton.tsx @@ -1,10 +1,9 @@ import {useTheme} from '@yoroi/theme' import * as React from 'react' -import {Image, StyleSheet, View} from 'react-native' +import {StyleSheet, View} from 'react-native' import SkeletonPlaceholder from 'react-native-skeleton-placeholder' -import ChartPlaceholder from '../../../../../assets/img/chart-placeholder.png' -import {Icon} from '../../../../../components/Icon' +import {ChartPlaceholder} from './ChartPlaceholder' export const PortfolioTokenChartSkeleton = () => { const {color, styles} = useStyles() @@ -19,8 +18,6 @@ export const PortfolioTokenChartSkeleton = () => { - - @@ -28,7 +25,7 @@ export const PortfolioTokenChartSkeleton = () => { - + ) } @@ -51,12 +48,6 @@ const useStyles = () => { ...atoms.align_center, ...atoms.gap_2xs, }, - chartPlaceholder: { - height: 112, - width: '100%', - marginVertical: 16, - resizeMode: 'stretch', - }, }) return {styles, color} as const } diff --git a/apps/wallet-mobile/src/features/Portfolio/useCases/PortfolioTokenDetails/PortfolioTokenChart/TokenPerformance.tsx b/apps/wallet-mobile/src/features/Portfolio/useCases/PortfolioTokenDetails/PortfolioTokenChart/TokenPerformance.tsx index bbe0c21850..b14eaef25b 100644 --- a/apps/wallet-mobile/src/features/Portfolio/useCases/PortfolioTokenDetails/PortfolioTokenChart/TokenPerformance.tsx +++ b/apps/wallet-mobile/src/features/Portfolio/useCases/PortfolioTokenDetails/PortfolioTokenChart/TokenPerformance.tsx @@ -3,7 +3,6 @@ import {useTheme} from '@yoroi/theme' import * as React from 'react' import {StyleSheet, View} from 'react-native' -import {Icon} from '../../../../../components/Icon' import {Text} from '../../../../../components/Text' import {Tooltip} from '../../../../../components/Tooltip/Tooltip' import {useCurrencyPairing} from '../../../../Settings/Currency/CurrencyContext' @@ -13,7 +12,7 @@ import {useStrings} from '../../../common/hooks/useStrings' import {PnlTag} from '../../../common/PnlTag/PnlTag' type Props = { - tokenPerformance: { + tokenPerformance?: { changePercent: number changeValue: number value: number @@ -27,11 +26,12 @@ export const TokenPerformance = ({tokenPerformance, timeInterval}: Props) => { const {currency, config} = useCurrencyPairing() const variant = React.useMemo(() => { + if (!tokenPerformance) return 'neutral' if (Number(tokenPerformance.changePercent) > 0) return 'success' if (Number(tokenPerformance.changePercent) < 0) return 'danger' return 'neutral' - }, [tokenPerformance.changePercent]) + }, [tokenPerformance]) const intervalLabel = React.useMemo(() => { switch (timeInterval) { @@ -54,25 +54,31 @@ export const TokenPerformance = ({tokenPerformance, timeInterval}: Props) => { return ( - - - {formatPriceChange(tokenPerformance.changePercent)}% - + + + + {!tokenPerformance ? '—' : formatPriceChange(tokenPerformance.changePercent)}% + - {`${formatPriceChange( - tokenPerformance.changeValue, - config.decimals, - )} ${currency}`} - - - - - + {`${ + !tokenPerformance ? '—' : formatPriceChange(tokenPerformance.changeValue, config.decimals) + } ${currency}`} + + - {formatPriceChange(tokenPerformance.value, config.decimals)} + {!tokenPerformance ? ( + + ) : ( + <> + {formatPriceChange(tokenPerformance.value, config.decimals)} - {currency} + {currency} + + )} ) diff --git a/apps/wallet-mobile/src/features/Portfolio/useCases/PortfolioTokenDetails/PortfolioTokenDetailsScreen.tsx b/apps/wallet-mobile/src/features/Portfolio/useCases/PortfolioTokenDetails/PortfolioTokenDetailsScreen.tsx index 43263f40f6..f0c284a3af 100644 --- a/apps/wallet-mobile/src/features/Portfolio/useCases/PortfolioTokenDetails/PortfolioTokenDetailsScreen.tsx +++ b/apps/wallet-mobile/src/features/Portfolio/useCases/PortfolioTokenDetails/PortfolioTokenDetailsScreen.tsx @@ -1,4 +1,3 @@ -import {isPrimaryTokenInfo} from '@yoroi/portfolio' import {useTheme} from '@yoroi/theme' import {App} from '@yoroi/types' import * as React from 'react' @@ -30,6 +29,9 @@ const tabs: Record = { overview: 'Overview', transactions: 'Transactions', } + +const HEADER_HEIGHT = 304 + export const PortfolioTokenDetailsScreen = () => { const strings = useStrings() const {activeTab, setActiveTab} = usePortfolioTokenDetailContext() @@ -38,8 +40,6 @@ export const PortfolioTokenDetailsScreen = () => { const {id: tokenId} = usePortfolioTokenDetailParams() const {wallet} = useSelectedWallet() const tokenInfo = wallet.balances.records.get(tokenId)?.info - const isPrimaryToken = isPrimaryTokenInfo(tokenInfo) - const HEADER_HEIGHT = isPrimaryToken ? 304 : 85 // Graph only in PT const {styles} = useStyles(HEADER_HEIGHT) if (!tokenInfo) throwLoggedError(new App.Errors.InvalidState('Token info not found, invalid state')) @@ -100,13 +100,9 @@ export const PortfolioTokenDetailsScreen = () => { - {isPrimaryToken && ( - <> - + - - - )} + {renderTabs} diff --git a/apps/wallet-mobile/src/features/Portfolio/useCases/PortfolioTokensList/PortfolioWalletTokenList/TokenBalanceItem.tsx b/apps/wallet-mobile/src/features/Portfolio/useCases/PortfolioTokensList/PortfolioWalletTokenList/TokenBalanceItem.tsx index 923e0f5516..43ae21f7d8 100644 --- a/apps/wallet-mobile/src/features/Portfolio/useCases/PortfolioTokensList/PortfolioWalletTokenList/TokenBalanceItem.tsx +++ b/apps/wallet-mobile/src/features/Portfolio/useCases/PortfolioTokensList/PortfolioWalletTokenList/TokenBalanceItem.tsx @@ -53,7 +53,7 @@ export const TokenBalanceItem = ({amount}: Props) => { - {isMissingPrices ? '—— ' : formatPriceChange(changePercent)}% + {isMissingPrices ? '— ' : formatPriceChange(changePercent)}% diff --git a/apps/wallet-mobile/translations/messages/src/components/PairedBalance/PairedBalance.json b/apps/wallet-mobile/translations/messages/src/components/PairedBalance/PairedBalance.json index cc74c5db5c..33ff0e463c 100644 --- a/apps/wallet-mobile/translations/messages/src/components/PairedBalance/PairedBalance.json +++ b/apps/wallet-mobile/translations/messages/src/components/PairedBalance/PairedBalance.json @@ -6,12 +6,12 @@ "start": { "line": 107, "column": 22, - "index": 3610 + "index": 3609 }, "end": { "line": 110, "column": 3, - "index": 3742 + "index": 3741 } } ] \ No newline at end of file From de98527b257f01cdd6fdfb2feb8a0cacfb529bca Mon Sep 17 00:00:00 2001 From: Michal S Date: Fri, 20 Sep 2024 12:39:03 +0100 Subject: [PATCH 2/2] fix(wallet-mobile): Use absolute slot number when creating a TX (#3642) --- .../helpers/date-to-epoch-info.test.ts | 5 +++ .../helpers/date-to-epoch-info.ts | 1 + .../helpers/epoch-progress.test.ts | 6 ++++ .../network-manager/helpers/epoch-progress.ts | 29 ++++++++++++---- .../yoroi-wallets/cardano/cardano-wallet.ts | 34 +++++++------------ packages/types/src/network/manager.ts | 2 ++ 6 files changed, 49 insertions(+), 28 deletions(-) diff --git a/apps/wallet-mobile/src/features/WalletManager/network-manager/helpers/date-to-epoch-info.test.ts b/apps/wallet-mobile/src/features/WalletManager/network-manager/helpers/date-to-epoch-info.test.ts index 032bddaf2e..1d313b544e 100644 --- a/apps/wallet-mobile/src/features/WalletManager/network-manager/helpers/date-to-epoch-info.test.ts +++ b/apps/wallet-mobile/src/features/WalletManager/network-manager/helpers/date-to-epoch-info.test.ts @@ -18,6 +18,7 @@ describe('dateToEpochInfo', () => { start: new Date('2024-05-09T21:44:51.000Z'), end: new Date('2024-05-14T21:44:51.000Z'), era: shelleyEraConfig, + eras: networkManagers[Chain.Network.Mainnet].eras, } const result = convertDateToEpoch(inputDate) @@ -42,6 +43,7 @@ describe('dateToEpochInfo', () => { start: new Date('2017-09-23T21:44:51.000Z'), end: new Date('2017-09-28T21:44:51.000Z'), era: byronEraConfig, + eras: networkManagers[Chain.Network.Mainnet].eras, } const result = convertDateToEpoch(inputDate) @@ -58,6 +60,7 @@ describe('dateToEpochInfo', () => { start: new Date('2020-07-24T21:44:51.000Z'), end: new Date('2020-07-29T21:44:51.000Z'), era: byronEraConfig, + eras: networkManagers[Chain.Network.Mainnet].eras, } const result = convertDateToEpoch(inputDate) @@ -75,6 +78,7 @@ describe('dateToEpochInfo', () => { start: new Date('2020-07-29T21:44:51.000Z'), end: new Date('2020-08-03T21:44:51.000Z'), era: shelleyEraConfig, + eras: networkManagers[Chain.Network.Mainnet].eras, } const result = convertDateToEpoch(inputDate) @@ -91,6 +95,7 @@ describe('dateToEpochInfo', () => { start: new Date('2024-05-11T01:00:00.000Z'), end: new Date('2024-05-16T01:00:00.000Z'), era: shelleyPreprodEraConfig, + eras: networkManagers['preprod'].eras, } const result = convertDateToEpoch(inputDate) diff --git a/apps/wallet-mobile/src/features/WalletManager/network-manager/helpers/date-to-epoch-info.ts b/apps/wallet-mobile/src/features/WalletManager/network-manager/helpers/date-to-epoch-info.ts index f7031a1102..d4d5fc77ee 100644 --- a/apps/wallet-mobile/src/features/WalletManager/network-manager/helpers/date-to-epoch-info.ts +++ b/apps/wallet-mobile/src/features/WalletManager/network-manager/helpers/date-to-epoch-info.ts @@ -17,6 +17,7 @@ export function dateToEpochInfo(eras: Network.Manager['eras']) { start: epochStart, end: epochEnd, era: era, + eras: eras, }) } diff --git a/apps/wallet-mobile/src/features/WalletManager/network-manager/helpers/epoch-progress.test.ts b/apps/wallet-mobile/src/features/WalletManager/network-manager/helpers/epoch-progress.test.ts index 37b686c9e7..c5ace04ceb 100644 --- a/apps/wallet-mobile/src/features/WalletManager/network-manager/helpers/epoch-progress.test.ts +++ b/apps/wallet-mobile/src/features/WalletManager/network-manager/helpers/epoch-progress.test.ts @@ -15,6 +15,7 @@ describe('epochProgress', () => { expect(result).toEqual({ progress: 100, currentSlot: 431999, + absoluteSlot: 124156799, timeRemaining: {days: 0, hours: 0, minutes: 0, seconds: 1}, }) }) @@ -24,6 +25,7 @@ describe('epochProgress', () => { const result = epochProgress(dateToEpochInfo(networkManagers['mainnet'].eras)(currentDate))(currentDate) expect(result).toEqual({ + absoluteSlot: 123724800, progress: 0, currentSlot: 0, timeRemaining: {days: 5, hours: 0, minutes: 0, seconds: 0}, @@ -35,6 +37,7 @@ describe('epochProgress', () => { const result = epochProgress(dateToEpochInfo(networkManagers['mainnet'].eras)(currentDate))(currentDate) expect(result).toEqual({ + absoluteSlot: 123940800, progress: 50, currentSlot: 216000, timeRemaining: {days: 2, hours: 12, minutes: 0, seconds: 0}, @@ -47,6 +50,7 @@ describe('epochProgress', () => { start: new Date('2024-05-09T21:44:51.000Z'), end: new Date('2024-05-14T21:44:51.000Z'), era: shelleyEraConfig, + eras: networkManagers['mainnet'].eras, } const currentDate = new Date('2022-01-02T00:00:01Z') @@ -56,6 +60,7 @@ describe('epochProgress', () => { expect(result).toEqual({ progress: 100, currentSlot: 432000, + absoluteSlot: 49515310, timeRemaining: {days: 0, hours: 0, minutes: 0, seconds: 0}, }) }) @@ -68,6 +73,7 @@ describe('epochProgress', () => { const result = progressFn(currentDate) expect(result).toEqual({ + absoluteSlot: 61718400, progress: 86.67, currentSlot: 374400, timeRemaining: {days: 0, hours: 16, minutes: 0, seconds: 0}, diff --git a/apps/wallet-mobile/src/features/WalletManager/network-manager/helpers/epoch-progress.ts b/apps/wallet-mobile/src/features/WalletManager/network-manager/helpers/epoch-progress.ts index d412bce685..a6ef809775 100644 --- a/apps/wallet-mobile/src/features/WalletManager/network-manager/helpers/epoch-progress.ts +++ b/apps/wallet-mobile/src/features/WalletManager/network-manager/helpers/epoch-progress.ts @@ -6,11 +6,24 @@ export function epochProgress(epochInfo: Network.EpochInfo) { const epochStart = epochInfo.start const epochEnd = epochInfo.end - if (date > epochEnd || date < epochStart) + let absoluteSlot = 0 + + for (const era of epochInfo.eras) { + if (date >= era.start && (era.end === undefined || date < era.end)) { + absoluteSlot += Math.floor((date.getTime() - era.start.getTime()) / 1e3 / era.slotInSeconds) + break + } + absoluteSlot += Math.floor( + ((era.end?.getTime() ?? date.getTime()) - era.start.getTime()) / 1e3 / era.slotInSeconds, + ) + } + + if (date > epochEnd || date < epochStart) { return freeze( { progress: 100, currentSlot: epochInfo.era.slotsPerEpoch, + absoluteSlot, timeRemaining: { days: 0, hours: 0, @@ -20,6 +33,7 @@ export function epochProgress(epochInfo: Network.EpochInfo) { }, true, ) + } const progress = Math.round( @@ -36,13 +50,14 @@ export function epochProgress(epochInfo: Network.EpochInfo) { return freeze( { - progress: progress, - currentSlot: currentSlot, + progress, + currentSlot, + absoluteSlot, timeRemaining: { - days: days, - hours: hours, - minutes: minutes, - seconds: seconds, + days, + hours, + minutes, + seconds, }, }, true, diff --git a/apps/wallet-mobile/src/yoroi-wallets/cardano/cardano-wallet.ts b/apps/wallet-mobile/src/yoroi-wallets/cardano/cardano-wallet.ts index dae44280f1..52df12db52 100644 --- a/apps/wallet-mobile/src/yoroi-wallets/cardano/cardano-wallet.ts +++ b/apps/wallet-mobile/src/yoroi-wallets/cardano/cardano-wallet.ts @@ -371,12 +371,9 @@ export const makeCardanoWallet = (networkManager: Network.Manager, implementatio addressMode: Wallet.AddressMode }) { if (implementationConfig.features.staking) { - const time = await this.checkServerStatus() - .then(({serverTime}) => serverTime || Date.now()) - .catch(() => Date.now()) const primaryTokenId = this.portfolioPrimaryTokenInfo.id - const absSlotNumber = new BigNumber(this.networkManager.epoch.progress(new Date(time)).currentSlot) + const absSlotNumber = await this.getAbsoluteSlotNumber() const changeAddr = this.getAddressedChangeAddress(addressMode) const addressedUtxos = await this.getAddressedUtxos() const registrationStatus = this.getDelegationStatus().isRegistered @@ -437,11 +434,7 @@ export const makeCardanoWallet = (networkManager: Network.Manager, implementatio const primaryTokenId = this.portfolioPrimaryTokenInfo.id try { - const time = await this.checkServerStatus() - .then(({serverTime}) => serverTime || Date.now()) - .catch(() => Date.now()) - - const absSlotNumber = new BigNumber(this.networkManager.epoch.progress(new Date(time)).currentSlot) + const absSlotNumber = await this.getAbsoluteSlotNumber() const votingPublicKey = await Promise.resolve(Buffer.from(catalystKeyHex, 'hex')) .then((bytes) => CardanoMobile.PrivateKey.fromExtendedBytes(bytes)) .then((key) => key.toPublic()) @@ -528,12 +521,9 @@ export const makeCardanoWallet = (networkManager: Network.Manager, implementatio addressMode: Wallet.AddressMode }): Promise { if (implementationConfig.features.staking) { - const time = await this.checkServerStatus() - .then(({serverTime}) => serverTime || Date.now()) - .catch(() => Date.now()) const primaryTokenId = this.portfolioPrimaryTokenInfo.id - const absSlotNumber = new BigNumber(this.networkManager.epoch.progress(new Date(time)).currentSlot) + const absSlotNumber = await this.getAbsoluteSlotNumber() const changeAddr = this.getAddressedChangeAddress(addressMode) const addressedUtxos = await this.getAddressedUtxos() const accountState = await legacyApi.getAccountState( @@ -589,11 +579,8 @@ export const makeCardanoWallet = (networkManager: Network.Manager, implementatio votingCertificates: CardanoTypes.Certificate[] addressMode: Wallet.AddressMode }) { - const time = await this.checkServerStatus() - .then(({serverTime}) => serverTime || Date.now()) - .catch(() => Date.now()) const primaryTokenId = this.portfolioPrimaryTokenInfo.id - const absSlotNumber = new BigNumber(this.networkManager.epoch.progress(new Date(time)).currentSlot) + const absSlotNumber = await this.getAbsoluteSlotNumber() const changeAddr = this.getAddressedChangeAddress(addressMode) const addressedUtxos = await this.getAddressedUtxos() @@ -758,6 +745,13 @@ export const makeCardanoWallet = (networkManager: Network.Manager, implementatio return Promise.resolve(addressedUtxos) } + private async getAbsoluteSlotNumber() { + const time = await this.checkServerStatus() + .then(({serverTime}) => serverTime || Date.now()) + .catch(() => Date.now()) + return new BigNumber(this.networkManager.epoch.progress(new Date(time)).absoluteSlot) + } + async createUnsignedTx({ entries, addressMode, @@ -767,11 +761,9 @@ export const makeCardanoWallet = (networkManager: Network.Manager, implementatio addressMode: Wallet.AddressMode metadata?: Array }) { - const time = await this.checkServerStatus() - .then(({serverTime}) => serverTime || Date.now()) - .catch(() => Date.now()) const primaryTokenId = this.portfolioPrimaryTokenInfo.id - const absSlotNumber = new BigNumber(this.networkManager.epoch.progress(new Date(time)).currentSlot) + const absSlotNumber = await this.getAbsoluteSlotNumber() + const changeAddr = this.getAddressedChangeAddress(addressMode) const addressedUtxos = await this.getAddressedUtxos() diff --git a/packages/types/src/network/manager.ts b/packages/types/src/network/manager.ts index fa1807fa04..705cec63c1 100644 --- a/packages/types/src/network/manager.ts +++ b/packages/types/src/network/manager.ts @@ -53,11 +53,13 @@ export type NetworkEpochInfo = { start: Date end: Date era: NetworkEraConfig + eras: ReadonlyArray } export type NetworkEpochProgress = { progress: number currentSlot: number + absoluteSlot: number timeRemaining: { days: number hours: number