Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add pagination to addresses #322

Merged
merged 8 commits into from
Sep 24, 2024
2 changes: 1 addition & 1 deletion client/src/api/neighborhood-provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export function NeighborhoodProvider({ children }: { children: ReactNode }) {

const tokensQuery = useQuery(
["neighborhoods", id, "tokens"],
getNeighborhoodTokens(id),
getNeighborhoodTokens(id, {page: 1, limit: 100}),
);

const { data, isError, isSuccess} = tokensQuery;
Expand Down
8 changes: 6 additions & 2 deletions client/src/api/queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,12 @@ export function getNeighborhoodTransaction(id: number, hash: string) {
return get(`neighborhoods/${id}/transactions/${hash}`);
}

export function getNeighborhoodAddress(id: number, address: string) {
return get(`neighborhoods/${id}/addresses/${address}`);
export function getNeighborhoodAddress(
id: number,
address: string,
{ page = PAGE, limit = LIMIT } = {}
) {
return get(`neighborhoods/${id}/addresses/${address}`, { page, limit });
}

export function getNeighborhoodMigrations(
Expand Down
23 changes: 15 additions & 8 deletions client/src/pages/address.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,30 @@
import { Box, Heading, Text } from "@liftedinit/ui";
import { useQuery } from "@tanstack/react-query";
import { useContext } from "react";
import { useContext, useState } from "react";
import { Link, useParams } from "react-router-dom";

import { getNeighborhoodAddress, NeighborhoodContext } from "api";
import { ObjectTable, QueryBox, TransactionList } from "ui";
import { ObjectTable, QueryBox, TransactionList, Pager } from "ui";

import { useBgColor } from "utils";

export function Address() {
const { id } = useContext(NeighborhoodContext);
const { address } = useParams();

const [page, setPage] = useState(1);
const query = useQuery(
["neighborhoods", id, "addresses", address],
getNeighborhoodAddress(id, address as string),
["neighborhoods", id, "addresses", address, page],
getNeighborhoodAddress(id, address as string, { page }),
);
const { data, error, isLoading } = query;

const bg = useBgColor();

console.log(`data: ${JSON.stringify(data)}`);
console.log(`error: ${error}`);
console.log(`totalPages: ${JSON.stringify(data?.transactions.totalPages)}`);
console.log(`page: ${page}`);

return (
<Box my={6} bg={bg} p={6}>
<Heading size="sm">
Expand All @@ -31,15 +36,17 @@ export function Address() {
<QueryBox query={query}>
<ObjectTable obj={{ Address: address }} />
</QueryBox>
{data?.transactions.length ? (
{data?.transactions.items.length ? (
<TransactionList
txns={data.transactions}
txns={data?.transactions.items}
error={error as Error}
isLoading={isLoading}
/>
) : (
""
""
)}

<Pager page={page} setPage={setPage} totalPages={data?.transactions.meta.totalPages} />
</Box>
);
}
4 changes: 2 additions & 2 deletions client/src/pages/transaction/ledger-send.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ export function useLedgerSend(data: any) {
{data.argument.to}
</Code>
),
Amount: `${(
Amount: `${parseFloat((
data.argument.amount /
10 ** token.precision
).toLocaleString()} ${token.symbol}`,
).toFixed(token.precision).toLocaleString())} ${token.symbol}`,
};
}
10 changes: 5 additions & 5 deletions client/src/pages/transaction/tokens-mint-burn.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,17 @@ import { useFindToken } from "./tokens";

export function useTokensMintBurn(data: any) {
const token = useFindToken(data.argument.symbol);

return {
Token: (
<Code as={Link} to={`/addresses/${token.address}`} color="brand.teal.500">
{data.argument.symbol}
{data.argument.symbol}
</Code>
),
Amounts: (
<Table variant="unstyled">
<Tbody>
{Object.entries(data.argument.amounts).map(([address, amount]) => (
{Object.entries(data.argument.amounts).map(([address, amount]) => (
<Tr mt="5px" mb="5px">
<Td pt="5px" pb="5px" pl="0" ps="0">
<Code
Expand All @@ -28,13 +29,12 @@ export function useTokensMintBurn(data: any) {
{(
parseInt(amount as string) /
10 ** token.precision
).toLocaleString()}{" "}
{token.symbol}
).toLocaleString()} {token.symbol}
</Td>
</Tr>
))}
</Tbody>
</Table>
),
};
}
}
7 changes: 4 additions & 3 deletions client/src/pages/transaction/tokens.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ interface token {
symbol: string,
address: string,
precision: number

}

export const MFX_TOKEN = {
Expand All @@ -28,12 +27,14 @@ export function useFindToken(address: string) {

let KNOWN_TOKENS: token[] = context.tokens

console.log(`context.tokens: ${JSON.stringify(context.tokens)}`);

// Check if there are tokens otherwise configure default to MFX
if (KNOWN_TOKENS === undefined || KNOWN_TOKENS.length === 0) {
KNOWN_TOKENS = [MFX_TOKEN];
} else {
} else {
KNOWN_TOKENS = context.tokens;
}
}

return KNOWN_TOKENS?.find((t) => t.address === address) ?? UNKNOWN_TOKEN;
}
7 changes: 5 additions & 2 deletions server/src/neighborhoods/addresses/addresses.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { EventDto } from "../../dto/event.dto";
import { TransactionDto } from "../../dto/transaction.dto";
import { ParseAddressPipe } from "../../utils/pipes";
import { AddressesService } from "./addresses.service";
import { PaginatedAddressDto } from "./addresses.service";

const maxLimit = 1000;

Expand Down Expand Up @@ -44,8 +45,10 @@ export class AddressesController {
async findOne(
@Param("nid", ParseIntPipe) nid: number,
@Param("address", ParseAddressPipe) address: Address,
): Promise<AddressDto> {
const a = await this.address.findOne(nid, address, { page: 1, limit: 100 });
@Query("page", new DefaultValuePipe(1), ParseIntPipe) page = 1,
@Query("limit", new DefaultValuePipe(100), ParseIntPipe) limit = 100,
): Promise<PaginatedAddressDto> {
const a = await this.address.findOne(nid, address, { page, limit });

if (!a) {
throw new NotFoundException();
Expand Down
31 changes: 26 additions & 5 deletions server/src/neighborhoods/addresses/addresses.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,25 @@ import { Event } from "../../database/entities/event.entity";
import { TransactionDetails } from "../../database/entities/transaction-details.entity";
import { Transaction } from "../../database/entities/transaction.entity";
import { AddressDto } from "../../dto/address.dto";
import { TransactionDto } from "../../dto/transaction.dto";
import { EventDto } from "../../dto/event.dto";
import { NetworkService } from "../../services/network.service";
import { TxAnalyzerService } from "../../services/scheduler/tx-analyzer.service";
import { EventsService } from "../events/events.service";

export interface PaginatedAddressDto {
address: string;
transactions: {
items: TransactionDto[];
meta: any;
};
events: {
items: EventDto[];
meta: any;
};
}


@Injectable()
export class AddressesService {
private readonly logger = new Logger(AddressesService.name);
Expand Down Expand Up @@ -81,15 +96,21 @@ export class AddressesService {
nid: number,
address: Address,
txOptions: IPaginationOptions,
evOptions = txOptions,
): Promise<AddressDto> {
evOptions: IPaginationOptions = txOptions,
): Promise<PaginatedAddressDto> {
const transactions = await this.findTransactions(nid, address, txOptions);
const events = await this.findEvents(nid, address, evOptions);

return {
address: address.toString(),
transactions: transactions.items.map((t) => t.intoDto()),
events: events.items.map((e) => e.intoDto()),
transactions: {
items: transactions.items.map((t) => t.intoDto()),
meta: transactions.meta,
},
events: {
items: events.items.map((e) => e.intoDto() as EventDto),
meta: events.meta,
},
};
}

Expand Down
10 changes: 9 additions & 1 deletion server/src/neighborhoods/events/events.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,15 @@ export class EventsService {
}

public async save(entities: EventEntity[]): Promise<void> {
await this.eventRepository.save(entities);
await Promise.all(
entities.map(async (entity) => {
try {
await this.eventRepository.save(entity);
} catch (error) {
this.logger.error(`Error occurred while saving event: ${JSON.stringify(entity)}, ${error}, eventId: ${JSON.stringify(entity.eventId)}`);
}
})
);
}

async findWithAddress(
Expand Down
4 changes: 3 additions & 1 deletion server/src/neighborhoods/migrations/migrations.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,9 @@ export class MigrationsService {
.createQueryBuilder("m")
.select(["m"])
.innerJoin("m.transaction", "t")
.innerJoin(Block, 'b', 'b.id = t.blockId AND b.neighborhoodId = :neighborhoodId', { neighborhoodId: neighborhoodId });
.innerJoin(Block, 'b', 'b.id = t.blockId AND b.neighborhoodId = :neighborhoodId', { neighborhoodId: neighborhoodId })
.orderBy("m.createdDate", "DESC");


if (status) {
query = query.andWhere("m.status = :status", { status });
Expand Down
16 changes: 1 addition & 15 deletions server/src/services/scheduler/neighborhood-updater/updater.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ export class NeighborhoodUpdater {
// Lower bound on eventID exclusive.
new Map([[3, new Map([[0, [1, latestEventId]]])]]),
);
this.logger.debug(`Got ${events.events.length} events for neighborhood ${neighborhood.name}`);

await this.events.save(
events.events.map((ev) => {
Expand All @@ -77,21 +78,6 @@ export class NeighborhoodUpdater {
}),
);

console.log(
JSON.stringify(
events.events
.map((ev) => {
return {
...ev,
id: bufferToHex(ev.id),
time: ev.time.toISOString(),
};
})
.filter((ev) => ev.info === null),
null,
2,
),
);
}

private async updateNeighborhoodMissingTransactionDetails(
Expand Down