Mp 1757 wallet connect (#66)
* MP-1757: implemented the WalletProvider and connect buttons * tidy: tidy up the search * MP-1691: moved modals outside of the DOM * MP-1691: changed CreditManager into AccountDetails * fix: fixed the naming * MP-1691: UX approvements * MP-1691: global confirm and delete modal added * fix: merged the credit-account and wallet branch * MP-1757: added the status store * fix: updated the store interaction * MP-1757: major cleanup of stores * tidy: format
@ -1,21 +1,26 @@
|
||||
import BigNumber from 'bignumber.js'
|
||||
import classNames from 'classnames'
|
||||
import { useState } from 'react'
|
||||
|
||||
import Button from 'components/Button'
|
||||
import FormattedNumber from 'components/FormattedNumber'
|
||||
import ArrowRightLine from 'components/Icons/arrow-right-line.svg'
|
||||
import ChevronDown from 'components/Icons/chevron-down.svg'
|
||||
import ChevronLeft from 'components/Icons/chevron-left.svg'
|
||||
import Text from 'components/Text'
|
||||
import useAccountStats from 'hooks/useAccountStats'
|
||||
import useCreditAccountPositions from 'hooks/useCreditAccountPositions'
|
||||
import useMarkets from 'hooks/useMarkets'
|
||||
import useTokenPrices from 'hooks/useTokenPrices'
|
||||
import useCreditManagerStore from 'stores/useCreditManagerStore'
|
||||
import useWalletStore from 'stores/useWalletStore'
|
||||
import { useAccountDetailsStore } from 'stores'
|
||||
import { chain } from 'utils/chains'
|
||||
import { getTokenDecimals, getTokenSymbol } from 'utils/tokens'
|
||||
|
||||
const CreditManager = () => {
|
||||
const address = useWalletStore((s) => s.address)
|
||||
const selectedAccount = useCreditManagerStore((s) => s.selectedAccount)
|
||||
const toggleCreditManager = useCreditManagerStore((s) => s.actions.toggleCreditManager)
|
||||
import AccountManageOverlay from './AccountManageOverlay'
|
||||
|
||||
const AccountDetails = () => {
|
||||
const selectedAccount = useAccountDetailsStore((s) => s.selectedAccount)
|
||||
const isOpen = useAccountDetailsStore((s) => s.isOpen)
|
||||
|
||||
const { data: positionsData, isLoading: isLoadingPositions } = useCreditAccountPositions(
|
||||
selectedAccount ?? '',
|
||||
@ -25,6 +30,8 @@ const CreditManager = () => {
|
||||
const { data: marketsData } = useMarkets()
|
||||
const accountStats = useAccountStats()
|
||||
|
||||
const [showManageMenu, setShowManageMenu] = useState(false)
|
||||
|
||||
const getTokenTotalUSDValue = (amount: string, denom: string) => {
|
||||
// early return if prices are not fetched yet
|
||||
if (!tokenPrices) return 0
|
||||
@ -37,16 +44,57 @@ const CreditManager = () => {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='flex w-[400px] basis-[400px] flex-wrap content-start border-white/20 bg-header placeholder:border-l'>
|
||||
<div className='flex w-full flex-wrap items-center border-b border-white/20'>
|
||||
<Text size='xl' uppercase={true} className='flex-grow text-center text-white'>
|
||||
<div
|
||||
className={classNames(
|
||||
'relative flex w-[400px] basis-[400px] flex-wrap content-start border-white/20 bg-header placeholder:border-l',
|
||||
'transition-[margin] duration-1000 ease-in-out',
|
||||
isOpen ? 'mr-0' : '-mr-[400px]',
|
||||
)}
|
||||
>
|
||||
<Button
|
||||
onClick={() => {
|
||||
useAccountDetailsStore.setState({ isOpen: true })
|
||||
}}
|
||||
variant='text'
|
||||
className={classNames(
|
||||
'absolute top-1/2 -left-[20px] w-[21px] -translate-y-1/2 bg-header p-0',
|
||||
'rounded-none rounded-tl-sm rounded-bl-sm',
|
||||
'border border-white/20',
|
||||
'transition-[opacity] delay-1000 duration-500 ease-in-out',
|
||||
isOpen ? 'pointer-events-none opacity-0' : 'opacity-100',
|
||||
)}
|
||||
>
|
||||
<span className='flex h-20 px-1 py-6 text-white/40 transition-[color] hover:text-white'>
|
||||
<ChevronLeft />
|
||||
</span>
|
||||
</Button>
|
||||
<div className='relative flex w-full flex-wrap items-center border-b border-white/20'>
|
||||
<Button
|
||||
variant='text'
|
||||
className='flex flex-grow flex-nowrap items-center justify-center p-4 text-center text-white text-xl-caps'
|
||||
onClick={() => setShowManageMenu(!showManageMenu)}
|
||||
>
|
||||
Account {selectedAccount}
|
||||
</Text>
|
||||
<div className='flex border-l border-white/20 p-4' onClick={() => {}}>
|
||||
<span className='w-5 hover:cursor-pointer' onClick={toggleCreditManager}>
|
||||
<ArrowRightLine />
|
||||
<span className='ml-2 flex w-4'>
|
||||
<ChevronDown />
|
||||
</span>
|
||||
</Button>
|
||||
<div className='flex border-l border-white/20' onClick={() => {}}>
|
||||
<Button
|
||||
variant='text'
|
||||
className='w-14 p-4 text-white/40 transition-[color] hover:cursor-pointer hover:text-white'
|
||||
onClick={() => {
|
||||
useAccountDetailsStore.setState({ isOpen: false })
|
||||
}}
|
||||
>
|
||||
<ArrowRightLine />
|
||||
</Button>
|
||||
</div>
|
||||
<AccountManageOverlay
|
||||
className='top-[60px] left-[36px]'
|
||||
show={showManageMenu}
|
||||
setShow={setShowManageMenu}
|
||||
/>
|
||||
</div>
|
||||
<div className='flex w-full flex-wrap p-2'>
|
||||
<div className='mb-2 flex w-full'>
|
||||
@ -80,7 +128,7 @@ const CreditManager = () => {
|
||||
</div>
|
||||
</div>
|
||||
<div className='flex w-full flex-wrap'>
|
||||
<Text uppercase={true} className='w-full bg-black/20 px-4 py-2 text-white/40'>
|
||||
<Text uppercase className='w-full bg-black/20 px-4 py-2 text-white/40'>
|
||||
Balances
|
||||
</Text>
|
||||
{isLoadingPositions ? (
|
||||
@ -88,16 +136,16 @@ const CreditManager = () => {
|
||||
) : (
|
||||
<div className='flex w-full flex-wrap'>
|
||||
<div className='mb-2 flex w-full border-b border-white/20 bg-black/20 px-4 py-2'>
|
||||
<Text size='xs' uppercase={true} className='flex-1 text-white'>
|
||||
<Text size='xs' uppercase className='flex-1 text-white'>
|
||||
Asset
|
||||
</Text>
|
||||
<Text size='xs' uppercase={true} className='flex-1 text-white'>
|
||||
<Text size='xs' uppercase className='flex-1 text-white'>
|
||||
Value
|
||||
</Text>
|
||||
<Text size='xs' uppercase={true} className='flex-1 text-white'>
|
||||
<Text size='xs' uppercase className='flex-1 text-white'>
|
||||
Size
|
||||
</Text>
|
||||
<Text size='xs' uppercase={true} className='flex-1 text-white'>
|
||||
<Text size='xs' uppercase className='flex-1 text-white'>
|
||||
APY
|
||||
</Text>
|
||||
</div>
|
||||
@ -169,4 +217,4 @@ const CreditManager = () => {
|
||||
)
|
||||
}
|
||||
|
||||
export default CreditManager
|
||||
export default AccountDetails
|
96
components/Account/AccountManageOverlay.tsx
Normal file
@ -0,0 +1,96 @@
|
||||
import { useEffect } from 'react'
|
||||
|
||||
import Button from 'components/Button'
|
||||
import PlusIcon from 'components/Icons/add.svg'
|
||||
import ArrowDown from 'components/Icons/arrow-down.svg'
|
||||
import ArrowUp from 'components/Icons/arrow-up.svg'
|
||||
import ArrowsLeftRight from 'components/Icons/arrows-left-right.svg'
|
||||
import DeleteIcon from 'components/Icons/rubbish.svg'
|
||||
import Overlay from 'components/Overlay/Overlay'
|
||||
import OverlayAction from 'components/Overlay/OverlayLink'
|
||||
import Text from 'components/Text'
|
||||
import useCreateCreditAccount from 'hooks/mutations/useCreateCreditAccount'
|
||||
import useDeleteCreditAccount from 'hooks/mutations/useDeleteCreditAccount'
|
||||
import { useAccountDetailsStore, useModalStore } from 'stores'
|
||||
|
||||
interface Props {
|
||||
className?: string
|
||||
setShow: (show: boolean) => void
|
||||
show: boolean
|
||||
}
|
||||
|
||||
const AccountManageOverlay = ({ className, setShow, show }: Props) => {
|
||||
const selectedAccount = useAccountDetailsStore((s) => s.selectedAccount)
|
||||
|
||||
const { mutate: createCreditAccount, isLoading: isLoadingCreate } = useCreateCreditAccount()
|
||||
const { mutate: deleteCreditAccount, isLoading: isLoadingDelete } = useDeleteCreditAccount(
|
||||
selectedAccount || '',
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
useModalStore.setState({ createAccountModal: isLoadingCreate })
|
||||
}, [isLoadingCreate])
|
||||
|
||||
useEffect(() => {
|
||||
useModalStore.setState({ deleteAccountModal: isLoadingDelete })
|
||||
}, [isLoadingDelete])
|
||||
|
||||
return (
|
||||
<Overlay className={className} show={show} setShow={setShow}>
|
||||
<div className='flex w-[274px] flex-wrap'>
|
||||
<Text size='sm' uppercase={true} className='w-full px-4 pt-4 text-center text-accent-dark'>
|
||||
Manage
|
||||
</Text>
|
||||
<div className='flex w-full justify-between border-b border-b-black/10 p-4'>
|
||||
<Button
|
||||
className='flex w-[115px] items-center justify-center pl-0 pr-2'
|
||||
onClick={() => {
|
||||
useModalStore.setState({ fundAccountModal: true })
|
||||
setShow(false)
|
||||
}}
|
||||
>
|
||||
<span className='mr-1 w-3'>
|
||||
<ArrowUp />
|
||||
</span>
|
||||
Fund
|
||||
</Button>
|
||||
<Button
|
||||
className='flex w-[115px] items-center justify-center pl-0 pr-2'
|
||||
color='secondary'
|
||||
onClick={() => {
|
||||
useModalStore.setState({ withdrawModal: true })
|
||||
setShow(false)
|
||||
}}
|
||||
>
|
||||
<span className='mr-1 w-3'>
|
||||
<ArrowDown />
|
||||
</span>
|
||||
Withdraw
|
||||
</Button>
|
||||
</div>
|
||||
<div className='flex w-full flex-wrap p-4'>
|
||||
<OverlayAction
|
||||
setShow={setShow}
|
||||
text='Create New Account'
|
||||
onClick={createCreditAccount}
|
||||
icon={<PlusIcon />}
|
||||
/>
|
||||
<OverlayAction
|
||||
setShow={setShow}
|
||||
text='Close Account'
|
||||
onClick={deleteCreditAccount}
|
||||
icon={<DeleteIcon />}
|
||||
/>
|
||||
<OverlayAction
|
||||
setShow={setShow}
|
||||
text='Transfer Balance'
|
||||
onClick={() => alert('TODO')}
|
||||
icon={<ArrowsLeftRight />}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</Overlay>
|
||||
)
|
||||
}
|
||||
|
||||
export default AccountManageOverlay
|
109
components/Account/AccountNavigation.tsx
Normal file
@ -0,0 +1,109 @@
|
||||
import classNames from 'classnames'
|
||||
import { useMemo, useState } from 'react'
|
||||
|
||||
import Button from 'components/Button'
|
||||
import ChevronDownIcon from 'components/Icons/chevron-down.svg'
|
||||
import Overlay from 'components/Overlay/Overlay'
|
||||
import { useAccountDetailsStore } from 'stores'
|
||||
|
||||
import AccountManageOverlay from './AccountManageOverlay'
|
||||
|
||||
interface Props {
|
||||
creditAccountsList: string[]
|
||||
selectedAccount: string | null
|
||||
}
|
||||
|
||||
const MAX_VISIBLE_CREDIT_ACCOUNTS = 5
|
||||
|
||||
const AccountNavigation = ({ creditAccountsList, selectedAccount }: Props) => {
|
||||
const { firstCreditAccounts, restCreditAccounts } = useMemo(() => {
|
||||
return {
|
||||
firstCreditAccounts: creditAccountsList?.slice(0, MAX_VISIBLE_CREDIT_ACCOUNTS) ?? [],
|
||||
restCreditAccounts: creditAccountsList?.slice(MAX_VISIBLE_CREDIT_ACCOUNTS) ?? [],
|
||||
}
|
||||
}, [creditAccountsList])
|
||||
|
||||
const [showManageMenu, setShowManageMenu] = useState(false)
|
||||
const [showMoreMenu, setShowMoreMenu] = useState(false)
|
||||
|
||||
return (
|
||||
<>
|
||||
{firstCreditAccounts.map((account) => (
|
||||
<Button
|
||||
key={account}
|
||||
className={classNames(
|
||||
'cursor-pointer whitespace-nowrap px-4 text-base hover:text-white',
|
||||
selectedAccount === account ? 'text-white' : 'text-white/40',
|
||||
)}
|
||||
variant='text'
|
||||
onClick={() => {
|
||||
useAccountDetailsStore.setState({ selectedAccount: account, isOpen: true })
|
||||
}}
|
||||
>
|
||||
Account {account}
|
||||
</Button>
|
||||
))}
|
||||
<div className='relative'>
|
||||
{restCreditAccounts.length > 0 && (
|
||||
<>
|
||||
<Button
|
||||
className='flex items-center px-3 py-3 text-base hover:text-white'
|
||||
variant='text'
|
||||
onClick={() => setShowMoreMenu(!showMoreMenu)}
|
||||
>
|
||||
More
|
||||
<span className='ml-1 inline-block w-3'>
|
||||
<ChevronDownIcon />
|
||||
</span>
|
||||
</Button>
|
||||
<Overlay show={showMoreMenu} setShow={setShowMoreMenu}>
|
||||
<div className='flex w-[120px] flex-wrap p-4'>
|
||||
{restCreditAccounts.map((account) => (
|
||||
<Button
|
||||
key={account}
|
||||
variant='text'
|
||||
className={classNames(
|
||||
'w-full whitespace-nowrap py-2 text-sm',
|
||||
selectedAccount === account
|
||||
? 'text-secondary'
|
||||
: 'cursor-pointer text-accent-dark hover:text-secondary',
|
||||
)}
|
||||
onClick={() => {
|
||||
setShowMoreMenu(!showMoreMenu)
|
||||
useAccountDetailsStore.setState({ selectedAccount: account, isOpen: true })
|
||||
}}
|
||||
>
|
||||
Account {account}
|
||||
</Button>
|
||||
))}
|
||||
</div>
|
||||
</Overlay>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
<div className='relative'>
|
||||
<Button
|
||||
className={classNames(
|
||||
'flex items-center px-3 py-3 text-base hover:text-white',
|
||||
showManageMenu ? 'text-white' : 'text-white/40',
|
||||
)}
|
||||
onClick={() => setShowManageMenu(!showManageMenu)}
|
||||
variant='text'
|
||||
>
|
||||
Manage
|
||||
<span className='ml-1 inline-block w-3'>
|
||||
<ChevronDownIcon />
|
||||
</span>
|
||||
</Button>
|
||||
|
||||
<AccountManageOverlay
|
||||
className='-left-[86px]'
|
||||
show={showManageMenu}
|
||||
setShow={setShowManageMenu}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default AccountNavigation
|
@ -1,22 +1,26 @@
|
||||
import BigNumber from 'bignumber.js'
|
||||
import { useEffect } from 'react'
|
||||
|
||||
import { BorrowCapacity } from 'components/BorrowCapacity'
|
||||
import Button from 'components/Button'
|
||||
import FormattedNumber from 'components/FormattedNumber'
|
||||
import Gauge from 'components/Gauge'
|
||||
import Text from 'components/Text'
|
||||
import useCreateCreditAccount from 'hooks/mutations/useCreateCreditAccount'
|
||||
import useAccountStats from 'hooks/useAccountStats'
|
||||
import useCreditAccounts from 'hooks/useCreditAccounts'
|
||||
import { useModalStore } from 'stores'
|
||||
import { chain } from 'utils/chains'
|
||||
import { formatValue } from 'utils/formatters'
|
||||
|
||||
interface Props {
|
||||
createCreditAccount: () => void
|
||||
}
|
||||
|
||||
const AccountStatus = ({ createCreditAccount }: Props) => {
|
||||
const AccountStatus = () => {
|
||||
const accountStats = useAccountStats()
|
||||
const { data: creditAccountsList, isLoading: isLoadingCreditAccounts } = useCreditAccounts()
|
||||
const { data: creditAccountsList } = useCreditAccounts()
|
||||
const { mutate: createCreditAccount, isLoading: isLoadingCreate } = useCreateCreditAccount()
|
||||
useEffect(() => {
|
||||
useModalStore.setState({ createAccountModal: isLoadingCreate })
|
||||
}, [isLoadingCreate])
|
||||
|
||||
const hasCreditAccounts = creditAccountsList && creditAccountsList.length > 0
|
||||
|
||||
if (!hasCreditAccounts) {
|
||||
|
24
components/Account/ConfirmModal.tsx
Normal file
@ -0,0 +1,24 @@
|
||||
import CircularProgress from 'components/CircularProgress'
|
||||
import Modal from 'components/Modal'
|
||||
import Text from 'components/Text'
|
||||
import { useModalStore } from 'stores'
|
||||
|
||||
const ConfirmModal = () => {
|
||||
const createOpen = useModalStore((s) => s.createAccountModal)
|
||||
const deleteOpen = useModalStore((s) => s.deleteAccountModal)
|
||||
|
||||
return (
|
||||
<Modal open={createOpen || deleteOpen}>
|
||||
<div className='w-full p-6'>
|
||||
<Text size='2xl' uppercase={true} className='mb-6 w-full text-center'>
|
||||
Confirm Transaction
|
||||
</Text>
|
||||
<div className='flex w-full justify-center pb-6'>
|
||||
<CircularProgress size={40} />
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
)
|
||||
}
|
||||
|
||||
export default ConfirmModal
|
@ -13,24 +13,29 @@ import Text from 'components/Text'
|
||||
import useDepositCreditAccount from 'hooks/mutations/useDepositCreditAccount'
|
||||
import useAllBalances from 'hooks/useAllBalances'
|
||||
import useAllowedCoins from 'hooks/useAllowedCoins'
|
||||
import useCreditManagerStore from 'stores/useCreditManagerStore'
|
||||
import { useAccountDetailsStore, useModalStore } from 'stores'
|
||||
import { getTokenDecimals, getTokenSymbol } from 'utils/tokens'
|
||||
|
||||
interface Props {
|
||||
open: boolean
|
||||
setOpen: (open: boolean) => void
|
||||
}
|
||||
|
||||
const FundAccountModal = ({ open, setOpen }: Props) => {
|
||||
const [amount, setAmount] = useState(0)
|
||||
const [selectedToken, setSelectedToken] = useState('')
|
||||
|
||||
const selectedAccount = useCreditManagerStore((s) => s.selectedAccount)
|
||||
const FundAccountModal = () => {
|
||||
// ---------------
|
||||
// STORE
|
||||
// ---------------
|
||||
const open = useModalStore((s) => s.fundAccountModal)
|
||||
|
||||
const selectedAccount = useAccountDetailsStore((s) => s.selectedAccount)
|
||||
const [lendAssets, setLendAssets] = useLocalStorageState(`lendAssets_${selectedAccount}`, {
|
||||
defaultValue: false,
|
||||
})
|
||||
|
||||
// ---------------
|
||||
// LOCAL STATE
|
||||
// ---------------
|
||||
const [amount, setAmount] = useState(0)
|
||||
const [selectedToken, setSelectedToken] = useState('')
|
||||
|
||||
// ---------------
|
||||
// EXTERNAL HOOKS
|
||||
// ---------------
|
||||
const { data: balancesData } = useAllBalances()
|
||||
const { data: allowedCoinsData, isLoading: isLoadingAllowedCoins } = useAllowedCoins()
|
||||
const { mutate, isLoading } = useDepositCreditAccount(
|
||||
@ -43,7 +48,7 @@ const FundAccountModal = ({ open, setOpen }: Props) => {
|
||||
onSuccess: () => {
|
||||
setAmount(0)
|
||||
toast.success(`${amount} ${getTokenSymbol(selectedToken)} successfully Deposited`)
|
||||
setOpen(false)
|
||||
useModalStore.setState({ fundAccountModal: false })
|
||||
},
|
||||
},
|
||||
)
|
||||
@ -72,6 +77,10 @@ const FundAccountModal = ({ open, setOpen }: Props) => {
|
||||
setAmount(value)
|
||||
}
|
||||
|
||||
const setOpen = (open: boolean) => {
|
||||
useModalStore.setState({ fundAccountModal: open })
|
||||
}
|
||||
|
||||
const maxValue = walletAmount
|
||||
const percentageValue = isNaN(amount) ? 0 : (amount * 100) / maxValue
|
||||
|
||||
@ -86,7 +95,7 @@ const FundAccountModal = ({ open, setOpen }: Props) => {
|
||||
|
||||
<div className='flex flex-1 flex-col items-start justify-between bg-fund-modal bg-cover p-6'>
|
||||
<div>
|
||||
<Text size='2xs' uppercase={true} className='mb-3 text-white'>
|
||||
<Text size='2xs' uppercase className='mb-3 text-white'>
|
||||
About
|
||||
</Text>
|
||||
<Text size='xl' className='mb-4 text-white'>
|
||||
@ -101,11 +110,11 @@ const FundAccountModal = ({ open, setOpen }: Props) => {
|
||||
</div>
|
||||
|
||||
<div className='flex flex-1 flex-col p-6'>
|
||||
<Text size='xl' uppercase={true} className='mb-4 text-white'>
|
||||
<Text size='xl' uppercase className='mb-4 text-white'>
|
||||
Account {selectedAccount}
|
||||
</Text>
|
||||
<div className='p-3" mb-2'>
|
||||
<Text size='sm' uppercase={true} className='mb-1 text-white'>
|
||||
<Text size='sm' uppercase className='mb-1 text-white'>
|
||||
Fund Account
|
||||
</Text>
|
||||
<Text size='sm' className='mb-6 text-white/60'>
|
||||
@ -154,7 +163,7 @@ const FundAccountModal = ({ open, setOpen }: Props) => {
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<Text size='xs' uppercase={true} className='mb-2 text-white/60'>
|
||||
<Text size='xs' uppercase className='mb-2 text-white/60'>
|
||||
{`In wallet: ${walletAmount.toLocaleString()} ${getTokenSymbol(selectedToken)}`}
|
||||
</Text>
|
||||
<Slider
|
||||
@ -175,7 +184,7 @@ const FundAccountModal = ({ open, setOpen }: Props) => {
|
||||
</div>
|
||||
<div className='mb-2 flex items-center justify-between'>
|
||||
<div>
|
||||
<Text size='sm' uppercase={true} className='mb-1 text-white'>
|
||||
<Text size='sm' uppercase className='mb-1 text-white'>
|
||||
Lending Assets
|
||||
</Text>
|
||||
<Text size='sm' className='text-white/60'>
|
||||
|
@ -1,191 +0,0 @@
|
||||
import { ExecuteResult } from '@cosmjs/cosmwasm-stargate'
|
||||
import { UseMutateFunction } from '@tanstack/react-query'
|
||||
import classNames from 'classnames'
|
||||
import { useMemo, useState } from 'react'
|
||||
|
||||
import { FundAccountModal, WithdrawModal } from 'components/Account'
|
||||
import Button from 'components/Button'
|
||||
import ArrowDown from 'components/Icons/arrow-down.svg'
|
||||
import ArrowUp from 'components/Icons/arrow-up.svg'
|
||||
import ChevronDownIcon from 'components/Icons/expand.svg'
|
||||
import Overlay from 'components/Overlay'
|
||||
import Text from 'components/Text'
|
||||
|
||||
interface Props {
|
||||
creditAccountsList: string[]
|
||||
selectedAccount: string | null
|
||||
deleteCreditAccount: UseMutateFunction<ExecuteResult | undefined, Error, void, unknown>
|
||||
setSelectedAccount: (id: string) => void
|
||||
createCreditAccount: () => void
|
||||
}
|
||||
|
||||
const MAX_VISIBLE_CREDIT_ACCOUNTS = 5
|
||||
|
||||
const SubAccountNavigation = ({
|
||||
creditAccountsList,
|
||||
createCreditAccount,
|
||||
deleteCreditAccount,
|
||||
selectedAccount,
|
||||
setSelectedAccount,
|
||||
}: Props) => {
|
||||
const { firstCreditAccounts, restCreditAccounts } = useMemo(() => {
|
||||
return {
|
||||
firstCreditAccounts: creditAccountsList?.slice(0, MAX_VISIBLE_CREDIT_ACCOUNTS) ?? [],
|
||||
restCreditAccounts: creditAccountsList?.slice(MAX_VISIBLE_CREDIT_ACCOUNTS) ?? [],
|
||||
}
|
||||
}, [creditAccountsList])
|
||||
|
||||
const [showManageMenu, setShowManageMenu] = useState(false)
|
||||
const [showMoreMenu, setShowMoreMenu] = useState(false)
|
||||
const [showFundWalletModal, setShowFundWalletModal] = useState(false)
|
||||
const [showWithdrawModal, setShowWithdrawModal] = useState(false)
|
||||
|
||||
return (
|
||||
<>
|
||||
{firstCreditAccounts.map((account) => (
|
||||
<Button
|
||||
key={account}
|
||||
className={classNames(
|
||||
'cursor-pointer whitespace-nowrap px-4 text-base hover:text-white',
|
||||
selectedAccount === account ? 'text-white' : ' text-white/40',
|
||||
)}
|
||||
variant='text'
|
||||
onClick={() => setSelectedAccount(account)}
|
||||
>
|
||||
Account {account}
|
||||
</Button>
|
||||
))}
|
||||
<div className='relative'>
|
||||
{restCreditAccounts.length > 0 && (
|
||||
<>
|
||||
<Button
|
||||
className='flex items-center px-3 py-3 text-base hover:text-white'
|
||||
variant='text'
|
||||
onClick={() => setShowMoreMenu(!showMoreMenu)}
|
||||
>
|
||||
More
|
||||
<span className='ml-1 inline-block w-3'>
|
||||
<ChevronDownIcon />
|
||||
</span>
|
||||
</Button>
|
||||
<Overlay show={showMoreMenu} setShow={setShowMoreMenu}>
|
||||
<div className='flex w-[120px] flex-wrap p-4'>
|
||||
{restCreditAccounts.map((account) => (
|
||||
<Button
|
||||
key={account}
|
||||
variant='text'
|
||||
className={classNames(
|
||||
'w-full whitespace-nowrap py-2 text-sm',
|
||||
selectedAccount === account
|
||||
? 'text-secondary'
|
||||
: 'cursor-pointer text-accent-dark hover:text-secondary',
|
||||
)}
|
||||
onClick={() => {
|
||||
setShowMoreMenu(!showMoreMenu)
|
||||
setSelectedAccount(account)
|
||||
}}
|
||||
>
|
||||
Account {account}
|
||||
</Button>
|
||||
))}
|
||||
</div>
|
||||
</Overlay>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
<div className='relative'>
|
||||
<Button
|
||||
className={classNames(
|
||||
'flex items-center px-3 py-3 text-base hover:text-white',
|
||||
showManageMenu ? 'text-white' : 'text-white/40',
|
||||
)}
|
||||
onClick={() => setShowManageMenu(!showManageMenu)}
|
||||
variant='text'
|
||||
>
|
||||
Manage
|
||||
<span className='ml-1 inline-block w-3'>
|
||||
<ChevronDownIcon />
|
||||
</span>
|
||||
</Button>
|
||||
<Overlay className='-left-[86px]' show={showManageMenu} setShow={setShowManageMenu}>
|
||||
<div className='flex w-[274px] flex-wrap'>
|
||||
<Text
|
||||
size='sm'
|
||||
uppercase={true}
|
||||
className='w-full px-4 pt-4 text-center text-accent-dark'
|
||||
>
|
||||
Manage
|
||||
</Text>
|
||||
<div className='flex w-full justify-between border-b border-b-black/10 p-4'>
|
||||
<Button
|
||||
className='flex w-[115px] items-center justify-center pl-0 pr-2'
|
||||
onClick={() => {
|
||||
setShowFundWalletModal(true)
|
||||
setShowManageMenu(!showManageMenu)
|
||||
}}
|
||||
>
|
||||
<span className='mr-1 w-3'>
|
||||
<ArrowUp />
|
||||
</span>
|
||||
Fund
|
||||
</Button>
|
||||
<Button
|
||||
className='flex w-[115px] items-center justify-center pl-0 pr-2'
|
||||
color='secondary'
|
||||
onClick={() => {
|
||||
setShowWithdrawModal(true)
|
||||
setShowManageMenu(!showManageMenu)
|
||||
}}
|
||||
>
|
||||
<span className='mr-1 w-3'>
|
||||
<ArrowDown />
|
||||
</span>
|
||||
Withdraw
|
||||
</Button>
|
||||
</div>
|
||||
<div className='flex w-full flex-wrap p-4'>
|
||||
<Button
|
||||
className='w-full cursor-pointer whitespace-nowrap py-2 text-left text-sm text-accent-dark hover:text-secondary'
|
||||
variant='text'
|
||||
onClick={() => {
|
||||
setShowManageMenu(!showManageMenu)
|
||||
createCreditAccount()
|
||||
}}
|
||||
>
|
||||
Create Account
|
||||
</Button>
|
||||
<Button
|
||||
className='w-full cursor-pointer whitespace-nowrap py-2 text-left text-sm text-accent-dark hover:text-secondary'
|
||||
variant='text'
|
||||
onClick={() => {
|
||||
setShowManageMenu(!showManageMenu)
|
||||
deleteCreditAccount()
|
||||
}}
|
||||
>
|
||||
Close Account
|
||||
</Button>
|
||||
<Button
|
||||
className='w-full cursor-pointer whitespace-nowrap py-2 text-left text-sm text-accent-dark hover:text-secondary'
|
||||
variant='text'
|
||||
onClick={() => alert('TODO')}
|
||||
>
|
||||
Transfer Balance
|
||||
</Button>
|
||||
<Button
|
||||
className='w-full cursor-pointer whitespace-nowrap py-2 text-left text-sm text-accent-dark hover:text-secondary'
|
||||
variant='text'
|
||||
onClick={() => alert('TODO')}
|
||||
>
|
||||
Rearrange
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</Overlay>
|
||||
</div>
|
||||
<FundAccountModal open={showFundWalletModal} setOpen={setShowFundWalletModal} />
|
||||
<WithdrawModal open={showWithdrawModal} setOpen={setShowWithdrawModal} />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default SubAccountNavigation
|
@ -19,25 +19,32 @@ import useCalculateMaxWithdrawAmount from 'hooks/useCalculateMaxWithdrawAmount'
|
||||
import useCreditAccountPositions from 'hooks/useCreditAccountPositions'
|
||||
import useMarkets from 'hooks/useMarkets'
|
||||
import useTokenPrices from 'hooks/useTokenPrices'
|
||||
import useCreditManagerStore from 'stores/useCreditManagerStore'
|
||||
import { useAccountDetailsStore, useModalStore } from 'stores'
|
||||
import { chain } from 'utils/chains'
|
||||
import { formatValue } from 'utils/formatters'
|
||||
import { getTokenDecimals, getTokenSymbol } from 'utils/tokens'
|
||||
interface Props {
|
||||
open: boolean
|
||||
setOpen: (open: boolean) => void
|
||||
}
|
||||
|
||||
const WithdrawModal = ({ open, setOpen }: Props) => {
|
||||
const [amount, setAmount] = useState(0)
|
||||
const [selectedToken, setSelectedToken] = useState('')
|
||||
const [isBorrowEnabled, setIsBorrowEnabled] = useState(false)
|
||||
const WithdrawModal = () => {
|
||||
// ---------------
|
||||
// STORE
|
||||
// ---------------
|
||||
const open = useModalStore((s) => s.withdrawModal)
|
||||
|
||||
const selectedAccount = useCreditManagerStore((s) => s.selectedAccount)
|
||||
const selectedAccount = useAccountDetailsStore((s) => s.selectedAccount)
|
||||
const { data: positionsData, isLoading: isLoadingPositions } = useCreditAccountPositions(
|
||||
selectedAccount ?? '',
|
||||
)
|
||||
|
||||
// ---------------
|
||||
// LOCAL STATE
|
||||
// ---------------
|
||||
const [amount, setAmount] = useState(0)
|
||||
const [selectedToken, setSelectedToken] = useState('')
|
||||
const [isBorrowEnabled, setIsBorrowEnabled] = useState(false)
|
||||
|
||||
// ---------------
|
||||
// EXTERNAL HOOKS
|
||||
// ---------------
|
||||
const { data: balancesData } = useAllBalances()
|
||||
const { data: tokenPrices } = useTokenPrices()
|
||||
const { data: marketsData } = useMarkets()
|
||||
@ -86,7 +93,7 @@ const WithdrawModal = ({ open, setOpen }: Props) => {
|
||||
|
||||
const { mutate, isLoading } = useWithdrawFunds(withdrawAmount, borrowAmount, selectedToken, {
|
||||
onSuccess: () => {
|
||||
setOpen(false)
|
||||
useModalStore.setState({ withdrawModal: false })
|
||||
toast.success(`${amount} ${selectedTokenSymbol} successfully withdrawn`)
|
||||
},
|
||||
})
|
||||
@ -146,6 +153,10 @@ const WithdrawModal = ({ open, setOpen }: Props) => {
|
||||
return (amount * 100) / maxWithdrawAmount
|
||||
}, [amount, maxWithdrawAmount])
|
||||
|
||||
const setOpen = (open: boolean) => {
|
||||
useModalStore.setState({ withdrawModal: open })
|
||||
}
|
||||
|
||||
return (
|
||||
<Modal open={open} setOpen={setOpen}>
|
||||
<div className='flex min-h-[470px] w-full flex-wrap'>
|
||||
@ -158,7 +169,7 @@ const WithdrawModal = ({ open, setOpen }: Props) => {
|
||||
<Text
|
||||
className='flex w-full border-b border-white/20 px-8 pt-4 pb-2 text-white'
|
||||
size='2xl'
|
||||
uppercase={true}
|
||||
uppercase
|
||||
>
|
||||
Withdraw from Account {selectedAccount}
|
||||
</Text>
|
||||
@ -198,7 +209,7 @@ const WithdrawModal = ({ open, setOpen }: Props) => {
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<Text size='xs' uppercase={true} className='mb-2 text-white/60'>
|
||||
<Text size='xs' uppercase className='mb-2 text-white/60'>
|
||||
Available: {formatValue(maxWithdrawAmount, 0, 4, true, false, false, false, false)}
|
||||
</Text>
|
||||
<Slider
|
||||
@ -218,7 +229,7 @@ const WithdrawModal = ({ open, setOpen }: Props) => {
|
||||
</div>
|
||||
<div className='flex items-center justify-between p-6'>
|
||||
<div className='flex flex-1 flex-wrap'>
|
||||
<Text size='sm' className='text-white' uppercase={true}>
|
||||
<Text size='sm' className='text-white' uppercase>
|
||||
Withdraw with borrowing
|
||||
</Text>
|
||||
<Text size='sm' className='text-white/60'>
|
||||
@ -330,7 +341,7 @@ const WithdrawModal = ({ open, setOpen }: Props) => {
|
||||
</div>
|
||||
</div>
|
||||
<div className='flex w-full flex-wrap'>
|
||||
<Text uppercase={true} className='w-full bg-black/20 px-6 py-2 text-white/40'>
|
||||
<Text uppercase className='w-full bg-black/20 px-6 py-2 text-white/40'>
|
||||
Balances
|
||||
</Text>
|
||||
{isLoadingPositions ? (
|
||||
@ -338,16 +349,16 @@ const WithdrawModal = ({ open, setOpen }: Props) => {
|
||||
) : (
|
||||
<div className='flex w-full flex-wrap'>
|
||||
<div className='mb-2 flex w-full border-b border-white/20 bg-black/20 px-6 py-2 '>
|
||||
<Text size='xs' uppercase={true} className='flex-1 text-white'>
|
||||
<Text size='xs' uppercase className='flex-1 text-white'>
|
||||
Asset
|
||||
</Text>
|
||||
<Text size='xs' uppercase={true} className='flex-1 text-white'>
|
||||
<Text size='xs' uppercase className='flex-1 text-white'>
|
||||
Value
|
||||
</Text>
|
||||
<Text size='xs' uppercase={true} className='flex-1 text-white'>
|
||||
<Text size='xs' uppercase className='flex-1 text-white'>
|
||||
Size
|
||||
</Text>
|
||||
<Text size='xs' uppercase={true} className='flex-1 text-white'>
|
||||
<Text size='xs' uppercase className='flex-1 text-white'>
|
||||
APY
|
||||
</Text>
|
||||
</div>
|
||||
|
@ -1,4 +1,7 @@
|
||||
export { default as AccountDetails } from './AccountDetails'
|
||||
export { default as AccountManageOverlay } from './AccountManageOverlay'
|
||||
export { default as AccountNavigation } from './AccountNavigation'
|
||||
export { default as AccountStatus } from './AccountStatus'
|
||||
export { default as ConfirmModal } from './ConfirmModal'
|
||||
export { default as FundAccountModal } from './FundAccountModal'
|
||||
export { default as SubAccountNavigation } from './SubAccountNavigation'
|
||||
export { default as WithdrawModal } from './WithdrawModal'
|
||||
|
@ -1,8 +1,8 @@
|
||||
import Image from 'next/image'
|
||||
import React, { useState } from 'react'
|
||||
|
||||
import ChevronUpIcon from 'components/Icons/collapse.svg'
|
||||
import ChevronDownIcon from 'components/Icons/expand.svg'
|
||||
import ChevronUpIcon from 'components/Icons/chevron-up.svg'
|
||||
import ChevronDownIcon from 'components/Icons/chevron-down.svg'
|
||||
import Button from 'components/Button'
|
||||
import { formatCurrency } from 'utils/formatters'
|
||||
|
||||
|
@ -9,8 +9,8 @@ import {
|
||||
import Image from 'next/image'
|
||||
import React from 'react'
|
||||
|
||||
import ChevronUpIcon from 'components/Icons/collapse.svg'
|
||||
import ChevronDownIcon from 'components/Icons/expand.svg'
|
||||
import ChevronUpIcon from 'components/Icons/chevron-up.svg'
|
||||
import ChevronDownIcon from 'components/Icons/chevron-down.svg'
|
||||
import { formatCurrency } from 'utils/formatters'
|
||||
|
||||
import AssetRow from './AssetRow'
|
||||
|
@ -19,7 +19,7 @@ import useCalculateMaxBorrowAmount from 'hooks/useCalculateMaxBorrowAmount'
|
||||
import useCreditAccountPositions from 'hooks/useCreditAccountPositions'
|
||||
import useMarkets from 'hooks/useMarkets'
|
||||
import useTokenPrices from 'hooks/useTokenPrices'
|
||||
import useCreditManagerStore from 'stores/useCreditManagerStore'
|
||||
import { useAccountDetailsStore } from 'stores'
|
||||
import { chain } from 'utils/chains'
|
||||
import { formatCurrency, formatValue } from 'utils/formatters'
|
||||
import { getTokenDecimals, getTokenSymbol } from 'utils/tokens'
|
||||
@ -34,7 +34,7 @@ const BorrowModal = ({ show, onClose, tokenDenom }: Props) => {
|
||||
const [amount, setAmount] = useState(0)
|
||||
const [isBorrowToCreditAccount, setIsBorrowToCreditAccount] = useState(false)
|
||||
|
||||
const selectedAccount = useCreditManagerStore((s) => s.selectedAccount)
|
||||
const selectedAccount = useAccountDetailsStore((s) => s.selectedAccount)
|
||||
const { data: positionsData, isLoading: isLoadingPositions } = useCreditAccountPositions(
|
||||
selectedAccount ?? '',
|
||||
)
|
||||
@ -250,7 +250,7 @@ const BorrowModal = ({ show, onClose, tokenDenom }: Props) => {
|
||||
|
||||
<div className='flex w-1/2 flex-col justify-center bg-[#4A4C60] p-4'>
|
||||
<p className='text-bold mb-3 text-xs uppercase text-white/50'>About</p>
|
||||
<h4 className='mb-4 text-xl'>Subaccount {selectedAccount}</h4>
|
||||
<h4 className='mb-4 text-xl'>Account {selectedAccount}</h4>
|
||||
<div className='mb-2 rounded-md border border-white/20 p-3'>
|
||||
{accountStats && (
|
||||
<div className='flex items-center gap-x-3'>
|
||||
|
@ -16,7 +16,7 @@ interface Props {
|
||||
onClick?: (e: React.MouseEvent<HTMLButtonElement>) => void
|
||||
}
|
||||
|
||||
const colorClasses = {
|
||||
export const buttonColorClasses = {
|
||||
primary:
|
||||
'border-none text-white bg-primary hover:bg-primary-highlight active:bg-primary-highlight-10 focus:bg-primary-highlight',
|
||||
secondary:
|
||||
@ -27,7 +27,7 @@ const colorClasses = {
|
||||
'border bg-transparent text-white/60 border-transparent hover:text-white hover:border-white active:text-white active:border-white',
|
||||
}
|
||||
|
||||
const transparentColorClasses = {
|
||||
const buttonTransparentColorClasses = {
|
||||
primary:
|
||||
'border-none text-primary hover:text-primary-highlight active:text-primary-highlight focus:text-primary-highlight',
|
||||
secondary:
|
||||
@ -38,19 +38,19 @@ const transparentColorClasses = {
|
||||
'border border-transparent text-white/60 hover:text-white hover:border-white active:text-white active:border-white',
|
||||
}
|
||||
|
||||
const roundSizeClasses = {
|
||||
const buttonRoundSizeClasses = {
|
||||
small: 'h-[32px] w-[32px]',
|
||||
medium: 'h-[40px] w-[40px]',
|
||||
large: 'h-[56px] w-[56px]',
|
||||
}
|
||||
|
||||
const sizeClasses = {
|
||||
export const buttonSizeClasses = {
|
||||
small: 'text-sm px-5 py-1.5 min-h-[32px]',
|
||||
medium: 'text-base px-6 py-2.5 min-h-[40px]',
|
||||
large: 'text-lg px-6 py-2.5 min-h-[56px]',
|
||||
}
|
||||
|
||||
const variantClasses = {
|
||||
export const buttonVariantClasses = {
|
||||
solid: 'text-white',
|
||||
transparent: 'bg-transparent p-0',
|
||||
round: 'rounded-full p-0',
|
||||
@ -76,15 +76,19 @@ const Button = React.forwardRef(function Button(
|
||||
|
||||
switch (variant) {
|
||||
case 'round':
|
||||
buttonClasses.push(sizeClasses[size], roundSizeClasses[size], colorClasses[color])
|
||||
buttonClasses.push(
|
||||
buttonSizeClasses[size],
|
||||
buttonRoundSizeClasses[size],
|
||||
buttonColorClasses[color],
|
||||
)
|
||||
break
|
||||
|
||||
case 'transparent':
|
||||
buttonClasses.push(sizeClasses[size], transparentColorClasses[color])
|
||||
buttonClasses.push(buttonSizeClasses[size], buttonTransparentColorClasses[color])
|
||||
break
|
||||
|
||||
case 'solid':
|
||||
buttonClasses.push(sizeClasses[size], colorClasses[color])
|
||||
buttonClasses.push(buttonSizeClasses[size], buttonColorClasses[color])
|
||||
break
|
||||
default:
|
||||
}
|
||||
@ -94,6 +98,7 @@ const Button = React.forwardRef(function Button(
|
||||
className={classNames(
|
||||
'cursor-pointer appearance-none break-normal rounded-3xl outline-none transition-colors',
|
||||
buttonClasses,
|
||||
buttonVariantClasses[variant],
|
||||
disabled && 'pointer-events-none opacity-50',
|
||||
className,
|
||||
)}
|
||||
|
@ -1,192 +0,0 @@
|
||||
import { Dialog, Transition } from '@headlessui/react'
|
||||
import Image from 'next/image'
|
||||
import { Fragment, useState } from 'react'
|
||||
import { toast } from 'react-toastify'
|
||||
|
||||
import useWalletStore from 'stores/useWalletStore'
|
||||
import { Wallet } from 'types'
|
||||
import { getInjectiveAddress } from 'utils/address'
|
||||
import { chain } from 'utils/chains'
|
||||
import { getExperimentalChainConfigBasedOnChainId } from 'utils/experimental-chains'
|
||||
|
||||
type Props = {
|
||||
isOpen: boolean
|
||||
onClose: () => void
|
||||
}
|
||||
|
||||
const ConnectModal = ({ isOpen, onClose }: Props) => {
|
||||
const [isLoading, setIsLoading] = useState(false)
|
||||
|
||||
const actions = useWalletStore((s) => s.actions)
|
||||
const metamaskInstalled = useWalletStore((s) => s.metamaskInstalled)
|
||||
const isKeplrInstalled = typeof window !== 'undefined' && window.keplr
|
||||
|
||||
const handleConnectSuccess = () => {
|
||||
onClose()
|
||||
|
||||
// defering update on loading state to avoid updating before close animation is finished
|
||||
setTimeout(() => {
|
||||
setIsLoading(false)
|
||||
}, 500)
|
||||
}
|
||||
|
||||
const handleConnectKeplr = async () => {
|
||||
if (!window.keplr) {
|
||||
toast.error('You need Keplr extension installed')
|
||||
return
|
||||
}
|
||||
|
||||
setIsLoading(true)
|
||||
|
||||
try {
|
||||
const chainData = getExperimentalChainConfigBasedOnChainId(chain.chainId)
|
||||
|
||||
if (chainData) {
|
||||
await window.keplr.experimentalSuggestChain(chainData)
|
||||
}
|
||||
|
||||
const key = await window.keplr.getKey(chain.chainId)
|
||||
actions.connect(key.bech32Address, Wallet.Keplr)
|
||||
|
||||
handleConnectSuccess()
|
||||
} catch (e) {
|
||||
// TODO: handle exception
|
||||
console.log(e)
|
||||
setIsLoading(false)
|
||||
}
|
||||
}
|
||||
|
||||
const handleConnectMetamask = async () => {
|
||||
if (!metamaskInstalled) {
|
||||
toast.error('You need Metamask extension installed')
|
||||
return
|
||||
}
|
||||
|
||||
setIsLoading(true)
|
||||
|
||||
try {
|
||||
// TODO: missing type definitions
|
||||
const addresses = await (window.ethereum as any).request({
|
||||
method: 'eth_requestAccounts',
|
||||
})
|
||||
const [address] = addresses
|
||||
actions.connect(getInjectiveAddress(address), Wallet.Metamask)
|
||||
handleConnectSuccess()
|
||||
} catch (e) {
|
||||
// TODO: handle exception
|
||||
console.log(e)
|
||||
setIsLoading(false)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Transition appear show={isOpen} as={Fragment}>
|
||||
<Dialog as='div' className='relative z-10' onClose={onClose}>
|
||||
<Transition.Child
|
||||
as={Fragment}
|
||||
enter='ease-out duration-300'
|
||||
enterFrom='opacity-0'
|
||||
enterTo='opacity-100'
|
||||
leave='ease-in duration-200'
|
||||
leaveFrom='opacity-100'
|
||||
leaveTo='opacity-0'
|
||||
>
|
||||
<div className='fixed inset-0 bg-black bg-opacity-40' />
|
||||
</Transition.Child>
|
||||
|
||||
<div className='fixed inset-0 overflow-y-auto'>
|
||||
<div className='flex min-h-full items-center justify-center p-4 text-center'>
|
||||
<Transition.Child
|
||||
as={Fragment}
|
||||
enter='ease-out duration-300'
|
||||
enterFrom='opacity-0 scale-95'
|
||||
enterTo='opacity-100 scale-100'
|
||||
leave='ease-in duration-200'
|
||||
leaveFrom='opacity-100 scale-100'
|
||||
leaveTo='opacity-0 scale-95'
|
||||
>
|
||||
<Dialog.Panel className='w-full max-w-md transform overflow-hidden rounded-2xl bg-white p-6 text-left align-middle shadow-xl transition-all'>
|
||||
<Dialog.Title as='h3' className='mb-6 text-lg font-medium leading-6 text-gray-900'>
|
||||
Connect your wallet
|
||||
</Dialog.Title>
|
||||
{isLoading ? (
|
||||
<div role='status' className='text-center'>
|
||||
<svg
|
||||
className='inline h-10 w-10 animate-spin fill-orange-500 text-gray-200'
|
||||
viewBox='0 0 100 101'
|
||||
fill='none'
|
||||
xmlns='http://www.w3.org/2000/svg'
|
||||
>
|
||||
<path
|
||||
d='M100 50.5908C100 78.2051 77.6142 100.591 50 100.591C22.3858 100.591 0 78.2051 0 50.5908C0 22.9766 22.3858 0.59082 50 0.59082C77.6142 0.59082 100 22.9766 100 50.5908ZM9.08144 50.5908C9.08144 73.1895 27.4013 91.5094 50 91.5094C72.5987 91.5094 90.9186 73.1895 90.9186 50.5908C90.9186 27.9921 72.5987 9.67226 50 9.67226C27.4013 9.67226 9.08144 27.9921 9.08144 50.5908Z'
|
||||
fill='currentColor'
|
||||
/>
|
||||
<path
|
||||
d='M93.9676 39.0409C96.393 38.4038 97.8624 35.9116 97.0079 33.5539C95.2932 28.8227 92.871 24.3692 89.8167 20.348C85.8452 15.1192 80.8826 10.7238 75.2124 7.41289C69.5422 4.10194 63.2754 1.94025 56.7698 1.05124C51.7666 0.367541 46.6976 0.446843 41.7345 1.27873C39.2613 1.69328 37.813 4.19778 38.4501 6.62326C39.0873 9.04874 41.5694 10.4717 44.0505 10.1071C47.8511 9.54855 51.7191 9.52689 55.5402 10.0491C60.8642 10.7766 65.9928 12.5457 70.6331 15.2552C75.2735 17.9648 79.3347 21.5619 82.5849 25.841C84.9175 28.9121 86.7997 32.2913 88.1811 35.8758C89.083 38.2158 91.5421 39.6781 93.9676 39.0409Z'
|
||||
fill='currentFill'
|
||||
/>
|
||||
</svg>
|
||||
<span className='sr-only'>Loading...</span>
|
||||
</div>
|
||||
) : (
|
||||
<div className='mt-2 flex flex-col gap-3'>
|
||||
<button
|
||||
className='flex items-center rounded-xl bg-black/90 p-4 hover:bg-black'
|
||||
onClick={handleConnectMetamask}
|
||||
// temporarily disable metamask connection as its not supported on osmosis
|
||||
disabled
|
||||
>
|
||||
<Image src='/wallets/metamask.webp' height={30} width={30} alt='metamask' />
|
||||
<div className='ml-4 text-left'>
|
||||
<div className='flex items-end'>
|
||||
<p>Metamask</p>
|
||||
{!metamaskInstalled && (
|
||||
<a
|
||||
className='ml-3 text-sm text-blue-600'
|
||||
onClick={(e) => {
|
||||
window.open('https://metamask.io/', '_blank')
|
||||
e.stopPropagation()
|
||||
}}
|
||||
>
|
||||
Install
|
||||
</a>
|
||||
)}
|
||||
</div>
|
||||
<p className='text-sm text-gray-400'>Connect using Metamask</p>
|
||||
</div>
|
||||
</button>
|
||||
<button
|
||||
className='flex items-center rounded-xl bg-black/90 p-4 hover:bg-black'
|
||||
onClick={handleConnectKeplr}
|
||||
>
|
||||
<Image src='/wallets/keplr.png' height={30} width={30} alt='keplr' />
|
||||
<div className='ml-4 text-left'>
|
||||
<div className='flex items-end'>
|
||||
<p>Keplr</p>
|
||||
{!isKeplrInstalled && (
|
||||
<a
|
||||
className='ml-3 text-sm text-blue-600'
|
||||
onClick={(e) => {
|
||||
window.open('https://www.keplr.app/', '_blank')
|
||||
e.stopPropagation()
|
||||
}}
|
||||
>
|
||||
Install
|
||||
</a>
|
||||
)}
|
||||
</div>
|
||||
<p className='text-sm text-gray-400'>Connect using Keplr</p>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
</Dialog.Panel>
|
||||
</Transition.Child>
|
||||
</div>
|
||||
</div>
|
||||
</Dialog>
|
||||
</Transition>
|
||||
)
|
||||
}
|
||||
|
||||
export default ConnectModal
|
3
components/Icons/arrows-left-right.svg
Normal file
@ -0,0 +1,3 @@
|
||||
<svg viewBox="0 0 14 8" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M13.6136 3.74679C13.5819 3.66496 13.5343 3.59019 13.4736 3.52679L10.8069 0.860124C10.7448 0.797965 10.671 0.748658 10.5898 0.715017C10.5085 0.681377 10.4215 0.664063 10.3336 0.664063C10.1561 0.664062 9.98579 0.734588 9.86026 0.860124C9.73472 0.985659 9.6642 1.15592 9.6642 1.33346C9.6642 1.51099 9.73472 1.68125 9.86026 1.80679L11.3936 3.33346H2.60692L4.14026 1.80679C4.20242 1.74463 4.25172 1.67084 4.28536 1.58962C4.319 1.50841 4.33632 1.42136 4.33632 1.33346C4.33632 1.24555 4.319 1.15851 4.28536 1.07729C4.25172 0.996076 4.20242 0.922283 4.14026 0.860124C4.0781 0.797965 4.0043 0.748658 3.92309 0.715017C3.84187 0.681377 3.75483 0.664062 3.66692 0.664063C3.57902 0.664063 3.49197 0.681377 3.41076 0.715017C3.32954 0.748658 3.25575 0.797965 3.19359 0.860124L0.526923 3.52679C0.466229 3.59019 0.418653 3.66496 0.386923 3.74679C0.320244 3.9091 0.320244 4.09115 0.386923 4.25346C0.418653 4.33529 0.466229 4.41005 0.526923 4.47346L3.19359 7.14012C3.25557 7.20261 3.3293 7.25221 3.41054 7.28605C3.49178 7.3199 3.57892 7.33732 3.66692 7.33732C3.75493 7.33732 3.84207 7.3199 3.92331 7.28605C4.00455 7.25221 4.07828 7.20261 4.14026 7.14012C4.20274 7.07815 4.25234 7.00441 4.28618 6.92317C4.32003 6.84194 4.33746 6.7548 4.33746 6.66679C4.33746 6.57878 4.32003 6.49165 4.28618 6.41041C4.25234 6.32917 4.20274 6.25543 4.14026 6.19346L2.60692 4.66679H11.3936L9.86026 6.19346C9.79777 6.25543 9.74817 6.32917 9.71433 6.41041C9.68048 6.49165 9.66306 6.57878 9.66306 6.66679C9.66306 6.7548 9.68048 6.84194 9.71433 6.92317C9.74817 7.00441 9.79777 7.07815 9.86026 7.14012C9.92223 7.20261 9.99597 7.25221 10.0772 7.28605C10.1584 7.3199 10.2456 7.33732 10.3336 7.33732C10.4216 7.33732 10.5087 7.3199 10.59 7.28605C10.6712 7.25221 10.7449 7.20261 10.8069 7.14012L13.4736 4.47346C13.5343 4.41005 13.5819 4.33529 13.6136 4.25346C13.6803 4.09115 13.6803 3.9091 13.6136 3.74679Z" fill="currentColor"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.9 KiB |
4
components/Icons/chevron-down.svg
Normal file
@ -0,0 +1,4 @@
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" viewBox="0 0 16 10">
|
||||
<path fill="currentColor" d="M0.2,0.7C0.5,0.4,1,0.4,1.3,0.7l0.1,0.1L8,7.5l6.6-6.7c0.3-0.3,0.7-0.3,1.1-0.1l0.1,0.1
|
||||
c0.3,0.3,0.3,0.8,0.1,1.1l-0.1,0.1L8.6,9.3C8.3,9.6,7.8,9.6,7.5,9.3L7.4,9.3L0.2,1.9C-0.1,1.6-0.1,1.1,0.2,0.7z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 324 B |
4
components/Icons/chevron-left.svg
Normal file
@ -0,0 +1,4 @@
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" viewBox="0 0 10 16">
|
||||
<path fill='currentColor' d="M9.3,0.2C9.6,0.5,9.6,1,9.3,1.3L9.3,1.4L2.5,8l6.7,6.6c0.3,0.3,0.3,0.7,0.1,1.1l-0.1,0.1c-0.3,0.3-0.8,0.3-1.1,0.1l-0.1-0.1
|
||||
L0.7,8.6C0.4,8.3,0.4,7.8,0.7,7.5l0.1-0.1l7.3-7.2C8.4-0.1,8.9-0.1,9.3,0.2z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 325 B |
4
components/Icons/chevron-right.svg
Normal file
@ -0,0 +1,4 @@
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" viewBox="0 0 10 16">
|
||||
<path fill='currentColor' d="M0.7,15.8c-0.3-0.3-0.3-0.7-0.1-1.1l0.1-0.1L7.5,8L0.7,1.4C0.4,1.1,0.4,0.7,0.7,0.3l0.1-0.1C1-0.1,1.5-0.1,1.8,0.2l0.1,0.1
|
||||
l7.3,7.2c0.3,0.3,0.3,0.7,0.1,1.1L9.3,8.6l-7.3,7.2C1.6,16.1,1.1,16.1,0.7,15.8z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 328 B |
4
components/Icons/chevron-up.svg
Normal file
@ -0,0 +1,4 @@
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" viewBox="0 0 16 10">
|
||||
<path fill='currentColor' d="M15.8,9.3c-0.3,0.3-0.7,0.3-1.1,0.1l-0.1-0.1L8,2.5L1.4,9.3C1.1,9.6,0.7,9.6,0.3,9.3L0.2,9.3
|
||||
C-0.1,9-0.1,8.5,0.2,8.2l0.1-0.1l7.2-7.3c0.3-0.3,0.7-0.3,1.1-0.1l0.1,0.1l7.2,7.3C16.1,8.4,16.1,8.9,15.8,9.3z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 329 B |
@ -1,6 +0,0 @@
|
||||
<svg viewBox='0 0 8 6' xmlns='http://www.w3.org/2000/svg'>
|
||||
<path
|
||||
d='M7.33346 3.93988L4.47346 1.11321C4.41149 1.05073 4.33775 1.00113 4.25651 0.967287C4.17527 0.933441 4.08814 0.916016 4.00013 0.916016C3.91212 0.916016 3.82498 0.933441 3.74374 0.967287C3.6625 1.00113 3.58877 1.05073 3.52679 1.11321L0.700129 3.93988C0.637643 4.00186 0.588047 4.07559 0.554201 4.15683C0.520355 4.23807 0.50293 4.32521 0.50293 4.41321C0.50293 4.50122 0.520355 4.58836 0.554201 4.6696C0.588047 4.75084 0.637643 4.82457 0.700129 4.88655C0.825037 5.01072 0.994005 5.08041 1.17013 5.08041C1.34625 5.08041 1.51522 5.01072 1.64013 4.88655L4.00013 2.52655L6.36013 4.88655C6.4843 5.00971 6.6519 5.07914 6.82679 5.07988C6.91453 5.08039 7.00151 5.06357 7.08273 5.0304C7.16396 4.99722 7.23783 4.94834 7.30013 4.88655C7.36485 4.8268 7.41708 4.75483 7.45382 4.67477C7.49056 4.59472 7.51107 4.50819 7.51417 4.42016C7.51727 4.33214 7.50289 4.24438 7.47188 4.16194C7.44086 4.0795 7.39382 4.00403 7.33346 3.93988Z'
|
||||
fill='currentColor'
|
||||
/>
|
||||
</svg>
|
Before Width: | Height: | Size: 1021 B |
@ -1,3 +1,3 @@
|
||||
;<svg viewBox='0 0 12 14' xmlns='http://www.w3.org/2000/svg' fill='currentColor'>
|
||||
<svg viewBox='0 0 12 14' xmlns='http://www.w3.org/2000/svg' fill='currentColor'>
|
||||
<path d='M8.66667 12.3333H3.33333C2.8029 12.3333 2.29419 12.1225 1.91912 11.7475C1.54405 11.3724 1.33333 10.8637 1.33333 10.3333V3.66659C1.33333 3.48977 1.2631 3.32021 1.13807 3.19518C1.01305 3.07016 0.843478 2.99992 0.666667 2.99992C0.489856 2.99992 0.320286 3.07016 0.195262 3.19518C0.0702379 3.32021 0 3.48977 0 3.66659V10.3333C0 11.2173 0.351189 12.0652 0.976311 12.6903C1.60143 13.3154 2.44928 13.6666 3.33333 13.6666H8.66667C8.84348 13.6666 9.01305 13.5963 9.13807 13.4713C9.2631 13.3463 9.33333 13.1767 9.33333 12.9999C9.33333 12.8231 9.2631 12.6535 9.13807 12.5285C9.01305 12.4035 8.84348 12.3333 8.66667 12.3333ZM12 4.95992C11.9931 4.89867 11.9796 4.83834 11.96 4.77992V4.71992C11.9279 4.65137 11.8852 4.58836 11.8333 4.53325L7.83333 0.533252C7.77822 0.481396 7.71521 0.438639 7.64667 0.406585H7.58667L7.37333 0.333252H4.66667C4.13623 0.333252 3.62753 0.543966 3.25245 0.919038C2.87738 1.29411 2.66667 1.80282 2.66667 2.33325V8.99992C2.66667 9.53035 2.87738 10.0391 3.25245 10.4141C3.62753 10.7892 4.13623 10.9999 4.66667 10.9999H10C10.5304 10.9999 11.0391 10.7892 11.4142 10.4141C11.7893 10.0391 12 9.53035 12 8.99992V4.99992C12 4.99992 12 4.99992 12 4.95992ZM8 2.60659L9.72667 4.33325H8.66667C8.48986 4.33325 8.32029 4.26301 8.19526 4.13799C8.07024 4.01297 8 3.8434 8 3.66659V2.60659ZM10.6667 8.99992C10.6667 9.17673 10.5964 9.3463 10.4714 9.47132C10.3464 9.59635 10.1768 9.66659 10 9.66659H4.66667C4.48986 9.66659 4.32029 9.59635 4.19526 9.47132C4.07024 9.3463 4 9.17673 4 8.99992V2.33325C4 2.15644 4.07024 1.98687 4.19526 1.86185C4.32029 1.73682 4.48986 1.66659 4.66667 1.66659H6.66667V3.66659C6.66667 4.19702 6.87738 4.70573 7.25245 5.0808C7.62753 5.45587 8.13623 5.66659 8.66667 5.66659H10.6667V8.99992Z' />
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
@ -1,6 +0,0 @@
|
||||
<svg fill='currentColor' viewBox='0 0 8 6' xmlns='http://www.w3.org/2000/svg'>
|
||||
<path
|
||||
d='M7.24327 1.13085C7.12112 1.00795 6.95588 0.938965 6.78364 0.938965C6.6114 0.938965 6.44617 1.00795 6.32401 1.13085L3.9835 3.46685L1.67558 1.13085C1.55343 1.00795 1.38819 0.938965 1.21595 0.938965C1.04371 0.938965 0.878475 1.00795 0.756324 1.13085C0.695217 1.1922 0.646715 1.26518 0.613616 1.3456C0.580517 1.42601 0.563477 1.51226 0.563477 1.59937C0.563477 1.68649 0.580517 1.77274 0.613616 1.85315C0.646715 1.93356 0.695217 2.00655 0.756324 2.06789L3.52061 4.86581C3.58122 4.92766 3.65332 4.97675 3.73277 5.01026C3.81222 5.04376 3.89743 5.06101 3.9835 5.06101C4.06956 5.06101 4.15478 5.04376 4.23422 5.01026C4.31367 4.97675 4.38578 4.92766 4.44639 4.86581L7.24327 2.06789C7.30438 2.00655 7.35288 1.93356 7.38598 1.85315C7.41908 1.77274 7.43612 1.68649 7.43612 1.59937C7.43612 1.51226 7.41908 1.42601 7.38598 1.3456C7.35288 1.26518 7.30438 1.1922 7.24327 1.13085Z'
|
||||
|
||||
/>
|
||||
</svg>
|
Before Width: | Height: | Size: 971 B |
340
components/Icons/osmo.svg
Normal file
@ -0,0 +1,340 @@
|
||||
<svg fill='none' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'>
|
||||
<path
|
||||
d='M22.8084 4.42014C22.5667 3.50503 21.7897 2.58992 20.3912 1.57122C19.2689 0.759705 18.0775 0.293518 17.1279 0.293518C16.9379 0.293518 16.7653 0.310784 16.5926 0.345317C16.1609 0.431648 15.7811 0.742439 15.5394 1.20863C15.2458 1.76114 15.1768 2.50359 15.3667 2.95251C15.4358 3.09064 15.5221 3.2633 15.6257 3.4187C14.7106 3.97122 14.1926 4.12661 14.1235 4.14388C16.5063 4.93812 18.4919 6.59568 19.735 8.75395L19.7523 8.54676C19.8041 7.97697 19.9768 7.32086 20.2185 6.64748C20.4602 6.71654 20.702 6.75107 20.9437 6.75107C21.5825 6.75107 22.135 6.49208 22.4804 6.02589C22.8257 5.55971 22.9638 4.93812 22.8084 4.42014Z'
|
||||
fill='#5E12A0'
|
||||
></path>
|
||||
<path
|
||||
d='M20.3225 6.14679C21.8937 6.57844 22.5326 5.36981 22.3254 4.5583C22.1009 3.74679 21.3757 2.91801 20.098 1.98564C18.8203 1.05326 17.5254 0.673409 16.6966 0.846071C15.8678 1.01873 15.6261 2.27916 15.8333 2.76262C15.9196 2.95255 16.1096 3.2288 16.3685 3.5396C16.0405 3.76406 15.7297 3.93672 15.4707 4.09211C17.0592 4.80003 18.4405 5.90506 19.4765 7.28636C19.5973 6.82017 19.77 6.40578 19.9254 6.04319C20.0462 6.06046 20.1844 6.09499 20.3225 6.14679Z'
|
||||
fill='url(#paint0_radial_8766_48743)'
|
||||
></path>
|
||||
<path
|
||||
d='M11.3266 23.0676C16.6572 23.0676 20.9784 18.7464 20.9784 13.4158C20.9784 8.08525 16.6572 3.76404 11.3266 3.76404C5.99601 3.76404 1.6748 8.08525 1.6748 13.4158C1.6748 18.7464 5.99601 23.0676 11.3266 23.0676Z'
|
||||
fill='url(#paint1_radial_8766_48743)'
|
||||
></path>
|
||||
<path
|
||||
d='M21.5307 3.76403C20.2185 2.38274 19.1134 2.02015 17.784 1.72662C16.748 1.4849 17.0242 0.897845 18.2847 1.01871C17.6804 0.811514 17.1106 0.759716 16.6962 0.846047C15.8674 1.01871 15.6257 2.27914 15.8329 2.76259C15.9192 2.95252 16.1091 3.22878 16.3681 3.53957C15.9019 3.85036 15.5048 4.07482 15.1768 4.24749C15.3322 4.31655 15.5221 4.40288 15.7465 4.52375C16.3336 4.83454 16.9724 5.35252 16.9724 5.35252C16.0055 4.52375 16.2127 4.14389 17.5422 3.21151C17.9566 2.91799 18.7163 2.95252 19.4242 3.31511C20.1322 3.6777 20.9609 4.59281 20.9609 4.59281L20.1667 6.11223C20.2185 6.1295 20.2703 6.14677 20.3221 6.16403C20.8228 6.30216 21.2199 6.26763 21.5307 6.14677C21.8933 5.92231 22.8429 5.16259 21.5307 3.76403Z'
|
||||
fill='#A98698'
|
||||
fill-opacity='0.6'
|
||||
></path>
|
||||
<path
|
||||
d='M17.7671 2.55539C18.1124 2.69352 18.5613 2.93525 19.1138 3.29784C19.7699 3.72949 20.3397 4.21295 20.7023 4.5928C20.098 5.38705 19.7009 6.47482 19.4592 7.23453C19.58 7.40719 19.7181 7.57985 19.839 7.75252C19.9599 7.32086 20.1671 6.68201 20.4433 6.04316C20.5124 6.06043 20.5987 6.06043 20.6851 6.06043C20.8922 6.06043 21.134 6.0259 21.3239 5.8705C21.462 5.7669 21.6174 5.57698 21.6002 5.23165C21.6002 4.90359 21.3412 4.48921 20.8059 3.98849C20.4261 3.6259 19.9081 3.22878 19.3901 2.86619C17.9052 1.88201 16.8692 1.60575 16.403 2.07194C16.0922 2.38273 16.1268 2.76259 16.2304 3.03885C15.6779 3.40144 15.2117 3.66043 14.9009 3.83309C15.1081 3.90216 15.298 3.98849 15.5052 4.07482C16.0577 3.78129 16.852 3.28057 17.7671 2.55539ZM21.0304 5.02446C21.0822 5.11079 21.0994 5.19712 21.0994 5.24892C21.0994 5.40431 21.0476 5.45611 21.0131 5.49065C20.944 5.54244 20.8059 5.57698 20.6851 5.57698C20.7886 5.36978 20.9095 5.19712 21.0304 5.02446ZM16.7656 2.4518C16.8174 2.4 16.9556 2.36547 17.18 2.4C17.0074 2.53813 16.8347 2.65899 16.662 2.77985C16.6448 2.65899 16.662 2.53813 16.7656 2.4518Z'
|
||||
fill='#5E12A0'
|
||||
></path>
|
||||
<path
|
||||
d='M11.3266 3.19427C5.68052 3.19427 1.10498 7.76981 1.10498 13.4159C1.10498 19.0619 5.68052 23.6374 11.3266 23.6374C16.9726 23.6374 21.5481 19.0619 21.5481 13.4159C21.5481 7.76981 16.9553 3.19427 11.3266 3.19427ZM11.3266 23.0677C5.99131 23.0677 1.67476 18.7511 1.67476 13.4159C1.67476 8.08061 5.99131 3.76406 11.3266 3.76406C16.6618 3.76406 20.9784 8.08061 20.9784 13.4159C20.9784 18.7511 16.6445 23.0677 11.3266 23.0677Z'
|
||||
fill='#5E12A0'
|
||||
></path>
|
||||
<path
|
||||
d='M11.3266 23.0676C16.6572 23.0676 20.9784 18.7464 20.9784 13.4158C20.9784 8.08525 16.6572 3.76404 11.3266 3.76404C5.99601 3.76404 1.6748 8.08525 1.6748 13.4158C1.6748 18.7464 5.99601 23.0676 11.3266 23.0676Z'
|
||||
fill='url(#paint2_linear_8766_48743)'
|
||||
></path>
|
||||
<path
|
||||
d='M11.2577 21.8935C5.99153 21.0475 2.41743 16.0921 3.28074 10.8259C3.6606 8.49494 4.8347 6.50933 6.49225 5.07623C4.07499 6.47479 2.2793 8.90933 1.79585 11.8791C0.949806 17.1453 4.52391 22.1007 9.77283 22.9467C12.7081 23.4302 15.5397 22.5151 17.6289 20.7194C15.7815 21.7899 13.5369 22.2561 11.2577 21.8935Z'
|
||||
fill='#A98698'
|
||||
fill-opacity='0.6'
|
||||
></path>
|
||||
<path
|
||||
d='M12.8631 3.90216C10.4285 3.50504 8.06307 4.05756 6.12926 5.28346C6.09473 5.31799 6.0602 5.35252 6.0602 5.35252C6.80264 4.9036 7.89041 4.50648 7.89041 4.50648C5.09329 6.1295 4.22998 7.97698 4.22998 7.97698C5.31775 5.87051 8.51199 4.38562 11.0156 4.28202C13.5192 4.17842 15.1595 4.92087 17.1624 6.52662C19.1652 8.14964 20.3739 11.4648 20.253 14.0892C20.1494 16.7137 18.7681 18.8374 18.7681 18.8374C19.7177 17.6115 20.2875 16.7137 20.6501 15.7986C20.7192 15.5223 20.7883 15.246 20.8228 14.9525C21.6861 9.7036 18.1293 4.74821 12.8631 3.90216Z'
|
||||
fill='url(#paint3_linear_8766_48743)'
|
||||
></path>
|
||||
<path
|
||||
d='M20.4951 13.3295C20.4951 18.3885 16.3857 22.4978 11.3267 22.4978C6.26773 22.4978 2.14111 18.3885 2.14111 13.3295H20.4951Z'
|
||||
fill='url(#paint4_linear_8766_48743)'
|
||||
></path>
|
||||
<path
|
||||
d='M19.7696 13.3295C19.7696 18.2676 15.8675 22.3079 10.9639 22.4978H11.3265C16.3855 22.4978 20.4948 18.3885 20.4948 13.3295H19.7696Z'
|
||||
fill='url(#paint5_linear_8766_48743)'
|
||||
></path>
|
||||
<path
|
||||
d='M3.43608 13.3295H2.14111C2.14111 18.3885 6.25047 22.4978 11.3095 22.4978C11.5339 22.4978 11.7411 22.4978 11.9483 22.4805C7.20011 22.1352 3.43608 18.164 3.43608 13.3295Z'
|
||||
fill='url(#paint6_linear_8766_48743)'
|
||||
></path>
|
||||
<path
|
||||
d='M20.4778 13.4158C20.4778 12.3626 18.6476 11.7583 16.2131 11.5511C14.4519 11.413 12.6735 11.5856 10.6361 12.2072C8.87493 12.7252 7.28644 12.6389 6.1296 12.5007C3.55694 12.2072 2.14111 12.1727 2.14111 13.4158C2.14111 15.2115 5.80155 17.4561 11.2922 16.6792C14.072 16.282 15.5051 15.4705 17.1454 14.918C18.9238 14.331 20.4778 14.3482 20.4778 13.4158Z'
|
||||
fill='url(#paint7_linear_8766_48743)'
|
||||
></path>
|
||||
<path
|
||||
d='M14.3308 9.06476C15.1891 9.06476 15.8848 8.36911 15.8848 7.5108C15.8848 6.6525 15.1891 5.95685 14.3308 5.95685C13.4725 5.95685 12.7769 6.6525 12.7769 7.5108C12.7769 8.36911 13.4725 9.06476 14.3308 9.06476Z'
|
||||
fill='white'
|
||||
></path>
|
||||
<path
|
||||
d='M16.869 10.2216C17.2314 10.2216 17.5251 9.9279 17.5251 9.56548C17.5251 9.20306 17.2314 8.90936 16.869 8.90936C16.5066 8.90936 16.2129 9.20306 16.2129 9.56548C16.2129 9.9279 16.5066 10.2216 16.869 10.2216Z'
|
||||
fill='white'
|
||||
></path>
|
||||
<path
|
||||
d='M19.2175 6.2676H19.1829C19.0793 6.25034 19.0103 6.14674 19.0275 6.02588C19.1829 5.23163 19.8391 4.47192 19.8736 4.43739C19.9427 4.35106 20.0808 4.35106 20.1498 4.42012C20.2362 4.48919 20.2362 4.62732 20.1671 4.69638C20.1498 4.71365 19.5455 5.42156 19.4074 6.11221C19.3901 6.2158 19.3038 6.2676 19.2175 6.2676Z'
|
||||
fill='url(#paint8_linear_8766_48743)'
|
||||
></path>
|
||||
<path
|
||||
d='M10.6876 20.6158C10.9545 20.6158 11.171 20.3993 11.171 20.1324C11.171 19.8654 10.9545 19.6489 10.6876 19.6489C10.4206 19.6489 10.2041 19.8654 10.2041 20.1324C10.2041 20.3993 10.4206 20.6158 10.6876 20.6158Z'
|
||||
fill='white'
|
||||
fill-opacity='0.2'
|
||||
></path>
|
||||
<path
|
||||
d='M10.4117 20.4432C10.2218 20.2532 10.2218 19.9425 10.4117 19.7525C10.4462 19.718 10.4808 19.7007 10.5153 19.6662C10.4462 19.6835 10.3944 19.718 10.3426 19.7698C10.1527 19.9597 10.1527 20.2705 10.3426 20.4604C10.498 20.6158 10.7398 20.6504 10.9297 20.5468C10.757 20.6158 10.5498 20.5813 10.4117 20.4432Z'
|
||||
fill='url(#paint9_linear_8766_48743)'
|
||||
></path>
|
||||
<path
|
||||
d='M10.8604 19.9942C10.9176 19.9942 10.964 19.9478 10.964 19.8906C10.964 19.8335 10.9176 19.787 10.8604 19.787C10.8033 19.787 10.7568 19.8335 10.7568 19.8906C10.7568 19.9478 10.8033 19.9942 10.8604 19.9942Z'
|
||||
fill='white'
|
||||
fill-opacity='0.3'
|
||||
></path>
|
||||
<path
|
||||
d='M13.2086 20.3741C13.4755 20.3741 13.692 20.1576 13.692 19.8906C13.692 19.6237 13.4755 19.4072 13.2086 19.4072C12.9416 19.4072 12.7251 19.6237 12.7251 19.8906C12.7251 20.1576 12.9416 20.3741 13.2086 20.3741Z'
|
||||
fill='white'
|
||||
fill-opacity='0.2'
|
||||
></path>
|
||||
<path
|
||||
d='M12.9322 20.2014C12.7423 20.0115 12.7423 19.7007 12.9322 19.5108C12.9667 19.4762 13.0013 19.459 13.0358 19.4244C12.9667 19.4417 12.9149 19.4762 12.8631 19.528C12.6732 19.718 12.6732 20.0288 12.8631 20.2187C13.0185 20.3741 13.2603 20.4086 13.4502 20.305C13.2775 20.3741 13.0703 20.3395 12.9322 20.2014Z'
|
||||
fill='url(#paint10_linear_8766_48743)'
|
||||
></path>
|
||||
<path
|
||||
d='M13.3814 19.7525C13.4386 19.7525 13.485 19.7061 13.485 19.6489C13.485 19.5918 13.4386 19.5453 13.3814 19.5453C13.3243 19.5453 13.2778 19.5918 13.2778 19.6489C13.2778 19.7061 13.3243 19.7525 13.3814 19.7525Z'
|
||||
fill='white'
|
||||
fill-opacity='0.3'
|
||||
></path>
|
||||
<path
|
||||
d='M11.9656 21.4964C12.1659 21.4964 12.3282 21.3341 12.3282 21.1338C12.3282 20.9335 12.1659 20.7712 11.9656 20.7712C11.7653 20.7712 11.603 20.9335 11.603 21.1338C11.603 21.3341 11.7653 21.4964 11.9656 21.4964Z'
|
||||
fill='white'
|
||||
fill-opacity='0.2'
|
||||
></path>
|
||||
<path
|
||||
d='M11.7584 21.3583C11.6203 21.2202 11.6203 20.9784 11.7584 20.8403C11.7757 20.823 11.8102 20.8058 11.8275 20.7885C11.7757 20.8058 11.7412 20.8403 11.7066 20.8748C11.5685 21.013 11.5685 21.2547 11.7066 21.3928C11.8275 21.5137 12.0002 21.531 12.1555 21.4446C12.0174 21.4964 11.862 21.4619 11.7584 21.3583Z'
|
||||
fill='url(#paint11_linear_8766_48743)'
|
||||
></path>
|
||||
<path
|
||||
d='M12.0862 21.0129C12.1243 21.0129 12.1552 20.982 12.1552 20.9439C12.1552 20.9057 12.1243 20.8748 12.0862 20.8748C12.048 20.8748 12.0171 20.9057 12.0171 20.9439C12.0171 20.982 12.048 21.0129 12.0862 21.0129Z'
|
||||
fill='white'
|
||||
fill-opacity='0.3'
|
||||
></path>
|
||||
<path
|
||||
d='M14.1927 21.2374C14.393 21.2374 14.5553 21.0751 14.5553 20.8748C14.5553 20.6745 14.393 20.5122 14.1927 20.5122C13.9924 20.5122 13.8301 20.6745 13.8301 20.8748C13.8301 21.0751 13.9924 21.2374 14.1927 21.2374Z'
|
||||
fill='white'
|
||||
fill-opacity='0.2'
|
||||
></path>
|
||||
<path
|
||||
d='M13.9855 21.0993C13.8473 20.9611 13.8473 20.7194 13.9855 20.5813C14.0027 20.564 14.0373 20.5467 14.0545 20.5295C14.0027 20.5467 13.9682 20.5813 13.9337 20.6158C13.7955 20.7539 13.7955 20.9957 13.9337 21.1338C14.0545 21.2547 14.2272 21.2719 14.3826 21.1856C14.2445 21.2374 14.0891 21.2029 13.9855 21.0993Z'
|
||||
fill='url(#paint12_linear_8766_48743)'
|
||||
></path>
|
||||
<path
|
||||
d='M14.3137 20.754C14.3519 20.754 14.3828 20.7231 14.3828 20.6849C14.3828 20.6468 14.3519 20.6158 14.3137 20.6158C14.2755 20.6158 14.2446 20.6468 14.2446 20.6849C14.2446 20.7231 14.2755 20.754 14.3137 20.754Z'
|
||||
fill='white'
|
||||
fill-opacity='0.3'
|
||||
></path>
|
||||
<path
|
||||
d='M8.63311 20.4432C9.07185 20.4432 9.42736 20.0877 9.42736 19.6489C9.42736 19.2104 9.07185 18.8547 8.63311 18.8547C8.19455 18.8547 7.83887 19.2104 7.83887 19.6489C7.83887 20.0877 8.19455 20.4432 8.63311 20.4432Z'
|
||||
fill='white'
|
||||
fill-opacity='0.2'
|
||||
></path>
|
||||
<path
|
||||
d='M8.18435 20.1497C7.87356 19.8389 7.87356 19.3381 8.18435 19.0274C8.23615 18.9756 8.28794 18.941 8.35701 18.9065C8.25341 18.941 8.16708 19.0101 8.08075 19.0792C7.76996 19.3899 7.76996 19.8907 8.08075 20.2015C8.33974 20.4605 8.73687 20.5122 9.04766 20.3223C8.75413 20.4432 8.40881 20.3914 8.18435 20.1497Z'
|
||||
fill='url(#paint13_linear_8766_48743)'
|
||||
></path>
|
||||
<path
|
||||
d='M8.90948 19.4072C9.00479 19.4072 9.08214 19.3299 9.08214 19.2346C9.08214 19.1392 9.00479 19.0619 8.90948 19.0619C8.81417 19.0619 8.73682 19.1392 8.73682 19.2346C8.73682 19.3299 8.81417 19.4072 8.90948 19.4072Z'
|
||||
fill='white'
|
||||
fill-opacity='0.3'
|
||||
></path>
|
||||
<path
|
||||
d='M15.7293 18.4921C16.168 18.4921 16.5235 18.1366 16.5235 17.6979C16.5235 17.2593 16.168 16.9036 15.7293 16.9036C15.2907 16.9036 14.9351 17.2593 14.9351 17.6979C14.9351 18.1366 15.2907 18.4921 15.7293 18.4921Z'
|
||||
fill='white'
|
||||
fill-opacity='0.2'
|
||||
></path>
|
||||
<path
|
||||
d='M15.2634 18.1985C14.9527 17.8878 14.9527 17.387 15.2634 17.0762C15.3152 17.0244 15.367 16.9899 15.4361 16.9554C15.3325 16.9899 15.2462 17.059 15.1599 17.128C14.8491 17.4388 14.8491 17.9396 15.1599 18.2503C15.4188 18.5093 15.816 18.5611 16.1268 18.3712C15.8332 18.4921 15.5052 18.4403 15.2634 18.1985Z'
|
||||
fill='url(#paint14_linear_8766_48743)'
|
||||
></path>
|
||||
<path
|
||||
d='M16.0057 17.4561C16.101 17.4561 16.1783 17.3788 16.1783 17.2834C16.1783 17.1881 16.101 17.1108 16.0057 17.1108C15.9104 17.1108 15.833 17.1881 15.833 17.2834C15.833 17.3788 15.9104 17.4561 16.0057 17.4561Z'
|
||||
fill='white'
|
||||
fill-opacity='0.3'
|
||||
></path>
|
||||
<defs>
|
||||
<radialGradient
|
||||
cx='0'
|
||||
cy='0'
|
||||
gradientTransform='translate(22.0104 3.47051) scale(7.71702 7.71702)'
|
||||
gradientUnits='userSpaceOnUse'
|
||||
id='paint0_radial_8766_48743'
|
||||
r='1'
|
||||
>
|
||||
<stop stop-color='#FFEAFF' stop-opacity='0.6'></stop>
|
||||
<stop offset='0.68' stop-color='#A087C9'></stop>
|
||||
<stop offset='1' stop-color='#10002F'></stop>
|
||||
</radialGradient>
|
||||
<radialGradient
|
||||
cx='0'
|
||||
cy='0'
|
||||
gradientTransform='translate(17.7169 6.76169) scale(18.8808)'
|
||||
gradientUnits='userSpaceOnUse'
|
||||
id='paint1_radial_8766_48743'
|
||||
r='1'
|
||||
>
|
||||
<stop stop-color='#FFEAFF' stop-opacity='0.6'></stop>
|
||||
<stop offset='0.68' stop-color='#A087C9'></stop>
|
||||
<stop offset='1' stop-color='#10002F'></stop>
|
||||
</radialGradient>
|
||||
<linearGradient
|
||||
gradientUnits='userSpaceOnUse'
|
||||
id='paint2_linear_8766_48743'
|
||||
x1='9.77838'
|
||||
x2='12.8655'
|
||||
y1='22.9307'
|
||||
y2='3.8849'
|
||||
>
|
||||
<stop stop-color='#81FFFF' stop-opacity='0.6'></stop>
|
||||
<stop offset='0.62' stop-color='white' stop-opacity='0'></stop>
|
||||
<stop offset='1' stop-color='white' stop-opacity='0'></stop>
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
gradientUnits='userSpaceOnUse'
|
||||
id='paint3_linear_8766_48743'
|
||||
x1='18.1284'
|
||||
x2='10.1473'
|
||||
y1='6.861'
|
||||
y2='14.1839'
|
||||
>
|
||||
<stop stop-color='white' stop-opacity='0.6'></stop>
|
||||
<stop offset='0.29' stop-color='white' stop-opacity='0.6'></stop>
|
||||
<stop offset='0.78' stop-color='white' stop-opacity='0'></stop>
|
||||
<stop offset='1' stop-color='white' stop-opacity='0'></stop>
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
gradientUnits='userSpaceOnUse'
|
||||
id='paint4_linear_8766_48743'
|
||||
x1='2.14889'
|
||||
x2='20.4906'
|
||||
y1='17.9083'
|
||||
y2='17.9083'
|
||||
>
|
||||
<stop stop-color='#0002E9'></stop>
|
||||
<stop offset='1' stop-color='#FF00C7'></stop>
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
gradientUnits='userSpaceOnUse'
|
||||
id='paint5_linear_8766_48743'
|
||||
x1='21.3586'
|
||||
x2='11.3753'
|
||||
y1='14.134'
|
||||
y2='23.5688'
|
||||
>
|
||||
<stop stop-color='white' stop-opacity='0.6'></stop>
|
||||
<stop offset='0.29' stop-color='white' stop-opacity='0.6'></stop>
|
||||
<stop offset='0.78' stop-color='white' stop-opacity='0'></stop>
|
||||
<stop offset='1' stop-color='white' stop-opacity='0'></stop>
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
gradientUnits='userSpaceOnUse'
|
||||
id='paint6_linear_8766_48743'
|
||||
x1='2.14889'
|
||||
x2='11.9616'
|
||||
y1='17.9083'
|
||||
y2='17.9083'
|
||||
>
|
||||
<stop stop-color='#000292' stop-opacity='0.7'></stop>
|
||||
<stop offset='1' stop-color='#7D00C7' stop-opacity='0.7'></stop>
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
gradientUnits='userSpaceOnUse'
|
||||
id='paint7_linear_8766_48743'
|
||||
x1='2.1612'
|
||||
x2='20.4784'
|
||||
y1='14.1775'
|
||||
y2='14.1775'
|
||||
>
|
||||
<stop stop-color='#000292'></stop>
|
||||
<stop offset='1' stop-color='#BE00C7'></stop>
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
gradientUnits='userSpaceOnUse'
|
||||
id='paint8_linear_8766_48743'
|
||||
x1='20.1778'
|
||||
x2='18.8614'
|
||||
y1='4.3533'
|
||||
y2='6.49258'
|
||||
>
|
||||
<stop stop-color='white' stop-opacity='0.6'></stop>
|
||||
<stop offset='0.29' stop-color='white' stop-opacity='0.6'></stop>
|
||||
<stop offset='0.78' stop-color='white' stop-opacity='0'></stop>
|
||||
<stop offset='1' stop-color='white' stop-opacity='0'></stop>
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
gradientUnits='userSpaceOnUse'
|
||||
id='paint9_linear_8766_48743'
|
||||
x1='10.1997'
|
||||
x2='10.9302'
|
||||
y1='20.1472'
|
||||
y2='20.1472'
|
||||
>
|
||||
<stop stop-color='white' stop-opacity='0.6'></stop>
|
||||
<stop offset='0.29' stop-color='white' stop-opacity='0.6'></stop>
|
||||
<stop offset='0.78' stop-color='white' stop-opacity='0'></stop>
|
||||
<stop offset='1' stop-color='white' stop-opacity='0'></stop>
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
gradientUnits='userSpaceOnUse'
|
||||
id='paint10_linear_8766_48743'
|
||||
x1='12.7185'
|
||||
x2='13.449'
|
||||
y1='19.9022'
|
||||
y2='19.9022'
|
||||
>
|
||||
<stop stop-color='white' stop-opacity='0.6'></stop>
|
||||
<stop offset='0.29' stop-color='white' stop-opacity='0.6'></stop>
|
||||
<stop offset='0.78' stop-color='white' stop-opacity='0'></stop>
|
||||
<stop offset='1' stop-color='white' stop-opacity='0'></stop>
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
gradientUnits='userSpaceOnUse'
|
||||
id='paint11_linear_8766_48743'
|
||||
x1='11.6008'
|
||||
x2='12.1492'
|
||||
y1='21.138'
|
||||
y2='21.138'
|
||||
>
|
||||
<stop stop-color='white' stop-opacity='0.6'></stop>
|
||||
<stop offset='0.29' stop-color='white' stop-opacity='0.6'></stop>
|
||||
<stop offset='0.78' stop-color='white' stop-opacity='0'></stop>
|
||||
<stop offset='1' stop-color='white' stop-opacity='0'></stop>
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
gradientUnits='userSpaceOnUse'
|
||||
id='paint12_linear_8766_48743'
|
||||
x1='13.8204'
|
||||
x2='14.3688'
|
||||
y1='20.8783'
|
||||
y2='20.8783'
|
||||
>
|
||||
<stop stop-color='white' stop-opacity='0.6'></stop>
|
||||
<stop offset='0.29' stop-color='white' stop-opacity='0.6'></stop>
|
||||
<stop offset='0.78' stop-color='white' stop-opacity='0'></stop>
|
||||
<stop offset='1' stop-color='white' stop-opacity='0'></stop>
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
gradientUnits='userSpaceOnUse'
|
||||
id='paint13_linear_8766_48743'
|
||||
x1='7.83973'
|
||||
x2='9.03272'
|
||||
y1='19.6691'
|
||||
y2='19.6691'
|
||||
>
|
||||
<stop stop-color='white' stop-opacity='0.6'></stop>
|
||||
<stop offset='0.29' stop-color='white' stop-opacity='0.6'></stop>
|
||||
<stop offset='0.78' stop-color='white' stop-opacity='0'></stop>
|
||||
<stop offset='1' stop-color='white' stop-opacity='0'></stop>
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
gradientUnits='userSpaceOnUse'
|
||||
id='paint14_linear_8766_48743'
|
||||
x1='14.9254'
|
||||
x2='16.1184'
|
||||
y1='17.7175'
|
||||
y2='17.7175'
|
||||
>
|
||||
<stop stop-color='white' stop-opacity='0.6'></stop>
|
||||
<stop offset='0.29' stop-color='white' stop-opacity='0.6'></stop>
|
||||
<stop offset='0.78' stop-color='white' stop-opacity='0'></stop>
|
||||
<stop offset='1' stop-color='white' stop-opacity='0'></stop>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 18 KiB |
@ -1,26 +1,29 @@
|
||||
import classNames from 'classnames'
|
||||
import React from 'react'
|
||||
import React, { useEffect } from 'react'
|
||||
import { useWallet, WalletConnectionStatus } from '@marsprotocol/wallet-connector'
|
||||
|
||||
import CreditManager from 'components/CreditManager'
|
||||
import ArrowLeftLine from 'components/Icons/arrow-left-line.svg'
|
||||
import AccountManager from 'components/Account/AccountDetails'
|
||||
import DesktopNavigation from 'components/Navigation/DesktopNavigation'
|
||||
import useCreditAccounts from 'hooks/useCreditAccounts'
|
||||
import useCreditManagerStore from 'stores/useCreditManagerStore'
|
||||
import useWalletStore from 'stores/useWalletStore'
|
||||
import { useWalletStore } from 'stores'
|
||||
|
||||
const filter = {
|
||||
day: 'brightness-100 hue-rotate-0',
|
||||
night: '-hue-rotate-82 brightness-30',
|
||||
}
|
||||
|
||||
const Layout = ({ children }: { children: React.ReactNode }) => {
|
||||
const toggleCreditManager = useCreditManagerStore((s) => s.actions.toggleCreditManager)
|
||||
const isOpen = useCreditManagerStore((s) => s.isOpen)
|
||||
const address = useWalletStore((s) => s.address)
|
||||
const { data: creditAccountsList, isLoading: isLoadingCreditAccounts } = useCreditAccounts()
|
||||
const hasCreditAccounts = creditAccountsList && creditAccountsList.length > 0
|
||||
|
||||
const filter = {
|
||||
day: 'brightness-100 hue-rotate-0',
|
||||
night: '-hue-rotate-82 brightness-30',
|
||||
}
|
||||
const { status, signingCosmWasmClient, chainInfo, address, name } = useWallet()
|
||||
const initialize = useWalletStore((s) => s.actions.initialize)
|
||||
|
||||
const isConnected = !!address
|
||||
useEffect(() => {
|
||||
initialize(status, signingCosmWasmClient, address, name, chainInfo)
|
||||
}, [status, signingCosmWasmClient, chainInfo, address, name, initialize])
|
||||
|
||||
const isConnected = status === WalletConnectionStatus.Connected
|
||||
|
||||
const backgroundClasses = classNames(
|
||||
isConnected ? filter.day : filter.night,
|
||||
@ -33,14 +36,7 @@ const Layout = ({ children }: { children: React.ReactNode }) => {
|
||||
<DesktopNavigation />
|
||||
<main className='relative flex lg:h-[calc(100vh-120px)]'>
|
||||
<div className='flex flex-grow flex-wrap p-6'>{children}</div>
|
||||
{isOpen && hasCreditAccounts && <CreditManager />}
|
||||
{!isOpen && hasCreditAccounts && (
|
||||
<div className='absolute top-0 right-0 border-l border-b border-white/20 bg-header p-4'>
|
||||
<div className='w-5 hover:cursor-pointer' onClick={toggleCreditManager}>
|
||||
<ArrowLeftLine />
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{hasCreditAccounts && <AccountManager />}
|
||||
</main>
|
||||
</div>
|
||||
)
|
||||
|
11
components/Modals.tsx
Normal file
@ -0,0 +1,11 @@
|
||||
import { ConfirmModal, FundAccountModal, WithdrawModal } from './Account'
|
||||
|
||||
const Modals = () => (
|
||||
<>
|
||||
<FundAccountModal />
|
||||
<WithdrawModal />
|
||||
<ConfirmModal />
|
||||
</>
|
||||
)
|
||||
|
||||
export default Modals
|
@ -1,29 +1,18 @@
|
||||
import Link from 'next/link'
|
||||
|
||||
import { AccountStatus, SubAccountNavigation } from 'components/Account'
|
||||
import CircularProgress from 'components/CircularProgress'
|
||||
import { AccountNavigation, AccountStatus } from 'components/Account'
|
||||
import Logo from 'components/Icons/logo.svg'
|
||||
import Modal from 'components/Modal'
|
||||
import { menuTree, NavLink } from 'components/Navigation'
|
||||
import SearchInput from 'components/Navigation/SearchInput'
|
||||
import Text from 'components/Text'
|
||||
import Wallet from 'components/Wallet'
|
||||
import useCreateCreditAccount from 'hooks/mutations/useCreateCreditAccount'
|
||||
import useDeleteCreditAccount from 'hooks/mutations/useDeleteCreditAccount'
|
||||
import Wallet from 'components/Wallet/Wallet'
|
||||
import useCreditAccounts from 'hooks/useCreditAccounts'
|
||||
import useCreditManagerStore from 'stores/useCreditManagerStore'
|
||||
import useWalletStore from 'stores/useWalletStore'
|
||||
import { useAccountDetailsStore, useWalletStore } from 'stores'
|
||||
|
||||
const Navigation = () => {
|
||||
const address = useWalletStore((s) => s.address)
|
||||
const selectedAccount = useCreditManagerStore((s) => s.selectedAccount)
|
||||
const setSelectedAccount = useCreditManagerStore((s) => s.actions.setSelectedAccount)
|
||||
const { mutate: createCreditAccount, isLoading: isLoadingCreate } = useCreateCreditAccount()
|
||||
const { mutate: deleteCreditAccount, isLoading: isLoadingDelete } = useDeleteCreditAccount(
|
||||
selectedAccount || '',
|
||||
)
|
||||
const selectedAccount = useAccountDetailsStore((s) => s.selectedAccount)
|
||||
|
||||
const { data: creditAccountsList, isLoading: isLoadingCreditAccounts } = useCreditAccounts()
|
||||
const { data: creditAccountsList } = useCreditAccounts()
|
||||
|
||||
const isConnected = !!address
|
||||
const hasCreditAccounts = creditAccountsList && creditAccountsList.length > 0
|
||||
@ -52,27 +41,14 @@ const Navigation = () => {
|
||||
<div className='flex items-center'>
|
||||
<SearchInput />
|
||||
{isConnected && hasCreditAccounts && (
|
||||
<SubAccountNavigation
|
||||
<AccountNavigation
|
||||
selectedAccount={selectedAccount}
|
||||
createCreditAccount={createCreditAccount}
|
||||
deleteCreditAccount={deleteCreditAccount}
|
||||
setSelectedAccount={setSelectedAccount}
|
||||
creditAccountsList={creditAccountsList}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
{isConnected && <AccountStatus createCreditAccount={createCreditAccount} />}
|
||||
{isConnected && <AccountStatus />}
|
||||
</div>
|
||||
<Modal open={isLoadingCreate || isLoadingDelete}>
|
||||
<div className='w-full p-6'>
|
||||
<Text size='2xl' uppercase={true} className='mb-6 w-full text-center'>
|
||||
Confirm Transaction
|
||||
</Text>
|
||||
<div className='flex w-full justify-center pb-6'>
|
||||
<CircularProgress size={40} />
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ const SearchInput = () => (
|
||||
<SearchIcon />
|
||||
</span>
|
||||
<input
|
||||
className='w-[280px] rounded-md border border-white/20 bg-black/30 py-2 pl-10 text-sm text-white placeholder:text-white/40 focus:outline-none'
|
||||
className='w-[280px] rounded-md border border-white/20 bg-black/30 py-2 pl-10 text-sm text-white placeholder:text-white/40 focus:border-white/60 focus:outline-none'
|
||||
placeholder='Search'
|
||||
/>
|
||||
</div>
|
||||
|
33
components/Overlay/OverlayLink.tsx
Normal file
@ -0,0 +1,33 @@
|
||||
import classNames from 'classnames'
|
||||
import { ReactNode } from 'react'
|
||||
|
||||
import Button from 'components/Button'
|
||||
|
||||
interface Props {
|
||||
className?: string
|
||||
icon?: ReactNode
|
||||
onClick: () => void
|
||||
setShow: (show: boolean) => void
|
||||
text: string | ReactNode
|
||||
}
|
||||
|
||||
const OverlayAction = ({ className, icon, onClick, setShow, text }: Props) => {
|
||||
return (
|
||||
<Button
|
||||
className={classNames(
|
||||
'flex items-center whitespace-nowrap py-2 text-left text-sm text-accent-dark hover:text-secondary',
|
||||
className,
|
||||
)}
|
||||
variant='text'
|
||||
onClick={() => {
|
||||
setShow(false)
|
||||
onClick()
|
||||
}}
|
||||
>
|
||||
{icon && <span className='mt-[1px] mr-2 flex w-4'>{icon}</span>}
|
||||
{text}
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
|
||||
export default OverlayAction
|
2
components/Overlay/index.tsx
Normal file
@ -0,0 +1,2 @@
|
||||
export { default as Overlay } from './Overlay'
|
||||
export { default as OverlayLink } from './OverlayLink'
|
@ -5,17 +5,17 @@ import React, { useMemo, useState } from 'react'
|
||||
import { NumericFormat } from 'react-number-format'
|
||||
import { toast } from 'react-toastify'
|
||||
|
||||
import Button from 'components/Button'
|
||||
import CircularProgress from 'components/CircularProgress'
|
||||
import ContainerSecondary from 'components/ContainerSecondary'
|
||||
import Slider from 'components/Slider'
|
||||
import useRepayFunds from 'hooks/mutations/useRepayFunds'
|
||||
import useAllBalances from 'hooks/useAllBalances'
|
||||
import useCreditAccountPositions from 'hooks/useCreditAccountPositions'
|
||||
import useTokenPrices from 'hooks/useTokenPrices'
|
||||
import useCreditManagerStore from 'stores/useCreditManagerStore'
|
||||
import { useAccountDetailsStore } from 'stores'
|
||||
import { formatCurrency } from 'utils/formatters'
|
||||
import { getTokenDecimals, getTokenSymbol } from 'utils/tokens'
|
||||
import Button from 'components/Button'
|
||||
import CircularProgress from 'components/CircularProgress'
|
||||
import ContainerSecondary from 'components/ContainerSecondary'
|
||||
|
||||
// 0.001% buffer / slippage to avoid repay action from not fully repaying the debt amount
|
||||
const REPAY_BUFFER = 1.00001
|
||||
@ -29,7 +29,7 @@ type Props = {
|
||||
const RepayModal = ({ show, onClose, tokenDenom }: Props) => {
|
||||
const [amount, setAmount] = useState(0)
|
||||
|
||||
const selectedAccount = useCreditManagerStore((s) => s.selectedAccount)
|
||||
const selectedAccount = useAccountDetailsStore((s) => s.selectedAccount)
|
||||
const { data: positionsData } = useCreditAccountPositions(selectedAccount ?? '')
|
||||
|
||||
const tokenSymbol = getTokenSymbol(tokenDenom)
|
||||
|
@ -14,7 +14,7 @@ import useCalculateMaxTradeAmount from 'hooks/useCalculateMaxTradeAmount'
|
||||
import useCreditAccountPositions from 'hooks/useCreditAccountPositions'
|
||||
import useMarkets from 'hooks/useMarkets'
|
||||
import useTokenPrices from 'hooks/useTokenPrices'
|
||||
import useCreditManagerStore from 'stores/useCreditManagerStore'
|
||||
import { useAccountDetailsStore } from 'stores'
|
||||
import { getTokenDecimals, getTokenSymbol } from 'utils/tokens'
|
||||
|
||||
enum FundingMode {
|
||||
@ -32,7 +32,7 @@ const TradeActionModule = () => {
|
||||
|
||||
const [isMarginEnabled, setIsMarginEnabled] = React.useState(false)
|
||||
|
||||
const selectedAccount = useCreditManagerStore((s) => s.selectedAccount)
|
||||
const selectedAccount = useAccountDetailsStore((s) => s.selectedAccount)
|
||||
|
||||
const { data: allowedCoinsData } = useAllowedCoins()
|
||||
const { data: balancesData } = useAllBalances()
|
||||
|
@ -1,86 +0,0 @@
|
||||
import { Popover } from '@headlessui/react'
|
||||
import Image from 'next/image'
|
||||
import React, { useState } from 'react'
|
||||
import { toast } from 'react-toastify'
|
||||
|
||||
import useTokenBalance from 'hooks/useTokenBalance'
|
||||
import useWalletStore from 'stores/useWalletStore'
|
||||
import { chain } from 'utils/chains'
|
||||
import { formatWalletAddress } from 'utils/formatters'
|
||||
import Button from 'components/Button'
|
||||
import ConnectModal from 'components/ConnectModal'
|
||||
|
||||
const WalletPopover = ({ children }: { children: React.ReactNode }) => {
|
||||
const address = useWalletStore((s) => s.address)
|
||||
const actions = useWalletStore((s) => s.actions)
|
||||
|
||||
const { data } = useTokenBalance()
|
||||
|
||||
return (
|
||||
<Popover className='relative'>
|
||||
<Popover.Button as={Button} className='w-[200px] !rounded-3xl !bg-green-500'>
|
||||
{children}
|
||||
</Popover.Button>
|
||||
|
||||
<Popover.Panel className='absolute right-0 z-10 pt-2'>
|
||||
<div className='rounded-2xl bg-white p-6 text-gray-900'>
|
||||
<div className='mb-4 flex items-center justify-between'>
|
||||
<div className='flex items-center'>
|
||||
<Image src={chain.stakeCurrency.coinImageUrl} alt='token' width={24} height={24} />
|
||||
<p className='ml-2'>
|
||||
{chain.stakeCurrency.coinDenom}{' '}
|
||||
<span className='ml-1 text-lg font-semibold'>{data?.toFixed(2)}</span>
|
||||
</p>
|
||||
</div>
|
||||
<Button onClick={() => actions.disconnect()}>Disconnect</Button>
|
||||
</div>
|
||||
<p className='color-primary mb-6 text-sm'>{address}</p>
|
||||
<button
|
||||
className='flex items-center text-sm text-slate-500 hover:text-slate-700'
|
||||
onClick={() => {
|
||||
navigator.clipboard.writeText(address).then(() => {
|
||||
toast.success('Address copied to your clipboard')
|
||||
})
|
||||
}}
|
||||
>
|
||||
<svg
|
||||
fill='none'
|
||||
viewBox='0 0 24 24'
|
||||
strokeWidth={1.5}
|
||||
stroke='currentColor'
|
||||
className='mr-1 h-5 w-5'
|
||||
>
|
||||
<path
|
||||
strokeLinecap='round'
|
||||
strokeLinejoin='round'
|
||||
d='M8.25 7.5V6.108c0-1.135.845-2.098 1.976-2.192.373-.03.748-.057 1.123-.08M15.75 18H18a2.25 2.25 0 002.25-2.25V6.108c0-1.135-.845-2.098-1.976-2.192a48.424 48.424 0 00-1.123-.08M15.75 18.75v-1.875a3.375 3.375 0 00-3.375-3.375h-1.5a1.125 1.125 0 01-1.125-1.125v-1.5A3.375 3.375 0 006.375 7.5H5.25m11.9-3.664A2.251 2.251 0 0015 2.25h-1.5a2.251 2.251 0 00-2.15 1.586m5.8 0c.065.21.1.433.1.664v.75h-6V4.5c0-.231.035-.454.1-.664M6.75 7.5H4.875c-.621 0-1.125.504-1.125 1.125v12c0 .621.504 1.125 1.125 1.125h9.75c.621 0 1.125-.504 1.125-1.125V16.5a9 9 0 00-9-9z'
|
||||
/>
|
||||
</svg>
|
||||
Copy Address
|
||||
</button>
|
||||
</div>
|
||||
</Popover.Panel>
|
||||
</Popover>
|
||||
)
|
||||
}
|
||||
|
||||
const Wallet = () => {
|
||||
const [showConnectModal, setShowConnectModal] = useState(false)
|
||||
|
||||
const address = useWalletStore((s) => s.address)
|
||||
|
||||
return (
|
||||
<>
|
||||
{address ? (
|
||||
<WalletPopover>{formatWalletAddress(address)}</WalletPopover>
|
||||
) : (
|
||||
<Button className='w-[200px]' color='primary' onClick={() => setShowConnectModal(true)}>
|
||||
Connect Wallet
|
||||
</Button>
|
||||
)}
|
||||
<ConnectModal isOpen={showConnectModal} onClose={() => setShowConnectModal(false)} />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default Wallet
|
40
components/Wallet/ConnectButton.tsx
Normal file
@ -0,0 +1,40 @@
|
||||
import { useWalletManager, WalletConnectionStatus } from '@marsprotocol/wallet-connector'
|
||||
import { ReactNode } from 'react'
|
||||
|
||||
import CircularProgress from 'components/CircularProgress'
|
||||
import WalletIcon from 'components/Icons/wallet.svg'
|
||||
|
||||
interface Props {
|
||||
textOverride?: string | ReactNode
|
||||
disabled?: boolean
|
||||
status?: WalletConnectionStatus
|
||||
}
|
||||
|
||||
const ConnectButton = ({ textOverride, disabled = false, status }: Props) => {
|
||||
const { connect } = useWalletManager()
|
||||
|
||||
return (
|
||||
<div className='relative'>
|
||||
<button
|
||||
disabled={disabled}
|
||||
className='flex h-[31px] min-w-[186px] flex-1 flex-nowrap content-center items-center justify-center rounded-2xl border border-white/60 bg-black/10 px-4 pt-0.5 text-white text-2xs-caps hover:border-white hover:bg-white/60'
|
||||
onClick={connect}
|
||||
>
|
||||
{status === WalletConnectionStatus.Connecting ? (
|
||||
<span className='flex justify-center'>
|
||||
<CircularProgress size={16} />
|
||||
</span>
|
||||
) : (
|
||||
<>
|
||||
<span className='flex h-4 w-4 items-center justify-center'>
|
||||
<WalletIcon />
|
||||
</span>
|
||||
<span className='ml-2 mt-0.5'>{textOverride || 'Connect Wallet'}</span>
|
||||
</>
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default ConnectButton
|
172
components/Wallet/ConnectedButton.tsx
Normal file
@ -0,0 +1,172 @@
|
||||
import {
|
||||
ChainInfoID,
|
||||
SimpleChainInfoList,
|
||||
useWallet,
|
||||
useWalletManager,
|
||||
} from '@marsprotocol/wallet-connector'
|
||||
import classNames from 'classnames'
|
||||
import { useCallback, useEffect, useState } from 'react'
|
||||
import useClipboard from 'react-use-clipboard'
|
||||
|
||||
import Button from 'components/Button'
|
||||
import CircularProgress from 'components/CircularProgress'
|
||||
import FormattedNumber from 'components/FormattedNumber'
|
||||
import CheckIcon from 'components/Icons/check.svg'
|
||||
import CopyIcon from 'components/Icons/copy.svg'
|
||||
import ExternalLinkIcon from 'components/Icons/external-link.svg'
|
||||
import OsmoIcon from 'components/Icons/osmo.svg'
|
||||
import WalletIcon from 'components/Icons/wallet.svg'
|
||||
import { Overlay } from 'components/Overlay'
|
||||
import Text from 'components/Text'
|
||||
import useTokenBalance from 'hooks/useTokenBalance'
|
||||
import { formatValue, truncate } from 'utils/formatters'
|
||||
|
||||
const ConnectedButton = () => {
|
||||
// ---------------
|
||||
// EXTERNAL HOOKS
|
||||
// ---------------
|
||||
const { disconnect } = useWalletManager()
|
||||
const { chainInfo, address, name } = useWallet()
|
||||
|
||||
// ---------------
|
||||
// LOCAL HOOKS
|
||||
// ---------------
|
||||
const { data } = useTokenBalance()
|
||||
|
||||
// ---------------
|
||||
// LOCAL STATE
|
||||
// ---------------
|
||||
const [isLoading, setIsLoading] = useState(false)
|
||||
const [showDetails, setShowDetails] = useState(false)
|
||||
const [isCopied, setCopied] = useClipboard(address || '', {
|
||||
successDuration: 1000 * 5,
|
||||
})
|
||||
|
||||
// ---------------
|
||||
// VARIABLES
|
||||
// ---------------
|
||||
const explorerName =
|
||||
chainInfo && SimpleChainInfoList[chainInfo.chainId as ChainInfoID].explorerName
|
||||
|
||||
const viewOnFinder = useCallback(() => {
|
||||
const explorerUrl = chainInfo && SimpleChainInfoList[chainInfo.chainId as ChainInfoID].explorer
|
||||
|
||||
window.open(`${explorerUrl}account/${address}`, '_blank')
|
||||
}, [chainInfo, address])
|
||||
|
||||
useEffect(() => {
|
||||
const loading = !(address && name && chainInfo)
|
||||
setIsLoading(loading)
|
||||
}, [address, name, chainInfo])
|
||||
|
||||
return (
|
||||
<div className={'relative'}>
|
||||
{chainInfo?.chainId !== ChainInfoID.Osmosis1 && (
|
||||
<Text
|
||||
className='absolute -right-2 -top-2.5 rounded-lg bg-secondary-highlight p-0.5 px-2'
|
||||
size='3xs'
|
||||
uppercase
|
||||
>
|
||||
{chainInfo?.chainId}
|
||||
</Text>
|
||||
)}
|
||||
|
||||
<button
|
||||
className={classNames(
|
||||
'flex h-[31px] flex-1 flex-nowrap content-center items-center justify-center rounded-2xl border border-white/60 bg-secondary-dark/70 px-4 py-0 text-sm text-white ',
|
||||
'hover:border-white hover:bg-secondary-dark',
|
||||
'active:border-white active:bg-secondary-dark-10',
|
||||
)}
|
||||
onClick={() => {
|
||||
setShowDetails(!showDetails)
|
||||
}}
|
||||
>
|
||||
<span className='flex h-4 w-4 items-center justify-center'>
|
||||
{chainInfo?.chainId === ChainInfoID.Osmosis1 ||
|
||||
chainInfo?.chainId === ChainInfoID.OsmosisTestnet ? (
|
||||
<OsmoIcon />
|
||||
) : (
|
||||
<WalletIcon />
|
||||
)}
|
||||
</span>
|
||||
<span className='ml-2'>{name ? name : truncate(address, [2, 4])}</span>
|
||||
<div
|
||||
className={classNames(
|
||||
'number relative ml-2 flex h-full items-center pl-2',
|
||||
'before:content-[" "] before:absolute before:top-1.5 before:bottom-1.5 before:left-0 before:h-[calc(100%-12px)] before:border-l before:border-white',
|
||||
)}
|
||||
>
|
||||
{!isLoading ? (
|
||||
`${formatValue(data, 2, 2, true, false, ` ${chainInfo?.stakeCurrency?.coinDenom}`)}`
|
||||
) : (
|
||||
<CircularProgress size={12} />
|
||||
)}
|
||||
</div>
|
||||
</button>
|
||||
<Overlay className='right-0 mt-2' show={showDetails} setShow={setShowDetails}>
|
||||
<div className='flex w-[420px] flex-wrap p-6'>
|
||||
<div className='flex-0 mb-4 flex w-full flex-nowrap items-start'>
|
||||
<div className='flex w-auto flex-1'>
|
||||
<div className='mr-2 flex h-[31px] items-end pb-0.5 text-secondary-dark text-base-caps'>
|
||||
{chainInfo?.stakeCurrency?.coinDenom}
|
||||
</div>
|
||||
<div className='flex-0 flex flex-wrap justify-end'>
|
||||
<FormattedNumber
|
||||
animate
|
||||
className='flex items-end text-2xl text-secondary-dark'
|
||||
amount={data}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className='flex h-[31px] w-[116px] justify-end'>
|
||||
<Button color='secondary' onClick={disconnect} text='Disconnect' />
|
||||
</div>
|
||||
</div>
|
||||
<div className='flex w-full flex-wrap'>
|
||||
<Text uppercase className='mb-1 break-all text-secondary-dark/80'>
|
||||
{name ? `‘${name}’` : 'Your Address'}
|
||||
</Text>
|
||||
|
||||
<Text
|
||||
size='sm'
|
||||
className='mb-1 hidden break-all font-bold text-secondary-dark md:block'
|
||||
>
|
||||
{address}
|
||||
</Text>
|
||||
<Text size='sm' className='mb-1 break-all font-bold text-secondary-dark md:hidden'>
|
||||
{truncate(address, [14, 14])}
|
||||
</Text>
|
||||
<div className='flex w-full pt-1'>
|
||||
<button
|
||||
className='mr-10 flex w-auto appearance-none items-center border-none py-2 text-secondary-dark opacity-70 hover:opacity-100'
|
||||
onClick={setCopied}
|
||||
>
|
||||
<span className='mr-1 w-4'>
|
||||
<CopyIcon />
|
||||
</span>
|
||||
{isCopied ? (
|
||||
<Text size='sm'>
|
||||
Copied <CheckIcon />
|
||||
</Text>
|
||||
) : (
|
||||
<Text size='sm'>Copy Address</Text>
|
||||
)}
|
||||
</button>
|
||||
<button
|
||||
className='flex w-auto appearance-none items-center border-none py-2 text-secondary-dark opacity-70 hover:opacity-100'
|
||||
onClick={viewOnFinder}
|
||||
>
|
||||
<span className='mr-1 w-4'>
|
||||
<ExternalLinkIcon />
|
||||
</span>
|
||||
<Text size='sm'>View on {explorerName}</Text>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Overlay>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default ConnectedButton
|
20
components/Wallet/Wallet.tsx
Normal file
@ -0,0 +1,20 @@
|
||||
import { useWallet, WalletConnectionStatus } from '@marsprotocol/wallet-connector'
|
||||
import { useEffect, useState } from 'react'
|
||||
|
||||
import { ConnectButton, ConnectedButton } from 'components/Wallet'
|
||||
|
||||
const Wallet = () => {
|
||||
const { status } = useWallet()
|
||||
const [isConnected, setIsConnected] = useState(false)
|
||||
|
||||
useEffect(() => {
|
||||
const connectedStatus = status === WalletConnectionStatus.Connected
|
||||
if (connectedStatus !== isConnected) {
|
||||
setIsConnected(connectedStatus)
|
||||
}
|
||||
}, [status, isConnected])
|
||||
|
||||
return !isConnected ? <ConnectButton status={status} /> : <ConnectedButton />
|
||||
}
|
||||
|
||||
export default Wallet
|
82
components/Wallet/WalletConnectProvider.tsx
Normal file
@ -0,0 +1,82 @@
|
||||
import { ChainInfoID, WalletManagerProvider, WalletType } from '@marsprotocol/wallet-connector'
|
||||
import { FC } from 'react'
|
||||
|
||||
import { buttonColorClasses, buttonSizeClasses, buttonVariantClasses } from 'components/Button'
|
||||
import CircularProgress from 'components/CircularProgress'
|
||||
import CloseIcon from 'components/Icons/close.svg'
|
||||
import KeplrImage from 'public/images/keplr-wallet-extension.png'
|
||||
import WalletConnectImage from 'public/images/walletconnect-keplr.png'
|
||||
|
||||
type Props = {
|
||||
children?: React.ReactNode
|
||||
}
|
||||
|
||||
const WalletConnectProvider: FC<Props> = ({ children }) => {
|
||||
return (
|
||||
<WalletManagerProvider
|
||||
chainInfoOverrides={{
|
||||
[ChainInfoID.OsmosisTestnet]: {
|
||||
rpc: 'https://osmosis-delphi-testnet-1.simply-vc.com.mt/XF32UOOU55CX/osmosis-rpc',
|
||||
rest: 'https://osmosis-delphi-testnet-1.simply-vc.com.mt/XF32UOOU55CX/osmosis-lcd',
|
||||
},
|
||||
}}
|
||||
classNames={{
|
||||
modalContent:
|
||||
'flex h-fit w-[500px] max-w-full overflow-hidden rounded-xl border-[7px] border-accent-highlight p-4 gradient-card flex-col outline-none relative',
|
||||
modalOverlay:
|
||||
'bg-black/60 fixed top-0 left-0 w-screen h-screen z-50 flex items-center justify-center cursor-pointer backdrop-blur',
|
||||
modalHeader: 'text-2xl-caps text-center text-white mb-4',
|
||||
walletList: 'flex flex-col gap-4 py-2',
|
||||
wallet:
|
||||
'bg-transparent rounded-base p-2 shadow-none flex items-center appearance-none border-none w-full no-underline cursor-pointer hover:bg-white/10 disabled:pointer-events-none disabled:opacity-50',
|
||||
walletImage: 'h-15 w-15',
|
||||
walletInfo: 'flex flex-col ml-5',
|
||||
walletName: 'text-lg-caps text-white',
|
||||
walletDescription: 'mt-1 text-white/40 text-base text-left',
|
||||
textContent: 'block w-full text-center text-base text-white',
|
||||
}}
|
||||
closeIcon={
|
||||
<span className='flex w-8 text-white/70 hover:text-white'>
|
||||
<CloseIcon />
|
||||
</span>
|
||||
}
|
||||
defaultChainId={ChainInfoID.OsmosisTestnet}
|
||||
enabledWalletTypes={[WalletType.Keplr, WalletType.WalletConnectKeplr]}
|
||||
enablingMeta={{
|
||||
text: 'If nothing shows up in your wallet try to connect again, by clicking on the button below. Refresh the page if the problem persists.',
|
||||
textClassName: 'block w-full text-center text-base text-white',
|
||||
buttonText: 'Retry the Connection',
|
||||
buttonClassName: `cursor-pointer appearance-none break-normal rounded-3xl outline-none transition-colors ${buttonColorClasses.primary} ${buttonSizeClasses.small} ${buttonVariantClasses.solid}`,
|
||||
contentClassName: 'flex flex-wrap w-full justify-center',
|
||||
}}
|
||||
enablingStringOverride='connecting to wallet'
|
||||
localStorageKey='walletConnection'
|
||||
renderLoader={() => (
|
||||
<div className='my-4 flex w-full justify-center'>
|
||||
<CircularProgress size={30} />
|
||||
</div>
|
||||
)}
|
||||
walletConnectClientMeta={{
|
||||
name: 'Mars Protocol',
|
||||
description: 'Mars V2 Description',
|
||||
url: 'https://marsprotocol.io',
|
||||
icons: ['https://marsprotocol.io/favicon.svg'],
|
||||
}}
|
||||
walletMetaOverride={{
|
||||
[WalletType.Keplr]: {
|
||||
description: 'Keplr browser extension',
|
||||
imageUrl: KeplrImage.src,
|
||||
},
|
||||
[WalletType.WalletConnectKeplr]: {
|
||||
name: 'Wallet Connect',
|
||||
description: 'Keplr mobile WalletConnect',
|
||||
imageUrl: WalletConnectImage.src,
|
||||
},
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</WalletManagerProvider>
|
||||
)
|
||||
}
|
||||
|
||||
export default WalletConnectProvider
|
3
components/Wallet/index.tsx
Normal file
@ -0,0 +1,3 @@
|
||||
export { default as ConnectButton } from './ConnectButton'
|
||||
export { default as ConnectedButton } from './ConnectedButton'
|
||||
export { default as Wallet } from './Wallet'
|
@ -2,8 +2,7 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react
|
||||
import { useMemo } from 'react'
|
||||
import { toast } from 'react-toastify'
|
||||
|
||||
import useCreditManagerStore from 'stores/useCreditManagerStore'
|
||||
import useWalletStore from 'stores/useWalletStore'
|
||||
import { useAccountDetailsStore, useWalletStore } from 'stores'
|
||||
import { queryKeys } from 'types/query-keys-factory'
|
||||
import { hardcodedFee } from 'utils/contants'
|
||||
|
||||
@ -14,7 +13,7 @@ const useBorrowFunds = (
|
||||
options: Omit<UseMutationOptions, 'onError'>,
|
||||
) => {
|
||||
const creditManagerClient = useWalletStore((s) => s.clients.creditManager)
|
||||
const selectedAccount = useCreditManagerStore((s) => s.selectedAccount ?? '')
|
||||
const selectedAccount = useAccountDetailsStore((s) => s.selectedAccount ?? '')
|
||||
const address = useWalletStore((s) => s.address)
|
||||
|
||||
const queryClient = useQueryClient()
|
||||
@ -60,8 +59,8 @@ const useBorrowFunds = (
|
||||
|
||||
// if withdrawing to wallet, need to explicility invalidate balances queries
|
||||
if (withdraw) {
|
||||
queryClient.invalidateQueries(queryKeys.tokenBalance(address, denom))
|
||||
queryClient.invalidateQueries(queryKeys.allBalances(address))
|
||||
queryClient.invalidateQueries(queryKeys.tokenBalance(address ?? '', denom))
|
||||
queryClient.invalidateQueries(queryKeys.allBalances(address ?? ''))
|
||||
}
|
||||
},
|
||||
onError: (err: Error) => {
|
||||
|
@ -2,8 +2,7 @@ import { useMutation, useQueryClient } from '@tanstack/react-query'
|
||||
import { toast } from 'react-toastify'
|
||||
|
||||
import { contractAddresses } from 'config/contracts'
|
||||
import useCreditManagerStore from 'stores/useCreditManagerStore'
|
||||
import useWalletStore from 'stores/useWalletStore'
|
||||
import { useAccountDetailsStore, useWalletStore } from 'stores'
|
||||
import { queryKeys } from 'types/query-keys-factory'
|
||||
import { hardcodedFee } from 'utils/contants'
|
||||
|
||||
@ -14,7 +13,6 @@ const executeMsg = {
|
||||
|
||||
const useCreateCreditAccount = () => {
|
||||
const signingClient = useWalletStore((s) => s.signingClient)
|
||||
const setSelectedAccount = useCreditManagerStore((s) => s.actions.setSelectedAccount)
|
||||
const address = useWalletStore((s) => s.address)
|
||||
|
||||
const queryClient = useQueryClient()
|
||||
@ -22,14 +20,14 @@ const useCreateCreditAccount = () => {
|
||||
return useMutation(
|
||||
async () =>
|
||||
await signingClient?.execute(
|
||||
address,
|
||||
address ?? '',
|
||||
contractAddresses.creditManager,
|
||||
executeMsg,
|
||||
hardcodedFee,
|
||||
),
|
||||
{
|
||||
onSettled: () => {
|
||||
queryClient.invalidateQueries(queryKeys.creditAccounts(address))
|
||||
queryClient.invalidateQueries(queryKeys.creditAccounts(address ?? ''))
|
||||
},
|
||||
onError: (err: Error) => {
|
||||
toast.error(err.message)
|
||||
@ -39,7 +37,7 @@ const useCreateCreditAccount = () => {
|
||||
|
||||
// TODO: is there some better way to parse response to extract token id???
|
||||
const createdID = data.logs[0].events[2].attributes[6].value
|
||||
setSelectedAccount(createdID)
|
||||
useAccountDetailsStore.setState({ selectedAccount: createdID })
|
||||
toast.success('New account created')
|
||||
},
|
||||
},
|
||||
|
@ -2,7 +2,7 @@ import { useMutation, useQueryClient } from '@tanstack/react-query'
|
||||
import { toast } from 'react-toastify'
|
||||
|
||||
import { contractAddresses } from 'config/contracts'
|
||||
import useWalletStore from 'stores/useWalletStore'
|
||||
import { useWalletStore } from 'stores'
|
||||
import { queryKeys } from 'types/query-keys-factory'
|
||||
import { hardcodedFee } from 'utils/contants'
|
||||
|
||||
@ -15,7 +15,7 @@ const useCreateCreditAccount = (accountId: string) => {
|
||||
return useMutation(
|
||||
async () =>
|
||||
await signingClient?.execute(
|
||||
address,
|
||||
address ?? '',
|
||||
contractAddresses.accountNft,
|
||||
{
|
||||
burn: {
|
||||
@ -26,7 +26,7 @@ const useCreateCreditAccount = (accountId: string) => {
|
||||
),
|
||||
{
|
||||
onSettled: () => {
|
||||
queryClient.invalidateQueries(queryKeys.creditAccounts(address))
|
||||
queryClient.invalidateQueries(queryKeys.creditAccounts(address ?? ''))
|
||||
},
|
||||
onError: (err: Error) => {
|
||||
toast.error(err.message)
|
||||
|
@ -2,7 +2,7 @@ import { useMutation, useQueryClient } from '@tanstack/react-query'
|
||||
import { toast } from 'react-toastify'
|
||||
|
||||
import { contractAddresses } from 'config/contracts'
|
||||
import useWalletStore from 'stores/useWalletStore'
|
||||
import { useWalletStore } from 'stores'
|
||||
import { queryKeys } from 'types/query-keys-factory'
|
||||
import { hardcodedFee } from 'utils/contants'
|
||||
|
||||
@ -22,7 +22,7 @@ const useDepositCreditAccount = (
|
||||
return useMutation(
|
||||
async () =>
|
||||
await signingClient?.execute(
|
||||
address,
|
||||
address ?? '',
|
||||
contractAddresses.creditManager,
|
||||
{
|
||||
update_credit_account: {
|
||||
@ -51,8 +51,8 @@ const useDepositCreditAccount = (
|
||||
toast.error(err.message)
|
||||
},
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries(queryKeys.allBalances(address))
|
||||
queryClient.invalidateQueries(queryKeys.tokenBalance(address, denom))
|
||||
queryClient.invalidateQueries(queryKeys.allBalances(address ?? ''))
|
||||
queryClient.invalidateQueries(queryKeys.tokenBalance(address ?? '', denom))
|
||||
queryClient.invalidateQueries(queryKeys.creditAccountsPositions(accountId))
|
||||
|
||||
options?.onSuccess && options.onSuccess()
|
||||
|
@ -2,9 +2,7 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react
|
||||
import { useMemo } from 'react'
|
||||
import { toast } from 'react-toastify'
|
||||
|
||||
import { contractAddresses } from 'config/contracts'
|
||||
import useCreditManagerStore from 'stores/useCreditManagerStore'
|
||||
import useWalletStore from 'stores/useWalletStore'
|
||||
import { useAccountDetailsStore, useWalletStore } from 'stores'
|
||||
import { queryKeys } from 'types/query-keys-factory'
|
||||
import { hardcodedFee } from 'utils/contants'
|
||||
|
||||
@ -14,7 +12,7 @@ const useRepayFunds = (
|
||||
options: Omit<UseMutationOptions, 'onError'>,
|
||||
) => {
|
||||
const creditManagerClient = useWalletStore((s) => s.clients.creditManager)
|
||||
const selectedAccount = useCreditManagerStore((s) => s.selectedAccount ?? '')
|
||||
const selectedAccount = useAccountDetailsStore((s) => s.selectedAccount ?? '')
|
||||
const address = useWalletStore((s) => s.address)
|
||||
|
||||
const queryClient = useQueryClient()
|
||||
@ -52,8 +50,8 @@ const useRepayFunds = (
|
||||
{
|
||||
onSettled: () => {
|
||||
queryClient.invalidateQueries(queryKeys.creditAccountsPositions(selectedAccount))
|
||||
queryClient.invalidateQueries(queryKeys.tokenBalance(address, denom))
|
||||
queryClient.invalidateQueries(queryKeys.allBalances(address))
|
||||
queryClient.invalidateQueries(queryKeys.tokenBalance(address ?? '', denom))
|
||||
queryClient.invalidateQueries(queryKeys.allBalances(address ?? ''))
|
||||
queryClient.invalidateQueries(queryKeys.redbankBalances())
|
||||
},
|
||||
onError: (err: Error) => {
|
||||
|
@ -2,11 +2,10 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react
|
||||
import { useMemo } from 'react'
|
||||
import { toast } from 'react-toastify'
|
||||
|
||||
import useCreditManagerStore from 'stores/useCreditManagerStore'
|
||||
import useWalletStore from 'stores/useWalletStore'
|
||||
import { useAccountDetailsStore, useWalletStore } from 'stores'
|
||||
import { Action } from 'types/generated/mars-credit-manager/MarsCreditManager.types'
|
||||
import { queryKeys } from 'types/query-keys-factory'
|
||||
import { hardcodedFee } from 'utils/contants'
|
||||
import { Action } from 'types/generated/mars-credit-manager/MarsCreditManager.types'
|
||||
|
||||
const useTradeAsset = (
|
||||
amount: number,
|
||||
@ -18,7 +17,7 @@ const useTradeAsset = (
|
||||
options?: Omit<UseMutationOptions, 'onError'>,
|
||||
) => {
|
||||
const creditManagerClient = useWalletStore((s) => s.clients.creditManager)
|
||||
const selectedAccount = useCreditManagerStore((s) => s.selectedAccount ?? '')
|
||||
const selectedAccount = useAccountDetailsStore((s) => s.selectedAccount ?? '')
|
||||
|
||||
const queryClient = useQueryClient()
|
||||
|
||||
|
@ -2,8 +2,7 @@ import { useMutation, useQueryClient } from '@tanstack/react-query'
|
||||
import { useMemo } from 'react'
|
||||
import { toast } from 'react-toastify'
|
||||
|
||||
import useCreditManagerStore from 'stores/useCreditManagerStore'
|
||||
import useWalletStore from 'stores/useWalletStore'
|
||||
import { useAccountDetailsStore, useWalletStore } from 'stores'
|
||||
import { queryKeys } from 'types/query-keys-factory'
|
||||
import { hardcodedFee } from 'utils/contants'
|
||||
|
||||
@ -15,7 +14,7 @@ const useWithdrawFunds = (
|
||||
onSuccess?: () => void
|
||||
},
|
||||
) => {
|
||||
const selectedAccount = useCreditManagerStore((s) => s.selectedAccount ?? '')
|
||||
const selectedAccount = useAccountDetailsStore((s) => s.selectedAccount ?? '')
|
||||
const address = useWalletStore((s) => s.address)
|
||||
const creditManagerClient = useWalletStore((s) => s.clients.creditManager)
|
||||
|
||||
@ -60,8 +59,8 @@ const useWithdrawFunds = (
|
||||
{
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries(queryKeys.creditAccountsPositions(selectedAccount))
|
||||
queryClient.invalidateQueries(queryKeys.tokenBalance(address, denom))
|
||||
queryClient.invalidateQueries(queryKeys.allBalances(address))
|
||||
queryClient.invalidateQueries(queryKeys.tokenBalance(address ?? '', denom))
|
||||
queryClient.invalidateQueries(queryKeys.allBalances(address ?? ''))
|
||||
queryClient.invalidateQueries(queryKeys.redbankBalances())
|
||||
|
||||
onSuccess && onSuccess()
|
||||
|
@ -1,7 +1,7 @@
|
||||
import BigNumber from 'bignumber.js'
|
||||
import { useMemo } from 'react'
|
||||
|
||||
import useCreditManagerStore from 'stores/useCreditManagerStore'
|
||||
import { useAccountDetailsStore } from 'stores'
|
||||
|
||||
import useCreditAccountPositions from './useCreditAccountPositions'
|
||||
import useMarkets from './useMarkets'
|
||||
@ -89,7 +89,7 @@ export type AccountStatsAction = {
|
||||
}
|
||||
|
||||
const useAccountStats = (actions?: AccountStatsAction[]) => {
|
||||
const selectedAccount = useCreditManagerStore((s) => s.selectedAccount)
|
||||
const selectedAccount = useAccountDetailsStore((s) => s.selectedAccount)
|
||||
|
||||
const { data: positionsData } = useCreditAccountPositions(selectedAccount ?? '')
|
||||
const { data: marketsData } = useMarkets()
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
|
||||
import useWalletStore from 'stores/useWalletStore'
|
||||
import { useWalletStore } from 'stores'
|
||||
import { queryKeys } from 'types/query-keys-factory'
|
||||
import { chain } from 'utils/chains'
|
||||
|
||||
@ -12,7 +12,7 @@ const useAllBalances = () => {
|
||||
const address = useWalletStore((s) => s.address)
|
||||
|
||||
const result = useQuery<Result>(
|
||||
queryKeys.allBalances(address),
|
||||
queryKeys.allBalances(address ?? ''),
|
||||
() => fetch(`${chain.rest}/cosmos/bank/v1beta1/balances/${address}`).then((res) => res.json()),
|
||||
{
|
||||
enabled: !!address,
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
|
||||
import { contractAddresses } from 'config/contracts'
|
||||
import useWalletStore from 'stores/useWalletStore'
|
||||
import { useWalletStore } from 'stores'
|
||||
import { queryKeys } from 'types/query-keys-factory'
|
||||
|
||||
type Result = string[]
|
||||
@ -11,7 +11,7 @@ const queryMsg = {
|
||||
}
|
||||
|
||||
const useAllowedCoins = () => {
|
||||
const client = useWalletStore((s) => s.client)
|
||||
const client = useWalletStore((s) => s.signingClient)
|
||||
|
||||
const result = useQuery<Result>(
|
||||
queryKeys.allowedCoins(),
|
||||
|
@ -1,7 +1,7 @@
|
||||
import BigNumber from 'bignumber.js'
|
||||
import { useCallback, useMemo } from 'react'
|
||||
|
||||
import useCreditManagerStore from 'stores/useCreditManagerStore'
|
||||
import { useAccountDetailsStore } from 'stores'
|
||||
import { getTokenDecimals } from 'utils/tokens'
|
||||
|
||||
import useCreditAccountPositions from './useCreditAccountPositions'
|
||||
@ -16,7 +16,7 @@ const getApproximateHourlyInterest = (amount: string, borrowAPY: string) => {
|
||||
}
|
||||
|
||||
const useCalculateMaxBorrowAmount = (denom: string, isUnderCollateralized: boolean) => {
|
||||
const selectedAccount = useCreditManagerStore((s) => s.selectedAccount)
|
||||
const selectedAccount = useAccountDetailsStore((s) => s.selectedAccount)
|
||||
|
||||
const { data: positionsData } = useCreditAccountPositions(selectedAccount ?? '')
|
||||
const { data: marketsData } = useMarkets()
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { useCallback, useMemo } from 'react'
|
||||
import BigNumber from 'bignumber.js'
|
||||
import { useCallback, useMemo } from 'react'
|
||||
|
||||
import useCreditManagerStore from 'stores/useCreditManagerStore'
|
||||
import { useAccountDetailsStore } from 'stores'
|
||||
|
||||
import useCreditAccountPositions from './useCreditAccountPositions'
|
||||
import useMarkets from './useMarkets'
|
||||
@ -17,7 +17,7 @@ const getApproximateHourlyInterest = (amount: string, borrowAPY: string) => {
|
||||
// max trade amount doesnt consider wallet balance as its not relevant
|
||||
// the entire token balance within the wallet will always be able to be fully swapped
|
||||
const useCalculateMaxTradeAmount = (tokenIn: string, tokenOut: string, isMargin: boolean) => {
|
||||
const selectedAccount = useCreditManagerStore((s) => s.selectedAccount)
|
||||
const selectedAccount = useAccountDetailsStore((s) => s.selectedAccount)
|
||||
|
||||
const { data: positionsData } = useCreditAccountPositions(selectedAccount ?? '')
|
||||
const { data: marketsData } = useMarkets()
|
||||
|
@ -1,13 +1,13 @@
|
||||
import BigNumber from 'bignumber.js'
|
||||
import { useCallback, useMemo } from 'react'
|
||||
|
||||
import useCreditManagerStore from 'stores/useCreditManagerStore'
|
||||
import { useAccountDetailsStore } from 'stores'
|
||||
import { getTokenDecimals } from 'utils/tokens'
|
||||
|
||||
import useCreditAccountPositions from './useCreditAccountPositions'
|
||||
import useMarkets from './useMarkets'
|
||||
import useTokenPrices from './useTokenPrices'
|
||||
import useRedbankBalances from './useRedbankBalances'
|
||||
import useTokenPrices from './useTokenPrices'
|
||||
|
||||
const getApproximateHourlyInterest = (amount: string, borrowAPY: string) => {
|
||||
const hourlyAPY = BigNumber(borrowAPY).div(24 * 365)
|
||||
@ -16,7 +16,7 @@ const getApproximateHourlyInterest = (amount: string, borrowAPY: string) => {
|
||||
}
|
||||
|
||||
const useCalculateMaxWithdrawAmount = (denom: string, borrow: boolean) => {
|
||||
const selectedAccount = useCreditManagerStore((s) => s.selectedAccount)
|
||||
const selectedAccount = useAccountDetailsStore((s) => s.selectedAccount)
|
||||
|
||||
const { data: positionsData } = useCreditAccountPositions(selectedAccount ?? '')
|
||||
const { data: marketsData } = useMarkets()
|
||||
|
@ -3,7 +3,7 @@ import { useQuery } from '@tanstack/react-query'
|
||||
import { useMemo } from 'react'
|
||||
|
||||
import { contractAddresses } from 'config/contracts'
|
||||
import useWalletStore from 'stores/useWalletStore'
|
||||
import { useWalletStore } from 'stores'
|
||||
import { queryKeys } from 'types/query-keys-factory'
|
||||
|
||||
interface DebtAmount {
|
||||
@ -26,7 +26,7 @@ interface Result {
|
||||
|
||||
const useCreditAccountPositions = (accountId: string) => {
|
||||
const address = useWalletStore((s) => s.address)
|
||||
const client = useWalletStore((s) => s.client)
|
||||
const client = useWalletStore((s) => s.signingClient)
|
||||
|
||||
const result = useQuery<Result>(
|
||||
queryKeys.creditAccountsPositions(accountId),
|
||||
|
@ -2,8 +2,7 @@ import { useQuery } from '@tanstack/react-query'
|
||||
import { useMemo } from 'react'
|
||||
|
||||
import { contractAddresses } from 'config/contracts'
|
||||
import useCreditManagerStore from 'stores/useCreditManagerStore'
|
||||
import useWalletStore from 'stores/useWalletStore'
|
||||
import { useAccountDetailsStore, useWalletStore } from 'stores'
|
||||
import { queryKeys } from 'types/query-keys-factory'
|
||||
|
||||
type Result = {
|
||||
@ -12,9 +11,11 @@ type Result = {
|
||||
|
||||
const useCreditAccounts = () => {
|
||||
const address = useWalletStore((s) => s.address)
|
||||
const client = useWalletStore((s) => s.client)
|
||||
const selectedAccount = useCreditManagerStore((s) => s.selectedAccount)
|
||||
const creditManagerActions = useCreditManagerStore((s) => s.actions)
|
||||
const client = useWalletStore((s) => s.signingClient)
|
||||
const selectedAccount = useAccountDetailsStore((s) => s.selectedAccount)
|
||||
const setSelectedAccount = (account: string) => {
|
||||
useAccountDetailsStore.setState({ selectedAccount: account })
|
||||
}
|
||||
|
||||
const queryMsg = useMemo(() => {
|
||||
return {
|
||||
@ -25,14 +26,14 @@ const useCreditAccounts = () => {
|
||||
}, [address])
|
||||
|
||||
const result = useQuery<Result>(
|
||||
queryKeys.creditAccounts(address),
|
||||
queryKeys.creditAccounts(address ?? ''),
|
||||
async () => client?.queryContractSmart(contractAddresses.accountNft, queryMsg),
|
||||
{
|
||||
staleTime: Infinity,
|
||||
enabled: !!address && !!client,
|
||||
onSuccess: (data) => {
|
||||
if (!data.tokens.includes(selectedAccount || '') && data.tokens.length > 0) {
|
||||
creditManagerActions.setSelectedAccount(data.tokens[0])
|
||||
setSelectedAccount(data.tokens[0])
|
||||
}
|
||||
},
|
||||
},
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
import BigNumber from 'bignumber.js'
|
||||
|
||||
import useWalletStore from 'stores/useWalletStore'
|
||||
import { useWalletStore } from 'stores'
|
||||
import { queryKeys } from 'types/query-keys-factory'
|
||||
import { chain } from 'utils/chains'
|
||||
|
||||
@ -16,7 +16,7 @@ const useTokenBalance = (denom?: string) => {
|
||||
const address = useWalletStore((s) => s.address)
|
||||
|
||||
const result = useQuery<Result>(
|
||||
queryKeys.tokenBalance(address, denom || chain.stakeCurrency.coinMinimalDenom),
|
||||
queryKeys.tokenBalance(address ?? '', denom || chain.stakeCurrency.coinMinimalDenom),
|
||||
async () =>
|
||||
fetch(
|
||||
`${chain.rest}/cosmos/bank/v1beta1/balances/${address}/by_denom?denom=${
|
||||
|
@ -10,10 +10,10 @@
|
||||
"start": "next start"
|
||||
},
|
||||
"dependencies": {
|
||||
"@cosmjs/cosmwasm-stargate": "^0.29.0",
|
||||
"@cosmjs/stargate": "^0.29.0",
|
||||
"@cosmjs/cosmwasm-stargate": "^0.29.4",
|
||||
"@cosmjs/stargate": "^0.29.4",
|
||||
"@headlessui/react": "^1.7.0",
|
||||
"@keplr-wallet/cosmos": "^0.10.24",
|
||||
"@marsprotocol/wallet-connector": "^0.9.5",
|
||||
"@metamask/detect-provider": "^1.2.0",
|
||||
"@radix-ui/react-slider": "^1.0.0",
|
||||
"@sentry/nextjs": "^7.12.1",
|
||||
@ -33,12 +33,12 @@
|
||||
"react-number-format": "^5.1.0",
|
||||
"react-spring": "^9.5.5",
|
||||
"react-toastify": "^9.0.8",
|
||||
"react-use-clipboard": "^1.0.9",
|
||||
"tailwindcss-border-gradient-radius": "^3.0.1",
|
||||
"use-local-storage-state": "^18.1.1",
|
||||
"zustand": "^4.1.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@keplr-wallet/types": "^0.10.24",
|
||||
"@svgr/webpack": "^6.4.0",
|
||||
"@types/node": "18.11.11",
|
||||
"@types/react": "18.0.26",
|
||||
|
21
pages/404.tsx
Normal file
@ -0,0 +1,21 @@
|
||||
import Button from 'components/Button'
|
||||
import Card from 'components/Card'
|
||||
import Text from 'components/Text'
|
||||
|
||||
const Error404 = () => {
|
||||
return (
|
||||
<div className='flex w-full'>
|
||||
<Card>
|
||||
<Text size='2xl' uppercase className='text-center'>
|
||||
Oooops...
|
||||
</Text>
|
||||
<Text className='my-4 text-center'>Looks like this page doesn't exist!</Text>
|
||||
<div className='flex justify-center'>
|
||||
<Button onClick={() => (location.href = '/trade')} text='Home'></Button>
|
||||
</div>
|
||||
</Card>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Error404
|
@ -1,60 +1,42 @@
|
||||
import 'react-toastify/dist/ReactToastify.min.css'
|
||||
import '../styles/globals.css'
|
||||
|
||||
import detectEthereumProvider from '@metamask/detect-provider'
|
||||
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
|
||||
import { ReactQueryDevtools } from '@tanstack/react-query-devtools'
|
||||
import type { AppProps } from 'next/app'
|
||||
import Head from 'next/head'
|
||||
import { useEffect } from 'react'
|
||||
import { ToastContainer, Zoom } from 'react-toastify'
|
||||
|
||||
import Layout from 'components/Layout'
|
||||
import useWalletStore from 'stores/useWalletStore'
|
||||
|
||||
async function isMetamaskInstalled(): Promise<boolean> {
|
||||
const provider = await detectEthereumProvider()
|
||||
|
||||
return !!provider
|
||||
}
|
||||
import Modals from 'components/Modals'
|
||||
import WalletConnectProvider from 'components/Wallet/WalletConnectProvider'
|
||||
|
||||
const queryClient = new QueryClient()
|
||||
|
||||
function MyApp({ Component, pageProps }: AppProps) {
|
||||
const actions = useWalletStore((s) => s.actions)
|
||||
|
||||
// init store
|
||||
useEffect(() => {
|
||||
const verifyMetamask = async () => {
|
||||
actions.setMetamaskInstalledStatus(await isMetamaskInstalled())
|
||||
}
|
||||
|
||||
actions.initialize()
|
||||
|
||||
verifyMetamask()
|
||||
}, [actions])
|
||||
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>Mars V2</title>
|
||||
{/* <meta name="description" content="Generated by create next app" /> */}
|
||||
<link rel='icon' href='/favicon.svg' />
|
||||
</Head>
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<ReactQueryDevtools initialIsOpen={false} />
|
||||
<Layout>
|
||||
<Component {...pageProps} />
|
||||
</Layout>
|
||||
<ToastContainer
|
||||
autoClose={1500}
|
||||
closeButton={false}
|
||||
position='bottom-right'
|
||||
hideProgressBar
|
||||
newestOnTop
|
||||
transition={Zoom}
|
||||
/>
|
||||
</QueryClientProvider>
|
||||
<WalletConnectProvider>
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<ReactQueryDevtools initialIsOpen={false} />
|
||||
<Layout>
|
||||
<Component {...pageProps} />
|
||||
</Layout>
|
||||
<Modals />
|
||||
<ToastContainer
|
||||
autoClose={1500}
|
||||
closeButton={false}
|
||||
position='bottom-right'
|
||||
hideProgressBar
|
||||
newestOnTop
|
||||
transition={Zoom}
|
||||
/>
|
||||
</QueryClientProvider>
|
||||
</WalletConnectProvider>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ import useCreditAccountPositions from 'hooks/useCreditAccountPositions'
|
||||
import useMarkets from 'hooks/useMarkets'
|
||||
import useRedbankBalances from 'hooks/useRedbankBalances'
|
||||
import useTokenPrices from 'hooks/useTokenPrices'
|
||||
import useCreditManagerStore from 'stores/useCreditManagerStore'
|
||||
import { useAccountDetailsStore } from 'stores'
|
||||
import { getTokenDecimals, getTokenInfo } from 'utils/tokens'
|
||||
|
||||
type ModalState = {
|
||||
@ -27,7 +27,7 @@ const Borrow = () => {
|
||||
data: { tokenDenom: '' },
|
||||
})
|
||||
|
||||
const selectedAccount = useCreditManagerStore((s) => s.selectedAccount)
|
||||
const selectedAccount = useAccountDetailsStore((s) => s.selectedAccount)
|
||||
|
||||
const { data: allowedCoinsData } = useAllowedCoins()
|
||||
const { data: positionsData } = useCreditAccountPositions(selectedAccount ?? '')
|
||||
@ -120,7 +120,7 @@ const Borrow = () => {
|
||||
<div className='flex-1'>
|
||||
<Card className='mb-4'>
|
||||
<div>
|
||||
<Text tag='h3' size='xl' uppercase={true} className='mb-7 text-center'>
|
||||
<Text tag='h3' size='xl' uppercase className='mb-7 text-center'>
|
||||
Borrowings
|
||||
</Text>
|
||||
<BorrowTable
|
||||
@ -132,7 +132,7 @@ const Borrow = () => {
|
||||
</Card>
|
||||
<Card>
|
||||
<div>
|
||||
<Text tag='h3' size='xl' uppercase={true} className='mb-7 text-center text-lg-caps'>
|
||||
<Text tag='h3' size='xl' uppercase className='mb-7 text-center text-lg-caps'>
|
||||
Available to Borrow
|
||||
</Text>
|
||||
<BorrowTable
|
||||
|
@ -5,7 +5,7 @@ const Council = () => {
|
||||
return (
|
||||
<div className='flex w-full'>
|
||||
<Card>
|
||||
<Text size='lg' uppercase={true}>
|
||||
<Text size='lg' uppercase>
|
||||
Council Placeholder
|
||||
</Text>
|
||||
</Card>
|
||||
|
@ -5,13 +5,13 @@ const Earn = () => {
|
||||
return (
|
||||
<div className='flex w-full gap-4'>
|
||||
<Card>
|
||||
<Text size='lg' uppercase={true}>
|
||||
<Text size='lg' uppercase>
|
||||
Yield Module
|
||||
</Text>
|
||||
</Card>
|
||||
<div className='w-[450px]'>
|
||||
<Card>
|
||||
<Text size='lg' uppercase={true}>
|
||||
<Text size='lg' uppercase>
|
||||
Placeholder
|
||||
</Text>
|
||||
</Card>
|
||||
|
@ -5,7 +5,7 @@ import Text from 'components/Text'
|
||||
const mockedAccounts = [
|
||||
{
|
||||
id: 1,
|
||||
label: 'Subaccount 1',
|
||||
label: 'Account 1',
|
||||
networth: 100000,
|
||||
totalPositionValue: 150000,
|
||||
debt: 50000,
|
||||
@ -15,7 +15,7 @@ const mockedAccounts = [
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
label: 'Subaccount 2',
|
||||
label: 'Account 2',
|
||||
networth: 33000,
|
||||
totalPositionValue: 11000,
|
||||
debt: 20000,
|
||||
@ -25,7 +25,7 @@ const mockedAccounts = [
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
label: 'Subaccount 3',
|
||||
label: 'Account 3',
|
||||
networth: 0,
|
||||
totalPositionValue: 12938129,
|
||||
debt: 9999999999,
|
||||
@ -35,7 +35,7 @@ const mockedAccounts = [
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
label: 'Subaccount 4',
|
||||
label: 'Account 4',
|
||||
networth: 33653.22,
|
||||
totalPositionValue: 100000,
|
||||
debt: 50001.9,
|
||||
@ -49,14 +49,14 @@ const Portfolio = () => {
|
||||
return (
|
||||
<div className='flex w-full items-start gap-4'>
|
||||
<Card className='flex-1'>
|
||||
<Text size='lg' uppercase={true}>
|
||||
<Text size='lg' uppercase>
|
||||
Portfolio Module
|
||||
</Text>
|
||||
</Card>
|
||||
<div className='grid grid-cols-2 gap-4'>
|
||||
{mockedAccounts.map((account) => (
|
||||
<Card key={account.id}>
|
||||
<Text size='lg' uppercase={true} className='mb-4 text-center'>
|
||||
<Text size='lg' uppercase className='mb-4 text-center'>
|
||||
{account.label}
|
||||
</Text>
|
||||
<div className='grid grid-cols-3 gap-4'>
|
||||
|
@ -7,7 +7,7 @@ const Trade = () => {
|
||||
<div className='flex w-full flex-wrap'>
|
||||
<div className='mb-4 flex flex-grow gap-4'>
|
||||
<Card className='flex-1'>
|
||||
<Text size='lg' uppercase={true}>
|
||||
<Text size='lg' uppercase>
|
||||
Tradingview Graph
|
||||
</Text>
|
||||
</Card>
|
||||
@ -16,14 +16,14 @@ const Trade = () => {
|
||||
<TradeActionModule />
|
||||
</Card>
|
||||
<Card>
|
||||
<Text size='lg' uppercase={true}>
|
||||
<Text size='lg' uppercase>
|
||||
Orderbook module (optional)
|
||||
</Text>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
<Card>
|
||||
<Text size='lg' uppercase={true}>
|
||||
<Text size='lg' uppercase>
|
||||
Order history
|
||||
</Text>
|
||||
</Card>
|
||||
|
BIN
public/images/keplr-wallet-extension.png
Normal file
After Width: | Height: | Size: 7.9 KiB |
BIN
public/images/walletconnect-keplr.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
3
stores/index.tsx
Normal file
@ -0,0 +1,3 @@
|
||||
export { useAccountDetailsStore } from './useAccountDetailsStore'
|
||||
export { useModalStore } from './useModalStore'
|
||||
export { useWalletStore } from './useWalletStore'
|
11
stores/useAccountDetailsStore.tsx
Normal file
@ -0,0 +1,11 @@
|
||||
import create from 'zustand'
|
||||
|
||||
interface AccountDetailsStore {
|
||||
isOpen: boolean
|
||||
selectedAccount: string | null
|
||||
}
|
||||
|
||||
export const useAccountDetailsStore = create<AccountDetailsStore>()((set) => ({
|
||||
isOpen: true,
|
||||
selectedAccount: null,
|
||||
}))
|
@ -1,37 +0,0 @@
|
||||
import create from 'zustand'
|
||||
import { persist } from 'zustand/middleware'
|
||||
|
||||
interface CreditManagerStore {
|
||||
isOpen: boolean
|
||||
selectedAccount: string | null
|
||||
actions: {
|
||||
toggleCreditManager: () => void
|
||||
setSelectedAccount: (id: string) => void
|
||||
}
|
||||
}
|
||||
|
||||
const useCreditManagerStore = create<CreditManagerStore>()(
|
||||
persist(
|
||||
(set, get) => ({
|
||||
isOpen: true,
|
||||
selectedAccount: null,
|
||||
actions: {
|
||||
toggleCreditManager: () => set(() => ({ isOpen: !get().isOpen })),
|
||||
setSelectedAccount: (accountId: string) => {
|
||||
set(() => ({
|
||||
selectedAccount: accountId,
|
||||
}))
|
||||
},
|
||||
},
|
||||
}),
|
||||
{
|
||||
name: 'creditManager',
|
||||
partialize: (state) =>
|
||||
Object.fromEntries(
|
||||
Object.entries(state).filter(([key]) => ['selectedAccount'].includes(key)),
|
||||
),
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
export default useCreditManagerStore
|
15
stores/useModalStore.tsx
Normal file
@ -0,0 +1,15 @@
|
||||
import create from 'zustand'
|
||||
|
||||
interface AccountDetailsStore {
|
||||
fundAccountModal: boolean
|
||||
withdrawModal: boolean
|
||||
createAccountModal: boolean
|
||||
deleteAccountModal: boolean
|
||||
}
|
||||
|
||||
export const useModalStore = create<AccountDetailsStore>()(() => ({
|
||||
fundAccountModal: false,
|
||||
withdrawModal: false,
|
||||
createAccountModal: false,
|
||||
deleteAccountModal: false,
|
||||
}))
|
@ -1,125 +1,88 @@
|
||||
import { CosmWasmClient, SigningCosmWasmClient } from '@cosmjs/cosmwasm-stargate'
|
||||
import { SigningCosmWasmClient } from '@cosmjs/cosmwasm-stargate'
|
||||
import create from 'zustand'
|
||||
import { persist } from 'zustand/middleware'
|
||||
import {
|
||||
WalletChainInfo,
|
||||
WalletConnectionStatus,
|
||||
WalletSigningCosmWasmClient,
|
||||
} from '@marsprotocol/wallet-connector'
|
||||
|
||||
import { contractAddresses } from 'config/contracts'
|
||||
import { Wallet } from 'types'
|
||||
import { MarsAccountNftClient } from 'types/generated/mars-account-nft/MarsAccountNft.client'
|
||||
import { MarsCreditManagerClient } from 'types/generated/mars-credit-manager/MarsCreditManager.client'
|
||||
import { MarsSwapperBaseClient } from 'types/generated/mars-swapper-base/MarsSwapperBase.client'
|
||||
import { chain } from 'utils/chains'
|
||||
|
||||
interface WalletStore {
|
||||
address: string
|
||||
address?: string
|
||||
chainInfo?: WalletChainInfo
|
||||
metamaskInstalled: boolean
|
||||
wallet: Wallet | null
|
||||
client?: CosmWasmClient
|
||||
signingClient?: SigningCosmWasmClient
|
||||
name?: string
|
||||
status: WalletConnectionStatus
|
||||
signingClient?: WalletSigningCosmWasmClient
|
||||
clients: {
|
||||
accountNft: MarsAccountNftClient | null
|
||||
creditManager: MarsCreditManagerClient | null
|
||||
swapperBase: MarsSwapperBaseClient | null
|
||||
accountNft?: MarsAccountNftClient
|
||||
creditManager?: MarsCreditManagerClient
|
||||
swapperBase?: MarsSwapperBaseClient
|
||||
}
|
||||
actions: {
|
||||
disconnect: () => void
|
||||
initClients: (address: string, signingClient: SigningCosmWasmClient) => void
|
||||
initialize: () => void
|
||||
connect: (address: string, wallet: Wallet) => void
|
||||
initialize: (
|
||||
status: WalletConnectionStatus,
|
||||
signingCosmWasmClient?: WalletSigningCosmWasmClient,
|
||||
address?: string,
|
||||
name?: string,
|
||||
chainInfo?: WalletChainInfo,
|
||||
) => void
|
||||
setMetamaskInstalledStatus: (value: boolean) => void
|
||||
}
|
||||
}
|
||||
|
||||
const useWalletStore = create<WalletStore>()(
|
||||
persist(
|
||||
(set, get) => ({
|
||||
address: '',
|
||||
metamaskInstalled: false,
|
||||
wallet: null,
|
||||
clients: {
|
||||
accountNft: null,
|
||||
creditManager: null,
|
||||
swapperBase: null,
|
||||
},
|
||||
actions: {
|
||||
disconnect: () => {
|
||||
set(() => ({ address: '', wallet: null, signingClient: undefined }))
|
||||
export const useWalletStore = create<WalletStore>()((set, get) => ({
|
||||
metamaskInstalled: false,
|
||||
status: WalletConnectionStatus.ReadyForConnection,
|
||||
clients: {},
|
||||
actions: {
|
||||
initClients: (address, signingClient) => {
|
||||
const client = get().signingClient
|
||||
if (!client) return
|
||||
const accountNft = new MarsAccountNftClient(client, address, contractAddresses.accountNft)
|
||||
const creditManager = new MarsCreditManagerClient(
|
||||
signingClient,
|
||||
address,
|
||||
contractAddresses.creditManager,
|
||||
)
|
||||
const swapperBase = new MarsSwapperBaseClient(
|
||||
signingClient,
|
||||
address,
|
||||
contractAddresses.swapper,
|
||||
)
|
||||
|
||||
set(() => ({
|
||||
clients: {
|
||||
accountNft,
|
||||
creditManager,
|
||||
swapperBase,
|
||||
},
|
||||
initClients: (address, signingClient) => {
|
||||
const accountNft = new MarsAccountNftClient(
|
||||
signingClient,
|
||||
address,
|
||||
contractAddresses.accountNft,
|
||||
)
|
||||
const creditManager = new MarsCreditManagerClient(
|
||||
signingClient,
|
||||
address,
|
||||
contractAddresses.creditManager,
|
||||
)
|
||||
const swapperBase = new MarsSwapperBaseClient(
|
||||
signingClient,
|
||||
address,
|
||||
contractAddresses.swapper,
|
||||
)
|
||||
|
||||
set(() => ({
|
||||
clients: {
|
||||
accountNft,
|
||||
creditManager,
|
||||
swapperBase,
|
||||
},
|
||||
}))
|
||||
},
|
||||
initialize: async () => {
|
||||
const clientInstance = await CosmWasmClient.connect(chain.rpc)
|
||||
|
||||
if (get().wallet === Wallet.Keplr && window.keplr) {
|
||||
const key = await window.keplr.getKey(chain.chainId)
|
||||
const offlineSigner = window.keplr.getOfflineSigner(chain.chainId)
|
||||
|
||||
const address = key.bech32Address
|
||||
const signingClientInstance = await SigningCosmWasmClient.connectWithSigner(
|
||||
chain.rpc,
|
||||
offlineSigner,
|
||||
)
|
||||
|
||||
get().actions.initClients(address, signingClientInstance)
|
||||
|
||||
set(() => ({
|
||||
client: clientInstance,
|
||||
signingClient: signingClientInstance,
|
||||
address,
|
||||
}))
|
||||
return
|
||||
}
|
||||
|
||||
set(() => ({ client: clientInstance }))
|
||||
},
|
||||
connect: async (address: string, wallet: Wallet) => {
|
||||
if (!window.keplr) return
|
||||
|
||||
const offlineSigner = window.keplr.getOfflineSigner(chain.chainId)
|
||||
const signingClientInstance = await SigningCosmWasmClient.connectWithSigner(
|
||||
chain.rpc,
|
||||
offlineSigner,
|
||||
)
|
||||
|
||||
get().actions.initClients(address, signingClientInstance)
|
||||
|
||||
set(() => ({ address, wallet, signingClient: signingClientInstance }))
|
||||
},
|
||||
setMetamaskInstalledStatus: (value: boolean) => set(() => ({ metamaskInstalled: value })),
|
||||
},
|
||||
}),
|
||||
{
|
||||
name: 'wallet',
|
||||
partialize: (state) =>
|
||||
Object.fromEntries(
|
||||
Object.entries(state).filter(
|
||||
([key]) => !['client', 'metamaskInstalled', 'actions', 'address'].includes(key),
|
||||
),
|
||||
),
|
||||
}))
|
||||
},
|
||||
),
|
||||
)
|
||||
initialize: async (
|
||||
status: WalletConnectionStatus,
|
||||
signingCosmWasmClient?: WalletSigningCosmWasmClient,
|
||||
address?: string,
|
||||
name?: string,
|
||||
chainInfo?: WalletChainInfo,
|
||||
) => {
|
||||
if (address && signingCosmWasmClient) {
|
||||
get().actions.initClients(address, signingCosmWasmClient)
|
||||
}
|
||||
|
||||
export default useWalletStore
|
||||
set({
|
||||
signingClient: signingCosmWasmClient,
|
||||
address,
|
||||
status,
|
||||
name,
|
||||
chainInfo,
|
||||
})
|
||||
},
|
||||
setMetamaskInstalledStatus: (value: boolean) => set(() => ({ metamaskInstalled: value })),
|
||||
},
|
||||
}))
|
||||
|
@ -4,6 +4,7 @@ const plugin = require('tailwindcss/plugin')
|
||||
module.exports = {
|
||||
content: ['./pages/**/*.{js,ts,jsx,tsx}', './components/**/*.{js,ts,jsx,tsx}'],
|
||||
safelist: [
|
||||
'h-15',
|
||||
'text-3xs',
|
||||
'text-3xs-caps',
|
||||
'text-2xs',
|
||||
@ -26,6 +27,7 @@ module.exports = {
|
||||
'text-4xl',
|
||||
'text-5xl-caps',
|
||||
'text-5xl',
|
||||
'w-15',
|
||||
],
|
||||
theme: {
|
||||
extend: {
|
||||
@ -113,6 +115,9 @@ module.exports = {
|
||||
semibold: 600,
|
||||
bold: 600,
|
||||
},
|
||||
height: {
|
||||
15: '60px',
|
||||
},
|
||||
hueRotate: {
|
||||
'-82': '-82deg',
|
||||
},
|
||||
@ -141,6 +146,9 @@ module.exports = {
|
||||
transitionProperty: {
|
||||
background: 'filter, -webkit-filter',
|
||||
},
|
||||
width: {
|
||||
15: '60px',
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: [
|
||||
|
5
types/keplr.d.ts
vendored
@ -1,5 +0,0 @@
|
||||
import type { Window as KeplrWindow } from '@keplr-wallet/types'
|
||||
|
||||
declare global {
|
||||
interface Window extends KeplrWindow {}
|
||||
}
|
@ -1,158 +0,0 @@
|
||||
import { Bech32Address } from '@keplr-wallet/cosmos'
|
||||
|
||||
import { ChainId, CosmosChainId, TestnetCosmosChainId } from 'types'
|
||||
|
||||
export const getEndpointsFromChainId = (
|
||||
chainId: TestnetCosmosChainId | CosmosChainId | ChainId,
|
||||
): { rpc: string; rest: string } => {
|
||||
switch (chainId) {
|
||||
case CosmosChainId.Osmosis:
|
||||
return {
|
||||
rpc: 'https://tm.osmosis.injective.network',
|
||||
rest: 'https://lcd.osmosis.injective.network',
|
||||
}
|
||||
case CosmosChainId.Injective:
|
||||
return {
|
||||
rpc: 'https://tm.injective.network',
|
||||
rest: 'https://lcd.injective.network',
|
||||
}
|
||||
case TestnetCosmosChainId.Cosmoshub:
|
||||
return {
|
||||
rpc: 'https://testnet.tm.cosmos.injective.dev',
|
||||
rest: 'https://testnet.lcd.cosmos.injective.dev',
|
||||
}
|
||||
case TestnetCosmosChainId.Osmosis:
|
||||
return {
|
||||
rpc: 'https://rpc-test.osmosis.zone/',
|
||||
rest: 'https://lcd-test.osmosis.zone/',
|
||||
}
|
||||
default:
|
||||
throw new Error(`Endpoints for ${chainId} not found`)
|
||||
}
|
||||
}
|
||||
|
||||
export const experimentalChainsConfig = {
|
||||
[TestnetCosmosChainId.Osmosis]: {
|
||||
...getEndpointsFromChainId(TestnetCosmosChainId.Osmosis),
|
||||
rpcConfig: undefined,
|
||||
restConfig: undefined,
|
||||
chainId: 'osmo-test-4',
|
||||
chainName: 'Osmosis Testnet',
|
||||
stakeCurrency: {
|
||||
coinDenom: 'OSMO',
|
||||
coinMinimalDenom: 'uosmo',
|
||||
coinDecimals: 6,
|
||||
coinGeckoId: 'osmosis',
|
||||
},
|
||||
walletUrl: 'https://wallet.keplr.app/#/cosmoshub/stake',
|
||||
walletUrlForStaking: 'https://wallet.keplr.app/#/cosmoshub/stake',
|
||||
bip44: {
|
||||
coinType: 118,
|
||||
},
|
||||
bech32Config: Bech32Address.defaultBech32Config('osmo'),
|
||||
currencies: [
|
||||
{
|
||||
coinDenom: 'OSMO',
|
||||
coinMinimalDenom: 'uosmo',
|
||||
coinDecimals: 6,
|
||||
coinGeckoId: 'osmosis',
|
||||
},
|
||||
{
|
||||
coinDenom: 'ION',
|
||||
coinMinimalDenom: 'uion',
|
||||
coinDecimals: 6,
|
||||
coinGeckoId: 'ion',
|
||||
},
|
||||
],
|
||||
feeCurrencies: [
|
||||
{
|
||||
coinDenom: 'OSMO',
|
||||
coinMinimalDenom: 'uosmo',
|
||||
coinDecimals: 6,
|
||||
coinGeckoId: 'osmosis',
|
||||
},
|
||||
],
|
||||
features: ['stargate', 'ibc-transfer', 'no-legacy-stdTx', 'ibc-go'],
|
||||
},
|
||||
[TestnetCosmosChainId.Cosmoshub]: {
|
||||
...getEndpointsFromChainId(TestnetCosmosChainId.Cosmoshub),
|
||||
rpcConfig: undefined,
|
||||
restConfig: undefined,
|
||||
chainId: 'cosmoshub-testnet',
|
||||
chainName: 'Cosmos Testnet',
|
||||
stakeCurrency: {
|
||||
coinDenom: 'UPHOTON',
|
||||
coinMinimalDenom: 'uphoton',
|
||||
coinDecimals: 6,
|
||||
coinGeckoId: 'cosmos',
|
||||
},
|
||||
walletUrl: 'https://wallet.keplr.app/#/osmosis/stake',
|
||||
walletUrlForStaking: 'https://wallet.keplr.app/#/osmosis/stake',
|
||||
bip44: {
|
||||
coinType: 118,
|
||||
},
|
||||
bech32Config: Bech32Address.defaultBech32Config('cosmos'),
|
||||
currencies: [
|
||||
{
|
||||
coinDenom: 'UPHOTON',
|
||||
coinMinimalDenom: 'uphoton',
|
||||
coinDecimals: 6,
|
||||
coinGeckoId: 'cosmos',
|
||||
},
|
||||
],
|
||||
feeCurrencies: [
|
||||
{
|
||||
coinDenom: 'UPHOTON',
|
||||
coinMinimalDenom: 'uphoton',
|
||||
coinDecimals: 6,
|
||||
coinGeckoId: 'cosmos',
|
||||
},
|
||||
],
|
||||
features: ['ibc-transfer'],
|
||||
},
|
||||
[CosmosChainId.Injective]: {
|
||||
...getEndpointsFromChainId(CosmosChainId.Injective),
|
||||
rpcConfig: undefined,
|
||||
restConfig: undefined,
|
||||
chainId: 'injective-1',
|
||||
chainName: 'Injective - Beta',
|
||||
stakeCurrency: {
|
||||
coinDenom: 'INJ',
|
||||
coinMinimalDenom: 'inj',
|
||||
coinDecimals: 18,
|
||||
coinGeckoId: 'injective-protocol',
|
||||
},
|
||||
walletUrl: 'https://hub.injective.network/',
|
||||
walletUrlForStaking: 'https://hub.injective.network/',
|
||||
bip44: {
|
||||
coinType: 60,
|
||||
},
|
||||
bech32Config: Bech32Address.defaultBech32Config('inj'),
|
||||
currencies: [
|
||||
{
|
||||
coinDenom: 'INJ',
|
||||
coinMinimalDenom: 'inj',
|
||||
coinDecimals: 18,
|
||||
coinGeckoId: 'injective-protocol',
|
||||
},
|
||||
],
|
||||
feeCurrencies: [
|
||||
{
|
||||
coinDenom: 'INJ',
|
||||
coinMinimalDenom: 'inj',
|
||||
coinDecimals: 18,
|
||||
coinGeckoId: 'injective-protocol',
|
||||
},
|
||||
],
|
||||
gasPriceStep: {
|
||||
low: 5000000000,
|
||||
average: 25000000000,
|
||||
high: 40000000000,
|
||||
},
|
||||
features: ['ibc-transfer', 'ibc-go', 'eth-address-gen', 'eth-key-sign'],
|
||||
beta: true,
|
||||
},
|
||||
} as Record<string, any>
|
||||
|
||||
export const getExperimentalChainConfigBasedOnChainId = (chainId: string): any | undefined =>
|
||||
experimentalChainsConfig[chainId]
|
@ -1,12 +1,9 @@
|
||||
export const formatWalletAddress = (address: string, substrLength = 6): string => {
|
||||
if (address.length <= 10) {
|
||||
return address
|
||||
}
|
||||
|
||||
return `${address.slice(0, substrLength)}...${address.slice(
|
||||
address.length - substrLength,
|
||||
address.length,
|
||||
)}`
|
||||
export function truncate(text = '', [h, t]: [number, number] = [6, 6]): string {
|
||||
const head = text.slice(0, h)
|
||||
if (t === 0) return text.length > h + t ? head + '...' : text
|
||||
const tail = text.slice(-1 * t, text.length)
|
||||
if (h === 0) return text.length > h + t ? '...' + tail : text
|
||||
return text.length > h + t ? [head, tail].join('...') : text
|
||||
}
|
||||
|
||||
export const formatCurrency = (value: string | number) => {
|
||||
|