Skip to content

Commit 2daa8db

Browse files
committed
chore: add impersonation option
1 parent dd65c2b commit 2daa8db

5 files changed

Lines changed: 69 additions & 3 deletions

File tree

apps/frontend/src/app/3_organisms/Header/Header.tsx

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
Header as UIHeader,
1010
Icon,
1111
IconNames,
12+
Tooltip,
1213
} from '@sovryn/ui';
1314

1415
import { ConnectWalletButton } from '../../2_molecules';
@@ -23,6 +24,7 @@ import { menuItemsMapping } from './Header.constants';
2324
import { BridgeMenuItem } from './components/BridgeMenuItem/BridgeMenuItem';
2425
import { NavItem } from './components/NavItem/NavItem';
2526
import { ProductLinks } from './components/ProductLinks/ProductLinks';
27+
import { IS_IMPERSONATING } from '../../../utils/account-debug';
2628

2729
export const Header: FC = () => {
2830
const chainId = useCurrentChain();
@@ -108,6 +110,18 @@ export const Header: FC = () => {
108110
pending={pending}
109111
dataAttribute="dapp-header-connect"
110112
/>
113+
{IS_IMPERSONATING && (
114+
<button
115+
className={
116+
'fixed bottom-3 right-3 bg-sovryn-black text-trade-short-25 text-xs px-2 py-1 rounded'
117+
}
118+
onClick={() => (window as any).stopImpersonatingAccount()}
119+
>
120+
<Tooltip content="You are in DEBUG MODE. All RPC requests will be called from the impersonated account. Click to disable.">
121+
<span>DEBUG MODE</span>
122+
</Tooltip>
123+
</button>
124+
)}
111125
</div>
112126
}
113127
extraContent={

apps/frontend/src/app/5_pages/LandingPage/components/ProtocolData/hooks/useGetBOBVolume.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ import { decimalic } from '../../../../../../utils/math';
1515
import { useGetTokens } from './useGetTokens';
1616

1717
const indexer = getIndexerUrl();
18-
console.log(indexer + 'sdex/volume');
1918

2019
export const useGetBOBVolume = () => {
2120
const { currentChainId } = useChainStore();

apps/frontend/src/hooks/useAccount.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { useMemo } from 'react';
33
import { ethers } from 'ethers';
44

55
import { useWalletConnect } from './useWalletConnect';
6+
import { maybeDebugAccount } from '../utils/account-debug';
67

78
export const useAccount = () => {
89
const { wallets } = useWalletConnect();
@@ -17,7 +18,7 @@ export const useAccount = () => {
1718
const signer = useMemo(() => web3provider?.getSigner(), [web3provider]);
1819

1920
return {
20-
account: wallets[0]?.accounts[0]?.address.toLowerCase() || '',
21+
account: maybeDebugAccount(wallets[0]?.accounts[0]?.address),
2122
type: wallets[0]?.label,
2223
eip1193Provider: wallets[0]?.provider,
2324
provider: web3provider,

apps/frontend/src/hooks/useWalletConnect.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { WalletState } from '@sovryn/onboard-core';
77
import { connectWallet$ } from '@sovryn/onboard-core/dist/streams';
88

99
import { onboard } from '../lib/connector';
10+
import { maybeDebugAccount } from '../utils/account-debug';
1011

1112
export const useWalletConnect = () => {
1213
const [pending, setPending] = useState(false);
@@ -44,7 +45,10 @@ export const useWalletConnect = () => {
4445
return () => sub.unsubscribe();
4546
}, []);
4647

47-
const account = useMemo(() => wallets[0]?.accounts[0]?.address, [wallets]);
48+
const account = useMemo(
49+
() => maybeDebugAccount(wallets[0]?.accounts[0]?.address),
50+
[wallets],
51+
);
4852

4953
const getWallet = useCallback((index: number) => wallets[index], [wallets]);
5054

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import { ethers } from 'ethers';
2+
3+
const DEBUG_WALLET =
4+
typeof localStorage !== 'undefined'
5+
? localStorage.getItem('impersonate')
6+
: null;
7+
8+
export const IS_IMPERSONATING = !!DEBUG_WALLET;
9+
10+
export function maybeDebugAccount(address?: string): string {
11+
// to enable debug mode, actual user wallet must be also connected
12+
if (DEBUG_WALLET && address) {
13+
return DEBUG_WALLET.toLowerCase();
14+
}
15+
return address?.toLowerCase() ?? '';
16+
}
17+
18+
function impersonateAccount(address: string) {
19+
if (!ethers.utils.isAddress(address?.toLowerCase())) {
20+
throw new Error("It's not a valid Ethereum address.");
21+
}
22+
23+
if (typeof localStorage !== 'undefined') {
24+
localStorage.setItem('impersonate', address.toLowerCase());
25+
window.location.reload();
26+
}
27+
}
28+
29+
function stopImpersonatingAccount() {
30+
if (typeof localStorage !== 'undefined') {
31+
localStorage.removeItem('impersonate');
32+
window.location.reload();
33+
}
34+
}
35+
36+
(() => {
37+
if (typeof window !== 'undefined') {
38+
(window as any).impersonateAccount = impersonateAccount;
39+
(window as any).stopImpersonatingAccount = stopImpersonatingAccount;
40+
}
41+
42+
if (IS_IMPERSONATING) {
43+
console.warn(
44+
'%cYou are in DEBUG MODE. All RPC requests will be called from the impersonated account. However transactions still will be signed with your connected wallet.\nTo stop impersonation, run stopImpersonatingAccount().',
45+
'background: red; color: white; font-size: 16px; padding: 4px;',
46+
);
47+
}
48+
})();

0 commit comments

Comments
 (0)