Skip to content

Commit

Permalink
Add WAX data support
Browse files Browse the repository at this point in the history
WAX blockchain data is stored in a different database. The API will
assume one exists for EOS and one for WAX. The `{chain}` path parameter
is added to select between the two. `/head` is renamed `/chains` and
returns information on supported Antelope chains for which data is
available.
  • Loading branch information
0237h committed Jun 27, 2024
1 parent 5d5cf46 commit a5bbb10
Show file tree
Hide file tree
Showing 7 changed files with 366 additions and 265 deletions.
16 changes: 8 additions & 8 deletions index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ function AntelopeTokenAPI() {
const createUsageEndpoint = (endpoint: UsageEndpoints) => app.get(
// Hono using different syntax than OpenAPI for path parameters
// `/{path_param}` (OpenAPI) VS `/:path_param` (Hono)
endpoint.replace(/{([^}]+)}/, ":$1"),
endpoint.replace(/{([^}]+)}/g, ":$1"),
async (ctx: Context) => {
const result = EndpointByMethod["get"][endpoint].parameters.safeParse({
query: ctx.req.query(),
Expand All @@ -92,13 +92,13 @@ function AntelopeTokenAPI() {
}
);

createUsageEndpoint("/balance"); // TODO: Maybe separate `block_num`/`timestamp` queries with path parameters (additional response schemas)
createUsageEndpoint("/head");
createUsageEndpoint("/holders");
createUsageEndpoint("/supply"); // TODO: Same as `balance``
createUsageEndpoint("/tokens");
createUsageEndpoint("/transfers"); // TODO: Redefine `block_range` params
createUsageEndpoint("/transfers/{trx_id}");
createUsageEndpoint("/{chain}/balance");
createUsageEndpoint("/chains");
createUsageEndpoint("/{chain}/holders");
createUsageEndpoint("/{chain}/supply");
createUsageEndpoint("/{chain}/tokens");
createUsageEndpoint("/{chain}/transfers");
createUsageEndpoint("/{chain}/transfers/{trx_id}");

app.notFound((ctx: Context) => APIErrorResponse(ctx, 404, "route_not_found", `Path not found: ${ctx.req.method} ${ctx.req.path}`));

Expand Down
1 change: 0 additions & 1 deletion src/clickhouse/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { ping } from "./ping.js";
import { APP_NAME, config } from "../config.js";

// TODO: Check how to abort previous queries if haven't returned yet
// TODO: Make client connect to all DB instances
const client = createClient({
...config,
clickhouse_settings: {
Expand Down
4 changes: 2 additions & 2 deletions src/types/api.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ZodArray, ZodBigInt, ZodBoolean, ZodDate, ZodDefault, ZodNumber, ZodOptional, ZodType, ZodTypeAny, ZodUndefined, ZodUnion, z } from "zod";
import { ZodArray, ZodBigInt, ZodBoolean, ZodDate, ZodDefault, ZodLiteral, ZodNumber, ZodOptional, ZodType, ZodTypeAny, ZodUndefined, ZodUnion, z } from "zod";

import { EndpointByMethod, type GetEndpoints } from './zod.gen.js';
import { config } from "../config.js";
Expand All @@ -25,7 +25,7 @@ export function fixEndpointParametersCoercion() {
if (EndpointByMethod["get"][endpoint as UsageEndpoints].parameters.shape) {
Object.values(EndpointByMethod["get"][endpoint as UsageEndpoints].parameters.shape).map(p => p.shape).forEach(
// `p` can be query or path parameters
(p) => Object.keys(p).forEach(
(p) => Object.keys(p).filter(k => k !== "chain").forEach(
(key, _) => {
let zod_type = p[key] as ZodTypeAny;
let underlying_zod_type: ZodTypeAny;
Expand Down
137 changes: 78 additions & 59 deletions src/types/zod.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,9 @@ export const Supply = z.object({
supply_delta: z.number(),
});

export type SupportedChains = z.infer<typeof SupportedChains>;
export const SupportedChains = z.union([z.literal("eos"), z.literal("wax")]);

export type Transfer = z.infer<typeof Transfer>;
export const Transfer = z.object({
trx_id: z.string(),
Expand All @@ -112,30 +115,10 @@ export const Version = z.object({
commit: z.string(),
});

export type get_Usage_balance = typeof get_Usage_balance;
export const get_Usage_balance = {
export type get_Usage_chains = typeof get_Usage_chains;
export const get_Usage_chains = {
method: z.literal("GET"),
path: z.literal("/balance"),
parameters: z.object({
query: z.object({
block_num: z.union([z.number(), z.undefined()]),
contract: z.union([z.string(), z.undefined()]),
symcode: z.union([z.string(), z.undefined()]),
account: z.string(),
limit: z.union([z.number(), z.undefined()]),
page: z.union([z.number(), z.undefined()]),
}),
}),
response: z.object({
data: z.array(BalanceChange),
meta: ResponseMetadata,
}),
};

export type get_Usage_head = typeof get_Usage_head;
export const get_Usage_head = {
method: z.literal("GET"),
path: z.literal("/head"),
path: z.literal("/chains"),
parameters: z.object({
query: z.object({
limit: z.number().optional(),
Expand All @@ -160,44 +143,78 @@ export const get_Monitoring_health = {
response: z.string(),
};

export type get_Monitoring_metrics = typeof get_Monitoring_metrics;
export const get_Monitoring_metrics = {
method: z.literal("GET"),
path: z.literal("/metrics"),
parameters: z.never(),
response: z.string(),
};

export type get_Docs_openapi = typeof get_Docs_openapi;
export const get_Docs_openapi = {
method: z.literal("GET"),
path: z.literal("/openapi"),
parameters: z.never(),
response: z.unknown(),
};

export type get_Docs_version = typeof get_Docs_version;
export const get_Docs_version = {
method: z.literal("GET"),
path: z.literal("/version"),
parameters: z.never(),
response: Version,
};

export type get_Usage_balance = typeof get_Usage_balance;
export const get_Usage_balance = {
method: z.literal("GET"),
path: z.literal("/{chain}/balance"),
parameters: z.object({
query: z.object({
block_num: z.union([z.number(), z.undefined()]),
contract: z.union([z.string(), z.undefined()]),
symcode: z.union([z.string(), z.undefined()]),
account: z.string(),
limit: z.union([z.number(), z.undefined()]),
page: z.union([z.number(), z.undefined()]),
}),
path: z.object({
chain: z.union([z.literal("eos"), z.literal("wax")]),
}),
}),
response: z.object({
data: z.array(BalanceChange),
meta: ResponseMetadata,
}),
};

export type get_Usage_holders = typeof get_Usage_holders;
export const get_Usage_holders = {
method: z.literal("GET"),
path: z.literal("/holders"),
path: z.literal("/{chain}/holders"),
parameters: z.object({
query: z.object({
contract: z.string(),
symcode: z.string(),
limit: z.union([z.number(), z.undefined()]),
page: z.union([z.number(), z.undefined()]),
}),
path: z.object({
chain: z.union([z.literal("eos"), z.literal("wax")]),
}),
}),
response: z.object({
data: z.array(Holder),
meta: ResponseMetadata,
}),
};

export type get_Monitoring_metrics = typeof get_Monitoring_metrics;
export const get_Monitoring_metrics = {
method: z.literal("GET"),
path: z.literal("/metrics"),
parameters: z.never(),
response: z.string(),
};

export type get_Docs_openapi = typeof get_Docs_openapi;
export const get_Docs_openapi = {
method: z.literal("GET"),
path: z.literal("/openapi"),
parameters: z.never(),
response: z.unknown(),
};

export type get_Usage_supply = typeof get_Usage_supply;
export const get_Usage_supply = {
method: z.literal("GET"),
path: z.literal("/supply"),
path: z.literal("/{chain}/supply"),
parameters: z.object({
query: z.object({
block_num: z.union([z.number(), z.undefined()]),
Expand All @@ -207,6 +224,9 @@ export const get_Usage_supply = {
limit: z.union([z.number(), z.undefined()]),
page: z.union([z.number(), z.undefined()]),
}),
path: z.object({
chain: z.union([z.literal("eos"), z.literal("wax")]),
}),
}),
response: z.object({
data: z.array(Supply),
Expand All @@ -217,12 +237,15 @@ export const get_Usage_supply = {
export type get_Usage_tokens = typeof get_Usage_tokens;
export const get_Usage_tokens = {
method: z.literal("GET"),
path: z.literal("/tokens"),
path: z.literal("/{chain}/tokens"),
parameters: z.object({
query: z.object({
limit: z.number().optional(),
page: z.number().optional(),
}),
path: z.object({
chain: z.union([z.literal("eos"), z.literal("wax")]),
}),
}),
response: z.object({
data: z.array(Supply),
Expand All @@ -233,7 +256,7 @@ export const get_Usage_tokens = {
export type get_Usage_transfers = typeof get_Usage_transfers;
export const get_Usage_transfers = {
method: z.literal("GET"),
path: z.literal("/transfers"),
path: z.literal("/{chain}/transfers"),
parameters: z.object({
query: z.object({
block_range: z.array(z.number()).optional(),
Expand All @@ -244,6 +267,9 @@ export const get_Usage_transfers = {
limit: z.number().optional(),
page: z.number().optional(),
}),
path: z.object({
chain: z.union([z.literal("eos"), z.literal("wax")]),
}),
}),
response: z.object({
data: z.array(Transfer),
Expand All @@ -254,13 +280,14 @@ export const get_Usage_transfers = {
export type get_Usage_transfer = typeof get_Usage_transfer;
export const get_Usage_transfer = {
method: z.literal("GET"),
path: z.literal("/transfers/{trx_id}"),
path: z.literal("/{chain}/transfers/{trx_id}"),
parameters: z.object({
query: z.object({
limit: z.number().optional(),
page: z.number().optional(),
}),
path: z.object({
chain: z.union([z.literal("eos"), z.literal("wax")]),
trx_id: z.string(),
}),
}),
Expand All @@ -270,28 +297,20 @@ export const get_Usage_transfer = {
}),
};

export type get_Docs_version = typeof get_Docs_version;
export const get_Docs_version = {
method: z.literal("GET"),
path: z.literal("/version"),
parameters: z.never(),
response: Version,
};

// <EndpointByMethod>
export const EndpointByMethod = {
get: {
"/balance": get_Usage_balance,
"/head": get_Usage_head,
"/chains": get_Usage_chains,
"/health": get_Monitoring_health,
"/holders": get_Usage_holders,
"/metrics": get_Monitoring_metrics,
"/openapi": get_Docs_openapi,
"/supply": get_Usage_supply,
"/tokens": get_Usage_tokens,
"/transfers": get_Usage_transfers,
"/transfers/{trx_id}": get_Usage_transfer,
"/version": get_Docs_version,
"/{chain}/balance": get_Usage_balance,
"/{chain}/holders": get_Usage_holders,
"/{chain}/supply": get_Usage_supply,
"/{chain}/tokens": get_Usage_tokens,
"/{chain}/transfers": get_Usage_transfers,
"/{chain}/transfers/{trx_id}": get_Usage_transfer,
},
};
export type EndpointByMethod = typeof EndpointByMethod;
Expand Down
Loading

0 comments on commit a5bbb10

Please sign in to comment.