Skip to content

Commit ea9957f

Browse files
committed
feat: Add back in Figure Wallet support
1 parent cd0eeff commit ea9957f

File tree

10 files changed

+637
-52
lines changed

10 files changed

+637
-52
lines changed

package-lock.json

Lines changed: 415 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
"@cosmos-kit/react": "2.20.0",
1717
"@esbuild-plugins/node-globals-polyfill": "0.2.3",
1818
"@interchain-ui/react": "1.25.3",
19+
"@provenanceio/walletconnect-js": "3.10.2",
1920
"@provlabs/provenancejs": "0.0.6",
2021
"@reduxjs/toolkit": "1.8.1",
2122
"@reown/appkit": "1.0.7",

src/App.js

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import { useEffect } from 'react';
22
import { ThemeProvider } from 'styled-components';
33
import { BrowserRouter, Route, Switch, Redirect } from 'react-router-dom';
4-
import { useAssets, useColorScheme } from '../src/redux/hooks';
4+
import { useWalletConnect } from '@provenanceio/walletconnect-js';
5+
import { useAssets, useColorScheme, useApp } from '../src/redux/hooks';
56
import { Navigation, Footer, SpriteSheet, BaseStyle } from '../src/Components';
67
import { GlobalStyle } from '../src/theme';
78
import { isProd } from '../src/consts';
@@ -42,6 +43,12 @@ import {
4243
const App = () => {
4344
const { activeTheme } = useColorScheme();
4445

46+
const { setAuthToken } = useApp();
47+
48+
const {
49+
walletConnectState: { signedJWT },
50+
} = useWalletConnect();
51+
4552
const { assetMetadata, assetMetadataLoading, getAssetMetadata, assetMetadataFailed } =
4653
useAssets();
4754

@@ -51,6 +58,12 @@ const App = () => {
5158
}
5259
}, [assetMetadata, assetMetadataLoading, getAssetMetadata, assetMetadataFailed]);
5360

61+
useEffect(() => {
62+
if (signedJWT) {
63+
setAuthToken(signedJWT);
64+
}
65+
}, [setAuthToken, signedJWT]);
66+
5467
return (
5568
<BrowserRouter basename={import.meta.env.PUBLIC_URL || ''}>
5669
<GlobalStyle theme={activeTheme} />

src/Components/UserAccount/UserAccount.tsx

Lines changed: 168 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
import { useEffect, useState } from 'react';
22
import styled, { useTheme } from 'styled-components';
3+
import { wallets } from '@cosmos-kit/leap-extension';
4+
import { QRCodeModal, useWalletConnect } from '@provenanceio/walletconnect-js';
5+
import { Link as BaseLink } from 'react-router-dom';
36
// @ts-ignore
47
import useOnClickOutside from 'react-tiny-hooks/use-on-click-outside';
58
// @ts-ignore
@@ -8,13 +11,16 @@ import useOnEscape from 'react-tiny-hooks/use-on-escape';
811
import useToggle from 'react-tiny-hooks/use-toggle';
912
import { useChain } from '@cosmos-kit/react';
1013
import { cosmos } from '@provlabs/provenancejs';
14+
import { maxLength } from '../../utils';
1115
import { signJWT } from '../../utils/jwt';
1216
import { CHAIN_NAME } from '../../config';
13-
import { ICON_NAMES } from '../../consts';
17+
import { breakpoints, ICON_NAMES, isProd } from '../../consts';
1418
import { useApp } from '../../redux/hooks';
1519
import { PopupNote } from '../../Components/PopupNote';
1620
import Button from '../Button';
1721
import Sprite from '../Sprite';
22+
import Modal from '../../Components/Modal';
23+
import figureWallet from '../../assets/figureMobileWalletIcon.png';
1824

1925
const Container = styled.div`
2026
position: relative;
@@ -30,59 +36,128 @@ const AccountBtn = styled(Button)<{ isLoggedIn?: boolean }>`
3036
animation-iteration-count: ${({ isLoggedIn }) => (isLoggedIn ? 0 : 2)};
3137
`;
3238

39+
const PopupTxt = styled.p`
40+
text-align: center;
41+
@media ${breakpoints.up('md')} {
42+
white-space: nowrap;
43+
}
44+
`;
45+
46+
const LogoutButton = styled(Button)`
47+
float: right;
48+
`;
49+
50+
const Link = styled(BaseLink)`
51+
&&& {
52+
:hover {
53+
opacity: 1;
54+
text-decoration: underline;
55+
}
56+
:visited {
57+
color: ${({ theme }) => theme.FONT_NAV_VISITED};
58+
}
59+
color: ${({ theme }) => theme.FONT_NAV};
60+
}
61+
`;
62+
63+
const ModalContent = styled.div`
64+
display: grid;
65+
grid-template-columns: 1fr;
66+
justify-content: center;
67+
justify-items: center;
68+
grid-auto-columns: max-content;
69+
@media ${breakpoints.up('md')} {
70+
grid-template-columns: 1fr 1fr;
71+
}
72+
`;
73+
74+
const ModalTitle = styled.div`
75+
font-weight: ${({ theme }) => theme.FONT_WEIGHT_BOLD};
76+
margin: 5px 0 10px 0;
77+
font-size: 1.063rem;
78+
`;
79+
80+
const ModalWalletButton = styled.div`
81+
padding: 0 20px 20px 20px;
82+
border-radius: 8px;
83+
font-size: 1rem;
84+
width: 100%;
85+
font-weight: ${({ theme }) => theme.FONT_WEIGHT_BOLD};
86+
display: flex;
87+
flex-direction: column;
88+
text-align: center;
89+
justify-items: center;
90+
justify-content: center;
91+
max-width: 200px;
92+
cursor: pointer;
93+
:hover {
94+
background-color: ${({ theme }) => theme.BACKGROUND_LIGHT};
95+
}
96+
`;
97+
98+
const WalletTitle = styled.p`
99+
margin-bottom: 4px;
100+
`;
101+
33102
const UserAccount = ({ isMobile }: { isMobile: boolean }) => {
34-
const { isLoggedIn, setIsLoggedIn, setWalletAddress } = useApp();
103+
const { isLoggedIn, setIsLoggedIn, setWalletAddress, setAuthToken, authToken, setWalletUrl } = useApp();
35104
const theme = useTheme();
36105
const position = isMobile ? 'above' : 'left';
37106
const [visible, setVisible] = useState(false);
38107

39-
const [, , , deactivateShowPopup] = useToggle();
108+
const [showPopup, toggleShowPopup, , deactivateShowPopup] = useToggle();
40109
const containerRef = useOnClickOutside(deactivateShowPopup);
41110
useOnEscape(deactivateShowPopup);
42-
43-
const { status, connect, address, signArbitrary, getSigningStargateClient, getAccount, wallet } =
44-
useChain(CHAIN_NAME);
45-
const { setAuthToken, authToken } = useApp();
111+
// This is the old Figure Wallet stuff
112+
const { walletConnectService: wcs, walletConnectState } = useWalletConnect();
113+
// This is Leap
114+
const {
115+
status,
116+
connect,
117+
address,
118+
signArbitrary,
119+
isWalletDisconnected,
120+
wallet,
121+
getSigningStargateClient,
122+
getAccount,
123+
} = useChain(CHAIN_NAME);
46124
const provJWT = localStorage.getItem('provenanceJWT');
47125
const jwtInfo = provJWT ? JSON.parse(provJWT) : '';
48126
const signedJWT = jwtInfo.expires < Date.now() / 1000 ? '' : jwtInfo.jwt;
49127

50128
useEffect(() => {
51-
if (status === 'Disconnected') {
129+
if (isWalletDisconnected && !walletConnectState.connected) {
52130
localStorage.removeItem('provenanceJWT');
53131
setIsLoggedIn(false);
54-
setAuthToken('');
55132
setWalletAddress('');
56133
}
57-
}, [setAuthToken, setWalletAddress, status, setIsLoggedIn]);
134+
}, [setAuthToken, setWalletAddress, status, isWalletDisconnected, setIsLoggedIn, walletConnectState]);
58135

59136
useEffect(() => {
60137
if (jwtInfo && jwtInfo.expires < Date.now() / 1000) {
61138
localStorage.removeItem('provenanceJWT');
62-
setIsLoggedIn(false);
63-
setAuthToken('');
64139
setWalletAddress('');
140+
setIsLoggedIn(false);
65141
}
66-
}, [jwtInfo, setAuthToken, setIsLoggedIn, setWalletAddress]);
142+
}, [jwtInfo, setIsLoggedIn, setWalletAddress]);
67143

68144
useEffect(() => {
69-
if (signedJWT) {
145+
if (signedJWT && status === 'Connected') {
70146
setAuthToken(signedJWT);
71147
}
72-
}, [setAuthToken, signedJWT]);
148+
}, [setAuthToken, signedJWT, status]);
73149

74150
useEffect(() => {
75-
setIsLoggedIn(status === 'Connected');
76-
if (address) {
77-
setWalletAddress(address);
151+
setIsLoggedIn(status === 'Connected' || walletConnectState.status === 'connected');
152+
if (address || walletConnectState.address) {
153+
setWalletAddress(address || walletConnectState.address);
78154
}
79-
}, [status, address, setIsLoggedIn, setWalletAddress]);
155+
}, [status, address, setIsLoggedIn, setWalletAddress, walletConnectState]);
80156

81-
// This is the effect that signs the local JWT to access the explorer service
157+
// This only occurs when connecting to Leap wallets
82158
useEffect(() => {
83159
const initialSigningEvent = async () => {
84160
if (
85-
!authToken &&
86161
status === 'Connected' &&
87162
address &&
88163
wallet &&
@@ -161,9 +236,24 @@ const UserAccount = ({ isMobile }: { isMobile: boolean }) => {
161236
]);
162237

163238
const handleLoginClick = () => {
164-
connect();
239+
if (wallet?.name.includes('leap')) {
240+
connect()
241+
} else {
242+
toggleShowPopup();
243+
wcs.connect();
244+
}
165245
};
166246

247+
const handleLogoutFigureWallet = () => {
248+
setWalletAddress('')
249+
setWalletUrl('')
250+
setIsLoggedIn(false)
251+
wcs.disconnect();
252+
setVisible(false);
253+
}
254+
255+
const [openSelectWalletModal, setOpenSelectWalletModal] = useState(false);
256+
167257
return (
168258
<Container
169259
ref={containerRef}
@@ -173,13 +263,68 @@ const UserAccount = ({ isMobile }: { isMobile: boolean }) => {
173263
<PopupNote show={!isLoggedIn && visible} position={position} zIndex="201">
174264
Login
175265
</PopupNote>
176-
<AccountBtn onClick={handleLoginClick} isLoggedIn={isLoggedIn}>
266+
<AccountBtn
267+
onClick={isLoggedIn ? handleLoginClick : () => setOpenSelectWalletModal(true)}
268+
isLoggedIn={isLoggedIn}
269+
>
177270
<Sprite
178271
icon={isLoggedIn ? ICON_NAMES.ACCOUNT : ICON_NAMES.KEY}
179272
color={theme.FONT_NAV}
180273
size="20px"
181274
/>
182275
</AccountBtn>
276+
{isLoggedIn && (
277+
<PopupNote show={showPopup} position={position} delay={0} zIndex="201">
278+
<PopupTxt>You are currently logged in as</PopupTxt>
279+
<PopupTxt>
280+
<Link to={`/accounts/${walletConnectState.address}`}>
281+
{isMobile ? maxLength(walletConnectState.address, 11, '3') : walletConnectState.address}
282+
</Link>
283+
</PopupTxt>
284+
<LogoutButton color="secondary" onClick={handleLogoutFigureWallet} icon={ICON_NAMES.LOGOUT}>
285+
Sign Out
286+
</LogoutButton>
287+
</PopupNote>
288+
)}
289+
<Modal isOpen={openSelectWalletModal} onClose={() => setOpenSelectWalletModal(false)}>
290+
<div>
291+
<ModalTitle>Select a Wallet Provider</ModalTitle>
292+
<ModalContent>
293+
<ModalWalletButton
294+
onClick={() => {
295+
setOpenSelectWalletModal(false);
296+
connect();
297+
}}
298+
>
299+
<WalletTitle>Leap Wallet</WalletTitle>
300+
<img src={wallets[0].walletInfo.logo as string} alt="Leap Wallet" />
301+
</ModalWalletButton>
302+
<ModalWalletButton
303+
onClick={() => {
304+
setOpenSelectWalletModal(false);
305+
wcs.connect();
306+
}}
307+
>
308+
<WalletTitle>Figure Wallet</WalletTitle>
309+
<img src={figureWallet} alt="Figure Wallet" />
310+
</ModalWalletButton>
311+
</ModalContent>
312+
</div>
313+
</Modal>
314+
<QRCodeModal
315+
walletConnectService={wcs}
316+
title="Scan the QRCode with your mobile Provenance Blockchain Wallet."
317+
className="QR-Code-Modal"
318+
devWallets={[
319+
'figure_mobile_test',
320+
'figure_hosted_test',
321+
// @ts-ignore
322+
'provenance_extension',
323+
// @ts-ignore
324+
'provenance_mobile',
325+
]}
326+
hideWallets={isProd ? ['figure_hosted_test'] : ['figure_hosted']}
327+
/>
183328
</Container>
184329
);
185330
};

0 commit comments

Comments
 (0)