Replies: 11 comments 15 replies
-
I am running into this same issue. Only thing I can think of is that after form information is submitted and values are set. Like maybe onChange of fields, it refetches the usePreparecontractWrite so it has the updated values by the time you click on the button to submit the write? |
Beta Was this translation helpful? Give feedback.
-
I began using that usePreparecontractWrite() setup as shown in the docs and now I'm trying to disable it since it's throwing errors all the time and it can't be disabled. I have lost many hours of development trying to solve problems with this new setup. |
Beta Was this translation helpful? Give feedback.
-
I have the similar issue too. Previously, I'll pass the instantiate the export const usePublicMint = (address: string): UsePublicMint => {
const {
write,
isLoading: contractIsLoading,
data: trx,
} = useContractWrite({
...ContractConfig,
functionName: 'publicMint',,
onSettled: data => {
if (data) {
notifySubmitted(data?.hash)
}
},
onError: error => {
notifyError({ message: error?.data?.message ?? error?.message })
},
})
const { isLoading: trxIsProcessing } = useWaitForTransaction({
hash: trx?.hash,
onError: error => {
// @ts-expect-error may not be needed to construct a custom type for error
notifyError({ message: error?.data?.message ?? error?.message })
},
onSuccess: data => {
if (data) {
notifySuccess()
}
},
})
const mint = (invocations: number) => {
if (!address) {
notifyError({ message: 'Please connect to wallet first.' })
}
if (invocations > maxInvocation) {
notifyError({ message: 'Trying to mint too many' })
}
const mintValue = config.totalPriceAllocation[invocations - 1]
const overrides = {
value: ethers.utils.parseEther(mintValue.toString()),
gasLimit: COLLECTION_DISTRIBUTION.gasLimit,
}
write({ args: [invocations], overrides })
}
return {
isLoading: contractIsLoading || trxIsProcessing,
mint,
}
} As you can see, in my custom hook, I return the How does that works with the current prepare hook? Does that mean, my use case won't be feasible to do with the prepare hook? |
Beta Was this translation helpful? Give feedback.
-
I might write some examples up this week when I have the time, but the best way to migrate from passing in args "lazily"/imperatively (via Below is a naive example, but hopefully good enough to convey the idea. Before: function Example() {
const inputRef = useRef()
const { data, write } = useContractWrite({
addressOrName: '0xecb504d39723b0be0e3a9aa33d646642d1051ee1',
contractInterface: nftABI,
functionName: 'mint'
})
return (
<div>
<input ref={inputRef} placeholder="Quantity" />
<button onClick={() => write({ args: [inputRef.current.value] })}>Mint</button>
</div>
)
} After: function Example() {
const [quantity, setQuantity] = useState()
const { config } = usePrepareContractWrite({
addressOrName: '0xecb504d39723b0be0e3a9aa33d646642d1051ee1',
contractInterface: nftABI,
functionName: 'mint',
enabled: Boolean(quantity),
args: [quantity]
})
const { data, write } = useContractWrite(config)
return (
<div>
<input onChange={e => setQuantity(e.target.value)} value={quantity} placeholder="Quantity" />
<button disabled={!write} onClick={() => write()}>Mint</button>
</div>
)
} Obviously, you'd probably want to debounce the quantity value (using a |
Beta Was this translation helpful? Give feedback.
-
I'm posting the solution to my use case for posterity (a form that places a bid on an ERC-721 auction contract): const NoopEventHandler = () => { return; }
type BidSubmitFormProps = {
tokenId: number;
onSuccess: (amount: ethers.BigNumber, transactionHash: string) => void;
onError: (error: string) => void;
};
const BidSubmitForm = ({
tokenId,
onSuccess = NoopEventHandler,
onError = NoopEventHandler,
}) => {
const [bid, setBid] = useState(ethers.BigNumber.from(0));
const { config } = usePrepareContractWrite({
addressOrName: '0x',
contractInterface: ContractAbi,
functionName: 'placeBid(uint256,uint256)',
args: [tokenId, bid],
overrides: {
value: bid,
},
});
const { write } = useContractWrite({
...config,
onSuccess: ({ hash }) => onSuccess(bid, hash),
onError: ({ message }) => onError(message),
});
return (
<div>
<input
onChange={e => setBid(ethers.BigNumber.from(e.target.value))}
value={bid}
/>
<button disabled={!write} onClick={write}>Place Bid</button>
</div>
);
} Things to consider:
|
Beta Was this translation helpful? Give feedback.
-
I got away with this by leveraging a export function TransactionModal({ onClose, isOpen, onCompleteHook, callValues, isFetching }: Props) {
const network = useNetwork();
const toast = useToast();
const { config } = usePrepareContractWrite({
addressOrName: config.registry,
contractInterface: Nnax__factory.abi,
chainId: network.chain?.id,
functionName: 'stake',
args: callValues,
enabled: false,
});
const callContract = useContractWrite({
...config,
onError(error) {
console.warn('Error', error);
},
onSettled(data, error) {
if (error || (error as any) instanceof UserRejectedRequestError) {
toast({
title: (error as unknown as ProviderRpcError).message ?? 'Operation Failed',
status: 'error',
duration: 5000,
isClosable: true,
});
} else {
toast({
title: 'Operation Successful',
status: 'success',
duration: 5000,
isClosable: true,
});
}
}
});
useWaitForTransaction({
wait: callContract.data?.wait,
hash: callContract.data?.hash,
onSettled(data, error) {
!error && onCompleteHook && onCompleteHook(data);
},
});
useEffect(() => {
if (isOpen) {
try {
callContract.writeAsync?.();
} catch (error) {
toast({
title: (error as unknown as ProviderRpcError).message ?? 'Operation Failed',
status: 'error',
duration: 5000,
isClosable: true,
});
}
}
return () => {
callContract.reset();
};
}, [isOpen, callValues]);
return (
<Modal isOpen={isOpen} onClose={onClose} size="3xl" closeOnOverlayClick={false}>
</Modal> Then in my form, I can then push transactions by opening up the transaction modal const handleComplete = async (data: any) => await storage.mutateAsync({ ...data})
const { renderForm, control } = useForm<FormInputRequest>({
onSubmit: handleSubmit,
defaultValues: Model.formDefaultValues,
schema: Model.validationSchema,
});
/* Watch form values from react context */
const { limitMaxTicketSupply } = useWatch({
control,
});
return renderForm(
<>
<FormWithReactHook />
<TransactionModal onCompleteHook={handleComplete} callValues={callParams} isOpen={isOpen} onClose={onClose} />
</> So the transaction modal is just a neat ui with a circular progress, that shows up and then tracks the completion of a transaction before exiting. This pained me, and cost me over 24 hours trying to maneuver |
Beta Was this translation helpful? Give feedback.
-
There is now an official example for this! |
Beta Was this translation helpful? Give feedback.
-
I'm sure part of this is a misunderstanding of WAGMI, and the other part is a misunderstanding at the winding road that is React . . . . . . but, what about situations in which you're using WAGMI inside another custom hook. I have a highly dynamic setup (previously using While I realize that may not be as performant or clean, it gave me the ability to call the function as needed as dynamically as needed. I've given the Dynamic Args wasn't helpful as it assumes the items are being set via Any direction in this regard? 🤔 |
Beta Was this translation helpful? Give feedback.
-
There is the possibility of using refetch from prepareWriteContract. This method worked for my use case.
The |
Beta Was this translation helpful? Give feedback.
-
Following some unreal broker on Instagram, I end up losing my saving money and profits. With the help of "' wiki help desks AT g mail . co m " I was able to recover my funds and I am Investing via wiki fx because they are secure, fast and reliable. |
Beta Was this translation helpful? Give feedback.
-
whats the implementation in 2024? I have encountered the same issue now. |
Beta Was this translation helpful? Give feedback.
-
I'm experiencing UX issues while sending a transaction via Rainbow wallet + WalletConnect (redirection to a website instead of opening the wallet right away) and I'm looking to move to prepared hooks as suggested in the wagmi docs. However, I fail to understand how to use this setup when I don't have the arguments ready by the time I call
useContractWrite(config)
as these need to be specified via a form by the user.I need to call
writeAsync
inside a click handler that fires when the user submits the form and set the arguments that will be passed to the contract, but the only way to do this is by usingrecklesslyUnprepared
mode, which I think defeats the purpose of using prepared hooks. Moreover, since I don't have the arguments ready, I get an error in the console about missing params expected by the contract (seems like it's trying to eagerly send the transaction?)I looked for examples of achieving this, but so far haven't found any. If someone can provide guidance or an example it would be very much appreciated!
Beta Was this translation helpful? Give feedback.
All reactions