From cb5e71644bb1c09b10d51f0fe4a9dae8ecd1693b Mon Sep 17 00:00:00 2001 From: Vasco Santos Date: Mon, 16 Nov 2020 15:03:20 +0100 Subject: [PATCH] feat: address sorter (#13) --- API.md | 40 +++++++++++++++++++++++++++++ src/address-sort.js | 44 ++++++++++++++++++++++++++++++++ test/address-sort.spec.js | 53 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 137 insertions(+) create mode 100644 src/address-sort.js create mode 100644 test/address-sort.spec.js diff --git a/API.md b/API.md index 0cbb4e6..3dbf66d 100644 --- a/API.md +++ b/API.md @@ -1,5 +1,9 @@ # API +* [addressSort.publicAddressesFirst(addresses)](#addresssortpublicaddressesfirstaddresses) + * [Parameters](#parameters) + * [Returns](#returns) + * [Example](#example) * [arrayEquals(a, b)](#arrayequalsa-b) * [Parameters](#parameters) * [Returns](#returns) @@ -21,6 +25,42 @@ * [Returns](#returns-4) * [Example](#example-4) +## addressSort.publicAddressesFirst(addresses) + +Sort given addresses by putting public addresses first. In case of equality, a certified address will come first. + +### Parameters + +| Name | Type | Description | +|------|------|-------------| +| addresses | `Array
` | Array of AddressBook addresses | + +### Returns + +| Type | Description | +|------|-------------| +| `Array
` | returns array of sorted addresses | + +### Example + +```js +const multiaddr = require('multiaddr') +const { publicAddressesFirst } = require('libp2p-utils/src/address-sort') + +const addresses = [ + { + multiaddr: multiaddr('/ip4/127.0.0.1/tcp/4000'), + isCertified: false + }, + { + multiaddr: multiaddr('/ip4/30.0.0.1/tcp/4000'), + isCertified: false + } +] + +const sortedAddresses = publicAddressesFirst(addresses) +``` + ## arrayEquals(a, b) Verify if two arrays of non primitive types with the "equals" function are equal. diff --git a/src/address-sort.js b/src/address-sort.js new file mode 100644 index 0000000..0a49143 --- /dev/null +++ b/src/address-sort.js @@ -0,0 +1,44 @@ +'use strict' + +const isPrivate = require('./multiaddr/is-private') + +/** + * Compare function for array.sort(). + * This sort aims to move the private adresses to the end of the array. + * In case of equality, a certified address will come first. + * + * @param {Address} a + * @param {Address} b + * @returns {number} + */ +function addressesPublicFirstCompareFunction (a, b) { + const isAPrivate = isPrivate(a.multiaddr) + const isBPrivate = isPrivate(b.multiaddr) + + if (isAPrivate && !isBPrivate) { + return 1 + } else if (!isAPrivate && isBPrivate) { + return -1 + } + // Check certified? + if (a.isCertified && !b.isCertified) { + return -1 + } else if (!a.isCertified && b.isCertified) { + return 1 + } + + return 0 +} + +/** + * Sort given addresses by putting public addresses first. + * In case of equality, a certified address will come first. + * + * @param {Array
} addresses + * @returns {Array
} + */ +function publicAddressesFirst (addresses) { + return [...addresses].sort(addressesPublicFirstCompareFunction) +} + +module.exports.publicAddressesFirst = publicAddressesFirst diff --git a/test/address-sort.spec.js b/test/address-sort.spec.js new file mode 100644 index 0000000..4e8dbd7 --- /dev/null +++ b/test/address-sort.spec.js @@ -0,0 +1,53 @@ +'use strict' +/* eslint-env mocha */ + +const { expect } = require('aegir/utils/chai') +const multiaddr = require('multiaddr') + +const { publicAddressesFirst } = require('../src/address-sort') + +describe('address-sort', () => { + it('should sort public addresses first', () => { + const addresses = [ + { + multiaddr: multiaddr('/ip4/127.0.0.1/tcp/4000'), + isCertified: false + }, + { + multiaddr: multiaddr('/ip4/30.0.0.1/tcp/4000'), + isCertified: false + }, + { + multiaddr: multiaddr('/ip4/31.0.0.1/tcp/4000'), + isCertified: false + } + ] + + const sortedAddresses = publicAddressesFirst(addresses) + expect(sortedAddresses[0].multiaddr.equals(multiaddr('/ip4/30.0.0.1/tcp/4000'))).to.eql(true) + expect(sortedAddresses[1].multiaddr.equals(multiaddr('/ip4/31.0.0.1/tcp/4000'))).to.eql(true) + expect(sortedAddresses[2].multiaddr.equals(multiaddr('/ip4/127.0.0.1/tcp/4000'))).to.eql(true) + }) + + it('should sort public certified addresses first', () => { + const addresses = [ + { + multiaddr: multiaddr('/ip4/127.0.0.1/tcp/4000'), + isCertified: false + }, + { + multiaddr: multiaddr('/ip4/30.0.0.1/tcp/4000'), + isCertified: false + }, + { + multiaddr: multiaddr('/ip4/31.0.0.1/tcp/4000'), + isCertified: true + } + ] + + const sortedAddresses = publicAddressesFirst(addresses) + expect(sortedAddresses[0].multiaddr.equals(multiaddr('/ip4/31.0.0.1/tcp/4000'))).to.eql(true) + expect(sortedAddresses[1].multiaddr.equals(multiaddr('/ip4/30.0.0.1/tcp/4000'))).to.eql(true) + expect(sortedAddresses[2].multiaddr.equals(multiaddr('/ip4/127.0.0.1/tcp/4000'))).to.eql(true) + }) +})