Skip to content

Commit

Permalink
Update and Sync ch-2 with last version Scaffold Stark
Browse files Browse the repository at this point in the history
  • Loading branch information
Nadai2010 committed Nov 21, 2024
1 parent 5cfa758 commit 9af45a9
Show file tree
Hide file tree
Showing 40 changed files with 3,004 additions and 1,924 deletions.
13 changes: 0 additions & 13 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -1,17 +1,4 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

DESIRED_COMMIT="46e0ec032956f0e7cbe0330f32b6b31eff824087"

cd packages/snfoundry/local-devnet

LAST_COMMIT=$(git log -1 --format="%H")

if [ "$LAST_COMMIT" != "$DESIRED_COMMIT" ]; then
echo "FAIL: Last local-devnet commit ($LAST_COMMIT) is not the desired ($DESIRED_COMMIT)."
exit 1
fi

cd -

npm run format:check
6 changes: 3 additions & 3 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
# Contributing to Scaffold-Stark

Thank you for your interest in contributing to Scaffold-Stark! Your support enhances this StarkNet-focused framework that bridges smart contract integration with web applications.
Thank you for your interest in contributing to Scaffold-Stark! Your support enhances this Starknet-focused framework that bridges smart contract integration with web applications.

## About the Project

**Scaffold-Stark** provides a full DApp development template, offering seamless integration of StarkNet smart contracts with web applications. **SpeedrunStark.com** offers interactive challenges that serve to practice your Cairo and StarkNet skills, learn how to use the provided hooks, and launch your applications swiftly with potential rewards.
**Scaffold-Stark** provides a full DApp development template, offering seamless integration of Starket smart contracts with web applications. **SpeedrunStark.com** offers interactive challenges that serve to practice your Cairo and Starknet skills, learn how to use the provided hooks, and launch your applications swiftly with potential rewards.

## Project Vision

Our goal is to simplify the DApp development and learning process, enabling developers to launch applications efficiently while understanding the intricacies of StarkNet.
Our goal is to simplify the DApp development and learning process, enabling developers to launch applications efficiently while understanding the intricacies of Starknet.

## How to Get Involved

Expand Down
1 change: 0 additions & 1 deletion packages/nextjs/.env

This file was deleted.

31 changes: 31 additions & 0 deletions packages/nextjs/app/api/price/[symbol]/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
export async function GET(
_: Request,
{ params: { symbol } }: { params: { symbol: string } },
) {
let apiUrl = "";
if (symbol === "ETH") {
apiUrl =
"https://api.coingecko.com/api/v3/simple/price?ids=ethereum&vs_currencies=usd";
} else if (symbol === "STRK") {
apiUrl =
"https://api.coingecko.com/api/v3/simple/price?ids=starknet&vs_currencies=usd";
} else {
return Response.json({
ethereum: { usd: 0 },
starknet: { usd: 0 },
});
}
try {
const response = await fetch(apiUrl);
if (!response.ok) {
throw new Error(`coingecko response status: ${response.status}`);
}
const json = await response.json();
return Response.json(json);
} catch (e) {
return Response.json({
ethereum: { usd: 0 },
starknet: { usd: 0 },
});
}
}
31 changes: 15 additions & 16 deletions packages/nextjs/app/debug/_components/contract/Array.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,15 @@ import { replacer } from "~~/utils/scaffold-stark/common";
import { ContractInput } from "./ContractInput";
import { Abi } from "abi-wan-kanabi";
import { parseGenericType } from "~~/utils/scaffold-stark";
import { FormErrorMessageState } from "./utilsDisplay";

type ArrayProps = {
abi: Abi;
abiParameter: AbiParameter;
parentForm: Record<string, any> | undefined;
setParentForm: (form: Record<string, any>) => void;
parentStateObjectKey: string;
setFormErrorMessage: Dispatch<SetStateAction<string | null>>;
setFormErrorMessage: Dispatch<SetStateAction<FormErrorMessageState>>;
};

export const ArrayInput = ({
Expand Down Expand Up @@ -67,23 +68,21 @@ export const ArrayInput = ({
| Record<string, any>
| ((arg: Record<string, any>) => void),
) => {
let nextInputObject: Record<string, any> = nextInputRecipe;
// if we find a function (a.k.a setState recipe), we run it to generate the next state based on recpe, else just use the object passed in
const nextInputObject: Record<string, any> =
typeof nextInputRecipe === "function"
? nextInputRecipe(parentForm!)
: nextInputRecipe;

// set state recipe function, handle
if (typeof nextInputRecipe === "function") {
nextInputObject = nextInputRecipe(parentForm!);
}

const currentInputArray = { ...inputArr };

// we do some nasty workaround
currentInputArray[index] =
nextInputObject?.[`input_${index}`] || null;

setInputArr(currentInputArray);
setInputArr((currentInputArray: any) => {
return {
...currentInputArray,
[index]: nextInputObject?.[index] || null,
};
});
}}
form={inputArr[index]}
stateObjectKey={`input_${index}`}
form={inputArr}
stateObjectKey={index}
paramType={
{
name: `${abiParameter.name}[${index}]`,
Expand Down
21 changes: 18 additions & 3 deletions packages/nextjs/app/debug/_components/contract/ContractInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,17 @@
import { Dispatch, SetStateAction } from "react";
import { InputBase, IntegerInput } from "~~/components/scaffold-stark";
import { AbiParameter } from "~~/utils/scaffold-stark/contract";
import { displayType } from "./utilsDisplay";
import {
addError,
clearError,
displayType,
FormErrorMessageState,
} from "./utilsDisplay";
import {
isCairoArray,
isCairoBigInt,
isCairoInt,
isCairoTuple,
isCairoType,
isCairoU256,
} from "~~/utils/scaffold-stark";
Expand All @@ -21,7 +27,7 @@ type ContractInputProps = {
form: Record<string, any> | undefined;
stateObjectKey: string;
paramType: AbiParameter;
setFormErrorMessage: Dispatch<SetStateAction<string | null>>;
setFormErrorMessage: Dispatch<SetStateAction<FormErrorMessageState>>;
};

export const ContractInput = ({
Expand Down Expand Up @@ -58,6 +64,11 @@ export const ContractInput = ({
setFormErrorMessage={setFormErrorMessage}
/>
);
}

// we prio tuples here to avoid wrong input
else if (isCairoTuple(paramType.type)) {
return <InputBase {...inputProps} />;
} else if (
isCairoInt(paramType.type) ||
isCairoBigInt(paramType.type) ||
Expand All @@ -68,7 +79,11 @@ export const ContractInput = ({
{...inputProps}
variant={paramType.type}
onError={(errMessage: string | null) =>
setFormErrorMessage(errMessage)
setFormErrorMessage((prev) => {
if (!!errMessage)
return addError(prev, "intError" + stateObjectKey, errMessage);
return clearError(prev, "intError" + stateObjectKey);
})
}
/>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
import { Abi } from "abi-wan-kanabi";
import {
AbiFunction,
Contract,
ContractName,
GenericContract,
InheritedFunctions,
getFunctionsByStateMutability,
} from "~~/utils/scaffold-stark/contract";
import { ReadOnlyFunctionForm } from "./ReadOnlyFunctionForm";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { Abi } from "abi-wan-kanabi";
import { Address } from "@starknet-react/chains";
import { useReadContract } from "@starknet-react/core";
import { BlockNumber } from "starknet";
import { displayTxResult } from "./utilsDisplay";
import { decodeContractResponse } from "./utilsDisplay";
import { useTheme } from "next-themes";

type DisplayVariableProps = {
Expand Down Expand Up @@ -85,7 +85,13 @@ export const DisplayVariable = ({
showAnimation ? "bg-warning rounded-sm animate-pulse-fast" : ""
}`}
>
{displayTxResult(result, false, abiFunction?.outputs)}
{decodeContractResponse({
resp: result,
abi,
functionOutputs: abiFunction?.outputs,
asText: true,
showAsString: true,
})}
</div>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,18 @@ import { useState, useRef, useEffect } from "react";
import { Abi } from "abi-wan-kanabi";
import { Address } from "@starknet-react/chains";
import {
displayTxResult,
getFunctionInputKey,
getInitialFormState,
getParsedContractFunctionArgs,
getArgsAsStringInputFromForm,
transformAbiFunction,
FormErrorMessageState,
isError,
getTopErrorMessage,
decodeContractResponse,
} from "~~/app/debug/_components/contract";
import { AbiFunction } from "~~/utils/scaffold-stark/contract";
import { BlockNumber } from "starknet";
import { useReadContract } from "@starknet-react/core";
import { useContract, useReadContract } from "@starknet-react/core";
import { ContractInput } from "./ContractInput";

type ReadOnlyFunctionFormProps = {
Expand All @@ -30,15 +33,21 @@ export const ReadOnlyFunctionForm = ({
getInitialFormState(abiFunction),
);
const [inputValue, setInputValue] = useState<any | undefined>(undefined);
const [formErrorMessage, setFormErrorMessage] = useState<string | null>(null);
const [formErrorMessage, setFormErrorMessage] =
useState<FormErrorMessageState>({});
const lastForm = useRef(form);

const { contract: contractInstance } = useContract({
abi,
address: contractAddress,
});

const { isFetching, data, refetch, error } = useReadContract({
address: contractAddress,
functionName: abiFunction.name,
abi: [...abi],
args: inputValue || [],
enabled: !!inputValue,
enabled: !!inputValue && !!contractInstance,
blockIdentifier: "pending" as BlockNumber,
});

Expand Down Expand Up @@ -66,8 +75,7 @@ export const ReadOnlyFunctionForm = ({
});

const handleRead = () => {
const newInputValue = getParsedContractFunctionArgs(form, false, true);

const newInputValue = getArgsAsStringInputFromForm(form);
if (JSON.stringify(form) !== JSON.stringify(lastForm.current)) {
setInputValue(newInputValue);
lastForm.current = form;
Expand All @@ -87,23 +95,28 @@ export const ReadOnlyFunctionForm = ({
<div className="bg-input text-sm px-4 py-1.5 break-words">
<p className="font-bold m-0 mb-1">Result:</p>
<pre className="whitespace-pre-wrap break-words">
{displayTxResult(data, false, abiFunction?.outputs)}
{decodeContractResponse({
resp: data,
abi,
functionOutputs: abiFunction?.outputs,
asText: true,
})}
</pre>
</div>
)}
</div>

<div
className={`flex ${
formErrorMessage &&
isError(formErrorMessage) &&
"tooltip before:content-[attr(data-tip)] before:right-[-10px] before:left-auto before:transform-none"
}`}
data-tip={`${formErrorMessage}`}
data-tip={`${getTopErrorMessage(formErrorMessage)}`}
>
<button
className="btn bg-gradient-dark btn-sm shadow-none border-none text-white"
onClick={handleRead}
disabled={(inputValue && isFetching) || !!formErrorMessage}
disabled={(inputValue && isFetching) || isError(formErrorMessage)}
>
{inputValue && isFetching && (
<span className="loading loading-spinner loading-xs"></span>
Expand Down
9 changes: 6 additions & 3 deletions packages/nextjs/app/debug/_components/contract/Struct.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@ import { AbiEnum, AbiStruct } from "~~/utils/scaffold-stark/contract";
import { replacer } from "~~/utils/scaffold-stark/common";
import { ContractInput } from "./ContractInput";
import { Abi } from "abi-wan-kanabi";
import { addError, clearError, FormErrorMessageState } from "./utilsDisplay";

type StructProps = {
abi?: Abi;
parentForm: Record<string, any> | undefined;
setParentForm: (form: Record<string, any>) => void;
parentStateObjectKey: string;
abiMember?: AbiStruct | AbiEnum;
setFormErrorMessage: Dispatch<SetStateAction<string | null>>;
setFormErrorMessage: Dispatch<SetStateAction<FormErrorMessageState>>;
};

export const Struct = ({
Expand Down Expand Up @@ -51,9 +52,11 @@ export const Struct = ({

// check for enum validity
if (values.filter((item) => (item || "").length > 0).length > 1) {
setFormErrorMessage("Enums can only have one defined value");
setFormErrorMessage((prev) =>
addError(prev, "enumError", "Enums can only have one active value"),
);
} else {
setFormErrorMessage(null);
setFormErrorMessage((prev) => clearError(prev, "enumError"));
}
}

Expand Down
20 changes: 17 additions & 3 deletions packages/nextjs/app/debug/_components/contract/TxReceipt.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
CheckCircleIcon,
DocumentDuplicateIcon,
} from "@heroicons/react/24/outline";
import { displayTxResult } from "~~/app/debug/_components/contract";
import { decodeContractResponse } from "~~/app/debug/_components/contract";

export const TxReceipt = (
txResult:
Expand All @@ -28,7 +28,14 @@ export const TxReceipt = (
/>
) : (
<CopyToClipboard
text={displayTxResult(txResult, false) as string}
text={
decodeContractResponse({
resp: txResult,
abi: [],
functionOutputs: [],
asText: true,
}) as string
}
onCopy={() => {
setTxResultCopied(true);
setTimeout(() => {
Expand All @@ -49,7 +56,14 @@ export const TxReceipt = (
<strong>Transaction Receipt</strong>
</div>
<div className="collapse-content overflow-auto bg-transparent rounded-t-none rounded-3xl">
<pre className="text-xs pt-4">{displayTxResult(txResult, false)}</pre>
<pre className="text-xs pt-4">
{decodeContractResponse({
resp: txResult,
abi: [],
functionOutputs: [],
asText: true,
})}
</pre>
</div>
</div>
</div>
Expand Down
Loading

0 comments on commit 9af45a9

Please sign in to comment.