From f918b346a010627864ac658c9e87d3c838cb0aea Mon Sep 17 00:00:00 2001 From: cartcrom <39385577+cartcrom@users.noreply.github.com> Date: Tue, 2 Aug 2022 13:08:36 -0400 Subject: [PATCH] feat: amplitude logs is_reconnect (#4214) * modified redux state to track wallet connections to properly log reconnects * linted and removed console.log * fixes for lynn's comments + documenting --- src/components/AccountDetails/index.tsx | 3 +++ src/components/WalletModal/index.tsx | 23 +++++++++++++++---- src/state/index.ts | 2 ++ src/state/wallets/hooks.tsx | 17 ++++++++++++++ src/state/wallets/reducer.ts | 30 +++++++++++++++++++++++++ src/state/wallets/types.ts | 4 ++++ 6 files changed, 75 insertions(+), 4 deletions(-) create mode 100644 src/state/wallets/hooks.tsx create mode 100644 src/state/wallets/reducer.ts create mode 100644 src/state/wallets/types.ts diff --git a/src/components/AccountDetails/index.tsx b/src/components/AccountDetails/index.tsx index 77f56fd629..2205f3bc09 100644 --- a/src/components/AccountDetails/index.tsx +++ b/src/components/AccountDetails/index.tsx @@ -6,6 +6,7 @@ import { Context, useCallback, useContext } from 'react' import { ExternalLink as LinkIcon } from 'react-feather' import { useAppDispatch } from 'state/hooks' import { updateSelectedWallet } from 'state/user/reducer' +import { removeConnectedWallet } from 'state/wallets/reducer' import { DefaultTheme } from 'styled-components/macro' import styled, { ThemeContext } from 'styled-components/macro' import { isMobile } from 'utils/userAgent' @@ -245,6 +246,7 @@ export default function AccountDetails({ { + const walletType = getConnectionName(getConnection(connector).type, getIsMetaMask()) if (connector.deactivate) { connector.deactivate() } else { @@ -252,6 +254,7 @@ export default function AccountDetails({ } dispatch(updateSelectedWallet({ wallet: undefined })) + dispatch(removeConnectedWallet({ account, walletType })) openOptions() }} > diff --git a/src/components/WalletModal/index.tsx b/src/components/WalletModal/index.tsx index e2827146b8..10beaf6e52 100644 --- a/src/components/WalletModal/index.tsx +++ b/src/components/WalletModal/index.tsx @@ -13,6 +13,7 @@ import { ArrowLeft } from 'react-feather' import { updateConnectionError } from 'state/connection/reducer' import { useAppDispatch, useAppSelector } from 'state/hooks' import { updateSelectedWallet } from 'state/user/reducer' +import { useConnectedWallets } from 'state/wallets/hooks' import styled from 'styled-components/macro' import { isMobile } from 'utils/userAgent' @@ -113,13 +114,18 @@ const WALLET_VIEWS = { PENDING: 'pending', } -const sendAnalyticsEventAndUserInfo = (account: string, walletType: string, chainId: number | undefined) => { +const sendAnalyticsEventAndUserInfo = ( + account: string, + walletType: string, + chainId: number | undefined, + isReconnect: boolean +) => { const currentDate = new Date().toISOString() sendAnalyticsEvent(EventName.WALLET_CONNECT_TXN_COMPLETED, { result: WALLET_CONNECTION_RESULT.SUCCEEDED, wallet_address: account, wallet_type: walletType, - // TODO(lynnshaoyu): Send correct is_reconnect value after modifying user state. + is_reconnect: isReconnect, }) user.set(CUSTOM_USER_PROPERTIES.WALLET_ADDRESS, account) user.set(CUSTOM_USER_PROPERTIES.WALLET_TYPE, walletType) @@ -140,6 +146,7 @@ export default function WalletModal({ }) { const dispatch = useAppDispatch() const { connector, account, chainId } = useWeb3React() + const [connectedWallets, updateConnectedWallets] = useConnectedWallets() const [walletView, setWalletView] = useState(WALLET_VIEWS.ACCOUNT) const [lastActiveWalletAddress, setLastActiveWalletAddress] = useState(account) @@ -173,10 +180,18 @@ export default function WalletModal({ useEffect(() => { if (account && account !== lastActiveWalletAddress) { const walletType = getConnectionName(getConnection(connector).type, getIsMetaMask()) - sendAnalyticsEventAndUserInfo(account, walletType, chainId) + + if ( + connectedWallets.filter((wallet) => wallet.account === account && wallet.walletType === walletType).length > 0 + ) { + sendAnalyticsEventAndUserInfo(account, walletType, chainId, true) + } else { + sendAnalyticsEventAndUserInfo(account, walletType, chainId, false) + updateConnectedWallets({ account, walletType }) + } } setLastActiveWalletAddress(account) - }, [lastActiveWalletAddress, account, connector, chainId]) + }, [connectedWallets, updateConnectedWallets, lastActiveWalletAddress, account, connector, chainId]) const tryActivation = useCallback( async (connector: Connector) => { diff --git a/src/state/index.ts b/src/state/index.ts index b7d199473e..af3b5420da 100644 --- a/src/state/index.ts +++ b/src/state/index.ts @@ -17,6 +17,7 @@ import { routingApi } from './routing/slice' import swap from './swap/reducer' import transactions from './transactions/reducer' import user from './user/reducer' +import wallets from './wallets/reducer' const PERSISTED_KEYS: string[] = ['user', 'transactions', 'lists'] @@ -26,6 +27,7 @@ const store = configureStore({ user, connection, transactions, + wallets, swap, mint, mintV3, diff --git a/src/state/wallets/hooks.tsx b/src/state/wallets/hooks.tsx new file mode 100644 index 0000000000..a68d0fee23 --- /dev/null +++ b/src/state/wallets/hooks.tsx @@ -0,0 +1,17 @@ +import { useCallback } from 'react' +import { useAppDispatch, useAppSelector } from 'state/hooks' + +import { addConnectedWallet } from './reducer' +import { Wallet } from './types' + +export function useConnectedWallets(): [Wallet[], (wallet: Wallet) => void] { + const dispatch = useAppDispatch() + const connectedWallets = useAppSelector((state) => state.wallets.connectedWallets) + const addWallet = useCallback( + (wallet: Wallet) => { + dispatch(addConnectedWallet(wallet)) + }, + [dispatch] + ) + return [connectedWallets, addWallet] +} diff --git a/src/state/wallets/reducer.ts b/src/state/wallets/reducer.ts new file mode 100644 index 0000000000..995f97e3e2 --- /dev/null +++ b/src/state/wallets/reducer.ts @@ -0,0 +1,30 @@ +import { createSlice } from '@reduxjs/toolkit' +import { shallowEqual } from 'react-redux' + +import { Wallet } from './types' + +/* Used to track wallets that have been connected by the user in current session, and remove them when deliberately disconnected. + Used to compute is_reconnect event property for analytics */ +export interface WalletState { + connectedWallets: Wallet[] +} + +export const initialState: WalletState = { + connectedWallets: [], +} + +const walletsSlice = createSlice({ + name: 'wallets', + initialState, + reducers: { + addConnectedWallet(state, { payload }) { + state.connectedWallets = state.connectedWallets.concat(payload) + }, + removeConnectedWallet(state, { payload }) { + state.connectedWallets = state.connectedWallets.filter((wallet) => !shallowEqual(wallet, payload)) + }, + }, +}) + +export const { addConnectedWallet, removeConnectedWallet } = walletsSlice.actions +export default walletsSlice.reducer diff --git a/src/state/wallets/types.ts b/src/state/wallets/types.ts new file mode 100644 index 0000000000..ab45e68604 --- /dev/null +++ b/src/state/wallets/types.ts @@ -0,0 +1,4 @@ +export interface Wallet { + walletType: string + account: string +}