Skip to content

Commit

Permalink
feat: successfully migrate coinflip to new abis
Browse files Browse the repository at this point in the history
  • Loading branch information
RasenGUY committed Nov 29, 2023
1 parent cac3f89 commit e616c54
Show file tree
Hide file tree
Showing 18 changed files with 345 additions and 169 deletions.
1 change: 1 addition & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
// } else {
// document.documentElement.classList.remove('dark');
// }
const htmlElement = document.documentElement;
if(htmlElement && !htmlElement.classList.contains('dark')) htmlElement.classList.add('dark');
</script>
</head>
Expand Down
23 changes: 12 additions & 11 deletions src/components/CoinFlip/animations.ts
Original file line number Diff line number Diff line change
@@ -1,33 +1,34 @@
import { useLayoutEffect, useState } from 'react';
import { gsap } from 'gsap';

// eslint-disable-next-line no-unused-vars
type Callback = (...args: any[]) => void | null;

export function useRoll(coinRef: any) {
const [trigger, setStrigger] = useState<boolean>(false);
const [rolled, setRolled] = useState<boolean>(false);
const [animationTarget, setAnimationTarget] = useState<string | undefined>(undefined);

function roll(to: string) {
const callb = () => {
gsap.fromTo("g#all-sides", {
ease: "power4.inOut",
duration: 0.5,
y: "0",
}, {y: to})
const callb: Callback = () => {
gsap.set("g#all-sides", { y: "0" })
gsap.fromTo("g#all-sides", {
ease: "power4.inOut",
duration: 0.5,
y: "0",
}, {y: to})
setTimeout(() => setRolled(true), 2000);
}
gsap.set("g#all-sides", {y: "0"})
const tl = gsap.timeline({ repeatDelay: 0, onComplete: callb })
tl.to("g#all-sides", {
repeat: 10,
ease: "none",
y: "300",
})
}
const triggerRoll = (rollDestination: number, isGameOver: boolean) => {
const triggerRoll = (rollDestination: number) => {
setAnimationTarget(String(rollDestination * 100));
setStrigger(s => !s);
if(isGameOver){
setTimeout(() => setRolled(true), 4000);
}
};

useLayoutEffect(()=> {
Expand Down
24 changes: 14 additions & 10 deletions src/components/CreateGameCard/CreateCoinFlipGameCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,14 @@ import { ErrorMessage } from '@hookform/error-message';
import { ArrowDownIcon, StarLoaderIcon } from '../../assets/icons';
import tw from 'twin.macro';
import { useForm } from 'react-hook-form';
import { useCreateGameParams, useNavigateTo, useWegaStore } from '../../hooks';
import { useCreateGameParams, useNavigateTo, useWegaStore, useTokenUSDValue } from '../../hooks';
import {
useCreateWagerAndDepositMutation,
useAllowanceQuery,
useApproveERC20Mutation,
} from './blockchainApiSlice';
import { useCreateGameMutation } from '../../containers/App/api';
import { toastSettings, toBigIntInWei, escrowConfig, parseTopicDataFromEventLog } from '../../utils';
import { useCreateGameMutation, useGetRandomNumberQuery } from './apiSlice';
import { toastSettings, toBigIntInWei, escrowConfig, parseTopicDataFromEventLog, convertBytesToNumber } from '../../utils';
import Button from '../../common/Button';
import { ToggleWagerBadge } from '../../common/ToggleWagerBadge';
import { useFormReveal } from './animations';
Expand All @@ -67,6 +67,8 @@ export const CreateCoinFlipGameCard = ({
const { wallet, network, user} = useWegaStore();
const formRef = useRef<HTMLFormElement>(null);
const detailsBlock = useRef<HTMLDivElement>(null)
const randomnessQuery = useGetRandomNumberQuery(undefined);

const [currentWagerType] = useState<AllPossibleWagerTypes>(wagerType);
const [currentCurrencyType, setCurrentCurrencyType] = useState<AllPossibleCurrencyTypes>(currencyType);
const [currentCoinSide, setCurrentCoinSide] = useState<AllPossibleCoinSides>(CoinSideTypes[CoinSideTypesEnum.HEADS]);
Expand All @@ -85,6 +87,7 @@ export const CreateCoinFlipGameCard = ({
});

// approval for allowance
const wagerUSDValue = useTokenUSDValue(currentCurrencyType, watch('wager'));
const isWagerApproved = (allowance: number, wagerAmount: number) => allowance >= wagerAmount;
const allowanceQuery = useAllowanceQuery({
spender: escrowConfig.address[network?.id as keyof typeof escrowConfig.address],
Expand Down Expand Up @@ -113,20 +116,20 @@ export const CreateCoinFlipGameCard = ({
await approveERC20({
spender: escrowConfig.address[network?.id as keyof typeof escrowConfig.address], wagerAsBigint: toBigIntInWei(wager), tokenAddress }).unwrap();
}
const receipt = await createWagerAndDeposit({ tokenAddress, wagerAsBigint: toBigIntInWei(wager), gameType }).unwrap();
const parsedTopicData = parseTopicDataFromEventLog(receipt.logs[3], ['event GameCreation(bytes32 indexed escrowHash, uint256 indexed nonce, address creator, string name)']);

const receipt = await createWagerAndDeposit({ tokenAddress, wagerAsBigint: toBigIntInWei(wager), gameType, randomness: [convertBytesToNumber(randomnessQuery.data?.randomness)] }).unwrap();
const parsedTopicData = parseTopicDataFromEventLog(receipt.logs[2], ['event GameCreation(bytes32 indexed escrowHash, uint256 indexed nonce, address creator, string name)']);
await createGame({
gameType,
players: [ { uuid: playerUuid } ],
creatorUuid: playerUuid,
networkId: network?.id as number,
wager: {
wagerType: currentWagerType.toUpperCase() as AllPossibleWagerTypes,
wagerHash: parsedTopicData?.escrowHash,
tokenAddress,
wagerAmount: parseEther(String(wager)).toString(),
wagerCurrency: currentCurrencyType,
nonce: parsedTopicData?.nonce.toNumber(),
nonce: Number(parsedTopicData?.nonce),
},
gameAttributes: [{ key: "players[0].flipChoice", value: currentCoinSide.toString()}]
}).unwrap();
Expand All @@ -145,8 +148,10 @@ export const CreateCoinFlipGameCard = ({

const navigateToGameUi = useNavigateTo()
useEffect(() => {
console.log(gameType);
if(wallet){
allowanceQuery.refetch();
randomnessQuery.refetch();
if(createGameStatus === 'fulfilled' && createGameResponse) {
navigateToGameUi(`/${gameType.toLowerCase()}/play/${createGameResponse.uuid}`, 1500, { replace: true,
state: { gameId: createGameResponse.id, gameUuid: createGameResponse.uuid } });
Expand All @@ -155,12 +160,11 @@ export const CreateCoinFlipGameCard = ({
}, [
watch('wager'),
tokenAddress,
isWagerApproved,
createGameStatus,
createGameResponse
]);

return (
return tokenAddress && playerAddress && playerUuid && randomnessQuery.data && (
<form
tw="w-full flex flex-col justify-center items-center"
onSubmit={handleSubmit(handleCreateGameClick)}
Expand All @@ -181,7 +185,7 @@ export const CreateCoinFlipGameCard = ({
name="wager"
render={({ message }) => <NormalText tw="text-[#E11D48]">{message}</NormalText> }
/>
<NormalText tw="dark:text-shinishi">00,00 USD</NormalText>
<NormalText tw="dark:text-shinishi">{wagerUSDValue.loading ? 'loading...' : wagerUSDValue.value} USD</NormalText>
<SmallText> Balance: {
isWagerbalanceLoading ? "Retrieving balance..." : userWagerBalance?.formatted + ' ' + userWagerBalance?.symbol
} </SmallText>
Expand Down
3 changes: 2 additions & 1 deletion src/components/CreateGameCard/CreateDiceGameCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ export const CreateDiceGameCard = ({
gameType,
players: [ { uuid: playerUuid } ],
creatorUuid: playerUuid,
networkId: network?.id as number,
wager: {
wagerType: currentWagerType.toUpperCase() as AllPossibleWagerTypes,
wagerHash: parsedTopicData?.escrowHash,
Expand Down Expand Up @@ -166,7 +167,7 @@ export const CreateDiceGameCard = ({
createGameStatus,
createGameResponse
]);
return (
return tokenAddress && playerAddress && playerUuid && randomnessQuery.data && (
<form
tw="w-full flex flex-row justify-center"
onSubmit={handleSubmit(handleCreateGameClick)}
Expand Down
8 changes: 5 additions & 3 deletions src/components/CreateGameCard/apiSlice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,19 @@ import {

export const createGameApiSlice = appApiSlice.injectEndpoints({
endpoints: (builder) => ({
createGame: builder.mutation<Wega, Partial<Wega> & Pick<Wega, 'creatorUuid'> & Pick<Wega, 'wager'> & Pick<Wega, 'gameType'> & Pick<Wega, 'gameAttributes'> & Partial<Player>>({
query: ({ wager, players, gameType, creatorUuid, gameAttributes }: {
createGame: builder.mutation<Wega,
Partial<Wega> & Pick<Wega, 'creatorUuid'> & Pick<Wega, 'wager'> & Pick<Wega, 'gameType'> & Pick<Wega, 'networkId'> & Pick<Wega, 'gameAttributes'> & Partial<Player>>({
query: ({ wager, players, gameType, creatorUuid, gameAttributes, networkId }: {
wager: Wager,
players: Player[],
gameType: AllPossibleWegaTypes,
creatorUuid: string;
gameAttributes?: WegaAttributes;
networkId: number;
}) => ({
url: '/games',
method: 'POST',
body: { wager, players, gameType, creatorUuid, gameAttributes }
body: { wager, players, gameType, creatorUuid, gameAttributes , networkId }
}),
}),
getRandomNumber: builder.query({
Expand Down
1 change: 1 addition & 0 deletions src/components/Dice/animations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export function useRoll(diceRef: any, onBegin?: Callback, onEnd?: Callback) {


function roll(to: string) {
console.log('ROLLING TO', to);
if(onBegin) onBegin();
const callb = () => {
gsap.fromTo("g#all-sides", {
Expand Down
44 changes: 30 additions & 14 deletions src/components/JoinGameCard/JoinCoinFlipGameCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,21 +27,26 @@ import {
renderGameTypeBadge,
BADGE_TEXTS
} from "../../common/JoinableGameBar";
import {
useConnectModal,
} from '@rainbow-me/rainbowkit';
import { joiResolver } from '@hookform/resolvers/joi';
import { ErrorMessage } from '@hookform/error-message';
import { ArrowDownIcon, StarLoaderIcon } from '../../assets/icons';
import tw from 'twin.macro';
import { useForm } from 'react-hook-form';
import { useBalance } from 'wagmi';
import { useNavigateTo } from '../../hooks';
import { useNavigateTo, useCreateGameParams, useWegaStore, useTokenUSDValue } from '../../hooks';
import { useDepositAndJoinCoinflipMutation } from './blockchainApiSlice';
import { useAllowanceQuery, useApproveERC20Mutation } from '../CreateGameCard/blockchainApiSlice';
import toast from 'react-hot-toast';
import { toastSettings, escrowConfig, toBigIntInWei } from '../../utils';
import { toastSettings, escrowConfig, toBigIntInWei, convertBytesToNumber } from '../../utils';
import Button from '../../common/Button';
import { useFormReveal } from '../CreateGameCard/animations';
import { useJoinGameMutation, useUpdateGameMutation } from '../../containers/App/api';
import { useJoinGameMutation, useUpdateGameMutation } from './apiSlice';
import { ToggleCoinFlipSides } from '../../common/ToggleCoinFlipSides';
import { useGetRandomNumberQuery } from '../CreateGameCard/apiSlice';



export interface JoinCoinFlipGameCardProps extends React.Attributes, React.AllHTMLAttributes<HTMLDivElement> {
Expand All @@ -62,29 +67,28 @@ export interface JoinCoinFlipGameCardProps extends React.Attributes, React.AllHT
const JoinCoinFlipGameCard = ({
wagerType,
currencyType,
tokenAddress,
playerAddress,
gameUuid,
playerUuid,
gameType,
wagerAmount,
escrowId,
gameId,
gameAttributes,
network,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
css,
...rest
}: JoinCoinFlipGameCardProps) => {

const { openConnectModal } = useConnectModal();
const { wallet, user, network } = useWegaStore();
const randomnessQuery = useGetRandomNumberQuery(undefined);
const {tokenAddress, playerAddress, playerUuid} = useCreateGameParams({ wallet, user, network}); // TODO change to generic name
const formRef = useRef<HTMLFormElement>(null);
const detailsBlock = useRef<HTMLDivElement>(null)
const [currentWagerType] = useState<AllPossibleWagerTypes>(wagerType);
const [currentCurrencyType] = useState<AllPossibleCurrencyTypes>(currencyType);
const {revealed, triggerRevealAnimation} = useFormReveal(false, formRef, detailsBlock);
const [currentCoinSide] = useState<AllPossibleCoinSides>(gameAttributes && Number(gameAttributes[0].value) === 1 ? 2 : 1);

const { register, formState: { errors }, handleSubmit } = useForm({
const { register, formState: { errors }, handleSubmit, watch } = useForm({
mode: 'onChange',
resolver: joiResolver(createGameSchema('wager', wagerAmount)) ,
reValidateMode: 'onChange',
Expand All @@ -94,9 +98,10 @@ const JoinCoinFlipGameCard = ({
});

// approval for allowance
const wagerUSDValue = useTokenUSDValue(currentCurrencyType, watch('wager'));
const isWagerApproved = (allowance: number, wagerAmount: number) => allowance >= wagerAmount;
const allowanceQuery = useAllowanceQuery({
spender: escrowConfig.address[network.id as keyof typeof escrowConfig.address],
spender: escrowConfig.address[network?.id as keyof typeof escrowConfig.address],
owner: playerAddress,
tokenAddress,
});
Expand All @@ -115,10 +120,10 @@ const JoinCoinFlipGameCard = ({
const handleDepositWagerClick = async () => {
try {
if(!isWagerApproved(allowanceQuery.data, wagerAmount)) {
await approveERC20({ spender: escrowConfig.address[network.id as keyof typeof escrowConfig.address], wagerAsBigint: toBigIntInWei(wagerAmount), tokenAddress }).unwrap();
await approveERC20({ spender: escrowConfig.address[network?.id as keyof typeof escrowConfig.address], wagerAsBigint: toBigIntInWei(wagerAmount), tokenAddress }).unwrap();
}
const playerChoices = [Number(gameAttributes[0].value), currentCoinSide];
await depositAndJoinCoinflip({escrowHash: escrowId, playerChoices }).unwrap();
await depositAndJoinCoinflip({escrowHash: escrowId, playerChoices, randomness: [convertBytesToNumber(randomnessQuery.data?.randomness)] }).unwrap();
await joinGame({ newPlayerUuid: playerUuid, gameUuid }).unwrap();
await updateGame({
uuid: gameUuid,
Expand All @@ -145,7 +150,10 @@ const JoinCoinFlipGameCard = ({
const navigateToGameUi = useNavigateTo()
useEffect(() => {
allowanceQuery.refetch();
}, [tokenAddress, wagerAmount, isWagerApproved]);
}, [
tokenAddress,
wagerAmount
]);

return (
<form
Expand Down Expand Up @@ -175,7 +183,7 @@ const JoinCoinFlipGameCard = ({
name="wager"
render={({ message }) => <NormalText tw="text-[#E11D48]">{message}</NormalText> }
/>
<NormalText tw="dark:text-shinishi">00,00 USD</NormalText>
<NormalText tw="dark:text-shinishi">{wagerUSDValue.loading ? 'loading...' : wagerUSDValue.value} USD</NormalText>
<SmallText> Balance: {
isWagerbalanceLoading ? "Retrieving balance..." : userWagerBalance?.formatted + ' ' + userWagerBalance?.symbol
} </SmallText>
Expand All @@ -186,6 +194,14 @@ const JoinCoinFlipGameCard = ({
</div>
{/* <Button buttonType="primary"><>Approve</></Button> */}
{
(!wallet && openConnectModal) ? <Button buttonType="primary" tw="flex" onClick={
(e: any) => {
e.preventDefault();
openConnectModal();
}}>
{"Play game"}
<StarLoaderIcon loading={false} color="#151515" tw="h-[16px] w-[16px] ms-[5px]" />
</Button> :
<Button type="submit" buttonType="primary" tw="flex">
{(
approveERC20Query.isLoading ||
Expand Down
Loading

0 comments on commit e616c54

Please sign in to comment.