2014-12-02 00:36:49 +01:00
$ ( document ) . ready ( function ( ) {
/* open wallet code */
2017-09-11 21:52:05 +02:00
var explorer _tx = "https://coinb.in/tx/"
var explorer _addr = "https://coinb.in/addr/"
var explorer _block = "https://coinb.in/block/"
2017-10-01 20:06:57 +02:00
var wallet _timer = false ;
2014-12-02 00:36:49 +01:00
$ ( "#openBtn" ) . click ( function ( ) {
var email = $ ( "#openEmail" ) . val ( ) . toLowerCase ( ) ;
if ( email . match ( /[\s\w\d]+@[\s\w\d]+/g ) ) {
if ( $ ( "#openPass" ) . val ( ) . length >= 10 ) {
if ( $ ( "#openPass" ) . val ( ) == $ ( "#openPassConfirm" ) . val ( ) ) {
var email = $ ( "#openEmail" ) . val ( ) . toLowerCase ( ) ;
var pass = $ ( "#openPass" ) . val ( ) ;
var s = email ;
s += '|' + pass + '|' ;
s += s . length + '|!@' + ( ( pass . length * 7 ) + email . length ) * 7 ;
var regchars = ( pass . match ( /[a-z]+/g ) ) ? pass . match ( /[a-z]+/g ) . length : 1 ;
var regupchars = ( pass . match ( /[A-Z]+/g ) ) ? pass . match ( /[A-Z]+/g ) . length : 1 ;
var regnums = ( pass . match ( /[0-9]+/g ) ) ? pass . match ( /[0-9]+/g ) . length : 1 ;
s += ( ( regnums + regchars ) + regupchars ) * pass . length + '3571' ;
2014-12-05 14:27:28 +01:00
s += ( s + '' + s ) ;
2014-12-02 00:36:49 +01:00
for ( i = 0 ; i <= 50 ; i ++ ) {
s = Crypto . SHA256 ( s ) ;
}
coinjs . compressed = true ;
var keys = coinjs . newKeys ( s ) ;
2017-09-16 11:03:10 +02:00
var address = keys . address ;
var wif = keys . wif ;
var pubkey = keys . pubkey ;
var privkeyaes = CryptoJS . AES . encrypt ( keys . wif , pass ) ;
2017-12-09 10:56:06 +01:00
$ ( "#walletKeys .walletSegWitRS" ) . addClass ( "hidden" ) ;
2017-09-16 11:03:10 +02:00
if ( $ ( "#walletSegwit" ) . is ( ":checked" ) ) {
2018-06-11 18:23:18 +02:00
if ( $ ( "#walletSegwitBech32" ) . is ( ":checked" ) ) {
var sw = coinjs . bech32Address ( pubkey ) ;
address = sw . address ;
} else {
var sw = coinjs . segwitAddress ( pubkey ) ;
address = sw . address ;
}
2017-12-09 10:56:06 +01:00
$ ( "#walletKeys .walletSegWitRS" ) . removeClass ( "hidden" ) ;
2018-06-11 18:23:18 +02:00
$ ( "#walletKeys .walletSegWitRS input:text" ) . val ( sw . redeemscript ) ;
2017-09-16 11:03:10 +02:00
}
2014-12-02 00:36:49 +01:00
2017-09-16 11:03:10 +02:00
$ ( "#walletAddress" ) . html ( address ) ;
$ ( "#walletHistory" ) . attr ( 'href' , explorer _addr + address ) ;
2014-12-07 19:01:08 +01:00
2014-12-07 20:12:52 +01:00
$ ( "#walletQrCode" ) . html ( "" ) ;
2014-12-07 19:01:08 +01:00
var qrcode = new QRCode ( "walletQrCode" ) ;
2017-09-16 11:03:10 +02:00
qrcode . makeCode ( "bitcoin:" + address ) ;
2014-12-07 19:01:08 +01:00
2017-09-16 11:03:10 +02:00
$ ( "#walletKeys .privkey" ) . val ( wif ) ;
$ ( "#walletKeys .pubkey" ) . val ( pubkey ) ;
$ ( "#walletKeys .privkeyaes" ) . val ( privkeyaes ) ;
2014-12-02 00:36:49 +01:00
$ ( "#openLogin" ) . hide ( ) ;
$ ( "#openWallet" ) . removeClass ( "hidden" ) . show ( ) ;
walletBalance ( ) ;
checkBalanceLoop ( ) ;
} else {
$ ( "#openLoginStatus" ) . html ( "Your passwords do not match!" ) . removeClass ( "hidden" ) . fadeOut ( ) . fadeIn ( ) ;
}
} else {
$ ( "#openLoginStatus" ) . html ( "Your password must be at least 10 chars long" ) . removeClass ( "hidden" ) . fadeOut ( ) . fadeIn ( ) ;
}
} else {
$ ( "#openLoginStatus" ) . html ( "Your email address doesn't appear to be valid" ) . removeClass ( "hidden" ) . fadeOut ( ) . fadeIn ( ) ;
}
$ ( "#openLoginStatus" ) . prepend ( '<span class="glyphicon glyphicon-exclamation-sign"></span> ' ) ;
} ) ;
$ ( "#walletLogout" ) . click ( function ( ) {
$ ( "#openEmail" ) . val ( "" ) ;
$ ( "#openPass" ) . val ( "" ) ;
$ ( "#openPassConfirm" ) . val ( "" ) ;
$ ( "#openLogin" ) . show ( ) ;
$ ( "#openWallet" ) . addClass ( "hidden" ) . show ( ) ;
$ ( "#walletAddress" ) . html ( "" ) ;
2017-09-11 21:52:05 +02:00
$ ( "#walletHistory" ) . attr ( 'href' , explorer _addr ) ;
2014-12-07 19:01:08 +01:00
2014-12-07 20:12:52 +01:00
$ ( "#walletQrCode" ) . html ( "" ) ;
2014-12-07 19:01:08 +01:00
var qrcode = new QRCode ( "walletQrCode" ) ;
qrcode . makeCode ( "bitcoin:" ) ;
2014-12-02 00:36:49 +01:00
$ ( "#walletKeys .privkey" ) . val ( "" ) ;
$ ( "#walletKeys .pubkey" ) . val ( "" ) ;
2017-09-16 11:03:10 +02:00
$ ( "#openLoginStatus" ) . html ( "" ) . hide ( ) ;
2014-12-02 00:36:49 +01:00
} ) ;
2018-06-11 18:23:18 +02:00
$ ( "#walletSegwit" ) . click ( function ( ) {
if ( $ ( this ) . is ( ":checked" ) ) {
$ ( ".walletSegwitType" ) . attr ( 'disabled' , false ) ;
} else {
$ ( ".walletSegwitType" ) . attr ( 'disabled' , true ) ;
}
} ) ;
2017-10-01 20:06:57 +02:00
$ ( "#walletToSegWit" ) . click ( function ( ) {
$ ( "#walletToBtn" ) . html ( 'SegWit <span class="caret"></span>' ) ;
$ ( "#walletSegwit" ) [ 0 ] . checked = true ;
2018-06-11 18:23:18 +02:00
$ ( "#walletSegwitp2sh" ) [ 0 ] . checked = true ;
$ ( "#openBtn" ) . click ( ) ;
} ) ;
$ ( "#walletToSegWitBech32" ) . click ( function ( ) {
$ ( "#walletToBtn" ) . html ( 'Bech32 <span class="caret"></span>' ) ;
$ ( "#walletSegwit" ) [ 0 ] . checked = true ;
$ ( "#walletSegwitBech32" ) [ 0 ] . checked = true ;
2017-10-01 20:06:57 +02:00
$ ( "#openBtn" ) . click ( ) ;
} ) ;
$ ( "#walletToLegacy" ) . click ( function ( ) {
$ ( "#walletToBtn" ) . html ( 'Legacy <span class="caret"></span>' ) ;
$ ( "#walletSegwit" ) [ 0 ] . checked = false ;
$ ( "#openBtn" ) . click ( ) ;
} ) ;
2014-12-02 00:36:49 +01:00
$ ( "#walletShowKeys" ) . click ( function ( ) {
$ ( "#walletKeys" ) . removeClass ( "hidden" ) ;
$ ( "#walletSpend" ) . removeClass ( "hidden" ) . addClass ( "hidden" ) ;
} ) ;
$ ( "#walletBalance" ) . click ( function ( ) {
walletBalance ( ) ;
} ) ;
$ ( "#walletConfirmSend" ) . click ( function ( ) {
var thisbtn = $ ( this ) ;
var tx = coinjs . transaction ( ) ;
var txfee = $ ( "#txFee" ) ;
var devaddr = coinjs . developer ;
var devamount = $ ( "#developerDonation" ) ;
if ( ( devamount . val ( ) * 1 ) > 0 ) {
tx . addoutput ( devaddr , devamount . val ( ) * 1 ) ;
}
var total = ( devamount . val ( ) * 1 ) + ( txfee . val ( ) * 1 ) ;
$ . each ( $ ( "#walletSpendTo .output" ) , function ( i , o ) {
var addr = $ ( '.addressTo' , o ) ;
var amount = $ ( '.amount' , o ) ;
2016-07-29 00:36:27 +02:00
if ( amount . val ( ) * 1 > 0 ) {
total += amount . val ( ) * 1 ;
tx . addoutput ( addr . val ( ) , amount . val ( ) * 1 ) ;
}
2014-12-02 00:36:49 +01:00
} ) ;
thisbtn . attr ( 'disabled' , true ) ;
2017-09-16 11:03:10 +02:00
var script = false ;
if ( $ ( "#walletSegwit" ) . is ( ":checked" ) ) {
2018-06-11 18:23:18 +02:00
if ( $ ( "#walletSegwitBech32" ) . is ( ":checked" ) ) {
var sw = coinjs . bech32Address ( $ ( "#walletKeys .pubkey" ) . val ( ) ) ;
} else {
var sw = coinjs . segwitAddress ( $ ( "#walletKeys .pubkey" ) . val ( ) ) ;
}
2017-09-20 11:56:20 +02:00
script = sw . redeemscript ;
2017-09-16 11:03:10 +02:00
}
2019-10-19 06:19:52 +02:00
var sequence = 0xffffffff - 1 ;
2018-01-06 17:11:20 +01:00
if ( $ ( "#walletRBF" ) . is ( ":checked" ) ) {
sequence = 0xffffffff - 2 ;
}
2014-12-02 00:36:49 +01:00
tx . addUnspent ( $ ( "#walletAddress" ) . html ( ) , function ( data ) {
2016-12-21 12:56:18 +01:00
var dvalue = ( data . value / 100000000 ) . toFixed ( 8 ) * 1 ;
total = ( total * 1 ) . toFixed ( 8 ) * 1 ;
2014-12-02 00:36:49 +01:00
if ( dvalue >= total ) {
var change = dvalue - total ;
2016-07-29 00:36:27 +02:00
if ( ( change * 1 ) > 0 ) {
2014-12-02 00:36:49 +01:00
tx . addoutput ( $ ( "#walletAddress" ) . html ( ) , change ) ;
}
// clone the transaction with out using coinjs.clone() function as it gives us trouble
var tx2 = coinjs . transaction ( ) ;
2017-09-16 11:03:10 +02:00
var txunspent = tx2 . deserialize ( tx . serialize ( ) ) ;
2014-12-02 00:36:49 +01:00
// then sign
var signed = txunspent . sign ( $ ( "#walletKeys .privkey" ) . val ( ) ) ;
// and finally broadcast!
2018-05-27 13:49:09 +02:00
2014-12-02 00:36:49 +01:00
tx2 . broadcast ( function ( data ) {
if ( $ ( data ) . find ( "result" ) . text ( ) == "1" ) {
2017-09-20 11:56:20 +02:00
$ ( "#walletSendConfirmStatus" ) . removeClass ( 'hidden' ) . addClass ( 'alert-success' ) . html ( 'txid: <a href="https://coinb.in/tx/' + $ ( data ) . find ( "txid" ) . text ( ) + '" target="_blank">' + $ ( data ) . find ( "txid" ) . text ( ) + '</a>' ) ;
2014-12-02 00:36:49 +01:00
} else {
$ ( "#walletSendConfirmStatus" ) . removeClass ( 'hidden' ) . addClass ( 'alert-danger' ) . html ( unescape ( $ ( data ) . find ( "response" ) . text ( ) ) . replace ( /\+/g , ' ' ) ) ;
2016-02-10 00:52:55 +01:00
$ ( "#walletSendFailTransaction" ) . removeClass ( 'hidden' ) ;
$ ( "#walletSendFailTransaction textarea" ) . val ( signed ) ;
2015-09-12 20:38:34 +02:00
thisbtn . attr ( 'disabled' , false ) ;
2014-12-02 00:36:49 +01:00
}
// update wallet balance
walletBalance ( ) ;
} , signed ) ;
} else {
2016-12-21 12:56:18 +01:00
$ ( "#walletSendConfirmStatus" ) . removeClass ( "hidden" ) . addClass ( 'alert-danger' ) . html ( "You have a confirmed balance of " + dvalue + " BTC unable to send " + total + " BTC" ) . fadeOut ( ) . fadeIn ( ) ;
2015-09-12 20:38:34 +02:00
thisbtn . attr ( 'disabled' , false ) ;
2014-12-02 00:36:49 +01:00
}
$ ( "#walletLoader" ) . addClass ( "hidden" ) ;
2017-09-16 11:03:10 +02:00
2018-01-06 17:11:20 +01:00
} , script , script , sequence ) ;
2014-12-02 00:36:49 +01:00
} ) ;
$ ( "#walletSendBtn" ) . click ( function ( ) {
2016-02-10 00:52:55 +01:00
$ ( "#walletSendFailTransaction" ) . addClass ( 'hidden' ) ;
2014-12-02 00:36:49 +01:00
$ ( "#walletSendStatus" ) . addClass ( "hidden" ) . html ( "" ) ;
var thisbtn = $ ( this ) ;
var txfee = $ ( "#txFee" ) ;
var devamount = $ ( "#developerDonation" ) ;
if ( ( ! isNaN ( devamount . val ( ) ) ) && devamount . val ( ) >= 0 ) {
$ ( devamount ) . parent ( ) . removeClass ( 'has-error' ) ;
} else {
$ ( devamount ) . parent ( ) . addClass ( 'has-error' )
}
if ( ( ! isNaN ( txfee . val ( ) ) ) && txfee . val ( ) >= 0 ) {
$ ( txfee ) . parent ( ) . removeClass ( 'has-error' ) ;
} else {
$ ( txfee ) . parent ( ) . addClass ( 'has-error' ) ;
}
var total = ( devamount . val ( ) * 1 ) + ( txfee . val ( ) * 1 ) ;
$ . each ( $ ( "#walletSpendTo .output" ) , function ( i , o ) {
var amount = $ ( '.amount' , o ) ;
var address = $ ( '.addressTo' , o ) ;
total += amount . val ( ) * 1 ;
if ( ( ! isNaN ( $ ( amount ) . val ( ) ) ) && $ ( amount ) . val ( ) > 0 ) {
$ ( amount ) . parent ( ) . removeClass ( 'has-error' ) ;
} else {
$ ( amount ) . parent ( ) . addClass ( 'has-error' ) ;
}
if ( coinjs . addressDecode ( $ ( address ) . val ( ) ) ) {
$ ( address ) . parent ( ) . removeClass ( 'has-error' ) ;
} else {
$ ( address ) . parent ( ) . addClass ( 'has-error' ) ;
}
} ) ;
total = total . toFixed ( 8 ) ;
if ( $ ( "#walletSpend .has-error" ) . length == 0 ) {
var balance = ( $ ( "#walletBalance" ) . html ( ) ) . replace ( /[^0-9\.]+/g , '' ) * 1 ;
if ( total <= balance ) {
$ ( "#walletSendConfirmStatus" ) . addClass ( "hidden" ) . removeClass ( 'alert-success' ) . removeClass ( 'alert-danger' ) . html ( "" ) ;
$ ( "#spendAmount" ) . html ( total ) ;
$ ( "#modalWalletConfirm" ) . modal ( "show" ) ;
$ ( "#walletConfirmSend" ) . attr ( 'disabled' , false ) ;
} else {
$ ( "#walletSendStatus" ) . removeClass ( "hidden" ) . html ( "You are trying to spend " + total + ' but have a balance of ' + balance ) ;
}
} else {
$ ( "#walletSpend .has-error" ) . fadeOut ( ) . fadeIn ( ) ;
$ ( "#walletSendStatus" ) . removeClass ( "hidden" ) . html ( '<span class="glyphicon glyphicon-exclamation-sign"></span> One or more input has an error' ) ;
}
} ) ;
$ ( "#walletShowSpend" ) . click ( function ( ) {
$ ( "#walletSpend" ) . removeClass ( "hidden" ) ;
$ ( "#walletKeys" ) . removeClass ( "hidden" ) . addClass ( "hidden" ) ;
} ) ;
$ ( "#walletSpendTo .addressAdd" ) . click ( function ( ) {
2015-03-24 01:40:56 +01:00
var clone = '<div class="form-horizontal output">' + $ ( this ) . parent ( ) . html ( ) + '</div>' ;
2014-12-02 00:36:49 +01:00
$ ( "#walletSpendTo" ) . append ( clone ) ;
$ ( "#walletSpendTo .glyphicon-plus:last" ) . removeClass ( 'glyphicon-plus' ) . addClass ( 'glyphicon-minus' ) ;
$ ( "#walletSpendTo .glyphicon-minus:last" ) . parent ( ) . removeClass ( 'addressAdd' ) . addClass ( 'addressRemove' ) ;
$ ( "#walletSpendTo .addressRemove" ) . unbind ( "" ) ;
$ ( "#walletSpendTo .addressRemove" ) . click ( function ( ) {
$ ( this ) . parent ( ) . fadeOut ( ) . remove ( ) ;
} ) ;
} ) ;
function walletBalance ( ) {
var tx = coinjs . transaction ( ) ;
$ ( "#walletLoader" ) . removeClass ( "hidden" ) ;
coinjs . addressBalance ( $ ( "#walletAddress" ) . html ( ) , function ( data ) {
if ( $ ( data ) . find ( "result" ) . text ( ) == 1 ) {
var v = $ ( data ) . find ( "balance" ) . text ( ) / 100000000 ;
$ ( "#walletBalance" ) . html ( v + " BTC" ) . attr ( 'rel' , v ) . fadeOut ( ) . fadeIn ( ) ;
} else {
$ ( "#walletBalance" ) . html ( "0.00 BTC" ) . attr ( 'rel' , v ) . fadeOut ( ) . fadeIn ( ) ;
}
$ ( "#walletLoader" ) . addClass ( "hidden" ) ;
} ) ;
}
function checkBalanceLoop ( ) {
2017-10-01 20:06:57 +02:00
clearTimeout ( wallet _timer ) ;
wallet _timer = setTimeout ( function ( ) {
2017-09-16 11:03:10 +02:00
if ( $ ( "#walletLoader" ) . hasClass ( "hidden" ) ) {
walletBalance ( ) ;
}
2014-12-02 00:36:49 +01:00
checkBalanceLoop ( ) ;
} , 45000 ) ;
}
/* new -> address code */
$ ( "#newKeysBtn" ) . click ( function ( ) {
coinjs . compressed = false ;
if ( $ ( "#newCompressed" ) . is ( ":checked" ) ) {
coinjs . compressed = true ;
}
var s = ( $ ( "#newBrainwallet" ) . is ( ":checked" ) ) ? $ ( "#brainwallet" ) . val ( ) : null ;
var coin = coinjs . newKeys ( s ) ;
$ ( "#newBitcoinAddress" ) . val ( coin . address ) ;
$ ( "#newPubKey" ) . val ( coin . pubkey ) ;
$ ( "#newPrivKey" ) . val ( coin . wif ) ;
2015-01-08 23:57:49 +01:00
/* encrypted key code */
if ( ( ! $ ( "#encryptKey" ) . is ( ":checked" ) ) || $ ( "#aes256pass" ) . val ( ) == $ ( "#aes256pass_confirm" ) . val ( ) ) {
$ ( "#aes256passStatus" ) . addClass ( "hidden" ) ;
2015-03-09 13:47:44 +01:00
if ( $ ( "#encryptKey" ) . is ( ":checked" ) ) {
$ ( "#aes256wifkey" ) . removeClass ( "hidden" ) ;
}
2015-01-08 23:57:49 +01:00
} else {
$ ( "#aes256passStatus" ) . removeClass ( "hidden" ) ;
}
$ ( "#newPrivKeyEnc" ) . val ( CryptoJS . AES . encrypt ( coin . wif , $ ( "#aes256pass" ) . val ( ) ) + '' ) ;
2017-11-25 00:53:00 +01:00
} ) ;
$ ( "#newPaperwalletBtn" ) . click ( function ( ) {
2019-05-24 16:44:47 +02:00
if ( $ ( "#newBitcoinAddress" ) . val ( ) == "" ) {
$ ( "#newKeysBtn" ) . click ( ) ;
}
2017-11-25 00:53:00 +01:00
var paperwallet = window . open ( ) ;
2019-05-24 16:44:47 +02:00
paperwallet . document . write ( '<h2>BTC PaperWallet</h2><hr><div style="margin-top: 5px; margin-bottom: 5px"><div><h3 style="margin-top: 0">Address (Share)</h3></div><div style="text-align: center;"><div id="qraddress"></div><p>' + $ ( "#newBitcoinAddress" ) . val ( ) + '</p></div></div><hr><div style="margin-top: 5px; margin-bottom: 5px"><div><h3 style="margin-top: 0">Public Key</h3></div><div style="text-align: center;"><div id="qrpubkey"></div><p>' + $ ( "#newPubKey" ) . val ( ) + '</p></div></div><hr><div style="margin-top: 5px; margin-bottom: 5px"><div><h3 style="margin-top: 0">Private Key (KEEP SECRET!)</h3></div><div style="text-align: center;"><div id="qrprivkey"></div><p>' + $ ( "#newPrivKey" ) . val ( ) + '</p></div></div>' ) ;
2017-11-25 00:53:00 +01:00
paperwallet . document . close ( ) ;
paperwallet . focus ( ) ;
2019-05-24 16:44:47 +02:00
new QRCode ( paperwallet . document . getElementById ( "qraddress" ) , { text : $ ( "#newBitcoinAddress" ) . val ( ) , width : 125 , height : 125 } ) ;
new QRCode ( paperwallet . document . getElementById ( "qrpubkey" ) , { text : $ ( "#newPubKey" ) . val ( ) , width : 125 , height : 125 } ) ;
new QRCode ( paperwallet . document . getElementById ( "qrprivkey" ) , { text : $ ( "#newPrivKey" ) . val ( ) , width : 125 , height : 125 } ) ;
2017-11-25 00:53:00 +01:00
paperwallet . print ( ) ;
paperwallet . close ( ) ;
2014-12-02 00:36:49 +01:00
} ) ;
$ ( "#newBrainwallet" ) . click ( function ( ) {
if ( $ ( this ) . is ( ":checked" ) ) {
$ ( "#brainwallet" ) . removeClass ( "hidden" ) ;
} else {
$ ( "#brainwallet" ) . addClass ( "hidden" ) ;
}
} ) ;
2017-09-10 15:18:31 +02:00
$ ( "#newSegWitBrainwallet" ) . click ( function ( ) {
if ( $ ( this ) . is ( ":checked" ) ) {
$ ( "#brainwalletSegWit" ) . removeClass ( "hidden" ) ;
} else {
$ ( "#brainwalletSegWit" ) . addClass ( "hidden" ) ;
}
} ) ;
2015-01-08 23:57:49 +01:00
$ ( "#encryptKey" ) . click ( function ( ) {
if ( $ ( this ) . is ( ":checked" ) ) {
2015-03-09 13:47:44 +01:00
$ ( "#aes256passform" ) . removeClass ( "hidden" ) ;
2015-01-08 23:57:49 +01:00
} else {
2015-03-09 13:47:44 +01:00
$ ( "#aes256wifkey, #aes256passform, #aes256passStatus" ) . addClass ( "hidden" ) ;
2015-01-08 23:57:49 +01:00
}
} ) ;
2017-09-10 15:18:31 +02:00
/* new -> segwit code */
$ ( "#newSegWitKeysBtn" ) . click ( function ( ) {
var compressed = coinjs . compressed ;
coinjs . compressed = true ;
2018-05-27 13:49:09 +02:00
2017-09-10 15:18:31 +02:00
var s = ( $ ( "#newSegWitBrainwallet" ) . is ( ":checked" ) ) ? $ ( "#brainwalletSegWit" ) . val ( ) : null ;
var coin = coinjs . newKeys ( s ) ;
2018-05-27 13:49:09 +02:00
if ( $ ( "#newSegWitBech32addr" ) . is ( ":checked" ) ) {
var sw = coinjs . bech32Address ( coin . pubkey ) ;
} else {
var sw = coinjs . segwitAddress ( coin . pubkey ) ;
}
2017-09-10 15:18:31 +02:00
$ ( "#newSegWitAddress" ) . val ( sw . address ) ;
$ ( "#newSegWitRedeemScript" ) . val ( sw . redeemscript ) ;
$ ( "#newSegWitPubKey" ) . val ( coin . pubkey ) ;
$ ( "#newSegWitPrivKey" ) . val ( coin . wif ) ;
coinjs . compressed = compressed ;
} ) ;
2017-11-25 00:53:00 +01:00
$ ( "#newSegwitPaperwalletBtn" ) . click ( function ( ) {
2019-05-24 16:44:47 +02:00
if ( $ ( "#newSegWitAddress" ) . val ( ) == "" ) {
$ ( "#newSegWitKeysBtn" ) . click ( ) ;
}
2017-11-25 00:53:00 +01:00
var paperwallet = window . open ( ) ;
2019-05-24 16:44:47 +02:00
paperwallet . document . write ( '<h2>BTC SegWit PaperWallet</h2><hr><div style="margin-top: 5px; margin-bottom: 5px"><div><h3 style="margin-top: 0">Address (Share)</h3></div><div style="text-align: center;"><div id="qraddress"></div><p>' + $ ( "#newSegWitAddress" ) . val ( ) + '</p></div></div><hr><div style="margin-top: 5px; margin-bottom: 5px"><div><h3 style="margin-top: 0">Public Key</h3></div><div style="text-align: center;"><div id="qrpubkey"></div><p>' + $ ( "#newSegWitPubKey" ) . val ( ) + '</p></div></div><hr><div style="margin-top: 5px; margin-bottom: 5px"><div><h3 style="margin-top: 0">Redeem Script</h3></div><div style="text-align: center;"><div id="qrredeem"></div><p>' + $ ( "#newSegWitRedeemScript" ) . val ( ) + '</p></div></div><hr><div style="margin-top: 5px; margin-bottom: 5px"><div><h3 style="margin-top: 0">Private Key (KEEP SECRET!)</h3></div><div style="text-align: center;"><div id="qrprivkey"></div><p>' + $ ( "#newSegWitPrivKey" ) . val ( ) + '</p></div></div>' ) ;
2017-11-25 00:53:00 +01:00
paperwallet . document . close ( ) ;
paperwallet . focus ( ) ;
2019-05-24 16:44:47 +02:00
new QRCode ( paperwallet . document . getElementById ( "qraddress" ) , { text : $ ( "#newSegWitAddress" ) . val ( ) , width : 110 , height : 110 } ) ;
new QRCode ( paperwallet . document . getElementById ( "qrpubkey" ) , { text : $ ( "#newSegWitPubKey" ) . val ( ) , width : 110 , height : 110 } ) ;
new QRCode ( paperwallet . document . getElementById ( "qrredeem" ) , { text : $ ( "#newSegWitRedeemScript" ) . val ( ) , width : 110 , height : 110 } ) ;
new QRCode ( paperwallet . document . getElementById ( "qrprivkey" ) , { text : $ ( "#newSegWitPrivKey" ) . val ( ) , width : 110 , height : 110 } ) ;
2017-11-25 00:53:00 +01:00
paperwallet . print ( ) ;
paperwallet . close ( ) ;
} ) ;
2017-09-10 15:18:31 +02:00
2014-12-02 00:36:49 +01:00
/* new -> multisig code */
$ ( "#newMultiSigAddress" ) . click ( function ( ) {
$ ( "#multiSigData" ) . removeClass ( 'show' ) . addClass ( 'hidden' ) . fadeOut ( ) ;
$ ( "#multisigPubKeys .pubkey" ) . parent ( ) . removeClass ( 'has-error' ) ;
$ ( "#releaseCoins" ) . parent ( ) . removeClass ( 'has-error' ) ;
$ ( "#multiSigErrorMsg" ) . hide ( ) ;
if ( ( isNaN ( $ ( "#releaseCoins option:selected" ) . html ( ) ) ) || ( ( ! isNaN ( $ ( "#releaseCoins option:selected" ) . html ( ) ) ) && ( $ ( "#releaseCoins option:selected" ) . html ( ) > $ ( "#multisigPubKeys .pubkey" ) . length || $ ( "#releaseCoins option:selected" ) . html ( ) * 1 <= 0 || $ ( "#releaseCoins option:selected" ) . html ( ) * 1 > 8 ) ) ) {
$ ( "#releaseCoins" ) . parent ( ) . addClass ( 'has-error' ) ;
$ ( "#multiSigErrorMsg" ) . html ( '<span class="glyphicon glyphicon-exclamation-sign"></span> Minimum signatures required is greater than the amount of public keys provided' ) . fadeIn ( ) ;
return false ;
}
var keys = [ ] ;
$ . each ( $ ( "#multisigPubKeys .pubkey" ) , function ( i , o ) {
if ( coinjs . pubkeydecompress ( $ ( o ) . val ( ) ) ) {
keys . push ( $ ( o ) . val ( ) ) ;
$ ( o ) . parent ( ) . removeClass ( 'has-error' ) ;
} else {
$ ( o ) . parent ( ) . addClass ( 'has-error' ) ;
}
} ) ;
if ( ( $ ( "#multisigPubKeys .pubkey" ) . parent ( ) . hasClass ( 'has-error' ) == false ) && $ ( "#releaseCoins" ) . parent ( ) . hasClass ( 'has-error' ) == false ) {
var sigsNeeded = $ ( "#releaseCoins option:selected" ) . html ( ) ;
var multisig = coinjs . pubkeys2MultisigAddress ( keys , sigsNeeded ) ;
2017-10-04 10:35:51 +02:00
if ( multisig . size <= 520 ) {
$ ( "#multiSigData .address" ) . val ( multisig [ 'address' ] ) ;
$ ( "#multiSigData .script" ) . val ( multisig [ 'redeemScript' ] ) ;
$ ( "#multiSigData .scriptUrl" ) . val ( document . location . origin + '' + document . location . pathname + '?verify=' + multisig [ 'redeemScript' ] + '#verify' ) ;
$ ( "#multiSigData" ) . removeClass ( 'hidden' ) . addClass ( 'show' ) . fadeIn ( ) ;
$ ( "#releaseCoins" ) . removeClass ( 'has-error' ) ;
} else {
$ ( "#multiSigErrorMsg" ) . html ( '<span class="glyphicon glyphicon-exclamation-sign"></span> Your generated redeemscript is too large (>520 bytes) it can not be used safely' ) . fadeIn ( ) ;
}
2014-12-02 00:36:49 +01:00
} else {
$ ( "#multiSigErrorMsg" ) . html ( '<span class="glyphicon glyphicon-exclamation-sign"></span> One or more public key is invalid!' ) . fadeIn ( ) ;
}
} ) ;
$ ( "#multisigPubKeys .pubkeyAdd" ) . click ( function ( ) {
if ( $ ( "#multisigPubKeys .pubkeyRemove" ) . length < 14 ) {
2015-03-23 14:02:29 +01:00
var clone = '<div class="form-horizontal">' + $ ( this ) . parent ( ) . html ( ) + '</div>' ;
2014-12-02 00:36:49 +01:00
$ ( "#multisigPubKeys" ) . append ( clone ) ;
$ ( "#multisigPubKeys .glyphicon-plus:last" ) . removeClass ( 'glyphicon-plus' ) . addClass ( 'glyphicon-minus' ) ;
$ ( "#multisigPubKeys .glyphicon-minus:last" ) . parent ( ) . removeClass ( 'pubkeyAdd' ) . addClass ( 'pubkeyRemove' ) ;
$ ( "#multisigPubKeys .pubkeyRemove" ) . unbind ( "" ) ;
$ ( "#multisigPubKeys .pubkeyRemove" ) . click ( function ( ) {
$ ( this ) . parent ( ) . fadeOut ( ) . remove ( ) ;
} ) ;
}
} ) ;
2015-09-12 20:38:34 +02:00
$ ( "#mediatorList" ) . change ( function ( ) {
var data = ( $ ( this ) . val ( ) ) . split ( ";" ) ;
$ ( "#mediatorPubkey" ) . val ( data [ 0 ] ) ;
$ ( "#mediatorEmail" ) . val ( data [ 1 ] ) ;
$ ( "#mediatorFee" ) . val ( data [ 2 ] ) ;
} ) . change ( ) ;
$ ( "#mediatorAddKey" ) . click ( function ( ) {
var count = 0 ;
var len = $ ( ".pubkeyRemove" ) . length ;
if ( len < 14 ) {
$ . each ( $ ( "#multisigPubKeys .pubkey" ) , function ( i , o ) {
if ( $ ( o ) . val ( ) == '' ) {
$ ( o ) . val ( $ ( "#mediatorPubkey" ) . val ( ) ) . fadeOut ( ) . fadeIn ( ) ;
$ ( "#mediatorClose" ) . click ( ) ;
return false ;
} else if ( count == len ) {
$ ( "#multisigPubKeys .pubkeyAdd" ) . click ( ) ;
$ ( "#mediatorAddKey" ) . click ( ) ;
return false ;
}
count ++ ;
} ) ;
$ ( "#mediatorClose" ) . click ( ) ;
}
} ) ;
2015-12-27 04:37:51 +01:00
/* new -> time locked code */
$ ( '#timeLockedDateTimePicker' ) . datetimepicker ( {
format : "MM/DD/YYYY HH:mm" ,
} ) ;
2016-07-03 19:28:47 +02:00
$ ( '#timeLockedRbTypeBox input' ) . change ( function ( ) {
if ( $ ( '#timeLockedRbTypeDate' ) . is ( ':checked' ) ) {
$ ( '#timeLockedDateTimePicker' ) . show ( ) ;
$ ( '#timeLockedBlockHeight' ) . hide ( ) ;
} else {
$ ( '#timeLockedDateTimePicker' ) . hide ( ) ;
$ ( '#timeLockedBlockHeight' ) . removeClass ( 'hidden' ) . show ( ) ;
}
} ) ;
2015-12-27 04:37:51 +01:00
$ ( "#newTimeLockedAddress" ) . click ( function ( ) {
$ ( "#timeLockedData" ) . removeClass ( 'show' ) . addClass ( 'hidden' ) . fadeOut ( ) ;
$ ( "#timeLockedPubKey" ) . parent ( ) . removeClass ( 'has-error' ) ;
$ ( "#timeLockedDateTimePicker" ) . parent ( ) . removeClass ( 'has-error' ) ;
$ ( "#timeLockedErrorMsg" ) . hide ( ) ;
if ( ! coinjs . pubkeydecompress ( $ ( "#timeLockedPubKey" ) . val ( ) ) ) {
$ ( '#timeLockedPubKey' ) . parent ( ) . addClass ( 'has-error' ) ;
}
2016-07-03 19:28:47 +02:00
var nLockTime = - 1 ;
if ( $ ( '#timeLockedRbTypeDate' ) . is ( ':checked' ) ) {
// by date
var date = $ ( '#timeLockedDateTimePicker' ) . data ( "DateTimePicker" ) . date ( ) ;
if ( ! date || ! date . isValid ( ) ) {
$ ( '#timeLockedDateTimePicker' ) . parent ( ) . addClass ( 'has-error' ) ;
}
nLockTime = date . unix ( )
if ( nLockTime < 500000000 ) {
$ ( '#timeLockedDateTimePicker' ) . parent ( ) . addClass ( 'has-error' ) ;
}
} else {
nLockTime = parseInt ( $ ( '#timeLockedBlockHeightVal' ) . val ( ) , 10 ) ;
if ( nLockTime >= 500000000 ) {
$ ( '#timeLockedDateTimePicker' ) . parent ( ) . addClass ( 'has-error' ) ;
}
2015-12-27 04:37:51 +01:00
}
if ( ( $ ( "#timeLockedPubKey" ) . parent ( ) . hasClass ( 'has-error' ) == false ) && $ ( "#timeLockedDateTimePicker" ) . parent ( ) . hasClass ( 'has-error' ) == false ) {
try {
2016-07-03 19:28:47 +02:00
var hodl = coinjs . simpleHodlAddress ( $ ( "#timeLockedPubKey" ) . val ( ) , nLockTime ) ;
2015-12-27 04:37:51 +01:00
$ ( "#timeLockedData .address" ) . val ( hodl [ 'address' ] ) ;
$ ( "#timeLockedData .script" ) . val ( hodl [ 'redeemScript' ] ) ;
$ ( "#timeLockedData .scriptUrl" ) . val ( document . location . origin + '' + document . location . pathname + '?verify=' + hodl [ 'redeemScript' ] + '#verify' ) ;
$ ( "#timeLockedData" ) . removeClass ( 'hidden' ) . addClass ( 'show' ) . fadeIn ( ) ;
} catch ( e ) {
$ ( "#timeLockedErrorMsg" ) . html ( '<span class="glyphicon glyphicon-exclamation-sign"></span> ' + e ) . fadeIn ( ) ;
}
} else {
$ ( "#timeLockedErrorMsg" ) . html ( '<span class="glyphicon glyphicon-exclamation-sign"></span> Public key and/or date is invalid!' ) . fadeIn ( ) ;
}
} ) ;
2015-05-17 02:30:21 +02:00
/* new -> Hd address code */
$ ( ".deriveHDbtn" ) . click ( function ( ) {
$ ( "#verifyScript" ) . val ( $ ( "input[type='text']" , $ ( this ) . parent ( ) . parent ( ) ) . val ( ) ) ;
window . location = "#verify" ;
$ ( "#verifyBtn" ) . click ( ) ;
} ) ;
$ ( "#newHDKeysBtn" ) . click ( function ( ) {
coinjs . compressed = true ;
var s = ( $ ( "#newHDBrainwallet" ) . is ( ":checked" ) ) ? $ ( "#HDBrainwallet" ) . val ( ) : null ;
var hd = coinjs . hd ( ) ;
var pair = hd . master ( s ) ;
$ ( "#newHDxpub" ) . val ( pair . pubkey ) ;
$ ( "#newHDxprv" ) . val ( pair . privkey ) ;
} ) ;
$ ( "#newHDBrainwallet" ) . click ( function ( ) {
if ( $ ( this ) . is ( ":checked" ) ) {
$ ( "#HDBrainwallet" ) . removeClass ( "hidden" ) ;
} else {
$ ( "#HDBrainwallet" ) . addClass ( "hidden" ) ;
}
} ) ;
2014-12-02 00:36:49 +01:00
/* new -> transaction code */
$ ( "#recipients .addressAddTo" ) . click ( function ( ) {
if ( $ ( "#recipients .addressRemoveTo" ) . length < 19 ) {
var clone = '<div class="row recipient"><br>' + $ ( this ) . parent ( ) . parent ( ) . html ( ) + '</div>' ;
$ ( "#recipients" ) . append ( clone ) ;
$ ( "#recipients .glyphicon-plus:last" ) . removeClass ( 'glyphicon-plus' ) . addClass ( 'glyphicon-minus' ) ;
$ ( "#recipients .glyphicon-minus:last" ) . parent ( ) . removeClass ( 'addressAdd' ) . addClass ( 'addressRemoveTo' ) ;
$ ( "#recipients .addressRemoveTo" ) . unbind ( "" ) ;
$ ( "#recipients .addressRemoveTo" ) . click ( function ( ) {
$ ( this ) . parent ( ) . parent ( ) . fadeOut ( ) . remove ( ) ;
validateOutputAmount ( ) ;
} ) ;
validateOutputAmount ( ) ;
}
} ) ;
$ ( "#inputs .txidAdd" ) . click ( function ( ) {
var clone = '<div class="row inputs"><br>' + $ ( this ) . parent ( ) . parent ( ) . html ( ) + '</div>' ;
$ ( "#inputs" ) . append ( clone ) ;
$ ( "#inputs .txidClear:last" ) . remove ( ) ;
$ ( "#inputs .glyphicon-plus:last" ) . removeClass ( 'glyphicon-plus' ) . addClass ( 'glyphicon-minus' ) ;
$ ( "#inputs .glyphicon-minus:last" ) . parent ( ) . removeClass ( 'txidAdd' ) . addClass ( 'txidRemove' ) ;
$ ( "#inputs .txidRemove" ) . unbind ( "" ) ;
$ ( "#inputs .txidRemove" ) . click ( function ( ) {
$ ( this ) . parent ( ) . parent ( ) . fadeOut ( ) . remove ( ) ;
totalInputAmount ( ) ;
} ) ;
$ ( "#inputs .row:last input" ) . attr ( 'disabled' , false ) ;
$ ( "#inputs .txIdAmount" ) . unbind ( "" ) . change ( function ( ) {
totalInputAmount ( ) ;
} ) . keyup ( function ( ) {
totalInputAmount ( ) ;
} ) ;
} ) ;
$ ( "#transactionBtn" ) . click ( function ( ) {
var tx = coinjs . transaction ( ) ;
2016-05-26 14:32:52 +02:00
var estimatedTxSize = 10 ; // <4:version><1:txInCount><1:txOutCount><4:nLockTime>
2014-12-15 13:15:28 +01:00
2015-09-12 20:38:34 +02:00
$ ( "#transactionCreate, #transactionCreateStatus" ) . addClass ( "hidden" ) ;
2014-12-15 13:15:28 +01:00
if ( ( $ ( "#nLockTime" ) . val ( ) ) . match ( /^[0-9]+$/g ) ) {
tx . lock _time = $ ( "#nLockTime" ) . val ( ) * 1 ;
}
2015-09-12 20:38:34 +02:00
$ ( "#inputs .row" ) . removeClass ( 'has-error' ) ;
$ ( '#putTabs a[href="#txinputs"], #putTabs a[href="#txoutputs"]' ) . attr ( 'style' , '' ) ;
2014-12-02 00:36:49 +01:00
$ . each ( $ ( "#inputs .row" ) , function ( i , o ) {
2015-09-12 20:38:34 +02:00
if ( ! ( $ ( ".txId" , o ) . val ( ) ) . match ( /^[a-f0-9]+$/i ) ) {
$ ( o ) . addClass ( "has-error" ) ;
} else if ( ( ! ( $ ( ".txIdScript" , o ) . val ( ) ) . match ( /^[a-f0-9]+$/i ) ) && $ ( ".txIdScript" , o ) . val ( ) != "" ) {
$ ( o ) . addClass ( "has-error" ) ;
} else if ( ! ( $ ( ".txIdN" , o ) . val ( ) ) . match ( /^[0-9]+$/i ) ) {
$ ( o ) . addClass ( "has-error" ) ;
}
if ( ! $ ( o ) . hasClass ( "has-error" ) ) {
2019-10-19 06:19:52 +02:00
var seq = 0xffffffff - 1 ;
2016-05-21 17:47:10 +02:00
if ( $ ( "#txRBF" ) . is ( ":checked" ) ) {
seq = 0xffffffff - 2 ;
}
2016-05-26 14:32:52 +02:00
var currentScript = $ ( ".txIdScript" , o ) . val ( ) ;
if ( currentScript . match ( /^76a914[0-9a-f]{40}88ac$/ ) ) {
estimatedTxSize += 147
} else if ( currentScript . match ( /^5[1-9a-f](?:210[23][0-9a-f]{64}){1,15}5[1-9a-f]ae$/ ) ) {
// <74:persig <1:push><72:sig><1:sighash> ><34:perpubkey <1:push><33:pubkey> > <32:prevhash><4:index><4:nSequence><1:m><1:n><1:OP>
var scriptSigSize = ( parseInt ( currentScript . slice ( 1 , 2 ) , 16 ) * 74 ) + ( parseInt ( currentScript . slice ( - 3 , - 2 ) , 16 ) * 34 ) + 43
// varint 2 bytes if scriptSig is > 252
estimatedTxSize += scriptSigSize + ( scriptSigSize > 252 ? 2 : 1 )
} else {
// underestimating won't hurt. Just showing a warning window anyways.
estimatedTxSize += 147
}
2016-05-21 17:47:10 +02:00
tx . addinput ( $ ( ".txId" , o ) . val ( ) , $ ( ".txIdN" , o ) . val ( ) , $ ( ".txIdScript" , o ) . val ( ) , seq ) ;
2015-09-12 20:38:34 +02:00
} else {
$ ( '#putTabs a[href="#txinputs"]' ) . attr ( 'style' , 'color:#a94442;' ) ;
2014-12-02 00:36:49 +01:00
}
} ) ;
2014-12-29 23:55:28 +01:00
$ ( "#recipients .row" ) . removeClass ( 'has-error' ) ;
2014-12-02 00:36:49 +01:00
$ . each ( $ ( "#recipients .row" ) , function ( i , o ) {
2014-12-30 04:40:30 +01:00
var a = ( $ ( ".address" , o ) . val ( ) ) ;
2015-06-24 00:34:30 +02:00
var ad = coinjs . addressDecode ( a ) ;
2018-05-27 13:49:09 +02:00
if ( ( ( a != "" ) && ( ad . version == coinjs . pub || ad . version == coinjs . multisig || ad . type == "bech32" ) ) && $ ( ".amount" , o ) . val ( ) != "" ) { // address
2016-05-26 14:32:52 +02:00
// P2SH output is 32, P2PKH is 34
estimatedTxSize += ( ad . version == coinjs . pub ? 34 : 32 )
2014-12-29 23:55:28 +01:00
tx . addoutput ( a , $ ( ".amount" , o ) . val ( ) ) ;
2015-01-02 14:52:01 +01:00
} else if ( ( ( a != "" ) && ad . version === 42 ) && $ ( ".amount" , o ) . val ( ) != "" ) { // stealth address
2016-05-26 14:32:52 +02:00
// 1 P2PKH and 1 OP_RETURN with 36 bytes, OP byte, and 8 byte value
estimatedTxSize += 78
2015-01-02 14:35:29 +01:00
tx . addstealth ( ad , $ ( ".amount" , o ) . val ( ) ) ;
2015-07-27 20:04:41 +02:00
} else if ( ( ( ( $ ( "#opReturn" ) . is ( ":checked" ) ) && a . match ( /^[a-f0-9]+$/ig ) ) && a . length < 160 ) && ( a . length % 2 ) == 0 ) { // data
2016-05-26 14:32:52 +02:00
estimatedTxSize += ( a . length / 2 ) + 1 + 8
2014-12-29 23:55:28 +01:00
tx . adddata ( a ) ;
} else { // neither address nor data
$ ( o ) . addClass ( 'has-error' ) ;
2015-09-12 20:38:34 +02:00
$ ( '#putTabs a[href="#txoutputs"]' ) . attr ( 'style' , 'color:#a94442;' ) ;
2014-12-02 00:36:49 +01:00
}
} ) ;
2015-09-12 20:38:34 +02:00
if ( ! $ ( "#recipients .row, #inputs .row" ) . hasClass ( 'has-error' ) ) {
2018-01-01 19:53:23 +01:00
2015-09-12 20:38:34 +02:00
$ ( "#transactionCreate textarea" ) . val ( tx . serialize ( ) ) ;
$ ( "#transactionCreate .txSize" ) . html ( tx . size ( ) ) ;
2018-01-01 19:53:23 +01:00
if ( $ ( "#feesestnewtx" ) . attr ( 'est' ) == 'y' ) {
$ ( "#fees .txhex" ) . val ( $ ( "#transactionCreate textarea" ) . val ( ) ) ;
2018-01-15 19:58:17 +01:00
$ ( "#feesAnalyseBtn" ) . click ( ) ;
2018-01-01 19:53:23 +01:00
$ ( "#fees .txhex" ) . val ( "" ) ;
window . location = "#fees" ;
} else {
$ ( "#transactionCreate" ) . removeClass ( "hidden" ) ;
2015-09-12 20:38:34 +02:00
2018-01-01 19:53:23 +01:00
// Check fee against hard 0.01 as well as fluid 200 satoshis per byte calculation.
if ( $ ( "#transactionFee" ) . val ( ) >= 0.01 || $ ( "#transactionFee" ) . val ( ) >= estimatedTxSize * 200 * 1e-8 ) {
$ ( "#modalWarningFeeAmount" ) . html ( $ ( "#transactionFee" ) . val ( ) ) ;
$ ( "#modalWarningFee" ) . modal ( "show" ) ;
}
2015-09-12 20:38:34 +02:00
}
2018-01-01 19:53:23 +01:00
$ ( "#feesestnewtx" ) . attr ( 'est' , '' ) ;
2015-09-12 20:38:34 +02:00
} else {
$ ( "#transactionCreateStatus" ) . removeClass ( "hidden" ) . html ( "One or more input or output is invalid" ) . fadeOut ( ) . fadeIn ( ) ;
}
2014-12-02 00:36:49 +01:00
} ) ;
2018-01-01 19:53:23 +01:00
$ ( "#feesestnewtx" ) . click ( function ( ) {
$ ( this ) . attr ( 'est' , 'y' ) ;
$ ( "#transactionBtn" ) . click ( ) ;
} ) ;
$ ( "#feesestwallet" ) . click ( function ( ) {
$ ( this ) . attr ( 'est' , 'y' ) ;
var outputs = $ ( "#walletSpendTo .output" ) . length ;
$ ( "#fees .inputno, #fees .outputno, #fees .bytes" ) . html ( 0 ) ;
$ ( "#fees .slider" ) . val ( 0 ) ;
var tx = coinjs . transaction ( ) ;
tx . listUnspent ( $ ( "#walletAddress" ) . html ( ) , function ( data ) {
var inputs = $ ( data ) . find ( "unspent" ) . children ( ) . length ;
if ( $ ( "#walletSegwit" ) . is ( ":checked" ) ) {
$ ( "#fees .txi_segwit" ) . val ( inputs ) ;
2018-01-04 11:42:45 +01:00
$ ( "#fees .txi_segwit" ) . trigger ( 'input' ) ;
2018-01-01 19:53:23 +01:00
} else {
$ ( "#fees .txi_regular" ) . val ( inputs ) ;
2018-01-04 11:42:45 +01:00
$ ( "#fees .txi_regular" ) . trigger ( 'input' ) ;
2018-01-01 19:53:23 +01:00
}
$ . each ( $ ( "#walletSpendTo .output" ) , function ( i , o ) {
var addr = $ ( '.addressTo' , o ) ;
var ad = coinjs . addressDecode ( addr . val ( ) ) ;
2018-06-11 18:23:18 +02:00
if ( ad . version == coinjs . pub ) { // p2pkh
2018-01-01 19:53:23 +01:00
$ ( "#fees .txo_p2pkh" ) . val ( ( $ ( "#fees .txo_p2pkh" ) . val ( ) * 1 ) + 1 ) ;
2018-01-04 11:42:45 +01:00
$ ( "#fees .txo_p2pkh" ) . trigger ( 'input' ) ;
2018-06-11 18:23:18 +02:00
} else { // p2psh
$ ( "#fees .txo_p2sh" ) . val ( ( $ ( "#fees .txo_p2sh" ) . val ( ) * 1 ) + 1 ) ;
$ ( "#fees .txo_p2sh" ) . trigger ( 'input' ) ;
2018-01-01 19:53:23 +01:00
}
} ) ;
if ( ( $ ( "#developerDonation" ) . val ( ) * 1 ) > 0 ) {
var addr = coinjs . developer ;
var ad = coinjs . addressDecode ( addr ) ;
2018-06-11 18:23:18 +02:00
if ( ad . version == coinjs . pub ) { // p2pkh
$ ( "#fees .txo_p2pkh" ) . val ( ( $ ( "#fees .txo_p2pkh" ) . val ( ) * 1 ) + 1 ) ;
$ ( "#fees .txo_p2pkh" ) . trigger ( 'input' ) ;
} else { // p2psh
2018-01-01 19:53:23 +01:00
$ ( "#fees .txo_p2sh" ) . val ( ( $ ( "#fees .txo_p2sh" ) . val ( ) * 1 ) + 1 ) ;
2018-01-04 11:42:45 +01:00
$ ( "#fees .txo_p2sh" ) . trigger ( 'input' ) ;
2018-01-01 19:53:23 +01:00
}
}
} ) ;
//feeStats();
window . location = "#fees" ;
} ) ;
2014-12-02 00:36:49 +01:00
$ ( ".txidClear" ) . click ( function ( ) {
$ ( "#inputs .row:first input" ) . attr ( 'disabled' , false ) ;
$ ( "#inputs .row:first input" ) . val ( "" ) ;
totalInputAmount ( ) ;
} ) ;
$ ( "#inputs .txIdAmount" ) . unbind ( "" ) . change ( function ( ) {
totalInputAmount ( ) ;
} ) . keyup ( function ( ) {
totalInputAmount ( ) ;
} ) ;
2017-03-13 22:12:06 +01:00
$ ( "#donateTxBtn" ) . click ( function ( ) {
var exists = false ;
$ . each ( $ ( "#recipients .address" ) , function ( i , o ) {
if ( $ ( o ) . val ( ) == coinjs . developer ) {
exists = true ;
$ ( o ) . fadeOut ( ) . fadeIn ( ) ;
return true ;
}
} ) ;
if ( ! exists ) {
if ( $ ( "#recipients .recipient:last .address:last" ) . val ( ) != "" ) {
$ ( "#recipients .addressAddTo:first" ) . click ( ) ;
} ;
$ ( "#recipients .recipient:last .address:last" ) . val ( coinjs . developer ) . fadeOut ( ) . fadeIn ( ) ;
return true ;
}
} ) ;
2015-03-09 01:34:19 +01:00
/* code for the qr code scanner */
2015-03-09 13:27:28 +01:00
$ ( ".qrcodeScanner" ) . click ( function ( ) {
if ( ( typeof MediaStreamTrack === 'function' ) && typeof MediaStreamTrack . getSources === 'function' ) {
MediaStreamTrack . getSources ( function ( sourceInfos ) {
var f = 0 ;
$ ( "select#videoSource" ) . html ( "" ) ;
for ( var i = 0 ; i !== sourceInfos . length ; ++ i ) {
var sourceInfo = sourceInfos [ i ] ;
var option = document . createElement ( 'option' ) ;
option . value = sourceInfo . id ;
if ( sourceInfo . kind === 'video' ) {
option . text = sourceInfo . label || 'camera ' + ( $ ( "select#videoSource options" ) . length + 1 ) ;
$ ( option ) . appendTo ( "select#videoSource" ) ;
}
2015-03-09 01:34:19 +01:00
}
2015-03-09 13:27:28 +01:00
} ) ;
2015-03-09 13:31:52 +01:00
$ ( "#videoSource" ) . unbind ( "change" ) . change ( function ( ) {
scannerStart ( )
} ) ;
2015-03-09 13:27:28 +01:00
} else {
$ ( "#videoSource" ) . addClass ( "hidden" ) ;
}
2015-03-09 13:31:52 +01:00
scannerStart ( ) ;
2015-03-09 01:34:19 +01:00
$ ( "#qrcode-scanner-callback-to" ) . html ( $ ( this ) . attr ( 'forward-result' ) ) ;
} ) ;
2015-03-09 13:31:52 +01:00
function scannerStart ( ) {
2015-03-09 13:27:28 +01:00
navigator . getUserMedia = navigator . getUserMedia || navigator . webkitGetUserMedia || navigator . mozGetUserMedia || false ;
if ( navigator . getUserMedia ) {
if ( ! ! window . stream ) {
$ ( "video" ) . attr ( 'src' , null ) ;
window . stream . stop ( ) ;
}
var videoSource = $ ( "select#videoSource" ) . val ( ) ;
var constraints = {
video : {
optional : [ { sourceId : videoSource } ]
}
} ;
navigator . getUserMedia ( constraints , function ( stream ) {
window . stream = stream ; // make stream available to console
var videoElement = document . querySelector ( 'video' ) ;
videoElement . src = window . URL . createObjectURL ( stream ) ;
videoElement . play ( ) ;
} , function ( error ) { } ) ;
QCodeDecoder ( ) . decodeFromCamera ( document . getElementById ( 'videoReader' ) , function ( er , data ) {
if ( ! er ) {
var match = data . match ( /^bitcoin\:([13][a-z0-9]{26,33})/i ) ;
var result = match ? match [ 1 ] : data ;
$ ( "" + $ ( "#qrcode-scanner-callback-to" ) . html ( ) ) . val ( result ) ;
$ ( "#qrScanClose" ) . click ( ) ;
}
} ) ;
} else {
$ ( "#videoReaderError" ) . removeClass ( "hidden" ) ;
$ ( "#videoReader, #videoSource" ) . addClass ( "hidden" ) ;
}
}
2015-08-14 23:07:19 +02:00
/* redeem from button code */
2014-12-02 00:36:49 +01:00
$ ( "#redeemFromBtn" ) . click ( function ( ) {
2018-12-29 00:33:42 +01:00
var redeem = redeemingFrom ( $ ( "#redeemFrom" ) . val ( ) ) ;
2014-12-02 00:36:49 +01:00
$ ( "#redeemFromStatus, #redeemFromAddress" ) . addClass ( 'hidden' ) ;
2015-08-14 23:07:19 +02:00
if ( redeem . from == 'multisigAddress' ) {
2014-12-02 00:36:49 +01:00
$ ( "#redeemFromStatus" ) . removeClass ( 'hidden' ) . html ( '<span class="glyphicon glyphicon-exclamation-sign"></span> You should use the redeem script, not the multisig address!' ) ;
2015-08-14 23:07:19 +02:00
return false ;
}
if ( redeem . from == 'other' ) {
2018-05-27 13:49:09 +02:00
$ ( "#redeemFromStatus" ) . removeClass ( 'hidden' ) . html ( '<span class="glyphicon glyphicon-exclamation-sign"></span> The address or redeem script you have entered is invalid' ) ;
2015-08-14 23:07:19 +02:00
return false ;
}
if ( $ ( "#clearInputsOnLoad" ) . is ( ":checked" ) ) {
$ ( "#inputs .txidRemove, #inputs .txidClear" ) . click ( ) ;
}
$ ( "#redeemFromBtn" ) . html ( "Please wait, loading..." ) . attr ( 'disabled' , true ) ;
var host = $ ( this ) . attr ( 'rel' ) ;
2016-09-11 20:40:18 +02:00
2019-08-16 23:28:29 +02:00
// api: blockcypher blockchair chain.so
// network name "btc" "bitcoin" "BTC"
// network name "ltc" "litecoin" "LTC"
// network name "doge" "dogecoin" "DOGE"
2019-09-22 22:32:42 +02:00
2019-08-16 23:28:29 +02:00
if ( host == 'chain.so_bitcoinmainnet' ) {
listUnspentChainso ( redeem , "BTC" ) ;
} else if ( host == 'chain.so_litecoin' ) {
listUnspentChainso ( redeem , "LTC" ) ;
2017-09-10 15:18:31 +02:00
} else if ( host == 'chain.so_dogecoin' ) {
2019-08-16 23:28:29 +02:00
listUnspentChainso ( redeem , "DOGE" ) ;
} else if ( host == 'blockcypher_bitcoinmainnet' ) {
listUnspentBlockcypher ( redeem , "btc" ) ;
} else if ( host == 'blockcypher_litecoin' ) {
listUnspentBlockcypher ( redeem , "ltc" ) ;
} else if ( host == 'blockcypher_dogecoin' ) {
listUnspentBlockcypher ( redeem , "doge" ) ;
} else if ( host == 'blockchair_bitcoinmainnet' ) {
listUnspentBlockchair ( redeem , "bitcoin" ) ;
} else if ( host == 'blockchair_litecoin' ) {
listUnspentBlockchair ( redeem , "litecoin" ) ;
} else if ( host == 'blockchair_dogecoin' ) {
listUnspentBlockchair ( redeem , "dogecoin" ) ;
2017-09-10 15:18:31 +02:00
} else if ( host == 'cryptoid.info_carboncoin' ) {
2016-09-11 20:40:18 +02:00
listUnspentCryptoidinfo _Carboncoin ( redeem ) ;
2015-08-14 23:07:19 +02:00
} else {
2015-08-15 00:09:51 +02:00
listUnspentDefault ( redeem ) ;
2015-08-14 23:07:19 +02:00
}
2015-12-27 05:15:47 +01:00
if ( $ ( "#redeemFromStatus" ) . hasClass ( "hidden" ) ) {
// An ethical dilemma: Should we automatically set nLockTime?
2018-12-29 00:42:00 +01:00
if ( redeem . from == 'redeemScript' && redeem . type == "hodl__" ) {
2018-12-29 00:33:42 +01:00
$ ( "#nLockTime" ) . val ( redeem . decodescript . checklocktimeverify ) ;
2015-12-27 05:15:47 +01:00
} else {
$ ( "#nLockTime" ) . val ( 0 ) ;
}
}
2015-08-14 23:07:19 +02:00
} ) ;
/* function to determine what we are redeeming from */
function redeemingFrom ( string ) {
var r = { } ;
var decode = coinjs . addressDecode ( string ) ;
if ( decode . version == coinjs . pub ) { // regular address
r . addr = string ;
r . from = 'address' ;
2018-05-27 13:49:09 +02:00
r . redeemscript = false ;
2015-08-14 23:07:19 +02:00
} else if ( decode . version == coinjs . priv ) { // wif key
var a = coinjs . wif2address ( string ) ;
r . addr = a [ 'address' ] ;
r . from = 'wif' ;
2018-05-27 13:49:09 +02:00
r . redeemscript = false ;
2015-08-14 23:07:19 +02:00
} else if ( decode . version == coinjs . multisig ) { // mulisig address
r . addr = '' ;
r . from = 'multisigAddress' ;
2018-05-27 13:49:09 +02:00
r . redeemscript = false ;
} else if ( decode . type == 'bech32' ) {
r . addr = string ;
r . from = 'bech32' ;
r . decodedRs = decode . redeemscript ;
r . redeemscript = true ;
2014-12-02 00:36:49 +01:00
} else {
var script = coinjs . script ( ) ;
2015-08-14 23:07:19 +02:00
var decodeRs = script . decodeRedeemScript ( string ) ;
if ( decodeRs ) { // redeem script
r . addr = decodeRs [ 'address' ] ;
r . from = 'redeemScript' ;
2018-05-27 13:49:09 +02:00
r . decodedRs = decodeRs . redeemscript ;
2018-12-29 00:33:42 +01:00
r . type = decodeRs [ 'type' ] ;
2018-05-27 13:49:09 +02:00
r . redeemscript = true ;
2018-12-29 00:33:42 +01:00
r . decodescript = decodeRs ;
2015-08-14 23:07:19 +02:00
} else { // something else
r . addr = '' ;
r . from = 'other' ;
2018-05-27 13:49:09 +02:00
r . redeemscript = false ;
2014-12-02 00:36:49 +01:00
}
}
2015-08-14 23:07:19 +02:00
return r ;
}
2014-12-02 00:36:49 +01:00
2015-09-12 20:38:34 +02:00
/* mediator payment code for when you used a public key */
function mediatorPayment ( redeem ) {
if ( redeem . from == "redeemScript" ) {
$ ( '#recipients .row[rel="' + redeem . addr + '"]' ) . parent ( ) . remove ( ) ;
$ . each ( redeem . decodedRs . pubkeys , function ( i , o ) {
$ . each ( $ ( "#mediatorList option" ) , function ( mi , mo ) {
var ms = ( $ ( mo ) . val ( ) ) . split ( ";" ) ;
var pubkey = ms [ 0 ] ; // mediators pubkey
var fee = ms [ 2 ] * 1 ; // fee in a percentage
var payto = coinjs . pubkey2address ( pubkey ) ; // pay to mediators address
if ( o == pubkey ) { // matched a mediators pubkey?
var clone = '<span><div class="row recipients mediator mediator_' + pubkey + '" rel="' + redeem . addr + '">' + $ ( "#recipients .addressAddTo" ) . parent ( ) . parent ( ) . html ( ) + '</div><br></span>' ;
$ ( "#recipients" ) . prepend ( clone ) ;
$ ( "#recipients .mediator_" + pubkey + " .glyphicon-plus:first" ) . removeClass ( 'glyphicon-plus' ) ;
$ ( "#recipients .mediator_" + pubkey + " .address:first" ) . val ( payto ) . attr ( 'disabled' , true ) . attr ( 'readonly' , true ) . attr ( 'title' , 'Medation fee for ' + $ ( mo ) . html ( ) ) ;
var amount = ( ( fee * $ ( "#totalInput" ) . html ( ) ) / 100 ) . toFixed ( 8 ) ;
$ ( "#recipients .mediator_" + pubkey + " .amount:first" ) . attr ( 'disabled' , ( ( ( amount * 1 ) == 0 ) ? false : true ) ) . val ( amount ) . attr ( 'title' , 'Medation fee for ' + $ ( mo ) . html ( ) ) ;
}
} ) ;
} ) ;
validateOutputAmount ( ) ;
}
}
2015-08-14 23:07:19 +02:00
/* global function to add outputs to page */
function addOutput ( tx , n , script , amount ) {
if ( tx ) {
if ( $ ( "#inputs .txId:last" ) . val ( ) != "" ) {
$ ( "#inputs .txidAdd" ) . click ( ) ;
}
$ ( "#inputs .row:last input" ) . attr ( 'disabled' , true ) ;
var txid = ( ( tx ) . match ( /.{1,2}/g ) . reverse ( ) ) . join ( "" ) + '' ;
$ ( "#inputs .txId:last" ) . val ( txid ) ;
$ ( "#inputs .txIdN:last" ) . val ( n ) ;
$ ( "#inputs .txIdAmount:last" ) . val ( amount ) ;
2017-09-10 15:18:31 +02:00
2018-05-27 13:49:09 +02:00
if ( ( ( script . match ( /^00/ ) && script . length == 44 ) ) || ( script . length == 40 && script . match ( /^[a-f0-9]+$/gi ) ) ) {
2017-09-10 15:18:31 +02:00
s = coinjs . script ( ) ;
s . writeBytes ( Crypto . util . hexToBytes ( script ) ) ;
s . writeOp ( 0 ) ;
s . writeBytes ( coinjs . numToBytes ( ( amount * 100000000 ) . toFixed ( 0 ) , 8 ) ) ;
script = Crypto . util . bytesToHex ( s . buffer ) ;
}
2015-08-14 23:07:19 +02:00
$ ( "#inputs .txIdScript:last" ) . val ( script ) ;
}
}
/* default function to retreive unspent outputs*/
2015-08-15 00:09:51 +02:00
function listUnspentDefault ( redeem ) {
2014-12-02 00:36:49 +01:00
var tx = coinjs . transaction ( ) ;
2015-08-15 00:09:51 +02:00
tx . listUnspent ( redeem . addr , function ( data ) {
if ( redeem . addr ) {
2017-09-11 21:52:05 +02:00
$ ( "#redeemFromAddress" ) . removeClass ( 'hidden' ) . html ( '<span class="glyphicon glyphicon-info-sign"></span> Retrieved unspent inputs from address <a href="' + explorer _addr + redeem . addr + '" target="_blank">' + redeem . addr + '</a>' ) ;
2014-12-02 00:36:49 +01:00
$ . each ( $ ( data ) . find ( "unspent" ) . children ( ) , function ( i , o ) {
2015-08-14 23:07:19 +02:00
var tx = $ ( o ) . find ( "tx_hash" ) . text ( ) ;
var n = $ ( o ) . find ( "tx_output_n" ) . text ( ) ;
2018-05-27 13:49:09 +02:00
var script = ( redeem . redeemscript == true ) ? redeem . decodedRs : $ ( o ) . find ( "script" ) . text ( ) ;
2015-08-14 23:07:19 +02:00
var amount = ( ( $ ( o ) . find ( "value" ) . text ( ) * 1 ) / 100000000 ) . toFixed ( 8 ) ;
2014-12-15 01:24:31 +01:00
2015-08-14 23:07:19 +02:00
addOutput ( tx , n , script , amount ) ;
} ) ;
}
2014-12-15 01:24:31 +01:00
2015-08-14 23:07:19 +02:00
$ ( "#redeemFromBtn" ) . html ( "Load" ) . attr ( 'disabled' , false ) ;
totalInputAmount ( ) ;
2015-09-12 20:38:34 +02:00
mediatorPayment ( redeem ) ;
2015-08-14 23:07:19 +02:00
} ) ;
}
2014-12-02 00:36:49 +01:00
2019-08-16 23:28:29 +02:00
/* retrieve unspent data from blockcypher */
function listUnspentBlockcypher ( redeem , network ) {
2015-08-14 23:07:19 +02:00
$ . ajax ( {
type : "GET" ,
2019-08-16 23:28:29 +02:00
url : "https://api.blockcypher.com/v1/" + network + "/main/addrs/" + redeem . addr + "?includeScript=true&unspentOnly=true" ,
2015-08-14 23:07:19 +02:00
dataType : "json" ,
error : function ( data ) {
$ ( "#redeemFromStatus" ) . removeClass ( 'hidden' ) . html ( '<span class="glyphicon glyphicon-exclamation-sign"></span> Unexpected error, unable to retrieve unspent outputs!' ) ;
} ,
success : function ( data ) {
2019-08-22 14:41:36 +02:00
if ( data . address ) { // address field will always be present, txrefs is only present if there are UTXOs
2019-08-16 23:28:29 +02:00
$ ( "#redeemFromAddress" ) . removeClass ( 'hidden' ) . html (
'<span class="glyphicon glyphicon-info-sign"></span> Retrieved unspent inputs from address <a href="' + explorer _addr + redeem . addr + '" target="_blank">' + redeem . addr + '</a>' ) ;
for ( var i in data . txrefs ) {
var o = data . txrefs [ i ]
var tx = ( ( "" + o . tx _hash ) . match ( /.{1,2}/g ) . reverse ( ) ) . join ( "" ) + '' ;
2019-04-19 17:40:59 +02:00
if ( tx . match ( /^[a-f0-9]+$/ ) ) {
2019-08-16 23:28:29 +02:00
var n = o . tx _output _n ;
var script = ( redeem . redeemscript == true ) ? redeem . decodedRs : o . script ;
var amount = ( ( o . value . toString ( ) * 1 ) / 100000000 ) . toFixed ( 8 ) ;
2019-04-19 17:40:59 +02:00
addOutput ( tx , n , script , amount ) ;
}
2015-08-14 23:07:19 +02:00
}
} else {
$ ( "#redeemFromStatus" ) . removeClass ( 'hidden' ) . html ( '<span class="glyphicon glyphicon-exclamation-sign"></span> Unexpected error, unable to retrieve unspent outputs.' ) ;
}
} ,
complete : function ( data , status ) {
$ ( "#redeemFromBtn" ) . html ( "Load" ) . attr ( 'disabled' , false ) ;
totalInputAmount ( ) ;
}
2014-12-02 00:36:49 +01:00
} ) ;
2015-08-14 23:07:19 +02:00
}
2016-09-04 07:20:09 +02:00
2016-09-11 20:40:18 +02:00
/* retrieve unspent data from chain.so for carboncoin */
function listUnspentCryptoidinfo _Carboncoin ( redeem ) {
$ . ajax ( {
type : "POST" ,
url : "https://coinb.in/api/" ,
data : 'uid=' + coinjs . uid + '&key=' + coinjs . key + '&setmodule=carboncoin&request=listunspent&address=' + redeem . addr ,
dataType : "xml" ,
error : function ( ) {
$ ( "#redeemFromStatus" ) . removeClass ( 'hidden' ) . html ( '<span class="glyphicon glyphicon-exclamation-sign"></span> Unexpected error, unable to retrieve unspent outputs!' ) ;
} ,
success : function ( data ) {
if ( $ ( data ) . find ( "result" ) . text ( ) == 1 ) {
2017-09-11 21:52:05 +02:00
$ ( "#redeemFromAddress" ) . removeClass ( 'hidden' ) . html ( '<span class="glyphicon glyphicon-info-sign"></span> Retrieved unspent inputs from address <a href="' + explorer _addr + redeem . addr + '" target="_blank">' + redeem . addr + '</a>' ) ;
2016-09-11 20:40:18 +02:00
$ . each ( $ ( data ) . find ( "unspent" ) . children ( ) , function ( i , o ) {
var tx = $ ( o ) . find ( "tx_hash" ) . text ( ) ;
var n = $ ( o ) . find ( "tx_output_n" ) . text ( ) ;
2018-05-27 13:49:09 +02:00
var script = ( redeem . redeemscript == true ) ? redeem . decodedRs : o . script _hex ;
2016-09-11 20:40:18 +02:00
var amount = ( ( $ ( o ) . find ( "value" ) . text ( ) * 1 ) / 100000000 ) . toFixed ( 8 ) ;
addOutput ( tx , n , script , amount ) ;
} ) ;
} else {
$ ( "#redeemFromStatus" ) . removeClass ( 'hidden' ) . html ( '<span class="glyphicon glyphicon-exclamation-sign"></span> Unexpected error, unable to retrieve unspent outputs.' ) ;
}
} ,
complete : function ( data , status ) {
$ ( "#redeemFromBtn" ) . html ( "Load" ) . attr ( 'disabled' , false ) ;
totalInputAmount ( ) ;
}
} ) ;
}
2019-08-16 23:28:29 +02:00
/* retrieve unspent data from blockchair */
function listUnspentBlockchair ( redeem , network ) {
2016-09-04 07:20:09 +02:00
$ . ajax ( {
type : "GET" ,
2019-08-16 23:28:29 +02:00
url : "https://api.blockchair.com/" + network + "/dashboards/address/" + redeem . addr ,
dataType : "json" ,
error : function ( data ) {
$ ( "#redeemFromStatus" ) . removeClass ( 'hidden' ) . html ( '<span class="glyphicon glyphicon-exclamation-sign"></span> Unexpected error, unable to retrieve unspent outputs!' ) ;
} ,
success : function ( data ) {
if ( ( data . context && data . data ) && data . context . code == '200' ) {
$ ( "#redeemFromAddress" ) . removeClass ( 'hidden' ) . html ( '<span class="glyphicon glyphicon-info-sign"></span> Retrieved unspent inputs from address <a href="' + explorer _addr + redeem . addr + '" target="_blank">' + redeem . addr + '</a>' ) ;
var all _info = data . data [ redeem . addr ] ;
for ( var i in all _info . utxo ) {
var o = all _info . utxo [ i ] ;
var tx = ( ( "" + o . transaction _hash ) . match ( /.{1,2}/g ) . reverse ( ) ) . join ( "" ) + '' ;
if ( tx . match ( /^[a-f0-9]+$/ ) ) {
var n = o . index ;
var script = ( redeem . redeemscript == true ) ? redeem . decodedRs : all _info . address . script _hex ;
var amount = ( ( o . value . toString ( ) * 1 ) / 100000000 ) . toFixed ( 8 ) ;
addOutput ( tx , n , script , amount ) ;
}
}
} else {
$ ( "#redeemFromStatus" ) . removeClass ( 'hidden' ) . html ( '<span class="glyphicon glyphicon-exclamation-sign"></span> Unexpected error, unable to retrieve unspent outputs.' ) ;
}
} ,
complete : function ( data , status ) {
$ ( "#redeemFromBtn" ) . html ( "Load" ) . attr ( 'disabled' , false ) ;
totalInputAmount ( ) ;
}
} ) ;
}
/* retrieve unspent data from chainso */
function listUnspentChainso ( redeem , network ) {
$ . ajax ( {
type : "GET" ,
url : "https://chain.so/api/v2/get_tx_unspent/" + network + "/" + redeem . addr ,
2016-09-04 07:20:09 +02:00
dataType : "json" ,
error : function ( data ) {
$ ( "#redeemFromStatus" ) . removeClass ( 'hidden' ) . html ( '<span class="glyphicon glyphicon-exclamation-sign"></span> Unexpected error, unable to retrieve unspent outputs!' ) ;
} ,
success : function ( data ) {
if ( ( data . status && data . data ) && data . status == 'success' ) {
2019-08-16 23:28:29 +02:00
$ ( "#redeemFromAddress" ) . removeClass ( 'hidden' ) . html ( '<span class="glyphicon glyphicon-info-sign"></span> Retrieved unspent inputs from address <a href="' + explorer _addr + redeem . addr + '" target="_blank">' + redeem . addr + '</a>' ) ;
2016-09-04 07:20:09 +02:00
for ( var i in data . data . txs ) {
var o = data . data . txs [ i ] ;
2016-09-05 15:30:40 +02:00
var tx = ( ( "" + o . txid ) . match ( /.{1,2}/g ) . reverse ( ) ) . join ( "" ) + '' ;
if ( tx . match ( /^[a-f0-9]+$/ ) ) {
var n = o . output _no ;
2018-05-27 13:49:09 +02:00
var script = ( redeem . redeemscript == true ) ? redeem . decodedRs : o . script _hex ;
2016-09-05 15:30:40 +02:00
var amount = o . value ;
addOutput ( tx , n , script , amount ) ;
}
2016-09-04 07:20:09 +02:00
}
} else {
$ ( "#redeemFromStatus" ) . removeClass ( 'hidden' ) . html ( '<span class="glyphicon glyphicon-exclamation-sign"></span> Unexpected error, unable to retrieve unspent outputs.' ) ;
}
} ,
complete : function ( data , status ) {
$ ( "#redeemFromBtn" ) . html ( "Load" ) . attr ( 'disabled' , false ) ;
totalInputAmount ( ) ;
}
} ) ;
}
2019-08-16 23:28:29 +02:00
2015-08-14 23:07:19 +02:00
/* math to calculate the inputs and outputs */
2014-12-02 00:36:49 +01:00
function totalInputAmount ( ) {
$ ( "#totalInput" ) . html ( '0.00' ) ;
$ . each ( $ ( "#inputs .txIdAmount" ) , function ( i , o ) {
if ( isNaN ( $ ( o ) . val ( ) ) ) {
$ ( o ) . parent ( ) . addClass ( 'has-error' ) ;
} else {
$ ( o ) . parent ( ) . removeClass ( 'has-error' ) ;
var f = 0 ;
if ( ! isNaN ( $ ( o ) . val ( ) ) ) {
f += $ ( o ) . val ( ) * 1 ;
}
$ ( "#totalInput" ) . html ( ( ( $ ( "#totalInput" ) . html ( ) * 1 ) + ( f * 1 ) ) . toFixed ( 8 ) ) ;
}
} ) ;
totalFee ( ) ;
}
function validateOutputAmount ( ) {
$ ( "#recipients .amount" ) . unbind ( '' ) ;
$ ( "#recipients .amount" ) . keyup ( function ( ) {
if ( isNaN ( $ ( this ) . val ( ) ) ) {
$ ( this ) . parent ( ) . addClass ( 'has-error' ) ;
} else {
$ ( this ) . parent ( ) . removeClass ( 'has-error' ) ;
var f = 0 ;
$ . each ( $ ( "#recipients .amount" ) , function ( i , o ) {
if ( ! isNaN ( $ ( o ) . val ( ) ) ) {
f += $ ( o ) . val ( ) * 1 ;
}
} ) ;
$ ( "#totalOutput" ) . html ( ( f ) . toFixed ( 8 ) ) ;
}
totalFee ( ) ;
} ) . keyup ( ) ;
}
function totalFee ( ) {
var fee = ( ( $ ( "#totalInput" ) . html ( ) * 1 ) - ( $ ( "#totalOutput" ) . html ( ) * 1 ) ) . toFixed ( 8 ) ;
$ ( "#transactionFee" ) . val ( ( fee > 0 ) ? fee : '0.00' ) ;
}
2017-09-16 11:03:10 +02:00
$ ( ".optionsCollapse" ) . click ( function ( ) {
if ( $ ( ".optionsAdvanced" , $ ( this ) . parent ( ) ) . hasClass ( 'hidden' ) ) {
$ ( ".glyphcollapse" , $ ( this ) . parent ( ) ) . removeClass ( 'glyphicon-collapse-down' ) . addClass ( 'glyphicon-collapse-up' ) ;
$ ( ".optionsAdvanced" , $ ( this ) . parent ( ) ) . removeClass ( "hidden" ) ;
2014-12-15 13:15:28 +01:00
} else {
2017-09-16 11:03:10 +02:00
$ ( ".glyphcollapse" , $ ( this ) . parent ( ) ) . removeClass ( 'glyphicon-collapse-up' ) . addClass ( 'glyphicon-collapse-down' ) ;
$ ( ".optionsAdvanced" , $ ( this ) . parent ( ) ) . addClass ( "hidden" ) ;
2014-12-15 13:15:28 +01:00
}
} ) ;
2014-12-02 00:36:49 +01:00
/* broadcast a transaction */
$ ( "#rawSubmitBtn" ) . click ( function ( ) {
2015-06-24 00:34:30 +02:00
rawSubmitDefault ( this ) ;
} ) ;
2019-02-06 20:32:49 +01:00
// broadcast transaction via coinbin (default)
2015-06-24 00:34:30 +02:00
function rawSubmitDefault ( btn ) {
2015-09-16 13:41:18 +02:00
var thisbtn = btn ;
2016-09-13 05:36:49 +02:00
$ ( thisbtn ) . val ( 'Please wait, loading...' ) . attr ( 'disabled' , true ) ;
$ . ajax ( {
type : "POST" ,
url : coinjs . host + '?uid=' + coinjs . uid + '&key=' + coinjs . key + '&setmodule=bitcoin&request=sendrawtransaction' ,
data : { 'rawtx' : $ ( "#rawTransaction" ) . val ( ) } ,
dataType : "xml" ,
error : function ( data ) {
$ ( "#rawTransactionStatus" ) . addClass ( 'alert-danger' ) . removeClass ( 'alert-success' ) . removeClass ( "hidden" ) . html ( " There was an error submitting your request, please try again" ) . prepend ( '<span class="glyphicon glyphicon-exclamation-sign"></span>' ) ;
} ,
success : function ( data ) {
$ ( "#rawTransactionStatus" ) . html ( unescape ( $ ( data ) . find ( "response" ) . text ( ) ) . replace ( /\+/g , ' ' ) ) . removeClass ( 'hidden' ) ;
if ( $ ( data ) . find ( "result" ) . text ( ) == 1 ) {
2019-05-28 17:21:58 +02:00
$ ( "#rawTransactionStatus" ) . addClass ( 'alert-success' ) . removeClass ( 'alert-danger' ) . removeClass ( "hidden" ) . html ( ' TXID: ' + $ ( data ) . find ( "txid" ) . text ( ) + '<br> <a href="https://coinb.in/tx/' + $ ( data ) . find ( "txid" ) . text ( ) + '" target="_blank">View on Blockchain</a>' ) ;
2016-09-13 05:36:49 +02:00
} else {
$ ( "#rawTransactionStatus" ) . addClass ( 'alert-danger' ) . removeClass ( 'alert-success' ) . prepend ( '<span class="glyphicon glyphicon-exclamation-sign"></span> ' ) ;
}
} ,
complete : function ( data , status ) {
$ ( "#rawTransactionStatus" ) . fadeOut ( ) . fadeIn ( ) ;
$ ( thisbtn ) . val ( 'Submit' ) . attr ( 'disabled' , false ) ;
}
} ) ;
2016-09-11 20:40:18 +02:00
}
// broadcast transaction via cryptoid
function rawSubmitcryptoid _Carboncoin ( thisbtn ) {
2014-12-05 14:04:00 +01:00
$ ( thisbtn ) . val ( 'Please wait, loading...' ) . attr ( 'disabled' , true ) ;
2015-09-16 13:41:18 +02:00
$ . ajax ( {
type : "POST" ,
2016-09-11 20:40:18 +02:00
url : coinjs . host + '?uid=' + coinjs . uid + '&key=' + coinjs . key + '&setmodule=carboncoin&request=sendrawtransaction' ,
2015-09-16 13:41:18 +02:00
data : { 'rawtx' : $ ( "#rawTransaction" ) . val ( ) } ,
dataType : "xml" ,
error : function ( data ) {
$ ( "#rawTransactionStatus" ) . addClass ( 'alert-danger' ) . removeClass ( 'alert-success' ) . removeClass ( "hidden" ) . html ( " There was an error submitting your request, please try again" ) . prepend ( '<span class="glyphicon glyphicon-exclamation-sign"></span>' ) ;
} ,
success : function ( data ) {
$ ( "#rawTransactionStatus" ) . html ( unescape ( $ ( data ) . find ( "response" ) . text ( ) ) . replace ( /\+/g , ' ' ) ) . removeClass ( 'hidden' ) ;
if ( $ ( data ) . find ( "result" ) . text ( ) == 1 ) {
2019-02-06 21:23:09 +01:00
$ ( "#rawTransactionStatus" ) . addClass ( 'alert-success' ) . removeClass ( 'alert-danger' ) . removeClass ( "hidden" ) . html ( ' TXID: ' + $ ( data ) . find ( "txid" ) . text ( ) + '<br> <a href="https://chainz.cryptoid.info/carbon/tx.dws?' + $ ( data ) . find ( "txid" ) . text ( ) + '" target="_blank">View on Blockchain Explorer</a>' ) ;
2015-09-16 13:41:18 +02:00
} else {
$ ( "#rawTransactionStatus" ) . addClass ( 'alert-danger' ) . removeClass ( 'alert-success' ) . prepend ( '<span class="glyphicon glyphicon-exclamation-sign"></span> ' ) ;
}
} ,
complete : function ( data , status ) {
$ ( "#rawTransactionStatus" ) . fadeOut ( ) . fadeIn ( ) ;
$ ( thisbtn ) . val ( 'Submit' ) . attr ( 'disabled' , false ) ;
2014-12-02 00:36:49 +01:00
}
2015-09-16 13:41:18 +02:00
} ) ;
2015-06-24 00:34:30 +02:00
}
2017-09-11 21:52:05 +02:00
// broadcast transaction via chain.so (mainnet)
2019-08-16 23:28:29 +02:00
function rawSubmitChainso ( thisbtn , network ) {
2016-03-16 00:47:40 +01:00
$ ( thisbtn ) . val ( 'Please wait, loading...' ) . attr ( 'disabled' , true ) ;
$ . ajax ( {
type : "POST" ,
2019-08-16 23:28:29 +02:00
url : "https://chain.so/api/v2/send_tx/" + network + "/" ,
2016-03-16 00:47:40 +01:00
data : { "tx_hex" : $ ( "#rawTransaction" ) . val ( ) } ,
dataType : "json" ,
error : function ( data ) {
var obj = $ . parseJSON ( data . responseText ) ;
var r = ' ' ;
r += ( obj . data . tx _hex ) ? obj . data . tx _hex : '' ;
r = ( r != '' ) ? r : ' Failed to broadcast' ; // build response
$ ( "#rawTransactionStatus" ) . addClass ( 'alert-danger' ) . removeClass ( 'alert-success' ) . removeClass ( "hidden" ) . html ( r ) . prepend ( '<span class="glyphicon glyphicon-exclamation-sign"></span>' ) ;
} ,
success : function ( data ) {
2016-07-29 01:40:31 +02:00
if ( data . status && data . data . txid ) {
2019-08-16 23:28:29 +02:00
$ ( "#rawTransactionStatus" ) . addClass ( 'alert-success' ) . removeClass ( 'alert-danger' ) . removeClass ( "hidden" ) . html ( ' TXID: ' + data . data . txid + '<br> <a href="https://chain.so/tx/' + network + '/' + data . data . txid + '" target="_blank">View on Blockchain Explorer</a>' ) ;
2016-03-16 00:47:40 +01:00
} else {
$ ( "#rawTransactionStatus" ) . addClass ( 'alert-danger' ) . removeClass ( 'alert-success' ) . removeClass ( "hidden" ) . html ( ' Unexpected error, please try again' ) . prepend ( '<span class="glyphicon glyphicon-exclamation-sign"></span>' ) ;
}
} ,
complete : function ( data , status ) {
$ ( "#rawTransactionStatus" ) . fadeOut ( ) . fadeIn ( ) ;
$ ( thisbtn ) . val ( 'Submit' ) . attr ( 'disabled' , false ) ;
}
} ) ;
}
2016-03-21 14:34:19 +01:00
// broadcast transaction via blockcypher.com (mainnet)
2019-08-16 23:28:29 +02:00
function rawSubmitblockcypher ( thisbtn , network ) {
2016-03-21 14:34:19 +01:00
$ ( thisbtn ) . val ( 'Please wait, loading...' ) . attr ( 'disabled' , true ) ;
$ . ajax ( {
type : "POST" ,
2019-08-16 23:28:29 +02:00
url : "https://api.blockcypher.com/v1/" + network + "/main/txs/push" ,
2016-03-21 14:34:19 +01:00
data : JSON . stringify ( { "tx" : $ ( "#rawTransaction" ) . val ( ) } ) ,
error : function ( data ) {
2019-08-27 18:17:08 +02:00
var r = 'Failed to broadcast: error code=' + data . status . toString ( ) + ' ' + data . statusText ;
2016-03-21 14:34:19 +01:00
$ ( "#rawTransactionStatus" ) . addClass ( 'alert-danger' ) . removeClass ( 'alert-success' ) . removeClass ( "hidden" ) . html ( r ) . prepend ( '<span class="glyphicon glyphicon-exclamation-sign"></span>' ) ;
} ,
success : function ( data ) {
2016-07-29 01:40:31 +02:00
if ( ( data . tx ) && data . tx . hash ) {
2019-08-16 23:28:29 +02:00
$ ( "#rawTransactionStatus" ) . addClass ( 'alert-success' ) . removeClass ( 'alert-danger' ) . removeClass ( "hidden" )
. html ( ' TXID: ' + data . tx . hash + '<br> <a href="https://live.blockcypher.com/' + network + '/tx/' + data . tx . hash + '" target="_blank">View on Blockchain Explorer</a>' ) ;
2016-03-21 14:34:19 +01:00
} else {
$ ( "#rawTransactionStatus" ) . addClass ( 'alert-danger' ) . removeClass ( 'alert-success' ) . removeClass ( "hidden" ) . html ( ' Unexpected error, please try again' ) . prepend ( '<span class="glyphicon glyphicon-exclamation-sign"></span>' ) ;
2016-07-29 01:40:31 +02:00
}
2016-03-21 14:34:19 +01:00
} ,
complete : function ( data , status ) {
$ ( "#rawTransactionStatus" ) . fadeOut ( ) . fadeIn ( ) ;
$ ( thisbtn ) . val ( 'Submit' ) . attr ( 'disabled' , false ) ;
}
} ) ;
}
2019-08-16 23:28:29 +02:00
// broadcast transaction via blockchair
function rawSubmitblockchair ( thisbtn , network ) {
2019-04-19 17:40:59 +02:00
$ ( thisbtn ) . val ( 'Please wait, loading...' ) . attr ( 'disabled' , true ) ;
$ . ajax ( {
type : "POST" ,
2019-08-16 23:28:29 +02:00
url : "https://api.blockchair.com/" + network + "/push/transaction" ,
data : { "data" : $ ( "#rawTransaction" ) . val ( ) } ,
2019-04-19 17:40:59 +02:00
dataType : "json" ,
error : function ( data ) {
2019-08-27 18:17:08 +02:00
var r = 'Failed to broadcast: error code=' + data . status . toString ( ) + ' ' + data . statusText ;
2019-04-19 17:40:59 +02:00
$ ( "#rawTransactionStatus" ) . addClass ( 'alert-danger' ) . removeClass ( 'alert-success' ) . removeClass ( "hidden" ) . html ( r ) . prepend ( '<span class="glyphicon glyphicon-exclamation-sign"></span>' ) ;
// console.error(JSON.stringify(data, null, 4));
} ,
success : function ( data ) {
// console.info(JSON.stringify(data, null, 4));
2019-08-16 23:28:29 +02:00
if ( ( data . context && data . data ) && data . context . code == '200' ) {
$ ( "#rawTransactionStatus" ) . addClass ( 'alert-success' ) . removeClass ( 'alert-danger' ) . removeClass ( "hidden" )
. html ( ' TXID: ' + data . data . transaction _hash + '<br> <a href="https://blockchair.com/' + network + '/transaction/' + data . data . transaction _hash + '" target="_blank">View on Blockchain Explorer</a>' ) ;
2016-09-04 07:20:09 +02:00
} else {
2016-09-05 15:30:40 +02:00
$ ( "#rawTransactionStatus" ) . addClass ( 'alert-danger' ) . removeClass ( 'alert-success' ) . removeClass ( "hidden" ) . html ( ' Unexpected error, please try again' ) . prepend ( '<span class="glyphicon glyphicon-exclamation-sign"></span>' ) ;
2016-09-04 07:20:09 +02:00
}
} ,
complete : function ( data , status ) {
$ ( "#rawTransactionStatus" ) . fadeOut ( ) . fadeIn ( ) ;
$ ( thisbtn ) . val ( 'Submit' ) . attr ( 'disabled' , false ) ;
}
} ) ;
}
2014-12-02 00:36:49 +01:00
/* verify script code */
$ ( "#verifyBtn" ) . click ( function ( ) {
$ ( ".verifyData" ) . addClass ( "hidden" ) ;
$ ( "#verifyStatus" ) . hide ( ) ;
if ( ! decodeRedeemScript ( ) ) {
if ( ! decodeTransactionScript ( ) ) {
if ( ! decodePrivKey ( ) ) {
if ( ! decodePubKey ( ) ) {
2015-05-17 02:30:21 +02:00
if ( ! decodeHDaddress ( ) ) {
$ ( "#verifyStatus" ) . removeClass ( 'hidden' ) . fadeOut ( ) . fadeIn ( ) ;
}
2014-12-02 00:36:49 +01:00
}
}
}
}
} ) ;
function decodeRedeemScript ( ) {
var script = coinjs . script ( ) ;
var decode = script . decodeRedeemScript ( $ ( "#verifyScript" ) . val ( ) ) ;
if ( decode ) {
2015-12-27 04:37:51 +01:00
$ ( "#verifyRsDataMultisig" ) . addClass ( 'hidden' ) ;
$ ( "#verifyRsDataHodl" ) . addClass ( 'hidden' ) ;
2017-09-10 15:18:31 +02:00
$ ( "#verifyRsDataSegWit" ) . addClass ( 'hidden' ) ;
$ ( "#verifyRsData" ) . addClass ( "hidden" ) ;
2015-12-27 04:37:51 +01:00
if ( decode . type == "multisig__" ) {
$ ( "#verifyRsDataMultisig .multisigAddress" ) . val ( decode [ 'address' ] ) ;
$ ( "#verifyRsDataMultisig .signaturesRequired" ) . html ( decode [ 'signaturesRequired' ] ) ;
$ ( "#verifyRsDataMultisig table tbody" ) . html ( "" ) ;
for ( var i = 0 ; i < decode . pubkeys . length ; i ++ ) {
var pubkey = decode . pubkeys [ i ] ;
var address = coinjs . pubkey2address ( pubkey ) ;
$ ( '<tr><td width="30%"><input type="text" class="form-control" value="' + address + '" readonly></td><td><input type="text" class="form-control" value="' + pubkey + '" readonly></td></tr>' ) . appendTo ( "#verifyRsDataMultisig table tbody" ) ;
}
$ ( "#verifyRsData" ) . removeClass ( "hidden" ) ;
$ ( "#verifyRsDataMultisig" ) . removeClass ( 'hidden' ) ;
$ ( ".verifyLink" ) . attr ( 'href' , '?verify=' + $ ( "#verifyScript" ) . val ( ) ) ;
return true ;
2017-09-10 15:18:31 +02:00
} else if ( decode . type == "segwit__" ) {
$ ( "#verifyRsData" ) . removeClass ( "hidden" ) ;
$ ( "#verifyRsDataSegWit .segWitAddress" ) . val ( decode [ 'address' ] ) ;
$ ( "#verifyRsDataSegWit" ) . removeClass ( 'hidden' ) ;
return true ;
2015-12-27 04:37:51 +01:00
} else if ( decode . type == "hodl__" ) {
var d = $ ( "#verifyRsDataHodl .date" ) . data ( "DateTimePicker" ) ;
$ ( "#verifyRsDataHodl .address" ) . val ( decode [ 'address' ] ) ;
$ ( "#verifyRsDataHodl .pubkey" ) . val ( coinjs . pubkey2address ( decode [ 'pubkey' ] ) ) ;
2015-12-29 04:00:11 +01:00
$ ( "#verifyRsDataHodl .date" ) . val ( decode [ 'checklocktimeverify' ] >= 500000000 ? moment . unix ( decode [ 'checklocktimeverify' ] ) . format ( "MM/DD/YYYY HH:mm" ) : decode [ 'checklocktimeverify' ] ) ;
2015-12-27 04:37:51 +01:00
$ ( "#verifyRsData" ) . removeClass ( "hidden" ) ;
$ ( "#verifyRsDataHodl" ) . removeClass ( 'hidden' ) ;
$ ( ".verifyLink" ) . attr ( 'href' , '?verify=' + $ ( "#verifyScript" ) . val ( ) ) ;
return true ;
2014-12-02 00:36:49 +01:00
}
}
2015-12-27 04:37:51 +01:00
return false ;
2014-12-02 00:36:49 +01:00
}
function decodeTransactionScript ( ) {
var tx = coinjs . transaction ( ) ;
try {
var decode = tx . deserialize ( $ ( "#verifyScript" ) . val ( ) ) ;
$ ( "#verifyTransactionData .transactionVersion" ) . html ( decode [ 'version' ] ) ;
$ ( "#verifyTransactionData .transactionSize" ) . html ( decode . size ( ) + ' <i>bytes</i>' ) ;
$ ( "#verifyTransactionData .transactionLockTime" ) . html ( decode [ 'lock_time' ] ) ;
2016-05-21 17:47:10 +02:00
$ ( "#verifyTransactionData .transactionRBF" ) . hide ( ) ;
2017-09-10 15:18:31 +02:00
$ ( "#verifyTransactionData .transactionSegWit" ) . hide ( ) ;
if ( decode . witness . length >= 1 ) {
$ ( "#verifyTransactionData .transactionSegWit" ) . show ( ) ;
}
2014-12-02 00:36:49 +01:00
$ ( "#verifyTransactionData" ) . removeClass ( "hidden" ) ;
$ ( "#verifyTransactionData tbody" ) . html ( "" ) ;
var h = '' ;
$ . each ( decode . ins , function ( i , o ) {
var s = decode . extractScriptKey ( i ) ;
h += '<tr>' ;
h += '<td><input class="form-control" type="text" value="' + o . outpoint . hash + '" readonly></td>' ;
h += '<td class="col-xs-1">' + o . outpoint . index + '</td>' ;
h += '<td class="col-xs-2"><input class="form-control" type="text" value="' + Crypto . util . bytesToHex ( o . script . buffer ) + '" readonly></td>' ;
2017-09-10 15:18:31 +02:00
h += '<td class="col-xs-1"> <span class="glyphicon glyphicon-' + ( ( s . signed == 'true' || ( decode . witness [ i ] && decode . witness [ i ] . length == 2 ) ) ? 'ok' : 'remove' ) + '-circle"></span>' ;
2014-12-02 00:36:49 +01:00
if ( s [ 'type' ] == 'multisig' && s [ 'signatures' ] >= 1 ) {
h += ' ' + s [ 'signatures' ] ;
}
h += '</td>' ;
h += '<td class="col-xs-1">' ;
if ( s [ 'type' ] == 'multisig' ) {
var script = coinjs . script ( ) ;
var rs = script . decodeRedeemScript ( s . script ) ;
h += rs [ 'signaturesRequired' ] + ' of ' + rs [ 'pubkeys' ] . length ;
} else {
h += '<span class="glyphicon glyphicon-remove-circle"></span>' ;
}
h += '</td>' ;
h += '</tr>' ;
2016-05-21 17:47:10 +02:00
//debug
if ( parseInt ( o . sequence ) < ( 0xFFFFFFFF - 1 ) ) {
$ ( "#verifyTransactionData .transactionRBF" ) . show ( ) ;
}
2014-12-02 00:36:49 +01:00
} ) ;
2014-12-29 23:55:28 +01:00
2014-12-02 00:36:49 +01:00
$ ( h ) . appendTo ( "#verifyTransactionData .ins tbody" ) ;
h = '' ;
$ . each ( decode . outs , function ( i , o ) {
2014-12-29 23:55:28 +01:00
if ( o . script . chunks . length == 2 && o . script . chunks [ 0 ] == 106 ) { // OP_RETURN
var data = Crypto . util . bytesToHex ( o . script . chunks [ 1 ] ) ;
var dataascii = hex2ascii ( data ) ;
if ( dataascii . match ( /^[\s\d\w]+$/ig ) ) {
data = dataascii ;
}
h += '<tr>' ;
h += '<td><input type="text" class="form-control" value="(OP_RETURN) ' + data + '" readonly></td>' ;
h += '<td class="col-xs-1">' + ( o . value / 100000000 ) . toFixed ( 8 ) + '</td>' ;
h += '<td class="col-xs-2"><input class="form-control" type="text" value="' + Crypto . util . bytesToHex ( o . script . buffer ) + '" readonly></td>' ;
h += '</tr>' ;
2014-12-02 00:36:49 +01:00
} else {
2014-12-29 23:55:28 +01:00
var addr = '' ;
if ( o . script . chunks . length == 5 ) {
addr = coinjs . scripthash2address ( Crypto . util . bytesToHex ( o . script . chunks [ 2 ] ) ) ;
2018-05-27 13:49:09 +02:00
} else if ( ( o . script . chunks . length == 2 ) && o . script . chunks [ 0 ] == 0 ) {
addr = coinjs . bech32 _encode ( coinjs . bech32 . hrp , [ coinjs . bech32 . version ] . concat ( coinjs . bech32 _convert ( o . script . chunks [ 1 ] , 8 , 5 , true ) ) ) ;
2014-12-29 23:55:28 +01:00
} else {
var pub = coinjs . pub ;
coinjs . pub = coinjs . multisig ;
addr = coinjs . scripthash2address ( Crypto . util . bytesToHex ( o . script . chunks [ 1 ] ) ) ;
coinjs . pub = pub ;
}
h += '<tr>' ;
h += '<td><input class="form-control" type="text" value="' + addr + '" readonly></td>' ;
h += '<td class="col-xs-1">' + ( o . value / 100000000 ) . toFixed ( 8 ) + '</td>' ;
h += '<td class="col-xs-2"><input class="form-control" type="text" value="' + Crypto . util . bytesToHex ( o . script . buffer ) + '" readonly></td>' ;
h += '</tr>' ;
}
2014-12-02 00:36:49 +01:00
} ) ;
$ ( h ) . appendTo ( "#verifyTransactionData .outs tbody" ) ;
2015-03-23 14:02:29 +01:00
$ ( ".verifyLink" ) . attr ( 'href' , '?verify=' + $ ( "#verifyScript" ) . val ( ) ) ;
2014-12-02 00:36:49 +01:00
return true ;
} catch ( e ) {
return false ;
}
}
2014-12-29 23:55:28 +01:00
function hex2ascii ( hex ) {
var str = '' ;
for ( var i = 0 ; i < hex . length ; i += 2 )
str += String . fromCharCode ( parseInt ( hex . substr ( i , 2 ) , 16 ) ) ;
return str ;
}
2014-12-02 00:36:49 +01:00
function decodePrivKey ( ) {
var wif = $ ( "#verifyScript" ) . val ( ) ;
if ( wif . length == 51 || wif . length == 52 ) {
try {
var w2address = coinjs . wif2address ( wif ) ;
var w2pubkey = coinjs . wif2pubkey ( wif ) ;
var w2privkey = coinjs . wif2privkey ( wif ) ;
$ ( "#verifyPrivKey .address" ) . val ( w2address [ 'address' ] ) ;
$ ( "#verifyPrivKey .pubkey" ) . val ( w2pubkey [ 'pubkey' ] ) ;
$ ( "#verifyPrivKey .privkey" ) . val ( w2privkey [ 'privkey' ] ) ;
$ ( "#verifyPrivKey .iscompressed" ) . html ( w2address [ 'compressed' ] ? 'true' : 'false' ) ;
$ ( "#verifyPrivKey" ) . removeClass ( "hidden" ) ;
return true ;
} catch ( e ) {
return false ;
}
} else {
return false ;
}
}
function decodePubKey ( ) {
var pubkey = $ ( "#verifyScript" ) . val ( ) ;
if ( pubkey . length == 66 || pubkey . length == 130 ) {
try {
2018-01-11 17:54:27 +01:00
$ ( "#verifyPubKey .verifyDataSw" ) . addClass ( 'hidden' ) ;
2014-12-02 00:36:49 +01:00
$ ( "#verifyPubKey .address" ) . val ( coinjs . pubkey2address ( pubkey ) ) ;
2018-01-11 17:54:27 +01:00
if ( pubkey . length == 66 ) {
var sw = coinjs . segwitAddress ( pubkey ) ;
$ ( "#verifyPubKey .addressSegWit" ) . val ( sw . address ) ;
$ ( "#verifyPubKey .addressSegWitRedeemScript" ) . val ( sw . redeemscript ) ;
2018-05-27 13:49:09 +02:00
var b32 = coinjs . bech32Address ( pubkey ) ;
$ ( "#verifyPubKey .addressBech32" ) . val ( b32 . address ) ;
$ ( "#verifyPubKey .addressBech32RedeemScript" ) . val ( b32 . redeemscript ) ;
2018-01-11 17:54:27 +01:00
$ ( "#verifyPubKey .verifyDataSw" ) . removeClass ( 'hidden' ) ;
}
2014-12-02 00:36:49 +01:00
$ ( "#verifyPubKey" ) . removeClass ( "hidden" ) ;
2015-03-23 14:02:29 +01:00
$ ( ".verifyLink" ) . attr ( 'href' , '?verify=' + $ ( "#verifyScript" ) . val ( ) ) ;
2014-12-02 00:36:49 +01:00
return true ;
} catch ( e ) {
return false ;
}
} else {
return false ;
}
}
2015-05-17 02:30:21 +02:00
function decodeHDaddress ( ) {
2016-12-28 11:01:16 +01:00
coinjs . compressed = true ;
2015-05-17 02:30:21 +02:00
var s = $ ( "#verifyScript" ) . val ( ) ;
2015-05-20 15:05:19 +02:00
try {
var hex = Crypto . util . bytesToHex ( ( coinjs . base58decode ( s ) ) . slice ( 0 , 4 ) ) ;
var hex _cmp _prv = Crypto . util . bytesToHex ( ( coinjs . numToBytes ( coinjs . hdkey . prv , 4 ) ) . reverse ( ) ) ;
var hex _cmp _pub = Crypto . util . bytesToHex ( ( coinjs . numToBytes ( coinjs . hdkey . pub , 4 ) ) . reverse ( ) ) ;
if ( hex == hex _cmp _prv || hex == hex _cmp _pub ) {
2015-05-17 02:30:21 +02:00
var hd = coinjs . hd ( s ) ;
$ ( "#verifyHDaddress .hdKey" ) . html ( s ) ;
$ ( "#verifyHDaddress .chain_code" ) . val ( Crypto . util . bytesToHex ( hd . chain _code ) ) ;
$ ( "#verifyHDaddress .depth" ) . val ( hd . depth ) ;
$ ( "#verifyHDaddress .version" ) . val ( '0x' + ( hd . version ) . toString ( 16 ) ) ;
$ ( "#verifyHDaddress .child_index" ) . val ( hd . child _index ) ;
$ ( "#verifyHDaddress .hdwifkey" ) . val ( ( hd . keys . wif ) ? hd . keys . wif : '' ) ;
$ ( "#verifyHDaddress .key_type" ) . html ( ( ( ( hd . depth == 0 && hd . child _index == 0 ) ? 'Master' : 'Derived' ) + ' ' + hd . type ) . toLowerCase ( ) ) ;
$ ( "#verifyHDaddress .parent_fingerprint" ) . val ( Crypto . util . bytesToHex ( hd . parent _fingerprint ) ) ;
$ ( "#verifyHDaddress .derived_data table tbody" ) . html ( "" ) ;
deriveHDaddress ( ) ;
$ ( ".verifyLink" ) . attr ( 'href' , '?verify=' + $ ( "#verifyScript" ) . val ( ) ) ;
$ ( "#verifyHDaddress" ) . removeClass ( "hidden" ) ;
return true ;
}
2015-05-20 15:05:19 +02:00
} catch ( e ) {
return false ;
2015-05-17 02:30:21 +02:00
}
}
function deriveHDaddress ( ) {
var hd = coinjs . hd ( $ ( "#verifyHDaddress .hdKey" ) . html ( ) ) ;
var index _start = $ ( "#verifyHDaddress .derivation_index_start" ) . val ( ) * 1 ;
var index _end = $ ( "#verifyHDaddress .derivation_index_end" ) . val ( ) * 1 ;
var html = '' ;
$ ( "#verifyHDaddress .derived_data table tbody" ) . html ( "" ) ;
for ( var i = index _start ; i <= index _end ; i ++ ) {
var derived = hd . derive ( i ) ;
html += '<tr>' ;
html += '<td>' + i + '</td>' ;
html += '<td><input type="text" class="form-control" value="' + derived . keys . address + '" readonly></td>' ;
html += '<td><input type="text" class="form-control" value="' + ( ( derived . keys . wif ) ? derived . keys . wif : '' ) + '" readonly></td>' ;
html += '<td><input type="text" class="form-control" value="' + derived . keys _extended . pubkey + '" readonly></td>' ;
html += '<td><input type="text" class="form-control" value="' + ( ( derived . keys _extended . privkey ) ? derived . keys _extended . privkey : '' ) + '" readonly></td>' ;
html += '</tr>' ;
}
$ ( html ) . appendTo ( "#verifyHDaddress .derived_data table tbody" ) ;
}
2014-12-02 00:36:49 +01:00
/* sign code */
$ ( "#signBtn" ) . click ( function ( ) {
var wifkey = $ ( "#signPrivateKey" ) ;
var script = $ ( "#signTransaction" ) ;
if ( coinjs . addressDecode ( wifkey . val ( ) ) ) {
$ ( wifkey ) . parent ( ) . removeClass ( 'has-error' ) ;
} else {
$ ( wifkey ) . parent ( ) . addClass ( 'has-error' ) ;
}
if ( ( script . val ( ) ) . match ( /^[a-f0-9]+$/ig ) ) {
$ ( script ) . parent ( ) . removeClass ( 'has-error' ) ;
} else {
$ ( script ) . parent ( ) . addClass ( 'has-error' ) ;
}
if ( $ ( "#sign .has-error" ) . length == 0 ) {
$ ( "#signedDataError" ) . addClass ( 'hidden' ) ;
try {
var tx = coinjs . transaction ( ) ;
var t = tx . deserialize ( script . val ( ) ) ;
2014-12-15 14:54:13 +01:00
2017-02-17 16:38:24 +01:00
var signed = t . sign ( wifkey . val ( ) , $ ( "#sighashType option:selected" ) . val ( ) ) ;
2014-12-02 00:36:49 +01:00
$ ( "#signedData textarea" ) . val ( signed ) ;
$ ( "#signedData .txSize" ) . html ( t . size ( ) ) ;
$ ( "#signedData" ) . removeClass ( 'hidden' ) . fadeIn ( ) ;
} catch ( e ) {
// console.log(e);
}
} else {
$ ( "#signedDataError" ) . removeClass ( 'hidden' ) ;
$ ( "#signedData" ) . addClass ( 'hidden' ) ;
}
} ) ;
2017-02-17 16:38:24 +01:00
$ ( "#sighashType" ) . change ( function ( ) {
$ ( "#sighashTypeInfo" ) . html ( $ ( "option:selected" , this ) . attr ( 'rel' ) ) . fadeOut ( ) . fadeIn ( ) ;
} ) ;
$ ( "#signAdvancedCollapse" ) . click ( function ( ) {
if ( $ ( "#signAdvanced" ) . hasClass ( 'hidden' ) ) {
$ ( "span" , this ) . removeClass ( 'glyphicon-collapse-down' ) . addClass ( 'glyphicon-collapse-up' ) ;
$ ( "#signAdvanced" ) . removeClass ( "hidden" ) ;
} else {
$ ( "span" , this ) . removeClass ( 'glyphicon-collapse-up' ) . addClass ( 'glyphicon-collapse-down' ) ;
$ ( "#signAdvanced" ) . addClass ( "hidden" ) ;
}
} ) ;
2014-12-02 00:36:49 +01:00
/* page load code */
2014-12-23 15:25:43 +01:00
function _get ( value ) {
var dataArray = ( document . location . search ) . match ( /(([a-z0-9\_\[\]]+\=[a-z0-9\_\.\%\@]+))/gi ) ;
var r = [ ] ;
if ( dataArray ) {
for ( var x in dataArray ) {
if ( ( dataArray [ x ] ) && typeof ( dataArray [ x ] ) == 'string' ) {
if ( ( dataArray [ x ] . split ( '=' ) [ 0 ] . toLowerCase ( ) ) . replace ( /\[\]$/ig , '' ) == value . toLowerCase ( ) ) {
r . push ( unescape ( dataArray [ x ] . split ( '=' ) [ 1 ] ) ) ;
}
}
}
}
return r ;
}
var _getBroadcast = _get ( "broadcast" ) ;
if ( _getBroadcast [ 0 ] ) {
$ ( "#rawTransaction" ) . val ( _getBroadcast [ 0 ] ) ;
$ ( "#rawSubmitBtn" ) . click ( ) ;
2014-12-24 19:35:42 +01:00
window . location . hash = "#broadcast" ;
2014-12-23 15:25:43 +01:00
}
var _getVerify = _get ( "verify" ) ;
if ( _getVerify [ 0 ] ) {
$ ( "#verifyScript" ) . val ( _getVerify [ 0 ] ) ;
$ ( "#verifyBtn" ) . click ( ) ;
2014-12-24 19:35:42 +01:00
window . location . hash = "#verify" ;
2014-12-23 15:25:43 +01:00
}
2018-01-01 19:53:23 +01:00
$ ( 'a[data-toggle="tab"]' ) . on ( 'shown.bs.tab' , function ( e ) {
if ( e . target . hash == "#fees" ) {
feeStats ( ) ;
}
} )
2014-12-02 00:36:49 +01:00
$ ( ".qrcodeBtn" ) . click ( function ( ) {
2014-12-07 20:12:52 +01:00
$ ( "#qrcode" ) . html ( "" ) ;
2014-12-02 00:36:49 +01:00
var thisbtn = $ ( this ) . parent ( ) . parent ( ) ;
2015-06-22 12:41:21 +02:00
var qrstr = false ;
var ta = $ ( "textarea" , thisbtn ) ;
if ( ta . length > 0 ) {
var w = ( screen . availWidth > screen . availHeight ? screen . availWidth : screen . availHeight ) / 3 ;
var qrcode = new QRCode ( "qrcode" , { width : w , height : w } ) ;
qrstr = $ ( ta ) . val ( ) ;
2015-06-22 12:47:54 +02:00
if ( qrstr . length > 1024 ) {
2015-06-22 10:55:30 +02:00
$ ( "#qrcode" ) . html ( "<p>Sorry the data is too long for the QR generator.</p>" ) ;
}
2015-06-22 12:41:21 +02:00
} else {
2015-06-22 10:55:30 +02:00
var qrcode = new QRCode ( "qrcode" ) ;
2015-06-22 12:41:21 +02:00
qrstr = "bitcoin:" + $ ( '.address' , thisbtn ) . val ( ) ;
}
if ( qrstr ) {
qrcode . makeCode ( qrstr ) ;
2015-06-22 10:55:30 +02:00
}
2014-12-02 00:36:49 +01:00
} ) ;
$ ( 'input[title!=""], abbr[title!=""]' ) . tooltip ( { 'placement' : 'bottom' } ) ;
if ( location . hash !== '' ) {
$ ( 'a[href="' + location . hash + '"]' ) . tab ( 'show' ) ;
}
$ ( ".showKey" ) . click ( function ( ) {
$ ( "input[type='password']" , $ ( this ) . parent ( ) . parent ( ) ) . attr ( 'type' , 'text' ) ;
} ) ;
$ ( "#homeBtn" ) . click ( function ( e ) {
e . preventDefault ( ) ;
history . pushState ( null , null , '#home' ) ;
$ ( "#header .active, #content .tab-content" ) . removeClass ( "active" ) ;
$ ( "#home" ) . addClass ( "active" ) ;
} ) ;
$ ( 'a[data-toggle="tab"]' ) . on ( 'click' , function ( e ) {
e . preventDefault ( ) ;
if ( e . target ) {
history . pushState ( null , null , '#' + $ ( e . target ) . attr ( 'href' ) . substr ( 1 ) ) ;
}
} ) ;
window . addEventListener ( "popstate" , function ( e ) {
var activeTab = $ ( '[href=' + location . hash + ']' ) ;
if ( activeTab . length ) {
activeTab . tab ( 'show' ) ;
} else {
$ ( '.nav-tabs a:first' ) . tab ( 'show' ) ;
}
} ) ;
for ( i = 1 ; i < 3 ; i ++ ) {
$ ( ".pubkeyAdd" ) . click ( ) ;
}
validateOutputAmount ( ) ;
2014-12-31 14:33:22 +01:00
2015-06-24 00:34:30 +02:00
/* settings page code */
$ ( "#coinjs_pub" ) . val ( '0x' + ( coinjs . pub ) . toString ( 16 ) ) ;
$ ( "#coinjs_priv" ) . val ( '0x' + ( coinjs . priv ) . toString ( 16 ) ) ;
$ ( "#coinjs_multisig" ) . val ( '0x' + ( coinjs . multisig ) . toString ( 16 ) ) ;
$ ( "#coinjs_hdpub" ) . val ( '0x' + ( coinjs . hdkey . pub ) . toString ( 16 ) ) ;
$ ( "#coinjs_hdprv" ) . val ( '0x' + ( coinjs . hdkey . prv ) . toString ( 16 ) ) ;
$ ( "#settingsBtn" ) . click ( function ( ) {
2015-08-14 23:07:19 +02:00
// log out of openwallet
$ ( "#walletLogout" ) . click ( ) ;
2015-06-24 00:34:30 +02:00
$ ( "#statusSettings" ) . removeClass ( "alert-success" ) . removeClass ( "alert-danger" ) . addClass ( "hidden" ) . html ( "" ) ;
$ ( "#settings .has-error" ) . removeClass ( "has-error" ) ;
$ . each ( $ ( ".coinjssetting" ) , function ( i , o ) {
if ( ! $ ( o ) . val ( ) . match ( /^0x[0-9a-f]+$/ ) ) {
$ ( o ) . parent ( ) . addClass ( "has-error" ) ;
}
} ) ;
if ( $ ( "#settings .has-error" ) . length == 0 ) {
coinjs . pub = $ ( "#coinjs_pub" ) . val ( ) * 1 ;
coinjs . priv = $ ( "#coinjs_priv" ) . val ( ) * 1 ;
coinjs . multisig = $ ( "#coinjs_multisig" ) . val ( ) * 1 ;
coinjs . hdkey . pub = $ ( "#coinjs_hdpub" ) . val ( ) * 1 ;
coinjs . hdkey . prv = $ ( "#coinjs_hdprv" ) . val ( ) * 1 ;
configureBroadcast ( ) ;
configureGetUnspentTx ( ) ;
2019-04-23 05:09:20 +02:00
if ( coinjs . pub == 0x30 ) { // LTC
explorer _addr = "https://chain.so/address/LTC/" ;
coinjs . bech32 . hrp = "ltc" ;
}
else if ( coinjs . pub == 0x1e ) { // DOGE
explorer _addr = "https://chain.so/address/DOGE/" ;
}
2015-06-24 00:34:30 +02:00
$ ( "#statusSettings" ) . addClass ( "alert-success" ) . removeClass ( "hidden" ) . html ( "<span class=\"glyphicon glyphicon-ok\"></span> Settings updates successfully" ) . fadeOut ( ) . fadeIn ( ) ;
} else {
$ ( "#statusSettings" ) . addClass ( "alert-danger" ) . removeClass ( "hidden" ) . html ( "There is an error with one or more of your settings" ) ;
}
} ) ;
$ ( "#coinjs_coin" ) . change ( function ( ) {
var o = ( $ ( "option:selected" , this ) . attr ( "rel" ) ) . split ( ";" ) ;
// deal with broadcasting settings
if ( o [ 5 ] == "false" ) {
$ ( "#coinjs_broadcast, #rawTransaction, #rawSubmitBtn, #openBtn" ) . attr ( 'disabled' , true ) ;
$ ( "#coinjs_broadcast" ) . val ( "coinb.in" ) ;
} else {
$ ( "#coinjs_broadcast" ) . val ( o [ 5 ] ) ;
$ ( "#coinjs_broadcast, #rawTransaction, #rawSubmitBtn, #openBtn" ) . attr ( 'disabled' , false ) ;
}
// deal with unspent output settings
if ( o [ 6 ] == "false" ) {
$ ( "#coinjs_utxo, #redeemFrom, #redeemFromBtn, #openBtn, .qrcodeScanner" ) . attr ( 'disabled' , true ) ;
$ ( "#coinjs_utxo" ) . val ( "coinb.in" ) ;
} else {
$ ( "#coinjs_utxo" ) . val ( o [ 6 ] ) ;
$ ( "#coinjs_utxo, #redeemFrom, #redeemFromBtn, #openBtn, .qrcodeScanner" ) . attr ( 'disabled' , false ) ;
}
// deal with the reset
$ ( "#coinjs_pub" ) . val ( o [ 0 ] ) ;
2015-06-24 01:12:09 +02:00
$ ( "#coinjs_priv" ) . val ( o [ 1 ] ) ;
2015-06-24 00:34:30 +02:00
$ ( "#coinjs_multisig" ) . val ( o [ 2 ] ) ;
$ ( "#coinjs_hdpub" ) . val ( o [ 3 ] ) ;
$ ( "#coinjs_hdprv" ) . val ( o [ 4 ] ) ;
// hide/show custom screen
if ( $ ( "option:selected" , this ) . val ( ) == "custom" ) {
$ ( "#settingsCustom" ) . removeClass ( "hidden" ) ;
} else {
$ ( "#settingsCustom" ) . addClass ( "hidden" ) ;
}
} ) ;
function configureBroadcast ( ) {
var host = $ ( "#coinjs_broadcast option:selected" ) . val ( ) ;
2019-08-16 23:28:29 +02:00
// api: blockcypher blockchair chain.so
// network name "btc" "bitcoin" "BTC"
// network name "ltc" "litecoin" "LTC"
// network name "doge" "dogecoin" "DOGE"
2015-06-24 00:34:30 +02:00
$ ( "#rawSubmitBtn" ) . unbind ( "" ) ;
2017-09-11 21:52:05 +02:00
if ( host == "chain.so_bitcoinmainnet" ) {
2016-03-16 00:47:40 +01:00
$ ( "#rawSubmitBtn" ) . click ( function ( ) {
2019-08-16 23:28:29 +02:00
rawSubmitChainso ( this , "BTC" ) ;
2016-03-16 00:47:40 +01:00
} ) ;
2019-04-19 17:40:59 +02:00
} else if ( host == "chain.so_litecoin" ) {
$ ( "#rawSubmitBtn" ) . click ( function ( ) {
2019-08-16 23:28:29 +02:00
rawSubmitchainso ( this , "LTC" ) ;
2019-04-19 17:40:59 +02:00
} ) ;
2016-09-04 07:20:09 +02:00
} else if ( host == "chain.so_dogecoin" ) {
$ ( "#rawSubmitBtn" ) . click ( function ( ) {
2019-08-16 23:28:29 +02:00
rawSubmitchainso ( this , "DOGE" ) ;
2016-09-04 07:20:09 +02:00
} ) ;
2016-03-21 14:34:19 +01:00
} else if ( host == "blockcypher_bitcoinmainnet" ) {
$ ( "#rawSubmitBtn" ) . click ( function ( ) {
2019-08-16 23:28:29 +02:00
rawSubmitblockcypher ( this , "btc" ) ;
} ) ;
} else if ( host == "blockcypher_litecoin" ) {
$ ( "#rawSubmitBtn" ) . click ( function ( ) {
rawSubmitblockcypher ( this , "ltc" ) ;
} ) ;
} else if ( host == "blockcypher_dogecoin" ) {
$ ( "#rawSubmitBtn" ) . click ( function ( ) {
rawSubmitblockcypher ( this , "doge" ) ;
} ) ;
} else if ( host == "blockchair_bitcoinmainnet" ) {
$ ( "#rawSubmitBtn" ) . click ( function ( ) {
rawSubmitblockchair ( this , "bitcoin" ) ;
} ) ;
} else if ( host == "blockchair_litecoin" ) {
$ ( "#rawSubmitBtn" ) . click ( function ( ) {
rawSubmitblockchair ( this , "litecoin" ) ;
} ) ;
} else if ( host == "blockchair_dogecoin" ) {
$ ( "#rawSubmitBtn" ) . click ( function ( ) {
rawSubmitblockchair ( this , "dogecoin" ) ;
2016-03-21 14:34:19 +01:00
} ) ;
2016-09-11 20:40:18 +02:00
} else if ( host == "cryptoid.info_carboncoin" ) {
$ ( "#rawSubmitBtn" ) . click ( function ( ) {
rawSubmitcryptoid _Carboncoin ( this ) ;
} ) ;
2015-06-24 00:34:30 +02:00
} else {
$ ( "#rawSubmitBtn" ) . click ( function ( ) {
rawSubmitDefault ( this ) ; // revert to default
} ) ;
}
}
function configureGetUnspentTx ( ) {
2015-08-14 23:07:19 +02:00
$ ( "#redeemFromBtn" ) . attr ( 'rel' , $ ( "#coinjs_utxo option:selected" ) . val ( ) ) ;
2015-06-24 00:34:30 +02:00
}
2018-01-01 19:53:23 +01:00
/* fees page code */
2018-01-03 20:27:53 +01:00
$ ( "#fees .slider" ) . on ( 'input' , function ( ) {
$ ( '.' + $ ( this ) . attr ( 'rel' ) + ' .inputno, .' + $ ( this ) . attr ( 'rel' ) + ' .outputno' , $ ( "#fees" ) ) . html ( $ ( this ) . val ( ) ) ;
$ ( '.' + $ ( this ) . attr ( 'rel' ) + ' .estimate' , $ ( "#fees" ) ) . removeClass ( 'hidden' ) ;
2018-01-01 19:53:23 +01:00
} ) ;
2018-01-03 20:27:53 +01:00
$ ( "#fees .txo_p2pkh" ) . on ( 'input' , function ( ) {
var outputno = $ ( '.' + $ ( this ) . attr ( 'rel' ) + ' .outputno' , $ ( "#fees .txoutputs" ) ) . html ( ) ;
$ ( '.' + $ ( this ) . attr ( 'rel' ) + ' .bytes' , $ ( "#fees .txoutputs" ) ) . html ( ( outputno * $ ( "#est_txo_p2pkh" ) . val ( ) ) + ( outputno * 9 ) ) ;
2018-01-01 19:53:23 +01:00
mathFees ( ) ;
} ) ;
2018-01-03 20:27:53 +01:00
$ ( "#fees .txo_p2sh" ) . on ( 'input' , function ( ) {
var outputno = $ ( '.' + $ ( this ) . attr ( 'rel' ) + ' .outputno' , $ ( "#fees .txoutputs" ) ) . html ( ) ;
$ ( '.' + $ ( this ) . attr ( 'rel' ) + ' .bytes' , $ ( "#fees .txoutputs" ) ) . html ( ( outputno * $ ( "#est_txo_p2sh" ) . val ( ) ) + ( outputno * 9 ) ) ;
2018-01-01 19:53:23 +01:00
mathFees ( ) ;
} ) ;
2018-01-03 20:27:53 +01:00
$ ( "#fees .txi_regular" ) . on ( 'input' , function ( ) {
var inputno = $ ( '.' + $ ( this ) . attr ( 'rel' ) + ' .inputno' , $ ( "#fees .txinputs" ) ) . html ( ) ;
$ ( '.' + $ ( this ) . attr ( 'rel' ) + ' .bytes' , $ ( "#fees .txinputs" ) ) . html ( ( inputno * $ ( "#est_txi_regular" ) . val ( ) ) + ( inputno * 41 ) ) ;
2018-01-01 19:53:23 +01:00
mathFees ( ) ;
} ) ;
2018-01-03 20:27:53 +01:00
$ ( "#fees .txi_segwit" ) . on ( 'input' , function ( ) {
var inputno = $ ( '.' + $ ( this ) . attr ( 'rel' ) + ' .inputno' , $ ( "#fees .txinputs" ) ) . html ( ) ;
2018-01-01 19:53:23 +01:00
var bytes = 0 ;
if ( inputno >= 1 ) {
bytes = 2 ;
bytes += ( inputno * 32 ) ;
bytes += ( inputno * $ ( "#est_txi_segwit" ) . val ( ) ) ;
bytes += ( inputno * ( 41 ) )
}
bytes = bytes . toFixed ( 0 ) ;
2018-01-03 20:27:53 +01:00
$ ( '.' + $ ( this ) . attr ( 'rel' ) + ' .bytes' , $ ( "#fees .txinputs" ) ) . html ( bytes ) ;
2018-01-01 19:53:23 +01:00
mathFees ( ) ;
} ) ;
2018-01-03 20:27:53 +01:00
$ ( "#fees .txi_multisig" ) . on ( 'input' , function ( ) {
var inputno = $ ( '.' + $ ( this ) . attr ( 'rel' ) + ' .inputno' , $ ( "#fees .txinputs" ) ) . html ( ) ;
$ ( '.' + $ ( this ) . attr ( 'rel' ) + ' .bytes' , $ ( "#fees .txinputs" ) ) . html ( ( inputno * $ ( "#est_txi_multisig" ) . val ( ) ) + ( inputno * 41 ) ) ;
2018-01-01 19:53:23 +01:00
mathFees ( ) ;
} ) ;
2018-01-03 20:27:53 +01:00
$ ( "#fees .txi_hodl" ) . on ( 'input' , function ( ) {
var inputno = $ ( '.' + $ ( this ) . attr ( 'rel' ) + ' .inputno' , $ ( "#fees .txinputs" ) ) . html ( ) ;
$ ( '.' + $ ( this ) . attr ( 'rel' ) + ' .bytes' , $ ( "#fees .txinputs" ) ) . html ( ( inputno * $ ( "#est_txi_hodl" ) . val ( ) ) + ( inputno * 41 ) ) ;
2018-01-01 19:53:23 +01:00
mathFees ( ) ;
} ) ;
2018-01-03 20:27:53 +01:00
$ ( "#fees .txi_unknown" ) . on ( 'input' , function ( ) {
var inputno = $ ( '.' + $ ( this ) . attr ( 'rel' ) + ' .inputno' , $ ( "#fees .txinputs" ) ) . html ( ) ;
$ ( '.' + $ ( this ) . attr ( 'rel' ) + ' .bytes' , $ ( "#fees .txinputs" ) ) . html ( ( inputno * $ ( "#est_txi_unknown" ) . val ( ) ) + ( inputno * 41 ) ) ;
2018-01-01 19:53:23 +01:00
mathFees ( ) ;
} ) ;
2018-01-03 20:27:53 +01:00
$ ( "#fees .sliderbtn.down" ) . click ( function ( ) {
var val = $ ( ".slider" , $ ( this ) . parent ( ) . parent ( ) ) . val ( ) * 1 ;
if ( val > ( $ ( ".slider" , $ ( this ) . parent ( ) . parent ( ) ) . attr ( 'min' ) * 1 ) ) {
$ ( ".slider" , $ ( this ) . parent ( ) . parent ( ) ) . val ( val - 1 ) ;
$ ( ".slider" , $ ( this ) . parent ( ) . parent ( ) ) . trigger ( 'input' ) ;
}
} ) ;
$ ( "#fees .sliderbtn.up" ) . click ( function ( ) {
var val = $ ( ".slider" , $ ( this ) . parent ( ) . parent ( ) ) . val ( ) * 1 ;
if ( val < ( $ ( ".slider" , $ ( this ) . parent ( ) . parent ( ) ) . attr ( 'max' ) * 1 ) ) {
$ ( ".slider" , $ ( this ) . parent ( ) . parent ( ) ) . val ( val + 1 ) ;
$ ( ".slider" , $ ( this ) . parent ( ) . parent ( ) ) . trigger ( 'input' ) ;
}
} ) ;
2018-01-01 19:53:23 +01:00
$ ( "#advancedFeesCollapse" ) . click ( function ( ) {
if ( $ ( "#advancedFees" ) . hasClass ( 'hidden' ) ) {
$ ( "span" , this ) . removeClass ( 'glyphicon-collapse-down' ) . addClass ( 'glyphicon-collapse-up' ) ;
$ ( "#advancedFees" ) . removeClass ( "hidden" ) ;
} else {
$ ( "span" , this ) . removeClass ( 'glyphicon-collapse-up' ) . addClass ( 'glyphicon-collapse-down' ) ;
$ ( "#advancedFees" ) . addClass ( "hidden" ) ;
}
} ) ;
2018-01-15 19:58:17 +01:00
$ ( "#feesAnalyseBtn" ) . click ( function ( ) {
2018-01-01 19:53:23 +01:00
if ( ! $ ( "#fees .txhex" ) . val ( ) . match ( /^[a-f0-9]+$/ig ) ) {
alert ( 'You must provide a hex encoded transaction' ) ;
return ;
}
var tx = coinjs . transaction ( ) ;
var deserialized = tx . deserialize ( $ ( "#fees .txhex" ) . val ( ) ) ;
$ ( "#fees .txoutputs .outputno, #fees .txinputs .inputno" ) . html ( "0" ) ;
$ ( "#fees .txoutputs .bytes, #fees .txinputs .bytes" ) . html ( "0" ) ;
$ ( "#fees .slider" ) . val ( 0 ) ;
for ( var i = 0 ; i < deserialized . ins . length ; i ++ ) {
var script = deserialized . extractScriptKey ( i ) ;
var size = 41 ;
if ( script . type == 'segwit' ) {
if ( deserialized . witness [ i ] ) {
size += deserialized . ins [ i ] . script . buffer . length / 2 ;
for ( w in deserialized . witness [ i ] ) {
size += ( deserialized . witness [ i ] [ w ] . length / 2 ) / 4 ;
}
} else {
size += $ ( "#est_txi_segwit" ) . val ( ) * 1 ;
}
$ ( "#fees .segwit .inputno" ) . html ( ( $ ( "#fees .segwit .inputno" ) . html ( ) * 1 ) + 1 ) ;
$ ( "#fees .txi_segwit" ) . val ( ( $ ( "#fees .txi_segwit" ) . val ( ) * 1 ) + 1 ) ;
2018-01-15 19:58:17 +01:00
$ ( "#fees .segwit .bytes" ) . html ( ( $ ( "#fees .segwit .bytes" ) . html ( ) * 1 ) + size ) ;
2018-01-01 19:53:23 +01:00
} else if ( script . type == 'multisig' ) {
var s = coinjs . script ( ) ;
var rs = s . decodeRedeemScript ( script . script ) ;
size += 4 + ( ( script . script . length / 2 ) + ( 73 * rs . signaturesRequired ) ) ;
$ ( "#fees .multisig .inputno" ) . html ( ( $ ( "#fees .multisig .inputno" ) . html ( ) * 1 ) + 1 ) ;
$ ( "#fees .txi_multisig" ) . val ( ( $ ( "#fees .txi_multisig" ) . val ( ) * 1 ) + 1 ) ;
2018-01-15 19:58:17 +01:00
$ ( "#fees .multisig .bytes" ) . html ( ( $ ( "#fees .multisig .bytes" ) . html ( ) * 1 ) + size ) ;
2018-01-01 19:53:23 +01:00
} else if ( script . type == 'hodl' ) {
size += 78 ;
$ ( "#fees .hodl .inputno" ) . html ( ( $ ( "#fees .hodl .inputno" ) . html ( ) * 1 ) + 1 ) ;
$ ( "#fees .txi_hodl" ) . val ( ( $ ( "#fees .txi_hodl" ) . val ( ) * 1 ) + 1 ) ;
2018-01-15 19:58:17 +01:00
$ ( "#fees .hodl .bytes" ) . html ( ( $ ( "#fees .hodl .bytes" ) . html ( ) * 1 ) + size ) ;
2018-01-01 19:53:23 +01:00
} else if ( script . type == 'empty' || script . type == 'scriptpubkey' ) {
if ( script . signatures == 1 ) {
size += script . script . length / 2 ;
} else {
size += $ ( "#est_txi_regular" ) . val ( ) * 1 ;
}
$ ( "#fees .regular .inputno" ) . html ( ( $ ( "#fees .regular .inputno" ) . html ( ) * 1 ) + 1 ) ;
$ ( "#fees .txi_regular" ) . val ( ( $ ( "#fees .txi_regular" ) . val ( ) * 1 ) + 1 ) ;
$ ( "#fees .regular .bytes" ) . html ( ( $ ( "#fees .regular .bytes" ) . html ( ) * 1 ) + size ) ;
} else if ( script . type == 'unknown' ) {
size += script . script . length / 2 ;
$ ( "#fees .unknown .inputno" ) . html ( ( $ ( "#fees .unknown .inputno" ) . html ( ) * 1 ) + 1 ) ;
$ ( "#fees .txi_unknown" ) . val ( ( $ ( "#fees .txi_unknown" ) . val ( ) * 1 ) + 1 ) ;
$ ( "#fees .unknown .bytes" ) . html ( ( $ ( "#fees .unknown .bytes" ) . html ( ) * 1 ) + size ) ;
}
}
for ( var i = 0 ; i < deserialized . outs . length ; i ++ ) {
if ( deserialized . outs [ i ] . script . buffer [ 0 ] == 118 ) {
$ ( "#fees .txoutputs .p2pkh .outputno" ) . html ( ( $ ( "#fees .txoutputs .p2pkh .outputno" ) . html ( ) * 1 ) + 1 ) ;
$ ( "#fees .txoutputs .p2pkh .bytes" ) . html ( ( $ ( "#fees .txoutputs .p2pkh .bytes" ) . html ( ) * 1 ) + 34 ) ;
$ ( "#fees .txo_p2pkh" ) . val ( ( $ ( "#fees .txo_p2pkh" ) . val ( ) * 1 ) + 1 ) ;
} else if ( deserialized . outs [ i ] . script . buffer [ 0 ] == 169 ) {
$ ( "#fees .txoutputs .p2sh .outputno" ) . html ( ( $ ( "#fees .txoutputs .p2sh .outputno" ) . html ( ) * 1 ) + 1 ) ;
$ ( "#fees .txoutputs .p2sh .bytes" ) . html ( ( $ ( "#fees .txoutputs .p2sh .bytes" ) . html ( ) * 1 ) + 32 ) ;
$ ( "#fees .txo_p2sh" ) . val ( ( $ ( "#fees .txo_p2sh" ) . val ( ) * 1 ) + 1 ) ;
}
}
2018-01-15 19:58:17 +01:00
feeStats ( ) ;
2018-01-01 19:53:23 +01:00
} ) ;
$ ( "#feeStatsReload" ) . click ( function ( ) {
feeStats ( ) ;
} ) ;
function mathFees ( ) {
var inputsTotal = 0 ;
var inputsBytes = 0 ;
$ . each ( $ ( ".inputno" ) , function ( i , o ) {
inputsTotal += ( $ ( o ) . html ( ) * 1 ) ;
inputsBytes += ( $ ( ".bytes" , $ ( o ) . parent ( ) ) . html ( ) * 1 ) ;
} ) ;
$ ( "#fees .txinputs .txsize" ) . html ( inputsBytes . toFixed ( 0 ) ) ;
$ ( "#fees .txinputs .txtotal" ) . html ( inputsTotal . toFixed ( 0 ) ) ;
var outputsTotal = 0 ;
var outputsBytes = 0 ;
$ . each ( $ ( ".outputno" ) , function ( i , o ) {
outputsTotal += ( $ ( o ) . html ( ) * 1 ) ;
outputsBytes += ( $ ( ".bytes" , $ ( o ) . parent ( ) ) . html ( ) * 1 ) ;
} ) ;
$ ( "#fees .txoutputs .txsize" ) . html ( outputsBytes . toFixed ( 0 ) ) ;
$ ( "#fees .txoutputs .txtotal" ) . html ( outputsTotal . toFixed ( 0 ) ) ;
var totalBytes = 10 + outputsBytes + inputsBytes ;
if ( ( ! isNaN ( $ ( "#fees .feeSatByte:first" ) . html ( ) ) ) && totalBytes > 10 ) {
var recommendedFee = ( ( totalBytes * $ ( ".feeSatByte" ) . html ( ) ) / 100000000 ) . toFixed ( 8 ) ;
$ ( ".recommendedFee" ) . html ( recommendedFee ) ;
$ ( ".feeTxSize" ) . html ( totalBytes ) ;
} else {
$ ( ".recommendedFee" ) . html ( ( 0 ) . toFixed ( 8 ) ) ;
$ ( ".feeTxSize" ) . html ( 0 ) ;
}
} ;
function feeStats ( ) {
$ ( "#feeStatsReload" ) . attr ( 'disabled' , true ) ;
$ . ajax ( {
type : "GET" ,
url : "https://coinb.in/api/?uid=1&key=12345678901234567890123456789012&setmodule=fees&request=stats" ,
dataType : "xml" ,
error : function ( data ) {
} ,
success : function ( data ) {
$ ( "#fees .recommended .blockHeight" ) . html ( '<a href="https://coinb.in/height/' + $ ( data ) . find ( "height" ) . text ( ) + '" target="_blank">' + $ ( data ) . find ( "height" ) . text ( ) + '</a>' ) ;
$ ( "#fees .recommended .blockHash" ) . html ( $ ( data ) . find ( "block" ) . text ( ) ) ;
$ ( "#fees .recommended .blockTime" ) . html ( $ ( data ) . find ( "timestamp" ) . text ( ) ) ;
$ ( "#fees .recommended .blockDateTime" ) . html ( unescape ( $ ( data ) . find ( "datetime" ) . text ( ) ) . replace ( /\+/g , ' ' ) ) ;
$ ( "#fees .recommended .txId" ) . html ( '<a href="https://coinb.in/tx/' + $ ( data ) . find ( "txid" ) . text ( ) + '" target="_blank">' + $ ( data ) . find ( "txid" ) . text ( ) + '</a>' ) ;
$ ( "#fees .recommended .txSize" ) . html ( $ ( data ) . find ( "txsize" ) . text ( ) ) ;
$ ( "#fees .recommended .txFee" ) . html ( $ ( data ) . find ( "txfee" ) . text ( ) ) ;
$ ( "#fees .feeSatByte" ) . html ( $ ( data ) . find ( "satbyte" ) . text ( ) ) ;
mathFees ( ) ;
} ,
complete : function ( data , status ) {
$ ( "#feeStatsReload" ) . attr ( 'disabled' , false ) ;
}
} ) ;
}
2014-12-31 14:33:22 +01:00
/* capture mouse movement to add entropy */
var IE = document . all ? true : false // Boolean, is browser IE?
if ( ! IE ) document . captureEvents ( Event . MOUSEMOVE )
document . onmousemove = getMouseXY ;
function getMouseXY ( e ) {
var tempX = 0 ;
var tempY = 0 ;
if ( IE ) { // If browser is IE
2014-12-31 20:18:51 +01:00
tempX = event . clientX + document . body . scrollLeft ;
tempY = event . clientY + document . body . scrollTop ;
2014-12-31 14:33:22 +01:00
} else {
2014-12-31 20:18:51 +01:00
tempX = e . pageX ;
tempY = e . pageY ;
2014-12-31 14:33:22 +01:00
} ;
2014-12-31 20:18:51 +01:00
2014-12-31 14:33:22 +01:00
if ( tempX < 0 ) { tempX = 0 } ;
if ( tempY < 0 ) { tempY = 0 } ;
2014-12-31 19:06:24 +01:00
var xEnt = Crypto . util . bytesToHex ( [ tempX ] ) . slice ( - 2 ) ;
var yEnt = Crypto . util . bytesToHex ( [ tempY ] ) . slice ( - 2 ) ;
2014-12-31 14:33:22 +01:00
var addEnt = xEnt . concat ( yEnt ) ;
2014-12-31 20:18:51 +01:00
2014-12-31 14:33:22 +01:00
if ( $ ( "#entropybucket" ) . html ( ) . indexOf ( xEnt ) == - 1 && $ ( "#entropybucket" ) . html ( ) . indexOf ( yEnt ) == - 1 ) {
$ ( "#entropybucket" ) . html ( addEnt + $ ( "#entropybucket" ) . html ( ) ) ;
} ;
2014-12-31 20:18:51 +01:00
if ( $ ( "#entropybucket" ) . html ( ) . length > 128 ) {
$ ( "#entropybucket" ) . html ( $ ( "#entropybucket" ) . html ( ) . slice ( 0 , 128 ) )
} ;
2014-12-31 14:33:22 +01:00
return true ;
} ;
2018-01-01 19:53:23 +01:00
2019-05-24 16:44:47 +02:00
} ) ;