on cedd040 help sign in
bridge/src/lib/useWalletConnect.ts
202 lines 4.3 kB history raw
1import WalletConnect from '@walletconnect/client';
2import QRCodeModal from '@walletconnect/qrcode-modal';
3import { useEffect, useState } from 'react';
4import { Just } from 'folktale/maybe';
6import { useWallet } from 'store/wallet';
7import { getAuthToken } from './authToken';
8import { DEFAULT_HD_PATH, WALLET_TYPES } from './constants';
9import WalletConnectWallet from './types/WalletConnectWallet';
11type PeerMeta = {
12 description: string;
13 icons: string[];
14 name: string;
15 url: string;
16};
18type ConnectEvent = {
19 event: 'connect';
20 params: [
21 {
22 accounts: string[];
23 chainId: number;
24 peerId: string;
25 peerMeta: PeerMeta;
26 }
27 ];
28};
30export const useWalletConnect = () => {
31 const { setWallet, setWalletHdPath, setAuthToken, resetWallet } = useWallet();
32 const [connector, setConnector] = useState<WalletConnect | null>(null);
33 const [address, setAddress] = useState<string | null>(null);
34 const [peerMeta, setPeerMeta] = useState<PeerMeta | null>(null);
36 const resetConnector = () => {
37 const newConnector = new WalletConnect({
38 bridge: 'https://bridge.walletconnect.org',
39 qrcodeModal: QRCodeModal,
40 });
42 setConnector(newConnector);
44 // restore state from cached connection
45 if (newConnector.accounts.length > 0) {
46 setAddress(newConnector.accounts[0]);
47 }
49 if (newConnector.peerMeta) {
50 setPeerMeta(newConnector.peerMeta);
51 }
52 };
54 // Init connector
55 useEffect(() => {
56 resetConnector();
57 // eslint-disable-next-line react-hooks/exhaustive-deps
58 }, []);
60 // Behavior
61 const connect = () => {
62 if (!connector || connector.connected) {
63 return;
64 }
66 connector.createSession();
67 };
69 const disconnect = async () => {
70 if (!connector) {
71 return;
72 }
74 await connector.killSession();
75 };
77 type AuthenticateArgs = {
78 hdPath?: string;
79 };
81 const authenticate = async ({
82 hdPath = DEFAULT_HD_PATH,
83 }: AuthenticateArgs) => {
84 if (!(address && connector)) {
85 return;
86 }
88 const authToken = await getAuthToken({
89 address,
90 connector,
91 walletType: WALLET_TYPES.WALLET_CONNECT,
92 });
94 // Inspired by the MetamaskWallet implementation :)
95 // TODO: We should refactor / unify how we handle wallets
96 const wallet: WalletConnectWallet = {
97 address,
98 };
100 setAuthToken(Just(authToken));
101 setWallet(Just(wallet));
102 setWalletHdPath(hdPath);
103 };
105 const isConnected = () => {
106 if (!connector) {
107 return false;
108 }
110 return connector.connected;
111 };
113 const initConnectHandler = () => {
114 if (!connector) {
115 return;
116 }
118 connector.on('connect', async (error, payload: ConnectEvent) => {
119 if (error) {
120 throw error;
121 }
123 const address = payload.params[0].accounts[0];
124 setAddress(address);
125 setPeerMeta(payload.params[0].peerMeta);
126 });
127 };
129 const initDisconnectHandler = () => {
130 if (!connector) {
131 return;
132 }
134 connector.on('disconnect', (error, _payload) => {
135 if (error) {
136 throw error;
137 }
139 setAddress(null);
140 setPeerMeta(null);
141 resetWallet();
142 });
143 };
145 const initSessionUpdateHandler = () => {
146 if (!connector) {
147 return;
148 }
150 connector.on('session_update', (error, payload) => {
151 if (error) {
152 throw error;
153 }
155 // TODO: Confirm what should happen on update?
156 // For now, disconnect and logout
157 disconnect();
158 });
159 };
161 const initModalClosedHandler = () => {
162 if (!connector) {
163 return;
164 }
166 connector.on('modal_closed', () => {
167 resetWallet();
168 resetConnector();
169 });
170 };
172 // Init and clean up
173 useEffect(() => {
174 if (!connector) {
175 return;
176 }
178 initConnectHandler();
179 initDisconnectHandler();
180 initSessionUpdateHandler();
181 initModalClosedHandler();
183 return () => {
184 // Clean up listeners
185 connector.off('connect');
186 connector.off('disconnect');
187 connector.off('session_update');
188 };
189 // eslint-disable-next-line react-hooks/exhaustive-deps
190 }, [connector]);
192 return {
193 address,
194 authenticate,
195 connect,
196 connector,
197 disconnect,
198 isConnected,
199 peerMeta,
200 resetConnector,
201 };
202};