Fixes to Token Deploy dapp (#4513)

* Renaming Basiccoin => Tokendeploy

* Rename Basiccoin => Tokendeploy

* UI and bug fixes to the TokenDeploy dapp

* Use decimals for Token Deployment #4311

* Typo

* PR Gumbles
This commit is contained in:
Nicolas Gotchac 2017-02-13 13:47:11 +01:00 committed by Jaco Greeff
parent 1fa830d19b
commit b561ae7b12
57 changed files with 79 additions and 34 deletions

View File

@ -35,6 +35,7 @@
width: 100%;
display: flex;
flex: 1;
flex-direction: column;
}
:root * {
@ -43,4 +44,5 @@
:root :global(#container) > div {
flex: 1;
flex-direction: column;
}

View File

@ -21,10 +21,10 @@ import { Redirect, Router, Route, hashHistory } from 'react-router';
import injectTapEventPlugin from 'react-tap-event-plugin';
injectTapEventPlugin();
import Deploy from './basiccoin/Deploy';
import Application from './basiccoin/Application';
import Overview from './basiccoin/Overview';
import Transfer from './basiccoin/Transfer';
import Deploy from './tokendeploy/Deploy';
import Application from './tokendeploy/Application';
import Overview from './tokendeploy/Overview';
import Transfer from './tokendeploy/Transfer';
import '../../assets/fonts/Roboto/font.css';
import '../../assets/fonts/RobotoMono/font.css';

View File

@ -20,11 +20,14 @@ import { api } from '../../parity';
import Container from '../../Container';
import styles from './deployment.css';
const DECIMALS = 6;
const BASE = Math.pow(10, DECIMALS);
const ERRORS = {
name: 'specify a valid name >2 & <32 characters',
tla: 'specify a valid TLA, 3 characters in length',
usedtla: 'the TLA used is not available for registration',
supply: 'supply needs to be valid >999 & <1 trillion'
supply: `supply needs to be > 1 & <1 trillion, with no more than ${DECIMALS} decimals`
};
export default class Deployment extends Component {
@ -34,9 +37,9 @@ export default class Deployment extends Component {
managerInstance: PropTypes.object.isRequired,
registryInstance: PropTypes.object.isRequired,
tokenregInstance: PropTypes.object.isRequired
}
};
state = {
static initState = {
base: null,
deployBusy: false,
deployDone: false,
@ -54,7 +57,9 @@ export default class Deployment extends Component {
totalSupplyError: null,
signerRequestId: null,
txHash: null
}
};
state = Deployment.initState
componentDidMount () {
const { managerInstance, tokenregInstance } = this.context;
@ -74,6 +79,10 @@ export default class Deployment extends Component {
});
}
reset () {
this.setState(Deployment.initState, () => this.componentDidMount());
}
render () {
const { deployBusy } = this.state;
@ -102,7 +111,7 @@ export default class Deployment extends Component {
Your deployment has encountered an error
</div>
<div className={ styles.statusError }>
{ deployError }
{ deployError.message }
</div>
</Container>
);
@ -155,8 +164,9 @@ export default class Deployment extends Component {
<label>token supply</label>
<input
type='number'
min='1000'
max='999999999999'
step={ 1 }
min={ 1 }
max='999999999999999'
name='totalSupply'
value={ totalSupply }
onChange={ this.onChangeSupply }
@ -196,12 +206,14 @@ export default class Deployment extends Component {
}
onChangeSupply = (event) => {
const totalSupply = parseInt(event.target.value, 10);
const totalSupplyError = isFinite(totalSupply) && totalSupply > 999
const { value } = event.target;
const floatValue = parseFloat(value, 10);
const convertedTotalSupply = floatValue * BASE;
const totalSupplyError = Number.isInteger(convertedTotalSupply) && floatValue >= 1
? null
: ERRORS.supply;
this.setState({ totalSupply, totalSupplyError });
this.setState({ totalSupply: value, totalSupplyError });
}
onChangeTla = (event) => {
@ -293,8 +305,12 @@ export default class Deployment extends Component {
this.setState({ txReceipt, deployDone: true, deployState: 'Network confirmed, Received transaction receipt' });
})
.catch((error) => {
if (error.type === 'REQUEST_REJECTED') {
return this.reset();
}
console.error('onDeploy', error);
this.setState({ deployError: error.message });
this.setState({ deployError: error });
});
}
}

View File

@ -23,6 +23,14 @@
border: none;
margin: 0 auto;
border-collapse: collapse;
display: flex;
overflow: auto;
> * {
display: flex;
flex: 1;
flex-direction: column;
}
}
.eventList tr:nth-child(even) {

View File

@ -121,8 +121,21 @@ export default class Send extends Component {
}
renderForm () {
const { tokens } = this.state;
if (!tokens || tokens.length === 0) {
return (
<Container>
<div className={ styles.statusHeader }>
There are no tokens to transfer
</div>
</Container>
);
}
const { accounts } = this.context;
const { availableBalances, fromAddress, amount, amountError, toKnown, toAddress } = this.state;
const fromBalance = availableBalances.find((balance) => balance.address === fromAddress);
const fromAddresses = availableBalances.map((balance) => balance.address);
const toAddresses = Object.keys(accounts);
@ -323,7 +336,10 @@ export default class Send extends Component {
});
this.setState({ tokens, loading: false });
this.onSelectToken({ target: { value: tokens[0].address } });
if (tokens.length > 0) {
this.onSelectToken({ target: { value: tokens[0].address } });
}
});
}
}

View File

@ -26,17 +26,19 @@
}
.form .input {
align-items: center;
display: flex;
flex-wrap: wrap;
margin-bottom: 1.5em;
}
.form .input * {
display: inline-block;
margin: 0 0.5em;
padding: 0.5em;
font-size: 1em;
}
.form label {
.form .input label {
width: 25em;
opacity: 0.8;
text-align: right;
@ -47,8 +49,8 @@
opacity: 0.5;
}
.form input,
.form select {
.form .input input,
.form .input select {
width: 18em;
color: #444;
background: rgba(255, 255, 255, 0.75);
@ -58,6 +60,7 @@
-moz-appearance: none;
-webkit-appearance: none;
appearance: none;
padding: 0.5em;
}
.form select {

View File

Before

Width:  |  Height:  |  Size: 124 KiB

After

Width:  |  Height:  |  Size: 124 KiB

View File

@ -1,7 +1,7 @@
[
{
"id": "0xf9f2d620c2e08f83e45555247146c62185e4ab7cf82a4b9002a265a0d020348f",
"url": "basiccoin",
"url": "tokendeploy",
"name": "Token Deployment",
"description": "Deploy new basic tokens that you are able to send around",
"author": "Parity Team <admin@ethcore.io>",

View File

@ -22,10 +22,10 @@ import Contracts from '~/contracts';
import Store, { LS_KEY_DISPLAY } from './dappsStore';
const APPID_BASICCOIN = '0xf9f2d620c2e08f83e45555247146c62185e4ab7cf82a4b9002a265a0d020348f';
const APPID_DAPPREG = '0x7bbc4f1a27628781b96213e781a1b8eec6982c1db8fac739af6e4c5a55862c03';
const APPID_GHH = '0x058740ee9a5a3fb9f1cfa10752baec87e09cc45cd7027fd54708271aca300c75';
const APPID_LOCALTX = '0xae74ad174b95cdbd01c88ac5b73a296d33e9088fc2a200e76bcedf3a94a7815d';
const APPID_TOKENDEPLOY = '0xf9f2d620c2e08f83e45555247146c62185e4ab7cf82a4b9002a265a0d020348f';
const FETCH_OK = {
ok: true,
status: 200
@ -91,7 +91,7 @@ describe('views/Dapps/DappStore', () => {
describe('@action', () => {
const defaultViews = {
[APPID_BASICCOIN]: { visible: false },
[APPID_TOKENDEPLOY]: { visible: false },
[APPID_DAPPREG]: { visible: true }
};
@ -106,10 +106,10 @@ describe('views/Dapps/DappStore', () => {
});
it('overrides single keys, keeping existing', () => {
store.setDisplayApps({ [APPID_BASICCOIN]: { visible: true } });
store.setDisplayApps({ [APPID_TOKENDEPLOY]: { visible: true } });
expect(store.displayApps).to.deep.equal(
Object.assign({}, defaultViews, { [APPID_BASICCOIN]: { visible: true } })
Object.assign({}, defaultViews, { [APPID_TOKENDEPLOY]: { visible: true } })
);
});
@ -143,19 +143,19 @@ describe('views/Dapps/DappStore', () => {
});
it('enables visibility', () => {
store.showApp(APPID_BASICCOIN);
store.showApp(APPID_TOKENDEPLOY);
expect(store.displayApps[APPID_BASICCOIN].visible).to.be.true;
expect(store.displayApps[APPID_TOKENDEPLOY].visible).to.be.true;
expect(localStore.get(LS_KEY_DISPLAY)).to.deep.equal(
Object.assign({}, defaultViews, { [APPID_BASICCOIN]: { visible: true } })
Object.assign({}, defaultViews, { [APPID_TOKENDEPLOY]: { visible: true } })
);
});
it('keeps visibility state', () => {
store.hideApp(APPID_BASICCOIN);
store.hideApp(APPID_TOKENDEPLOY);
store.showApp(APPID_DAPPREG);
expect(store.displayApps[APPID_BASICCOIN].visible).to.be.false;
expect(store.displayApps[APPID_TOKENDEPLOY].visible).to.be.false;
expect(store.displayApps[APPID_DAPPREG].visible).to.be.true;
expect(localStore.get(LS_KEY_DISPLAY)).to.deep.equal(defaultViews);
});
@ -177,11 +177,11 @@ describe('views/Dapps/DappStore', () => {
});
it('saves visibility to storage', () => {
store.setDisplayApps({ [APPID_BASICCOIN]: { visible: true } });
store.setDisplayApps({ [APPID_TOKENDEPLOY]: { visible: true } });
store.writeDisplayApps();
expect(localStore.get(LS_KEY_DISPLAY)).to.deep.equal(
Object.assign({}, defaultViews, { [APPID_BASICCOIN]: { visible: true } })
Object.assign({}, defaultViews, { [APPID_TOKENDEPLOY]: { visible: true } })
);
});
});
@ -190,7 +190,7 @@ describe('views/Dapps/DappStore', () => {
describe('saved views', () => {
beforeEach(() => {
localStore.set(LS_KEY_DISPLAY, {
[APPID_BASICCOIN]: { visible: false },
[APPID_TOKENDEPLOY]: { visible: false },
[APPID_DAPPREG]: { visible: true }
});
@ -202,7 +202,7 @@ describe('views/Dapps/DappStore', () => {
});
it('disables based on saved keys', () => {
expect(store.displayApps[APPID_BASICCOIN].visible).to.be.false;
expect(store.displayApps[APPID_TOKENDEPLOY].visible).to.be.false;
});
it('enables based on saved keys', () => {