commit
a9cfa44c44
8 changed files with 552 additions and 31 deletions
5
css/bootstrap-datetimepicker.min.css
vendored
Normal file
5
css/bootstrap-datetimepicker.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
149
index.html
149
index.html
|
@ -12,10 +12,15 @@
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
|
||||||
<link rel="stylesheet" href="css/bootstrap.min.css" media="screen">
|
<link rel="stylesheet" href="css/bootstrap.min.css" media="screen">
|
||||||
|
<link rel="stylesheet" href="css/bootstrap-datetimepicker.min.css">
|
||||||
<link rel="stylesheet" href="css/style.css" media="screen">
|
<link rel="stylesheet" href="css/style.css" media="screen">
|
||||||
|
|
||||||
<script type="text/javascript" src="js/jquery-1.9.1.min.js"></script>
|
<script type="text/javascript" src="js/jquery-1.9.1.min.js"></script>
|
||||||
|
<script type="text/javascript" src="js/moment.min.js"></script>
|
||||||
|
<script type="text/javascript" src="js/transition.js"></script>
|
||||||
|
<script type="text/javascript" src="js/collapse.js"></script>
|
||||||
<script type="text/javascript" src="js/bootstrap.min.js"></script>
|
<script type="text/javascript" src="js/bootstrap.min.js"></script>
|
||||||
|
<script type="text/javascript" src="js/bootstrap-datetimepicker.min.js"></script>
|
||||||
|
|
||||||
<script type="text/javascript" src="js/crypto-min.js"></script>
|
<script type="text/javascript" src="js/crypto-min.js"></script>
|
||||||
<script type="text/javascript" src="js/crypto-sha256.js"></script>
|
<script type="text/javascript" src="js/crypto-sha256.js"></script>
|
||||||
|
@ -54,6 +59,7 @@
|
||||||
<ul class="dropdown-menu">
|
<ul class="dropdown-menu">
|
||||||
<li><a href="#newAddress" data-toggle="tab">New Address</a></li>
|
<li><a href="#newAddress" data-toggle="tab">New Address</a></li>
|
||||||
<li><a href="#newMultiSig" data-toggle="tab">MultiSig Address</a></li>
|
<li><a href="#newMultiSig" data-toggle="tab">MultiSig Address</a></li>
|
||||||
|
<li><a href="#newTimeLocked" data-toggle="tab">New Time Locked Address</a></li>
|
||||||
<li><a href="#newHDaddress" data-toggle="tab">HD Address</a></li>
|
<li><a href="#newHDaddress" data-toggle="tab">HD Address</a></li>
|
||||||
<li class="divider"></li>
|
<li class="divider"></li>
|
||||||
<li><a href="#newTransaction" data-toggle="tab">Transaction</a></li>
|
<li><a href="#newTransaction" data-toggle="tab">Transaction</a></li>
|
||||||
|
@ -377,6 +383,73 @@
|
||||||
<br>
|
<br>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="tab-pane tab-content" id="newTimeLocked">
|
||||||
|
<h2>New Time Locked Address <small>Coins can be released only after a certain date</small></h2>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
|
||||||
|
<div class="col-md-11">
|
||||||
|
<p>Public keys can be <a href="#newAddress">generated in your browser</a> or from your bitcoin client</a>.</p>
|
||||||
|
<p>Enter the public key that will be able to unlock the funds after the a certain date.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-1">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="form-horizontal">
|
||||||
|
<div class="col-xs-11">
|
||||||
|
<input id="timeLockedPubKey" type="text" class="form-control pubkey">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p>Enter the date and time required to release the coins</p>
|
||||||
|
<div class="row">
|
||||||
|
<div class='col-xs-3'>
|
||||||
|
<div class="form-group">
|
||||||
|
<div class='input-group date' id='timeLockedDateTimePicker'>
|
||||||
|
<input type='text' class="form-control" />
|
||||||
|
<span class="input-group-addon">
|
||||||
|
<span class="glyphicon glyphicon-calendar"></span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class='col-xs-3'>
|
||||||
|
<small>System Local Time</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<div id="timeLockedErrorMsg" class="alert alert-danger" style="display:none;"></div>
|
||||||
|
|
||||||
|
<div class="alert alert-success hidden" id="timeLockedData">
|
||||||
|
<label>Address</label>
|
||||||
|
<p>Payment should be made to this address:</p>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-6">
|
||||||
|
<div class="input-group">
|
||||||
|
<input type="text" class="form-control address" value="" readonly>
|
||||||
|
<span class="input-group-btn">
|
||||||
|
<button class="qrcodeBtn btn btn-default" type="button" data-toggle="modal" data-target="#modalQrcode"><span class="glyphicon glyphicon-qrcode"></span></button>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<label>Redeem Script</label>
|
||||||
|
<p>This script should be <i>saved and should be shared with all the participants before a payment is made</i>, so they may validate the authenticity of the address, it will also be used later to release the bitcoins.</p>
|
||||||
|
<textarea class="form-control script" style="height:160px" readonly></textarea>
|
||||||
|
<label>Shareable URL</label>
|
||||||
|
<input type="text" class="scriptUrl form-control" readonly>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<input type="button" class="btn btn-primary" value="Submit" id="newTimeLockedAddress">
|
||||||
|
<br>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="tab-pane tab-content" id="newHDaddress">
|
<div class="tab-pane tab-content" id="newHDaddress">
|
||||||
<h2>New HD Address <small>making bip32 even easier</small></h2>
|
<h2>New HD Address <small>making bip32 even easier</small></h2>
|
||||||
<p>Use the form below to generate a <i>master</i> hierarchical deterministic address.</p>
|
<p>Use the form below to generate a <i>master</i> hierarchical deterministic address.</p>
|
||||||
|
@ -585,24 +658,64 @@
|
||||||
<div class="hidden verifyData" id="verifyRsData">
|
<div class="hidden verifyData" id="verifyRsData">
|
||||||
<h4>Redeem Script</h4>
|
<h4>Redeem Script</h4>
|
||||||
<p><span style="float:right"><a href="javascript:;" target="_blank" class="verifyLink" title="Link to this page"><span class="glyphicon glyphicon-link"></span></a></span>The above redeem script has been decoded</p>
|
<p><span style="float:right"><a href="javascript:;" target="_blank" class="verifyLink" title="Link to this page"><span class="glyphicon glyphicon-link"></span></a></span>The above redeem script has been decoded</p>
|
||||||
<label>Multi Signature Address</label>
|
|
||||||
<div class="row">
|
<div class="hidden" id="verifyRsDataMultisig">
|
||||||
<div class="col-lg-6">
|
<label>Multi Signature Address</label>
|
||||||
<div class="input-group">
|
<div class="row">
|
||||||
<input type="text" class="form-control address multisigAddress" value="" readonly>
|
<div class="col-lg-6">
|
||||||
<span class="input-group-btn">
|
<div class="input-group">
|
||||||
<button class="qrcodeBtn btn btn-default" type="button" data-toggle="modal" data-target="#modalQrcode"><span class="glyphicon glyphicon-qrcode"></span></button>
|
<input type="text" class="form-control address multisigAddress" value="" readonly>
|
||||||
</span>
|
<span class="input-group-btn">
|
||||||
</div>
|
<button class="qrcodeBtn btn btn-default" type="button" data-toggle="modal" data-target="#modalQrcode"><span class="glyphicon glyphicon-qrcode"></span></button>
|
||||||
</div>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<label>Required Signatures</label>
|
</div>
|
||||||
<p class="signaturesRequired">?</p>
|
</div>
|
||||||
<label>Signatures Required from</label>
|
<label>Required Signatures</label>
|
||||||
<table class="table table-striped table-hover">
|
<p class="signaturesRequired">?</p>
|
||||||
<tbody>
|
<label>Signatures Required from</label>
|
||||||
</tbody>
|
<table class="table table-striped table-hover">
|
||||||
</table>
|
<tbody>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="hidden" id="verifyRsDataHodl">
|
||||||
|
<label>Hodl Address</label>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-6">
|
||||||
|
<div class="input-group">
|
||||||
|
<input type="text" class="form-control address" value="" readonly>
|
||||||
|
<span class="input-group-btn">
|
||||||
|
<button class="qrcodeBtn btn btn-default" type="button" data-toggle="modal" data-target="#modalQrcode"><span class="glyphicon glyphicon-qrcode"></span></button>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<label>Required Signature</label>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-6">
|
||||||
|
<div class="input-group">
|
||||||
|
<input type="text" class="form-control pubkey" value="" readonly>
|
||||||
|
<span class="input-group-btn">
|
||||||
|
<button class="qrcodeBtn btn btn-default" type="button" data-toggle="modal" data-target="#modalQrcode"><span class="glyphicon glyphicon-qrcode"></span></button>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<label>Unlock Time</label>
|
||||||
|
<div class="row">
|
||||||
|
<div class='col-lg-6'>
|
||||||
|
<div class="input-group">
|
||||||
|
<input type="text" class="form-control date" value="" readonly>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<br>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="hidden verifyData" id="verifyTransactionData">
|
<div class="hidden verifyData" id="verifyTransactionData">
|
||||||
|
|
9
js/bootstrap-datetimepicker.min.js
vendored
Normal file
9
js/bootstrap-datetimepicker.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
57
js/coin.js
57
js/coin.js
|
@ -135,6 +135,36 @@
|
||||||
return {'address':address, 'redeemScript':redeemScript};
|
return {'address':address, 'redeemScript':redeemScript};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* new time locked address, provide the pubkey and time necessary to unlock the funds.
|
||||||
|
when time is greater than 500000000, it should be a unix timestamp (seconds since epoch),
|
||||||
|
otherwise it should be the block height required before this transaction can be released.
|
||||||
|
|
||||||
|
may throw a string on failure!
|
||||||
|
*/
|
||||||
|
coinjs.simpleHodlAddress = function(pubkey, checklocktimeverify) {
|
||||||
|
|
||||||
|
if(checklocktimeverify < 0) {
|
||||||
|
throw "Parameter for OP_CHECKLOCKTIMEVERIFY is negative.";
|
||||||
|
}
|
||||||
|
|
||||||
|
var s = coinjs.script();
|
||||||
|
s.writeBytes(Crypto.util.hexToBytes(checklocktimeverify.toString(16)).reverse());
|
||||||
|
s.writeOp(177);//OP_CHECKLOCKTIMEVERIFY
|
||||||
|
s.writeOp(117);//OP_DROP
|
||||||
|
s.writeBytes(Crypto.util.hexToBytes(pubkey));
|
||||||
|
s.writeOp(172);//OP_CHECKSIG
|
||||||
|
|
||||||
|
var x = ripemd160(Crypto.SHA256(s.buffer, {asBytes: true}), {asBytes: true});
|
||||||
|
x.unshift(coinjs.multisig);
|
||||||
|
var r = x;
|
||||||
|
r = Crypto.SHA256(Crypto.SHA256(r, {asBytes: true}), {asBytes: true});
|
||||||
|
var checksum = r.slice(0,4);
|
||||||
|
var redeemScript = Crypto.util.bytesToHex(s.buffer);
|
||||||
|
var address = coinjs.base58encode(x.concat(checksum));
|
||||||
|
|
||||||
|
return {'address':address, 'redeemScript':redeemScript};
|
||||||
|
}
|
||||||
|
|
||||||
/* provide a privkey and return an WIF */
|
/* provide a privkey and return an WIF */
|
||||||
coinjs.privkey2wif = function(h){
|
coinjs.privkey2wif = function(h){
|
||||||
var r = Crypto.util.hexToBytes(h);
|
var r = Crypto.util.hexToBytes(h);
|
||||||
|
@ -649,6 +679,14 @@
|
||||||
r.pubkeys = pubkeys;
|
r.pubkeys = pubkeys;
|
||||||
var multi = coinjs.pubkeys2MultisigAddress(pubkeys, r.signaturesRequired);
|
var multi = coinjs.pubkeys2MultisigAddress(pubkeys, r.signaturesRequired);
|
||||||
r.address = multi['address'];
|
r.address = multi['address'];
|
||||||
|
r.type = 'multisig__'; // using __ for now to differentiat from the other object .type == "multisig"
|
||||||
|
} else if(s.chunks.length == 5 && s.chunks[1] == 177 && s.chunks[2] == 117 && s.chunks[4] == 172){
|
||||||
|
// ^ <unlocktime> OP_CHECKLOCKTIMEVERIFY OP_DROP <pubkey> OP_CHECKSIG ^
|
||||||
|
r = {}
|
||||||
|
r.pubkey = Crypto.util.bytesToHex(s.chunks[3]);
|
||||||
|
r.checklocktimeverify = parseInt(Crypto.util.bytesToHex(s.chunks[0].slice().reverse()), 16);
|
||||||
|
r.address = coinjs.simpleHodlAddress(r.pubkey, r.checklocktimeverify).address;
|
||||||
|
r.type = "hodl__";
|
||||||
}
|
}
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
// console.log(e);
|
// console.log(e);
|
||||||
|
@ -898,9 +936,15 @@
|
||||||
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
|
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)
|
// 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)};
|
||||||
|
} 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)};
|
||||||
} else if((this.ins[index].script.chunks.length==2) && this.ins[index].script.chunks[0][0]==48){
|
} else if((this.ins[index].script.chunks.length==2) && this.ins[index].script.chunks[0][0]==48){
|
||||||
// regular scriptPubkey (probably signed)
|
// 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)};
|
||||||
|
} 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[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
|
} 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
|
// 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])};
|
||||||
|
@ -1049,6 +1093,17 @@
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* signs a time locked / hodl input */
|
||||||
|
r.signhodl = function(index, wif){
|
||||||
|
var signature = this.transactionSig(index, wif);
|
||||||
|
var redeemScript = this.ins[index].script.buffer
|
||||||
|
var s = coinjs.script();
|
||||||
|
s.writeBytes(Crypto.util.hexToBytes(signature));
|
||||||
|
s.writeBytes(redeemScript);
|
||||||
|
this.ins[index].script = s;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/* sign a multisig input */
|
/* sign a multisig input */
|
||||||
r.signmultisig = function(index, wif){
|
r.signmultisig = function(index, wif){
|
||||||
|
|
||||||
|
@ -1111,6 +1166,8 @@
|
||||||
|
|
||||||
if(((d['type'] == 'scriptpubkey' && d['script']==Crypto.util.bytesToHex(pubkeyHash.buffer)) || d['type'] == 'empty') && d['signed'] == "false"){
|
if(((d['type'] == 'scriptpubkey' && d['script']==Crypto.util.bytesToHex(pubkeyHash.buffer)) || d['type'] == 'empty') && d['signed'] == "false"){
|
||||||
this.signinput(i, wif);
|
this.signinput(i, wif);
|
||||||
|
} else if (d['type'] == 'hodl' && d['signed'] == "false") {
|
||||||
|
this.signhodl(i, wif);
|
||||||
} else if (d['type'] == 'multisig') {
|
} else if (d['type'] == 'multisig') {
|
||||||
this.signmultisig(i, wif);
|
this.signmultisig(i, wif);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -360,6 +360,43 @@ $(document).ready(function() {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/* new -> time locked code */
|
||||||
|
|
||||||
|
$('#timeLockedDateTimePicker').datetimepicker({
|
||||||
|
format: "MM/DD/YYYY HH:mm",
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#newTimeLockedAddress").click(function(){
|
||||||
|
|
||||||
|
$("#timeLockedData").removeClass('show').addClass('hidden').fadeOut();
|
||||||
|
$("#timeLockedPubKey").parent().removeClass('has-error');
|
||||||
|
$("#timeLockedDateTimePicker").parent().removeClass('has-error');
|
||||||
|
$("#timeLockedErrorMsg").hide();
|
||||||
|
|
||||||
|
if(!coinjs.pubkeydecompress($("#timeLockedPubKey").val())) {
|
||||||
|
$('#timeLockedPubKey').parent().addClass('has-error');
|
||||||
|
}
|
||||||
|
|
||||||
|
var date = $('#timeLockedDateTimePicker').data("DateTimePicker").date();
|
||||||
|
if(!date || !date.isValid()) {
|
||||||
|
$('#timeLockedDateTimePicker').parent().addClass('has-error');
|
||||||
|
}
|
||||||
|
|
||||||
|
if(($("#timeLockedPubKey").parent().hasClass('has-error')==false) && $("#timeLockedDateTimePicker").parent().hasClass('has-error')==false){
|
||||||
|
try {
|
||||||
|
var hodl = coinjs.simpleHodlAddress($("#timeLockedPubKey").val(), date.unix());
|
||||||
|
$("#timeLockedData .address").val(hodl['address']);
|
||||||
|
$("#timeLockedData .script").val(hodl['redeemScript']);
|
||||||
|
$("#timeLockedData .scriptUrl").val(document.location.origin+''+document.location.pathname+'?verify='+hodl['redeemScript']+'#verify');
|
||||||
|
$("#timeLockedData").removeClass('hidden').addClass('show').fadeIn();
|
||||||
|
} catch(e) {
|
||||||
|
$("#timeLockedErrorMsg").html('<span class="glyphicon glyphicon-exclamation-sign"></span> ' + e).fadeIn();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$("#timeLockedErrorMsg").html('<span class="glyphicon glyphicon-exclamation-sign"></span> Public key and/or date is invalid!').fadeIn();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
/* new -> Hd address code */
|
/* new -> Hd address code */
|
||||||
|
|
||||||
$(".deriveHDbtn").click(function(){
|
$(".deriveHDbtn").click(function(){
|
||||||
|
@ -594,6 +631,15 @@ $(document).ready(function() {
|
||||||
} else {
|
} else {
|
||||||
listUnspentDefault(redeem);
|
listUnspentDefault(redeem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if($("#redeemFromStatus").hasClass("hidden")) {
|
||||||
|
// An ethical dilemma: Should we automatically set nLockTime?
|
||||||
|
if(redeem.from == 'redeemScript' && redeem.decodedRs.type == "hodl__") {
|
||||||
|
$("#nLockTime").val(redeem.decodedRs.checklocktimeverify);
|
||||||
|
} else {
|
||||||
|
$("#nLockTime").val(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
/* function to determine what we are redeeming from */
|
/* function to determine what we are redeeming from */
|
||||||
|
@ -620,7 +666,7 @@ $(document).ready(function() {
|
||||||
r.addr = decodeRs['address'];
|
r.addr = decodeRs['address'];
|
||||||
r.from = 'redeemScript';
|
r.from = 'redeemScript';
|
||||||
r.decodedRs = decodeRs;
|
r.decodedRs = decodeRs;
|
||||||
r.isMultisig = true;
|
r.isMultisig = true; // not quite, may be hodl
|
||||||
} else { // something else
|
} else { // something else
|
||||||
r.addr = '';
|
r.addr = '';
|
||||||
r.from = 'other';
|
r.from = 'other';
|
||||||
|
@ -941,20 +987,34 @@ $(document).ready(function() {
|
||||||
var script = coinjs.script();
|
var script = coinjs.script();
|
||||||
var decode = script.decodeRedeemScript($("#verifyScript").val());
|
var decode = script.decodeRedeemScript($("#verifyScript").val());
|
||||||
if(decode){
|
if(decode){
|
||||||
$("#verifyRsData .multisigAddress").val(decode['address']);
|
$("#verifyRsDataMultisig").addClass('hidden');
|
||||||
$("#verifyRsData .signaturesRequired").html(decode['signaturesRequired']);
|
$("#verifyRsDataHodl").addClass('hidden');
|
||||||
$("#verifyRsData table tbody").html("");
|
|
||||||
for(var i=0;i<decode.pubkeys.length;i++){
|
if(decode.type == "multisig__") {
|
||||||
var pubkey = decode.pubkeys[i];
|
$("#verifyRsDataMultisig .multisigAddress").val(decode['address']);
|
||||||
var address = coinjs.pubkey2address(pubkey);
|
$("#verifyRsDataMultisig .signaturesRequired").html(decode['signaturesRequired']);
|
||||||
$('<tr><td width="30%"><input type="text" class="form-control" value="'+address+'" readonly></td><td><input type="text" class="form-control" value="'+pubkey+'" readonly></td></tr>').appendTo("#verifyRsData table tbody");
|
$("#verifyRsDataMultisig table tbody").html("");
|
||||||
|
for(var i=0;i<decode.pubkeys.length;i++){
|
||||||
|
var pubkey = decode.pubkeys[i];
|
||||||
|
var address = coinjs.pubkey2address(pubkey);
|
||||||
|
$('<tr><td width="30%"><input type="text" class="form-control" value="'+address+'" readonly></td><td><input type="text" class="form-control" value="'+pubkey+'" readonly></td></tr>').appendTo("#verifyRsDataMultisig table tbody");
|
||||||
|
}
|
||||||
|
$("#verifyRsData").removeClass("hidden");
|
||||||
|
$("#verifyRsDataMultisig").removeClass('hidden');
|
||||||
|
$(".verifyLink").attr('href','?verify='+$("#verifyScript").val());
|
||||||
|
return true;
|
||||||
|
} 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;
|
||||||
}
|
}
|
||||||
$("#verifyRsData").removeClass("hidden");
|
|
||||||
$(".verifyLink").attr('href','?verify='+$("#verifyScript").val());
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function decodeTransactionScript(){
|
function decodeTransactionScript(){
|
||||||
|
|
211
js/collapse.js
Normal file
211
js/collapse.js
Normal file
|
@ -0,0 +1,211 @@
|
||||||
|
/* ========================================================================
|
||||||
|
* Bootstrap: collapse.js v3.3.4
|
||||||
|
* http://getbootstrap.com/javascript/#collapse
|
||||||
|
* ========================================================================
|
||||||
|
* Copyright 2011-2015 Twitter, Inc.
|
||||||
|
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||||
|
* ======================================================================== */
|
||||||
|
|
||||||
|
|
||||||
|
+function ($) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
// COLLAPSE PUBLIC CLASS DEFINITION
|
||||||
|
// ================================
|
||||||
|
|
||||||
|
var Collapse = function (element, options) {
|
||||||
|
this.$element = $(element)
|
||||||
|
this.options = $.extend({}, Collapse.DEFAULTS, options)
|
||||||
|
this.$trigger = $('[data-toggle="collapse"][href="#' + element.id + '"],' +
|
||||||
|
'[data-toggle="collapse"][data-target="#' + element.id + '"]')
|
||||||
|
this.transitioning = null
|
||||||
|
|
||||||
|
if (this.options.parent) {
|
||||||
|
this.$parent = this.getParent()
|
||||||
|
} else {
|
||||||
|
this.addAriaAndCollapsedClass(this.$element, this.$trigger)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.options.toggle) this.toggle()
|
||||||
|
}
|
||||||
|
|
||||||
|
Collapse.VERSION = '3.3.4'
|
||||||
|
|
||||||
|
Collapse.TRANSITION_DURATION = 350
|
||||||
|
|
||||||
|
Collapse.DEFAULTS = {
|
||||||
|
toggle: true
|
||||||
|
}
|
||||||
|
|
||||||
|
Collapse.prototype.dimension = function () {
|
||||||
|
var hasWidth = this.$element.hasClass('width')
|
||||||
|
return hasWidth ? 'width' : 'height'
|
||||||
|
}
|
||||||
|
|
||||||
|
Collapse.prototype.show = function () {
|
||||||
|
if (this.transitioning || this.$element.hasClass('in')) return
|
||||||
|
|
||||||
|
var activesData
|
||||||
|
var actives = this.$parent && this.$parent.children('.panel').children('.in, .collapsing')
|
||||||
|
|
||||||
|
if (actives && actives.length) {
|
||||||
|
activesData = actives.data('bs.collapse')
|
||||||
|
if (activesData && activesData.transitioning) return
|
||||||
|
}
|
||||||
|
|
||||||
|
var startEvent = $.Event('show.bs.collapse')
|
||||||
|
this.$element.trigger(startEvent)
|
||||||
|
if (startEvent.isDefaultPrevented()) return
|
||||||
|
|
||||||
|
if (actives && actives.length) {
|
||||||
|
Plugin.call(actives, 'hide')
|
||||||
|
activesData || actives.data('bs.collapse', null)
|
||||||
|
}
|
||||||
|
|
||||||
|
var dimension = this.dimension()
|
||||||
|
|
||||||
|
this.$element
|
||||||
|
.removeClass('collapse')
|
||||||
|
.addClass('collapsing')[dimension](0)
|
||||||
|
.attr('aria-expanded', true)
|
||||||
|
|
||||||
|
this.$trigger
|
||||||
|
.removeClass('collapsed')
|
||||||
|
.attr('aria-expanded', true)
|
||||||
|
|
||||||
|
this.transitioning = 1
|
||||||
|
|
||||||
|
var complete = function () {
|
||||||
|
this.$element
|
||||||
|
.removeClass('collapsing')
|
||||||
|
.addClass('collapse in')[dimension]('')
|
||||||
|
this.transitioning = 0
|
||||||
|
this.$element
|
||||||
|
.trigger('shown.bs.collapse')
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$.support.transition) return complete.call(this)
|
||||||
|
|
||||||
|
var scrollSize = $.camelCase(['scroll', dimension].join('-'))
|
||||||
|
|
||||||
|
this.$element
|
||||||
|
.one('bsTransitionEnd', $.proxy(complete, this))
|
||||||
|
.emulateTransitionEnd(Collapse.TRANSITION_DURATION)[dimension](this.$element[0][scrollSize])
|
||||||
|
}
|
||||||
|
|
||||||
|
Collapse.prototype.hide = function () {
|
||||||
|
if (this.transitioning || !this.$element.hasClass('in')) return
|
||||||
|
|
||||||
|
var startEvent = $.Event('hide.bs.collapse')
|
||||||
|
this.$element.trigger(startEvent)
|
||||||
|
if (startEvent.isDefaultPrevented()) return
|
||||||
|
|
||||||
|
var dimension = this.dimension()
|
||||||
|
|
||||||
|
this.$element[dimension](this.$element[dimension]())[0].offsetHeight
|
||||||
|
|
||||||
|
this.$element
|
||||||
|
.addClass('collapsing')
|
||||||
|
.removeClass('collapse in')
|
||||||
|
.attr('aria-expanded', false)
|
||||||
|
|
||||||
|
this.$trigger
|
||||||
|
.addClass('collapsed')
|
||||||
|
.attr('aria-expanded', false)
|
||||||
|
|
||||||
|
this.transitioning = 1
|
||||||
|
|
||||||
|
var complete = function () {
|
||||||
|
this.transitioning = 0
|
||||||
|
this.$element
|
||||||
|
.removeClass('collapsing')
|
||||||
|
.addClass('collapse')
|
||||||
|
.trigger('hidden.bs.collapse')
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$.support.transition) return complete.call(this)
|
||||||
|
|
||||||
|
this.$element
|
||||||
|
[dimension](0)
|
||||||
|
.one('bsTransitionEnd', $.proxy(complete, this))
|
||||||
|
.emulateTransitionEnd(Collapse.TRANSITION_DURATION)
|
||||||
|
}
|
||||||
|
|
||||||
|
Collapse.prototype.toggle = function () {
|
||||||
|
this[this.$element.hasClass('in') ? 'hide' : 'show']()
|
||||||
|
}
|
||||||
|
|
||||||
|
Collapse.prototype.getParent = function () {
|
||||||
|
return $(this.options.parent)
|
||||||
|
.find('[data-toggle="collapse"][data-parent="' + this.options.parent + '"]')
|
||||||
|
.each($.proxy(function (i, element) {
|
||||||
|
var $element = $(element)
|
||||||
|
this.addAriaAndCollapsedClass(getTargetFromTrigger($element), $element)
|
||||||
|
}, this))
|
||||||
|
.end()
|
||||||
|
}
|
||||||
|
|
||||||
|
Collapse.prototype.addAriaAndCollapsedClass = function ($element, $trigger) {
|
||||||
|
var isOpen = $element.hasClass('in')
|
||||||
|
|
||||||
|
$element.attr('aria-expanded', isOpen)
|
||||||
|
$trigger
|
||||||
|
.toggleClass('collapsed', !isOpen)
|
||||||
|
.attr('aria-expanded', isOpen)
|
||||||
|
}
|
||||||
|
|
||||||
|
function getTargetFromTrigger($trigger) {
|
||||||
|
var href
|
||||||
|
var target = $trigger.attr('data-target')
|
||||||
|
|| (href = $trigger.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7
|
||||||
|
|
||||||
|
return $(target)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// COLLAPSE PLUGIN DEFINITION
|
||||||
|
// ==========================
|
||||||
|
|
||||||
|
function Plugin(option) {
|
||||||
|
return this.each(function () {
|
||||||
|
var $this = $(this)
|
||||||
|
var data = $this.data('bs.collapse')
|
||||||
|
var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option)
|
||||||
|
|
||||||
|
if (!data && options.toggle && /show|hide/.test(option)) options.toggle = false
|
||||||
|
if (!data) $this.data('bs.collapse', (data = new Collapse(this, options)))
|
||||||
|
if (typeof option == 'string') data[option]()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
var old = $.fn.collapse
|
||||||
|
|
||||||
|
$.fn.collapse = Plugin
|
||||||
|
$.fn.collapse.Constructor = Collapse
|
||||||
|
|
||||||
|
|
||||||
|
// COLLAPSE NO CONFLICT
|
||||||
|
// ====================
|
||||||
|
|
||||||
|
$.fn.collapse.noConflict = function () {
|
||||||
|
$.fn.collapse = old
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// COLLAPSE DATA-API
|
||||||
|
// =================
|
||||||
|
|
||||||
|
$(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) {
|
||||||
|
var $this = $(this)
|
||||||
|
|
||||||
|
if (!$this.attr('data-target')) e.preventDefault()
|
||||||
|
|
||||||
|
var $target = getTargetFromTrigger($this)
|
||||||
|
var data = $target.data('bs.collapse')
|
||||||
|
var option = data ? 'toggle' : $this.data()
|
||||||
|
|
||||||
|
Plugin.call($target, option)
|
||||||
|
})
|
||||||
|
|
||||||
|
}(jQuery);
|
7
js/moment.min.js
vendored
Normal file
7
js/moment.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
59
js/transition.js
Normal file
59
js/transition.js
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
/* ========================================================================
|
||||||
|
* Bootstrap: transition.js v3.3.4
|
||||||
|
* http://getbootstrap.com/javascript/#transitions
|
||||||
|
* ========================================================================
|
||||||
|
* Copyright 2011-2015 Twitter, Inc.
|
||||||
|
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||||
|
* ======================================================================== */
|
||||||
|
|
||||||
|
|
||||||
|
+function ($) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
// CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/)
|
||||||
|
// ============================================================
|
||||||
|
|
||||||
|
function transitionEnd() {
|
||||||
|
var el = document.createElement('bootstrap')
|
||||||
|
|
||||||
|
var transEndEventNames = {
|
||||||
|
WebkitTransition : 'webkitTransitionEnd',
|
||||||
|
MozTransition : 'transitionend',
|
||||||
|
OTransition : 'oTransitionEnd otransitionend',
|
||||||
|
transition : 'transitionend'
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var name in transEndEventNames) {
|
||||||
|
if (el.style[name] !== undefined) {
|
||||||
|
return { end: transEndEventNames[name] }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false // explicit for ie8 ( ._.)
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://blog.alexmaccaw.com/css-transitions
|
||||||
|
$.fn.emulateTransitionEnd = function (duration) {
|
||||||
|
var called = false
|
||||||
|
var $el = this
|
||||||
|
$(this).one('bsTransitionEnd', function () { called = true })
|
||||||
|
var callback = function () { if (!called) $($el).trigger($.support.transition.end) }
|
||||||
|
setTimeout(callback, duration)
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
$(function () {
|
||||||
|
$.support.transition = transitionEnd()
|
||||||
|
|
||||||
|
if (!$.support.transition) return
|
||||||
|
|
||||||
|
$.event.special.bsTransitionEnd = {
|
||||||
|
bindType: $.support.transition.end,
|
||||||
|
delegateType: $.support.transition.end,
|
||||||
|
handle: function (e) {
|
||||||
|
if ($(e.target).is(this)) return e.handleObj.handler.apply(this, arguments)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
}(jQuery);
|
Loading…
Reference in a new issue