diff --git a/.env b/.env index e10eefb0f..57ec36c79 100644 --- a/.env +++ b/.env @@ -34,7 +34,7 @@ REACT_APP_HANGZHOUNET_FARMING_CONTRACT=KT1RRh3b5oPLsd4CZdmsZAfWMKuoqizyiRpF REACT_APP_ITHACANET_FARMING_CONTRACT=KT1HXQcPhPtVWiU64X4WZG9dmRBhBAkAEfT1 REACT_APP_MAINNET_COIN_FLIP_CONTRACT= -REACT_APP_ITHACANET_COIN_FLIP_CONTRACT= +REACT_APP_ITHACANET_COIN_FLIP_CONTRACT=KT1LVVEjsveEKc9hGHmDxrADRuenxRafjixd REACT_APP_HANGZHOUNET_COIN_FLIP_CONTRACT= # Contract for UI fee: diff --git a/src/config/config.ts b/src/config/config.ts index abf6a1cfa..ba53fd271 100644 --- a/src/config/config.ts +++ b/src/config/config.ts @@ -97,3 +97,13 @@ export const NEW_FARMINGS = ['5', '6']; export const YOUVES_FARMINGS = ['5', '6']; // Link to the Youves site export const YOUVES_LINK = 'https://app.youves.com/earn'; + +const COINFLIP_CONTRACTS: Record = { + [NetworkType.HANGZHOUNET]: '', + [NetworkType.MAINNET]: '', + [NetworkType.ITHACANET]: 'KT1LVVEjsveEKc9hGHmDxrADRuenxRafjixd' +}; + +export const DEFAULT_COINFLIP_CONTRACT = COINFLIP_CONTRACTS[NETWORK_ID]; + +export const COINFLIP_CONTRACT_DECIMALS = 1e18; diff --git a/src/modules/coinflip/api/coinflip-contract.interface.ts b/src/modules/coinflip/api/coinflip-contract.interface.ts new file mode 100644 index 000000000..0f0649712 --- /dev/null +++ b/src/modules/coinflip/api/coinflip-contract.interface.ts @@ -0,0 +1,15 @@ +import { BigMapAbstraction } from '@taquito/taquito'; +import { BigNumber } from 'bignumber.js'; + +export interface CoinflipStorage { + admin: string; + asset_to_id: BigMapAbstraction; + gamer_stats: BigMapAbstraction; + games: BigMapAbstraction; + id_to_asset: BigMapAbstraction; + assets_counter: BigNumber; + games_counter: BigNumber; + network_bank: BigNumber; + network_fee: BigNumber; + server: string; +} diff --git a/src/modules/coinflip/api/get-coinflip-general-stats.ts b/src/modules/coinflip/api/get-coinflip-general-stats.ts new file mode 100644 index 000000000..8754b516d --- /dev/null +++ b/src/modules/coinflip/api/get-coinflip-general-stats.ts @@ -0,0 +1,41 @@ +import { TezosToolkit } from '@taquito/taquito'; +import { BigNumber } from 'bignumber.js'; + +import { COINFLIP_CONTRACT_DECIMALS } from '@config/config'; +import { DEFAULT_TOKEN } from '@config/tokens'; +import { getStorageInfo } from '@shared/dapp'; +import { isEqual } from '@shared/helpers'; + +import { DashboardGeneralStats } from '../interfaces/dashboard-general-stats.interface'; +import { CoinflipStorage } from './coinflip-contract.interface'; + +enum TOKEN_ASSETS { + QUIPU = 0, + TEZOS = 1 +} + +interface GeneralStatsInterface { + bank: BigNumber; + games_count: BigNumber; + payout_quot_f: BigNumber; + total_won_amt: BigNumber; +} + +export const getCoinflipGeneralStats = async ( + tezos: TezosToolkit, + contractAddress: string, + tokenAddress: string +): Promise> => { + const tokenAsset = isEqual(tokenAddress, DEFAULT_TOKEN.contractAddress) ? TOKEN_ASSETS.QUIPU : TOKEN_ASSETS.TEZOS; + const storage = await getStorageInfo(tezos, contractAddress); + const generalStats = (await storage.id_to_asset.get(tokenAsset)) ?? null; + + if (!generalStats) { + return null; + } + + const { bank, games_count: gamesCount, payout_quot_f, total_won_amt: totalWins } = generalStats; + const payoutCoefficient = payout_quot_f.div(COINFLIP_CONTRACT_DECIMALS); + + return { bank, gamesCount, payoutCoefficient, totalWins }; +}; diff --git a/src/modules/coinflip/api/index.ts b/src/modules/coinflip/api/index.ts index 4df06f40e..116a0707e 100644 --- a/src/modules/coinflip/api/index.ts +++ b/src/modules/coinflip/api/index.ts @@ -1 +1,2 @@ export * from './flip.api'; +export * from './get-coinflip-general-stats'; diff --git a/src/modules/coinflip/coinflip.page.module.scss b/src/modules/coinflip/coinflip.page.module.scss index fa9845362..59ac83539 100644 --- a/src/modules/coinflip/coinflip.page.module.scss +++ b/src/modules/coinflip/coinflip.page.module.scss @@ -1,26 +1,10 @@ @import '@styles/breakpoints'; -.dashboardCard > :nth-child(1) { - font-size: 14px; -} - -.dashboardCard > :nth-child(2) { - font-size: 14px; -} - .game { margin-top: 24px; } @include media('>Lphone') { - .dashboardCard > :nth-child(1) { - font-size: 16px; - } - - .dashboardCard > :nth-child(2) { - font-size: 18px; - } - .game { width: 50%; } diff --git a/src/modules/coinflip/coinflip.page.tsx b/src/modules/coinflip/coinflip.page.tsx index d7e38203e..07f56816f 100644 --- a/src/modules/coinflip/coinflip.page.tsx +++ b/src/modules/coinflip/coinflip.page.tsx @@ -1,53 +1,26 @@ import { FC } from 'react'; -import { PageTitle, TestnetAlert, StateWrapper, DashboardStatsInfo, DashboardCard } from '@shared/components'; +import { PageTitle, TestnetAlert, StateWrapper } from '@shared/components'; +import { useTranslation } from '@translation'; import { useCoinflipPageViewModel } from './coinflip-page.vm'; import styles from './coinflip.page.module.scss'; import { CoinflipGame, CoinflipTokenSelector } from './components'; +import { CoinflipDashboardStatsInfo } from './components/dashboard-general-stats-info/coinflip-dashboard-stats'; export const CoinflipPage: FC = () => { + const { t } = useTranslation('coinflip'); const { isInitialized } = useCoinflipPageViewModel(); return ( loading...}> - Game + {t('coinflip|Game')} - , - , - , - - ]} - countOfRightElements={1} - /> +
diff --git a/src/modules/coinflip/components/dashboard-general-stats-info/coinflip-dashboard-stats.module.scss b/src/modules/coinflip/components/dashboard-general-stats-info/coinflip-dashboard-stats.module.scss new file mode 100644 index 000000000..f54ab3534 --- /dev/null +++ b/src/modules/coinflip/components/dashboard-general-stats-info/coinflip-dashboard-stats.module.scss @@ -0,0 +1,15 @@ +@import '@styles/breakpoints'; + +.dashboardCard > :nth-child(n) { + font-size: 14px; +} + +@include media('>Lphone') { + .dashboardCard > :nth-child(1) { + font-size: 16px; + } + + .dashboardCard > :nth-child(2) { + font-size: 18px; + } +} diff --git a/src/modules/coinflip/components/dashboard-general-stats-info/coinflip-dashboard-stats.tsx b/src/modules/coinflip/components/dashboard-general-stats-info/coinflip-dashboard-stats.tsx new file mode 100644 index 000000000..4622f2d8e --- /dev/null +++ b/src/modules/coinflip/components/dashboard-general-stats-info/coinflip-dashboard-stats.tsx @@ -0,0 +1,60 @@ +import { FC } from 'react'; + +import { observer } from 'mobx-react-lite'; + +import { useCoinflipStore } from '@modules/coinflip/hooks'; +import { DashboardCard, DashboardStatsInfo } from '@shared/components'; + +import styles from './coinflip-dashboard-stats.module.scss'; +import { useCoinflipDashboardStatsViewModel } from './use-coinflip-dashboard-stats.vm'; + +export const CoinflipDashboardStatsInfo: FC = observer(() => { + const coinflipStore = useCoinflipStore(); + const { token } = coinflipStore; + const { generalStats, isLoading, currency } = useCoinflipDashboardStatsViewModel(token); + const { bank, gamesCount, payoutCoefficient, totalWins } = generalStats; + + return ( + , + , + , + + ]} + countOfRightElements={1} + /> + ); +}); diff --git a/src/modules/coinflip/components/dashboard-general-stats-info/use-coinflip-dashboard-stats.vm.ts b/src/modules/coinflip/components/dashboard-general-stats-info/use-coinflip-dashboard-stats.vm.ts new file mode 100644 index 000000000..bae6ced86 --- /dev/null +++ b/src/modules/coinflip/components/dashboard-general-stats-info/use-coinflip-dashboard-stats.vm.ts @@ -0,0 +1,74 @@ +import { useEffect, useState } from 'react'; + +import { NetworkType } from '@airgap/beacon-sdk'; +import { TezosToolkit } from '@taquito/taquito'; + +import { DEFAULT_COINFLIP_CONTRACT } from '@config/config'; +import { RPC_URLS } from '@config/enviroment'; +import { DashboardGeneralStats } from '@modules/coinflip/interfaces/dashboard-general-stats.interface'; +import { TokenToPlay } from '@modules/coinflip/stores'; +import { bigNumberToString, isTezosToken } from '@shared/helpers'; +import { Token } from '@shared/types'; +import { useToasts } from '@shared/utils'; + +import { getCoinflipGeneralStats } from '../../api'; + +interface DashboardGeneralStatsMapped { + bank: Nullable; + gamesCount: Nullable; + payoutCoefficient: Nullable; + totalWins: Nullable; +} + +const DEFAULT_GENERAL_STATS: DashboardGeneralStatsMapped = { + bank: null, + gamesCount: null, + payoutCoefficient: null, + totalWins: null +}; + +export const useCoinflipDashboardStatsViewModel = (token: Token) => { + const [isLoading, setLoading] = useState(true); + const [generalStats, setGeneralStats] = useState>(null); + const { showErrorToast } = useToasts(); + + const currency = isTezosToken(token) ? TokenToPlay.Tezos : TokenToPlay.Quipu; + + useEffect(() => { + const asyncLoad = async () => { + const tezos = new TezosToolkit(RPC_URLS[NetworkType.ITHACANET]); + setLoading(true); + try { + const coinflipGeneralStats = await getCoinflipGeneralStats( + tezos, + DEFAULT_COINFLIP_CONTRACT, + token.contractAddress + ); + setGeneralStats(coinflipGeneralStats); + } catch (error) { + showErrorToast(error as Error); + } + + setLoading(false); + }; + void asyncLoad(); + }, [showErrorToast, token]); + + const generalStatsMapping = ({ + bank, + gamesCount, + payoutCoefficient, + totalWins + }: DashboardGeneralStats): DashboardGeneralStatsMapped => { + return { + bank: bank ? bigNumberToString(bank) : null, + gamesCount: gamesCount ? bigNumberToString(gamesCount) : null, + payoutCoefficient: payoutCoefficient ? bigNumberToString(payoutCoefficient) : null, + totalWins: totalWins ? bigNumberToString(totalWins) : null + }; + }; + + const generalStatsMap = generalStats ? generalStatsMapping(generalStats) : DEFAULT_GENERAL_STATS; + + return { generalStats: generalStatsMap, currency, isLoading }; +}; diff --git a/src/modules/coinflip/interfaces/dashboard-general-stats.interface.ts b/src/modules/coinflip/interfaces/dashboard-general-stats.interface.ts new file mode 100644 index 000000000..c6d41e343 --- /dev/null +++ b/src/modules/coinflip/interfaces/dashboard-general-stats.interface.ts @@ -0,0 +1,8 @@ +import { BigNumber } from 'bignumber.js'; + +export interface DashboardGeneralStats { + bank: Nullable; + gamesCount: Nullable; + payoutCoefficient: Nullable; + totalWins: Nullable; +} diff --git a/src/translation/locales/en/coinflip.ts b/src/translation/locales/en/coinflip.ts index b2b4bbfe8..66874d8e9 100644 --- a/src/translation/locales/en/coinflip.ts +++ b/src/translation/locales/en/coinflip.ts @@ -1,4 +1,5 @@ export const coinflip = { + Game: 'Game', selectCoinTitle: 'Select your side of coin', Flip: 'Flip', selectTokenToPlayWith: 'Select Token to Play with'