Skip to content

Commit 80897c2

Browse files
/tvm/tokens endpoint (#286)
* add /tvm/tokens endpoint * changeset
1 parent 3ce3552 commit 80897c2

File tree

4 files changed

+55
-44
lines changed

4 files changed

+55
-44
lines changed

.changeset/whole-games-begin.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"token-api": minor
3+
---
4+
5+
Added /tvm/tokens metadata endpoint

src/routes/v1/tvm/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import dexes from './dexes/index.js';
44
// import holders from './holders/index.js';
55
import pools from './pools/index.js';
66
import swaps from './swaps/index.js';
7-
// import tokens from './tokens/index.js';
7+
import tokens from './tokens/index.js';
88
import transfers from './transfers/index.js';
99

1010
const router = new Hono();
@@ -14,7 +14,7 @@ router.route('/dexes', dexes);
1414
// router.route('/holders', holders);
1515
router.route('/pools', pools);
1616
router.route('/swaps', swaps);
17-
// router.route('/tokens', tokens);
17+
router.route('/tokens', tokens);
1818
router.route('/transfers', transfers);
1919

2020
export default router;

src/routes/v1/tvm/tokens/tvm.ts

Lines changed: 17 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -3,61 +3,45 @@ import { describeRoute, resolver, validator } from 'hono-openapi';
33
import { z } from 'zod';
44
import { config } from '../../../../config.js';
55
import { handleUsageQueryError, makeUsageQueryJson } from '../../../../handleQuery.js';
6-
import { injectIcons } from '../../../../inject/icon.js';
7-
import { injectSymbol } from '../../../../inject/symbol.js';
86
import { sqlQueries } from '../../../../sql/index.js';
97
import {
108
apiUsageResponseSchema,
119
createQuerySchema,
1210
dateTimeSchema,
13-
evmContractSchema,
14-
evmNetworkIdSchema,
11+
tvmContractSchema,
12+
tvmNetworkIdSchema,
1513
} from '../../../../types/zod.js';
1614
import { validatorHook, withErrorResponses } from '../../../../utils.js';
1715

1816
const querySchema = createQuerySchema({
19-
network: { schema: evmNetworkIdSchema },
20-
contract: { schema: evmContractSchema },
17+
network: { schema: tvmNetworkIdSchema },
18+
contract: { schema: tvmContractSchema },
2119
});
2220

2321
const responseSchema = apiUsageResponseSchema.extend({
2422
data: z.array(
2523
z.object({
26-
// -- block --
2724
last_update: dateTimeSchema,
2825
last_update_block_num: z.number(),
2926
last_update_timestamp: z.number(),
3027

31-
// -- contract --
32-
contract: evmContractSchema,
28+
contract: tvmContractSchema,
29+
decimals: z.number().nullable(),
3330

34-
// -- contract --
3531
name: z.string().nullable(),
3632
symbol: z.string().nullable(),
37-
decimals: z.number().nullable(),
38-
39-
// -- token --
40-
circulating_supply: z.number(),
41-
total_supply: z.number(),
42-
holders: z.number(),
43-
44-
// -- chain --
45-
network: evmNetworkIdSchema,
4633

47-
// -- icon --
48-
icon: z.object({
49-
web3icon: z.string(),
50-
}),
34+
network: z.string(),
5135
})
5236
),
5337
});
5438

5539
const openapi = describeRoute(
5640
withErrorResponses({
5741
summary: 'Token Metadata',
58-
description: 'Returns ERC-20 token metadata including supply and holder count.',
42+
description: 'Provides TVM token contract metadata.',
5943

60-
tags: ['EVM Tokens'],
44+
tags: ['TVM Tokens'],
6145
security: [{ bearerAuth: [] }],
6246
responses: {
6347
200: {
@@ -70,20 +54,14 @@ const openapi = describeRoute(
7054
value: {
7155
data: [
7256
{
73-
last_update: '2025-10-16 09:24:47',
74-
last_update_block_num: 23589316,
75-
last_update_timestamp: 1760606687,
76-
contract: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2',
77-
name: 'Wrapped Ether',
78-
symbol: 'WETH',
79-
decimals: 18,
80-
circulating_supply: 2335108.0877502915,
81-
total_supply: 2335107.8841477665,
82-
holders: 3014993,
83-
network: 'mainnet',
84-
icon: {
85-
web3icon: 'ETH',
86-
},
57+
last_update: '2025-11-05 14:57:51',
58+
last_update_block_num: 77231165,
59+
last_update_timestamp: 1762354671,
60+
contract: 'TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t',
61+
decimals: 6,
62+
name: 'Tether USD',
63+
symbol: 'USDT',
64+
network: 'tron',
8765
},
8866
],
8967
},
@@ -110,10 +88,7 @@ route.get('/', openapi, validator('query', querySchema, validatorHook), async (c
11088

11189
const response = await makeUsageQueryJson(c, [query], params, {
11290
database: dbConfig.database,
113-
clickhouse_settings: { query_cache_ttl: config.cacheDurations[1] },
11491
});
115-
injectSymbol(response, params.network, true);
116-
injectIcons(response);
11792
return handleUsageQueryError(c, response);
11893
});
11994

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
WITH filtered_contract AS (
2+
SELECT
3+
timestamp AS last_update,
4+
block_num AS last_update_block_num,
5+
log_address AS contract
6+
FROM trc20_transfer
7+
WHERE log_address = {contract:String}
8+
ORDER BY timestamp DESC
9+
LIMIT 1
10+
),
11+
metadata AS
12+
(
13+
SELECT
14+
contract,
15+
if(empty(name), NULL, name) AS name,
16+
if(empty(symbol), NULL, symbol) AS symbol,
17+
decimals
18+
FROM metadata
19+
WHERE contract = {contract:String}
20+
)
21+
SELECT
22+
last_update,
23+
last_update_block_num,
24+
toUnixTimestamp(last_update) AS last_update_timestamp,
25+
toString(fc.contract) AS contract,
26+
decimals,
27+
name,
28+
symbol,
29+
{network:String} AS network
30+
FROM filtered_contract AS fc
31+
LEFT JOIN metadata USING contract

0 commit comments

Comments
 (0)