mirror of https://github.com/BTCPrivate/copay.git
fix conflicts
This commit is contained in:
commit
74f7271310
|
@ -28,15 +28,6 @@ npm-debug.log
|
||||||
|
|
||||||
.DS_Store
|
.DS_Store
|
||||||
public/lib/*
|
public/lib/*
|
||||||
db/txs/*
|
|
||||||
db/txs
|
|
||||||
db/testnet/txs/*
|
|
||||||
db/testnet/txs
|
|
||||||
db/blocks/*
|
|
||||||
db/blocks
|
|
||||||
db/testnet/blocks/*
|
|
||||||
db/testnet/blocks
|
|
||||||
|
|
||||||
public/js/angularjs-all.js
|
public/js/angularjs-all.js
|
||||||
public/js/main.js
|
public/js/main.js
|
||||||
public/js/vendors.js
|
public/js/vendors.js
|
||||||
|
@ -49,3 +40,4 @@ lib/*
|
||||||
!lib/socket.io.js
|
!lib/socket.io.js
|
||||||
|
|
||||||
js/copayBundle.js
|
js/copayBundle.js
|
||||||
|
js/config.js
|
||||||
|
|
17
css/main.css
17
css/main.css
|
@ -58,7 +58,6 @@ body {
|
||||||
.header {
|
.header {
|
||||||
background: #111;
|
background: #111;
|
||||||
color: white;
|
color: white;
|
||||||
overflow: hidden;
|
|
||||||
margin-bottom: 30px;
|
margin-bottom: 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,6 +70,10 @@ body {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.top-bar {
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
.panel {
|
.panel {
|
||||||
color: #333;
|
color: #333;
|
||||||
background: #FFFFFF;
|
background: #FFFFFF;
|
||||||
|
@ -164,7 +167,7 @@ span.panel-res {
|
||||||
color: #FBE500;
|
color: #FBE500;
|
||||||
}
|
}
|
||||||
|
|
||||||
.alert-box.warning {
|
.alert-box.warning, .alert-box.error {
|
||||||
background-color: #C0392A;
|
background-color: #C0392A;
|
||||||
border-color: #C0392A;
|
border-color: #C0392A;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
|
@ -174,6 +177,14 @@ span.panel-res {
|
||||||
color:#C0392A;
|
color:#C0392A;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
small.is-valid {
|
||||||
|
color: #04B404;
|
||||||
|
}
|
||||||
|
|
||||||
|
small.has-error {
|
||||||
|
color: #f04124;
|
||||||
|
}
|
||||||
|
|
||||||
hr { margin: 2.25rem 0;}
|
hr { margin: 2.25rem 0;}
|
||||||
|
|
||||||
button.primary { background-color: #111; }
|
button.primary { background-color: #111; }
|
||||||
|
@ -203,4 +214,4 @@ button.secondary:hover { background-color: #FFDF00 !important;}
|
||||||
.p20h {padding: 0 20px;}
|
.p20h {padding: 0 20px;}
|
||||||
.m30v {margin: 30px 0;}
|
.m30v {margin: 30px 0;}
|
||||||
.m30a {margin: 30px auto;}
|
.m30a {margin: 30px auto;}
|
||||||
.br100 {border-radius: 100%;}
|
.br100 {border-radius: 100%;}
|
||||||
|
|
105
index.html
105
index.html
|
@ -45,11 +45,14 @@
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div ng-if='$root.flashMessage.message' class="panel callout radius" style="color:red" >
|
<div class="row" ng-if='$root.flashMessage.message'>
|
||||||
{{$root.flashMessage.type}}:
|
<div class="small-8 large-centered columns">
|
||||||
{{$root.flashMessage.message}}
|
<div data-alert class="alert-box round {{$root.flashMessage.type}}">
|
||||||
<a ng-click="clearFlashMessage()" class="button tiny">Dismiss</a>
|
{{$root.flashMessage.message}}
|
||||||
|
<a ng-click="clearFlashMessage()" class="close">×</a>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div ng-if='$root.wallet && !$root.wallet.publicKeyRing.isComplete() && !loading' data-alert class="alert-box warning round" >
|
<div ng-if='$root.wallet && !$root.wallet.publicKeyRing.isComplete() && !loading' data-alert class="alert-box warning round" >
|
||||||
|
@ -61,14 +64,14 @@
|
||||||
<span ng-show="$root.wallet.publicKeyRing.totalCopayers - $root.wallet.publicKeyRing.registeredCopayers()==1">
|
<span ng-show="$root.wallet.publicKeyRing.totalCopayers - $root.wallet.publicKeyRing.registeredCopayers()==1">
|
||||||
One key is
|
One key is
|
||||||
</span>
|
</span>
|
||||||
missing. Ask your copayers to join your session: <b>{{$root.wallet.network.peerId}}</b>
|
missing. Share this secret with your other copayers for them to join your wallet: <b>{{$root.wallet.getMyPeerId()}}</b>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row m30a">
|
<div class="row">
|
||||||
<div class="large-12 columns" ng-view></div>
|
<div class="large-12 columns" ng-view></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -81,8 +84,9 @@
|
||||||
<div ng-show="!loading">
|
<div ng-show="!loading">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="large-6 columns">
|
<div class="large-6 columns">
|
||||||
<h3>Join a Network Wallet</h3>
|
<h3>Join Wallet Creation</h3>
|
||||||
<input type="text" class="form-control" placeholder="Peer ID" ng-model="connectionId" autofocus>
|
<input type="text" class="form-control" placeholder="Paste secret here"
|
||||||
|
ng-model="connectionId" autofocus>
|
||||||
</div>
|
</div>
|
||||||
<div class="large-3 columns">
|
<div class="large-3 columns">
|
||||||
<button class="button primary expand round" type="button" ng-click="join(connectionId)">Join</button>
|
<button class="button primary expand round" type="button" ng-click="join(connectionId)">Join</button>
|
||||||
|
@ -109,7 +113,7 @@
|
||||||
<div ng-show="walletIds.length>0">
|
<div ng-show="walletIds.length>0">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="large-6 columns">
|
<div class="large-6 columns">
|
||||||
<h3>Open a Existing Wallet</h3>
|
<h3>Open Existing Wallet</h3>
|
||||||
<select class="form-control" ng-model="selectedWalletId" ng-options="walletId for walletId in walletIds">
|
<select class="form-control" ng-model="selectedWalletId" ng-options="walletId for walletId in walletIds">
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
@ -234,20 +238,27 @@
|
||||||
<div class="row" ng-show='$root.wallet.publicKeyRing.isComplete()'>
|
<div class="row" ng-show='$root.wallet.publicKeyRing.isComplete()'>
|
||||||
<div class="large-12 columns">
|
<div class="large-12 columns">
|
||||||
<h3>Pending Transactions <small>({{txs.length}})</small></h3>
|
<h3>Pending Transactions <small>({{txs.length}})</small></h3>
|
||||||
<div class="panel pending" ng-repeat="txp in txs">
|
<div class="panel pending" ng-repeat="tx in txs">
|
||||||
<div class="row" ng-repeat="o in txs.outs">
|
NTXID: {{tx.ntxid}}
|
||||||
<p class="large-5 columns"> {{o.address}}</p>
|
CREATOR: {{tx.creator}}
|
||||||
<i class="large-2 columns fi-arrow-right size-16 text-center"></i>
|
CREATED_TS: {{tx.createdTs}}
|
||||||
|
<div class="row" ng-repeat="o in tx.outs">
|
||||||
<p class="large-5 columns"> {{o.value}} BTC </p>
|
<p class="large-5 columns"> {{o.value}} BTC </p>
|
||||||
|
<i class="large-2 columns fi-arrow-right size-16 text-center"></i>
|
||||||
|
<p class="large-5 columns"> {{o.address}}</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="large-12 columns m0 panel panel-sign" ng-show="txp.signedByUs">
|
<div class="large-12 columns m0 panel panel-sign" ng-show="tx.signedByUs">
|
||||||
<i class="fi-check size-40"></i> YOU SIGNED!
|
<i class="fi-check size-40"></i> Signed by you already
|
||||||
</div>
|
</div>
|
||||||
<div class="large-12 columns m0" ng-show="!txp.signedByUs">
|
<div class="large-12 columns m0" ng-show="!tx.signedByUs">
|
||||||
<div class="line"></div>
|
<div class="line"></div>
|
||||||
<button class="primary round large-4 columns"><i class="large-2 columns fi-x size-16 text-center"></i> Ignore</button>
|
<button class="primary round large-4 columns"><i class="large-2 columns fi-x size-16 text-center"></i> Ignore</button>
|
||||||
<small class="large-4 columns text-center">Faltan 3 cosigners</small>
|
<small class="large-4 columns text-center">
|
||||||
<button class="secondary round large-4 columns" ng-click="sign(txp.ntxid)"><i class="large-2 columns fi-check size-16 text-center"></i> Sign</button>
|
<span ng-show="tx.missingSignatures==1"> One signature </span>
|
||||||
|
<span ng-show="tx.missingSignatures>1"> {{tx.missingSignatures}} signatures </span>
|
||||||
|
missing
|
||||||
|
</small>
|
||||||
|
<button class="secondary round large-4 columns" ng-click="sign(tx.ntxid)"><i class="large-2 columns fi-check size-16 text-center"></i> Sign</button>
|
||||||
</div>
|
</div>
|
||||||
</div> <!-- end of row -->
|
</div> <!-- end of row -->
|
||||||
</div> <!-- end of pending -->
|
</div> <!-- end of pending -->
|
||||||
|
@ -295,21 +306,51 @@
|
||||||
<script type="text/ng-template" id="send.html">
|
<script type="text/ng-template" id="send.html">
|
||||||
<div class="send" data-ng-controller="SendController">
|
<div class="send" data-ng-controller="SendController">
|
||||||
<div class="row" ng-show='$root.wallet.publicKeyRing.isComplete()'>
|
<div class="row" ng-show='$root.wallet.publicKeyRing.isComplete()'>
|
||||||
<div class="large-8 columns">
|
<div class="small-6 large-centered columns">
|
||||||
<form>
|
<h1>{{title}}</h1>
|
||||||
<label for="address">To
|
<form name="sendForm" ng-submit="submitForm(sendForm)" novalidate>
|
||||||
<input type="text" id="address" placeholder="Send to">
|
<div class="row">
|
||||||
</label>
|
<div class="large-12 columns">
|
||||||
<label for="amount">Amount
|
<label for="address">To address
|
||||||
<input type="text" id="amount" placeholder="Amount">
|
<small ng-hide="!sendForm.address.$pristine">required</small>
|
||||||
<select class="form-control">
|
<small class="is-valid" ng-show="!sendForm.address.$invalid && !sendForm.address.$pristine">is valid!</small>
|
||||||
<option>mBTC</option>
|
<small class="has-error" ng-show="sendForm.address.$invalid && !sendForm.address.$pristine">
|
||||||
<option>BTC</option>
|
is not valid</small>
|
||||||
</select>
|
</label>
|
||||||
</label>
|
<input type="text" id="address" name="address" placeholder="Send to" ng-model="address" ng-minlength="20" ng-maxlength="37" required>
|
||||||
<button class="button primary round" type="button" ng-click="sendTest()">sendTest</button>
|
</div>
|
||||||
<button type="submit" class="button secondary round right">send</button>
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="large-6 columns">
|
||||||
|
<div class="row collapse">
|
||||||
|
<label for="amount">Amount
|
||||||
|
<small ng-hide="!sendForm.amount.$pristine">required</small>
|
||||||
|
<small class="is-valid" ng-show="!sendForm.amount.$invalid && !sendForm.amount.$pristine">is valid!</small>
|
||||||
|
<small class="has-error" ng-show="sendForm.amount.$invalid && !sendForm.amount.$pristine">
|
||||||
|
is not valid</small>
|
||||||
|
</label>
|
||||||
|
<div class="small-9 columns">
|
||||||
|
<input type="number" id="amount" name="amount" placeholder="Amount" ng-model="amount" min="0.0001" max="10000000" required>
|
||||||
|
</div>
|
||||||
|
<div class="small-3 columns">
|
||||||
|
<span class="postfix">BTC</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="large-4 columns">
|
||||||
|
<button type="submit" class="button secondary round text-center" ng-disabled="sendForm.$invalid">
|
||||||
|
Send
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
<hr>
|
||||||
|
<div class="text-center">
|
||||||
|
<a ng-click="sendTest()">sendTest</a>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -3,12 +3,12 @@
|
||||||
var config = {
|
var config = {
|
||||||
networkName: 'testnet',
|
networkName: 'testnet',
|
||||||
network: {
|
network: {
|
||||||
key: 'lwjd5qra8257b9',
|
// key: 'lwjd5qra8257b9',
|
||||||
// This is for running local peerJs with params: ./peerjs -p 10009 -k 'sdfjhwefh'
|
// This is for running local peerJs with params: ./peerjs -p 10009 -k 'sdfjhwefh'
|
||||||
// key: 'sdfjhwefh',
|
key: 'sdfjhwefh',
|
||||||
// host: 'localhost',
|
host: 'localhost',
|
||||||
// port: 10009,
|
port: 10009,
|
||||||
// path: '/',
|
path: '/',
|
||||||
maxPeers: 3,
|
maxPeers: 3,
|
||||||
debug: 3,
|
debug: 3,
|
||||||
},
|
},
|
|
@ -10,11 +10,12 @@ angular.module('copay.home').controller('HomeController',
|
||||||
|
|
||||||
var _updateBalance = function () {
|
var _updateBalance = function () {
|
||||||
w.getBalance(function (balance, balanceByAddr) {
|
w.getBalance(function (balance, balanceByAddr) {
|
||||||
$rootScope.$apply(function() {
|
if (balanceByAddr && Object.keys(balanceByAddr).length) {
|
||||||
$rootScope.balanceByAddr = balanceByAddr;
|
$scope.balanceByAddr = balanceByAddr;
|
||||||
$scope.addrs = Object.keys(balanceByAddr);
|
$scope.addrs = Object.keys(balanceByAddr);
|
||||||
$scope.selectedAddr = $scope.addrs[0];
|
$scope.selectedAddr = $scope.addrs[0];
|
||||||
});
|
$scope.$digest();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -30,4 +31,5 @@ angular.module('copay.home').controller('HomeController',
|
||||||
};
|
};
|
||||||
|
|
||||||
_updateBalance();
|
_updateBalance();
|
||||||
|
w.on('refresh',_updateBalance);
|
||||||
});
|
});
|
||||||
|
|
|
@ -4,8 +4,35 @@ angular.module('copay.send').controller('SendController',
|
||||||
function($scope, $rootScope, $location) {
|
function($scope, $rootScope, $location) {
|
||||||
$scope.title = 'Send';
|
$scope.title = 'Send';
|
||||||
|
|
||||||
|
$scope.unitIds = ['BTC','mBTC'];
|
||||||
|
$scope.selectedUnit = $scope.unitIds[0];
|
||||||
|
|
||||||
|
$scope.submitForm = function(form) {
|
||||||
|
if (form.$invalid) {
|
||||||
|
$rootScope.flashMessage = { message: 'You can not send a proposal transaction. Please, try again', type: 'error'};
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var address = form.address.$modelValue;
|
||||||
|
var amount = (form.amount.$modelValue * 100000000).toString(); // satoshi to string
|
||||||
|
|
||||||
|
var w = $rootScope.wallet;
|
||||||
|
w.createTx( address, amount,function() {
|
||||||
|
$rootScope.$digest();
|
||||||
|
});
|
||||||
|
|
||||||
|
// reset fields
|
||||||
|
$scope.address = null;
|
||||||
|
$scope.amount = null;
|
||||||
|
form.address.$pristine = true;
|
||||||
|
form.amount.$pristine = true;
|
||||||
|
|
||||||
|
// TODO: check if createTx has an error.
|
||||||
|
$rootScope.flashMessage = { message: 'You send a proposal transaction succefully', type: 'success'};
|
||||||
|
};
|
||||||
|
|
||||||
$scope.sendTest = function() {
|
$scope.sendTest = function() {
|
||||||
var w = $rootScope.wallet;
|
var w = $rootScope.wallet;
|
||||||
w.createTx( 'mimoZNLcP2rrMRgdeX5PSnR7AjCqQveZZ4', '12345',function() {
|
w.createTx( 'mimoZNLcP2rrMRgdeX5PSnR7AjCqQveZZ4', '12345',function() {
|
||||||
$rootScope.$digest();
|
$rootScope.$digest();
|
||||||
});
|
});
|
||||||
|
|
|
@ -34,7 +34,6 @@ angular.module('copay.setup').controller('SetupController',
|
||||||
};
|
};
|
||||||
var w = walletFactory.create(opts);
|
var w = walletFactory.create(opts);
|
||||||
controllerUtils.setupUxHandlers(w);
|
controllerUtils.setupUxHandlers(w);
|
||||||
w.netStart();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -10,23 +10,26 @@ angular.module('copay.signin').controller('SigninController',
|
||||||
$location.path('setup');
|
$location.path('setup');
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.open = function(walletId) {
|
$scope.open = function(walletId, opts) {
|
||||||
$scope.loading = true;
|
$scope.loading = true;
|
||||||
|
|
||||||
var w = walletFactory.open(walletId);
|
console.log('[signin.js.23:walletId:]',walletId); //TODO
|
||||||
|
var w = walletFactory.open(walletId, opts);
|
||||||
controllerUtils.setupUxHandlers(w);
|
controllerUtils.setupUxHandlers(w);
|
||||||
w.netStart();
|
w.netStart();
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.join = function(peerId) {
|
$scope.join = function(secret) {
|
||||||
$scope.loading = true;
|
$scope.loading = true;
|
||||||
walletFactory.network.on('openError', function() {
|
|
||||||
controllerUtils.onError($scope);
|
walletFactory.network.on('joinError', function() {
|
||||||
$rootScope.$digest();
|
controllerUtils.onErrorDigest($scope);
|
||||||
});
|
});
|
||||||
walletFactory.connectTo(peerId, function(w) {
|
|
||||||
|
walletFactory.joinCreateSession(secret, function(w) {
|
||||||
|
console.log('[signin.js.33] joinCreateSession RETURN', w); //TODO
|
||||||
controllerUtils.setupUxHandlers(w);
|
controllerUtils.setupUxHandlers(w);
|
||||||
w.netStart();
|
w.setupNetHandlers();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
var bitcore = require('bitcore');
|
||||||
|
|
||||||
angular.module('copay.transactions').controller('TransactionsController',
|
angular.module('copay.transactions').controller('TransactionsController',
|
||||||
function($scope, $rootScope, $location) {
|
function($scope, $rootScope, $location) {
|
||||||
|
@ -9,7 +10,7 @@ angular.module('copay.transactions').controller('TransactionsController',
|
||||||
var _updateTxs = function() {
|
var _updateTxs = function() {
|
||||||
var w =$rootScope.wallet;
|
var w =$rootScope.wallet;
|
||||||
var inT = w.getTxProposals();
|
var inT = w.getTxProposals();
|
||||||
var ts = [];
|
var txs = [];
|
||||||
|
|
||||||
inT.forEach(function(i){
|
inT.forEach(function(i){
|
||||||
var b = i.txp.builder;
|
var b = i.txp.builder;
|
||||||
|
@ -18,28 +19,49 @@ angular.module('copay.transactions').controller('TransactionsController',
|
||||||
feeSat: b.feeSat,
|
feeSat: b.feeSat,
|
||||||
};
|
};
|
||||||
var outs = [];
|
var outs = [];
|
||||||
var bitcore = require('bitcore');
|
|
||||||
tx.outs.forEach(function(o) {
|
tx.outs.forEach(function(o) {
|
||||||
var s = o.getScript();
|
var addr = bitcore.Address.fromScriptPubKey(o.getScript(), config.networkName)[0].toString();
|
||||||
var aStr = bitcore.Address.fromScript(s, config.networkName).toString();
|
if (!w.addressIsOwn(addr)) {
|
||||||
if (!w.addressIsOwn(aStr))
|
|
||||||
outs.push({
|
outs.push({
|
||||||
address: aStr,
|
address: addr,
|
||||||
value: bitcore.util.valueToBigInt(o.getValue())/bitcore.util.COIN,
|
value: bitcore.util.valueToBigInt(o.getValue())/bitcore.util.COIN,
|
||||||
});
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
one.outs = outs;
|
one.outs = outs;
|
||||||
ts.push(one);
|
|
||||||
});
|
|
||||||
$scope.txs = ts;
|
|
||||||
};
|
|
||||||
|
|
||||||
_updateTxs();
|
// TOD: check missingSignatures === in al inputs?
|
||||||
|
one.missingSignatures = tx.countInputMissingSignatures(0);
|
||||||
|
one.signedByUs = i.signedByUs;
|
||||||
|
one.ntxid = i.ntxid;
|
||||||
|
one.creator = i.txp.creator,
|
||||||
|
one.createdTs = i.txp.createdTs;
|
||||||
|
txs.push(one);
|
||||||
|
});
|
||||||
|
$scope.txs = txs;
|
||||||
|
};
|
||||||
|
|
||||||
$scope.sign = function (ntxid) {
|
$scope.sign = function (ntxid) {
|
||||||
var w = $rootScope.wallet;
|
var w = $rootScope.wallet;
|
||||||
var ret = w.sign(ntxid);
|
var ret = w.sign(ntxid);
|
||||||
$rootScope.flashMessage = {type:'success', message: 'Transactions SEND! : ' + ret};
|
_updateTxs();
|
||||||
|
|
||||||
|
var p = w.getTxProposal(ntxid);
|
||||||
|
if (p.txp.builder.isFullySigned()) {
|
||||||
|
w.sendTx(ntxid, function(txid) {
|
||||||
|
$rootScope.flashMessage = txid
|
||||||
|
? {type:'success', message: 'Transactions SENT! txid:' + txid}
|
||||||
|
: {type:'error', message: 'There was an error sending the Transaction'}
|
||||||
|
;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$rootScope.flashMessage = ret
|
||||||
|
? {type:'success', message: 'Transactions signed'}
|
||||||
|
: {type:'error', message: 'There was an error signing the Transaction'}
|
||||||
|
;
|
||||||
|
}
|
||||||
_updateTxs();
|
_updateTxs();
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
|
@ -102,7 +102,7 @@ Insight.prototype._request = function(options, callback) {
|
||||||
return callback({message: 'Wrong response from insight'});
|
return callback({message: 'Wrong response from insight'});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return callback({message: 'Error ' + response.statusCode});
|
return callback({message: 'Error ' + request.status});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -16,13 +16,17 @@ function PrivateKey(opts) {
|
||||||
var init = opts.extendedPrivateKeyString || this.network.name;
|
var init = opts.extendedPrivateKeyString || this.network.name;
|
||||||
this.bip = opts.BIP32 || new BIP32(init);
|
this.bip = opts.BIP32 || new BIP32(init);
|
||||||
this.privateKeyCache = opts.privateKeyCache || {};
|
this.privateKeyCache = opts.privateKeyCache || {};
|
||||||
this._calcId();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
PrivateKey.prototype._calcId = function() {
|
PrivateKey.prototype.getId = function(prefix) {
|
||||||
this.id = util.ripe160(this.bip.extendedPublicKey).toString('hex');
|
var buf = this.bip.extendedPublicKey;
|
||||||
|
if (prefix) {
|
||||||
|
buf = Buffer.concat([prefix, buf]);
|
||||||
|
}
|
||||||
|
return util.ripe160(buf).toString('hex');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
PrivateKey.fromObj = function(obj) {
|
PrivateKey.fromObj = function(obj) {
|
||||||
return new PrivateKey(obj);
|
return new PrivateKey(obj);
|
||||||
};
|
};
|
||||||
|
|
|
@ -9,6 +9,7 @@ var Address = bitcore.Address;
|
||||||
var Script = bitcore.Script;
|
var Script = bitcore.Script;
|
||||||
var coinUtil = bitcore.util;
|
var coinUtil = bitcore.util;
|
||||||
var Transaction = bitcore.Transaction;
|
var Transaction = bitcore.Transaction;
|
||||||
|
var util = bitcore.util;
|
||||||
|
|
||||||
var Storage = imports.Storage || require('../storage/Base.js');
|
var Storage = imports.Storage || require('../storage/Base.js');
|
||||||
var storage = Storage.default();
|
var storage = Storage.default();
|
||||||
|
@ -76,6 +77,17 @@ PublicKeyRing.prototype.serialize = function () {
|
||||||
return JSON.stringify(this.toObj());
|
return JSON.stringify(this.toObj());
|
||||||
};
|
};
|
||||||
|
|
||||||
|
PublicKeyRing.prototype.getCopayerId = function(i, prefix) {
|
||||||
|
var buf = this.copayersBIP32[i].extendedPublicKey;
|
||||||
|
if (prefix) {
|
||||||
|
buf = Buffer.concat([prefix, buf]);
|
||||||
|
}
|
||||||
|
return util.ripe160(buf).toString('hex');
|
||||||
|
};
|
||||||
|
|
||||||
|
PublicKeyRing.prototype.myCopayerId = function(i, prefix) {
|
||||||
|
return this.getCopayerId(0,prefix);
|
||||||
|
};
|
||||||
|
|
||||||
PublicKeyRing.prototype.registeredCopayers = function () {
|
PublicKeyRing.prototype.registeredCopayers = function () {
|
||||||
return this.copayersBIP32.length;
|
return this.copayersBIP32.length;
|
||||||
|
@ -225,12 +237,12 @@ PublicKeyRing.prototype._checkInPRK = function(inPKR, ignoreId) {
|
||||||
if (
|
if (
|
||||||
this.requiredCopayers && inPKR.requiredCopayers &&
|
this.requiredCopayers && inPKR.requiredCopayers &&
|
||||||
(this.requiredCopayers !== inPKR.requiredCopayers))
|
(this.requiredCopayers !== inPKR.requiredCopayers))
|
||||||
throw new Error('inPRK requiredCopayers mismatch');
|
throw new Error('inPRK requiredCopayers mismatch '+this.requiredCopayers+'!='+inPKR.requiredCopayers);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
this.totalCopayers && inPKR.totalCopayers &&
|
this.totalCopayers && inPKR.totalCopayers &&
|
||||||
(this.totalCopayers !== inPKR.totalCopayers))
|
(this.totalCopayers !== inPKR.totalCopayers))
|
||||||
throw new Error('inPRK requiredCopayers mismatch');
|
throw new Error('inPRK totalCopayers mismatch'+this.totalCopayers+'!='+inPKR.requiredCopayers);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -14,10 +14,27 @@ var Storage = imports.Storage || require('../storage/Base');
|
||||||
var storage = Storage.default();
|
var storage = Storage.default();
|
||||||
|
|
||||||
function TxProposal(opts) {
|
function TxProposal(opts) {
|
||||||
|
this.creator = opts.creator;
|
||||||
|
this.createdTs = opts.createdTs;
|
||||||
this.seenBy = opts.seenBy || {};
|
this.seenBy = opts.seenBy || {};
|
||||||
this.signedBy = opts.signedBy || {};
|
this.signedBy = opts.signedBy || {};
|
||||||
this.builder = opts.builder;
|
this.builder = opts.builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
TxProposal.prototype.toObj = function() {
|
||||||
|
var o = JSON.parse(JSON.stringify(this));
|
||||||
|
delete o['builder'];
|
||||||
|
o.builderObj = this.builder.toObj();
|
||||||
|
return o;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
TxProposal.fromObj = function(o) {
|
||||||
|
var t = new TxProposal(o);
|
||||||
|
var b = new Builder.fromObj(o.builderObj);
|
||||||
|
t.builder = b;
|
||||||
|
return t;
|
||||||
|
};
|
||||||
|
|
||||||
module.exports = require('soop')(TxProposal);
|
module.exports = require('soop')(TxProposal);
|
||||||
|
|
||||||
|
|
||||||
|
@ -26,7 +43,7 @@ function TxProposals(opts) {
|
||||||
this.walletId = opts.walletId;
|
this.walletId = opts.walletId;
|
||||||
this.network = opts.networkName === 'livenet' ?
|
this.network = opts.networkName === 'livenet' ?
|
||||||
bitcore.networks.livenet : bitcore.networks.testnet;
|
bitcore.networks.livenet : bitcore.networks.testnet;
|
||||||
this.txps = [];
|
this.txps = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
TxProposals.fromObj = function(o) {
|
TxProposals.fromObj = function(o) {
|
||||||
|
@ -34,12 +51,10 @@ TxProposals.fromObj = function(o) {
|
||||||
networkName: o.networkName,
|
networkName: o.networkName,
|
||||||
walletId: o.walletId,
|
walletId: o.walletId,
|
||||||
});
|
});
|
||||||
o.txps.forEach(function(t) {
|
o.txps.forEach(function(o2) {
|
||||||
ret.txps.push({
|
var t = TxProposal.fromObj(o2);
|
||||||
seenBy: t.seenBy,
|
var id = t.builder.build().getNormalizedHash().toString('hex');
|
||||||
signedBy: t.signedBy,
|
ret.txps[id] = t;
|
||||||
builder: new Builder.fromObj(t.builderObj),
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
return ret;
|
return ret;
|
||||||
};
|
};
|
||||||
|
@ -47,13 +62,10 @@ TxProposals.fromObj = function(o) {
|
||||||
|
|
||||||
TxProposals.prototype.toObj = function() {
|
TxProposals.prototype.toObj = function() {
|
||||||
var ret = [];
|
var ret = [];
|
||||||
this.txps.forEach(function(t) {
|
for(var id in this.txps){
|
||||||
ret.push({
|
var t = this.txps[id];
|
||||||
seenBy: t.seenBy,
|
ret.push(t.toObj());
|
||||||
signedBy: t.signedBy,
|
}
|
||||||
builderObj: t.builder.toObj(),
|
|
||||||
});
|
|
||||||
});
|
|
||||||
return {
|
return {
|
||||||
txps: ret,
|
txps: ret,
|
||||||
walletId: this.walletId,
|
walletId: this.walletId,
|
||||||
|
@ -62,36 +74,27 @@ TxProposals.prototype.toObj = function() {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
TxProposals.prototype._getNormHash = function(txps) {
|
|
||||||
var ret = {};
|
|
||||||
txps.forEach(function(txp) {
|
|
||||||
var hash = txp.builder.build().getNormalizedHash().toString('hex');
|
|
||||||
ret[hash]=txp;
|
|
||||||
});
|
|
||||||
return ret;
|
|
||||||
};
|
|
||||||
|
|
||||||
TxProposals.prototype._startMerge = function(myTxps, theirTxps) {
|
TxProposals.prototype._startMerge = function(myTxps, theirTxps) {
|
||||||
var fromUs=0, fromTheirs=0, merged =0;
|
var fromUs=0, fromTheirs=0, merged =0;
|
||||||
var toMerge = {}, ready=[];
|
var toMerge = {}, ready={};
|
||||||
|
|
||||||
Object.keys(theirTxps).forEach(function(hash) {
|
for(var hash in theirTxps){
|
||||||
if (!myTxps[hash]) {
|
if (!myTxps[hash]) {
|
||||||
ready.push(theirTxps[hash]); // only in theirs;
|
ready[hash]=theirTxps[hash]; // only in theirs;
|
||||||
fromTheirs++;
|
fromTheirs++;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
toMerge[hash]=theirTxps[hash]; // need Merging
|
toMerge[hash]=theirTxps[hash]; // need Merging
|
||||||
merged++;
|
merged++;
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
Object.keys(myTxps).forEach(function(hash) {
|
for(var hash in myTxps){
|
||||||
if(!toMerge[hash]) {
|
if(!toMerge[hash]) {
|
||||||
ready.push(myTxps[hash]); // only in myTxps;
|
ready[hash]=myTxps[hash]; // only in myTxps;
|
||||||
fromUs++;
|
fromUs++;
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
stats: {
|
stats: {
|
||||||
|
@ -124,42 +127,48 @@ TxProposals.prototype._mergeMetadata = function(myTxps, theirTxps, mergeInfo) {
|
||||||
|
|
||||||
|
|
||||||
TxProposals.prototype._mergeBuilder = function(myTxps, theirTxps, mergeInfo) {
|
TxProposals.prototype._mergeBuilder = function(myTxps, theirTxps, mergeInfo) {
|
||||||
var self = this;
|
|
||||||
var toMerge = mergeInfo.toMerge;
|
var toMerge = mergeInfo.toMerge;
|
||||||
|
|
||||||
Object.keys(toMerge).forEach(function(hash) {
|
for(var hash in toMerge){
|
||||||
var v0 = myTxps[hash].builder;
|
var v0 = myTxps[hash].builder;
|
||||||
var v1 = toMerge[hash].builder;
|
var v1 = toMerge[hash].builder;
|
||||||
|
|
||||||
v0.merge(v1);
|
v0.merge(v1);
|
||||||
});
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
TxProposals.prototype.add = function(data) {
|
TxProposals.prototype.add = function(data) {
|
||||||
this.txps.push( new TxProposal(data) );
|
var id = data.builder.build().getNormalizedHash().toString('hex');
|
||||||
|
this.txps[id] = new TxProposal(data);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
TxProposals.prototype.remove = function(ntxid) {
|
||||||
|
|
||||||
|
console.log('[TxProposals.js.147] DELETING:', ntxid); //TODO
|
||||||
|
delete this.txps[ntxid];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
TxProposals.prototype.merge = function(t) {
|
TxProposals.prototype.merge = function(t) {
|
||||||
if (this.network.name !== t.network.name)
|
if (this.network.name !== t.network.name)
|
||||||
throw new Error('network mismatch in:', t);
|
throw new Error('network mismatch in:', t);
|
||||||
|
|
||||||
var res = [];
|
var res = [];
|
||||||
|
|
||||||
var myTxps = this._getNormHash(this.txps);
|
var myTxps = this.txps;
|
||||||
var theirTxps = this._getNormHash(t.txps);
|
var theirTxps = t.txps;
|
||||||
|
|
||||||
var mergeInfo = this._startMerge(myTxps, theirTxps);
|
var mergeInfo = this._startMerge(myTxps, theirTxps);
|
||||||
this._mergeMetadata(myTxps, theirTxps, mergeInfo);
|
this._mergeMetadata(myTxps, theirTxps, mergeInfo);
|
||||||
this._mergeBuilder(myTxps, theirTxps, mergeInfo);
|
this._mergeBuilder(myTxps, theirTxps, mergeInfo);
|
||||||
|
|
||||||
Object.keys(mergeInfo.toMerge).forEach(function(hash) {
|
Object.keys(mergeInfo.toMerge).forEach(function(hash) {
|
||||||
mergeInfo.ready.push(myTxps[hash]);
|
mergeInfo.ready[hash] = myTxps[hash];
|
||||||
});
|
});
|
||||||
|
|
||||||
this.txps=mergeInfo.ready;
|
this.txps=mergeInfo.ready;
|
||||||
return mergeInfo.stats;
|
return mergeInfo.stats;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
module.exports = require('soop')(TxProposals);
|
module.exports = require('soop')(TxProposals);
|
||||||
|
|
|
@ -48,17 +48,19 @@ Wallet.prototype._handlePublicKeyRing = function(senderId, data, isInbound) {
|
||||||
var shouldSend = false;
|
var shouldSend = false;
|
||||||
var recipients, pkr = this.publicKeyRing;
|
var recipients, pkr = this.publicKeyRing;
|
||||||
var inPKR = copay.PublicKeyRing.fromObj(data.publicKeyRing);
|
var inPKR = copay.PublicKeyRing.fromObj(data.publicKeyRing);
|
||||||
if (pkr.merge(inPKR, true) && !data.isBroadcast) {
|
|
||||||
|
var hasChanged = pkr.merge(inPKR, true);
|
||||||
|
if (hasChanged) {
|
||||||
this.log('### BROADCASTING PKR');
|
this.log('### BROADCASTING PKR');
|
||||||
recipients = null;
|
recipients = null;
|
||||||
shouldSend = true;
|
shouldSend = true;
|
||||||
}
|
}
|
||||||
else if (isInbound && !data.isBroadcast) {
|
// else if (isInbound && !data.isBroadcast) {
|
||||||
// always replying to connecting peer
|
// // always replying to connecting peer
|
||||||
this.log('### REPLYING PKR TO:', senderId);
|
// this.log('### REPLYING PKR TO:', senderId);
|
||||||
recipients = senderId;
|
// recipients = senderId;
|
||||||
shouldSend = true;
|
// shouldSend = true;
|
||||||
}
|
// }
|
||||||
|
|
||||||
if (shouldSend) {
|
if (shouldSend) {
|
||||||
this.sendPublicKeyRing(recipients);
|
this.sendPublicKeyRing(recipients);
|
||||||
|
@ -76,17 +78,18 @@ Wallet.prototype._handleTxProposals = function(senderId, data, isInbound) {
|
||||||
var mergeInfo = this.txProposals.merge(inTxp, true);
|
var mergeInfo = this.txProposals.merge(inTxp, true);
|
||||||
|
|
||||||
var addSeen = this.addSeenToTxProposals();
|
var addSeen = this.addSeenToTxProposals();
|
||||||
if ((mergeInfo.merged && !data.isBroadcast) || addSeen) {
|
// if ((mergeInfo.merged && !data.isBroadcast) || addSeen) {
|
||||||
|
if (mergeInfo.merged || addSeen) {
|
||||||
this.log('### BROADCASTING txProposals. ' );
|
this.log('### BROADCASTING txProposals. ' );
|
||||||
recipients = null;
|
recipients = null;
|
||||||
shouldSend = true;
|
shouldSend = true;
|
||||||
}
|
}
|
||||||
else if (isInbound && !data.isBroadcast) {
|
// else if (isInbound && !data.isBroadcast) {
|
||||||
// always replying to connecting peer
|
// // always replying to connecting peer
|
||||||
this.log('### REPLYING txProposals TO:', senderId);
|
// this.log('### REPLYING txProposals TO:', senderId);
|
||||||
recipients = senderId;
|
// recipients = senderId;
|
||||||
shouldSend = true;
|
// shouldSend = true;
|
||||||
}
|
// }
|
||||||
|
|
||||||
if (shouldSend)
|
if (shouldSend)
|
||||||
this.sendTxProposals(recipients);
|
this.sendTxProposals(recipients);
|
||||||
|
@ -95,7 +98,7 @@ Wallet.prototype._handleTxProposals = function(senderId, data, isInbound) {
|
||||||
};
|
};
|
||||||
|
|
||||||
Wallet.prototype._handleData = function(senderId, data, isInbound) {
|
Wallet.prototype._handleData = function(senderId, data, isInbound) {
|
||||||
|
// TODO check message signature
|
||||||
if (this.id !== data.walletId) {
|
if (this.id !== data.walletId) {
|
||||||
this.emit('badMessage',senderId);
|
this.emit('badMessage',senderId);
|
||||||
this.log('badMessage FROM:', senderId); //TODO
|
this.log('badMessage FROM:', senderId); //TODO
|
||||||
|
@ -103,6 +106,12 @@ Wallet.prototype._handleData = function(senderId, data, isInbound) {
|
||||||
}
|
}
|
||||||
this.log('[Wallet.js.98]' , data.type); //TODO
|
this.log('[Wallet.js.98]' , data.type); //TODO
|
||||||
switch(data.type) {
|
switch(data.type) {
|
||||||
|
case 'walletReady':
|
||||||
|
|
||||||
|
console.log('[Wallet.js.109] RECV WALLETREADY'); //TODO
|
||||||
|
this.sendPublicKeyRing(senderId);
|
||||||
|
this.sendTxProposals(senderId);
|
||||||
|
break;
|
||||||
case 'publicKeyRing':
|
case 'publicKeyRing':
|
||||||
this._handlePublicKeyRing(senderId, data, isInbound);
|
this._handlePublicKeyRing(senderId, data, isInbound);
|
||||||
break;
|
break;
|
||||||
|
@ -112,16 +121,15 @@ Wallet.prototype._handleData = function(senderId, data, isInbound) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Wallet.prototype._handleNetworkChange = function(newPeer) {
|
Wallet.prototype._handleNetworkChange = function(newPeerId) {
|
||||||
if (newPeer) {
|
if (newPeerId) {
|
||||||
this.log('#### Setting new PEER:', newPeer);
|
this.log('#### Setting new PEER:', newPeerId);
|
||||||
this.sendWalletId(newPeer);
|
this.sendWalletId(newPeerId);
|
||||||
this.sendPublicKeyRing(newPeer);
|
|
||||||
this.sendTxProposals(newPeer);
|
|
||||||
}
|
}
|
||||||
this.emit('refresh');
|
this.emit('refresh');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
Wallet.prototype._optsToObj = function () {
|
Wallet.prototype._optsToObj = function () {
|
||||||
var obj = {
|
var obj = {
|
||||||
id: this.id,
|
id: this.id,
|
||||||
|
@ -133,7 +141,28 @@ Wallet.prototype._optsToObj = function () {
|
||||||
return obj;
|
return obj;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Wallet.prototype.getPeerId = function(index) {
|
||||||
|
// if (typeof index === 'undefined') {
|
||||||
|
// // return my own peerId
|
||||||
|
// var gen = this.privateKey.getId(idBuf);
|
||||||
|
// return gen;
|
||||||
|
// }
|
||||||
|
// return peer number 'index' peerId
|
||||||
|
//
|
||||||
|
var idBuf;
|
||||||
|
// TODO idBuf DISABLED FOR NOW
|
||||||
|
//idBuf = new Buffer(this.id);
|
||||||
|
return this.publicKeyRing.getCopayerId(index || 0, idBuf);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Wallet.prototype.getMyPeerId = function() {
|
||||||
|
return this.getPeerId(0);
|
||||||
|
};
|
||||||
|
|
||||||
Wallet.prototype.netStart = function() {
|
Wallet.prototype.netStart = function() {
|
||||||
|
console.log('[Wallet.js.159:netStart:]'); //TODO
|
||||||
var self = this;
|
var self = this;
|
||||||
var net = this.network;
|
var net = this.network;
|
||||||
net.removeAllListeners();
|
net.removeAllListeners();
|
||||||
|
@ -141,15 +170,27 @@ Wallet.prototype.netStart = function() {
|
||||||
net.on('data', self._handleData.bind(self) );
|
net.on('data', self._handleData.bind(self) );
|
||||||
net.on('open', function() {}); // TODO
|
net.on('open', function() {}); // TODO
|
||||||
net.on('openError', function() {
|
net.on('openError', function() {
|
||||||
this.log('[Wallet.js.132:openError:] GOT openError'); //TODO
|
self.log('[Wallet.js.132:openError:] GOT openError'); //TODO
|
||||||
self.emit('openError');
|
self.emit('openError');
|
||||||
});
|
});
|
||||||
net.on('close', function() {
|
net.on('close', function() {
|
||||||
self.emit('close');
|
self.emit('close');
|
||||||
});
|
});
|
||||||
net.start(function(peerId) {
|
|
||||||
|
var myPeerId = self.getMyPeerId();
|
||||||
|
var startOpts = {
|
||||||
|
peerId: myPeerId
|
||||||
|
};
|
||||||
|
net.start(function() {
|
||||||
|
console.log('[Wallet.js.177] NET START: emit CREATED'); //TODO
|
||||||
self.emit('created');
|
self.emit('created');
|
||||||
});
|
for (var i=0; i<self.publicKeyRing.registeredCopayers(); i++) {
|
||||||
|
var otherPeerId = self.getPeerId(i);
|
||||||
|
if (otherPeerId !== myPeerId) {
|
||||||
|
net.connectTo(otherPeerId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, startOpts);
|
||||||
};
|
};
|
||||||
|
|
||||||
Wallet.prototype.store = function(isSync) {
|
Wallet.prototype.store = function(isSync) {
|
||||||
|
@ -200,6 +241,15 @@ Wallet.prototype.sendTxProposals = function(recipients) {
|
||||||
this.emit('txProposalsUpdated', this.txProposals);
|
this.emit('txProposalsUpdated', this.txProposals);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Wallet.prototype.sendWalletReady = function(recipients) {
|
||||||
|
this.log('### SENDING WalletReady TO:', recipients);
|
||||||
|
|
||||||
|
this.network.send( recipients, {
|
||||||
|
type: 'walletReady',
|
||||||
|
walletId: this.id,
|
||||||
|
});
|
||||||
|
this.emit('walletReady');
|
||||||
|
};
|
||||||
|
|
||||||
Wallet.prototype.sendWalletId = function(recipients) {
|
Wallet.prototype.sendWalletId = function(recipients) {
|
||||||
this.log('### SENDING walletId TO:', recipients||'All', this.walletId);
|
this.log('### SENDING walletId TO:', recipients||'All', this.walletId);
|
||||||
|
@ -207,6 +257,7 @@ Wallet.prototype.sendWalletId = function(recipients) {
|
||||||
this.network.send(recipients, {
|
this.network.send(recipients, {
|
||||||
type: 'walletId',
|
type: 'walletId',
|
||||||
walletId: this.id,
|
walletId: this.id,
|
||||||
|
opts: this._optsToObj()
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -230,75 +281,82 @@ Wallet.prototype.generateAddress = function() {
|
||||||
return addr;
|
return addr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// TODO : sort by time... / signed.
|
||||||
Wallet.prototype.getTxProposals = function() {
|
Wallet.prototype.getTxProposals = function() {
|
||||||
var ret = [];
|
var ret = [];
|
||||||
var self= this;
|
for(var k in this.txProposals.txps) {
|
||||||
self.txProposals.txps.forEach(function(txp) {
|
var txp = this.txProposals.txps[k];
|
||||||
var i = {txp:txp};
|
var i = {txp:txp};
|
||||||
i.ntxid = txp.builder.build().getNormalizedHash();
|
i.ntxid = k;
|
||||||
i.signedByUs = txp.signedBy[self.privateKey.id]?true:false;
|
i.signedByUs = txp.signedBy[this.privateKey.getId()]?true:false;
|
||||||
ret.push(i);
|
ret.push(i);
|
||||||
});
|
|
||||||
return ret;
|
|
||||||
};
|
|
||||||
|
|
||||||
// TODO: this can be precalculated.
|
|
||||||
Wallet.prototype._findTxByNtxid = function(ntxid) {
|
|
||||||
var ret;
|
|
||||||
var l = this.txProposals.txps.length;
|
|
||||||
var id = ntxid.toString('hex');
|
|
||||||
for(var i=0; i<l; i++) {
|
|
||||||
var txp = this.txProposals.txps[i];
|
|
||||||
var id2 = txp.builder.build().getNormalizedHash().toString('hex');
|
|
||||||
if (id === id2 ) {
|
|
||||||
ret = txp;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Wallet.prototype.getTxProposal = function(ntxid) {
|
||||||
|
var txp = this.txProposals.txps[ntxid];
|
||||||
|
var i = {txp:txp};
|
||||||
|
i.ntxid = ntxid;
|
||||||
|
i.signedByUs = txp.signedBy[this.privateKey.getId()]?true:false;
|
||||||
|
return i;
|
||||||
|
};
|
||||||
|
|
||||||
Wallet.prototype.sign = function(ntxid) {
|
Wallet.prototype.sign = function(ntxid) {
|
||||||
var txp = this._findTxByNtxid(ntxid);
|
var self = this;
|
||||||
|
var txp = self.txProposals.txps[ntxid];
|
||||||
if (!txp) return;
|
if (!txp) return;
|
||||||
|
|
||||||
var pkr = this.publicKeyRing;
|
var pkr = self.publicKeyRing;
|
||||||
var keys = this.privateKey.getAll(pkr.addressIndex, pkr.changeAddressIndex);
|
var keys = self.privateKey.getAll(pkr.addressIndex, pkr.changeAddressIndex);
|
||||||
var ret = txp.builder.sign(keys);
|
|
||||||
|
|
||||||
if (ret.signaturesAdded) {
|
var b = txp.builder;
|
||||||
txp.signedBy[this.privateKey.id] = Date.now();
|
var before = b.signaturesAdded;
|
||||||
this.log('[Wallet.js.230:ret:]',ret); //TODO
|
b.sign(keys);
|
||||||
if (ret.isFullySigned) {
|
|
||||||
this.log('[Wallet.js.231] BROADCASTING TX!!!'); //TODO
|
var ret = false;
|
||||||
var tx = txp.builder.build();
|
if (b.signaturesAdded > before) {
|
||||||
var txHex = tx.serialize().toString('hex');
|
txp.signedBy[self.privateKey.getId()] = Date.now();
|
||||||
this.blockchain.sendRawTransaction(txHex, function(txid) {
|
this.sendTxProposals();
|
||||||
this.log('[Wallet.js.235:txid:]',txid); //TODO
|
this.store(true);
|
||||||
if (txid) {
|
ret = true;
|
||||||
this.store(true);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.sendTxProposals();
|
|
||||||
this.store(true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Wallet.prototype.sendTx = function(ntxid) {
|
||||||
|
var txp = this.txProposals.txps[ntxid];
|
||||||
|
if (!txp) return;
|
||||||
|
|
||||||
|
var tx = txp.builder.build();
|
||||||
|
if (!tx.isComplete()) return;
|
||||||
|
this.log('[Wallet.js.231] BROADCASTING TX!!!'); //TODO
|
||||||
|
|
||||||
|
var txHex = tx.serialize().toString('hex');
|
||||||
|
this.log('[Wallet.js.261:txHex:]',txHex); //TODO
|
||||||
|
|
||||||
|
var self = this;
|
||||||
|
this.blockchain.sendRawTransaction(txHex, function(txid) {
|
||||||
|
self.log('BITCOND txid:',txid); //TODO
|
||||||
|
if (txid) {
|
||||||
|
self.txProposals.remove(ntxid);
|
||||||
|
self.store(true);
|
||||||
|
}
|
||||||
|
return (txid);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
Wallet.prototype.addSeenToTxProposals = function() {
|
Wallet.prototype.addSeenToTxProposals = function() {
|
||||||
var ret=false;
|
var ret=false;
|
||||||
var self=this;
|
var self=this;
|
||||||
|
|
||||||
this.txProposals.txps.forEach(function(txp) {
|
for(var k in this.txProposals.txps) {
|
||||||
if (!txp.seenBy[self.privateKey.id]) {
|
var txp = this.txProposals.txps[k];
|
||||||
txp.seenBy[self.privateKey.id] = Date.now();
|
if (!txp.seenBy[self.privateKey.getId()]) {
|
||||||
|
txp.seenBy[self.privateKey.getId()] = Date.now();
|
||||||
ret = true;
|
ret = true;
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
return ret;
|
return ret;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -333,9 +391,12 @@ Wallet.prototype.getBalance = function(cb) {
|
||||||
var balance = 0;
|
var balance = 0;
|
||||||
var balanceByAddr = {};
|
var balanceByAddr = {};
|
||||||
var COIN = bitcore.util.COIN;
|
var COIN = bitcore.util.COIN;
|
||||||
|
var addresses = this.getAddressesStr(true);
|
||||||
|
|
||||||
|
if (!addresses.length) return cb(0,[]);
|
||||||
|
|
||||||
// Prefill balanceByAddr with main address
|
// Prefill balanceByAddr with main address
|
||||||
this.getAddressesStr(true).forEach(function(a){
|
addresses.forEach(function(a){
|
||||||
balanceByAddr[a]=0;
|
balanceByAddr[a]=0;
|
||||||
});
|
});
|
||||||
this.getUnspent(function(utxos) {
|
this.getUnspent(function(utxos) {
|
||||||
|
@ -345,9 +406,9 @@ Wallet.prototype.getBalance = function(cb) {
|
||||||
balance = balance + amt;
|
balance = balance + amt;
|
||||||
balanceByAddr[u.address] = (balanceByAddr[u.address]||0) + amt;
|
balanceByAddr[u.address] = (balanceByAddr[u.address]||0) + amt;
|
||||||
}
|
}
|
||||||
Object.keys(balanceByAddr).forEach(function(a) {
|
for(var a in balanceByAddr){
|
||||||
balanceByAddr[a] = balanceByAddr[a]/COIN;
|
balanceByAddr[a] = balanceByAddr[a]/COIN;
|
||||||
});
|
};
|
||||||
return cb(balance / COIN, balanceByAddr);
|
return cb(balance / COIN, balanceByAddr);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -369,14 +430,10 @@ Wallet.prototype.createTx = function(toAddress, amountSatStr, opts, cb) {
|
||||||
if (typeof opts.spendUnconfirmed === 'undefined') {
|
if (typeof opts.spendUnconfirmed === 'undefined') {
|
||||||
opts.spendUnconfirmed = this.spendUnconfirmed;
|
opts.spendUnconfirmed = this.spendUnconfirmed;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!opts.remainderOut) {
|
|
||||||
opts.remainderOut={ address: this.publicKeyRing.generateAddress(true).toString()};
|
|
||||||
}
|
|
||||||
|
|
||||||
self.getUnspent(function(unspentList) {
|
self.getUnspent(function(unspentList) {
|
||||||
// TODO check enough funds, etc.
|
// TODO check enough funds, etc.
|
||||||
self.createTxSync(toAddress, amountSatStr, unspentList, opts);
|
self.createTxSync(toAddress, amountSatStr, unspentList, opts);
|
||||||
|
self.sendPublicKeyRing(); // Change Address
|
||||||
self.sendTxProposals();
|
self.sendTxProposals();
|
||||||
self.store();
|
self.store();
|
||||||
return cb();
|
return cb();
|
||||||
|
@ -409,11 +466,13 @@ Wallet.prototype.createTxSync = function(toAddress, amountSatStr, utxos, opts) {
|
||||||
b.sign( priv.getAll(pkr.addressIndex, pkr.changeAddressIndex) );
|
b.sign( priv.getAll(pkr.addressIndex, pkr.changeAddressIndex) );
|
||||||
}
|
}
|
||||||
var me = {};
|
var me = {};
|
||||||
if (priv) me[priv.id] = Date.now();
|
if (priv) me[priv.getId()] = Date.now();
|
||||||
|
|
||||||
this.txProposals.add({
|
this.txProposals.add({
|
||||||
signedBy: priv && b.signaturesAdded ? me : {},
|
signedBy: priv && b.signaturesAdded ? me : {},
|
||||||
seenBy: priv ? me : {},
|
seenBy: priv ? me : {},
|
||||||
|
creator: priv.getId(),
|
||||||
|
createdTs: Date.now(),
|
||||||
builder: b,
|
builder: b,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -39,10 +39,13 @@ WalletFactory.prototype.log = function(){
|
||||||
|
|
||||||
WalletFactory.prototype._checkRead = function(walletId) {
|
WalletFactory.prototype._checkRead = function(walletId) {
|
||||||
var s = this.storage;
|
var s = this.storage;
|
||||||
var ret = s.get(walletId, 'publicKeyRing') &&
|
var ret =
|
||||||
s.get(walletId, 'txProposals') &&
|
(
|
||||||
s.get(walletId, 'opts') &&
|
s.get(walletId, 'publicKeyRing') &&
|
||||||
s.get(walletId, 'privateKey')
|
s.get(walletId, 'txProposals') &&
|
||||||
|
s.get(walletId, 'opts') &&
|
||||||
|
s.get(walletId, 'privateKey')
|
||||||
|
)?true:false;
|
||||||
;
|
;
|
||||||
return ret?true:false;
|
return ret?true:false;
|
||||||
};
|
};
|
||||||
|
@ -53,17 +56,14 @@ WalletFactory.prototype.read = function(walletId) {
|
||||||
|
|
||||||
var s = this.storage;
|
var s = this.storage;
|
||||||
var opts = s.get(walletId, 'opts');
|
var opts = s.get(walletId, 'opts');
|
||||||
|
|
||||||
opts.id = walletId;
|
opts.id = walletId;
|
||||||
opts.publicKeyRing = new PublicKeyRing.fromObj(s.get(walletId, 'publicKeyRing'));
|
opts.publicKeyRing = new PublicKeyRing.fromObj(s.get(walletId, 'publicKeyRing'));
|
||||||
opts.txProposals = new TxProposals.fromObj(s.get(walletId, 'txProposals'));
|
opts.txProposals = new TxProposals.fromObj(s.get(walletId, 'txProposals'));
|
||||||
opts.privateKey = new PrivateKey.fromObj(s.get(walletId, 'privateKey'));
|
opts.privateKey = new PrivateKey.fromObj(s.get(walletId, 'privateKey'));
|
||||||
|
|
||||||
opts.storage = this.storage;
|
opts.storage = this.storage;
|
||||||
opts.network = this.network;
|
opts.network = this.network;
|
||||||
opts.blockchain = this.blockchain;
|
opts.blockchain = this.blockchain;
|
||||||
opts.verbose = this.verbose;
|
opts.verbose = this.verbose;
|
||||||
|
|
||||||
var w = new Wallet(opts);
|
var w = new Wallet(opts);
|
||||||
|
|
||||||
// JIC: Add our key
|
// JIC: Add our key
|
||||||
|
@ -81,10 +81,13 @@ WalletFactory.prototype.read = function(walletId) {
|
||||||
WalletFactory.prototype.create = function(opts) {
|
WalletFactory.prototype.create = function(opts) {
|
||||||
var s = WalletFactory.storage;
|
var s = WalletFactory.storage;
|
||||||
opts = opts || {};
|
opts = opts || {};
|
||||||
this.log('### CREATING NEW WALLET.' + (opts.id ? ' USING ID: ' + opts.id : ' NEW ID'));
|
this.log('### CREATING NEW WALLET.' +
|
||||||
|
(opts.id ? ' USING ID: ' + opts.id : ' NEW ID') +
|
||||||
|
(opts.privateKey ? ' USING PrivateKey: ' + opts.privateKey.getId() : ' NEW PrivateKey')
|
||||||
|
);
|
||||||
|
|
||||||
opts.privateKey = opts.privateKey || new PrivateKey({ networkName: this.networkName });
|
opts.privateKey = opts.privateKey || new PrivateKey({ networkName: this.networkName });
|
||||||
this.log('\t### PrivateKey Initialized');
|
|
||||||
|
|
||||||
var requiredCopayers = opts.requiredCopayers || this.walletDefaults.requiredCopayers;
|
var requiredCopayers = opts.requiredCopayers || this.walletDefaults.requiredCopayers;
|
||||||
var totalCopayers = opts.totalCopayers || this.walletDefaults.totalCopayers;
|
var totalCopayers = opts.totalCopayers || this.walletDefaults.totalCopayers;
|
||||||
|
@ -115,48 +118,12 @@ WalletFactory.prototype.create = function(opts) {
|
||||||
return w;
|
return w;
|
||||||
};
|
};
|
||||||
|
|
||||||
WalletFactory.prototype.open = function(walletId) {
|
WalletFactory.prototype.open = function(walletId, opts) {
|
||||||
var w = this.read(walletId) || this.create({
|
this.log('Opening walletId:' + walletId);
|
||||||
id: walletId,
|
opts = opts || {};
|
||||||
verbose: this.verbose,
|
opts.id = walletId;
|
||||||
});
|
opts.verbose = this.verbose;
|
||||||
return w;
|
var w = this.read(walletId) || this.create(opts);
|
||||||
};
|
|
||||||
|
|
||||||
WalletFactory.prototype.openRemote = function(peedId) {
|
|
||||||
var s = WalletFactory.storage;
|
|
||||||
opts = opts || {};
|
|
||||||
this.log('### CREATING NEW WALLET.' + (opts.id ? ' USING ID: ' + opts.id : ' NEW ID'));
|
|
||||||
|
|
||||||
opts.privateKey = opts.privateKey || new PrivateKey({ networkName: this.networkName });
|
|
||||||
this.log('\t### PrivateKey Initialized');
|
|
||||||
|
|
||||||
var requiredCopayers = opts.requiredCopayers || this.walletDefaults.requiredCopayers;
|
|
||||||
var totalCopayers = opts.totalCopayers || this.walletDefaults.totalCopayers;
|
|
||||||
|
|
||||||
opts.publicKeyRing = opts.publicKeyRing || new PublicKeyRing({
|
|
||||||
networkName: this.networkName,
|
|
||||||
requiredCopayers: requiredCopayers,
|
|
||||||
totalCopayers: totalCopayers,
|
|
||||||
});
|
|
||||||
opts.publicKeyRing.addCopayer(opts.privateKey.getExtendedPublicKeyString());
|
|
||||||
this.log('\t### PublicKeyRing Initialized');
|
|
||||||
|
|
||||||
opts.txProposals = opts.txProposals || new TxProposals({
|
|
||||||
networkName: this.networkName,
|
|
||||||
});
|
|
||||||
this.log('\t### TxProposals Initialized');
|
|
||||||
|
|
||||||
opts.storage = this.storage;
|
|
||||||
opts.network = this.network;
|
|
||||||
opts.blockchain = this.blockchain;
|
|
||||||
|
|
||||||
opts.spendUnconfirmed = typeof opts.spendUnconfirmed === undefined
|
|
||||||
?this.walletDefaults.spendUnconfirmed : opts.spendUnconfirmed;
|
|
||||||
|
|
||||||
opts.requiredCopayers = requiredCopayers;
|
|
||||||
opts.totalCopayers = totalCopayers;
|
|
||||||
var w = new Wallet(opts);
|
|
||||||
w.store();
|
w.store();
|
||||||
return w;
|
return w;
|
||||||
};
|
};
|
||||||
|
@ -167,16 +134,27 @@ WalletFactory.prototype.getWalletIds = function() {
|
||||||
|
|
||||||
WalletFactory.prototype.remove = function(walletId) {
|
WalletFactory.prototype.remove = function(walletId) {
|
||||||
// TODO remove wallet contents
|
// TODO remove wallet contents
|
||||||
|
console.log('TODO: remove wallet contents');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
WalletFactory.prototype.connectTo = function(peerId, cb) {
|
WalletFactory.prototype.joinCreateSession = function(peerId, cb) {
|
||||||
var self=this;
|
var self = this;
|
||||||
|
|
||||||
|
//Create our PrivateK
|
||||||
|
var privateKey = new PrivateKey({ networkName: this.networkName });
|
||||||
|
this.log('\t### PrivateKey Initialized');
|
||||||
|
self.network.setPeerId(privateKey.getId());
|
||||||
|
|
||||||
self.network.start(function() {
|
self.network.start(function() {
|
||||||
self.network.connectTo(peerId)
|
self.network.connectTo(peerId);
|
||||||
self.network.on('walletId', function(walletId) {
|
self.network.on('data', function(sender, data) {
|
||||||
self.log('Opening walletId:' + walletId);
|
if (data.type ==='walletId') {
|
||||||
return cb(self.open(walletId));
|
data.opts.privateKey = privateKey;
|
||||||
|
var w = self.open(data.walletId, data.opts);
|
||||||
|
w.sendWalletReady(peerId);
|
||||||
|
return cb(w);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
|
|
||||||
|
|
||||||
function Peer(id) {
|
|
||||||
this.id = id;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
module.exports = require('soop')(Peer);
|
|
|
@ -21,7 +21,7 @@ function Network(opts) {
|
||||||
this.peerId = opts.peerId;
|
this.peerId = opts.peerId;
|
||||||
this.apiKey = opts.apiKey || 'lwjd5qra8257b9';
|
this.apiKey = opts.apiKey || 'lwjd5qra8257b9';
|
||||||
this.debug = opts.debug || 3;
|
this.debug = opts.debug || 3;
|
||||||
this.maxPeers = opts.maxPeers || 5;
|
this.maxPeers = opts.maxPeers || 10;
|
||||||
this.opts = { key: opts.key };
|
this.opts = { key: opts.key };
|
||||||
|
|
||||||
// For using your own peerJs server
|
// For using your own peerJs server
|
||||||
|
@ -29,6 +29,7 @@ function Network(opts) {
|
||||||
if (opts[k]) self.opts[k]=opts[k];
|
if (opts[k]) self.opts[k]=opts[k];
|
||||||
});
|
});
|
||||||
this.connectedPeers = [];
|
this.connectedPeers = [];
|
||||||
|
this.started = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Network.parent=EventEmitter;
|
Network.parent=EventEmitter;
|
||||||
|
@ -64,7 +65,6 @@ Network._arrayPushOnce = function(el, array) {
|
||||||
Network._arrayRemove = function(el, array) {
|
Network._arrayRemove = function(el, array) {
|
||||||
var pos = array.indexOf(el);
|
var pos = array.indexOf(el);
|
||||||
if (pos >= 0) array.splice(pos, 1);
|
if (pos >= 0) array.splice(pos, 1);
|
||||||
|
|
||||||
return array;
|
return array;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -104,9 +104,6 @@ Network.prototype._onData = function(data, isInbound) {
|
||||||
case 'disconnect':
|
case 'disconnect':
|
||||||
this._onClose(obj.sender);
|
this._onClose(obj.sender);
|
||||||
break;
|
break;
|
||||||
case 'walletId':
|
|
||||||
this.emit('walletId', obj.data.walletId);
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
this.emit('data', obj.sender, obj.data, isInbound);
|
this.emit('data', obj.sender, obj.data, isInbound);
|
||||||
}
|
}
|
||||||
|
@ -123,8 +120,6 @@ Network.prototype._sendPeers = function(peerIds) {
|
||||||
Network.prototype._addPeer = function(peerId, isInbound) {
|
Network.prototype._addPeer = function(peerId, isInbound) {
|
||||||
|
|
||||||
var hasChanged = Network._arrayPushOnce(peerId, this.connectedPeers);
|
var hasChanged = Network._arrayPushOnce(peerId, this.connectedPeers);
|
||||||
|
|
||||||
|
|
||||||
if (isInbound && hasChanged) {
|
if (isInbound && hasChanged) {
|
||||||
this._sendPeers(); //broadcast peer list
|
this._sendPeers(); //broadcast peer list
|
||||||
}
|
}
|
||||||
|
@ -184,18 +179,16 @@ Network.prototype._setupPeerHandlers = function(openCallback) {
|
||||||
var self=this;
|
var self=this;
|
||||||
var p = this.peer;
|
var p = this.peer;
|
||||||
|
|
||||||
p.on('open', function(peerId) {
|
p.on('open', function() {
|
||||||
self.peerId = peerId;
|
self.connectedPeers = [self.peerId];
|
||||||
self.connectedPeers = [peerId];
|
|
||||||
self._notifyNetworkChange();
|
console.log('[WebRTC.js.187] LENGTH', self.connectedPeers.length); //TODO
|
||||||
return openCallback(peerId);
|
return openCallback();
|
||||||
});
|
});
|
||||||
|
|
||||||
p.on('error', function(err) {
|
p.on('error', function(err) {
|
||||||
console.log('### PEER ERROR:', err);
|
console.log('### PEER ERROR:', err);
|
||||||
self.peer.disconnect();
|
//self.disconnect(null, true); // force disconnect
|
||||||
self.peer.destroy();
|
|
||||||
self.peer = null;
|
|
||||||
self._checkAnyPeer();
|
self._checkAnyPeer();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -215,12 +208,33 @@ Network.prototype._setupPeerHandlers = function(openCallback) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
Network.prototype.start = function(openCallback) {
|
Network.prototype.setPeerId = function(peerId) {
|
||||||
|
if (this.started) {
|
||||||
|
throw new Error ('network already started: can not change peerId')
|
||||||
|
}
|
||||||
|
this.peerId = peerId;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Network.prototype.start = function(openCallback, opts) {
|
||||||
|
opts = opts || {};
|
||||||
// Start PeerJS Peer
|
// Start PeerJS Peer
|
||||||
if (this.peer) return openCallback(); // This is for connectTo-> peer is started before
|
var self = this;
|
||||||
|
|
||||||
|
if (this.started) return openCallback();
|
||||||
|
|
||||||
|
opts.connectedPeers = opts.connectedPeers || [];
|
||||||
|
this.peerId = this.peerId || opts.peerId;
|
||||||
|
|
||||||
this.peer = new Peer(this.peerId, this.opts);
|
this.peer = new Peer(this.peerId, this.opts);
|
||||||
this._setupPeerHandlers(openCallback);
|
this._setupPeerHandlers(openCallback);
|
||||||
|
for (var i = 0; i<opts.connectedPeers.length; i++) {
|
||||||
|
var otherPeerId = opts.connectedPeers[i];
|
||||||
|
this.connectTo(otherPeerId);
|
||||||
|
}
|
||||||
|
this.started = true;
|
||||||
|
|
||||||
|
console.log('[WebRTC.js.237] started TRUE'); //TODO
|
||||||
};
|
};
|
||||||
|
|
||||||
Network.prototype._sendToOne = function(peerId, data, cb) {
|
Network.prototype._sendToOne = function(peerId, data, cb) {
|
||||||
|
@ -267,7 +281,7 @@ console.log('[WebRTC.js.258:peerId:]',peerId); //TODO
|
||||||
Network.prototype.connectTo = function(peerId) {
|
Network.prototype.connectTo = function(peerId) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
console.log('### STARTING TO CONNECT TO:' + peerId );
|
console.log('### STARTING CONNECTION TO:' + peerId );
|
||||||
|
|
||||||
var dataConn = this.peer.connect(peerId, {
|
var dataConn = this.peer.connect(peerId, {
|
||||||
serialization: 'none',
|
serialization: 'none',
|
||||||
|
@ -279,11 +293,12 @@ Network.prototype.connectTo = function(peerId) {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
Network.prototype.disconnect = function(cb) {
|
Network.prototype.disconnect = function(cb, forced) {
|
||||||
var self = this;
|
var self = this;
|
||||||
self.closing = 1;
|
self.closing = 1;
|
||||||
this.send(null, { type: 'disconnect' }, function() {
|
var cleanUp = function() {
|
||||||
self.connectedPeers = [];
|
self.connectedPeers = [];
|
||||||
|
self.started = false;
|
||||||
self.peerId = null;
|
self.peerId = null;
|
||||||
if (self.peer) {
|
if (self.peer) {
|
||||||
self.peer.disconnect();
|
self.peer.disconnect();
|
||||||
|
@ -292,7 +307,12 @@ Network.prototype.disconnect = function(cb) {
|
||||||
}
|
}
|
||||||
self.closing = 0;
|
self.closing = 0;
|
||||||
if (typeof cb === 'function') cb();
|
if (typeof cb === 'function') cb();
|
||||||
});
|
};
|
||||||
|
if (!forced) {
|
||||||
|
this.send(null, { type: 'disconnect' }, cleanUp);
|
||||||
|
} else {
|
||||||
|
cleanUp();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = require('soop')(Network);
|
module.exports = require('soop')(Network);
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
var imports = require('soop').imports();
|
var imports = require('soop').imports();
|
||||||
var fs = imports.fs || require('fs');
|
var fs = imports.fs || require('fs');
|
||||||
var parent = imports.parent || require('./Base');
|
var parent = imports.parent || require('./Base');
|
||||||
var crypto = imports.crypto || require('crypto');
|
|
||||||
var CryptoJS = require('node-cryptojs-aes').CryptoJS;
|
var CryptoJS = require('node-cryptojs-aes').CryptoJS;
|
||||||
|
|
||||||
var passwords = [];
|
var passwords = [];
|
||||||
|
@ -15,8 +14,33 @@ function Storage(opts) {
|
||||||
}
|
}
|
||||||
Storage.parent = parent;
|
Storage.parent = parent;
|
||||||
|
|
||||||
|
Storage.prototype._encrypt = function(string) {
|
||||||
|
var encrypted = CryptoJS.AES.encrypt(string, passwords[0]);
|
||||||
|
var encryptedBase64 = encrypted.toString();
|
||||||
|
return encryptedBase64;
|
||||||
|
};
|
||||||
|
|
||||||
|
Storage.prototype._encryptObj = function(obj) {
|
||||||
|
var string = JSON.stringify(obj);
|
||||||
|
return this._encrypt(string);
|
||||||
|
};
|
||||||
|
|
||||||
|
Storage.prototype._decrypt = function(base64) {
|
||||||
|
var decrypted = CryptoJS.AES.decrypt(base64, passwords[0]);
|
||||||
|
var decryptedStr = decrypted.toString(CryptoJS.enc.Utf8);
|
||||||
|
return decryptedStr;
|
||||||
|
};
|
||||||
|
|
||||||
|
Storage.prototype._decryptObj = function(base64) {
|
||||||
|
var decryptedStr = this._decrypt(base64);
|
||||||
|
return JSON.parse(decryptedStr);
|
||||||
|
};
|
||||||
|
|
||||||
Storage.prototype.load = function(walletId, callback) {
|
Storage.prototype.load = function(walletId, callback) {
|
||||||
fs.readFile(walletId, function(err, data) {
|
var self = this;
|
||||||
|
fs.readFile(walletId, function(err, base64) {
|
||||||
|
var data = self._decryptObj(base64);
|
||||||
|
|
||||||
if (err) return callback(err);
|
if (err) return callback(err);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -32,10 +56,11 @@ Storage.prototype.load = function(walletId, callback) {
|
||||||
};
|
};
|
||||||
|
|
||||||
Storage.prototype.save = function(walletId, callback) {
|
Storage.prototype.save = function(walletId, callback) {
|
||||||
var data = JSON.stringify(this.data[walletId]);
|
var obj = this.data[walletId];
|
||||||
|
var encryptedBase64 = this._encryptObj(obj);
|
||||||
|
|
||||||
//TODO: update to use a queue to ensure that saves are made sequentially
|
//TODO: update to use a queue to ensure that saves are made sequentially
|
||||||
fs.writeFile(walletId, data, function(err) {
|
fs.writeFile(walletId, encryptedBase64, function(err) {
|
||||||
if (callback)
|
if (callback)
|
||||||
return callback(err);
|
return callback(err);
|
||||||
});
|
});
|
||||||
|
@ -105,16 +130,15 @@ Storage.prototype.setFromObj = function(walletId, obj, callback) {
|
||||||
this.save(walletId, callback);
|
this.save(walletId, callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
Storage.prototype.setFromEncryptedObj = function(walletId) {
|
Storage.prototype.setFromEncryptedObj = function(walletId, base64, callback) {
|
||||||
//TODO: implement
|
var obj = this._decryptObj(base64);
|
||||||
|
this.setFromObj(walletId, obj, callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
Storage.prototype.getEncryptedObj = function(walletId) {
|
Storage.prototype.getEncryptedObj = function(walletId) {
|
||||||
var data = JSON.stringify(this.data[walletId]);
|
var encryptedBase64 = this._encryptObj(this.data[walletId]);
|
||||||
var encrypted = CryptoJS.AES.encrypt(data, passwords[0]);
|
|
||||||
var hex = CryptoJS.enc.Hex.stringify(CryptoJS.enc.Base64.parse(encrypted.toString()));
|
|
||||||
|
|
||||||
return hex;
|
return encryptedBase64;
|
||||||
};
|
};
|
||||||
|
|
||||||
// remove all values
|
// remove all values
|
||||||
|
|
|
@ -25,12 +25,26 @@ Storage.prototype._setPassphrase = function(password) {
|
||||||
pps[this.__uniqueid] = password;
|
pps[this.__uniqueid] = password;
|
||||||
}
|
}
|
||||||
|
|
||||||
Storage.prototype._encrypt = function(data) {
|
Storage.prototype._encrypt = function(string) {
|
||||||
return CryptoJS.AES.encrypt(data, this._getPassphrase());
|
var encrypted = CryptoJS.AES.encrypt(string, this._getPassphrase());
|
||||||
|
var encryptedBase64 = encrypted.toString();
|
||||||
|
return encryptedBase64;
|
||||||
};
|
};
|
||||||
|
|
||||||
Storage.prototype._decrypt = function(encrypted) {
|
Storage.prototype._encryptObj = function(obj) {
|
||||||
return CryptoJS.AES.decrypt(encrypted, this._getPassphrase());
|
var string = JSON.stringify(obj);
|
||||||
|
return this._encrypt(string);
|
||||||
|
};
|
||||||
|
|
||||||
|
Storage.prototype._decrypt = function(base64) {
|
||||||
|
var decrypted = CryptoJS.AES.decrypt(base64, this._getPassphrase());
|
||||||
|
var decryptedStr = decrypted.toString(CryptoJS.enc.Utf8);
|
||||||
|
return decryptedStr;
|
||||||
|
};
|
||||||
|
|
||||||
|
Storage.prototype._decryptObj = function(base64) {
|
||||||
|
var decryptedStr = this._decrypt(base64);
|
||||||
|
return JSON.parse(decryptedStr);
|
||||||
};
|
};
|
||||||
|
|
||||||
Storage.prototype._read = function(k) {
|
Storage.prototype._read = function(k) {
|
||||||
|
@ -53,6 +67,17 @@ Storage.prototype._write = function(k,v) {
|
||||||
localStorage.setItem(k, v);
|
localStorage.setItem(k, v);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Storage.prototype.setFromObj = function(walletId, obj) {
|
||||||
|
for (var i in keys) {
|
||||||
|
var key = keys[0];
|
||||||
|
obj[key] = this.get(walletId, key);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Storage.prototype.setFromEncryptedObj = function(walletId, base64) {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
Storage.prototype.getEncryptedObj = function(walletId) {
|
Storage.prototype.getEncryptedObj = function(walletId) {
|
||||||
var keys = this._getWalletKeys();
|
var keys = this._getWalletKeys();
|
||||||
var obj = {};
|
var obj = {};
|
||||||
|
@ -62,9 +87,9 @@ Storage.prototype.getEncryptedObj = function(walletId) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var str = JSON.stringify(obj);
|
var str = JSON.stringify(obj);
|
||||||
var hex = CryptoJS.enc.Hex.stringify(CryptoJS.enc.Base64.parse(this._encrypt(str).toString()));
|
var base64 = this._encrypt(str).toString();
|
||||||
|
|
||||||
return hex;
|
return base64;
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = require('soop')(Storage);
|
module.exports = require('soop')(Storage);
|
||||||
|
|
|
@ -27,6 +27,7 @@ angular.module('copay.controllerUtils').factory('controllerUtils', function ($ro
|
||||||
});
|
});
|
||||||
|
|
||||||
w.on('created', function() {
|
w.on('created', function() {
|
||||||
|
console.log('[controllerUtils.js.30:created:] RECV '); //TODO
|
||||||
$location.path('peer');
|
$location.path('peer');
|
||||||
$rootScope.wallet = w;
|
$rootScope.wallet = w;
|
||||||
|
|
||||||
|
@ -41,6 +42,8 @@ angular.module('copay.controllerUtils').factory('controllerUtils', function ($ro
|
||||||
});
|
});
|
||||||
w.on('openError', root.onErrorDigest);
|
w.on('openError', root.onErrorDigest);
|
||||||
w.on('close', root.onErrorDigest);
|
w.on('close', root.onErrorDigest);
|
||||||
|
w.netStart();
|
||||||
|
console.log('[controllerUtils.js.45] setupUxHandlers END'); //TODO
|
||||||
};
|
};
|
||||||
|
|
||||||
root.setSocketHandlers = function(cb) {
|
root.setSocketHandlers = function(cb) {
|
||||||
|
|
375
lib/bitcore.js
375
lib/bitcore.js
File diff suppressed because one or more lines are too long
|
@ -0,0 +1 @@
|
||||||
|
../../bitcore/browser/bundle.js
|
|
@ -0,0 +1,27 @@
|
||||||
|
|
||||||
|
var imports = require('soop').imports();
|
||||||
|
var EventEmitter= imports.EventEmitter || require('events').EventEmitter;
|
||||||
|
|
||||||
|
function Network(opts) {
|
||||||
|
}
|
||||||
|
|
||||||
|
Network.parent=EventEmitter;
|
||||||
|
|
||||||
|
Network.prototype.start = function(openCallback, opts) {
|
||||||
|
// start! :D
|
||||||
|
};
|
||||||
|
|
||||||
|
Network.prototype.send = function(peerIds, data, cb) {
|
||||||
|
// send! c:
|
||||||
|
};
|
||||||
|
|
||||||
|
Network.prototype.connectTo = function(peerId) {
|
||||||
|
// connect C:
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Network.prototype.disconnect = function(cb) {
|
||||||
|
// disconect :c
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = require('soop')(Network);
|
|
@ -69,16 +69,16 @@ describe('PrivateKey model', function() {
|
||||||
|
|
||||||
it('should calculate .id', function () {
|
it('should calculate .id', function () {
|
||||||
var w1 = new PrivateKey(config);
|
var w1 = new PrivateKey(config);
|
||||||
should.exist(w1.id);
|
should.exist(w1.getId());
|
||||||
w1.id.length.should.equal(40);
|
w1.getId().length.should.equal(40);
|
||||||
});
|
});
|
||||||
it('fromObj toObj roundtrip', function () {
|
it('fromObj toObj roundtrip', function () {
|
||||||
var w1 = new PrivateKey(config);
|
var w1 = new PrivateKey(config);
|
||||||
var w2 = PrivateKey.fromObj(w1.toObj());
|
var o = JSON.parse(JSON.stringify(w1.toObj()))
|
||||||
|
var w2 = PrivateKey.fromObj(o);
|
||||||
|
|
||||||
w2.toObj().extendedPrivateKeyString.should.equal(w1.toObj().extendedPrivateKeyString);
|
w2.toObj().extendedPrivateKeyString.should.equal(w1.toObj().extendedPrivateKeyString);
|
||||||
w2.id.should.equal(w1.id);
|
w2.getId().should.equal(w1.getId());
|
||||||
|
|
||||||
|
|
||||||
JSON.stringify(w2.get(1,1).storeObj()).should
|
JSON.stringify(w2.get(1,1).storeObj()).should
|
||||||
.equal(JSON.stringify(w1.get(1,1).storeObj()));
|
.equal(JSON.stringify(w1.get(1,1).storeObj()));
|
||||||
|
|
|
@ -125,21 +125,22 @@ describe('TxProposals model', function() {
|
||||||
priv,
|
priv,
|
||||||
pkr
|
pkr
|
||||||
));
|
));
|
||||||
var tx = w.txps[0].builder.build();
|
var k = Object.keys(w.txps)[0];
|
||||||
|
var tx = w.txps[k].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[0].signedBy[priv.id] - ts > 0).should.equal(true);
|
(w.txps[k].signedBy[priv.id] - ts > 0).should.equal(true);
|
||||||
(w.txps[0].seenBy[priv.id] - ts > 0).should.equal(true);
|
(w.txps[k].seenBy[priv.id] - ts > 0).should.equal(true);
|
||||||
|
|
||||||
w.merge(w);
|
w.merge(w);
|
||||||
w.txps.length.should.equal(1);
|
Object.keys(w.txps).length.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);
|
||||||
|
|
||||||
(w.txps[0].signedBy[priv.id] - ts > 0).should.equal(true);
|
(w.txps[k].signedBy[priv.id] - ts > 0).should.equal(true);
|
||||||
(w.txps[0].seenBy[priv.id] - ts > 0).should.equal(true);
|
(w.txps[k].seenBy[priv.id] - ts > 0).should.equal(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
@ -168,12 +169,13 @@ describe('TxProposals model', function() {
|
||||||
pkr
|
pkr
|
||||||
));
|
));
|
||||||
|
|
||||||
var tx = w.txps[0].builder.build();
|
var k = Object.keys(w.txps)[0];
|
||||||
|
var tx = w.txps[k].builder.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[0].signedBy).length.should.equal(0);
|
Object.keys(w.txps[k].signedBy).length.should.equal(0);
|
||||||
Object.keys(w.txps[0].seenBy).length.should.equal(1);
|
Object.keys(w.txps[k].seenBy).length.should.equal(1);
|
||||||
|
|
||||||
|
|
||||||
var w2 = new TxProposals({
|
var w2 = new TxProposals({
|
||||||
|
@ -191,21 +193,22 @@ describe('TxProposals model', function() {
|
||||||
pkr
|
pkr
|
||||||
));
|
));
|
||||||
|
|
||||||
var tx = w2.txps[0].builder.build();
|
var k = Object.keys(w.txps)[0];
|
||||||
|
var tx = w2.txps[k].builder.build();
|
||||||
tx.isComplete().should.equal(false);
|
tx.isComplete().should.equal(false);
|
||||||
tx.countInputMissingSignatures(0).should.equal(2);
|
tx.countInputMissingSignatures(0).should.equal(2);
|
||||||
|
|
||||||
(w2.txps[0].signedBy[priv.id] - ts > 0).should.equal(true);
|
(w2.txps[k].signedBy[priv.id] - ts > 0).should.equal(true);
|
||||||
(w2.txps[0].seenBy[priv.id] - ts > 0).should.equal(true);
|
(w2.txps[k].seenBy[priv.id] - ts > 0).should.equal(true);
|
||||||
|
|
||||||
w.merge(w2);
|
w.merge(w2);
|
||||||
w.txps.length.should.equal(1);
|
Object.keys(w.txps).length.should.equal(1);
|
||||||
|
|
||||||
var tx = w.txps[0].builder.build();
|
var tx = w.txps[k].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[0].signedBy[priv.id] - ts > 0).should.equal(true);
|
(w.txps[k].signedBy[priv.id] - ts > 0).should.equal(true);
|
||||||
(w.txps[0].seenBy[priv.id] - ts > 0).should.equal(true);
|
(w.txps[k].seenBy[priv.id] - ts > 0).should.equal(true);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -243,12 +246,13 @@ var _dumpChunks = function (scriptSig, label) {
|
||||||
pkr
|
pkr
|
||||||
));
|
));
|
||||||
|
|
||||||
var tx = w.txps[0].builder.build();
|
var k = Object.keys(w.txps)[0];
|
||||||
|
var tx = w.txps[k].builder.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[0].signedBy).length.should.equal(0);
|
Object.keys(w.txps[k].signedBy).length.should.equal(0);
|
||||||
Object.keys(w.txps[0].seenBy).length.should.equal(1);
|
Object.keys(w.txps[k].seenBy).length.should.equal(1);
|
||||||
|
|
||||||
|
|
||||||
var w2 = new TxProposals({
|
var w2 = new TxProposals({
|
||||||
|
@ -265,21 +269,22 @@ var _dumpChunks = function (scriptSig, label) {
|
||||||
priv,
|
priv,
|
||||||
pkr
|
pkr
|
||||||
));
|
));
|
||||||
tx = w2.txps[0].builder.build();
|
var k = Object.keys(w2.txps)[0];
|
||||||
|
tx = w2.txps[k].builder.build();
|
||||||
tx.isComplete().should.equal(false);
|
tx.isComplete().should.equal(false);
|
||||||
tx.countInputMissingSignatures(0).should.equal(2);
|
tx.countInputMissingSignatures(0).should.equal(2);
|
||||||
|
|
||||||
(w2.txps[0].signedBy[priv.id] - ts > 0).should.equal(true);
|
(w2.txps[k].signedBy[priv.id] - ts > 0).should.equal(true);
|
||||||
(w2.txps[0].seenBy[priv.id] - ts > 0).should.equal(true);
|
(w2.txps[k].seenBy[priv.id] - ts > 0).should.equal(true);
|
||||||
|
|
||||||
w.merge(w2);
|
w.merge(w2);
|
||||||
w.txps.length.should.equal(1);
|
Object.keys(w.txps).length.should.equal(1);
|
||||||
|
|
||||||
tx = w.txps[0].builder.build();
|
tx = w.txps[k].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[0].signedBy[priv.id] - ts > 0).should.equal(true);
|
(w.txps[k].signedBy[priv.id] - ts > 0).should.equal(true);
|
||||||
(w.txps[0].seenBy[priv.id] - ts > 0).should.equal(true);
|
(w.txps[k].seenBy[priv.id] - ts > 0).should.equal(true);
|
||||||
|
|
||||||
|
|
||||||
var w3 = new TxProposals({
|
var w3 = new TxProposals({
|
||||||
|
@ -296,22 +301,22 @@ var _dumpChunks = function (scriptSig, label) {
|
||||||
priv2,
|
priv2,
|
||||||
pkr
|
pkr
|
||||||
));
|
));
|
||||||
tx = w3.txps[0].builder.build();
|
tx = w3.txps[k].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[0].signedBy[priv2.id] - ts > 0).should.equal(true);
|
(w3.txps[k].signedBy[priv2.id] - ts > 0).should.equal(true);
|
||||||
(w3.txps[0].seenBy[priv2.id] - ts > 0).should.equal(true);
|
(w3.txps[k].seenBy[priv2.id] - ts > 0).should.equal(true);
|
||||||
|
|
||||||
w.merge(w3);
|
w.merge(w3);
|
||||||
w.txps.length.should.equal(1);
|
Object.keys(w.txps).length.should.equal(1);
|
||||||
|
|
||||||
(w.txps[0].signedBy[priv.id] - ts > 0).should.equal(true);
|
(w.txps[k].signedBy[priv.id] - ts > 0).should.equal(true);
|
||||||
(w.txps[0].seenBy[priv.id] - ts > 0).should.equal(true);
|
(w.txps[k].seenBy[priv.id] - ts > 0).should.equal(true);
|
||||||
(w.txps[0].signedBy[priv2.id] - ts > 0).should.equal(true);
|
(w.txps[k].signedBy[priv2.id] - ts > 0).should.equal(true);
|
||||||
(w.txps[0].seenBy[priv2.id] - ts > 0).should.equal(true);
|
(w.txps[k].seenBy[priv2.id] - ts > 0).should.equal(true);
|
||||||
|
|
||||||
tx = w.txps[0].builder.build();
|
tx = w.txps[k].builder.build();
|
||||||
tx.isComplete().should.equal(false);
|
tx.isComplete().should.equal(false);
|
||||||
tx.countInputMissingSignatures(0).should.equal(1);
|
tx.countInputMissingSignatures(0).should.equal(1);
|
||||||
});
|
});
|
||||||
|
@ -341,11 +346,12 @@ var _dumpChunks = function (scriptSig, label) {
|
||||||
priv,
|
priv,
|
||||||
pkr
|
pkr
|
||||||
));
|
));
|
||||||
var tx = w.txps[0].builder.build();
|
var k = Object.keys(w.txps)[0];
|
||||||
|
var tx = w.txps[k].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[0].signedBy[priv.id] - ts > 0).should.equal(true);
|
(w.txps[k].signedBy[priv.id] - ts > 0).should.equal(true);
|
||||||
(w.txps[0].seenBy[priv.id] - ts > 0).should.equal(true);
|
(w.txps[k].seenBy[priv.id] - ts > 0).should.equal(true);
|
||||||
|
|
||||||
|
|
||||||
var w2 = new TxProposals({
|
var w2 = new TxProposals({
|
||||||
|
@ -361,11 +367,11 @@ var _dumpChunks = function (scriptSig, label) {
|
||||||
priv2,
|
priv2,
|
||||||
pkr
|
pkr
|
||||||
));
|
));
|
||||||
var tx = w2.txps[0].builder.build();
|
var tx = w2.txps[k].builder.build();
|
||||||
tx.isComplete().should.equal(false);
|
tx.isComplete().should.equal(false);
|
||||||
tx.countInputMissingSignatures(0).should.equal(2);
|
tx.countInputMissingSignatures(0).should.equal(2);
|
||||||
(w2.txps[0].signedBy[priv2.id] - ts > 0).should.equal(true);
|
(w2.txps[k].signedBy[priv2.id] - ts > 0).should.equal(true);
|
||||||
(w2.txps[0].seenBy[priv2.id] - ts > 0).should.equal(true);
|
(w2.txps[k].seenBy[priv2.id] - ts > 0).should.equal(true);
|
||||||
|
|
||||||
|
|
||||||
var w3 = new TxProposals({
|
var w3 = new TxProposals({
|
||||||
|
@ -381,34 +387,34 @@ var _dumpChunks = function (scriptSig, label) {
|
||||||
priv3,
|
priv3,
|
||||||
pkr
|
pkr
|
||||||
));
|
));
|
||||||
var tx = w3.txps[0].builder.build();
|
var tx = w3.txps[k].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[0].signedBy[priv3.id] - ts > 0).should.equal(true);
|
(w3.txps[k].signedBy[priv3.id] - ts > 0).should.equal(true);
|
||||||
(w3.txps[0].seenBy[priv3.id] - ts > 0).should.equal(true);
|
(w3.txps[k].seenBy[priv3.id] - ts > 0).should.equal(true);
|
||||||
|
|
||||||
w.merge(w2);
|
w.merge(w2);
|
||||||
w.txps.length.should.equal(1);
|
Object.keys(w.txps).length.should.equal(1);
|
||||||
var tx = w.txps[0].builder.build();
|
var tx = w.txps[k].builder.build();
|
||||||
tx.isComplete().should.equal(false);
|
tx.isComplete().should.equal(false);
|
||||||
tx.countInputMissingSignatures(0).should.equal(1);
|
tx.countInputMissingSignatures(0).should.equal(1);
|
||||||
(w.txps[0].seenBy[priv.id] - ts > 0).should.equal(true);
|
(w.txps[k].seenBy[priv.id] - ts > 0).should.equal(true);
|
||||||
(w.txps[0].seenBy[priv2.id] - ts > 0).should.equal(true);
|
(w.txps[k].seenBy[priv2.id] - ts > 0).should.equal(true);
|
||||||
(w.txps[0].signedBy[priv.id] - ts > 0).should.equal(true);
|
(w.txps[k].signedBy[priv.id] - ts > 0).should.equal(true);
|
||||||
(w.txps[0].signedBy[priv2.id] - ts > 0).should.equal(true);
|
(w.txps[k].signedBy[priv2.id] - ts > 0).should.equal(true);
|
||||||
|
|
||||||
|
|
||||||
w.merge(w3);
|
w.merge(w3);
|
||||||
var tx = w.txps[0].builder.build();
|
var tx = w.txps[k].builder.build();
|
||||||
tx.isComplete().should.equal(true);
|
tx.isComplete().should.equal(true);
|
||||||
tx.countInputMissingSignatures(0).should.equal(0);
|
tx.countInputMissingSignatures(0).should.equal(0);
|
||||||
w.txps.length.should.equal(1);
|
Object.keys(w.txps).length.should.equal(1);
|
||||||
(w.txps[0].seenBy[priv.id] - ts > 0).should.equal(true);
|
(w.txps[k].seenBy[priv.id] - ts > 0).should.equal(true);
|
||||||
(w.txps[0].seenBy[priv2.id] - ts > 0).should.equal(true);
|
(w.txps[k].seenBy[priv2.id] - ts > 0).should.equal(true);
|
||||||
(w.txps[0].seenBy[priv3.id] - ts > 0).should.equal(true);
|
(w.txps[k].seenBy[priv3.id] - ts > 0).should.equal(true);
|
||||||
(w.txps[0].signedBy[priv.id] - ts > 0).should.equal(true);
|
(w.txps[k].signedBy[priv.id] - ts > 0).should.equal(true);
|
||||||
(w.txps[0].signedBy[priv2.id] - ts > 0).should.equal(true);
|
(w.txps[k].signedBy[priv2.id] - ts > 0).should.equal(true);
|
||||||
(w.txps[0].signedBy[priv3.id] - ts > 0).should.equal(true);
|
(w.txps[k].signedBy[priv3.id] - ts > 0).should.equal(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
@ -435,11 +441,12 @@ var _dumpChunks = function (scriptSig, label) {
|
||||||
priv,
|
priv,
|
||||||
pkr
|
pkr
|
||||||
));
|
));
|
||||||
var tx = w.txps[0].builder.build();
|
var k = Object.keys(w.txps)[0];
|
||||||
|
var tx = w.txps[k].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[0].signedBy[priv.id] - ts > 0).should.equal(true);
|
(w.txps[k].signedBy[priv.id] - ts > 0).should.equal(true);
|
||||||
(w.txps[0].seenBy[priv.id] - ts > 0).should.equal(true);
|
(w.txps[k].seenBy[priv.id] - ts > 0).should.equal(true);
|
||||||
|
|
||||||
var o = w.toObj();
|
var o = w.toObj();
|
||||||
should.exist(o);
|
should.exist(o);
|
||||||
|
@ -451,18 +458,22 @@ var _dumpChunks = function (scriptSig, label) {
|
||||||
should.exist(o.txps[0].builderObj.valueInSat);
|
should.exist(o.txps[0].builderObj.valueInSat);
|
||||||
should.exist(o.txps[0].signedBy[priv.id]);
|
should.exist(o.txps[0].signedBy[priv.id]);
|
||||||
|
|
||||||
var w2 = TxProposals.fromObj(o);
|
var o2 = JSON.parse(JSON.stringify(o));
|
||||||
|
var w2 = TxProposals.fromObj(o2);
|
||||||
w2.walletId.should.equal(w.walletId);
|
w2.walletId.should.equal(w.walletId);
|
||||||
var tx2 = w2.txps[0].builder.build();
|
var tx2 = w2.txps[k].builder.build();
|
||||||
tx2.isComplete().should.equal(false);
|
tx2.isComplete().should.equal(false);
|
||||||
tx2.countInputMissingSignatures(0).should.equal(2);
|
tx2.countInputMissingSignatures(0).should.equal(2);
|
||||||
(w2.txps[0].signedBy[priv.id] - ts > 0).should.equal(true);
|
(w2.txps[k].signedBy[priv.id] - ts > 0).should.equal(true);
|
||||||
(w2.txps[0].seenBy[priv.id] - ts > 0).should.equal(true);
|
(w2.txps[k].seenBy[priv.id] - ts > 0).should.equal(true);
|
||||||
should.exist(w2.txps[0].builder);
|
should.exist(w2.txps[k].builder);
|
||||||
should.exist(w2.txps[0].builder.valueInSat);
|
should.exist(w2.txps[k].builder.valueInSat);
|
||||||
|
|
||||||
w2.merge(w);
|
w2.merge(w);
|
||||||
|
Object.keys(w2.txps).length.should.equal(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -126,11 +126,12 @@ describe('Wallet model', function() {
|
||||||
);
|
);
|
||||||
|
|
||||||
var t = w.txProposals;
|
var t = w.txProposals;
|
||||||
var tx = t.txps[0].builder.build();
|
var k = Object.keys(t.txps)[0];
|
||||||
|
var tx = t.txps[k].builder.build();
|
||||||
should.exist(tx);
|
should.exist(tx);
|
||||||
tx.isComplete().should.equal(false);
|
tx.isComplete().should.equal(false);
|
||||||
Object.keys(t.txps[0].signedBy).length.should.equal(1);
|
Object.keys(t.txps[k].signedBy).length.should.equal(1);
|
||||||
Object.keys(t.txps[0].seenBy).length.should.equal(1);
|
Object.keys(t.txps[k].seenBy).length.should.equal(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('#addressIsOwn', function () {
|
it('#addressIsOwn', function () {
|
||||||
|
@ -157,13 +158,14 @@ describe('Wallet model', function() {
|
||||||
unspentTest
|
unspentTest
|
||||||
);
|
);
|
||||||
var t = w.txProposals;
|
var t = w.txProposals;
|
||||||
var tx = t.txps[0].builder.build();
|
var k = Object.keys(t.txps)[0];
|
||||||
|
var tx = t.txps[k].builder.build();
|
||||||
should.exist(tx);
|
should.exist(tx);
|
||||||
tx.isComplete().should.equal(false);
|
tx.isComplete().should.equal(false);
|
||||||
tx.countInputMissingSignatures(0).should.equal(2);
|
tx.countInputMissingSignatures(0).should.equal(2);
|
||||||
|
|
||||||
( t.txps[0].signedBy[w.privateKey.id] - ts > 0).should.equal(true);
|
( t.txps[k].signedBy[w.privateKey.getId()] - ts > 0).should.equal(true);
|
||||||
( t.txps[0].seenBy[w.privateKey.id] - ts > 0).should.equal(true);
|
( t.txps[k].seenBy[w.privateKey.getId()] - ts > 0).should.equal(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -3,12 +3,12 @@
|
||||||
var chai = chai || require('chai');
|
var chai = chai || require('chai');
|
||||||
var should = chai.should();
|
var should = chai.should();
|
||||||
|
|
||||||
var WebRTC = require('../js/models/network/WebRTC');
|
var FakeNetwork = require('./mocks/FakeNetwork');
|
||||||
var Insight = require('../js/models/blockchain/Insight');
|
var Insight = require('../js/models/blockchain/Insight');
|
||||||
var FakeStorage = require('./mocks/FakeStorage');
|
var FakeStorage = require('./mocks/FakeStorage');
|
||||||
|
|
||||||
var WalletFactory = typeof copay === 'undefined' ? require('soop').load('../js/models/core/WalletFactory',{
|
var WalletFactory = typeof copay === 'undefined' ? require('soop').load('../js/models/core/WalletFactory',{
|
||||||
Network: WebRTC,
|
Network: FakeNetwork,
|
||||||
Blockchain: Insight,
|
Blockchain: Insight,
|
||||||
Storage: FakeStorage,
|
Storage: FakeStorage,
|
||||||
}) : copay.WalletFactory;
|
}) : copay.WalletFactory;
|
||||||
|
|
|
@ -17,7 +17,9 @@ describe('Storage/File', function() {
|
||||||
var fs = {}
|
var fs = {}
|
||||||
fs.readFile = function(filename, callback) {
|
fs.readFile = function(filename, callback) {
|
||||||
filename.should.equal('myfilename');
|
filename.should.equal('myfilename');
|
||||||
callback();
|
var obj = {"test":"test"};
|
||||||
|
var encryptedStr = CryptoJS.AES.encrypt(JSON.stringify(obj), "password").toString();
|
||||||
|
callback(null, encryptedStr);
|
||||||
};
|
};
|
||||||
var Storage = require('soop').load('../js/models/storage/File.js', {fs: fs});
|
var Storage = require('soop').load('../js/models/storage/File.js', {fs: fs});
|
||||||
var storage = new Storage({password: 'password'});
|
var storage = new Storage({password: 'password'});
|
||||||
|
@ -156,15 +158,16 @@ describe('Storage/File', function() {
|
||||||
var obj = {test:'testval'};
|
var obj = {test:'testval'};
|
||||||
var data = JSON.stringify(obj);
|
var data = JSON.stringify(obj);
|
||||||
var encrypted = CryptoJS.AES.encrypt(data, 'password');
|
var encrypted = CryptoJS.AES.encrypt(data, 'password');
|
||||||
var hex = CryptoJS.enc.Hex.stringify(CryptoJS.enc.Base64.parse(encrypted.toString()));
|
var base64 = encrypted.toString();
|
||||||
|
|
||||||
var storage = new Storage({password: 'password'});
|
var storage = new Storage({password: 'password'});
|
||||||
storage.data['walletId'] = obj;
|
storage.data['walletId'] = obj;
|
||||||
|
|
||||||
var enc = storage.getEncryptedObj('walletId');
|
var enc = storage.getEncryptedObj('walletId');
|
||||||
enc.length.should.equal(96);
|
//enc.length.should.equal(96);
|
||||||
enc.slice(0,10).should.equal(hex.slice(0,10));
|
enc.length.should.be.greaterThan(10);
|
||||||
enc.slice(0,6).should.equal("53616c");
|
enc.slice(0,10).should.equal(base64.slice(0,10));
|
||||||
|
//enc.slice(0,6).should.equal("53616c");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -53,8 +53,8 @@ if (typeof process === 'undefined' || !process.version) {
|
||||||
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.getEncryptedObj('walletId');
|
||||||
encrypted.length.should.equal(96);
|
encrypted.length.should.be.greaterThan(10);
|
||||||
encrypted.slice(0,6).should.equal("53616c");
|
//encrypted.slice(0,6).should.equal("53616c");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue