multi-order cancel (#391)
* wip * cancel all orders for market * disable button when loading * fix * fix --------- Co-authored-by: Adrian Brzeziński <a.brzezinski94@gmail.com>
This commit is contained in:
parent
99d609ce0b
commit
2910d04086
|
@ -14,7 +14,7 @@ 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="grid grid-cols-2 pb-20 sm:grid-cols-3">
|
||||
<div className="col-span-2 sm:col-span-3">
|
||||
<FavoriteMarketsBar />
|
||||
</div>
|
||||
|
|
|
@ -42,7 +42,7 @@ import useFilledOrders from 'hooks/useFilledOrders'
|
|||
import { useViewport } from 'hooks/useViewport'
|
||||
import { useTranslation } from 'next-i18next'
|
||||
import Link from 'next/link'
|
||||
import { ChangeEvent, useCallback, useState } from 'react'
|
||||
import { ChangeEvent, Fragment, useCallback, useState } from 'react'
|
||||
import { isMangoError } from 'types'
|
||||
import { notify } from 'utils/notifications'
|
||||
import { getDecimalCount } from 'utils/numbers'
|
||||
|
@ -52,6 +52,7 @@ import PerpSideBadge from './PerpSideBadge'
|
|||
import TableMarketName from './TableMarketName'
|
||||
import { useSortableData } from 'hooks/useSortableData'
|
||||
import { BN } from '@project-serum/anchor'
|
||||
import NukeIcon from '@components/icons/NukeIcon'
|
||||
|
||||
type TableData = {
|
||||
expiryTimestamp: number | undefined
|
||||
|
@ -95,6 +96,7 @@ const OpenOrders = ({
|
|||
const { t } = useTranslation(['common', 'trade'])
|
||||
const openOrders = mangoStore((s) => s.mangoAccount.openOrders)
|
||||
const [cancelId, setCancelId] = useState<string>('')
|
||||
const [cancelAllMarket, setCancelAllMarket] = useState<string | number>('')
|
||||
const [modifyOrderId, setModifyOrderId] = useState<string | undefined>(
|
||||
undefined,
|
||||
)
|
||||
|
@ -109,6 +111,48 @@ const OpenOrders = ({
|
|||
const { selectedMarket } = useSelectedMarket()
|
||||
const { filledOrders, fetchingFilledOrders } = useFilledOrders()
|
||||
|
||||
const handleCancelAllForSpotMarket = useCallback(
|
||||
async (o: Order) => {
|
||||
const client = mangoStore.getState().client
|
||||
const group = mangoStore.getState().group
|
||||
const mangoAccount = mangoStore.getState().mangoAccount.current
|
||||
if (!group || !mangoAccount) return
|
||||
const marketPk = findSerum3MarketPkInOpenOrders(o)
|
||||
if (!marketPk) return
|
||||
const market = group.getSerum3MarketByExternalMarket(
|
||||
new PublicKey(marketPk),
|
||||
)
|
||||
setCancelAllMarket(market.name)
|
||||
try {
|
||||
const { signature: tx } = await client.serum3CancelAllOrders(
|
||||
group,
|
||||
mangoAccount,
|
||||
market.serumMarketExternal,
|
||||
)
|
||||
const actions = mangoStore.getState().actions
|
||||
await actions.fetchOpenOrders(true)
|
||||
notify({
|
||||
type: 'success',
|
||||
title: 'Transaction successful',
|
||||
txid: tx,
|
||||
})
|
||||
} catch (e) {
|
||||
console.error('Error canceling', e)
|
||||
if (isMangoError(e)) {
|
||||
notify({
|
||||
title: t('trade:cancel-order-error'),
|
||||
description: e.message,
|
||||
txid: e.txid,
|
||||
type: 'error',
|
||||
})
|
||||
}
|
||||
} finally {
|
||||
setCancelAllMarket('')
|
||||
}
|
||||
},
|
||||
[t],
|
||||
)
|
||||
|
||||
const handleCancelSerumOrder = useCallback(
|
||||
async (o: Order) => {
|
||||
const client = mangoStore.getState().client
|
||||
|
@ -222,7 +266,7 @@ const OpenOrders = ({
|
|||
cancelEditOrderForm()
|
||||
}
|
||||
},
|
||||
[t, modifiedOrderSize, modifiedOrderPrice],
|
||||
[modifiedOrderSize, modifiedOrderPrice],
|
||||
)
|
||||
|
||||
const handleCancelPerpOrder = useCallback(
|
||||
|
@ -263,6 +307,44 @@ const OpenOrders = ({
|
|||
[t],
|
||||
)
|
||||
|
||||
const handleCancelAllPerpOrders = 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
|
||||
setCancelAllMarket(o.perpMarketIndex)
|
||||
try {
|
||||
const { signature: tx } = await client.perpCancelAllOrders(
|
||||
group,
|
||||
mangoAccount,
|
||||
o.perpMarketIndex,
|
||||
100,
|
||||
)
|
||||
await actions.fetchOpenOrders(true)
|
||||
notify({
|
||||
type: 'success',
|
||||
title: 'Transaction successful',
|
||||
txid: tx,
|
||||
})
|
||||
} catch (e) {
|
||||
console.error('Error canceling', e)
|
||||
if (isMangoError(e)) {
|
||||
notify({
|
||||
title: t('trade:cancel-order-error'),
|
||||
description: e.message,
|
||||
txid: e.txid,
|
||||
type: 'error',
|
||||
})
|
||||
}
|
||||
} finally {
|
||||
setCancelAllMarket('')
|
||||
}
|
||||
},
|
||||
[t],
|
||||
)
|
||||
|
||||
const showEditOrderForm = (order: Order | PerpOrder, tickSize: number) => {
|
||||
setModifyOrderId(order.orderId.toString())
|
||||
setModifiedOrderSize(order.size.toString())
|
||||
|
@ -377,6 +459,13 @@ const OpenOrders = ({
|
|||
sortConfig,
|
||||
} = useSortableData(formattedTableData())
|
||||
|
||||
const ordersByMarket: { [key: string]: number } = {}
|
||||
// count the number of orders for each market
|
||||
tableData.forEach((data) => {
|
||||
const { market } = data
|
||||
ordersByMarket[market.name] = (ordersByMarket[market.name] || 0) + 1
|
||||
})
|
||||
|
||||
return mangoAccountAddress && tableData.length ? (
|
||||
showTableView ? (
|
||||
<Table>
|
||||
|
@ -431,12 +520,12 @@ const OpenOrders = ({
|
|||
</div>
|
||||
</Th>
|
||||
{!isUnownedAccount ? (
|
||||
<Th className="w-[14.28%] text-right" />
|
||||
<Th className="w-[16.67%] text-right" />
|
||||
) : null}
|
||||
</TrHead>
|
||||
</thead>
|
||||
<tbody>
|
||||
{tableData.map((data) => {
|
||||
{tableData.map((data, index) => {
|
||||
const {
|
||||
expiryTimestamp,
|
||||
filledQuantity,
|
||||
|
@ -450,23 +539,33 @@ const OpenOrders = ({
|
|||
tickSize,
|
||||
value,
|
||||
} = data
|
||||
|
||||
const isFirstOrderForMarket =
|
||||
ordersByMarket[market.name] > 1 &&
|
||||
index ===
|
||||
tableData.findIndex((item) => item.market.name === market.name)
|
||||
|
||||
const loadingCancel =
|
||||
cancelAllMarket === market.name ||
|
||||
(order instanceof PerpOrder &&
|
||||
cancelAllMarket === order.perpMarketIndex)
|
||||
return (
|
||||
<TrBody
|
||||
key={`${side}${size}${price}${orderId.toString()}`}
|
||||
className="my-1 p-2"
|
||||
>
|
||||
<Td className="w-[14.28%]">
|
||||
<Td className="w-[16.67%]">
|
||||
<TableMarketName market={market} side={side} />
|
||||
</Td>
|
||||
{modifyOrderId !== orderId.toString() ? (
|
||||
<>
|
||||
<Td className="w-[14.28%] text-right font-mono">
|
||||
<Td className="w-[16.67%] text-right font-mono">
|
||||
<FormatNumericValue
|
||||
value={size}
|
||||
decimals={getDecimalCount(minOrderSize)}
|
||||
/>
|
||||
</Td>
|
||||
<Td className="w-[14.28%] whitespace-nowrap text-right font-mono">
|
||||
<Td className="w-[16.67%] whitespace-nowrap text-right font-mono">
|
||||
<FormatNumericValue
|
||||
value={price}
|
||||
decimals={getDecimalCount(tickSize)}
|
||||
|
@ -475,9 +574,9 @@ const OpenOrders = ({
|
|||
</>
|
||||
) : (
|
||||
<>
|
||||
<Td className="w-[14.28%]">
|
||||
<Td className="w-[16.67%]">
|
||||
<input
|
||||
className="h-8 w-full rounded-l-none rounded-r-none border-b-2 border-l-0 border-r-0 border-t-0 border-th-bkg-4 bg-transparent px-0 text-right font-mono text-sm hover:border-th-fgd-3 focus:border-th-fgd-3 focus:outline-none"
|
||||
className="h-8 w-full rounded-none border-x-0 border-b-2 border-t-0 border-th-bkg-4 bg-transparent px-0 text-right font-mono text-sm hover:border-th-fgd-3 focus:border-th-fgd-3 focus:outline-none"
|
||||
type="text"
|
||||
value={modifiedOrderSize}
|
||||
onChange={(e: ChangeEvent<HTMLInputElement>) =>
|
||||
|
@ -485,10 +584,10 @@ const OpenOrders = ({
|
|||
}
|
||||
/>
|
||||
</Td>
|
||||
<Td className="w-[14.28%]">
|
||||
<Td className="w-[16.67%]">
|
||||
<input
|
||||
autoFocus
|
||||
className="h-8 w-full rounded-l-none rounded-r-none border-b-2 border-l-0 border-r-0 border-t-0 border-th-bkg-4 bg-transparent px-0 text-right font-mono text-sm hover:border-th-fgd-3 focus:border-th-fgd-3 focus:outline-none"
|
||||
className="h-8 w-full rounded-none border-x-0 border-b-2 border-t-0 border-th-bkg-4 bg-transparent px-0 text-right font-mono text-sm hover:border-th-fgd-3 focus:border-th-fgd-3 focus:outline-none"
|
||||
type="text"
|
||||
value={modifiedOrderPrice}
|
||||
onChange={(e: ChangeEvent<HTMLInputElement>) =>
|
||||
|
@ -498,9 +597,9 @@ const OpenOrders = ({
|
|||
</Td>
|
||||
</>
|
||||
)}
|
||||
<Td className="w-[14.28%] text-right font-mono">
|
||||
<Td className="w-[16.67%] text-right font-mono">
|
||||
{fetchingFilledOrders ? (
|
||||
<div className="items flex justify-end">
|
||||
<div className="flex justify-end">
|
||||
<SheenLoader className="flex justify-end">
|
||||
<div className="h-4 w-8 bg-th-bkg-2" />
|
||||
</SheenLoader>
|
||||
|
@ -512,7 +611,7 @@ const OpenOrders = ({
|
|||
/>
|
||||
)}
|
||||
</Td>
|
||||
<Td className="w-[14.28%] text-right font-mono">
|
||||
<Td className="w-[16.67%] text-right font-mono">
|
||||
<FormatNumericValue value={value} isUsd />
|
||||
{expiryTimestamp ? (
|
||||
<div className="h-min text-xxs leading-tight text-th-fgd-4">{`Expires ${new Date(
|
||||
|
@ -521,56 +620,85 @@ const OpenOrders = ({
|
|||
) : null}
|
||||
</Td>
|
||||
{!isUnownedAccount ? (
|
||||
<Td className="w-[14.28%]">
|
||||
<div className="flex justify-end space-x-2">
|
||||
{modifyOrderId !== orderId.toString() ? (
|
||||
<>
|
||||
<IconButton
|
||||
onClick={() => showEditOrderForm(order, tickSize)}
|
||||
size="small"
|
||||
>
|
||||
<PencilIcon className="h-4 w-4" />
|
||||
</IconButton>
|
||||
<Tooltip content={t('cancel')}>
|
||||
<IconButton
|
||||
disabled={cancelId === orderId.toString()}
|
||||
onClick={() =>
|
||||
order instanceof PerpOrder
|
||||
? handleCancelPerpOrder(order)
|
||||
: handleCancelSerumOrder(order)
|
||||
}
|
||||
size="small"
|
||||
>
|
||||
{cancelId === orderId.toString() ? (
|
||||
<Loading className="h-4 w-4" />
|
||||
<>
|
||||
<Td className="w-[16.67%]">
|
||||
<div className="flex w-full justify-end">
|
||||
<div className="flex justify-start space-x-2">
|
||||
{modifyOrderId !== orderId.toString() ? (
|
||||
<>
|
||||
<IconButton
|
||||
onClick={() =>
|
||||
showEditOrderForm(order, tickSize)
|
||||
}
|
||||
size="small"
|
||||
>
|
||||
<PencilIcon className="h-4 w-4" />
|
||||
</IconButton>
|
||||
<Tooltip content={t('cancel')}>
|
||||
<IconButton
|
||||
disabled={cancelId === orderId.toString()}
|
||||
onClick={() =>
|
||||
order instanceof PerpOrder
|
||||
? handleCancelPerpOrder(order)
|
||||
: handleCancelSerumOrder(order)
|
||||
}
|
||||
size="small"
|
||||
>
|
||||
{cancelId === orderId.toString() ||
|
||||
loadingCancel ? (
|
||||
<Loading className="h-4 w-4" />
|
||||
) : (
|
||||
<TrashIcon className="h-4 w-4" />
|
||||
)}
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
{isFirstOrderForMarket ? (
|
||||
<Tooltip
|
||||
content={t('trade:cancel-all-orders', {
|
||||
market: market.name,
|
||||
})}
|
||||
>
|
||||
<IconButton
|
||||
disabled={loadingCancel}
|
||||
onClick={() =>
|
||||
order instanceof PerpOrder
|
||||
? handleCancelAllPerpOrders(order)
|
||||
: handleCancelAllForSpotMarket(order)
|
||||
}
|
||||
size="small"
|
||||
>
|
||||
<NukeIcon className="h-4 w-4" />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
) : (
|
||||
<TrashIcon className="h-4 w-4" />
|
||||
<div className="h-8 w-8" />
|
||||
)}
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<IconButton
|
||||
onClick={() => modifyOrder(order)}
|
||||
size="small"
|
||||
>
|
||||
{loadingModifyOrder ? (
|
||||
<Loading className="h-4 w-4" />
|
||||
) : (
|
||||
<CheckIcon className="h-4 w-4" />
|
||||
)}
|
||||
</IconButton>
|
||||
<IconButton
|
||||
onClick={cancelEditOrderForm}
|
||||
size="small"
|
||||
>
|
||||
<XMarkIcon className="h-4 w-4" />
|
||||
</IconButton>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</Td>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<IconButton
|
||||
onClick={() => modifyOrder(order)}
|
||||
size="small"
|
||||
>
|
||||
{loadingModifyOrder ? (
|
||||
<Loading className="h-4 w-4" />
|
||||
) : (
|
||||
<CheckIcon className="h-4 w-4" />
|
||||
)}
|
||||
</IconButton>
|
||||
<IconButton
|
||||
onClick={cancelEditOrderForm}
|
||||
size="small"
|
||||
>
|
||||
<XMarkIcon className="h-4 w-4" />
|
||||
</IconButton>
|
||||
<div className="h-8 w-8" />
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</Td>
|
||||
</>
|
||||
) : null}
|
||||
</TrBody>
|
||||
)
|
||||
|
@ -579,7 +707,7 @@ const OpenOrders = ({
|
|||
</Table>
|
||||
) : (
|
||||
<div>
|
||||
{tableData.map((data) => {
|
||||
{tableData.map((data, index) => {
|
||||
const {
|
||||
expiryTimestamp,
|
||||
market,
|
||||
|
@ -603,6 +731,14 @@ const OpenOrders = ({
|
|||
externalMarket.quoteTokenIndex,
|
||||
)
|
||||
}
|
||||
const isFirstOrderForMarket =
|
||||
ordersByMarket[market.name] > 1 &&
|
||||
index ===
|
||||
tableData.findIndex((item) => item.market.name === market.name)
|
||||
const loadingCancel =
|
||||
cancelAllMarket === market.name ||
|
||||
(order instanceof PerpOrder &&
|
||||
cancelAllMarket === order.perpMarketIndex)
|
||||
return (
|
||||
<div
|
||||
className="flex items-center justify-between border-b border-th-bkg-3 p-4"
|
||||
|
@ -676,7 +812,7 @@ const OpenOrders = ({
|
|||
<div>
|
||||
<p className="text-xs">{t('trade:size')}</p>
|
||||
<Input
|
||||
className="w-full rounded-l-none rounded-r-none border-b-2 border-l-0 border-r-0 border-t-0 border-th-bkg-4 bg-transparent px-0 text-right font-mono hover:border-th-fgd-3 focus:border-th-fgd-3 focus:outline-none"
|
||||
className="w-full rounded-none border-x-0 border-b-2 border-t-0 border-th-bkg-4 bg-transparent px-0 text-right font-mono hover:border-th-fgd-3 focus:border-th-fgd-3 focus:outline-none"
|
||||
type="text"
|
||||
value={modifiedOrderSize}
|
||||
onChange={(e: ChangeEvent<HTMLInputElement>) =>
|
||||
|
@ -688,7 +824,7 @@ const OpenOrders = ({
|
|||
<p className="text-xs">{t('price')}</p>
|
||||
<Input
|
||||
autoFocus
|
||||
className="w-full rounded-l-none rounded-r-none border-b-2 border-l-0 border-r-0 border-t-0 border-th-bkg-4 bg-transparent px-0 text-right font-mono hover:border-th-fgd-3 focus:border-th-fgd-3 focus:outline-none"
|
||||
className="w-full rounded-none border-x-0 border-b-2 border-t-0 border-th-bkg-4 bg-transparent px-0 text-right font-mono hover:border-th-fgd-3 focus:border-th-fgd-3 focus:outline-none"
|
||||
type="text"
|
||||
value={modifiedOrderPrice}
|
||||
onChange={(e: ChangeEvent<HTMLInputElement>) =>
|
||||
|
@ -720,12 +856,31 @@ const OpenOrders = ({
|
|||
}
|
||||
size="small"
|
||||
>
|
||||
{cancelId === orderId.toString() ? (
|
||||
{cancelId === orderId.toString() || loadingCancel ? (
|
||||
<Loading className="h-4 w-4" />
|
||||
) : (
|
||||
<TrashIcon className="h-4 w-4" />
|
||||
)}
|
||||
</IconButton>
|
||||
{isFirstOrderForMarket ? (
|
||||
<Tooltip
|
||||
content={t('trade:cancel-all-orders', {
|
||||
market: market.name,
|
||||
})}
|
||||
>
|
||||
<IconButton
|
||||
disabled={loadingCancel}
|
||||
onClick={() =>
|
||||
order instanceof PerpOrder
|
||||
? handleCancelAllPerpOrders(order)
|
||||
: handleCancelAllForSpotMarket(order)
|
||||
}
|
||||
size="small"
|
||||
>
|
||||
<NukeIcon className="h-4 w-4" />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
) : null}
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
"dependencies": {
|
||||
"@blockworks-foundation/mango-feeds": "0.1.7",
|
||||
"@blockworks-foundation/mango-mints-redemption": "^0.0.10",
|
||||
"@blockworks-foundation/mango-v4": "0.21.29",
|
||||
"@blockworks-foundation/mango-v4": "0.21.31",
|
||||
"@blockworks-foundation/mango-v4-settings": "0.14.15",
|
||||
"@blockworks-foundation/mangolana": "0.0.14",
|
||||
"@headlessui/react": "1.6.6",
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
"book": "Book",
|
||||
"buys": "Buys",
|
||||
"cancel-all": "Cancel All",
|
||||
"cancel-all-orders": "Cancel all {{market}} orders",
|
||||
"cancel-order": "Cancel Order",
|
||||
"cancel-order-error": "Failed to cancel order",
|
||||
"close-all": "Close All",
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
"book": "Book",
|
||||
"buys": "Buys",
|
||||
"cancel-all": "Cancel All",
|
||||
"cancel-all-orders": "Cancel all {{market}} orders",
|
||||
"cancel-order": "Cancel Order",
|
||||
"cancel-order-error": "Failed to cancel order",
|
||||
"close-all": "Close All",
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
"book": "Livro",
|
||||
"buys": "Compras",
|
||||
"cancel-all": "Cancelar Todos",
|
||||
"cancel-all-orders": "Cancel all {{market}} orders",
|
||||
"cancel-order": "Cancelar Pedido",
|
||||
"cancel-order-error": "Falha ao cancelar pedido",
|
||||
"close-all": "Fechar Todos",
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
"book": "Book",
|
||||
"buys": "Buys",
|
||||
"cancel-all": "Cancel All",
|
||||
"cancel-all-orders": "Cancel all {{market}} orders",
|
||||
"cancel-order": "Cancel Order",
|
||||
"cancel-order-error": "Failed to cancel order",
|
||||
"close-all": "Close All",
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
"book": "单薄",
|
||||
"buys": "买",
|
||||
"cancel-all": "取消全部",
|
||||
"cancel-all-orders": "Cancel all {{market}} orders",
|
||||
"cancel-order": "取消订单",
|
||||
"cancel-order-error": "取消订单失败",
|
||||
"close-all": "全部平仓",
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
"book": "單薄",
|
||||
"buys": "買",
|
||||
"cancel-all": "取消全部",
|
||||
"cancel-all-orders": "Cancel all {{market}} orders",
|
||||
"cancel-order": "取消訂單",
|
||||
"cancel-order-error": "取消訂單失敗",
|
||||
"close-all": "全部平倉",
|
||||
|
|
18
yarn.lock
18
yarn.lock
|
@ -350,20 +350,12 @@
|
|||
bn.js "^5.2.1"
|
||||
eslint-config-prettier "^9.0.0"
|
||||
|
||||
"@blockworks-foundation/mango-v4-settings@0.4.10":
|
||||
version "0.4.10"
|
||||
resolved "https://registry.yarnpkg.com/@blockworks-foundation/mango-v4-settings/-/mango-v4-settings-0.4.10.tgz#7a30db53c81abea56c2dd83e928259246e3b4e7d"
|
||||
integrity sha512-J4RhfhcNmBn0CeqjN4mlaou+vPW9NGpWlbkx1+ZczsJw6r5tIkQ82MDqKMKvyIgn457krRVdJ9+gLmHEln4QfA==
|
||||
"@blockworks-foundation/mango-v4@0.21.31":
|
||||
version "0.21.31"
|
||||
resolved "https://registry.yarnpkg.com/@blockworks-foundation/mango-v4/-/mango-v4-0.21.31.tgz#b57511a66bc4a69d30e6e23f8053acf9fb21552f"
|
||||
integrity sha512-KYGRvbqagsiTOnvu2yirdRuirXl2ei//b1VkCXtXJ2TCQE6lPyvMe24HziXzWbn9rymAnSohooKCvODQXDGFug==
|
||||
dependencies:
|
||||
bn.js "^5.2.1"
|
||||
eslint-config-prettier "^9.0.0"
|
||||
|
||||
"@blockworks-foundation/mango-v4@0.21.29":
|
||||
version "0.21.29"
|
||||
resolved "https://registry.yarnpkg.com/@blockworks-foundation/mango-v4/-/mango-v4-0.21.29.tgz#4ff5f6c7efed7daa6f34ac2779a3fd5785a5566e"
|
||||
integrity sha512-gu+U55g52ttLu+44z66+5NDhLYaCGujjUjQm1/jVHbE4iXwgQoBCxY/QD6a0rZVR9tJYs+epoCL3KK9q0AUqCg==
|
||||
dependencies:
|
||||
"@blockworks-foundation/mango-v4-settings" "0.4.10"
|
||||
"@blockworks-foundation/mango-v4-settings" "0.14.15"
|
||||
"@blockworks-foundation/mangolana" "0.0.14"
|
||||
"@coral-xyz/anchor" "^0.28.1-beta.2"
|
||||
"@project-serum/serum" "0.13.65"
|
||||
|
|
Loading…
Reference in New Issue