Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RED-69: support for other wallets #21

Open
wants to merge 3 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 19 additions & 28 deletions components/RemoveStakeButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ import LoadingButton from './LoadingButton';
import { ConfirmModalContext } from './ConfirmModalContextProvider';
import { isMetaMaskError } from '../utils/isMetaMaskError';
import { isEthersError } from '../utils/isEthersError';
import { Address } from 'wagmi';
import { ExternalProvider } from '@ethersproject/providers';
import { NodeStatus } from '../model/node-status'
import {useAccount} from "wagmi";

export default function RemoveStakeButton({nominee, force = false, nodeStatus}: { nominee: string, force?: boolean, nodeStatus: NodeStatus['state'] }) {
const {showTemporarySuccessMessage, showErrorDetails} = useContext(ToastContext);
const { address } = useAccount();
const {writeUnstakeLog} = useTXLogs()
const {openModal} = useContext(ConfirmModalContext);
const ethereum = window.ethereum;
Expand All @@ -33,13 +33,10 @@ export default function RemoveStakeButton({nominee, force = false, nodeStatus}:
throw new Error('MetaMask not found');
}
try {
const provider = new ethers.providers.Web3Provider(ethereum as ExternalProvider);
const signer = provider.getSigner();
const [gasPrice, from, nonce] = await Promise.all([
signer.getGasPrice(),
signer.getAddress(),
signer.getTransactionCount()
]);
const provider = new ethers.BrowserProvider(window.ethereum!);
const signer = await provider.getSigner();
const from = await signer.getAddress()
const nonce = await provider.getTransactionCount(from, 'latest');

const unstakeData = {
isInternalTx: true,
Expand All @@ -54,9 +51,8 @@ export default function RemoveStakeButton({nominee, force = false, nodeStatus}:
const params = {
from,
to: '0x0000000000000000000000000000000000010000',
gasPrice,
data: ethers.utils.hexlify(
ethers.utils.toUtf8Bytes(JSON.stringify(unstakeData))
data: ethers.hexlify(
ethers.toUtf8Bytes(JSON.stringify(unstakeData))
),
nonce
};
Expand All @@ -75,7 +71,7 @@ export default function RemoveStakeButton({nominee, force = false, nodeStatus}:
let errorMessage = (error as Error)?.message || String(error);

// 4001 is the error code for when a user rejects a transaction
if ((isMetaMaskError(error) && error.code === 4001)
if ((isMetaMaskError(error) && error.code === 4001)
|| (isEthersError(error) && error.code === 'ACTION_REJECTED')) {
errorMessage = 'Transaction rejected by user';
}
Expand All @@ -85,15 +81,15 @@ export default function RemoveStakeButton({nominee, force = false, nodeStatus}:
};

const [haveMetamask, sethaveMetamask] = useState(false);
const [accountAddress, setAccountAddress] = useState("");
const [accountAddress, setAccountAddress] = useState<string>('');

useEffect(() => {
const checkMetamaskAvailability = async () => {
const checkWalletAvailability = async () => {
if (!ethereum) {
sethaveMetamask(false);
} else sethaveMetamask(true);
};
checkMetamaskAvailability();
checkWalletAvailability();
}, [ethereum]);

const connectWallet = async () => {
Expand All @@ -106,26 +102,21 @@ export default function RemoveStakeButton({nominee, force = false, nodeStatus}:
method: "eth_requestAccounts"
});

setAccountAddress(accounts[0]);
if (!address || address.length === 0) {
console.error("No accounts returned from Ethereum provider.");
return;
}

setAccountAddress(accounts[0]!);

console.log("Account2: ", accountAddress);
await sendTransaction(accounts[0], nominee, force);
await sendTransaction(address, nominee, force);
} catch (error) {
setLoading(false);
}
};

const [isLoading, setLoading] = useState(false);
const [data, setData] = useState({
isInternalTx: true,
internalTXType: 7,
nominator: accountAddress,
timestamp: Date.now()
});

ethereum?.on?.("accountsChanged", (accounts: Address[]) => {
setData({...data, nominator: accounts[0]});
});

async function removeStake() {
setLoading(true);
Expand Down
98 changes: 41 additions & 57 deletions components/StakeForm.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import React, { ChangeEvent, useContext, useEffect, useState } from "react";
import React, {ChangeEvent, useContext, useEffect, useState} from "react";
import { ethers } from "ethers";
import { ArrowRightIcon } from "@heroicons/react/20/solid";
import { ToastContext } from "./ToastContextProvider";
import { useTXLogs } from "../hooks/useTXLogs";
import LoadingButton from "./LoadingButton";
import { isMetaMaskError } from "../utils/isMetaMaskError";
import { isEthersError } from "../utils/isEthersError";
import { ExternalProvider } from "@ethersproject/providers";
import { useAccount } from "wagmi";
import {replacer} from "../utils/bigIntReplacer";

interface StakeData {
isInternalTx: boolean;
Expand All @@ -15,38 +16,36 @@ interface StakeData {
nominee: string;
stake: string;
timestamp: number;
stakeOk: boolean;
}

type StakeFormProps = {
nominator: string;
nominee: string;
stakeAmount: string;
onStake?: () => void;
totalStaked: number;
};

export default function StakeForm({
nominator,
nominee,
stakeAmount,
onStake,
totalStaked,
}: StakeFormProps) {
const { showTemporarySuccessMessage, showErrorDetails } =
useContext(ToastContext);
const requiredStake = ethers.utils.parseEther(stakeAmount).toString();
const requiredStake = ethers.parseEther(stakeAmount).toString() ?? '0';
const ethereum = window.ethereum;
const { writeStakeLog } = useTXLogs();
const [isLoading, setLoading] = useState(false);
const [isStakeOk, setStakeOk] = useState(true);
const { address } = useAccount();
const [data, setData] = useState<StakeData>({
isInternalTx: true,
internalTXType: 6,
nominator: nominator.toLowerCase(),
nominator: address?.toLowerCase() ?? '',
nominee,
stake: requiredStake,
timestamp: Date.now(),
stakeOk: true,
});

const createStakeLog = (
Expand All @@ -62,32 +61,35 @@ export default function StakeForm({
txHash: hash,
};

return JSON.stringify(logData);
return JSON.stringify(logData, replacer);
};

function setDataWithNominator(data: StakeData): void {
return setData({
...data,
nominator: address?.toLowerCase() ?? '',
});
}

async function sendTransaction() {
setLoading(true);
let errorFlag = false;
try {
const blobData: string = JSON.stringify(data);
const provider = new ethers.providers.Web3Provider(
ethereum as ExternalProvider
);
const signer = provider.getSigner();
const [gasPrice, from, nonce] = await Promise.all([
signer.getGasPrice(),
signer.getAddress(),
signer.getTransactionCount(),
]);
const dataWithNominator = {...data, nominator: address}
const blobData: string = JSON.stringify(dataWithNominator);
const provider = new ethers.BrowserProvider(ethereum!);
const signer = await provider.getSigner();
const from = await signer.getAddress()
const nonce = await provider.getTransactionCount(from, 'latest');
console.log("BLOB: ", blobData);
console.log(stakeAmount,totalStaked);
const value = ethers.BigNumber.from(data.stake);
const totalStakeBigNumber = ethers.BigNumber.from(totalStaked);
const stakeAmountBigNumber = ethers.utils.parseUnits(stakeAmount, "ether")
const value = BigInt(data.stake);

const totalStakeBigNumber = BigInt(totalStaked);
const stakeAmountBigNumber = ethers.parseUnits(stakeAmount, "ether")

console.log(totalStakeBigNumber, stakeAmountBigNumber)
if (totalStakeBigNumber.lt(stakeAmountBigNumber) && value.lt(stakeAmountBigNumber)) {
if (totalStakeBigNumber < stakeAmountBigNumber && value < stakeAmountBigNumber) {
errorFlag = true;
throw new Error(
"Stake Amount should be greater than the required stake"
Expand All @@ -96,22 +98,17 @@ export default function StakeForm({
const params = {
from,
to: "0x0000000000000000000000000000000000010000",
gasPrice,
value,
data: ethers.utils.hexlify(ethers.utils.toUtf8Bytes(blobData)),
data: ethers.hexlify(ethers.toUtf8Bytes(blobData)),
nonce,
};
console.log("Params: ", params);

const {
hash,
data: resultData,
wait,
} = await signer.sendTransaction(params);
console.log("TX RECEIPT: ", { hash, resultData });
await writeStakeLog(createStakeLog(blobData, params, hash, from));
const txResponse = await signer.sendTransaction(params);
console.log("TX RECEIPT: ", { hash: txResponse.hash, resultData: txResponse.data });
await writeStakeLog(createStakeLog(blobData, params, txResponse.hash, from));

const txConfirmation = await wait();
const txConfirmation = await txResponse.wait();
console.log("TX CONFRIMED: ", txConfirmation);
showTemporarySuccessMessage("Stake successful!");
} catch (error: unknown) {
Expand All @@ -135,34 +132,21 @@ export default function StakeForm({
onStake?.();
}

useEffect(() => {
ethereum?.on?.("accountsChanged", (accounts: string[]) => {
setData((currentData) => ({
...currentData,
nominator: accounts[0].toLowerCase(),
}));
});
setData((currentData) => ({
...currentData,
stake: "0",
}));
}, [requiredStake, ethereum]);

function handleStakeChange(e: ChangeEvent<HTMLInputElement>) {
try {
const newValue = e.target.value.toString();
const stake = ethers.utils.parseEther(newValue).toString();
setData({
const stake = ethers.parseEther(newValue).toString();
setDataWithNominator({
...data,
stake,
stakeOk: true,
});
setStakeOk(true)
} catch (e) {
console.error(e);
setData({
setDataWithNominator({
...data,
stakeOk: false,
});
setStakeOk(false)
}
}

Expand All @@ -173,7 +157,7 @@ export default function StakeForm({
</label>
<input
id="rewardWallet"
value={data.nominator}
value={address}
type="text"
className="bg-white text-black p-3 mt-2 w-full block border border-black"
disabled
Expand All @@ -187,7 +171,7 @@ export default function StakeForm({
placeholder="Nominee Public Key"
value={data.nominee}
onChange={(e) =>
setData({ ...data, nominee: e.target.value.toLowerCase() })
setDataWithNominator({ ...data, nominee: e.target.value.toLowerCase() })
}
/>
<label className="block mt-4">Stake Amount (SHM)</label>
Expand All @@ -201,7 +185,7 @@ export default function StakeForm({
/>
<div
className={`flex items-center mb-5 ${
!data.stakeOk ? "text-red-500" : ""
!isStakeOk ? "text-red-500" : ""
}`}
>
<div className="ml-2 font-semibold">
Expand All @@ -214,7 +198,7 @@ export default function StakeForm({
onClick={async () => sendTransaction()}
isLoading={isLoading}
className={`btn btn-primary ${
isLoading || !data.stakeOk ? "btn-disabled" : ""
isLoading || !isStakeOk ? "btn-disabled" : ""
}`}
>
Stake
Expand Down
Loading