Skip to content

Commit

Permalink
fix(core-database): properly sort BigNumber values (#2144)
Browse files Browse the repository at this point in the history
  • Loading branch information
faustbrian authored Feb 25, 2019
1 parent e02c2c8 commit b836819
Show file tree
Hide file tree
Showing 16 changed files with 110 additions and 46 deletions.
30 changes: 29 additions & 1 deletion packages/core-api/__tests__/v2/handlers/delegates.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { utils } from "../utils";

import { blocks2to100 } from "../../../../core-test-utils/src/fixtures/testnet/blocks2to100";

import { models } from "@arkecosystem/crypto";
import { Bignum, models } from "@arkecosystem/crypto";
const { Block } = models;

import { app } from "@arkecosystem/core-container";
Expand Down Expand Up @@ -38,6 +38,34 @@ describe("API 2.0 - Delegates", () => {
response.data.data.forEach(utils.expectDelegate);
expect(response.data.data.sort((a, b) => a.rank < b.rank)).toEqual(response.data.data);
});

it("should GET all the delegates sorted by votes,asc", async () => {
const wm = app.resolvePlugin("database").walletManager;
const wallet = wm.findByUsername("genesis_51");
wallet.voteBalance = new Bignum(1);
wm.reindex(wallet);

const response = await utils[request]("GET", "delegates", { orderBy: "votes:asc" });
expect(response).toBeSuccessfulResponse();
expect(response.data.data).toBeArray();

expect(response.data.data[0].username).toBe(wallet.username);
expect(response.data.data[0].votes).toBe(+wallet.voteBalance.toFixed());
});

it("should GET all the delegates sorted by votes,desc", async () => {
const wm = app.resolvePlugin("database").walletManager;
const wallet = wm.findByUsername("genesis_1");
wallet.voteBalance = new Bignum(12500000000000000);
wm.reindex(wallet);

const response = await utils[request]("GET", "delegates", { orderBy: "votes:desc" });
expect(response).toBeSuccessfulResponse();
expect(response.data.data).toBeArray();

expect(response.data.data[0].username).toBe(wallet.username);
expect(response.data.data[0].votes).toBe(+wallet.voteBalance.toFixed());
});
},
);

Expand Down
19 changes: 19 additions & 0 deletions packages/core-api/__tests__/v2/handlers/wallets.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import "@arkecosystem/core-test-utils";
import { Bignum } from "@arkecosystem/crypto";
import { setUp, tearDown } from "../../__support__/setup";
import { utils } from "../utils";

Expand Down Expand Up @@ -28,6 +29,24 @@ describe("API 2.0 - Wallets", () => {

utils.expectWallet(response.data.data[0]);
});

it("should GET all the wallets sorted by balance,asc", async () => {
const response = await utils[request]("GET", "wallets", { orderBy: "balance:asc" });
expect(response).toBeSuccessfulResponse();
expect(response.data.data).toBeArray();

expect(response.data.data[0].address).toBe("APnhwwyTbMiykJwYbGhYjNgtHiVJDSEhSn");
expect(response.data.data[0].balance).toBe(-12500000000000000);
});

it("should GET all the wallets sorted by balance,desc", async () => {
const response = await utils[request]("GET", "wallets", { orderBy: "balance:desc" });
expect(response).toBeSuccessfulResponse();
expect(response.data.data).toBeArray();

expect(response.data.data[0].address).toBe("ANBkoGqWeTSiaEVgVzSKZd3jS7UWzv9PSo");
expect(response.data.data[0].balance).toBe(245100000000000);
});
},
);
});
Expand Down
10 changes: 3 additions & 7 deletions packages/core-api/__tests__/v2/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,17 @@ class Helpers {
"Content-Type": "application/json",
};

const server = app.resolvePlugin("api");

return ApiHelpers.request(server.http, method, url, headers, params);
return ApiHelpers.request(app.resolvePlugin("api").http, method, url, headers, params);
}

public async requestWithAcceptHeader(method, path, params = {}) {
const url = `http://localhost:4003/api/${path}`;
const headers = {
Accept: "application/vnd.core-api.v2+json",
"API-Version": 2,
"Content-Type": "application/json",
};

const server = app.resolvePlugin("api");

return ApiHelpers.request(server.http, method, url, headers, params);
return ApiHelpers.request(app.resolvePlugin("api").http, method, url, headers, params);
}

public expectJson(response) {
Expand Down
2 changes: 1 addition & 1 deletion packages/core-api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
"@arkecosystem/core-transaction-pool": "^2.2.0-beta.7",
"@arkecosystem/core-utils": "^2.2.0-beta.7",
"@arkecosystem/crypto": "^2.2.0-beta.7",
"@arkecosystem/utils": "^0.2.3",
"@arkecosystem/utils": "^0.2.4",
"@faustbrian/hapi-version": "^0.2.11",
"@types/lodash.orderby": "^4.6.4",
"@types/lodash.partition": "^4.6.4",
Expand Down
2 changes: 2 additions & 0 deletions packages/core-database/__tests__/repositories/wallets.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,8 @@ describe("Wallet Repository", () => {
if (i < 17) {
wallet.vote = vote;
}

wallet.balance = new Bignum(0);
});
walletManager.index(wallets);
});
Expand Down
2 changes: 1 addition & 1 deletion packages/core-database/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
"@arkecosystem/core-interfaces": "^2.2.0-beta.7",
"@arkecosystem/core-utils": "^2.2.0-beta.7",
"@arkecosystem/crypto": "^2.2.0-beta.7",
"@arkecosystem/utils": "^0.2.3",
"@arkecosystem/utils": "^0.2.4",
"@types/lodash.clonedeep": "^4.5.4",
"@types/lodash.compact": "^3.0.4",
"@types/lodash.uniq": "^4.5.4",
Expand Down
16 changes: 13 additions & 3 deletions packages/core-database/src/database-service-factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,20 @@ import { DelegatesRepository } from "./repositories/delegates";
import { WalletsRepository } from "./repositories/wallets";

// Allow extenders of core-database to provide, optionally, a IWalletManager concrete in addition to a IDatabaseConnection, but keep the business repos common
export const databaseServiceFactory = async (opts: any, walletManager: Database.IWalletManager, connection: Database.IDatabaseConnection): Promise<Database.IDatabaseService> => {
export const databaseServiceFactory = async (
opts: any,
walletManager: Database.IWalletManager,
connection: Database.IDatabaseConnection,
): Promise<Database.IDatabaseService> => {
let databaseService: DatabaseService;
databaseService = new DatabaseService(opts, connection, walletManager, new WalletsRepository(() => databaseService), new DelegatesRepository(() => databaseService));
databaseService = new DatabaseService(
opts,
connection,
walletManager,
// @ts-ignore
new WalletsRepository(() => databaseService),
new DelegatesRepository(() => databaseService),
);
await databaseService.init();
return databaseService;
};

22 changes: 14 additions & 8 deletions packages/core-database/src/repositories/delegates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Database } from "@arkecosystem/core-interfaces";
import { delegateCalculator } from "@arkecosystem/core-utils";
import { orderBy } from "@arkecosystem/utils";
import limitRows from "./utils/limit-rows";
import { sortEntries } from "./utils/sort-entries";

export class DelegatesRepository implements Database.IDelegatesBusinessRepository {
/**
Expand All @@ -26,12 +27,12 @@ export class DelegatesRepository implements Database.IDelegatesBusinessRepositor
* @return {Object}
*/
public findAll(params: Database.IParameters = {}) {
const delegates = this.getLocalDelegates();
this.applyOrder(params);

const [iteratee, order] = this.__orderBy(params);
const delegates = sortEntries(params, this.getLocalDelegates(), ["rate", "asc"]);

return {
rows: limitRows(orderBy(delegates, [iteratee], [order as "desc" | "asc"]), params),
rows: limitRows(delegates, params),
count: delegates.length,
};
}
Expand Down Expand Up @@ -99,21 +100,26 @@ export class DelegatesRepository implements Database.IDelegatesBusinessRepositor
});
}

public __orderBy(params): string[] {
private applyOrder(params): string {
const assignOrder = (params, value) => (params.orderBy = value.join(":"));

if (!params.orderBy) {
return ["rate", "asc"];
return assignOrder(params, ["rate", "asc"]);
}

const orderByMapped = params.orderBy.split(":").map(p => p.toLowerCase());

if (orderByMapped.length !== 2 || ["desc", "asc"].includes(orderByMapped[1]) !== true) {
return ["rate", "asc"];
return assignOrder(params, ["rate", "asc"]);
}

return [this.__manipulateIteratee(orderByMapped[0]), orderByMapped[1]];
return assignOrder(params, [this.manipulateIteratee(orderByMapped[0]), orderByMapped[1]]);
}

public __manipulateIteratee(iteratee): any {
private manipulateIteratee(iteratee): any {
switch (iteratee) {
case "votes":
return "voteBalance";
case "rank":
return "rate";
case "productivity":
Expand Down
14 changes: 14 additions & 0 deletions packages/core-database/src/repositories/utils/sort-entries.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { Database } from "@arkecosystem/core-interfaces";
import { orderBy } from "@arkecosystem/utils";

export function sortEntries(params: Database.IParameters, entries: any[], defaultValue) {
const [iteratee, order] = params.orderBy ? params.orderBy.split(":") : defaultValue;

if (["balance", "voteBalance"].includes(iteratee)) {
return Object.values(entries).sort((a: any, b: any) => {
return order === "asc" ? a[iteratee].comparedTo(b[iteratee]) : b[iteratee].comparedTo(a[iteratee]);
});
}

return orderBy(entries, [iteratee], [order as "desc" | "asc"]);
}
13 changes: 5 additions & 8 deletions packages/core-database/src/repositories/wallets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Database } from "@arkecosystem/core-interfaces";
import { orderBy } from "@arkecosystem/utils";
import filterRows from "./utils/filter-rows";
import limitRows from "./utils/limit-rows";
import { sortEntries } from "./utils/sort-entries";

export class WalletsRepository implements Database.IWalletsBusinessRepository {
/**
Expand All @@ -24,12 +25,10 @@ export class WalletsRepository implements Database.IWalletsBusinessRepository {
* @return {Object}
*/
public findAll(params: Database.IParameters = {}) {
const wallets = this.all();

const [iteratee, order] = params.orderBy ? params.orderBy.split(":") : ["rate", "asc"];
const wallets = sortEntries(params, this.all(), ["rate", "asc"]);

return {
rows: limitRows(orderBy(wallets, [iteratee], [order as "desc" | "asc"]), params),
rows: limitRows(wallets, params),
count: wallets.length,
};
}
Expand All @@ -43,10 +42,8 @@ export class WalletsRepository implements Database.IWalletsBusinessRepository {
public findAllByVote(publicKey: string, params: Database.IParameters = {}) {
const wallets = this.all().filter(wallet => wallet.vote === publicKey);

const [iteratee, order] = params.orderBy ? params.orderBy.split(":") : ["balance", "desc"];

return {
rows: limitRows(orderBy(wallets, [iteratee], [order as "desc" | "asc"]), params),
rows: limitRows(sortEntries(params, wallets, ["balance", "desc"]), params),
count: wallets.length,
};
}
Expand All @@ -69,7 +66,7 @@ export class WalletsRepository implements Database.IWalletsBusinessRepository {
* Find all wallets sorted by balance.
*/
public top(params: Database.IParameters = {}) {
const wallets = Object.values(this.all()).sort((a: any, b: any) => +b.balance.minus(a.balance).toFixed());
const wallets = sortEntries(params, this.all(), ["balance", "desc"]);

return {
rows: limitRows(wallets, params),
Expand Down
4 changes: 1 addition & 3 deletions packages/core-http-utils/src/server/create-secure.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import expandHomeDir from "expand-home-dir";
import { readFileSync } from "fs";
import { createServer } from "./create";

async function createSecureServer(options, callback, secure) {
export async function createSecureServer(options, callback, secure) {
options.host = secure.host;
options.port = secure.port;
options.tls = {
Expand All @@ -12,5 +12,3 @@ async function createSecureServer(options, callback, secure) {

return createServer(options, callback);
}

export { createSecureServer };
4 changes: 1 addition & 3 deletions packages/core-http-utils/src/server/create.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import Hapi from "hapi";
import { monitorServer } from "./monitor";

async function createServer(options, callback: any = null) {
export async function createServer(options, callback: any = null) {
const server = new Hapi.Server(options);

await server.register([require("vision"), require("inert"), require("lout")]);
Expand All @@ -21,5 +21,3 @@ async function createServer(options, callback: any = null) {

return server;
}

export { createServer };
4 changes: 1 addition & 3 deletions packages/core-http-utils/src/server/monitor.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
async function monitorServer(server) {
export async function monitorServer(server) {
return server.register({
plugin: require("good"),
options: {
Expand All @@ -18,5 +18,3 @@ async function monitorServer(server) {
},
});
}

export { monitorServer };
4 changes: 1 addition & 3 deletions packages/core-http-utils/src/server/mount.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { app } from "@arkecosystem/core-container";

async function mountServer(name, server) {
export async function mountServer(name, server) {
try {
await server.start();

Expand All @@ -11,5 +11,3 @@ async function mountServer(name, server) {
app.forceExit(`Could not start ${name} Server!`, error);
}
}

export { mountServer };
2 changes: 1 addition & 1 deletion packages/core-jest-matchers/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
"dependencies": {
"@arkecosystem/core-container": "^2.2.0-beta.7",
"@arkecosystem/crypto": "^2.2.0-beta.7",
"@arkecosystem/utils": "^0.2.3",
"@arkecosystem/utils": "^0.2.4",
"@types/bip39": "^2.4.1",
"@types/lodash.get": "^4.4.4",
"@types/lodash.isequal": "^4.5.3",
Expand Down
8 changes: 4 additions & 4 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -135,10 +135,10 @@
webpack-node-externals "^1.7.2"
wif "^2.0.6"

"@arkecosystem/utils@^0.2.3":
version "0.2.3"
resolved "https://registry.yarnpkg.com/@arkecosystem/utils/-/utils-0.2.3.tgz#8e8cac978cd892b6e8d9cd956d60f2e6c4312fd0"
integrity sha512-7DrnQlrPWxIUQA/C1c1Grry0aAkxIwt4uN7aKd0afSkqpwg+rIyByT9N+rwqwYyhSxEZtN6og+iOHXnbNs0epQ==
"@arkecosystem/utils@^0.2.4":
version "0.2.4"
resolved "https://registry.yarnpkg.com/@arkecosystem/utils/-/utils-0.2.4.tgz#1458a1046141adb55e9b8af0a355b00920d35332"
integrity sha512-24+DQLJ42KOJywFiq6oWd7oUJwbUZMRrVUkec8HprwXXza5MjmcIYf62cHqSfikTCxWJdXXKujUaKNd9ZJpPoA==
dependencies:
"@flatten/array" "^1.1.7"
dottie "^2.0.1"
Expand Down

0 comments on commit b836819

Please sign in to comment.