diff --git a/.env.sample b/.env.sample index e180f1e512..adcff73b88 100644 --- a/.env.sample +++ b/.env.sample @@ -4,3 +4,5 @@ MAINNET_RPC=https://mango.rpcpool.com DEVNET_RPC=https://mango.devnet.rpcpool.com DEFAULT_GOVERNANCE_PROGRAM_ID=GTesTBiEWE32WHXXE2S4XbZvA5CrEc4xs6ZgRe895dP + +NEXT_PUBLIC_API_ENDPOINT=http://localhost:3001/graphql diff --git a/components/App.tsx b/components/App.tsx new file mode 100644 index 0000000000..a2e0dc8b47 --- /dev/null +++ b/components/App.tsx @@ -0,0 +1,221 @@ +import { ThemeProvider } from 'next-themes' +import { WalletIdentityProvider } from '@cardinal/namespaces-components' +import dynamic from 'next/dynamic' +import React, { useEffect } from 'react' +import Head from 'next/head' + +import { GatewayProvider } from '@components/Gateway/GatewayProvider' +import { usePrevious } from '@hooks/usePrevious' +import { useVotingPlugins, vsrPluginsPks } from '@hooks/useVotingPlugins' +import ErrorBoundary from '@components/ErrorBoundary' +import handleGovernanceAssetsStore from '@hooks/handleGovernanceAssetsStore' +import handleRouterHistory from '@hooks/handleRouterHistory' +import NavBar from '@components/NavBar' +import PageBodyContainer from '@components/PageBodyContainer' +import tokenService from '@utils/services/token' +import TransactionLoader from '@components/TransactionLoader' +import useDepositStore from 'VoteStakeRegistry/stores/useDepositStore' +import useGovernanceAssets from '@hooks/useGovernanceAssets' +import useHydrateStore from '@hooks/useHydrateStore' +import useMarketStore from 'Strategies/store/marketStore' +import useMembers from '@components/Members/useMembers' +import useRealm from '@hooks/useRealm' +import useTreasuryAccountStore from 'stores/useTreasuryAccountStore' +import useVotePluginsClientStore from 'stores/useVotePluginsClientStore' +import useWallet from '@hooks/useWallet' +import useWalletStore from 'stores/useWalletStore' +import NftVotingCountingModal from '@components/NftVotingCountingModal' +import { getResourcePathPart } from '@tools/core/resources' + +const Notifications = dynamic(() => import('../components/Notification'), { + ssr: false, +}) + +interface Props { + children: React.ReactNode +} + +export function App(props: Props) { + useHydrateStore() + useWallet() + handleRouterHistory() + useVotingPlugins() + handleGovernanceAssetsStore() + useMembers() + useEffect(() => { + tokenService.fetchSolanaTokenList() + }, []) + const { loadMarket } = useMarketStore() + const { governedTokenAccounts } = useGovernanceAssets() + const possibleNftsAccounts = governedTokenAccounts.filter( + (x) => x.isSol || x.isNft + ) + const { getNfts } = useTreasuryAccountStore() + const { getOwnedDeposits, resetDepositState } = useDepositStore() + const { realm, ownTokenRecord, realmInfo, symbol, config } = useRealm() + const wallet = useWalletStore((s) => s.current) + const connection = useWalletStore((s) => s.connection) + const client = useVotePluginsClientStore((s) => s.state.vsrClient) + const prevStringifyPossibleNftsAccounts = usePrevious( + JSON.stringify(possibleNftsAccounts) + ) + const realmName = realmInfo?.displayName ?? realm?.account?.name + const title = realmName ? `${realmName}` : 'Realms' + + // Note: ?v==${Date.now()} is added to the url to force favicon refresh. + // Without it browsers would cache the last used and won't change it for different realms + // https://stackoverflow.com/questions/2208933/how-do-i-force-a-favicon-refresh + const faviconUrl = + symbol && + `/realms/${getResourcePathPart( + symbol as string + )}/favicon.ico?v=${Date.now()}` + + useEffect(() => { + if (realm?.pubkey) { + loadMarket(connection, connection.cluster) + } + }, [connection.cluster, realm?.pubkey.toBase58()]) + useEffect(() => { + if ( + realm && + config?.account.communityTokenConfig.voterWeightAddin && + vsrPluginsPks.includes( + config.account.communityTokenConfig.voterWeightAddin.toBase58() + ) && + realm.pubkey && + wallet?.connected && + ownTokenRecord && + client + ) { + getOwnedDeposits({ + realmPk: realm!.pubkey, + communityMintPk: realm!.account.communityMint, + walletPk: ownTokenRecord!.account!.governingTokenOwner, + client: client!, + connection: connection.current, + }) + } else if (!wallet?.connected || !ownTokenRecord) { + resetDepositState() + } + }, [ + realm?.pubkey.toBase58(), + ownTokenRecord?.pubkey.toBase58(), + wallet?.connected, + client?.program.programId.toBase58(), + ]) + + useEffect(() => { + if ( + prevStringifyPossibleNftsAccounts !== + JSON.stringify(possibleNftsAccounts) && + realm?.pubkey + ) { + getNfts(possibleNftsAccounts, connection) + } + }, [JSON.stringify(possibleNftsAccounts), realm?.pubkey.toBase58()]) + + return ( +