Merge pull request #401 from ryanxcharles/feature/bip70-protobuf
add BIP70 protobuf features in new PayPro lib file
This commit is contained in:
commit
e48561302b
|
@ -60,6 +60,7 @@ requireWhenAccessed('Script', './lib/Script');
|
|||
requireWhenAccessed('Transaction', './lib/Transaction');
|
||||
requireWhenAccessed('TransactionBuilder', './lib/TransactionBuilder');
|
||||
requireWhenAccessed('Connection', './lib/Connection');
|
||||
requireWhenAccessed('PayPro', './lib/PayPro');
|
||||
requireWhenAccessed('Peer', './lib/Peer');
|
||||
requireWhenAccessed('Block', './lib/Block');
|
||||
requireWhenAccessed('ScriptInterpreter', './lib/ScriptInterpreter');
|
||||
|
|
|
@ -38,6 +38,7 @@ var modules = [
|
|||
'lib/Electrum',
|
||||
'lib/Message',
|
||||
'lib/Opcode',
|
||||
'lib/PayPro',
|
||||
'lib/Peer',
|
||||
'lib/PeerManager',
|
||||
'lib/PrivateKey',
|
||||
|
@ -87,12 +88,14 @@ var createBitcore = function(opts) {
|
|||
|
||||
var submodules = opts.submodules;
|
||||
|
||||
//modules included in "all" but not included in "main" bundle
|
||||
if (opts.includemain) {
|
||||
submodules = JSON.parse(JSON.stringify(modules));
|
||||
submodules.splice(submodules.indexOf('lib/BIP39'), 1);
|
||||
submodules.splice(submodules.indexOf('lib/BIP39WordlistEn'), 1);
|
||||
submodules.splice(submodules.indexOf('lib/PayPro'), 1);
|
||||
var assert = require('assert');
|
||||
assert(submodules.length == modules.length - 2);
|
||||
assert(submodules.length == modules.length - 3);
|
||||
}
|
||||
|
||||
if (opts.submodules) {
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1174,7 +1174,6 @@ var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
|
|||
? Uint8Array
|
||||
: Array
|
||||
|
||||
var ZERO = '0'.charCodeAt(0)
|
||||
var PLUS = '+'.charCodeAt(0)
|
||||
var SLASH = '/'.charCodeAt(0)
|
||||
var NUMBER = '0'.charCodeAt(0)
|
||||
|
@ -1283,9 +1282,9 @@ var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
|
|||
return output
|
||||
}
|
||||
|
||||
module.exports.toByteArray = b64ToByteArray
|
||||
module.exports.fromByteArray = uint8ToBase64
|
||||
}())
|
||||
exports.toByteArray = b64ToByteArray
|
||||
exports.fromByteArray = uint8ToBase64
|
||||
}(typeof exports === 'undefined' ? (this.base64js = {}) : exports))
|
||||
|
||||
},{}],4:[function(require,module,exports){
|
||||
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-mocha-test": "~0.8.2",
|
||||
"grunt-shell": "~0.6.4",
|
||||
"protobufjs": "=3.0.0",
|
||||
"coveralls": "^2.10.0",
|
||||
"istanbul": "~0.2.6",
|
||||
"commander": "~2.2.0",
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
<script src="test.Message.js"></script>
|
||||
<script src="test.misc.js"></script>
|
||||
<script src="test.Opcode.js"></script>
|
||||
<script src="test.PayPro.js"></script>
|
||||
<script src="test.Peer.js"></script>
|
||||
<script src="test.PeerManager.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