From 75e94ae59bbd1aab3ba22ce013146228e07cedf1 Mon Sep 17 00:00:00 2001 From: Berteotti Date: Fri, 25 Oct 2024 14:18:27 +0700 Subject: [PATCH] feat: show market status and winning outcome on cardbet --- app/(main)/markets/Bet.tsx | 13 ++--- app/(main)/markets/MarketActivity.tsx | 12 ++--- app/components/CardBet.tsx | 68 ++++++++++++++++++--------- constants/index.ts | 9 +++- entities/markets/market.ts | 22 +++++++-- 5 files changed, 81 insertions(+), 43 deletions(-) diff --git a/app/(main)/markets/Bet.tsx b/app/(main)/markets/Bet.tsx index 2b6aa0cb..eb624475 100644 --- a/app/(main)/markets/Bet.tsx +++ b/app/(main)/markets/Bet.tsx @@ -4,7 +4,6 @@ import { ButtonLink, Icon, Tag, - TagProps, Tooltip, TooltipContent, TooltipTrigger, @@ -12,19 +11,13 @@ import { import { Market } from '@/entities'; import { FixedProductMarketMaker } from '@/queries/omen'; import { Swapbox } from '@/app/components'; -import { KLEROS_URL, REALITY_QUESTION_URL } from '@/constants'; +import { KLEROS_URL, OUTCOME_TAG_COLORS_SCHEME, REALITY_QUESTION_URL } from '@/constants'; import { PropsWithChildren } from 'react'; interface BetProps { fixedProductMarketMaker: FixedProductMarketMaker; } -const tagSchemeColors: Record = { - 0: 'success', - 1: 'danger', - [Market.INVALID_ANSWER]: 'quaternary', -}; - export const Bet = ({ fixedProductMarketMaker }: BetProps) => { const marketModel = new Market(fixedProductMarketMaker); @@ -82,7 +75,7 @@ export const Bet = ({ fixedProductMarketMaker }: BetProps) => { Current winner outcome is {marketModel.currentAnswer === Market.INVALID_ANSWER ? 'Invalid' @@ -123,7 +116,7 @@ export const Bet = ({ fixedProductMarketMaker }: BetProps) => {
{winnerOutcome.name} diff --git a/app/(main)/markets/MarketActivity.tsx b/app/(main)/markets/MarketActivity.tsx index f10396d0..11ca2f6e 100644 --- a/app/(main)/markets/MarketActivity.tsx +++ b/app/(main)/markets/MarketActivity.tsx @@ -15,17 +15,13 @@ import { getMarketTradesAndTransactions, } from '@/queries/omen'; import { formatDateTimeWithYear, formatEtherWithFixedDecimals, timeAgo } from '@/utils'; -import { Button, Icon, Tag, TagColorSchemeProp } from '@swapr/ui'; +import { Button, Icon, Tag } from '@swapr/ui'; import { Outcome } from '@/entities'; import { Skeleton, TokenLogo, UserAvatarWithAddress } from '@/app/components'; import { getAIAgents } from '@/queries/dune'; import { Address } from 'viem'; - -const TAG_COLOR_SCHEMES: { 0: TagColorSchemeProp; 1: TagColorSchemeProp } = { - 0: 'success', - 1: 'danger', -}; +import { OUTCOME_TAG_COLORS_SCHEME } from '@/constants'; const txTypeHumanWords: Record = { [TransactionType.Add]: ['added', 'to'], @@ -215,7 +211,9 @@ const TradeRow = ({ activity, isAIAgent }: TradeRowProps) => { )}

{formatEtherWithFixedDecimals(activity.outcomeTokensTraded)}

diff --git a/app/components/CardBet.tsx b/app/components/CardBet.tsx index 6d4b81c1..7d2b43b4 100644 --- a/app/components/CardBet.tsx +++ b/app/components/CardBet.tsx @@ -24,6 +24,7 @@ import { MarketThumbnail } from './MarketThumbnail'; import { Skeleton } from './Skeleton'; import { formatEtherWithFixedDecimals, formatValueWithFixedDecimals } from '@/utils'; import { useTx } from '@/context'; +import { OUTCOME_TAG_COLORS_SCHEME } from '@/constants'; interface CardBetProps extends PropsWithChildren { userBets: UserBets; @@ -55,7 +56,7 @@ export const CardBet = ({ userBets, children }: CardBetProps) => { const isLoser = market.isLoser(outcomeIndex); const getResultAmountString = (): string => { - if (!market.isClosed) return 'Potential win'; + if (!market.isClosed || !market.isAnswerFinal) return 'Potential win'; if (isWinner) return 'Won'; if (market.isAnswerInvalid) return 'Receive'; @@ -68,7 +69,7 @@ export const CardBet = ({ userBets, children }: CardBetProps) => { outcomeIndex ); - if (!market.isClosed || isWinner) + if (!market.isClosed || isWinner || !market.isAnswerFinal) return formatValueWithFixedDecimals(outcomeBalance, 2); if (market.isAnswerInvalid) @@ -85,46 +86,69 @@ export const CardBet = ({ userBets, children }: CardBetProps) => { className={cx( 'w-full bg-gradient-to-b from-[#F1F1F1] dark:from-[#131313]', isWinner && 'from-[#F2f2F2] to-[#d0ffd6] dark:from-[#131313] dark:to-[#11301F]', - isLoser && 'from-[#F2f2F2] to-[#f4cbc4] dark:from-[#131313] dark:to-[#301111]' + isLoser + ? market.isAnswerInvalid + ? '' + : 'from-[#F2f2F2] to-[#f4cbc4] dark:from-[#131313] dark:to-[#301111]' + : '' )} > -
+
-
+ + {market.fpmm.category} + +
- {market.fpmm.category} - - - {position.getOutcome()} + {market.getMarketStatus()} +

+ {remainingTime(market.closingDate)} +

-

- {remainingTime(market.closingDate)} -

-
+
-
- {market.fpmm.title} +
+
+ {market.fpmm.title} +
+ {market.isClosed && ( +
+

Answer:

+ {market.currentAnswer !== null && ( + + {market.getCurrentAnswerOutcome()?.name} + + )} +
+ )}
-
+
-
+
-

Bet amount:

-

-

{formatEtherWithFixedDecimals(collateralAmountSpent, 2)}

- -

+

Bet:

{' '} +
+ + {position.getOutcome()} + +

+

{formatEtherWithFixedDecimals(collateralAmountSpent, 2)}

+ +

+

diff --git a/constants/index.ts b/constants/index.ts index 2ce6e30c..94ab5969 100644 --- a/constants/index.ts +++ b/constants/index.ts @@ -1,4 +1,5 @@ -import { Token } from '@/entities'; +import { Market, Token } from '@/entities'; +import { TagProps } from '@swapr/ui'; export const AI_AGENTS_ALLOWLIST = [ '0x89c5cc945dd550bcffb72fe42bff002429f46fec', @@ -76,3 +77,9 @@ export const DISCORD_URL = process.env.NEXT_PUBLIC_DISCORD_URL || 'https://discord.com/invite/QFkNsjTkzD'; export const GITHUB_URL = process.env.NEXT_PUBLIC_GITHUB_URL || 'https://github.com/SwaprHQ/presagio'; + +export const OUTCOME_TAG_COLORS_SCHEME: Record = { + 0: 'success', + 1: 'danger', + [Market.INVALID_ANSWER]: 'quaternary', +}; diff --git a/entities/markets/market.ts b/entities/markets/market.ts index e3193965..5287a02d 100644 --- a/entities/markets/market.ts +++ b/entities/markets/market.ts @@ -24,8 +24,7 @@ export class Market { this.fpmm = fpmm; this.closingDate = new Date(+fpmm.openingTimestamp * 1000); this.isAnswerFinal = - !!fpmm.resolutionTimestamp || - fpmm.answerFinalizedTimestamp < nowTimestamp; + !!fpmm.resolutionTimestamp || fpmm.answerFinalizedTimestamp < nowTimestamp; this.currentAnswer = fpmm.question?.currentAnswer ? fpmm.question.currentAnswer === INVALID_ANSWER_HEX @@ -56,6 +55,7 @@ export class Market { fpmm.id, fpmm.outcomeTokenMarginalPrices?.[1] ), + new Outcome(-1, 'Invalid', fpmm.id), ]; } @@ -68,8 +68,24 @@ export class Market { } getWinnerOutcome() { - return this.isClosed && this.answer !== null && this.answer !== Market.INVALID_ANSWER + return this.isClosed && this.answer !== null && !this.isAnswerInvalid ? this.outcomes[this.answer] : null; } + + getCurrentAnswerOutcome() { + return this.currentAnswer !== null + ? this.outcomes.at(this.currentAnswer) || null + : null; + } + + getMarketStatus() { + if (this.isAnswerInvalid) return 'invalid market'; + + if (!this.isAnswerFinal && this.isClosed) return 'finalizing'; + + if (this.isClosed) return 'closed'; + + return 'open'; + } }