diff --git a/CHANGELOG.md b/CHANGELOG.md index 73542c27a1e..ebe4cfb9d2d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -271,6 +271,7 @@ Released with 1.0.0-beta.37 code base. ### Added - Support for typescript files (.ts) to be writtern alongside regular .js files (#3652) +- Add compareBlock function that allows for complex block comparisons (#3682) ### Changed diff --git a/packages/web3-utils/src/index.js b/packages/web3-utils/src/index.js index 6f857cfe470..d7693b7ce19 100644 --- a/packages/web3-utils/src/index.js +++ b/packages/web3-utils/src/index.js @@ -27,7 +27,7 @@ var ethjsUnit = require('ethjs-unit'); var utils = require('./utils.js'); var soliditySha3 = require('./soliditySha3.js'); var randombytes = require('randombytes'); - +var BN = require('bn.js'); /** @@ -316,6 +316,62 @@ var toChecksumAddress = function (address) { return checksumAddress; }; +/** + * Returns -1 if ab; 0 if a == b. + * For more details on this type of function, see + * developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort + * + * @method compareBlockNumbers + * + * @param {String|Number|BN} a + * + * @param {String|Number|BN} b + * + * @returns {Number} -1, 0, or 1 + */ +var compareBlockNumbers = function(a, b) { + if (a == b) { + return 0; + } else if (("genesis" == a || "earliest" == a || 0 == a) && ("genesis" == b || "earliest" == b || 0 == b)) { + return 0; + } else if ("genesis" == a || "earliest" == a) { + // b !== a, thus a < b + return -1; + } else if ("genesis" == b || "earliest" == b) { + // b !== a, thus a > b + return 1; + } else if (a == "latest") { + if (b == "pending") { + return -1; + } else { + // b !== ("pending" OR "latest"), thus a > b + return 1; + } + } else if (b === "latest") { + if (a == "pending") { + return 1; + } else { + // b !== ("pending" OR "latest"), thus a > b + return -1 + } + } else if (a == "pending") { + // b (== OR <) "latest", thus a > b + return 1; + } else if (b == "pending") { + return -1; + } else { + let bnA = new BN(a); + let bnB = new BN(b); + if(bnA.lt(bnB)) { + return -1; + } else if(bnA.eq(bnB)) { + return 0; + } else { + return 1; + } + } +}; + module.exports = { _fireError: _fireError, _jsonInterfaceMethodToString: _jsonInterfaceMethodToString, @@ -379,5 +435,7 @@ module.exports = { isContractAddressInBloom: utils.isContractAddressInBloom, isTopic: utils.isTopic, isTopicInBloom: utils.isTopicInBloom, - isInBloom: utils.isInBloom + isInBloom: utils.isInBloom, + + compareBlockNumbers: compareBlockNumbers }; diff --git a/test/utils.compareBlockNumbers.js b/test/utils.compareBlockNumbers.js new file mode 100644 index 00000000000..71617da26b5 --- /dev/null +++ b/test/utils.compareBlockNumbers.js @@ -0,0 +1,58 @@ +const chai = require('chai'); +const assert = chai.assert; +const BN = require('bn.js'); +const formatters = require('../packages/web3-utils/src/index.js'); + +const pending = "pending"; +const latest = "latest"; +const genesis = "genesis"; +const earliest = "earliest"; + +const tests = [ + // Base cases for numbers + { input: {a: 1, b: 1}, result: 0 }, + { input: {a: 1, b: 2}, result: -1 }, + { input: {a: 2, b: 1}, result: 1 }, + // Base cases for BN + { input: {a: new BN(1), b: new BN(1)}, result: 0 }, + { input: {a: new BN(1), b: new BN(2)}, result: -1 }, + { input: {a: new BN(2), b: new BN(1)}, result: 1 }, + // Base cases for numbers vs BN + { input: {a: new BN(1), b: 1}, result: 0 }, + { input: {a: new BN(1), b: 2}, result: -1 }, + { input: {a: new BN(2), b: 1}, result: 1 }, + // Base cases for strings (sanity) + { input: {a: genesis, b: earliest}, result: 0 }, + { input: {a: genesis, b: 0}, result: 0 }, + { input: {a: earliest, b: 0}, result: 0 }, + { input: {a: latest, b: latest}, result: 0 }, + { input: {a: pending, b: pending}, result: 0 }, + // Complex Strings + // Genesis + { input: {a: earliest, b: 2}, result: -1 }, + { input: {a: earliest, b: new BN(2)}, result: -1 }, + { input: {a: earliest, b: latest}, result: -1 }, + { input: {a: earliest, b: pending}, result: -1 }, + { input: {a: genesis, b: 2}, result: -1 }, + { input: {a: genesis, b: new BN(2)}, result: -1 }, + { input: {a: genesis, b: latest}, result: -1 }, + { input: {a: genesis, b: pending}, result: -1 }, + // latest + { input: {a: latest, b: 0}, result: 1 }, + { input: {a: latest, b: new BN(1)}, result: 1 }, + { input: {a: latest, b: pending}, result: -1 }, + // pending + { input: {a: pending, b: 0}, result: 1 }, + { input: {a: pending, b: new BN(1)}, result: 1 }, +]; + +describe('formatters', function () { + describe('compare blocknumbers', function () { + tests.forEach(function(test){ + it('should return the correct value', function () { + assert.deepEqual(formatters.compareBlockNumbers(test.input.a, test.input.b), test.result); + }); + }); + }); + +});