Skip to content
This repository has been archived by the owner on Apr 15, 2019. It is now read-only.

Add support for optional data field - Closes #595 #1069

Merged
merged 5 commits into from
May 17, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions i18n/locales/en/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@
"Lisk Website": "Lisk Website",
"Login": "Login",
"Mainnet": "Mainnet",
"Maximum length of 64 characters is exceeded.": "Maximum length of 64 characters is exceeded.",
"Maximum of {{n}} votes exceeded.": "Maximum of {{n}} votes exceeded.",
"Maximum of {{n}} votes in one transaction exceeded.": "Maximum of {{n}} votes in one transaction exceeded.",
"Message": "Message",
Expand Down Expand Up @@ -121,6 +122,7 @@
"Recipient Address": "Recipient Address",
"Recipient PublicKey": "Recipient PublicKey",
"Redo": "Redo",
"Reference": "Reference",
"Register": "Register",
"Register Second Passphrase": "Register Second Passphrase",
"Register as delegate": "Register as delegate",
Expand Down Expand Up @@ -188,6 +190,7 @@
"Uptime": "Uptime",
"Upvotes:": "Upvotes:",
"Username": "Username",
"Using a reference will cost an additional fee of 0.1 LSK. Your total transaction fee will be 0.2 LSK if you choose to use a reference.": "Using a reference will cost an additional fee of 0.1 LSK. Your total transaction fee will be 0.2 LSK if you choose to use a reference.",
"Verify message": "Verify message",
"Version": "Version",
"View": "View",
Expand Down
9 changes: 5 additions & 4 deletions src/actions/account.js
Original file line number Diff line number Diff line change
Expand Up @@ -106,14 +106,15 @@ export const delegateRegistered = ({
/**
*
*/
export const sent = ({ activePeer, account, recipientId, amount, passphrase, secondPassphrase }) =>
export const sent = ({ activePeer, account, recipientId,
amount, passphrase, secondPassphrase, data }) =>
(dispatch) => {
loadingStarted('sent');
send(activePeer, recipientId, toRawLsk(amount), passphrase, secondPassphrase)
.then((data) => {
send(activePeer, recipientId, toRawLsk(amount), passphrase, secondPassphrase, data)
.then((res) => {
loadingFinished('sent');
dispatch(transactionAdded({
id: data.id,
id: res.id,
senderPublicKey: account.publicKey,
senderId: account.address,
recipientId,
Expand Down
7 changes: 7 additions & 0 deletions src/components/send/send.css
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,10 @@
line-height: 14px;
color: grey;
}

.notice {
float: left;
margin-right: 10px;
display: inline-block;
margin-top: -3px;
}
29 changes: 25 additions & 4 deletions src/components/send/send.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from 'react';
import Input from 'react-toolbox/lib/input';
import { IconMenu, MenuItem } from 'react-toolbox/lib/menu';
import FontIcon from 'react-toolbox/lib/font_icon';
import { fromRawLsk, toRawLsk } from '../../utils/lsk';
import AuthInputs from '../authInputs';
import ActionBar from '../actionBar';
Expand All @@ -18,9 +19,12 @@ class Send extends React.Component {
amount: {
value: '',
},
reference: {
value: '',
},
fee: 0.1,
...authStatePrefill(),
};
this.fee = 0.1;
this.inputValidationRegexps = {
recipient: /^\d{1,21}[L|l]$/,
amount: /^\d+(\.\d{1,8})?$/,
Expand All @@ -41,7 +45,10 @@ class Send extends React.Component {
}

handleChange(name, value, error) {
const fee = (name === 'reference' && value.length > 0) ?
0.2 : 0.1;
this.setState({
fee,
[name]: {
value,
error: typeof error === 'string' ? error : this.validateInput(name, value),
Expand All @@ -50,14 +57,16 @@ class Send extends React.Component {
}

validateInput(name, value) {
if (!value) {
if (!value && name !== 'reference') {
return this.props.t('Required');
} else if (!value.match(this.inputValidationRegexps[name])) {
return this.props.t('Invalid');
} else if (name === 'amount' && value > parseFloat(this.getMaxAmount())) {
return this.props.t('Insufficient funds');
} else if (name === 'amount' && value === '0') {
return this.props.t('Zero not allowed');
} else if (name === 'reference' && value.length > 64) {
return this.props.t('Maximum length of 64 characters is exceeded.');
}
return undefined;
}
Expand All @@ -71,12 +80,13 @@ class Send extends React.Component {
amount: this.state.amount.value,
passphrase: this.state.passphrase.value,
secondPassphrase: this.state.secondPassphrase.value,
data: this.state.reference.value,
});
this.setState({ executed: true });
}

getMaxAmount() {
return fromRawLsk(Math.max(0, this.props.account.balance - toRawLsk(this.fee)));
return fromRawLsk(Math.max(0, this.props.account.balance - toRawLsk(this.state.fee)));
}

setMaxAmount() {
Expand All @@ -98,11 +108,22 @@ class Send extends React.Component {
error={this.state.amount.error}
value={this.state.amount.value}
onChange={this.handleChange.bind(this, 'amount')} />
<Input
label={this.props.t('Reference')}
required={false}
className='reference'
error={this.state.reference.error}
value={this.state.reference.value}
onChange={this.handleChange.bind(this, 'reference')} />
{this.state.reference.value.length > 0 ? <div>
<FontIcon className={styles.notice} value='error_outline' />
{this.props.t('Using a reference will cost an additional fee of 0.1 LSK. Your total transaction fee will be 0.2 LSK if you choose to use a reference.')}
</div> : null }
<AuthInputs
passphrase={this.state.passphrase}
secondPassphrase={this.state.secondPassphrase}
onChange={this.handleChange.bind(this)} />
<div className={styles.fee}> {this.props.t('Fee: {{fee}} LSK', { fee: this.fee })} </div>
<div className={styles.fee}> {this.props.t('Fee: {{fee}} LSK', { fee: this.state.fee })} </div>
<IconMenu icon='more_vert' position='topRight' menuRipple className={`${styles.sendAllMenu} transaction-amount`} >
<MenuItem onClick={this.setMaxAmount.bind(this)}
caption={this.props.t('Set maximum amount')}
Expand Down
10 changes: 9 additions & 1 deletion src/components/send/send.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ describe('Send', () => {
});

it('renders two Input components', () => {
expect(wrapper.find('Input')).to.have.length(2);
expect(wrapper.find('Input')).to.have.length(3);
});

it('renders two Button components', () => {
Expand All @@ -67,6 +67,13 @@ describe('Send', () => {
expect(wrapper.find('Input.amount').text()).to.contain('Insufficient funds');
});


it('show filling reference field increase transaction fee to 0.2 LSK', () => {
expect(wrapper.state('fee')).to.be.equal(0.1);
wrapper.find('.reference input').simulate('change', { target: { value: 'message' } });
expect(wrapper.state('fee')).to.be.equal(0.2);
});

it('recognizes empty amount', () => {
wrapper.find('.amount input').simulate('change', { target: { value: '12000' } });
wrapper.find('.amount input').simulate('change', { target: { value: '' } });
Expand Down Expand Up @@ -102,6 +109,7 @@ describe('Send', () => {
passphrase: props.account.passphrase,
recipientId: '11004588490103196952L',
secondPassphrase: null,
data: '',
});
});
});
11 changes: 9 additions & 2 deletions src/utils/api/account.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,17 @@ export const setSecondPassphrase = (activePeer, secondPassphrase, publicKey, pas
});
});

export const send = (activePeer, recipientId, amount, passphrase, secondPassphrase = null) =>
export const send = (activePeer, recipientId, amount,
passphrase, secondPassphrase = null, data = null) =>
new Promise((resolve) => {
const transaction = Lisk.transaction
.transfer({ recipientId, amount, passphrase, secondPassphrase });
.transfer({
recipientId,
amount,
passphrase,
secondPassphrase,
data,
});
activePeer.transactions.broadcast(transaction).then(() => {
resolve(transaction);
});
Expand Down