From abead37e73e226167419f05496dc65c8be7fb092 Mon Sep 17 00:00:00 2001 From: Ilias Trichopoulos Date: Fri, 7 Feb 2025 15:15:56 +0100 Subject: [PATCH 01/17] Add shortcut buttons in token details modal --- .../useFetchWalletBalancesTokensByAddress.ts | 11 +++--- .../components/Buttons/ShortcutButtons.tsx | 35 ++++++++++++++----- .../transfer/AddressesTxModalContent.tsx | 2 +- .../src/features/send/sendTypes.ts | 2 ++ apps/desktop-wallet/src/hooks/useAddresses.ts | 25 ++++++++----- .../modals/tokenDetails/TokenDetailsModal.tsx | 2 ++ 6 files changed, 55 insertions(+), 22 deletions(-) diff --git a/apps/desktop-wallet/src/api/apiDataHooks/wallet/useFetchWalletBalancesTokensByAddress.ts b/apps/desktop-wallet/src/api/apiDataHooks/wallet/useFetchWalletBalancesTokensByAddress.ts index 016d1688e..deb522a24 100644 --- a/apps/desktop-wallet/src/api/apiDataHooks/wallet/useFetchWalletBalancesTokensByAddress.ts +++ b/apps/desktop-wallet/src/api/apiDataHooks/wallet/useFetchWalletBalancesTokensByAddress.ts @@ -25,14 +25,17 @@ const combineBalancesByAddress = ( ...combineIsLoading(results) }) -const { - useData: useFetchWalletBalancesTokensByAddress, - DataContextProvider: UseFetchWalletBalancesTokensByAddressContextProvider -} = createDataContext({ +const { useData, DataContextProvider } = createDataContext< + AddressTokensBalancesQueryFnData, + AddressesTokensBalances['data'] +>({ useDataHook: useFetchWalletBalancesTokens, combineFn: combineBalancesByAddress, defaultValue: {} }) +const useFetchWalletBalancesTokensByAddress = useData +const UseFetchWalletBalancesTokensByAddressContextProvider = DataContextProvider + export default useFetchWalletBalancesTokensByAddress export { UseFetchWalletBalancesTokensByAddressContextProvider } diff --git a/apps/desktop-wallet/src/components/Buttons/ShortcutButtons.tsx b/apps/desktop-wallet/src/components/Buttons/ShortcutButtons.tsx index c96d16252..f0c1a4bbd 100644 --- a/apps/desktop-wallet/src/components/Buttons/ShortcutButtons.tsx +++ b/apps/desktop-wallet/src/components/Buttons/ShortcutButtons.tsx @@ -1,4 +1,5 @@ import { AddressHash } from '@alephium/shared' +import { ALPH } from '@alephium/token-list' import { ArrowDownToLine, CreditCard, Send, Settings } from 'lucide-react' import { useTranslation } from 'react-i18next' import styled from 'styled-components' @@ -9,18 +10,14 @@ import { useAppDispatch, useAppSelector } from '@/hooks/redux' import { useFetchAddressesHashesWithBalance } from '@/hooks/useAddresses' import { selectAddressByHash, selectDefaultAddress } from '@/storage/addresses/addressesSelectors' import { selectCurrentlyOnlineNetworkId } from '@/storage/network/networkSelectors' +import { TokenId } from '@/types/tokens' interface ShortcutButtonBaseProps { analyticsOrigin: string highlight?: boolean } -interface ShortcutButtonsGroupWalletProps extends ShortcutButtonBaseProps { - settings?: boolean - lock?: boolean -} - -export const ShortcutButtonsGroupWallet = ({ ...buttonProps }: ShortcutButtonsGroupWalletProps) => { +export const ShortcutButtonsGroupWallet = ({ ...buttonProps }: ShortcutButtonBaseProps) => { const { hash: defaultAddressHash } = useAppSelector(selectDefaultAddress) return ( @@ -45,6 +42,22 @@ export const ShortcutButtonsGroupAddress = ({ addressHash, ...buttonProps }: Sho ) +interface ShortcutButtonsGroupTokenProps extends ShortcutButtonBaseProps { + tokenId: TokenId +} + +export const ShortcutButtonsGroupToken = ({ tokenId, ...buttonProps }: ShortcutButtonsGroupTokenProps) => { + const { hash: defaultAddressHash } = useAppSelector(selectDefaultAddress) + + return ( + + + + {tokenId === ALPH.id && } + + ) +} + interface SettingsButtonProps extends ShortcutButtonBaseProps { addressHash?: AddressHash } @@ -93,12 +106,16 @@ const ReceiveButton = ({ addressHash, analyticsOrigin }: ShortcutButtonsGroupAdd ) } -const SendButton = ({ addressHash, analyticsOrigin }: ShortcutButtonsGroupAddressProps) => { +interface SendButtonProps extends ShortcutButtonsGroupAddressProps { + tokenId?: TokenId +} + +const SendButton = ({ addressHash, tokenId, analyticsOrigin }: SendButtonProps) => { const { sendAnalytics } = useAnalytics() const { t } = useTranslation() const fromAddress = useAppSelector((s) => selectAddressByHash(s, addressHash)) const dispatch = useAppDispatch() - const { data: addressesHashesWithBalance } = useFetchAddressesHashesWithBalance() + const { data: addressesHashesWithBalance } = useFetchAddressesHashesWithBalance(tokenId) const currentNetwork = useAppSelector(selectCurrentlyOnlineNetworkId) if (!fromAddress) return null @@ -114,7 +131,7 @@ const SendButton = ({ addressHash, analyticsOrigin }: ShortcutButtonsGroupAddres const handleSendClick = () => { if (isDisabled) return - dispatch(openModal({ name: 'TransferSendModal', props: { initialTxData: { fromAddress } } })) + dispatch(openModal({ name: 'TransferSendModal', props: { initialTxData: { fromAddress, tokenId } } })) sendAnalytics({ event: 'Send button clicked', props: { origin: analyticsOrigin } }) } diff --git a/apps/desktop-wallet/src/features/send/sendModals/transfer/AddressesTxModalContent.tsx b/apps/desktop-wallet/src/features/send/sendModals/transfer/AddressesTxModalContent.tsx index 33848e815..4f4324799 100644 --- a/apps/desktop-wallet/src/features/send/sendModals/transfer/AddressesTxModalContent.tsx +++ b/apps/desktop-wallet/src/features/send/sendModals/transfer/AddressesTxModalContent.tsx @@ -18,7 +18,7 @@ interface TransferAddressesTxModalContentProps { const TransferAddressesTxModalContent = ({ data, onSubmit, onCancel }: TransferAddressesTxModalContentProps) => { const { t } = useTranslation() - const { data: fromAddresses } = useFetchAddressesHashesWithBalance() + const { data: fromAddresses } = useFetchAddressesHashesWithBalance(data.tokenId) const [fromAddressHash, setFromAddressHash] = useState(data.fromAddress.hash) const [toAddress, setToAddress] = useStateWithError(data?.toAddress ?? '') diff --git a/apps/desktop-wallet/src/features/send/sendTypes.ts b/apps/desktop-wallet/src/features/send/sendTypes.ts index 46fd757a3..cf35489a9 100644 --- a/apps/desktop-wallet/src/features/send/sendTypes.ts +++ b/apps/desktop-wallet/src/features/send/sendTypes.ts @@ -2,6 +2,7 @@ import { AssetAmount } from '@alephium/shared' import { node } from '@alephium/web3' import { Address } from '@/types/addresses' +import { TokenId } from '@/types/tokens' export interface TransferTxData { fromAddress: Address @@ -11,6 +12,7 @@ export interface TransferTxData { gasAmount?: number gasPrice?: string lockTime?: Date + tokenId?: TokenId } export interface CallContractTxData { diff --git a/apps/desktop-wallet/src/hooks/useAddresses.ts b/apps/desktop-wallet/src/hooks/useAddresses.ts index afdf04add..3d3351fba 100644 --- a/apps/desktop-wallet/src/hooks/useAddresses.ts +++ b/apps/desktop-wallet/src/hooks/useAddresses.ts @@ -1,13 +1,16 @@ +import { ALPH } from '@alephium/token-list' import { orderBy } from 'lodash' import { useMemo } from 'react' import { SkipProp } from '@/api/apiDataHooks/apiDataHooksTypes' import useFetchLatestTransactionOfEachAddress from '@/api/apiDataHooks/wallet/useFetchLatestTransactionOfEachAddress' import useFetchWalletBalancesAlphByAddress from '@/api/apiDataHooks/wallet/useFetchWalletBalancesAlphByAddress' +import useFetchWalletBalancesTokensByAddress from '@/api/apiDataHooks/wallet/useFetchWalletBalancesTokensByAddress' import { useAppSelector } from '@/hooks/redux' import { useUnsortedAddressesHashes } from '@/hooks/useUnsortedAddresses' import { selectDefaultAddress } from '@/storage/addresses/addressesSelectors' import { selectCurrentlyOnlineNetworkId } from '@/storage/network/networkSelectors' +import { TokenId } from '@/types/tokens' export const useFetchSortedAddressesHashes = (props?: SkipProp) => { const isNetworkOffline = useAppSelector(selectCurrentlyOnlineNetworkId) === undefined @@ -40,24 +43,30 @@ export const useFetchSortedAddressesHashesWithLatestTx = (props?: SkipProp) => { } } -export const useFetchAddressesHashesWithBalance = () => { +export const useFetchAddressesHashesWithBalance = (tokenId?: TokenId) => { const isNetworkOffline = useAppSelector(selectCurrentlyOnlineNetworkId) === undefined const allAddressHashes = useUnsortedAddressesHashes() - const { data: addressesAlphBalances, isLoading } = useFetchWalletBalancesAlphByAddress() + const { data: addressesAlphBalances, isLoading: isLoadingAlphBalances } = useFetchWalletBalancesAlphByAddress() + const { data: addressesTokenBalances, isLoading: isLoadingTokenBalances } = useFetchWalletBalancesTokensByAddress() const filteredAddressHashes = useMemo( () => isNetworkOffline ? allAddressHashes - : allAddressHashes.filter( - (addressHash) => - addressesAlphBalances[addressHash] && addressesAlphBalances[addressHash].totalBalance !== '0' - ), - [addressesAlphBalances, allAddressHashes, isNetworkOffline] + : allAddressHashes.filter((addressHash) => { + if (!tokenId || tokenId === ALPH.id) { + return addressesAlphBalances[addressHash] && addressesAlphBalances[addressHash].totalBalance !== '0' + } + + const addressTokenBalance = addressesTokenBalances[addressHash]?.find(({ id }) => id === tokenId) + + return addressTokenBalance && addressTokenBalance.totalBalance !== '0' + }), + [addressesAlphBalances, addressesTokenBalances, allAddressHashes, isNetworkOffline, tokenId] ) return { data: filteredAddressHashes, - isLoading + isLoading: isLoadingAlphBalances || isLoadingTokenBalances } } diff --git a/apps/desktop-wallet/src/modals/tokenDetails/TokenDetailsModal.tsx b/apps/desktop-wallet/src/modals/tokenDetails/TokenDetailsModal.tsx index 8dfa6a40c..199d707b7 100644 --- a/apps/desktop-wallet/src/modals/tokenDetails/TokenDetailsModal.tsx +++ b/apps/desktop-wallet/src/modals/tokenDetails/TokenDetailsModal.tsx @@ -2,6 +2,7 @@ import { useTranslation } from 'react-i18next' import styled from 'styled-components' import AnimatedBackground from '@/components/AnimatedBackground' +import { ShortcutButtonsGroupToken } from '@/components/Buttons/ShortcutButtons' import LabeledWorthOverview from '@/components/LabeledWorthOverview' import withModal from '@/features/modals/withModal' import SideModal from '@/modals/SideModal' @@ -19,6 +20,7 @@ const TokenDetailsModal = withModal(({ id, tokenId }) => + ) From 205f33722c1c6bb3b04e19852c3e1981e4c1b302 Mon Sep 17 00:00:00 2001 From: Ilias Trichopoulos Date: Fri, 7 Feb 2025 15:36:32 +0100 Subject: [PATCH 02/17] Initialize amounts with selected token --- .../send/sendModals/transfer/AddressesTxModalContent.tsx | 3 ++- .../send/sendModals/transfer/BuildTxModalContent.tsx | 6 +++--- apps/desktop-wallet/src/features/send/sendTypes.ts | 5 ++++- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/apps/desktop-wallet/src/features/send/sendModals/transfer/AddressesTxModalContent.tsx b/apps/desktop-wallet/src/features/send/sendModals/transfer/AddressesTxModalContent.tsx index 4f4324799..0e363a771 100644 --- a/apps/desktop-wallet/src/features/send/sendModals/transfer/AddressesTxModalContent.tsx +++ b/apps/desktop-wallet/src/features/send/sendModals/transfer/AddressesTxModalContent.tsx @@ -61,7 +61,8 @@ const TransferAddressesTxModalContent = ({ data, onSubmit, onCancel }: TransferA onClick={() => onSubmit({ fromAddress, - toAddress: toAddress.value + toAddress: toAddress.value, + tokenId: data.tokenId }) } disabled={!isSubmitButtonActive} diff --git a/apps/desktop-wallet/src/features/send/sendModals/transfer/BuildTxModalContent.tsx b/apps/desktop-wallet/src/features/send/sendModals/transfer/BuildTxModalContent.tsx index d12cfc6c0..b1075b728 100644 --- a/apps/desktop-wallet/src/features/send/sendModals/transfer/BuildTxModalContent.tsx +++ b/apps/desktop-wallet/src/features/send/sendModals/transfer/BuildTxModalContent.tsx @@ -22,8 +22,6 @@ export interface TransferBuildTxModalContentProps { onSubmit: (data: TransferTxData) => void } -const defaultAssetAmounts = [{ id: ALPH.id }] - const TransferBuildTxModalContent = ({ data, onSubmit }: TransferBuildTxModalContentProps) => { const { t } = useTranslation() const { @@ -37,7 +35,9 @@ const TransferBuildTxModalContent = ({ data, onSubmit }: TransferBuildTxModalCon } = useGasSettings(data?.gasAmount?.toString(), data?.gasPrice) const [lockTime, setLockTime] = useState(data.lockTime) - const [assetAmounts, setAssetAmounts] = useState(data.assetAmounts || defaultAssetAmounts) + const [assetAmounts, setAssetAmounts] = useState( + data.assetAmounts || [{ id: data.tokenId ?? ALPH.id }] + ) const { fromAddress, toAddress } = data diff --git a/apps/desktop-wallet/src/features/send/sendTypes.ts b/apps/desktop-wallet/src/features/send/sendTypes.ts index cf35489a9..a5f196063 100644 --- a/apps/desktop-wallet/src/features/send/sendTypes.ts +++ b/apps/desktop-wallet/src/features/send/sendTypes.ts @@ -40,7 +40,10 @@ export type TransferTxModalData = PartialTxData export type CallContractTxModalData = PartialTxData export type DeployContractTxModalData = PartialTxData -export type TransferAddressesTxModalOnSubmitData = PartialTxData +export type TransferAddressesTxModalOnSubmitData = PartialTxData< + TransferTxData, + 'fromAddress' | 'toAddress' | 'tokenId' +> export type AddressesTxModalData = | TransferAddressesTxModalOnSubmitData From c8ed4741e697d55ba0e979f9ed61dd56c0b4d3ae Mon Sep 17 00:00:00 2001 From: Ilias Trichopoulos Date: Fri, 7 Feb 2025 16:50:36 +0100 Subject: [PATCH 03/17] Address list in token details modal --- .../locales/en-US/translation.json | 2 +- .../src/components/amounts/FTAmounts.tsx | 19 +++++--- .../assetsLists/TokensBalancesHeader.tsx | 2 +- .../AddressTokenBalancesRow.tsx | 4 +- .../tokenBalanceRow/FTAmountCells.tsx | 45 ++++++++++++------- .../tokenBalanceRow/FTWorthCell.tsx | 32 +++++++++++-- .../WalletTokenBalancesRow.tsx | 4 +- .../modals/tokenDetails/TokenAddressList.tsx | 37 +++++++++++++++ .../modals/tokenDetails/TokenDetailsModal.tsx | 2 + .../addressListRow/AddressListRow.tsx | 28 +++++++++--- 10 files changed, 136 insertions(+), 39 deletions(-) create mode 100644 apps/desktop-wallet/src/modals/tokenDetails/TokenAddressList.tsx diff --git a/apps/desktop-wallet/locales/en-US/translation.json b/apps/desktop-wallet/locales/en-US/translation.json index 3b7dc4fa2..6d96adfc2 100644 --- a/apps/desktop-wallet/locales/en-US/translation.json +++ b/apps/desktop-wallet/locales/en-US/translation.json @@ -495,7 +495,7 @@ "You can now complete your purchase in the dedicated window!": "You can now complete your purchase in the dedicated window!", "Token": "Token", "Price": "Price", - "Value": "Value", + "Worth": "Worth", "Invalid mnemonic. Please double check your words.": "Invalid mnemonic. Please double check your words.", "Incorrect word. Please try again.": "Incorrect word. Please try again.", "Select the correct word for word number <1>{{ number }} of 24.": "Select the correct word for word number <1>{{ number }} of 24.", diff --git a/apps/desktop-wallet/src/components/amounts/FTAmounts.tsx b/apps/desktop-wallet/src/components/amounts/FTAmounts.tsx index d21a09c37..990b99024 100644 --- a/apps/desktop-wallet/src/components/amounts/FTAmounts.tsx +++ b/apps/desktop-wallet/src/components/amounts/FTAmounts.tsx @@ -1,20 +1,25 @@ import { useTranslation } from 'react-i18next' import styled, { useTheme } from 'styled-components' -import useFetchWalletSingleTokenBalances from '@/api/apiDataHooks/wallet/useFetchWalletSingleTokenBalances' import Amount, { TokenAmountProps } from '@/components/Amount' +import { TokenId } from '@/types/tokens' -const FTAmounts = (props: Omit) => { - const { data: balances, isLoading } = useFetchWalletSingleTokenBalances({ tokenId: props.tokenId }) +export interface FTAmountsBaseProp { + isLoading: boolean + tokenId: TokenId + totalBalance?: bigint + availableBalance?: bigint +} + +type FTAmountsProps = FTAmountsBaseProp & Omit + +const FTAmounts = ({ totalBalance, availableBalance, isLoading, ...props }: FTAmountsProps) => { const { t } = useTranslation() const theme = useTheme() - const totalBalance = BigInt(balances.totalBalance) - const availableBalance = BigInt(balances.availableBalance) - return ( <> - {totalBalance && } + {totalBalance !== undefined && } {availableBalance !== totalBalance && availableBalance !== undefined && ( diff --git a/apps/desktop-wallet/src/features/assetsLists/TokensBalancesHeader.tsx b/apps/desktop-wallet/src/features/assetsLists/TokensBalancesHeader.tsx index 4e65ba457..d8d2077c8 100644 --- a/apps/desktop-wallet/src/features/assetsLists/TokensBalancesHeader.tsx +++ b/apps/desktop-wallet/src/features/assetsLists/TokensBalancesHeader.tsx @@ -27,7 +27,7 @@ const TokensBalancesHeader = ({ showAllocation }: TokensBalancesHeaderProps) => {t('Amount')} - {t('Value')} + {t('Worth')} ) diff --git a/apps/desktop-wallet/src/features/assetsLists/tokenBalanceRow/AddressTokenBalancesRow.tsx b/apps/desktop-wallet/src/features/assetsLists/tokenBalanceRow/AddressTokenBalancesRow.tsx index a3cf64c8a..baef861d7 100644 --- a/apps/desktop-wallet/src/features/assetsLists/tokenBalanceRow/AddressTokenBalancesRow.tsx +++ b/apps/desktop-wallet/src/features/assetsLists/tokenBalanceRow/AddressTokenBalancesRow.tsx @@ -3,7 +3,7 @@ import styled from 'styled-components' import { TableCell } from '@/components/Table' import { FTAddressAmountCell } from '@/features/assetsLists/tokenBalanceRow/FTAmountCells' import FTPriceCell from '@/features/assetsLists/tokenBalanceRow/FTPriceCell' -import FTWorth from '@/features/assetsLists/tokenBalanceRow/FTWorthCell' +import { FTAddressWorthCell } from '@/features/assetsLists/tokenBalanceRow/FTWorthCell' import { FTNameCell, NSTNameCell } from '@/features/assetsLists/tokenBalanceRow/NameCells' import TokenBalancesRow from '@/features/assetsLists/tokenBalanceRow/TokenBalancesRow' import TokenLogo from '@/features/assetsLists/tokenBalanceRow/TokenLogo' @@ -16,7 +16,7 @@ export const AddressFTBalancesRow = ({ tokenId, addressHash }: AddressTokenBalan - + ) diff --git a/apps/desktop-wallet/src/features/assetsLists/tokenBalanceRow/FTAmountCells.tsx b/apps/desktop-wallet/src/features/assetsLists/tokenBalanceRow/FTAmountCells.tsx index 28057ad2d..d1552e722 100644 --- a/apps/desktop-wallet/src/features/assetsLists/tokenBalanceRow/FTAmountCells.tsx +++ b/apps/desktop-wallet/src/features/assetsLists/tokenBalanceRow/FTAmountCells.tsx @@ -22,7 +22,7 @@ import styled from 'styled-components' import useFetchAddressSingleTokenBalances from '@/api/apiDataHooks/address/useFetchAddressSingleTokenBalances' import useFetchWalletSingleTokenBalances from '@/api/apiDataHooks/wallet/useFetchWalletSingleTokenBalances' -import FTAmounts from '@/components/amounts/FTAmounts' +import FTAmounts, { FTAmountsBaseProp } from '@/components/amounts/FTAmounts' import SkeletonLoader from '@/components/SkeletonLoader' import { TableCell } from '@/components/Table' import { TokenId } from '@/types/tokens' @@ -33,29 +33,44 @@ interface FTAddressAmountCellProps { } export const FTAddressAmountCell = ({ tokenId, addressHash }: FTAddressAmountCellProps) => { - const { isLoading } = useFetchAddressSingleTokenBalances({ addressHash: addressHash, tokenId }) - - return + const { data: tokenBalances, isLoading } = useFetchAddressSingleTokenBalances({ addressHash, tokenId }) + + const totalBalance = tokenBalances?.totalBalance ? BigInt(tokenBalances.totalBalance) : undefined + const availableBalance = tokenBalances?.availableBalance ? BigInt(tokenBalances.availableBalance) : undefined + + return ( + + ) } export const FTWalletAmountCell = ({ tokenId }: Omit) => { - const { isLoading } = useFetchWalletSingleTokenBalances({ tokenId }) - - return -} - -interface FTAmountCellProps { - tokenId: TokenId - isLoading: boolean + const { data: tokenBalances, isLoading } = useFetchWalletSingleTokenBalances({ tokenId }) + + const totalBalance = tokenBalances?.totalBalance ? BigInt(tokenBalances.totalBalance) : undefined + const availableBalance = tokenBalances?.availableBalance ? BigInt(tokenBalances.availableBalance) : undefined + + return ( + + ) } -const FTAmountCell = ({ tokenId, isLoading }: FTAmountCellProps) => ( +const FTAmountCell = (props: FTAmountsBaseProp) => ( - {isLoading ? ( + {props.isLoading ? ( ) : ( - + )} diff --git a/apps/desktop-wallet/src/features/assetsLists/tokenBalanceRow/FTWorthCell.tsx b/apps/desktop-wallet/src/features/assetsLists/tokenBalanceRow/FTWorthCell.tsx index 1d989bcf6..34323b049 100644 --- a/apps/desktop-wallet/src/features/assetsLists/tokenBalanceRow/FTWorthCell.tsx +++ b/apps/desktop-wallet/src/features/assetsLists/tokenBalanceRow/FTWorthCell.tsx @@ -1,12 +1,38 @@ +import useFetchAddressSingleTokenBalances from '@/api/apiDataHooks/address/useFetchAddressSingleTokenBalances' import useFetchTokenPrices from '@/api/apiDataHooks/market/useFetchTokenPrices' import useFetchToken, { isFT } from '@/api/apiDataHooks/token/useFetchToken' import useFetchWalletSingleTokenBalances from '@/api/apiDataHooks/wallet/useFetchWalletSingleTokenBalances' import FTWorthAmount from '@/components/amounts/FTWorthAmount' import SkeletonLoader from '@/components/SkeletonLoader' import { TableCell } from '@/components/Table' -import { TokenBalancesRowBaseProps } from '@/features/assetsLists/tokenBalanceRow/types' +import { AddressTokenBalancesRowProps, TokenBalancesRowBaseProps } from '@/features/assetsLists/tokenBalanceRow/types' -const FTWorthCell = ({ tokenId }: TokenBalancesRowBaseProps) => { +export const FTAddressWorthCell = ({ tokenId, addressHash }: AddressTokenBalancesRowProps) => { + const { data: totalBalance, isLoading: isLoadingBalance } = useFetchAddressSingleTokenBalances({ + tokenId, + addressHash + }) + const { data: token } = useFetchToken(tokenId) + const { isLoading: isLoadingTokenPrices } = useFetchTokenPrices() + + if (!isFT(token)) return null + + return ( + + {isLoadingBalance || isLoadingTokenPrices ? ( + + ) : ( + + )} + + ) +} + +export const FTWalletWorthCell = ({ tokenId }: TokenBalancesRowBaseProps) => { const { data: totalBalance, isLoading: isLoadingBalance } = useFetchWalletSingleTokenBalances({ tokenId }) @@ -29,5 +55,3 @@ const FTWorthCell = ({ tokenId }: TokenBalancesRowBaseProps) => { ) } - -export default FTWorthCell diff --git a/apps/desktop-wallet/src/features/assetsLists/tokenBalanceRow/WalletTokenBalancesRow.tsx b/apps/desktop-wallet/src/features/assetsLists/tokenBalanceRow/WalletTokenBalancesRow.tsx index ffc2eb1e2..312e3f6e9 100644 --- a/apps/desktop-wallet/src/features/assetsLists/tokenBalanceRow/WalletTokenBalancesRow.tsx +++ b/apps/desktop-wallet/src/features/assetsLists/tokenBalanceRow/WalletTokenBalancesRow.tsx @@ -2,7 +2,7 @@ import { TableCell } from '@/components/Table' import FTAllocationCell from '@/features/assetsLists/tokenBalanceRow/FTAllocationCell' import { FTWalletAmountCell } from '@/features/assetsLists/tokenBalanceRow/FTAmountCells' import FTPriceCell from '@/features/assetsLists/tokenBalanceRow/FTPriceCell' -import FTWorthCell from '@/features/assetsLists/tokenBalanceRow/FTWorthCell' +import { FTWalletWorthCell } from '@/features/assetsLists/tokenBalanceRow/FTWorthCell' import { FTNameCell, NSTNameCell } from '@/features/assetsLists/tokenBalanceRow/NameCells' import TokenBalancesRow from '@/features/assetsLists/tokenBalanceRow/TokenBalancesRow' import TokenLogo from '@/features/assetsLists/tokenBalanceRow/TokenLogo' @@ -17,7 +17,7 @@ export const WalletFTBalancesRow = ({ tokenId }: TokenBalancesRowBaseProps) => ( - + ) diff --git a/apps/desktop-wallet/src/modals/tokenDetails/TokenAddressList.tsx b/apps/desktop-wallet/src/modals/tokenDetails/TokenAddressList.tsx new file mode 100644 index 000000000..ff45e5608 --- /dev/null +++ b/apps/desktop-wallet/src/modals/tokenDetails/TokenAddressList.tsx @@ -0,0 +1,37 @@ +import styled from 'styled-components' + +import { useFetchAddressesHashesWithBalance } from '@/hooks/useAddresses' +import { TokenDetailsModalProps } from '@/modals/tokenDetails/tokeDetailsTypes' +import AddressListRow from '@/pages/unlockedWallet/addressesPage/addressListRow/AddressListRow' + +const TokenAddressesList = ({ tokenId }: TokenDetailsModalProps) => { + const { data: addresses } = useFetchAddressesHashesWithBalance(tokenId) + + if (!addresses) return null + + return ( + + + {addresses.map((addressHash) => ( + + ))} + + + ) +} + +export default TokenAddressesList + +// TODO: DRY +const TableGrid = styled.div` + flex: 1; + display: flex; + flex-direction: column; + border-radius: var(--radius-big); +` + +// TODO: DRY +const TableGridContent = styled.div` + display: flex; + flex-direction: column; +` diff --git a/apps/desktop-wallet/src/modals/tokenDetails/TokenDetailsModal.tsx b/apps/desktop-wallet/src/modals/tokenDetails/TokenDetailsModal.tsx index 199d707b7..6f7efe117 100644 --- a/apps/desktop-wallet/src/modals/tokenDetails/TokenDetailsModal.tsx +++ b/apps/desktop-wallet/src/modals/tokenDetails/TokenDetailsModal.tsx @@ -7,6 +7,7 @@ import LabeledWorthOverview from '@/components/LabeledWorthOverview' import withModal from '@/features/modals/withModal' import SideModal from '@/modals/SideModal' import { TokenDetailsModalProps } from '@/modals/tokenDetails/tokeDetailsTypes' +import TokenAddressesList from '@/modals/tokenDetails/TokenAddressList' import TokenBalances from '@/modals/tokenDetails/TokenBalances' import TokenDetailsModalHeader from '@/modals/tokenDetails/TokenDetailsModalHeader' @@ -21,6 +22,7 @@ const TokenDetailsModal = withModal(({ id, tokenId }) => + ) diff --git a/apps/desktop-wallet/src/pages/unlockedWallet/addressesPage/addressListRow/AddressListRow.tsx b/apps/desktop-wallet/src/pages/unlockedWallet/addressesPage/addressListRow/AddressListRow.tsx index e5613f570..1b757f7db 100644 --- a/apps/desktop-wallet/src/pages/unlockedWallet/addressesPage/addressListRow/AddressListRow.tsx +++ b/apps/desktop-wallet/src/pages/unlockedWallet/addressesPage/addressListRow/AddressListRow.tsx @@ -5,19 +5,23 @@ import styled from 'styled-components' import AddressBadge from '@/components/AddressBadge' import AddressColorIndicator from '@/components/AddressColorIndicator' import AddressTokensBadgesList from '@/features/assetsLists/AddressTokensBadgesList' +import { FTAddressAmountCell } from '@/features/assetsLists/tokenBalanceRow/FTAmountCells' +import { FTAddressWorthCell } from '@/features/assetsLists/tokenBalanceRow/FTWorthCell' import { openModal } from '@/features/modals/modalActions' import { useAppDispatch } from '@/hooks/redux' import AddressGroup from '@/pages/unlockedWallet/addressesPage/addressListRow/AddressGroup' import AddressLastActivity from '@/pages/unlockedWallet/addressesPage/addressListRow/AddressLastActivity' import AddressWorth from '@/pages/unlockedWallet/addressesPage/addressListRow/AddressWorth' +import { TokenId } from '@/types/tokens' import { onEnterOrSpace } from '@/utils/misc' interface AddressListRowProps { addressHash: AddressHash className?: string + tokenId?: TokenId } -const AddressListRow = memo(({ addressHash, className }: AddressListRowProps) => { +const AddressListRow = memo(({ addressHash, tokenId, className }: AddressListRowProps) => { const dispatch = useAppDispatch() const openAddressDetailsModal = () => dispatch(openModal({ name: 'AddressDetailsModal', props: { addressHash } })) @@ -45,12 +49,22 @@ const AddressListRow = memo(({ addressHash, className }: AddressListRowProps) => - - - - - - + + {tokenId ? ( + + ) : ( + + + + )} + + {tokenId ? ( + + ) : ( + + + + )} ) }) From 4d02c23af3b61b75fcc237b72b12f2b04d7278e4 Mon Sep 17 00:00:00 2001 From: Ilias Trichopoulos Date: Fri, 7 Feb 2025 17:00:03 +0100 Subject: [PATCH 04/17] Fix type errors --- .../src/modals/tokenDetails/TokenBalances.tsx | 26 ++++++++++++++----- 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/apps/desktop-wallet/src/modals/tokenDetails/TokenBalances.tsx b/apps/desktop-wallet/src/modals/tokenDetails/TokenBalances.tsx index f194ee1d8..8142232fe 100644 --- a/apps/desktop-wallet/src/modals/tokenDetails/TokenBalances.tsx +++ b/apps/desktop-wallet/src/modals/tokenDetails/TokenBalances.tsx @@ -7,12 +7,26 @@ import FTAmounts from '@/components/amounts/FTAmounts' import FTWorthAmount from '@/components/amounts/FTWorthAmount' import { TokenDetailsModalProps } from '@/modals/tokenDetails/tokeDetailsTypes' -const TokenBalances = ({ tokenId }: TokenDetailsModalProps) => ( - <> - - - -) +const TokenBalances = ({ tokenId }: TokenDetailsModalProps) => { + const { data: tokenBalances, isLoading } = useFetchWalletSingleTokenBalances({ + tokenId + }) + + const totalBalance = tokenBalances?.totalBalance ? BigInt(tokenBalances.totalBalance) : undefined + const availableBalance = tokenBalances?.availableBalance ? BigInt(tokenBalances.availableBalance) : undefined + + return ( + <> + + + + ) +} export default TokenBalances From 0b104b5429d4f2e675076b7827fa81617ef6b72c Mon Sep 17 00:00:00 2001 From: Ilias Trichopoulos Date: Mon, 10 Feb 2025 16:10:00 +0100 Subject: [PATCH 05/17] Cleanup --- apps/desktop-wallet/electron/electron-env.ts | 2 +- .../locales/en-US/translation.json | 1 - apps/desktop-wallet/src/components/Box.tsx | 2 +- .../src/components/DeltaPercentage.tsx | 54 ------------------ .../src/components/LabeledWorthOverview.tsx | 18 ------ .../src/components/Paragraph.tsx | 2 +- .../src/components/WalletNameButton.tsx | 17 ------ .../tokenBalanceRow/FTAllocationCell.tsx | 18 ------ .../tokenBalanceRow/FTAmountCells.tsx | 18 ------ .../tokenBalanceRow/FTPriceCell.tsx | 18 ------ .../balancesOverview/TotalAlphBalance.tsx | 57 ------------------- .../src/features/buy/BuyModal.tsx | 24 +------- .../src/features/settings/SettingsButton.tsx | 1 + .../src/features/snackbar/SnackbarBox.tsx | 6 +- .../transactionRow/TimestampCell.tsx | 18 ------ packages/shared/src/store/prices/index.ts | 1 - .../shared/src/store/prices/pricesActions.ts | 52 +---------------- .../shared/src/store/prices/pricesAdapter.ts | 7 +-- .../src/store/prices/pricesHistorySlice.ts | 45 --------------- .../src/store/prices/pricesSelectors.ts | 5 +- packages/shared/src/store/store.ts | 5 +- packages/shared/src/types/price.ts | 4 -- 22 files changed, 13 insertions(+), 362 deletions(-) delete mode 100644 apps/desktop-wallet/src/components/DeltaPercentage.tsx delete mode 100644 apps/desktop-wallet/src/features/balancesOverview/TotalAlphBalance.tsx delete mode 100644 packages/shared/src/store/prices/pricesHistorySlice.ts diff --git a/apps/desktop-wallet/electron/electron-env.ts b/apps/desktop-wallet/electron/electron-env.ts index a45e3afd2..1c5899306 100644 --- a/apps/desktop-wallet/electron/electron-env.ts +++ b/apps/desktop-wallet/electron/electron-env.ts @@ -33,7 +33,7 @@ declare global { getSystemRegion: () => Promise setProxySettings: (proxySettings: ProxySettings) => Promise openOnRampServiceWindow: ({ url, targetLocation }: { url: string; targetLocation: string }) => void - onOnRampTargetLocationReached: (callback: () => void) => () => Electron.IpcRenderer + onOnRampTargetLocationReached: (callback: () => void) => () => void restart: () => void } window: { diff --git a/apps/desktop-wallet/locales/en-US/translation.json b/apps/desktop-wallet/locales/en-US/translation.json index 6d96adfc2..03df53099 100644 --- a/apps/desktop-wallet/locales/en-US/translation.json +++ b/apps/desktop-wallet/locales/en-US/translation.json @@ -9,7 +9,6 @@ "Address NFTs": "Address NFTs", "Address options": "Address options", "Address tokens": "Address tokens", - "Address transactions": "Address transactions", "Addresses": "Addresses", "Addresses & contacts": "Addresses & contacts", "Advanced feature": "Advanced feature", diff --git a/apps/desktop-wallet/src/components/Box.tsx b/apps/desktop-wallet/src/components/Box.tsx index 58eafeb91..672df81f3 100644 --- a/apps/desktop-wallet/src/components/Box.tsx +++ b/apps/desktop-wallet/src/components/Box.tsx @@ -1,7 +1,7 @@ import { motion } from 'framer-motion' import styled from 'styled-components' -const Box = styled(motion.div)<{ secondary?: boolean }>` +const Box = styled(motion.div)` border-radius: var(--radius-huge); width: 100%; ` diff --git a/apps/desktop-wallet/src/components/DeltaPercentage.tsx b/apps/desktop-wallet/src/components/DeltaPercentage.tsx deleted file mode 100644 index a8a7bce5e..000000000 --- a/apps/desktop-wallet/src/components/DeltaPercentage.tsx +++ /dev/null @@ -1,54 +0,0 @@ -import { ArrowDownRight, ArrowUpRight } from 'lucide-react' -import { useTranslation } from 'react-i18next' -import styled, { css, useTheme } from 'styled-components' - -import Badge from '@/components/Badge' -import { useAppSelector } from '@/hooks/redux' - -interface DeltaPercentageProps { - initialValue: number - latestValue: number - className?: string -} - -const DeltaPercentage = ({ initialValue, latestValue, className }: DeltaPercentageProps) => { - const theme = useTheme() - const { t } = useTranslation() - const discreetMode = useAppSelector((state) => state.settings.discreetMode) - - const percentage = Math.round(((latestValue - initialValue) / initialValue) * 10000) / 100 - const isUp = percentage >= 0 - const color = discreetMode ? theme.font.primary : isUp ? theme.global.valid : theme.global.alert - - const DirectionArrow = percentage >= 0 ? ArrowUpRight : ArrowDownRight - - return ( - - - {percentage}% - - ) -} - -export default DeltaPercentage - -const DeltaPercentageStyled = styled(Badge)<{ discreetMode: boolean }>` - display: flex; - align-items: center; - height: 24px; - - ${({ discreetMode }) => - discreetMode && - css` - filter: blur(10px); - overflow: hidden; - cursor: pointer; - `} -` diff --git a/apps/desktop-wallet/src/components/LabeledWorthOverview.tsx b/apps/desktop-wallet/src/components/LabeledWorthOverview.tsx index 5ad91bbf4..37dd8a2c1 100644 --- a/apps/desktop-wallet/src/components/LabeledWorthOverview.tsx +++ b/apps/desktop-wallet/src/components/LabeledWorthOverview.tsx @@ -1,21 +1,3 @@ -/* -Copyright 2018 - 2024 The Alephium Authors -This file is part of the alephium project. - -The library is free software: you can redistribute it and/or modify -it under the terms of the GNU Lesser General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -The library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License -along with the library. If not, see . -*/ - import { ReactNode } from 'react' import styled from 'styled-components' diff --git a/apps/desktop-wallet/src/components/Paragraph.tsx b/apps/desktop-wallet/src/components/Paragraph.tsx index 9251b471d..e0015a767 100644 --- a/apps/desktop-wallet/src/components/Paragraph.tsx +++ b/apps/desktop-wallet/src/components/Paragraph.tsx @@ -8,7 +8,7 @@ interface ParagraphProps { children?: ReactNode } -const Paragraph: FC = ({ centered, secondary, children, className }: ParagraphProps) => ( +const Paragraph = ({ centered, secondary, children, className }: ParagraphProps) => ( {children} diff --git a/apps/desktop-wallet/src/components/WalletNameButton.tsx b/apps/desktop-wallet/src/components/WalletNameButton.tsx index 1f0543855..0d14ac0bc 100644 --- a/apps/desktop-wallet/src/components/WalletNameButton.tsx +++ b/apps/desktop-wallet/src/components/WalletNameButton.tsx @@ -1,20 +1,3 @@ -/* -Copyright 2018 - 2024 The Alephium Authors -This file is part of the alephium project. - -The library is free software: you can redistribute it and/or modify -it under the terms of the GNU Lesser General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -The library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License -along with the library. If not, see . -*/ import styled from 'styled-components' import { openModal } from '@/features/modals/modalActions' diff --git a/apps/desktop-wallet/src/features/assetsLists/tokenBalanceRow/FTAllocationCell.tsx b/apps/desktop-wallet/src/features/assetsLists/tokenBalanceRow/FTAllocationCell.tsx index fea5e03fe..0564eeb12 100644 --- a/apps/desktop-wallet/src/features/assetsLists/tokenBalanceRow/FTAllocationCell.tsx +++ b/apps/desktop-wallet/src/features/assetsLists/tokenBalanceRow/FTAllocationCell.tsx @@ -1,21 +1,3 @@ -/* -Copyright 2018 - 2024 The Alephium Authors -This file is part of the alephium project. - -The library is free software: you can redistribute it and/or modify -it under the terms of the GNU Lesser General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -The library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License -along with the library. If not, see . -*/ - import { calculateAmountWorth } from '@alephium/shared' import styled from 'styled-components' diff --git a/apps/desktop-wallet/src/features/assetsLists/tokenBalanceRow/FTAmountCells.tsx b/apps/desktop-wallet/src/features/assetsLists/tokenBalanceRow/FTAmountCells.tsx index d1552e722..c33979f27 100644 --- a/apps/desktop-wallet/src/features/assetsLists/tokenBalanceRow/FTAmountCells.tsx +++ b/apps/desktop-wallet/src/features/assetsLists/tokenBalanceRow/FTAmountCells.tsx @@ -1,21 +1,3 @@ -/* -Copyright 2018 - 2024 The Alephium Authors -This file is part of the alephium project. - -The library is free software: you can redistribute it and/or modify -it under the terms of the GNU Lesser General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -The library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License -along with the library. If not, see . -*/ - import { AddressHash } from '@alephium/shared' import { useTranslation } from 'react-i18next' import styled from 'styled-components' diff --git a/apps/desktop-wallet/src/features/assetsLists/tokenBalanceRow/FTPriceCell.tsx b/apps/desktop-wallet/src/features/assetsLists/tokenBalanceRow/FTPriceCell.tsx index 053c58afa..709e43213 100644 --- a/apps/desktop-wallet/src/features/assetsLists/tokenBalanceRow/FTPriceCell.tsx +++ b/apps/desktop-wallet/src/features/assetsLists/tokenBalanceRow/FTPriceCell.tsx @@ -1,21 +1,3 @@ -/* -Copyright 2018 - 2024 The Alephium Authors -This file is part of the alephium project. - -The library is free software: you can redistribute it and/or modify -it under the terms of the GNU Lesser General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -The library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License -along with the library. If not, see . -*/ - import { useTheme } from 'styled-components' import { useFetchTokenPrice } from '@/api/apiDataHooks/market/useFetchTokenPrices' diff --git a/apps/desktop-wallet/src/features/balancesOverview/TotalAlphBalance.tsx b/apps/desktop-wallet/src/features/balancesOverview/TotalAlphBalance.tsx deleted file mode 100644 index 441328f7d..000000000 --- a/apps/desktop-wallet/src/features/balancesOverview/TotalAlphBalance.tsx +++ /dev/null @@ -1,57 +0,0 @@ -import { ALPH } from '@alephium/token-list' -import { useTranslation } from 'react-i18next' -import styled from 'styled-components' - -import useFetchWalletBalancesAlph from '@/api/apiDataHooks/wallet/useFetchWalletBalancesAlph' -import Amount from '@/components/Amount' - -interface TotalAlphBalanceProps { - type: 'available' | 'locked' - className?: string -} - -const TotalAlphBalance = ({ className, type }: TotalAlphBalanceProps) => { - const { t } = useTranslation() - - const available = type === 'available' - - return ( -
- - {t(available ? 'Available' : 'Locked')} - - {available ? : } -
- ) -} - -const AvailableAlphAmount = () => { - const { data, isLoading } = useFetchWalletBalancesAlph() - - const value = data?.availableBalance ? BigInt(data.availableBalance) : undefined - - return -} - -const LockedAlphAmount = () => { - const { data, isLoading } = useFetchWalletBalancesAlph() - - const value = data?.lockedBalance ? BigInt(data.lockedBalance) : undefined - - return -} - -export default TotalAlphBalance - -const BalanceLabel = styled.label` - color: ${({ theme }) => theme.font.tertiary}; - font-size: 12px; - display: block; - margin-bottom: 3px; -` - -const AmountStyled = styled(Amount)` - color: ${({ theme }) => theme.font.primary}; - font-size: 21px; - font-weight: var(--fontWeight-semiBold); -` diff --git a/apps/desktop-wallet/src/features/buy/BuyModal.tsx b/apps/desktop-wallet/src/features/buy/BuyModal.tsx index ac5af260e..06de53c82 100644 --- a/apps/desktop-wallet/src/features/buy/BuyModal.tsx +++ b/apps/desktop-wallet/src/features/buy/BuyModal.tsx @@ -1,21 +1,3 @@ -/* -Copyright 2018 - 2024 The Alephium Authors -This file is part of the alephium project. - -The library is free software: you can redistribute it and/or modify -it under the terms of the GNU Lesser General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -The library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License -along with the library. If not, see . -*/ - import { AddressHash } from '@alephium/shared' import { memo, useEffect, useState } from 'react' import { Trans, useTranslation } from 'react-i18next' @@ -53,15 +35,13 @@ const BuyModal = memo(({ id, addressHash }: ModalBaseProp & BuyModalProps) => { } useEffect(() => { - const listner = window.electron?.app.onOnRampTargetLocationReached(() => { + const removeListener = window.electron?.app.onOnRampTargetLocationReached(() => { showToast({ text: t('Purchase done!'), type: 'success', duration: 'short' }) navigate('/wallet/activity') dispatch(closeModal({ id })) }) - return () => { - listner?.() - } + return removeListener }, [dispatch, id, navigate, t]) return ( diff --git a/apps/desktop-wallet/src/features/settings/SettingsButton.tsx b/apps/desktop-wallet/src/features/settings/SettingsButton.tsx index 4b10520e9..e17b5acdf 100644 --- a/apps/desktop-wallet/src/features/settings/SettingsButton.tsx +++ b/apps/desktop-wallet/src/features/settings/SettingsButton.tsx @@ -10,6 +10,7 @@ const SettingsButton = () => { const dispatch = useAppDispatch() const openSettingsModal = () => dispatch(openModal({ name: 'SettingsModal', props: {} })) + return (