Skip to content
This repository has been archived by the owner on Nov 6, 2020. It is now read-only.

Commit

Permalink
Basic Details for Wallet #3282
Browse files Browse the repository at this point in the history
  • Loading branch information
ngotchac committed Nov 30, 2016
1 parent 8d45509 commit 4f39eab
Show file tree
Hide file tree
Showing 11 changed files with 251 additions and 50 deletions.
2 changes: 1 addition & 1 deletion js/src/redux/providers/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,4 @@ export statusReducer from './statusReducer';
export blockchainReducer from './blockchainReducer';
export compilerReducer from './compilerReducer';
export snackbarReducer from './snackbarReducer';
export walletsReducer from './walletsReducer';
export walletReducer from './walletReducer';
2 changes: 1 addition & 1 deletion js/src/redux/providers/personalActions.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
import { isEqual } from 'lodash';

import { fetchBalances } from './balancesActions';
import { attachWallets } from './walletsActions';
import { attachWallets } from './walletActions';

export function personalAccountsInfo (accountsInfo) {
const accounts = {};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,23 @@ import { isEqual, uniq, range } from 'lodash';
import Contract from '../../api/contract';
import { wallet as WALLET_ABI } from '../../contracts/abi';

const UPDATE_OWNERS = 'owners';
const UPDATE_REQUIRE = 'require';
const UPDATE_DAILYLIMIT = 'dailylimit';

export function attachWallets (_wallets) {
return (dispatch, getState) => {
const { wallets, api } = getState();
const { wallet, api } = getState();

const prevAddresses = wallets.walletsAddresses;
const prevAddresses = wallet.walletsAddresses;
const nextAddresses = Object.keys(_wallets).map((a) => a.toLowerCase()).sort();

if (isEqual(prevAddresses, nextAddresses)) {
return;
}

if (wallets.filterSubId) {
api.eth.uninstallFilter(wallets.filterSubId);
if (wallet.filterSubId) {
api.eth.uninstallFilter(wallet.filterSubId);
}

if (nextAddresses.length === 0) {
Expand All @@ -51,7 +55,7 @@ export function attachWallets (_wallets) {
})
.catch((error) => {
if (process.env.NODE_ENV === 'production') {
console.error('walletsActions::attachWallets', error);
console.error('walletActions::attachWallets', error);
} else {
throw error;
}
Expand All @@ -69,13 +73,13 @@ export function load (api) {
api.subscribe('eth_blockNumber', (error) => {
if (error) {
if (process.env.NODE_ENV === 'production') {
return console.error('[eth_blockNumber] walletsActions::load', error);
return console.error('[eth_blockNumber] walletActions::load', error);
} else {
throw error;
}
}

const { filterSubId } = getState().wallets;
const { filterSubId } = getState().wallet;

if (!filterSubId) {
return;
Expand All @@ -88,7 +92,7 @@ export function load (api) {
})
.catch((error) => {
if (process.env.NODE_ENV === 'production') {
return console.error('[getFilterChanges] walletsActions::load', error);
return console.error('[getFilterChanges] walletActions::load', error);
} else {
throw error;
}
Expand All @@ -102,8 +106,9 @@ function fetchWalletsInfo (updates) {
if (Array.isArray(updates)) {
const _updates = updates.reduce((updates, address) => {
updates[address] = {
owners: true,
require: true,
[ UPDATE_OWNERS ]: true,
[ UPDATE_REQUIRE ]: true,
[ UPDATE_DAILYLIMIT ]: true,
transactions: true,
address
};
Expand All @@ -114,7 +119,7 @@ function fetchWalletsInfo (updates) {
return fetchWalletsInfo(_updates)(dispatch, getState);
}

const { contract } = getState().wallets;
const { contract } = getState().wallet;
const _updates = Object.values(updates);

Promise
Expand All @@ -124,7 +129,7 @@ function fetchWalletsInfo (updates) {
})
.catch((error) => {
if (process.env.NODE_ENV === 'production') {
return console.error('walletsActions::fetchWalletsInfo', error);
return console.error('walletAction::fetchWalletsInfo', error);
} else {
throw error;
}
Expand All @@ -135,10 +140,19 @@ function fetchWalletsInfo (updates) {
function fetchWalletInfo (contract, update) {
const promises = [];

if (update.owners) {
if (update[UPDATE_OWNERS]) {
promises.push(fetchWalletOwners(contract, update.address));
}

if (update[UPDATE_REQUIRE]) {
promises.push(fetchWalletRequire(contract, update.address));
}


if (update[UPDATE_DAILYLIMIT]) {
promises.push(fetchWalletDailylimit(contract, update.address));
}

return Promise
.all(promises)
.then((updates) => {
Expand All @@ -160,18 +174,56 @@ function fetchWalletOwners (contract, address) {
.then((mNumOwners) => {
return Promise.all(range(mNumOwners.toNumber()).map((idx) => walletInstance.getOwner.call({}, [ idx ])));
})
.then((owners) => {
.then((value) => {
return {
key: UPDATE_OWNERS,
value
};
});
}

function fetchWalletRequire (contract, address) {
const walletInstance = contract.at(address).instance;

return walletInstance
.m_required.call()
.then((value) => {
return {
key: 'owners',
value: owners
key: UPDATE_REQUIRE,
value
};
});
}

function fetchWalletDailylimit (contract, address) {
const walletInstance = contract.at(address).instance;

return Promise
.all([
walletInstance.m_dailyLimit.call(),
walletInstance.m_spentToday.call(),
walletInstance.m_lastDay.call()
])
.then((values) => {
return {
key: UPDATE_DAILYLIMIT,
value: {
limit: values[0],
spent: values[1],
last: values[2]
}
};
});
}

function parseLogs (logs) {
return (dispatch, getState) => {
const { wallets } = getState();
const { contract } = wallets;
if (!logs || logs.length === 0) {
return;
}

const { wallet } = getState();
const { contract } = wallet;

const updates = {};

Expand All @@ -186,14 +238,14 @@ function parseLogs (logs) {
case [ contract.OwnerRemoved.signature ]:
updates[address] = {
...prev,
owners: true
[ UPDATE_OWNERS ]: true
};
return;

case [ contract.RequirementChanged.signature ]:
updates[address] = {
...prev,
require: true
[ UPDATE_REQUIRE ]: true
};
return;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,10 @@ export default handleActions({

Object.values(wallets).forEach((wallet) => {
const prevWallet = prevWallets[wallet.address] || {};
const nextWallet = nextWallets[wallet.address];

nextWallets[wallet.address] = {
...prevWallet,
...nextWallet
...wallet
};
});

Expand Down
4 changes: 2 additions & 2 deletions js/src/redux/reducers.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
import { combineReducers } from 'redux';
import { routerReducer } from 'react-router-redux';

import { apiReducer, balancesReducer, blockchainReducer, compilerReducer, imagesReducer, personalReducer, signerReducer, statusReducer as nodeStatusReducer, snackbarReducer, walletsReducer } from './providers';
import { apiReducer, balancesReducer, blockchainReducer, compilerReducer, imagesReducer, personalReducer, signerReducer, statusReducer as nodeStatusReducer, snackbarReducer, walletReducer } from './providers';

import errorReducer from '../ui/Errors/reducers';
import settingsReducer from '../views/Settings/reducers';
Expand All @@ -39,6 +39,6 @@ export default function () {
personal: personalReducer,
signer: signerReducer,
snackbar: snackbarReducer,
wallets: walletsReducer
wallet: walletReducer
});
}
2 changes: 1 addition & 1 deletion js/src/redux/store.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { applyMiddleware, createStore } from 'redux';
import initMiddleware from './middleware';
import initReducers from './reducers';

import { load as loadWallet } from './providers/walletsActions';
import { load as loadWallet } from './providers/walletActions';

import {
Balances as BalancesProvider,
Expand Down
2 changes: 1 addition & 1 deletion js/src/ui/Form/InputAddress/inputAddress.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class InputAddress extends Component {
const { className, disabled, error, label, hint, value, text, onSubmit, accountsInfo, tokens } = this.props;

const account = accountsInfo[value] || tokens[value];
const hasAccount = account && (!account.meta || !account.meta.deleted);
const hasAccount = account && !(account.meta && account.meta.deleted);

const icon = this.renderIcon();

Expand Down
102 changes: 102 additions & 0 deletions js/src/views/Wallet/Details/details.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
// Copyright 2015, 2016 Ethcore (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 moment from 'moment';

import { Container, InputAddress, Input } from '../../../ui';

import styles from '../wallet.css';

export default class WalletDetails extends Component {
static contextTypes = {
api: PropTypes.object.isRequired
};

static propTypes = {
owners: PropTypes.array,
require: PropTypes.object,
dailylimit: PropTypes.object
};

render () {
return (
<div className={ styles.details }>
<Container title='Owners'>
{ this.renderOwners() }
</Container>

<Container title='Details'>
{ this.renderDetails() }
</Container>
</div>
);
}

renderOwners () {
const { owners } = this.props;

if (!owners) {
return null;
}

const ownersList = owners.map((address) => (
<InputAddress
key={ address }
value={ address }
disabled
text
/>
));

return (
<div>
{ ownersList }
</div>
);
}

renderDetails () {
const { require, dailylimit } = this.props;
const { api } = this.context;

if (!dailylimit || !dailylimit.limit) {
return null;
}

const limit = api.util.fromWei(dailylimit.limit).toFormat(3);
const spent = api.util.fromWei(dailylimit.spent).toFormat(3);
const date = moment(dailylimit.last.toNumber() * 24 * 3600 * 1000);

return (
<div>
<p>
<span>This wallet requires at least</span>
<span className={ styles.detail }>{ require.toFormat() } owners</span>
<span>to validate any action (transactions, modifications).</span>
</p>

<p>
<span className={ styles.detail }>{ spent }<span className={ styles.eth } /></span>
<span>has been spent today, out of</span>
<span className={ styles.detail }>{ limit }<span className={ styles.eth } /></span>
<span>set as the daily limit, which has been reset on</span>
<span className={ styles.detail }>{ date.format('LL') }</span>
</p>
</div>
);
}
}
17 changes: 17 additions & 0 deletions js/src/views/Wallet/Details/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright 2015, 2016 Ethcore (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 './details';
Loading

0 comments on commit 4f39eab

Please sign in to comment.