Fix Conflicts:

bower.json
This commit is contained in:
Gustavo Cortez 2014-06-13 15:01:32 -03:00
commit 8c2a784d86
20 changed files with 415 additions and 251 deletions

View file

@ -1,3 +1,4 @@
[![Stories in Ready](https://badge.waffle.io/bitpay/copay.png?label=ready&title=Ready)](https://waffle.io/bitpay/copay)
# Copay # Copay
[![Build Status](https://secure.travis-ci.org/bitpay/copay.png)](http://travis-ci.org/bitpay/copay) [![Build Status](https://secure.travis-ci.org/bitpay/copay.png)](http://travis-ci.org/bitpay/copay)
[![Coverage Status](https://coveralls.io/repos/bitpay/copay/badge.png?branch=)](https://coveralls.io/r/bitpay/copay?branch=) [![Coverage Status](https://coveralls.io/repos/bitpay/copay/badge.png?branch=)](https://coveralls.io/r/bitpay/copay?branch=)

View file

@ -18,7 +18,7 @@
"sjcl": "1.0.0", "sjcl": "1.0.0",
"file-saver": "*", "file-saver": "*",
"qrcode-decoder-js": "*", "qrcode-decoder-js": "*",
"bitcore": "~0.1.24", "bitcore": "0.1.24",
"angular-moment": "~0.7.1", "angular-moment": "~0.7.1",
"socket.io-client": ">=1.0.0", "socket.io-client": ">=1.0.0",
"mousetrap": "1.4.6" "mousetrap": "1.4.6"

View file

@ -422,6 +422,14 @@ hr { margin: 2.25rem 0;}
background: #C0392B; background: #C0392B;
} }
.box-note {
text-align: center;
clear: both;
font-style: italic;
color: gray;
margin-bottom: 10px;
}
.box-signin { .box-signin {
padding: 20px 40px; padding: 20px 40px;
border: 1px solid #eee; border: 1px solid #eee;
@ -478,6 +486,32 @@ a.loading {
vertical-align:middle vertical-align:middle
} }
@-webkit-keyframes yellow-flash {
0% {
background-color: #FFFFE0;
opacity:1;
}
22% {
background-color: #FFFFE0;
}
100% {
background-color: none;
}
}
.highlight{
-webkit-animation-name: yellow-flash;
-webkit-animation-duration: 400ms;
-webkit-animation-iteration-count: 1;
-webkit-animation-timing-function: linear;
-moz-animation-name: yellow-flash;
-moz-animation-duration: 400ms;
-moz-animation-iteration-count: 1;
-moz-animation-timing-function: linear;
}
/* notifications */ /* notifications */
.dr-notification-container { .dr-notification-container {

0
failsearch.sh Normal file → Executable file
View file

View file

@ -189,7 +189,7 @@
src="./img/satoshi.gif" src="./img/satoshi.gif"
/> />
<div class="size-12 text-center text-gray" stype="margin-top:4px"> <div class="size-12 text-center text-gray" stype="margin-top:4px">
{{c.nick || 'NN'}} {{c.nick}}
</div> </div>
</div> </div>
</div> </div>
@ -230,7 +230,7 @@
<h3>Join a Wallet in Creation</h3> <h3>Join a Wallet in Creation</h3>
<form name="joinForm" ng-submit="join(joinForm)" novalidate> <form name="joinForm" ng-submit="join(joinForm)" novalidate>
<input type="text" class="form-control" placeholder="Paste wallet secret here" name="connectionId" ng-model="connectionId" wallet-secret required> <input type="text" class="form-control" placeholder="Paste wallet secret here" name="connectionId" ng-model="connectionId" wallet-secret required>
<input type="password" class="form-control" placeholder="Choose your password" name="joinPassword" ng-model="$parent.joinPassword" check-strength="passwordStrength" tooltip="Password strength: {{passwordStrength}}" tooltip-trigger="focus" required> <input type="password" class="form-control" placeholder="Choose your password" name="joinPassword" ng-model="$parent.joinPassword" check-strength="passwordStrength" tooltip-html-unsafe="Password strength: {{passwordStrength}}<br/><small>Tip: Use lower and uppercase, numbers and symbols</small>" tooltip-trigger="focus" required>
<input type="text" class="form-control" placeholder="Your name (optional)" name="nickname" ng-model="nickname"> <input type="text" class="form-control" placeholder="Your name (optional)" name="nickname" ng-model="nickname">
<button type="submit" class="button primary radius" ng-disabled="joinForm.$invalid || loading" loading="Joining">Join</button> <button type="submit" class="button primary radius" ng-disabled="joinForm.$invalid || loading" loading="Joining">Join</button>
</form> </form>
@ -316,7 +316,7 @@
<div class="small-12 medium-6 large-6 columns"> <div class="small-12 medium-6 large-6 columns">
<label>Your Wallet Password <small class="has-tip" tooltip="doesn't need to be shared">Required</small> <label>Your Wallet Password <small class="has-tip" tooltip="doesn't need to be shared">Required</small>
<input type="password" placeholder="Choose your password" class="form-control" <input type="password" placeholder="Choose your password" class="form-control"
ng-model="$parent.walletPassword" check-strength="passwordStrength" tooltip="Password strength: {{passwordStrength}}" tooltip-trigger="focus" required> ng-model="$parent.walletPassword" check-strength="passwordStrength" tooltip-html-unsafe="Password strength: {{passwordStrength}}<br/><small>Tip: Use lower and uppercase, numbers and symbols</small>" tooltip-trigger="focus" required>
</label> </label>
</div> </div>
</div> </div>
@ -399,7 +399,7 @@
<span ng-if="showAll">Show less</span> <span ng-if="showAll">Show less</span>
</a> </a>
</div> </div>
<div class="large-4 medium-4 columns line-dashed-v text-center" ng-show="selectedAddr"> <div class="large-4 medium-4 columns line-dashed-v text-center" highlight-on-change="selectedAddr" ng-show="selectedAddr">
<qrcode size="160" data="{{selectedAddr.address}}"></qrcode> <qrcode size="160" data="{{selectedAddr.address}}"></qrcode>
<p class="m10t"> <p class="m10t">
<strong> <strong>
@ -411,7 +411,8 @@
<i class="fi-bitcoin"></i> <i class="fi-bitcoin"></i>
</span> </span>
</span> </span>
<span ng-if="addrWithFund != selectedAddr.address"> <span ng-if="addrWithFund != selectedAddr.address" style="word-wrap: break-word;">
{{selectedAddr.address}}<br/>
{{selectedAddr.balance || 0}} {{selectedAddr.balance || 0}}
<i class="fi-bitcoin"></i> <i class="fi-bitcoin"></i>
</span> </span>
@ -455,6 +456,9 @@
</div> </div>
<div class="tx-copayers"> <div class="tx-copayers">
<div class="box-note large-12" ng-show="tx.comment">
"{{tx.comment}}" - {{$root.wallet.publicKeyRing.nicknameForCopayer(tx.creator)}}
</div>
<div class="box-copayers" ng-repeat="(cId, actions) in tx.peerActions"> <div class="box-copayers" ng-repeat="(cId, actions) in tx.peerActions">
<figure class="left"> <figure class="left">
@ -665,6 +669,23 @@
</div> </div>
</div> </div>
</div> </div>
<div class="row">
<div class="large-12 medium-6 columns">
<div class="row collapse">
<label for="comment">Note
<small ng-hide="!sendForm.comment.$pristine">optional</small>
<small class="is-valid" ng-show="!sendForm.comment.$invalid && !sendForm.comment.$pristine">valid!</small>
<small class="has-error" ng-show="sendForm.comment.$invalid && !sendForm.comment.$pristine">too long!</small>
</label>
<div class="small-12 columns">
<textarea id="comment" ng-disabled="loading"
name="comment" placeholder="Leave a private message to your copayers" ng-model="comment" ng-maxlength="100"></textarea>
</div>
</div>
</div>
</div>
<div class="row"> <div class="row">
<div class="large-5 columns"> <div class="large-5 columns">
<button type="submit" class="button secondary radius text-center" ng-disabled="sendForm.$invalid || loading" loading="Sending"> <button type="submit" class="button secondary radius text-center" ng-disabled="sendForm.$invalid || loading" loading="Sending">

View file

@ -47,19 +47,18 @@ angular.module('copayApp.controllers').controller('SendController',
var address = form.address.$modelValue; var address = form.address.$modelValue;
var amount = (form.amount.$modelValue * 100000000).toFixed(); // satoshi to string var amount = (form.amount.$modelValue * 100000000).toFixed(); // satoshi to string
var comment = form.comment.$modelValue;
var w = $rootScope.wallet; var w = $rootScope.wallet;
w.createTx(address, amount,function() { w.createTx(address, amount, comment, function() {
$scope.loading = false; $scope.loading = false;
$rootScope.$flashMessage = { message: 'The transaction proposal has been created', type: 'success'}; $rootScope.$flashMessage = { message: 'The transaction proposal has been created', type: 'success'};
$rootScope.$digest(); $rootScope.$digest();
}); });
// reset fields // reset fields
$scope.address = null; $scope.address = $scope.amount = $scope.comment = null;
$scope.amount = null; form.address.$pristine = form.amount.$pristine = form.comment.$pristine = true;
form.address.$pristine = true;
form.amount.$pristine = true;
}; };
// QR code Scanner // QR code Scanner

View file

@ -122,55 +122,47 @@ angular.module('copayApp.directives')
} }
} }
}) })
.directive('highlightOnChange', function() {
return {
restrict: 'A',
link: function(scope, element, attrs) {
scope.$watch(attrs.highlightOnChange, function (newValue, oldValue) {
element.addClass('highlight');
setTimeout(function() { element.removeClass('highlight'); }, 500);
});
}
}
})
.directive('checkStrength', function() { .directive('checkStrength', function() {
return { return {
replace: false, replace: false,
restrict: 'EACM', restrict: 'EACM',
require: 'ngModel', require: 'ngModel',
link: function(scope, element, attrs) { link: function(scope, element, attrs) {
var _grep = function(elems, callback, invert) {
var callbackInverse,
matches = [],
i = 0,
length = elems.length,
callbackExpect = !invert;
// Go through the array, only saving the items
// that pass the validator function
for (; i < length; i++) {
callbackInverse = !callback(elems[i], i);
if (callbackInverse !== callbackExpect) {
matches.push(elems[i]);
}
}
return matches;
};
var strength = { var strength = {
messages: ['too weak', 'weak', 'weak', 'medium', 'strong'], messages: ['very weak', 'weak', 'weak', 'medium', 'strong'],
colors: ['#c0392b', '#e74c3c', '#d35400', '#f39c12', '#27ae60'], colors: ['#c0392b', '#e74c3c', '#d35400', '#f39c12', '#27ae60'],
mesureStrength: function (p) { mesureStrength: function (p) {
var _force = 0; var force = 0;
var _regex = /[$-/:-?{-~!"^_`\[\]]/g; var regex = /[$-/:-?{-~!"^_`\[\]]/g;
var _lowerLetters = /[a-z]+/.test(p); var lowerLetters = /[a-z]+/.test(p);
var _upperLetters = /[A-Z]+/.test(p); var upperLetters = /[A-Z]+/.test(p);
var _numbers = /[0-9]+/.test(p); var numbers = /[0-9]+/.test(p);
var _symbols = _regex.test(p); var symbols = regex.test(p);
var _flags = [_lowerLetters, _upperLetters, _numbers, _symbols]; var flags = [lowerLetters, upperLetters, numbers, symbols];
var _passedMatches = _grep(_flags, function (el) { return el === true; }).length; var passedMatches = flags.filter(function (el) { return !!el; }).length;
_force += 2 * p.length + ((p.length >= 10) ? 1 : 0); force = 2 * p.length + (p.length >= 10 ? 1 : 0);
_force += _passedMatches * 10; force += passedMatches * 10;
// penality (short password) // penality (short password)
_force = (p.length <= 6) ? Math.min(_force, 10) : _force; force = (p.length <= 6) ? Math.min(force, 10) : force;
// penality (poor variety of characters) // penality (poor variety of characters)
_force = (_passedMatches == 1) ? Math.min(_force, 10) : _force; force = (passedMatches == 1) ? Math.min(force, 10) : force;
_force = (_passedMatches == 2) ? Math.min(_force, 20) : _force; force = (passedMatches == 2) ? Math.min(force, 20) : force;
_force = (_passedMatches == 3) ? Math.min(_force, 40) : _force; force = (passedMatches == 3) ? Math.min(force, 40) : force;
return _force; return force;
}, },
getColor: function (s) { getColor: function (s) {
var idx = 0; var idx = 0;

View file

@ -182,7 +182,6 @@ Insight.prototype._request = function(options, callback) {
request.open(options.method, url, true); request.open(options.method, url, true);
request.timeout = 5000; request.timeout = 5000;
request.ontimeout = function() { request.ontimeout = function() {
console.log('Insight timeout...retrying');
setTimeout(function() { setTimeout(function() {
return self._request(options,callback); return self._request(options,callback);
}, self.retryDelay); }, self.retryDelay);
@ -206,9 +205,7 @@ Insight.prototype._request = function(options, callback) {
else { else {
var err= 'Error code: ' + request.status + ' - Status: ' + request.statusText var err= 'Error code: ' + request.status + ' - Status: ' + request.statusText
+ ' - Description: ' + request.responseText; + ' - Description: ' + request.responseText;
console.log('Insight Temporary error (will retry):', err);
setTimeout(function() { setTimeout(function() {
console.log('### Retrying Insight Request....'); //TODO
return self._request(options,callback); return self._request(options,callback);
}, self.retryDelay); }, self.retryDelay);
return callback(new Error(err)); return callback(new Error(err));

View file

@ -58,7 +58,8 @@ PrivateKey.prototype._getHK = function(path) {
if (typeof path === 'undefined') { if (typeof path === 'undefined') {
return this.bip; return this.bip;
} }
return this.bip.derive(path); var ret = this.bip.derive(path);
return ret;
}; };
PrivateKey.prototype.getForPaths = function(paths) { PrivateKey.prototype.getForPaths = function(paths) {

View file

@ -107,7 +107,7 @@ PublicKeyRing.prototype.nicknameForIndex = function(index) {
}; };
PublicKeyRing.prototype.nicknameForCopayer = function(copayerId) { PublicKeyRing.prototype.nicknameForCopayer = function(copayerId) {
return this.nicknameFor[copayerId]; return this.nicknameFor[copayerId] || 'NN';
}; };
PublicKeyRing.prototype.addCopayer = function(newEpk, nickname) { PublicKeyRing.prototype.addCopayer = function(newEpk, nickname) {
@ -151,6 +151,7 @@ PublicKeyRing.prototype.getPubKeys = function(index, isChange) {
pubKeys = pubKeys.map(function(s){return new Buffer(s,'hex');}); pubKeys = pubKeys.map(function(s){return new Buffer(s,'hex');});
} }
return pubKeys; return pubKeys;
}; };

View file

@ -20,6 +20,7 @@ function TxProposal(opts) {
this.sentTs = opts.sentTs || null; this.sentTs = opts.sentTs || null;
this.sentTxid = opts.sentTxid || null; this.sentTxid = opts.sentTxid || null;
this.inputChainPaths = opts.inputChainPaths || []; this.inputChainPaths = opts.inputChainPaths || [];
this.comment = opts.comment || null;
} }
TxProposal.prototype.toObj = function() { TxProposal.prototype.toObj = function() {

View file

@ -92,7 +92,7 @@ Wallet.prototype._handlePublicKeyRing = function(senderId, data, isInbound) {
try{ try{
hasChanged = this.publicKeyRing.merge(inPKR, true); hasChanged = this.publicKeyRing.merge(inPKR, true);
} catch (e){ } catch (e){
console.log('## WALLET ERROR', e); //TODO this.log('## WALLET ERROR', e); //TODO
this.emit('connectionError', e.message); this.emit('connectionError', e.message);
return; return;
} }
@ -620,7 +620,7 @@ Wallet.prototype.getUnspent = function(cb) {
}; };
Wallet.prototype.createTx = function(toAddress, amountSatStr, opts, cb) { Wallet.prototype.createTx = function(toAddress, amountSatStr, comment, opts, cb) {
var self = this; var self = this;
if (typeof opts === 'function') { if (typeof opts === 'function') {
cb = opts; cb = opts;
@ -633,7 +633,7 @@ Wallet.prototype.createTx = function(toAddress, amountSatStr, opts, cb) {
} }
this.getUnspent(function(err, safeUnspent) { this.getUnspent(function(err, safeUnspent) {
var ntxid = self.createTxSync(toAddress, amountSatStr, safeUnspent, opts); var ntxid = self.createTxSync(toAddress, amountSatStr, comment, safeUnspent, opts);
if (ntxid) { if (ntxid) {
self.sendIndexes(); self.sendIndexes();
self.sendTxProposals(null, ntxid); self.sendTxProposals(null, ntxid);
@ -644,7 +644,7 @@ Wallet.prototype.createTx = function(toAddress, amountSatStr, opts, cb) {
}); });
}; };
Wallet.prototype.createTxSync = function(toAddress, amountSatStr, utxos, opts) { Wallet.prototype.createTxSync = function(toAddress, amountSatStr, comment, utxos, opts) {
var pkr = this.publicKeyRing; var pkr = this.publicKeyRing;
var priv = this.privateKey; var priv = this.privateKey;
opts = opts || {}; opts = opts || {};
@ -655,6 +655,10 @@ Wallet.prototype.createTxSync = function(toAddress, amountSatStr, utxos, opts) {
throw new Error('publicKeyRing is not complete'); throw new Error('publicKeyRing is not complete');
} }
if (comment && comment.length > 100) {
throw new Error("comment can't be longer that 100 characters");
}
if (!opts.remainderOut) { if (!opts.remainderOut) {
opts.remainderOut = { opts.remainderOut = {
address: this._doGenerateAddress(true).toString() address: this._doGenerateAddress(true).toString()
@ -695,6 +699,7 @@ Wallet.prototype.createTxSync = function(toAddress, amountSatStr, utxos, opts) {
creator: myId, creator: myId,
createdTs: now, createdTs: now,
builder: b, builder: b,
comment: comment
}; };
var ntxid = this.txProposals.add(data); var ntxid = this.txProposals.add(data);

View file

@ -138,7 +138,7 @@ angular.module('copayApp.services')
var myCopayerId = w.getMyCopayerId(); var myCopayerId = w.getMyCopayerId();
var pendingForUs = 0; var pendingForUs = 0;
var inT = w.getTxProposals().sort(function(t1, t2) { return t1.createdTs < t2.createdTs }); var inT = w.getTxProposals().sort(function(t1, t2) { return t2.createdTs - t1.createdTs });
var txs = []; var txs = [];
inT.forEach(function(i, index){ inT.forEach(function(i, index){

View file

@ -28,7 +28,7 @@
"homepage": "https://github.com/bitpay/copay", "homepage": "https://github.com/bitpay/copay",
"devDependencies": { "devDependencies": {
"async": "0.9.0", "async": "0.9.0",
"bitcore": "git://github.com/bitpay/bitcore.git#e71cdb3bb2b7cd9dea69046d275ecc34ff3dd838", "bitcore": "0.1.24",
"blanket": "1.1.6", "blanket": "1.1.6",
"browser-pack": "2.0.1", "browser-pack": "2.0.1",
"browserify": "3.32.1", "browserify": "3.32.1",

View file

@ -12,12 +12,11 @@
<script src="../node_modules/chai/chai.js"></script> <script src="../node_modules/chai/chai.js"></script>
<script src="../lib/crypto-js/rollups/aes.js"></script> <script src="../lib/crypto-js/rollups/aes.js"></script>
<script>mocha.setup('bdd')</script> <script>mocha.setup('bdd')</script>
<script src="../lib/bitcore.js"></script> <script src="../lib/bitcore/browser/bundle.js"></script>
<script src="../js/copayBundle.js"></script> <script src="../js/copayBundle.js"></script>
<script> <script>
var copay = require('copay'); var copay = require('copay');
</script> </script>
<script src="test.API.js"></script>
<script src="test.blockchain.Insight.js"></script> <script src="test.blockchain.Insight.js"></script>
<script src="test.performance.js"></script> <script src="test.performance.js"></script>
<script src="test.PrivateKey.js"></script> <script src="test.PrivateKey.js"></script>

View file

@ -1,64 +1,63 @@
'use strict'; 'use strict';
var chai = chai || require('chai'); var chai = chai || require('chai');
var should = chai.should(); var should = chai.should();
var bitcore = bitcore || require('bitcore'); var bitcore = bitcore || require('bitcore');
var Transaction = bitcore.Transaction; var Transaction = bitcore.Transaction;
var buffertools = bitcore.buffertools; var buffertools = bitcore.buffertools;
var WalletKey = bitcore.WalletKey; var WalletKey = bitcore.WalletKey;
var Key = bitcore.Key; var Key = bitcore.Key;
var bignum = bitcore.bignum; var bignum = bitcore.bignum;
var Script = bitcore.Script; var Script = bitcore.Script;
var Builder = bitcore.TransactionBuilder; var Builder = bitcore.TransactionBuilder;
var util = bitcore.util; var util = bitcore.util;
var networks = bitcore.networks; var networks = bitcore.networks;
var copay = copay || require('../copay'); var copay = copay || require('../copay');
var fakeStorage = copay.FakeStorage; var fakeStorage = copay.FakeStorage;
var PrivateKey = copay.PrivateKey || require('../js/models/PrivateKey'); var PrivateKey = copay.PrivateKey || require('../js/models/PrivateKey');
var TxProposals = copay.TxProposals || require('../js/models/TxProposal'); var TxProposals = copay.TxProposals || require('../js/models/TxProposal');
var PublicKeyRing = is_browser ? copay.PublicKeyRing : var PublicKeyRing = is_browser ? copay.PublicKeyRing :
require('soop').load('../js/models/core/PublicKeyRing', {Storage: fakeStorage}); require('soop').load('../js/models/core/PublicKeyRing', {
var is_browser = (typeof process.versions === 'undefined') Storage: fakeStorage
});
var is_browser = (typeof process.versions === 'undefined')
var config = { var config = {
networkName:'livenet', networkName: 'testnet',
}; };
var unspentTest = [ var unspentTest = [{
{ "address": "dummy",
"address": "dummy", "scriptPubKey": "dummy",
"scriptPubKey": "dummy", "txid": "2ac165fa7a3a2b535d106a0041c7568d03b531e58aeccdd3199d7289ab12cfc1",
"txid": "2ac165fa7a3a2b535d106a0041c7568d03b531e58aeccdd3199d7289ab12cfc1", "vout": 1,
"vout": 1, "amount": 10,
"amount": 10, "confirmations": 7
"confirmations":7 }];
}
];
var createPKR = function (bip32s) { var createPKR = function(bip32s) {
var w = new PublicKeyRing(config); var w = new PublicKeyRing(config);
should.exist(w); should.exist(w);
for(var i=0; i<5; i++) { for (var i = 0; i < 5; i++) {
if (bip32s) { if (bip32s && i < bip32s.length) {
var b=bip32s[i]; var b = bip32s[i];
w.addCopayer(b?b.deriveBIP45Branch().extendedPublicKeyString():null); w.addCopayer(b.deriveBIP45Branch().extendedPublicKeyString());
} } else {
else
w.addCopayer(); w.addCopayer();
}
} }
w.generateAddress(true); w.generateAddress(false);
w.generateAddress(true); w.generateAddress(false);
w.generateAddress(true); w.generateAddress(false);
w.generateAddress(false); w.generateAddress(true);
w.generateAddress(false); w.generateAddress(true);
w.generateAddress(false); w.generateAddress(true);
//3x3 indexes
return w; return w;
}; };
var vopts = { var vopts = {
verifyP2SH: true, verifyP2SH: true,
dontVerifyStrictEnc: true dontVerifyStrictEnc: true
}; };
@ -66,25 +65,29 @@ var vopts = {
describe('TxProposals model', function() { describe('TxProposals model', function() {
it('verify TXs', function (done) { it('verify TXs', function(done) {
var priv = new PrivateKey(config); var priv = new PrivateKey(config);
var priv2 = new PrivateKey(config); var priv2 = new PrivateKey(config);
var priv3 = new PrivateKey(config); var priv3 = new PrivateKey(config);
var ts = Date.now(); var ts = Date.now();
var isChange=0; var isChange = 0;
var index=0; var index = 0;
var pkr = createPKR([priv, priv2, priv3]); var pkr = createPKR([priv, priv2, priv3]);
var opts = {remainderOut: { address: pkr.generateAddress(true).toString() }}; var opts = {
remainderOut: {
address: pkr.generateAddress(true).toString()
}
};
var w = new TxProposals({ var w = new TxProposals({
networkName: config.networkName, networkName: config.networkName,
}); });
unspentTest[0].address = pkr.getAddress(index, isChange).toString(); unspentTest[0].address = pkr.getAddress(index, isChange).toString();
unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange); unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange);
w.add(createTx( w.add(createTx(
'15q6HKjWHAksHcH91JW23BJEuzZgFwydBt', '15q6HKjWHAksHcH91JW23BJEuzZgFwydBt',
'123456789', '123456789',
unspentTest, unspentTest,
opts, opts,
priv, priv,
@ -94,83 +97,87 @@ describe('TxProposals model', function() {
var b = w.txps[k].builder; var b = w.txps[k].builder;
var tx = b.build(); var tx = b.build();
tx.isComplete().should.equal(false); tx.isComplete().should.equal(false);
b.sign(priv2.getAll(pkr.indexes.getReceiveIndex(), pkr.indexes.getChangeIndex()) ); b.sign(priv2.getAll(pkr.indexes.getReceiveIndex(), pkr.indexes.getChangeIndex()));
b.sign(priv3.getAll(pkr.indexes.getReceiveIndex(), pkr.indexes.getChangeIndex()) ); b.sign(priv3.getAll(pkr.indexes.getReceiveIndex(), pkr.indexes.getChangeIndex()));
tx = b.build(); tx = b.build();
tx.isComplete().should.equal(true); tx.isComplete().should.equal(true);
var s = new Script(new Buffer(unspentTest[0].scriptPubKey,'hex')); var s = new Script(new Buffer(unspentTest[0].scriptPubKey, 'hex'));
tx.verifyInput(0,s, { tx.verifyInput(0, s, {
verifyP2SH: true, verifyP2SH: true,
dontVerifyStrictEnc: true dontVerifyStrictEnc: true
}, function(err, results){ }, function(err, results) {
should.not.exist(err); should.not.exist(err);
results.should.equal(true); results.should.equal(true);
done(); done();
}); });
}); });
it('should create an instance', function () {
it('should create an instance', function() {
var w = new TxProposals({ var w = new TxProposals({
networkName: config.networkName networkName: config.networkName
}); });
should.exist(w); should.exist(w);
w.network.name.should.equal('livenet'); w.network.name.should.equal(config.networkName);
}); });
function createTx(toAddress, amountSatStr, utxos, opts, priv, pkr) { var createTx = function(toAddress, amountSatStr, utxos, opts, priv, pkr) {
opts = opts || {}; opts = opts || {};
var amountSat = bitcore.bignum(amountSatStr); var amountSat = bitcore.bignum(amountSatStr);
if(! pkr.isComplete() ) { if (!pkr.isComplete()) {
throw new Error('publicKeyRing is not complete'); throw new Error('publicKeyRing is not complete');
} }
if (!opts.remainderOut) { if (!opts.remainderOut) {
opts.remainderOut ={ address: pkr.generateAddress(true).toString() }; opts.remainderOut = {
address: pkr.generateAddress(true).toString()
};
}; };
var b = new Builder(opts) var b = new Builder(opts)
.setUnspent(utxos) .setUnspent(utxos)
.setHashToScriptMap(pkr.getRedeemScriptMap()) .setHashToScriptMap(pkr.getRedeemScriptMap())
.setOutputs([{address: toAddress, amountSat: amountSat}]) .setOutputs([{
; address: toAddress,
amountSat: amountSat
}]);
var signRet; var signRet;
if (priv) { if (priv) {
b.sign( priv.getAll(pkr.indexes.getReceiveIndex(), pkr.indexes.getChangeIndex()) ); var pkeys = priv.getAll(pkr.indexes.getReceiveIndex(), pkr.indexes.getChangeIndex());
b.sign(pkeys);
} }
var me = {}; var me = {};
if (priv) me[priv.id] = Date.now(); if (priv) me[priv.id] = Date.now();
return { return {
signedBy: priv && b.signaturesAdded ? me : {}, signedBy: priv && b.signaturesAdded ? me : {},
seenBy: priv ? me : {}, seenBy: priv ? me : {},
builder: b, builder: b,
}; };
}; };
it('#getUsedUnspend', function () { it('#getUsedUnspend', function() {
var priv = new PrivateKey(config); var priv = new PrivateKey(config);
var w = new TxProposals({ var w = new TxProposals({
networkName: config.networkName, networkName: config.networkName,
}); });
var start = new Date().getTime(); var start = new Date().getTime();
var pkr=createPKR([priv]); var pkr = createPKR([priv]);
var ts = Date.now(); var ts = Date.now();
var isChange=0; var isChange = 0;
var index=0; var index = 0;
unspentTest[0].address = pkr.getAddress(index, isChange).toString(); unspentTest[0].address = pkr.getAddress(index, isChange).toString();
unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange); unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange);
w.add(createTx( w.add(createTx(
'15q6HKjWHAksHcH91JW23BJEuzZgFwydBt', '15q6HKjWHAksHcH91JW23BJEuzZgFwydBt',
'123456789', '123456789',
unspentTest, unspentTest, {},
{},
priv, priv,
pkr pkr
)); ));
@ -180,24 +187,23 @@ describe('TxProposals model', function() {
uuk[0].split(',')[0].should.equal(unspentTest[0].txid); uuk[0].split(',')[0].should.equal(unspentTest[0].txid);
}); });
it('#merge with self', function () { it('#merge with self', function() {
var priv = new PrivateKey(config); var priv = new PrivateKey(config);
var w = new TxProposals({ var w = new TxProposals({
networkName: config.networkName, networkName: config.networkName,
}); });
var start = new Date().getTime(); var start = new Date().getTime();
var pkr=createPKR([priv]); var pkr = createPKR([priv]);
var ts = Date.now(); var ts = Date.now();
var isChange=0; var isChange = 0;
var index=0; var index = 0;
unspentTest[0].address = pkr.getAddress(index, isChange).toString(); unspentTest[0].address = pkr.getAddress(index, isChange).toString();
unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange); unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange);
w.add(createTx( w.add(createTx(
'15q6HKjWHAksHcH91JW23BJEuzZgFwydBt', '15q6HKjWHAksHcH91JW23BJEuzZgFwydBt',
'123456789', '123456789',
unspentTest, unspentTest, {},
{},
priv, priv,
pkr pkr
)); ));
@ -221,24 +227,28 @@ describe('TxProposals model', function() {
it('#merge, merge signatures case 1', function () { it('#merge, merge signatures case 1', function() {
var priv2 = new PrivateKey(config); var priv2 = new PrivateKey(config);
var priv = new PrivateKey(config); var priv = new PrivateKey(config);
var ts = Date.now(); var ts = Date.now();
var isChange=0; var isChange = 0;
var index=0; var index = 0;
var pkr = createPKR([priv]); var pkr = createPKR([priv]);
var opts = {remainderOut: { address: pkr.generateAddress(true).toString() }}; var opts = {
remainderOut: {
address: pkr.generateAddress(true).toString()
}
};
var w = new TxProposals({ var w = new TxProposals({
networkName: config.networkName, networkName: config.networkName,
}); });
unspentTest[0].address = pkr.getAddress(index, isChange).toString(); unspentTest[0].address = pkr.getAddress(index, isChange).toString();
unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange); unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange);
w.add(createTx( w.add(createTx(
'15q6HKjWHAksHcH91JW23BJEuzZgFwydBt', '15q6HKjWHAksHcH91JW23BJEuzZgFwydBt',
'123456789', '123456789',
unspentTest, unspentTest,
opts, opts,
priv2, priv2,
@ -258,11 +268,11 @@ describe('TxProposals model', function() {
networkName: config.networkName, networkName: config.networkName,
publicKeyRing: w.publicKeyRing, publicKeyRing: w.publicKeyRing,
}); });
unspentTest[0].address = pkr.getAddress(index, isChange).toString(); unspentTest[0].address = pkr.getAddress(index, isChange).toString();
unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange); unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange);
w2.add(createTx( w2.add(createTx(
'15q6HKjWHAksHcH91JW23BJEuzZgFwydBt', '15q6HKjWHAksHcH91JW23BJEuzZgFwydBt',
'123456789', '123456789',
unspentTest, unspentTest,
opts, opts,
priv, priv,
@ -285,139 +295,163 @@ describe('TxProposals model', function() {
tx.countInputMissingSignatures(0).should.equal(2); tx.countInputMissingSignatures(0).should.equal(2);
(w.txps[k].signedBy[priv.id] - ts > 0).should.equal(true); (w.txps[k].signedBy[priv.id] - ts > 0).should.equal(true);
(w.txps[k].seenBy[priv.id] - ts > 0).should.equal(true); (w.txps[k].seenBy[priv.id] - ts > 0).should.equal(true);
}); });
var _dumpChunks = function (scriptSig, label) { var _dumpChunks = function(scriptSig, label) {
console.log('## DUMP: ' + label + ' ##'); console.log('## DUMP: ' + label + ' ##');
for(var i=0; i<scriptSig.chunks.length; i++) { for (var i = 0; i < scriptSig.chunks.length; i++) {
console.log('\tCHUNK ', i, scriptSig.chunks[i]); console.log('\tCHUNK ', i, scriptSig.chunks[i]);
} }
}; };
it('#merge, merge signatures case 2', function () { it('#merge, merge signatures case 2', function() {
var priv = new PrivateKey(config); var o1 ={ extendedPrivateKeyString: 'tprv8ZgxMBicQKsPdSF1avR6mXyDj5Uv1XY2UyUHSDpAXQ5TvPN7prGeDppjy4562rBB9gMMAhRfFdJrNDpQ4t69kkqHNEEen3PX1zBJqSehJDH',
var priv2 = new PrivateKey(config); networkName: 'testnet',
var priv3 = new PrivateKey(config); privateKeyCache: {} };
var ts = Date.now(); var o2 ={ extendedPrivateKeyString: 'tprv8ZgxMBicQKsPdVeB5RzuxS9JQcACueZYgUaM5eWzaEBkHjW5Pg6Mqez1APSqoUP1jUdbT8WVG7ZJYTXvUL7XtPzFYBXjmdKuwSor1dcNQ8j',
var isChange=0; networkName: 'testnet',
var index=0; privateKeyCache: {} };
var o3 ={ extendedPrivateKeyString: 'tprv8ZgxMBicQKsPeHWNrPVZtQVgcCtXBr5TACNbDQ56rwqNJce9MEc64US6DJKxpWsrebEomxxWZFDtkvkZGkzA43uLvdF4XHiWqoNaL6Dq2Gd',
networkName: 'testnet',
privateKeyCache: {} };
var priv = PrivateKey.fromObj(o1);
var priv2 = PrivateKey.fromObj(o2);
var priv3 = PrivateKey.fromObj(o3);
var ts = Date.now();
var isChange = 0;
var index = 0;
var pkr = createPKR([priv, priv2]); var pkr = createPKR([priv, priv2]);
var opts = {remainderOut: { address: pkr.generateAddress(true).toString() }}; var opts = {
remainderOut: {
address: '2MxK2m7cPtEwjZBB8Ksq7ppjkgJyFPJGemr'
}
};
var addressToSign = pkr.generateAddress(false);
unspentTest[0].address = addressToSign.toString();
unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange);
var tx, txb;
var w = new TxProposals({ var w = new TxProposals({
networkName: config.networkName, networkName: config.networkName,
}); });
unspentTest[0].address = pkr.getAddress(index, isChange).toString();
unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange);
w.add(createTx( w.add(createTx(
'15q6HKjWHAksHcH91JW23BJEuzZgFwydBt', '15q6HKjWHAksHcH91JW23BJEuzZgFwydBt',
'123456789', '123456789',
unspentTest, unspentTest,
opts, opts,
priv3, priv3,
pkr pkr
)); ));
var k = Object.keys(w.txps)[0]; var ntxid = Object.keys(w.txps)[0];
var tx = w.txps[k].builder.build(); txb = w.txps[ntxid].builder;
txb.signaturesAdded.should.equal(0);
tx = txb.build();
tx.isComplete().should.equal(false); tx.isComplete().should.equal(false);
tx.countInputMissingSignatures(0).should.equal(1); tx.countInputMissingSignatures(0).should.equal(1);
Object.keys(w.txps[k].signedBy).length.should.equal(0); Object.keys(w.txps[ntxid].signedBy).length.should.equal(0);
Object.keys(w.txps[k].seenBy).length.should.equal(1); Object.keys(w.txps[ntxid].seenBy).length.should.equal(1);
var w2 = new TxProposals({ var w2 = new TxProposals({
networkName: config.networkName, networkName: config.networkName,
}); });
unspentTest[0].address = pkr.getAddress(index, isChange).toString();
unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange);
w2.add(createTx( w2.add(createTx(
'15q6HKjWHAksHcH91JW23BJEuzZgFwydBt', '15q6HKjWHAksHcH91JW23BJEuzZgFwydBt',
'123456789', '123456789',
unspentTest, unspentTest,
opts, opts,
priv, priv,
pkr pkr
)); ));
var k = Object.keys(w2.txps)[0]; var ntxid = Object.keys(w2.txps)[0];
tx = w2.txps[k].builder.build(); txb = w2.txps[ntxid].builder;
tx = txb.build();
txb.signaturesAdded.should.equal(1);
tx.isComplete().should.equal(false); tx.isComplete().should.equal(false);
tx.countInputMissingSignatures(0).should.equal(2); tx.countInputMissingSignatures(0).should.equal(2);
(w2.txps[k].signedBy[priv.id] - ts > 0).should.equal(true); (w2.txps[ntxid].signedBy[priv.id] - ts > 0).should.equal(true);
(w2.txps[k].seenBy[priv.id] - ts > 0).should.equal(true); (w2.txps[ntxid].seenBy[priv.id] - ts > 0).should.equal(true);
w.merge(w2); w.merge(w2);
Object.keys(w.txps).length.should.equal(1); Object.keys(w.txps).length.should.equal(1);
tx = w.txps[k].builder.build(); tx = w.txps[ntxid].builder.build();
tx.isComplete().should.equal(false); tx.isComplete().should.equal(false);
tx.countInputMissingSignatures(0).should.equal(2); tx.countInputMissingSignatures(0).should.equal(2);
(w.txps[k].signedBy[priv.id] - ts > 0).should.equal(true); (w.txps[ntxid].signedBy[priv.id] - ts > 0).should.equal(true);
(w.txps[k].seenBy[priv.id] - ts > 0).should.equal(true); (w.txps[ntxid].seenBy[priv.id] - ts > 0).should.equal(true);
var w3 = new TxProposals({ var w3 = new TxProposals({
networkName: config.networkName, networkName: config.networkName,
publicKeyRing: pkr, publicKeyRing: pkr,
}); });
unspentTest[0].address = pkr.getAddress(index, isChange).toString();
unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange);
w3.add(createTx( w3.add(createTx(
'15q6HKjWHAksHcH91JW23BJEuzZgFwydBt', '15q6HKjWHAksHcH91JW23BJEuzZgFwydBt',
'123456789', '123456789',
unspentTest, unspentTest,
opts, opts,
priv2, priv2,
pkr pkr
)); ));
tx = w3.txps[k].builder.build(); tx = w3.txps[ntxid].builder.build();
tx.isComplete().should.equal(false); tx.isComplete().should.equal(false);
tx.countInputMissingSignatures(0).should.equal(2); tx.countInputMissingSignatures(0).should.equal(2);
(w3.txps[k].signedBy[priv2.id] - ts > 0).should.equal(true); (w3.txps[ntxid].signedBy[priv2.id] - ts > 0).should.equal(true);
(w3.txps[k].seenBy[priv2.id] - ts > 0).should.equal(true); (w3.txps[ntxid].seenBy[priv2.id] - ts > 0).should.equal(true);
w.merge(w3); w.merge(w3);
Object.keys(w.txps).length.should.equal(1); Object.keys(w.txps).length.should.equal(1);
(w.txps[k].signedBy[priv.id] - ts > 0).should.equal(true); (w.txps[ntxid].signedBy[priv.id] - ts > 0).should.equal(true);
(w.txps[k].seenBy[priv.id] - ts > 0).should.equal(true); (w.txps[ntxid].seenBy[priv.id] - ts > 0).should.equal(true);
(w.txps[k].signedBy[priv2.id] - ts > 0).should.equal(true); (w.txps[ntxid].signedBy[priv2.id] - ts > 0).should.equal(true);
(w.txps[k].seenBy[priv2.id] - ts > 0).should.equal(true); (w.txps[ntxid].seenBy[priv2.id] - ts > 0).should.equal(true);
tx = w.txps[k].builder.build(); tx = w.txps[ntxid].builder.build();
tx.isComplete().should.equal(false); tx.isComplete().should.equal(false);
tx.countInputMissingSignatures(0).should.equal(1); tx.countInputMissingSignatures(0).should.equal(1);
}); });
it('#merge, merge signatures case 3', function () { it('#merge, merge signatures case 3', function() {
var priv = new PrivateKey(config); var priv = new PrivateKey(config);
var priv2 = new PrivateKey(config); var priv2 = new PrivateKey(config);
var priv3 = new PrivateKey(config); var priv3 = new PrivateKey(config);
var ts = Date.now(); var ts = Date.now();
var isChange=0; var isChange = 0;
var index=0; var index = 0;
var pkr = createPKR([priv, priv2, priv3]); var pkr = createPKR([priv, priv2, priv3]);
var opts = {remainderOut: { address: pkr.generateAddress(true).toString() }}; var opts = {
remainderOut: {
address: pkr.generateAddress(true).toString()
}
};
var w = new TxProposals({ var w = new TxProposals({
networkName: config.networkName, networkName: config.networkName,
}); });
unspentTest[0].address = pkr.getAddress(index, isChange).toString(); unspentTest[0].address = pkr.getAddress(index, isChange).toString();
unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange); unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange);
w.add(createTx( w.add(createTx(
'15q6HKjWHAksHcH91JW23BJEuzZgFwydBt', '15q6HKjWHAksHcH91JW23BJEuzZgFwydBt',
'123456789', '123456789',
unspentTest, unspentTest,
opts, opts,
priv, priv,
@ -434,11 +468,11 @@ var _dumpChunks = function (scriptSig, label) {
var w2 = new TxProposals({ var w2 = new TxProposals({
networkName: config.networkName, networkName: config.networkName,
}); });
unspentTest[0].address = pkr.getAddress(index, isChange).toString(); unspentTest[0].address = pkr.getAddress(index, isChange).toString();
unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange); unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange);
w2.add(createTx( w2.add(createTx(
'15q6HKjWHAksHcH91JW23BJEuzZgFwydBt', '15q6HKjWHAksHcH91JW23BJEuzZgFwydBt',
'123456789', '123456789',
unspentTest, unspentTest,
opts, opts,
priv2, priv2,
@ -454,11 +488,11 @@ var _dumpChunks = function (scriptSig, label) {
var w3 = new TxProposals({ var w3 = new TxProposals({
networkName: config.networkName, networkName: config.networkName,
}); });
unspentTest[0].address = pkr.getAddress(index, isChange).toString(); unspentTest[0].address = pkr.getAddress(index, isChange).toString();
unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange); unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange);
w3.add(createTx( w3.add(createTx(
'15q6HKjWHAksHcH91JW23BJEuzZgFwydBt', '15q6HKjWHAksHcH91JW23BJEuzZgFwydBt',
'123456789', '123456789',
unspentTest, unspentTest,
opts, opts,
priv3, priv3,
@ -496,7 +530,7 @@ var _dumpChunks = function (scriptSig, label) {
it('#toObj #fromObj roundtrip', function () { it('#toObj #fromObj roundtrip', function() {
var priv = new PrivateKey(config); var priv = new PrivateKey(config);
var pkr = createPKR([priv]); var pkr = createPKR([priv]);
@ -505,16 +539,15 @@ var _dumpChunks = function (scriptSig, label) {
networkName: config.networkName, networkName: config.networkName,
}); });
var ts = Date.now(); var ts = Date.now();
var isChange=0; var isChange = 0;
var index=0; var index = 0;
unspentTest[0].address = pkr.getAddress(index, isChange).toString(); unspentTest[0].address = pkr.getAddress(index, isChange).toString();
unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange); unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange);
w.add(createTx( w.add(createTx(
'15q6HKjWHAksHcH91JW23BJEuzZgFwydBt', '15q6HKjWHAksHcH91JW23BJEuzZgFwydBt',
'123456789', '123456789',
unspentTest, unspentTest, {},
{},
priv, priv,
pkr pkr
)); ));
@ -545,7 +578,7 @@ var _dumpChunks = function (scriptSig, label) {
(w2.txps[k].seenBy[priv.id] - ts > 0).should.equal(true); (w2.txps[k].seenBy[priv.id] - ts > 0).should.equal(true);
should.exist(w2.txps[k].builder); should.exist(w2.txps[k].builder);
should.exist(w2.txps[k].builder.valueInSat); should.exist(w2.txps[k].builder.valueInSat);
w2.merge(w); w2.merge(w);
Object.keys(w2.txps).length.should.equal(1); Object.keys(w2.txps).length.should.equal(1);
}); });

View file

@ -140,6 +140,7 @@ describe('Wallet model', function() {
var ntxid = w.createTxSync( var ntxid = w.createTxSync(
'15q6HKjWHAksHcH91JW23BJEuzZgFwydBt', '15q6HKjWHAksHcH91JW23BJEuzZgFwydBt',
'123456789', '123456789',
null,
unspentTest unspentTest
); );
@ -147,11 +148,54 @@ describe('Wallet model', function() {
var txp = t.txps[ntxid]; var txp = t.txps[ntxid];
var tx = txp.builder.build(); var tx = txp.builder.build();
should.exist(tx); should.exist(tx);
chai.expect(txp.comment).to.be.null;
tx.isComplete().should.equal(false); tx.isComplete().should.equal(false);
Object.keys(txp.seenBy).length.should.equal(1); Object.keys(txp.seenBy).length.should.equal(1);
Object.keys(txp.signedBy).length.should.equal(1); Object.keys(txp.signedBy).length.should.equal(1);
}); });
it('#create with comment', function() {
var w = createW2();
var comment = 'This is a comment';
unspentTest[0].address = w.publicKeyRing.getAddress(1, true).toString();
unspentTest[0].scriptPubKey = w.publicKeyRing.getScriptPubKeyHex(1, true);
var ntxid = w.createTxSync(
'15q6HKjWHAksHcH91JW23BJEuzZgFwydBt',
'123456789',
comment,
unspentTest
);
var t = w.txProposals;
var txp = t.txps[ntxid];
var tx = txp.builder.build();
should.exist(tx);
txp.comment.should.equal(comment);
});
it('#create throw exception on long comment', function() {
var w = createW2();
var comment = 'Lorem ipsum dolor sit amet, suas euismod vis te, velit deleniti vix an. Pri ex suscipit similique, inermis per';
unspentTest[0].address = w.publicKeyRing.getAddress(1, true).toString();
unspentTest[0].scriptPubKey = w.publicKeyRing.getScriptPubKeyHex(1, true);
var badCreate = function() {
w.createTxSync(
'15q6HKjWHAksHcH91JW23BJEuzZgFwydBt',
'123456789',
comment,
unspentTest
);
}
chai.expect(badCreate).to.throw(Error);
});
it('#addressIsOwn', function() { it('#addressIsOwn', function() {
var w = createW2(); var w = createW2();
var l = w.getAddressesStr(); var l = w.getAddressesStr();
@ -178,6 +222,7 @@ describe('Wallet model', function() {
w.createTxSync( w.createTxSync(
'15q6HKjWHAksHcH91JW23BJEuzZgFwydBt', '15q6HKjWHAksHcH91JW23BJEuzZgFwydBt',
'123456789', '123456789',
null,
unspentTest unspentTest
); );
var t = w.txProposals; var t = w.txProposals;
@ -428,7 +473,7 @@ describe('Wallet model', function() {
var w = createW2(); var w = createW2();
var utxo = createUTXO(w); var utxo = createUTXO(w);
w.blockchain.fixUnspent(utxo); w.blockchain.fixUnspent(utxo);
w.createTx(toAddress, amountSatStr, function(ntxid) { w.createTx(toAddress, amountSatStr, null, function(ntxid) {
ntxid.length.should.equal(64); ntxid.length.should.equal(64);
done(); done();
}); });
@ -439,7 +484,7 @@ describe('Wallet model', function() {
w.privateKey = null; w.privateKey = null;
var utxo = createUTXO(w); var utxo = createUTXO(w);
w.blockchain.fixUnspent(utxo); w.blockchain.fixUnspent(utxo);
w.createTx(toAddress, amountSatStr, function(ntxid) { w.createTx(toAddress, amountSatStr, null, function(ntxid) {
w.on('txProposalsUpdated', function() { w.on('txProposalsUpdated', function() {
w.getTxProposals()[0].signedByUs.should.equal(true); w.getTxProposals()[0].signedByUs.should.equal(true);
w.getTxProposals()[0].rejectedByUs.should.equal(false); w.getTxProposals()[0].rejectedByUs.should.equal(false);
@ -456,7 +501,7 @@ describe('Wallet model', function() {
w.privateKey = null; w.privateKey = null;
var utxo = createUTXO(w); var utxo = createUTXO(w);
w.blockchain.fixUnspent(utxo); w.blockchain.fixUnspent(utxo);
w.createTx(toAddress, amountSatStr, function(ntxid) { w.createTx(toAddress, amountSatStr, null, function(ntxid) {
w.on('txProposalsUpdated', function() { w.on('txProposalsUpdated', function() {
w.getTxProposals()[0].signedByUs.should.equal(false); w.getTxProposals()[0].signedByUs.should.equal(false);
w.getTxProposals()[0].rejectedByUs.should.equal(true); w.getTxProposals()[0].rejectedByUs.should.equal(true);
@ -470,7 +515,7 @@ describe('Wallet model', function() {
var w = createW2(null, 1); var w = createW2(null, 1);
var utxo = createUTXO(w); var utxo = createUTXO(w);
w.blockchain.fixUnspent(utxo); w.blockchain.fixUnspent(utxo);
w.createTx(toAddress, amountSatStr, function(ntxid) { w.createTx(toAddress, amountSatStr, null, function(ntxid) {
w.sendTx(ntxid, function(txid) { w.sendTx(ntxid, function(txid) {
txid.length.should.equal(64); txid.length.should.equal(64);
done(); done();

View file

@ -46,13 +46,13 @@ if (typeof process === 'undefined' || !process.version) {
}); });
}); });
describe('#getEncryptedObj', function() { describe('#export', function() {
it('should encrypt the wallet', function() { it('should export the encrypted wallet', function() {
localStorage.clear(); localStorage.clear();
var storage = new LocalEncrypted({password: 'password'}); var storage = new LocalEncrypted({password: 'password'});
storage.set('walletId', 'test', 'testval'); storage.set('walletId', 'test', 'testval');
var obj = {test:'testval'}; var obj = {test:'testval'};
var encrypted = storage.getEncryptedObj('walletId'); var encrypted = storage.export(obj);
encrypted.length.should.be.greaterThan(10); encrypted.length.should.be.greaterThan(10);
//encrypted.slice(0,6).should.equal("53616c"); //encrypted.slice(0,6).should.equal("53616c");
}); });

View file

@ -65,4 +65,39 @@ describe("Unit: Testing Directives", function() {
}); });
}); });
describe('Password strength', function() {
beforeEach(inject(function($compile, $rootScope) {
$scope = $rootScope;
var element = angular.element(
'<input type="password" name="password" ng-model="password" check-strength="passwordStrength" value="asd" required>'
);
$compile(element)($scope);
$scope.$digest();
}));
it('should check very weak password', function() {
$scope.password = 'asd';
$scope.$digest();
expect($scope.passwordStrength).to.equal('very weak');
});
it('should check weak password', function() {
$scope.password = 'asdasdASDASD';
$scope.$digest();
expect($scope.passwordStrength).to.equal('weak');
});
it('should check medium password', function() {
$scope.password = 'asdasdASDASD1';
$scope.$digest();
expect($scope.passwordStrength).to.equal('medium');
});
it('should check strong password', function() {
$scope.password = 'asdasdASDASD1{';
$scope.$digest();
expect($scope.passwordStrength).to.equal('strong');
});
});
}); });

View file

@ -80,7 +80,7 @@ for (var n = 1; n <= N_LIMIT; n++) {
'amount': 10.0, 'amount': 10.0,
'confirmations': 2 'confirmations': 2
}]; }];
var ntxid = w.createTxSync(toAddress, amount, utxos); var ntxid = w.createTxSync(toAddress, amount, null, utxos);
var txp = w.txProposals.txps[ntxid]; var txp = w.txProposals.txps[ntxid];
var signTx = function(pk, cb) { var signTx = function(pk, cb) {