Skip to content

Commit

Permalink
Merge pull request #164 from moonstream-to/fetching-improvements
Browse files Browse the repository at this point in the history
Fetching improvements
  • Loading branch information
Anton-Mushnin authored Mar 14, 2024
2 parents 357c845 + 1bfdf22 commit 2e14baa
Show file tree
Hide file tree
Showing 5 changed files with 101 additions and 74 deletions.
116 changes: 76 additions & 40 deletions web/src/components/playing/PlayView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { OwnedToken, Token } from "../../types";
import Outcome from "./Outcome";
import InviteLink from "./InviteLink";
import FullcountABIImported from "../../web3/abi/FullcountABI.json";
import TokenABIImported from "../../web3/abi/BLBABI.json";
import { AbiItem } from "web3-utils";
import { FULLCOUNT_ASSETS_PATH, ZERO_ADDRESS } from "../../constants";
import { getTokenMetadata } from "../../utils/decoders";
Expand All @@ -17,8 +18,10 @@ import TokenView from "../tokens/TokenView";
import PitcherViewMobile from "./PitcherViewMobile";
import BatterViewMobile from "./BatterViewMobile";
import styles from "./PlayView.module.css";
import { getMulticallResults } from "../../utils/multicall";

const FullcountABI = FullcountABIImported as unknown as AbiItem[];
const TokenABI = TokenABIImported as unknown as AbiItem[];

export function getRowCol(index: number): [number, number] {
const size = 5; // Size of the grid (5x5)
Expand Down Expand Up @@ -69,7 +72,14 @@ const PlayView = ({ selectedToken }: { selectedToken: Token }) => {
const [isShowOutcomeDone, setIsShowOutcomeDone] = useState(false);
const [isSmallView] = useMediaQuery("(max-width: 1023px)");

const { selectedAtBat, selectedSession, updateContext, contractAddress } = useGameContext();
const {
tokensCache,
secondsPerPhase,
selectedAtBat,
selectedSession,
updateContext,
contractAddress,
} = useGameContext();
const web3ctx = useContext(Web3Context);
const gameContract = new web3ctx.web3.eth.Contract(FullcountABI) as any;
gameContract.options.address = contractAddress;
Expand All @@ -94,20 +104,20 @@ const PlayView = ({ selectedToken }: { selectedToken: Token }) => {
refetchInterval: 100000000,
onSuccess: (data) => {
console.log("sessionAtBatID success: ", data);
atBatStatus.refetch();
},
},
);

const queryClient = useQueryClient();

const atBatStatus = useQuery(
["atBatStatus", atBat.data],
["atBatStatus", atBat.data?.progress],
async () => {
if (!atBat.data) {
console.log("!atBat.data");
return;
}
console.log("atBatStatus");
console.log("atBatStatus", atBat.data);

const atBatID = atBat.data;
const status = await gameContract.methods.getAtBat(atBatID).call();
Expand Down Expand Up @@ -141,35 +151,40 @@ const PlayView = ({ selectedToken }: { selectedToken: Token }) => {
},
);

useEffect(() => {
console.log(
"atBatStatus.data, isShowOutcomeDone useEffect: ",
atBatStatus.data,
isShowOutcomeDone,
"sessionID: ",
sessionID,
);
if (isShowOutcomeDone && atBatStatus.data?.currentSessionID) {
if (Number(atBatStatus.data.currentSessionID) !== sessionStatus.data?.sessionID) {
setSessionID(atBatStatus.data.currentSessionID);
setIsShowOutcomeDone(false);
}
}
}, [atBatStatus.data, isShowOutcomeDone]);

const sessionStatus = useQuery(
["session", selectedSession, atBatStatus.data, sessionID],
async () => {
console.log("sessionStatus");
if (!selectedSession) return undefined;
const id = sessionID ?? selectedSession.sessionID;
const progress = Number(await gameContract.methods.sessionProgress(id).call());
const session = await gameContract.methods.getSession(id).call();
if (!secondsPerPhase) {
const secondsPerPhaseRes = Number(await gameContract.methods.SecondsPerPhase().call());
updateContext({ secondsPerPhase: secondsPerPhaseRes });
}
const queries = [
{
target: gameContract.options.address,
callData: gameContract.methods.sessionProgress(id).encodeABI(),
},
{
target: gameContract.options.address,
callData: gameContract.methods.getSession(id).encodeABI(),
},
];
const [progresses, sessions] = await getMulticallResults(
FullcountABI,
["sessionProgress", "getSession"],
queries,
);
const progress = Number(progresses[0]);
const session = sessions[0];

if (progress < 2 || progress > 4) {
setGameOver(true);
} else {
setGameOver(false);
}

const pitcherAddress = session.pitcherNFT.nftAddress;
const pitcherTokenID = session.pitcherNFT.tokenID;
const batterAddress = session.batterNFT.nftAddress;
Expand All @@ -188,17 +203,22 @@ const PlayView = ({ selectedToken }: { selectedToken: Token }) => {
? { address: pitcherAddress, id: pitcherTokenID }
: { address: batterAddress, id: batterTokenID };
if (otherToken.address !== ZERO_ADDRESS && !(otherToken.address === opponent?.address)) {
tokenContract.options.address = otherToken.address;
const URI = await tokenContract.methods.tokenURI(otherToken.id).call();
const staker = await tokenContract.methods.ownerOf(otherToken.id).call();
const tokenMetadata = await getTokenMetadata(URI);

setOpponent({
...otherToken,
staker,
image: tokenMetadata.image,
name: tokenMetadata.name.split(` - ${otherToken.id}`)[0],
});
const tokenFromCache = tokensCache.find(
(token) => token.address === otherToken.address && token.id === otherToken.id,
);
if (!tokenFromCache) {
tokenContract.options.address = otherToken.address;
const URI = await tokenContract.methods.tokenURI(otherToken.id).call();
const tokenMetadata = await getTokenMetadata(URI);
setOpponent({
...otherToken,
staker: "0x",
image: tokenMetadata.image,
name: tokenMetadata.name.split(` - ${otherToken.id}`)[0],
});
} else {
setOpponent({ ...tokenFromCache });
}
}

const {
Expand All @@ -214,8 +234,6 @@ const PlayView = ({ selectedToken }: { selectedToken: Token }) => {
batterLeftSession,
} = session;

const secondsPerPhase = Number(await gameContract.methods.SecondsPerPhase().call());

let isExpired = progress === 6;
if (progress === 3 || progress === 4) {
const currentTime = Math.floor(Date.now() / 1000); // Convert to seconds
Expand All @@ -240,7 +258,6 @@ const PlayView = ({ selectedToken }: { selectedToken: Token }) => {
batterLeftSession,
outcome,
phaseStartTimestamp: Number(phaseStartTimestamp),
secondsPerPhase: Number(secondsPerPhase),
isExpired,
pitcherReveal: {
speed,
Expand All @@ -261,6 +278,7 @@ const PlayView = ({ selectedToken }: { selectedToken: Token }) => {
console.log("sessionStatus success: ", data);
},
refetchInterval: 3000,
retry: false,
},
);

Expand All @@ -270,9 +288,27 @@ const PlayView = ({ selectedToken }: { selectedToken: Token }) => {
}, [selectedToken, opponent]);

useEffect(() => {
console.log("sessionStatus.data useEffect:", sessionStatus.data);
atBatStatus.refetch();
}, [sessionStatus.data]);
console.log("sessionStatus.data useEffect:", sessionStatus.data?.progress);
if (sessionStatus.data) {
atBatStatus.refetch();
}
}, [sessionStatus.data?.progress]);

useEffect(() => {
console.log(
"atBatStatus.data, isShowOutcomeDone useEffect: ",
atBatStatus.data,
isShowOutcomeDone,
"sessionID: ",
sessionID,
);
if (isShowOutcomeDone && atBatStatus.data?.currentSessionID) {
if (Number(atBatStatus.data.currentSessionID) !== sessionStatus.data?.sessionID) {
setSessionID(atBatStatus.data.currentSessionID);
setIsShowOutcomeDone(false);
}
}
}, [atBatStatus.data, isShowOutcomeDone]);

const numberToOrdinal = (n: number): string => {
if (n > 10) return "";
Expand Down Expand Up @@ -360,7 +396,7 @@ const PlayView = ({ selectedToken }: { selectedToken: Token }) => {
balls={atBatStatus.data?.balls ?? 3}
strikes={atBatStatus.data?.strikes ?? 2}
start={Number(sessionStatus.data?.phaseStartTimestamp)}
delay={sessionStatus.data?.secondsPerPhase}
delay={secondsPerPhase ?? 300}
isActive={
sessionStatus.data?.progress === 3 ||
sessionStatus.data?.progress === 4 ||
Expand Down
2 changes: 2 additions & 0 deletions web/src/contexts/GameContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ interface GameContextProps {
sessionOffset: number;
soundVolume: number;
ownedTokens: OwnedToken[];
secondsPerPhase: number | undefined;
}

interface GameContextType extends GameContextProps {
Expand Down Expand Up @@ -62,6 +63,7 @@ export const GameContextProvider: FC<ProviderProps> = ({ children }) => {
sessionOffset: 40,
soundVolume: 20,
ownedTokens: [],
secondsPerPhase: undefined,
});

useEffect(() => {
Expand Down
31 changes: 12 additions & 19 deletions web/src/tokenInterfaces/BLBTokenAPI.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export const fetchOwnedBLBTokens = async ({
return [];
}
try {
const { tokenContract } = getContracts(web3ctx);
const { tokenContract } = getContracts();
const balanceOf = await tokenContract.methods.balanceOf(web3ctx.account).call();
const tokensQueries = [];
for (let i = 0; i < balanceOf; i += 1) {
Expand All @@ -32,12 +32,7 @@ export const fetchOwnedBLBTokens = async ({
});
}

const [tokens] = await getMulticallResults(
web3ctx,
TokenABI,
["tokenOfOwnerByIndex"],
tokensQueries,
);
const [tokens] = await getMulticallResults(TokenABI, ["tokenOfOwnerByIndex"], tokensQueries);
return await getTokensData({
web3ctx,
tokens: tokens.map((t) => ({ id: t, address: TOKEN_CONTRACT })),
Expand All @@ -58,13 +53,12 @@ export const getTokensData = async ({
tokens: TokenId[];
tokensSource: TokenSource;
}) => {
const { tokenContract, gameContract } = getContracts(web3ctx);
const { tokenContract, gameContract } = getContracts();
const stakedQueries = tokens.map((t) => ({
target: gameContract.options.address,
callData: gameContract.methods.StakedSession(t.address, t.id).encodeABI(),
}));
const [stakedSessions] = await getMulticallResults(
web3ctx,
FullcountABI,
["StakedSession"],
stakedQueries,
Expand All @@ -76,7 +70,6 @@ export const getTokensData = async ({
}));

const [progresses] = await getMulticallResults(
web3ctx,
FullcountABI,
["sessionProgress"],
progressQueries,
Expand All @@ -87,7 +80,7 @@ export const getTokensData = async ({
callData: tokenContract.methods.tokenURI(t.id).encodeABI(),
}));

const [uris] = await getMulticallResults(web3ctx, TokenABI, ["tokenURI"], uriQueries);
const [uris] = await getMulticallResults(TokenABI, ["tokenURI"], uriQueries);

const promises = uris.map(async (uri, idx) => {
const { name, image } = await getTokenMetadata(uri);
Expand Down Expand Up @@ -118,7 +111,7 @@ export const startSessionBLB = ({
role: number;
requireSignature: boolean;
}): Promise<{ sessionID: string; sign: string | undefined }> => {
const { gameContract } = getContracts(web3ctx);
const { gameContract } = getContracts();

return sendTransactionWithEstimate(
web3ctx.account,
Expand Down Expand Up @@ -146,7 +139,7 @@ export const joinSessionBLB = ({
sessionID: number;
inviteCode: string | undefined;
}) => {
const { gameContract } = getContracts(web3ctx);
const { gameContract } = getContracts();
return sendTransactionWithEstimate(
web3ctx.account,
gameContract.methods.joinSession(
Expand All @@ -164,7 +157,7 @@ export const unstakeBLBToken = ({
web3ctx: MoonstreamWeb3ProviderInterface;
token: OwnedToken;
}) => {
const { gameContract } = getContracts(web3ctx);
const { gameContract } = getContracts();

if (token.tokenProgress === 2 && token.stakedSessionID) {
return sendTransactionWithEstimate(
Expand All @@ -189,7 +182,7 @@ export const commitSwingBLBToken = ({
sign: string;
sessionID: number;
}) => {
const { gameContract } = getContracts(web3ctx);
const { gameContract } = getContracts();

return sendTransactionWithEstimate(
web3ctx.account,
Expand All @@ -212,7 +205,7 @@ export const revealSwingBLBToken = ({
horizontal: number;
sessionID: number;
}) => {
const { gameContract } = getContracts(web3ctx);
const { gameContract } = getContracts();
return sendTransactionWithEstimate(
web3ctx.account,
gameContract.methods.revealSwing(sessionID, nonce, actionChoice, vertical, horizontal),
Expand All @@ -228,7 +221,7 @@ export const commitPitchBLBToken = ({
sign: string;
sessionID: number;
}) => {
const { gameContract } = getContracts(web3ctx);
const { gameContract } = getContracts();

return sendTransactionWithEstimate(
web3ctx.account,
Expand All @@ -251,7 +244,7 @@ export const revealPitchBLBToken = ({
horizontal: number;
sessionID: number;
}) => {
const { gameContract } = getContracts(web3ctx);
const { gameContract } = getContracts();
return sendTransactionWithEstimate(
web3ctx.account,
gameContract.methods.revealPitch(sessionID, nonce, actionChoice, vertical, horizontal),
Expand All @@ -267,6 +260,6 @@ export const mintBLBToken = ({
name: string;
imageIndex: number;
}) => {
const { tokenContract } = getContracts(web3ctx);
const { tokenContract } = getContracts();
return sendTransactionWithEstimate(web3ctx.account, tokenContract.methods.mint(name, imageIndex));
};
14 changes: 5 additions & 9 deletions web/src/utils/getWeb3Contracts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@ import { AbiItem } from "web3-utils";
import FullcountABIImported from "../web3/abi/FullcountABI.json";
import TokenABIImported from "../web3/abi/BLBABI.json";
import MulticallABIImported from "../web3/abi/Multicall2.json";
import { MoonstreamWeb3ProviderInterface } from "../types/Moonstream";
import Web3 from "web3";

const FullcountABI = FullcountABIImported as unknown as AbiItem[];
const TokenABI = TokenABIImported as unknown as AbiItem[];
const MulticallABI = MulticallABIImported as unknown as AbiItem[];

export const getContracts = (web3ctx: MoonstreamWeb3ProviderInterface) => {
const { web3 } = web3ctx;
export const getContracts = () => {
const web3 = new Web3(RPC);
const gameContract = new web3.eth.Contract(FullcountABI) as unknown as FullcountContract;
gameContract.options.address = GAME_CONTRACT;
const tokenContract = new web3.eth.Contract(TokenABI);
Expand All @@ -34,13 +34,9 @@ export const getContracts = (web3ctx: MoonstreamWeb3ProviderInterface) => {
return { gameContract, tokenContract, multicallContract };
};

export const getMulticallContract = (web3ctx: MoonstreamWeb3ProviderInterface) => {
export const getMulticallContract = () => {
const web3 = new Web3(RPC);
const MULTICALL2_CONTRACT_ADDRESS =
MULTICALL2_CONTRACT_ADDRESSES[String(CHAIN_ID) as keyof typeof MULTICALL2_CONTRACT_ADDRESSES];
const multicallContract = new web3.eth.Contract(
MulticallABI,
MULTICALL2_CONTRACT_ADDRESS,
) as unknown as Multicall2;
return multicallContract;
return new web3.eth.Contract(MulticallABI, MULTICALL2_CONTRACT_ADDRESS) as unknown as Multicall2;
};
Loading

0 comments on commit 2e14baa

Please sign in to comment.