Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 23 additions & 3 deletions src/components/ContractFunctions/AccountFunctions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,20 @@ import { useAirkit } from "../../hooks/useAirkit";
import { isUrl } from "../../utils";
import { Button } from "../common/Button";
import { useLogging } from "../../hooks/useLogging";
import { useState } from "react";

export const AccountFunctions = () => {
const { airService } = useAirkit();
const { addresses, address } = useAccount();
const { data: balance } = useBalance({ address });
const { setLog } = useLogging();
const [loadingStates, setLoadingStates] = useState<Record<string, boolean>>(
{}
);

const setLoading = (key: string, loading: boolean) => {
setLoadingStates((prev) => ({ ...prev, [key]: loading }));
};

const getUserInfo = async () => {
try {
Expand Down Expand Up @@ -129,7 +137,7 @@ export const AccountFunctions = () => {
}
};

const ACCOUNT_FUNCTIONS: Record<string, () => void> = {
const ACCOUNT_FUNCTIONS: Record<string, () => Promise<void> | void> = {
"Get User Info": getUserInfo,
"Get Accounts": getAccounts,
"Get Account Balance": getAccountBalance,
Expand All @@ -147,8 +155,20 @@ export const AccountFunctions = () => {
<h2 className="text-2xl font-bold">Account Functions</h2>
<div className="grid grid-cols-2 gap-2">
{Object.entries(ACCOUNT_FUNCTIONS).map(([key, value]) => (
<Button key={key} onClick={value} variant="outline">
{key}
<Button
key={key}
onClick={async () => {
setLoading(key, true);
try {
await value();
} finally {
setLoading(key, false);
}
}}
variant="outline"
disabled={loadingStates[key]}
>
{loadingStates[key] ? "Loading..." : key}
</Button>
))}
</div>
Expand Down
55 changes: 41 additions & 14 deletions src/components/ContractFunctions/ContractFunctions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,19 @@ import {
MOCK_ERC721_CONTRACT,
} from "../../utils/constants";
import { Button } from "../common/Button";
import { useMemo } from "react";
import { useMemo, useState } from "react";

export const ContractFunctions = () => {
const { setLog } = useLogging();
const { address } = useAccount();
const config = useConfig();
const [loadingStates, setLoadingStates] = useState<Record<string, boolean>>(
{}
);

const setLoading = (key: string, loading: boolean) => {
setLoadingStates((prev) => ({ ...prev, [key]: loading }));
};

const data = useMemo(
() =>
Expand Down Expand Up @@ -92,12 +99,16 @@ export const ContractFunctions = () => {
};

const balanceOfTokenFn = async () => {
const { data: result } = await refetchErc20Balance();
if (typeof result !== "bigint") {
setLog("No balance of token", "info");
return;
try {
const { data: result } = await refetchErc20Balance();
if (typeof result !== "bigint") {
setLog("No balance of token", "info");
return;
}
setLog(`Balance of token: ${formatEther(result)}`, "info");
} catch (error) {
setLog(`Error getting balance: ${error}`, "error");
}
setLog(`Balance of token: ${formatEther(result)}`, "info");
};

const mintMockERC721Fn = async () => {
Expand All @@ -115,12 +126,16 @@ export const ContractFunctions = () => {
};

const balanceOfERC721Fn = async () => {
const { data: result } = await refetchErc721Balance();
if (typeof result !== "bigint") {
setLog("No balance of token", "info");
return;
try {
const { data: result } = await refetchErc721Balance();
if (typeof result !== "bigint") {
setLog("No balance of token", "info");
return;
}
setLog(`Balance of token: ${result}`, "info");
} catch (error) {
setLog(`Error getting balance: ${error}`, "error");
}
setLog(`Balance of token: ${result}`, "info");
};

const multicallFn = async () => {
Expand All @@ -147,7 +162,7 @@ export const ContractFunctions = () => {
}
};

const CONTRACT_FUNCTIONS: Record<string, () => void> = {
const CONTRACT_FUNCTIONS: Record<string, () => Promise<void> | void> = {
"Estimate Gas (transfer)": estimateGasForTransferTokenFn,
"mint (ERC20)": mintMockTokenFn,
"transfer (ERC20)": transferTokenFn,
Expand All @@ -162,8 +177,20 @@ export const ContractFunctions = () => {
<h2 className="text-2xl font-bold">Contract Functions</h2>
<div className="grid grid-cols-2 gap-2">
{Object.entries(CONTRACT_FUNCTIONS).map(([key, value]) => (
<Button key={key} onClick={value} variant="outline">
{key}
<Button
key={key}
onClick={async () => {
setLoading(key, true);
try {
await value();
} finally {
setLoading(key, false);
}
}}
variant="outline"
disabled={loadingStates[key]}
>
{loadingStates[key] ? "Loading..." : key}
</Button>
))}
</div>
Expand Down
9 changes: 7 additions & 2 deletions src/components/ContractFunctions/SigningFunctions.tsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,32 @@
import { useSignMessage } from "wagmi";
import { Button } from "../common/Button";
import { useLogging } from "../../hooks/useLogging";
import { useState } from "react";

export const SigningFunctions = () => {
const { signMessageAsync } = useSignMessage();
const { setLog } = useLogging();
const [loading, setLoading] = useState(false);

const signMessageFn = async () => {
setLoading(true);
try {
const message = "Hello, World!";
const signature = await signMessageAsync({ message });
setLog(`Signature: ${signature}`, "success");
} catch (error) {
setLog(`Error: ${error}`, "error");
} finally {
setLoading(false);
}
};

return (
<div className="flex flex-col gap-2 mt-4">
<h2 className="text-2xl font-bold">Signing Functions</h2>
<div className="grid grid-cols-2 gap-2">
<Button onClick={signMessageFn} variant="outline">
Sign Message
<Button onClick={signMessageFn} variant="outline" disabled={loading}>
{loading ? "Loading..." : "Sign Message"}
</Button>
</div>
</div>
Expand Down
38 changes: 27 additions & 11 deletions src/components/common/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,32 @@ type ButtonProps = {
variant?: "primary" | "danger" | "outline";
} & React.ButtonHTMLAttributes<HTMLButtonElement>;

const getVariantStyles = (
variant: NonNullable<ButtonProps["variant"]>,
disabled: boolean = false
) => {
const baseStyles = "p-2 rounded-md cursor-pointer";

const variantStyles = {
primary: "bg-blue-500 text-white",
danger: "bg-red-400 text-white",
outline: "border border-gray-300 text-black",
} satisfies Record<typeof variant, string>;

const hoverStyles = {
primary: "hover:bg-blue-400",
danger: "hover:bg-red-500",
outline: "hover:bg-gray-100",
} satisfies Record<typeof variant, string>;

return cn(
baseStyles,
variantStyles[variant],
!disabled && hoverStyles[variant],
disabled && "opacity-50 cursor-not-allowed"
);
};

export const Button: FC<ButtonProps> = ({
children,
onClick,
Expand All @@ -18,17 +44,7 @@ export const Button: FC<ButtonProps> = ({
}) => {
return (
<button
className={cn(
"text-white p-2 rounded-md hover:bg-blue-400 cursor-pointer",
variant === "primary" && "bg-blue-500 hover:bg-blue-400",
variant === "danger" && "bg-red-400 hover:bg-red-500",
variant === "outline" &&
"border border-gray-300 text-black hover:bg-gray-100",
{
"opacity-50 cursor-not-allowed": disabled,
},
className
)}
className={cn(getVariantStyles(variant, disabled), className)}
onClick={onClick}
disabled={disabled}
{...props}
Expand Down