diff --git a/API.js b/API.js
new file mode 100644
index 000000000..5b4a969ed
--- /dev/null
+++ b/API.js
@@ -0,0 +1,184 @@
+var WalletFactory = require('./js/models/core/WalletFactory');
+
+var API = function(opts) {
+ this._init(opts);
+};
+
+API.prototype._init = function(opts) {
+ var self = this;
+
+ opts = opts || {};
+ self.opts = opts;
+
+ this.walletFactory = new WalletFactory(opts);
+};
+
+API._coerceArgTypes = function(args, argTypes) {
+ for (var i in args) {
+ var arg = args[i];
+ var argType = argTypes[i][1];
+ if (typeof arg == 'string') {
+ switch (argType) {
+ case 'object':
+ args[i] = JSON.parse(arg);
+ break;
+ case 'number':
+ args[i] = Number(arg);
+ break;
+ }
+ }
+ }
+
+ return args;
+};
+
+API.prototype._command = function(command, args, callback) {
+ var self = this;
+
+ if (!command || command[0] == "_")
+ return callback(new Error('invalid command'));
+
+ if (!API._checkArgTypes(command, args)) {
+ var argTypes = API.prototype[command].argTypes;
+ API._coerceArgTypes(args, argTypes)
+ if (!API._checkArgTypes(command, args))
+ throw new Error('invalid arguments');
+ }
+
+ if (typeof self["_cmd_" + command] == 'function') {
+ var f = API.prototype[command];
+ if (f.argTypes[f.argTypes.length - 1][1] == 'function')
+ return self["_cmd_" + command].apply(self, args.concat([callback]));
+ else
+ return callback(null, self["_cmd_" + command].apply(self, args));
+ };
+
+ return callback(new Error('invalid command'));
+};
+
+API._checkArgTypes = function(command, args) {
+ var f = API.prototype[command];
+
+ if (f.argTypes.length != args.length) {
+
+ //if the function doesn't have a callback
+ if (!(f.argTypes.length == args.length + 1 && f.argTypes[f.argTypes.length - 1][1] == 'function'))
+ return false;
+ }
+
+ for (var i in args) {
+ if (typeof args[i] != f.argTypes[i][1])
+ return false;
+ }
+ return true;
+};
+
+function decorate(command, argTypes) {
+ var d = function() {
+ API.prototype._command.call(this, command, Array.prototype.slice.call(arguments, 0));
+ };
+
+ d.argTypes = argTypes;
+
+ return d;
+};
+
+API.prototype._cmd_echo = function(str, callback) {
+ var self = this;
+
+ return callback(null, str);
+};
+
+API.prototype.echo = decorate('echo', [
+ ['str', 'string'],
+ ['callback', 'function']
+]);
+
+API.prototype._cmd_echoNumber = function(num, callback) {
+ var self = this;
+
+ return callback(null, num);
+};
+
+API.prototype.echoNumber = decorate('echoNumber', [
+ ['num', 'number'],
+ ['callback', 'function']
+]);
+
+API.prototype._cmd_echoObject = function(obj, callback) {
+ var self = this;
+
+ return callback(null, obj);
+};
+
+API.prototype.echoObject = decorate('echoObject', [
+ ['obj', 'object'],
+ ['callback', 'function']
+]);
+
+/*
+API.prototype.getBalance = function(callback) {
+ var self = this;
+
+ return callback(null, self.wallet.getBalance([]));
+};
+
+API.prototype.getBalance.argTypes =
+ [
+ ['callback', 'function']
+ ];
+*/
+
+API.prototype._cmd_getArgTypes = function(command, callback) {
+ var self = this;
+
+ if (command[0] == '_' || typeof API.prototype[command] != 'function')
+ return callback(new Error('Invalid command'));
+
+ var argTypes = API.prototype[command].argTypes;
+
+ return callback(null, argTypes);
+};
+
+API.prototype.getArgTypes = decorate('getArgTypes', [
+ ['command', 'string'],
+ ['callback', 'function']
+]);
+
+API.prototype._cmd_getCommands = function(callback) {
+ var self = this;
+
+ var fs = [];
+
+ for (var i in API.prototype) {
+ var f = API.prototype[i];
+ if (typeof f == 'function' && i[0] != "_")
+ fs.push(i);
+ };
+
+ return callback(null, fs);
+};
+
+API.prototype.getCommands = decorate('getCommands', [
+ ['callback', 'function']
+]);
+
+API.prototype._cmd_getWallets = function(callback) {
+ var self = this;
+
+ return callback(null, self.walletFactory.getWallets());
+};
+
+API.prototype.getWallets = decorate('getWallets', [
+ ['callback', 'function']
+]);
+
+API.prototype._cmd_help = function(callback) {
+ this._cmd_getCommands.apply(this, arguments);
+};
+
+API.prototype.help = decorate('help', [
+ ['callback', 'function']
+]);
+
+module.exports = API;
diff --git a/js/models/blockchain/Insight.js b/js/models/blockchain/Insight.js
index bafde9861..b0a0b7654 100644
--- a/js/models/blockchain/Insight.js
+++ b/js/models/blockchain/Insight.js
@@ -1,6 +1,5 @@
'use strict';
-var imports = require('soop').imports();
var bitcore = require('bitcore');
var coinUtil = bitcore.util;
var preconditions = require('preconditions').singleton();
@@ -286,4 +285,4 @@ Insight.prototype._request = function(options, callback) {
}
};
-module.exports = require('soop')(Insight);
+module.exports = Insight;
diff --git a/js/models/core/Message.js b/js/models/core/Message.js
index b8b37f772..ad6324440 100644
--- a/js/models/core/Message.js
+++ b/js/models/core/Message.js
@@ -1,6 +1,5 @@
'use strict';
-var imports = require('soop').imports();
var bitcore = require('bitcore');
/* Encrypted, authenticated messages to be shared between copayers */
@@ -146,4 +145,4 @@ Message._verify = function(pubkey, signature, payload) {
return v;
};
-module.exports = require('soop')(Message);
+module.exports = Message;
diff --git a/js/models/core/Wallet.js b/js/models/core/Wallet.js
index 81dda34f5..2a4fa7542 100644
--- a/js/models/core/Wallet.js
+++ b/js/models/core/Wallet.js
@@ -1,8 +1,8 @@
'use strict';
-var imports = require('soop').imports();
var http = require('http');
-var EventEmitter = imports.EventEmitter || require('events').EventEmitter;
+var EventEmitter = require('events').EventEmitter;
+var nodeUtil = require('util');
var async = require('async');
var preconditions = require('preconditions').singleton();
var parseBitcoinURI = require('./HDPath').parseBitcoinURI;
@@ -64,6 +64,7 @@ function Wallet(opts) {
this.network.setHexNonces(opts.networkNonces);
}
+nodeUtil.inherits(Wallet, EventEmitter);
Wallet.builderOpts = {
lockTime: null,
@@ -72,7 +73,6 @@ Wallet.builderOpts = {
feeSat: null,
};
-Wallet.parent = EventEmitter;
Wallet.prototype.log = function() {
if (!this.verbose) return;
if (console)
@@ -1849,4 +1849,4 @@ Wallet.request = function(options, callback) {
return ret;
};
-module.exports = require('soop')(Wallet);
+module.exports = Wallet;
diff --git a/js/models/core/WalletFactory.js b/js/models/core/WalletFactory.js
index cc56cd976..f40a02e4d 100644
--- a/js/models/core/WalletFactory.js
+++ b/js/models/core/WalletFactory.js
@@ -1,7 +1,5 @@
'use strict';
-var imports = require('soop').imports();
-
var TxProposals = require('./TxProposals');
var PublicKeyRing = require('./PublicKeyRing');
var PrivateKey = require('./PrivateKey');
@@ -235,7 +233,6 @@ WalletFactory.prototype.joinCreateSession = function(secret, nickname, passphras
});
self.network.on('serverError', function() {
- console.log('[WalletFactory.js.236]'); //TODO
return cb('joinError');
});
@@ -260,4 +257,4 @@ WalletFactory.prototype.joinCreateSession = function(secret, nickname, passphras
});
};
-module.exports = require('soop')(WalletFactory);
+module.exports = WalletFactory;
diff --git a/js/models/network/WebRTC.js b/js/models/network/WebRTC.js
index ea88c890a..256bc3ec7 100644
--- a/js/models/network/WebRTC.js
+++ b/js/models/network/WebRTC.js
@@ -1,10 +1,9 @@
'use strict';
-var imports = require('soop').imports();
-var EventEmitter = imports.EventEmitter || require('events').EventEmitter;
+var EventEmitter = require('events').EventEmitter;
var bitcore = require('bitcore');
var util = bitcore.util;
-var extend = require('util')._extend;
+var nodeUtil = require('util');
var Message = require('../core/Message');
/*
* Emits
@@ -39,7 +38,7 @@ function Network(opts) {
this.cleanUp();
}
-Network.parent = EventEmitter;
+nodeUtil.inherits(Network, EventEmitter);
Network.prototype.cleanUp = function() {
this.started = false;
@@ -64,7 +63,6 @@ Network.prototype.cleanUp = function() {
this.removeAllListeners();
};
-Network.parent = EventEmitter;
// Array helpers
Network._arrayDiff = function(a, b) {
@@ -524,4 +522,4 @@ Network.prototype.disconnect = function(cb, forced) {
});
};
-module.exports = require('soop')(Network);
+module.exports = Network;
diff --git a/js/models/storage/File.js b/js/models/storage/File.js
index abee8ee6b..ec0880145 100644
--- a/js/models/storage/File.js
+++ b/js/models/storage/File.js
@@ -1,6 +1,5 @@
'use strict';
-var imports = require('soop').imports();
-var fs = imports.fs || require('fs');
+var fs = require('fs');
var CryptoJS = require('node-cryptojs-aes').CryptoJS;
var passwords = [];
@@ -37,6 +36,8 @@ Storage.prototype._decryptObj = function(base64) {
Storage.prototype.load = function(walletId, callback) {
var self = this;
fs.readFile(walletId, function(err, base64) {
+ if (typeof base64 !== 'string')
+ base64 = base64.toString();
var data = self._decryptObj(base64);
if (err) return callback(err);
@@ -145,4 +146,4 @@ Storage.prototype.clearAll = function(callback) {
this.save(callback);
};
-module.exports = require('soop')(Storage);
+module.exports = Storage;
diff --git a/js/models/storage/LocalEncrypted.js b/js/models/storage/LocalEncrypted.js
index 0ea61f217..da1d99742 100644
--- a/js/models/storage/LocalEncrypted.js
+++ b/js/models/storage/LocalEncrypted.js
@@ -1,6 +1,6 @@
'use strict';
-var imports = require('soop').imports();
+var CryptoJS = require('node-cryptojs-aes').CryptoJS;
var id = 0;
@@ -215,4 +215,4 @@ Storage.prototype.import = function(base64) {
return decryptedObj;
};
-module.exports = require('soop')(Storage);
+module.exports = Storage;
diff --git a/package.json b/package.json
index 0509e251e..d41d1a13a 100644
--- a/package.json
+++ b/package.json
@@ -36,34 +36,38 @@
"bitcoin"
],
"devDependencies": {
- "mocha-lcov-reporter": "0.0.1",
- "travis-cov": "0.2.5",
- "chai": "1.9.1",
+ "async": "0.9.0",
+ "blanket": "1.1.6",
+ "browser-pack": "2.0.1",
+ "browserify": "3.32.1",
"buffertools": "2.0.1",
+ "chai": "1.9.1",
+ "cli-color": "0.3.2",
"commander": "2.1.0",
- "uglifyify": "1.2.3",
- "soop": "0.1.5",
- "grunt-contrib-watch": "0.5.3",
- "istanbul": "0.2.10",
- "grunt-mocha-test": "0.8.2",
+ "coveralls": "2.10.0",
+ "express": "4.0.0",
"github-releases": "0.2.0",
+ "grunt-browserify": "2.0.8",
+ "grunt-contrib-watch": "0.5.3",
"grunt-markdown": "0.5.0",
"browser-pack": "2.0.1",
"bitcore": "0.1.35",
"node-cryptojs-aes": "0.4.0",
"blanket": "1.1.6",
"express": "4.0.0",
+ "grunt-mocha-test": "0.8.2",
"grunt-shell": "0.6.4",
- "karma-mocha": "0.1.3",
- "async": "0.9.0",
- "mocha": "1.18.2",
- "browserify": "3.32.1",
- "karma-phantomjs-launcher": "^0.1.4",
- "coveralls": "2.10.0",
- "grunt-browserify": "2.0.8",
- "karma-chrome-launcher": "0.1.3",
+ "istanbul": "0.2.10",
"karma": "0.12.9",
- "cli-color": "0.3.2"
+ "karma-chrome-launcher": "0.1.3",
+ "karma-mocha": "0.1.3",
+ "karma-phantomjs-launcher": "^0.1.4",
+ "mocha": "1.18.2",
+ "mocha-lcov-reporter": "0.0.1",
+ "mock-fs": "^2.3.1",
+ "node-cryptojs-aes": "0.4.0",
+ "travis-cov": "0.2.5",
+ "uglifyify": "1.2.3"
},
"main": "app.js",
"homepage": "https://github.com/bitpay/copay",
diff --git a/test/index.html b/test/index.html
index f755dc486..0a0d77852 100644
--- a/test/index.html
+++ b/test/index.html
@@ -20,13 +20,11 @@
-
+
-
diff --git a/test/mocks/FakeLocalStorage.js b/test/mocks/FakeLocalStorage.js
index 6029b2601..e39280719 100644
--- a/test/mocks/FakeLocalStorage.js
+++ b/test/mocks/FakeLocalStorage.js
@@ -24,4 +24,4 @@ FakeLocalStorage.setItem = function(k, v) {
this.length = Object.keys(ls).length;
};
-module.exports = require('soop')(FakeLocalStorage);
+module.exports = FakeLocalStorage;
diff --git a/test/mocks/FakeNetwork.js b/test/mocks/FakeNetwork.js
index 4bdf68487..4368e8de5 100644
--- a/test/mocks/FakeNetwork.js
+++ b/test/mocks/FakeNetwork.js
@@ -1,9 +1,9 @@
-var imports = require('soop').imports();
-var EventEmitter = imports.EventEmitter || require('events').EventEmitter;
+var EventEmitter = require('events').EventEmitter;
+var util = require('util');
function Network(opts) {}
-Network.parent = EventEmitter;
+util.inherits(Network, EventEmitter);
Network.prototype.start = function(opts, cb) {
// start! :D
@@ -92,4 +92,4 @@ Network.prototype.iterateNonce = function() {
};
-module.exports = require('soop')(Network);
+module.exports = Network;
diff --git a/test/mocks/FakeStorage.js b/test/mocks/FakeStorage.js
index 3a4b426cc..56b88c2f4 100644
--- a/test/mocks/FakeStorage.js
+++ b/test/mocks/FakeStorage.js
@@ -119,4 +119,4 @@ FakeStorage.prototype.setFromObj = function(walletId, obj) {
this.setName(walletId, obj.opts.name);
};
-module.exports = require('soop')(FakeStorage);
+module.exports = FakeStorage;
diff --git a/test/mocks/FakeWallet.js b/test/mocks/FakeWallet.js
index 58d58a458..5ca39a8cc 100644
--- a/test/mocks/FakeWallet.js
+++ b/test/mocks/FakeWallet.js
@@ -1,6 +1,4 @@
-
-var is_browser = typeof process == 'undefined'
- || typeof process.versions === 'undefined';
+var is_browser = typeof process == 'undefined' || typeof process.versions === 'undefined';
if (is_browser) {
var copay = require('copay'); //browser
} else {
@@ -27,7 +25,11 @@ var FakeWallet = function() {
createdTs: 1403102115,
}
};
- this.publicKeyRing = {isComplete: function(){ return true; }};
+ this.publicKeyRing = {
+ isComplete: function() {
+ return true;
+ }
+ };
};
FakeWallet.prototype.createTx = function(toAddress, amountSatStr, comment, opts, cb) {
@@ -96,7 +98,5 @@ FakeWallet.prototype.disconnect = function() {
this.disconnectCalled = 1;
};
-// This mock is meant for karma, module.exports is not necesary.
-try {
- module.exports = require('soop')(FakeWallet);
-} catch (e) {}
+// TODO a try catch was here
+module.exports = FakeWallet;
diff --git a/test/test.storage.LocalEncrypted.js b/test/test.LocalEncrypted.js
similarity index 89%
rename from test/test.storage.LocalEncrypted.js
rename to test/test.LocalEncrypted.js
index a25f6cc92..5fcd6068c 100644
--- a/test/test.storage.LocalEncrypted.js
+++ b/test/test.LocalEncrypted.js
@@ -1,33 +1,10 @@
-//Crypto Mock
-CryptoJS = {};
-CryptoJS.AES = {};
-CryptoJS.AES.encrypt = function(a) {
- return a;
-};
-
-CryptoJS.enc = {
- utf8: ''
-};
-
-CryptoJS.AES.decrypt = function(a) {
- return a;
-};
-
-
-
-
'use strict';
+var copay = copay || require('../copay');
var chai = chai || require('chai');
var should = chai.should();
-var is_browser = typeof process == 'undefined'
- || typeof process.versions === 'undefined';
-if (is_browser) {
- var copay = require('copay'); //browser
-} else {
- var copay = require('../copay'); //node
-}
var LocalEncrypted = copay.StorageLocalEncrypted;
+
var fakeWallet = 'fake-wallet-id';
var timeStamp = Date.now();
var localMock = require('./mocks/FakeLocalStorage');
@@ -104,18 +81,6 @@ describe('Storage/LocalEncrypted model', function() {
//encrypted.slice(0,6).should.equal("53616c");
});
});
- describe('#_decryptObj', function() {
- it('should decrypt and Obj', function() {
- var storage = new LocalEncrypted({
- password: 'password',
- localStorage: localMock,
- });
- storage._decryptObj('{"a":"2"}').should.deep.equal({
- a: "2"
- });
- });
- });
-
describe('#remove', function() {
it('should remove an item', function() {
diff --git a/test/test.storage.File.js b/test/test.storage.File.js
index 23212871c..38e5789f1 100644
--- a/test/test.storage.File.js
+++ b/test/test.storage.File.js
@@ -7,29 +7,31 @@ var sinon = require('sinon');
var crypto = require('crypto');
var CryptoJS = require('node-cryptojs-aes').CryptoJS;
+var mock = require('mock-fs');
+
describe('Storage/File', function() {
it('should exist', function() {
should.exist(Storage);
});
+ var mockFS = function() {
+ var obj = {
+ "test": "test"
+ };
+ var encryptedStr = CryptoJS.AES.encrypt(JSON.stringify(obj), 'password').toString();
+ mock({
+ 'myfilename': encryptedStr
+ });
+ };
+
describe('#load', function(done) {
it('should call fs.readFile', function(done) {
- var fs = {}
- fs.readFile = function(filename, callback) {
- filename.should.equal('myfilename');
- 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
- });
+ mockFS();
var storage = new Storage({
password: 'password'
});
storage.load('myfilename', function(err) {
+ mock.restore();
done();
});
});
@@ -37,18 +39,12 @@ describe('Storage/File', function() {
describe('#save', function(done) {
it('should call fs.writeFile', function(done) {
- var fs = {}
- fs.writeFile = function(filename, data, callback) {
- filename.should.equal('myfilename');
- callback();
- };
- var Storage = require('soop').load('../js/models/storage/File.js', {
- fs: fs
- });
+ mockFS();
var storage = new Storage({
password: 'password'
});
storage.save('myfilename', function(err) {
+ mock.restore();
done();
});
});
diff --git a/util/build.js b/util/build.js
index a8215e977..965e01b46 100644
--- a/util/build.js
+++ b/util/build.js
@@ -4,24 +4,9 @@
var fs = require('fs');
var browserify = require('browserify');
-var browserPack = require('browser-pack');
var exec = require('child_process').exec;
-var sys = require('sys');
var puts = function(error, stdout, stderr) {
if (error) console.log(error);
- //sys.puts(stdout);
- //sys.puts(stderr);
-};
-
-var pack = function(params) {
- var file = require.resolve('soop');
- var dir = file.substr(0, file.length - String('soop.js').length);
- var preludePath = dir + 'example/custom_prelude.js';
- params.raw = true;
- params.sourceMapPrefix = '//#';
- params.prelude = fs.readFileSync(preludePath, 'utf8');
- params.preludePath = preludePath;
- return browserPack(params);
};
var createVersion = function() {
@@ -34,7 +19,6 @@ var createBundle = function(opts) {
opts.dir = opts.dir || 'js/';
var bopts = {
- pack: pack,
debug: true,
standalone: 'copay',
insertGlobals: true
@@ -60,30 +44,6 @@ var createBundle = function(opts) {
b.require('./js/models/core/Wallet', {
expose: '../../js/models/core/Wallet'
});
- b.require('./test/mocks/FakeStorage', {
- expose: './mocks/FakeStorage'
- });
- b.require('./test/mocks/FakeLocalStorage', {
- expose: './mocks/FakeLocalStorage'
- });
- b.require('./js/models/core/Message', {
- expose: '../js/models/core/Message'
- });
- b.require('./test/mocks/FakeBlockchain', {
- expose: './mocks/FakeBlockchain'
- });
- b.require('./test/mocks/FakeNetwork', {
- expose: './mocks/FakeNetwork'
- });
- b.require('./test/mocks/FakePayProServer', {
- expose: './mocks/FakePayProServer'
- });
- b.require('./test/mocks/FakePayProServer', {
- expose: '../../mocks/FakePayProServer'
- });
- b.require('./test/mocks/FakeBuilder', {
- expose: './mocks/FakeBuilder'
- });
b.require('./js/models/network/WebRTC', {
expose: '../js/models/network/WebRTC'
});
@@ -106,11 +66,34 @@ var createBundle = function(opts) {
expose: '../config'
});
- if (opts.dontminify) {
+ if (opts.debug) {
//include dev dependencies
b.require('sinon');
b.require('blanket');
- b.require('soop');
+ b.require('./test/mocks/FakeStorage', {
+ expose: './mocks/FakeStorage'
+ });
+ b.require('./test/mocks/FakeLocalStorage', {
+ expose: './mocks/FakeLocalStorage'
+ });
+ b.require('./js/models/core/Message', {
+ expose: '../js/models/core/Message'
+ });
+ b.require('./test/mocks/FakeBlockchain', {
+ expose: './mocks/FakeBlockchain'
+ });
+ b.require('./test/mocks/FakeNetwork', {
+ expose: './mocks/FakeNetwork'
+ });
+ b.require('./test/mocks/FakePayProServer', {
+ expose: './mocks/FakePayProServer'
+ });
+ b.require('./test/mocks/FakePayProServer', {
+ expose: '../../mocks/FakePayProServer'
+ });
+ b.require('./test/mocks/FakeBuilder', {
+ expose: './mocks/FakeBuilder'
+ });
}
if (!opts.dontminify) {