';
$("#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();
}
}
/* 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);
if(((script.match(/^00/) && script.length==44)) || (script.length==40 && script.match(/^[a-f0-9]+$/gi))){
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);
}
$("#inputs .txIdScript:last").val(script);
}
}
/* default function to retreive unspent outputs*/
function listUnspentDefault(redeem){
var tx = coinjs.transaction();
tx.listUnspent(redeem.addr, function(data){
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);
addOutput(tx, n, script, amount);
});
}
$("#redeemFromBtn").html("Load").attr('disabled',false);
totalInputAmount();
mediatorPayment(redeem);
});
}
/* 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 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(' Unexpected error, unable to retrieve unspent outputs!');
},
success: function(data) {
if($(data).find("result").text()==1){
$("#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.script_hex;
var amount = (($(o).find("value").text()*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 */
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');
}
$(".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");
} else {
$(".glyphcollapse",$(this).parent()).removeClass('glyphicon-collapse-up').addClass('glyphicon-collapse-down');
$(".optionsAdvanced",$(this).parent()).addClass("hidden");
}
});
/* broadcast a transaction */
$("#rawSubmitBtn").click(function(){
rawSubmitDefault(this);
});
// broadcast transaction via coinbin (default)
function rawSubmitDefault(btn){
var thisbtn = btn;
$(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('');
},
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');
} else {
$("#rawTransactionStatus").addClass('alert-danger').removeClass('alert-success').prepend(' ');
}
},
complete: function(data, status) {
$("#rawTransactionStatus").fadeOut().fadeIn();
$(thisbtn).val('Submit').attr('disabled',false);
}
});
}
// broadcast transaction via cryptoid
function rawSubmitcryptoid_Carboncoin(thisbtn) {
$(thisbtn).val('Please wait, loading...').attr('disabled',true);
$.ajax ({
type: "POST",
url: coinjs.host+'?uid='+coinjs.uid+'&key='+coinjs.key+'&setmodule=carboncoin&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('');
},
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 Explorer');
} else {
$("#rawTransactionStatus").addClass('alert-danger').removeClass('alert-success').prepend(' ');
}
},
complete: function(data, status) {
$("#rawTransactionStatus").fadeOut().fadeIn();
$(thisbtn).val('Submit').attr('disabled',false);
}
});
}
// 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);
}
});
}
/* verify script code */
$("#verifyBtn").click(function(){
$(".verifyData").addClass("hidden");
$("#verifyStatus").hide();
if(!decodeRedeemScript()){
if(!decodeTransactionScript()){
if(!decodePrivKey()){
if(!decodePubKey()){
if(!decodeHDaddress()){
$("#verifyStatus").removeClass('hidden').fadeOut().fadeIn();
}
}
}
}
}
});
function decodeRedeemScript(){
var script = coinjs.script();
var decode = script.decodeRedeemScript($("#verifyScript").val());
if(decode){
$("#verifyRsDataMultisig").addClass('hidden');
$("#verifyRsDataHodl").addClass('hidden');
$("#verifyRsDataSegWit").addClass('hidden');
$("#verifyRsData").addClass("hidden");
if(decode.type == "multisig__") {
$("#verifyRsDataMultisig .multisigAddress").val(decode['address']);
$("#verifyRsDataMultisig .signaturesRequired").html(decode['signaturesRequired']);
$("#verifyRsDataMultisig table tbody").html("");
for(var i=0;i
').appendTo("#verifyRsDataMultisig table tbody");
}
$("#verifyRsData").removeClass("hidden");
$("#verifyRsDataMultisig").removeClass('hidden');
$(".verifyLink").attr('href','?verify='+$("#verifyScript").val());
return true;
} else if(decode.type == "segwit__"){
$("#verifyRsData").removeClass("hidden");
$("#verifyRsDataSegWit .segWitAddress").val(decode['address']);
$("#verifyRsDataSegWit").removeClass('hidden');
return true;
} else if(decode.type == "hodl__") {
var d = $("#verifyRsDataHodl .date").data("DateTimePicker");
$("#verifyRsDataHodl .address").val(decode['address']);
$("#verifyRsDataHodl .pubkey").val(coinjs.pubkey2address(decode['pubkey']));
$("#verifyRsDataHodl .date").val(decode['checklocktimeverify'] >= 500000000? moment.unix(decode['checklocktimeverify']).format("MM/DD/YYYY HH:mm") : decode['checklocktimeverify']);
$("#verifyRsData").removeClass("hidden");
$("#verifyRsDataHodl").removeClass('hidden');
$(".verifyLink").attr('href','?verify='+$("#verifyScript").val());
return true;
}
}
return false;
}
function decodeTransactionScript(){
var tx = coinjs.transaction();
try {
var decode = tx.deserialize($("#verifyScript").val());
$("#verifyTransactionData .transactionVersion").html(decode['version']);
$("#verifyTransactionData .transactionSize").html(decode.size()+' bytes');
$("#verifyTransactionData .transactionLockTime").html(decode['lock_time']);
$("#verifyTransactionData .transactionRBF").hide();
$("#verifyTransactionData .transactionSegWit").hide();
if (decode.witness.length>=1) {
$("#verifyTransactionData .transactionSegWit").show();
}
$("#verifyTransactionData").removeClass("hidden");
$("#verifyTransactionData tbody").html("");
var h = '';
$.each(decode.ins, function(i,o){
var s = decode.extractScriptKey(i);
h += '
';
h += '
';
h += '
'+o.outpoint.index+'
';
h += '
';
h += '
';
if(s['type']=='multisig' && s['signatures']>=1){
h += ' '+s['signatures'];
}
h += '
';
h += '
';
if(s['type']=='multisig'){
var script = coinjs.script();
var rs = script.decodeRedeemScript(s.script);
h += rs['signaturesRequired']+' of '+rs['pubkeys'].length;
} else {
h += '';
}
h += '
';
h += '
';
//debug
if(parseInt(o.sequence)<(0xFFFFFFFF-1)){
$("#verifyTransactionData .transactionRBF").show();
}
});
$(h).appendTo("#verifyTransactionData .ins tbody");
h = '';
$.each(decode.outs, function(i,o){
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 += '