diff --git a/dl/src/actions/ImportKeysActions.js b/dl/src/actions/ImportKeysActions.js deleted file mode 100644 index ad2b14622..000000000 --- a/dl/src/actions/ImportKeysActions.js +++ /dev/null @@ -1,17 +0,0 @@ -import alt from "alt-instance" - -export default alt.generateActions( "setStatus" ) - -/* -class ImportKeysActions { - - saved() { - this.dispatch() - } - -} - - -var ImportKeysActionsWrapped = alt.createActions(ImportKeysActions) -export default ImportKeysActionsWrapped -*/ diff --git a/dl/src/alt-instance.js b/dl/src/alt-instance.js index 2d961139a..4bc9e6256 100644 --- a/dl/src/alt-instance.js +++ b/dl/src/alt-instance.js @@ -1,9 +1,7 @@ var Alt = require("alt"); var alt = new Alt(); - // DEBUG log all action events -// https://github.com/goatslacker/alt/issues/516 -// alt.dispatcher.register('alt.dispatcher', console.log.bind(console)) +alt.dispatcher.register(console.log.bind(console, 'alt.dispatcher')) module.exports = alt; diff --git a/dl/src/stores/AddressIndex.js b/dl/src/stores/AddressIndex.js index d7d141dd6..5bae35a99 100644 --- a/dl/src/stores/AddressIndex.js +++ b/dl/src/stores/AddressIndex.js @@ -47,39 +47,39 @@ class AddressIndex extends BaseStore { /** Worker thread implementation (for more than 10K keys) */ addAll(pubkeys) { - console.log("addAll"); - this.saving() - this.loadAddyMap().then( () => { - var AddressIndexWorker = require("worker!workers/AddressIndexWorker") - var worker = new AddressIndexWorker - worker.postMessage({ pubkeys }) - var _this = this - worker.onmessage = event => { try { - console.log("addAll onmessage"); - var key_addresses = event.data - var dirty = false - var addresses = _this.state.addresses.withMutations( addresses => { - for(let i = 0; i < pubkeys.length; i++) { - var pubkey = pubkeys[i] - if(_this.pubkeys.has(pubkey)) continue - _this.pubkeys.add(pubkey) - // Gather all 5 legacy address formats (see key.addresses) - var address_strings = key_addresses[i] - for(let address of address_strings) { - addresses.set(address, pubkey) - dirty = true + return new Promise( (resolve, reject) => { + this.saving() + this.loadAddyMap().then( () => { + var AddressIndexWorker = require("worker!workers/AddressIndexWorker") + var worker = new AddressIndexWorker + worker.postMessage({ pubkeys }) + var _this = this + worker.onmessage = event => { try { + var key_addresses = event.data + var dirty = false + var addresses = _this.state.addresses.withMutations( addresses => { + for(let i = 0; i < pubkeys.length; i++) { + var pubkey = pubkeys[i] + if(_this.pubkeys.has(pubkey)) continue + _this.pubkeys.add(pubkey) + // Gather all 5 legacy address formats (see key.addresses) + var address_strings = key_addresses[i] + for(let address of address_strings) { + addresses.set(address, pubkey) + dirty = true + } } + }) + if( dirty ) { + _this.setState({ addresses }) + _this.saveAddyMap() + } else { + _this.setState({ saving: false }) } - }) - if( dirty ) { - _this.setState({ addresses }) - _this.saveAddyMap() - } else { - _this.setState({ saving: false }) - } - console.log("addAll onmessage done"); - } catch( e ) { console.error('AddressIndex.addAll', e) }} - }).catch ( e => { throw e }) + resolve() + } catch( e ) { console.error('AddressIndex.addAll', e); reject(e) }} + }).catch ( e => { throw e }) + }) } loadAddyMap() { diff --git a/dl/src/stores/ImportKeysStore.js b/dl/src/stores/ImportKeysStore.js deleted file mode 100644 index 183591712..000000000 --- a/dl/src/stores/ImportKeysStore.js +++ /dev/null @@ -1,18 +0,0 @@ -import alt from "alt-instance" - -import ImportKeysActions from "actions/ImportKeysActions" - -class ImportKeysStore { - - constructor() { - this.bindActions(ImportKeysActions) - } - - onSetStatus(status) { - this.setState({status}) - } - -} - -export var ImportKeysStoreWrapped = alt.createStore(ImportKeysStore, "ImportKeysStore"); -export default ImportKeysStoreWrapped diff --git a/dl/src/stores/PrivateKeyStore.js b/dl/src/stores/PrivateKeyStore.js index ddae7462e..f3e811c9b 100644 --- a/dl/src/stores/PrivateKeyStore.js +++ b/dl/src/stores/PrivateKeyStore.js @@ -8,6 +8,7 @@ import {PrivateKeyTcomb} from "./tcomb_structs"; import PrivateKeyActions from "actions/PrivateKeyActions" import CachedPropertyActions from "actions/CachedPropertyActions" import AddressIndex from "stores/AddressIndex" +import ChainStore from "api/ChainStore" import PublicKey from "ecc/key_public" import Address from "ecc/address" @@ -169,9 +170,11 @@ class PrivateKeyStore extends BaseStore { var private_tcomb = PrivateKeyTcomb(private_key_object) store.add( private_key_object ) keys.set( private_key_object.pubkey, private_tcomb ) + ChainStore.getAccountRefsOfKey(private_key_object.pubkey) } }) this.setState({ keys }) + this.binaryBackupRecommended() return duplicate_count } diff --git a/dl/src/stores/WalletDb.js b/dl/src/stores/WalletDb.js index 934abe94f..63b467e10 100644 --- a/dl/src/stores/WalletDb.js +++ b/dl/src/stores/WalletDb.js @@ -35,7 +35,7 @@ class WalletDb extends BaseStore { // WalletDb use to be a plan old javascript class (not an Alt store) so // for now many methods need to be exported... this._export( - "checkNextGeneratedKey","getWallet","onLock","isLocked","decryptTcomb_PrivateKey","getPrivateKey","process_transaction","transaction_update","transaction_update_keys","getBrainKey","getBrainKeyPrivate","onCreateWallet","validatePassword","changePassword","generateNextKey","incrementBrainKeySequence","importKeys","saveKeys","saveKey","setWalletModified","setBackupDate","setBrainkeyBackupDate","_updateWallet","loadDbData", + "checkNextGeneratedKey","getWallet","onLock","isLocked","decryptTcomb_PrivateKey","getPrivateKey","process_transaction","transaction_update","transaction_update_keys","getBrainKey","getBrainKeyPrivate","onCreateWallet","validatePassword","changePassword","generateNextKey","incrementBrainKeySequence","saveKeys","saveKey","setWalletModified","setBackupDate","setBrainkeyBackupDate","_updateWallet","loadDbData", "importKeysWorker" ) } @@ -337,11 +337,11 @@ class WalletDb extends BaseStore { } importKeysWorker(private_key_objs) { - WalletUnlockActions.unlock().then( () => { + return new Promise( (resolve, reject) => { var pubkeys = [] for(let private_key_obj of private_key_objs) pubkeys.push( private_key_obj.public_key_string ) - AddressIndex.addAll(pubkeys) + var addyIndexPromise = AddressIndex.addAll(pubkeys) var private_plainhex_array = [] for(let private_key_obj of private_key_objs) @@ -379,74 +379,28 @@ class WalletDb extends BaseStore { } enc_private_key_objs.push(private_key_object) } - console.log("Ready to save private keys"); + console.log("Saving private keys", new Date().toString()); var transaction = _this.transaction_update_keys() + var insertKeysPromise = idb_helper.on_transaction_end(transaction) try { - var duplicate_count = PrivateKeyStore. - addPrivateKeys_noindex(enc_private_key_objs, transaction ) + var duplicate_count = PrivateKeyStore + .addPrivateKeys_noindex(enc_private_key_objs, transaction ) if( private_key_objs.length != duplicate_count ) _this.setWalletModified(transaction) _this.setState({saving_keys: false}) + resolve(Promise.all([ insertKeysPromise, addyIndexPromise ]).then( ()=> { + console.log("Done saving keys", new Date().toString()) + // return { duplicate_count } + })) } catch(e) { transaction.abort() console.error(e) + reject(e) } - console.log("Done saving keys"); } catch( e ) { console.error('AesWorker.encrypt', e) }} }) } - importKeys(private_key_objs) { - if(TRACE) console.log('... WalletDb.importKeys START') - return WalletUnlockActions.unlock().then( () => { - var transaction = this.transaction_update_keys() - var promises = [] - var import_count = 0, duplicate_count = 0 - if(TRACE) console.log('... importKeys save key loop start') - for(let private_key_obj of private_key_objs) { - - var private_key = - private_key_obj.private_key || - PrivateKey.fromWif( private_key_obj.wif ) - - if( ! private_key) { - console.error("ERROR WalletDb importKeys, missing private_key or wif") - continue - } - promises.push( - this.saveKey( - private_key, - null,//brainkey_sequence - private_key_obj.import_account_names, - private_key_obj.public_key_string, - transaction - ).then( - ret => { - if(ret.result == "duplicate") { - duplicate_count++ - } else if(ret.result == "added") { - import_count++ - } else - throw new Error('unknown return',ret) - return ret.id - } - ) - ) - } - if(TRACE) console.log('... importKeys save key loop done') - return this.setWalletModified(transaction).then( ()=> { - return Promise.all(promises).catch( error => { - //DEBUG - console.log('importKeys transaction.abort', error) - throw error - }).then( private_key_ids => { - if(TRACE) console.log('... WalletDb.importKeys done') - return {import_count, duplicate_count, private_key_ids} - }) - }) - }) - } - saveKeys(private_keys, transaction, public_key_string) { var promises = [] for(let private_key_record of private_keys) { diff --git a/web/app/components/Wallet/BalanceClaimAssetTotal.jsx b/web/app/components/Wallet/BalanceClaimAssetTotal.jsx index ed7ee0d3f..d2d68761b 100644 --- a/web/app/components/Wallet/BalanceClaimAssetTotal.jsx +++ b/web/app/components/Wallet/BalanceClaimAssetTotal.jsx @@ -23,7 +23,7 @@ export default class BalanceClaimAssetTotals extends Component { .map( l => l.reduce( (r,v) => r + Number(v.balance.amount), 0 )) if( ! total_by_asset.size) - return
No balances to claim
+ return
None
return
{total_by_asset.map( (total, asset_id) => diff --git a/web/app/components/Wallet/ImportKeys.jsx b/web/app/components/Wallet/ImportKeys.jsx index 34f8a88d0..6c8f7c0f1 100644 --- a/web/app/components/Wallet/ImportKeys.jsx +++ b/web/app/components/Wallet/ImportKeys.jsx @@ -10,7 +10,6 @@ import hash from "common/hash"; import Apis from "rpc_api/ApiInstances" import PrivateKeyStore from "stores/PrivateKeyStore" -import ImportKeysActions from "actions/ImportKeysActions"; import WalletUnlockActions from "actions/WalletUnlockActions" import WalletCreate from "components/Wallet/WalletCreate" import LoadingIndicator from "components/LoadingIndicator" @@ -20,6 +19,7 @@ import BalanceClaimActiveActions from "actions/BalanceClaimActiveActions" import BalanceClaimAssetTotal from "components/Wallet/BalanceClaimAssetTotal" import WalletDb from "stores/WalletDb"; import PublicKey from "ecc/key_public"; +import AddressIndex from "stores/AddressIndex" require("./ImportKeys.scss"); @@ -53,6 +53,7 @@ export default class ImportKeys extends Component { } reset(e) { + console.log("imp reset"); if(e) e.preventDefault() var state = this._getInitialState(); this.setState(state); @@ -60,8 +61,9 @@ export default class ImportKeys extends Component { } render() { - - if(this.state.save_import_loading) { + // console.log("ImportKeys render") + if( ! WalletDb.getWallet()) return + if( this.state.save_import_loading) { return

@@ -69,7 +71,6 @@ export default class ImportKeys extends Component {
} - var has_keys = this.state.key_count !== 0; var import_ready = has_keys var password_placeholder = "Enter import file password"; @@ -92,11 +93,13 @@ export default class ImportKeys extends Component { // Create wallet prior to the import keys (helps keep the layout clean) return (
-

{/* Key file upload */}
- + {this.state.key_text_message ? + this.state.key_text_message : + + } {!this.state.key_count ? null : (RESET) @@ -138,7 +141,6 @@ export default class ImportKeys extends Component { onChange={this._passwordCheck.bind(this)} />
{this.state.import_password_message}
-
{this.state.key_text_message}
) : null}
@@ -193,7 +195,6 @@ export default class ImportKeys extends Component {
) : null} - ); } @@ -236,21 +237,23 @@ export default class ImportKeys extends Component { reader.onload = evt => { var contents = evt.target.result try { + var json_contents try { + json_contents = JSON.parse(contents) // This is the only chance to encounter a large file, // try this format first. - this._parseImportKeyUpload(contents, file) + this._parseImportKeyUpload(json_contents) } catch(e) { - //DEBUG console.log("... _parseWalletJson",e) + //DEBUG console.log("... _parseImportKeyUpload",e) try { - this._parseWalletJson(contents) + if( ! json_contents) file.name + " is an unrecognized format" + this._parseWalletJson(json_contents) } catch(ee) { if( ! this.addByPattern(contents)) throw ee } } - var pwNode = React.findDOMNode(this.refs.password) - if(pwNode) pwNode.focus() + this._passwordFocus() // try empty password, also display "Enter import file password" this._passwordCheck() @@ -264,21 +267,19 @@ export default class ImportKeys extends Component { } /** BTS 1.0 client wallet_export_keys format. */ - _parseImportKeyUpload(contents, file) { + _parseImportKeyUpload(json_contents, file) { var password_checksum, account_keys try { - var import_keys = JSON.parse(contents) - password_checksum = import_keys.password_checksum + password_checksum = json_contents.password_checksum if( ! password_checksum) throw file.name + " is an unrecognized format" - if( ! Array.isArray(import_keys.account_keys)) + if( ! Array.isArray(json_contents.account_keys)) throw file.name + " is an unrecognized format" - account_keys = import_keys.account_keys + account_keys = json_contents.account_keys } catch(e) { throw e.message || e } - this.setState({ password_checksum, account_keys @@ -296,7 +297,7 @@ export default class ImportKeys extends Component { keys. */ - _parseWalletJson(contents) { + _parseWalletJson(json_contents) { var password_checksum var encrypted_brainkey var address_to_enckeys = {} @@ -314,12 +315,11 @@ export default class ImportKeys extends Component { } try { - var wallet_json = JSON.parse(contents) - if(! Array.isArray(wallet_json)) { - //DEBUG console.log('... wallet_json',wallet_json) + if(! Array.isArray(json_contents)) { + //DEBUG console.log('... json_contents',json_contents) throw new Error("Invalid wallet format") } - for(let element of wallet_json) { + for(let element of json_contents) { if( "key_record_type" == element.type && element.data.account_address && @@ -394,6 +394,11 @@ export default class ImportKeys extends Component { //encrypted_brainkey }) } + + _passwordFocus() { + var pwNode = React.findDOMNode(this.refs.password) + if(pwNode) pwNode.focus() + } _passwordCheck(evt) { if( ! this.state.account_keys.length) @@ -439,7 +444,7 @@ export default class ImportKeys extends Component { var private_plainhex = password_aes.decryptHex(encrypted_private) if(import_keys_assert_checking && public_key_string) { var private_key = PrivateKey.fromHex( private_plainhex ) - var pub = private_key.toPublicKey() + var pub = private_key.toPublicKey() // S L O W var addy = pub.toAddressString() var pubby = pub.toPublicKeyString() var error = "" @@ -457,10 +462,9 @@ export default class ImportKeys extends Component { console.log("ERROR Miss-match key",error) } - var public_key if( ! public_key_string) { var private_key = PrivateKey.fromHex( private_plainhex ) - public_key = private_key.toPublicKey()// S L O W + var public_key = private_key.toPublicKey()// S L O W public_key_string = public_key.toPublicKeyString() } else { if( ! same_prefix_regex.test(public_key_string)) @@ -479,7 +483,6 @@ export default class ImportKeys extends Component { dup = true if(dup) continue account_names.push(account_name) - var public_key = this.state.keys_to_account[private_plainhex] = {account_names, public_key_string} } catch(e) { console.log(e, e.stack) @@ -520,54 +523,30 @@ export default class ImportKeys extends Component { saveImport() { // Lookup and add accounts referenced by the keys - var imported_keys_public = this.state.imported_keys_public - var db = Apis.instance().db_api() + // var imported_keys_public = this.state.imported_keys_public + // var db = Apis.instance().db_api() if(TRACE) console.log('... ImportKeys._saveImport START') - ImportKeysActions.setStatus("saving") var keys_to_account = this.state.keys_to_account var private_key_objs = [] for(let private_plainhex of Object.keys(keys_to_account)) { var {account_names, public_key_string} = keys_to_account[private_plainhex] private_key_objs.push({ - private_key: PrivateKey.fromHex(private_plainhex), + private_plainhex, import_account_names: account_names, public_key_string }) } - this.reset() - - WalletDb.importKeys( private_key_objs ).then( result => { + WalletDb.importKeysWorker( private_key_objs ).then( result => { this.setState({save_import_loading: false}) - var {import_count, duplicate_count, private_key_ids} = result - if( ! import_count && ! duplicate_count) { - notify.warning(`There where no keys to import`) - return - } - if( ! import_count && duplicate_count) { - notify.warning(`${duplicate_count} duplicates (Not Imported)`) - return - } - var message = "" - if (import_count) - message = `Successfully imported ${import_count} keys.` - if (duplicate_count) - message += ` ${duplicate_count} duplicates (Not Imported)` - - if(duplicate_count) - notify.warning(message) - else - notify.success(message) - - if (import_count) { - ImportKeysActions.setStatus("saveDone") - this.onBack() // back to claim balances - } + var import_count = private_key_objs.length + notify.success(`Successfully imported ${import_count} keys.`) + this.onBack() // back to claim balances }).catch( error => { - ImportKeysActions.setStatus("saveError") console.log("error:", error) + this.setState({save_import_loading: false}) var message = error try { message = error.target.error.message } catch (e){} notify.error(`Key import error: ${message}`) @@ -584,16 +563,24 @@ export default class ImportKeys extends Component { try { var private_key = PrivateKey.fromWif(wif) //could throw and error var private_plainhex = private_key.toBuffer().toString('hex') - this.state.keys_to_account[private_plainhex] = {account_names: []} + var public_key = private_key.toPublicKey() // S L O W + var public_key_string = public_key.toPublicKeyString() + this.state.imported_keys_public[public_key_string] = true + this.state.keys_to_account[private_plainhex] = { + account_names: [], public_key_string} count++ } catch(e) { invalid_count++ } } this.updateOnChange() this.setState({ - key_text_message: - (!count ? "" : count + " keys found from text.") + - (!invalid_count ? "" : " " + invalid_count + " invalid keys.") + imported_keys_public: this.state.imported_keys_public, + keys_to_account: this.state.keys_to_account, + key_text_message: 'Found ' + + (!count ? "" : count + " valid") + + (!invalid_count ? "" : " and " + invalid_count + " invalid") + + " key" + ( count > 1 || invalid_count > 1 ? "s" : "") + "." }) + this.state.key_text_message = null return count }