merge main
This commit is contained in:
commit
066fd9b364
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/env sh
|
||||
. "$(dirname -- "$0")/_/husky.sh"
|
||||
|
||||
yarn format && yarn typecheck && yarn lint --quiet
|
||||
yarn typecheck && yarn lint --quiet && yarn format
|
||||
|
|
|
@ -53,26 +53,16 @@ const HydrateStore = () => {
|
|||
// watch selected Mango Account for changes
|
||||
useEffect(() => {
|
||||
const client = mangoStore.getState().client
|
||||
|
||||
if (!mangoAccountPk) return
|
||||
|
||||
const subscriptionId = connection.onAccountChange(
|
||||
mangoAccountPk,
|
||||
async (info, context) => {
|
||||
if (info?.lamports === 0) return
|
||||
|
||||
const lastSeenSlot = mangoStore.getState().mangoAccount.lastSlot
|
||||
// const mangoAccountLastUpdated = new Date(
|
||||
// mangoStore.getState().mangoAccount.lastUpdatedAt
|
||||
// )
|
||||
const mangoAccount = mangoStore.getState().mangoAccount.current
|
||||
if (!mangoAccount) return
|
||||
// const newUpdatedAt = new Date()
|
||||
// const timeDiff =
|
||||
// mangoAccountLastUpdated.getTime() - newUpdatedAt.getTime()
|
||||
|
||||
// only updated mango account if it's been more than 1 second since last update
|
||||
// if (Math.abs(timeDiff) >= 500 && context.slot > lastSeenSlot) {
|
||||
if (context.slot > lastSeenSlot) {
|
||||
const decodedMangoAccount = client.program.coder.accounts.decode(
|
||||
'mangoAccount',
|
||||
|
@ -83,10 +73,8 @@ const HydrateStore = () => {
|
|||
decodedMangoAccount
|
||||
)
|
||||
await newMangoAccount.reloadSerum3OpenOrders(client)
|
||||
actions.fetchOpenOrders()
|
||||
// newMangoAccount.spotOpenOrdersAccounts =
|
||||
// mangoAccount.spotOpenOrdersAccounts
|
||||
// newMangoAccount.advancedOrders = mangoAccount.advancedOrders
|
||||
actions.fetchOpenOrders(newMangoAccount)
|
||||
|
||||
set((s) => {
|
||||
s.mangoAccount.current = newMangoAccount
|
||||
s.mangoAccount.lastSlot = context.slot
|
||||
|
|
|
@ -34,6 +34,7 @@ import BankAmountWithValue from './shared/BankAmountWithValue'
|
|||
import useBanksWithBalances, {
|
||||
BankWithBalance,
|
||||
} from 'hooks/useBanksWithBalances'
|
||||
import useUnownedAccount from 'hooks/useUnownedAccount'
|
||||
|
||||
const TokenList = () => {
|
||||
const { t } = useTranslation(['common', 'token', 'trade'])
|
||||
|
@ -399,7 +400,7 @@ const ActionsMenu = ({
|
|||
const router = useRouter()
|
||||
const { mangoTokens } = useJupiterMints()
|
||||
const spotMarkets = mangoStore((s) => s.serumMarkets)
|
||||
const { connected } = useWallet()
|
||||
const isUnownedAccount = useUnownedAccount()
|
||||
|
||||
const spotMarket = useMemo(() => {
|
||||
return spotMarkets.find((m) => {
|
||||
|
@ -477,7 +478,7 @@ const ActionsMenu = ({
|
|||
|
||||
return (
|
||||
<>
|
||||
{mangoAccount && !connected ? null : (
|
||||
{isUnownedAccount ? null : (
|
||||
<IconDropMenu
|
||||
icon={<EllipsisHorizontalIcon className="h-5 w-5" />}
|
||||
postion="leftBottom"
|
||||
|
|
|
@ -24,6 +24,7 @@ import DepositWithdrawModal from './modals/DepositWithdrawModal'
|
|||
import { useViewport } from 'hooks/useViewport'
|
||||
import { breakpoints } from 'utils/theme'
|
||||
import AccountsButton from './AccountsButton'
|
||||
import useUnownedAccount from 'hooks/useUnownedAccount'
|
||||
// import ThemeSwitcher from './ThemeSwitcher'
|
||||
|
||||
const TopBar = () => {
|
||||
|
@ -41,6 +42,7 @@ const TopBar = () => {
|
|||
const { query } = router
|
||||
const { width } = useViewport()
|
||||
const isMobile = width ? width < breakpoints.sm : false
|
||||
const isUnownedAccount = useUnownedAccount()
|
||||
|
||||
const handleCloseSetup = useCallback(() => {
|
||||
setShowUserSetup(false)
|
||||
|
@ -77,7 +79,7 @@ const TopBar = () => {
|
|||
</div>
|
||||
) : null}
|
||||
<img
|
||||
className="mr-4 ml-2 h-8 w-auto md:hidden"
|
||||
className="mr-4 h-8 w-auto md:hidden"
|
||||
src="/logos/logo-mark.svg"
|
||||
alt="next"
|
||||
/>
|
||||
|
@ -112,7 +114,7 @@ const TopBar = () => {
|
|||
{/* <div className="px-3 md:px-4">
|
||||
<ThemeSwitcher />
|
||||
</div> */}
|
||||
{(mangoAccount && !connected) || (!connected && isMobile) ? null : (
|
||||
{isUnownedAccount || (!connected && isMobile) ? null : (
|
||||
<Button
|
||||
onClick={() => handleDepositWithdrawModal('deposit')}
|
||||
secondary
|
||||
|
|
|
@ -23,6 +23,7 @@ import { useWallet } from '@solana/wallet-adapter-react'
|
|||
import CreateAccountModal from '@components/modals/CreateAccountModal'
|
||||
import { Popover, Transition } from '@headlessui/react'
|
||||
import ActionsLinkButton from './ActionsLinkButton'
|
||||
import useUnownedAccount from 'hooks/useUnownedAccount'
|
||||
|
||||
export const handleCopyAddress = (
|
||||
mangoAccount: MangoAccount,
|
||||
|
@ -37,7 +38,7 @@ export const handleCopyAddress = (
|
|||
|
||||
const AccountActions = () => {
|
||||
const { t } = useTranslation(['common', 'close-account'])
|
||||
const { mangoAccount } = useMangoAccount()
|
||||
const { mangoAccount, mangoAccountAddress } = useMangoAccount()
|
||||
const [showCloseAccountModal, setShowCloseAccountModal] = useState(false)
|
||||
const [showEditAccountModal, setShowEditAccountModal] = useState(false)
|
||||
const [showBorrowModal, setShowBorrowModal] = useState(false)
|
||||
|
@ -45,9 +46,10 @@ const AccountActions = () => {
|
|||
const [showDelegateModal, setShowDelegateModal] = useState(false)
|
||||
const [showCreateAccountModal, setShowCreateAccountModal] = useState(false)
|
||||
const { connected } = useWallet()
|
||||
const isUnownedAccount = useUnownedAccount()
|
||||
|
||||
const handleBorrowModal = () => {
|
||||
if (!connected || mangoAccount) {
|
||||
if (mangoAccountAddress || !connected) {
|
||||
setShowBorrowModal(true)
|
||||
} else {
|
||||
setShowCreateAccountModal(true)
|
||||
|
@ -56,11 +58,11 @@ const AccountActions = () => {
|
|||
|
||||
return (
|
||||
<>
|
||||
{mangoAccount && !connected ? null : (
|
||||
{isUnownedAccount ? null : (
|
||||
<div className="flex items-center space-x-2">
|
||||
<Button
|
||||
className="flex w-1/3 items-center justify-center md:w-auto"
|
||||
disabled={!mangoAccount}
|
||||
disabled={!mangoAccountAddress}
|
||||
onClick={() => setShowRepayModal(true)}
|
||||
secondary
|
||||
>
|
||||
|
|
|
@ -16,7 +16,11 @@ const SimpleAreaChart = dynamic(
|
|||
import { COLORS } from '../../styles/colors'
|
||||
import { useTheme } from 'next-themes'
|
||||
import { IconButton } from '../shared/Button'
|
||||
import { ArrowsPointingOutIcon, ChartBarIcon } from '@heroicons/react/20/solid'
|
||||
import {
|
||||
ArrowsPointingOutIcon,
|
||||
CalendarIcon,
|
||||
ChartBarIcon,
|
||||
} from '@heroicons/react/20/solid'
|
||||
import { Transition } from '@headlessui/react'
|
||||
import AccountTabs from './AccountTabs'
|
||||
import SheenLoader from '../shared/SheenLoader'
|
||||
|
@ -28,7 +32,7 @@ import {
|
|||
ANIMATION_SETTINGS_KEY,
|
||||
// IS_ONBOARDED_KEY
|
||||
} from 'utils/constants'
|
||||
// import { useWallet } from '@solana/wallet-adapter-react'
|
||||
import { useWallet } from '@solana/wallet-adapter-react'
|
||||
import useLocalStorageState from 'hooks/useLocalStorageState'
|
||||
// import AccountOnboardingTour from '@components/tours/AccountOnboardingTour'
|
||||
import dayjs from 'dayjs'
|
||||
|
@ -42,7 +46,7 @@ import HealthBar from './HealthBar'
|
|||
|
||||
const AccountPage = () => {
|
||||
const { t } = useTranslation(['common', 'account'])
|
||||
// const { connected } = useWallet()
|
||||
const { connected } = useWallet()
|
||||
const { group } = useMangoGroup()
|
||||
const { mangoAccount, mangoAccountAddress } = useMangoAccount()
|
||||
const actions = mangoStore.getState().actions
|
||||
|
@ -69,8 +73,7 @@ const AccountPage = () => {
|
|||
)
|
||||
|
||||
useEffect(() => {
|
||||
if (mangoAccountAddress) {
|
||||
console.log('fired')
|
||||
if (mangoAccountAddress || (!mangoAccountAddress && connected)) {
|
||||
actions.fetchAccountPerformance(mangoAccountAddress, 31)
|
||||
actions.fetchAccountInterestTotals(mangoAccountAddress)
|
||||
}
|
||||
|
@ -442,7 +445,11 @@ const AccountPage = () => {
|
|||
{mangoAccountAddress ? (
|
||||
<div className="flex items-center space-x-3">
|
||||
{performanceData.length > 4 ? (
|
||||
<Tooltip content={t('account:pnl-chart')} delay={250}>
|
||||
<Tooltip
|
||||
className="hidden md:block"
|
||||
content={t('account:pnl-chart')}
|
||||
delay={250}
|
||||
>
|
||||
<IconButton
|
||||
className="text-th-fgd-3"
|
||||
hideBg
|
||||
|
@ -452,15 +459,19 @@ const AccountPage = () => {
|
|||
</IconButton>
|
||||
</Tooltip>
|
||||
) : null}
|
||||
{/* <Tooltip content={t('account:pnl-history')} delay={250}>
|
||||
<Tooltip
|
||||
className="hidden md:block"
|
||||
content={t('account:pnl-history')}
|
||||
delay={250}
|
||||
>
|
||||
<IconButton
|
||||
className="text-th-fgd-3"
|
||||
hideBg
|
||||
onClick={() => setShowPnlHistory(true)}
|
||||
>
|
||||
<ClockIcon className="h-5 w-5" />
|
||||
<CalendarIcon className="h-5 w-5" />
|
||||
</IconButton>
|
||||
</Tooltip> */}
|
||||
</Tooltip>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
|
@ -491,7 +502,11 @@ const AccountPage = () => {
|
|||
</p>
|
||||
</Tooltip>
|
||||
{interestTotalValue > 1 || interestTotalValue < -1 ? (
|
||||
<Tooltip content="Cumulative Interest Chart" delay={250}>
|
||||
<Tooltip
|
||||
className="hidden md:block"
|
||||
content="Cumulative Interest Chart"
|
||||
delay={250}
|
||||
>
|
||||
<IconButton
|
||||
className="text-th-fgd-3"
|
||||
hideBg
|
||||
|
|
|
@ -124,7 +124,10 @@ const ActivityFilters = () => {
|
|||
<Disclosure>
|
||||
<div className="flex items-center">
|
||||
{hasFilters ? (
|
||||
<Tooltip content={t('activity:reset-filters')}>
|
||||
<Tooltip
|
||||
className="hidden md:block"
|
||||
content={t('activity:reset-filters')}
|
||||
>
|
||||
<IconButton
|
||||
className={`${loadActivityFeed ? 'animate-spin' : ''}`}
|
||||
onClick={() => handleResetFilters()}
|
||||
|
|
|
@ -201,7 +201,6 @@ const YourBorrowsTable = ({ banks }: { banks: BankWithBalance[] }) => {
|
|||
</p>
|
||||
</div>
|
||||
<div className="flex space-x-2">
|
||||
<Tooltip content={`${t('repay')} ${bank.name}`}>
|
||||
<IconButton
|
||||
onClick={() =>
|
||||
handleShowActionModals(bank.name, 'repay')
|
||||
|
@ -210,8 +209,6 @@ const YourBorrowsTable = ({ banks }: { banks: BankWithBalance[] }) => {
|
|||
>
|
||||
<ArrowDownRightIcon className="h-5 w-5" />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
<Tooltip content={`${t('borrow')} ${bank.name}`}>
|
||||
<IconButton
|
||||
disabled={available.eq(0)}
|
||||
onClick={() =>
|
||||
|
@ -221,7 +218,6 @@ const YourBorrowsTable = ({ banks }: { banks: BankWithBalance[] }) => {
|
|||
>
|
||||
<ArrowUpLeftIcon className="h-5 w-5" />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -75,7 +75,7 @@ const CloseAccountModal = ({ isOpen, onClose }: ModalProps) => {
|
|||
}
|
||||
|
||||
const fetchTotalAccountSOL = useCallback(async () => {
|
||||
if (!mangoAccount) {
|
||||
if (!mangoAccount?.current) {
|
||||
return
|
||||
}
|
||||
const accountKeys = [
|
||||
|
|
|
@ -193,7 +193,11 @@ const MangoAccountsListModal = ({
|
|||
</div>
|
||||
</button>
|
||||
<div className="flex h-full items-center justify-center rounded-md rounded-l-none bg-th-bkg-3">
|
||||
<Tooltip content={t('copy-address')} delay={250}>
|
||||
<Tooltip
|
||||
className="hidden md:block"
|
||||
content={t('copy-address')}
|
||||
delay={250}
|
||||
>
|
||||
<IconButton
|
||||
className="text-th-fgd-3"
|
||||
onClick={() =>
|
||||
|
|
|
@ -33,7 +33,7 @@ const PnlHistoryModal = ({
|
|||
|
||||
useEffect(() => {
|
||||
if (mangoAccountAddress) {
|
||||
actions.fetchAccountPerformance(mangoAccountAddress, 30)
|
||||
actions.fetchAccountPerformance(mangoAccountAddress, 31)
|
||||
}
|
||||
}, [actions, mangoAccountAddress])
|
||||
|
||||
|
@ -41,8 +41,10 @@ const PnlHistoryModal = ({
|
|||
if (!performanceData.length) return []
|
||||
|
||||
const dailyPnl = performanceData.filter((d: PerformanceDataItem) => {
|
||||
const date = new Date(d.time)
|
||||
return date.getHours() === 0
|
||||
const startTime = new Date().getTime() - 30 * 86400000
|
||||
const dataDate = new Date(d.time)
|
||||
const dataTime = dataDate.getTime()
|
||||
return dataTime >= startTime && dataDate.getHours() === 0
|
||||
})
|
||||
|
||||
return dailyPnl.length
|
||||
|
|
|
@ -107,7 +107,7 @@ const DisplaySettings = () => {
|
|||
/>
|
||||
</div>
|
||||
</div> */}
|
||||
<div className="flex flex-col border-t border-th-bkg-3 py-4 md:flex-row md:items-center md:justify-between md:px-4">
|
||||
<div className="hidden border-t border-th-bkg-3 py-4 md:flex md:flex-row md:items-center md:justify-between md:px-4">
|
||||
<p className="mb-2 md:mb-0">{t('settings:notification-position')}</p>
|
||||
<div className="w-full min-w-[140px] md:w-auto">
|
||||
<Select
|
||||
|
|
|
@ -20,12 +20,12 @@ import { Table, Td, Th, TrBody, TrHead } from './TableElements'
|
|||
import useSelectedMarket from 'hooks/useSelectedMarket'
|
||||
import ConnectEmptyState from './ConnectEmptyState'
|
||||
import { useWallet } from '@solana/wallet-adapter-react'
|
||||
import Decimal from 'decimal.js'
|
||||
import FormatNumericValue from './FormatNumericValue'
|
||||
import BankAmountWithValue from './BankAmountWithValue'
|
||||
import useBanksWithBalances, {
|
||||
BankWithBalance,
|
||||
} from 'hooks/useBanksWithBalances'
|
||||
import useUnownedAccount from 'hooks/useUnownedAccount'
|
||||
|
||||
const BalancesTable = () => {
|
||||
const { t } = useTranslation(['common', 'trade'])
|
||||
|
@ -195,6 +195,7 @@ export default BalancesTable
|
|||
const Balance = ({ bank }: { bank: BankWithBalance }) => {
|
||||
const { selectedMarket } = useSelectedMarket()
|
||||
const { asPath } = useRouter()
|
||||
const isUnownedAccount = useUnownedAccount()
|
||||
|
||||
const tokenBank = bank.bank
|
||||
|
||||
|
@ -288,12 +289,12 @@ const Balance = ({ bank }: { bank: BankWithBalance }) => {
|
|||
}
|
||||
}, [tokenBank, selectedMarket])
|
||||
|
||||
console.log(tokenBank.name, ' balance', new Decimal(balance).toFixed())
|
||||
if (!balance) return <p className="flex justify-end">0</p>
|
||||
|
||||
return (
|
||||
<p className="flex justify-end">
|
||||
{asPath.includes('/trade') && isBaseOrQuote ? (
|
||||
{!isUnownedAccount ? (
|
||||
asPath.includes('/trade') && isBaseOrQuote ? (
|
||||
<LinkButton
|
||||
className="font-normal underline-offset-4"
|
||||
onClick={() =>
|
||||
|
@ -319,6 +320,12 @@ const Balance = ({ bank }: { bank: BankWithBalance }) => {
|
|||
decimals={tokenBank.mintDecimals}
|
||||
/>
|
||||
</LinkButton>
|
||||
) : (
|
||||
<FormatNumericValue
|
||||
value={balance}
|
||||
decimals={tokenBank.mintDecimals}
|
||||
/>
|
||||
)
|
||||
) : (
|
||||
<FormatNumericValue value={balance} decimals={tokenBank.mintDecimals} />
|
||||
)}
|
||||
|
|
|
@ -363,12 +363,14 @@ const DetailedAreaChart: FunctionComponent<DetailedAreaChartProps> = ({
|
|||
domain
|
||||
? domain
|
||||
: ([dataMin, dataMax]) => {
|
||||
const difference =
|
||||
Math.abs(dataMax) - Math.abs(dataMin)
|
||||
if (difference < 0.1) {
|
||||
const difference = dataMax - dataMin
|
||||
|
||||
if (difference < 0.01) {
|
||||
return [dataMin - 0.001, dataMax + 0.001]
|
||||
} else if (difference < 0.1) {
|
||||
return [dataMin - 0.01, dataMax + 0.01]
|
||||
} else if (difference < 1) {
|
||||
return [dataMin - 0.1, dataMax + 0.1]
|
||||
return [dataMin - 0.1, dataMax + 0.11]
|
||||
} else if (difference < 10) {
|
||||
return [dataMin - 1, dataMax + 1]
|
||||
} else {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Fragment, useCallback, useEffect, useMemo, useState } from 'react'
|
||||
import { useCallback, useEffect, useState } from 'react'
|
||||
import {
|
||||
CheckCircleIcon,
|
||||
ArrowTopRightOnSquareIcon,
|
||||
|
@ -70,31 +70,31 @@ const NotificationList = () => {
|
|||
|
||||
const reversedNotifications = [...notifications].reverse()
|
||||
|
||||
const position: string = useMemo(() => {
|
||||
switch (notificationPosition) {
|
||||
case 'bottom-left':
|
||||
return 'bottom-0 left-0'
|
||||
case 'bottom-right':
|
||||
return 'bottom-0 right-0'
|
||||
case 'top-left':
|
||||
return 'top-0 left-0'
|
||||
case 'top-right':
|
||||
return 'top-0 right-0'
|
||||
const getPosition = (position: string) => {
|
||||
const sharedClasses =
|
||||
'pointer-events-none fixed z-50 flex items-end p-4 text-th-fgd-1 md:p-6'
|
||||
switch (position) {
|
||||
case 'Bottom-Left':
|
||||
return 'flex-col bottom-0 left-0 ' + sharedClasses
|
||||
case 'Bottom-Right':
|
||||
return 'flex-col w-full bottom-0 right-0 ' + sharedClasses
|
||||
case 'Top-Left':
|
||||
return 'flex-col-reverse top-0 left-0 ' + sharedClasses
|
||||
case 'Top-Right':
|
||||
return 'flex-col-reverse w-full top-0 right-0 ' + sharedClasses
|
||||
default:
|
||||
return 'bottom-0 left-0'
|
||||
return 'flex-col bottom-0 left-0 ' + sharedClasses
|
||||
}
|
||||
}
|
||||
}, [notificationPosition])
|
||||
|
||||
useEffect(() => setMounted(true), [])
|
||||
if (!mounted) return null
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`pointer-events-none fixed z-50 flex w-full flex-col items-end space-y-2 p-4 text-th-fgd-1 md:w-auto md:p-6 ${position}`}
|
||||
>
|
||||
<div className={`${getPosition(notificationPosition)}`}>
|
||||
{notifications.filter((n) => n.show).length > 1 ? (
|
||||
<button
|
||||
className="default-transition pointer-events-auto flex items-center rounded bg-th-bkg-3 px-2 py-1 text-xs text-th-fgd-3 md:hover:bg-th-bkg-4"
|
||||
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"
|
||||
onClick={clearAll}
|
||||
>
|
||||
<XMarkIcon className="mr-1 h-3.5 w-3.5" />
|
||||
|
@ -111,7 +111,7 @@ const NotificationList = () => {
|
|||
const Notification = ({ notification }: { notification: Notification }) => {
|
||||
const [notificationPosition] = useLocalStorageState(
|
||||
NOTIFICATION_POSITION_KEY,
|
||||
'bottom-left'
|
||||
'Bottom-Left'
|
||||
)
|
||||
const [preferredExplorer] = useLocalStorageState(
|
||||
PREFERRED_EXPLORER_KEY,
|
||||
|
@ -179,17 +179,7 @@ const Notification = ({ notification }: { notification: Notification }) => {
|
|||
}
|
||||
})
|
||||
|
||||
const {
|
||||
enterFromClass,
|
||||
enterToClass,
|
||||
leaveFromClass,
|
||||
leaveToClass,
|
||||
}: {
|
||||
enterFromClass: string
|
||||
enterToClass: string
|
||||
leaveFromClass: string
|
||||
leaveToClass: string
|
||||
} = useMemo(() => {
|
||||
const getTransformClasses = (position: string) => {
|
||||
const fromLeft = {
|
||||
enterFromClass: 'md:-translate-x-48',
|
||||
enterToClass: 'md:translate-x-100',
|
||||
|
@ -202,31 +192,39 @@ const Notification = ({ notification }: { notification: Notification }) => {
|
|||
leaveFromClass: 'md:translate-x-0',
|
||||
leaveToClass: 'md:translate-x-48',
|
||||
}
|
||||
switch (notificationPosition) {
|
||||
case 'bottom-left':
|
||||
switch (position) {
|
||||
case 'Bottom-Left':
|
||||
return fromLeft
|
||||
case 'bottom-right':
|
||||
case 'Bottom-Right':
|
||||
return fromRight
|
||||
case 'top-left':
|
||||
case 'Top-Left':
|
||||
return fromLeft
|
||||
case 'top-right':
|
||||
case 'Top-Right':
|
||||
return fromRight
|
||||
default:
|
||||
return fromLeft
|
||||
}
|
||||
}, [notificationPosition])
|
||||
}
|
||||
|
||||
return (
|
||||
<Transition
|
||||
className="my-1 w-full md:w-auto"
|
||||
show={show}
|
||||
as={Fragment}
|
||||
appear={true}
|
||||
enter="ease-out duration-500 transition"
|
||||
enterFrom={`-translate-y-2 opacity-0 md:translate-y-0 ${enterFromClass}`}
|
||||
enterTo={`translate-y-0 opacity-100 ${enterToClass}`}
|
||||
enterFrom={`-translate-y-2 opacity-0 md:translate-y-0 ${
|
||||
getTransformClasses(notificationPosition).enterFromClass
|
||||
}`}
|
||||
enterTo={`translate-y-0 opacity-100 ${
|
||||
getTransformClasses(notificationPosition).enterToClass
|
||||
}`}
|
||||
leave="ease-in duration-200 transition"
|
||||
leaveFrom={`translate-y-0 ${leaveFromClass}`}
|
||||
leaveTo={`-translate-y-2 md:translate-y-0 ${leaveToClass}`}
|
||||
leaveFrom={`translate-y-0 ${
|
||||
getTransformClasses(notificationPosition).leaveFromClass
|
||||
}`}
|
||||
leaveTo={`-translate-y-2 md:translate-y-0 ${
|
||||
getTransformClasses(notificationPosition).leaveToClass
|
||||
}`}
|
||||
>
|
||||
<div
|
||||
className={`pointer-events-auto w-full rounded-md border bg-th-bkg-2 shadow-lg md:w-auto ${
|
||||
|
|
|
@ -43,8 +43,11 @@ const SimpleAreaChart = ({
|
|||
<XAxis dataKey={xKey} hide />
|
||||
<YAxis
|
||||
domain={([dataMin, dataMax]) => {
|
||||
const difference = Math.abs(dataMax) - Math.abs(dataMin)
|
||||
if (difference < 0.1) {
|
||||
const difference = dataMax - dataMin
|
||||
|
||||
if (difference < 0.01) {
|
||||
return [dataMin - 0.001, dataMax + 0.001]
|
||||
} else if (difference < 0.1) {
|
||||
return [dataMin - 0.01, dataMax + 0.01]
|
||||
} else if (difference < 1) {
|
||||
return [dataMin - 0.1, dataMax + 0.11]
|
||||
|
|
|
@ -10,10 +10,7 @@ import SpotMarketsTable from './SpotMarketsTable'
|
|||
import TokenStats from './TokenStats'
|
||||
|
||||
// const TABS = ['tokens', 'perp', 'spot', 'mango']
|
||||
const TABS =
|
||||
process.env.NEXT_PUBLIC_SHOW_PERPS === 'true'
|
||||
? ['tokens', 'perp', 'spot', 'mango']
|
||||
: ['tokens', 'spot', 'mango']
|
||||
const TABS = ['tokens', 'perp', 'spot', 'mango']
|
||||
|
||||
const StatsPage = () => {
|
||||
const [activeTab, setActiveTab] = useState('tokens')
|
||||
|
|
|
@ -48,6 +48,7 @@ import useIpAddress from 'hooks/useIpAddress'
|
|||
import { useEnhancedWallet } from '@components/wallet/EnhancedWalletProvider'
|
||||
import SwapSettings from './SwapSettings'
|
||||
import InlineNotification from '@components/shared/InlineNotification'
|
||||
import useUnownedAccount from 'hooks/useUnownedAccount'
|
||||
|
||||
const MAX_DIGITS = 11
|
||||
export const withValueLimit = (values: NumberFormatValues): boolean => {
|
||||
|
@ -69,6 +70,7 @@ const SwapForm = () => {
|
|||
const { group } = useMangoGroup()
|
||||
const [swapFormSizeUi] = useLocalStorageState(SIZE_INPUT_UI_KEY, 'slider')
|
||||
const { ipAllowed, ipCountry } = useIpAddress()
|
||||
const isUnownedAccount = useUnownedAccount()
|
||||
|
||||
const {
|
||||
margin: useMargin,
|
||||
|
@ -327,10 +329,12 @@ const SwapForm = () => {
|
|||
</div>
|
||||
<div className="mb-2 flex items-end justify-between">
|
||||
<p className="text-th-fgd-2 lg:text-base">{t('swap:pay')}</p>
|
||||
{!isUnownedAccount ? (
|
||||
<MaxSwapAmount
|
||||
useMargin={useMargin}
|
||||
setAmountIn={(v) => setAmountInFormValue(v, true)}
|
||||
/>
|
||||
) : null}
|
||||
</div>
|
||||
<div className="mb-3 grid grid-cols-2" id="swap-step-two">
|
||||
<div className="col-span-1 rounded-lg rounded-r-none border border-r-0 border-th-input-border bg-th-input-bkg">
|
||||
|
|
|
@ -164,8 +164,6 @@ const fetchJupiterTransaction = async (
|
|||
const filtered_jup_ixs = ixs
|
||||
.filter((ix) => !isSetupIx(ix.programId))
|
||||
.filter((ix) => !isDuplicateAta(ix))
|
||||
console.log('ixs: ', ixs)
|
||||
console.log('filtered ixs: ', filtered_jup_ixs)
|
||||
|
||||
return [filtered_jup_ixs, alts]
|
||||
}
|
||||
|
|
|
@ -103,7 +103,13 @@ export const getTokenInMax = (
|
|||
}
|
||||
}
|
||||
|
||||
export const useTokenMax = (useMargin = true) => {
|
||||
interface TokenMaxResults {
|
||||
amount: Decimal
|
||||
amountWithBorrow: Decimal
|
||||
decimals: number
|
||||
}
|
||||
|
||||
export const useTokenMax = (useMargin = true): TokenMaxResults => {
|
||||
const { mangoAccount } = useMangoAccount()
|
||||
const { group } = useMangoGroup()
|
||||
const inputBank = mangoStore((s) => s.swap.inputBank)
|
||||
|
|
|
@ -9,7 +9,7 @@ import { useCoingecko } from 'hooks/useCoingecko'
|
|||
import parse from 'html-react-parser'
|
||||
import { useTranslation } from 'next-i18next'
|
||||
import dynamic from 'next/dynamic'
|
||||
import { useLayoutEffect, useMemo, useRef, useState } from 'react'
|
||||
import { useMemo, useState } from 'react'
|
||||
const PriceChart = dynamic(() => import('@components/token/PriceChart'), {
|
||||
ssr: false,
|
||||
})
|
||||
|
@ -48,14 +48,6 @@ const CoingeckoStats = ({
|
|||
const [chartData, setChartData] = useState<{ prices: any[] } | null>(null)
|
||||
const [loadChartData, setLoadChartData] = useState(true)
|
||||
const { isLoading: loadingPrices, data: coingeckoPrices } = useCoingecko()
|
||||
const descWidthRef = useRef<any>(null)
|
||||
|
||||
const [width, setWidth] = useState<number>(0)
|
||||
|
||||
useLayoutEffect(() => {
|
||||
if (!descWidthRef.current) return
|
||||
setWidth(descWidthRef.current.clientWidth)
|
||||
}, [])
|
||||
|
||||
const handleDaysToShow = async (days: string) => {
|
||||
if (days !== '1') {
|
||||
|
@ -109,21 +101,26 @@ const CoingeckoStats = ({
|
|||
return []
|
||||
}, [coingeckoPrices, bank, daysToShow, chartData, loadingChart])
|
||||
|
||||
const truncateDescription = (desc: string) =>
|
||||
desc.substring(0, (desc + ' ').lastIndexOf(' ', 144))
|
||||
|
||||
const description = useMemo(() => {
|
||||
const desc = coingeckoData?.description?.en
|
||||
if (!desc) return ''
|
||||
return showFullDesc
|
||||
? coingeckoData.description.en
|
||||
: truncateDescription(coingeckoData.description.en)
|
||||
}, [coingeckoData, showFullDesc])
|
||||
|
||||
return (
|
||||
<>
|
||||
{coingeckoData?.description?.en?.length ? (
|
||||
{description ? (
|
||||
<div className="border-b border-th-bkg-3 py-4 px-6">
|
||||
<h2 className="mb-1 text-xl">About {bank.name}</h2>
|
||||
<div className="flex items-end">
|
||||
<p
|
||||
className={`${
|
||||
showFullDesc ? 'h-full' : 'h-5'
|
||||
} max-w-[720px] overflow-hidden`}
|
||||
ref={descWidthRef}
|
||||
>
|
||||
{parse(coingeckoData.description.en)}
|
||||
</p>
|
||||
{width === 720 ? (
|
||||
<p className="max-w-[720px]">{parse(description)}</p>
|
||||
{coingeckoData.description.en.length > description.length ||
|
||||
showFullDesc ? (
|
||||
<span
|
||||
className="default-transition ml-4 flex cursor-pointer items-end font-normal underline hover:text-th-fgd-2 md:hover:no-underline"
|
||||
onClick={() => setShowFullDesc(!showFullDesc)}
|
||||
|
|
|
@ -3,7 +3,7 @@ import { useTheme } from 'next-themes'
|
|||
import { useMemo } from 'react'
|
||||
import { Area, AreaChart, ResponsiveContainer, XAxis, YAxis } from 'recharts'
|
||||
import { COLORS } from 'styles/colors'
|
||||
import { formatYAxis } from 'utils/formatting'
|
||||
import { formatCurrencyValue } from 'utils/numbers'
|
||||
|
||||
const PriceChart = ({
|
||||
prices,
|
||||
|
@ -19,8 +19,8 @@ const PriceChart = ({
|
|||
}, [prices])
|
||||
|
||||
return (
|
||||
<div className="relative -mt-1 h-96 w-auto">
|
||||
<div className="-mx-6 mt-6 h-full px-10">
|
||||
<div className="relative -mt-1 h-72 w-auto md:h-96">
|
||||
<div className="mt-6 h-full">
|
||||
<ResponsiveContainer width="100%" height="100%">
|
||||
<AreaChart data={prices}>
|
||||
<defs>
|
||||
|
@ -71,8 +71,9 @@ const PriceChart = ({
|
|||
fill: 'var(--fgd-4)',
|
||||
fontSize: 10,
|
||||
}}
|
||||
tickFormatter={(x) => formatYAxis(x)}
|
||||
tickFormatter={(x) => formatCurrencyValue(x)}
|
||||
tickLine={false}
|
||||
width={prices[0][1] < 0.00001 ? 100 : 60}
|
||||
/>
|
||||
</AreaChart>
|
||||
</ResponsiveContainer>
|
||||
|
|
|
@ -55,7 +55,7 @@ const AdvancedMarketHeader = ({
|
|||
|
||||
return (
|
||||
<div className="flex flex-col bg-th-bkg-1 md:h-12 md:flex-row md:items-center">
|
||||
<div className=" w-full px-5 md:w-auto md:py-0 md:pr-6 lg:pb-0">
|
||||
<div className="w-full px-4 md:w-auto md:px-6 md:py-0 lg:pb-0">
|
||||
<MarketSelectDropdown />
|
||||
</div>
|
||||
<div className="border-t border-th-bkg-3 py-2 px-5 md:border-t-0 md:py-0 md:px-0">
|
||||
|
|
|
@ -537,6 +537,7 @@ const AdvancedTradeForm = () => {
|
|||
{selectedMarket instanceof Serum3Market ? (
|
||||
<div className="mt-4" id="trade-step-eight">
|
||||
<Tooltip
|
||||
className="hidden md:block"
|
||||
delay={250}
|
||||
placement="left"
|
||||
content={t('trade:tooltip-enable-margin')}
|
||||
|
@ -594,7 +595,9 @@ const AdvancedTradeForm = () => {
|
|||
) : (
|
||||
<div className="flex items-center space-x-2">
|
||||
<Loading />
|
||||
<span>{t('trade:placing-order')}</span>
|
||||
<span className="hidden sm:block">
|
||||
{t('trade:placing-order')}
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
</Button>
|
||||
|
|
|
@ -3,24 +3,20 @@ import { StarIcon } from '@heroicons/react/20/solid'
|
|||
import useLocalStorageState from 'hooks/useLocalStorageState'
|
||||
import useMangoGroup from 'hooks/useMangoGroup'
|
||||
import useSelectedMarket from 'hooks/useSelectedMarket'
|
||||
import { useViewport } from 'hooks/useViewport'
|
||||
import Link from 'next/link'
|
||||
import { useRouter } from 'next/router'
|
||||
import { FAVORITE_MARKETS_KEY } from 'utils/constants'
|
||||
import { breakpoints } from 'utils/theme'
|
||||
import MarketLogos from './MarketLogos'
|
||||
|
||||
const FavoriteMarketsBar = () => {
|
||||
const [favoriteMarkets] = useLocalStorageState(FAVORITE_MARKETS_KEY, [])
|
||||
const { width } = useViewport()
|
||||
const isMobile = width ? width < breakpoints.sm : false
|
||||
const { asPath } = useRouter()
|
||||
const { selectedMarket } = useSelectedMarket()
|
||||
const { group } = useMangoGroup()
|
||||
|
||||
return !isMobile ? (
|
||||
return (
|
||||
<Transition
|
||||
className="flex items-center space-x-4 overflow-hidden border-b border-th-bkg-3 py-1 px-6"
|
||||
className="hide-scroll flex items-center space-x-2 overflow-x-auto border-b border-th-bkg-3 bg-th-bkg-2 py-1 px-4 md:space-x-4 md:px-6"
|
||||
show={!!favoriteMarkets.length}
|
||||
enter="transition-all ease-in duration-200"
|
||||
enterFrom="opacity-0 h-0"
|
||||
|
@ -29,7 +25,7 @@ const FavoriteMarketsBar = () => {
|
|||
leaveFrom="opacity-100 h-8"
|
||||
leaveTo="opacity-0 h-0"
|
||||
>
|
||||
<StarIcon className="h-4 w-4 text-th-fgd-4" />
|
||||
<StarIcon className="h-4 w-4 flex-shrink-0 text-th-fgd-4" />
|
||||
{favoriteMarkets.map((mkt: string) => {
|
||||
// const change24h = marketsInfo?.find((m) => m.name === mkt)?.change24h
|
||||
const isPerp = mkt.includes('PERP')
|
||||
|
@ -71,7 +67,7 @@ const FavoriteMarketsBar = () => {
|
|||
)
|
||||
})}
|
||||
</Transition>
|
||||
) : null
|
||||
)
|
||||
}
|
||||
|
||||
export default FavoriteMarketsBar
|
||||
|
|
|
@ -10,8 +10,7 @@ import { useMemo, useState } from 'react'
|
|||
import { DEFAULT_MARKET_NAME } from 'utils/constants'
|
||||
import MarketLogos from './MarketLogos'
|
||||
|
||||
const isTesting = process.env.NEXT_PUBLIC_SHOW_PERPS === 'true'
|
||||
const TAB_VALUES = isTesting ? ['spot', 'perp'] : ['spot']
|
||||
const TAB_VALUES = ['spot', 'perp']
|
||||
|
||||
const MarketSelectDropdown = () => {
|
||||
const { selectedMarket } = useSelectedMarket()
|
||||
|
@ -21,11 +20,13 @@ const MarketSelectDropdown = () => {
|
|||
const [spotBaseFilter, setSpotBaseFilter] = useState('All')
|
||||
|
||||
const perpMarkets = useMemo(() => {
|
||||
return allPerpMarkets.filter(
|
||||
return allPerpMarkets
|
||||
.filter(
|
||||
(p) =>
|
||||
p.publicKey.toString() !==
|
||||
'9Y8paZ5wUpzLFfQuHz8j2RtPrKsDtHx9sbgFmWb5abCw'
|
||||
)
|
||||
.sort((a, b) => a.name.localeCompare(b.name))
|
||||
}, [allPerpMarkets])
|
||||
|
||||
const spotBaseTokens: string[] = useMemo(() => {
|
||||
|
@ -87,6 +88,7 @@ const MarketSelectDropdown = () => {
|
|||
return mkt.name.split('/')[1] === spotBaseFilter
|
||||
}
|
||||
})
|
||||
.sort((a, b) => a.name.localeCompare(b.name))
|
||||
.map((m) => {
|
||||
return (
|
||||
<div
|
||||
|
|
|
@ -4,6 +4,7 @@ import { FadeInFadeOut } from '@components/shared/Transitions'
|
|||
import mangoStore from '@store/mangoStore'
|
||||
import useMangoAccount from 'hooks/useMangoAccount'
|
||||
import useSelectedMarket from 'hooks/useSelectedMarket'
|
||||
import useUnownedAccount from 'hooks/useUnownedAccount'
|
||||
import { useTranslation } from 'next-i18next'
|
||||
import { useCallback, useMemo } from 'react'
|
||||
import { formatNumericValue } from 'utils/numbers'
|
||||
|
@ -28,6 +29,7 @@ const MaxSizeButton = ({
|
|||
side,
|
||||
useMargin
|
||||
)
|
||||
const isUnownedAccount = useUnownedAccount()
|
||||
|
||||
const perpMax = useMemo(() => {
|
||||
const group = mangoStore.getState().group
|
||||
|
@ -108,7 +110,7 @@ const MaxSizeButton = ({
|
|||
return (
|
||||
<div className="mb-2 mt-3 flex items-center justify-between">
|
||||
<p className="text-xs text-th-fgd-3">{t('trade:size')}</p>
|
||||
<FadeInFadeOut show={!!price}>
|
||||
<FadeInFadeOut show={!!price && !isUnownedAccount}>
|
||||
<MaxAmountButton
|
||||
className="text-xs"
|
||||
decimals={minOrderDecimals}
|
||||
|
|
|
@ -7,12 +7,16 @@ import TabButtons from '@components/shared/TabButtons'
|
|||
import { TABS } from './OrderbookAndTrades'
|
||||
import RecentTrades from './RecentTrades'
|
||||
import TradingChartContainer from './TradingChartContainer'
|
||||
import FavoriteMarketsBar from './FavoriteMarketsBar'
|
||||
|
||||
const MobileTradeAdvancedPage = () => {
|
||||
const [activeTab, setActiveTab] = useState('trade:book')
|
||||
const [showChart, setShowChart] = useState(false)
|
||||
return (
|
||||
<div className="grid grid-cols-2 sm:grid-cols-3">
|
||||
<div className="col-span-2 sm:col-span-3">
|
||||
<FavoriteMarketsBar />
|
||||
</div>
|
||||
<div className="col-span-2 border-b border-th-bkg-3 sm:col-span-3">
|
||||
<AdvancedMarketHeader
|
||||
showChart={showChart}
|
||||
|
@ -36,18 +40,10 @@ const MobileTradeAdvancedPage = () => {
|
|||
fillWidth
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
className={`h-full ${
|
||||
activeTab === 'trade:book' ? 'visible' : 'hidden'
|
||||
}`}
|
||||
>
|
||||
<div className={activeTab === 'trade:book' ? 'visible' : 'hidden'}>
|
||||
<Orderbook />
|
||||
</div>
|
||||
<div
|
||||
className={`h-full ${
|
||||
activeTab === 'trade:trades' ? 'visible' : 'hidden'
|
||||
}`}
|
||||
>
|
||||
<div className={activeTab === 'trade:trades' ? 'visible' : 'hidden'}>
|
||||
<RecentTrades />
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -27,6 +27,7 @@ import { useWallet } from '@solana/wallet-adapter-react'
|
|||
import { PublicKey } from '@solana/web3.js'
|
||||
import mangoStore from '@store/mangoStore'
|
||||
import useMangoAccount from 'hooks/useMangoAccount'
|
||||
import useUnownedAccount from 'hooks/useUnownedAccount'
|
||||
import { useViewport } from 'hooks/useViewport'
|
||||
import { useTranslation } from 'next-i18next'
|
||||
import { ChangeEvent, useCallback, useState } from 'react'
|
||||
|
@ -49,6 +50,7 @@ const OpenOrders = () => {
|
|||
const showTableView = width ? width > breakpoints.md : false
|
||||
const { mangoAccountAddress } = useMangoAccount()
|
||||
const { connected } = useWallet()
|
||||
const isUnownedAccount = useUnownedAccount()
|
||||
|
||||
const findSerum3MarketPkInOpenOrders = (o: Order): string | undefined => {
|
||||
const openOrders = mangoStore.getState().mangoAccount.openOrders
|
||||
|
@ -237,7 +239,9 @@ const OpenOrders = () => {
|
|||
<Th className="w-[16.67%] text-right">{t('trade:size')}</Th>
|
||||
<Th className="w-[16.67%] text-right">{t('price')}</Th>
|
||||
<Th className="w-[16.67%] text-right">{t('value')}</Th>
|
||||
<Th className="w-[16.67%] text-right"></Th>
|
||||
{!isUnownedAccount ? (
|
||||
<Th className="w-[16.67%] text-right" />
|
||||
) : null}
|
||||
</TrHead>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
@ -248,21 +252,14 @@ const OpenOrders = () => {
|
|||
let market: PerpMarket | Serum3Market
|
||||
let tickSize: number
|
||||
let minOrderSize: number
|
||||
let quoteSymbol
|
||||
if (o instanceof PerpOrder) {
|
||||
market = group.getPerpMarketByMarketIndex(o.perpMarketIndex)
|
||||
quoteSymbol = group.getFirstBankByTokenIndex(
|
||||
market.settleTokenIndex
|
||||
).name
|
||||
tickSize = market.tickSize
|
||||
minOrderSize = market.minOrderSize
|
||||
} else {
|
||||
market = group.getSerum3MarketByExternalMarket(
|
||||
new PublicKey(marketPk)
|
||||
)
|
||||
quoteSymbol = group.getFirstBankByTokenIndex(
|
||||
market!.quoteTokenIndex
|
||||
).name
|
||||
const serumMarket = group.getSerum3ExternalMarket(
|
||||
market.serumMarketExternal
|
||||
)
|
||||
|
@ -283,21 +280,16 @@ const OpenOrders = () => {
|
|||
{modifyOrderId !== o.orderId.toString() ? (
|
||||
<>
|
||||
<Td className="w-[16.67%] text-right font-mono">
|
||||
{o.size.toLocaleString(undefined, {
|
||||
maximumFractionDigits:
|
||||
getDecimalCount(minOrderSize),
|
||||
})}
|
||||
<FormatNumericValue
|
||||
value={o.size}
|
||||
decimals={getDecimalCount(minOrderSize)}
|
||||
/>
|
||||
</Td>
|
||||
<Td className="w-[16.67%] whitespace-nowrap text-right">
|
||||
<span className="font-mono">
|
||||
{o.price.toLocaleString(undefined, {
|
||||
minimumFractionDigits: getDecimalCount(tickSize),
|
||||
maximumFractionDigits: getDecimalCount(tickSize),
|
||||
})}{' '}
|
||||
<span className="font-body text-th-fgd-4">
|
||||
{quoteSymbol}
|
||||
</span>
|
||||
</span>
|
||||
<Td className="w-[16.67%] whitespace-nowrap text-right font-mono">
|
||||
<FormatNumericValue
|
||||
value={o.price}
|
||||
decimals={getDecimalCount(tickSize)}
|
||||
/>
|
||||
</Td>
|
||||
</>
|
||||
) : (
|
||||
|
@ -325,13 +317,10 @@ const OpenOrders = () => {
|
|||
</Td>
|
||||
</>
|
||||
)}
|
||||
<Td className="w-[16.67%] text-right">
|
||||
<FormatNumericValue
|
||||
value={o.size * o.price}
|
||||
decimals={2}
|
||||
isUsd
|
||||
/>
|
||||
<Td className="w-[16.67%] text-right font-mono">
|
||||
<FormatNumericValue value={o.size * o.price} isUsd />
|
||||
</Td>
|
||||
{!isUnownedAccount ? (
|
||||
<Td className="w-[16.67%]">
|
||||
<div className="flex justify-end space-x-2">
|
||||
{modifyOrderId !== o.orderId.toString() ? (
|
||||
|
@ -382,6 +371,7 @@ const OpenOrders = () => {
|
|||
)}
|
||||
</div>
|
||||
</Td>
|
||||
) : null}
|
||||
</TrBody>
|
||||
)
|
||||
})
|
||||
|
@ -397,24 +387,14 @@ const OpenOrders = () => {
|
|||
let market: PerpMarket | Serum3Market
|
||||
let tickSize: number
|
||||
let minOrderSize: number
|
||||
let quoteSymbol: string
|
||||
let baseSymbol: string
|
||||
if (o instanceof PerpOrder) {
|
||||
market = group.getPerpMarketByMarketIndex(o.perpMarketIndex)
|
||||
baseSymbol = market.name.split('-')[0]
|
||||
quoteSymbol = group.getFirstBankByTokenIndex(
|
||||
market.settleTokenIndex
|
||||
).name
|
||||
tickSize = market.tickSize
|
||||
minOrderSize = market.minOrderSize
|
||||
} else {
|
||||
market = group.getSerum3MarketByExternalMarket(
|
||||
new PublicKey(marketPk)
|
||||
)
|
||||
baseSymbol = market.name.split('/')[0]
|
||||
quoteSymbol = group.getFirstBankByTokenIndex(
|
||||
market!.quoteTokenIndex
|
||||
).name
|
||||
const serumMarket = group.getSerum3ExternalMarket(
|
||||
market.serumMarketExternal
|
||||
)
|
||||
|
@ -433,20 +413,18 @@ const OpenOrders = () => {
|
|||
<SideBadge side={o.side} />
|
||||
<p className="text-th-fgd-4">
|
||||
<span className="font-mono text-th-fgd-3">
|
||||
{o.size.toLocaleString(undefined, {
|
||||
maximumFractionDigits:
|
||||
getDecimalCount(minOrderSize),
|
||||
})}
|
||||
</span>{' '}
|
||||
{baseSymbol}
|
||||
{' for '}
|
||||
<FormatNumericValue
|
||||
value={o.size}
|
||||
decimals={getDecimalCount(minOrderSize)}
|
||||
/>
|
||||
</span>
|
||||
{' at '}
|
||||
<span className="font-mono text-th-fgd-3">
|
||||
{o.price.toLocaleString(undefined, {
|
||||
minimumFractionDigits: getDecimalCount(tickSize),
|
||||
maximumFractionDigits: getDecimalCount(tickSize),
|
||||
})}
|
||||
</span>{' '}
|
||||
{quoteSymbol}
|
||||
<FormatNumericValue
|
||||
value={o.price}
|
||||
decimals={getDecimalCount(tickSize)}
|
||||
/>
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
) : (
|
||||
|
@ -477,7 +455,7 @@ const OpenOrders = () => {
|
|||
</div>
|
||||
)}
|
||||
</div>
|
||||
{connected ? (
|
||||
{!isUnownedAccount ? (
|
||||
<div className="flex items-center space-x-3 pl-8">
|
||||
<div className="flex items-center space-x-2">
|
||||
{modifyOrderId !== o.orderId.toString() ? (
|
||||
|
|
|
@ -437,6 +437,7 @@ const Orderbook = () => {
|
|||
<div className="flex items-center justify-between border-b border-th-bkg-3 px-4 py-2">
|
||||
<div id="trade-step-three" className="flex items-center space-x-1.5">
|
||||
<Tooltip
|
||||
className="hidden md:block"
|
||||
content={showBuys ? t('trade:hide-bids') : t('trade:show-bids')}
|
||||
placement="bottom"
|
||||
>
|
||||
|
@ -451,6 +452,7 @@ const Orderbook = () => {
|
|||
</button>
|
||||
</Tooltip>
|
||||
<Tooltip
|
||||
className="hidden md:block"
|
||||
content={showSells ? t('trade:hide-asks') : t('trade:show-asks')}
|
||||
placement="bottom"
|
||||
>
|
||||
|
@ -464,7 +466,11 @@ const Orderbook = () => {
|
|||
<OrderbookIcon className="h-4 w-4" side="sell" />
|
||||
</button>
|
||||
</Tooltip>
|
||||
<Tooltip content={'Reset and center orderbook'} placement="bottom">
|
||||
<Tooltip
|
||||
className="hidden md:block"
|
||||
content={'Reset and center orderbook'}
|
||||
placement="bottom"
|
||||
>
|
||||
<button
|
||||
className={`rounded ${
|
||||
showSells ? 'bg-th-bkg-3' : 'bg-th-bkg-2'
|
||||
|
@ -477,7 +483,12 @@ const Orderbook = () => {
|
|||
</div>
|
||||
{market ? (
|
||||
<div id="trade-step-four">
|
||||
<Tooltip content={t('trade:grouping')} placement="left" delay={250}>
|
||||
<Tooltip
|
||||
className="hidden md:block"
|
||||
content={t('trade:grouping')}
|
||||
placement="left"
|
||||
delay={250}
|
||||
>
|
||||
<GroupSize
|
||||
tickSize={market.tickSize}
|
||||
onChange={onGroupSizeChange}
|
||||
|
|
|
@ -9,9 +9,12 @@ import mangoStore from '@store/mangoStore'
|
|||
import useMangoAccount from 'hooks/useMangoAccount'
|
||||
import useMangoGroup from 'hooks/useMangoGroup'
|
||||
import useSelectedMarket from 'hooks/useSelectedMarket'
|
||||
import useUnownedAccount from 'hooks/useUnownedAccount'
|
||||
import { useViewport } from 'hooks/useViewport'
|
||||
import { useTranslation } from 'next-i18next'
|
||||
import { useCallback, useState } from 'react'
|
||||
import { floorToDecimal, getDecimalCount } from 'utils/numbers'
|
||||
import { breakpoints } from 'utils/theme'
|
||||
import { calculateLimitPriceForMarketOrder } from 'utils/tradeForm'
|
||||
import MarketCloseModal from './MarketCloseModal'
|
||||
import PerpSideBadge from './PerpSideBadge'
|
||||
|
@ -28,6 +31,9 @@ const PerpPositions = () => {
|
|||
const { selectedMarket } = useSelectedMarket()
|
||||
const { connected } = useWallet()
|
||||
const { mangoAccountAddress } = useMangoAccount()
|
||||
const isUnownedAccount = useUnownedAccount()
|
||||
const { width } = useViewport()
|
||||
const showTableView = width ? width > breakpoints.md : false
|
||||
|
||||
const handlePositionClick = (positionSize: number, market: PerpMarket) => {
|
||||
const tradeForm = mangoStore.getState().tradeForm
|
||||
|
@ -72,6 +78,7 @@ const PerpPositions = () => {
|
|||
)
|
||||
|
||||
return mangoAccountAddress && openPerpPositions.length ? (
|
||||
showTableView ? (
|
||||
<>
|
||||
<div className="thin-scroll overflow-x-auto">
|
||||
<Table>
|
||||
|
@ -86,7 +93,7 @@ const PerpPositions = () => {
|
|||
'pnl'
|
||||
)}`}</Th>
|
||||
<Th className="text-right">{t('pnl')}</Th>
|
||||
<Th />
|
||||
{!isUnownedAccount ? <Th /> : null}
|
||||
</TrHead>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
@ -164,6 +171,7 @@ const PerpPositions = () => {
|
|||
>
|
||||
<FormatNumericValue value={cummulativePnl} isUsd />
|
||||
</Td>
|
||||
{!isUnownedAccount ? (
|
||||
<Td className={`text-right`}>
|
||||
<Button
|
||||
className="text-xs"
|
||||
|
@ -174,6 +182,7 @@ const PerpPositions = () => {
|
|||
Close
|
||||
</Button>
|
||||
</Td>
|
||||
) : null}
|
||||
</TrBody>
|
||||
)
|
||||
})}
|
||||
|
@ -188,6 +197,86 @@ const PerpPositions = () => {
|
|||
/>
|
||||
) : null}
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
{openPerpPositions.map((position) => {
|
||||
const market = group.getPerpMarketByMarketIndex(position.marketIndex)
|
||||
const basePosition = position.getBasePositionUi(market)
|
||||
const floorBasePosition = floorToDecimal(
|
||||
basePosition,
|
||||
getDecimalCount(market.minOrderSize)
|
||||
).toNumber()
|
||||
const isSelectedMarket =
|
||||
selectedMarket instanceof PerpMarket &&
|
||||
selectedMarket.perpMarketIndex === position.marketIndex
|
||||
|
||||
if (!basePosition) return null
|
||||
const cummulativePnl =
|
||||
position.cumulativePnlOverPositionLifetimeUi(market)
|
||||
return (
|
||||
<div
|
||||
className="flex items-center justify-between border-b border-th-bkg-3 p-4"
|
||||
key={`${position.marketIndex}`}
|
||||
>
|
||||
<div>
|
||||
<TableMarketName market={market} />
|
||||
<div className="mt-1 flex items-center space-x-1">
|
||||
<PerpSideBadge basePosition={basePosition} />
|
||||
<p className="text-th-fgd-4">
|
||||
<span className="font-mono text-th-fgd-3">
|
||||
{isSelectedMarket ? (
|
||||
<LinkButton
|
||||
onClick={() =>
|
||||
handlePositionClick(floorBasePosition, market)
|
||||
}
|
||||
>
|
||||
<FormatNumericValue
|
||||
value={Math.abs(basePosition)}
|
||||
decimals={getDecimalCount(market.minOrderSize)}
|
||||
/>
|
||||
</LinkButton>
|
||||
) : (
|
||||
<FormatNumericValue
|
||||
value={Math.abs(basePosition)}
|
||||
decimals={getDecimalCount(market.minOrderSize)}
|
||||
/>
|
||||
)}
|
||||
</span>
|
||||
{' at '}
|
||||
<span className="font-mono text-th-fgd-3">
|
||||
<FormatNumericValue
|
||||
value={position.getAverageEntryPriceUi(market)}
|
||||
decimals={getDecimalCount(market.tickSize)}
|
||||
isUsd
|
||||
/>
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center space-x-3">
|
||||
<div
|
||||
className={`text-right font-mono ${
|
||||
cummulativePnl > 0 ? 'text-th-up' : 'text-th-down'
|
||||
}`}
|
||||
>
|
||||
<FormatNumericValue value={cummulativePnl} isUsd />
|
||||
</div>
|
||||
{!isUnownedAccount ? (
|
||||
<Button
|
||||
className="text-xs"
|
||||
secondary
|
||||
size="small"
|
||||
onClick={() => showClosePositionModal(position)}
|
||||
>
|
||||
Close
|
||||
</Button>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</>
|
||||
)
|
||||
) : mangoAccountAddress || connected ? (
|
||||
<div className="flex flex-col items-center p-8">
|
||||
<NoSymbolIcon className="mb-2 h-6 w-6 text-th-fgd-4" />
|
||||
|
|
|
@ -16,6 +16,7 @@ import TradeVolumeAlertModal, {
|
|||
DEFAULT_VOLUME_ALERT_SETTINGS,
|
||||
} from '@components/modals/TradeVolumeAlertModal'
|
||||
import dayjs from 'dayjs'
|
||||
import { PerpMarket } from '@blockworks-foundation/mango-v4'
|
||||
|
||||
const volumeAlertSound = new Howl({
|
||||
src: ['/sounds/trade-buy.mp3'],
|
||||
|
@ -46,17 +47,29 @@ const RecentTrades = () => {
|
|||
|
||||
useEffect(() => {
|
||||
if (!fills.length) return
|
||||
const latesetFill = fills[0]
|
||||
if (!latestFillId) {
|
||||
setLatestFillId(fills[0].orderId.toString())
|
||||
const fillId =
|
||||
selectedMarket instanceof PerpMarket
|
||||
? latesetFill.takerClientOrderId
|
||||
: latesetFill.orderId
|
||||
setLatestFillId(fillId.toString())
|
||||
}
|
||||
}, [fills])
|
||||
|
||||
useInterval(() => {
|
||||
if (!soundSettings['recent-trades'] || !quoteBank) return
|
||||
setLatestFillId(fills[0].orderId.toString())
|
||||
const fillsLimitIndex = fills.findIndex(
|
||||
(f) => f.orderId.toString() === latestFillId
|
||||
)
|
||||
if (!soundSettings['recent-trades'] || !quoteBank || !fills.length) return
|
||||
const latesetFill = fills[0]
|
||||
const fillId =
|
||||
selectedMarket instanceof PerpMarket
|
||||
? latesetFill.takerClientOrderId
|
||||
: latesetFill.orderId
|
||||
setLatestFillId(fillId.toString())
|
||||
const fillsLimitIndex = fills.findIndex((f) => {
|
||||
const id =
|
||||
selectedMarket instanceof PerpMarket ? f.takerClientOrderId : f.orderId
|
||||
return id.toString() === fillId.toString()
|
||||
})
|
||||
const newFillsVolumeValue = fills
|
||||
.slice(0, fillsLimitIndex)
|
||||
.reduce((a, c) => a + c.size * c.price, 0)
|
||||
|
@ -107,7 +120,7 @@ const RecentTrades = () => {
|
|||
|
||||
const vol = fills.reduce(
|
||||
(a: { buys: number; sells: number }, c: any) => {
|
||||
if (c.side === 'buy' || c.takerSide === 1) {
|
||||
if (c.side === 'buy' || c.takerSide === 0) {
|
||||
a.buys = a.buys + c.size
|
||||
} else {
|
||||
a.sells = a.sells + c.size
|
||||
|
@ -124,7 +137,11 @@ const RecentTrades = () => {
|
|||
<>
|
||||
<div className="thin-scroll h-full overflow-y-scroll">
|
||||
<div className="flex items-center justify-between border-b border-th-bkg-3 py-1 px-2">
|
||||
<Tooltip content={t('trade:tooltip-volume-alert')} delay={250}>
|
||||
<Tooltip
|
||||
className="hidden md:block"
|
||||
content={t('trade:tooltip-volume-alert')}
|
||||
delay={250}
|
||||
>
|
||||
<IconButton
|
||||
onClick={() => setShowVolumeAlertModal(true)}
|
||||
size="small"
|
||||
|
|
|
@ -340,7 +340,7 @@ const TradeHistory = () => {
|
|||
<span className="font-mono text-th-fgd-2">
|
||||
{trade.size}
|
||||
</span>
|
||||
{' for '}
|
||||
{' at '}
|
||||
<span className="font-mono text-th-fgd-2">
|
||||
<FormatNumericValue value={trade.price} />
|
||||
</span>
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
import { useEffect, useRef, useMemo, useState } from 'react'
|
||||
import { useEffect, useRef, useMemo, useState, useCallback } from 'react'
|
||||
import { useTheme } from 'next-themes'
|
||||
import {
|
||||
widget,
|
||||
ChartingLibraryWidgetOptions,
|
||||
IChartingLibraryWidget,
|
||||
ResolutionString,
|
||||
IOrderLineAdapter,
|
||||
EntityId,
|
||||
} from '@public/charting_library'
|
||||
import mangoStore from '@store/mangoStore'
|
||||
|
@ -12,15 +13,30 @@ import { useViewport } from 'hooks/useViewport'
|
|||
import {
|
||||
CHART_DATA_FEED,
|
||||
DEFAULT_MARKET_NAME,
|
||||
SHOW_ORDER_LINES_KEY,
|
||||
SHOW_STABLE_PRICE_KEY,
|
||||
} from 'utils/constants'
|
||||
import { breakpoints } from 'utils/theme'
|
||||
import { COLORS } from 'styles/colors'
|
||||
import useLocalStorageState from 'hooks/useLocalStorageState'
|
||||
import { useTranslation } from 'next-i18next'
|
||||
import useStablePrice from 'hooks/useStablePrice'
|
||||
import { notify } from 'utils/notifications'
|
||||
import {
|
||||
PerpMarket,
|
||||
PerpOrder,
|
||||
PerpOrderType,
|
||||
Serum3Market,
|
||||
Serum3OrderType,
|
||||
Serum3SelfTradeBehavior,
|
||||
Serum3Side,
|
||||
} from '@blockworks-foundation/mango-v4'
|
||||
import { Order } from '@project-serum/serum/lib/market'
|
||||
import { PublicKey } from '@solana/web3.js'
|
||||
import useLocalStorageState from 'hooks/useLocalStorageState'
|
||||
import { formatNumericValue, getDecimalCount } from 'utils/numbers'
|
||||
import { BN } from '@project-serum/anchor'
|
||||
import SpotDatafeed from 'apis/birdeye/datafeed'
|
||||
import PerpDatafeed from 'apis/mngo/datafeed'
|
||||
import useStablePrice from 'hooks/useStablePrice'
|
||||
|
||||
export interface ChartContainerProps {
|
||||
container: ChartingLibraryWidgetOptions['container']
|
||||
|
@ -49,12 +65,17 @@ function hexToRgb(hex: string) {
|
|||
}
|
||||
|
||||
const TradingViewChart = () => {
|
||||
const { t } = useTranslation('tv-chart')
|
||||
const { t } = useTranslation(['tv-chart', 'trade'])
|
||||
const { theme } = useTheme()
|
||||
const { width } = useViewport()
|
||||
|
||||
const [chartReady, setChartReady] = useState(false)
|
||||
const [spotOrPerp, setSpotOrPerp] = useState('spot')
|
||||
const [showOrderLinesLocalStorage, toggleShowOrderLinesLocalStorage] =
|
||||
useLocalStorageState(SHOW_ORDER_LINES_KEY, true)
|
||||
const [showOrderLines, toggleShowOrderLines] = useState(
|
||||
showOrderLinesLocalStorage
|
||||
)
|
||||
|
||||
const [showStablePriceLocalStorage, toggleShowStablePriceLocalStorage] =
|
||||
useLocalStorageState(SHOW_STABLE_PRICE_KEY, false)
|
||||
const [showStablePrice, toggleShowStablePrice] = useState(
|
||||
|
@ -151,6 +172,96 @@ const TradingViewChart = () => {
|
|||
}
|
||||
}, [selectedMarket, chartReady])
|
||||
|
||||
useEffect(() => {
|
||||
if (
|
||||
selectedMarketName?.toLowerCase().includes('perp') &&
|
||||
spotOrPerp !== 'perp'
|
||||
) {
|
||||
setSpotOrPerp('perp')
|
||||
} else if (
|
||||
!selectedMarketName?.toLowerCase().includes('perp') &&
|
||||
spotOrPerp !== 'spot'
|
||||
) {
|
||||
setSpotOrPerp('spot')
|
||||
}
|
||||
}, [selectedMarketName, spotOrPerp])
|
||||
|
||||
useEffect(() => {
|
||||
if (window) {
|
||||
const widgetOptions: ChartingLibraryWidgetOptions = {
|
||||
// debug: true,
|
||||
symbol: selectedMarket,
|
||||
// BEWARE: no trailing slash is expected in feed URL
|
||||
// tslint:disable-next-line:no-any
|
||||
datafeed: spotOrPerp === 'spot' ? SpotDatafeed : PerpDatafeed,
|
||||
interval:
|
||||
defaultProps.interval as ChartingLibraryWidgetOptions['interval'],
|
||||
container:
|
||||
defaultProps.container as ChartingLibraryWidgetOptions['container'],
|
||||
library_path: defaultProps.libraryPath as string,
|
||||
locale: 'en',
|
||||
enabled_features: ['hide_left_toolbar_by_default'],
|
||||
disabled_features: [
|
||||
'use_localstorage_for_settings',
|
||||
'timeframes_toolbar',
|
||||
isMobile ? 'left_toolbar' : '',
|
||||
'show_logo_on_all_charts',
|
||||
'caption_buttons_text_if_possible',
|
||||
'header_settings',
|
||||
// 'header_chart_type',
|
||||
'header_compare',
|
||||
'compare_symbol',
|
||||
'header_screenshot',
|
||||
// 'header_widget_dom_node',
|
||||
// 'header_widget',
|
||||
'header_saveload',
|
||||
'header_undo_redo',
|
||||
'header_interval_dialog_button',
|
||||
'show_interval_dialog_on_key_press',
|
||||
'header_symbol_search',
|
||||
'popup_hints',
|
||||
],
|
||||
fullscreen: defaultProps.fullscreen,
|
||||
autosize: defaultProps.autosize,
|
||||
studies_overrides: defaultProps.studiesOverrides,
|
||||
theme:
|
||||
theme === 'Light' || theme === 'Banana' || theme === 'Lychee'
|
||||
? 'Light'
|
||||
: 'Dark',
|
||||
custom_css_url: '/styles/tradingview.css',
|
||||
loading_screen: {
|
||||
backgroundColor: COLORS.BKG1[theme],
|
||||
},
|
||||
overrides: {
|
||||
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
|
||||
|
||||
...chartStyleOverrides,
|
||||
},
|
||||
}
|
||||
|
||||
const tvWidget = new widget(widgetOptions)
|
||||
tvWidgetRef.current = tvWidget
|
||||
|
||||
tvWidgetRef.current.onChartReady(function () {
|
||||
createOLButton()
|
||||
createStablePriceButton()
|
||||
if (showOrderLines) {
|
||||
const openOrders = mangoStore.getState().mangoAccount.openOrders
|
||||
deleteLines()
|
||||
drawLinesForMarket(openOrders)
|
||||
}
|
||||
if (showStablePrice && stablePrice) {
|
||||
const set = mangoStore.getState().set
|
||||
set((s) => {
|
||||
s.tradingView.stablePriceLine = drawStablePriceLine(stablePrice)
|
||||
})
|
||||
}
|
||||
setChartReady(true)
|
||||
})
|
||||
//eslint-disable-next-line
|
||||
}
|
||||
}, [theme, isMobile, defaultProps, spotOrPerp])
|
||||
|
||||
const createStablePriceButton = () => {
|
||||
const button = tvWidgetRef?.current?.createButton()
|
||||
if (!button) {
|
||||
|
@ -242,108 +353,425 @@ const TradingViewChart = () => {
|
|||
})
|
||||
}
|
||||
|
||||
const createOLButton = () => {
|
||||
const button = tvWidgetRef?.current?.createButton()
|
||||
if (!button) {
|
||||
return
|
||||
}
|
||||
button.textContent = 'OL'
|
||||
if (showOrderLinesLocalStorage) {
|
||||
button.style.color = COLORS.ACTIVE[theme]
|
||||
} else {
|
||||
button.style.color = COLORS.FGD4[theme]
|
||||
}
|
||||
button.setAttribute('title', t('tv-chart:toggle-order-line'))
|
||||
button.addEventListener('click', toggleOrderLines)
|
||||
}
|
||||
|
||||
function toggleOrderLines(this: HTMLElement) {
|
||||
toggleShowOrderLines((prevState: boolean) => !prevState)
|
||||
if (this.style.color === hexToRgb(COLORS.ACTIVE[theme])) {
|
||||
deleteLines()
|
||||
this.style.color = COLORS.FGD4[theme]
|
||||
} else {
|
||||
const openOrders = mangoStore.getState().mangoAccount.openOrders
|
||||
drawLinesForMarket(openOrders)
|
||||
this.style.color = COLORS.ACTIVE[theme]
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (showOrderLines !== showOrderLinesLocalStorage) {
|
||||
toggleShowOrderLinesLocalStorage(showOrderLines)
|
||||
}
|
||||
}, [showOrderLines])
|
||||
|
||||
// update order lines if a user's open orders change
|
||||
useEffect(() => {
|
||||
let subscription
|
||||
if (chartReady && tvWidgetRef?.current) {
|
||||
subscription = mangoStore.subscribe(
|
||||
(state) => state.mangoAccount.openOrders,
|
||||
(openOrders) => {
|
||||
const orderLines = mangoStore.getState().tradingView.orderLines
|
||||
tvWidgetRef.current?.onChartReady(() => {
|
||||
let matchingOrderLines = 0
|
||||
let openOrdersForMarket = 0
|
||||
|
||||
const oOrders = Object.entries(openOrders).map(
|
||||
([marketPk, orders]) => ({
|
||||
orders,
|
||||
marketPk,
|
||||
})
|
||||
)
|
||||
|
||||
for (const [key] of orderLines) {
|
||||
oOrders?.forEach(({ orders }) => {
|
||||
for (const order of orders) {
|
||||
if (order.orderId == key) {
|
||||
matchingOrderLines += 1
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const selectedMarket = mangoStore.getState().selectedMarket.current
|
||||
const selectedMarketPk =
|
||||
selectedMarket instanceof Serum3Market
|
||||
? selectedMarket?.serumMarketExternal.toString()
|
||||
: selectedMarket?.publicKey.toString()
|
||||
|
||||
oOrders?.forEach(({ marketPk, orders }) => {
|
||||
if (marketPk === selectedMarketPk) {
|
||||
openOrdersForMarket = orders.length
|
||||
}
|
||||
})
|
||||
|
||||
tvWidgetRef.current?.activeChart().dataReady(() => {
|
||||
if (
|
||||
selectedMarketName?.toLowerCase().includes('perp') &&
|
||||
spotOrPerp !== 'perp'
|
||||
(showOrderLines &&
|
||||
matchingOrderLines !== openOrdersForMarket) ||
|
||||
orderLines?.size !== matchingOrderLines
|
||||
) {
|
||||
setSpotOrPerp('perp')
|
||||
} else if (
|
||||
!selectedMarketName?.toLowerCase().includes('perp') &&
|
||||
spotOrPerp !== 'spot'
|
||||
) {
|
||||
setSpotOrPerp('spot')
|
||||
deleteLines()
|
||||
drawLinesForMarket(openOrders)
|
||||
}
|
||||
}, [selectedMarketName, spotOrPerp])
|
||||
|
||||
useEffect(() => {
|
||||
if (window) {
|
||||
const widgetOptions: ChartingLibraryWidgetOptions = {
|
||||
// debug: true,
|
||||
symbol: selectedMarket,
|
||||
// BEWARE: no trailing slash is expected in feed URL
|
||||
// tslint:disable-next-line:no-any
|
||||
datafeed: spotOrPerp === 'spot' ? SpotDatafeed : PerpDatafeed,
|
||||
interval:
|
||||
defaultProps.interval as ChartingLibraryWidgetOptions['interval'],
|
||||
container:
|
||||
defaultProps.container as ChartingLibraryWidgetOptions['container'],
|
||||
library_path: defaultProps.libraryPath as string,
|
||||
locale: 'en',
|
||||
enabled_features: ['hide_left_toolbar_by_default'],
|
||||
disabled_features: [
|
||||
'use_localstorage_for_settings',
|
||||
'timeframes_toolbar',
|
||||
isMobile ? 'left_toolbar' : '',
|
||||
'show_logo_on_all_charts',
|
||||
'caption_buttons_text_if_possible',
|
||||
'header_settings',
|
||||
// 'header_chart_type',
|
||||
'header_compare',
|
||||
'compare_symbol',
|
||||
'header_screenshot',
|
||||
// 'header_widget_dom_node',
|
||||
// 'header_widget',
|
||||
'header_saveload',
|
||||
'header_undo_redo',
|
||||
'header_interval_dialog_button',
|
||||
'show_interval_dialog_on_key_press',
|
||||
'header_symbol_search',
|
||||
'popup_hints',
|
||||
],
|
||||
fullscreen: defaultProps.fullscreen,
|
||||
autosize: defaultProps.autosize,
|
||||
studies_overrides: defaultProps.studiesOverrides,
|
||||
theme:
|
||||
theme === 'Light' || theme === 'Banana' || theme === 'Lychee'
|
||||
? 'Light'
|
||||
: 'Dark',
|
||||
custom_css_url: '/styles/tradingview.css',
|
||||
loading_screen: {
|
||||
backgroundColor:
|
||||
theme === 'Dark'
|
||||
? COLORS.BKG1.Dark
|
||||
: theme === 'Light'
|
||||
? COLORS.BKG1.Light
|
||||
: theme === 'Mango Classic'
|
||||
? COLORS.BKG1['Mango Classic']
|
||||
: theme === 'Medium'
|
||||
? COLORS.BKG1.Medium
|
||||
: theme === 'Avocado'
|
||||
? COLORS.BKG1.Avocado
|
||||
: theme === 'Blueberry'
|
||||
? COLORS.BKG1.Blueberry
|
||||
: theme === 'Banana'
|
||||
? COLORS.BKG1.Banana
|
||||
: theme === 'Lychee'
|
||||
? COLORS.BKG1.Lychee
|
||||
: theme === 'Olive'
|
||||
? COLORS.BKG1.Olive
|
||||
: COLORS.BKG1['High Contrast'],
|
||||
},
|
||||
overrides: {
|
||||
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
|
||||
|
||||
...chartStyleOverrides,
|
||||
},
|
||||
})
|
||||
})
|
||||
}
|
||||
)
|
||||
}
|
||||
return subscription
|
||||
}, [chartReady, showOrderLines])
|
||||
|
||||
const tvWidget = new widget(widgetOptions)
|
||||
tvWidgetRef.current = tvWidget
|
||||
|
||||
tvWidgetRef.current.onChartReady(function () {
|
||||
if (showStablePrice && stablePrice) {
|
||||
const drawLinesForMarket = (
|
||||
openOrders: Record<string, Order[] | PerpOrder[]>
|
||||
) => {
|
||||
const set = mangoStore.getState().set
|
||||
set((s) => {
|
||||
s.tradingView.stablePriceLine = drawStablePriceLine(stablePrice)
|
||||
const newOrderLines = new Map()
|
||||
const oOrders = Object.entries(openOrders).map(([marketPk, orders]) => ({
|
||||
orders,
|
||||
marketPk,
|
||||
}))
|
||||
if (oOrders?.length) {
|
||||
const selectedMarket = mangoStore.getState().selectedMarket.current
|
||||
const selectedMarketPk =
|
||||
selectedMarket instanceof Serum3Market
|
||||
? selectedMarket?.serumMarketExternal.toString()
|
||||
: selectedMarket?.publicKey.toString()
|
||||
for (const { orders, marketPk } of oOrders) {
|
||||
if (marketPk === selectedMarketPk) {
|
||||
for (const order of orders) {
|
||||
newOrderLines.set(order.orderId.toString(), drawLine(order))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
set((state) => {
|
||||
state.tradingView.orderLines = newOrderLines
|
||||
})
|
||||
}
|
||||
createStablePriceButton()
|
||||
setChartReady(true)
|
||||
|
||||
const deleteLines = () => {
|
||||
const set = mangoStore.getState().set
|
||||
const orderLines = mangoStore.getState().tradingView.orderLines
|
||||
if (orderLines.size > 0) {
|
||||
orderLines?.forEach((value: IOrderLineAdapter, key: string | BN) => {
|
||||
orderLines.get(key)?.remove()
|
||||
})
|
||||
|
||||
set((state) => {
|
||||
state.tradingView.orderLines = new Map()
|
||||
})
|
||||
//eslint-disable-next-line
|
||||
}
|
||||
}, [theme, isMobile, defaultProps, spotOrPerp])
|
||||
}
|
||||
|
||||
function getOrderDecimals() {
|
||||
const selectedMarket = mangoStore.getState().selectedMarket.current
|
||||
let minOrderDecimals = 4
|
||||
let tickSizeDecimals = 2
|
||||
if (!selectedMarket) return [minOrderDecimals, tickSizeDecimals]
|
||||
if (selectedMarket instanceof PerpMarket) {
|
||||
minOrderDecimals = getDecimalCount(selectedMarket.minOrderSize)
|
||||
tickSizeDecimals = getDecimalCount(selectedMarket.tickSize)
|
||||
} else {
|
||||
const group = mangoStore.getState().group
|
||||
const market = group?.getSerum3ExternalMarket(
|
||||
selectedMarket.serumMarketExternal
|
||||
)
|
||||
if (market) {
|
||||
minOrderDecimals = getDecimalCount(market.minOrderSize)
|
||||
tickSizeDecimals = getDecimalCount(market.tickSize)
|
||||
}
|
||||
}
|
||||
return [minOrderDecimals, tickSizeDecimals]
|
||||
}
|
||||
|
||||
function drawLine(order: Order | PerpOrder) {
|
||||
const side =
|
||||
typeof order.side === 'string'
|
||||
? t(order.side)
|
||||
: 'bid' in order.side
|
||||
? t('trade:long')
|
||||
: t('trade:short')
|
||||
const isLong = side === 'buy' || side === 'long'
|
||||
const isShort = side === 'sell' || side === 'short'
|
||||
const [minOrderDecimals, tickSizeDecimals] = getOrderDecimals()
|
||||
const orderSizeUi: string = formatNumericValue(order.size, minOrderDecimals)
|
||||
if (!tvWidgetRef?.current?.chart()) return
|
||||
return (
|
||||
tvWidgetRef.current
|
||||
.chart()
|
||||
.createOrderLine({ disableUndo: false })
|
||||
.onMove(function (this: IOrderLineAdapter) {
|
||||
const currentOrderPrice = order.price
|
||||
const updatedOrderPrice = this.getPrice()
|
||||
const selectedMarketPrice =
|
||||
mangoStore.getState().selectedMarket.markPrice
|
||||
if (
|
||||
(isLong && updatedOrderPrice > 1.05 * selectedMarketPrice) ||
|
||||
(isShort && updatedOrderPrice < 0.95 * selectedMarketPrice)
|
||||
) {
|
||||
tvWidgetRef.current?.showNoticeDialog({
|
||||
title: t('tv-chart:outside-range'),
|
||||
body:
|
||||
t('tv-chart:slippage-warning', {
|
||||
updatedOrderPrice: updatedOrderPrice,
|
||||
aboveBelow:
|
||||
side == 'buy' || side === 'long' ? t('above') : t('below'),
|
||||
selectedMarketPrice: selectedMarketPrice,
|
||||
}) +
|
||||
'<p><p>' +
|
||||
t('tv-chart:slippage-accept'),
|
||||
callback: () => {
|
||||
this.setPrice(currentOrderPrice)
|
||||
},
|
||||
})
|
||||
} else {
|
||||
tvWidgetRef.current?.showConfirmDialog({
|
||||
title: t('tv-chart:modify-order'),
|
||||
body: t('tv-chart:modify-order-details', {
|
||||
marketName: selectedMarketName,
|
||||
orderSize: orderSizeUi,
|
||||
orderSide: side.toUpperCase(),
|
||||
currentOrderPrice: formatNumericValue(
|
||||
currentOrderPrice,
|
||||
tickSizeDecimals
|
||||
),
|
||||
updatedOrderPrice: formatNumericValue(
|
||||
updatedOrderPrice,
|
||||
tickSizeDecimals
|
||||
),
|
||||
}),
|
||||
callback: (res) => {
|
||||
if (res) {
|
||||
modifyOrder(order, updatedOrderPrice)
|
||||
} else {
|
||||
this.setPrice(currentOrderPrice)
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
})
|
||||
.onCancel(function () {
|
||||
tvWidgetRef.current?.showConfirmDialog({
|
||||
title: t('tv-chart:cancel-order'),
|
||||
body: t('tv-chart:cancel-order-details', {
|
||||
marketName: selectedMarketName,
|
||||
orderSize: orderSizeUi,
|
||||
orderSide: side.toUpperCase(),
|
||||
orderPrice: formatNumericValue(order.price, tickSizeDecimals),
|
||||
}),
|
||||
callback: (res) => {
|
||||
if (res) {
|
||||
if (order instanceof PerpOrder) {
|
||||
cancelPerpOrder(order)
|
||||
} else {
|
||||
cancelSpotOrder(order)
|
||||
}
|
||||
}
|
||||
},
|
||||
})
|
||||
})
|
||||
.setPrice(order.price)
|
||||
.setQuantity(orderSizeUi)
|
||||
.setText(side.toUpperCase())
|
||||
// .setTooltip(
|
||||
// order.perpTrigger?.clientOrderId
|
||||
// ? `${order.orderType} Order #: ${order.orderId}`
|
||||
// : `Order #: ${order.orderId}`
|
||||
// )
|
||||
.setBodyTextColor(isLong ? COLORS.UP[theme] : COLORS.DOWN[theme])
|
||||
.setQuantityTextColor(isLong ? COLORS.UP[theme] : COLORS.DOWN[theme])
|
||||
.setCancelButtonIconColor(COLORS.FGD4[theme])
|
||||
.setBodyBorderColor(isLong ? COLORS.UP[theme] : COLORS.DOWN[theme])
|
||||
.setQuantityBorderColor(isLong ? COLORS.UP[theme] : COLORS.DOWN[theme])
|
||||
.setCancelButtonBorderColor(
|
||||
isLong ? COLORS.UP[theme] : COLORS.DOWN[theme]
|
||||
)
|
||||
.setBodyBackgroundColor(COLORS.BKG1[theme])
|
||||
.setQuantityBackgroundColor(COLORS.BKG1[theme])
|
||||
.setCancelButtonBackgroundColor(COLORS.BKG1[theme])
|
||||
.setLineColor(isLong ? COLORS.UP[theme] : COLORS.DOWN[theme])
|
||||
.setLineLength(3)
|
||||
.setLineWidth(1)
|
||||
.setLineStyle(1)
|
||||
)
|
||||
}
|
||||
|
||||
const modifyOrder = useCallback(
|
||||
async (o: PerpOrder | Order, price: number) => {
|
||||
const client = mangoStore.getState().client
|
||||
const group = mangoStore.getState().group
|
||||
const mangoAccount = mangoStore.getState().mangoAccount.current
|
||||
const actions = mangoStore.getState().actions
|
||||
const baseSize = o.size
|
||||
if (!group || !mangoAccount) return
|
||||
try {
|
||||
let tx = ''
|
||||
if (o instanceof PerpOrder) {
|
||||
tx = await client.modifyPerpOrder(
|
||||
group,
|
||||
mangoAccount,
|
||||
o.perpMarketIndex,
|
||||
o.orderId,
|
||||
o.side,
|
||||
price,
|
||||
Math.abs(baseSize),
|
||||
undefined, // maxQuoteQuantity
|
||||
Date.now(),
|
||||
PerpOrderType.limit,
|
||||
undefined,
|
||||
undefined
|
||||
)
|
||||
} else {
|
||||
const marketPk = findSerum3MarketPkInOpenOrders(o)
|
||||
if (!marketPk) return
|
||||
const market = group.getSerum3MarketByExternalMarket(
|
||||
new PublicKey(marketPk)
|
||||
)
|
||||
tx = await client.modifySerum3Order(
|
||||
group,
|
||||
o.orderId,
|
||||
mangoAccount,
|
||||
market.serumMarketExternal,
|
||||
o.side === 'buy' ? Serum3Side.bid : Serum3Side.ask,
|
||||
price,
|
||||
baseSize,
|
||||
Serum3SelfTradeBehavior.decrementTake,
|
||||
Serum3OrderType.limit,
|
||||
Date.now(),
|
||||
10
|
||||
)
|
||||
}
|
||||
actions.fetchOpenOrders()
|
||||
notify({
|
||||
type: 'success',
|
||||
title: 'Transaction successful',
|
||||
txid: tx,
|
||||
})
|
||||
} catch (e: any) {
|
||||
console.error('Error canceling', e)
|
||||
notify({
|
||||
title: 'Unable to modify order',
|
||||
description: e.message,
|
||||
txid: e.txid,
|
||||
type: 'error',
|
||||
})
|
||||
}
|
||||
},
|
||||
[t]
|
||||
)
|
||||
|
||||
const cancelSpotOrder = useCallback(
|
||||
async (o: Order) => {
|
||||
const client = mangoStore.getState().client
|
||||
const group = mangoStore.getState().group
|
||||
const mangoAccount = mangoStore.getState().mangoAccount.current
|
||||
const actions = mangoStore.getState().actions
|
||||
if (!group || !mangoAccount) return
|
||||
const marketPk = findSerum3MarketPkInOpenOrders(o)
|
||||
if (!marketPk) return
|
||||
const market = group.getSerum3MarketByExternalMarket(
|
||||
new PublicKey(marketPk)
|
||||
)
|
||||
try {
|
||||
const tx = await client.serum3CancelOrder(
|
||||
group,
|
||||
mangoAccount,
|
||||
market!.serumMarketExternal,
|
||||
o.side === 'buy' ? Serum3Side.bid : Serum3Side.ask,
|
||||
o.orderId
|
||||
)
|
||||
|
||||
actions.fetchOpenOrders()
|
||||
notify({
|
||||
type: 'success',
|
||||
title: 'Transaction successful',
|
||||
txid: tx,
|
||||
})
|
||||
} catch (e: any) {
|
||||
console.error('Error canceling', e)
|
||||
notify({
|
||||
title: t('trade:cancel-order-error'),
|
||||
description: e.message,
|
||||
txid: e.txid,
|
||||
type: 'error',
|
||||
})
|
||||
}
|
||||
},
|
||||
[t]
|
||||
)
|
||||
|
||||
const cancelPerpOrder = useCallback(
|
||||
async (o: PerpOrder) => {
|
||||
const client = mangoStore.getState().client
|
||||
const group = mangoStore.getState().group
|
||||
const mangoAccount = mangoStore.getState().mangoAccount.current
|
||||
const actions = mangoStore.getState().actions
|
||||
if (!group || !mangoAccount) return
|
||||
try {
|
||||
const tx = await client.perpCancelOrder(
|
||||
group,
|
||||
mangoAccount,
|
||||
o.perpMarketIndex,
|
||||
o.orderId
|
||||
)
|
||||
actions.fetchOpenOrders()
|
||||
notify({
|
||||
type: 'success',
|
||||
title: 'Transaction successful',
|
||||
txid: tx,
|
||||
})
|
||||
} catch (e: any) {
|
||||
console.error('Error canceling', e)
|
||||
notify({
|
||||
title: t('trade:cancel-order-error'),
|
||||
description: e.message,
|
||||
txid: e.txid,
|
||||
type: 'error',
|
||||
})
|
||||
}
|
||||
},
|
||||
[t]
|
||||
)
|
||||
|
||||
const findSerum3MarketPkInOpenOrders = (o: Order): string | undefined => {
|
||||
const openOrders = mangoStore.getState().mangoAccount.openOrders
|
||||
let foundedMarketPk: string | undefined = undefined
|
||||
for (const [marketPk, orders] of Object.entries(openOrders)) {
|
||||
for (const order of orders) {
|
||||
if (order.orderId.eq(o.orderId)) {
|
||||
foundedMarketPk = marketPk
|
||||
break
|
||||
}
|
||||
}
|
||||
if (foundedMarketPk) {
|
||||
break
|
||||
}
|
||||
}
|
||||
return foundedMarketPk
|
||||
}
|
||||
|
||||
return (
|
||||
<div id={defaultProps.container as string} className="tradingview-chart" />
|
||||
|
|
|
@ -17,6 +17,7 @@ import useMangoAccount from 'hooks/useMangoAccount'
|
|||
import { useWallet } from '@solana/wallet-adapter-react'
|
||||
import ConnectEmptyState from '@components/shared/ConnectEmptyState'
|
||||
import FormatNumericValue from '@components/shared/FormatNumericValue'
|
||||
import useUnownedAccount from 'hooks/useUnownedAccount'
|
||||
|
||||
const UnsettledTrades = ({
|
||||
unsettledSpotBalances,
|
||||
|
@ -32,6 +33,7 @@ const UnsettledTrades = ({
|
|||
const showTableView = width ? width > breakpoints.md : false
|
||||
const { mangoAccountAddress } = useMangoAccount()
|
||||
const { connected } = useWallet()
|
||||
const isUnownedAccount = useUnownedAccount()
|
||||
|
||||
const handleSettleSerumFunds = useCallback(async (mktAddress: string) => {
|
||||
const client = mangoStore.getState().client
|
||||
|
@ -136,7 +138,9 @@ const UnsettledTrades = ({
|
|||
<TrHead>
|
||||
<Th className="bg-th-bkg-1 text-left">{t('market')}</Th>
|
||||
<Th className="bg-th-bkg-1 text-right">{t('trade:amount')}</Th>
|
||||
{!isUnownedAccount ? (
|
||||
<Th className="bg-th-bkg-1 text-right" />
|
||||
) : null}
|
||||
</TrHead>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
@ -156,18 +160,23 @@ const UnsettledTrades = ({
|
|||
<div className="flex justify-end">
|
||||
{unsettledSpotBalances[mktAddress].base ? (
|
||||
<div>
|
||||
{unsettledSpotBalances[mktAddress].base}{' '}
|
||||
<FormatNumericValue
|
||||
value={unsettledSpotBalances[mktAddress].base}
|
||||
/>{' '}
|
||||
<span className="font-body text-th-fgd-4">{base}</span>
|
||||
</div>
|
||||
) : null}
|
||||
{unsettledSpotBalances[mktAddress].quote ? (
|
||||
<div className="ml-4">
|
||||
{unsettledSpotBalances[mktAddress].quote}{' '}
|
||||
<FormatNumericValue
|
||||
value={unsettledSpotBalances[mktAddress].quote}
|
||||
/>{' '}
|
||||
<span className="font-body text-th-fgd-4">{quote}</span>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
</Td>
|
||||
{!isUnownedAccount ? (
|
||||
<Td>
|
||||
<div className="flex justify-end">
|
||||
<Tooltip content={t('trade:settle-funds')}>
|
||||
|
@ -184,6 +193,7 @@ const UnsettledTrades = ({
|
|||
</Tooltip>
|
||||
</div>
|
||||
</Td>
|
||||
) : null}
|
||||
</TrBody>
|
||||
)
|
||||
})}
|
||||
|
@ -203,6 +213,7 @@ const UnsettledTrades = ({
|
|||
/>{' '}
|
||||
<span className="font-body text-th-fgd-4">USDC</span>
|
||||
</Td>
|
||||
{!isUnownedAccount ? (
|
||||
<Td>
|
||||
<div className="flex justify-end">
|
||||
<Tooltip content={t('trade:settle-funds')}>
|
||||
|
@ -219,13 +230,47 @@ const UnsettledTrades = ({
|
|||
</Tooltip>
|
||||
</div>
|
||||
</Td>
|
||||
) : null}
|
||||
</TrBody>
|
||||
)
|
||||
})}
|
||||
</tbody>
|
||||
</Table>
|
||||
) : (
|
||||
<div className="pb-20">
|
||||
<div>
|
||||
{unsettledPerpPositions.map((position) => {
|
||||
const market = group.getPerpMarketByMarketIndex(position.marketIndex)
|
||||
|
||||
return (
|
||||
<div
|
||||
key={position.marketIndex}
|
||||
className="flex items-center justify-between border-b border-th-bkg-3 p-4"
|
||||
>
|
||||
<TableMarketName market={market} />
|
||||
<div className="flex items-center space-x-3">
|
||||
<div>
|
||||
<FormatNumericValue
|
||||
value={position.getUnsettledPnlUi(market)}
|
||||
decimals={market.baseDecimals}
|
||||
/>{' '}
|
||||
<span className="font-body text-th-fgd-4">USDC</span>
|
||||
</div>
|
||||
{!isUnownedAccount ? (
|
||||
<IconButton
|
||||
onClick={() => handleSettlePerpFunds(market)}
|
||||
size="medium"
|
||||
>
|
||||
{settleMktAddress === market.publicKey.toString() ? (
|
||||
<Loading className="h-4 w-4" />
|
||||
) : (
|
||||
<CheckIcon className="h-4 w-4" />
|
||||
)}
|
||||
</IconButton>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
{Object.entries(unsettledSpotBalances).map(([mktAddress]) => {
|
||||
const market = group.getSerum3MarketByExternalMarket(
|
||||
new PublicKey(mktAddress)
|
||||
|
@ -242,16 +287,21 @@ const UnsettledTrades = ({
|
|||
<div className="flex items-center space-x-3">
|
||||
{unsettledSpotBalances[mktAddress].base ? (
|
||||
<span className="font-mono text-sm">
|
||||
{unsettledSpotBalances[mktAddress].base}{' '}
|
||||
<FormatNumericValue
|
||||
value={unsettledSpotBalances[mktAddress].base}
|
||||
/>{' '}
|
||||
<span className="font-body text-th-fgd-4">{base}</span>
|
||||
</span>
|
||||
) : null}
|
||||
{unsettledSpotBalances[mktAddress].quote ? (
|
||||
<span className="font-mono text-sm">
|
||||
{unsettledSpotBalances[mktAddress].quote}{' '}
|
||||
<FormatNumericValue
|
||||
value={unsettledSpotBalances[mktAddress].quote}
|
||||
/>{' '}
|
||||
<span className="font-body text-th-fgd-4">{quote}</span>
|
||||
</span>
|
||||
) : null}
|
||||
{!isUnownedAccount ? (
|
||||
<IconButton
|
||||
onClick={() => handleSettleSerumFunds(mktAddress)}
|
||||
size="medium"
|
||||
|
@ -262,6 +312,7 @@ const UnsettledTrades = ({
|
|||
<CheckIcon className="h-4 w-4" />
|
||||
)}
|
||||
</IconButton>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
|
|
@ -27,7 +27,7 @@ export const ConnectWalletButton: React.FC = () => {
|
|||
disabled={!groupLoaded}
|
||||
className={` text-white focus:outline-none disabled:cursor-wait disabled:opacity-25`}
|
||||
>
|
||||
<div className="relative flex h-16 w-44 bg-th-bkg-2 py-2 before:absolute before:inset-0 before:bg-gradient-to-r before:from-transparent before:via-th-bkg-4 before:to-transparent before:opacity-0 hover:overflow-hidden hover:before:-translate-x-full hover:before:animate-[shimmer_0.75s_normal] hover:before:opacity-100">
|
||||
<div className="relative flex h-16 w-44 bg-th-bkg-3 py-2 before:absolute before:inset-0 before:bg-gradient-to-r before:from-transparent before:via-th-bkg-4 before:to-transparent before:opacity-0 hover:overflow-hidden hover:before:-translate-x-full hover:before:animate-[shimmer_0.75s_normal] hover:before:opacity-100">
|
||||
<div className="default-transition relative z-10 flex h-full items-center justify-center space-x-3 px-4">
|
||||
{connecting ? (
|
||||
<Loading className="h-[28px] w-[28px]" />
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
import { useWallet } from '@solana/wallet-adapter-react'
|
||||
import { useMemo } from 'react'
|
||||
import useMangoAccount from './useMangoAccount'
|
||||
|
||||
const useUnownedAccount = () => {
|
||||
const { connected } = useWallet()
|
||||
const { mangoAccountAddress } = useMangoAccount()
|
||||
|
||||
const isUnownedAccount = useMemo(() => {
|
||||
if (connected) return false
|
||||
return mangoAccountAddress && !connected
|
||||
}, [connected, mangoAccountAddress])
|
||||
|
||||
return isUnownedAccount
|
||||
}
|
||||
|
||||
export default useUnownedAccount
|
|
@ -230,13 +230,6 @@ const Dashboard: NextPage = () => {
|
|||
label="Init Asset/Liab Weight"
|
||||
value={`${bank.initAssetWeight.toFixed(2)}/
|
||||
${bank.initLiabWeight.toFixed(2)}`}
|
||||
/>
|
||||
<KeyValuePair
|
||||
label="Scaled Init Asset/Liab Weight"
|
||||
value={`${bank
|
||||
.scaledInitAssetWeight()
|
||||
.toFixed(4)}/
|
||||
${bank.scaledInitLiabWeight().toFixed(4)}`}
|
||||
/>
|
||||
<KeyValuePair
|
||||
label="Deposit weight scale start quote"
|
||||
|
|
|
@ -1,13 +1,15 @@
|
|||
import ExplorerLink from '@components/shared/ExplorerLink'
|
||||
import useMangoGroup from 'hooks/useMangoGroup'
|
||||
import type { NextPage } from 'next'
|
||||
import { ReactNode } from 'react'
|
||||
import { ReactNode, useCallback, useEffect, useState } from 'react'
|
||||
import { serverSideTranslations } from 'next-i18next/serverSideTranslations'
|
||||
import useMangoAccount from 'hooks/useMangoAccount'
|
||||
import {
|
||||
toUiDecimalsForQuote,
|
||||
HealthType,
|
||||
PerpOrder,
|
||||
} from '@blockworks-foundation/mango-v4'
|
||||
import mangoStore from '@store/mangoStore'
|
||||
|
||||
export async function getStaticProps({ locale }: { locale: string }) {
|
||||
return {
|
||||
|
@ -22,6 +24,29 @@ const Dashboard: NextPage = () => {
|
|||
// const { mangoTokens } = useJupiterMints()
|
||||
// const client = mangoStore(s => s.client)
|
||||
const { mangoAccount } = useMangoAccount()
|
||||
const client = mangoStore((s) => s.client)
|
||||
const [openOrders, setOpenOrders] = useState<Record<string, PerpOrder[]>>()
|
||||
|
||||
useEffect(() => {
|
||||
if (mangoAccount) {
|
||||
loadOpenOrders()
|
||||
}
|
||||
}, [mangoAccount])
|
||||
|
||||
const loadOpenOrders = useCallback(async () => {
|
||||
if (!mangoAccount || !group) return
|
||||
const openOrders: Record<string, any> = {}
|
||||
for (const perpOrder of mangoAccount.perpOrdersActive()) {
|
||||
const market = group.getPerpMarketByMarketIndex(perpOrder.orderMarket)
|
||||
const orders = await mangoAccount.loadPerpOpenOrdersForMarket(
|
||||
client,
|
||||
group,
|
||||
perpOrder.orderMarket
|
||||
)
|
||||
openOrders[market.publicKey.toString()] = orders
|
||||
}
|
||||
setOpenOrders(openOrders)
|
||||
}, [mangoAccount, client, group])
|
||||
|
||||
return (
|
||||
<div className="grid grid-cols-12">
|
||||
|
@ -222,6 +247,49 @@ const Dashboard: NextPage = () => {
|
|||
</div>
|
||||
)
|
||||
})}
|
||||
|
||||
<h3 className="mt-4">Perp Open Orders</h3>
|
||||
{openOrders
|
||||
? Object.entries(openOrders).map(
|
||||
([marketAddress, openOrders]) => {
|
||||
return (
|
||||
<div key={marketAddress} className="mt-4">
|
||||
<KeyValuePair
|
||||
label="Market Address"
|
||||
value={<ExplorerLink address={marketAddress} />}
|
||||
/>
|
||||
{openOrders.map((openOrder) => {
|
||||
return (
|
||||
<div
|
||||
key={`${openOrder.orderId}${openOrder.side}${openOrder.seqNum}`}
|
||||
className="mt-4 rounded border border-th-bkg-3 px-2"
|
||||
>
|
||||
<KeyValuePair
|
||||
label="Side"
|
||||
value={
|
||||
openOrder.side
|
||||
? 'bid' in openOrder.side
|
||||
? 'Bid'
|
||||
: 'Ask'
|
||||
: null
|
||||
}
|
||||
/>
|
||||
<KeyValuePair
|
||||
label="Price"
|
||||
value={openOrder.price}
|
||||
/>
|
||||
<KeyValuePair
|
||||
label="Size"
|
||||
value={openOrder.size}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
)
|
||||
: null}
|
||||
</div>
|
||||
) : (
|
||||
'Loading'
|
||||
|
|
|
@ -14,5 +14,6 @@
|
|||
"settle-balances": "Settle all balances",
|
||||
"transaction-confirmed": "Transaction Confirmed",
|
||||
"withdraw-assets-worth": "Withdraw assets worth {{value}}",
|
||||
"you-must": "Before you can close your account"
|
||||
"you-must": "Before you can close your account",
|
||||
"account-closed": "Account Closed 👋"
|
||||
}
|
|
@ -22,6 +22,7 @@
|
|||
"instantaneous-funding": "Instantaneous Funding",
|
||||
"interval-seconds": "Interval (seconds)",
|
||||
"limit-price": "Limit Price",
|
||||
"long": "Long",
|
||||
"margin": "Margin",
|
||||
"no-balances": "No balances",
|
||||
"no-orders": "No open orders",
|
||||
|
@ -46,6 +47,7 @@
|
|||
"sells": "Sells",
|
||||
"settle-funds": "Settle Funds",
|
||||
"settle-funds-error": "Failed to settle funds",
|
||||
"short": "Short",
|
||||
"show-asks": "Show Asks",
|
||||
"show-bids": "Show Bids",
|
||||
"side": "Side",
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
{
|
||||
"advanced-order": "Advanced Order Type",
|
||||
"advanced-order-details": "Advanced order types in the chart window may only be cancelled. If new conditions are required, please cancel this order and use the Advanced Trade Form.",
|
||||
"cancel-order": "Cancel Your Order?",
|
||||
"cancel-order-details": "Would you like to cancel your order for {{orderSize}} {{baseSymbol}} {{orderSide}} at ${{orderPrice}}?",
|
||||
"modify-order": "Modify Your Order?",
|
||||
"modify-order-details": "Would you like to change your order from a {{orderSize}} {{baseSymbol}} {{orderSide}} at ${{currentOrderPrice}} to a {{orderSize}} {{baseSymbol}} LIMIT {{orderSide}} at ${{updatedOrderPrice}}?",
|
||||
"advanced-order-details": "Advanced order types in the chart window may only be cancelled. If new conditions are required, cancel this order and use the trade order form.",
|
||||
"cancel-order": "Cancel Order",
|
||||
"cancel-order-details": "Cancel your order for {{orderSide}} {{orderSize}} {{marketName}} at {{orderPrice}}",
|
||||
"modify-order": "Modify Order",
|
||||
"modify-order-details": "Edit your {{marketName}} order from {{orderSide}} {{orderSize}} at {{currentOrderPrice}} to {{orderSide}} {{orderSize}} at {{updatedOrderPrice}}",
|
||||
"order-details": " ({{orderType}} {{orderSide}}) if price is {{triggerCondition}} {{triggerPrice}}",
|
||||
"outside-range": "Order Price Outside Range",
|
||||
"slippage-accept": "Please use the trade input form if you wish to accept the potential slippage.",
|
||||
"slippage-warning": "Your order price ({{updatedOrderPrice}}) is greater than 5% {{aboveBelow}} the current market price ({{selectedMarketPrice}}) indicating you might incur significant slippage.",
|
||||
"toggle-stable-price": "Toggle stable price line",
|
||||
"slippage-accept": "Use the trade order form if you wish to accept the potential slippage.",
|
||||
"slippage-warning": "{{updatedOrderPrice}} is greater than 5% {{aboveBelow}} the current market price of {{selectedMarketPrice}}. Executing this trade could incur significant slippage.",
|
||||
"toggle-order-line": "Toggle order line visibility",
|
||||
"toggle-stable-price": "Toggle stable price line"
|
||||
"toggle-trade-executions": "Toggle trade execution visibility"
|
||||
}
|
|
@ -14,5 +14,6 @@
|
|||
"settle-balances": "Settle all balances",
|
||||
"transaction-confirmed": "Transaction Confirmed",
|
||||
"withdraw-assets-worth": "Withdraw assets worth {{value}}",
|
||||
"you-must": "Before you can close your account"
|
||||
"you-must": "Before you can close your account",
|
||||
"account-closed": "Account Closed 👋"
|
||||
}
|
|
@ -22,6 +22,7 @@
|
|||
"instantaneous-funding": "Instantaneous Funding",
|
||||
"interval-seconds": "Interval (seconds)",
|
||||
"limit-price": "Limit Price",
|
||||
"long": "Long",
|
||||
"margin": "Margin",
|
||||
"no-balances": "No balances",
|
||||
"no-orders": "No open orders",
|
||||
|
@ -46,6 +47,7 @@
|
|||
"sells": "Sells",
|
||||
"settle-funds": "Settle Funds",
|
||||
"settle-funds-error": "Failed to settle funds",
|
||||
"short": "Short",
|
||||
"show-asks": "Show Asks",
|
||||
"show-bids": "Show Bids",
|
||||
"side": "Side",
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
{
|
||||
"advanced-order": "Advanced Order Type",
|
||||
"advanced-order-details": "Advanced order types in the chart window may only be cancelled. If new conditions are required, please cancel this order and use the Advanced Trade Form.",
|
||||
"cancel-order": "Cancel Your Order?",
|
||||
"cancel-order-details": "Would you like to cancel your order for {{orderSize}} {{baseSymbol}} {{orderSide}} at ${{orderPrice}}?",
|
||||
"modify-order": "Modify Your Order?",
|
||||
"modify-order-details": "Would you like to change your order from a {{orderSize}} {{baseSymbol}} {{orderSide}} at ${{currentOrderPrice}} to a {{orderSize}} {{baseSymbol}} LIMIT {{orderSide}} at ${{updatedOrderPrice}}?",
|
||||
"advanced-order-details": "Advanced order types in the chart window may only be cancelled. If new conditions are required, cancel this order and use the trade order form.",
|
||||
"cancel-order": "Cancel Order",
|
||||
"cancel-order-details": "Cancel your order for {{orderSide}} {{orderSize}} {{marketName}} at {{orderPrice}}",
|
||||
"modify-order": "Modify Order",
|
||||
"modify-order-details": "Edit your {{marketName}} order from {{orderSide}} {{orderSize}} at {{currentOrderPrice}} to {{orderSide}} {{orderSize}} at {{updatedOrderPrice}}",
|
||||
"order-details": " ({{orderType}} {{orderSide}}) if price is {{triggerCondition}} {{triggerPrice}}",
|
||||
"outside-range": "Order Price Outside Range",
|
||||
"slippage-accept": "Please use the trade input form if you wish to accept the potential slippage.",
|
||||
"slippage-warning": "Your order price ({{updatedOrderPrice}}) is greater than 5% {{aboveBelow}} the current market price ({{selectedMarketPrice}}) indicating you might incur significant slippage.",
|
||||
"toggle-stable-price": "Toggle stable price line",
|
||||
"slippage-accept": "Use the trade order form if you wish to accept the potential slippage.",
|
||||
"slippage-warning": "{{updatedOrderPrice}} is greater than 5% {{aboveBelow}} the current market price of {{selectedMarketPrice}}. Executing this trade could incur significant slippage.",
|
||||
"toggle-order-line": "Toggle order line visibility",
|
||||
"toggle-stable-price": "Toggle stable price line"
|
||||
"toggle-trade-executions": "Toggle trade execution visibility"
|
||||
}
|
|
@ -14,5 +14,6 @@
|
|||
"settle-balances": "Settle all balances",
|
||||
"transaction-confirmed": "Transaction Confirmed",
|
||||
"withdraw-assets-worth": "Withdraw assets worth {{value}}",
|
||||
"you-must": "Before you can close your account"
|
||||
"you-must": "Before you can close your account",
|
||||
"account-closed": "Account Closed 👋"
|
||||
}
|
|
@ -22,6 +22,7 @@
|
|||
"instantaneous-funding": "Instantaneous Funding",
|
||||
"interval-seconds": "Interval (seconds)",
|
||||
"limit-price": "Limit Price",
|
||||
"long": "Long",
|
||||
"margin": "Margin",
|
||||
"no-balances": "No balances",
|
||||
"no-orders": "No open orders",
|
||||
|
@ -46,6 +47,7 @@
|
|||
"sells": "Sells",
|
||||
"settle-funds": "Settle Funds",
|
||||
"settle-funds-error": "Failed to settle funds",
|
||||
"short": "Short",
|
||||
"show-asks": "Show Asks",
|
||||
"show-bids": "Show Bids",
|
||||
"side": "Side",
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
{
|
||||
"advanced-order": "高級訂單類型",
|
||||
"advanced-order-details": "在圖表窗口中高級訂單類型只能取消。如果需要新條件,請取消此訂單並使用高級交易表格進行。",
|
||||
"cancel-order": "取消訂單嗎?",
|
||||
"cancel-order-details": "您確定要取消{{orderSize}} {{baseSymbol}} {{orderSide}} 價格${{orderPrice}}的掛單嗎?",
|
||||
"modify-order": "改您的訂單嗎?",
|
||||
"modify-order-details": "您確定要把{{orderSize}} {{baseSymbol}}{{orderSide}} 價格${{currentOrderPrice}}的掛單改成{{orderSize}} {{baseSymbol}}限價{{orderSide}} 價格${{updatedOrderPrice}}嗎?",
|
||||
"order-details": "({{orderType}}{{orderSide}})若價格{{triggerCondition}}{{triggerPrice}}",
|
||||
"outside-range": "訂單價格在範圍之外",
|
||||
"slippage-accept": "若您接受潛在的下滑請使用交易表格進行。",
|
||||
"slippage-warning": "您的訂單價格({{updatedOrderPrice}})多餘5%{{aboveBelow}}市場價格({{selectedMarketPrice}})表是您也許遭受可觀的下滑。",
|
||||
"toggle-order-line": "切換訂單線可見性",
|
||||
"toggle-stable-price": "Toggle stable price line"
|
||||
"advanced-order": "Advanced Order Type",
|
||||
"advanced-order-details": "Advanced order types in the chart window may only be cancelled. If new conditions are required, cancel this order and use the trade order form.",
|
||||
"cancel-order": "Cancel Order",
|
||||
"cancel-order-details": "Cancel your order for {{orderSide}} {{orderSize}} {{marketName}} at {{orderPrice}}",
|
||||
"modify-order": "Modify Order",
|
||||
"modify-order-details": "Edit your {{marketName}} order from {{orderSide}} {{orderSize}} at {{currentOrderPrice}} to {{orderSide}} {{orderSize}} at {{updatedOrderPrice}}",
|
||||
"order-details": " ({{orderType}} {{orderSide}}) if price is {{triggerCondition}} {{triggerPrice}}",
|
||||
"outside-range": "Order Price Outside Range",
|
||||
"toggle-stable-price": "Toggle stable price line",
|
||||
"slippage-accept": "Use the trade order form if you wish to accept the potential slippage.",
|
||||
"slippage-warning": "{{updatedOrderPrice}} is greater than 5% {{aboveBelow}} the current market price of {{selectedMarketPrice}}. Executing this trade could incur significant slippage.",
|
||||
"toggle-order-line": "Toggle order line visibility",
|
||||
"toggle-trade-executions": "Toggle trade execution visibility"
|
||||
}
|
|
@ -14,5 +14,6 @@
|
|||
"settle-balances": "Settle all balances",
|
||||
"transaction-confirmed": "Transaction Confirmed",
|
||||
"withdraw-assets-worth": "Withdraw assets worth {{value}}",
|
||||
"you-must": "Before you can close your account"
|
||||
"you-must": "Before you can close your account",
|
||||
"account-closed": "Account Closed 👋"
|
||||
}
|
|
@ -22,6 +22,7 @@
|
|||
"instantaneous-funding": "Instantaneous Funding",
|
||||
"interval-seconds": "Interval (seconds)",
|
||||
"limit-price": "Limit Price",
|
||||
"long": "Long",
|
||||
"margin": "Margin",
|
||||
"no-balances": "No balances",
|
||||
"no-orders": "No open orders",
|
||||
|
@ -45,6 +46,7 @@
|
|||
"sells": "Sells",
|
||||
"settle-funds": "Settle Funds",
|
||||
"settle-funds-error": "Failed to settle funds",
|
||||
"short": "Short",
|
||||
"show-asks": "Show Asks",
|
||||
"show-bids": "Show Bids",
|
||||
"side": "Side",
|
||||
|
|
|
@ -10,5 +10,6 @@
|
|||
"slippage-accept": "若您接受潜在的下滑请使用交易表格进行。",
|
||||
"slippage-warning": "您的订单价格({{updatedOrderPrice}})多余5%{{aboveBelow}}市场价格({{selectedMarketPrice}})表是您也许遭受可观的下滑。",
|
||||
"toggle-order-line": "切换订单线可见性",
|
||||
"toggle-stable-price": "Toggle stable price line"
|
||||
"toggle-stable-price": "Toggle stable price line",
|
||||
"toggle-trade-executions": "Toggle trade execution visibility"
|
||||
}
|
|
@ -14,5 +14,6 @@
|
|||
"settle-balances": "Settle all balances",
|
||||
"transaction-confirmed": "Transaction Confirmed",
|
||||
"withdraw-assets-worth": "Withdraw assets worth {{value}}",
|
||||
"you-must": "Before you can close your account"
|
||||
"you-must": "Before you can close your account",
|
||||
"account-closed": "Account Closed 👋"
|
||||
}
|
|
@ -22,6 +22,7 @@
|
|||
"instantaneous-funding": "Instantaneous Funding",
|
||||
"interval-seconds": "Interval (seconds)",
|
||||
"limit-price": "Limit Price",
|
||||
"long": "Long",
|
||||
"margin": "Margin",
|
||||
"no-balances": "No balances",
|
||||
"no-orders": "No open orders",
|
||||
|
@ -45,6 +46,7 @@
|
|||
"sells": "Sells",
|
||||
"settle-funds": "Settle Funds",
|
||||
"settle-funds-error": "Failed to settle funds",
|
||||
"short": "Short",
|
||||
"show-asks": "Show Asks",
|
||||
"show-bids": "Show Bids",
|
||||
"side": "Side",
|
||||
|
|
|
@ -10,5 +10,6 @@
|
|||
"slippage-accept": "若您接受潛在的下滑請使用交易表格進行。",
|
||||
"slippage-warning": "您的訂單價格({{updatedOrderPrice}})多餘5%{{aboveBelow}}市場價格({{selectedMarketPrice}})表是您也許遭受可觀的下滑。",
|
||||
"toggle-order-line": "切換訂單線可見性",
|
||||
"toggle-stable-price": "Toggle stable price line"
|
||||
"toggle-stable-price": "Toggle stable price line",
|
||||
"toggle-trade-executions": "Toggle trade execution visibility"
|
||||
}
|
|
@ -2,7 +2,7 @@ import dayjs from 'dayjs'
|
|||
import produce from 'immer'
|
||||
import create from 'zustand'
|
||||
import { subscribeWithSelector } from 'zustand/middleware'
|
||||
import { AnchorProvider, Wallet, web3 } from '@project-serum/anchor'
|
||||
import { AnchorProvider, BN, Wallet, web3 } from '@project-serum/anchor'
|
||||
import { Connection, Keypair, PublicKey } from '@solana/web3.js'
|
||||
import { OpenOrders, Order } from '@project-serum/serum/lib/market'
|
||||
import { Orderbook } from '@project-serum/serum'
|
||||
|
@ -49,7 +49,10 @@ import spotBalancesUpdater from './spotBalancesUpdater'
|
|||
import { PerpMarket } from '@blockworks-foundation/mango-v4/'
|
||||
import perpPositionsUpdater from './perpPositionsUpdater'
|
||||
import { DEFAULT_PRIORITY_FEE } from '@components/settings/RpcSettings'
|
||||
import { EntityId } from '@public/charting_library/charting_library'
|
||||
import {
|
||||
EntityId,
|
||||
IOrderLineAdapter,
|
||||
} from '@public/charting_library/charting_library'
|
||||
|
||||
const GROUP = new PublicKey('78b8f4cGCwmZ9ysPFMWLaLTkkaYnUjwMJYStWe5RTSSX')
|
||||
|
||||
|
@ -95,6 +98,8 @@ const initMangoClient = (
|
|||
})
|
||||
}
|
||||
|
||||
let mangoGroupRetryAttempt = 0
|
||||
|
||||
export interface TotalInterestDataItem {
|
||||
borrow_interest: number
|
||||
deposit_interest: number
|
||||
|
@ -332,6 +337,7 @@ export type MangoStore = {
|
|||
tradeForm: TradeForm
|
||||
tradingView: {
|
||||
stablePriceLine: Map<string, EntityId> | undefined
|
||||
orderLines: Map<string | BN, IOrderLineAdapter>
|
||||
}
|
||||
wallet: {
|
||||
tokens: TokenAccount[]
|
||||
|
@ -479,6 +485,7 @@ const mangoStore = create<MangoStore>()(
|
|||
tradeForm: DEFAULT_TRADE_FORM,
|
||||
tradingView: {
|
||||
stablePriceLine: new Map(),
|
||||
orderLines: new Map(),
|
||||
},
|
||||
wallet: {
|
||||
tokens: [],
|
||||
|
@ -603,7 +610,7 @@ const mangoStore = create<MangoStore>()(
|
|||
state.activityFeed.feed = combinedFeed
|
||||
})
|
||||
} catch (e) {
|
||||
console.log('Failed to fetch account activity feed', e)
|
||||
console.error('Failed to fetch account activity feed', e)
|
||||
} finally {
|
||||
set((state) => {
|
||||
state.activityFeed.loading = false
|
||||
|
@ -656,10 +663,16 @@ const mangoStore = create<MangoStore>()(
|
|||
)
|
||||
}
|
||||
})
|
||||
mangoGroupRetryAttempt = 0
|
||||
} catch (e) {
|
||||
if (mangoGroupRetryAttempt < 2) {
|
||||
// get().actions.fetchGroup()
|
||||
mangoGroupRetryAttempt++
|
||||
} else {
|
||||
notify({ type: 'info', title: 'Unable to refresh data' })
|
||||
console.error('Error fetching group', e)
|
||||
}
|
||||
}
|
||||
},
|
||||
reloadMangoAccount: async () => {
|
||||
const set = get().set
|
||||
|
@ -813,7 +826,9 @@ const mangoStore = create<MangoStore>()(
|
|||
mangoAccount.serum3Active().length &&
|
||||
Object.keys(openOrders).length
|
||||
) {
|
||||
serumOpenOrderAccounts =
|
||||
serumOpenOrderAccounts = Array.from(
|
||||
mangoAccount.serum3OosMapByMarketIndex.values()
|
||||
)
|
||||
await mangoAccount.loadSerum3OpenOrdersAccounts(client)
|
||||
}
|
||||
|
||||
|
|
|
@ -47,6 +47,8 @@ export const PRIORITY_FEE_KEY = 'priorityFeeKey-0.1'
|
|||
|
||||
export const SHOW_STABLE_PRICE_KEY = 'showStablePriceKey-0.1'
|
||||
|
||||
export const SHOW_ORDER_LINES_KEY = 'showOrderLines-0.1'
|
||||
|
||||
// Unused
|
||||
export const PROFILE_CATEGORIES = [
|
||||
'borrower',
|
||||
|
|
313
yarn.lock
313
yarn.lock
|
@ -24,12 +24,12 @@
|
|||
|
||||
"@blockworks-foundation/mango-v4@https://github.com/blockworks-foundation/mango-v4.git#ts-client":
|
||||
version "0.4.3"
|
||||
resolved "https://github.com/blockworks-foundation/mango-v4.git#35763da947e3b15175dcee5c81633e409803b2f7"
|
||||
resolved "https://github.com/blockworks-foundation/mango-v4.git#c0af34311455de5685387a80812a938215025a6f"
|
||||
dependencies:
|
||||
"@project-serum/anchor" "^0.25.0"
|
||||
"@project-serum/serum" "^0.13.65"
|
||||
"@pythnetwork/client" "~2.8.0"
|
||||
"@solana/spl-token" "0.2.0"
|
||||
"@pythnetwork/client" "~2.14.0"
|
||||
"@solana/spl-token" "0.3.7"
|
||||
"@solana/web3.js" "^1.63.1"
|
||||
"@switchboard-xyz/sbv2-lite" "^0.1.6"
|
||||
big.js "^6.1.1"
|
||||
|
@ -37,7 +37,6 @@
|
|||
bs58 "^5.0.0"
|
||||
cross-fetch "^3.1.5"
|
||||
dotenv "^16.0.3"
|
||||
ftx-api "^1.1.13"
|
||||
node-kraken-api "^2.2.2"
|
||||
|
||||
"@blocto/sdk@^0.2.21":
|
||||
|
@ -50,6 +49,35 @@
|
|||
eip1193-provider "^1.0.1"
|
||||
js-sha3 "^0.8.0"
|
||||
|
||||
"@coral-xyz/anchor@^0.26.0":
|
||||
version "0.26.0"
|
||||
resolved "https://registry.yarnpkg.com/@coral-xyz/anchor/-/anchor-0.26.0.tgz#c8e4f7177e93441afd030f22d777d54d0194d7d1"
|
||||
integrity sha512-PxRl+wu5YyptWiR9F2MBHOLLibm87Z4IMUBPreX+DYBtPM+xggvcPi0KAN7+kIL4IrIhXI8ma5V0MCXxSN1pHg==
|
||||
dependencies:
|
||||
"@coral-xyz/borsh" "^0.26.0"
|
||||
"@solana/web3.js" "^1.68.0"
|
||||
base64-js "^1.5.1"
|
||||
bn.js "^5.1.2"
|
||||
bs58 "^4.0.1"
|
||||
buffer-layout "^1.2.2"
|
||||
camelcase "^6.3.0"
|
||||
cross-fetch "^3.1.5"
|
||||
crypto-hash "^1.3.0"
|
||||
eventemitter3 "^4.0.7"
|
||||
js-sha256 "^0.9.0"
|
||||
pako "^2.0.3"
|
||||
snake-case "^3.0.4"
|
||||
superstruct "^0.15.4"
|
||||
toml "^3.0.0"
|
||||
|
||||
"@coral-xyz/borsh@^0.26.0":
|
||||
version "0.26.0"
|
||||
resolved "https://registry.yarnpkg.com/@coral-xyz/borsh/-/borsh-0.26.0.tgz#d054f64536d824634969e74138f9f7c52bbbc0d5"
|
||||
integrity sha512-uCZ0xus0CszQPHYfWAqKS5swS1UxvePu83oOF+TWpUkedsNlg6p2p4azxZNSSqwXb9uXMFgxhuMBX9r3Xoi0vQ==
|
||||
dependencies:
|
||||
bn.js "^5.1.2"
|
||||
buffer-layout "^1.2.0"
|
||||
|
||||
"@eslint/eslintrc@^1.2.1":
|
||||
version "1.4.1"
|
||||
resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.4.1.tgz#af58772019a2d271b7e2d4c23ff4ddcba3ccfb3e"
|
||||
|
@ -84,18 +112,6 @@
|
|||
resolved "https://registry.yarnpkg.com/@hapi/bourne/-/bourne-2.1.0.tgz#66aff77094dc3080bd5df44ec63881f2676eb020"
|
||||
integrity sha512-i1BpaNDVLJdRBEKeJWkVO6tYX6DMFBuwMhSuWqLsY4ufeTKGVuV5rBsUhxPayXqnnWHgXUAmWK16H/ykO5Wj4Q==
|
||||
|
||||
"@hapi/hoek@^9.0.0":
|
||||
version "9.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.3.0.tgz#8368869dcb735be2e7f5cb7647de78e167a251fb"
|
||||
integrity sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==
|
||||
|
||||
"@hapi/topo@^5.0.0":
|
||||
version "5.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@hapi/topo/-/topo-5.1.0.tgz#dc448e332c6c6e37a4dc02fd84ba8d44b9afb012"
|
||||
integrity sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==
|
||||
dependencies:
|
||||
"@hapi/hoek" "^9.0.0"
|
||||
|
||||
"@headlessui/react@1.6.6":
|
||||
version "1.6.6"
|
||||
resolved "https://registry.yarnpkg.com/@headlessui/react/-/react-1.6.6.tgz#3073c066b85535c9d28783da0a4d9288b5354d0c"
|
||||
|
@ -547,11 +563,12 @@
|
|||
bs58 "^4.0.1"
|
||||
eventemitter3 "^4.0.7"
|
||||
|
||||
"@pythnetwork/client@~2.8.0":
|
||||
version "2.8.0"
|
||||
resolved "https://registry.yarnpkg.com/@pythnetwork/client/-/client-2.8.0.tgz#1b764d710f17c2f3cd3c9ba0c4ae74d26e72b01b"
|
||||
integrity sha512-YqqZSDDsEApC/F4H5ejcl8OCr7gsWv0noTK8YABT8pCtFRTQxXBP0r2S8KQMaIw1x97Mue/jkYybdMeFQzPjCw==
|
||||
"@pythnetwork/client@~2.14.0":
|
||||
version "2.14.0"
|
||||
resolved "https://registry.yarnpkg.com/@pythnetwork/client/-/client-2.14.0.tgz#0c12a7e1bcc66ff198fdb64c003b8d4a24431efc"
|
||||
integrity sha512-tFLGnuIBjlzDa8TrJULzJIdykketGXDJZtO+8+i4XO9l2uOKXzxt+pjt05ng5B9iY63FzJqgAkawT/O3V0NAdQ==
|
||||
dependencies:
|
||||
"@coral-xyz/anchor" "^0.26.0"
|
||||
buffer "^6.0.1"
|
||||
|
||||
"@react-native-async-storage/async-storage@^1.17.7":
|
||||
|
@ -566,23 +583,6 @@
|
|||
resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.1.4.tgz#0c8b74c50f29ee44f423f7416829c0bf8bb5eb27"
|
||||
integrity sha512-LwzQKA4vzIct1zNZzBmRKI9QuNpLgTQMEjsQLf3BXuGYb3QPTP4Yjf6mkdX+X1mYttZ808QpOwAzZjv28kq7DA==
|
||||
|
||||
"@sideway/address@^4.1.3":
|
||||
version "4.1.4"
|
||||
resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.4.tgz#03dccebc6ea47fdc226f7d3d1ad512955d4783f0"
|
||||
integrity sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw==
|
||||
dependencies:
|
||||
"@hapi/hoek" "^9.0.0"
|
||||
|
||||
"@sideway/formula@^3.0.0":
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@sideway/formula/-/formula-3.0.1.tgz#80fcbcbaf7ce031e0ef2dd29b1bfc7c3f583611f"
|
||||
integrity sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==
|
||||
|
||||
"@sideway/pinpoint@^2.0.0":
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@sideway/pinpoint/-/pinpoint-2.0.0.tgz#cff8ffadc372ad29fd3f78277aeb29e632cc70df"
|
||||
integrity sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==
|
||||
|
||||
"@socket.io/component-emitter@~3.1.0":
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz#96116f2a912e0c02817345b3c10751069920d553"
|
||||
|
@ -612,16 +612,6 @@
|
|||
"@solana/wallet-adapter-base" "^0.9.17"
|
||||
js-base64 "^3.7.2"
|
||||
|
||||
"@solana/buffer-layout-utils@^0.2.0":
|
||||
version "0.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@solana/buffer-layout-utils/-/buffer-layout-utils-0.2.0.tgz#b45a6cab3293a2eb7597cceb474f229889d875ca"
|
||||
integrity sha512-szG4sxgJGktbuZYDg2FfNmkMi0DYQoVjN2h7ta1W1hPrwzarcFLBq9UpX1UjNXsNpT9dn+chgprtWGioUAr4/g==
|
||||
dependencies:
|
||||
"@solana/buffer-layout" "^4.0.0"
|
||||
"@solana/web3.js" "^1.32.0"
|
||||
bigint-buffer "^1.1.5"
|
||||
bignumber.js "^9.0.1"
|
||||
|
||||
"@solana/buffer-layout@^4.0.0":
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@solana/buffer-layout/-/buffer-layout-4.0.1.tgz#b996235eaec15b1e0b5092a8ed6028df77fa6c15"
|
||||
|
@ -629,15 +619,14 @@
|
|||
dependencies:
|
||||
buffer "~6.0.3"
|
||||
|
||||
"@solana/spl-token@0.2.0":
|
||||
version "0.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@solana/spl-token/-/spl-token-0.2.0.tgz#329bb6babb5de0f9c40035ddb1657f01a8347acd"
|
||||
integrity sha512-RWcn31OXtdqIxmkzQfB2R+WpsJOVS6rKuvpxJFjvik2LyODd+WN58ZP3Rpjpro03fscGAkzlFuP3r42doRJgyQ==
|
||||
"@solana/spl-token@0.3.7":
|
||||
version "0.3.7"
|
||||
resolved "https://registry.yarnpkg.com/@solana/spl-token/-/spl-token-0.3.7.tgz#6f027f9ad8e841f792c32e50920d9d2e714fc8da"
|
||||
integrity sha512-bKGxWTtIw6VDdCBngjtsGlKGLSmiu/8ghSt/IOYJV24BsymRbgq7r12GToeetpxmPaZYLddKwAz7+EwprLfkfg==
|
||||
dependencies:
|
||||
"@solana/buffer-layout" "^4.0.0"
|
||||
"@solana/buffer-layout-utils" "^0.2.0"
|
||||
"@solana/web3.js" "^1.32.0"
|
||||
start-server-and-test "^1.14.0"
|
||||
buffer "^6.0.3"
|
||||
|
||||
"@solana/spl-token@^0.1.6", "@solana/spl-token@^0.1.8":
|
||||
version "0.1.8"
|
||||
|
@ -1091,7 +1080,7 @@
|
|||
"@wallet-standard/app" "^1.0.0"
|
||||
"@wallet-standard/base" "^1.0.0"
|
||||
|
||||
"@solana/web3.js@^1.17.0", "@solana/web3.js@^1.21.0", "@solana/web3.js@^1.31.0", "@solana/web3.js@^1.32.0", "@solana/web3.js@^1.36.0", "@solana/web3.js@^1.44.3", "@solana/web3.js@^1.63.1":
|
||||
"@solana/web3.js@^1.17.0", "@solana/web3.js@^1.21.0", "@solana/web3.js@^1.31.0", "@solana/web3.js@^1.36.0", "@solana/web3.js@^1.44.3", "@solana/web3.js@^1.63.1", "@solana/web3.js@^1.68.0":
|
||||
version "1.73.2"
|
||||
resolved "https://registry.yarnpkg.com/@solana/web3.js/-/web3.js-1.73.2.tgz#4b30cd402b35733dae3a7d0b638be26a7742b395"
|
||||
integrity sha512-9WACF8W4Nstj7xiDw3Oom22QmrhBh0VyZyZ7JvvG3gOxLWLlX3hvm5nPVJOGcCE/9fFavBbCUb5A6CIuvMGdoA==
|
||||
|
@ -2219,21 +2208,13 @@ axios@1.2.4:
|
|||
form-data "^4.0.0"
|
||||
proxy-from-env "^1.1.0"
|
||||
|
||||
axios@^0.21.0, axios@^0.21.4:
|
||||
axios@^0.21.0:
|
||||
version "0.21.4"
|
||||
resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575"
|
||||
integrity sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==
|
||||
dependencies:
|
||||
follow-redirects "^1.14.0"
|
||||
|
||||
axios@^0.27.2:
|
||||
version "0.27.2"
|
||||
resolved "https://registry.yarnpkg.com/axios/-/axios-0.27.2.tgz#207658cc8621606e586c85db4b41a750e756d972"
|
||||
integrity sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==
|
||||
dependencies:
|
||||
follow-redirects "^1.14.9"
|
||||
form-data "^4.0.0"
|
||||
|
||||
axobject-query@^2.2.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-2.2.0.tgz#943d47e10c0b704aa42275e20edf3722648989be"
|
||||
|
@ -2349,11 +2330,6 @@ blakejs@^1.1.0:
|
|||
resolved "https://registry.yarnpkg.com/blakejs/-/blakejs-1.2.1.tgz#5057e4206eadb4a97f7c0b6e197a505042fc3814"
|
||||
integrity sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ==
|
||||
|
||||
bluebird@3.7.2:
|
||||
version "3.7.2"
|
||||
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f"
|
||||
integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==
|
||||
|
||||
bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.8, bn.js@^4.11.9:
|
||||
version "4.12.0"
|
||||
resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88"
|
||||
|
@ -2589,6 +2565,11 @@ camelcase@^5.0.0, camelcase@^5.3.1:
|
|||
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320"
|
||||
integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==
|
||||
|
||||
camelcase@^6.3.0:
|
||||
version "6.3.0"
|
||||
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a"
|
||||
integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==
|
||||
|
||||
caniuse-lite@^1.0.30001400, caniuse-lite@^1.0.30001406, caniuse-lite@^1.0.30001426:
|
||||
version "1.0.30001448"
|
||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001448.tgz#ca7550b1587c92a392a2b377cd9c508b3b4395bf"
|
||||
|
@ -2628,11 +2609,6 @@ chalk@^4.0.0:
|
|||
ansi-styles "^4.1.0"
|
||||
supports-color "^7.1.0"
|
||||
|
||||
check-more-types@2.24.0:
|
||||
version "2.24.0"
|
||||
resolved "https://registry.yarnpkg.com/check-more-types/-/check-more-types-2.24.0.tgz#1420ffb10fd444dcfc79b43891bbfffd32a84600"
|
||||
integrity sha512-Pj779qHxV2tuapviy1bSZNEL1maXr13bPYpsvSDB68HlYcYuhlDrmGd63i0JHMCLKzc7rUSNIrpdJlhVlNwrxA==
|
||||
|
||||
chokidar@^3.5.3:
|
||||
version "3.5.3"
|
||||
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd"
|
||||
|
@ -2827,7 +2803,7 @@ cross-fetch@^3.1.4, cross-fetch@^3.1.5:
|
|||
dependencies:
|
||||
node-fetch "2.6.7"
|
||||
|
||||
cross-spawn@^7.0.2, cross-spawn@^7.0.3:
|
||||
cross-spawn@^7.0.2:
|
||||
version "7.0.3"
|
||||
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
|
||||
integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==
|
||||
|
@ -2966,7 +2942,7 @@ dayjs@1.11.3:
|
|||
resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.3.tgz#4754eb694a624057b9ad2224b67b15d552589258"
|
||||
integrity sha512-xxwlswWOlGhzgQ4TKzASQkUhqERI3egRNqgV4ScR8wlANA/A9tZ7miXa44vTTKEq5l7vWoL5G57bG3zA+Kow0A==
|
||||
|
||||
debug@4, debug@4.3.4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.2, debug@^4.3.4, debug@~4.3.1, debug@~4.3.2:
|
||||
debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.2, debug@^4.3.4, debug@~4.3.1, debug@~4.3.2:
|
||||
version "4.3.4"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
|
||||
integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
|
||||
|
@ -3186,11 +3162,6 @@ drbg.js@^1.0.1:
|
|||
create-hash "^1.1.2"
|
||||
create-hmac "^1.1.4"
|
||||
|
||||
duplexer@~0.1.1:
|
||||
version "0.1.2"
|
||||
resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6"
|
||||
integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==
|
||||
|
||||
ecc-jsbn@~0.1.1:
|
||||
version "0.1.2"
|
||||
resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9"
|
||||
|
@ -3654,19 +3625,6 @@ ethereumjs-util@^7.1.5:
|
|||
ethereum-cryptography "^0.1.3"
|
||||
rlp "^2.2.4"
|
||||
|
||||
event-stream@=3.3.4:
|
||||
version "3.3.4"
|
||||
resolved "https://registry.yarnpkg.com/event-stream/-/event-stream-3.3.4.tgz#4ab4c9a0f5a54db9338b4c34d86bfce8f4b35571"
|
||||
integrity sha512-QHpkERcGsR0T7Qm3HNJSyXKEEj8AHNxkY3PK8TS2KJvQ7NiSHe3DDpwVKKtoYprL/AreyzFBeIkBIWChAqn60g==
|
||||
dependencies:
|
||||
duplexer "~0.1.1"
|
||||
from "~0"
|
||||
map-stream "~0.1.0"
|
||||
pause-stream "0.0.11"
|
||||
split "0.3"
|
||||
stream-combiner "~0.0.4"
|
||||
through "~2.3.1"
|
||||
|
||||
eventemitter3@^4.0.0, eventemitter3@^4.0.1, eventemitter3@^4.0.4, eventemitter3@^4.0.7:
|
||||
version "4.0.7"
|
||||
resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f"
|
||||
|
@ -3685,21 +3643,6 @@ evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3:
|
|||
md5.js "^1.3.4"
|
||||
safe-buffer "^5.1.1"
|
||||
|
||||
execa@5.1.1:
|
||||
version "5.1.1"
|
||||
resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd"
|
||||
integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==
|
||||
dependencies:
|
||||
cross-spawn "^7.0.3"
|
||||
get-stream "^6.0.0"
|
||||
human-signals "^2.1.0"
|
||||
is-stream "^2.0.0"
|
||||
merge-stream "^2.0.0"
|
||||
npm-run-path "^4.0.1"
|
||||
onetime "^5.1.2"
|
||||
signal-exit "^3.0.3"
|
||||
strip-final-newline "^2.0.0"
|
||||
|
||||
exenv@^1.2.0:
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/exenv/-/exenv-1.2.2.tgz#2ae78e85d9894158670b03d47bec1f03bd91bb9d"
|
||||
|
@ -3841,7 +3784,7 @@ flatted@^3.1.0:
|
|||
resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.5.tgz#76c8584f4fc843db64702a6bd04ab7a8bd666da3"
|
||||
integrity sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==
|
||||
|
||||
follow-redirects@^1.14.0, follow-redirects@^1.14.9, follow-redirects@^1.15.0:
|
||||
follow-redirects@^1.14.0, follow-redirects@^1.15.0:
|
||||
version "1.15.2"
|
||||
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13"
|
||||
integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==
|
||||
|
@ -3881,11 +3824,6 @@ fraction.js@^4.2.0:
|
|||
resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.2.0.tgz#448e5109a313a3527f5a3ab2119ec4cf0e0e2950"
|
||||
integrity sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==
|
||||
|
||||
from@~0:
|
||||
version "0.1.7"
|
||||
resolved "https://registry.yarnpkg.com/from/-/from-0.1.7.tgz#83c60afc58b9c56997007ed1a768b3ab303a44fe"
|
||||
integrity sha512-twe20eF1OxVxp/ML/kq2p1uc6KvFK/+vs8WjEbeKmV2He22MKm7YF2ANIt+EOqhJ5L3K/SuuPhk0hWQDjOM23g==
|
||||
|
||||
fs-minipass@^2.0.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb"
|
||||
|
@ -3903,15 +3841,6 @@ fsevents@~2.3.2:
|
|||
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
|
||||
integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
|
||||
|
||||
ftx-api@^1.1.13:
|
||||
version "1.1.14"
|
||||
resolved "https://registry.yarnpkg.com/ftx-api/-/ftx-api-1.1.14.tgz#14457c3927da448468bf7b1c2e4909bfbf668919"
|
||||
integrity sha512-p6HPgqBiS02RSvHUB8vFRc1XDv5uEBclsuDXoX2AonPEVZySOt0Tp7V+P4R8xlbyohDa3UN6D54dm5C94P/unQ==
|
||||
dependencies:
|
||||
axios "^0.21.4"
|
||||
isomorphic-ws "^4.0.1"
|
||||
ws "^7.4.0"
|
||||
|
||||
function-bind@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
|
||||
|
@ -3965,11 +3894,6 @@ get-intrinsic@^1.0.2, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3:
|
|||
has "^1.0.3"
|
||||
has-symbols "^1.0.3"
|
||||
|
||||
get-stream@^6.0.0:
|
||||
version "6.0.1"
|
||||
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7"
|
||||
integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==
|
||||
|
||||
get-symbol-description@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.0.tgz#7fdb81c900101fbd564dd5f1a30af5aadc1e58d6"
|
||||
|
@ -4215,11 +4139,6 @@ https-proxy-agent@^5.0.0:
|
|||
agent-base "6"
|
||||
debug "4"
|
||||
|
||||
human-signals@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0"
|
||||
integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==
|
||||
|
||||
humanize-ms@^1.2.1:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/humanize-ms/-/humanize-ms-1.2.1.tgz#c46e3159a293f6b896da29316d8b6fe8bb79bbed"
|
||||
|
@ -4448,7 +4367,7 @@ is-shared-array-buffer@^1.0.2:
|
|||
dependencies:
|
||||
call-bind "^1.0.2"
|
||||
|
||||
is-stream@^2.0.0, is-stream@^2.0.1:
|
||||
is-stream@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077"
|
||||
integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==
|
||||
|
@ -4554,17 +4473,6 @@ jmespath@^0.15.0:
|
|||
resolved "https://registry.yarnpkg.com/jmespath/-/jmespath-0.15.0.tgz#a3f222a9aae9f966f5d27c796510e28091764217"
|
||||
integrity sha512-+kHj8HXArPfpPEKGLZ+kB5ONRTCiGQXo8RQYL0hH8t6pWXUBBK5KkkQmTNOwKK4LEsd0yTsgtjJVm4UBSZea4w==
|
||||
|
||||
joi@^17.7.0:
|
||||
version "17.7.0"
|
||||
resolved "https://registry.yarnpkg.com/joi/-/joi-17.7.0.tgz#591a33b1fe1aca2bc27f290bcad9b9c1c570a6b3"
|
||||
integrity sha512-1/ugc8djfn93rTE3WRKdCzGGt/EtiYKxITMO4Wiv6q5JL1gl9ePt4kBsl1S499nbosspfctIQTpYIhSmHA3WAg==
|
||||
dependencies:
|
||||
"@hapi/hoek" "^9.0.0"
|
||||
"@hapi/topo" "^5.0.0"
|
||||
"@sideway/address" "^4.1.3"
|
||||
"@sideway/formula" "^3.0.0"
|
||||
"@sideway/pinpoint" "^2.0.0"
|
||||
|
||||
joycon@^2.2.5:
|
||||
version "2.2.5"
|
||||
resolved "https://registry.yarnpkg.com/joycon/-/joycon-2.2.5.tgz#8d4cf4cbb2544d7b7583c216fcdfec19f6be1615"
|
||||
|
@ -4722,11 +4630,6 @@ language-tags@^1.0.5:
|
|||
dependencies:
|
||||
language-subtag-registry "~0.3.2"
|
||||
|
||||
lazy-ass@1.6.0:
|
||||
version "1.6.0"
|
||||
resolved "https://registry.yarnpkg.com/lazy-ass/-/lazy-ass-1.6.0.tgz#7999655e8646c17f089fdd187d150d3324d54513"
|
||||
integrity sha512-cc8oEVoctTvsFZ/Oje/kGnHbpWHYBe8IAJe4C0QNc3t8uM/0Y8+erSz/7Y1ALuXTEZTMvxXwO6YbX1ey3ujiZw==
|
||||
|
||||
leven@2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/leven/-/leven-2.1.0.tgz#c2e7a9f772094dee9d34202ae8acce4687875580"
|
||||
|
@ -4817,11 +4720,6 @@ lru-cache@^6.0.0:
|
|||
dependencies:
|
||||
yallist "^4.0.0"
|
||||
|
||||
map-stream@~0.1.0:
|
||||
version "0.1.0"
|
||||
resolved "https://registry.yarnpkg.com/map-stream/-/map-stream-0.1.0.tgz#e56aa94c4c8055a16404a0674b78f215f7c8e194"
|
||||
integrity sha512-CkYQrPYZfWnu/DAmVCpTSX/xHpKZ80eKh2lAkyA6AJTef6bW+6JpbQZN5rofum7da+SyN1bi5ctTm+lTfcCW3g==
|
||||
|
||||
md5.js@^1.3.4:
|
||||
version "1.3.5"
|
||||
resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f"
|
||||
|
@ -4843,11 +4741,6 @@ merge-options@^3.0.4:
|
|||
dependencies:
|
||||
is-plain-obj "^2.1.0"
|
||||
|
||||
merge-stream@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60"
|
||||
integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==
|
||||
|
||||
merge2@^1.3.0, merge2@^1.4.1:
|
||||
version "1.4.1"
|
||||
resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae"
|
||||
|
@ -4881,11 +4774,6 @@ mime-types@^2.1.12, mime-types@~2.1.19:
|
|||
dependencies:
|
||||
mime-db "1.52.0"
|
||||
|
||||
mimic-fn@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
|
||||
integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
|
||||
|
||||
minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7"
|
||||
|
@ -4903,7 +4791,7 @@ minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2:
|
|||
dependencies:
|
||||
brace-expansion "^1.1.7"
|
||||
|
||||
minimist@^1.2.0, minimist@^1.2.6, minimist@^1.2.7:
|
||||
minimist@^1.2.0, minimist@^1.2.6:
|
||||
version "1.2.7"
|
||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.7.tgz#daa1c4d91f507390437c6a8bc01078e7000c4d18"
|
||||
integrity sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==
|
||||
|
@ -5116,13 +5004,6 @@ npm-normalize-package-bin@^3.0.0:
|
|||
resolved "https://registry.yarnpkg.com/npm-normalize-package-bin/-/npm-normalize-package-bin-3.0.0.tgz#6097436adb4ef09e2628b59a7882576fe53ce485"
|
||||
integrity sha512-g+DPQSkusnk7HYXr75NtzkIP4+N81i3RPsGFidF3DzHd9MT9wWngmqoeg/fnHFz5MNdtG4w03s+QnhewSLTT2Q==
|
||||
|
||||
npm-run-path@^4.0.1:
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea"
|
||||
integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==
|
||||
dependencies:
|
||||
path-key "^3.0.0"
|
||||
|
||||
npmlog@^4.1.2:
|
||||
version "4.1.2"
|
||||
resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b"
|
||||
|
@ -5228,13 +5109,6 @@ once@^1.3.0, once@^1.3.1, once@^1.4.0:
|
|||
dependencies:
|
||||
wrappy "1"
|
||||
|
||||
onetime@^5.1.2:
|
||||
version "5.1.2"
|
||||
resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e"
|
||||
integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==
|
||||
dependencies:
|
||||
mimic-fn "^2.1.0"
|
||||
|
||||
optionator@^0.9.1:
|
||||
version "0.9.1"
|
||||
resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499"
|
||||
|
@ -5318,7 +5192,7 @@ path-is-absolute@^1.0.0:
|
|||
resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
|
||||
integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==
|
||||
|
||||
path-key@^3.0.0, path-key@^3.1.0:
|
||||
path-key@^3.1.0:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375"
|
||||
integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==
|
||||
|
@ -5333,13 +5207,6 @@ path-type@^4.0.0:
|
|||
resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b"
|
||||
integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==
|
||||
|
||||
pause-stream@0.0.11:
|
||||
version "0.0.11"
|
||||
resolved "https://registry.yarnpkg.com/pause-stream/-/pause-stream-0.0.11.tgz#fe5a34b0cbce12b5aa6a2b403ee2e73b602f1445"
|
||||
integrity sha512-e3FBlXLmN/D1S+zHzanP4E/4Z60oFAa3O051qt1pxa7DEJWKAyil6upYVXCWadEnuoqa4Pkc9oUx9zsxYeRv8A==
|
||||
dependencies:
|
||||
through "~2.3"
|
||||
|
||||
pbkdf2@^3.0.17, pbkdf2@^3.0.3:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.2.tgz#dd822aa0887580e52f1a039dc3eda108efae3075"
|
||||
|
@ -5553,13 +5420,6 @@ proxy-from-env@^1.1.0:
|
|||
resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2"
|
||||
integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==
|
||||
|
||||
ps-tree@1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/ps-tree/-/ps-tree-1.2.0.tgz#5e7425b89508736cdd4f2224d028f7bb3f722ebd"
|
||||
integrity sha512-0VnamPPYHl4uaU/nSFeZZpR21QAWRz+sRv4iW9+v/GS/J5U5iZB5BNN6J0RMoOvdx2gWM2+ZFMIm58q24e4UYA==
|
||||
dependencies:
|
||||
event-stream "=3.3.4"
|
||||
|
||||
psl@^1.1.28:
|
||||
version "1.9.0"
|
||||
resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7"
|
||||
|
@ -6059,13 +5919,6 @@ rxjs@6, rxjs@^6.6.3:
|
|||
dependencies:
|
||||
tslib "^1.9.0"
|
||||
|
||||
rxjs@^7.8.0:
|
||||
version "7.8.0"
|
||||
resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.0.tgz#90a938862a82888ff4c7359811a595e14e1e09a4"
|
||||
integrity sha512-F2+gxDshqmIub1KdvZkaEfGDwLNpPvk9Fs6LD/MyQxNgMds/WH9OdDDXOmxUZpME+iSK3rQCctkL0DYyytUqMg==
|
||||
dependencies:
|
||||
tslib "^2.1.0"
|
||||
|
||||
safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0:
|
||||
version "5.2.1"
|
||||
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
|
||||
|
@ -6202,7 +6055,7 @@ side-channel@^1.0.4:
|
|||
get-intrinsic "^1.0.2"
|
||||
object-inspect "^1.9.0"
|
||||
|
||||
signal-exit@^3.0.0, signal-exit@^3.0.3, signal-exit@^3.0.7:
|
||||
signal-exit@^3.0.0, signal-exit@^3.0.7:
|
||||
version "3.0.7"
|
||||
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9"
|
||||
integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==
|
||||
|
@ -6263,13 +6116,6 @@ split2@^3.1.1:
|
|||
dependencies:
|
||||
readable-stream "^3.0.0"
|
||||
|
||||
split@0.3:
|
||||
version "0.3.3"
|
||||
resolved "https://registry.yarnpkg.com/split/-/split-0.3.3.tgz#cd0eea5e63a211dfff7eb0f091c4133e2d0dd28f"
|
||||
integrity sha512-wD2AeVmxXRBoX44wAycgjVpMhvbwdI2aZjCkvfNcH1YqHQvJVa1duWc73OyVGJUc05fhFaTZeQ/PYsrmyH0JVA==
|
||||
dependencies:
|
||||
through "2"
|
||||
|
||||
sshpk@^1.7.0:
|
||||
version "1.17.0"
|
||||
resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.17.0.tgz#578082d92d4fe612b13007496e543fa0fbcbe4c5"
|
||||
|
@ -6285,20 +6131,6 @@ sshpk@^1.7.0:
|
|||
safer-buffer "^2.0.2"
|
||||
tweetnacl "~0.14.0"
|
||||
|
||||
start-server-and-test@^1.14.0:
|
||||
version "1.15.3"
|
||||
resolved "https://registry.yarnpkg.com/start-server-and-test/-/start-server-and-test-1.15.3.tgz#33bb6465ff4d5e3a476337512a7e0d737a5ef026"
|
||||
integrity sha512-4GqkqghvUR9cJ8buvtgkyT0AHgVwCJ5EN8eDEhe9grTChGwWUxGm2nqfSeE9+0PZkLRdFqcwTwxVHe1y3ViutQ==
|
||||
dependencies:
|
||||
arg "^5.0.2"
|
||||
bluebird "3.7.2"
|
||||
check-more-types "2.24.0"
|
||||
debug "4.3.4"
|
||||
execa "5.1.1"
|
||||
lazy-ass "1.6.0"
|
||||
ps-tree "1.2.0"
|
||||
wait-on "7.0.1"
|
||||
|
||||
stream-browserify@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-3.0.0.tgz#22b0a2850cdf6503e73085da1fc7b7d0c2122f2f"
|
||||
|
@ -6307,13 +6139,6 @@ stream-browserify@^3.0.0:
|
|||
inherits "~2.0.4"
|
||||
readable-stream "^3.5.0"
|
||||
|
||||
stream-combiner@~0.0.4:
|
||||
version "0.0.4"
|
||||
resolved "https://registry.yarnpkg.com/stream-combiner/-/stream-combiner-0.0.4.tgz#4d5e433c185261dde623ca3f44c586bcf5c4ad14"
|
||||
integrity sha512-rT00SPnTVyRsaSz5zgSPma/aHSOic5U1prhYdRy5HS2kTZviFpmDgzilbtsJsxiroqACmayynDN/9VzIbX5DOw==
|
||||
dependencies:
|
||||
duplexer "~0.1.1"
|
||||
|
||||
strict-uri-encode@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546"
|
||||
|
@ -6418,11 +6243,6 @@ strip-bom@^3.0.0:
|
|||
resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3"
|
||||
integrity sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==
|
||||
|
||||
strip-final-newline@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad"
|
||||
integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==
|
||||
|
||||
strip-json-comments@^3.1.0, strip-json-comments@^3.1.1:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006"
|
||||
|
@ -6528,7 +6348,7 @@ text-table@^0.2.0:
|
|||
resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
|
||||
integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==
|
||||
|
||||
through@2, "through@>=2.2.7 <3", through@~2.3, through@~2.3.1:
|
||||
"through@>=2.2.7 <3":
|
||||
version "2.3.8"
|
||||
resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
|
||||
integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==
|
||||
|
@ -6595,7 +6415,7 @@ tslib@^1.8.1, tslib@^1.9.0:
|
|||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
|
||||
integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
|
||||
|
||||
tslib@^2.0.3, tslib@^2.1.0, tslib@^2.3.0, tslib@^2.3.1, tslib@^2.4.0:
|
||||
tslib@^2.0.3, tslib@^2.3.0, tslib@^2.3.1, tslib@^2.4.0:
|
||||
version "2.5.0"
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.5.0.tgz#42bfed86f5787aeb41d031866c8f402429e0fddf"
|
||||
integrity sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==
|
||||
|
@ -7080,17 +6900,6 @@ void-elements@3.1.0:
|
|||
resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-3.1.0.tgz#614f7fbf8d801f0bb5f0661f5b2f5785750e4f09"
|
||||
integrity sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==
|
||||
|
||||
wait-on@7.0.1:
|
||||
version "7.0.1"
|
||||
resolved "https://registry.yarnpkg.com/wait-on/-/wait-on-7.0.1.tgz#5cff9f8427e94f4deacbc2762e6b0a489b19eae9"
|
||||
integrity sha512-9AnJE9qTjRQOlTZIldAaf/da2eW0eSRSgcqq85mXQja/DW3MriHxkpODDSUEg+Gri/rKEcXUZHe+cevvYItaog==
|
||||
dependencies:
|
||||
axios "^0.27.2"
|
||||
joi "^17.7.0"
|
||||
lodash "^4.17.21"
|
||||
minimist "^1.2.7"
|
||||
rxjs "^7.8.0"
|
||||
|
||||
walktour@5.1.1:
|
||||
version "5.1.1"
|
||||
resolved "https://registry.yarnpkg.com/walktour/-/walktour-5.1.1.tgz#951b5bce2abed0ae4209dc74d4d79f252a85e813"
|
||||
|
@ -7213,9 +7022,9 @@ ws@^7.2.0, ws@^7.4.0, ws@^7.4.5, ws@^7.5.1:
|
|||
integrity sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==
|
||||
|
||||
ws@^8.5.0:
|
||||
version "8.12.0"
|
||||
resolved "https://registry.yarnpkg.com/ws/-/ws-8.12.0.tgz#485074cc392689da78e1828a9ff23585e06cddd8"
|
||||
integrity sha512-kU62emKIdKVeEIOIKVegvqpXMSTAMLJozpHZaJNDYqBjzlSYXQGviYwN1osDLJ9av68qHd4a2oSjd7yD4pacig==
|
||||
version "8.12.1"
|
||||
resolved "https://registry.yarnpkg.com/ws/-/ws-8.12.1.tgz#c51e583d79140b5e42e39be48c934131942d4a8f"
|
||||
integrity sha512-1qo+M9Ba+xNhPB+YTWUlK6M17brTut5EXbcBaMRN5pH5dFrXz7lzz1ChFSUq3bOUl8yEvSenhHmYUNJxFzdJew==
|
||||
|
||||
ws@~8.2.3:
|
||||
version "8.2.3"
|
||||
|
|
Loading…
Reference in New Issue