From a17866c64602199107d55ef9c67d8e1de1030e41 Mon Sep 17 00:00:00 2001 From: Imamah-Zafar <88320460+Imamah-Zafar@users.noreply.github.com> Date: Tue, 8 Nov 2022 13:41:10 +0500 Subject: [PATCH 1/3] include nft dashboard --- package.json | 2 + src/app/components/button/index.tsx | 10 +- src/app/components/shareNft/index.tsx | 73 ++++++ src/app/components/shareNft/shareLinkRow.tsx | 59 +++++ src/app/components/tabBar/index.tsx | 4 +- src/app/routes/index.tsx | 5 + src/app/screens/accountList/index.tsx | 6 +- .../screens/confirmStxTransaxtion/index.tsx | 2 +- .../screens/confrimBtcTransaction/index.tsx | 4 +- src/app/screens/home/index.tsx | 34 ++- src/app/screens/nftDashboard/index.tsx | 210 ++++++++++++++++++ src/app/screens/nftDashboard/nft.tsx | 92 ++++++++ src/app/screens/nftDashboard/nftImage.tsx | 59 +++++ .../stores/wallet/actions/actionCreators.ts | 21 +- src/app/stores/wallet/actions/types.ts | 24 +- src/app/stores/wallet/saga.ts | 9 +- src/app/stores/wallet/walletReducer.ts | 19 +- src/app/utils/constants.ts | 2 + src/app/utils/helper.ts | 10 + .../img/nftDashboard/ic_nft_diamond.svg | 3 + src/assets/img/nftDashboard/nft_user.svg | 4 + .../img/nftDashboard/shareNft/Envelope.svg | 6 + src/assets/img/nftDashboard/shareNft/Link.svg | 4 + .../img/nftDashboard/shareNft/Vector.svg | 3 + .../img/nftDashboard/shareNft/facebook-f.svg | 3 + src/assets/img/nftDashboard/share_network.svg | 7 + src/assets/img/nftDashboard/squares_four.svg | 6 + src/locales/en.json | 54 ++++- 28 files changed, 702 insertions(+), 33 deletions(-) create mode 100644 src/app/components/shareNft/index.tsx create mode 100644 src/app/components/shareNft/shareLinkRow.tsx create mode 100644 src/app/screens/nftDashboard/index.tsx create mode 100644 src/app/screens/nftDashboard/nft.tsx create mode 100644 src/app/screens/nftDashboard/nftImage.tsx create mode 100644 src/assets/img/nftDashboard/ic_nft_diamond.svg create mode 100644 src/assets/img/nftDashboard/nft_user.svg create mode 100644 src/assets/img/nftDashboard/shareNft/Envelope.svg create mode 100644 src/assets/img/nftDashboard/shareNft/Link.svg create mode 100644 src/assets/img/nftDashboard/shareNft/Vector.svg create mode 100644 src/assets/img/nftDashboard/shareNft/facebook-f.svg create mode 100644 src/assets/img/nftDashboard/share_network.svg create mode 100644 src/assets/img/nftDashboard/squares_four.svg diff --git a/package.json b/package.json index ac3986b5b..f76076c78 100644 --- a/package.json +++ b/package.json @@ -24,12 +24,14 @@ "react-content-loader": "^6.2.0", "react-dom": "^18.2.0", "react-i18next": "^11.18.6", + "react-image": "^2.4.0", "react-modal": "^3.15.1", "react-number-format": "^5.0.0", "react-qr-code": "^2.0.8", "react-redux": "^7.2.1", "react-router-dom": "^6.4.0", "react-select": "^5.4.0", + "react-share": "^4.4.1", "react-spinners-css": "^2.0.1", "react-switch": "^7.0.0", "redux": "^4.0.5", diff --git a/src/app/components/button/index.tsx b/src/app/components/button/index.tsx index a24cab493..c8c551b1c 100644 --- a/src/app/components/button/index.tsx +++ b/src/app/components/button/index.tsx @@ -5,6 +5,7 @@ interface ButtonProps { alignment?: string; border?: string; margin: number; + marginTop: number; disabled?: boolean; } @@ -16,10 +17,14 @@ const Button = styled.button((props) => ({ borderRadius: props.theme.radius(1), backgroundColor: props.color ?? props.theme.colors.action.classic, width: '100%', - padding: '12px 16px 12px 10px', + paddingLeft: props.alignment ? '0px' : '10px', + paddingRight: '16px', + paddingTop: '12px', + paddingBottom: '12px', border: `1px solid ${props.border}`, marginRight: props.theme.spacing(props.margin), marginLeft: props.theme.spacing(props.margin), + marginTop: props.theme.spacing(props.marginTop), opacity: props.disabled ? 0.6 : 1, })); @@ -46,6 +51,7 @@ interface Props { buttonColor?: string; buttonAlignment?: string; margin?: number; + marginTop?: number; } function ActionButton({ @@ -58,6 +64,7 @@ function ActionButton({ buttonColor, buttonAlignment, margin, + marginTop, }: Props) { const handleOnPress = () => { if (!disabled) { onPress(); } @@ -70,6 +77,7 @@ function ActionButton({ alignment={buttonAlignment} border={buttonBorderColor} margin={margin ?? 0} + marginTop={marginTop ?? 0} disabled={disabled} > {processing ? ( diff --git a/src/app/components/shareNft/index.tsx b/src/app/components/shareNft/index.tsx new file mode 100644 index 000000000..8adad553c --- /dev/null +++ b/src/app/components/shareNft/index.tsx @@ -0,0 +1,73 @@ +import styled, { useTheme } from 'styled-components'; +import { + FacebookShareButton, TwitterShareButton, EmailShareButton, +} from 'react-share'; +import { useTranslation } from 'react-i18next'; +import FBIcon from '@assets/img/nftDashboard/shareNft/facebook-f.svg'; +import EmailIcon from '@assets/img/nftDashboard/shareNft/Envelope.svg'; +import LinkIcon from '@assets/img/nftDashboard/shareNft/Link.svg'; +import TwitterIcon from '@assets/img/nftDashboard/shareNft/Vector.svg'; +import Cross from '@assets/img/dashboard/X.svg'; +import ShareLinkRow from './shareLinkRow'; + +const Container = styled.button((props) => ({ + display: 'flex', + flexDirection: 'column', + position: 'absolute', + top: 0, + right: 0, + justifyContent: 'center', + paddingLeft: props.theme.spacing(6), + paddingRight: props.theme.spacing(8), + paddingTop: props.theme.spacing(8), + paddingBottom: props.theme.spacing(8), + borderRadius: props.theme.radius(6), + width: 260, + background: props.theme.colors.background.elevation2, +})); + +const CrossContainer = styled.button(() => ({ + display: 'flex', + alignItems: 'flex-end', + justifyContent: 'flex-end', + background: 'transparent', + width: '100%', + +})); + +interface Props { + url: string; + onCrossClick: () => void; +} +function ShareDialog({ url, onCrossClick }: Props) { + const { t } = useTranslation('translation', { keyPrefix: 'NFT_DASHBOARD_SCREEN' }); + const theme = useTheme(); + + const onCopyPress = () => { + navigator.clipboard.writeText(url); + }; + + return ( + + + cross + + + + + + + + + + + + + ); +} + +export default ShareDialog; diff --git a/src/app/components/shareNft/shareLinkRow.tsx b/src/app/components/shareNft/shareLinkRow.tsx new file mode 100644 index 000000000..5172ceb90 --- /dev/null +++ b/src/app/components/shareNft/shareLinkRow.tsx @@ -0,0 +1,59 @@ +import styled from 'styled-components'; + +const RowContainer = styled.button` + display: flex; + flex-direction: row; + align-items: center; + background: transparent; + justify-content: center; + padding: 8px; + :hover { + opacity: 0.8; + } + :active { + opacity: 0.6; + } +`; + +interface ImgContainerProps { + color: string +} + +const ImgContainer = styled.div((props) => ({ + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + background: props.color, + width: 32, + height: 32, + borderRadius: 25, + padding: props.theme.spacing(6), +})); + +const Text = styled.h1((props) => ({ + ...props.theme.body_medium_m, + color: props.theme.colors.white['0'], + marginLeft: props.theme.spacing(6), +})); + +interface Props { + img: string, + text: string, + background: string + onClick?: () => void; +} + +function ShareLinkRow({ + img, text, background, onClick, +}: Props) { + return ( + + + option + + {text} + + ); +} + +export default ShareLinkRow; diff --git a/src/app/components/tabBar/index.tsx b/src/app/components/tabBar/index.tsx index 92516b7f7..d6fade869 100644 --- a/src/app/components/tabBar/index.tsx +++ b/src/app/components/tabBar/index.tsx @@ -38,7 +38,7 @@ function BottomTabBar({ tab }:Props) { }; const handleNftButtonClick = () => { - + if (tab !== 'nft') { navigate('/nft-dashboard'); } }; const handleStackingButtonClick = () => { @@ -46,7 +46,7 @@ function BottomTabBar({ tab }:Props) { }; const handleSettingButtonClick = () => { - + if (tab !== 'settings') { navigate('/settings'); } }; return ( diff --git a/src/app/routes/index.tsx b/src/app/routes/index.tsx index f5eb54e64..6ee439eb1 100644 --- a/src/app/routes/index.tsx +++ b/src/app/routes/index.tsx @@ -20,6 +20,7 @@ import Login from '@screens/login'; import RestoreWallet from '@screens/restoreWallet'; import ForgotPassword from '@screens/forgotPassword'; import BackupWalletSteps from '@screens/backupWalletSteps'; +import NftDashboard from '@screens/nftDashboard'; const router = createHashRouter([ { @@ -106,6 +107,10 @@ const router = createHashRouter([ path: 'backupWalletSteps', element: , }, + { + path: 'nft-dashboard', + element: , + }, ], }, ]); diff --git a/src/app/screens/accountList/index.tsx b/src/app/screens/accountList/index.tsx index 76df0f60a..a3b27ccda 100644 --- a/src/app/screens/accountList/index.tsx +++ b/src/app/screens/accountList/index.tsx @@ -11,8 +11,6 @@ import { StoreState } from '@stores/index'; import { Account } from '@stores/wallet/actions/types'; import { walletFromSeedPhrase } from '@secretkeylabs/xverse-core/wallet'; import { getBnsName } from '@secretkeylabs/xverse-core/api'; -import { SettingsNetwork } from '@secretkeylabs/xverse-core'; -import { initialNetworksList } from '@utils/constants'; const Container = styled.div` display: flex; @@ -90,15 +88,15 @@ function AccountList(): JSX.Element { }; async function onCreateAccount() { + const selectedNetwork = network.type; const index = accountsList.length > 0 ? accountsList.length : 1; const { stxAddress, btcAddress, masterPubKey, stxPublicKey, btcPublicKey, } = await walletFromSeedPhrase({ mnemonic: seedPhrase, index: BigInt(index), - network, + network: selectedNetwork, }); - const selectedNetwork: SettingsNetwork = network === 'Mainnet' ? initialNetworksList[0] : initialNetworksList[1]; const bnsName = await getBnsName(stxAddress, selectedNetwork); const account: Account = { diff --git a/src/app/screens/confirmStxTransaxtion/index.tsx b/src/app/screens/confirmStxTransaxtion/index.tsx index b727764cd..a6113b0b4 100644 --- a/src/app/screens/confirmStxTransaxtion/index.tsx +++ b/src/app/screens/confirmStxTransaxtion/index.tsx @@ -120,7 +120,7 @@ function ConfirmStxTransaction() { const networkInfoSection = ( {t('NETWORK')} - {network} + {network.type} ); diff --git a/src/app/screens/confrimBtcTransaction/index.tsx b/src/app/screens/confrimBtcTransaction/index.tsx index cefd3b62b..4f4ee1b4f 100644 --- a/src/app/screens/confrimBtcTransaction/index.tsx +++ b/src/app/screens/confrimBtcTransaction/index.tsx @@ -67,7 +67,7 @@ function ConfirmBtcTransaction() { }, }); setTimeout(() => { - dispatch(fetchBtcWalletDataRequestAction(btcAddress, network, stxBtcRate, btcFiatRate)); + dispatch(fetchBtcWalletDataRequestAction(btcAddress, network.type, stxBtcRate, btcFiatRate)); }, 1000); } }, [btcTxBroadcastData]); @@ -87,7 +87,7 @@ function ConfirmBtcTransaction() { const networkInfoSection = ( {t('NETWORK')} - {network} + {network.type} ); diff --git a/src/app/screens/home/index.tsx b/src/app/screens/home/index.tsx index 87d663a85..932a2c42a 100644 --- a/src/app/screens/home/index.tsx +++ b/src/app/screens/home/index.tsx @@ -4,7 +4,7 @@ import { useCallback, useEffect, useState } from 'react'; import { useNavigate } from 'react-router-dom'; import styled from 'styled-components'; import { fetchAppInfo, getBnsName } from '@secretkeylabs/xverse-core/api'; -import { FeesMultipliers, FungibleToken, SettingsNetwork } from '@secretkeylabs/xverse-core/types'; +import { FeesMultipliers, FungibleToken } from '@secretkeylabs/xverse-core/types'; import ListDashes from '@assets/img/dashboard/list_dashes.svg'; import CreditCard from '@assets/img/dashboard/credit_card.svg'; import ArrowDownLeft from '@assets/img/dashboard/arrow_down_left.svg'; @@ -28,7 +28,6 @@ import BottomBar from '@components/tabBar'; import { StoreState } from '@stores/index'; import { Account } from '@stores/wallet/actions/types'; import Seperator from '@components/seperator'; -import { initialNetworksList } from '@utils/constants'; import BalanceCard from './balanceCard'; const Container = styled.div` @@ -80,6 +79,21 @@ const TokenListButtonContainer = styled.div((props) => ({ marginTop: props.theme.spacing(4), })); +const TestnetContainer = styled.div((props) => ({ + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + background: props.theme.colors.background.elevation1, + paddingTop: props.theme.spacing(3), + paddingBottom: props.theme.spacing(3), +})); + +const TestnetText = styled.h1((props) => ({ + ...props.theme.body_xs, + textAlign: 'center', + color: props.theme.colors.white['200'], +})); + function Home(): JSX.Element { const { t } = useTranslation('translation', { keyPrefix: 'DASHBOARD_SCREEN' }); const navigate = useNavigate(); @@ -110,8 +124,7 @@ function Home(): JSX.Element { }; const fetchAccount = async () => { - const selectedNetwork: SettingsNetwork = network === 'Mainnet' ? initialNetworksList[0] : initialNetworksList[1]; - const bnsName = await getBnsName(stxAddress, selectedNetwork); + const bnsName = await getBnsName(stxAddress, network); if (accountsList.length === 0) { const accounts: Account[] = [ { @@ -139,10 +152,10 @@ function Home(): JSX.Element { fetchFeeMultiplierData(); dispatch(fetchRatesAction(fiatCurrency)); dispatch(fetchStxWalletDataRequestAction(stxAddress, network, fiatCurrency, stxBtcRate)); - dispatch(fetchBtcWalletDataRequestAction(btcAddress, network, stxBtcRate, btcFiatRate)); + dispatch(fetchBtcWalletDataRequestAction(btcAddress, network.type, stxBtcRate, btcFiatRate)); dispatch(fetchCoinDataRequestAction(stxAddress, network, fiatCurrency, coinsList)); } - }, []); + }, [stxAddress]); useEffect(() => { loadInitialData(); @@ -197,8 +210,17 @@ function Home(): JSX.Element { navigate('/receive/STX'); }; + const testnetBannerView = network.type === 'Testnet' && ( + + + {t('TESTNET')} + + + ); + return ( <> + {testnetBannerView} diff --git a/src/app/screens/nftDashboard/index.tsx b/src/app/screens/nftDashboard/index.tsx new file mode 100644 index 000000000..bc3528694 --- /dev/null +++ b/src/app/screens/nftDashboard/index.tsx @@ -0,0 +1,210 @@ +import styled, { useTheme } from 'styled-components'; +import { Ring } from 'react-spinners-css'; +import useWalletSelector from '@hooks/useWalletSelector'; +import BottomTabBar from '@components/tabBar'; +import AccountRow from '@components/accountRow'; +import Seperator from '@components/seperator'; +import { useTranslation } from 'react-i18next'; +import { useNavigate } from 'react-router-dom'; +import SquaresFour from '@assets/img/nftDashboard/squares_four.svg'; +import ArrowDownLeft from '@assets/img/dashboard/arrow_down_left.svg'; +import ShareNetwork from '@assets/img/nftDashboard/share_network.svg'; +import ActionButton from '@components/button'; +import { getNftsData } from '@secretkeylabs/xverse-core/api'; +import { useEffect, useRef, useState } from 'react'; +import { useQuery } from '@tanstack/react-query'; +import { NonFungibleToken } from '@secretkeylabs/xverse-core/types'; +import BarLoader from '@components/barLoader'; +import { GAMMA_URL, LoaderSize } from '@utils/constants'; +import ShareDialog from '@components/shareNft'; +import Nft from './nft'; + +const Container = styled.div` +display: flex; +flex-direction: column; +flex: 1; +margin-left: 5%; +margin-right: 5%; +margin-bottom: 5%; +overflow-y: auto; +&::-webkit-scrollbar { + display: none; +} +`; + +const GridContainer = styled.div((props) => ({ + display: 'grid', + columnGap: props.theme.spacing(8), + rowGap: props.theme.spacing(6), + gridTemplateColumns: 'repeat(auto-fit,minmax(150px,1fr))', +})); + +const SelectedAccountContainer = styled.div({ + marginLeft: '5%', + marginRight: '5%', +}); + +const CollectibleContainer = styled.div((props) => ({ + marginTop: props.theme.spacing(12), + marginBottom: props.theme.spacing(12), +})); + +const LoaderContainer = styled.div((props) => ({ + display: 'flex', + justifyContent: 'center', + alignItems: 'center', + marginTop: props.theme.spacing(12), +})); + +const ButtonContainer = styled.div((props) => ({ + display: 'flex', + position: 'relative', + flexDirection: 'row', + maxWidth: 400, + marginBottom: props.theme.spacing(20), +})); + +const BottomBarContainer = styled.div({ + marginTop: 'auto', +}); + +const CollectiblesHeadingText = styled.h1((props) => ({ + ...props.theme.headline_category_s, + color: props.theme.colors.white['200'], + textTransform: 'uppercase', + letterSpacing: '0.02em', + opacity: 0.7, +})); + +const CollectiblesValueText = styled.h1((props) => ({ + ...props.theme.headline_l, + marginTop: props.theme.spacing(4), +})); + +const NoCollectiblesText = styled.h1((props) => ({ + ...props.theme.body_bold_m, + color: props.theme.colors.white['200'], + marginTop: props.theme.spacing(4), + textAlign: 'center', +})); + +const BarLoaderContainer = styled.div((props) => ({ + display: 'flex', + marginTop: props.theme.spacing(5), +})); + +function NftDashboard() { + const { t } = useTranslation('translation', { keyPrefix: 'NFT_DASHBOARD_SCREEN' }); + const navigate = useNavigate(); + const theme = useTheme(); + const offset = useRef(0); + const { selectedAccount, stxAddress, network } = useWalletSelector(); + const [nftList, setNftList] = useState([]); + const [nftTotal, setNftTotal] = useState(0); + const [showShareNftOptions, setShowNftOptions] = useState(false); + + const { + isLoading, data, + } = useQuery( + ['nft-meta-data', { stxAddress, network, offset: offset.current }], + async () => getNftsData(stxAddress, network, offset.current), + ); + + useEffect(() => { + if (data) { + setNftList(data.nftsList); + setNftTotal(data.total); + } + }, [data]); + const handleAccountSelect = () => { + navigate('/account-list'); + }; + + const loader = ( + + + + ); + + const openInGalleryView = async () => { + await chrome.tabs.create({ + url: chrome.runtime.getURL('options.html#/nft-dashboard'), + }); + }; + + const collectiblesCard = ( + + {t('COLLECTIBLES')} + {isLoading ? loader + : {`${nftTotal} ${t('ITEMS')}`}} + + + ); + + const nftListView = ( + nftTotal === 0 ? ( + + {t('NO_COLLECTIBLES')} + + ) : ( + + { nftList.map((nft) => ( + + ))} + + ) + ); + + const onSharePress = () => { + setShowNftOptions(true); + }; + + const onCrossPress = () => { + setShowNftOptions(false); + }; + + const onReceivePress = () => { + navigate('/receive/STX'); + }; + + const buttons = ( + + + + {showShareNftOptions && } + + ); + + const showLoader = ( + + + + ); + + return ( + <> + + + + + + {collectiblesCard} + {buttons} + {isLoading ? showLoader : nftListView} + + + + + + + ); +} + +export default NftDashboard; diff --git a/src/app/screens/nftDashboard/nft.tsx b/src/app/screens/nftDashboard/nft.tsx new file mode 100644 index 000000000..587e389f9 --- /dev/null +++ b/src/app/screens/nftDashboard/nft.tsx @@ -0,0 +1,92 @@ +import { useQuery } from '@tanstack/react-query'; +import styled from 'styled-components'; +import { getNftDetail } from '@secretkeylabs/xverse-core/api'; +import { NonFungibleToken, getBnsNftName } from '@secretkeylabs/xverse-core/types/index'; +import { BNS_CONTRACT } from '@utils/constants'; +import NftUser from '@assets/img/nftDashboard/nft_user.svg'; +import { useNavigate } from 'react-router-dom'; +import NftImage from './nftImage'; + +interface Props { + asset: NonFungibleToken; +} + +const NftNameText = styled.h1((props) => ({ + ...props.theme.body_bold_m, + marginTop: 'auto', +})); + +const GradientContainer = styled.div((props) => ({ + objectFit: 'cover', + display: 'flex', + width: '100%', + height: '100%', + justifyContent: 'center', + alignItems: 'center', + borderRadius: 8, + marginBottom: props.theme.spacing(4), + background: 'linear-gradient(to bottom,#E5A78E, #EA603E, #4D52EF)', +})); + +const GridItemContainer = styled.button((props) => ({ + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + justifyContent: 'center', + color: props.theme.colors.white['0'], + padding: props.theme.spacing(7), + borderRadius: props.theme.radius(3), + background: 'linear-gradient(27.88deg, #1D2032 0%, rgba(29, 32, 50, 0) 100%)', + border: ` 1px solid ${props.theme.colors.background.elevation2}`, +})); + +function Nft({ asset }: Props) { + const navigate = useNavigate(); + const { data } = useQuery( + ['nft-meta-data', asset.asset_identifier], + async () => { + const principal: string[] = asset.asset_identifier.split('::'); + const contractInfo: string[] = principal[0].split('.'); + return getNftDetail( + asset.value.repr.replace('u', ''), + contractInfo[0], + contractInfo[1], + ); + }, + ); + + function getName() { + if (data?.data.token_metadata) return `${data?.data.token_metadata.name} `; + + if (asset.asset_identifier === BNS_CONTRACT) { + return getBnsNftName(asset); + } + } + + const nftName = ( + {getName()} + ); + + const bnsPlaceholder = ( + + user + + ); + + const handleOnClick = () => { + + }; + + return ( + + {asset.asset_identifier === BNS_CONTRACT ? bnsPlaceholder : ( + + )} + {nftName} + + + ); +} +export default Nft; diff --git a/src/app/screens/nftDashboard/nftImage.tsx b/src/app/screens/nftDashboard/nftImage.tsx new file mode 100644 index 000000000..a20444b5d --- /dev/null +++ b/src/app/screens/nftDashboard/nftImage.tsx @@ -0,0 +1,59 @@ +import { Suspense } from 'react'; +import styled from 'styled-components'; +import { Ring } from 'react-spinners-css'; +import { TokenMetaData } from '@secretkeylabs/xverse-core/types/api/stacks/assets'; +import { getFetchableUrl } from '@utils/helper'; +import NftPlaceholderImage from '@assets/img/nftDashboard/ic_nft_diamond.svg'; +import Img from 'react-image'; + +const ImageContainer = styled.div((props) => ({ + padding: props.theme.spacing(10), + borderRadius: props.theme.radius(2), + marginBottom: props.theme.spacing(4), +})); + +const Video = styled.video({ + width: '100%', + height: '100%', + objectFit: 'cover', +}); + +interface Props { + metadata: TokenMetaData; +} + +const showloader = ( + + + +); + +const showNftImagePlaceholder = ( + + nft + +); + +function NftImage({ metadata }: Props) { + if (metadata?.image_protocol) { + return ( + + + + ); + } + + if (metadata?.asset_protocol) { + return ( + + + ); + } + + return ( + showloader + ); +} + +export default NftImage; diff --git a/src/app/stores/wallet/actions/actionCreators.ts b/src/app/stores/wallet/actions/actionCreators.ts index 980e948ab..113e0eaaa 100644 --- a/src/app/stores/wallet/actions/actionCreators.ts +++ b/src/app/stores/wallet/actions/actionCreators.ts @@ -4,6 +4,7 @@ import { FeesMultipliers, FungibleToken, NetworkType, + SettingsNetwork, SupportedCurrency, TransactionData, } from '@secretkeylabs/xverse-core/types'; @@ -63,7 +64,7 @@ export function selectAccount( masterPubKey: string, stxPublicKey: string, btcPublicKey: string, - network: NetworkType, + network: SettingsNetwork, // stackingState: StackingStateData, bnsName?: string, ): actions.SelectAccount { @@ -115,7 +116,7 @@ export function fetchRatesFailAction(error: string): actions.FetchRatesFail { export function fetchStxWalletDataRequestAction( stxAddress: string, - network: NetworkType, + network: SettingsNetwork, fiatCurrency: string, stxBtcRate: BigNumber, ): actions.FetchStxWalletDataRequest { @@ -182,7 +183,7 @@ export function fetchBtcWalletDataFail(): actions.FetchBtcWalletDataFail { export function fetchCoinDataRequestAction( stxAddress: string, - network: NetworkType, + network: SettingsNetwork, fiatCurrency: string, coinsList: FungibleToken[] | null, ): actions.FetchCoinDataRequest { @@ -221,3 +222,17 @@ export function FetchUpdatedVisibleCoinListAction( coinsList, }; } + +export function ChangeFiatCurrencyAction(fiatCurrency: SupportedCurrency): actions.ChangeFiatCurrency { + return { + type: actions.ChangeFiatCurrencyKey, + fiatCurrency, + }; +} + +export function ChangeNetworkAction(network: SettingsNetwork): actions.ChangeNetwork { + return { + type: actions.ChangeNetworkKey, + network, + }; +} diff --git a/src/app/stores/wallet/actions/types.ts b/src/app/stores/wallet/actions/types.ts index 8e0eaeabf..0631c733a 100644 --- a/src/app/stores/wallet/actions/types.ts +++ b/src/app/stores/wallet/actions/types.ts @@ -4,6 +4,7 @@ import { FeesMultipliers, FungibleToken, NetworkType, + SettingsNetwork, SupportedCurrency, TransactionData, } from '@secretkeylabs/xverse-core/types'; @@ -19,6 +20,8 @@ export const StoreEncryptedSeedKey = 'StoreEncryptedSeed'; export const UpdateVisibleCoinListKey = 'UpdateVisibleCoinList'; export const AddAccountKey = 'AddAccount'; export const FetchFeeMultiplierKey = 'FetchFeeMultiplier'; +export const ChangeFiatCurrencyKey = 'ChangeFiatCurrency'; +export const ChangeNetworkKey = 'ChangeNetwork'; export const FetchStxWalletDataRequestKey = 'FetchStxWalletDataRequest'; export const FetchStxWalletDataSuccessKey = 'FetchStxWalletDataSuccess'; @@ -54,7 +57,7 @@ export interface WalletState { btcPublicKey: string; accountsList: Account[]; selectedAccount: Account | null; - network: NetworkType; + network: SettingsNetwork; seedPhrase: string; encryptedSeed: string; loadingWalletData: boolean; @@ -128,7 +131,7 @@ export interface SelectAccount { stxPublicKey: string; btcPublicKey: string; bnsName?: string; - network: NetworkType; + network: SettingsNetwork; // stackingState: StackingStateData; } @@ -151,7 +154,7 @@ export interface FetchRatesFail { export interface FetchStxWalletDataRequest { type: typeof FetchStxWalletDataRequestKey; stxAddress: string; - network: NetworkType; + network: SettingsNetwork; fiatCurrency: string; stxBtcRate: BigNumber; } @@ -190,7 +193,7 @@ export interface FetchBtcWalletDataFail { export interface FetchCoinDataRequest { type: typeof FetchCoinDataRequestKey; stxAddress: string; - network: NetworkType; + network: SettingsNetwork; fiatCurrency: string; coinsList: FungibleToken[] | null; } @@ -210,6 +213,15 @@ export interface UpdateVisibleCoinList { coinsList: FungibleToken[]; } +export interface ChangeFiatCurrency { + type: typeof ChangeFiatCurrencyKey; + fiatCurrency: SupportedCurrency; +} +export interface ChangeNetwork { + type: typeof ChangeNetworkKey; + network: SettingsNetwork; +} + export type WalletActions = | SetWallet | ResetWallet @@ -232,4 +244,6 @@ export type WalletActions = | FetchCoinDataRequest | FetchCoinDataSuccess | FetchCoinDataFailure - | UpdateVisibleCoinList; + | UpdateVisibleCoinList + | ChangeFiatCurrency + | ChangeNetwork; diff --git a/src/app/stores/wallet/saga.ts b/src/app/stores/wallet/saga.ts index bfb26e9d1..9f7b12881 100644 --- a/src/app/stores/wallet/saga.ts +++ b/src/app/stores/wallet/saga.ts @@ -7,11 +7,10 @@ import { getCoinsInfo, getFtData, } from '@secretkeylabs/xverse-core/api'; -import { initialNetworksList, PAGINATION_LIMIT } from '@utils/constants'; +import { PAGINATION_LIMIT } from '@utils/constants'; import BigNumber from 'bignumber.js'; import { BtcAddressData, - SettingsNetwork, StxAddressData, FungibleToken, CoinsResponse, @@ -51,10 +50,9 @@ function* fetchRates(action: FetchRates) { function* fetchStxWalletData(action: FetchStxWalletDataRequest) { try { - const selectedNetwork: SettingsNetwork = action.network === 'Mainnet' ? initialNetworksList[0] : initialNetworksList[1]; const stxData: StxAddressData = yield fetchStxAddressData( action.stxAddress, - selectedNetwork, + action.network, 0, PAGINATION_LIMIT, ); @@ -93,11 +91,10 @@ function* fetchBtcWalletData(action: FetchBtcWalletDataRequest) { function* fetchCoinData(action: FetchCoinDataRequest) { try { - const selectedNetwork: SettingsNetwork = action.network === 'Mainnet' ? initialNetworksList[0] : initialNetworksList[1]; const fungibleTokenList: Array = yield call( getFtData, action.stxAddress, - selectedNetwork, + action.network, ); const visibleCoins: FungibleToken[] | null = action.coinsList; if (visibleCoins) { diff --git a/src/app/stores/wallet/walletReducer.ts b/src/app/stores/wallet/walletReducer.ts index 14abefd07..557800b1e 100644 --- a/src/app/stores/wallet/walletReducer.ts +++ b/src/app/stores/wallet/walletReducer.ts @@ -22,6 +22,8 @@ import { AddAccountKey, UpdateVisibleCoinListKey, FetchFeeMultiplierKey, + ChangeFiatCurrencyKey, + ChangeNetworkKey, } from './actions/types'; const initialWalletState: WalletState = { @@ -30,7 +32,10 @@ const initialWalletState: WalletState = { masterPubKey: '', stxPublicKey: '', btcPublicKey: '', - network: 'Mainnet', + network: { + type: 'Mainnet', + address: 'https://stacks-node-api.mainnet.stacks.co', + }, accountsList: [], selectedAccount: null, seedPhrase: '', @@ -174,6 +179,18 @@ const walletReducer = ( ...state, feeMultipliers: action.feeMultipliers, }; + case ChangeFiatCurrencyKey: + return { + ...state, + fiatCurrency: action.fiatCurrency, + }; + case ChangeNetworkKey: + return { + ...state, + network: action.network, + selectedAccount: null, + accountsList: [], + }; default: return state; } diff --git a/src/app/utils/constants.ts b/src/app/utils/constants.ts index d6020f249..2500207b1 100644 --- a/src/app/utils/constants.ts +++ b/src/app/utils/constants.ts @@ -1,5 +1,7 @@ import { SettingsNetwork } from '@secretkeylabs/xverse-core/types'; +export const BNS_CONTRACT = 'SP000000000000000000002Q6VF78.bns::names'; +export const GAMMA_URL = 'https://gamma.io/'; /** * terms of service and privacy policy links */ diff --git a/src/app/utils/helper.ts b/src/app/utils/helper.ts index c4659ddf1..52f6040f2 100644 --- a/src/app/utils/helper.ts +++ b/src/app/utils/helper.ts @@ -52,3 +52,13 @@ export function getAddressDetail(account:Account) { export function getExplorerUrl(stxAddress: string): string { return `https://explorer.stacks.co/address/${stxAddress}?chain=mainnet`; } + +export function getFetchableUrl(uri: string, protocol: string): string | undefined { + const publicIpfs = 'https://ipfs.io/ipfs'; + if (protocol === 'http') return uri; + if (protocol === 'ipfs') { + const url = uri.split('//'); + return `${publicIpfs}/${url[1]}`; + } + return undefined; +} diff --git a/src/assets/img/nftDashboard/ic_nft_diamond.svg b/src/assets/img/nftDashboard/ic_nft_diamond.svg new file mode 100644 index 000000000..b78cce2ce --- /dev/null +++ b/src/assets/img/nftDashboard/ic_nft_diamond.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/img/nftDashboard/nft_user.svg b/src/assets/img/nftDashboard/nft_user.svg new file mode 100644 index 000000000..0101a3c43 --- /dev/null +++ b/src/assets/img/nftDashboard/nft_user.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/assets/img/nftDashboard/shareNft/Envelope.svg b/src/assets/img/nftDashboard/shareNft/Envelope.svg new file mode 100644 index 000000000..23326fbad --- /dev/null +++ b/src/assets/img/nftDashboard/shareNft/Envelope.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/assets/img/nftDashboard/shareNft/Link.svg b/src/assets/img/nftDashboard/shareNft/Link.svg new file mode 100644 index 000000000..44f630670 --- /dev/null +++ b/src/assets/img/nftDashboard/shareNft/Link.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/assets/img/nftDashboard/shareNft/Vector.svg b/src/assets/img/nftDashboard/shareNft/Vector.svg new file mode 100644 index 000000000..7aedbbcb5 --- /dev/null +++ b/src/assets/img/nftDashboard/shareNft/Vector.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/img/nftDashboard/shareNft/facebook-f.svg b/src/assets/img/nftDashboard/shareNft/facebook-f.svg new file mode 100644 index 000000000..4d18a5220 --- /dev/null +++ b/src/assets/img/nftDashboard/shareNft/facebook-f.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/img/nftDashboard/share_network.svg b/src/assets/img/nftDashboard/share_network.svg new file mode 100644 index 000000000..bca07c0db --- /dev/null +++ b/src/assets/img/nftDashboard/share_network.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/assets/img/nftDashboard/squares_four.svg b/src/assets/img/nftDashboard/squares_four.svg new file mode 100644 index 000000000..35f272088 --- /dev/null +++ b/src/assets/img/nftDashboard/squares_four.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/locales/en.json b/src/locales/en.json index 28f8b85be..9f18cf98f 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -23,7 +23,8 @@ "RECEIVE": "Receive", "SEND": "Send", "BUY":"Buy", - "MANAGE_TOKEN":"Manage token list" + "MANAGE_TOKEN":"Manage token list", + "TESTNET": "Testnet" }, "TOKEN_SCREEN": { "ADD_COINS": "Manage tokens" @@ -125,7 +126,9 @@ "CREATE_PASSWORD_SCREEN": { "CREATE_PASSWORD_TITLE": "Enter your new password", "CONFIRM_PASSWORD_TITLE": "Confirm your new password", + "ENTER_PASSWORD": "Enter your current password", "TEXT_INPUT_NEW_PASSWORD_LABEL": "New Password", + "TEXT_INPUT_ENTER_PASSWORD_LABEL": "Enter your current password", "TEXT_INPUT_CONFIRM_PASSWORD_LABEL": "Confirm Password", "CONTINUE_BUTTON": "Continue", "BACK_BUTTON": "Back", @@ -134,7 +137,8 @@ "PASSWORD_STRENGTH_MEDIUM": "Medium", "PASSWORD_STRENGTH_STRONG": "Strong", "PASSWORD_STRENGTH_ERROR": "You need to enter a stronger password", - "CONFIRM_PASSWORD_MATCH_ERROR": "please make sure your passwords match" + "CONFIRM_PASSWORD_MATCH_ERROR": "Please make sure your passwords match", + "INCORRECT_PASSWORD_ERROR": "Incorrect password" }, "WALLET_SUCCESS_SCREEN": { "SCREEN_TITLE": "Wallet created successfully", @@ -161,5 +165,51 @@ "SEED_INPUT_LABEL": "Selected Words", "SEED_INPUT_ERROR": "Invalid seed phrase, please try again", "CONTINUE_BUTTON": "Continue" + }, + "NFT_DASHBOARD_SCREEN": { + "COLLECTIBLES": "Number of collectibles", + "NO_COLLECTIBLES": "No collectibles yet", + "ITEMS": "items", + "WEB_GALLERY": "Open web gallery", + "RECEIVE": "Receive", + "SEND": "Send", + "SHARE": "Share collection", + "FACEBOOK": "Share on Facebook", + "TWITTER": "Share on Twitter", + "MAIL": "Share by Mail", + "COPY": "Copy link", + "NFT_DETAIL":"Item detail" + }, + "RESET_WALLET_SCREEN": { + "ENTER_PASSWORD": "Enter your password to reset your wallet", + "PASSWORD": "Password", + "RESET": "Reset", + "BACK": "Back", + "INCORRECT_PASSWORD_ERROR":"Incorrect password" + }, + "SETTING_SCREEN": { + "GENERAL": "General", + "CURRENCY": "Fiat Currency", + "NETWORK": "Network", + "SECURITY": "Security", + "UPDATE_PASSWORD": "Update Password", + "BACKUP_WALLET": "Backup Wallet", + "RESET_WALLET": "Reset Wallet", + "ABOUT": "About", + "TERMS_OF_SERVICE": "Terms of Service", + "PRIVACY_POLICY": "Privacy Policy", + "SUPPORT_CENTER": "Support Center", + "VERSION": "Version", + "UPDATE_PASSWORD_SUCCESS": "Password successfully updated", + "OK": "OK", + "RESET_WALLET_DESCRIPTION": "This will reset your wallet from this browser. Make sure you have your seed phrase backed up.", + "CANCEL": "Cancel", + "NODE": "STX Node", + "BACKUP_WALLET_UNLOCK_SEED": "Enter your password to reveal your seedphrase", + "REVEAL": "Reveal", + "BACK": "Back", + "PASSWORD": "Password", + "SAVE": "Save", + "INVALID_URL": "Invalid URL" } } \ No newline at end of file From 0a0125178d35bfae6ea36c7f885eb02351b47182 Mon Sep 17 00:00:00 2001 From: Imamah-Zafar <88320460+Imamah-Zafar@users.noreply.github.com> Date: Sun, 13 Nov 2022 16:21:52 +0500 Subject: [PATCH 2/3] refactor nft screen --- src/app/screens/nftDashboard/index.tsx | 56 ++++++++++------------- src/app/screens/nftDashboard/nft.tsx | 18 +++----- src/app/screens/nftDashboard/nftImage.tsx | 21 +++++---- 3 files changed, 42 insertions(+), 53 deletions(-) diff --git a/src/app/screens/nftDashboard/index.tsx b/src/app/screens/nftDashboard/index.tsx index bc3528694..9b57a1938 100644 --- a/src/app/screens/nftDashboard/index.tsx +++ b/src/app/screens/nftDashboard/index.tsx @@ -132,15 +132,6 @@ function NftDashboard() { }); }; - const collectiblesCard = ( - - {t('COLLECTIBLES')} - {isLoading ? loader - : {`${nftTotal} ${t('ITEMS')}`}} - - - ); - const nftListView = ( nftTotal === 0 ? ( @@ -167,27 +158,6 @@ function NftDashboard() { navigate('/receive/STX'); }; - const buttons = ( - - - - {showShareNftOptions && } - - ); - - const showLoader = ( - - - - ); - return ( <> @@ -195,9 +165,29 @@ function NftDashboard() { - {collectiblesCard} - {buttons} - {isLoading ? showLoader : nftListView} + + {t('COLLECTIBLES')} + {isLoading ? loader + : {`${nftTotal} ${t('ITEMS')}`}} + + + + + + {showShareNftOptions && } + + {isLoading ? ( + + + + ) : nftListView} diff --git a/src/app/screens/nftDashboard/nft.tsx b/src/app/screens/nftDashboard/nft.tsx index 587e389f9..1952fc4ff 100644 --- a/src/app/screens/nftDashboard/nft.tsx +++ b/src/app/screens/nftDashboard/nft.tsx @@ -63,28 +63,22 @@ function Nft({ asset }: Props) { } } - const nftName = ( - {getName()} - ); - - const bnsPlaceholder = ( - - user - - ); - const handleOnClick = () => { }; return ( - {asset.asset_identifier === BNS_CONTRACT ? bnsPlaceholder : ( + {asset.asset_identifier === BNS_CONTRACT ? ( + + user + + ) : ( )} - {nftName} + {getName()} ); diff --git a/src/app/screens/nftDashboard/nftImage.tsx b/src/app/screens/nftDashboard/nftImage.tsx index a20444b5d..b7dd4216d 100644 --- a/src/app/screens/nftDashboard/nftImage.tsx +++ b/src/app/screens/nftDashboard/nftImage.tsx @@ -22,12 +22,6 @@ interface Props { metadata: TokenMetaData; } -const showloader = ( - - - -); - const showNftImagePlaceholder = ( nft @@ -38,7 +32,16 @@ function NftImage({ metadata }: Props) { if (metadata?.image_protocol) { return ( - + + + +)} + unloader={showNftImagePlaceholder} + /> ); } @@ -52,7 +55,9 @@ function NftImage({ metadata }: Props) { } return ( - showloader + + + ); } From dc59904fbf33549ee313bd42c9f806989fbff0a2 Mon Sep 17 00:00:00 2001 From: Imamah-Zafar <88320460+Imamah-Zafar@users.noreply.github.com> Date: Tue, 15 Nov 2022 12:37:13 +0500 Subject: [PATCH 3/3] fix package.json --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7099d96a6..863002971 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "version": "0.0.1", "private": true, "dependencies": { - "@secretkeylabs/xverse-core": "file:/Users/imamah/Desktop/xverse-core/xverse-core", + "@secretkeylabs/xverse-core": "github:secretkeylabs/xverse-core", "@stacks/encryption": "4.3.5", "@tanstack/react-query": "^4.12.0", "@testing-library/jest-dom": "^5.16.5",