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

feat: ui-738 improve demo page (stake) #79

Merged
merged 6 commits into from
Jul 24, 2023
Merged
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
9 changes: 5 additions & 4 deletions apps/demo-react/components/ConnectDisconnect.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Button } from 'reef-knot/ui-react';
import { useDisconnect } from 'reef-knot/web3-react';
import { FlexContainer } from '../styles/global';

const ConnectDisconnect = (props: { handleOpen: () => void }) => {
const { handleOpen } = props;
Expand All @@ -9,21 +10,21 @@ const ConnectDisconnect = (props: { handleOpen: () => void }) => {
};

return (
<>
<FlexContainer>
<Button
style={{ width: '300px', alignSelf: 'center' }}
style={{ maxWidth: '300px', alignSelf: 'center' }}
onClick={handleOpen}
>
Connect wallet
</Button>
<Button
style={{ width: '200px', marginTop: '10px', alignSelf: 'center' }}
style={{ maxWidth: '200px', marginTop: '10px', alignSelf: 'center' }}
variant="text"
onClick={handleDisconnect}
>
Disconnect
</Button>
</>
</FlexContainer>
);
};

Expand Down
224 changes: 224 additions & 0 deletions apps/demo-react/components/ContractTesting.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,224 @@
import React, { useEffect, useState } from 'react';
import {
Input,
Button,
Text,
Eth,
Option,
Select,
Loader,
Section,
} from '@lidofinance/lido-ui';
import {
useContractSWR,
useSDK,
useSTETHBalance,
useSTETHContractRPC,
useSTETHContractWeb3,
} from '@lido-sdk/react';
import { useWeb3 } from 'reef-knot/web3-react';
import { parseEther } from 'ethers/lib/utils.js';
import { AddressZero } from '@ethersproject/constants';
import { BigNumber } from 'ethers';
import { formatBalance } from '../util/contractTestingUtils';
import { BlueWrapper } from './info';
import {
STETH_SUBMIT_GAS_LIMIT_DEFAULT,
useStethSubmitGasLimit,
} from '../hooks/useStethSubmitGasLimit';
import { useTxCostInUsd } from '../hooks/txCost';

const SUBMIT_EXTRA_GAS_TRANSACTION_RATIO = 1.05;

const ContractTesting = () => {
const [inputValue, setInputValue] = useState('0.0001');
const [isLoading, setIsLoading] = useState(false);

const [stakeData, setStakeData] = useState({} as any);
const [referralAddress, setReferralAddress] = useState('');
const [walletBalance, setWalletBalance] = useState('');
const [estimateGas, setEstimateGas] = useState(0);
const [isGasLoading, setGasLoading] = useState(false);
const [txError, setTxError] = useState('');
const [gasError, setGasError] = useState('');

const submitGasLimit = useStethSubmitGasLimit();
const txCostInUsd = useTxCostInUsd({ gasLimit: submitGasLimit });
const stethBalance = useSTETHBalance();
const stethContractWeb3 = useSTETHContractWeb3();

const { chainId, account } = useWeb3();
const { providerWeb3 } = useSDK();
const contractRpc = useSTETHContractRPC();
const lidoFee = useContractSWR({
contract: contractRpc,
method: 'getFee',
});

const calculateGas = async () => {
setGasError('');
setGasLoading(true);
try {
const feeData = await providerWeb3?.getFeeData();
const maxPriorityFeePerGas = feeData?.maxPriorityFeePerGas ?? undefined;

const maxFeePerGas = feeData?.maxFeePerGas ?? undefined;
const overrides = {
value: parseEther(inputValue),
maxPriorityFeePerGas,
maxFeePerGas,
};
const originalGasLimit = await stethContractWeb3?.estimateGas.submit(
referralAddress || AddressZero,
overrides,
);
setEstimateGas(originalGasLimit as any);
setGasLoading(false);
} catch (e: any) {
setEstimateGas(STETH_SUBMIT_GAS_LIMIT_DEFAULT);
setGasError(e?.message);
}
};

const stake = async () => {
setTxError('');
if (!stethContractWeb3 || !chainId) {
return;
}

try {
const feeData = await providerWeb3?.getFeeData();

const maxPriorityFeePerGas = feeData?.maxPriorityFeePerGas ?? undefined;
const maxFeePerGas = feeData?.maxFeePerGas ?? undefined;

const overrides = {
value: parseEther(inputValue),
maxPriorityFeePerGas,
maxFeePerGas,
};
const originalGasLimit = await stethContractWeb3.estimateGas.submit(
referralAddress || AddressZero,
overrides,
);

const gasLimit = originalGasLimit
? Math.ceil(
originalGasLimit.toNumber() * SUBMIT_EXTRA_GAS_TRANSACTION_RATIO,
)
: null;

const callback = async () => {
return stethContractWeb3.submit(referralAddress || AddressZero, {
...overrides,
gasLimit: gasLimit ? BigNumber.from(gasLimit) : undefined,
});
};

const transaction = await callback();

setIsLoading(true);

if (typeof transaction === 'object') {
await transaction.wait().then((data) => {
setIsLoading(false);
setStakeData(data);
});
}
} catch (error: any) {
console.log({
error,
});
setTxError(error?.reason);
}
};
useEffect(() => {
if (providerWeb3) {
const balance = async () => {
await providerWeb3
.getBalance(account || '')
.then((data) => setWalletBalance(formatBalance(data, 4)));
};
balance().catch((e) => console.log(e));
}
}, []);

return (
<Section title="Contract Testing">
<BlueWrapper>
<Select
disabled
label="Contract action"
onChange={() => null}
themeOverride="light"
defaultValue="stake"
>
<Option value="stake">Stake</Option>
</Select>
<Input
placeholder="Amount"
type="number"
leftDecorator={<Eth />}
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
/>
<Input
type="text"
placeholder="Referral Address"
value={referralAddress}
onChange={(e) => setReferralAddress(e.target.value)}
/>

<Input type="text" value={estimateGas} disabled label="Estimate GAS" />
{gasError && <Text color="warning">{gasError}</Text>}
<Button onClick={calculateGas} loading={isGasLoading}>
Calculate GAS
</Button>

<Text color="secondary">You will receive: {`${inputValue} stEth`}</Text>
<Text color="secondary">
Your Wallet Balance: {walletBalance} ETH
<br />
Your Stake Balance:{' '}
{stethBalance.data ? (
`${formatBalance(stethBalance.data, 4)} stEth`
) : (
<Loader style={{ display: 'inline' }} />
)}{' '}
<br />
Max TX cost:{' '}
{txCostInUsd ? (
` ${txCostInUsd?.toFixed(2)}$`
) : (
<Loader style={{ display: 'inline' }} />
)}{' '}
<br />
Lido Reward Fee: &nbsp;
{lidoFee.data ? (
`${lidoFee.data / 100}%`
) : (
<Loader style={{ display: 'inline' }} />
)}
</Text>
{stakeData.blockHash && (
<>
<Text>About transaction</Text>
<Text color="secondary">
Gas used: {stakeData.gasUsed.toNumber()} WEI
</Text>
<Text color="secondary">
Status: {stakeData.status && 'success'}
</Text>
</>
)}
{!stakeData.blockHash && <Text color="error">{txError}</Text>}

<Button loading={isLoading || isGasLoading} onClick={stake}>
Stake
</Button>
</BlueWrapper>
</Section>
);
};

export default ContractTesting;
3 changes: 2 additions & 1 deletion apps/demo-react/components/MainContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ const MainContainer = (props: { children: ReactNode }) => (
<div
style={{
display: 'flex',
flexDirection: 'column',
padding: '50px 20px 20px',
flexDirection: 'column',
justifyContent: 'center',
}}
>
{props.children}
Expand Down
22 changes: 22 additions & 0 deletions apps/demo-react/components/MainSection.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import React from 'react';
import { Section, Block } from '@lidofinance/lido-ui';

const MainSection: React.FC = ({ children }) => {
return (
<Section>
<Block>
<div
style={{
display: 'flex',
justifyContent: 'flex-start',
alignItems: 'flex-start',
gap: '40px',
}}
>
{children}
</div>
</Block>
</Section>
);
};
export default MainSection;
40 changes: 28 additions & 12 deletions apps/demo-react/components/ProviderWeb3WithProps.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,34 @@
import { ReactNode } from 'react';
import { mainnet, goerli } from 'wagmi/chains';
import { ProviderWeb3 } from 'reef-knot/web3-react';
import { goerli } from 'wagmi/chains';
import { ProviderWeb3, useWeb3 } from 'reef-knot/web3-react';
import { ProviderSDK } from '@lido-sdk/react';
import { rpc } from '../util/rpc';
import { WC_PROJECT_ID } from '../util/walletconnectProjectId';

const ProviderWeb3WithProps = (props: { children: ReactNode }) => (
<ProviderWeb3
defaultChainId={goerli.id}
supportedChainIds={[mainnet.id, goerli.id]}
rpc={rpc}
walletconnectProjectId={WC_PROJECT_ID}
>
{props.children}
</ProviderWeb3>
);
const SDKProvider: React.FC = ({ children }) => {
const web3 = useWeb3();
return (
<ProviderSDK
chainId={goerli.id}
supportedChainIds={[goerli.id]}
providerWeb3={web3.library}
account={web3.account ?? undefined}
>
{children}
</ProviderSDK>
);
};

const ProviderWeb3WithProps = (props: { children: ReactNode }) => {
return (
<ProviderWeb3
defaultChainId={goerli.id}
supportedChainIds={[goerli.id]}
rpc={rpc}
walletconnectProjectId={WC_PROJECT_ID}
>
<SDKProvider>{props.children}</SDKProvider>
</ProviderWeb3>
);
};
export default ProviderWeb3WithProps;
26 changes: 12 additions & 14 deletions apps/demo-react/components/ThemeSelect.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,21 @@
import { ThemeName } from '@lidofinance/lido-ui';
import { ThemeName, Select, Option, OptionValue } from '@lidofinance/lido-ui';

const ThemeSelect = (props: {
selectedTheme: ThemeName;
handleSelect: (value: ThemeName) => void;
handleSelect: (e: OptionValue) => void;
}) => {
const { selectedTheme, handleSelect } = props;
return (
<div>
<label htmlFor="themeSwitcher">
Theme:&nbsp;
<select
name="themeSwitcher"
value={selectedTheme}
onChange={(e) => handleSelect?.(e.target.value as ThemeName)}
>
<option value={ThemeName.light}>Light</option>
<option value={ThemeName.dark}>Dark</option>
</select>
</label>
<div style={{ padding: '0 32px' }}>
<Select
label="Theme"
name="themeSwitcher"
value={selectedTheme}
onChange={handleSelect}
>
<Option value={ThemeName.light}>Light</Option>
<Option value={ThemeName.dark}>Dark</Option>
</Select>
</div>
);
};
Expand Down
2 changes: 2 additions & 0 deletions apps/demo-react/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,6 @@ export { default as ProviderWeb3WithProps } from './ProviderWeb3WithProps';
export { default as ThemeSelect } from './ThemeSelect';
export { default as Wagmi } from './Wagmi';
export { default as WalletsModal } from './WalletsModal';
export { default as ContractTesting } from './ContractTesting';
export { default as MainSection } from './MainSection';
export * from './info';
Loading