diff --git a/js/src/abi/encoder/encoder.spec.js b/js/src/abi/encoder/encoder.spec.js index 32d75e7ec91..008861602d1 100644 --- a/js/src/abi/encoder/encoder.spec.js +++ b/js/src/abi/encoder/encoder.spec.js @@ -192,9 +192,9 @@ describe('abi/encoder/Encoder', () => { }); describe('bytes', () => { - const bytes1 = '1234'; - const bytes2 = '10000000000000000000000000000000000000000000000000000000000002'; - const bytes3 = '1000000000000000000000000000000000000000000000000000000000000000'; + const bytes1 = '0x1234'; + const bytes2 = '0x10000000000000000000000000000000000000000000000000000000000002'; + const bytes3 = '0x1000000000000000000000000000000000000000000000000000000000000000'; it('encodes fixed bytes', () => { const token = new Token('fixedBytes', bytes1); @@ -215,15 +215,15 @@ describe('abi/encoder/Encoder', () => { }); it('encodes bytes (two blocks)', () => { - const input = `${bytes3}${bytes3}`; + const input = `${bytes3}${bytes3.slice(-64)}`; const token = new Token('bytes', input); expect(Encoder.encode([token])).to.equal(`${padU32(0x20)}${padU32(0x40)}${padFixedBytes(input)}`); }); it('encodes two consecutive bytes', () => { - const in1 = '10000000000000000000000000000000000000000000000000000000000002'; - const in2 = '0010000000000000000000000000000000000000000000000000000000000002'; + const in1 = '0x10000000000000000000000000000000000000000000000000000000000002'; + const in2 = '0x0010000000000000000000000000000000000000000000000000000000000002'; const tokens = [new Token('bytes', in1), new Token('bytes', in2)]; expect(Encoder.encode(tokens)).to.equal(`${padU32(0x40)}${padU32(0x80)}${padU32(0x1f)}${padFixedBytes(in1)}${padU32(0x20)}${padFixedBytes(in2)}`); @@ -233,7 +233,7 @@ describe('abi/encoder/Encoder', () => { describe('string', () => { it('encodes a string', () => { const string = 'gavofyork'; - const stringEnc = padFixedBytes('6761766f66796f726b'); + const stringEnc = padFixedBytes('0x6761766f66796f726b'); const token = new Token('string', string); expect(Encoder.encode([token])).to.equal(`${padU32(0x20)}${padU32(string.length.toString(16))}${stringEnc}`); @@ -272,16 +272,16 @@ describe('abi/encoder/Encoder', () => { describe('comprehensive test', () => { it('encodes a complex sequence', () => { - const bytes = '131a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b131a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b'; + const bytes = '0x131a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b131a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b'; const tokens = [new Token('int', 5), new Token('bytes', bytes), new Token('int', 3), new Token('bytes', bytes)]; - expect(Encoder.encode(tokens)).to.equal(`${padU32(5)}${padU32(0x80)}${padU32(3)}${padU32(0xe0)}${padU32(0x40)}${bytes}${padU32(0x40)}${bytes}`); + expect(Encoder.encode(tokens)).to.equal(`${padU32(5)}${padU32(0x80)}${padU32(3)}${padU32(0xe0)}${padU32(0x40)}${bytes.substr(2)}${padU32(0x40)}${bytes.substr(2)}`); }); it('encodes a complex sequence (nested)', () => { const array = [new Token('int', 5), new Token('int', 6), new Token('int', 7)]; const tokens = [new Token('int', 1), new Token('string', 'gavofyork'), new Token('int', 2), new Token('int', 3), new Token('int', 4), new Token('array', array)]; - const stringEnc = padFixedBytes('6761766f66796f726b'); + const stringEnc = padFixedBytes('0x6761766f66796f726b'); expect(Encoder.encode(tokens)).to.equal(`${padU32(1)}${padU32(0xc0)}${padU32(2)}${padU32(3)}${padU32(4)}${padU32(0x100)}${padU32(9)}${stringEnc}${padU32(3)}${padU32(5)}${padU32(6)}${padU32(7)}`); }); diff --git a/js/src/abi/util/pad.js b/js/src/abi/util/pad.js index b14991ac2fb..9f2a45b86b2 100644 --- a/js/src/abi/util/pad.js +++ b/js/src/abi/util/pad.js @@ -42,33 +42,34 @@ export function padU32 (input) { return `${ZERO_64}${bn.toString(16)}`.slice(-64); } -export function padBytes (input) { - const length = isArray(input) ? input.length : (`${input}`.length / 2); - - return `${padU32(length)}${padFixedBytes(input)}`; -} - -export function padFixedBytes (input) { - let sinput; - +function stringToBytes (input) { if (isArray(input)) { - sinput = input.map((code) => code.toString(16)).join(''); + return input; } else if (input.substr(0, 2) === '0x') { - sinput = `${input.substr(2)}`; + return input.substr(2).match(/.{1,2}/g).map((value) => parseInt(value, 16)); } else { - sinput = `${input}`; + return input.split('').map((char) => char.charCodeAt(0)); } +} + +export function padBytes (_input) { + const input = stringToBytes(_input); + + return `${padU32(input.length)}${padFixedBytes(input)}`; +} +export function padFixedBytes (_input) { + const input = stringToBytes(_input); + const sinput = input.map((code) => `0${code.toString(16)}`.slice(-2)).join(''); const max = Math.floor((sinput.length + 63) / 64) * 64; return `${sinput}${ZERO_64}`.substr(0, max); } export function padString (input) { - const encoded = utf8.encode(input) + const array = utf8.encode(input) .split('') - .map((char) => char.charCodeAt(0).toString(16)) - .join(''); + .map((char) => char.charCodeAt(0)); - return padBytes(encoded); + return padBytes(array); } diff --git a/js/src/abi/util/pad.spec.js b/js/src/abi/util/pad.spec.js index 2ce9e65bf76..96c73368248 100644 --- a/js/src/abi/util/pad.spec.js +++ b/js/src/abi/util/pad.spec.js @@ -74,7 +74,7 @@ describe('abi/util/pad', () => { describe('padFixedBytes', () => { it('right pads length < 64 bytes to 64 bytes (string)', () => { - expect(padFixedBytes(SHORT15)).to.equal(LONG15); + expect(padFixedBytes(`0x${SHORT15}`)).to.equal(LONG15); }); it('right pads length < 64 bytes to 64 bytes (array)', () => { @@ -82,7 +82,7 @@ describe('abi/util/pad', () => { }); it('right pads length > 64 bytes (64 byte multiples)', () => { - expect(padFixedBytes(`${LONG15}${SHORT15}`)).to.equal(`${LONG15}${LONG15}`); + expect(padFixedBytes(`0x${LONG15}${SHORT15}`)).to.equal(`${LONG15}${LONG15}`); }); it('strips leading 0x when passed in', () => { @@ -92,7 +92,7 @@ describe('abi/util/pad', () => { describe('padBytes', () => { it('right pads length < 64, adding the length (string)', () => { - const result = padBytes(SHORT15); + const result = padBytes(`0x${SHORT15}`); expect(result.length).to.equal(128); expect(result).to.equal(`${padU32(8)}${LONG15}`); @@ -106,7 +106,7 @@ describe('abi/util/pad', () => { }); it('right pads length > 64, adding the length', () => { - const result = padBytes(`${LONG15}${SHORT15}`); + const result = padBytes(`0x${LONG15}${SHORT15}`); expect(result.length).to.equal(192); expect(result).to.equal(`${padU32(0x28)}${LONG15}${LONG15}`); @@ -118,7 +118,7 @@ describe('abi/util/pad', () => { const result = padString('gavofyork'); expect(result.length).to.equal(128); - expect(result).to.equal(padBytes('6761766f66796f726b')); + expect(result).to.equal(padBytes('0x6761766f66796f726b')); }); }); }); diff --git a/js/src/dapps/githubhint/Application/application.js b/js/src/dapps/githubhint/Application/application.js index 37b7a817654..ea7e760c588 100644 --- a/js/src/dapps/githubhint/Application/application.js +++ b/js/src/dapps/githubhint/Application/application.js @@ -244,6 +244,8 @@ export default class Application extends Component { instance.entries .call({}, [contentHash]) .then(([accountSlashRepo, commit, owner]) => { + console.log('lookupHash', accountSlashRepo, api.util.bytesToHex(commit), owner); + if (owner !== ZERO_ADDRESS) { this.setState({ contentHashError: contentHash, contentHash: null }); } else { diff --git a/js/src/dapps/tokenreg/Tokens/Token/add-meta.js b/js/src/dapps/tokenreg/Tokens/Token/add-meta.js index bb4c5b49796..09e65954d25 100644 --- a/js/src/dapps/tokenreg/Tokens/Token/add-meta.js +++ b/js/src/dapps/tokenreg/Tokens/Token/add-meta.js @@ -19,6 +19,7 @@ import { Dialog, RaisedButton, FlatButton, SelectField, MenuItem } from 'materia import AddIcon from 'material-ui/svg-icons/content/add'; import InputText from '../../Inputs/Text'; +import { ADDRESS_TYPE } from '../../Inputs/validation'; import styles from './token.css'; @@ -133,7 +134,7 @@ export default class AddMeta extends Component { diff --git a/js/src/dapps/tokenreg/Tokens/Token/token.js b/js/src/dapps/tokenreg/Tokens/Token/token.js index 2669920edc7..b940a8360fb 100644 --- a/js/src/dapps/tokenreg/Tokens/Token/token.js +++ b/js/src/dapps/tokenreg/Tokens/Token/token.js @@ -55,8 +55,7 @@ export default class Token extends Component { metaMined: PropTypes.bool, isLoading: PropTypes.bool, isPending: PropTypes.bool, - isOwner: PropTypes.bool, - isTokenOwner: PropTypes.bool, + isTokenOwner: PropTypes.bool.isRequired, fullWidth: PropTypes.bool }; @@ -197,7 +196,9 @@ export default class Token extends Component { renderIsPending () { const { isPending } = this.props; - if (!isPending) return null; + if (!isPending) { + return null; + } return (
@@ -205,6 +206,10 @@ export default class Token extends Component { } renderAddMeta () { + if (!this.props.isTokenOwner) { + return null; + } + return ( ({ @@ -164,17 +164,15 @@ export const queryTokenMeta = (index, query) => (dispatch, getState) => { const state = getState(); const contractInstance = state.status.contract.instance; - const key = sha3(query); - const startDate = Date.now(); dispatch(setTokenMetaLoading(index, true)); contractInstance .meta - .call({}, [ index, key ]) + .call({}, [ index, query ]) .then((value) => { const meta = { - key, query, + query, value: value.find(v => v !== 0) ? bytesToHex(value) : null }; @@ -195,35 +193,22 @@ export const addTokenMeta = (index, key, value) => (dispatch, getState) => { const state = getState(); const contractInstance = state.status.contract.instance; - const token = state.tokens.tokens.find(t => t.index === index); - const keyHash = sha3(key); - const options = { - from: token.owner - }; - - let values; - - if (key === 'IMG') { - const valueHash = sha3(value); - dispatch(addGithubhintURL(token.owner, valueHash, value)); - values = [ index, keyHash, valueHash ]; - } else { - values = [ index, keyHash, value ]; - } + const options = { from: token.owner }; + const values = [ index, key, value ]; contractInstance .setMeta .estimateGas(options, values) .then((gasEstimate) => { options.gas = gasEstimate.mul(1.2).toFixed(0); - console.log(`transfer: gas estimated as ${gasEstimate.toFixed(0)} setting to ${options.gas}`); + console.log(`addTokenMeta: gas estimated as ${gasEstimate.toFixed(0)} setting to ${options.gas}`); return contractInstance.setMeta.postTransaction(options, values); }) .catch((e) => { - console.error(`addTokenMeta #${index} error`, e); + console.error(`addTokenMeta: #${index} error`, e); }); }; diff --git a/js/src/dapps/tokenreg/Tokens/container.js b/js/src/dapps/tokenreg/Tokens/container.js index 5e9af4b4ae4..b6171c2cc1d 100644 --- a/js/src/dapps/tokenreg/Tokens/container.js +++ b/js/src/dapps/tokenreg/Tokens/container.js @@ -27,7 +27,8 @@ class TokensContainer extends Component { isLoading: PropTypes.bool, tokens: PropTypes.array, tokenCount: PropTypes.number, - onLoadTokens: PropTypes.func + onLoadTokens: PropTypes.func, + accounts: PropTypes.array }; componentDidMount () { @@ -35,17 +36,22 @@ class TokensContainer extends Component { } render () { - return (); + console.log(this.props); + return ( + + ); } } const mapStateToProps = (state) => { + const { list } = state.accounts; const { isLoading, tokens, tokenCount } = state.tokens; + const { isOwner } = state.status.contract; - return { isLoading, tokens, tokenCount, isOwner }; + return { isLoading, tokens, tokenCount, isOwner, accounts: list }; }; const mapDispatchToProps = (dispatch) => { diff --git a/js/src/dapps/tokenreg/Tokens/tokens.js b/js/src/dapps/tokenreg/Tokens/tokens.js index a45213d90c8..57c2a2a9138 100644 --- a/js/src/dapps/tokenreg/Tokens/tokens.js +++ b/js/src/dapps/tokenreg/Tokens/tokens.js @@ -28,12 +28,12 @@ export default class Tokens extends Component { handleMetaLookup: PropTypes.func.isRequired, isOwner: PropTypes.bool.isRequired, isLoading: PropTypes.bool.isRequired, - tokens: PropTypes.array + tokens: PropTypes.array, + accounts: PropTypes.array }; render () { const { isLoading, tokens } = this.props; - const loading = isLoading ? () : null; return ( @@ -45,8 +45,14 @@ export default class Tokens extends Component { } renderTokens (tokens) { + const { accounts } = this.props; + return tokens.map((token, index) => { - if (!token || !token.tla) return null; + if (!token || !token.tla) { + return null; + } + + const isTokenOwner = !!accounts.find((account) => account.address === token.owner); return ( + isTokenOwner={ isTokenOwner } /> ); }); } diff --git a/js/src/dapps/tokenreg/constants.js b/js/src/dapps/tokenreg/constants.js index 64a03e8a3c0..e9e7bebcab8 100644 --- a/js/src/dapps/tokenreg/constants.js +++ b/js/src/dapps/tokenreg/constants.js @@ -14,13 +14,13 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -import { URL_TYPE, ADDRESS_TYPE } from './Inputs/validation'; +import { HEX_TYPE, ADDRESS_TYPE } from './Inputs/validation'; export const metaDataKeys = [ { label: 'Image', value: 'IMG', - validation: URL_TYPE + validation: HEX_TYPE }, { label: 'Address', diff --git a/js/src/images/contracts/ethereum-56.png b/js/src/images/contracts/ethereum-black-64x64.png similarity index 50% rename from js/src/images/contracts/ethereum-56.png rename to js/src/images/contracts/ethereum-black-64x64.png index a88a419a4ba..8e80e4ff134 100644 Binary files a/js/src/images/contracts/ethereum-56.png and b/js/src/images/contracts/ethereum-black-64x64.png differ diff --git a/js/src/images/contracts/gavcoin-56.png b/js/src/images/contracts/gavcoin-56.png deleted file mode 100644 index 7970f070526..00000000000 Binary files a/js/src/images/contracts/gavcoin-56.png and /dev/null differ diff --git a/js/src/images/contracts/gavcoin-64x64.png b/js/src/images/contracts/gavcoin-64x64.png new file mode 100644 index 00000000000..13b25a3411f Binary files /dev/null and b/js/src/images/contracts/gavcoin-64x64.png differ diff --git a/js/src/images/contracts/unknown-56.png b/js/src/images/contracts/unknown-56.png deleted file mode 100644 index 2a4777e247f..00000000000 Binary files a/js/src/images/contracts/unknown-56.png and /dev/null differ diff --git a/js/src/images/contracts/unknown-64x64.png b/js/src/images/contracts/unknown-64x64.png new file mode 100644 index 00000000000..c2b39a80a37 Binary files /dev/null and b/js/src/images/contracts/unknown-64x64.png differ diff --git a/js/src/modals/Transfer/Details/details.js b/js/src/modals/Transfer/Details/details.js index f74620ba46c..456fdf9cb4f 100644 --- a/js/src/modals/Transfer/Details/details.js +++ b/js/src/modals/Transfer/Details/details.js @@ -20,6 +20,7 @@ import { Checkbox, MenuItem } from 'material-ui'; import Form, { Input, InputAddressSelect, Select } from '../../../ui/Form'; +import imageUnknown from '../../../images/contracts/unknown-64x64.png'; import styles from '../transfer.css'; const CHECK_STYLE = { @@ -38,6 +39,7 @@ export default class Details extends Component { balance: PropTypes.object, all: PropTypes.bool, extras: PropTypes.bool, + images: PropTypes.object.isRequired, recipient: PropTypes.string, recipientError: PropTypes.string, tag: PropTypes.string, @@ -114,13 +116,14 @@ export default class Details extends Component { renderTokenSelect () { const { api } = this.context; - const { balance, tag } = this.props; + const { balance, images, tag } = this.props; const items = balance.tokens .filter((token) => token.value.gt(0)) .map((balance, idx) => { const token = balance.token; const isEth = idx === 0; + const imagesrc = token.image || images[token.address] || imageUnknown; let value = 0; if (isEth) { @@ -131,7 +134,7 @@ export default class Details extends Component { const label = (
- +
{ token.name }
diff --git a/js/src/modals/Transfer/transfer.js b/js/src/modals/Transfer/transfer.js index 01e77d93762..78dc6f77080 100644 --- a/js/src/modals/Transfer/transfer.js +++ b/js/src/modals/Transfer/transfer.js @@ -49,6 +49,7 @@ export default class Transfer extends Component { account: PropTypes.object, balance: PropTypes.object, balances: PropTypes.object, + images: PropTypes.object.isRequired, onClose: PropTypes.func } @@ -147,7 +148,7 @@ export default class Transfer extends Component { } renderDetailsPage () { - const { account, balance } = this.props; + const { account, balance, images } = this.props; return (
. import { newError } from '../ui/Errors/actions'; +import { setAddressImage } from './providers/imagesActions'; import { clearStatusLogs, toggleStatusLogs } from './providers/statusActions'; import { toggleView } from '../views/Settings'; export { newError, clearStatusLogs, + setAddressImage, toggleStatusLogs, toggleView }; diff --git a/js/src/redux/providers/balances.js b/js/src/redux/providers/balances.js index d262a3f19c7..151cb014dd4 100644 --- a/js/src/redux/providers/balances.js +++ b/js/src/redux/providers/balances.js @@ -15,23 +15,16 @@ // along with Parity. If not, see . import { getBalances, getTokens } from './balancesActions'; +import { setAddressImage } from './imagesActions'; import * as abis from '../../contracts/abi'; -import imagesEthereum from '../../images/contracts/ethereum-56.png'; -import imagesGavcoin from '../../images/contracts/gavcoin-56.png'; -import imagesUnknown from '../../images/contracts/unknown-56.png'; - -// TODO: Images should not be imported like this, should be via the content from GitHubHint contract (here until it is ready) -const images = { - ethereum: imagesEthereum, - gavcoin: imagesGavcoin -}; +import imagesEthereum from '../../images/contracts/ethereum-black-64x64.png'; const ETH = { name: 'Ethereum', tag: 'ΞTH', - image: images.ethereum + image: imagesEthereum }; export default class Balances { @@ -89,18 +82,25 @@ export default class Balances { return tokenreg.instance.tokenCount .call() .then((numTokens) => { - const promises = []; + const promisesTokens = []; + const promisesImages = []; + + while (promisesTokens.length < numTokens.toNumber()) { + const index = promisesTokens.length; - while (promises.length < numTokens.toNumber()) { - promises.push(tokenreg.instance.token.call({}, [promises.length])); + promisesTokens.push(tokenreg.instance.token.call({}, [index])); + promisesImages.push(tokenreg.instance.meta.call({}, [index, 'IMG'])); } - return Promise.all(promises); + return Promise.all([ + Promise.all(promisesTokens), + Promise.all(promisesImages) + ]); }); }) - .then((_tokens) => { + .then(([_tokens, images]) => { const tokens = {}; - this._tokens = _tokens.map((_token) => { + this._tokens = _tokens.map((_token, index) => { const [address, tag, format, name] = _token; const token = { @@ -108,10 +108,10 @@ export default class Balances { name, tag, format: format.toString(), - image: images[name.toLowerCase()] || imagesUnknown, contract: this._api.newContract(abis.eip20, address) }; tokens[address] = token; + this._store.dispatch(setAddressImage(address, images[index])); return token; }); diff --git a/js/src/redux/providers/imagesActions.js b/js/src/redux/providers/imagesActions.js new file mode 100644 index 00000000000..ce9221a3b97 --- /dev/null +++ b/js/src/redux/providers/imagesActions.js @@ -0,0 +1,23 @@ +// 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 . + +export function setAddressImage (address, hashArray) { + return { + type: 'setAddressImage', + address, + hashArray + }; +} diff --git a/js/src/redux/providers/imagesReducer.js b/js/src/redux/providers/imagesReducer.js new file mode 100644 index 00000000000..af4be49b5f5 --- /dev/null +++ b/js/src/redux/providers/imagesReducer.js @@ -0,0 +1,35 @@ +// 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 . + +import { handleActions } from 'redux-actions'; +import { bytesToHex } from '../../api/util/format'; + +const ZERO = '0x0000000000000000000000000000000000000000000000000000000000000000'; + +const initialState = { + images: {} +}; + +export default handleActions({ + setAddressImage (state, action) { + const { address, hashArray } = action; + const hash = hashArray ? bytesToHex(hashArray) : ZERO; + + return Object.assign({}, state, { + [address]: hash === ZERO ? null : `/api/content/${hash.substr(2)}` + }); + } +}, initialState); diff --git a/js/src/redux/providers/index.js b/js/src/redux/providers/index.js index a6f52fdaf3d..a29e9c32d08 100644 --- a/js/src/redux/providers/index.js +++ b/js/src/redux/providers/index.js @@ -19,5 +19,6 @@ export Personal from './personal'; export Status from './status'; export balancesReducer from './balancesReducer'; +export imagesReducer from './imagesReducer'; export personalReducer from './personalReducer'; export statusReducer from './statusReducer'; diff --git a/js/src/redux/reducers.js b/js/src/redux/reducers.js index 42cbc6ef4f9..e98e17acc2b 100644 --- a/js/src/redux/reducers.js +++ b/js/src/redux/reducers.js @@ -17,7 +17,7 @@ import { combineReducers } from 'redux'; import { routerReducer } from 'react-router-redux'; -import { balancesReducer, personalReducer, statusReducer as nodeStatusReducer } from './providers'; +import { balancesReducer, imagesReducer, personalReducer, statusReducer as nodeStatusReducer } from './providers'; import { errorReducer } from '../ui/Errors'; import { settingsReducer } from '../views/Settings'; @@ -36,6 +36,7 @@ export default function () { settings: settingsReducer, balances: balancesReducer, + images: imagesReducer, nodeStatus: nodeStatusReducer, personal: personalReducer, diff --git a/js/src/ui/Balance/balance.js b/js/src/ui/Balance/balance.js index 6b94b60b302..9c18849cb1e 100644 --- a/js/src/ui/Balance/balance.js +++ b/js/src/ui/Balance/balance.js @@ -16,21 +16,25 @@ import BigNumber from 'bignumber.js'; import React, { Component, PropTypes } from 'react'; +import { connect } from 'react-redux'; +import { bindActionCreators } from 'redux'; +import unknownImage from '../../images/contracts/unknown-64x64.png'; import styles from './balance.css'; -export default class Balance extends Component { +class Balance extends Component { static contextTypes = { api: PropTypes.object } static propTypes = { - balance: PropTypes.object + balance: PropTypes.object, + images: PropTypes.object.isRequired } render () { const { api } = this.context; - const { balance } = this.props; + const { balance, images } = this.props; if (!balance) { return null; @@ -43,13 +47,14 @@ export default class Balance extends Component { const value = token.format ? new BigNumber(balance.value).div(new BigNumber(token.format)).toFormat(3) : api.util.fromWei(balance.value).toFormat(3); + const imagesrc = token.image || images[token.address] || unknownImage; return (
{
{ value } { token.tag }
@@ -71,3 +76,18 @@ export default class Balance extends Component { ); } } + +function mapStateToProps (state) { + const { images } = state; + + return { images }; +} + +function mapDispatchToProps (dispatch) { + return bindActionCreators({}, dispatch); +} + +export default connect( + mapStateToProps, + mapDispatchToProps +)(Balance); diff --git a/js/src/ui/Form/AddressSelect/addressSelect.js b/js/src/ui/Form/AddressSelect/addressSelect.js index 6cd0996ff75..c7500846cbd 100644 --- a/js/src/ui/Form/AddressSelect/addressSelect.js +++ b/js/src/ui/Form/AddressSelect/addressSelect.js @@ -63,14 +63,11 @@ export default class AddressSelect extends Component { } renderSelectEntry = (entry) => { - const { tokens } = this.props; - const item = (
diff --git a/js/src/ui/Form/InputAddress/inputAddress.js b/js/src/ui/Form/InputAddress/inputAddress.js index dde7c3a7cc0..5bc0f1a4d68 100644 --- a/js/src/ui/Form/InputAddress/inputAddress.js +++ b/js/src/ui/Form/InputAddress/inputAddress.js @@ -56,7 +56,7 @@ export default class InputAddress extends Component { } renderIcon () { - const { value, tokens } = this.props; + const { value } = this.props; if (!value || !value.length) { return null; @@ -66,7 +66,6 @@ export default class InputAddress extends Component {
); diff --git a/js/src/ui/IdentityIcon/identityIcon.js b/js/src/ui/IdentityIcon/identityIcon.js index 292e99b9a8d..928a340a737 100644 --- a/js/src/ui/IdentityIcon/identityIcon.js +++ b/js/src/ui/IdentityIcon/identityIcon.js @@ -15,11 +15,13 @@ // along with Parity. If not, see . import React, { Component, PropTypes } from 'react'; +import { connect } from 'react-redux'; +import { bindActionCreators } from 'redux'; import ContractIcon from 'material-ui/svg-icons/action/code'; import styles from './identityIcon.css'; -export default class IdentityIcon extends Component { +class IdentityIcon extends Component { static contextTypes = { api: PropTypes.object.isRequired } @@ -32,7 +34,7 @@ export default class IdentityIcon extends Component { padded: PropTypes.bool, inline: PropTypes.bool, tiny: PropTypes.bool, - tokens: PropTypes.object + images: PropTypes.object.isRequired } state = { @@ -40,31 +42,27 @@ export default class IdentityIcon extends Component { } componentDidMount () { - const { address } = this.props; - - this.updateIcon(address); + this.updateIcon(this.props.address, this.props.images); } componentWillReceiveProps (newProps) { - const { address, tokens } = this.props; + const sameAddress = newProps.address === this.props.address; + const sameImages = Object.keys(newProps.images).length === Object.keys(this.props.images).length; - if (newProps.address === address && newProps.tokens === tokens) { + if (sameAddress && sameImages) { return; } - this.updateIcon(newProps.address); + this.updateIcon(newProps.address, newProps.images); } - updateIcon (_address) { + updateIcon (_address, images) { const { api } = this.context; - const { button, tokens, inline, tiny } = this.props; - const token = (tokens || {})[_address]; - - if (token && token.image) { - this.setState({ - iconsrc: token.image - }); + const { button, inline, tiny } = this.props; + const iconsrc = images[_address]; + if (iconsrc) { + this.setState({ iconsrc }); return; } @@ -121,3 +119,18 @@ export default class IdentityIcon extends Component { ); } } + +function mapStateToProps (state) { + const { images } = state; + + return { images }; +} + +function mapDispatchToProps (dispatch) { + return bindActionCreators({}, dispatch); +} + +export default connect( + mapStateToProps, + mapDispatchToProps +)(IdentityIcon); diff --git a/js/src/ui/MethodDecoding/methodDecoding.js b/js/src/ui/MethodDecoding/methodDecoding.js index 58aeb68f857..fc9254c42f9 100644 --- a/js/src/ui/MethodDecoding/methodDecoding.js +++ b/js/src/ui/MethodDecoding/methodDecoding.js @@ -270,13 +270,12 @@ export default class Method extends Component { } renderAddressName (address, withName = true) { - const { tokens } = this.props; const account = this.getAccount(address); const name = account ? account.name.toUpperCase() : null; return ( - + { withName ? (name || address) : address } ); diff --git a/js/src/views/Account/Transactions/Transaction/transaction.js b/js/src/views/Account/Transactions/Transaction/transaction.js index 9fcd5744ebb..af10086a2ab 100644 --- a/js/src/views/Account/Transactions/Transaction/transaction.js +++ b/js/src/views/Account/Transactions/Transaction/transaction.js @@ -132,7 +132,6 @@ export default class Transaction extends Component {
diff --git a/js/src/views/Account/account.js b/js/src/views/Account/account.js index bbba53479a1..0470653643a 100644 --- a/js/src/views/Account/account.js +++ b/js/src/views/Account/account.js @@ -35,6 +35,7 @@ class Account extends Component { params: PropTypes.object, accounts: PropTypes.object, balances: PropTypes.object, + images: PropTypes.object.isRequired, isTest: PropTypes.bool } @@ -141,7 +142,7 @@ class Account extends Component { } const { address } = this.props.params; - const { accounts, balances } = this.props; + const { accounts, balances, images } = this.props; const account = accounts[address]; const balance = balances[address]; @@ -150,6 +151,7 @@ class Account extends Component { account={ account } balance={ balance } balances={ balances } + images={ images } onClose={ this.onTransferClose } /> ); } @@ -184,12 +186,14 @@ class Account extends Component { function mapStateToProps (state) { const { accounts } = state.personal; const { balances } = state.balances; + const { images } = state; const { isTest } = state.nodeStatus; return { isTest, accounts, - balances + balances, + images }; } diff --git a/js/src/views/Dapps/Summary/summary.js b/js/src/views/Dapps/Summary/summary.js index 43377be5fd7..3182d19d700 100644 --- a/js/src/views/Dapps/Summary/summary.js +++ b/js/src/views/Dapps/Summary/summary.js @@ -32,7 +32,7 @@ export default class Summary extends Component { } render () { - const { app, tokens } = this.props; + const { app } = this.props; if (!app) { return null; @@ -43,8 +43,7 @@ export default class Summary extends Component { return ( + address={ app.address } /> { app.name }</Link> } byline={ app.description } /> diff --git a/js/src/views/Signer/components/Account/Account.js b/js/src/views/Signer/components/Account/Account.js index 248a9d497ae..618292fd138 100644 --- a/js/src/views/Signer/components/Account/Account.js +++ b/js/src/views/Signer/components/Account/Account.js @@ -56,15 +56,14 @@ class Account extends Component { } render () { - const { address, chain, className, tokens } = this.props; + const { address, chain, className } = this.props; return ( <div className={ `${styles.acc} ${className}` } title={ this.renderTitle() }> <AccountLink address={ address } chain={ chain }> <IdentityIcon center - address={ address } - tokens={ tokens } /> + address={ address } /> </AccountLink> { this.renderName() } { this.renderBalance() } diff --git a/js/src/views/Signer/containers/LoadingPage/LoadingPage.css b/js/src/views/Signer/containers/--remove-LoadingPage/LoadingPage.css similarity index 100% rename from js/src/views/Signer/containers/LoadingPage/LoadingPage.css rename to js/src/views/Signer/containers/--remove-LoadingPage/LoadingPage.css diff --git a/js/src/views/Signer/containers/LoadingPage/LoadingPage.js b/js/src/views/Signer/containers/--remove-LoadingPage/LoadingPage.js similarity index 100% rename from js/src/views/Signer/containers/LoadingPage/LoadingPage.js rename to js/src/views/Signer/containers/--remove-LoadingPage/LoadingPage.js diff --git a/js/src/views/Signer/containers/LoadingPage/index.js b/js/src/views/Signer/containers/--remove-LoadingPage/index.js similarity index 100% rename from js/src/views/Signer/containers/LoadingPage/index.js rename to js/src/views/Signer/containers/--remove-LoadingPage/index.js diff --git a/js/src/views/Signer/containers/OfflinePage/OfflinePage.js b/js/src/views/Signer/containers/--remove-OfflinePage/OfflinePage.js similarity index 100% rename from js/src/views/Signer/containers/OfflinePage/OfflinePage.js rename to js/src/views/Signer/containers/--remove-OfflinePage/OfflinePage.js diff --git a/js/src/views/Signer/containers/OfflinePage/index.js b/js/src/views/Signer/containers/--remove-OfflinePage/index.js similarity index 100% rename from js/src/views/Signer/containers/OfflinePage/index.js rename to js/src/views/Signer/containers/--remove-OfflinePage/index.js diff --git a/js/src/views/Signer/containers/UnAuthorizedPage/UnAuthorizedPage.css b/js/src/views/Signer/containers/--remove-UnAuthorizedPage/UnAuthorizedPage.css similarity index 100% rename from js/src/views/Signer/containers/UnAuthorizedPage/UnAuthorizedPage.css rename to js/src/views/Signer/containers/--remove-UnAuthorizedPage/UnAuthorizedPage.css diff --git a/js/src/views/Signer/containers/UnAuthorizedPage/UnAuthorizedPage.js b/js/src/views/Signer/containers/--remove-UnAuthorizedPage/UnAuthorizedPage.js similarity index 100% rename from js/src/views/Signer/containers/UnAuthorizedPage/UnAuthorizedPage.js rename to js/src/views/Signer/containers/--remove-UnAuthorizedPage/UnAuthorizedPage.js diff --git a/js/src/views/Signer/containers/UnAuthorizedPage/index.js b/js/src/views/Signer/containers/--remove-UnAuthorizedPage/index.js similarity index 100% rename from js/src/views/Signer/containers/UnAuthorizedPage/index.js rename to js/src/views/Signer/containers/--remove-UnAuthorizedPage/index.js diff --git a/js/src/views/Signer/signer.js b/js/src/views/Signer/signer.js index 88c5d360bcd..b9aace59530 100644 --- a/js/src/views/Signer/signer.js +++ b/js/src/views/Signer/signer.js @@ -14,59 +14,23 @@ // 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 { connect } from 'react-redux'; +import React, { Component } from 'react'; import { Actionbar, Page } from '../../ui'; - -import LoadingPage from './containers/LoadingPage'; import RequestsPage from './containers/RequestsPage'; import styles from './signer.css'; -export class Signer extends Component { - static propTypes = { - signer: PropTypes.shape({ - isLoading: PropTypes.bool.isRequired - }).isRequired - }; - +export default class Signer extends Component { render () { return ( <div className={ styles.signer }> <Actionbar title='Trusted Signer' /> <Page> - { this.renderPage() } + <RequestsPage /> </Page> </div> ); } - - renderPage () { - const { isLoading } = this.props.signer; - - if (isLoading) { - return ( - <LoadingPage /> - ); - } - - return ( - <RequestsPage /> - ); - } -} - -function mapStateToProps (state) { - return state; } - -function mapDispatchToProps (dispatch) { - return {}; -} - -export default connect( - mapStateToProps, - mapDispatchToProps -)(Signer);