From f045e3a590e12ca05d31e9d18cc8e9b50adbc5fa Mon Sep 17 00:00:00 2001 From: Bogdan Crisan Date: Mon, 4 Nov 2024 13:49:46 +0100 Subject: [PATCH 1/5] Fix page number wrong on search --- .../frontend/src/app/home/HomePage.tsx | 6 +-- src/typescript/frontend/src/app/home/page.tsx | 36 +++++++++++---- src/typescript/frontend/src/app/page.tsx | 2 +- .../home/components/emoji-table/index.tsx | 2 +- .../sdk/src/indexer-v2/queries/app/home.ts | 24 +++++++--- .../sdk/src/indexer-v2/queries/utils.ts | 44 +++++++++++++++++++ .../sdk/src/indexer-v2/types/common.ts | 1 + 7 files changed, 96 insertions(+), 19 deletions(-) diff --git a/src/typescript/frontend/src/app/home/HomePage.tsx b/src/typescript/frontend/src/app/home/HomePage.tsx index 122140e2c..793752202 100644 --- a/src/typescript/frontend/src/app/home/HomePage.tsx +++ b/src/typescript/frontend/src/app/home/HomePage.tsx @@ -8,7 +8,7 @@ import { type MarketDataSortByHomePage } from "lib/queries/sorting/types"; export interface HomePageProps { featured?: DatabaseModels["market_state"]; markets: Array; - numRegisteredMarkets: number; + numMarkets: number; page: number; sortBy: MarketDataSortByHomePage; searchBytes?: string; @@ -20,7 +20,7 @@ export interface HomePageProps { export default async function HomePageComponent({ featured, markets, - numRegisteredMarkets, + numMarkets, page, sortBy, searchBytes, @@ -42,7 +42,7 @@ export default async function HomePageComponent({ e.emoji) : undefined; - const numRegisteredMarkets = await fetchNumRegisteredMarkets(); const featured = await fetchFeaturedMarket(); - const markets = await fetchMarkets({ - page, - sortBy, - orderBy, - searchEmojis, - pageSize: MARKETS_PER_PAGE, - }); + let numMarkets: number; + let markets: Awaited>['rows']; + + if (searchEmojis?.length) { + const res = await fetchMarketsWithCount({ + page, + sortBy, + orderBy, + searchEmojis, + pageSize: MARKETS_PER_PAGE, + count: true, + }); + numMarkets = res.count!; + markets = res.rows; + } else { + numMarkets = await fetchNumRegisteredMarkets(); + markets = await fetchMarkets({ + page, + sortBy, + orderBy, + searchEmojis, + pageSize: MARKETS_PER_PAGE, + }); + } + const priceFeed = await fetchPriceFeed({}); const geoblocked = await isUserGeoblocked(headers().get("x-real-ip")); @@ -35,7 +53,7 @@ export default async function Home({ searchParams }: HomePageParams) { { const { markets, page, sort, pages, searchBytes } = useMemo(() => { const { markets, page, sortBy: sort } = props; - const numMarkets = Math.max(props.numRegisteredMarkets, 1); + const numMarkets = Math.max(props.numMarkets, 1); const pages = Math.ceil(numMarkets / MARKETS_PER_PAGE); const searchBytes = props.searchBytes ?? ""; return { markets, page, sort, pages, searchBytes }; diff --git a/src/typescript/sdk/src/indexer-v2/queries/app/home.ts b/src/typescript/sdk/src/indexer-v2/queries/app/home.ts index 71df6f297..5208f2824 100644 --- a/src/typescript/sdk/src/indexer-v2/queries/app/home.ts +++ b/src/typescript/sdk/src/indexer-v2/queries/app/home.ts @@ -6,12 +6,13 @@ import { LIMIT, ORDER_BY } from "../../../queries/const"; import { SortMarketsBy, type MarketStateQueryArgs } from "../../types/common"; import { DatabaseRpc, TableName } from "../../types/json-types"; import { postgrest, toQueryArray } from "../client"; -import { getLatestProcessedEmojicoinVersion, queryHelper } from "../utils"; +import { getLatestProcessedEmojicoinVersion, queryHelper, queryHelperWithCount } from "../utils"; import { DatabaseTypeConverter } from "../../types"; import { RegistryView } from "../../../emojicoin_dot_fun/emojicoin-dot-fun"; import { getAptosClient } from "../../../utils/aptos-client"; import { toRegistryView } from "../../../types"; import { sortByWithFallback } from "../query-params"; +import { PostgrestFilterBuilder } from "@supabase/postgrest-js"; const selectMarketStates = ({ page = 1, @@ -20,10 +21,18 @@ const selectMarketStates = ({ searchEmojis, sortBy = SortMarketsBy.MarketCap, inBondingCurve, -}: MarketStateQueryArgs) => { - let query = postgrest - .from(TableName.MarketState) - .select("*") + count, +}: MarketStateQueryArgs): PostgrestFilterBuilder => { + let query: any = postgrest + .from(TableName.MarketState); + + if (count === true) { + query = query.select("*", { count: 'exact' }); + } else { + query = query.select("*"); + } + + query = query .order(sortByWithFallback(sortBy), orderBy) .range((page - 1) * pageSize, page * pageSize - 1); @@ -43,6 +52,11 @@ export const fetchMarkets = queryHelper( DatabaseTypeConverter[TableName.MarketState] ); +export const fetchMarketsWithCount = queryHelperWithCount( + selectMarketStates, + DatabaseTypeConverter[TableName.MarketState] +); + // The featured market is simply the current highest daily volume market. export const fetchFeaturedMarket = async () => fetchMarkets({ diff --git a/src/typescript/sdk/src/indexer-v2/queries/utils.ts b/src/typescript/sdk/src/indexer-v2/queries/utils.ts index 3547b6c10..59c859853 100644 --- a/src/typescript/sdk/src/indexer-v2/queries/utils.ts +++ b/src/typescript/sdk/src/indexer-v2/queries/utils.ts @@ -155,6 +155,50 @@ export function queryHelperSingle< return query; } +/** + * + * @param queryFn Takes in a query function that's used to be called after waiting for the indexer + * to reach a certain version. Then it extracts the row data and returns it. + * @param convert A function that converts the raw row data into the desired output, usually + * by converting it into a camelCased representation of the database row. + * @returns A curried function that applies the logic to the new query function. + */ +export function queryHelperWithCount< + Row extends Record, + Result extends Row[], + RelationName, + Relationships extends TableName, + QueryArgs extends Record | undefined, + OutputType, +>( + queryFn: QueryFunction, QueryArgs>, + convert: (rows: Row) => OutputType +): (args: WithConfig) => Promise<{ rows: OutputType[], count: number | null }> { + const query = async (args: WithConfig) => { + const { minimumVersion, ...queryArgs } = args; + const innerQuery = queryFn(queryArgs as QueryArgs); + + if (minimumVersion) { + await waitForEmojicoinIndexer(minimumVersion); + } + + try { + const res = await innerQuery; + const rows = extractRows(res); + if (res.error) { + console.error("[Failed row conversion]:\n"); + throw new Error(JSON.stringify(res)); + } + return { rows: rows.map(convert), count: res.count }; + } catch (e) { + console.error(e); + return { rows: [], count: null }; + } + }; + + return query; +} + /** * Strip leading zeroes from an address. * diff --git a/src/typescript/sdk/src/indexer-v2/types/common.ts b/src/typescript/sdk/src/indexer-v2/types/common.ts index 740c7ca0b..354987aad 100644 --- a/src/typescript/sdk/src/indexer-v2/types/common.ts +++ b/src/typescript/sdk/src/indexer-v2/types/common.ts @@ -19,6 +19,7 @@ export type MarketStateQueryArgs = { orderBy?: OrderBy; searchEmojis?: string[]; inBondingCurve?: boolean; + count?: boolean; }; export type PeriodicStateEventQueryArgs = { From 57a96fd9b630728b637d9781ff6c97850a3b4962 Mon Sep 17 00:00:00 2001 From: Bogdan Crisan Date: Tue, 5 Nov 2024 17:26:30 +0100 Subject: [PATCH 2/5] Fix linting issues --- src/typescript/frontend/src/app/home/page.tsx | 2 +- src/typescript/sdk/src/indexer-v2/queries/app/home.ts | 9 +++++---- src/typescript/sdk/src/indexer-v2/queries/utils.ts | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/typescript/frontend/src/app/home/page.tsx b/src/typescript/frontend/src/app/home/page.tsx index 69081d895..b34a73014 100644 --- a/src/typescript/frontend/src/app/home/page.tsx +++ b/src/typescript/frontend/src/app/home/page.tsx @@ -22,7 +22,7 @@ export default async function Home({ searchParams }: HomePageParams) { const featured = await fetchFeaturedMarket(); let numMarkets: number; - let markets: Awaited>['rows']; + let markets: Awaited>["rows"]; if (searchEmojis?.length) { const res = await fetchMarketsWithCount({ diff --git a/src/typescript/sdk/src/indexer-v2/queries/app/home.ts b/src/typescript/sdk/src/indexer-v2/queries/app/home.ts index 5208f2824..2f7a90fab 100644 --- a/src/typescript/sdk/src/indexer-v2/queries/app/home.ts +++ b/src/typescript/sdk/src/indexer-v2/queries/app/home.ts @@ -12,7 +12,7 @@ import { RegistryView } from "../../../emojicoin_dot_fun/emojicoin-dot-fun"; import { getAptosClient } from "../../../utils/aptos-client"; import { toRegistryView } from "../../../types"; import { sortByWithFallback } from "../query-params"; -import { PostgrestFilterBuilder } from "@supabase/postgrest-js"; +import { type PostgrestFilterBuilder } from "@supabase/postgrest-js"; const selectMarketStates = ({ page = 1, @@ -22,12 +22,13 @@ const selectMarketStates = ({ sortBy = SortMarketsBy.MarketCap, inBondingCurve, count, + /* eslint-disable-next-line @typescript-eslint/no-explicit-any */ }: MarketStateQueryArgs): PostgrestFilterBuilder => { - let query: any = postgrest - .from(TableName.MarketState); + /* eslint-disable-next-line @typescript-eslint/no-explicit-any */ + let query: any = postgrest.from(TableName.MarketState); if (count === true) { - query = query.select("*", { count: 'exact' }); + query = query.select("*", { count: "exact" }); } else { query = query.select("*"); } diff --git a/src/typescript/sdk/src/indexer-v2/queries/utils.ts b/src/typescript/sdk/src/indexer-v2/queries/utils.ts index 59c859853..b7e00f49e 100644 --- a/src/typescript/sdk/src/indexer-v2/queries/utils.ts +++ b/src/typescript/sdk/src/indexer-v2/queries/utils.ts @@ -173,7 +173,7 @@ export function queryHelperWithCount< >( queryFn: QueryFunction, QueryArgs>, convert: (rows: Row) => OutputType -): (args: WithConfig) => Promise<{ rows: OutputType[], count: number | null }> { +): (args: WithConfig) => Promise<{ rows: OutputType[]; count: number | null }> { const query = async (args: WithConfig) => { const { minimumVersion, ...queryArgs } = args; const innerQuery = queryFn(queryArgs as QueryArgs); From 137e05383b1cb0d1655b6269f5d7201bcbc77285 Mon Sep 17 00:00:00 2001 From: Matt <90358481+xbtmatt@users.noreply.github.com> Date: Mon, 11 Nov 2024 23:54:58 -0800 Subject: [PATCH 3/5] Have `queryHelper` call `queryHelperWithCount` to clean up the duplicated logic --- .../sdk/src/indexer-v2/queries/utils.ts | 32 +++---------------- 1 file changed, 4 insertions(+), 28 deletions(-) diff --git a/src/typescript/sdk/src/indexer-v2/queries/utils.ts b/src/typescript/sdk/src/indexer-v2/queries/utils.ts index b7e00f49e..d0311d9f8 100644 --- a/src/typescript/sdk/src/indexer-v2/queries/utils.ts +++ b/src/typescript/sdk/src/indexer-v2/queries/utils.ts @@ -90,12 +90,9 @@ export const waitForEmojicoinIndexer = async ( }); /** + * Return the curried version of queryHelperWithCount that extracts just the rows. * - * @param queryFn Takes in a query function that's used to be called after waiting for the indexer - * to reach a certain version. Then it extracts the row data and returns it. - * @param convert A function that converts the raw row data into the desired output, usually - * by converting it into a camelCased representation of the database row. - * @returns A curried function that applies the logic to the new query function. + * @see queryHelperWithCount */ export function queryHelper< Row extends Record, @@ -108,29 +105,8 @@ export function queryHelper< queryFn: QueryFunction, QueryArgs>, convert: (rows: Row) => OutputType ): (args: WithConfig) => Promise { - const query = async (args: WithConfig) => { - const { minimumVersion, ...queryArgs } = args; - const innerQuery = queryFn(queryArgs as QueryArgs); - - if (minimumVersion) { - await waitForEmojicoinIndexer(minimumVersion); - } - - try { - const res = await innerQuery; - const rows = extractRows(res); - if (res.error) { - console.error("[Failed row conversion]:\n"); - throw new Error(JSON.stringify(res)); - } - return rows.map(convert); - } catch (e) { - console.error(e); - return []; - } - }; - - return query; + // Return the curried version of queryHelperWithCount that extracts just the rows. + return async (args) => (await queryHelperWithCount(queryFn, convert)(args)).rows; } export function queryHelperSingle< From cb70457aa9947c1129b113c06cf0f0c94b55ab99 Mon Sep 17 00:00:00 2001 From: Bogdan Crisan Date: Tue, 12 Nov 2024 20:55:47 +0100 Subject: [PATCH 4/5] Reset page on search change --- .../src/components/pages/home/components/emoji-table/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/typescript/frontend/src/components/pages/home/components/emoji-table/index.tsx b/src/typescript/frontend/src/components/pages/home/components/emoji-table/index.tsx index 71b4096ab..0ce65f1ee 100644 --- a/src/typescript/frontend/src/components/pages/home/components/emoji-table/index.tsx +++ b/src/typescript/frontend/src/components/pages/home/components/emoji-table/index.tsx @@ -85,7 +85,7 @@ const EmojiTable = (props: EmojiTableProps) => { }; useEffect(() => { - pushURL(); + pushURL({ page: 0 }); /* eslint-disable-next-line react-hooks/exhaustive-deps */ }, [emojis]); From f23050a247da4257e5bea750e02845c1258d93ec Mon Sep 17 00:00:00 2001 From: Matt <90358481+xbtmatt@users.noreply.github.com> Date: Tue, 12 Nov 2024 11:59:26 -0800 Subject: [PATCH 5/5] Remove unnecessary barrel file for one component --- .../components/emoji-table/components/buttons-block/index.tsx | 2 +- .../pages/home/components/emoji-table/components/index.ts | 1 - .../src/components/pages/home/components/emoji-table/index.tsx | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) delete mode 100644 src/typescript/frontend/src/components/pages/home/components/emoji-table/components/index.ts diff --git a/src/typescript/frontend/src/components/pages/home/components/emoji-table/components/buttons-block/index.tsx b/src/typescript/frontend/src/components/pages/home/components/emoji-table/components/buttons-block/index.tsx index 7455a1beb..5bdaff2ae 100644 --- a/src/typescript/frontend/src/components/pages/home/components/emoji-table/components/buttons-block/index.tsx +++ b/src/typescript/frontend/src/components/pages/home/components/emoji-table/components/buttons-block/index.tsx @@ -14,7 +14,7 @@ export type ButtonsBlockProps = { className?: string; }; -const ButtonsBlock: React.FC = ({ +export const ButtonsBlock: React.FC = ({ value, numPages, onChange, diff --git a/src/typescript/frontend/src/components/pages/home/components/emoji-table/components/index.ts b/src/typescript/frontend/src/components/pages/home/components/emoji-table/components/index.ts deleted file mode 100644 index 434a3c2c4..000000000 --- a/src/typescript/frontend/src/components/pages/home/components/emoji-table/components/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default as ButtonsBlock } from "./buttons-block"; diff --git a/src/typescript/frontend/src/components/pages/home/components/emoji-table/index.tsx b/src/typescript/frontend/src/components/pages/home/components/emoji-table/index.tsx index 0ce65f1ee..d803db9b3 100644 --- a/src/typescript/frontend/src/components/pages/home/components/emoji-table/index.tsx +++ b/src/typescript/frontend/src/components/pages/home/components/emoji-table/index.tsx @@ -2,7 +2,7 @@ import React, { useEffect, useMemo } from "react"; -import { ButtonsBlock } from "./components"; +import { ButtonsBlock } from "./components/buttons-block"; import { InnerGridContainer, SearchWrapper,