Skip to content

Commit 9bee4e3

Browse files
committed
feat: allowing to query holders of certain fungible module
1 parent 9eb62b0 commit 9bee4e3

File tree

5 files changed

+95
-42
lines changed

5 files changed

+95
-42
lines changed

indexer/src/kadena-server/config/graphql-types.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ export type Scalars = {
2929

3030
export type BalanceNode = {
3131
__typename?: 'BalanceNode';
32+
accountName: Scalars['String']['output'];
3233
balance: Scalars['String']['output'];
3334
chainId: Scalars['String']['output'];
3435
module: Scalars['String']['output'];
@@ -807,7 +808,7 @@ export type Query = {
807808
};
808809

809810
export type QueryBalanceArgs = {
810-
accountName: Scalars['String']['input'];
811+
accountName?: InputMaybe<Scalars['String']['input']>;
811812
after?: InputMaybe<Scalars['String']['input']>;
812813
before?: InputMaybe<Scalars['String']['input']>;
813814
chainIds?: InputMaybe<Array<Scalars['String']['input']>>;
@@ -2171,6 +2172,7 @@ export type BalanceNodeResolvers<
21712172
ContextType = any,
21722173
ParentType extends ResolversParentTypes['BalanceNode'] = ResolversParentTypes['BalanceNode'],
21732174
> = {
2175+
accountName?: Resolver<ResolversTypes['String'], ParentType, ContextType>;
21742176
balance?: Resolver<ResolversTypes['String'], ParentType, ContextType>;
21752177
chainId?: Resolver<ResolversTypes['String'], ParentType, ContextType>;
21762178
module?: Resolver<ResolversTypes['String'], ParentType, ContextType>;
@@ -2972,7 +2974,7 @@ export type QueryResolvers<
29722974
ResolversTypes['QueryBalanceConnection'],
29732975
ParentType,
29742976
ContextType,
2975-
RequireFields<QueryBalanceArgs, 'accountName'>
2977+
Partial<QueryBalanceArgs>
29762978
>;
29772979
block?: Resolver<
29782980
Maybe<ResolversTypes['Block']>,

indexer/src/kadena-server/config/schema.graphql

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ type Query {
124124
Retrieve live balances for a given account with optional filtering by chains and module. Default page size is 20.
125125
"""
126126
balance(
127-
accountName: String!
127+
accountName: String
128128
chainIds: [String!]
129129
module: String
130130
after: String
@@ -478,6 +478,7 @@ type QueryBalanceConnectionEdge {
478478
}
479479

480480
type BalanceNode {
481+
accountName: String!
481482
module: String!
482483
chainId: String!
483484
balance: String!

indexer/src/kadena-server/repository/application/balance-repository.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ export interface GetTokensParams extends PaginationsParams {}
9999
* Parameters for fetching account balances with pagination and filters.
100100
*/
101101
export interface GetAccountBalancesParams extends PaginationsParams {
102-
accountName: string;
102+
accountName?: string | null;
103103
chainIds?: string[] | null;
104104
module?: string | null;
105105
}
@@ -168,7 +168,12 @@ export default interface BalanceRepository {
168168
*/
169169
getAccountBalances(params: GetAccountBalancesParams): Promise<{
170170
pageInfo: PageInfo;
171-
edges: ConnectionEdge<{ module: string; chainId: string; balance: string }>[];
171+
edges: ConnectionEdge<{
172+
accountName: string;
173+
module: string;
174+
chainId: string;
175+
balance: string;
176+
}>[];
172177
}>;
173178

174179
/**

indexer/src/kadena-server/repository/infra/repository/balance-db-repository.ts

Lines changed: 79 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -471,7 +471,7 @@ export default class BalanceDbRepository implements BalanceRepository {
471471
* Retrieves live balances for an account with optional module and chain filters, paginated.
472472
*/
473473
async getAccountBalances(params: {
474-
accountName: string;
474+
accountName?: string | null;
475475
chainIds?: string[] | null;
476476
module?: string | null;
477477
after?: string | null;
@@ -481,37 +481,83 @@ export default class BalanceDbRepository implements BalanceRepository {
481481
}) {
482482
const { accountName, chainIds, module } = params;
483483
const { limit, order, after, before } = getPaginationParams(params);
484+
let queryParams: any[] = [];
485+
let query = '';
484486

485-
const queryParams: any[] = [accountName, limit];
486-
let conditions = 'WHERE b.account = $1';
487-
488-
if (module) {
489-
queryParams.push(module);
490-
conditions += ` AND b.module = $${queryParams.length}`;
491-
}
492-
493-
if (chainIds && chainIds.length) {
494-
queryParams.push(chainIds);
495-
conditions += ` AND b."chainId" = ANY($${queryParams.length})`;
496-
}
497-
498-
if (after) {
499-
queryParams.push(after);
500-
conditions += ` AND b.id < $${queryParams.length}`;
501-
}
502-
503-
if (before) {
504-
queryParams.push(before);
505-
conditions += ` AND b.id > $${queryParams.length}`;
506-
}
487+
if (accountName) {
488+
// Original behavior: filter by account, optionally by module and chains
489+
queryParams = [accountName, limit];
490+
let conditions = 'WHERE b.account = $1';
491+
492+
if (module) {
493+
queryParams.push(module);
494+
conditions += ` AND b.module = $${queryParams.length}`;
495+
}
496+
497+
if (chainIds && chainIds.length) {
498+
queryParams.push(chainIds);
499+
conditions += ` AND b."chainId" = ANY($${queryParams.length})`;
500+
}
501+
502+
if (after) {
503+
queryParams.push(after);
504+
conditions += ` AND b.id < $${queryParams.length}`;
505+
}
506+
507+
if (before) {
508+
queryParams.push(before);
509+
conditions += ` AND b.id > $${queryParams.length}`;
510+
}
511+
512+
// If module specified, return at most one row per chain (latest by id)
513+
if (module) {
514+
query = `
515+
WITH ranked AS (
516+
SELECT b.id, b."chainId", b.module, b.account,
517+
ROW_NUMBER() OVER (PARTITION BY b."chainId" ORDER BY b.id DESC) AS rn
518+
FROM "Balances" b
519+
${conditions}
520+
)
521+
SELECT id, "chainId", module, account
522+
FROM ranked
523+
WHERE rn = 1
524+
ORDER BY id ${order}
525+
LIMIT $2
526+
`;
527+
} else {
528+
query = `
529+
SELECT b.id, b."chainId", b.module, b.account
530+
FROM "Balances" b
531+
${conditions}
532+
ORDER BY b.id ${order}
533+
LIMIT $2
534+
`;
535+
}
536+
} else {
537+
// Holders mode: require module; get latest per (account, chainId)
538+
// Build conditions starting with module filter
539+
queryParams = [module, limit];
540+
let conditions = 'WHERE b.module = $1';
541+
542+
if (chainIds && chainIds.length) {
543+
queryParams.push(chainIds);
544+
conditions += ` AND b."chainId" = ANY($${queryParams.length})`;
545+
}
546+
547+
if (after) {
548+
queryParams.push(after);
549+
conditions += ` AND b.id < $${queryParams.length}`;
550+
}
551+
552+
if (before) {
553+
queryParams.push(before);
554+
conditions += ` AND b.id > $${queryParams.length}`;
555+
}
507556

508-
// If module specified, return at most one row per chain (latest by id)
509-
let query = '';
510-
if (module) {
511557
query = `
512558
WITH ranked AS (
513559
SELECT b.id, b."chainId", b.module, b.account,
514-
ROW_NUMBER() OVER (PARTITION BY b."chainId" ORDER BY b.id DESC) AS rn
560+
ROW_NUMBER() OVER (PARTITION BY b.account, b."chainId" ORDER BY b.id DESC) AS rn
515561
FROM "Balances" b
516562
${conditions}
517563
)
@@ -521,15 +567,6 @@ export default class BalanceDbRepository implements BalanceRepository {
521567
ORDER BY id ${order}
522568
LIMIT $2
523569
`;
524-
} else {
525-
// Without module, allow multiple modules per chain
526-
query = `
527-
SELECT b.id, b."chainId", b.module, b.account
528-
FROM "Balances" b
529-
${conditions}
530-
ORDER BY b.id ${order}
531-
LIMIT $2
532-
`;
533570
}
534571

535572
const { rows } = await rootPgPool.query(query, queryParams);
@@ -543,7 +580,12 @@ export default class BalanceDbRepository implements BalanceRepository {
543580
const balance = formatBalance_NODE(res).toString();
544581
return {
545582
cursor: row.id.toString(),
546-
node: { module: row.module, chainId: String(row.chainId), balance },
583+
node: {
584+
accountName: row.account,
585+
module: row.module,
586+
chainId: String(row.chainId),
587+
balance,
588+
},
547589
};
548590
});
549591

indexer/src/kadena-server/resolvers/query/balance-query-resolver.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ export const balanceQueryResolver: QueryResolvers<ResolverContext>['balance'] =
77
context,
88
) => {
99
const { accountName, chainIds, module, after, before, first, last } = args;
10+
if (!accountName && !module) {
11+
throw new Error('Either accountName or module must be provided.');
12+
}
1013
const output = await context.balanceRepository.getAccountBalances({
1114
accountName,
1215
chainIds: chainIds ?? null,

0 commit comments

Comments
 (0)