diff --git a/packages/client/src/mud/createSystemCalls.ts b/packages/client/src/mud/createSystemCalls.ts index 1c48bbb..5587ed1 100644 --- a/packages/client/src/mud/createSystemCalls.ts +++ b/packages/client/src/mud/createSystemCalls.ts @@ -11,6 +11,9 @@ import { ethers } from "ethers"; import { ClientComponents } from "./createClientComponents"; import { SetupNetworkResult } from "./setupNetwork"; +import IERC20Abi from "contracts/out/IERC20.sol/IERC20.abi.json"; +import ILapuVaultAbi from "contracts/out/ILapuVault.sol/ILapuVault.abi.json"; + export type SystemCalls = ReturnType; export function createSystemCalls( @@ -31,8 +34,21 @@ export function createSystemCalls( * through createClientComponents.ts, but it originates in * syncToRecs (https://github.com/latticexyz/mud/blob/26dabb34321eedff7a43f3fcb46da4f3f5ba3708/templates/react/packages/client/src/mud/setupNetwork.ts#L39). */ - { worldContract, waitForTransaction }: SetupNetworkResult, - { Counter, Position, Orientation, EntityType, OwnedBy }: ClientComponents + { + worldContract, + waitForTransaction, + publicClient, + walletClient, + worldAddress, + }: SetupNetworkResult, + { + Counter, + Position, + Orientation, + EntityType, + OwnedBy, + GameSetting, + }: ClientComponents ) { const defaultVector3 = new Vector3(1, 0, 3); @@ -196,6 +212,88 @@ export function createSystemCalls( return res; }; + const approveDaiToLapuVaultForTheConnectedPlayer = async (amount) => { + const gameSetting = await getComponentValue(GameSetting, singletonEntity); + const { request } = await publicClient.simulateContract({ + address: gameSetting?.daiAddress, + abi: IERC20Abi, + functionName: "approve", + args: [gameSetting?.lapuVaultAddress, amount], + account: walletClient?.account, + }); + const res = await walletClient.writeContract(request); + return res; + }; + + const approveLapuToMudWorldForTheConnectedPlayer = async (amount) => { + const gameSetting = await getComponentValue(GameSetting, singletonEntity); + const { request } = await publicClient.simulateContract({ + address: gameSetting?.lapuVaultAddress, + abi: IERC20Abi, + functionName: "approve", + args: [worldAddress, amount], + account: walletClient?.account, + }); + const res = await walletClient.writeContract(request); + return res; + }; + + const depositDaiToLapuVaultForTheConnectedPlayer = async (amount) => { + const gameSetting = await getComponentValue(GameSetting, singletonEntity); + const { request } = await publicClient.simulateContract({ + address: gameSetting?.lapuVaultAddress, + abi: ILapuVaultAbi, + functionName: "deposit", + args: [amount, walletClient?.account.address], + account: walletClient?.account, + }); + const res = await walletClient.writeContract(request); + return res; + }; + + const withdrawDaiFromLapuVaultForTheConnectedPlayer = async (amount) => { + const gameSetting = await getComponentValue(GameSetting, singletonEntity); + const { request } = await publicClient.simulateContract({ + address: gameSetting?.lapuVaultAddress, + abi: ILapuVaultAbi, + functionName: "withdraw", + args: [ + amount, + walletClient?.account.address, + walletClient?.account.address, + ], + account: walletClient?.account, + }); + const res = await walletClient.writeContract(request); + return res; + }; + + const mudDefiConsumesLapuFromPlayer = async (amount, playerAddress) => { + const tx = await worldContract.write.defiConsumesLapuFromPlayer([ + amount, + playerAddress, + ]); + await waitForTransaction(tx); + return tx; + }; + + const mudMockYieldGenerationFromDeFiPool = async (amount) => { + const tx = await worldContract.write.mockYieldGenerationFromDeFiPool([ + amount, + ]); + await waitForTransaction(tx); + return tx; + }; + + const mudMockReleaseRewardToPlayer = async (playerAddress, amount) => { + const tx = await worldContract.write.mockReleaseRewardToPlayer([ + playerAddress, + amount, + ]); + await waitForTransaction(tx); + return tx; + }; + return { increment, mudGetEntityType, @@ -211,5 +309,12 @@ export function createSystemCalls( mudDefiDaiBalanceOf, mudDefiLapuBalanceOf, mudDefiGetTotalRewardBalance, + approveDaiToLapuVaultForTheConnectedPlayer, + approveLapuToMudWorldForTheConnectedPlayer, + depositDaiToLapuVaultForTheConnectedPlayer, + withdrawDaiFromLapuVaultForTheConnectedPlayer, + mudDefiConsumesLapuFromPlayer, + mudMockYieldGenerationFromDeFiPool, + mudMockReleaseRewardToPlayer, }; } diff --git a/packages/client/src/mud/setupNetwork.ts b/packages/client/src/mud/setupNetwork.ts index c778066..89607af 100644 --- a/packages/client/src/mud/setupNetwork.ts +++ b/packages/client/src/mud/setupNetwork.ts @@ -137,5 +137,6 @@ export async function setupNetwork() { waitForTransaction, worldContract, write$: write$.asObservable().pipe(share()), + worldAddress: networkConfig.worldAddress as Hex, }; } diff --git a/packages/client/src/mudExample.tsx b/packages/client/src/mudExample.tsx index 4e075f1..4a61e97 100644 --- a/packages/client/src/mudExample.tsx +++ b/packages/client/src/mudExample.tsx @@ -4,31 +4,100 @@ import { singletonEntity } from "@latticexyz/store-sync/recs"; import { useMUD } from "./useMUD"; import { getState } from "./game/store"; -import { useState } from "react"; +import { useState, useEffect } from "react"; export const MudExample = () => { const { components: { Counter }, systemCalls: { - mudGetAllFacilityEntityMetadatas, - mudBuildFacility, - mudGetEntityMetadataAtPosition, mudDefiDaiBalanceOf, mudMockDaiFaucet, + approveDaiToLapuVaultForTheConnectedPlayer, + approveLapuToMudWorldForTheConnectedPlayer, + depositDaiToLapuVaultForTheConnectedPlayer, + withdrawDaiFromLapuVaultForTheConnectedPlayer, + mudDefiLapuBalanceOf, + mudDefiConsumesLapuFromPlayer, + mudDefiGetTotalRewardBalance, + mudMockYieldGenerationFromDeFiPool, + mudMockReleaseRewardToPlayer, }, } = useMUD(); + const defaultTestAmount = 1000; + const defaultConsumeAmount = 100; + const defaultYieldAmount = 50; + const defaultRewardAmount = 30; + const counter = useComponentValue(Counter, singletonEntity); const playerAddress = getState().player?.playerData?.address; const [playerDaiBalance, setPlayerDaiBalance] = useState(null); + const [playerLapuBalance, setPlayerLapuBalance] = useState( + null + ); + const [totalRewardBalance, setTotalRewardBalance] = useState( + null + ); + + useEffect(() => { + const refreshData = async () => { + const playerDaiBalance_ = (await mudDefiDaiBalanceOf( + playerAddress + )) as number; + setPlayerDaiBalance(playerDaiBalance_); + + const playerLapuBalance_ = (await mudDefiLapuBalanceOf( + playerAddress + )) as number; + setPlayerLapuBalance(playerLapuBalance_); + + const totalRewardBalance_ = + (await mudDefiGetTotalRewardBalance()) as number; + setTotalRewardBalance(totalRewardBalance_); + }; + + const refreshDataIntervalId = setInterval(refreshData, 1000); + return () => { + clearInterval(refreshDataIntervalId); + }; + }, [ + mudDefiDaiBalanceOf, + mudDefiLapuBalanceOf, + mudDefiGetTotalRewardBalance, + playerAddress, + ]); + + useEffect(() => { + const generateYieldIntervalId = setInterval(() => { + mudMockYieldGenerationFromDeFiPool(defaultYieldAmount); + }, 10000); + return () => { + clearInterval(generateYieldIntervalId); + }; + }, [mudMockYieldGenerationFromDeFiPool]); + + useEffect(() => { + const rewardPlayerIntervalId = setInterval(() => { + mudMockReleaseRewardToPlayer(playerAddress, defaultRewardAmount); + }, 15000); + return () => { + clearInterval(rewardPlayerIntervalId); + }; + }, [playerAddress, mudMockReleaseRewardToPlayer]); + + const delay = async (ms) => { + return new Promise((resolve) => setTimeout(resolve, ms)); + }; return (
- Player Address: {playerAddress ?? "??"} + Player balance: {playerDaiBalance?.toString() ?? "??"} DAI{" "} + {playerLapuBalance?.toString() ?? "??"} LAPU
- Player DAI balance: {playerDaiBalance ?? "??"} + Reward balance:{" "} + {totalRewardBalance?.toString() ?? "??"} LAPU
Counter: {counter?.value ?? "??"} @@ -40,25 +109,34 @@ export const MudExample = () => { event.preventDefault(); console.log( "mudMockDaiFaucet:", - await mudMockDaiFaucet(playerAddress, 1000) + await mudMockDaiFaucet(playerAddress, defaultTestAmount) ); const playerDaiBalance_ = (await mudDefiDaiBalanceOf( playerAddress )) as number; + console.log("playerDaiBalance_:", playerDaiBalance_); setPlayerDaiBalance(playerDaiBalance_); }} > - mudMockDaiFaucet + getDaiFromFaucet
); diff --git a/packages/contracts/test/DefiSystemtTest.t.sol b/packages/contracts/test/DefiSystemtTest.t.sol index 61d8255..63a33c2 100644 --- a/packages/contracts/test/DefiSystemtTest.t.sol +++ b/packages/contracts/test/DefiSystemtTest.t.sol @@ -54,7 +54,7 @@ contract DefiSystemTest is MudTest { assertEq(world.defiGetTotalRewardBalance(), amount02); vm.stopPrank(); - //5. mock yield generation from DeFi pool (which we can call periodically from client) + //5. mock yield generation from DeFi pool (which we can call periodically call from client) world.mockYieldGenerationFromDeFiPool(amount03); assertEq(world.defiGetTotalRewardBalance(), amount02 + amount03);