Skip to content
This repository has been archived by the owner on Mar 28, 2023. It is now read-only.

Commit

Permalink
Merge pull request #195 from keep-network/react-to-web3
Browse files Browse the repository at this point in the history
Integrate react-web3 into dApp architecture

This PR encapsulates some refactoring of our Web3 logic using
the web3-react library. web3-react's architecture enables a clean
abstraction of connecting different wallet types, forthcoming in
following PRs. Aside from this, it has a well-defined React hook API
which can replace our suite of HOC's (withAccount, withWeb3,
withBalance, the unused ContractWrapper, etc.). Hooks only work
with stateless components, so some components eg. Start were
rewritten to be stateless from their Component class bases.

A new connect wallet dialog is introduced. For now, it connects to
Metamask only. Some additional styles are added.

Web3Loaded and TBTCLoaded have also been refactored to work
with the web3-react flow. They still use promises, but now rely on
a construct called Deferred (originally from JQuery). They still
behave like promises, but we can resolve them independent of
their definition, which aids with composing logic. The dApp UI will
load independent of Web3 being enabled, and form flow relying
on Web3Loaded will block until a wallet is connected.

Minor changes:
- sleep 2 is removed from the npm script - this was a hack from when
  we ran the LESS compiler first.
- Loadable was moved into wrappers/
- Electrum config is loaded from the config.json, instead of embedded
  in code
  • Loading branch information
Shadowfiend authored Apr 3, 2020
2 parents 7d051ca + df1a89f commit 90f12ee
Show file tree
Hide file tree
Showing 12 changed files with 5,359 additions and 3,520 deletions.
8,185 changes: 4,939 additions & 3,246 deletions package-lock.json

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
"version": "0.12.0-pre",
"dependencies": {
"@keep-network/tbtc.js": ">0.12.0-pre <0.12.0-rc",
"@web3-react/core": "^6.0.7",
"@web3-react/injected-connector": "^6.0.7",
"bignumber.js": "^9.0.0",
"classnames": "^2.2.6",
"history": "^4.9.0",
Expand All @@ -19,7 +21,7 @@
"web3": "^1.2.6"
},
"scripts": {
"start-js": "sleep 2 && react-scripts start",
"start-js": "react-scripts start",
"start": "npm-run-all -p start-js",
"build": "react-scripts --max_old_space_size=8192 build",
"test": "react-scripts test --env=jsdom",
Expand Down
61 changes: 61 additions & 0 deletions public/images/metamask-fox.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
95 changes: 43 additions & 52 deletions src/components/deposit/Start.js
Original file line number Diff line number Diff line change
@@ -1,63 +1,54 @@
import React, { Component } from 'react'
import React, { Component, useEffect } from 'react'

import history from '../../history'
import { requestPermission } from '../../lib/notifications'
import { withAccount } from '../../wrappers/web3'
import StatusIndicator from '../svgs/StatusIndicator'
import BTCLogo from '../svgs/btclogo'
import { useWeb3React } from '@web3-react/core'

class Start extends Component {
const handleClickPay = (evt) => {
evt.preventDefault()
evt.stopPropagation()

componentDidMount() {
requestPermission()
}

handleClickPay = (evt) => {
evt.preventDefault()
evt.stopPropagation()

const { account } = this.props

if (account) {
history.push('/deposit/new')
}
}

render() {
const { account } = this.props
history.push('/deposit/new')
}

return (
<div className="deposit-start">
<div className="page-top">
<StatusIndicator green>
<BTCLogo height={100} width={100} />
</StatusIndicator>
</div>
<div className="page-body">
<div className="step">
Step 1/5
</div>
<div className="title">
Initiate a deposit
</div>
<hr />
<div className="description">
<p>To mint tBTC, we first need to initiate a deposit. This is where we will send BTC.</p>
<p>This should take less than 1 minute.</p>
</div>
<div className='cta'>
<button
onClick={this.handleClickPay}
disabled={typeof account === 'undefined'}
className="black"
>
Begin now
</button>
</div>
</div>
const Start = () => {
useEffect(() => {
requestPermission()
}, [])

let { account } = useWeb3React()

return <div className="deposit-start">
<div className="page-top">
<StatusIndicator green>
<BTCLogo height={100} width={100} />
</StatusIndicator>
</div>
<div className="page-body">
<div className="step">
Step 1/5
</div>
<div className="title">
Initiate a deposit
</div>
<hr />
<div className="description">
<p>To mint TBTC, we first need to initiate a deposit. This is where we will send BTC.</p>
<p>This should take less than 1 minute.</p>
</div>
<div className='cta'>
<button
onClick={handleClickPay}
disabled={typeof account === 'undefined'}
className="black"
>
Begin now
</button>
</div>
)
}
</div>
</div>
}

export default withAccount(Start)
export default Start
110 changes: 110 additions & 0 deletions src/components/lib/ConnectWalletDialog.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import React, { Component, useReducer, useState } from 'react'
import Check from '../svgs/Check'
import { useWeb3React } from '@web3-react/core'
import { InjectedConnector } from '@web3-react/injected-connector'

const SUPPORTED_CHAIN_IDS = [
// Mainnet
1,
// Ropsten
3,
// Rinkeby
4,
// Dev chains (Ganache, Geth)
123, // Low chainId to workaround ledgerjs signing issues.
1337,
// Keep testnet
1101
]

// Connectors.
const injectedConnector = new InjectedConnector({
supportedChainIds: SUPPORTED_CHAIN_IDS
})

// Wallets.
const WALLETS = [
{
name: "Metamask",
icon: "/images/metamask-fox.svg",
showName: true
}
]

export const ConnectWalletDialog = ({ shown, onConnected }) => {
const { active, account, activate } = useWeb3React()

let [chosenWallet, setChosenWallet] = useState(null)
let [error, setError] = useState(null)
let state = {
chosenWallet,
error
}

async function chooseWallet(wallet) {
setChosenWallet(wallet)

try {
await activate(injectedConnector, undefined, true)
onConnected()
} catch(ex) {
setError(ex.toString())
throw ex
}
}

const ChooseWalletStep = () => {
return <>
<header>
<div className="title">Connect To A Wallet</div>
</header>
<p>This wallet will be used to sign transactions on Ethereum.</p>

<ul className='wallets'>
{
WALLETS.map(({ name, icon, showName }) => {
return <li className='wallet-option' onClick={() => chooseWallet(name)}>
<img src={icon} />
{showName && name}
</li>
})
}
</ul>
</>
}

const ConnectToWalletStep = () => {
return <>
<header>
<div className="title">Connect To A Wallet</div>
</header>
<p>Connecting to {chosenWallet} wallet...</p>
{ error && <p>{error}</p> }
</>
}

const ConnectedView = () => {
return <div className='connected-view'>
<header>
<div className="title">Connect To A Wallet</div>
</header>

<div className='details'>
<p>{chosenWallet}</p>
<p>
{account}
</p>
</div>
</div>
}

return <div>
<div className={`modal connect-wallet ${shown ? 'open' : 'closed'}`}>
<div className="modal-body">
{!chosenWallet && <ChooseWalletStep />}
{(chosenWallet && !active) && <ConnectToWalletStep />}
{(chosenWallet && active) && <ConnectedView />}
</div>
</div>
</div>
}
71 changes: 31 additions & 40 deletions src/components/lib/Web3Status.js
Original file line number Diff line number Diff line change
@@ -1,46 +1,37 @@
import React, { Component } from 'react'

import { withWeb3, withAccount, withConnectDapp } from '../../wrappers/web3'
import React, { Component, useReducer, useState } from 'react'
import Check from '../svgs/Check'
import { useWeb3React } from '@web3-react/core'
import { ConnectWalletDialog } from './ConnectWalletDialog'

export const Web3Status = (props) => {
const { active, error } = useWeb3React()

let [showConnectWallet, setShowConnectWallet] = useState(false)

class Web3Status extends Component {
componentDidMount() {
this.props.connectDapp()
}
let body = <div>
<div className="web3-status loading">
Loading...
</div>
</div>

if(!active) {
body = <div className="web3-status notify">
<span onClick={() => setShowConnectWallet(true)}>
Connect to a Wallet
</span>
</div>
}

render() {
const { account, loading, web3 } = this.props
else if(active) {
body = <div className="web3-status success">
<Check width="15px" /> Connected
</div>
}

if (loading) {
return (
<div className="web3-status loading">
loading...
</div>
)
}

if (!web3) {
return (
<div className="web3-status alert">
Web3 not detected. We suggest <a href="http://metamask.io" target="_blank" rel="noopener noreferrer">MetaMask</a>.
</div>
)
}

if (!account) {
return (
<div className="web3-status notify">
Web3 detected, but you need to connect & log into an account.
</div>
)
}

return (
<div className="web3-status success">
<Check width="15px" /> Account logged in
</div>
)
}
return <div>
<ConnectWalletDialog onConnected={() => setShowConnectWallet(false)} shown={showConnectWallet} />
{body}
</div>
}

export default withConnectDapp(withWeb3(withAccount(Web3Status)))
export default Web3Status
7 changes: 6 additions & 1 deletion src/css/app.scss
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,11 @@ a {
a {
color: unset;
}

&:hover {
background: darken($lighter-grey, 5%);
cursor: pointer;
}
}
}

Expand Down Expand Up @@ -350,4 +355,4 @@ footer {
}
}
}
}
}
Loading

0 comments on commit 90f12ee

Please sign in to comment.