diff options
112 files changed, 9041 insertions, 929 deletions
diff --git a/.eslintignore b/.eslintignore index bfb2163d2..df49525be 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,2 +1 @@ app/scripts/lib/extension-instance.js -ui/app/conversion-util.js @@ -127,9 +127,9 @@ "no-whitespace-before-property": 2, "no-with": 2, "one-var": [2, { "initialized": "never" }], - "operator-linebreak": [1, "after", { "overrides": { "?": "before", ":": "before" } }], + "operator-linebreak": [1, "after", { "overrides": { "?": "ignore", ":": "ignore" } }], "padded-blocks": [1, "never"], - "quotes": [2, "single", "avoid-escape"], + "quotes": [2, "single", {"avoidEscape": true, "allowTemplateLiterals": true}], "semi": [2, "never"], "semi-spacing": [2, { "before": false, "after": true }], "space-before-blocks": [1, "always"], diff --git a/.gitignore b/.gitignore index 657c24099..af6449834 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,4 @@ dist - npm-debug.log node_modules temp @@ -8,7 +7,6 @@ temp app/bower_components test/bower_components package - .DS_Store builds/ notes.txt diff --git a/CHANGELOG.md b/CHANGELOG.md index 0fd1e83bf..44f8567e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,9 @@ - Add support for the new, default Ropsten Test Network. - Fix bug that would cause MetaMask to occasionally lose its StreamProvider connection and drop requests. +- Fix bug that would cause the Custom RPC menu item to not appear when Localhost 8545 was selected. +- Point ropsten faucet button to actual faucet. +- Phase out ethereumjs-util from our encryptor module. ## 2.13.8 2016-11-16 @@ -18,6 +18,12 @@ If you're a web dapp developer, we've got two types of guides for you: Uncompressed builds can be found in `/dist`, compressed builds can be found in `/builds` once they're built. +## Installing Local Builds on Chrome + +To install your locally built extension on Chrome, [follow this guide](http://stackoverflow.com/a/24577660/272576). + +The built extension is stored in `./dist/chrome/`. + ## Architecture [![Architecture Diagram](./docs/architecture.png)][1] @@ -26,6 +32,13 @@ If you're a web dapp developer, we've got two types of guides for you: ```bash npm install +npm start +``` + +## Build for Publishing + +```bash +npm run dist ``` #### In Chrome @@ -78,7 +91,7 @@ To enjoy the live-reloading that `gulp dev` offers while working on the `web3-pr 2. `npm install` in its folder. 3. Run `npm link` in its folder. 4. Run `npm link $DEP_NAME` in this project folder. - 5. Next time you `gulp dev` it will watch the dependency for changes as well! + 5. Next time you `npm start` it will watch the dependency for changes as well! ### Running Tests @@ -90,6 +103,10 @@ You can also test with a continuously watching process, via `npm run watch`. You can run the linter by itself with `gulp lint`. +#### Writing Browser Tests + +To write tests that will be run in the browser using QUnit, add your test files to `test/integration/lib`. + ### Deploying the UI You must be authorized already on the MetaMask plugin. diff --git a/app/scripts/background.js b/app/scripts/background.js index 652acc113..7cb25d8bf 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -10,6 +10,7 @@ const MetamaskController = require('./metamask-controller') const extension = require('./lib/extension') const STORAGE_KEY = 'metamask-config' +const METAMASK_DEBUG = 'GULP_METAMASK_DEBUG' var popupIsOpen = false const controller = new MetamaskController({ @@ -21,7 +22,7 @@ const controller = new MetamaskController({ setData, loadData, }) -const idStore = controller.idStore +const keyringController = controller.keyringController function triggerUi () { if (!popupIsOpen) notification.show() @@ -29,7 +30,7 @@ function triggerUi () { // On first install, open a window to MetaMask website to how-it-works. extension.runtime.onInstalled.addListener(function (details) { - if (details.reason === 'install') { + if ((details.reason === 'install') && (!METAMASK_DEBUG)) { extension.tabs.create({url: 'https://metamask.io/#how-it-works'}) } }) @@ -82,7 +83,7 @@ function setupControllerConnection (stream) { // push updates to popup controller.ethStore.on('update', controller.sendUpdate.bind(controller)) controller.listeners.push(remote) - idStore.on('update', controller.sendUpdate.bind(controller)) + keyringController.on('update', controller.sendUpdate.bind(controller)) // teardown on disconnect eos(stream, () => { @@ -96,9 +97,9 @@ function setupControllerConnection (stream) { // plugin badge text // -idStore.on('update', updateBadge) +keyringController.on('update', updateBadge) -function updateBadge (state) { +function updateBadge () { var label = '' var unconfTxs = controller.configManager.unconfirmedTxs() var unconfTxLen = Object.keys(unconfTxs).length diff --git a/app/scripts/contentscript.js b/app/scripts/contentscript.js index e2a968ac9..ab64dc9fa 100644 --- a/app/scripts/contentscript.js +++ b/app/scripts/contentscript.js @@ -6,7 +6,7 @@ const extension = require('./lib/extension') const fs = require('fs') const path = require('path') -const inpageText = fs.readFileSync(path.join(__dirname + '/inpage.js')).toString() +const inpageText = fs.readFileSync(path.join(__dirname, 'inpage.js')).toString() // Eventually this streaming injection could be replaced with: // https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XPCOM/Language_Bindings/Components.utils.exportFunction @@ -20,9 +20,8 @@ if (shouldInjectWeb3()) { setupStreams() } -function setupInjection(){ +function setupInjection () { try { - // inject in-page script var scriptTag = document.createElement('script') scriptTag.src = extension.extension.getURL('scripts/inpage.js') @@ -31,14 +30,12 @@ function setupInjection(){ var container = document.head || document.documentElement // append as first child container.insertBefore(scriptTag, container.children[0]) - } catch (e) { console.error('Metamask injection failed.', e) } } -function setupStreams(){ - +function setupStreams () { // setup communication to page and plugin var pageStream = new LocalMessageDuplexStream({ name: 'contentscript', @@ -65,14 +62,13 @@ function setupStreams(){ mx.ignoreStream('provider') mx.ignoreStream('publicConfig') mx.ignoreStream('reload') - } -function shouldInjectWeb3(){ +function shouldInjectWeb3 () { return isAllowedSuffix(window.location.href) } -function isAllowedSuffix(testCase) { +function isAllowedSuffix (testCase) { var prohibitedTypes = ['xml', 'pdf'] var currentUrl = window.location.href var currentRegex diff --git a/app/scripts/inpage.js b/app/scripts/inpage.js index 7d43bd20e..42332d92e 100644 --- a/app/scripts/inpage.js +++ b/app/scripts/inpage.js @@ -43,6 +43,7 @@ reloadStream.once('data', triggerReload) // var pingChannel = inpageProvider.multiStream.createStream('pingpong') // var pingStream = new PingStream({ objectMode: true }) // wait for first successful reponse + // disable pingStream until https://github.com/MetaMask/metamask-plugin/issues/746 is resolved more gracefully // metamaskStream.once('data', function(){ // pingStream.pipe(pingChannel).pipe(pingStream) @@ -51,7 +52,7 @@ reloadStream.once('data', triggerReload) // set web3 defaultAcount inpageProvider.publicConfigStore.subscribe(function (state) { - web3.eth.defaultAccount = state.selectedAddress + web3.eth.defaultAccount = state.selectedAccount }) // diff --git a/app/scripts/keyring-controller.js b/app/scripts/keyring-controller.js new file mode 100644 index 000000000..40c9695dd --- /dev/null +++ b/app/scripts/keyring-controller.js @@ -0,0 +1,889 @@ +const async = require('async') +const ethUtil = require('ethereumjs-util') +const EthQuery = require('eth-query') +const bip39 = require('bip39') +const Transaction = require('ethereumjs-tx') +const EventEmitter = require('events').EventEmitter +const filter = require('promise-filter') +const normalize = require('./lib/sig-util').normalize +const encryptor = require('./lib/encryptor') +const messageManager = require('./lib/message-manager') +const IdStoreMigrator = require('./lib/idStore-migrator') +const BN = ethUtil.BN + +// Keyrings: +const SimpleKeyring = require('./keyrings/simple') +const HdKeyring = require('./keyrings/hd') +const keyringTypes = [ + SimpleKeyring, + HdKeyring, +] + +const createId = require('./lib/random-id') + +module.exports = class KeyringController extends EventEmitter { + + // PUBLIC METHODS + // + // THE FIRST SECTION OF METHODS ARE PUBLIC-FACING, + // MEANING THEY ARE USED BY CONSUMERS OF THIS CLASS. + // + // THEIR SURFACE AREA SHOULD BE CHANGED WITH GREAT CARE. + + constructor (opts) { + super() + this.configManager = opts.configManager + this.ethStore = opts.ethStore + this.encryptor = encryptor + this.keyringTypes = keyringTypes + + this.keyrings = [] + this.identities = {} // Essentially a name hash + + this._unconfTxCbs = {} + this._unconfMsgCbs = {} + + this.getNetwork = opts.getNetwork + + // TEMPORARY UNTIL FULL DEPRECATION: + this.idStoreMigrator = new IdStoreMigrator({ + configManager: this.configManager, + }) + } + + // Set Store + // + // Allows setting the ethStore after the constructor. + // This is currently required because of the initialization order + // of the ethStore and this class. + // + // Eventually would be nice to be able to add this in the constructor. + setStore (ethStore) { + this.ethStore = ethStore + } + + // Full Update + // returns Promise( @object state ) + // + // Emits the `update` event and + // returns a Promise that resolves to the current state. + // + // Frequently used to end asynchronous chains in this class, + // indicating consumers can often either listen for updates, + // or accept a state-resolving promise to consume their results. + // + // Not all methods end with this, that might be a nice refactor. + fullUpdate() { + this.emit('update') + return Promise.resolve(this.getState()) + } + + // Get State + // returns @object state + // + // This method returns a hash representing the current state + // that the keyringController manages. + // + // It is extended in the MetamaskController along with the EthStore + // state, and its own state, to create the metamask state branch + // that is passed to the UI. + // + // This is currently a rare example of a synchronously resolving method + // in this class, but will need to be Promisified when we move our + // persistence to an async model. + getState () { + const configManager = this.configManager + const address = configManager.getSelectedAccount() + const wallet = configManager.getWallet() // old style vault + const vault = configManager.getVault() // new style vault + + return { + seedWords: this.configManager.getSeedWords(), + isInitialized: (!!wallet || !!vault), + isUnlocked: Boolean(this.password), + isDisclaimerConfirmed: this.configManager.getConfirmedDisclaimer(), // AUDIT this.configManager.getConfirmedDisclaimer(), + unconfTxs: this.configManager.unconfirmedTxs(), + transactions: this.configManager.getTxList(), + unconfMsgs: messageManager.unconfirmedMsgs(), + messages: messageManager.getMsgList(), + selectedAccount: address, + shapeShiftTxList: this.configManager.getShapeShiftTxList(), + currentFiat: this.configManager.getCurrentFiat(), + conversionRate: this.configManager.getConversionRate(), + conversionDate: this.configManager.getConversionDate(), + keyringTypes: this.keyringTypes.map(krt => krt.type), + identities: this.identities, + } + } + + // Create New Vault And Keychain + // @string password - The password to encrypt the vault with + // + // returns Promise( @object state ) + // + // Destroys any old encrypted storage, + // creates a new encrypted store with the given password, + // randomly creates a new HD wallet with 1 account, + // faucets that account on the testnet. + createNewVaultAndKeychain (password) { + return this.persistAllKeyrings(password) + .then(this.createFirstKeyTree.bind(this)) + .then(this.fullUpdate.bind(this)) + } + + // CreateNewVaultAndRestore + // @string password - The password to encrypt the vault with + // @string seed - The BIP44-compliant seed phrase. + // + // returns Promise( @object state ) + // + // Destroys any old encrypted storage, + // creates a new encrypted store with the given password, + // creates a new HD wallet from the given seed with 1 account. + createNewVaultAndRestore (password, seed) { + if (typeof password !== 'string') { + return Promise.reject('Password must be text.') + } + + if (!bip39.validateMnemonic(seed)) { + return Promise.reject('Seed phrase is invalid.') + } + + this.clearKeyrings() + + return this.persistAllKeyrings(password) + .then(() => { + return this.addNewKeyring('HD Key Tree', { + mnemonic: seed, + numberOfAccounts: 1, + }) + }).then(() => { + const firstKeyring = this.keyrings[0] + return firstKeyring.getAccounts() + }) + .then((accounts) => { + const firstAccount = accounts[0] + const hexAccount = normalize(firstAccount) + this.configManager.setSelectedAccount(hexAccount) + return this.setupAccounts(accounts) + }) + .then(this.persistAllKeyrings.bind(this, password)) + .then(this.fullUpdate.bind(this)) + } + + // PlaceSeedWords + // returns Promise( @object state ) + // + // Adds the current vault's seed words to the UI's state tree. + // + // Used when creating a first vault, to allow confirmation. + // Also used when revealing the seed words in the confirmation view. + placeSeedWords () { + const firstKeyring = this.keyrings[0] + return firstKeyring.serialize() + .then((serialized) => { + const seedWords = serialized.mnemonic + this.configManager.setSeedWords(seedWords) + return this.fullUpdate() + }) + } + + // ClearSeedWordCache + // + // returns Promise( @string currentSelectedAccount ) + // + // Removes the current vault's seed words from the UI's state tree, + // ensuring they are only ever available in the background process. + clearSeedWordCache () { + this.configManager.setSeedWords(null) + return Promise.resolve(this.configManager.getSelectedAccount()) + } + + // Set Locked + // returns Promise( @object state ) + // + // This method deallocates all secrets, and effectively locks metamask. + setLocked () { + this.password = null + this.keyrings = [] + return this.fullUpdate() + } + + // Submit Password + // @string password + // + // returns Promise( @object state ) + // + // Attempts to decrypt the current vault and load its keyrings + // into memory. + // + // Temporarily also migrates any old-style vaults first, as well. + // (Pre MetaMask 3.0.0) + submitPassword (password) { + return this.migrateOldVaultIfAny(password) + .then(() => { + return this.unlockKeyrings(password) + }) + .then((keyrings) => { + this.keyrings = keyrings + return this.fullUpdate() + }) + } + + // Add New Keyring + // @string type + // @object opts + // + // returns Promise( @Keyring keyring ) + // + // Adds a new Keyring of the given `type` to the vault + // and the current decrypted Keyrings array. + // + // All Keyring classes implement a unique `type` string, + // and this is used to retrieve them from the keyringTypes array. + addNewKeyring (type, opts) { + const Keyring = this.getKeyringClassForType(type) + const keyring = new Keyring(opts) + return keyring.getAccounts() + .then((accounts) => { + this.keyrings.push(keyring) + return this.setupAccounts(accounts) + }) + .then(() => { return this.password }) + .then(this.persistAllKeyrings.bind(this)) + .then(() => { + return keyring + }) + } + + // Add New Account + // @number keyRingNum + // + // returns Promise( @object state ) + // + // Calls the `addAccounts` method on the Keyring + // in the kryings array at index `keyringNum`, + // and then saves those changes. + addNewAccount (keyRingNum = 0) { + const ring = this.keyrings[keyRingNum] + return ring.addAccounts(1) + .then(this.setupAccounts.bind(this)) + .then(this.persistAllKeyrings.bind(this)) + .then(this.fullUpdate.bind(this)) + } + + // Set Selected Account + // @string address + // + // returns Promise( @string address ) + // + // Sets the state's `selectedAccount` value + // to the specified address. + setSelectedAccount (address) { + var addr = normalize(address) + this.configManager.setSelectedAccount(addr) + return Promise.resolve(addr) + } + + // Save Account Label + // @string account + // @string label + // + // returns Promise( @string label ) + // + // Persists a nickname equal to `label` for the specified account. + saveAccountLabel (account, label) { + const address = normalize(account) + const configManager = this.configManager + configManager.setNicknameForWallet(address, label) + this.identities[address].name = label + return Promise.resolve(label) + } + + // Export Account + // @string address + // + // returns Promise( @string privateKey ) + // + // Requests the private key from the keyring controlling + // the specified address. + // + // Returns a Promise that may resolve with the private key string. + exportAccount (address) { + try { + return this.getKeyringForAccount(address) + .then((keyring) => { + return keyring.exportAccount(normalize(address)) + }) + } catch (e) { + return Promise.reject(e) + } + } + + + // SIGNING RELATED METHODS + // + // SIGN, SUBMIT TX, CANCEL, AND APPROVE. + // THIS SECTION INVOLVES THE REQUEST, STORING, AND SIGNING OF DATA + // WITH THE KEYS STORED IN THIS CONTROLLER. + + + // Add Unconfirmed Transaction + // @object txParams + // @function onTxDoneCb + // @function cb + // + // Calls back `cb` with @object txData = { txParams } + // Calls back `onTxDoneCb` with `true` or an `error` depending on result. + // + // Prepares the given `txParams` for final confirmation and approval. + // Estimates gas and other preparatory steps. + // Caches the requesting Dapp's callback, `onTxDoneCb`, for resolution later. + addUnconfirmedTransaction (txParams, onTxDoneCb, cb) { + const configManager = this.configManager + + // create txData obj with parameters and meta data + var time = (new Date()).getTime() + var txId = createId() + txParams.metamaskId = txId + txParams.metamaskNetworkId = this.getNetwork() + var txData = { + id: txId, + txParams: txParams, + time: time, + status: 'unconfirmed', + gasMultiplier: configManager.getGasMultiplier() || 1, + metamaskNetworkId: this.getNetwork(), + } + + // keep the onTxDoneCb around for after approval/denial (requires user interaction) + // This onTxDoneCb fires completion to the Dapp's write operation. + this._unconfTxCbs[txId] = onTxDoneCb + + var provider = this.ethStore._query.currentProvider + var query = new EthQuery(provider) + + // calculate metadata for tx + this.analyzeTxGasUsage(query, txData, this.txDidComplete.bind(this, txData, cb)) + } + + estimateTxGas (query, txData, blockGasLimitHex, cb) { + const txParams = txData.txParams + // check if gasLimit is already specified + txData.gasLimitSpecified = Boolean(txParams.gas) + // if not, fallback to block gasLimit + if (!txData.gasLimitSpecified) { + txParams.gas = blockGasLimitHex + } + // run tx, see if it will OOG + query.estimateGas(txParams, cb) + } + + checkForTxGasError (txData, estimatedGasHex, cb) { + txData.estimatedGas = estimatedGasHex + // all gas used - must be an error + if (estimatedGasHex === txData.txParams.gas) { + txData.simulationFails = true + } + cb() + } + + setTxGas (txData, blockGasLimitHex, cb) { + const txParams = txData.txParams + // if OOG, nothing more to do + if (txData.simulationFails) { + cb() + return + } + // if gasLimit was specified and doesnt OOG, + // use original specified amount + if (txData.gasLimitSpecified) { + txData.estimatedGas = txParams.gas + cb() + return + } + // if gasLimit not originally specified, + // try adding an additional gas buffer to our estimation for safety + const estimatedGasBn = new BN(ethUtil.stripHexPrefix(txData.estimatedGas), 16) + const blockGasLimitBn = new BN(ethUtil.stripHexPrefix(blockGasLimitHex), 16) + const estimationWithBuffer = new BN(this.addGasBuffer(estimatedGasBn), 16) + // added gas buffer is too high + if (estimationWithBuffer.gt(blockGasLimitBn)) { + txParams.gas = txData.estimatedGas + // added gas buffer is safe + } else { + const gasWithBufferHex = ethUtil.intToHex(estimationWithBuffer) + txParams.gas = gasWithBufferHex + } + cb() + return + } + + txDidComplete (txData, cb, err) { + if (err) return cb(err) + const configManager = this.configManager + configManager.addTx(txData) + // signal update + this.emit('update') + // signal completion of add tx + cb(null, txData) + } + + analyzeTxGasUsage (query, txData, cb) { + query.getBlockByNumber('latest', true, (err, block) => { + if (err) return cb(err) + async.waterfall([ + this.estimateTxGas.bind(this, query, txData, block.gasLimit), + this.checkForTxGasError.bind(this, txData), + this.setTxGas.bind(this, txData, block.gasLimit), + ], cb) + }) + } + + // Cancel Transaction + // @string txId + // @function cb + // + // Calls back `cb` with no error if provided. + // + // Forgets any tx matching `txId`. + cancelTransaction (txId, cb) { + const configManager = this.configManager + var approvalCb = this._unconfTxCbs[txId] || noop + + // reject tx + approvalCb(null, false) + // clean up + configManager.rejectTx(txId) + delete this._unconfTxCbs[txId] + + if (cb && typeof cb === 'function') { + cb() + } + } + + // Approve Transaction + // @string txId + // @function cb + // + // Calls back `cb` with no error always. + // + // Attempts to sign a Transaction with `txId` + // and submit it to the blockchain. + // + // Calls back the cached Dapp's confirmation callback, also. + approveTransaction (txId, cb) { + const configManager = this.configManager + var approvalCb = this._unconfTxCbs[txId] || noop + + // accept tx + cb() + approvalCb(null, true) + // clean up + configManager.confirmTx(txId) + delete this._unconfTxCbs[txId] + this.emit('update') + } + + signTransaction (txParams, cb) { + try { + const address = normalize(txParams.from) + return this.getKeyringForAccount(address) + .then((keyring) => { + // Handle gas pricing + var gasMultiplier = this.configManager.getGasMultiplier() || 1 + var gasPrice = new BN(ethUtil.stripHexPrefix(txParams.gasPrice), 16) + gasPrice = gasPrice.mul(new BN(gasMultiplier * 100, 10)).div(new BN(100, 10)) + txParams.gasPrice = ethUtil.intToHex(gasPrice.toNumber()) + + // normalize values + txParams.to = normalize(txParams.to) + txParams.from = normalize(txParams.from) + txParams.value = normalize(txParams.value) + txParams.data = normalize(txParams.data) + txParams.gasLimit = normalize(txParams.gasLimit || txParams.gas) + txParams.nonce = normalize(txParams.nonce) + + const tx = new Transaction(txParams) + return keyring.signTransaction(address, tx) + }) + .then((tx) => { + // Add the tx hash to the persisted meta-tx object + var txHash = ethUtil.bufferToHex(tx.hash()) + var metaTx = this.configManager.getTx(txParams.metamaskId) + metaTx.hash = txHash + this.configManager.updateTx(metaTx) + + // return raw serialized tx + var rawTx = ethUtil.bufferToHex(tx.serialize()) + cb(null, rawTx) + }) + } catch (e) { + cb(e) + } + } + + // Add Unconfirmed Message + // @object msgParams + // @function cb + // + // Does not call back, only emits an `update` event. + // + // Adds the given `msgParams` and `cb` to a local cache, + // for displaying to a user for approval before signing or canceling. + addUnconfirmedMessage (msgParams, cb) { + // create txData obj with parameters and meta data + var time = (new Date()).getTime() + var msgId = createId() + var msgData = { + id: msgId, + msgParams: msgParams, + time: time, + status: 'unconfirmed', + } + messageManager.addMsg(msgData) + console.log('addUnconfirmedMessage:', msgData) + + // keep the cb around for after approval (requires user interaction) + // This cb fires completion to the Dapp's write operation. + this._unconfMsgCbs[msgId] = cb + + // signal update + this.emit('update') + return msgId + } + + // Cancel Message + // @string msgId + // @function cb (optional) + // + // Calls back to cached `unconfMsgCb`. + // Calls back to `cb` if provided. + // + // Forgets any messages matching `msgId`. + cancelMessage (msgId, cb) { + var approvalCb = this._unconfMsgCbs[msgId] || noop + + // reject tx + approvalCb(null, false) + // clean up + messageManager.rejectMsg(msgId) + delete this._unconfTxCbs[msgId] + + if (cb && typeof cb === 'function') { + cb() + } + } + + // Sign Message + // @object msgParams + // @function cb + // + // returns Promise(@buffer rawSig) + // calls back @function cb with @buffer rawSig + // calls back cached Dapp's @function unconfMsgCb. + // + // Attempts to sign the provided @object msgParams. + signMessage (msgParams, cb) { + try { + + const msgId = msgParams.metamaskId + delete msgParams.metamaskId + const approvalCb = this._unconfMsgCbs[msgId] || noop + + const address = normalize(msgParams.from) + return this.getKeyringForAccount(address) + .then((keyring) => { + return keyring.signMessage(address, msgParams.data) + }).then((rawSig) => { + cb(null, rawSig) + approvalCb(null, true) + return rawSig + }) + } catch (e) { + cb(e) + } + } + + // PRIVATE METHODS + // + // THESE METHODS ARE ONLY USED INTERNALLY TO THE KEYRING-CONTROLLER + // AND SO MAY BE CHANGED MORE LIBERALLY THAN THE ABOVE METHODS. + + // Migrate Old Vault If Any + // @string password + // + // returns Promise() + // + // Temporary step used when logging in. + // Checks if old style (pre-3.0.0) Metamask Vault exists. + // If so, persists that vault in the new vault format + // with the provided password, so the other unlock steps + // may be completed without interruption. + migrateOldVaultIfAny (password) { + const shouldMigrate = !!this.configManager.getWallet() && !this.configManager.getVault() + return this.idStoreMigrator.migratedVaultForPassword(password) + .then((serialized) => { + this.password = password + + if (serialized && shouldMigrate) { + return this.restoreKeyring(serialized) + .then(keyring => keyring.getAccounts()) + .then((accounts) => { + this.configManager.setSelectedAccount(accounts[0]) + return this.persistAllKeyrings() + }) + } else { + return Promise.resolve() + } + }) + } + + // Create First Key Tree + // returns @Promise + // + // Clears the vault, + // creates a new one, + // creates a random new HD Keyring with 1 account, + // makes that account the selected account, + // faucets that account on testnet, + // puts the current seed words into the state tree. + createFirstKeyTree () { + this.clearKeyrings() + return this.addNewKeyring('HD Key Tree', {numberOfAccounts: 1}) + .then(() => { + return this.keyrings[0].getAccounts() + }) + .then((accounts) => { + const firstAccount = accounts[0] + const hexAccount = normalize(firstAccount) + this.configManager.setSelectedAccount(hexAccount) + this.emit('newAccount', hexAccount) + return this.setupAccounts(accounts) + }).then(() => { + return this.placeSeedWords() + }) + .then(this.persistAllKeyrings.bind(this)) + } + + // Setup Accounts + // @array accounts + // + // returns @Promise(@object account) + // + // Initializes the provided account array + // Gives them numerically incremented nicknames, + // and adds them to the ethStore for regular balance checking. + setupAccounts (accounts) { + return this.getAccounts() + .then((loadedAccounts) => { + const arr = accounts || loadedAccounts + return Promise.all(arr.map((account) => { + return this.getBalanceAndNickname(account) + })) + }) + } + + // Get Balance And Nickname + // @string account + // + // returns Promise( @string label ) + // + // Takes an account address and an iterator representing + // the current number of named accounts. + getBalanceAndNickname (account) { + if (!account) { + throw new Error('Problem loading account.') + } + const address = normalize(account) + this.ethStore.addAccount(address) + return this.createNickname(address) + } + + // Create Nickname + // @string address + // + // returns Promise( @string label ) + // + // Takes an address, and assigns it an incremented nickname, persisting it. + createNickname (address) { + const hexAddress = normalize(address) + var i = Object.keys(this.identities).length + const oldNickname = this.configManager.nicknameForWallet(address) + const name = oldNickname || `Account ${++i}` + this.identities[hexAddress] = { + address: hexAddress, + name, + } + return this.saveAccountLabel(hexAddress, name) + } + + // Persist All Keyrings + // @password string + // + // returns Promise + // + // Iterates the current `keyrings` array, + // serializes each one into a serialized array, + // encrypts that array with the provided `password`, + // and persists that encrypted string to storage. + persistAllKeyrings (password = this.password) { + if (typeof password === 'string') { + this.password = password + } + return Promise.all(this.keyrings.map((keyring) => { + return Promise.all([keyring.type, keyring.serialize()]) + .then((serializedKeyringArray) => { + // Label the output values on each serialized Keyring: + return { + type: serializedKeyringArray[0], + data: serializedKeyringArray[1], + } + }) + })) + .then((serializedKeyrings) => { + return this.encryptor.encrypt(this.password, serializedKeyrings) + }) + .then((encryptedString) => { + this.configManager.setVault(encryptedString) + return true + }) + } + + // Unlock Keyrings + // @string password + // + // returns Promise( @array keyrings ) + // + // Attempts to unlock the persisted encrypted storage, + // initializing the persisted keyrings to RAM. + unlockKeyrings (password) { + const encryptedVault = this.configManager.getVault() + return this.encryptor.decrypt(password, encryptedVault) + .then((vault) => { + this.password = password + vault.forEach(this.restoreKeyring.bind(this)) + return this.keyrings + }) + } + + // Restore Keyring + // @object serialized + // + // returns Promise( @Keyring deserialized ) + // + // Attempts to initialize a new keyring from the provided + // serialized payload. + // + // On success, returns the resulting @Keyring instance. + restoreKeyring (serialized) { + const { type, data } = serialized + const Keyring = this.getKeyringClassForType(type) + const keyring = new Keyring() + return keyring.deserialize(data) + .then(() => { + return keyring.getAccounts() + }) + .then((accounts) => { + return this.setupAccounts(accounts) + }) + .then(() => { + this.keyrings.push(keyring) + return keyring + }) + } + + // Get Keyring Class For Type + // @string type + // + // Returns @class Keyring + // + // Searches the current `keyringTypes` array + // for a Keyring class whose unique `type` property + // matches the provided `type`, + // returning it if it exists. + getKeyringClassForType (type) { + return this.keyringTypes.find(kr => kr.type === type) + } + + // Get Accounts + // returns Promise( @Array[ @string accounts ] ) + // + // Returns the public addresses of all current accounts + // managed by all currently unlocked keyrings. + getAccounts () { + const keyrings = this.keyrings || [] + return Promise.all(keyrings.map(kr => kr.getAccounts())) + .then((keyringArrays) => { + return keyringArrays.reduce((res, arr) => { + return res.concat(arr) + }, []) + }) + } + + // Get Keyring For Account + // @string address + // + // returns Promise(@Keyring keyring) + // + // Returns the currently initialized keyring that manages + // the specified `address` if one exists. + getKeyringForAccount (address) { + const hexed = normalize(address) + + return Promise.all(this.keyrings.map((keyring) => { + return Promise.all([ + keyring, + keyring.getAccounts(), + ]) + })) + .then(filter((candidate) => { + const accounts = candidate[1].map(normalize) + return accounts.includes(hexed) + })) + .then((winners) => { + if (winners && winners.length > 0) { + return winners[0][0] + } else { + throw new Error('No keyring found for the requested account.') + } + }) + } + + // Add Gas Buffer + // @string gas (as hexadecimal value) + // + // returns @string bufferedGas (as hexadecimal value) + // + // Adds a healthy buffer of gas to an initial gas estimate. + addGasBuffer (gas) { + const gasBuffer = new BN('100000', 10) + const bnGas = new BN(ethUtil.stripHexPrefix(gas), 16) + const correct = bnGas.add(gasBuffer) + return ethUtil.addHexPrefix(correct.toString(16)) + } + + // Clear Keyrings + // + // Deallocates all currently managed keyrings and accounts. + // Used before initializing a new vault. + clearKeyrings () { + let accounts + try { + accounts = Object.keys(this.ethStore._currentState.accounts) + } catch (e) { + accounts = [] + } + accounts.forEach((address) => { + this.ethStore.removeAccount(address) + }) + + this.keyrings = [] + this.identities = {} + this.configManager.setSelectedAccount() + } + +} + + +function noop () {} diff --git a/app/scripts/keyrings/hd.js b/app/scripts/keyrings/hd.js new file mode 100644 index 000000000..cfec56561 --- /dev/null +++ b/app/scripts/keyrings/hd.js @@ -0,0 +1,111 @@ +const EventEmitter = require('events').EventEmitter +const hdkey = require('ethereumjs-wallet/hdkey') +const bip39 = require('bip39') +const ethUtil = require('ethereumjs-util') + +// *Internal Deps +const sigUtil = require('../lib/sig-util') + +// Options: +const hdPathString = `m/44'/60'/0'/0` +const type = 'HD Key Tree' + +class HdKeyring extends EventEmitter { + + /* PUBLIC METHODS */ + + constructor (opts = {}) { + super() + this.type = type + this.deserialize(opts) + } + + serialize () { + return Promise.resolve({ + mnemonic: this.mnemonic, + numberOfAccounts: this.wallets.length, + }) + } + + deserialize (opts = {}) { + this.opts = opts || {} + this.wallets = [] + this.mnemonic = null + this.root = null + + if ('mnemonic' in opts) { + this._initFromMnemonic(opts.mnemonic) + } + + if ('numberOfAccounts' in opts) { + this.addAccounts(opts.numberOfAccounts) + } + + return Promise.resolve() + } + + addAccounts (numberOfAccounts = 1) { + if (!this.root) { + this._initFromMnemonic(bip39.generateMnemonic()) + } + + const oldLen = this.wallets.length + const newWallets = [] + for (let i = oldLen; i < numberOfAccounts + oldLen; i++) { + const child = this.root.deriveChild(i) + const wallet = child.getWallet() + newWallets.push(wallet) + this.wallets.push(wallet) + } + const hexWallets = newWallets.map(w => w.getAddress().toString('hex')) + return Promise.resolve(hexWallets) + } + + getAccounts () { + return Promise.resolve(this.wallets.map(w => w.getAddress().toString('hex'))) + } + + // tx is an instance of the ethereumjs-transaction class. + signTransaction (address, tx) { + const wallet = this._getWalletForAccount(address) + var privKey = wallet.getPrivateKey() + tx.sign(privKey) + return Promise.resolve(tx) + } + + // For eth_sign, we need to sign transactions: + signMessage (withAccount, data) { + const wallet = this._getWalletForAccount(withAccount) + const message = ethUtil.removeHexPrefix(data) + var privKey = wallet.getPrivateKey() + var msgSig = ethUtil.ecsign(new Buffer(message, 'hex'), privKey) + var rawMsgSig = ethUtil.bufferToHex(sigUtil.concatSig(msgSig.v, msgSig.r, msgSig.s)) + return Promise.resolve(rawMsgSig) + } + + exportAccount (address) { + const wallet = this._getWalletForAccount(address) + return Promise.resolve(wallet.getPrivateKey().toString('hex')) + } + + + /* PRIVATE METHODS */ + + _initFromMnemonic (mnemonic) { + this.mnemonic = mnemonic + const seed = bip39.mnemonicToSeed(mnemonic) + this.hdWallet = hdkey.fromMasterSeed(seed) + this.root = this.hdWallet.derivePath(hdPathString) + } + + + _getWalletForAccount (account) { + return this.wallets.find((w) => { + const address = w.getAddress().toString('hex') + return ((address === account) || (sigUtil.normalize(address) === account)) + }) + } +} + +HdKeyring.type = type +module.exports = HdKeyring diff --git a/app/scripts/keyrings/simple.js b/app/scripts/keyrings/simple.js new file mode 100644 index 000000000..8f339cf80 --- /dev/null +++ b/app/scripts/keyrings/simple.js @@ -0,0 +1,78 @@ +const EventEmitter = require('events').EventEmitter +const Wallet = require('ethereumjs-wallet') +const ethUtil = require('ethereumjs-util') +const type = 'Simple Key Pair' +const sigUtil = require('../lib/sig-util') + +class SimpleKeyring extends EventEmitter { + + /* PUBLIC METHODS */ + + constructor (opts) { + super() + this.type = type + this.opts = opts || {} + this.wallets = [] + } + + serialize () { + return Promise.resolve(this.wallets.map(w => w.getPrivateKey().toString('hex'))) + } + + deserialize (wallets = []) { + this.wallets = wallets.map((w) => { + var b = new Buffer(w, 'hex') + const wallet = Wallet.fromPrivateKey(b) + return wallet + }) + return Promise.resolve() + } + + addAccounts (n = 1) { + var newWallets = [] + for (var i = 0; i < n; i++) { + newWallets.push(Wallet.generate()) + } + this.wallets = this.wallets.concat(newWallets) + const hexWallets = newWallets.map(w => w.getAddress().toString('hex')) + return Promise.resolve(hexWallets) + } + + getAccounts () { + return Promise.resolve(this.wallets.map(w => w.getAddress().toString('hex'))) + } + + // tx is an instance of the ethereumjs-transaction class. + signTransaction (address, tx) { + const wallet = this._getWalletForAccount(address) + var privKey = wallet.getPrivateKey() + tx.sign(privKey) + return Promise.resolve(tx) + } + + // For eth_sign, we need to sign transactions: + signMessage (withAccount, data) { + const wallet = this._getWalletForAccount(withAccount) + const message = ethUtil.removeHexPrefix(data) + var privKey = wallet.getPrivateKey() + var msgSig = ethUtil.ecsign(new Buffer(message, 'hex'), privKey) + var rawMsgSig = ethUtil.bufferToHex(sigUtil.concatSig(msgSig.v, msgSig.r, msgSig.s)) + return Promise.resolve(rawMsgSig) + } + + exportAccount (address) { + const wallet = this._getWalletForAccount(address) + return Promise.resolve(wallet.getPrivateKey().toString('hex')) + } + + + /* PRIVATE METHODS */ + + _getWalletForAccount (account) { + return this.wallets.find(w => w.getAddress().toString('hex') === account) + } + +} + +SimpleKeyring.type = type +module.exports = SimpleKeyring diff --git a/app/scripts/lib/auto-faucet.js b/app/scripts/lib/auto-faucet.js index 59cf0ec20..1e86f735e 100644 --- a/app/scripts/lib/auto-faucet.js +++ b/app/scripts/lib/auto-faucet.js @@ -1,6 +1,9 @@ -var uri = 'https://faucet.metamask.io/' +const uri = 'https://faucet.metamask.io/' +const METAMASK_DEBUG = 'GULP_METAMASK_DEBUG' +const env = process.env.METAMASK_ENV module.exports = function (address) { + if (METAMASK_DEBUG || env === 'test') return // Don't faucet in development or test var http = new XMLHttpRequest() var data = address http.open('POST', uri, true) diff --git a/app/scripts/lib/auto-reload.js b/app/scripts/lib/auto-reload.js index 3c90905db..1302df35f 100644 --- a/app/scripts/lib/auto-reload.js +++ b/app/scripts/lib/auto-reload.js @@ -18,17 +18,16 @@ function setupDappAutoReload (web3) { return handleResetRequest - function handleResetRequest() { + function handleResetRequest () { resetWasRequested = true // ignore if web3 was not used if (!pageIsUsingWeb3) return // reload after short timeout setTimeout(triggerReset, 500) } - } // reload the page function triggerReset () { global.location.reload() -}
\ No newline at end of file +} diff --git a/app/scripts/lib/config-manager.js b/app/scripts/lib/config-manager.js index b8ffb6991..59cc2b63c 100644 --- a/app/scripts/lib/config-manager.js +++ b/app/scripts/lib/config-manager.js @@ -2,6 +2,8 @@ const Migrator = require('pojo-migrator') const MetamaskConfig = require('../config.js') const migrations = require('./migrations') const rp = require('request-promise') +const ethUtil = require('ethereumjs-util') +const normalize = require('./sig-util').normalize const TESTNET_RPC = MetamaskConfig.network.testnet const MAINNET_RPC = MetamaskConfig.network.mainnet @@ -111,6 +113,27 @@ ConfigManager.prototype.setWallet = function (wallet) { this.setData(data) } +ConfigManager.prototype.setVault = function (encryptedString) { + var data = this.getData() + data.vault = encryptedString + this.setData(data) +} + +ConfigManager.prototype.getVault = function () { + var data = this.getData() + return ('vault' in data) && data.vault +} + +ConfigManager.prototype.getKeychains = function () { + return this.migrator.getData().keychains || [] +} + +ConfigManager.prototype.setKeychains = function (keychains) { + var data = this.migrator.getData() + data.keychains = keychains + this.setData(data) +} + ConfigManager.prototype.getSelectedAccount = function () { var config = this.getConfig() return config.selectedAccount @@ -118,7 +141,7 @@ ConfigManager.prototype.getSelectedAccount = function () { ConfigManager.prototype.setSelectedAccount = function (address) { var config = this.getConfig() - config.selectedAccount = address + config.selectedAccount = ethUtil.addHexPrefix(address) this.setConfig(config) } @@ -133,11 +156,23 @@ ConfigManager.prototype.setShowSeedWords = function (should) { this.setData(data) } + ConfigManager.prototype.getShouldShowSeedWords = function () { var data = this.migrator.getData() return data.showSeedWords } +ConfigManager.prototype.setSeedWords = function (words) { + var data = this.getData() + data.seedWords = words + this.setData(data) +} + +ConfigManager.prototype.getSeedWords = function () { + var data = this.getData() + return ('seedWords' in data) && data.seedWords +} + ConfigManager.prototype.getCurrentRpcAddress = function () { var provider = this.getProvider() if (!provider) return null @@ -239,13 +274,15 @@ ConfigManager.prototype.getWalletNicknames = function () { } ConfigManager.prototype.nicknameForWallet = function (account) { + const address = normalize(account) const nicknames = this.getWalletNicknames() - return nicknames[account] + return nicknames[address] } ConfigManager.prototype.setNicknameForWallet = function (account, nickname) { + const address = normalize(account) const nicknames = this.getWalletNicknames() - nicknames[account] = nickname + nicknames[address] = nickname var data = this.getData() data.walletNicknames = nicknames this.setData(data) @@ -253,6 +290,17 @@ ConfigManager.prototype.setNicknameForWallet = function (account, nickname) { // observable +ConfigManager.prototype.getSalt = function () { + var data = this.getData() + return ('salt' in data) && data.salt +} + +ConfigManager.prototype.setSalt = function (salt) { + var data = this.getData() + data.salt = salt + this.setData(data) +} + ConfigManager.prototype.subscribe = function (fn) { this._subs.push(fn) var unsubscribe = this.unsubscribe.bind(this, fn) @@ -270,15 +318,15 @@ ConfigManager.prototype._emitUpdates = function (state) { }) } -ConfigManager.prototype.setConfirmed = function (confirmed) { +ConfigManager.prototype.setConfirmedDisclaimer = function (confirmed) { var data = this.getData() - data.isConfirmed = confirmed + data.isDisclaimerConfirmed = confirmed this.setData(data) } -ConfigManager.prototype.getConfirmed = function () { +ConfigManager.prototype.getConfirmedDisclaimer = function () { var data = this.getData() - return ('isConfirmed' in data) && data.isConfirmed + return ('isDisclaimerConfirmed' in data) && data.isDisclaimerConfirmed } ConfigManager.prototype.setTOSHash = function (hash) { @@ -315,7 +363,6 @@ ConfigManager.prototype.updateConversionRate = function () { this.setConversionPrice(0) this.setConversionDate('N/A') }) - } ConfigManager.prototype.setConversionPrice = function (price) { @@ -340,21 +387,6 @@ ConfigManager.prototype.getConversionDate = function () { return (('conversionDate' in data) && data.conversionDate) || 'N/A' } -ConfigManager.prototype.setShouldntShowWarning = function () { - var data = this.getData() - if (data.isEthConfirmed) { - data.isEthConfirmed = !data.isEthConfirmed - } else { - data.isEthConfirmed = true - } - this.setData(data) -} - -ConfigManager.prototype.getShouldntShowWarning = function () { - var data = this.getData() - return ('isEthConfirmed' in data) && data.isEthConfirmed -} - ConfigManager.prototype.getShapeShiftTxList = function () { var data = this.getData() var shapeShiftTxList = data.shapeShiftTxList ? data.shapeShiftTxList : [] diff --git a/app/scripts/lib/encryptor.js b/app/scripts/lib/encryptor.js new file mode 100644 index 000000000..4770d2f54 --- /dev/null +++ b/app/scripts/lib/encryptor.js @@ -0,0 +1,156 @@ +module.exports = { + + // Simple encryption methods: + encrypt, + decrypt, + + // More advanced encryption methods: + keyFromPassword, + encryptWithKey, + decryptWithKey, + + // Buffer <-> String methods + convertArrayBufferViewtoString, + convertStringToArrayBufferView, + + // Buffer <-> Hex string methods + serializeBufferForStorage, + serializeBufferFromStorage, + + // Buffer <-> base64 string methods + encodeBufferToBase64, + decodeBase64ToBuffer, + + generateSalt, +} + +// Takes a Pojo, returns cypher text. +function encrypt (password, dataObj) { + const salt = this.generateSalt() + + return keyFromPassword(password + salt) + .then(function (passwordDerivedKey) { + return encryptWithKey(passwordDerivedKey, dataObj) + }) + .then(function (payload) { + payload.salt = salt + return JSON.stringify(payload) + }) +} + +function encryptWithKey (key, dataObj) { + var data = JSON.stringify(dataObj) + var dataBuffer = convertStringToArrayBufferView(data) + var vector = global.crypto.getRandomValues(new Uint8Array(16)) + return global.crypto.subtle.encrypt({ + name: 'AES-GCM', + iv: vector, + }, key, dataBuffer).then(function (buf) { + var buffer = new Uint8Array(buf) + var vectorStr = encodeBufferToBase64(vector) + var vaultStr = encodeBufferToBase64(buffer) + return { + data: vaultStr, + iv: vectorStr, + } + }) +} + +// Takes encrypted text, returns the restored Pojo. +function decrypt (password, text) { + const payload = JSON.parse(text) + const salt = payload.salt + return keyFromPassword(password + salt) + .then(function (key) { + return decryptWithKey(key, payload) + }) +} + +function decryptWithKey (key, payload) { + const encryptedData = decodeBase64ToBuffer(payload.data) + const vector = decodeBase64ToBuffer(payload.iv) + return crypto.subtle.decrypt({name: 'AES-GCM', iv: vector}, key, encryptedData) + .then(function (result) { + const decryptedData = new Uint8Array(result) + const decryptedStr = convertArrayBufferViewtoString(decryptedData) + const decryptedObj = JSON.parse(decryptedStr) + return decryptedObj + }) + .catch(function (reason) { + throw new Error('Incorrect password') + }) +} + +function convertStringToArrayBufferView (str) { + var bytes = new Uint8Array(str.length) + for (var i = 0; i < str.length; i++) { + bytes[i] = str.charCodeAt(i) + } + + return bytes +} + +function convertArrayBufferViewtoString (buffer) { + var str = '' + for (var i = 0; i < buffer.byteLength; i++) { + str += String.fromCharCode(buffer[i]) + } + + return str +} + +function keyFromPassword (password) { + var passBuffer = convertStringToArrayBufferView(password) + return global.crypto.subtle.digest('SHA-256', passBuffer) + .then(function (passHash) { + return global.crypto.subtle.importKey('raw', passHash, {name: 'AES-GCM'}, false, ['encrypt', 'decrypt']) + }) +} + +function serializeBufferFromStorage (str) { + var stripStr = (str.slice(0, 2) === '0x') ? str.slice(2) : str + var buf = new Uint8Array(stripStr.length / 2) + for (var i = 0; i < stripStr.length; i += 2) { + var seg = stripStr.substr(i, 2) + buf[i / 2] = parseInt(seg, 16) + } + return buf +} + +// Should return a string, ready for storage, in hex format. +function serializeBufferForStorage (buffer) { + var result = '0x' + var len = buffer.length || buffer.byteLength + for (var i = 0; i < len; i++) { + result += unprefixedHex(buffer[i]) + } + return result +} + +function unprefixedHex (num) { + var hex = num.toString(16) + while (hex.length < 2) { + hex = '0' + hex + } + return hex +} + +function encodeBufferToBase64 (buf) { + var b64encoded = btoa(String.fromCharCode.apply(null, buf)) + return b64encoded +} + +function decodeBase64ToBuffer (base64) { + var buf = new Uint8Array(atob(base64).split('') + .map(function (c) { + return c.charCodeAt(0) + })) + return buf +} + +function generateSalt (byteCount = 32) { + var view = new Uint8Array(byteCount) + global.crypto.getRandomValues(view) + var b64encoded = btoa(String.fromCharCode.apply(null, view)) + return b64encoded +} diff --git a/app/scripts/lib/idStore-migrator.js b/app/scripts/lib/idStore-migrator.js new file mode 100644 index 000000000..40b08efee --- /dev/null +++ b/app/scripts/lib/idStore-migrator.js @@ -0,0 +1,52 @@ +const IdentityStore = require('./idStore') + + +module.exports = class IdentityStoreMigrator { + + constructor ({ configManager }) { + this.configManager = configManager + const hasOldVault = this.hasOldVault() + if (!hasOldVault) { + this.idStore = new IdentityStore({ configManager }) + } + } + + migratedVaultForPassword (password) { + const hasOldVault = this.hasOldVault() + const configManager = this.configManager + + if (!this.idStore) { + this.idStore = new IdentityStore({ configManager }) + } + + if (!hasOldVault) { + return Promise.resolve(null) + } + + return new Promise((resolve, reject) => { + this.idStore.submitPassword(password, (err) => { + if (err) return reject(err) + try { + resolve(this.serializeVault()) + } catch (e) { + reject(e) + } + }) + }) + } + + serializeVault () { + const mnemonic = this.idStore._idmgmt.getSeed() + const numberOfAccounts = this.idStore._getAddresses().length + + return { + type: 'HD Key Tree', + data: { mnemonic, numberOfAccounts }, + } + } + + hasOldVault () { + const wallet = this.configManager.getWallet() + return wallet + } +} diff --git a/app/scripts/lib/idStore.js b/app/scripts/lib/idStore.js index 1077d263d..d36504f13 100644 --- a/app/scripts/lib/idStore.js +++ b/app/scripts/lib/idStore.js @@ -44,7 +44,7 @@ function IdentityStore (opts = {}) { // public // -IdentityStore.prototype.createNewVault = function (password, entropy, cb) { +IdentityStore.prototype.createNewVault = function (password, cb) { delete this._keyStore var serializedKeystore = this.configManager.getWallet() @@ -53,7 +53,7 @@ IdentityStore.prototype.createNewVault = function (password, entropy, cb) { } this.purgeCache() - this._createVault(password, null, entropy, (err) => { + this._createVault(password, null, (err) => { if (err) return cb(err) this._autoFaucet() @@ -77,7 +77,7 @@ IdentityStore.prototype.recoverSeed = function (cb) { IdentityStore.prototype.recoverFromSeed = function (password, seed, cb) { this.purgeCache() - this._createVault(password, seed, null, (err) => { + this._createVault(password, seed, (err) => { if (err) return cb(err) this._loadIdentities() @@ -102,8 +102,7 @@ IdentityStore.prototype.getState = function () { isInitialized: !!configManager.getWallet() && !seedWords, isUnlocked: this._isUnlocked(), seedWords: seedWords, - isConfirmed: configManager.getConfirmed(), - isEthConfirmed: configManager.getShouldntShowWarning(), + isDisclaimerConfirmed: configManager.getConfirmedDisclaimer(), unconfTxs: configManager.unconfirmedTxs(), transactions: configManager.getTxList(), unconfMsgs: messageManager.unconfirmedMsgs(), @@ -114,7 +113,6 @@ IdentityStore.prototype.getState = function () { conversionRate: configManager.getConversionRate(), conversionDate: configManager.getConversionDate(), gasMultiplier: configManager.getGasMultiplier(), - })) } @@ -245,7 +243,7 @@ IdentityStore.prototype.addUnconfirmedTransaction = function (txParams, onTxDone ], didComplete) // perform static analyis on the target contract code - function analyzeForDelegateCall(cb){ + function analyzeForDelegateCall (cb) { if (txParams.to) { query.getCode(txParams.to, (err, result) => { if (err) return cb(err.message || err) @@ -258,7 +256,7 @@ IdentityStore.prototype.addUnconfirmedTransaction = function (txParams, onTxDone } } - function estimateGas(cb){ + function estimateGas (cb) { var estimationParams = extend(txParams) query.getBlockByNumber('latest', true, function(err, block){ if (err) return cb(err) @@ -466,7 +464,9 @@ IdentityStore.prototype._loadIdentities = function () { var addresses = this._getAddresses() addresses.forEach((address, i) => { // // add to ethStore - this._ethStore.addAccount(ethUtil.addHexPrefix(address)) + if (this._ethStore) { + this._ethStore.addAccount(ethUtil.addHexPrefix(address)) + } // add to identities const defaultLabel = 'Account ' + (i + 1) const nickname = configManager.nicknameForWallet(address) @@ -523,7 +523,7 @@ IdentityStore.prototype.tryPassword = function (password, cb) { }) } -IdentityStore.prototype._createVault = function (password, seedPhrase, entropy, cb) { +IdentityStore.prototype._createVault = function (password, seedPhrase, cb) { const opts = { password, hdPathString: this.hdPathString, diff --git a/app/scripts/lib/inpage-provider.js b/app/scripts/lib/inpage-provider.js index 71ac69ad1..30fcbcb66 100644 --- a/app/scripts/lib/inpage-provider.js +++ b/app/scripts/lib/inpage-provider.js @@ -40,7 +40,7 @@ function MetamaskInpageProvider (connectionStream) { self.idMap = {} // handle sendAsync requests via asyncProvider - self.sendAsync = function(payload, cb){ + self.sendAsync = function (payload, cb) { // rewrite request ids var request = eachJsonMessage(payload, (message) => { var newId = createRandomId() @@ -49,7 +49,7 @@ function MetamaskInpageProvider (connectionStream) { return message }) // forward to asyncProvider - asyncProvider.sendAsync(request, function(err, res){ + asyncProvider.sendAsync(request, function (err, res) { if (err) return cb(err) // transform messages to original ids eachJsonMessage(res, (message) => { @@ -66,20 +66,20 @@ function MetamaskInpageProvider (connectionStream) { MetamaskInpageProvider.prototype.send = function (payload) { const self = this - let selectedAddress + let selectedAccount let result = null switch (payload.method) { case 'eth_accounts': // read from localStorage - selectedAddress = self.publicConfigStore.get('selectedAddress') - result = selectedAddress ? [selectedAddress] : [] + selectedAccount = self.publicConfigStore.get('selectedAddress') + result = selectedAccount ? [selectedAccount] : [] break case 'eth_coinbase': // read from localStorage - selectedAddress = self.publicConfigStore.get('selectedAddress') - result = selectedAddress || '0x0000000000000000000000000000000000000000' + selectedAccount = self.publicConfigStore.get('selectedAddress') + result = selectedAccount || '0x0000000000000000000000000000000000000000' break case 'eth_uninstallFilter': @@ -125,7 +125,7 @@ function remoteStoreWithLocalStorageCache (storageKey) { return store } -function eachJsonMessage(payload, transformFn){ +function eachJsonMessage (payload, transformFn) { if (Array.isArray(payload)) { return payload.map(transformFn) } else { diff --git a/app/scripts/lib/is-popup-or-notification.js b/app/scripts/lib/is-popup-or-notification.js index 5c38ac823..693fa8751 100644 --- a/app/scripts/lib/is-popup-or-notification.js +++ b/app/scripts/lib/is-popup-or-notification.js @@ -1,4 +1,4 @@ -module.exports = function isPopupOrNotification() { +module.exports = function isPopupOrNotification () { const url = window.location.href if (url.match(/popup.html$/)) { return 'popup' diff --git a/app/scripts/lib/nodeify.js b/app/scripts/lib/nodeify.js new file mode 100644 index 000000000..51d89a8fb --- /dev/null +++ b/app/scripts/lib/nodeify.js @@ -0,0 +1,24 @@ +module.exports = function (promiseFn) { + return function () { + var args = [] + for (var i = 0; i < arguments.length - 1; i++) { + args.push(arguments[i]) + } + var cb = arguments[arguments.length - 1] + + const nodeified = promiseFn.apply(this, args) + + if (!nodeified) { + const methodName = String(promiseFn).split('(')[0] + throw new Error(`The ${methodName} did not return a Promise, but was nodeified.`) + } + nodeified.then(function (result) { + cb(null, result) + }) + .catch(function (reason) { + cb(reason) + }) + + return nodeified + } +} diff --git a/app/scripts/lib/notifications.js b/app/scripts/lib/notifications.js index cd7535232..3db1ac6b5 100644 --- a/app/scripts/lib/notifications.js +++ b/app/scripts/lib/notifications.js @@ -15,12 +15,9 @@ function show () { if (err) throw err if (popup) { - // bring focus to existing popup extension.windows.update(popup.id, { focused: true }) - } else { - // create new popup extension.windows.create({ url: 'notification.html', @@ -29,12 +26,11 @@ function show () { width, height, }) - } }) } -function getWindows(cb) { +function getWindows (cb) { // Ignore in test environment if (!extension.windows) { return cb() @@ -45,14 +41,14 @@ function getWindows(cb) { }) } -function getPopup(cb) { +function getPopup (cb) { getWindows((err, windows) => { if (err) throw err cb(null, getPopupIn(windows)) }) } -function getPopupIn(windows) { +function getPopupIn (windows) { return windows ? windows.find((win) => { return (win && win.type === 'popup' && win.height === height && @@ -60,7 +56,7 @@ function getPopupIn(windows) { }) : null } -function closePopup() { +function closePopup () { getPopup((err, popup) => { if (err) throw err if (!popup) return diff --git a/app/scripts/lib/random-id.js b/app/scripts/lib/random-id.js index 3c5ae5600..788f3370f 100644 --- a/app/scripts/lib/random-id.js +++ b/app/scripts/lib/random-id.js @@ -1,7 +1,7 @@ -const MAX = 1000000000 +const MAX = Number.MAX_SAFE_INTEGER -let idCounter = Math.round( Math.random() * MAX ) -function createRandomId() { +let idCounter = Math.round(Math.random() * MAX) +function createRandomId () { idCounter = idCounter % MAX return idCounter++ } diff --git a/app/scripts/lib/sig-util.js b/app/scripts/lib/sig-util.js new file mode 100644 index 000000000..193dda381 --- /dev/null +++ b/app/scripts/lib/sig-util.js @@ -0,0 +1,28 @@ +const ethUtil = require('ethereumjs-util') + +module.exports = { + + concatSig: function (v, r, s) { + const rSig = ethUtil.fromSigned(r) + const sSig = ethUtil.fromSigned(s) + const vSig = ethUtil.bufferToInt(v) + const rStr = padWithZeroes(ethUtil.toUnsigned(rSig).toString('hex'), 64) + const sStr = padWithZeroes(ethUtil.toUnsigned(sSig).toString('hex'), 64) + const vStr = ethUtil.stripHexPrefix(ethUtil.intToHex(vSig)) + return ethUtil.addHexPrefix(rStr.concat(sStr, vStr)).toString('hex') + }, + + normalize: function (address) { + if (!address) return + return ethUtil.addHexPrefix(address.toLowerCase()) + }, + +} + +function padWithZeroes (number, length) { + var myString = '' + number + while (myString.length < length) { + myString = '0' + myString + } + return myString +} diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 1477ce9e7..4b8fa4323 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -1,22 +1,27 @@ const extend = require('xtend') const EthStore = require('eth-store') const MetaMaskProvider = require('web3-provider-engine/zero.js') -const IdentityStore = require('./lib/idStore') +const KeyringController = require('./keyring-controller') const NoticeController = require('./notice-controller') const messageManager = require('./lib/message-manager') const HostStore = require('./lib/remote-store.js').HostStore const Web3 = require('web3') const ConfigManager = require('./lib/config-manager') const extension = require('./lib/extension') +const autoFaucet = require('./lib/auto-faucet') +const nodeify = require('./lib/nodeify') + module.exports = class MetamaskController { constructor (opts) { + this.state = { network: 'loading' } this.opts = opts this.listeners = [] this.configManager = new ConfigManager(opts) - this.idStore = new IdentityStore({ + this.keyringController = new KeyringController({ configManager: this.configManager, + getNetwork: this.getStateNetwork.bind(this), }) // notices this.noticeController = new NoticeController({ @@ -27,7 +32,8 @@ module.exports = class MetamaskController { // this.noticeController.startPolling() this.provider = this.initializeProvider(opts) this.ethStore = new EthStore(this.provider) - this.idStore.setStore(this.ethStore) + this.keyringController.setStore(this.ethStore) + this.getNetwork() this.messageManager = messageManager this.publicConfigStore = this.initPublicConfigStore() @@ -42,15 +48,16 @@ module.exports = class MetamaskController { getState () { return extend( + this.state, this.ethStore.getState(), - this.idStore.getState(), this.configManager.getConfig(), + this.keyringController.getState(), this.noticeController.getState() ) } getApi () { - const idStore = this.idStore + const keyringController = this.keyringController const noticeController = this.noticeController return { @@ -61,27 +68,29 @@ module.exports = class MetamaskController { agreeToDisclaimer: this.agreeToDisclaimer.bind(this), resetDisclaimer: this.resetDisclaimer.bind(this), setCurrentFiat: this.setCurrentFiat.bind(this), - agreeToEthWarning: this.agreeToEthWarning.bind(this), setTOSHash: this.setTOSHash.bind(this), checkTOSChange: this.checkTOSChange.bind(this), setGasMultiplier: this.setGasMultiplier.bind(this), - // forward directly to idStore - createNewVault: idStore.createNewVault.bind(idStore), - recoverFromSeed: idStore.recoverFromSeed.bind(idStore), - submitPassword: idStore.submitPassword.bind(idStore), - setSelectedAddress: idStore.setSelectedAddress.bind(idStore), - approveTransaction: idStore.approveTransaction.bind(idStore), - cancelTransaction: idStore.cancelTransaction.bind(idStore), - signMessage: idStore.signMessage.bind(idStore), - cancelMessage: idStore.cancelMessage.bind(idStore), - setLocked: idStore.setLocked.bind(idStore), - clearSeedWordCache: idStore.clearSeedWordCache.bind(idStore), - exportAccount: idStore.exportAccount.bind(idStore), - revealAccount: idStore.revealAccount.bind(idStore), - saveAccountLabel: idStore.saveAccountLabel.bind(idStore), - tryPassword: idStore.tryPassword.bind(idStore), - recoverSeed: idStore.recoverSeed.bind(idStore), + // forward directly to keyringController + createNewVaultAndKeychain: nodeify(keyringController.createNewVaultAndKeychain).bind(keyringController), + createNewVaultAndRestore: nodeify(keyringController.createNewVaultAndRestore).bind(keyringController), + placeSeedWords: nodeify(keyringController.placeSeedWords).bind(keyringController), + clearSeedWordCache: nodeify(keyringController.clearSeedWordCache).bind(keyringController), + setLocked: nodeify(keyringController.setLocked).bind(keyringController), + submitPassword: nodeify(keyringController.submitPassword).bind(keyringController), + addNewKeyring: nodeify(keyringController.addNewKeyring).bind(keyringController), + addNewAccount: nodeify(keyringController.addNewAccount).bind(keyringController), + setSelectedAccount: nodeify(keyringController.setSelectedAccount).bind(keyringController), + saveAccountLabel: nodeify(keyringController.saveAccountLabel).bind(keyringController), + exportAccount: nodeify(keyringController.exportAccount).bind(keyringController), + + // signing methods + approveTransaction: keyringController.approveTransaction.bind(keyringController), + cancelTransaction: keyringController.cancelTransaction.bind(keyringController), + signMessage: keyringController.signMessage.bind(keyringController), + cancelMessage: keyringController.cancelMessage.bind(keyringController), + // coinbase buyEth: this.buyEth.bind(this), // shapeshift @@ -97,23 +106,6 @@ module.exports = class MetamaskController { } onRpcRequest (stream, originDomain, request) { - - /* Commented out for Parity compliance - * Parity does not permit additional keys, like `origin`, - * and Infura is not currently filtering this key out. - var payloads = Array.isArray(request) ? request : [request] - payloads.forEach(function (payload) { - // Append origin to rpc payload - payload.origin = originDomain - // Append origin to signature request - if (payload.method === 'eth_sendTransaction') { - payload.params[0].origin = originDomain - } else if (payload.method === 'eth_sign') { - payload.params.push({ origin: originDomain }) - } - }) - */ - // handle rpc request this.provider.sendAsync(request, function onPayloadHandled (err, response) { logger(err, request, response) @@ -146,38 +138,38 @@ module.exports = class MetamaskController { } initializeProvider (opts) { - const idStore = this.idStore + const keyringController = this.keyringController var providerOpts = { rpcUrl: this.configManager.getCurrentRpcAddress(), // account mgmt getAccounts: (cb) => { - var selectedAddress = idStore.getSelectedAddress() - var result = selectedAddress ? [selectedAddress] : [] + var selectedAccount = this.configManager.getSelectedAccount() + var result = selectedAccount ? [selectedAccount] : [] cb(null, result) }, // tx signing approveTransaction: this.newUnsignedTransaction.bind(this), signTransaction: (...args) => { - idStore.signTransaction(...args) + keyringController.signTransaction(...args) this.sendUpdate() }, // msg signing approveMessage: this.newUnsignedMessage.bind(this), signMessage: (...args) => { - idStore.signMessage(...args) + keyringController.signMessage(...args) this.sendUpdate() }, } var provider = MetaMaskProvider(providerOpts) var web3 = new Web3(provider) - idStore.web3 = web3 - idStore.getNetwork() + this.web3 = web3 + keyringController.web3 = web3 provider.on('block', this.processBlock.bind(this)) - provider.on('error', idStore.getNetwork.bind(idStore)) + provider.on('error', this.getNetwork.bind(this)) return provider } @@ -185,7 +177,7 @@ module.exports = class MetamaskController { initPublicConfigStore () { // get init state var initPublicState = extend( - idStoreToPublic(this.idStore.getState()), + keyringControllerToPublic(this.keyringController.getState()), configToPublic(this.configManager.getConfig()) ) @@ -195,21 +187,27 @@ module.exports = class MetamaskController { this.configManager.subscribe(function (state) { storeSetFromObj(publicConfigStore, configToPublic(state)) }) - this.idStore.on('update', function (state) { - storeSetFromObj(publicConfigStore, idStoreToPublic(state)) + this.keyringController.on('update', () => { + const state = this.keyringController.getState() + storeSetFromObj(publicConfigStore, keyringControllerToPublic(state)) + this.sendUpdate() }) - // idStore substate - function idStoreToPublic (state) { + this.keyringController.on('newAccount', (account) => { + autoFaucet(account) + }) + + // keyringController substate + function keyringControllerToPublic (state) { return { - selectedAddress: state.selectedAddress, + selectedAccount: state.selectedAccount, } } // config substate function configToPublic (state) { return { provider: state.provider, - selectedAddress: state.selectedAccount, + selectedAccount: state.selectedAccount, } } // dump obj into store @@ -223,10 +221,10 @@ module.exports = class MetamaskController { } newUnsignedTransaction (txParams, onTxDoneCb) { - const idStore = this.idStore - let err = this.enforceTxValidations(txParams) + const keyringController = this.keyringController + const err = this.enforceTxValidations(txParams) if (err) return onTxDoneCb(err) - idStore.addUnconfirmedTransaction(txParams, onTxDoneCb, (err, txData) => { + keyringController.addUnconfirmedTransaction(txParams, onTxDoneCb, (err, txData) => { if (err) return onTxDoneCb(err) this.sendUpdate() this.opts.showUnconfirmedTx(txParams, txData, onTxDoneCb) @@ -241,9 +239,9 @@ module.exports = class MetamaskController { } newUnsignedMessage (msgParams, cb) { - var state = this.idStore.getState() + var state = this.keyringController.getState() if (!state.isUnlocked) { - this.idStore.addUnconfirmedMessage(msgParams, cb) + this.keyringController.addUnconfirmedMessage(msgParams, cb) this.opts.unlockAccountMessage() } else { this.addUnconfirmedMessage(msgParams, cb) @@ -252,8 +250,8 @@ module.exports = class MetamaskController { } addUnconfirmedMessage (msgParams, cb) { - const idStore = this.idStore - const msgId = idStore.addUnconfirmedMessage(msgParams, cb) + const keyringController = this.keyringController + const msgId = keyringController.addUnconfirmedMessage(msgParams, cb) this.opts.showUnconfirmedMessage(msgParams, msgId) } @@ -272,8 +270,8 @@ module.exports = class MetamaskController { verifyNetwork () { // Check network when restoring connectivity: - if (this.idStore._currentState.network === 'loading') { - this.idStore.getNetwork() + if (this.state.network === 'loading') { + this.getNetwork() } } @@ -298,14 +296,13 @@ module.exports = class MetamaskController { } catch (err) { console.error('Error in checking TOS change.') } - } // disclaimer agreeToDisclaimer (cb) { try { - this.configManager.setConfirmed(true) + this.configManager.setConfirmedDisclaimer(true) cb() } catch (err) { cb(err) @@ -314,9 +311,9 @@ module.exports = class MetamaskController { resetDisclaimer () { try { - this.configManager.setConfirmed(false) - } catch (err) { - console.error(err) + this.configManager.setConfirmedDisclaimer(false) + } catch (e) { + console.error(e) } } @@ -345,26 +342,17 @@ module.exports = class MetamaskController { }, 300000) } - agreeToEthWarning (cb) { - try { - this.configManager.setShouldntShowWarning() - cb() - } catch (err) { - cb(err) - } - } - // called from popup setRpcTarget (rpcTarget) { this.configManager.setRpcTarget(rpcTarget) extension.runtime.reload() - this.idStore.getNetwork() + this.getNetwork() } setProviderType (type) { this.configManager.setProviderType(type) extension.runtime.reload() - this.idStore.getNetwork() + this.getNetwork() } useEtherscanProvider () { @@ -375,7 +363,7 @@ module.exports = class MetamaskController { buyEth (address, amount) { if (!amount) amount = '5' - var network = this.idStore._currentState.network + var network = this.state.network var url = `https://buy.coinbase.com/?code=9ec56d01-7e81-5017-930c-513daa27bb6a&amount=${amount}&address=${address}&crypto_currency=ETH` if (network === '3') { @@ -391,6 +379,25 @@ module.exports = class MetamaskController { this.configManager.createShapeShiftTx(depositAddress, depositType) } + getNetwork (err) { + if (err) { + this.state.network = 'loading' + this.sendUpdate() + } + + this.web3.version.getNetwork((err, network) => { + if (err) { + this.state.network = 'loading' + return this.sendUpdate() + } + if (global.METAMASK_DEBUG) { + console.log('web3.getNetwork returned ' + network) + } + this.state.network = network + this.sendUpdate() + }) + } + setGasMultiplier (gasMultiplier, cb) { try { this.configManager.setGasMultiplier(gasMultiplier) @@ -399,4 +406,8 @@ module.exports = class MetamaskController { cb(err) } } + + getStateNetwork () { + return this.state.network + } } diff --git a/app/scripts/popup-core.js b/app/scripts/popup-core.js index 94413a1c4..0c97a5d19 100644 --- a/app/scripts/popup-core.js +++ b/app/scripts/popup-core.js @@ -9,7 +9,7 @@ const setupMultiplex = require('./lib/stream-utils.js').setupMultiplex module.exports = initializePopup -function initializePopup(connectionStream){ +function initializePopup (connectionStream) { // setup app connectToAccountManager(connectionStream, setupApp) } @@ -32,7 +32,7 @@ function setupWeb3Connection (connectionStream) { } function setupControllerConnection (connectionStream, cb) { - // this is a really sneaky way of adding EventEmitter api + // this is a really sneaky way of adding EventEmitter api // to a bi-directional dnode instance var eventEmitter = new EventEmitter() var accountManagerDnode = Dnode({ diff --git a/app/scripts/popup.js b/app/scripts/popup.js index e6f149f96..62db68c10 100644 --- a/app/scripts/popup.js +++ b/app/scripts/popup.js @@ -18,7 +18,7 @@ var portStream = new PortStream(pluginPort) startPopup(portStream) -function closePopupIfOpen(name) { +function closePopupIfOpen (name) { if (name !== 'notification') { notification.closePopup() } diff --git a/development/states.json b/development/states.json index b2776edcc..0e87fb7ae 100644 --- a/development/states.json +++ b/development/states.json @@ -1 +1 @@ -module.exports = [{"account detail":{"metamask":{"isInitialized":true,"isUnlocked":true,"currentDomain":"example.com","rpcTarget":"https://rawtestrpc.metamask.io/","identities":{"0x5f11b68b7d41633e74c6b18d8b8d147da52aedd6":{"name":"Secret Wallet!","address":"0x5f11b68b7d41633e74c6b18d8b8d147da52aedd6","mayBeFauceting":false},"0x843963b837841dad3b0f5969ff271108776616df":{"name":"Main Wallet","address":"0x843963b837841dad3b0f5969ff271108776616df","mayBeFauceting":false},"0x2cb215323857bec1c91e5db10fe87379a5cf129a":{"name":"Wallet 3","address":"0x2cb215323857bec1c91e5db10fe87379a5cf129a","mayBeFauceting":false}},"unconfTxs":{},"accounts":{"0x5f11b68b7d41633e74c6b18d8b8d147da52aedd6":{"code":"0x","balance":"0x0","nonce":"0x0","address":"0x5f11b68b7d41633e74c6b18d8b8d147da52aedd6"},"0x843963b837841dad3b0f5969ff271108776616df":{"code":"0x","balance":"0x0","nonce":"0x0","address":"0x843963b837841dad3b0f5969ff271108776616df"},"0x2cb215323857bec1c91e5db10fe87379a5cf129a":{"code":"0x","balance":"0x0","nonce":"0x0","address":"0x2cb215323857bec1c91e5db10fe87379a5cf129a"}},"transactions":[],"selectedAddress":"0x843963b837841dad3b0f5969ff271108776616df","network":"2","seedWords":null,"isConfirmed":true,"unconfMsgs":{},"messages":[],"provider":{"type":"testnet"},"selectedAccount":"0x843963b837841dad3b0f5969ff271108776616df"},"appState":{"menuOpen":false,"currentView":{"name":"accountDetail","detailView":null,"context":"0x843963b837841dad3b0f5969ff271108776616df"},"accountDetail":{"subview":"transactions"},"currentDomain":"127.0.0.1:9966","transForward":true,"isLoading":false,"warning":null},"identities":{}}},{"accounts":{"metamask":{"isInitialized":true,"isUnlocked":true,"currentDomain":"example.com","rpcTarget":"https://rawtestrpc.metamask.io/","identities":{"0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc":{"name":"Wallet 1","address":"0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc","mayBeFauceting":false},"0xec1adf982415d2ef5ec55899b9bfb8bc0f29251b":{"name":"Wallet 2","address":"0xec1adf982415d2ef5ec55899b9bfb8bc0f29251b","mayBeFauceting":false},"0xeb9e64b93097bc15f01f13eae97015c57ab64823":{"name":"Wallet 3","address":"0xeb9e64b93097bc15f01f13eae97015c57ab64823","mayBeFauceting":false},"0x704107d04affddd9b66ab9de3dd7b095852e9b69":{"name":"Wallet 4","address":"0x704107d04affddd9b66ab9de3dd7b095852e9b69","mayBeFauceting":false}},"unconfTxs":{},"accounts":{"0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc":{"balance":"0x0","nonce":"0x0","code":"0x","address":"0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc"},"0xec1adf982415d2ef5ec55899b9bfb8bc0f29251b":{"balance":"0x0","nonce":"0x0","code":"0x","address":"0xec1adf982415d2ef5ec55899b9bfb8bc0f29251b"},"0xeb9e64b93097bc15f01f13eae97015c57ab64823":{"balance":"0x0","nonce":"0x0","code":"0x","address":"0xeb9e64b93097bc15f01f13eae97015c57ab64823"},"0x704107d04affddd9b66ab9de3dd7b095852e9b69":{"balance":"0x0","code":"0x","nonce":"0x0","address":"0x704107d04affddd9b66ab9de3dd7b095852e9b69"}},"transactions":[],"network":"2","isConfirmed":true,"unconfMsgs":{},"messages":[],"provider":{"type":"testnet"},"selectedAccount":"0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc","selectedAddress":"0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc","seedWords":null},"appState":{"menuOpen":false,"currentView":{"name":"accounts"},"accountDetail":{"subview":"transactions","accountExport":"none","privateKey":""},"currentDomain":"extensions","transForward":true,"isLoading":false,"warning":null,"scrollToBottom":true},"identities":{}}},{"config":{"metamask":{"isInitialized":true,"isUnlocked":true,"currentDomain":"example.com","rpcTarget":"https://rawtestrpc.metamask.io/","identities":{"0x5f11b68b7d41633e74c6b18d8b8d147da52aedd6":{"name":"Wallet 1","address":"0x5f11b68b7d41633e74c6b18d8b8d147da52aedd6","mayBeFauceting":false},"0x843963b837841dad3b0f5969ff271108776616df":{"name":"Wallet 2","address":"0x843963b837841dad3b0f5969ff271108776616df","mayBeFauceting":false},"0x2cb215323857bec1c91e5db10fe87379a5cf129a":{"name":"Wallet 3","address":"0x2cb215323857bec1c91e5db10fe87379a5cf129a","mayBeFauceting":false},"0xc5091450b7548b0dce3a76b8d325929c39e648d1":{"name":"Wallet 4","address":"0xc5091450b7548b0dce3a76b8d325929c39e648d1","mayBeFauceting":false}},"unconfTxs":{},"accounts":{"0x5f11b68b7d41633e74c6b18d8b8d147da52aedd6":{"balance":"0x0","nonce":"0x0","code":"0x","address":"0x5f11b68b7d41633e74c6b18d8b8d147da52aedd6"},"0x843963b837841dad3b0f5969ff271108776616df":{"balance":"0x0","nonce":"0x0","code":"0x","address":"0x843963b837841dad3b0f5969ff271108776616df"},"0x2cb215323857bec1c91e5db10fe87379a5cf129a":{"balance":"0x0","nonce":"0x0","code":"0x","address":"0x2cb215323857bec1c91e5db10fe87379a5cf129a"},"0xc5091450b7548b0dce3a76b8d325929c39e648d1":{"balance":"0x0","nonce":"0x0","code":"0x","address":"0xc5091450b7548b0dce3a76b8d325929c39e648d1"}},"transactions":[],"selectedAddress":"0x843963b837841dad3b0f5969ff271108776616df","network":"2","isConfirmed":true,"unconfMsgs":{},"messages":[],"provider":{"type":"testnet"},"selectedAccount":"0x843963b837841dad3b0f5969ff271108776616df","seedWords":null},"appState":{"menuOpen":false,"currentView":{"name":"accounts"},"accountDetail":{"subview":"transactions","accountExport":"none","privateKey":""},"currentDomain":"testfaucet.metamask.io","transForward":true,"isLoading":false,"warning":null,"scrollToBottom":true},"identities":{}}},{"create vault password":{"metamask":{"isInitialized":false,"isUnlocked":false,"currentDomain":"example.com","rpcTarget":"https://rawtestrpc.metamask.io/","identities":{},"unconfTxs":{},"accounts":{},"transactions":[],"network":"2","seedWords":null,"isConfirmed":true,"unconfMsgs":{},"messages":[],"provider":{"type":"testnet"}},"appState":{"menuOpen":false,"currentView":{"name":"accounts","detailView":null},"accountDetail":{"subview":"transactions"},"currentDomain":"extensions","transForward":false,"isLoading":false,"warning":null},"identities":{}}},{"help":{"metamask":{"isInitialized":true,"isUnlocked":true,"currentDomain":"example.com","rpcTarget":"https://rawtestrpc.metamask.io/","identities":{"0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc":{"name":"Wallet 1","address":"0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc","mayBeFauceting":false},"0xec1adf982415d2ef5ec55899b9bfb8bc0f29251b":{"name":"Wallet 2","address":"0xec1adf982415d2ef5ec55899b9bfb8bc0f29251b","mayBeFauceting":false},"0xeb9e64b93097bc15f01f13eae97015c57ab64823":{"name":"Wallet 3","address":"0xeb9e64b93097bc15f01f13eae97015c57ab64823","mayBeFauceting":false},"0x704107d04affddd9b66ab9de3dd7b095852e9b69":{"name":"Wallet 4","address":"0x704107d04affddd9b66ab9de3dd7b095852e9b69","mayBeFauceting":false}},"unconfTxs":{},"accounts":{"0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc":{"code":"0x","balance":"0x0","nonce":"0x0","address":"0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc"},"0xec1adf982415d2ef5ec55899b9bfb8bc0f29251b":{"code":"0x","balance":"0x0","nonce":"0x0","address":"0xec1adf982415d2ef5ec55899b9bfb8bc0f29251b"},"0xeb9e64b93097bc15f01f13eae97015c57ab64823":{"code":"0x","balance":"0x0","nonce":"0x0","address":"0xeb9e64b93097bc15f01f13eae97015c57ab64823"},"0x704107d04affddd9b66ab9de3dd7b095852e9b69":{"code":"0x","nonce":"0x0","balance":"0x0","address":"0x704107d04affddd9b66ab9de3dd7b095852e9b69"}},"transactions":[],"network":"2","isConfirmed":true,"unconfMsgs":{},"messages":[],"provider":{"type":"testnet"},"selectedAccount":"0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc","selectedAddress":"0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc","seedWords":null},"appState":{"menuOpen":false,"currentView":{"name":"info"},"accountDetail":{"subview":"transactions","accountExport":"none","privateKey":""},"currentDomain":"extensions","transForward":true,"isLoading":false,"warning":null,"scrollToBottom":true},"identities":{}}},{"locked":{"metamask":{"isInitialized":true,"isUnlocked":true,"currentDomain":"example.com","rpcTarget":"https://rawtestrpc.metamask.io/","identities":{"0x5f11b68b7d41633e74c6b18d8b8d147da52aedd6":{"name":"Wallet 1","address":"0x5f11b68b7d41633e74c6b18d8b8d147da52aedd6","mayBeFauceting":false},"0x843963b837841dad3b0f5969ff271108776616df":{"name":"Wallet 2","address":"0x843963b837841dad3b0f5969ff271108776616df","mayBeFauceting":false},"0x2cb215323857bec1c91e5db10fe87379a5cf129a":{"name":"Wallet 3","address":"0x2cb215323857bec1c91e5db10fe87379a5cf129a","mayBeFauceting":false},"0xc5091450b7548b0dce3a76b8d325929c39e648d1":{"name":"Wallet 4","address":"0xc5091450b7548b0dce3a76b8d325929c39e648d1","mayBeFauceting":false}},"unconfTxs":{},"accounts":{"0x5f11b68b7d41633e74c6b18d8b8d147da52aedd6":{"balance":"0x0","nonce":"0x0","code":"0x","address":"0x5f11b68b7d41633e74c6b18d8b8d147da52aedd6"},"0x843963b837841dad3b0f5969ff271108776616df":{"balance":"0x0","nonce":"0x0","code":"0x","address":"0x843963b837841dad3b0f5969ff271108776616df"},"0x2cb215323857bec1c91e5db10fe87379a5cf129a":{"balance":"0x0","nonce":"0x0","code":"0x","address":"0x2cb215323857bec1c91e5db10fe87379a5cf129a"},"0xc5091450b7548b0dce3a76b8d325929c39e648d1":{"balance":"0x0","nonce":"0x0","code":"0x","address":"0xc5091450b7548b0dce3a76b8d325929c39e648d1"}},"transactions":[],"selectedAddress":"0x843963b837841dad3b0f5969ff271108776616df","network":"2","isConfirmed":true,"unconfMsgs":{},"messages":[],"provider":{"type":"testnet"},"selectedAccount":"0x843963b837841dad3b0f5969ff271108776616df"},"appState":{"menuOpen":false,"currentView":{"name":"accountDetail"},"accountDetail":{"subview":"transactions","accountExport":"none","privateKey":""},"currentDomain":"testfaucet.metamask.io","transForward":false,"isLoading":false,"warning":null,"scrollToBottom":false},"identities":{}}},{"new vault":{"metamask":{"isInitialized":false,"isUnlocked":false,"currentDomain":"example.com","rpcTarget":"https://rawtestrpc.metamask.io/","identities":{},"unconfTxs":{},"accounts":{},"transactions":[],"network":"2","seedWords":null,"isConfirmed":false,"unconfMsgs":{},"messages":[],"provider":{"type":"testnet"}},"appState":{"menuOpen":false,"currentView":{"name":"accounts","detailView":null},"accountDetail":{"subview":"transactions"},"currentDomain":"extensions","transForward":true,"isLoading":false,"warning":null},"identities":{}}},{"show seed words":{"metamask":{"isInitialized":false,"isUnlocked":true,"currentDomain":"example.com","rpcTarget":"https://rawtestrpc.metamask.io/","identities":{"0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc":{"name":"Wallet 1","address":"0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc","mayBeFauceting":false},"0xec1adf982415d2ef5ec55899b9bfb8bc0f29251b":{"name":"Wallet 2","address":"0xec1adf982415d2ef5ec55899b9bfb8bc0f29251b","mayBeFauceting":false},"0xeb9e64b93097bc15f01f13eae97015c57ab64823":{"name":"Wallet 3","address":"0xeb9e64b93097bc15f01f13eae97015c57ab64823","mayBeFauceting":false}},"unconfTxs":{},"accounts":{"0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc":{"balance":"0x0","nonce":"0x0","code":"0x","address":"0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc"},"0xec1adf982415d2ef5ec55899b9bfb8bc0f29251b":{"balance":"0x0","nonce":"0x0","code":"0x","address":"0xec1adf982415d2ef5ec55899b9bfb8bc0f29251b"},"0xeb9e64b93097bc15f01f13eae97015c57ab64823":{"balance":"0x0","nonce":"0x0","code":"0x","address":"0xeb9e64b93097bc15f01f13eae97015c57ab64823"}},"transactions":[],"network":"2","seedWords":"debris dizzy just program just float decrease vacant alarm reduce speak stadium","isConfirmed":false,"unconfMsgs":{},"messages":[],"provider":{"type":"testnet"}},"appState":{"menuOpen":false,"currentView":{"name":"createVaultComplete","seedWords":"debris dizzy just program just float decrease vacant alarm reduce speak stadium"},"accountDetail":{"subview":"transactions"},"currentDomain":"extensions","transForward":true,"isLoading":false,"warning":null},"identities":{}}},{"terms":{"metamask":{"accounts":{},"transactions":[],"identities":{},"network":"2","isInitialized":false,"isUnlocked":false,"seedWords":null,"isConfirmed":false,"unconfTxs":{},"unconfMsgs":{},"messages":[],"provider":{"type":"testnet"}},"appState":{"currentDomain":"extensions"}}}]
\ No newline at end of file +module.exports = [{"account detail":{"metamask":{"isInitialized":true,"isUnlocked":true,"currentDomain":"example.com","rpcTarget":"https://rawtestrpc.metamask.io/","identities":{"0x5f11b68b7d41633e74c6b18d8b8d147da52aedd6":{"name":"Secret Wallet!","address":"0x5f11b68b7d41633e74c6b18d8b8d147da52aedd6","mayBeFauceting":false},"0x843963b837841dad3b0f5969ff271108776616df":{"name":"Main Wallet","address":"0x843963b837841dad3b0f5969ff271108776616df","mayBeFauceting":false},"0x2cb215323857bec1c91e5db10fe87379a5cf129a":{"name":"Wallet 3","address":"0x2cb215323857bec1c91e5db10fe87379a5cf129a","mayBeFauceting":false}},"unconfTxs":{},"accounts":{"0x5f11b68b7d41633e74c6b18d8b8d147da52aedd6":{"code":"0x","balance":"0x0","nonce":"0x0","address":"0x5f11b68b7d41633e74c6b18d8b8d147da52aedd6"},"0x843963b837841dad3b0f5969ff271108776616df":{"code":"0x","balance":"0x0","nonce":"0x0","address":"0x843963b837841dad3b0f5969ff271108776616df"},"0x2cb215323857bec1c91e5db10fe87379a5cf129a":{"code":"0x","balance":"0x0","nonce":"0x0","address":"0x2cb215323857bec1c91e5db10fe87379a5cf129a"}},"transactions":[],"selectedAddress":"0x843963b837841dad3b0f5969ff271108776616df","network":"2","seedWords":null,"isDisclaimerConfirmed":true,"unconfMsgs":{},"messages":[],"provider":{"type":"testnet"},"selectedAccount":"0x843963b837841dad3b0f5969ff271108776616df"},"appState":{"menuOpen":false,"currentView":{"name":"accountDetail","detailView":null,"context":"0x843963b837841dad3b0f5969ff271108776616df"},"accountDetail":{"subview":"transactions"},"currentDomain":"127.0.0.1:9966","transForward":true,"isLoading":false,"warning":null},"identities":{}}},{"accounts":{"metamask":{"isInitialized":true,"isUnlocked":true,"currentDomain":"example.com","rpcTarget":"https://rawtestrpc.metamask.io/","identities":{"0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc":{"name":"Wallet 1","address":"0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc","mayBeFauceting":false},"0xec1adf982415d2ef5ec55899b9bfb8bc0f29251b":{"name":"Wallet 2","address":"0xec1adf982415d2ef5ec55899b9bfb8bc0f29251b","mayBeFauceting":false},"0xeb9e64b93097bc15f01f13eae97015c57ab64823":{"name":"Wallet 3","address":"0xeb9e64b93097bc15f01f13eae97015c57ab64823","mayBeFauceting":false},"0x704107d04affddd9b66ab9de3dd7b095852e9b69":{"name":"Wallet 4","address":"0x704107d04affddd9b66ab9de3dd7b095852e9b69","mayBeFauceting":false}},"unconfTxs":{},"accounts":{"0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc":{"balance":"0x0","nonce":"0x0","code":"0x","address":"0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc"},"0xec1adf982415d2ef5ec55899b9bfb8bc0f29251b":{"balance":"0x0","nonce":"0x0","code":"0x","address":"0xec1adf982415d2ef5ec55899b9bfb8bc0f29251b"},"0xeb9e64b93097bc15f01f13eae97015c57ab64823":{"balance":"0x0","nonce":"0x0","code":"0x","address":"0xeb9e64b93097bc15f01f13eae97015c57ab64823"},"0x704107d04affddd9b66ab9de3dd7b095852e9b69":{"balance":"0x0","code":"0x","nonce":"0x0","address":"0x704107d04affddd9b66ab9de3dd7b095852e9b69"}},"transactions":[],"network":"2","isDisclaimerConfirmed":true,"unconfMsgs":{},"messages":[],"provider":{"type":"testnet"},"selectedAccount":"0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc","selectedAddress":"0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc","seedWords":null},"appState":{"menuOpen":false,"currentView":{"name":"accounts"},"accountDetail":{"subview":"transactions","accountExport":"none","privateKey":""},"currentDomain":"extensions","transForward":true,"isLoading":false,"warning":null,"scrollToBottom":true},"identities":{}}},{"config":{"metamask":{"isInitialized":true,"isUnlocked":true,"currentDomain":"example.com","rpcTarget":"https://rawtestrpc.metamask.io/","identities":{"0x5f11b68b7d41633e74c6b18d8b8d147da52aedd6":{"name":"Wallet 1","address":"0x5f11b68b7d41633e74c6b18d8b8d147da52aedd6","mayBeFauceting":false},"0x843963b837841dad3b0f5969ff271108776616df":{"name":"Wallet 2","address":"0x843963b837841dad3b0f5969ff271108776616df","mayBeFauceting":false},"0x2cb215323857bec1c91e5db10fe87379a5cf129a":{"name":"Wallet 3","address":"0x2cb215323857bec1c91e5db10fe87379a5cf129a","mayBeFauceting":false},"0xc5091450b7548b0dce3a76b8d325929c39e648d1":{"name":"Wallet 4","address":"0xc5091450b7548b0dce3a76b8d325929c39e648d1","mayBeFauceting":false}},"unconfTxs":{},"accounts":{"0x5f11b68b7d41633e74c6b18d8b8d147da52aedd6":{"balance":"0x0","nonce":"0x0","code":"0x","address":"0x5f11b68b7d41633e74c6b18d8b8d147da52aedd6"},"0x843963b837841dad3b0f5969ff271108776616df":{"balance":"0x0","nonce":"0x0","code":"0x","address":"0x843963b837841dad3b0f5969ff271108776616df"},"0x2cb215323857bec1c91e5db10fe87379a5cf129a":{"balance":"0x0","nonce":"0x0","code":"0x","address":"0x2cb215323857bec1c91e5db10fe87379a5cf129a"},"0xc5091450b7548b0dce3a76b8d325929c39e648d1":{"balance":"0x0","nonce":"0x0","code":"0x","address":"0xc5091450b7548b0dce3a76b8d325929c39e648d1"}},"transactions":[],"selectedAddress":"0x843963b837841dad3b0f5969ff271108776616df","network":"2","isDisclaimerConfirmed":true,"unconfMsgs":{},"messages":[],"provider":{"type":"testnet"},"selectedAccount":"0x843963b837841dad3b0f5969ff271108776616df","seedWords":null},"appState":{"menuOpen":false,"currentView":{"name":"accounts"},"accountDetail":{"subview":"transactions","accountExport":"none","privateKey":""},"currentDomain":"testfaucet.metamask.io","transForward":true,"isLoading":false,"warning":null,"scrollToBottom":true},"identities":{}}},{"create vault password":{"metamask":{"isInitialized":false,"isUnlocked":false,"currentDomain":"example.com","rpcTarget":"https://rawtestrpc.metamask.io/","identities":{},"unconfTxs":{},"accounts":{},"transactions":[],"network":"2","seedWords":null,"isDisclaimerConfirmed":true,"unconfMsgs":{},"messages":[],"provider":{"type":"testnet"}},"appState":{"menuOpen":false,"currentView":{"name":"accounts","detailView":null},"accountDetail":{"subview":"transactions"},"currentDomain":"extensions","transForward":false,"isLoading":false,"warning":null},"identities":{}}},{"help":{"metamask":{"isInitialized":true,"isUnlocked":true,"currentDomain":"example.com","rpcTarget":"https://rawtestrpc.metamask.io/","identities":{"0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc":{"name":"Wallet 1","address":"0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc","mayBeFauceting":false},"0xec1adf982415d2ef5ec55899b9bfb8bc0f29251b":{"name":"Wallet 2","address":"0xec1adf982415d2ef5ec55899b9bfb8bc0f29251b","mayBeFauceting":false},"0xeb9e64b93097bc15f01f13eae97015c57ab64823":{"name":"Wallet 3","address":"0xeb9e64b93097bc15f01f13eae97015c57ab64823","mayBeFauceting":false},"0x704107d04affddd9b66ab9de3dd7b095852e9b69":{"name":"Wallet 4","address":"0x704107d04affddd9b66ab9de3dd7b095852e9b69","mayBeFauceting":false}},"unconfTxs":{},"accounts":{"0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc":{"code":"0x","balance":"0x0","nonce":"0x0","address":"0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc"},"0xec1adf982415d2ef5ec55899b9bfb8bc0f29251b":{"code":"0x","balance":"0x0","nonce":"0x0","address":"0xec1adf982415d2ef5ec55899b9bfb8bc0f29251b"},"0xeb9e64b93097bc15f01f13eae97015c57ab64823":{"code":"0x","balance":"0x0","nonce":"0x0","address":"0xeb9e64b93097bc15f01f13eae97015c57ab64823"},"0x704107d04affddd9b66ab9de3dd7b095852e9b69":{"code":"0x","nonce":"0x0","balance":"0x0","address":"0x704107d04affddd9b66ab9de3dd7b095852e9b69"}},"transactions":[],"network":"2","isDisclaimerConfirmed":true,"unconfMsgs":{},"messages":[],"provider":{"type":"testnet"},"selectedAccount":"0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc","selectedAddress":"0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc","seedWords":null},"appState":{"menuOpen":false,"currentView":{"name":"info"},"accountDetail":{"subview":"transactions","accountExport":"none","privateKey":""},"currentDomain":"extensions","transForward":true,"isLoading":false,"warning":null,"scrollToBottom":true},"identities":{}}},{"locked":{"metamask":{"isInitialized":true,"isUnlocked":true,"currentDomain":"example.com","rpcTarget":"https://rawtestrpc.metamask.io/","identities":{"0x5f11b68b7d41633e74c6b18d8b8d147da52aedd6":{"name":"Wallet 1","address":"0x5f11b68b7d41633e74c6b18d8b8d147da52aedd6","mayBeFauceting":false},"0x843963b837841dad3b0f5969ff271108776616df":{"name":"Wallet 2","address":"0x843963b837841dad3b0f5969ff271108776616df","mayBeFauceting":false},"0x2cb215323857bec1c91e5db10fe87379a5cf129a":{"name":"Wallet 3","address":"0x2cb215323857bec1c91e5db10fe87379a5cf129a","mayBeFauceting":false},"0xc5091450b7548b0dce3a76b8d325929c39e648d1":{"name":"Wallet 4","address":"0xc5091450b7548b0dce3a76b8d325929c39e648d1","mayBeFauceting":false}},"unconfTxs":{},"accounts":{"0x5f11b68b7d41633e74c6b18d8b8d147da52aedd6":{"balance":"0x0","nonce":"0x0","code":"0x","address":"0x5f11b68b7d41633e74c6b18d8b8d147da52aedd6"},"0x843963b837841dad3b0f5969ff271108776616df":{"balance":"0x0","nonce":"0x0","code":"0x","address":"0x843963b837841dad3b0f5969ff271108776616df"},"0x2cb215323857bec1c91e5db10fe87379a5cf129a":{"balance":"0x0","nonce":"0x0","code":"0x","address":"0x2cb215323857bec1c91e5db10fe87379a5cf129a"},"0xc5091450b7548b0dce3a76b8d325929c39e648d1":{"balance":"0x0","nonce":"0x0","code":"0x","address":"0xc5091450b7548b0dce3a76b8d325929c39e648d1"}},"transactions":[],"selectedAddress":"0x843963b837841dad3b0f5969ff271108776616df","network":"2","isDisclaimerConfirmed":true,"unconfMsgs":{},"messages":[],"provider":{"type":"testnet"},"selectedAccount":"0x843963b837841dad3b0f5969ff271108776616df"},"appState":{"menuOpen":false,"currentView":{"name":"accountDetail"},"accountDetail":{"subview":"transactions","accountExport":"none","privateKey":""},"currentDomain":"testfaucet.metamask.io","transForward":false,"isLoading":false,"warning":null,"scrollToBottom":false},"identities":{}}},{"new vault":{"metamask":{"isInitialized":false,"isUnlocked":false,"currentDomain":"example.com","rpcTarget":"https://rawtestrpc.metamask.io/","identities":{},"unconfTxs":{},"accounts":{},"transactions":[],"network":"2","seedWords":null,"isDisclaimerConfirmed":false,"unconfMsgs":{},"messages":[],"provider":{"type":"testnet"}},"appState":{"menuOpen":false,"currentView":{"name":"accounts","detailView":null},"accountDetail":{"subview":"transactions"},"currentDomain":"extensions","transForward":true,"isLoading":false,"warning":null},"identities":{}}},{"show seed words":{"metamask":{"isInitialized":false,"isUnlocked":true,"currentDomain":"example.com","rpcTarget":"https://rawtestrpc.metamask.io/","identities":{"0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc":{"name":"Wallet 1","address":"0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc","mayBeFauceting":false},"0xec1adf982415d2ef5ec55899b9bfb8bc0f29251b":{"name":"Wallet 2","address":"0xec1adf982415d2ef5ec55899b9bfb8bc0f29251b","mayBeFauceting":false},"0xeb9e64b93097bc15f01f13eae97015c57ab64823":{"name":"Wallet 3","address":"0xeb9e64b93097bc15f01f13eae97015c57ab64823","mayBeFauceting":false}},"unconfTxs":{},"accounts":{"0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc":{"balance":"0x0","nonce":"0x0","code":"0x","address":"0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc"},"0xec1adf982415d2ef5ec55899b9bfb8bc0f29251b":{"balance":"0x0","nonce":"0x0","code":"0x","address":"0xec1adf982415d2ef5ec55899b9bfb8bc0f29251b"},"0xeb9e64b93097bc15f01f13eae97015c57ab64823":{"balance":"0x0","nonce":"0x0","code":"0x","address":"0xeb9e64b93097bc15f01f13eae97015c57ab64823"}},"transactions":[],"network":"2","seedWords":"debris dizzy just program just float decrease vacant alarm reduce speak stadium","isDisclaimerConfirmed":false,"unconfMsgs":{},"messages":[],"provider":{"type":"testnet"}},"appState":{"menuOpen":false,"currentView":{"name":"createVaultComplete","seedWords":"debris dizzy just program just float decrease vacant alarm reduce speak stadium"},"accountDetail":{"subview":"transactions"},"currentDomain":"extensions","transForward":true,"isLoading":false,"warning":null},"identities":{}}},{"terms":{"metamask":{"accounts":{},"transactions":[],"identities":{},"network":"2","isInitialized":false,"isUnlocked":false,"seedWords":null,"isDisclaimerConfirmed":false,"unconfTxs":{},"unconfMsgs":{},"messages":[],"provider":{"type":"testnet"}},"appState":{"currentDomain":"extensions"}}}]
\ No newline at end of file diff --git a/development/states/account-detail-with-shapeshift-tx.json b/development/states/account-detail-with-shapeshift-tx.json index 027062979..1335ba2c3 100644 --- a/development/states/account-detail-with-shapeshift-tx.json +++ b/development/states/account-detail-with-shapeshift-tx.json @@ -133,10 +133,10 @@ "address": "0x704107d04affddd9b66ab9de3dd7b095852e9b69" } }, - "selectedAddress": "0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc", + "selectedAccount": "0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc", "network": "1", "seedWords": null, - "isConfirmed": true, + "isDisclaimerConfirmed": true, "unconfMsgs": {}, "messages": [], "provider": { diff --git a/development/states/account-detail-with-transaction-history.json b/development/states/account-detail-with-transaction-history.json index 69af85623..3847e341e 100644 --- a/development/states/account-detail-with-transaction-history.json +++ b/development/states/account-detail-with-transaction-history.json @@ -99,10 +99,10 @@ "status": "confirmed", "containsDelegateCall": false }], - "selectedAddress": "0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc", + "selectedAccount": "0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc", "network": "2", "seedWords": null, - "isConfirmed": true, + "isDisclaimerConfirmed": true, "unconfMsgs": {}, "messages": [], "provider": { diff --git a/development/states/account-detail.json b/development/states/account-detail.json index e51e31587..23729f37a 100644 --- a/development/states/account-detail.json +++ b/development/states/account-detail.json @@ -57,10 +57,10 @@ } }, "transactions": [], - "selectedAddress": "0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc", + "selectedAccount": "0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc", "network": "2", "seedWords": null, - "isConfirmed": true, + "isDisclaimerConfirmed": true, "unconfMsgs": {}, "messages": [], "provider": { diff --git a/development/states/accounts.json b/development/states/accounts.json index 9068be0bd..02c11cd98 100644 --- a/development/states/accounts.json +++ b/development/states/accounts.json @@ -2,7 +2,6 @@ "metamask": { "isInitialized": true, "isUnlocked": true, - "isEthConfirmed": true, "rpcTarget": "https://rawtestrpc.metamask.io/", "identities": { "0x0abdd95cafcabec9b3e99dcd09fc4b441037cb80": { @@ -90,9 +89,9 @@ } }, "transactions": [], - "selectedAddress": "0x0abdd95cafcabec9b3e99dcd09fc4b441037cb80", + "selectedAccount": "0x0abdd95cafcabec9b3e99dcd09fc4b441037cb80", "network": "2", - "isConfirmed": true, + "isDisclaimerConfirmed": true, "unconfMsgs": {}, "messages": [], "shapeShiftTxList": [], @@ -116,4 +115,4 @@ "scrollToBottom": true }, "identities": {} -}
\ No newline at end of file +} diff --git a/development/states/config.json b/development/states/config.json index 22d999158..195e13bbb 100644 --- a/development/states/config.json +++ b/development/states/config.json @@ -57,9 +57,9 @@ } }, "transactions": [], - "selectedAddress": "0x843963b837841dad3b0f5969ff271108776616df", + "selectedAccount": "0x843963b837841dad3b0f5969ff271108776616df", "network": "2", - "isConfirmed": true, + "isDisclaimerConfirmed": true, "unconfMsgs": {}, "messages": [], "provider": { diff --git a/development/states/create-vault-password.json b/development/states/create-vault-password.json index 2253ba639..69daec818 100644 --- a/development/states/create-vault-password.json +++ b/development/states/create-vault-password.json @@ -10,7 +10,7 @@ "transactions": [], "network": "2", "seedWords": null, - "isConfirmed": true, + "isDisclaimerConfirmed": true, "unconfMsgs": {}, "messages": [], "provider": { diff --git a/development/states/custom-rpc.json b/development/states/custom-rpc.json index 5ac8e9e58..79c2d667a 100644 --- a/development/states/custom-rpc.json +++ b/development/states/custom-rpc.json @@ -157,11 +157,10 @@ "estimatedGas": "0x5208" } ], - "selectedAddress": "0xfdea65c8e26263f6d9a1b5de9555d2931a33b825", + "selectedAccount": "0xfdea65c8e26263f6d9a1b5de9555d2931a33b825", "network": "166", "seedWords": null, - "isConfirmed": true, - "isEthConfirmed": true, + "isDisclaimerConfirmed": true, "unconfMsgs": {}, "messages": [], "provider": { diff --git a/development/states/empty-account-detail.json b/development/states/empty-account-detail.json index f95a4b251..d4e94b566 100644 --- a/development/states/empty-account-detail.json +++ b/development/states/empty-account-detail.json @@ -54,10 +54,10 @@ } }, "transactions": [], - "selectedAddress": "0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc", + "selectedAccount": "0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc", "network": "2", "seedWords": null, - "isConfirmed": true, + "isDisclaimerConfirmed": true, "unconfMsgs": {}, "messages": [], "provider": { diff --git a/development/states/terms.json b/development/states/first-time.json index 3a4914841..d6d95fe06 100644 --- a/development/states/terms.json +++ b/development/states/first-time.json @@ -2,18 +2,22 @@ "metamask": { "isInitialized": false, "isUnlocked": false, - "currentDomain": "example.com", "rpcTarget": "https://rawtestrpc.metamask.io/", "identities": {}, "unconfTxs": {}, + "currentFiat": "USD", + "conversionRate": 11.47635827, + "conversionDate": 1477606503, + "network": null, "accounts": {}, "transactions": [], - "network": "2", - "seedWords": null, - "isConfirmed": false, - "isEthConfirmed": false, + "isDisclaimerConfirmed": true, "unconfMsgs": {}, "messages": [], + "shapeShiftTxList": [], + "keyringTypes": [ + "Simple Key Pair" + ], "provider": { "type": "testnet" } @@ -21,15 +25,15 @@ "appState": { "menuOpen": false, "currentView": { - "name": "EthStoreWarning" + "name": "accounts", + "detailView": null }, "accountDetail": { "subview": "transactions" }, - "currentDomain": "127.0.0.1:9966", "transForward": true, "isLoading": false, "warning": null }, "identities": {} -}
\ No newline at end of file +} diff --git a/development/states/help.json b/development/states/help.json index 9c2c4f0d3..b0c9903ac 100644 --- a/development/states/help.json +++ b/development/states/help.json @@ -55,14 +55,14 @@ }, "transactions": [], "network": "2", - "isConfirmed": true, + "isDisclaimerConfirmed": true, "unconfMsgs": {}, "messages": [], "provider": { "type": "testnet" }, "selectedAccount": "0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc", - "selectedAddress": "0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc", + "selectedAccount": "0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc", "seedWords": null }, "appState": { diff --git a/development/states/locked.json b/development/states/locked.json index d21a062c1..d1eab125a 100644 --- a/development/states/locked.json +++ b/development/states/locked.json @@ -2,7 +2,6 @@ "metamask": { "isInitialized": true, "isUnlocked": false, - "isEthConfirmed": true, "currentDomain": "example.com", "rpcTarget": "https://rawtestrpc.metamask.io/", "identities": {}, @@ -12,10 +11,10 @@ "conversionDate": 1473358355, "accounts": {}, "transactions": [], - "selectedAddress": "0xfdea65c8e26263f6d9a1b5de9555d2931a33b825", + "selectedAccount": "0xfdea65c8e26263f6d9a1b5de9555d2931a33b825", "network": "1473186153102", "seedWords": null, - "isConfirmed": true, + "isDisclaimerConfirmed": true, "unconfMsgs": {}, "messages": [], "shapeShiftTxList": [], diff --git a/development/states/new-vault.json b/development/states/new-vault.json index 18b4e7427..b9d7c845b 100644 --- a/development/states/new-vault.json +++ b/development/states/new-vault.json @@ -10,7 +10,7 @@ "transactions": [], "network": "2", "seedWords": null, - "isConfirmed": false, + "isDisclaimerConfirmed": false, "unconfMsgs": {}, "messages": [], "provider": { diff --git a/development/states/pending-crash.json b/development/states/pending-crash.json index 086238d62..6c25323ea 100644 --- a/development/states/pending-crash.json +++ b/development/states/pending-crash.json @@ -1 +1 @@ -{"metamask":{"isInitialized":true,"isUnlocked":true,"currentDomain":"example.com","rpcTarget":"https://rawtestrpc.metamask.io/","identities":{},"unconfTxs":{"1467755147235616":{"id":1467755147235616,"txParams":{"from":"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825","data":"0x60a060405260046060527f48302e31000000000000000000000000000000000000000000000000000000006080526006805460008290527f48302e310000000000000000000000000000000000000000000000000000000882556100b5907ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f602060026001841615610100026000190190931692909204601f01919091048101905b8082111561017957600081556001016100a1565b505060405161099338038061099383398101604052808051906020019091908051820191906020018051906020019091908051820191906020015050836000600050600033600160a060020a0316815260200190815260200160002060005081905550836002600050819055508260036000509080519060200190828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061017d57805160ff19168380011785555b506101ad9291506100a1565b5090565b8280016001018555821561016d579182015b8281111561016d57825182600050559160200191906001019061018f565b50506004805460ff19168317905560058054825160008390527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db0602060026001851615610100026000190190941693909304601f90810184900482019386019083901061022d57805160ff19168380011785555b5061025d9291506100a1565b82800160010185558215610221579182015b8281111561022157825182600050559160200191906001019061023f565b505050505050610722806102716000396000f36060604052361561008d5760e060020a600035046306fdde038114610095578063095ea7b3146100f257806318160ddd1461015d57806323b872dd14610166578063313ce567146102c757806354fd4d50146102d357806370a082311461033057806395d89b411461035e578063a9059cbb146103bb578063cae9ca511461044d578063dd62ed3e14610639575b610000610002565b61066d60038054602060026001831615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156107105780601f106106e557610100808354040283529160200191610710565b61034c60043560243533600160a060020a03908116600081815260016020908152604080832094871680845294825282208590556060858152919392917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259190a35060015b92915050565b61034c60025481565b61034c600435602435604435600160a060020a0383166000908152602081905260408120548290108015906101b9575060016020908152604080832033600160a060020a03168452909152812054829010155b80156101c55750600082115b1561071d57816000600050600085600160a060020a03168152602001908152602001600020600082828250540192505081905550816000600050600086600160a060020a03168152602001908152602001600020600082828250540392505081905550816001600050600086600160a060020a03168152602001908152602001600020600050600033600160a060020a0316815260200190815260200160002060008282825054039250508190555082600160a060020a031684600160a060020a03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a3506001610632565b6106db60045460ff1681565b61066d60068054602060026001831615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156107105780601f106106e557610100808354040283529160200191610710565b600160a060020a03600435166000908152602081905260409020545b60408051918252519081900360200190f35b61066d60058054602060026001831615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156107105780601f106106e557610100808354040283529160200191610710565b61034c60043560243533600160a060020a03166000908152602081905260408120548290108015906103ed5750600082115b1561071857604080822080548490039055600160a060020a03808516808452918320805485019055606084815233909116907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602090a3506001610157565b60806020604435600481810135601f81018490049093028401604052606083815261034c94823594602480359560649493910191908190838280828437509496505050505050506000826001600050600033600160a060020a03168152602001908152602001600020600050600086600160a060020a031681526020019081526020016000206000508190555083600160a060020a031660405180807f72656365697665417070726f76616c28616464726573732c75696e743235362c81526020017f616464726573732c627974657329000000000000000000000000000000000000815260200150602e019050604051809103902060e060020a8091040260e060020a9004338530866040518560e060020a0281526004018085600160a060020a0316815260200184815260200183600160a060020a031681526020018280519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156105d45780820380516001836020036101000a031916815260200191505b509450505050506000604051808303816000876161da5a03f1505060408051868152905133600160a060020a031692507f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259181900360200190a35060015b9392505050565b61034c600435602435600160a060020a03808316600090815260016020908152604080832093851683529290522054610157565b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156106cd5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6060908152602090f35b820191906000526020600020905b8154815290600101906020018083116106f357829003601f168201915b505050505081565b610157565b6106325600000000000000000000000000000000000000000000000000000000000f42400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000844616e4275636b7300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034442580000000000000000000000000000000000000000000000000000000000","gasPrice":"0xba43b7400","gas":"0xf4240","origin":"tokenfactory.surge.sh","metamaskId":1467755147235616,"metamaskNetworkId":"1"},"time":1467755147235,"status":"unconfirmed"}},"accounts":{"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825":{}},"transactions":[{"id":1467742640796159,"txParams":{"from":"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825","data":"0x60a060405260046060527f48302e31000000000000000000000000000000000000000000000000000000006080526006805460008290527f48302e310000000000000000000000000000000000000000000000000000000882556100b5907ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f602060026001841615610100026000190190931692909204601f01919091048101905b8082111561017957600081556001016100a1565b505060405161099338038061099383398101604052808051906020019091908051820191906020018051906020019091908051820191906020015050836000600050600033600160a060020a0316815260200190815260200160002060005081905550836002600050819055508260036000509080519060200190828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061017d57805160ff19168380011785555b506101ad9291506100a1565b5090565b8280016001018555821561016d579182015b8281111561016d57825182600050559160200191906001019061018f565b50506004805460ff19168317905560058054825160008390527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db0602060026001851615610100026000190190941693909304601f90810184900482019386019083901061022d57805160ff19168380011785555b5061025d9291506100a1565b82800160010185558215610221579182015b8281111561022157825182600050559160200191906001019061023f565b505050505050610722806102716000396000f36060604052361561008d5760e060020a600035046306fdde038114610095578063095ea7b3146100f257806318160ddd1461015d57806323b872dd14610166578063313ce567146102c757806354fd4d50146102d357806370a082311461033057806395d89b411461035e578063a9059cbb146103bb578063cae9ca511461044d578063dd62ed3e14610639575b610000610002565b61066d60038054602060026001831615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156107105780601f106106e557610100808354040283529160200191610710565b61034c60043560243533600160a060020a03908116600081815260016020908152604080832094871680845294825282208590556060858152919392917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259190a35060015b92915050565b61034c60025481565b61034c600435602435604435600160a060020a0383166000908152602081905260408120548290108015906101b9575060016020908152604080832033600160a060020a03168452909152812054829010155b80156101c55750600082115b1561071d57816000600050600085600160a060020a03168152602001908152602001600020600082828250540192505081905550816000600050600086600160a060020a03168152602001908152602001600020600082828250540392505081905550816001600050600086600160a060020a03168152602001908152602001600020600050600033600160a060020a0316815260200190815260200160002060008282825054039250508190555082600160a060020a031684600160a060020a03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a3506001610632565b6106db60045460ff1681565b61066d60068054602060026001831615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156107105780601f106106e557610100808354040283529160200191610710565b600160a060020a03600435166000908152602081905260409020545b60408051918252519081900360200190f35b61066d60058054602060026001831615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156107105780601f106106e557610100808354040283529160200191610710565b61034c60043560243533600160a060020a03166000908152602081905260408120548290108015906103ed5750600082115b1561071857604080822080548490039055600160a060020a03808516808452918320805485019055606084815233909116907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602090a3506001610157565b60806020604435600481810135601f81018490049093028401604052606083815261034c94823594602480359560649493910191908190838280828437509496505050505050506000826001600050600033600160a060020a03168152602001908152602001600020600050600086600160a060020a031681526020019081526020016000206000508190555083600160a060020a031660405180807f72656365697665417070726f76616c28616464726573732c75696e743235362c81526020017f616464726573732c627974657329000000000000000000000000000000000000815260200150602e019050604051809103902060e060020a8091040260e060020a9004338530866040518560e060020a0281526004018085600160a060020a0316815260200184815260200183600160a060020a031681526020018280519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156105d45780820380516001836020036101000a031916815260200191505b509450505050506000604051808303816000876161da5a03f1505060408051868152905133600160a060020a031692507f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259181900360200190a35060015b9392505050565b61034c600435602435600160a060020a03808316600090815260016020908152604080832093851683529290522054610157565b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156106cd5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6060908152602090f35b820191906000526020600020905b8154815290600101906020018083116106f357829003601f168201915b505050505081565b610157565b6106325600000000000000000000000000000000000000000000000000000000000186a00000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000844616e6275636b7300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034442580000000000000000000000000000000000000000000000000000000000","gasPrice":"0xba43b7400","gas":"0xf4240","origin":"tokenfactory.surge.sh","metamaskId":1467742640796159,"metamaskNetworkId":"2"},"time":1467742640796,"status":"rejected"},{"id":1467742652846512,"txParams":{"from":"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825","data":"0x60a060405260046060527f48302e31000000000000000000000000000000000000000000000000000000006080526006805460008290527f48302e310000000000000000000000000000000000000000000000000000000882556100b5907ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f602060026001841615610100026000190190931692909204601f01919091048101905b8082111561017957600081556001016100a1565b505060405161099338038061099383398101604052808051906020019091908051820191906020018051906020019091908051820191906020015050836000600050600033600160a060020a0316815260200190815260200160002060005081905550836002600050819055508260036000509080519060200190828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061017d57805160ff19168380011785555b506101ad9291506100a1565b5090565b8280016001018555821561016d579182015b8281111561016d57825182600050559160200191906001019061018f565b50506004805460ff19168317905560058054825160008390527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db0602060026001851615610100026000190190941693909304601f90810184900482019386019083901061022d57805160ff19168380011785555b5061025d9291506100a1565b82800160010185558215610221579182015b8281111561022157825182600050559160200191906001019061023f565b505050505050610722806102716000396000f36060604052361561008d5760e060020a600035046306fdde038114610095578063095ea7b3146100f257806318160ddd1461015d57806323b872dd14610166578063313ce567146102c757806354fd4d50146102d357806370a082311461033057806395d89b411461035e578063a9059cbb146103bb578063cae9ca511461044d578063dd62ed3e14610639575b610000610002565b61066d60038054602060026001831615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156107105780601f106106e557610100808354040283529160200191610710565b61034c60043560243533600160a060020a03908116600081815260016020908152604080832094871680845294825282208590556060858152919392917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259190a35060015b92915050565b61034c60025481565b61034c600435602435604435600160a060020a0383166000908152602081905260408120548290108015906101b9575060016020908152604080832033600160a060020a03168452909152812054829010155b80156101c55750600082115b1561071d57816000600050600085600160a060020a03168152602001908152602001600020600082828250540192505081905550816000600050600086600160a060020a03168152602001908152602001600020600082828250540392505081905550816001600050600086600160a060020a03168152602001908152602001600020600050600033600160a060020a0316815260200190815260200160002060008282825054039250508190555082600160a060020a031684600160a060020a03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a3506001610632565b6106db60045460ff1681565b61066d60068054602060026001831615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156107105780601f106106e557610100808354040283529160200191610710565b600160a060020a03600435166000908152602081905260409020545b60408051918252519081900360200190f35b61066d60058054602060026001831615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156107105780601f106106e557610100808354040283529160200191610710565b61034c60043560243533600160a060020a03166000908152602081905260408120548290108015906103ed5750600082115b1561071857604080822080548490039055600160a060020a03808516808452918320805485019055606084815233909116907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602090a3506001610157565b60806020604435600481810135601f81018490049093028401604052606083815261034c94823594602480359560649493910191908190838280828437509496505050505050506000826001600050600033600160a060020a03168152602001908152602001600020600050600086600160a060020a031681526020019081526020016000206000508190555083600160a060020a031660405180807f72656365697665417070726f76616c28616464726573732c75696e743235362c81526020017f616464726573732c627974657329000000000000000000000000000000000000815260200150602e019050604051809103902060e060020a8091040260e060020a9004338530866040518560e060020a0281526004018085600160a060020a0316815260200184815260200183600160a060020a031681526020018280519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156105d45780820380516001836020036101000a031916815260200191505b509450505050506000604051808303816000876161da5a03f1505060408051868152905133600160a060020a031692507f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259181900360200190a35060015b9392505050565b61034c600435602435600160a060020a03808316600090815260016020908152604080832093851683529290522054610157565b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156106cd5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6060908152602090f35b820191906000526020600020905b8154815290600101906020018083116106f357829003601f168201915b505050505081565b610157565b6106325600000000000000000000000000000000000000000000000000000000000186a00000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000844616e6275636b7300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034442580000000000000000000000000000000000000000000000000000000000","gasPrice":"0xba43b7400","gas":"0xf4240","origin":"tokenfactory.surge.sh","metamaskId":1467742652846512,"metamaskNetworkId":"2"},"time":1467742652846,"status":"confirmed","hash":"0xa991793a6918aea6d58c30934dab5ca4c0a47c2444e5b60769637491f118de26"},{"id":1467755147235616,"txParams":{"from":"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825","data":"0x60a060405260046060527f48302e31000000000000000000000000000000000000000000000000000000006080526006805460008290527f48302e310000000000000000000000000000000000000000000000000000000882556100b5907ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f602060026001841615610100026000190190931692909204601f01919091048101905b8082111561017957600081556001016100a1565b505060405161099338038061099383398101604052808051906020019091908051820191906020018051906020019091908051820191906020015050836000600050600033600160a060020a0316815260200190815260200160002060005081905550836002600050819055508260036000509080519060200190828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061017d57805160ff19168380011785555b506101ad9291506100a1565b5090565b8280016001018555821561016d579182015b8281111561016d57825182600050559160200191906001019061018f565b50506004805460ff19168317905560058054825160008390527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db0602060026001851615610100026000190190941693909304601f90810184900482019386019083901061022d57805160ff19168380011785555b5061025d9291506100a1565b82800160010185558215610221579182015b8281111561022157825182600050559160200191906001019061023f565b505050505050610722806102716000396000f36060604052361561008d5760e060020a600035046306fdde038114610095578063095ea7b3146100f257806318160ddd1461015d57806323b872dd14610166578063313ce567146102c757806354fd4d50146102d357806370a082311461033057806395d89b411461035e578063a9059cbb146103bb578063cae9ca511461044d578063dd62ed3e14610639575b610000610002565b61066d60038054602060026001831615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156107105780601f106106e557610100808354040283529160200191610710565b61034c60043560243533600160a060020a03908116600081815260016020908152604080832094871680845294825282208590556060858152919392917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259190a35060015b92915050565b61034c60025481565b61034c600435602435604435600160a060020a0383166000908152602081905260408120548290108015906101b9575060016020908152604080832033600160a060020a03168452909152812054829010155b80156101c55750600082115b1561071d57816000600050600085600160a060020a03168152602001908152602001600020600082828250540192505081905550816000600050600086600160a060020a03168152602001908152602001600020600082828250540392505081905550816001600050600086600160a060020a03168152602001908152602001600020600050600033600160a060020a0316815260200190815260200160002060008282825054039250508190555082600160a060020a031684600160a060020a03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a3506001610632565b6106db60045460ff1681565b61066d60068054602060026001831615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156107105780601f106106e557610100808354040283529160200191610710565b600160a060020a03600435166000908152602081905260409020545b60408051918252519081900360200190f35b61066d60058054602060026001831615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156107105780601f106106e557610100808354040283529160200191610710565b61034c60043560243533600160a060020a03166000908152602081905260408120548290108015906103ed5750600082115b1561071857604080822080548490039055600160a060020a03808516808452918320805485019055606084815233909116907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602090a3506001610157565b60806020604435600481810135601f81018490049093028401604052606083815261034c94823594602480359560649493910191908190838280828437509496505050505050506000826001600050600033600160a060020a03168152602001908152602001600020600050600086600160a060020a031681526020019081526020016000206000508190555083600160a060020a031660405180807f72656365697665417070726f76616c28616464726573732c75696e743235362c81526020017f616464726573732c627974657329000000000000000000000000000000000000815260200150602e019050604051809103902060e060020a8091040260e060020a9004338530866040518560e060020a0281526004018085600160a060020a0316815260200184815260200183600160a060020a031681526020018280519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156105d45780820380516001836020036101000a031916815260200191505b509450505050506000604051808303816000876161da5a03f1505060408051868152905133600160a060020a031692507f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259181900360200190a35060015b9392505050565b61034c600435602435600160a060020a03808316600090815260016020908152604080832093851683529290522054610157565b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156106cd5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6060908152602090f35b820191906000526020600020905b8154815290600101906020018083116106f357829003601f168201915b505050505081565b610157565b6106325600000000000000000000000000000000000000000000000000000000000f42400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000844616e4275636b7300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034442580000000000000000000000000000000000000000000000000000000000","gasPrice":"0xba43b7400","gas":"0xf4240","origin":"tokenfactory.surge.sh","metamaskId":1467755147235616,"metamaskNetworkId":"1"},"time":1467755147235,"status":"unconfirmed"}],"selectedAddress":"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825","network":"1","seedWords":null,"isConfirmed":true,"unconfMsgs":{},"messages":[],"provider":{"type":"mainnet"},"selectedAccount":"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825"},"appState":{"menuOpen":false,"currentView":{"name":"confTx","context":0},"accountDetail":{"subview":"transactions"},"currentDomain":"tokenfactory.surge.sh","transForward":true,"isLoading":false,"warning":null},"identities":{}}
\ No newline at end of file +{"metamask":{"isInitialized":true,"isUnlocked":true,"currentDomain":"example.com","rpcTarget":"https://rawtestrpc.metamask.io/","identities":{},"unconfTxs":{"1467755147235616":{"id":1467755147235616,"txParams":{"from":"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825","data":"0x60a060405260046060527f48302e31000000000000000000000000000000000000000000000000000000006080526006805460008290527f48302e310000000000000000000000000000000000000000000000000000000882556100b5907ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f602060026001841615610100026000190190931692909204601f01919091048101905b8082111561017957600081556001016100a1565b505060405161099338038061099383398101604052808051906020019091908051820191906020018051906020019091908051820191906020015050836000600050600033600160a060020a0316815260200190815260200160002060005081905550836002600050819055508260036000509080519060200190828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061017d57805160ff19168380011785555b506101ad9291506100a1565b5090565b8280016001018555821561016d579182015b8281111561016d57825182600050559160200191906001019061018f565b50506004805460ff19168317905560058054825160008390527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db0602060026001851615610100026000190190941693909304601f90810184900482019386019083901061022d57805160ff19168380011785555b5061025d9291506100a1565b82800160010185558215610221579182015b8281111561022157825182600050559160200191906001019061023f565b505050505050610722806102716000396000f36060604052361561008d5760e060020a600035046306fdde038114610095578063095ea7b3146100f257806318160ddd1461015d57806323b872dd14610166578063313ce567146102c757806354fd4d50146102d357806370a082311461033057806395d89b411461035e578063a9059cbb146103bb578063cae9ca511461044d578063dd62ed3e14610639575b610000610002565b61066d60038054602060026001831615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156107105780601f106106e557610100808354040283529160200191610710565b61034c60043560243533600160a060020a03908116600081815260016020908152604080832094871680845294825282208590556060858152919392917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259190a35060015b92915050565b61034c60025481565b61034c600435602435604435600160a060020a0383166000908152602081905260408120548290108015906101b9575060016020908152604080832033600160a060020a03168452909152812054829010155b80156101c55750600082115b1561071d57816000600050600085600160a060020a03168152602001908152602001600020600082828250540192505081905550816000600050600086600160a060020a03168152602001908152602001600020600082828250540392505081905550816001600050600086600160a060020a03168152602001908152602001600020600050600033600160a060020a0316815260200190815260200160002060008282825054039250508190555082600160a060020a031684600160a060020a03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a3506001610632565b6106db60045460ff1681565b61066d60068054602060026001831615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156107105780601f106106e557610100808354040283529160200191610710565b600160a060020a03600435166000908152602081905260409020545b60408051918252519081900360200190f35b61066d60058054602060026001831615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156107105780601f106106e557610100808354040283529160200191610710565b61034c60043560243533600160a060020a03166000908152602081905260408120548290108015906103ed5750600082115b1561071857604080822080548490039055600160a060020a03808516808452918320805485019055606084815233909116907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602090a3506001610157565b60806020604435600481810135601f81018490049093028401604052606083815261034c94823594602480359560649493910191908190838280828437509496505050505050506000826001600050600033600160a060020a03168152602001908152602001600020600050600086600160a060020a031681526020019081526020016000206000508190555083600160a060020a031660405180807f72656365697665417070726f76616c28616464726573732c75696e743235362c81526020017f616464726573732c627974657329000000000000000000000000000000000000815260200150602e019050604051809103902060e060020a8091040260e060020a9004338530866040518560e060020a0281526004018085600160a060020a0316815260200184815260200183600160a060020a031681526020018280519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156105d45780820380516001836020036101000a031916815260200191505b509450505050506000604051808303816000876161da5a03f1505060408051868152905133600160a060020a031692507f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259181900360200190a35060015b9392505050565b61034c600435602435600160a060020a03808316600090815260016020908152604080832093851683529290522054610157565b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156106cd5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6060908152602090f35b820191906000526020600020905b8154815290600101906020018083116106f357829003601f168201915b505050505081565b610157565b6106325600000000000000000000000000000000000000000000000000000000000f42400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000844616e4275636b7300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034442580000000000000000000000000000000000000000000000000000000000","gasPrice":"0xba43b7400","gas":"0xf4240","origin":"tokenfactory.surge.sh","metamaskId":1467755147235616,"metamaskNetworkId":"1"},"time":1467755147235,"status":"unconfirmed"}},"accounts":{"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825":{}},"transactions":[{"id":1467742640796159,"txParams":{"from":"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825","data":"0x60a060405260046060527f48302e31000000000000000000000000000000000000000000000000000000006080526006805460008290527f48302e310000000000000000000000000000000000000000000000000000000882556100b5907ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f602060026001841615610100026000190190931692909204601f01919091048101905b8082111561017957600081556001016100a1565b505060405161099338038061099383398101604052808051906020019091908051820191906020018051906020019091908051820191906020015050836000600050600033600160a060020a0316815260200190815260200160002060005081905550836002600050819055508260036000509080519060200190828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061017d57805160ff19168380011785555b506101ad9291506100a1565b5090565b8280016001018555821561016d579182015b8281111561016d57825182600050559160200191906001019061018f565b50506004805460ff19168317905560058054825160008390527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db0602060026001851615610100026000190190941693909304601f90810184900482019386019083901061022d57805160ff19168380011785555b5061025d9291506100a1565b82800160010185558215610221579182015b8281111561022157825182600050559160200191906001019061023f565b505050505050610722806102716000396000f36060604052361561008d5760e060020a600035046306fdde038114610095578063095ea7b3146100f257806318160ddd1461015d57806323b872dd14610166578063313ce567146102c757806354fd4d50146102d357806370a082311461033057806395d89b411461035e578063a9059cbb146103bb578063cae9ca511461044d578063dd62ed3e14610639575b610000610002565b61066d60038054602060026001831615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156107105780601f106106e557610100808354040283529160200191610710565b61034c60043560243533600160a060020a03908116600081815260016020908152604080832094871680845294825282208590556060858152919392917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259190a35060015b92915050565b61034c60025481565b61034c600435602435604435600160a060020a0383166000908152602081905260408120548290108015906101b9575060016020908152604080832033600160a060020a03168452909152812054829010155b80156101c55750600082115b1561071d57816000600050600085600160a060020a03168152602001908152602001600020600082828250540192505081905550816000600050600086600160a060020a03168152602001908152602001600020600082828250540392505081905550816001600050600086600160a060020a03168152602001908152602001600020600050600033600160a060020a0316815260200190815260200160002060008282825054039250508190555082600160a060020a031684600160a060020a03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a3506001610632565b6106db60045460ff1681565b61066d60068054602060026001831615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156107105780601f106106e557610100808354040283529160200191610710565b600160a060020a03600435166000908152602081905260409020545b60408051918252519081900360200190f35b61066d60058054602060026001831615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156107105780601f106106e557610100808354040283529160200191610710565b61034c60043560243533600160a060020a03166000908152602081905260408120548290108015906103ed5750600082115b1561071857604080822080548490039055600160a060020a03808516808452918320805485019055606084815233909116907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602090a3506001610157565b60806020604435600481810135601f81018490049093028401604052606083815261034c94823594602480359560649493910191908190838280828437509496505050505050506000826001600050600033600160a060020a03168152602001908152602001600020600050600086600160a060020a031681526020019081526020016000206000508190555083600160a060020a031660405180807f72656365697665417070726f76616c28616464726573732c75696e743235362c81526020017f616464726573732c627974657329000000000000000000000000000000000000815260200150602e019050604051809103902060e060020a8091040260e060020a9004338530866040518560e060020a0281526004018085600160a060020a0316815260200184815260200183600160a060020a031681526020018280519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156105d45780820380516001836020036101000a031916815260200191505b509450505050506000604051808303816000876161da5a03f1505060408051868152905133600160a060020a031692507f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259181900360200190a35060015b9392505050565b61034c600435602435600160a060020a03808316600090815260016020908152604080832093851683529290522054610157565b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156106cd5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6060908152602090f35b820191906000526020600020905b8154815290600101906020018083116106f357829003601f168201915b505050505081565b610157565b6106325600000000000000000000000000000000000000000000000000000000000186a00000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000844616e6275636b7300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034442580000000000000000000000000000000000000000000000000000000000","gasPrice":"0xba43b7400","gas":"0xf4240","origin":"tokenfactory.surge.sh","metamaskId":1467742640796159,"metamaskNetworkId":"2"},"time":1467742640796,"status":"rejected"},{"id":1467742652846512,"txParams":{"from":"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825","data":"0x60a060405260046060527f48302e31000000000000000000000000000000000000000000000000000000006080526006805460008290527f48302e310000000000000000000000000000000000000000000000000000000882556100b5907ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f602060026001841615610100026000190190931692909204601f01919091048101905b8082111561017957600081556001016100a1565b505060405161099338038061099383398101604052808051906020019091908051820191906020018051906020019091908051820191906020015050836000600050600033600160a060020a0316815260200190815260200160002060005081905550836002600050819055508260036000509080519060200190828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061017d57805160ff19168380011785555b506101ad9291506100a1565b5090565b8280016001018555821561016d579182015b8281111561016d57825182600050559160200191906001019061018f565b50506004805460ff19168317905560058054825160008390527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db0602060026001851615610100026000190190941693909304601f90810184900482019386019083901061022d57805160ff19168380011785555b5061025d9291506100a1565b82800160010185558215610221579182015b8281111561022157825182600050559160200191906001019061023f565b505050505050610722806102716000396000f36060604052361561008d5760e060020a600035046306fdde038114610095578063095ea7b3146100f257806318160ddd1461015d57806323b872dd14610166578063313ce567146102c757806354fd4d50146102d357806370a082311461033057806395d89b411461035e578063a9059cbb146103bb578063cae9ca511461044d578063dd62ed3e14610639575b610000610002565b61066d60038054602060026001831615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156107105780601f106106e557610100808354040283529160200191610710565b61034c60043560243533600160a060020a03908116600081815260016020908152604080832094871680845294825282208590556060858152919392917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259190a35060015b92915050565b61034c60025481565b61034c600435602435604435600160a060020a0383166000908152602081905260408120548290108015906101b9575060016020908152604080832033600160a060020a03168452909152812054829010155b80156101c55750600082115b1561071d57816000600050600085600160a060020a03168152602001908152602001600020600082828250540192505081905550816000600050600086600160a060020a03168152602001908152602001600020600082828250540392505081905550816001600050600086600160a060020a03168152602001908152602001600020600050600033600160a060020a0316815260200190815260200160002060008282825054039250508190555082600160a060020a031684600160a060020a03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a3506001610632565b6106db60045460ff1681565b61066d60068054602060026001831615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156107105780601f106106e557610100808354040283529160200191610710565b600160a060020a03600435166000908152602081905260409020545b60408051918252519081900360200190f35b61066d60058054602060026001831615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156107105780601f106106e557610100808354040283529160200191610710565b61034c60043560243533600160a060020a03166000908152602081905260408120548290108015906103ed5750600082115b1561071857604080822080548490039055600160a060020a03808516808452918320805485019055606084815233909116907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602090a3506001610157565b60806020604435600481810135601f81018490049093028401604052606083815261034c94823594602480359560649493910191908190838280828437509496505050505050506000826001600050600033600160a060020a03168152602001908152602001600020600050600086600160a060020a031681526020019081526020016000206000508190555083600160a060020a031660405180807f72656365697665417070726f76616c28616464726573732c75696e743235362c81526020017f616464726573732c627974657329000000000000000000000000000000000000815260200150602e019050604051809103902060e060020a8091040260e060020a9004338530866040518560e060020a0281526004018085600160a060020a0316815260200184815260200183600160a060020a031681526020018280519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156105d45780820380516001836020036101000a031916815260200191505b509450505050506000604051808303816000876161da5a03f1505060408051868152905133600160a060020a031692507f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259181900360200190a35060015b9392505050565b61034c600435602435600160a060020a03808316600090815260016020908152604080832093851683529290522054610157565b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156106cd5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6060908152602090f35b820191906000526020600020905b8154815290600101906020018083116106f357829003601f168201915b505050505081565b610157565b6106325600000000000000000000000000000000000000000000000000000000000186a00000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000844616e6275636b7300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034442580000000000000000000000000000000000000000000000000000000000","gasPrice":"0xba43b7400","gas":"0xf4240","origin":"tokenfactory.surge.sh","metamaskId":1467742652846512,"metamaskNetworkId":"2"},"time":1467742652846,"status":"confirmed","hash":"0xa991793a6918aea6d58c30934dab5ca4c0a47c2444e5b60769637491f118de26"},{"id":1467755147235616,"txParams":{"from":"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825","data":"0x60a060405260046060527f48302e31000000000000000000000000000000000000000000000000000000006080526006805460008290527f48302e310000000000000000000000000000000000000000000000000000000882556100b5907ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f602060026001841615610100026000190190931692909204601f01919091048101905b8082111561017957600081556001016100a1565b505060405161099338038061099383398101604052808051906020019091908051820191906020018051906020019091908051820191906020015050836000600050600033600160a060020a0316815260200190815260200160002060005081905550836002600050819055508260036000509080519060200190828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061017d57805160ff19168380011785555b506101ad9291506100a1565b5090565b8280016001018555821561016d579182015b8281111561016d57825182600050559160200191906001019061018f565b50506004805460ff19168317905560058054825160008390527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db0602060026001851615610100026000190190941693909304601f90810184900482019386019083901061022d57805160ff19168380011785555b5061025d9291506100a1565b82800160010185558215610221579182015b8281111561022157825182600050559160200191906001019061023f565b505050505050610722806102716000396000f36060604052361561008d5760e060020a600035046306fdde038114610095578063095ea7b3146100f257806318160ddd1461015d57806323b872dd14610166578063313ce567146102c757806354fd4d50146102d357806370a082311461033057806395d89b411461035e578063a9059cbb146103bb578063cae9ca511461044d578063dd62ed3e14610639575b610000610002565b61066d60038054602060026001831615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156107105780601f106106e557610100808354040283529160200191610710565b61034c60043560243533600160a060020a03908116600081815260016020908152604080832094871680845294825282208590556060858152919392917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259190a35060015b92915050565b61034c60025481565b61034c600435602435604435600160a060020a0383166000908152602081905260408120548290108015906101b9575060016020908152604080832033600160a060020a03168452909152812054829010155b80156101c55750600082115b1561071d57816000600050600085600160a060020a03168152602001908152602001600020600082828250540192505081905550816000600050600086600160a060020a03168152602001908152602001600020600082828250540392505081905550816001600050600086600160a060020a03168152602001908152602001600020600050600033600160a060020a0316815260200190815260200160002060008282825054039250508190555082600160a060020a031684600160a060020a03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a3506001610632565b6106db60045460ff1681565b61066d60068054602060026001831615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156107105780601f106106e557610100808354040283529160200191610710565b600160a060020a03600435166000908152602081905260409020545b60408051918252519081900360200190f35b61066d60058054602060026001831615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156107105780601f106106e557610100808354040283529160200191610710565b61034c60043560243533600160a060020a03166000908152602081905260408120548290108015906103ed5750600082115b1561071857604080822080548490039055600160a060020a03808516808452918320805485019055606084815233909116907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602090a3506001610157565b60806020604435600481810135601f81018490049093028401604052606083815261034c94823594602480359560649493910191908190838280828437509496505050505050506000826001600050600033600160a060020a03168152602001908152602001600020600050600086600160a060020a031681526020019081526020016000206000508190555083600160a060020a031660405180807f72656365697665417070726f76616c28616464726573732c75696e743235362c81526020017f616464726573732c627974657329000000000000000000000000000000000000815260200150602e019050604051809103902060e060020a8091040260e060020a9004338530866040518560e060020a0281526004018085600160a060020a0316815260200184815260200183600160a060020a031681526020018280519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156105d45780820380516001836020036101000a031916815260200191505b509450505050506000604051808303816000876161da5a03f1505060408051868152905133600160a060020a031692507f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259181900360200190a35060015b9392505050565b61034c600435602435600160a060020a03808316600090815260016020908152604080832093851683529290522054610157565b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156106cd5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6060908152602090f35b820191906000526020600020905b8154815290600101906020018083116106f357829003601f168201915b505050505081565b610157565b6106325600000000000000000000000000000000000000000000000000000000000f42400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000844616e4275636b7300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034442580000000000000000000000000000000000000000000000000000000000","gasPrice":"0xba43b7400","gas":"0xf4240","origin":"tokenfactory.surge.sh","metamaskId":1467755147235616,"metamaskNetworkId":"1"},"time":1467755147235,"status":"unconfirmed"}],"selectedAccount":"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825","network":"1","seedWords":null,"isDisclaimerConfirmed":true,"unconfMsgs":{},"messages":[],"provider":{"type":"mainnet"},"selectedAccount":"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825"},"appState":{"menuOpen":false,"currentView":{"name":"confTx","context":0},"accountDetail":{"subview":"transactions"},"currentDomain":"tokenfactory.surge.sh","transForward":true,"isLoading":false,"warning":null},"identities":{}}
\ No newline at end of file diff --git a/development/states/pending-signature.json b/development/states/pending-signature.json index 33f79b4c8..bc233a0ad 100644 --- a/development/states/pending-signature.json +++ b/development/states/pending-signature.json @@ -2,7 +2,6 @@ "metamask": { "isInitialized": true, "isUnlocked": true, - "isEthConfirmed": true, "currentDomain": "example.com", "rpcTarget": "https://rawtestrpc.metamask.io/", "identities": { @@ -352,10 +351,10 @@ "hash": "0xb6e6ff57e7b5f6bd7f2e6dc44c39f4e858a227c9509586634ca547179345a13e" } ], - "selectedAddress": "0xfdea65c8e26263f6d9a1b5de9555d2931a33b825", + "selectedAccount": "0xfdea65c8e26263f6d9a1b5de9555d2931a33b825", "network": "1471904489432", "seedWords": null, - "isConfirmed": true, + "isDisclaimerConfirmed": true, "unconfMsgs": { "1472076978535283": { "id": 1472076978535283, @@ -403,4 +402,4 @@ "warning": null }, "identities": {} -}
\ No newline at end of file +} diff --git a/development/states/pending-tx-contract.json b/development/states/pending-tx-contract.json index 5599f3753..f60198032 100644 --- a/development/states/pending-tx-contract.json +++ b/development/states/pending-tx-contract.json @@ -1 +1 @@ -{"metamask":{"isInitialized":true,"isUnlocked":true,"currentDomain":"example.com","rpcTarget":"https://rawtestrpc.metamask.io/","identities":{"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825":{"name":"Wallet 1","address":"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825","mayBeFauceting":false},"0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb":{"name":"Wallet 2","address":"0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb","mayBeFauceting":false},"0x2f8d4a878cfa04a6e60d46362f5644deab66572d":{"name":"Wallet 3","address":"0x2f8d4a878cfa04a6e60d46362f5644deab66572d","mayBeFauceting":false}},"unconfTxs":{"1467755147235616":{"id":1467755147235616,"txParams":{"from":"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825","data":"0x60a060405260046060527f48302e31000000000000000000000000000000000000000000000000000000006080526006805460008290527f48302e310000000000000000000000000000000000000000000000000000000882556100b5907ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f602060026001841615610100026000190190931692909204601f01919091048101905b8082111561017957600081556001016100a1565b505060405161099338038061099383398101604052808051906020019091908051820191906020018051906020019091908051820191906020015050836000600050600033600160a060020a0316815260200190815260200160002060005081905550836002600050819055508260036000509080519060200190828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061017d57805160ff19168380011785555b506101ad9291506100a1565b5090565b8280016001018555821561016d579182015b8281111561016d57825182600050559160200191906001019061018f565b50506004805460ff19168317905560058054825160008390527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db0602060026001851615610100026000190190941693909304601f90810184900482019386019083901061022d57805160ff19168380011785555b5061025d9291506100a1565b82800160010185558215610221579182015b8281111561022157825182600050559160200191906001019061023f565b505050505050610722806102716000396000f36060604052361561008d5760e060020a600035046306fdde038114610095578063095ea7b3146100f257806318160ddd1461015d57806323b872dd14610166578063313ce567146102c757806354fd4d50146102d357806370a082311461033057806395d89b411461035e578063a9059cbb146103bb578063cae9ca511461044d578063dd62ed3e14610639575b610000610002565b61066d60038054602060026001831615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156107105780601f106106e557610100808354040283529160200191610710565b61034c60043560243533600160a060020a03908116600081815260016020908152604080832094871680845294825282208590556060858152919392917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259190a35060015b92915050565b61034c60025481565b61034c600435602435604435600160a060020a0383166000908152602081905260408120548290108015906101b9575060016020908152604080832033600160a060020a03168452909152812054829010155b80156101c55750600082115b1561071d57816000600050600085600160a060020a03168152602001908152602001600020600082828250540192505081905550816000600050600086600160a060020a03168152602001908152602001600020600082828250540392505081905550816001600050600086600160a060020a03168152602001908152602001600020600050600033600160a060020a0316815260200190815260200160002060008282825054039250508190555082600160a060020a031684600160a060020a03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a3506001610632565b6106db60045460ff1681565b61066d60068054602060026001831615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156107105780601f106106e557610100808354040283529160200191610710565b600160a060020a03600435166000908152602081905260409020545b60408051918252519081900360200190f35b61066d60058054602060026001831615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156107105780601f106106e557610100808354040283529160200191610710565b61034c60043560243533600160a060020a03166000908152602081905260408120548290108015906103ed5750600082115b1561071857604080822080548490039055600160a060020a03808516808452918320805485019055606084815233909116907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602090a3506001610157565b60806020604435600481810135601f81018490049093028401604052606083815261034c94823594602480359560649493910191908190838280828437509496505050505050506000826001600050600033600160a060020a03168152602001908152602001600020600050600086600160a060020a031681526020019081526020016000206000508190555083600160a060020a031660405180807f72656365697665417070726f76616c28616464726573732c75696e743235362c81526020017f616464726573732c627974657329000000000000000000000000000000000000815260200150602e019050604051809103902060e060020a8091040260e060020a9004338530866040518560e060020a0281526004018085600160a060020a0316815260200184815260200183600160a060020a031681526020018280519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156105d45780820380516001836020036101000a031916815260200191505b509450505050506000604051808303816000876161da5a03f1505060408051868152905133600160a060020a031692507f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259181900360200190a35060015b9392505050565b61034c600435602435600160a060020a03808316600090815260016020908152604080832093851683529290522054610157565b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156106cd5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6060908152602090f35b820191906000526020600020905b8154815290600101906020018083116106f357829003601f168201915b505050505081565b610157565b6106325600000000000000000000000000000000000000000000000000000000000f42400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000844616e4275636b7300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034442580000000000000000000000000000000000000000000000000000000000","gasPrice":"0xba43b7400","gas":"0xf4240","origin":"tokenfactory.surge.sh","metamaskId":1467755147235616,"metamaskNetworkId":"1"},"time":1467755147235,"status":"unconfirmed"}},"accounts":{"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825":{"code":"0x","balance":"0x1000000","nonce":"0x0","address":"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825"},"0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb":{"code":"0x","nonce":"0x0","balance":"0x1000000","address":"0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb"},"0x2f8d4a878cfa04a6e60d46362f5644deab66572d":{"code":"0x","balance":"0x1000000","nonce":"0x0","address":"0x2f8d4a878cfa04a6e60d46362f5644deab66572d"}},"transactions":[{"id":1467742640796159,"txParams":{"from":"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825","data":"0x60a060405260046060527f48302e31000000000000000000000000000000000000000000000000000000006080526006805460008290527f48302e310000000000000000000000000000000000000000000000000000000882556100b5907ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f602060026001841615610100026000190190931692909204601f01919091048101905b8082111561017957600081556001016100a1565b505060405161099338038061099383398101604052808051906020019091908051820191906020018051906020019091908051820191906020015050836000600050600033600160a060020a0316815260200190815260200160002060005081905550836002600050819055508260036000509080519060200190828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061017d57805160ff19168380011785555b506101ad9291506100a1565b5090565b8280016001018555821561016d579182015b8281111561016d57825182600050559160200191906001019061018f565b50506004805460ff19168317905560058054825160008390527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db0602060026001851615610100026000190190941693909304601f90810184900482019386019083901061022d57805160ff19168380011785555b5061025d9291506100a1565b82800160010185558215610221579182015b8281111561022157825182600050559160200191906001019061023f565b505050505050610722806102716000396000f36060604052361561008d5760e060020a600035046306fdde038114610095578063095ea7b3146100f257806318160ddd1461015d57806323b872dd14610166578063313ce567146102c757806354fd4d50146102d357806370a082311461033057806395d89b411461035e578063a9059cbb146103bb578063cae9ca511461044d578063dd62ed3e14610639575b610000610002565b61066d60038054602060026001831615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156107105780601f106106e557610100808354040283529160200191610710565b61034c60043560243533600160a060020a03908116600081815260016020908152604080832094871680845294825282208590556060858152919392917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259190a35060015b92915050565b61034c60025481565b61034c600435602435604435600160a060020a0383166000908152602081905260408120548290108015906101b9575060016020908152604080832033600160a060020a03168452909152812054829010155b80156101c55750600082115b1561071d57816000600050600085600160a060020a03168152602001908152602001600020600082828250540192505081905550816000600050600086600160a060020a03168152602001908152602001600020600082828250540392505081905550816001600050600086600160a060020a03168152602001908152602001600020600050600033600160a060020a0316815260200190815260200160002060008282825054039250508190555082600160a060020a031684600160a060020a03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a3506001610632565b6106db60045460ff1681565b61066d60068054602060026001831615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156107105780601f106106e557610100808354040283529160200191610710565b600160a060020a03600435166000908152602081905260409020545b60408051918252519081900360200190f35b61066d60058054602060026001831615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156107105780601f106106e557610100808354040283529160200191610710565b61034c60043560243533600160a060020a03166000908152602081905260408120548290108015906103ed5750600082115b1561071857604080822080548490039055600160a060020a03808516808452918320805485019055606084815233909116907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602090a3506001610157565b60806020604435600481810135601f81018490049093028401604052606083815261034c94823594602480359560649493910191908190838280828437509496505050505050506000826001600050600033600160a060020a03168152602001908152602001600020600050600086600160a060020a031681526020019081526020016000206000508190555083600160a060020a031660405180807f72656365697665417070726f76616c28616464726573732c75696e743235362c81526020017f616464726573732c627974657329000000000000000000000000000000000000815260200150602e019050604051809103902060e060020a8091040260e060020a9004338530866040518560e060020a0281526004018085600160a060020a0316815260200184815260200183600160a060020a031681526020018280519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156105d45780820380516001836020036101000a031916815260200191505b509450505050506000604051808303816000876161da5a03f1505060408051868152905133600160a060020a031692507f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259181900360200190a35060015b9392505050565b61034c600435602435600160a060020a03808316600090815260016020908152604080832093851683529290522054610157565b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156106cd5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6060908152602090f35b820191906000526020600020905b8154815290600101906020018083116106f357829003601f168201915b505050505081565b610157565b6106325600000000000000000000000000000000000000000000000000000000000186a00000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000844616e6275636b7300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034442580000000000000000000000000000000000000000000000000000000000","gasPrice":"0xba43b7400","gas":"0xf4240","origin":"tokenfactory.surge.sh","metamaskId":1467742640796159,"metamaskNetworkId":"2"},"time":1467742640796,"status":"rejected"},{"id":1467742652846512,"txParams":{"from":"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825","data":"0x60a060405260046060527f48302e31000000000000000000000000000000000000000000000000000000006080526006805460008290527f48302e310000000000000000000000000000000000000000000000000000000882556100b5907ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f602060026001841615610100026000190190931692909204601f01919091048101905b8082111561017957600081556001016100a1565b505060405161099338038061099383398101604052808051906020019091908051820191906020018051906020019091908051820191906020015050836000600050600033600160a060020a0316815260200190815260200160002060005081905550836002600050819055508260036000509080519060200190828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061017d57805160ff19168380011785555b506101ad9291506100a1565b5090565b8280016001018555821561016d579182015b8281111561016d57825182600050559160200191906001019061018f565b50506004805460ff19168317905560058054825160008390527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db0602060026001851615610100026000190190941693909304601f90810184900482019386019083901061022d57805160ff19168380011785555b5061025d9291506100a1565b82800160010185558215610221579182015b8281111561022157825182600050559160200191906001019061023f565b505050505050610722806102716000396000f36060604052361561008d5760e060020a600035046306fdde038114610095578063095ea7b3146100f257806318160ddd1461015d57806323b872dd14610166578063313ce567146102c757806354fd4d50146102d357806370a082311461033057806395d89b411461035e578063a9059cbb146103bb578063cae9ca511461044d578063dd62ed3e14610639575b610000610002565b61066d60038054602060026001831615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156107105780601f106106e557610100808354040283529160200191610710565b61034c60043560243533600160a060020a03908116600081815260016020908152604080832094871680845294825282208590556060858152919392917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259190a35060015b92915050565b61034c60025481565b61034c600435602435604435600160a060020a0383166000908152602081905260408120548290108015906101b9575060016020908152604080832033600160a060020a03168452909152812054829010155b80156101c55750600082115b1561071d57816000600050600085600160a060020a03168152602001908152602001600020600082828250540192505081905550816000600050600086600160a060020a03168152602001908152602001600020600082828250540392505081905550816001600050600086600160a060020a03168152602001908152602001600020600050600033600160a060020a0316815260200190815260200160002060008282825054039250508190555082600160a060020a031684600160a060020a03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a3506001610632565b6106db60045460ff1681565b61066d60068054602060026001831615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156107105780601f106106e557610100808354040283529160200191610710565b600160a060020a03600435166000908152602081905260409020545b60408051918252519081900360200190f35b61066d60058054602060026001831615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156107105780601f106106e557610100808354040283529160200191610710565b61034c60043560243533600160a060020a03166000908152602081905260408120548290108015906103ed5750600082115b1561071857604080822080548490039055600160a060020a03808516808452918320805485019055606084815233909116907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602090a3506001610157565b60806020604435600481810135601f81018490049093028401604052606083815261034c94823594602480359560649493910191908190838280828437509496505050505050506000826001600050600033600160a060020a03168152602001908152602001600020600050600086600160a060020a031681526020019081526020016000206000508190555083600160a060020a031660405180807f72656365697665417070726f76616c28616464726573732c75696e743235362c81526020017f616464726573732c627974657329000000000000000000000000000000000000815260200150602e019050604051809103902060e060020a8091040260e060020a9004338530866040518560e060020a0281526004018085600160a060020a0316815260200184815260200183600160a060020a031681526020018280519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156105d45780820380516001836020036101000a031916815260200191505b509450505050506000604051808303816000876161da5a03f1505060408051868152905133600160a060020a031692507f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259181900360200190a35060015b9392505050565b61034c600435602435600160a060020a03808316600090815260016020908152604080832093851683529290522054610157565b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156106cd5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6060908152602090f35b820191906000526020600020905b8154815290600101906020018083116106f357829003601f168201915b505050505081565b610157565b6106325600000000000000000000000000000000000000000000000000000000000186a00000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000844616e6275636b7300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034442580000000000000000000000000000000000000000000000000000000000","gasPrice":"0xba43b7400","gas":"0xf4240","origin":"tokenfactory.surge.sh","metamaskId":1467742652846512,"metamaskNetworkId":"2"},"time":1467742652846,"status":"confirmed","hash":"0xa991793a6918aea6d58c30934dab5ca4c0a47c2444e5b60769637491f118de26"},{"id":1467755147235616,"txParams":{"from":"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825","data":"0x60a060405260046060527f48302e31000000000000000000000000000000000000000000000000000000006080526006805460008290527f48302e310000000000000000000000000000000000000000000000000000000882556100b5907ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f602060026001841615610100026000190190931692909204601f01919091048101905b8082111561017957600081556001016100a1565b505060405161099338038061099383398101604052808051906020019091908051820191906020018051906020019091908051820191906020015050836000600050600033600160a060020a0316815260200190815260200160002060005081905550836002600050819055508260036000509080519060200190828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061017d57805160ff19168380011785555b506101ad9291506100a1565b5090565b8280016001018555821561016d579182015b8281111561016d57825182600050559160200191906001019061018f565b50506004805460ff19168317905560058054825160008390527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db0602060026001851615610100026000190190941693909304601f90810184900482019386019083901061022d57805160ff19168380011785555b5061025d9291506100a1565b82800160010185558215610221579182015b8281111561022157825182600050559160200191906001019061023f565b505050505050610722806102716000396000f36060604052361561008d5760e060020a600035046306fdde038114610095578063095ea7b3146100f257806318160ddd1461015d57806323b872dd14610166578063313ce567146102c757806354fd4d50146102d357806370a082311461033057806395d89b411461035e578063a9059cbb146103bb578063cae9ca511461044d578063dd62ed3e14610639575b610000610002565b61066d60038054602060026001831615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156107105780601f106106e557610100808354040283529160200191610710565b61034c60043560243533600160a060020a03908116600081815260016020908152604080832094871680845294825282208590556060858152919392917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259190a35060015b92915050565b61034c60025481565b61034c600435602435604435600160a060020a0383166000908152602081905260408120548290108015906101b9575060016020908152604080832033600160a060020a03168452909152812054829010155b80156101c55750600082115b1561071d57816000600050600085600160a060020a03168152602001908152602001600020600082828250540192505081905550816000600050600086600160a060020a03168152602001908152602001600020600082828250540392505081905550816001600050600086600160a060020a03168152602001908152602001600020600050600033600160a060020a0316815260200190815260200160002060008282825054039250508190555082600160a060020a031684600160a060020a03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a3506001610632565b6106db60045460ff1681565b61066d60068054602060026001831615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156107105780601f106106e557610100808354040283529160200191610710565b600160a060020a03600435166000908152602081905260409020545b60408051918252519081900360200190f35b61066d60058054602060026001831615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156107105780601f106106e557610100808354040283529160200191610710565b61034c60043560243533600160a060020a03166000908152602081905260408120548290108015906103ed5750600082115b1561071857604080822080548490039055600160a060020a03808516808452918320805485019055606084815233909116907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602090a3506001610157565b60806020604435600481810135601f81018490049093028401604052606083815261034c94823594602480359560649493910191908190838280828437509496505050505050506000826001600050600033600160a060020a03168152602001908152602001600020600050600086600160a060020a031681526020019081526020016000206000508190555083600160a060020a031660405180807f72656365697665417070726f76616c28616464726573732c75696e743235362c81526020017f616464726573732c627974657329000000000000000000000000000000000000815260200150602e019050604051809103902060e060020a8091040260e060020a9004338530866040518560e060020a0281526004018085600160a060020a0316815260200184815260200183600160a060020a031681526020018280519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156105d45780820380516001836020036101000a031916815260200191505b509450505050506000604051808303816000876161da5a03f1505060408051868152905133600160a060020a031692507f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259181900360200190a35060015b9392505050565b61034c600435602435600160a060020a03808316600090815260016020908152604080832093851683529290522054610157565b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156106cd5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6060908152602090f35b820191906000526020600020905b8154815290600101906020018083116106f357829003601f168201915b505050505081565b610157565b6106325600000000000000000000000000000000000000000000000000000000000f42400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000844616e4275636b7300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034442580000000000000000000000000000000000000000000000000000000000","gasPrice":"0xba43b7400","gas":"0xf4240","origin":"tokenfactory.surge.sh","metamaskId":1467755147235616,"metamaskNetworkId":"1"},"time":1467755147235,"status":"unconfirmed"}],"selectedAddress":"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825","network":"1","seedWords":null,"isConfirmed":true,"unconfMsgs":{},"messages":[],"provider":{"type":"mainnet"},"selectedAccount":"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825"},"appState":{"menuOpen":false,"currentView":{"name":"confTx","context":0},"accountDetail":{"subview":"transactions"},"currentDomain":"127.0.0.1:9966","transForward":true,"isLoading":false,"warning":null},"identities":{}} +{"metamask":{"isInitialized":true,"isUnlocked":true,"currentDomain":"example.com","rpcTarget":"https://rawtestrpc.metamask.io/","identities":{"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825":{"name":"Wallet 1","address":"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825","mayBeFauceting":false},"0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb":{"name":"Wallet 2","address":"0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb","mayBeFauceting":false},"0x2f8d4a878cfa04a6e60d46362f5644deab66572d":{"name":"Wallet 3","address":"0x2f8d4a878cfa04a6e60d46362f5644deab66572d","mayBeFauceting":false}},"unconfTxs":{"1467755147235616":{"id":1467755147235616,"txParams":{"from":"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825","data":"0x60a060405260046060527f48302e31000000000000000000000000000000000000000000000000000000006080526006805460008290527f48302e310000000000000000000000000000000000000000000000000000000882556100b5907ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f602060026001841615610100026000190190931692909204601f01919091048101905b8082111561017957600081556001016100a1565b505060405161099338038061099383398101604052808051906020019091908051820191906020018051906020019091908051820191906020015050836000600050600033600160a060020a0316815260200190815260200160002060005081905550836002600050819055508260036000509080519060200190828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061017d57805160ff19168380011785555b506101ad9291506100a1565b5090565b8280016001018555821561016d579182015b8281111561016d57825182600050559160200191906001019061018f565b50506004805460ff19168317905560058054825160008390527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db0602060026001851615610100026000190190941693909304601f90810184900482019386019083901061022d57805160ff19168380011785555b5061025d9291506100a1565b82800160010185558215610221579182015b8281111561022157825182600050559160200191906001019061023f565b505050505050610722806102716000396000f36060604052361561008d5760e060020a600035046306fdde038114610095578063095ea7b3146100f257806318160ddd1461015d57806323b872dd14610166578063313ce567146102c757806354fd4d50146102d357806370a082311461033057806395d89b411461035e578063a9059cbb146103bb578063cae9ca511461044d578063dd62ed3e14610639575b610000610002565b61066d60038054602060026001831615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156107105780601f106106e557610100808354040283529160200191610710565b61034c60043560243533600160a060020a03908116600081815260016020908152604080832094871680845294825282208590556060858152919392917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259190a35060015b92915050565b61034c60025481565b61034c600435602435604435600160a060020a0383166000908152602081905260408120548290108015906101b9575060016020908152604080832033600160a060020a03168452909152812054829010155b80156101c55750600082115b1561071d57816000600050600085600160a060020a03168152602001908152602001600020600082828250540192505081905550816000600050600086600160a060020a03168152602001908152602001600020600082828250540392505081905550816001600050600086600160a060020a03168152602001908152602001600020600050600033600160a060020a0316815260200190815260200160002060008282825054039250508190555082600160a060020a031684600160a060020a03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a3506001610632565b6106db60045460ff1681565b61066d60068054602060026001831615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156107105780601f106106e557610100808354040283529160200191610710565b600160a060020a03600435166000908152602081905260409020545b60408051918252519081900360200190f35b61066d60058054602060026001831615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156107105780601f106106e557610100808354040283529160200191610710565b61034c60043560243533600160a060020a03166000908152602081905260408120548290108015906103ed5750600082115b1561071857604080822080548490039055600160a060020a03808516808452918320805485019055606084815233909116907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602090a3506001610157565b60806020604435600481810135601f81018490049093028401604052606083815261034c94823594602480359560649493910191908190838280828437509496505050505050506000826001600050600033600160a060020a03168152602001908152602001600020600050600086600160a060020a031681526020019081526020016000206000508190555083600160a060020a031660405180807f72656365697665417070726f76616c28616464726573732c75696e743235362c81526020017f616464726573732c627974657329000000000000000000000000000000000000815260200150602e019050604051809103902060e060020a8091040260e060020a9004338530866040518560e060020a0281526004018085600160a060020a0316815260200184815260200183600160a060020a031681526020018280519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156105d45780820380516001836020036101000a031916815260200191505b509450505050506000604051808303816000876161da5a03f1505060408051868152905133600160a060020a031692507f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259181900360200190a35060015b9392505050565b61034c600435602435600160a060020a03808316600090815260016020908152604080832093851683529290522054610157565b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156106cd5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6060908152602090f35b820191906000526020600020905b8154815290600101906020018083116106f357829003601f168201915b505050505081565b610157565b6106325600000000000000000000000000000000000000000000000000000000000f42400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000844616e4275636b7300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034442580000000000000000000000000000000000000000000000000000000000","gasPrice":"0xba43b7400","gas":"0xf4240","origin":"tokenfactory.surge.sh","metamaskId":1467755147235616,"metamaskNetworkId":"1"},"time":1467755147235,"status":"unconfirmed"}},"accounts":{"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825":{"code":"0x","balance":"0x1000000","nonce":"0x0","address":"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825"},"0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb":{"code":"0x","nonce":"0x0","balance":"0x1000000","address":"0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb"},"0x2f8d4a878cfa04a6e60d46362f5644deab66572d":{"code":"0x","balance":"0x1000000","nonce":"0x0","address":"0x2f8d4a878cfa04a6e60d46362f5644deab66572d"}},"transactions":[{"id":1467742640796159,"txParams":{"from":"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825","data":"0x60a060405260046060527f48302e31000000000000000000000000000000000000000000000000000000006080526006805460008290527f48302e310000000000000000000000000000000000000000000000000000000882556100b5907ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f602060026001841615610100026000190190931692909204601f01919091048101905b8082111561017957600081556001016100a1565b505060405161099338038061099383398101604052808051906020019091908051820191906020018051906020019091908051820191906020015050836000600050600033600160a060020a0316815260200190815260200160002060005081905550836002600050819055508260036000509080519060200190828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061017d57805160ff19168380011785555b506101ad9291506100a1565b5090565b8280016001018555821561016d579182015b8281111561016d57825182600050559160200191906001019061018f565b50506004805460ff19168317905560058054825160008390527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db0602060026001851615610100026000190190941693909304601f90810184900482019386019083901061022d57805160ff19168380011785555b5061025d9291506100a1565b82800160010185558215610221579182015b8281111561022157825182600050559160200191906001019061023f565b505050505050610722806102716000396000f36060604052361561008d5760e060020a600035046306fdde038114610095578063095ea7b3146100f257806318160ddd1461015d57806323b872dd14610166578063313ce567146102c757806354fd4d50146102d357806370a082311461033057806395d89b411461035e578063a9059cbb146103bb578063cae9ca511461044d578063dd62ed3e14610639575b610000610002565b61066d60038054602060026001831615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156107105780601f106106e557610100808354040283529160200191610710565b61034c60043560243533600160a060020a03908116600081815260016020908152604080832094871680845294825282208590556060858152919392917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259190a35060015b92915050565b61034c60025481565b61034c600435602435604435600160a060020a0383166000908152602081905260408120548290108015906101b9575060016020908152604080832033600160a060020a03168452909152812054829010155b80156101c55750600082115b1561071d57816000600050600085600160a060020a03168152602001908152602001600020600082828250540192505081905550816000600050600086600160a060020a03168152602001908152602001600020600082828250540392505081905550816001600050600086600160a060020a03168152602001908152602001600020600050600033600160a060020a0316815260200190815260200160002060008282825054039250508190555082600160a060020a031684600160a060020a03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a3506001610632565b6106db60045460ff1681565b61066d60068054602060026001831615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156107105780601f106106e557610100808354040283529160200191610710565b600160a060020a03600435166000908152602081905260409020545b60408051918252519081900360200190f35b61066d60058054602060026001831615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156107105780601f106106e557610100808354040283529160200191610710565b61034c60043560243533600160a060020a03166000908152602081905260408120548290108015906103ed5750600082115b1561071857604080822080548490039055600160a060020a03808516808452918320805485019055606084815233909116907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602090a3506001610157565b60806020604435600481810135601f81018490049093028401604052606083815261034c94823594602480359560649493910191908190838280828437509496505050505050506000826001600050600033600160a060020a03168152602001908152602001600020600050600086600160a060020a031681526020019081526020016000206000508190555083600160a060020a031660405180807f72656365697665417070726f76616c28616464726573732c75696e743235362c81526020017f616464726573732c627974657329000000000000000000000000000000000000815260200150602e019050604051809103902060e060020a8091040260e060020a9004338530866040518560e060020a0281526004018085600160a060020a0316815260200184815260200183600160a060020a031681526020018280519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156105d45780820380516001836020036101000a031916815260200191505b509450505050506000604051808303816000876161da5a03f1505060408051868152905133600160a060020a031692507f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259181900360200190a35060015b9392505050565b61034c600435602435600160a060020a03808316600090815260016020908152604080832093851683529290522054610157565b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156106cd5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6060908152602090f35b820191906000526020600020905b8154815290600101906020018083116106f357829003601f168201915b505050505081565b610157565b6106325600000000000000000000000000000000000000000000000000000000000186a00000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000844616e6275636b7300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034442580000000000000000000000000000000000000000000000000000000000","gasPrice":"0xba43b7400","gas":"0xf4240","origin":"tokenfactory.surge.sh","metamaskId":1467742640796159,"metamaskNetworkId":"2"},"time":1467742640796,"status":"rejected"},{"id":1467742652846512,"txParams":{"from":"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825","data":"0x60a060405260046060527f48302e31000000000000000000000000000000000000000000000000000000006080526006805460008290527f48302e310000000000000000000000000000000000000000000000000000000882556100b5907ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f602060026001841615610100026000190190931692909204601f01919091048101905b8082111561017957600081556001016100a1565b505060405161099338038061099383398101604052808051906020019091908051820191906020018051906020019091908051820191906020015050836000600050600033600160a060020a0316815260200190815260200160002060005081905550836002600050819055508260036000509080519060200190828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061017d57805160ff19168380011785555b506101ad9291506100a1565b5090565b8280016001018555821561016d579182015b8281111561016d57825182600050559160200191906001019061018f565b50506004805460ff19168317905560058054825160008390527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db0602060026001851615610100026000190190941693909304601f90810184900482019386019083901061022d57805160ff19168380011785555b5061025d9291506100a1565b82800160010185558215610221579182015b8281111561022157825182600050559160200191906001019061023f565b505050505050610722806102716000396000f36060604052361561008d5760e060020a600035046306fdde038114610095578063095ea7b3146100f257806318160ddd1461015d57806323b872dd14610166578063313ce567146102c757806354fd4d50146102d357806370a082311461033057806395d89b411461035e578063a9059cbb146103bb578063cae9ca511461044d578063dd62ed3e14610639575b610000610002565b61066d60038054602060026001831615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156107105780601f106106e557610100808354040283529160200191610710565b61034c60043560243533600160a060020a03908116600081815260016020908152604080832094871680845294825282208590556060858152919392917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259190a35060015b92915050565b61034c60025481565b61034c600435602435604435600160a060020a0383166000908152602081905260408120548290108015906101b9575060016020908152604080832033600160a060020a03168452909152812054829010155b80156101c55750600082115b1561071d57816000600050600085600160a060020a03168152602001908152602001600020600082828250540192505081905550816000600050600086600160a060020a03168152602001908152602001600020600082828250540392505081905550816001600050600086600160a060020a03168152602001908152602001600020600050600033600160a060020a0316815260200190815260200160002060008282825054039250508190555082600160a060020a031684600160a060020a03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a3506001610632565b6106db60045460ff1681565b61066d60068054602060026001831615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156107105780601f106106e557610100808354040283529160200191610710565b600160a060020a03600435166000908152602081905260409020545b60408051918252519081900360200190f35b61066d60058054602060026001831615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156107105780601f106106e557610100808354040283529160200191610710565b61034c60043560243533600160a060020a03166000908152602081905260408120548290108015906103ed5750600082115b1561071857604080822080548490039055600160a060020a03808516808452918320805485019055606084815233909116907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602090a3506001610157565b60806020604435600481810135601f81018490049093028401604052606083815261034c94823594602480359560649493910191908190838280828437509496505050505050506000826001600050600033600160a060020a03168152602001908152602001600020600050600086600160a060020a031681526020019081526020016000206000508190555083600160a060020a031660405180807f72656365697665417070726f76616c28616464726573732c75696e743235362c81526020017f616464726573732c627974657329000000000000000000000000000000000000815260200150602e019050604051809103902060e060020a8091040260e060020a9004338530866040518560e060020a0281526004018085600160a060020a0316815260200184815260200183600160a060020a031681526020018280519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156105d45780820380516001836020036101000a031916815260200191505b509450505050506000604051808303816000876161da5a03f1505060408051868152905133600160a060020a031692507f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259181900360200190a35060015b9392505050565b61034c600435602435600160a060020a03808316600090815260016020908152604080832093851683529290522054610157565b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156106cd5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6060908152602090f35b820191906000526020600020905b8154815290600101906020018083116106f357829003601f168201915b505050505081565b610157565b6106325600000000000000000000000000000000000000000000000000000000000186a00000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000844616e6275636b7300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034442580000000000000000000000000000000000000000000000000000000000","gasPrice":"0xba43b7400","gas":"0xf4240","origin":"tokenfactory.surge.sh","metamaskId":1467742652846512,"metamaskNetworkId":"2"},"time":1467742652846,"status":"confirmed","hash":"0xa991793a6918aea6d58c30934dab5ca4c0a47c2444e5b60769637491f118de26"},{"id":1467755147235616,"txParams":{"from":"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825","data":"0x60a060405260046060527f48302e31000000000000000000000000000000000000000000000000000000006080526006805460008290527f48302e310000000000000000000000000000000000000000000000000000000882556100b5907ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f602060026001841615610100026000190190931692909204601f01919091048101905b8082111561017957600081556001016100a1565b505060405161099338038061099383398101604052808051906020019091908051820191906020018051906020019091908051820191906020015050836000600050600033600160a060020a0316815260200190815260200160002060005081905550836002600050819055508260036000509080519060200190828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061017d57805160ff19168380011785555b506101ad9291506100a1565b5090565b8280016001018555821561016d579182015b8281111561016d57825182600050559160200191906001019061018f565b50506004805460ff19168317905560058054825160008390527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db0602060026001851615610100026000190190941693909304601f90810184900482019386019083901061022d57805160ff19168380011785555b5061025d9291506100a1565b82800160010185558215610221579182015b8281111561022157825182600050559160200191906001019061023f565b505050505050610722806102716000396000f36060604052361561008d5760e060020a600035046306fdde038114610095578063095ea7b3146100f257806318160ddd1461015d57806323b872dd14610166578063313ce567146102c757806354fd4d50146102d357806370a082311461033057806395d89b411461035e578063a9059cbb146103bb578063cae9ca511461044d578063dd62ed3e14610639575b610000610002565b61066d60038054602060026001831615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156107105780601f106106e557610100808354040283529160200191610710565b61034c60043560243533600160a060020a03908116600081815260016020908152604080832094871680845294825282208590556060858152919392917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259190a35060015b92915050565b61034c60025481565b61034c600435602435604435600160a060020a0383166000908152602081905260408120548290108015906101b9575060016020908152604080832033600160a060020a03168452909152812054829010155b80156101c55750600082115b1561071d57816000600050600085600160a060020a03168152602001908152602001600020600082828250540192505081905550816000600050600086600160a060020a03168152602001908152602001600020600082828250540392505081905550816001600050600086600160a060020a03168152602001908152602001600020600050600033600160a060020a0316815260200190815260200160002060008282825054039250508190555082600160a060020a031684600160a060020a03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a3506001610632565b6106db60045460ff1681565b61066d60068054602060026001831615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156107105780601f106106e557610100808354040283529160200191610710565b600160a060020a03600435166000908152602081905260409020545b60408051918252519081900360200190f35b61066d60058054602060026001831615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156107105780601f106106e557610100808354040283529160200191610710565b61034c60043560243533600160a060020a03166000908152602081905260408120548290108015906103ed5750600082115b1561071857604080822080548490039055600160a060020a03808516808452918320805485019055606084815233909116907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602090a3506001610157565b60806020604435600481810135601f81018490049093028401604052606083815261034c94823594602480359560649493910191908190838280828437509496505050505050506000826001600050600033600160a060020a03168152602001908152602001600020600050600086600160a060020a031681526020019081526020016000206000508190555083600160a060020a031660405180807f72656365697665417070726f76616c28616464726573732c75696e743235362c81526020017f616464726573732c627974657329000000000000000000000000000000000000815260200150602e019050604051809103902060e060020a8091040260e060020a9004338530866040518560e060020a0281526004018085600160a060020a0316815260200184815260200183600160a060020a031681526020018280519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156105d45780820380516001836020036101000a031916815260200191505b509450505050506000604051808303816000876161da5a03f1505060408051868152905133600160a060020a031692507f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259181900360200190a35060015b9392505050565b61034c600435602435600160a060020a03808316600090815260016020908152604080832093851683529290522054610157565b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156106cd5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6060908152602090f35b820191906000526020600020905b8154815290600101906020018083116106f357829003601f168201915b505050505081565b610157565b6106325600000000000000000000000000000000000000000000000000000000000f42400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000844616e4275636b7300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034442580000000000000000000000000000000000000000000000000000000000","gasPrice":"0xba43b7400","gas":"0xf4240","origin":"tokenfactory.surge.sh","metamaskId":1467755147235616,"metamaskNetworkId":"1"},"time":1467755147235,"status":"unconfirmed"}],"selectedAccount":"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825","network":"1","seedWords":null,"isDisclaimerConfirmed":true,"unconfMsgs":{},"messages":[],"provider":{"type":"mainnet"},"selectedAccount":"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825"},"appState":{"menuOpen":false,"currentView":{"name":"confTx","context":0},"accountDetail":{"subview":"transactions"},"currentDomain":"127.0.0.1:9966","transForward":true,"isLoading":false,"warning":null},"identities":{}} diff --git a/development/states/pending-tx-send-coin.json b/development/states/pending-tx-send-coin.json index 262d791bb..6d447996a 100644 --- a/development/states/pending-tx-send-coin.json +++ b/development/states/pending-tx-send-coin.json @@ -1 +1 @@ -{"metamask":{"isInitialized":true,"isUnlocked":true,"currentDomain":"example.com","rpcTarget":"https://rawtestrpc.metamask.io/","identities":{"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825":{"name":"Wallet 1","address":"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825","mayBeFauceting":false},"0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb":{"name":"Wallet 2","address":"0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb","mayBeFauceting":false},"0x2f8d4a878cfa04a6e60d46362f5644deab66572d":{"name":"Wallet 3","address":"0x2f8d4a878cfa04a6e60d46362f5644deab66572d","mayBeFauceting":false}},"unconfTxs":{"1467868023090690":{"id":1467868023090690,"txParams":{"data":"0xa9059cbb0000000000000000000000008deb4d106090c3eb8f1950f727e87c4f884fb06f0000000000000000000000000000000000000000000000000000000000000064","from":"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825","value":"0x16345785d8a0000","to":"0xbeb0ed3034c4155f3d16a64a5c5e7c8d4ea9e9c9","origin":"MetaMask","metamaskId":1467868023090690,"metamaskNetworkId":"2"},"time":1467868023090,"status":"unconfirmed","containsDelegateCall":false}},"accounts":{"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825":{"code":"0x","balance":"0x38326dc32cf80800","nonce":"0x10000c","address":"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825"},"0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb":{"code":"0x","balance":"0x15e578bd8e9c8000","nonce":"0x100000","address":"0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb"},"0x2f8d4a878cfa04a6e60d46362f5644deab66572d":{"code":"0x","nonce":"0x100000","balance":"0x2386f26fc10000","address":"0x2f8d4a878cfa04a6e60d46362f5644deab66572d"}},"transactions":[],"selectedAddress":"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825","network":"2","seedWords":null,"isConfirmed":true,"unconfMsgs":{},"messages":[],"provider":{"type":"testnet"},"selectedAccount":"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825"},"appState":{"menuOpen":false,"currentView":{"name":"confTx","context":0},"accountDetail":{"subview":"transactions"},"currentDomain":"extensions","transForward":true,"isLoading":false,"warning":null},"identities":{}} +{"metamask":{"isInitialized":true,"isUnlocked":true,"currentDomain":"example.com","rpcTarget":"https://rawtestrpc.metamask.io/","identities":{"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825":{"name":"Wallet 1","address":"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825","mayBeFauceting":false},"0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb":{"name":"Wallet 2","address":"0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb","mayBeFauceting":false},"0x2f8d4a878cfa04a6e60d46362f5644deab66572d":{"name":"Wallet 3","address":"0x2f8d4a878cfa04a6e60d46362f5644deab66572d","mayBeFauceting":false}},"unconfTxs":{"1467868023090690":{"id":1467868023090690,"txParams":{"data":"0xa9059cbb0000000000000000000000008deb4d106090c3eb8f1950f727e87c4f884fb06f0000000000000000000000000000000000000000000000000000000000000064","from":"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825","value":"0x16345785d8a0000","to":"0xbeb0ed3034c4155f3d16a64a5c5e7c8d4ea9e9c9","origin":"MetaMask","metamaskId":1467868023090690,"metamaskNetworkId":"2"},"time":1467868023090,"status":"unconfirmed","containsDelegateCall":false}},"accounts":{"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825":{"code":"0x","balance":"0x38326dc32cf80800","nonce":"0x10000c","address":"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825"},"0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb":{"code":"0x","balance":"0x15e578bd8e9c8000","nonce":"0x100000","address":"0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb"},"0x2f8d4a878cfa04a6e60d46362f5644deab66572d":{"code":"0x","nonce":"0x100000","balance":"0x2386f26fc10000","address":"0x2f8d4a878cfa04a6e60d46362f5644deab66572d"}},"transactions":[],"selectedAccount":"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825","network":"2","seedWords":null,"isDisclaimerConfirmed":true,"unconfMsgs":{},"messages":[],"provider":{"type":"testnet"},"selectedAccount":"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825"},"appState":{"menuOpen":false,"currentView":{"name":"confTx","context":0},"accountDetail":{"subview":"transactions"},"currentDomain":"extensions","transForward":true,"isLoading":false,"warning":null},"identities":{}} diff --git a/development/states/pending-tx-value.json b/development/states/pending-tx-value.json index 61fe7fa34..8bbf14b4b 100644 --- a/development/states/pending-tx-value.json +++ b/development/states/pending-tx-value.json @@ -1 +1 @@ -{"metamask":{"isInitialized":true,"isUnlocked":true,"currentDomain":"example.com","rpcTarget":"https://rawtestrpc.metamask.io/","identities":{"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825":{"name":"Wallet 1","address":"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825","mayBeFauceting":false},"0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb":{"name":"Wallet 2","address":"0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb","mayBeFauceting":false},"0x2f8d4a878cfa04a6e60d46362f5644deab66572d":{"name":"Wallet 3","address":"0x2f8d4a878cfa04a6e60d46362f5644deab66572d","mayBeFauceting":false}},"unconfTxs":{"1467868023090690":{"id":1467868023090690,"txParams":{"from":"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825","value":"0x16345785d8a0000","to":"0xC5b8dBAc4c1d3F152cDeb400E2313F309c410aCb","origin":"MetaMask","metamaskId":1467868023090690,"metamaskNetworkId":"2"},"time":1467868023090,"status":"unconfirmed","containsDelegateCall":false}},"accounts":{"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825":{"code":"0x","balance":"0x38326dc32cf80800","nonce":"0x10000c","address":"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825"},"0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb":{"code":"0x","balance":"0x15e578bd8e9c8000","nonce":"0x100000","address":"0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb"},"0x2f8d4a878cfa04a6e60d46362f5644deab66572d":{"code":"0x","nonce":"0x100000","balance":"0x2386f26fc10000","address":"0x2f8d4a878cfa04a6e60d46362f5644deab66572d"}},"transactions":[{"id":1467742640796159,"txParams":{"from":"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825","data":"0x60a060405260046060527f48302e31000000000000000000000000000000000000000000000000000000006080526006805460008290527f48302e310000000000000000000000000000000000000000000000000000000882556100b5907ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f602060026001841615610100026000190190931692909204601f01919091048101905b8082111561017957600081556001016100a1565b505060405161099338038061099383398101604052808051906020019091908051820191906020018051906020019091908051820191906020015050836000600050600033600160a060020a0316815260200190815260200160002060005081905550836002600050819055508260036000509080519060200190828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061017d57805160ff19168380011785555b506101ad9291506100a1565b5090565b8280016001018555821561016d579182015b8281111561016d57825182600050559160200191906001019061018f565b50506004805460ff19168317905560058054825160008390527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db0602060026001851615610100026000190190941693909304601f90810184900482019386019083901061022d57805160ff19168380011785555b5061025d9291506100a1565b82800160010185558215610221579182015b8281111561022157825182600050559160200191906001019061023f565b505050505050610722806102716000396000f36060604052361561008d5760e060020a600035046306fdde038114610095578063095ea7b3146100f257806318160ddd1461015d57806323b872dd14610166578063313ce567146102c757806354fd4d50146102d357806370a082311461033057806395d89b411461035e578063a9059cbb146103bb578063cae9ca511461044d578063dd62ed3e14610639575b610000610002565b61066d60038054602060026001831615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156107105780601f106106e557610100808354040283529160200191610710565b61034c60043560243533600160a060020a03908116600081815260016020908152604080832094871680845294825282208590556060858152919392917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259190a35060015b92915050565b61034c60025481565b61034c600435602435604435600160a060020a0383166000908152602081905260408120548290108015906101b9575060016020908152604080832033600160a060020a03168452909152812054829010155b80156101c55750600082115b1561071d57816000600050600085600160a060020a03168152602001908152602001600020600082828250540192505081905550816000600050600086600160a060020a03168152602001908152602001600020600082828250540392505081905550816001600050600086600160a060020a03168152602001908152602001600020600050600033600160a060020a0316815260200190815260200160002060008282825054039250508190555082600160a060020a031684600160a060020a03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a3506001610632565b6106db60045460ff1681565b61066d60068054602060026001831615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156107105780601f106106e557610100808354040283529160200191610710565b600160a060020a03600435166000908152602081905260409020545b60408051918252519081900360200190f35b61066d60058054602060026001831615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156107105780601f106106e557610100808354040283529160200191610710565b61034c60043560243533600160a060020a03166000908152602081905260408120548290108015906103ed5750600082115b1561071857604080822080548490039055600160a060020a03808516808452918320805485019055606084815233909116907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602090a3506001610157565b60806020604435600481810135601f81018490049093028401604052606083815261034c94823594602480359560649493910191908190838280828437509496505050505050506000826001600050600033600160a060020a03168152602001908152602001600020600050600086600160a060020a031681526020019081526020016000206000508190555083600160a060020a031660405180807f72656365697665417070726f76616c28616464726573732c75696e743235362c81526020017f616464726573732c627974657329000000000000000000000000000000000000815260200150602e019050604051809103902060e060020a8091040260e060020a9004338530866040518560e060020a0281526004018085600160a060020a0316815260200184815260200183600160a060020a031681526020018280519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156105d45780820380516001836020036101000a031916815260200191505b509450505050506000604051808303816000876161da5a03f1505060408051868152905133600160a060020a031692507f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259181900360200190a35060015b9392505050565b61034c600435602435600160a060020a03808316600090815260016020908152604080832093851683529290522054610157565b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156106cd5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6060908152602090f35b820191906000526020600020905b8154815290600101906020018083116106f357829003601f168201915b505050505081565b610157565b6106325600000000000000000000000000000000000000000000000000000000000186a00000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000844616e6275636b7300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034442580000000000000000000000000000000000000000000000000000000000","gasPrice":"0xba43b7400","gas":"0xf4240","origin":"tokenfactory.surge.sh","metamaskId":1467742640796159,"metamaskNetworkId":"2"},"time":1467742640796,"status":"rejected"},{"id":1467742652846512,"txParams":{"from":"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825","data":"0x60a060405260046060527f48302e31000000000000000000000000000000000000000000000000000000006080526006805460008290527f48302e310000000000000000000000000000000000000000000000000000000882556100b5907ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f602060026001841615610100026000190190931692909204601f01919091048101905b8082111561017957600081556001016100a1565b505060405161099338038061099383398101604052808051906020019091908051820191906020018051906020019091908051820191906020015050836000600050600033600160a060020a0316815260200190815260200160002060005081905550836002600050819055508260036000509080519060200190828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061017d57805160ff19168380011785555b506101ad9291506100a1565b5090565b8280016001018555821561016d579182015b8281111561016d57825182600050559160200191906001019061018f565b50506004805460ff19168317905560058054825160008390527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db0602060026001851615610100026000190190941693909304601f90810184900482019386019083901061022d57805160ff19168380011785555b5061025d9291506100a1565b82800160010185558215610221579182015b8281111561022157825182600050559160200191906001019061023f565b505050505050610722806102716000396000f36060604052361561008d5760e060020a600035046306fdde038114610095578063095ea7b3146100f257806318160ddd1461015d57806323b872dd14610166578063313ce567146102c757806354fd4d50146102d357806370a082311461033057806395d89b411461035e578063a9059cbb146103bb578063cae9ca511461044d578063dd62ed3e14610639575b610000610002565b61066d60038054602060026001831615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156107105780601f106106e557610100808354040283529160200191610710565b61034c60043560243533600160a060020a03908116600081815260016020908152604080832094871680845294825282208590556060858152919392917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259190a35060015b92915050565b61034c60025481565b61034c600435602435604435600160a060020a0383166000908152602081905260408120548290108015906101b9575060016020908152604080832033600160a060020a03168452909152812054829010155b80156101c55750600082115b1561071d57816000600050600085600160a060020a03168152602001908152602001600020600082828250540192505081905550816000600050600086600160a060020a03168152602001908152602001600020600082828250540392505081905550816001600050600086600160a060020a03168152602001908152602001600020600050600033600160a060020a0316815260200190815260200160002060008282825054039250508190555082600160a060020a031684600160a060020a03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a3506001610632565b6106db60045460ff1681565b61066d60068054602060026001831615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156107105780601f106106e557610100808354040283529160200191610710565b600160a060020a03600435166000908152602081905260409020545b60408051918252519081900360200190f35b61066d60058054602060026001831615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156107105780601f106106e557610100808354040283529160200191610710565b61034c60043560243533600160a060020a03166000908152602081905260408120548290108015906103ed5750600082115b1561071857604080822080548490039055600160a060020a03808516808452918320805485019055606084815233909116907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602090a3506001610157565b60806020604435600481810135601f81018490049093028401604052606083815261034c94823594602480359560649493910191908190838280828437509496505050505050506000826001600050600033600160a060020a03168152602001908152602001600020600050600086600160a060020a031681526020019081526020016000206000508190555083600160a060020a031660405180807f72656365697665417070726f76616c28616464726573732c75696e743235362c81526020017f616464726573732c627974657329000000000000000000000000000000000000815260200150602e019050604051809103902060e060020a8091040260e060020a9004338530866040518560e060020a0281526004018085600160a060020a0316815260200184815260200183600160a060020a031681526020018280519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156105d45780820380516001836020036101000a031916815260200191505b509450505050506000604051808303816000876161da5a03f1505060408051868152905133600160a060020a031692507f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259181900360200190a35060015b9392505050565b61034c600435602435600160a060020a03808316600090815260016020908152604080832093851683529290522054610157565b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156106cd5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6060908152602090f35b820191906000526020600020905b8154815290600101906020018083116106f357829003601f168201915b505050505081565b610157565b6106325600000000000000000000000000000000000000000000000000000000000186a00000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000844616e6275636b7300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034442580000000000000000000000000000000000000000000000000000000000","gasPrice":"0xba43b7400","gas":"0xf4240","origin":"tokenfactory.surge.sh","metamaskId":1467742652846512,"metamaskNetworkId":"2"},"time":1467742652846,"status":"confirmed","hash":"0xa991793a6918aea6d58c30934dab5ca4c0a47c2444e5b60769637491f118de26"},{"id":1467755147235616,"txParams":{"from":"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825","data":"0x60a060405260046060527f48302e31000000000000000000000000000000000000000000000000000000006080526006805460008290527f48302e310000000000000000000000000000000000000000000000000000000882556100b5907ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f602060026001841615610100026000190190931692909204601f01919091048101905b8082111561017957600081556001016100a1565b505060405161099338038061099383398101604052808051906020019091908051820191906020018051906020019091908051820191906020015050836000600050600033600160a060020a0316815260200190815260200160002060005081905550836002600050819055508260036000509080519060200190828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061017d57805160ff19168380011785555b506101ad9291506100a1565b5090565b8280016001018555821561016d579182015b8281111561016d57825182600050559160200191906001019061018f565b50506004805460ff19168317905560058054825160008390527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db0602060026001851615610100026000190190941693909304601f90810184900482019386019083901061022d57805160ff19168380011785555b5061025d9291506100a1565b82800160010185558215610221579182015b8281111561022157825182600050559160200191906001019061023f565b505050505050610722806102716000396000f36060604052361561008d5760e060020a600035046306fdde038114610095578063095ea7b3146100f257806318160ddd1461015d57806323b872dd14610166578063313ce567146102c757806354fd4d50146102d357806370a082311461033057806395d89b411461035e578063a9059cbb146103bb578063cae9ca511461044d578063dd62ed3e14610639575b610000610002565b61066d60038054602060026001831615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156107105780601f106106e557610100808354040283529160200191610710565b61034c60043560243533600160a060020a03908116600081815260016020908152604080832094871680845294825282208590556060858152919392917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259190a35060015b92915050565b61034c60025481565b61034c600435602435604435600160a060020a0383166000908152602081905260408120548290108015906101b9575060016020908152604080832033600160a060020a03168452909152812054829010155b80156101c55750600082115b1561071d57816000600050600085600160a060020a03168152602001908152602001600020600082828250540192505081905550816000600050600086600160a060020a03168152602001908152602001600020600082828250540392505081905550816001600050600086600160a060020a03168152602001908152602001600020600050600033600160a060020a0316815260200190815260200160002060008282825054039250508190555082600160a060020a031684600160a060020a03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a3506001610632565b6106db60045460ff1681565b61066d60068054602060026001831615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156107105780601f106106e557610100808354040283529160200191610710565b600160a060020a03600435166000908152602081905260409020545b60408051918252519081900360200190f35b61066d60058054602060026001831615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156107105780601f106106e557610100808354040283529160200191610710565b61034c60043560243533600160a060020a03166000908152602081905260408120548290108015906103ed5750600082115b1561071857604080822080548490039055600160a060020a03808516808452918320805485019055606084815233909116907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602090a3506001610157565b60806020604435600481810135601f81018490049093028401604052606083815261034c94823594602480359560649493910191908190838280828437509496505050505050506000826001600050600033600160a060020a03168152602001908152602001600020600050600086600160a060020a031681526020019081526020016000206000508190555083600160a060020a031660405180807f72656365697665417070726f76616c28616464726573732c75696e743235362c81526020017f616464726573732c627974657329000000000000000000000000000000000000815260200150602e019050604051809103902060e060020a8091040260e060020a9004338530866040518560e060020a0281526004018085600160a060020a0316815260200184815260200183600160a060020a031681526020018280519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156105d45780820380516001836020036101000a031916815260200191505b509450505050506000604051808303816000876161da5a03f1505060408051868152905133600160a060020a031692507f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259181900360200190a35060015b9392505050565b61034c600435602435600160a060020a03808316600090815260016020908152604080832093851683529290522054610157565b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156106cd5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6060908152602090f35b820191906000526020600020905b8154815290600101906020018083116106f357829003601f168201915b505050505081565b610157565b6106325600000000000000000000000000000000000000000000000000000000000f42400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000844616e4275636b7300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034442580000000000000000000000000000000000000000000000000000000000","gasPrice":"0xba43b7400","gas":"0xf4240","origin":"tokenfactory.surge.sh","metamaskId":1467755147235616,"metamaskNetworkId":"1"},"time":1467755147235,"status":"rejected"},{"id":1467868023090690,"txParams":{"from":"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825","value":"0x16345785d8a0000","to":"0xC5b8dBAc4c1d3F152cDeb400E2313F309c410aCb","origin":"MetaMask","metamaskId":1467868023090690,"metamaskNetworkId":"2"},"time":1467868023090,"status":"unconfirmed","containsDelegateCall":false}],"selectedAddress":"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825","network":"2","seedWords":null,"isConfirmed":true,"unconfMsgs":{},"messages":[],"provider":{"type":"testnet"},"selectedAccount":"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825"},"appState":{"menuOpen":false,"currentView":{"name":"confTx","context":0},"accountDetail":{"subview":"transactions"},"currentDomain":"extensions","transForward":true,"isLoading":false,"warning":null},"identities":{}}
\ No newline at end of file +{"metamask":{"isInitialized":true,"isUnlocked":true,"currentDomain":"example.com","rpcTarget":"https://rawtestrpc.metamask.io/","identities":{"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825":{"name":"Wallet 1","address":"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825","mayBeFauceting":false},"0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb":{"name":"Wallet 2","address":"0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb","mayBeFauceting":false},"0x2f8d4a878cfa04a6e60d46362f5644deab66572d":{"name":"Wallet 3","address":"0x2f8d4a878cfa04a6e60d46362f5644deab66572d","mayBeFauceting":false}},"unconfTxs":{"1467868023090690":{"id":1467868023090690,"txParams":{"from":"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825","value":"0x16345785d8a0000","to":"0xC5b8dBAc4c1d3F152cDeb400E2313F309c410aCb","origin":"MetaMask","metamaskId":1467868023090690,"metamaskNetworkId":"2"},"time":1467868023090,"status":"unconfirmed","containsDelegateCall":false}},"accounts":{"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825":{"code":"0x","balance":"0x38326dc32cf80800","nonce":"0x10000c","address":"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825"},"0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb":{"code":"0x","balance":"0x15e578bd8e9c8000","nonce":"0x100000","address":"0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb"},"0x2f8d4a878cfa04a6e60d46362f5644deab66572d":{"code":"0x","nonce":"0x100000","balance":"0x2386f26fc10000","address":"0x2f8d4a878cfa04a6e60d46362f5644deab66572d"}},"transactions":[{"id":1467742640796159,"txParams":{"from":"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825","data":"0x60a060405260046060527f48302e31000000000000000000000000000000000000000000000000000000006080526006805460008290527f48302e310000000000000000000000000000000000000000000000000000000882556100b5907ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f602060026001841615610100026000190190931692909204601f01919091048101905b8082111561017957600081556001016100a1565b505060405161099338038061099383398101604052808051906020019091908051820191906020018051906020019091908051820191906020015050836000600050600033600160a060020a0316815260200190815260200160002060005081905550836002600050819055508260036000509080519060200190828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061017d57805160ff19168380011785555b506101ad9291506100a1565b5090565b8280016001018555821561016d579182015b8281111561016d57825182600050559160200191906001019061018f565b50506004805460ff19168317905560058054825160008390527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db0602060026001851615610100026000190190941693909304601f90810184900482019386019083901061022d57805160ff19168380011785555b5061025d9291506100a1565b82800160010185558215610221579182015b8281111561022157825182600050559160200191906001019061023f565b505050505050610722806102716000396000f36060604052361561008d5760e060020a600035046306fdde038114610095578063095ea7b3146100f257806318160ddd1461015d57806323b872dd14610166578063313ce567146102c757806354fd4d50146102d357806370a082311461033057806395d89b411461035e578063a9059cbb146103bb578063cae9ca511461044d578063dd62ed3e14610639575b610000610002565b61066d60038054602060026001831615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156107105780601f106106e557610100808354040283529160200191610710565b61034c60043560243533600160a060020a03908116600081815260016020908152604080832094871680845294825282208590556060858152919392917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259190a35060015b92915050565b61034c60025481565b61034c600435602435604435600160a060020a0383166000908152602081905260408120548290108015906101b9575060016020908152604080832033600160a060020a03168452909152812054829010155b80156101c55750600082115b1561071d57816000600050600085600160a060020a03168152602001908152602001600020600082828250540192505081905550816000600050600086600160a060020a03168152602001908152602001600020600082828250540392505081905550816001600050600086600160a060020a03168152602001908152602001600020600050600033600160a060020a0316815260200190815260200160002060008282825054039250508190555082600160a060020a031684600160a060020a03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a3506001610632565b6106db60045460ff1681565b61066d60068054602060026001831615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156107105780601f106106e557610100808354040283529160200191610710565b600160a060020a03600435166000908152602081905260409020545b60408051918252519081900360200190f35b61066d60058054602060026001831615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156107105780601f106106e557610100808354040283529160200191610710565b61034c60043560243533600160a060020a03166000908152602081905260408120548290108015906103ed5750600082115b1561071857604080822080548490039055600160a060020a03808516808452918320805485019055606084815233909116907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602090a3506001610157565b60806020604435600481810135601f81018490049093028401604052606083815261034c94823594602480359560649493910191908190838280828437509496505050505050506000826001600050600033600160a060020a03168152602001908152602001600020600050600086600160a060020a031681526020019081526020016000206000508190555083600160a060020a031660405180807f72656365697665417070726f76616c28616464726573732c75696e743235362c81526020017f616464726573732c627974657329000000000000000000000000000000000000815260200150602e019050604051809103902060e060020a8091040260e060020a9004338530866040518560e060020a0281526004018085600160a060020a0316815260200184815260200183600160a060020a031681526020018280519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156105d45780820380516001836020036101000a031916815260200191505b509450505050506000604051808303816000876161da5a03f1505060408051868152905133600160a060020a031692507f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259181900360200190a35060015b9392505050565b61034c600435602435600160a060020a03808316600090815260016020908152604080832093851683529290522054610157565b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156106cd5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6060908152602090f35b820191906000526020600020905b8154815290600101906020018083116106f357829003601f168201915b505050505081565b610157565b6106325600000000000000000000000000000000000000000000000000000000000186a00000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000844616e6275636b7300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034442580000000000000000000000000000000000000000000000000000000000","gasPrice":"0xba43b7400","gas":"0xf4240","origin":"tokenfactory.surge.sh","metamaskId":1467742640796159,"metamaskNetworkId":"2"},"time":1467742640796,"status":"rejected"},{"id":1467742652846512,"txParams":{"from":"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825","data":"0x60a060405260046060527f48302e31000000000000000000000000000000000000000000000000000000006080526006805460008290527f48302e310000000000000000000000000000000000000000000000000000000882556100b5907ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f602060026001841615610100026000190190931692909204601f01919091048101905b8082111561017957600081556001016100a1565b505060405161099338038061099383398101604052808051906020019091908051820191906020018051906020019091908051820191906020015050836000600050600033600160a060020a0316815260200190815260200160002060005081905550836002600050819055508260036000509080519060200190828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061017d57805160ff19168380011785555b506101ad9291506100a1565b5090565b8280016001018555821561016d579182015b8281111561016d57825182600050559160200191906001019061018f565b50506004805460ff19168317905560058054825160008390527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db0602060026001851615610100026000190190941693909304601f90810184900482019386019083901061022d57805160ff19168380011785555b5061025d9291506100a1565b82800160010185558215610221579182015b8281111561022157825182600050559160200191906001019061023f565b505050505050610722806102716000396000f36060604052361561008d5760e060020a600035046306fdde038114610095578063095ea7b3146100f257806318160ddd1461015d57806323b872dd14610166578063313ce567146102c757806354fd4d50146102d357806370a082311461033057806395d89b411461035e578063a9059cbb146103bb578063cae9ca511461044d578063dd62ed3e14610639575b610000610002565b61066d60038054602060026001831615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156107105780601f106106e557610100808354040283529160200191610710565b61034c60043560243533600160a060020a03908116600081815260016020908152604080832094871680845294825282208590556060858152919392917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259190a35060015b92915050565b61034c60025481565b61034c600435602435604435600160a060020a0383166000908152602081905260408120548290108015906101b9575060016020908152604080832033600160a060020a03168452909152812054829010155b80156101c55750600082115b1561071d57816000600050600085600160a060020a03168152602001908152602001600020600082828250540192505081905550816000600050600086600160a060020a03168152602001908152602001600020600082828250540392505081905550816001600050600086600160a060020a03168152602001908152602001600020600050600033600160a060020a0316815260200190815260200160002060008282825054039250508190555082600160a060020a031684600160a060020a03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a3506001610632565b6106db60045460ff1681565b61066d60068054602060026001831615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156107105780601f106106e557610100808354040283529160200191610710565b600160a060020a03600435166000908152602081905260409020545b60408051918252519081900360200190f35b61066d60058054602060026001831615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156107105780601f106106e557610100808354040283529160200191610710565b61034c60043560243533600160a060020a03166000908152602081905260408120548290108015906103ed5750600082115b1561071857604080822080548490039055600160a060020a03808516808452918320805485019055606084815233909116907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602090a3506001610157565b60806020604435600481810135601f81018490049093028401604052606083815261034c94823594602480359560649493910191908190838280828437509496505050505050506000826001600050600033600160a060020a03168152602001908152602001600020600050600086600160a060020a031681526020019081526020016000206000508190555083600160a060020a031660405180807f72656365697665417070726f76616c28616464726573732c75696e743235362c81526020017f616464726573732c627974657329000000000000000000000000000000000000815260200150602e019050604051809103902060e060020a8091040260e060020a9004338530866040518560e060020a0281526004018085600160a060020a0316815260200184815260200183600160a060020a031681526020018280519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156105d45780820380516001836020036101000a031916815260200191505b509450505050506000604051808303816000876161da5a03f1505060408051868152905133600160a060020a031692507f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259181900360200190a35060015b9392505050565b61034c600435602435600160a060020a03808316600090815260016020908152604080832093851683529290522054610157565b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156106cd5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6060908152602090f35b820191906000526020600020905b8154815290600101906020018083116106f357829003601f168201915b505050505081565b610157565b6106325600000000000000000000000000000000000000000000000000000000000186a00000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000844616e6275636b7300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034442580000000000000000000000000000000000000000000000000000000000","gasPrice":"0xba43b7400","gas":"0xf4240","origin":"tokenfactory.surge.sh","metamaskId":1467742652846512,"metamaskNetworkId":"2"},"time":1467742652846,"status":"confirmed","hash":"0xa991793a6918aea6d58c30934dab5ca4c0a47c2444e5b60769637491f118de26"},{"id":1467755147235616,"txParams":{"from":"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825","data":"0x60a060405260046060527f48302e31000000000000000000000000000000000000000000000000000000006080526006805460008290527f48302e310000000000000000000000000000000000000000000000000000000882556100b5907ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f602060026001841615610100026000190190931692909204601f01919091048101905b8082111561017957600081556001016100a1565b505060405161099338038061099383398101604052808051906020019091908051820191906020018051906020019091908051820191906020015050836000600050600033600160a060020a0316815260200190815260200160002060005081905550836002600050819055508260036000509080519060200190828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061017d57805160ff19168380011785555b506101ad9291506100a1565b5090565b8280016001018555821561016d579182015b8281111561016d57825182600050559160200191906001019061018f565b50506004805460ff19168317905560058054825160008390527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db0602060026001851615610100026000190190941693909304601f90810184900482019386019083901061022d57805160ff19168380011785555b5061025d9291506100a1565b82800160010185558215610221579182015b8281111561022157825182600050559160200191906001019061023f565b505050505050610722806102716000396000f36060604052361561008d5760e060020a600035046306fdde038114610095578063095ea7b3146100f257806318160ddd1461015d57806323b872dd14610166578063313ce567146102c757806354fd4d50146102d357806370a082311461033057806395d89b411461035e578063a9059cbb146103bb578063cae9ca511461044d578063dd62ed3e14610639575b610000610002565b61066d60038054602060026001831615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156107105780601f106106e557610100808354040283529160200191610710565b61034c60043560243533600160a060020a03908116600081815260016020908152604080832094871680845294825282208590556060858152919392917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259190a35060015b92915050565b61034c60025481565b61034c600435602435604435600160a060020a0383166000908152602081905260408120548290108015906101b9575060016020908152604080832033600160a060020a03168452909152812054829010155b80156101c55750600082115b1561071d57816000600050600085600160a060020a03168152602001908152602001600020600082828250540192505081905550816000600050600086600160a060020a03168152602001908152602001600020600082828250540392505081905550816001600050600086600160a060020a03168152602001908152602001600020600050600033600160a060020a0316815260200190815260200160002060008282825054039250508190555082600160a060020a031684600160a060020a03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a3506001610632565b6106db60045460ff1681565b61066d60068054602060026001831615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156107105780601f106106e557610100808354040283529160200191610710565b600160a060020a03600435166000908152602081905260409020545b60408051918252519081900360200190f35b61066d60058054602060026001831615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156107105780601f106106e557610100808354040283529160200191610710565b61034c60043560243533600160a060020a03166000908152602081905260408120548290108015906103ed5750600082115b1561071857604080822080548490039055600160a060020a03808516808452918320805485019055606084815233909116907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602090a3506001610157565b60806020604435600481810135601f81018490049093028401604052606083815261034c94823594602480359560649493910191908190838280828437509496505050505050506000826001600050600033600160a060020a03168152602001908152602001600020600050600086600160a060020a031681526020019081526020016000206000508190555083600160a060020a031660405180807f72656365697665417070726f76616c28616464726573732c75696e743235362c81526020017f616464726573732c627974657329000000000000000000000000000000000000815260200150602e019050604051809103902060e060020a8091040260e060020a9004338530866040518560e060020a0281526004018085600160a060020a0316815260200184815260200183600160a060020a031681526020018280519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156105d45780820380516001836020036101000a031916815260200191505b509450505050506000604051808303816000876161da5a03f1505060408051868152905133600160a060020a031692507f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259181900360200190a35060015b9392505050565b61034c600435602435600160a060020a03808316600090815260016020908152604080832093851683529290522054610157565b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156106cd5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6060908152602090f35b820191906000526020600020905b8154815290600101906020018083116106f357829003601f168201915b505050505081565b610157565b6106325600000000000000000000000000000000000000000000000000000000000f42400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000844616e4275636b7300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034442580000000000000000000000000000000000000000000000000000000000","gasPrice":"0xba43b7400","gas":"0xf4240","origin":"tokenfactory.surge.sh","metamaskId":1467755147235616,"metamaskNetworkId":"1"},"time":1467755147235,"status":"rejected"},{"id":1467868023090690,"txParams":{"from":"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825","value":"0x16345785d8a0000","to":"0xC5b8dBAc4c1d3F152cDeb400E2313F309c410aCb","origin":"MetaMask","metamaskId":1467868023090690,"metamaskNetworkId":"2"},"time":1467868023090,"status":"unconfirmed","containsDelegateCall":false}],"selectedAccount":"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825","network":"2","seedWords":null,"isDisclaimerConfirmed":true,"unconfMsgs":{},"messages":[],"provider":{"type":"testnet"},"selectedAccount":"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825"},"appState":{"menuOpen":false,"currentView":{"name":"confTx","context":0},"accountDetail":{"subview":"transactions"},"currentDomain":"extensions","transForward":true,"isLoading":false,"warning":null},"identities":{}}
\ No newline at end of file diff --git a/development/states/private-network.json b/development/states/private-network.json new file mode 100644 index 000000000..7d24533c5 --- /dev/null +++ b/development/states/private-network.json @@ -0,0 +1,86 @@ +{ + "metamask": { + "isInitialized": true, + "isUnlocked": true, + "rpcTarget": "https://rawtestrpc.metamask.io/", + "identities": { + "0xfdea65c8e26263f6d9a1b5de9555d2931a33b825": { + "name": "Account 1", + "address": "0xfdea65c8e26263f6d9a1b5de9555d2931a33b825", + "mayBeFauceting": false + }, + "0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb": { + "name": "Account 2", + "address": "0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb", + "mayBeFauceting": false + } + }, + "unconfTxs": {}, + "currentFiat": "USD", + "conversionRate": 9.52855776, + "conversionDate": 1479756513, + "accounts": { + "0xfdea65c8e26263f6d9a1b5de9555d2931a33b825": { + "balance": "0x0", + "nonce": "0x0", + "code": "0x0", + "address": "0xfdea65c8e26263f6d9a1b5de9555d2931a33b825" + }, + "0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb": { + "balance": "0x0", + "nonce": "0x0", + "code": "0x0", + "address": "0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb" + } + }, + "transactions": [ + { + "id": 5551995700357153, + "txParams": { + "from": "0xfdea65c8e26263f6d9a1b5de9555d2931a33b825", + "to": "0x48ff0cbac0acefedf152281ee80e9a0a01d5da63", + "data": "0x90b98a11000000000000000000000000c5b8dbac4c1d3f152cdeb400e2313f309c410acb000000000000000000000000000000000000000000000000000000000000000a", + "metamaskId": 5551995700357153, + "metamaskNetworkId": "1479490588308" + }, + "time": 1479498745949, + "status": "confirmed", + "gasMultiplier": 1, + "metamaskNetworkId": "1479490588308", + "containsDelegateCall": true, + "estimatedGas": "0x24b33", + "hash": "0xad609a6931f54a575ad71222ffc27cd6746017106d5b89f4ad300b37b273f8ac" + } + ], + "selectedAccount": "0xfdea65c8e26263f6d9a1b5de9555d2931a33b825", + "network": "1479753732793", + "isConfirmed": true, + "isEthConfirmed": true, + "unconfMsgs": {}, + "messages": [], + "shapeShiftTxList": [], + "gasMultiplier": false, + "provider": { + "type": "rpc", + "rpcTarget": "http://localhost:8545" + }, + "selectedAccount": "0xfdea65c8e26263f6d9a1b5de9555d2931a33b825", + "isDisclaimerConfirmed": true + }, + "appState": { + "menuOpen": false, + "currentView": { + "name": "accountDetail" + }, + "accountDetail": { + "subview": "transactions", + "accountExport": "none", + "privateKey": "" + }, + "transForward": false, + "isLoading": false, + "warning": null, + "scrollToBottom": false + }, + "identities": {} +}
\ No newline at end of file diff --git a/development/states/restore-vault.json b/development/states/restore-vault.json index e1f157ddf..bde15d861 100644 --- a/development/states/restore-vault.json +++ b/development/states/restore-vault.json @@ -2,7 +2,6 @@ "metamask": { "isInitialized": false, "isUnlocked": false, - "isEthConfirmed": false, "currentDomain": "example.com", "rpcTarget": "https://rawtestrpc.metamask.io/", "identities": {}, @@ -13,7 +12,7 @@ "accounts": {}, "transactions": [], "seedWords": null, - "isConfirmed": true, + "isDisclaimerConfirmed": true, "unconfMsgs": {}, "messages": [], "shapeShiftTxList": [], @@ -36,4 +35,4 @@ "warning": null }, "identities": {} -}
\ No newline at end of file +} diff --git a/development/states/send.json b/development/states/send.json index afc1e6397..3e1aa88ba 100644 --- a/development/states/send.json +++ b/development/states/send.json @@ -2,7 +2,6 @@ "metamask": { "isInitialized": true, "isUnlocked": true, - "isEthConfirmed": false, "currentDomain": "example.com", "rpcTarget": "https://rawtestrpc.metamask.io/", "identities": { @@ -49,7 +48,7 @@ "transactions": [], "network": "2", "seedWords": null, - "isConfirmed": true, + "isDisclaimerConfirmed": true, "unconfMsgs": {}, "messages": [], "shapeShiftTxList": [], @@ -73,4 +72,4 @@ "detailView": {} }, "identities": {} -}
\ No newline at end of file +} diff --git a/development/states/shapeshift.json b/development/states/shapeshift.json index a656fb00f..7004e83be 100644 --- a/development/states/shapeshift.json +++ b/development/states/shapeshift.json @@ -2,7 +2,6 @@ "metamask": { "isInitialized": true, "isUnlocked": true, - "isEthConfirmed": true, "currentDomain": "example.com", "rpcTarget": "https://rawtestrpc.metamask.io/", "identities": { @@ -47,10 +46,10 @@ } }, "transactions": [], - "selectedAddress": "0xfdea65c8e26263f6d9a1b5de9555d2931a33b825", + "selectedAccount": "0xfdea65c8e26263f6d9a1b5de9555d2931a33b825", "network": "1", "seedWords": null, - "isConfirmed": true, + "isDisclaimerConfirmed": true, "unconfMsgs": {}, "messages": [], "shapeShiftTxList": [], @@ -345,4 +344,4 @@ "isSubLoading": false }, "identities": {} -}
\ No newline at end of file +} diff --git a/development/states/show-seed-words.json b/development/states/show-seed-words.json index 19be51fbd..ddf1f9fba 100644 --- a/development/states/show-seed-words.json +++ b/development/states/show-seed-words.json @@ -45,7 +45,7 @@ "transactions": [], "network": "2", "seedWords": "debris dizzy just program just float decrease vacant alarm reduce speak stadium", - "isConfirmed": true, + "isDisclaimerConfirmed": true, "unconfMsgs": {}, "messages": [], "provider": { diff --git a/development/test.html b/development/test.html new file mode 100644 index 000000000..702be7fa0 --- /dev/null +++ b/development/test.html @@ -0,0 +1,31 @@ +<!doctype html> +<html> + <head> + <meta charset="utf-8"> + <title>MetaMask</title> + + <script> + window.METAMASK_DEBUG = true + window.TEST_MODE = true + </script> + </head> + <body> + + <!-- app content --> + <div id="app-content" style="height: 100%"></div> + <script src="./bundle.js" type="text/javascript" charset="utf-8"></script> + + </body> + +<style> +html, body, #app-content, .super-dev-container { + height: 100%; + width: 100%; + position: relative; + background: white; +} +.mock-app-root { + background: #F7F7F7; +} +</style> +</html> diff --git a/docs/multi_vault_planning.md b/docs/multi_vault_planning.md new file mode 100644 index 000000000..fdde2bc50 --- /dev/null +++ b/docs/multi_vault_planning.md @@ -0,0 +1,188 @@ +https://hackmd.io/JwIwDMDGKQZgtAFgKZjEgbARhPAhgKxZbwAcA7LAWOQCaKEgFA==?edit + +Subscribablez(initState) + .subscribe() + .emitUpdate(newState) + //.getState() + + +var initState = fromDisk() +ReduxStore(reducer, initState) +.reduce(action) -> .emitUpdate() + +ReduxStore.subscribe(toDisk) + + +### KeyChainManager / idStore 2.0 (maybe just in MetaMaskController) + keychains: [] + getAllAccounts(cb) + getAllKeychainViewStates(cb) -> returns [ KeyChainViewState] + +#### Old idStore external methods, for feature parity: + +- init(configManager) +- setStore(ethStore) +- getState() +- getSelectedAddres() +- setSelectedAddress() +- createNewVault() +- recoverFromSeed() +- submitPassword() +- approveTransaction() +- cancelTransaction() +- addUnconfirmedMessage(msgParams, cb) +- signMessage() +- cancelMessage() +- setLocked() +- clearSeedWordCache() +- exportAccount() +- revealAccount() +- saveAccountLabel() +- tryPassword() +- recoverSeed() +- getNetwork() + +##### Of those methods + +Where they should end up: + +##### MetaMaskController + +- getNetwork() + +##### KeyChainManager + +- init(configManager) +- setStore(ethStore) +- getState() // Deprecate for unidirectional flow +- on('update', cb) +- createNewVault(password) +- getSelectedAddres() +- setSelectedAddress() +- submitPassword() +- tryPassword() +- approveTransaction() +- cancelTransaction() +- signMessage() +- cancelMessage() +- setLocked() +- exportAccount() + +##### Bip44 KeyChain + +- getState() // Deprecate for unidirectional flow +- on('update', cb) + +If we adopt a ReactStore style unidirectional action dispatching data flow, these methods will be unified under a `dispatch` method, and rather than having a cb will emit an update to the UI: + +- createNewKeyChain(entropy) +- recoverFromSeed() +- approveTransaction() +- signMessage() +- clearSeedWordCache() +- exportAccount() +- revealAccount() +- saveAccountLabel() +- recoverSeed() + +Additional methods, new to this: +- serialize() + - Returns pojo with optional `secret` key whose contents will be encrypted with the users' password and salt when written to disk. + - The isolation of secrets is to preserve performance when decrypting user data. +- deserialize(pojo) + +### KeyChain (ReduxStore?) + // attributes + @name + + signTx(txParams, cb) + signMsg(msg, cb) + + getAddressList(cb) + + getViewState(cb) -> returns KeyChainViewState + + serialize(cb) -> obj + deserialize(obj) + + dispatch({ type: <str>, value: <pojo> }) + + +### KeyChainViewState + // The serialized, renderable keychain data + accountList: [], + typeName: 'uPort', + iconAddress: 'uport.gif', + internal: {} // Subclass-defined metadata + +### KeyChainReactComponent + // takes a KeyChainViewState + + // Subclasses of this: + - KeyChainListItemComponent + - KeyChainInitComponent - Maybe part of the List Item + - KeyChainAccountHeaderComponent + - KeyChainConfirmationComponent + // Account list item, tx confirmation extra data (like a QR code), + // Maybe an options screen, init screen, + + how to send actions? + emitAction(keychains.<id>.didInit) + + +gimmeRemoteKeychain((err, remoteKeychain)=> + +) + + + + + +KeyChainReactComponent({ + keychain +}) + +Keychain: + methods:{}, + cachedAccountList: [], + name: '', + + +CoinbaseKeychain + getAccountList + + +CoinbaseKeychainComponent + isLoading = true + keychain.getAccountList(()=>{ + isLoading=false + accountList=accounts + }) + + + + + +KeyChainViewState { + attributes: { + //mandatory: + accountList: [], + typeName: 'uPort', + iconAddress: 'uport.gif', + + internal: { + // keychain-specific metadata + proxyAddresses: { + 0xReal: '0xProxy' + } + }, + }, + methods: { + // arbitrary, internal + } +} + +## A note on the security of arbitrary action dispatchers + +Since keychains will be dispatching actions that are then passed through the background process to be routed, we should not trust or require them to include their own keychain ID as a prefix to their action, but we should tack it on ourselves, so that no action dispatched by a KeyChainComponent ever reaches any KeyChain other than its own. + diff --git a/mock-dev.js b/mock-dev.js index 99b846e51..84f2d234a 100644 --- a/mock-dev.js +++ b/mock-dev.js @@ -26,7 +26,7 @@ const extension = require('./development/mockExtension') // Query String const qs = require('qs') let queryString = qs.parse(window.location.href.split('#')[1]) -let selectedView = queryString.view || 'terms' +let selectedView = queryString.view || 'first time' const firstState = states[selectedView] updateQueryParams(selectedView) @@ -107,7 +107,7 @@ function getOldStyleData () { return result } -actions._setAccountManager(controller.getApi()) +actions._setBackgroundConnection(controller.getApi()) actions.update = function(stateName) { selectedView = stateName updateQueryParams(stateName) diff --git a/package.json b/package.json index 2b3b821db..46d17a94c 100644 --- a/package.json +++ b/package.json @@ -4,19 +4,20 @@ "public": false, "private": true, "scripts": { - "start": "gulp dev", + "start": "npm run dev", "lint": "gulp lint", - "dev": "gulp dev", + "buildCiUnits": "node test/integration/index.js", + "dev": "gulp dev --debug", "dist": "gulp dist --disableLiveReload", "test": "npm run fastTest && npm run ci && npm run lint", - "fastTest": "mocha --require test/helper.js --compilers js:babel-register --recursive \"test/unit/**/*.js\"", + "fastTest": "METAMASK_ENV=test mocha --require test/helper.js --compilers js:babel-register --recursive \"test/unit/**/*.js\"", "watch": "mocha watch --compilers js:babel-register --recursive \"test/unit/**/*.js\"", "genStates": "node development/genStates.js", "ui": "npm run genStates && beefy ui-dev.js:bundle.js --live --open --index=./development/index.html --cwd ./", "mock": "beefy mock-dev.js:bundle.js --live --open --index=./development/index.html --cwd ./", "buildMock": "npm run genStates && browserify ./mock-dev.js -o ./development/bundle.js", "testem": "npm run buildMock && testem", - "ci": "npm run buildMock && testem ci -P 2", + "ci": "npm run buildMock && npm run buildCiUnits && testem ci -P 2", "announce": "node development/announcer.js", "generateNotice": "node development/notice-generator.js" }, @@ -35,6 +36,7 @@ }, "dependencies": { "async": "^1.5.2", + "bip39": "^2.2.0", "browserify-derequire": "^0.9.4", "clone": "^1.0.2", "copy-to-clipboard": "^2.0.0", @@ -48,6 +50,7 @@ "eth-store": "^1.1.0", "ethereumjs-tx": "^1.0.0", "ethereumjs-util": "^4.4.0", + "ethereumjs-wallet": "^0.6.0", "express": "^4.14.0", "extension-link-enabler": "^1.0.0", "extensionizer": "^1.0.0", @@ -57,7 +60,7 @@ "iframe": "^1.0.0", "iframe-stream": "^1.0.2", "inject-css": "^0.1.1", - "jazzicon": "1.1.5", + "jazzicon": "^1.2.0", "menu-droppo": "^1.1.0", "metamask-logo": "^2.1.2", "mississippi": "^1.2.0", @@ -67,6 +70,7 @@ "pojo-migrator": "^2.1.0", "polyfill-crypto.getrandomvalues": "^1.0.0", "post-message-stream": "^1.0.0", + "promise-filter": "^1.1.0", "pumpify": "^1.3.4", "qrcode-npm": "0.0.3", "react": "^15.0.2", diff --git a/test/integration/helpers.js b/test/integration/helpers.js index 95c36017a..eede103b4 100644 --- a/test/integration/helpers.js +++ b/test/integration/helpers.js @@ -1,7 +1,7 @@ -function wait() { +function wait(time) { return new Promise(function(resolve, reject) { setTimeout(function() { resolve() - }, 500) + }, time * 3 || 1500) }) } diff --git a/test/integration/index.html b/test/integration/index.html index 6de40b046..8a54cb829 100644 --- a/test/integration/index.html +++ b/test/integration/index.html @@ -12,10 +12,10 @@ <script src="https://code.jquery.com/qunit/qunit-2.0.0.js"></script> <script src="./jquery-3.1.0.min.js"></script> <script src="helpers.js"></script> - <script src="tests.js"></script> + <script src="bundle.js"></script> <script src="/testem.js"></script> - <iframe src="/development/index.html" height="500px" width="360px"> + <iframe src="/development/test.html" height="500px" width="360px"> <p>Your browser does not support iframes</p> </iframe> </body> diff --git a/test/integration/index.js b/test/integration/index.js new file mode 100644 index 000000000..ff6d1baf8 --- /dev/null +++ b/test/integration/index.js @@ -0,0 +1,21 @@ +var fs = require('fs') +var path = require('path') +var browserify = require('browserify'); +var tests = fs.readdirSync(path.join(__dirname, 'lib')) +var bundlePath = path.join(__dirname, 'bundle.js') + +var b = browserify(); + +// Remove old bundle +try { + fs.unlinkSync(bundlePath) +} catch (e) {} + +var writeStream = fs.createWriteStream(bundlePath) + +tests.forEach(function(fileName) { + b.add(path.join(__dirname, 'lib', fileName)) +}) + +b.bundle().pipe(writeStream); + diff --git a/test/integration/lib/encryptor-test.js b/test/integration/lib/encryptor-test.js new file mode 100644 index 000000000..897d22740 --- /dev/null +++ b/test/integration/lib/encryptor-test.js @@ -0,0 +1,71 @@ +var encryptor = require('../../../app/scripts/lib/encryptor') + +QUnit.module('encryptor') + +QUnit.test('encryptor:serializeBufferForStorage', function (assert) { + assert.expect(1) + var buf = new Buffer(2) + buf[0] = 16 + buf[1] = 1 + + var output = encryptor.serializeBufferForStorage(buf) + + var expect = '0x1001' + assert.equal(expect, output) +}) + +QUnit.test('encryptor:serializeBufferFromStorage', function (assert) { + assert.expect(2) + var input = '0x1001' + var output = encryptor.serializeBufferFromStorage(input) + + assert.equal(output[0], 16) + assert.equal(output[1], 1) +}) + +QUnit.test('encryptor:encrypt & decrypt', function(assert) { + var done = assert.async(); + var password, data, encrypted + + password = 'a sample passw0rd' + data = { foo: 'data to encrypt' } + + encryptor.encrypt(password, data) + .then(function(encryptedStr) { + assert.equal(typeof encryptedStr, 'string', 'returns a string') + return encryptor.decrypt(password, encryptedStr) + }) + .then(function (decryptedObj) { + assert.deepEqual(decryptedObj, data, 'decrypted what was encrypted') + done() + }) + .catch(function(reason) { + assert.ifError(reason, 'threw an error') + done(reason) + }) + +}) + +QUnit.test('encryptor:encrypt & decrypt with wrong password', function(assert) { + var done = assert.async(); + var password, data, encrypted, wrongPassword + + password = 'a sample passw0rd' + wrongPassword = 'a wrong password' + data = { foo: 'data to encrypt' } + + encryptor.encrypt(password, data) + .then(function(encryptedStr) { + assert.equal(typeof encryptedStr, 'string', 'returns a string') + return encryptor.decrypt(wrongPassword, encryptedStr) + }) + .then(function (decryptedObj) { + assert.equal(!decryptedObj, true, 'Wrong password should not decrypt') + done() + }) + .catch(function(reason) { + done() + }) +}) + + diff --git a/test/integration/lib/first-time.js b/test/integration/lib/first-time.js new file mode 100644 index 000000000..12c573db1 --- /dev/null +++ b/test/integration/lib/first-time.js @@ -0,0 +1,90 @@ +const PASSWORD = 'password123' + +QUnit.module('first time usage') + +QUnit.test('agree to terms', function (assert) { + var done = assert.async() + let app + + wait().then(function() { + app = $('iframe').contents().find('#app-content .mock-app-root') + app.find('.markdown').prop('scrollTop', 100000000) + return wait() + + }).then(function() { + + var title = app.find('h1').text() + assert.equal(title, 'MetaMask', 'title screen') + + var pwBox = app.find('#password-box')[0] + var confBox = app.find('#password-box-confirm')[0] + + pwBox.value = PASSWORD + confBox.value = PASSWORD + return wait() + + }).then(function() { + + var createButton = app.find('button.primary')[0] + createButton.click() + + return wait(1500) + }).then(function() { + + var terms = app.find('h3.terms-header')[0] + assert.equal(terms.textContent, 'MetaMask Terms & Conditions', 'Showing TOS') + + // Scroll through terms + var scrollable = app.find('.markdown')[0] + scrollable.scrollTop = scrollable.scrollHeight + + return wait(10) + }).then(function() { + + var button = app.find('button')[0] // Agree button + button.click() + + return wait(1000) + }).then(function() { + + var created = app.find('h3')[0] + assert.equal(created.textContent, 'Vault Created', 'Vault created screen') + + var button = app.find('button')[0] // Agree button + button.click() + + return wait(1000) + }).then(function() { + + var detail = app.find('.account-detail-section')[0] + assert.ok(detail, 'Account detail section loaded.') + + var sandwich = app.find('.sandwich-expando')[0] + sandwich.click() + + return wait() + }).then(function() { + + var sandwich = app.find('.menu-droppo')[0] + var lock = sandwich.children[2] + assert.ok(lock, 'Lock menu item found') + lock.click() + + return wait(1000) + }).then(function() { + + var pwBox = app.find('#password-box')[0] + pwBox.value = PASSWORD + + var createButton = app.find('button.primary')[0] + createButton.click() + + return wait(1500) + }).then(function() { + + var detail = app.find('.account-detail-section')[0] + assert.ok(detail, 'Account detail section loaded again.') + + done() + }) +}) diff --git a/test/integration/lib/keyring-controller-test.js b/test/integration/lib/keyring-controller-test.js new file mode 100644 index 000000000..ae5ecc578 --- /dev/null +++ b/test/integration/lib/keyring-controller-test.js @@ -0,0 +1,62 @@ +var KeyringController = require('../../../app/scripts/keyring-controller') +var ConfigManager = require('../../../app/scripts/lib/config-manager') + +var oldStyleVault = require('../mocks/oldVault.json') + +var STORAGE_KEY = 'metamask-config' +var PASSWORD = '12345678' +var FIRST_ADDRESS = '0x4dd5d356c5A016A220bCD69e82e5AF680a430d00'.toLowerCase() + + +QUnit.module('Old Style Vaults', { + beforeEach: function () { + window.localStorage[STORAGE_KEY] = JSON.stringify(oldStyleVault) + + this.configManager = new ConfigManager({ + loadData: () => { return JSON.parse(window.localStorage[STORAGE_KEY]) }, + setData: (data) => { window.localStorage[STORAGE_KEY] = JSON.stringify(data) }, + }) + + this.keyringController = new KeyringController({ + configManager: this.configManager, + getNetwork: () => { return '2' }, + }) + + this.ethStore = { + addAccount: () => {}, + removeAccount: () => {}, + } + + this.keyringController.setStore(this.ethStore) + } +}) + +QUnit.test('keyringController:isInitialized', function (assert) { + assert.ok(this.keyringController.getState().isInitialized) +}) + +QUnit.test('keyringController:submitPassword', function (assert) { + var done = assert.async() + + this.keyringController.submitPassword(PASSWORD) + .then((state) => { + assert.ok(state.identities[FIRST_ADDRESS]) + done() + }) +}) + +QUnit.test('keyringController:setLocked', function (assert) { + var done = assert.async() + var self = this + + this.keyringController.setLocked() + .then(function() { + assert.notOk(self.keyringController.password, 'password should be deallocated') + assert.deepEqual(self.keyringController.keyrings, [], 'keyrings should be deallocated') + done() + }) + .catch((reason) => { + assert.ifError(reason) + done() + }) +}) diff --git a/test/integration/mocks/oldVault.json b/test/integration/mocks/oldVault.json new file mode 100644 index 000000000..5861c41d7 --- /dev/null +++ b/test/integration/mocks/oldVault.json @@ -0,0 +1,21 @@ +{ + "meta": { + "version": 4 + }, + "data": { + "fiatCurrency": "USD", + "isConfirmed": true, + "TOSHash": "a4f4e23f823a7ac51783e7ffba7914a911b09acdb97263296b7e14b527f80c5b", + "conversionRate": 9.47316629, + "conversionDate": 1479510994, + "wallet": "{\"encSeed\":{\"encStr\":\"a5tjKtDGlHkua+6Ta5s3wMFWPmsBqaPdMKGmqeI2z1kMbNs3V03HBaCptU7NtMra1DjHKbSNsUToxFUrmrvWBmUejamN16+l1CviwqASsv7kKzpot00/dfyyJgtZwwFP5Je+TAB1V231nRbPidOfeE1cDec5V8KTF8epl6qzsbA25pjeW76Dfw==\",\"nonce\":\"RzID6bAhWfGTSR74xdIh3RaT1+1sLk6F\"},\"ksData\":{\"m/44'/60'/0'/0\":{\"info\":{\"curve\":\"secp256k1\",\"purpose\":\"sign\"},\"encHdPathPriv\":{\"encStr\":\"6nlYAopRbmGcqerRZO08XwgeYaCJg9XRhh4oiYiVVdQtyNPdxvOI9TcE/mqvBiatMwBwA+TmsqTV6eZZe/VDZKYIGajKulQbScd0xQ71JhYfqqmzSG6EH2Pnzwa+aSAsfARgN1JJSaff2+p6wV6Zg5BUDtl72OGEIEfXhcUGwg==\",\"nonce\":\"Ee1KiDqtx7NvYToQUFvjEhKNinNQcXlK\"},\"hdIndex\":1,\"encPrivKeys\":{\"4dd5d356c5a016a220bcd69e82e5af680a430d00\":{\"key\":\"htGRGAH10lGF4M+fvioznmYVIUSWAzwp/yWSIo85psgZZwmCdJY72oyGanYsrFO8\",\"nonce\":\"PkP8XeZ+ok215rzEorvJu9nYTWzkOVr0\"}},\"addresses\":[\"4dd5d356c5a016a220bcd69e82e5af680a430d00\"]}},\"encHdRootPriv\":{\"encStr\":\"TAZAo71a+4IlAaoA66f0w4ts2f+V7ArTSUHRIrMltfAPXz7GfJBmKXNtHPORUYAjRiKqWK6FZnhKLf7Vcng2LG7VnDQwC4xPxzSRZzSEilnoY3V+zRY0HD7Wb/pndb4FliA/buZQmjohO4vezeX0hl70rJlPJEZTyYoWgxbxFA==\",\"nonce\":\"FlJOaLyBEHMaH5fEnYjdHc6nn18+WkRj\"},\"salt\":\"CmuCcWpbqpKUUv+1aE2ZwvQl7EIQ731uFibSq++vwtY=\",\"version\":2}", + "config": { + "provider": { + "type": "testnet" + }, + "selectedAccount": "0x4dd5d356c5a016a220bcd69e82e5af680a430d00" + }, + "showSeedWords": false, + "isEthConfirmed": true + } +} diff --git a/test/integration/tests.js b/test/integration/tests.js deleted file mode 100644 index 92111b05b..000000000 --- a/test/integration/tests.js +++ /dev/null @@ -1,24 +0,0 @@ -QUnit.test('agree to terms', function (assert) { - var done = assert.async() - - // Select the mock app root - var app = $('iframe').contents().find('#app-content .mock-app-root') - - app.find('.markdown').prop('scrollTop', 100000000) - - wait().then(function() { - app.find('button').click() - }).then(function() { - return wait() - }).then(function() { - var title = app.find('h1').text() - assert.equal(title, 'MetaMask', 'title screen') - - var buttons = app.find('button') - assert.equal(buttons.length, 2, 'two buttons: create and restore') - - done() - }) - - // Wait for view to transition: -}) diff --git a/test/lib/mock-config-manager.js b/test/lib/mock-config-manager.js index fe841f455..ccd518c68 100644 --- a/test/lib/mock-config-manager.js +++ b/test/lib/mock-config-manager.js @@ -1,5 +1,5 @@ var ConfigManager = require('../../app/scripts/lib/config-manager') -const STORAGE_KEY = 'metamask-persistance-key' +const STORAGE_KEY = 'metamask-config' const extend = require('xtend') module.exports = function() { diff --git a/test/lib/mock-encryptor.js b/test/lib/mock-encryptor.js new file mode 100644 index 000000000..09bbf7ad5 --- /dev/null +++ b/test/lib/mock-encryptor.js @@ -0,0 +1,32 @@ +var mockHex = '0xabcdef0123456789' +var mockKey = new Buffer(32) +let cacheVal + +module.exports = { + + encrypt(password, dataObj) { + cacheVal = dataObj + return Promise.resolve(mockHex) + }, + + decrypt(password, text) { + return Promise.resolve(cacheVal || {}) + }, + + encryptWithKey(key, dataObj) { + return this.encrypt(key, dataObj) + }, + + decryptWithKey(key, text) { + return this.decrypt(key, text) + }, + + keyFromPassword(password) { + return Promise.resolve(mockKey) + }, + + generateSalt() { + return 'WHADDASALT!' + }, + +} diff --git a/test/lib/mock-simple-keychain.js b/test/lib/mock-simple-keychain.js new file mode 100644 index 000000000..615b3e537 --- /dev/null +++ b/test/lib/mock-simple-keychain.js @@ -0,0 +1,38 @@ +var fakeWallet = { + privKey: '0x123456788890abcdef', + address: '0xfedcba0987654321', +} +const type = 'Simple Key Pair' + +module.exports = class MockSimpleKeychain { + + static type() { return type } + + constructor(opts) { + this.type = type + this.opts = opts || {} + this.wallets = [] + } + + serialize() { + return [ fakeWallet.privKey ] + } + + deserialize(data) { + if (!Array.isArray(data)) { + throw new Error('Simple keychain deserialize requires a privKey array.') + } + this.wallets = [ fakeWallet ] + } + + addAccounts(n = 1) { + for(var i = 0; i < n; i++) { + this.wallets.push(fakeWallet) + } + } + + getAccounts() { + return this.wallets.map(w => w.address) + } + +} diff --git a/test/unit/actions/restore_vault_test.js b/test/unit/actions/restore_vault_test.js deleted file mode 100644 index 609f5429e..000000000 --- a/test/unit/actions/restore_vault_test.js +++ /dev/null @@ -1,60 +0,0 @@ -var jsdom = require('mocha-jsdom') -var assert = require('assert') -var freeze = require('deep-freeze-strict') -var path = require('path') -var sinon = require('sinon') - -var actions = require(path.join(__dirname, '..', '..', '..', 'ui', 'app', 'actions.js')) -var reducers = require(path.join(__dirname, '..', '..', '..', 'ui', 'app', 'reducers.js')) - -describe('#recoverFromSeed(password, seed)', function() { - - beforeEach(function() { - // sinon allows stubbing methods that are easily verified - this.sinon = sinon.sandbox.create() - }) - - afterEach(function() { - // sinon requires cleanup otherwise it will overwrite context - this.sinon.restore() - }) - - // stub out account manager - actions._setAccountManager({ - recoverFromSeed(pw, seed, cb) { - cb(null, { - identities: { - foo: 'bar' - } - }) - }, - }) - - it('sets metamask.isUnlocked to true', function() { - var initialState = { - metamask: { - isUnlocked: false, - isInitialized: false, - } - } - freeze(initialState) - - const restorePhrase = 'invite heavy among daring outdoor dice jelly coil stable note seat vicious' - const password = 'foo' - const dispatchFunc = actions.recoverFromSeed(password, restorePhrase) - - var dispatchStub = this.sinon.stub() - dispatchStub.withArgs({ TYPE: actions.unlockMetamask() }).onCall(0) - dispatchStub.withArgs({ TYPE: actions.showAccountsPage() }).onCall(1) - - var action - var resultingState = initialState - dispatchFunc((newAction) => { - action = newAction - resultingState = reducers(resultingState, action) - }) - - assert.equal(resultingState.metamask.isUnlocked, true, 'was unlocked') - assert.equal(resultingState.metamask.isInitialized, true, 'was initialized') - }); -}); diff --git a/test/unit/actions/set_selected_account_test.js b/test/unit/actions/set_selected_account_test.js index 69eb11e47..f72ca82e4 100644 --- a/test/unit/actions/set_selected_account_test.js +++ b/test/unit/actions/set_selected_account_test.js @@ -44,6 +44,5 @@ describe('SHOW_ACCOUNT_DETAIL', function() { var resultingState = reducers(initialState, action) assert.equal(resultingState.metamask.selectedAccount, action.value) - assert.equal(resultingState.metamask.selectedAddress, action.value) }) }) diff --git a/test/unit/actions/tx_test.js b/test/unit/actions/tx_test.js index c08a8aa26..1f06b1120 100644 --- a/test/unit/actions/tx_test.js +++ b/test/unit/actions/tx_test.js @@ -46,7 +46,7 @@ describe('tx confirmation screen', function() { describe('cancelTx', function() { before(function(done) { - actions._setAccountManager({ + actions._setBackgroundConnection({ approveTransaction(txId, cb) { cb('An error!') }, cancelTransaction(txId) { /* noop */ }, clearSeedWordCache(cb) { cb() }, @@ -75,7 +75,7 @@ describe('tx confirmation screen', function() { before(function(done) { alert = () => {/* noop */} - actions._setAccountManager({ + actions._setBackgroundConnection({ approveTransaction(txId, cb) { cb({message: 'An error!'}) }, }) @@ -96,7 +96,7 @@ describe('tx confirmation screen', function() { describe('when there is success', function() { it('should complete tx and go home', function() { - actions._setAccountManager({ + actions._setBackgroundConnection({ approveTransaction(txId, cb) { cb() }, }) @@ -135,7 +135,7 @@ describe('tx confirmation screen', function() { } freeze(initialState) - actions._setAccountManager({ + actions._setBackgroundConnection({ approveTransaction(txId, cb) { cb() }, }) diff --git a/test/unit/config-manager-test.js b/test/unit/config-manager-test.js index 26aa35a74..477188b67 100644 --- a/test/unit/config-manager-test.js +++ b/test/unit/config-manager-test.js @@ -100,31 +100,31 @@ describe('config-manager', function() { describe('confirmation', function() { - describe('#getConfirmed', function() { + describe('#getConfirmedDisclaimer', function() { it('should return false if no previous key exists', function() { - var result = configManager.getConfirmed() + var result = configManager.getConfirmedDisclaimer() assert.ok(!result) }) }) - describe('#setConfirmed', function() { - it('should make getConfirmed return true once set', function() { - assert.equal(configManager.getConfirmed(), false) - configManager.setConfirmed(true) - var result = configManager.getConfirmed() + describe('#setConfirmedDisclaimer', function() { + it('should make getConfirmedDisclaimer return true once set', function() { + assert.equal(configManager.getConfirmedDisclaimer(), false) + configManager.setConfirmedDisclaimer(true) + var result = configManager.getConfirmedDisclaimer() assert.equal(result, true) }) it('should be able to set false', function() { - configManager.setConfirmed(false) - var result = configManager.getConfirmed() + configManager.setConfirmedDisclaimer(false) + var result = configManager.getConfirmedDisclaimer() assert.equal(result, false) }) it('should persist to local storage', function() { - configManager.setConfirmed(true) + configManager.setConfirmedDisclaimer(true) var data = configManager.getData() - assert.equal(data.isConfirmed, true) + assert.equal(data.isDisclaimerConfirmed, true) }) }) }) @@ -153,7 +153,7 @@ describe('config-manager', function() { rpcTarget: 'foobar' }, } - configManager.setConfirmed(true) + configManager.setConfirmedDisclaimer(true) configManager.setConfig(testConfig) var testWallet = { @@ -164,7 +164,7 @@ describe('config-manager', function() { var result = configManager.getData() assert.equal(result.wallet.name, testWallet.name, 'wallet name is set') assert.equal(result.config.provider.rpcTarget, testConfig.provider.rpcTarget) - assert.equal(configManager.getConfirmed(), true) + assert.equal(configManager.getConfirmedDisclaimer(), true) testConfig.provider.type = 'something else!' configManager.setConfig(testConfig) @@ -173,7 +173,7 @@ describe('config-manager', function() { assert.equal(result.wallet.name, testWallet.name, 'wallet name is set') assert.equal(result.config.provider.rpcTarget, testConfig.provider.rpcTarget) assert.equal(result.config.provider.type, testConfig.provider.type) - assert.equal(configManager.getConfirmed(), true) + assert.equal(configManager.getConfirmedDisclaimer(), true) }) }) diff --git a/test/unit/idStore-migration-test.js b/test/unit/idStore-migration-test.js new file mode 100644 index 000000000..ac8e23d22 --- /dev/null +++ b/test/unit/idStore-migration-test.js @@ -0,0 +1,160 @@ +const async = require('async') +const assert = require('assert') +const ethUtil = require('ethereumjs-util') +const BN = ethUtil.BN +const ConfigManager = require('../../app/scripts/lib/config-manager') +const delegateCallCode = require('../lib/example-code.json').delegateCallCode + +// The old way: +const IdentityStore = require('../../app/scripts/lib/idStore') +const STORAGE_KEY = 'metamask-config' +const extend = require('xtend') + +// The new ways: +var KeyringController = require('../../app/scripts/keyring-controller') +const mockEncryptor = require('../lib/mock-encryptor') +const MockSimpleKeychain = require('../lib/mock-simple-keychain') +const sinon = require('sinon') + +const mockVault = { + seed: 'picnic injury awful upper eagle junk alert toss flower renew silly vague', + account: '0x5d8de92c205279c10e5669f797b853ccef4f739a', +} + +describe('IdentityStore to KeyringController migration', function() { + + // The stars of the show: + let idStore, keyringController, seedWords, configManager + + let password = 'password123' + let entropy = 'entripppppyy duuude' + let accounts = [] + let newAccounts = [] + let originalKeystore + + // This is a lot of setup, I know! + // We have to create an old style vault, populate it, + // and THEN create a new one, before we can run tests on it. + beforeEach(function(done) { + this.sinon = sinon.sandbox.create() + window.localStorage = {} // Hacking localStorage support into JSDom + configManager = new ConfigManager({ + loadData, + setData: (d) => { window.localStorage = d } + }) + + + idStore = new IdentityStore({ + configManager: configManager, + ethStore: { + addAccount(acct) { accounts.push(ethUtil.addHexPrefix(acct)) }, + del(acct) { delete accounts[acct] }, + }, + }) + + idStore._createVault(password, mockVault.seed, (err) => { + assert.ifError(err, 'createNewVault threw error') + originalKeystore = idStore._idmgmt.keyStore + + idStore.setLocked((err) => { + assert.ifError(err, 'createNewVault threw error') + keyringController = new KeyringController({ + configManager, + ethStore: { + addAccount(acct) { newAccounts.push(ethUtil.addHexPrefix(acct)) }, + del(acct) { delete newAccounts[acct] }, + }, + }) + + // Stub out the browser crypto for a mock encryptor. + // Browser crypto is tested in the integration test suite. + keyringController.encryptor = mockEncryptor + done() + }) + }) + }) + + describe('entering a password', function() { + it('should identify an old wallet as an initialized keyring', function() { + keyringController.configManager.setWallet('something') + const state = keyringController.getState() + assert(state.isInitialized, 'old vault counted as initialized.') + }) + + /* + it('should use the password to migrate the old vault', function(done) { + this.timeout(5000) + console.log('calling submitPassword') + console.dir(keyringController) + keyringController.submitPassword(password, function (err, state) { + assert.ifError(err, 'submitPassword threw error') + + function log(str, dat) { console.log(str + ': ' + JSON.stringify(dat)) } + + let newAccounts = keyringController.getAccounts() + log('new accounts: ', newAccounts) + + let newAccount = ethUtil.addHexPrefix(newAccounts[0]) + assert.equal(ethUtil.addHexPrefix(newAccount), mockVault.account, 'restored the correct account') + const newSeed = keyringController.keyrings[0].mnemonic + log('keyringController keyrings', keyringController.keyrings) + assert.equal(newSeed, mockVault.seed, 'seed phrase transferred.') + + assert(configManager.getVault(), 'new type of vault is persisted') + done() + }) + }) + */ + + }) +}) + +function loadData () { + var oldData = getOldStyleData() + var newData + try { + newData = JSON.parse(window.localStorage[STORAGE_KEY]) + } catch (e) {} + + var data = extend({ + meta: { + version: 0, + }, + data: { + config: { + provider: { + type: 'testnet', + }, + }, + }, + }, oldData || null, newData || null) + return data +} + +function setData (data) { + window.localStorage[STORAGE_KEY] = JSON.stringify(data) +} + +function getOldStyleData () { + var config, wallet, seedWords + + var result = { + meta: { version: 0 }, + data: {}, + } + + try { + config = JSON.parse(window.localStorage['config']) + result.data.config = config + } catch (e) {} + try { + wallet = JSON.parse(window.localStorage['lightwallet']) + result.data.wallet = wallet + } catch (e) {} + try { + seedWords = window.localStorage['seedWords'] + result.data.seedWords = seedWords + } catch (e) {} + + return result +} diff --git a/test/unit/idStore-test.js b/test/unit/idStore-test.js index bf8270540..3ca89cd38 100644 --- a/test/unit/idStore-test.js +++ b/test/unit/idStore-test.js @@ -11,7 +11,6 @@ describe('IdentityStore', function() { describe('#createNewVault', function () { let idStore let password = 'password123' - let entropy = 'entripppppyy duuude' let seedWords let accounts = [] let originalKeystore @@ -26,7 +25,7 @@ describe('IdentityStore', function() { }, }) - idStore.createNewVault(password, entropy, (err, seeds) => { + idStore.createNewVault(password, (err, seeds) => { assert.ifError(err, 'createNewVault threw error') seedWords = seeds originalKeystore = idStore._idmgmt.keyStore diff --git a/test/unit/keyring-controller-test.js b/test/unit/keyring-controller-test.js new file mode 100644 index 000000000..69a57ef52 --- /dev/null +++ b/test/unit/keyring-controller-test.js @@ -0,0 +1,200 @@ +var assert = require('assert') +var KeyringController = require('../../app/scripts/keyring-controller') +var configManagerGen = require('../lib/mock-config-manager') +const ethUtil = require('ethereumjs-util') +const BN = ethUtil.BN +const async = require('async') +const mockEncryptor = require('../lib/mock-encryptor') +const MockSimpleKeychain = require('../lib/mock-simple-keychain') +const sinon = require('sinon') + +describe('KeyringController', function() { + + let keyringController, state + let password = 'password123' + let seedWords = 'puzzle seed penalty soldier say clay field arctic metal hen cage runway' + let addresses = ['eF35cA8EbB9669A35c31b5F6f249A9941a812AC1'.toLowerCase()] + let accounts = [] + let originalKeystore + + beforeEach(function(done) { + this.sinon = sinon.sandbox.create() + window.localStorage = {} // Hacking localStorage support into JSDom + + keyringController = new KeyringController({ + configManager: configManagerGen(), + ethStore: { + addAccount(acct) { accounts.push(ethUtil.addHexPrefix(acct)) }, + }, + }) + + // Stub out the browser crypto for a mock encryptor. + // Browser crypto is tested in the integration test suite. + keyringController.encryptor = mockEncryptor + + keyringController.createNewVaultAndKeychain(password) + .then(function (newState) { + state = newState + done() + }) + }) + + afterEach(function() { + // Cleanup mocks + this.sinon.restore() + }) + + describe('#createNewVaultAndKeychain', function () { + this.timeout(10000) + + it('should set a vault on the configManager', function(done) { + keyringController.configManager.setVault(null) + assert(!keyringController.configManager.getVault(), 'no previous vault') + keyringController.createNewVaultAndKeychain(password) + .then(() => { + const vault = keyringController.configManager.getVault() + assert(vault, 'vault created') + done() + }) + .catch((reason) => { + assert.ifError(reason) + done() + }) + }) + }) + + describe('#restoreKeyring', function() { + + it(`should pass a keyring's serialized data back to the correct type.`, function(done) { + const mockSerialized = { + type: 'HD Key Tree', + data: { + mnemonic: seedWords, + numberOfAccounts: 1, + } + } + const mock = this.sinon.mock(keyringController) + + mock.expects('getBalanceAndNickname') + .exactly(1) + + keyringController.restoreKeyring(mockSerialized) + .then((keyring) => { + assert.equal(keyring.wallets.length, 1, 'one wallet restored') + return keyring.getAccounts() + }) + .then((accounts) => { + assert.equal(accounts[0], addresses[0]) + mock.verify() + done() + }) + .catch((reason) => { + assert.ifError(reason) + done() + }) + }) + }) + + describe('#migrateOldVaultIfAny', function() { + it('should return and init a new vault', function(done) { + keyringController.migrateOldVaultIfAny(password) + .then(() => { + assert(keyringController.configManager.getVault(), 'now has a vault') + assert(keyringController.password, 'has a password set') + done() + }) + .catch((reason) => { + assert.ifError(reason) + done() + }) + }) + }) + + describe('#createNickname', function() { + it('should add the address to the identities hash', function() { + const fakeAddress = '0x12345678' + keyringController.createNickname(fakeAddress) + const identities = keyringController.identities + const identity = identities[fakeAddress] + assert.equal(identity.address, fakeAddress) + + const nick = keyringController.configManager.nicknameForWallet(fakeAddress) + assert.equal(typeof nick, 'string') + }) + }) + + describe('#saveAccountLabel', function() { + it ('sets the nickname', function(done) { + const account = addresses[0] + var nick = 'Test nickname' + keyringController.identities[ethUtil.addHexPrefix(account)] = {} + keyringController.saveAccountLabel(account, nick) + .then((label) => { + assert.equal(label, nick) + const persisted = keyringController.configManager.nicknameForWallet(account) + assert.equal(persisted, nick) + done() + }) + .catch((reason) => { + assert.ifError(reason) + done() + }) + }) + + this.timeout(10000) + it('retrieves the persisted nickname', function(done) { + const account = addresses[0] + var nick = 'Test nickname' + keyringController.configManager.setNicknameForWallet(account, nick) + keyringController.createNewVaultAndRestore(password, seedWords) + .then((state) => { + + const identity = keyringController.identities['0x' + account] + assert.equal(identity.name, nick) + + assert(accounts) + done() + }) + .catch((reason) => { + assert.ifError(reason) + done() + }) + }) + }) + + describe('#getAccounts', function() { + it('returns the result of getAccounts for each keyring', function() { + keyringController.keyrings = [ + { getAccounts() { return Promise.resolve([1,2,3]) } }, + { getAccounts() { return Promise.resolve([4,5,6]) } }, + ] + + keyringController.getAccounts() + .then((result) => { + assert.deepEqual(result, [1,2,3,4,5,6]) + done() + }) + }) + }) + + describe('#addGasBuffer', function() { + it('adds 100k gas buffer to estimates', function() { + + const gas = '0x04ee59' // Actual estimated gas example + const tooBigOutput = '0x80674f9' // Actual bad output + const bnGas = new BN(ethUtil.stripHexPrefix(gas), 16) + const correctBuffer = new BN('100000', 10) + const correct = bnGas.add(correctBuffer) + + const tooBig = new BN(tooBigOutput, 16) + const result = keyringController.addGasBuffer(gas) + const bnResult = new BN(ethUtil.stripHexPrefix(result), 16) + + assert.equal(result.indexOf('0x'), 0, 'included hex prefix') + assert(bnResult.gt(bnGas), 'Estimate increased in value.') + assert.equal(bnResult.sub(bnGas).toString(10), '100000', 'added 100k gas') + assert.equal(result, '0x' + correct.toString(16), 'Added the right amount') + assert.notEqual(result, tooBigOutput, 'not that bad estimate') + }) + }) +}) diff --git a/test/unit/keyrings/hd-test.js b/test/unit/keyrings/hd-test.js new file mode 100644 index 000000000..dfc0ec908 --- /dev/null +++ b/test/unit/keyrings/hd-test.js @@ -0,0 +1,127 @@ +const assert = require('assert') +const extend = require('xtend') +const HdKeyring = require('../../../app/scripts/keyrings/hd') + +// Sample account: +const privKeyHex = 'b8a9c05beeedb25df85f8d641538cbffedf67216048de9c678ee26260eb91952' + +const sampleMnemonic = 'finish oppose decorate face calm tragic certain desk hour urge dinosaur mango' +const firstAcct = '1c96099350f13d558464ec79b9be4445aa0ef579' +const secondAcct = '1b00aed43a693f3a957f9feb5cc08afa031e37a0' + +describe('hd-keyring', function() { + + let keyring + beforeEach(function() { + keyring = new HdKeyring() + }) + + describe('constructor', function(done) { + keyring = new HdKeyring({ + mnemonic: sampleMnemonic, + numberOfAccounts: 2, + }) + + const accounts = keyring.getAccounts() + .then((accounts) => { + assert.equal(accounts[0], firstAcct) + assert.equal(accounts[1], secondAcct) + done() + }) + }) + + describe('Keyring.type', function() { + it('is a class property that returns the type string.', function() { + const type = HdKeyring.type + assert.equal(typeof type, 'string') + }) + }) + + describe('#type', function() { + it('returns the correct value', function() { + const type = keyring.type + const correct = HdKeyring.type + assert.equal(type, correct) + }) + }) + + describe('#serialize empty wallets.', function() { + it('serializes a new mnemonic', function() { + keyring.serialize() + .then((output) => { + assert.equal(output.numberOfAccounts, 0) + assert.equal(output.mnemonic, null) + }) + }) + }) + + describe('#deserialize a private key', function() { + it('serializes what it deserializes', function(done) { + keyring.deserialize({ + mnemonic: sampleMnemonic, + numberOfAccounts: 1 + }) + .then(() => { + assert.equal(keyring.wallets.length, 1, 'restores two accounts') + return keyring.addAccounts(1) + }).then(() => { + return keyring.getAccounts() + }).then((accounts) => { + assert.equal(accounts[0], firstAcct) + assert.equal(accounts[1], secondAcct) + assert.equal(accounts.length, 2) + + return keyring.serialize() + }).then((serialized) => { + assert.equal(serialized.mnemonic, sampleMnemonic) + done() + }) + }) + }) + + describe('#addAccounts', function() { + describe('with no arguments', function() { + it('creates a single wallet', function(done) { + keyring.addAccounts() + .then(() => { + assert.equal(keyring.wallets.length, 1) + done() + }) + }) + }) + + describe('with a numeric argument', function() { + it('creates that number of wallets', function(done) { + keyring.addAccounts(3) + .then(() => { + assert.equal(keyring.wallets.length, 3) + done() + }) + }) + }) + }) + + describe('#getAccounts', function() { + it('calls getAddress on each wallet', function(done) { + + // Push a mock wallet + const desiredOutput = 'foo' + keyring.wallets.push({ + getAddress() { + return { + toString() { + return desiredOutput + } + } + } + }) + + const output = keyring.getAccounts() + .then((output) => { + assert.equal(output[0], desiredOutput) + assert.equal(output.length, 1) + done() + }) + }) + }) +}) diff --git a/test/unit/keyrings/simple-test.js b/test/unit/keyrings/simple-test.js new file mode 100644 index 000000000..979abdb69 --- /dev/null +++ b/test/unit/keyrings/simple-test.js @@ -0,0 +1,94 @@ +const assert = require('assert') +const extend = require('xtend') +const SimpleKeyring = require('../../../app/scripts/keyrings/simple') +const TYPE_STR = 'Simple Key Pair' + +// Sample account: +const privKeyHex = 'b8a9c05beeedb25df85f8d641538cbffedf67216048de9c678ee26260eb91952' + +describe('simple-keyring', function() { + + let keyring + beforeEach(function() { + keyring = new SimpleKeyring() + }) + + describe('Keyring.type', function() { + it('is a class property that returns the type string.', function() { + const type = SimpleKeyring.type + assert.equal(type, TYPE_STR) + }) + }) + + describe('#type', function() { + it('returns the correct value', function() { + const type = keyring.type + assert.equal(type, TYPE_STR) + }) + }) + + describe('#serialize empty wallets.', function() { + it('serializes an empty array', function(done) { + keyring.serialize() + .then((output) => { + assert.deepEqual(output, []) + done() + }) + }) + }) + + describe('#deserialize a private key', function() { + it('serializes what it deserializes', function() { + keyring.deserialize([privKeyHex]) + .then(() => { + assert.equal(keyring.wallets.length, 1, 'has one wallet') + const serialized = keyring.serialize() + assert.equal(serialized[0], privKeyHex) + }) + }) + }) + + describe('#addAccounts', function() { + describe('with no arguments', function() { + it('creates a single wallet', function() { + keyring.addAccounts() + .then(() => { + assert.equal(keyring.wallets.length, 1) + }) + }) + }) + + describe('with a numeric argument', function() { + it('creates that number of wallets', function() { + keyring.addAccounts(3) + .then(() => { + assert.equal(keyring.wallets.length, 3) + }) + }) + }) + }) + + describe('#getAccounts', function() { + it('calls getAddress on each wallet', function(done) { + + // Push a mock wallet + const desiredOutput = 'foo' + keyring.wallets.push({ + getAddress() { + return { + toString() { + return desiredOutput + } + } + } + }) + + keyring.getAccounts() + .then((output) => { + assert.equal(output[0], desiredOutput) + assert.equal(output.length, 1) + done() + }) + }) + }) +}) diff --git a/test/unit/nodeify-test.js b/test/unit/nodeify-test.js new file mode 100644 index 000000000..a14d34338 --- /dev/null +++ b/test/unit/nodeify-test.js @@ -0,0 +1,22 @@ +const assert = require('assert') +const nodeify = require('../../app/scripts/lib/nodeify') + +describe('nodeify', function() { + + var obj = { + foo: 'bar', + promiseFunc: function (a) { + var solution = this.foo + a + return Promise.resolve(solution) + } + } + + it('should retain original context', function(done) { + var nodified = nodeify(obj.promiseFunc).bind(obj) + nodified('baz', function (err, res) { + assert.equal(res, 'barbaz') + done() + }) + }) + +}) diff --git a/testem.yml b/testem.yml index 7923a2929..2cf40f7f4 100644 --- a/testem.yml +++ b/testem.yml @@ -6,4 +6,5 @@ launch_in_ci: - Firefox framework: - qunit +before_tests: "npm run buildCiUnits" test_page: "test/integration/index.html" @@ -25,7 +25,7 @@ const Selector = require('./development/selector') // Query String const qs = require('qs') let queryString = qs.parse(window.location.href.split('#')[1]) -let selectedView = queryString.view || 'account detail' +let selectedView = queryString.view || 'first time' const firstState = states[selectedView] updateQueryParams(selectedView) @@ -41,7 +41,7 @@ function updateQueryParams(newView) { } const actions = { - _setAccountManager(){}, + _setBackgroundConnection(){}, update: function(stateName) { selectedView = stateName updateQueryParams(stateName) diff --git a/ui/app/account-detail.js b/ui/app/account-detail.js index 01c7e8781..c41ba61fd 100644 --- a/ui/app/account-detail.js +++ b/ui/app/account-detail.js @@ -30,7 +30,6 @@ function mapStateToProps (state) { network: state.metamask.network, unconfTxs: valuesFor(state.metamask.unconfTxs), unconfMsgs: valuesFor(state.metamask.unconfMsgs), - isEthWarningConfirmed: state.metamask.isEthConfirmed, shapeShiftTxList: state.metamask.shapeShiftTxList, } } diff --git a/ui/app/accounts/account-list-item.js b/ui/app/accounts/account-list-item.js index 4e0d69ed7..ef7b749e4 100644 --- a/ui/app/accounts/account-list-item.js +++ b/ui/app/accounts/account-list-item.js @@ -16,7 +16,7 @@ function AccountListItem () { AccountListItem.prototype.render = function () { const identity = this.props.identity - var isSelected = this.props.selectedAddress === identity.address + var isSelected = this.props.selectedAccount === identity.address var account = this.props.accounts[identity.address] const selectedClass = isSelected ? '.selected' : '' diff --git a/ui/app/accounts/index.js b/ui/app/accounts/index.js index 7551c498e..fcb3a7b0f 100644 --- a/ui/app/accounts/index.js +++ b/ui/app/accounts/index.js @@ -19,7 +19,7 @@ function mapStateToProps (state) { accounts: state.metamask.accounts, identities: state.metamask.identities, unconfTxs: state.metamask.unconfTxs, - selectedAddress: state.metamask.selectedAddress, + selectedAccount: state.metamask.selectedAccount, scrollToBottom: state.appState.scrollToBottom, pending, } @@ -34,11 +34,7 @@ AccountsScreen.prototype.render = function () { var state = this.props var identityList = valuesFor(state.identities) var unconfTxList = valuesFor(state.unconfTxs) - var actions = { - onSelect: this.onSelect.bind(this), - onShowDetail: this.onShowDetail.bind(this), - goHome: this.goHome.bind(this), - } + return ( h('.accounts-section.flex-grow', [ @@ -46,7 +42,7 @@ AccountsScreen.prototype.render = function () { // subtitle and nav h('.section-title.flex-center', [ h('i.fa.fa-arrow-left.fa-lg.cursor-pointer', { - onClick: actions.goHome, + onClick: this.goHome.bind(this), }), h('h2.page-subtitle', 'Select Account'), ]), @@ -76,7 +72,7 @@ AccountsScreen.prototype.render = function () { return h(AccountListItem, { key: `acct-panel-${identity.address}`, identity, - selectedAddress: this.props.selectedAddress, + selectedAccount: this.props.selectedAccount, accounts: this.props.accounts, onShowDetail: this.onShowDetail.bind(this), pending, @@ -87,7 +83,7 @@ AccountsScreen.prototype.render = function () { h('div.footer.hover-white.pointer', { key: 'reveal-account-bar', onClick: () => { - this.onRevealAccount() + this.addNewAccount() }, style: { display: 'flex', @@ -137,8 +133,8 @@ AccountsScreen.prototype.navigateToConfTx = function () { AccountsScreen.prototype.onSelect = function (address, event) { event.stopPropagation() // if already selected, deselect - if (this.props.selectedAddress === address) address = null - this.props.dispatch(actions.setSelectedAddress(address)) + if (this.props.selectedAccount === address) address = null + this.props.dispatch(actions.setSelectedAccount(address)) } AccountsScreen.prototype.onShowDetail = function (address, event) { @@ -146,8 +142,8 @@ AccountsScreen.prototype.onShowDetail = function (address, event) { this.props.dispatch(actions.showAccountDetail(address)) } -AccountsScreen.prototype.onRevealAccount = function () { - this.props.dispatch(actions.revealAccount()) +AccountsScreen.prototype.addNewAccount = function () { + this.props.dispatch(actions.addNewAccount(0)) } AccountsScreen.prototype.goHome = function () { diff --git a/ui/app/actions.js b/ui/app/actions.js index 07df5ada2..58600dd34 100644 --- a/ui/app/actions.js +++ b/ui/app/actions.js @@ -1,9 +1,15 @@ var actions = { + _setBackgroundConnection: _setBackgroundConnection, + GO_HOME: 'GO_HOME', goHome: goHome, // menu state getNetworkStatus: 'getNetworkStatus', - + // transition state + TRANSITION_FORWARD: 'TRANSITION_FORWARD', + TRANSITION_BACKWARD: 'TRANSITION_BACKWARD', + transitionForward, + transitionBackward, // remote state UPDATE_METAMASK_STATE: 'UPDATE_METAMASK_STATE', updateMetamaskState: updateMetamaskState, @@ -23,17 +29,16 @@ var actions = { SHOW_INIT_MENU: 'SHOW_INIT_MENU', SHOW_NEW_VAULT_SEED: 'SHOW_NEW_VAULT_SEED', SHOW_INFO_PAGE: 'SHOW_INFO_PAGE', - RECOVER_FROM_SEED: 'RECOVER_FROM_SEED', - CLEAR_SEED_WORD_CACHE: 'CLEAR_SEED_WORD_CACHE', - clearSeedWordCache: clearSeedWordCache, - recoverFromSeed: recoverFromSeed, unlockMetamask: unlockMetamask, unlockFailed: unlockFailed, showCreateVault: showCreateVault, showRestoreVault: showRestoreVault, showInitializeMenu: showInitializeMenu, - createNewVault: createNewVault, + createNewVaultAndKeychain: createNewVaultAndKeychain, + createNewVaultAndRestore: createNewVaultAndRestore, createNewVaultInProgress: createNewVaultInProgress, + addNewKeyring, + addNewAccount, showNewVaultSeed: showNewVaultSeed, showInfoPage: showInfoPage, // seed recovery actions @@ -59,8 +64,6 @@ var actions = { SHOW_ACCOUNTS_PAGE: 'SHOW_ACCOUNTS_PAGE', SHOW_CONF_TX_PAGE: 'SHOW_CONF_TX_PAGE', SHOW_CONF_MSG_PAGE: 'SHOW_CONF_MSG_PAGE', - REVEAL_ACCOUNT: 'REVEAL_ACCOUNT', - revealAccount: revealAccount, SET_CURRENT_FIAT: 'SET_CURRENT_FIAT', setCurrentFiat: setCurrentFiat, // account detail screen @@ -74,16 +77,12 @@ var actions = { showPrivateKey: showPrivateKey, SAVE_ACCOUNT_LABEL: 'SAVE_ACCOUNT_LABEL', saveAccountLabel: saveAccountLabel, - AGREE_TO_ETH_WARNING: 'AGREE_TO_ETH_WARNING', - agreeToEthWarning: agreeToEthWarning, - SHOW_ETH_WARNING: 'SHOW_ETH_WARNING', - showEthWarning: showEthWarning, // tx conf screen COMPLETED_TX: 'COMPLETED_TX', TRANSACTION_ERROR: 'TRANSACTION_ERROR', NEXT_TX: 'NEXT_TX', PREVIOUS_TX: 'PREV_TX', - setSelectedAddress: setSelectedAddress, + setSelectedAccount: setSelectedAccount, signMsg: signMsg, cancelMsg: cancelMsg, sendTx: sendTx, @@ -96,12 +95,12 @@ var actions = { viewPendingTx: viewPendingTx, VIEW_PENDING_TX: 'VIEW_PENDING_TX', // app messages + confirmSeedWords: confirmSeedWords, showAccountDetail: showAccountDetail, BACK_TO_ACCOUNT_DETAIL: 'BACK_TO_ACCOUNT_DETAIL', backToAccountDetail: backToAccountDetail, showAccountsPage: showAccountsPage, showConfTxPage: showConfTxPage, - confirmSeedWords: confirmSeedWords, // config screen SHOW_CONFIG_PAGE: 'SHOW_CONFIG_PAGE', SET_RPC_TARGET: 'SET_RPC_TARGET', @@ -111,8 +110,6 @@ var actions = { showConfigPage: showConfigPage, setRpcTarget: setRpcTarget, setProviderType: setProviderType, - // hacky - need a way to get a reference to account manager - _setAccountManager: _setAccountManager, // loading overlay SHOW_LOADING: 'SHOW_LOADING_INDICATION', HIDE_LOADING: 'HIDE_LOADING_INDICATION', @@ -149,13 +146,18 @@ var actions = { RECOVERY_IN_PROGRESS: 'RECOVERY_IN_PROGRESS', BACK_TO_UNLOCK_VIEW: 'BACK_TO_UNLOCK_VIEW', backToUnlockView: backToUnlockView, + // SHOWING KEYCHAIN + SHOW_NEW_KEYCHAIN: 'SHOW_NEW_KEYCHAIN', + showNewKeychain: showNewKeychain, + + } module.exports = actions -var _accountManager = null -function _setAccountManager (accountManager) { - _accountManager = accountManager +var background = null +function _setBackgroundConnection (backgroundConnection) { + background = backgroundConnection } function goHome () { @@ -170,25 +172,63 @@ function tryUnlockMetamask (password) { return (dispatch) => { dispatch(actions.showLoadingIndication()) dispatch(actions.unlockInProgress()) - _accountManager.submitPassword(password, (err, selectedAccount) => { + background.submitPassword(password, (err, newState) => { dispatch(actions.hideLoadingIndication()) if (err) { - dispatch(actions.unlockFailed()) + dispatch(actions.unlockFailed(err.message)) } else { - dispatch(actions.unlockMetamask(selectedAccount)) + dispatch(actions.transitionForward()) + dispatch(actions.updateMetamaskState(newState)) } }) } } -function createNewVault (password, entropy) { +function transitionForward() { + return { + type: this.TRANSITION_FORWARD, + } +} + +function transitionBackward() { + return { + type: this.TRANSITION_BACKWARD, + } +} + +function confirmSeedWords () { return (dispatch) => { - dispatch(actions.createNewVaultInProgress()) - _accountManager.createNewVault(password, entropy, (err, result) => { + dispatch(actions.showLoadingIndication()) + background.clearSeedWordCache((err, account) => { + dispatch(actions.hideLoadingIndication()) if (err) { return dispatch(actions.displayWarning(err.message)) } - dispatch(actions.showNewVaultSeed(result)) + + console.log('Seed word cache cleared. ' + account) + dispatch(actions.showAccountDetail(account)) + }) + } +} + +function createNewVaultAndRestore (password, seed) { + return (dispatch) => { + dispatch(actions.showLoadingIndication()) + background.createNewVaultAndRestore(password, seed, (err) => { + dispatch(actions.hideLoadingIndication()) + if (err) return dispatch(actions.displayWarning(err.message)) + dispatch(actions.showAccountsPage()) + }) + } +} + +function createNewVaultAndKeychain (password) { + return (dispatch) => { + background.createNewVaultAndKeychain(password, (err, newState) => { + if (err) { + return dispatch(actions.showWarning(err.message)) + } + dispatch(actions.updateMetamaskState(newState)) }) } } @@ -202,27 +242,37 @@ function revealSeedConfirmation () { function requestRevealSeed (password) { return (dispatch) => { dispatch(actions.showLoadingIndication()) - _accountManager.tryPassword(password, (err, seed) => { - dispatch(actions.hideLoadingIndication()) + background.submitPassword(password, (err) => { if (err) return dispatch(actions.displayWarning(err.message)) - _accountManager.recoverSeed((err, seed) => { + background.placeSeedWords((err) => { if (err) return dispatch(actions.displayWarning(err.message)) - dispatch(actions.showNewVaultSeed(seed)) + dispatch(actions.hideLoadingIndication()) }) }) } } -function recoverFromSeed (password, seed) { + +function addNewKeyring (type, opts) { return (dispatch) => { - // dispatch(actions.createNewVaultInProgress()) dispatch(actions.showLoadingIndication()) - _accountManager.recoverFromSeed(password, seed, (err, metamaskState) => { - dispatch(actions.hideLoadingIndication()) - if (err) return dispatch(actions.displayWarning(err.message)) + background.addNewKeyring(type, opts, (err) => { + dispatch(this.hideLoadingIndication()) + if (err) { + return dispatch(actions.showWarning(err)) + } + }) + } +} - var account = Object.keys(metamaskState.identities)[0] - dispatch(actions.unlockMetamask(account)) +function addNewAccount (ringNumber = 0) { + return (dispatch) => { + dispatch(actions.showLoadingIndication()) + background.addNewAccount(ringNumber, (err) => { + dispatch(this.hideLoadingIndication()) + if (err) { + return dispatch(actions.showWarning(err)) + } }) } } @@ -233,29 +283,16 @@ function showInfoPage () { } } -function setSelectedAddress (address) { +function setSelectedAccount (address) { return (dispatch) => { - _accountManager.setSelectedAddress(address) - } -} - -function revealAccount () { - return (dispatch) => { - dispatch(actions.showLoadingIndication()) - _accountManager.revealAccount((err) => { - dispatch(actions.hideLoadingIndication()) - if (err) return dispatch(actions.displayWarning(err.message)) - dispatch({ - type: actions.REVEAL_ACCOUNT, - }) - }) + background.setSelectedAccount(address) } } function setCurrentFiat (fiat) { return (dispatch) => { dispatch(this.showLoadingIndication()) - _accountManager.setCurrentFiat(fiat, (data, err) => { + background.setCurrentFiat(fiat, (data, err) => { dispatch(this.hideLoadingIndication()) dispatch({ type: this.SET_CURRENT_FIAT, @@ -273,7 +310,7 @@ function signMsg (msgData) { return (dispatch) => { dispatch(actions.showLoadingIndication()) - _accountManager.signMessage(msgData, (err) => { + background.signMessage(msgData, (err) => { dispatch(actions.hideLoadingIndication()) if (err) return dispatch(actions.displayWarning(err.message)) @@ -284,7 +321,7 @@ function signMsg (msgData) { function signTx (txData) { return (dispatch) => { - _accountManager.setGasMultiplier(txData.gasMultiplier, (err) => { + background.setGasMultiplier(txData.gasMultiplier, (err) => { if (err) return dispatch(actions.displayWarning(err.message)) web3.eth.sendTransaction(txData, (err, data) => { dispatch(actions.hideLoadingIndication()) @@ -299,7 +336,7 @@ function signTx (txData) { function sendTx (txData) { return (dispatch) => { - _accountManager.approveTransaction(txData.id, (err) => { + background.approveTransaction(txData.id, (err) => { if (err) { alert(err.message) dispatch(actions.txError(err)) @@ -325,12 +362,12 @@ function txError (err) { } function cancelMsg (msgData) { - _accountManager.cancelMessage(msgData.id) + background.cancelMessage(msgData.id) return actions.completedTx(msgData.id) } function cancelTx (txData) { - _accountManager.cancelTransaction(txData.id) + background.cancelTransaction(txData.id) return actions.completedTx(txData.id) } @@ -359,7 +396,7 @@ function showInitializeMenu () { function agreeToDisclaimer () { return (dispatch) => { dispatch(this.showLoadingIndication()) - _accountManager.agreeToDisclaimer((err) => { + background.agreeToDisclaimer((err) => { if (err) { return dispatch(actions.displayWarning(err.message)) } @@ -391,6 +428,12 @@ function backToUnlockView () { } } +function showNewKeychain () { + return { + type: actions.SHOW_NEW_KEYCHAIN, + } +} + // // unlock screen // @@ -401,9 +444,10 @@ function unlockInProgress () { } } -function unlockFailed () { +function unlockFailed (message) { return { type: actions.UNLOCK_FAILED, + value: message, } } @@ -423,15 +467,12 @@ function updateMetamaskState (newState) { function lockMetamask () { return (dispatch) => { - _accountManager.setLocked((err) => { + background.setLocked((err, newState) => { dispatch(actions.hideLoadingIndication()) if (err) { return dispatch(actions.displayWarning(err.message)) } - - dispatch({ - type: actions.LOCK_METAMASK, - }) + dispatch(actions.updateMetamaskState(newState)) }) } } @@ -439,7 +480,7 @@ function lockMetamask () { function showAccountDetail (address) { return (dispatch) => { dispatch(actions.showLoadingIndication()) - _accountManager.setSelectedAddress(address, (err, address) => { + background.setSelectedAccount(address, (err, address) => { dispatch(actions.hideLoadingIndication()) if (err) { return dispatch(actions.displayWarning(err.message)) @@ -459,27 +500,6 @@ function backToAccountDetail (address) { value: address, } } -function clearSeedWordCache (account) { - return { - type: actions.CLEAR_SEED_WORD_CACHE, - value: account, - } -} - -function confirmSeedWords () { - return (dispatch) => { - dispatch(actions.showLoadingIndication()) - _accountManager.clearSeedWordCache((err, account) => { - dispatch(actions.hideLoadingIndication()) - if (err) { - return dispatch(actions.displayWarning(err.message)) - } - - console.log('Seed word cache cleared. ' + account) - dispatch(actions.showAccountDetail(account)) - }) - } -} function showAccountsPage () { return { @@ -533,7 +553,7 @@ function goBackToInitView () { function markNoticeRead (notice) { return (dispatch) => { dispatch(this.showLoadingIndication()) - _accountManager.markNoticeRead(notice, (err, notice) => { + background.markNoticeRead(notice, (err, notice) => { dispatch(this.hideLoadingIndication()) if (err) { return dispatch(actions.showWarning(err)) @@ -568,7 +588,7 @@ function clearNotices () { // function setRpcTarget (newRpc) { - _accountManager.setRpcTarget(newRpc) + background.setRpcTarget(newRpc) return { type: actions.SET_RPC_TARGET, value: newRpc, @@ -576,7 +596,7 @@ function setRpcTarget (newRpc) { } function setProviderType (type) { - _accountManager.setProviderType(type) + background.setProviderType(type) return { type: actions.SET_PROVIDER_TYPE, value: type, @@ -584,7 +604,7 @@ function setProviderType (type) { } function useEtherscanProvider () { - _accountManager.useEtherscanProvider() + background.useEtherscanProvider() return { type: actions.USE_ETHERSCAN_PROVIDER, } @@ -639,7 +659,7 @@ function exportAccount (address) { return function (dispatch) { dispatch(self.showLoadingIndication()) - _accountManager.exportAccount(address, function (err, result) { + background.exportAccount(address, function (err, result) { dispatch(self.hideLoadingIndication()) if (err) { @@ -662,7 +682,7 @@ function showPrivateKey (key) { function saveAccountLabel (account, label) { return (dispatch) => { dispatch(actions.showLoadingIndication()) - _accountManager.saveAccountLabel(account, label, (err) => { + background.saveAccountLabel(account, label, (err) => { dispatch(actions.hideLoadingIndication()) if (err) { return dispatch(actions.displayWarning(err.message)) @@ -681,28 +701,9 @@ function showSendPage () { } } -function agreeToEthWarning () { - return (dispatch) => { - _accountManager.agreeToEthWarning((err) => { - if (err) { - return dispatch(actions.showEthWarning(err.message)) - } - dispatch({ - type: actions.AGREE_TO_ETH_WARNING, - }) - }) - } -} - -function showEthWarning () { - return { - type: actions.SHOW_ETH_WARNING, - } -} - function buyEth (address, amount) { return (dispatch) => { - _accountManager.buyEth(address, amount) + background.buyEth(address, amount) dispatch({ type: actions.BUY_ETH, }) @@ -780,7 +781,7 @@ function coinShiftRquest (data, marketData) { if (response.error) return dispatch(actions.displayWarning(response.error)) var message = ` Deposit your ${response.depositType} to the address bellow:` - _accountManager.createShapeShiftTx(response.deposit, response.depositType) + background.createShapeShiftTx(response.deposit, response.depositType) dispatch(actions.showQrView(response.deposit, [message].concat(marketData))) }) } diff --git a/ui/app/app.js b/ui/app/app.js index 422b3739c..2fa6415dd 100644 --- a/ui/app/app.js +++ b/ui/app/app.js @@ -7,9 +7,7 @@ const ReactCSSTransitionGroup = require('react-addons-css-transition-group') // init const DisclaimerScreen = require('./first-time/disclaimer') const InitializeMenuScreen = require('./first-time/init-menu') -const CreateVaultScreen = require('./first-time/create-vault') -const CreateVaultCompleteScreen = require('./first-time/create-vault-complete') -const RestoreVaultScreen = require('./first-time/restore-vault') +const NewKeyChainScreen = require('./new-keychain') // unlock const UnlockScreen = require('./unlock') // accounts @@ -21,7 +19,6 @@ const ConfirmTxScreen = require('./conf-tx') const NoticeScreen = require('./notice') // other views const ConfigScreen = require('./config') -const RevealSeedConfirmation = require('./recover-seed/confirmation') const InfoScreen = require('./info') const LoadingIndicator = require('./components/loading') const SandwichExpando = require('sandwich-expando') @@ -29,9 +26,12 @@ const MenuDroppo = require('menu-droppo') const DropMenuItem = require('./components/drop-menu-item') const NetworkIndicator = require('./components/network') const Tooltip = require('./components/tooltip') -const EthStoreWarning = require('./eth-store-warning') const BuyView = require('./components/buy-button-subview') const QrView = require('./components/qr-code') +const HDCreateVaultComplete = require('./keychains/hd/create-vault-complete') +const HDRestoreVaultScreen = require('./keychains/hd/restore-vault') +const RevealSeedConfirmation = require('./keychains/hd/recover-seed/confirmation') + module.exports = connect(mapStateToProps)(App) inherits(App, Component) @@ -41,8 +41,7 @@ function mapStateToProps (state) { return { // state from plugin isLoading: state.appState.isLoading, - isConfirmed: state.metamask.isConfirmed, - isEthConfirmed: state.metamask.isEthConfirmed, + isDisclaimerConfirmed: state.metamask.isDisclaimerConfirmed, noActiveNotices: state.metamask.noActiveNotices, isInitialized: state.metamask.isInitialized, isUnlocked: state.metamask.isUnlocked, @@ -94,7 +93,6 @@ App.prototype.render = function () { transitionLeaveTimeout: 300, }, [ this.renderPrimary(), - this.renderBackToInitButton(), ]), ]), ]) @@ -102,7 +100,6 @@ App.prototype.render = function () { } App.prototype.renderAppBar = function () { - if (window.METAMASK_UI_TYPE === 'notification') { return null } @@ -254,7 +251,15 @@ App.prototype.renderNetworkDropdown = function () { activeNetworkRender: props.provider.rpcTarget, }), - this.renderCustomOption(props.provider.rpcTarget), + this.renderCustomOption(props.provider), + + h(DropMenuItem, { + label: 'Custom RPC', + closeMenu: () => this.setState({ isNetworkMenuOpen: false }), + action: () => this.props.dispatch(actions.showConfigPage()), + icon: h('i.fa.fa-question-circle.fa-lg'), + }), + ]) } @@ -305,6 +310,7 @@ App.prototype.renderDropdown = function () { }), ]) } + App.prototype.renderBackButton = function (style, justArrow = false) { var props = this.props return ( @@ -322,85 +328,17 @@ App.prototype.renderBackButton = function (style, justArrow = false) { }, 'BACK'), ]) ) - -} -App.prototype.renderBackToInitButton = function () { - var props = this.props - var button = null - if (!props.isConfirmed) return button - if (!props.isUnlocked) { - if (props.currentView.name === 'InitMenu') { - button = props.forgottenPassword ? h('.flex-row', { - key: 'rightArrow', - style: { - position: 'absolute', - bottom: '10px', - right: '15px', - fontSize: '21px', - fontFamily: 'Montserrat Light', - color: '#7F8082', - width: '77.578px', - alignItems: 'flex-end', - }, - }, [ - h('div.cursor-pointer', { - style: { - marginRight: '3px', - }, - onClick: () => props.dispatch(actions.backToUnlockView()), - }, 'LOGIN'), - h('i.fa.fa-arrow-right.cursor-pointer'), - ]) : null - } else if (props.isInitialized) { - var style - switch (props.currentView.name) { - case 'createVault': - style = { - position: 'absolute', - top: '41px', - left: '80px', - fontSize: '21px', - fontFamily: 'Montserrat Bold', - color: 'rgb(174, 174, 174)', - } - return this.renderBackButton(style, true) - case 'restoreVault': - style = { - position: 'absolute', - top: '41px', - left: '70px', - fontSize: '21px', - fontFamily: 'Montserrat Bold', - color: 'rgb(174, 174, 174)', - } - return this.renderBackButton(style, true) - default: - style = { - position: 'absolute', - bottom: '10px', - left: '15px', - fontSize: '21px', - fontFamily: 'Montserrat Light', - color: '#7F8082', - width: '71.969px', - alignItems: 'flex-end', - } - return this.renderBackButton(style) - } - } - } - return button } App.prototype.renderPrimary = function () { var props = this.props - if (!props.isConfirmed) { + if (!props.isDisclaimerConfirmed) { return h(DisclaimerScreen, {key: 'disclaimerScreen'}) } if (props.seedWords) { - return h(CreateVaultCompleteScreen, {key: 'createVaultComplete'}) + return h(HDCreateVaultComplete, {key: 'HDCreateVaultComplete'}) } // show initialize screen @@ -408,24 +346,24 @@ App.prototype.renderPrimary = function () { // show current view switch (props.currentView.name) { - case 'createVault': - return h(CreateVaultScreen, {key: 'createVault'}) - case 'restoreVault': - return h(RestoreVaultScreen, {key: 'restoreVault'}) - - case 'createVaultComplete': - return h(CreateVaultCompleteScreen, {key: 'createVaultComplete'}) + return h(HDRestoreVaultScreen, {key: 'HDRestoreVaultScreen'}) default: return h(InitializeMenuScreen, {key: 'menuScreenInit'}) - } } // show unlock screen if (!props.isUnlocked) { - return h(UnlockScreen, {key: 'locked'}) + switch (props.currentView.name) { + + case 'restoreVault': + return h(HDRestoreVaultScreen, {key: 'HDRestoreVaultScreen'}) + + default: + return h(UnlockScreen, {key: 'locked'}) + } } if (!props.noActiveNotices) { @@ -434,8 +372,6 @@ App.prototype.renderPrimary = function () { // show current view switch (props.currentView.name) { - case 'EthStoreWarning': - return h(EthStoreWarning, {key: 'ethWarning'}) case 'accounts': return h(AccountsScreen, {key: 'accounts'}) @@ -446,6 +382,9 @@ App.prototype.renderPrimary = function () { case 'sendTransaction': return h(SendTransactionScreen, {key: 'send-transaction'}) + case 'newKeychain': + return h(NewKeyChainScreen, {key: 'new-keychain'}) + case 'confTx': return h(ConfirmTxScreen, {key: 'confirm-tx'}) @@ -458,10 +397,9 @@ App.prototype.renderPrimary = function () { case 'info': return h(InfoScreen, {key: 'info'}) - case 'createVault': - return h(CreateVaultScreen, {key: 'createVault'}) case 'buyEth': return h(BuyView, {key: 'buyEthView'}) + case 'qr': return h('div', { style: { @@ -506,23 +444,14 @@ App.prototype.toggleMetamaskActive = function () { } } -App.prototype.renderCustomOption = function (rpcTarget) { +App.prototype.renderCustomOption = function (provider) { + const { rpcTarget, type } = provider + if (type !== 'rpc') return null + switch (rpcTarget) { - case undefined: - return h(DropMenuItem, { - label: 'Custom RPC', - closeMenu: () => this.setState({ isNetworkMenuOpen: false }), - action: () => this.props.dispatch(actions.showConfigPage()), - icon: h('i.fa.fa-question-circle.fa-lg'), - }) case 'http://localhost:8545': - return h(DropMenuItem, { - label: 'Custom RPC', - closeMenu: () => this.setState({ isNetworkMenuOpen: false }), - action: () => this.props.dispatch(actions.showConfigPage()), - icon: h('i.fa.fa-question-circle.fa-lg'), - }) + return null default: return h(DropMenuItem, { diff --git a/ui/app/components/coinbase-form.js b/ui/app/components/coinbase-form.js index 3c5708bf8..693eb2ea8 100644 --- a/ui/app/components/coinbase-form.js +++ b/ui/app/components/coinbase-form.js @@ -7,7 +7,7 @@ const actions = require('../actions') const isValidAddress = require('../util').isValidAddress module.exports = connect(mapStateToProps)(CoinbaseForm) -function mapStateToProps(state) { +function mapStateToProps (state) { return { selectedAccount: state.selectedAccount, warning: state.appState.warning, @@ -16,7 +16,7 @@ function mapStateToProps(state) { inherits(CoinbaseForm, Component) -function CoinbaseForm() { +function CoinbaseForm () { Component.call(this) } @@ -124,7 +124,6 @@ CoinbaseForm.prototype.toCoinbase = function () { } CoinbaseForm.prototype.renderLoading = function () { - return h('img', { style: { width: '27px', @@ -134,9 +133,8 @@ CoinbaseForm.prototype.renderLoading = function () { }) } -function isValidAmountforCoinBase(amount) { +function isValidAmountforCoinBase (amount) { amount = parseFloat(amount) - if (amount) { if (amount <= 5 && amount > 0) { return { diff --git a/ui/app/components/copyButton.js b/ui/app/components/copyButton.js index a01603585..a25d0719c 100644 --- a/ui/app/components/copyButton.js +++ b/ui/app/components/copyButton.js @@ -50,12 +50,10 @@ CopyButton.prototype.render = function () { ]) } -CopyButton.prototype.debounceRestore = function() { - +CopyButton.prototype.debounceRestore = function () { this.setState({ copied: true }) clearTimeout(this.timeout) this.timeout = setTimeout(() => { this.setState({ copied: false }) }, 850) - } diff --git a/ui/app/components/drop-menu-item.js b/ui/app/components/drop-menu-item.js index ac0aecadd..9f002234e 100644 --- a/ui/app/components/drop-menu-item.js +++ b/ui/app/components/drop-menu-item.js @@ -32,9 +32,9 @@ DropMenuItem.prototype.render = function () { } DropMenuItem.prototype.activeNetworkRender = function () { - let activeNetwork = this.props.activeNetworkRender - let { provider } = this.props - let providerType = provider ? provider.type : null + const activeNetwork = this.props.activeNetworkRender + const { provider } = this.props + const providerType = provider ? provider.type : null if (activeNetwork === undefined) return switch (this.props.label) { diff --git a/ui/app/components/identicon.js b/ui/app/components/identicon.js index 4b2bf899e..6d4871d02 100644 --- a/ui/app/components/identicon.js +++ b/ui/app/components/identicon.js @@ -16,8 +16,8 @@ function IdenticonComponent () { } IdenticonComponent.prototype.render = function () { - var state = this.props - var diameter = state.diameter || this.defaultDiameter + var props = this.props + var diameter = props.diameter || this.defaultDiameter return ( h('div', { key: 'identicon-' + this.props.address, @@ -33,15 +33,31 @@ IdenticonComponent.prototype.render = function () { } IdenticonComponent.prototype.componentDidMount = function () { - var state = this.props - var address = state.address + var props = this.props + var address = props.address if (!address) return var container = findDOMNode(this) - var diameter = state.diameter || this.defaultDiameter - var imageify = state.imageify === undefined ? true : state.imageify - var img = iconFactory.iconForAddress(address, diameter, imageify) + var diameter = props.diameter || this.defaultDiameter + var img = iconFactory.iconForAddress(address, diameter, false) container.appendChild(img) } +IdenticonComponent.prototype.componentDidUpdate = function () { + var props = this.props + var address = props.address + + if (!address) return + + var container = findDOMNode(this) + + var children = container.children + for (var i = 0; i < children.length; i++) { + container.removeChild(children[i]) + } + + var diameter = props.diameter || this.defaultDiameter + var img = iconFactory.iconForAddress(address, diameter, false) + container.appendChild(img) +} diff --git a/ui/app/components/network.js b/ui/app/components/network.js index 1f61ef73f..43dc747b3 100644 --- a/ui/app/components/network.js +++ b/ui/app/components/network.js @@ -22,7 +22,6 @@ Network.prototype.render = function () { let iconName, hoverText if (networkNumber === 'loading') { - return h('img.network-indicator', { title: 'Attempting to connect to blockchain.', onClick: (event) => this.props.onClick(event), @@ -32,7 +31,6 @@ Network.prototype.render = function () { }, src: 'images/loading.svg', }) - } else if (providerName === 'mainnet') { hoverText = 'Main Ethereum Network' iconName = 'ethereum-network' diff --git a/ui/app/components/pending-msg-details.js b/ui/app/components/pending-msg-details.js index 16308d121..404cb8ae2 100644 --- a/ui/app/components/pending-msg-details.js +++ b/ui/app/components/pending-msg-details.js @@ -16,7 +16,7 @@ PendingMsgDetails.prototype.render = function () { var msgData = state.txData var msgParams = msgData.msgParams || {} - var address = msgParams.from || state.selectedAddress + var address = msgParams.from || state.selectedAccount var identity = state.identities[address] || { address: address } var account = state.accounts[address] || { address: address } diff --git a/ui/app/components/pending-tx-details.js b/ui/app/components/pending-tx-details.js index 545302098..89472b221 100644 --- a/ui/app/components/pending-tx-details.js +++ b/ui/app/components/pending-tx-details.js @@ -24,7 +24,7 @@ PTXP.render = function () { var txData = props.txData var txParams = txData.txParams || {} - var address = txParams.from || props.selectedAddress + var address = txParams.from || props.selectedAccount var identity = props.identities[address] || { address: address } var account = props.accounts[address] var balance = account ? account.balance : '0x0' @@ -154,8 +154,6 @@ PTXP.render = function () { ]), ]), // End of Table - this.warnIfNeeded(), - ]) ) } @@ -201,29 +199,6 @@ PTXP.miniAccountPanelForRecipient = function () { } } -// Should analyze if there is a DELEGATECALL opcode -// in the recipient contract, and show a warning if so. -PTXP.warnIfNeeded = function () { - const containsDelegateCall = !!this.props.txData.containsDelegateCall - - if (!containsDelegateCall) { - return null - } - - return h('span.error', { - style: { - fontFamily: 'Montserrat Light', - fontSize: '13px', - display: 'flex', - justifyContent: 'center', - }, - }, [ - h('i.fa.fa-lg.fa-info-circle', { style: { margin: '5px' } }), - h('span', ' Your identity may be used in other contracts!'), - ]) -} - - function forwardCarrat () { return ( diff --git a/ui/app/components/shapeshift-form.js b/ui/app/components/shapeshift-form.js index 1da549288..383d5b623 100644 --- a/ui/app/components/shapeshift-form.js +++ b/ui/app/components/shapeshift-form.js @@ -8,7 +8,7 @@ const Qr = require('./qr-code') const isValidAddress = require('../util').isValidAddress module.exports = connect(mapStateToProps)(ShapeshiftForm) -function mapStateToProps(state) { +function mapStateToProps (state) { return { selectedAccount: state.selectedAccount, warning: state.appState.warning, @@ -25,7 +25,6 @@ function ShapeshiftForm () { } ShapeshiftForm.prototype.render = function () { - return h(ReactCSSTransitionGroup, { className: 'css-transition-group', transitionName: 'main', @@ -34,7 +33,6 @@ ShapeshiftForm.prototype.render = function () { }, [ this.props.qrRequested ? h(Qr, {key: 'qr'}) : this.renderMain(), ]) - } ShapeshiftForm.prototype.renderMain = function () { diff --git a/ui/app/components/shift-list-item.js b/ui/app/components/shift-list-item.js index 38c19eb28..e0243e247 100644 --- a/ui/app/components/shift-list-item.js +++ b/ui/app/components/shift-list-item.js @@ -26,7 +26,6 @@ function ShiftListItem () { } ShiftListItem.prototype.render = function () { - return ( h('.transaction-list-item.flex-row', { style: { diff --git a/ui/app/components/tooltip.js b/ui/app/components/tooltip.js index 757ad0cd6..edbc074bb 100644 --- a/ui/app/components/tooltip.js +++ b/ui/app/components/tooltip.js @@ -11,7 +11,6 @@ function Tooltip () { } Tooltip.prototype.render = function () { - const props = this.props const { position, title, children } = props @@ -20,5 +19,4 @@ Tooltip.prototype.render = function () { title, fixed: false, }, children) - } diff --git a/ui/app/components/transaction-list-item.js b/ui/app/components/transaction-list-item.js index 491e90c7c..d1306549e 100644 --- a/ui/app/components/transaction-list-item.js +++ b/ui/app/components/transaction-list-item.js @@ -63,7 +63,7 @@ TransactionListItem.prototype.render = function () { style: { fontSize: '27px', }, - }) : h( '.pop-hover', { + }) : h('.pop-hover', { onClick: (event) => { event.stopPropagation() if (!isTx || isPending) return diff --git a/ui/app/conf-tx.js b/ui/app/conf-tx.js index 8d23adfe5..0b1dcac45 100644 --- a/ui/app/conf-tx.js +++ b/ui/app/conf-tx.js @@ -18,7 +18,7 @@ function mapStateToProps (state) { return { identities: state.metamask.identities, accounts: state.metamask.accounts, - selectedAddress: state.metamask.selectedAddress, + selectedAccount: state.metamask.selectedAccount, unconfTxs: state.metamask.unconfTxs, unconfMsgs: state.metamask.unconfMsgs, index: state.appState.currentView.context, @@ -90,12 +90,12 @@ ConfirmTxScreen.prototype.render = function () { // Properties txData: txData, key: txData.id, - selectedAddress: state.selectedAddress, + selectedAccount: state.selectedAccount, accounts: state.accounts, identities: state.identities, insufficientBalance: this.checkBalnceAgainstTx(txData), // Actions - buyEth: this.buyEth.bind(this, txParams.from || state.selectedAddress), + buyEth: this.buyEth.bind(this, txParams.from || state.selectedAccount), sendTransaction: this.sendTransaction.bind(this, txData), cancelTransaction: this.cancelTransaction.bind(this, txData), signMessage: this.signMessage.bind(this, txData), @@ -120,7 +120,7 @@ ConfirmTxScreen.prototype.checkBalnceAgainstTx = function (txData) { var state = this.props var txParams = txData.txParams || {} - var address = txParams.from || state.selectedAddress + var address = txParams.from || state.selectedAccount var account = state.accounts[address] var balance = account ? account.balance : '0x0' diff --git a/ui/app/config.js b/ui/app/config.js index 8824c6bec..3730baf6b 100644 --- a/ui/app/config.js +++ b/ui/app/config.js @@ -3,7 +3,7 @@ const Component = require('react').Component const h = require('react-hyperscript') const connect = require('react-redux').connect const actions = require('./actions') -const currencies = require('./conversion-util').availableCurrencies.rows +const currencies = require('./conversion.json').rows module.exports = connect(mapStateToProps)(ConfigScreen) function mapStateToProps (state) { diff --git a/ui/app/conversion-util.js b/ui/app/conversion-util.js deleted file mode 100644 index 19259602a..000000000 --- a/ui/app/conversion-util.js +++ /dev/null @@ -1,5 +0,0 @@ -var availableCurrencies = {"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":"404","name":"404","statuses":["primary"]},{"code":"611","name":"611","statuses":["primary"]},{"code":"888","name":"888","statuses":["primary"]},{"code":"8BIT","name":"8Bit","statuses":["primary"]},{"code":"ACLR","name":"ACLR","statuses":["primary"]},{"code":"ACOIN","name":"ACOIN","statuses":["primary"]},{"code":"ACP","name":"ACP","statuses":["primary"]},{"code":"ADC","name":"ADC","statuses":["primary"]},{"code":"ADZ","name":"Adzcoin","statuses":["primary"]},{"code":"AEC","name":"AEC","statuses":["primary"]},{"code":"AEON","name":"Aeon","statuses":["primary"]},{"code":"AGRS","name":"Agoras Tokens","statuses":["primary"]},{"code":"AIB","name":"AIB","statuses":["primary"]},{"code":"ADN","name":"Aiden","statuses":["primary"]},{"code":"AIR","name":"AIR","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":"AND","name":"AND","statuses":["primary"]},{"code":"ANI","name":"ANI","statuses":["primary"]},{"code":"ANC","name":"Anoncoin","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":"ABY","name":"ArtByte","statuses":["primary"]},{"code":"ARTC","name":"ARTC","statuses":["primary"]},{"code":"ADCN","name":"Asiadigicoin","statuses":["primary"]},{"code":"ATEN","name":"ATEN","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":"BA","name":"BA","statuses":["primary"]},{"code":"BAC","name":"BAC","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":"BDC","name":"BDC","statuses":["primary"]},{"code":"BEC","name":"BEC","statuses":["primary"]},{"code":"BEEZ","name":"BEEZ","statuses":["primary"]},{"code":"BELA","name":"BellaCoin","statuses":["primary"]},{"code":"BERN","name":"BERNcash","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":"BTM","name":"Bitmark","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":"PTS","name":"BitShares PTS","statuses":["primary"]},{"code":"SWIFT","name":"BitSwift","statuses":["primary"]},{"code":"BITZ","name":"Bitz","statuses":["primary"]},{"code":"BLK","name":"Blackcoin","statuses":["primary"]},{"code":"JACK","name":"BlackJack","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":"BM","name":"BM","statuses":["primary"]},{"code":"BNT","name":"BNT","statuses":["primary"]},{"code":"BOB","name":"BOB","statuses":["primary"]},{"code":"BON","name":"BON","statuses":["primary"]},{"code":"BBR","name":"Boolberry","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":"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":"BTCU","name":"BTCU","statuses":["primary"]},{"code":"BTTF","name":"BTTF","statuses":["primary"]},{"code":"BTX","name":"BTX","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":"BYC","name":"Bytecent","statuses":["primary"]},{"code":"BCN","name":"Bytecoin","statuses":["primary"]},{"code":"XCT","name":"C-Bit","statuses":["primary"]},{"code":"C0C0","name":"C0C0","statuses":["primary"]},{"code":"CAB","name":"Cabbage Unit","statuses":["primary"]},{"code":"CAD","name":"CAD","statuses":["primary","secondary"]},{"code":"CAGE","name":"CAGE","statuses":["primary"]},{"code":"CANN","name":"CannabisCoin","statuses":["primary"]},{"code":"CCN","name":"Cannacoin","statuses":["primary"]},{"code":"CPC","name":"Capricoin","statuses":["primary"]},{"code":"DIEM","name":"CarpeDiemCoin","statuses":["primary"]},{"code":"CASH","name":"CASH","statuses":["primary"]},{"code":"CBIT","name":"CBIT","statuses":["primary"]},{"code":"CC","name":"CC","statuses":["primary"]},{"code":"CCB","name":"CCB","statuses":["primary"]},{"code":"CD","name":"CD","statuses":["primary"]},{"code":"CDN","name":"CDN","statuses":["primary"]},{"code":"CF","name":"CF","statuses":["primary"]},{"code":"CFC","name":"CFC","statuses":["primary"]},{"code":"CGA","name":"CGA","statuses":["primary"]},{"code":"CHC","name":"CHC","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":"CHRG","name":"CHRG","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":"CMT","name":"CMT","statuses":["primary"]},{"code":"CNC","name":"CNC","statuses":["primary"]},{"code":"COXST","name":"CoExistCoin","statuses":["primary"]},{"code":"COIN","name":"COIN","statuses":["primary"]},{"code":"C2","name":"Coin2.1","statuses":["primary"]},{"code":"CNMT","name":"Coinomat","statuses":["primary"]},{"code":"CV2","name":"Colossuscoin2.0","statuses":["primary"]},{"code":"CON","name":"CON","statuses":["primary"]},{"code":"XCP","name":"Counterparty","statuses":["primary"]},{"code":"COV","name":"COV","statuses":["primary"]},{"code":"CRAFT","name":"CRAFT","statuses":["primary"]},{"code":"CRAVE","name":"CRAVE","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":"CRIME","name":"CRIME","statuses":["primary"]},{"code":"CRT","name":"CRT","statuses":["primary"]},{"code":"CRW","name":"CRW","statuses":["primary"]},{"code":"CRY","name":"CRY","statuses":["primary"]},{"code":"XCR","name":"Crypti","statuses":["primary"]},{"code":"CBX","name":"Crypto Bullion","statuses":["primary"]},{"code":"CESC","name":"CryptoEscudo","statuses":["primary"]},{"code":"XCN","name":"Cryptonite","statuses":["primary"]},{"code":"CSMIC","name":"CSMIC","statuses":["primary"]},{"code":"CST","name":"CST","statuses":["primary"]},{"code":"CTC","name":"CTC","statuses":["primary"]},{"code":"CTO","name":"CTO","statuses":["primary"]},{"code":"CURE","name":"Curecoin","statuses":["primary"]},{"code":"CYP","name":"Cypher","statuses":["primary"]},{"code":"CZC","name":"CZC","statuses":["primary"]},{"code":"CZECO","name":"CZECO","statuses":["primary"]},{"code":"CZR","name":"CZR","statuses":["primary"]},{"code":"DAO","name":"DAO","statuses":["primary"]},{"code":"DGD","name":"DarkGoldCoin","statuses":["primary"]},{"code":"DNET","name":"Darknet","statuses":["primary"]},{"code":"DASH","name":"Dash","statuses":["primary"]},{"code":"DTC","name":"Datacoin","statuses":["primary"]},{"code":"DBG","name":"DBG","statuses":["primary"]},{"code":"DBLK","name":"DBLK","statuses":["primary"]},{"code":"DBTC","name":"DBTC","statuses":["primary"]},{"code":"DCK","name":"DCK","statuses":["primary"]},{"code":"DCR","name":"Decred","statuses":["primary"]},{"code":"DES","name":"Destiny","statuses":["primary"]},{"code":"DETH","name":"DETH","statuses":["primary"]},{"code":"DEUR","name":"DEUR","statuses":["primary"]},{"code":"DEM","name":"Deutsche eMark","statuses":["primary"]},{"code":"DVC","name":"Devcoin","statuses":["primary"]},{"code":"DGCS","name":"DGCS","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":"DIGS","name":"DIGS","statuses":["primary"]},{"code":"DIME","name":"Dimecoin","statuses":["primary"]},{"code":"DISK","name":"DISK","statuses":["primary"]},{"code":"DLISK","name":"DLISK","statuses":["primary"]},{"code":"NOTE","name":"DNotes","statuses":["primary"]},{"code":"DOGE","name":"Dogecoin","statuses":["primary","secondary"]},{"code":"DON","name":"DON","statuses":["primary"]},{"code":"DOPE","name":"DopeCoin","statuses":["primary"]},{"code":"DOX","name":"DOX","statuses":["primary"]},{"code":"DRACO","name":"DRACO","statuses":["primary"]},{"code":"DRM","name":"DRM","statuses":["primary"]},{"code":"DROP","name":"DROP","statuses":["primary"]},{"code":"DRZ","name":"DRZ","statuses":["primary"]},{"code":"DSH","name":"DSH","statuses":["primary"]},{"code":"DBIC","name":"DubaiCoin","statuses":["primary"]},{"code":"DUO","name":"DUO","statuses":["primary"]},{"code":"DUST","name":"DUST","statuses":["primary"]},{"code":"EAC","name":"Earthcoin","statuses":["primary"]},{"code":"ECCHI","name":"ECCHI","statuses":["primary"]},{"code":"ECC","name":"ECCoin","statuses":["primary"]},{"code":"ECOS","name":"ECOS","statuses":["primary"]},{"code":"EDC","name":"EDC","statuses":["primary"]},{"code":"EDRC","name":"EDRC","statuses":["primary"]},{"code":"EGG","name":"EGG","statuses":["primary"]},{"code":"EMC2","name":"Einsteinium","statuses":["primary"]},{"code":"EKO","name":"EKO","statuses":["primary"]},{"code":"EL","name":"EL","statuses":["primary"]},{"code":"ELCO","name":"ELcoin","statuses":["primary"]},{"code":"ELE","name":"ELE","statuses":["primary"]},{"code":"EFL","name":"Electronic Gulden","statuses":["primary"]},{"code":"EMC","name":"Emercoin","statuses":["primary"]},{"code":"EMIRG","name":"EMIRG","statuses":["primary"]},{"code":"ENE","name":"ENE","statuses":["primary"]},{"code":"ENRG","name":"Energycoin","statuses":["primary"]},{"code":"EPC","name":"EPC","statuses":["primary"]},{"code":"EPY","name":"EPY","statuses":["primary"]},{"code":"ERC","name":"ERC","statuses":["primary"]},{"code":"ERC3","name":"ERC3","statuses":["primary"]},{"code":"ESC","name":"ESC","statuses":["primary"]},{"code":"ETC","name":"Ethereum Classic","statuses":["primary"]},{"code":"ETHS","name":"ETHS","statuses":["primary"]},{"code":"EURC","name":"EURC","statuses":["primary"]},{"code":"EUR","name":"Euro","statuses":["primary","secondary"]},{"code":"EGC","name":"EvergreenCoin","statuses":["primary"]},{"code":"EVIL","name":"EVIL","statuses":["primary"]},{"code":"EVO","name":"EVO","statuses":["primary"]},{"code":"EXCL","name":"EXCL","statuses":["primary"]},{"code":"EXIT","name":"EXIT","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":"FCN","name":"FCN","statuses":["primary"]},{"code":"FTC","name":"Feathercoin","statuses":["primary"]},{"code":"TIPS","name":"Fedoracoin","statuses":["primary"]},{"code":"FFC","name":"FFC","statuses":["primary"]},{"code":"FIBRE","name":"Fibre","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":"FLX","name":"FLX","statuses":["primary"]},{"code":"FLY","name":"Flycoin","statuses":["primary"]},{"code":"FLDC","name":"FoldingCoin","statuses":["primary"]},{"code":"FONZ","name":"FONZ","statuses":["primary"]},{"code":"FRK","name":"Franko","statuses":["primary"]},{"code":"FRC","name":"Freicoin","statuses":["primary"]},{"code":"FRN","name":"FRN","statuses":["primary"]},{"code":"FRWC","name":"FRWC","statuses":["primary"]},{"code":"FSC2","name":"FSC2","statuses":["primary"]},{"code":"FST","name":"FST","statuses":["primary"]},{"code":"FTP","name":"FTP","statuses":["primary"]},{"code":"FUN","name":"FUN","statuses":["primary"]},{"code":"FUTC","name":"FUTC","statuses":["primary"]},{"code":"FUZZ","name":"FUZZ","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":"GCC","name":"GCC","statuses":["primary"]},{"code":"GCN","name":"GCN","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":"GIFT","name":"GIFT","statuses":["primary"]},{"code":"GIG","name":"GIG","statuses":["primary"]},{"code":"GLC","name":"GLC","statuses":["primary"]},{"code":"BSTY","name":"GlobalBoost-Y","statuses":["primary"]},{"code":"GML","name":"GML","statuses":["primary"]},{"code":"GMX","name":"GMX","statuses":["primary"]},{"code":"GCR","name":"GoCoineR","statuses":["primary"]},{"code":"GLD","name":"GoldCoin","statuses":["primary"]},{"code":"GOON","name":"GOON","statuses":["primary"]},{"code":"GP","name":"GP","statuses":["primary"]},{"code":"GPU","name":"GPU","statuses":["primary"]},{"code":"GRAM","name":"GRAM","statuses":["primary"]},{"code":"GRT","name":"Grantcoin","statuses":["primary"]},{"code":"GRE","name":"GRE","statuses":["primary"]},{"code":"GRC","name":"Gridcoin","statuses":["primary"]},{"code":"GRN","name":"GRN","statuses":["primary"]},{"code":"GRS","name":"Groestlcoin","statuses":["primary"]},{"code":"GRW","name":"GRW","statuses":["primary"]},{"code":"GSM","name":"GSM","statuses":["primary"]},{"code":"GSX","name":"GSX","statuses":["primary"]},{"code":"GUA","name":"GUA","statuses":["primary"]},{"code":"NLG","name":"Gulden","statuses":["primary"]},{"code":"GUN","name":"GUN","statuses":["primary"]},{"code":"HAM","name":"HAM","statuses":["primary"]},{"code":"HAWK","name":"HAWK","statuses":["primary"]},{"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":"HIFUN","name":"HIFUN","statuses":["primary"]},{"code":"HILL","name":"HILL","statuses":["primary"]},{"code":"HIRE","name":"HIRE","statuses":["primary"]},{"code":"HNC","name":"HNC","statuses":["primary"]},{"code":"HODL","name":"HOdlcoin","statuses":["primary"]},{"code":"HKD","name":"Hong Kong Dollar","statuses":["secondary"]},{"code":"HZ","name":"Horizon","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":"HYPER","name":"Hyper","statuses":["primary"]},{"code":"HYP","name":"HyperStake","statuses":["primary"]},{"code":"I0C","name":"I0C","statuses":["primary"]},{"code":"IBANK","name":"IBANK","statuses":["primary"]},{"code":"ICASH","name":"iCash","statuses":["primary"]},{"code":"ICN","name":"ICN","statuses":["primary"]},{"code":"IEC","name":"IEC","statuses":["primary"]},{"code":"IFC","name":"Infinitecoin","statuses":["primary"]},{"code":"INFX","name":"Influxcoin","statuses":["primary"]},{"code":"INV","name":"INV","statuses":["primary"]},{"code":"IOC","name":"IO Coin","statuses":["primary"]},{"code":"ION","name":"ION","statuses":["primary"]},{"code":"IRL","name":"IRL","statuses":["primary"]},{"code":"ISL","name":"IslaCoin","statuses":["primary"]},{"code":"IVZ","name":"IVZ","statuses":["primary"]},{"code":"IXC","name":"IXC","statuses":["primary"]},{"code":"JIF","name":"JIF","statuses":["primary"]},{"code":"JPC","name":"JPC","statuses":["primary"]},{"code":"JPY","name":"JPY","statuses":["primary","secondary"]},{"code":"JBS","name":"Jumbucks","statuses":["primary"]},{"code":"KAT","name":"KAT","statuses":["primary"]},{"code":"KGC","name":"KGC","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":"KRYP","name":"KRYP","statuses":["primary"]},{"code":"KR","name":"Krypton","statuses":["primary"]},{"code":"KTK","name":"KTK","statuses":["primary"]},{"code":"KUBO","name":"KUBO","statuses":["primary"]},{"code":"LANA","name":"LANA","statuses":["primary"]},{"code":"LBC","name":"LBC","statuses":["primary"]},{"code":"LC","name":"LC","statuses":["primary"]},{"code":"LEA","name":"LeaCoin","statuses":["primary"]},{"code":"LEMON","name":"LEMON","statuses":["primary"]},{"code":"LEO","name":"LEO","statuses":["primary"]},{"code":"LFC","name":"LFC","statuses":["primary"]},{"code":"LFO","name":"LFO","statuses":["primary"]},{"code":"LFTC","name":"LFTC","statuses":["primary"]},{"code":"LQD","name":"LIQUID","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":"LDOGE","name":"LiteDoge","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":"LUN","name":"LUN","statuses":["primary"]},{"code":"LXC","name":"LXC","statuses":["primary"]},{"code":"LYB","name":"LYB","statuses":["primary"]},{"code":"M1","name":"M1","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":"MARV","name":"MARV","statuses":["primary"]},{"code":"MARYJ","name":"MARYJ","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":"MCAR","name":"MCAR","statuses":["primary"]},{"code":"MCN","name":"MCN","statuses":["primary"]},{"code":"MCZ","name":"MCZ","statuses":["primary"]},{"code":"MED","name":"MediterraneanCoin","statuses":["primary"]},{"code":"MEC","name":"Megacoin","statuses":["primary"]},{"code":"MEME","name":"Memetic","statuses":["primary"]},{"code":"METAL","name":"METAL","statuses":["primary"]},{"code":"MND","name":"MindCoin","statuses":["primary"]},{"code":"MINT","name":"Mintcoin","statuses":["primary"]},{"code":"MIS","name":"MIS","statuses":["primary"]},{"code":"MM","name":"MM","statuses":["primary"]},{"code":"MMC","name":"MMC","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":"MNTA","name":"Moneta","statuses":["primary"]},{"code":"MUE","name":"MonetaryUnit","statuses":["primary"]},{"code":"MOON","name":"Mooncoin","statuses":["primary"]},{"code":"MOOND","name":"MOOND","statuses":["primary"]},{"code":"MOTO","name":"MOTO","statuses":["primary"]},{"code":"MPRO","name":"MPRO","statuses":["primary"]},{"code":"MRB","name":"MRB","statuses":["primary"]},{"code":"MRP","name":"MRP","statuses":["primary"]},{"code":"MSC","name":"MSC","statuses":["primary"]},{"code":"MYR","name":"Myriadcoin","statuses":["primary"]},{"code":"NMC","name":"Namecoin","statuses":["primary"]},{"code":"NAUT","name":"Nautiluscoin","statuses":["primary"]},{"code":"NAV","name":"NAV Coin","statuses":["primary"]},{"code":"NCS","name":"NCS","statuses":["primary"]},{"code":"XEM","name":"NEM","statuses":["primary"]},{"code":"NEOS","name":"NeosCoin","statuses":["primary"]},{"code":"NETC","name":"NETC","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":"NIRO","name":"Nexus","statuses":["primary"]},{"code":"NIC","name":"NIC","statuses":["primary"]},{"code":"NKA","name":"NKA","statuses":["primary"]},{"code":"NKC","name":"NKC","statuses":["primary"]},{"code":"NOBL","name":"NobleCoin","statuses":["primary"]},{"code":"NODE","name":"NODE","statuses":["primary"]},{"code":"NODES","name":"NODES","statuses":["primary"]},{"code":"NOO","name":"NOO","statuses":["primary"]},{"code":"NVC","name":"Novacoin","statuses":["primary"]},{"code":"NRC","name":"NRC","statuses":["primary"]},{"code":"NRS","name":"NRS","statuses":["primary"]},{"code":"NUBIS","name":"NUBIS","statuses":["primary"]},{"code":"NBT","name":"NuBits","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":"OC","name":"OC","statuses":["primary"]},{"code":"OCOW","name":"OCOW","statuses":["primary"]},{"code":"OK","name":"OKCash","statuses":["primary"]},{"code":"OMA","name":"OMA","statuses":["primary"]},{"code":"ONE","name":"ONE","statuses":["primary"]},{"code":"ONEC","name":"ONEC","statuses":["primary"]},{"code":"OP","name":"OP","statuses":["primary"]},{"code":"OPAL","name":"OPAL","statuses":["primary"]},{"code":"OPES","name":"OPES","statuses":["primary"]},{"code":"ORB","name":"Orbitcoin","statuses":["primary"]},{"code":"ORLY","name":"Orlycoin","statuses":["primary"]},{"code":"OS76","name":"OS76","statuses":["primary"]},{"code":"OZC","name":"OZC","statuses":["primary"]},{"code":"PAC","name":"PAC","statuses":["primary"]},{"code":"PAK","name":"PAK","statuses":["primary"]},{"code":"PND","name":"Pandacoin","statuses":["primary"]},{"code":"PAPAF","name":"PAPAF","statuses":["primary"]},{"code":"XPY","name":"Paycoin","statuses":["primary"]},{"code":"PBC","name":"PBC","statuses":["primary"]},{"code":"PDC","name":"PDC","statuses":["primary"]},{"code":"XPB","name":"Pebblecoin","statuses":["primary"]},{"code":"PPC","name":"Peercoin","statuses":["primary"]},{"code":"PEN","name":"PEN","statuses":["primary"]},{"code":"PHR","name":"PHR","statuses":["primary"]},{"code":"PIGGY","name":"Piggycoin","statuses":["primary"]},{"code":"PC","name":"Pinkcoin","statuses":["primary"]},{"code":"PKB","name":"PKB","statuses":["primary"]},{"code":"PLN","name":"PLN","statuses":["primary","secondary"]},{"code":"PLNC","name":"PLNC","statuses":["primary"]},{"code":"PNC","name":"PNC","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":"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":"PSP","name":"PSP","statuses":["primary"]},{"code":"PTC","name":"PTC","statuses":["primary"]},{"code":"PULSE","name":"PULSE","statuses":["primary"]},{"code":"PURE","name":"PURE","statuses":["primary"]},{"code":"PUTIN","name":"PUTIN","statuses":["primary"]},{"code":"PWR","name":"PWR","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":"RED","name":"RED","statuses":["primary"]},{"code":"RDD","name":"Reddcoin","statuses":["primary"]},{"code":"REE","name":"REE","statuses":["primary"]},{"code":"REV","name":"Revenu","statuses":["primary"]},{"code":"RBR","name":"RibbitRewards","statuses":["primary"]},{"code":"RICHX","name":"RICHX","statuses":["primary"]},{"code":"RIC","name":"Riecoin","statuses":["primary"]},{"code":"RBT","name":"Rimbit","statuses":["primary"]},{"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":"ROOT","name":"ROOT","statuses":["primary"]},{"code":"ROS","name":"RosCoin","statuses":["primary"]},{"code":"RPC","name":"RPC","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":"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":"SBIT","name":"SBIT","statuses":["primary"]},{"code":"SCAN","name":"SCAN","statuses":["primary"]},{"code":"SCOT","name":"Scotcoin","statuses":["primary"]},{"code":"SCRPT","name":"SCRPT","statuses":["primary"]},{"code":"SCRT","name":"SCRT","statuses":["primary"]},{"code":"SRC","name":"SecureCoin","statuses":["primary"]},{"code":"SXC","name":"Sexcoin","statuses":["primary"]},{"code":"SFE","name":"SFE","statuses":["primary"]},{"code":"SFR","name":"SFR","statuses":["primary"]},{"code":"SGD","name":"SGD","statuses":["primary","secondary"]},{"code":"SDC","name":"ShadowCash","statuses":["primary"]},{"code":"SHELL","name":"SHELL","statuses":["primary"]},{"code":"SHF","name":"SHF","statuses":["primary"]},{"code":"SHI","name":"SHI","statuses":["primary"]},{"code":"SHIFT","name":"Shift","statuses":["primary"]},{"code":"SHREK","name":"SHREK","statuses":["primary"]},{"code":"SC","name":"Siacoin","statuses":["primary"]},{"code":"SIB","name":"Siberian chervonets","statuses":["primary"]},{"code":"SIC","name":"SIC","statuses":["primary"]},{"code":"SIGU","name":"SIGU","statuses":["primary"]},{"code":"SILK","name":"Silkcoin","statuses":["primary"]},{"code":"SIX","name":"SIX","statuses":["primary"]},{"code":"SLING","name":"Sling","statuses":["primary"]},{"code":"SLS","name":"SLS","statuses":["primary"]},{"code":"SMBR","name":"SMBR","statuses":["primary"]},{"code":"SMC","name":"SMC","statuses":["primary"]},{"code":"SMLY","name":"SmileyCoin","statuses":["primary"]},{"code":"SNRG","name":"SNRG","statuses":["primary"]},{"code":"SOIL","name":"SOILcoin","statuses":["primary"]},{"code":"SLR","name":"Solarcoin","statuses":["primary"]},{"code":"SOLO","name":"SOLO","statuses":["primary"]},{"code":"SONG","name":"SongCoin","statuses":["primary"]},{"code":"SOON","name":"SOON","statuses":["primary"]},{"code":"SPC","name":"SPC","statuses":["primary"]},{"code":"SPEX","name":"SPEX","statuses":["primary"]},{"code":"SPHR","name":"Sphere","statuses":["primary"]},{"code":"SPM","name":"SPM","statuses":["primary"]},{"code":"SPN","name":"SPN","statuses":["primary"]},{"code":"SPOTS","name":"SPOTS","statuses":["primary"]},{"code":"SPR","name":"SpreadCoin","statuses":["primary"]},{"code":"SPRTS","name":"Sprouts","statuses":["primary"]},{"code":"SQC","name":"SQC","statuses":["primary"]},{"code":"SSC","name":"SSC","statuses":["primary"]},{"code":"SSTC","name":"SSTC","statuses":["primary"]},{"code":"STA","name":"STA","statuses":["primary"]},{"code":"START","name":"Startcoin","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":"STL","name":"STL","statuses":["primary"]},{"code":"SJCX","name":"Storjcoin X","statuses":["primary"]},{"code":"STP","name":"STP","statuses":["primary"]},{"code":"STRB","name":"STRB","statuses":["primary"]},{"code":"STS","name":"Stress","statuses":["primary"]},{"code":"STRP","name":"STRP","statuses":["primary"]},{"code":"STV","name":"STV","statuses":["primary"]},{"code":"SUB","name":"Subcriptio","statuses":["primary"]},{"code":"SUPER","name":"SUPER","statuses":["primary"]},{"code":"UNITY","name":"SuperNET","statuses":["primary"]},{"code":"SWARM","name":"Swarm","statuses":["primary"]},{"code":"SWING","name":"SWING","statuses":["primary"]},{"code":"SDP","name":"SydPak Coin","statuses":["primary"]},{"code":"SYNC","name":"SYNC","statuses":["primary"]},{"code":"AMP","name":"Synereo","statuses":["primary"]},{"code":"SYS","name":"Syscoin","statuses":["primary"]},{"code":"TAG","name":"TagCoin","statuses":["primary"]},{"code":"TAJ","name":"TAJ","statuses":["primary"]},{"code":"TAK","name":"TAK","statuses":["primary"]},{"code":"TAM","name":"TAM","statuses":["primary"]},{"code":"TAO","name":"TAO","statuses":["primary"]},{"code":"TBC","name":"TBC","statuses":["primary"]},{"code":"TBCX","name":"TBCX","statuses":["primary"]},{"code":"TCR","name":"TCR","statuses":["primary"]},{"code":"TDFB","name":"TDFB","statuses":["primary"]},{"code":"TDY","name":"TDY","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":"USDT","name":"Tether","statuses":["primary","secondary"]},{"code":"THC","name":"THC","statuses":["primary"]},{"code":"THS","name":"THS","statuses":["primary"]},{"code":"TIX","name":"Tickets","statuses":["primary"]},{"code":"XTC","name":"TileCoin","statuses":["primary"]},{"code":"TIT","name":"Titcoin","statuses":["primary"]},{"code":"TTC","name":"TittieCoin","statuses":["primary"]},{"code":"TMC","name":"TMC","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":"TROLL","name":"TROLL","statuses":["primary"]},{"code":"TRK","name":"Truckcoin","statuses":["primary"]},{"code":"TRUMP","name":"TrumpCoin","statuses":["primary"]},{"code":"TRUST","name":"TRUST","statuses":["primary"]},{"code":"UAE","name":"UAE","statuses":["primary"]},{"code":"UFO","name":"UFO Coin","statuses":["primary"]},{"code":"UIS","name":"UIS","statuses":["primary"]},{"code":"UTC","name":"UltraCoin","statuses":["primary"]},{"code":"UNC","name":"UNC","statuses":["primary"]},{"code":"UNIQ","name":"UNIQ","statuses":["primary"]},{"code":"UNIT","name":"Universal Currency","statuses":["primary"]},{"code":"UNO","name":"Unobtanium","statuses":["primary"]},{"code":"URO","name":"Uro","statuses":["primary"]},{"code":"USD","name":"US Dollar","statuses":["primary","secondary"]},{"code":"USDE","name":"USDE","statuses":["primary"]},{"code":"UTH","name":"UTH","statuses":["primary"]},{"code":"VAL","name":"VAL","statuses":["primary"]},{"code":"XVC","name":"Vcash","statuses":["primary"]},{"code":"VCN","name":"VCN","statuses":["primary"]},{"code":"VEG","name":"VEG","statuses":["primary"]},{"code":"VENE","name":"VENE","statuses":["primary"]},{"code":"XVG","name":"Verge","statuses":["primary"]},{"code":"VRC","name":"VeriCoin","statuses":["primary"]},{"code":"VTC","name":"Vertcoin","statuses":["primary"]},{"code":"VIA","name":"Viacoin","statuses":["primary"]},{"code":"VIOR","name":"Viorcoin","statuses":["primary"]},{"code":"VIP","name":"VIP Tokens","statuses":["primary"]},{"code":"VIRAL","name":"Viral","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":"VPRC","name":"VPRC","statuses":["primary"]},{"code":"VTA","name":"VTA","statuses":["primary"]},{"code":"VTN","name":"VTN","statuses":["primary"]},{"code":"VTR","name":"VTR","statuses":["primary"]},{"code":"WAC","name":"WAC","statuses":["primary"]},{"code":"WARP","name":"WARP","statuses":["primary"]},{"code":"WAVES","name":"WAVES","statuses":["primary"]},{"code":"WGC","name":"WGC","statuses":["primary"]},{"code":"XWC","name":"Whitecoin","statuses":["primary"]},{"code":"WBB","name":"Wild Beast Block","statuses":["primary"]},{"code":"WLC","name":"WLC","statuses":["primary"]},{"code":"WMC","name":"WMC","statuses":["primary"]},{"code":"LOG","name":"Woodcoin","statuses":["primary"]},{"code":"WOP","name":"WOP","statuses":["primary"]},{"code":"WDC","name":"Worldcoin","statuses":["primary"]},{"code":"XAB","name":"XAB","statuses":["primary"]},{"code":"XAI","name":"XAI","statuses":["primary"]},{"code":"XAU","name":"Xaurum","statuses":["primary"]},{"code":"XBS","name":"XBS","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":"XEMP","name":"XEMP","statuses":["primary"]},{"code":"XFC","name":"XFC","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":"XMS","name":"XMS","statuses":["primary"]},{"code":"XNX","name":"XNX","statuses":["primary"]},{"code":"XPD","name":"XPD","statuses":["primary"]},{"code":"XPOKE","name":"XPOKE","statuses":["primary"]},{"code":"XPRO","name":"XPRO","statuses":["primary"]},{"code":"XQN","name":"XQN","statuses":["primary"]},{"code":"XSEED","name":"XSEED","statuses":["primary"]},{"code":"XSP","name":"XSP","statuses":["primary"]},{"code":"XT","name":"XT","statuses":["primary"]},{"code":"XTP","name":"XTP","statuses":["primary"]},{"code":"XUSD","name":"XUSD","statuses":["primary"]},{"code":"YACC","name":"YACC","statuses":["primary"]},{"code":"YAC","name":"Yacoin","statuses":["primary"]},{"code":"YAY","name":"YAY","statuses":["primary"]},{"code":"YBC","name":"Ybcoin","statuses":["primary"]},{"code":"YOC","name":"YOC","statuses":["primary"]},{"code":"YOVI","name":"YOVI","statuses":["primary"]},{"code":"YUM","name":"YUM","statuses":["primary"]},{"code":"ZCC","name":"ZCC","statuses":["primary"]},{"code":"ZEIT","name":"Zeitcoin","statuses":["primary"]},{"code":"ZET","name":"Zetacoin","statuses":["primary"]},{"code":"ZRC","name":"ZiftrCOIN","statuses":["primary"]},{"code":"ZMC","name":"ZMC","statuses":["primary"]},{"code":"ZNY","name":"ZNY","statuses":["primary"]},{"code":"ZS","name":"ZS","statuses":["primary"]}]} - -module.exports = { - availableCurrencies -} diff --git a/ui/app/conversion.json b/ui/app/conversion.json new file mode 100644 index 000000000..eeca164ce --- /dev/null +++ b/ui/app/conversion.json @@ -0,0 +1,5730 @@ +{
+ "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 diff --git a/ui/app/eth-store-warning.js b/ui/app/eth-store-warning.js deleted file mode 100644 index fe3c7ce5d..000000000 --- a/ui/app/eth-store-warning.js +++ /dev/null @@ -1,89 +0,0 @@ -const connect = require('react-redux').connect -const Component = require('react').Component -const h = require('react-hyperscript') -const inherits = require('util').inherits -const actions = require('./actions') - -module.exports = connect(mapStateToProps)(EthStoreWarning) - -inherits(EthStoreWarning, Component) -function EthStoreWarning () { - Component.call(this) -} - -function mapStateToProps (state) { - return { - selectedAccount: state.metamask.selectedAccount, - } -} - -EthStoreWarning.prototype.render = function () { - - return ( - - h('.flex-column', { - key: 'ethWarning', - style: { - paddingTop: '25px', - marginRight: '30px', - marginLeft: '30px', - alignItems: 'center', - }, - }, [ - h('.warning', { - style: { - margin: '10px 10px 10px 10px', - }, - }, - `MetaMask is currently in beta; use - caution in storing large - amounts of ether. - `), - - h('i.fa.fa-exclamation-triangle.fa-4', { - style: { - fontSize: '152px', - color: '#AEAEAE', - textAlign: 'center', - }, - }), - - h('.flex-row', { - style: { - marginTop: '25px', - marginBottom: '10px', - }, - }, [ - h('input', { - type: 'checkbox', - onChange: this.toggleShowWarning.bind(this), - }), - h('.warning', { - style: { - fontSize: '11px', - }, - - }, 'Don\'t show me this message again'), - ]), - h('.flex-row', { - style: { - width: '100%', - justifyContent: 'space-around', - }, - }, [ - h('button', { - onClick: this.toAccounts.bind(this), - }, - 'Continue to MetaMask'), - ]), - ]) - ) -} - -EthStoreWarning.prototype.toggleShowWarning = function () { - this.props.dispatch(actions.agreeToEthWarning()) -} - -EthStoreWarning.prototype.toAccounts = function () { - this.props.dispatch(actions.showAccountDetail(this.props.account)) -} diff --git a/ui/app/first-time/create-vault.js b/ui/app/first-time/create-vault.js deleted file mode 100644 index 33ae62179..000000000 --- a/ui/app/first-time/create-vault.js +++ /dev/null @@ -1,129 +0,0 @@ -const inherits = require('util').inherits - -const Component = require('react').Component -const connect = require('react-redux').connect -const h = require('react-hyperscript') -const actions = require('../actions') - -module.exports = connect(mapStateToProps)(CreateVaultScreen) - -inherits(CreateVaultScreen, Component) -function CreateVaultScreen () { - Component.call(this) -} - -function mapStateToProps (state) { - return { - warning: state.appState.warning, - } -} - -CreateVaultScreen.prototype.render = function () { - var state = this.props - return ( - - h('.initialize-screen.flex-column.flex-center.flex-grow', [ - - h('h3.flex-center.text-transform-uppercase', { - style: { - background: '#EBEBEB', - color: '#AEAEAE', - marginBottom: 24, - width: '100%', - fontSize: '20px', - padding: 6, - }, - }, [ - 'Create Vault', - ]), - - // password - h('input.large-input.letter-spacey', { - type: 'password', - id: 'password-box', - placeholder: 'New Password (min 8 chars)', - style: { - width: 260, - marginTop: 12, - }, - }), - - // confirm password - h('input.large-input.letter-spacey', { - type: 'password', - id: 'password-box-confirm', - placeholder: 'Confirm Password', - onKeyPress: this.createVaultOnEnter.bind(this), - style: { - width: 260, - marginTop: 16, - }, - }), - - h('.flex-row.flex-space-between', { - style: { - marginTop: 30, - width: '50%', - }, - }, [ - - // cancel - h('button.primary', { - onClick: this.showInitializeMenu.bind(this), - }, 'CANCEL'), - - // submit - h('button.primary', { - onClick: this.createNewVault.bind(this), - }, 'OK'), - - ]), - - (!state.inProgress && state.warning) && ( - h('span.in-progress-notification', state.warning) - ), - - state.inProgress && ( - h('span.in-progress-notification', 'Generating Seed...') - ), - ]) - ) -} - -CreateVaultScreen.prototype.componentDidMount = function () { - document.getElementById('password-box').focus() -} - -CreateVaultScreen.prototype.showInitializeMenu = function () { - this.props.dispatch(actions.showInitializeMenu()) -} - -// create vault - -CreateVaultScreen.prototype.createVaultOnEnter = function (event) { - if (event.key === 'Enter') { - event.preventDefault() - this.createNewVault() - } -} - -CreateVaultScreen.prototype.createNewVault = function () { - var passwordBox = document.getElementById('password-box') - var password = passwordBox.value - var passwordConfirmBox = document.getElementById('password-box-confirm') - var passwordConfirm = passwordConfirmBox.value - // var entropy = document.getElementById('entropy-text-entry').value - - if (password.length < 8) { - this.warning = 'password not long enough' - this.props.dispatch(actions.displayWarning(this.warning)) - return - } - if (password !== passwordConfirm) { - this.warning = 'passwords don\'t match' - this.props.dispatch(actions.displayWarning(this.warning)) - return - } - - this.props.dispatch(actions.createNewVault(password, ''/* entropy*/)) -} diff --git a/ui/app/first-time/init-menu.js b/ui/app/first-time/init-menu.js index 94a9d3df6..c41aecc48 100644 --- a/ui/app/first-time/init-menu.js +++ b/ui/app/first-time/init-menu.js @@ -5,6 +5,8 @@ const connect = require('react-redux').connect const h = require('react-hyperscript') const Mascot = require('../components/mascot') const actions = require('../actions') +const Tooltip = require('../components/tooltip') +const getCaretCoordinates = require('textarea-caret') module.exports = connect(mapStateToProps)(InitializeMenuScreen) @@ -18,6 +20,8 @@ function mapStateToProps (state) { return { // state from plugin currentView: state.appState.currentView, + warning: state.appState.warning, + forgottenPassword: state.metamask.isInitialized, } } @@ -27,7 +31,7 @@ InitializeMenuScreen.prototype.render = function () { switch (state.currentView.name) { default: - return this.renderMenu() + return this.renderMenu(state) } } @@ -36,7 +40,7 @@ InitializeMenuScreen.prototype.render = function () { // document.getElementById('password-box').focus() // } -InitializeMenuScreen.prototype.renderMenu = function () { +InitializeMenuScreen.prototype.renderMenu = function (state) { return ( h('.initialize-screen.flex-column.flex-center.flex-grow', [ @@ -47,49 +51,146 @@ InitializeMenuScreen.prototype.renderMenu = function () { h('h1', { style: { - fontSize: '1.4em', + fontSize: '1.3em', textTransform: 'uppercase', color: '#7F8082', - marginBottom: 20, + marginBottom: 10, }, }, 'MetaMask'), - h('button.primary', { - onClick: this.showCreateVault.bind(this), + + h('div', [ + h('h3', { + style: { + fontSize: '0.8em', + color: '#7F8082', + display: 'inline', + }, + }, 'Encrypt your new DEN'), + + h(Tooltip, { + title: 'Your DEN is your password-encrypted storage within MetaMask.', + }, [ + h('i.fa.fa-question-circle.pointer', { + style: { + fontSize: '18px', + position: 'relative', + color: 'rgb(247, 134, 28)', + top: '2px', + marginLeft: '4px', + }, + }), + ]), + ]), + + h('span.in-progress-notification', state.warning), + + // password + h('input.large-input.letter-spacey', { + type: 'password', + id: 'password-box', + placeholder: 'New Password (min 8 chars)', + onInput: this.inputChanged.bind(this), style: { - margin: 12, + width: 260, + marginTop: 12, + }, + }), + + // confirm password + h('input.large-input.letter-spacey', { + type: 'password', + id: 'password-box-confirm', + placeholder: 'Confirm Password', + onKeyPress: this.createVaultOnEnter.bind(this), + onInput: this.inputChanged.bind(this), + style: { + width: 260, + marginTop: 16, }, - }, 'Create New Vault'), + }), - h('.flex-row.flex-center.flex-grow', [ - h('hr'), - h('div', 'OR'), - h('hr'), - ]), h('button.primary', { - onClick: this.showRestoreVault.bind(this), + onClick: this.createNewVaultAndKeychain.bind(this), style: { margin: 12, }, - }, 'Restore Existing Vault'), + }, 'Create'), + + state.forgottenPassword ? h('.flex-row.flex-center.flex-grow', [ + h('p.pointer', { + onClick: this.backToUnlockView.bind(this), + style: { + fontSize: '0.8em', + color: 'rgb(247, 134, 28)', + textDecoration: 'underline', + }, + }, 'Return to Login'), + ]) : null, + + h('.flex-row.flex-center.flex-grow', [ + h('p.pointer', { + onClick: this.showRestoreVault.bind(this), + style: { + fontSize: '0.8em', + color: 'rgb(247, 134, 28)', + textDecoration: 'underline', + }, + }, 'Import Existing DEN'), + ]), + ]) ) } -// InitializeMenuScreen.prototype.splitWor = function() { -// this.props.dispatch(actions.showInitializeMenu()) -// } - -InitializeMenuScreen.prototype.showInitializeMenu = function () { - this.props.dispatch(actions.showInitializeMenu()) +InitializeMenuScreen.prototype.createVaultOnEnter = function (event) { + if (event.key === 'Enter') { + event.preventDefault() + this.createNewVaultAndKeychain() + } } -InitializeMenuScreen.prototype.showCreateVault = function () { - this.props.dispatch(actions.showCreateVault()) +InitializeMenuScreen.prototype.componentDidMount = function () { + document.getElementById('password-box').focus() } InitializeMenuScreen.prototype.showRestoreVault = function () { this.props.dispatch(actions.showRestoreVault()) } +InitializeMenuScreen.prototype.backToUnlockView = function () { + this.props.dispatch(actions.backToUnlockView()) +} + +InitializeMenuScreen.prototype.createNewVaultAndKeychain = function () { + var passwordBox = document.getElementById('password-box') + var password = passwordBox.value + var passwordConfirmBox = document.getElementById('password-box-confirm') + var passwordConfirm = passwordConfirmBox.value + // var entropy = document.getElementById('entropy-text-entry').value + + if (password.length < 8) { + this.warning = 'password not long enough' + this.props.dispatch(actions.displayWarning(this.warning)) + return + } + if (password !== passwordConfirm) { + this.warning = 'passwords don\'t match' + this.props.dispatch(actions.displayWarning(this.warning)) + return + } + + this.props.dispatch(actions.createNewVaultAndKeychain(password)) +} + +InitializeMenuScreen.prototype.inputChanged = function (event) { + // tell mascot to look at page action + var element = event.target + var boundingRect = element.getBoundingClientRect() + var coordinates = getCaretCoordinates(element, element.selectionEnd) + this.animationEventEmitter.emit('point', { + x: boundingRect.left + coordinates.left - element.scrollLeft, + y: boundingRect.top + coordinates.top - element.scrollTop, + }) +} diff --git a/ui/app/first-time/create-vault-complete.js b/ui/app/keychains/hd/create-vault-complete.js index 2b5413955..7272ebdbd 100644 --- a/ui/app/first-time/create-vault-complete.js +++ b/ui/app/keychains/hd/create-vault-complete.js @@ -2,7 +2,7 @@ const inherits = require('util').inherits const Component = require('react').Component const connect = require('react-redux').connect const h = require('react-hyperscript') -const actions = require('../actions') +const actions = require('../../actions') module.exports = connect(mapStateToProps)(CreateVaultCompleteScreen) @@ -71,4 +71,3 @@ CreateVaultCompleteScreen.prototype.render = function () { CreateVaultCompleteScreen.prototype.confirmSeedWords = function () { this.props.dispatch(actions.confirmSeedWords()) } - diff --git a/ui/app/recover-seed/confirmation.js b/ui/app/keychains/hd/recover-seed/confirmation.js index 55b18025f..56ac461ea 100644 --- a/ui/app/recover-seed/confirmation.js +++ b/ui/app/keychains/hd/recover-seed/confirmation.js @@ -3,12 +3,12 @@ const inherits = require('util').inherits const Component = require('react').Component const connect = require('react-redux').connect const h = require('react-hyperscript') -const actions = require('../actions') +const actions = require('../../../actions') -module.exports = connect(mapStateToProps)(RevealSeedConfirmatoin) +module.exports = connect(mapStateToProps)(RevealSeedConfirmation) -inherits(RevealSeedConfirmatoin, Component) -function RevealSeedConfirmatoin () { +inherits(RevealSeedConfirmation, Component) +function RevealSeedConfirmation () { Component.call(this) } @@ -18,9 +18,9 @@ function mapStateToProps (state) { } } -RevealSeedConfirmatoin.prototype.confirmationPhrase = 'I understand' +RevealSeedConfirmation.prototype.confirmationPhrase = 'I understand' -RevealSeedConfirmatoin.prototype.render = function () { +RevealSeedConfirmation.prototype.render = function () { const props = this.props const state = this.state @@ -68,7 +68,7 @@ RevealSeedConfirmatoin.prototype.render = function () { style: { marginTop: '12px', }, - }, 'Enter the phrase "I understand" to proceed.'), + }, `Enter the phrase "${this.confirmationPhrase}" to proceed.`), // confirm confirmation h('input.large-input.letter-spacey', { @@ -116,24 +116,24 @@ RevealSeedConfirmatoin.prototype.render = function () { ) } -RevealSeedConfirmatoin.prototype.componentDidMount = function () { +RevealSeedConfirmation.prototype.componentDidMount = function () { document.getElementById('password-box').focus() } -RevealSeedConfirmatoin.prototype.goHome = function () { +RevealSeedConfirmation.prototype.goHome = function () { this.props.dispatch(actions.showConfigPage(false)) } // create vault -RevealSeedConfirmatoin.prototype.checkConfirmation = function (event) { +RevealSeedConfirmation.prototype.checkConfirmation = function (event) { if (event.key === 'Enter') { event.preventDefault() this.revealSeedWords() } } -RevealSeedConfirmatoin.prototype.revealSeedWords = function () { +RevealSeedConfirmation.prototype.revealSeedWords = function () { this.setState({ confirmationWrong: false }) const confirmBox = document.getElementById('confirm-box') diff --git a/ui/app/first-time/restore-vault.js b/ui/app/keychains/hd/restore-vault.js index 4c1f21008..3fa25a2eb 100644 --- a/ui/app/first-time/restore-vault.js +++ b/ui/app/keychains/hd/restore-vault.js @@ -1,8 +1,8 @@ const inherits = require('util').inherits -const PersistentForm = require('../../lib/persistent-form') +const PersistentForm = require('../../../lib/persistent-form') const connect = require('react-redux').connect const h = require('react-hyperscript') -const actions = require('../actions') +const actions = require('../../actions') module.exports = connect(mapStateToProps)(RestoreVaultScreen) @@ -66,7 +66,7 @@ RestoreVaultScreen.prototype.render = function () { type: 'password', id: 'password-box-confirm', placeholder: 'Confirm Password', - onKeyPress: this.onMaybeCreate.bind(this), + onKeyPress: this.createOnEnter.bind(this), dataset: { persistentFormId: 'password-confirmation', }, @@ -96,7 +96,7 @@ RestoreVaultScreen.prototype.render = function () { // submit h('button.primary', { - onClick: this.restoreVault.bind(this), + onClick: this.createNewVaultAndRestore.bind(this), }, 'OK'), ]), @@ -110,13 +110,13 @@ RestoreVaultScreen.prototype.showInitializeMenu = function () { this.props.dispatch(actions.showInitializeMenu()) } -RestoreVaultScreen.prototype.onMaybeCreate = function (event) { +RestoreVaultScreen.prototype.createOnEnter = function (event) { if (event.key === 'Enter') { - this.restoreVault() + this.createNewVaultAndRestore() } } -RestoreVaultScreen.prototype.restoreVault = function () { +RestoreVaultScreen.prototype.createNewVaultAndRestore = function () { // check password var passwordBox = document.getElementById('password-box') var password = passwordBox.value @@ -144,5 +144,5 @@ RestoreVaultScreen.prototype.restoreVault = function () { // submit this.warning = null this.props.dispatch(actions.displayWarning(this.warning)) - this.props.dispatch(actions.recoverFromSeed(password, seed)) + this.props.dispatch(actions.createNewVaultAndRestore(password, seed)) } diff --git a/ui/app/new-keychain.js b/ui/app/new-keychain.js new file mode 100644 index 000000000..cc9633166 --- /dev/null +++ b/ui/app/new-keychain.js @@ -0,0 +1,29 @@ +const inherits = require('util').inherits +const Component = require('react').Component +const h = require('react-hyperscript') +const connect = require('react-redux').connect + +module.exports = connect(mapStateToProps)(NewKeychain) + +function mapStateToProps (state) { + return {} +} + +inherits(NewKeychain, Component) +function NewKeychain () { + Component.call(this) +} + +NewKeychain.prototype.render = function () { + // const props = this.props + + return ( + h('div', { + style: { + background: 'blue', + }, + }, [ + h('h1', `Here's a list!!!!`), + ]) + ) +} diff --git a/ui/app/reducers.js b/ui/app/reducers.js index a691cf614..4d10e2b39 100644 --- a/ui/app/reducers.js +++ b/ui/app/reducers.js @@ -41,7 +41,7 @@ function rootReducer (state, action) { return state } -window.logState = function() { +window.logState = function () { var stateString = JSON.stringify(window.METAMASK_CACHED_LOG_STATE, null, 2) console.log(stateString) } diff --git a/ui/app/reducers/app.js b/ui/app/reducers/app.js index 5c5c0acce..719d8c8b9 100644 --- a/ui/app/reducers/app.js +++ b/ui/app/reducers/app.js @@ -29,13 +29,10 @@ function reduceApp (state, action) { name: 'createVaultComplete', seedWords, } - var ethStoreWarning = { - name: 'EthStoreWarning', - } var appState = extend({ menuOpen: false, - currentView: seedWords ? seedConfView : !state.metamask.isEthConfirmed ? ethStoreWarning : defaultView, + currentView: seedWords ? seedConfView : defaultView, accountDetail: { subview: 'transactions', }, @@ -46,7 +43,19 @@ function reduceApp (state, action) { switch (action.type) { - // intialize + // transition methods + + case actions.TRANSITION_FORWARD: + return extend(appState, { + transForward: true, + }) + + case actions.TRANSITION_BACKWARD: + return extend(appState, { + transForward: false, + }) + + // intialize case actions.SHOW_CREATE_VAULT: return extend(appState, { @@ -119,6 +128,15 @@ function reduceApp (state, action) { warning: null, }) + case actions.SHOW_NEW_KEYCHAIN: + return extend(appState, { + currentView: { + name: 'newKeychain', + context: appState.currentView.context, + }, + transForward: true, + }) + // unlock case actions.UNLOCK_METAMASK: @@ -227,6 +245,7 @@ function reduceApp (state, action) { isLoading: false, warning: null, scrollToBottom: false, + forgottenPassword: false, }) case actions.SHOW_NOTICE: @@ -278,7 +297,6 @@ function reduceApp (state, action) { warning: null, }) } else { - notification.closePopup() return extend(appState, { @@ -286,7 +304,7 @@ function reduceApp (state, action) { warning: null, currentView: { name: 'accountDetail', - context: state.metamask.selectedAddress, + context: state.metamask.selectedAccount, }, accountDetail: { subview: 'transactions', @@ -335,7 +353,7 @@ function reduceApp (state, action) { case actions.UNLOCK_FAILED: return extend(appState, { - warning: 'Incorrect password. Try again.', + warning: action.value || 'Incorrect password. Try again.', }) case actions.SHOW_LOADING: @@ -546,4 +564,3 @@ function indexForPending (state, txId) { }) return idx } - diff --git a/ui/app/reducers/metamask.js b/ui/app/reducers/metamask.js index 9a1c5814d..8679ab062 100644 --- a/ui/app/reducers/metamask.js +++ b/ui/app/reducers/metamask.js @@ -10,7 +10,6 @@ function reduceMetamask (state, action) { var metamaskState = extend({ isInitialized: false, isUnlocked: false, - isEthConfirmed: false, rpcTarget: 'https://rawtestrpc.metamask.io/', identities: {}, unconfTxs: {}, @@ -44,12 +43,7 @@ function reduceMetamask (state, action) { case actions.AGREE_TO_DISCLAIMER: return extend(metamaskState, { - isConfirmed: true, - }) - - case actions.AGREE_TO_ETH_WARNING: - return extend(metamaskState, { - isEthConfirmed: !metamaskState.isEthConfirmed, + isDisclaimerConfirmed: true, }) case actions.UNLOCK_METAMASK: @@ -117,7 +111,6 @@ function reduceMetamask (state, action) { isUnlocked: true, isInitialized: true, selectedAccount: action.value, - selectedAddress: action.value, }) delete newState.seedWords return newState diff --git a/ui/app/unlock.js b/ui/app/unlock.js index b82e46d02..17416766d 100644 --- a/ui/app/unlock.js +++ b/ui/app/unlock.js @@ -55,6 +55,8 @@ UnlockScreen.prototype.render = function () { h('.error', { style: { display: warning ? 'block' : 'none', + padding: '0 20px', + textAlign: 'center', }, }, warning), @@ -65,6 +67,17 @@ UnlockScreen.prototype.render = function () { }, }, 'Unlock'), ]), + + h('.flex-row.flex-center.flex-grow', [ + h('p.pointer', { + onClick: () => this.props.dispatch(actions.goBackToInitView()), + style: { + fontSize: '0.8em', + color: 'rgb(247, 134, 28)', + textDecoration: 'underline', + }, + }, 'I forgot my password.'), + ]), ]) ) } @@ -103,7 +116,3 @@ UnlockScreen.prototype.inputChanged = function (event) { y: boundingRect.top + coordinates.top - element.scrollTop, }) } - -UnlockScreen.prototype.emitAnim = function (name, a, b, c) { - this.animationEventEmitter.emit(name, a, b, c) -} diff --git a/ui/example.js b/ui/example.js index f4126438c..888748c48 100644 --- a/ui/example.js +++ b/ui/example.js @@ -53,14 +53,14 @@ function addUnconfTx (txParams) { } var isUnlocked = false -var selectedAddress = null +var selectedAccount = null function getState () { return { isUnlocked: isUnlocked, identities: isUnlocked ? identities : {}, unconfTxs: isUnlocked ? unconfTxs : {}, - selectedAddress: selectedAddress, + selectedAccount: selectedAccount, } } @@ -85,8 +85,8 @@ accountManager.submitPassword = function (password, cb) { } } -accountManager.setSelectedAddress = function (address, cb) { - selectedAddress = address +accountManager.setSelectedAccount = function (address, cb) { + selectedAccount = address cb(null, getState()) this._didUpdate() } diff --git a/ui/index.js b/ui/index.js index a6905b639..dedfd8c8c 100644 --- a/ui/index.js +++ b/ui/index.js @@ -8,7 +8,7 @@ module.exports = launchApp function launchApp (opts) { var accountManager = opts.accountManager - actions._setAccountManager(accountManager) + actions._setBackgroundConnection(accountManager) // check if we are unlocked first accountManager.getState(function (err, metamaskState) { diff --git a/ui/lib/account-link.js b/ui/lib/account-link.js index ff52d9c54..77db0851d 100644 --- a/ui/lib/account-link.js +++ b/ui/lib/account-link.js @@ -1,4 +1,4 @@ -module.exports = function(address, network) { +module.exports = function (address, network) { const net = parseInt(network) let link diff --git a/ui/lib/contract-namer.js b/ui/lib/contract-namer.js index c99d44de6..a94c62b62 100644 --- a/ui/lib/contract-namer.js +++ b/ui/lib/contract-namer.js @@ -8,23 +8,22 @@ // Nickname keys must be stored in lower case. const nicknames = {} -module.exports = function(addr, identities = {}) { - +module.exports = function (addr, identities = {}) { const address = addr.toLowerCase() const ids = hashFromIdentities(identities) return addrFromHash(address, ids) || addrFromHash(address, nicknames) } -function hashFromIdentities(identities) { +function hashFromIdentities (identities) { const result = {} - for (let key in identities) { + for (const key in identities) { result[key] = identities[key].name } return result } -function addrFromHash(addr, hash) { +function addrFromHash (addr, hash) { const address = addr.toLowerCase() return hash[address] || null } diff --git a/ui/lib/icon-factory.js b/ui/lib/icon-factory.js index a30041114..82cc839d6 100644 --- a/ui/lib/icon-factory.js +++ b/ui/lib/icon-factory.js @@ -55,6 +55,6 @@ function jsNumberForAddress (address) { return seed } -function toDataUri(identiconSrc){ +function toDataUri (identiconSrc) { return 'data:image/svg+xml;charset=utf-8,' + encodeURIComponent(identiconSrc) -}
\ No newline at end of file +} |