From cce2a7fad3ee81a4c274c910cc096ad154aa3d11 Mon Sep 17 00:00:00 2001 From: Jernej Pregelj Date: Tue, 9 Jul 2019 12:22:40 +0200 Subject: [PATCH] select wallet modal --- client/package-lock.json | 8 +-- client/package.json | 3 +- .../molecules/AccountStatus/Indicator.tsx | 4 +- .../molecules/AccountStatus/Popover.tsx | 10 +--- client/src/components/organisms/Header.tsx | 7 +-- .../organisms/WalletSelector.module.scss | 49 ++++++++++++++++ .../components/organisms/WalletSelector.tsx | 58 +++++++++++++++++++ .../src/components/organisms/Web3message.tsx | 5 +- client/src/context/BurnerWalletProvider.ts | 48 +++++++++++++++ client/src/context/MetamaskProvider.ts | 6 ++ client/src/context/UserProvider.tsx | 53 ++++++----------- client/src/context/index.tsx | 6 +- 12 files changed, 190 insertions(+), 67 deletions(-) create mode 100644 client/src/components/organisms/WalletSelector.module.scss create mode 100644 client/src/components/organisms/WalletSelector.tsx create mode 100644 client/src/context/BurnerWalletProvider.ts diff --git a/client/package-lock.json b/client/package-lock.json index 2e30db7..ea58962 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -1684,8 +1684,7 @@ "@types/prop-types": { "version": "15.7.1", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.1.tgz", - "integrity": "sha512-CFzn9idOEpHrgdw8JsoTkaDDyRWk1jrzIV8djzcgpq0y9tG4B4lFT+Nxh52DVpDXV+n4+NPNv7M1Dj5uMp6XFg==", - "dev": true + "integrity": "sha512-CFzn9idOEpHrgdw8JsoTkaDDyRWk1jrzIV8djzcgpq0y9tG4B4lFT+Nxh52DVpDXV+n4+NPNv7M1Dj5uMp6XFg==" }, "@types/q": { "version": "1.5.2", @@ -1697,7 +1696,6 @@ "version": "16.8.22", "resolved": "https://registry.npmjs.org/@types/react/-/react-16.8.22.tgz", "integrity": "sha512-C3O1yVqk4sUXqWyx0wlys76eQfhrQhiDhDlHBrjER76lR2S2Agiid/KpOU9oCqj1dISStscz7xXz1Cg8+sCQeA==", - "dev": true, "requires": { "@types/prop-types": "*", "csstype": "^2.2.0" @@ -1744,7 +1742,6 @@ "version": "3.8.2", "resolved": "https://registry.npmjs.org/@types/react-modal/-/react-modal-3.8.2.tgz", "integrity": "sha512-/Drs+XfHg9M60fy2Q63UUlhECXSNknDu3tnwFnbOhcdDjq03VD3hLCfv3X+BBzRqgu4TOu+TwEwBhgI8qdVAAQ==", - "dev": true, "requires": { "@types/react": "*" } @@ -4886,8 +4883,7 @@ "csstype": { "version": "2.6.5", "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.5.tgz", - "integrity": "sha512-JsTaiksRsel5n7XwqPAfB0l3TFKdpjW/kgAELf9vrb5adGA7UCPLajKK5s3nFrcFm3Rkyp/Qkgl73ENc1UY3cA==", - "dev": true + "integrity": "sha512-JsTaiksRsel5n7XwqPAfB0l3TFKdpjW/kgAELf9vrb5adGA7UCPLajKK5s3nFrcFm3Rkyp/Qkgl73ENc1UY3cA==" }, "currently-unhandled": { "version": "0.4.1", diff --git a/client/package.json b/client/package.json index 22dfcf1..cabdcc7 100644 --- a/client/package.json +++ b/client/package.json @@ -16,8 +16,9 @@ "@oceanprotocol/squid": "0.6.2", "@oceanprotocol/typographies": "^0.1.0", "@sindresorhus/slugify": "^0.9.1", - "bip39": "^3.0.2", + "@types/react-modal": "^3.8.2", "axios": "^0.19.0", + "bip39": "^3.0.2", "classnames": "^2.2.6", "ethereum-blockies": "github:MyEtherWallet/blockies", "filesize": "^4.1.2", diff --git a/client/src/components/molecules/AccountStatus/Indicator.tsx b/client/src/components/molecules/AccountStatus/Indicator.tsx index 866922e..ee81513 100644 --- a/client/src/components/molecules/AccountStatus/Indicator.tsx +++ b/client/src/components/molecules/AccountStatus/Indicator.tsx @@ -20,9 +20,7 @@ const Indicator = ({ > {states => - !states.isWeb3 ? ( - - ) : !states.isLogged || !states.isOceanNetwork ? ( + !states.isLogged || !states.isOceanNetwork ? ( ) : states.isLogged ? ( diff --git a/client/src/components/molecules/AccountStatus/Popover.tsx b/client/src/components/molecules/AccountStatus/Popover.tsx index 49dcd96..f16d327 100644 --- a/client/src/components/molecules/AccountStatus/Popover.tsx +++ b/client/src/components/molecules/AccountStatus/Popover.tsx @@ -12,7 +12,6 @@ export default class Popover extends PureComponent<{ account, balance, network, - isWeb3, isOceanNetwork } = this.context @@ -22,12 +21,7 @@ export default class Popover extends PureComponent<{ ref={this.props.forwardedRef} style={this.props.style} > - {!isWeb3 ? ( -
- No Web3 detected. Use a browser with MetaMask installed - to publish assets. -
- ) : ( + { <>
@@ -58,7 +52,7 @@ export default class Popover extends PureComponent<{ : network && `Connected to ${network} network`}
- )} + } ) } diff --git a/client/src/components/organisms/Header.tsx b/client/src/components/organisms/Header.tsx index 59e0384..4fc6833 100644 --- a/client/src/components/organisms/Header.tsx +++ b/client/src/components/organisms/Header.tsx @@ -1,8 +1,8 @@ import React, { PureComponent } from 'react' import { NavLink } from 'react-router-dom' import { ReactComponent as Logo } from '@oceanprotocol/art/logo/logo.svg' -import { User } from '../../context' import AccountStatus from '../molecules/AccountStatus' +import WalletSelector from './WalletSelector' import styles from './Header.module.scss' import menu from '../../data/menu.json' @@ -33,8 +33,7 @@ export default class Header extends PureComponent { {menu.map(item => ( ))} - - + @@ -42,5 +41,3 @@ export default class Header extends PureComponent { ) } } - -Header.contextType = User diff --git a/client/src/components/organisms/WalletSelector.module.scss b/client/src/components/organisms/WalletSelector.module.scss new file mode 100644 index 0000000..d79ea81 --- /dev/null +++ b/client/src/components/organisms/WalletSelector.module.scss @@ -0,0 +1,49 @@ +@import '../../styles/variables'; + +.actions { + text-align: right; + margin-top: $spacer; +} + +.openLink { + margin: 0; + font-size: $font-size-small; +} + +.info { + background: $brand-white; + padding: $spacer; + border: 1px solid $brand-grey-lighter; + border-radius: $border-radius; + + h3 { + font-size: $font-size-base; + margin-top: 0; + margin-bottom: $spacer / 8; + } + + p { + border-bottom: 1px solid $brand-grey-lighter; + padding-bottom: $spacer / 2; + } + + code { + padding: 0; + color: $brand-grey-light; + } +} + +.error { + background: $red; + padding: $spacer / 2; + text-align: center; + color: $brand-white; + border-radius: $border-radius; + font-weight: $font-weight-bold; + font-size: $font-size-small; +} + +.success { + composes: error; + background: $green; +} diff --git a/client/src/components/organisms/WalletSelector.tsx b/client/src/components/organisms/WalletSelector.tsx new file mode 100644 index 0000000..dfa039b --- /dev/null +++ b/client/src/components/organisms/WalletSelector.tsx @@ -0,0 +1,58 @@ +import React, { PureComponent } from 'react' +import Modal from '../atoms/Modal' +import { User } from '../../context' +import styles from './WalletSelector.module.scss' +import Button from '../atoms/Button' + +export default class WalletSelector extends PureComponent< + {}, + { + isModalOpen: boolean + } +> { + public state = { + isModalOpen: false + } + + private toggleModal = () => { + this.setState({ isModalOpen: !this.state.isModalOpen }) + } + + private loginBurnerWallet = () => { + this.context.loginBurnerWallet() + this.toggleModal() + } + + private loginMetamask = () => { + this.context.loginMetamask() + this.toggleModal() + } + + + public render() { + return ( +
+ + +
+ + +
+
+
+ ) + } +} + +WalletSelector.contextType = User diff --git a/client/src/components/organisms/Web3message.tsx b/client/src/components/organisms/Web3message.tsx index e726ae8..db59316 100644 --- a/client/src/components/organisms/Web3message.tsx +++ b/client/src/components/organisms/Web3message.tsx @@ -31,16 +31,13 @@ export default class Web3message extends PureComponent { public render() { const { - isWeb3, isOceanNetwork, isLogged, account, unlockAccounts } = this.context - return !isWeb3 - ? this.message(content.noweb3) - : !isOceanNetwork + return !isOceanNetwork ? this.message(content.wrongNetwork) : !isLogged ? this.message(content.noAccount, '', unlockAccounts) diff --git a/client/src/context/BurnerWalletProvider.ts b/client/src/context/BurnerWalletProvider.ts new file mode 100644 index 0000000..a1b0854 --- /dev/null +++ b/client/src/context/BurnerWalletProvider.ts @@ -0,0 +1,48 @@ +import Web3 from 'web3' +import { nodeUri } from '../config' +const bip39 = require('bip39') +const HDWalletProvider = require('truffle-hdwallet-provider') + +export class BurnerWalletProvider { + web3: Web3 + + constructor() { + // Default + this.web3 = null as any + } + + async isAvaliable() { + return true + } + + async isLogged() { + if (localStorage.getItem('seedphrase') !== null) { + return true + } + return false + } + + async startLogin() { + if (await this.isLogged()) { + const mnemonic = localStorage.getItem('seedphrase') as string + localStorage.setItem('logType', 'BurnerWallet') + const provider = new HDWalletProvider(mnemonic, `${nodeUri}`, 0, 1); + this.web3 = new Web3(provider) + } else { + const mnemonic = bip39.generateMnemonic() + localStorage.setItem('seedphrase', mnemonic) + localStorage.setItem('logType', 'BurnerWallet') + const provider = new HDWalletProvider(mnemonic, `${nodeUri}`, 0, 1); + this.web3 = new Web3(provider) + } + } + + async logout() { + localStorage.removeItem('seedphrase') + localStorage.removeItem('logType') + } + + getProvider() { + return this.web3 + } + } diff --git a/client/src/context/MetamaskProvider.ts b/client/src/context/MetamaskProvider.ts index c85b6d9..d5ff6d3 100644 --- a/client/src/context/MetamaskProvider.ts +++ b/client/src/context/MetamaskProvider.ts @@ -31,11 +31,17 @@ export class MetamaskProvider { async startLogin() { try { await window.ethereum.enable() + localStorage.setItem('logType', 'Metamask') } catch (error) { return false } } + async logout() { + localStorage.removeItem('logType') + // reload page? + } + getProvider() { return this.web3 } diff --git a/client/src/context/UserProvider.tsx b/client/src/context/UserProvider.tsx index 0079c96..b55ea88 100644 --- a/client/src/context/UserProvider.tsx +++ b/client/src/context/UserProvider.tsx @@ -6,7 +6,7 @@ import { provideOcean, requestFromFaucet, FaucetResponse } from '../ocean' import { nodeUri } from '../config' import MarketProvider from './MarketProvider' import { MetamaskProvider } from './MetamaskProvider' -import { ZeroWalletProvider } from './ZeroWalletProvider' +import { BurnerWalletProvider } from './BurnerWalletProvider' const POLL_ACCOUNTS = 1000 // every 1s const POLL_NETWORK = POLL_ACCOUNTS * 60 // every 1 min @@ -48,7 +48,6 @@ declare global { interface UserProviderState { isLogged: boolean isLoading: boolean - isWeb3: boolean isOceanNetwork: boolean account: string balance: { @@ -59,26 +58,15 @@ interface UserProviderState { web3: Web3 ocean: Ocean requestFromFaucet(account: string): Promise - unlockAccounts(): Promise loginMetamask(): Promise - loginZeroWallet(): Promise + loginBurnerWallet(): Promise message: string } export default class UserProvider extends PureComponent<{}, UserProviderState> { - private unlockAccounts = async () => { - try { - window.ethereum.enable() - } catch (error) { - // User denied account access... - return null - } - } - private loginMetamask = async () => { const metamaskProvider = new MetamaskProvider() await metamaskProvider.startLogin() - localStorage.setItem('logType', 'Metamask') const web3 = metamaskProvider.getProvider() this.setState( { @@ -91,11 +79,10 @@ export default class UserProvider extends PureComponent<{}, UserProviderState> { ) } - private loginZeroWallet = async () => { - const zerowalletProvider = new ZeroWalletProvider() - await zerowalletProvider.createLogin() - localStorage.setItem('logType', 'ZeroWallet') - const web3 = zerowalletProvider.getProvider() + private loginBurnerWallet = async () => { + const burnerwalletProvider = new BurnerWalletProvider() + await burnerwalletProvider.startLogin() + const web3 = burnerwalletProvider.getProvider() this.setState( { isLogged: true, @@ -110,7 +97,6 @@ export default class UserProvider extends PureComponent<{}, UserProviderState> { public state = { isLogged: false, isLoading: true, - isWeb3: true, isOceanNetwork: false, balance: { eth: 0, @@ -121,9 +107,8 @@ export default class UserProvider extends PureComponent<{}, UserProviderState> { account: '', ocean: {} as any, requestFromFaucet: () => requestFromFaucet(''), - unlockAccounts: () => this.unlockAccounts(), loginMetamask: () => this.loginMetamask(), - loginZeroWallet: () => this.loginZeroWallet(), + loginBurnerWallet: () => this.loginBurnerWallet(), message: 'Connecting to Ocean...' } @@ -182,10 +167,10 @@ export default class UserProvider extends PureComponent<{}, UserProviderState> { this.loadOcean() } break - case 'ZeroWallet': - const zerowalletProvider = new ZeroWalletProvider() + case 'BurnerWallet': + const zerowalletProvider = new BurnerWalletProvider() if (await zerowalletProvider.isLogged()) { - await zerowalletProvider.restoreStoredLogin() + await zerowalletProvider.startLogin() this.setState( { isLogged: true, @@ -250,19 +235,17 @@ export default class UserProvider extends PureComponent<{}, UserProviderState> { } private fetchNetwork = async () => { - const { ocean, isWeb3 } = this.state + const { ocean } = this.state - if (isWeb3) { - const network = await ocean.keeper.getNetworkName() - const isPacific = network === 'Pacific' - const isNile = network === 'Nile' - const isDuero = network === 'Duero' - const isSpree = network === 'Spree' - const isOceanNetwork = isPacific || isNile || isDuero || isSpree + const network = await ocean.keeper.getNetworkName() + const isPacific = network === 'Pacific' + const isNile = network === 'Nile' + const isDuero = network === 'Duero' + const isSpree = network === 'Spree' + const isOceanNetwork = isPacific || isNile || isDuero || isSpree - network !== this.state.network && + network !== this.state.network && this.setState({ isOceanNetwork, network }) - } } public render() { diff --git a/client/src/context/index.tsx b/client/src/context/index.tsx index 8a1d156..1ca6b5b 100644 --- a/client/src/context/index.tsx +++ b/client/src/context/index.tsx @@ -3,7 +3,6 @@ import React from 'react' export const User = React.createContext({ isLogged: false, isLoading: false, - isWeb3: false, isOceanNetwork: false, account: '', web3: {}, @@ -16,13 +15,10 @@ export const User = React.createContext({ requestFromFaucet: () => { /* empty */ }, - unlockAccounts: () => { - /* empty */ - }, loginMetamask: () => { /* empty */ }, - loginZeroWallet: () => { + loginBurnerWallet: () => { /* empty */ }, message: ''