components#ColoredSlider TypeScript Examples
The following examples show how to use
components#ColoredSlider.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: RemoveLiquidityModal.tsx From interface-v2 with GNU General Public License v3.0 | 4 votes |
RemoveLiquidityModal: React.FC<RemoveLiquidityModalProps> = ({
currency0,
currency1,
open,
onClose,
}) => {
const classes = useStyles();
const { palette } = useTheme();
const [showConfirm, setShowConfirm] = useState(false);
const [txPending, setTxPending] = useState(false);
const [approving, setApproving] = useState(false);
const [attemptingTxn, setAttemptingTxn] = useState(false);
const [removeErrorMessage, setRemoveErrorMessage] = useState('');
const [errorMsg, setErrorMsg] = useState('');
const [txHash, setTxHash] = useState('');
const addTransaction = useTransactionAdder();
const finalizedTransaction = useTransactionFinalizer();
const { chainId, account, library } = useActiveWeb3React();
const [tokenA, tokenB] = useMemo(
() => [
wrappedCurrency(currency0, chainId),
wrappedCurrency(currency1, chainId),
],
[currency0, currency1, chainId],
);
const { independentField, typedValue } = useBurnState();
const { pair, parsedAmounts, error } = useDerivedBurnInfo(
currency0,
currency1,
);
const deadline = useTransactionDeadline();
const { onUserInput: _onUserInput } = useBurnActionHandlers();
const [allowedSlippage] = useUserSlippageTolerance();
const onUserInput = useCallback(
(field: Field, typedValue: string) => {
return _onUserInput(field, typedValue);
},
[_onUserInput],
);
const onLiquidityInput = useCallback(
(typedValue: string): void => onUserInput(Field.LIQUIDITY, typedValue),
[onUserInput],
);
const liquidityPercentChangeCallback = useCallback(
(value: number) => {
onUserInput(Field.LIQUIDITY_PERCENT, value.toString());
},
[onUserInput],
);
const [
innerLiquidityPercentage,
setInnerLiquidityPercentage,
] = useDebouncedChangeHandler(
Number.parseInt(parsedAmounts[Field.LIQUIDITY_PERCENT].toFixed(0)),
liquidityPercentChangeCallback,
);
const userPoolBalance = useTokenBalance(
account ?? undefined,
pair?.liquidityToken,
);
const totalPoolTokens = useTotalSupply(pair?.liquidityToken);
const poolTokenPercentage =
!!userPoolBalance &&
!!totalPoolTokens &&
JSBI.greaterThanOrEqual(totalPoolTokens.raw, userPoolBalance.raw)
? new Percent(userPoolBalance.raw, totalPoolTokens.raw)
: undefined;
const formattedAmounts = {
[Field.LIQUIDITY_PERCENT]: parsedAmounts[Field.LIQUIDITY_PERCENT].equalTo(
'0',
)
? '0'
: parsedAmounts[Field.LIQUIDITY_PERCENT].lessThan(new Percent('1', '100'))
? '<1'
: parsedAmounts[Field.LIQUIDITY_PERCENT].toFixed(0),
[Field.LIQUIDITY]:
independentField === Field.LIQUIDITY
? typedValue
: parsedAmounts[Field.LIQUIDITY]?.toExact() ?? '',
[Field.CURRENCY_A]:
independentField === Field.CURRENCY_A
? typedValue
: parsedAmounts[Field.CURRENCY_A]?.toExact() ?? '',
[Field.CURRENCY_B]:
independentField === Field.CURRENCY_B
? typedValue
: parsedAmounts[Field.CURRENCY_B]?.toExact() ?? '',
};
const [token0Deposited, token1Deposited] =
!!pair &&
!!totalPoolTokens &&
!!userPoolBalance &&
JSBI.greaterThanOrEqual(totalPoolTokens.raw, userPoolBalance.raw)
? [
pair.getLiquidityValue(
pair.token0,
totalPoolTokens,
userPoolBalance,
false,
),
pair.getLiquidityValue(
pair.token1,
totalPoolTokens,
userPoolBalance,
false,
),
]
: [undefined, undefined];
const pairContract: Contract | null = usePairContract(
pair?.liquidityToken?.address,
);
const [approval, approveCallback] = useApproveCallback(
parsedAmounts[Field.LIQUIDITY],
chainId ? GlobalConst.addresses.ROUTER_ADDRESS[chainId] : undefined,
);
const onAttemptToApprove = async () => {
if (!pairContract || !pair || !library || !deadline) {
setErrorMsg('missing dependencies');
return;
}
const liquidityAmount = parsedAmounts[Field.LIQUIDITY];
if (!liquidityAmount) {
setErrorMsg('missing liquidity amount');
return;
}
setApproving(true);
try {
await approveCallback();
setApproving(false);
} catch (e) {
setApproving(false);
}
};
const handleDismissConfirmation = useCallback(() => {
setShowConfirm(false);
setTxHash('');
}, []);
const router = useRouterContract();
const onRemove = async () => {
if (!chainId || !library || !account || !deadline || !router)
throw new Error('missing dependencies');
const {
[Field.CURRENCY_A]: currencyAmountA,
[Field.CURRENCY_B]: currencyAmountB,
} = parsedAmounts;
if (!currencyAmountA || !currencyAmountB) {
throw new Error('missing currency amounts');
}
const amountsMin = {
[Field.CURRENCY_A]: calculateSlippageAmount(
currencyAmountA,
allowedSlippage,
)[0],
[Field.CURRENCY_B]: calculateSlippageAmount(
currencyAmountB,
allowedSlippage,
)[0],
};
const liquidityAmount = parsedAmounts[Field.LIQUIDITY];
if (!liquidityAmount) throw new Error('missing liquidity amount');
const currencyBIsETH = currency1 === ETHER;
const oneCurrencyIsETH = currency0 === ETHER || currencyBIsETH;
if (!tokenA || !tokenB) throw new Error('could not wrap');
let methodNames: string[],
args: Array<string | string[] | number | boolean>;
// we have approval, use normal remove liquidity
if (approval === ApprovalState.APPROVED) {
// removeLiquidityETH
if (oneCurrencyIsETH) {
methodNames = [
'removeLiquidityETH',
'removeLiquidityETHSupportingFeeOnTransferTokens',
];
args = [
currencyBIsETH ? tokenA.address : tokenB.address,
liquidityAmount.raw.toString(),
amountsMin[
currencyBIsETH ? Field.CURRENCY_A : Field.CURRENCY_B
].toString(),
amountsMin[
currencyBIsETH ? Field.CURRENCY_B : Field.CURRENCY_A
].toString(),
account,
deadline.toHexString(),
];
}
// removeLiquidity
else {
methodNames = ['removeLiquidity'];
args = [
tokenA.address,
tokenB.address,
liquidityAmount.raw.toString(),
amountsMin[Field.CURRENCY_A].toString(),
amountsMin[Field.CURRENCY_B].toString(),
account,
deadline.toHexString(),
];
}
} else {
throw new Error(
'Attempting to confirm without approval. Please contact support.',
);
}
const safeGasEstimates: (BigNumber | undefined)[] = await Promise.all(
methodNames.map((methodName) =>
router.estimateGas[methodName](...args)
.then(calculateGasMargin)
.catch((error) => {
console.error(`estimateGas failed`, methodName, args, error);
return undefined;
}),
),
);
const indexOfSuccessfulEstimation = safeGasEstimates.findIndex(
(safeGasEstimate) => BigNumber.isBigNumber(safeGasEstimate),
);
// all estimations failed...
if (indexOfSuccessfulEstimation === -1) {
console.error('This transaction would fail. Please contact support.');
} else {
const methodName = methodNames[indexOfSuccessfulEstimation];
const safeGasEstimate = safeGasEstimates[indexOfSuccessfulEstimation];
setAttemptingTxn(true);
await router[methodName](...args, {
gasLimit: safeGasEstimate,
})
.then(async (response: TransactionResponse) => {
setAttemptingTxn(false);
setTxPending(true);
const summary =
'Remove ' +
parsedAmounts[Field.CURRENCY_A]?.toSignificant(3) +
' ' +
currency0.symbol +
' and ' +
parsedAmounts[Field.CURRENCY_B]?.toSignificant(3) +
' ' +
currency1.symbol;
addTransaction(response, {
summary,
});
setTxHash(response.hash);
try {
const receipt = await response.wait();
finalizedTransaction(receipt, {
summary,
});
setTxPending(false);
} catch (error) {
setTxPending(false);
setRemoveErrorMessage('There is an error in transaction.');
}
ReactGA.event({
category: 'Liquidity',
action: 'Remove',
label: [currency0.symbol, currency1.symbol].join('/'),
});
})
.catch((error: Error) => {
setAttemptingTxn(false);
// we only care if the error is something _other_ than the user rejected the tx
console.error(error);
});
}
};
const modalHeader = () => {
return (
<Box>
<Box mt={10} mb={3} display='flex' justifyContent='center'>
<DoubleCurrencyLogo
currency0={currency0}
currency1={currency1}
size={48}
/>
</Box>
<Box mb={6} color={palette.text.primary} textAlign='center'>
<Typography variant='h6'>
Removing {formattedAmounts[Field.LIQUIDITY]} {currency0.symbol} /{' '}
{currency1.symbol} LP Tokens
<br />
You will receive {parsedAmounts[Field.CURRENCY_A]?.toSignificant(
2,
)}{' '}
{currency0.symbol} and{' '}
{parsedAmounts[Field.CURRENCY_B]?.toSignificant(2)}{' '}
{currency1.symbol}
</Typography>
</Box>
<Box mb={3} color={palette.text.secondary} textAlign='center'>
<Typography variant='body2'>
{`Output is estimated. If the price changes by more than ${allowedSlippage /
100}% your transaction will revert.`}
</Typography>
</Box>
<Box mt={2}>
<Button
style={{ width: '100%' }}
className={classes.removeButton}
onClick={onRemove}
>
Confirm
</Button>
</Box>
</Box>
);
};
return (
<CustomModal open={open} onClose={onClose}>
<Box paddingX={3} paddingY={4}>
{showConfirm && (
<TransactionConfirmationModal
isOpen={showConfirm}
onDismiss={handleDismissConfirmation}
attemptingTxn={attemptingTxn}
txPending={txPending}
hash={txHash}
content={() =>
removeErrorMessage ? (
<TransactionErrorContent
onDismiss={handleDismissConfirmation}
message={removeErrorMessage}
/>
) : (
<ConfirmationModalContent
title='Removing Liquidity'
onDismiss={handleDismissConfirmation}
content={modalHeader}
/>
)
}
pendingText=''
modalContent={
txPending
? 'Submitted transaction to remove liquidity'
: 'Successfully removed liquidity'
}
/>
)}
<Box display='flex' alignItems='center' justifyContent='space-between'>
<ArrowLeft
color={palette.text.secondary}
style={{ cursor: 'pointer' }}
onClick={onClose}
/>
<Typography
variant='subtitle2'
style={{ color: palette.text.primary }}
>
Remove Liquidity
</Typography>
<CloseIcon style={{ cursor: 'pointer' }} onClick={onClose} />
</Box>
<Box
mt={3}
bgcolor={palette.background.default}
border='1px solid rgba(105, 108, 128, 0.12)'
borderRadius='10px'
padding='16px'
>
<Box
display='flex'
alignItems='center'
justifyContent='space-between'
>
<Typography variant='body2'>
{currency0.symbol} / {currency1.symbol} LP
</Typography>
<Typography variant='body2'>
Balance: {formatTokenAmount(userPoolBalance)}
</Typography>
</Box>
<Box mt={2}>
<NumericalInput
placeholder='0'
value={formattedAmounts[Field.LIQUIDITY]}
fontSize={28}
onUserInput={(value) => {
onLiquidityInput(value);
}}
/>
</Box>
<Box display='flex' alignItems='center'>
<Box flex={1} mr={2} mt={0.5}>
<ColoredSlider
min={1}
max={100}
step={1}
value={innerLiquidityPercentage}
onChange={(evt: any, value) =>
setInnerLiquidityPercentage(value as number)
}
/>
</Box>
<Typography variant='body2'>
{formattedAmounts[Field.LIQUIDITY_PERCENT]}%
</Typography>
</Box>
</Box>
<Box display='flex' my={3} justifyContent='center'>
<ArrowDown color={palette.text.secondary} />
</Box>
<Box
padding='16px'
bgcolor={palette.secondary.light}
borderRadius='10px'
>
<Box
display='flex'
justifyContent='space-between'
alignItems='center'
>
<Typography variant='body1'>Pooled {currency0.symbol}</Typography>
<Box display='flex' alignItems='center'>
<Typography variant='body1' style={{ marginRight: 6 }}>
{formatTokenAmount(token0Deposited)}
</Typography>
<CurrencyLogo currency={currency0} />
</Box>
</Box>
<Box
mt={1}
display='flex'
justifyContent='space-between'
alignItems='center'
>
<Typography
variant='body1'
style={{ color: 'rgba(68, 138, 255, 0.5)' }}
>
- Withdraw {currency0.symbol}
</Typography>
<Typography
variant='body1'
style={{ color: 'rgba(68, 138, 255, 0.5)' }}
>
{formattedAmounts[Field.CURRENCY_A]}
</Typography>
</Box>
<Box
mt={1}
display='flex'
justifyContent='space-between'
alignItems='center'
>
<Typography variant='body1'>Pooled {currency1.symbol}</Typography>
<Box display='flex' alignItems='center'>
<Typography variant='body1' style={{ marginRight: 6 }}>
{formatTokenAmount(token1Deposited)}
</Typography>
<CurrencyLogo currency={currency1} />
</Box>
</Box>
<Box
mt={1}
display='flex'
justifyContent='space-between'
alignItems='center'
>
<Typography
variant='body1'
style={{ color: 'rgba(68, 138, 255, 0.5)' }}
>
- Withdraw {currency1.symbol}
</Typography>
<Typography
variant='body1'
style={{ color: 'rgba(68, 138, 255, 0.5)' }}
>
{formattedAmounts[Field.CURRENCY_B]}
</Typography>
</Box>
<Box
mt={1}
display='flex'
justifyContent='space-between'
alignItems='center'
>
<Typography variant='body1'>Your Pool Share</Typography>
<Typography variant='body1'>
{poolTokenPercentage
? poolTokenPercentage.toSignificant() + '%'
: '-'}
</Typography>
</Box>
</Box>
{pair && (
<Box
display='flex'
mt={2}
px={2}
alignItems='center'
justifyContent='space-between'
>
<Typography variant='body2'>
1 {currency0.symbol} ={' '}
{tokenA ? pair.priceOf(tokenA).toSignificant(6) : '-'}{' '}
{currency1.symbol}
</Typography>
<Typography variant='body2'>
1 {currency1.symbol} ={' '}
{tokenB ? pair.priceOf(tokenB).toSignificant(6) : '-'}{' '}
{currency0.symbol}
</Typography>
</Box>
)}
<Box
mt={2}
display='flex'
alignItems='center'
justifyContent='space-between'
>
<Button
className={classes.removeButton}
onClick={onAttemptToApprove}
disabled={approving || approval !== ApprovalState.NOT_APPROVED}
>
{approving
? 'Approving...'
: approval === ApprovalState.APPROVED
? 'Approved'
: 'Approve'}
</Button>
<Button
className={classes.removeButton}
onClick={() => {
setShowConfirm(true);
}}
disabled={Boolean(error) || approval !== ApprovalState.APPROVED}
>
{error || 'Remove'}
</Button>
</Box>
<Box mt={2}>
<Typography variant='body1' style={{ color: palette.error.main }}>
{errorMsg}
</Typography>
</Box>
</Box>
</CustomModal>
);
}
Example #2
Source File: StakeQuickModal.tsx From interface-v2 with GNU General Public License v3.0 | 4 votes |
StakeQuickModal: React.FC<StakeQuickModalProps> = ({ open, onClose }) => {
const classes = useStyles();
const { palette } = useTheme();
const [attempting, setAttempting] = useState(false);
const { account } = useActiveWeb3React();
const addTransaction = useTransactionAdder();
const finalizedTransaction = useTransactionFinalizer();
const quickBalance = useCurrencyBalance(
account ?? undefined,
returnTokenFromKey('QUICK'),
);
const userLiquidityUnstaked = useTokenBalance(
account ?? undefined,
returnTokenFromKey('QUICK'),
);
const [typedValue, setTypedValue] = useState('');
const [stakePercent, setStakePercent] = useState(0);
const [approving, setApproving] = useState(false);
const { parsedAmount, error } = useDerivedLairInfo(
typedValue,
returnTokenFromKey('QUICK'),
userLiquidityUnstaked,
);
const lairContract = useLairContract();
const [approval, approveCallback] = useApproveCallback(
parsedAmount,
GlobalConst.addresses.LAIR_ADDRESS,
);
const onAttemptToApprove = async () => {
if (!lairContract) throw new Error('missing dependencies');
const liquidityAmount = parsedAmount;
if (!liquidityAmount) throw new Error('missing liquidity amount');
return approveCallback();
};
const onStake = async () => {
setAttempting(true);
if (lairContract && parsedAmount) {
if (approval === ApprovalState.APPROVED) {
try {
const response: TransactionResponse = await lairContract.enter(
`0x${parsedAmount.raw.toString(16)}`,
{
gasLimit: 350000,
},
);
addTransaction(response, {
summary: `Stake QUICK`,
});
const receipt = await response.wait();
finalizedTransaction(receipt, {
summary: `Deposit dQUICK`,
});
setAttempting(false);
setStakePercent(0);
setTypedValue('');
} catch (err) {
setAttempting(false);
}
} else {
setAttempting(false);
throw new Error(
'Attempting to stake without approval or a signature. Please contact support.',
);
}
}
};
return (
<CustomModal open={open} onClose={onClose}>
<Box paddingX={3} paddingY={4}>
<Box display='flex' alignItems='center' justifyContent='space-between'>
<Typography variant='h5'>Stake QUICK</Typography>
<CloseIcon style={{ cursor: 'pointer' }} onClick={onClose} />
</Box>
<Box
mt={3}
bgcolor={palette.background.default}
border='1px solid rgba(105, 108, 128, 0.12)'
borderRadius='10px'
padding='16px'
>
<Box
display='flex'
alignItems='center'
justifyContent='space-between'
>
<Typography variant='body2'>QUICK</Typography>
<Typography variant='body2'>
Balance: {formatTokenAmount(quickBalance)}
</Typography>
</Box>
<Box mt={2} display='flex' alignItems='center'>
<NumericalInput
placeholder='0'
value={typedValue}
fontSize={28}
onUserInput={(value) => {
const totalBalance = quickBalance
? Number(quickBalance.toExact())
: 0;
setTypedValue(value);
setStakePercent(
totalBalance > 0 ? (Number(value) / totalBalance) * 100 : 0,
);
}}
/>
<Typography
variant='caption'
style={{
color: palette.primary.main,
fontWeight: 'bold',
cursor: 'pointer',
}}
onClick={() => {
setTypedValue(quickBalance ? quickBalance.toExact() : '0');
setStakePercent(100);
}}
>
MAX
</Typography>
</Box>
<Box display='flex' alignItems='center'>
<Box flex={1} mr={2} mt={0.5}>
<ColoredSlider
min={1}
max={100}
step={1}
value={stakePercent}
onChange={(evt: any, value) => {
setStakePercent(value as number);
setTypedValue(
quickBalance
? stakePercent < 100
? (
(Number(quickBalance.toExact()) * stakePercent) /
100
).toString()
: quickBalance.toExact()
: '0',
);
}}
/>
</Box>
<Typography variant='body2'>
{Math.min(stakePercent, 100).toLocaleString()}%
</Typography>
</Box>
</Box>
<Box
mt={3}
display='flex'
justifyContent='space-between'
alignItems='center'
>
<Button
className={classes.stakeButton}
disabled={approving || approval !== ApprovalState.NOT_APPROVED}
onClick={async () => {
setApproving(true);
try {
await onAttemptToApprove();
setApproving(false);
} catch (e) {
setApproving(false);
}
}}
>
{approving ? 'Approving...' : 'Approve'}
</Button>
<Button
className={classes.stakeButton}
disabled={
!!error || attempting || approval !== ApprovalState.APPROVED
}
onClick={onStake}
>
{attempting ? 'Staking...' : 'Stake'}
</Button>
</Box>
</Box>
</CustomModal>
);
}
Example #3
Source File: StakeSyrupModal.tsx From interface-v2 with GNU General Public License v3.0 | 4 votes |
StakeSyrupModal: React.FC<StakeSyrupModalProps> = ({
open,
onClose,
syrup,
}) => {
const classes = useStyles();
const { palette } = useTheme();
const [attempting, setAttempting] = useState(false);
const [hash, setHash] = useState('');
const { account, chainId, library } = useActiveWeb3React();
const addTransaction = useTransactionAdder();
const finalizedTransaction = useTransactionFinalizer();
const userLiquidityUnstaked = useTokenBalance(
account ?? undefined,
syrup.stakedAmount?.token,
);
const [typedValue, setTypedValue] = useState('');
const [stakePercent, setStakePercent] = useState(0);
const [approving, setApproving] = useState(false);
const maxAmountInput = maxAmountSpend(userLiquidityUnstaked);
const { parsedAmount, error } = useDerivedSyrupInfo(
typedValue,
syrup.stakedAmount?.token,
userLiquidityUnstaked,
);
const parsedAmountWrapped = wrappedCurrencyAmount(parsedAmount, chainId);
let hypotheticalRewardRate = syrup.rewardRate
? new TokenAmount(syrup.rewardRate.token, '0')
: undefined;
if (parsedAmountWrapped && parsedAmountWrapped.greaterThan('0')) {
hypotheticalRewardRate =
syrup.stakedAmount && syrup.totalStakedAmount
? syrup.getHypotheticalRewardRate(
syrup.stakedAmount.add(parsedAmountWrapped),
syrup.totalStakedAmount.add(parsedAmountWrapped),
)
: undefined;
}
const deadline = useTransactionDeadline();
const [approval, approveCallback] = useApproveCallback(
parsedAmount,
syrup.stakingRewardAddress,
);
const [signatureData, setSignatureData] = useState<{
v: number;
r: string;
s: string;
deadline: number;
} | null>(null);
const stakingContract = useStakingContract(syrup.stakingRewardAddress);
const onAttemptToApprove = async () => {
if (!library || !deadline) throw new Error('missing dependencies');
const liquidityAmount = parsedAmount;
if (!liquidityAmount) throw new Error('missing liquidity amount');
return approveCallback();
};
const onStake = async () => {
setAttempting(true);
if (stakingContract && parsedAmount && deadline) {
if (approval === ApprovalState.APPROVED) {
stakingContract
.stake(`0x${parsedAmount.raw.toString(16)}`, { gasLimit: 350000 })
.then(async (response: TransactionResponse) => {
addTransaction(response, {
summary: `Deposit ${syrup.stakingToken.symbol}`,
});
try {
const receipt = await response.wait();
finalizedTransaction(receipt, {
summary: `Deposit ${syrup.stakingToken.symbol}`,
});
setAttempting(false);
setStakePercent(0);
setTypedValue('');
} catch (e) {
setAttempting(false);
setStakePercent(0);
setTypedValue('');
}
})
.catch((error: any) => {
setAttempting(false);
console.log(error);
});
} else if (signatureData) {
stakingContract
.stakeWithPermit(
`0x${parsedAmount.raw.toString(16)}`,
signatureData.deadline,
signatureData.v,
signatureData.r,
signatureData.s,
{ gasLimit: 350000 },
)
.then((response: TransactionResponse) => {
addTransaction(response, {
summary: `Deposit liquidity`,
});
setHash(response.hash);
})
.catch((error: any) => {
setAttempting(false);
console.log(error);
});
} else {
setAttempting(false);
throw new Error(
'Attempting to stake without approval or a signature. Please contact support.',
);
}
}
};
return (
<CustomModal open={open} onClose={onClose}>
<Box paddingX={3} paddingY={4}>
<Box display='flex' alignItems='center' justifyContent='space-between'>
<Typography variant='h5'>
Stake {syrup.stakingToken.symbol}
</Typography>
<CloseIcon style={{ cursor: 'pointer' }} onClick={onClose} />
</Box>
<Box
mt={3}
bgcolor={palette.background.default}
border='1px solid rgba(105, 108, 128, 0.12)'
borderRadius='10px'
padding='16px'
>
<Box
display='flex'
alignItems='center'
justifyContent='space-between'
>
<Typography variant='body2'>{syrup.stakingToken.symbol}</Typography>
<Typography variant='body2'>
Balance: {formatTokenAmount(maxAmountInput)}
</Typography>
</Box>
<Box mt={2} display='flex' alignItems='center'>
<NumericalInput
placeholder='0'
value={typedValue}
fontSize={28}
onUserInput={(value) => {
setSignatureData(null);
const totalBalance = getExactTokenAmount(maxAmountInput);
const exactTypedValue = getValueTokenDecimals(
value,
syrup.stakedAmount?.token,
);
// this is to avoid input amount more than balance
if (Number(exactTypedValue) <= totalBalance) {
setTypedValue(exactTypedValue);
setStakePercent(
totalBalance > 0
? (Number(exactTypedValue) / totalBalance) * 100
: 0,
);
}
}}
/>
<Typography
variant='caption'
style={{
color: palette.primary.main,
fontWeight: 'bold',
cursor: 'pointer',
}}
onClick={() => {
setTypedValue(maxAmountInput ? maxAmountInput.toExact() : '0');
setStakePercent(100);
}}
>
MAX
</Typography>
</Box>
<Box display='flex' alignItems='center'>
<Box flex={1} mr={2} mt={0.5}>
<ColoredSlider
min={1}
max={100}
step={1}
value={stakePercent}
onChange={(_, value) => {
const percent = value as number;
setStakePercent(percent);
setTypedValue(getPartialTokenAmount(percent, maxAmountInput));
}}
/>
</Box>
<Typography variant='body2'>
{Math.min(stakePercent, 100).toLocaleString()}%
</Typography>
</Box>
</Box>
<Box
mt={2}
display='flex'
alignItems='center'
justifyContent='space-between'
>
<Typography variant='body1'>Daily Rewards</Typography>
<Typography variant='body1'>
{hypotheticalRewardRate
? formatNumber(
Number(hypotheticalRewardRate.toExact()) * getSecondsOneDay(),
)
: '-'}{' '}
{syrup.token.symbol} / day
</Typography>
</Box>
<Box
mt={3}
display='flex'
justifyContent='space-between'
alignItems='center'
>
<Button
className={classes.stakeButton}
disabled={approving || approval !== ApprovalState.NOT_APPROVED}
onClick={async () => {
setApproving(true);
try {
await onAttemptToApprove();
setApproving(false);
} catch (e) {
setApproving(false);
}
}}
>
{approving ? 'Approving...' : 'Approve'}
</Button>
<Button
className={classes.stakeButton}
disabled={
!!error || attempting || approval !== ApprovalState.APPROVED
}
onClick={onStake}
>
{attempting ? 'Staking...' : 'Stake'}
</Button>
</Box>
</Box>
</CustomModal>
);
}
Example #4
Source File: UnstakeQuickModal.tsx From interface-v2 with GNU General Public License v3.0 | 4 votes |
UnstakeQuickModal: React.FC<UnstakeQuickModalProps> = ({
open,
onClose,
}) => {
const classes = useStyles();
const { palette } = useTheme();
const [attempting, setAttempting] = useState(false);
const addTransaction = useTransactionAdder();
const lairInfo = useLairInfo();
const dQuickBalance = lairInfo.dQUICKBalance;
const [typedValue, setTypedValue] = useState('');
const [stakePercent, setStakePercent] = useState(0);
const lairContract = useLairContract();
const error =
Number(typedValue) > Number(dQuickBalance.toExact()) || !typedValue;
const onWithdraw = () => {
if (lairContract && lairInfo?.dQUICKBalance) {
setAttempting(true);
const balance = web3.utils.toWei(typedValue, 'ether');
lairContract
.leave(balance.toString(), { gasLimit: 300000 })
.then(async (response: TransactionResponse) => {
addTransaction(response, {
summary: `Unstake dQUICK`,
});
await response.wait();
setAttempting(false);
})
.catch((error: any) => {
setAttempting(false);
console.log(error);
});
}
};
return (
<CustomModal open={open} onClose={onClose}>
<Box paddingX={3} paddingY={4}>
<Box display='flex' alignItems='center' justifyContent='space-between'>
<Typography variant='h5'>Unstake dQUICK</Typography>
<CloseIcon style={{ cursor: 'pointer' }} onClick={onClose} />
</Box>
<Box
mt={3}
bgcolor={palette.background.default}
border='1px solid rgba(105, 108, 128, 0.12)'
borderRadius='10px'
padding='16px'
>
<Box
display='flex'
alignItems='center'
justifyContent='space-between'
>
<Typography variant='body2'>dQUICK</Typography>
<Typography variant='body2'>
Balance: {formatTokenAmount(dQuickBalance)}
</Typography>
</Box>
<Box mt={2} display='flex' alignItems='center'>
<NumericalInput
placeholder='0'
value={typedValue}
fontSize={28}
onUserInput={(value) => {
const totalBalance = dQuickBalance
? Number(dQuickBalance.toExact())
: 0;
setTypedValue(value);
setStakePercent(
totalBalance > 0 ? (Number(value) / totalBalance) * 100 : 0,
);
}}
/>
<Typography
variant='caption'
style={{
color: palette.primary.main,
fontWeight: 'bold',
cursor: 'pointer',
}}
onClick={() => {
setTypedValue(dQuickBalance ? dQuickBalance.toExact() : '0');
setStakePercent(100);
}}
>
MAX
</Typography>
</Box>
<Box display='flex' alignItems='center'>
<Box flex={1} mr={2} mt={0.5}>
<ColoredSlider
min={1}
max={100}
step={1}
value={stakePercent}
onChange={(evt: any, value) => {
setStakePercent(value as number);
setTypedValue(
dQuickBalance
? stakePercent < 100
? (
(Number(dQuickBalance.toExact()) * stakePercent) /
100
).toString()
: dQuickBalance.toExact()
: '0',
);
}}
/>
</Box>
<Typography variant='body2'>
{Math.min(stakePercent, 100).toLocaleString()}%
</Typography>
</Box>
</Box>
<Box mt={3}>
<Button
className={classes.stakeButton}
disabled={!!error || attempting}
onClick={onWithdraw}
>
{attempting ? 'Unstaking...' : 'Unstake'}
</Button>
</Box>
</Box>
</CustomModal>
);
}