From f0ace3eae5fd6a12328757aaa7fec4e6d2f63795 Mon Sep 17 00:00:00 2001 From: Alex Grintsvayg Date: Wed, 16 Feb 2022 13:49:16 -0500 Subject: [PATCH] mostly support lbry it cannot sign timelocked txns because the private key is for the underlying address, so it doesn't know which inputs to sign also broadcasting doesnt work yet because there's no broadcast endpoint on chainquery --- index.html | 8 +- js/coin.js | 93 ++++++++----- js/coinbin.js | 351 ++++++++------------------------------------------ 3 files changed, 116 insertions(+), 336 deletions(-) diff --git a/index.html b/index.html index a5c5fa4..c9f6d77 100644 --- a/index.html +++ b/index.html @@ -1382,13 +1382,7 @@ Network:

Select which network you'd like to use for key pair generation.

diff --git a/js/coin.js b/js/coin.js index 84a1149..f75f7f7 100644 --- a/js/coin.js +++ b/js/coin.js @@ -10,11 +10,11 @@ var coinjs = window.coinjs = function () { }; /* public vars */ - coinjs.pub = 0x00; - coinjs.priv = 0x80; - coinjs.multisig = 0x05; + coinjs.pub = 0x55; + coinjs.priv = 0x1c; + coinjs.multisig = 0x7a; coinjs.hdkey = {'prv':0x0488ade4, 'pub':0x0488b21e}; - coinjs.bech32 = {'charset':'qpzry9x8gf2tvdw0s3jn54khce6mua7l', 'version':0, 'hrp':'bc'}; + coinjs.bech32 = {'charset':'qpzry9x8gf2tvdw0s3jn54khce6mua7l', 'version':0, 'hrp':'lbc'}; coinjs.compressed = false; @@ -22,10 +22,13 @@ coinjs.developer = '33tht1bKDgZVxb39MnZsWa8oxHXHvUYE4G'; //bitcoin /* bit(coinb.in) api vars */ - coinjs.hostname = ((document.location.hostname.split(".")[(document.location.hostname.split(".")).length-1]) == 'onion') ? 'coinbin3ravkwb24f7rmxx6w3snkjw45jhs5lxbh3yfeg3vpt6janwqd.onion' : 'coinb.in'; +// coinjs.hostname = ((document.location.hostname.split(".")[(document.location.hostname.split(".")).length-1]) == 'onion') ? 'coinbin3ravkwb24f7rmxx6w3snkjw45jhs5lxbh3yfeg3vpt6janwqd.onion' : 'coinb.in'; + coinjs.hostname = 'localhost:8000'; coinjs.host = ('https:'==document.location.protocol?'https://':'http://')+coinjs.hostname+'/api/'; coinjs.uid = '1'; coinjs.key = '12345678901234567890123456789012'; + coinjs.chainqueryAPI = "https://chainquery.lbry.com/api/sql" + /* start of address functions */ @@ -177,6 +180,37 @@ return {'address':address, 'redeemScript':redeemScript}; } + coinjs.timelockedAddress = function(pubkey, checklocktimeverify) { + + if(checklocktimeverify < 0) { + throw "Parameter for OP_CHECKLOCKTIMEVERIFY is negative."; + } + + var s = coinjs.script(); + if (checklocktimeverify <= 16 && checklocktimeverify >= 1) { + s.writeOp(0x50 + checklocktimeverify);//OP_1 to OP_16 for minimal encoding + } else { + s.writeBytes(coinjs.numToScriptNumBytes(checklocktimeverify)); + } + s.writeOp(0xb1);//OP_CHECKLOCKTIMEVERIFY + s.writeOp(0x75);//OP_DROP + s.writeOp(0x76);//OP_DUP + s.writeOp(0xa9);//OP_HASH160 + s.writeBytes(Crypto.util.hexToBytes(pubkey)); + s.writeOp(0x88);//88 OP_EQUALVERIFY + s.writeOp(0xac);//OP_CHECKSIG + + var x = ripemd160(Crypto.SHA256(s.buffer, {asBytes: true}), {asBytes: true}); + x.unshift(coinjs.multisig); + var r = x; + r = Crypto.SHA256(Crypto.SHA256(r, {asBytes: true}), {asBytes: true}); + var checksum = r.slice(0,4); + var redeemScript = Crypto.util.bytesToHex(s.buffer); + var address = coinjs.base58encode(x.concat(checksum)); + + return {'address':address, 'redeemScript':redeemScript}; + } + /* create a new segwit address */ coinjs.segwitAddress = function(pubkey){ var keyhash = [0x00,0x14].concat(ripemd160(Crypto.SHA256(Crypto.util.hexToBytes(pubkey), {asBytes: true}), {asBytes: true})); @@ -321,7 +355,8 @@ /* retreive the balance from a given address */ coinjs.addressBalance = function(address, callback){ - coinjs.ajax(coinjs.host+'?uid='+coinjs.uid+'&key='+coinjs.key+'&setmodule=addresses&request=bal&address='+address+'&r='+Math.random(), callback, "GET"); + const query = 'select balance from address where address = "'+address+'";' + coinjs.ajax(coinjs.chainqueryAPI+'?query='+encodeURIComponent(query), (response)=>{callback(JSON.parse(response))}, "GET"); } /* decompress an compressed public key */ @@ -899,6 +934,16 @@ var rs = Crypto.util.bytesToHex(s.buffer); r.redeemscript = rs; r.type = "hodl__"; + + } else if(s.chunks.length == 8 && s.chunks[1] == 177 && s.chunks[2] == 117 && s.chunks[3] == 118 && s.chunks[7] == 172){ + // ^ OP_CHECKLOCKTIMEVERIFY OP_DROP OP_DUP OP_HASH160 OP_EQUALVERIFY OP_CHECKSIG ^ + r = {} + r.pubkey = Crypto.util.bytesToHex(s.chunks[5]); + r.checklocktimeverify = coinjs.bytesToNum(s.chunks[0].slice()); + r.address = coinjs.timelockedAddress(r.pubkey, r.checklocktimeverify).address; + var rs = Crypto.util.bytesToHex(s.buffer); + r.redeemscript = rs; + r.type = "hodl__"; } } catch(e) { // console.log(e); @@ -1064,12 +1109,14 @@ /* list unspent transactions */ r.listUnspent = function(address, callback) { - coinjs.ajax(coinjs.host+'?uid='+coinjs.uid+'&key='+coinjs.key+'&setmodule=addresses&request=unspent&address='+address+'&r='+Math.random(), callback, "GET"); + const query = 'select o.transaction_hash, o.vout, o.value, o.script_pub_key_hex, o.type from address a inner join transaction_address ta on a.id = ta.address_id inner join output o on o.transaction_id = ta.transaction_id and o.is_spent = 0 and o.type not in ("nonstandard","nulldata") and o.address_list = \'["'+address+'"]\' where a.address = "'+address+'";' + coinjs.ajax(coinjs.chainqueryAPI+'?query='+encodeURIComponent(query), (response)=>{callback(JSON.parse(response))}, "GET"); } /* list transaction data */ r.getTransaction = function(txid, callback) { - coinjs.ajax(coinjs.host+'?uid='+coinjs.uid+'&key='+coinjs.key+'&setmodule=bitcoin&request=gettransaction&txid='+txid+'&r='+Math.random(), callback, "GET"); + const query = 'select transaction_hash, vout, value, script_pub_key_hex from output where is_spent = 0 and type not in ("nonstandard","nulldata") and transaction_hash = "'+txid+'"' + coinjs.ajax(coinjs.chainqueryAPI+'?query='+encodeURIComponent(query), (response)=>{callback(JSON.parse(response))}, "GET"); } /* add unspent to transaction */ @@ -1081,23 +1128,12 @@ var total = 0; var x = {}; - if (window.DOMParser) { - parser=new DOMParser(); - xmlDoc=parser.parseFromString(data,"text/xml"); - } else { - xmlDoc=new ActiveXObject("Microsoft.XMLDOM"); - xmlDoc.async=false; - xmlDoc.loadXML(data); - } - - var unspent = xmlDoc.getElementsByTagName("unspent")[0]; - - if(unspent){ - for(i=1;i<=unspent.childElementCount;i++){ - var u = xmlDoc.getElementsByTagName("unspent_"+i)[0] - var txhash = (u.getElementsByTagName("tx_hash")[0].childNodes[0].nodeValue).match(/.{1,2}/g).reverse().join("")+''; - var n = u.getElementsByTagName("tx_output_n")[0].childNodes[0].nodeValue; - var scr = script || u.getElementsByTagName("script")[0].childNodes[0].nodeValue; + if(data){ + for(i=0;i<=data["data"].length;i++){ + var u = data["data"][i] + var txhash = u["transaction_hash"]; + var n = u["vout"]; + var scr = script || n["script_pub_key_hex"]; if(segwit){ /* this is a small hack to include the value with the redeemscript to make the signing procedure smoother. @@ -1106,22 +1142,19 @@ s = coinjs.script(); s.writeBytes(Crypto.util.hexToBytes(script)); s.writeOp(0); - s.writeBytes(coinjs.numToBytes(u.getElementsByTagName("value")[0].childNodes[0].nodeValue*1, 8)); + s.writeBytes(coinjs.numToBytes(u["value"])); scr = Crypto.util.bytesToHex(s.buffer); } var seq = sequence || false; self.addinput(txhash, n, scr, seq); - value += u.getElementsByTagName("value")[0].childNodes[0].nodeValue*1; + value += u["value"]; total++; } } - x.result = xmlDoc.getElementsByTagName("result")[0].childNodes[0].nodeValue; - x.unspent = unspent; x.value = value; x.total = total; - x.response = xmlDoc.getElementsByTagName("response")[0].childNodes[0].nodeValue; return callback(x); }); diff --git a/js/coinbin.js b/js/coinbin.js index 393b63f..4f14184 100644 --- a/js/coinbin.js +++ b/js/coinbin.js @@ -2,9 +2,9 @@ $(document).ready(function() { /* open wallet code */ - var explorer_tx = "https://coinb.in/tx/" - var explorer_addr = "https://coinb.in/addr/" - var explorer_block = "https://coinb.in/block/" + var explorer_tx = "https://explorer.lbry.com/tx/" + var explorer_addr = "https://explorer.lbry.com/address/" + var explorer_block = "https://explorer.lbry.com/blocks/" var wallet_timer = false; @@ -202,7 +202,7 @@ $(document).ready(function() { tx2.broadcast(function(data){ if($(data).find("result").text()=="1"){ - $("#walletSendConfirmStatus").removeClass('hidden').addClass('alert-success').html('txid: '+$(data).find("txid").text()+''); + $("#walletSendConfirmStatus").removeClass('hidden').addClass('alert-success').html('txid: '+$(data).find("txid").text()+''); } else { $("#walletSendConfirmStatus").removeClass('hidden').addClass('alert-danger').html(unescape($(data).find("response").text()).replace(/\+/g,' ')); $("#walletSendFailTransaction").removeClass('hidden'); @@ -302,14 +302,13 @@ $(document).ready(function() { function walletBalance(){ if($("#walletLoader").hasClass("hidden")){ - 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(); + if(data["success"]){ + const v = data["data"][0]["balance"]; + $("#walletBalance").html(v+" LBC").attr('rel',v).fadeOut().fadeIn(); } else { - $("#walletBalance").html("0.00 BTC").attr('rel',v).fadeOut().fadeIn(); + $("#walletBalance").html("0.00 LBC").attr('rel',0).fadeOut().fadeIn(); } $("#walletLoader").addClass("hidden"); @@ -908,34 +907,7 @@ $(document).ready(function() { var host = $(this).attr('rel'); - // api: blockcypher blockchair chain.so - // network name "btc" "bitcoin" "BTC" - // network name "ltc" "litecoin" "LTC" - // network name "doge" "dogecoin" "DOGE" - - if(host=='chain.so_bitcoinmainnet'){ - listUnspentChainso(redeem, "BTC"); - } else if(host=='chain.so_litecoin'){ - listUnspentChainso(redeem, "LTC"); - } else if(host=='chain.so_dogecoin'){ - 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"); - } else { - listUnspentDefault(redeem); - } + listUnspentDefault(redeem); if($("#redeemFromStatus").hasClass("hidden")) { // An ethical dilemma: Should we automatically set nLockTime? @@ -1001,28 +973,30 @@ $(document).ready(function() { $('#recipients .row[rel="'+redeem.addr+'"]').parent().remove(); - $.each(redeem.decodedRs.pubkeys, function(i, o){ - $.each($("#mediatorList option"), function(mi, mo){ + if (redeem.decodedRs.pubkeys) { + $.each(redeem.decodedRs.pubkeys, function(i, o){ + $.each($("#mediatorList option"), function(mi, mo){ - var ms = ($(mo).val()).split(";"); + 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 + 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? + if(o==pubkey){ // matched a mediators pubkey? - var clone = '
'+$("#recipients .addressAddTo").parent().parent().html()+'

'; - $("#recipients").prepend(clone); + var clone = '
'+$("#recipients .addressAddTo").parent().parent().html()+'

'; + $("#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()); + $("#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()); - } + 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(); } @@ -1075,18 +1049,21 @@ $(document).ready(function() { if(redeem.from == 'txid'){ tx.getTransaction(redeem.addr, function(data){ + if (data["error"]) { + $("#redeemFromStatus").removeClass('hidden').html(' Unexpected error, unable to retrieve unspent outputs. '+data["error"]); + $("#redeemFromBtn").html("Load").attr('disabled',false); + return; + } $("#redeemFromAddress").removeClass('hidden').html(' Attempted to rebuild transaction id '+redeem.addr+''); - $.each($(data).find("inputs").children(), function(i,o){ - var tx = $(o).find("txid").text(); - var n = $(o).find("output_no").text(); - var amount = (($(o).find("value").text()*1)).toFixed(8); - - var scr = $(o).find("script").text(); - - addOutput(tx, n, scr, amount); + $.each(data["data"], function(i,o){ + var tx = o["transaction_hash"]; + var n = o["vout"]; + var script = (redeem.redeemscript==true) ? redeem.decodedRs : o["script_pub_key_hex"]; + var amount = o["value"]; + addOutput(tx, n, script, amount); }); $("#recipients .addressRemoveTo").click(); @@ -1109,14 +1086,20 @@ $(document).ready(function() { // unspent from address tx.listUnspent(redeem.addr, function(data){ + if (data["error"]) { + $("#redeemFromStatus").removeClass('hidden').html(' Unexpected error, unable to retrieve unspent outputs. '+data["error"]); + $("#redeemFromBtn").html("Load").attr('disabled',false); + return; + } + if(redeem.addr) { $("#redeemFromAddress").removeClass('hidden').html(' Retrieved unspent inputs from address '+redeem.addr+''); - $.each($(data).find("unspent").children(), function(i,o){ - var tx = $(o).find("tx_hash").text(); - var n = $(o).find("tx_output_n").text(); - var script = (redeem.redeemscript==true) ? redeem.decodedRs : $(o).find("script").text(); - var amount = (($(o).find("value").text()*1)/100000000).toFixed(8); + $.each(data["data"], function(i,o){ + var tx = o["transaction_hash"]; + var n = o["vout"]; + var script = (redeem.redeemscript==true) ? redeem.decodedRs : o["script_pub_key_hex"]; + var amount = o["value"]; addOutput(tx, n, script, amount); }); @@ -1130,107 +1113,6 @@ $(document).ready(function() { } - /* retrieve unspent data from blockcypher */ - function listUnspentBlockcypher(redeem,network){ - $.ajax ({ - type: "GET", - url: "https://api.blockcypher.com/v1/"+network+"/main/addrs/"+redeem.addr+"?includeScript=true&unspentOnly=true", - dataType: "json", - error: function(data) { - $("#redeemFromStatus").removeClass('hidden').html(' Unexpected error, unable to retrieve unspent outputs!'); - }, - success: function(data) { - if (data.address) { // address field will always be present, txrefs is only present if there are UTXOs - $("#redeemFromAddress").removeClass('hidden').html(' Retrieved unspent inputs from address '+redeem.addr+''); - for(var i in data.txrefs){ - var o = data.txrefs[i]; - var tx = ((""+o.tx_hash).match(/.{1,2}/g).reverse()).join("")+''; - if(tx.match(/^[a-f0-9]+$/)){ - var n = o.tx_output_n; - var script = (redeem.redeemscript==true) ? redeem.decodedRs : o.script; - var amount = ((o.value.toString()*1)/100000000).toFixed(8); - addOutput(tx, n, script, amount); - } - } - } else { - $("#redeemFromStatus").removeClass('hidden').html(' Unexpected error, unable to retrieve unspent outputs.'); - } - }, - complete: function(data, status) { - $("#redeemFromBtn").html("Load").attr('disabled',false); - totalInputAmount(); - } - }); - } - - /* retrieve unspent data from blockchair */ - function listUnspentBlockchair(redeem,network){ - $.ajax ({ - type: "GET", - url: "https://api.blockchair.com/"+network+"/dashboards/address/"+redeem.addr, - dataType: "json", - error: function(data) { - $("#redeemFromStatus").removeClass('hidden').html(' Unexpected error, unable to retrieve unspent outputs!'); - }, - success: function(data) { - if((data.context && data.data) && data.context.code =='200'){ - $("#redeemFromAddress").removeClass('hidden').html(' Retrieved unspent inputs from address '+redeem.addr+''); - 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(' 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, - dataType: "json", - error: function(data) { - $("#redeemFromStatus").removeClass('hidden').html(' Unexpected error, unable to retrieve unspent outputs!'); - }, - success: function(data) { - if((data.status && data.data) && data.status=='success'){ - $("#redeemFromAddress").removeClass('hidden').html(' Retrieved unspent inputs from address '+redeem.addr+''); - for(var i in data.data.txs){ - var o = data.data.txs[i]; - var tx = ((""+o.txid).match(/.{1,2}/g).reverse()).join("")+''; - if(tx.match(/^[a-f0-9]+$/)){ - var n = o.output_no; - var script = (redeem.redeemscript==true) ? redeem.decodedRs : o.script_hex; - var amount = o.value; - addOutput(tx, n, script, amount); - } - } - } else { - $("#redeemFromStatus").removeClass('hidden').html(' Unexpected error, unable to retrieve unspent outputs.'); - } - }, - complete: function(data, status) { - $("#redeemFromBtn").html("Load").attr('disabled',false); - totalInputAmount(); - } - }); - } - /* math to calculate the inputs and outputs */ @@ -1303,7 +1185,7 @@ $(document).ready(function() { error: function(data) { $("#rawTransactionStatus").addClass('alert-danger').removeClass('alert-success').removeClass("hidden").html(" There was an error submitting your request, please try again").prepend(''); }, - success: function(data) { + success: function(data) { $("#rawTransactionStatus").html(unescape($(data).find("response").text()).replace(/\+/g,' ')).removeClass('hidden'); if($(data).find("result").text()==1){ $("#rawTransactionStatus").addClass('alert-success').removeClass('alert-danger').removeClass("hidden").html(' TXID: ' + $(data).find("txid").text() + '
View on Blockchain'); @@ -1318,89 +1200,6 @@ $(document).ready(function() { }); } - // broadcast transaction via chain.so (mainnet) - function rawSubmitChainso(thisbtn, network){ - $(thisbtn).val('Please wait, loading...').attr('disabled',true); - $.ajax ({ - type: "POST", - url: "https://chain.so/api/v2/send_tx/"+network+"/", - 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(''); - }, - success: function(data) { - if(data.status && data.data.txid){ - $("#rawTransactionStatus").addClass('alert-success').removeClass('alert-danger').removeClass("hidden").html(' TXID: ' + data.data.txid + '
View on Blockchain Explorer'); - } else { - $("#rawTransactionStatus").addClass('alert-danger').removeClass('alert-success').removeClass("hidden").html(' Unexpected error, please try again').prepend(''); - } - }, - complete: function(data, status) { - $("#rawTransactionStatus").fadeOut().fadeIn(); - $(thisbtn).val('Submit').attr('disabled',false); - } - }); - } - - // broadcast transaction via blockcypher.com (mainnet) - function rawSubmitblockcypher(thisbtn, network){ - $(thisbtn).val('Please wait, loading...').attr('disabled',true); - $.ajax ({ - type: "POST", - url: "https://api.blockcypher.com/v1/"+network+"/main/txs/push", - data: JSON.stringify({"tx":$("#rawTransaction").val()}), - error: function(data) { - var r = 'Failed to broadcast: error code=' + data.status.toString() + ' ' + data.statusText; - $("#rawTransactionStatus").addClass('alert-danger').removeClass('alert-success').removeClass("hidden").html(r).prepend(''); - }, - success: function(data) { - if((data.tx) && data.tx.hash){ - $("#rawTransactionStatus").addClass('alert-success').removeClass('alert-danger').removeClass("hidden") - .html(' TXID: ' + data.tx.hash + '
View on Blockchain Explorer'); - } else { - $("#rawTransactionStatus").addClass('alert-danger').removeClass('alert-success').removeClass("hidden").html(' Unexpected error, please try again').prepend(''); - } - }, - complete: function(data, status) { - $("#rawTransactionStatus").fadeOut().fadeIn(); - $(thisbtn).val('Submit').attr('disabled',false); - } - }); - } - - // broadcast transaction via blockchair - function rawSubmitblockchair(thisbtn, network){ - $(thisbtn).val('Please wait, loading...').attr('disabled',true); - $.ajax ({ - type: "POST", - url: "https://api.blockchair.com/"+network+"/push/transaction", - data: {"data":$("#rawTransaction").val()}, - dataType: "json", - error: function(data) { - var r = 'Failed to broadcast: error code=' + data.status.toString() + ' ' + data.statusText; - $("#rawTransactionStatus").addClass('alert-danger').removeClass('alert-success').removeClass("hidden").html(r).prepend(''); - // console.error(JSON.stringify(data, null, 4)); - }, - success: function(data) { - // console.info(JSON.stringify(data, null, 4)); - if((data.context && data.data) && data.context.code=='200'){ - $("#rawTransactionStatus").addClass('alert-success').removeClass('alert-danger').removeClass("hidden") - .html(' TXID: ' + data.data.transaction_hash + '
View on Blockchain Explorer'); - } else { - $("#rawTransactionStatus").addClass('alert-danger').removeClass('alert-success').removeClass("hidden").html(' Unexpected error, please try again').prepend(''); - } - }, - complete: function(data, status) { - $("#rawTransactionStatus").fadeOut().fadeIn(); - $(thisbtn).val('Submit').attr('disabled',false); - } - }); - } @@ -1915,55 +1714,9 @@ $(document).ready(function() { }); function configureBroadcast(){ - var host = $("#coinjs_broadcast option:selected").val(); - - // api: blockcypher blockchair chain.so - // network name "btc" "bitcoin" "BTC" - // network name "ltc" "litecoin" "LTC" - // network name "doge" "dogecoin" "DOGE" - - $("#rawSubmitBtn").unbind(""); - if(host=="chain.so_bitcoinmainnet"){ - $("#rawSubmitBtn").click(function(){ - rawSubmitChainso(this, "BTC"); - }); - } else if(host=="chain.so_litecoin"){ - $("#rawSubmitBtn").click(function(){ - rawSubmitChainso(this, "LTC"); - }); - } else if(host=="chain.so_dogecoin"){ - $("#rawSubmitBtn").click(function(){ - rawSubmitChainso(this, "DOGE"); - }); - } else if(host=="blockcypher_bitcoinmainnet"){ - $("#rawSubmitBtn").click(function(){ - 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"); - }); - } else { - $("#rawSubmitBtn").click(function(){ - rawSubmitDefault(this); // revert to default - }); - } + $("#rawSubmitBtn").click(function(){ + rawSubmitDefault(this); // revert to default + }); } function configureGetUnspentTx(){