Skip to content

Commit 5508fb4

Browse files
committed
Add SVM Token Holders by Mint endpoint
- Get token holders by `mint`
1 parent 9f17204 commit 5508fb4

File tree

3 files changed

+71
-29
lines changed

3 files changed

+71
-29
lines changed

src/routes/token/holders/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import { Hono } from 'hono';
22
import evm from './evm.js';
3+
import svm from './svm.js';
34

45
const router = new Hono();
56

67
router.route('/evm', evm);
7-
// router.route('/svm', svm)
8+
router.route('/svm', svm);
89

910
export default router;

src/routes/token/holders/svm.ts

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,26 +5,16 @@ import { z } from 'zod';
55
import { config } from '../../../config.js';
66
import { handleUsageQueryError, makeUsageQueryJson } from '../../../handleQuery.js';
77
import { sqlQueries } from '../../../sql/index.js';
8-
import {
9-
apiUsageResponse,
10-
orderBySchemaValue,
11-
orderDirectionSchema,
12-
paginationQuery,
13-
SVM_networkIdSchema,
14-
svmAddressSchema,
15-
WSOL,
16-
} from '../../../types/zod.js';
8+
import { apiUsageResponse, paginationQuery, SVM_networkIdSchema, svmAddressSchema, WSOL } from '../../../types/zod.js';
179
import { validatorHook, withErrorResponses } from '../../../utils.js';
1810

1911
const paramSchema = z.object({
20-
contract: WSOL,
12+
mint: WSOL,
2113
});
2214

2315
const querySchema = z
2416
.object({
2517
network_id: SVM_networkIdSchema,
26-
orderBy: orderBySchemaValue.optional(),
27-
orderDirection: orderDirectionSchema.optional(),
2818
})
2919
.extend(paginationQuery.shape);
3020

@@ -58,7 +48,7 @@ const responseSchema = apiUsageResponse.extend({
5848
const openapi = describeRoute(
5949
withErrorResponses({
6050
summary: 'Token Holders',
61-
description: 'Returns token holders ranked by balance with holdings and supply percentage.',
51+
description: 'Returns token holders ranked by balance with holdings.',
6252

6353
tags: ['SVM'],
6454
security: [{ bearerAuth: [] }],
@@ -96,7 +86,7 @@ const openapi = describeRoute(
9686
const route = new Hono<{ Variables: { validatedData: z.infer<typeof querySchema> } }>();
9787

9888
route.get(
99-
'/:contract',
89+
'/:mint',
10090
openapi,
10191
validator('param', paramSchema, validatorHook),
10292
validator('query', querySchema, validatorHook),
Lines changed: 65 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,67 @@
1+
WITH filtered_balances AS
2+
(
3+
SELECT
4+
max(block_num) AS block_num,
5+
max(timestamp) AS timestamp,
6+
any(program_id) AS program_id,
7+
account,
8+
argMax(amount, b.timestamp) AS amount,
9+
mint,
10+
any(decimals) AS decimals
11+
FROM balances AS b
12+
WHERE
13+
mint = {mint:String}
14+
AND account IN (
15+
SELECT DISTINCT account
16+
FROM balances
17+
WHERE mint = {mint:String}
18+
ORDER BY amount DESC
19+
LIMIT {limit:UInt64}
20+
)
21+
GROUP BY mint, account
22+
ORDER BY amount DESC
23+
LIMIT {limit:UInt64}
24+
OFFSET {offset:UInt64}
25+
),
26+
owners AS
27+
(
28+
SELECT
29+
account,
30+
owner
31+
FROM owner_state_latest AS o
32+
WHERE account IN (SELECT account FROM filtered_balances)
33+
),
34+
metadata AS
35+
(
36+
SELECT
37+
mint,
38+
if(empty(name), NULL, name) AS name,
39+
if(empty(symbol), NULL, symbol) AS symbol,
40+
if(empty(uri), NULL, uri) AS uri
41+
FROM metadata_view
42+
WHERE metadata IN (
43+
SELECT metadata
44+
FROM metadata_mint_state_latest
45+
WHERE mint IN (SELECT mint FROM filtered_balances)
46+
GROUP BY metadata
47+
)
48+
)
149
SELECT
2-
block_num,
3-
timestamp as last_balance_update,
4-
toString(owner) AS owner,
5-
amount,
6-
toString(b.amount / pow(10, decimals)) as value,
50+
b.timestamp AS last_update,
51+
block_num AS last_update_block_num,
52+
toUnixTimestamp(b.timestamp) AS last_update_timestamp,
53+
toString(program_id) AS program_id,
54+
toString(owner) AS owner,
55+
toString(account) AS token_account,
56+
toString(mint) AS mint,
57+
toString(b.amount) AS amount,
58+
b.amount / pow(10, decimals) AS value,
759
decimals,
8-
'TO IMPLEMENT' as symbol,
9-
{network_id: String} as network_id
10-
FROM balances_by_mint AS b
11-
FINAL
12-
WHERE
13-
mint = {contract: String} AND amount > 0
14-
ORDER BY value DESC
15-
LIMIT {limit:UInt64}
16-
OFFSET {offset:UInt64}
60+
name,
61+
symbol,
62+
uri,
63+
{network_id:String} AS network_id
64+
FROM filtered_balances AS b
65+
LEFT JOIN metadata USING mint
66+
LEFT JOIN owners USING account
67+
ORDER BY value DESC

0 commit comments

Comments
 (0)