Merge branch 'main' into chinese-localization
This commit is contained in:
commit
d0326c76d4
|
@ -9,7 +9,7 @@ export const API_URL = 'https://public-api.birdeye.so/'
|
|||
|
||||
export const socketUrl = `wss://public-api.birdeye.so/socket?x-api-key=${NEXT_PUBLIC_BIRDEYE_API_KEY}`
|
||||
|
||||
// Make requests to CryptoCompare API
|
||||
// Make requests to Birdeye API
|
||||
export async function makeApiRequest(path: string) {
|
||||
const response = await fetch(`${API_URL}${path}`, {
|
||||
headers: {
|
||||
|
|
|
@ -6,6 +6,7 @@ import { abbreviateAddress } from 'utils/formatting'
|
|||
import CreateAccountModal from './modals/CreateAccountModal'
|
||||
import { DEFAULT_DELEGATE } from './modals/DelegateModal'
|
||||
import MangoAccountsListModal from './modals/MangoAccountsListModal'
|
||||
import SheenLoader from './shared/SheenLoader'
|
||||
import Tooltip from './shared/Tooltip'
|
||||
|
||||
const AccountsButton = () => {
|
||||
|
@ -44,7 +45,9 @@ const AccountsButton = () => {
|
|||
) : null}
|
||||
</div>
|
||||
) : initialLoad ? (
|
||||
<span>{t('loading')}...</span>
|
||||
<SheenLoader className="mt-1">
|
||||
<div className="h-4 w-24 bg-th-bkg-2" />
|
||||
</SheenLoader>
|
||||
) : (
|
||||
<span>
|
||||
<span className="mr-1.5">🥭</span>
|
||||
|
|
|
@ -5,11 +5,10 @@ import {
|
|||
EllipsisHorizontalIcon,
|
||||
QuestionMarkCircleIcon,
|
||||
} from '@heroicons/react/20/solid'
|
||||
import { useWallet } from '@solana/wallet-adapter-react'
|
||||
import { useTranslation } from 'next-i18next'
|
||||
import Image from 'next/legacy/image'
|
||||
import { useRouter } from 'next/router'
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react'
|
||||
import { useCallback, useMemo, useState } from 'react'
|
||||
import { useViewport } from '../hooks/useViewport'
|
||||
import mangoStore from '@store/mangoStore'
|
||||
import { breakpoints } from '../utils/theme'
|
||||
|
@ -24,7 +23,7 @@ import { Table, Td, Th, TrBody, TrHead } from './shared/TableElements'
|
|||
import DepositWithdrawModal from './modals/DepositWithdrawModal'
|
||||
import BorrowRepayModal from './modals/BorrowRepayModal'
|
||||
import { WRAPPED_SOL_MINT } from '@project-serum/serum/lib/token-instructions'
|
||||
import { USDC_MINT } from 'utils/constants'
|
||||
import { SHOW_ZERO_BALANCES_KEY, USDC_MINT } from 'utils/constants'
|
||||
import { PublicKey } from '@solana/web3.js'
|
||||
import ActionsLinkButton from './account/ActionsLinkButton'
|
||||
import FormatNumericValue from './shared/FormatNumericValue'
|
||||
|
@ -33,12 +32,15 @@ import useBanksWithBalances, {
|
|||
BankWithBalance,
|
||||
} from 'hooks/useBanksWithBalances'
|
||||
import useUnownedAccount from 'hooks/useUnownedAccount'
|
||||
import useLocalStorageState from 'hooks/useLocalStorageState'
|
||||
|
||||
const TokenList = () => {
|
||||
const { t } = useTranslation(['common', 'token', 'trade'])
|
||||
const { connected } = useWallet()
|
||||
const [showZeroBalances, setShowZeroBalances] = useState(true)
|
||||
const { mangoAccount } = useMangoAccount()
|
||||
const [showZeroBalances, setShowZeroBalances] = useLocalStorageState(
|
||||
SHOW_ZERO_BALANCES_KEY,
|
||||
true
|
||||
)
|
||||
const { mangoAccount, mangoAccountAddress } = useMangoAccount()
|
||||
const spotBalances = mangoStore((s) => s.mangoAccount.spotBalances)
|
||||
const { mangoTokens } = useJupiterMints()
|
||||
const totalInterestData = mangoStore(
|
||||
|
@ -50,21 +52,16 @@ const TokenList = () => {
|
|||
|
||||
const filteredBanks = useMemo(() => {
|
||||
if (banks.length) {
|
||||
return showZeroBalances
|
||||
return showZeroBalances || !mangoAccountAddress
|
||||
? banks
|
||||
: banks.filter((b) => Math.abs(b.balance) > 0)
|
||||
}
|
||||
return []
|
||||
}, [banks, showZeroBalances])
|
||||
|
||||
useEffect(() => {
|
||||
if (!connected) {
|
||||
setShowZeroBalances(true)
|
||||
}
|
||||
}, [connected])
|
||||
}, [banks, mangoAccountAddress, showZeroBalances])
|
||||
|
||||
return (
|
||||
<ContentBox hideBorder hidePadding>
|
||||
{mangoAccountAddress ? (
|
||||
<div className="flex w-full items-center justify-end border-b border-th-bkg-3 py-3 px-6 lg:-mt-[36px] lg:mb-4 lg:w-auto lg:border-0 lg:py-0">
|
||||
<Switch
|
||||
checked={showZeroBalances}
|
||||
|
@ -74,6 +71,7 @@ const TokenList = () => {
|
|||
{t('show-zero-balances')}
|
||||
</Switch>
|
||||
</div>
|
||||
) : null}
|
||||
{showTableView ? (
|
||||
<Table>
|
||||
<thead>
|
||||
|
|
|
@ -52,6 +52,7 @@ const ButtonGroup = <T extends Values>({
|
|||
style={{
|
||||
width: `${100 / values.length}%`,
|
||||
}}
|
||||
type="button"
|
||||
>
|
||||
{names ? (unit ? names[i] + unit : names[i]) : unit ? v + unit : v}
|
||||
</button>
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
export const TwitterIcon = ({ className }: { className?: string }) => {
|
||||
return (
|
||||
<svg
|
||||
className={`${className}`}
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="currentColor"
|
||||
// stroke="currentColor"
|
||||
// strokeWidth="2"
|
||||
// strokeLinecap="round"
|
||||
>
|
||||
<path d="M23 3a10.9 10.9 0 0 1-3.14 1.53 4.48 4.48 0 0 0-7.86 3v1A10.66 10.66 0 0 1 3 4s-4 9 5 13a11.64 11.64 0 0 1-7 2c9 5 20 0 20-11.5a4.5 4.5 0 0 0-.08-.83A7.72 7.72 0 0 0 23 3z"></path>
|
||||
</svg>
|
||||
)
|
||||
}
|
|
@ -107,14 +107,14 @@ const MoreMenuPanel = ({
|
|||
const { t } = useTranslation(['common', 'search'])
|
||||
return (
|
||||
<div
|
||||
className={`fixed bottom-0 z-30 h-[420px] w-full overflow-hidden rounded-t-3xl bg-th-bkg-2 px-4 transition duration-300 ease-in-out ${
|
||||
className={`fixed bottom-0 z-30 h-[calc(100%-32px)] w-full overflow-hidden rounded-t-3xl bg-th-bkg-2 px-4 transition duration-300 ease-in-out ${
|
||||
showPanel ? 'translate-y-0' : 'translate-y-full'
|
||||
}`}
|
||||
>
|
||||
<div className="flex justify-between py-4">
|
||||
<SolanaTps />
|
||||
<IconButton onClick={() => setShowPanel(false)} hideBg>
|
||||
<XMarkIcon className="h-6 w-6" />
|
||||
<XMarkIcon className="h-6 w-6 text-th-fgd-3" />
|
||||
</IconButton>
|
||||
</div>
|
||||
<div
|
||||
|
|
|
@ -0,0 +1,181 @@
|
|||
import { Group, PerpPosition } from '@blockworks-foundation/mango-v4'
|
||||
import { TwitterIcon } from '@components/icons/TwitterIcon'
|
||||
import Button from '@components/shared/Button'
|
||||
import { Dialog } from '@headlessui/react'
|
||||
import { DocumentDuplicateIcon } from '@heroicons/react/20/solid'
|
||||
import { useScreenshot } from 'hooks/useScreenshot'
|
||||
import { useTranslation } from 'next-i18next'
|
||||
import { createRef, useEffect, useMemo, useState } from 'react'
|
||||
import { ModalProps } from 'types/modal'
|
||||
import { formatNumericValue, getDecimalCount } from 'utils/numbers'
|
||||
|
||||
interface SharePositionModalProps {
|
||||
group: Group
|
||||
position: PerpPosition
|
||||
}
|
||||
|
||||
type ModalCombinedProps = SharePositionModalProps & ModalProps
|
||||
|
||||
async function copyToClipboard(image: HTMLCanvasElement) {
|
||||
try {
|
||||
image.toBlob((blob: Blob | null) => {
|
||||
if (blob) {
|
||||
navigator.clipboard.write([new ClipboardItem({ 'image/png': blob })])
|
||||
}
|
||||
}, 'image/png')
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
}
|
||||
|
||||
const SharePositionModal = ({
|
||||
group,
|
||||
isOpen,
|
||||
onClose,
|
||||
position,
|
||||
}: ModalCombinedProps) => {
|
||||
const { t } = useTranslation('trade')
|
||||
const ref = createRef<HTMLDivElement>()
|
||||
const [copied, setCopied] = useState(false)
|
||||
const [showButton, setShowButton] = useState(true)
|
||||
const [image, takeScreenshot] = useScreenshot()
|
||||
const market = group.getPerpMarketByMarketIndex(position.marketIndex)
|
||||
const basePosition = position.getBasePositionUi(market)
|
||||
const entryPrice = position.getAverageEntryPriceUi(market)
|
||||
const side = basePosition > 0 ? 'long' : 'short'
|
||||
|
||||
const roi = useMemo(() => {
|
||||
if (!market) return 0
|
||||
let roi
|
||||
const indexPrice = market.uiPrice
|
||||
if (basePosition > 0) {
|
||||
roi = (indexPrice / entryPrice - 1) * 100
|
||||
} else {
|
||||
roi = (indexPrice / entryPrice - 1) * -100
|
||||
}
|
||||
return roi
|
||||
}, [basePosition, entryPrice, market])
|
||||
|
||||
useEffect(() => {
|
||||
if (image) {
|
||||
copyToClipboard(image)
|
||||
setCopied(true)
|
||||
setShowButton(true)
|
||||
}
|
||||
}, [image])
|
||||
|
||||
useEffect(() => {
|
||||
// if the button is hidden we are taking a screenshot
|
||||
if (!showButton) {
|
||||
takeScreenshot(ref.current as HTMLElement)
|
||||
}
|
||||
}, [showButton])
|
||||
|
||||
const handleCopyToClipboard = () => {
|
||||
setShowButton(false)
|
||||
}
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
open={isOpen}
|
||||
onClose={onClose}
|
||||
className="relative z-40 overflow-y-auto"
|
||||
>
|
||||
<div
|
||||
className="fixed inset-0 backdrop-brightness-[0.3]"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
<div className="fixed inset-0 flex flex-col items-center justify-center text-center">
|
||||
<Dialog.Panel className="relative flex flex-col items-center">
|
||||
<div
|
||||
className="relative h-[338px] w-[600px] overflow-hidden border border-slate-700 bg-gradient-to-b from-slate-900 to-black pt-6"
|
||||
ref={ref}
|
||||
>
|
||||
<div className="w-1/2 text-left">
|
||||
<div className="px-8">
|
||||
<img
|
||||
className="mb-8 h-7 w-auto flex-shrink-0"
|
||||
src="/logos/logo-with-text.svg"
|
||||
alt="Mango"
|
||||
/>
|
||||
<div className="mb-4 flex items-center">
|
||||
<p
|
||||
className={`font-display text-base uppercase text-th-fgd-1 ${
|
||||
side === 'long' ? 'text-th-up' : 'text-th-down'
|
||||
}`}
|
||||
>
|
||||
{side}
|
||||
</p>
|
||||
<span className="mx-2 text-base text-th-fgd-4">|</span>
|
||||
<p className="font-display text-base text-white">
|
||||
{market.name}
|
||||
</p>
|
||||
</div>
|
||||
<div
|
||||
className={`mb-4 font-display text-5xl ${
|
||||
roi >= 0 ? 'text-th-up' : 'text-th-down'
|
||||
}`}
|
||||
>
|
||||
{roi >= 0 ? '+' : ''}
|
||||
{roi.toFixed(2)}%
|
||||
</div>
|
||||
<div className="flex justify-between">
|
||||
<p className="mb-2 text-base text-gray-500">
|
||||
{t('entry-price')}
|
||||
</p>
|
||||
<p className="ml-2 font-mono text-base text-white">
|
||||
{formatNumericValue(
|
||||
entryPrice,
|
||||
getDecimalCount(market.tickSize)
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex justify-between">
|
||||
<p className="text-base text-gray-500">
|
||||
{t('current-price')}
|
||||
</p>
|
||||
<p className="ml-2 font-mono text-base text-white">
|
||||
{formatNumericValue(
|
||||
market.uiPrice,
|
||||
getDecimalCount(market.tickSize)
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="absolute top-0 left-0">
|
||||
<img
|
||||
src={roi >= 0 ? '/images/space.svg' : '/images/underwater.svg'}
|
||||
alt="Share Background"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{copied ? (
|
||||
<a
|
||||
href={`https://twitter.com/intent/tweet?text=I'm ${side.toUpperCase()} %24${
|
||||
market.name
|
||||
} on %40mangomarkets%0A[PASTE IMAGE HERE]`}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
<Button className="mt-6 flex items-center">
|
||||
<TwitterIcon className="mr-2 h-5 w-5 text-th-fgd-1" />
|
||||
{t('tweet-position')}
|
||||
</Button>
|
||||
</a>
|
||||
) : (
|
||||
<Button
|
||||
className="mt-6 flex items-center"
|
||||
onClick={handleCopyToClipboard}
|
||||
>
|
||||
<DocumentDuplicateIcon className="mr-2 h-5 w-5 text-th-fgd-1" />
|
||||
{t('copy-and-share')}
|
||||
</Button>
|
||||
)}
|
||||
</Dialog.Panel>
|
||||
</div>
|
||||
</Dialog>
|
||||
)
|
||||
}
|
||||
|
||||
export default SharePositionModal
|
|
@ -30,6 +30,8 @@ const LeverageSlider = ({
|
|||
useEffect(() => {
|
||||
if (amount) {
|
||||
setValue(amount)
|
||||
} else {
|
||||
setValue(0)
|
||||
}
|
||||
}, [amount])
|
||||
|
||||
|
|
|
@ -91,7 +91,7 @@ const NotificationList = () => {
|
|||
if (!mounted) return null
|
||||
|
||||
return (
|
||||
<div className={`${getPosition(notificationPosition)}`}>
|
||||
<div className={`${getPosition(notificationPosition)} w-full sm:w-auto`}>
|
||||
{notifications.filter((n) => n.show).length > 1 ? (
|
||||
<button
|
||||
className="default-transition pointer-events-auto my-1 flex items-center rounded bg-th-bkg-3 px-2 py-1 text-xs text-th-fgd-3 md:hover:bg-th-bkg-4"
|
||||
|
@ -208,7 +208,7 @@ const Notification = ({ notification }: { notification: Notification }) => {
|
|||
|
||||
return (
|
||||
<Transition
|
||||
className="my-1 w-full md:w-auto"
|
||||
className="my-1 w-full sm:w-auto"
|
||||
show={show}
|
||||
appear={true}
|
||||
enter="ease-out duration-500 transition"
|
||||
|
@ -227,7 +227,7 @@ const Notification = ({ notification }: { notification: Notification }) => {
|
|||
}`}
|
||||
>
|
||||
<div
|
||||
className={`pointer-events-auto w-full rounded-md border bg-th-bkg-2 shadow-lg md:w-auto ${
|
||||
className={`pointer-events-auto w-full rounded-md border bg-th-bkg-2 shadow-lg sm:w-auto ${
|
||||
type === 'success'
|
||||
? 'border-th-success'
|
||||
: type === 'error'
|
||||
|
@ -235,7 +235,7 @@ const Notification = ({ notification }: { notification: Notification }) => {
|
|||
: 'border-th-bkg-4'
|
||||
}`}
|
||||
>
|
||||
<div className={`relative flex w-full items-center p-3.5 md:w-96`}>
|
||||
<div className={`relative flex w-full items-center p-3.5 sm:w-96`}>
|
||||
<div className={`mr-1 flex-shrink-0`}>
|
||||
{type === 'success' ? (
|
||||
<CheckCircleIcon className={`h-6 w-6 text-th-success`} />
|
||||
|
|
|
@ -25,7 +25,7 @@ const SimpleAreaChart = ({
|
|||
<AreaChart data={data}>
|
||||
<defs>
|
||||
<linearGradient
|
||||
id={`gradientArea-${name}`}
|
||||
id={`gradientArea-${name.replace(/[^a-zA-Z]/g, '')}`}
|
||||
x1="0"
|
||||
y1={flipGradientCoords ? '0' : '1'}
|
||||
x2="0"
|
||||
|
@ -39,7 +39,7 @@ const SimpleAreaChart = ({
|
|||
type="monotone"
|
||||
dataKey={yKey}
|
||||
stroke={color}
|
||||
fill={`url(#gradientArea-${name})`}
|
||||
fill={`url(#gradientArea-${name.replace(/[^a-zA-Z]/g, '')}`}
|
||||
/>
|
||||
<XAxis dataKey={xKey} hide />
|
||||
<YAxis
|
||||
|
|
|
@ -10,10 +10,10 @@ import ContentBox from '../shared/ContentBox'
|
|||
import Change from '../shared/Change'
|
||||
import MarketLogos from '@components/trade/MarketLogos'
|
||||
import dynamic from 'next/dynamic'
|
||||
import { useCoingecko } from 'hooks/useCoingecko'
|
||||
import useMangoGroup from 'hooks/useMangoGroup'
|
||||
import { Table, Td, Th, TrBody, TrHead } from '@components/shared/TableElements'
|
||||
import FormatNumericValue from '@components/shared/FormatNumericValue'
|
||||
import { useBirdeyeMarketPrices } from 'hooks/useBirdeyeMarketPrices'
|
||||
const SimpleAreaChart = dynamic(
|
||||
() => import('@components/shared/SimpleAreaChart'),
|
||||
{ ssr: false }
|
||||
|
@ -21,12 +21,13 @@ const SimpleAreaChart = dynamic(
|
|||
|
||||
const SpotMarketsTable = () => {
|
||||
const { t } = useTranslation('common')
|
||||
const { isLoading: loadingPrices, data: coingeckoPrices } = useCoingecko()
|
||||
const { group } = useMangoGroup()
|
||||
const serumMarkets = mangoStore((s) => s.serumMarkets)
|
||||
const { theme } = useTheme()
|
||||
const { width } = useViewport()
|
||||
const showTableView = width ? width > breakpoints.md : false
|
||||
const { data: birdeyePrices, isLoading: loadingPrices } =
|
||||
useBirdeyeMarketPrices()
|
||||
|
||||
return (
|
||||
<ContentBox hideBorder hidePadding>
|
||||
|
@ -50,21 +51,18 @@ const SpotMarketsTable = () => {
|
|||
)
|
||||
const oraclePrice = bank?.uiPrice
|
||||
|
||||
const coingeckoData = coingeckoPrices.find(
|
||||
(asset) =>
|
||||
asset.symbol.toUpperCase() === bank?.name.toUpperCase()
|
||||
const birdeyeData = birdeyePrices.find(
|
||||
(m) => m.mint === market.serumMarketExternal.toString()
|
||||
)
|
||||
|
||||
const change =
|
||||
coingeckoData && oraclePrice
|
||||
? ((oraclePrice - coingeckoData.prices[0][1]) /
|
||||
coingeckoData.prices[0][1]) *
|
||||
birdeyeData && oraclePrice
|
||||
? ((oraclePrice - birdeyeData.data[0].value) /
|
||||
birdeyeData.data[0].value) *
|
||||
100
|
||||
: 0
|
||||
|
||||
const chartData = coingeckoData
|
||||
? coingeckoData.prices
|
||||
: undefined
|
||||
const chartData = birdeyeData ? birdeyeData.data : undefined
|
||||
|
||||
return (
|
||||
<TrBody key={market.publicKey.toString()}>
|
||||
|
@ -97,8 +95,8 @@ const SpotMarketsTable = () => {
|
|||
}
|
||||
data={chartData}
|
||||
name={bank!.name}
|
||||
xKey="0"
|
||||
yKey="1"
|
||||
xKey="unixTime"
|
||||
yKey="value"
|
||||
/>
|
||||
</div>
|
||||
) : bank?.name === 'USDC' ||
|
||||
|
@ -123,7 +121,10 @@ const SpotMarketsTable = () => {
|
|||
</Table>
|
||||
) : (
|
||||
<div>
|
||||
{serumMarkets.map((market) => {
|
||||
{serumMarkets
|
||||
.slice()
|
||||
.sort((a, b) => a.name.localeCompare(b.name))
|
||||
.map((market) => {
|
||||
return (
|
||||
<MobileSpotMarketItem
|
||||
key={market.publicKey.toString()}
|
||||
|
@ -141,38 +142,38 @@ export default SpotMarketsTable
|
|||
|
||||
const MobileSpotMarketItem = ({ market }: { market: Serum3Market }) => {
|
||||
const { t } = useTranslation('common')
|
||||
const { isLoading: loadingPrices, data: coingeckoPrices } = useCoingecko()
|
||||
const { data: birdeyePrices, isLoading: loadingPrices } =
|
||||
useBirdeyeMarketPrices()
|
||||
const { group } = useMangoGroup()
|
||||
const { theme } = useTheme()
|
||||
const bank = group?.getFirstBankByTokenIndex(market.baseTokenIndex)
|
||||
|
||||
const coingeckoData = useMemo(() => {
|
||||
const birdeyeData = useMemo(() => {
|
||||
if (!loadingPrices && bank) {
|
||||
return coingeckoPrices.find(
|
||||
(asset) => asset.symbol.toUpperCase() === bank?.name
|
||||
return birdeyePrices.find(
|
||||
(m) => m.mint === market.serumMarketExternal.toString()
|
||||
)
|
||||
}
|
||||
return null
|
||||
}, [loadingPrices, bank])
|
||||
|
||||
const change = useMemo(() => {
|
||||
if (coingeckoData) {
|
||||
if (birdeyeData && bank) {
|
||||
return (
|
||||
((coingeckoData.prices[coingeckoData.prices.length - 1][1] -
|
||||
coingeckoData.prices[0][1]) /
|
||||
coingeckoData.prices[0][1]) *
|
||||
((bank.uiPrice - birdeyeData.data[0].value) /
|
||||
birdeyeData.data[0].value) *
|
||||
100
|
||||
)
|
||||
}
|
||||
return 0
|
||||
}, [coingeckoData])
|
||||
}, [birdeyeData, bank])
|
||||
|
||||
const chartData = useMemo(() => {
|
||||
if (coingeckoData) {
|
||||
return coingeckoData.prices
|
||||
if (birdeyeData) {
|
||||
return birdeyeData.data
|
||||
}
|
||||
return undefined
|
||||
}, [coingeckoData])
|
||||
}, [birdeyeData])
|
||||
|
||||
return (
|
||||
<div className="border-b border-th-bkg-3 px-6 py-4">
|
||||
|
@ -200,11 +201,11 @@ const MobileSpotMarketItem = ({ market }: { market: Serum3Market }) => {
|
|||
color={change >= 0 ? COLORS.UP[theme] : COLORS.DOWN[theme]}
|
||||
data={chartData}
|
||||
name={bank!.name}
|
||||
xKey="0"
|
||||
yKey="1"
|
||||
xKey="unixTime"
|
||||
yKey="value"
|
||||
/>
|
||||
</div>
|
||||
) : bank?.name === 'USDC' || bank?.name === 'USDT' ? null : (
|
||||
) : (
|
||||
<p className="mb-0 text-th-fgd-4">{t('unavailable')}</p>
|
||||
)
|
||||
) : (
|
||||
|
|
|
@ -438,9 +438,9 @@ const SwapForm = () => {
|
|||
setShowConfirm={setShowConfirm}
|
||||
amountIn={amountInAsDecimal}
|
||||
inputSymbol={inputBank?.name}
|
||||
amountOut={
|
||||
selectedRoute ? amountOutAsDecimal.toNumber() : undefined
|
||||
}
|
||||
// amountOut={
|
||||
// selectedRoute ? amountOutAsDecimal.toNumber() : undefined
|
||||
// }
|
||||
isDelegatedAccount={isDelegatedAccount}
|
||||
/>
|
||||
) : (
|
||||
|
@ -507,7 +507,7 @@ export default SwapForm
|
|||
|
||||
const SwapFormSubmitButton = ({
|
||||
amountIn,
|
||||
amountOut,
|
||||
// amountOut,
|
||||
inputSymbol,
|
||||
loadingSwapDetails,
|
||||
selectedRoute,
|
||||
|
@ -516,7 +516,7 @@ const SwapFormSubmitButton = ({
|
|||
isDelegatedAccount,
|
||||
}: {
|
||||
amountIn: Decimal
|
||||
amountOut: number | undefined
|
||||
// amountOut: number | undefined
|
||||
inputSymbol: string | undefined
|
||||
loadingSwapDetails: boolean
|
||||
selectedRoute: RouteInfo | undefined | null
|
||||
|
@ -533,12 +533,12 @@ const SwapFormSubmitButton = ({
|
|||
? amountWithBorrow.lt(amountIn)
|
||||
: tokenMax.lt(amountIn)
|
||||
|
||||
const disabled =
|
||||
connected &&
|
||||
(!amountIn.toNumber() ||
|
||||
showInsufficientBalance ||
|
||||
!amountOut ||
|
||||
!selectedRoute)
|
||||
// const disabled =
|
||||
// connected &&
|
||||
// (!amountIn.toNumber() ||
|
||||
// showInsufficientBalance ||
|
||||
// !amountOut ||
|
||||
// !selectedRoute)
|
||||
|
||||
const onClick = connected ? () => setShowConfirm(true) : handleConnect
|
||||
|
||||
|
@ -547,7 +547,8 @@ const SwapFormSubmitButton = ({
|
|||
<Button
|
||||
onClick={onClick}
|
||||
className="mt-6 mb-4 flex w-full items-center justify-center text-base"
|
||||
disabled={disabled}
|
||||
// disabled={disabled}
|
||||
disabled={true}
|
||||
size="large"
|
||||
>
|
||||
{isDelegatedAccount ? (
|
||||
|
|
|
@ -7,6 +7,7 @@ import dynamic from 'next/dynamic'
|
|||
import SwapIntroModal from '@components/modals/SwapIntroModal'
|
||||
import { useLocalStorage } from '@solana/wallet-adapter-react'
|
||||
import { SHOW_SWAP_INTRO_MODAL } from 'utils/constants'
|
||||
import { ExclamationTriangleIcon } from '@heroicons/react/20/solid'
|
||||
// import useLocalStorageState from 'hooks/useLocalStorageState'
|
||||
// import { IS_ONBOARDED_KEY } from 'utils/constants'
|
||||
const SwapTokenChart = dynamic(() => import('./SwapTokenChart'), { ssr: false })
|
||||
|
@ -22,6 +23,12 @@ const SwapPage = () => {
|
|||
|
||||
return (
|
||||
<>
|
||||
<div className="flex items-center justify-center bg-th-down-muted py-2 px-6">
|
||||
<ExclamationTriangleIcon className="mr-1.5 h-4 w-4 flex-shrink-0 text-white" />
|
||||
<span className="leading-tight text-white">
|
||||
Swaps are currently disabled. A program update is required.
|
||||
</span>
|
||||
</div>
|
||||
<div className="grid grid-cols-12">
|
||||
<div className="col-span-12 border-th-bkg-3 md:col-span-6 md:border-b lg:col-span-7 xl:col-span-8">
|
||||
<SwapTokenChart />
|
||||
|
|
|
@ -4,9 +4,11 @@ import ChartRangeButtons from '@components/shared/ChartRangeButtons'
|
|||
import FormatNumericValue from '@components/shared/FormatNumericValue'
|
||||
import SheenLoader from '@components/shared/SheenLoader'
|
||||
import { ArrowSmallUpIcon, NoSymbolIcon } from '@heroicons/react/20/solid'
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
import { makeApiRequest } from 'apis/birdeye/helpers'
|
||||
import dayjs from 'dayjs'
|
||||
import relativeTime from 'dayjs/plugin/relativeTime'
|
||||
import { useCoingecko } from 'hooks/useCoingecko'
|
||||
import { BirdeyePriceResponse } from 'hooks/useBirdeyeMarketPrices'
|
||||
import parse from 'html-react-parser'
|
||||
import { useTranslation } from 'next-i18next'
|
||||
import dynamic from 'next/dynamic'
|
||||
|
@ -34,40 +36,55 @@ const DEFAULT_COINGECKO_VALUES = {
|
|||
total_volume: 0,
|
||||
}
|
||||
|
||||
interface BirdeyeResponse {
|
||||
data: { items: BirdeyePriceResponse[] }
|
||||
success: boolean
|
||||
}
|
||||
|
||||
const fetchBirdeyePrices = async (
|
||||
daysToShow: string,
|
||||
mint: string
|
||||
): Promise<BirdeyePriceResponse[] | []> => {
|
||||
const interval = daysToShow === '1' ? '30m' : daysToShow === '7' ? '1H' : '4H'
|
||||
const queryEnd = Math.floor(Date.now() / 1000)
|
||||
const queryStart = queryEnd - parseInt(daysToShow) * 86400
|
||||
const query = `defi/history_price?address=${mint}&address_type=token&type=${interval}&time_from=${queryStart}&time_to=${queryEnd}`
|
||||
const response: BirdeyeResponse = await makeApiRequest(query)
|
||||
|
||||
if (response.success && response?.data?.items) {
|
||||
return response.data.items
|
||||
}
|
||||
return []
|
||||
}
|
||||
|
||||
const CoingeckoStats = ({
|
||||
bank,
|
||||
coingeckoData,
|
||||
coingeckoId,
|
||||
}: {
|
||||
bank: Bank
|
||||
// TODO: Add Coingecko api types
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
coingeckoData: any
|
||||
coingeckoId: string
|
||||
}) => {
|
||||
const { t } = useTranslation(['common', 'token'])
|
||||
const [showFullDesc, setShowFullDesc] = useState(false)
|
||||
const [daysToShow, setDaysToShow] = useState<string>('1')
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const [chartData, setChartData] = useState<{ prices: any[] } | null>(null)
|
||||
const [loadChartData, setLoadChartData] = useState(true)
|
||||
const { isLoading: loadingPrices, data: coingeckoPrices } = useCoingecko()
|
||||
|
||||
const handleDaysToShow = async (days: string) => {
|
||||
if (days !== '1') {
|
||||
try {
|
||||
const response = await fetch(
|
||||
`https://api.coingecko.com/api/v3/coins/${coingeckoId}/market_chart?vs_currency=usd&days=${days}`
|
||||
const {
|
||||
data: birdeyePrices,
|
||||
isLoading: loadingBirdeyePrices,
|
||||
isFetching: fetchingBirdeyePrices,
|
||||
} = useQuery(
|
||||
['birdeye-token-prices', daysToShow, bank.mint],
|
||||
() => fetchBirdeyePrices(daysToShow, bank.mint.toString()),
|
||||
{
|
||||
cacheTime: 1000 * 60 * 15,
|
||||
staleTime: 1000 * 60 * 10,
|
||||
retry: 3,
|
||||
enabled: !!bank,
|
||||
refetchOnWindowFocus: false,
|
||||
}
|
||||
)
|
||||
const data = await response.json()
|
||||
setLoadChartData(false)
|
||||
setChartData(data)
|
||||
} catch {
|
||||
setLoadChartData(false)
|
||||
}
|
||||
}
|
||||
setDaysToShow(days)
|
||||
}
|
||||
|
||||
const {
|
||||
ath,
|
||||
|
@ -82,28 +99,7 @@ const CoingeckoStats = ({
|
|||
max_supply,
|
||||
total_supply,
|
||||
total_volume,
|
||||
} = coingeckoData ? coingeckoData.market_data : DEFAULT_COINGECKO_VALUES
|
||||
|
||||
const loadingChart = useMemo(() => {
|
||||
return daysToShow == '1' ? loadingPrices : loadChartData
|
||||
}, [loadChartData, loadingPrices])
|
||||
|
||||
const coingeckoTokenPrices = useMemo(() => {
|
||||
if (daysToShow === '1' && coingeckoPrices.length && bank) {
|
||||
const tokenPriceData = coingeckoPrices.find(
|
||||
(asset) => asset.symbol.toUpperCase() === bank.name.toUpperCase()
|
||||
)
|
||||
|
||||
if (tokenPriceData) {
|
||||
return tokenPriceData.prices
|
||||
}
|
||||
} else {
|
||||
if (chartData && !loadingChart) {
|
||||
return chartData.prices
|
||||
}
|
||||
}
|
||||
return []
|
||||
}, [coingeckoPrices, bank, daysToShow, chartData, loadingChart])
|
||||
} = coingeckoData ? coingeckoData : DEFAULT_COINGECKO_VALUES
|
||||
|
||||
const truncateDescription = (desc: string) =>
|
||||
desc.substring(0, (desc + ' ').lastIndexOf(' ', 144))
|
||||
|
@ -140,35 +136,30 @@ const CoingeckoStats = ({
|
|||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
{!loadingChart ? (
|
||||
coingeckoTokenPrices.length ? (
|
||||
<>
|
||||
<div className="mt-4 flex w-full items-center justify-between px-6">
|
||||
<h2 className="text-base">{bank.name} Price Chart</h2>
|
||||
<ChartRangeButtons
|
||||
activeValue={daysToShow}
|
||||
names={['24H', '7D', '30D']}
|
||||
values={['1', '7', '30']}
|
||||
onChange={(v) => handleDaysToShow(v)}
|
||||
onChange={(v) => setDaysToShow(v)}
|
||||
/>
|
||||
</div>
|
||||
<PriceChart
|
||||
daysToShow={parseInt(daysToShow)}
|
||||
prices={coingeckoTokenPrices}
|
||||
/>
|
||||
</>
|
||||
) : bank?.name === 'USDC' || bank?.name === 'USDT' ? null : (
|
||||
<div className="flex flex-col items-center p-6">
|
||||
<NoSymbolIcon className="mb-1 h-6 w-6 text-th-fgd-4" />
|
||||
<p className="mb-0 text-th-fgd-4">{t('token:chart-unavailable')}</p>
|
||||
</div>
|
||||
)
|
||||
) : (
|
||||
{birdeyePrices?.length ? (
|
||||
<PriceChart daysToShow={parseInt(daysToShow)} prices={birdeyePrices} />
|
||||
) : loadingBirdeyePrices || fetchingBirdeyePrices ? (
|
||||
<div className="p-6">
|
||||
<SheenLoader className="flex flex-1">
|
||||
<div className="h-72 w-full rounded-md bg-th-bkg-2" />
|
||||
<div className="h-72 w-full rounded-lg bg-th-bkg-2 md:h-80" />
|
||||
</SheenLoader>
|
||||
</div>
|
||||
) : (
|
||||
<div className="m-6 flex h-72 items-center justify-center rounded-lg border border-th-bkg-3 md:h-80">
|
||||
<div className="flex flex-col items-center">
|
||||
<NoSymbolIcon className="mb-2 h-7 w-7 text-th-fgd-4" />
|
||||
<p>{t('chart-unavailable')}</p>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<div className="grid grid-cols-1 border-b border-th-bkg-3 md:grid-cols-2">
|
||||
<div className="col-span-1 border-y border-th-bkg-3 px-6 py-4 md:col-span-2">
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
import { formatDateAxis } from '@components/shared/DetailedAreaChart'
|
||||
import dayjs from 'dayjs'
|
||||
import { BirdeyePriceResponse } from 'hooks/useBirdeyeMarketPrices'
|
||||
import { useTheme } from 'next-themes'
|
||||
import { useMemo } from 'react'
|
||||
import { Area, AreaChart, ResponsiveContainer, XAxis, YAxis } from 'recharts'
|
||||
|
@ -9,13 +11,13 @@ const PriceChart = ({
|
|||
prices,
|
||||
daysToShow,
|
||||
}: {
|
||||
prices: number[][]
|
||||
prices: BirdeyePriceResponse[]
|
||||
daysToShow: number
|
||||
}) => {
|
||||
const { theme } = useTheme()
|
||||
|
||||
const change = useMemo(() => {
|
||||
return prices[prices.length - 1][1] - prices[0][1]
|
||||
return prices[prices.length - 1].value - prices[0].value
|
||||
}, [prices])
|
||||
|
||||
return (
|
||||
|
@ -44,14 +46,14 @@ const PriceChart = ({
|
|||
<Area
|
||||
isAnimationActive={false}
|
||||
type="monotone"
|
||||
dataKey="1"
|
||||
dataKey="value"
|
||||
stroke={change >= 0 ? COLORS.UP[theme] : COLORS.DOWN[theme]}
|
||||
strokeWidth={1.5}
|
||||
fill="url(#gradientArea)"
|
||||
/>
|
||||
<XAxis
|
||||
axisLine={false}
|
||||
dataKey="0"
|
||||
dataKey="unixTime"
|
||||
minTickGap={20}
|
||||
padding={{ left: 20, right: 20 }}
|
||||
tick={{
|
||||
|
@ -59,11 +61,13 @@ const PriceChart = ({
|
|||
fontSize: 10,
|
||||
}}
|
||||
tickLine={false}
|
||||
tickFormatter={(d) => formatDateAxis(d, daysToShow)}
|
||||
tickFormatter={(d) =>
|
||||
formatDateAxis(dayjs(d * 1000).toISOString(), daysToShow)
|
||||
}
|
||||
/>
|
||||
<YAxis
|
||||
axisLine={false}
|
||||
dataKey={'1'}
|
||||
dataKey="value"
|
||||
type="number"
|
||||
domain={['dataMin', 'dataMax']}
|
||||
padding={{ top: 20, bottom: 20 }}
|
||||
|
@ -73,7 +77,7 @@ const PriceChart = ({
|
|||
}}
|
||||
tickFormatter={(x) => formatCurrencyValue(x)}
|
||||
tickLine={false}
|
||||
width={prices[0][1] < 0.00001 ? 100 : 60}
|
||||
width={prices[0].value < 0.00001 ? 100 : 60}
|
||||
/>
|
||||
</AreaChart>
|
||||
</ResponsiveContainer>
|
||||
|
|
|
@ -106,7 +106,8 @@ const TokenPage = () => {
|
|||
}
|
||||
}, [bank, mangoTokens])
|
||||
|
||||
const coingeckoTokenInfo = useQuery<CoingeckoDataType, Error>(
|
||||
const { data: coingeckoTokenInfo, isLoading: loadingCoingeckoInfo } =
|
||||
useQuery<CoingeckoDataType, Error>(
|
||||
['coingecko-token-info', coingeckoId],
|
||||
() => fetchTokenInfo(coingeckoId),
|
||||
{
|
||||
|
@ -119,8 +120,8 @@ const TokenPage = () => {
|
|||
)
|
||||
|
||||
const { high_24h, low_24h, price_change_percentage_24h } =
|
||||
coingeckoTokenInfo.data
|
||||
? coingeckoTokenInfo.data.market_data
|
||||
coingeckoTokenInfo?.market_data
|
||||
? coingeckoTokenInfo.market_data
|
||||
: DEFAULT_COINGECKO_VALUES
|
||||
|
||||
return (
|
||||
|
@ -131,9 +132,9 @@ const TokenPage = () => {
|
|||
<div className="mb-4 md:mb-1">
|
||||
<div className="mb-1.5 flex items-center space-x-2">
|
||||
<Image src={logoURI!} height="20" width="20" />
|
||||
{coingeckoTokenInfo.data ? (
|
||||
{coingeckoTokenInfo ? (
|
||||
<h1 className="text-base font-normal">
|
||||
{coingeckoTokenInfo.data.name}{' '}
|
||||
{coingeckoTokenInfo.name}{' '}
|
||||
<span className="text-th-fgd-4">{bank.name}</span>
|
||||
</h1>
|
||||
) : (
|
||||
|
@ -155,13 +156,13 @@ const TokenPage = () => {
|
|||
<FormatNumericValue value={bank.uiPrice} isUsd />
|
||||
)}
|
||||
</div>
|
||||
{coingeckoTokenInfo.data ? (
|
||||
{coingeckoTokenInfo?.market_data ? (
|
||||
<div className="mb-2">
|
||||
<Change change={price_change_percentage_24h} suffix="%" />
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
{coingeckoTokenInfo.data ? (
|
||||
{coingeckoTokenInfo?.market_data ? (
|
||||
<DailyRange
|
||||
high={high_24h.usd}
|
||||
low={low_24h.usd}
|
||||
|
@ -191,12 +192,17 @@ const TokenPage = () => {
|
|||
</span>
|
||||
</div>
|
||||
{bank ? <TopTokenAccounts bank={bank} /> : null}
|
||||
{coingeckoTokenInfo.data && coingeckoId ? (
|
||||
{coingeckoTokenInfo?.market_data ? (
|
||||
<CoingeckoStats
|
||||
bank={bank}
|
||||
coingeckoData={coingeckoTokenInfo.data}
|
||||
coingeckoId={coingeckoId}
|
||||
coingeckoData={coingeckoTokenInfo.market_data}
|
||||
/>
|
||||
) : loadingCoingeckoInfo && coingeckoId ? (
|
||||
<div className="p-6">
|
||||
<SheenLoader className="flex flex-1">
|
||||
<div className="h-72 w-full rounded-lg bg-th-bkg-2 md:h-80" />
|
||||
</SheenLoader>
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex flex-col items-center p-6">
|
||||
<span className="mb-0.5 text-2xl">🦎</span>
|
||||
|
|
|
@ -1,16 +1,12 @@
|
|||
import { Bank, PerpMarket, Serum3Market } from '@blockworks-foundation/mango-v4'
|
||||
import { Bank, PerpMarket } from '@blockworks-foundation/mango-v4'
|
||||
import { IconButton, LinkButton } from '@components/shared/Button'
|
||||
import Change from '@components/shared/Change'
|
||||
import { getOneDayPerpStats } from '@components/stats/PerpMarketsTable'
|
||||
import { ChartBarIcon, InformationCircleIcon } from '@heroicons/react/20/solid'
|
||||
import { Market } from '@project-serum/serum'
|
||||
import mangoStore from '@store/mangoStore'
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
import useJupiterMints from 'hooks/useJupiterMints'
|
||||
import useSelectedMarket from 'hooks/useSelectedMarket'
|
||||
import { useTranslation } from 'next-i18next'
|
||||
import { useEffect, useMemo, useState } from 'react'
|
||||
import { Token } from 'types/jupiter'
|
||||
import {
|
||||
formatCurrencyValue,
|
||||
getDecimalCount,
|
||||
|
@ -19,31 +15,11 @@ import {
|
|||
import MarketSelectDropdown from './MarketSelectDropdown'
|
||||
import PerpFundingRate from './PerpFundingRate'
|
||||
import { BorshAccountsCoder } from '@coral-xyz/anchor'
|
||||
import { useBirdeyeMarketPrices } from 'hooks/useBirdeyeMarketPrices'
|
||||
import SheenLoader from '@components/shared/SheenLoader'
|
||||
import usePrevious from '@components/shared/usePrevious'
|
||||
import PerpMarketDetailsModal from '@components/modals/PerpMarketDetailsModal.tsx'
|
||||
|
||||
type ResponseType = {
|
||||
prices: [number, number][]
|
||||
market_caps: [number, number][]
|
||||
total_volumes: [number, number][]
|
||||
}
|
||||
|
||||
const fetchTokenChange = async (
|
||||
mangoTokens: Token[],
|
||||
baseAddress: string
|
||||
): Promise<ResponseType> => {
|
||||
let coingeckoId = mangoTokens.find((t) => t.address === baseAddress)
|
||||
?.extensions?.coingeckoId
|
||||
|
||||
if (baseAddress === '3NZ9JMVBmGAqocybic2c7LQCJScmgsAZ6vQqTDzcqmJh') {
|
||||
coingeckoId = 'bitcoin'
|
||||
}
|
||||
|
||||
const response = await fetch(
|
||||
`https://api.coingecko.com/api/v3/coins/${coingeckoId}/market_chart?vs_currency=usd&days=1`
|
||||
)
|
||||
const data = await response.json()
|
||||
return data
|
||||
}
|
||||
import useMangoGroup from 'hooks/useMangoGroup'
|
||||
|
||||
const AdvancedMarketHeader = ({
|
||||
showChart,
|
||||
|
@ -54,16 +30,20 @@ const AdvancedMarketHeader = ({
|
|||
}) => {
|
||||
const { t } = useTranslation(['common', 'trade'])
|
||||
const perpStats = mangoStore((s) => s.perpStats.data)
|
||||
const loadingPerpStats = mangoStore((s) => s.perpStats.loading)
|
||||
const {
|
||||
serumOrPerpMarket,
|
||||
price: stalePrice,
|
||||
selectedMarket,
|
||||
} = useSelectedMarket()
|
||||
const selectedMarketName = mangoStore((s) => s.selectedMarket.name)
|
||||
const { mangoTokens } = useJupiterMints()
|
||||
const connection = mangoStore((s) => s.connection)
|
||||
const [price, setPrice] = useState(stalePrice)
|
||||
const { data: birdeyePrices, isLoading: loadingPrices } =
|
||||
useBirdeyeMarketPrices()
|
||||
const previousMarketName = usePrevious(selectedMarketName)
|
||||
const [showMarketDetails, setShowMarketDetails] = useState(false)
|
||||
const { group } = useMangoGroup()
|
||||
|
||||
//subscribe to the market oracle account
|
||||
useEffect(() => {
|
||||
|
@ -112,57 +92,48 @@ const AdvancedMarketHeader = ({
|
|||
}, [connection, selectedMarket])
|
||||
|
||||
useEffect(() => {
|
||||
if (serumOrPerpMarket instanceof PerpMarket) {
|
||||
if (group) {
|
||||
const actions = mangoStore.getState().actions
|
||||
actions.fetchPerpStats()
|
||||
}
|
||||
}, [serumOrPerpMarket])
|
||||
}, [group])
|
||||
|
||||
const spotBaseAddress = useMemo(() => {
|
||||
const group = mangoStore.getState().group
|
||||
if (group && selectedMarket && selectedMarket instanceof Serum3Market) {
|
||||
return group
|
||||
.getFirstBankByTokenIndex(selectedMarket.baseTokenIndex)
|
||||
.mint.toString()
|
||||
}
|
||||
}, [selectedMarket])
|
||||
|
||||
const spotChangeResponse = useQuery(
|
||||
['coingecko-tokens', spotBaseAddress],
|
||||
() => fetchTokenChange(mangoTokens, spotBaseAddress!),
|
||||
{
|
||||
cacheTime: 1000 * 60 * 15,
|
||||
staleTime: 1000 * 60 * 10,
|
||||
retry: 3,
|
||||
enabled:
|
||||
!!spotBaseAddress &&
|
||||
serumOrPerpMarket instanceof Market &&
|
||||
mangoTokens.length > 0,
|
||||
refetchOnWindowFocus: false,
|
||||
}
|
||||
const birdeyeData = useMemo(() => {
|
||||
if (
|
||||
!birdeyePrices?.length ||
|
||||
!selectedMarket ||
|
||||
selectedMarket instanceof PerpMarket
|
||||
)
|
||||
return
|
||||
return birdeyePrices.find(
|
||||
(m) => m.mint === selectedMarket.serumMarketExternal.toString()
|
||||
)
|
||||
}, [birdeyePrices, selectedMarket])
|
||||
|
||||
const change = useMemo(() => {
|
||||
if (!price || !serumOrPerpMarket) return 0
|
||||
if (
|
||||
!price ||
|
||||
!serumOrPerpMarket ||
|
||||
selectedMarketName !== previousMarketName
|
||||
)
|
||||
return 0
|
||||
if (serumOrPerpMarket instanceof PerpMarket) {
|
||||
const changeData = getOneDayPerpStats(perpStats, selectedMarketName)
|
||||
|
||||
return changeData.length
|
||||
? ((price - changeData[0].price) / changeData[0].price) * 100
|
||||
: 0
|
||||
} else {
|
||||
if (!spotChangeResponse.data) return 0
|
||||
if (!birdeyeData) return 0
|
||||
return (
|
||||
((price - spotChangeResponse.data.prices?.[0][1]) /
|
||||
spotChangeResponse.data.prices?.[0][1]) *
|
||||
100
|
||||
((price - birdeyeData.data[0].value) / birdeyeData.data[0].value) * 100
|
||||
)
|
||||
}
|
||||
}, [
|
||||
spotChangeResponse,
|
||||
birdeyeData,
|
||||
price,
|
||||
serumOrPerpMarket,
|
||||
perpStats,
|
||||
previousMarketName,
|
||||
selectedMarketName,
|
||||
])
|
||||
|
||||
|
@ -194,7 +165,13 @@ const AdvancedMarketHeader = ({
|
|||
</div>
|
||||
<div className="ml-6 flex-col whitespace-nowrap">
|
||||
<div className="text-xs text-th-fgd-4">{t('rolling-change')}</div>
|
||||
{!loadingPrices && !loadingPerpStats ? (
|
||||
<Change change={change} size="small" suffix="%" />
|
||||
) : (
|
||||
<SheenLoader className="mt-0.5">
|
||||
<div className="h-3.5 w-12 bg-th-bkg-2" />
|
||||
</SheenLoader>
|
||||
)}
|
||||
</div>
|
||||
{serumOrPerpMarket instanceof PerpMarket ? (
|
||||
<>
|
||||
|
|
|
@ -43,7 +43,7 @@ import SpotButtonGroup from './SpotButtonGroup'
|
|||
import PerpButtonGroup from './PerpButtonGroup'
|
||||
import SolBalanceWarnings from '@components/shared/SolBalanceWarnings'
|
||||
import useSelectedMarket from 'hooks/useSelectedMarket'
|
||||
import { getDecimalCount } from 'utils/numbers'
|
||||
import { floorToDecimal, getDecimalCount } from 'utils/numbers'
|
||||
import LogoWithFallback from '@components/shared/LogoWithFallback'
|
||||
import useIpAddress from 'hooks/useIpAddress'
|
||||
import ButtonGroup from '@components/forms/ButtonGroup'
|
||||
|
@ -215,18 +215,69 @@ const AdvancedTradeForm = () => {
|
|||
|
||||
const handleSetMargin = useCallback(
|
||||
(e: ChangeEvent<HTMLInputElement>) => {
|
||||
if (!e.target.checked) {
|
||||
set((s) => {
|
||||
s.tradeForm.quoteSize = ''
|
||||
s.tradeForm.baseSize = ''
|
||||
})
|
||||
}
|
||||
setSavedCheckboxSettings({
|
||||
...savedCheckboxSettings,
|
||||
margin: e.target.checked,
|
||||
})
|
||||
|
||||
const { group } = mangoStore.getState()
|
||||
const { tradeType, side, price, baseSize, quoteSize } = tradeForm
|
||||
const tradePrice = tradeType === 'Market' ? oraclePrice : price
|
||||
|
||||
if (
|
||||
!group ||
|
||||
!mangoAccount ||
|
||||
!tradePrice ||
|
||||
!(selectedMarket instanceof Serum3Market)
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
const isBuySide = side === 'buy'
|
||||
const tokenIndex =
|
||||
selectedMarket[isBuySide ? 'quoteTokenIndex' : 'baseTokenIndex']
|
||||
const balance = mangoAccount.getTokenBalanceUi(
|
||||
group.getFirstBankByTokenIndex(tokenIndex)
|
||||
)
|
||||
const max = Math.max(balance, 0)
|
||||
|
||||
const sizeToCompare = isBuySide ? quoteSize : baseSize
|
||||
const isSizeTooLarge = parseFloat(sizeToCompare) > max
|
||||
|
||||
set((s) => {
|
||||
if (max <= 0) {
|
||||
s.tradeForm.baseSize = ''
|
||||
s.tradeForm.quoteSize = ''
|
||||
return
|
||||
}
|
||||
if (isSizeTooLarge) {
|
||||
if (isBuySide) {
|
||||
s.tradeForm.quoteSize = floorToDecimal(max, tickDecimals).toFixed()
|
||||
s.tradeForm.baseSize = floorToDecimal(
|
||||
max / Number(tradePrice),
|
||||
minOrderDecimals
|
||||
).toFixed()
|
||||
} else {
|
||||
s.tradeForm.baseSize = floorToDecimal(
|
||||
max,
|
||||
minOrderDecimals
|
||||
).toFixed()
|
||||
s.tradeForm.quoteSize = floorToDecimal(
|
||||
max * Number(tradePrice),
|
||||
tickDecimals
|
||||
).toFixed()
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
[savedCheckboxSettings]
|
||||
[
|
||||
mangoAccount,
|
||||
oraclePrice,
|
||||
savedCheckboxSettings,
|
||||
selectedMarket,
|
||||
set,
|
||||
tradeForm,
|
||||
]
|
||||
)
|
||||
|
||||
const [tickDecimals, tickSize] = useMemo(() => {
|
||||
|
@ -362,6 +413,8 @@ const AdvancedTradeForm = () => {
|
|||
: tradeForm.postOnly
|
||||
? PerpOrderType.postOnly
|
||||
: PerpOrderType.limit
|
||||
console.log('perpOrderType', perpOrderType)
|
||||
|
||||
const tx = await client.perpPlaceOrder(
|
||||
group,
|
||||
mangoAccount,
|
||||
|
@ -580,7 +633,7 @@ const AdvancedTradeForm = () => {
|
|||
content={t('trade:tooltip-post')}
|
||||
>
|
||||
<Checkbox
|
||||
checked={savedCheckboxSettings.post}
|
||||
checked={tradeForm.postOnly}
|
||||
onChange={(e) => handlePostOnlyChange(e.target.checked)}
|
||||
>
|
||||
{t('trade:post')}
|
||||
|
@ -596,7 +649,7 @@ const AdvancedTradeForm = () => {
|
|||
>
|
||||
<div className="flex items-center text-xs text-th-fgd-3">
|
||||
<Checkbox
|
||||
checked={savedCheckboxSettings.ioc}
|
||||
checked={tradeForm.ioc}
|
||||
onChange={(e) => handleIocChange(e.target.checked)}
|
||||
>
|
||||
IOC
|
||||
|
@ -654,7 +707,7 @@ const AdvancedTradeForm = () => {
|
|||
? 'bg-th-up-dark text-white md:hover:bg-th-up'
|
||||
: 'bg-th-down-dark text-white md:hover:bg-th-down'
|
||||
}`}
|
||||
disabled={connected && !tradeForm.baseSize}
|
||||
disabled={connected && (!tradeForm.baseSize || !tradeForm.price)}
|
||||
size="large"
|
||||
type="submit"
|
||||
>
|
||||
|
|
|
@ -1,8 +1,13 @@
|
|||
// import ChartRangeButtons from '@components/shared/ChartRangeButtons'
|
||||
import Change from '@components/shared/Change'
|
||||
import FavoriteMarketButton from '@components/shared/FavoriteMarketButton'
|
||||
import SheenLoader from '@components/shared/SheenLoader'
|
||||
import { getOneDayPerpStats } from '@components/stats/PerpMarketsTable'
|
||||
import { Popover } from '@headlessui/react'
|
||||
import { ChevronDownIcon } from '@heroicons/react/20/solid'
|
||||
import mangoStore from '@store/mangoStore'
|
||||
import { useBirdeyeMarketPrices } from 'hooks/useBirdeyeMarketPrices'
|
||||
import useMangoGroup from 'hooks/useMangoGroup'
|
||||
import useSelectedMarket from 'hooks/useSelectedMarket'
|
||||
import { useTranslation } from 'next-i18next'
|
||||
import Link from 'next/link'
|
||||
|
@ -15,6 +20,11 @@ const MarketSelectDropdown = () => {
|
|||
const { selectedMarket } = useSelectedMarket()
|
||||
const serumMarkets = mangoStore((s) => s.serumMarkets)
|
||||
const allPerpMarkets = mangoStore((s) => s.perpMarkets)
|
||||
const perpStats = mangoStore((s) => s.perpStats.data)
|
||||
const loadingPerpStats = mangoStore((s) => s.perpStats.loading)
|
||||
const { group } = useMangoGroup()
|
||||
const { data: birdeyePrices, isLoading: loadingPrices } =
|
||||
useBirdeyeMarketPrices()
|
||||
// const [spotBaseFilter, setSpotBaseFilter] = useState('All')
|
||||
|
||||
const perpMarkets = useMemo(() => {
|
||||
|
@ -61,10 +71,17 @@ const MarketSelectDropdown = () => {
|
|||
} mt-0.5 ml-2 h-6 w-6 flex-shrink-0 text-th-fgd-2`}
|
||||
/>
|
||||
</Popover.Button>
|
||||
<Popover.Panel className="absolute -left-4 top-12 z-40 mr-4 w-screen rounded-none bg-th-bkg-2 pb-4 pt-2 md:-left-6 md:w-72 md:rounded-br-md">
|
||||
<Popover.Panel className="absolute -left-4 top-12 z-40 mr-4 w-screen rounded-none bg-th-bkg-2 pb-4 pt-2 md:-left-6 md:w-96 md:rounded-br-md">
|
||||
<p className="my-2 ml-4 text-xs md:ml-6">{t('perp')}</p>
|
||||
{perpMarkets?.length
|
||||
? perpMarkets.map((m) => {
|
||||
const changeData = getOneDayPerpStats(perpStats, m.name)
|
||||
|
||||
const change = changeData.length
|
||||
? ((m.uiPrice - changeData[0].price) /
|
||||
changeData[0].price) *
|
||||
100
|
||||
: 0
|
||||
return (
|
||||
<div
|
||||
className="flex items-center justify-between py-2 px-4 md:px-6"
|
||||
|
@ -93,8 +110,17 @@ const MarketSelectDropdown = () => {
|
|||
</span>
|
||||
</div>
|
||||
</Link>
|
||||
<div className="flex items-center space-x-3">
|
||||
{!loadingPerpStats ? (
|
||||
<Change change={change} suffix="%" />
|
||||
) : (
|
||||
<SheenLoader className="mt-0.5">
|
||||
<div className="h-3.5 w-12 bg-th-bkg-2" />
|
||||
</SheenLoader>
|
||||
)}
|
||||
<FavoriteMarketButton market={m} />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
: null}
|
||||
|
@ -105,6 +131,21 @@ const MarketSelectDropdown = () => {
|
|||
.map((x) => x)
|
||||
.sort((a, b) => a.name.localeCompare(b.name))
|
||||
.map((m) => {
|
||||
const birdeyeData = birdeyePrices?.length
|
||||
? birdeyePrices.find(
|
||||
(market) =>
|
||||
market.mint === m.serumMarketExternal.toString()
|
||||
)
|
||||
: null
|
||||
const bank = group?.getFirstBankByTokenIndex(
|
||||
m.baseTokenIndex
|
||||
)
|
||||
const change =
|
||||
birdeyeData && bank
|
||||
? ((bank.uiPrice - birdeyeData.data[0].value) /
|
||||
birdeyeData.data[0].value) *
|
||||
100
|
||||
: 0
|
||||
return (
|
||||
<div
|
||||
className="flex items-center justify-between py-2 px-4 md:px-6"
|
||||
|
@ -133,8 +174,17 @@ const MarketSelectDropdown = () => {
|
|||
</span>
|
||||
</div>
|
||||
</Link>
|
||||
<div className="flex items-center space-x-3">
|
||||
{!loadingPrices ? (
|
||||
<Change change={change} suffix="%" />
|
||||
) : (
|
||||
<SheenLoader className="mt-0.5">
|
||||
<div className="h-3.5 w-12 bg-th-bkg-2" />
|
||||
</SheenLoader>
|
||||
)}
|
||||
<FavoriteMarketButton market={m} />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</>
|
||||
|
|
|
@ -81,12 +81,12 @@ const MaxSizeButton = ({
|
|||
if (tradeType === 'Market' || !price) {
|
||||
state.tradeForm.quoteSize = floorToDecimal(
|
||||
max * oraclePrice,
|
||||
minOrderDecimals
|
||||
tickDecimals
|
||||
).toFixed()
|
||||
} else {
|
||||
state.tradeForm.quoteSize = floorToDecimal(
|
||||
max * parseFloat(price),
|
||||
minOrderDecimals
|
||||
tickDecimals
|
||||
).toFixed()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ export const usePerpFundingRate = () => {
|
|||
|
||||
export const formatFunding = Intl.NumberFormat('en', {
|
||||
minimumSignificantDigits: 1,
|
||||
maximumSignificantDigits: 2,
|
||||
maximumSignificantDigits: 3,
|
||||
style: 'percent',
|
||||
})
|
||||
|
||||
|
@ -54,22 +54,18 @@ const PerpFundingRate = () => {
|
|||
}, [rate, selectedMarket])
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="font-mono text-xs text-th-fgd-2">
|
||||
<p className="font-mono text-xs text-th-fgd-2">
|
||||
{selectedMarket instanceof PerpMarket && fundingRate ? (
|
||||
`${formatFunding.format(fundingRate)}`
|
||||
<span>
|
||||
{formatFunding.format(fundingRate)}
|
||||
<span className="mx-1">|</span>
|
||||
{formatFunding.format(fundingRate * 8760)}{' '}
|
||||
<span className="font-body text-th-fgd-3">APR</span>
|
||||
</span>
|
||||
) : (
|
||||
<span className="text-th-fgd-4">-</span>
|
||||
)}
|
||||
</div>
|
||||
{/* <div className="font-mono text-xs text-th-fgd-2">
|
||||
{selectedMarket instanceof PerpMarket &&
|
||||
bids instanceof BookSide &&
|
||||
asks instanceof BookSide
|
||||
? selectedMarket.getCurrentFundingRate(bids, asks)
|
||||
: '-'}
|
||||
</div> */}
|
||||
</>
|
||||
</p>
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
import { PerpMarket, PerpPosition } from '@blockworks-foundation/mango-v4'
|
||||
import Button, { LinkButton } from '@components/shared/Button'
|
||||
import { TwitterIcon } from '@components/icons/TwitterIcon'
|
||||
import SharePositionModal from '@components/modals/SharePositionModal'
|
||||
import Button, { IconButton, LinkButton } from '@components/shared/Button'
|
||||
import ConnectEmptyState from '@components/shared/ConnectEmptyState'
|
||||
import FormatNumericValue from '@components/shared/FormatNumericValue'
|
||||
import { Table, Td, Th, TrBody, TrHead } from '@components/shared/TableElements'
|
||||
|
@ -30,6 +32,10 @@ const PerpPositions = () => {
|
|||
const [positionToClose, setPositionToClose] = useState<PerpPosition | null>(
|
||||
null
|
||||
)
|
||||
const [showShareModal, setShowShareModal] = useState(false)
|
||||
const [positionToShare, setPositionToShare] = useState<PerpPosition | null>(
|
||||
null
|
||||
)
|
||||
const perpPositions = mangoStore((s) => s.mangoAccount.perpPositions)
|
||||
const { selectedMarket } = useSelectedMarket()
|
||||
const { connected } = useWallet()
|
||||
|
@ -75,13 +81,20 @@ const PerpPositions = () => {
|
|||
setPositionToClose(null)
|
||||
}, [])
|
||||
|
||||
const handleShowShare = (position: PerpPosition) => {
|
||||
setPositionToShare(position)
|
||||
setShowShareModal(true)
|
||||
}
|
||||
|
||||
if (!group) return null
|
||||
|
||||
const openPerpPositions = Object.values(perpPositions).filter((p) =>
|
||||
p.basePositionLots.toNumber()
|
||||
)
|
||||
|
||||
return mangoAccountAddress && openPerpPositions.length ? (
|
||||
return (
|
||||
<>
|
||||
{mangoAccountAddress && openPerpPositions.length ? (
|
||||
showTableView ? (
|
||||
<>
|
||||
<div className="thin-scroll overflow-x-auto">
|
||||
|
@ -102,7 +115,7 @@ const PerpPositions = () => {
|
|||
</TrHead>
|
||||
</thead>
|
||||
<tbody>
|
||||
{openPerpPositions.map((position) => {
|
||||
{openPerpPositions.map((position, index) => {
|
||||
const market = group.getPerpMarketByMarketIndex(
|
||||
position.marketIndex
|
||||
)
|
||||
|
@ -122,7 +135,10 @@ const PerpPositions = () => {
|
|||
position.cumulativePnlOverPositionLifetimeUi(market)
|
||||
|
||||
return (
|
||||
<TrBody key={`${position.marketIndex}`} className="my-1 p-2">
|
||||
<TrBody
|
||||
key={`${position.marketIndex}`}
|
||||
className="my-1 p-2"
|
||||
>
|
||||
<Td>
|
||||
<TableMarketName market={market} />
|
||||
</Td>
|
||||
|
@ -139,7 +155,9 @@ const PerpPositions = () => {
|
|||
>
|
||||
<FormatNumericValue
|
||||
value={Math.abs(basePosition)}
|
||||
decimals={getDecimalCount(market.minOrderSize)}
|
||||
decimals={getDecimalCount(
|
||||
market.minOrderSize
|
||||
)}
|
||||
/>
|
||||
</LinkButton>
|
||||
) : (
|
||||
|
@ -152,7 +170,9 @@ const PerpPositions = () => {
|
|||
</Td>
|
||||
<Td className="text-right font-mono">
|
||||
<FormatNumericValue
|
||||
value={Math.abs(floorBasePosition) * market._uiPrice}
|
||||
value={
|
||||
Math.abs(floorBasePosition) * market._uiPrice
|
||||
}
|
||||
isUsd
|
||||
/>
|
||||
</Td>
|
||||
|
@ -182,10 +202,15 @@ const PerpPositions = () => {
|
|||
cummulativePnl > 0 ? 'text-th-up' : 'text-th-down'
|
||||
}`}
|
||||
>
|
||||
<FormatNumericValue value={cummulativePnl} isUsd />
|
||||
<FormatNumericValue
|
||||
value={cummulativePnl}
|
||||
isUsd
|
||||
decimals={2}
|
||||
/>
|
||||
</Td>
|
||||
{!isUnownedAccount ? (
|
||||
<Td className={`text-right`}>
|
||||
<Td>
|
||||
<div className="flex items-center justify-end space-x-4">
|
||||
<Button
|
||||
className="text-xs"
|
||||
secondary
|
||||
|
@ -194,6 +219,16 @@ const PerpPositions = () => {
|
|||
>
|
||||
Close
|
||||
</Button>
|
||||
<IconButton
|
||||
hideBg
|
||||
onClick={() =>
|
||||
handleShowShare(openPerpPositions[index])
|
||||
}
|
||||
disabled={!group || !basePosition}
|
||||
>
|
||||
<TwitterIcon className="h-4 w-4" />
|
||||
</IconButton>
|
||||
</div>
|
||||
</Td>
|
||||
) : null}
|
||||
</TrBody>
|
||||
|
@ -213,7 +248,9 @@ const PerpPositions = () => {
|
|||
) : (
|
||||
<>
|
||||
{openPerpPositions.map((position) => {
|
||||
const market = group.getPerpMarketByMarketIndex(position.marketIndex)
|
||||
const market = group.getPerpMarketByMarketIndex(
|
||||
position.marketIndex
|
||||
)
|
||||
const basePosition = position.getBasePositionUi(market)
|
||||
const floorBasePosition = floorToDecimal(
|
||||
basePosition,
|
||||
|
@ -238,7 +275,9 @@ const PerpPositions = () => {
|
|||
<div>
|
||||
<div className="mb-1 flex space-x-1 leading-none text-th-fgd-2">
|
||||
{selectedMarket?.name === market.name ? (
|
||||
<span className="whitespace-nowrap">{market.name}</span>
|
||||
<span className="whitespace-nowrap">
|
||||
{market.name}
|
||||
</span>
|
||||
) : (
|
||||
<Link href={`/trade?name=${market.name}`}>
|
||||
<div className="default-transition flex items-center underline underline-offset-2 md:hover:text-th-fgd-3 md:hover:no-underline">
|
||||
|
@ -262,7 +301,9 @@ const PerpPositions = () => {
|
|||
>
|
||||
<FormatNumericValue
|
||||
value={Math.abs(basePosition)}
|
||||
decimals={getDecimalCount(market.minOrderSize)}
|
||||
decimals={getDecimalCount(
|
||||
market.minOrderSize
|
||||
)}
|
||||
/>
|
||||
</LinkButton>
|
||||
) : (
|
||||
|
@ -318,6 +359,16 @@ const PerpPositions = () => {
|
|||
<div className="p-8">
|
||||
<ConnectEmptyState text={t('trade:connect-positions')} />
|
||||
</div>
|
||||
)}
|
||||
{showShareModal ? (
|
||||
<SharePositionModal
|
||||
group={group}
|
||||
isOpen={showShareModal}
|
||||
onClose={() => setShowShareModal(false)}
|
||||
position={positionToShare!}
|
||||
/>
|
||||
) : null}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -104,11 +104,12 @@ const UnsettledTrades = ({
|
|||
const unprofitableAccount =
|
||||
mangoAccountPnl > 0 ? settleCandidates[0].account : mangoAccount
|
||||
|
||||
const txid = await client.perpSettlePnl(
|
||||
const txid = await client.perpSettlePnlAndFees(
|
||||
group,
|
||||
profitableAccount,
|
||||
unprofitableAccount,
|
||||
mangoAccount,
|
||||
mangoAccount,
|
||||
market.perpMarketIndex
|
||||
)
|
||||
actions.reloadMangoAccount()
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
import { Serum3Market } from '@blockworks-foundation/mango-v4'
|
||||
import mangoStore from '@store/mangoStore'
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
import { makeApiRequest } from 'apis/birdeye/helpers'
|
||||
|
||||
export interface BirdeyePriceResponse {
|
||||
address: string
|
||||
unixTime: number
|
||||
value: number
|
||||
}
|
||||
|
||||
const fetchBirdeyePrices = async (
|
||||
spotMarkets: Serum3Market[]
|
||||
): Promise<{ data: BirdeyePriceResponse[]; mint: string }[]> => {
|
||||
const mints = spotMarkets.map((market) =>
|
||||
market.serumMarketExternal.toString()
|
||||
)
|
||||
|
||||
const promises = []
|
||||
const queryEnd = Math.floor(Date.now() / 1000)
|
||||
const queryStart = queryEnd - 86400
|
||||
for (const mint of mints) {
|
||||
const query = `defi/history_price?address=${mint}&address_type=pair&type=30m&time_from=${queryStart}&time_to=${queryEnd}`
|
||||
promises.push(makeApiRequest(query))
|
||||
}
|
||||
|
||||
const responses = await Promise.all(promises)
|
||||
if (responses?.length) {
|
||||
return responses.map((res) => ({
|
||||
data: res.data.items,
|
||||
mint: res.data.items[0].address,
|
||||
}))
|
||||
}
|
||||
|
||||
return []
|
||||
}
|
||||
|
||||
export const useBirdeyeMarketPrices = () => {
|
||||
const spotMarkets = mangoStore((s) => s.serumMarkets)
|
||||
const res = useQuery(
|
||||
['birdeye-market-prices'],
|
||||
() => fetchBirdeyePrices(spotMarkets),
|
||||
{
|
||||
cacheTime: 1000 * 60 * 15,
|
||||
staleTime: 1000 * 60 * 10,
|
||||
retry: 3,
|
||||
enabled: !!spotMarkets?.length,
|
||||
refetchOnWindowFocus: false,
|
||||
}
|
||||
)
|
||||
|
||||
return {
|
||||
isFetching: res?.isFetching,
|
||||
isLoading: res?.isLoading,
|
||||
data: res?.data || [],
|
||||
}
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
import { useState } from 'react'
|
||||
import html2canvas from 'html2canvas'
|
||||
|
||||
/**
|
||||
* @module Main_Hook
|
||||
* Hook return
|
||||
* @typedef {Array} HookReturn
|
||||
* @property {string} HookReturn[0] - image string
|
||||
* @property {string} HookReturn[1] - take screen shot string
|
||||
* @property {object} HookReturn[2] - errors
|
||||
*/
|
||||
|
||||
/**
|
||||
* hook for creating screenshot from html node
|
||||
* @returns {HookReturn}
|
||||
*/
|
||||
const useScreenshot: () => [
|
||||
HTMLCanvasElement | null,
|
||||
(node: HTMLElement) => Promise<void | HTMLCanvasElement>,
|
||||
{ error: null }
|
||||
] = () => {
|
||||
const [image, setImage] = useState<HTMLCanvasElement | null>(null)
|
||||
const [error, setError] = useState(null)
|
||||
/**
|
||||
* convert html node to image
|
||||
* @param {HTMLElement} node
|
||||
*/
|
||||
const takeScreenshot = (node: HTMLElement) => {
|
||||
if (!node) {
|
||||
throw new Error('You should provide correct html node.')
|
||||
}
|
||||
return html2canvas(node)
|
||||
.then((canvas) => {
|
||||
const croppedCanvas = document.createElement('canvas')
|
||||
const croppedCanvasContext = croppedCanvas.getContext('2d')
|
||||
// init data
|
||||
const cropPositionTop = 0
|
||||
const cropPositionLeft = 0
|
||||
const cropWidth = canvas.width
|
||||
const cropHeight = canvas.height
|
||||
|
||||
croppedCanvas.width = cropWidth
|
||||
croppedCanvas.height = cropHeight
|
||||
|
||||
croppedCanvasContext?.drawImage(
|
||||
canvas,
|
||||
cropPositionLeft,
|
||||
cropPositionTop
|
||||
)
|
||||
|
||||
setImage(croppedCanvas)
|
||||
return croppedCanvas
|
||||
})
|
||||
.catch(setError)
|
||||
}
|
||||
|
||||
return [
|
||||
image,
|
||||
takeScreenshot,
|
||||
{
|
||||
error,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
/**
|
||||
* creates name of file
|
||||
* @param {string} extension
|
||||
* @param {string[]} parts of file name
|
||||
*/
|
||||
const createFileName = (extension = '', ...names: string[]) => {
|
||||
if (!extension) {
|
||||
return ''
|
||||
}
|
||||
|
||||
return `${names.join('')}.${extension}`
|
||||
}
|
||||
|
||||
export { useScreenshot, createFileName }
|
|
@ -18,14 +18,14 @@
|
|||
"postinstall": "tar -xzC public -f vendor/charting_library.tgz;tar -xzC public -f vendor/datafeeds.tgz"
|
||||
},
|
||||
"dependencies": {
|
||||
"@blockworks-foundation/mango-v4": "^0.9.14",
|
||||
"@blockworks-foundation/mango-v4": "^0.9.15",
|
||||
"@headlessui/react": "1.6.6",
|
||||
"@heroicons/react": "2.0.10",
|
||||
"@project-serum/anchor": "0.25.0",
|
||||
"@pythnetwork/client": "2.15.0",
|
||||
"@solana/spl-governance": "0.3.25",
|
||||
"@solana/wallet-adapter-base": "0.9.20",
|
||||
"@solana/wallet-adapter-react": "0.15.28",
|
||||
"@solana/wallet-adapter-react": "0.15.32",
|
||||
"@solana/wallet-adapter-wallets": "0.19.11",
|
||||
"@solflare-wallet/pfp": "0.0.6",
|
||||
"@tanstack/react-query": "4.10.1",
|
||||
|
@ -40,6 +40,7 @@
|
|||
"decimal.js": "10.4.0",
|
||||
"howler": "2.2.3",
|
||||
"html-react-parser": "3.0.4",
|
||||
"html2canvas": "1.4.1",
|
||||
"http-proxy-middleware": "2.0.6",
|
||||
"immer": "9.0.12",
|
||||
"klinecharts": "8.6.3",
|
||||
|
@ -63,7 +64,7 @@
|
|||
},
|
||||
"peerDependencies": {
|
||||
"@project-serum/anchor": "0.25.0",
|
||||
"@project-serum/serum": ">=0.13.62",
|
||||
"@project-serum/serum": "0.13.65",
|
||||
"@solana/web3.js": ">=1.70.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
|
@ -94,11 +94,11 @@ function MyApp({ Component, pageProps }: AppProps) {
|
|||
<meta name="twitter:title" content="Mango Markets" />
|
||||
<meta
|
||||
name="twitter:description"
|
||||
content="Mango Markets - Decentralised, cross-margin trading up to 10x leverage with lightning speed and near-zero fees."
|
||||
content="A magical new way to interact with DeFi. Groundbreaking safety features designed to keep your funds secure."
|
||||
/>
|
||||
<meta
|
||||
name="twitter:image"
|
||||
content="https://www.mango.markets/socials/twitter-image-1200x600.png?34567878"
|
||||
content="https://app.mango.markets/images/1200x600-share.png?34567878"
|
||||
/>
|
||||
<meta name="google" content="notranslate" />
|
||||
<link rel="manifest" href="/manifest.json"></link>
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 134 KiB |
|
@ -0,0 +1,63 @@
|
|||
<svg width="1200" height="675" viewBox="0 0 1200 675" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_1361_21222)">
|
||||
<g opacity="0.2" filter="url(#filter0_f_1361_21222)">
|
||||
<circle cx="929" cy="138" r="210" fill="#8477C4"/>
|
||||
</g>
|
||||
<circle cx="929" cy="138" r="210" fill="url(#paint0_radial_1361_21222)"/>
|
||||
<path d="M1347.3 601.267C1272.11 602.466 1227.01 603.279 1212.03 603.701C1197.05 604.055 1174.56 602.43 1144.57 598.828C1114.53 595.225 1069.29 588.233 1008.85 577.852C948.462 567.257 905.115 562.666 878.792 564.079C852.408 565.348 825.006 568.739 796.584 574.25C768.101 579.687 733.264 585.268 692.069 590.988C655.133 598.545 617.026 605.784 577.751 612.707C538.418 619.632 509.576 621.006 491.228 616.839C465.384 614.72 430.936 608.117 387.884 597.029C334.337 583.183 294.343 576.263 267.898 576.263C227.125 576.263 187.611 581.17 149.355 590.988C126.628 596.778 113.018 600.135 108.521 601.053C93.5311 604.091 78.7804 605.608 64.269 605.608C58.5721 605.608 52.8157 605.22 47 604.445C49.218 605.714 51.4666 606.987 53.7457 608.257C57.1635 610.236 60.8206 612.425 64.7188 614.826C77.6687 622.384 93.1101 631.777 111.039 643.009C130.285 654.31 148.245 662.362 164.913 667.164C185.782 673.097 210.606 676.063 239.388 676.063C246.103 676.063 278.963 672.815 337.965 666.318C396.966 659.892 432.105 656.675 443.378 656.675C464.186 656.675 487.33 659.287 512.814 664.515C527.984 667.694 550.83 673.45 581.349 681.787C611.629 690.19 634.536 695.983 650.067 699.162C675.789 704.389 699.235 707 720.401 707C741.447 707 760.906 704.989 778.774 700.961C790.229 698.348 804.407 693.898 821.319 687.614C839.307 680.903 852.588 676.49 861.161 674.371C877.053 670.272 893.841 668.223 911.531 668.223C924.249 668.223 949.307 672.109 986.724 679.877C1024.19 687.647 1047.7 691.532 1057.24 691.532C1086.38 691.532 1113.78 686.304 1139.45 675.853C1157.02 668.789 1184.78 658.654 1222.73 645.445L1347.3 601.267Z" fill="#1C192B"/>
|
||||
<path d="M1368.29 535.153C1352.54 541.457 1338.26 546.652 1325.48 550.739C1302.41 558.12 1276.83 567.153 1248.76 577.835C1220.76 588.58 1205.91 594.281 1204.2 594.94C1178.05 605.231 1155.99 612.53 1138.02 616.842C1112.94 622.861 1086.17 625.872 1057.69 625.872C1048.38 625.872 1025.4 623.636 988.791 619.159C952.23 614.682 927.744 612.446 915.317 612.446C898.032 612.446 881.627 613.617 866.099 615.962C857.722 617.186 844.744 619.744 827.167 623.636C810.642 627.257 796.788 629.815 785.595 631.307C768.135 633.651 749.122 634.825 728.556 634.825C707.875 634.825 684.964 633.305 659.83 630.268C644.654 628.456 622.271 625.127 592.683 620.277C562.861 615.428 540.538 612.098 525.715 610.286C500.813 607.25 478.198 605.73 457.867 605.73C446.851 605.73 412.515 607.595 354.863 611.325C297.209 615.054 265.101 616.92 258.539 616.92C230.415 616.92 206.159 615.216 185.767 611.804C169.48 609.034 151.931 604.398 133.125 597.897C115.597 591.423 100.51 585.96 87.8631 581.512C84.0699 580.205 80.4964 578.98 77.1409 577.835C74.942 577.085 72.7149 576.34 70.4615 575.598C46.2417 567.553 20.8705 560.333 -5.64845 553.936V599.657L-6 599.735V716.03H1409.33V517.809C1394.69 524.314 1380.99 530.094 1368.29 535.153Z" fill="#2A2440"/>
|
||||
<g filter="url(#filter1_f_1361_21222)">
|
||||
<path d="M855.299 287.708C754.602 259.807 690.732 222.958 610.014 157.337C537.662 98.5179 485.094 15.6903 455.5 -71.3529C446.51 -97.7966 444.893 -124.359 443.35 -152.73" stroke="#5B48AD" stroke-width="83" stroke-linecap="round"/>
|
||||
</g>
|
||||
<path d="M853.536 282.283L798.345 286.431C793.83 286.77 792.012 283.229 794.275 278.52L841.694 179.999C843.962 175.292 849.459 171.198 853.97 170.858L909.161 166.71C913.676 166.372 915.494 169.912 913.231 174.621L865.811 273.145C863.545 277.853 858.05 281.945 853.536 282.283Z" fill="#DCE4ED"/>
|
||||
<path d="M820.607 268.79L793.901 284.594L814.051 314.008L845.728 292.924L820.607 268.79Z" fill="#DCE4ED"/>
|
||||
<path d="M932.671 196.35L913.15 167.951L883.908 181.068L885.937 212.192L932.671 196.35Z" fill="#DCE4ED"/>
|
||||
<path d="M873.179 310.808L817.985 314.958C813.474 315.295 811.653 311.753 813.919 307.046L861.338 208.524C863.604 203.816 869.099 199.725 873.611 199.385L928.802 195.235C933.316 194.899 935.138 198.438 932.871 203.148L885.452 301.67C883.187 306.378 877.691 310.469 873.179 310.808Z" fill="#C1CED6"/>
|
||||
<path d="M872.542 308.175L821.3 312.028C817.111 312.343 815.42 309.053 817.525 304.683L863.218 209.744C865.32 205.373 870.426 201.572 874.614 201.26L925.856 197.408C930.047 197.093 931.736 200.382 929.634 204.753L883.938 299.692C881.833 304.061 876.734 307.861 872.542 308.175Z" fill="#B0C3CB"/>
|
||||
<path d="M808.708 296.315L804.83 290.631C803.391 288.523 803.266 284.662 804.541 282.01L845.612 196.672C846.89 194.018 849.089 193.576 850.528 195.684L854.404 201.365C855.843 203.473 855.969 207.334 854.694 209.986L813.623 295.323C812.344 297.977 810.145 298.419 808.708 296.315Z" fill="#B0C3CB"/>
|
||||
<path d="M843.349 197.919L843.958 194.971L848.039 194.39L849.541 196.885L843.349 197.919Z" fill="#B0C3CB"/>
|
||||
<path d="M807.186 295.501L807.42 298.106L811.434 297.543L812.005 293.213L807.186 295.501Z" fill="#B0C3CB"/>
|
||||
<path d="M804.72 296.872L800.846 291.193C799.407 289.084 799.278 285.225 800.554 282.57L841.628 197.234C842.906 194.58 845.106 194.135 846.541 196.245L850.418 201.925C851.856 204.034 851.986 207.893 850.71 210.548L809.636 295.884C808.357 298.538 806.158 298.98 804.72 296.872Z" fill="#C1CED6"/>
|
||||
<path d="M846.807 214.118C845.204 217.441 842.448 217.999 840.647 215.357C838.846 212.718 838.684 207.882 840.284 204.555C841.885 201.228 844.643 200.674 846.444 203.316C848.243 205.954 848.407 210.791 846.807 214.118Z" fill="#F84638"/>
|
||||
<path d="M845.328 212.471C844.275 214.668 842.455 215.033 841.267 213.291C840.079 211.549 839.971 208.359 841.026 206.165C842.084 203.971 843.904 203.607 845.091 205.349C846.28 207.088 846.385 210.28 845.328 212.471Z" fill="#F2C94C"/>
|
||||
<path d="M916.927 225.495C916.927 225.495 926.978 219.307 937.05 225.993C942.943 229.903 945.66 235.156 950.013 242.096C953.109 247.02 956.62 255.139 960.829 261.45C973.428 269.263 976.441 281.863 977.87 288.902C978.228 290.664 979.109 301.02 971.524 299.583C958.757 297.166 946.902 282.798 945.704 276.823C937.546 274.343 916.193 246.465 915.351 244.7C914.508 242.938 916.927 225.495 916.927 225.495Z" fill="#DCE4ED"/>
|
||||
<path d="M821.032 391.143C821.032 391.143 815.488 395.36 811.066 398.647C806.644 401.932 808.011 404.895 809.377 407.259C810.742 409.626 813.539 411.4 813.539 411.4C813.539 411.4 812.114 419.438 819.057 428.448C826.002 437.46 830.626 436.949 833.182 435.944C835.742 434.94 842.992 433.146 841.729 427.351C840.46 421.556 834.281 406.735 834.281 406.735L821.032 391.143Z" fill="#2A2440"/>
|
||||
<path d="M826.466 384.975C826.466 384.975 818.748 385.003 820.87 394.462C823.213 404.891 835.056 412.899 841.141 406.814C847.225 400.726 826.466 384.975 826.466 384.975Z" fill="#C1CED6"/>
|
||||
<path d="M862.18 356.856C856.479 359.611 848.287 366.058 842.571 370.557C840.148 372.463 838.171 374.019 837.016 374.796C835.003 376.15 833.114 377.253 831.393 378.259C826.76 380.964 823.339 382.962 821.981 387.237C820.846 390.807 829.087 404.082 835.369 406.744C841.877 409.498 845.036 406.86 849.663 402.995C850.594 402.217 851.584 401.391 852.672 400.548C860.096 394.798 875.538 384.356 881.865 380.084C888.434 375.648 890.329 372.524 892.268 368.504C897.208 359.759 900.88 341.449 902.879 331.481C903.227 329.745 903.525 328.262 903.769 327.127C905.84 317.518 910.883 301.467 910.883 301.467L873.464 293.595C873.464 293.595 862.803 302.215 860.977 309.918C859.151 317.622 859.401 324.353 860.155 329.814C860.48 332.167 861.837 351.849 862.18 356.856Z" fill="#CDD9E2"/>
|
||||
<path d="M776.336 346.719C776.336 346.719 766.712 348.213 760.865 350.185C755.015 352.156 755.276 355.896 755.641 357.229C756.001 358.562 754.871 359.951 754.871 359.951C754.871 359.951 748.768 363.016 746.171 369.939C743.576 376.864 745.536 386.16 750.15 388.161C754.766 390.164 761.382 389.445 766.092 381.601C770.805 373.755 777.061 366.964 777.061 366.964L776.336 346.719Z" fill="#2A2440"/>
|
||||
<path d="M777.164 345.941C777.164 345.941 770.195 342.945 768.405 352.304C766.434 362.623 773.978 374.48 781.849 371.375C789.717 368.268 777.164 345.941 777.164 345.941Z" fill="#C1CED6"/>
|
||||
<path d="M851.938 277.64L888.607 304.757C888.607 304.757 884.508 315.82 878.083 325.099C874.627 330.082 870.923 332.712 868.146 334.684C866.959 335.526 865.941 336.248 865.185 336.983C864.65 337.501 863.791 338.473 862.67 339.741C857.096 346.048 845.059 359.668 834.377 361.033L834.375 361.033C834.382 361.044 834.39 361.055 834.397 361.066C826.684 362.562 819.518 364.123 815.95 364.955C812.987 365.648 808.853 366.722 804.56 367.837C796.612 369.902 788.116 372.109 785.471 372.311C781.398 372.619 773.203 366.833 771.355 359.749C770.013 354.599 772.354 345.032 777 341.86C782.58 338.053 808.742 331.305 823.011 327.787C824.354 325.026 825.657 322.109 826.994 319.117C829.838 312.754 832.832 306.053 836.672 299.81C843.402 288.88 851.938 277.64 851.938 277.64Z" fill="#DCE4ED"/>
|
||||
<path d="M849.521 279.97C854.08 287.737 860.459 296.234 877.141 303.102C897.451 311.464 905.975 306.387 910.97 303.702C912.463 302.902 913.416 297.388 913.416 297.388C913.416 297.388 899.98 306.261 878.767 297.171C863.405 290.588 857.288 281.228 852.328 275.724C851.537 274.844 848.304 277.893 849.521 279.97Z" fill="#1D1A2B"/>
|
||||
<path d="M855.72 269.946C854.725 271.828 853.414 274.04 852.083 276.249C856.911 286.8 870.835 297.252 884.595 300.706C905.999 306.079 913.361 297.675 913.419 297.389C918.784 288.158 925.941 274.716 929.725 266.368C934.772 255.229 939.757 242.001 937.872 235.081C937.032 231.993 932.447 223.842 924.889 218.936C911.199 210.05 884.515 209.513 878.312 218.513C874.221 224.451 869.358 237.637 865.78 247.983C863.199 255.446 859.288 263.196 855.72 269.946Z" fill="#ECF1F6"/>
|
||||
<path d="M920.363 246.328C919.216 248.706 916.527 249.786 914.351 248.739C912.177 247.693 911.339 244.915 912.487 242.538C913.631 240.16 916.323 239.08 918.496 240.126C920.672 241.176 921.508 243.95 920.363 246.328Z" fill="#F84638"/>
|
||||
<path d="M919.434 245.181C918.755 246.587 917.167 247.225 915.877 246.606C914.591 245.987 914.098 244.345 914.774 242.938C915.453 241.532 917.041 240.895 918.331 241.513C919.617 242.133 920.11 243.774 919.434 245.181Z" fill="#F2C94C"/>
|
||||
<path d="M893.262 206.145C893.744 209.937 895.059 211.476 897.485 214.683C901.666 220.211 906.052 224.859 912.458 227.811C918.967 230.811 927.586 232.388 934.523 229.833C936.011 229.288 937.359 228.472 938.63 227.516C938.966 225.38 939.376 223.55 939.973 221.79C943.691 219.086 946.815 215.456 948.949 211.025C955.832 196.725 949.818 179.554 935.518 172.672C929.168 169.617 921.922 169.682 915.646 171.503C906.47 174.17 901.619 178.484 897.168 186.104C891.731 195.41 893.948 203.529 893.262 206.145Z" fill="#DCE4ED"/>
|
||||
<path d="M896.327 213.081C896.69 213.603 897.067 214.132 897.486 214.683C901.667 220.211 906.053 224.859 912.46 227.811C918.969 230.811 927.588 232.388 934.525 229.833C936.012 229.288 937.361 228.472 938.631 227.515C938.967 225.38 939.377 223.55 939.974 221.79C943.692 219.086 946.816 215.456 948.951 211.025C951.095 206.57 951.006 201.776 951.766 197.222C953.364 187.648 947.363 177.559 937.518 172.819C931.168 169.764 920.658 170.187 914.329 171.811C913.745 172.007 902.34 177.254 899.37 190.564C896.319 204.239 898.767 204.279 896.327 213.081Z" fill="#ECF1F6"/>
|
||||
<path d="M938.885 225.94C938.885 225.94 924.477 229.604 913.28 221.793C903.925 215.269 902.708 208.599 908.071 198.781C912.48 190.708 915.387 187.925 928.437 189.106C940.869 190.236 951.759 197.22 951.759 197.22C951.759 197.22 952.993 201.315 949.417 211.25C946.952 218.102 938.885 225.94 938.885 225.94Z" fill="#DCE4ED"/>
|
||||
<path d="M946.892 198.114C941.963 195.57 932.244 191.766 922.455 191.716C917.087 191.691 912.499 195.183 909.291 201.982C907.384 206.027 906.503 211.031 911.311 215.783C918.218 222.605 927.3 224.856 933.643 224.743C937.855 224.668 940.75 224.006 940.75 224.006C940.75 224.006 949.753 217.823 951.765 205.173C952.371 200.062 949.716 199.569 946.892 198.114Z" fill="#1D1A2B"/>
|
||||
<path d="M951.765 205.17C952.371 200.062 949.715 199.569 946.891 198.114C941.962 195.569 932.243 191.766 922.454 191.716C919.295 191.701 916.414 192.938 913.919 195.32C922.77 195.616 931.571 199.025 937.111 206.457C941.479 212.314 942.234 218.768 939.7 224.203C940.365 224.09 940.749 224.005 940.749 224.005C940.749 224.005 949.752 217.823 951.765 205.17Z" fill="#4F4965"/>
|
||||
<path d="M893.264 206.145C892.414 206.934 891.182 213.668 901.491 223.643C911.8 233.619 924.958 236.096 932.838 232.725C938.479 230.313 938.89 225.941 938.89 225.941C938.89 225.941 936.726 230.147 928.101 230.249C919.161 230.353 907.81 227.683 898.348 215.454C894.098 209.961 893.264 206.145 893.264 206.145Z" fill="#1D1A2B"/>
|
||||
<path d="M875.651 244.93C882.236 239.163 894.362 229.65 886.934 214.872C882.655 206.347 867.614 213.221 857.594 221.991C849.71 228.891 838.957 236.942 835.786 242.496C829.217 253.999 825.933 270.19 822.793 281.209C829.855 278.382 837.156 281.105 841.362 283.348C843.573 279.141 850.479 268.85 852.06 264.986C853.176 262.251 855.254 256.942 855.254 256.942C855.254 256.942 865.808 253.549 875.651 244.93Z" fill="#DCE4ED"/>
|
||||
<path d="M842.46 292.514C841.593 290.742 840.246 285.459 840.246 285.459C840.246 285.459 844.18 283.526 842.437 281.293C840.693 279.059 833.093 276.993 826.189 278.152C819.284 279.315 822.085 282.988 822.085 282.988L822.263 283.012C819.141 293.318 815.543 299.942 820.158 306.79C824.959 313.907 830.163 316.974 833.092 311.051C836.023 305.129 834.076 297.411 834.419 294.445C834.571 293.111 838.54 296.274 840.711 296.937C843.361 297.744 844.165 296.001 842.46 292.514Z" fill="#2A2440"/>
|
||||
<path d="M979.1 288.851C979.1 288.851 979.326 285.418 974.392 286.585C971.047 287.375 965.697 291.36 964.833 295.557C964.334 297.983 966.96 299.247 966.96 299.247C966.96 299.247 967.781 305.262 970.838 309.406C974.783 314.756 975.683 318.388 978.012 318.455C980.833 318.538 979.164 312.655 978.207 310.28C977.569 308.692 978.075 307.378 979.789 308.271C981.206 309.008 981.952 310.795 984.048 313.091C988.682 318.163 999.712 320.576 994.605 307.374C993.115 303.522 989.868 298.322 986.293 295.457C982.619 292.509 979.1 288.851 979.1 288.851Z" fill="#2A2440"/>
|
||||
</g>
|
||||
<defs>
|
||||
<filter id="filter0_f_1361_21222" x="599" y="-192" width="660" height="660" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||
<feGaussianBlur stdDeviation="60" result="effect1_foregroundBlur_1361_21222"/>
|
||||
</filter>
|
||||
<filter id="filter1_f_1361_21222" x="137.85" y="-458.231" width="1022.96" height="1051.45" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||
<feGaussianBlur stdDeviation="132" result="effect1_foregroundBlur_1361_21222"/>
|
||||
</filter>
|
||||
<radialGradient id="paint0_radial_1361_21222" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(1059 -18) rotate(112.264) scale(322.006 332.517)">
|
||||
<stop stop-color="#8477C4"/>
|
||||
<stop offset="1"/>
|
||||
</radialGradient>
|
||||
<clipPath id="clip0_1361_21222">
|
||||
<rect width="1200" height="675" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 15 KiB |
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 95 KiB |
|
@ -11,6 +11,8 @@
|
|||
"connect-positions": "Connect to view your perp positions",
|
||||
"connect-trade-history": "Connect to view your trade history",
|
||||
"connect-unsettled": "Connect to view your unsettled funds",
|
||||
"copy-and-share": "Copy Image to Clipboard",
|
||||
"current-price": "Current Price",
|
||||
"entry-price": "Entry Price",
|
||||
"est-slippage": "Est. Slippage",
|
||||
"funding-limits": "Funding Limits",
|
||||
|
@ -70,6 +72,7 @@
|
|||
"tooltip-stable-price": "Stable price is used in a safety mechanism that limits a user's ability to enter risky positions when the oracle price is changing rapidly",
|
||||
"trade-sounds-tooltip": "Play a sound alert for every new trade",
|
||||
"trades": "Trades",
|
||||
"tweet-position": "Share to Twitter",
|
||||
"unsettled": "Unsettled",
|
||||
"volume-alert": "Volume Alert",
|
||||
"volume-alert-desc": "Play a sound whenever volume exceeds your alert threshold"
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
"connect-positions": "Connect to view your perp positions",
|
||||
"connect-trade-history": "Connect to view your trade history",
|
||||
"connect-unsettled": "Connect to view your unsettled funds",
|
||||
"copy-and-share": "Copy Image to Clipboard",
|
||||
"current-price": "Current Price",
|
||||
"entry-price": "Entry Price",
|
||||
"est-slippage": "Est. Slippage",
|
||||
"funding-limits": "Funding Limits",
|
||||
|
@ -70,6 +72,7 @@
|
|||
"tooltip-stable-price": "Stable price is used in a safety mechanism that limits a user's ability to enter risky positions when the oracle price is changing rapidly",
|
||||
"trade-sounds-tooltip": "Play a sound alert for every new trade",
|
||||
"trades": "Trades",
|
||||
"tweet-position": "Share to Twitter",
|
||||
"unsettled": "Unsettled",
|
||||
"volume-alert": "Volume Alert",
|
||||
"volume-alert-desc": "Play a sound whenever volume exceeds your alert threshold"
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
"connect-positions": "Connect to view your perp positions",
|
||||
"connect-trade-history": "Connect to view your trade history",
|
||||
"connect-unsettled": "Connect to view your unsettled funds",
|
||||
"copy-and-share": "Copy Image to Clipboard",
|
||||
"current-price": "Current Price",
|
||||
"entry-price": "Entry Price",
|
||||
"est-slippage": "Est. Slippage",
|
||||
"funding-limits": "Funding Limits",
|
||||
|
@ -70,6 +72,7 @@
|
|||
"tooltip-stable-price": "Stable price is used in a safety mechanism that limits a user's ability to enter risky positions when the oracle price is changing rapidly",
|
||||
"trade-sounds-tooltip": "Play a sound alert for every new trade",
|
||||
"trades": "Trades",
|
||||
"tweet-position": "Share to Twitter",
|
||||
"unsettled": "Unsettled",
|
||||
"volume-alert": "Volume Alert",
|
||||
"volume-alert-desc": "Play a sound whenever volume exceeds your alert threshold"
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
"connect-positions": "Connect to view your perp positions",
|
||||
"connect-trade-history": "Connect to view your trade history",
|
||||
"connect-unsettled": "Connect to view your unsettled funds",
|
||||
"copy-and-share": "Copy Image to Clipboard",
|
||||
"current-price": "Current Price",
|
||||
"entry-price": "Entry Price",
|
||||
"est-slippage": "Est. Slippage",
|
||||
"funding-limits": "Funding Limits",
|
||||
|
@ -70,6 +72,7 @@
|
|||
"tooltip-stable-price": "Stable price is used in a safety mechanism that limits a user's ability to enter risky positions when the oracle price is changing rapidly",
|
||||
"trade-sounds-tooltip": "Play a sound alert for every new trade",
|
||||
"trades": "Trades",
|
||||
"tweet-position": "Share to Twitter",
|
||||
"unsettled": "Unsettled",
|
||||
"volume-alert": "Volume Alert",
|
||||
"volume-alert-desc": "Play a sound whenever volume exceeds your alert threshold"
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
"connect-positions": "連接以查看您的持倉",
|
||||
"connect-trade-history": "連接以查看交易紀錄",
|
||||
"connect-unsettled": "連接以查看未結清餘額",
|
||||
"copy-and-share": "複製影像",
|
||||
"current-price": "目前價格",
|
||||
"entry-price": "入場價",
|
||||
"est-slippage": "預計下滑",
|
||||
"funding-limits": "資金費限制",
|
||||
|
@ -70,6 +72,7 @@
|
|||
"tooltip-volume-alert": "交易量警報設定",
|
||||
"trade-sounds-tooltip": "為每筆新交易播放警報聲音",
|
||||
"trades": "交易",
|
||||
"tweet-position": "分享至Twitter",
|
||||
"unsettled": "未結清",
|
||||
"volume-alert": "交易量警報",
|
||||
"volume-alert-desc": "交易量超過警報設定時播放聲音"
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
<svg width="142" height="37" viewBox="0 0 142 37" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M15.8764 10.5433C15.8766 10.5431 15.8767 10.5429 15.8769 10.5427C17.1286 11.1848 18.4982 11.4048 19.8088 11.401C20.5703 12.1004 21.2039 12.9219 21.7992 13.7654C22.0461 14.1178 22.2687 14.4864 22.4656 14.869C22.9208 15.7455 23.2556 16.6729 23.5944 17.6112C23.6937 17.8864 23.7934 18.1626 23.8966 18.4386C23.9289 18.5568 23.9627 18.675 23.9979 18.7933L23.9997 18.7928C24.5229 20.5871 25.2869 22.5039 26.3106 24.0865L26.3096 24.0869C26.6482 24.6068 27.0275 25.099 27.4439 25.559C27.5259 25.6477 27.6097 25.7355 27.6936 25.8234L27.6936 25.8234L27.6937 25.8234L27.6938 25.8235C28.0859 26.2343 28.4807 26.6479 28.7045 27.1654C28.9832 27.8103 28.9618 28.5521 28.7942 29.2346C28.0034 32.4515 24.9051 33.2967 21.9441 33.3747L21.9455 33.371C20.8353 33.3931 19.7328 33.3103 18.7551 33.2102C18.7551 33.2102 14.0399 32.7222 10.0432 29.8005L9.91421 29.7046C9.91421 29.7046 9.91421 29.7046 9.91424 29.7046C9.44772 29.357 9.00266 28.9815 8.5815 28.58C7.46125 27.511 6.46448 26.2984 5.70224 24.9672C5.70735 24.9621 5.71242 24.957 5.71752 24.9519C5.6273 24.7896 5.54079 24.6256 5.45805 24.46C4.72065 22.9843 4.27124 21.3779 4.25089 19.6705C4.21619 16.8055 5.19644 13.8715 7.05972 11.7443C7.05903 11.7425 7.05837 11.7408 7.05771 11.739C8.06656 10.6341 9.32752 9.76603 10.8203 9.27185C11.7561 8.95919 12.7386 8.80907 13.725 8.82801C14.3253 9.5328 15.0558 10.1152 15.8764 10.5433ZM13.5796 29.2887C14.2542 29.0425 14.8932 28.7114 15.4892 28.3034C14.8895 28.7086 14.2495 29.04 13.5796 29.2887Z" fill="url(#paint0_linear_1363_21577)"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M25.663 8.21009C25.6635 8.21009 25.664 8.21009 25.6645 8.21006L25.7052 8.18385C20.4481 -0.78261 13.5742 6.27675 13.5742 6.27675L13.584 6.29403C13.5836 6.29413 13.5833 6.29424 13.5828 6.29434C17.5356 13.2238 25.0479 8.60527 25.663 8.21009Z" fill="url(#paint1_linear_1363_21577)"/>
|
||||
<path d="M19.1464 23.654C17.6978 27.1164 14.9165 29.4091 11.5467 29.7563C11.4743 29.766 10.552 29.8388 10.043 29.8012C14.0397 32.7228 18.7549 33.2108 18.7549 33.2108C19.7644 33.3143 20.9071 33.3991 22.0539 33.3691C22.4578 32.3149 22.6851 31.1079 22.6199 29.7384C22.4685 26.5577 24.313 24.9248 26.3103 24.0871C25.2867 22.5045 24.5227 20.5878 23.9995 18.7935C22.4398 19.2083 20.4591 20.5129 19.1464 23.654Z" fill="url(#paint2_linear_1363_21577)"/>
|
||||
<path d="M22.5582 29.7154C22.6237 31.0849 22.3492 32.3205 21.9453 33.3747C24.9063 33.2968 28.0046 32.4515 28.7954 29.2347C28.963 28.5522 28.9844 27.8104 28.7057 27.1655C28.434 26.5371 27.91 26.0619 27.4451 25.5591C27.0102 25.0787 26.6158 24.5631 26.2659 24.0176C24.2703 24.8556 22.4068 26.5351 22.5582 29.7154Z" fill="url(#paint3_linear_1363_21577)"/>
|
||||
<path d="M23.8964 18.4387C23.4415 17.2213 23.0542 16.0026 22.4654 14.869C22.2686 14.4865 22.0459 14.1178 21.7991 13.7655C21.2038 12.9219 20.5702 12.1005 19.8087 11.4011C18.498 11.4049 17.1284 11.1849 15.8768 10.5427C14.6089 12.3408 13.1582 15.3912 14.4861 18.8729C16.4469 24.0148 12.4677 27.5289 9.91406 29.7047L10.0431 29.8006C10.5219 29.8379 11.0031 29.831 11.4806 29.7799C14.85 29.4322 17.7923 27.0844 19.2409 23.6223C20.554 20.4813 22.4641 19.2881 24.0216 18.8729C23.9777 18.728 23.936 18.5833 23.8964 18.4387Z" fill="url(#paint4_linear_1363_21577)"/>
|
||||
<path d="M7.19672 11.5918C5.24456 13.73 4.21536 16.7368 4.25089 19.6713C4.27124 21.3787 4.72065 22.9851 5.45805 24.4607C5.56866 24.6821 5.68593 24.9005 5.80986 25.116C9.91387 20.9969 8.43113 14.8594 7.19672 11.5918Z" fill="url(#paint5_linear_1363_21577)"/>
|
||||
<path d="M14.5561 18.8728C13.2282 15.3897 14.6465 12.3594 15.9126 10.5616C15.0776 10.1318 14.3348 9.54291 13.7259 8.82801C12.7394 8.80907 11.757 8.95919 10.8211 9.27185C9.32841 9.76603 8.06744 10.6341 7.0586 11.739C8.26576 14.9348 9.71642 20.9386 5.70312 24.9672C6.46536 26.2984 7.46213 27.511 8.58238 28.58C9.02423 29.0012 9.49241 29.3939 9.98407 29.7557C12.5377 27.581 16.5169 24.0147 14.5561 18.8728Z" fill="url(#paint6_linear_1363_21577)"/>
|
||||
<path d="M19.5068 6.84799C22.2857 7.94431 24.232 8.24124 25.643 8.19882L25.6837 8.17261C20.4267 -0.793831 13.5527 6.26552 13.5527 6.26552L13.5627 6.2831C15.0455 6.02032 17.2004 5.93859 19.5068 6.84799Z" fill="url(#paint7_linear_1363_21577)"/>
|
||||
<path d="M19.5405 6.78609C17.2355 5.87807 15.0681 5.91255 13.5605 6.28328C17.5135 13.213 25.0262 8.59387 25.6408 8.199C24.2288 8.24141 22.3194 7.88241 19.5405 6.78609Z" fill="url(#paint8_linear_1363_21577)"/>
|
||||
<path d="M54.748 24.464L62.98 9.4H65.78V29H62.42V16.624L55.476 29H53.796L46.964 16.764V29H43.604V9.4H46.46L54.748 24.464ZM76.7431 14.44C78.8711 14.44 80.5231 15 81.6991 16.12C82.8938 17.2213 83.4911 18.696 83.4911 20.544V29H80.9991L80.4391 27.404H80.2991C79.8324 27.9267 79.1698 28.3933 78.3111 28.804C77.4711 29.196 76.4258 29.392 75.1751 29.392C73.9804 29.392 72.9444 29.196 72.0671 28.804C71.2084 28.412 70.5551 27.8893 70.1071 27.236C69.6591 26.564 69.4351 25.8173 69.4351 24.996C69.4351 23.6333 69.9951 22.532 71.1151 21.692C72.2351 20.8333 73.8404 20.404 75.9311 20.404H80.1871V20.236C80.1871 19.3587 79.8884 18.6587 79.2911 18.136C78.7124 17.6133 77.8724 17.352 76.7711 17.352C75.1471 17.352 74.0551 17.9213 73.4951 19.06H70.1911C70.4898 17.6787 71.2084 16.568 72.3471 15.728C73.4858 14.8693 74.9511 14.44 76.7431 14.44ZM75.7071 26.648C77.1444 26.648 78.2458 26.3493 79.0111 25.752C79.7951 25.136 80.1871 24.3707 80.1871 23.456V22.784H76.0431C74.8858 22.784 74.0364 22.9613 73.4951 23.316C72.9724 23.6707 72.7111 24.1467 72.7111 24.744C72.7111 25.3227 72.9538 25.7893 73.4391 26.144C73.9244 26.48 74.6804 26.648 75.7071 26.648ZM87.4131 29V14.832H89.8771L90.4651 16.4H90.6051C91.0157 15.896 91.6317 15.448 92.4531 15.056C93.2931 14.6453 94.3104 14.44 95.5051 14.44C96.8304 14.44 97.9971 14.72 99.0051 15.28C100.032 15.84 100.825 16.6333 101.385 17.66C101.964 18.668 102.253 19.844 102.253 21.188V29H98.9771V21.692C98.9771 20.4413 98.5944 19.4333 97.8291 18.668C97.0824 17.884 96.0931 17.492 94.8611 17.492C93.6104 17.492 92.6024 17.884 91.8371 18.668C91.0717 19.4333 90.6891 20.4413 90.6891 21.692V29H87.4131ZM113.192 34.32C111.717 34.32 110.457 34.0867 109.412 33.62C108.385 33.172 107.592 32.6027 107.032 31.912C106.49 31.24 106.136 30.5587 105.968 29.868H109.356C109.636 30.3533 110.093 30.7267 110.728 30.988C111.381 31.268 112.202 31.408 113.192 31.408C114.554 31.408 115.628 31.0813 116.412 30.428C117.196 29.7933 117.588 28.8973 117.588 27.74V26.648H117.448C117.298 26.872 117 27.1333 116.552 27.432C116.122 27.7307 115.572 27.992 114.9 28.216C114.228 28.4213 113.49 28.524 112.688 28.524C111.269 28.524 109.99 28.216 108.852 27.6C107.732 26.9653 106.854 26.116 106.22 25.052C105.585 23.9693 105.268 22.7653 105.268 21.44C105.268 20.1333 105.585 18.948 106.22 17.884C106.854 16.82 107.732 15.98 108.852 15.364C109.972 14.748 111.241 14.44 112.66 14.44C113.892 14.44 114.918 14.6453 115.74 15.056C116.561 15.4667 117.205 15.9147 117.672 16.4H117.812L118.4 14.832H120.892V27.656C120.892 29 120.584 30.1667 119.968 31.156C119.352 32.164 118.465 32.9387 117.308 33.48C116.15 34.04 114.778 34.32 113.192 34.32ZM113.08 25.612C113.938 25.612 114.713 25.4347 115.404 25.08C116.094 24.7253 116.626 24.2307 117 23.596C117.392 22.9613 117.588 22.252 117.588 21.468C117.588 20.684 117.392 19.984 117 19.368C116.608 18.7333 116.066 18.2387 115.376 17.884C114.704 17.5293 113.938 17.352 113.08 17.352C111.773 17.352 110.69 17.744 109.832 18.528C108.992 19.2933 108.572 20.2733 108.572 21.468C108.572 22.252 108.758 22.9613 109.132 23.596C109.524 24.2307 110.065 24.7253 110.756 25.08C111.446 25.4347 112.221 25.612 113.08 25.612ZM132.111 29.392C130.599 29.392 129.227 29.0653 127.995 28.412C126.763 27.74 125.792 26.8347 125.083 25.696C124.374 24.5573 124.019 23.2973 124.019 21.916C124.019 20.5347 124.374 19.2747 125.083 18.136C125.792 16.9973 126.763 16.1013 127.995 15.448C129.227 14.776 130.599 14.44 132.111 14.44C133.623 14.44 134.995 14.776 136.227 15.448C137.459 16.1013 138.43 16.9973 139.139 18.136C139.848 19.2747 140.203 20.5347 140.203 21.916C140.203 23.2973 139.848 24.5573 139.139 25.696C138.43 26.8347 137.459 27.74 136.227 28.412C134.995 29.0653 133.623 29.392 132.111 29.392ZM132.111 26.396C133.026 26.396 133.847 26.2093 134.575 25.836C135.322 25.444 135.9 24.912 136.311 24.24C136.722 23.5493 136.927 22.7747 136.927 21.916C136.927 21.0573 136.722 20.292 136.311 19.62C135.9 18.9293 135.322 18.3973 134.575 18.024C133.847 17.632 133.026 17.436 132.111 17.436C131.196 17.436 130.375 17.632 129.647 18.024C128.919 18.3973 128.35 18.9293 127.939 19.62C127.528 20.292 127.323 21.0573 127.323 21.916C127.323 22.7747 127.528 23.5493 127.939 24.24C128.35 24.912 128.919 25.444 129.647 25.836C130.375 26.2093 131.196 26.396 132.111 26.396Z" fill="#E5E3EC"/>
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear_1363_21577" x1="1.17504" y1="13.0336" x2="33.318" y2="32.2975" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#E54033"/>
|
||||
<stop offset="0.489583" stop-color="#FECA1A"/>
|
||||
<stop offset="1" stop-color="#AFD803"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint1_linear_1363_21577" x1="9096.98" y1="1078.01" x2="7084.85" y2="-991.996" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0.15" stop-color="#6CBF00"/>
|
||||
<stop offset="1" stop-color="#AFD803"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint2_linear_1363_21577" x1="6.72534" y1="30.0439" x2="26.8674" y2="25.1458" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0.21" stop-color="#E54033"/>
|
||||
<stop offset="0.84" stop-color="#FECA1A"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint3_linear_1363_21577" x1="22.5961" y1="28.685" x2="28.8113" y2="28.7315" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#FECA1A"/>
|
||||
<stop offset="0.4" stop-color="#FECA1A"/>
|
||||
<stop offset="1" stop-color="#AFD803"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint4_linear_1363_21577" x1="8.52652" y1="30.1689" x2="21.267" y2="12.9184" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0.16" stop-color="#E54033"/>
|
||||
<stop offset="0.84" stop-color="#FECA1A"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint5_linear_1363_21577" x1="6.67108" y1="13.0306" x2="6.10695" y2="24.1717" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#FECA1A"/>
|
||||
<stop offset="0.76" stop-color="#E54033"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint6_linear_1363_21577" x1="12.9054" y1="10.1368" x2="9.50298" y2="23.0579" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0.16" stop-color="#FECA1A"/>
|
||||
<stop offset="1" stop-color="#E54033"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint7_linear_1363_21577" x1="14.2229" y1="3.95079" x2="26.8229" y2="8.59568" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0.15" stop-color="#6CBF00"/>
|
||||
<stop offset="1" stop-color="#AFD803"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint8_linear_1363_21577" x1="9096.95" y1="1078" x2="7084.82" y2="-992.007" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0.15" stop-color="#6CBF00"/>
|
||||
<stop offset="1" stop-color="#AFD803"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 11 KiB |
|
@ -748,8 +748,7 @@ const mangoStore = create<MangoStore>()(
|
|||
fetchPerpStats: async () => {
|
||||
const set = get().set
|
||||
const group = get().group
|
||||
const stats = get().perpStats.data
|
||||
if ((stats && stats.length) || !group) return
|
||||
if (!group) return []
|
||||
set((state) => {
|
||||
state.perpStats.loading = true
|
||||
})
|
||||
|
|
|
@ -15,10 +15,7 @@ module.exports = {
|
|||
'spin-fast': 'spin 0.5s linear infinite',
|
||||
},
|
||||
backgroundImage: {
|
||||
'long-loss': "url('/share_images/bg-long-loss.png')",
|
||||
'long-profit': "url('/share_images/bg-long-profit.png')",
|
||||
'short-loss': "url('/share_images/bg-short-loss.png')",
|
||||
'short-profit': "url('/share_images/bg-short-profit.png')",
|
||||
'share-position': "url('/images/share-image.png')",
|
||||
},
|
||||
boxShadow: {
|
||||
bottomBar: '0px -4px 8px -1px rgba(0,0,0,0.2)',
|
||||
|
|
104
yarn.lock
104
yarn.lock
|
@ -14,10 +14,10 @@
|
|||
dependencies:
|
||||
regenerator-runtime "^0.13.11"
|
||||
|
||||
"@blockworks-foundation/mango-v4@^0.9.14":
|
||||
version "0.9.14"
|
||||
resolved "https://registry.yarnpkg.com/@blockworks-foundation/mango-v4/-/mango-v4-0.9.14.tgz#e46f890d3321e5ea9b1f7cb84713e64b68d8af45"
|
||||
integrity sha512-g0Bv5q5znOPk9GTI3cKsXLxWF+lNF/sn1xLg0RNDwyuVCejM0eqJ2X6hfFIBRGVSolScvG+1w5BuEO8sBcD+Hg==
|
||||
"@blockworks-foundation/mango-v4@^0.9.15":
|
||||
version "0.9.16"
|
||||
resolved "https://registry.yarnpkg.com/@blockworks-foundation/mango-v4/-/mango-v4-0.9.16.tgz#9a3e70c95e46f112e7a204cd80d42a1c26e7d484"
|
||||
integrity sha512-tyGtLiVQeWwxggSnkv1tqT3akeIpsiFtAcNuXPiJKfm/zwgPhLLOAsFbl0cr9IGqtV7uY/+CmKSqL2dHJD2czg==
|
||||
dependencies:
|
||||
"@coral-xyz/anchor" "^0.26.0"
|
||||
"@project-serum/serum" "0.13.65"
|
||||
|
@ -638,27 +638,27 @@
|
|||
resolved "https://registry.yarnpkg.com/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz#96116f2a912e0c02817345b3c10751069920d553"
|
||||
integrity sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==
|
||||
|
||||
"@solana-mobile/mobile-wallet-adapter-protocol-web3js@^0.9.9":
|
||||
version "0.9.9"
|
||||
resolved "https://registry.yarnpkg.com/@solana-mobile/mobile-wallet-adapter-protocol-web3js/-/mobile-wallet-adapter-protocol-web3js-0.9.9.tgz#ef4040abef66e4c080ebf2a0db109f31ef95652d"
|
||||
integrity sha512-JzlNjZ/Uog56iP/z8QtNrIOgQwmaoicpr9768s0QVF4xuvNbyWHOaDtsngzNneNTMfLSgd0tueboKUrkvto/Wg==
|
||||
"@solana-mobile/mobile-wallet-adapter-protocol-web3js@^2.0.0":
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@solana-mobile/mobile-wallet-adapter-protocol-web3js/-/mobile-wallet-adapter-protocol-web3js-2.0.0.tgz#5433705c174f59a177280f85396df051711be09d"
|
||||
integrity sha512-cMADp/UIAN42QJVCM1oyj1wFM/9DTZNIa5z5eHXUXBksw/bNv2fWkiO+4ZUoQj1P4UoMoZJUBx9+qMVl18sPOA==
|
||||
dependencies:
|
||||
"@solana-mobile/mobile-wallet-adapter-protocol" "^0.9.9"
|
||||
"@solana-mobile/mobile-wallet-adapter-protocol" "^2.0.0"
|
||||
bs58 "^5.0.0"
|
||||
js-base64 "^3.7.2"
|
||||
|
||||
"@solana-mobile/mobile-wallet-adapter-protocol@^0.9.9":
|
||||
version "0.9.9"
|
||||
resolved "https://registry.yarnpkg.com/@solana-mobile/mobile-wallet-adapter-protocol/-/mobile-wallet-adapter-protocol-0.9.9.tgz#8b8e3f94f609e0e8c1149c0dbf1548adf18bfd4b"
|
||||
integrity sha512-Jxd3O3txeUiAXLIo6YfWhTs7UTVMlnIgz/xgdYmf99TSE4IaUhWGEVC2/OcOA7eAA85y0/XItU5OhHhXSPva8g==
|
||||
"@solana-mobile/mobile-wallet-adapter-protocol@^2.0.0":
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@solana-mobile/mobile-wallet-adapter-protocol/-/mobile-wallet-adapter-protocol-2.0.0.tgz#75a3e8163544f659803260cb1dd7aede6da96b36"
|
||||
integrity sha512-mLK9B/AQgOxzbdRoOMH3G5wB5akWgGSBoVqIZ/6iDWY37uu/CuyX4lTwRyoRlOb8Cxs/tDwiovIGobkti2qF/w==
|
||||
|
||||
"@solana-mobile/wallet-adapter-mobile@^0.9.9":
|
||||
version "0.9.9"
|
||||
resolved "https://registry.yarnpkg.com/@solana-mobile/wallet-adapter-mobile/-/wallet-adapter-mobile-0.9.9.tgz#5d65a1983a422ad56ff95fe9efaedef4c87d6436"
|
||||
integrity sha512-nmxTEbKgkuI37zMpI3GWWn6DvAd/lgl6GF1lGbYSObXyZDun0bfCIQ8rBVEcvwZLyekp+i/nLW8JdSccN4i3zw==
|
||||
"@solana-mobile/wallet-adapter-mobile@^2.0.0":
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@solana-mobile/wallet-adapter-mobile/-/wallet-adapter-mobile-2.0.0.tgz#4429dec675e5a3339b7734521dd386d94bf3ad71"
|
||||
integrity sha512-q/m0X+LUhoSYBUaQsw+9YhttbokA5+klrC2euLhbDu+Wy/n9hL4NXNvw7291bzVvNXVh9ovBi7DjoCdcfPXRWA==
|
||||
dependencies:
|
||||
"@react-native-async-storage/async-storage" "^1.17.7"
|
||||
"@solana-mobile/mobile-wallet-adapter-protocol-web3js" "^0.9.9"
|
||||
"@solana-mobile/mobile-wallet-adapter-protocol-web3js" "^2.0.0"
|
||||
"@solana/wallet-adapter-base" "^0.9.17"
|
||||
js-base64 "^3.7.2"
|
||||
|
||||
|
@ -741,7 +741,7 @@
|
|||
dependencies:
|
||||
eventemitter3 "^4.0.0"
|
||||
|
||||
"@solana/wallet-adapter-base@^0.9.17", "@solana/wallet-adapter-base@^0.9.20", "@solana/wallet-adapter-base@^0.9.21", "@solana/wallet-adapter-base@^0.9.22":
|
||||
"@solana/wallet-adapter-base@^0.9.17", "@solana/wallet-adapter-base@^0.9.21", "@solana/wallet-adapter-base@^0.9.22":
|
||||
version "0.9.22"
|
||||
resolved "https://registry.yarnpkg.com/@solana/wallet-adapter-base/-/wallet-adapter-base-0.9.22.tgz#97812eaf6aebe01e5fe714326b3c9a0614ae6112"
|
||||
integrity sha512-xbLEZPGSJFvgTeldG9D55evhl7QK/3e/F7vhvcA97mEt1eieTgeKMnGlmmjs3yivI3/gtZNZeSk1XZLnhKcQvw==
|
||||
|
@ -936,14 +936,14 @@
|
|||
dependencies:
|
||||
"@solana/wallet-adapter-base" "^0.9.22"
|
||||
|
||||
"@solana/wallet-adapter-react@0.15.28":
|
||||
version "0.15.28"
|
||||
resolved "https://registry.yarnpkg.com/@solana/wallet-adapter-react/-/wallet-adapter-react-0.15.28.tgz#0818cdbe295db901fa17cb11133c42b4124fa298"
|
||||
integrity sha512-1QG8Mk1LYt4e+JwmpdBifiJzYJG80T4LageOU/7X+trpjbhxMbn+6ceWjkupa0MvHnUxpZBpHYwvHUbWbZlQ9w==
|
||||
"@solana/wallet-adapter-react@0.15.32":
|
||||
version "0.15.32"
|
||||
resolved "https://registry.yarnpkg.com/@solana/wallet-adapter-react/-/wallet-adapter-react-0.15.32.tgz#3e8a949dbf183460d54fee707374f22799199c01"
|
||||
integrity sha512-dnbMVQeO2WBvK13M4kiUo1TBONJpfpO1r9JA5FuXG/Zwdt4RbGT+h6HSOaplHPO6pzDVk2nT/bU8wjqI9GxTYQ==
|
||||
dependencies:
|
||||
"@solana-mobile/wallet-adapter-mobile" "^0.9.9"
|
||||
"@solana/wallet-adapter-base" "^0.9.20"
|
||||
"@solana/wallet-standard-wallet-adapter-react" "^1.0.0"
|
||||
"@solana-mobile/wallet-adapter-mobile" "^2.0.0"
|
||||
"@solana/wallet-adapter-base" "^0.9.22"
|
||||
"@solana/wallet-standard-wallet-adapter-react" "^1.0.1"
|
||||
|
||||
"@solana/wallet-adapter-safepal@^0.5.15":
|
||||
version "0.5.17"
|
||||
|
@ -1149,10 +1149,10 @@
|
|||
"@solana/wallet-standard-chains" "^1.0.0"
|
||||
"@solana/wallet-standard-features" "^1.0.0"
|
||||
|
||||
"@solana/wallet-standard-wallet-adapter-base@^1.0.1":
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@solana/wallet-standard-wallet-adapter-base/-/wallet-standard-wallet-adapter-base-1.0.1.tgz#4f44d1041856460ca9bb8b3aaaec0855e98d0bf2"
|
||||
integrity sha512-no3NwFIfWN653g1I2i8bbfwMjASzBSau9De8tQgoE+CPyQXJxNYyb2B5uw6SsJImMCES7fT2k4J0mM2OlUmreQ==
|
||||
"@solana/wallet-standard-wallet-adapter-base@^1.0.2":
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@solana/wallet-standard-wallet-adapter-base/-/wallet-standard-wallet-adapter-base-1.0.2.tgz#d6028c27381fe384a34a7426b3eb828a1da6bff0"
|
||||
integrity sha512-QqkupdWvWuihX87W6ijt174u6ZdP5OSFlNhZhuhoMlIdyI/sj7MhGsdppuRlMh65oVO2WNWTL9y2bO5Pbx+dfg==
|
||||
dependencies:
|
||||
"@solana/wallet-adapter-base" "^0.9.21"
|
||||
"@solana/wallet-standard-chains" "^1.0.0"
|
||||
|
@ -1163,12 +1163,12 @@
|
|||
"@wallet-standard/features" "^1.0.3"
|
||||
"@wallet-standard/wallet" "^1.0.1"
|
||||
|
||||
"@solana/wallet-standard-wallet-adapter-react@^1.0.0":
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@solana/wallet-standard-wallet-adapter-react/-/wallet-standard-wallet-adapter-react-1.0.1.tgz#fb391834f81e040619b4a23f4d1e31a7b818bbc9"
|
||||
integrity sha512-sqYufApzZDFjyXtu5Yq7HQR8HzY5l9WuTZByfQxDOF62oMP2wx8sE0AGuAlisggJhGpMzNDsEek9VqED81eDzg==
|
||||
"@solana/wallet-standard-wallet-adapter-react@^1.0.1":
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@solana/wallet-standard-wallet-adapter-react/-/wallet-standard-wallet-adapter-react-1.0.2.tgz#8359900de37b05f921eb2318162a4dc179ce9864"
|
||||
integrity sha512-0YTPUnjiSG5ajDP2hK8EipxkeHhO3+nCtXeF1eS/ZP2QcFAgS/4luywrn/6CdfzQ2cQYPCFdnG/QculpUp6bBg==
|
||||
dependencies:
|
||||
"@solana/wallet-standard-wallet-adapter-base" "^1.0.1"
|
||||
"@solana/wallet-standard-wallet-adapter-base" "^1.0.2"
|
||||
"@wallet-standard/app" "^1.0.1"
|
||||
"@wallet-standard/base" "^1.0.1"
|
||||
|
||||
|
@ -2470,6 +2470,11 @@ base-x@^4.0.0:
|
|||
resolved "https://registry.yarnpkg.com/base-x/-/base-x-4.0.0.tgz#d0e3b7753450c73f8ad2389b5c018a4af7b2224a"
|
||||
integrity sha512-FuwxlW4H5kh37X/oW59pwTzzTKRzfrrQwhmyspRM7swOEZcHtDZSCt45U6oKgtuFE+WYPblePMVIPR4RZrh/hw==
|
||||
|
||||
base64-arraybuffer@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz#1c37589a7c4b0746e34bd1feb951da2df01c1bdc"
|
||||
integrity sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==
|
||||
|
||||
base64-js@^1.3.1, base64-js@^1.5.1:
|
||||
version "1.5.1"
|
||||
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
|
||||
|
@ -3079,6 +3084,13 @@ crypto-js@^4.1.1:
|
|||
resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-4.1.1.tgz#9e485bcf03521041bd85844786b83fb7619736cf"
|
||||
integrity sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw==
|
||||
|
||||
css-line-break@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/css-line-break/-/css-line-break-2.1.0.tgz#bfef660dfa6f5397ea54116bb3cb4873edbc4fa0"
|
||||
integrity sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==
|
||||
dependencies:
|
||||
utrie "^1.0.2"
|
||||
|
||||
css-unit-converter@^1.1.1:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/css-unit-converter/-/css-unit-converter-1.1.2.tgz#4c77f5a1954e6dbff60695ecb214e3270436ab21"
|
||||
|
@ -4424,6 +4436,14 @@ html-react-parser@3.0.4:
|
|||
react-property "2.0.0"
|
||||
style-to-js "1.1.1"
|
||||
|
||||
html2canvas@1.4.1:
|
||||
version "1.4.1"
|
||||
resolved "https://registry.yarnpkg.com/html2canvas/-/html2canvas-1.4.1.tgz#7cef1888311b5011d507794a066041b14669a543"
|
||||
integrity sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==
|
||||
dependencies:
|
||||
css-line-break "^2.1.0"
|
||||
text-segmentation "^1.0.3"
|
||||
|
||||
htmlparser2@8.0.1:
|
||||
version "8.0.1"
|
||||
resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-8.0.1.tgz#abaa985474fcefe269bc761a779b544d7196d010"
|
||||
|
@ -6753,6 +6773,13 @@ text-encoding-utf-8@^1.0.2:
|
|||
resolved "https://registry.yarnpkg.com/text-encoding-utf-8/-/text-encoding-utf-8-1.0.2.tgz#585b62197b0ae437e3c7b5d0af27ac1021e10d13"
|
||||
integrity sha512-8bw4MY9WjdsD2aMtO0OzOCY3pXGYNx2d2FfHRVUKkiCPDWjKuOlhLVASS+pD7VkLTVjW268LYJHwsnPFlBpbAg==
|
||||
|
||||
text-segmentation@^1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/text-segmentation/-/text-segmentation-1.0.3.tgz#52a388159efffe746b24a63ba311b6ac9f2d7943"
|
||||
integrity sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==
|
||||
dependencies:
|
||||
utrie "^1.0.2"
|
||||
|
||||
text-table@^0.2.0:
|
||||
version "0.2.0"
|
||||
resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
|
||||
|
@ -7308,6 +7335,13 @@ util@^0.12.0:
|
|||
is-typed-array "^1.1.3"
|
||||
which-typed-array "^1.1.2"
|
||||
|
||||
utrie@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/utrie/-/utrie-1.0.2.tgz#d42fe44de9bc0119c25de7f564a6ed1b2c87a645"
|
||||
integrity sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==
|
||||
dependencies:
|
||||
base64-arraybuffer "^1.0.2"
|
||||
|
||||
uuid@^3.3.2:
|
||||
version "3.4.0"
|
||||
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee"
|
||||
|
|
Loading…
Reference in New Issue