From ff5cbf6f07b664d681bbc97820e3e8c2cfede860 Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Wed, 20 Jan 2016 16:19:25 -0800 Subject: More wallet updates --- bower.json | 1 + package.json | 1 + public/css/coinos.css | 4 ++ public/css/coinos.less | 3 +- public/js/calculator.coffee | 8 +-- public/js/calculator.js | 5 +- public/js/wallet.coffee | 121 ++++++++++++++++--------------------- public/js/wallet.js | 143 ++++++++++++++++++++------------------------ views/users/wallet.html | 36 +++++------ 9 files changed, 142 insertions(+), 180 deletions(-) diff --git a/bower.json b/bower.json index 992dd8e4..7dbb4b43 100644 --- a/bower.json +++ b/bower.json @@ -34,5 +34,6 @@ "jquery-serialize-object": "~2.5.0", "crypto-js": "~3.1.5", "bootbox.js": "bootbox#~4.4.0" + } } diff --git a/package.json b/package.json index ace1ba6b..0f94d4b8 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "bcryptjs": "^2.3.0", "bip39": "^2.2.0", "body-parser": "^1.5.0", + "browser-sync": "^2.11.0", "coffee-script": "1.7.1", "connect-assets": "*", "connect-redis": "2.0.0", diff --git a/public/css/coinos.css b/public/css/coinos.css index b6375221..dc2a3e50 100644 --- a/public/css/coinos.css +++ b/public/css/coinos.css @@ -78,8 +78,12 @@ div#calculator strong#total { font-size: 30px; } div#calculator p#address { + font-size: 16px; padding-top: 10px; } +div#calculator p#address a { + color: #000; +} div#calculator #title { display: none; } diff --git a/public/css/coinos.less b/public/css/coinos.less index 7f202449..11f19007 100644 --- a/public/css/coinos.less +++ b/public/css/coinos.less @@ -33,7 +33,8 @@ div#calculator { #amount { width: 5em; } #received { font-size: 16px; width: 100%; } strong#total { font-size: 30px; } - p#address { padding-top: 10px; } + p#address { font-size: 16px; padding-top: 10px; } + p#address a { color: #000 } #title { display: none; } #title a { color: #000; text-decoration: none; } #logo { display: none; padding: 10px 0; margin-bottom: 10px; max-height: 250px; width: 100%; } diff --git a/public/js/calculator.coffee b/public/js/calculator.coffee index 08a0a0c5..9583a018 100644 --- a/public/js/calculator.coffee +++ b/public/js/calculator.coffee @@ -171,13 +171,7 @@ getAddress = -> catch fail(ADDRESS_FAIL) - s = """ - #{g.user.address} - - - - """ - $('#address').html(s) + $('#address').html("#{g.user.address}") fail = (msg) -> g.errors.push(msg) diff --git a/public/js/calculator.js b/public/js/calculator.js index 840d389b..4d0491cf 100644 --- a/public/js/calculator.js +++ b/public/js/calculator.js @@ -181,7 +181,7 @@ }; getAddress = function() { - var child, master, s; + var child, master; try { bitcoin.address.fromBase58Check(g.user.pubkey); g.user.address = g.user.pubkey; @@ -198,8 +198,7 @@ fail(ADDRESS_FAIL); } } - s = "" + g.user.address + " \n\n \n"; - return $('#address').html(s); + return $('#address').html("" + g.user.address + ""); }; fail = function(msg) { diff --git a/public/js/wallet.coffee b/public/js/wallet.coffee index 97221e00..53734be6 100644 --- a/public/js/wallet.coffee +++ b/public/js/wallet.coffee @@ -10,40 +10,11 @@ validators = catch return false - password: (e) -> - return true if e.val() is '' - 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 - 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.' $(-> @@ -68,14 +39,12 @@ $(-> val = $(this).val() $('#keytype').val('unknown') - $('#phrase').closest('.form-group').show() switch val[0] when '1' try bitcoin.address.fromBase58Check(val) $('#keytype').val('address') - $('#phrase').closest('.form-group').hide() when '5', \ 'L', \ 'K' @@ -84,7 +53,7 @@ $(-> $('#keytype').val('wif') when 'U' try - if CryptoJS.AES.decrypt(val, $('#phrase').val()).toString(CryptoJS.enc.Utf8) + if CryptoJS.AES.decrypt(val, g.password).toString(CryptoJS.enc.Utf8) $('#keytype').val('aes') when '6' if bip38().verify(val) @@ -94,7 +63,6 @@ $(-> try bitcoin.HDNode.fromBase58(val) $('#keytype').val('xpub') - $('#phrase').closest('.form-group').hide() else try bitcoin.HDNode.fromBase58(val) @@ -104,10 +72,6 @@ $(-> $('#keytype').val('bip39') ) - $('#key').blur(-> - $('#keys form').validator('validate') - ) - $('#save').click(-> $('.form-control').blur() if $('#keys .has-error').length > 0 @@ -123,25 +87,25 @@ $(-> $('#privkey').val('') when 'wif' pubkey = bitcoin.ECPair.fromWIF(key).getAddress() - privkey = CryptoJS.AES.encrypt(key, $('#phrase').val()) + privkey = CryptoJS.AES.encrypt(key, g.password) $('#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 = bitcoin.HDNode.fromBase58(CryptoJS.AES.decrypt(key, g.password).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 = bitcoin.ECPair.fromWIF(CryptoJS.AES.decrypt(key, g.password).toString(CryptoJS.enc.Utf8)).getAddress() $('#pubkey').val(pubkey) $('#privkey').val(key) catch proceed = false when 'bip38' - wif = bip38().decrypt(key, $('#phrase').val()) + wif = bip38().decrypt(key, g.password) pubkey = bitcoin.ECPair.fromWIF(wif).getAddress() - privkey = CryptoJS.AES.encrypt(wif, $('#phrase').val()) + privkey = CryptoJS.AES.encrypt(wif, g.password) $('#pubkey').val(pubkey) $('#privkey, #key').val(privkey) when 'xpub' @@ -149,17 +113,22 @@ $(-> $('#privkey').val('') when 'xprv' pubkey = bitcoin.HDNode.fromBase58(key).neutered().toString() - privkey = CryptoJS.AES.encrypt(key, $('#phrase').val()) + privkey = CryptoJS.AES.encrypt(key, g.password) $('#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()) + privkey = CryptoJS.AES.encrypt(master.toString(), g.password) $('#pubkey').val(pubkey) $('#privkey').val(privkey) - updateUser() if proceed + if proceed + updateUser() + $('#keys').hide() + $('#keys_updated').fadeIn() + $('#balances').hide() + $('#fetching').show() ) @@ -199,16 +168,28 @@ $(-> $(this).val($(this).attr('max')) ) - $('#phrase').keyup(-> + $('#password').keyup(-> try - CryptoJS.AES.decrypt(g.user.privkey, $(this).val()).toString(CryptoJS.enc.Utf8) - $('#key').keyup() + if g.user.privkey + g.privkey = CryptoJS.AES.decrypt(g.user.privkey, $(this).val()).toString(CryptoJS.enc.Utf8) + + if g.privkey[0] is 'x' + g.key = bitcoin.HDNode.fromBase58(g.privkey) + else + g.key = bitcoin.ECPair.fromWIF(g.privkey) + + $('#key').val(g.privkey).keyup() + else + $('#key').val(g.user.pubkey).keyup() + + $(this).closest('.form-group').hide() + $('.wallet').fadeIn() + g.password = $(this).val() ) $('#manage').click(-> $('#withdrawal').hide() $('#keys').show() - $('#withdraw').hide().toggle(g.balance > 0 and g.user.privkey) $('#privkey').val(g.user.privkey) ) @@ -216,20 +197,24 @@ $(-> $('#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() + if g.balance > 0 and g.user.privkey + $('#withdrawal form').validator('destroy') + $('#withdrawal form').validator(custom: validators, errors: errors, delay: 1200) + $('#withdrawal').show() + $('#amount').focus() ) $('#backup').click(-> url = 'data:application/json;base64,' + btoa(JSON.stringify(g.user.privkey)) a = document.createElement('a') a.setAttribute('href', url) - a.setAttribute('download', 'coinos-wallet.aes.json') + a.setAttribute('download', 'wallet.json.aes') a.click() ) @@ -239,8 +224,6 @@ $(-> 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() ) ) @@ -250,16 +233,18 @@ $(-> getUser = -> $.getJSON("/#{$('#username').val()}.json", (user) -> g.user = user - g.privkey = user.privkey - $('#key').val(user.privkey or user.pubkey).keyup() + $('#key').val(user.pubkey) $('#pubkey').val(user.pubkey) $('#privkey').val(user.privkey) $('#address').val(user.address) $('#unit').html(user.unit) $('#currency_toggle').html(user.unit) $('#amount').attr('step', 0.00000001 * multiplier()) + $('#password').closest('.form-group').show() + $('#password').focus() getExchangeRate() + $('#password').keyup() ) getExchangeRate = -> @@ -294,7 +279,8 @@ getBalance = -> $('#balance').html(g.balance) $('#fiat').html("#{fiat} #{g.user.currency}") $('#amount').attr('max', g.balance) - $('.wallet').fadeIn() + $('#balances').show() + $('#fetching').hide() if g.balance > 0 and g.user.privkey $('#keys').hide() @@ -302,35 +288,28 @@ getBalance = -> $('#withdrawal form').validator(custom: validators, errors: errors, delay: 1200) $('#withdrawal').show() $('#amount').focus() - else - $('#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}" + url: "#{g.api}/wallets/#{g.user.username}" type: 'DELETE' ).always(-> $.ajax( - url: "#{g.api}/wallets/#{g.user.username}" + url: "#{g.api}/wallets/hd/#{g.user.username}" type: 'DELETE' ).always(-> - $('#keys').hide() - createWallet() + getUser() ) ) ) sendTransaction = -> - if !g.key or (typeof g.key.d is 'undefined' and typeof g.key.keyPair.d is 'undefined') - $('#invalid_keys').fadeIn() - $('#password').focus() - else + if g.key and not (typeof g.key.d is 'undefined' and typeof g.key.keyPair.d is 'undefined') dialog = new BootstrapDialog( title: '

Confirm Transaction

' message: ' Calculating fee...' @@ -386,6 +365,7 @@ sendTransaction = -> if value > parseFloat(g.balance).toSatoshis() - data.tx.fees total += fee + $('.dialog .amount').html("#{(amount.toBTC())} #{g.user.unit} (#{amount.toFiat()} #{g.user.currency})") $('.dialog .fee').html("#{(fee.toBTC())} #{g.user.unit} (#{fee.toFiat()} #{g.user.currency})") $('.dialog .total').html("#{(total.toBTC())} #{g.user.unit} (#{total.toFiat()} #{g.user.currency})") @@ -393,6 +373,9 @@ sendTransaction = -> dialog.getModalBody().html($('.dialog').html()) + if amount.toBTC() < 0.00000534 + displayErrors({errors: [error: 'Amount left over after fee is too small to send']}, dialog) + dialog.getModal().find('.btn-primary').click(-> $.post("#{g.api}/txs/send", JSON.stringify(g.data)).then((finaltx) -> $('#transaction_sent').fadeIn() @@ -401,7 +384,7 @@ sendTransaction = -> fiat = balance.toFiat() $('#balance').html(g.balance) $('#fiat').html("#{fiat} #{g.user.currency}") - $('#blockchain').off('click').on('click', -> window.open('https://live.blockcypher.com/btc/main/tx/' + finaltx.tx.hash, '_blank')) + $('#blockchain').off('click').on('click', -> window.open('https://tradeblock.com/bitcoin/tx/' + finaltx.tx.hash, '_blank')) dialog.close() ) ) @@ -456,7 +439,7 @@ precision = -> 9 - multiplier().toString().length Number.prototype.toBTC = -> - parseFloat((this / 100000000 * multiplier()).toFixed(precision())) + parseFloat((this / 100000000 * multiplier())).toFixed(precision()) Number.prototype.toFiat = -> (this * g.exchange / 100000000).toFixed(2) diff --git a/public/js/wallet.js b/public/js/wallet.js index 15dfab03..c7cdd4c3 100644 --- a/public/js/wallet.js +++ b/public/js/wallet.js @@ -20,38 +20,6 @@ return false; } }, - password: function(e) { - var s; - if (e.val() === '') { - return true; - } - g.key = null; - try { - 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'; } @@ -59,8 +27,6 @@ errors = { address: 'Invalid address.', - password: 'Wrong password.', - phrase: 'Wrong password.', key: 'Could not detect key type.' }; @@ -85,13 +51,11 @@ var val, _ref; val = $(this).val(); $('#keytype').val('unknown'); - $('#phrase').closest('.form-group').show(); switch (val[0]) { case '1': try { bitcoin.address.fromBase58Check(val); - $('#keytype').val('address'); - return $('#phrase').closest('.form-group').hide(); + return $('#keytype').val('address'); } catch (_error) {} break; case '5': @@ -104,7 +68,7 @@ break; case 'U': try { - if (CryptoJS.AES.decrypt(val, $('#phrase').val()).toString(CryptoJS.enc.Utf8)) { + if (CryptoJS.AES.decrypt(val, g.password).toString(CryptoJS.enc.Utf8)) { return $('#keytype').val('aes'); } } catch (_error) {} @@ -118,8 +82,7 @@ if ($(this).val()[3] === 'b') { try { bitcoin.HDNode.fromBase58(val); - $('#keytype').val('xpub'); - return $('#phrase').closest('.form-group').hide(); + return $('#keytype').val('xpub'); } catch (_error) {} } else { try { @@ -134,9 +97,6 @@ } } }); - $('#key').blur(function() { - return $('#keys form').validator('validate'); - }); $('#save').click(function() { var key, master, privkey, proceed, pubkey, wif; $('.form-control').blur(); @@ -153,18 +113,18 @@ break; case 'wif': pubkey = bitcoin.ECPair.fromWIF(key).getAddress(); - privkey = CryptoJS.AES.encrypt(key, $('#phrase').val()); + privkey = CryptoJS.AES.encrypt(key, g.password); $('#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 = bitcoin.HDNode.fromBase58(CryptoJS.AES.decrypt(key, g.password).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 = bitcoin.ECPair.fromWIF(CryptoJS.AES.decrypt(key, g.password).toString(CryptoJS.enc.Utf8)).getAddress(); $('#pubkey').val(pubkey); $('#privkey').val(key); } catch (_error) { @@ -173,9 +133,9 @@ } break; case 'bip38': - wif = bip38().decrypt(key, $('#phrase').val()); + wif = bip38().decrypt(key, g.password); pubkey = bitcoin.ECPair.fromWIF(wif).getAddress(); - privkey = CryptoJS.AES.encrypt(wif, $('#phrase').val()); + privkey = CryptoJS.AES.encrypt(wif, g.password); $('#pubkey').val(pubkey); $('#privkey, #key').val(privkey); break; @@ -185,19 +145,23 @@ break; case 'xprv': pubkey = bitcoin.HDNode.fromBase58(key).neutered().toString(); - privkey = CryptoJS.AES.encrypt(key, $('#phrase').val()); + privkey = CryptoJS.AES.encrypt(key, g.password); $('#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()); + privkey = CryptoJS.AES.encrypt(master.toString(), g.password); $('#pubkey').val(pubkey); $('#privkey').val(privkey); } if (proceed) { - return updateUser(); + updateUser(); + $('#keys').hide(); + $('#keys_updated').fadeIn(); + $('#balances').hide(); + return $('#fetching').show(); } }); $('#withdrawal form input[type=button]').click(sendTransaction); @@ -237,23 +201,33 @@ return $(this).val($(this).attr('max')); } }); - $('#phrase').keyup(function() { + $('#password').keyup(function() { try { - CryptoJS.AES.decrypt(g.user.privkey, $(this).val()).toString(CryptoJS.enc.Utf8); - return $('#key').keyup(); + if (g.user.privkey) { + g.privkey = CryptoJS.AES.decrypt(g.user.privkey, $(this).val()).toString(CryptoJS.enc.Utf8); + if (g.privkey[0] === 'x') { + g.key = bitcoin.HDNode.fromBase58(g.privkey); + } else { + g.key = bitcoin.ECPair.fromWIF(g.privkey); + } + $('#key').val(g.privkey).keyup(); + } else { + $('#key').val(g.user.pubkey).keyup(); + } + $(this).closest('.form-group').hide(); + $('.wallet').fadeIn(); + return g.password = $(this).val(); } catch (_error) {} }); $('#manage').click(function() { $('#withdrawal').hide(); $('#keys').show(); - $('#withdraw').hide().toggle(g.balance > 0 && g.user.privkey); return $('#privkey').val(g.user.privkey); }); $('#withdraw').click(function() { $('#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, @@ -262,14 +236,24 @@ }); }); $('#cancel').click(function() { - return $('#keys').hide(); + $('#keys').hide(); + if (g.balance > 0 && g.user.privkey) { + $('#withdrawal form').validator('destroy'); + $('#withdrawal form').validator({ + custom: validators, + errors: errors, + delay: 1200 + }); + $('#withdrawal').show(); + return $('#amount').focus(); + } }); $('#backup').click(function() { var a, url; url = 'data:application/json;base64,' + btoa(JSON.stringify(g.user.privkey)); a = document.createElement('a'); a.setAttribute('href', url); - a.setAttribute('download', 'coinos-wallet.aes.json'); + a.setAttribute('download', 'wallet.json.aes'); return a.click(); }); $('#generate').click(function() { @@ -278,9 +262,7 @@ 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 $('#key').val(key.toString()).effect('highlight', {}, 2000).keyup(); } }); }); @@ -292,15 +274,17 @@ getUser = function() { return $.getJSON("/" + ($('#username').val()) + ".json", function(user) { g.user = user; - g.privkey = user.privkey; - $('#key').val(user.privkey || user.pubkey).keyup(); + $('#key').val(user.pubkey); $('#pubkey').val(user.pubkey); $('#privkey').val(user.privkey); $('#address').val(user.address); $('#unit').html(user.unit); $('#currency_toggle').html(user.unit); $('#amount').attr('step', 0.00000001 * multiplier()); - return getExchangeRate(); + $('#password').closest('.form-group').show(); + $('#password').focus(); + getExchangeRate(); + return $('#password').keyup(); }); }; @@ -345,7 +329,8 @@ $('#balance').html(g.balance); $('#fiat').html("" + fiat + " " + g.user.currency); $('#amount').attr('max', g.balance); - $('.wallet').fadeIn(); + $('#balances').show(); + $('#fetching').hide(); if (g.balance > 0 && g.user.privkey) { $('#keys').hide(); $('#withdrawal form').validator('destroy'); @@ -356,8 +341,6 @@ }); $('#withdrawal').show(); return $('#amount').focus(); - } else { - return $('#withdraw').hide(); } }); }; @@ -366,18 +349,16 @@ 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, + url: "" + g.api + "/wallets/" + g.user.username, type: 'DELETE' }).always(function() { return $.ajax({ - url: "" + g.api + "/wallets/" + g.user.username, + url: "" + g.api + "/wallets/hd/" + g.user.username, type: 'DELETE' }).always(function() { - $('#keys').hide(); - return createWallet(); + return getUser(); }); }); }); @@ -385,10 +366,7 @@ sendTransaction = function() { var dialog, params; - if (!g.key || (typeof g.key.d === 'undefined' && typeof g.key.keyPair.d === 'undefined')) { - $('#invalid_keys').fadeIn(); - return $('#password').focus(); - } else { + if (g.key && !(typeof g.key.d === 'undefined' && typeof g.key.keyPair.d === 'undefined')) { dialog = new BootstrapDialog({ title: '

Confirm Transaction

', message: ' Calculating fee...', @@ -463,6 +441,15 @@ $('.dialog .total').html("" + (total.toBTC()) + " " + g.user.unit + " (" + (total.toFiat()) + " " + g.user.currency + ")"); $('.dialog .address').html(data.tx.outputs[0].addresses[0]); dialog.getModalBody().html($('.dialog').html()); + if (amount.toBTC() < 0.00000534) { + displayErrors({ + errors: [ + { + error: 'Amount left over after fee is too small to send' + } + ] + }, dialog); + } return dialog.getModal().find('.btn-primary').click(function() { return $.post("" + g.api + "/txs/send", JSON.stringify(g.data)).then(function(finaltx) { var balance, fiat; @@ -473,7 +460,7 @@ $('#balance').html(g.balance); $('#fiat').html("" + fiat + " " + g.user.currency); $('#blockchain').off('click').on('click', function() { - return window.open('https://live.blockcypher.com/btc/main/tx/' + finaltx.tx.hash, '_blank'); + return window.open('https://tradeblock.com/bitcoin/tx/' + finaltx.tx.hash, '_blank'); }); return dialog.close(); }); @@ -552,7 +539,7 @@ }; Number.prototype.toBTC = function() { - return parseFloat((this / 100000000 * multiplier()).toFixed(precision())); + return parseFloat(this / 100000000 * multiplier()).toFixed(precision()); }; Number.prototype.toFiat = function() { diff --git a/views/users/wallet.html b/views/users/wallet.html index 0a546864..a7d850e1 100644 --- a/views/users/wallet.html +++ b/views/users/wallet.html @@ -7,20 +7,27 @@ {{/yield-scripts}} - -
-
- - -
-
-
- -- cgit v1.2.3