Skip to content

Commit

Permalink
sync
Browse files Browse the repository at this point in the history
  • Loading branch information
0xquantum3labs committed Apr 26, 2024
2 parents 60aeb0d + d4ed5c8 commit d6868d5
Show file tree
Hide file tree
Showing 15 changed files with 402 additions and 80 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ Then download the challenge to your computer and install dependencies by running
git clone https://github.com/Quantum3-Labs/speedrunstark.git --recurse-submodules challenge-0-simple-nft
cd challenge-0-simple-nft
git checkout simple-nft-example
>>>>>>> challenge-base
yarn install
```

Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
"use client";

import { useState } from "react";
import { useState, useRef } from "react";
import { Abi } from "abi-wan-kanabi";
import { Address } from "@starknet-react/chains";
import {
// ContractInput,
displayTxResult,
getFunctionInputKey,
getInitialFormState,
Expand All @@ -19,52 +18,56 @@ import { ContractInput } from "./ContractInput";
type ReadOnlyFunctionFormProps = {
contractAddress: Address;
abiFunction: AbiFunction;
// inheritedFrom?: string;
abi: Abi;
};

export const ReadOnlyFunctionForm = ({
contractAddress,
abiFunction,
// inheritedFrom,
abi,
}: ReadOnlyFunctionFormProps) => {
const [form, setForm] = useState<Record<string, any>>(() =>
getInitialFormState(abiFunction),
);
const [inputValue, setInputValue] = useState<any>();
const [inputValue, setInputValue] = useState<any | undefined>(undefined);
const lastForm = useRef(form);

const { isLoading, isFetching, data } = useContractRead({
const { isFetching, data, refetch } = useContractRead({
address: contractAddress,
functionName: abiFunction.name,
abi: [...abi],
args: inputValue,
enabled: false, // TODO : notify when failed - add error
enabled: false,
blockIdentifier: "pending" as BlockNumber,
});

const transformedFunction = transformAbiFunction(abiFunction);
const inputElements = transformedFunction.inputs.map((input, inputIndex) => {
const key = getFunctionInputKey(abiFunction.name, input, inputIndex);
return (
<ContractInput
key={key}
setForm={(updatedFormValue) => {
setInputValue(undefined);
setForm(updatedFormValue);
}}
setForm={setForm}
form={form}
stateObjectKey={key}
paramType={input}
/>
);
});

const handleRead = async () => {
const newInputValue = getParsedContractFunctionArgs(form);
if (JSON.stringify(form) === JSON.stringify(lastForm.current)) {
await refetch();
} else {
setInputValue(newInputValue);
lastForm.current = form;
}
};

return (
<div className="flex flex-col gap-3 py-5 first:pt-0 last:pb-1">
<p className="font-medium my-0 break-words">
{abiFunction.name}
{/* <InheritanceTooltip inheritedFrom={inheritedFrom} /> */}
</p>
<p className="font-medium my-0 break-words">{abiFunction.name}</p>
{inputElements}
<div className="flex justify-between gap-2 flex-wrap">
<div className="flex-grow w-4/5">
Expand All @@ -78,13 +81,11 @@ export const ReadOnlyFunctionForm = ({
)}
</div>
<button
className="btn btn-secondary btn-sm bg-primary text-neutral-content"
onClick={async () => {
setInputValue(getParsedContractFunctionArgs(form));
}}
disabled={!isLoading && isFetching}
className="btn btn-secondary btn-sm"
onClick={handleRead}
disabled={inputValue && isFetching}
>
{!isLoading && isFetching && (
{inputValue && isFetching && (
<span className="loading loading-spinner loading-xs"></span>
)}
Read 📡
Expand Down
5 changes: 4 additions & 1 deletion packages/nextjs/components/Footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
MagnifyingGlassIcon,
} from "@heroicons/react/24/outline";
import { Faucet } from "./scaffold-stark";
import { getBlockExplorerLink } from "~~/utils/scaffold-stark";

/**
* Site footer
Expand Down Expand Up @@ -39,7 +40,9 @@ export const Footer = () => {
<>
<Faucet />
<Link
href="/blockexplorer"
href={getBlockExplorerLink(targetNetwork)}
target={"_blank"}
rel={"noopener noreferrer"}
passHref
className="btn btn-primary btn-sm font-normal gap-1 text-base-100 border-base-100 "
>
Expand Down
1 change: 0 additions & 1 deletion packages/nextjs/components/MenuItem/MenuItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ interface MenuItemProps {
}

const MenuItem: React.FC<MenuItemProps> = ({ link, isActive }) => {
// console.log({ isActive }, link.label);
return (
<li key={link.href}>
<Link
Expand Down
22 changes: 6 additions & 16 deletions packages/nextjs/components/scaffold-stark/Balance.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@

import { useState } from "react";
import { Address } from "@starknet-react/chains";
import { useBalance } from "@starknet-react/core";
import { useTargetNetwork } from "~~/hooks/scaffold-stark/useTargetNetwork";
import { useGlobalState } from "~~/services/store/store";
import useScaffoldEthBalance from "~~/hooks/scaffold-stark/useScaffoldEthBalance";

type BalanceProps = {
address?: Address;
Expand All @@ -17,17 +16,8 @@ type BalanceProps = {
*/
export const Balance = ({ address, className = "", usdMode }: BalanceProps) => {
const { targetNetwork } = useTargetNetwork();

const price = useGlobalState((state) => state.nativeCurrencyPrice);
const {
data: balance,
isError,
isLoading,
} = useBalance({
address,
watch: true,
});

const { price, balance, usdValue, isLoading, isError } =
useScaffoldEthBalance({ address });
const [displayUsdMode, setDisplayUsdMode] = useState(
price > 0 ? Boolean(usdMode) : false,
);
Expand Down Expand Up @@ -59,7 +49,7 @@ export const Balance = ({ address, className = "", usdMode }: BalanceProps) => {
);
}

const formattedBalance = balance ? Number(balance.formatted) : 0;
//const formattedBalance = balance ? Number(balance.formatted) : 0;

return (
<button
Expand All @@ -71,15 +61,15 @@ export const Balance = ({ address, className = "", usdMode }: BalanceProps) => {
<>
<span className="text-[0.8em] font-bold mr-1">$</span>
<span>
{(formattedBalance * price).toLocaleString("en-US", {
{usdValue.toLocaleString("en-US", {
minimumFractionDigits: 2,
maximumFractionDigits: 2,
})}
</span>
</>
) : (
<>
<span>{formattedBalance.toFixed(4)}</span>
<span>{balance}</span>
<span className="text-[0.8em] font-bold ml-1">
{targetNetwork.nativeCurrency.symbol}
</span>
Expand Down
14 changes: 5 additions & 9 deletions packages/nextjs/components/scaffold-stark/FaucetButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ import { useState } from "react";
import { BanknotesIcon } from "@heroicons/react/24/outline";
import { mintEth } from "~~/services/web3/faucet";
import { Address, devnet } from "@starknet-react/chains";
import { useAccount, useBalance, useNetwork } from "@starknet-react/core";
import { useAccount } from "@starknet-react/core";
import { useTargetNetwork } from "~~/hooks/scaffold-stark/useTargetNetwork";
import useScaffoldEthBalance from "~~/hooks/scaffold-stark/useScaffoldEthBalance";

// Number of ETH faucet sends to an address
const NUM_OF_ETH = "1";
Expand All @@ -15,11 +16,7 @@ const NUM_OF_ETH = "1";
*/
export const FaucetButton = () => {
const { address } = useAccount();
const { data: balance, refetch } = useBalance({
address,
watch: true,
refetchInterval: 4500,
});
const { balance } = useScaffoldEthBalance({ address });

const { targetNetwork } = useTargetNetwork();

Expand All @@ -33,7 +30,6 @@ export const FaucetButton = () => {
try {
setLoading(true);
await mintEth(address as Address, NUM_OF_ETH);
await refetch();
setLoading(false);
} catch (error) {
console.error("⚡️ ~ file: FaucetButton.tsx:sendETH ~ error", error);
Expand All @@ -42,11 +38,11 @@ export const FaucetButton = () => {
};

// Render only on local chain
if (targetNetwork.id !== devnet.id) {
if (targetNetwork.id !== devnet.id || address == undefined) {
return null;
}

const isBalanceZero = balance && balance.value === 0n;
const isBalanceZero = balance && balance === "0";

return (
<div
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ export const useScaffoldContractWrite = <
const writeTx = useTransactor();
const { targetNetwork } = useTargetNetwork();

// Memoize the ABI function retrieval
const abiFunction = useMemo(
() =>
getFunctionsByStateMutability(
Expand All @@ -47,7 +46,6 @@ export const useScaffoldContractWrite = <
[deployedContractData?.abi, functionName],
);

// Memoize parsing function parameters
const parsedParams = useMemo(() => {
if (args && abiFunction) {
return parseFunctionParams(abiFunction, args as any[]);
Expand Down Expand Up @@ -126,8 +124,6 @@ export const useScaffoldContractWrite = <

return {
...wagmiContractWrite,
// isMining,
// Overwrite wagmi's write async
writeAsync: sendContractWriteTx,
};
};
50 changes: 50 additions & 0 deletions packages/nextjs/hooks/scaffold-stark/useScaffoldEthBalance.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { useGlobalState } from "~~/services/store/store";
import { useEffect, useState } from "react";
import { useContractRead } from "@starknet-react/core";
import ethAbi, { ethContractAddress, ethDecimals } from "~~/utils/eth";
import { BlockNumber, uint256 } from "starknet";
import { Address } from "@starknet-react/chains";

type UseScaffoldEthBalanceProps = {
address?: Address | string;
};

const useScaffoldEthBalance = ({ address }: UseScaffoldEthBalanceProps) => {
const price = useGlobalState((state) => state.nativeCurrencyPrice);
const [balance, setBalance] = useState("0");

const { data, ...props } = useContractRead({
address: ethContractAddress,
watch: true,
abi: ethAbi,
functionName: "balanceOf",
args: [address as string],
blockIdentifier: "pending" as BlockNumber,
});

useEffect(() => {
// @ts-ignore
if (data && data.balance !== undefined) {
// @ts-ignore
const balanceBigInt = uint256.uint256ToBN(data.balance);
const integerPart = balanceBigInt / ethDecimals;
const remainder = balanceBigInt % ethDecimals;

const remainderStr = remainder
.toString()
.padStart(ethDecimals.toString().length, "0");
const decimalPart = remainderStr.slice(0, 4);

setBalance(`${integerPart}.${decimalPart}`);
}
}, [data]);

return {
price,
balance,
usdValue: parseFloat(balance) * price,
...props,
};
};

export default useScaffoldEthBalance;
Loading

0 comments on commit d6868d5

Please sign in to comment.