Today we're going to send real transactions via our React Dapp, both reading from & writing to an Ethereum smart-contract written in Solidity. ...
For further actions, you may consider blocking this person and/or reporting abuse
Great tutorial! If I clone your repo, npm install, npm start, and then click the "increment" button, I get an unsupported chain error (see pic). At first I thought it was something I missed/modified while following this tutorial, but I still get the error when using your repo as-is.
Also, it appears to be changing the state of count appropriately. Everything is working on the blockchain/smart contract side as expected (ropsten.etherscan.io/tx/0xe6cd6480...), but the UI crashes. Anyone else having this issue?
Yes me too :/
Great tutorial though! :)
Hi - sorry for the late reply, tbh I'm not really sure about that, if I get the chance I'll spin the project back up and see what the issue might be.
hey, thanks so much for the tutorial, it is great. I am stuck on one section, how do I modify the code to be able to call a payable contract function with a value? Thanks again for such a clear explanation.
Hi George,
With useDapp, in order to call a payable function and pass along a value we are using the useContractFunction method, which will automatically forward arguments to the underlying ethers.js contract object - this means that we don't need to explicitly do anything other than just pass the value, like we do inside the call to setCount inside the Count component:
function handleSetCount() {
const _count = parseInt(input) {
if (_count) {
setCount(_count); // passing _count here, which is handled by useContractFunction and sent through to the contract by ethers under the hood
}
}
}
Btw here's the specific documentation for useContractFunction: usedapp.readthedocs.io/en/latest/c...
Hi Jacob, thanks for the reply. I did have a read of the documentation but I am still a little stuck! I am able to call the contract with arguments when it is not expecting a value for the message but when it is expecting a value I am still not able to trigger this.
If I call it like this:
mintButton.tsx
import {useContractMethod } from "../hooks";
index.ts
export function useContractMethod(methodName: string) {
}
I am able to mint a token if the contract function is not expecting payment (the first 200 tokens are free). If I try beyond the first 200 I get an error in metamask, MetaMask - RPC Error: execution reverted: Value below price.
I have tried passing in a value as a third argument to mintIt() e.g.
but when I run this metamask does not pop up a transaction as it does when I run it without the third argument.
The contract abi for the mintTea function looks like this and takes just two arguments, the address and the number to mint.
{
"inputs": [
{
"internalType": "address",
"name": "_to",
"type": "address"
},
{
"internalType": "uint256",
"name": "_count",
"type": "uint256"
}
],
"name": "mintTea",
"outputs": [],
"stateMutability": "payable",
"type": "function"
},
and here is the mintTea and price functions from the Solidity contract:
Sorry for such a long question, I am still very new to dapp development in general so am probably missing something quite basic! Any suggestions would be greatly welcomed, I have been trying various things to get this to work for a few days now but feel like I may be missing something obvious.
Hi George - the value property is a special property that is added to the msg object that the contract function receives - you can pass in your arguments sequentially and add a configuration object as the last argument:
mintTea(arg1, arg2, {
value: PARSED_ETH_VALUE
});
Here's a concrete example - I updated the contract I used in this tutorial with a payable function called "takeTwoVariables":
Inside Count.tsx, I've imported utils from ethers (so we can parse our value):
// Count.tsx
And I've added a new function called "handleTwoVariables":
I replaced "handleSetCount" with "handleTwoVariables" in the onClick handler, so when the user clicks "Set Count" we will send 0.05 ether to the payable function along with the 2 integers (_count & 2). If the value property is not set, or set to 0, the function will revert because in the contract there is now a require statement, so the value must be > 0.
So, the TLDR is that you add arguments sequentially (based on their defined order in the contract), and you add "special" properties on the msg object like "value" inside the config object.
I hope that makes sense! Feel free to ask any more questions if that isn't quite clear :)
Thank you so much. That works perfectly and makes sense now. Thanks for taking the time to reply in such detail, it has really helped!
I had to create account to thank you
sir, you are really the legend
thank you very much
Wow, thanks! Happy to hear it helped you :)
Hi Jacob, wonderful tutorial. Thank you.
I was wondering if there is a way to get the count from the contract without being connected with MetaMask. Currently the count only shows up if connected. If not connected, it defaults to 0. Thanks again.
Hello! Great tutorial - extremely thorough and helpful for a newbie just getting into React.
I'm adapting your code to fit my smart contract - and I'm having trouble using the useContractCall hook. It works perfectly well when I have a single input address to pass to it (along with the ABI) - the problem is I have a 2-tiered smart contract that has a parent contract and then children contracts are created from the parent. I have an array of children contracts, but when I try and iterate through the array using the useContractCall hook, React barks at me that I "can't use a hook in a callback function".
Any ideas how to pass an array of contracts through to the useContractCall hook?
Thanks for the help!
Hey Jacob, your tutorials have been awesome.
I am having trouble with what is probably a newbie error. I am trying to query a read function on my contract that returns a list of token id's that are held by the connected wallet address.
My GetTokenIds function below is a repurposed version of your "getCount" function in this tut.
When I hard code the wallet address, it works ok, eg:
const wallet_address = "0x6Ff6**hidden*****C05";
const [token_ids]: any = GetTokenIds(wallet_address) ?? [];
but when i try to pass "account" to GetTokenIds it errors, i think because initially the account is 'undefined' for a brief moment at first.
How do i only execute the GetTokenIds function above when account is a valid wallet address?
Thanks so much
Great tutorial. And comments!
Any ideas for trapping errors? When a "require" condition fails in the contract, I get an "RPC Error: execution reverted" message on the Javascript console, but there doesn't seem to be anyway to capture it. I tried try {] catch {} and no luck. Any ideas?
Much appreciated!
Hi, how would one go about creating a transaction to a payable function?
The ABI of said function is:
{
"inputs": [
{
"internalType": "uint256",
"name": "_quantity",
"type": "uint256"
}
],
"name": "mint",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "payable",
"type": "function"
}
hello! I had some errors after 'transaction action'!
And after refreshing the page by force, it will return ok! Why?
A lot of people have also been having this issue (github.com/EthWorks/useDApp/issues...). It appears to be an issue with with Metamask using EIP-1559 type transactions.
FIXED: See the workaround provided here (github.com/EthWorks/useDApp/issues...).
If you're following this tutorial:
1.) Simply copy/paste the code provided in the workaround link into a new file "workaround.ts".
2.) At the top of src/hooks/index.ts, import useContractFunction from your new workaround.ts file instead of from "@usedapp/core".
3.) Note where the variable/const "contract" is assigned in src/hooks/index.ts. Then replace that line with the below code.
declare const window: any;
const provider = new ethers.providers.Web3Provider(window.ethereum);
const signer = provider.getSigner()
const counterContractInterface = new ethers.utils.Interface(counterContractAbi);
export const contract = new Contract(counterContractAddress, counterContractInterface, signer);
Hey - thanks a lot for sharing that info, I only just saw these recent comments! I believe a lot of issues are being causes in Dapps at the moment due to interactions between MetaMask regarding EIP-1559, hopefully they'll be resolved soon.
Hi Jacob, just finished going through your beginners post and this one! Awesome tutorials and I'm very grateful to you for making them. Thank you!
Hi, Fantastic guide! I used this guide to use the minting feature of my contract, also following the comments. However, I have a problem: my contract has a cost for the minting of 0.02 ETH and if I set this number I am able to mint only 1 NFT. If I increase this number (for example 0.06) I am able to coin 3 NFT but the problem is that if I want to coin only 1 I always pay 0.06! Can you help me correct this error?
function handleSetCount() {
const _count = parseInt(input);
if (_count) {
mint(_count, {
value: utils.parseEther("0.02"),
});
}
}
Hi Jacob. Loved the tutorial. Recently I've decided to try to develop a project on BSC, which required me to update the usedapp package. I've deployed my contract and followed the exact steps to somewhat replicate the same behavior as the one shown on your tutorial. It worked fine until I had a function that required the passage of arguments. It is done in the same way as the setCount function, but when I press the button, I get an error instead saying that the argument is undefined. On an attempt to figure out if I had done anything wrong during development, I've pulled the code from your repo, updated the usedapps and attempted to call the setCount, which resulted in the same error.
Do you have any clues into either solving this?
Best regards,
FΓ‘bio Jesus