diff --git a/src/components/Swap/Swap.tsx b/src/components/Swap/Swap.tsx index 514517ec5..39d7b684e 100644 --- a/src/components/Swap/Swap.tsx +++ b/src/components/Swap/Swap.tsx @@ -126,6 +126,7 @@ export interface ISwap { > promotedSwapPairs: { tokenX: string; tokenY: string }[] swapMultiplier: string + rpc: string } export const Swap: React.FC = ({ @@ -166,7 +167,8 @@ export const Swap: React.FC = ({ pointsPerUsdFee, feeds, promotedSwapPairs, - swapMultiplier + swapMultiplier, + rpc }) => { const { classes } = useStyles() enum inputTarget { @@ -700,6 +702,9 @@ export const Swap: React.FC = ({ (getStateMessage() === 'Loading' && (inputRef === inputTarget.FROM || inputRef === inputTarget.DEFAULT)) + useEffect(() => { + onRefresh(tokenFromIndex, tokenToIndex) + }, [rpc]) return ( {wrappedETHAccountExist && ( diff --git a/src/containers/EventsHandlers/market.ts b/src/containers/EventsHandlers/market.ts index 02ad1ee8d..cfd404c0f 100644 --- a/src/containers/EventsHandlers/market.ts +++ b/src/containers/EventsHandlers/market.ts @@ -1,5 +1,5 @@ import { useDispatch, useSelector } from 'react-redux' -import { useEffect, useState } from 'react' +import { useEffect, useMemo, useState } from 'react' import { network, rpcAddress, status } from '@store/selectors/solanaConnection' import { Status, actions as solanaConnectionActions } from '@store/reducers/solanaConnection' import { actions } from '@store/reducers/pools' @@ -19,7 +19,6 @@ const MarketEvents = () => { const networkType = useSelector(network) const rpc = useSelector(rpcAddress) const wallet = getEclipseWallet() - const marketProgram = getMarketProgramSync(networkType, rpc, wallet as IWallet) const { tokenFrom, tokenTo } = useSelector(swap) const networkStatus = useSelector(status) const allPools = useSelector(poolsArraySortedByFees) @@ -29,6 +28,11 @@ const MarketEvents = () => { PublicKey.default ) + const marketProgram = useMemo( + () => getMarketProgramSync(networkType, rpc, wallet as IWallet), + [rpc, wallet, networkType] + ) + const location = useLocation() useEffect(() => { @@ -79,7 +83,7 @@ const MarketEvents = () => { } connectEvents() - }, [dispatch, networkStatus]) + }, [dispatch, networkStatus, rpc]) // New position pool subscription useEffect(() => { @@ -111,7 +115,7 @@ const MarketEvents = () => { ) } } - }, [dispatch, networkStatus, newPositionPoolIndex]) + }, [dispatch, networkStatus, newPositionPoolIndex, rpc]) useEffect(() => { window.addEventListener('unhandledrejection', e => { @@ -162,7 +166,7 @@ const MarketEvents = () => { } } } - }, [tokenFrom, tokenTo]) + }, [tokenFrom, tokenTo, rpc]) useEffect(() => { // Unsubscribe from swap pools on different pages than swap @@ -181,7 +185,7 @@ const MarketEvents = () => { marketProgram.program.account.pool.unsubscribe(newPositionSubscribedPool) setNewPositionSubscribedPool(PublicKey.default) } - }, [location.pathname]) + }, [location.pathname, rpc]) return null } diff --git a/src/containers/HeaderWrapper/HeaderWrapper.tsx b/src/containers/HeaderWrapper/HeaderWrapper.tsx index 02a27b827..f858b5df4 100644 --- a/src/containers/HeaderWrapper/HeaderWrapper.tsx +++ b/src/containers/HeaderWrapper/HeaderWrapper.tsx @@ -10,6 +10,7 @@ import { useDispatch, useSelector } from 'react-redux' import { useLocation, useNavigate } from 'react-router-dom' import { actions as snackbarsActions } from '@store/reducers/snackbars' import { actions as leaderboardActions } from '@store/reducers/leaderboard' +import { actions as positionsActions } from '@store/reducers/positions' import { Chain, WalletType } from '@store/consts/types' import { RpcErrorModal } from '@components/RpcErrorModal/RpcErrorModal' import { ThankYouModal } from '@components/Modals/ThankYouModal/ThankYouModal' @@ -206,8 +207,11 @@ export const HeaderWrapper: React.FC = () => { localStorage.setItem(`INVARIANT_RPC_Eclipse_${network}`, rpcAddress) dispatch(actions.setRPCAddress(rpcAddress)) dispatch(actions.setRpcStatus(RpcStatus.Uninitialized)) + dispatch(actions.initSolanaConnection()) + dispatch(walletActions.directInitWallet()) + dispatch(leaderboardActions.getLeaderboardData({ page: 1, itemsPerPage: 25 })) + dispatch(positionsActions.getPositionsList()) localStorage.setItem('IS_RPC_WARNING_IGNORED', 'false') - window.location.reload() } if (network !== currentNetwork) { diff --git a/src/containers/NewPositionWrapper/NewPositionWrapper.tsx b/src/containers/NewPositionWrapper/NewPositionWrapper.tsx index f2cf24b05..290d23c7d 100644 --- a/src/containers/NewPositionWrapper/NewPositionWrapper.tsx +++ b/src/containers/NewPositionWrapper/NewPositionWrapper.tsx @@ -26,7 +26,7 @@ import { actions, actions as positionsActions } from '@store/reducers/positions' import { actions as connectionActions } from '@store/reducers/solanaConnection' import { actions as snackbarsActions } from '@store/reducers/snackbars' import { actions as walletActions } from '@store/reducers/solanaWallet' -import { network, timeoutError } from '@store/selectors/solanaConnection' +import { network, rpcAddress, timeoutError } from '@store/selectors/solanaConnection' import { isLoadingLatestPoolsForTransaction, isLoadingPathTokens, @@ -70,6 +70,7 @@ export const NewPositionWrapper: React.FC = ({ initialIsRange }) => { const dispatch = useDispatch() + const currentRpc = useSelector(rpcAddress) const connection = getCurrentSolanaConnection() const ethBalance = useSelector(balance) const tokens = useSelector(poolTokens) @@ -636,6 +637,9 @@ export const NewPositionWrapper: React.FC = ({ } }, [isTimeoutError]) + useEffect(() => { + onRefresh() + }, [currentRpc]) const isPromotedPool = useMemo(() => { if (poolIndex === null) { return false diff --git a/src/containers/SinglePositionWrapper/SinglePositionWrapper.tsx b/src/containers/SinglePositionWrapper/SinglePositionWrapper.tsx index a36d1dc1d..62051772e 100644 --- a/src/containers/SinglePositionWrapper/SinglePositionWrapper.tsx +++ b/src/containers/SinglePositionWrapper/SinglePositionWrapper.tsx @@ -17,7 +17,7 @@ import { actions } from '@store/reducers/positions' import { actions as lockerActions } from '@store/reducers/locker' import { actions as snackbarsActions } from '@store/reducers/snackbars' import { Status, actions as walletActions } from '@store/reducers/solanaWallet' -import { network, timeoutError } from '@store/selectors/solanaConnection' +import { network, rpcAddress, timeoutError } from '@store/selectors/solanaConnection' import { isLoadingPositionsList, plotTicks, singlePositionData } from '@store/selectors/positions' import { balance, balanceLoading, status } from '@store/selectors/solanaWallet' import { VariantType } from 'notistack' @@ -44,6 +44,7 @@ export const SinglePositionWrapper: React.FC = ({ id }) => { const navigate = useNavigate() const currentNetwork = useSelector(network) + const currentRpc = useSelector(rpcAddress) const position = useSelector(singlePositionData(id)) const { success, inProgress } = useSelector(lockerState) @@ -358,6 +359,10 @@ export const SinglePositionWrapper: React.FC = ({ id }) => { } }, [isLoadingList]) + useEffect(() => { + onRefresh() + }, [currentRpc]) + if (position) { return ( { const dispatch = useDispatch() const connection = getCurrentSolanaConnection() - + const rpc = useSelector(rpcAddress) const walletStatus = useSelector(status) const swap = useSelector(swapPool) const tickmap = useSelector(tickMaps) @@ -415,6 +415,7 @@ export const WrappedSwap = ({ initialTokenFrom, initialTokenTo }: Props) => { feeds={priceFeeds} promotedSwapPairs={promotedSwapPairs} swapMultiplier={multiplyer} + rpc={rpc} /> ) } diff --git a/src/pages/RootPage.tsx b/src/pages/RootPage.tsx index fb3a4a2b9..08c71ae01 100644 --- a/src/pages/RootPage.tsx +++ b/src/pages/RootPage.tsx @@ -100,7 +100,7 @@ const RootPage: React.FC = memo(() => { walletAddressRef.current !== addr ) { walletAddressRef.current = addr - dispatch(walletActions.changeWalletInExtension()) + dispatch(walletActions.directInitWallet()) dispatch(leaderboardActions.getLeaderboardData({ page: 1, itemsPerPage })) dispatch(actions.getPositionsList()) } diff --git a/src/store/consts/static.ts b/src/store/consts/static.ts index a4fc4463c..30c979d69 100644 --- a/src/store/consts/static.ts +++ b/src/store/consts/static.ts @@ -423,6 +423,16 @@ export enum RPC { LOCAL = 'http://127.0.0.1:8899' } +export const RPCNames: Record = { + [RPC.TEST]: 'Eclipse Testnet', + [RPC.MAIN]: 'Eclipse Mainnet', + [RPC.MAIN_HELIUS]: 'Helius', + [RPC.MAIN_TRITON]: 'Triton', + [RPC.MAIN_LGNS]: 'Lgns', + [RPC.DEV]: 'Eclipse Devnet', + [RPC.LOCAL]: 'Local' +} + export const EGOAT_MAIN: Token = { tokenProgram: TOKEN_PROGRAM_ID, symbol: 'EGoat', diff --git a/src/store/reducers/solanaWallet.ts b/src/store/reducers/solanaWallet.ts index 6c2d8ddb9..93a9c0669 100644 --- a/src/store/reducers/solanaWallet.ts +++ b/src/store/reducers/solanaWallet.ts @@ -77,7 +77,7 @@ const solanaWalletSlice = createSlice({ getBalance(state) { return state }, - changeWalletInExtension(state) { + directInitWallet(state) { return state }, setIsEthBalanceLoading(state, action: PayloadAction) { diff --git a/src/store/sagas/connection.ts b/src/store/sagas/connection.ts index 4ce9d2cf4..4ccfc7f45 100644 --- a/src/store/sagas/connection.ts +++ b/src/store/sagas/connection.ts @@ -6,7 +6,7 @@ import { network, rpcAddress, rpcStatus } from '@store/selectors/solanaConnectio import { getSolanaConnection } from '@utils/web3/connection' import { actions, RpcStatus, Status } from '@store/reducers/solanaConnection' import { NetworkType, RECOMMENDED_RPC_ADDRESS } from '@store/consts/static' -import { ensureError } from '@utils/utils' +import { ensureError, getRpcNameByAddress } from '@utils/utils' export function* handleRpcError(error: string): Generator { const currentRpc = yield* select(rpcAddress) @@ -41,10 +41,11 @@ export function* getConnection(): SagaGenerator { export function* initConnection(): Generator { try { yield* call(getConnection) - + const rpc = yield* select(rpcAddress) + const rpcName = getRpcNameByAddress(rpc) yield* put( snackbarsActions.add({ - message: 'Eclipse network connected', + message: `Eclipse network connected via ${rpcName} RPC`, variant: 'success', persist: false }) diff --git a/src/store/sagas/wallet.ts b/src/store/sagas/wallet.ts index a81ec52aa..ecb78c45c 100644 --- a/src/store/sagas/wallet.ts +++ b/src/store/sagas/wallet.ts @@ -532,6 +532,7 @@ export function* init(isEagerConnect: boolean): Generator { }) ) } + yield* put(actions.setStatus(Status.Initialized)) yield* call(handleBalance) } catch (e: unknown) { @@ -581,7 +582,7 @@ export function* handleConnect(action: PayloadAction): Generator { } } -export function* handleChangeWalletInExtenstion(): Generator { +export function* handleDirectInitWallet(): Generator { try { yield* call(init, false) } catch (e: unknown) { @@ -699,8 +700,8 @@ export function* handleUnwrapWETH(): Generator { yield put(snackbarsActions.remove(loaderUnwrapWETH)) } -export function* changeWalletInExtenstionHandler(): Generator { - yield takeLatest(actions.changeWalletInExtension, handleChangeWalletInExtenstion) +export function* directInitWalletHandler(): Generator { + yield takeLatest(actions.directInitWallet, handleDirectInitWallet) } export function* connectHandler(): Generator { yield takeLatest(actions.connect, handleConnect) @@ -730,7 +731,7 @@ export function* walletSaga(): Generator { disconnectHandler, handleBalanceSaga, unwrapWETHHandler, - changeWalletInExtenstionHandler + directInitWalletHandler ].map(spawn) ) } diff --git a/src/utils/utils.ts b/src/utils/utils.ts index 76487fd6e..903cebec9 100644 --- a/src/utils/utils.ts +++ b/src/utils/utils.ts @@ -91,7 +91,8 @@ import { KYSOL_MAIN, EZSOL_MAIN, LEADERBOARD_DECIMAL, - POSITIONS_PER_PAGE + POSITIONS_PER_PAGE, + RPCNames } from '@store/consts/static' import { PoolWithAddress } from '@store/reducers/pools' import { bs58 } from '@coral-xyz/anchor/dist/cjs/utils/bytes' @@ -2050,3 +2051,7 @@ export const ROUTES = { getPositionRoute: (id: string): string => `${ROUTES.POSITION}/${id}` } + +export const getRpcNameByAddress = (addr: string) => { + return RPCNames[addr] ?? 'Custom' +} diff --git a/src/utils/web3/connection.ts b/src/utils/web3/connection.ts index 46c9f3b21..e50f6f5d6 100644 --- a/src/utils/web3/connection.ts +++ b/src/utils/web3/connection.ts @@ -9,6 +9,7 @@ const getSolanaConnection = (url: string): Connection => { if (_connection && _network === url) { return _connection } + _connection = new Connection(url, 'confirmed') _network = url diff --git a/src/utils/web3/programs/amm.ts b/src/utils/web3/programs/amm.ts index eec55bef7..a346be04b 100644 --- a/src/utils/web3/programs/amm.ts +++ b/src/utils/web3/programs/amm.ts @@ -3,8 +3,10 @@ import { PublicKey } from '@solana/web3.js' import { NetworkType } from '@store/consts/static' import { getSolanaConnection, networkTypetoProgramNetwork } from '../connection' import { Locker } from '@invariant-labs/locker-eclipse-sdk' + let _market: Market let _locker: Locker +let _currentRpc: string export const getCurrentMarketProgram = (): Market => { return _market @@ -15,12 +17,14 @@ export const getMarketProgram = async ( rpcAddress: string, solWallet: IWallet ): Promise => { - if (_market) { + if (_market && _currentRpc && _currentRpc === rpcAddress) { return _market } + + _currentRpc = rpcAddress const net = networkTypetoProgramNetwork(networkType) - _market = await Market.build( + _market = Market.build( net, solWallet, getSolanaConnection(rpcAddress),