Verify transactions and other scripts
@@ -864,7 +1088,20 @@
WIF key
Public key
The above public key has been encoded to its address
-
Address :
+
Legacy Address :
+
+
+
+
+
+
+
+
Segwit Redeem Script :
+
+
+
@@ -964,8 +1201,8 @@
Keys
-
Sign Transaction once a transaction has been verified
-
Once you have verified a transaction you can sign and then broadcast it into the network.
+
Sign Transaction once a transaction has been verified
+
Once you have verified a transaction you can sign and then broadcast it into the network.
@@ -988,6 +1225,13 @@
Sign Transaction once a transaction has been verified
+
+
+
Advanced Options
@@ -1055,7 +1299,7 @@
Development Javascript framework, API and more
About open source bitcoin wallet
Version 1.3
Compatible with bitcoin-qt
-
Github https://github.com/OutCast3k/coinbin/
+
Github https://github.com/poolgold/coinbin/
TOR 4zpinp6gdkjfplhk.onion
What is Bitcoin?
Bitcoin is a type of digital currency in which encryption techniques are used to regulate the generation of units of currency and verify the transfer of funds, operating independently of a central bank. See weusecoins.com for more information.
@@ -1064,11 +1308,11 @@
Information
Coinb.in is a free and open source project released under the MIT license, originally by OutCast3k in 2013. Discussion of the project can be found at bitcointalk.org during its early testing stages when its primary focus was to develop a proof of concept multisig solution in javascript.
Coinb.in is run and funded by the generosity of others in terms of development and hosting.
Privacy
-
Coinb.in beleives strongly in privacy, not only do we support the use of TOR, the site does not collect and store IP or transaction data via our servers nor do we store your bitcoins private key. We do route traffic via cloudflare using an SSL certificate.
+
Coinb.in believes strongly in privacy, not only do we support the use of TOR, the site does not collect and store IP or transaction data via our servers nor do we store your bitcoins private key. We do route traffic via cloudflare using an SSL certificate.
Support
-
We recommend that you first check our service status page, if the problem persists you can contact us by emailing support{at}coinb.in.
+
We recommend that you first check our service status page and then blog page which has multiple guides . However if the problem persists you can contact us by emailing support{at}coinb.in.
Donate
-
Please donate to 1CWHWkTWaq1K5hevimJia3cyinQsrgXUvg if you found this project useful or want to see more features!
+
Please donate to 3K1oFZMks41C7qDYBsr72SYjapLqDuSYuN if you found this project useful or want to see more features!
@@ -1080,7 +1324,9 @@
Settings making coinb.in even better!
Network :
Select which network you'd like to use for key pair generation.
+
Bitcoin (mainnet)
+ Bitcoin Gold (mainnet)
Dogecoin (mainnet)
Carboncoin (mainnet)
ShadowCash (mainnet)
@@ -1114,15 +1360,20 @@ Settings making coinb.in even better!
-
+
HD Pub :
-
@@ -1131,7 +1382,6 @@
Settings making coinb.in even better!
-
Broadcast :
@@ -1142,10 +1392,10 @@
Settings making coinb.in even better!
Blockcypher.com (Bitcoin mainnet)
Chain.so (Dogecoin)
Cryptoid.info (Carboncoin)
+ explorer.bitcoingold.org (Bitcoin Gold)
-
@@ -1157,6 +1407,7 @@
Settings making coinb.in even better!
Chain.so (Litecoin)
Chain.so (Dogecoin)
Cryptoid.info (Carboncoin)
+ explorer.bitcoingold.org (Bitcoin Gold)
@@ -1171,7 +1422,7 @@ Settings making coinb.in even better!
-
This page uses javascript to generate your addresses and sign your transactions within your browser, this means we never receive your private keys, this can be independently verified by reviewing the source code on github . You can even download this page and host it yourself or run it offline!
+
This page uses javascript to generate your addresses and sign your transactions within your browser, this means we never receive your private keys, this can be independently verified by reviewing the source code on github . You can even download this page and host it yourself or run it offline!
@@ -1179,8 +1430,11 @@
Settings making coinb.in even better!
diff --git a/js/coin.js b/js/coin.js
index 84362e51..b0c4b61e 100644
--- a/js/coin.js
+++ b/js/coin.js
@@ -10,15 +10,16 @@
var coinjs = window.coinjs = function () { };
/* public vars */
- coinjs.pub = 0x00;
+ coinjs.pub = 0x26;
coinjs.priv = 0x80;
- coinjs.multisig = 0x05;
+ coinjs.multisig = 0x17;
coinjs.hdkey = {'prv':0x0488ade4, 'pub':0x0488b21e};
-
+ coinjs.useForkId = true;
+ coinjs.forkId = 79;
coinjs.compressed = false;
/* other vars */
- coinjs.developer = '1CWHWkTWaq1K5hevimJia3cyinQsrgXUvg'; // bitcoin
+ coinjs.developer = 'GHri78iH9CfBbm79rfdXtCqjsiFhbKMwZd'; // bitcoin gold
/* bit(coinb.in) api vars */
coinjs.host = ('https:'==document.location.protocol?'https://':'http://')+'coinb.in/api/';
@@ -803,11 +804,13 @@
r.block = null;
/* add an input to a transaction */
- r.addinput = function(txid, index, script, sequence){
+ r.addinput = function(txid, index, script, sequence, value){
var o = {};
o.outpoint = {'hash':txid, 'index':index};
o.script = coinjs.script(script||[]);
o.sequence = sequence || ((r.lock_time==0) ? 4294967295 : 0);
+ console.assert(value, 'Missing input value');
+ o.value = value;
return this.ins.push(o);
}
@@ -882,7 +885,7 @@
}
/* add unspent to transaction */
- r.addUnspent = function(address, callback, script, segwit){
+ r.addUnspent = function(address, callback, script, segwit, sequence){
var self = this;
this.listUnspent(address, function(data){
var s = coinjs.script();
@@ -908,18 +911,9 @@
var n = u.getElementsByTagName("tx_output_n")[0].childNodes[0].nodeValue;
var scr = script || u.getElementsByTagName("script")[0].childNodes[0].nodeValue;
- if(segwit){
- /* this is a small hack to include the value with the redeemscript to make the signing procedure smoother.
- It is not standard and removed during the signing procedure. */
-
- 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));
- scr = Crypto.util.bytesToHex(s.buffer);
- }
-
- self.addinput(txhash, n, scr);
+ var seq = sequence || false;
+ var value = u.getElementsByTagName("value")[0].childNodes[0].nodeValue*1;
+ self.addinput(txhash, n, scr, seq, value);
value += u.getElementsByTagName("value")[0].childNodes[0].nodeValue*1;
total++;
}
@@ -949,7 +943,14 @@
/* generate the transaction hash to sign from a transaction input */
r.transactionHash = function(index, sigHashType) {
-
+ if (coinjs.useForkId) {
+ var witnessSigHash = this.transactionHashSegWitV0(index, sigHashType);
+ if (witnessSigHash['result'] == 1) {
+ return witnessSigHash['hash'];
+ } else {
+ return false;
+ }
+ }
var clone = coinjs.clone(this);
var shType = sigHashType || 1;
@@ -1029,22 +1030,23 @@
/* generate a segwit transaction hash to sign from a transaction input */
r.transactionHashSegWitV0 = function(index, sigHashType){
- /*
- Notice: coinb.in by default, deals with segwit transactions in a non-standard way.
- Segwit transactions require that input values are included in the transaction hash.
- To save wasting resources and potentially slowing down this service, we include the amount with the
- redeem script to generate the transaction hash and remove it after its signed.
- */
-
// start redeem script check
var extract = this.extractScriptKey(index);
- if(extract['type'] != 'segwit'){
- return {'result':0, 'fail':'redeemscript', 'response':'redeemscript missing or not valid for segwit'};
+ if(!coinjs.useForkId && extract['type'] != 'segwit'){
+ return {'result':0, 'fail':'txtype', 'response':'sighash-witnessv0 is only for sigwit when forkid is not enabled'};
}
var scriptcode = Crypto.util.hexToBytes(extract['script']);
- if(scriptcode[0] != 0){
- return {'result':0, 'fail':'scriptcode', 'response':'redeemscript is not valid'};
+ if(extract['type'] == 'sigwit') {
+ if(scriptcode[0] != 0){
+ return {'result':0, 'fail':'scriptcode', 'response':'redeemscript is not valid'};
+ }
+ scriptcode = scriptcode.slice(1);
+ scriptcode.unshift(25, 118, 169);
+ scriptcode.push(136, 172);
+ } else {
+ var sz = coinjs.numToVarInt(scriptcode.length);
+ scriptcode = sz.concat(scriptcode);
}
if(extract['value'] == -1){
@@ -1053,10 +1055,6 @@
// end of redeem script check
- scriptcode = scriptcode.slice(1);
- scriptcode.unshift(25, 118, 169);
- scriptcode.push(136, 172);
-
var value = coinjs.numToBytes(extract['value'], 8);
// start
@@ -1103,6 +1101,10 @@
}
var locktime = coinjs.numToBytes(this.lock_time, 4);
+ if (coinjs.useForkId) {
+ sigHashType |= 0x40;
+ sigHashType |= (coinjs.forkId << 8);
+ }
var sighash = coinjs.numToBytes(sigHashType, 4);
var buffer = [];
@@ -1124,39 +1126,40 @@
/* extract the scriptSig, used in the transactionHash() function */
r.extractScriptKey = function(index) {
if(this.ins[index]){
+ var value = -1;
+ if ('value' in this.ins[index]) {
+ value = this.ins[index].value;
+ }
if((this.ins[index].script.chunks.length==5) && this.ins[index].script.chunks[4]==172 && coinjs.isArray(this.ins[index].script.chunks[2])){ //OP_CHECKSIG
// regular scriptPubkey (not signed)
- return {'type':'scriptpubkey', 'signed':'false', 'signatures':0, 'script': Crypto.util.bytesToHex(this.ins[index].script.buffer)};
+ return {'type':'scriptpubkey', 'signed':'false', 'signatures':0, 'script': Crypto.util.bytesToHex(this.ins[index].script.buffer), 'value': value};
} else if((this.ins[index].script.chunks.length==2) && this.ins[index].script.chunks[0][0]==48 && this.ins[index].script.chunks[1].length == 5 && this.ins[index].script.chunks[1][1]==177){//OP_CHECKLOCKTIMEVERIFY
// hodl script (signed)
- return {'type':'hodl', 'signed':'true', 'signatures':1, 'script': Crypto.util.bytesToHex(this.ins[index].script.buffer)};
+ return {'type':'hodl', 'signed':'true', 'signatures':1, 'script': Crypto.util.bytesToHex(this.ins[index].script.buffer), 'value': value};
} else if((this.ins[index].script.chunks.length==2) && this.ins[index].script.chunks[0][0]==48){
// regular scriptPubkey (probably signed)
- return {'type':'scriptpubkey', 'signed':'true', 'signatures':1, 'script': Crypto.util.bytesToHex(this.ins[index].script.buffer)};
+ return {'type':'scriptpubkey', 'signed':'true', 'signatures':1, 'script': Crypto.util.bytesToHex(this.ins[index].script.buffer), 'value': value};
} else if(this.ins[index].script.chunks.length == 5 && this.ins[index].script.chunks[1] == 177){//OP_CHECKLOCKTIMEVERIFY
// hodl script (not signed)
- return {'type':'hodl', 'signed':'false', 'signatures': 0, 'script': Crypto.util.bytesToHex(this.ins[index].script.buffer)};
- } else if((this.ins[index].script.chunks.length <= 3 && this.ins[index].script.chunks.length > 0) && this.ins[index].script.chunks[0].length == 22 && this.ins[index].script.chunks[0][0] == 0){
+ return {'type':'hodl', 'signed':'false', 'signatures': 0, 'script': Crypto.util.bytesToHex(this.ins[index].script.buffer), 'value': value};
+ } else if((this.ins[index].script.chunks.length <= 3 && this.ins[index].script.chunks.length > 0) && this.ins[index].script.buffer.length == 22 && this.ins[index].script.chunks[0] == 0){
// segwit script
var signed = ((this.witness[index]) && this.witness[index].length==2) ? 'true' : 'false';
var sigs = (signed == 'true') ? 1 : 0;
- var value = -1; // no value found
- if((this.ins[index].script.chunks[2]) && this.ins[index].script.chunks[2].length==8){
- value = coinjs.bytesToNum(this.ins[index].script.chunks[2]); // value found encoded in transaction (THIS IS NON STANDARD)
- }
- return {'type':'segwit', 'signed':signed, 'signatures': sigs, 'script': Crypto.util.bytesToHex(this.ins[index].script.chunks[0]), 'value': value};
+ return {'type':'segwit', 'signed':signed, 'signatures': sigs, 'script': Crypto.util.bytesToHex(this.ins[index].script.buffer), 'value': value}; // **** correct?
} else if (this.ins[index].script.chunks[0]==0 && this.ins[index].script.chunks[this.ins[index].script.chunks.length-1][this.ins[index].script.chunks[this.ins[index].script.chunks.length-1].length-1]==174) { // OP_CHECKMULTISIG
// multisig script, with signature(s) included
- return {'type':'multisig', 'signed':'true', 'signatures':this.ins[index].script.chunks.length-2, 'script': Crypto.util.bytesToHex(this.ins[index].script.chunks[this.ins[index].script.chunks.length-1])};
+ return {'type':'multisig', 'signed':'true', 'signatures':this.ins[index].script.chunks.length-2, 'script': Crypto.util.bytesToHex(this.ins[index].script.chunks[this.ins[index].script.chunks.length-1]),
+ 'value': value};
} else if (this.ins[index].script.chunks[0]>=80 && this.ins[index].script.chunks[this.ins[index].script.chunks.length-1]==174) { // OP_CHECKMULTISIG
// multisig script, without signature!
- return {'type':'multisig', 'signed':'false', 'signatures':0, 'script': Crypto.util.bytesToHex(this.ins[index].script.buffer)};
+ return {'type':'multisig', 'signed':'false', 'signatures':0, 'script': Crypto.util.bytesToHex(this.ins[index].script.buffer), 'value': value};
} else if (this.ins[index].script.chunks.length==0) {
// empty
- return {'type':'empty', 'signed':'false', 'signatures':0, 'script': ''};
+ return {'type':'empty', 'signed':'false', 'signatures':0, 'script': '', 'value': value};
} else {
// something else
- return {'type':'unknown', 'signed':'false', 'signatures':0, 'script':Crypto.util.bytesToHex(this.ins[index].script.buffer)};
+ return {'type':'unknown', 'signed':'false', 'signatures':0, 'script':Crypto.util.bytesToHex(this.ins[index].script.buffer), 'value': value};
}
} else {
return false;
@@ -1186,6 +1189,9 @@
}
var shType = sigHashType || 1;
+ if (coinjs.useForkId) {
+ shType |= 0x40;
+ }
var hash = txhash || Crypto.util.hexToBytes(this.transactionHash(index, shType));
if(hash){
@@ -1367,16 +1373,11 @@
var wif2 = coinjs.wif2pubkey(wif);
var segwit = coinjs.segwitAddress(wif2['pubkey']);
- if(segwit['redeemscript'] == Crypto.util.bytesToHex(this.ins[index].script.chunks[0])){
+ if(segwit['redeemscript'] == Crypto.util.bytesToHex(this.ins[index].script.buffer)){
var txhash = this.transactionHashSegWitV0(index, shType);
if(txhash.result == 1){
var segwitHash = Crypto.util.hexToBytes(txhash.hash);
var signature = this.transactionSig(index, wif, shType, segwitHash);
-
- // remove any non standard data we store, i.e. input value
- var script = coinjs.script();
- script.writeBytes(this.ins[index].script.chunks[0]);
- this.ins[index].script = script;
if(!coinjs.isArray(this.witness)){
this.witness = [];
@@ -1395,7 +1396,7 @@
for(var y = 0; y < this.witness.length; y++){
if(!witness_used.includes(y)){
var sw = coinjs.segwitAddress(this.witness[y][1]);
- if(sw['redeemscript'] == Crypto.util.bytesToHex(this.ins[i].script.chunks[0])){
+ if(sw['redeemscript'] == Crypto.util.bytesToHex(this.ins[i].script.buffer)){
witness_order.push(this.witness[y]);
witness_used.push(y);
break;
@@ -1563,6 +1564,42 @@
return obj;
}
+ r.coreInputObject = function() {
+ var inputs = [];
+ for (var i = 0; i < this.ins.length; i++) {
+ var cvin = this.ins[i];
+ var vin = {};
+ vin.txid = cvin.outpoint.hash;
+ vin.vout = parseInt(cvin.outpoint.index);
+ // vin.scriptPubKey = '';
+ // vin.redeemScript = '';
+ vin.script = Crypto.util.bytesToHex(cvin.script.buffer);
+ vin.amount = cvin.value;
+ inputs.push(vin);
+ }
+ return inputs;
+ }
+
+ r.completeInputValues = function(txinputs){
+ function vinOutpoint(vin) { return vin.txid + ':' + vin.vout; }
+ function cbvinOutpoint(cvin) { return cvin.outpoint.hash + ':' + cvin.outpoint.index; }
+ var inputMap = {};
+ for (var i = 0; i < txinputs.length; i++) {
+ var vin = txinputs[i];
+ inputMap[vinOutpoint(vin)] = vin;
+ }
+ for (var i = 0; i < this.ins.length; i++) {
+ var cvin = this.ins[i];
+ var outpoint = cbvinOutpoint(cvin);
+ if (outpoint in inputMap) {
+ var vin = inputMap[outpoint];
+ cvin.value = vin.amount;
+ cvin.script = coinjs.script(Crypto.util.hexToBytes(vin.script));
+ }
+ }
+ console.log(this.ins);
+ };
+
r.size = function(){
return ((this.serialize()).length/2).toFixed(0);
}
diff --git a/js/coinbin.js b/js/coinbin.js
index c07170ad..27339291 100644
--- a/js/coinbin.js
+++ b/js/coinbin.js
@@ -35,9 +35,13 @@ $(document).ready(function() {
var pubkey = keys.pubkey;
var privkeyaes = CryptoJS.AES.encrypt(keys.wif, pass);
+ $("#walletKeys .walletSegWitRS").addClass("hidden");
if($("#walletSegwit").is(":checked")){
var sw = coinjs.segwitAddress(pubkey);
address = sw.address;
+
+ $("#walletKeys .walletSegWitRS").removeClass("hidden");
+ $("#walletKeys .walletSegWitRS input:text").val(sw.redeemscript);
}
$("#walletAddress").html(address);
@@ -142,6 +146,11 @@ $(document).ready(function() {
script = sw.redeemscript;
}
+ var sequence = false;
+ if($("#walletRBF").is(":checked")){
+ sequence = 0xffffffff-2;
+ }
+
tx.addUnspent($("#walletAddress").html(), function(data){
var dvalue = (data.value/100000000).toFixed(8) * 1;
@@ -182,7 +191,7 @@ $(document).ready(function() {
$("#walletLoader").addClass("hidden");
- }, script, script);
+ }, script, script, sequence);
});
$("#walletSendBtn").click(function(){
@@ -601,7 +610,8 @@ $(document).ready(function() {
estimatedTxSize += 147
}
- tx.addinput($(".txId",o).val(), $(".txIdN",o).val(), $(".txIdScript",o).val(), seq);
+ var value = parseInt($(".txIdAmount", o).val() * 1e8);
+ tx.addinput($(".txId",o).val(), $(".txIdN",o).val(), $(".txIdScript",o).val(), seq, value);
} else {
$('#putTabs a[href="#txinputs"]').attr('style','color:#a94442;');
}
@@ -631,21 +641,94 @@ $(document).ready(function() {
if(!$("#recipients .row, #inputs .row").hasClass('has-error')){
- $("#transactionCreate textarea").val(tx.serialize());
+ var txhex = tx.serialize();
+ var txinputs = JSON.stringify(tx.coreInputObject());
+ $("#transactionCreate textarea.transactionHex").val(txhex);
+ $("#transactionCreate textarea.transactionInputs").val(txinputs);
$("#transactionCreate .txSize").html(tx.size());
- $("#transactionCreate").removeClass("hidden");
+ if($("#feesestnewtx").attr('est')=='y'){
+ $("#fees .txhex").val(txhex);
+ $("#feesAnalyseBtn").click();
+ $("#fees .txhex").val("");
+ window.location = "#fees";
+ } else {
+
+ $("#transactionCreate").removeClass("hidden");
- // 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");
+ // 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");
+ }
}
+ $("#feesestnewtx").attr('est','');
} else {
$("#transactionCreateStatus").removeClass("hidden").html("One or more input or output is invalid").fadeOut().fadeIn();
}
});
+ $("#transactionToSignBtn").click(function(){
+ var txhex = $("#transactionCreate textarea.transactionHex").val();
+ var txinputs = $("#transactionCreate textarea.transactionInputs").val();
+ $("#signTransaction").val(txhex);
+ $("#signTransactionInputs").val(txinputs);
+ window.location.hash = "#sign";
+ });
+
+ $("#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);
+ $("#fees .txi_segwit").trigger('input');
+ } else {
+ $("#fees .txi_regular").val(inputs);
+ $("#fees .txi_regular").trigger('input');
+ }
+
+ $.each($("#walletSpendTo .output"), function(i,o){
+ var addr = $('.addressTo',o);
+ var ad = coinjs.addressDecode(addr.val());
+ if (ad.version == coinjs.multisig){ // p2sh
+ $("#fees .txo_p2sh").val(($("#fees .txo_p2sh").val()*1)+1);
+ $("#fees .txo_p2sh").trigger('input');
+ } else { // p2pkh
+ $("#fees .txo_p2pkh").val(($("#fees .txo_p2pkh").val()*1)+1);
+ $("#fees .txo_p2pkh").trigger('input');
+ }
+ });
+
+ if(($("#developerDonation").val()*1)>0){
+ var addr = coinjs.developer;
+ var ad = coinjs.addressDecode(addr);
+ if (ad.version == coinjs.multisig){ // p2sh
+ $("#fees .txo_p2sh").val(($("#fees .txo_p2sh").val()*1)+1);
+ $("#fees .txo_p2sh").trigger('input');
+ } else { // p2pkh
+ $("#fees .txo_p2pkh").val(($("#fees .txo_p2pkh").val()*1)+1);
+ $("#fees .txo_p2pkh").trigger('input');
+ }
+ }
+
+ });
+
+ //feeStats();
+ window.location = "#fees";
+ });
+
$(".txidClear").click(function(){
$("#inputs .row:first input").attr('disabled',false);
$("#inputs .row:first input").val("");
@@ -778,6 +861,10 @@ $(document).ready(function() {
listUnspentChainso_Dogecoin(redeem);
} else if(host=='cryptoid.info_carboncoin'){
listUnspentCryptoidinfo_Carboncoin(redeem);
+ } else if(host=='bitcoingold.org_bgoldmainnet'){
+ listUnspentBitcoingoldorg_BitcoinGold(redeem, true);
+ } else if(host=='bitcoingold.org_bgoldtestnet'){
+ listUnspentBitcoingoldorg_BitcoinGold(redeem, false);
} else {
listUnspentDefault(redeem);
}
@@ -1011,6 +1098,45 @@ $(document).ready(function() {
});
}
+ function listUnspentBitcoingoldorg_BitcoinGold(redeem, mainnet) {
+ $.ajax ({
+ type: "GET",
+ url: "https://explorer.bitcoingold.org/insight-api/addr/"+redeem.addr+"/utxo",
+ dataType: "json",
+ crossDomain: true,
+ contentType: 'text/plain',
+ xhrFields: {
+ withCredentials: false
+ },
+ error: function(data) {
+ $("#redeemFromStatus").removeClass('hidden').html('
Unexpected error, unable to retrieve unspent outputs!');
+ },
+ success: function(data) {
+ if(data instanceof Array){
+ $("#redeemFromAddress").removeClass('hidden').html(
+ '
Retrieved unspent inputs from address
'+redeem.addr+' ');
+ for(var i=0; i
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(){
@@ -1125,6 +1251,33 @@ $(document).ready(function() {
});
}
+ // broadcast transaction via bitcoingold.org
+ function rawSubmitBitcoingoldorg_BitcoinGold(thisbtn, mainnet) {
+ $(thisbtn).val('Please wait, loading...').attr('disabled',true);
+ $.ajax ({
+ type: "POST",
+ url: "https://explorer.bitcoingold.org/insight-api/tx/send",
+ data: "rawtx: " + $("#rawTransaction").val(),
+ dataType: "json",
+ 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("Successful").removeClass('hidden');
+ if(data.txid) {
+ $("#rawTransactionStatus").addClass('alert-success').removeClass('alert-danger');
+ $("#rawTransactionStatus").html('txid: '+data.txid);
+ } 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_BitcoinMainnet(thisbtn){
$(thisbtn).val('Please wait, loading...').attr('disabled',true);
@@ -1403,7 +1556,15 @@ $(document).ready(function() {
var pubkey = $("#verifyScript").val();
if(pubkey.length==66 || pubkey.length==130){
try {
+ $("#verifyPubKey .verifyDataSw").addClass('hidden');
$("#verifyPubKey .address").val(coinjs.pubkey2address(pubkey));
+ if(pubkey.length == 66){
+ var sw = coinjs.segwitAddress(pubkey);
+ $("#verifyPubKey .addressSegWit").val(sw.address);
+ $("#verifyPubKey .addressSegWitRedeemScript").val(sw.redeemscript);
+
+ $("#verifyPubKey .verifyDataSw").removeClass('hidden');
+ }
$("#verifyPubKey").removeClass("hidden");
$(".verifyLink").attr('href','?verify='+$("#verifyScript").val());
return true;
@@ -1468,6 +1629,7 @@ $(document).ready(function() {
$("#signBtn").click(function(){
var wifkey = $("#signPrivateKey");
var script = $("#signTransaction");
+ var txinputs = $("#signTransactionInputs");
if(coinjs.addressDecode(wifkey.val())){
$(wifkey).parent().removeClass('has-error');
@@ -1481,11 +1643,26 @@ $(document).ready(function() {
$(script).parent().addClass('has-error');
}
+ var txinputsObj = null;
+ if (txinputs.val().trim()) {
+ try {
+ txinputsObj = JSON.parse(txinputs.val());
+ $(txinputs).parent().removeClass('has-error');
+ } catch(e) {
+ $(txinputs).parent().addClass('has-error');
+ }
+ } else {
+ $(script).parent().removeClass('has-error');
+ }
+
if($("#sign .has-error").length==0){
$("#signedDataError").addClass('hidden');
try {
var tx = coinjs.transaction();
var t = tx.deserialize(script.val());
+ if (txinputsObj) {
+ t.completeInputValues(txinputsObj);
+ }
var signed = t.sign(wifkey.val(), $("#sighashType option:selected").val());
$("#signedData textarea").val(signed);
@@ -1545,6 +1722,12 @@ $(document).ready(function() {
window.location.hash = "#verify";
}
+ $('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
+ if(e.target.hash == "#fees"){
+ feeStats();
+ }
+ })
+
$(".qrcodeBtn").click(function(){
$("#qrcode").html("");
var thisbtn = $(this).parent().parent();
@@ -1625,7 +1808,8 @@ $(document).ready(function() {
$("#settings .has-error").removeClass("has-error");
$.each($(".coinjssetting"),function(i, o){
- if(!$(o).val().match(/^0x[0-9a-f]+$/)){
+ // allow hex, dec, or empty.
+ if(!$(o).val().match(/^0x[0-9a-f]+|[0-9]+|$/)){
$(o).parent().addClass("has-error");
}
});
@@ -1635,6 +1819,14 @@ $(document).ready(function() {
coinjs.pub = $("#coinjs_pub").val()*1;
coinjs.priv = $("#coinjs_priv").val()*1;
coinjs.multisig = $("#coinjs_multisig").val()*1;
+ var forkIdVal = $("#coinjs_forkid").val();
+ if (!isNaN(forkIdVal) && forkIdVal*1 >= 0) {
+ coinjs.useForkId = true;
+ coinjs.forkId = forkIdVal*1;
+ } else {
+ coinjs.useForkId = false;
+ coinjs.forkId = 0;
+ }
coinjs.hdkey.pub = $("#coinjs_hdpub").val()*1;
coinjs.hdkey.prv = $("#coinjs_hdprv").val()*1;
@@ -1677,6 +1869,12 @@ $(document).ready(function() {
$("#coinjs_hdpub").val(o[3]);
$("#coinjs_hdprv").val(o[4]);
+ if(o.length >= 8) {
+ $("#coinjs_forkid").val(o[7]);
+ } else {
+ $("#coinjs_forkid").val("");
+ }
+
// hide/show custom screen
if($("option:selected",this).val()=="custom"){
$("#settingsCustom").removeClass("hidden");
@@ -1704,6 +1902,14 @@ $(document).ready(function() {
$("#rawSubmitBtn").click(function(){
rawSubmitcryptoid_Carboncoin(this);
});
+ } else if(host=="bitcoingold.org_bgoldmainnet"){
+ $("#rawSubmitBtn").click(function(){
+ rawSubmitBitcoingoldorg_BitcoinGold(this, true);
+ });
+ } else if(host=="bitcoingold.org_bgoldtestnet"){
+ $("#rawSubmitBtn").click(function(){
+ rawSubmitBitcoingoldorg_BitcoinGold(this, false);
+ });
} else {
$("#rawSubmitBtn").click(function(){
rawSubmitDefault(this); // revert to default
@@ -1715,6 +1921,231 @@ $(document).ready(function() {
$("#redeemFromBtn").attr('rel',$("#coinjs_utxo option:selected").val());
}
+
+ /* fees page code */
+
+ $("#fees .slider").on('input', function(){
+ $('.'+$(this).attr('rel')+' .inputno, .'+$(this).attr('rel')+' .outputno',$("#fees")).html($(this).val());
+ $('.'+$(this).attr('rel')+' .estimate',$("#fees")).removeClass('hidden');
+ });
+
+ $("#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));
+ mathFees();
+ });
+
+ $("#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));
+ mathFees();
+ });
+
+ $("#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));
+ mathFees();
+ });
+
+ $("#fees .txi_segwit").on('input', function(){
+ var inputno = $('.'+$(this).attr('rel')+' .inputno',$("#fees .txinputs")).html();
+ var bytes = 0;
+ if(inputno >= 1){
+ bytes = 2;
+ bytes += (inputno*32);
+ bytes += (inputno*$("#est_txi_segwit").val());
+ bytes += (inputno*(41))
+ }
+
+ bytes = bytes.toFixed(0);
+ $('.'+$(this).attr('rel')+' .bytes',$("#fees .txinputs")).html(bytes);
+ mathFees();
+ });
+
+ $("#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));
+ mathFees();
+ });
+
+ $("#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));
+ mathFees();
+ });
+
+ $("#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));
+ mathFees();
+ });
+
+ $("#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');
+ }
+ });
+
+ $("#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");
+ }
+ });
+
+ $("#feesAnalyseBtn").click(function(){
+ 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);
+ $("#fees .segwit .bytes").html(($("#fees .segwit .bytes").html()*1)+size);
+
+ } 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);
+ $("#fees .multisig .bytes").html(($("#fees .multisig .bytes").html()*1)+size);
+
+ } 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);
+ $("#fees .hodl .bytes").html(($("#fees .hodl .bytes").html()*1)+size);
+
+ } 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);
+ }
+ }
+
+ feeStats();
+ });
+
+ $("#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(''+$(data).find("height").text()+' ');
+ $("#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(''+$(data).find("txid").text()+' ');
+ $("#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);
+ }
+ });
+ }
+
/* capture mouse movement to add entropy */
var IE = document.all?true:false // Boolean, is browser IE?
if (!IE) document.captureEvents(Event.MOUSEMOVE)
@@ -1746,4 +2177,5 @@ $(document).ready(function() {
return true;
};
+
});
diff --git a/sha1sum b/sha1sum
index ae427aca..17fcfb2e 100644
--- a/sha1sum
+++ b/sha1sum
@@ -1,9 +1,9 @@
----- Version 1.3 2017.10.04 ----
+---- Version 1.3 2018.01.15 ---
77e4519962e2f6a9fc93342137dbb31c33b76b04 ./js/aes.js
3a09a8fc0cfe828b57fc798d668234d0490ee1a6 ./js/bootstrap-datetimepicker.min.js
253711c6d825de55a8360552573be950da180614 ./js/bootstrap.min.js
-8e9b7114276b56d1073698f025f707523d53631b ./js/coinbin.js
-31fbebf65d9cae8f26761cb057c4fb1b97339d08 ./js/coin.js
+106646cb21653e8eeaa36dbf7ba4c572efbef08c ./js/coinbin.js
+2d48b86fe5c7d485c6613afcb0d52d5352ecf01b ./js/coin.js
988565bc2cb402d63ed5c5fd7ff47c4278efc2c5 ./js/collapse.js
9ba5ede3d7f9d4c8fd623395f196adfdcf7e970f ./js/crypto-min.js
f7c09f2f5a721371e7d478050119f7e2d58e3ef9 ./js/crypto-sha256-hmac.js
@@ -21,7 +21,8 @@ ad038e1f39646b68ae666324ed4c2882a8c42474 ./js/qrcode.js
255c58c17e63eb54adb3cd02b5c06224c67fc364 ./css/bootstrap-datetimepicker.min.css
ed29315e0ffb3f14382431f2724235bf67f44eb3 ./css/bootstrap.min.css
fc6b4268fbd57ad95d2b41a1d4d6866f222fbdb2 ./css/bootstrap-theme.min.css
-4198ed869836ea5727ad6b80bf2df0a9c1a83244 ./css/style.css
+eb54f374256b75a17f274847b4ca9985fd046f9f ./css/style.css
+2e3217a3f3b7c2fb30562ab9a4ef9a407ae81897 ./images/btc32x.png
8ac24915d59cef71c542e7cb7d7e153f560cba1f ./images/coinbin.gif
f2af060f1cadbc9065c8c465c648dc01be67cc12 ./images/loader.gif
86b6f62b7853e67d3e635f6512a5a5efc58ea3c3 ./fonts/glyphicons-halflings-regular.eot
@@ -29,8 +30,5 @@ ca35b697d99cae4d1b60f2d60fcd37771987eb07 ./fonts/glyphicons-halflings-regular.w
de51a8494180a6db074af2dee2383f0a363c5b08 ./fonts/glyphicons-halflings-regular.svg
278e49a86e634da6f2a02f3b47dd9d2a8f26210f ./fonts/glyphicons-halflings-regular.woff
44bc1850f570972267b169ae18f1cb06b611ffa2 ./fonts/glyphicons-halflings-regular.ttf
-d8a324a13501cd5705dc26b945fc8088f00907ae ./README.md
-fa37c3b94927a222abf589a1c16129a3a3f4b4ab ./index.html
-
-
-
+177232f8f3eac41ec9402c581dd26c69e498874d ./README.md
+2334df7122e15cae4f045a7e15bc24abbbe79aa7 ./index.html