g = exports ? this
g.proceed = false
g.api = '/blockcypher/v1/btc/main'
validators =
address: (e) ->
return true if e.val() is ''
try
bitcoin.address.fromBase58Check(e.val())
catch
return false
key: (e) ->
$('#keytype').val() != 'unknown'
errors =
address: 'Invalid address.'
key: 'Could not detect key type.'
$(->
getUser()
$('#types').attr('data-content', """
Bitcoin Address (starts with 1 or 3)
Private Key (starts with 5 or L)
HD Wallet pubkey (starts with xpub)
HD Wallet private key (starts with xprv)
AES Encrypted Private Key (starts with U)
BIP38 Encrypted Private Key (starts with 6)
BIP39 Mnemonic (series of 12-24 english words)
""")
.popover(html: true)
.on("show.bs.popover", -> $(this).data("bs.popover").tip().css(minWidth: "400px"))
$('form').validator(custom: validators, errors: errors, delay: 1200)
$('[data-toggle=tooltip]').tooltip(trigger: 'hover')
$('#key').keyup(->
val = $(this).val()
$('#keytype').val('unknown')
switch val[0]
when '1'
try
bitcoin.address.fromBase58Check(val)
$('#keytype').val('address')
when 'm'
try
bitcoin.address.fromBase58Check(val)
$('#keytype').val('address')
when '5', \
'L', \
'K'
try
bitcoin.ECPair.fromWIF(val)
$('#keytype').val('wif')
when 'U'
try
if CryptoJS.AES.decrypt(val, g.password).toString(CryptoJS.enc.Utf8)
$('#keytype').val('aes')
when '6'
if bip38().verify(val)
$('#keytype').val('bip38')
when 'x'
if $(this).val()[3] is 'b'
try
bitcoin.HDNode.fromBase58(val)
$('#keytype').val('xpub')
else
try
bitcoin.HDNode.fromBase58(val)
$('#keytype').val('xprv')
else
if val.split(' ').length in [12, 15, 18, 21, 24] and bip39.validateMnemonic(val)
$('#keytype').val('bip39')
)
$('#save').click(->
$('.form-control').blur()
if $('#keys .has-error').length > 0
$('#keys .has-error').effect('shake', 500)
return
key = $('#key').val()
proceed = true
switch $('#keytype').val()
when 'address'
$('#pubkey').val(key)
$('#privkey').val('')
when 'wif'
pubkey = bitcoin.ECPair.fromWIF(key).getAddress()
privkey = CryptoJS.AES.encrypt(key, g.password)
$('#pubkey').val(pubkey)
$('#privkey').val(privkey)
when 'aes'
try
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, g.password).toString(CryptoJS.enc.Utf8)).getAddress()
$('#pubkey').val(pubkey)
$('#privkey').val(key)
catch
proceed = false
when 'bip38'
wif = bip38().decrypt(key, g.password)
pubkey = bitcoin.ECPair.fromWIF(wif).getAddress()
privkey = CryptoJS.AES.encrypt(wif, g.password)
$('#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, 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(), g.password)
$('#pubkey').val(pubkey)
$('#privkey').val(privkey)
if proceed
updateUser()
$('#keys').hide()
$('#keys_updated').fadeIn()
$('#balances').hide()
$('#fetching').show()
)
$('#withdrawal form input[type=button]').click(sendTransaction)
$('#currency_toggle').click(->
if $(this).html() is g.user.unit
$(this).html(g.user.currency)
g.amount = parseFloat($('#amount').val()).toFixed(precision())
amount = (g.amount * g.exchange / multiplier()).toFixed(2)
$('#amount').val(amount)
$('#amount').attr('step', 0.01)
$('#amount').attr('max', (g.balance * g.exchange / multiplier()).toFixed(2))
else
$(this).html(g.user.unit)
$('#amount').val(convertedAmount())
$('#amount').attr('step', 0.00000001 * multiplier())
$('#amount').attr('max', g.balance)
)
$('#max').click(->
if $('#currency_toggle').html() is g.user.unit
$('#amount').val(g.balance).blur()
else
g.amount = parseFloat(g.balance).toFixed(precision())
amount = (g.balance / multiplier() * g.exchange).toFixed(2)
$('#amount').val(amount).blur()
)
$('#amount').change(->
if $('#currency_toggle').html() is g.user.unit
$(this).val(parseFloat($(this).val()).toFixed(precision()))
else
$(this).val(parseFloat($(this).val()).toFixed(2))
if parseFloat($(this).val()) > parseFloat($(this).attr('max'))
$(this).val($(this).attr('max'))
)
$('#password').keyup(->
try
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()
$('#privkey').val(g.user.privkey)
)
$('#withdraw').click(->
$('#withdrawal').show()
$('#amount').focus()
$('#keys').hide()
$('#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', 'wallet.json.aes')
a.click()
)
$('#generate').click(->
bootbox.confirm('
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.
', (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() ) ) $('.close').on('click', -> $(this).closest('.alert').fadeOut()) ) getUser = -> $.getJSON("/#{$('#username').val()}.json", (user) -> g.user = user $('#key').val(user.pubkey) $('#pubkey').val(user.pubkey) $('#privkey').val(user.privkey) $('#address').val(user.address) $('.address').html(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 = -> $.get("/ticker?currency=#{g.user.currency}&symbol=#{g.user.symbol}&type=bid", (exchange) -> g.exchange = exchange createWallet() ) createWallet = -> $.get("#{g.api}/wallets", (data) -> if g.user.username in data.wallet_names getBalance() else params = name: g.user.username if isBip32(g.user.pubkey) params.extended_public_key = g.user.pubkey params.subchain_indexes = [0,1] $.post("#{g.api}/wallets/hd", JSON.stringify(params)).done(getBalance).fail(-> $('.wallet').fadeIn()) else params.addresses = [g.user.pubkey] $.post("#{g.api}/wallets", JSON.stringify(params)).done(getBalance).fail(-> $('.wallet').fadeIn()) ) getBalance = -> $.get("#{g.api}/addrs/#{g.user.username}/balance?omitWalletAddresses=true", (data) -> balance = data.final_balance g.balance = parseFloat(balance.toBTC()) fiat = balance.toFiat() $('#balance').html(g.balance) $('#fiat').html("#{fiat} #{g.user.currency}") $('#amount').attr('max', g.balance) $('#balances').show() $('#fetching').hide() 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() ) updateUser = -> data = $('#keys form').serializeObject() delete data['key'] $.post("/#{g.user.username}", data, -> $.ajax( url: "#{g.api}/wallets/#{g.user.username}" type: 'DELETE' ).always(-> $.ajax( url: "#{g.api}/wallets/hd/#{g.user.username}" type: 'DELETE' ).always(-> getUser() ) ) ) sendTransaction = -> if g.key and not (typeof g.key.d is 'undefined' and typeof g.key.keyPair.d is 'undefined') dialog = new BootstrapDialog( title: '