1import WalletConnect from '@walletconnect/client';
2import QRCodeModal from '@walletconnect/qrcode-modal';
3import { ITxData } from '@walletconnect/types';
5import { useEffect, useMemo, useState } from 'react';
6import { Just, Nothing } from 'folktale/maybe';
8import { useWallet } from 'store/wallet';
9import { getAuthToken } from './authToken';
10import { WALLET_TYPES } from './constants';
11import WalletConnectWallet from './types/WalletConnectWallet';
32export const useWalletConnect = () => {
40 const [connector, setConnector] = useState<WalletConnect | null>(null);
41 const [address, setAddress] = useState<string | null>(null);
42 const [peerMeta, setPeerMeta] = useState<PeerMeta | null>(null);
44 const resetConnector = () => {
45 const newConnector = new WalletConnect({
46 bridge: 'https://bridge.walletconnect.org',
47 qrcodeModal: QRCodeModal,
50 setConnector(newConnector);
52 // restore state from cached connection
53 if (newConnector.accounts.length > 0) {
54 setAddress(newConnector.accounts[0]);
57 if (newConnector.peerMeta) {
58 setPeerMeta(newConnector.peerMeta);
65 // eslint-disable-next-line react-hooks/exhaustive-deps
69 const connect = async () => {
70 if (!connector || connector.connected) {
74 await connector.createSession();
77 const disconnect = async () => {
82 await connector.killSession();
85 const authenticate = async () => {
86 if (!(address && connector)) {
90 const wallet: WalletConnectWallet = {
93 setWallet(Just(wallet));
94 if (skipLoginSigning) {
99 let authToken = Nothing();
101 const token = await getAuthToken({
104 walletType: WALLET_TYPES.WALLET_CONNECT,
106 authToken = Just(token);
107 setAuthToken(authToken);
109 if (e.message === 'METHOD_NOT_SUPPORTED') {
111 'wallet does not support message signing. proceeding without auth token.'
115 //TODO should errors with this *really* prevent login?
120 const isConnected = () => {
125 return connector.connected;
128 const peerIcon = useMemo(() => {
129 if (!peerMeta?.icons) {
133 // Some peers return a list of empty string(s) :)
134 const iconCandidates = peerMeta.icons.filter(pm => pm !== '');
136 return iconCandidates.length > 0 ? iconCandidates[0] : null;
139 const signTransaction = async ({
147 }: ITxData): Promise<string> => {
148 return new Promise((resolve, reject) => {
149 if (!connector || !isConnected()) {
150 reject(new Error('No connected wallet available for signing'));
164 .then((signature: string) => resolve(signature))
165 .catch((error: Error) => reject(error));
169 const sendTransaction = async ({
177 }: ITxData): Promise<string> => {
178 return new Promise((resolve, reject) => {
179 if (!connector || !isConnected()) {
180 reject(new Error('No connected wallet available for sending'));
184 //REVIEW .then path untested
195 .then((txHash: string) => resolve(txHash))
196 .catch((error: Error) => reject(error));
201 const initConnectHandler = () => {
206 connector.on('connect', async (error, payload: ConnectEvent) => {
211 const address = payload.params[0].accounts[0];
213 setPeerMeta(payload.params[0].peerMeta);
217 const initDisconnectHandler = () => {
222 connector.on('disconnect', (error, _payload) => {
233 const initSessionUpdateHandler = () => {
238 connector.on('session_update', (error, payload) => {
247 const initModalClosedHandler = () => {
252 connector.on('modal_closed', () => {
264 initConnectHandler();
265 initDisconnectHandler();
266 initSessionUpdateHandler();
267 initModalClosedHandler();
270 // Clean up listeners
271 connector.off('connect');
272 connector.off('disconnect');
273 connector.off('session_update');
274 connector.off('modal_closed');
276 // eslint-disable-next-line react-hooks/exhaustive-deps
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list