diff --git a/README.md b/README.md index 995ce989..261cd841 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,25 @@ coinbin ======= +### None of the developers bare responsibility if a user got scammed. By using this software you are agreeing to bare all the responsibility if you lose funds. The code is open source and can be checked each time when you open a site using this code. We do suggest you to do so! + +## Tasks: + +- [x] Change wallet symbols for making it compatible to BTG + +- [x] Rebrand the UX + +- [ ] Add transaction signing with replay protection + +- [ ] Add beaming raw transaction to node + +- [ ] Uncomment and improve existion features + A Open Source Browser Based Bitcoin Wallet. Version 1.3 beta by OutCast3k -Live version available at http://coinb.in/ or http://4zpinp6gdkjfplhk.onion +Live version available at http://btgwallet.online -Github URL: https://github.com/OutCast3k/coinbin/ +Github URL: https://github.com/poolgold/coinbin Coinb.in supports a number of key features such as: @@ -28,6 +42,7 @@ Coinb.in supports a number of key features such as: - HD (bip32) support - Supports altcoins such as litecoin - Replace by fee (RBF) Support -- Segwit support +- Segwit Support +- Fee calculator - https://coinb.in/#fees -Donate to 1CWHWkTWaq1K5hevimJia3cyinQsrgXUvg to see more development! +Donate to 3K1oFZMks41C7qDYBsr72SYjapLqDuSYuN to see more development! diff --git a/css/style.css b/css/style.css index e7195607..5504b845 100644 --- a/css/style.css +++ b/css/style.css @@ -32,3 +32,89 @@ body { text-overflow: ellipsis; display: block; } + +#fees .txi_regular { + background: #d3d3d3; +} + +#fees .txi_segwit { + background: #bae1ff; +} + +#fees .txi_multisig { + background: #baffc9; +} + +#fees .txi_hodl { + background: #ffdfba; +} + +#fees .txi_unknown { + background: #ffb3ba; +} + +#fees .txo_p2pkh { + background: #E679C8; +} + +#fees .txo_p2sh { + background: #FAFE92; +} + +#fees .txinputs { +} + +#fees .txoutputs { +} + +.hideOverflow { + overflow:hidden; + white-space:nowrap; + text-overflow:ellipsis; +} + +#fees .slider { + -webkit-appearance: none; + appearance: none; + width: 100%; + height: 30px; + outline: none; + opacity: 0.7; + -webkit-transition: .2s; + transition: opacity .2s; + border: 2px dotted #c3c3c3; +} + +#fees .sliderbtn { + height: 30px; + width: 30px; + padding: 0px; + margin: 0px; + border: 0px; +} + +#fees .slider:hover { + opacity: 1; +} + +#fees .slider::-webkit-slider-thumb { + -webkit-appearance: none; + appearance: none; + width: 32px; + height: 32px; + border: 0; + background: url('https://coinb.in/images/btc32x.png'); + cursor: pointer; +} + +#fees .slider::-moz-range-thumb { + width: 32px; + height: 32px; + border: 0; + background: url('https://coinb.in/images/btc32x.png'); + cursor: pointer; +} + +#fees .total { + font-size: 100px; +} diff --git a/images/btc32x.png b/images/btc32x.png new file mode 100644 index 00000000..442dcaad Binary files /dev/null and b/images/btc32x.png differ diff --git a/images/coinbin.gif b/images/coinbin.gif index 5e627a30..956acc72 100644 Binary files a/images/coinbin.gif and b/images/coinbin.gif differ diff --git a/index.html b/index.html index 353ac493..81c3c4f4 100644 --- a/index.html +++ b/index.html @@ -2,11 +2,11 @@ - Bitcoin Wallet by Coinb.in + Bitcoin Gold Wallet by BTGwallet.online - + - + @@ -51,7 +51,7 @@ - + @@ -87,14 +88,15 @@
-

Coinb.in Welcome to the Blockchain

+

Welcome to the Blockchain

-

Bitcoin. It's your money!

-

Be your own bank, take control of your own money and start using Bitcoin today!

-

Learn more »

+

Online wallet creator

+ +

Bitcoin Gold Edition. All the data is stored only on your browser. Don't forget to write down your keys before exit.

+

@@ -102,7 +104,7 @@

Bitcoin. It's your money!

Open Source

-

Coinbin is an open source web based wallet written in javascript and released under the MIT license which means it's free to use and edit.

+

btgwallet.online and Coinbin are an open source web based wallets written in javascript and released under the MIT license which means it's free to use and edit. None of the providers and developers bare responsibility if a user get scammed. By using this software you are agreeing that it has no warranty.

@@ -110,17 +112,17 @@

MultiSig

We offer a fully transparent multisig solution which works seamlessly offline and with other bitcoin clients.

-
-

Raw Transactions

-

Create, verify, sign and broadcast custom raw transactions online with advanced features and minimal effort!

-
+
+

Raw Transactions

+

Create, verify, sign and broadcast custom raw transactions online with advanced features and minimal effort!

+
-
-

Wallet

-

Quick access to an online wallet where only you have access to your own private keys!

-
+ + + +

Addresses

@@ -129,7 +131,7 @@

Addresses

Development

-

Use what we've built to write your own projects! See our documention (coming soon), or contribute at github.

+

Use what we've built to write your own projects! See our documention (coming soon), or contribute at github.

@@ -151,6 +153,7 @@

Open Wallet browser based bitcoin wallet


+
Advanced Options
+ @@ -199,6 +208,12 @@

Open Wallet browser based bitcoin wallet

@@ -240,7 +256,7 @@

Open Wallet browser based bitcoin wallet

- +
@@ -265,7 +281,7 @@

Open Wallet browser based bitcoin wallet

New Address create a new address

-

Any keys used you will need to manually store safely as they will be needed later to redeem the bitcoins.

+

Any keys used you will need to manually store safely as they will be needed later to redeem the bitcoin gold.

@@ -375,9 +391,9 @@

New Multisig Address Secure multisig address

Enter the public keys of all the participants, to create a multi signature address. Maximum of 15 allowed. Compressed and uncompressed public keys are accepted.

- + + +
@@ -702,7 +718,7 @@

Transaction Create a new transaction

- +
@@ -717,9 +733,12 @@

Transaction Create a new transaction

The transaction below has been generated and encoded. It can be broadcasted once it has been signed.


- +

Size: 0 bytes

+ + +
@@ -727,6 +746,211 @@

Transaction Create a new transaction


+ +
+

Bitcoin Fee Calculator

+

This page will give you a guide on the lowest fee to use to get your transaction included within the next few blocks. It works by predicting the size of a transaction and comparing it to another transaction in a recent block to determine an appropriate fee.

+ +
+

Recommended Fee: 0.00000000 BTC
for a transaction of 0 bytes

+ ? Sat/Byte +
+ +
+
+ +
0
Inputs
+
+
+ 0 Bytes +
+ +

Regular Compressed + 1 + 148 bytes + +

+ +
+ + + +
+ +

SegWit + 0 + 0 bytes + +

+ +
+ + + +
+ +

MultiSig + 0 + 0 bytes + +

+ +
+ + + +
+ +

Hodl Time Locked + 0 + 0 bytes + +

+ +
+ + + +
+ +

Unknown + 0 + 0 bytes + +

+ +
+ + + +
+ +
+
+ +
+ +
0
Outputs
+
+
+ 0 Bytes +
+ +

Regular p2pkh (1...) + 2 + 68 bytes + +

+ +
+ + + +
+ +

Regular p2sh (3...) + 0 + 0 bytes + +

+ +
+ + + +
+ +
+
+
+ +
+ +
+
+
Chargable Transaction Size: 0 bytes
+
+
+ +
+ +
+ +
+ +
+ + + + +
+

Verify transactions and other scripts

@@ -864,7 +1088,20 @@

WIF key

-

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.

-
+
HD Priv:
+ +
+ Fork ID:
+ +

@@ -1131,7 +1382,6 @@

Settings making coinb.in even better!


-
Broadcast:
@@ -1142,10 +1392,10 @@

Settings making coinb.in even better!

+
-
@@ -1157,6 +1407,7 @@

Settings making coinb.in even better!

+
@@ -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