diff --git a/.env.example b/.env.example
index 8752a9076..04e49f347 100644
--- a/.env.example
+++ b/.env.example
@@ -24,7 +24,7 @@ NEXT_PUBLIC_AVATAR_COLLECTION_ID="2e55d4bf2e85715b63-ZEITASTAGE"
NEXT_PUBLIC_SINGULAR_URL="https://singular-rmrk2-dev.vercel.app"
NEXT_PUBLIC_RMRK_INDEXER_API="https://gql2.rmrk.dev/v1/graphql"
NEXT_PUBLIC_IPFS_NODE="http://ipfs.zeitgeist.pm:5001"
-NEXT_PUBLIC_RMRK_CHAIN_RPC_NODE="wss://staging.node.rmrk.app"
+NEXT_PUBLIC_RMRK_CHAIN_RPC_NODE="wss://kusama-node-staging.rmrk.link/"
NEXT_PUBLIC_AVATAR_API_HOST="https://avatar-bsr.zeitgeist.pm/"
NEXT_PUBLIC_MIGRATION_IN_PROGRESS=false
diff --git a/components/account/AccountButton.tsx b/components/account/AccountButton.tsx
index 86015a130..9146e4f3d 100644
--- a/components/account/AccountButton.tsx
+++ b/components/account/AccountButton.tsx
@@ -14,7 +14,6 @@ import { useWallet } from "lib/state/wallet";
import { formatNumberLocalized, shortenAddress } from "lib/util";
import { FaNetworkWired } from "react-icons/fa";
-import dynamic from "next/dynamic";
import Link from "next/link";
import { useRouter } from "next/router";
import React, { FC, Fragment, PropsWithChildren, useState } from "react";
diff --git a/components/markets/market-card/index.tsx b/components/markets/market-card/index.tsx
index d9c85b8c5..74a2c9865 100644
--- a/components/markets/market-card/index.tsx
+++ b/components/markets/market-card/index.tsx
@@ -1,6 +1,5 @@
import type { ScalarRangeType } from "@zeitgeistpm/sdk";
import Skeleton from "components/ui/Skeleton";
-import { motion } from "framer-motion";
import Decimal from "decimal.js";
import { ZTG } from "lib/constants";
import { MarketOutcomes } from "lib/types/markets";
@@ -18,8 +17,6 @@ import {
} from "@zeitgeistpm/sdk";
import { lookupAssetImagePath } from "lib/constants/foreign-asset";
import Image from "next/image";
-import MarketImage from "components/ui/MarketImage";
-import { useHover } from "lib/hooks/events/useHover";
export interface IndexedMarketCardData {
marketId: number;
@@ -28,11 +25,11 @@ export interface IndexedMarketCardData {
creation: string;
creator: string;
outcomes: MarketOutcomes;
- marketType: { categorical?: string; scalar?: string[] };
- scalarType: ScalarRangeType;
+ marketType: MarketType;
+ scalarType: ScalarRangeType | null;
prediction: { name: string; price: number };
volume: number;
- pool: { poolId?: number; volume: string } | null;
+ pool?: { poolId?: number; volume: string } | null;
baseAsset: string;
tags?: string[];
status: string;
@@ -40,6 +37,12 @@ export interface IndexedMarketCardData {
liquidity?: string;
numParticipants?: number;
}
+
+export interface MarketType {
+ categorical?: string;
+ scalar?: string[];
+}
+
export interface MarketCardProps extends IndexedMarketCardData {
className?: string;
disableLink?: boolean;
@@ -256,7 +259,7 @@ export const MarketCard = ({
) : pool && marketType?.categorical ? (
- ) : pool && Object.keys(pool).length !== 0 ? (
+ ) : pool && scalarType && Object.keys(pool).length !== 0 ? (
=> {
const ids = await getFeaturedMarketIds();
- const featuredMarkets = await Promise.all(
- ids.map(async (id) => {
- const marketRes = await client.request<{
- markets: {
- pool: {
- poolId: number;
- volume: string;
- } | null;
- marketId: number;
- baseAsset: string;
- img: string;
- question: string;
- creator: string;
- creation: ZeitgeistPrimitivesMarketMarketCreation["type"];
- marketType: { [key: string]: string };
- scalarType: ScalarRangeType;
- categories: { color: string; name: string }[];
- outcomeAssets: string[];
- tags: [];
- status: string;
- period: { end: string };
- }[];
- }>(marketQuery, {
- marketId: id,
- });
-
- const market = marketRes.markets[0];
-
- if (!market) return;
- const pool = market.pool;
-
- if (!pool) {
- const noPoolMarket: IndexedMarketCardData = {
- marketId: market.marketId,
- question: market.question,
- creation: market.creation,
- creator: market.creator,
- pool: market.pool,
- img: market.img,
- prediction: { name: "None", price: 0 },
- marketType: market.marketType,
- scalarType: market.scalarType,
- volume: 0,
- baseAsset: market.baseAsset,
- outcomes: [],
- tags: [],
- status: market.status,
- endDate: market.period.end,
+ const { markets } = await sdk.indexer.markets({
+ where: {
+ marketId_in: ids,
+ },
+ });
+
+ const featuredMarkets: IndexedMarketCardData[] = markets.map((market) => {
+ const marketCategories: MarketOutcomes =
+ market.categories?.map((category, index) => {
+ const asset = market.assets[index];
+ const marketCategory: MarketOutcome = {
+ name: category.name ?? "",
+ assetId: market.outcomeAssets[index],
+ price: asset?.price ?? 0,
};
- return noPoolMarket;
- }
- const assetsRes = await client.request<{
- assets: {
- pool: { poolId: number };
- price: number;
- assetId: string;
- }[];
- }>(assetsQuery, {
- poolId: pool.poolId,
- });
-
- const assets = assetsRes.assets;
-
- const prediction = getCurrentPrediction(assets, market);
-
- const marketCategories: MarketOutcomes = market.categories.map(
- (category, index) => {
- const asset = assets[index];
- const marketCategory: MarketOutcome = {
- ...category,
- assetId: market.outcomeAssets[index],
- price: asset.price,
- };
-
- return marketCategory;
- },
- );
- const featuredMarket: IndexedMarketCardData = {
- marketId: market.marketId,
- question: market.question,
- creation: market.creation,
- creator: market.creator,
- img: market.img,
- prediction: prediction,
- volume: new Decimal(pool.volume).div(ZTG).toNumber(),
- baseAsset: market.baseAsset,
- outcomes: marketCategories,
- pool: market.pool,
- marketType: market.marketType,
- scalarType: market.scalarType,
- tags: market.tags,
- status: market.status,
- endDate: market.period.end,
- };
-
- return featuredMarket;
- }),
- );
-
- const filterMarkets = featuredMarkets.filter(isPresent);
-
- return filterMarkets;
+ return marketCategory;
+ }) ?? [];
+
+ const prediction = getCurrentPrediction(market.assets, market);
+
+ const cardMarket: IndexedMarketCardData = {
+ marketId: market.marketId,
+ question: market.question ?? "",
+ creation: market.creation,
+ creator: market.creator,
+ img: market.img ?? "",
+ prediction: prediction,
+ volume: new Decimal(market.pool?.volume ?? 0).div(ZTG).toNumber(),
+ baseAsset: market.baseAsset,
+ outcomes: marketCategories,
+ pool: market.pool,
+ marketType: market.marketType as MarketType,
+ scalarType: (market.scalarType ?? null) as ScalarRangeType,
+ tags: market.tags?.filter(isPresent) ?? [],
+ status: market.status,
+ endDate: market.period.end,
+ };
+ return cardMarket;
+ });
+
+ return featuredMarkets;
};
export default getFeaturedMarkets;
diff --git a/lib/hooks/queries/useAmm2MarketSpotPrices.ts b/lib/hooks/queries/useAmm2MarketSpotPrices.ts
new file mode 100644
index 000000000..37933d76b
--- /dev/null
+++ b/lib/hooks/queries/useAmm2MarketSpotPrices.ts
@@ -0,0 +1,58 @@
+import { useQuery } from "@tanstack/react-query";
+import { AssetId, isRpcSdk } from "@zeitgeistpm/sdk";
+import Decimal from "decimal.js";
+import { calculateSpotPrice } from "lib/util/amm2";
+import { getApiAtBlock } from "lib/util/get-api-at";
+import { useSdkv2 } from "../useSdkv2";
+
+export const amm2MarketSpotPricesRootKey = "amm2-market-spot-prices";
+
+export const useAmm2MarketSpotPrices = (
+ marketIds?: number[],
+ blockNumber?: number,
+) => {
+ const [sdk, id] = useSdkv2();
+
+ const enabled = !!sdk && !!marketIds && isRpcSdk(sdk);
+ const query = useQuery(
+ [id, amm2MarketSpotPricesRootKey, blockNumber],
+
+ async () => {
+ if (!enabled) return;
+ const api = await getApiAtBlock(sdk.api, blockNumber);
+
+ const pools = await Promise.all(
+ marketIds.map((marketId) => api.query.neoSwaps.pools(marketId)),
+ );
+
+ const prices: { [key: string]: Decimal } = {};
+
+ pools.forEach((wrappedPool) => {
+ const pool = wrappedPool.unwrapOr(null);
+ if (pool) {
+ pool.reserves.forEach((reserve, asset) => {
+ prices[asset.toString().toLowerCase()] = calculateSpotPrice(
+ new Decimal(reserve.toString()),
+ new Decimal(pool.liquidityParameter.toString()),
+ );
+ });
+ }
+ });
+
+ return prices;
+ },
+ {
+ enabled: enabled,
+ staleTime: 10_000,
+ },
+ );
+
+ return query;
+};
+
+export const lookupAssetPrice = (
+ assetId: AssetId,
+ prices?: { [key: string]: Decimal },
+): Decimal | undefined => {
+ return prices?.[JSON.stringify(assetId).toLowerCase()];
+};
diff --git a/lib/hooks/queries/useInfiniteMarkets.ts b/lib/hooks/queries/useInfiniteMarkets.ts
index cfb004890..6eb7aea5b 100644
--- a/lib/hooks/queries/useInfiniteMarkets.ts
+++ b/lib/hooks/queries/useInfiniteMarkets.ts
@@ -13,6 +13,7 @@ import { MarketOutcomes } from "lib/types/markets";
import { MarketStatus } from "@zeitgeistpm/indexer";
import { hiddenMarketIds } from "lib/constants/markets";
import { marketMetaFilter } from "./constants";
+import { ScoringRule } from "@zeitgeistpm/indexer";
export const rootKey = "markets-filtered";
@@ -62,45 +63,62 @@ export const useInfiniteMarkets = (
const markets: Market[] = await sdk.model.markets.list({
where: {
- ...validMarketWhereInput,
- status_not_in: [MarketStatus.Destroyed],
- status_in: statuses.length === 0 ? undefined : statuses,
- tags_containsAny: tags?.length === 0 ? undefined : tags,
- pool_isNull: withLiquidityOnly ? false : undefined,
- baseAsset_in: currencies?.length !== 0 ? currencies : undefined,
- ...(withLiquidityOnly
- ? {
- pool: {
- account: {
- balances_some: {
- balance_gt: 0,
- },
- },
+ AND: [
+ {
+ ...validMarketWhereInput,
+ status_not_in: [MarketStatus.Destroyed],
+ status_in: statuses.length === 0 ? undefined : statuses,
+ tags_containsAny: tags?.length === 0 ? undefined : tags,
+ baseAsset_in: currencies?.length !== 0 ? currencies : undefined,
+ },
+ {
+ OR: [
+ {
+ scoringRule_eq: ScoringRule.Cpmm,
+ pool_isNull: withLiquidityOnly ? false : undefined,
+ ...(withLiquidityOnly
+ ? {
+ pool: {
+ account: {
+ balances_some: {
+ balance_gt: 0,
+ },
+ },
+ },
+ }
+ : {}),
},
- }
- : {}),
+ {
+ scoringRule_eq: ScoringRule.Lmsr,
+ neoPool_isNull: withLiquidityOnly ? false : undefined,
+ },
+ ],
+ },
+ ],
},
offset: !pageParam ? 0 : limit * pageParam,
limit: limit,
order: orderByMap[orderBy],
});
- const outcomes = await getOutcomesForMarkets(sdk.indexer.client, markets);
-
- let resMarkets: Array = [];
+ const resMarkets: Array = markets.map((market) => {
+ const outcomes: MarketOutcomes = market.assets.map((asset, index) => {
+ return {
+ price: asset.price,
+ name: market.categories?.[index].name ?? "",
+ assetId: asset.assetId,
+ amountInPool: asset.amountInPool,
+ };
+ });
- for (const m of markets) {
- const marketOutcomes = outcomes[m.marketId];
- const prediction =
- m.pool != null
- ? getCurrentPrediction(marketOutcomes, m as any)
- : { name: "None", price: 0 };
+ const prediction = getCurrentPrediction(outcomes, market);
- resMarkets = [
- ...resMarkets,
- { ...m, outcomes: marketOutcomes, prediction },
- ];
- }
+ return {
+ ...market,
+ outcomes,
+ prediction,
+ };
+ });
return {
data: resMarkets,
diff --git a/lib/hooks/queries/usePortfolioPositions.ts b/lib/hooks/queries/usePortfolioPositions.ts
index 923724ebf..c9e3985aa 100644
--- a/lib/hooks/queries/usePortfolioPositions.ts
+++ b/lib/hooks/queries/usePortfolioPositions.ts
@@ -44,6 +44,11 @@ import {
ForeignAssetPrices,
useAllForeignAssetUsdPrices,
} from "./useAssetUsdPrice";
+import { ScoringRule } from "@zeitgeistpm/indexer";
+import {
+ lookupAssetPrice,
+ useAmm2MarketSpotPrices,
+} from "./useAmm2MarketSpotPrices";
export type UsePortfolioPositions = {
/**
@@ -74,9 +79,9 @@ export type Position = {
*/
market: FullMarketFragment;
/**
- * The pool related to the position.
+ * The cpmm pool related to the position.
*/
- pool: IndexedPool;
+ pool?: IndexedPool;
/**
* The outcome of the position. Name of the outcome.
*/
@@ -113,7 +118,7 @@ export type Position = {
* The total issuance of the positions pool shares.
* @nb This is only available for pool share positions.
*/
- totalIssuance: Decimal;
+ totalIssuance?: Decimal;
/**
* The change in the price of the position the last 24 hours.
*/
@@ -195,6 +200,16 @@ export const usePortfolioPositions = (
const pools = usePoolsByIds(filter);
const markets = useMarketsByIds(filter);
+ const amm2MarketIds = markets.data
+ ?.filter((market) => market.scoringRule === ScoringRule.Lmsr)
+ .map((m) => m.marketId);
+
+ const { data: amm2SpotPrices } = useAmm2MarketSpotPrices(amm2MarketIds);
+
+ const { data: amm2SpotPrices24HoursAgo } = useAmm2MarketSpotPrices(
+ amm2MarketIds,
+ block24HoursAgo,
+ );
const poolAccountIds = usePoolAccountIds(pools.data);
@@ -322,21 +337,23 @@ export const usePortfolioPositions = (
pool = pools.data?.find((pool) => pool.marketId === marketId);
}
- if (!market || !pool) {
+ if (!market) {
continue;
}
const balance = address
? userAssetBalances?.get(address, assetId)?.data?.balance
: undefined;
- const totalIssuanceForPoolQuery = poolsTotalIssuance[pool.poolId];
- const totalIssuanceData = poolsTotalIssuance[pool.poolId]?.data;
+ const totalIssuanceForPoolQuery = pool && poolsTotalIssuance[pool.poolId];
+ const totalIssuanceData = pool && poolsTotalIssuance[pool.poolId]?.data;
const userBalance = new Decimal(balance?.free.toNumber() ?? 0);
- const totalIssuance = new Decimal(
- totalIssuanceForPoolQuery.data?.totalIssuance.toString() ?? 0,
- );
+ const totalIssuance =
+ totalIssuanceForPoolQuery &&
+ new Decimal(
+ totalIssuanceForPoolQuery.data?.totalIssuance.toString() ?? 0,
+ );
let price: Decimal | undefined;
let price24HoursAgo: Decimal | undefined;
@@ -346,23 +363,32 @@ export const usePortfolioPositions = (
price = calcResolvedMarketPrices(market).get(getIndexOf(assetId));
price24HoursAgo = price;
} else {
- price =
- calculatePrice(
- pool,
+ if (market.scoringRule === ScoringRule.Cpmm && pool) {
+ price =
+ calculatePrice(
+ pool,
+ assetId,
+ poolsZtgBalances.data,
+ poolAssetBalances,
+ ) ?? undefined;
+
+ price24HoursAgo =
+ calculatePrice(
+ pool,
+ assetId,
+ poolsZtgBalances24HoursAgo.data,
+ poolAssetBalances24HoursAgo,
+ ) ?? undefined;
+ } else if (market.scoringRule === ScoringRule.Lmsr) {
+ price = lookupAssetPrice(assetId, amm2SpotPrices);
+
+ price24HoursAgo = lookupAssetPrice(
assetId,
- poolsZtgBalances.data,
- poolAssetBalances,
- ) ?? undefined;
-
- price24HoursAgo =
- calculatePrice(
- pool,
- assetId,
- poolsZtgBalances24HoursAgo.data,
- poolAssetBalances24HoursAgo,
- ) ?? undefined;
+ amm2SpotPrices24HoursAgo,
+ );
+ }
}
- } else if (IOPoolShareAssetId.is(assetId)) {
+ } else if (IOPoolShareAssetId.is(assetId) && pool) {
const poolAssetIds = pool.weights
.map((w) => parseAssetId(w.assetId).unwrap())
.filter(IOMarketOutcomeAssetId.is.bind(IOMarketOutcomeAssetId));
diff --git a/package.json b/package.json
index 86e859726..24776496d 100644
--- a/package.json
+++ b/package.json
@@ -39,11 +39,11 @@
"@web3auth/modal": "^7.0.4",
"@yornaath/batshit": "^0.7.1",
"@yornaath/batshit-devtools-react": "^0.5.4",
- "@zeitgeistpm/augment-api": "2.23.0",
+ "@zeitgeistpm/augment-api": "2.23.1",
"@zeitgeistpm/avatara-nft-sdk": "^1.3.1",
"@zeitgeistpm/avatara-react": "^1.3.2",
"@zeitgeistpm/avatara-util": "^1.2.0",
- "@zeitgeistpm/sdk": "2.47.0",
+ "@zeitgeistpm/sdk": "2.47.1",
"@zeitgeistpm/utility": "^2.20.0",
"axios": "^0.21.4",
"boring-avatars": "^1.6.1",
diff --git a/yarn.lock b/yarn.lock
index 42da8ca2c..5cfb8d846 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -4438,14 +4438,14 @@ __metadata:
languageName: node
linkType: hard
-"@zeitgeistpm/augment-api@npm:2.23.0, @zeitgeistpm/augment-api@npm:^2.23.0":
- version: 2.23.0
- resolution: "@zeitgeistpm/augment-api@npm:2.23.0"
+"@zeitgeistpm/augment-api@npm:2.23.1, @zeitgeistpm/augment-api@npm:^2.23.1":
+ version: 2.23.1
+ resolution: "@zeitgeistpm/augment-api@npm:2.23.1"
peerDependencies:
"@polkadot/api-base": "*"
"@polkadot/rpc-core": "*"
"@polkadot/types": "*"
- checksum: 482ea1c15b8c2e42325b730015979d16b369348307497d0a3c9451dee20aaa507e1dd1f6c0b241ca05c8d466bac075c0146ec917d96222e67c4df41abf213c79
+ checksum: 87751b2b100b5bc304e0a4a925cd7bbb15fb90eb03b6ea229d8f9ec4043a33c5ee20a5a915d9576daf73cfd1b2692c2945455b2c6e43592e3be9e4d14632991f
languageName: node
linkType: hard
@@ -4526,14 +4526,14 @@ __metadata:
languageName: node
linkType: hard
-"@zeitgeistpm/indexer@npm:^3.18.0":
- version: 3.18.0
- resolution: "@zeitgeistpm/indexer@npm:3.18.0"
+"@zeitgeistpm/indexer@npm:^3.18.1":
+ version: 3.18.1
+ resolution: "@zeitgeistpm/indexer@npm:3.18.1"
dependencies:
graphql: ^16.6.0
graphql-request: ^5.0.0
graphql-tag: ^2.12.6
- checksum: befbc749a39fa3777fd7c7036056010322ee5270bef661bc72c0e69d52ca64a86cfea747a481d97b5cd7f43961863d12a658eb9eed853d140f9570d4c1bfd4da
+ checksum: 8dd36e336f74fee95ad09c7f94f0cd0217fbc68820b661982e381fa8102fe547239ae955cc21355e94f26d6276cf4d4ee074b90715ecee00634bf9bfd4bcbc0f
languageName: node
linkType: hard
@@ -4551,12 +4551,12 @@ __metadata:
languageName: node
linkType: hard
-"@zeitgeistpm/sdk@npm:2.47.0":
- version: 2.47.0
- resolution: "@zeitgeistpm/sdk@npm:2.47.0"
+"@zeitgeistpm/sdk@npm:2.47.1":
+ version: 2.47.1
+ resolution: "@zeitgeistpm/sdk@npm:2.47.1"
dependencies:
- "@zeitgeistpm/augment-api": ^2.23.0
- "@zeitgeistpm/indexer": ^3.18.0
+ "@zeitgeistpm/augment-api": ^2.23.1
+ "@zeitgeistpm/indexer": ^3.18.1
"@zeitgeistpm/rpc": ^2.14.0
"@zeitgeistpm/utility": ^2.24.0
"@zeitgeistpm/web3.storage": ^2.15.0
@@ -4573,7 +4573,7 @@ __metadata:
"@polkadot/api": "*"
"@polkadot/types": "*"
"@polkadot/util": "*"
- checksum: ffcb1a82229a5f5f225262513f554d89ca642555a2311dacb38d17b44164a8c273e60080f0ee238ff43de869626d7c129981d093ab015ab23d9ca2bddd7ca3e4
+ checksum: 44186464d5d99301ac9dd3af5732fbac7aa6bde8ce38f6b2f7f49f51f7577f188af794af030107738b2e5c5dfafe798ac4809ad38950c4276717ad59aa9a71c7
languageName: node
linkType: hard
@@ -4631,11 +4631,11 @@ __metadata:
"@web3auth/modal": ^7.0.4
"@yornaath/batshit": ^0.7.1
"@yornaath/batshit-devtools-react": ^0.5.4
- "@zeitgeistpm/augment-api": 2.23.0
+ "@zeitgeistpm/augment-api": 2.23.1
"@zeitgeistpm/avatara-nft-sdk": ^1.3.1
"@zeitgeistpm/avatara-react": ^1.3.2
"@zeitgeistpm/avatara-util": ^1.2.0
- "@zeitgeistpm/sdk": 2.47.0
+ "@zeitgeistpm/sdk": 2.47.1
"@zeitgeistpm/utility": ^2.20.0
autoprefixer: 10.2.5
axios: ^0.21.4