1+ "use client" ;
2+
13import {
24 Form ,
35 FormControl ,
46 FormField ,
57 FormItem ,
68 FormLabel ,
9+ FormMessage ,
710} from "@/components/ui/form" ;
811import { Input } from "@/components/ui/input" ;
912import { Skeleton } from "@/components/ui/skeleton" ;
1013import { zodResolver } from "@hookform/resolvers/zod" ;
1114import { useMutation } from "@tanstack/react-query" ;
15+ import { useCallback } from "react" ;
1216import { useForm } from "react-hook-form" ;
1317import { toast } from "sonner" ;
14- import { type ContractOptions , waitForReceipt } from "thirdweb" ;
18+ import { isAddress , sendAndConfirmTransaction } from "thirdweb" ;
1519import { MintableERC721 } from "thirdweb/modules" ;
16- import { useReadContract , useSendTransaction } from "thirdweb/react" ;
20+ import { useReadContract } from "thirdweb/react" ;
1721import { z } from "zod" ;
1822import { ModuleCardUI , type ModuleCardUIProps } from "./module-card" ;
23+ import type { ModuleInstanceProps } from "./module-instance" ;
1924
2025const formSchema = z . object ( {
21- primarySaleRecipient : z . string ( ) ,
26+ primarySaleRecipient : z . string ( ) . refine (
27+ ( v ) => {
28+ // don't return isAddress(v) directly to avoid typecasting to `0x${string}`
29+ if ( isAddress ( v ) ) {
30+ return true ;
31+ }
32+ return false ;
33+ } ,
34+ {
35+ message : "Invalid Address" ,
36+ } ,
37+ ) ,
2238} ) ;
2339
2440export type MintableModuleFormValues = z . infer < typeof formSchema > ;
2541
26- export function MintableModule (
27- props : Omit < ModuleCardUIProps , "children" > & {
28- contract : ContractOptions ;
29- isOwnerAccount : boolean ;
30- } ,
31- ) {
32- const { contract } = props ;
33- const { mutateAsync : sendTransaction } = useSendTransaction ( ) ;
34- const { data : primarySaleRecipient , isLoading } = useReadContract (
42+ function MintableModule ( props : ModuleInstanceProps ) {
43+ const { contract, ownerAccount } = props ;
44+
45+ const primarySaleRecipientQuery = useReadContract (
3546 MintableERC721 . getSaleConfig ,
3647 {
37- contract,
48+ contract : contract ,
3849 } ,
3950 ) ;
4051
41- async function update ( values : MintableModuleFormValues ) {
42- const setSaleConfigTransaction = MintableERC721 . setSaleConfig ( {
43- contract ,
44- primarySaleRecipient : values . primarySaleRecipient ,
45- } ) ;
52+ const update = useCallback (
53+ async ( values : MintableModuleFormValues ) => {
54+ if ( ! ownerAccount ) {
55+ throw new Error ( "Not an owner account" ) ;
56+ }
4657
47- const setSaleConfigTxResult = await sendTransaction (
48- setSaleConfigTransaction ,
49- ) ;
58+ const setSaleConfigTx = MintableERC721 . setSaleConfig ( {
59+ contract : contract ,
60+ primarySaleRecipient : values . primarySaleRecipient ,
61+ } ) ;
5062
51- try {
52- await waitForReceipt ( setSaleConfigTxResult ) ;
53- toast . success ( "Successfully updated primary sale recipient" ) ;
54- } catch ( _ ) {
55- toast . error ( "Failed to update the primary sale recipient" ) ;
56- }
57- }
63+ await sendAndConfirmTransaction ( {
64+ account : ownerAccount ,
65+ transaction : setSaleConfigTx ,
66+ } ) ;
67+ } ,
68+ [ contract , ownerAccount ] ,
69+ ) ;
5870
5971 return (
6072 < MintableModuleUI
61- isPending = { isLoading }
62- primarySaleRecipient = { primarySaleRecipient || "" }
63- update = { update }
6473 { ...props }
74+ isPending = { primarySaleRecipientQuery . isPending }
75+ primarySaleRecipient = { primarySaleRecipientQuery . data }
76+ update = { update }
77+ isOwnerAccount = { ! ! ownerAccount }
6578 />
6679 ) ;
6780}
6881
6982export function MintableModuleUI (
7083 props : Omit < ModuleCardUIProps , "children" | "updateButton" > & {
71- primarySaleRecipient : string ;
84+ primarySaleRecipient : string | undefined ;
7285 isPending : boolean ;
7386 isOwnerAccount : boolean ;
7487 update : ( values : MintableModuleFormValues ) => Promise < void > ;
@@ -77,7 +90,7 @@ export function MintableModuleUI(
7790 const form = useForm < MintableModuleFormValues > ( {
7891 resolver : zodResolver ( formSchema ) ,
7992 values : {
80- primarySaleRecipient : props . primarySaleRecipient ,
93+ primarySaleRecipient : props . primarySaleRecipient || "" ,
8194 } ,
8295 reValidateMode : "onChange" ,
8396 } ) ;
@@ -87,47 +100,50 @@ export function MintableModuleUI(
87100 } ) ;
88101
89102 const onSubmit = async ( ) => {
90- const _values = form . getValues ( ) ;
91- const values = { ..._values } ;
92-
93- updateMutation . mutate ( values ) ;
103+ const promise = updateMutation . mutateAsync ( form . getValues ( ) ) ;
104+ toast . promise ( promise , {
105+ success : "Successfully updated primary sale recipient" ,
106+ error : "Failed to update primary sale recipient" ,
107+ } ) ;
94108 } ;
95109
96- if ( props . isPending ) {
97- return < Skeleton className = "h-36" /> ;
98- }
99-
100110 return (
101- < ModuleCardUI
102- { ...props }
103- updateButton = { {
104- onClick : onSubmit ,
105- isPending : updateMutation . isPending ,
106- isDisabled : ! form . formState . isDirty ,
107- } }
108- >
109- < Form { ...form } >
110- < form onSubmit = { form . handleSubmit ( onSubmit ) } >
111- < div className = "flex flex-col gap-4" >
112- < FormField
113- control = { form . control }
114- name = "primarySaleRecipient"
115- render = { ( { field } ) => (
116- < FormItem className = "flex flex-1 flex-col gap-3" >
117- < FormLabel > Primary Sale Recipient</ FormLabel >
118- < FormControl >
119- < Input
120- placeholder = "0x..."
121- { ...field }
122- disabled = { ! props . isOwnerAccount }
123- />
124- </ FormControl >
125- </ FormItem >
126- ) }
127- />
128- </ div >
129- </ form >
130- </ Form >
131- </ ModuleCardUI >
111+ < Form { ...form } >
112+ < form onSubmit = { form . handleSubmit ( onSubmit ) } >
113+ < ModuleCardUI
114+ { ...props }
115+ updateButton = { {
116+ isPending : updateMutation . isPending ,
117+ isDisabled : ! form . formState . isDirty ,
118+ } }
119+ >
120+ { props . isPending && < Skeleton className = "h-[74px]" /> }
121+
122+ { ! props . isPending && (
123+ < div className = "flex flex-col gap-4" >
124+ < FormField
125+ control = { form . control }
126+ name = "primarySaleRecipient"
127+ render = { ( { field } ) => (
128+ < FormItem >
129+ < FormLabel > Primary Sale Recipient</ FormLabel >
130+ < FormControl >
131+ < Input
132+ placeholder = "0x..."
133+ { ...field }
134+ disabled = { ! props . isOwnerAccount }
135+ />
136+ </ FormControl >
137+ < FormMessage />
138+ </ FormItem >
139+ ) }
140+ />
141+ </ div >
142+ ) }
143+ </ ModuleCardUI >
144+ </ form >
145+ </ Form >
132146 ) ;
133147}
148+
149+ export default MintableModule ;
0 commit comments