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

Commit

Permalink
Refactoring Transfer Modal (#3705)
Browse files Browse the repository at this point in the history
* Better Token Select in Transfer > Details

* Better Autocomplete

* Crete MobX store for Transfer modal

* Remove unused var

* Update Webpack Conf

* Small changes...

* Optional gas in MethodDecoding + better input

* New Contract `getAll` method // TxList Row component

* Method Decoding selections

* Rename `getAll` to `getAllLogs`
  • Loading branch information
ngotchac authored and jacogr committed Dec 2, 2016
1 parent bd2e2b6 commit c892a4f
Show file tree
Hide file tree
Showing 18 changed files with 865 additions and 642 deletions.
4 changes: 0 additions & 4 deletions js/src/abi/util/slice.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,5 @@ export function sliceData (_data) {
data = padAddress('');
}

if (data.length % 64) {
throw new Error(`Invalid data length (not mod 64) passed to sliceData, ${data}, % 64 == ${data.length % 64}`);
}

return data.match(/.{1,64}/g);
}
27 changes: 26 additions & 1 deletion js/src/api/contract/contract.js
Original file line number Diff line number Diff line change
Expand Up @@ -240,9 +240,29 @@ export default class Contract {
return this.unsubscribe(subscriptionId);
};

event.getAllLogs = (options = {}) => {
return this.getAllLogs(event);
};

return event;
}

getAllLogs (event, _options) {
// Options as first parameter
if (!_options && event && event.topics) {
return this.getAllLogs(null, event);
}

const options = this._getFilterOptions(event, _options);
return this._api.eth
.getLogs({
fromBlock: 0,
toBlock: 'latest',
...options
})
.then((logs) => this.parseEventLogs(logs));
}

_findEvent (eventName = null) {
const event = eventName
? this._events.find((evt) => evt.name === eventName)
Expand All @@ -256,7 +276,7 @@ export default class Contract {
return event;
}

_createEthFilter (event = null, _options) {
_getFilterOptions (event = null, _options = {}) {
const optionTopics = _options.topics || [];
const signature = event && event.signature || null;

Expand All @@ -271,6 +291,11 @@ export default class Contract {
topics
});

return options;
}

_createEthFilter (event = null, _options) {
const options = this._getFilterOptions(event, _options);
return this._api.eth.newFilter(options);
}

Expand Down
3 changes: 2 additions & 1 deletion js/src/api/rpc/eth/eth.js
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,8 @@ export default class Eth {

getLogs (options) {
return this._transport
.execute('eth_getLogs', inFilter(options));
.execute('eth_getLogs', inFilter(options))
.then((logs) => logs.map(outLog));
}

getLogsEx (options) {
Expand Down
4 changes: 4 additions & 0 deletions js/src/api/util/format.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ export function hex2Ascii (_hex) {
return str;
}

export function bytesToAscii (bytes) {
return bytes.map((b) => String.fromCharCode(b % 512)).join('');
}

export function asciiToHex (string) {
return '0x' + string.split('').map((s) => s.charCodeAt(0).toString(16)).join('');
}
Expand Down
153 changes: 99 additions & 54 deletions js/src/modals/Transfer/Details/details.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import BigNumber from 'bignumber.js';
import React, { Component, PropTypes } from 'react';
import { Checkbox, MenuItem } from 'material-ui';

import { isEqual } from 'lodash';

import Form, { Input, InputAddressSelect, Select } from '../../../ui/Form';

import imageUnknown from '../../../../assets/images/contracts/unknown-64x64.png';
Expand All @@ -29,11 +31,101 @@ const CHECK_STYLE = {
left: '1em'
};

export default class Details extends Component {
class TokenSelect extends Component {
static contextTypes = {
api: PropTypes.object
}

static propTypes = {
onChange: PropTypes.func.isRequired,
balance: PropTypes.object.isRequired,
images: PropTypes.object.isRequired,
tag: PropTypes.string.isRequired
};

componentWillMount () {
this.computeTokens();
}

componentWillReceiveProps (nextProps) {
const prevTokens = this.props.balance.tokens.map((t) => `${t.token.tag}_${t.value.toNumber()}`);
const nextTokens = nextProps.balance.tokens.map((t) => `${t.token.tag}_${t.value.toNumber()}`);

if (!isEqual(prevTokens, nextTokens)) {
this.computeTokens(nextProps);
}
}

computeTokens (props = this.props) {
const { api } = this.context;
const { balance, images } = this.props;

const items = balance.tokens
.filter((token, index) => !index || token.value.gt(0))
.map((balance, index) => {
const token = balance.token;
const isEth = index === 0;
let imagesrc = token.image;
if (!imagesrc) {
imagesrc =
images[token.address]
? `${api.dappsUrl}${images[token.address]}`
: imageUnknown;
}
let value = 0;

if (isEth) {
value = api.util.fromWei(balance.value).toFormat(3);
} else {
const format = balance.token.format || 1;
const decimals = format === 1 ? 0 : Math.min(3, Math.floor(format / 10));
value = new BigNumber(balance.value).div(format).toFormat(decimals);
}

const label = (
<div className={ styles.token }>
<img src={ imagesrc } />
<div className={ styles.tokenname }>
{ token.name }
</div>
<div className={ styles.tokenbalance }>
{ value }<small> { token.tag }</small>
</div>
</div>
);

return (
<MenuItem
key={ token.tag }
value={ token.tag }
label={ label }>
{ label }
</MenuItem>
);
});

this.setState({ items });
}

render () {
const { tag, onChange } = this.props;
const { items } = this.state;

return (
<Select
className={ styles.tokenSelect }
label='type of token transfer'
hint='type of token to transfer'
value={ tag }
onChange={ onChange }
>
{ items }
</Select>
);
}
}

export default class Details extends Component {
static propTypes = {
address: PropTypes.string,
balance: PropTypes.object,
Expand Down Expand Up @@ -115,62 +207,15 @@ export default class Details extends Component {
}

renderTokenSelect () {
const { api } = this.context;
const { balance, images, tag } = this.props;

const items = balance.tokens
.filter((token, index) => !index || token.value.gt(0))
.map((balance, index) => {
const token = balance.token;
const isEth = index === 0;
let imagesrc = token.image;
if (!imagesrc) {
imagesrc =
images[token.address]
? `${api.dappsUrl}${images[token.address]}`
: imageUnknown;
}
let value = 0;

if (isEth) {
value = api.util.fromWei(balance.value).toFormat(3);
} else {
const format = balance.token.format || 1;
const decimals = format === 1 ? 0 : Math.min(3, Math.floor(format / 10));
value = new BigNumber(balance.value).div(format).toFormat(decimals);
}

const label = (
<div className={ styles.token }>
<img src={ imagesrc } />
<div className={ styles.tokenname }>
{ token.name }
</div>
<div className={ styles.tokenbalance }>
{ value }<small> { token.tag }</small>
</div>
</div>
);

return (
<MenuItem
key={ token.tag }
value={ token.tag }
label={ label }>
{ label }
</MenuItem>
);
});

return (
<Select
className={ styles.tokenSelect }
label='type of token transfer'
hint='type of token to transfer'
value={ tag }
onChange={ this.onChangeToken }>
{ items }
</Select>
<TokenSelect
balance={ balance }
images={ images }
tag={ tag }
onChange={ this.onChangeToken }
/>
);
}

Expand Down
1 change: 1 addition & 0 deletions js/src/modals/Transfer/errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
// along with Parity. If not, see <http://www.gnu.org/licenses/>.

const ERRORS = {
requireSender: 'a valid sender is required for the transaction',
requireRecipient: 'a recipient network address is required for the transaction',
invalidAddress: 'the supplied address is an invalid network address',
invalidAmount: 'the supplied amount should be a valid positive number',
Expand Down
Loading

0 comments on commit c892a4f

Please sign in to comment.