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%; width: 100%;
display: flex; display: flex;
flex: 1; flex: 1;
flex-direction: column;
} }
:root * { :root * {
@ -43,4 +44,5 @@
:root :global(#container) > div { :root :global(#container) > div {
flex: 1; 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'; import injectTapEventPlugin from 'react-tap-event-plugin';
injectTapEventPlugin(); injectTapEventPlugin();
import Deploy from './basiccoin/Deploy'; import Deploy from './tokendeploy/Deploy';
import Application from './basiccoin/Application'; import Application from './tokendeploy/Application';
import Overview from './basiccoin/Overview'; import Overview from './tokendeploy/Overview';
import Transfer from './basiccoin/Transfer'; import Transfer from './tokendeploy/Transfer';
import '../../assets/fonts/Roboto/font.css'; import '../../assets/fonts/Roboto/font.css';
import '../../assets/fonts/RobotoMono/font.css'; import '../../assets/fonts/RobotoMono/font.css';

View File

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

View File

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

View File

@ -121,8 +121,21 @@ export default class Send extends Component {
} }
renderForm () { 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 { accounts } = this.context;
const { availableBalances, fromAddress, amount, amountError, toKnown, toAddress } = this.state; const { availableBalances, fromAddress, amount, amountError, toKnown, toAddress } = this.state;
const fromBalance = availableBalances.find((balance) => balance.address === fromAddress); const fromBalance = availableBalances.find((balance) => balance.address === fromAddress);
const fromAddresses = availableBalances.map((balance) => balance.address); const fromAddresses = availableBalances.map((balance) => balance.address);
const toAddresses = Object.keys(accounts); const toAddresses = Object.keys(accounts);
@ -323,7 +336,10 @@ export default class Send extends Component {
}); });
this.setState({ tokens, loading: false }); 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 { .form .input {
align-items: center;
display: flex;
flex-wrap: wrap;
margin-bottom: 1.5em; margin-bottom: 1.5em;
} }
.form .input * { .form .input * {
display: inline-block; display: inline-block;
margin: 0 0.5em; margin: 0 0.5em;
padding: 0.5em;
font-size: 1em; font-size: 1em;
} }
.form label { .form .input label {
width: 25em; width: 25em;
opacity: 0.8; opacity: 0.8;
text-align: right; text-align: right;
@ -47,8 +49,8 @@
opacity: 0.5; opacity: 0.5;
} }
.form input, .form .input input,
.form select { .form .input select {
width: 18em; width: 18em;
color: #444; color: #444;
background: rgba(255, 255, 255, 0.75); background: rgba(255, 255, 255, 0.75);
@ -58,6 +60,7 @@
-moz-appearance: none; -moz-appearance: none;
-webkit-appearance: none; -webkit-appearance: none;
appearance: none; appearance: none;
padding: 0.5em;
} }
.form select { .form select {

View File

Before

Width:  |  Height:  |  Size: 124 KiB

After

Width:  |  Height:  |  Size: 124 KiB

View File

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

View File

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