Skip to content

Commit 8e5a5f0

Browse files
authored
Refactor contract tabs (#156)
* fix * fix
1 parent d067248 commit 8e5a5f0

16 files changed

Lines changed: 561 additions & 720 deletions

File tree

.storybook/preview.tsx

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,22 @@
11
import { withThemeByClassName } from "@storybook/addon-themes";
22
import type { Preview } from "@storybook/react-vite";
3+
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
4+
import React from "react";
35
import "../tailwind.css";
46
import { ClipboardProvider } from "../components/providers/clipboard-provider";
57

8+
const queryClient = new QueryClient({
9+
defaultOptions: {
10+
queries: {
11+
retry: false,
12+
refetchOnWindowFocus: false,
13+
},
14+
mutations: {
15+
retry: false,
16+
},
17+
},
18+
});
19+
620
const preview: Preview = {
721
parameters: {
822
controls: {
@@ -22,11 +36,13 @@ const preview: Preview = {
2236
defaultTheme: "light",
2337
}),
2438
(Story) => (
25-
<div className="p-4 dark:bg-background">
26-
<ClipboardProvider>
27-
<Story />
28-
</ClipboardProvider>
29-
</div>
39+
<QueryClientProvider client={queryClient}>
40+
<div className="p-4 dark:bg-background">
41+
<ClipboardProvider>
42+
<Story />
43+
</ClipboardProvider>
44+
</div>
45+
</QueryClientProvider>
3046
),
3147
],
3248
};

components/contract-execution/contract-execution-tabs/function-item.tsx

Lines changed: 20 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,12 @@
1-
import { memo, useCallback, useState } from "react";
2-
import { FormProvider } from "react-hook-form";
1+
import { memo } from "react";
32
import type { AbiFunction } from "viem";
4-
import { AbiItemFormWithPreview } from "../../abi-form/abi-item-form-with-preview.js";
53
import {
64
AccordionContent,
75
AccordionItem,
86
AccordionTrigger,
97
} from "../../shadcn/accordion.js";
10-
import {
11-
ActionButtons,
12-
ConnectWalletAlert,
13-
DefaultResultDisplay,
14-
MsgSenderInput,
15-
} from "../shared/components.js";
16-
import { useMsgSenderForm } from "../shared/form-utils.js";
17-
import type { BaseExecutionProps, ExecutionParams } from "../shared/types.js";
18-
import { useFunctionExecution } from "../shared/use-function-execution.js";
19-
import { isWriteFunction } from "../shared/utils.js";
8+
import { ExecutionForm } from "../shared/components/execution-form.js";
9+
import type { BaseExecutionProps, ExecutionParams } from "../types.js";
2010

2111
interface FunctionItemProps extends BaseExecutionProps {
2212
func: AbiFunction;
@@ -42,42 +32,6 @@ export const FunctionItem = memo(
4232
addressRenderer,
4333
onHashClick,
4434
}: FunctionItemProps) => {
45-
const [callData, setCallData] = useState<string>("");
46-
const { result, isSimulating, isExecuting, simulate, execute } =
47-
useFunctionExecution();
48-
const { form, msgSender } = useMsgSenderForm(sender);
49-
50-
const isWrite = isWriteFunction(func);
51-
52-
const handleCallDataChange = useCallback(
53-
(newCallData: string | undefined) => {
54-
setCallData(newCallData || "");
55-
},
56-
[],
57-
);
58-
59-
const handleSimulate = () => {
60-
simulate({
61-
abiFunction: func,
62-
callData,
63-
msgSender,
64-
onQuery,
65-
onWrite,
66-
onSimulate,
67-
});
68-
};
69-
70-
const handleExecute = () => {
71-
execute({
72-
abiFunction: func,
73-
callData,
74-
msgSender,
75-
onQuery,
76-
onWrite,
77-
onSimulate,
78-
});
79-
};
80-
8135
const functionKey = `${func.name}-${index}`;
8236

8337
return (
@@ -91,55 +45,23 @@ export const FunctionItem = memo(
9145
</span>
9246
</AccordionTrigger>
9347
<AccordionContent className="px-3 pb-3">
94-
<FormProvider {...form}>
95-
<div className="mt-4 space-y-6">
96-
{isWrite && <MsgSenderInput />}
97-
98-
<AbiItemFormWithPreview
99-
addresses={addresses}
100-
key={func.name}
101-
onChange={(data) => {
102-
const callData = data.data?.toString() ?? undefined;
103-
handleCallDataChange(callData);
104-
}}
105-
abiFunction={func}
106-
address={address}
107-
sender={sender || address}
108-
chainId={chainId}
109-
defaultCalldata={callData as `0x${string}` | undefined}
110-
ArgProps={
111-
addressRenderer
112-
? {
113-
addressRenderer,
114-
}
115-
: undefined
116-
}
117-
/>
118-
119-
{isWrite && requiresConnection && !isConnected && (
120-
<ConnectWalletAlert />
121-
)}
122-
123-
<ActionButtons
124-
isWrite={isWrite}
125-
callData={callData}
126-
isSimulating={isSimulating}
127-
isExecuting={isExecuting}
128-
isConnected={isConnected}
129-
hasSimulate={!!onSimulate}
130-
simulate={handleSimulate}
131-
execute={handleExecute}
132-
/>
133-
134-
{result && (
135-
<DefaultResultDisplay
136-
key={`${result.type}-${result.data}`}
137-
result={result}
138-
onHashClick={onHashClick}
139-
/>
140-
)}
141-
</div>
142-
</FormProvider>
48+
<ExecutionForm
49+
abiFunction={func}
50+
address={address}
51+
chainId={chainId}
52+
sender={sender}
53+
addresses={addresses}
54+
requiresConnection={requiresConnection}
55+
isConnected={isConnected}
56+
addressRenderer={addressRenderer}
57+
onHashClick={onHashClick}
58+
executionParams={{
59+
onQuery,
60+
onWrite,
61+
onSimulate,
62+
}}
63+
className="space-y-4"
64+
/>
14365
</AccordionContent>
14466
</AccordionItem>
14567
);

components/contract-execution/contract-execution-tabs/index.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { cn } from "../../../lib/utils.js";
55
import { Accordion } from "../../shadcn/accordion.js";
66
import { Input } from "../../shadcn/input.js";
77
import { Tabs, TabsContent, TabsList, TabsTrigger } from "../../shadcn/tabs.js";
8-
import type { ContractExecutionTabsProps } from "../shared/types.js";
8+
import type { ContractExecutionTabsProps } from "../types.js";
99
import { FunctionItem } from "./function-item.js";
1010
import { RawOperations } from "./raw-tab.js";
1111
import { SignatureOperations } from "./signature-tab.js";
@@ -213,6 +213,7 @@ export function ContractExecutionTabs({
213213
isConnected={isConnected}
214214
onQuery={onQuery}
215215
onWrite={onWrite}
216+
onSimulate={onSimulate}
216217
addressRenderer={addressRenderer}
217218
onHashClick={onHashClick}
218219
/>

components/contract-execution/contract-execution-tabs/raw-tab.tsx

Lines changed: 30 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,16 @@
1-
import { useCallback, useState } from "react";
2-
import { FormProvider } from "react-hook-form";
3-
import type { Hex } from "viem";
4-
import { AbiItemFormWithPreview } from "../../abi-form/abi-item-form-with-preview.js";
51
import {
62
Accordion,
73
AccordionContent,
84
AccordionItem,
95
AccordionTrigger,
106
} from "../../shadcn/accordion.js";
11-
import { Button } from "../../shadcn/button.js";
12-
import {
13-
ConnectWalletAlert,
14-
DefaultResultDisplay,
15-
MsgSenderInput,
16-
} from "../shared/components.js";
17-
import { useMsgSenderForm } from "../shared/form-utils.js";
18-
import type { BaseExecutionProps, ExecutionParams } from "../shared/types.js";
19-
import { useRawExecution } from "../shared/use-raw-execution.js";
7+
import { ExecutionForm } from "../shared/components/execution-form.js";
8+
import type { BaseExecutionProps, ExecutionParams } from "../types.js";
209

2110
interface RawOperationsProps extends BaseExecutionProps {
2211
onQuery: (params: ExecutionParams) => Promise<`0x${string}`>;
2312
onWrite: (params: ExecutionParams) => Promise<`0x${string}`>;
13+
onSimulate?: (params: ExecutionParams) => Promise<`0x${string}`>;
2414
}
2515

2616
export function RawOperations({
@@ -32,6 +22,7 @@ export function RawOperations({
3222
isConnected,
3323
onQuery,
3424
onWrite,
25+
onSimulate,
3526
addressRenderer,
3627
onHashClick,
3728
}: RawOperationsProps) {
@@ -46,7 +37,7 @@ export function RawOperations({
4637
addresses={addresses}
4738
requiresConnection={requiresConnection}
4839
isConnected={isConnected}
49-
onExecute={onQuery}
40+
onQuery={onQuery}
5041
addressRenderer={addressRenderer}
5142
onHashClick={onHashClick}
5243
/>
@@ -58,7 +49,8 @@ export function RawOperations({
5849
addresses={addresses}
5950
requiresConnection={requiresConnection}
6051
isConnected={isConnected}
61-
onExecute={onWrite}
52+
onWrite={onWrite}
53+
onSimulate={onSimulate}
6254
addressRenderer={addressRenderer}
6355
onHashClick={onHashClick}
6456
/>
@@ -69,7 +61,9 @@ export function RawOperations({
6961

7062
interface RawOperationItemProps extends BaseExecutionProps {
7163
type: "call" | "transaction";
72-
onExecute: (params: ExecutionParams) => Promise<`0x${string}`>;
64+
onQuery?: (params: ExecutionParams) => Promise<`0x${string}`>;
65+
onWrite?: (params: ExecutionParams) => Promise<`0x${string}`>;
66+
onSimulate?: (params: ExecutionParams) => Promise<`0x${string}`>;
7367
}
7468

7569
function RawOperationItem({
@@ -80,41 +74,18 @@ function RawOperationItem({
8074
addresses,
8175
requiresConnection,
8276
isConnected,
83-
onExecute,
77+
onQuery,
78+
onWrite,
79+
onSimulate,
8480
addressRenderer,
8581
onHashClick,
8682
}: RawOperationItemProps) {
87-
const [callData, setCallData] = useState<string>("");
88-
const [value, setValue] = useState<bigint | undefined>();
89-
const { form, msgSender } = useMsgSenderForm(sender);
90-
91-
const isWrite = type === "transaction";
92-
const {
93-
result,
94-
isExecuting,
95-
execute: executeRaw,
96-
} = useRawExecution({
97-
isWrite,
98-
onExecute,
99-
});
10083
const title = type === "call" ? "Raw Call" : "Raw Transaction";
10184
const description =
10285
type === "call"
10386
? "Execute eth_call with arbitrary calldata"
10487
: "Send transaction with arbitrary calldata";
10588

106-
const handleCallDataChange = useCallback(
107-
({ data, value: newValue }: { data?: Hex; value?: bigint }) => {
108-
setCallData(data || "");
109-
setValue(newValue);
110-
},
111-
[],
112-
);
113-
114-
const handleExecute = () => {
115-
executeRaw({ callData, value, msgSender });
116-
};
117-
11889
return (
11990
<AccordionItem
12091
value={type}
@@ -127,53 +98,23 @@ function RawOperationItem({
12798
</div>
12899
</AccordionTrigger>
129100
<AccordionContent className="px-3 pb-3">
130-
<FormProvider {...form}>
131-
<div className="mt-4 space-y-6">
132-
{isWrite && <MsgSenderInput />}
133-
134-
<AbiItemFormWithPreview
135-
addresses={addresses}
136-
onChange={handleCallDataChange}
137-
abiFunction={type === "call" ? "rawCall" : "raw"}
138-
address={address}
139-
sender={sender || address}
140-
chainId={chainId}
141-
ArgProps={
142-
addressRenderer
143-
? {
144-
addressRenderer,
145-
}
146-
: undefined
147-
}
148-
/>
149-
150-
{isWrite && requiresConnection && !isConnected && (
151-
<ConnectWalletAlert />
152-
)}
153-
154-
<div className="flex flex-row items-center justify-center gap-2">
155-
<Button
156-
onClick={handleExecute}
157-
disabled={!callData || isExecuting || (isWrite && !isConnected)}
158-
className="w-fit"
159-
>
160-
{isExecuting
161-
? "Executing..."
162-
: type === "call"
163-
? "Call"
164-
: "Send Transaction"}
165-
</Button>
166-
</div>
167-
168-
{result && (
169-
<DefaultResultDisplay
170-
key={`${result.type}-${result.data}`}
171-
result={result}
172-
onHashClick={onHashClick}
173-
/>
174-
)}
175-
</div>
176-
</FormProvider>
101+
<ExecutionForm
102+
abiFunction={type === "call" ? "rawCall" : "raw"}
103+
address={address}
104+
chainId={chainId}
105+
sender={sender}
106+
addresses={addresses}
107+
requiresConnection={requiresConnection}
108+
isConnected={isConnected}
109+
addressRenderer={addressRenderer}
110+
onHashClick={onHashClick}
111+
executionParams={{
112+
onQuery,
113+
onWrite,
114+
onSimulate,
115+
}}
116+
className="mt-4 space-y-4"
117+
/>
177118
</AccordionContent>
178119
</AccordionItem>
179120
);

0 commit comments

Comments
 (0)