add BIP70 protobuf features in new PayPro lib file
...and add to the "main" bundle, but not the "all" bundle, since it adds hundreds of kilobytes to the bundle.
This commit is contained in:
parent
3842ed69cb
commit
0bea06f785
|
@ -60,6 +60,7 @@ requireWhenAccessed('Script', './lib/Script');
|
||||||
requireWhenAccessed('Transaction', './lib/Transaction');
|
requireWhenAccessed('Transaction', './lib/Transaction');
|
||||||
requireWhenAccessed('TransactionBuilder', './lib/TransactionBuilder');
|
requireWhenAccessed('TransactionBuilder', './lib/TransactionBuilder');
|
||||||
requireWhenAccessed('Connection', './lib/Connection');
|
requireWhenAccessed('Connection', './lib/Connection');
|
||||||
|
requireWhenAccessed('PayPro', './lib/PayPro');
|
||||||
requireWhenAccessed('Peer', './lib/Peer');
|
requireWhenAccessed('Peer', './lib/Peer');
|
||||||
requireWhenAccessed('Block', './lib/Block');
|
requireWhenAccessed('Block', './lib/Block');
|
||||||
requireWhenAccessed('ScriptInterpreter', './lib/ScriptInterpreter');
|
requireWhenAccessed('ScriptInterpreter', './lib/ScriptInterpreter');
|
||||||
|
|
|
@ -38,6 +38,7 @@ var modules = [
|
||||||
'lib/Electrum',
|
'lib/Electrum',
|
||||||
'lib/Message',
|
'lib/Message',
|
||||||
'lib/Opcode',
|
'lib/Opcode',
|
||||||
|
'lib/PayPro',
|
||||||
'lib/Peer',
|
'lib/Peer',
|
||||||
'lib/PeerManager',
|
'lib/PeerManager',
|
||||||
'lib/PrivateKey',
|
'lib/PrivateKey',
|
||||||
|
@ -87,12 +88,14 @@ var createBitcore = function(opts) {
|
||||||
|
|
||||||
var submodules = opts.submodules;
|
var submodules = opts.submodules;
|
||||||
|
|
||||||
|
//modules not included in "main" bundle
|
||||||
if (opts.includemain) {
|
if (opts.includemain) {
|
||||||
submodules = JSON.parse(JSON.stringify(modules));
|
submodules = JSON.parse(JSON.stringify(modules));
|
||||||
submodules.splice(submodules.indexOf('lib/BIP39'), 1);
|
submodules.splice(submodules.indexOf('lib/BIP39'), 1);
|
||||||
submodules.splice(submodules.indexOf('lib/BIP39WordlistEn'), 1);
|
submodules.splice(submodules.indexOf('lib/BIP39WordlistEn'), 1);
|
||||||
|
submodules.splice(submodules.indexOf('lib/PayPro'), 1);
|
||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
assert(submodules.length == modules.length - 2);
|
assert(submodules.length == modules.length - 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opts.submodules) {
|
if (opts.submodules) {
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1174,7 +1174,6 @@ var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
|
||||||
? Uint8Array
|
? Uint8Array
|
||||||
: Array
|
: Array
|
||||||
|
|
||||||
var ZERO = '0'.charCodeAt(0)
|
|
||||||
var PLUS = '+'.charCodeAt(0)
|
var PLUS = '+'.charCodeAt(0)
|
||||||
var SLASH = '/'.charCodeAt(0)
|
var SLASH = '/'.charCodeAt(0)
|
||||||
var NUMBER = '0'.charCodeAt(0)
|
var NUMBER = '0'.charCodeAt(0)
|
||||||
|
@ -1283,9 +1282,9 @@ var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
|
||||||
return output
|
return output
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports.toByteArray = b64ToByteArray
|
exports.toByteArray = b64ToByteArray
|
||||||
module.exports.fromByteArray = uint8ToBase64
|
exports.fromByteArray = uint8ToBase64
|
||||||
}())
|
}(typeof exports === 'undefined' ? (this.base64js = {}) : exports))
|
||||||
|
|
||||||
},{}],4:[function(require,module,exports){
|
},{}],4:[function(require,module,exports){
|
||||||
exports.read = function(buffer, offset, isLE, mLen, nBytes) {
|
exports.read = function(buffer, offset, isLE, mLen, nBytes) {
|
||||||
|
|
|
@ -0,0 +1,186 @@
|
||||||
|
'use strict';
|
||||||
|
var imports = require('soop').imports();
|
||||||
|
var protobufjs = protobufjs || require('protobufjs/dist/ProtoBuf');
|
||||||
|
|
||||||
|
// BIP 70 - payment protocol
|
||||||
|
function PayPro() {
|
||||||
|
this.messageType = null;
|
||||||
|
this.message = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
PayPro.constants = {};
|
||||||
|
|
||||||
|
PayPro.PAYMENT_REQUEST_MAX_SIZE = 50000;
|
||||||
|
PayPro.PAYMENT_MAX_SIZE = 50000;
|
||||||
|
PayPro.PAYMENT_ACK_MAX_SIZE = 60000;
|
||||||
|
PayPro.PAYMENT_REQUEST_CONTENT_TYPE = "application/bitcoin-paymentrequest";
|
||||||
|
PayPro.PAYMENT_CONTENT_TYPE = "application/bitcoin-payment";
|
||||||
|
PayPro.PAYMENT_ACK_CONTENT_TYPE = "application/bitcoin-paymentack";
|
||||||
|
|
||||||
|
PayPro.proto = {};
|
||||||
|
|
||||||
|
PayPro.proto.Output = "message Output {\
|
||||||
|
optional uint64 amount = 1 [default = 0];\
|
||||||
|
optional bytes script = 2;\
|
||||||
|
}\n";
|
||||||
|
|
||||||
|
PayPro.proto.PaymentDetails = "message PaymentDetails {\
|
||||||
|
optional string network = 1 [default = \"main\"];\
|
||||||
|
repeated Output outputs = 2;\
|
||||||
|
required uint64 time = 3;\
|
||||||
|
optional uint64 expires = 4;\
|
||||||
|
optional string memo = 5;\
|
||||||
|
optional string payment_url = 6;\
|
||||||
|
optional bytes merchant_data = 7;\
|
||||||
|
}\n";
|
||||||
|
|
||||||
|
PayPro.proto.PaymentRequest = "message PaymentRequest {\
|
||||||
|
optional uint32 payment_details_version = 1 [default = 1];\
|
||||||
|
optional string pki_type = 2 [default = \"none\"];\
|
||||||
|
optional bytes pki_data = 3;\
|
||||||
|
required bytes serialized_payment_details = 4;\
|
||||||
|
optional bytes signature = 5;\
|
||||||
|
}\n";
|
||||||
|
|
||||||
|
PayPro.proto.Payment = "message Payment {\
|
||||||
|
optional bytes merchant_data = 1;\
|
||||||
|
repeated bytes transactions = 2;\
|
||||||
|
repeated Output refund_to = 3;\
|
||||||
|
optional string memo = 4;\
|
||||||
|
}\n";
|
||||||
|
|
||||||
|
PayPro.proto.PaymentACK = "message PaymentACK {\
|
||||||
|
required Payment payment = 1;\
|
||||||
|
optional string memo = 2;\
|
||||||
|
}\n";
|
||||||
|
|
||||||
|
PayPro.proto.X509Certificates = "message X509Certificates {\
|
||||||
|
repeated bytes certificate = 1;\
|
||||||
|
}\n";
|
||||||
|
|
||||||
|
PayPro.proto.all = "";
|
||||||
|
PayPro.proto.all = PayPro.proto.all + PayPro.proto.Output;
|
||||||
|
PayPro.proto.all = PayPro.proto.all + PayPro.proto.PaymentDetails;
|
||||||
|
PayPro.proto.all = PayPro.proto.all + PayPro.proto.PaymentRequest;
|
||||||
|
PayPro.proto.all = PayPro.proto.all + PayPro.proto.Payment;
|
||||||
|
PayPro.proto.all = PayPro.proto.all + PayPro.proto.PaymentACK;
|
||||||
|
PayPro.proto.all = PayPro.proto.all + PayPro.proto.X509Certificates;
|
||||||
|
|
||||||
|
PayPro.builder = protobufjs.loadProto(PayPro.proto.all);
|
||||||
|
|
||||||
|
PayPro.Output = PayPro.builder.build("Output");
|
||||||
|
PayPro.PaymentDetails = PayPro.builder.build("PaymentDetails");
|
||||||
|
PayPro.PaymentRequest = PayPro.builder.build("PaymentRequest");
|
||||||
|
PayPro.Payment = PayPro.builder.build("Payment");
|
||||||
|
PayPro.PaymentACK = PayPro.builder.build("PaymentACK");
|
||||||
|
PayPro.X509Certificates = PayPro.builder.build("X509Certificates");
|
||||||
|
|
||||||
|
PayPro.prototype.makeOutput = function(obj) {
|
||||||
|
this.messageType = 'Output';
|
||||||
|
this.message = new PayPro.Output();
|
||||||
|
this.setObj(obj);
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
PayPro.prototype.makePaymentDetails = function(obj) {
|
||||||
|
this.messageType = 'PaymentDetails';
|
||||||
|
this.message = new PayPro.PaymentDetails();
|
||||||
|
this.setObj(obj);
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
PayPro.prototype.makePaymentRequest = function(obj) {
|
||||||
|
this.messageType = 'PaymentRequest';
|
||||||
|
this.message = new PayPro.PaymentRequest();
|
||||||
|
this.setObj(obj);
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
PayPro.prototype.makePayment = function(obj) {
|
||||||
|
this.messageType = 'Payment';
|
||||||
|
this.message = new PayPro.Payment();
|
||||||
|
this.setObj(obj);
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
PayPro.prototype.makePaymentACK = function(obj) {
|
||||||
|
this.messageType = 'Payment';
|
||||||
|
this.message = new PayPro.PaymentACK();
|
||||||
|
this.setObj(obj);
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
PayPro.prototype.makeX509Certificates = function(obj) {
|
||||||
|
this.messageType = 'X509Certificates';
|
||||||
|
this.message = new PayPro.X509Certificates();
|
||||||
|
this.setObj(obj);
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
PayPro.prototype.isValidSize = function() {
|
||||||
|
var s = this.serialize();
|
||||||
|
if (this.messageType == 'PaymentRequest')
|
||||||
|
return s.length < PayPro.PAYMENT_REQUEST_MAX_SIZE;
|
||||||
|
if (this.messageType == 'Payment')
|
||||||
|
return s.length < PayPro.PAYMENT_MAX_SIZE;
|
||||||
|
if (this.messageType == 'PaymentACK')
|
||||||
|
return s.length < PayPro.PAYMENT_ACK_MAX_SIZE;
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
PayPro.prototype.getContentType = function() {
|
||||||
|
if (this.messageType == 'PaymentRequest')
|
||||||
|
return PayPro.PAYMENT_REQUEST_CONTENT_TYPE;
|
||||||
|
|
||||||
|
if (this.messageType == 'Payment')
|
||||||
|
return PayPro.PAYMENT_CONTENT_TYPE;
|
||||||
|
|
||||||
|
if (this.messageType == 'PaymentACK')
|
||||||
|
return PayPro.PAYMENT_ACK_CONTENT_TYPE;
|
||||||
|
|
||||||
|
throw new Error('No known content type for this message type');
|
||||||
|
};
|
||||||
|
|
||||||
|
PayPro.prototype.set = function(key, val) {
|
||||||
|
this.message.set(key, val);
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
PayPro.prototype.get = function(key) {
|
||||||
|
var v = this.message.get(key);
|
||||||
|
|
||||||
|
//protobuf supports longs, javascript naturally does not
|
||||||
|
//convert longs (see long.js, e.g. require('long')) to Numbers
|
||||||
|
if (typeof v.low !== 'undefined' && typeof v.high !== 'undefined')
|
||||||
|
return v.toInt();
|
||||||
|
|
||||||
|
return v;
|
||||||
|
};
|
||||||
|
|
||||||
|
PayPro.prototype.setObj = function(obj) {
|
||||||
|
for (var key in obj) {
|
||||||
|
if (obj.hasOwnProperty(key)) {
|
||||||
|
var val = obj[key];
|
||||||
|
this.message.set(key, val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
PayPro.prototype.serialize = function() {
|
||||||
|
//protobufjs returns either a Buffer or an ArrayBuffer
|
||||||
|
//but we always want a Buffer (which browserify understands, browser or no)
|
||||||
|
var maybebuf = this.message.toBuffer();
|
||||||
|
var buf = (Buffer.isBuffer(maybebuf)) ? maybebuf : new Buffer(new Uint8Array(maybebuf));
|
||||||
|
return buf;
|
||||||
|
};
|
||||||
|
|
||||||
|
PayPro.prototype.deserialize = function(buf, messageType) {
|
||||||
|
this.messageType = messageType || this.messageType;
|
||||||
|
if (!this.messageType)
|
||||||
|
throw new Error('Must specify messageType');
|
||||||
|
this.message = PayPro[this.messageType].decode(buf);
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = require('soop')(PayPro);
|
|
@ -57,6 +57,7 @@
|
||||||
"grunt-markdown": "~0.5.0",
|
"grunt-markdown": "~0.5.0",
|
||||||
"grunt-mocha-test": "~0.8.2",
|
"grunt-mocha-test": "~0.8.2",
|
||||||
"grunt-shell": "~0.6.4",
|
"grunt-shell": "~0.6.4",
|
||||||
|
"protobufjs": "=3.0.0",
|
||||||
"coveralls": "^2.10.0",
|
"coveralls": "^2.10.0",
|
||||||
"istanbul": "~0.2.6",
|
"istanbul": "~0.2.6",
|
||||||
"commander": "~2.2.0",
|
"commander": "~2.2.0",
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
<script src="test.Message.js"></script>
|
<script src="test.Message.js"></script>
|
||||||
<script src="test.misc.js"></script>
|
<script src="test.misc.js"></script>
|
||||||
<script src="test.Opcode.js"></script>
|
<script src="test.Opcode.js"></script>
|
||||||
|
<script src="test.PayPro.js"></script>
|
||||||
<script src="test.Peer.js"></script>
|
<script src="test.Peer.js"></script>
|
||||||
<script src="test.PeerManager.js"></script>
|
<script src="test.PeerManager.js"></script>
|
||||||
<script src="test.Point.js"></script>
|
<script src="test.Point.js"></script>
|
||||||
|
|
|
@ -0,0 +1,212 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var chai = chai || require('chai');
|
||||||
|
var should = chai.should();
|
||||||
|
var expect = chai.expect;
|
||||||
|
var bitcore = bitcore || require('../bitcore');
|
||||||
|
|
||||||
|
var PayPro = bitcore.PayPro;
|
||||||
|
var Key = bitcore.Key;
|
||||||
|
|
||||||
|
describe('PayPro', function() {
|
||||||
|
|
||||||
|
it('should be able to create class', function() {
|
||||||
|
should.exist(PayPro);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#Output', function() {
|
||||||
|
|
||||||
|
it('should not fail', function() {
|
||||||
|
var obj = {};
|
||||||
|
var output = new PayPro.Output();
|
||||||
|
output.$set('amount', 20);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be able to set the amount of an output', function() {
|
||||||
|
var output = new PayPro.Output();
|
||||||
|
output.set('amount', 20);
|
||||||
|
output.get('amount').toInt().should.equal(20);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#PaymentDetails', function() {
|
||||||
|
|
||||||
|
it('should not fail', function() {
|
||||||
|
var obj = {};
|
||||||
|
var pd = new PayPro.PaymentDetails();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set the memo', function() {
|
||||||
|
var obj = {};
|
||||||
|
var pd = new PayPro.PaymentDetails();
|
||||||
|
pd.set('memo', 'test memo');
|
||||||
|
pd.get('memo').should.equal('test memo');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should serialize', function() {
|
||||||
|
var obj = {};
|
||||||
|
var pd = new PayPro.PaymentDetails();
|
||||||
|
pd.set('time', 0);
|
||||||
|
pd.set('memo', 'test memo');
|
||||||
|
var hex = pd.toHex();
|
||||||
|
hex.length.should.be.greaterThan(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#PaymentRequest', function() {
|
||||||
|
|
||||||
|
it('should not fail', function() {
|
||||||
|
var obj = {};
|
||||||
|
var pd = new PayPro.PaymentRequest();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should serialize', function() {
|
||||||
|
var obj = {};
|
||||||
|
var pd = new PayPro.PaymentDetails();
|
||||||
|
pd.set('time', 0);
|
||||||
|
var pdbuf = pd.toBuffer();
|
||||||
|
var pr = new PayPro.PaymentRequest();
|
||||||
|
pr.set('serialized_payment_details', pdbuf);
|
||||||
|
var prhex = pr.toHex();
|
||||||
|
prhex.length.should.be.greaterThan(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#Payment', function() {
|
||||||
|
|
||||||
|
it('should not fail', function() {
|
||||||
|
var obj = {};
|
||||||
|
var pd = new PayPro.Payment();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should serialize', function() {
|
||||||
|
var obj = {};
|
||||||
|
var p = new PayPro.Payment();
|
||||||
|
p.set('memo', 'this is a memo');
|
||||||
|
p.get('memo').should.equal('this is a memo');
|
||||||
|
var phex = p.toHex();
|
||||||
|
phex.length.should.be.greaterThan(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#PaymentACK', function() {
|
||||||
|
|
||||||
|
it('should not fail', function() {
|
||||||
|
var obj = {};
|
||||||
|
var pd = new PayPro.PaymentACK();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should serialize', function() {
|
||||||
|
var obj = {};
|
||||||
|
var p = new PayPro.Payment();
|
||||||
|
var pa = new PayPro.PaymentACK();
|
||||||
|
pa.set('payment', p);
|
||||||
|
pa.set('memo', 'this is a memo');
|
||||||
|
pa.get('memo').should.equal('this is a memo');
|
||||||
|
var pahex = pa.toHex();
|
||||||
|
pahex.length.should.be.greaterThan(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#X509Certificates', function() {
|
||||||
|
|
||||||
|
it('should not fail', function() {
|
||||||
|
var obj = {};
|
||||||
|
var pd = new PayPro.X509Certificates();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should serialize', function() {
|
||||||
|
var obj = {};
|
||||||
|
var x = new PayPro.X509Certificates();
|
||||||
|
var fakecertificate = new Buffer([0, 0, 0, 0]);
|
||||||
|
x.set('certificate', [fakecertificate]);
|
||||||
|
var xhex = x.toHex();
|
||||||
|
xhex.length.should.be.greaterThan(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#isValidSize', function() {
|
||||||
|
|
||||||
|
it('should return true for validly sized payment', function() {
|
||||||
|
var paypro = new PayPro();
|
||||||
|
paypro.makePayment();
|
||||||
|
paypro.set('memo', 'test memo');
|
||||||
|
paypro.isValidSize().should.equal(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#getContentType', function() {
|
||||||
|
|
||||||
|
it('should get a content type for payment', function() {
|
||||||
|
var paypro = new PayPro();
|
||||||
|
paypro.makePayment();
|
||||||
|
paypro.set('memo', 'test memo');
|
||||||
|
paypro.getContentType().should.equal('application/bitcoin-payment');
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#set', function() {
|
||||||
|
|
||||||
|
it('should set a field', function() {
|
||||||
|
var obj = {};
|
||||||
|
var paypro = new PayPro();
|
||||||
|
paypro.makePaymentDetails();
|
||||||
|
paypro.set('memo', 'test memo');
|
||||||
|
paypro.get('memo').should.equal('test memo');
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#get', function() {
|
||||||
|
|
||||||
|
it('should get a field', function() {
|
||||||
|
var obj = {};
|
||||||
|
var paypro = new PayPro();
|
||||||
|
paypro.makePaymentDetails();
|
||||||
|
paypro.set('memo', 'test memo');
|
||||||
|
paypro.get('memo').should.equal('test memo');
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#serialize', function() {
|
||||||
|
|
||||||
|
it('should serialize', function() {
|
||||||
|
var obj = {};
|
||||||
|
var paypro = new PayPro();
|
||||||
|
paypro.makePaymentDetails();
|
||||||
|
paypro.set('memo', 'test memo');
|
||||||
|
paypro.set('time', 0);
|
||||||
|
var buf = paypro.serialize();
|
||||||
|
buf.length.should.be.greaterThan(0);
|
||||||
|
Buffer.isBuffer(buf).should.equal(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#deserialize', function() {
|
||||||
|
|
||||||
|
it('should deserialize a serialized message', function() {
|
||||||
|
var obj = {};
|
||||||
|
var paypro = new PayPro();
|
||||||
|
paypro.makePaymentDetails();
|
||||||
|
paypro.set('memo', 'test memo');
|
||||||
|
paypro.set('time', 0);
|
||||||
|
var buf = paypro.serialize();
|
||||||
|
var paypro2 = new PayPro();
|
||||||
|
paypro2.deserialize(buf, 'PaymentDetails');
|
||||||
|
paypro2.get('memo').should.equal('test memo');
|
||||||
|
paypro2.get('time').should.equal(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
Loading…
Reference in New Issue