Skip to content

Commit

Permalink
feat: Prefetch qrcode
Browse files Browse the repository at this point in the history
  • Loading branch information
wenty22 committed Oct 31, 2023
1 parent e5213cb commit 3e7d898
Show file tree
Hide file tree
Showing 7 changed files with 134 additions and 66 deletions.
2 changes: 1 addition & 1 deletion packages/walletkit/src/components/RouteProvider/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export function RouteProvider(props: RouteProviderProps) {
const { children } = props;

const { onClose } = useWalletKitContext();
const [route, setRoute] = useState('ConnectWithQRCode');
const [route, setRoute] = useState('');
const { current: history } = useRef<string[]>([]);

const page = useMemo(() => {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import React, { useContext } from 'react';

export interface WalletConnectUriContextProps {
wcUri: string;
}

export const WalletConnectUriContext = React.createContext({} as WalletConnectUriContextProps);

export function useWalletConnectUri() {
const context = useContext(WalletConnectUriContext);
return context;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import { useEffect, useMemo, useState } from 'react';
import { WalletConnectUriContext } from './context';
import { useWalletKitContext } from '../WalletKitProvider/context';
import { WALLET_CONNECT_ID } from '../../wallets';
import { useConnector } from '../../hooks/useConnectors';
import { useAccount, useConnect } from 'wagmi';
import { commonErrorHandler } from '../../utils/common';

/**
* Don't use `useWalletKitConnect`
* otherwise when user repeats go and back between the wallet list and QR code page
* due to the following `connectAsync` logic, multiple errors will be thrown
*/

export interface WalletConnectUriProviderProps {
children: React.ReactNode;
}

let timer: any = 0;

export function WalletConnectUriProvider(props: WalletConnectUriProviderProps) {
const { children } = props;

const { log, options } = useWalletKitContext();

const [wcUri, setWcUri] = useState<string>('');
const connector = useConnector(WALLET_CONNECT_ID);

const { connectAsync } = useConnect(); // don't use `useWalletKitConnect`
const { isConnected } = useAccount();

useEffect(() => {
if (!connector || isConnected || connector?.options.showQrModal) return;

let provider: any;
const updateWcUri = async () => {
provider = await connector.getProvider();
provider.on('display_uri', setWcUri);
};
updateWcUri();

const connectWallet = async () => {
try {
await connectAsync({ connector });
} catch (error: any) {
clearTimeout(timer);

timer = setTimeout(() => {
commonErrorHandler({
log,
error,
handler: options.onError,
});

if (error?.code === 4001) {
connectWallet();
}
}, 100);
}
};

connectWallet();

return () => {
provider?.off?.('display_uri', setWcUri);
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [connector, isConnected]);

const value = useMemo(() => {
return {
wcUri,
};
}, [wcUri]);

return (
<WalletConnectUriContext.Provider value={value}>{children}</WalletConnectUriContext.Provider>
);
}
9 changes: 6 additions & 3 deletions packages/walletkit/src/components/WalletKitProvider/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { WalletKitModal } from '../WalletKitModal';
import { ThemeMode, ThemeProvider, ThemeVariant } from '../ThemeProvider';
import { ToastProvider } from '../base/toast/ToastProvider';
import { CustomTheme } from '../../themes/base';
import { WalletConnectUriProvider } from '../WalletConnectUriProvider';

export interface WalletKitProviderProps {
options: WalletKitOptions;
Expand Down Expand Up @@ -65,9 +66,11 @@ export const WalletKitProvider = (props: WalletKitProviderProps) => {
<WalletKitContext.Provider value={value}>
<ThemeProvider variant={theme} mode={mode} customTheme={customTheme}>
<RouteProvider>
{children}
<WalletKitModal />
<ToastProvider />
<WalletConnectUriProvider>
{children}
<WalletKitModal />
<ToastProvider />
</WalletConnectUriProvider>
</RouteProvider>
</ThemeProvider>
</WalletKitContext.Provider>
Expand Down
94 changes: 34 additions & 60 deletions packages/walletkit/src/hooks/useWalletConnectUri.ts
Original file line number Diff line number Diff line change
@@ -1,87 +1,61 @@
import { useState, useEffect } from 'react';

import { Connector, useAccount } from 'wagmi';
import { useAccount, useConnect } from 'wagmi';
import { useWalletKitContext } from '..';
import { useWalletKitConnect } from './useWalletKitConnect';
import { useConnector } from './useConnectors';
import { WALLET_CONNECT_ID } from '../wallets';
import { commonErrorHandler } from '../utils/common';

/**
* Don't use `useWalletKitConnect`
* otherwise when user repeats go and back between the wallet list and QR code page
* due to the following `connectAsync` logic, multiple errors will be thrown
*/
let timer: any = 0;

export function useWalletConnectUri() {
const { log } = useWalletKitContext();
const { log, options } = useWalletKitContext();

const [wcUri, setWcUri] = useState<string | undefined>(undefined);

const connector = useConnector(WALLET_CONNECT_ID);
const { connectAsync } = useWalletKitConnect();

const { connectAsync } = useConnect(); // don't use `useWalletKitConnect`
const { isConnected } = useAccount();

useEffect(() => {
if (!connector || wcUri || isConnected) return;

async function handleMessage({ type, data }: any) {
if (type === 'display_uri') {
setWcUri(data);
}
}

async function handleChange(e: any) {
log('WC Change', e);
}
async function handleDisconnect() {
log('WC Disconnect');
}
async function handleConnect() {
log('WC Connect');
}
async function handleError(e: any) {
log('WC Error', e);
}

async function connectWallet(connector: Connector) {
const result = await connectAsync({ connector });
if (result) return result;
return false;
}
let provider: any;
const updateWcUri = async () => {
provider = await connector.getProvider();
provider.on('display_uri', setWcUri);
};
updateWcUri();

async function connectWalletConnect(connector: Connector) {
const connectWallet = async () => {
try {
await connectWallet(connector);
await connectAsync({ connector });
} catch (error: any) {
log('catch error');
log(error);
clearTimeout(timer);

timer = setTimeout(() => {
commonErrorHandler({
log,
error,
handler: options.onError,
});

if (error.code) {
switch (error.code) {
case 4001:
log('error.code - User rejected');
connectWalletConnect(connector); // Regenerate QR code
break;
default:
log('error.code - Unknown Error');
break;
if (error?.code === 4001) {
connectWallet();
}
} else {
// Sometimes the error doesn't respond with a code
log('WalletConnect cannot connect.', error);
}
}, 100);
}
}
};

connectWalletConnect(connector);
connectWallet();

connector.on('message', handleMessage);
connector.on('change', handleChange);
connector.on('connect', handleConnect);
connector.on('disconnect', handleDisconnect);
connector.on('error', handleError);
return () => {
console.log('wallet connect');

connector.off('message', handleMessage);
connector.off('change', handleChange);
connector.off('connect', handleConnect);
connector.off('disconnect', handleDisconnect);
connector.off('error', handleError);
provider?.off?.('display_uri', setWcUri);
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [connector, isConnected]);
Expand Down
2 changes: 1 addition & 1 deletion packages/walletkit/src/pages/ConnectWithQRCode/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ import { Link } from '../../components/base/Link';
import { ModalHeader } from '../../components/base/Modal/ModalHeader';
import { useWalletConfig } from '../../hooks/useWalletConfig';
import { useWalletConnectModal } from '../../hooks/useWalletConnectModal';
import { useWalletConnectUri } from '../../hooks/useWalletConnectUri';
import { cx } from '../../utils/css';
import { container, officialButton } from './styles.css';
import { MODAL_AUTO_CLOSE_DELAY } from '../../constants/common';
import { ForwardIcon } from '../../components/base/icons/ForwardIcon';
import { ModalBody } from '../../components/base/Modal/ModalBody';
import { CustomQRCode } from '../../components/CustomQRCode';
import { useWalletConnectUri } from '../../components/WalletConnectUriProvider/context';

export function ConnectWithQRCodePage() {
const { selectedConnector, onClose, options } = useWalletKitContext();
Expand Down
2 changes: 1 addition & 1 deletion packages/walletkit/src/utils/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export function mergeList(list1: any[] = [], list2: any[] = []) {
return result;
}

export function commonErrorHandler(props: any) {
export function commonErrorHandler(props: { log: any; handler: any; error: any }) {
const { log, handler, error } = props;

let text = '';
Expand Down

0 comments on commit 3e7d898

Please sign in to comment.