From 549e03e67c7652f304da78f4d1f722599111f464 Mon Sep 17 00:00:00 2001 From: Tom Robiquet Date: Wed, 10 Jan 2024 10:36:22 +0200 Subject: [PATCH 1/4] Support og images for amm2 --- pages/api/og/[marketId].ts | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/pages/api/og/[marketId].ts b/pages/api/og/[marketId].ts index 85b088966..9b6f3cfc7 100644 --- a/pages/api/og/[marketId].ts +++ b/pages/api/og/[marketId].ts @@ -53,17 +53,13 @@ export default async function ( price: 0, }; - if (market.pool) { - const { assets } = await sdk.assets({ - where: { - pool: { poolId_eq: market.pool.poolId }, - }, - }); - - prediction = getCurrentPrediction(assets as any, market); + if (market.pool || market.neoPool) { + prediction = getCurrentPrediction(market.assets as any, market); } - const volume = new Decimal(market.pool?.volume ?? 0).div(ZTG).toFixed(2); + const volume = new Decimal(market.pool?.volume ?? market.neoPool?.volume ?? 0) + .div(ZTG) + .toFixed(2); const ends = moment(Number(market.period.end)).format("MMM Do, YYYY"); From 5576d65efae786f0df723b18e6ab6925d44f5d0a Mon Sep 17 00:00:00 2001 From: Tom Robiquet Date: Wed, 10 Jan 2024 10:47:40 +0200 Subject: [PATCH 2/4] include neopools in total volume calcs --- lib/gql/get-network-stats.ts | 37 ++++++++++++++++++++++++++++++------ 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/lib/gql/get-network-stats.ts b/lib/gql/get-network-stats.ts index 3fe250a6f..2fea2a95d 100644 --- a/lib/gql/get-network-stats.ts +++ b/lib/gql/get-network-stats.ts @@ -5,12 +5,13 @@ import { parseAssetIdString } from "lib/util/parse-asset-id"; import { getBaseAssetHistoricalPrices, lookupPrice } from "./historical-prices"; import { PoolOrderByInput, + NeoPoolOrderByInput, HistoricalSwapOrderByInput, } from "@zeitgeistpm/indexer"; export const getNetworkStats = async (sdk: Sdk) => { - const [marketCountBN, basePrices, pools, historicalSwaps] = await Promise.all( - [ + const [marketCountBN, basePrices, pools, neoPools, historicalSwaps] = + await Promise.all([ sdk.api.query.marketCommons.marketCounter(), getBaseAssetHistoricalPrices(), fetchAllPages(async (pageNumber, limit) => { @@ -21,6 +22,14 @@ export const getNetworkStats = async (sdk: Sdk) => { }); return pools; }), + fetchAllPages(async (pageNumber, limit) => { + const { neoPools } = await sdk.indexer.neoPools({ + limit: limit, + offset: pageNumber * limit, + order: NeoPoolOrderByInput.IdAsc, + }); + return neoPools; + }), fetchAllPages(async (pageNumber, limit) => { const { historicalSwaps } = await sdk.indexer.historicalSwaps({ limit: limit, @@ -29,10 +38,23 @@ export const getNetworkStats = async (sdk: Sdk) => { }); return historicalSwaps; }), - ], - ); + ]); + + const totalPoolVolumeUsd = pools.reduce((total, pool) => { + const poolCreationBaseAssetPrice = lookupPrice( + basePrices, + parseAssetIdString(pool.baseAsset) as BaseAssetId, + new Date(pool.createdAt).getTime(), + ); + + const volumeUsd = new Decimal(pool.volume).mul( + poolCreationBaseAssetPrice ?? 0, + ); + + return total.plus(volumeUsd); + }, new Decimal(0)); - const totalVolumeUsd = pools.reduce((total, pool) => { + const totalNeopoolVolumeUsd = pools.reduce((total, pool) => { const poolCreationBaseAssetPrice = lookupPrice( basePrices, parseAssetIdString(pool.baseAsset) as BaseAssetId, @@ -54,6 +76,9 @@ export const getNetworkStats = async (sdk: Sdk) => { return { marketCount: marketCountBN.toNumber(), tradersCount, - volumeUsd: totalVolumeUsd.div(ZTG).toNumber(), + volumeUsd: totalNeopoolVolumeUsd + .plus(totalPoolVolumeUsd) + .div(ZTG) + .toNumber(), }; }; From bb2c1de1687e94ab650d739d325fe35fbbbd5200 Mon Sep 17 00:00:00 2001 From: Tom Robiquet Date: Wed, 10 Jan 2024 13:07:20 +0200 Subject: [PATCH 3/4] amm2 support for trending markets --- lib/gql/trending-markets.ts | 202 +++++++++++++++--------------------- 1 file changed, 86 insertions(+), 116 deletions(-) diff --git a/lib/gql/trending-markets.ts b/lib/gql/trending-markets.ts index d5aa6a45d..870ede531 100644 --- a/lib/gql/trending-markets.ts +++ b/lib/gql/trending-markets.ts @@ -1,15 +1,18 @@ -import { PoolOrderByInput, PoolStatus } from "@zeitgeistpm/indexer"; +import { + MarketOrderByInput, + MarketStatus, + ScoringRule, +} from "@zeitgeistpm/indexer"; import { BaseAssetId, FullContext, IOForeignAssetId, - ScalarRangeType, Sdk, } from "@zeitgeistpm/sdk"; -import { ZeitgeistPrimitivesMarketMarketCreation } from "@polkadot/types/lookup"; +import { isNotNull } from "@zeitgeistpm/utility/dist/null"; import { IndexedMarketCardData } from "components/markets/market-card/index"; import Decimal from "decimal.js"; -import { gql, GraphQLClient } from "graphql-request"; +import { GraphQLClient, gql } from "graphql-request"; import { DAY_SECONDS, ZTG } from "lib/constants"; import { hiddenMarketIds } from "lib/constants/markets"; import { @@ -21,17 +24,11 @@ import { getCurrentPrediction } from "lib/util/assets"; import { fetchAllPages } from "lib/util/fetch-all-pages"; import { parseAssetIdString } from "lib/util/parse-asset-id"; import { marketMetaFilter } from "./constants"; -import { isNotNull } from "@zeitgeistpm/utility/dist/null"; const poolChangesQuery = gql` query PoolChanges($start: DateTime, $end: DateTime) { historicalPools( - where: { - timestamp_gt: $start - volume_gt: "0" - event_contains: "Swap" - timestamp_lt: $end - } + where: { timestamp_gt: $start, volume_gt: "0", timestamp_lt: $end } orderBy: id_DESC ) { poolId @@ -111,107 +108,74 @@ const getTrendingMarkets = async ( end: now, }); - const pools = await fetchAllPages(async (pageNumber, limit) => { - const { pools } = await sdk.indexer.pools({ + const markets = await fetchAllPages(async (pageNumber, limit) => { + const { markets } = await sdk.indexer.markets({ limit: limit, offset: pageNumber * limit, - where: { status_eq: PoolStatus.Active }, - order: PoolOrderByInput.IdAsc, + order: MarketOrderByInput.IdDesc, + where: { + status_eq: MarketStatus.Active, + scoringRule_eq: ScoringRule.Lmsr, + }, }); - return pools; + return markets; }); const basePrices = await getBaseAssetPrices(sdk); - const trendingPoolIds = calcTrendingPools(historicalPools, basePrices, pools); - - const trendingMarkets = await Promise.all( - trendingPoolIds.map(async (poolId) => { - const marketsRes = await client.request<{ - markets: { - marketId: number; - img: string; - question: string; - creation: ZeitgeistPrimitivesMarketMarketCreation["type"]; - marketType: { [key: string]: string }; - categories: { color: string; name: string }[]; - outcomeAssets: string[]; - baseAsset: string; - creator: string; - pool: { - volume: string; - }; - tags: []; - status: string; - scalarType: ScalarRangeType; - period: { end: string }; - }[]; - }>(marketQuery, { - poolId: Number(poolId), - }); - - const market = marketsRes.markets[0]; - - if (!market) { - console.log("No market"); - return null; - } - - const assetsRes = await client.request<{ - assets: { - pool: { poolId: number }; - price: number; - assetId: string; - }[]; - }>(assetsQuery, { - poolId: Number(poolId), - }); - - const assets = assetsRes.assets; - - const prediction = getCurrentPrediction(assets, market); + const trendingMarketIds = calcTrendingMarkets( + historicalPools, + basePrices, + markets, + ); - if (!market.categories) { - console.log("No categories for market", market.marketId); - return null; - } + const tm = trendingMarketIds.map((marketId) => { + const market = markets.find( + (market) => market.marketId === Number(marketId), + ); - const marketCategories: MarketOutcomes = market.categories.map( - (category, index) => { - const asset = assets[index]; - const marketCategory: MarketOutcome = { - ...category, - assetId: market.outcomeAssets[index], - price: asset.price, - }; + if (!market || !market.categories) return; + const marketCategories: MarketOutcomes = market.categories.map( + (category, index) => { + const asset = market.assets[index]; - return marketCategory; - }, - ); + const marketCategory: MarketOutcome = { + name: category.name ?? "", + assetId: market.outcomeAssets[index], + price: asset.price, + }; - const trendingMarket: IndexedMarketCardData = { - marketId: market.marketId, - question: market.question, - creation: market.creation, - img: market.img, - prediction: prediction, - creator: market.creator, - volume: Number(new Decimal(market.pool.volume).div(ZTG).toFixed(0)), - baseAsset: market.baseAsset, - outcomes: marketCategories, - pool: market.pool ?? null, - marketType: market.marketType, - tags: market.tags, - status: market.status, - scalarType: market.scalarType, - endDate: market.period.end, - }; + return marketCategory; + }, + ); - return trendingMarket; - }), - ); + const prediction = getCurrentPrediction(market.assets, market); + + const trendingMarket: IndexedMarketCardData = { + marketId: market.marketId, + question: market.question ?? "", + creation: market.creation, + img: market.img ?? "", + prediction: prediction, + creator: market.creator, + volume: Number( + new Decimal(market.neoPool?.volume ?? 0).div(ZTG).toFixed(0), + ), + baseAsset: market.baseAsset, + outcomes: marketCategories, + pool: market.pool ?? null, + neoPool: market.neoPool, + marketType: market.marketType as any, + tags: market.tags?.filter(isNotNull), + status: market.status, + scalarType: (market.scalarType ?? null) as "number" | "date" | null, + endDate: market.period.end, + }; + + return trendingMarket; + }); - return trendingMarkets.filter(isNotNull); + return tm.filter(isNotNull); }; const lookupPrice = ( @@ -223,29 +187,35 @@ const lookupPrice = ( : basePrices["ztg"]; }; -const calcTrendingPools = ( +const calcTrendingMarkets = ( transactions: { poolId: number; dVolume: string; }[], basePrices: ForeignAssetPrices, - pools: { poolId: number; baseAsset: string; status: string }[], + markets: { marketId: number; baseAsset: string }[], ) => { - const poolVolumes: { [key: string]: Decimal } = {}; - const maxPools = 8; + const marketVolumes: { [key: string]: Decimal } = {}; + const maxMarkets = 8; - // find total volume for each pool + // find total volume for each market transactions.forEach((transaction) => { - const volume = poolVolumes[transaction.poolId]; - if (volume) { - poolVolumes[transaction.poolId] = volume.plus(transaction.dVolume); - } else { - poolVolumes[transaction.poolId] = new Decimal(transaction.dVolume); + //for lsmr poolId === marketId + const marketId = transaction.poolId; + + if (markets.some((market) => market.marketId === marketId)) { + const volume = marketVolumes[transaction.poolId]; + if (volume) { + // for amm2 marketId === poolId + marketVolumes[transaction.poolId] = volume.plus(transaction.dVolume); + } else { + marketVolumes[transaction.poolId] = new Decimal(transaction.dVolume); + } } }); - for (let poolId in poolVolumes) { - const base = pools.find((pool) => pool.poolId === Number(poolId)) + for (let marketId in marketVolumes) { + const base = markets.find((market) => market.marketId === Number(marketId)) ?.baseAsset; const value = lookupPrice( @@ -253,16 +223,16 @@ const calcTrendingPools = ( parseAssetIdString(base) as BaseAssetId, ); - poolVolumes[poolId] = poolVolumes[poolId].mul(value ?? 0); + marketVolumes[marketId] = marketVolumes[marketId].mul(value ?? 0); } - const poolIdsByVolumeDesc = Object.keys(poolVolumes).sort((a, b) => { - const aVol = poolVolumes[a]; - const bVol = poolVolumes[b]; + const marketIdsByVolumeDesc = Object.keys(marketVolumes).sort((a, b) => { + const aVol = marketVolumes[a]; + const bVol = marketVolumes[b]; return bVol.minus(aVol).toNumber(); }); - return poolIdsByVolumeDesc.splice(0, maxPools); + return marketIdsByVolumeDesc.splice(0, maxMarkets); }; export default getTrendingMarkets; From e034e00b502bdb60f331aca27b757621ce8d7889 Mon Sep 17 00:00:00 2001 From: Tom Robiquet Date: Wed, 10 Jan 2024 13:26:35 +0200 Subject: [PATCH 4/4] display asset cost symbol --- components/front-page/LatestTrades.tsx | 4 +++- lib/hooks/queries/useLatestTrades.tsx | 20 ++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/components/front-page/LatestTrades.tsx b/components/front-page/LatestTrades.tsx index 98cd1fe5d..d7f5beb80 100644 --- a/components/front-page/LatestTrades.tsx +++ b/components/front-page/LatestTrades.tsx @@ -68,7 +68,9 @@ const LatestTrades = ({ ), outcome: trade.outcomeName, trade: trade.type === "buy" ? "Buy" : "Sell", - cost: formatNumberLocalized(trade.cost.div(ZTG).toNumber()), + cost: `${formatNumberLocalized(trade.cost.div(ZTG).toNumber())} ${ + trade.costSymbol + }`, price: formatNumberLocalized(trade.outcomePrice.toNumber()), time: `${moment.duration(now.diff(trade.time)).humanize()} ago`, }; diff --git a/lib/hooks/queries/useLatestTrades.tsx b/lib/hooks/queries/useLatestTrades.tsx index 0f8663220..1a910c123 100644 --- a/lib/hooks/queries/useLatestTrades.tsx +++ b/lib/hooks/queries/useLatestTrades.tsx @@ -4,13 +4,16 @@ import { getIndexOf, getMarketIdOf, IOBaseAssetId, + IOForeignAssetId, IOMarketOutcomeAssetId, isIndexedSdk, parseAssetId, } from "@zeitgeistpm/sdk"; import Decimal from "decimal.js"; import { BLOCK_TIME_SECONDS } from "lib/constants"; +import { lookupAssetSymbol } from "lib/constants/foreign-asset"; import { getMarketHeaders, MarketHeader } from "lib/gql/market-header"; +import { parseAssetIdString } from "lib/util/parse-asset-id"; import { useSdkv2 } from "../useSdkv2"; import { swapsMetaFilter } from "./constants"; @@ -25,6 +28,7 @@ export type TradeItem = { outcomePrice: Decimal; time: Date; cost: Decimal; + costSymbol: string; }; export const useLatestTrades = (limit?: number, marketId?: number) => { @@ -82,6 +86,8 @@ export const useLatestTrades = (limit?: number, marketId?: number) => { return; } + const costSymbol = findBaseAssetSymbol(swap.assetIn, swap.assetOut); + const assetInId = parseAssetId(swap.assetIn).unwrap(); const assetInIsBaseAsset = IOBaseAssetId.is(assetInId); @@ -100,6 +106,7 @@ export const useLatestTrades = (limit?: number, marketId?: number) => { assetInIsBaseAsset === true ? new Decimal(swap.assetAmountIn).div(swap.assetAmountOut) : new Decimal(swap.assetAmountOut).div(swap.assetAmountIn), + costSymbol, }; return item; @@ -131,6 +138,19 @@ const lookupOutcomeAsset = (asset: string, markets: MarketHeader[]) => { } }; +const findBaseAssetSymbol = (asset1: string, asset2: string) => { + const asset1Obj = parseAssetIdString(asset1); + const asset2Obj = parseAssetIdString(asset2); + + if (IOForeignAssetId.is(asset1Obj)) { + return lookupAssetSymbol(asset1Obj); + } + if (IOForeignAssetId.is(asset2Obj)) { + return lookupAssetSymbol(asset2Obj); + } + return lookupAssetSymbol(); +}; + const lookupMarket = (asset: string, markets: MarketHeader[]) => { const assetId = parseAssetId(asset).unwrap();