Merge branch 'main' into trade-hot-keys

This commit is contained in:
tjs 2023-06-26 12:58:10 -04:00
commit ce13f685a3
48 changed files with 1433 additions and 803 deletions

View File

@ -264,14 +264,6 @@ function DepositForm({ onSuccess, token }: DepositFormProps) {
<p>{t('deposit-amount')}</p>
<BankAmountWithValue amount={inputAmount} bank={bank} />
</div>
{/* <div className="flex justify-between">
<div className="flex items-center">
<Tooltip content={t('asset-weight-desc')}>
<p className="tooltip-underline">{t('asset-weight')}</p>
</Tooltip>
</div>
<p className="font-mono">{bank!.initAssetWeight.toFixed(2)}x</p>
</div> */}
<div className="flex justify-between">
<Tooltip content={t('tooltip-collateral-value')}>
<p className="tooltip-underline">{t('collateral-value')}</p>
@ -281,7 +273,7 @@ function DepositForm({ onSuccess, token }: DepositFormProps) {
value={
bank.uiPrice *
Number(inputAmount) *
Number(bank.initAssetWeight)
Number(bank.scaledInitAssetWeight(bank.price))
}
isUsd
/>

View File

@ -75,38 +75,52 @@ function WithdrawForm({ onSuccess, token }: WithdrawFormProps) {
return logoURI
}, [bank?.mint, mangoTokens])
const tokenMax = useMemo(() => {
if (!bank || !mangoAccount || !group) return new Decimal(0)
const amount = getMaxWithdrawForBank(group, bank, mangoAccount)
return amount
const [adjustedTokenMax, tokenMax] = useMemo(() => {
if (!bank || !mangoAccount || !group)
return [new Decimal(0), new Decimal(0)]
const tokenMax = getMaxWithdrawForBank(group, bank, mangoAccount).toNumber()
let adjustedTokenMax = tokenMax
const balance = mangoAccount.getTokenBalanceUi(bank)
if (tokenMax < balance) {
adjustedTokenMax = tokenMax * 0.998
}
return [new Decimal(adjustedTokenMax), new Decimal(tokenMax)]
}, [mangoAccount, bank, group])
const handleSizePercentage = useCallback(
(percentage: string) => {
if (!bank) return
setSizePercentage(percentage)
const amount = floorToDecimal(
new Decimal(tokenMax).mul(percentage).div(100),
bank.mintDecimals
)
setInputAmount(amount.toFixed())
let amount: Decimal
if (percentage !== '100') {
amount = floorToDecimal(
new Decimal(adjustedTokenMax).mul(percentage).div(100),
bank.mintDecimals
)
} else {
amount = floorToDecimal(
new Decimal(adjustedTokenMax),
bank.mintDecimals
)
}
setInputAmount(amount.toString())
},
[bank, tokenMax]
[bank, adjustedTokenMax]
)
const setMax = useCallback(() => {
if (!bank) return
const max = floorToDecimal(tokenMax, bank.mintDecimals)
setInputAmount(max.toFixed())
const max = floorToDecimal(adjustedTokenMax, bank.mintDecimals)
setInputAmount(max.toString())
setSizePercentage('100')
}, [bank, tokenMax])
}, [bank, adjustedTokenMax])
const handleWithdraw = useCallback(async () => {
const client = mangoStore.getState().client
const group = mangoStore.getState().group
const mangoAccount = mangoStore.getState().mangoAccount.current
const actions = mangoStore.getState().actions
const withdrawAmount = parseFloat(inputAmount)
if (!mangoAccount || !group || !bank) return
setSubmitting(true)
try {
@ -114,7 +128,7 @@ function WithdrawForm({ onSuccess, token }: WithdrawFormProps) {
group,
mangoAccount,
bank.mint,
parseFloat(inputAmount),
withdrawAmount,
false
)
notify({
@ -201,7 +215,7 @@ function WithdrawForm({ onSuccess, token }: WithdrawFormProps) {
decimals={bank.mintDecimals}
label={t('max')}
onClick={setMax}
value={tokenMax}
value={adjustedTokenMax}
/>
) : null}
</div>

View File

@ -40,7 +40,8 @@ const AccountChart = ({
if (chartToShow === 'cumulative-interest-value') {
return data.map((d) => ({
interest_value:
d.borrow_interest_cumulative_usd + d.deposit_interest_cumulative_usd,
d.borrow_interest_cumulative_usd * -1 +
d.deposit_interest_cumulative_usd,
time: d.time,
}))
}

View File

@ -420,7 +420,7 @@ const AccountPage = () => {
The lower your account health is the more likely you are to
get liquidated when prices fluctuate.
</p>
{maintHealth < 100 ? (
{maintHealth < 100 && mangoAccountAddress ? (
<>
<p className="text-xs font-bold text-th-fgd-1">
Your account health is {maintHealth}%

View File

@ -62,7 +62,12 @@ const ActivityFilters = () => {
let advancedParams = ''
Object.entries(advancedFilters).map((entry) => {
if (entry[1].length) {
advancedParams = advancedParams + `&${entry[0]}=${entry[1]}`
// ETH should be renamed to ETH (Portal) in the database
const alignSymbolsToBackend = entry[1].map((e: string) =>
e === 'ETH (Portal)' ? 'ETH' : e
)
advancedParams =
advancedParams + `&${entry[0]}=${alignSymbolsToBackend}`
}
})
return advancedParams

View File

@ -45,7 +45,11 @@ const fetchHourlyFunding = async (mangoAccountPk: string) => {
const stats: HourlyFundingStatsData[] = entries.map(([key, value]) => {
const marketEntries = Object.entries(value)
const marketFunding = marketEntries.map(([key, value]) => {
return { ...value, time: key }
return {
long_funding: value.long_funding * -1,
short_funding: value.short_funding * -1,
time: key,
}
})
return { marketFunding, market: key }
})

View File

@ -3,7 +3,13 @@ import GovernanceStore from '@store/governanceStore'
import mangoStore from '@store/mangoStore'
import { ReactNode, useEffect } from 'react'
const GovernancePageWrapper = ({ children }: { children: ReactNode }) => {
const GovernancePageWrapper = ({
children,
noStyles,
}: {
children: ReactNode
noStyles?: boolean
}) => {
const { publicKey } = useWallet()
const initConnection = GovernanceStore((s) => s.initConnection)
@ -44,8 +50,12 @@ const GovernancePageWrapper = ({ children }: { children: ReactNode }) => {
])
return (
<div className="grid grid-cols-12">
<div className="col-span-12 lg:col-span-8 lg:col-start-3">{children}</div>
<div className={!noStyles ? 'grid grid-cols-12' : ''}>
<div
className={!noStyles ? 'col-span-12 lg:col-span-8 lg:col-start-3' : ''}
>
{children}
</div>
</div>
)
}

View File

@ -49,7 +49,7 @@ import CreateOpenbookMarketModal from '@components/modals/CreateOpenbookMarketMo
import { calculateTradingParameters } from 'utils/governance/listingTools'
import useJupiterMints from 'hooks/useJupiterMints'
import CreateSwitchboardOracleModal from '@components/modals/CreateSwitchboardOracleModal'
import { BN } from '@project-serum/anchor'
import { BN } from '@coral-xyz/anchor'
type FormErrors = Partial<Record<keyof TokenListForm, string>>

View File

@ -1,5 +1,5 @@
import InlineNotification from '@components/shared/InlineNotification'
import { BN } from '@project-serum/anchor'
import { BN } from '@coral-xyz/anchor'
import { useWallet } from '@solana/wallet-adapter-react'
import GovernanceStore from '@store/governanceStore'
import { useTranslation } from 'next-i18next'

View File

@ -17,7 +17,7 @@ import {
HandThumbDownIcon,
HandThumbUpIcon,
} from '@heroicons/react/20/solid'
import { BN } from '@project-serum/anchor'
import { BN } from '@coral-xyz/anchor'
import { useEffect, useState } from 'react'
import { MANGO_GOVERNANCE_PROGRAM } from 'utils/governance/constants'
import mangoStore from '@store/mangoStore'

View File

@ -8,7 +8,7 @@ import { MANGO_MINT } from 'utils/constants'
import { PublicKey } from '@solana/web3.js'
import dynamic from 'next/dynamic'
import { tryGetMint } from 'utils/governance/tools'
import { BN } from '@project-serum/anchor'
import { BN } from '@coral-xyz/anchor'
import { useTranslation } from 'next-i18next'
import SheenLoader from '@components/shared/SheenLoader'
import { NoSymbolIcon } from '@heroicons/react/20/solid'

View File

@ -1,6 +1,6 @@
import Tooltip from '@components/shared/Tooltip'
import { CheckCircleIcon } from '@heroicons/react/20/solid'
import { BN } from '@project-serum/anchor'
import { BN } from '@coral-xyz/anchor'
import { Governance, ProgramAccount, Proposal } from '@solana/spl-governance'
import { RawMint } from '@solana/spl-token'
import GovernanceStore from '@store/governanceStore'

View File

@ -3,7 +3,7 @@ import VoteResultsBar from './VoteResultBar'
import { fmtTokenAmount } from 'utils/governance/tools'
import { RawMint } from '@solana/spl-token'
import { useTranslation } from 'next-i18next'
import { BN } from '@project-serum/anchor'
import { BN } from '@coral-xyz/anchor'
type VoteResultsProps = {
proposal: Proposal

View File

@ -17,7 +17,9 @@ import Tooltip from '@components/shared/Tooltip'
const RPC_URLS = [
{
label: 'Triton',
value: 'https://mango.rpcpool.com/0f9acc0d45173b51bf7d7e09c1e5',
value:
process.env.NEXT_PUBLIC_ENDPOINT ||
'https://mango.rpcpool.com/946ef7337da3f5b8d3e4a34e7f88',
},
// {
// label: 'Genesys Go',

View File

@ -141,9 +141,13 @@ const TokenDetailsTable = () => {
</Td>
<Td>
<div className="flex justify-end space-x-1.5 text-right">
<p>{bank.initAssetWeight.toFixed(2)}</p>
<p>
{bank.scaledInitAssetWeight(bank.price).toFixed(2)}
</p>
<span className="text-th-fgd-4">|</span>
<p>{bank.initLiabWeight.toFixed(2)}</p>
<p>
{bank.scaledInitLiabWeight(bank.price).toFixed(2)}
</p>
</div>
</Td>
<Td>
@ -254,11 +258,15 @@ const TokenDetailsTable = () => {
</Tooltip>
<div className="flex space-x-1.5 text-right font-mono">
<p className="text-th-fgd-1">
{bank.initAssetWeight.toFixed(2)}
{bank
.scaledInitAssetWeight(bank.price)
.toFixed(2)}
</p>
<span className="text-th-fgd-4">|</span>
<p className="text-th-fgd-1">
{bank.initLiabWeight.toFixed(2)}
{bank
.scaledInitLiabWeight(bank.price)
.toFixed(2)}
</p>
</div>
</div>

View File

@ -6,7 +6,7 @@ import {
} from '@blockworks-foundation/mango-v4'
import Tooltip from '@components/shared/Tooltip'
import { ArrowTopRightOnSquareIcon } from '@heroicons/react/20/solid'
import { BN } from '@project-serum/anchor'
import { BN } from '@coral-xyz/anchor'
import mangoStore from '@store/mangoStore'
import { getOracleProvider } from 'hooks/useOracleProvider'
import { useTranslation } from 'next-i18next'
@ -41,11 +41,11 @@ const TokenParams = ({ bank }: { bank: Bank }) => {
</Tooltip>
<div className="flex space-x-2">
<p className="font-mono text-th-fgd-2">
{bank.initAssetWeight.toFixed(2)}
{bank.scaledInitAssetWeight(bank.price).toFixed(2)}
</p>
<span className="text-th-fgd-4">|</span>
<p className="font-mono text-th-fgd-2">
{bank.initLiabWeight.toFixed(2)}
{bank.scaledInitLiabWeight(bank.price).toFixed(2)}
</p>
</div>
</div>

View File

@ -22,6 +22,7 @@ import {
import MarketLogos from './MarketLogos'
import SoonBadge from '@components/shared/SoonBadge'
import TabButtons from '@components/shared/TabButtons'
import { PerpMarket } from '@blockworks-foundation/mango-v4'
const MARKET_LINK_WRAPPER_CLASSES =
'flex items-center justify-between px-4 md:pl-6 md:pr-4'
@ -35,7 +36,9 @@ const MARKET_LINK_DISABLED_CLASSES =
const MarketSelectDropdown = () => {
const { t } = useTranslation('common')
const { selectedMarket } = useSelectedMarket()
const [spotOrPerp, setSpotOrPerp] = useState('perp')
const [spotOrPerp, setSpotOrPerp] = useState(
selectedMarket instanceof PerpMarket ? 'perp' : 'spot'
)
const serumMarkets = mangoStore((s) => s.serumMarkets)
const allPerpMarkets = mangoStore((s) => s.perpMarkets)
const perpStats = mangoStore((s) => s.perpStats.data)
@ -130,9 +133,6 @@ const MarketSelectDropdown = () => {
<div
className={MARKET_LINK_WRAPPER_CLASSES}
key={m.publicKey.toString()}
onClick={() => {
if (!isComingSoon) close()
}}
>
{!isComingSoon ? (
<>
@ -142,6 +142,9 @@ const MarketSelectDropdown = () => {
pathname: '/trade',
query: { name: m.name },
}}
onClick={() => {
close()
}}
shallow={true}
>
<div className="flex items-center">
@ -236,9 +239,6 @@ const MarketSelectDropdown = () => {
<div
className={MARKET_LINK_WRAPPER_CLASSES}
key={m.publicKey.toString()}
onClick={() => {
close()
}}
>
<Link
className={MARKET_LINK_CLASSES}
@ -246,6 +246,9 @@ const MarketSelectDropdown = () => {
pathname: '/trade',
query: { name: m.name },
}}
onClick={() => {
close()
}}
shallow={true}
>
<div className="flex items-center">

View File

@ -24,6 +24,7 @@ import {
BookSideType,
MangoClient,
PerpMarket,
Serum3Market,
} from '@blockworks-foundation/mango-v4'
import useSelectedMarket from 'hooks/useSelectedMarket'
import { INITIAL_ANIMATION_SETTINGS } from '@components/settings/AnimationSettings'
@ -425,7 +426,11 @@ const Orderbook = () => {
const selectedMarket = mangoStore.getState().selectedMarket
if (!useOrderbookFeed || !selectedMarket || !selectedMarket.current)
return
if (update.market != selectedMarket.current.publicKey.toBase58()) return
const selectedMarketKey =
selectedMarket.current instanceof Serum3Market
? selectedMarket.current['serumMarketExternal']
: selectedMarket.current.publicKey
if (update.market != selectedMarketKey.toBase58()) return
// ensure updates are applied in the correct order by checking slot and writeVersion
const lastSeenSlot =

View File

@ -17,13 +17,18 @@ import { useTranslation } from 'next-i18next'
import Link from 'next/link'
import { useRouter } from 'next/router'
import { useCallback, useState } from 'react'
import { floorToDecimal, getDecimalCount } from 'utils/numbers'
import {
floorToDecimal,
formatCurrencyValue,
getDecimalCount,
} from 'utils/numbers'
import { breakpoints } from 'utils/theme'
import { calculateLimitPriceForMarketOrder } from 'utils/tradeForm'
import MarketCloseModal from './MarketCloseModal'
import MarketLogos from './MarketLogos'
import PerpSideBadge from './PerpSideBadge'
import TableMarketName from './TableMarketName'
import Tooltip from '@components/shared/Tooltip'
const PerpPositions = () => {
const { t } = useTranslation(['common', 'trade'])
@ -119,7 +124,7 @@ const PerpPositions = () => {
<Th className="text-right">{`${t('trade:unsettled')} ${t(
'pnl'
)}`}</Th>
<Th className="text-right">{t('pnl')}</Th>
<Th className="text-right">{t('trade:unrealized-pnl')}</Th>
{!isUnownedAccount ? <Th /> : null}
</TrHead>
</thead>
@ -140,8 +145,10 @@ const PerpPositions = () => {
if (!basePosition) return null
const unsettledPnl = position.getUnsettledPnlUi(market)
const cummulativePnl =
const totalPnl =
position.cumulativePnlOverPositionLifetimeUi(market)
const unrealizedPnl = position.getUnRealizedPnlUi(market)
const realizedPnl = position.getRealizedPnlUi()
return (
<TrBody
@ -207,16 +214,31 @@ const PerpPositions = () => {
decimals={2}
/>
</Td>
<Td
className={`text-right font-mono ${
cummulativePnl > 0 ? 'text-th-up' : 'text-th-down'
}`}
>
<FormatNumericValue
value={cummulativePnl}
isUsd
decimals={2}
/>
<Td className="text-right font-mono">
<Tooltip
content={
<PnlTooltipContent
unrealizedPnl={unrealizedPnl}
realizedPnl={realizedPnl}
totalPnl={totalPnl}
/>
}
delay={100}
>
<span
className={`tooltip-underline ${
unrealizedPnl > 0
? 'text-th-up'
: 'text-th-down'
}`}
>
<FormatNumericValue
value={unrealizedPnl}
isUsd
decimals={2}
/>
</span>
</Tooltip>
</Td>
{!isUnownedAccount ? (
<Td>
@ -271,8 +293,10 @@ const PerpPositions = () => {
selectedMarket.perpMarketIndex === position.marketIndex
if (!basePosition) return null
const cummulativePnl =
const totalPnl =
position.cumulativePnlOverPositionLifetimeUi(market)
const unrealizedPnl = position.getUnRealizedPnlUi(market)
const realizedPnl = position.getRealizedPnlUi()
return (
<div
className="flex items-center justify-between border-b border-th-bkg-3 p-4"
@ -338,11 +362,24 @@ const PerpPositions = () => {
<div className="flex items-center space-x-4">
<div
className={`text-right font-mono leading-none ${
cummulativePnl > 0 ? 'text-th-up' : 'text-th-down'
unrealizedPnl > 0 ? 'text-th-up' : 'text-th-down'
}`}
>
<p className="mb-1 text-th-fgd-4">PnL</p>
<FormatNumericValue value={cummulativePnl} isUsd />
<Tooltip
content={
<PnlTooltipContent
unrealizedPnl={unrealizedPnl}
realizedPnl={realizedPnl}
totalPnl={totalPnl}
/>
}
delay={100}
>
<p className="tooltip-underline mb-1 font-body text-th-fgd-4">
{t('trade:unrealized-pnl')}
</p>
</Tooltip>
<FormatNumericValue value={unrealizedPnl} isUsd />
</div>
{!isUnownedAccount ? (
<Button
@ -383,3 +420,46 @@ const PerpPositions = () => {
}
export default PerpPositions
const PnlTooltipContent = ({
unrealizedPnl,
realizedPnl,
totalPnl,
}: {
unrealizedPnl: number
realizedPnl: number
totalPnl: number
}) => {
const { t } = useTranslation(['common', 'trade'])
return (
<>
<div className="mb-3 space-y-1">
<div className="flex justify-between">
<p className="mr-3">{t('trade:unrealized-pnl')}</p>
<span className="font-mono text-th-fgd-2">
{formatCurrencyValue(unrealizedPnl, 2)}
</span>
</div>
<div className="flex justify-between">
<p className="mr-3">{t('trade:realized-pnl')}</p>
<span className="font-mono text-th-fgd-2">
{formatCurrencyValue(realizedPnl, 2)}
</span>
</div>
<div className="flex justify-between">
<p className="mr-3">{t('trade:total-pnl')}</p>
<span className="font-mono text-th-fgd-2">
{formatCurrencyValue(totalPnl, 2)}
</span>
</div>
</div>
<a
href="https://docs.mango.markets/mango-markets/settle-pnl"
target="_blank"
rel="noopener noreferrer"
>
{t('learn-more')}
</a>
</>
)
}

View File

@ -31,7 +31,7 @@ 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 { BN } from '@coral-xyz/anchor'
import Datafeed from 'apis/datafeed'
// import PerpDatafeed from 'apis/mngo/datafeed'
import { CombinedTradeHistory, isMangoError } from 'types'

View File

@ -50,9 +50,12 @@ export default function useBanksWithBalances(
const maxBorrow = mangoAccount
? getMaxWithdrawForBank(group, bank, mangoAccount, true).toNumber()
: 0
const maxWithdraw = mangoAccount
let maxWithdraw = mangoAccount
? getMaxWithdrawForBank(group, bank, mangoAccount).toNumber()
: 0
if (maxWithdraw < balance) {
maxWithdraw = maxWithdraw * 0.998
}
const borrowedAmount = mangoAccount
? floorToDecimal(
mangoAccount.getTokenBorrowsUi(bank),

View File

@ -28,7 +28,7 @@ const fetchBirdeyePrices = async (
if (responses?.length) {
return responses.map((res) => ({
data: res.data.items,
mint: res.data.items[0].address,
mint: res.data.items[0]?.address,
}))
}

View File

@ -5,7 +5,12 @@ const webpack = require('webpack')
const nextConfig = {
i18n,
images: {
domains: ['raw.githubusercontent.com', 'arweave.net', 'www.dual.finance'],
domains: [
'raw.githubusercontent.com',
'arweave.net',
'www.dual.finance',
'storage.googleapis.com',
],
},
reactStrictMode: true,
//proxy for openserum api cors

View File

@ -19,7 +19,7 @@
},
"dependencies": {
"@blockworks-foundation/mango-feeds": "0.1.6",
"@blockworks-foundation/mango-v4": "^0.15.13",
"@blockworks-foundation/mango-v4": "^0.16.6",
"@headlessui/react": "1.6.6",
"@heroicons/react": "2.0.10",
"@metaplex-foundation/js": "0.18.3",
@ -104,6 +104,7 @@
"typescript": "4.9.4"
},
"resolutions": {
"@coral-xyz/anchor": "^0.27.0",
"eslint-config-next/eslint-import-resolver-typescript/tsconfig-paths/json5": "1.0.2"
},
"lavamoat": {

View File

@ -42,6 +42,10 @@ import { THEME_KEY } from 'utils/constants'
// Create a client
export const queryClient = new QueryClient()
const metaTitle = 'Mango Markets Safer. Smarter. Faster.'
const metaDescription =
'A magical new way to interact with DeFi. Groundbreaking safety features designed to keep your funds secure. The easiest way to margin trade any token pair. All powered by flashloans.'
function MyApp({ Component, pageProps }: AppProps) {
const network = WalletAdapterNetwork.Mainnet
const endpoint = useMemo(() => clusterApiUrl(network), [network])
@ -73,16 +77,9 @@ function MyApp({ Component, pageProps }: AppProps) {
<Head>
<title>Mango Markets</title>
<link rel="icon" href="/favicon.ico" />
<meta property="og:title" content="Mango Markets" />
<meta property="og:title" content={metaTitle} />
<meta name="description" content={metaDescription} />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta
name="keywords"
content="Mango Markets, Serum, SRM, Serum DEX, DEFI, Decentralized Finance, Decentralised Finance, Crypto, ERC20, Ethereum, Decentralize, Solana, SOL, SPL, Cross-Chain, Trading, Fastest, Fast, SerumBTC, SerumUSD, SRM Tokens, SPL Tokens"
/>
<meta
name="description"
content="A magical new way to interact with DeFi. Groundbreaking safety features designed to keep your funds secure."
/>
<link
rel="apple-touch-icon"
sizes="192x192"
@ -91,11 +88,8 @@ function MyApp({ Component, pageProps }: AppProps) {
<meta name="msapplication-TileColor" content="#da532c" />
<meta name="theme-color" content="#ffffff" />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content="Mango Markets" />
<meta
name="twitter:description"
content="A magical new way to interact with DeFi. Groundbreaking safety features designed to keep your funds secure."
/>
<meta name="twitter:title" content={metaTitle} />
<meta name="twitter:description" content={metaDescription} />
<meta
name="twitter:image"
content="https://app.mango.markets/images/1200x600-share.png?34567879"

File diff suppressed because it is too large Load Diff

View File

@ -12,7 +12,7 @@ import {
} from '@blockworks-foundation/mango-v4'
import { PublicKey } from '@solana/web3.js'
import { formatNumericValue } from 'utils/numbers'
import { AnchorProvider, web3 } from '@project-serum/anchor'
import { AnchorProvider, web3 } from '@coral-xyz/anchor'
export async function getStaticProps({ locale }: { locale: string }) {
return {
@ -51,7 +51,8 @@ const RiskDashboard: NextPage = () => {
() => {
const provider = new AnchorProvider(
new web3.Connection(
'https://mango.rpcpool.com/0f9acc0d45173b51bf7d7e09c1e5',
process.env.NEXT_PUBLIC_ENDPOINT ||
'https://mango.rpcpool.com/946ef7337da3f5b8d3e4a34e7f88',
'processed'
),
emptyWallet,

19
public/icons/jitosol.svg Normal file
View File

@ -0,0 +1,19 @@
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_2784_2263)">
<path d="M16 32C24.8366 32 32 24.8366 32 16C32 7.16345 24.8366 0 16 0C7.16345 0 0 7.16345 0 16C0 24.8366 7.16345 32 16 32Z" fill="url(#paint0_linear_2784_2263)"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M1.5 16C1.5 7.99188 7.99188 1.5 16 1.5C24.0081 1.5 30.5 7.99188 30.5 16C30.5 24.0081 24.0081 30.5 16 30.5C7.99188 30.5 1.5 24.0081 1.5 16ZM16 2.5C8.54416 2.5 2.5 8.54416 2.5 16C2.5 23.4558 8.54416 29.5 16 29.5C23.4558 29.5 29.5 23.4558 29.5 16C29.5 8.54416 23.4558 2.5 16 2.5Z" fill="white"/>
<path d="M6.15479 12.2139H6.18078C6.17324 12.2168 6.16359 12.2168 6.15479 12.2139Z" fill="#308D8A"/>
<path d="M10.2963 19.1043C10.3983 19.0023 10.5384 18.9429 10.6871 18.9429H24.1678C24.4141 18.9429 24.5373 19.2402 24.3632 19.4143L21.7001 22.0773C21.5982 22.1793 21.4581 22.2387 21.3094 22.2387H7.82868C7.58234 22.2387 7.45917 21.9414 7.63331 21.7673L10.2963 19.1043Z" fill="white"/>
<path d="M10.2963 9.16139C10.4025 9.05946 10.5427 9 10.6871 9H24.1678C24.4141 9 24.5373 9.29731 24.3632 9.47144L21.7001 12.1345C21.5982 12.2364 21.4581 12.2958 21.3094 12.2958H7.82868C7.58234 12.2958 7.45917 11.9985 7.63331 11.8244L10.2963 9.16139Z" fill="white"/>
<path d="M21.7001 14.1008C21.5982 13.9989 21.4581 13.9395 21.3094 13.9395H7.82868C7.58234 13.9395 7.45917 14.2368 7.63331 14.4109L10.2963 17.0739C10.3983 17.1758 10.5384 17.2353 10.6871 17.2353H24.1678C24.4141 17.2353 24.5373 16.938 24.3632 16.7639L21.7001 14.1008Z" fill="white"/>
</g>
<defs>
<linearGradient id="paint0_linear_2784_2263" x1="32" y1="32" x2="0" y2="0" gradientUnits="userSpaceOnUse">
<stop stop-color="#3D9B7F"/>
<stop offset="1" stop-color="#87D58F"/>
</linearGradient>
<clipPath id="clip0_2784_2263">
<rect width="32" height="32" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -89,6 +89,7 @@
"interest-earned-paid": "Interest Earned",
"leaderboard": "Leaderboard",
"learn": "Learn",
"learn-more": "Learn More",
"leverage": "Leverage",
"liability-weight": "Liability Weight",
"liquidity": "Liquidity",

View File

@ -64,6 +64,7 @@
"price-expect": "The price you receive may be worse than you expect and full execution is not guaranteed. Max slippage is 2.5% for your safety. The part of your position with slippage beyond 2.5% will not be closed.",
"price-provided-by": "Oracle by",
"quote": "Quote",
"realized-pnl": "Realized PnL",
"reduce": "Reduce",
"reduce-only": "Reduce Only",
"sells": "Sells",
@ -88,9 +89,11 @@
"tooltip-slippage": "An estimate of the difference between the current price and the price your trade will be executed at",
"tooltip-volume-alert": "Volume Alert Settings",
"tooltip-stable-price": "Stable price is used in a safety mechanism that limits a user's ability to enter risky positions when the oracle price is changing rapidly",
"total-pnl": "Total PnL",
"trade-sounds-tooltip": "Play a sound alert for every new trade",
"trades": "Trades",
"tweet-position": "Share to Twitter",
"unrealized-pnl": "Unrealized PnL",
"unsettled": "Unsettled",
"volume-alert": "Volume Alert",
"volume-alert-desc": "Play a sound whenever volume exceeds your alert threshold"

View File

@ -89,6 +89,7 @@
"interest-earned-paid": "Interest Earned",
"leaderboard": "Leaderboard",
"learn": "Learn",
"learn-more": "Learn More",
"leverage": "Leverage",
"liability-weight": "Liability Weight",
"liquidity": "Liquidity",

View File

@ -64,6 +64,7 @@
"price-expect": "The price you receive may be worse than you expect and full execution is not guaranteed. Max slippage is 2.5% for your safety. The part of your position with slippage beyond 2.5% will not be closed.",
"price-provided-by": "Oracle by",
"quote": "Quote",
"realized-pnl": "Realized PnL",
"reduce": "Reduce",
"reduce-only": "Reduce Only",
"sells": "Sells",
@ -88,9 +89,11 @@
"tooltip-slippage": "An estimate of the difference between the current price and the price your trade will be executed at",
"tooltip-volume-alert": "Volume Alert Settings",
"tooltip-stable-price": "Stable price is used in a safety mechanism that limits a user's ability to enter risky positions when the oracle price is changing rapidly",
"total-pnl": "Total PnL",
"trade-sounds-tooltip": "Play a sound alert for every new trade",
"trades": "Trades",
"tweet-position": "Share to Twitter",
"unrealized-pnl": "Unrealized PnL",
"unsettled": "Unsettled",
"volume-alert": "Volume Alert",
"volume-alert-desc": "Play a sound whenever volume exceeds your alert threshold"

View File

@ -89,6 +89,7 @@
"interest-earned-paid": "Interest Earned",
"leaderboard": "Leaderboard",
"learn": "Learn",
"learn-more": "Learn More",
"leverage": "Leverage",
"liability-weight": "Liability Weight",
"liquidity": "Liquidity",

View File

@ -64,6 +64,7 @@
"price-expect": "The price you receive may be worse than you expect and full execution is not guaranteed. Max slippage is 2.5% for your safety. The part of your position with slippage beyond 2.5% will not be closed.",
"price-provided-by": "Oracle by",
"quote": "Quote",
"realized-pnl": "Realized PnL",
"reduce": "Reduce",
"reduce-only": "Reduce Only",
"sells": "Sells",
@ -88,9 +89,11 @@
"tooltip-slippage": "An estimate of the difference between the current price and the price your trade will be executed at",
"tooltip-volume-alert": "Volume Alert Settings",
"tooltip-stable-price": "Stable price is used in a safety mechanism that limits a user's ability to enter risky positions when the oracle price is changing rapidly",
"total-pnl": "Total PnL",
"trade-sounds-tooltip": "Play a sound alert for every new trade",
"trades": "Trades",
"tweet-position": "Share to Twitter",
"unrealized-pnl": "Unrealized PnL",
"unsettled": "Unsettled",
"volume-alert": "Volume Alert",
"volume-alert-desc": "Play a sound whenever volume exceeds your alert threshold"

View File

@ -89,6 +89,7 @@
"interest-earned-paid": "获取利息",
"leaderboard": "排行榜",
"learn": "学",
"learn-more": "Learn More",
"leverage": "杠杆",
"liability-weight": "债务权重",
"liquidity": "流动性",

View File

@ -1,34 +1,34 @@
{
"24h-volume": "24h Volume",
"activate-volume-alert": "开启交易量警报",
"amount": "数量",
"activate-volume-alert": "Activate Volume Alert",
"amount": "Amount",
"average-funding": "Average {{interval}} Funding",
"base": "基础",
"book": "挂单薄",
"buys": "买单",
"cancel-order-error": "取消挂单出错",
"close-confirm": "市场平仓您的{{config_name}}持仓",
"close-position": "平仓",
"connect-orders": "连接以查看您的订单",
"connect-positions": "连接以查看您的持仓",
"connect-trade-history": "连接以查看交易纪录",
"connect-unsettled": "连接以查看未结清余额",
"copy-and-share": "复制影像",
"current-price": "目前价格",
"base": "Base",
"book": "Book",
"buys": "Buys",
"cancel-order-error": "Failed to cancel order",
"close-confirm": "Market close your {{config_name}} position",
"close-position": "Close Position",
"connect-orders": "Connect to view your open orders",
"connect-positions": "Connect to view your perp positions",
"connect-trade-history": "Connect to view your trade history",
"connect-unsettled": "Connect to view your unsettled funds",
"copy-and-share": "Copy Image to Clipboard",
"current-price": "Current Price",
"edit-order": "Edit Order",
"entry-price": "入场价",
"est-slippage": "预计下滑",
"funding-limits": "资金费限制",
"funding-rate": "资金费率",
"grouping": "分组",
"hide-asks": "隐藏要价",
"hide-bids": "隐藏出价",
"in-orders": "在挂单中",
"init-leverage": "初始杠杆",
"instantaneous-funding": "瞬时资金费率",
"insured": "被{{token}}保险",
"interval-seconds": "间隔(秒)",
"last-updated": "最近更新",
"entry-price": "Entry Price",
"est-slippage": "Est. Slippage",
"funding-limits": "Funding Limits",
"funding-rate": "1h Avg Funding Rate",
"grouping": "Grouping",
"hide-asks": "Hide Asks",
"hide-bids": "Hide Bids",
"in-orders": "In Orders",
"init-leverage": "Init Leverage",
"instantaneous-funding": "Instantaneous Funding Snapshot",
"interval-seconds": "Interval (seconds)",
"insured": "{{token}} Insured",
"last-updated": "Last updated",
"limit": "Limit",
"limit-price": "限价价格",
"long": "做多",
@ -38,26 +38,27 @@
"market-details": "{{market}}市场细节",
"max-leverage": "最多杠杆",
"min-order-size": "最小订单量",
"maker-fee": "Maker Fee",
"min-order-size-error": "Min order size is {{minSize}} {{symbol}}",
"more-details": "More Details",
"no-balances": "您没有余额",
"no-orders": "您没有订单",
"no-positions": "您没有持仓",
"no-unsettled": "您没有未结清余额",
"notional": "合约面值",
"notional-volume": "面值交易量($)",
"open-interest": "持仓量",
"oracle": "预言机",
"oracle-not-updated": "此预言机最近没有更新。",
"oracle-not-updated-warning": "含有此币种的帐户无法进行活动。",
"oracle-price": "预言机价格",
"order-error": "下订单出错了",
"order-type": "订单方式",
"order-value": "订单价值",
"orders": "订单",
"place-order": "下{{side}}单",
"placing-order": "正在下单",
"positions": "当前持仓",
"no-balances": "No balances",
"no-orders": "No open orders",
"no-positions": "No perp positions",
"no-unsettled": "No unsettled funds",
"notional": "Notional",
"notional-volume": "Notional Volume ($)",
"open-interest": "Open Interest",
"oracle": "Oracle",
"oracle-not-updated": "This oracle has not updated recently.",
"oracle-not-updated-warning": "Actions will fail for accounts with a position in this token.",
"oracle-price": "Oracle Price",
"order-error": "Failed to place order",
"order-type": "Order Type",
"order-value": "Order Value",
"orders": "Orders",
"place-order": "Place {{side}} Order",
"placing-order": "Placing Order",
"positions": "Positions",
"post": "Post",
"preview-sound": "声音预览",
"price-expect": "您收到的价格可能与您预期有差异,并且无法保证完全执行。为了您的安全,最大滑点保持为 2.5%。超过 2.5%滑点的部分不会被平仓。",
@ -77,19 +78,22 @@
"stable-price": "穩定價格",
"taker": "吃單者",
"tick-size": "波動單位",
"taker-fee": "Taker Fee",
"tooltip-borrow-balance": "You'll use your {{balance}} {{token}} balance and borrow {{borrowAmount}} {{token}} to execute this trade. The current {{token}} variable borrow rate is {{rate}}%",
"tooltip-borrow-no-balance": "You'll borrow {{borrowAmount}} {{token}} to execute this trade. The current {{token}} variable borrow rate is {{rate}}%",
"tooltip-enable-margin": "為此交易啟用保證金",
"tooltip-ioc": "IOC交易若不吃單就會被取消。任何無法立刻成交的部分將被取消",
"tooltip-insured": "如果發生破產,{{tokenOrMarket}}損失是否可以從保險基金中歸還",
"tooltip-post": "Post交易若不掛單就會被取消。",
"tooltip-slippage": "當前價格與您的交易將執行的價格之間的差值的估計",
"tooltip-stable-price": "穩定價格用於一個安全機制。此機制可以限制用戶在預言機價格快速波動時下風險高的訂單",
"tooltip-volume-alert": "交易量警報設定",
"trade-sounds-tooltip": "為每筆新交易播放警報聲音",
"trades": "交易",
"tweet-position": "分享至Twitter",
"unsettled": "未結清",
"volume-alert": "交易量警報",
"volume-alert-desc": "交易量超過警報設定時播放聲音"
"tooltip-enable-margin": "Enable spot margin for this trade",
"tooltip-ioc": "Immediate-Or-Cancel (IOC) orders are guaranteed to be the taker and must be executed immediately. Any portion of the order that can't be filled immediately will be cancelled",
"tooltip-insured": "Whether or not {{tokenOrMarket}} losses can be recovered from the insurance fund in the event of bankruptcies.",
"tooltip-post": "Post orders are guaranteed to be the maker or they will be canceled",
"tooltip-slippage": "An estimate of the difference between the current price and the price your trade will be executed at",
"tooltip-volume-alert": "Volume Alert Settings",
"tooltip-stable-price": "Stable price is used in a safety mechanism that limits a user's ability to enter risky positions when the oracle price is changing rapidly",
"total-pnl": "Total PnL",
"trade-sounds-tooltip": "Play a sound alert for every new trade",
"trades": "Trades",
"tweet-position": "Share to Twitter",
"unrealized-pnl": "Unrealized PnL",
"unsettled": "Unsettled",
"volume-alert": "Volume Alert",
"volume-alert-desc": "Play a sound whenever volume exceeds your alert threshold"
}

View File

@ -89,6 +89,7 @@
"interest-earned-paid": "獲取利息",
"leaderboard": "排行榜",
"learn": "學",
"learn-more": "Learn More",
"leverage": "槓桿",
"liability-weight": "債務權重",
"liquidity": "流動性",

View File

@ -1,34 +1,34 @@
{
"24h-volume": "24h Volume",
"activate-volume-alert": "開啟交易量警報",
"amount": "數量",
"activate-volume-alert": "Activate Volume Alert",
"amount": "Amount",
"average-funding": "Average {{interval}} Funding",
"base": "基礎",
"book": "掛單薄",
"buys": "買單",
"cancel-order-error": "取消掛單出錯",
"close-confirm": "市場平倉您的{{config_name}}持倉",
"close-position": "平倉",
"connect-orders": "連接以查看您的訂單",
"connect-positions": "連接以查看您的持倉",
"connect-trade-history": "連接以查看交易紀錄",
"connect-unsettled": "連接以查看未結清餘額",
"copy-and-share": "複製影像",
"current-price": "目前價格",
"base": "Base",
"book": "Book",
"buys": "Buys",
"cancel-order-error": "Failed to cancel order",
"close-confirm": "Market close your {{config_name}} position",
"close-position": "Close Position",
"connect-orders": "Connect to view your open orders",
"connect-positions": "Connect to view your perp positions",
"connect-trade-history": "Connect to view your trade history",
"connect-unsettled": "Connect to view your unsettled funds",
"copy-and-share": "Copy Image to Clipboard",
"current-price": "Current Price",
"edit-order": "Edit Order",
"entry-price": "入場價",
"est-slippage": "預計下滑",
"funding-limits": "資金費限制",
"funding-rate": "資金費率",
"grouping": "分組",
"hide-asks": "隱藏要價",
"hide-bids": "隱藏出價",
"in-orders": "在掛單中",
"init-leverage": "初始槓桿",
"instantaneous-funding": "瞬時資金費率",
"insured": "被{{token}}保險",
"interval-seconds": "間隔(秒)",
"last-updated": "最近更新",
"entry-price": "Entry Price",
"est-slippage": "Est. Slippage",
"funding-limits": "Funding Limits",
"funding-rate": "1h Avg Funding Rate",
"grouping": "Grouping",
"hide-asks": "Hide Asks",
"hide-bids": "Hide Bids",
"in-orders": "In Orders",
"init-leverage": "Init Leverage",
"instantaneous-funding": "Instantaneous Funding Snapshot",
"interval-seconds": "Interval (seconds)",
"insured": "{{token}} Insured",
"last-updated": "Last updated",
"limit": "Limit",
"limit-price": "限價價格",
"long": "做多",
@ -41,24 +41,24 @@
"min-order-size": "最小訂單量",
"min-order-size-error": "Min order size is {{minSize}} {{symbol}}",
"more-details": "More Details",
"no-balances": "您沒有餘額",
"no-orders": "您沒有訂單",
"no-positions": "您沒有持倉",
"no-unsettled": "您沒有未結清餘額",
"notional": "合約面值",
"notional-volume": "面值交易量($)",
"open-interest": "持倉量",
"oracle": "預言機",
"oracle-not-updated": "此預言機最近沒有更新。",
"oracle-not-updated-warning": "含有此幣種的帳戶無法進行活動。",
"oracle-price": "預言機價格",
"order-error": "下訂單出錯了",
"order-type": "訂單方式",
"order-value": "訂單價值",
"orders": "訂單",
"place-order": "下{{side}}單",
"placing-order": "正在下單",
"positions": "當前持倉",
"no-balances": "No balances",
"no-orders": "No open orders",
"no-positions": "No perp positions",
"no-unsettled": "No unsettled funds",
"notional": "Notional",
"notional-volume": "Notional Volume ($)",
"open-interest": "Open Interest",
"oracle": "Oracle",
"oracle-not-updated": "This oracle has not updated recently.",
"oracle-not-updated-warning": "Actions will fail for accounts with a position in this token.",
"oracle-price": "Oracle Price",
"order-error": "Failed to place order",
"order-type": "Order Type",
"order-value": "Order Value",
"orders": "Orders",
"place-order": "Place {{side}} Order",
"placing-order": "Placing Order",
"positions": "Positions",
"post": "Post",
"preview-sound": "聲音預覽",
"price-expect": "您收到的價格可能與您預期有差異,並且無法保證完全執行。為了您的安全,最大滑點保持為 2.5%。超過 2.5%滑點的部分不會被平倉。",
@ -79,19 +79,22 @@
"taker": "吃單者",
"taker-fee": "吃單者 Fee",
"tick-size": "波動單位",
"realized-pnl": "Realized PnL",
"tooltip-borrow-balance": "You'll use your {{balance}} {{token}} balance and borrow {{borrowAmount}} {{token}} to execute this trade. The current {{token}} variable borrow rate is {{rate}}%",
"tooltip-borrow-no-balance": "You'll borrow {{borrowAmount}} {{token}} to execute this trade. The current {{token}} variable borrow rate is {{rate}}%",
"tooltip-enable-margin": "為此交易啟用保證金",
"tooltip-ioc": "IOC交易若不吃單就會被取消。任何無法立刻成交的部分將被取消",
"tooltip-insured": "如果發生破產,{{tokenOrMarket}}損失是否可以從保險基金中歸還",
"tooltip-post": "Post交易若不掛單就會被取消。",
"tooltip-slippage": "當前價格與您的交易將執行的價格之間的差值的估計",
"tooltip-stable-price": "穩定價格用於一個安全機制。此機制可以限制用戶在預言機價格快速波動時下風險高的訂單",
"tooltip-volume-alert": "交易量警報設定",
"trade-sounds-tooltip": "為每筆新交易播放警報聲音",
"trades": "交易",
"tweet-position": "分享至Twitter",
"unsettled": "未結清",
"volume-alert": "交易量警報",
"volume-alert-desc": "交易量超過警報設定時播放聲音"
"tooltip-enable-margin": "Enable spot margin for this trade",
"tooltip-ioc": "Immediate-Or-Cancel (IOC) orders are guaranteed to be the taker and must be executed immediately. Any portion of the order that can't be filled immediately will be cancelled",
"tooltip-insured": "Whether or not {{tokenOrMarket}} losses can be recovered from the insurance fund in the event of bankruptcies.",
"tooltip-post": "Post orders are guaranteed to be the maker or they will be canceled",
"tooltip-slippage": "An estimate of the difference between the current price and the price your trade will be executed at",
"tooltip-volume-alert": "Volume Alert Settings",
"tooltip-stable-price": "Stable price is used in a safety mechanism that limits a user's ability to enter risky positions when the oracle price is changing rapidly",
"total-pnl": "Total PnL",
"trade-sounds-tooltip": "Play a sound alert for every new trade",
"trades": "Trades",
"tweet-position": "Share to Twitter",
"unrealized-pnl": "Unrealized PnL",
"unsettled": "Unsettled",
"volume-alert": "Volume Alert",
"volume-alert-desc": "Play a sound whenever volume exceeds your alert threshold"
}

View File

@ -1,4 +1,4 @@
import { AnchorProvider, BN } from '@project-serum/anchor'
import { AnchorProvider, BN } from '@coral-xyz/anchor'
import {
getAllProposals,
getGovernanceAccounts,

View File

@ -2,7 +2,7 @@ import dayjs from 'dayjs'
import produce from 'immer'
import create from 'zustand'
import { subscribeWithSelector } from 'zustand/middleware'
import { AnchorProvider, BN, Wallet, web3 } from '@project-serum/anchor'
import { AnchorProvider, BN, Wallet, web3 } from '@coral-xyz/anchor'
import { Connection, Keypair, PublicKey } from '@solana/web3.js'
import { OpenOrders, Order } from '@project-serum/serum/lib/market'
import { Orderbook } from '@project-serum/serum'
@ -75,10 +75,10 @@ const ENDPOINTS = [
name: 'mainnet-beta',
url:
process.env.NEXT_PUBLIC_ENDPOINT ||
'https://mango.rpcpool.com/0f9acc0d45173b51bf7d7e09c1e5',
'https://mango.rpcpool.com/946ef7337da3f5b8d3e4a34e7f88',
websocket:
process.env.NEXT_PUBLIC_ENDPOINT ||
'https://mango.rpcpool.com/0f9acc0d45173b51bf7d7e09c1e5',
'https://mango.rpcpool.com/946ef7337da3f5b8d3e4a34e7f88',
custom: false,
},
{
@ -481,7 +481,15 @@ const mangoStore = create<MangoStore>()(
const latestFeed = entries
.map(([key, value]) => {
return { ...value, symbol: key }
// ETH should be renamed to ETH (Portal) in the database
let symbol = value.activity_details.symbol
if (symbol === 'ETH') {
value.activity_details.symbol = 'ETH (Portal)'
}
return {
...value,
symbol: key,
}
})
.sort(
(a, b) =>

View File

@ -610,7 +610,7 @@ input[type='range']::-webkit-slider-runnable-track {
}
.tooltip-underline {
@apply default-transition w-max border-b border-dashed border-th-fgd-4 leading-tight hover:cursor-help hover:border-transparent;
@apply default-transition w-max border-b border-dashed border-current leading-tight hover:cursor-help hover:border-transparent;
}
.radial-gradient-bg {

View File

@ -43,7 +43,7 @@ export const FAVORITE_MARKETS_KEY = 'favoriteMarkets-0.2'
export const THEME_KEY = 'theme-0.1'
export const RPC_PROVIDER_KEY = 'rpcProviderKey-0.4'
export const RPC_PROVIDER_KEY = 'rpcProviderKey-0.5'
export const PRIORITY_FEE_KEY = 'priorityFeeKey-0.1'

View File

@ -1,8 +1,16 @@
import { AnchorProvider, Program } from '@project-serum/anchor'
import { AnchorProvider, Program } from '@coral-xyz/anchor'
import { PythHttpClient } from '@pythnetwork/client'
import { notify } from 'utils/notifications'
import { MAINNET_PYTH_PROGRAM } from './constants'
import { OPENBOOK_PROGRAM_ID, toNative } from '@blockworks-foundation/mango-v4'
import {
Bank,
Group,
I80F48,
OPENBOOK_PROGRAM_ID,
toNative,
toUiDecimals,
toUiDecimalsForQuote,
} from '@blockworks-foundation/mango-v4'
import { Market } from '@project-serum/serum'
import { Connection, Keypair, PublicKey } from '@solana/web3.js'
import EmptyWallet from 'utils/wallet'
@ -307,8 +315,13 @@ const listingBase = {
insuranceFound: true,
borrowWeightScale: toNative(250000, 6).toNumber(),
depositWeightScale: toNative(250000, 6).toNumber(),
preset_key: 'PREMIUM',
preset_name: 'Blue chip',
target_amount: 100000,
}
export type ListingPreset = typeof listingBase
export type LISTING_PRESETS_KEYS =
| 'PREMIUM'
| 'MID'
@ -317,14 +330,11 @@ export type LISTING_PRESETS_KEYS =
| 'UNTRUSTED'
export const LISTING_PRESETS: {
[key in LISTING_PRESETS_KEYS]:
| (typeof listingBase & { name: string })
| Record<string, never>
[key in LISTING_PRESETS_KEYS]: ListingPreset | Record<string, never>
} = {
//Price impact $100,000 < 1%
PREMIUM: {
...listingBase,
name: 'Premium',
},
//Price impact $20,000 < 1%
MID: {
@ -335,10 +345,12 @@ export const LISTING_PRESETS: {
initLiabWeight: 1.4,
liquidationFee: 0.1,
netBorrowLimitPerWindowQuote: toNative(20000, 6).toNumber(),
name: 'Mid',
borrowWeightScale: toNative(50000, 6).toNumber(),
depositWeightScale: toNative(50000, 6).toNumber(),
insuranceFound: false,
preset_key: 'MID',
preset_name: 'Midwit',
target_amount: 20000,
},
//Price impact $5,000 < 1%
MEME: {
@ -354,7 +366,9 @@ export const LISTING_PRESETS: {
borrowWeightScale: toNative(20000, 6).toNumber(),
depositWeightScale: toNative(20000, 6).toNumber(),
insuranceFound: false,
name: 'Meme',
preset_key: 'MEME',
preset_name: 'Meme Coin',
target_amount: 5000,
},
//Price impact $1,000 < 1%
SHIT: {
@ -370,7 +384,9 @@ export const LISTING_PRESETS: {
borrowWeightScale: toNative(5000, 6).toNumber(),
depositWeightScale: toNative(5000, 6).toNumber(),
insuranceFound: false,
name: 'Shit',
preset_key: 'SHIT',
preset_name: 'Shit Coin',
target_amount: 1000,
},
UNTRUSTED: {},
}
@ -384,3 +400,128 @@ export const coinTiersToNames: {
SHIT: 'Shit Coin',
UNTRUSTED: 'Untrusted',
}
export const formatSuggestedValues = (
suggestedParams:
| Record<string, never>
| Omit<
typeof listingBase,
'name' | 'netBorrowLimitWindowSizeTs' | 'insuranceFound'
>
) => {
return {
maxStalenessSlots: suggestedParams.maxStalenessSlots,
oracleConfFilter: (100 * suggestedParams.oracleConfFilter).toFixed(2),
adjustmentFactor: (suggestedParams.adjustmentFactor * 100).toFixed(2),
rate0: (100 * suggestedParams.rate0).toFixed(2),
util0: (100 * suggestedParams.util0).toFixed(),
rate1: (100 * suggestedParams.rate1).toFixed(2),
util1: (100 * suggestedParams.util1).toFixed(),
maxRate: (100 * suggestedParams.maxRate).toFixed(2),
loanFeeRate: (10000 * suggestedParams.loanFeeRate).toFixed(2),
loanOriginationFeeRate: (
10000 * suggestedParams.loanOriginationFeeRate
).toFixed(2),
maintAssetWeight: suggestedParams.maintAssetWeight.toFixed(2),
initAssetWeight: suggestedParams.initAssetWeight.toFixed(2),
maintLiabWeight: suggestedParams.maintLiabWeight.toFixed(2),
initLiabWeight: suggestedParams.initLiabWeight.toFixed(2),
liquidationFee: (suggestedParams.liquidationFee * 100).toFixed(2),
minVaultToDepositsRatio: suggestedParams.minVaultToDepositsRatio * 100,
netBorrowLimitPerWindowQuote: toUiDecimals(
suggestedParams.netBorrowLimitPerWindowQuote,
6
),
borrowWeightScale: toUiDecimals(suggestedParams.borrowWeightScale, 6),
depositWeightScale: toUiDecimals(suggestedParams.depositWeightScale, 6),
}
}
export const getFormattedBankValues = (group: Group, bank: Bank) => {
return {
...bank,
publicKey: bank.publicKey.toBase58(),
vault: bank.vault.toBase58(),
oracle: bank.oracle.toBase58(),
stablePrice: group.toUiPrice(
I80F48.fromNumber(bank.stablePriceModel.stablePrice),
bank.mintDecimals
),
maxStalenessSlots: bank.oracleConfig.maxStalenessSlots.toNumber(),
lastStablePriceUpdated: new Date(
1000 * bank.stablePriceModel.lastUpdateTimestamp.toNumber()
).toUTCString(),
stablePriceGrowthLimitsDelay: (
100 * bank.stablePriceModel.delayGrowthLimit
).toFixed(2),
stablePriceGrowthLimitsStable: (
100 * bank.stablePriceModel.stableGrowthLimit
).toFixed(2),
loanFeeRate: (10000 * bank.loanFeeRate.toNumber()).toFixed(2),
loanOriginationFeeRate: (
10000 * bank.loanOriginationFeeRate.toNumber()
).toFixed(2),
collectedFeesNative: toUiDecimals(
bank.collectedFeesNative.toNumber(),
bank.mintDecimals
).toFixed(2),
collectedFeesNativePrice: (
toUiDecimals(bank.collectedFeesNative.toNumber(), bank.mintDecimals) *
bank.uiPrice
).toFixed(2),
dust: bank.dust.toNumber(),
deposits: toUiDecimals(
bank.indexedDeposits.mul(bank.depositIndex).toNumber(),
bank.mintDecimals
),
depositsPrice: (
toUiDecimals(
bank.indexedDeposits.mul(bank.depositIndex).toNumber(),
bank.mintDecimals
) * bank.uiPrice
).toFixed(2),
borrows: toUiDecimals(
bank.indexedBorrows.mul(bank.borrowIndex).toNumber(),
bank.mintDecimals
),
borrowsPrice: (
toUiDecimals(
bank.indexedBorrows.mul(bank.borrowIndex).toNumber(),
bank.mintDecimals
) * bank.uiPrice
).toFixed(2),
avgUtilization: bank.avgUtilization.toNumber() * 100,
maintAssetWeight: bank.maintAssetWeight.toFixed(2),
maintLiabWeight: bank.maintLiabWeight.toFixed(2),
initAssetWeight: bank.initAssetWeight.toFixed(2),
initLiabWeight: bank.initLiabWeight.toFixed(2),
depositWeightScale: toUiDecimalsForQuote(bank.depositWeightScaleStartQuote),
borrowWeightScale: toUiDecimalsForQuote(bank.borrowWeightScaleStartQuote),
rate0: (100 * bank.rate0.toNumber()).toFixed(2),
util0: (100 * bank.util0.toNumber()).toFixed(),
rate1: (100 * bank.rate1.toNumber()).toFixed(2),
util1: (100 * bank.util1.toNumber()).toFixed(),
maxRate: (100 * bank.maxRate.toNumber()).toFixed(2),
adjustmentFactor: (bank.adjustmentFactor.toNumber() * 100).toFixed(2),
depositRate: bank.getDepositRateUi(),
borrowRate: bank.getBorrowRateUi(),
lastIndexUpdate: new Date(
1000 * bank.indexLastUpdated.toNumber()
).toUTCString(),
lastRatesUpdate: new Date(
1000 * bank.bankRateLastUpdated.toNumber()
).toUTCString(),
oracleConfFilter: (100 * bank.oracleConfig.confFilter.toNumber()).toFixed(
2
),
minVaultToDepositsRatio: bank.minVaultToDepositsRatio * 100,
netBorrowsInWindow: toUiDecimalsForQuote(
I80F48.fromI64(bank.netBorrowsInWindow).mul(bank.price)
).toFixed(2),
netBorrowLimitPerWindowQuote: toUiDecimals(
bank.netBorrowLimitPerWindowQuote,
6
),
liquidationFee: (bank.liquidationFee.toNumber() * 100).toFixed(2),
}
}

View File

@ -1,4 +1,4 @@
import { BN } from '@project-serum/anchor'
import { BN } from '@coral-xyz/anchor'
import {
Governance,
MintMaxVoteWeightSource,

View File

@ -8,7 +8,7 @@ import {
import { Connection, PublicKey } from '@solana/web3.js'
import { TokenProgramAccount } from './accounts/vsrAccounts'
import { MintLayout, RawMint } from '@solana/spl-token'
import { BN } from '@project-serum/anchor'
import { BN } from '@coral-xyz/anchor'
export async function fetchRealm({
connection,
@ -139,3 +139,21 @@ export async function resolveProposalDescription(descriptionLink: string) {
return descriptionLink
}
}
export const compareObjectsAndGetDifferentKeys = <T extends object>(
object1: T,
object2: T
): (keyof T)[] => {
const diffKeys: string[] = []
Object.keys(object1).forEach((key) => {
if (
object1[key as keyof typeof object1] !==
object2[key as keyof typeof object2]
) {
diffKeys.push(key)
}
})
return diffKeys as (keyof T)[]
}

View File

@ -1,5 +1,5 @@
import { Program, Provider, web3 } from '@coral-xyz/anchor'
import { Idl } from '@project-serum/anchor'
import { Idl } from '@coral-xyz/anchor'
import { PublicKey } from '@solana/web3.js'
export const DEFAULT_VSR_ID = new web3.PublicKey(

View File

@ -1,17 +1,34 @@
import { Wallet } from '@project-serum/anchor'
import { Keypair, PublicKey, Transaction } from '@solana/web3.js'
import { Wallet } from '@coral-xyz/anchor'
import { isVersionedTransaction } from '@solana/wallet-adapter-base'
import {
Keypair,
PublicKey,
Transaction,
VersionedTransaction,
} from '@solana/web3.js'
export default class EmptyWallet implements Wallet {
constructor(readonly payer: Keypair) {}
async signTransaction(tx: Transaction): Promise<Transaction> {
tx.partialSign(this.payer)
async signTransaction<T extends Transaction | VersionedTransaction>(
tx: T
): Promise<T> {
if (isVersionedTransaction(tx)) {
tx.sign([this.payer])
} else {
tx.partialSign(this.payer)
}
return tx
}
async signAllTransactions(txs: Transaction[]): Promise<Transaction[]> {
async signAllTransactions<T extends Transaction | VersionedTransaction>(
txs: T[]
): Promise<T[]> {
return txs.map((t) => {
t.partialSign(this.payer)
if (isVersionedTransaction(t)) {
t.sign([this.payer])
} else {
t.partialSign(this.payer)
}
return t
})
}

View File

@ -21,12 +21,12 @@
dependencies:
ws "^8.13.0"
"@blockworks-foundation/mango-v4@^0.15.13":
version "0.15.13"
resolved "https://registry.yarnpkg.com/@blockworks-foundation/mango-v4/-/mango-v4-0.15.13.tgz#adbfb63a69fc94ddaed9a7d65733e881335d092d"
integrity sha512-akqs0LYK7sjD5mqxwGWBaN7AaPIgDhdUswRWjFRCRXJy1B9la2pmJv9iWjXFU9DDWPORrpu5psFZ0NZ8hYKpnA==
"@blockworks-foundation/mango-v4@^0.16.6":
version "0.16.6"
resolved "https://registry.yarnpkg.com/@blockworks-foundation/mango-v4/-/mango-v4-0.16.6.tgz#abd65dd70f4c81f6f9b08f6d735ea73b53d2a378"
integrity sha512-QKsKiJSbqM0CXcNsrIYaW0TWOTGXktMm4ZQnF+XnO1WyMylq7M5pnA/UPhuGuk2X0KUI9iedVYhoHBO73wdFOA==
dependencies:
"@coral-xyz/anchor" "^0.26.0"
"@coral-xyz/anchor" "^0.27.0"
"@project-serum/serum" "0.13.65"
"@pythnetwork/client" "~2.14.0"
"@solana/spl-token" "0.3.7"
@ -84,28 +84,7 @@
eventemitter3 "^4.0.7"
uuid "^8.3.2"
"@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/anchor@^0.27.0":
"@coral-xyz/anchor@^0.26.0", "@coral-xyz/anchor@^0.27.0":
version "0.27.0"
resolved "https://registry.yarnpkg.com/@coral-xyz/anchor/-/anchor-0.27.0.tgz#621e5ef123d05811b97e49973b4ed7ede27c705c"
integrity sha512-+P/vPdORawvg3A9Wj02iquxb4T0C5m4P6aZBVYysKl4Amk+r6aMPZkUhilBkD6E4Nuxnoajv3CFykUfkGE0n5g==
@ -126,14 +105,6 @@
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"
"@coral-xyz/borsh@^0.27.0":
version "0.27.0"
resolved "https://registry.yarnpkg.com/@coral-xyz/borsh/-/borsh-0.27.0.tgz#700c647ea5262b1488957ac7fb4e8acf72c72b63"