Skip to content

Commit

Permalink
feat: Add walletConnect qrcode
Browse files Browse the repository at this point in the history
  • Loading branch information
wenty22 committed Oct 31, 2023
1 parent 788d538 commit ae64ae9
Show file tree
Hide file tree
Showing 14 changed files with 198 additions and 74 deletions.
2 changes: 2 additions & 0 deletions examples/vite/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ const config = createConfig(

const options: WalletKitOptions = {
initialChainId: 5600,
// hideOfficialWalletConnectCTA: true,
// hideNoWalletCTA: true,
};

export default function App() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
import QRCodeUtil from 'qrcode';
import { ReactElement, useMemo } from 'react';
import { Box } from '../base/Box';
import { cx } from '../../utils/css';
import { qrCodeLogo, qrCodeWrapper } from './styles.css';

function generateMatrix(
value: string,
Expand All @@ -22,19 +19,19 @@ function generateMatrix(

export interface QRCodeProps {
ecl?: QRCodeUtil.QRCodeErrorCorrectionLevel;
logo?: ReactElement;
logoSize?: number;
clearSize?: number;
size?: number;
uri: string;
}

export function QRCode(props: QRCodeProps) {
const { ecl = 'M', logo, logoSize = 52, size = 200, uri } = props;
const { ecl = 'M', clearSize = 52, size = 212, uri } = props;

const dots = useMemo(() => {
const dots: ReactElement[] = [];
const matrix = generateMatrix(uri, ecl);
const cellSize = size / matrix.length;

const qrList = [
{ x: 0, y: 0 },
{ x: 1, y: 0 },
Expand All @@ -45,22 +42,25 @@ export function QRCode(props: QRCodeProps) {
const x1 = (matrix.length - 7) * cellSize * x;
const y1 = (matrix.length - 7) * cellSize * y;
for (let i = 0; i < 3; i++) {
const width = cellSize * (7 - i * 2);
const r = [8, 4, 0][i];

dots.push(
<rect
fill={i % 2 !== 0 ? 'var(--wk-colors-modalBackground)' : 'var(--wk-colors-qrCodeDot)'}
height={cellSize * (7 - i * 2)}
key={`${i}-${x}-${y}`}
rx={(i - 2) * -5 + (i === 0 ? 2 : 0)} // calculated border radius for corner squares
ry={(i - 2) * -5 + (i === 0 ? 2 : 0)} // calculated border radius for corner squares
width={cellSize * (7 - i * 2)}
fill={i % 2 === 0 ? 'var(--wk-colors-qrCodeDot)' : 'var(--wk-colors-modalBackground)'}
height={width}
width={width}
rx={r}
ry={r}
x={x1 + cellSize * i}
y={y1 + cellSize * i}
/>,
);
}
});

const clearArenaSize = Math.floor((logoSize + 25) / cellSize);
const clearArenaSize = Math.ceil(clearSize / cellSize) + 4;
const matrixMiddleStart = matrix.length / 2 - clearArenaSize / 2;
const matrixMiddleEnd = matrix.length / 2 + clearArenaSize / 2 - 1;

Expand Down Expand Up @@ -98,20 +98,11 @@ export function QRCode(props: QRCodeProps) {
});

return dots;
}, [ecl, logoSize, size, uri]);
}, [ecl, clearSize, size, uri]);

return (
<Box
className={cx('wk-qrcode', qrCodeWrapper)}
style={{
width: size,
height: size,
}}
>
<svg height="100%" width="100%">
{dots}
</svg>
<Box className={cx('wk-qrcode-logo', qrCodeLogo)}>{logo}</Box>
</Box>
<svg height="100%" width="100%" viewBox={`0 0 ${size} ${size}`}>
{dots}
</svg>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { Box } from '../../base/Box';
import { container, corner } from './styles.css';

export function QRCodePlaceHolder() {
return (
<Box className={container}>
<Box as="span" className={corner} />
<Box as="span" className={corner} />
<Box as="span" className={corner} />
</Box>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import { style, keyframes } from '@vanilla-extract/css';
import { cssVar } from '../../..';

const flicker = keyframes({
'0%': {
backgroundPosition: '100% 0',
},
'100%': {
backgroundPosition: '-100% 0',
},
});

export const container = style({
width: '100%',
height: '100%',
opacity: 0.1,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
position: 'absolute',
pointerEvents: 'none',
'::before': {
zIndex: 3,
content: '""',
position: 'absolute',
inset: 0,
backgroundPosition: 'initial',
backgroundRepeat: 'repeat',
backgroundAttachment: 'initial',
backgroundOrigin: 'initial',
backgroundClip: 'initial',
backgroundColor: 'initial',
backgroundSize: '1.888% 1.888%',
backgroundImage: `radial-gradient(${cssVar('qrCodeDot')} 41%,transparent 41%)`,
},
'::after': {
zIndex: 5,
content: '""',
position: 'absolute',
inset: 0,
transform: 'scale(2) rotate(45deg)',
backgroundImage:
'linear-gradient(90deg, rgba(255, 255, 255, 0) 50%, rgb(255, 255, 255), rgba(255, 255, 255, 0))',
backgroundSize: '200% 100%',
animation: `1000ms linear 0s infinite normal both running ${flicker}`,
},
});

export const corner = style({
zIndex: 4,
position: 'absolute',

background: cssVar('qrCodeDot'),
borderRadius: 8,
width: '13.2%',
height: '13.2%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
outline: `3px solid ${cssVar('modalBackground')}`,
'::before': {
content: '""',
width: '42.86%',
height: '42.86%',
borderRadius: 4,
border: `4px solid ${cssVar('modalBackground')}`,
},
selectors: {
'&:nth-child(1)': {
left: 0,
top: 0,
},
'&:nth-child(2)': {
right: 0,
top: 0,
},
'&:nth-child(3)': {
left: 0,
bottom: 0,
},
},
});
33 changes: 33 additions & 0 deletions packages/walletkit/src/components/CustomQRCode/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { ReactElement } from 'react';
import { Box, BoxProps } from '../base/Box';
import { QRCode } from './QRCode';
import { QRCodePlaceHolder } from './QRCodePlaceHolder';
import { qrCodeContainer, qrCodeLogo, qrCodeWrapper } from './styles.css';
import { cx } from '../../utils/css';

export interface CustomQRCodeProps extends BoxProps {
logo?: ReactElement;
logoSize?: number;
value?: string;
}

export function CustomQRCode(props: CustomQRCodeProps) {
const { className, logo, logoSize = 52, value, ...restProps } = props;

return (
<Box className={cx('wk-qrcode', qrCodeContainer, className)} {...restProps}>
<Box className={qrCodeWrapper}>
{value ? <QRCode uri={value} /> : <QRCodePlaceHolder />}
<Box
className={cx('wk-qrcode-logo', qrCodeLogo)}
style={{
width: logoSize,
height: logoSize,
}}
>
{logo}
</Box>
</Box>
</Box>
);
}
34 changes: 34 additions & 0 deletions packages/walletkit/src/components/CustomQRCode/styles.css.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { globalStyle, style } from '@vanilla-extract/css';
import { cssVar } from '../../utils/css';

export const qrCodeContainer = style({
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
width: 240,
height: 240,
overflow: 'hidden',
fontSize: 0,
border: '1px solid',
borderColor: cssVar('qrCodeBorder'),
borderRadius: cssVar('qrCode', 'radii'),
});

export const qrCodeWrapper = style({
width: 212,
height: 212,
position: 'relative',
});

export const qrCodeLogo = style({
position: 'absolute',
left: '50%',
top: '50%',
transform: 'translate(-50%, -50%)',
display: 'inline-flex',
});

globalStyle(`${qrCodeLogo} > svg`, {
width: '100%',
height: '100%',
});
17 changes: 0 additions & 17 deletions packages/walletkit/src/components/QRCode/styles.css.ts

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export type WalletErrorProps = {
export interface WalletKitOptions {
initialChainId?: number;
hideNoWalletCTA?: boolean;
hideOfficialWalletConnectCTA?: boolean;
walletDownloadUrl?: string;
chainsConfig?: ChainProps[];
onClickWallet?: (connector: Connector, e?: React.MouseEvent) => undefined | boolean;
Expand Down
2 changes: 2 additions & 0 deletions packages/walletkit/src/components/base/Modal/styles.css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ export const modal = style({
color: cssVar('text'),
margin: 0,
padding: 0,
transition: 'all 0.3s',
boxSizing: 'border-box',
});

export const modalOverlay = style({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export function getDefaultProviderOptions(options: WalletKitOptions, chains: Cha
const mergedOptions: WalletKitOptions = {
initialChainId: chains?.[0]?.id,
hideNoWalletCTA: false,
hideOfficialWalletConnectCTA: false,
walletDownloadUrl: `https://trustwallet.com/`,
onError,
...restOptions,
Expand Down
2 changes: 1 addition & 1 deletion packages/walletkit/src/hooks/useWalletConnectUri.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { WALLET_CONNECT_ID } from '../wallets';
export function useWalletConnectUri() {
const { log } = useWalletKitContext();

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

const connector = useConnector(WALLET_CONNECT_ID);
const { connectAsync } = useWalletKitConnect();
Expand Down
27 changes: 13 additions & 14 deletions packages/walletkit/src/pages/ConnectWithQRCode/index.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,20 @@
import { useCallback } from 'react';
import { Navbar } from '../../components/Navbar';
import { QRCode } from '../../components/QRCode';
import { useWalletKitContext } from '../../components/WalletKitProvider/context';
import { Box } from '../../components/base/Box';
import { Link } from '../../components/base/Link';
// 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 { officialButton, qrCodeContainer, qrCodeWrapper } from './styles.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';

export function ConnectWithQRCodePage() {
const { selectedConnector, onClose } = useWalletKitContext();
const { selectedConnector, onClose, options } = useWalletKitContext();

const wallet = useWalletConfig(selectedConnector);
const { wcUri } = useWalletConnectUri();
Expand All @@ -36,16 +35,16 @@ export function ConnectWithQRCodePage() {
<Navbar showBack />
<ModalHeader>Scan with your phone</ModalHeader>

<Box className={cx('wk-modal-body', 'wk-wc-qrcode', qrCodeContainer)}>
<Box className={cx('wk-qrcode-wrapper', qrCodeWrapper)}>
{wcUri && <QRCode uri={wcUri} logo={logo} size={212} />}
</Box>
<ModalBody className={cx('wk-scan-qrcode', container)}>
<CustomQRCode value={wcUri} logo={logo} />

<Link className={cx('wk-official-button', officialButton)} onClick={onClickOpenWcModal}>
Open the official WalletConnect modal
<ForwardIcon />
</Link>
</Box>
{!options.hideOfficialWalletConnectCTA && (
<Link className={cx('wk-official-button', officialButton)} onClick={onClickOpenWcModal}>
Open the official WalletConnect modal
<ForwardIcon />
</Link>
)}
</ModalBody>
</>
);
}
16 changes: 1 addition & 15 deletions packages/walletkit/src/pages/ConnectWithQRCode/styles.css.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,7 @@
import { style } from '@vanilla-extract/css';
import { cssVar } from '../..';

export const qrCodeContainer = style({
display: 'flex',
export const container = style({
alignItems: 'center',
justifyContent: 'center',
marginTop: 32,
flexDirection: 'column',
});

export const qrCodeWrapper = style({
width: 240,
height: 240,
padding: 14,
border: '1px solid',
borderColor: cssVar('qrCodeBorder'),
borderRadius: cssVar('qrCode', 'radii'),
});

export const officialButton = style({
Expand Down
2 changes: 0 additions & 2 deletions packages/walletkit/src/pages/Connectors/styles.css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ import { style } from '@vanilla-extract/css';

export const wallets = style({
overflowY: 'auto',
display: 'flex',
flexDirection: 'column',
gap: 16,
});

Expand Down

0 comments on commit ae64ae9

Please sign in to comment.