Skip to content

Commit

Permalink
fixup! feat(suite): nft section
Browse files Browse the repository at this point in the history
  • Loading branch information
enjojoy committed Nov 27, 2024
1 parent a222baa commit 2947732
Show file tree
Hide file tree
Showing 8 changed files with 88 additions and 115 deletions.
5 changes: 5 additions & 0 deletions packages/blockchain-link-types/src/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import type {
AddressAlias,
TokenTransfer as BlockbookTokenTransfer,
ContractInfo,
MultiTokenValue,
StakingPool,
} from './blockbook-api';

Expand Down Expand Up @@ -188,6 +189,10 @@ export interface TokenInfo {
accounts?: TokenAccount[]; // token accounts for solana
policyId?: string; // Cardano policy id
fingerprint?: string; // Cardano starting with "asset"
multiTokenValues?: MultiTokenValue[];
ids?: string[];
totalReceived?: string;
totalSent?: string;
// transfers: number, // total transactions?
}

Expand Down
59 changes: 0 additions & 59 deletions packages/suite/src/utils/wallet/nftUtils.ts
Original file line number Diff line number Diff line change
@@ -1,60 +1 @@
import { isTokenDefinitionKnown, TokenDefinition } from '@suite-common/token-definitions';
import { isNftMatchesSearch, filterNftTokens } from '@suite-common/wallet-utils';
import { NetworkSymbol, getNetworkFeatures } from '@suite-common/wallet-config';
import { Token } from '@trezor/blockchain-link-types/src/blockbook-api';

type GetNfts = {
tokens: Token[];
symbol: NetworkSymbol;
nftDefinitions?: TokenDefinition;
searchQuery?: string;
};

export type NftType = 'ERC721' | 'ERC1155';

export const getNfts = ({ tokens, symbol, nftDefinitions, searchQuery }: GetNfts) => {
// filter out NFT tokens until we implement them
const nfts = filterNftTokens(tokens);

const hasNftDefinitions = getNetworkFeatures(symbol).includes('nft-definitions');

const shownVerified: Token[] = [];
const shownUnverified: Token[] = [];
const hiddenVerified: Token[] = [];
const hiddenUnverified: Token[] = [];

nfts.forEach(token => {
const isKnown = isTokenDefinitionKnown(nftDefinitions?.data, symbol, token.contract || '');
const isHidden = nftDefinitions?.hide.includes(token.contract || '');
const isShown = nftDefinitions?.show.includes(token.contract || '');

const query = searchQuery ? searchQuery.trim().toLowerCase() : '';

if (searchQuery && !isNftMatchesSearch(token, query)) return;

const pushToArray = (arrayVerified: Token[], arrayUnverified: Token[]) => {
if (isKnown) {
arrayVerified.push(token);
} else {
arrayUnverified.push(token);
}
};

if (isShown) {
pushToArray(shownVerified, shownUnverified);
} else if (hasNftDefinitions && !isKnown) {
pushToArray(hiddenVerified, hiddenUnverified);
} else if (isHidden) {
pushToArray(hiddenVerified, hiddenUnverified);
} else {
pushToArray(shownVerified, shownUnverified);
}
});

return {
shownVerified,
shownUnverified,
hiddenVerified,
hiddenUnverified,
};
};
99 changes: 68 additions & 31 deletions packages/suite/src/utils/wallet/tokenUtils.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import { BigNumber } from '@trezor/utils/src/bigNumber';
import { Account, Rate, TokenAddress, RatesByKey } from '@suite-common/wallet-types';
import { TokenInfo } from '@trezor/connect';
import { getFiatRateKey, isNftToken, isTokenMatchesSearch } from '@suite-common/wallet-utils';
import {
getFiatRateKey,
isNftMatchesSearch,
isNftToken,
isTokenMatchesSearch,
} from '@suite-common/wallet-utils';
import { NetworkSymbol, getNetworkFeatures } from '@suite-common/wallet-config';
import { FiatCurrencyCode } from '@suite-common/suite-config';
import {

Check warning on line 12 in packages/suite/src/utils/wallet/tokenUtils.ts

View workflow job for this annotation

GitHub Actions / Linting and formatting

There should be no empty line within import group
Expand All @@ -10,6 +15,8 @@ import {
isTokenDefinitionKnown,
} from '@suite-common/token-definitions';

import { Token } from '@trezor/blockchain-link-types/src/blockbook-api';

export interface TokensWithRates extends TokenInfo {
fiatValue: BigNumber;
fiatRate?: Rate;
Expand Down Expand Up @@ -65,32 +72,64 @@ export const formatTokenSymbol = (symbol: string) => {
return isTokenSymbolLong ? `${upperCasedSymbol.slice(0, 7)}...` : upperCasedSymbol;
};

export const getTokens = (
tokens: EnhancedTokenInfo[] | TokenInfo[],
symbol: NetworkSymbol,
coinDefinitions?: TokenDefinition,
searchQuery?: string,
) => {
type GetTokens = {
tokens: EnhancedTokenInfo[] | TokenInfo[];
symbol: NetworkSymbol;
tokenDefinitions?: TokenDefinition;
searchQuery?: string;
isNft?: boolean;
};

export type TokensResult = {
shownWithBalance: EnhancedTokenInfo[];
shownWithoutBalance: EnhancedTokenInfo[];
hiddenWithBalance: EnhancedTokenInfo[];
hiddenWithoutBalance: EnhancedTokenInfo[];
unverifiedWithBalance: EnhancedTokenInfo[];
unverifiedWithoutBalance: EnhancedTokenInfo[];
};

export type NftTokensResult = {
shownVerified: EnhancedTokenInfo[];
shownUnverified: EnhancedTokenInfo[];
hiddenVerified: EnhancedTokenInfo[];
hiddenUnverified: EnhancedTokenInfo[];
};

export const getTokens = ({
tokens,
symbol,
tokenDefinitions,
searchQuery,
isNft = false,
}: GetTokens): NftTokensResult | TokensResult => {
// filter out NFT tokens until we implement them
const tokensWithoutNFTs = tokens.filter(token => !isNftToken(token));
const filteredTokens = isNft
? tokens.filter(token => isNftToken(token))
: tokens.filter(token => !isNftToken(token));

const hasCoinDefinitions = getNetworkFeatures(symbol).includes('coin-definitions');
const hasDefinitions = getNetworkFeatures(symbol).includes(
isNft ? 'nft-definitions' : 'coin-definitions',
);

const shownWithBalance: EnhancedTokenInfo[] = [];
const shownWithoutBalance: EnhancedTokenInfo[] = [];
const hiddenWithBalance: EnhancedTokenInfo[] = [];
const hiddenWithoutBalance: EnhancedTokenInfo[] = [];
const unverifiedWithBalance: EnhancedTokenInfo[] = [];
const unverifiedWithoutBalance: EnhancedTokenInfo[] = [];
const shownVerified: EnhancedTokenInfo[] = [];
const shownUnverified: EnhancedTokenInfo[] = [];
const hiddenVerified: EnhancedTokenInfo[] = [];
const hiddenUnverified: EnhancedTokenInfo[] = [];

tokensWithoutNFTs.forEach(token => {
const isKnown = isTokenDefinitionKnown(coinDefinitions?.data, symbol, token.contract);
const isHidden = coinDefinitions?.hide.includes(token.contract);
const isShown = coinDefinitions?.show.includes(token.contract);
filteredTokens.forEach(token => {
const isKnown = isTokenDefinitionKnown(tokenDefinitions?.data, symbol, token.contract);
const isHidden = tokenDefinitions?.hide.includes(token.contract);
const isShown = tokenDefinitions?.show.includes(token.contract);

const query = searchQuery ? searchQuery.trim().toLowerCase() : '';

if (searchQuery && !isTokenMatchesSearch(token, query)) return;
if (
searchQuery &&
(!isTokenMatchesSearch(token, query) ||
(isNft && isNftMatchesSearch(token as Token, query)))
)
return;

const hasBalance = new BigNumber(token?.balance || '0').gt(0);

Expand All @@ -106,22 +145,20 @@ export const getTokens = (
};

if (isShown) {
pushToArray(shownWithBalance, shownWithoutBalance);
} else if (hasCoinDefinitions && !isKnown) {
pushToArray(unverifiedWithBalance, unverifiedWithoutBalance);
pushToArray(shownVerified, shownUnverified);
} else if (hasDefinitions && !isKnown) {
pushToArray(hiddenVerified, hiddenUnverified);
} else if (isHidden) {
pushToArray(hiddenWithBalance, hiddenWithoutBalance);
pushToArray(hiddenVerified, hiddenUnverified);
} else {
pushToArray(shownWithBalance, shownWithoutBalance);
pushToArray(shownVerified, shownUnverified);
}
});

return {
shownWithBalance,
shownWithoutBalance,
hiddenWithBalance,
hiddenWithoutBalance,
unverifiedWithBalance,
unverifiedWithoutBalance,
shownVerified,
shownUnverified,
hiddenVerified,
hiddenUnverified,
};
};
15 changes: 7 additions & 8 deletions packages/suite/src/views/wallet/nfts/HiddenNfts.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,10 @@ import { Banner, Column, H3 } from '@trezor/components';
import { SelectedAccountLoaded } from '@suite-common/wallet-types';

Check warning on line 2 in packages/suite/src/views/wallet/nfts/HiddenNfts.tsx

View workflow job for this annotation

GitHub Actions / Linting and formatting

There should be at least one empty line between import groups
import NftsTable from './NftsTable/NftsTable';

Check warning on line 3 in packages/suite/src/views/wallet/nfts/HiddenNfts.tsx

View workflow job for this annotation

GitHub Actions / Linting and formatting

There should be at least one empty line between import groups
import { Translation } from 'src/components/suite';

Check warning on line 4 in packages/suite/src/views/wallet/nfts/HiddenNfts.tsx

View workflow job for this annotation

GitHub Actions / Linting and formatting

`src/components/suite` import should occur before import of `./NftsTable/NftsTable`
import { Token } from '@trezor/blockchain-link-types/src/blockbook-api';
import { useSelector } from 'src/hooks/suite';

Check warning on line 5 in packages/suite/src/views/wallet/nfts/HiddenNfts.tsx

View workflow job for this annotation

GitHub Actions / Linting and formatting

There should be at least one empty line between import groups

Check warning on line 5 in packages/suite/src/views/wallet/nfts/HiddenNfts.tsx

View workflow job for this annotation

GitHub Actions / Linting and formatting

`src/hooks/suite` import should occur before import of `./NftsTable/NftsTable`
import { getNfts } from 'src/utils/wallet/nftUtils';
import { selectNftDefinitions } from '@suite-common/token-definitions';

Check warning on line 6 in packages/suite/src/views/wallet/nfts/HiddenNfts.tsx

View workflow job for this annotation

GitHub Actions / Linting and formatting

There should be at least one empty line between import groups

Check warning on line 6 in packages/suite/src/views/wallet/nfts/HiddenNfts.tsx

View workflow job for this annotation

GitHub Actions / Linting and formatting

`@suite-common/token-definitions` import should occur before import of `./NftsTable/NftsTable`
import { filterNftTokens } from '@suite-common/wallet-utils';
import { NoTokens } from '../tokens/common/NoTokens';

Check warning on line 7 in packages/suite/src/views/wallet/nfts/HiddenNfts.tsx

View workflow job for this annotation

GitHub Actions / Linting and formatting

There should be at least one empty line between import groups
import { getTokens, NftTokensResult } from 'src/utils/wallet/tokenUtils';

Check warning on line 8 in packages/suite/src/views/wallet/nfts/HiddenNfts.tsx

View workflow job for this annotation

GitHub Actions / Linting and formatting

`src/utils/wallet/tokenUtils` import should occur before import of `./NftsTable/NftsTable`

type NftsTableProps = {
selectedAccount: SelectedAccountLoaded;
Expand All @@ -19,13 +17,14 @@ const HiddenNfts = ({ selectedAccount, searchQuery }: NftsTableProps) => {
const nftDefinitions = useSelector(state =>
selectNftDefinitions(state, selectedAccount.account.symbol),
);
const nfts = getNfts({
tokens: filteredTokens as Token[],
const nfts = getTokens({
tokens: filteredTokens,
symbol: selectedAccount.account.symbol,
nftDefinitions,
});
tokenDefinitions: nftDefinitions,
isNft: true,
}) as NftTokensResult;

return nfts.hiddenVerified.length > 0 || nfts.hiddenUnverified.length > 0 ? (
return (nfts && nfts.hiddenVerified.length > 0) || nfts.hiddenUnverified.length > 0 ? (
<Column gap={24} alignItems="stretch">
<NftsTable
selectedAccount={selectedAccount}
Expand Down
10 changes: 4 additions & 6 deletions packages/suite/src/views/wallet/nfts/NftsTable/NftsRow.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Network } from '@suite-common/wallet-config';
import { DefinitionType, tokenDefinitionsActions } from '@suite-common/token-definitions';
import { TokenManagementAction } from '@suite-common/token-definitions';
import { Token } from '@trezor/blockchain-link-types/src/blockbook-api';
import { EnhancedTokenInfo } from '@suite-common/token-definitions';
import {
Button,
Column,
Expand Down Expand Up @@ -30,7 +30,7 @@ import { notificationsActions } from '@suite-common/toast-notifications';
import { AddressType } from '@suite-common/wallet-types';

type NftsRowProps = {
nft: Token;
nft: EnhancedTokenInfo;
type: NftType;
network: Network;
shown?: boolean;
Expand All @@ -54,15 +54,15 @@ const NftsRow = ({ nft, type, network, shown }: NftsRowProps) => {
const { translationString } = useTranslation();
const shouldShowCopyAddressModal = useSelector(selectIsCopyAddressModalShown);

const getNftContractExplorerUrl = (network: Network, nft: Token) => {
const getNftContractExplorerUrl = (network: Network, nft: EnhancedTokenInfo) => {
const explorerUrl = network.explorer.account;
const contractAddress = nft.contract;
const queryString = network.explorer.queryString ?? '';

return `${explorerUrl}${contractAddress}${queryString}`;
};

const getNftExplorerUrl = (network: Network, nft: Token, id?: string) => {
const getNftExplorerUrl = (network: Network, nft: EnhancedTokenInfo, id?: string) => {
const explorerUrl = network.explorer.nft;
const contractAddressWithId = nft.contract + `/${id}`;

Expand All @@ -86,8 +86,6 @@ const NftsRow = ({ nft, type, network, shown }: NftsRowProps) => {
}
};

const name = nft.name.length > 15 ? `${nft.name.slice(0, 15)}...` : nft.name;

return (
<Table.Row>
<Table.Cell colSpan={1}>
Expand Down
8 changes: 2 additions & 6 deletions packages/suite/src/views/wallet/nfts/NftsTable/NftsTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,15 @@ import { Translation } from 'src/components/suite/Translation';
import NftsRow from './NftsRow';
import { Token } from '@trezor/blockchain-link-types/src/blockbook-api';
import { getNetwork } from '@suite-common/wallet-config';
import { NftTokensResult } from 'src/utils/wallet/tokenUtils';

type NftsTableProps = {
selectedAccount: SelectedAccountLoaded;
searchQuery: string;
type: 'ERC721' | 'ERC1155';
shown?: boolean;
verified?: boolean;
nfts: {
shownVerified: Token[];
shownUnverified: Token[];
hiddenVerified: Token[];
hiddenUnverified: Token[];
};
nfts: NftTokensResult;
};

const NftsTable = ({
Expand Down
3 changes: 2 additions & 1 deletion suite-common/wallet-utils/src/accountUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1187,6 +1187,7 @@ export const isNftMatchesSearch = (token: Token, search: string) => {
token.ids
?.map(id => id.toString())
.join(', ')
.includes(search)
.includes(search) ||
token.multiTokenValues?.some(value => value.id?.includes(search))
);
};
4 changes: 0 additions & 4 deletions suite-common/wallet-utils/src/transactionUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ import { FiatCurrencyCode } from '@suite-common/suite-config';
import { formatAmount, formatNetworkAmount, isTokenMatchesSearch } from './accountUtils';
import { toFiatCurrency } from '../src/fiatConverterUtils';
import { getFiatRateKey, roundTimestampToNearestPastHour } from './fiatRatesUtils';
import { Token } from '@trezor/blockchain-link-types/src/blockbook-api';

export const sortByBlockHeight = (a: { blockHeight?: number }, b: { blockHeight?: number }) => {
// if both are missing the blockHeight don't change their order
Expand Down Expand Up @@ -489,9 +488,6 @@ export const getNftTokenId = (transfer: TokenTransfer) =>
? transfer.multiTokenValues[0].id
: transfer.amount;

export const filterNftTokens = (tokens: Token[] | TokenInfo[]) =>
tokens.filter(token => isNftToken(token as TokenInfo)) as TokenInfo[];

export const getTxIcon = (txType: WalletAccountTransaction['type']) => {
switch (txType) {
case 'recv':
Expand Down

0 comments on commit 2947732

Please sign in to comment.