diff options
author | Dan Finlay <dan@danfinlay.com> | 2017-06-13 08:06:39 +0800 |
---|---|---|
committer | Dan Finlay <dan@danfinlay.com> | 2017-06-13 08:17:16 +0800 |
commit | a741cc4fc4fb68e3f460c70ea848bdf3d2d2c894 (patch) | |
tree | 58652d4789e71a47a763096e746bd25904d91bfe /ui/app | |
parent | d05d9a5f57b9311d6f29539233f9065330e8bda4 (diff) | |
parent | bbe0c73dca45542b519036bec2bae5feb1e55485 (diff) | |
download | tangerine-wallet-browser-a741cc4fc4fb68e3f460c70ea848bdf3d2d2c894.tar tangerine-wallet-browser-a741cc4fc4fb68e3f460c70ea848bdf3d2d2c894.tar.gz tangerine-wallet-browser-a741cc4fc4fb68e3f460c70ea848bdf3d2d2c894.tar.bz2 tangerine-wallet-browser-a741cc4fc4fb68e3f460c70ea848bdf3d2d2c894.tar.lz tangerine-wallet-browser-a741cc4fc4fb68e3f460c70ea848bdf3d2d2c894.tar.xz tangerine-wallet-browser-a741cc4fc4fb68e3f460c70ea848bdf3d2d2c894.tar.zst tangerine-wallet-browser-a741cc4fc4fb68e3f460c70ea848bdf3d2d2c894.zip |
Merge branch 'master' into AddTokenList
Diffstat (limited to 'ui/app')
37 files changed, 982 insertions, 6150 deletions
diff --git a/ui/app/account-detail.js b/ui/app/account-detail.js index 5ceee4fe0..5b2588ec5 100644 --- a/ui/app/account-detail.js +++ b/ui/app/account-detail.js @@ -16,9 +16,9 @@ const ExportAccountView = require('./components/account-export') const ethUtil = require('ethereumjs-util') const EditableLabel = require('./components/editable-label') const Tooltip = require('./components/tooltip') -const BuyButtonSubview = require('./components/buy-button-subview') const TabBar = require('./components/tab-bar') const TokenList = require('./components/token-list') + module.exports = connect(mapStateToProps)(AccountDetailScreen) function mapStateToProps (state) { @@ -32,6 +32,8 @@ function mapStateToProps (state) { unapprovedMsgs: valuesFor(state.metamask.unapprovedMsgs), shapeShiftTxList: state.metamask.shapeShiftTxList, transactions: state.metamask.selectedAddressTxList || [], + conversionRate: state.metamask.conversionRate, + currentCurrency: state.metamask.currentCurrency, } } @@ -47,7 +49,7 @@ AccountDetailScreen.prototype.render = function () { var checksumAddress = selected && ethUtil.toChecksumAddress(selected) var identity = props.identities[selected] var account = props.accounts[selected] - const { network } = props + const { network, conversionRate, currentCurrency } = props return ( @@ -186,6 +188,8 @@ AccountDetailScreen.prototype.render = function () { h(EthBalance, { value: account && account.balance, + conversionRate, + currentCurrency, style: { lineHeight: '7px', marginTop: '10px', @@ -241,8 +245,6 @@ AccountDetailScreen.prototype.subview = function () { case 'export': var state = extend({key: 'export'}, this.props) return h(ExportAccountView, state) - case 'buyForm': - return h(BuyButtonSubview, extend({key: 'buyForm'}, this.props)) default: return this.tabSections() } @@ -275,14 +277,6 @@ AccountDetailScreen.prototype.tabSections = function () { AccountDetailScreen.prototype.tabSwitchView = function () { const userAddress = this.props.address - var subview - try { - subview = this.props.accountDetail.subview - return h(TokenList, { userAddress }) - } catch (e) { - subview = null - } - const tabSelection = this.state.tabSelection || 'history' switch (tabSelection) { @@ -294,12 +288,14 @@ AccountDetailScreen.prototype.tabSwitchView = function () { } AccountDetailScreen.prototype.transactionList = function () { + const {transactions, unapprovedMsgs, address, + network, shapeShiftTxList, conversionRate } = this.props - const {transactions, unapprovedMsgs, address, network, shapeShiftTxList } = this.props return h(TransactionList, { transactions: transactions.sort((a, b) => b.time - a.time), network, unapprovedMsgs, + conversionRate, address, shapeShiftTxList, viewPendingTx: (txId) => { @@ -311,15 +307,3 @@ AccountDetailScreen.prototype.transactionList = function () { AccountDetailScreen.prototype.requestAccountExport = function () { this.props.dispatch(actions.requestExportAccount()) } - - -AccountDetailScreen.prototype.buyButtonDeligator = function () { - var props = this.props - var selected = props.address || Object.keys(props.accounts)[0] - - if (this.props.accountDetail.subview === 'buyForm') { - props.dispatch(actions.backToAccountDetail(props.address)) - } else { - props.dispatch(actions.buyEthView(selected)) - } -} diff --git a/ui/app/accounts/account-list-item.js b/ui/app/accounts/account-list-item.js index 2a3c13d05..10a0b6cc7 100644 --- a/ui/app/accounts/account-list-item.js +++ b/ui/app/accounts/account-list-item.js @@ -15,7 +15,8 @@ function AccountListItem () { } AccountListItem.prototype.render = function () { - const { identity, selectedAddress, accounts, onShowDetail } = this.props + const { identity, selectedAddress, accounts, onShowDetail, + conversionRate, currentCurrency } = this.props const checksumAddress = identity && identity.address && ethUtil.toChecksumAddress(identity.address) const isSelected = selectedAddress === identity.address @@ -52,6 +53,8 @@ AccountListItem.prototype.render = function () { }, checksumAddress), h(EthBalance, { value: account && account.balance, + currentCurrency, + conversionRate, style: { lineHeight: '7px', marginTop: '10px', diff --git a/ui/app/accounts/import/index.js b/ui/app/accounts/import/index.js index 96350852a..a0f0f9bdb 100644 --- a/ui/app/accounts/import/index.js +++ b/ui/app/accounts/import/index.js @@ -73,7 +73,7 @@ AccountImportSubview.prototype.render = function () { ) } -AccountImportSubview.prototype.renderImportView = function() { +AccountImportSubview.prototype.renderImportView = function () { const props = this.props const state = this.state || {} const { type } = state diff --git a/ui/app/accounts/index.js b/ui/app/accounts/index.js index 9584ebad9..ac2615cd7 100644 --- a/ui/app/accounts/index.js +++ b/ui/app/accounts/index.js @@ -23,6 +23,8 @@ function mapStateToProps (state) { scrollToBottom: state.appState.scrollToBottom, pending, keyrings: state.metamask.keyrings, + conversionRate: state.metamask.conversionRate, + currentCurrency: state.metamask.currentCurrency, } } @@ -33,7 +35,7 @@ function AccountsScreen () { AccountsScreen.prototype.render = function () { const props = this.props - const { keyrings } = props + const { keyrings, conversionRate, currentCurrency } = props const identityList = valuesFor(props.identities) const unapprovedTxList = valuesFor(props.unapprovedTxs) @@ -81,6 +83,8 @@ AccountsScreen.prototype.render = function () { key: `acct-panel-${identity.address}`, identity, selectedAddress: this.props.selectedAddress, + conversionRate, + currentCurrency, accounts: this.props.accounts, onShowDetail: this.onShowDetail.bind(this), pending, diff --git a/ui/app/actions.js b/ui/app/actions.js index 8934299e7..1a3557cb4 100644 --- a/ui/app/actions.js +++ b/ui/app/actions.js @@ -134,10 +134,6 @@ var actions = { buyEth: buyEth, buyEthView: buyEthView, BUY_ETH_VIEW: 'BUY_ETH_VIEW', - UPDATE_COINBASE_AMOUNT: 'UPDATE_COIBASE_AMOUNT', - updateCoinBaseAmount: updateCoinBaseAmount, - UPDATE_BUY_ADDRESS: 'UPDATE_BUY_ADDRESS', - updateBuyAddress: updateBuyAddress, COINBASE_SUBVIEW: 'COINBASE_SUBVIEW', coinBaseSubview: coinBaseSubview, SHAPESHIFT_SUBVIEW: 'SHAPESHIFT_SUBVIEW', @@ -318,7 +314,7 @@ function importNewAccount (strategy, args) { } } -function navigateToNewAccountScreen() { +function navigateToNewAccountScreen () { return { type: this.NEW_ACCOUNT_SCREEN, } @@ -397,7 +393,7 @@ function signPersonalMsg (msgData) { function signTx (txData) { return (dispatch) => { - web3.eth.sendTransaction(txData, (err, data) => { + global.ethQuery.sendTransaction(txData, (err, data) => { dispatch(actions.hideLoadingIndication()) if (err) return dispatch(actions.displayWarning(err.message)) dispatch(actions.hideWarning()) @@ -669,7 +665,7 @@ function clearNotices () { } } -function markAccountsFound() { +function markAccountsFound () { log.debug(`background.markAccountsFound`) return callBackgroundThenUpdate(background.markAccountsFound) } @@ -852,20 +848,6 @@ function buyEthView (address) { } } -function updateCoinBaseAmount (value) { - return { - type: actions.UPDATE_COINBASE_AMOUNT, - value, - } -} - -function updateBuyAddress (value) { - return { - type: actions.UPDATE_BUY_ADDRESS, - value, - } -} - function coinBaseSubview () { return { type: actions.COINBASE_SUBVIEW, @@ -996,7 +978,7 @@ function callBackgroundThenUpdate (method, ...args) { } } -function forceUpdateMetamaskState(dispatch){ +function forceUpdateMetamaskState (dispatch) { log.debug(`background.getState`) background.getState((err, newState) => { if (err) { diff --git a/ui/app/app.js b/ui/app/app.js index 5a7596aca..53dbc3354 100644 --- a/ui/app/app.js +++ b/ui/app/app.js @@ -249,7 +249,7 @@ App.prototype.renderNetworkDropdown = function () { h(DropMenuItem, { label: 'Ropsten Test Network', closeMenu: () => this.setState({ isNetworkMenuOpen: false }), - action: () => props.dispatch(actions.setProviderType('testnet')), + action: () => props.dispatch(actions.setProviderType('ropsten')), icon: h('.menu-icon.red-dot'), activeNetworkRender: props.network, provider: props.provider, @@ -265,6 +265,15 @@ App.prototype.renderNetworkDropdown = function () { }), h(DropMenuItem, { + label: 'Rinkeby Test Network', + closeMenu: () => this.setState({ isNetworkMenuOpen: false}), + action: () => props.dispatch(actions.setProviderType('rinkeby')), + icon: h('.menu-icon.golden-square'), + activeNetworkRender: props.network, + provider: props.provider, + }), + + h(DropMenuItem, { label: 'Localhost 8545', closeMenu: () => this.setState({ isNetworkMenuOpen: false }), action: () => props.dispatch(actions.setDefaultRpcTarget(rpcList)), @@ -332,7 +341,7 @@ App.prototype.renderDropdown = function () { }), h(DropMenuItem, { - label: 'Info', + label: 'Info/Help', closeMenu: () => this.setState({ isMainMenuOpen: !isOpen }), action: () => this.props.dispatch(actions.showInfoPage()), icon: h('i.fa.fa-question.fa-lg'), @@ -552,5 +561,4 @@ App.prototype.renderCommonRpc = function (rpcList, provider) { }) } }) - } diff --git a/ui/app/components/balance.js b/ui/app/components/balance.js index 3c5e24b65..57ca84564 100644 --- a/ui/app/components/balance.js +++ b/ui/app/components/balance.js @@ -1,7 +1,8 @@ const Component = require('react').Component const h = require('react-hyperscript') const inherits = require('util').inherits -const formatBalance = require('../util').formatBalance const generateBalanceObject = require('../util').generateBalanceObject +const formatBalance = require('../util').formatBalance +const generateBalanceObject = require('../util').generateBalanceObject const Tooltip = require('./tooltip.js') const FiatValue = require('./fiat-value.js') diff --git a/ui/app/components/bn-as-decimal-input.js b/ui/app/components/bn-as-decimal-input.js new file mode 100644 index 000000000..f3ace4720 --- /dev/null +++ b/ui/app/components/bn-as-decimal-input.js @@ -0,0 +1,174 @@ +const Component = require('react').Component +const h = require('react-hyperscript') +const inherits = require('util').inherits +const ethUtil = require('ethereumjs-util') +const BN = ethUtil.BN +const extend = require('xtend') + +module.exports = BnAsDecimalInput + +inherits(BnAsDecimalInput, Component) +function BnAsDecimalInput () { + this.state = { invalid: null } + Component.call(this) +} + +/* Bn as Decimal Input + * + * A component for allowing easy, decimal editing + * of a passed in bn string value. + * + * On change, calls back its `onChange` function parameter + * and passes it an updated bn string. + */ + +BnAsDecimalInput.prototype.render = function () { + const props = this.props + const state = this.state + + const { value, scale, precision, onChange, min, max } = props + + const suffix = props.suffix + const style = props.style + const valueString = value.toString(10) + const newValue = this.downsize(valueString, scale, precision) + + return ( + h('.flex-column', [ + h('.flex-row', { + style: { + alignItems: 'flex-end', + lineHeight: '13px', + fontFamily: 'Montserrat Light', + textRendering: 'geometricPrecision', + }, + }, [ + h('input.hex-input', { + type: 'number', + step: 'any', + required: true, + min, + max, + style: extend({ + display: 'block', + textAlign: 'right', + backgroundColor: 'transparent', + border: '1px solid #bdbdbd', + + }, style), + value: newValue, + onBlur: (event) => { + this.updateValidity(event) + }, + onChange: (event) => { + this.updateValidity(event) + const value = (event.target.value === '') ? '' : event.target.value + + + const scaledNumber = this.upsize(value, scale, precision) + const precisionBN = new BN(scaledNumber, 10) + onChange(precisionBN, event.target.checkValidity()) + }, + onInvalid: (event) => { + const msg = this.constructWarning() + if (msg === state.invalid) { + return + } + this.setState({ invalid: msg }) + event.preventDefault() + return false + }, + }), + h('div', { + style: { + color: ' #AEAEAE', + fontSize: '12px', + marginLeft: '5px', + marginRight: '6px', + width: '20px', + }, + }, suffix), + ]), + + state.invalid ? h('span.error', { + style: { + position: 'absolute', + right: '0px', + textAlign: 'right', + transform: 'translateY(26px)', + padding: '3px', + background: 'rgba(255,255,255,0.85)', + zIndex: '1', + textTransform: 'capitalize', + border: '2px solid #E20202', + }, + }, state.invalid) : null, + ]) + ) +} + +BnAsDecimalInput.prototype.setValid = function (message) { + this.setState({ invalid: null }) +} + +BnAsDecimalInput.prototype.updateValidity = function (event) { + const target = event.target + const value = this.props.value + const newValue = target.value + + if (value === newValue) { + return + } + + const valid = target.checkValidity() + + if (valid) { + this.setState({ invalid: null }) + } +} + +BnAsDecimalInput.prototype.constructWarning = function () { + const { name, min, max } = this.props + let message = name ? name + ' ' : '' + + if (min && max) { + message += `must be greater than or equal to ${min} and less than or equal to ${max}.` + } else if (min) { + message += `must be greater than or equal to ${min}.` + } else if (max) { + message += `must be less than or equal to ${max}.` + } else { + message += 'Invalid input.' + } + + return message +} + + +BnAsDecimalInput.prototype.downsize = function (number, scale, precision) { + // if there is no scaling, simply return the number + if (scale === 0) { + return Number(number) + } else { + // if the scale is the same as the precision, account for this edge case. + var decimals = (scale === precision) ? -1 : scale - precision + return Number(number.slice(0, -scale) + '.' + number.slice(-scale, decimals)) + } +} + +BnAsDecimalInput.prototype.upsize = function (number, scale, precision) { + var stringArray = number.toString().split('.') + var decimalLength = stringArray[1] ? stringArray[1].length : 0 + var newString = stringArray[0] + + // If there is scaling and decimal parts exist, integrate them in. + if ((scale !== 0) && (decimalLength !== 0)) { + newString += stringArray[1].slice(0, precision) + } + + // Add 0s to account for the upscaling. + for (var i = decimalLength; i < scale; i++) { + newString += '0' + } + return newString +} diff --git a/ui/app/components/buy-button-subview.js b/ui/app/components/buy-button-subview.js index 6810303e1..87084f92d 100644 --- a/ui/app/components/buy-button-subview.js +++ b/ui/app/components/buy-button-subview.js @@ -6,12 +6,15 @@ const actions = require('../actions') const CoinbaseForm = require('./coinbase-form') const ShapeshiftForm = require('./shapeshift-form') const Loading = require('./loading') -const TabBar = require('./tab-bar') +const AccountPanel = require('./account-panel') +const RadioList = require('./custom-radio-list') module.exports = connect(mapStateToProps)(BuyButtonSubview) function mapStateToProps (state) { return { + identity: state.appState.identity, + account: state.metamask.accounts[state.appState.buyView.buyAddress], warning: state.appState.warning, buyView: state.appState.buyView, network: state.metamask.network, @@ -31,7 +34,11 @@ BuyButtonSubview.prototype.render = function () { const isLoading = props.isSubLoading return ( - h('.buy-eth-section', [ + h('.buy-eth-section.flex-column', { + style: { + alignItems: 'center', + }, + }, [ // back button h('.flex-row', { style: { @@ -46,58 +53,79 @@ BuyButtonSubview.prototype.render = function () { left: '10px', }, }), - h('h2.page-subtitle', 'Buy Eth'), - ]), - - h(Loading, { isLoading }), - - h(TabBar, { - tabs: [ - { - content: [ - 'Coinbase', - h('a', { - onClick: (event) => this.navigateTo('https://github.com/MetaMask/faq/blob/master/COINBASE.md'), - }, [ - h('i.fa.fa-question-circle', { - style: { - margin: '0px 5px', - }, - }), - ]), - ], - key: 'coinbase', + h('h2.text-transform-uppercase.flex-center', { + style: { + width: '100vw', + background: 'rgb(235, 235, 235)', + color: 'rgb(174, 174, 174)', + paddingTop: '4px', + paddingBottom: '4px', }, - { - content: [ - 'Shapeshift', - h('a', { - href: 'https://github.com/MetaMask/faq/blob/master/COINBASE.md', - onClick: (event) => this.navigateTo('https://info.shapeshift.io/about'), - }, [ - h('i.fa.fa-question-circle', { - style: { - margin: '0px 5px', - }, - }), - ]), - ], - key: 'shapeshift', + }, 'Buy Eth'), + ]), + h('div', { + style: { + position: 'absolute', + top: '57vh', + left: '49vw', + }, + }, [ + h(Loading, {isLoading}), + ]), + h('div', { + style: { + width: '80%', + }, + }, [ + h(AccountPanel, { + showFullAddress: true, + identity: props.identity, + account: props.account, + }), + ]), + h('h3.text-transform-uppercase', { + style: { + paddingLeft: '15px', + fontFamily: 'Montserrat Light', + width: '100vw', + background: 'rgb(235, 235, 235)', + color: 'rgb(174, 174, 174)', + paddingTop: '4px', + paddingBottom: '4px', + }, + }, 'Select Service'), + h('.flex-row.selected-exchange', { + style: { + position: 'relative', + right: '35px', + marginTop: '20px', + marginBottom: '20px', + }, + }, [ + h(RadioList, { + defaultFocus: props.buyView.subview, + labels: [ + 'Coinbase', + 'ShapeShift', + ], + subtext: { + 'Coinbase': 'Crypto/FIAT (USA only)', + 'ShapeShift': 'Crypto', }, - ], - defaultTab: 'coinbase', - tabSelected: (key) => { - switch (key) { - case 'coinbase': - props.dispatch(actions.coinBaseSubview()) - break - case 'shapeshift': - props.dispatch(actions.shapeShiftSubview(props.provider.type)) - break - } + onClick: this.radioHandler.bind(this), + }), + ]), + h('h3.text-transform-uppercase', { + style: { + paddingLeft: '15px', + fontFamily: 'Montserrat Light', + width: '100vw', + background: 'rgb(235, 235, 235)', + color: 'rgb(174, 174, 174)', + paddingTop: '4px', + paddingBottom: '4px', }, - }), - + }, props.buyView.subview), this.formVersionSubview(), ]) ) @@ -124,13 +152,19 @@ BuyButtonSubview.prototype.formVersionSubview = function () { marginBottom: '15px', }, }, 'In order to access this feature, please switch to the Main Network'), - ((network === '3') || (network === '42')) ? h('h3.text-transform-uppercase', 'or go to the') : null, + ((network === '3') || (network === '4') || (network === '42')) ? h('h3.text-transform-uppercase', 'or go to the') : null, (network === '3') ? h('button.text-transform-uppercase', { onClick: () => this.props.dispatch(actions.buyEth({ network })), style: { marginTop: '15px', }, }, 'Ropsten Test Faucet') : null, + (network === '4') ? h('button.text-transform-uppercase', { + onClick: () => this.props.dispatch(actions.buyEth({ network })), + style: { + marginTop: '15px', + }, + }, 'Rinkeby Test Faucet') : null, (network === '42') ? h('button.text-transform-uppercase', { onClick: () => this.props.dispatch(actions.buyEth({ network })), style: { @@ -152,3 +186,12 @@ BuyButtonSubview.prototype.backButtonContext = function () { this.props.dispatch(actions.goHome()) } } + +BuyButtonSubview.prototype.radioHandler = function (event) { + switch (event.target.title) { + case 'Coinbase': + return this.props.dispatch(actions.coinBaseSubview()) + case 'ShapeShift': + return this.props.dispatch(actions.shapeShiftSubview(this.props.provider.type)) + } +} diff --git a/ui/app/components/coinbase-form.js b/ui/app/components/coinbase-form.js index fd5816a21..f44d86045 100644 --- a/ui/app/components/coinbase-form.js +++ b/ui/app/components/coinbase-form.js @@ -4,7 +4,6 @@ const inherits = require('util').inherits const connect = require('react-redux').connect const actions = require('../actions') -const isValidAddress = require('../util').isValidAddress module.exports = connect(mapStateToProps)(CoinbaseForm) function mapStateToProps (state) { @@ -21,105 +20,36 @@ function CoinbaseForm () { CoinbaseForm.prototype.render = function () { var props = this.props - var amount = props.buyView.amount - var address = props.buyView.buyAddress return h('.flex-column', { style: { - // margin: '10px', + marginTop: '35px', padding: '25px', + width: '100%', }, }, [ - h('.flex-column', { - style: { - alignItems: 'flex-start', - }, - }, [ - h('.flex-row', [ - h('div', 'Address:'), - h('.ellip-address', address), - ]), - h('.flex-row', [ - h('div', 'Amount: $'), - h('.input-container', [ - h('input.buy-inputs', { - style: { - width: '3em', - boxSizing: 'border-box', - }, - defaultValue: amount, - onChange: this.handleAmount.bind(this), - }), - h('i.fa.fa-pencil-square-o.edit-text', { - style: { - fontSize: '12px', - color: '#F7861C', - position: 'relative', - bottom: '5px', - right: '11px', - }, - }), - ]), - ]), - ]), - - h('.info-gray', { - style: { - fontSize: '10px', - fontFamily: 'Montserrat Light', - margin: '15px', - lineHeight: '13px', - }, - }, - `there is a USD$ 15 a day max and a USD$ 50 - dollar limit per the life time of an account without a - coinbase account. A fee of 3.75% will be aplied to debit/credit cards.`), - - !props.warning ? h('div', { - style: { - width: '340px', - height: '22px', - }, - }) : props.warning && h('span.error.flex-center', props.warning), - - h('.flex-row', { style: { justifyContent: 'space-around', margin: '33px', + marginTop: '0px', }, }, [ - h('button', { + h('button.btn-green', { onClick: this.toCoinbase.bind(this), }, 'Continue to Coinbase'), - h('button', { + h('button.btn-red', { onClick: () => props.dispatch(actions.backTobuyView(props.accounts.address)), }, 'Cancel'), ]), ]) } -CoinbaseForm.prototype.handleAmount = function (event) { - this.props.dispatch(actions.updateCoinBaseAmount(event.target.value)) -} -CoinbaseForm.prototype.handleAddress = function (event) { - this.props.dispatch(actions.updateBuyAddress(event.target.value)) -} -CoinbaseForm.prototype.toCoinbase = function () { - var props = this.props - var amount = props.buyView.amount - var address = props.buyView.buyAddress - var message - if (isValidAddress(address) && isValidAmountforCoinBase(amount).valid) { - props.dispatch(actions.buyEth({ network: '1', address, amount: props.buyView.amount })) - } else if (!isValidAmountforCoinBase(amount).valid) { - message = isValidAmountforCoinBase(amount).message - return props.dispatch(actions.displayWarning(message)) - } else { - message = 'Receiving address is invalid.' - return props.dispatch(actions.displayWarning(message)) - } +CoinbaseForm.prototype.toCoinbase = function () { + const props = this.props + const address = props.buyView.buyAddress + props.dispatch(actions.buyEth({ network: '1', address, amount: 0 })) } CoinbaseForm.prototype.renderLoading = function () { @@ -131,29 +61,3 @@ CoinbaseForm.prototype.renderLoading = function () { src: 'images/loading.svg', }) } - -function isValidAmountforCoinBase (amount) { - amount = parseFloat(amount) - if (amount) { - if (amount <= 15 && amount > 0) { - return { - valid: true, - } - } else if (amount > 15) { - return { - valid: false, - message: 'The amount can not be greater then $15', - } - } else { - return { - valid: false, - message: 'Can not buy amounts less then $0', - } - } - } else { - return { - valid: false, - message: 'The amount entered is not a number', - } - } -} diff --git a/ui/app/components/copyable.js b/ui/app/components/copyable.js new file mode 100644 index 000000000..a4f6f4bc6 --- /dev/null +++ b/ui/app/components/copyable.js @@ -0,0 +1,46 @@ +const Component = require('react').Component +const h = require('react-hyperscript') +const inherits = require('util').inherits + +const Tooltip = require('./tooltip') +const copyToClipboard = require('copy-to-clipboard') + +module.exports = Copyable + +inherits(Copyable, Component) +function Copyable () { + Component.call(this) + this.state = { + copied: false, + } +} + +Copyable.prototype.render = function () { + const props = this.props + const state = this.state + const { value, children } = props + const { copied } = state + + return h(Tooltip, { + title: copied ? 'Copied!' : 'Copy', + position: 'bottom', + }, h('span', { + style: { + cursor: 'pointer', + }, + onClick: (event) => { + event.preventDefault() + event.stopPropagation() + copyToClipboard(value) + this.debounceRestore() + }, + }, children)) +} + +Copyable.prototype.debounceRestore = function () { + this.setState({ copied: true }) + clearTimeout(this.timeout) + this.timeout = setTimeout(() => { + this.setState({ copied: false }) + }, 850) +} diff --git a/ui/app/components/custom-radio-list.js b/ui/app/components/custom-radio-list.js new file mode 100644 index 000000000..a4c525396 --- /dev/null +++ b/ui/app/components/custom-radio-list.js @@ -0,0 +1,60 @@ +const Component = require('react').Component +const h = require('react-hyperscript') +const inherits = require('util').inherits + +module.exports = RadioList + +inherits(RadioList, Component) +function RadioList () { + Component.call(this) +} + +RadioList.prototype.render = function () { + const props = this.props + const activeClass = '.custom-radio-selected' + const inactiveClass = '.custom-radio-inactive' + const { + labels, + defaultFocus, + } = props + + + return ( + h('.flex-row', { + style: { + fontSize: '12px', + }, + }, [ + h('.flex-column.custom-radios', { + style: { + marginRight: '5px', + }, + }, + labels.map((lable, i) => { + let isSelcted = (this.state !== null) + isSelcted = isSelcted ? (this.state.selected === lable) : (defaultFocus === lable) + return h(isSelcted ? activeClass : inactiveClass, { + title: lable, + onClick: (event) => { + this.setState({selected: event.target.title}) + props.onClick(event) + }, + }) + }) + ), + h('.text', {}, + labels.map((lable) => { + if (props.subtext) { + return h('.flex-row', {}, [ + h('.radio-titles', lable), + h('.radio-titles-subtext', `- ${props.subtext[lable]}`), + ]) + } else { + return h('.radio-titles', lable) + } + }) + ), + ]) + ) +} + diff --git a/ui/app/components/drop-menu-item.js b/ui/app/components/drop-menu-item.js index 3eb6ec876..e42948209 100644 --- a/ui/app/components/drop-menu-item.js +++ b/ui/app/components/drop-menu-item.js @@ -42,11 +42,14 @@ DropMenuItem.prototype.activeNetworkRender = function () { if (providerType === 'mainnet') return h('.check', '✓') break case 'Ropsten Test Network': - if (providerType === 'testnet') return h('.check', '✓') + if (providerType === 'ropsten') return h('.check', '✓') break case 'Kovan Test Network': if (providerType === 'kovan') return h('.check', '✓') break + case 'Rinkeby Test Network': + if (providerType === 'rinkeby') return h('.check', '✓') + break case 'Localhost 8545': if (activeNetwork === 'http://localhost:8545') return h('.check', '✓') break diff --git a/ui/app/components/ens-input.js b/ui/app/components/ens-input.js index facf29d97..43bb7ab22 100644 --- a/ui/app/components/ens-input.js +++ b/ui/app/components/ens-input.js @@ -5,11 +5,9 @@ const extend = require('xtend') const debounce = require('debounce') const copyToClipboard = require('copy-to-clipboard') const ENS = require('ethjs-ens') +const networkMap = require('ethjs-ens/lib/network-map.json') const ensRE = /.+\.eth$/ -const networkResolvers = { - '3': '112234455c3a32fd11230c42e7bccd4a84e02010', -} module.exports = EnsInput @@ -23,9 +21,10 @@ EnsInput.prototype.render = function () { const opts = extend(props, { list: 'addresses', onChange: () => { + this.setState({ ensResolution: '0x0000000000000000000000000000000000000000' }) const network = this.props.network - let resolverAddress = networkResolvers[network] - if (!resolverAddress) return + const networkHasEnsSupport = getNetworkEnsSupport(network) + if (!networkHasEnsSupport) return const recipient = document.querySelector('input[name="address"]').value if (recipient.match(ensRE) === null) { @@ -52,7 +51,7 @@ EnsInput.prototype.render = function () { [ // Corresponds to the addresses owned. Object.keys(props.identities).map((key) => { - let identity = props.identities[key] + const identity = props.identities[key] return h('option', { value: identity.address, label: identity.name, @@ -63,6 +62,7 @@ EnsInput.prototype.render = function () { return h('option', { value: identity.address, label: identity.name, + key: identity.address, }) }), ]), @@ -72,10 +72,10 @@ EnsInput.prototype.render = function () { EnsInput.prototype.componentDidMount = function () { const network = this.props.network - let resolverAddress = networkResolvers[network] + const networkHasEnsSupport = getNetworkEnsSupport(network) - if (resolverAddress) { - const provider = web3.currentProvider + if (networkHasEnsSupport) { + const provider = global.ethereumProvider this.ens = new ENS({ provider, network }) this.checkName = debounce(this.lookupEnsName.bind(this), 200) } @@ -96,12 +96,14 @@ EnsInput.prototype.lookupEnsName = function () { log.info(`ENS attempting to resolve name: ${recipient}`) this.ens.lookup(recipient.trim()) .then((address) => { + if (address === '0x0000000000000000000000000000000000000000') throw new Error('No address has been set for this name.') if (address !== ensResolution) { this.setState({ loadingEns: false, ensResolution: address, nickname: recipient.trim(), hoverText: address + '\nClick to Copy', + ensFailure: false, }) } }) @@ -109,6 +111,7 @@ EnsInput.prototype.lookupEnsName = function () { log.error(reason) return this.setState({ loadingEns: false, + ensResolution: '0x0000000000000000000000000000000000000000', ensFailure: true, hoverText: reason.message, }) @@ -168,3 +171,8 @@ EnsInput.prototype.ensIconContents = function (recipient) { }) } } + +function getNetworkEnsSupport (network) { + return Boolean(networkMap[network]) +} + diff --git a/ui/app/components/eth-balance.js b/ui/app/components/eth-balance.js index 57ca84564..4f538fd31 100644 --- a/ui/app/components/eth-balance.js +++ b/ui/app/components/eth-balance.js @@ -16,20 +16,19 @@ function EthBalanceComponent () { EthBalanceComponent.prototype.render = function () { var props = this.props let { value } = props - var style = props.style + const { style, width } = props var needsParse = this.props.needsParse !== undefined ? this.props.needsParse : true value = value ? formatBalance(value, 6, needsParse) : '...' - var width = props.width return ( h('.ether-balance.ether-balance-amount', { - style: style, + style, }, [ h('div', { style: { display: 'inline', - width: width, + width, }, }, this.renderBalance(value)), ]) @@ -38,16 +37,17 @@ EthBalanceComponent.prototype.render = function () { } EthBalanceComponent.prototype.renderBalance = function (value) { var props = this.props + const { conversionRate, shorten, incoming, currentCurrency } = props if (value === 'None') return value if (value === '...') return value - var balanceObj = generateBalanceObject(value, props.shorten ? 1 : 3) + var balanceObj = generateBalanceObject(value, shorten ? 1 : 3) var balance var splitBalance = value.split(' ') var ethNumber = splitBalance[0] var ethSuffix = splitBalance[1] const showFiat = 'showFiat' in props ? props.showFiat : true - if (props.shorten) { + if (shorten) { balance = balanceObj.shortBalance } else { balance = balanceObj.balance @@ -73,7 +73,7 @@ EthBalanceComponent.prototype.renderBalance = function (value) { width: '100%', textAlign: 'right', }, - }, this.props.incoming ? `+${balance}` : balance), + }, incoming ? `+${balance}` : balance), h('div', { style: { color: ' #AEAEAE', @@ -83,7 +83,7 @@ EthBalanceComponent.prototype.renderBalance = function (value) { }, label), ]), - showFiat ? h(FiatValue, { value: props.value }) : null, + showFiat ? h(FiatValue, { value: props.value, conversionRate, currentCurrency }) : null, ])) ) } diff --git a/ui/app/components/fiat-value.js b/ui/app/components/fiat-value.js index 298809b30..8a64a1cfc 100644 --- a/ui/app/components/fiat-value.js +++ b/ui/app/components/fiat-value.js @@ -1,17 +1,9 @@ const Component = require('react').Component const h = require('react-hyperscript') const inherits = require('util').inherits -const connect = require('react-redux').connect const formatBalance = require('../util').formatBalance -module.exports = connect(mapStateToProps)(FiatValue) - -function mapStateToProps (state) { - return { - conversionRate: state.metamask.conversionRate, - currentCurrency: state.metamask.currentCurrency, - } -} +module.exports = FiatValue inherits(FiatValue, Component) function FiatValue () { @@ -20,23 +12,23 @@ function FiatValue () { FiatValue.prototype.render = function () { const props = this.props + const { conversionRate, currentCurrency } = props + const value = formatBalance(props.value, 6) if (value === 'None') return value var fiatDisplayNumber, fiatTooltipNumber var splitBalance = value.split(' ') - if (props.conversionRate !== 0) { - fiatTooltipNumber = Number(splitBalance[0]) * props.conversionRate + if (conversionRate !== 0) { + fiatTooltipNumber = Number(splitBalance[0]) * conversionRate fiatDisplayNumber = fiatTooltipNumber.toFixed(2) } else { fiatDisplayNumber = 'N/A' fiatTooltipNumber = 'Unknown' } - var fiatSuffix = props.currentCurrency - - return fiatDisplay(fiatDisplayNumber, fiatSuffix) + return fiatDisplay(fiatDisplayNumber, currentCurrency) } function fiatDisplay (fiatDisplayNumber, fiatSuffix) { diff --git a/ui/app/components/hex-as-decimal-input.js b/ui/app/components/hex-as-decimal-input.js index e37aaa8c3..4a71e9585 100644 --- a/ui/app/components/hex-as-decimal-input.js +++ b/ui/app/components/hex-as-decimal-input.js @@ -139,7 +139,7 @@ HexAsDecimalInput.prototype.constructWarning = function () { } function hexify (decimalString) { - const hexBN = new BN(decimalString, 10) + const hexBN = new BN(parseInt(decimalString), 10) return '0x' + hexBN.toString('hex') } diff --git a/ui/app/components/identicon.js b/ui/app/components/identicon.js index 1bb92301e..58bd2bdc4 100644 --- a/ui/app/components/identicon.js +++ b/ui/app/components/identicon.js @@ -1,6 +1,7 @@ const Component = require('react').Component const h = require('react-hyperscript') const inherits = require('util').inherits +const isNode = require('detect-node') const findDOMNode = require('react-dom').findDOMNode const jazzicon = require('jazzicon') const iconFactoryGen = require('../../lib/icon-factory') @@ -34,19 +35,22 @@ IdenticonComponent.prototype.render = function () { IdenticonComponent.prototype.componentDidMount = function () { var props = this.props - const { address, network } = props + const { address } = props if (!address) return var container = findDOMNode(this) var diameter = props.diameter || this.defaultDiameter - var img = iconFactory.iconForAddress(address, diameter, false, network) - container.appendChild(img) + + if (!isNode) { + var img = iconFactory.iconForAddress(address, diameter) + container.appendChild(img) + } } IdenticonComponent.prototype.componentDidUpdate = function () { var props = this.props - const { address, network } = props + const { address } = props if (!address) return @@ -58,6 +62,9 @@ IdenticonComponent.prototype.componentDidUpdate = function () { } var diameter = props.diameter || this.defaultDiameter - var img = iconFactory.iconForAddress(address, diameter, false, network) - container.appendChild(img) + if (!isNode) { + var img = iconFactory.iconForAddress(address, diameter) + container.appendChild(img) + } } + diff --git a/ui/app/components/network.js b/ui/app/components/network.js index d9045167f..31a8fc17c 100644 --- a/ui/app/components/network.js +++ b/ui/app/components/network.js @@ -34,7 +34,7 @@ Network.prototype.render = function () { } else if (providerName === 'mainnet') { hoverText = 'Main Ethereum Network' iconName = 'ethereum-network' - } else if (providerName === 'testnet') { + } else if (providerName === 'ropsten') { hoverText = 'Ropsten Test Network' iconName = 'ropsten-test-network' } else if (parseInt(networkNumber) === 3) { @@ -43,6 +43,9 @@ Network.prototype.render = function () { } else if (providerName === 'kovan') { hoverText = 'Kovan Test Network' iconName = 'kovan-test-network' + } else if (providerName === 'rinkeby') { + hoverText = 'Rinkeby Test Network' + iconName = 'rinkeby-test-network' } else { hoverText = 'Unknown Private Network' iconName = 'unknown-private-network' @@ -82,6 +85,15 @@ Network.prototype.render = function () { }}, 'Kovan Test Net'), ]) + case 'rinkeby-test-network': + return h('.network-indicator', [ + h('.menu-icon.golden-square'), + h('.network-name', { + style: { + color: '#e7a218', + }}, + 'Rinkeby Test Net'), + ]) default: return h('.network-indicator', [ h('i.fa.fa-question-circle.fa-lg', { diff --git a/ui/app/components/notice.js b/ui/app/components/notice.js index b85787033..d9f0067cd 100644 --- a/ui/app/components/notice.js +++ b/ui/app/components/notice.js @@ -107,7 +107,7 @@ Notice.prototype.render = function () { style: { marginTop: '18px', }, - }, 'Continue'), + }, 'Accept'), ]) ) } @@ -115,8 +115,9 @@ Notice.prototype.render = function () { Notice.prototype.componentDidMount = function () { var node = findDOMNode(this) linker.setupListener(node) - if (document.getElementsByClassName('notice-box')[0].clientHeight < 310) { this.setState({disclaimerDisabled: false}) } - + if (document.getElementsByClassName('notice-box')[0].clientHeight < 310) { + this.setState({disclaimerDisabled: false}) + } } Notice.prototype.componentWillUnmount = function () { diff --git a/ui/app/components/pending-tx.js b/ui/app/components/pending-tx.js index 1b83f5043..4b1a00eca 100644 --- a/ui/app/components/pending-tx.js +++ b/ui/app/components/pending-tx.js @@ -1,29 +1,26 @@ const Component = require('react').Component -const connect = require('react-redux').connect const h = require('react-hyperscript') const inherits = require('util').inherits const actions = require('../actions') +const clone = require('clone') const ethUtil = require('ethereumjs-util') const BN = ethUtil.BN const hexToBn = require('../../../app/scripts/lib/hex-to-bn') - +const util = require('../util') const MiniAccountPanel = require('./mini-account-panel') +const Copyable = require('./copyable') const EthBalance = require('./eth-balance') -const util = require('../util') const addressSummary = util.addressSummary const nameForAddress = require('../../lib/contract-namer') -const HexInput = require('./hex-as-decimal-input') +const BNInput = require('./bn-as-decimal-input') -const MIN_GAS_PRICE_BN = new BN(20000000) +const MIN_GAS_PRICE_GWEI_BN = new BN(2) +const GWEI_FACTOR = new BN(1e9) +const MIN_GAS_PRICE_BN = MIN_GAS_PRICE_GWEI_BN.mul(GWEI_FACTOR) const MIN_GAS_LIMIT_BN = new BN(21000) -module.exports = connect(mapStateToProps)(PendingTx) - -function mapStateToProps (state) { - return {} -} - +module.exports = PendingTx inherits(PendingTx, Component) function PendingTx () { Component.call(this) @@ -35,19 +32,29 @@ function PendingTx () { PendingTx.prototype.render = function () { const props = this.props + const { currentCurrency, blockGasLimit } = props + const conversionRate = props.conversionRate const txMeta = this.gatherTxMeta() const txParams = txMeta.txParams || {} + // Account Details const address = txParams.from || props.selectedAddress const identity = props.identities[address] || { address: address } const account = props.accounts[address] const balance = account ? account.balance : '0x0' - const gas = txParams.gas - const gasPrice = txParams.gasPrice + // recipient check + const isValidAddress = !txParams.to || util.isValidAddress(txParams.to) + // Gas + const gas = txParams.gas const gasBn = hexToBn(gas) + const gasLimit = new BN(parseInt(blockGasLimit)) + const safeGasLimit = this.bnMultiplyByFraction(gasLimit, 19, 20).toString(10) + + // Gas Price + const gasPrice = txParams.gasPrice || MIN_GAS_PRICE_BN.toString(16) const gasPriceBn = hexToBn(gasPrice) const txFeeBn = gasBn.mul(gasPriceBn) @@ -55,7 +62,6 @@ PendingTx.prototype.render = function () { const maxCost = txFeeBn.add(valueBn) const dataLength = txParams.data ? (txParams.data.length - 2) / 2 : 0 - const imageify = props.imageifyIdenticons === undefined ? true : props.imageifyIdenticons const balanceBn = hexToBn(balance) const insufficientBalance = balanceBn.lt(maxCost) @@ -69,17 +75,8 @@ PendingTx.prototype.render = function () { }, [ h('form#pending-tx-form', { - onSubmit: (event) => { - event.preventDefault() - const form = document.querySelector('form#pending-tx-form') - const valid = form.checkValidity() - this.setState({ valid }) - if (valid && this.verifyGasParams()) { - props.sendTransaction(txMeta, event) - } else { - this.props.dispatch(actions.displayWarning('Invalid Gas Parameters')) - } - }, + onSubmit: this.onSubmit.bind(this), + }, [ // tx info @@ -93,7 +90,6 @@ PendingTx.prototype.render = function () { h(MiniAccountPanel, { imageSeed: address, - imageifyIdenticons: imageify, picOrder: 'right', }, [ h('span.font-small', { @@ -101,11 +97,16 @@ PendingTx.prototype.render = function () { fontFamily: 'Montserrat Bold, Montserrat, sans-serif', }, }, identity.name), - h('span.font-small', { - style: { - fontFamily: 'Montserrat Light, Montserrat, sans-serif', - }, - }, addressSummary(address, 6, 4, false)), + + h(Copyable, { + value: ethUtil.toChecksumAddress(address), + }, [ + h('span.font-small', { + style: { + fontFamily: 'Montserrat Light, Montserrat, sans-serif', + }, + }, addressSummary(address, 6, 4, false)), + ]), h('span.font-small', { style: { @@ -114,6 +115,8 @@ PendingTx.prototype.render = function () { }, [ h(EthBalance, { value: balance, + conversionRate, + currentCurrency, inline: true, labelColor: '#F7861C', }), @@ -151,7 +154,7 @@ PendingTx.prototype.render = function () { // in the way that gas and gasLimit currently are. h('.row', [ h('.cell.label', 'Amount'), - h(EthBalance, { value: txParams.value }), + h(EthBalance, { value: txParams.value, currentCurrency, conversionRate }), ]), // Gas Limit (customizable) @@ -159,22 +162,21 @@ PendingTx.prototype.render = function () { h('.cell.label', 'Gas Limit'), h('.cell.value', { }, [ - h(HexInput, { + h(BNInput, { name: 'Gas Limit', - value: gas, + value: gasBn, + precision: 0, + scale: 0, // The hard lower limit for gas. min: MIN_GAS_LIMIT_BN.toString(10), + max: safeGasLimit, suffix: 'UNITS', style: { position: 'relative', top: '5px', }, - onChange: (newHex) => { - log.info(`Gas limit changed to ${newHex}`) - const txMeta = this.gatherTxMeta() - txMeta.txParams.gas = newHex - this.setState({ txData: txMeta }) - }, + onChange: this.gasLimitChanged.bind(this), + ref: (hexInput) => { this.inputs.push(hexInput) }, }), ]), @@ -185,21 +187,18 @@ PendingTx.prototype.render = function () { h('.cell.label', 'Gas Price'), h('.cell.value', { }, [ - h(HexInput, { + h(BNInput, { name: 'Gas Price', - value: gasPrice, - suffix: 'WEI', - min: MIN_GAS_PRICE_BN.toString(10), + value: gasPriceBn, + precision: 9, + scale: 9, + suffix: 'GWEI', + min: MIN_GAS_PRICE_GWEI_BN.toString(10), style: { position: 'relative', top: '5px', }, - onChange: (newHex) => { - log.info(`Gas price changed to: ${newHex}`) - const txMeta = this.gatherTxMeta() - txMeta.txParams.gasPrice = newHex - this.setState({ txData: txMeta }) - }, + onChange: this.gasPriceChanged.bind(this), ref: (hexInput) => { this.inputs.push(hexInput) }, }), ]), @@ -208,7 +207,7 @@ PendingTx.prototype.render = function () { // Max Transaction Fee (calculated) h('.cell.row', [ h('.cell.label', 'Max Transaction Fee'), - h(EthBalance, { value: txFeeBn.toString(16) }), + h(EthBalance, { value: txFeeBn.toString(16), currentCurrency, conversionRate }), ]), h('.cell.row', { @@ -227,6 +226,8 @@ PendingTx.prototype.render = function () { }, [ h(EthBalance, { value: maxCost.toString(16), + currentCurrency, + conversionRate, inline: true, labelColor: 'black', fontSize: '16px', @@ -269,6 +270,15 @@ PendingTx.prototype.render = function () { }, 'Transaction Error. Exception thrown in contract code.') : null, + !isValidAddress ? + h('.error', { + style: { + marginLeft: 50, + fontSize: '0.9em', + }, + }, 'Recipient address is invalid. Sending this transaction will result in a loss of ETH.') + : null, + insufficientBalance ? h('span.error', { style: { @@ -289,7 +299,7 @@ PendingTx.prototype.render = function () { insufficientBalance ? - h('button', { + h('button.btn-green', { onClick: props.buyEth, }, 'Buy Ether') : null, @@ -306,7 +316,7 @@ PendingTx.prototype.render = function () { type: 'submit', value: 'ACCEPT', style: { marginLeft: '10px' }, - disabled: insufficientBalance || !this.state.valid, + disabled: insufficientBalance || !this.state.valid || !isValidAddress, }), h('button.cancel.btn-red', { @@ -323,29 +333,33 @@ PendingTx.prototype.miniAccountPanelForRecipient = function () { const txData = props.txData const txParams = txData.txParams || {} const isContractDeploy = !('to' in txParams) - const imageify = props.imageifyIdenticons === undefined ? true : props.imageifyIdenticons // If it's not a contract deploy, send to the account if (!isContractDeploy) { return h(MiniAccountPanel, { imageSeed: txParams.to, - imageifyIdenticons: imageify, picOrder: 'left', }, [ + h('span.font-small', { style: { fontFamily: 'Montserrat Bold, Montserrat, sans-serif', }, }, nameForAddress(txParams.to, props.identities)), - h('span.font-small', { - style: { - fontFamily: 'Montserrat Light, Montserrat, sans-serif', - }, - }, addressSummary(txParams.to, 6, 4, false)), + + h(Copyable, { + value: ethUtil.toChecksumAddress(txParams.to), + }, [ + h('span.font-small', { + style: { + fontFamily: 'Montserrat Light, Montserrat, sans-serif', + }, + }, addressSummary(txParams.to, 6, 4, false)), + ]), + ]) } else { return h(MiniAccountPanel, { - imageifyIdenticons: imageify, picOrder: 'left', }, [ @@ -359,6 +373,26 @@ PendingTx.prototype.miniAccountPanelForRecipient = function () { } } +PendingTx.prototype.gasPriceChanged = function (newBN, valid) { + log.info(`Gas price changed to: ${newBN.toString(10)}`) + const txMeta = this.gatherTxMeta() + txMeta.txParams.gasPrice = '0x' + newBN.toString('hex') + this.setState({ + txData: clone(txMeta), + valid, + }) +} + +PendingTx.prototype.gasLimitChanged = function (newBN, valid) { + log.info(`Gas limit changed to ${newBN.toString(10)}`) + const txMeta = this.gatherTxMeta() + txMeta.txParams.gas = '0x' + newBN.toString('hex') + this.setState({ + txData: clone(txMeta), + valid, + }) +} + PendingTx.prototype.resetGasFields = function () { log.debug(`pending-tx resetGasFields`) @@ -374,12 +408,39 @@ PendingTx.prototype.resetGasFields = function () { }) } +PendingTx.prototype.onSubmit = function (event) { + event.preventDefault() + const txMeta = this.gatherTxMeta() + const valid = this.checkValidity() + this.setState({ valid }) + if (valid && this.verifyGasParams()) { + this.props.sendTransaction(txMeta, event) + } else { + this.props.dispatch(actions.displayWarning('Invalid Gas Parameters')) + } +} + +PendingTx.prototype.checkValidity = function () { + const form = this.getFormEl() + const valid = form.checkValidity() + return valid +} + +PendingTx.prototype.getFormEl = function () { + const form = document.querySelector('form#pending-tx-form') + // Stub out form for unit tests: + if (!form) { + return { checkValidity () { return true } } + } + return form +} + // After a customizable state value has been updated, PendingTx.prototype.gatherTxMeta = function () { log.debug(`pending-tx gatherTxMeta`) const props = this.props const state = this.state - const txData = state.txData || props.txData + const txData = clone(state.txData) || clone(props.txData) log.debug(`UI has defaulted to tx meta ${JSON.stringify(txData)}`) return txData @@ -398,9 +459,14 @@ PendingTx.prototype._notZeroOrEmptyString = function (obj) { return obj !== '' && obj !== '0x0' } +PendingTx.prototype.bnMultiplyByFraction = function (targetBN, numerator, denominator) { + const numBN = new BN(numerator) + const denomBN = new BN(denominator) + return targetBN.mul(numBN).div(denomBN) +} + function forwardCarrat () { return ( - h('img', { src: 'images/forward-carrat.svg', style: { @@ -408,7 +474,5 @@ function forwardCarrat () { height: '37px', }, }) - ) } - diff --git a/ui/app/components/qr-code.js b/ui/app/components/qr-code.js index 5488599eb..06b9aed9b 100644 --- a/ui/app/components/qr-code.js +++ b/ui/app/components/qr-code.js @@ -3,6 +3,7 @@ const h = require('react-hyperscript') const qrCode = require('qrcode-npm').qrcode const inherits = require('util').inherits const connect = require('react-redux').connect +const isHexPrefixed = require('ethereumjs-util').isHexPrefixed const CopyButton = require('./copyButton') module.exports = connect(mapStateToProps)(QrCodeView) @@ -22,13 +23,12 @@ function QrCodeView () { } QrCodeView.prototype.render = function () { - var props = this.props - var Qr = props.Qr - var qrImage = qrCode(4, 'M') - - qrImage.addData(Qr.data) + const props = this.props + const Qr = props.Qr + const address = `${isHexPrefixed(Qr.data) ? 'ethereum:' : ''}${Qr.data}` + const qrImage = qrCode(4, 'M') + qrImage.addData(address) qrImage.make() - return h('.main-container.flex-column', { key: 'qr', style: { diff --git a/ui/app/components/shapeshift-form.js b/ui/app/components/shapeshift-form.js index 8c9686035..e0a720426 100644 --- a/ui/app/components/shapeshift-form.js +++ b/ui/app/components/shapeshift-form.js @@ -43,14 +43,18 @@ ShapeshiftForm.prototype.renderMain = function () { style: { // marginTop: '10px', padding: '25px', + paddingTop: '5px', width: '100%', + minHeight: '215px', alignItems: 'center', + overflowY: 'auto', }, }, [ h('.flex-row', { style: { justifyContent: 'center', alignItems: 'baseline', + height: '42px', }, }, [ h('img', { @@ -66,6 +70,7 @@ ShapeshiftForm.prototype.renderMain = function () { h('input#fromCoin.buy-inputs.ex-coins', { type: 'text', list: 'coinList', + autoFocus: true, dataset: { persistentFormId: 'input-coin', }, @@ -92,7 +97,6 @@ ShapeshiftForm.prototype.renderMain = function () { h('.icon-control', [ h('i.fa.fa-refresh.fa-4.orange', { style: { - position: 'relative', bottom: '5px', left: '5px', color: '#F7861C', @@ -121,8 +125,6 @@ ShapeshiftForm.prototype.renderMain = function () { }, }), ]), - - this.props.isSubLoading ? this.renderLoading() : null, h('.flex-column', { style: { alignItems: 'flex-start', @@ -138,17 +140,6 @@ ShapeshiftForm.prototype.renderMain = function () { this.props.warning) : this.renderInfo(), ]), - h('.flex-row', { - style: { - padding: '10px', - paddingBottom: '2px', - width: '100%', - }, - }, [ - h('div', 'Receiving address:'), - h('.ellip-address', this.props.buyView.buyAddress), - ]), - h(this.activeToggle('.input-container'), { style: { padding: '10px', @@ -156,6 +147,7 @@ ShapeshiftForm.prototype.renderMain = function () { width: '100%', }, }, [ + h('div', `${coin} Address:`), h('input#fromCoinAddress.buy-inputs', { @@ -166,8 +158,8 @@ ShapeshiftForm.prototype.renderMain = function () { }, style: { boxSizing: 'border-box', - width: '278px', - height: '20px', + width: '227px', + height: '30px', padding: ' 5px ', }, }), @@ -177,7 +169,7 @@ ShapeshiftForm.prototype.renderMain = function () { fontSize: '12px', color: '#F7861C', position: 'relative', - bottom: '5px', + bottom: '10px', right: '11px', }, }), @@ -190,6 +182,8 @@ ShapeshiftForm.prototype.renderMain = function () { onClick: this.shift.bind(this), style: { marginTop: '10px', + position: 'relative', + bottom: '40px', }, }, 'Submit'), @@ -266,8 +260,6 @@ ShapeshiftForm.prototype.renderInfo = function () { return h('span', { style: { - marginTop: '10px', - marginBottom: '15px', }, }, [ h('h3.flex-row.text-transform-uppercase', { @@ -286,10 +278,6 @@ ShapeshiftForm.prototype.renderInfo = function () { ]) } -ShapeshiftForm.prototype.handleAddress = function (event) { - this.props.dispatch(actions.updateBuyAddress(event.target.value)) -} - ShapeshiftForm.prototype.activeToggle = function (elementType) { if (!this.props.buyView.formView.response || this.props.warning) return elementType return `${elementType}.inactive` diff --git a/ui/app/components/shift-list-item.js b/ui/app/components/shift-list-item.js index 96a7cba6e..32bfbeda4 100644 --- a/ui/app/components/shift-list-item.js +++ b/ui/app/components/shift-list-item.js @@ -8,14 +8,17 @@ const actions = require('../actions') const addressSummary = require('../util').addressSummary const CopyButton = require('./copyButton') -const EtherBalance = require('./eth-balance') +const EthBalance = require('./eth-balance') const Tooltip = require('./tooltip') module.exports = connect(mapStateToProps)(ShiftListItem) function mapStateToProps (state) { - return {} + return { + conversionRate: state.metamask.conversionRate, + currentCurrency: state.metamask.currentCurrency, + } } inherits(ShiftListItem, Component) @@ -64,6 +67,7 @@ function formatDate (date) { ShiftListItem.prototype.renderUtilComponents = function () { var props = this.props + const { conversionRate, currentCurrency } = props switch (props.response.status) { case 'no_deposits': @@ -94,8 +98,10 @@ ShiftListItem.prototype.renderUtilComponents = function () { h(CopyButton, { value: this.props.response.transaction, }), - h(EtherBalance, { + h(EthBalance, { value: `${props.response.outgoingCoin}`, + conversionRate, + currentCurrency, width: '55px', shorten: true, needsParse: false, diff --git a/ui/app/components/transaction-list-item-icon.js b/ui/app/components/transaction-list-item-icon.js index ca2781451..431054340 100644 --- a/ui/app/components/transaction-list-item-icon.js +++ b/ui/app/components/transaction-list-item-icon.js @@ -1,6 +1,7 @@ const Component = require('react').Component const h = require('react-hyperscript') const inherits = require('util').inherits +const Tooltip = require('./tooltip') const Identicon = require('./identicon') @@ -15,7 +16,7 @@ TransactionIcon.prototype.render = function () { const { transaction, txParams, isMsg } = this.props switch (transaction.status) { case 'unapproved': - return h( !isMsg ? '.unapproved-tx-icon' : 'i.fa.fa-certificate.fa-lg') + return h(!isMsg ? '.unapproved-tx-icon' : 'i.fa.fa-certificate.fa-lg') case 'rejected': return h('i.fa.fa-exclamation-triangle.fa-lg.warning', { @@ -32,11 +33,16 @@ TransactionIcon.prototype.render = function () { }) case 'submitted': - return h('i.fa.fa-ellipsis-h', { - style: { - fontSize: '27px', - }, - }) + return h(Tooltip, { + title: 'Pending', + position: 'bottom', + }, [ + h('i.fa.fa-ellipsis-h', { + style: { + fontSize: '27px', + }, + }), + ]) } if (isMsg) { diff --git a/ui/app/components/transaction-list-item.js b/ui/app/components/transaction-list-item.js index 9fef52355..dbda66a31 100644 --- a/ui/app/components/transaction-list-item.js +++ b/ui/app/components/transaction-list-item.js @@ -2,12 +2,13 @@ const Component = require('react').Component const h = require('react-hyperscript') const inherits = require('util').inherits -const EtherBalance = require('./eth-balance') +const EthBalance = require('./eth-balance') const addressSummary = require('../util').addressSummary const explorerLink = require('../../lib/explorer-link') const CopyButton = require('./copyButton') const vreme = new (require('vreme')) const Tooltip = require('./tooltip') +const numberToBN = require('number-to-bn') const TransactionIcon = require('./transaction-list-item-icon') const ShiftListItem = require('./shift-list-item') @@ -19,7 +20,7 @@ function TransactionListItem () { } TransactionListItem.prototype.render = function () { - const { transaction, network } = this.props + const { transaction, network, conversionRate, currentCurrency } = this.props if (transaction.key === 'shapeshift') { if (network === '1') return h(ShiftListItem, transaction) } @@ -27,7 +28,7 @@ TransactionListItem.prototype.render = function () { let isLinkable = false const numericNet = parseInt(network) - isLinkable = numericNet === 1 || numericNet === 3 || numericNet === 42 + isLinkable = numericNet === 1 || numericNet === 3 || numericNet === 4 || numericNet === 42 var isMsg = ('msgParams' in transaction) var isTx = ('txParams' in transaction) @@ -39,6 +40,8 @@ TransactionListItem.prototype.render = function () { txParams = transaction.msgParams } + const nonce = txParams.nonce ? numberToBN(txParams.nonce).toString(10) : '' + const isClickable = ('hash' in transaction && isLinkable) || isPending return ( h(`.transaction-list-item.flex-row.flex-space-between${isClickable ? '.pointer' : ''}`, { @@ -69,6 +72,22 @@ TransactionListItem.prototype.render = function () { ]), ]), + h(Tooltip, { + title: 'Transaction Number', + position: 'bottom', + }, [ + h('span', { + style: { + display: 'flex', + cursor: 'normal', + flexDirection: 'column', + alignItems: 'center', + justifyContent: 'center', + padding: '10px', + }, + }, nonce), + ]), + h('.flex-column', {style: {width: '200px', overflow: 'hidden'}}, [ domainField(txParams), h('div', date), @@ -78,8 +97,10 @@ TransactionListItem.prototype.render = function () { // Places a copy button if tx is successful, else places a placeholder empty div. transaction.hash ? h(CopyButton, { value: transaction.hash }) : h('div', {style: { display: 'flex', alignItems: 'center', width: '26px' }}), - isTx ? h(EtherBalance, { + isTx ? h(EthBalance, { value: txParams.value, + conversionRate, + currentCurrency, width: '55px', shorten: true, showFiat: false, @@ -134,7 +155,6 @@ function failIfFailed (transaction) { return h('span.error', ' (Rejected)') } if (transaction.err) { - return h(Tooltip, { title: transaction.err.message, position: 'bottom', @@ -142,5 +162,4 @@ function failIfFailed (transaction) { h('span.error', ' (Failed)'), ]) } - } diff --git a/ui/app/components/transaction-list.js b/ui/app/components/transaction-list.js index 4c25f3dd9..3b4ba741e 100644 --- a/ui/app/components/transaction-list.js +++ b/ui/app/components/transaction-list.js @@ -13,7 +13,7 @@ function TransactionList () { } TransactionList.prototype.render = function () { - const { transactions, network, unapprovedMsgs } = this.props + const { transactions, network, unapprovedMsgs, conversionRate } = this.props var shapeShiftTxList if (network === '1') { @@ -58,6 +58,7 @@ TransactionList.prototype.render = function () { } return h(TransactionListItem, { transaction, i, network, key, + conversionRate, showTx: (txId) => { this.props.viewPendingTx(txId) }, diff --git a/ui/app/conf-tx.js b/ui/app/conf-tx.js index 3b8618992..747d3ce2b 100644 --- a/ui/app/conf-tx.js +++ b/ui/app/conf-tx.js @@ -27,6 +27,9 @@ function mapStateToProps (state) { warning: state.appState.warning, network: state.metamask.network, provider: state.metamask.provider, + conversionRate: state.metamask.conversionRate, + currentCurrency: state.metamask.currentCurrency, + blockGasLimit: state.metamask.currentBlockGasLimit, } } @@ -37,8 +40,8 @@ function ConfirmTxScreen () { ConfirmTxScreen.prototype.render = function () { const props = this.props - const { network, provider, unapprovedTxs, - unapprovedMsgs, unapprovedPersonalMsgs } = props + const { network, provider, unapprovedTxs, currentCurrency, + unapprovedMsgs, unapprovedPersonalMsgs, conversionRate, blockGasLimit } = props var unconfTxList = txHelper(unapprovedTxs, unapprovedMsgs, unapprovedPersonalMsgs, network) @@ -46,6 +49,7 @@ ConfirmTxScreen.prototype.render = function () { var txParams = txData.params || {} var isNotification = isPopupOrNotification() === 'notification' + log.info(`rendering a combined ${unconfTxList.length} unconf msg & txs`) if (unconfTxList.length === 0) return h(Loading, { isLoading: true }) @@ -102,9 +106,12 @@ ConfirmTxScreen.prototype.render = function () { selectedAddress: props.selectedAddress, accounts: props.accounts, identities: props.identities, + conversionRate, + currentCurrency, + blockGasLimit, // Actions buyEth: this.buyEth.bind(this, txParams.from || props.selectedAddress), - sendTransaction: this.sendTransaction.bind(this, txData), + sendTransaction: this.sendTransaction.bind(this), cancelTransaction: this.cancelTransaction.bind(this, txData), signMessage: this.signMessage.bind(this, txData), signPersonalMessage: this.signPersonalMessage.bind(this, txData), @@ -125,14 +132,12 @@ function currentTxView (opts) { if (txParams) { log.debug('txParams detected, rendering pending tx') return h(PendingTx, opts) - } else if (msgParams) { log.debug('msgParams detected, rendering pending msg') if (type === 'eth_sign') { log.debug('rendering eth_sign message') return h(PendingMsg, opts) - } else if (type === 'personal_sign') { log.debug('rendering personal_sign message') return h(PendingPersonalMsg, opts) @@ -141,7 +146,7 @@ function currentTxView (opts) { } ConfirmTxScreen.prototype.buyEth = function (address, event) { - this.stopPropagation(event) + event.preventDefault() this.props.dispatch(actions.buyEthView(address)) } diff --git a/ui/app/config.js b/ui/app/config.js index 444365de2..d7be26757 100644 --- a/ui/app/config.js +++ b/ui/app/config.js @@ -156,7 +156,7 @@ function currentProviderDisplay (metamaskState) { value = 'Main Ethereum Network' break - case 'testnet': + case 'ropsten': title = 'Current Network' value = 'Ropsten Test Network' break @@ -166,6 +166,11 @@ function currentProviderDisplay (metamaskState) { value = 'Kovan Test Network' break + case 'rinkeby': + title = 'Current Network' + value = 'Rinkeby Test Network' + break + default: title = 'Current RPC' value = metamaskState.provider.rpcTarget diff --git a/ui/app/conversion.json b/ui/app/conversion.json index eeca164ce..155ffc4fc 100644 --- a/ui/app/conversion.json +++ b/ui/app/conversion.json @@ -1,5730 +1,207 @@ -{
- "rows":[
- {
- "code":"007",
- "name":"007",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"1337",
- "name":"1337",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"1CR",
- "name":"1CR",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"256",
- "name":"256",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"2FLAV",
- "name":"2FLAV",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"2GIVE",
- "name":"2GIVE",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"32BIT",
- "name":"32BIT",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"404",
- "name":"404",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"611",
- "name":"611",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"888",
- "name":"888",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"8BIT",
- "name":"8Bit",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"ACES",
- "name":"ACES",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"ACID",
- "name":"ACID",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"ACLR",
- "name":"ACLR",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"ACP",
- "name":"ACP",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"ADC",
- "name":"ADC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"ADZ",
- "name":"Adzcoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"AEON",
- "name":"Aeon",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"AGRS",
- "name":"Agoras Tokens",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"AIB",
- "name":"AIB",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"ALC",
- "name":"ALC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"ALTC",
- "name":"ALTC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"AM",
- "name":"AM",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"AMBER",
- "name":"AMBER",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"AMS",
- "name":"AMS",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"ANAL",
- "name":"ANAL",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"ANI",
- "name":"ANI",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"ANC",
- "name":"Anoncoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"ANS",
- "name":"ANS",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"ANTI",
- "name":"AntiBitcoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"APEX",
- "name":"APEX",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"APC",
- "name":"Applecoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"APT",
- "name":"APT",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"AR2",
- "name":"AR2",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"ARB",
- "name":"ARB",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"ARC",
- "name":"ARC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"ARCH",
- "name":"ARCH",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"ARD",
- "name":"ARD",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"ARDR",
- "name":"ARDR",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"ABY",
- "name":"ArtByte",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"ARTC",
- "name":"ARTC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"ASAFE",
- "name":"ASAFE",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"ADCN",
- "name":"Asiadigicoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"ASN",
- "name":"ASN",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"ATEN",
- "name":"ATEN",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"ATOM",
- "name":"ATOM",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"ATX",
- "name":"ATX",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"REP",
- "name":"Augur",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"AUR",
- "name":"Auroracoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"AUD",
- "name":"Australian Dollar",
- "statuses":[
- "secondary"
- ]
- },
- {
- "code":"AV",
- "name":"AV",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"B2",
- "name":"B2",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"B3",
- "name":"B3",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"BA",
- "name":"BA",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"BAC",
- "name":"BAC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"BASH",
- "name":"BASH",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"BTA",
- "name":"Bata",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"BAY",
- "name":"BAY",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"BBCC",
- "name":"BBCC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"BQC",
- "name":"BBQCoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"BEC",
- "name":"BEC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"BEEP",
- "name":"BEEP",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"BELA",
- "name":"BellaCoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"BERN",
- "name":"BERNcash",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"BHC",
- "name":"BHC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"BILL",
- "name":"BILL",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"BILS",
- "name":"BILS",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"BIOS",
- "name":"BiosCrypto",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"BIT",
- "name":"BIT",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"BIT16",
- "name":"BIT16",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"BITB",
- "name":"BitBean",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"BTC",
- "name":"Bitcoin",
- "statuses":[
- "primary",
- "secondary"
- ]
- },
- {
- "code":"XBC",
- "name":"Bitcoin Plus",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"BTCD",
- "name":"BitcoinDark",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"BCY",
- "name":"Bitcrystals",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"BFX",
- "name":"Bitfinex Debt token",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"BTM",
- "name":"Bitmark",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"BITON",
- "name":"BITON",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"BTQ",
- "name":"BitQuark",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"BITS",
- "name":"BITS",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"BSD",
- "name":"BitSend",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"BTS",
- "name":"BitShares",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"SWIFT",
- "name":"BitSwift",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"BITZ",
- "name":"Bitz",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"BLK",
- "name":"Blackcoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"BLC",
- "name":"Blakecoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"BLEU",
- "name":"BLEU",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"BLITZ",
- "name":"Blitzcoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"BLOCK",
- "name":"Blocknet",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"BLRY",
- "name":"BLRY",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"BLU",
- "name":"BLU",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"BLUS",
- "name":"BLUS",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"BNT",
- "name":"BNT",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"BOLI",
- "name":"Bolivarcoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"BBR",
- "name":"Boolberry",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"BOOM",
- "name":"BOOM",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"BOST",
- "name":"BoostCoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"BOSS",
- "name":"BOSS",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"BPOK",
- "name":"BPOK",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"BRAIN",
- "name":"BRAIN",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"BRC",
- "name":"BRC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"BRDD",
- "name":"BRDD",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"BRIT",
- "name":"BRIT",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"GBP",
- "name":"British Pound Sterling",
- "statuses":[
- "secondary"
- ]
- },
- {
- "code":"BRK",
- "name":"BRK",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"BRX",
- "name":"BRX",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"BS",
- "name":"BS",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"BSC",
- "name":"BSC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"BST",
- "name":"BST",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"BTCHC",
- "name":"BTCHC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"BTCR",
- "name":"BTCR",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"BTCS",
- "name":"BTCS",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"BTD",
- "name":"BTD",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"BTLC",
- "name":"BTLC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"BTTF",
- "name":"BTTF",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"BTZ",
- "name":"BTZ",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"BUCKS",
- "name":"BUCKS",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"BUN",
- "name":"BUN",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"BURST",
- "name":"Burst",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"BUZZ",
- "name":"BUZZ",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"BVC",
- "name":"BVC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"BXT",
- "name":"BXT",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"BYC",
- "name":"Bytecent",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"BCN",
- "name":"Bytecoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"CAB",
- "name":"Cabbage Unit",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"CAGE",
- "name":"CAGE",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"CAID",
- "name":"CAID",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"CAD",
- "name":"Canadian Dollar",
- "statuses":[
- "secondary"
- ]
- },
- {
- "code":"CANN",
- "name":"CannabisCoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"CCN",
- "name":"Cannacoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"CPC",
- "name":"Capricoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"CAPT",
- "name":"CAPT",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"DIEM",
- "name":"CarpeDiemCoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"CASH",
- "name":"CASH",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"CBD",
- "name":"CBD",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"CBIT",
- "name":"CBIT",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"CCX",
- "name":"CCX",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"CD",
- "name":"CD",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"CDN",
- "name":"CDN",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"CF",
- "name":"CF",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"CGA",
- "name":"CGA",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"CKC",
- "name":"Checkcoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"CHEMX",
- "name":"CHEMX",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"CHESS",
- "name":"CHESS",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"CHF",
- "name":"CHF",
- "statuses":[
- "primary",
- "secondary"
- ]
- },
- {
- "code":"CNY",
- "name":"Chinese Yuan",
- "statuses":[
- "secondary"
- ]
- },
- {
- "code":"CHOOF",
- "name":"CHOOF",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"CJ",
- "name":"CJ",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"CLAM",
- "name":"Clams",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"CLICK",
- "name":"CLICK",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"CLINT",
- "name":"CLINT",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"CLOAK",
- "name":"Cloakcoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"CLR",
- "name":"CLR",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"CLUB",
- "name":"CLUB",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"CLUD",
- "name":"CLUD",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"CLV",
- "name":"CLV",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"CME",
- "name":"CME",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"CMT",
- "name":"CMT",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"CNC",
- "name":"CNC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"COC",
- "name":"COC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"COXST",
- "name":"CoExistCoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"COIN",
- "name":"COIN",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"C2",
- "name":"Coin2.1",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"CV2",
- "name":"Colossuscoin2.0",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"CON",
- "name":"CON",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"XCP",
- "name":"Counterparty",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"COVAL",
- "name":"COVAL",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"COX",
- "name":"COX",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"CRAB",
- "name":"CRAB",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"CRC",
- "name":"CRC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"CRE",
- "name":"CRE",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"CRBIT",
- "name":"Creditbit",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"CREVA",
- "name":"CrevaCoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"CRNK",
- "name":"CRNK",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"CRPC",
- "name":"CRPC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"CRPS",
- "name":"CRPS",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"CRT",
- "name":"CRT",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"CRW",
- "name":"CRW",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"CRX",
- "name":"CRX",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"CRY",
- "name":"CRY",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"CBX",
- "name":"Crypto Bullion",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"CESC",
- "name":"CryptoEscudo",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"XCN",
- "name":"Cryptonite",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"CSH",
- "name":"CSH",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"CST",
- "name":"CST",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"CTK",
- "name":"CTK",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"CTL",
- "name":"CTL",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"CTO",
- "name":"CTO",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"CURE",
- "name":"Curecoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"CYC",
- "name":"CYC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"CYP",
- "name":"Cypher",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"CZC",
- "name":"CZC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"CZR",
- "name":"CZR",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"DGD",
- "name":"DarkGoldCoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"DNET",
- "name":"Darknet",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"DAS",
- "name":"DAS",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"DASH",
- "name":"Dash",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"DTC",
- "name":"Datacoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"DB",
- "name":"DB",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"DBG",
- "name":"DBG",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"DBLK",
- "name":"DBLK",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"DBTC",
- "name":"DBTC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"DC",
- "name":"DC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"DCK",
- "name":"DCK",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"DCRE",
- "name":"DCRE",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"DCT",
- "name":"DCT",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"DCYP",
- "name":"DCYP",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"DCR",
- "name":"Decred",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"DES",
- "name":"Destiny",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"DEUR",
- "name":"DEUR",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"DEM",
- "name":"Deutsche eMark",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"DVC",
- "name":"Devcoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"DGMS",
- "name":"DGMS",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"DGORE",
- "name":"DGORE",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"DMD",
- "name":"Diamond",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"DGB",
- "name":"Digibyte",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"CUBE",
- "name":"DigiCube",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"DGC",
- "name":"Digitalcoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"XDN",
- "name":"DigitalNote",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"DP",
- "name":"DigitalPrice",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"DIME",
- "name":"Dimecoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"DISK",
- "name":"DISK",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"DKC",
- "name":"DKC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"DLC",
- "name":"DLC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"DLISK",
- "name":"DLISK",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"DMC",
- "name":"DMC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"NOTE",
- "name":"DNotes",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"DOGE",
- "name":"Dogecoin",
- "statuses":[
- "primary",
- "secondary"
- ]
- },
- {
- "code":"DOPE",
- "name":"DopeCoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"DOV",
- "name":"DOV",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"DOX",
- "name":"DOX",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"DPAY",
- "name":"DPAY",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"DRACO",
- "name":"DRACO",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"DRM8",
- "name":"DRM8",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"DROP",
- "name":"DROP",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"DRZ",
- "name":"DRZ",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"DSH",
- "name":"DSH",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"DTT",
- "name":"DTT",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"DBIC",
- "name":"DubaiCoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"DUO",
- "name":"DUO",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"DUST",
- "name":"DUST",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"EAGS",
- "name":"EAGS",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"EAC",
- "name":"Earthcoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"EBST",
- "name":"EBST",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"EC",
- "name":"EC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"ECC",
- "name":"ECCoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"ECLI",
- "name":"ECLI",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"EDC",
- "name":"EDC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"EDRC",
- "name":"EDRC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"EDR",
- "name":"EDRCoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"EGG",
- "name":"EGG",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"EGO",
- "name":"EGO",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"EMC2",
- "name":"Einsteinium",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"EL",
- "name":"EL",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"ELE",
- "name":"ELE",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"EFL",
- "name":"Electronic Gulden",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"EMB",
- "name":"EMB",
- "statuses":[
- "secondary"
- ]
- },
- {
- "code":"EME",
- "name":"EME",
- "statuses":[
- "secondary"
- ]
- },
- {
- "code":"EMC",
- "name":"Emercoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"EMIRG",
- "name":"EMIRG",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"EMP",
- "name":"EMP",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"EMPC",
- "name":"EMPC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"ENRG",
- "name":"Energycoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"ENT",
- "name":"ENT",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"EPC",
- "name":"EPC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"EQM",
- "name":"EQM",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"EQUAL",
- "name":"EQUAL",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"ERC",
- "name":"ERC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"ERC3",
- "name":"ERC3",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"ESB",
- "name":"ESB",
- "statuses":[
- "secondary"
- ]
- },
- {
- "code":"ESC",
- "name":"ESC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"ESP",
- "name":"ESP",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"ETCO",
- "name":"ETCO",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"ETH",
- "name":"Ethereum",
- "statuses":[
- "primary",
- "secondary"
- ]
- },
- {
- "code":"ETC",
- "name":"Ethereum Classic",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"ETHS",
- "name":"ETHS",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"EUC",
- "name":"EUC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"EUR",
- "name":"Euro",
- "statuses":[
- "primary",
- "secondary"
- ]
- },
- {
- "code":"EGC",
- "name":"EvergreenCoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"EVIL",
- "name":"EVIL",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"EXCL",
- "name":"EXCL",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"EXP",
- "name":"Expanse",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"FCT",
- "name":"Factom",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"FAIR",
- "name":"Faircoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"FC2",
- "name":"FC2",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"FCH",
- "name":"FCH",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"FCN",
- "name":"FCN",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"FCP",
- "name":"FCP",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"FTC",
- "name":"Feathercoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"TIPS",
- "name":"Fedoracoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"FIND",
- "name":"FIND",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"FIT",
- "name":"FIT",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"FJC",
- "name":"FJC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"FLO",
- "name":"Florincoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"FLOZ",
- "name":"FLOZ",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"FLT",
- "name":"FlutterCoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"FLY",
- "name":"Flycoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"FLDC",
- "name":"FoldingCoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"FOREX",
- "name":"FOREX",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"FRK",
- "name":"Franko",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"FRDC",
- "name":"FRDC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"FRC",
- "name":"Freicoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"FRN",
- "name":"FRN",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"FRWC",
- "name":"FRWC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"FSN",
- "name":"FSN",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"FST",
- "name":"FST",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"FTP",
- "name":"FTP",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"FUEL",
- "name":"FUEL",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"FUN",
- "name":"FUN",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"FUTC",
- "name":"FUTC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"FUZZ",
- "name":"FUZZ",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"FX",
- "name":"FX",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"GAIA",
- "name":"GAIA",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"GAIN",
- "name":"GAIN",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"GAKH",
- "name":"GAKH",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"GAM",
- "name":"GAM",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"GBT",
- "name":"GameBet Coin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"GAME",
- "name":"GameCredits",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"GAP",
- "name":"Gapcoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"GARY",
- "name":"GARY",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"GB",
- "name":"GB",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"GBC",
- "name":"GBC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"GBIT",
- "name":"GBIT",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"GBRC",
- "name":"GBRC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"GCN",
- "name":"GCN",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"GENE",
- "name":"GENE",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"GEO",
- "name":"GeoCoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"GEMZ",
- "name":"GetGems",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"GHOST",
- "name":"GHOST",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"GHS",
- "name":"GHS",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"GLC",
- "name":"GLC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"BSTY",
- "name":"GlobalBoost-Y",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"GMCX",
- "name":"GMCX",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"GML",
- "name":"GML",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"GMX",
- "name":"GMX",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"GOAT",
- "name":"GOAT",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"GCR",
- "name":"GoCoineR",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"GLD",
- "name":"GoldCoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"GOON",
- "name":"GOON",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"GOTX",
- "name":"GOTX",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"GP",
- "name":"GP",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"GPU",
- "name":"GPU",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"GRF",
- "name":"Graffiti",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"GRAM",
- "name":"GRAM",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"GRT",
- "name":"Grantcoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"GREED",
- "name":"GREED",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"GRC",
- "name":"Gridcoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"GRN",
- "name":"GRN",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"GRS",
- "name":"Groestlcoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"GROW",
- "name":"GrowCoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"GRW",
- "name":"GRW",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"GSY",
- "name":"GSY",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"GUA",
- "name":"GUA",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"NLG",
- "name":"Gulden",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"GUM",
- "name":"GUM",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"GUN",
- "name":"GUN",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"GYC",
- "name":"GYC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"HALLO",
- "name":"HALLO",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"HAM",
- "name":"HAM",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"HBT",
- "name":"HBT",
- "statuses":[
- "secondary"
- ]
- },
- {
- "code":"HCC",
- "name":"HCC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"HEAT",
- "name":"HEAT",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"HMP",
- "name":"HempCoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"XHI",
- "name":"HiCoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"HILL",
- "name":"HILL",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"HODL",
- "name":"HOdlcoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"HKD",
- "name":"Hong Kong Dollar",
- "statuses":[
- "secondary"
- ]
- },
- {
- "code":"HZ",
- "name":"Horizon",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"HSP",
- "name":"HSP",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"HTC",
- "name":"HTC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"HTML5",
- "name":"HTMLCOIN",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"HUC",
- "name":"HUC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"HVCO",
- "name":"HVCO",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"HXX",
- "name":"HXX",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"HYPER",
- "name":"Hyper",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"HYP",
- "name":"HyperStake",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"IBANK",
- "name":"IBANK",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"ICASH",
- "name":"iCash",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"ICN",
- "name":"iCoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"IFLT",
- "name":"IFLT",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"IMPS",
- "name":"IMPS",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"INCP",
- "name":"INCP",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"IFC",
- "name":"Infinitecoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"INFX",
- "name":"Influxcoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"IOC",
- "name":"IO Coin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"ION",
- "name":"ION",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"ISL",
- "name":"IslaCoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"IVZ",
- "name":"IVZ",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"IXC",
- "name":"IXC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"JPY",
- "name":"Japanese Yen",
- "statuses":[
- "secondary"
- ]
- },
- {
- "code":"JOBS",
- "name":"JOBS",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"JPC",
- "name":"JPC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"JBS",
- "name":"Jumbucks",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"JW",
- "name":"JW",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"JWL",
- "name":"JWL",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"KAT",
- "name":"KAT",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"KC",
- "name":"KC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"KNC",
- "name":"KhanCoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"KLC",
- "name":"KLC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"KOBO",
- "name":"KOBO",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"KORE",
- "name":"KoreCoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"KRAK",
- "name":"KRAK",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"KRB",
- "name":"KRB",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"KRC",
- "name":"KRC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"KRYP",
- "name":"KRYP",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"KR",
- "name":"Krypton",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"KTK",
- "name":"KTK",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"LANA",
- "name":"LANA",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"LAZ",
- "name":"LAZ",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"LBC",
- "name":"LBC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"LC",
- "name":"LC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"LEA",
- "name":"LeaCoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"LEAF",
- "name":"LEAF",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"LEO",
- "name":"LEO",
- "statuses":[
- "primary",
- "secondary"
- ]
- },
- {
- "code":"LFC",
- "name":"LFC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"LFO",
- "name":"LFO",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"LFTC",
- "name":"LFTC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"LGBTQ",
- "name":"LGBTQ",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"LIR",
- "name":"LIR",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"LSK",
- "name":"Lisk",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"LTC",
- "name":"Litecoin",
- "statuses":[
- "primary",
- "secondary"
- ]
- },
- {
- "code":"LTCR",
- "name":"Litecred",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"LIV",
- "name":"LIV",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"LKC",
- "name":"LKC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"LOC",
- "name":"LOC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"LOOT",
- "name":"LOOT",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"LTBC",
- "name":"LTBcoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"LTH",
- "name":"LTH",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"LTS",
- "name":"LTS",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"LUCKY",
- "name":"LUCKY",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"LUN",
- "name":"LUN",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"LXC",
- "name":"LXC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"MAD",
- "name":"MAD",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"XMG",
- "name":"Magi",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"MAID",
- "name":"MaidSafeCoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"MXT",
- "name":"MarteXcoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"OMNI",
- "name":"Mastercoin (Omni)",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"MTR",
- "name":"MasterTraderCoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"MAX",
- "name":"Maxcoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"MZC",
- "name":"Mazacoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"MBL",
- "name":"MBL",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"MCZ",
- "name":"MCZ",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"MED",
- "name":"MediterraneanCoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"MEGA",
- "name":"MEGA",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"MEC",
- "name":"Megacoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"MEME",
- "name":"Memetic",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"METAL",
- "name":"METAL",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"MG",
- "name":"MG",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"MND",
- "name":"MindCoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"MINT",
- "name":"Mintcoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"MIS",
- "name":"MIS",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"MMNXT",
- "name":"MMNXT",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"MMXVI",
- "name":"MMXVI",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"MNM",
- "name":"MNM",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"MOIN",
- "name":"MOIN",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"MOJO",
- "name":"MojoCoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"MONA",
- "name":"MonaCoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"XMR",
- "name":"Monero",
- "statuses":[
- "primary",
- "secondary"
- ]
- },
- {
- "code":"MUE",
- "name":"MonetaryUnit",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"MOON",
- "name":"Mooncoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"MOOND",
- "name":"MOOND",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"MPRO",
- "name":"MPRO",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"MRB",
- "name":"MRB",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"MUDRA",
- "name":"MUDRA",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"MYR",
- "name":"Myriadcoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"N2O",
- "name":"N2O",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"N7",
- "name":"N7",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"NMC",
- "name":"Namecoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"NAT",
- "name":"NAT",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"NAUT",
- "name":"Nautiluscoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"NAV",
- "name":"NAV Coin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"NBIT",
- "name":"NBIT",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"NCS",
- "name":"NCS",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"NDOGE",
- "name":"NDOGE",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"XEM",
- "name":"NEM",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"NEOS",
- "name":"NeosCoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"NET",
- "name":"NetCoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"NEU",
- "name":"NeuCoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"NTRN",
- "name":"Neutron",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"NEVA",
- "name":"NevaCoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"NEWB",
- "name":"NEWB",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"NXS",
- "name":"Nexus",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"NIC",
- "name":"NIC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"NICE",
- "name":"NICE",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"NKC",
- "name":"NKC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"NLC",
- "name":"NLC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"NOBL",
- "name":"NobleCoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"NODES",
- "name":"NODES",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"NVC",
- "name":"Novacoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"NRS",
- "name":"NRS",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"NTC",
- "name":"NTC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"NBT",
- "name":"NuBits",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"NUKE",
- "name":"NUKE",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"NUM",
- "name":"NUM",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"NSR",
- "name":"NuShares",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"NXE",
- "name":"NXE",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"NXT",
- "name":"NXT",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"NXTTY",
- "name":"Nxttycoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"NYC",
- "name":"NYC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"NZC",
- "name":"NZC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"NZD",
- "name":"NZD",
- "statuses":[
- "primary",
- "secondary"
- ]
- },
- {
- "code":"OBS",
- "name":"OBS",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"OCOW",
- "name":"OCOW",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"OK",
- "name":"OKCash",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"OLYMP",
- "name":"OLYMP",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"OMC",
- "name":"OMC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"ONE",
- "name":"ONE",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"OP",
- "name":"OP",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"OPAL",
- "name":"OPAL",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"ORB",
- "name":"Orbitcoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"OZC",
- "name":"OZC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"PAC",
- "name":"PAC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"PAL",
- "name":"PAL",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"PND",
- "name":"Pandacoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"PARA",
- "name":"PARA",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"PAY",
- "name":"PAY",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"XPY",
- "name":"Paycoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"PBC",
- "name":"PBC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"PCM",
- "name":"PCM",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"PCS",
- "name":"PCS",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"PDC",
- "name":"PDC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"PEC",
- "name":"PEC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"PPC",
- "name":"Peercoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"PEN",
- "name":"PEN",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"PHR",
- "name":"PHR",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"PIN",
- "name":"PIN",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"PC",
- "name":"Pinkcoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"PIO",
- "name":"PIO",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"PIZZA",
- "name":"PIZZA",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"PKB",
- "name":"PKB",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"PLN",
- "name":"PLN",
- "statuses":[
- "primary",
- "secondary"
- ]
- },
- {
- "code":"PLNC",
- "name":"PLNC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"PNK",
- "name":"PNK",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"POKE",
- "name":"POKE",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"PONZ2",
- "name":"PONZ2",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"PONZI",
- "name":"PONZI",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"PEX",
- "name":"PosEx",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"POST",
- "name":"POST",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"POT",
- "name":"Potcoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"PRE",
- "name":"PRE",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"PRES",
- "name":"PRES",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"PXI",
- "name":"Prime-XI",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"PRIME",
- "name":"PrimeChain",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"XPM",
- "name":"Primecoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"PRM",
- "name":"PRM",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"PRT",
- "name":"PRT",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"PSB",
- "name":"PSB",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"PSP",
- "name":"PSP",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"PSY",
- "name":"PSY",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"PTC",
- "name":"PTC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"PURE",
- "name":"PURE",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"PUTIN",
- "name":"PUTIN",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"PWR",
- "name":"PWR",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"PX",
- "name":"PX",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"PXL",
- "name":"PXL",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"QBC",
- "name":"QBC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"QBK",
- "name":"QBK",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"QCN",
- "name":"QCN",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"QORA",
- "name":"Qora",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"QTZ",
- "name":"QTZ",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"QRK",
- "name":"Quark",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"QTL",
- "name":"Quatloo",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"RADI",
- "name":"RADI",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"RADS",
- "name":"Radium",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"XRA",
- "name":"RateCoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"RBIT",
- "name":"RBIT",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"RCN",
- "name":"RCN",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"RED",
- "name":"RED",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"RDD",
- "name":"Reddcoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"REE",
- "name":"REE",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"REV",
- "name":"Revenu",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"RICHX",
- "name":"RICHX",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"RIC",
- "name":"Riecoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"RBT",
- "name":"Rimbit",
- "statuses":[
- "primary",
- "secondary"
- ]
- },
- {
- "code":"RIO",
- "name":"RIO",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"XRP",
- "name":"Ripple",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"RISE",
- "name":"RISE",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"RMS",
- "name":"RMS",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"RONIN",
- "name":"RONIN",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"ROYAL",
- "name":"ROYAL",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"RPC",
- "name":"RPC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"RRT",
- "name":"RRT",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"RBIES",
- "name":"Rubies",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"RUBIT",
- "name":"RUBIT",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"RUR",
- "name":"Ruble",
- "statuses":[
- "secondary"
- ]
- },
- {
- "code":"RBY",
- "name":"Rubycoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"RUST",
- "name":"RUST",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"RYCN",
- "name":"RYCN",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"SEC",
- "name":"Safe Exchange Coin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"SAK",
- "name":"SAK",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"SAR",
- "name":"SAR",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"SBD",
- "name":"SBD",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"SCAN",
- "name":"SCAN",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"SCB",
- "name":"SCB",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"SCN",
- "name":"SCN",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"SCOT",
- "name":"Scotcoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"SCRPT",
- "name":"SCRPT",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"SCRT",
- "name":"SCRT",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"SCT",
- "name":"SCT",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"SRC",
- "name":"SecureCoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"SED",
- "name":"SED",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"SXC",
- "name":"Sexcoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"SGD",
- "name":"SGD",
- "statuses":[
- "primary",
- "secondary"
- ]
- },
- {
- "code":"SH",
- "name":"SH",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"SDC",
- "name":"ShadowCash",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"SHELL",
- "name":"SHELL",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"SHI",
- "name":"SHI",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"SHIFT",
- "name":"Shift",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"SC",
- "name":"Siacoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"SIB",
- "name":"Siberian chervonets",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"SIGU",
- "name":"SIGU",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"SLFI",
- "name":"SLFI",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"SLING",
- "name":"Sling",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"SLK",
- "name":"SLK",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"SLS",
- "name":"SLS",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"SMC",
- "name":"SMC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"SMLY",
- "name":"SmileyCoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"SNGLS",
- "name":"SNGLS",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"SNRG",
- "name":"SNRG",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"SOIL",
- "name":"SOILcoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"SLR",
- "name":"Solarcoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"SONG",
- "name":"SongCoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"SOON",
- "name":"SOON",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"SP",
- "name":"SP",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"SPACE",
- "name":"SPACE",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"SPEX",
- "name":"SPEX",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"SPHR",
- "name":"Sphere",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"SPKTR",
- "name":"SPKTR",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"SPN",
- "name":"SPN",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"SPORT",
- "name":"SPORT",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"SPR",
- "name":"SpreadCoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"SPT",
- "name":"SPT",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"SPX",
- "name":"SPX",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"SSC",
- "name":"SSC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"STA",
- "name":"STA",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"STAR",
- "name":"STAR",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"START",
- "name":"Startcoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"STE",
- "name":"STE",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"XST",
- "name":"Stealthcoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"STEEM",
- "name":"Steem",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"XLM",
- "name":"Stellar",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"STR",
- "name":"Stellar",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"STEPS",
- "name":"Steps",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"SLG",
- "name":"Sterlingcoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"STHR",
- "name":"STHR",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"STL",
- "name":"STL",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"STO",
- "name":"STO",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"SJCX",
- "name":"Storjcoin X",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"STP",
- "name":"STP",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"STRAT",
- "name":"STRAT",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"STS",
- "name":"Stress",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"STV",
- "name":"STV",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"SUB",
- "name":"Subcriptio",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"UNITY",
- "name":"SuperNET",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"SWEET",
- "name":"SWEET",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"SWING",
- "name":"SWING",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"SYNC",
- "name":"SYNC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"AMP",
- "name":"Synereo",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"SYNX",
- "name":"SYNX",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"SYS",
- "name":"Syscoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"TAB",
- "name":"TAB",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"TAG",
- "name":"TagCoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"TAJ",
- "name":"TAJ",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"TAK",
- "name":"TAK",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"TAO",
- "name":"TAO",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"TBC",
- "name":"TBC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"TC",
- "name":"TC",
- "statuses":[
- "secondary"
- ]
- },
- {
- "code":"TCOIN",
- "name":"TCOIN",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"TCR",
- "name":"TCR",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"TDFB",
- "name":"TDFB",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"TDY",
- "name":"TDY",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"TEAM",
- "name":"TEAM",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"TEC",
- "name":"TEC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"TECH",
- "name":"TECH",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"TEK",
- "name":"TEKcoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"TRC",
- "name":"Terracoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"TESLA",
- "name":"TESLA",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"TES",
- "name":"TeslaCoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"TET",
- "name":"TET",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"THC",
- "name":"THC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"DAO",
- "name":"The DAO",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"TIA",
- "name":"TIA",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"TIX",
- "name":"Tickets",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"XTC",
- "name":"TileCoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"TIT",
- "name":"Titcoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"TMC",
- "name":"TMC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"TNG",
- "name":"TNG",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"TODAY",
- "name":"TODAY",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"TOKEN",
- "name":"TOKEN",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"TP1",
- "name":"TP1",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"TPC",
- "name":"TPC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"TPG",
- "name":"TPG",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"TX",
- "name":"Transfercoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"TRAP",
- "name":"TRAP",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"TRICK",
- "name":"TRICK",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"TRIG",
- "name":"TRIG",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"TROLL",
- "name":"TROLL",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"TRK",
- "name":"Truckcoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"TRUMP",
- "name":"TrumpCoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"TRUST",
- "name":"TRUST",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"TSC",
- "name":"TSC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"TWERK",
- "name":"TWERK",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"TWIST",
- "name":"TWIST",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"TWO",
- "name":"TWO",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"UAE",
- "name":"UAE",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"UB",
- "name":"UB",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"UFO",
- "name":"UFO Coin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"UIS",
- "name":"UIS",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"UAH",
- "name":"Ukrainian Hryvnia",
- "statuses":[
- "secondary"
- ]
- },
- {
- "code":"UTC",
- "name":"UltraCoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"UNB",
- "name":"UNB",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"UNC",
- "name":"UNC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"UNF",
- "name":"Unfed",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"UNIQ",
- "name":"UNIQ",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"UNIT",
- "name":"Universal Currency",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"UNO",
- "name":"Unobtanium",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"URC",
- "name":"URC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"URO",
- "name":"Uro",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"USD",
- "name":"US Dollar",
- "statuses":[
- "primary",
- "secondary"
- ]
- },
- {
- "code":"USDE",
- "name":"USDE",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"XVC",
- "name":"Vcash",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"VCN",
- "name":"VCN",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"VCOIN",
- "name":"VCOIN",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"VEC",
- "name":"VEC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"VEG",
- "name":"VEG",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"XVG",
- "name":"Verge",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"VRC",
- "name":"VeriCoin",
- "statuses":[
- "primary",
- "secondary"
- ]
- },
- {
- "code":"VTC",
- "name":"Vertcoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"VIA",
- "name":"Viacoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"VIP",
- "name":"VIP Tokens",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"VIRAL",
- "name":"Viral",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"VLT",
- "name":"VLT",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"VOOT",
- "name":"VootCoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"VOX",
- "name":"Voxels",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"VOYA",
- "name":"VOYA",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"VPN",
- "name":"VPNCoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"VRM",
- "name":"VRM",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"VRS",
- "name":"VRS",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"VTA",
- "name":"VTA",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"VTN",
- "name":"VTN",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"VTR",
- "name":"VTR",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"VTY",
- "name":"VTY",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"WA",
- "name":"WA",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"WAC",
- "name":"WAC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"WARP",
- "name":"WARP",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"WASH",
- "name":"WASH",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"WAV",
- "name":"WAV",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"WAVES",
- "name":"WAVES",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"WAY",
- "name":"WAY",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"WCN",
- "name":"WCN",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"WEX",
- "name":"WEX",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"WGC",
- "name":"WGC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"XWC",
- "name":"Whitecoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"WBB",
- "name":"Wild Beast Block",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"WINE",
- "name":"WINE",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"WLC",
- "name":"WLC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"WMC",
- "name":"WMC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"LOG",
- "name":"Woodcoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"WDC",
- "name":"Worldcoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"WRP",
- "name":"WRP",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"X2",
- "name":"X2",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"X2C",
- "name":"X2C",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"XAB",
- "name":"XAB",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"XAUR",
- "name":"XAUR",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"XAU",
- "name":"Xaurum",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"XBS",
- "name":"XBS",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"XBTS",
- "name":"XBTS",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"XBU",
- "name":"XBU",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"XCO",
- "name":"XCO",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"XC",
- "name":"XCurrency",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"XDB",
- "name":"XDB",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"XDE2",
- "name":"XDE2",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"MI",
- "name":"Xiaomicoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"XID",
- "name":"XID",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"XJO",
- "name":"XJO",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"XLTCG",
- "name":"XLTCG",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"XMINE",
- "name":"XMINE",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"XMS",
- "name":"XMS",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"XNG",
- "name":"XNG",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"XODUS",
- "name":"XODUS",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"XPC",
- "name":"XPC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"XPO",
- "name":"XPO",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"XPOKE",
- "name":"XPOKE",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"XPRO",
- "name":"XPRO",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"XPTX",
- "name":"XPTX",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"XQN",
- "name":"XQN",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"XRC",
- "name":"XRC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"XSEED",
- "name":"XSEED",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"XSY",
- "name":"XSY",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"XTP",
- "name":"XTP",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"XUP",
- "name":"XUP",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"YAC",
- "name":"Yacoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"YAY",
- "name":"YAY",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"YBC",
- "name":"Ybcoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"YMC",
- "name":"YMC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"YOC",
- "name":"YOC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"YOVI",
- "name":"YOVI",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"YUM",
- "name":"YUM",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"ZEC",
- "name":"Zcash",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"ZCL",
- "name":"Zcash classic",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"ZCC",
- "name":"ZCC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"ZCOIN",
- "name":"ZCOIN",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"XZC",
- "name":"Zcoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"ZECD",
- "name":"ZECD",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"ZEIT",
- "name":"Zeitcoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"ZET2",
- "name":"ZET2",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"ZET",
- "name":"Zetacoin",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"ZRC",
- "name":"ZiftrCOIN",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"ZLQ",
- "name":"ZLQ",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"ZMC",
- "name":"ZMC",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"ZNE",
- "name":"ZNE",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"ZNY",
- "name":"ZNY",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"ZS",
- "name":"ZS",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"ZUR",
- "name":"ZUR",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"ZXT",
- "name":"ZXT",
- "statuses":[
- "primary"
- ]
- },
- {
- "code":"ZYD",
- "name":"ZYD",
- "statuses":[
- "primary"
- ]
- }
- ]
-}
\ No newline at end of file +{ + "rows": [ + { + "code": "REP", + "name": "Augur", + "statuses": [ + "primary" + ] + }, + { + "code": "BCN", + "name": "Bytecoin", + "statuses": [ + "primary" + ] + }, + { + "code": "BTC", + "name": "Bitcoin", + "statuses": [ + "primary", + "secondary" + ] + }, + { + "code": "BTS", + "name": "BitShares", + "statuses": [ + "primary", + "secondary" + ] + }, + { + "code": "BLK", + "name": "Blackcoin", + "statuses": [ + "primary" + ] + }, + { + "code": "GBP", + "name": "British Pound Sterling", + "statuses": [ + "secondary" + ] + }, + { + "code": "CAD", + "name": "Canadian Dollar", + "statuses": [ + "secondary" + ] + }, + { + "code": "CNY", + "name": "Chinese Yuan", + "statuses": [ + "secondary" + ] + }, + { + "code": "DSH", + "name": "Dashcoin", + "statuses": [ + "primary" + ] + }, + { + "code": "DOGE", + "name": "Dogecoin", + "statuses": [ + "primary", + "secondary" + ] + }, + { + "code": "ETC", + "name": "Ethereum Classic", + "statuses": [ + "primary" + ] + }, + { + "code": "EUR", + "name": "Euro", + "statuses": [ + "primary", + "secondary" + ] + }, + { + "code": "GNO", + "name": "GNO", + "statuses": [ + "primary" + ] + }, + { + "code": "GNT", + "name": "GNT", + "statuses": [ + "primary" + ] + }, + { + "code": "JPY", + "name": "Japanese Yen", + "statuses": [ + "secondary" + ] + }, + { + "code": "LTC", + "name": "Litecoin", + "statuses": [ + "primary", + "secondary" + ] + }, + { + "code": "MAID", + "name": "MaidSafeCoin", + "statuses": [ + "primary" + ] + }, + { + "code": "XEM", + "name": "NEM", + "statuses": [ + "primary" + ] + }, + { + "code": "XLM", + "name": "Stellar", + "statuses": [ + "primary" + ] + }, + { + "code": "XMR", + "name": "Monero", + "statuses": [ + "primary", + "secondary" + ] + }, + { + "code": "XRP", + "name": "Ripple", + "statuses": [ + "primary" + ] + }, + { + "code": "RUR", + "name": "Ruble", + "statuses": [ + "secondary" + ] + }, + { + "code": "STEEM", + "name": "Steem", + "statuses": [ + "primary" + ] + }, + { + "code": "STRAT", + "name": "STRAT", + "statuses": [ + "primary" + ] + }, + { + "code": "UAH", + "name": "Ukrainian Hryvnia", + "statuses": [ + "secondary" + ] + }, + { + "code": "USD", + "name": "US Dollar", + "statuses": [ + "primary", + "secondary" + ] + }, + { + "code": "WAVES", + "name": "WAVES", + "statuses": [ + "primary" + ] + }, + { + "code": "ZEC", + "name": "Zcash", + "statuses": [ + "primary" + ] + } + ] +} diff --git a/ui/app/css/index.css b/ui/app/css/index.css index 033502f5a..808aafb4c 100644 --- a/ui/app/css/index.css +++ b/ui/app/css/index.css @@ -489,6 +489,47 @@ input.large-input { } /* buy eth warning screen */ +.custom-radios { + justify-content: space-around; + align-items: center; +} + + +.custom-radio-selected { + width: 17px; + height: 17px; + border: solid; + border-style: double; + border-radius: 15px; + border-width: 5px; + background: rgba(247, 134, 28, 1); + border-color: #F7F7F7; +} + +.custom-radio-inactive { + width: 14px; + height: 14px; + border: solid; + border-width: 1px; + border-radius: 24px; + border-color: #AEAEAE; +} + +.radio-titles { + color: rgba(247, 134, 28, 1); +} + +.radio-titles-subtext { + +} + +.selected-exchange { + +} + +.buy-radio { + +} .eth-warning{ transition: opacity 400ms ease-in, transform 400ms ease-in; diff --git a/ui/app/css/lib.css b/ui/app/css/lib.css index 670dc9fd0..910a24ee2 100644 --- a/ui/app/css/lib.css +++ b/ui/app/css/lib.css @@ -191,6 +191,10 @@ hr.horizontal-line { border: 3px solid #690496; } +.golden-square { + background: #EBB33F; +} + .pending-dot { background: red; left: 14px; diff --git a/ui/app/info.js b/ui/app/info.js index a6fdeb315..aa4503b62 100644 --- a/ui/app/info.js +++ b/ui/app/info.js @@ -52,7 +52,7 @@ InfoScreen.prototype.render = function () { h('div', { style: { - marginBottom: '10px', + marginBottom: '5px', }}, [ h('div', [ @@ -87,7 +87,7 @@ InfoScreen.prototype.render = function () { h('hr', { style: { - margin: '20px 0 ', + margin: '10px 0 ', width: '7em', }, }), @@ -97,6 +97,13 @@ InfoScreen.prototype.render = function () { paddingLeft: '30px', }}, [ + h('div.fa.fa-github', [ + h('a.info', { + href: 'https://github.com/MetaMask/faq', + target: '_blank', + onClick (event) { this.navigateTo(event.target.href) }, + }, 'Need Help? Read our FAQ!'), + ]), h('div', [ h('a', { href: 'https://metamask.io/', @@ -138,14 +145,6 @@ InfoScreen.prototype.render = function () { onClick () { this.navigateTo('mailto:help@metamask.io?subject=Feedback') }, }, 'Email us!'), ]), - - h('div.fa.fa-github', [ - h('a.info', { - href: 'https://github.com/MetaMask/metamask-plugin/issues', - target: '_blank', - onClick (event) { this.navigateTo(event.target.href) }, - }, 'Start a thread on GitHub'), - ]), ]), ]), ]), diff --git a/ui/app/reducers.js b/ui/app/reducers.js index c656af849..11efca529 100644 --- a/ui/app/reducers.js +++ b/ui/app/reducers.js @@ -44,6 +44,7 @@ function rootReducer (state, action) { window.logState = function () { var stateString = JSON.stringify(window.METAMASK_CACHED_LOG_STATE, removeSeedWords, 2) console.log(stateString) + return stateString } function removeSeedWords (key, value) { diff --git a/ui/app/reducers/app.js b/ui/app/reducers/app.js index 7ad1229e5..deacad0a7 100644 --- a/ui/app/reducers/app.js +++ b/ui/app/reducers/app.js @@ -315,7 +315,7 @@ function reduceApp (state, action) { case actions.COMPLETED_TX: log.debug('reducing COMPLETED_TX for tx ' + action.value) const otherUnconfActions = getUnconfActionList(state) - .filter(tx => tx.id !== action.value ) + .filter(tx => tx.id !== action.value) const hasOtherUnconfActions = otherUnconfActions.length > 0 if (hasOtherUnconfActions) { @@ -469,8 +469,9 @@ function reduceApp (state, action) { name: 'buyEth', context: appState.currentView.name, }, + identity: state.metamask.identities[action.value], buyView: { - subview: 'buyForm', + subview: 'Coinbase', amount: '15.00', buyAddress: action.value, formView: { @@ -480,36 +481,10 @@ function reduceApp (state, action) { }, }) - case actions.UPDATE_BUY_ADDRESS: - return extend(appState, { - buyView: { - subview: 'buyForm', - formView: { - coinbase: appState.buyView.formView.coinbase, - shapeshift: appState.buyView.formView.shapeshift, - }, - buyAddress: action.value, - amount: appState.buyView.amount, - }, - }) - - case actions.UPDATE_COINBASE_AMOUNT: - return extend(appState, { - buyView: { - subview: 'buyForm', - formView: { - coinbase: true, - shapeshift: false, - }, - buyAddress: appState.buyView.buyAddress, - amount: action.value, - }, - }) - case actions.COINBASE_SUBVIEW: return extend(appState, { buyView: { - subview: 'buyForm', + subview: 'Coinbase', formView: { coinbase: true, shapeshift: false, @@ -522,7 +497,7 @@ function reduceApp (state, action) { case actions.SHAPESHIFT_SUBVIEW: return extend(appState, { buyView: { - subview: 'buyForm', + subview: 'ShapeShift', formView: { coinbase: false, shapeshift: true, @@ -537,7 +512,7 @@ function reduceApp (state, action) { case actions.PAIR_UPDATE: return extend(appState, { buyView: { - subview: 'buyForm', + subview: 'ShapeShift', formView: { coinbase: false, shapeshift: true, diff --git a/ui/app/send.js b/ui/app/send.js index eb32d5e06..fd6994145 100644 --- a/ui/app/send.js +++ b/ui/app/send.js @@ -21,6 +21,8 @@ function mapStateToProps (state) { warning: state.appState.warning, network: state.metamask.network, addressBook: state.metamask.addressBook, + conversionRate: state.metamask.conversionRate, + currentCurrency: state.metamask.currentCurrency, } result.error = result.warning && result.warning.split('.')[0] @@ -40,13 +42,17 @@ function SendTransactionScreen () { SendTransactionScreen.prototype.render = function () { this.persistentFormParentId = 'send-tx-form' - var state = this.props - var address = state.address - var account = state.account - var identity = state.identity - var network = state.network - var identities = state.identities - var addressBook = state.addressBook + const props = this.props + const { + address, + account, + identity, + network, + identities, + addressBook, + conversionRate, + currentCurrency, + } = props return ( @@ -125,6 +131,8 @@ SendTransactionScreen.prototype.render = function () { h(EthBalance, { value: account && account.balance, + conversionRate, + currentCurrency, }), ]), @@ -147,7 +155,7 @@ SendTransactionScreen.prototype.render = function () { ]), // error message - state.error && h('span.error.flex-center', state.error), + props.error && h('span.error.flex-center', props.error), // 'to' field h('section.flex-row.flex-center', [ diff --git a/ui/app/util.js b/ui/app/util.js index 7a56bf6a0..ac3f42c6b 100644 --- a/ui/app/util.js +++ b/ui/app/util.js @@ -61,6 +61,7 @@ function miniAddressSummary (address) { function isValidAddress (address) { var prefixed = ethUtil.addHexPrefix(address) + if (address === '0x0000000000000000000000000000000000000000') return false return (isAllOneCase(prefixed) && ethUtil.isValidAddress(prefixed)) || ethUtil.isValidChecksumAddress(prefixed) } |