From 32e40afce594d9f357eace013dd999aeb3ff5a54 Mon Sep 17 00:00:00 2001 From: Radu Mojic Date: Mon, 6 Nov 2023 14:07:39 +0200 Subject: [PATCH 1/9] handle VM Errors on successful tx --- .../TransactionErrorDisplay/TransactionErrorDisplay.tsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/pages/TransactionDetails/components/TransactionInfo/TransactionErrorDisplay/TransactionErrorDisplay.tsx b/src/pages/TransactionDetails/components/TransactionInfo/TransactionErrorDisplay/TransactionErrorDisplay.tsx index 64ea4279b..9fd64593e 100644 --- a/src/pages/TransactionDetails/components/TransactionInfo/TransactionErrorDisplay/TransactionErrorDisplay.tsx +++ b/src/pages/TransactionDetails/components/TransactionInfo/TransactionErrorDisplay/TransactionErrorDisplay.tsx @@ -50,6 +50,10 @@ export const TransactionErrorDisplay = ({ ? '' : 'text-danger'; + if (transactionMessages.length === 0 && internalVMErrorEvent) { + transactionMessages.push('Internal VM Error'); + } + return ( <> {transactionMessages.map((transactionMessage, messageIndex) => ( From b1a9bb3aaa7376ef18df36444d4197900961b1b8 Mon Sep 17 00:00:00 2001 From: Radu Mojic Date: Mon, 6 Nov 2023 14:34:35 +0200 Subject: [PATCH 2/9] show the owners too in the collection Nfts table --- src/hooks/adapter/helpers.ts | 6 ++-- .../CollectionDetails/CollectionNfts.tsx | 33 +++++++++++-------- src/types/adapter.types.ts | 1 + 3 files changed, 24 insertions(+), 16 deletions(-) diff --git a/src/hooks/adapter/helpers.ts b/src/hooks/adapter/helpers.ts index 3c79fc4ae..e582e191e 100644 --- a/src/hooks/adapter/helpers.ts +++ b/src/hooks/adapter/helpers.ts @@ -136,7 +136,8 @@ export function getCollectionsParams({ identifiers, type, sort, - excludeMetaESDT + excludeMetaESDT, + withOwner }: GetCollectionsType) { const params: AdapterProviderPropsType['params'] = { ...(fields !== undefined ? { fields } : {}), @@ -146,7 +147,8 @@ export function getCollectionsParams({ ...(sort !== undefined ? { sort } : {}), ...(excludeMetaESDT !== undefined ? { excludeMetaESDT } : {}), ...(page !== undefined ? { from: (page - 1) * size } : {}), - ...(size !== undefined ? { size } : {}) + ...(size !== undefined ? { size } : {}), + ...(withOwner !== undefined ? { withOwner } : {}) }; return params; diff --git a/src/pages/CollectionDetails/CollectionNfts.tsx b/src/pages/CollectionDetails/CollectionNfts.tsx index efd80156e..ab40aa36c 100644 --- a/src/pages/CollectionDetails/CollectionNfts.tsx +++ b/src/pages/CollectionDetails/CollectionNfts.tsx @@ -6,7 +6,7 @@ import { Loader, Pager, NetworkLink, - Trim, + AccountLink, PageState, NftBadge } from 'components'; @@ -15,7 +15,7 @@ import { useAdapter, useGetPage, useGetSearch } from 'hooks'; import { faUser } from 'icons/regular'; import { CollectionTabs } from 'layouts/CollectionLayout/CollectionTabs'; import { activeNetworkSelector, collectionSelector } from 'redux/selectors'; -import { NftType } from 'types'; +import { NftType, NftTypeEnum } from 'types'; export const CollectionNfts = () => { const ref = useRef(null); @@ -36,7 +36,13 @@ export const CollectionNfts = () => { const fetchCollectionNfts = () => { if (ref.current !== null) { Promise.all([ - getCollectionNfts({ search, page, size, collection }), + getCollectionNfts({ + search, + page, + size, + collection, + ...(type === NftTypeEnum.NonFungibleESDT ? { withOwner: true } : {}) + }), getCollectionNftsCount({ search, collection }) ]).then(([nftsData, count]) => { if (nftsData.success && count.success) { @@ -77,6 +83,7 @@ export const CollectionNfts = () => { Identifier Name Creator + {type === NftTypeEnum.NonFungibleESDT && Owner} @@ -114,19 +121,17 @@ export const CollectionNfts = () => {
- - - +
+ + {type === NftTypeEnum.NonFungibleESDT && + nft?.owner && ( +
+ +
+ )} + ))} diff --git a/src/types/adapter.types.ts b/src/types/adapter.types.ts index be5d93d03..62000ce0f 100644 --- a/src/types/adapter.types.ts +++ b/src/types/adapter.types.ts @@ -51,6 +51,7 @@ export interface GetCollectionsType { after?: string; sort?: string; excludeMetaESDT?: boolean; + withOwner?: boolean; } export interface GetNodesType { From dcbb5645873dd98cecfe07cb40d0f337cef63fee Mon Sep 17 00:00:00 2001 From: Radu Mojic Date: Mon, 6 Nov 2023 15:52:12 +0200 Subject: [PATCH 3/9] [+] use the AccountLink component --- src/components/AccountLink/AccountLink.tsx | 16 ++++-- .../ScResultsTable/components/ScResultRow.tsx | 31 +++--------- .../TransactionAction/TransactionAction.tsx | 18 +++---- .../components/TransactionRow.tsx | 50 ++++++++----------- .../transactionsTable.styles.scss | 4 +- .../CollectionDetailsCard.tsx | 14 ++---- .../ProviderLayout/ProviderDetailsCard.tsx | 19 ++----- .../TokenDetailsCard/TokenDetailsCard.tsx | 14 ++---- src/pages/Collections/Collections.tsx | 15 +----- .../LatestTransactions/LatestTransactions.tsx | 38 ++++---------- src/pages/Nfts/Nfts.tsx | 14 +----- .../components/NodeInformation.tsx | 10 ++-- src/pages/TokensMeta/TokensMeta.tsx | 16 ++---- .../components/EventsList/EventsList.tsx | 10 +--- .../OperationsList/OperationsList.tsx | 12 ++--- .../ScResultsList/ScResultsList.tsx | 31 ++++-------- .../TransactionInfo/TransactionInfo.tsx | 43 +++++----------- src/widgets/MostUsed/MostUsedContracts.tsx | 24 +++------ 18 files changed, 113 insertions(+), 266 deletions(-) diff --git a/src/components/AccountLink/AccountLink.tsx b/src/components/AccountLink/AccountLink.tsx index 553048691..fa1f41e7d 100644 --- a/src/components/AccountLink/AccountLink.tsx +++ b/src/components/AccountLink/AccountLink.tsx @@ -14,13 +14,21 @@ export const AccountLink = ({ address, assets, className, - linkClassName + linkClassName, + 'data-testid': testId }: AccountLinkType) => { return (
{addressIsBech32(address) ? ( diff --git a/src/components/ScResultsTable/components/ScResultRow.tsx b/src/components/ScResultsTable/components/ScResultRow.tsx index 4734e5458..20e985583 100644 --- a/src/components/ScResultsTable/components/ScResultRow.tsx +++ b/src/components/ScResultsTable/components/ScResultRow.tsx @@ -1,12 +1,11 @@ import { ScAddressIcon, - ShardSpan, NetworkLink, TimeAgo, Trim, - Denominate + Denominate, + AccountLink } from 'components'; -import { addressIsBech32, urlBuilder } from 'helpers'; import { TransactionSCResultType } from 'types'; export interface ScResultRowType { @@ -14,25 +13,6 @@ export interface ScResultRowType { address?: string; } -export const ScAccountLink = ({ - address, - testId -}: { - address: string; - testId?: string; -}) => - addressIsBech32(address) ? ( - - - - ) : ( - - ); - export const ScResultRow = ({ scResult, address }: ScResultRowType) => { const directionOut = address === scResult.sender; const directionIn = address === scResult.receiver; @@ -65,7 +45,7 @@ export const ScResultRow = ({ scResult, address }: ScResultRowType) => { {directionOut ? ( ) : ( - + )}
@@ -75,7 +55,10 @@ export const ScResultRow = ({ scResult, address }: ScResultRowType) => { {directionIn ? ( ) : ( - + )} diff --git a/src/components/TransactionAction/TransactionAction.tsx b/src/components/TransactionAction/TransactionAction.tsx index cb137b177..315a5f795 100644 --- a/src/components/TransactionAction/TransactionAction.tsx +++ b/src/components/TransactionAction/TransactionAction.tsx @@ -3,9 +3,8 @@ import { useSelector } from 'react-redux'; import { ReactComponent as DefaultAvatar } from 'assets/img/default-avatar.svg'; import { - ScAddressIcon, NetworkLink, - AccountName, + AccountLink, Denominate, TransactionActionBlock, NftBadge @@ -110,16 +109,11 @@ const ActionText = ({ } return addressIsBech32(entry.address) ? ( -
- - - - -
+ ) : ( '' ); diff --git a/src/components/TransactionsTable/components/TransactionRow.tsx b/src/components/TransactionsTable/components/TransactionRow.tsx index 5235c520d..f7bf5fea8 100644 --- a/src/components/TransactionsTable/components/TransactionRow.tsx +++ b/src/components/TransactionsTable/components/TransactionRow.tsx @@ -1,5 +1,6 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { + AccountLink, ScAddressIcon, ShardSpan, NetworkLink, @@ -9,7 +10,7 @@ import { AccountName, TransactionIcon } from 'components'; -import { addressIsBech32, urlBuilder, getDisplayReceiver } from 'helpers'; +import { urlBuilder, getDisplayReceiver } from 'helpers'; import { faArrowRight } from 'icons/regular'; import { UITransactionType, TransferTypeEnum } from 'types'; @@ -99,29 +100,21 @@ export const TransactionRow = ({ {showLockedAccounts && ( )} - + {directionOut ? ( - + + + + ) : ( + - ) : ( - <> - {addressIsBech32(transaction.sender) ? ( - - - - ) : ( - - )} - )} @@ -140,17 +133,18 @@ export const TransactionRow = ({
{showLockedAccounts && } - + {directionIn ? ( - + <> + + + ) : ( - - - + /> )}
diff --git a/src/components/TransactionsTable/transactionsTable.styles.scss b/src/components/TransactionsTable/transactionsTable.styles.scss index 11b70e27f..7177da3f0 100644 --- a/src/components/TransactionsTable/transactionsTable.styles.scss +++ b/src/components/TransactionsTable/transactionsTable.styles.scss @@ -25,8 +25,8 @@ } .transaction-value { color: var(--body-color); - max-width: 13.5rem; - min-width: 13.5rem; + max-width: 12.5rem; + min-width: 12.5rem; } .transaction-function { max-width: 9.5rem; diff --git a/src/layouts/CollectionLayout/CollectionDetailsCard.tsx b/src/layouts/CollectionLayout/CollectionDetailsCard.tsx index fa65d3bdc..6edb3bf88 100644 --- a/src/layouts/CollectionLayout/CollectionDetailsCard.tsx +++ b/src/layouts/CollectionLayout/CollectionDetailsCard.tsx @@ -3,8 +3,7 @@ import { OverlayTrigger, Tooltip } from 'react-bootstrap'; import { useSelector } from 'react-redux'; import { - Trim, - NetworkLink, + AccountLink, RolesBadges, DetailItem, NftBadge, @@ -13,7 +12,7 @@ import { SpotlightButton, AssetsHelmet } from 'components'; -import { urlBuilder, formatDate } from 'helpers'; +import { formatDate } from 'helpers'; import { useActiveRoute } from 'hooks'; import { faClock } from 'icons/regular'; import { faHexagonCheck } from 'icons/solid'; @@ -112,14 +111,7 @@ export const CollectionDetailsCard = () => { -
- - - -
+
{timestamp !== undefined && ( diff --git a/src/layouts/ProviderLayout/ProviderDetailsCard.tsx b/src/layouts/ProviderLayout/ProviderDetailsCard.tsx index 7ed29d623..7a4364c95 100644 --- a/src/layouts/ProviderLayout/ProviderDetailsCard.tsx +++ b/src/layouts/ProviderLayout/ProviderDetailsCard.tsx @@ -5,15 +5,13 @@ import { CopyButton, Denominate, LockedAmountTooltip, - NetworkLink, - Trim + AccountLink } from 'components'; import { DelegationCap } from 'components/ProvidersTable/components/DelegationCap'; import { PercentageFilled, hasDelegationCap } from 'components/ProvidersTable/components/PercentageFilled'; -import { urlBuilder } from 'helpers'; import { faServer, faLock, @@ -54,12 +52,7 @@ export const ProviderDetailsCard = ({
Address:
- - {provider.provider} - +
@@ -153,12 +146,8 @@ export const ProviderDetailsCard = ({ {provider?.owner && (
- - - + +
diff --git a/src/layouts/TokenLayout/TokenDetailsCard/TokenDetailsCard.tsx b/src/layouts/TokenLayout/TokenDetailsCard/TokenDetailsCard.tsx index 240db4798..f44123df8 100644 --- a/src/layouts/TokenLayout/TokenDetailsCard/TokenDetailsCard.tsx +++ b/src/layouts/TokenLayout/TokenDetailsCard/TokenDetailsCard.tsx @@ -2,14 +2,13 @@ import { useRef } from 'react'; import BigNumber from 'bignumber.js'; import { useSelector } from 'react-redux'; import { - Trim, - NetworkLink, + AccountLink, SocialIcons, RolesBadges, SmallDetailItem, AssetsHelmet } from 'components'; -import { urlBuilder, amountWithoutRounding } from 'helpers'; +import { amountWithoutRounding } from 'helpers'; import { tokenSelector } from 'redux/selectors'; @@ -118,14 +117,7 @@ export const TokenDetailsCard = () => {
-
- - - -
+
{supply && ( diff --git a/src/pages/Collections/Collections.tsx b/src/pages/Collections/Collections.tsx index d449c426e..b5addbcdc 100644 --- a/src/pages/Collections/Collections.tsx +++ b/src/pages/Collections/Collections.tsx @@ -6,12 +6,11 @@ import { useLocation } from 'react-router-dom'; import { Loader, NetworkLink, - Trim, + AccountLink, Pager, CollectionLink, TimeAgo } from 'components'; -import { urlBuilder } from 'helpers'; import { useAdapter, useGetSearch, @@ -206,17 +205,7 @@ export const Collections = () => {
- - - +
diff --git a/src/pages/Home/components/LatestTransactions/LatestTransactions.tsx b/src/pages/Home/components/LatestTransactions/LatestTransactions.tsx index 2aacf4232..f125f4bd1 100644 --- a/src/pages/Home/components/LatestTransactions/LatestTransactions.tsx +++ b/src/pages/Home/components/LatestTransactions/LatestTransactions.tsx @@ -8,11 +8,10 @@ import { Trim, Loader, LatestItem, - AccountName, - ScAddressIcon, PulsatingLed, TransactionIcon, - TransactionGuardianIcon + TransactionGuardianIcon, + AccountLink } from 'components'; import { FailedTransactions } from 'components/TransactionsTable/components/FailedTransactions'; import { NoTransactions } from 'components/TransactionsTable/components/NoTransactions'; @@ -162,19 +161,11 @@ export const LatestTransactions = () => {
To: - - - - + /> { From: {addressIsBech32(transaction.sender) ? ( <> - - - - diff --git a/src/pages/Nfts/Nfts.tsx b/src/pages/Nfts/Nfts.tsx index 91a6d4afe..eb6f6685a 100644 --- a/src/pages/Nfts/Nfts.tsx +++ b/src/pages/Nfts/Nfts.tsx @@ -4,7 +4,7 @@ import { useSearchParams } from 'react-router-dom'; import { Loader, NetworkLink, - Trim, + AccountLink, Pager, CollectionBlock, NftBadge @@ -124,17 +124,7 @@ export const Nfts = () => {
- - - +
diff --git a/src/pages/NodeDetails/components/NodeInformation.tsx b/src/pages/NodeDetails/components/NodeInformation.tsx index 87ecec7aa..5353a87fb 100644 --- a/src/pages/NodeDetails/components/NodeInformation.tsx +++ b/src/pages/NodeDetails/components/NodeInformation.tsx @@ -5,7 +5,8 @@ import { CopyButton, CardItem, Denominate, - LockedAmountTooltip + LockedAmountTooltip, + AccountLink } from 'components'; import { getIcon } from 'components/NodesTable/components/RowIcon'; import { urlBuilder } from 'helpers'; @@ -153,12 +154,7 @@ export const NodeInformation = ({ nodeData }: { nodeData: NodeType }) => { {owner && (
- - - +
diff --git a/src/pages/TokensMeta/TokensMeta.tsx b/src/pages/TokensMeta/TokensMeta.tsx index e9eebe03a..be9574391 100644 --- a/src/pages/TokensMeta/TokensMeta.tsx +++ b/src/pages/TokensMeta/TokensMeta.tsx @@ -2,7 +2,7 @@ import { useEffect, useRef, useState } from 'react'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { useLocation } from 'react-router-dom'; -import { Loader, NetworkLink, Trim, Pager } from 'components'; +import { Loader, NetworkLink, AccountLink, Pager } from 'components'; import { urlBuilder } from 'helpers'; import { useAdapter, useGetSearch, useActiveRoute, useGetPage } from 'hooks'; import { faDiamond } from 'icons/regular'; @@ -187,17 +187,9 @@ export const TokensMeta = () => {
- - - +
diff --git a/src/pages/TransactionDetails/components/EventsList/EventsList.tsx b/src/pages/TransactionDetails/components/EventsList/EventsList.tsx index 915511bf7..1dd11b76a 100644 --- a/src/pages/TransactionDetails/components/EventsList/EventsList.tsx +++ b/src/pages/TransactionDetails/components/EventsList/EventsList.tsx @@ -2,9 +2,8 @@ import { useEffect, useRef } from 'react'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { useLocation } from 'react-router-dom'; -import { CopyButton, Trim, DataDecode, NetworkLink } from 'components'; +import { CopyButton, DataDecode, AccountLink } from 'components'; import { DecodeMethodType } from 'components/DataDecode'; -import { urlBuilder } from 'helpers'; import { faExchange } from 'icons/regular'; import { EventType } from 'types'; @@ -71,12 +70,7 @@ export const EventsList = ({
Address
- - - + - - - + ) : ( diff --git a/src/pages/TransactionDetails/components/ScResultsList/ScResultsList.tsx b/src/pages/TransactionDetails/components/ScResultsList/ScResultsList.tsx index ad580880e..4d7f71052 100644 --- a/src/pages/TransactionDetails/components/ScResultsList/ScResultsList.tsx +++ b/src/pages/TransactionDetails/components/ScResultsList/ScResultsList.tsx @@ -9,8 +9,7 @@ import { Trim, NetworkLink, DataDecode, - AccountName, - ScAddressIcon + AccountLink } from 'components'; import { DecodeMethodType } from 'components/DataDecode'; import { urlBuilder } from 'helpers'; @@ -130,16 +129,10 @@ export const ScResultsList = ({
From
- - - - +
To
- - - - + { export const AddressDetailItem = ({ address }: { address: string }) => (
- - {addressIsBech32(address) ? ( - <> - - - - - - ) : null} + +
); @@ -292,15 +283,10 @@ export const TransactionInfo = ({ {addressIsBech32(transaction.sender) ? ( <> - - - + - - + {!isNaN(transaction.receiverShard) && ( {contract.rank} -
- - - - -
+ {new BigNumber(contract.value).toFormat()} From 4a6782640354d588b96ae174d244888f45bda3f8 Mon Sep 17 00:00:00 2001 From: Radu Mojic Date: Mon, 6 Nov 2023 15:56:07 +0200 Subject: [PATCH 4/9] fix the xl trim on mobile --- src/components/Trim/trim.styles.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/Trim/trim.styles.scss b/src/components/Trim/trim.styles.scss index 409c0eece..469d4a1e1 100644 --- a/src/components/Trim/trim.styles.scss +++ b/src/components/Trim/trim.styles.scss @@ -153,6 +153,7 @@ a:hover > .trim span { } } .table .trim-size-xl .trim { + max-width: 10rem; @include media-breakpoint-up(md) { max-width: 13rem; } From d9f464ccfd0ce2a07b12efba072276ee2bb8c9b2 Mon Sep 17 00:00:00 2001 From: Radu Mojic Date: Mon, 6 Nov 2023 16:02:02 +0200 Subject: [PATCH 5/9] fix trim on multiple tokens icon --- .../components/TransactionValue/TransactionValue.tsx | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/components/TransactionsTable/components/TransactionValue/TransactionValue.tsx b/src/components/TransactionsTable/components/TransactionValue/TransactionValue.tsx index ebee7e817..4bd7b8b39 100644 --- a/src/components/TransactionsTable/components/TransactionValue/TransactionValue.tsx +++ b/src/components/TransactionsTable/components/TransactionValue/TransactionValue.tsx @@ -28,11 +28,8 @@ const MultipleTokensBadge = ({ ); return ( - }> - + } className='cursor-context multiple-tokens'> + ); }; From 346974d6c099f73fe4ec9884559e23bd4167929a Mon Sep 17 00:00:00 2001 From: Radu Mojic Date: Mon, 6 Nov 2023 17:09:50 +0200 Subject: [PATCH 6/9] show the first transaction date on the account overview card --- src/hooks/adapter/helpers.ts | 4 +- .../AccountDetailsCard/AccountDetailsCard.tsx | 30 ++++++++++---- src/layouts/AccountLayout/AccountLayout.tsx | 35 +++++++++++++++- src/redux/reducers.ts | 2 + src/redux/selectors/accountExtra.ts | 11 +++++ src/redux/selectors/index.ts | 1 + src/redux/slices/accountExtra.ts | 31 ++++++++++++++ src/redux/slices/index.ts | 1 + src/types/account.types.ts | 6 +++ src/types/adapter.types.ts | 41 ++++++++----------- 10 files changed, 129 insertions(+), 33 deletions(-) create mode 100644 src/redux/selectors/accountExtra.ts create mode 100644 src/redux/slices/accountExtra.ts diff --git a/src/hooks/adapter/helpers.ts b/src/hooks/adapter/helpers.ts index e582e191e..d0758ee51 100644 --- a/src/hooks/adapter/helpers.ts +++ b/src/hooks/adapter/helpers.ts @@ -33,6 +33,7 @@ export function getTransactionsParams({ miniBlockHash, search, token, + order, withUsername = true }: GetTransactionsType) { const params: AdapterProviderPropsType['params'] = { @@ -50,7 +51,8 @@ export function getTransactionsParams({ ...(status ? { status } : {}), ...(miniBlockHash ? { miniBlockHash } : {}), ...(search ? { search } : {}), - ...(token ? { token } : {}) + ...(token ? { token } : {}), + ...(order ? { order } : {}) }; return params; diff --git a/src/layouts/AccountLayout/AccountDetailsCard/AccountDetailsCard.tsx b/src/layouts/AccountLayout/AccountDetailsCard/AccountDetailsCard.tsx index bbfc6abe7..91b97a498 100644 --- a/src/layouts/AccountLayout/AccountDetailsCard/AccountDetailsCard.tsx +++ b/src/layouts/AccountLayout/AccountDetailsCard/AccountDetailsCard.tsx @@ -1,6 +1,5 @@ import React, { useEffect, useRef, useState } from 'react'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { DECIMALS } from 'config'; import { useSelector } from 'react-redux'; import { ELLIPSIS } from 'appConstants'; @@ -19,6 +18,7 @@ import { FormatUSD, Overlay } from 'components'; +import { DECIMALS } from 'config'; import { isContract, urlBuilder, formatDate, formatHerotag } from 'helpers'; import { useAdapter } from 'hooks'; import { faClock, faExclamationTriangle, faInfoCircle } from 'icons/regular'; @@ -29,7 +29,11 @@ import { faHexagonVerticalNft, faShieldCheck } from 'icons/solid'; -import { activeNetworkSelector, accountSelector } from 'redux/selectors'; +import { + activeNetworkSelector, + accountSelector, + accountExtraSelector +} from 'redux/selectors'; import { AccountUpgradeType } from 'types'; import { AccountUsdValueCardItem } from './components/AccountUsdValueCardItem'; @@ -39,6 +43,7 @@ export const AccountDetailsCard = () => { const ref = useRef(null); const { account } = useSelector(accountSelector); + const { accountExtra } = useSelector(accountExtraSelector); const { address, balance, @@ -59,6 +64,7 @@ export const AccountDetailsCard = () => { activeGuardianAddress, activeGuardianServiceUid } = account; + const { firstTransactionDate } = accountExtra; const { id: activeNetworkId, adapter } = useSelector(activeNetworkSelector); const { getProvider, @@ -100,11 +106,6 @@ export const AccountDetailsCard = () => { } }; - React.useEffect(() => { - fetchProviderDetails(); - fetchUpgradesDetails(); - }, [activeNetworkId, address]); - const fetchAccountTokensCount = () => { if (tokensActive) { getAccountTokensCount({ address, includeMetaESDT: true }).then( @@ -141,6 +142,12 @@ export const AccountDetailsCard = () => { ); } }; + + useEffect(() => { + fetchProviderDetails(); + fetchUpgradesDetails(); + }, [activeNetworkId, address]); + useEffect(() => { fetchAccountNftsCount(); fetchAccountTokensCount(); @@ -515,6 +522,15 @@ export const AccountDetailsCard = () => { <>N/A )} + {firstTransactionDate && ( + + + + )}
diff --git a/src/layouts/AccountLayout/AccountLayout.tsx b/src/layouts/AccountLayout/AccountLayout.tsx index 79323bf0c..3f89acb16 100644 --- a/src/layouts/AccountLayout/AccountLayout.tsx +++ b/src/layouts/AccountLayout/AccountLayout.tsx @@ -11,8 +11,13 @@ import { Loader } from 'components'; import { addressIsBech32, getTotalTokenUsdValue } from 'helpers'; import { useAdapter, useGetPage } from 'hooks'; import { activeNetworkSelector } from 'redux/selectors'; -import { setAccount, setAccountStaking } from 'redux/slices'; -import { IdentityType, ProviderType, DelegationType } from 'types'; +import { setAccount, setAccountExtra, setAccountStaking } from 'redux/slices'; +import { + IdentityType, + ProviderType, + DelegationType, + SortOrderEnum +} from 'types'; import { AccountDetailsCard } from './AccountDetailsCard'; import { FailedAccount } from './FailedAccount'; @@ -28,6 +33,7 @@ export const AccountLayout = () => { const { getAccount, getAccountTokens, + getAccountTransfers, getAccountDelegationLegacy, getAccountDelegation, getAccountStake, @@ -68,6 +74,30 @@ export const AccountLayout = () => { } }; + const fetchFirstTransactionDate = () => { + if (address) { + getAccountTransfers({ + address, + size: 1, + order: SortOrderEnum.asc, + fields: 'timestamp' + }).then(({ data, success }) => { + let firstTransactionDate = undefined; + if (success && data && data.length > 0) { + firstTransactionDate = data[0]?.['timestamp']; + } + dispatch( + setAccountExtra({ + accountExtra: { + firstTransactionDate + }, + isFetched: success + }) + ); + }); + } + }; + const fetchStakingDetails = () => { if (address) { Promise.all([ @@ -323,6 +353,7 @@ export const AccountLayout = () => { useEffect(() => { fetchStakingDetails(); + fetchFirstTransactionDate(); }, [address, activeNetworkId]); useEffect(() => { diff --git a/src/redux/reducers.ts b/src/redux/reducers.ts index 91b9ffe65..994ec56f7 100644 --- a/src/redux/reducers.ts +++ b/src/redux/reducers.ts @@ -4,6 +4,7 @@ import storage from 'redux-persist/lib/storage'; // import sessionStorage from 'redux-persist/lib/storage/session'; import { accountReducer } from './slices/account'; +import { accountExtraReducer } from './slices/accountExtra'; import { accountStakingReducer } from './slices/accountStaking'; import { collectionReducer } from './slices/collection'; import { economicsReducer } from './slices/economics'; @@ -51,6 +52,7 @@ export const customIgnoredSlices = { interface: interfaceReducer, account: accountReducer, + accountExtra: accountExtraReducer, accountStaking: accountStakingReducer, collection: collectionReducer, economics: economicsReducer, diff --git a/src/redux/selectors/accountExtra.ts b/src/redux/selectors/accountExtra.ts new file mode 100644 index 000000000..962cfd074 --- /dev/null +++ b/src/redux/selectors/accountExtra.ts @@ -0,0 +1,11 @@ +import { createSelector } from 'reselect'; +import { RootState } from '../store'; + +const stateSelector = (state: RootState) => { + return state.accountExtra; +}; + +export const accountExtraSelector = createSelector( + stateSelector, + (state) => state +); diff --git a/src/redux/selectors/index.ts b/src/redux/selectors/index.ts index a5d664663..33e6cd64a 100644 --- a/src/redux/selectors/index.ts +++ b/src/redux/selectors/index.ts @@ -1,4 +1,5 @@ export * from './account'; +export * from './accountExtra'; export * from './accountStaking'; export * from './collection'; export * from './economics'; diff --git a/src/redux/slices/accountExtra.ts b/src/redux/slices/accountExtra.ts new file mode 100644 index 000000000..02a55731d --- /dev/null +++ b/src/redux/slices/accountExtra.ts @@ -0,0 +1,31 @@ +import { createSlice, PayloadAction } from '@reduxjs/toolkit'; +import { AccountExtraSliceType } from 'types/account.types'; + +export const getInitialAccountExtraState = (): AccountExtraSliceType => { + return { + accountExtra: { + firstTransactionDate: undefined + }, + isFetched: false + }; +}; + +export const accountExtraSlice = createSlice({ + name: 'accountExtraSlice', + initialState: getInitialAccountExtraState(), + reducers: { + setAccountExtra: ( + state: AccountExtraSliceType, + action: PayloadAction + ) => { + state.accountExtra.firstTransactionDate = + action.payload.accountExtra.firstTransactionDate; + + state.isFetched = action.payload.isFetched; + } + } +}); + +export const { setAccountExtra } = accountExtraSlice.actions; + +export const accountExtraReducer = accountExtraSlice.reducer; diff --git a/src/redux/slices/index.ts b/src/redux/slices/index.ts index e5fbb171c..f67a7bea2 100644 --- a/src/redux/slices/index.ts +++ b/src/redux/slices/index.ts @@ -1,4 +1,5 @@ export * from './account'; +export * from './accountExtra'; export * from './accountStaking'; export * from './collection'; export * from './economics'; diff --git a/src/types/account.types.ts b/src/types/account.types.ts index 71c2151cb..a0ba2a7bb 100644 --- a/src/types/account.types.ts +++ b/src/types/account.types.ts @@ -64,6 +64,12 @@ export interface AccountStakingSliceType { delegationLegacyIdentity: IdentityType | undefined; } +export interface AccountExtraSliceType extends SliceType { + accountExtra: { + firstTransactionDate: number | undefined; + }; +} + export interface AccountAssetType { name: string; description?: string; diff --git a/src/types/adapter.types.ts b/src/types/adapter.types.ts index 62000ce0f..b8f4043b7 100644 --- a/src/types/adapter.types.ts +++ b/src/types/adapter.types.ts @@ -1,30 +1,32 @@ -export interface GetBlocksType { +import { SortOrderEnum } from 'types'; + +export interface BaseApiType { page?: number; size?: number; + fields?: string; + extract?: string; +} + +export interface GetBlocksType extends BaseApiType { shard?: number; epoch?: number; proposer?: string; withProposerIdentity?: boolean; } -export interface GetTokensType { - fields?: string; - page?: number; - size?: number; +export interface GetTokensType extends BaseApiType { type?: string; search?: string; name?: string; identifier?: string; identifiers?: string; sort?: string; - order?: string; + order?: SortOrderEnum; includeMetaESDT?: boolean; withUsername?: boolean; } -export interface GetNftsType { - page?: number; - size?: number; +export interface GetNftsType extends BaseApiType { search?: string; identifiers?: string; type?: string; @@ -40,10 +42,7 @@ export interface GetNftsType { source?: string; } -export interface GetCollectionsType { - fields?: string; - page?: number; - size?: number; +export interface GetCollectionsType extends BaseApiType { search?: string; identifiers?: string; type?: string; @@ -54,7 +53,7 @@ export interface GetCollectionsType { withOwner?: boolean; } -export interface GetNodesType { +export interface GetNodesType extends BaseApiType { search?: string; issues?: string; online?: boolean; @@ -62,19 +61,15 @@ export interface GetNodesType { shard?: string; status?: string; count?: boolean; - page?: number; - size?: number; identity?: string; sort?: string; - order?: string; + order?: SortOrderEnum; pagination?: boolean; provider?: string; fullHistory?: string; } -export interface GetTransactionsType { - page?: number; - size?: number; +export interface GetTransactionsType extends BaseApiType { address?: string; senderShard?: number; receiverShard?: number; @@ -88,12 +83,12 @@ export interface GetTransactionsType { search?: string; token?: string; withUsername?: boolean; + order?: SortOrderEnum; } -export interface GetProvidersType { +export interface GetProvidersType extends BaseApiType { identity?: string; providers?: string; - fields?: string; } export type AdapterProviderType = ( @@ -131,7 +126,7 @@ export interface AdapterProviderPropsType { identities?: string; provider?: string; sort?: string; - order?: string; + order?: SortOrderEnum; online?: boolean; collection?: string; identifier?: string; From f8edb618ae3252ad8902f427113563599781843b Mon Sep 17 00:00:00 2001 From: Radu Mojic Date: Mon, 6 Nov 2023 17:10:46 +0200 Subject: [PATCH 7/9] updated the TimeAgo component --- src/components/TimeAgo/TimeAgo.tsx | 14 +++++++++++--- src/components/TimeAgo/helpers/timeAgo.ts | 10 ++++------ src/pages/AccountDetails/AccountContracts.tsx | 2 +- src/pages/AccountDetails/AccountUpgrades.tsx | 2 +- .../Home/components/LatestBlocks/LatestBlocks.tsx | 2 +- 5 files changed, 18 insertions(+), 12 deletions(-) diff --git a/src/components/TimeAgo/TimeAgo.tsx b/src/components/TimeAgo/TimeAgo.tsx index d609f2121..2662656d5 100644 --- a/src/components/TimeAgo/TimeAgo.tsx +++ b/src/components/TimeAgo/TimeAgo.tsx @@ -5,11 +5,13 @@ import { timeAgo } from './helpers/timeAgo'; export const TimeAgo = ({ value, short = false, - tooltip = false + tooltip = false, + showAgo = false }: { value: number; short?: boolean; tooltip?: boolean; + showAgo?: boolean; }) => { const ms = value * 1000; let result = timeAgo(ms); @@ -31,9 +33,15 @@ export const TimeAgo = ({ )} > - {result} + + {result} + {showAgo ? ' ago' : ''} + ) : ( - <>{result} + <> + {result} + {showAgo ? ' ago' : ''} + ); }; diff --git a/src/components/TimeAgo/helpers/timeAgo.ts b/src/components/TimeAgo/helpers/timeAgo.ts index 7826fe434..cdb028409 100644 --- a/src/components/TimeAgo/helpers/timeAgo.ts +++ b/src/components/TimeAgo/helpers/timeAgo.ts @@ -9,8 +9,6 @@ export function dhms(ms: number) { const minsms = hrsms % (60 * 1000); const secs = Math.floor(minsms / 1000); - // let diff = ' ago'; - const diff = ''; let secsString = secs + ' sec'; let minsString = mins + ' min'; let hrsString = hrs + ' hr'; @@ -21,17 +19,17 @@ export function dhms(ms: number) { if (hrs > 1) hrsString = hrs + ' hrs'; if (days > 1) daysString = days + ' days'; - if (days >= 1) return daysString + ' ' + hrsString + diff; + if (days >= 1) return daysString + ' ' + hrsString; if (hrs >= 1) { - const minutesString = mins === 0 ? '' : ' ' + minsString + diff; + const minutesString = mins === 0 ? '' : ' ' + minsString; return hrsString + minutesString; } if (mins >= 1) { - const secString = secs === 0 ? '' : ' ' + secsString + diff; + const secString = secs === 0 ? '' : ' ' + secsString; return minsString + secString; } - return secsString + diff; + return secsString; } export const timeAgo = (timestamp: number) => { diff --git a/src/pages/AccountDetails/AccountContracts.tsx b/src/pages/AccountDetails/AccountContracts.tsx index 8f921bbcd..480957253 100644 --- a/src/pages/AccountDetails/AccountContracts.tsx +++ b/src/pages/AccountDetails/AccountContracts.tsx @@ -115,7 +115,7 @@ export const AccountContracts = () => {
- ago +   diff --git a/src/pages/AccountDetails/AccountUpgrades.tsx b/src/pages/AccountDetails/AccountUpgrades.tsx index 52faf6bdc..2d2259007 100644 --- a/src/pages/AccountDetails/AccountUpgrades.tsx +++ b/src/pages/AccountDetails/AccountUpgrades.tsx @@ -99,7 +99,7 @@ export const AccountUpgrades = () => {
- ago +   diff --git a/src/pages/Home/components/LatestBlocks/LatestBlocks.tsx b/src/pages/Home/components/LatestBlocks/LatestBlocks.tsx index 78b388107..4963272b3 100644 --- a/src/pages/Home/components/LatestBlocks/LatestBlocks.tsx +++ b/src/pages/Home/components/LatestBlocks/LatestBlocks.tsx @@ -106,7 +106,7 @@ export const LatestBlocks = () => {
- ago +
From 2fa47773677eb5d2c7420d4e6624bb3425c0ccca Mon Sep 17 00:00:00 2001 From: Radu Mojic Date: Mon, 6 Nov 2023 17:18:34 +0200 Subject: [PATCH 8/9] updated the data-testid on the NetworkLink Component --- src/components/NetworkLink/NetworkLink.tsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/components/NetworkLink/NetworkLink.tsx b/src/components/NetworkLink/NetworkLink.tsx index 1505bcd75..ac042a280 100644 --- a/src/components/NetworkLink/NetworkLink.tsx +++ b/src/components/NetworkLink/NetworkLink.tsx @@ -9,6 +9,7 @@ export const NetworkLink = ({ to, children, preventScrollReset = false, + 'data-testid': dataTestId, ...rest }: NetworkLinkPropsType) => { const { id: activeNetworkId } = useSelector(activeNetworkSelector); @@ -32,7 +33,11 @@ export const NetworkLink = ({ }; return ( - + {children} ); From 6773751ae3fed9e99a6706b3530ba06c5254ee0f Mon Sep 17 00:00:00 2001 From: Radu Mojic Date: Mon, 6 Nov 2023 17:35:42 +0200 Subject: [PATCH 9/9] updated readme --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 111c5fd00..8ac6fe5e0 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # MultiversX Explorer +![explorer.multiversx.com](https://github.com/multiversx/mx-explorer-dapp/blob/main/public/share.jpg) + This project was bootstrapped with [Vite](https://vitejs.dev/guide/). ## Deployments