update to latest client and program version

This commit is contained in:
tjs 2022-08-18 16:50:34 -04:00
parent 32ca6ff2f5
commit ae324a6da5
18 changed files with 317 additions and 381 deletions

View File

@ -10,7 +10,7 @@ import { useTranslation } from 'next-i18next'
import { useTheme } from 'next-themes'
import Image from 'next/image'
import { useRouter } from 'next/router'
import { Fragment, useEffect, useMemo, useState } from 'react'
import { Fragment, useCallback, useEffect, useMemo, useState } from 'react'
import { useViewport } from '../hooks/useViewport'
import mangoStore from '../store/state'
@ -53,8 +53,8 @@ const TokenList = () => {
}, [coingeckoPrices, actions])
const banks = useMemo(() => {
if (group?.banksMap) {
const rawBanks = Array.from(group?.banksMap, ([key, value]) => ({
if (group) {
const rawBanks = Array.from(group?.banksMapByName, ([key, value]) => ({
key,
value,
}))
@ -62,17 +62,27 @@ const TokenList = () => {
? showZeroBalances
? rawBanks.sort(
(a, b) =>
Math.abs(mangoAccount?.getUi(b.value) * Number(b.value.price)) -
Math.abs(mangoAccount?.getUi(a.value) * Number(a.value.price))
Math.abs(
mangoAccount?.getTokenBalanceUi(b.value[0]) *
Number(b.value[0].price)
) -
Math.abs(
mangoAccount?.getTokenBalanceUi(a.value[0]) *
Number(a.value[0].price)
)
)
: rawBanks
.filter((b) => mangoAccount?.getUi(b.value) !== 0)
.filter((b) => mangoAccount?.getTokenBalanceUi(b.value[0]) !== 0)
.sort(
(a, b) =>
Math.abs(
mangoAccount?.getUi(b.value) * Number(b.value.price)
mangoAccount?.getTokenBalanceUi(b.value[0]) *
Number(b.value[0].price)
) -
Math.abs(mangoAccount?.getUi(a.value) * Number(a.value.price))
Math.abs(
mangoAccount?.getTokenBalanceUi(a.value[0]) *
Number(a.value[0].price)
)
)
: rawBanks
}
@ -116,11 +126,12 @@ const TokenList = () => {
</tr>
</thead>
<tbody>
{banks.map((bank, index) => {
const oraclePrice = bank.value.price
{banks.map(({ key, value }, index) => {
const bank = value[0]
const oraclePrice = bank.price
const coingeckoData = coingeckoPrices.find(
(asset) => asset.symbol === bank.key
(asset) => asset.symbol === key
)
const change = coingeckoData
@ -135,12 +146,12 @@ const TokenList = () => {
let logoURI
if (jupiterTokens.length) {
logoURI = jupiterTokens.find(
(t) => t.address === bank.value.mint.toString()
(t) => t.address === bank.mint.toString()
)!.logoURI
}
const hasInterestEarned = totalInterestData.find(
(d) => d.symbol === bank.value.name
(d) => d.symbol === bank.name
)
const interestAmount = hasInterestEarned
@ -154,7 +165,7 @@ const TokenList = () => {
: 0.0
return (
<tr key={bank.key}>
<tr key={key}>
<td className="w-[16.67%]">
<div className="flex items-center">
<div className="mr-2.5 flex flex-shrink-0 items-center">
@ -164,7 +175,7 @@ const TokenList = () => {
<QuestionMarkCircleIcon className="h-7 w-7 text-th-fgd-3" />
)}
</div>
<p>{bank.value.name}</p>
<p>{bank.name}</p>
</div>
</td>
<td className="w-[16.67%]">
@ -183,12 +194,12 @@ const TokenList = () => {
}
data={chartData}
height={40}
name={bank.key}
name={key}
width={104}
xKey="0"
yKey="1"
/>
) : bank.key === 'USDC' || bank.key === 'USDT' ? null : (
) : key === 'USDC' || key === 'USDT' ? null : (
<p className="mb-0 text-th-fgd-4">{t('unavailable')}</p>
)
) : (
@ -198,20 +209,16 @@ const TokenList = () => {
<td className="w-[16.67%]">
<div className="flex justify-center space-x-2">
<p className="text-th-green">
{formatDecimal(
bank.value.getDepositRate().toNumber(),
2,
{ fixed: true }
)}
{formatDecimal(bank.getDepositRate().toNumber(), 2, {
fixed: true,
})}
%
</p>
<span className="text-th-fgd-4">|</span>
<p className="text-th-red">
{formatDecimal(
bank.value.getBorrowRate().toNumber(),
2,
{ fixed: true }
)}
{formatDecimal(bank.getBorrowRate().toNumber(), 2, {
fixed: true,
})}
%
</p>
</div>
@ -227,13 +234,13 @@ const TokenList = () => {
<td className="w-[16.67%] pt-4 text-right">
<p className="px-2">
{mangoAccount
? formatDecimal(mangoAccount.getUi(bank.value))
? formatDecimal(mangoAccount.getTokenBalanceUi(bank))
: 0}
</p>
<p className="px-2 text-sm text-th-fgd-4">
{mangoAccount
? `${formatFixedDecimals(
mangoAccount.getUi(bank.value) *
mangoAccount.getTokenBalanceUi(bank) *
oraclePrice.toNumber(),
true
)}`
@ -242,10 +249,7 @@ const TokenList = () => {
</td>
<td className="w-[16.67%]">
<div className="flex justify-end space-x-2">
<ActionsMenu
bank={bank.value}
mangoAccount={mangoAccount}
/>
<ActionsMenu bank={bank} mangoAccount={mangoAccount} />
</div>
</td>
</tr>
@ -255,19 +259,17 @@ const TokenList = () => {
</table>
) : (
<div className="mt-4 space-y-2">
{banks.map((bank) => {
const oraclePrice = bank.value.price
{banks.map(({ key, value }) => {
const bank = value[0]
const oraclePrice = bank.price
let logoURI
if (jupiterTokens.length) {
logoURI = jupiterTokens.find(
(t) => t.address === bank.value.mint.toString()
(t) => t.address === bank.mint.toString()
)!.logoURI
}
return (
<div
key={bank.key}
className="rounded-md border border-th-bkg-4 p-4"
>
<div key={key} className="rounded-md border border-th-bkg-4 p-4">
<div className="flex items-center justify-between">
<div className="flex items-center">
<div className="mr-2.5 flex flex-shrink-0 items-center">
@ -278,28 +280,25 @@ const TokenList = () => {
)}
</div>
<div>
<p>{bank.value.name}</p>
<p>{bank.name}</p>
<p className="text-sm">
<span className="mr-1 text-th-fgd-4">
{t('available')}:
</span>
{mangoAccount
? formatDecimal(mangoAccount.getUi(bank.value))
? formatDecimal(mangoAccount.getTokenBalanceUi(bank))
: 0}
</p>
</div>
</div>
<div className="flex items-center space-x-3">
<ActionsMenu
bank={bank.value}
mangoAccount={mangoAccount}
/>
<ActionsMenu bank={bank} mangoAccount={mangoAccount} />
<IconButton
onClick={() => handleShowTokenDetails(bank.value.name)}
onClick={() => handleShowTokenDetails(bank.name)}
>
<ChevronDownIcon
className={`${
showTokenDetails === bank.value.name
showTokenDetails === bank.name
? 'rotate-180'
: 'rotate-360'
} h-6 w-6 flex-shrink-0 text-th-fgd-1`}
@ -309,7 +308,7 @@ const TokenList = () => {
</div>
<Transition
appear={true}
show={showTokenDetails === bank.value.name}
show={showTokenDetails === bank.name}
as={Fragment}
enter="transition ease-in duration-200"
enterFrom="opacity-0"
@ -338,19 +337,11 @@ const TokenList = () => {
<p className="text-xs text-th-fgd-3">{t('rates')}</p>
<p className="space-x-2 font-bold">
<span className="text-th-green">
{formatDecimal(
bank.value.getDepositRate().toNumber(),
2
)}
%
{formatDecimal(bank.getDepositRate().toNumber(), 2)}%
</span>
<span className="font-normal text-th-fgd-4">|</span>
<span className="text-th-red">
{formatDecimal(
bank.value.getBorrowRate().toNumber(),
2
)}
%
{formatDecimal(bank.getBorrowRate().toNumber(), 2)}%
</span>
</p>
</div>
@ -358,8 +349,8 @@ const TokenList = () => {
<p className="text-xs text-th-fgd-3">{t('liquidity')}</p>
<p className="font-bold">
{formatDecimal(
bank.value.uiDeposits() - bank.value.uiBorrows(),
bank.value.mintDecimals
bank.uiDeposits() - bank.uiBorrows(),
bank.mintDecimals
)}
</p>
</div>
@ -392,37 +383,35 @@ const ActionsMenu = ({
const router = useRouter()
const { asPath } = router
const handleShowActionModals = (
token: string,
action: 'borrow' | 'deposit' | 'withdraw'
) => {
setSelectedToken(token)
action === 'borrow'
? setShowBorrowModal(true)
: action === 'deposit'
? setShowDepositModal(true)
: setShowWithdrawModal(true)
}
const handleShowActionModals = useCallback(
(token: string, action: 'borrow' | 'deposit' | 'withdraw') => {
setSelectedToken(token)
action === 'borrow'
? setShowBorrowModal(true)
: action === 'deposit'
? setShowDepositModal(true)
: setShowWithdrawModal(true)
},
[]
)
const handleBuy = () => {
const handleBuy = useCallback(() => {
set((s) => {
s.swap.inputToken = 'USDC'
s.swap.outputToken = bank.name
s.swap.outputBank = bank
})
if (asPath === '/') {
router.push('/trade', undefined, { shallow: true })
}
}
}, [bank, router, asPath, set])
const handleSell = () => {
const handleSell = useCallback(() => {
set((s) => {
s.swap.inputToken = bank.name
s.swap.outputToken = 'USDC'
s.swap.inputBank = bank
})
if (asPath === '/') {
router.push('/trade', undefined, { shallow: true })
}
}
}, [router, asPath, set, bank])
return (
<>
@ -465,14 +454,14 @@ const ActionsMenu = ({
<LinkButton
className="w-full text-left"
disabled={!mangoAccount}
onClick={() => handleBuy()}
onClick={handleBuy}
>
{t('buy')}
</LinkButton>
<LinkButton
className="w-full text-left"
disabled={!mangoAccount}
onClick={() => handleSell()}
onClick={handleSell}
>
{t('sell')}
</LinkButton>

View File

@ -3,12 +3,16 @@ import Image from 'next/image'
import mangoStore from '../store/state'
type TokenSelectProps = {
token: string
tokenSymbol: string | undefined
showTokenList: (x: any) => void
type: 'input' | 'output'
}
const TokenSelect = ({ token, showTokenList, type }: TokenSelectProps) => {
const TokenSelect = ({
tokenSymbol,
showTokenList,
type,
}: TokenSelectProps) => {
const group = mangoStore((s) => s.group)
const jupiterTokens = mangoStore((s) => s.jupiterTokens)
@ -16,7 +20,7 @@ const TokenSelect = ({ token, showTokenList, type }: TokenSelectProps) => {
let logoURI
if (jupiterTokens.length) {
logoURI = jupiterTokens.find((t) => t.symbol === token)!.logoURI
logoURI = jupiterTokens.find((t) => t.symbol === tokenSymbol)!.logoURI
}
return (
@ -33,7 +37,7 @@ const TokenSelect = ({ token, showTokenList, type }: TokenSelectProps) => {
)}
</div>
<div className="flex w-full items-center justify-between">
<div className="text-xl font-bold text-th-fgd-1">{token}</div>
<div className="text-xl font-bold text-th-fgd-1">{tokenSymbol}</div>
<ChevronDownIcon className="h-6 w-6" />
</div>
</div>

View File

@ -13,7 +13,7 @@ const ActionTokenItem = ({
}: {
bank: Bank
customValue: number
onSelect: (x: any) => void
onSelect: (x: string) => void
showBorrowRates?: boolean
showDepositRates?: boolean
}) => {

View File

@ -9,7 +9,7 @@ const ActionTokenList = ({
showDepositRates,
}: {
banks: any
onSelect: (x: any) => void
onSelect: (x: string) => void
sortByKey: string
showBorrowRates?: boolean
showDepositRates?: boolean

View File

@ -3,7 +3,7 @@ import { ChevronDownIcon } from '@heroicons/react/solid'
import { useTranslation } from 'next-i18next'
import Image from 'next/image'
import React, { ChangeEvent, useCallback, useMemo, useState } from 'react'
import mangoStore from '../../store/state'
import mangoStore, { INPUT_TOKEN_DEFAULT } from '../../store/state'
import { ModalProps } from '../../types/modal'
import { notify } from '../../utils/notifications'
import { formatFixedDecimals } from '../../utils/numbers'
@ -29,14 +29,16 @@ function BorrowModal({ isOpen, onClose, token }: ModalCombinedProps) {
const group = mangoStore((s) => s.group)
const [inputAmount, setInputAmount] = useState('')
const [submitting, setSubmitting] = useState(false)
const [selectedToken, setSelectedToken] = useState(token || 'USDC')
const [selectedToken, setSelectedToken] = useState(
token || INPUT_TOKEN_DEFAULT
)
const [showTokenList, setShowTokenList] = useState(false)
const [sizePercentage, setSizePercentage] = useState('')
const jupiterTokens = mangoStore((s) => s.jupiterTokens)
const bank = useMemo(() => {
const group = mangoStore.getState().group
return group?.banksMap.get(selectedToken)
return group?.banksMapByName.get(selectedToken)![0]
}, [selectedToken])
const logoUri = useMemo(() => {
@ -55,7 +57,7 @@ function BorrowModal({ isOpen, onClose, token }: ModalCombinedProps) {
const group = mangoStore.getState().group
if (!group || !bank) return 0
const amount = mangoAccount
?.getMaxWithdrawWithBorrowForToken(group, selectedToken)
?.getMaxWithdrawWithBorrowForToken(group, bank.mint)
.toNumber()
return amount && amount > 0 ? toUiDecimals(amount, bank.mintDecimals) : 0
}, [mangoAccount, bank, selectedToken])
@ -89,7 +91,7 @@ function BorrowModal({ isOpen, onClose, token }: ModalCombinedProps) {
const tx = await client.tokenWithdraw(
group,
mangoAccount,
selectedToken,
bank!.mint,
parseFloat(inputAmount),
true
)
@ -116,17 +118,18 @@ function BorrowModal({ isOpen, onClose, token }: ModalCombinedProps) {
const banks = useMemo(() => {
if (mangoAccount) {
return group?.banksMap
? Array.from(group?.banksMap, ([key, value]) => {
return group?.banksMapByName
? Array.from(group?.banksMapByName, ([key, value]) => {
const bank = value[0]
const amount = mangoAccount
?.getMaxWithdrawWithBorrowForToken(group, key)
?.getMaxWithdrawWithBorrowForToken(group, bank.mint)
.toNumber()
return {
key,
value,
maxAmount:
amount && amount > 0
? toUiDecimals(amount, value.mintDecimals)
? toUiDecimals(amount, bank.mintDecimals)
: 0,
}
})
@ -230,10 +233,7 @@ function BorrowModal({ isOpen, onClose, token }: ModalCombinedProps) {
/>
</div>
</div>
<HealthImpact
tokenName={selectedToken}
amount={parseFloat(inputAmount)}
/>
<HealthImpact tokenPk={bank!.mint} amount={parseFloat(inputAmount)} />
</div>
<Button
onClick={handleWithdraw}

View File

@ -30,7 +30,7 @@ export const walletBalanceForToken = (
token: string
): { maxAmount: number; maxDecimals: number } => {
const group = mangoStore.getState().group
const bank = group?.banksMap.get(token)
const bank = group?.banksMapByName.get(token)![0]
let walletToken
if (bank) {
@ -58,7 +58,7 @@ function DepositModal({ isOpen, onClose, token }: ModalCombinedProps) {
const bank = useMemo(() => {
const group = mangoStore.getState().group
return group?.banksMap.get(selectedToken)
return group?.banksMapByName.get(selectedToken)![0]
}, [selectedToken])
const logoUri = useMemo(() => {
@ -114,7 +114,7 @@ function DepositModal({ isOpen, onClose, token }: ModalCombinedProps) {
const tx = await client.tokenDeposit(
group,
mangoAccount,
selectedToken,
bank!.mint,
parseFloat(inputAmount)
)
notify({
@ -140,8 +140,8 @@ function DepositModal({ isOpen, onClose, token }: ModalCombinedProps) {
}
const banks = useMemo(() => {
return group?.banksMap
? Array.from(group?.banksMap, ([key, value]) => {
return group?.banksMapByName
? Array.from(group?.banksMapByName, ([key, value]) => {
const walletBalance = walletBalanceForToken(walletTokens, key)
return {
key,
@ -153,7 +153,7 @@ function DepositModal({ isOpen, onClose, token }: ModalCombinedProps) {
}
})
: []
}, [group?.banksMap, walletTokens])
}, [group?.banksMapByName, walletTokens])
return (
<Modal isOpen={isOpen} onClose={onClose}>
@ -243,7 +243,7 @@ function DepositModal({ isOpen, onClose, token }: ModalCombinedProps) {
</div>
</div>
<HealthImpact
tokenName={selectedToken}
tokenPk={bank!.mint}
amount={parseFloat(inputAmount)}
isDeposit
/>

View File

@ -1,6 +1,6 @@
import { Transition } from '@headlessui/react'
import { useTranslation } from 'next-i18next'
import { ChangeEvent, useEffect, useMemo, useState } from 'react'
import { ChangeEvent, useCallback, useEffect, useMemo, useState } from 'react'
import { ModalProps } from '../../types/modal'
// import { PROFILE_CATEGORIES } from '../../utils/profile'
import Input from '../forms/Input'
@ -12,7 +12,6 @@ import Modal from '../shared/Modal'
import useLocalStorageState from '../../hooks/useLocalStorageState'
import { CheckCircleIcon, PencilIcon } from '@heroicons/react/solid'
import { useWallet } from '@solana/wallet-adapter-react'
import { handleWalletConnect } from '../../utils/wallet'
import mangoStore from '../../store/state'
import { IS_ONBOARDED_KEY } from '../Layout'
import { EnterRightExitLeft, FadeInFadeOut } from '../shared/Transitions'
@ -57,12 +56,13 @@ const UserSetupModal = ({ isOpen, onClose }: ModalProps) => {
}
const connectWallet = async () => {
const actions = mangoStore.getState().actions
if (wallet) {
handleWalletConnect(wallet)
actions.handleWalletConnect(wallet)
}
}
const handleCreateAccount = async () => {
const handleCreateAccount = useCallback(async () => {
const client = mangoStore.getState().client
const group = mangoStore.getState().group
const actions = mangoStore.getState().actions
@ -94,22 +94,22 @@ const UserSetupModal = ({ isOpen, onClose }: ModalProps) => {
})
console.log(e)
}
}
}, [accountName, wallet, t])
const handleDeposit = async () => {
const handleDeposit = useCallback(async () => {
const client = mangoStore.getState().client
const group = mangoStore.getState().group
const actions = mangoStore.getState().actions
const mangoAccount = mangoStore.getState().mangoAccount.current
if (!mangoAccount || !group) return
const bank = group.banksMapByName.get(depositToken)![0]
try {
setSubmitDeposit(true)
const tx = await client.tokenDeposit(
group,
mangoAccount,
depositToken,
bank.mint,
parseFloat(depositAmount)
)
notify({
@ -132,7 +132,7 @@ const UserSetupModal = ({ isOpen, onClose }: ModalProps) => {
setSubmitDeposit(false)
console.error(e)
}
}
}, [depositAmount, depositToken, onClose, setIsOnboarded])
useEffect(() => {
if (mangoAccount && showSetupStep === 1) {
@ -148,8 +148,8 @@ const UserSetupModal = ({ isOpen, onClose }: ModalProps) => {
}, [connected, mangoAccountLoading])
const banks = useMemo(() => {
return group?.banksMap
? Array.from(group?.banksMap, ([key, value]) => {
return group?.banksMapByName
? Array.from(group?.banksMapByName, ([key, value]) => {
const walletBalance = walletBalanceForToken(walletTokens, key)
return {
key,
@ -161,7 +161,7 @@ const UserSetupModal = ({ isOpen, onClose }: ModalProps) => {
}
})
: []
}, [group?.banksMap, walletTokens])
}, [group?.banksMapByName, walletTokens])
return (
<Modal isOpen={isOpen} onClose={onClose} disableOutsideClose hideClose>

View File

@ -1,4 +1,5 @@
import { ChevronDownIcon } from '@heroicons/react/solid'
import { PublicKey } from '@solana/web3.js'
import { useTranslation } from 'next-i18next'
import Image from 'next/image'
import { ChangeEvent, useCallback, useMemo, useState } from 'react'
@ -23,19 +24,19 @@ interface WithdrawModalProps {
type ModalCombinedProps = WithdrawModalProps & ModalProps
function WithdrawModal({ isOpen, onClose, token }: ModalCombinedProps) {
function WithdrawModal({ isOpen, onClose }: ModalCombinedProps) {
const { t } = useTranslation('common')
const group = mangoStore((s) => s.group)
const [inputAmount, setInputAmount] = useState('')
const [submitting, setSubmitting] = useState(false)
const [selectedToken, setSelectedToken] = useState(token || 'USDC')
const [selectedToken, setSelectedToken] = useState('USDC')
const [showTokenList, setShowTokenList] = useState(false)
const [sizePercentage, setSizePercentage] = useState('')
const jupiterTokens = mangoStore((s) => s.jupiterTokens)
const bank = useMemo(() => {
const group = mangoStore.getState().group
return group?.banksMap.get(selectedToken)
return group?.banksMapByName.get(selectedToken)![0]
}, [selectedToken])
const logoUri = useMemo(() => {
@ -52,7 +53,7 @@ function WithdrawModal({ isOpen, onClose, token }: ModalCombinedProps) {
const tokenMax = useMemo(() => {
if (!bank) return 0
const amount = mangoAccount?.getUi(bank)
const amount = mangoAccount?.getTokenBalanceUi(bank)
return amount ? floorToDecimal(amount, bank.mintDecimals) : 0
}, [mangoAccount, bank])
@ -76,7 +77,7 @@ function WithdrawModal({ isOpen, onClose, token }: ModalCombinedProps) {
const tx = await client.tokenWithdraw(
group,
mangoAccount,
selectedToken,
bank!.mint,
parseFloat(inputAmount),
false
)
@ -108,9 +109,9 @@ function WithdrawModal({ isOpen, onClose, token }: ModalCombinedProps) {
const banks = useMemo(() => {
if (mangoAccount) {
return group?.banksMap
? Array.from(group?.banksMap, ([key, value]) => {
const accountBalance = mangoAccount?.getUi(value)
return group?.banksMapByName
? Array.from(group?.banksMapByName, ([key, value]) => {
const accountBalance = mangoAccount?.getTokenBalanceUi(value[0])
return {
key,
value,
@ -120,7 +121,7 @@ function WithdrawModal({ isOpen, onClose, token }: ModalCombinedProps) {
: []
}
return []
}, [mangoAccount, group?.banksMap])
}, [mangoAccount, group?.banksMapByName])
return (
<Modal isOpen={isOpen} onClose={onClose}>
@ -207,7 +208,7 @@ function WithdrawModal({ isOpen, onClose, token }: ModalCombinedProps) {
</div>
</div>
<HealthImpact
tokenName={selectedToken}
tokenPk={bank!.mint}
amount={parseFloat(inputAmount)}
/>
</div>

View File

@ -1,5 +1,6 @@
import { HealthType } from '@blockworks-foundation/mango-v4'
import { ArrowRightIcon } from '@heroicons/react/solid'
import { PublicKey } from '@solana/web3.js'
import { useTranslation } from 'next-i18next'
import { useMemo } from 'react'
import mangoStore from '../../store/state'
@ -7,11 +8,11 @@ import mangoStore from '../../store/state'
const HealthImpact = ({
amount,
isDeposit,
tokenName,
tokenPk,
}: {
amount: number
isDeposit?: boolean
tokenName: string
tokenPk: PublicKey
}) => {
const { t } = useTranslation('common')
const mangoAccount = mangoStore((s) => s.mangoAccount.current)
@ -26,7 +27,7 @@ const HealthImpact = ({
if (!group || !mangoAccount) return 0
const projectedHealth = mangoAccount
.simHealthRatioWithTokenPositionChanges(group, [
{ tokenName: tokenName, tokenAmount: isDeposit ? amount : amount * -1 },
{ mintPk: tokenPk, tokenAmount: isDeposit ? amount : amount * -1 },
])
.toNumber()
@ -35,7 +36,7 @@ const HealthImpact = ({
: projectedHealth < 0
? 0
: projectedHealth
}, [mangoAccount, tokenName, amount, isDeposit])
}, [mangoAccount, tokenPk, amount, isDeposit])
return (
<div className="space-y-2 border-y border-th-bkg-3 px-2 py-4">

View File

@ -26,18 +26,17 @@ import Image from 'next/image'
import { formatDecimal } from '../../utils/numbers'
type JupiterRouteInfoProps = {
inputToken: string
outputToken: string
amountIn: Decimal
slippage: number
submitting: boolean
handleSwap: (x: TransactionInstruction[]) => void
onClose: () => void
inputTokenInfo: Token | undefined
jupiter: Jupiter | undefined
routes: RouteInfo[] | undefined
onClose: () => void
outputTokenInfo: Token | undefined
routes: RouteInfo[] | undefined
selectedRoute: RouteInfo | undefined
setSelectedRoute: Dispatch<SetStateAction<RouteInfo | undefined>>
slippage: number
submitting: boolean
}
const parseJupiterRoute = async (
@ -63,7 +62,7 @@ const parseJupiterRoute = async (
}
const JupiterRouteInfo = ({
inputToken,
inputTokenInfo,
amountIn,
handleSwap,
submitting,
@ -85,12 +84,8 @@ const JupiterRouteInfo = ({
const connected = mangoStore((s) => s.connected)
const inputTokenIconUri = useMemo(() => {
if (jupiterTokens.length) {
const found = jupiterTokens.find((t) => t.symbol === inputToken)
return found ? found.logoURI : ''
}
return ''
}, [inputToken, jupiterTokens])
return inputTokenInfo ? inputTokenInfo.logoURI : ''
}, [inputTokenInfo])
const amountOut = useMemo(() => {
if (!selectedRoute || !outputTokenInfo) return
@ -114,27 +109,35 @@ const JupiterRouteInfo = ({
const healthImpact = useMemo(() => {
const group = mangoStore.getState().group
if (!group || !mangoAccount || !outputTokenInfo || !amountOut)
if (
!inputTokenInfo ||
!mangoAccount ||
!outputTokenInfo ||
!amountOut ||
!group
)
return 'Unknown'
const bank = group.banksMap.get(inputToken)!
const simulatedHealthRatio = mangoAccount
.simHealthRatioWithTokenPositionChanges(group, [
{
tokenName: inputToken,
mintPk: new PublicKey(inputTokenInfo.address),
tokenAmount:
toNativeDecimals(
amountIn.toNumber(),
bank.mintDecimals
inputTokenInfo.decimals
).toNumber() * -1,
},
{ tokenName: outputTokenInfo.symbol, tokenAmount: amountOut },
{
mintPk: new PublicKey(outputTokenInfo.address),
tokenAmount: amountOut,
},
])
.toNumber()
// console.log('simulatedHealthRatio', simulatedHealthRatio)
return simulatedHealthRatio
}, [mangoAccount, inputToken, outputTokenInfo, amountIn, amountOut])
}, [mangoAccount, inputTokenInfo, outputTokenInfo, amountIn, amountOut])
const onSwap = async () => {
if (!jupiter || !selectedRoute) return
@ -171,12 +174,14 @@ const JupiterRouteInfo = ({
/>
</div>
</div>
<p className="mb-0.5 text-lg font-bold text-th-fgd-1">{`${amountIn} ${inputToken} for ${amountOut} ${outputTokenInfo.symbol}`}</p>
<p className="mb-0.5 text-lg font-bold text-th-fgd-1">{`${amountIn} ${
inputTokenInfo!.name
} for ${amountOut} ${outputTokenInfo.symbol}`}</p>
<div className="flex items-center justify-end">
<p className="text-right text-sm">
{swapRate ? (
<>
1 {inputToken} {' '}
1 {inputTokenInfo!.name} {' '}
{formatDecimal(amountOut / amountIn.toNumber(), 6)}{' '}
{outputTokenInfo?.symbol}
</>
@ -184,7 +189,7 @@ const JupiterRouteInfo = ({
<>
1 {outputTokenInfo?.symbol} {' '}
{formatDecimal(amountIn.toNumber() / amountOut, 6)}{' '}
{inputToken}
{inputTokenInfo!.name}
</>
)}
</p>
@ -417,7 +422,7 @@ const JupiterRouteInfo = ({
setSelectedRoute={setSelectedRoute}
selectedRoute={selectedRoute}
routes={routes}
inputTokenSymbol={inputToken}
inputTokenSymbol={inputTokenInfo!.name}
outputTokenInfo={outputTokenInfo}
/>
) : null}

View File

@ -1,14 +1,8 @@
import { PublicKey } from '@solana/web3.js'
import { ChangeEvent, useEffect, useRef, useState } from 'react'
import mangoStore from '../../store/state'
import { useTokenMax } from './Swap'
type LeverageSliderProps = {
amount: number
inputToken: string
outputToken: string
onChange: (x: string) => void
}
const LeverageSlider = ({
amount,
leverageMax,
@ -16,7 +10,7 @@ const LeverageSlider = ({
}: {
amount: number
leverageMax: number
onChange: (x: any) => any
onChange: (x: string) => any
}) => {
const [value, setValue] = useState(0)
const inputEl = useRef<HTMLInputElement>(null)
@ -36,8 +30,10 @@ const LeverageSlider = ({
}, [leverageMax, value])
useEffect(() => {
onChange(amount.toString())
setValue(amount)
if (amount) {
onChange(amount.toString())
setValue(amount)
}
}, [amount])
const handleSliderChange = (e: ChangeEvent<HTMLInputElement>) => {
@ -72,11 +68,12 @@ const LeverageSlider = ({
export const SwapLeverageSlider = ({
amount,
inputToken,
outputToken,
onChange,
}: LeverageSliderProps) => {
const { amountWithBorrow } = useTokenMax(inputToken, outputToken)
}: {
amount: number
onChange: (x: string) => void
}) => {
const { amountWithBorrow } = useTokenMax()
return (
<>
@ -96,7 +93,7 @@ export const BorrowLeverageSlider = ({
}: {
amount: number
tokenMax: number
onChange: (x: any) => any
onChange: (x: string) => any
}) => {
return (
<>

View File

@ -1,11 +1,14 @@
import { useState, useCallback, useEffect, useMemo } from 'react'
import { TransactionInstruction } from '@solana/web3.js'
import { PublicKey, TransactionInstruction } from '@solana/web3.js'
import { ArrowDownIcon, CogIcon } from '@heroicons/react/solid'
import { RouteInfo } from '@jup-ag/core'
import NumberFormat, { NumberFormatValues } from 'react-number-format'
import Decimal from 'decimal.js'
import mangoStore from '../../store/state'
import mangoStore, {
INPUT_TOKEN_DEFAULT,
OUTPUT_TOKEN_DEFAULT,
} from '../../store/state'
import ContentBox from '../shared/ContentBox'
import { notify } from '../../utils/notifications'
import JupiterRouteInfo from './JupiterRouteInfo'
@ -45,18 +48,15 @@ const Swap = () => {
const set = mangoStore.getState().set
const useMargin = mangoStore((s) => s.swap.margin)
const slippage = mangoStore((s) => s.swap.slippage)
const inputToken = mangoStore((s) => s.swap.inputToken)
const outputToken = mangoStore((s) => s.swap.outputToken)
const inputTokenInfo = mangoStore((s) => s.swap.inputTokenInfo)
const outputTokenInfo = mangoStore((s) => s.swap.outputTokenInfo)
const jupiterTokens = mangoStore((s) => s.jupiterTokens)
const connected = mangoStore((s) => s.connected)
const [debouncedAmountIn, setDebouncedValue] = useDebounce(
amountInFormValue,
300
)
const [debouncedAmountIn] = useDebounce(amountInFormValue, 300)
const { amountOut, jupiter, outputTokenInfo, routes } = useJupiter({
inputTokenSymbol: inputToken,
outputTokenSymbol: outputToken,
const { amountOut, jupiter, routes } = useJupiter({
inputTokenInfo,
outputTokenInfo,
inputAmount: debouncedAmountIn,
slippage,
})
@ -69,11 +69,6 @@ const Swap = () => {
setAmountInFormValue(e.value)
}, [])
const inputBank = useMemo(() => {
const group = mangoStore.getState().group
return group?.banksMap.get(inputToken)
}, [inputToken])
const handleTokenInSelect = useCallback(
(mintAddress: string) => {
const inputTokenInfo = jupiterTokens.find(
@ -81,10 +76,9 @@ const Swap = () => {
)
const group = mangoStore.getState().group
if (group) {
const banks = Array.from(group.banksMap.values())
const bank = banks.find((b) => b.mint.toString() === mintAddress)
const bank = group.getFirstBankByMint(new PublicKey(mintAddress))
set((s) => {
s.swap.inputToken = bank!.name
s.swap.inputBank = bank
s.swap.inputTokenInfo = inputTokenInfo
})
}
@ -100,10 +94,9 @@ const Swap = () => {
)
const group = mangoStore.getState().group
if (group) {
const banks = Array.from(group.banksMap.values())
const bank = banks.find((b) => b.mint.toString() === mintAddress)
const bank = group.getFirstBankByMint(new PublicKey(mintAddress))
set((s) => {
s.swap.outputToken = bank!.name
s.swap.outputBank = bank
s.swap.outputTokenInfo = outputTokenInfo
})
}
@ -113,24 +106,19 @@ const Swap = () => {
)
const handleSwitchTokens = useCallback(() => {
const inputTokenInfo = jupiterTokens.find(
(t: any) => t.symbol === inputToken
)
const outputTokenInfo = jupiterTokens.find(
(t: any) => t.symbol === outputToken
)
setAmountInFormValue(amountOut.toString())
const inputBank = mangoStore.getState().swap.inputBank
const outputBank = mangoStore.getState().swap.outputBank
set((s) => {
s.swap.inputToken = outputToken
s.swap.outputToken = inputToken
s.swap.inputBank = outputBank
s.swap.outputBank = inputBank
s.swap.inputTokenInfo = outputTokenInfo
s.swap.outputTokenInfo = inputTokenInfo
})
setAnimateSwitchArrow(
(prevanimateSwitchArrow) => prevanimateSwitchArrow + 1
)
}, [jupiterTokens, inputToken, outputToken, set, amountOut])
}, [inputTokenInfo, outputTokenInfo, set, amountOut])
const handleSwap = useCallback(
async (userDefinedInstructions: TransactionInstruction[]) => {
@ -138,17 +126,20 @@ const Swap = () => {
const group = mangoStore.getState().group
const actions = mangoStore.getState().actions
const mangoAccount = mangoStore.getState().mangoAccount.current
if (!mangoAccount || !group) return
const inputBank = mangoStore.getState().swap.inputBank
const outputBank = mangoStore.getState().swap.outputBank
if (!mangoAccount || !group || !inputBank || !outputBank) return
try {
setSubmitting(true)
const tx = await client.marginTrade({
group,
mangoAccount,
inputToken,
inputMintPk: inputBank.mint,
amountIn: parseFloat(debouncedAmountIn),
outputToken,
outputMintPk: outputBank.mint,
userDefinedInstructions,
flashLoanType: 'swap',
})
console.log('Success swapping:', tx)
notify({
@ -170,7 +161,7 @@ const Swap = () => {
setSubmitting(false)
}
},
[debouncedAmountIn, inputToken, outputToken]
[debouncedAmountIn]
)
const amountIn: Decimal | null = useMemo(() => {
@ -198,9 +189,8 @@ const Swap = () => {
leaveTo="translate-x-full"
>
<JupiterRouteInfo
inputToken={inputToken}
inputTokenInfo={inputTokenInfo}
onClose={() => setShowConfirm(false)}
outputToken={outputToken}
amountIn={amountIn}
slippage={slippage}
handleSwap={handleSwap}
@ -246,15 +236,13 @@ const Swap = () => {
<p className="text-th-fgd-3">{t('sell')}</p>
<MaxSwapAmount
useMargin={useMargin}
inputToken={inputToken}
outputToken={outputToken}
setAmountIn={setAmountInFormValue}
/>
</div>
<div className="mb-3 grid grid-cols-2">
<div className="col-span-1 rounded-lg rounded-r-none border border-r-0 border-th-bkg-4 bg-th-bkg-1">
<TokenSelect
token={inputToken}
tokenSymbol={inputTokenInfo?.symbol || INPUT_TOKEN_DEFAULT}
showTokenList={setShowTokenSelect}
type="input"
/>
@ -263,7 +251,7 @@ const Swap = () => {
<NumberFormat
inputMode="decimal"
thousandSeparator=","
decimalScale={inputBank?.mintDecimals || 6}
decimalScale={inputTokenInfo?.decimals || 6}
name="amountIn"
id="amountIn"
className="w-full rounded-lg rounded-l-none border border-th-bkg-4 bg-th-bkg-1 p-3 text-right text-xl font-bold tracking-wider text-th-fgd-1 focus:outline-none"
@ -274,11 +262,7 @@ const Swap = () => {
/>
</div>
{!useMargin ? (
<PercentageSelectButtons
setAmountIn={setAmountInFormValue}
inputToken={inputToken}
outputToken={outputToken}
/>
<PercentageSelectButtons setAmountIn={setAmountInFormValue} />
) : null}
</div>
<div className="flex justify-center">
@ -300,7 +284,7 @@ const Swap = () => {
<div className="mb-3 grid grid-cols-2">
<div className="col-span-1 rounded-lg rounded-r-none border border-r-0 border-th-bkg-4 bg-th-bkg-1">
<TokenSelect
token={outputToken}
tokenSymbol={outputTokenInfo?.symbol || OUTPUT_TOKEN_DEFAULT}
showTokenList={setShowTokenSelect}
type="output"
/>
@ -314,7 +298,7 @@ const Swap = () => {
</div>
) : (
<span className="p-3">
{amountOut ? numberFormat.format(amountOut) : 0}
{amountOut ? numberFormat.format(amountOut) : ''}
</span>
)}
</div>
@ -327,8 +311,6 @@ const Swap = () => {
</div>
<SwapLeverageSlider
amount={amountIn.toNumber()}
inputToken={inputToken}
outputToken={outputToken}
onChange={setAmountInFormValue}
/>
</>
@ -361,53 +343,47 @@ const Swap = () => {
export default Swap
export const useTokenMax = (inputToken: string, outputToken: string) => {
export const useTokenMax = () => {
const mangoAccount = mangoStore((s) => s.mangoAccount.current)
const inputBank = mangoStore((s) => s.swap.inputBank)
const outputBank = mangoStore((s) => s.swap.outputBank)
const tokenInMax = useMemo(() => {
const group = mangoStore.getState().group
const bank = group?.banksMap.get(inputToken)
if (!group || !bank || !mangoAccount)
if (!group || !inputBank || !mangoAccount || !outputBank)
return { amount: 0.0, decimals: 6, amountWithBorrow: 0.0 }
const amount = mangoAccount.getUi(bank)
const amount = mangoAccount.getTokenBalanceUi(inputBank)
const amountWithBorrow = mangoAccount
?.getMaxSourceForTokenSwap(group, inputToken, outputToken, 0.94)
?.getMaxSourceForTokenSwap(group, inputBank.mint, outputBank.mint, 0.94)
.toNumber()
return {
amount: amount > 0 ? floorToDecimal(amount, bank.mintDecimals) : 0,
amount: amount > 0 ? floorToDecimal(amount, inputBank.mintDecimals) : 0,
amountWithBorrow:
amountWithBorrow > 0
? floorToDecimal(
toUiDecimals(amountWithBorrow, bank.mintDecimals),
bank.mintDecimals
toUiDecimals(amountWithBorrow, inputBank.mintDecimals),
inputBank.mintDecimals
)
: 0,
decimals: bank.mintDecimals,
decimals: inputBank.mintDecimals,
}
}, [inputToken, mangoAccount, outputToken])
}, [inputBank, mangoAccount, outputBank])
return tokenInMax
}
const MaxSwapAmount = ({
inputToken,
outputToken,
setAmountIn,
useMargin,
}: {
inputToken: string
outputToken: string
setAmountIn: (x: any) => void
useMargin: boolean
}) => {
const { t } = useTranslation('common')
const { amount: tokenMax, amountWithBorrow } = useTokenMax(
inputToken,
outputToken
)
const { amount: tokenMax, amountWithBorrow } = useTokenMax()
const setMaxInputAmount = () => {
const amountIn = useMargin ? amountWithBorrow : tokenMax
@ -425,16 +401,12 @@ const MaxSwapAmount = ({
}
const PercentageSelectButtons = ({
inputToken,
outputToken,
setAmountIn,
}: {
inputToken: string
outputToken: string
setAmountIn: (x: any) => any
}) => {
const [sizePercentage, setSizePercentage] = useState('')
const { amount: tokenMax, decimals } = useTokenMax(inputToken, outputToken)
const { amount: tokenMax, decimals } = useTokenMax()
const handleSizePercentage = (percentage: string) => {
setSizePercentage(percentage)

View File

@ -6,29 +6,28 @@ import Decimal from 'decimal.js'
import mangoStore, { CLUSTER } from '../../store/state'
import { Token } from '../../types/jupiter'
import { PublicKey } from '@solana/web3.js'
type useJupiterPropTypes = {
inputTokenSymbol: string
outputTokenSymbol: string
inputTokenInfo: Token | undefined
outputTokenInfo: Token | undefined
inputAmount: string
slippage: number
}
type RouteParams = {
routes: RouteInfo[]
outputTokenInfo: Token | undefined
amountOut: number
}
const defaultComputedInfo = {
routes: [],
outputTokenInfo: undefined,
amountOut: 0,
}
const useJupiter = ({
inputTokenSymbol,
outputTokenSymbol,
inputTokenInfo,
outputTokenInfo,
inputAmount,
slippage,
}: useJupiterPropTypes) => {
@ -61,19 +60,17 @@ const useJupiter = ({
const tokens = mangoStore.getState().jupiterTokens
const loadRoutes = async () => {
const inputBank = group.banksMap.get(inputTokenSymbol)
const outputBank = group.banksMap.get(outputTokenSymbol)
if (!inputBank || !outputBank) return
if (!outputTokenInfo || !inputTokenInfo) return
if (!inputAmount) {
setComputedInfo(defaultComputedInfo)
} else {
try {
const computedRoutes = await jupiter
?.computeRoutes({
inputMint: inputBank.mint, // Mint address of the input token
outputMint: outputBank.mint, // Mint address of the output token
inputMint: new PublicKey(inputTokenInfo.address), // Mint address of the input token
outputMint: new PublicKey(outputTokenInfo.address), // Mint address of the output token
amount: JSBI.BigInt(
new Decimal(inputAmount).mul(10 ** inputBank.mintDecimals)
new Decimal(inputAmount).mul(10 ** inputTokenInfo.decimals)
),
slippage, // The slippage in % terms
filterTopNResult: 10,
@ -83,9 +80,7 @@ const useJupiter = ({
console.error('Error computing Jupiter routes:', e)
return
})
const tokenOut = tokens.find(
(t: any) => t.address === outputBank.mint.toString()
)
const routesInfosWithoutRaydium = computedRoutes?.routesInfos.filter(
(r) => {
for (const mkt of r.marketInfos) {
@ -101,10 +96,9 @@ const useJupiter = ({
setComputedInfo({
routes: routesInfosWithoutRaydium,
outputTokenInfo: tokenOut,
amountOut: toUiDecimals(
JSBI.toNumber(bestRoute.outAmount),
tokenOut?.decimals!
outputTokenInfo.decimals!
),
})
}
@ -115,7 +109,7 @@ const useJupiter = ({
}
loadRoutes()
}, [inputTokenSymbol, outputTokenSymbol, jupiter, slippage, inputAmount])
}, [inputTokenInfo, outputTokenInfo, jupiter, slippage, inputAmount])
return { jupiter, ...computedInfo }
}

View File

@ -4,26 +4,9 @@ import { WalletReadyState } from '@solana/wallet-adapter-base'
import { useTranslation } from 'next-i18next'
// import AccountsModal from './AccountsModal'
import uniqBy from 'lodash/uniqBy'
import { notify } from '../../utils/notifications'
import WalletSelect from './WalletSelect'
import mangoStore from '../../store/state'
export const handleWalletConnect = (wallet: Wallet) => {
if (!wallet) {
return
}
wallet?.adapter?.connect().catch((e) => {
if (e.name.includes('WalletLoadError')) {
notify({
title: `${wallet.adapter.name} Error`,
type: 'error',
description: `Please install ${wallet.adapter.name} and then reload this page.`,
})
}
})
}
export const ConnectWalletButton: React.FC = () => {
const { wallet, wallets, select } = useWallet()
const { t } = useTranslation('common')
@ -49,11 +32,12 @@ export const ConnectWalletButton: React.FC = () => {
const handleConnect = useCallback(() => {
const set = mangoStore.getState().set
const actions = mangoStore.getState().actions
if (wallet) {
set((state) => {
state.mangoAccount.loading = true
})
handleWalletConnect(wallet)
actions.handleWalletConnect(wallet)
}
}, [wallet])

View File

@ -5,12 +5,12 @@ import { Wallet } from '@project-serum/anchor'
const WalletListener = () => {
const { wallet, connected, disconnecting } = useWallet()
const loadingMangoAccounts = mangoStore((s) => s.mangoAccounts.loading)
const mangoAccounts = mangoStore((s) => s.mangoAccounts.accounts)
useEffect(() => {
const actions = mangoStore.getState().actions
const set = mangoStore.getState().set
const mangoAccounts = mangoStore.getState().mangoAccounts.accounts
const loadingMangoAccounts = mangoStore.getState().mangoAccounts.loading
const onConnect = async () => {
if (!wallet) return
@ -21,11 +21,9 @@ const WalletListener = () => {
mangoAccounts[0].accountNum
)
} else {
if (!loadingMangoAccounts) {
set((s) => {
s.mangoAccount.loading = false
})
}
set((s) => {
s.mangoAccount.loading = false
})
}
actions.fetchProfilePicture(wallet.adapter as unknown as Wallet)
actions.fetchWalletTokens(wallet.adapter as unknown as Wallet)
@ -35,7 +33,7 @@ const WalletListener = () => {
if (connected) {
onConnect()
}
}, [wallet, connected, loadingMangoAccounts, mangoAccounts.length])
}, [wallet, connected])
useEffect(() => {
const setStore = mangoStore.getState().set

View File

@ -1,17 +1,27 @@
import dayjs from 'dayjs'
import produce from 'immer'
import create from 'zustand'
import { subscribeWithSelector } from 'zustand/middleware'
import produce from 'immer'
import { AnchorProvider, Wallet, web3 } from '@project-serum/anchor'
import {
AnchorProvider,
Wallet as AnchorWallet,
web3,
} from '@project-serum/anchor'
import { Connection, Keypair, PublicKey } from '@solana/web3.js'
import { getProfilePicture, ProfilePicture } from '@solflare-wallet/pfp'
import { TOKEN_LIST_URL } from '@jup-ag/core'
import { Order } from '@project-serum/serum/lib/market'
import { Wallet } from '@solana/wallet-adapter-react'
import {
MangoClient,
Group,
MangoAccount,
Serum3Market,
MANGO_V4_ID,
Bank,
} from '@blockworks-foundation/mango-v4'
import EmptyWallet from '../utils/wallet'
import { Order } from '@project-serum/serum/lib/market'
import { Notification, notify } from '../utils/notifications'
import {
COINGECKO_IDS,
@ -20,9 +30,6 @@ import {
TokenAccount,
} from '../utils/tokens'
import { Token } from '../types/jupiter'
import { getProfilePicture, ProfilePicture } from '@solflare-wallet/pfp'
import { TOKEN_LIST_URL } from '@jup-ag/core'
import dayjs from 'dayjs'
const GROUP = new PublicKey('DLdcpC6AsAJ9xeKMR3WhHrN5sM5o7GVVXQhQ5vwisTtz')
@ -44,6 +51,8 @@ const DEFAULT_CLIENT = MangoClient.connect(
CLUSTER,
MANGO_V4_ID[CLUSTER]
)
export const INPUT_TOKEN_DEFAULT = 'USDC'
export const OUTPUT_TOKEN_DEFAULT = 'SOL'
interface TotalInterestDataItem {
borrow_interest: number
@ -109,8 +118,8 @@ export type MangoStore = {
notifications: Array<Notification>
serumOrders: Order[] | undefined
swap: {
inputToken: string
outputToken: string
inputBank: Bank | undefined
outputBank: Bank | undefined
inputTokenInfo: Token | undefined
outputTokenInfo: Token | undefined
margin: boolean
@ -134,16 +143,19 @@ export type MangoStore = {
) => Promise<void>
fetchCoingeckoPrices: () => Promise<void>
fetchGroup: () => Promise<void>
fetchMangoAccount: (wallet: Wallet, accountNumber?: number) => Promise<void>
fetchMangoAccounts: (wallet: Wallet) => Promise<void>
fetchMangoAccount: (
wallet: AnchorWallet,
accountNumber?: number
) => Promise<void>
fetchMangoAccounts: (wallet: AnchorWallet) => Promise<void>
fetchNfts: (connection: Connection, walletPk: PublicKey) => void
fetchProfilePicture: (wallet: Wallet) => void
fetchProfilePicture: (wallet: AnchorWallet) => void
fetchJupiterTokens: () => Promise<void>
fetchTradeHistory: (mangoAccountPk: string) => Promise<void>
fetchWalletTokens: (wallet: Wallet) => Promise<void>
fetchWalletTokens: (wallet: AnchorWallet) => Promise<void>
handleWalletConnect: (wallet: Wallet) => Promise<void>
reloadAccount: () => Promise<void>
reloadGroup: () => Promise<void>
loadSerumMarket: () => Promise<void>
}
}
@ -175,8 +187,8 @@ const mangoStore = create<MangoStore>(
serumOrders: undefined,
set: (fn) => set(produce(fn)),
swap: {
inputToken: 'USDC',
outputToken: 'SOL',
inputBank: undefined,
outputBank: undefined,
inputTokenInfo: undefined,
outputTokenInfo: undefined,
margin: true,
@ -301,15 +313,8 @@ const mangoStore = create<MangoStore>(
const client = get().client
const group = await client.getGroup(GROUP)
const markets = await client.serum3GetMarkets(
group,
group.banksMap.get('BTC')?.tokenIndex,
group.banksMap.get('USDC')?.tokenIndex
)
set((state) => {
state.group = group
state.markets = markets
})
} catch (e) {
console.error('Error fetching group', e)
@ -319,27 +324,9 @@ const mangoStore = create<MangoStore>(
const set = get().set
try {
const group = get().group
const client = get().client
if (!group) throw new Error('Group not loaded')
const provider = new AnchorProvider(connection, wallet, options)
provider.opts.skipPreflight = true
const client = await MangoClient.connect(
provider,
CLUSTER,
MANGO_V4_ID[CLUSTER],
{
prioritizationFee: 2,
postSendTxCallback: ({ txid }: { txid: string }) => {
notify({
title: 'Transaction sent',
description: 'Waiting for confirmation',
type: 'confirm',
txid: txid,
})
},
}
)
const mangoAccount = await client.getMangoAccountForOwner(
group,
wallet.publicKey,
@ -355,11 +342,8 @@ const mangoStore = create<MangoStore>(
await mangoAccount.reloadAccountData(client, group)
}
set((state) => {
state.client = client
state.mangoAccount.current = mangoAccount
state.mangoAccount.loading = false
state.connected = true
// state.serumOrders = orders
})
} catch (e) {
set((state) => {
@ -443,7 +427,7 @@ const mangoStore = create<MangoStore>(
})
}
},
fetchWalletTokens: async (wallet: Wallet) => {
fetchWalletTokens: async (wallet: AnchorWallet) => {
const set = get().set
const connection = get().connection
@ -471,8 +455,8 @@ const mangoStore = create<MangoStore>(
)
return
}
const bankMints = Array.from(group.banksMap.values()).map((b) =>
b.mint.toString()
const bankMints = Array.from(group.banksMapByName.values()).map((b) =>
b[0].mint.toString()
)
fetch(TOKEN_LIST_URL[CLUSTER])
@ -482,10 +466,10 @@ const mangoStore = create<MangoStore>(
bankMints.includes(t.address)
)
const inputTokenInfo = groupTokens.find(
(t: any) => t.symbol === 'SOL'
(t: any) => t.symbol === INPUT_TOKEN_DEFAULT
)
const outputTokenInfo = groupTokens.find(
(t: any) => t.symbol === 'USDC'
(t: any) => t.symbol === OUTPUT_TOKEN_DEFAULT
)
set((s) => {
s.swap.inputTokenInfo = inputTokenInfo
@ -494,6 +478,50 @@ const mangoStore = create<MangoStore>(
})
})
},
handleWalletConnect: async (wallet: Wallet) => {
if (!wallet) {
return
}
try {
await wallet?.adapter?.connect()
const provider = new AnchorProvider(
connection,
wallet as unknown as AnchorWallet,
options
)
provider.opts.skipPreflight = true
const client = await MangoClient.connect(
provider,
CLUSTER,
MANGO_V4_ID[CLUSTER],
{
prioritizationFee: 2,
postSendTxCallback: ({ txid }: { txid: string }) => {
notify({
title: 'Transaction sent',
description: 'Waiting for confirmation',
type: 'confirm',
txid: txid,
})
},
}
)
set((s) => {
s.client = client
s.connected = true
})
} catch (e: any) {
if (e.name.includes('WalletLoadError')) {
notify({
title: `${wallet.adapter.name} Error`,
type: 'error',
description: `Please install ${wallet.adapter.name} and then reload this page.`,
})
}
}
},
reloadGroup: async () => {
try {
const set = get().set
@ -527,26 +555,7 @@ const mangoStore = create<MangoStore>(
console.error('Error reloading mango account')
}
},
loadSerumMarket: async () => {
const set = get().set
const client = get().client
const group = get().group
if (!group) return
const markets = await client.serum3GetMarkets(
group,
group.banksMap.get('BTC')?.tokenIndex,
group.banksMap.get('USDC')?.tokenIndex
)
let orders = await client.getSerum3Orders(group, 'BTC/USDC')
set((state) => {
state.markets = markets
state.serumOrders = orders
})
},
async fetchProfilePicture(wallet: Wallet) {
async fetchProfilePicture(wallet: AnchorWallet) {
const set = get().set
const walletPk = wallet?.publicKey
const connection = get().connection

View File

@ -1,7 +1,5 @@
import { Wallet } from '@project-serum/anchor'
import { Wallet as WalletAdapter } from '@solana/wallet-adapter-react'
import { Keypair, PublicKey, Transaction } from '@solana/web3.js'
import { notify } from './notifications'
export default class EmptyWallet implements Wallet {
constructor(readonly payer: Keypair) {}
@ -22,19 +20,3 @@ export default class EmptyWallet implements Wallet {
return this.payer.publicKey
}
}
export const handleWalletConnect = (wallet: WalletAdapter) => {
if (!wallet) {
return
}
wallet?.adapter?.connect().catch((e) => {
if (e.name.includes('WalletLoadError')) {
notify({
title: `${wallet.adapter.name} Error`,
type: 'error',
description: `Please install ${wallet.adapter.name} and then reload this page.`,
})
}
})
}

View File

@ -33,7 +33,7 @@
"@blockworks-foundation/mango-v4@git+https://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:x-oauth-basic@github.com/blockworks-foundation/mango-v4.git#main":
version "0.0.1-beta.1"
resolved "git+https://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:x-oauth-basic@github.com/blockworks-foundation/mango-v4.git#3c06b718c6faaee861fdbc734399aa72547e8a5c"
resolved "git+https://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:x-oauth-basic@github.com/blockworks-foundation/mango-v4.git#f40f33f3b35a8c18e1a74a9db2cca1b73faafa9b"
dependencies:
"@project-serum/anchor" "^0.25.0"
"@project-serum/serum" "^0.13.65"
@ -1195,9 +1195,9 @@
integrity sha512-/THyiqyQAP9AfARo4pF+aCGcyiQ94tX/Is2I7HofNRqoYLgN1PBoOWu2/zTA5zMxzP5EFutMtWtGAFRKUe961Q==
"@types/node@*":
version "18.7.5"
resolved "https://registry.yarnpkg.com/@types/node/-/node-18.7.5.tgz#f1c1d4b7d8231c0278962347163656f9c36f3e83"
integrity sha512-NcKK6Ts+9LqdHJaW6HQmgr7dT/i3GOHG+pt6BiWv++5SnjtRd4NXeiuN2kA153SjhXPR/AhHIPHPbrsbpUVOww==
version "18.7.6"
resolved "https://registry.yarnpkg.com/@types/node/-/node-18.7.6.tgz#31743bc5772b6ac223845e18c3fc26f042713c83"
integrity sha512-EdxgKRXgYsNITy5mjjXjVE/CS8YENSdhiagGrLqjG0pvA2owgJ6i4l7wy/PFZGC0B1/H20lWKN7ONVDNYDZm7A==
"@types/node@17.0.23":
version "17.0.23"