generated from scaffold-eth/scaffold-eth-2
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
69d29b7
commit ce78234
Showing
19 changed files
with
1,372 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
"use client"; | ||
|
||
import React, { useEffect, useState } from "react"; | ||
import { ApolloClient, InMemoryCache, gql } from "@apollo/client"; | ||
|
||
interface Game { | ||
gameId: string; | ||
players: string[]; | ||
fighterIds: string[]; | ||
state: string; | ||
} | ||
|
||
interface QueryData { | ||
games: Game[]; | ||
} | ||
|
||
interface QueryError { | ||
message: string; | ||
} | ||
|
||
export function QueryGames() { | ||
const [games, setGames] = useState<Game[]>([]); | ||
const [loading, setLoading] = useState<boolean>(true); | ||
const [error, setError] = useState<QueryError | null>(null); | ||
|
||
const APIURL = "https://api.studio.thegraph.com/query/72991/scrollfighter/version/latest"; | ||
|
||
const tokensQuery = gql` | ||
query { | ||
games(first: 5) { | ||
gameId | ||
players | ||
fighterIds | ||
state | ||
} | ||
} | ||
`; | ||
|
||
const client = new ApolloClient({ | ||
uri: APIURL, | ||
cache: new InMemoryCache(), | ||
}); | ||
|
||
useEffect(() => { | ||
client | ||
.query<QueryData>({ | ||
query: tokensQuery, | ||
}) | ||
.then(response => { | ||
setGames(response.data.games); | ||
setLoading(false); | ||
}) | ||
.catch(err => { | ||
console.error("Error fetching data: ", err); | ||
setError(err); | ||
setLoading(false); | ||
}); | ||
}, []); | ||
|
||
if (loading) return <div>Loading...</div>; | ||
if (error) return <div>Error fetching data: {error.message}</div>; | ||
|
||
return ( | ||
<div> | ||
<h1>Games</h1> | ||
{games.map(game => ( | ||
<div key={game.gameId}> | ||
<h2>Game ID: {game.gameId}</h2> | ||
<p>Players: {game.players.join(", ")}</p> | ||
<p>Fighter IDs: {game.fighterIds.join(", ")}</p> | ||
<p>State: {game.state}</p> | ||
</div> | ||
))} | ||
</div> | ||
); | ||
} |
84 changes: 84 additions & 0 deletions
84
packages/nextjs/app/games/_components/contract/ContractInput.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
"use client"; | ||
|
||
import { Dispatch, SetStateAction } from "react"; | ||
import { Tuple } from "./Tuple"; | ||
import { TupleArray } from "./TupleArray"; | ||
import { AbiParameter } from "abitype"; | ||
import { | ||
AddressInput, | ||
Bytes32Input, | ||
BytesInput, | ||
InputBase, | ||
IntegerInput, | ||
IntegerVariant, | ||
} from "~~/components/scaffold-eth"; | ||
import { AbiParameterTuple } from "~~/utils/scaffold-eth/contract"; | ||
|
||
type ContractInputProps = { | ||
setForm: Dispatch<SetStateAction<Record<string, any>>>; | ||
form: Record<string, any> | undefined; | ||
stateObjectKey: string; | ||
paramType: AbiParameter; | ||
}; | ||
|
||
/** | ||
* Generic Input component to handle input's based on their function param type | ||
*/ | ||
export const ContractInput = ({ setForm, form, stateObjectKey, paramType }: ContractInputProps) => { | ||
const inputProps = { | ||
name: stateObjectKey, | ||
value: form?.[stateObjectKey], | ||
placeholder: paramType.name ? `${paramType.type} ${paramType.name}` : paramType.type, | ||
onChange: (value: any) => { | ||
setForm(form => ({ ...form, [stateObjectKey]: value })); | ||
}, | ||
}; | ||
|
||
const renderInput = () => { | ||
switch (paramType.type) { | ||
case "address": | ||
return <AddressInput {...inputProps} />; | ||
case "bytes32": | ||
return <Bytes32Input {...inputProps} />; | ||
case "bytes": | ||
return <BytesInput {...inputProps} />; | ||
case "string": | ||
return <InputBase {...inputProps} />; | ||
case "tuple": | ||
return ( | ||
<Tuple | ||
setParentForm={setForm} | ||
parentForm={form} | ||
abiTupleParameter={paramType as AbiParameterTuple} | ||
parentStateObjectKey={stateObjectKey} | ||
/> | ||
); | ||
default: | ||
// Handling 'int' types and 'tuple[]' types | ||
if (paramType.type.includes("int") && !paramType.type.includes("[")) { | ||
return <IntegerInput {...inputProps} variant={paramType.type as IntegerVariant} />; | ||
} else if (paramType.type.startsWith("tuple[")) { | ||
return ( | ||
<TupleArray | ||
setParentForm={setForm} | ||
parentForm={form} | ||
abiTupleParameter={paramType as AbiParameterTuple} | ||
parentStateObjectKey={stateObjectKey} | ||
/> | ||
); | ||
} else { | ||
return <InputBase {...inputProps} />; | ||
} | ||
} | ||
}; | ||
|
||
return ( | ||
<div className="flex flex-col gap-1.5 w-full"> | ||
<div className="flex items-center ml-2"> | ||
{paramType.name && <span className="text-xs font-medium mr-2 leading-none">{paramType.name}</span>} | ||
<span className="block text-xs font-extralight leading-none">{paramType.type}</span> | ||
</div> | ||
{renderInput()} | ||
</div> | ||
); | ||
}; |
43 changes: 43 additions & 0 deletions
43
packages/nextjs/app/games/_components/contract/ContractReadMethods.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import { Abi, AbiFunction } from "abitype"; | ||
import { ReadOnlyFunctionForm } from "~~/app/debug/_components/contract"; | ||
import { Contract, ContractName, GenericContract, InheritedFunctions } from "~~/utils/scaffold-eth/contract"; | ||
|
||
export const ContractReadMethods = ({ deployedContractData }: { deployedContractData: Contract<ContractName> }) => { | ||
if (!deployedContractData) { | ||
return null; | ||
} | ||
|
||
const functionsToDisplay = ( | ||
((deployedContractData.abi || []) as Abi).filter(part => part.type === "function") as AbiFunction[] | ||
) | ||
.filter(fn => { | ||
const isQueryableWithParams = | ||
(fn.stateMutability === "view" || fn.stateMutability === "pure") && fn.inputs.length > 0; | ||
return isQueryableWithParams; | ||
}) | ||
.map(fn => { | ||
return { | ||
fn, | ||
inheritedFrom: ((deployedContractData as GenericContract)?.inheritedFunctions as InheritedFunctions)?.[fn.name], | ||
}; | ||
}) | ||
.sort((a, b) => (b.inheritedFrom ? b.inheritedFrom.localeCompare(a.inheritedFrom) : 1)); | ||
|
||
if (!functionsToDisplay.length) { | ||
return <>No read methods</>; | ||
} | ||
|
||
return ( | ||
<> | ||
{functionsToDisplay.map(({ fn, inheritedFrom }) => ( | ||
<ReadOnlyFunctionForm | ||
abi={deployedContractData.abi as Abi} | ||
contractAddress={deployedContractData.address} | ||
abiFunction={fn} | ||
key={fn.name} | ||
inheritedFrom={inheritedFrom} | ||
/> | ||
))} | ||
</> | ||
); | ||
}; |
104 changes: 104 additions & 0 deletions
104
packages/nextjs/app/games/_components/contract/ContractUI.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
"use client"; | ||
|
||
// @refresh reset | ||
import { useReducer } from "react"; | ||
import { ContractReadMethods } from "./ContractReadMethods"; | ||
import { ContractVariables } from "./ContractVariables"; | ||
import { ContractWriteMethods } from "./ContractWriteMethods"; | ||
import { Address, Balance } from "~~/components/scaffold-eth"; | ||
import { useDeployedContractInfo, useNetworkColor } from "~~/hooks/scaffold-eth"; | ||
import { useTargetNetwork } from "~~/hooks/scaffold-eth/useTargetNetwork"; | ||
import { ContractName } from "~~/utils/scaffold-eth/contract"; | ||
|
||
type ContractUIProps = { | ||
contractName: ContractName; | ||
className?: string; | ||
}; | ||
|
||
/** | ||
* UI component to interface with deployed contracts. | ||
**/ | ||
export const ContractUI = ({ contractName, className = "" }: ContractUIProps) => { | ||
const [refreshDisplayVariables, triggerRefreshDisplayVariables] = useReducer(value => !value, false); | ||
const { targetNetwork } = useTargetNetwork(); | ||
const { data: deployedContractData, isLoading: deployedContractLoading } = useDeployedContractInfo(contractName); | ||
const networkColor = useNetworkColor(); | ||
|
||
if (deployedContractLoading) { | ||
return ( | ||
<div className="mt-14"> | ||
<span className="loading loading-spinner loading-lg"></span> | ||
</div> | ||
); | ||
} | ||
|
||
if (!deployedContractData) { | ||
return ( | ||
<p className="text-3xl mt-14"> | ||
{`No contract found by the name of "${contractName}" on chain "${targetNetwork.name}"!`} | ||
</p> | ||
); | ||
} | ||
|
||
return ( | ||
<div className={`grid grid-cols-1 lg:grid-cols-6 px-6 lg:px-10 lg:gap-12 w-full max-w-7xl my-0 ${className}`}> | ||
<div className="col-span-5 grid grid-cols-1 lg:grid-cols-3 gap-8 lg:gap-10"> | ||
<div className="col-span-1 flex flex-col"> | ||
<div className="bg-base-100 border-base-300 border shadow-md shadow-secondary rounded-3xl px-6 lg:px-8 mb-6 space-y-1 py-4"> | ||
<div className="flex"> | ||
<div className="flex flex-col gap-1"> | ||
<span className="font-bold">{contractName}</span> | ||
<Address address={deployedContractData.address} /> | ||
<div className="flex gap-1 items-center"> | ||
<span className="font-bold text-sm">Balance:</span> | ||
<Balance address={deployedContractData.address} className="px-0 h-1.5 min-h-[0.375rem]" /> | ||
</div> | ||
</div> | ||
</div> | ||
{targetNetwork && ( | ||
<p className="my-0 text-sm"> | ||
<span className="font-bold">Network</span>:{" "} | ||
<span style={{ color: networkColor }}>{targetNetwork.name}</span> | ||
</p> | ||
)} | ||
</div> | ||
<div className="bg-base-300 rounded-3xl px-6 lg:px-8 py-4 shadow-lg shadow-base-300"> | ||
<ContractVariables | ||
refreshDisplayVariables={refreshDisplayVariables} | ||
deployedContractData={deployedContractData} | ||
/> | ||
</div> | ||
</div> | ||
<div className="col-span-1 lg:col-span-2 flex flex-col gap-6"> | ||
<div className="z-10"> | ||
<div className="bg-base-100 rounded-3xl shadow-md shadow-secondary border border-base-300 flex flex-col mt-10 relative"> | ||
<div className="h-[5rem] w-[5.5rem] bg-base-300 absolute self-start rounded-[22px] -top-[38px] -left-[1px] -z-10 py-[0.65rem] shadow-lg shadow-base-300"> | ||
<div className="flex items-center justify-center space-x-2"> | ||
<p className="my-0 text-sm">Read</p> | ||
</div> | ||
</div> | ||
<div className="p-5 divide-y divide-base-300"> | ||
<ContractReadMethods deployedContractData={deployedContractData} /> | ||
</div> | ||
</div> | ||
</div> | ||
<div className="z-10"> | ||
<div className="bg-base-100 rounded-3xl shadow-md shadow-secondary border border-base-300 flex flex-col mt-10 relative"> | ||
<div className="h-[5rem] w-[5.5rem] bg-base-300 absolute self-start rounded-[22px] -top-[38px] -left-[1px] -z-10 py-[0.65rem] shadow-lg shadow-base-300"> | ||
<div className="flex items-center justify-center space-x-2"> | ||
<p className="my-0 text-sm">Write</p> | ||
</div> | ||
</div> | ||
<div className="p-5 divide-y divide-base-300"> | ||
<ContractWriteMethods | ||
deployedContractData={deployedContractData} | ||
onChange={triggerRefreshDisplayVariables} | ||
/> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
); | ||
}; |
50 changes: 50 additions & 0 deletions
50
packages/nextjs/app/games/_components/contract/ContractVariables.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
import { DisplayVariable } from "./DisplayVariable"; | ||
import { Abi, AbiFunction } from "abitype"; | ||
import { Contract, ContractName, GenericContract, InheritedFunctions } from "~~/utils/scaffold-eth/contract"; | ||
|
||
export const ContractVariables = ({ | ||
refreshDisplayVariables, | ||
deployedContractData, | ||
}: { | ||
refreshDisplayVariables: boolean; | ||
deployedContractData: Contract<ContractName>; | ||
}) => { | ||
if (!deployedContractData) { | ||
return null; | ||
} | ||
|
||
const functionsToDisplay = ( | ||
(deployedContractData.abi as Abi).filter(part => part.type === "function") as AbiFunction[] | ||
) | ||
.filter(fn => { | ||
const isQueryableWithNoParams = | ||
(fn.stateMutability === "view" || fn.stateMutability === "pure") && fn.inputs.length === 0; | ||
return isQueryableWithNoParams; | ||
}) | ||
.map(fn => { | ||
return { | ||
fn, | ||
inheritedFrom: ((deployedContractData as GenericContract)?.inheritedFunctions as InheritedFunctions)?.[fn.name], | ||
}; | ||
}) | ||
.sort((a, b) => (b.inheritedFrom ? b.inheritedFrom.localeCompare(a.inheritedFrom) : 1)); | ||
|
||
if (!functionsToDisplay.length) { | ||
return <>No contract variables</>; | ||
} | ||
|
||
return ( | ||
<> | ||
{functionsToDisplay.map(({ fn, inheritedFrom }) => ( | ||
<DisplayVariable | ||
abi={deployedContractData.abi as Abi} | ||
abiFunction={fn} | ||
contractAddress={deployedContractData.address} | ||
key={fn.name} | ||
refreshDisplayVariables={refreshDisplayVariables} | ||
inheritedFrom={inheritedFrom} | ||
/> | ||
))} | ||
</> | ||
); | ||
}; |
Oops, something went wrong.