diff --git a/src/js/ripple/transaction.js b/src/js/ripple/transaction.js index 20e016f2..1167907b 100644 --- a/src/js/ripple/transaction.js +++ b/src/js/ripple/transaction.js @@ -167,6 +167,9 @@ Transaction.set_clear_flags = { } }; +Transaction.MEMO_TYPES = { +}; + Transaction.formats = require('./binformat').tx; Transaction.prototype.consts = { @@ -595,6 +598,48 @@ Transaction.prototype.setFlags = function(flags) { return this; }; +/** + * Add a Memo to transaction. Memos can be used as key-value, + * using the MemoType as a key + * + * @param {String} data + * @param {String} type + */ + +Transaction.prototype.addMemo = function(type, data) { + if (!/(undefined|string)/.test(typeof type)) { + throw new Error('MemoType must be a string'); + } + + if (!/(undefined|string)/.test(typeof data)) { + throw new Error('MemoData must be string'); + } + + function toHex(str) { + return sjcl.codec.hex.fromBits(sjcl.codec.utf8String.toBits(str)); + }; + + var memo = { }; + + if (type) { + if (Transaction.MEMO_TYPES[type]) { + //XXX Maybe in the future we want a schema validator for + //memo types + memo.MemoType = Transaction.MEMO_TYPES[type]; + } else { + memo.MemoType = toHex(type); + } + } + + if (data) { + memo.MemoData = toHex(data); + } + + this.tx_json.Memos = (this.tx_json.Memos || []).concat({ Memo: memo }); + + return this; +}; + // Options: // .domain() NYI // .flags() diff --git a/test/transaction-test.js b/test/transaction-test.js index 5c8b065d..df7aae62 100644 --- a/test/transaction-test.js +++ b/test/transaction-test.js @@ -292,9 +292,7 @@ describe('Transaction', function() { var s3 = new Server(remote, 'wss://s-west.ripple.com:443'); s3._connected = true; - // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< s3._load_factor = (256 * 7) + 1; - // Is this ever possible? <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< var s4 = new Server(remote, 'wss://s-west.ripple.com:443'); s4._connected = true; @@ -1017,6 +1015,53 @@ describe('Transaction', function() { transaction.setFlags('test'); }); + it('Add Memo', function() { + var transaction = new Transaction(); + transaction.tx_json.TransactionType = 'Payment'; + + transaction.addMemo('testkey', 'testvalue'); + transaction.addMemo('testkey2', 'testvalue2'); + transaction.addMemo('testkey3'); + transaction.addMemo(void(0), 'testvalue4'); + + var expected = [ + { Memo: { + MemoType: new Buffer('testkey').toString('hex'), + MemoData: new Buffer('testvalue').toString('hex') + }}, + { Memo: { + MemoType: new Buffer('testkey2').toString('hex'), + MemoData: new Buffer('testvalue2').toString('hex') + }}, + { Memo: { + MemoType: new Buffer('testkey3').toString('hex') + }}, + { Memo: { + MemoData: new Buffer('testvalue4').toString('hex') + } } + ]; + + assert.deepEqual(transaction.tx_json.Memos, expected); + }); + + it('Add Memo - invalid MemoType', function() { + var transaction = new Transaction(); + transaction.tx_json.TransactionType = 'Payment'; + + assert.throws(function() { + transaction.addMemo(1); + }, 'MemoType must be a string'); + }); + + it('Add Memo - invalid MemoData', function() { + var transaction = new Transaction(); + transaction.tx_json.TransactionType = 'Payment'; + + assert.throws(function() { + transaction.addMemo('key', 1); + }, 'MemoData must be a string'); + }); + it('Construct AccountSet transaction', function() { var transaction = new Transaction().accountSet('rsLEU1TPdCJPPysqhWYw9jD97xtG5WqSJm');