Skip to content

Commit 5add0bc

Browse files
authored
Merge branch 'develop' into YW-164/ada-handles
2 parents ba75dbe + cc9fd6c commit 5add0bc

File tree

10 files changed

+130
-205
lines changed

10 files changed

+130
-205
lines changed

packages/e2e-tests/helpers/portfolioHelper.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ export const Columns = Object.freeze({
1212
Day: '24h',
1313
Week: '1W',
1414
Month: '1M',
15+
Percentage: 'portfolioPercentage',
1516
Total: 'totalAmount',
16-
Percentage: 'portfolioPercents',
1717
});
1818
export const RedirectionButtons = Object.freeze({
1919
Receive: 'receive',

packages/e2e-tests/test/extension/portfolio/Portfolio_09_sorting.test.js

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,6 @@ describe('Portfolio Sorting columns', function () {
4545

4646
for (const columnName in Columns) {
4747
it(`Sort by column ${columnName} and check sorting`, async function () {
48-
if (Columns[columnName] === Columns.Percentage) {
49-
console.warn(
50-
'Skipping sorting check on Percentage column until the issue https://emurgo.atlassian.net/browse/YOEXT-2289 is fixed'
51-
);
52-
this.skip();
53-
}
5448
await portfolioMainPage.sortBy(Columns[columnName]);
5549
const arrowSortingDirection = await portfolioMainPage.getSortingArrowDirection(Columns[columnName]);
5650
const columnsRawValues = await portfolioMainPage.getColumnValues(Columns[columnName]);

packages/yoroi-extension/app/UI/features/airdrop/useCases/Redeem.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import Dialog from '../../../../components/widgets/Dialog';
22
import { Typography, Box, Button } from '@mui/material';
33
import { useEffect, useState, useRef } from 'react';
4-
import { getCollateralUtxos, getRedemptionTransaction } from '../../../../api/ada/midnight';
4+
import { getRedemptionUtxos, getRedemptionTransaction } from '../../../../api/ada/midnight';
55
import { useStrings } from '../common/hooks/useStrings';
66
import LoadingSpinner from '../../../../components/widgets/LoadingSpinner';
77
import { formatNumberExactly } from '../../../../api/ada/midnightRedemption';
@@ -23,7 +23,7 @@ export default function Redeem(props: {
2323
const abort = useRef(false);
2424

2525
const updateCollateralUtxos = async (reorgTxId?: string) => {
26-
const result = await getCollateralUtxos(props.wallet);
26+
const result = await getRedemptionUtxos(props.wallet);
2727
setGetCollateralUtxosResult(result);
2828
if (result.state === 'exist') {
2929
// we just submitted the re-org tx, wait for it to be confirmed
@@ -44,8 +44,8 @@ export default function Redeem(props: {
4444
props.address,
4545
props.endpoint,
4646
result.fundingUtxoAddr,
47-
result.collateralUtxos,
48-
[result.fundingUtxo]
47+
[],
48+
result.fundingUtxos
4949
);
5050
if (abort.current) {
5151
return;

packages/yoroi-extension/app/UI/features/portfolio/common/hooks/usePortfolioTokenChart.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { isRight } from '@yoroi/common';
22
import { useQuery, UseQueryOptions } from '@tanstack/react-query';
3-
// import { useLanguage } from '../../../kernel/i18n';
43
import { supportedCurrencies, time } from '../../../../utils/constants';
54
import { fetchPtPriceActivity } from '../../../../utils/usePrimaryTokenActivity';
65
import { usePortfolio } from '../../module/PortfolioContextProvider';
@@ -20,11 +19,10 @@ type TokenChartData = {
2019
type TokenChartQueryKey = ['useGetPortfolioTokenChart', string, TokenChartInterval, string | undefined];
2120

2221
export const useGetPortfolioTokenChart = (
23-
timeInterval = TOKEN_CHART_INTERVAL.DAY as TokenChartInterval,
2422
tokenInfo: any,
23+
timeInterval = TOKEN_CHART_INTERVAL.DAY as TokenChartInterval,
2524
options: Omit<UseQueryOptions<TokenChartData[], Error, TokenChartData[], TokenChartQueryKey>, 'queryKey' | 'queryFn'> = {}
2625
) => {
27-
// const { currency } = useCurrencyPairing();
2826
const { unitOfAccount, primaryTokenInfo } = usePortfolio();
2927

3028
const currency = unitOfAccount;

packages/yoroi-extension/app/UI/features/portfolio/common/hooks/useTableSort.ts

Lines changed: 33 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -19,18 +19,36 @@ const useTableSort = ({ order, orderBy, setSortState, headCells, data }: Props)
1919
name: 'desc',
2020
price: 'desc',
2121
totalAmount: 'desc',
22-
portfolioPercents: 'desc',
22+
portfolioPercentage: 'desc',
2323
'24h': 'desc',
2424
'1W': 'desc',
2525
'1M': 'desc',
2626
};
2727

28+
const _compAB = (valueA: string | number, valueB: string | number) => {
29+
if (valueA === valueB) return 0;
30+
return valueA < valueB ? -1 : 1;
31+
};
32+
33+
const _checkForWeirdSymbols = (tokenAName: string, tokenBName: string) => {
34+
const startsWithSymbolOrNumber = (str: string) => /^[^a-zA-Z]/.test(str);
35+
36+
const aIsWeird = startsWithSymbolOrNumber(tokenAName);
37+
const bIsWeird = startsWithSymbolOrNumber(tokenBName);
38+
39+
if (aIsWeird && !bIsWeird) return 1;
40+
if (!aIsWeird && bIsWeird) return -1;
41+
return undefined;
42+
};
43+
2844
const compareValues = (a: any, b: any, sortType: TableSortType, sortOrder: 'asc' | 'desc', sortKey: string): number => {
29-
const isInvalid = (val: any) => isNaN(Number(val));
45+
const isInvalid = (val: any) => Number.isNaN(Number(val));
46+
const valueA = a[sortKey];
47+
const valueB = b[sortKey];
3048

31-
if (['price', 'portfolio', 'totalAmount', '24h', '1W', '1M'].includes(sortKey)) {
32-
const aInvalid = isInvalid(a[sortKey]);
33-
const bInvalid = isInvalid(b[sortKey]);
49+
if (['price', 'portfolioPercentage', 'totalAmount', '24h', '1W', '1M'].includes(sortKey)) {
50+
const aInvalid = isInvalid(valueA);
51+
const bInvalid = isInvalid(valueB);
3452

3553
if (aInvalid && !bInvalid) return 1;
3654
if (!aInvalid && bInvalid) return -1;
@@ -41,30 +59,21 @@ const useTableSort = ({ order, orderBy, setSortState, headCells, data }: Props)
4159

4260
switch (sortType) {
4361
case 'numeric': {
44-
const aValue = Number(a[sortKey]);
45-
const bValue = Number(b[sortKey]);
46-
comparison = aValue === bValue ? 0 : aValue < bValue ? -1 : 1;
62+
comparison = _compAB(Number(valueA), Number(valueB));
4763
break;
4864
}
4965
case 'character': {
5066
const aName = String(a.info?.[sortKey] ?? '');
5167
const bName = String(b.info?.[sortKey] ?? '');
5268

53-
const startsWithSymbolOrNumber = (str: string) => /^[^a-zA-Z]/.test(str);
54-
55-
const aIsWeird = startsWithSymbolOrNumber(aName);
56-
const bIsWeird = startsWithSymbolOrNumber(bName);
57-
58-
if (aIsWeird && !bIsWeird) return 1;
59-
if (!aIsWeird && bIsWeird) return -1;
69+
const checkResult = _checkForWeirdSymbols(aName, bName);
70+
if (checkResult) return checkResult;
6071

6172
comparison = aName.localeCompare(bName, undefined, { sensitivity: 'base' });
6273
break;
6374
}
6475
default: {
65-
const aVal = a[sortKey];
66-
const bVal = b[sortKey];
67-
comparison = aVal === bVal ? 0 : aVal < bVal ? -1 : 1;
76+
comparison = _compAB(valueA, valueB);
6877
}
6978
}
7079

@@ -80,7 +89,12 @@ const useTableSort = ({ order, orderBy, setSortState, headCells, data }: Props)
8089

8190
const handleRequestSort = (property: string) => {
8291
const defaultDirection = defaultSortDirections[property] ?? 'asc';
83-
const newOrder = property !== orderBy ? defaultDirection : order === 'asc' ? 'desc' : 'asc';
92+
let newOrder: 'asc' | 'desc';
93+
if (property === orderBy) {
94+
newOrder = order === 'asc' ? 'desc' : 'asc';
95+
} else {
96+
newOrder = defaultDirection;
97+
}
8498

8599
setSortState({ order: newOrder, orderBy: property });
86100
};

packages/yoroi-extension/app/UI/features/portfolio/useCases/TokenDetails/ChartDetails/TokenChartInterval.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ export const TokenChartInterval = ({ tokenInfo, pathId = '' }: Props): React.Rea
6464

6565
// Fetch data based on the selected interval
6666
const [timeInterval, setTimeInterval] = useState<any>(TOKEN_CHART_INTERVAL.DAY);
67-
const { data, isFetching } = useGetPortfolioTokenChart(timeInterval, tokenInfo);
67+
const { data, isFetching } = useGetPortfolioTokenChart(tokenInfo, timeInterval);
6868

6969
const handlePeriodChange = (id: string) => {
7070
setTimeInterval(TOKEN_CHART_INTERVAL[id]);
@@ -119,7 +119,7 @@ export const TokenChartInterval = ({ tokenInfo, pathId = '' }: Props): React.Rea
119119
height: '160px',
120120
}}
121121
>
122-
{!data ? null : (
122+
{data && (
123123
<ResponsiveContainer width={'100%'} height="100%">
124124
<LineChart
125125
margin={{ top: 10, left: -16, right: 0, bottom: 0 }}

packages/yoroi-extension/app/UI/features/portfolio/useCases/TokensTable/StatsTable.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ const StatsTable = ({ data, stores }: Props): React.ReactNode => {
5959
{ id: '1W', label: strings['1W'], align: 'left', sortType: 'numeric' },
6060
{ id: '1M', label: strings['1M'], align: 'left', sortType: 'numeric' },
6161
{
62-
id: 'portfolioPercents',
62+
id: 'portfolioPercentage',
6363
label: `${strings.portfolio} %`,
6464
align: 'left',
6565
sortType: 'numeric',
@@ -137,7 +137,7 @@ const StatsTable = ({ data, stores }: Props): React.ReactNode => {
137137
</STableCell>
138138

139139
<STableCell sx={{ padding: '16.8px 1rem' }}>
140-
<TokenProcentage procentage={row.percentage} pathId={tokenPathId(rowIndex)} />
140+
<TokenProcentage procentage={row.portfolioPercentage} pathId={tokenPathId(rowIndex)} />
141141
</STableCell>
142142

143143
<STableCell sx={{ padding: '16.8px 1rem' }}>

packages/yoroi-extension/app/UI/features/portfolio/useCases/TokensTable/TableColumnsChip.tsx

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ export const TokenPriceChangeChip = ({
6666
timeInterval,
6767
pathId,
6868
}: TokenPriceChangeChipProps) => {
69-
const { data: ptTokenDataInterval, isFetching } = useGetPortfolioTokenChart(timeInterval, { info: { id: '' } });
69+
const { data: ptTokenDataInterval, isFetching } = useGetPortfolioTokenChart({ info: { id: '' } }, timeInterval);
7070
const pathIdInterval = timeInterval ? timeInterval.replace(' ', '') : '24h';
7171
const fullPathId = `${pathId}-${pathIdInterval}_priceChanges-text`;
7272

@@ -79,13 +79,9 @@ export const TokenPriceChangeChip = ({
7979
return <Skeleton variant="text" width="60px" height="30px" />;
8080
}
8181

82-
const tokenPriceClose = isPrimaryToken
83-
? primaryTokenActivity?.close
84-
: secondaryTokenActivity && secondaryTokenActivity[1].price?.close;
82+
const tokenPriceClose = isPrimaryToken ? primaryTokenActivity?.close : secondaryTokenActivity?.[1]?.price?.close;
8583

86-
const tokenPriceOpen = isPrimaryToken
87-
? primaryTokenActivity?.open
88-
: secondaryTokenActivity && secondaryTokenActivity[1].price?.open;
84+
const tokenPriceOpen = isPrimaryToken ? primaryTokenActivity?.open : secondaryTokenActivity?.[1]?.price?.open;
8985

9086
const { changePercent, variantPnl } = priceChange(tokenPriceOpen, tokenPriceClose);
9187

@@ -183,7 +179,7 @@ export const TokenPriceTotal = observer(({ token, secondaryToken24Activity, stor
183179
ptActivity: { close: ptPrice },
184180
} = useCurrencyPairing();
185181

186-
const tokenPrice = secondaryToken24Activity && secondaryToken24Activity[1].price?.close;
182+
const tokenPrice = secondaryToken24Activity?.[1]?.price?.close;
187183
const tokenQuantityAsBigInt = bigNumberToBigInt(token.quantity);
188184

189185
const showingAda = accountPair?.from.name === primaryTokenInfo.name;
@@ -234,10 +230,10 @@ export const TokenPriceTotal = observer(({ token, secondaryToken24Activity, stor
234230
export const TokenPrice = ({ secondaryToken24Activity, ptActivity, token, pathId }) => {
235231
const { unitOfAccount } = usePortfolio();
236232
const isPrimaryToken = token.id === '-';
237-
const tokenPrice = secondaryToken24Activity && secondaryToken24Activity[1].price?.close;
233+
const tokenPrice = secondaryToken24Activity?.[1]?.price?.close;
238234
const ptPrice = ptActivity?.close;
239235
const ptUnitPrice = tokenPrice * ptPrice;
240-
const priceDisplay = parseFloat(isPrimaryToken ? ptPrice : ptUnitPrice).toFixed(4);
236+
const priceDisplay = Number.parseFloat(isPrimaryToken ? ptPrice : ptUnitPrice).toFixed(4);
241237

242238
const noDataToDisplay = priceDisplay === 'NaN';
243239

@@ -254,7 +250,7 @@ export const TokenProcentage = ({ procentage, pathId }) => {
254250

255251
return (
256252
<Typography variant="body2" color="ds.text_gray_medium" id={`${pathId}-percentage-text`}>
257-
{showWelcomeBanner ? 0 : parseFloat(procentage).toFixed(2)}%
253+
{showWelcomeBanner ? 0 : Number.parseFloat(procentage).toFixed(2)}%
258254
</Typography>
259255
);
260256
};

packages/yoroi-extension/app/UI/features/portfolio/useCases/TokensTable/useProcentage.tsx

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,18 @@ import { bigNumberToBigInt } from './TableColumnsChip';
1010

1111
export const useProcessedTokenData = ({ data, ptActivity, data24h, data7d, data30d }) => {
1212
const { primaryTokenInfo } = usePortfolio();
13-
const { data: ptTokenDataInterval7d } = useGetPortfolioTokenChart(TOKEN_CHART_INTERVAL.WEEK, {
14-
info: { id: '' },
15-
});
16-
const { data: ptTokenDataInterval1M } = useGetPortfolioTokenChart(TOKEN_CHART_INTERVAL.MONTH, {
17-
info: { id: '' },
18-
});
13+
const { data: ptTokenDataInterval7d } = useGetPortfolioTokenChart(
14+
{
15+
info: { id: '' },
16+
},
17+
TOKEN_CHART_INTERVAL.WEEK
18+
);
19+
const { data: ptTokenDataInterval1M } = useGetPortfolioTokenChart(
20+
{
21+
info: { id: '' },
22+
},
23+
TOKEN_CHART_INTERVAL.MONTH
24+
);
1925

2026
// Helper to calculate fiat value and unit price for a token
2127
const calculateTotalFiatForToken = token => {
@@ -33,10 +39,10 @@ export const useProcessedTokenData = ({ data, ptActivity, data24h, data7d, data3
3339
.times(new BigNumber(ptActivity?.close.toString() || 1))
3440
.toNumber();
3541

36-
const unitPrice = parseFloat((tokenPrice * ptActivity?.close || 1).toFixed(4));
42+
const unitPrice = Number.parseFloat((tokenPrice * ptActivity?.close || 1).toFixed(4));
3743
const primaryTokenFiatTotalAmount = formatValue(primaryTokenInfo.quantity.multipliedBy(String(ptActivity?.close)));
3844

39-
const tokenValueDisplay = secondaryToken24Activity && secondaryToken24Activity[0] === 500 ? 0 : totalValue;
45+
const tokenValueDisplay = secondaryToken24Activity?.[0] === 500 ? 0 : totalValue;
4046
return { totalValue: isPrimaryToken ? primaryTokenFiatTotalAmount : tokenValueDisplay, unitPrice };
4147
};
4248

@@ -63,7 +69,7 @@ export const useProcessedTokenData = ({ data, ptActivity, data24h, data7d, data3
6369
return data
6470
.map(token => {
6571
const { totalValue, unitPrice } = tokenFiatValues[token.info.id] || {};
66-
const percentage = totalPortfolioValue ? (totalValue / Number(totalPortfolioValue)) * 100 : 0;
72+
const portfolioPercentage = totalPortfolioValue ? (totalValue / Number(totalPortfolioValue)) * 100 : 0;
6773
const isPrimaryToken = token.id === '-';
6874

6975
const { open: open24, close: close24 } = getTokenActivityChange(token.info.id, data24h, isPrimaryToken);
@@ -76,7 +82,7 @@ export const useProcessedTokenData = ({ data, ptActivity, data24h, data7d, data3
7682

7783
return {
7884
...token,
79-
percentage,
85+
portfolioPercentage,
8086
totalAmount: totalValue,
8187
price: totalValue === 0 ? 0 : unitPrice,
8288
'24h': changePercent24,
@@ -86,22 +92,16 @@ export const useProcessedTokenData = ({ data, ptActivity, data24h, data7d, data3
8692
};
8793
})
8894
.sort((a, b) => {
89-
// If both tokens have special names, sort them by percentage
90-
if (a.isSpecialName && b.isSpecialName) {
91-
return Number(b.percentage) - Number(a.percentage);
95+
// Handle case when both tokens have special names and 0 portfolioPercentage
96+
// They should be considered equal to maintain comparator antisymmetry
97+
if (a.isSpecialName && a.portfolioPercentage === 0 && b.isSpecialName && b.portfolioPercentage === 0) {
98+
return 0;
9299
}
93-
// If only one token has a special name but has percentage > 0, still sort it normally
94-
if (a.isSpecialName && a.percentage > 0 && !b.isSpecialName) {
95-
return Number(b.percentage) - Number(a.percentage);
96-
}
97-
if (b.isSpecialName && b.percentage > 0 && !a.isSpecialName) {
98-
return Number(b.percentage) - Number(a.percentage);
99-
}
100-
// Move tokens with special names and 0 percentage to the bottom
101-
if (a.isSpecialName && a.percentage === 0) return 1;
102-
if (b.isSpecialName && b.percentage === 0) return -1;
103-
// Default sorting by percentage
104-
return Number(b.percentage) - Number(a.percentage);
100+
// Move tokens with special names and 0 portfolioPercentage to the bottom
101+
if (a.isSpecialName && a.portfolioPercentage === 0) return 1;
102+
if (b.isSpecialName && b.portfolioPercentage === 0) return -1;
103+
// Default sorting by portfolioPercentage
104+
return Number(b.portfolioPercentage) - Number(a.portfolioPercentage);
105105
});
106106
}, [data, ptActivity, data24h, data7d, data30d, primaryTokenInfo, ptTokenDataInterval7d, ptTokenDataInterval1M]);
107107

0 commit comments

Comments
 (0)