Merges main

This commit is contained in:
Luc Succes 2022-03-17 12:53:33 -04:00
commit 562d45677e
26 changed files with 1151 additions and 951 deletions

View File

@ -124,13 +124,11 @@ export const DEFAULT_PUBLIC_KEY = new PublicKey(
export interface WalletAdapter {
publicKey: PublicKey
autoApprove: boolean
connected: boolean
signTransaction: (transaction: Transaction) => Promise<Transaction>
signAllTransactions: (transaction: Transaction[]) => Promise<Transaction[]>
connect: () => any
disconnect: () => any
on(event: string, fn: () => void): this
}
export interface PerpTriggerOrder {

View File

@ -1,54 +1,113 @@
import { Fragment, useCallback, useState } from 'react'
import useMangoStore from '../stores/useMangoStore'
import React, {
Fragment,
useCallback,
useState,
useMemo,
useEffect,
} from 'react'
import { Menu, Transition } from '@headlessui/react'
import { useWallet, Wallet } from '@solana/wallet-adapter-react'
import { WalletReadyState } from '@solana/wallet-adapter-base'
import {
CurrencyDollarIcon,
DuplicateIcon,
LogoutIcon,
} from '@heroicons/react/outline'
import { PROVIDER_LOCAL_STORAGE_KEY } from '../hooks/useWallet'
import useLocalStorageState from '../hooks/useLocalStorageState'
import { abbreviateAddress, copyToClipboard } from '../utils'
import WalletSelect from './WalletSelect'
import { WalletIcon, ProfileIcon } from './icons'
import AccountsModal from './AccountsModal'
import { useEffect } from 'react'
import { notify } from 'utils/notifications'
import { abbreviateAddress, copyToClipboard } from 'utils'
import useMangoStore from 'stores/useMangoStore'
import { ProfileIcon, WalletIcon } from './icons'
import { useTranslation } from 'next-i18next'
import { DEFAULT_PROVIDER, WALLET_PROVIDERS } from '../utils/wallet-adapters'
import { WalletSelect } from 'components/WalletSelect'
import AccountsModal from './AccountsModal'
import { uniqBy } from 'lodash'
const ConnectWalletButton = () => {
const { t } = useTranslation('common')
const wallet = useMangoStore((s) => s.wallet.current)
const mangoGroup = useMangoStore((s) => s.selectedMangoGroup.current)
const pfp = useMangoStore((s) => s.wallet.pfp)
const connected = useMangoStore((s) => s.wallet.connected)
const set = useMangoStore((s) => s.set)
const [showAccountsModal, setShowAccountsModal] = useState(false)
const [selectedWallet, setSelectedWallet] = useState(DEFAULT_PROVIDER.url)
const [savedProviderUrl] = useLocalStorageState(
PROVIDER_LOCAL_STORAGE_KEY,
DEFAULT_PROVIDER.url
)
// update in useEffect to prevent SRR error from next.js
useEffect(() => {
setSelectedWallet(savedProviderUrl)
}, [savedProviderUrl])
const handleWalletConect = () => {
wallet.connect()
set((state) => {
state.selectedMangoAccount.initialLoad = true
export const handleWalletConnect = (wallet: Wallet) => {
if (!wallet) {
return
}
if (wallet.readyState === WalletReadyState.NotDetected) {
window.open(wallet.adapter.url, '_blank')
} else {
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 { connected, publicKey, wallet, wallets, select } = useWallet()
const { t } = useTranslation('common')
const pfp = useMangoStore((s) => s.wallet.pfp)
const set = useMangoStore((s) => s.set)
const mangoGroup = useMangoStore((s) => s.selectedMangoGroup.current)
const [showAccountsModal, setShowAccountsModal] = useState(false)
const defaultWallets = useMemo(() => {
return ['Phantom', 'Solflare', 'Sollet']
}, [])
const installedWallets = useMemo(() => {
const installed: Wallet[] = []
for (const wallet of wallets) {
if (wallet.readyState === WalletReadyState.Installed) {
installed.push(wallet)
}
}
return installed
}, [wallets])
const displayedWallets = useMemo(() => {
return uniqBy(
[
...installedWallets,
...wallets.filter((w) => defaultWallets.includes(w.adapter.name)),
],
(w) => {
return w.adapter.name
}
)
}, [wallets, installedWallets, defaultWallets])
const handleConnect = useCallback(() => {
handleWalletConnect(wallet)
}, [wallet])
const handleCloseAccounts = useCallback(() => {
setShowAccountsModal(false)
}, [])
const handleDisconnect = useCallback(() => {
wallet?.adapter?.disconnect()
set((state) => {
state.wallet.connected = false
state.mangoAccounts = []
state.selectedMangoAccount.current = null
state.tradeHistory = { spot: [], perp: [] }
})
notify({
type: 'info',
title: t('wallet-disconnected'),
})
}, [wallet, set, t])
useEffect(() => {
if (!wallet && displayedWallets?.length) {
select(displayedWallets[0].adapter.name)
}
}, [wallet, displayedWallets, select])
return (
<>
{connected && wallet?.publicKey ? (
{connected && publicKey ? (
<Menu>
{({ open }) => (
<div className="relative" id="profile-menu-tip">
@ -83,7 +142,7 @@ const ConnectWalletButton = () => {
<Menu.Item>
<button
className="flex w-full flex-row items-center rounded-none py-0.5 font-normal hover:cursor-pointer hover:text-th-primary focus:outline-none"
onClick={() => copyToClipboard(wallet?.publicKey)}
onClick={() => copyToClipboard(publicKey)}
>
<DuplicateIcon className="h-4 w-4" />
<div className="pl-2 text-left">{t('copy-address')}</div>
@ -92,13 +151,13 @@ const ConnectWalletButton = () => {
<Menu.Item>
<button
className="flex w-full flex-row items-center rounded-none py-0.5 font-normal hover:cursor-pointer hover:text-th-primary focus:outline-none"
onClick={() => wallet.disconnect()}
onClick={handleDisconnect}
>
<LogoutIcon className="h-4 w-4" />
<div className="pl-2 text-left">
<div className="pb-0.5">{t('disconnect')}</div>
<div className="text-xs text-th-fgd-4">
{abbreviateAddress(wallet?.publicKey)}
{abbreviateAddress(publicKey)}
</div>
</div>
</button>
@ -114,8 +173,8 @@ const ConnectWalletButton = () => {
id="connect-wallet-tip"
>
<button
onClick={handleWalletConect}
disabled={!wallet || !mangoGroup}
onClick={handleConnect}
disabled={!mangoGroup}
className="rounded-none bg-th-primary-dark text-th-bkg-1 hover:brightness-[1.1] focus:outline-none disabled:cursor-wait disabled:text-th-bkg-2"
>
<div className="default-transition flex h-full flex-row items-center justify-center px-3">
@ -124,25 +183,25 @@ const ConnectWalletButton = () => {
<div className="mb-0.5 whitespace-nowrap font-bold">
{t('connect')}
</div>
<div className="text-xxs font-normal leading-3 tracking-wider text-th-bkg-2">
{WALLET_PROVIDERS.find((p) => p.url === selectedWallet)?.name}
</div>
{wallet?.adapter?.name && (
<div className="text-xxs font-normal leading-3 tracking-wider text-th-bkg-2">
{wallet.adapter.name}
</div>
)}
</div>
</div>
</button>
<div className="relative">
<WalletSelect />
<WalletSelect wallets={displayedWallets} />
</div>
</div>
)}
{showAccountsModal ? (
{showAccountsModal && (
<AccountsModal
onClose={handleCloseAccounts}
isOpen={showAccountsModal}
/>
) : null}
)}
</>
)
}
export default ConnectWalletButton

View File

@ -1,5 +1,4 @@
import { FunctionComponent, ReactNode } from 'react'
import useMangoStore from '../stores/useMangoStore'
import Button from './Button'
interface EmptyStateProps {
@ -8,6 +7,7 @@ interface EmptyStateProps {
onClickButton?: () => void
desc?: string
title: string
disabled?: boolean
}
const EmptyState: FunctionComponent<EmptyStateProps> = ({
@ -16,10 +16,8 @@ const EmptyState: FunctionComponent<EmptyStateProps> = ({
onClickButton,
desc,
title,
disabled = false,
}) => {
const wallet = useMangoStore((s) => s.wallet.current)
const mangoGroup = useMangoStore((s) => s.selectedMangoGroup.current)
return (
<div className="flex flex-col items-center rounded-lg px-4 pb-2 text-th-fgd-1">
<div className="mb-1 h-6 w-6 text-th-primary">{icon}</div>
@ -34,11 +32,7 @@ const EmptyState: FunctionComponent<EmptyStateProps> = ({
</p>
) : null}
{buttonText && onClickButton ? (
<Button
className="mt-2"
onClick={onClickButton}
disabled={!wallet || !mangoGroup}
>
<Button className="mt-2" onClick={onClickButton} disabled={disabled}>
{buttonText}
</Button>
) : null}

View File

@ -1,31 +1,11 @@
import React, { FunctionComponent } from 'react'
// import styled from '@emotion/styled'
import React, { FunctionComponent, useCallback } from 'react'
import { LinkIcon } from '@heroicons/react/outline'
import useMangoStore from '../stores/useMangoStore'
import { MoveIcon } from './icons'
import EmptyState from './EmptyState'
import { useTranslation } from 'next-i18next'
// const StyledDragWrapperContent = styled.div`
// transition: all 0.25s ease-in;
// opacity: 0;
// `
// const StyledDragBkg = styled.div`
// transition: all 0.25s ease-in;
// opacity: 0;
// `
// const StyledDragWrapper = styled.div`
// :hover {
// ${StyledDragWrapperContent} {
// opacity: 1;
// }
// ${StyledDragBkg} {
// opacity: 0.9;
// }
// }
// `
import { useWallet } from '@solana/wallet-adapter-react'
import { handleWalletConnect } from 'components/ConnectWalletButton'
interface FloatingElementProps {
className?: string
@ -38,9 +18,15 @@ const FloatingElement: FunctionComponent<FloatingElementProps> = ({
showConnect,
}) => {
const { t } = useTranslation('common')
const { wallet } = useWallet()
const { uiLocked } = useMangoStore((s) => s.settings)
const mangoGroup = useMangoStore((s) => s.selectedMangoGroup.current)
const connected = useMangoStore((s) => s.wallet.connected)
const wallet = useMangoStore((s) => s.wallet.current)
const handleConnect = useCallback(() => {
handleWalletConnect(wallet)
}, [wallet])
return (
<div
className={`thin-scroll relative overflow-auto overflow-x-hidden rounded-lg bg-th-bkg-2 p-2.5 md:p-4 ${className}`}
@ -49,9 +35,10 @@ const FloatingElement: FunctionComponent<FloatingElementProps> = ({
<div className="absolute top-0 left-0 z-10 h-full w-full">
<div className="relative z-10 flex h-full flex-col items-center justify-center">
<EmptyState
disabled={!wallet || !mangoGroup}
buttonText={t('connect')}
icon={<LinkIcon />}
onClickButton={() => (wallet ? wallet.connect() : null)}
onClickButton={handleConnect}
title={t('connect-wallet')}
/>
</div>

View File

@ -12,7 +12,6 @@ import useMangoStore from '../stores/useMangoStore'
import {
connectionSelector,
walletConnectedSelector,
walletSelector,
} from '../stores/selectors'
import { sortBy, sum } from 'lodash'
import {
@ -46,6 +45,8 @@ import { numberFormatter } from './SwapTokenInfo'
import { useTranslation } from 'next-i18next'
import Tabs from './Tabs'
import SwapTokenInsights from './SwapTokenInsights'
import { useWallet } from '@solana/wallet-adapter-react'
import { handleWalletConnect } from 'components/ConnectWalletButton'
const TABS = ['Market Data', 'Performance Insights']
@ -53,10 +54,9 @@ type UseJupiterProps = Parameters<typeof useJupiter>[0]
const JupiterForm: FunctionComponent = () => {
const { t } = useTranslation(['common', 'swap'])
const wallet = useMangoStore(walletSelector)
const connection = useMangoStore(connectionSelector)
const connected = useMangoStore(walletConnectedSelector)
const { wallet, publicKey } = useWallet()
const [showSettings, setShowSettings] = useState(false)
const [depositAndFee, setDepositAndFee] = useState(null)
const [selectedRoute, setSelectedRoute] = useState<RouteInfo>(null)
@ -93,7 +93,7 @@ const JupiterForm: FunctionComponent = () => {
const ownedTokens = []
const ownedTokenAccounts = await getTokenAccountsByOwnerWithWrappedSol(
connection,
wallet.publicKey
publicKey
)
ownedTokenAccounts.forEach((account) => {
@ -237,6 +237,10 @@ const JupiterForm: FunctionComponent = () => {
}
}, [routeMap, tokens, formValue.inputMint])
const handleConnect = useCallback(() => {
handleWalletConnect(wallet)
}, [wallet])
const inputWalletBalance = () => {
if (walletTokens.length) {
const walletToken = walletTokens.filter((t) => {
@ -373,11 +377,11 @@ const JupiterForm: FunctionComponent = () => {
</div>
<a
className="flex items-center text-xs text-th-fgd-3 hover:text-th-fgd-2"
href={`https://explorer.solana.com/address/${wallet?.publicKey}`}
href={`https://explorer.solana.com/address/${publicKey}`}
target="_blank"
rel="noopener noreferrer"
>
{abbreviateAddress(wallet.publicKey)}
{abbreviateAddress(publicKey)}
<ExternalLinkIcon className="ml-0.5 -mt-0.5 h-3.5 w-3.5" />
</a>
</div>
@ -945,8 +949,8 @@ const JupiterForm: FunctionComponent = () => {
<Button
disabled={swapDisabled}
onClick={async () => {
if (!connected && zeroKey !== wallet?.publicKey) {
wallet.connect()
if (!connected && zeroKey !== publicKey) {
handleConnect()
} else if (!loading && selectedRoute && connected) {
setSwapping(true)
let txCount = 1

View File

@ -5,7 +5,7 @@ import useLocalStorageState from '../hooks/useLocalStorageState'
import MenuItem from './MenuItem'
import ThemeSwitch from './ThemeSwitch'
import useMangoStore from '../stores/useMangoStore'
import ConnectWalletButton from './ConnectWalletButton'
import { ConnectWalletButton } from 'components'
import NavDropMenu from './NavDropMenu'
import AccountsModal from './AccountsModal'
import LanguageSwitch from './LanguageSwitch'
@ -16,23 +16,6 @@ import TradeNavMenu from './TradeNavMenu'
import { CalculatorIcon, LightBulbIcon } from '@heroicons/react/outline'
import { MangoIcon } from './icons'
// const StyledNewLabel = ({ children, ...props }) => (
// <div style={{ fontSize: '0.5rem', marginLeft: '1px' }} {...props}>
// {children}
// </div>
// )
// <div className="relative">
// <MenuItem href="/referral">
// {t('referrals')}
// <div className="absolute flex items-center justify-center h-4 px-1.5 bg-gradient-to-br from-red-500 to-yellow-500 rounded-full -right-3 -top-3">
// <StyledNewLabel className="text-white uppercase">
// new
// </StyledNewLabel>
// </div>
// </MenuItem>
// </div>
const TopBar = () => {
const { t } = useTranslation('common')
const mangoAccount = useMangoStore((s) => s.selectedMangoAccount.current)

View File

@ -0,0 +1,93 @@
import React, { useEffect, useMemo } from 'react'
import {
ConnectionProvider,
useWallet,
WalletProvider as SolanaWalletProvider,
} from '@solana/wallet-adapter-react'
import { WalletAdapterNetwork } from '@solana/wallet-adapter-base'
import { getWalletAdapters } from '@solana/wallet-adapter-wallets'
import { clusterApiUrl } from '@solana/web3.js'
import useMangoStore from 'stores/useMangoStore'
const WalletListener: React.FC = () => {
const set = useMangoStore((s) => s.set)
const actions = useMangoStore((s) => s.actions)
const {
publicKey,
wallet,
signTransaction,
signAllTransactions,
connect,
disconnect,
connected,
} = useWallet()
const connecting = wallet?.adapter?.connecting
useEffect(() => {
const onConnect = async () => {
set((state) => {
state.selectedMangoAccount.initialLoad = true
state.wallet.providerUrl = wallet.adapter.url
state.wallet.connected = true
state.wallet.current = {
publicKey,
connected: true,
signTransaction,
signAllTransactions,
connect,
disconnect,
}
})
await actions.fetchAllMangoAccounts()
actions.fetchProfilePicture()
actions.reloadOrders()
actions.fetchTradeHistory()
actions.fetchWalletTokens()
}
if (connecting) {
onConnect()
}
}, [
connecting,
connected,
set,
actions,
wallet,
publicKey,
signAllTransactions,
signTransaction,
connect,
disconnect,
])
return null
}
export const WalletProvider: React.FC = ({ children }) => {
// The network can be set to 'devnet', 'testnet', or 'mainnet-beta'.
const network = WalletAdapterNetwork.Mainnet
// You can also provide a custom RPC endpoint.
const endpoint = useMemo(() => clusterApiUrl(network), [network])
// @solana/wallet-adapter-wallets includes all the adapters but supports tree shaking and lazy loading --
// Only the wallets you configure here will be compiled into your application, and only the dependencies
// of wallets that your users connect to will be loaded.
const wallets = getWalletAdapters({ network })
return (
<ConnectionProvider endpoint={endpoint}>
<SolanaWalletProvider wallets={wallets}>
<WalletListener />
{children}
</SolanaWalletProvider>
</ConnectionProvider>
)
}

View File

@ -1,16 +1,13 @@
import { Fragment } from 'react'
import React, { Fragment } from 'react'
import { Menu, Transition } from '@headlessui/react'
import { ChevronDownIcon } from '@heroicons/react/solid'
import useMangoStore from '../stores/useMangoStore'
import { WALLET_PROVIDERS } from '../utils/wallet-adapters'
import { useWallet, Wallet } from '@solana/wallet-adapter-react'
export default function WalletSelect() {
const setMangoStore = useMangoStore((s) => s.set)
export const WalletSelect: React.FC<{ wallets: Wallet[] }> = ({ wallets }) => {
const { select } = useWallet()
const handleSelectProvider = (url) => {
setMangoStore((state) => {
state.wallet.providerUrl = url
})
if (!wallets?.length) {
return null
}
return (
@ -38,15 +35,21 @@ export default function WalletSelect() {
leaveTo="opacity-0"
>
<Menu.Items className="absolute right-0 z-20 w-44 rounded-b-md bg-th-bkg-3 px-4 py-2.5 outline-none">
{WALLET_PROVIDERS.map(({ name, url, icon }) => (
<Menu.Item key={name}>
{wallets?.map((wallet, index) => (
<Menu.Item key={index}>
<button
className="flex w-full flex-row items-center justify-between rounded-none py-1.5 font-normal hover:cursor-pointer hover:text-th-primary focus:outline-none"
onClick={() => handleSelectProvider(url)}
onClick={() => {
select(wallet.adapter.name)
}}
>
<div className="flex items-center">
<img src={icon} className="mr-2 h-4 w-4" />
{name}
<img
src={wallet.adapter.icon}
className="mr-2 h-4 w-4"
alt={`${wallet.adapter.name} icon`}
/>
{wallet.adapter.name}
</div>
</button>
</Menu.Item>

85
components/index.tsx Normal file
View File

@ -0,0 +1,85 @@
export * from './AccountInfo'
export * from './AccountNameModal'
export * from './AccountSelect'
export * from './AccountsModal'
export * from './AlphaModal'
export * from './BalancesTable'
export * from './Button'
export * from './ButtonGroup'
export * from './Chart'
export * from './Checkbox'
export * from './CloseAccountModal'
export * from './ConnectWalletButton'
export * from './CreateAlertModal'
export * from './DayHighLow'
export * from './DelegateModal'
export * from './DepositModal'
export * from './DepositMsrmModal'
export * from './DropMenu'
export * from './EmptyState'
export * from './ErrorBoundary'
export * from './FavoritesShortcutBar'
export * from './FeeDiscountsTable'
export * from './FlipCard'
export * from './FloatingElement'
export * from './GlobalNotification'
export * from './icons'
export * from './ImageWithFallback'
export * from './InlineNotification'
export * from './Input'
export * from './IntroTips'
export * from './JupiterForm'
export * from './LanguageSwitch'
export * from './LeverageSlider'
export * from './Loading'
export * from './MangoAccountSelect'
export * from './MangoIcon'
export * from './ManualRefresh'
export * from './MarketBalances'
export * from './MarketCloseModal'
export * from './MarketDetails'
export * from './MarketFee'
export * from './MarketMenuItem'
export * from './MarketNavItem'
export * from './MarketSelect'
export * from './MarketsModal'
export * from './MenuItem'
export * from './Modal'
export * from './NavDropMenu'
export * from './NewAccount'
export * from './Notification'
export * from './OpenOrdersTable'
export * from './Orderbook'
export * from './PageBodyContainer'
export * from './Pagination'
export * from './PerpPositionsTable'
export * from './PerpSideBadge'
export * from './PnlText'
export * from './RecentMarketTrades'
export * from './ResetLayout'
export * from './Select'
export * from './Settings'
export * from './SettingsModal'
export * from './SideBadge'
export * from './Slider'
export * from './styles'
export * from './SwapSettingsModal'
export * from './SwapTokenInfo'
export * from './SwapTokenInsights'
export * from './SwapTokenSelect'
export * from './Switch'
export * from './SwitchMarketDropdown'
export * from './TableElements'
export * from './Tabs'
export * from './ThemeSwitch'
export * from './Tooltip'
export * from './TopBar'
export * from './TradeHistoryTable'
export * from './TradeNavMenu'
export * from './TradePageGrid'
export * from './UiLock'
export * from './UserInfo'
export * from './UserMarketInfo'
export * from './WalletProvider'
export * from './WithdrawModal'
export * from './WithdrawMsrmModal'

View File

@ -174,6 +174,7 @@ export default function StatsPerps({ perpStats }) {
x.toLocaleString(undefined, { maximumFractionDigits: 4 })
}
type="area"
yAxisWidth={70}
/>
</div>
<div

View File

@ -1,103 +0,0 @@
import { useEffect, useMemo } from 'react'
import Wallet from '@project-serum/sol-wallet-adapter'
import useLocalStorageState from './useLocalStorageState'
import useMangoStore from '../stores/useMangoStore'
import { notify } from '../utils/notifications'
import { WalletAdapter } from '../@types/types'
import { useTranslation } from 'next-i18next'
import { DEFAULT_PROVIDER, WALLET_PROVIDERS } from '../utils/wallet-adapters'
export const PROVIDER_LOCAL_STORAGE_KEY = 'walletProvider-0.1'
export default function useWallet() {
const { t } = useTranslation('common')
const setMangoStore = useMangoStore((state) => state.set)
const {
current: wallet,
connected,
providerUrl: selectedProviderUrl,
} = useMangoStore((state) => state.wallet)
const endpoint = useMangoStore((state) => state.connection.endpoint)
const actions = useMangoStore((s) => s.actions)
const [savedProviderUrl, setSavedProviderUrl] = useLocalStorageState(
PROVIDER_LOCAL_STORAGE_KEY,
DEFAULT_PROVIDER.url
)
const provider = useMemo(
() => WALLET_PROVIDERS.find(({ url }) => url === savedProviderUrl),
[savedProviderUrl]
)
useEffect(() => {
if (selectedProviderUrl) {
setSavedProviderUrl(selectedProviderUrl)
}
}, [selectedProviderUrl])
useEffect(() => {
if (provider) {
const updateWallet = () => {
// hack to also update wallet synchronously in case it disconnects
// eslint-disable-next-line react-hooks/exhaustive-deps
const wallet = new (provider.adapter || Wallet)(
savedProviderUrl,
endpoint
) as WalletAdapter
setMangoStore((state) => {
state.wallet.current = wallet
})
}
if (document.readyState !== 'complete') {
// wait to ensure that browser extensions are loaded
const listener = () => {
updateWallet()
window.removeEventListener('load', listener)
}
window.addEventListener('load', listener)
return () => window.removeEventListener('load', listener)
} else {
updateWallet()
}
}
}, [provider, savedProviderUrl, endpoint])
useEffect(() => {
if (!wallet) return
wallet.on('connect', async () => {
setMangoStore((state) => {
state.wallet.connected = true
})
// set connected before fetching data
await actions.fetchAllMangoAccounts()
actions.fetchProfilePicture()
actions.reloadOrders()
actions.fetchTradeHistory()
actions.fetchWalletTokens()
// notify({
// title: t('wallet-connected'),
// description:
// t('connected-to') +
// wallet.publicKey.toString().substr(0, 5) +
// '...' +
// wallet.publicKey.toString().substr(-5),
// })
})
wallet.on('disconnect', () => {
console.log('disconnecting wallet')
setMangoStore((state) => {
state.wallet.connected = false
state.mangoAccounts = []
state.selectedMangoAccount.current = null
state.tradeHistory = { spot: [], perp: [] }
})
notify({
type: 'info',
title: t('wallet-disconnected'),
})
})
}, [wallet, setMangoStore])
return { connected, wallet }
}

View File

@ -17,13 +17,16 @@
"test-all": "yarn lint && yarn type-check && yarn test"
},
"dependencies": {
"@blockworks-foundation/mango-client": "^3.3.20",
"@blockworks-foundation/mango-client": "^3.3.21",
"@headlessui/react": "^1.2.0",
"@heroicons/react": "^1.0.0",
"@jup-ag/react-hook": "^1.0.0-beta.16",
"@project-serum/serum": "0.13.55",
"@project-serum/sol-wallet-adapter": "0.2.0",
"@solana/web3.js": "^1.31.0",
"@solana/wallet-adapter-base": "^0.9.5",
"@solana/wallet-adapter-react": "^0.15.4",
"@solana/wallet-adapter-wallets": "^0.15.5",
"@solana/web3.js": "^1.36.0",
"@solflare-wallet/pfp": "^0.0.6",
"@solflare-wallet/sdk": "^1.0.10",
"@tippyjs/react": "^4.2.5",

View File

@ -4,7 +4,6 @@ import '../node_modules/react-grid-layout/css/styles.css'
import '../node_modules/react-resizable/css/styles.css'
import 'intro.js/introjs.css'
import '../styles/index.css'
import useWallet from '../hooks/useWallet'
import useHydrateStore from '../hooks/useHydrateStore'
import Notifications from '../components/Notification'
import useMangoStore from '../stores/useMangoStore'
@ -25,17 +24,13 @@ import {
ReferrerIdRecordLayout,
ReferrerIdRecord,
} from '@blockworks-foundation/mango-client'
import { WalletProvider } from 'components'
const MangoStoreUpdater = () => {
useHydrateStore()
return null
}
const WalletStoreUpdater = () => {
useWallet()
return null
}
const OpenOrdersStoreUpdater = () => {
useOpenOrders()
return null
@ -153,28 +148,29 @@ function App({ Component, pageProps }) {
<ErrorBoundary>
<PageTitle />
<MangoStoreUpdater />
<WalletStoreUpdater />
<OpenOrdersStoreUpdater />
<PerpPositionsStoreUpdater />
<FetchReferrer />
</ErrorBoundary>
<ThemeProvider defaultTheme="Mango">
<ViewportProvider>
<div className="min-h-screen bg-th-bkg-1">
<ErrorBoundary>
<GlobalNotification />
<Component {...pageProps} />
</ErrorBoundary>
</div>
<div className="fixed bottom-0 left-0 z-20 w-full md:hidden">
<ErrorBoundary>
<BottomBar />
</ErrorBoundary>
</div>
<WalletProvider>
<ViewportProvider>
<div className="min-h-screen bg-th-bkg-1">
<ErrorBoundary>
<GlobalNotification />
<Component {...pageProps} />
</ErrorBoundary>
</div>
<div className="fixed bottom-0 left-0 z-20 w-full md:hidden">
<ErrorBoundary>
<BottomBar />
</ErrorBoundary>
</div>
<Notifications />
</ViewportProvider>
<Notifications />
</ViewportProvider>
</WalletProvider>
</ThemeProvider>
</ErrorBoundary>
</>

View File

@ -19,43 +19,41 @@ import {
} from '@heroicons/react/outline'
import { ChevronDownIcon } from '@heroicons/react/solid'
import { nativeToUi, ZERO_BN } from '@blockworks-foundation/mango-client'
import useMangoStore, {
serumProgramId,
MNGO_INDEX,
} from '../stores/useMangoStore'
import PageBodyContainer from '../components/PageBodyContainer'
import TopBar from '../components/TopBar'
import AccountOrders from '../components/account_page/AccountOrders'
import AccountHistory from '../components/account_page/AccountHistory'
import AccountsModal from '../components/AccountsModal'
import AccountOverview from '../components/account_page/AccountOverview'
import AccountInterest from '../components/account_page/AccountInterest'
import AccountFunding from '../components/account_page/AccountFunding'
import AccountNameModal from '../components/AccountNameModal'
import { IconButton, LinkButton } from '../components/Button'
import EmptyState from '../components/EmptyState'
import Loading from '../components/Loading'
import Swipeable from '../components/mobile/Swipeable'
import Tabs from '../components/Tabs'
import { useViewport } from '../hooks/useViewport'
import { breakpoints } from '../components/TradePageGrid'
import useMangoStore, { serumProgramId, MNGO_INDEX } from 'stores/useMangoStore'
import PageBodyContainer from 'components/PageBodyContainer'
import TopBar from 'components/TopBar'
import AccountOrders from 'components/account_page/AccountOrders'
import AccountHistory from 'components/account_page/AccountHistory'
import AccountsModal from 'components/AccountsModal'
import AccountOverview from 'components/account_page/AccountOverview'
import AccountInterest from 'components/account_page/AccountInterest'
import AccountFunding from 'components/account_page/AccountFunding'
import AccountNameModal from 'components/AccountNameModal'
import { IconButton, LinkButton } from 'components/Button'
import EmptyState from 'components/EmptyState'
import Loading from 'components/Loading'
import Swipeable from 'components/mobile/Swipeable'
import Tabs from 'components/Tabs'
import { useViewport } from 'hooks/useViewport'
import { breakpoints } from 'components/TradePageGrid'
import { serverSideTranslations } from 'next-i18next/serverSideTranslations'
import { useTranslation } from 'next-i18next'
import Select from '../components/Select'
import Select from 'components/Select'
import { useRouter } from 'next/router'
import { PublicKey } from '@solana/web3.js'
import CloseAccountModal from '../components/CloseAccountModal'
import { notify } from '../utils/notifications'
import CloseAccountModal from 'components/CloseAccountModal'
import { notify } from 'utils/notifications'
import {
actionsSelector,
mangoAccountSelector,
mangoGroupSelector,
walletConnectedSelector,
} from '../stores/selectors'
import CreateAlertModal from '../components/CreateAlertModal'
import { copyToClipboard } from '../utils'
import DelegateModal from '../components/DelegateModal'
} from 'stores/selectors'
import CreateAlertModal from 'components/CreateAlertModal'
import { copyToClipboard } from 'utils'
import DelegateModal from 'components/DelegateModal'
import { Menu, Transition } from '@headlessui/react'
import { useWallet } from '@solana/wallet-adapter-react'
import { handleWalletConnect } from 'components/ConnectWalletButton'
export async function getStaticProps({ locale }) {
return {
@ -77,15 +75,12 @@ export default function Account() {
const { t } = useTranslation(['common', 'close-account', 'delegate'])
const { width } = useViewport()
const router = useRouter()
const connected = useMangoStore(walletConnectedSelector)
const { connected, wallet, publicKey } = useWallet()
const isLoading = useMangoStore((s) => s.selectedMangoAccount.initialLoad)
const mangoAccount = useMangoStore(mangoAccountSelector)
const mangoGroup = useMangoStore(mangoGroupSelector)
const wallet = useMangoStore((s) => s.wallet.current)
const isLoading = useMangoStore((s) => s.selectedMangoAccount.initialLoad)
const actions = useMangoStore(actionsSelector)
const setMangoStore = useMangoStore((s) => s.set)
const [showAccountsModal, setShowAccountsModal] = useState(false)
const [showNameModal, setShowNameModal] = useState(false)
const [showCloseAccountModal, setShowCloseAccountModal] = useState(false)
@ -97,10 +92,11 @@ export default function Account() {
const [viewIndex, setViewIndex] = useState(0)
const [activeTab, setActiveTab] = useState(TABS[0])
const connecting = wallet?.adapter?.connecting
const isMobile = width ? width < breakpoints.sm : false
const { pubkey } = router.query
const isDelegatedAccount = wallet?.publicKey
? !mangoAccount?.owner?.equals(wallet?.publicKey)
const isDelegatedAccount = publicKey
? !mangoAccount?.owner?.equals(publicKey)
: false
const handleCloseAlertModal = useCallback(() => {
@ -123,6 +119,10 @@ export default function Account() {
setShowDelegateModal(false)
}, [])
const handleConnect = useCallback(() => {
handleWalletConnect(wallet)
}, [wallet])
useEffect(() => {
async function loadUnownedMangoAccount() {
try {
@ -141,6 +141,7 @@ export default function Account() {
setResetOnLeave(true)
}
} catch (error) {
console.log('error', error)
router.push('/account')
}
}
@ -153,12 +154,6 @@ export default function Account() {
}
}, [pubkey, mangoGroup])
useEffect(() => {
if (connected) {
router.push('/account')
}
}, [connected])
useEffect(() => {
const handleRouteChange = () => {
if (resetOnLeave) {
@ -205,6 +200,14 @@ export default function Account() {
)
}, [mangoAccount])
console.log('connecting', connecting)
useEffect(() => {
if (connecting) {
router.push('/account')
}
}, [connecting, router])
const handleRedeemMngo = async () => {
const wallet = useMangoStore.getState().wallet.current
const mangoClient = useMangoStore.getState().connection.client
@ -447,14 +450,16 @@ export default function Account() {
icon={<CurrencyDollarIcon />}
onClickButton={() => setShowAccountsModal(true)}
title={t('no-account-found')}
disabled={!wallet || !mangoGroup}
/>
)
) : (
<EmptyState
buttonText={t('connect')}
desc={t('connect-view')}
disabled={!wallet || !mangoGroup}
icon={<LinkIcon />}
onClickButton={() => wallet.connect()}
onClickButton={handleConnect}
title={t('connect-wallet')}
/>
)}

View File

@ -7,7 +7,6 @@ import {
mangoCacheSelector,
mangoGroupConfigSelector,
mangoGroupSelector,
walletSelector,
} from '../stores/selectors'
import Button, { IconButton } from '../components/Button'
import {
@ -41,6 +40,8 @@ import MobileTableHeader from '../components/mobile/MobileTableHeader'
import Input, { Label } from '../components/Input'
import InlineNotification from '../components/InlineNotification'
import useMangoAccount from '../hooks/useMangoAccount'
import { useWallet } from '@solana/wallet-adapter-react'
import { handleWalletConnect } from 'components/ConnectWalletButton'
export async function getStaticProps({ locale }) {
return {
@ -72,7 +73,6 @@ export default function Referral() {
const mangoCache = useMangoStore(mangoCacheSelector)
const { mangoAccount } = useMangoAccount()
const groupConfig = useMangoStore(mangoGroupConfigSelector)
const wallet = useMangoStore(walletSelector)
const connected = useMangoStore((s) => s.wallet.connected)
const actions = useMangoStore((s) => s.actions)
@ -80,6 +80,9 @@ export default function Referral() {
const referralTotalAmount = useMangoStore((s) => s.referrals.total)
const hasReferrals = referralHistory.length > 0
const { wallet } = useWallet()
const mangoStoreWallet = useMangoStore.getState().wallet.current
const [customRefLinkInput, setCustomRefLinkInput] = useState('')
const [existingCustomRefLinks, setexistingCustomRefLinks] = useState<
ReferrerIdRecord[]
@ -144,6 +147,10 @@ export default function Referral() {
}
}
const handleConnect = useCallback(() => {
handleWalletConnect(wallet)
}, [wallet])
const submitRefLink = async () => {
let encodedRefLink: string
try {
@ -161,7 +168,7 @@ export default function Referral() {
const txid = await mangoClient.registerReferrerId(
mangoGroup,
mangoAccount,
wallet,
mangoStoreWallet,
encodedRefLink
)
notify({
@ -518,6 +525,7 @@ export default function Referral() {
icon={<CurrencyDollarIcon />}
onClickButton={() => setShowAccountsModal(true)}
title={t('no-account-found')}
disabled={!wallet || !mangoGroup}
/>
</div>
</>
@ -530,8 +538,9 @@ export default function Referral() {
<div className="col-span-12 flex items-center justify-center rounded-md bg-th-bkg-3 p-6 lg:col-span-8">
<EmptyState
buttonText={t('connect')}
disabled={!wallet || !mangoGroup}
icon={<LinkIcon />}
onClickButton={() => wallet.connect()}
onClickButton={handleConnect}
title={t('connect-wallet')}
/>
</div>

View File

@ -407,19 +407,19 @@ const useMangoStore = create<
const wallet = get().wallet.current
const actions = get().actions
if (!wallet?.publicKey || !mangoGroup) return
const delegateFilter = [
{
memcmp: {
offset: MangoAccountLayout.offsetOf('delegate'),
bytes: wallet?.publicKey.toBase58(),
bytes: wallet?.publicKey?.toBase58(),
},
},
]
const accountSorter = (a, b) =>
a.publicKey.toBase58() > b.publicKey.toBase58() ? 1 : -1
if (!wallet?.publicKey || !mangoGroup) return
return Promise.all([
mangoClient.getMangoAccountsForOwner(
mangoGroup,

View File

@ -13,7 +13,8 @@
"resolveJsonModule": true,
"jsx": "preserve",
"isolatedModules": true,
"incremental": true
"incremental": true,
"baseUrl": "."
},
"exclude": ["node_modules", ".next", "out", "public/datafeeds"],
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", "**/*.js"]

View File

@ -1,116 +0,0 @@
import EventEmitter from 'eventemitter3'
import { PublicKey, Transaction } from '@solana/web3.js'
import { notify } from '../../utils/notifications'
import { WalletAdapter } from '../../@types/types'
interface BitpieWallet {
getAccount(): Promise<string>
signTransaction(transaction: Transaction): Promise<Transaction>
signAllTransactions(transactions: Transaction[]): Promise<Transaction[]>
}
interface BitpieWalletWindow extends Window {
bitpie?: BitpieWallet
}
declare const window: BitpieWalletWindow
export class BitpieWalletAdapter extends EventEmitter implements WalletAdapter {
private _connecting: boolean
private _wallet: BitpieWallet | null
private _publicKey: PublicKey | null
constructor() {
super()
this._connecting = false
this._wallet = null
this._publicKey = null
}
get publicKey(): PublicKey | null {
return this._publicKey
}
get ready(): boolean {
return typeof window !== 'undefined' && !!window.bitpie
}
get connecting(): boolean {
return this._connecting
}
get connected(): boolean {
return !!this._wallet
}
get autoApprove() {
return true
}
async connect(): Promise<void> {
try {
if (this.connected || this.connecting) return
this._connecting = true
const wallet = typeof window !== 'undefined' && window.bitpie
if (!wallet) return
let account: string
try {
account = await wallet.getAccount()
} catch (error: any) {
notify({
title: 'Connection Error',
type: 'error',
description:
'Please install Bitpie wallet and then reload this page.',
})
}
this._wallet = wallet
this._publicKey = new PublicKey(account)
this.emit('connect')
} catch (error: any) {
this.emit('error', error)
throw error
} finally {
this._connecting = false
}
}
async disconnect(): Promise<void> {
if (this._wallet) {
this._wallet = null
this._publicKey = null
}
this.emit('disconnect')
}
async signTransaction(transaction: Transaction): Promise<Transaction> {
try {
const wallet = this._wallet
if (!wallet) return
return (await wallet.signTransaction(transaction)) || transaction
} catch (error: any) {
this.emit('error', error)
throw error
}
}
async signAllTransactions(
transactions: Transaction[]
): Promise<Transaction[]> {
try {
const wallet = this._wallet
if (!wallet) return
return (await wallet.signAllTransactions(transactions)) || transactions
} catch (error: any) {
this.emit('error', error)
throw error
}
}
}

View File

@ -1,101 +0,0 @@
import EventEmitter from 'eventemitter3'
import { PublicKey, Transaction } from '@solana/web3.js'
import { notify } from '../../utils/notifications'
import { DEFAULT_PUBLIC_KEY, WalletAdapter } from '../../@types/types'
type GlowEvent = 'disconnect' | 'connect'
type GlowRequestMethod =
| 'connect'
| 'disconnect'
| 'signTransaction'
| 'signAllTransactions'
interface GlowProvider {
publicKey?: PublicKey
isConnected?: boolean
autoApprove?: boolean
signTransaction: (transaction: Transaction) => Promise<Transaction>
signAllTransactions: (transactions: Transaction[]) => Promise<Transaction[]>
connect: () => Promise<void>
disconnect: () => Promise<void>
on: (event: GlowEvent, handler: (args: any) => void) => void
request: (method: GlowRequestMethod, params: any) => Promise<any>
listeners: (event: GlowEvent) => (() => void)[]
}
export class GlowWalletAdapter extends EventEmitter implements WalletAdapter {
constructor() {
super()
this.connect = this.connect.bind(this)
}
private get _provider(): GlowProvider | undefined {
if ((window as any)?.glowSolana?.isGlow) {
return (window as any).glowSolana
}
return undefined
}
private _handleConnect = (...args) => {
this.emit('connect', ...args)
}
private _handleDisconnect = (...args) => {
this.emit('disconnect', ...args)
}
get connected() {
return this._provider?.isConnected || false
}
get autoApprove() {
return this._provider?.autoApprove || false
}
async signAllTransactions(
transactions: Transaction[]
): Promise<Transaction[]> {
if (!this._provider) {
return transactions
}
return this._provider.signAllTransactions(transactions)
}
get publicKey() {
return this._provider?.publicKey || DEFAULT_PUBLIC_KEY
}
async signTransaction(transaction: Transaction) {
if (!this._provider) {
return transaction
}
return this._provider.signTransaction(transaction)
}
connect() {
if (!this._provider) {
window.open('https://glow.app/', '_blank')
notify({
title: 'Connection Error',
type: 'error',
description: 'Please install Glow wallet and then reload this page.',
})
return
}
if (!this._provider.listeners('connect').length) {
this._provider?.on('connect', this._handleConnect)
}
if (!this._provider.listeners('disconnect').length) {
this._provider?.on('disconnect', this._handleDisconnect)
}
return this._provider?.connect()
}
disconnect() {
if (this._provider) {
this._provider.disconnect()
}
}
}

View File

@ -1,94 +0,0 @@
import EventEmitter from 'eventemitter3'
import { PublicKey, Transaction } from '@solana/web3.js'
import { DEFAULT_PUBLIC_KEY, WalletAdapter } from '../../@types/types'
type HuobiEvent = 'disconnect' | 'connect'
type HuobiRequestMethod =
| 'connect'
| 'disconnect'
| 'signTransaction'
| 'signAllTransactions'
interface HuobiProvider {
publicKey?: PublicKey
isConnected?: boolean
autoApprove?: boolean
signTransaction: (transaction: Transaction) => Promise<Transaction>
signAllTransactions: (transactions: Transaction[]) => Promise<Transaction[]>
connect: () => Promise<void>
disconnect: () => Promise<void>
on: (event: HuobiEvent, handler: (args: any) => void) => void
request: (method: HuobiRequestMethod, params: any) => Promise<any>
listeners: (event: HuobiEvent) => (() => void)[]
}
export class HuobiWalletAdapter extends EventEmitter implements WalletAdapter {
constructor() {
super()
this.connect = this.connect.bind(this)
}
private get _provider(): HuobiProvider | undefined {
if ((window as any)?.huobiWallet?.isHuobiWallet) {
return (window as any).huobiWallet
}
return undefined
}
private _handleConnect = (...args) => {
this.emit('connect', ...args)
}
private _handleDisconnect = (...args) => {
this.emit('disconnect', ...args)
}
get connected() {
return this._provider?.isConnected || false
}
get autoApprove() {
return this._provider?.autoApprove || false
}
async signAllTransactions(
transactions: Transaction[]
): Promise<Transaction[]> {
if (!this._provider) {
return transactions
}
return this._provider.signAllTransactions(transactions)
}
get publicKey() {
return this._provider?.publicKey || DEFAULT_PUBLIC_KEY
}
async signTransaction(transaction: Transaction) {
if (!this._provider) {
return transaction
}
return this._provider.signTransaction(transaction)
}
connect() {
if (!this._provider) {
return
}
if (!this._provider.listeners('connect').length) {
this._provider?.on('connect', this._handleConnect)
}
if (!this._provider.listeners('disconnect').length) {
this._provider?.on('disconnect', this._handleDisconnect)
}
return this._provider?.connect()
}
disconnect() {
if (this._provider) {
this._provider.disconnect()
}
}
}

File diff suppressed because one or more lines are too long

View File

@ -1,104 +0,0 @@
import EventEmitter from 'eventemitter3'
import { PublicKey, Transaction } from '@solana/web3.js'
import { notify } from '../../utils/notifications'
import { DEFAULT_PUBLIC_KEY, WalletAdapter } from '../../@types/types'
type PhantomEvent = 'disconnect' | 'connect'
type PhantomRequestMethod =
| 'connect'
| 'disconnect'
| 'signTransaction'
| 'signAllTransactions'
interface PhantomProvider {
publicKey?: PublicKey
isConnected?: boolean
autoApprove?: boolean
signTransaction: (transaction: Transaction) => Promise<Transaction>
signAllTransactions: (transactions: Transaction[]) => Promise<Transaction[]>
connect: () => Promise<void>
disconnect: () => Promise<void>
on: (event: PhantomEvent, handler: (args: any) => void) => void
request: (method: PhantomRequestMethod, params: any) => Promise<any>
listeners: (event: PhantomEvent) => (() => void)[]
}
export class PhantomWalletAdapter
extends EventEmitter
implements WalletAdapter
{
constructor() {
super()
this.connect = this.connect.bind(this)
}
private get _provider(): PhantomProvider | undefined {
if ((window as any)?.solana?.isPhantom) {
return (window as any).solana
}
return undefined
}
private _handleConnect = (...args) => {
this.emit('connect', ...args)
}
private _handleDisconnect = (...args) => {
this.emit('disconnect', ...args)
}
get connected() {
return this._provider?.isConnected || false
}
get autoApprove() {
return this._provider?.autoApprove || false
}
async signAllTransactions(
transactions: Transaction[]
): Promise<Transaction[]> {
if (!this._provider) {
return transactions
}
return this._provider.signAllTransactions(transactions)
}
get publicKey() {
return this._provider?.publicKey || DEFAULT_PUBLIC_KEY
}
async signTransaction(transaction: Transaction) {
if (!this._provider) {
return transaction
}
return this._provider.signTransaction(transaction)
}
connect() {
if (!this._provider) {
window.open('https://phantom.app/', '_blank')
notify({
title: 'Connection Error',
type: 'error',
description: 'Please install Phantom wallet and then reload this page.',
})
return
}
if (!this._provider.listeners('connect').length) {
this._provider?.on('connect', this._handleConnect)
}
if (!this._provider.listeners('disconnect').length) {
this._provider?.on('disconnect', this._handleDisconnect)
}
return this._provider?.connect()
}
disconnect() {
if (this._provider) {
this._provider.disconnect()
}
}
}

View File

@ -1,132 +0,0 @@
import { PublicKey, Transaction } from '@solana/web3.js'
import bs58 from 'bs58'
import EventEmitter from 'events'
import { WalletAdapter } from '../../@types/types'
import { notify } from '../notifications'
interface SlopeWallet {
connect(): Promise<{
msg: string
data: {
publicKey?: string
}
}>
disconnect(): Promise<{ msg: string }>
signTransaction(message: string): Promise<{
msg: string
data: {
publicKey?: string
signature?: string
}
}>
signAllTransactions(messages: string[]): Promise<{
msg: string
data: {
publicKey?: string
signatures?: string[]
}
}>
}
interface SlopeWindow extends Window {
Slope?: {
new (): SlopeWallet
}
}
declare const window: SlopeWindow
export class SlopeWalletAdapter extends EventEmitter implements WalletAdapter {
private _connecting: boolean
private _wallet: SlopeWallet | null
private _publicKey: PublicKey | null
constructor() {
super()
this._connecting = false
this._wallet = null
this._publicKey = null
}
get publicKey(): PublicKey | null {
return this._publicKey
}
get ready(): boolean {
return typeof window !== 'undefined' && !!window.Slope
}
get connecting(): boolean {
return this._connecting
}
get connected(): boolean {
return !!this._publicKey
}
get autoApprove() {
return true
}
async connect(): Promise<void> {
try {
if (this.connected || this.connecting) return
this._connecting = true
const wallet = new window.Slope()
const { data } = await wallet.connect()
this._wallet = wallet
this._publicKey = new PublicKey(data.publicKey)
this.emit('connect')
} catch (error: any) {
notify({
title: 'Connection Error',
type: 'error',
description: 'Please install Slope wallet and then reload this page.',
})
} finally {
this._connecting = false
}
}
async disconnect(): Promise<void> {
const wallet = this._wallet
if (wallet) {
this._wallet = null
this._publicKey = null
await wallet.disconnect()
this.emit('disconnect')
}
}
async signTransaction(transaction: Transaction): Promise<Transaction> {
const wallet = this._wallet
const message = bs58.encode(transaction.serializeMessage())
const { data } = await wallet.signTransaction(message)
const publicKey = new PublicKey(data.publicKey)
const signature = bs58.decode(data.signature)
transaction.addSignature(publicKey, signature)
return transaction
}
async signAllTransactions(
transactions: Transaction[]
): Promise<Transaction[]> {
const wallet = this._wallet
const messages = transactions.map((transaction) =>
bs58.encode(transaction.serializeMessage())
)
const { data } = await wallet.signAllTransactions(messages)
const length = transactions.length
const publicKey = new PublicKey(data.publicKey)
for (let i = 0; i < length; i++) {
transactions[i].addSignature(publicKey, bs58.decode(data.signatures[i]))
}
return transactions
}
}

View File

@ -1,5 +0,0 @@
import Solflare from '@solflare-wallet/sdk'
export function SolflareWalletAdapter(_, network) {
return new Solflare({ network })
}

View File

@ -1,21 +0,0 @@
import Wallet from '@project-serum/sol-wallet-adapter'
import { notify } from '../../utils/notifications'
export function SolletExtensionAdapter(_, network) {
const sollet = (window as any).sollet
if (sollet) {
return new Wallet(sollet, network)
}
return {
on: () => {},
connect: () => {
notify({
title: 'Sollet Extension Error',
type: 'error',
description:
'Please install the Sollet Extension for Chrome and then reload this page.',
})
},
}
}

752
yarn.lock

File diff suppressed because it is too large Load Diff