2022-09-27 11:47:15 -07:00
|
|
|
import '../styles/globals.css'
|
2022-09-29 20:22:55 -07:00
|
|
|
import 'react-nice-dates/build/style.css'
|
|
|
|
import '../styles/datepicker.css'
|
2024-02-11 19:14:47 -08:00
|
|
|
import 'driver.js/dist/driver.css'
|
2024-02-20 18:08:12 -08:00
|
|
|
import 'slick-carousel/slick/slick.css'
|
|
|
|
import 'slick-carousel/slick/slick-theme.css'
|
2022-04-12 13:48:22 -07:00
|
|
|
import type { AppProps } from 'next/app'
|
2022-11-15 20:12:51 -08:00
|
|
|
import { useCallback, useMemo } from 'react'
|
|
|
|
import {
|
|
|
|
Adapter,
|
|
|
|
WalletAdapterNetwork,
|
|
|
|
WalletError,
|
|
|
|
WalletNotReadyError,
|
|
|
|
} from '@solana/wallet-adapter-base'
|
|
|
|
import {
|
|
|
|
ConnectionProvider,
|
|
|
|
WalletProvider,
|
2023-10-26 07:00:05 -07:00
|
|
|
useWallet,
|
2022-11-15 20:12:51 -08:00
|
|
|
} from '@solana/wallet-adapter-react'
|
2022-06-10 06:05:45 -07:00
|
|
|
import {
|
|
|
|
PhantomWalletAdapter,
|
2023-07-20 16:07:59 -07:00
|
|
|
CoinbaseWalletAdapter,
|
|
|
|
MathWalletAdapter,
|
|
|
|
Coin98WalletAdapter,
|
|
|
|
CloverWalletAdapter,
|
|
|
|
LedgerWalletAdapter,
|
2023-07-21 07:28:26 -07:00
|
|
|
WalletConnectWalletAdapter,
|
2022-06-10 06:05:45 -07:00
|
|
|
} from '@solana/wallet-adapter-wallets'
|
2023-09-12 02:56:28 -07:00
|
|
|
import { SolflareWalletAdapter } from '@solana/wallet-adapter-solflare'
|
2022-06-10 06:05:45 -07:00
|
|
|
import { clusterApiUrl } from '@solana/web3.js'
|
2023-04-21 07:23:27 -07:00
|
|
|
import TransactionNotification from '@components/notifications/TransactionNotification'
|
2023-10-26 07:00:05 -07:00
|
|
|
import { ThemeProvider, useTheme } from 'next-themes'
|
2022-07-14 16:36:31 -07:00
|
|
|
import { appWithTranslation } from 'next-i18next'
|
2022-07-26 19:45:27 -07:00
|
|
|
import Layout from '../components/Layout'
|
2022-09-27 11:47:15 -07:00
|
|
|
import MangoProvider from '@components/MangoProvider'
|
2022-10-07 16:39:06 -07:00
|
|
|
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
|
2022-11-15 20:12:51 -08:00
|
|
|
import { notify } from 'utils/notifications'
|
2022-12-11 19:46:03 -08:00
|
|
|
import { useRouter } from 'next/router'
|
|
|
|
import useSelectedMarket from 'hooks/useSelectedMarket'
|
|
|
|
import Head from 'next/head'
|
|
|
|
import useMangoGroup from 'hooks/useMangoGroup'
|
|
|
|
import { PerpMarket } from '@blockworks-foundation/mango-v4'
|
|
|
|
import { getDecimalCount } from 'utils/numbers'
|
2023-10-23 09:06:43 -07:00
|
|
|
import {
|
|
|
|
AUTO_CONNECT_WALLET,
|
|
|
|
SEND_TELEMETRY_KEY,
|
|
|
|
THEME_KEY,
|
|
|
|
} from 'utils/constants'
|
2023-07-21 07:28:26 -07:00
|
|
|
import useLocalStorageState from 'hooks/useLocalStorageState'
|
2023-10-23 09:06:43 -07:00
|
|
|
import PlausibleProvider from 'next-plausible'
|
2022-06-10 06:05:45 -07:00
|
|
|
|
2023-07-20 16:07:59 -07:00
|
|
|
// init react-query
|
2023-12-05 15:20:09 -08:00
|
|
|
const queryClient = new QueryClient()
|
2022-10-07 16:39:06 -07:00
|
|
|
|
2023-07-20 16:07:59 -07:00
|
|
|
// Do not add hooks to this component, that will cause unnecessary rerenders
|
|
|
|
// Top level state hydrating/updating should go in MangoProvider
|
2022-06-29 20:37:25 -07:00
|
|
|
function MyApp({ Component, pageProps }: AppProps) {
|
2022-12-30 12:07:32 -08:00
|
|
|
const network = WalletAdapterNetwork.Mainnet
|
2022-06-10 06:05:45 -07:00
|
|
|
const endpoint = useMemo(() => clusterApiUrl(network), [network])
|
2023-07-21 21:00:55 -07:00
|
|
|
const router = useRouter()
|
2023-07-21 07:28:26 -07:00
|
|
|
const wallets = useMemo(() => {
|
|
|
|
return [
|
2022-12-30 12:07:32 -08:00
|
|
|
new PhantomWalletAdapter(),
|
|
|
|
new SolflareWalletAdapter(),
|
2023-07-20 16:07:59 -07:00
|
|
|
new CoinbaseWalletAdapter(),
|
|
|
|
new MathWalletAdapter(),
|
|
|
|
new Coin98WalletAdapter(),
|
|
|
|
new CloverWalletAdapter(),
|
|
|
|
new LedgerWalletAdapter(),
|
2023-07-21 07:28:26 -07:00
|
|
|
new WalletConnectWalletAdapter({ network, options: {} }),
|
|
|
|
]
|
|
|
|
}, [network])
|
2022-06-10 06:05:45 -07:00
|
|
|
|
2022-11-15 20:12:51 -08:00
|
|
|
const onError = useCallback((error: WalletError, adapter?: Adapter) => {
|
|
|
|
console.error(error, adapter)
|
|
|
|
if (error instanceof WalletNotReadyError && adapter) {
|
|
|
|
notify({
|
|
|
|
title: `${adapter.name} Error`,
|
|
|
|
type: 'error',
|
|
|
|
description: `Please install ${adapter.name} and then reload this page.`,
|
|
|
|
})
|
|
|
|
if (typeof window !== 'undefined') {
|
|
|
|
window.open(adapter.url, '_blank')
|
|
|
|
}
|
2023-07-21 07:28:26 -07:00
|
|
|
} else {
|
|
|
|
notify({
|
2023-07-22 13:43:36 -07:00
|
|
|
title: `${adapter?.name} ${error.error?.message || 'Error'}`,
|
|
|
|
type: 'info',
|
2023-07-21 07:28:26 -07:00
|
|
|
})
|
2022-11-15 20:12:51 -08:00
|
|
|
}
|
|
|
|
}, [])
|
|
|
|
|
2023-07-21 21:00:55 -07:00
|
|
|
const [autoConnectSetting] = useLocalStorageState(AUTO_CONNECT_WALLET, true)
|
|
|
|
const autoConnect =
|
|
|
|
autoConnectSetting === false || router.asPath.includes('?address')
|
|
|
|
? false
|
|
|
|
: true
|
2023-07-21 07:28:26 -07:00
|
|
|
|
2022-06-10 06:05:45 -07:00
|
|
|
return (
|
2023-10-26 07:00:05 -07:00
|
|
|
<>
|
2022-12-19 19:53:00 -08:00
|
|
|
<Head>
|
|
|
|
<link rel="icon" href="/favicon.ico" />
|
2023-06-22 17:05:28 -07:00
|
|
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
2022-12-19 19:53:00 -08:00
|
|
|
<link
|
|
|
|
rel="apple-touch-icon"
|
|
|
|
sizes="192x192"
|
|
|
|
href="/apple-touch-icon.png"
|
|
|
|
/>
|
|
|
|
<meta name="msapplication-TileColor" content="#da532c" />
|
|
|
|
<meta name="theme-color" content="#ffffff" />
|
|
|
|
<meta name="twitter:card" content="summary_large_image" />
|
|
|
|
<meta
|
|
|
|
name="twitter:image"
|
2023-06-15 17:58:19 -07:00
|
|
|
content="https://app.mango.markets/images/1200x600-share.png?34567879"
|
2022-12-19 19:53:00 -08:00
|
|
|
/>
|
|
|
|
<meta name="google" content="notranslate" />
|
|
|
|
<link rel="manifest" href="/manifest.json"></link>
|
|
|
|
</Head>
|
2022-10-07 16:39:06 -07:00
|
|
|
<QueryClientProvider client={queryClient}>
|
|
|
|
<ConnectionProvider endpoint={endpoint}>
|
2023-07-21 07:28:26 -07:00
|
|
|
<WalletProvider
|
|
|
|
wallets={wallets}
|
|
|
|
onError={onError}
|
2023-07-21 21:00:55 -07:00
|
|
|
autoConnect={autoConnect}
|
2023-07-21 07:28:26 -07:00
|
|
|
>
|
2023-07-20 21:30:43 -07:00
|
|
|
<MangoProvider />
|
2023-07-20 16:07:59 -07:00
|
|
|
<ThemeProvider defaultTheme="Mango Classic" storageKey={THEME_KEY}>
|
2023-08-17 20:57:46 -07:00
|
|
|
<PageTitle />
|
|
|
|
<Layout>
|
2023-10-26 07:00:05 -07:00
|
|
|
<Telemetry />
|
2023-08-17 20:57:46 -07:00
|
|
|
<Component {...pageProps} />
|
|
|
|
</Layout>
|
2023-07-20 16:07:59 -07:00
|
|
|
<TransactionNotification />
|
|
|
|
</ThemeProvider>
|
2022-10-07 16:39:06 -07:00
|
|
|
</WalletProvider>
|
|
|
|
</ConnectionProvider>
|
|
|
|
</QueryClientProvider>
|
2023-10-26 07:00:05 -07:00
|
|
|
</>
|
2022-06-10 06:05:45 -07:00
|
|
|
)
|
2022-04-12 13:48:22 -07:00
|
|
|
}
|
|
|
|
|
2022-07-14 16:36:31 -07:00
|
|
|
export default appWithTranslation(MyApp)
|
2022-12-11 19:46:03 -08:00
|
|
|
|
2023-12-05 15:20:09 -08:00
|
|
|
const Telemetry = () => {
|
2023-10-26 07:00:05 -07:00
|
|
|
const router = useRouter()
|
|
|
|
const { wallet, connected } = useWallet()
|
|
|
|
const { theme } = useTheme()
|
|
|
|
|
|
|
|
const [sendTelemetry] = useLocalStorageState(SEND_TELEMETRY_KEY, true)
|
|
|
|
|
|
|
|
const telemetryProps = useMemo(() => {
|
|
|
|
const props = {
|
|
|
|
walletProvider: wallet?.adapter.name ?? 'unknown',
|
|
|
|
walletConnected: (wallet?.adapter.connected ?? 'false').toString(),
|
|
|
|
viewingAccount: router.asPath.includes('?address').toString(),
|
|
|
|
currentTheme: theme ?? 'unknown',
|
|
|
|
}
|
|
|
|
|
|
|
|
// Hack to update script tag
|
|
|
|
const el = document.getElementById('plausible')
|
|
|
|
if (el) {
|
|
|
|
Object.entries(props).forEach(([key, value]) => {
|
|
|
|
el.setAttribute(`event-${key}`, value)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
return props
|
|
|
|
}, [wallet, connected, theme])
|
|
|
|
|
|
|
|
return (
|
|
|
|
<PlausibleProvider
|
|
|
|
domain="app.mango.markets"
|
|
|
|
customDomain="https://pl.mngo.cloud"
|
|
|
|
trackLocalhost={true}
|
|
|
|
selfHosted={true}
|
|
|
|
enabled={sendTelemetry}
|
|
|
|
scriptProps={{ id: 'plausible' }}
|
|
|
|
pageviewProps={telemetryProps}
|
|
|
|
/>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2022-12-11 19:46:03 -08:00
|
|
|
const PageTitle = () => {
|
|
|
|
const router = useRouter()
|
|
|
|
const { selectedMarket } = useSelectedMarket()
|
|
|
|
const { group } = useMangoGroup()
|
|
|
|
|
|
|
|
const [market, price] = useMemo(() => {
|
|
|
|
if (!selectedMarket || !group) return []
|
|
|
|
if (selectedMarket instanceof PerpMarket) {
|
|
|
|
return [selectedMarket, selectedMarket.uiPrice]
|
|
|
|
} else {
|
2023-04-25 19:29:37 -07:00
|
|
|
const baseBank = group.getFirstBankByTokenIndex(
|
2023-07-21 11:47:53 -07:00
|
|
|
selectedMarket.baseTokenIndex,
|
2023-04-25 19:29:37 -07:00
|
|
|
)
|
|
|
|
const quoteBank = group.getFirstBankByTokenIndex(
|
2023-07-21 11:47:53 -07:00
|
|
|
selectedMarket.quoteTokenIndex,
|
2023-04-25 19:29:37 -07:00
|
|
|
)
|
2022-12-11 19:46:03 -08:00
|
|
|
const market = group.getSerum3ExternalMarket(
|
2023-07-21 11:47:53 -07:00
|
|
|
selectedMarket.serumMarketExternal,
|
2022-12-11 19:46:03 -08:00
|
|
|
)
|
2023-04-25 19:29:37 -07:00
|
|
|
const price = baseBank.uiPrice / quoteBank.uiPrice
|
2022-12-11 19:46:03 -08:00
|
|
|
return [market, price]
|
|
|
|
}
|
|
|
|
}, [selectedMarket, group])
|
|
|
|
|
|
|
|
const marketTitleString =
|
|
|
|
market && selectedMarket && router.pathname == '/trade'
|
|
|
|
? `${price?.toFixed(getDecimalCount(market.tickSize))} ${
|
|
|
|
selectedMarket.name
|
2023-09-05 08:04:30 -07:00
|
|
|
} - Mango`
|
|
|
|
: 'Mango Markets'
|
2022-12-11 19:46:03 -08:00
|
|
|
|
|
|
|
return (
|
|
|
|
<Head>
|
2023-09-05 08:04:30 -07:00
|
|
|
<title>{marketTitleString}</title>
|
2022-12-11 19:46:03 -08:00
|
|
|
</Head>
|
|
|
|
)
|
|
|
|
}
|