0

I created a simple dapp with react/truffle/web3 that allows users to enter a number of tokens and submit it to stake it, the problem that I got is that when clicked on submit button, Metamask popup to confirm the transaction(approuve) but I don't get the second popup to confirm stakeTokens function.

N.b(by default a give I put 100 tokens in their account to stake)

stake Token in solidity

   function stakeTokens(uint _amount) public {
         // Require amount greater than 0
        require(_amount > 0, "amount cannot be 0");

        // Transfer tokens from the investor wallet to "this" farm
        daiToken.transferFrom(msg.sender, address(this), _amount);
 
        // Store deposit balance
        stakingBalance[msg.sender] = stakingBalance[msg.sender] + _amount;

        // To store inside the array *Only* who haven't stake yet(The new investors);
       //  if hasStacked is false then will be true ! then will execute the code
        if(!hasStaked[msg.sender]){
            stakers.push(msg.sender);
        }

        //update staking status
        isStaking[msg.sender] = true;
        hasStaked[msg.sender] = true;
        
    }

stake token in React

const stakeTokens = async (amount) => {
     await dTokens.methods.approve(FarmAddress, amount).send({ from : investorAccount}).on("transitionsHash", (hash)=> {
       fTokens.methods.stakeTokens(amount).send({from : investorAccount})
    }).on("transitionsHash", (hash)=> {
      console.log("stacking has been validated")
    });
};

submit function

const stackHandler =  (e) => {
    e.preventDefault();

    const amount = refInput.current.value;
    const newAmount = amount.toString();
    const myAmount = web3.utils.toWei(newAmount, "ether");
    stakeTokens(myAmount);
    
}

web3 js

import Web3 from "web3";

window.ethereum.request({method: "eth_requestAccounts" });

const web3 = new Web3(window.ethereum);


export default web3;

1 Answer 1

0

You transaction "chaining" might be a bit off. Your second transitionsHash listener is still linked to the first tx. Try the following:

const stakeTokens = (amount, onSuccess) => {
  dTokens.methods
    .approve(FarmAddress, amount)
    .send({ from: investorAccount })
    .on('transitionsHash', hash => {
      fTokens.methods
        .stakeTokens(amount)
        .send({ from: investorAccount })
        .on('transitionsHash', hash => {
          console.log('stacking has been validated')
          onSuccess(); // Example of where to use a callback
        })
    })
}

Suggestions:

  1. You should consider adding some callbacks (I've added one as an example) for success and failure, that you can trigger in the listeners to get results back to the app. Check on('error') as well.
  2. You may want to separate the approve from the stake transaction. You'll have users that approve but close the app before the transaction is minted. Next time they return, they should be able to stake immediately, but they'll be asked to approve again.
5
  • I made the changes that you provided in this solution but the problem persists !! What do you think @razgraf, I was doubting maybe the fact that I'm not calling the function inside useEffect or because I'm passing the function throught props to another component(form) correctly
    – David Jay
    Commented Jan 9, 2022 at 15:10
  • I may need to see more of your code in order to figure out what the problem is. The fact that you are passing it as a prop shouldn't be relevant. I'd first bind this action (stakeTokens) to an onClick to test it. Then, add some error listeners .on('error', function(error){ ... }) to check where the call is failing. See here examples: web3js.readthedocs.io/en/v1.5.2/… Also, make sure your logic is corect there. You are giving allowance to FarmAddress to spend DAI (dTokens). is fTokens an instance of Farm?
    – razgraf
    Commented Jan 10, 2022 at 12:02
  • Yes fTokens is an instance of FarmTokens, I've also tried to debug stakeTokens using error listeners but I got an error only when I declined the transaction from metaMask. The dapp I'm creating is from this tutorial "youtube.com/watch?v=CgXQC4dbGUE" and I got a stack in the timing of 2:21:27, In order to see more about my code please check out my repo"github.com/Tayarthouail/DEFI_Digital_Bank". Thanks a lot
    – David Jay
    Commented Jan 11, 2022 at 9:28
  • Your transaction chaining is still incorrect in the github project, the second ".on" has to be after the second transaction. Try to make the function exactly like in my post above, or like in the tutorial you shared (~2:22:44 shows the full code). As an extra, log your fTokens instance and the other variables to make sure nothing is null. Also, per documentation (github.com/Tayarthouail/DEFI_Digital_Bank/blob/…) your async/await there in the function is redundant, as the send() metod doesn't return an await-able object.
    – razgraf
    Commented Jan 11, 2022 at 13:10
  • I logged almost all the instances and variables, everything looks good but still, something is wrong with my code, I just updated my repo "github.com/Tayarthouail/DEFI_Digital_Bank" is you could give me your opinion, please. thanks for your time @razgraf
    – David Jay
    Commented Jan 12, 2022 at 8:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.