From efea6dfefd3fb4e4ca6b42711c08df1bd2fab1d5 Mon Sep 17 00:00:00 2001 From: fernandomg Date: Thu, 8 Mar 2018 12:27:04 -0300 Subject: [PATCH 01/16] Remove 'whitelistElements' --- src/components/Common/WhitelistInputBlock.js | 16 ++++++---------- src/components/Common/WhitelistItem.js | 16 ++++++++-------- src/components/manage/index.js | 2 +- src/components/manage/utils.js | 11 +++-------- src/components/stepThree/index.js | 3 +-- src/stores/TierStore.js | 17 ++++++++--------- src/utils/constants.js | 3 +-- 7 files changed, 28 insertions(+), 40 deletions(-) diff --git a/src/components/Common/WhitelistInputBlock.js b/src/components/Common/WhitelistInputBlock.js index bf9fc06fc..4862be21d 100644 --- a/src/components/Common/WhitelistInputBlock.js +++ b/src/components/Common/WhitelistInputBlock.js @@ -104,8 +104,8 @@ export class WhitelistInputBlock extends React.Component { render () { - const { num } = this.props - const { whitelistElements } = this.props.tierStore.tiers[num] + const { num, tierStore } = this.props + const { whitelist } = tierStore.tiers[num] const dropzoneStyle = { position: 'relative', @@ -152,15 +152,11 @@ export class WhitelistInputBlock extends React.Component { /> - {whitelistElements && whitelistElements.map(e => + {whitelist.length > 0 && whitelist.filter(item => !item.deleted).map(item => )} item.addr === addr && !item.deleted) - return whitelist && whitelist.deleted ? null : ( + return !whitelist ? null : (
+ className="white-list-item-container">
{addr} {min} @@ -24,7 +24,7 @@ export class WhitelistItem extends React.Component {
{!alreadyDeployed - ? this.removeItem()}> + ? this.removeItem(addr)}> : null }
diff --git a/src/components/manage/index.js b/src/components/manage/index.js index 5ff2fcb52..4fdbf80a9 100644 --- a/src/components/manage/index.js +++ b/src/components/manage/index.js @@ -338,7 +338,7 @@ export class Manage extends Component { if (!this.state.formPristine && !this.state.crowdsaleHasEnded && updatableTiers.length && validTiers) { const keys = Object .keys(updatableTiers[0]) - .filter(key => key !== 'index' && key !== 'updatable' && key !== 'addresses' && key !== 'whitelistElements') + .filter(key => key !== 'index' && key !== 'updatable' && key !== 'addresses') updatableTiers .reduce((toUpdate, tier) => { diff --git a/src/components/manage/utils.js b/src/components/manage/utils.js index 5fff889dd..8e438d87c 100644 --- a/src/components/manage/utils.js +++ b/src/components/manage/utils.js @@ -201,8 +201,7 @@ export const processTier = (crowdsaleAddress, crowdsaleNum) => { const { web3 } = web3Store const newTier = { - whitelist: [], - whitelistElements: [] + whitelist: [] } const initialValues = {} @@ -295,17 +294,14 @@ export const processTier = (crowdsaleAddress, crowdsaleNum) => { } const whitelist = newTier.whitelist.slice() - const whitelistElements = newTier.whitelistElements.slice() - whitelistAccounts.forEach(({ addr, min, max }, whitelistNum) => { + whitelistAccounts.forEach(({ addr, min, max }) => { min = parseInt(toFixed(min), 10) / 10 ** tokenDecimals max = parseInt(toFixed(max), 10) / 10 ** tokenDecimals - whitelistElements.push({ addr, min, max, whitelistNum, crowdsaleNum, alreadyDeployed: true }) - whitelist.push({ addr, min, max }) + whitelist.push({ addr, min, max, alreadyDeployed: true }) }) - tierStore.setTierProperty(whitelistElements, 'whitelistElements', crowdsaleNum) tierStore.setTierProperty(whitelist, 'whitelist', crowdsaleNum) if (initialValues.updatable) { @@ -314,7 +310,6 @@ export const processTier = (crowdsaleAddress, crowdsaleNum) => { initialValues.rate = newTier.rate initialValues.supply = newTier.supply initialValues.whitelist = whitelist - initialValues.whitelistElements = whitelistElements } crowdsaleStore.addInitialTierValues(initialValues) }) diff --git a/src/components/stepThree/index.js b/src/components/stepThree/index.js index 9d2aa547e..fe17ddc6c 100644 --- a/src/components/stepThree/index.js +++ b/src/components/stepThree/index.js @@ -83,8 +83,7 @@ export class stepThree extends React.Component { supply: 0, rate: 0, updatable: "off", - whitelist: [], - whitelistElements: [] + whitelist: [] }; const newTierValidations = { diff --git a/src/stores/TierStore.js b/src/stores/TierStore.js index bcd1d2a12..520d28963 100644 --- a/src/stores/TierStore.js +++ b/src/stores/TierStore.js @@ -176,20 +176,19 @@ class TierStore { if (isAdded) return - const whitelistElements = tier.whitelistElements.slice() - const whitelistNum = whitelistElements.length - - whitelistElements.push({ addr, min, max, whitelistNum, crowdsaleNum }) whitelist.push({ addr, min, max }) - this.setTierProperty(whitelistElements, 'whitelistElements', crowdsaleNum) this.setTierProperty(whitelist, 'whitelist', crowdsaleNum) } - @action removeWhitelistItem = (whitelistNum, crowdsaleNum) => { - let whitelist = this.tiers[crowdsaleNum].whitelist.slice() - whitelist[whitelistNum].deleted = true - this.setTierProperty(whitelist, 'whitelist', crowdsaleNum) + @action removeWhitelistItem = (address, crowdsaleNum) => { + const whitelist = this.tiers[crowdsaleNum].whitelist.slice() + const addressIndex = whitelist.findIndex(item => item.addr === address && !item.deleted) + + if (addressIndex > -1) { + whitelist[addressIndex].deleted = true + this.setTierProperty(whitelist, 'whitelist', crowdsaleNum) + } } @computed get maxSupply () { diff --git a/src/utils/constants.js b/src/utils/constants.js index 3271acfbd..fa439f210 100644 --- a/src/utils/constants.js +++ b/src/utils/constants.js @@ -3,8 +3,7 @@ export const defaultTiers = [{ endTime: '', walletAddress: '', supply: '', - whitelist: [], - whitelistElements: [] + whitelist: [] }] export const CONTRACT_TYPES = { From 6f03e62749342ff43dbb3c00d62aed55462e9dc9 Mon Sep 17 00:00:00 2001 From: fernandomg Date: Thu, 8 Mar 2018 13:26:48 -0300 Subject: [PATCH 02/16] Remove 'deleted' flag from 'whitelist' collection --- src/components/Common/WhitelistInputBlock.js | 2 +- src/components/Common/WhitelistItem.js | 5 ++--- src/components/manage/index.js | 2 +- src/components/stepFour/utils.js | 10 ++++------ src/components/stepThree/index.js | 2 +- src/stores/TierStore.js | 8 +++----- 6 files changed, 12 insertions(+), 17 deletions(-) diff --git a/src/components/Common/WhitelistInputBlock.js b/src/components/Common/WhitelistInputBlock.js index 4862be21d..d8f0b80aa 100644 --- a/src/components/Common/WhitelistInputBlock.js +++ b/src/components/Common/WhitelistInputBlock.js @@ -152,7 +152,7 @@ export class WhitelistInputBlock extends React.Component { />
- {whitelist.length > 0 && whitelist.filter(item => !item.deleted).map(item => + {whitelist.length > 0 && whitelist.map(item => item.addr === addr && !item.deleted) + const { addr, min, max, alreadyDeployed } = this.props - return !whitelist ? null : ( + return (
diff --git a/src/components/manage/index.js b/src/components/manage/index.js index 4fdbf80a9..349aea30a 100644 --- a/src/components/manage/index.js +++ b/src/components/manage/index.js @@ -348,7 +348,7 @@ export class Manage extends Component { if (isObservableArray(newValue)) { if (newValue.length > tier[key].length) { - newValue = newValue.slice(tier[key].length).filter(whitelist => !whitelist.deleted) + newValue = newValue.slice(tier[key].length) if (newValue.length) { toUpdate.push({ key, newValue, addresses }) } diff --git a/src/components/stepFour/utils.js b/src/components/stepFour/utils.js index 85743f3e2..d945db0d4 100644 --- a/src/components/stepFour/utils.js +++ b/src/components/stepFour/utils.js @@ -440,12 +440,10 @@ export const addWhitelist = () => { let maxCaps = [] for (let i = 0; i < whitelist.length; i++) { - if (!whitelist[i].deleted) { - addrs.push(whitelist[i].addr) - statuses.push(true) - minCaps.push(whitelist[i].min * 10 ** tokenStore.decimals ? toFixed((whitelist[i].min * 10 ** tokenStore.decimals).toString()) : 0) - maxCaps.push(whitelist[i].max * 10 ** tokenStore.decimals ? toFixed((whitelist[i].max * 10 ** tokenStore.decimals).toString()) : 0) - } + addrs.push(whitelist[i].addr) + statuses.push(true) + minCaps.push(whitelist[i].min * 10 ** tokenStore.decimals ? toFixed((whitelist[i].min * 10 ** tokenStore.decimals).toString()) : 0) + maxCaps.push(whitelist[i].max * 10 ** tokenStore.decimals ? toFixed((whitelist[i].max * 10 ** tokenStore.decimals).toString()) : 0) } console.log('addrs:', addrs) diff --git a/src/components/stepThree/index.js b/src/components/stepThree/index.js index fe17ddc6c..f0854567b 100644 --- a/src/components/stepThree/index.js +++ b/src/components/stepThree/index.js @@ -173,7 +173,7 @@ export class stepThree extends React.Component { if (hasWhitelist) { whitelistCount = tierStore.tiers.reduce((total, tier) => { - total += tier.whitelist.filter(address => !address.deleted).length + total += tier.whitelist.length return total }, 0) } diff --git a/src/stores/TierStore.js b/src/stores/TierStore.js index 520d28963..4ab4a26a2 100644 --- a/src/stores/TierStore.js +++ b/src/stores/TierStore.js @@ -172,7 +172,7 @@ class TierStore { const whitelist = tier.whitelist.slice() - const isAdded = whitelist.find(item => item.addr === addr && !item.deleted) + const isAdded = whitelist.find(item => item.addr === addr) if (isAdded) return @@ -182,12 +182,10 @@ class TierStore { } @action removeWhitelistItem = (address, crowdsaleNum) => { - const whitelist = this.tiers[crowdsaleNum].whitelist.slice() - const addressIndex = whitelist.findIndex(item => item.addr === address && !item.deleted) + const addressIndex = this.tiers[crowdsaleNum].whitelist.findIndex(item => item.addr === address) if (addressIndex > -1) { - whitelist[addressIndex].deleted = true - this.setTierProperty(whitelist, 'whitelist', crowdsaleNum) + this.tiers[crowdsaleNum].whitelist.splice(addressIndex, 1) } } From f661acc86fdcbee94f510da7119bcabbe5a33ee9 Mon Sep 17 00:00:00 2001 From: fernandomg Date: Thu, 8 Mar 2018 14:05:42 -0300 Subject: [PATCH 03/16] Add support for manage screen --- src/components/Common/WhitelistInputBlock.js | 2 +- src/stores/TierStore.js | 25 +++++++++++++++----- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/src/components/Common/WhitelistInputBlock.js b/src/components/Common/WhitelistInputBlock.js index d8f0b80aa..dd0e5ec9b 100644 --- a/src/components/Common/WhitelistInputBlock.js +++ b/src/components/Common/WhitelistInputBlock.js @@ -154,7 +154,7 @@ export class WhitelistInputBlock extends React.Component {
{whitelist.length > 0 && whitelist.map(item => diff --git a/src/stores/TierStore.js b/src/stores/TierStore.js index 4ab4a26a2..a9caa1aa1 100644 --- a/src/stores/TierStore.js +++ b/src/stores/TierStore.js @@ -168,17 +168,26 @@ class TierStore { } @action addWhitelistItem = ({ addr, min, max }, crowdsaleNum) => { - const tier = this.tiers[crowdsaleNum] + const { whitelist } = this.tiers[crowdsaleNum] + const newItem = { addr, min, max } + const _addr = addr.toLowerCase() + const isAdded = whitelist.find(item => item.addr.toLowerCase() === _addr) - const whitelist = tier.whitelist.slice() + if (this.deployedContract) { + const alreadyDeployedIndex = whitelist.findIndex(item => item.addr.toLowerCase() === _addr && item.alreadyDeployed) + const duplicatedIndex = whitelist.findIndex(item => item.addr.toLowerCase() === _addr && !item.alreadyDeployed && item.duplicated) - const isAdded = whitelist.find(item => item.addr === addr) + if (duplicatedIndex > -1) return - if (isAdded) return + if (alreadyDeployedIndex > -1) { + whitelist[alreadyDeployedIndex].duplicated = true + newItem.duplicated = true - whitelist.push({ addr, min, max }) + } else if (isAdded) return - this.setTierProperty(whitelist, 'whitelist', crowdsaleNum) + } else if (isAdded) return + + whitelist.push(newItem) } @action removeWhitelistItem = (address, crowdsaleNum) => { @@ -192,6 +201,10 @@ class TierStore { @computed get maxSupply () { return this.tiers.map(tier => +tier.supply).reduce((a, b) => Math.max(a, b), 0) } + + @computed get deployedContract () { + return this.tiers.some(tier => tier.whitelist.some(item => item.alreadyDeployed)) + } } export default TierStore; From 21ad35294e467c0746afbb758564492b947b6557 Mon Sep 17 00:00:00 2001 From: fernandomg Date: Thu, 8 Mar 2018 15:48:27 -0300 Subject: [PATCH 04/16] Fix manage screen Whitelist presentation --- package-lock.json | 9 ++++++ package.json | 1 + src/assets/stylesheets/application.css | 2 +- .../stylesheets/application/manage.scss | 29 +++++++++++++++++-- .../application/steps/whitelist.scss | 23 +++++++++++++++ src/components/Common/WhitelistItem.js | 19 ++++++++++-- src/components/manage/index.js | 2 +- 7 files changed, 77 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index 16b91ffc0..d0e4db3ce 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12745,6 +12745,15 @@ "object-assign": "4.1.1" } }, + "react-tooltip": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/react-tooltip/-/react-tooltip-3.4.0.tgz", + "integrity": "sha1-A38495fD5rG1jSU0zMjCx2r09S0=", + "requires": { + "classnames": "2.2.5", + "prop-types": "15.6.0" + } + }, "react-transition-group": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-1.2.1.tgz", diff --git a/package.json b/package.json index 932537b6f..a5258c907 100755 --- a/package.json +++ b/package.json @@ -86,6 +86,7 @@ "react-dropzone": "^4.2.8", "react-error-overlay": "^1.0.9", "react-router-dom": "^4.1.2", + "react-tooltip": "^3.4.0", "solc": "^0.4.14", "solidity-flattener": "file:submodules/solidity-flattener", "store2": "^2.6.0", diff --git a/src/assets/stylesheets/application.css b/src/assets/stylesheets/application.css index 1876238a9..f554d0d84 100644 --- a/src/assets/stylesheets/application.css +++ b/src/assets/stylesheets/application.css @@ -1 +1 @@ -.header,.footer,.crowdsale,.process{left:0;right:0}.header .logo,.footer .logo{display:block;background-image:url(../images/logos.png)}@media(min--moz-device-pixel-ratio:1.3),(-webkit-min-device-pixel-ratio:1.3),(min-device-pixel-ratio:1.3),(min-resolution:1.3dppx){.header .logo,.footer .logo{background-image:url("../images/logos@2x.png");background-size:182px 59px}}@font-face{font-family:'Open Sans';font-style:normal;font-weight:400;src:local("Open Sans"),local("OpenSans"),url(https://fonts.gstatic.com/s/opensans/v13/cJZKeOuBrn4kERxqtaUH3ZBw1xU1rKptJj_0jans920.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2212,U+2215,U+E0FF,U+EFFD,U+F000}@font-face{font-family:'Open Sans';font-style:normal;font-weight:700;src:local("Open Sans Bold"),local("OpenSans-Bold"),url(https://fonts.gstatic.com/s/opensans/v13/k3k702ZOKiLJc3WVjuplzBampu5_7CjHW5spxoeN3Vs.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2212,U+2215,U+E0FF,U+EFFD,U+F000}html,body{color:#333;line-height:1;font-size:14px;font-family:'Open Sans',sans-serif;-webkit-font-smoothing:antialiased}html,body{margin:0;padding:0}p,h1,h2,h3,h4{margin:0;padding:0;font-family:'Open Sans',sans-serif}html{height:100%}body{position:relative;width:100%;min-width:1000px;min-height:100%;box-sizing:border-box;padding:80px 0 60px;background-color:#fbfbfc}.container{width:960px;margin:0 auto;box-sizing:border-box}.hidden{overflow:hidden}.notdisplayed{display:none}.left{width:46%;float:left}.right{width:46%;float:right}.item-remove{background-image:url(../images/delete.png);background-repeat:no-repeat;display:block;width:12px;height:12px;cursor:pointer;float:right}@media(min--moz-device-pixel-ratio:1.3),(-webkit-min-device-pixel-ratio:1.3),(min-device-pixel-ratio:1.3),(min-resolution:1.3dppx){.item-remove{background-image:url("../images/delete@2x.png");background-size:12px 12px}}.copy{background-image:url(../images/copy.png);background-repeat:no-repeat;display:block;width:12px;height:12px;cursor:pointer;float:right}@media(min--moz-device-pixel-ratio:1.3),(-webkit-min-device-pixel-ratio:1.3),(min-device-pixel-ratio:1.3),(min-resolution:1.3dppx){.copy{background-image:url("../images/copy@2x.png");background-size:12px 12px}}.copy-field-container{display:table-cell;padding-left:10px;vertical-align:top;padding-top:30.5px}.copy-area-container{display:table-cell;padding-left:10px}.display-container{display:table-cell;width:100%}.input-block-container{display:table;width:100%}.section-title{display:block;margin-bottom:30px;text-transform:uppercase;font-size:20px;font-weight:bold}@media(max-height:600px){body{padding-top:0}}.header{position:absolute;top:0;height:80px;background-image:url(../images/bg.png);background-size:cover;background-position:center center}.header .logo{width:182px;height:35px;margin-top:22.5px;background-position:0 -25px}@media(max-height:600px){.header{position:relative;top:0;height:auto;padding:1px 0 21px}}.footer{position:absolute;bottom:0;height:60px;background-image:url(../images/bg.png);background-size:cover;background-position:center center;color:#fff}.footer .container{position:relative}.footer .logo,.footer .socials{-webkit-transform:translateY(-50%);transform:translateY(-50%);position:absolute;z-index:1;top:50%}.footer .logo{left:0;width:126px;height:24px;background-position:0 0}.footer .rights{color:#fff;line-height:60px;text-align:center;font-size:12px}.footer .socials{right:0}.socials{font-size:0}.socials .social{transition:.3s background-color;position:relative;display:inline-block;vertical-align:top;width:30px;height:30px;border-radius:50%;background-color:rgba(255,255,255,0.2)}.socials .social:not(:first-child){margin-left:10px}.socials .social:hover{background-color:rgba(255,255,255,0.4)}.socials .social:before{-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);content:'';position:absolute;left:50%;top:50%;background-image:url(../images/socials.png)}@media(min--moz-device-pixel-ratio:1.3),(-webkit-min-device-pixel-ratio:1.3),(min-device-pixel-ratio:1.3),(min-resolution:1.3dppx){.socials .social:before{background-image:url("../images/socials@2x.png");background-size:16px 69px}}.socials .social_github:before{width:16px;height:16px;background-position:0 0}.socials .social_oracles:before{width:16px;height:14px;background-position:0 -16px}.socials .social_reddit:before{width:15px;height:13px;background-position:0 -30px}.socials .social_telegram:before{width:16px;height:14px;background-position:0 -43px}.socials .social_twitter:before{width:15px;height:12px;background-position:0 -57px}.step-icons{background-image:url(../images/step-icons.png)}@media(min--moz-device-pixel-ratio:1.3),(-webkit-min-device-pixel-ratio:1.3),(min-device-pixel-ratio:1.3),(min-resolution:1.3dppx){.step-icons{background-image:url("../images/step-icons@2x.png");background-size:100px 480px}}.step-icons_crowdsale-contract{width:80px;height:100px;background-position:0 0}.step-icons_crowdsale-page{width:100px;height:80px;background-position:0 -100px}.step-icons_crowdsale-setup{width:88px;height:100px;background-position:0 -180px}.step-icons_publish{width:100px;height:100px;background-position:0 -280px}.step-icons_token-setup{width:100px;height:100px;background-position:0 -380px}.button{cursor:pointer;display:inline-block;transition:.3s background-color,0.3s color;border-radius:3px;box-sizing:border-box;padding:0 15px;line-height:36px;font-size:13px;text-decoration:none;text-transform:uppercase;font-weight:bold}.button-container{text-align:center}.button_fill{background-color:#08b3f2;color:#fff}.button_fill:hover{background-color:#34c3f8;cursor:pointer}.button_disabled{background-color:#e6e6e6;color:#9c9c9c}.button_disabled:hover{cursor:default !important}.button_fill_secondary{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAAAFVBMVEX///////////////////////////9nSIHRAAAABnRSTlMASUrk5udXTd49AAAAOUlEQVR42tXQsQEAIAgDQcAn+4+snRZxAK79KokrIcNBwgYdc0Migwxk8Qsd1TJWDf/KQWobqt+9G4coA99W7as5AAAAAElFTkSuQmCC) !important;background-color:#64299d;color:#fff;margin-right:10px}.button_fill_secondary:hover{background-color:#752fb6}.button_fill_plus{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAAAFVBMVEX///////////////////////////9nSIHRAAAABnRSTlMASUrk5udXTd49AAAAOUlEQVR42tXQsQEAIAgDQcAn+4+snRZxAK79KokrIcNBwgYdc0Migwxk8Qsd1TJWDf/KQWobqt+9G4coA99W7as5AAAAAElFTkSuQmCC) !important;width:36px;height:36px;padding-left:0 !important;background-position:center center !important}.button_outline{box-shadow:inset 0 0 0 2px #08b3f2;color:#08b3f2}.button_outline:hover{background-color:#08b3f2;color:#fff}.plus-button-container{display:table-cell;padding-left:20px;padding-top:28.5px;vertical-align:top}.label{display:block;margin-bottom:15px;text-transform:uppercase;font-weight:bold}.input{transition:.3s border-color;width:100%;height:36px;margin-bottom:15px;outline:0;border:1px solid #eee;box-sizing:border-box;border-radius:3px;padding:0 10px;color:#333;font-size:14px;font-family:'Open Sans',sans-serif}.input:focus{border-color:#08b3f2}.input:disabled{background:#f2f2f2}.invest{margin:30px auto;padding-left:30px;border-radius:8px;border:1px solid #eee;background-color:#fff}.invest .timer{position:absolute;z-index:2;left:25px;top:25px;width:180px;height:180px;border-radius:50%;background-color:#fff;line-height:180px;text-align:center}.invest .timer-inner{line-height:normal;display:inline-block}.invest .timer-i{display:inline-block;vertical-align:middle;margin:0 5px;font-size:0;text-align:center}.invest .timer-count{display:block;margin-bottom:5px;color:#642f9c;font-size:24px;font-weight:bold}.invest .timer-interval{display:block;text-transform:uppercase;font-size:10px;color:#8197a2}.invest .timer-container{position:absolute;z-index:1;left:0;top:30px;border-radius:50%;background-color:#eee}.invest .hashes{position:relative;min-height:240px;padding-left:260px}.invest .hashes-i{margin-bottom:30px}.invest .hashes-title{margin-bottom:10px;color:#642f9c;font-weight:bold}.invest .hashes-description{color:#8197a2;font-size:12px}.invest .balance{border-bottom:1px solid #eee;padding:30px}.invest .balance-title{margin-bottom:5px;color:#642f9c;font-size:20px;font-weight:bold}.invest .balance-description{margin-bottom:30px;color:#8197a2}.invest .description{color:#8197a2;line-height:20px;font-size:12px}.invest-through{-webkit-appearance:none;-moz-appearance:none;appearance:none;float:left;height:36px;outline:0;padding:0 28px 0 10px;box-sizing:border-box;border:1px solid #eee;border-radius:3px;background-image:url(../images/select.png);background-repeat:no-repeat;background-position:center right 10px;background-color:#fff;color:#8197a2;font-size:12px}@media(min--moz-device-pixel-ratio:1.3),(-webkit-min-device-pixel-ratio:1.3),(min-device-pixel-ratio:1.3),(min-resolution:1.3dppx){.invest-through{background-image:url("../images/select@2x.png");background-size:8px 5px}}.invest-through-container{overflow:hidden;margin-bottom:30px}.invest-form{padding:30px}.invest-form ::-webkit-input-placeholder{color:#8197a2}.invest-form :-ms-input-placeholder{color:#8197a2}.invest-form ::placeholder{color:#8197a2}.invest-form-label{color:#8197a2}.invest-form-input{display:block;width:100%;height:44px;outline:0;padding-right:30px;border:0;border-bottom:1px solid #eee;box-sizing:border-box;color:#8197a2;font-size:14px;font-weight:bold}.invest-form-input-container{position:relative;margin:15px 0 50px}.invest-form-input-container .invest-form-label{-webkit-transform:translateY(-50%);transform:translateY(-50%);position:absolute;right:0;top:50%}.invest-form-input-container .error{color:red;font-weight:bold;font-size:12px;width:100%;height:10px;position:absolute;margin-top:5px}.invest-form .button{float:right}.invest-title{margin-bottom:10px;color:#333;text-transform:uppercase;font-weight:bold}.invest-description{margin-bottom:30px;color:#8197a2;line-height:18px;font-size:12px}.invest-table{display:table;width:100%}.invest-table-cell{display:table-cell}.invest-table-cell_left{position:relative;width:600px;padding-right:30px;border-right:1px solid #eee}@media(max-height:600px){.invest .qr-selected .balance-description{margin-bottom:0}.invest .qr-selected .description{display:none}.invest .qr-selected .invest-form{padding-bottom:0}.invest .qr-selected .invest-form-label{display:none}.invest .qr-selected .invest-form-input-container{display:none}.invest .qr-selected .payment-process{padding-top:5px}}@-webkit-keyframes paymentLoading{from{-webkit-transform:rotate(0);transform:rotate(0)}to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes paymentLoading{from{-webkit-transform:rotate(0);transform:rotate(0)}to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}.payment-process{padding:30px}.payment-process-qr{display:block;width:140px;margin:0 auto 20px}.payment-process-description{margin-bottom:10px;color:#8197a2;line-height:18px;font-size:13px}.payment-process-hash{margin-bottom:15px;color:#642f9c;word-break:break-all;line-height:20px;font-size:14px;font-weight:bold}.payment-process-copy,.payment-process-see{display:inline-block;margin-bottom:20px;padding-left:20px;background-position:left center;background-repeat:no-repeat;color:#642f9c;text-decoration:none;line-height:14px;font-size:13px}.payment-process-copy:hover,.payment-process-see:hover{text-decoration:underline}.payment-process-copy{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAMAAABF0y+mAAAAFVBMVEVlKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ4g+6HIAAAABnRSTlMASUrk5udXTd49AAAAS0lEQVR42sXSQQoAIAhEUTP1/kduNSIlIUT1t281KKEmNiXNERbV0ZLqSKGLmO4DpvscLamOFPqC6AR1g52f3vH862Q1dWSdrTNsAP8SCeaGkeh2AAAAAElFTkSuQmCC);background-size:14px 14px}.payment-process-see{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAUCAMAAACpgK3LAAAAvVBMVEVlKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ6cDY85AAAAPnRSTlMAAgYHCAkQESElJygpLzAxQkNITlBRUlZXW1xdXmFjZGVnaWqTo6WorcTFxtXa29ze3+Hi7/Dx8vP19vn8/uFjRaQAAADzSURBVHjafVLXEoIwEDxQERF7b6goGsFeUMTw/5/lnbEQRt0HZjcbdq4E3lDrzioIVk5DhSQUax89cRgqsqcvohhcPe6VT5GEU/njdUM68Wwzky3ZHvGw8/J6HOWy+pLVJUreE6J2QzFNAeSY77McQGqKB7caeYUAmYXEOFLg0UBq4f2gAKBt0WsDgoliGPEWujsN5qgnQPCFeXkIG9kMZvi1f5naDmMHydjBI1YUxCk4LwrK038cCypKrRjsfGYGtcJFK4T+tyH05fG5YzOdNscu8bD7Z/AVaWVe3PP0xLJHh/eyRwokoTac9fW6cZqfZ3IHucE/W04kek0AAAAASUVORK5CYII=);background-size:14px 10px}.payment-process-loader{position:relative;margin-bottom:20px;padding-left:20px;color:#8197a2;font-size:13px}.payment-process-loader:before{-webkit-animation-duration:1s;animation-duration:1s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-iteration-count:infinite;animation-iteration-count:infinite;-webkit-animation-name:paymentLoading;animation-name:paymentLoading;-webkit-animation-timing-function:linear;animation-timing-function:linear;content:"";position:absolute;left:0;top:50%;width:14px;height:14px;margin-top:-7px;background-image:url(../images/payment-loader.png)}@media(min--moz-device-pixel-ratio:1.3),(-webkit-min-device-pixel-ratio:1.3),(min-device-pixel-ratio:1.3),(min-resolution:1.3dppx){.payment-process-loader:before{background-image:url("../images/payment-loader@2x.png");background-size:100% 100%}}.payment-process-notation{border-radius:5px;border:1px solid #6d2eae;padding:10px;background-color:rgba(109,46,174,0.1);color:#6d2eae}.payment-process-notation-title{margin-bottom:5px;padding-left:28px;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAgCAMAAABNTyq8AAABX1BMVEVlKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ52EUWdAAAAdHRSTlMAAQIEBQcJCgsMDQ4SExUYGx4gISIoKjAxMzY4Oz1AQUtOT1VbXF5haW1ub3Byc3R1eHl7fH2CiImKi4yVlpeZm6Cjpaeoqq+0tre5usLExcbJysvQ0dLT1dbX2Nna29zh4uPn7O/w8fLz9PX29/n6+/z9/n/AovIAAAE8SURBVHgBhcGJmwoBHMfhj1Ub1rLY3PctdyTkJgclHSTkFiKpvv//s83RNL+npt4Xa/FSpfW3nIoxw2pdrvIKkTY15avFiZJTIEOEZFeBP9uYrqCQx0x1TMYhpkh81lA+AUtPNfQ2xqRrcpwCOCvHBSbs6MhxBeC6HD+3AtYTue4CPJLrPliH5XkOUJJrsA8j3pSnAfBVnuoCYZflawOxnnynCVn5rZFl2K6R78uMPVRgNxxQ4DaBgwMFjsJxBXq78K2va+wMpDVWXIcnpZCbcEchJ3Bt+aGQZ/BSId+WcNyT8SAvIwewt6+ZuklYqMqonTvfkPECTsqoxSHxQcYRXsnIANyQUaAtIwtwS0aLnoxfe2B/R0aHj7L+F0t9Wa/Jaq40m79ojk8bYOd7zfRuFWDj1Tf/FKFdubgIazWRPDi5QqQ+AAAAAElFTkSuQmCC);background-size:18px 16px;background-repeat:no-repeat;background-position:left center;line-height:16px;text-transform:uppercase;font-size:14px;font-weight:bold}.payment-process-notation-description{line-height:18px;font-size:12px}.payment-process-success{width:140px;height:146px;margin:0 auto 20px;background-image:url(../images/payment-success.png)}@media(min--moz-device-pixel-ratio:1.3),(-webkit-min-device-pixel-ratio:1.3),(min-device-pixel-ratio:1.3),(min-resolution:1.3dppx){.payment-process-success{background-image:url("../images/payment-success@2x.png");background-size:100% 100%}}.crowdsale,.process{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;position:absolute;height:50%;box-sizing:border-box}.home{min-height:600px}.crowdsale-modal{position:absolute;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.crowdsale-modal .modal{background:white;width:45%;min-width:830px;padding:30px 20px 20px;border-radius:10px;position:relative}.crowdsale-modal .modal .title{margin-bottom:20px;text-transform:uppercase;font-size:24px;font-weight:bold}.crowdsale-modal .modal .description{margin-bottom:25px;color:#8197a2;line-height:24px;font-size:13px}.crowdsale-modal .modal .close-button{position:absolute;top:-40px;right:-40px;z-index:400000;padding:15px}.crowdsale-modal .modal .close-button i.icon:before{content:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABkAAAAZCAYAAADE6YVjAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4gEDETQvtZKRngAAAaJJREFUSMetlcFOwkAURV9NXLjURUNwBbToTlJ04ULDJ7jSjd+hbvkEl3yC/2L8CRODBklMQAwJHhdO8VHeQFu5SdN0+jq3b+6dOyIiAgRAD2i6ZymD9DvgBLjXLwLgmV98AlFZEjdfAkzdfE/pYI9FTIBWSYJzltEVoOk6yBKFBQn2DYIPoJoWRG5ijbFr3auR0qADzDLf94HKvNBdLYNoBMSWGRTBsdHBEKiZPweErgMNrxmAthI5xQDYy+OO0TozeER+Aeq5vA7Eno5CJfK3IXIll/3VWjcM142BW4PgT+QiO9ddRwZRFu9ekQsQWmbQBLuyCQA3HpKrTRFUjY2mNQr/m6ZnhsgYrmutSoZVBIlHg0uPvRuFjgkXFVOfyM4Mlr3jvPukY3TQB2qZOsveIyDJE9ezPDvZadAwlm7ZDEoDXxZV1mgX+7JuwQwekQdAfdUaq2RIjI4mQKQP/alxHuyVSIaJ4brDLRG5FpFtVf8qIu0gCIZFSIIgeBORUxH5UsM7InKR/sVj4bj2L1+kXPeQLejOD/3yEZTeD4C7dPwHuOyCT59BxPUAAAAASUVORK5CYII=")}.crowdsale-modal .modal .close-button:hover{cursor:pointer}.crowdsale{top:0;padding-top:80px;text-align:center}.crowdsale .container{padding:0 40px;box-sizing:border-box}.crowdsale .title{margin-bottom:20px;text-transform:uppercase;font-size:24px;font-weight:bold}.crowdsale .description{margin-bottom:25px;color:#8197a2;line-height:24px;font-size:13px}.crowdsale .buttons{font-size:0}.crowdsale .button{margin:0 10px}@-webkit-keyframes show-process{from{opacity:0;-webkit-transform:scale(0);transform:scale(0)}to{opacity:1;transition:scale(1)}}@keyframes show-process{from{opacity:0;-webkit-transform:scale(0);transform:scale(0)}to{opacity:1;transition:scale(1)}}.process{bottom:0;padding-bottom:60px;background-color:#f5f5f7;font-size:0}.process .step-icons{-webkit-transform:translateX(-50%);transform:translateX(-50%);position:absolute;left:50%;top:0}.process .step-icons_crowdsale-page{top:10px}.process .process-item{opacity:0;-webkit-animation-name:show-process;animation-name:show-process;-webkit-animation-duration:1s;animation-duration:1s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;position:relative;display:inline-block;vertical-align:top;width:20%;padding:130px 10px 0;box-sizing:border-box;text-align:center}.process .process-item:nth-child(1){-webkit-animation-delay:200ms;animation-delay:200ms}.process .process-item:nth-child(1):after{content:"1"}.process .process-item:nth-child(2){-webkit-animation-delay:400ms;animation-delay:400ms}.process .process-item:nth-child(2):after{content:"2"}.process .process-item:nth-child(3){-webkit-animation-delay:600ms;animation-delay:600ms}.process .process-item:nth-child(3):after{content:"3"}.process .process-item:nth-child(4){-webkit-animation-delay:800ms;animation-delay:800ms}.process .process-item:nth-child(4):after{content:"4"}.process .process-item:nth-child(5){-webkit-animation-delay:1000ms;animation-delay:1000ms}.process .process-item:nth-child(5):after{content:"5"}.process .process-item:after{position:absolute;width:32px;height:32px;right:28px;top:-16px;border-radius:50%;border:4px solid #fff;background-color:#08b3f2;color:#fff;line-height:32px;text-align:center;font-size:14px;font-weight:bold}.process .title{margin-bottom:10px;text-transform:uppercase;font-size:14px;font-weight:bold}.process .description{color:#8197a2;line-height:18px;font-size:12px}.steps pre{display:block;overflow:auto;height:200px;padding:15px;box-sizing:border-box;border:1px solid #eee;border-radius:3px;font-size:14px;word-break:break-all;word-wrap:break-word;white-space:pre-wrap}.steps .button-container{margin:40px 0}.steps .value{margin-bottom:10px}.steps .left,.steps .right,.steps .item{margin-bottom:25px}.steps .publish-title{position:relative;z-index:2;display:inline-block;padding-right:5px;padding-left:30px;text-transform:uppercase;font-size:11px;font-weight:bold;background-color:#fff}.steps .publish-title-container{position:relative;margin-bottom:25px;line-height:20px}.steps .publish-title-container:after{content:"";position:absolute;z-index:1;right:0;left:0;top:50%;height:1px;margin-top:-1px;border-bottom:1px dashed #eee}.steps .publish-title:before{content:attr(data-step);position:absolute;z-index:2;left:0;top:50%;width:20px;height:20px;border-radius:50%;margin-top:-10px;background-color:#08b3f2;color:#fff;line-height:20px;text-align:center}.steps .button{padding-left:30px;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAUCAMAAACgaw2xAAAAMFBMVEX///////////////////////////////////////////////////////////////9Or7hAAAAAD3RSTlMAPT5BSUpRUt3f5ufp6vUxUI2NAAAASUlEQVR42rWROw7AMAxC3abN3+b+t80WZYAxb/STsAR2kr0+xnAgEhMVwryhTLpjvg5CFOugTCXc/sGj1PM7d12irl0Plb3taRdkbQmzeFkz0wAAAABJRU5ErkJggg==);background-size:12px 10px;background-repeat:no-repeat;background-position:left 10px center;cursor:pointer}.steps .button.no_image{padding-left:15px;background-image:none;background-position:0 0;background-size:auto}.steps-content{padding:30px 30px 0;border-radius:8px;border:1px solid #eee;background-color:#fff}.steps-content .about-step{position:relative;min-height:100px;padding-left:120px;padding-bottom:30px}.steps:not(.steps_publish) .steps-content .about-step{margin-bottom:30px;border-bottom:1px solid #eee}.steps-content .about-step .step-icons{position:absolute;left:0;top:0}.steps-content .about-step .title{display:block;margin-bottom:10px;text-transform:uppercase;font-size:20px;font-weight:bold}.steps-content .about-step .description{line-height:24px;font-size:13px}.steps-content .description{color:#8197a2;line-height:20px;font-size:12px}.steps-navigation{margin-bottom:30px;padding:30px 0;border-bottom:1px solid #eee;background-color:#fff}.steps-navigation .container{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}.steps-navigation .step-navigation{position:relative;padding-left:30px;color:#8197a2;text-transform:uppercase;line-height:20px;font-size:11px;font-weight:bold}.steps-navigation .step-navigation:nth-child(1):before{content:"1"}.steps-navigation .step-navigation:nth-child(2):before{content:"2"}.steps-navigation .step-navigation:nth-child(3):before{content:"3"}.steps-navigation .step-navigation:nth-child(4):before{content:"4"}.steps-navigation .step-navigation:nth-child(5):before{content:"5"}.steps-navigation .step-navigation:before{-webkit-transform:translateY(-50%);transform:translateY(-50%);position:absolute;width:20px;height:20px;left:0;top:50%;border-radius:50%;background-color:rgba(129,151,162,0.4);color:#fff;line-height:20px;text-align:center;font-size:11px;font-weight:bold}.steps-navigation .step-navigation_active{color:#333}.steps-navigation .step-navigation_active:before{background-color:#08b3f2}.steps .radios input{display:none}.steps .radios input:checked+.title:before{background-color:#642f9c}.steps .radio{cursor:pointer;position:relative;display:block;margin-bottom:60px;padding-left:45px}.steps .radio:not(:last-child):after{cursor:default;content:'';position:absolute;left:0;right:0;bottom:-29px;height:1px;background-color:#eee}.steps .radio:last-child{margin-bottom:30px}.steps .radio .title{position:relative;display:block;margin-bottom:5px;line-height:20px;text-transform:uppercase;font-weight:bold}.steps .radio .title:before{content:'';position:absolute;left:-45px;top:50%;width:10px;height:10px;margin-top:-5px;border:5px solid #fff;box-shadow:0 0 0 1px #cdd5da;border-radius:50%}.steps .radio .title_soon:after{content:'soon';display:inline-block;vertical-align:top;margin-left:5px;padding:0 5px;border-radius:2px;background-color:#642f9c;color:#fff;line-height:20px;text-transform:uppercase;font-size:10px;font-weight:bold}.steps .radio .description{color:#8197a2;line-height:20px;font-size:12px}.steps .radios-inline{height:36px;vertical-align:middle;margin-bottom:15px}.steps .radios-inline input{display:none}.steps .radios-inline input:checked+.title:before{background-color:#642f9c}.steps .radio-inline{cursor:pointer;position:relative;display:table-cell;padding-left:30px;padding-right:20px;line-height:36px}.steps .radio-inline:last-child{margin-bottom:30px}.steps .radio-inline .title{position:relative;display:block}.steps .radio-inline .title:before{content:'';position:absolute;left:-29px;top:50%;width:10px;height:10px;margin-top:-8.5px;border:5px solid #fff;box-shadow:0 0 0 1px #cdd5da;border-radius:50%}.reserved-tokens-title{display:block;margin-bottom:30px;text-transform:uppercase;font-size:20px;font-weight:bold}.reserved-tokens-container{margin-bottom:40px}.reserved-tokens-radio-container{height:36px;vertical-align:middle;display:table;width:100%;margin-bottom:15px}.reserved-tokens-radio-container-item{display:inline;line-height:36px;vertical-align:middle;margin-right:10px}.reserved-tokens-input-property{width:33%}.reserved-tokens-input-property-left{display:table-cell;vertical-align:top;padding-right:5px}.reserved-tokens-input-property-middle{display:table-cell;vertical-align:top;padding-left:5px;padding-right:5px}.reserved-tokens-input-property-right{display:table-cell;vertical-align:top;padding-left:5px}.reserved-tokens-input-container{margin-bottom:20px;display:table}.reserved-tokens-item{display:table-cell;height:60px;line-height:60px;width:33%}.reserved-tokens-item-left{padding-right:5px}.reserved-tokens-item-middle{padding-left:5px;padding-right:5px}.reserved-tokens-item-right{padding-left:5px}.reserved-tokens-item-empty{display:table-cell;line-height:60px;width:56px}.reserved-tokens-item-container{border-top:1px solid #eee;display:table;width:100%}.reserved-tokens-item-container-last{border-bottom:1px solid #eee}.reserved-tokens-item-container-inner{display:table;width:100%}.total-funds .right{text-align:right}.total-funds-title{margin-bottom:15px;color:#642f9c;font-size:24px;font-weight:bold}.total-funds-description{color:#8197a2;font-size:14px}.total-funds-chart{position:relative;z-index:1;height:20px;margin-bottom:30px;border-radius:10px;background-color:#f5f5f5}.total-funds-chart-active{position:absolute;left:0;top:0;bottom:0;border-radius:10px;background-image:linear-gradient(to right,#7738b9,#853ecf)}.total-funds-chart-container{position:relative}.total-funds-chart-division{position:absolute;z-index:0;top:-5px;bottom:-5px;width:1px;background-color:#ddd}.total-funds-chart-division:nth-child(1){left:10%}.total-funds-chart-division:nth-child(2){left:20%}.total-funds-chart-division:nth-child(3){left:30%}.total-funds-chart-division:nth-child(4){left:40%}.total-funds-chart-division:nth-child(5){left:50%}.total-funds-chart-division:nth-child(6){left:60%}.total-funds-chart-division:nth-child(7){left:70%}.total-funds-chart-division:nth-child(8){left:80%}.total-funds-chart-division:nth-child(9){left:90%}.total-funds-statistics .left,.total-funds-statistics .right{width:50%;box-sizing:border-box}.total-funds-statistics .title,.total-funds-statistics .hash{margin-bottom:10px;color:#642f9c;font-weight:bold}.total-funds-statistics .title{font-size:16px}.total-funds-statistics .hash{font-size:14px}.white-list-container{margin-bottom:40px}.white-list-input-property-left{display:table-cell;vertical-align:top;padding-right:5px;width:42%}.white-list-input-property-middle{display:table-cell;vertical-align:top;padding-left:5px;padding-right:5px;width:29%}.white-list-input-property-right{display:table-cell;vertical-align:top;padding-left:5px;width:29%}.white-list-input-container{margin-bottom:20px;display:table}.white-list-item{display:table-cell;height:60px;line-height:60px}.white-list-item-left{padding-right:5px;width:42%}.white-list-item-middle{padding-left:5px;padding-right:5px;width:29%}.white-list-item-right{padding-left:5px;width:29%}.white-list-item-empty{display:table-cell;width:56px}.white-list-item-container{border-top:1px solid #eee;display:table;width:100%}.white-list-item-container-last{border-bottom:1px solid #eee}.white-list-item-container-inner{display:table;width:100%}@-webkit-keyframes fadeOut{0%{opacity:.2}20%{opacity:1;-webkit-transform:scale(1);transform:scale(1)}100%{opacity:.2;-webkit-transform:scale(0.3);transform:scale(0.3)}}@keyframes fadeOut{0%{opacity:.2}20%{opacity:1;-webkit-transform:scale(1);transform:scale(1)}100%{opacity:.2;-webkit-transform:scale(0.3);transform:scale(0.3)}}.loading{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;position:absolute;left:50%;top:50%;width:206px;margin:-30px 0 0 -111.5px;padding-top:50px}.loading:before{content:'';position:absolute;left:0;top:0;width:206px;height:35px;background-image:url("../images/loading.png");background-position:0 0}@media(min--moz-device-pixel-ratio:1.3),(-webkit-min-device-pixel-ratio:1.3),(min-device-pixel-ratio:1.3),(min-resolution:1.3dppx){.loading:before{background-image:url("../images/loading@2x.png");background-size:100% 100%}}.loading-container{position:fixed;z-index:1000000;left:0;right:0;top:0;bottom:0;background-color:rgba(35,29,115,0.8)}.loading-text-container{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;position:absolute;left:50%;top:50%;width:206px;margin:-30px 0 0 -111.5px;padding-top:45px}.loading-text{color:white;font-weight:bold;text-align:justify;word-spacing:2px;width:100%;font-size:14.2px}.loading-progress{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;position:absolute;left:50%;top:50%;width:206px;margin:-30px 0 0 -111.5px;padding-top:70px}.loading-i{-webkit-animation-duration:2s;animation-duration:2s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-iteration-count:infinite;animation-iteration-count:infinite;-webkit-animation-name:fadeOut;animation-name:fadeOut;-webkit-animation-timing-function:linear;animation-timing-function:linear;opacity:.2;width:9px;height:9px;border-radius:50%;background-color:#fff}.loading-i:nth-child(2){-webkit-animation-delay:.1s;animation-delay:.1s}.loading-i:nth-child(3){-webkit-animation-delay:.2s;animation-delay:.2s}.loading-i:nth-child(4){-webkit-animation-delay:.3s;animation-delay:.3s}.loading-i:nth-child(5){-webkit-animation-delay:.4s;animation-delay:.4s}.loading-i:nth-child(6){-webkit-animation-delay:.5s;animation-delay:.5s}.flex-table .container-fluid{position:relative;width:100%}.flex-table .table-row{display:-webkit-box;display:-ms-flexbox;display:flex;display:-webkit-flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-webkit-box-flex:0;-ms-flex-positive:0;flex-grow:0;-webkit-flex-grow:0;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-flex-wrap:wrap;width:100%;padding-left:15px;padding-right:15px}.flex-table .sm-text,.flex-table .text{-webkit-box-flex:2;-ms-flex-positive:2;flex-grow:2;padding-right:0}.flex-table .sm-text{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-webkit-flex-grow:1}.flex-table .text{width:260px}.flex-table .sm-text{width:100px}.flex-table .num{width:80px}.flex-table .table-row{border-collapse:collapse;padding-bottom:15px;padding-top:15px;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.flex-table .table-row.flex-table-header{padding-top:8px;padding-bottom:8px;width:99%}.flex-table .table-row.selected{background-color:#08b3f2;color:#fff}.flex-table .table-row.clickable:hover{cursor:pointer}.flex-table .table-row.datagrid{padding-bottom:5px;padding-top:5px}.flex-table .table-row.datagrid:nth-child(even){background-color:#e8e8e8}.flex-table .scrollable-content{border:1px solid lightgray;min-height:185px;max-height:600px;overflow-x:hidden;overflow-y:auto}.flex-table .scrollable-content::-webkit-scrollbar{width:5px}.flex-table .scrollable-content::-webkit-scrollbar-track{border-left:1px solid lightgray;padding:3px}.flex-table .scrollable-content::-webkit-scrollbar-thumb{background:lightgray}.flex-table .steps{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;margin-top:3%}.manage{min-height:600px}.manage .warning-logo{color:#642f9c !important;border-color:#642f9c !important;position:absolute !important;left:0 !important;top:0 !important;display:-webkit-box;display:-ms-flexbox;display:flex}.manage .steps-content{margin-top:30px}.manage .description{margin-bottom:20px}.manage .crowdsale-page-link{color:#08b3f2;text-decoration:none;font-size:13px}.manage .divisor{margin-bottom:30px;border-bottom:1px solid #eee}.manage .no-arrow{background-image:none;padding:0 15px} \ No newline at end of file +.header,.footer,.crowdsale,.process{left:0;right:0}.header .logo,.footer .logo{display:block;background-image:url(../images/logos.png)}@media(min--moz-device-pixel-ratio:1.3),(-webkit-min-device-pixel-ratio:1.3),(min-device-pixel-ratio:1.3),(min-resolution:1.3dppx){.header .logo,.footer .logo{background-image:url("../images/logos@2x.png");background-size:182px 59px}}@font-face{font-family:'Open Sans';font-style:normal;font-weight:400;src:local("Open Sans"),local("OpenSans"),url(https://fonts.gstatic.com/s/opensans/v13/cJZKeOuBrn4kERxqtaUH3ZBw1xU1rKptJj_0jans920.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2212,U+2215,U+E0FF,U+EFFD,U+F000}@font-face{font-family:'Open Sans';font-style:normal;font-weight:700;src:local("Open Sans Bold"),local("OpenSans-Bold"),url(https://fonts.gstatic.com/s/opensans/v13/k3k702ZOKiLJc3WVjuplzBampu5_7CjHW5spxoeN3Vs.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2212,U+2215,U+E0FF,U+EFFD,U+F000}html,body{color:#333;line-height:1;font-size:14px;font-family:'Open Sans',sans-serif;-webkit-font-smoothing:antialiased}html,body{margin:0;padding:0}p,h1,h2,h3,h4{margin:0;padding:0;font-family:'Open Sans',sans-serif}html{height:100%}body{position:relative;width:100%;min-width:1000px;min-height:100%;box-sizing:border-box;padding:80px 0 60px;background-color:#fbfbfc}.container{width:960px;margin:0 auto;box-sizing:border-box}.hidden{overflow:hidden}.notdisplayed{display:none}.left{width:46%;float:left}.right{width:46%;float:right}.item-remove{background-image:url(../images/delete.png);background-repeat:no-repeat;display:block;width:12px;height:12px;cursor:pointer;float:right}@media(min--moz-device-pixel-ratio:1.3),(-webkit-min-device-pixel-ratio:1.3),(min-device-pixel-ratio:1.3),(min-resolution:1.3dppx){.item-remove{background-image:url("../images/delete@2x.png");background-size:12px 12px}}.copy{background-image:url(../images/copy.png);background-repeat:no-repeat;display:block;width:12px;height:12px;cursor:pointer;float:right}@media(min--moz-device-pixel-ratio:1.3),(-webkit-min-device-pixel-ratio:1.3),(min-device-pixel-ratio:1.3),(min-resolution:1.3dppx){.copy{background-image:url("../images/copy@2x.png");background-size:12px 12px}}.copy-field-container{display:table-cell;padding-left:10px;vertical-align:top;padding-top:30.5px}.copy-area-container{display:table-cell;padding-left:10px}.display-container{display:table-cell;width:100%}.input-block-container{display:table;width:100%}.section-title{display:block;margin-bottom:30px;text-transform:uppercase;font-size:20px;font-weight:bold}@media(max-height:600px){body{padding-top:0}}.header{position:absolute;top:0;height:80px;background-image:url(../images/bg.png);background-size:cover;background-position:center center}.header .logo{width:182px;height:35px;margin-top:22.5px;background-position:0 -25px}@media(max-height:600px){.header{position:relative;top:0;height:auto;padding:1px 0 21px}}.footer{position:absolute;bottom:0;height:60px;background-image:url(../images/bg.png);background-size:cover;background-position:center center;color:#fff}.footer .container{position:relative}.footer .logo,.footer .socials{-webkit-transform:translateY(-50%);transform:translateY(-50%);position:absolute;z-index:1;top:50%}.footer .logo{left:0;width:126px;height:24px;background-position:0 0}.footer .rights{color:#fff;line-height:60px;text-align:center;font-size:12px}.footer .socials{right:0}.socials{font-size:0}.socials .social{transition:.3s background-color;position:relative;display:inline-block;vertical-align:top;width:30px;height:30px;border-radius:50%;background-color:rgba(255,255,255,0.2)}.socials .social:not(:first-child){margin-left:10px}.socials .social:hover{background-color:rgba(255,255,255,0.4)}.socials .social:before{-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);content:'';position:absolute;left:50%;top:50%;background-image:url(../images/socials.png)}@media(min--moz-device-pixel-ratio:1.3),(-webkit-min-device-pixel-ratio:1.3),(min-device-pixel-ratio:1.3),(min-resolution:1.3dppx){.socials .social:before{background-image:url("../images/socials@2x.png");background-size:16px 69px}}.socials .social_github:before{width:16px;height:16px;background-position:0 0}.socials .social_oracles:before{width:16px;height:14px;background-position:0 -16px}.socials .social_reddit:before{width:15px;height:13px;background-position:0 -30px}.socials .social_telegram:before{width:16px;height:14px;background-position:0 -43px}.socials .social_twitter:before{width:15px;height:12px;background-position:0 -57px}.step-icons{background-image:url(../images/step-icons.png)}@media(min--moz-device-pixel-ratio:1.3),(-webkit-min-device-pixel-ratio:1.3),(min-device-pixel-ratio:1.3),(min-resolution:1.3dppx){.step-icons{background-image:url("../images/step-icons@2x.png");background-size:100px 480px}}.step-icons_crowdsale-contract{width:80px;height:100px;background-position:0 0}.step-icons_crowdsale-page{width:100px;height:80px;background-position:0 -100px}.step-icons_crowdsale-setup{width:88px;height:100px;background-position:0 -180px}.step-icons_publish{width:100px;height:100px;background-position:0 -280px}.step-icons_token-setup{width:100px;height:100px;background-position:0 -380px}.button{cursor:pointer;display:inline-block;transition:.3s background-color,0.3s color;border-radius:3px;box-sizing:border-box;padding:0 15px;line-height:36px;font-size:13px;text-decoration:none;text-transform:uppercase;font-weight:bold}.button-container{text-align:center}.button_fill{background-color:#08b3f2;color:#fff}.button_fill:hover{background-color:#34c3f8;cursor:pointer}.button_disabled{background-color:#e6e6e6;color:#9c9c9c}.button_disabled:hover{cursor:default !important}.button_fill_secondary{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAAAFVBMVEX///////////////////////////9nSIHRAAAABnRSTlMASUrk5udXTd49AAAAOUlEQVR42tXQsQEAIAgDQcAn+4+snRZxAK79KokrIcNBwgYdc0Migwxk8Qsd1TJWDf/KQWobqt+9G4coA99W7as5AAAAAElFTkSuQmCC) !important;background-color:#64299d;color:#fff;margin-right:10px}.button_fill_secondary:hover{background-color:#752fb6}.button_fill_plus{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAAAFVBMVEX///////////////////////////9nSIHRAAAABnRSTlMASUrk5udXTd49AAAAOUlEQVR42tXQsQEAIAgDQcAn+4+snRZxAK79KokrIcNBwgYdc0Migwxk8Qsd1TJWDf/KQWobqt+9G4coA99W7as5AAAAAElFTkSuQmCC) !important;width:36px;height:36px;padding-left:0 !important;background-position:center center !important}.button_outline{box-shadow:inset 0 0 0 2px #08b3f2;color:#08b3f2}.button_outline:hover{background-color:#08b3f2;color:#fff}.plus-button-container{display:table-cell;padding-left:20px;padding-top:28.5px;vertical-align:top}.label{display:block;margin-bottom:15px;text-transform:uppercase;font-weight:bold}.input{transition:.3s border-color;width:100%;height:36px;margin-bottom:15px;outline:0;border:1px solid #eee;box-sizing:border-box;border-radius:3px;padding:0 10px;color:#333;font-size:14px;font-family:'Open Sans',sans-serif}.input:focus{border-color:#08b3f2}.input:disabled{background:#f2f2f2}.invest{margin:30px auto;padding-left:30px;border-radius:8px;border:1px solid #eee;background-color:#fff}.invest .timer{position:absolute;z-index:2;left:25px;top:25px;width:180px;height:180px;border-radius:50%;background-color:#fff;line-height:180px;text-align:center}.invest .timer-inner{line-height:normal;display:inline-block}.invest .timer-i{display:inline-block;vertical-align:middle;margin:0 5px;font-size:0;text-align:center}.invest .timer-count{display:block;margin-bottom:5px;color:#642f9c;font-size:24px;font-weight:bold}.invest .timer-interval{display:block;text-transform:uppercase;font-size:10px;color:#8197a2}.invest .timer-container{position:absolute;z-index:1;left:0;top:30px;border-radius:50%;background-color:#eee}.invest .hashes{position:relative;min-height:240px;padding-left:260px}.invest .hashes-i{margin-bottom:30px}.invest .hashes-title{margin-bottom:10px;color:#642f9c;font-weight:bold}.invest .hashes-description{color:#8197a2;font-size:12px}.invest .balance{border-bottom:1px solid #eee;padding:30px}.invest .balance-title{margin-bottom:5px;color:#642f9c;font-size:20px;font-weight:bold}.invest .balance-description{margin-bottom:30px;color:#8197a2}.invest .description{color:#8197a2;line-height:20px;font-size:12px}.invest-through{-webkit-appearance:none;-moz-appearance:none;appearance:none;float:left;height:36px;outline:0;padding:0 28px 0 10px;box-sizing:border-box;border:1px solid #eee;border-radius:3px;background-image:url(../images/select.png);background-repeat:no-repeat;background-position:center right 10px;background-color:#fff;color:#8197a2;font-size:12px}@media(min--moz-device-pixel-ratio:1.3),(-webkit-min-device-pixel-ratio:1.3),(min-device-pixel-ratio:1.3),(min-resolution:1.3dppx){.invest-through{background-image:url("../images/select@2x.png");background-size:8px 5px}}.invest-through-container{overflow:hidden;margin-bottom:30px}.invest-form{padding:30px}.invest-form ::-webkit-input-placeholder{color:#8197a2}.invest-form :-ms-input-placeholder{color:#8197a2}.invest-form ::placeholder{color:#8197a2}.invest-form-label{color:#8197a2}.invest-form-input{display:block;width:100%;height:44px;outline:0;padding-right:30px;border:0;border-bottom:1px solid #eee;box-sizing:border-box;color:#8197a2;font-size:14px;font-weight:bold}.invest-form-input-container{position:relative;margin:15px 0 50px}.invest-form-input-container .invest-form-label{-webkit-transform:translateY(-50%);transform:translateY(-50%);position:absolute;right:0;top:50%}.invest-form-input-container .error{color:red;font-weight:bold;font-size:12px;width:100%;height:10px;position:absolute;margin-top:5px}.invest-form .button{float:right}.invest-title{margin-bottom:10px;color:#333;text-transform:uppercase;font-weight:bold}.invest-description{margin-bottom:30px;color:#8197a2;line-height:18px;font-size:12px}.invest-table{display:table;width:100%}.invest-table-cell{display:table-cell}.invest-table-cell_left{position:relative;width:600px;padding-right:30px;border-right:1px solid #eee}@media(max-height:600px){.invest .qr-selected .balance-description{margin-bottom:0}.invest .qr-selected .description{display:none}.invest .qr-selected .invest-form{padding-bottom:0}.invest .qr-selected .invest-form-label{display:none}.invest .qr-selected .invest-form-input-container{display:none}.invest .qr-selected .payment-process{padding-top:5px}}@-webkit-keyframes paymentLoading{from{-webkit-transform:rotate(0);transform:rotate(0)}to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes paymentLoading{from{-webkit-transform:rotate(0);transform:rotate(0)}to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}.payment-process{padding:30px}.payment-process-qr{display:block;width:140px;margin:0 auto 20px}.payment-process-description{margin-bottom:10px;color:#8197a2;line-height:18px;font-size:13px}.payment-process-hash{margin-bottom:15px;color:#642f9c;word-break:break-all;line-height:20px;font-size:14px;font-weight:bold}.payment-process-copy,.payment-process-see{display:inline-block;margin-bottom:20px;padding-left:20px;background-position:left center;background-repeat:no-repeat;color:#642f9c;text-decoration:none;line-height:14px;font-size:13px}.payment-process-copy:hover,.payment-process-see:hover{text-decoration:underline}.payment-process-copy{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAMAAABF0y+mAAAAFVBMVEVlKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ4g+6HIAAAABnRSTlMASUrk5udXTd49AAAAS0lEQVR42sXSQQoAIAhEUTP1/kduNSIlIUT1t281KKEmNiXNERbV0ZLqSKGLmO4DpvscLamOFPqC6AR1g52f3vH862Q1dWSdrTNsAP8SCeaGkeh2AAAAAElFTkSuQmCC);background-size:14px 14px}.payment-process-see{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAUCAMAAACpgK3LAAAAvVBMVEVlKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ6cDY85AAAAPnRSTlMAAgYHCAkQESElJygpLzAxQkNITlBRUlZXW1xdXmFjZGVnaWqTo6WorcTFxtXa29ze3+Hi7/Dx8vP19vn8/uFjRaQAAADzSURBVHjafVLXEoIwEDxQERF7b6goGsFeUMTw/5/lnbEQRt0HZjcbdq4E3lDrzioIVk5DhSQUax89cRgqsqcvohhcPe6VT5GEU/njdUM68Wwzky3ZHvGw8/J6HOWy+pLVJUreE6J2QzFNAeSY77McQGqKB7caeYUAmYXEOFLg0UBq4f2gAKBt0WsDgoliGPEWujsN5qgnQPCFeXkIG9kMZvi1f5naDmMHydjBI1YUxCk4LwrK038cCypKrRjsfGYGtcJFK4T+tyH05fG5YzOdNscu8bD7Z/AVaWVe3PP0xLJHh/eyRwokoTac9fW6cZqfZ3IHucE/W04kek0AAAAASUVORK5CYII=);background-size:14px 10px}.payment-process-loader{position:relative;margin-bottom:20px;padding-left:20px;color:#8197a2;font-size:13px}.payment-process-loader:before{-webkit-animation-duration:1s;animation-duration:1s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-iteration-count:infinite;animation-iteration-count:infinite;-webkit-animation-name:paymentLoading;animation-name:paymentLoading;-webkit-animation-timing-function:linear;animation-timing-function:linear;content:"";position:absolute;left:0;top:50%;width:14px;height:14px;margin-top:-7px;background-image:url(../images/payment-loader.png)}@media(min--moz-device-pixel-ratio:1.3),(-webkit-min-device-pixel-ratio:1.3),(min-device-pixel-ratio:1.3),(min-resolution:1.3dppx){.payment-process-loader:before{background-image:url("../images/payment-loader@2x.png");background-size:100% 100%}}.payment-process-notation{border-radius:5px;border:1px solid #6d2eae;padding:10px;background-color:rgba(109,46,174,0.1);color:#6d2eae}.payment-process-notation-title{margin-bottom:5px;padding-left:28px;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAgCAMAAABNTyq8AAABX1BMVEVlKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ5lKZ52EUWdAAAAdHRSTlMAAQIEBQcJCgsMDQ4SExUYGx4gISIoKjAxMzY4Oz1AQUtOT1VbXF5haW1ub3Byc3R1eHl7fH2CiImKi4yVlpeZm6Cjpaeoqq+0tre5usLExcbJysvQ0dLT1dbX2Nna29zh4uPn7O/w8fLz9PX29/n6+/z9/n/AovIAAAE8SURBVHgBhcGJmwoBHMfhj1Ub1rLY3PctdyTkJgclHSTkFiKpvv//s83RNL+npt4Xa/FSpfW3nIoxw2pdrvIKkTY15avFiZJTIEOEZFeBP9uYrqCQx0x1TMYhpkh81lA+AUtPNfQ2xqRrcpwCOCvHBSbs6MhxBeC6HD+3AtYTue4CPJLrPliH5XkOUJJrsA8j3pSnAfBVnuoCYZflawOxnnynCVn5rZFl2K6R78uMPVRgNxxQ4DaBgwMFjsJxBXq78K2va+wMpDVWXIcnpZCbcEchJ3Bt+aGQZ/BSId+WcNyT8SAvIwewt6+ZuklYqMqonTvfkPECTsqoxSHxQcYRXsnIANyQUaAtIwtwS0aLnoxfe2B/R0aHj7L+F0t9Wa/Jaq40m79ojk8bYOd7zfRuFWDj1Tf/FKFdubgIazWRPDi5QqQ+AAAAAElFTkSuQmCC);background-size:18px 16px;background-repeat:no-repeat;background-position:left center;line-height:16px;text-transform:uppercase;font-size:14px;font-weight:bold}.payment-process-notation-description{line-height:18px;font-size:12px}.payment-process-success{width:140px;height:146px;margin:0 auto 20px;background-image:url(../images/payment-success.png)}@media(min--moz-device-pixel-ratio:1.3),(-webkit-min-device-pixel-ratio:1.3),(min-device-pixel-ratio:1.3),(min-resolution:1.3dppx){.payment-process-success{background-image:url("../images/payment-success@2x.png");background-size:100% 100%}}.crowdsale,.process{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;position:absolute;height:50%;box-sizing:border-box}.home{min-height:600px}.crowdsale-modal{position:absolute;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.crowdsale-modal .modal{background:white;width:45%;min-width:830px;padding:30px 20px 20px;border-radius:10px;position:relative}.crowdsale-modal .modal .title{margin-bottom:20px;text-transform:uppercase;font-size:24px;font-weight:bold}.crowdsale-modal .modal .description{margin-bottom:25px;color:#8197a2;line-height:24px;font-size:13px}.crowdsale-modal .modal .close-button{position:absolute;top:-40px;right:-40px;z-index:400000;padding:15px}.crowdsale-modal .modal .close-button i.icon:before{content:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABkAAAAZCAYAAADE6YVjAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4gEDETQvtZKRngAAAaJJREFUSMetlcFOwkAURV9NXLjURUNwBbToTlJ04ULDJ7jSjd+hbvkEl3yC/2L8CRODBklMQAwJHhdO8VHeQFu5SdN0+jq3b+6dOyIiAgRAD2i6ZymD9DvgBLjXLwLgmV98AlFZEjdfAkzdfE/pYI9FTIBWSYJzltEVoOk6yBKFBQn2DYIPoJoWRG5ijbFr3auR0qADzDLf94HKvNBdLYNoBMSWGRTBsdHBEKiZPweErgMNrxmAthI5xQDYy+OO0TozeER+Aeq5vA7Eno5CJfK3IXIll/3VWjcM142BW4PgT+QiO9ddRwZRFu9ekQsQWmbQBLuyCQA3HpKrTRFUjY2mNQr/m6ZnhsgYrmutSoZVBIlHg0uPvRuFjgkXFVOfyM4Mlr3jvPukY3TQB2qZOsveIyDJE9ezPDvZadAwlm7ZDEoDXxZV1mgX+7JuwQwekQdAfdUaq2RIjI4mQKQP/alxHuyVSIaJ4brDLRG5FpFtVf8qIu0gCIZFSIIgeBORUxH5UsM7InKR/sVj4bj2L1+kXPeQLejOD/3yEZTeD4C7dPwHuOyCT59BxPUAAAAASUVORK5CYII=")}.crowdsale-modal .modal .close-button:hover{cursor:pointer}.crowdsale{top:0;padding-top:80px;text-align:center}.crowdsale .container{padding:0 40px;box-sizing:border-box}.crowdsale .title{margin-bottom:20px;text-transform:uppercase;font-size:24px;font-weight:bold}.crowdsale .description{margin-bottom:25px;color:#8197a2;line-height:24px;font-size:13px}.crowdsale .buttons{font-size:0}.crowdsale .button{margin:0 10px}@-webkit-keyframes show-process{from{opacity:0;-webkit-transform:scale(0);transform:scale(0)}to{opacity:1;transition:scale(1)}}@keyframes show-process{from{opacity:0;-webkit-transform:scale(0);transform:scale(0)}to{opacity:1;transition:scale(1)}}.process{bottom:0;padding-bottom:60px;background-color:#f5f5f7;font-size:0}.process .step-icons{-webkit-transform:translateX(-50%);transform:translateX(-50%);position:absolute;left:50%;top:0}.process .step-icons_crowdsale-page{top:10px}.process .process-item{opacity:0;-webkit-animation-name:show-process;animation-name:show-process;-webkit-animation-duration:1s;animation-duration:1s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;position:relative;display:inline-block;vertical-align:top;width:20%;padding:130px 10px 0;box-sizing:border-box;text-align:center}.process .process-item:nth-child(1){-webkit-animation-delay:200ms;animation-delay:200ms}.process .process-item:nth-child(1):after{content:"1"}.process .process-item:nth-child(2){-webkit-animation-delay:400ms;animation-delay:400ms}.process .process-item:nth-child(2):after{content:"2"}.process .process-item:nth-child(3){-webkit-animation-delay:600ms;animation-delay:600ms}.process .process-item:nth-child(3):after{content:"3"}.process .process-item:nth-child(4){-webkit-animation-delay:800ms;animation-delay:800ms}.process .process-item:nth-child(4):after{content:"4"}.process .process-item:nth-child(5){-webkit-animation-delay:1000ms;animation-delay:1000ms}.process .process-item:nth-child(5):after{content:"5"}.process .process-item:after{position:absolute;width:32px;height:32px;right:28px;top:-16px;border-radius:50%;border:4px solid #fff;background-color:#08b3f2;color:#fff;line-height:32px;text-align:center;font-size:14px;font-weight:bold}.process .title{margin-bottom:10px;text-transform:uppercase;font-size:14px;font-weight:bold}.process .description{color:#8197a2;line-height:18px;font-size:12px}.steps pre{display:block;overflow:auto;height:200px;padding:15px;box-sizing:border-box;border:1px solid #eee;border-radius:3px;font-size:14px;word-break:break-all;word-wrap:break-word;white-space:pre-wrap}.steps .button-container{margin:40px 0}.steps .value{margin-bottom:10px}.steps .left,.steps .right,.steps .item{margin-bottom:25px}.steps .publish-title{position:relative;z-index:2;display:inline-block;padding-right:5px;padding-left:30px;text-transform:uppercase;font-size:11px;font-weight:bold;background-color:#fff}.steps .publish-title-container{position:relative;margin-bottom:25px;line-height:20px}.steps .publish-title-container:after{content:"";position:absolute;z-index:1;right:0;left:0;top:50%;height:1px;margin-top:-1px;border-bottom:1px dashed #eee}.steps .publish-title:before{content:attr(data-step);position:absolute;z-index:2;left:0;top:50%;width:20px;height:20px;border-radius:50%;margin-top:-10px;background-color:#08b3f2;color:#fff;line-height:20px;text-align:center}.steps .button{padding-left:30px;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAUCAMAAACgaw2xAAAAMFBMVEX///////////////////////////////////////////////////////////////9Or7hAAAAAD3RSTlMAPT5BSUpRUt3f5ufp6vUxUI2NAAAASUlEQVR42rWROw7AMAxC3abN3+b+t80WZYAxb/STsAR2kr0+xnAgEhMVwryhTLpjvg5CFOugTCXc/sGj1PM7d12irl0Plb3taRdkbQmzeFkz0wAAAABJRU5ErkJggg==);background-size:12px 10px;background-repeat:no-repeat;background-position:left 10px center;cursor:pointer}.steps .button.no_image{padding-left:15px;background-image:none;background-position:0 0;background-size:auto}.steps-content{padding:30px 30px 0;border-radius:8px;border:1px solid #eee;background-color:#fff}.steps-content .about-step{position:relative;min-height:100px;padding-left:120px;padding-bottom:30px}.steps:not(.steps_publish) .steps-content .about-step{margin-bottom:30px;border-bottom:1px solid #eee}.steps-content .about-step .step-icons{position:absolute;left:0;top:0}.steps-content .about-step .title{display:block;margin-bottom:10px;text-transform:uppercase;font-size:20px;font-weight:bold}.steps-content .about-step .description{line-height:24px;font-size:13px}.steps-content .description{color:#8197a2;line-height:20px;font-size:12px}.steps-navigation{margin-bottom:30px;padding:30px 0;border-bottom:1px solid #eee;background-color:#fff}.steps-navigation .container{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}.steps-navigation .step-navigation{position:relative;padding-left:30px;color:#8197a2;text-transform:uppercase;line-height:20px;font-size:11px;font-weight:bold}.steps-navigation .step-navigation:nth-child(1):before{content:"1"}.steps-navigation .step-navigation:nth-child(2):before{content:"2"}.steps-navigation .step-navigation:nth-child(3):before{content:"3"}.steps-navigation .step-navigation:nth-child(4):before{content:"4"}.steps-navigation .step-navigation:nth-child(5):before{content:"5"}.steps-navigation .step-navigation:before{-webkit-transform:translateY(-50%);transform:translateY(-50%);position:absolute;width:20px;height:20px;left:0;top:50%;border-radius:50%;background-color:rgba(129,151,162,0.4);color:#fff;line-height:20px;text-align:center;font-size:11px;font-weight:bold}.steps-navigation .step-navigation_active{color:#333}.steps-navigation .step-navigation_active:before{background-color:#08b3f2}.steps .radios input{display:none}.steps .radios input:checked+.title:before{background-color:#642f9c}.steps .radio{cursor:pointer;position:relative;display:block;margin-bottom:60px;padding-left:45px}.steps .radio:not(:last-child):after{cursor:default;content:'';position:absolute;left:0;right:0;bottom:-29px;height:1px;background-color:#eee}.steps .radio:last-child{margin-bottom:30px}.steps .radio .title{position:relative;display:block;margin-bottom:5px;line-height:20px;text-transform:uppercase;font-weight:bold}.steps .radio .title:before{content:'';position:absolute;left:-45px;top:50%;width:10px;height:10px;margin-top:-5px;border:5px solid #fff;box-shadow:0 0 0 1px #cdd5da;border-radius:50%}.steps .radio .title_soon:after{content:'soon';display:inline-block;vertical-align:top;margin-left:5px;padding:0 5px;border-radius:2px;background-color:#642f9c;color:#fff;line-height:20px;text-transform:uppercase;font-size:10px;font-weight:bold}.steps .radio .description{color:#8197a2;line-height:20px;font-size:12px}.steps .radios-inline{height:36px;vertical-align:middle;margin-bottom:15px}.steps .radios-inline input{display:none}.steps .radios-inline input:checked+.title:before{background-color:#642f9c}.steps .radio-inline{cursor:pointer;position:relative;display:table-cell;padding-left:30px;padding-right:20px;line-height:36px}.steps .radio-inline:last-child{margin-bottom:30px}.steps .radio-inline .title{position:relative;display:block}.steps .radio-inline .title:before{content:'';position:absolute;left:-29px;top:50%;width:10px;height:10px;margin-top:-8.5px;border:5px solid #fff;box-shadow:0 0 0 1px #cdd5da;border-radius:50%}.reserved-tokens-title{display:block;margin-bottom:30px;text-transform:uppercase;font-size:20px;font-weight:bold}.reserved-tokens-container{margin-bottom:40px}.reserved-tokens-radio-container{height:36px;vertical-align:middle;display:table;width:100%;margin-bottom:15px}.reserved-tokens-radio-container-item{display:inline;line-height:36px;vertical-align:middle;margin-right:10px}.reserved-tokens-input-property{width:33%}.reserved-tokens-input-property-left{display:table-cell;vertical-align:top;padding-right:5px}.reserved-tokens-input-property-middle{display:table-cell;vertical-align:top;padding-left:5px;padding-right:5px}.reserved-tokens-input-property-right{display:table-cell;vertical-align:top;padding-left:5px}.reserved-tokens-input-container{margin-bottom:20px;display:table}.reserved-tokens-item{display:table-cell;height:60px;line-height:60px;width:33%}.reserved-tokens-item-left{padding-right:5px}.reserved-tokens-item-middle{padding-left:5px;padding-right:5px}.reserved-tokens-item-right{padding-left:5px}.reserved-tokens-item-empty{display:table-cell;line-height:60px;width:56px}.reserved-tokens-item-container{border-top:1px solid #eee;display:table;width:100%}.reserved-tokens-item-container-last{border-bottom:1px solid #eee}.reserved-tokens-item-container-inner{display:table;width:100%}.total-funds .right{text-align:right}.total-funds-title{margin-bottom:15px;color:#642f9c;font-size:24px;font-weight:bold}.total-funds-description{color:#8197a2;font-size:14px}.total-funds-chart{position:relative;z-index:1;height:20px;margin-bottom:30px;border-radius:10px;background-color:#f5f5f5}.total-funds-chart-active{position:absolute;left:0;top:0;bottom:0;border-radius:10px;background-image:linear-gradient(to right,#7738b9,#853ecf)}.total-funds-chart-container{position:relative}.total-funds-chart-division{position:absolute;z-index:0;top:-5px;bottom:-5px;width:1px;background-color:#ddd}.total-funds-chart-division:nth-child(1){left:10%}.total-funds-chart-division:nth-child(2){left:20%}.total-funds-chart-division:nth-child(3){left:30%}.total-funds-chart-division:nth-child(4){left:40%}.total-funds-chart-division:nth-child(5){left:50%}.total-funds-chart-division:nth-child(6){left:60%}.total-funds-chart-division:nth-child(7){left:70%}.total-funds-chart-division:nth-child(8){left:80%}.total-funds-chart-division:nth-child(9){left:90%}.total-funds-statistics .left,.total-funds-statistics .right{width:50%;box-sizing:border-box}.total-funds-statistics .title,.total-funds-statistics .hash{margin-bottom:10px;color:#642f9c;font-weight:bold}.total-funds-statistics .title{font-size:16px}.total-funds-statistics .hash{font-size:14px}.white-list-container{margin-bottom:40px}.white-list-input-property-left{display:table-cell;vertical-align:top;padding-right:5px;width:42%}.white-list-input-property-middle{display:table-cell;vertical-align:top;padding-left:5px;padding-right:5px;width:29%}.white-list-input-property-right{display:table-cell;vertical-align:top;padding-left:5px;width:29%}.white-list-input-container{margin-bottom:20px;display:table}.white-list-item{display:table-cell;height:60px;line-height:60px}.white-list-item-left{padding-right:5px;width:42%}.white-list-item-middle{padding-left:5px;padding-right:5px;width:29%}.white-list-item-right{padding-left:5px;width:29%}.white-list-item-empty{display:table-cell;width:56px}.white-list-item-container{font-weight:bold;border-top:1px solid #eee;display:table;width:100%}.white-list-item-container-last{border-bottom:1px solid #eee}.white-list-item-container-inner{display:table;width:100%}.white-list-item-container.to-be-removed{font-weight:normal;color:orange;text-decoration:line-through}.white-list-item-container.stored{font-weight:normal;color:#555}.white-list-item-container.no-style{font-weight:normal;color:#555}.white-list-item-container.duplicated{padding-bottom:15px;border-top:1px dashed orange;margin-top:-15px}.white-list-item-container.duplicated span{line-height:30px;height:12px}@-webkit-keyframes fadeOut{0%{opacity:.2}20%{opacity:1;-webkit-transform:scale(1);transform:scale(1)}100%{opacity:.2;-webkit-transform:scale(0.3);transform:scale(0.3)}}@keyframes fadeOut{0%{opacity:.2}20%{opacity:1;-webkit-transform:scale(1);transform:scale(1)}100%{opacity:.2;-webkit-transform:scale(0.3);transform:scale(0.3)}}.loading{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;position:absolute;left:50%;top:50%;width:206px;margin:-30px 0 0 -111.5px;padding-top:50px}.loading:before{content:'';position:absolute;left:0;top:0;width:206px;height:35px;background-image:url("../images/loading.png");background-position:0 0}@media(min--moz-device-pixel-ratio:1.3),(-webkit-min-device-pixel-ratio:1.3),(min-device-pixel-ratio:1.3),(min-resolution:1.3dppx){.loading:before{background-image:url("../images/loading@2x.png");background-size:100% 100%}}.loading-container{position:fixed;z-index:1000000;left:0;right:0;top:0;bottom:0;background-color:rgba(35,29,115,0.8)}.loading-text-container{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;position:absolute;left:50%;top:50%;width:206px;margin:-30px 0 0 -111.5px;padding-top:45px}.loading-text{color:white;font-weight:bold;text-align:justify;word-spacing:2px;width:100%;font-size:14.2px}.loading-progress{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;position:absolute;left:50%;top:50%;width:206px;margin:-30px 0 0 -111.5px;padding-top:70px}.loading-i{-webkit-animation-duration:2s;animation-duration:2s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-iteration-count:infinite;animation-iteration-count:infinite;-webkit-animation-name:fadeOut;animation-name:fadeOut;-webkit-animation-timing-function:linear;animation-timing-function:linear;opacity:.2;width:9px;height:9px;border-radius:50%;background-color:#fff}.loading-i:nth-child(2){-webkit-animation-delay:.1s;animation-delay:.1s}.loading-i:nth-child(3){-webkit-animation-delay:.2s;animation-delay:.2s}.loading-i:nth-child(4){-webkit-animation-delay:.3s;animation-delay:.3s}.loading-i:nth-child(5){-webkit-animation-delay:.4s;animation-delay:.4s}.loading-i:nth-child(6){-webkit-animation-delay:.5s;animation-delay:.5s}.flex-table .container-fluid{position:relative;width:100%}.flex-table .table-row{display:-webkit-box;display:-ms-flexbox;display:flex;display:-webkit-flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-webkit-box-flex:0;-ms-flex-positive:0;flex-grow:0;-webkit-flex-grow:0;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-flex-wrap:wrap;width:100%;padding-left:15px;padding-right:15px}.flex-table .sm-text,.flex-table .text{-webkit-box-flex:2;-ms-flex-positive:2;flex-grow:2;padding-right:0}.flex-table .sm-text{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-webkit-flex-grow:1}.flex-table .text{width:260px}.flex-table .sm-text{width:100px}.flex-table .num{width:80px}.flex-table .table-row{border-collapse:collapse;padding-bottom:15px;padding-top:15px;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.flex-table .table-row.flex-table-header{padding-top:8px;padding-bottom:8px;width:99%}.flex-table .table-row.selected{background-color:#08b3f2;color:#fff}.flex-table .table-row.clickable:hover{cursor:pointer}.flex-table .table-row.datagrid{padding-bottom:5px;padding-top:5px}.flex-table .table-row.datagrid:nth-child(even){background-color:#e8e8e8}.flex-table .scrollable-content{border:1px solid lightgray;min-height:185px;max-height:600px;overflow-x:hidden;overflow-y:auto}.flex-table .scrollable-content::-webkit-scrollbar{width:5px}.flex-table .scrollable-content::-webkit-scrollbar-track{border-left:1px solid lightgray;padding:3px}.flex-table .scrollable-content::-webkit-scrollbar-thumb{background:lightgray}.flex-table .steps{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;margin-top:3%}.manage{min-height:600px}.manage .warning-logo{color:#642f9c !important;border-color:#642f9c !important;position:absolute;left:0;top:0;display:-webkit-box;display:-ms-flexbox;display:flex}.manage .white-list-item-container .remove{display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;margin-top:8px}.manage .white-list-item-container .swal2-icon{width:14px;height:14px;line-height:14px;border:2px solid transparent}.manage .white-list-item-container .warning-logo{color:orange !important;border-color:orange !important;position:relative;float:right;font-size:14px;font-weight:bold}.manage .steps-content{margin-top:30px}.manage .description{margin-bottom:20px}.manage .crowdsale-page-link{color:#08b3f2;text-decoration:none;font-size:13px}.manage .divisor{margin-bottom:30px;border-bottom:1px solid #eee}.manage .no-arrow{background-image:none;padding:0 15px} \ No newline at end of file diff --git a/src/assets/stylesheets/application/manage.scss b/src/assets/stylesheets/application/manage.scss index 131c5b615..60577ba1c 100644 --- a/src/assets/stylesheets/application/manage.scss +++ b/src/assets/stylesheets/application/manage.scss @@ -4,12 +4,35 @@ .warning-logo { color: #642F9C !important; border-color: #642F9C !important; - position: absolute !important; - left: 0 !important; - top: 0 !important; + position: absolute; + left: 0; + top: 0; display: flex; } + .white-list-item-container { + .remove { + display: inline-flex; + margin-top: 8px; + } + + .swal2-icon { + width: 14px; + height: 14px; + line-height: 14px; + border: 2px solid transparent; + } + + .warning-logo { + color: orange !important; + border-color: orange !important; + position: relative; + float: right; + font-size: 14px; + font-weight: bold; + } + } + .steps-content { margin-top: 30px; } diff --git a/src/assets/stylesheets/application/steps/whitelist.scss b/src/assets/stylesheets/application/steps/whitelist.scss index 5ff5712aa..af07b037a 100644 --- a/src/assets/stylesheets/application/steps/whitelist.scss +++ b/src/assets/stylesheets/application/steps/whitelist.scss @@ -58,6 +58,7 @@ } &-container { + font-weight: bold; border-top: 1px solid #eee; display: table; width: 100%; @@ -70,6 +71,28 @@ display: table; width: 100%; } + + &.to-be-removed { + font-weight: normal; + color: orange; + text-decoration: line-through; + } + + &.no-style { + font-weight: normal; + color: #555555; + } + + &.duplicated { + padding-bottom: 15px; + border-top: 1px dashed orange; + margin-top: -15px; + + span { + line-height: 30px; + height: 12px; + } + } } } } diff --git a/src/components/Common/WhitelistItem.js b/src/components/Common/WhitelistItem.js index 7c04ac0a5..0ddc42d59 100644 --- a/src/components/Common/WhitelistItem.js +++ b/src/components/Common/WhitelistItem.js @@ -1,6 +1,8 @@ import React from 'react' import '../../assets/stylesheets/application.css'; import { inject, observer } from 'mobx-react' +import classNames from 'classnames' +import ReactTooltip from 'react-tooltip' @inject('tierStore') @observer @@ -11,11 +13,14 @@ export class WhitelistItem extends React.Component { } render () { - const { addr, min, max, alreadyDeployed } = this.props + const { addr, min, max, alreadyDeployed, duplicated } = this.props return ( -
+
{addr} {min} @@ -26,7 +31,15 @@ export class WhitelistItem extends React.Component { ? this.removeItem(addr)}> : null } + {duplicated && !alreadyDeployed + ? ! + : null + }
+ +

Address already loaded,

+

saving will overwrite old values

+
) } diff --git a/src/components/manage/index.js b/src/components/manage/index.js index 349aea30a..8cb47f14b 100644 --- a/src/components/manage/index.js +++ b/src/components/manage/index.js @@ -410,7 +410,7 @@ export class Manage extends Component { } return tier.whitelist.map(item => ( -
+
{item.addr} {item.min} From 9e5ddd2d8d23c660794da0bdec69c493d0dc760f Mon Sep 17 00:00:00 2001 From: fernandomg Date: Thu, 8 Mar 2018 15:49:14 -0300 Subject: [PATCH 05/16] Fix 'removeWhitelistItem' method --- src/components/Common/WhitelistInputBlock.js | 3 ++- src/components/Common/WhitelistItem.js | 8 ++++---- src/stores/TierStore.js | 10 ++++++---- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/components/Common/WhitelistInputBlock.js b/src/components/Common/WhitelistInputBlock.js index dd0e5ec9b..73821a000 100644 --- a/src/components/Common/WhitelistInputBlock.js +++ b/src/components/Common/WhitelistInputBlock.js @@ -152,10 +152,11 @@ export class WhitelistInputBlock extends React.Component { />
- {whitelist.length > 0 && whitelist.map(item => + {whitelist.length > 0 && whitelist.map((item, index) => )} diff --git a/src/components/Common/WhitelistItem.js b/src/components/Common/WhitelistItem.js index 0ddc42d59..f637fa48c 100644 --- a/src/components/Common/WhitelistItem.js +++ b/src/components/Common/WhitelistItem.js @@ -7,9 +7,9 @@ import ReactTooltip from 'react-tooltip' @inject('tierStore') @observer export class WhitelistItem extends React.Component { - removeItem (address) { - const { tierStore, crowdsaleNum } = this.props - tierStore.removeWhitelistItem(address, crowdsaleNum) + removeItem () { + const { tierStore, whitelistNum, crowdsaleNum } = this.props + tierStore.removeWhitelistItem(whitelistNum, crowdsaleNum) } render () { @@ -28,7 +28,7 @@ export class WhitelistItem extends React.Component {
{!alreadyDeployed - ? this.removeItem(addr)}> + ? this.removeItem()} className="remove"> : null } {duplicated && !alreadyDeployed diff --git a/src/stores/TierStore.js b/src/stores/TierStore.js index a9caa1aa1..84c0712d5 100644 --- a/src/stores/TierStore.js +++ b/src/stores/TierStore.js @@ -190,11 +190,13 @@ class TierStore { whitelist.push(newItem) } - @action removeWhitelistItem = (address, crowdsaleNum) => { - const addressIndex = this.tiers[crowdsaleNum].whitelist.findIndex(item => item.addr === address) + @action removeWhitelistItem = (whitelistNum, crowdsaleNum) => { + const removedItem = this.tiers[crowdsaleNum].whitelist.splice(whitelistNum, 1)[0] - if (addressIndex > -1) { - this.tiers[crowdsaleNum].whitelist.splice(addressIndex, 1) + if (this.deployedContract && removedItem.duplicated) { + const alreadyDeployedIndex = this.tiers[crowdsaleNum].whitelist.findIndex(item => item.addr === removedItem.addr) + + if (alreadyDeployedIndex > -1) this.tiers[crowdsaleNum].whitelist[alreadyDeployedIndex].duplicated = false } } From 8f59f3213b96d2c74224ff4c927adc6221688975 Mon Sep 17 00:00:00 2001 From: fernandomg Date: Thu, 8 Mar 2018 15:52:02 -0300 Subject: [PATCH 06/16] Rename 'alreadyDeployed' to 'stored' --- src/components/Common/WhitelistInputBlock.js | 2 +- src/components/Common/WhitelistItem.js | 12 ++++++------ src/components/manage/utils.js | 2 +- src/stores/TierStore.js | 14 +++++++------- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/components/Common/WhitelistInputBlock.js b/src/components/Common/WhitelistInputBlock.js index 73821a000..65b9e6654 100644 --- a/src/components/Common/WhitelistInputBlock.js +++ b/src/components/Common/WhitelistInputBlock.js @@ -154,7 +154,7 @@ export class WhitelistInputBlock extends React.Component {
{whitelist.length > 0 && whitelist.map((item, index) =>
{addr} @@ -27,11 +27,11 @@ export class WhitelistItem extends React.Component { {max}
- {!alreadyDeployed + {!stored ? this.removeItem()} className="remove"> : null } - {duplicated && !alreadyDeployed + {duplicated && !stored ? ! : null } diff --git a/src/components/manage/utils.js b/src/components/manage/utils.js index 8e438d87c..eeb01cba4 100644 --- a/src/components/manage/utils.js +++ b/src/components/manage/utils.js @@ -299,7 +299,7 @@ export const processTier = (crowdsaleAddress, crowdsaleNum) => { min = parseInt(toFixed(min), 10) / 10 ** tokenDecimals max = parseInt(toFixed(max), 10) / 10 ** tokenDecimals - whitelist.push({ addr, min, max, alreadyDeployed: true }) + whitelist.push({ addr, min, max, stored: true }) }) tierStore.setTierProperty(whitelist, 'whitelist', crowdsaleNum) diff --git a/src/stores/TierStore.js b/src/stores/TierStore.js index 84c0712d5..a92cdd3e7 100644 --- a/src/stores/TierStore.js +++ b/src/stores/TierStore.js @@ -174,13 +174,13 @@ class TierStore { const isAdded = whitelist.find(item => item.addr.toLowerCase() === _addr) if (this.deployedContract) { - const alreadyDeployedIndex = whitelist.findIndex(item => item.addr.toLowerCase() === _addr && item.alreadyDeployed) - const duplicatedIndex = whitelist.findIndex(item => item.addr.toLowerCase() === _addr && !item.alreadyDeployed && item.duplicated) + const storedIndex = whitelist.findIndex(item => item.addr.toLowerCase() === _addr && item.stored) + const duplicatedIndex = whitelist.findIndex(item => item.addr.toLowerCase() === _addr && !item.stored && item.duplicated) if (duplicatedIndex > -1) return - if (alreadyDeployedIndex > -1) { - whitelist[alreadyDeployedIndex].duplicated = true + if (storedIndex > -1) { + whitelist[storedIndex].duplicated = true newItem.duplicated = true } else if (isAdded) return @@ -194,9 +194,9 @@ class TierStore { const removedItem = this.tiers[crowdsaleNum].whitelist.splice(whitelistNum, 1)[0] if (this.deployedContract && removedItem.duplicated) { - const alreadyDeployedIndex = this.tiers[crowdsaleNum].whitelist.findIndex(item => item.addr === removedItem.addr) + const storedIndex = this.tiers[crowdsaleNum].whitelist.findIndex(item => item.addr === removedItem.addr) - if (alreadyDeployedIndex > -1) this.tiers[crowdsaleNum].whitelist[alreadyDeployedIndex].duplicated = false + if (storedIndex > -1) this.tiers[crowdsaleNum].whitelist[storedIndex].duplicated = false } } @@ -205,7 +205,7 @@ class TierStore { } @computed get deployedContract () { - return this.tiers.some(tier => tier.whitelist.some(item => item.alreadyDeployed)) + return this.tiers.some(tier => tier.whitelist.some(item => item.stored)) } } From bca2fdc8e1ae319d18f96e92113ba5ee77c6fe02 Mon Sep 17 00:00:00 2001 From: fernandomg Date: Thu, 8 Mar 2018 16:16:16 -0300 Subject: [PATCH 07/16] Sort whitelist alphabetically --- src/components/manage/utils.js | 1 + src/stores/TierStore.js | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/src/components/manage/utils.js b/src/components/manage/utils.js index eeb01cba4..d0c276489 100644 --- a/src/components/manage/utils.js +++ b/src/components/manage/utils.js @@ -303,6 +303,7 @@ export const processTier = (crowdsaleAddress, crowdsaleNum) => { }) tierStore.setTierProperty(whitelist, 'whitelist', crowdsaleNum) + tierStore.sortWhitelist(crowdsaleNum) if (initialValues.updatable) { initialValues.startTime = newTier.startTime diff --git a/src/stores/TierStore.js b/src/stores/TierStore.js index a92cdd3e7..06ecd30b1 100644 --- a/src/stores/TierStore.js +++ b/src/stores/TierStore.js @@ -188,6 +188,16 @@ class TierStore { } else if (isAdded) return whitelist.push(newItem) + this.sortWhitelist(crowdsaleNum) + } + + @action sortWhitelist = (crowdsaleNum) => { + this.tiers[crowdsaleNum].whitelist = this.tiers[crowdsaleNum].whitelist.sort((prev, curr) => { + const currentAddress = curr.addr.toLowerCase() + const previousAddress = prev.addr.toLowerCase() + + return currentAddress > previousAddress ? -1 : currentAddress === previousAddress ? curr.stored ? 1 : -1 : 1 + }) } @action removeWhitelistItem = (whitelistNum, crowdsaleNum) => { From 163962fc67f05ff2b7a24f8584d4540707e3879e Mon Sep 17 00:00:00 2001 From: fernandomg Date: Thu, 8 Mar 2018 16:23:40 -0300 Subject: [PATCH 08/16] Fix whitelist styling --- src/components/Common/WhitelistItem.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/Common/WhitelistItem.js b/src/components/Common/WhitelistItem.js index 113069270..a9b621784 100644 --- a/src/components/Common/WhitelistItem.js +++ b/src/components/Common/WhitelistItem.js @@ -13,13 +13,13 @@ export class WhitelistItem extends React.Component { } render () { - const { addr, min, max, stored, duplicated } = this.props + const { addr, min, max, stored, duplicated, tierStore } = this.props return (
{addr} From b2b98d44c5e422b5db89f11e43246e88b26bdf0e Mon Sep 17 00:00:00 2001 From: fernandomg Date: Thu, 8 Mar 2018 17:43:43 -0300 Subject: [PATCH 09/16] Fix removeWhitelistItem addresses comparison --- src/stores/TierStore.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/stores/TierStore.js b/src/stores/TierStore.js index 06ecd30b1..e456a6766 100644 --- a/src/stores/TierStore.js +++ b/src/stores/TierStore.js @@ -204,7 +204,8 @@ class TierStore { const removedItem = this.tiers[crowdsaleNum].whitelist.splice(whitelistNum, 1)[0] if (this.deployedContract && removedItem.duplicated) { - const storedIndex = this.tiers[crowdsaleNum].whitelist.findIndex(item => item.addr === removedItem.addr) + const removedAddr = removedItem.addr.toLowerCase() + const storedIndex = this.tiers[crowdsaleNum].whitelist.findIndex(item => item.addr.toLowerCase() === removedAddr) if (storedIndex > -1) this.tiers[crowdsaleNum].whitelist[storedIndex].duplicated = false } From a93cbb9b14d276096204063bd976357ed0363c47 Mon Sep 17 00:00:00 2001 From: fernandomg Date: Thu, 8 Mar 2018 18:13:07 -0300 Subject: [PATCH 10/16] Modify how to check the "ready to save" status of manage form for whitelist edition --- src/components/manage/index.js | 34 +++++++++++++++++++--------------- src/stores/TierStore.js | 4 ++++ 2 files changed, 23 insertions(+), 15 deletions(-) diff --git a/src/components/manage/index.js b/src/components/manage/index.js index 8cb47f14b..50a08baae 100644 --- a/src/components/manage/index.js +++ b/src/components/manage/index.js @@ -18,6 +18,7 @@ import { toast } from '../../utils/utils' import { getWhiteListWithCapCrowdsaleAssets } from '../../stores/utils' import { getTiers, processTier, updateTierAttribute } from './utils' import { Loader } from '../Common/Loader' +import classNames from 'classnames' const { START_TIME, END_TIME, RATE, SUPPLY, WALLET_ADDRESS, CROWDSALE_SETUP_NAME } = TEXT_FIELDS @@ -331,11 +332,12 @@ export class Manage extends Component { this.updateCrowdsaleStatus() .then(() => { const { crowdsaleStore, tierStore } = this.props + const { formPristine, crowdsaleHasEnded } = this.state const updatableTiers = crowdsaleStore.selected.initialTiersValues.filter(tier => tier.updatable) const isValidTier = tierStore.individuallyValidTiers const validTiers = updatableTiers.every(tier => isValidTier[tier.index]) - if (!this.state.formPristine && !this.state.crowdsaleHasEnded && updatableTiers.length && validTiers) { + if ((!formPristine || tierStore.modifiedStoredWhitelist) && !crowdsaleHasEnded && updatableTiers.length && validTiers) { const keys = Object .keys(updatableTiers[0]) .filter(key => key !== 'index' && key !== 'updatable' && key !== 'addresses') @@ -383,12 +385,6 @@ export class Manage extends Component { }) } - clickedWhiteListInputBlock = e => { - if (e.target.classList.contains('button_fill_plus')) { - this.setState({ formPristine: false }) - } - } - whitelistInputBlock = index => { return ( +

Whitelist

@@ -514,12 +510,20 @@ export class Manage extends Component {
) - const saveButton = ( - this.saveCrowdsale(e)}> - Save - - ) + const saveButton = () => { + let buttonStyle = 'button_disabled' + + if (ownerCurrentUser && (!formPristine || tierStore.modifiedStoredWhitelist) && !crowdsaleHasEnded) { + buttonStyle = 'button_fill' + } + + return ( + this.saveCrowdsale(e)}> + Save + + ) + } const tierNameAndWallet = (tier) => { return
@@ -619,7 +623,7 @@ export class Manage extends Component { ))}
- {!crowdsaleHasEnded && updatable ? saveButton : null} + {!crowdsaleHasEnded && updatable ? saveButton() : null}
diff --git a/src/stores/TierStore.js b/src/stores/TierStore.js index e456a6766..4cbf65dfd 100644 --- a/src/stores/TierStore.js +++ b/src/stores/TierStore.js @@ -218,6 +218,10 @@ class TierStore { @computed get deployedContract () { return this.tiers.some(tier => tier.whitelist.some(item => item.stored)) } + + @computed get modifiedStoredWhitelist () { + return this.deployedContract && this.tiers.some(tier => tier.whitelist.some(item => !item.stored)) + } } export default TierStore; From 7897082269f3da71777b0e996ef2c66859348275 Mon Sep 17 00:00:00 2001 From: fernandomg Date: Thu, 8 Mar 2018 18:14:27 -0300 Subject: [PATCH 11/16] Fix whitelist items to be saved filter --- src/components/manage/index.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/components/manage/index.js b/src/components/manage/index.js index 50a08baae..957fbb206 100644 --- a/src/components/manage/index.js +++ b/src/components/manage/index.js @@ -349,11 +349,10 @@ export class Manage extends Component { let newValue = tierStore.tiers[tier.index][key] if (isObservableArray(newValue)) { - if (newValue.length > tier[key].length) { - newValue = newValue.slice(tier[key].length) - if (newValue.length) { - toUpdate.push({ key, newValue, addresses }) - } + newValue = newValue.filter(item => !item.stored) + + if (newValue.length) { + toUpdate.push({ key, newValue, addresses }) } } else if (newValue !== tier[key]) { From 01cb352dd5ae28711c98d81a3b55cacebcb7ac38 Mon Sep 17 00:00:00 2001 From: fernandomg Date: Fri, 9 Mar 2018 15:59:22 -0300 Subject: [PATCH 12/16] Fix unnecessary whitelist length check --- src/components/Common/WhitelistInputBlock.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Common/WhitelistInputBlock.js b/src/components/Common/WhitelistInputBlock.js index 65b9e6654..05fa418b6 100644 --- a/src/components/Common/WhitelistInputBlock.js +++ b/src/components/Common/WhitelistInputBlock.js @@ -152,7 +152,7 @@ export class WhitelistInputBlock extends React.Component { />
- {whitelist.length > 0 && whitelist.map((item, index) => + {whitelist && whitelist.map((item, index) => Date: Mon, 12 Mar 2018 11:26:19 -0300 Subject: [PATCH 13/16] Remove unreached condition --- src/stores/TierStore.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/stores/TierStore.js b/src/stores/TierStore.js index 4cbf65dfd..267113cf9 100644 --- a/src/stores/TierStore.js +++ b/src/stores/TierStore.js @@ -182,8 +182,7 @@ class TierStore { if (storedIndex > -1) { whitelist[storedIndex].duplicated = true newItem.duplicated = true - - } else if (isAdded) return + } } else if (isAdded) return From 4d66cc4040524729e4c2446cb1093646f1a49672 Mon Sep 17 00:00:00 2001 From: fernandomg Date: Mon, 12 Mar 2018 11:26:32 -0300 Subject: [PATCH 14/16] Add TierStore tests --- src/stores/TierStore.spec.js | 181 ++++++++++++++++++++++++++++++++++- 1 file changed, 180 insertions(+), 1 deletion(-) diff --git a/src/stores/TierStore.spec.js b/src/stores/TierStore.spec.js index 1bb2d8bee..0dce5d887 100644 --- a/src/stores/TierStore.spec.js +++ b/src/stores/TierStore.spec.js @@ -1,6 +1,30 @@ import TierStore from './TierStore' describe('TierStore', () => { + let whitelist + let tierStore + + beforeEach(() => { + tierStore = new TierStore() + + whitelist = [ + { addr: '0x90f8bf6a479f320ead074411a4b0e7944ea8c9c1', min: 1234, max: 50505 }, + { addr: '0xffcf8fdee72ac11b5c542428b35eef5769c409f0', min: 1234, max: 50505 }, + { addr: '0x22d491bde2303f2f43325b2108d26f1eaba1e32b', min: 1234, max: 50505 }, + { addr: '0xe11ba2b4d45eaed5996cd0823791e0c93114882d', min: 1234, max: 50505 }, + { addr: '0xd03ea8624c8c5987235048901fb614fdca89b117', min: 1234, max: 50505 }, + { addr: '0x95ced938f7991cd0dfcb48f0a06a40fa1af46ebc', min: 1234, max: 50505 }, + { addr: '0x3e5e9111ae8eb78fe1cc3bb8915d5d461f3ef9a9', min: 1234, max: 50505 }, + { addr: '0x28a8746e75304c0780e011bed21c72cd78cd535e', min: 1234, max: 50505 }, + { addr: '0xaca94ef8bd5ffee41947b4585a84bda5a3d3da6e', min: 1234, max: 50505 }, + { addr: '0x1df62f291b2e969fb0849d99d9ce41e2f137006e', min: 1234, max: 50505 }, + ] + }) + + afterEach(() => { + tierStore.reset() + }) + describe('maxSupply', () => { const testCases = [{ tiers: [], @@ -21,7 +45,6 @@ describe('TierStore', () => { testCases.forEach(({ tiers, expected }) => { it(`should get the max supply for tiers ${JSON.stringify(tiers)}`, () => { - const tierStore = new TierStore() tierStore.emptyList() tiers.forEach(tier => tierStore.addTier({ @@ -34,4 +57,160 @@ describe('TierStore', () => { }) }) }) + + describe('sortWhitelist', () => { + let sortedWhitelist + + beforeEach(() => { + sortedWhitelist = [ + { addr: '0x1df62f291b2e969fb0849d99d9ce41e2f137006e', min: 1234, max: 50505 }, + { addr: '0x22d491bde2303f2f43325b2108d26f1eaba1e32b', min: 1234, max: 50505 }, + { addr: '0x28a8746e75304c0780e011bed21c72cd78cd535e', min: 1234, max: 50505 }, + { addr: '0x3e5e9111ae8eb78fe1cc3bb8915d5d461f3ef9a9', min: 1234, max: 50505 }, + { addr: '0x90f8bf6a479f320ead074411a4b0e7944ea8c9c1', min: 1234, max: 50505 }, + { addr: '0x95ced938f7991cd0dfcb48f0a06a40fa1af46ebc', min: 1234, max: 50505 }, + { addr: '0xaca94ef8bd5ffee41947b4585a84bda5a3d3da6e', min: 1234, max: 50505 }, + { addr: '0xd03ea8624c8c5987235048901fb614fdca89b117', min: 1234, max: 50505 }, + { addr: '0xe11ba2b4d45eaed5996cd0823791e0c93114882d', min: 1234, max: 50505 }, + { addr: '0xffcf8fdee72ac11b5c542428b35eef5769c409f0', min: 1234, max: 50505 }, + ] + }) + + it('Should sort in ascending order', () => { + tierStore.setTierProperty(whitelist, 'whitelist', 0) + tierStore.sortWhitelist(0) + tierStore.tiers[0].whitelist.forEach((item, index) => { + expect(item.addr).toBe(sortedWhitelist[index].addr) + }) + }) + + it('Should sort in ascending order after adding a duplicated address', () => { + const sortedWhitelistWithDuplicated = [ + { addr: '0x1df62f291b2e969fb0849d99d9ce41e2f137006e', min: 1234, max: 50505 }, + { addr: '0x22d491bde2303f2f43325b2108d26f1eaba1e32b', min: 1234, max: 50505 }, + { addr: '0x28a8746e75304c0780e011bed21c72cd78cd535e', min: 1234, max: 50505 }, + { addr: '0x3e5e9111ae8eb78fe1cc3bb8915d5d461f3ef9a9', min: 1234, max: 50505 }, + { addr: '0x90f8bf6a479f320ead074411a4b0e7944ea8c9c1', min: 1234, max: 50505 }, + { addr: '0x90f8bf6a479f320ead074411a4b0e7944ea8c9c1', min: 2222, max: 44444 }, + { addr: '0x95ced938f7991cd0dfcb48f0a06a40fa1af46ebc', min: 1234, max: 50505 }, + { addr: '0xaca94ef8bd5ffee41947b4585a84bda5a3d3da6e', min: 1234, max: 50505 }, + { addr: '0xd03ea8624c8c5987235048901fb614fdca89b117', min: 1234, max: 50505 }, + { addr: '0xe11ba2b4d45eaed5996cd0823791e0c93114882d', min: 1234, max: 50505 }, + { addr: '0xffcf8fdee72ac11b5c542428b35eef5769c409f0', min: 1234, max: 50505 }, + ] + const duplicatedAddress = { addr: '0x90f8bf6a479f320ead074411a4b0e7944ea8c9c1', min: 2222, max: 44444 } + + tierStore.setTierProperty(whitelist.map(item => { + item.stored = true + return item + }), 'whitelist', 0) + tierStore.sortWhitelist(0) + tierStore.addWhitelistItem(duplicatedAddress, 0) + + tierStore.tiers[0].whitelist.forEach((item, index) => { + expect(item.addr).toBe(sortedWhitelistWithDuplicated[index].addr) + expect(item.min).toBe(sortedWhitelistWithDuplicated[index].min) + expect(item.max).toBe(sortedWhitelistWithDuplicated[index].max) + }) + }) + }) + + describe('removeWhitelistItem', () => { + it('Should remove the address from the list', () => { + whitelist.forEach(item => tierStore.addWhitelistItem(item, 0)) + tierStore.removeWhitelistItem(8, 0) + + const itemLookup = tierStore.tiers[0].whitelist + .find(item => item.addr === '0xe11ba2b4d45eaed5996cd0823791e0c93114882d') + + expect(itemLookup).toBeUndefined() + }) + + it('Should set duplicated to false for the stored address, after removing its duplicate', () => { + const duplicatedAddress = { addr: '0xffcf8fdee72ac11b5c542428b35eef5769c409f0', min: 2222, max: 44444 } + + tierStore.setTierProperty(whitelist.map(item => { + item.stored = true + return item + }), 'whitelist', 0) + tierStore.sortWhitelist(0) + tierStore.addWhitelistItem(duplicatedAddress, 0) + tierStore.removeWhitelistItem(10, 0) + + expect(tierStore.tiers[0].whitelist[1].duplicated).toBeFalsy() + }) + }) + + it('Should be truthy "deployedContract" after adding "stored" addresses', () => { + // set whitelist items as stored + tierStore.setTierProperty(whitelist.map(item => { + item.stored = true + return item + }), 'whitelist', 0) + expect(tierStore.deployedContract).toBeTruthy() + }) + + it('Should mark repeated addresses as duplicated', () => { + const duplicatedAddress = { addr: '0xffcf8fdee72ac11b5c542428b35eef5769c409f0', min: 2222, max: 44444 } + + // set whitelist items as stored + tierStore.setTierProperty(whitelist.map(item => { + item.stored = true + return item + }), 'whitelist', 0) + tierStore.sortWhitelist(0) + + expect(tierStore.tiers[0].whitelist.every(item => item.stored)).toBeTruthy() + tierStore.addWhitelistItem(duplicatedAddress, 0) + + const storedIndex = tierStore.tiers[0].whitelist.findIndex(item => item.addr === duplicatedAddress.addr) + + expect(tierStore.tiers[0].whitelist[storedIndex].duplicated).toBeTruthy() + expect(tierStore.tiers[0].whitelist[10].duplicated).toBeTruthy() + }) + + it('Should prevent adding an already duplicated address', () => { + const firstAddr = { addr: '0xffcf8fdee72ac11b5c542428b35eef5769c409f0', min: 2222, max: 44444 } + const secondAddr = { addr: '0xffcf8fdee72ac11b5c542428b35eef5769c409f0', min: 7777, max: 44444 } + + tierStore.setTierProperty(whitelist.map(item => { + item.stored = true + return item + }), 'whitelist', 0) + tierStore.sortWhitelist(0) + + tierStore.addWhitelistItem(firstAddr, 0) + expect(tierStore.tiers[0].whitelist.length).toBe(11) + + tierStore.addWhitelistItem(secondAddr, 0) + expect(tierStore.tiers[0].whitelist.length).toBe(11) + expect(tierStore.tiers[0].whitelist[10].min).toBe(firstAddr.min) + }) + + it('Should prevent adding a duplicated address for a non-stored list', () => { + const duplicatedAddress = { addr: '0xffcf8fdee72ac11b5c542428b35eef5769c409f0', min: 2222, max: 44444 } + + whitelist.forEach(item => tierStore.addWhitelistItem(item, 0)) + expect(tierStore.tiers[0].whitelist.length).toBe(10) + tierStore.addWhitelistItem(duplicatedAddress, 0) + expect(tierStore.tiers[0].whitelist.length).toBe(10) + + }) + + it('Should set as modified the whitelist if an address was added to an "stored" list', () => { + const duplicatedAddress = { addr: '0xffcf8fdee72ac11b5c542428b35eef5769c409f0', min: 2222, max: 44444 } + + tierStore.setTierProperty(whitelist.map(item => { + item.stored = true + return item + }), 'whitelist', 0) + tierStore.sortWhitelist(0) + + expect(tierStore.modifiedStoredWhitelist).toBeFalsy() + + tierStore.addWhitelistItem(duplicatedAddress, 0) + + expect(tierStore.modifiedStoredWhitelist).toBeTruthy() + }) + }) From 1272d8860a0f082c5c1e23058aa98b421228007b Mon Sep 17 00:00:00 2001 From: fernandomg Date: Tue, 13 Mar 2018 11:44:09 -0300 Subject: [PATCH 15/16] Conflict resolution after merge with master --- package-lock.json | 2 +- src/components/crowdsale/index.js | 2 +- src/components/stepFour/utils.js | 4 ++-- src/components/stepThree/index.js | 36 ++++++++++++------------------- src/stores/TierStore.spec.js | 2 ++ 5 files changed, 20 insertions(+), 26 deletions(-) diff --git a/package-lock.json b/package-lock.json index 12980e439..62739cb6a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12771,7 +12771,7 @@ "integrity": "sha1-A38495fD5rG1jSU0zMjCx2r09S0=", "requires": { "classnames": "2.2.5", - "prop-types": "15.6.0" + "prop-types": "15.6.1" } }, "react-transition-group": { diff --git a/src/components/crowdsale/index.js b/src/components/crowdsale/index.js index 3240986ea..b2eebc31f 100644 --- a/src/components/crowdsale/index.js +++ b/src/components/crowdsale/index.js @@ -10,7 +10,7 @@ import { initializeAccumulativeData, toBigNumber } from './utils' -import { getQueryVariable, toFixed } from '../../utils/utils' +import { getQueryVariable } from '../../utils/utils' import { getWhiteListWithCapCrowdsaleAssets } from '../../stores/utils' import { StepNavigation } from '../Common/StepNavigation' import { CONTRACT_TYPES, NAVIGATION_STEPS } from '../../utils/constants' diff --git a/src/components/stepFour/utils.js b/src/components/stepFour/utils.js index a83bf112f..8f4c02441 100644 --- a/src/components/stepFour/utils.js +++ b/src/components/stepFour/utils.js @@ -8,8 +8,8 @@ import { sendTXToContract } from '../../utils/blockchainHelpers' import { noContractAlert, noContractDataAlert } from '../../utils/alerts' -import { countDecimalPlaces, floorToDecimals, toFixed } from '../../utils/utils' -import { CONTRACT_TYPES, DOWNLOAD_NAME, TRUNC_TO_DECIMALS } from '../../utils/constants' +import { countDecimalPlaces, toFixed } from '../../utils/utils' +import { CONTRACT_TYPES, DOWNLOAD_NAME } from '../../utils/constants' import { isObservableArray } from 'mobx' import { contractStore, diff --git a/src/components/stepThree/index.js b/src/components/stepThree/index.js index 9abfa6d60..2e12d470b 100644 --- a/src/components/stepThree/index.js +++ b/src/components/stepThree/index.js @@ -72,28 +72,20 @@ export class stepThree extends React.Component { componentDidMount () { const { gasPriceStore } = this.props - addCrowdsale() { - const { crowdsaleBlockListStore, tierStore } = this.props; - let num = crowdsaleBlockListStore.blockList.length + 1; - const newTier = { - tier: "Tier " + (num + 1), - supply: 0, - rate: 0, - updatable: "off", - whitelist: [] - }; - - const newTierValidations = { - tier: VALID, - startTime: VALID, - endTime: VALID, - supply: EMPTY, - rate: EMPTY - }; - - tierStore.addTier(newTier); - tierStore.addTierValidations(newTierValidations); - this.addCrowdsaleBlock(num); + gasPriceStore.updateValues() + .then(() => this.setGasPrice(gasPriceStore.slow)) + .catch(() => noGasPriceAvailable()) + .then(() => { + this.addCrowdsale() + this.setState({ loading: false }) + window.scrollTo(0, 0) + }) + } + + showErrorMessages = () => { + const { tierStore } = this.props + + tierStore.invalidateToken() } updateTierStore = (event, property, index) => { diff --git a/src/stores/TierStore.spec.js b/src/stores/TierStore.spec.js index 0dce5d887..e7adf5af0 100644 --- a/src/stores/TierStore.spec.js +++ b/src/stores/TierStore.spec.js @@ -19,6 +19,8 @@ describe('TierStore', () => { { addr: '0xaca94ef8bd5ffee41947b4585a84bda5a3d3da6e', min: 1234, max: 50505 }, { addr: '0x1df62f291b2e969fb0849d99d9ce41e2f137006e', min: 1234, max: 50505 }, ] + + tierStore.addTier({ whitelist: [] }) }) afterEach(() => { From b7ca648232d475ad4915138d2758b25579c8f48b Mon Sep 17 00:00:00 2001 From: fernandomg Date: Tue, 13 Mar 2018 11:46:04 -0300 Subject: [PATCH 16/16] Update CrowdsaleBlock snapshot --- .../__snapshots__/CrowdsaleBlock.spec.js.snap | 31 +++++-------------- 1 file changed, 8 insertions(+), 23 deletions(-) diff --git a/src/components/stepThree/__snapshots__/CrowdsaleBlock.spec.js.snap b/src/components/stepThree/__snapshots__/CrowdsaleBlock.spec.js.snap index a4e132eac..a83ab632a 100644 --- a/src/components/stepThree/__snapshots__/CrowdsaleBlock.spec.js.snap +++ b/src/components/stepThree/__snapshots__/CrowdsaleBlock.spec.js.snap @@ -15,7 +15,6 @@ exports[`CrowdsaleBlock Should render the component for the first Tier 1`] = ` "updatable": "off", "walletAddress": "0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1", "whitelist": Array [], - "whitelistElements": Array [], "whitelistEnabled": "no", }, ], @@ -50,7 +49,6 @@ exports[`CrowdsaleBlock Should render the component for the first Tier 1`] = ` "updatable": "off", "walletAddress": "0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1", "whitelist": Array [], - "whitelistElements": Array [], "whitelistEnabled": "no", }, ], @@ -410,7 +408,6 @@ exports[`CrowdsaleBlock Should render the component for the second Tier 1`] = ` "updatable": "off", "walletAddress": "0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1", "whitelist": Array [], - "whitelistElements": Array [], "whitelistEnabled": "no", }, Object { @@ -422,7 +419,6 @@ exports[`CrowdsaleBlock Should render the component for the second Tier 1`] = ` "updatable": "off", "walletAddress": "0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1", "whitelist": Array [], - "whitelistElements": Array [], "whitelistEnabled": "no", }, Object { @@ -432,8 +428,8 @@ exports[`CrowdsaleBlock Should render the component for the second Tier 1`] = ` "supply": "", "tier": "Tier 2", "updatable": "off", + "walletAddress": "", "whitelist": Array [], - "whitelistElements": Array [], }, ], "validTiers": Array [ @@ -483,7 +479,6 @@ exports[`CrowdsaleBlock Should render the component for the second Tier 1`] = ` "updatable": "off", "walletAddress": "0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1", "whitelist": Array [], - "whitelistElements": Array [], "whitelistEnabled": "no", }, Object { @@ -495,7 +490,6 @@ exports[`CrowdsaleBlock Should render the component for the second Tier 1`] = ` "updatable": "off", "walletAddress": "0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1", "whitelist": Array [], - "whitelistElements": Array [], "whitelistEnabled": "no", }, Object { @@ -505,8 +499,8 @@ exports[`CrowdsaleBlock Should render the component for the second Tier 1`] = ` "supply": "", "tier": "Tier 2", "updatable": "off", + "walletAddress": "", "whitelist": Array [], - "whitelistElements": Array [], }, ], "validTiers": Array [ @@ -881,7 +875,6 @@ exports[`CrowdsaleBlock Should render the component for the second Tier with whi "updatable": "off", "walletAddress": "0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1", "whitelist": Array [], - "whitelistElements": Array [], "whitelistEnabled": "yes", }, Object { @@ -893,7 +886,6 @@ exports[`CrowdsaleBlock Should render the component for the second Tier with whi "updatable": "off", "walletAddress": "0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1", "whitelist": Array [], - "whitelistElements": Array [], "whitelistEnabled": "no", }, Object { @@ -903,8 +895,8 @@ exports[`CrowdsaleBlock Should render the component for the second Tier with whi "supply": "", "tier": "Tier 2", "updatable": "off", + "walletAddress": "", "whitelist": Array [], - "whitelistElements": Array [], }, Object { "endTime": "", @@ -915,7 +907,6 @@ exports[`CrowdsaleBlock Should render the component for the second Tier with whi "updatable": "off", "walletAddress": "0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1", "whitelist": Array [], - "whitelistElements": Array [], "whitelistEnabled": "no", }, Object { @@ -925,8 +916,8 @@ exports[`CrowdsaleBlock Should render the component for the second Tier with whi "supply": "", "tier": "Tier 2", "updatable": "off", + "walletAddress": "", "whitelist": Array [], - "whitelistElements": Array [], }, ], "validTiers": Array [ @@ -992,7 +983,6 @@ exports[`CrowdsaleBlock Should render the component for the second Tier with whi "updatable": "off", "walletAddress": "0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1", "whitelist": Array [], - "whitelistElements": Array [], "whitelistEnabled": "yes", }, Object { @@ -1004,7 +994,6 @@ exports[`CrowdsaleBlock Should render the component for the second Tier with whi "updatable": "off", "walletAddress": "0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1", "whitelist": Array [], - "whitelistElements": Array [], "whitelistEnabled": "no", }, Object { @@ -1014,8 +1003,8 @@ exports[`CrowdsaleBlock Should render the component for the second Tier with whi "supply": "", "tier": "Tier 2", "updatable": "off", + "walletAddress": "", "whitelist": Array [], - "whitelistElements": Array [], }, Object { "endTime": "", @@ -1026,7 +1015,6 @@ exports[`CrowdsaleBlock Should render the component for the second Tier with whi "updatable": "off", "walletAddress": "0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1", "whitelist": Array [], - "whitelistElements": Array [], "whitelistEnabled": "no", }, Object { @@ -1036,8 +1024,8 @@ exports[`CrowdsaleBlock Should render the component for the second Tier with whi "supply": "", "tier": "Tier 2", "updatable": "off", + "walletAddress": "", "whitelist": Array [], - "whitelistElements": Array [], }, ], "validTiers": Array [ @@ -1435,7 +1423,6 @@ exports[`CrowdsaleBlock Should render the component for the second Tier with whi "updatable": "off", "walletAddress": "0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1", "whitelist": Array [], - "whitelistElements": Array [], "whitelistEnabled": "yes", }, Object { @@ -1447,7 +1434,6 @@ exports[`CrowdsaleBlock Should render the component for the second Tier with whi "updatable": "off", "walletAddress": "0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1", "whitelist": Array [], - "whitelistElements": Array [], "whitelistEnabled": "no", }, Object { @@ -1457,8 +1443,8 @@ exports[`CrowdsaleBlock Should render the component for the second Tier with whi "supply": "", "tier": "Tier 2", "updatable": "off", + "walletAddress": "", "whitelist": Array [], - "whitelistElements": Array [], }, Object { "endTime": "", @@ -1469,7 +1455,6 @@ exports[`CrowdsaleBlock Should render the component for the second Tier with whi "updatable": "off", "walletAddress": "0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1", "whitelist": Array [], - "whitelistElements": Array [], "whitelistEnabled": "no", }, Object { @@ -1479,8 +1464,8 @@ exports[`CrowdsaleBlock Should render the component for the second Tier with whi "supply": "", "tier": "Tier 2", "updatable": "off", + "walletAddress": "", "whitelist": Array [], - "whitelistElements": Array [], }, ], "validTiers": Array [