adrianhajdin / project_crowdfunding

With a stunning design, connected to the blockchain, metamask pairing, interaction with smart contracts, sending Ethereum through the blockchain network, and writing solidity code.
https://jsmastery.pro
708 stars 382 forks source link

getDonators and donateToCampaign give errors #40

Open eeshaanSA opened 1 year ago

eeshaanSA commented 1 year ago

getDonators error image

donateToCampaign error image

My Code: index.jsx

`const donate = async (pId, amount) => {
    // const value = ethers.utils.parseEther(amount);
    const data = await contract.call("donaateToCampaign", [pId]);

    return data;
  };

  const getDonations = async (pId) => {
    const donatorData = await contract.call("getDonators", [pId]);
    const numberOfDonations = donatorData[0].length; //returns the number of donators (check smart contract)
    const parsedDonations = [];

    for (let i = 0; i < numberOfDonations; i++) {
      parsedDonations.push({
        donator: donatorData[0][i],
        donation: ethers.utils.formatEther(donatorData[1][i].toString()),
      });
    }
    console.log(parsedDonations);

    return parsedDonations;
  };`

CampaignDetails.jsx

import React, { useEffect, useState } from "react";
import { useLocation } from "react-router-dom";
import { ethers } from "ethers";
import { useStateContext } from "../context";
import { CountBox, CustomBtn } from "../components";
import { calculateBarPercentage, daysLeft } from "../utils";
import { thirdweb } from "../assets";

const campaignDetails = () => {
  const { state } = useLocation();
  // console.log(state); we pass the state of that particular card into the the Campaign Details component so that when click on that particular card we can load the sae details i nthat Campaign details component.
  const { donate, address, contract, getDonations } = useStateContext();

  const [isLoading, setIsLoading] = useState(false);
  const [amount, setAmount] = useState("");
  const [donators, setDonators] = useState([]);
  const remainingDays = daysLeft(state.deadline);

  const handleDonate = async () => {
    setIsLoading(true);
    await donate(state.pId);
    setIsLoading(false);
  };

  const fetchDonators = async () => {
    const data = await getDonations(state.pId);
    // setDonators(data);
    console.log(data);
  };

  useEffect(() => {
    if (contract) {
      fetchDonators();
    }
  }, [contract, address]);

The smart contract works fine. Tried using the ThirdWeb dashboard to make a trasaction, and it worked. The getDonators and Donate function both give errors, please help me solve them.

eeshaanSA commented 1 year ago

@adrianhajdin @KhGunindro (Since you completed the project ), I am wondering if you could help.

KhGunindro commented 1 year ago

Sure, I think you have a typo in the index.jsx file. The contract.call() method in the 'donate' function seems to take in the first parameter as 'donaateToCampaign' instead of 'donateToCampaign'. And the main problem lies in the donate function. Try this code out for the donate function:

      const donate = async (pId, amount) => {
        const data = await contract.call('donateToCampaign', [pId], { value: ethers.utils.parseEther(amount)});
        return data;
      }

Also, in the CampaignDetails.jsx, in the handleDonate function , you only passed one parameter in the await donate(state.pId) give the amount as the second parameter like this :

await donate(state.pId, amount);
eeshaanSA commented 1 year ago

@KhGunindro , I named in the func donaateToCampaign in the smart contract by mistake, so using the same everywhere. As far as await donate goes, yes I missed the second param, and I passed the amount as the second param. (acc. to the video) Still getting these errors: The first error pops up as soon as the page loads, (getDonators function) and the Second one pops up when I click the Fund Button. Both errors are of the same type. Everything else works fine for me. // @adrianhajdin image

KhGunindro commented 1 year ago

@eeshaanSA can I see the whole index.jsx code?

KhGunindro commented 1 year ago

have you tried passing in this parameter ( { value: ethers.utils.parseEther(amount)}) to you const data = await contract.call('donateToCampaign', [pId]); like this: const data = await contract.call('donateToCampaign', [pId], { value: ethers.utils.parseEther(amount)});

eeshaanSA commented 1 year ago

whole index.jsx

import React, { useContext, createContext } from "react";
import {
  useAddress,
  useContract,
  useMetamask,
  useContractWrite,
} from "@thirdweb-dev/react";
import { ethers } from "ethers";
const StateContext = createContext();
export const StateContextProvider = ({ children }) => {
  const { contract } = useContract(
    "0x886bed96a74C838fac806F153078898d8311Db95"
  );
  const { mutateAsync: createCampaign } = useContractWrite(
    contract,
    "createCampaign"
  );

  const address = useAddress();
  const connect = useMetamask();

  const publishCampaign = async (form) => {
    try {
      const data = await createCampaign({
        args: [
          address,
          form.title,
          form.description,
          form.target,
          new Date(form.deadline).getTime(), //deadline in seconds since 1970
          form.image,
        ],
      });

      console.log("contract call success", data);
    } catch (error) {
      console.log("failure hogaya bhaii", error);
    }
  };

  const getCampaigns = async () => {
    const campaigns = await contract.call("getCampaigns");
    // console.log(campaigns);

    const parsedCampaigns = campaigns.map((campaign, index) => ({
      owner: campaign.owner,
      title: campaign.title,
      description: campaign.descp,
      target: ethers.utils.formatEther(campaign.target.toString()),
      deadline: campaign.deadline.toNumber(),
      amountCollected: ethers.utils.formatEther(
        campaign.amountCollected.toString()
      ),
      image: campaign.image,
      PiD: index,
    }));
    return parsedCampaigns;
  };

  const getUserCampaigns = async () => {
    const allCampaigns = await getCampaigns();
    const filteredCampaigns = allCampaigns.filter((campaign) => {
      return campaign.owner === address;
    });

    return filteredCampaigns;
  };

  const donate = async (pId, amount) => {
    // const value = ethers.utils.parseEther(amount);
    const data = await contract.call('donaateToCampaign', [pId], {
      value: ethers.utils.parseEther(amount)
    });

    return data;
  };

  const getDonations = async (pId) => {
    const donatorData = await contract.call("getDonators", [pId]);
    const numberOfDonations = donatorData[0].length; //returns the number of donators (check smart contract)
    const parsedDonations = [];

    for (let i = 0; i < numberOfDonations; i++) {
      parsedDonations.push({
        donator: donatorData[0][i],
        donation: ethers.utils.formatEther(donatorData[1][i].toString()),
      });
    }
    console.log(parsedDonations);

    return parsedDonations;
  };

  return (
    <StateContext.Provider
      value={{
        address,
        contract,
        connect,
        createCampaign: publishCampaign,
        getCampaigns,
        getUserCampaigns,
        donate,
        getDonations,
      }}
    >
      {children}
    </StateContext.Provider>
  );
};

export const useStateContext = () => useContext(StateContext);
eeshaanSA commented 1 year ago

have you tried passing in this parameter ( { value: ethers.utils.parseEther(amount)}) to you const data = await contract.call('donateToCampaign', [pId]); like this: const data = await contract.call('donateToCampaign', [pId], { value: ethers.utils.parseEther(amount)});

yes, i have. Theres some problem with coversion from a bignumber or something like that. :disappointed:

KhGunindro commented 1 year ago

@eeshaanSA Well, I do know where the problem is coming form but cannot pinpoint what exactly is causing it. It's most probably caused by the arguments that are passed to that contract.call() function. On the note, I found out another very crucial typo that just might be the case: image You're using the arguments as pId while declaring it as PiD. Try changing the PiD to pId, I really hope it works.

KhGunindro commented 1 year ago

please do update me if you find a solution to this bug😊

eeshaanSA commented 1 year ago

@KhGunindro you are a gem. Thanks a lot. I missed that. Thats for looking into this in so much detail. It works now. I owe you one. PS - I dont know what casing I used there. (PiD) :rofl:

karanrawat08 commented 1 year ago

Hey Brother Can you please help me I am getting an error. This ERROR catch (error) { console.log("failure hogaya bhaii", error);

mirakiii commented 1 year ago

have you tried passing in this parameter ( { value: ethers.utils.parseEther(amount)}) to you const data = await contract.call('donateToCampaign', [pId]); like this: const data = await contract.call('donateToCampaign', [pId], { value: ethers.utils.parseEther(amount)});

Thanks @KhGunindro it worked !

MarsIfeanyi commented 1 year ago

Thanks man, this worked for me.

const donate = async (pId, amount) => { const data = await contract.call("donateToCampaign", [pId], { value: ethers.utils.parseEther(amount), }); return data; };

i was initially calling it as:

const donate = async (pId, amount) => { const data = await contract.call("donateToCampaign", pId, { value: ethers.utils.parseEther(amount), });

return data;

};