Skip to content

Commit fdfad11

Browse files
authored
Merge pull request #213 from multiversx/development
Development
2 parents ad6f0fe + c37a1c1 commit fdfad11

34 files changed

Lines changed: 595 additions & 112 deletions

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
- ## [[2.3.3](https://github.com/multiversx/mx-explorer-dapp/pull/213)] - 2026-01-22
11+
12+
- [Websocket Transfers](https://github.com/multiversx/mx-explorer-dapp/pull/210)
13+
1014
- ## [[2.3.2](https://github.com/multiversx/mx-explorer-dapp/pull/208)] - 2025-11-27
1115

1216
- [Handle deprecatedRelayedV1V2](https://github.com/multiversx/mx-explorer-dapp/pull/208)

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "mx-explorer-dapp",
33
"description": "MultiversX Blockchain Explorer",
4-
"version": "2.3.2",
4+
"version": "2.3.3",
55
"author": "MultiversX",
66
"license": "GPL-3.0-or-later",
77
"repository": "multiversx/mx-explorer-dapp",

src/assets/scss/common/variables/_bootstrap-variables.scss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -393,7 +393,7 @@ $dropdown-link-color: $neutral-400;
393393
$dropdown-link-hover-color: $body-color;
394394
$dropdown-link-hover-bg: $neutral-700;
395395
$dropdown-link-active-color: $body-color;
396-
$dropdown-link-active-bg: $neutral-900;
396+
$dropdown-link-active-bg: $neutral-980;
397397
$dropdown-link-disabled-color: $neutral-700;
398398
$dropdown-header-color: $neutral-700;
399399
// scss-docs-end dropdown-variables

src/components/Chart/ChartLine.tsx

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,10 @@
11
import BigNumber from 'bignumber.js';
22
import classNames from 'classnames';
33
import moment from 'moment';
4-
import {
5-
ResponsiveContainer,
6-
XAxis,
7-
YAxis,
8-
Line,
9-
LineChart,
10-
Tooltip,
11-
CartesianGrid
12-
} from 'recharts';
4+
import { XAxis, YAxis, Line, Tooltip, CartesianGrid } from 'recharts';
135

146
import { getColors } from 'helpers';
7+
import { ChartLineContainer } from './ChartLineContainer';
158
import { ChartTooltip } from './ChartTooltip';
169
import { formatYAxis } from './helpers/formatYAxis';
1710
import { getChartMergedData } from './helpers/getChartMergedData';
@@ -82,8 +75,8 @@ export const ChartLine = ({
8275
'has-only-start-end-tick': hasOnlyStartEndTick
8376
})}
8477
>
85-
<ResponsiveContainer width={width ?? '100%'} height={height ?? '100%'}>
86-
<LineChart data={chartData}>
78+
<ChartLineContainer width={width} height={height} data={chartData}>
79+
<>
8780
<defs>
8881
<linearGradient id='transparent' x1='0' y1='0' x2='0' y2='1'>
8982
<stop offset='100%' stopColor='transparent' stopOpacity={0} />
@@ -190,8 +183,8 @@ export const ChartLine = ({
190183
}
191184
/>
192185
)}
193-
</LineChart>
194-
</ResponsiveContainer>
186+
</>
187+
</ChartLineContainer>
195188
</div>
196189
);
197190
};
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { JSXElementConstructor, memo, ReactElement } from 'react';
2+
import { ResponsiveContainer, LineChart } from 'recharts';
3+
import { MergedChartDataType } from './helpers/types';
4+
5+
interface ChartLineContainerUIType {
6+
children: ReactElement<unknown, string | JSXElementConstructor<any>>;
7+
data: MergedChartDataType[];
8+
width?: string | number;
9+
height?: string | number;
10+
}
11+
12+
export const ChartLineContainer = memo(
13+
({ children, data, width, height }: ChartLineContainerUIType) => {
14+
if (typeof width === 'number' && typeof height === 'number') {
15+
return (
16+
<LineChart data={data} width={width} height={height}>
17+
{children}
18+
</LineChart>
19+
);
20+
}
21+
22+
return (
23+
<ResponsiveContainer width={width ?? '100%'} height={height ?? '100%'}>
24+
<LineChart data={data}>{children}</LineChart>
25+
</ResponsiveContainer>
26+
);
27+
}
28+
);

src/components/NftPreview/NftPreview.tsx

Lines changed: 44 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -83,50 +83,52 @@ export const NftPreview = ({ token }: { token: NftType }) => {
8383
<div className='nft-details d-flex flex-column text-start'>
8484
<ul className='list-unstyled mb-0'>
8585
{token.uris.map((uri, i) => {
86-
if (uri !== null && uri !== undefined) {
87-
const link = Buffer.from(String(uri), 'base64').toString();
88-
const { stringWithLinks, found } = scamFlag(link, token.scamInfo);
86+
if (!uri) {
87+
return null;
88+
}
8989

90-
return (
91-
<li key={i}>
92-
<FontAwesomeIcon
93-
icon={faCaretRight}
94-
size='xs'
95-
className='text-neutral-400 me-2'
96-
/>
97-
{link.startsWith(
98-
'https://ipfs.io/ipfs/'
99-
) /* && token.isWhitelistedStorage === true */ ? (
100-
<ModalLink
101-
href={found ? stringWithLinks : link}
102-
target='_blank'
103-
rel='noreferrer nofollow noopener'
104-
className='text-break-all'
105-
>
106-
<Thumbnail link={found ? '' : link} token={token} index={i}>
107-
{found ? stringWithLinks : link}
90+
const link = Buffer.from(String(uri), 'base64').toString();
91+
const { stringWithLinks, found } = scamFlag(link, token.scamInfo);
92+
93+
return (
94+
<li key={i}>
95+
<FontAwesomeIcon
96+
icon={faCaretRight}
97+
size='xs'
98+
className='text-neutral-400 me-2'
99+
/>
100+
{link.startsWith(
101+
'https://ipfs.io/ipfs/'
102+
) /* && token.isWhitelistedStorage === true */ ? (
103+
<ModalLink
104+
href={found ? stringWithLinks : link}
105+
target='_blank'
106+
rel='noreferrer nofollow noopener'
107+
className='text-break-all'
108+
>
109+
<Thumbnail link={found ? '' : link} token={token} index={i}>
110+
{found ? stringWithLinks : link}
111+
</Thumbnail>
112+
</ModalLink>
113+
) : (
114+
<span className='text-break'>
115+
{found ? (
116+
<Anchorme
117+
linkComponent={ModalLink}
118+
target='_blank'
119+
rel='noreferrer nofollow noopener'
120+
>
121+
{stringWithLinks}
122+
</Anchorme>
123+
) : (
124+
<Thumbnail link={link} token={token} index={i}>
125+
<span>{link}</span>
108126
</Thumbnail>
109-
</ModalLink>
110-
) : (
111-
<span className='text-break'>
112-
{found ? (
113-
<Anchorme
114-
linkComponent={ModalLink}
115-
target='_blank'
116-
rel='noreferrer nofollow noopener'
117-
>
118-
{stringWithLinks}
119-
</Anchorme>
120-
) : (
121-
<Thumbnail link={link} token={token} index={i}>
122-
<span>{link}</span>
123-
</Thumbnail>
124-
)}
125-
</span>
126-
)}
127-
</li>
128-
);
129-
} else return null;
127+
)}
128+
</span>
129+
)}
130+
</li>
131+
);
130132
})}
131133
</ul>
132134
{/* {token.isWhitelistedStorage === false && (

src/helpers/processData/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ export * from './processGrowthPrice';
77
export * from './processGrowthSearch';
88
export * from './processGrowthStaking';
99
export * from './processGrowthTransactions';
10+
export * from './processListUpdates';
1011
export * from './processNodesIdentities';
1112
export * from './processNodesOverview';
1213
export * from './processNodesVersions';
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import { PAGE_SIZE } from 'appConstants';
2+
3+
interface ProcessListUpdatesProps {
4+
existing: any[];
5+
incoming: any[];
6+
uniqueKey: string;
7+
size?: number;
8+
}
9+
10+
export const processListUpdates = ({
11+
existing = [],
12+
incoming = [],
13+
uniqueKey,
14+
size = PAGE_SIZE
15+
}: ProcessListUpdatesProps) => {
16+
const existingSet = new Set(existing.map((entry) => entry[uniqueKey]));
17+
const updated = new Map<string, any>();
18+
const result: any[] = [];
19+
20+
for (const entry of existing) {
21+
updated.set(entry[uniqueKey], entry);
22+
}
23+
for (const entry of incoming) {
24+
updated.set(entry[uniqueKey], { ...entry, isNew: true });
25+
}
26+
27+
for (const entry of incoming) {
28+
if (!existingSet.has(entry[uniqueKey])) {
29+
result.push(updated.get(entry[uniqueKey])!);
30+
}
31+
}
32+
33+
for (const entry of existing) {
34+
if (entry[uniqueKey] === undefined) {
35+
continue;
36+
}
37+
result.push(updated.get(entry[uniqueKey])!);
38+
}
39+
40+
// keep the resulting set the same size as the page size prop
41+
return result.slice(0, size);
42+
};

src/hooks/adapter/requests/useTokenRequests.ts

Lines changed: 16 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ export const useTokenRequests = () => {
1414
return {
1515
/* Tokens */
1616

17-
getToken: (tokenId: string, { signal, timeout }: AxiosParamsApiType = {}) =>
18-
provider({ url: `/tokens/${tokenId}`, signal, timeout }),
17+
getToken: (token: string, { signal, timeout }: AxiosParamsApiType = {}) =>
18+
provider({ url: `/tokens/${token}`, signal, timeout }),
1919

2020
getTokens: ({ signal, timeout, ...params }: GetTokensType) =>
2121
provider({
@@ -34,13 +34,13 @@ export const useTokenRequests = () => {
3434
}),
3535

3636
getTokenTransactions: ({
37-
tokenId,
37+
token,
3838
signal,
3939
timeout,
4040
...params
4141
}: GetTransactionsType & GetTokenResourceType) =>
4242
provider({
43-
url: `/tokens/${tokenId}/transactions`,
43+
url: `/tokens/${token}/transactions`,
4444
signal,
4545
timeout,
4646
params: getTransactionsParams({
@@ -49,13 +49,13 @@ export const useTokenRequests = () => {
4949
}),
5050

5151
getTokenTransactionsCount: ({
52-
tokenId,
52+
token,
5353
signal,
5454
timeout,
5555
...params
5656
}: GetTransactionsType & GetTokenResourceType) =>
5757
provider({
58-
url: `/tokens/${tokenId}/transactions/c`,
58+
url: `/tokens/${token}/transactions/c`,
5959
signal,
6060
timeout,
6161
params: getTransactionsParams({
@@ -65,13 +65,13 @@ export const useTokenRequests = () => {
6565
}),
6666

6767
getTokenTransfers: ({
68-
tokenId,
68+
token,
6969
signal,
7070
timeout,
7171
...params
7272
}: GetTransactionsType & GetTokenResourceType) =>
7373
provider({
74-
url: `/tokens/${tokenId}/transfers`,
74+
url: `/tokens/${token}/transfers`,
7575
signal,
7676
timeout,
7777
params: getTransactionsParams({
@@ -80,13 +80,13 @@ export const useTokenRequests = () => {
8080
}),
8181

8282
getTokenTransfersCount: ({
83-
tokenId,
83+
token,
8484
signal,
8585
timeout,
8686
...params
8787
}: GetTransactionsType & GetTokenResourceType) =>
8888
provider({
89-
url: `/tokens/${tokenId}/transfers/c`,
89+
url: `/tokens/${token}/transfers/c`,
9090
signal,
9191
timeout,
9292
params: getTransactionsParams({
@@ -96,32 +96,28 @@ export const useTokenRequests = () => {
9696
}),
9797

9898
getTokenAccounts: ({
99-
tokenId,
99+
token,
100100
signal,
101101
timeout,
102102
...params
103103
}: GetTokensType & GetTokenResourceType) =>
104104
provider({
105-
url: `/tokens/${tokenId}/accounts`,
105+
url: `/tokens/${token}/accounts`,
106106
signal,
107107
timeout,
108108
params: getTokensParams({ ...params })
109109
}),
110110

111-
getTokenAccountsCount: ({
112-
tokenId,
113-
signal,
114-
timeout
115-
}: GetTokenResourceType) =>
111+
getTokenAccountsCount: ({ token, signal, timeout }: GetTokenResourceType) =>
116112
provider({
117-
url: `/tokens/${tokenId}/accounts/count`,
113+
url: `/tokens/${token}/accounts/count`,
118114
signal,
119115
timeout
120116
}),
121117

122-
getTokenSupply: ({ tokenId, signal, timeout }: GetTokenResourceType) =>
118+
getTokenSupply: ({ token, signal, timeout }: GetTokenResourceType) =>
123119
provider({
124-
url: `/tokens/${tokenId}/supply`,
120+
url: `/tokens/${token}/supply`,
125121
signal,
126122
timeout
127123
})

src/hooks/fetch/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,6 @@ export * from './useFetchNodesVersions';
1212
export * from './useFetchShards';
1313
export * from './useFetchStats';
1414
export * from './useFetchTransactions';
15+
export * from './useFetchCustomTransfers';
1516
export * from './useFetchTransactionsInPool';
1617
export * from './useFetchWebsocketConfig';

0 commit comments

Comments
 (0)