Skip to content

Commit

Permalink
[ECO-2207] Incorporate indexer API key (#265)
Browse files Browse the repository at this point in the history
Co-authored-by: matt <[email protected]>
  • Loading branch information
CRBl69 and matt authored Sep 29, 2024
1 parent 545285e commit 0fd9bb9
Show file tree
Hide file tree
Showing 32 changed files with 250 additions and 245 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"restart": "pnpm --prefix src/typescript run restart",
"start": "pnpm --prefix src/typescript run start",
"test": "pnpm --prefix src/typescript run test",
"test:debug": "pnpm --prefix src/typescript run test:debug",
"test:verbose": "pnpm --prefix src/typescript run test:verbose",
"up": "pnpm --prefix src/typescript run up"
}
Expand Down
6 changes: 4 additions & 2 deletions src/docker/frontend/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ ARG HASH_SEED \
NEXT_PUBLIC_REWARDS_MODULE_ADDRESS \
NEXT_PUBLIC_BROKER_URL \
REVALIDATION_TIME \
EMOJICOIN_INDEXER_URL
EMOJICOIN_INDEXER_URL \
EMOJICOIN_INDEXER_API_KEY
ENV HASH_SEED=$HASH_SEED \
NEXT_PUBLIC_APTOS_NETWORK=$NEXT_PUBLIC_APTOS_NETWORK \
NEXT_PUBLIC_INTEGRATOR_ADDRESS=$NEXT_PUBLIC_INTEGRATOR_ADDRESS \
Expand All @@ -29,7 +30,8 @@ ENV HASH_SEED=$HASH_SEED \
NEXT_PUBLIC_REWARDS_MODULE_ADDRESS=$NEXT_PUBLIC_REWARDS_MODULE_ADDRESS \
NEXT_PUBLIC_BROKER_URL=$NEXT_PUBLIC_BROKER_URL \
REVALIDATION_TIME=$REVALIDATION_TIME \
EMOJICOIN_INDEXER_URL=$EMOJICOIN_INDEXER_URL
EMOJICOIN_INDEXER_URL=$EMOJICOIN_INDEXER_URL \
EMOJICOIN_INDEXER_API_KEY=${EMOJICOIN_INDEXER_API_KEY}

RUN ["bash", "-c", "pnpm install && pnpm run build"]

Expand Down
50 changes: 0 additions & 50 deletions src/typescript/.env.ci

This file was deleted.

3 changes: 1 addition & 2 deletions src/typescript/ci.env
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ NEXT_PUBLIC_REWARDS_MODULE_ADDRESS="0xf000d910b99722d201c6cf88eb7d1112b43475b976
NEXT_PUBLIC_INTEGRATOR_ADDRESS="0xf000d910b99722d201c6cf88eb7d1112b43475b9765b118f289b5d65d919000d"
NEXT_PUBLIC_INTEGRATOR_FEE_RATE_BPS="100"
NEXT_PUBLIC_IS_ALLOWLIST_ENABLED="false"
INDEXER_URL="http://localhost:3000"
EMOJICOIN_INDEXER_URL="http://localhost:3000"
REVALIDATION_TIME="1"
HASH_SEED="some random string that is not public"
START_LOCAL_NODE_FOR_TEST="true"
PUBLISHER_PRIVATE_KEY="eaa964d1353b075ac63b0c5a0c1e92aa93355be1402f6077581e37e2a846105e"
4 changes: 2 additions & 2 deletions src/typescript/example.env
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ NEXT_PUBLIC_LINKS='{
EMOJICOIN_INDEXER_URL="http://localhost:3000"

# An optional API key to access the indexer.
# If set, all requests to the indexer will be made with the header "X-Api-Key: $INDEXER_API_KEY".
INDEXER_API_KEY=""
# If set, all requests to the indexer will be made with the header "X-Api-Key: $EMOJICOIN_INDEXER_API_KEY".
EMOJICOIN_INDEXER_API_KEY=""

# A Next.js setting to determine the query revalidation length, in seconds.
REVALIDATION_TIME="1"
Expand Down
1 change: 1 addition & 0 deletions src/typescript/frontend/.eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ module.exports = {
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended",
"plugin:react/recommended",
"prettier",
],
globals: {
JSX: true,
Expand Down
4 changes: 2 additions & 2 deletions src/typescript/frontend/src/app/pools/api/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export async function GET(request: Request) {
sortBy,
provider,
searchEmojis,
limit: MARKETS_PER_PAGE,
pageSize: MARKETS_PER_PAGE,
});
return new Response(stringifyJSON(data));
} else {
Expand All @@ -40,7 +40,7 @@ export async function GET(request: Request) {
orderBy: toOrderBy(orderBy),
sortBy,
searchEmojis,
limit: MARKETS_PER_PAGE,
pageSize: MARKETS_PER_PAGE,
});
return new Response(stringifyJSON(data));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,6 @@ export const Chart = async (props: ChartContainerProps) => {
}
const period = ResolutionStringToPeriod[resolution.toString()];
const marketEmojis = getEmojisInString(symbolInfo.ticker);
console.debug("Subscribing to emojis:", marketEmojis);
subscribeToPeriod({
marketEmojis,
period,
Expand Down
5 changes: 3 additions & 2 deletions src/typescript/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,9 @@
"prune": "../docker/utils/prune.sh --reset-localnet --yes",
"restart": "pnpm run down && pnpm run up",
"start": "dotenv -e .env.local -e .env -- turbo run start",
"test": "dotenv -e ci.env -e ../docker/example.local.env -e ../docker/.env -- turbo run test --force",
"test:verbose": "dotenv -e ci.env -e ../docker/example.local.env -e ../docker/.env -v VERBOSE_TEST_LOGS=true -- turbo run test:verbose --force",
"test": "pnpm run load-env -- dotenv -e ci.env -e ../docker/example.local.env -e ../docker/.env -- turbo run test --no-cache --force",
"test:debug": "dotenv -v FETCH_DEBUG=true -- pnpm run test",
"test:verbose": "pnpm run load-env -- dotenv -e ci.env -e ../docker/example.local.env -e ../docker/.env -v VERBOSE_TEST_LOGS=true -- turbo run test:verbose --force",
"up": "docker compose -f ../docker/compose.local.yaml up -d"
},
"version": "0.0.0",
Expand Down
2 changes: 1 addition & 1 deletion src/typescript/sdk/.eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ module.exports = {
es2021: true,
node: true,
},
ignorePatterns: ["dist/**", "node_modules/**", ".eslintrc.js", "mock-data.ts"],
ignorePatterns: ["dist/**", "node_modules/**", ".eslintrc.js"],
extends: ["airbnb-base", "airbnb-typescript/base", "prettier"],
parser: "@typescript-eslint/parser",
parserOptions: {
Expand Down
6 changes: 3 additions & 3 deletions src/typescript/sdk/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,9 @@
"pre-commit": "pnpm run pre-commit:install && pnpm run pre-commit:run",
"pre-commit:install": "pre-commit install -c ../../../cfg/pre-commit-config.yaml",
"pre-commit:run": "pre-commit run --all-files -c ../../../cfg/pre-commit-config.yaml",
"test": "dotenv -e ../env.ci -e ../../docker/example.local.env -e ../../docker/.env -- pnpm jest",
"test:debug": "dotenv -e ../env.ci -e ../../docker/example.local.env -e ../../docker/.env -v FETCH_DEBUG=true -- pnpm jest",
"test:verbose": "dotenv -e ../env.ci -e ../../docker/example.local.env -e ../../docker/.env -v VERBOSE_TEST_LOGS=true -- pnpm jest",
"test": "dotenv -e ../env.ci -e ../../docker/example.local.env -e ../../docker/.env -- pnpm jest --conditions=react-server",
"test:debug": "dotenv -e ../env.ci -e ../../docker/example.local.env -e ../../docker/.env -v FETCH_DEBUG=true -- pnpm jest --conditions=react-server",
"test:verbose": "dotenv -e ../env.ci -e ../../docker/example.local.env -e ../../docker/.env -v VERBOSE_TEST_LOGS=true -- pnpm jest --conditions=react-server",
"unit-test": "dotenv -e ../env.ci -v NO_TEST_SETUP=true -- pnpm jest tests/unit"
},
"typings": "dist/src/index.d.ts",
Expand Down
29 changes: 17 additions & 12 deletions src/typescript/sdk/src/indexer-v2/queries/app/home.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { LIMIT, ORDER_BY } from "../../../queries/const";
import { SortMarketsBy, type MarketStateQueryArgs } from "../../types/common";
import { TableName } from "../../types/json-types";
import { postgrest, toQueryArray } from "../client";
import { getLatestProcessedVersionByTable, queryHelper } from "../utils";
import { getLatestProcessedEmojicoinVersion, queryHelper } from "../utils";
import { DatabaseTypeConverter } from "../../types";
import { RegistryView } from "../../../emojicoin_dot_fun/emojicoin-dot-fun";
import { getAptosClient } from "../../../utils/aptos-client";
Expand Down Expand Up @@ -43,9 +43,11 @@ export const fetchMarkets = queryHelper(

// The featured market is simply the current highest daily volume market.
export const fetchFeaturedMarket = async () =>
fetchMarkets({ page: 1, pageSize: 1, sortBy: SortMarketsBy.DailyVolume }).then((markets) =>
markets.at(0)
);
fetchMarkets({
page: 1,
pageSize: 1,
sortBy: SortMarketsBy.DailyVolume,
}).then((markets) => (markets ?? []).at(0));

/**
* Retrieves the number of markets by querying the view function in the registry contract on-chain.
Expand All @@ -56,7 +58,13 @@ export const fetchFeaturedMarket = async () =>
*/
export const fetchNumRegisteredMarkets = async () => {
const { aptos } = getAptosClient();
const latestVersion = await getLatestProcessedVersionByTable();
let latestVersion: bigint;
try {
latestVersion = await getLatestProcessedEmojicoinVersion();
} catch (e) {
console.error("Couldn't get the latest processed version.");
return 0;
}
try {
const numRegisteredMarkets = await RegistryView.view({
aptos,
Expand All @@ -70,12 +78,9 @@ export const fetchNumRegisteredMarkets = async () => {
// and we should just find the count ourselves. Since this is a costly operation, this should
// primarily be a fallback to avoid defaulting to "0" in the UI. In practice, we should never
// get rate-limited, since we'll cache the query results and add a proper revalidation time.
return (
postgrest
.from(TableName.MarketState)
// `count: "exact", head: true` retrieves the count of all rows in the table, but no rows.
.select("", { count: "exact", head: true })
.then((r) => r.count ?? 0)
);
return postgrest
.from(TableName.MarketState)
.select("", { count: "exact", head: true })
.then((r) => r.count ?? 0);
}
};
30 changes: 20 additions & 10 deletions src/typescript/sdk/src/indexer-v2/queries/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,19 +39,10 @@ const fetchPatch: typeof fetch = async (input, init) => {
return new Response(json, response);
};

// Custom client that enforces a proper table name when calling `from`.
class CustomClient extends PostgrestClient {
from = (table: TableName) => super.from(table);
}

export const postgrest = new CustomClient(EMOJICOIN_INDEXER_URL, {
fetch: fetchPatch,
});

/**
* Converts an input array of any type to a proper query param for the `postgrest` client.
*
* @param s an array of values
* @params an array of values
* @returns the properly formatted string input for the query input param
* @example
* ```typescript
Expand All @@ -61,3 +52,22 @@ export const postgrest = new CustomClient(EMOJICOIN_INDEXER_URL, {
* ```
*/
export const toQueryArray = <T>(s: T[]) => `{${s.join(",")}}`;

// Custom client that enforces a proper table name when calling `from`.
class CustomClient extends PostgrestClient {
from = (table: TableName) => super.from(table);
}

const localIndexer =
EMOJICOIN_INDEXER_URL.includes("localhost") ||
EMOJICOIN_INDEXER_URL.includes("host.docker.internal");

const authHeaders =
!localIndexer && process.env.EMOJICOIN_INDEXER_API_KEY
? { "x-api-key": `${process.env.EMOJICOIN_INDEXER_API_KEY}`, Accept: "application-json" }
: undefined;

export const postgrest = new CustomClient(EMOJICOIN_INDEXER_URL, {
fetch: fetchPatch,
headers: authHeaders,
});
8 changes: 6 additions & 2 deletions src/typescript/sdk/src/indexer-v2/queries/test/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,16 @@ const selectLiquidityEvents = ({
.eq("market_id", marketID)
.eq("market_nonce", marketNonce);

// prettier-ignore
const selectMarket1MPeriodsInLastDay = ({ marketID }: { marketID: AnyNumberString }) =>
postgrest.from(TableName.Market1MPeriodsInLastDay).select("*").eq("market_id", marketID);
postgrest
.from(TableName.Market1MPeriodsInLastDay)
.select("*")
.eq("market_id", marketID);

// prettier-ignore
const selectMarketDailyVolume = ({ marketID }: { marketID: AnyNumberString }) =>
postgrest
postgrest
.from(TableName.MarketDailyVolume)
.select("daily_volume")
.eq("market_id", marketID);
Expand Down
22 changes: 15 additions & 7 deletions src/typescript/sdk/src/indexer-v2/queries/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,20 +39,23 @@ const extractRows = <T>(res: PostgrestSingleResponse<Array<T>>) => res.data ?? (
// NOTE: If we ever add another processor type to the indexer processor stack, this will need to be
// updated, because it is assumed here that there is a single row returned. Multiple processors
// would mean there would be multiple rows.
export const getLatestProcessedVersionByTable = async () =>
export const getLatestProcessedEmojicoinVersion = async () =>
postgrest
.from(TableName.ProcessorStatus)
.select("last_success_version")
.maybeSingle()
.limit(1)
.single()
.then((r) => {
const rowWithVersion = extractRow(r);
if (!rowWithVersion) {
console.error(r);
throw new Error("No processor status row found.");
}
if (!("last_success_version" in rowWithVersion)) {
console.warn("Couldn't find `last_success_version` in the response data.", r);
}
return BigInt(rowWithVersion.last_success_version);
});

/**
* Wait for the processed version of a table or view to be at least the given version.
*/
Expand All @@ -63,7 +66,7 @@ export const waitForEmojicoinIndexer = async (minimumVersion: AnyNumberString) =

const check = async () => {
try {
const latestVersion = await getLatestProcessedVersionByTable();
const latestVersion = await getLatestProcessedEmojicoinVersion();
if (latestVersion >= BigInt(minimumVersion)) {
resolve();
} else if (i > maxTries) {
Expand Down Expand Up @@ -107,9 +110,14 @@ export function queryHelper<
await waitForEmojicoinIndexer(minimumVersion);
}

const res = await innerQuery;
const rows = extractRows<Row>(res);
return rows.map((row) => convert(row));
try {
const res = await innerQuery;
const rows = extractRows<Row>(res);
return rows.map(convert);
} catch (e) {
console.error(e);
return [];
}
};

return query;
Expand Down
7 changes: 6 additions & 1 deletion src/typescript/sdk/src/server-env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,16 @@ if (typeof process.env.EMOJICOIN_INDEXER_URL === "undefined") {
throw new Error("The indexer processor url must be defined.");
} else {
try {
const res = new URL(process.env.EMOJICOIN_INDEXER_URL);
const urlString = process.env.EMOJICOIN_INDEXER_URL;
const res = new URL(urlString);
if (urlString.endsWith("/")) {
throw new Error("Do not end the EMOJICOIN_INDEXER_URL with a trailing slash.");
}
if (typeof res.toString() !== "string") {
throw new Error(`Invalid URL: ${process.env.EMOJICOIN_INDEXER_URL}`);
}
} catch (e) {
console.error(e);
throw new Error(`Invalid URL: ${process.env.EMOJICOIN_INDEXER_URL}`);
}
}
Expand Down
6 changes: 3 additions & 3 deletions src/typescript/sdk/tests/e2e/emoji-data.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@ import {
import { getPublishHelpers } from "../utils";
import { STRUCT_STRINGS, SYMBOL_DATA, normalizeHex } from "../../src";
import EmojiJSONData from "../../src/emoji_data/symbol-emojis.json";
import { getPublishTransactionFromIndexer } from "../utils/get-publish-txn-from-indexer";

jest.setTimeout(10000);

describe("verification of typescript emoji JSON data", () => {
const { aptos, publishPackageResult } = getPublishHelpers();
const { aptos } = getPublishHelpers();

it("checks the on-chain changes in the publish txn to verify the JSON data", async () => {
const publishResult = publishPackageResult;
const transactionHash = publishResult.transaction_hash;
const { transaction_hash: transactionHash } = await getPublishTransactionFromIndexer();
const res = (await aptos.waitForTransaction({ transactionHash })) as UserTransactionResponse;
const { changes } = res;

Expand Down
Loading

0 comments on commit 0fd9bb9

Please sign in to comment.