mirror of
https://github.com/Xahau/xahau.js.git
synced 2025-11-21 20:55:48 +00:00
Add Transaction.signingData()
This commit is contained in:
@@ -1,3 +1,10 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
// TODO: move in helpers from serializedtypes to utils
|
||||||
|
function toBytes(n) {
|
||||||
|
return [n >>> 24, (n >>> 16) & 0xff, (n >>> 8) & 0xff, n & 0xff];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prefix for hashing functions.
|
* Prefix for hashing functions.
|
||||||
*
|
*
|
||||||
@@ -23,3 +30,7 @@ exports.HASH_LEAF_NODE = 0x4D4C4E00; // 'MLN'
|
|||||||
exports.HASH_TX_SIGN = 0x53545800; // 'STX'
|
exports.HASH_TX_SIGN = 0x53545800; // 'STX'
|
||||||
// inner transaction to sign (TESTNET)
|
// inner transaction to sign (TESTNET)
|
||||||
exports.HASH_TX_SIGN_TESTNET = 0x73747800; // 'stx'
|
exports.HASH_TX_SIGN_TESTNET = 0x73747800; // 'stx'
|
||||||
|
|
||||||
|
Object.keys(exports).forEach(function(k) {
|
||||||
|
exports[k + '_BYTES'] = toBytes(exports[k]);
|
||||||
|
});
|
||||||
|
|||||||
@@ -50,57 +50,9 @@ function SerializedObject(buf) {
|
|||||||
this.pointer = 0;
|
this.pointer = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
SerializedObject.from_json = function(obj_) {
|
SerializedObject.from_json = function(obj) {
|
||||||
// Create a copy of the object so we don't modify it
|
|
||||||
const obj = extend(true, {}, obj_);
|
|
||||||
|
|
||||||
const so = new SerializedObject();
|
const so = new SerializedObject();
|
||||||
let typedef;
|
so.parse_json(obj);
|
||||||
|
|
||||||
if (typeof obj.TransactionType === 'number') {
|
|
||||||
obj.TransactionType = SerializedObject.lookup_type_tx(obj.TransactionType);
|
|
||||||
if (!obj.TransactionType) {
|
|
||||||
throw new Error('Transaction type ID is invalid.');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof obj.LedgerEntryType === 'number') {
|
|
||||||
obj.LedgerEntryType = SerializedObject.lookup_type_le(obj.LedgerEntryType);
|
|
||||||
|
|
||||||
if (!obj.LedgerEntryType) {
|
|
||||||
throw new Error('LedgerEntryType ID is invalid.');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof obj.TransactionType === 'string') {
|
|
||||||
typedef = binformat.tx[obj.TransactionType];
|
|
||||||
if (!Array.isArray(typedef)) {
|
|
||||||
throw new Error('Transaction type is invalid');
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef = typedef.slice();
|
|
||||||
obj.TransactionType = typedef.shift();
|
|
||||||
} else if (typeof obj.LedgerEntryType === 'string') {
|
|
||||||
typedef = binformat.ledger[obj.LedgerEntryType];
|
|
||||||
|
|
||||||
if (!Array.isArray(typedef)) {
|
|
||||||
throw new Error('LedgerEntryType is invalid');
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef = typedef.slice();
|
|
||||||
obj.LedgerEntryType = typedef.shift();
|
|
||||||
|
|
||||||
} else if (typeof obj.AffectedNodes === 'object') {
|
|
||||||
typedef = binformat.metadata;
|
|
||||||
} else {
|
|
||||||
throw new Error('Object to be serialized must contain either' +
|
|
||||||
' TransactionType, LedgerEntryType or AffectedNodes.');
|
|
||||||
}
|
|
||||||
|
|
||||||
// ND: This from_*json* seems a reasonable place to put validation of `json`
|
|
||||||
SerializedObject.check_fields(typedef, obj);
|
|
||||||
so.serialize(typedef, obj);
|
|
||||||
|
|
||||||
return so;
|
return so;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -154,6 +106,55 @@ SerializedObject.check_fields = function(typedef, obj) {
|
|||||||
throw new Error(errorMessage);
|
throw new Error(errorMessage);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
SerializedObject.prototype.parse_json = function(obj_) {
|
||||||
|
// Create a copy of the object so we don't modify it
|
||||||
|
const obj = extend(true, {}, obj_);
|
||||||
|
let typedef;
|
||||||
|
|
||||||
|
if (typeof obj.TransactionType === 'number') {
|
||||||
|
obj.TransactionType = SerializedObject.lookup_type_tx(obj.TransactionType);
|
||||||
|
if (!obj.TransactionType) {
|
||||||
|
throw new Error('Transaction type ID is invalid.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof obj.LedgerEntryType === 'number') {
|
||||||
|
obj.LedgerEntryType = SerializedObject.lookup_type_le(obj.LedgerEntryType);
|
||||||
|
|
||||||
|
if (!obj.LedgerEntryType) {
|
||||||
|
throw new Error('LedgerEntryType ID is invalid.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof obj.TransactionType === 'string') {
|
||||||
|
typedef = binformat.tx[obj.TransactionType];
|
||||||
|
if (!Array.isArray(typedef)) {
|
||||||
|
throw new Error('Transaction type is invalid');
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef = typedef.slice();
|
||||||
|
obj.TransactionType = typedef.shift();
|
||||||
|
} else if (typeof obj.LedgerEntryType === 'string') {
|
||||||
|
typedef = binformat.ledger[obj.LedgerEntryType];
|
||||||
|
|
||||||
|
if (!Array.isArray(typedef)) {
|
||||||
|
throw new Error('LedgerEntryType is invalid');
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef = typedef.slice();
|
||||||
|
obj.LedgerEntryType = typedef.shift();
|
||||||
|
|
||||||
|
} else if (typeof obj.AffectedNodes === 'object') {
|
||||||
|
typedef = binformat.metadata;
|
||||||
|
} else {
|
||||||
|
throw new Error('Object to be serialized must contain either' +
|
||||||
|
' TransactionType, LedgerEntryType or AffectedNodes.');
|
||||||
|
}
|
||||||
|
|
||||||
|
SerializedObject.check_fields(typedef, obj);
|
||||||
|
this.serialize(typedef, obj);
|
||||||
|
};
|
||||||
|
|
||||||
SerializedObject.prototype.append = function(bytes_) {
|
SerializedObject.prototype.append = function(bytes_) {
|
||||||
const bytes = bytes_ instanceof SerializedObject ? bytes_.buffer : bytes_;
|
const bytes = bytes_ instanceof SerializedObject ? bytes_.buffer : bytes_;
|
||||||
|
|
||||||
|
|||||||
@@ -274,7 +274,7 @@ Transaction.prototype.getManager = function(account_) {
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
let account = account_ || this.tx_json.Account;
|
const account = account_ || this.tx_json.Account;
|
||||||
return this.remote.account(account)._transactionManager;
|
return this.remote.account(account)._transactionManager;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -290,7 +290,7 @@ Transaction.prototype._accountSecret = function(account_) {
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
let account = account_ || this.tx_json.Account;
|
const account = account_ || this.tx_json.Account;
|
||||||
return this.remote.secrets[account];
|
return this.remote.secrets[account];
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -326,7 +326,7 @@ Transaction.prototype._computeFee = function() {
|
|||||||
const fees = [ ];
|
const fees = [ ];
|
||||||
|
|
||||||
for (let i = 0; i < servers.length; i++) {
|
for (let i = 0; i < servers.length; i++) {
|
||||||
let server = servers[i];
|
const server = servers[i];
|
||||||
if (server.isConnected()) {
|
if (server.isConnected()) {
|
||||||
fees.push(Number(server._computeFee(this._getFeeUnits())));
|
fees.push(Number(server._computeFee(this._getFeeUnits())));
|
||||||
}
|
}
|
||||||
@@ -435,6 +435,13 @@ Transaction.prototype.signingHash = function(testnet) {
|
|||||||
return this.hash(testnet ? 'HASH_TX_SIGN_TESTNET' : 'HASH_TX_SIGN');
|
return this.hash(testnet ? 'HASH_TX_SIGN_TESTNET' : 'HASH_TX_SIGN');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Transaction.prototype.signingData = function() {
|
||||||
|
const so = new SerializedObject();
|
||||||
|
so.append(hashprefixes.HASH_TX_SIGN_BYTES);
|
||||||
|
so.parse_json(this.tx_json);
|
||||||
|
return so;
|
||||||
|
};
|
||||||
|
|
||||||
Transaction.prototype.hash = function(prefix_, asUINT256, serialized) {
|
Transaction.prototype.hash = function(prefix_, asUINT256, serialized) {
|
||||||
let prefix;
|
let prefix;
|
||||||
|
|
||||||
@@ -770,7 +777,7 @@ Transaction.prototype.addMemo = function(options_) {
|
|||||||
const memo = {};
|
const memo = {};
|
||||||
const memoRegex = Transaction.MEMO_REGEX;
|
const memoRegex = Transaction.MEMO_REGEX;
|
||||||
let memoType = options.memoType;
|
let memoType = options.memoType;
|
||||||
let memoFormat = options.memoFormat;
|
const memoFormat = options.memoFormat;
|
||||||
let memoData = options.memoData;
|
let memoData = options.memoData;
|
||||||
|
|
||||||
if (memoType) {
|
if (memoType) {
|
||||||
@@ -918,7 +925,7 @@ Transaction.prototype.transferRate = function(rate) {
|
|||||||
// }
|
// }
|
||||||
/* eslint-enable max-len */
|
/* eslint-enable max-len */
|
||||||
|
|
||||||
let transferRate = rate;
|
const transferRate = rate;
|
||||||
|
|
||||||
if (transferRate === 0) {
|
if (transferRate === 0) {
|
||||||
// Clear TransferRate
|
// Clear TransferRate
|
||||||
@@ -1323,7 +1330,7 @@ Transaction.prototype.setExpiration = function(expiration) {
|
|||||||
// throw new Error('TransactionType must be OfferCreate to use Expiration');
|
// throw new Error('TransactionType must be OfferCreate to use Expiration');
|
||||||
// }
|
// }
|
||||||
|
|
||||||
let timeOffset = expiration instanceof Date
|
const timeOffset = expiration instanceof Date
|
||||||
? expiration.getTime()
|
? expiration.getTime()
|
||||||
: expiration;
|
: expiration;
|
||||||
|
|
||||||
@@ -1433,7 +1440,7 @@ Transaction.prototype.abort = function() {
|
|||||||
|
|
||||||
Transaction.prototype.getSummary =
|
Transaction.prototype.getSummary =
|
||||||
Transaction.prototype.summary = function() {
|
Transaction.prototype.summary = function() {
|
||||||
let txSummary = {
|
const txSummary = {
|
||||||
tx_json: this.tx_json,
|
tx_json: this.tx_json,
|
||||||
clientID: this._clientID,
|
clientID: this._clientID,
|
||||||
submittedIDs: this.submittedIDs,
|
submittedIDs: this.submittedIDs,
|
||||||
|
|||||||
@@ -553,19 +553,38 @@ describe('Transaction', function() {
|
|||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Get signing hash', function(done) {
|
describe('signing', function() {
|
||||||
const transaction = new Transaction();
|
const tx_json = {
|
||||||
|
SigningPubKey: '021FED5FD081CE5C4356431267D04C6E2167E4112C897D5E10335D4E22B4DA49ED',
|
||||||
|
Account: 'rMWwx3Ma16HnqSd4H6saPisihX9aKpXxHJ',
|
||||||
|
Flags: 0,
|
||||||
|
Fee: 10,
|
||||||
|
Sequence: 1,
|
||||||
|
TransactionType: 'AccountSet'
|
||||||
|
};
|
||||||
|
|
||||||
|
const expectedSigningHash =
|
||||||
|
'D1C15200CF532175F1890B6440AD223D3676140522BC11D2784E56760AE3B4FE';
|
||||||
|
|
||||||
|
it('Get signing hash', function() {
|
||||||
|
const transaction = Transaction.from_json(tx_json);
|
||||||
transaction._secret = 'sh2pTicynUEG46jjR4EoexHcQEoij';
|
transaction._secret = 'sh2pTicynUEG46jjR4EoexHcQEoij';
|
||||||
transaction.tx_json.SigningPubKey = '021FED5FD081CE5C4356431267D04C6E2167E4112C897D5E10335D4E22B4DA49ED';
|
assert.strictEqual(transaction.signingHash(), expectedSigningHash);
|
||||||
transaction.tx_json.Account = 'rMWwx3Ma16HnqSd4H6saPisihX9aKpXxHJ';
|
});
|
||||||
transaction.tx_json.Flags = 0;
|
|
||||||
transaction.tx_json.Fee = 10;
|
|
||||||
transaction.tx_json.Sequence = 1;
|
|
||||||
transaction.tx_json.TransactionType = 'AccountSet';
|
|
||||||
|
|
||||||
assert.strictEqual(transaction.signingHash(), 'D1C15200CF532175F1890B6440AD223D3676140522BC11D2784E56760AE3B4FE');
|
it('Get signing data', function() {
|
||||||
|
const tx = Transaction.from_json(tx_json);
|
||||||
|
const data = tx.signingData();
|
||||||
|
|
||||||
done();
|
assert.strictEqual(data.hash().to_json(),
|
||||||
|
expectedSigningHash);
|
||||||
|
|
||||||
|
assert.strictEqual(data.to_hex(),
|
||||||
|
('535458001200032200000000240000000168400000000000000' +
|
||||||
|
'A7321021FED5FD081CE5C4356431267D04C6E2167E4112C897D' +
|
||||||
|
'5E10335D4E22B4DA49ED8114E0E6E281CA324AEE034B2BB8AC9' +
|
||||||
|
'7BA1ACA95A068'));
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Get hash - no prefix', function(done) {
|
it('Get hash - no prefix', function(done) {
|
||||||
@@ -1959,7 +1978,7 @@ describe('Transaction', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Get min ledger', function() {
|
it('Get min ledger', function() {
|
||||||
let queue = new TransactionQueue();
|
const queue = new TransactionQueue();
|
||||||
|
|
||||||
// Randomized submit indexes
|
// Randomized submit indexes
|
||||||
[
|
[
|
||||||
@@ -1975,7 +1994,7 @@ describe('Transaction', function() {
|
|||||||
543305
|
543305
|
||||||
]
|
]
|
||||||
.forEach(function(index) {
|
.forEach(function(index) {
|
||||||
let tx = new Transaction();
|
const tx = new Transaction();
|
||||||
tx.initialSubmitIndex = index;
|
tx.initialSubmitIndex = index;
|
||||||
queue.push(tx);
|
queue.push(tx);
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user