-
Notifications
You must be signed in to change notification settings - Fork 2
/
TxButton.tsx
94 lines (90 loc) · 1.99 KB
/
TxButton.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
import { Button } from "@radix-ui/themes";
import { useQueryClient } from "@tanstack/react-query";
import { useEffect, useState } from "react";
import { toast } from "sonner";
import { useWaitForTransactionReceipt, useWriteContract } from "wagmi";
export function TxButton({
label,
description,
payload,
disabled,
set_busy,
cleanup,
}: {
label: string;
description?: string;
payload: object;
disabled?: boolean;
set_busy: (busy: boolean) => void;
cleanup?: () => void;
}) {
const query_client = useQueryClient();
const [resolver, set_resolver] = useState<
(() => (value: unknown) => void) | null
>(null);
const {
data: txn_hash,
isPending,
writeContract,
} = useWriteContract({
mutation: {
onError(error) {
// signature rejected or gas estimation failed
toast.error(error.name, { description: error.message });
set_busy(false);
},
onSuccess(data) {
// tx broadcasted
toast_broadcast(data);
},
},
});
const { isLoading, isSuccess } = useWaitForTransactionReceipt({
hash: txn_hash,
});
function toast_broadcast(txn_hash: string) {
toast.promise(
new Promise((resolve) => {
// save to resolve from the effect when we get a receipt
set_resolver(() => resolve);
}),
{
loading: `<Strong>${
description ?? label
}</Strong> transaction submitted`,
success: () => {
return `<Strong>${
description ?? label
}</Strong> transaction confirmed`;
},
error: "error",
action: {
label: "view",
onClick: () => {
window.open(`https://etherscan.io/tx/${txn_hash}`, "_blank");
},
},
},
);
}
useEffect(() => {
if (!isSuccess) return;
set_busy(false);
!!cleanup && cleanup();
query_client.invalidateQueries();
// sets the promise toast to success
!!resolver && resolver();
}, [isSuccess]);
return (
<Button
onClick={() => {
set_busy(true);
// @ts-ignore
writeContract(payload);
}}
disabled={isPending || isLoading || disabled}
>
{label}
</Button>
);
}