diff --git a/App.tsx b/App.tsx index ac2e27e..b36da6c 100644 --- a/App.tsx +++ b/App.tsx @@ -1,8 +1,9 @@ import React, { useCallback, useEffect, useState } from 'react'; -import { Button, Snackbar } from 'react-native-paper'; +import { Button, Snackbar, Text } from 'react-native-paper'; import Icon from 'react-native-vector-icons/MaterialCommunityIcons'; import { SignClientTypes } from '@walletconnect/types'; +import { getSdkError } from '@walletconnect/utils'; import { useNavigation } from '@react-navigation/native'; import { NativeStackNavigationProp, @@ -17,22 +18,19 @@ import PairingModal from './components/PairingModal'; import AddSession from './components/AddSession'; import WalletConnect from './components/WalletConnect'; import { StackParamsList } from './types'; -import useInitialization, { - web3wallet, -} from './utils/wallet-connect/WalletConnectUtils'; +import { web3wallet } from './utils/wallet-connect/WalletConnectUtils'; import { EIP155_SIGNING_METHODS } from './utils/wallet-connect/EIP155Lib'; import { getSignParamsMessage } from './utils/wallet-connect/Helpers'; -import { useRequests } from './context/RequestContext'; +import { useWalletConnect } from './context/WalletConnectContext'; const Stack = createNativeStackNavigator(); const App = (): React.JSX.Element => { - useInitialization(); - const navigation = useNavigation>(); - const { requestSession, setRequestSession } = useRequests(); + const { requestSession, setRequestSession, setActiveSessions } = + useWalletConnect(); const [modalVisible, setModalVisible] = useState(false); const [toastVisible, setToastVisible] = useState(false); @@ -95,13 +93,20 @@ const App = (): React.JSX.Element => { }, [requestSession, setRequestSession, navigation], ); + + const onSessionDelete = useCallback(() => { + let sessions = web3wallet?.getActiveSessions(); + setActiveSessions(sessions); + }, []); + useEffect(() => { web3wallet?.on('session_proposal', onSessionProposal); web3wallet?.on('session_request', onSessionRequest); - + web3wallet?.on('session_delete', onSessionDelete); return () => { web3wallet?.off('session_proposal', onSessionProposal); web3wallet?.off('session_request', onSessionRequest); + web3wallet?.off('session_delete', onSessionDelete); }; //TODO: Investigate dependencies }); @@ -113,7 +118,7 @@ const App = (): React.JSX.Element => { name="Laconic" component={HomeScreen} options={{ - title: 'Laconic Wallet', + headerTitle: () => Laconic Wallet, headerBackVisible: false, }} /> @@ -121,7 +126,7 @@ const App = (): React.JSX.Element => { name="SignMessage" component={SignMessage} options={{ - title: 'Sign Message', + headerTitle: () => Sign Message, }} initialParams={{ selectedNetwork: 'Ethereum' }} /> @@ -129,14 +134,16 @@ const App = (): React.JSX.Element => { name="SignRequest" component={SignRequest} options={{ - title: 'Sign this message?', + headerTitle: () => ( + Sign this message? + ), }} /> Bad Request, headerBackVisible: false, }} /> @@ -144,7 +151,7 @@ const App = (): React.JSX.Element => { name="WalletConnect" component={WalletConnect} options={{ - title: 'WalletConnect Sessions', + headerTitle: () => WalletConnect, headerRight: () => ( ), }); } else { @@ -86,6 +84,16 @@ const HomeScreen = () => { cosmosAccounts: [], }); setCurrentIndex(0); + const sessions = await web3wallet.getActiveSessions(); + + Object.keys(sessions).forEach(async sessionId => { + await web3wallet.disconnectSession({ + topic: sessionId, + reason: getSdkError('USER_DISCONNECTED'), + }); + }); + setActiveSessions({}); + hideResetDialog(); setNetwork('eth'); }; diff --git a/components/PairingModal.tsx b/components/PairingModal.tsx index 3b34841..b44959f 100644 --- a/components/PairingModal.tsx +++ b/components/PairingModal.tsx @@ -9,6 +9,7 @@ import { PairingModalProps } from '../types'; import styles from '../styles/stylesheet'; import { web3wallet } from '../utils/wallet-connect/WalletConnectUtils'; import { useAccounts } from '../context/AccountsContext'; +import { useWalletConnect } from '../context/WalletConnectContext'; const PairingModal = ({ visible, @@ -92,6 +93,8 @@ const PairingModal = ({ }); }, [currentProposal]); + const { setActiveSessions } = useWalletConnect(); + const handleAccept = async () => { if (currentProposal) { const { id, params } = currentProposal; @@ -140,6 +143,8 @@ const PairingModal = ({ namespaces, }); + const sessions = web3wallet.getActiveSessions(); + setActiveSessions(sessions); setModalVisible(false); setToastVisible(true); setCurrentProposal(undefined); diff --git a/components/SignMessage.tsx b/components/SignMessage.tsx index 0f90654..a193741 100644 --- a/components/SignMessage.tsx +++ b/components/SignMessage.tsx @@ -35,7 +35,7 @@ const SignMessage = ({ route }: SignProps) => { - + {account && `Account ${account.counterId + 1}`} diff --git a/components/SignRequest.tsx b/components/SignRequest.tsx index df13712..fa5ebeb 100644 --- a/components/SignRequest.tsx +++ b/components/SignRequest.tsx @@ -18,12 +18,12 @@ import { rejectEIP155Request, } from '../utils/wallet-connect/WalletConnectRequests'; import { web3wallet } from '../utils/wallet-connect/WalletConnectUtils'; -import { useRequests } from '../context/RequestContext'; +import { useWalletConnect } from '../context/WalletConnectContext'; type SignRequestProps = NativeStackScreenProps; const SignRequest = ({ route }: SignRequestProps) => { - const { requestSession } = useRequests(); + const { requestSession } = useWalletConnect(); const requestName = requestSession?.peer?.metadata?.name; const requestIcon = requestSession?.peer?.metadata?.icons[0]; diff --git a/components/WalletConnect.tsx b/components/WalletConnect.tsx index 1461f6d..fed7fed 100644 --- a/components/WalletConnect.tsx +++ b/components/WalletConnect.tsx @@ -1,6 +1,71 @@ -import React from 'react'; -import { View, Text } from 'react-native'; +import React, { useEffect } from 'react'; +import { Image, TouchableOpacity, View } from 'react-native'; +import { List, Text } from 'react-native-paper'; + +import { getSdkError } from '@walletconnect/utils'; + +import { useWalletConnect } from '../context/WalletConnectContext'; +import { web3wallet } from '../utils/wallet-connect/WalletConnectUtils'; +import styles from '../styles/stylesheet'; export default function WalletConnect() { - return ; + const { activeSessions, setActiveSessions } = useWalletConnect(); + + const disconnect = async (sessionId: string) => { + await web3wallet.disconnectSession({ + topic: sessionId, + reason: getSdkError('USER_DISCONNECTED'), + }); + const sessions = await web3wallet?.getActiveSessions(); + setActiveSessions(sessions); + return; + }; + + useEffect(() => { + const sessions = web3wallet.getActiveSessions(); + setActiveSessions(sessions); + }, []); + + return ( + + {Object.keys(activeSessions).length > 0 ? ( + <> + + Active Sessions + + + {Object.entries(activeSessions).map( + ([sessionId, session], index) => ( + ( + + )} + right={() => ( + disconnect(sessionId)} + style={{ display: 'flex', justifyContent: 'center' }}> + + + )} + /> + ), + )} + + + ) : ( + + You have no active sessions + + )} + + ); } diff --git a/context/RequestContext.tsx b/context/RequestContext.tsx deleted file mode 100644 index c78233d..0000000 --- a/context/RequestContext.tsx +++ /dev/null @@ -1,31 +0,0 @@ -import React, { createContext, useContext, useState } from 'react'; - -interface RequestContextProps { - requestSession: any; - setRequestSession: (requestSession: any) => void; -} - -const RequestContext = createContext({ - requestSession: {}, - setRequestSession: () => {}, -}); - -const useRequests = () => { - const requestContext = useContext(RequestContext); - return requestContext; -}; - -const RequestProvider = ({ children }: { children: React.ReactNode }) => { - const [requestSession, setRequestSession] = useState({}); - return ( - - {children} - - ); -}; - -export { useRequests, RequestProvider }; diff --git a/context/WalletConnectContext.tsx b/context/WalletConnectContext.tsx new file mode 100644 index 0000000..8161d69 --- /dev/null +++ b/context/WalletConnectContext.tsx @@ -0,0 +1,48 @@ +import React, { createContext, useContext, useEffect, useState } from 'react'; + +import { SessionTypes } from '@walletconnect/types'; + +import { WalletConnectContextProps } from '../types'; +import useInitialization, { + web3wallet, +} from '../utils/wallet-connect/WalletConnectUtils'; + +const WalletConnectContext = createContext({ + requestSession: {}, + setRequestSession: () => {}, + activeSessions: {}, + setActiveSessions: () => {}, +}); + +const useWalletConnect = () => { + const walletConnectContext = useContext(WalletConnectContext); + return walletConnectContext; +}; + +const WalletConnectProvider = ({ children }: { children: React.ReactNode }) => { + useInitialization(); + + useEffect(() => { + const sessions = web3wallet?.getActiveSessions() ?? {}; + setActiveSessions(sessions); + }, []); + + const [requestSession, setRequestSession] = useState({}); + const [activeSessions, setActiveSessions] = useState< + Record + >({}); + + return ( + + {children} + + ); +}; + +export { useWalletConnect, WalletConnectProvider }; diff --git a/index.js b/index.js index 95dc0f7..37d8a67 100644 --- a/index.js +++ b/index.js @@ -7,7 +7,7 @@ import { NavigationContainer } from '@react-navigation/native'; import App from './App'; import { AccountsProvider } from './context/AccountsContext'; -import { RequestProvider } from './context/RequestContext'; +import { WalletConnectProvider } from './context/WalletConnectContext'; import { name as appName } from './app.json'; export default function Main() { @@ -24,11 +24,11 @@ export default function Main() { return ( - + - + ); diff --git a/styles/stylesheet.js b/styles/stylesheet.js index e3de033..0690a8c 100644 --- a/styles/stylesheet.js +++ b/styles/stylesheet.js @@ -18,7 +18,7 @@ const styles = StyleSheet.create({ fontWeight: '700', }, accountContainer: { - marginTop: 24, + marginTop: 12, }, addAccountButton: { marginTop: 24, @@ -48,7 +48,7 @@ const styles = StyleSheet.create({ paddingHorizontal: 24, }, accountInfo: { - marginTop: 24, + marginTop: 12, marginBottom: 30, }, networkDropdown: { diff --git a/types.ts b/types.ts index 51418ad..edbc1b4 100644 --- a/types.ts +++ b/types.ts @@ -1,5 +1,4 @@ -import { StdSignDoc } from '@cosmjs/amino'; -import { SignClientTypes } from '@walletconnect/types'; +import { SignClientTypes, SessionTypes } from '@walletconnect/types'; export type StackParamsList = { Laconic: undefined; @@ -109,3 +108,12 @@ export interface SignModalProps { requestEvent: SignClientTypes.EventArguments['session_request'] | undefined; currentEthAddresses: string[]; } + +export interface WalletConnectContextProps { + requestSession: any; + setRequestSession: (requestSession: any) => void; + activeSessions: Record; + setActiveSessions: ( + activeSessions: Record, + ) => void; +}