diff options
Diffstat (limited to 'public')
| -rw-r--r-- | public/img/village_books.png | bin | 0 -> 121526 bytes | |||
| -rw-r--r-- | public/js/calculator.coffee | 2 | ||||
| -rw-r--r-- | public/js/calculator.js | 2 | ||||
| -rw-r--r-- | public/js/register.coffee | 16 | ||||
| -rw-r--r-- | public/js/register.js | 22 | ||||
| -rw-r--r-- | public/js/wallet.coffee | 253 | ||||
| -rw-r--r-- | public/js/wallet.js | 296 |
7 files changed, 386 insertions, 205 deletions
diff --git a/public/img/village_books.png b/public/img/village_books.png Binary files differnew file mode 100644 index 00000000..3743f069 --- /dev/null +++ b/public/img/village_books.png diff --git a/public/js/calculator.coffee b/public/js/calculator.coffee index 27606325..08a0a0c5 100644 --- a/public/js/calculator.coffee +++ b/public/js/calculator.coffee @@ -112,7 +112,7 @@ listen = -> clear(SOCKET_FAIL) g.blockchain.send('{"op":"addr_sub", "addr":"' + g.user.address + '"}') else - setTimeout(g.blockchain.onopen, 12000) + setTimeout(g.blockchain.onopen, 12000 * g.attempts) g.blockchain.onerror = -> fail(SOCKET_FAIL) diff --git a/public/js/calculator.js b/public/js/calculator.js index 39b47598..840d389b 100644 --- a/public/js/calculator.js +++ b/public/js/calculator.js @@ -130,7 +130,7 @@ clear(SOCKET_FAIL); return g.blockchain.send('{"op":"addr_sub", "addr":"' + g.user.address + '"}'); } else { - return setTimeout(g.blockchain.onopen, 12000); + return setTimeout(g.blockchain.onopen, 12000 * g.attempts); } }; g.blockchain.onerror = function() { diff --git a/public/js/register.coffee b/public/js/register.coffee index 0963d9d1..b012713f 100644 --- a/public/js/register.coffee +++ b/public/js/register.coffee @@ -4,17 +4,6 @@ $(-> $('#username').focus() $('#password').pwstrength(showVerdicts: false) - mnemonic = bip39.generateMnemonic() - key = bitcoin.HDNode.fromSeedBuffer(bip39.mnemonicToSeed(mnemonic)).deriveHardened(44).deriveHardened(0) - $('#pubkey').val(key.neutered().toString()) - privkey = key.toString() - - $('#password').keyup((e) -> - return if e.keyCode is 9 or e.keyCode is 16 - enc_privkey = CryptoJS.AES.encrypt(privkey, $(this).val()).toString() - enc_privkey = privkey if $(this).val() == '' - $('#privkey').val(enc_privkey) - ) $('#username').blur(-> $(this).parent().next('.alert').remove() @@ -62,5 +51,10 @@ $(-> if $('.has-error').length > 0 $('.has-error').effect('shake', 500) return false + else + mnemonic = bip39.generateMnemonic() + key = bitcoin.HDNode.fromSeedBuffer(bip39.mnemonicToSeed(mnemonic)).deriveHardened(44).deriveHardened(0) + $('#pubkey').val(key.neutered().toString()) + $('#privkey').val(CryptoJS.AES.encrypt(key.toString(), $('#password').val()).toString()) ) ) diff --git a/public/js/register.js b/public/js/register.js index 02041163..5872896c 100644 --- a/public/js/register.js +++ b/public/js/register.js @@ -5,26 +5,10 @@ g = this; $(function() { - var key, mnemonic, privkey; $('#username').focus(); $('#password').pwstrength({ showVerdicts: false }); - mnemonic = bip39.generateMnemonic(); - key = bitcoin.HDNode.fromSeedBuffer(bip39.mnemonicToSeed(mnemonic)).deriveHardened(44).deriveHardened(0); - $('#pubkey').val(key.neutered().toString()); - privkey = key.toString(); - $('#password').keyup(function(e) { - var enc_privkey; - if (e.keyCode === 9 || e.keyCode === 16) { - return; - } - enc_privkey = CryptoJS.AES.encrypt(privkey, $(this).val()).toString(); - if ($(this).val() === '') { - enc_privkey = privkey; - } - return $('#privkey').val(enc_privkey); - }); $('#username').blur(function() { $(this).parent().next('.alert').remove(); if (/^[a-z]+$/.test($(this).val()) && $(this).val().length > 2) { @@ -68,10 +52,16 @@ } }); return $('#register').submit(function() { + var key, mnemonic; $('.form-control').blur(); if ($('.has-error').length > 0) { $('.has-error').effect('shake', 500); return false; + } else { + mnemonic = bip39.generateMnemonic(); + key = bitcoin.HDNode.fromSeedBuffer(bip39.mnemonicToSeed(mnemonic)).deriveHardened(44).deriveHardened(0); + $('#pubkey').val(key.neutered().toString()); + return $('#privkey').val(CryptoJS.AES.encrypt(key.toString(), $('#password').val()).toString()); } }); }); diff --git a/public/js/wallet.coffee b/public/js/wallet.coffee index 32688150..97221e00 100644 --- a/public/js/wallet.coffee +++ b/public/js/wallet.coffee @@ -12,16 +12,39 @@ validators = password: (e) -> return true if e.val() is '' - g.master = null + g.key = null + + try + s = CryptoJS.AES.decrypt($('#privkey').val(), e.val()).toString(CryptoJS.enc.Utf8) + if s[0] is 'x' + g.key = bitcoin.HDNode.fromBase58(s) + else + g.key = bitcoin.ECPair.fromWIF(s) + catch + return false + + $('#invalid_keys').fadeOut() + + phrase: (e) -> try - g.master = bitcoin.HDNode.fromBase58(CryptoJS.AES.decrypt($('#privkey').val(), e.val()).toString(CryptoJS.enc.Utf8)) - $('#invalid_keys').fadeOut() + s = CryptoJS.AES.decrypt(g.user.privkey, e.val()).toString(CryptoJS.enc.Utf8) + if s[0] is 'x' + bitcoin.HDNode.fromBase58(s) + else + bitcoin.ECPair.fromWIF(s) catch return false + $('#invalid_keys').fadeOut() + + key: (e) -> + $('#keytype').val() != 'unknown' + errors = address: 'Invalid address.' password: 'Wrong password.' + phrase: 'Wrong password.' + key: 'Could not detect key type.' $(-> getUser() @@ -38,79 +61,108 @@ $(-> .popover(html: true) .on("show.bs.popover", -> $(this).data("bs.popover").tip().css(minWidth: "400px")) - $('form').validator(custom: validators, errors: errors) + $('form').validator(custom: validators, errors: errors, delay: 1200) $('[data-toggle=tooltip]').tooltip(trigger: 'hover') - $('#pubkey').keyup(-> + $('#key').keyup(-> val = $(this).val() - $('#type').val('unknown') + + $('#keytype').val('unknown') + $('#phrase').closest('.form-group').show() + switch val[0] when '1' try bitcoin.address.fromBase58Check(val) - $('#type').val('address') + $('#keytype').val('address') + $('#phrase').closest('.form-group').hide() when '5', \ 'L', \ 'K' try bitcoin.ECPair.fromWIF(val) - $('#type').val('private_key') + $('#keytype').val('wif') when 'U' try - CryptoJS.AES.decrypt(val, $('#new_password').val()) - $('#type').val('aes') + if CryptoJS.AES.decrypt(val, $('#phrase').val()).toString(CryptoJS.enc.Utf8) + $('#keytype').val('aes') when '6' - try - key = bip38().decrypt(val, $('#new_password').val()) - bitcoin.ECPair.fromWIF(key) - $('#type').val('bip38') + if bip38().verify(val) + $('#keytype').val('bip38') when 'x' if $(this).val()[3] is 'b' try bitcoin.HDNode.fromBase58(val) - $('#type').val('xpub') + $('#keytype').val('xpub') + $('#phrase').closest('.form-group').hide() else try bitcoin.HDNode.fromBase58(val) - $('#type').val('xprv') + $('#keytype').val('xprv') else - if val.split(' ').length in [12, 15, 18, 21, 24] - if bip39.validateMnemonic(val) - $('#type').val('bip39') + if val.split(' ').length in [12, 15, 18, 21, 24] and bip39.validateMnemonic(val) + $('#keytype').val('bip39') + ) + + $('#key').blur(-> + $('#keys form').validator('validate') ) - $('#keys form input[type=button]').click(-> + $('#save').click(-> $('.form-control').blur() if $('#keys .has-error').length > 0 $('#keys .has-error').effect('shake', 500) return - $('#withdraw').click() - $('#keys_updated').fadeIn() + key = $('#key').val() + proceed = true - $.post("/#{g.user.username}", $('#keys form').serializeObject(), -> - $.ajax( - url: "#{g.api}/wallets/hd/#{g.user.username}" - type: 'DELETE' - ).done(-> - setTimeout(-> - data = - name: g.user.username - extended_public_key: $('#pubkey').val() - subchain_indexes: [0,1] - - $.post("#{g.api}/wallets/hd", JSON.stringify(data)).always(-> - $.post("#{g.api}/wallets/hd/#{g.user.username}/addresses/derive").always(-> - getBalance() - ) - ) - , 300) - ) - ) + switch $('#keytype').val() + when 'address' + $('#pubkey').val(key) + $('#privkey').val('') + when 'wif' + pubkey = bitcoin.ECPair.fromWIF(key).getAddress() + privkey = CryptoJS.AES.encrypt(key, $('#phrase').val()) + $('#pubkey').val(pubkey) + $('#privkey').val(privkey) + when 'aes' + try + pubkey = bitcoin.HDNode.fromBase58(CryptoJS.AES.decrypt(key, $('#phrase').val()).toString(CryptoJS.enc.Utf8)).neutered().toString() + $('#pubkey').val(pubkey) + $('#privkey').val(key) + catch + try + pubkey = bitcoin.ECPair.fromWIF(CryptoJS.AES.decrypt(key, $('#phrase').val()).toString(CryptoJS.enc.Utf8)).getAddress() + $('#pubkey').val(pubkey) + $('#privkey').val(key) + catch + proceed = false + when 'bip38' + wif = bip38().decrypt(key, $('#phrase').val()) + pubkey = bitcoin.ECPair.fromWIF(wif).getAddress() + privkey = CryptoJS.AES.encrypt(wif, $('#phrase').val()) + $('#pubkey').val(pubkey) + $('#privkey, #key').val(privkey) + when 'xpub' + $('#pubkey').val(key) + $('#privkey').val('') + when 'xprv' + pubkey = bitcoin.HDNode.fromBase58(key).neutered().toString() + privkey = CryptoJS.AES.encrypt(key, $('#phrase').val()) + $('#pubkey').val(pubkey) + $('#privkey').val(privkey) + when 'bip39' + master = bitcoin.HDNode.fromSeedBuffer(bip39.mnemonicToSeed(key)).deriveHardened(44).deriveHardened(0) + pubkey = master.neutered().toString() + privkey = CryptoJS.AES.encrypt(master.toString(), $('#phrase').val()) + $('#pubkey').val(pubkey) + $('#privkey').val(privkey) - return false + updateUser() if proceed ) + $('#withdrawal form input[type=button]').click(sendTransaction) $('#currency_toggle').click(-> @@ -147,46 +199,49 @@ $(-> $(this).val($(this).attr('max')) ) - $('#password').keyup(-> - ) - - $('#new_password').keyup(-> - $('#privkey').val(CryptoJS.AES.encrypt(g.privkey, $(this).val())) - + $('#phrase').keyup(-> try - bitcoin.HDNode.fromBase58(CryptoJS.AES.decrypt(g.user.privkey, $(this).val()).toString(CryptoJS.enc.Utf8)) - catch + CryptoJS.AES.decrypt(g.user.privkey, $(this).val()).toString(CryptoJS.enc.Utf8) + $('#key').keyup() ) - + $('#manage').click(-> $('#withdrawal').hide() $('#keys').show() - $('#withdraw').toggle(g.balance > 0) - $('#manage').hide() + $('#withdraw').hide().toggle(g.balance > 0 and g.user.privkey) $('#privkey').val(g.user.privkey) ) $('#withdraw').click(-> - $('#keys, #withdrawal').toggle() - $('#withdraw, #manage').toggle() + $('#withdrawal').show() + $('#amount').focus() + $('#keys').hide() + $('#withdraw').hide().toggle(g.balance > 0 and g.user.privkey) + $('#withdrawal form').validator('destroy') + $('#withdrawal form').validator(custom: validators, errors: errors, delay: 1200) + ) + + $('#cancel').click(-> + $('#keys').hide() ) $('#backup').click(-> url = 'data:application/json;base64,' + btoa(JSON.stringify(g.user.privkey)) - pom = document.createElement('a') - pom.setAttribute('href', url) - pom.setAttribute('download', 'coinos-wallet.aes.json') - pom.click() + a = document.createElement('a') + a.setAttribute('href', url) + a.setAttribute('download', 'coinos-wallet.aes.json') + a.click() ) $('#generate').click(-> - mnemonic = bip39.generateMnemonic() - key = bitcoin.HDNode.fromSeedBuffer(bip39.mnemonicToSeed(mnemonic)).deriveHardened(44).deriveHardened(0) - g.privkey = key.toString() - $('#pubkey').val(key.neutered().toString()).effect('highlight', {}, 2000).keyup() - $('#privkey').val('') - $('#new_password').parent().show() - $('#new_password').effect('shake', 500).focus() + bootbox.confirm('<h3>Are you sure?</h3> <p>This will overwrite your existing wallet so make sure that you have the backup we sent to your email in case you want to restore it.</p>', (result) -> + if result + mnemonic = bip39.generateMnemonic() + key = bitcoin.HDNode.fromSeedBuffer(bip39.mnemonicToSeed(mnemonic)).deriveHardened(44).deriveHardened(0) + $('#key').val(key.toString()).effect('highlight', {}, 2000).keyup() + $('#phrase').parent().show() + $('#phrase').effect('shake', 500).focus() + ) ) $('.close').on('click', -> $(this).closest('.alert').fadeOut()) @@ -195,7 +250,9 @@ $(-> getUser = -> $.getJSON("/#{$('#username').val()}.json", (user) -> g.user = user - $('#pubkey').val(user.pubkey).keyup() + g.privkey = user.privkey + $('#key').val(user.privkey or user.pubkey).keyup() + $('#pubkey').val(user.pubkey) $('#privkey').val(user.privkey) $('#address').val(user.address) $('#unit').html(user.unit) @@ -216,17 +273,16 @@ createWallet = -> if g.user.username in data.wallet_names getBalance() else + params = name: g.user.username + if isBip32(g.user.pubkey) - data = - name: g.user.username - extended_public_key: g.user.pubkey - subchain_indexes: [0,1] + params.extended_public_key = g.user.pubkey + params.subchain_indexes = [0,1] - $.post("#{g.api}/wallets/hd", JSON.stringify(data)).always(getBalance) + $.post("#{g.api}/wallets/hd", JSON.stringify(params)).done(getBalance).fail(-> $('.wallet').fadeIn()) else - # TODO implement this properly - $('#balance').html(99) - $('#amount').val(99) + params.addresses = [g.user.pubkey] + $.post("#{g.api}/wallets", JSON.stringify(params)).done(getBalance).fail(-> $('.wallet').fadeIn()) ) @@ -240,15 +296,38 @@ getBalance = -> $('#amount').attr('max', g.balance) $('.wallet').fadeIn() - if g.balance > 0 + if g.balance > 0 and g.user.privkey + $('#keys').hide() + $('#withdrawal form').validator('destroy') + $('#withdrawal form').validator(custom: validators, errors: errors, delay: 1200) $('#withdrawal').show() $('#amount').focus() else - $('#manage').click() + $('#withdraw').hide() + ) + +updateUser = -> + data = $('#keys form').serializeObject() + delete data['key'] + delete data['phrase'] + + $.post("/#{g.user.username}", data, -> + $.ajax( + url: "#{g.api}/wallets/hd/#{g.user.username}" + type: 'DELETE' + ).always(-> + $.ajax( + url: "#{g.api}/wallets/#{g.user.username}" + type: 'DELETE' + ).always(-> + $('#keys').hide() + createWallet() + ) + ) ) sendTransaction = -> - if !g.master or typeof g.master.keyPair.d is 'undefined' + if !g.key or (typeof g.key.d is 'undefined' and typeof g.key.keyPair.d is 'undefined') $('#invalid_keys').fadeIn() $('#password').focus() else @@ -286,12 +365,18 @@ sendTransaction = -> $.post("#{g.api}/txs/new", JSON.stringify(params)).done((data) -> data.pubkeys = [] - data.signatures = data.tosign.map((tosign, i) -> - path = data.tx.inputs[i].hd_path.split('/') - key = g.master.derive(path[1]).derive(path[2]) - data.pubkeys.push(key.keyPair.getPublicKeyBuffer().toString('hex')) - return key.keyPair.sign(new buffer.Buffer(tosign, "hex")).toDER().toString("hex") - ) + if g.key instanceof bitcoin.ECPair + data.signatures = data.tosign.map((tosign, i) -> + data.pubkeys.push(g.key.getPublicKeyBuffer().toString('hex')) + g.key.sign(new buffer.Buffer(tosign, "hex")).toDER().toString("hex") + ) + else + data.signatures = data.tosign.map((tosign, i) -> + path = data.tx.inputs[i].hd_path.split('/') + key = g.key.derive(path[1]).derive(path[2]) + data.pubkeys.push(key.keyPair.getPublicKeyBuffer().toString('hex')) + key.keyPair.sign(new buffer.Buffer(tosign, "hex")).toDER().toString("hex") + ) g.data = data diff --git a/public/js/wallet.js b/public/js/wallet.js index 9a2d1ff5..15dfab03 100644 --- a/public/js/wallet.js +++ b/public/js/wallet.js @@ -1,6 +1,6 @@ ;(function(e,t,n){function i(n,s){if(!t[n]){if(!e[n]){var o=typeof require=="function"&&require;if(!s&&o)return o(n,!0);if(r)return r(n,!0);throw new Error("Cannot find module '"+n+"'")}var u=t[n]={exports:{}};e[n][0](function(t){var r=e[n][1][t];return i(r?r:t)},u,u.exports)}return t[n].exports}var r=typeof require=="function"&&require;for(var s=0;s<n.length;s++)i(n[s]);return i})({1:[function(require,module,exports){ (function(){(function() { - var check_address, convertedAmount, createWallet, displayErrors, errors, g, getBalance, getExchangeRate, getUser, isBip32, multiplier, precision, sendTransaction, validators, + var check_address, convertedAmount, createWallet, displayErrors, errors, g, getBalance, getExchangeRate, getUser, isBip32, multiplier, precision, sendTransaction, updateUser, validators, __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; g = typeof exports !== "undefined" && exports !== null ? exports : this; @@ -21,22 +21,47 @@ } }, password: function(e) { + var s; if (e.val() === '') { return true; } - g.master = null; + g.key = null; try { - g.master = bitcoin.HDNode.fromBase58(CryptoJS.AES.decrypt($('#privkey').val(), e.val()).toString(CryptoJS.enc.Utf8)); - return $('#invalid_keys').fadeOut(); + s = CryptoJS.AES.decrypt($('#privkey').val(), e.val()).toString(CryptoJS.enc.Utf8); + if (s[0] === 'x') { + g.key = bitcoin.HDNode.fromBase58(s); + } else { + g.key = bitcoin.ECPair.fromWIF(s); + } } catch (_error) { return false; } + return $('#invalid_keys').fadeOut(); + }, + phrase: function(e) { + var s; + try { + s = CryptoJS.AES.decrypt(g.user.privkey, e.val()).toString(CryptoJS.enc.Utf8); + if (s[0] === 'x') { + bitcoin.HDNode.fromBase58(s); + } else { + bitcoin.ECPair.fromWIF(s); + } + } catch (_error) { + return false; + } + return $('#invalid_keys').fadeOut(); + }, + key: function(e) { + return $('#keytype').val() !== 'unknown'; } }; errors = { address: 'Invalid address.', - password: 'Wrong password.' + password: 'Wrong password.', + phrase: 'Wrong password.', + key: 'Could not detect key type.' }; $(function() { @@ -50,20 +75,23 @@ }); $('form').validator({ custom: validators, - errors: errors + errors: errors, + delay: 1200 }); $('[data-toggle=tooltip]').tooltip({ trigger: 'hover' }); - $('#pubkey').keyup(function() { - var key, val, _ref; + $('#key').keyup(function() { + var val, _ref; val = $(this).val(); - $('#type').val('unknown'); + $('#keytype').val('unknown'); + $('#phrase').closest('.form-group').show(); switch (val[0]) { case '1': try { bitcoin.address.fromBase58Check(val); - return $('#type').val('address'); + $('#keytype').val('address'); + return $('#phrase').closest('.form-group').hide(); } catch (_error) {} break; case '5': @@ -71,72 +99,106 @@ case 'K': try { bitcoin.ECPair.fromWIF(val); - return $('#type').val('private_key'); + return $('#keytype').val('wif'); } catch (_error) {} break; case 'U': try { - CryptoJS.AES.decrypt(val, $('#new_password').val()); - return $('#type').val('aes'); + if (CryptoJS.AES.decrypt(val, $('#phrase').val()).toString(CryptoJS.enc.Utf8)) { + return $('#keytype').val('aes'); + } } catch (_error) {} break; case '6': - try { - key = bip38().decrypt(val, $('#new_password').val()); - bitcoin.ECPair.fromWIF(key); - return $('#type').val('bip38'); - } catch (_error) {} + if (bip38().verify(val)) { + return $('#keytype').val('bip38'); + } break; case 'x': if ($(this).val()[3] === 'b') { try { bitcoin.HDNode.fromBase58(val); - return $('#type').val('xpub'); + $('#keytype').val('xpub'); + return $('#phrase').closest('.form-group').hide(); } catch (_error) {} } else { try { bitcoin.HDNode.fromBase58(val); - return $('#type').val('xprv'); + return $('#keytype').val('xprv'); } catch (_error) {} } break; default: - if ((_ref = val.split(' ').length) === 12 || _ref === 15 || _ref === 18 || _ref === 21 || _ref === 24) { - if (bip39.validateMnemonic(val)) { - return $('#type').val('bip39'); - } + if (((_ref = val.split(' ').length) === 12 || _ref === 15 || _ref === 18 || _ref === 21 || _ref === 24) && bip39.validateMnemonic(val)) { + return $('#keytype').val('bip39'); } } }); - $('#keys form input[type=button]').click(function() { + $('#key').blur(function() { + return $('#keys form').validator('validate'); + }); + $('#save').click(function() { + var key, master, privkey, proceed, pubkey, wif; $('.form-control').blur(); if ($('#keys .has-error').length > 0) { $('#keys .has-error').effect('shake', 500); return; } - $('#withdraw').click(); - $('#keys_updated').fadeIn(); - $.post("/" + g.user.username, $('#keys form').serializeObject(), function() { - return $.ajax({ - url: "" + g.api + "/wallets/hd/" + g.user.username, - type: 'DELETE' - }).done(function() { - return setTimeout(function() { - var data; - data = { - name: g.user.username, - extended_public_key: $('#pubkey').val(), - subchain_indexes: [0, 1] - }; - return $.post("" + g.api + "/wallets/hd", JSON.stringify(data)).always(function() { - return $.post("" + g.api + "/wallets/hd/" + g.user.username + "/addresses/derive").always(function() { - return getBalance(); - }); - }); - }, 300); - }); - }); - return false; + key = $('#key').val(); + proceed = true; + switch ($('#keytype').val()) { + case 'address': + $('#pubkey').val(key); + $('#privkey').val(''); + break; + case 'wif': + pubkey = bitcoin.ECPair.fromWIF(key).getAddress(); + privkey = CryptoJS.AES.encrypt(key, $('#phrase').val()); + $('#pubkey').val(pubkey); + $('#privkey').val(privkey); + break; + case 'aes': + try { + pubkey = bitcoin.HDNode.fromBase58(CryptoJS.AES.decrypt(key, $('#phrase').val()).toString(CryptoJS.enc.Utf8)).neutered().toString(); + $('#pubkey').val(pubkey); + $('#privkey').val(key); + } catch (_error) { + try { + pubkey = bitcoin.ECPair.fromWIF(CryptoJS.AES.decrypt(key, $('#phrase').val()).toString(CryptoJS.enc.Utf8)).getAddress(); + $('#pubkey').val(pubkey); + $('#privkey').val(key); + } catch (_error) { + proceed = false; + } + } + break; + case 'bip38': + wif = bip38().decrypt(key, $('#phrase').val()); + pubkey = bitcoin.ECPair.fromWIF(wif).getAddress(); + privkey = CryptoJS.AES.encrypt(wif, $('#phrase').val()); + $('#pubkey').val(pubkey); + $('#privkey, #key').val(privkey); + break; + case 'xpub': + $('#pubkey').val(key); + $('#privkey').val(''); + break; + case 'xprv': + pubkey = bitcoin.HDNode.fromBase58(key).neutered().toString(); + privkey = CryptoJS.AES.encrypt(key, $('#phrase').val()); + $('#pubkey').val(pubkey); + $('#privkey').val(privkey); + break; + case 'bip39': + master = bitcoin.HDNode.fromSeedBuffer(bip39.mnemonicToSeed(key)).deriveHardened(44).deriveHardened(0); + pubkey = master.neutered().toString(); + privkey = CryptoJS.AES.encrypt(master.toString(), $('#phrase').val()); + $('#pubkey').val(pubkey); + $('#privkey').val(privkey); + } + if (proceed) { + return updateUser(); + } }); $('#withdrawal form input[type=button]').click(sendTransaction); $('#currency_toggle').click(function() { @@ -175,43 +237,52 @@ return $(this).val($(this).attr('max')); } }); - $('#password').keyup(function() {}); - $('#new_password').keyup(function() { - $('#privkey').val(CryptoJS.AES.encrypt(g.privkey, $(this).val())); + $('#phrase').keyup(function() { try { - return bitcoin.HDNode.fromBase58(CryptoJS.AES.decrypt(g.user.privkey, $(this).val()).toString(CryptoJS.enc.Utf8)); - } catch (_error) { - - } + CryptoJS.AES.decrypt(g.user.privkey, $(this).val()).toString(CryptoJS.enc.Utf8); + return $('#key').keyup(); + } catch (_error) {} }); $('#manage').click(function() { $('#withdrawal').hide(); $('#keys').show(); - $('#withdraw').toggle(g.balance > 0); - $('#manage').hide(); + $('#withdraw').hide().toggle(g.balance > 0 && g.user.privkey); return $('#privkey').val(g.user.privkey); }); $('#withdraw').click(function() { - $('#keys, #withdrawal').toggle(); - return $('#withdraw, #manage').toggle(); + $('#withdrawal').show(); + $('#amount').focus(); + $('#keys').hide(); + $('#withdraw').hide().toggle(g.balance > 0 && g.user.privkey); + $('#withdrawal form').validator('destroy'); + return $('#withdrawal form').validator({ + custom: validators, + errors: errors, + delay: 1200 + }); + }); + $('#cancel').click(function() { + return $('#keys').hide(); }); $('#backup').click(function() { - var pom, url; + var a, url; url = 'data:application/json;base64,' + btoa(JSON.stringify(g.user.privkey)); - pom = document.createElement('a'); - pom.setAttribute('href', url); - pom.setAttribute('download', 'coinos-wallet.aes.json'); - return pom.click(); + a = document.createElement('a'); + a.setAttribute('href', url); + a.setAttribute('download', 'coinos-wallet.aes.json'); + return a.click(); }); $('#generate').click(function() { - var key, mnemonic; - mnemonic = bip39.generateMnemonic(); - key = bitcoin.HDNode.fromSeedBuffer(bip39.mnemonicToSeed(mnemonic)).deriveHardened(44).deriveHardened(0); - g.privkey = key.toString(); - $('#pubkey').val(key.neutered().toString()).effect('highlight', {}, 2000).keyup(); - $('#privkey').val(''); - $('#new_password').parent().show(); - return $('#new_password').effect('shake', 500).focus(); + return bootbox.confirm('<h3>Are you sure?</h3> <p>This will overwrite your existing wallet so make sure that you have the backup we sent to your email in case you want to restore it.</p>', function(result) { + var key, mnemonic; + if (result) { + mnemonic = bip39.generateMnemonic(); + key = bitcoin.HDNode.fromSeedBuffer(bip39.mnemonicToSeed(mnemonic)).deriveHardened(44).deriveHardened(0); + $('#key').val(key.toString()).effect('highlight', {}, 2000).keyup(); + $('#phrase').parent().show(); + return $('#phrase').effect('shake', 500).focus(); + } + }); }); return $('.close').on('click', function() { return $(this).closest('.alert').fadeOut(); @@ -221,7 +292,9 @@ getUser = function() { return $.getJSON("/" + ($('#username').val()) + ".json", function(user) { g.user = user; - $('#pubkey').val(user.pubkey).keyup(); + g.privkey = user.privkey; + $('#key').val(user.privkey || user.pubkey).keyup(); + $('#pubkey').val(user.pubkey); $('#privkey').val(user.privkey); $('#address').val(user.address); $('#unit').html(user.unit); @@ -240,20 +313,24 @@ createWallet = function() { return $.get("" + g.api + "/wallets", function(data) { - var _ref; + var params, _ref; if (_ref = g.user.username, __indexOf.call(data.wallet_names, _ref) >= 0) { return getBalance(); } else { + params = { + name: g.user.username + }; if (isBip32(g.user.pubkey)) { - data = { - name: g.user.username, - extended_public_key: g.user.pubkey, - subchain_indexes: [0, 1] - }; - return $.post("" + g.api + "/wallets/hd", JSON.stringify(data)).always(getBalance); + params.extended_public_key = g.user.pubkey; + params.subchain_indexes = [0, 1]; + return $.post("" + g.api + "/wallets/hd", JSON.stringify(params)).done(getBalance).fail(function() { + return $('.wallet').fadeIn(); + }); } else { - $('#balance').html(99); - return $('#amount').val(99); + params.addresses = [g.user.pubkey]; + return $.post("" + g.api + "/wallets", JSON.stringify(params)).done(getBalance).fail(function() { + return $('.wallet').fadeIn(); + }); } } }); @@ -269,18 +346,46 @@ $('#fiat').html("" + fiat + " " + g.user.currency); $('#amount').attr('max', g.balance); $('.wallet').fadeIn(); - if (g.balance > 0) { + if (g.balance > 0 && g.user.privkey) { + $('#keys').hide(); + $('#withdrawal form').validator('destroy'); + $('#withdrawal form').validator({ + custom: validators, + errors: errors, + delay: 1200 + }); $('#withdrawal').show(); return $('#amount').focus(); } else { - return $('#manage').click(); + return $('#withdraw').hide(); } }); }; + updateUser = function() { + var data; + data = $('#keys form').serializeObject(); + delete data['key']; + delete data['phrase']; + return $.post("/" + g.user.username, data, function() { + return $.ajax({ + url: "" + g.api + "/wallets/hd/" + g.user.username, + type: 'DELETE' + }).always(function() { + return $.ajax({ + url: "" + g.api + "/wallets/" + g.user.username, + type: 'DELETE' + }).always(function() { + $('#keys').hide(); + return createWallet(); + }); + }); + }); + }; + sendTransaction = function() { var dialog, params; - if (!g.master || typeof g.master.keyPair.d === 'undefined') { + if (!g.key || (typeof g.key.d === 'undefined' && typeof g.key.keyPair.d === 'undefined')) { $('#invalid_keys').fadeIn(); return $('#password').focus(); } else { @@ -332,13 +437,20 @@ return $.post("" + g.api + "/txs/new", JSON.stringify(params)).done(function(data) { var fee, total; data.pubkeys = []; - data.signatures = data.tosign.map(function(tosign, i) { - var key, path; - path = data.tx.inputs[i].hd_path.split('/'); - key = g.master.derive(path[1]).derive(path[2]); - data.pubkeys.push(key.keyPair.getPublicKeyBuffer().toString('hex')); - return key.keyPair.sign(new buffer.Buffer(tosign, "hex")).toDER().toString("hex"); - }); + if (g.key instanceof bitcoin.ECPair) { + data.signatures = data.tosign.map(function(tosign, i) { + data.pubkeys.push(g.key.getPublicKeyBuffer().toString('hex')); + return g.key.sign(new buffer.Buffer(tosign, "hex")).toDER().toString("hex"); + }); + } else { + data.signatures = data.tosign.map(function(tosign, i) { + var key, path; + path = data.tx.inputs[i].hd_path.split('/'); + key = g.key.derive(path[1]).derive(path[2]); + data.pubkeys.push(key.keyPair.getPublicKeyBuffer().toString('hex')); + return key.keyPair.sign(new buffer.Buffer(tosign, "hex")).toDER().toString("hex"); + }); + } g.data = data; amount = data.tx.outputs[0].value; fee = data.tx.fees; |
