Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions packages/api-database/source/contracts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ import type {
State,
System,
Token,
TokenAction,
TokenHolder,
TokenTransfer,
TokenWhitelist,
Transaction,
ValidatorRound,
Expand Down Expand Up @@ -106,8 +106,8 @@ export type TokenRepositoryExtension = Record<string, unknown>;
export type TokenRepository = ExtendedRepository<Token> & TokenRepositoryExtension;
export type TokenHolderRepositoryExtension = Record<string, unknown>;
export type TokenHolderRepository = ExtendedRepository<TokenHolder> & TokenHolderRepositoryExtension;
export type TokenTransferRepositoryExtension = Record<string, unknown>;
export type TokenTransferRepository = ExtendedRepository<TokenTransfer> & TokenTransferRepositoryExtension;
export type TokenActionRepositoryExtension = Record<string, unknown>;
export type TokenActionRepository = ExtendedRepository<TokenAction> & TokenActionRepositoryExtension;
export type TokenWhitelistRepositoryExtension = Record<string, unknown>;
export type TokenWhitelistRepository = ExtendedRepository<TokenWhitelist> & TokenWhitelistRepositoryExtension;

Expand Down Expand Up @@ -142,7 +142,7 @@ export type PeerRepositoryFactory = (customDataSource?: RepositoryDataSource) =>
export type TransactionRepositoryFactory = (customDataSource?: RepositoryDataSource) => TransactionRepository;
export type TokenRepositoryFactory = (customDataSource?: RepositoryDataSource) => TokenRepository;
export type TokenHolderRepositoryFactory = (customDataSource?: RepositoryDataSource) => TokenHolderRepository;
export type TokenTransferRepositoryFactory = (customDataSource?: RepositoryDataSource) => TokenTransferRepository;
export type TokenActionRepositoryFactory = (customDataSource?: RepositoryDataSource) => TokenActionRepository;
export type TokenWhitelistRepositoryFactory = (customDataSource?: RepositoryDataSource) => TokenWhitelistRepository;
export type MultiPaymentRepositoryFactory = (customDataSource?: RepositoryDataSource) => MultiPaymentRepository;
export type ValidatorRoundRepositoryFactory = (customDataSource?: RepositoryDataSource) => ValidatorRoundRepository;
Expand Down
2 changes: 1 addition & 1 deletion packages/api-database/source/identifiers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ export const Identifiers = {
PluginRepositoryFactory: Symbol.for("API<Factory.PluginRepositoryFactory>"),
StateRepositoryFactory: Symbol.for("API<Factory.StateRepositoryFactory>"),
SystemRepositoryFactory: Symbol.for("API<Factory.SystemRepositoryFactory>"),
TokenActionRepositoryFactory: Symbol.for("API<Factory.TokenActionRepositoryFactory>"),
TokenHolderRepositoryFactory: Symbol.for("API<Factory.TokenHolderRepositoryFactory>"),
TokenRepositoryFactory: Symbol.for("API<Factory.TokenRepositoryFactory>"),
TokenTransferRepositoryFactory: Symbol.for("API<Factory.TokenTransferRepositoryFactory>"),
TokenWhitelistRepositoryFactory: Symbol.for("API<Factory.TokenWhitelistRepositoryFactory>"),
TransactionRepositoryFactory: Symbol.for("API<Factory.TransactionRepositoryFactory>"),
ValidatorRoundRepositoryFactory: Symbol.for("API<Factory.ValidatorRoundRepositoryFactory>"),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { MigrationInterface, QueryRunner } from "typeorm";

Check warning on line 1 in packages/api-database/source/migrations/1697617471901-CreateIndexes.ts

View workflow job for this annotation

GitHub Actions / source (22.x)

Filename is not in kebab case. Rename it to `1697617471901-create-indexes.ts`

export class CreateIndexes1697617471901 implements MigrationInterface {
public async up(queryRunner: QueryRunner): Promise<void> {
Expand Down Expand Up @@ -57,13 +57,13 @@
CREATE INDEX token_holders_address_token ON token_holders ("address", "token_address");
CREATE INDEX token_holders_token_address_balance ON token_holders ("address", "token_address", "balance");

CREATE INDEX token_transfers_all ON token_transfers ("block_number" DESC, "index" DESC);
CREATE INDEX token_transfers_all_from ON token_transfers ("from", "block_number" DESC, "index" DESC);
CREATE INDEX token_transfers_all_to ON token_transfers ("to", "block_number" DESC, "index" DESC);
CREATE INDEX token_transfers_address ON token_transfers ("address", "block_number" DESC, "index" DESC);
CREATE INDEX token_transfers_address_from ON token_transfers ("address", "from", "block_number" DESC, "index" DESC);
CREATE INDEX token_transfers_address_to ON token_transfers ("address", "to", "block_number" DESC, "index" DESC );
CREATE INDEX token_transfers_tx_hash ON token_transfers ("transaction_hash");
CREATE INDEX token_actions_all ON token_actions (action, "block_number" DESC, "index" DESC);
CREATE INDEX token_actions_all_from ON token_actions (action, "from", "block_number" DESC, "index" DESC);
CREATE INDEX token_actions_all_to ON token_actions (action, "to", "block_number" DESC, "index" DESC);
CREATE INDEX token_actions_address ON token_actions (action, "address", "block_number" DESC, "index" DESC);
CREATE INDEX token_actions_address_from ON token_actions (action, "address", "from", "block_number" DESC, "index" DESC);
CREATE INDEX token_actions_address_to ON token_actions (action, "address", "to", "block_number" DESC, "index" DESC );
CREATE INDEX token_actions_tx_hash ON token_actions ("transaction_hash");

-- when >= 3 chars
CREATE INDEX tokens_symbol_trgm ON tokens USING gin (symbol gin_trgm_ops);
Expand Down Expand Up @@ -130,13 +130,13 @@
DROP INDEX token_holders_address_token;
DROP INDEX token_holders_token_address_balance;

DROP INDEX token_transfers_all;
DROP INDEX token_transfers_all_from;
DROP INDEX token_transfers_all_to;
DROP INDEX token_transfers_address;
DROP INDEX token_transfers_address_from;
DROP INDEX token_transfers_address_to;
DROP INDEX token_transfers_tx_hash;
DROP INDEX token_actions_all;
DROP INDEX token_actions_all_from;
DROP INDEX token_actions_all_to;
DROP INDEX token_actions_address;
DROP INDEX token_actions_address_from;
DROP INDEX token_actions_address_to;
DROP INDEX token_actions_tx_hash;
`);
}
}
2 changes: 1 addition & 1 deletion packages/api-database/source/models/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ export * from "./plugin.js";
export * from "./state.js";
export * from "./system.js";
export * from "./token.js";
export * from "./token-action.js";
export * from "./token-holder.js";
export * from "./token-transfers.js";
export * from "./token-whitelist.js";
export * from "./transaction.js";
export * from "./validator-round.js";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,28 @@
import { Column, Entity } from "typeorm";

export enum TokenActionEnum {
Transfer = "Transfer",
Approval = "Approval",
}

@Entity({
name: "token_transfers",
name: "token_actions",
})
export class TokenTransfer {
export class TokenAction {
@Column({
primary: true,
type: "citext",
})
public readonly address!: string;

@Column({
enum: TokenActionEnum,
enumName: "token_action_enum",
primary: true,
type: "enum",
})
public readonly action!: string;

@Column({
primary: true,
type: "bigint",
Expand Down
2 changes: 1 addition & 1 deletion packages/api-database/source/repositories/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ export { makePeerRepository } from "./peer-repository.js";
export { makePluginRepository } from "./plugin-repository.js";
export { makeStateRepository } from "./state-repository.js";
export { makeSystemRepository } from "./system-repository.js";
export { makeTokenActionRepository } from "./token-action-repository.js";
export { makeTokenHolderRepository } from "./token-holder-repository.js";
export { makeTokenRepository } from "./token-repository.js";
export { makeTokenTransferRepository } from "./token-transfer-repository.js";
export { makeTokenWhitelistRepository } from "./token-whitelist-repository.js";
export { makeTransactionRepository } from "./transaction-repository.js";
export { makeValidatorRoundRepository } from "./validator-round-repository.js";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import type { RepositoryDataSource, TokenActionRepository, TokenActionRepositoryExtension } from "../contracts.js";
import { TokenAction } from "../models/index.js";
import { makeExtendedRepository } from "./repository-extension.js";

export const makeTokenActionRepository = (dataSource: RepositoryDataSource): TokenActionRepository =>
makeExtendedRepository<TokenAction, TokenActionRepositoryExtension>(TokenAction, dataSource, {
// Add any extensions here
});

This file was deleted.

12 changes: 6 additions & 6 deletions packages/api-database/source/service-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ import {
RepositoryDataSource,
StateRepository,
SystemRepository,
TokenActionRepository,
TokenHolderRepository,
TokenRepository,
TokenTransferRepository,
TokenWhitelistRepository,
TransactionRepository,
ValidatorRoundRepository,
Expand All @@ -39,8 +39,8 @@ import {
State,
System,
Token,
TokenAction,
TokenHolder,
TokenTransfer,
TokenWhitelist,
Transaction,
ValidatorRound,
Expand All @@ -57,9 +57,9 @@ import {
makePluginRepository,
makeStateRepository,
makeSystemRepository,
makeTokenActionRepository,
makeTokenHolderRepository,
makeTokenRepository,
makeTokenTransferRepository,
makeTokenWhitelistRepository,
makeTransactionRepository,
makeValidatorRoundRepository,
Expand Down Expand Up @@ -108,8 +108,8 @@ export class ServiceProvider extends Providers.ServiceProvider {
System,
Transaction,
Token,
TokenAction,
TokenHolder,
TokenTransfer,
TokenWhitelist,
MultiPayment,
ValidatorRound,
Expand Down Expand Up @@ -218,10 +218,10 @@ export class ServiceProvider extends Providers.ServiceProvider {
);

this.app
.bind<() => TokenTransferRepository>(Identifiers.TokenTransferRepositoryFactory)
.bind<() => TokenActionRepository>(Identifiers.TokenActionRepositoryFactory)
.toFactory(
() => (customDataSource?: RepositoryDataSource) =>
makeTokenTransferRepository(customDataSource ?? dataSource),
makeTokenActionRepository(customDataSource ?? dataSource),
);

this.app
Expand Down
61 changes: 46 additions & 15 deletions packages/api-http/integration/routes/tokens.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ import tokens from "../../test/fixtures/tokens.json";
import tokenHolders from "../../test/fixtures/token_holders.json";
import tokenTransferTokens from "../../test/fixtures/token_transfer.tokens.json";
import tokenTransferTransactions from "../../test/fixtures/token_transfer.transactions.json";
import tokenTransfers from "../../test/fixtures/token_transfers.json";
import tokenActions from "../../test/fixtures/token_actions.json";
import tokenWhitelist from "../../test/fixtures/token_whitelist.json";
import tokenTransfersResponse from "../../test/fixtures/token_transfers.response.json";
import tokenApprovalsResponse from "../../test/fixtures/token_approvals.response.json";

describe<{
app: Application;
Expand Down Expand Up @@ -150,54 +151,48 @@ describe<{
}
});

it("/tokens custom whitelist (POST)", async () => {
it("/tokens?whitelist", async () => {
await apiContext.tokenRepository.save(tokens);
await apiContext.tokenWhitelistRepository.save(tokenWhitelist.slice(0, 1));

const testCases = [
{
query: "",
method: "POST",
result: {
data: [tokens[0]],
statusCode: 200,
},
},
{
query: "",
body: JSON.stringify({ whitelist: [tokens[1].address] }),
method: "POST",
query: `?whitelist=${tokens[1].address}`,
result: {
data: [tokens[0], tokens[1]],
statusCode: 200,
},
},
{
query: "",
body: JSON.stringify({ whitelist: tokens.map((t) => t.address) }),
method: "POST",
query: `?whitelist=${tokens.map((t) => t.address).join(",")}`,
result: {
data: [...tokens].sort((a, b) => a.address.localeCompare(b.address)),
statusCode: 200,
},
},
{
query: "",
query: `?whitelist=0x0000000000000000000000000000000000000000`,
body: JSON.stringify({ whitelist: ["0x0000000000000000000000000000000000000000"] }),
method: "POST",
result: {
data: [tokens[0]],
statusCode: 200,
},
},
];

for (const { query, result, body, method } of testCases) {
for (const { query, result } of testCases) {
const endpoint = `/tokens${query}`;
if (result.statusCode === 404) {
await assert.rejects(async () => request(endpoint, options), "Response code 404 (Not Found)");
} else {
const { statusCode, data } = await request(endpoint, { ...options, body, method });
const { statusCode, data } = await request(endpoint, { ...options });
assert.equal(statusCode, result.statusCode);
assert.equal(data.data, result.data);
}
Expand Down Expand Up @@ -289,7 +284,7 @@ describe<{
it("/tokens/transfers", async () => {
await apiContext.tokenRepository.save(tokenTransferTokens);
await apiContext.transactionRepository.save(tokenTransferTransactions);
await apiContext.tokenTransferRepository.save(tokenTransfers);
await apiContext.tokenActionRepository.save(tokenActions);
await apiContext.tokenWhitelistRepository.save(tokenWhitelist);

const testCases = [
Expand Down Expand Up @@ -380,7 +375,7 @@ describe<{
it("/tokens/{}/transfers", async () => {
await apiContext.tokenRepository.save(tokenTransferTokens);
await apiContext.transactionRepository.save(tokenTransferTransactions);
await apiContext.tokenTransferRepository.save(tokenTransfers);
await apiContext.tokenActionRepository.save(tokenActions);
await apiContext.tokenWhitelistRepository.save(tokenWhitelist);

const testCases = [
Expand Down Expand Up @@ -412,4 +407,40 @@ describe<{
}
}
});

it("/tokens/{}/approvals", async () => {
await apiContext.tokenRepository.save(tokenTransferTokens);
await apiContext.transactionRepository.save(tokenTransferTransactions);
await apiContext.tokenActionRepository.save(tokenActions);
await apiContext.tokenWhitelistRepository.save(tokenWhitelist);

const testCases = [
{
query: "",
token: tokenTransferTokens[1].address,
result: {
data: tokenApprovalsResponse.filter((t) => t.token.address === tokenTransferTokens[1].address),
statusCode: 200,
},
},
{
query: "",
token: "0xdead78251073157e400c3d8d2ed92a85c958f9fa",
result: {
statusCode: 404,
},
},
];

for (const { query, token, result } of testCases) {
const endpoint = `/tokens/${token}/approvals${query}`;
if (result.statusCode === 404) {
await assert.rejects(async () => request(endpoint, options), "Response code 404 (Not Found)");
} else {
const { statusCode, data } = await request(endpoint, options);
assert.equal(statusCode, result.statusCode);
assert.equal(data.results, result.data);
}
}
});
});
16 changes: 16 additions & 0 deletions packages/api-http/integration/routes/transactions.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ import { describe } from "@mainsail/test-runner";
import { Application } from "@mainsail/kernel";
import receiptTransactions from "../../test/fixtures/receipt_transactions.json";
import receiptTransactionsResponse from "../../test/fixtures/receipt_transactions.response.json";
import tokens from "../../test/fixtures/tokens.json";
import tokenActions from "../../test/fixtures/token_actions.json";
import transactions from "../../test/fixtures/transactions.json";
import transactionsTokens from "../../test/fixtures/transactions.tokens.json";
import transactionsTokensResponse from "../../test/fixtures/transactions.tokens.response.json";
import transactionsResponse from "../../test/fixtures/transactions.response.json";
import wallets from "../../test/fixtures/wallets.json";
import { ApiContext, prepareSandbox } from "../../test/helpers/prepare-sandbox";
Expand Down Expand Up @@ -103,6 +107,18 @@ describe<{
assert.equal(data.data, transactionsResponse.at(-1));
});

it("/transactions/{hash}?includeTokens", async () => {
await apiContext.transactionRepository.save(transactionsTokens);
await apiContext.tokenActionRepository.save(tokenActions);
await apiContext.tokenRepository.save(tokens);

for (const result of transactionsTokensResponse) {
const { statusCode, data } = await request(`/transactions/${result.hash}?includeTokens=true`, options);
assert.equal(statusCode, 200);
assert.equal(data.data, result);
}
});

it("/transactions with receipt enriched", async () => {
await apiContext.transactionRepository.save(receiptTransactions);

Expand Down
Loading
Loading