Dapps use defaultAccount instead of own selectors (#4386)

* Remove account selection from GitHubHint

* Fix naming

* Update to match BasicCoin

* BasicCoin defaultAddress

* typo

* method registry without selector

* Update after manual tests

* IdentityIcon for localtx

* Fix non-secure personal subscriptions

* Query defaultAccount for non-secure apps on send
This commit is contained in:
Jaco Greeff
2017-02-03 13:54:53 +01:00
committed by Gav Wood
parent 3af45c6ad9
commit acf41d6f27
13 changed files with 115 additions and 172 deletions

View File

@@ -17,10 +17,9 @@
import React, { Component } from 'react';
import { api } from '../parity';
import { attachInterface } from '../services';
import { attachInterface, subscribeDefaultAddress, unsubscribeDefaultAddress } from '../services';
import Button from '../Button';
import Events from '../Events';
import IdentityIcon from '../IdentityIcon';
import Loading from '../Loading';
import styles from './application.css';
@@ -32,7 +31,7 @@ let nextEventId = 0;
export default class Application extends Component {
state = {
fromAddress: null,
defaultAddress: null,
loading: true,
url: '',
urlError: null,
@@ -47,19 +46,32 @@ export default class Application extends Component {
registerType: 'file',
repo: '',
repoError: null,
subscriptionId: null,
events: {},
eventIds: []
}
componentDidMount () {
attachInterface()
.then((state) => {
this.setState(state, () => {
this.setState({ loading: false });
});
return Promise
.all([
attachInterface(),
subscribeDefaultAddress((error, defaultAddress) => {
if (!error) {
this.setState({ defaultAddress });
}
})
])
.then(([state]) => {
this.setState(Object.assign({}, state, {
loading: false
}));
});
}
componentWillUnmount () {
return unsubscribeDefaultAddress();
}
render () {
const { loading } = this.state;
@@ -75,12 +87,14 @@ export default class Application extends Component {
}
renderPage () {
const { fromAddress, registerBusy, url, urlError, contentHash, contentHashError, contentHashOwner, commit, commitError, registerType, repo, repoError } = this.state;
const { defaultAddress, registerBusy, url, urlError, contentHash, contentHashError, contentHashOwner, commit, commitError, registerType, repo, repoError } = this.state;
let hashClass = null;
if (contentHashError) {
hashClass = contentHashOwner !== fromAddress ? styles.hashError : styles.hashWarning;
hashClass = contentHashOwner !== defaultAddress
? styles.hashError
: styles.hashWarning;
} else if (contentHash) {
hashClass = styles.hashOk;
}
@@ -166,20 +180,13 @@ export default class Application extends Component {
}
renderButtons () {
const { accounts, fromAddress, urlError, repoError, commitError, contentHashError, contentHashOwner } = this.state;
const account = accounts[fromAddress];
const { defaultAddress, urlError, repoError, commitError, contentHashError, contentHashOwner } = this.state;
return (
<div className={ styles.buttons }>
<div className={ styles.addressSelect }>
<Button invert onClick={ this.onSelectFromAddress }>
<IdentityIcon address={ account.address } />
<div>{ account.name || account.address }</div>
</Button>
</div>
<Button
onClick={ this.onClickRegister }
disabled={ (contentHashError && contentHashOwner !== fromAddress) || urlError || repoError || commitError }
disabled={ (contentHashError && contentHashOwner !== defaultAddress) || urlError || repoError || commitError }
>register url</Button>
</div>
);
@@ -294,11 +301,11 @@ export default class Application extends Component {
}
onClickRegister = () => {
const { commit, commitError, contentHashError, contentHashOwner, fromAddress, url, urlError, registerType, repo, repoError } = this.state;
const { defaultAddress, commit, commitError, contentHashError, contentHashOwner, url, urlError, registerType, repo, repoError } = this.state;
// TODO: No errors are currently set, validation to be expanded and added for each
// field (query is fast to pick up the issues, so not burning atm)
if ((contentHashError && contentHashOwner !== fromAddress) || repoError || urlError || commitError) {
if ((contentHashError && contentHashOwner !== defaultAddress) || repoError || urlError || commitError) {
return;
}
@@ -368,13 +375,15 @@ export default class Application extends Component {
}
registerContent (contentRepo, contentCommit) {
const { contentHash, fromAddress, instance } = this.state;
const { defaultAddress, contentHash, instance } = this.state;
contentCommit = contentCommit.substr(0, 2) === '0x' ? contentCommit : `0x${contentCommit}`;
contentCommit = contentCommit.substr(0, 2) === '0x'
? contentCommit
: `0x${contentCommit}`;
const eventId = nextEventId++;
const values = [contentHash, contentRepo, contentCommit];
const options = { from: fromAddress };
const options = { from: defaultAddress };
this.setState({
eventIds: [eventId].concat(this.state.eventIds),
@@ -383,7 +392,7 @@ export default class Application extends Component {
contentHash,
contentRepo,
contentCommit,
fromAddress,
defaultAddress,
registerBusy: true,
registerState: 'Estimating gas for the transaction',
timestamp: new Date()
@@ -421,11 +430,11 @@ export default class Application extends Component {
}
registerUrl (contentUrl) {
const { contentHash, fromAddress, instance } = this.state;
const { contentHash, defaultAddress, instance } = this.state;
const eventId = nextEventId++;
const values = [contentHash, contentUrl];
const options = { from: fromAddress };
const options = { from: defaultAddress };
this.setState({
eventIds: [eventId].concat(this.state.eventIds),
@@ -433,7 +442,7 @@ export default class Application extends Component {
[eventId]: {
contentHash,
contentUrl,
fromAddress,
defaultAddress,
registerBusy: true,
registerState: 'Estimating gas for the transaction',
timestamp: new Date()
@@ -470,25 +479,6 @@ export default class Application extends Component {
);
}
onSelectFromAddress = () => {
const { accounts, fromAddress } = this.state;
const addresses = Object.keys(accounts);
let index = 0;
addresses.forEach((address, _index) => {
if (address === fromAddress) {
index = _index;
}
});
index++;
if (index >= addresses.length) {
index = 0;
}
this.setState({ fromAddress: addresses[index] });
}
lookupHash (url) {
const { instance } = this.state;

View File

@@ -1,23 +0,0 @@
/* Copyright 2015-2017 Parity Technologies (UK) Ltd.
/* This file is part of Parity.
/*
/* Parity is free software: you can redistribute it and/or modify
/* it under the terms of the GNU General Public License as published by
/* the Free Software Foundation, either version 3 of the License, or
/* (at your option) any later version.
/*
/* Parity is distributed in the hope that it will be useful,
/* but WITHOUT ANY WARRANTY; without even the implied warranty of
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
/* GNU General Public License for more details.
/*
/* You should have received a copy of the GNU General Public License
/* along with Parity. If not, see <http://www.gnu.org/licenses/>.
*/
.icon {
width: 24px;
height: 24px;
border-radius: 50%;
margin-right: 0.5em;
}

View File

@@ -1,37 +0,0 @@
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
import React, { Component, PropTypes } from 'react';
import { api } from '../parity';
import styles from './identityIcon.css';
export default class IdentityIcon extends Component {
static propTypes = {
address: PropTypes.string.isRequired
}
render () {
const { address } = this.props;
return (
<img
className={ styles.icon }
src={ api.util.createIdentityImg(address, 3) }
/>
);
}
}

View File

@@ -1,17 +0,0 @@
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
export default from './identityIcon';

View File

@@ -17,48 +17,44 @@
import * as abis from '~/contracts/abi';
import { api } from './parity';
let defaultSubscriptionId;
export function attachInterface () {
return api.parity
.registryAddress()
.then((registryAddress) => {
console.log(`the registry was found at ${registryAddress}`);
const registry = api.newContract(abis.registry, registryAddress).instance;
return Promise
.all([
registry.getAddress.call({}, [api.util.sha3('githubhint'), 'A']),
api.parity.accountsInfo()
]);
return api
.newContract(abis.registry, registryAddress).instance
.getAddress.call({}, [api.util.sha3('githubhint'), 'A']);
})
.then(([address, accountsInfo]) => {
.then((address) => {
console.log(`githubhint was found at ${address}`);
const contract = api.newContract(abis.githubhint, address);
const accounts = Object
.keys(accountsInfo)
.reduce((obj, address) => {
const account = accountsInfo[address];
return Object.assign(obj, {
[address]: {
address,
name: account.name
}
});
}, {});
const fromAddress = Object.keys(accounts)[0];
return {
accounts,
address,
accountsInfo,
contract,
instance: contract.instance,
fromAddress
instance: contract.instance
};
})
.catch((error) => {
console.error('attachInterface', error);
});
}
export function subscribeDefaultAddress (callback) {
return api
.subscribe('parity_defaultAccount', callback)
.then((subscriptionId) => {
defaultSubscriptionId = subscriptionId;
return defaultSubscriptionId;
});
}
export function unsubscribeDefaultAddress () {
return api.unsubscribe(defaultSubscriptionId);
}