diff --git a/index.ts b/index.ts index 4c382c3..5c45be9 100644 --- a/index.ts +++ b/index.ts @@ -142,13 +142,13 @@ function ERC20TokenAPI() { } ); - 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("/transfers"); // TODO: Redefine `block_range` params - createUsageEndpoint("/transfers/{tx_id}"); - createUsageEndpoint("/tokens"); + createUsageEndpoint("/{chain}/balance"); // TODO: Maybe separate `block_num`/`timestamp` queries with path parameters (additional response schemas) + createUsageEndpoint("/chains"); + createUsageEndpoint("/{chain}/holders"); + createUsageEndpoint("/{chain}/supply"); // TODO: Same as `balance`` + createUsageEndpoint("/{chain}/transfers"); // TODO: Redefine `block_range` params + createUsageEndpoint("/{chain}/transfers/{tx_id}"); + createUsageEndpoint("/{chain}/tokens"); app.notFound((ctx: Context) => APIErrorResponse(ctx, 404, "route_not_found", `Path not found: ${ctx.req.method} ${ctx.req.path}`)); return app; diff --git a/src/queries.ts b/src/queries.ts index 2ceff04..3b4492f 100644 --- a/src/queries.ts +++ b/src/queries.ts @@ -2,6 +2,7 @@ import { DEFAULT_SORT_BY } from "./config.js"; import { getAddress, parseLimit, parseTimestamp, formatTxid } from "./utils.js"; import type { EndpointReturnTypes, UsageEndpoints, UsageResponse, ValidUserParams } from "./types/api.js"; import { Contract } from "ethers"; +import { SupportedChains } from "./types/zod.gen.js"; export function addBlockFilter(q: any, where: any[]) { if (q.block_num) where.push(`block_num <= ${q.block_num}`); @@ -20,9 +21,26 @@ export function addBlockRangeFilter(q: any, where: any[]) { } +export function getChains() { + + + //ADD more chains if needed + let supportedChain = ['eth']; + let queries = []; + + // Use a for loop to iterate over each item + for (const chain of supportedChain) { + queries.push(`SELECT '${chain}' as chain, MAX(block_num) as block_num FROM ${chain}_erc20_token.cursors`) + } + + let query = queries.join(' UNION ALL '); + return query; +} + + export function getTotalSupply(endpoint: UsageEndpoints, query_param: any, example?: boolean) { - if (endpoint === "/supply") { + if (endpoint === "/{chain}/supply") { const q = query_param as ValidUserParams; let address; @@ -85,7 +103,7 @@ export function getTotalSupply(endpoint: UsageEndpoints, query_param: any, examp export function getContracts(endpoint: UsageEndpoints, query_param: any, example?: boolean) { - if (endpoint === "/tokens") { + if (endpoint === "/{chain}/tokens") { const q = query_param as ValidUserParams; // Params @@ -280,7 +298,7 @@ function getBalanceChanges_historical(q: any) { } export function getBalanceChanges(endpoint: UsageEndpoints, query_param: any) { - if (endpoint === "/balance") { + if (endpoint === "/{chain}/balance") { const q = query_param as ValidUserParams; let query; if (q.block_num) query = getBalanceChanges_historical(q); @@ -382,7 +400,7 @@ FROM ${table} `; export function getHolders(endpoint: UsageEndpoints, query_param: any) { - if (endpoint === "/holders") { + if (endpoint === "/{chain}/holders") { const q = query_param as ValidUserParams; let query; @@ -398,7 +416,7 @@ export function getHolders(endpoint: UsageEndpoints, query_param: any) { export function getTransfers(endpoint: UsageEndpoints, query_param: any) { - if (endpoint === "/transfers") { + if (endpoint === "/{chain}/transfers") { const q = query_param as ValidUserParams; let contract; @@ -463,10 +481,7 @@ export function getTransfers(endpoint: UsageEndpoints, query_param: any) { export function getTransfer(endpoint: UsageEndpoints, query_param: any) { - - console.log("///////////////////////////////////////////////////////", endpoint) - console.log("enpoint", endpoint) - if (endpoint === "/transfers/{tx_id}") { + if (endpoint === "/{chain}/transfers/{tx_id}") { const q = query_param as ValidUserParams; let contract; @@ -507,7 +522,3 @@ export function getTransfer(endpoint: UsageEndpoints, query_param: any) { return "" } } - -export function getChain() { - return `ETH`; -} \ No newline at end of file diff --git a/src/types/zod.gen.ts b/src/types/zod.gen.ts index 0052188..1e8af9f 100644 --- a/src/types/zod.gen.ts +++ b/src/types/zod.gen.ts @@ -87,6 +87,9 @@ export const Supply = z.object({ timestamp: z.number(), }); +export type SupportedChains = z.infer; +export const SupportedChains = z.literal("eth"); + export type Transfer = z.infer; export const Transfer = z.object({ contract: z.string(), @@ -111,29 +114,10 @@ export const Version = z.object({ commit: z.string(), }); -export type get_Usage_balance = typeof get_Usage_balance; -export const get_Usage_balance = { - method: z.literal("GET"), - path: z.literal("/balance"), - parameters: z.object({ - query: z.object({ - contract: z.union([z.string(), z.undefined()]), - account: z.string(), - block_num: z.union([z.number(), z.undefined()]), - 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 = { +export type get_Usage_chains = typeof get_Usage_chains; +export const get_Usage_chains = { method: z.literal("GET"), - path: z.literal("/head"), + path: z.literal("/chains"), parameters: z.object({ query: z.object({ limit: z.number().optional(), @@ -143,6 +127,7 @@ export const get_Usage_head = { response: z.object({ data: z.array( z.object({ + chain: SupportedChains, block_num: z.number(), }), ), @@ -158,10 +143,56 @@ 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({ + contract: z.union([z.string(), z.undefined()]), + account: z.string(), + block_num: z.union([z.number(), z.undefined()]), + limit: z.union([z.number(), z.undefined()]), + page: z.union([z.number(), z.undefined()]), + }), + path: z.object({ + chain: z.literal("eth"), + }), + }), + 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(), @@ -169,6 +200,9 @@ export const get_Usage_holders = { limit: z.union([z.number(), z.undefined()]), page: z.union([z.number(), z.undefined()]), }), + path: z.object({ + chain: z.literal("eth"), + }), }), response: z.object({ data: z.array(Holder), @@ -176,26 +210,10 @@ export const get_Usage_holders = { }), }; -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({ contract: z.string().optional(), @@ -205,6 +223,9 @@ export const get_Usage_supply = { limit: z.number().optional(), page: z.number().optional(), }), + path: z.object({ + chain: z.literal("eth"), + }), }), response: z.object({ data: z.array(Supply), @@ -215,7 +236,7 @@ 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({ contract: z.string().optional(), @@ -224,6 +245,9 @@ export const get_Usage_tokens = { limit: z.number().optional(), page: z.number().optional(), }), + path: z.object({ + chain: z.literal("eth"), + }), }), response: z.object({ data: TypeSpec_OpenAPI_Contact, @@ -234,7 +258,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({ from: z.string().optional(), @@ -244,6 +268,9 @@ export const get_Usage_transfers = { limit: z.number().optional(), page: z.number().optional(), }), + path: z.object({ + chain: z.literal("eth"), + }), }), response: z.object({ data: z.array(Transfer), @@ -254,13 +281,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/{tx_id}"), + path: z.literal("/{chain}/transfers/{tx_id}"), parameters: z.object({ query: z.object({ limit: z.number().optional(), page: z.number().optional(), }), path: z.object({ + chain: z.literal("eth"), tx_id: z.string(), }), }), @@ -270,28 +298,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, -}; - // 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/{tx_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/{tx_id}": get_Usage_transfer, }, }; export type EndpointByMethod = typeof EndpointByMethod; diff --git a/src/typespec/openapi3.tsp b/src/typespec/openapi3.tsp index 25f1e5e..074e85b 100644 --- a/src/typespec/openapi3.tsp +++ b/src/typespec/openapi3.tsp @@ -99,13 +99,20 @@ alias AmountFilter = { // This also helps preventing self-references in generated `components` for codegen to work properly. alias APIResponse = T | APIError; alias PaginationQueryParams = { - @query limit?: uint64 = 1; + @query limit?: uint64 = 100; @query page?: uint64 = 1; }; // Helper aliases for accessing underlying properties alias BlockInfo = Models.BlockInfo; + + + +enum SupportedChains { + ETH: "eth", +} + @tag("Usage") interface Usage { /** @@ -113,9 +120,10 @@ interface Usage { @returns Array of balances. */ @summary("Token balance") - @route("/balance") + @route("/{chain}/balance") @get balance( + @path chain: SupportedChains, @query contract?: BalanceChange.contract, @query account: BalanceChange.owner, ...BlockFilter, @@ -127,9 +135,10 @@ interface Usage { @returns Array of accounts. */ @summary("Token holders") - @route("/holders") + @route("/{chain}/holders") @get holders( + @path chain: SupportedChains, @query contract: BalanceChange.contract, ...BlockFilter, ...PaginationQueryParams, @@ -140,9 +149,10 @@ interface Usage { @returns Array of supplies. */ @summary("Token supply") - @route("/supply") + @route("/{chain}/supply") @get supply( + @path chain: SupportedChains, @query contract?: Supply.contract, @query symbol?: Contract.symbol, @query name?: Contract.name, @@ -155,9 +165,10 @@ interface Usage { @returns One contract. */ @summary("Token contract information") - @route("/tokens") + @route("/{chain}/tokens") @get tokens( + @path chain: SupportedChains, @query contract?: Supply.contract, @query symbol?: Contract.symbol, @query name?: Contract.name, @@ -169,9 +180,10 @@ interface Usage { @returns Array of transfers. */ @summary("Token transfers") - @route("/transfers") + @route("/{chain}/transfers") @get transfers( + @path chain: SupportedChains, @query from?: Transfer.from, @query to?: Transfer.to, @query contract?: Transfer.contract, @@ -184,9 +196,10 @@ interface Usage { @returns Array of transfers. */ @summary("Token transfer") - @route("/transfers/{tx_id}") + @route("/{chain}/transfers/{tx_id}") @get transfer( + @path chain: SupportedChains, @path tx_id: Transfer.tx_id, ...PaginationQueryParams, ): APIResponse>; @@ -196,10 +209,11 @@ interface Usage { Information about the current head block in the database. @returns Array of block information. */ - @summary("Head block information") - @route("/head") + @summary("Chains and latest block available") + @route("/chains") @get - head(...PaginationQueryParams): APIResponse>; diff --git a/src/usage.ts b/src/usage.ts index e320dd4..0de6920 100644 --- a/src/usage.ts +++ b/src/usage.ts @@ -1,6 +1,6 @@ import { makeQuery } from "./clickhouse/makeQuery.js"; import { APIErrorResponse } from "./utils.js"; -import { getBalanceChanges, getContracts, getTotalSupply, getHolders, getTransfer, getTransfers } from "./queries.js" +import { getBalanceChanges, getContracts, getTotalSupply, getHolders, getTransfer, getTransfers, getChains } from "./queries.js" import type { Context } from "hono"; import type { EndpointReturnTypes, UsageEndpoints, UsageResponse, ValidUserParams } from "./types/api.js"; @@ -19,15 +19,22 @@ export async function makeUsageQuery(ctx: Context, endpoint: UsageEndpoints, use switch (endpoint) { - case "/balance": query = getBalanceChanges(endpoint, query_params); break; - case "/supply": query = getTotalSupply(endpoint, query_params); break; - case "/transfers": query = getTransfers(endpoint, query_params); break; - case "/holders": query = getHolders(endpoint, query_params); break; - case "/head": query = `SELECT block_num FROM cursors`; break; - case "/transfers/{tx_id}": query = getTransfer(endpoint, query_params); break; - case "/tokens": query = getContracts(endpoint, query_params); break; + case "/{chain}/balance": query = getBalanceChanges(endpoint, query_params); break; + case "/{chain}/supply": query = getTotalSupply(endpoint, query_params); break; + case "/{chain}/transfers": query = getTransfers(endpoint, query_params); break; + case "/{chain}/holders": query = getHolders(endpoint, query_params); break; + case "/chains": query = getChains(); break; + case "/{chain}/transfers/{tx_id}": query = getTransfer(endpoint, query_params); break; + case "/{chain}/tokens": query = getContracts(endpoint, query_params); break; } + //choose Chain + + let finalquery + if (endpoint != '/chains') { + const q = query_params as ValidUserParams; + finalquery = `USE ${q.chain}_erc20_token; ${query}` + } let query_results; try { query_results = await makeQuery(query, { ...query_params, offset: query_params.limit * (page - 1) }); diff --git a/tsp-output/@typespec/openapi3/openapi.json b/tsp-output/@typespec/openapi3/openapi.json index 6f3de86..666f525 100644 --- a/tsp-output/@typespec/openapi3/openapi.json +++ b/tsp-output/@typespec/openapi3/openapi.json @@ -21,40 +21,15 @@ } ], "paths": { - "/balance": { + "/chains": { "get": { "tags": [ "Usage" ], - "operationId": "Usage_balance", - "summary": "Token balance", - "description": "Balances of an account.", + "operationId": "Usage_chains", + "summary": "Chains and latest block available", + "description": "Information about the current head block in the database.", "parameters": [ - { - "name": "contract", - "in": "query", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "account", - "in": "query", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "block_num", - "in": "query", - "required": false, - "schema": { - "type": "integer", - "format": "uint64" - } - }, { "name": "limit", "in": "query", @@ -62,7 +37,7 @@ "schema": { "type": "integer", "format": "uint64", - "default": 1 + "default": 100 } }, { @@ -78,7 +53,7 @@ ], "responses": { "200": { - "description": "Array of balances.", + "description": "Array of block information.", "content": { "application/json": { "schema": { @@ -91,7 +66,20 @@ "data": { "type": "array", "items": { - "$ref": "#/components/schemas/BalanceChange" + "type": "object", + "properties": { + "chain": { + "$ref": "#/components/schemas/SupportedChains" + }, + "block_num": { + "type": "integer", + "format": "uint64" + } + }, + "required": [ + "chain", + "block_num" + ] } }, "meta": { @@ -115,67 +103,79 @@ } } }, - "/head": { + "/health": { "get": { "tags": [ - "Usage" + "Monitoring" ], - "operationId": "Usage_head", - "summary": "Head block information", - "description": "Information about the current head block in the database.", - "parameters": [ - { - "name": "limit", - "in": "query", - "required": false, - "schema": { - "type": "integer", - "format": "uint64", - "default": 1 + "operationId": "Monitoring_health", + "summary": "Health check", + "description": "Checks database connection.", + "parameters": [], + "responses": { + "200": { + "description": "OK or APIError.", + "content": { + "application/json": { + "schema": { + "type": "string" + } + } } }, - { - "name": "page", - "in": "query", - "required": false, - "schema": { - "type": "integer", - "format": "uint64", - "default": 1 + "default": { + "description": "An unexpected error response.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/APIError" + } + } } } + } + } + }, + "/metrics": { + "get": { + "tags": [ + "Monitoring" ], + "operationId": "Monitoring_metrics", + "summary": "Prometheus metrics", + "description": "Prometheus metrics.", + "parameters": [], "responses": { "200": { - "description": "Array of block information.", + "description": "Metrics as text.", + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + } + } + }, + "/openapi": { + "get": { + "tags": [ + "Docs" + ], + "operationId": "Docs_openapi", + "summary": "OpenAPI JSON spec", + "description": "Reflection endpoint to return OpenAPI JSON spec. Also used by Swagger to generate the frontpage.", + "parameters": [], + "responses": { + "200": { + "description": "The OpenAPI JSON spec", "content": { "application/json": { "schema": { "type": "object", - "required": [ - "data", - "meta" - ], - "properties": { - "data": { - "type": "array", - "items": { - "type": "object", - "properties": { - "block_num": { - "type": "integer", - "format": "uint64" - } - }, - "required": [ - "block_num" - ] - } - }, - "meta": { - "$ref": "#/components/schemas/ResponseMetadata" - } - } + "additionalProperties": {} } } } @@ -193,22 +193,22 @@ } } }, - "/health": { + "/version": { "get": { "tags": [ - "Monitoring" + "Docs" ], - "operationId": "Monitoring_health", - "summary": "Health check", - "description": "Checks database connection.", + "operationId": "Docs_version", + "summary": "API version", + "description": "API version and Git short commit hash.", "parameters": [], "responses": { "200": { - "description": "OK or APIError.", + "description": "The API version and commit hash.", "content": { "application/json": { "schema": { - "type": "string" + "$ref": "#/components/schemas/Version" } } } @@ -226,18 +226,34 @@ } } }, - "/holders": { + "/{chain}/balance": { "get": { "tags": [ "Usage" ], - "operationId": "Usage_holders", - "summary": "Token holders", - "description": "List of holders of a token.", + "operationId": "Usage_balance", + "summary": "Token balance", + "description": "Balances of an account.", "parameters": [ + { + "name": "chain", + "in": "path", + "required": true, + "schema": { + "$ref": "#/components/schemas/SupportedChains" + } + }, { "name": "contract", "in": "query", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "account", + "in": "query", "required": true, "schema": { "type": "string" @@ -259,7 +275,7 @@ "schema": { "type": "integer", "format": "uint64", - "default": 1 + "default": 100 } }, { @@ -275,7 +291,7 @@ ], "responses": { "200": { - "description": "Array of accounts.", + "description": "Array of balances.", "content": { "application/json": { "schema": { @@ -288,7 +304,7 @@ "data": { "type": "array", "items": { - "$ref": "#/components/schemas/Holder" + "$ref": "#/components/schemas/BalanceChange" } }, "meta": { @@ -312,46 +328,83 @@ } } }, - "/metrics": { + "/{chain}/holders": { "get": { "tags": [ - "Monitoring" + "Usage" ], - "operationId": "Monitoring_metrics", - "summary": "Prometheus metrics", - "description": "Prometheus metrics.", - "parameters": [], - "responses": { - "200": { - "description": "Metrics as text.", - "content": { - "application/json": { - "schema": { - "type": "string" - } - } + "operationId": "Usage_holders", + "summary": "Token holders", + "description": "List of holders of a token.", + "parameters": [ + { + "name": "chain", + "in": "path", + "required": true, + "schema": { + "$ref": "#/components/schemas/SupportedChains" + } + }, + { + "name": "contract", + "in": "query", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "block_num", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "format": "uint64" + } + }, + { + "name": "limit", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "format": "uint64", + "default": 100 + } + }, + { + "name": "page", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "format": "uint64", + "default": 1 } } - } - } - }, - "/openapi": { - "get": { - "tags": [ - "Docs" ], - "operationId": "Docs_openapi", - "summary": "OpenAPI JSON spec", - "description": "Reflection endpoint to return OpenAPI JSON spec. Also used by Swagger to generate the frontpage.", - "parameters": [], "responses": { "200": { - "description": "The OpenAPI JSON spec", + "description": "Array of accounts.", "content": { "application/json": { "schema": { "type": "object", - "additionalProperties": {} + "required": [ + "data", + "meta" + ], + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Holder" + } + }, + "meta": { + "$ref": "#/components/schemas/ResponseMetadata" + } + } } } } @@ -369,7 +422,7 @@ } } }, - "/supply": { + "/{chain}/supply": { "get": { "tags": [ "Usage" @@ -378,6 +431,14 @@ "summary": "Token supply", "description": "Total supply for a token.", "parameters": [ + { + "name": "chain", + "in": "path", + "required": true, + "schema": { + "$ref": "#/components/schemas/SupportedChains" + } + }, { "name": "contract", "in": "query", @@ -418,7 +479,7 @@ "schema": { "type": "integer", "format": "uint64", - "default": 1 + "default": 100 } }, { @@ -471,7 +532,7 @@ } } }, - "/tokens": { + "/{chain}/tokens": { "get": { "tags": [ "Usage" @@ -480,6 +541,14 @@ "summary": "Token contract information", "description": "get Token Contract information.", "parameters": [ + { + "name": "chain", + "in": "path", + "required": true, + "schema": { + "$ref": "#/components/schemas/SupportedChains" + } + }, { "name": "contract", "in": "query", @@ -511,7 +580,7 @@ "schema": { "type": "integer", "format": "uint64", - "default": 1 + "default": 100 } }, { @@ -561,7 +630,7 @@ } } }, - "/transfers": { + "/{chain}/transfers": { "get": { "tags": [ "Usage" @@ -570,6 +639,14 @@ "summary": "Token transfers", "description": "All transfers related to a token.", "parameters": [ + { + "name": "chain", + "in": "path", + "required": true, + "schema": { + "$ref": "#/components/schemas/SupportedChains" + } + }, { "name": "from", "in": "query", @@ -615,7 +692,7 @@ "schema": { "type": "integer", "format": "uint64", - "default": 1 + "default": 100 } }, { @@ -668,7 +745,7 @@ } } }, - "/transfers/{tx_id}": { + "/{chain}/transfers/{tx_id}": { "get": { "tags": [ "Usage" @@ -677,6 +754,14 @@ "summary": "Token transfer", "description": "Specific transfer related to a token.", "parameters": [ + { + "name": "chain", + "in": "path", + "required": true, + "schema": { + "$ref": "#/components/schemas/SupportedChains" + } + }, { "name": "tx_id", "in": "path", @@ -692,7 +777,7 @@ "schema": { "type": "integer", "format": "uint64", - "default": 1 + "default": 100 } }, { @@ -744,39 +829,6 @@ } } } - }, - "/version": { - "get": { - "tags": [ - "Docs" - ], - "operationId": "Docs_version", - "summary": "API version", - "description": "API version and Git short commit hash.", - "parameters": [], - "responses": { - "200": { - "description": "The API version and commit hash.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Version" - } - } - } - }, - "default": { - "description": "An unexpected error response.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/APIError" - } - } - } - } - } - } } }, "components": { @@ -1026,6 +1078,12 @@ } } }, + "SupportedChains": { + "type": "string", + "enum": [ + "eth" + ] + }, "Transfer": { "type": "object", "required": [