diff --git a/deployed-addresses.json b/deployed-addresses.json index 3d2cf79..9218a97 100644 --- a/deployed-addresses.json +++ b/deployed-addresses.json @@ -5,9 +5,12 @@ "contracts": { "WegaERC20Escrow": { "address": "0x1fFd5291E09264174d9956187cf8eFAE01E34875", - "legacyAddresses": [], + "legacyAddresses": [ + "0x2EE1d66d4c62a8c648f36fC8Faa7f8454F470520", + "0x65BdAB5722E4f5F7c377d73d5c0073Bb0671597d" + ], "deploymentBlock": null, - "implementation": "0x65BdAB5722E4f5F7c377d73d5c0073Bb0671597d" + "implementation": "0xed4a0cb18aF2D6b022F8f99Cf09b91aa06A9513d" }, "WegaERC20Dummy": { "address": "0x0000000000000000000000000000000000000000" @@ -37,10 +40,10 @@ "implementation": "0x720736cd88D57aF277A62495037Ce51788681B71" }, "FeeManager": { - "address": "0xE38d4530337a45C6D0C061f108e5AF040FCC175c", + "address": "0x679e91BAb4fA83c5d0543c460A41CEc52E6A6fd1", "legacyAddresses": [], "deploymentBlock": null, - "implementation": "0xc484aC8D7385dFbA73977832c9eb6413823de3A9" + "implementation": "0xfB244ac04620695e40bc165e99C1C1381B797DA8" }, "WegaRandomizer": { "address": "0x0000000000000000000000000000000000000000" diff --git a/src/common/ButtonForClaiming/index.tsx b/src/common/ButtonForClaiming/index.tsx index 2e1e20f..af7cdd6 100644 --- a/src/common/ButtonForClaiming/index.tsx +++ b/src/common/ButtonForClaiming/index.tsx @@ -8,9 +8,10 @@ import 'twin.macro' interface ButtonForClaimingProps { game: Wega; + tokenDecimals: number; } -export const ButtonForClaiming = ({ game }: ButtonForClaimingProps) => { +export const ButtonForClaiming = ({ game, tokenDecimals }: ButtonForClaimingProps) => { const { wallet } = useWegaStore() const { openConnectModal } = useConnectModal(); @@ -20,11 +21,11 @@ export const ButtonForClaiming = ({ game }: ButtonForClaimingProps) => { showModal(MODAL_TYPES.CLAIM_MODAL, { game, wallet, + tokenDecimals, hide: hideModal, }, true); } - - return (!wallet && openConnectModal ? + return tokenDecimals && (!wallet && openConnectModal ? : - diff --git a/src/common/ClaimBar/index.tsx b/src/common/ClaimBar/index.tsx index 8151b34..aad6a0e 100644 --- a/src/common/ClaimBar/index.tsx +++ b/src/common/ClaimBar/index.tsx @@ -1,4 +1,4 @@ -import { formatEther } from 'ethers'; +import { formatUnits } from 'ethers' import { GameTypeBadgeWrapper, DateColumn, @@ -26,6 +26,7 @@ import { selectGameById } from '../../components/WegaGames/apiSlice'; import { useSelector } from 'react-redux' import { ButtonForClaiming } from '../ButtonForClaiming'; import { constructBlockExplorerHash } from '../GameBar/utils'; +import { SupportedWagerTokenAddresses } from '../../models/constants'; import { Link } from 'react-router-dom' import { NormalText, @@ -43,7 +44,7 @@ interface ClaimBarProps { networkId: number; game?: Wega; } - +// TODO move token decimals into game props (URGENT) function ClaimBar({ gameId, networkId, @@ -55,13 +56,14 @@ function ClaimBar({ }: { gameId: number, count: number } & React.Attributes & Partial> & ClaimBarProps) { let claimableGame = useSelector(state => selectGameById(state, gameId)); if(game) claimableGame = game; + const tokenDecimals: number = SupportedWagerTokenAddresses[claimableGame?.wager.wagerCurrency as AllPossibleCurrencyTypes][claimableGame?.networkId as number].decimals as number; return claimableGame && ( {parseBarCount(count)} {/* date */} {dateFromTs(new Date(claimableGame.createdAt as string).getTime() * 1000)} - {formatEther(claimableGame.wager.wagerAmount)} + {Number(parseFloat(formatUnits(BigInt(claimableGame.wager.wagerAmount), tokenDecimals)).toFixed(0))} {renderWagerBadge(claimableGame.wager.wagerType, claimableGame.wager.wagerCurrency)} {claimableGame.wager.wagerCurrency} @@ -79,7 +81,7 @@ function ClaimBar({ {/* render for a joinable game */} - + diff --git a/src/common/GameBar/index.tsx b/src/common/GameBar/index.tsx index 5d0cb11..4ea41c4 100644 --- a/src/common/GameBar/index.tsx +++ b/src/common/GameBar/index.tsx @@ -23,7 +23,7 @@ import { dateFromTs } from '../../utils'; import { BarDiceIcon, BarCoinIcon, USDCIcon, USDTIcon, ArrowTrSquareIcon } from '../../assets/icons'; import { selectGameById } from '../../components/WegaGames/apiSlice'; import { GameBarLoadingSkeleton } from '../GameBar/GameBarLoadingSkeleton'; -import { formatEther } from 'ethers'; +import { formatUnits } from 'ethers'; import { ButtonForJoinableGame } from '../ButtonForJoinableGame'; import { ButtonForWaitingGame } from '../ButtonForWaitingGame'; import { useWegaStore } from '../../hooks' @@ -32,6 +32,7 @@ import { NormalText, } from "../../components/CreateGameCard/types"; import { Link } from 'react-router-dom'; +import { SupportedWagerTokenAddresses } from '../../models/constants'; import 'twin.macro'; export const BADGE_TEXTS: any = { @@ -51,6 +52,8 @@ function GameBar({ }: { gameId: number } & React.Attributes & Partial> & GameBarProps) { const game = useSelector(state => selectGameById(state, gameId)); const { user, network } = useWegaStore(); + const tokenDecimals: number = SupportedWagerTokenAddresses[game?.wager.wagerCurrency as AllPossibleCurrencyTypes][game?.networkId as number].decimals as number; + return game && user?.uuid && network ? ( {/* date */} @@ -62,12 +65,12 @@ function GameBar({ - {formatEther(game.wager.wagerAmount)} + {Number(parseFloat(formatUnits(BigInt(game.wager.wagerAmount), tokenDecimals)).toFixed(0))} {renderWagerBadge(game.wager.wagerType, game.wager.wagerCurrency)} {game.wager.wagerCurrency} - {/* escrow link button */} + {/* escrow link button */} {/* render for a joinable game */} {/* tx hash */} diff --git a/src/common/modals/ClaimModal.tsx b/src/common/modals/ClaimModal.tsx index 8654623..9d60813 100644 --- a/src/common/modals/ClaimModal.tsx +++ b/src/common/modals/ClaimModal.tsx @@ -1,4 +1,4 @@ -import { formatEther } from 'ethers'; +import { formatUnits } from 'ethers'; import tw, { styled } from 'twin.macro'; import { WinnerDeclarationContainer, GradientDiv } from './types'; import { NormalText, SmallText } from '../../components/CreateGameCard/types'; @@ -10,6 +10,7 @@ import { useTokenUSDValue } from '../../hooks'; import { useWithdrawMutation, useGetClaimAmountQuery } from './blockchainApiSlice'; import { useUpdateGameMutation } from '../../components/PlayGameSection/apiSlice'; import { miniWalletAddress, capitalize, toastSettings, parseError } from '../../utils'; + import Button from '../Button'; import WalletAvatar from "../../common/WalletAvatar"; import toast from 'react-hot-toast'; @@ -20,10 +21,11 @@ export interface ClaimModalProps { hide: any; game: Wega; wallet: any; + tokenDecimals: number; } -export const ClaimModal = ({ hide, game, wallet +export const ClaimModal = ({ hide, game, wallet, tokenDecimals }: ClaimModalProps) => { const [feeAmountIndex, sendAmountIndex] = [0, 1] const [claim, claimQuery] = useWithdrawMutation(); @@ -44,10 +46,9 @@ export const ClaimModal = ({ hide, game, wallet toast.error(message, { ...toastSettings('error', 'bottom-center') as any }); } }; - const wagerUSDValue = useTokenUSDValue(game.wager.wagerCurrency, Number(formatEther(game.wager.wagerAmount))); - // console.log(feeTaker) - // console.log(game.wager) - return ( + const wagerUSDValue = useTokenUSDValue(game.wager.wagerCurrency, Number(formatUnits(game.wager.wagerAmount, tokenDecimals))); + console.log(Number(formatUnits(game.wager.wagerAmount, tokenDecimals))) + return tokenDecimals && (
@@ -69,8 +70,8 @@ export const ClaimModal = ({ hide, game, wallet
{renderWagerBadge(game.wager.wagerType, game.wager.wagerCurrency)}
- {formatEther(game.wager.wagerAmount)} USDC - ${formatEther(game.wager.wagerAmount)} + {formatUnits(game.wager.wagerAmount, tokenDecimals)} USDC + ${formatUnits(game.wager.wagerAmount, tokenDecimals)}
@@ -110,7 +111,7 @@ export const ClaimModal = ({ hide, game, wallet Total claim before fees { !calculateFeesQuery.data ? 'calculating...' : { - Number(formatEther(calculateFeesQuery.data[feeAmountIndex])) + Number(formatEther(calculateFeesQuery.data[sendAmountIndex])) + parseFloat(String((Number(formatUnits(calculateFeesQuery.data[feeAmountIndex], tokenDecimals)) + Number(formatUnits(calculateFeesQuery.data[sendAmountIndex], tokenDecimals))/2))).toFixed(0) } {game.wager.wagerCurrency} } @@ -130,7 +131,7 @@ export const ClaimModal = ({ hide, game, wallet You pay { !calculateFeesQuery.data ? 'calculating...' : { - parseFloat(formatEther(calculateFeesQuery.data[feeAmountIndex])).toFixed(2) + parseFloat(formatUnits(calculateFeesQuery.data[feeAmountIndex], tokenDecimals) ).toFixed(2) } {game.wager.wagerCurrency} } @@ -140,7 +141,7 @@ export const ClaimModal = ({ hide, game, wallet Net winnings { !calculateFeesQuery.data ? 'calculating...' : { - formatEther(calculateFeesQuery.data[sendAmountIndex]) + formatUnits(calculateFeesQuery.data[sendAmountIndex], tokenDecimals) } {game.wager.wagerCurrency} } diff --git a/src/common/modals/CoinflipWinnerModal.tsx b/src/common/modals/CoinflipWinnerModal.tsx index 44d4b67..3a16407 100644 --- a/src/common/modals/CoinflipWinnerModal.tsx +++ b/src/common/modals/CoinflipWinnerModal.tsx @@ -6,7 +6,9 @@ import { BadgeIcon, renderWagerBadge } from "../GameBar"; import Button from '../Button'; import 'twin.macro'; import { AllPossibleCurrencyTypes, AllPossibleWagerTypes, AllPossibleWegaTypes} from '../../models'; -import { BigNumberish, formatEther } from 'ethers'; +import { SupportedWagerTokenAddresses } from '../../models/constants'; + +import { BigNumberish, formatUnits } from 'ethers'; import { Link } from 'react-router-dom'; import { CoinflipWinnerLogo, CoinflipLoserLogo } from './GameResolutionImages' @@ -15,6 +17,7 @@ export interface CoinflipWinnerModalProps { wagerCurrency: AllPossibleCurrencyTypes; wagerType: AllPossibleWagerTypes; wagerAmount: BigNumberish; + networkId: number; winnerFlipChoice: number; loserFlipChoice: number; hide: any; @@ -26,7 +29,10 @@ const CoinflipWinnerModal = ({ wagerAmount, gameType, winnerFlipChoice, + networkId, loserFlipChoice }: CoinflipWinnerModalProps) => { + const tokenDecimals: number = SupportedWagerTokenAddresses[wagerCurrency][networkId].decimals as number; + return (
@@ -48,7 +54,7 @@ const CoinflipWinnerModal = ({
- {formatEther(wagerAmount)} + {Number(parseFloat(formatUnits(BigInt(wagerAmount), tokenDecimals)).toFixed(0))} {renderWagerBadge(wagerType, wagerCurrency)} {wagerCurrency} diff --git a/src/common/modals/DiceWinnerModal.tsx b/src/common/modals/DiceWinnerModal.tsx index e0f4d11..cad6018 100644 --- a/src/common/modals/DiceWinnerModal.tsx +++ b/src/common/modals/DiceWinnerModal.tsx @@ -6,7 +6,8 @@ import { BadgeIcon, renderWagerBadge } from "../GameBar"; import Button from '../Button'; import 'twin.macro'; import { AllPossibleCurrencyTypes, AllPossibleWagerTypes, AllPossibleWegaTypes} from '../../models'; -import { BigNumberish, formatEther } from 'ethers'; +import { SupportedWagerTokenAddresses } from '../../models/constants'; +import { BigNumberish, formatUnits } from 'ethers'; import { Link } from 'react-router-dom'; import { DiceWinnerLogo, DiceLoserLogo } from './GameResolutionImages' @@ -15,6 +16,7 @@ export interface DiceWinnerModalProps { wagerCurrency: AllPossibleCurrencyTypes, wagerType: AllPossibleWagerTypes, wagerAmount: BigNumberish, + networkId: number, results: any, hide: any, } @@ -25,7 +27,9 @@ const DiceWinnerModal = ({ wagerAmount, gameType, results, + networkId, }: DiceWinnerModalProps) => { + const tokenDecimals: number = SupportedWagerTokenAddresses[wagerCurrency][networkId].decimals as number; return ( @@ -50,7 +54,7 @@ const DiceWinnerModal = ({ - {formatEther(wagerAmount)} + {Number(parseFloat(formatUnits(BigInt(wagerAmount), tokenDecimals)).toFixed(0))} {renderWagerBadge(wagerType, wagerCurrency)} {wagerCurrency} diff --git a/src/common/modals/GameWinnerDeclarationModal.tsx b/src/common/modals/GameWinnerDeclarationModal.tsx index 52718a9..c7bf0ab 100644 --- a/src/common/modals/GameWinnerDeclarationModal.tsx +++ b/src/common/modals/GameWinnerDeclarationModal.tsx @@ -6,7 +6,8 @@ import { BadgeIcon, renderWagerBadge } from "../GameBar"; import Button from '../Button'; import 'twin.macro'; import { AllPossibleCurrencyTypes, AllPossibleWagerTypes, AllPossibleWegaTypes} from '../../models'; -import { BigNumberish, formatEther } from 'ethers'; +import { SupportedWagerTokenAddresses } from '../../models/constants'; +import { BigNumberish, formatUnits } from 'ethers'; import { Link } from 'react-router-dom'; import { DiceWinnerLogo, DiceLoserLogo } from './GameResolutionImages' @@ -14,7 +15,9 @@ export interface GameWinnerDeclarationModalProps { gameType: AllPossibleWegaTypes, wagerCurrency: AllPossibleCurrencyTypes, wagerType: AllPossibleWagerTypes, + tokenDecimals: number; wagerAmount: BigNumberish, + networkId: number, results: any, hide: any, } @@ -24,8 +27,10 @@ export const GameWinnerDeclarationModal = ({ wagerType, wagerAmount, gameType, - results, + results, + networkId, }: GameWinnerDeclarationModalProps) => { + const tokenDecimals: number = SupportedWagerTokenAddresses[wagerCurrency][networkId].decimals as number; return ( @@ -50,7 +55,7 @@ export const GameWinnerDeclarationModal = ({ - {formatEther(wagerAmount)} + {Number(parseFloat(formatUnits(BigInt(wagerAmount), tokenDecimals)).toFixed(0))} {renderWagerBadge(wagerType, wagerCurrency)} {wagerCurrency} diff --git a/src/common/modals/GlobalModal.tsx b/src/common/modals/GlobalModal.tsx index 51bce31..7b8a3df 100644 --- a/src/common/modals/GlobalModal.tsx +++ b/src/common/modals/GlobalModal.tsx @@ -75,7 +75,6 @@ const GlobalModal: React.FC = ({ children }) => { modalProps: any, persist?: boolean, ) => { - console.log(modalType) setStore({ ...store, modalType, diff --git a/src/components/CreateGameCard/CreateCoinFlipGameCard.tsx b/src/components/CreateGameCard/CreateCoinFlipGameCard.tsx index 3408d07..36a46cf 100644 --- a/src/components/CreateGameCard/CreateCoinFlipGameCard.tsx +++ b/src/components/CreateGameCard/CreateCoinFlipGameCard.tsx @@ -40,7 +40,7 @@ import { useApproveERC20Mutation, } from './blockchainApiSlice'; import { useCreateGameMutation } from './apiSlice'; -import { toastSettings, toBigIntInWei, escrowConfig, parseTopicDataFromEventLog, convertBytesToNumber, parseError } from '../../utils'; +import { toastSettings, toBigIntInWei, escrowConfig, parseTopicDataFromEventLogs, convertBytesToNumber, parseError } from '../../utils'; import Button from '../../common/Button'; import { ToggleWagerBadge } from '../../common/ToggleWagerBadge'; import { useFormReveal } from './animations'; @@ -89,15 +89,11 @@ export const CreateCoinFlipGameCard = ({ // approval for allowance const wagerUSDValue = useTokenUSDValue(currentCurrencyType, watch('wager')); - const isWagerApproved = (allowance: string, wagerAmount: number, withDecimals?: boolean ) => { - if(withDecimals) return toBigIntInWei(allowance, tokenDecimals) >= toBigIntInWei(String(wagerAmount), tokenDecimals); - return toBigIntInWei(allowance) >= toBigIntInWei(String(wagerAmount), tokenDecimals); // if decimals then the correct wei amount will be returned - }; - + const isWagerApproved = (allowance: bigint, wagerAmount: bigint) => allowance >= wagerAmount; const allowanceQuery = useAllowanceQuery({ spender: escrowConfig.address[network?.id as keyof typeof escrowConfig.address], owner: playerAddress, - tokenAddress, + tokenAddress }); // get token balance of user @@ -109,7 +105,7 @@ export const CreateCoinFlipGameCard = ({ // create game const [approveERC20, approveERC20Query] = useApproveERC20Mutation(); const [createWagerAndDeposit, createWagerAndDepositQuery] = useCreateWagerAndDepositMutation(); - const [ createGame, { + const [createGame, { isLoading: isCreateGameLoading, status: createGameStatus, data: createGameResponse @@ -117,15 +113,17 @@ export const CreateCoinFlipGameCard = ({ const handleCreateGameClick = async ({ wager }: { wager: number }) => { try { - if(!isWagerApproved(allowanceQuery.data, wager)) { + if(!isWagerApproved(allowanceQuery.data, toBigIntInWei(String(wager), tokenDecimals))) { + console.log(toBigIntInWei(String(watch('wager')), tokenDecimals).toString()) await approveERC20({ spender: escrowConfig.address[network?.id as keyof typeof escrowConfig.address], wagerAsBigint: toBigIntInWei(String(wager), tokenDecimals), tokenAddress }).unwrap(); } - const receipt = await createWagerAndDeposit({ tokenAddress, wagerAsBigint: toBigIntInWei(String(wager), tokenDecimals), gameType, randomness: [convertBytesToNumber(drand.randomness)] }).unwrap(); - const parsedTopicData = parseTopicDataFromEventLog(receipt.logs[2], ['event GameCreation(bytes32 indexed escrowHash, uint256 indexed nonce, address creator, string name)']); + const receipt = await createWagerAndDeposit({ + tokenAddress, wagerAsBigint: toBigIntInWei(String(wager), tokenDecimals), gameType, randomness: [convertBytesToNumber(drand.randomness)] }).unwrap(); + const parsedTopicData = parseTopicDataFromEventLogs(receipt.logs, ['event GameCreation(bytes32 indexed escrowHash, uint256 indexed nonce, address creator, string name)']); await createGame({ gameType, players: [ { uuid: playerUuid } ], @@ -136,7 +134,7 @@ export const CreateCoinFlipGameCard = ({ wagerType: currentWagerType.toUpperCase() as AllPossibleWagerTypes, wagerHash: parsedTopicData?.escrowHash, tokenAddress, - wagerAmount: toBigIntInWei(String(wager), tokenDecimals).toString(), + wagerAmount: toBigIntInWei(String(wager), tokenDecimals).toString(), wagerCurrency: currentCurrencyType, nonce: Number(parsedTopicData?.nonce), }, @@ -157,7 +155,9 @@ export const CreateCoinFlipGameCard = ({ const navigateToGameUi = useNavigateTo() useEffect(() => { - if(wallet){ + console.log(!isWagerApproved(toBigIntInWei(allowanceQuery.data.toString(), tokenDecimals), toBigIntInWei(String(watch('wager')), tokenDecimals))) + console.log(toBigIntInWei(String(watch('wager')), tokenDecimals).toString()) + if(playerAddress && tokenAddress && tokenDecimals) { allowanceQuery.refetch(); if(createGameStatus === 'fulfilled' && createGameResponse) { navigateToGameUi(`/play/${gameType.toLowerCase()}/${createGameResponse.uuid}`, 1500, { replace: true, @@ -168,10 +168,11 @@ export const CreateCoinFlipGameCard = ({ watch('wager'), tokenAddress, createGameStatus, - createGameResponse + createGameResponse, + tokenDecimals ]); - return drand ? ( + return drand && tokenDecimals ? (
{ - if(withDecimals) return toBigIntInWei(allowance, tokenDecimals) >= toBigIntInWei(String(wagerAmount), tokenDecimals); - return toBigIntInWei(allowance) >= toBigIntInWei(String(wagerAmount), tokenDecimals); // if decimals then the correct wei amount will be returned - }; + const isWagerApproved = (allowance: bigint, wagerAmount: bigint) => allowance >= wagerAmount; const allowanceQuery = useAllowanceQuery({ spender: escrowConfig.address[network?.id as keyof typeof escrowConfig.address], @@ -119,7 +116,7 @@ export const CreateDiceGameCard = ({ const handleCreateGameClick = async ({ wager }: { wager: number }) => { try { - if(!isWagerApproved(allowanceQuery?.data, wager)) { + if(!isWagerApproved(allowanceQuery.data, toBigIntInWei(String(wager), tokenDecimals))) { await approveERC20({ spender: escrowConfig.address[network?.id as keyof typeof escrowConfig.address], wagerAsBigint: toBigIntInWei(String(wager), tokenDecimals), @@ -132,7 +129,7 @@ export const CreateDiceGameCard = ({ gameType, randomness: [convertBytesToNumber(randomness.randomness)] }).unwrap(); - const parsedTopicData = parseTopicDataFromEventLog(receipt.logs[2], ['event GameCreation(bytes32 indexed escrowHash, uint256 indexed nonce, address creator, string name)']); + const parsedTopicData = parseTopicDataFromEventLogs(receipt.logs, ['event GameCreation(bytes32 indexed escrowHash, uint256 indexed nonce, address creator, string name)']); await createGame({ gameType, players: [ { uuid: playerUuid } ], @@ -163,7 +160,7 @@ export const CreateDiceGameCard = ({ const navigateToGameUi = useNavigateTo() useEffect(() => { - if(playerAddress && tokenAddress) { + if(playerAddress && tokenAddress && tokenDecimals) { if(createGameStatus === 'fulfilled' && createGameResponse) { navigateToGameUi(`/play/${gameType.toLowerCase()}/${createGameResponse.uuid}`, 1500, { replace: true, state: { gameId: createGameResponse.id, gameUuid: createGameResponse.uuid } @@ -174,7 +171,8 @@ export const CreateDiceGameCard = ({ watch('wager'), tokenAddress, createGameStatus, - createGameResponse + createGameResponse, + tokenDecimals ]); useEffect(() => { allowanceQuery.refetch(); @@ -203,7 +201,7 @@ export const CreateDiceGameCard = ({ {/* should receive wager amount as input */} {wagerUSDValue.loading ? 'loading...' : wagerUSDValue.value} USD Balance: { - isWagerbalanceLoading ? "Retrieving balance..." : userWagerBalance ? parseFloat(userWagerBalance?.formatted as string).toFixed(2) : String(0) + isWagerbalanceLoading ? "Retrieving balance..." : userWagerBalance ? parseFloat(userWagerBalance?.formatted as string ?? 0).toFixed(2) : String(0) } {/* useBalance from wagmi can be used here */} diff --git a/src/components/CreateGameCard/blockchainApiSlice.ts b/src/components/CreateGameCard/blockchainApiSlice.ts index 6088dc3..637ab55 100644 --- a/src/components/CreateGameCard/blockchainApiSlice.ts +++ b/src/components/CreateGameCard/blockchainApiSlice.ts @@ -4,7 +4,7 @@ import { HexishString } from '../../models'; import { ContractTypes } from '../../libs/wagmi'; -import { formatEther } from 'ethers'; + // Todo // write function names with type safety @@ -34,8 +34,7 @@ export const createGameBlockchainApiSlice = blockchainApiSlice.injectEndpoints({ contract: ContractTypes.TOKEN, contractAddress: tokenAddress, args: [owner, spender] - }), - transformResponse: (response: any) => formatEther(response.toString()) + }) }), hash: builder.query ({ query: ({ tokenAddress, numPlayers, playerAddress, nonce, wagerAsBigint }) => ({ diff --git a/src/components/JoinGameCard/JoinCoinFlipGameCard.tsx b/src/components/JoinGameCard/JoinCoinFlipGameCard.tsx index 358bf1f..8c82e5d 100644 --- a/src/components/JoinGameCard/JoinCoinFlipGameCard.tsx +++ b/src/components/JoinGameCard/JoinCoinFlipGameCard.tsx @@ -40,14 +40,13 @@ import { useNavigateTo, useCreateGameParams, useWegaStore, useTokenUSDValue, use import { useDepositAndJoinCoinflipMutation } from './blockchainApiSlice'; import { useAllowanceQuery, useApproveERC20Mutation } from '../CreateGameCard/blockchainApiSlice'; import toast from 'react-hot-toast'; -import { toastSettings, escrowConfig, convertBytesToNumber, parseError, formatLowerDecimalTokenValue, exponentialToBigintInWei } from '../../utils'; +import { toastSettings, escrowConfig, convertBytesToNumber, parseError } from '../../utils'; import Button from '../../common/Button'; import { useFormReveal } from '../CreateGameCard/animations'; import { useJoinGameMutation, useUpdateGameMutation } from './apiSlice'; import { ToggleCoinFlipSides } from '../../common/ToggleCoinFlipSides'; -import { ComponentLoader } from '../../common/loaders' - - +import { ComponentLoader } from '../../common/loaders'; +import { formatUnits, toBigInt, BigNumberish } from 'ethers'; export interface JoinCoinFlipGameCardProps extends React.Attributes, React.AllHTMLAttributes { wagerType: AllPossibleWagerTypes; @@ -56,11 +55,11 @@ export interface JoinCoinFlipGameCardProps extends React.Attributes, React.AllHT playerAddress: HexishString; gameType: AllPossibleWegaTypes; playerUuid: string; - wagerAmount: number; + wagerAmount: BigNumberish; gameUuid: string; escrowId: HexishString; gameId: number; - gameAttributes: WegaAttributes; + gameAttributes: WegaAttributes; network: Network; } @@ -89,24 +88,22 @@ const JoinCoinFlipGameCard = ({ const [currentCoinSide] = useState(gameAttributes && Number(gameAttributes[0].value) === 1 ? 2 : 1); const {tokenAddress, playerAddress, playerUuid, tokenDecimals } = useCreateGameParams({ wallet, user, network, currencyType: currentCurrencyType }); // TODO change to generic name - const { register, formState: { errors }, handleSubmit } = useForm({ + const { register, formState: { errors }, handleSubmit, setValue } = useForm({ mode: 'onChange', - resolver: joiResolver(createGameSchema('wager', formatLowerDecimalTokenValue(wagerAmount, tokenDecimals))) , + resolver: joiResolver(createGameSchema('wager', Number(parseFloat(formatUnits(BigInt(wagerAmount), tokenDecimals)).toFixed(0)))), reValidateMode: 'onChange', defaultValues: { - wager: tokenDecimals && formatLowerDecimalTokenValue(wagerAmount, tokenDecimals), + wager: tokenDecimals && Number(parseFloat(formatUnits(BigInt(wagerAmount), tokenDecimals)).toFixed(0)), } }); // approval for allowance - const wagerUSDValue = useTokenUSDValue(currentCurrencyType, tokenDecimals && formatLowerDecimalTokenValue(wagerAmount, tokenDecimals)); - const isWagerApproved = (allowance: string | number, wagerAmount: number) => { - return exponentialToBigintInWei(Number(allowance)) >= exponentialToBigintInWei(wagerAmount); // if decimals then the correct wei amount will be returned - }; + const wagerUSDValue = useTokenUSDValue(currentCurrencyType, Number(parseFloat(formatUnits(BigInt(wagerAmount), tokenDecimals)).toFixed(0))); + const isWagerApproved = (allowance: bigint, wagerAmount: bigint) => allowance >= wagerAmount; const allowanceQuery = useAllowanceQuery({ spender: escrowConfig.address[network?.id as keyof typeof escrowConfig.address], owner: playerAddress, - tokenAddress, + tokenAddress, }); // get token balance of userP @@ -122,10 +119,10 @@ const JoinCoinFlipGameCard = ({ const handleDepositWagerClick = async () => { try { - if(!isWagerApproved(allowanceQuery.data, wagerAmount)) { + if(!isWagerApproved(allowanceQuery.data, toBigInt(wagerAmount))) { await approveERC20({ spender: escrowConfig.address[network?.id as keyof typeof escrowConfig.address], - wagerAsBigint: exponentialToBigintInWei(wagerAmount), + wagerAsBigint: toBigInt(wagerAmount), tokenAddress }).unwrap(); } @@ -156,7 +153,10 @@ const JoinCoinFlipGameCard = ({ const navigateToGameUi = useNavigateTo() useEffect(() => { + console.log(allowanceQuery?.data, toBigInt(wagerAmount)) + allowanceQuery.refetch(); + if(tokenDecimals) setValue('wager', Number(parseFloat(formatUnits(BigInt(wagerAmount), tokenDecimals)).toFixed(0))) }, [ tokenAddress, playerAddress, @@ -184,7 +184,7 @@ const JoinCoinFlipGameCard = ({
{/* wager */}
- + {wagerUSDValue.loading ? 'loading...' : wagerUSDValue.value} USD Balance: { - isWagerbalanceLoading ? "Retrieving balance..." : parseFloat(userWagerBalance?.formatted as string).toFixed(2) + isWagerbalanceLoading ? "Retrieving balance..." : parseFloat(userWagerBalance?.formatted as string ?? 0).toFixed(2) } {/* useBalance from wagmi can be used here */}
@@ -225,7 +225,7 @@ const JoinCoinFlipGameCard = ({
Wager
- {formatLowerDecimalTokenValue(wagerAmount, tokenDecimals)} + {Number(parseFloat(formatUnits(BigInt(wagerAmount), tokenDecimals)).toFixed(0))} <>{renderWagerBadge(currentWagerType, currentCurrencyType)} {currencyType}
diff --git a/src/components/JoinGameCard/JoinDiceGamecard.tsx b/src/components/JoinGameCard/JoinDiceGamecard.tsx index 79d6fa6..5ccdb32 100644 --- a/src/components/JoinGameCard/JoinDiceGamecard.tsx +++ b/src/components/JoinGameCard/JoinDiceGamecard.tsx @@ -38,16 +38,16 @@ import toast from 'react-hot-toast'; import { toastSettings, escrowConfig, - formatLowerDecimalTokenValue, convertBytesToNumber, - parseError, - exponentialToBigintInWei + parseError } from '../../utils'; import Button from '../../common/Button'; import { useFormReveal } from '../CreateGameCard/animations'; import { useJoinGameMutation, useUpdateGameMutation } from './apiSlice'; import { JoinGameCardProps } from './' import { ComponentLoader } from '../../common/loaders' +import { formatUnits, toBigInt } from 'ethers'; + export interface JoinDiceGameCardProps extends JoinGameCardProps, React.Attributes, React.AllHTMLAttributes {}; @@ -71,27 +71,24 @@ const JoinGameDiceCard: React.FC = ({ const detailsBlock = useRef(null) const [currentWagerType] = useState(wagerType); const [currentCurrencyType] = useState(currencyType); - const {tokenAddress, playerAddress, playerUuid, tokenDecimals } = useCreateGameParams({ wallet, user, network, currencyType: currentCurrencyType }); // TODO change to generic name + const {tokenAddress, playerAddress, playerUuid, tokenDecimals } = useCreateGameParams({ wallet, user, network, currencyType: currentCurrencyType }); const {revealed, triggerRevealAnimation} = useFormReveal(false, formRef, detailsBlock); // should go into blockchain api slice const { formState: { errors }, handleSubmit, setValue, register } = useForm({ mode: 'onChange', - resolver: joiResolver(createGameSchema('wager', formatLowerDecimalTokenValue(wagerAmount, tokenDecimals))) , + resolver: joiResolver(createGameSchema('wager', Number(parseFloat(formatUnits(BigInt(wagerAmount), tokenDecimals)).toFixed(0)))) , reValidateMode: 'onChange', defaultValues: { - wager: tokenDecimals && formatLowerDecimalTokenValue(wagerAmount, tokenDecimals), + wager: tokenDecimals && Number(parseFloat(formatUnits(BigInt(wagerAmount), tokenDecimals)).toFixed(0)), } }); - const wagerUSDValue = useTokenUSDValue(currentCurrencyType, tokenDecimals && formatLowerDecimalTokenValue(wagerAmount, tokenDecimals)); + const wagerUSDValue = useTokenUSDValue(currentCurrencyType, tokenDecimals && Number(parseFloat(formatUnits(BigInt(wagerAmount), tokenDecimals)).toFixed(0))); // approval for allowance - const isWagerApproved = (allowance: string | number, wagerAmount: number) => { - return exponentialToBigintInWei(Number(allowance)) >= exponentialToBigintInWei(wagerAmount); // if decimals then the correct wei amount will be returned - }; - + const isWagerApproved = (allowance: bigint, wagerAmount: bigint) => allowance >= wagerAmount; const allowanceQuery = useAllowanceQuery({ spender: escrowConfig.address[network?.id as keyof typeof escrowConfig.address], owner: playerAddress, @@ -110,10 +107,10 @@ const JoinGameDiceCard: React.FC = ({ const [approveERC20, approveERC20Query] = useApproveERC20Mutation(); const handleDepositWagerClick = async () => { try { - if(!isWagerApproved(allowanceQuery.data, wagerAmount)) { + if(!isWagerApproved(allowanceQuery?.data, toBigInt(wagerAmount))) { await approveERC20({ spender: escrowConfig.address[network?.id as keyof typeof escrowConfig.address], - wagerAsBigint: exponentialToBigintInWei(wagerAmount), + wagerAsBigint: toBigInt(wagerAmount), tokenAddress }).unwrap(); } @@ -135,7 +132,7 @@ const JoinGameDiceCard: React.FC = ({ const navigateToGameUi = useNavigateTo() useEffect(() => { allowanceQuery.refetch(); - if(tokenDecimals) setValue('wager', formatLowerDecimalTokenValue(wagerAmount, tokenDecimals)) + if(tokenDecimals) setValue('wager', Number(parseFloat(formatUnits(BigInt(wagerAmount), tokenDecimals)).toFixed(0))) }, [ tokenAddress, playerAddress, @@ -159,7 +156,7 @@ const JoinGameDiceCard: React.FC = ({
{/* wager */}
- + = ({
Wager
- {formatLowerDecimalTokenValue(wagerAmount, tokenDecimals)} + {Number(parseFloat(formatUnits(BigInt(wagerAmount), tokenDecimals)).toFixed(0))} <>{renderWagerBadge(currentWagerType, currentCurrencyType)} {currencyType}
diff --git a/src/components/JoinGameCard/index.tsx b/src/components/JoinGameCard/index.tsx index ebf3397..8748147 100644 --- a/src/components/JoinGameCard/index.tsx +++ b/src/components/JoinGameCard/index.tsx @@ -9,12 +9,13 @@ import { } from "../../models"; import JoinDiceGameCard from './JoinDiceGamecard'; import JoinCoinFlipGameCard from './JoinCoinFlipGameCard'; +import { BigNumberish } from "ethers"; export interface JoinGameCardProps extends React.Attributes, React.AllHTMLAttributes { wagerType: AllPossibleWagerTypes; currencyType: AllPossibleCurrencyTypes; gameType: AllPossibleWegaTypes; - wagerAmount: number; + wagerAmount: BigNumberish; gameUuid: string; escrowId: HexishString; gameId: number; diff --git a/src/components/PlayGamePlayerCard/index.tsx b/src/components/PlayGamePlayerCard/index.tsx index 09607dc..b64ad25 100644 --- a/src/components/PlayGamePlayerCard/index.tsx +++ b/src/components/PlayGamePlayerCard/index.tsx @@ -111,7 +111,7 @@ const DicePlayerCard: React.FC = ({
Wager: - {format(wager.wagerAmount, tokenDecimals as number)} + {parseFloat(format(wager.wagerAmount, tokenDecimals as number)).toFixed(0)} {renderWagerBadge(wager.wagerType, wager.wagerCurrency)} {wager.wagerCurrency} @@ -179,7 +179,7 @@ const CoinFlipPlayerCard: React.FC = ({
Wager: - {format(wager.wagerAmount, tokenDecimals as number)} + {parseFloat(format(wager.wagerAmount, tokenDecimals as number)).toFixed(0)} {renderWagerBadge(wager.wagerType, wager.wagerCurrency)} {wager.wagerCurrency} diff --git a/src/components/PlayGameSection/PlayCoinFlipGameSection.tsx b/src/components/PlayGameSection/PlayCoinFlipGameSection.tsx index c8248ca..2adf53e 100644 --- a/src/components/PlayGameSection/PlayCoinFlipGameSection.tsx +++ b/src/components/PlayGameSection/PlayCoinFlipGameSection.tsx @@ -74,6 +74,7 @@ const PlayCoinFlipGameSection: React.FC = ({ wagerType: game.wager.wagerType, wagerAmount: game.wager.wagerAmount, gameType: game.gameType, + networkId: game.networkId, playerFlipChoices, hide: hideModal }) @@ -84,6 +85,7 @@ const PlayCoinFlipGameSection: React.FC = ({ wagerType: game.wager.wagerType, wagerAmount: game.wager.wagerAmount, gameType: game.gameType, + networkId: game.networkId, winnerFlipChoice: [playerFlipChoices.playerOne as AllPossibleCoinSides, playerFlipChoices.playerTwo as AllPossibleCoinSides][indexOfMaxValue], loserFlipChoice: [playerFlipChoices.playerOne as AllPossibleCoinSides, playerFlipChoices.playerTwo as AllPossibleCoinSides][indexOfMaxValue === 1 ? 0 : 1], hide: hideModal @@ -91,6 +93,7 @@ const PlayCoinFlipGameSection: React.FC = ({ } else { showModal(MODAL_TYPES.COINFLIP_LOSER_MODAL, { gameType: game.gameType, + networkId: game.networkId, winnerFlipChoice: [playerFlipChoices.playerOne as AllPossibleCoinSides, playerFlipChoices.playerTwo as AllPossibleCoinSides][indexOfMaxValue], loserFlipChoice: [playerFlipChoices.playerOne as AllPossibleCoinSides, playerFlipChoices.playerTwo as AllPossibleCoinSides][indexOfMaxValue === 1 ? 0 : 1], hide: hideModal diff --git a/src/components/PlayGameSection/PlayDiceGameSection.tsx b/src/components/PlayGameSection/PlayDiceGameSection.tsx index 9e44b92..78eecc3 100644 --- a/src/components/PlayGameSection/PlayDiceGameSection.tsx +++ b/src/components/PlayGameSection/PlayDiceGameSection.tsx @@ -97,6 +97,7 @@ const PlayDiceGameSection: React.FC= ({ wagerType: game.wager.wagerType, wagerAmount: game.wager.wagerAmount, gameType: game.gameType, + networkId: game.networkId, results: getWinnerAndLoserResults(), hide: hideModal, }); @@ -107,6 +108,7 @@ const PlayDiceGameSection: React.FC= ({ wagerType: game.wager.wagerType, wagerAmount: game.wager.wagerAmount, gameType: game.gameType, + networkId: game.networkId, results: getWinnerAndLoserResults(), hide: hideModal, }); @@ -114,6 +116,7 @@ const PlayDiceGameSection: React.FC= ({ showModal(MODAL_TYPES.DICE_LOSER_MODAL, { gameType: game.gameType, results: getWinnerAndLoserResults(), + networkId: game.networkId, hide: hideModal, }); } diff --git a/src/components/PlayGameSection/index.tsx b/src/components/PlayGameSection/index.tsx index 71a5bfa..37638f9 100644 --- a/src/components/PlayGameSection/index.tsx +++ b/src/components/PlayGameSection/index.tsx @@ -64,6 +64,7 @@ const PlayGameSection: React.FC = ({ escrowHash: escrowHash as HexishString, },); useEffect(() => { + console.log(players) gameResultsQuery.refetch(); refetchGameWinners() }, [players.length]); diff --git a/src/components/WegaGames/index.tsx b/src/components/WegaGames/index.tsx index d9a9ae5..e9b626e 100644 --- a/src/components/WegaGames/index.tsx +++ b/src/components/WegaGames/index.tsx @@ -84,6 +84,7 @@ export const PlayableGames: React.FC = ({ gamesCo setGameIds(sortedGameIds ?? []); } }, [data, gamesCount, isSuccess, defaultNetwork?.id]); + return !isLoading ? (
Date created @@ -102,7 +103,7 @@ export interface ClaimableGamesProps extends React.Attributes, React.HTMLAttribu userWalletAddress: HexishString; gamesCount: number; networkId: number; - } +} export const ClaimableGames: React.FC = ({ gamesCount, userWalletAddress, networkId, ...rest }: ClaimableGamesProps) => { const { data, isLoading, isSuccess } = useGetGamesQuery({ state: WegaState.COMPLETED, winners: userWalletAddress, networkId: networkId ?? defaultNetwork?.id }); const [sortedGames, setSortedGames] = useState(); diff --git a/src/containers/JoinGamePage/index.tsx b/src/containers/JoinGamePage/index.tsx index aa76073..071f6ed 100644 --- a/src/containers/JoinGamePage/index.tsx +++ b/src/containers/JoinGamePage/index.tsx @@ -9,7 +9,6 @@ import { useParams } from 'react-router-dom'; import MainContainer from '../../components/MainContainer'; import { BADGE_TEXTS } from "../../common/JoinableGameBar"; import { FloatingOrbs } from "../../common/FloatingOrbs" -import { formatEther } from 'ethers'; import 'twin.macro'; const JoinGamePage = () => { @@ -33,7 +32,7 @@ const JoinGamePage = () => { wagerType={game.wager.wagerType} currencyType={game.wager.wagerCurrency} gameType={game.gameType.toUpperCase() as AllPossibleWegaTypes} - wagerAmount={Number(formatEther(game.wager.wagerAmount))} + wagerAmount={game.wager.wagerAmount} gameUuid={game.uuid} escrowId={game.wager.wagerHash as HexishString} gameId={game.id} diff --git a/src/utils/abis.ts b/src/utils/abis.ts index 85a090e..800a696 100644 --- a/src/utils/abis.ts +++ b/src/utils/abis.ts @@ -1,4 +1,4 @@ -// Generated by @wagmi/cli@1.3.0 on 12/5/2023 at 3:08:33 PM +// Generated by @wagmi/cli@1.3.0 on 12/6/2023 at 5:46:37 PM ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // AccessControlUpgradeable @@ -521,7 +521,7 @@ export const enumerableMapABI = [ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** - * - [__View Contract on Polygon Polygon Scan__](https://polygonscan.com/address/0xE38d4530337a45C6D0C061f108e5AF040FCC175c) + * - [__View Contract on Polygon Polygon Scan__](https://polygonscan.com/address/0x679e91BAb4fA83c5d0543c460A41CEc52E6A6fd1) * - * - [__View Contract on Polygon Mumbai Polygon Scan__](https://mumbai.polygonscan.com/address/0xc392D90803D462Ac5395A76d59AB942a8d9DCe69) * - [__View Contract on Skale Calypso Nft Hub Testnet Skale Explorer__](https://staging-utter-unripe-menkar.explorer.staging-v3.skalenodes.com/address/0x0000000000000000000000000000000000000000) @@ -860,20 +860,20 @@ export const feeManagerABI = [ ] as const /** - * - [__View Contract on Polygon Polygon Scan__](https://polygonscan.com/address/0xE38d4530337a45C6D0C061f108e5AF040FCC175c) + * - [__View Contract on Polygon Polygon Scan__](https://polygonscan.com/address/0x679e91BAb4fA83c5d0543c460A41CEc52E6A6fd1) * - * - [__View Contract on Polygon Mumbai Polygon Scan__](https://mumbai.polygonscan.com/address/0xc392D90803D462Ac5395A76d59AB942a8d9DCe69) * - [__View Contract on Skale Calypso Nft Hub Testnet Skale Explorer__](https://staging-utter-unripe-menkar.explorer.staging-v3.skalenodes.com/address/0x0000000000000000000000000000000000000000) */ export const feeManagerAddress = { - 137: "0xE38d4530337a45C6D0C061f108e5AF040FCC175c", + 137: "0x679e91BAb4fA83c5d0543c460A41CEc52E6A6fd1", 1337: "0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0", 80001: "0xc392D90803D462Ac5395A76d59AB942a8d9DCe69", 344106930: "0x0000000000000000000000000000000000000000" } as const /** - * - [__View Contract on Polygon Polygon Scan__](https://polygonscan.com/address/0xE38d4530337a45C6D0C061f108e5AF040FCC175c) + * - [__View Contract on Polygon Polygon Scan__](https://polygonscan.com/address/0x679e91BAb4fA83c5d0543c460A41CEc52E6A6fd1) * - * - [__View Contract on Polygon Mumbai Polygon Scan__](https://mumbai.polygonscan.com/address/0xc392D90803D462Ac5395A76d59AB942a8d9DCe69) * - [__View Contract on Skale Calypso Nft Hub Testnet Skale Explorer__](https://staging-utter-unripe-menkar.explorer.staging-v3.skalenodes.com/address/0x0000000000000000000000000000000000000000) diff --git a/src/utils/ethers-helpers.ts b/src/utils/ethers-helpers.ts index 0a1c214..80a328d 100644 --- a/src/utils/ethers-helpers.ts +++ b/src/utils/ethers-helpers.ts @@ -15,8 +15,12 @@ export function parseIntFromBigNumber(val: BigNumberish | number) { } return val; } -export function exponentialToBigintInWei(val: number): bigint { - return toBigIntInWei(Number.parseFloat(String(val)).toFixed(18) as string); +export function exponentialToBigintInWei(val: number, decimals?: number): bigint { + if(decimals && decimals !== 18) { + return toBigIntInWei(Number.parseFloat(String(val)).toFixed(18) as string); + } else { + return toBigIntInWei(Number.parseFloat(String(val)).toString()); + } } export function formatLowerDecimalTokenValue(value: number, tokenDecimals: number) { @@ -46,6 +50,16 @@ export function parseTopicDataFromEventLog(txLog: { data: string, topics: Array< return interfaceIdFromAbi(eventAbi).parseLog({ data: txLog.data, topics: txLog.topics })?.args.toObject(); } +export function parseTopicDataFromEventLogs(txLogs: ({ data: string, topics: Array })[], eventAbi: string[]){ + let parsedData: any | undefined = undefined; + let i = 0; + while(!parsedData?.escrowHash) { + parsedData = interfaceIdFromAbi(eventAbi).parseLog({ data: txLogs[i].data, topics: txLogs[i].topics })?.args.toObject(); + i++; + } + return parsedData +} + export function isGameCreator( connectedPlayerUUid: string | undefined, players: Player | any, diff --git a/src/utils/index.ts b/src/utils/index.ts index 52589d6..fe244e9 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -5,6 +5,7 @@ export { miniWalletAddress, toBigIntInWei, parseTopicDataFromEventLog, + parseTopicDataFromEventLogs, interfaceIdFromAbi, convertBytesToNumber, format,