Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
a7cd519
feat: create delegation controller
edulennert Jan 7, 2026
0af72f2
feat: create delegation mappers
edulennert Jan 7, 2026
f855dc0
feat: create new files
edulennert Jan 7, 2026
76c9c36
feat: create controllers, service ans repositories
edulennert Jan 15, 2026
6cbccd0
feat: fix controller
edulennert Jan 15, 2026
aa82290
feat: create actual endpoint
edulennert Jan 15, 2026
6551c28
feat: break endpoint
edulennert Jan 15, 2026
6a075f7
feat: remove unused param
edulennert Jan 16, 2026
4d3e3e8
feat: create historical file
edulennert Jan 16, 2026
c534279
fix: historical delegations query
PedroBinotto Jan 16, 2026
e17c100
fix: oops
PedroBinotto Jan 16, 2026
482cb54
Merge branch 'feat/delegations-rest-endpoint' of github.com:blockful-…
edulennert Jan 16, 2026
23cf1d6
feat: get only used data
edulennert Jan 16, 2026
faf49a6
Merge branch 'dev' into feat/delegations-rest-endpoint
edulennert Jan 16, 2026
61a7961
fix: merge resolver index files
PedroBinotto Jan 16, 2026
22ff9ce
feat: create delegations endpoint
edulennert Jan 16, 2026
c278508
feat: fix query and return only the latest delegation
edulennert Jan 16, 2026
f351c4f
Merge branch 'feat/delegations-rest-endpoint' of github.com:blockful-…
edulennert Jan 17, 2026
f7dccf7
feat: partial delegation fetching
PedroBinotto Jan 19, 2026
22c67d0
Update apps/indexer/src/api/controllers/delegations/delegations.ts
edulennert Jan 21, 2026
17dafdb
Update apps/indexer/src/api/mappers/delegations/delegations.ts
edulennert Jan 21, 2026
927fe3a
feat: merge branch dev into feat/delegations-rest-endpoint
edulennert Jan 21, 2026
1737ac1
Update apps/indexer/src/api/repositories/delegations/historical.ts
edulennert Jan 21, 2026
34c10b5
refactor: fix linter
edulennert Jan 21, 2026
22b2f76
Update apps/indexer/src/api/repositories/delegations/general.ts
edulennert Jan 21, 2026
b897cac
refactor: remove get address from mappers/delegations/historical
edulennert Jan 21, 2026
7e9d556
refactor: make ponder schema address
edulennert Jan 21, 2026
46e234f
refactor: rename functions to have a lowercase first letter
edulennert Jan 21, 2026
9a92fb0
refactor: use default fuctionoo drizzle
edulennert Jan 21, 2026
4bbc716
fix: eslint
edulennert Jan 21, 2026
b1b4b69
refactor: remove as address
edulennert Jan 21, 2026
ec5fd83
Merge branch 'dev' into feat/delegations-rest-endpoint
pikonha Jan 22, 2026
bb8873e
fix: resolve pr reviews
edulennert Jan 22, 2026
69be668
Merge branch 'feat/delegations-rest-endpoint' of github.com:blockful-…
edulennert Jan 22, 2026
e50c932
fix: resolve requested changes
edulennert Jan 22, 2026
28f9f85
Merge branch 'dev' into feat/delegations-rest-endpoint
edulennert Jan 22, 2026
8b80b1b
Merge branch 'dev' into feat/delegations-rest-endpoint
edulennert Jan 22, 2026
ce80e4b
chore: export from barrel file
pikonha Jan 22, 2026
7ec464c
fix: remove repeated item query
edulennert Jan 22, 2026
8fca5da
refactor: remome address in param
edulennert Jan 22, 2026
6cfbc98
feat: fix delegations graphql queries
edulennert Jan 22, 2026
8d0ea0a
fix: hooks types
edulennert Jan 22, 2026
ba0343c
Merge branch 'dev' into feat/delegations-rest-endpoint
edulennert Jan 22, 2026
c34e1da
Merge branch 'dev' into feat/delegations-rest-endpoint
edulennert Jan 23, 2026
c56b727
refactor: remove comment
edulennert Jan 23, 2026
96ea87d
Merge branch 'feat/delegations-rest-endpoint' of github.com:blockful-…
edulennert Jan 23, 2026
00a21fa
Merge branch 'dev' into feat/delegations-rest-endpoint
edulennert Jan 23, 2026
1240d11
chore: remove delegations from gateway
pikonha Jan 26, 2026
6b5c584
Merge branch 'dev' into feat/delegations-rest-endpoint
edulennert Jan 27, 2026
0653de2
feat: resolve requested changes
edulennert Jan 27, 2026
b85fa22
feat: remove unused query
edulennert Jan 27, 2026
4e72443
refactor: remove unused query from generated types
edulennert Jan 27, 2026
cabf238
Merge branch 'feat/delegations-rest-endpoint' of github.com:blockful-…
edulennert Jan 27, 2026
f8a8372
refactor: remove partial delegations
edulennert Jan 27, 2026
8ccba53
fix: typecheck
edulennert Jan 27, 2026
b518a38
refactor: remove totalCount
edulennert Jan 27, 2026
ec69bef
fix: timestamp in votingPower query
edulennert Jan 27, 2026
273efe7
feat: fix generated files
edulennert Jan 27, 2026
dee5abd
fix: conflict
edulennert Jan 27, 2026
c9b67e5
Merge branch 'dev' into feat/delegations-rest-endpoint
edulennert Jan 27, 2026
5d0889d
feat: generate generated files
edulennert Jan 27, 2026
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
2 changes: 2 additions & 0 deletions apps/api-gateway/meshrc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ export default processConfig(
"Query.!{account}",
"Query.!{daoMetricsDayBucket}",
"Query.!{daoMetricsDayBuckets}",
"Query.!{delegation}",
"Query.!{delegations}",
"Query.!{proposalsOnchains}",
"Query.!{proposalsOnchain}",
"Query.!{tokenPrices}",
Expand Down
150 changes: 104 additions & 46 deletions apps/api-gateway/schema.graphql

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion apps/api-gateway/src/resolvers/list.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
const daoListQueries = [
"daoMetricsDayBuckets",
"delegations",
"votesOnchains",
"votingPowerHistorys", // FIXME: Leave endpoint active for now as it is still used by the notification bot
];
Expand Down
2 changes: 2 additions & 0 deletions apps/api-gateway/src/resolvers/rest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ const daoItemQueries = [
"compareTotalSupply",
"compareTreasury",
"compareVotes",
"delegations",
"dao",
"delegationPercentageByDay",
"getDaoTokenTreasury",
Expand All @@ -22,6 +23,7 @@ const daoItemQueries = [
"getTotalTreasury",
"getVotingPower",
"historicalBalances",
"historicalDelegations",
"historicalTokenData",
"historicalVotingPowers",
"lastUpdate",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,11 @@ interface UseTopAccountsChartDataParams {
daoId: DaoIdEnum;
}

type DelegationItems = GetDelegationHistoryItemsQuery["delegations"]["items"];
type DelegationItems = NonNullable<
NonNullable<
GetDelegationHistoryItemsQuery["historicalDelegations"]
>["items"][number]
>[];

export function useTopAccountsChartData({
chartData,
Expand All @@ -46,9 +50,9 @@ export function useTopAccountsChartData({
return addresses
.map((address) => {
const latestDelegation = delegationData[address]?.find(
(item) => item.delegateAccountId !== zeroAddress,
(item) => item.delegateAddress !== zeroAddress,
);
return latestDelegation?.delegateAccountId as Address | undefined;
return latestDelegation?.delegateAddress as Address | undefined;
})
.filter((address): address is Address => !!address);
}, [addresses, delegationData]);
Expand Down Expand Up @@ -79,9 +83,9 @@ export function useTopAccountsChartData({
query: GetDelegationHistoryItemsDocument,
variables: {
delegator: address,
orderBy: "timestamp",
orderDirection: "desc",
limit: 10,
skip: 0,
},
context: {
headers: {
Expand Down Expand Up @@ -114,7 +118,11 @@ export function useTopAccountsChartData({
const dataByAddress = addresses.reduce(
(acc, address, index) => {
acc[address] =
delegationResults[index].data?.delegations?.items || [];
delegationResults[
index
].data?.historicalDelegations?.items?.filter(
(item): item is NonNullable<typeof item> => item !== null,
) || [];
return acc;
},
{} as Record<string, DelegationItems>,
Expand Down Expand Up @@ -154,12 +162,11 @@ export function useTopAccountsChartData({
const processedData = useMemo(() => {
return chartData.map((item) => {
const latestDelegation = delegationData[item.address]?.find(
(delegation) => delegation.delegateAccountId !== zeroAddress,
(delegation) => delegation.delegateAddress !== zeroAddress,
);

const delegateAddress = latestDelegation?.delegateAccountId as
| Address
| undefined;
const delegateAddress =
(latestDelegation?.delegateAddress as Address | undefined) || undefined;

return {
...item,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
"use client";

import { useGetDelegationHistoryItemsQuery } from "@anticapture/graphql-client/hooks";
import {
useGetDelegationHistoryItemsQuery,
useGetDelegationHistoryCountQuery,
} from "@anticapture/graphql-client/hooks";
import { GetDelegationHistoryItemsQuery } from "@anticapture/graphql-client";
GetDelegationHistoryItemsQuery,
QueryInput_HistoricalDelegations_OrderDirection,
} from "@anticapture/graphql-client";
import { useMemo, useCallback, useState, useEffect } from "react";
import { NetworkStatus } from "@apollo/client";
import { DaoIdEnum } from "@/shared/types/daos";
Expand All @@ -23,7 +23,11 @@ interface PaginationInfo {
}

interface UseDelegationHistoryResult {
data: GetDelegationHistoryItemsQuery["delegations"]["items"] | null;
data:
| NonNullable<
GetDelegationHistoryItemsQuery["historicalDelegations"]
>["items"]
| null;
loading: boolean;
error: Error | null;
refetch: () => void;
Expand Down Expand Up @@ -72,16 +76,19 @@ export const useDelegationHistory = ({
} = useGetDelegationHistoryItemsQuery({
variables: {
delegator: delegatorAccountId,
after: undefined,
before: undefined,
orderBy,
orderDirection,
skip: (currentPage - 1) * itemsPerPage,
limit: itemsPerPage,
...(delegateAccountId && { delegate: delegateAccountId }),
orderDirection:
orderDirection === "asc"
? QueryInput_HistoricalDelegations_OrderDirection.Asc
: QueryInput_HistoricalDelegations_OrderDirection.Desc,
...(delegateAccountId && { delegate: [delegateAccountId] }),
...(filterVariables?.fromValue && {
fromValue: filterVariables.fromValue,
fromValue: filterVariables.fromValue.toString(),
}),
...(filterVariables?.toValue && {
toValue: filterVariables.toValue.toString(),
}),
...(filterVariables?.toValue && { toValue: filterVariables.toValue }),
},
context: {
headers: {
Expand All @@ -94,99 +101,107 @@ export const useDelegationHistory = ({

// Refetch data when sorting changes to ensure we start from page 1
useEffect(() => {
setCurrentPage(1);
refetch({
after: undefined,
before: undefined,
orderBy,
orderDirection,
skip: 0,
limit: itemsPerPage,
orderDirection:
orderDirection === "asc"
? QueryInput_HistoricalDelegations_OrderDirection.Asc
: QueryInput_HistoricalDelegations_OrderDirection.Desc,
});
}, [orderBy, orderDirection, refetch]);
}, [orderDirection, refetch, itemsPerPage]);

const processedData = useMemo(() => {
return delegationHistoryData?.delegations?.items ?? [];
return (
delegationHistoryData?.historicalDelegations?.items?.filter(
(item): item is NonNullable<typeof item> => item !== null,
) ?? []
);
}, [delegationHistoryData]);

// Fetch totalCount with separate lightweight query
const { data: countData } = useGetDelegationHistoryCountQuery({
variables: { delegator: delegatorAccountId },
context: {
headers: {
"anticapture-dao-id": daoId,
},
},
});

const pagination = useMemo<PaginationInfo>(() => {
const pageInfo = delegationHistoryData?.delegations?.pageInfo;
const totalCount = countData?.delegations?.totalCount || 0;
const totalCount =
delegationHistoryData?.historicalDelegations?.totalCount || 0;
const currentItemsCount =
delegationHistoryData?.delegations?.items?.length || 0;
delegationHistoryData?.historicalDelegations?.items?.length || 0;
const totalPages = Math.ceil(totalCount / itemsPerPage);
const hasNextPage = currentPage < totalPages;
const hasPreviousPage = currentPage > 1;

return {
hasNextPage: pageInfo?.hasNextPage || false,
hasPreviousPage: pageInfo?.hasPreviousPage || false,
endCursor: pageInfo?.endCursor,
startCursor: pageInfo?.startCursor,
hasNextPage,
hasPreviousPage,
endCursor: undefined,
startCursor: undefined,
totalCount,
currentPage,
totalPages,
itemsPerPage,
currentItemsCount,
};
}, [
delegationHistoryData?.delegations?.pageInfo,
delegationHistoryData?.delegations?.items?.length,
delegationHistoryData?.historicalDelegations?.items?.length,
delegationHistoryData?.historicalDelegations?.totalCount,
currentPage,
itemsPerPage,
countData?.delegations?.totalCount,
]);

// Fetch next page function
const fetchNextPage = useCallback(async () => {
if (
!pagination.hasNextPage ||
!pagination.endCursor ||
isPaginationLoading
) {
if (!pagination.hasNextPage || isPaginationLoading) {
console.warn("No next page available");
return;
}

setIsPaginationLoading(true);

try {
const skip = currentPage * itemsPerPage;
await fetchMore({
variables: {
delegator: delegatorAccountId,
after: pagination.endCursor,
before: undefined,
orderBy,
orderDirection,
skip,
limit: itemsPerPage,
orderDirection:
orderDirection === "asc"
? QueryInput_HistoricalDelegations_OrderDirection.Asc
: QueryInput_HistoricalDelegations_OrderDirection.Desc,
...(delegateAccountId && { delegate: [delegateAccountId] }),
...(filterVariables?.fromValue && {
fromValue: filterVariables.fromValue.toString(),
}),
...(filterVariables?.toValue && {
toValue: filterVariables.toValue.toString(),
}),
},
updateQuery: (
previousResult: GetDelegationHistoryItemsQuery,
{
fetchMoreResult,
}: { fetchMoreResult?: GetDelegationHistoryItemsQuery },
) => {
if (!fetchMoreResult) return previousResult;
const prevItems = previousResult.delegations.items ?? [];
const newItems = fetchMoreResult.delegations.items ?? [];
if (!fetchMoreResult?.historicalDelegations) return previousResult;
const prevItems =
previousResult.historicalDelegations?.items?.filter(
(item): item is NonNullable<typeof item> => item !== null,
) ?? [];
const newItems =
fetchMoreResult.historicalDelegations.items?.filter(
(item): item is NonNullable<typeof item> => item !== null,
) ?? [];
const merged = [
...prevItems,
...newItems.filter(
(n) => !prevItems.some((p) => p.timestamp === n.timestamp),
),
];
// Replace the current data with the new page data
return {
...fetchMoreResult,
delegations: {
...fetchMoreResult.delegations,
historicalDelegations: {
...fetchMoreResult.historicalDelegations,
items: merged,
totalCount: fetchMoreResult.historicalDelegations.totalCount ?? 0,
},
};
},
Expand All @@ -201,49 +216,57 @@ export const useDelegationHistory = ({
}, [
fetchMore,
pagination.hasNextPage,
pagination.endCursor,
orderBy,
currentPage,
itemsPerPage,
orderDirection,
delegatorAccountId,
delegateAccountId,
filterVariables,
isPaginationLoading,
]);

// Fetch previous page function
const fetchPreviousPage = useCallback(async () => {
if (
!pagination.hasPreviousPage ||
!pagination.startCursor ||
isPaginationLoading
) {
if (!pagination.hasPreviousPage || isPaginationLoading) {
console.warn("No previous page available or already loading");
return;
}

setIsPaginationLoading(true);

try {
const skip = Math.max(0, (currentPage - 2) * itemsPerPage);
await fetchMore({
variables: {
after: undefined,
before: pagination.startCursor,
orderBy,
orderDirection,
delegator: delegatorAccountId,
skip,
limit: itemsPerPage,
orderDirection:
orderDirection === "asc"
? QueryInput_HistoricalDelegations_OrderDirection.Asc
: QueryInput_HistoricalDelegations_OrderDirection.Desc,
...(delegateAccountId && { delegate: [delegateAccountId] }),
...(filterVariables?.fromValue && {
fromValue: filterVariables.fromValue.toString(),
}),
...(filterVariables?.toValue && {
toValue: filterVariables.toValue.toString(),
}),
},
updateQuery: (
previousResult: GetDelegationHistoryItemsQuery,
{
fetchMoreResult,
}: { fetchMoreResult?: GetDelegationHistoryItemsQuery },
) => {
if (!fetchMoreResult) return previousResult;

if (!fetchMoreResult?.historicalDelegations) return previousResult;
// Replace the current data with the new page data
return {
...fetchMoreResult,
delegations: {
...fetchMoreResult.delegations,
items: fetchMoreResult.delegations.items,
historicalDelegations: {
...fetchMoreResult.historicalDelegations,
items: fetchMoreResult.historicalDelegations.items,
totalCount: fetchMoreResult.historicalDelegations.totalCount ?? 0,
},
};
},
Expand All @@ -259,9 +282,12 @@ export const useDelegationHistory = ({
}, [
fetchMore,
pagination.hasPreviousPage,
pagination.startCursor,
orderBy,
currentPage,
itemsPerPage,
orderDirection,
delegatorAccountId,
delegateAccountId,
filterVariables,
isPaginationLoading,
]);

Expand Down
Loading