allow login to wallets

This commit is contained in:
Jernej Pregelj 2019-05-21 12:12:02 +02:00 committed by Matthias Kretschmann
parent d545bcaa30
commit adf52ceb77
Signed by: m
GPG Key ID: 606EEEF3C479A91F
8 changed files with 247 additions and 97 deletions

View File

@ -2986,6 +2986,32 @@
"integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==",
"dev": true
},
"bindings": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
"integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
"requires": {
"file-uri-to-path": "1.0.0"
}
},
"bip39": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/bip39/-/bip39-3.0.2.tgz",
"integrity": "sha512-J4E1r2N0tUylTKt07ibXvhpT2c5pyAFgvuA5q1H9uDy6dEGpjV8jmymh3MTYJDLCNbIVClSB9FbND49I6N24MQ==",
"requires": {
"@types/node": "11.11.6",
"create-hash": "^1.1.0",
"pbkdf2": "^3.0.9",
"randombytes": "^2.0.1"
},
"dependencies": {
"@types/node": {
"version": "11.11.6",
"resolved": "https://registry.npmjs.org/@types/node/-/node-11.11.6.tgz",
"integrity": "sha512-Exw4yUWMBXM3X+8oqzJNRqZSwUAaS4+7NdvHqQuFi/d+synz++xmX3QIf+BFqneW8N31R8Ky+sikfZUXq07ggQ=="
}
}
},
"bl": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz",
@ -6515,6 +6541,11 @@
"resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz",
"integrity": "sha1-LdvqfHP/42No365J3DOMBYwritY="
},
"file-uri-to-path": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
"integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw=="
},
"filesize": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/filesize/-/filesize-4.1.2.tgz",
@ -15531,6 +15562,29 @@
"glob": "^7.1.2"
}
},
"truffle-hdwallet-provider": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/truffle-hdwallet-provider/-/truffle-hdwallet-provider-1.0.5.tgz",
"integrity": "sha512-T9qNm7b6MD0UPWVmmJEhgzW1DdR6mkMDijGBSbdJqYaaBLufoycE+qH3dsV+m1mLTE+ebM5RcJ4gF4oXgDW67w==",
"requires": {
"any-promise": "^1.3.0",
"bindings": "^1.3.1",
"websocket": "^1.0.28"
},
"dependencies": {
"websocket": {
"version": "1.0.28",
"resolved": "https://registry.npmjs.org/websocket/-/websocket-1.0.28.tgz",
"integrity": "sha512-00y/20/80P7H4bCYkzuuvvfDvh+dgtXi5kzDf3UcZwN6boTYaKvsrtZ5lIYm1Gsg48siMErd9M4zjSYfYFHTrA==",
"requires": {
"debug": "^2.2.0",
"nan": "^2.11.0",
"typedarray-to-buffer": "^3.1.5",
"yaeti": "^0.0.6"
}
}
}
},
"ts-pnp": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/ts-pnp/-/ts-pnp-1.1.2.tgz",

View File

@ -16,6 +16,7 @@
"@oceanprotocol/squid": "0.6.2",
"@oceanprotocol/typographies": "^0.1.0",
"@sindresorhus/slugify": "^0.9.1",
"bip39": "^3.0.2",
"axios": "^0.19.0",
"classnames": "^2.2.6",
"ethereum-blockies": "github:MyEtherWallet/blockies",
@ -38,6 +39,7 @@
"react-popper": "^1.3.3",
"react-router-dom": "^5.0.1",
"react-transition-group": "^4.1.1",
"truffle-hdwallet-provider": "1.0.5",
"web3": "1.0.0-beta.37"
},
"devDependencies": {

View File

@ -33,6 +33,8 @@ export default class Header extends PureComponent {
{menu.map(item => (
<MenuItem key={item.title} item={item} />
))}
<button onClick={this.context.loginMetamask}>login Metamask</button>
<button onClick={this.context.loginZeroWallet}>login ZWallet</button>
<AccountStatus className={styles.accountStatus} />
</nav>
</div>

View File

@ -0,0 +1,42 @@
import Web3 from 'web3'
export class MetamaskProvider {
web3: Web3
constructor() {
// Default
this.web3 = null as any
// Modern dapp browsers
if (window.ethereum) {
this.web3 = new Web3(window.ethereum)
}
// Legacy dapp browsers
else if (window.web3) {
this.web3 = new Web3(window.web3.currentProvider)
}
}
async isAvaliable() {
return this.web3 !== null
}
async isLogged() {
if(this.web3 === null) return false
if((await this.web3.eth.getAccounts()).length > 0) {
return true
}
return false
}
async startLogin() {
try {
await window.ethereum.enable()
} catch (error) {
return false
}
}
getProvider() {
return this.web3
}
}

View File

@ -1,10 +1,12 @@
import React, { PureComponent } from 'react'
import Web3 from 'web3'
import { Logger, Ocean, Account } from '@oceanprotocol/squid'
import { Ocean, Account } from '@oceanprotocol/squid'
import { User } from '.'
import { provideOcean, requestFromFaucet, FaucetResponse } from '../ocean'
import { nodeUri } from '../config'
import MarketProvider from './MarketProvider'
import { MetamaskProvider } from './MetamaskProvider'
import { ZeroWalletProvider } from './ZeroWalletProvider'
const POLL_ACCOUNTS = 1000 // every 1s
const POLL_NETWORK = POLL_ACCOUNTS * 60 // every 1 min
@ -58,23 +60,57 @@ interface UserProviderState {
ocean: Ocean
requestFromFaucet(account: string): Promise<FaucetResponse>
unlockAccounts(): Promise<any>
loginMetamask(): Promise<any>
loginZeroWallet(): Promise<any>
message: string
}
export default class UserProvider extends PureComponent<{}, UserProviderState> {
private unlockAccounts = async () => {
try {
await window.ethereum.enable()
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(
{
isLogged: true,
web3
},
() => {
this.loadOcean()
}
)
}
private loginZeroWallet = async () => {
const zerowalletProvider = new ZeroWalletProvider()
await zerowalletProvider.createLogin()
localStorage.setItem('logType', 'ZeroWallet')
const web3 = zerowalletProvider.getProvider()
this.setState(
{
isLogged: true,
web3
},
() => {
this.loadOcean()
}
)
}
public state = {
isLogged: false,
isLoading: true,
isWeb3: false,
isWeb3: true,
isOceanNetwork: false,
balance: {
eth: 0,
@ -86,6 +122,8 @@ export default class UserProvider extends PureComponent<{}, UserProviderState> {
ocean: {} as any,
requestFromFaucet: () => requestFromFaucet(''),
unlockAccounts: () => this.unlockAccounts(),
loginMetamask: () => this.loginMetamask(),
loginZeroWallet: () => this.loginZeroWallet(),
message: 'Connecting to Ocean...'
}
@ -94,9 +132,6 @@ export default class UserProvider extends PureComponent<{}, UserProviderState> {
public async componentDidMount() {
await this.bootstrap()
this.initAccountsPoll()
this.initNetworkPoll()
}
private initAccountsPoll() {
@ -114,105 +149,66 @@ export default class UserProvider extends PureComponent<{}, UserProviderState> {
}
}
private getWeb3 = () => {
// Modern dapp browsers
if (window.ethereum) {
window.web3 = new Web3(window.ethereum)
return window.web3
}
// Legacy dapp browsers
else if (window.web3) {
window.web3 = new Web3(window.web3.currentProvider)
return window.web3
}
// Non-dapp browsers
else {
return null
}
private loadOcean = async () => {
const { ocean } = await provideOcean(this.state.web3)
this.setState({ ocean, isLoading: false }, () => {
this.initNetworkPoll()
this.initAccountsPoll()
this.fetchNetwork()
this.fetchAccounts()
})
}
private bootstrap = async () => {
try {
//
// Start with Web3 detection only
//
this.setState({ message: 'Setting up Web3...' })
let web3 = await this.getWeb3()
web3
? this.setState({ isWeb3: true })
: this.setState({ isWeb3: false })
// Modern & legacy dapp browsers
if (web3 && this.state.isWeb3) {
//
// Detecting network with window.web3
//
let isOceanNetwork
await window.web3.eth.net.getId((err, netId) => {
if (err) return
const isPacific = netId === 0xcea11
const isNile = netId === 8995
const isDuero = netId === 2199
const isSpree = netId === 8996
isOceanNetwork = isPacific || isNile || isDuero || isSpree
const network = isPacific
? 'Pacific'
: isNile
? 'Nile'
: isDuero
? 'Duero'
: netId.toString()
if (
isOceanNetwork !== this.state.isOceanNetwork ||
network !== this.state.network
) {
this.setState({ isOceanNetwork, network })
}
})
if (!isOceanNetwork) {
web3 = this.state.web3 // eslint-disable-line
const logType = localStorage.getItem('logType')
switch (logType) {
case 'Metamask':
const metamaskProvider = new MetamaskProvider()
if (
(await metamaskProvider.isAvaliable()) &&
(await metamaskProvider.isLogged())
) {
const web3 = metamaskProvider.getProvider()
this.setState(
{
isLogged: true,
web3
},
() => {
this.loadOcean()
}
)
} else {
this.loadOcean()
}
//
// Provide the Ocean
//
this.setState({ message: 'Connecting to Ocean...' })
const { ocean } = await provideOcean(web3)
this.setState({ ocean, message: 'Getting accounts...' })
// Get accounts
await this.fetchAccounts()
this.setState({ isLoading: false, message: '' })
}
// Non-dapp browsers
else {
this.setState({ message: 'Connecting to Ocean...' })
const { ocean } = await provideOcean(this.state.web3)
this.setState({ ocean, isLoading: false })
this.fetchNetwork()
}
} catch (e) {
// error in bootstrap process
// show error connecting to ocean
Logger.error('web3 error', e.message)
this.setState({ isLoading: false })
break
case 'ZeroWallet':
const zerowalletProvider = new ZeroWalletProvider()
if (await zerowalletProvider.isLogged()) {
await zerowalletProvider.restoreStoredLogin()
this.setState(
{
isLogged: true,
web3: zerowalletProvider.getProvider()
},
() => {
this.loadOcean()
}
)
} else {
this.loadOcean()
}
break
default:
this.loadOcean()
break
}
}
private fetchAccounts = async () => {
const { ocean, isWeb3, isLogged, isOceanNetwork } = this.state
const { ocean, isLogged, isOceanNetwork } = this.state
if (isWeb3) {
if (isLogged) {
let accounts
// Modern dapp browsers

View File

@ -0,0 +1,44 @@
import Web3 from 'web3'
import { nodeHost, nodePort, nodeScheme } from '../config'
import bip39 from 'bip39'
const HDWalletProvider = require('truffle-hdwallet-provider')
export class ZeroWalletProvider {
web3: Web3
constructor() {
// Default
this.web3 = null as any
}
async isLogged() {
if (localStorage.getItem('seedphrase') !== null) {
return true
}
return false
}
async restoreStoredLogin() {
const mnemonic = localStorage.getItem('seedphrase') as string
localStorage.setItem('seedphrase', mnemonic)
const provider = new HDWalletProvider(mnemonic, `${nodeScheme}://${nodeHost}:${nodePort}`, 0, 1);
this.web3 = new Web3(provider)
}
async createLogin() {
const mnemonic = bip39.generateMnemonic()
localStorage.setItem('seedphrase', mnemonic)
const provider = new HDWalletProvider(mnemonic, `${nodeScheme}://${nodeHost}:${nodePort}`, 0, 1);
this.web3 = new Web3(provider)
}
async restoreLogin(mnemonic: string) {
localStorage.setItem('seedphrase', mnemonic)
const provider = new HDWalletProvider(mnemonic, `${nodeScheme}://${nodeHost}:${nodePort}`, 0, 1);
this.web3 = new Web3(provider)
}
getProvider() {
return this.web3
}
}

View File

@ -19,6 +19,12 @@ export const User = React.createContext({
unlockAccounts: () => {
/* empty */
},
loginMetamask: () => {
/* empty */
},
loginZeroWallet: () => {
/* empty */
},
message: ''
})

View File

@ -22,7 +22,11 @@ export async function provideOcean(web3provider: Web3) {
verbose
}
const ocean: Ocean = await Ocean.getInstance(config)
console.log('accs web3:', (await web3provider.eth.getAccounts())[0])
const ocean: any = await Ocean.getInstance(config)
console.log('accs ocean:', (await ocean.accounts.list())[0].id)
return { ocean }
}