1
0
mirror of https://github.com/oceanprotocol/commons.git synced 2023-03-15 18:03:00 +01:00

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==", "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==",
"dev": true "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": { "bl": {
"version": "1.2.2", "version": "1.2.2",
"resolved": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz", "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", "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz",
"integrity": "sha1-LdvqfHP/42No365J3DOMBYwritY=" "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": { "filesize": {
"version": "4.1.2", "version": "4.1.2",
"resolved": "https://registry.npmjs.org/filesize/-/filesize-4.1.2.tgz", "resolved": "https://registry.npmjs.org/filesize/-/filesize-4.1.2.tgz",
@ -15531,6 +15562,29 @@
"glob": "^7.1.2" "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": { "ts-pnp": {
"version": "1.1.2", "version": "1.1.2",
"resolved": "https://registry.npmjs.org/ts-pnp/-/ts-pnp-1.1.2.tgz", "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/squid": "0.6.2",
"@oceanprotocol/typographies": "^0.1.0", "@oceanprotocol/typographies": "^0.1.0",
"@sindresorhus/slugify": "^0.9.1", "@sindresorhus/slugify": "^0.9.1",
"bip39": "^3.0.2",
"axios": "^0.19.0", "axios": "^0.19.0",
"classnames": "^2.2.6", "classnames": "^2.2.6",
"ethereum-blockies": "github:MyEtherWallet/blockies", "ethereum-blockies": "github:MyEtherWallet/blockies",
@ -38,6 +39,7 @@
"react-popper": "^1.3.3", "react-popper": "^1.3.3",
"react-router-dom": "^5.0.1", "react-router-dom": "^5.0.1",
"react-transition-group": "^4.1.1", "react-transition-group": "^4.1.1",
"truffle-hdwallet-provider": "1.0.5",
"web3": "1.0.0-beta.37" "web3": "1.0.0-beta.37"
}, },
"devDependencies": { "devDependencies": {

View File

@ -33,6 +33,8 @@ export default class Header extends PureComponent {
{menu.map(item => ( {menu.map(item => (
<MenuItem key={item.title} item={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} /> <AccountStatus className={styles.accountStatus} />
</nav> </nav>
</div> </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 React, { PureComponent } from 'react'
import Web3 from 'web3' import Web3 from 'web3'
import { Logger, Ocean, Account } from '@oceanprotocol/squid' import { Ocean, Account } from '@oceanprotocol/squid'
import { User } from '.' import { User } from '.'
import { provideOcean, requestFromFaucet, FaucetResponse } from '../ocean' import { provideOcean, requestFromFaucet, FaucetResponse } from '../ocean'
import { nodeUri } from '../config' import { nodeUri } from '../config'
import MarketProvider from './MarketProvider' import MarketProvider from './MarketProvider'
import { MetamaskProvider } from './MetamaskProvider'
import { ZeroWalletProvider } from './ZeroWalletProvider'
const POLL_ACCOUNTS = 1000 // every 1s const POLL_ACCOUNTS = 1000 // every 1s
const POLL_NETWORK = POLL_ACCOUNTS * 60 // every 1 min const POLL_NETWORK = POLL_ACCOUNTS * 60 // every 1 min
@ -58,23 +60,57 @@ interface UserProviderState {
ocean: Ocean ocean: Ocean
requestFromFaucet(account: string): Promise<FaucetResponse> requestFromFaucet(account: string): Promise<FaucetResponse>
unlockAccounts(): Promise<any> unlockAccounts(): Promise<any>
loginMetamask(): Promise<any>
loginZeroWallet(): Promise<any>
message: string message: string
} }
export default class UserProvider extends PureComponent<{}, UserProviderState> { export default class UserProvider extends PureComponent<{}, UserProviderState> {
private unlockAccounts = async () => { private unlockAccounts = async () => {
try { try {
await window.ethereum.enable() window.ethereum.enable()
} catch (error) { } catch (error) {
// User denied account access... // User denied account access...
return null 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 = { public state = {
isLogged: false, isLogged: false,
isLoading: true, isLoading: true,
isWeb3: false, isWeb3: true,
isOceanNetwork: false, isOceanNetwork: false,
balance: { balance: {
eth: 0, eth: 0,
@ -86,6 +122,8 @@ export default class UserProvider extends PureComponent<{}, UserProviderState> {
ocean: {} as any, ocean: {} as any,
requestFromFaucet: () => requestFromFaucet(''), requestFromFaucet: () => requestFromFaucet(''),
unlockAccounts: () => this.unlockAccounts(), unlockAccounts: () => this.unlockAccounts(),
loginMetamask: () => this.loginMetamask(),
loginZeroWallet: () => this.loginZeroWallet(),
message: 'Connecting to Ocean...' message: 'Connecting to Ocean...'
} }
@ -94,9 +132,6 @@ export default class UserProvider extends PureComponent<{}, UserProviderState> {
public async componentDidMount() { public async componentDidMount() {
await this.bootstrap() await this.bootstrap()
this.initAccountsPoll()
this.initNetworkPoll()
} }
private initAccountsPoll() { private initAccountsPoll() {
@ -114,105 +149,66 @@ export default class UserProvider extends PureComponent<{}, UserProviderState> {
} }
} }
private getWeb3 = () => { private loadOcean = async () => {
// Modern dapp browsers const { ocean } = await provideOcean(this.state.web3)
if (window.ethereum) { this.setState({ ocean, isLoading: false }, () => {
window.web3 = new Web3(window.ethereum) this.initNetworkPoll()
return window.web3 this.initAccountsPoll()
} this.fetchNetwork()
// Legacy dapp browsers this.fetchAccounts()
else if (window.web3) { })
window.web3 = new Web3(window.web3.currentProvider)
return window.web3
}
// Non-dapp browsers
else {
return null
}
} }
private bootstrap = async () => { private bootstrap = async () => {
try { const logType = localStorage.getItem('logType')
// switch (logType) {
// Start with Web3 detection only case 'Metamask':
// const metamaskProvider = new MetamaskProvider()
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 ( if (
isOceanNetwork !== this.state.isOceanNetwork || (await metamaskProvider.isAvaliable()) &&
network !== this.state.network (await metamaskProvider.isLogged())
) { ) {
this.setState({ isOceanNetwork, network }) const web3 = metamaskProvider.getProvider()
this.setState(
{
isLogged: true,
web3
},
() => {
this.loadOcean()
} }
}) )
} else {
if (!isOceanNetwork) { this.loadOcean()
web3 = this.state.web3 // eslint-disable-line
} }
break
// case 'ZeroWallet':
// Provide the Ocean const zerowalletProvider = new ZeroWalletProvider()
// if (await zerowalletProvider.isLogged()) {
this.setState({ message: 'Connecting to Ocean...' }) await zerowalletProvider.restoreStoredLogin()
this.setState(
const { ocean } = await provideOcean(web3) {
this.setState({ ocean, message: 'Getting accounts...' }) isLogged: true,
web3: zerowalletProvider.getProvider()
// Get accounts },
await this.fetchAccounts() () => {
this.loadOcean()
this.setState({ isLoading: false, message: '' })
} }
// Non-dapp browsers )
else { } else {
this.setState({ message: 'Connecting to Ocean...' }) this.loadOcean()
const { ocean } = await provideOcean(this.state.web3)
this.setState({ ocean, isLoading: false })
this.fetchNetwork()
} }
} catch (e) { break
// error in bootstrap process default:
// show error connecting to ocean this.loadOcean()
Logger.error('web3 error', e.message) break
this.setState({ isLoading: false })
} }
} }
private fetchAccounts = async () => { private fetchAccounts = async () => {
const { ocean, isWeb3, isLogged, isOceanNetwork } = this.state const { ocean, isLogged, isOceanNetwork } = this.state
if (isWeb3) { if (isLogged) {
let accounts let accounts
// Modern dapp browsers // 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: () => { unlockAccounts: () => {
/* empty */ /* empty */
}, },
loginMetamask: () => {
/* empty */
},
loginZeroWallet: () => {
/* empty */
},
message: '' message: ''
}) })

View File

@ -22,7 +22,11 @@ export async function provideOcean(web3provider: Web3) {
verbose 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 } return { ocean }
} }