-
Notifications
You must be signed in to change notification settings - Fork 47
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support Wallet Connect #243
Merged
Merged
Changes from 8 commits
Commits
Show all changes
27 commits
Select commit
Hold shift + click to select a range
d75787b
Basic set up for Wallet Connect
taoalpha c394161
Move connect to integrations folder
taoalpha 136e871
Support QR scanner for wallet connect
taoalpha 44223f7
Fix the style of the prompt screen
taoalpha e2e39e8
Show list of pending requests
taoalpha 7577179
make supported files human readable; fix onScan silent failures due t…
polymorpher 37d3a9b
Revert qr change and add some new entries and fixes
taoalpha 9f0d245
Merge branch 'master' into taoalpha/walletconnect
polymorpher 3ff7c7d
Merge branch 'master' into taoalpha/walletconnect
polymorpher 3afad8b
Merge branch 'master' into taoalpha/walletconnect
polymorpher 7a28132
fix outdated packages; WC wip
polymorpher fb92303
revert to antd 4.17.0 to fix bugs
polymorpher 3f82058
WalletConnect v2
polymorpher 55b5023
fix wc bugs
polymorpher e5a096c
fix wallectconnect ui and bugs
polymorpher 1483f6c
add eip712 typed data support; implement web3provider for walletconne…
polymorpher 8e803ff
cleanup dep
polymorpher fa04857
ditto
polymorpher 400fd6c
support using raw message hash for signing
polymorpher 27ffd8a
allow WC eth_sign only when dev mode is activated
polymorpher 9898035
WalletConnectActionModal
polymorpher 43a1ba4
Wallet Connect tool in ui
polymorpher cc8808f
remove client side web3 dep (duplicating root module)
polymorpher e8f7994
proper web3 resolution; fix bigint type issue
polymorpher d693f89
fix bug and end-to-end test
polymorpher 7af66b7
show equivalent hex address in address input; show wallet name in wC
polymorpher 7506ab7
remvoe console.log
polymorpher File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,271 @@ | ||
import React, { useState, useEffect } from 'react' | ||
import { useDispatch, useSelector } from 'react-redux' | ||
import WalletConnectClient from '@walletconnect/client' | ||
import { InputBox, Link, Text } from '../components/Text' | ||
import Image from 'antd/es/image' | ||
import { Row } from 'antd/es/grid' | ||
import ConfigProvider from 'antd/es/config-provider' | ||
import Button from 'antd/es/button' | ||
import cacheActions from '../state/modules/cache/actions' | ||
import AnimatedSection from '../components/AnimatedSection' | ||
import message from '../message' | ||
import Spin from 'antd/es/spin' | ||
import util, { checkCamera } from '../util' | ||
import QrCodeScanner from '../components/QrCodeScanner' | ||
import { WalletSelector } from './Common' | ||
import Send from '../pages/Show/Send' | ||
import List from 'antd/es/list' | ||
|
||
const PromptView = ({ peerMeta, approveSession, rejectSession }) => { | ||
return ( | ||
<> | ||
<Row type='flex' justify='center' align='middle'> | ||
<Image style={{ maxWidth: '100px' }} src={peerMeta.icons[0]} alt={peerMeta.name} /> | ||
</Row> | ||
<Row type='flex' justify='center' align='middle'> | ||
<Text>{peerMeta.name}</Text> | ||
</Row> | ||
<Row type='flex' justify='center' align='middle'> | ||
<Text>{peerMeta.description}</Text> | ||
</Row> | ||
<Row type='flex' justify='center' align='middle'> | ||
<Link target='_blank' href={peerMeta.url} rel='noreferrer'>{peerMeta.url}</Link> | ||
</Row> | ||
<Row type='flex' justify='center' align='middle' style={{ marginTop: '24px' }}> | ||
<Button style={{ marginRight: '24px' }} onClick={approveSession}>Approve</Button> | ||
<Button onClick={rejectSession}>Reject</Button> | ||
</Row> | ||
</> | ||
) | ||
} | ||
|
||
const WalletConnect = ({ wc }) => { | ||
const dispatch = useDispatch() | ||
const wallets = useSelector(state => state.wallet) | ||
const walletConnectSession = useSelector(state => state.cache.walletConnectSession) | ||
const walletList = Object.keys(wallets).filter(addr => util.safeNormalizedAddress(addr)) | ||
const [selectedAddress, setSelectedAddress] = useState({ value: walletList[0] }) | ||
const [connected, setConnected] = useState(false) | ||
const [loading, setLoading] = useState(false) | ||
// Default to QR unless wc provided. | ||
const [isScanMode, setScanMode] = useState(!wc) | ||
const [hasCamera, setHasCamera] = useState(false) | ||
const [uri, setUri] = useState('') | ||
const [connector, setConnector] = useState(null) | ||
const [peerMeta, setPeerMeta] = useState(null) | ||
const [requests, setRequests] = useState([]) | ||
|
||
useEffect(() => { | ||
const f = async () => { | ||
const [hasCamera] = await checkCamera() | ||
setHasCamera(hasCamera) | ||
} | ||
|
||
f() | ||
}, []) | ||
|
||
useEffect(() => { | ||
if (wc) { | ||
initWalletConnect(wc) | ||
} | ||
}, [wc]) | ||
|
||
const subscribeToEvents = (connector) => { | ||
if (connector) { | ||
connector.on('session_request', (error, payload) => { | ||
if (error) { | ||
throw error | ||
} | ||
// dispatch(cacheActions.fetchVersion({ network })) | ||
const { peerMeta } = payload.params[0] | ||
setPeerMeta(peerMeta) | ||
}) | ||
|
||
connector.on('session_update', error => { | ||
if (error) { | ||
throw error | ||
} | ||
|
||
dispatch(cacheActions.updateWalletConnectSession(connector.session)) | ||
}) | ||
|
||
connector.on('call_request', async (error, payload) => { | ||
console.log('EVENT', 'call_request', 'method', payload.method) | ||
if (error) { | ||
throw error | ||
} | ||
|
||
setRequests(requests => ([...requests, payload])) | ||
}) | ||
|
||
connector.on('connect', (error, payload) => { | ||
if (error) { | ||
throw error | ||
} | ||
|
||
setConnected(true) | ||
dispatch(cacheActions.updateWalletConnectSession(connector.session)) | ||
}) | ||
|
||
connector.on('disconnect', (error, payload) => { | ||
if (error) { | ||
throw error | ||
} | ||
|
||
setConnected(false) | ||
setLoading(false) | ||
setConnector(null) | ||
setPeerMeta(null) | ||
dispatch(cacheActions.updateWalletConnectSession(null)) | ||
}) | ||
|
||
if (connector.connected) { | ||
setConnected(true) | ||
} | ||
|
||
setConnector(connector) | ||
} | ||
} | ||
|
||
useEffect(() => { | ||
if (walletConnectSession) { | ||
const connector = new WalletConnectClient({ session: walletConnectSession }) | ||
subscribeToEvents(connector) | ||
} | ||
}, []) | ||
|
||
const initWalletConnect = async (uri, reportOnError = true) => { | ||
setLoading(true) | ||
|
||
try { | ||
const connector = new WalletConnectClient({ | ||
uri, | ||
clientMeta: { | ||
description: '1Wallet', | ||
url: 'https://1wallet.crazy.one', | ||
icons: ['https://1wallet.crazy.one/1wallet.png'], | ||
name: '1Wallet', | ||
} | ||
}) | ||
|
||
if (!connector.connected) { | ||
await connector.createSession() | ||
} | ||
|
||
setLoading(false) | ||
|
||
subscribeToEvents(connector) | ||
} catch (error) { | ||
if (reportOnError) { | ||
message.error('Failed to connect.', 15) | ||
} | ||
setLoading(false) | ||
} | ||
} | ||
|
||
const approveSession = () => { | ||
if (connector) { | ||
connector.approveSession({ chainId: connector.chainId, accounts: [selectedAddress.value] }) | ||
} | ||
} | ||
|
||
const rejectSession = () => { | ||
if (connector) { | ||
connector.rejectSession() | ||
setUri('') | ||
} | ||
} | ||
|
||
const approveRequest = (request) => { | ||
console.log(request) | ||
if (connector) { | ||
// TODO: Handle requests based on methods | ||
// connector.approveRequest({ | ||
// id: request.id, | ||
// result | ||
// }) | ||
// setRequests(requests.filter(r => r.id !== request.id)) | ||
} | ||
} | ||
|
||
const rejectRequest = (request) => { | ||
console.log(request) | ||
if (connector) { | ||
connector.rejectRequest({ id: request.id, error: { message: 'User rejected the requets.' } }) | ||
setRequests(requests.filter(r => r.id !== request.id)) | ||
} | ||
} | ||
|
||
const disconnect = () => { | ||
if (connector) { | ||
connector.killSession() | ||
setUri('') | ||
} | ||
} | ||
|
||
const onScan = (uri) => { | ||
initWalletConnect(uri, /* reportOnError= */ false) | ||
} | ||
|
||
useEffect(() => { | ||
if (!uri) { | ||
return | ||
} | ||
initWalletConnect(uri) | ||
}, [uri]) | ||
|
||
return ( | ||
<AnimatedSection> | ||
{loading && ( | ||
<Row type='flex' justify='center' align='middle' style={{ minHeight: '100vh' }}> | ||
<Spin size='large' /> | ||
</Row>)} | ||
{!connected | ||
? (peerMeta && peerMeta.name | ||
? <PromptView peerMeta={peerMeta} approveSession={approveSession} rejectSession={rejectSession} /> | ||
: ( | ||
<> | ||
<WalletSelector onAddressSelected={setSelectedAddress} filter={e => e.majorVersion >= 10} showOlderVersions={false} useHex={false} /> | ||
{/* If no camera or `uri` provided, do not show the qr scanner initially. */} | ||
{(!isScanMode || !hasCamera) && ( | ||
<> | ||
<InputBox margin='auto' width={440} value={uri} onChange={({ target: { value } }) => setUri(value)} placeholder='Paste wc: uri...' /> | ||
{hasCamera && <Button onClick={() => setScanMode(true)}>Scan</Button>} | ||
</>)} | ||
{selectedAddress.value && isScanMode && hasCamera && <QrCodeScanner shouldInit uploadBtnText='Upload QR Code Instead' onScan={onScan} />} | ||
</>)) | ||
: ( | ||
<> | ||
<Row type='flex' justify='center' align='middle'> | ||
<Text>{selectedAddress.value}</Text> | ||
<Button type='link' onClick={disconnect}>Disconnect</Button> | ||
</Row> | ||
<ConfigProvider renderEmpty={() => ( | ||
<Text>No pending requests for this wallet.</Text> | ||
)} | ||
> | ||
<List | ||
style={{ marginTop: '24px' }} | ||
size='large' | ||
bordered | ||
dataSource={requests} | ||
// TODO: customize item render based on request method type. | ||
renderItem={item => ( | ||
<List.Item | ||
actions={[<Button key='request-list-action-approve' onClick={() => approveRequest(item)}>Approve</Button>, <Button key='request-list-action-reject' onClick={() => rejectRequest(item)}>Reject</Button>]} | ||
> | ||
{item.method} | ||
{item.method === 'eth_sendTransaction' && | ||
<Send | ||
address={selectedAddress.value} onSuccess={() => alert('a')} | ||
prefillAmount={10} | ||
/>} | ||
</List.Item>)} | ||
/> | ||
</ConfigProvider> | ||
</>)} | ||
</AnimatedSection> | ||
) | ||
} | ||
|
||
export default WalletConnect |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is quite hidden. Probably not the best place to put it. Any suggestions for better place?