Share accounts (#539)
* feat: do not redirect to wallet on portfolio page * fix: use connected wallet for AccountMenu * fix: fixed ghost AccountDetails * feat: created ShareBar and share functionality * fix: don’t show shareBar if no address is present * fix: stupid 'next/navigation' * tidy: format * fix: fixed tests * ✨ routing and pages for HLS (#538) * 🐛 use useAccountIds * fix: fixed the tests * fix: accountIds is now a suspense --------- Co-authored-by: Bob van der Helm <34470358+bobthebuidlr@users.noreply.github.com>
This commit is contained in:
parent
4915729ed5
commit
ea614997a7
@ -14,15 +14,28 @@ jest.mock('hooks/useHealthComputer', () =>
|
|||||||
jest.mock('components/Account/AccountBalancesTable', () => jest.fn(() => null))
|
jest.mock('components/Account/AccountBalancesTable', () => jest.fn(() => null))
|
||||||
|
|
||||||
const mockedUseCurrentAccount = useCurrentAccount as jest.Mock
|
const mockedUseCurrentAccount = useCurrentAccount as jest.Mock
|
||||||
const mockedAccount = { id: '1', deposits: [], lends: [], debts: [], vaults: [] }
|
const mockedAccounts = [
|
||||||
|
{ id: '1', deposits: [], lends: [], debts: [], vaults: [] },
|
||||||
|
{ id: '2', deposits: [], lends: [], debts: [], vaults: [] },
|
||||||
|
]
|
||||||
jest.mock('hooks/useAccountId', () => jest.fn(() => '1'))
|
jest.mock('hooks/useAccountId', () => jest.fn(() => '1'))
|
||||||
jest.mock('hooks/useAccounts', () => jest.fn(() => [mockedAccount]))
|
jest.mock('hooks/useAccounts', () =>
|
||||||
|
jest.fn(() => ({
|
||||||
|
data: mockedAccounts,
|
||||||
|
})),
|
||||||
|
)
|
||||||
|
jest.mock('hooks/useAccountIds', () =>
|
||||||
|
jest.fn(() => ({
|
||||||
|
data: ['1', '2'],
|
||||||
|
})),
|
||||||
|
)
|
||||||
|
jest.mock('hooks/useCurrentAccount', () => jest.fn(() => mockedAccounts[0]))
|
||||||
|
|
||||||
describe('<AccountDetails />', () => {
|
describe('<AccountDetails />', () => {
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
useStore.setState({
|
useStore.setState({
|
||||||
address: 'walletAddress',
|
address: 'walletAddress',
|
||||||
accounts: [mockedAccount],
|
accounts: mockedAccounts,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -31,7 +44,7 @@ describe('<AccountDetails />', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('renders account details WHEN account is selected', () => {
|
it('renders account details WHEN account is selected', () => {
|
||||||
mockedUseCurrentAccount.mockReturnValue(mockedAccount)
|
mockedUseCurrentAccount.mockReturnValue(mockedAccounts)
|
||||||
render(<AccountDetails />)
|
render(<AccountDetails />)
|
||||||
|
|
||||||
const container = screen.queryByTestId('account-details')
|
const container = screen.queryByTestId('account-details')
|
||||||
|
@ -5,8 +5,8 @@ export default async function getAccountIds(
|
|||||||
address?: string,
|
address?: string,
|
||||||
previousResults?: string[],
|
previousResults?: string[],
|
||||||
): Promise<string[]> {
|
): Promise<string[]> {
|
||||||
|
if (!address) return []
|
||||||
try {
|
try {
|
||||||
if (!address) return []
|
|
||||||
const accountNftQueryClient = await getAccountNftQueryClient()
|
const accountNftQueryClient = await getAccountNftQueryClient()
|
||||||
|
|
||||||
const lastItem = previousResults && previousResults.at(-1)
|
const lastItem = previousResults && previousResults.at(-1)
|
||||||
|
@ -17,6 +17,7 @@ import { DEFAULT_SETTINGS } from 'constants/defaultSettings'
|
|||||||
import { REDUCE_MOTION_KEY } from 'constants/localStore'
|
import { REDUCE_MOTION_KEY } from 'constants/localStore'
|
||||||
import { ORACLE_DENOM } from 'constants/oracle'
|
import { ORACLE_DENOM } from 'constants/oracle'
|
||||||
import useAccountId from 'hooks/useAccountId'
|
import useAccountId from 'hooks/useAccountId'
|
||||||
|
import useAccountIds from 'hooks/useAccountIds'
|
||||||
import useAccounts from 'hooks/useAccounts'
|
import useAccounts from 'hooks/useAccounts'
|
||||||
import useBorrowMarketAssetsTableData from 'hooks/useBorrowMarketAssetsTableData'
|
import useBorrowMarketAssetsTableData from 'hooks/useBorrowMarketAssetsTableData'
|
||||||
import useCurrentAccount from 'hooks/useCurrentAccount'
|
import useCurrentAccount from 'hooks/useCurrentAccount'
|
||||||
@ -34,12 +35,15 @@ import {
|
|||||||
|
|
||||||
export default function AccountDetailsController() {
|
export default function AccountDetailsController() {
|
||||||
const address = useStore((s) => s.address)
|
const address = useStore((s) => s.address)
|
||||||
const { isLoading } = useAccounts(address)
|
const { data: accounts, isLoading } = useAccounts(address)
|
||||||
|
const { data: accountIds } = useAccountIds(address, false)
|
||||||
const accountId = useAccountId()
|
const accountId = useAccountId()
|
||||||
const account = useCurrentAccount()
|
const account = useCurrentAccount()
|
||||||
const focusComponent = useStore((s) => s.focusComponent)
|
|
||||||
|
|
||||||
if (!address || focusComponent) return null
|
const focusComponent = useStore((s) => s.focusComponent)
|
||||||
|
const isOwnAccount = accountId && accountIds?.includes(accountId)
|
||||||
|
|
||||||
|
if (!address || focusComponent || !isOwnAccount) return null
|
||||||
|
|
||||||
if ((isLoading && accountId && !focusComponent) || !account) return <Skeleton />
|
if ((isLoading && accountId && !focusComponent) || !account) return <Skeleton />
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import classNames from 'classnames'
|
import classNames from 'classnames'
|
||||||
import { useEffect } from 'react'
|
import { useEffect } from 'react'
|
||||||
import { useLocation, useNavigate, useParams } from 'react-router-dom'
|
import { useLocation, useNavigate } from 'react-router-dom'
|
||||||
|
|
||||||
import AccountStats from 'components/Account/AccountList/AccountStats'
|
import AccountStats from 'components/Account/AccountList/AccountStats'
|
||||||
import Card from 'components/Card'
|
import Card from 'components/Card'
|
||||||
@ -26,7 +26,7 @@ export default function AccountList(props: Props) {
|
|||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
const { pathname } = useLocation()
|
const { pathname } = useLocation()
|
||||||
const currentAccountId = useAccountId()
|
const currentAccountId = useAccountId()
|
||||||
const { address } = useParams()
|
const address = useStore((s) => s.address)
|
||||||
const { data: accountIds } = useAccountIds(address)
|
const { data: accountIds } = useAccountIds(address)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -37,7 +37,7 @@ export default function AccountList(props: Props) {
|
|||||||
}
|
}
|
||||||
}, [currentAccountId])
|
}, [currentAccountId])
|
||||||
|
|
||||||
if (!accountIds?.length) return null
|
if (!accountIds || !accountIds.length) return null
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='flex flex-wrap w-full p-4'>
|
<div className='flex flex-wrap w-full p-4'>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import classNames from 'classnames'
|
import classNames from 'classnames'
|
||||||
import { useCallback } from 'react'
|
import { useCallback } from 'react'
|
||||||
import { useLocation, useNavigate, useParams } from 'react-router-dom'
|
import { useLocation, useNavigate } from 'react-router-dom'
|
||||||
|
|
||||||
import AccountCreateFirst from 'components/Account/AccountCreateFirst'
|
import AccountCreateFirst from 'components/Account/AccountCreateFirst'
|
||||||
import AccountFund from 'components/Account/AccountFund/AccountFundFullPage'
|
import AccountFund from 'components/Account/AccountFund/AccountFundFullPage'
|
||||||
@ -30,7 +30,7 @@ const ACCOUNT_MENU_BUTTON_ID = 'account-menu-button'
|
|||||||
export default function AccountMenuContent() {
|
export default function AccountMenuContent() {
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
const { pathname } = useLocation()
|
const { pathname } = useLocation()
|
||||||
const { address } = useParams()
|
const address = useStore((s) => s.address)
|
||||||
const { data: accountIds } = useAccountIds(address)
|
const { data: accountIds } = useAccountIds(address)
|
||||||
const accountId = useAccountId()
|
const accountId = useAccountId()
|
||||||
|
|
||||||
@ -42,8 +42,9 @@ export default function AccountMenuContent() {
|
|||||||
const [lendAssets] = useLocalStorage<boolean>(LEND_ASSETS_KEY, DEFAULT_SETTINGS.lendAssets)
|
const [lendAssets] = useLocalStorage<boolean>(LEND_ASSETS_KEY, DEFAULT_SETTINGS.lendAssets)
|
||||||
const { enableAutoLendAccountId } = useAutoLend()
|
const { enableAutoLendAccountId } = useAutoLend()
|
||||||
|
|
||||||
const hasCreditAccounts = !!accountIds.length
|
const hasCreditAccounts = !!accountIds?.length
|
||||||
const isAccountSelected = isNumber(accountId)
|
const isAccountSelected =
|
||||||
|
hasCreditAccounts && accountId && isNumber(accountId) && accountIds.includes(accountId)
|
||||||
|
|
||||||
const checkHasFunds = useCallback(() => {
|
const checkHasFunds = useCallback(() => {
|
||||||
return (
|
return (
|
||||||
|
@ -23,7 +23,7 @@ export default function ActionButton(props: ButtonProps) {
|
|||||||
|
|
||||||
if (!address) return <WalletConnectButton {...defaultProps} />
|
if (!address) return <WalletConnectButton {...defaultProps} />
|
||||||
|
|
||||||
if (accountIds.length === 0) {
|
if (accountIds && accountIds.length === 0) {
|
||||||
return (
|
return (
|
||||||
<Button
|
<Button
|
||||||
onClick={handleCreateAccountClick}
|
onClick={handleCreateAccountClick}
|
||||||
|
6
src/components/Icons/Chain.svg
Normal file
6
src/components/Icons/Chain.svg
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" x="0px" y="0px" viewBox="0 0 512 512">
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M459.654,233.373l-90.531,90.5c-49.969,50-131.031,50-181,0c-7.875-7.844-14.031-16.688-19.438-25.813 l42.063-42.063c2-2.016,4.469-3.172,6.828-4.531c2.906,9.938,7.984,19.344,15.797,27.156c24.953,24.969,65.563,24.938,90.5,0 l90.5-90.5c24.969-24.969,24.969-65.563,0-90.516c-24.938-24.953-65.531-24.953-90.5,0l-32.188,32.219 c-26.109-10.172-54.25-12.906-81.641-8.891l68.578-68.578c50-49.984,131.031-49.984,181.031,0 C509.623,102.342,509.623,183.389,459.654,233.373z M220.326,382.186l-32.203,32.219c-24.953,24.938-65.563,24.938-90.516,0 c-24.953-24.969-24.953-65.563,0-90.531l90.516-90.5c24.969-24.969,65.547-24.969,90.5,0c7.797,7.797,12.875,17.203,15.813,27.125 c2.375-1.375,4.813-2.5,6.813-4.5l42.063-42.047c-5.375-9.156-11.563-17.969-19.438-25.828c-49.969-49.984-131.031-49.984-181.016,0 l-90.5,90.5c-49.984,50-49.984,131.031,0,181.031c49.984,49.969,131.031,49.969,181.016,0l68.594-68.594 C274.561,395.092,246.42,392.342,220.326,382.186z"
|
||||||
|
/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.1 KiB |
7
src/components/Icons/Twitter.svg
Normal file
7
src/components/Icons/Twitter.svg
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" viewBox="0 0 120 120">
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M0.3,3.8l46.3,61.9L0,116.2h10.5l40.8-44.1l33,44.1H120L71.1,50.7l43.4-46.9H104L66.4,44.5L36,3.8
|
||||||
|
H0.3z M15.7,11.6h16.4l72.4,96.9H88.2L15.7,11.6z"
|
||||||
|
/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 289 B |
@ -7,6 +7,7 @@ export { default as ArrowCircledTopRight } from 'components/Icons/ArrowCircledTo
|
|||||||
export { default as ArrowDownLine } from 'components/Icons/ArrowDownLine.svg'
|
export { default as ArrowDownLine } from 'components/Icons/ArrowDownLine.svg'
|
||||||
export { default as ArrowRight } from 'components/Icons/ArrowRight.svg'
|
export { default as ArrowRight } from 'components/Icons/ArrowRight.svg'
|
||||||
export { default as ArrowUpLine } from 'components/Icons/ArrowUpLine.svg'
|
export { default as ArrowUpLine } from 'components/Icons/ArrowUpLine.svg'
|
||||||
|
export { default as Chain } from 'components/Icons/Chain.svg'
|
||||||
export { default as Check } from 'components/Icons/Check.svg'
|
export { default as Check } from 'components/Icons/Check.svg'
|
||||||
export { default as CheckCircled } from 'components/Icons/CheckCircled.svg'
|
export { default as CheckCircled } from 'components/Icons/CheckCircled.svg'
|
||||||
export { default as ChevronDown } from 'components/Icons/ChevronDown.svg'
|
export { default as ChevronDown } from 'components/Icons/ChevronDown.svg'
|
||||||
@ -54,6 +55,7 @@ export { default as SwapIcon } from 'components/Icons/SwapIcon.svg'
|
|||||||
export { default as ThreeDots } from 'components/Icons/ThreeDots.svg'
|
export { default as ThreeDots } from 'components/Icons/ThreeDots.svg'
|
||||||
export { default as TooltipArrow } from 'components/Icons/TooltipArrow.svg'
|
export { default as TooltipArrow } from 'components/Icons/TooltipArrow.svg'
|
||||||
export { default as TrashBin } from 'components/Icons/TrashBin.svg'
|
export { default as TrashBin } from 'components/Icons/TrashBin.svg'
|
||||||
|
export { default as Twitter } from 'components/Icons/Twitter.svg'
|
||||||
export { default as VerticalThreeLine } from 'components/Icons/VerticalThreeLine.svg'
|
export { default as VerticalThreeLine } from 'components/Icons/VerticalThreeLine.svg'
|
||||||
export { default as Wallet } from 'components/Icons/Wallet.svg'
|
export { default as Wallet } from 'components/Icons/Wallet.svg'
|
||||||
// @endindex
|
// @endindex
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import classNames from 'classnames'
|
import classNames from 'classnames'
|
||||||
import { useParams } from 'react-router-dom'
|
|
||||||
|
|
||||||
import { menuTree } from 'components/Header/DesktopHeader'
|
import { menuTree } from 'components/Header/DesktopHeader'
|
||||||
import { Logo } from 'components/Icons'
|
import { Logo } from 'components/Icons'
|
||||||
@ -9,7 +8,7 @@ import useStore from 'store'
|
|||||||
import { getRoute } from 'utils/route'
|
import { getRoute } from 'utils/route'
|
||||||
|
|
||||||
export default function DesktopNavigation() {
|
export default function DesktopNavigation() {
|
||||||
const { address } = useParams()
|
const address = useStore((s) => s.address)
|
||||||
const accountId = useAccountId()
|
const accountId = useAccountId()
|
||||||
|
|
||||||
const focusComponent = useStore((s) => s.focusComponent)
|
const focusComponent = useStore((s) => s.focusComponent)
|
||||||
@ -26,7 +25,7 @@ export default function DesktopNavigation() {
|
|||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<NavLink href={getRoute('trade', address, accountId)}>
|
<NavLink href={getRoute('trade', address, accountId)}>
|
||||||
<span className='block h-10 w-10'>
|
<span className='block w-10 h-10'>
|
||||||
<Logo className='text-white' />
|
<Logo className='text-white' />
|
||||||
</span>
|
</span>
|
||||||
</NavLink>
|
</NavLink>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import classNames from 'classnames'
|
import classNames from 'classnames'
|
||||||
import React, { ReactNode, useMemo } from 'react'
|
import { ReactNode, useMemo } from 'react'
|
||||||
import { NavLink } from 'react-router-dom'
|
import { NavLink, useParams } from 'react-router-dom'
|
||||||
|
|
||||||
import { FormattedNumber } from 'components/FormattedNumber'
|
import { FormattedNumber } from 'components/FormattedNumber'
|
||||||
import Loading from 'components/Loading'
|
import Loading from 'components/Loading'
|
||||||
@ -30,6 +30,7 @@ interface Props {
|
|||||||
export default function PortfolioCard(props: Props) {
|
export default function PortfolioCard(props: Props) {
|
||||||
const { data: account } = useAccount(props.accountId)
|
const { data: account } = useAccount(props.accountId)
|
||||||
const { health } = useHealthComputer(account)
|
const { health } = useHealthComputer(account)
|
||||||
|
const { address: urlAddress } = useParams()
|
||||||
const { data: prices } = usePrices()
|
const { data: prices } = usePrices()
|
||||||
const currentAccountId = useAccountId()
|
const currentAccountId = useAccountId()
|
||||||
const { allAssets: lendingAssets } = useLendingMarketAssetsTableData()
|
const { allAssets: lendingAssets } = useLendingMarketAssetsTableData()
|
||||||
@ -91,7 +92,7 @@ export default function PortfolioCard(props: Props) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<NavLink
|
<NavLink
|
||||||
to={getRoute(`portfolio/${props.accountId}` as Page, address, currentAccountId)}
|
to={getRoute(`portfolio/${props.accountId}` as Page, urlAddress, currentAccountId)}
|
||||||
className={classNames('w-full hover:bg-white/5', !reduceMotion && 'transition-all')}
|
className={classNames('w-full hover:bg-white/5', !reduceMotion && 'transition-all')}
|
||||||
>
|
>
|
||||||
<Skeleton
|
<Skeleton
|
||||||
|
@ -42,7 +42,7 @@ export default function AccountSummary() {
|
|||||||
|
|
||||||
if (!walletAddress && !urlAddress) return <ConnectInfo />
|
if (!walletAddress && !urlAddress) return <ConnectInfo />
|
||||||
|
|
||||||
if (!isLoading && accountIds?.length === 0) {
|
if (!isLoading && accountIds && accountIds.length === 0) {
|
||||||
return (
|
return (
|
||||||
<Card
|
<Card
|
||||||
className='w-full h-fit bg-white/5'
|
className='w-full h-fit bg-white/5'
|
||||||
@ -72,7 +72,7 @@ export default function AccountSummary() {
|
|||||||
<div
|
<div
|
||||||
className={classNames('grid w-full grid-cols-1 gap-6', 'md:grid-cols-2', 'lg:grid-cols-3')}
|
className={classNames('grid w-full grid-cols-1 gap-6', 'md:grid-cols-2', 'lg:grid-cols-3')}
|
||||||
>
|
>
|
||||||
{accountIds.map((accountId: string, index: number) => {
|
{accountIds?.map((accountId: string, index: number) => {
|
||||||
return <PortfolioCard key={accountId} accountId={accountId} />
|
return <PortfolioCard key={accountId} accountId={accountId} />
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
|
@ -4,17 +4,18 @@ import Intro from 'components/Intro'
|
|||||||
import useStore from 'store'
|
import useStore from 'store'
|
||||||
|
|
||||||
export default function PortfolioIntro() {
|
export default function PortfolioIntro() {
|
||||||
const { address } = useParams()
|
const { address: urlAddress } = useParams()
|
||||||
const walletAddress = useStore((s) => s.address)
|
const address = useStore((s) => s.address)
|
||||||
|
const isCurrentWalllet = !urlAddress || urlAddress === address
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Intro
|
<Intro
|
||||||
text={
|
text={
|
||||||
address && !walletAddress ? (
|
!isCurrentWalllet ? (
|
||||||
<>
|
<>
|
||||||
This is the <span className='text-white'>Portfolio</span> of the address{' '}
|
This is the <span className='text-white'>Portfolio</span> of the address{' '}
|
||||||
<span className='text-white'>{address}</span>. You can see all Credit Accounts of this
|
<span className='text-white'>{urlAddress}</span>. You can see all Credit Accounts of
|
||||||
address, but you can't interact with them.
|
this address, but you can't interact with them.
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
|
55
src/components/ShareBar.tsx
Normal file
55
src/components/ShareBar.tsx
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
import classNames from 'classnames'
|
||||||
|
import { useLocation, useParams } from 'react-router-dom'
|
||||||
|
import useClipboard from 'react-use-clipboard'
|
||||||
|
|
||||||
|
import Button from 'components/Button'
|
||||||
|
import { Chain, Check, Twitter } from 'components/Icons'
|
||||||
|
import Text from 'components/Text'
|
||||||
|
import { Tooltip } from 'components/Tooltip'
|
||||||
|
import ConditionalWrapper from 'hocs/ConditionalWrapper'
|
||||||
|
import { DocURL } from 'types/enums/docURL'
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
text: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function ShareBar(props: Props) {
|
||||||
|
const { address } = useParams()
|
||||||
|
const { pathname } = useLocation()
|
||||||
|
const currentUrl = `https://${location.host}${pathname}`
|
||||||
|
const [isCopied, setCopied] = useClipboard(currentUrl, {
|
||||||
|
successDuration: 1000 * 5,
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!window || !address) return null
|
||||||
|
return (
|
||||||
|
<div className='flex justify-end w-full gap-4'>
|
||||||
|
<ConditionalWrapper
|
||||||
|
condition={isCopied}
|
||||||
|
wrapper={(children) => (
|
||||||
|
<Tooltip type='info' content={<Text size='2xs'>Link copied!</Text>}>
|
||||||
|
{children}
|
||||||
|
</Tooltip>
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
color='secondary'
|
||||||
|
iconClassName='w-4 h-4'
|
||||||
|
className={classNames('!p-2', isCopied && '!bg-transparent')}
|
||||||
|
leftIcon={isCopied ? <Check /> : <Chain />}
|
||||||
|
onClick={setCopied}
|
||||||
|
/>
|
||||||
|
</ConditionalWrapper>
|
||||||
|
<Button
|
||||||
|
color='secondary'
|
||||||
|
iconClassName='w-4 h-4'
|
||||||
|
className='!p-2'
|
||||||
|
leftIcon={<Twitter />}
|
||||||
|
onClick={(e) => {
|
||||||
|
e.preventDefault()
|
||||||
|
window.open(`${DocURL.X_SHARE_URL}?text=${props.text} ${currentUrl}`, '_blank')
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
@ -224,7 +224,8 @@ export class OsmosisTheGraphDataFeed implements IDatafeedChartApi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const filler = Array.from({ length: this.batchSize - bars.length }).map((_, index) => ({
|
const filler = Array.from({ length: this.batchSize - bars.length }).map((_, index) => ({
|
||||||
time: (bars[0]?.time || new Date().getTime()) - index * this.minutesPerInterval[resolution],
|
time:
|
||||||
|
(bars[0]?.time || new Date().getTime()) - index * this.minutesPerInterval[resolution],
|
||||||
close: 0,
|
close: 0,
|
||||||
open: 0,
|
open: 0,
|
||||||
high: 0,
|
high: 0,
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { Suspense, useEffect, useMemo } from 'react'
|
import { Suspense, useEffect, useMemo } from 'react'
|
||||||
import { useLocation, useNavigate } from 'react-router-dom'
|
import { useLocation, useNavigate, useParams } from 'react-router-dom'
|
||||||
|
|
||||||
import AccountCreateFirst from 'components/Account/AccountCreateFirst'
|
import AccountCreateFirst from 'components/Account/AccountCreateFirst'
|
||||||
import { CircularProgress } from 'components/CircularProgress'
|
import { CircularProgress } from 'components/CircularProgress'
|
||||||
@ -27,6 +27,7 @@ function FetchLoading() {
|
|||||||
|
|
||||||
function Content() {
|
function Content() {
|
||||||
const address = useStore((s) => s.address)
|
const address = useStore((s) => s.address)
|
||||||
|
const { address: urlAddress } = useParams()
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
const { pathname } = useLocation()
|
const { pathname } = useLocation()
|
||||||
const { data: accountIds, isLoading: isLoadingAccounts } = useAccountIds(address || '')
|
const { data: accountIds, isLoading: isLoadingAccounts } = useAccountIds(address || '')
|
||||||
@ -39,18 +40,26 @@ function Content() {
|
|||||||
)
|
)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
const page = getPage(pathname)
|
||||||
|
if (page === 'portfolio' && urlAddress && urlAddress !== address) {
|
||||||
|
navigate(getRoute(page, urlAddress as string))
|
||||||
|
useStore.setState({ balances: walletBalances, focusComponent: null })
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
|
accountIds &&
|
||||||
accountIds.length !== 0 &&
|
accountIds.length !== 0 &&
|
||||||
BN(baseBalance).isGreaterThanOrEqualTo(defaultFee.amount[0].amount)
|
BN(baseBalance).isGreaterThanOrEqualTo(defaultFee.amount[0].amount)
|
||||||
) {
|
) {
|
||||||
navigate(getRoute(getPage(pathname), address, accountIds[0]))
|
navigate(getRoute(page, address, accountIds[0]))
|
||||||
useStore.setState({ balances: walletBalances, focusComponent: null })
|
useStore.setState({ balances: walletBalances, focusComponent: null })
|
||||||
}
|
}
|
||||||
}, [accountIds, baseBalance, navigate, pathname, address, walletBalances])
|
}, [accountIds, baseBalance, navigate, pathname, address, walletBalances, urlAddress])
|
||||||
|
|
||||||
if (isLoadingAccounts || isLoadingBalances) return <FetchLoading />
|
if (isLoadingAccounts || isLoadingBalances) return <FetchLoading />
|
||||||
if (BN(baseBalance).isLessThan(defaultFee.amount[0].amount)) return <WalletBridges />
|
if (BN(baseBalance).isLessThan(defaultFee.amount[0].amount)) return <WalletBridges />
|
||||||
if (accountIds.length === 0) return <AccountCreateFirst />
|
if (accountIds && accountIds.length === 0) return <AccountCreateFirst />
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,9 +2,9 @@ import useSWR from 'swr'
|
|||||||
|
|
||||||
import getAccountIds from 'api/wallets/getAccountIds'
|
import getAccountIds from 'api/wallets/getAccountIds'
|
||||||
|
|
||||||
export default function useAccountIds(address?: string) {
|
export default function useAccountIds(address?: string, suspense = true) {
|
||||||
return useSWR(`wallets/${address}/account-ids`, () => getAccountIds(address), {
|
return useSWR(`wallets/${address}/account-ids`, () => getAccountIds(address), {
|
||||||
suspense: true,
|
suspense: suspense,
|
||||||
fallback: [] as string[],
|
fallback: [] as string[],
|
||||||
revalidateOnFocus: false,
|
revalidateOnFocus: false,
|
||||||
})
|
})
|
||||||
|
@ -4,6 +4,7 @@ import MigrationBanner from 'components/MigrationBanner'
|
|||||||
import Balances from 'components/Portfolio/Account/Balances'
|
import Balances from 'components/Portfolio/Account/Balances'
|
||||||
import BreadCrumbs from 'components/Portfolio/Account/BreadCrumbs'
|
import BreadCrumbs from 'components/Portfolio/Account/BreadCrumbs'
|
||||||
import Summary from 'components/Portfolio/Account/Summary'
|
import Summary from 'components/Portfolio/Account/Summary'
|
||||||
|
import ShareBar from 'components/ShareBar'
|
||||||
import useAccountId from 'hooks/useAccountId'
|
import useAccountId from 'hooks/useAccountId'
|
||||||
import { getRoute } from 'utils/route'
|
import { getRoute } from 'utils/route'
|
||||||
|
|
||||||
@ -23,6 +24,7 @@ export default function PortfolioAccountPage() {
|
|||||||
<BreadCrumbs accountId={accountId} />
|
<BreadCrumbs accountId={accountId} />
|
||||||
<Summary accountId={accountId} />
|
<Summary accountId={accountId} />
|
||||||
<Balances accountId={accountId} />
|
<Balances accountId={accountId} />
|
||||||
|
<ShareBar text={`Have a look at Credit Account ${accountId} on @mars_protocol!`} />
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ import MigrationBanner from 'components/MigrationBanner'
|
|||||||
import AccountOverview from 'components/Portfolio/Overview'
|
import AccountOverview from 'components/Portfolio/Overview'
|
||||||
import PortfolioSummary from 'components/Portfolio/Overview/Summary'
|
import PortfolioSummary from 'components/Portfolio/Overview/Summary'
|
||||||
import PortfolioIntro from 'components/Portfolio/PortfolioIntro'
|
import PortfolioIntro from 'components/Portfolio/PortfolioIntro'
|
||||||
|
import ShareBar from 'components/ShareBar'
|
||||||
|
|
||||||
export default function PortfolioPage() {
|
export default function PortfolioPage() {
|
||||||
return (
|
return (
|
||||||
@ -10,6 +11,7 @@ export default function PortfolioPage() {
|
|||||||
<PortfolioIntro />
|
<PortfolioIntro />
|
||||||
<PortfolioSummary />
|
<PortfolioSummary />
|
||||||
<AccountOverview />
|
<AccountOverview />
|
||||||
|
<ShareBar text='Have a look at this @mars_protocol portfolio!' />
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -10,4 +10,5 @@ export enum DocURL {
|
|||||||
TRADING_INTRO_URL = 'https://docs.marsprotocol.io/docs/learn/tutorials/trading/trading-intro',
|
TRADING_INTRO_URL = 'https://docs.marsprotocol.io/docs/learn/tutorials/trading/trading-intro',
|
||||||
V1_URL = 'https://v1.marsprotocol.io',
|
V1_URL = 'https://v1.marsprotocol.io',
|
||||||
WALLET_INTRO_URL = 'https://docs.marsprotocol.io/docs/learn/tutorials/basics/connecting-your-wallet',
|
WALLET_INTRO_URL = 'https://docs.marsprotocol.io/docs/learn/tutorials/basics/connecting-your-wallet',
|
||||||
|
X_SHARE_URL = 'https://x.com/intent/tweet',
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user