Skip to content

Commit

Permalink
fix(core-api): /wallets/{id}/transactions search parameters (#2923)
Browse files Browse the repository at this point in the history
  • Loading branch information
spkjp authored and faustbrian committed Sep 13, 2019
1 parent 86c98bf commit af87eaa
Show file tree
Hide file tree
Showing 8 changed files with 67 additions and 77 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -454,23 +454,6 @@ describe("Transactions Business Repository", () => {
});
});

describe("findAllByWallet", () => {
it("should search by wallet", async () => {
databaseService.connection.transactionsRepository = {
findAllByWallet: async wallet => wallet,
getModel: () => new MockDatabaseModel(),
} as any;

jest.spyOn(databaseService.connection.transactionsRepository, "findAllByWallet").mockImplementation(
async () => ({ rows: [], count: 0 }),
);

await transactionsBusinessRepository.findAllByWallet({} as any);

expect(databaseService.connection.transactionsRepository.findAllByWallet).toHaveBeenCalled();
});
});

describe("findById", () => {
it("should invoke findById on db repository", async () => {
const expectedBlockId = "id";
Expand Down
12 changes: 12 additions & 0 deletions packages/core-api/src/handlers/transactions/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ export const index: object = {
type: Joi.number()
.integer()
.min(0),
typeGroup: Joi.number()
.integer()
.min(0),
version: Joi.number()
.integer()
.positive(),
Expand All @@ -34,6 +37,9 @@ export const index: object = {
timestamp: Joi.number()
.integer()
.min(0),
nonce: Joi.number()
.integer()
.min(0),
amount: Joi.number()
.integer()
.min(0),
Expand Down Expand Up @@ -103,6 +109,9 @@ export const search: object = {
type: Joi.number()
.integer()
.min(0),
typeGroup: Joi.number()
.integer()
.min(0),
version: Joi.number()
.integer()
.positive(),
Expand All @@ -125,6 +134,9 @@ export const search: object = {
.integer()
.min(0),
}),
nonce: Joi.number()
.integer()
.min(0),
amount: Joi.object().keys({
from: Joi.number()
.integer()
Expand Down
13 changes: 11 additions & 2 deletions packages/core-api/src/handlers/wallets/methods.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,20 @@ const transactions = async request => {
return Boom.notFound("Wallet not found");
}

const rows = await transactionsRepository.findAllByWallet(wallet, {
// Overwrite parameters for special wallet treatment inside transaction repository
const parameters = {
...request.query,
...request.params,
...paginate(request),
});
walletPublicKey: wallet.publicKey,
walletAddress: wallet.address,
};

delete parameters.publicKey;
delete parameters.recipientId;
delete parameters.id;

const rows = await transactionsRepository.search(parameters);

return toPagination(rows, "transaction", (request.query.transform as unknown) as boolean);
};
Expand Down
27 changes: 18 additions & 9 deletions packages/core-api/src/handlers/wallets/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,21 +56,18 @@ export const transactions: object = {
type: Joi.number()
.integer()
.min(0),
typeGroup: Joi.number()
.integer()
.min(0),
version: Joi.number()
.integer()
.positive(),
senderPublicKey: Joi.string()
.hex()
.length(66),
senderId: Joi.string()
.alphanum()
.length(34),
recipientId: Joi.string()
.alphanum()
.length(34),
timestamp: Joi.number()
.integer()
.min(0),
nonce: Joi.number()
.integer()
.min(0),
amount: Joi.number()
.integer()
.min(0),
Expand Down Expand Up @@ -98,6 +95,9 @@ export const transactionsSent: object = {
type: Joi.number()
.integer()
.min(0),
typeGroup: Joi.number()
.integer()
.min(0),
version: Joi.number()
.integer()
.positive(),
Expand All @@ -107,6 +107,9 @@ export const transactionsSent: object = {
timestamp: Joi.number()
.integer()
.min(0),
nonce: Joi.number()
.integer()
.min(0),
amount: Joi.number()
.integer()
.min(0),
Expand Down Expand Up @@ -134,6 +137,9 @@ export const transactionsReceived: object = {
type: Joi.number()
.integer()
.min(0),
typeGroup: Joi.number()
.integer()
.min(0),
version: Joi.number()
.integer()
.positive(),
Expand All @@ -146,6 +152,9 @@ export const transactionsReceived: object = {
timestamp: Joi.number()
.integer()
.min(0),
nonce: Joi.number()
.integer()
.min(0),
amount: Joi.number()
.integer()
.min(0),
Expand Down
43 changes: 24 additions & 19 deletions packages/core-database-postgres/src/repositories/transactions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,20 @@ export class TransactionsRepository extends Repository implements Database.ITran
const params = parameters.parameters;

if (params.length) {
// Special handling when called for `/wallets/transactions` endpoint
let walletAddress: string;
let walletPublicKey: string;

// 'search' doesn't support custom-op 'ownerId' like 'findAll' can
const ops = params.filter(value => value.operator !== Database.SearchOperator.OP_CUSTOM);
const ops = params.filter(value => {
if (value.field === "walletAddress") {
walletAddress = value.value;
} else if (value.field === "walletPublicKey") {
walletPublicKey = value.value;
}

return value.operator !== Database.SearchOperator.OP_CUSTOM;
});

const [participants, rest] = partition(ops, op =>
["sender_public_key", "recipient_id"].includes(this.propToColumnName(op.field)),
Expand Down Expand Up @@ -71,6 +83,17 @@ export class TransactionsRepository extends Repository implements Database.ITran
}
}

if (walletAddress && walletPublicKey) {
const useWhere: boolean = !selectQuery.nodes.some(node => node.type === "WHERE");
for (const query of [selectQuery, selectQueryCount]) {
query[useWhere ? "where" : "and"](
this.query.sender_public_key
.equals(walletPublicKey)
.or(this.query.recipient_id.equals(walletAddress)),
);
}
}

for (const condition of rest) {
for (const query of [selectQuery, selectQueryCount]) {
query.and(this.query[this.propToColumnName(condition.field)][condition.operator](condition.value));
Expand Down Expand Up @@ -162,24 +185,6 @@ export class TransactionsRepository extends Repository implements Database.ITran
return this.db.manyOrNone(queries.transactions.feeStatistics, { age, minFee });
}

public async findAllByWallet(
wallet: State.IWallet,
paginate?: Database.ISearchPaginate,
orderBy?: Database.ISearchOrderBy[],
): Promise<Database.ITransactionsPaginated> {
const selectQuery = this.query.select();
const selectQueryCount = this.query.select(this.query.count().as("cnt"));

for (const query of [selectQuery, selectQueryCount]) {
query
.from(this.query)
.where(this.query.sender_public_key.equals(wallet.publicKey))
.or(this.query.recipient_id.equals(wallet.address));
}

return this.findManyWithCount(selectQuery, selectQueryCount, paginate, orderBy);
}

public getModel(): Transaction {
return new Transaction(this.pgp);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { app } from "@arkecosystem/core-container";
import { Database, State } from "@arkecosystem/core-interfaces";
import { Database } from "@arkecosystem/core-interfaces";
import { Enums, Interfaces } from "@arkecosystem/crypto";
import { SearchParameterConverter } from "./utils/search-parameter-converter";

Expand Down Expand Up @@ -60,24 +60,6 @@ export class TransactionsBusinessRepository implements Database.ITransactionsBus
return this.search({ type, ...parameters });
}

// @TODO: simplify this
public async findAllByWallet(
wallet: State.IWallet,
parameters: Database.IParameters = {},
): Promise<Database.ITransactionsPaginated> {
const { transactionsRepository }: Database.IConnection = this.databaseServiceProvider().connection;
const searchParameters = new SearchParameterConverter(transactionsRepository.getModel()).convert(parameters);

const result = await transactionsRepository.findAllByWallet(
wallet,
searchParameters.paginate,
searchParameters.orderBy,
);
result.rows = await this.mapBlocksToTransactions(result.rows);

return result;
}

// @TODO: simplify this
public async findById(id: string) {
return (await this.mapBlocksToTransactions(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { Interfaces } from "@arkecosystem/crypto";
import { IWallet } from "../../core-state/wallets";
import { IParameters } from "./parameters";

export interface ITransactionsPaginated {
Expand All @@ -10,8 +9,6 @@ export interface ITransactionsPaginated {
export interface ITransactionsBusinessRepository {
search(params: IParameters, sequenceOrder?: "asc" | "desc"): Promise<ITransactionsPaginated>;

findAllByWallet(wallet: IWallet, parameters?: IParameters): Promise<ITransactionsPaginated>;

findAllBySender(senderPublicKey: string, parameters?: IParameters): Promise<ITransactionsPaginated>;

findAllByRecipient(recipientId: string, parameters?: IParameters): Promise<ITransactionsPaginated>;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { Interfaces, Utils } from "@arkecosystem/crypto";
import { IWallet } from "../../core-state/wallets";
import { ITransactionsPaginated } from "../business-repository";
import { ISearchOrderBy, ISearchPaginate, ISearchParameters } from "../search";
import { ISearchParameters } from "../search";
import { IRepository } from "./repository";

export interface IBootstrapTransaction {
Expand Down Expand Up @@ -67,11 +66,5 @@ export interface ITransactionsRepository extends IRepository {

deleteByBlockId(blockIds: string[], db: any): Promise<void>;

findAllByWallet(
wallet: IWallet,
paginate?: ISearchPaginate,
orderBy?: ISearchOrderBy[],
): Promise<ITransactionsPaginated>;

search(parameters: ISearchParameters): Promise<ITransactionsPaginated>;
}

0 comments on commit af87eaa

Please sign in to comment.