Skip to content
This repository was archived by the owner on Mar 14, 2025. It is now read-only.

Commit 67b61ee

Browse files
committed
feat: status endpoint
1 parent 99038e5 commit 67b61ee

File tree

4 files changed

+61
-1
lines changed

4 files changed

+61
-1
lines changed

api/src/api/init.ts

+2
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,14 @@ import { EtchingRoutes } from './routes/etchings';
77
import { AddressRoutes } from './routes/addresses';
88
import { TransactionRoutes } from './routes/transactions';
99
import { BlockRoutes } from './routes/blocks';
10+
import { StatusRoutes } from './routes/status';
1011

1112
export const Api: FastifyPluginAsync<
1213
Record<never, never>,
1314
Server,
1415
TypeBoxTypeProvider
1516
> = async fastify => {
17+
await fastify.register(StatusRoutes);
1618
await fastify.register(EtchingRoutes);
1719
await fastify.register(AddressRoutes);
1820
await fastify.register(TransactionRoutes);

api/src/api/routes/status.ts

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import { TypeBoxTypeProvider } from '@fastify/type-provider-typebox';
2+
import { FastifyPluginCallback } from 'fastify';
3+
import { Server } from 'http';
4+
import { ApiStatusResponse } from '../schemas';
5+
import { SERVER_VERSION } from '@hirosystems/api-toolkit';
6+
import { handleCache } from '../util/cache';
7+
8+
export const StatusRoutes: FastifyPluginCallback<
9+
Record<never, never>,
10+
Server,
11+
TypeBoxTypeProvider
12+
> = (fastify, options, done) => {
13+
fastify.addHook('preHandler', handleCache);
14+
15+
fastify.get(
16+
'/',
17+
{
18+
schema: {
19+
operationId: 'getApiStatus',
20+
summary: 'API Status',
21+
description: 'Displays the status of the API',
22+
tags: ['Status'],
23+
response: {
24+
200: ApiStatusResponse,
25+
},
26+
},
27+
},
28+
async (request, reply) => {
29+
const result = await fastify.db.sqlTransaction(async sql => {
30+
const block_height = await fastify.db.getChainTipBlockHeight();
31+
return {
32+
server_version: `runes-api ${SERVER_VERSION.tag} (${SERVER_VERSION.branch}:${SERVER_VERSION.commit})`,
33+
status: 'ready',
34+
block_height: block_height ? parseInt(block_height) : undefined,
35+
};
36+
});
37+
await reply.send(result);
38+
}
39+
);
40+
41+
done();
42+
};

api/src/api/schemas.ts

+9
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,15 @@ export type Block = Static<typeof BlockSchema>;
107107
// Responses
108108
// ==========================
109109

110+
export const ApiStatusResponse = Type.Object(
111+
{
112+
server_version: Type.String({ examples: [''] }),
113+
status: Type.String(),
114+
block_height: Optional(Type.Integer()),
115+
},
116+
{ title: 'Api Status Response' }
117+
);
118+
110119
export const EtchingResponseSchema = Type.Object({
111120
id: Type.String({ examples: ['840000:1'] }),
112121
name: Type.String({ examples: ['ZZZZZFEHUZZZZZ'] }),

api/src/pg/pg-store.ts

+8-1
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,13 @@ export class PgStore extends BasePgStore {
8282
return result[0]?.etag;
8383
}
8484

85+
async getChainTipBlockHeight(): Promise<string | undefined> {
86+
const result = await this.sql<{ block_height: string }[]>`
87+
SELECT block_height FROM ledger ORDER BY block_height DESC LIMIT 1
88+
`;
89+
return result[0]?.block_height;
90+
}
91+
8592
async getEtching(id: Rune): Promise<DbRuneWithChainTip | undefined> {
8693
const result = await this.sql<DbRuneWithChainTip[]>`
8794
SELECT *, (SELECT MAX(block_height) FROM ledger) AS chain_tip
@@ -95,7 +102,7 @@ export class PgStore extends BasePgStore {
95102
const results = await this.sql<DbCountedQueryResult<DbRuneWithChainTip>[]>`
96103
WITH
97104
rune_count AS (SELECT COALESCE(MAX(number), 0) + 1 AS total FROM runes),
98-
max AS (SELECT MAX(block_height) AS max FROM ledger)
105+
max AS (SELECT MAX(block_height) AS chain_tip FROM ledger)
99106
SELECT *, (SELECT total FROM rune_count), (SELECT chain_tip FROM max)
100107
FROM runes
101108
ORDER BY block_height DESC, tx_index DESC

0 commit comments

Comments
 (0)