state/user/hooks#useGasPrice TypeScript Examples
The following examples show how to use
state/user/hooks#useGasPrice.
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: useCallWithGasPrice.ts From vvs-ui with GNU General Public License v3.0 | 6 votes |
/**
* Perform a contract call with a gas price returned from useGasPrice
* @param contract Used to perform the call
* @param methodName The name of the method called
* @param methodArgs An array of arguments to pass to the method
* @param overrides An overrides object to pass to the method. gasPrice passed in here will take priority over the price returned by useGasPrice
* @returns https://docs.ethers.io/v5/api/providers/types/#providers-TransactionReceipt
*/
export function useCallWithGasPrice() {
const gasPrice = useGasPrice()
const callWithGasPrice = useCallback(
async (
contract: Contract,
methodName: string,
methodArgs: any[] = [],
overrides: CallOverrides = null,
): Promise<ethers.providers.TransactionResponse> => {
const contractMethod = get(contract, methodName)
const hasManualGasPriceOverride = overrides?.gasPrice
const tx = await contractMethod(
...methodArgs,
hasManualGasPriceOverride ? { ...overrides } : { ...overrides, gasPrice },
)
return tx
},
[gasPrice],
)
return { callWithGasPrice }
}
Example #2
Source File: useSwapCallback.ts From vvs-ui with GNU General Public License v3.0 | 4 votes |
// returns a function that will execute a swap, if the parameters are all valid
// and the user has approved the slippage adjusted input amount for the trade
export function useSwapCallback(
trade: Trade | undefined, // trade to execute, required
allowedSlippage: number = INITIAL_ALLOWED_SLIPPAGE, // in bips
recipientAddressOrName: string | null, // the ENS name or address of the recipient of the trade, or null if swap should be returned to sender
): { state: SwapCallbackState; callback: null | (() => Promise<string>); error: string | null } {
const { account, chainId, library } = useActiveWeb3React()
const gasPrice = useGasPrice()
const swapCalls = useSwapCallArguments(trade, allowedSlippage, recipientAddressOrName)
const addTransaction = useTransactionAdder()
const { address: recipientAddress } = useENS(recipientAddressOrName)
const recipient = recipientAddressOrName === null ? account : recipientAddress
return useMemo(() => {
if (!trade || !library || !account || !chainId) {
return { state: SwapCallbackState.INVALID, callback: null, error: 'Missing dependencies' }
}
if (!recipient) {
if (recipientAddressOrName !== null) {
return { state: SwapCallbackState.INVALID, callback: null, error: 'Invalid recipient' }
}
return { state: SwapCallbackState.LOADING, callback: null, error: null }
}
return {
state: SwapCallbackState.VALID,
callback: async function onSwap(): Promise<string> {
const estimatedCalls: EstimatedSwapCall[] = await Promise.all(
swapCalls.map((call) => {
const {
parameters: { methodName, args, value },
contract,
} = call
const options = !value || isZero(value) ? {} : { value }
return contract.estimateGas[methodName](...args, options)
.then((gasEstimate) => {
return {
call,
gasEstimate,
}
})
.catch((gasError) => {
console.error('Gas estimate failed, trying eth_call to extract error', call)
return contract.callStatic[methodName](...args, options)
.then((result) => {
console.error('Unexpected successful call after failed estimate gas', call, gasError, result)
return { call, error: new Error('Unexpected issue with estimating the gas. Please try again.') }
})
.catch((callError) => {
console.error('Call threw error', call, callError)
const reason: string = callError.reason || callError.data?.message || callError.message
const errorMessage = `The transaction cannot succeed due to error: ${
reason ?? 'Unknown error, check the logs'
}.`
return { call, error: new Error(errorMessage) }
})
})
}),
)
// a successful estimation is a bignumber gas estimate and the next call is also a bignumber gas estimate
const successfulEstimation = estimatedCalls.find(
(el, ix, list): el is SuccessfulCall =>
'gasEstimate' in el && (ix === list.length - 1 || 'gasEstimate' in list[ix + 1]),
)
if (!successfulEstimation) {
const errorCalls = estimatedCalls.filter((call): call is FailedCall => 'error' in call)
if (errorCalls.length > 0) throw errorCalls[errorCalls.length - 1].error
throw new Error('Unexpected error. Please contact support: none of the calls threw an error')
}
const {
call: {
contract,
parameters: { methodName, args, value },
},
gasEstimate,
} = successfulEstimation
return contract[methodName](...args, {
gasLimit: calculateGasMargin(gasEstimate),
gasPrice,
...(value && !isZero(value) ? { value, from: account } : { from: account }),
})
.then((response: any) => {
const inputSymbol = trade.inputAmount.currency.symbol
const outputSymbol = trade.outputAmount.currency.symbol
const inputAmount = trade.inputAmount.toSignificant(3)
const outputAmount = trade.outputAmount.toSignificant(3)
const base = `Swap ${inputAmount} ${inputSymbol} for ${outputAmount} ${outputSymbol}`
const withRecipient =
recipient === account
? base
: `${base} to ${
recipientAddressOrName && isAddress(recipientAddressOrName)
? truncateHash(recipientAddressOrName)
: recipientAddressOrName
}`
addTransaction(response, {
summary: withRecipient,
})
return response.hash
})
.catch((error: any) => {
// if the user rejected the tx, pass this along
if (error?.code === 4001) {
throw new Error('Transaction rejected.')
} else {
// otherwise, the error was unexpected and we need to convey that
console.error(`Swap failed`, error, methodName, args, value)
throw new Error(`Swap failed: ${error.message}`)
}
})
},
error: null,
}
}, [trade, library, account, chainId, recipient, recipientAddressOrName, swapCalls, addTransaction, gasPrice])
}
Example #3
Source File: ClaimPrizesInner.tsx From vvs-ui with GNU General Public License v3.0 | 4 votes |
ClaimInnerContainer: React.FC<ClaimInnerProps> = ({ onSuccess, roundsToClaim }) => { const { account } = useWeb3React() const { t } = useTranslation() const dispatch = useAppDispatch() const { maxNumberTicketsPerBuyOrClaim, currentLotteryId } = useLottery() const gasPrice = useGasPrice() const { toastSuccess, toastError } = useToast() const [activeClaimIndex, setActiveClaimIndex] = useState(0) const [pendingTx, setPendingTx] = useState(false) const [pendingBatchClaims, setPendingBatchClaims] = useState( Math.ceil( roundsToClaim[activeClaimIndex].ticketsWithUnclaimedRewards.length / maxNumberTicketsPerBuyOrClaim.toNumber(), ), ) const lotteryContract = useLotteryV2Contract() const activeClaimData = roundsToClaim[activeClaimIndex] const vvsPriceUsdc = usePriceVvsUsdc() const vvsReward = activeClaimData.cakeTotal const dollarReward = vvsReward.times(vvsPriceUsdc) const rewardAsBalance = getBalanceAmount(vvsReward).toNumber() const dollarRewardAsBalance = getBalanceAmount(dollarReward).toNumber() const parseUnclaimedTicketDataForClaimCall = (ticketsWithUnclaimedRewards: LotteryTicket[], lotteryId: string) => { const ticketIds = ticketsWithUnclaimedRewards.map((ticket) => { return ticket.id }) const brackets = ticketsWithUnclaimedRewards.map((ticket) => { return ticket.rewardBracket }) return { lotteryId, ticketIds, brackets } } const claimTicketsCallData = parseUnclaimedTicketDataForClaimCall( activeClaimData.ticketsWithUnclaimedRewards, activeClaimData.roundId, ) const shouldBatchRequest = maxNumberTicketsPerBuyOrClaim.lt(claimTicketsCallData.ticketIds.length) const handleProgressToNextClaim = () => { if (roundsToClaim.length > activeClaimIndex + 1) { // If there are still rounds to claim, move onto the next claim setActiveClaimIndex(activeClaimIndex + 1) dispatch(fetchUserLotteries({ account, currentLotteryId })) } else { onSuccess() } } const getTicketBatches = (ticketIds: string[], brackets: number[]): { ticketIds: string[]; brackets: number[] }[] => { const requests = [] const maxAsNumber = maxNumberTicketsPerBuyOrClaim.toNumber() for (let i = 0; i < ticketIds.length; i += maxAsNumber) { const ticketIdsSlice = ticketIds.slice(i, maxAsNumber + i) const bracketsSlice = brackets.slice(i, maxAsNumber + i) requests.push({ ticketIds: ticketIdsSlice, brackets: bracketsSlice }) } return requests } const handleClaim = async () => { const { lotteryId, ticketIds, brackets } = claimTicketsCallData setPendingTx(true) try { const tx = await callWithEstimateGas(lotteryContract, 'claimTickets', [lotteryId, ticketIds, brackets], { gasPrice, }) const receipt = await tx.wait() if (receipt.status) { toastSuccess( t('Prizes Collected!'), <ToastDescriptionWithTx txHash={receipt.transactionHash}> {t('Your CAKE prizes for round %lotteryId% have been sent to your wallet', { lotteryId })} </ToastDescriptionWithTx>, ) setPendingTx(false) handleProgressToNextClaim() } } catch (error) { console.error(error) toastError(t('Error'), t('%error% - Please try again.', { error: error.message })) setPendingTx(false) } } const handleBatchClaim = async () => { const { lotteryId, ticketIds, brackets } = claimTicketsCallData const ticketBatches = getTicketBatches(ticketIds, brackets) const transactionsToFire = ticketBatches.length const receipts = [] setPendingTx(true) // eslint-disable-next-line no-restricted-syntax for (const ticketBatch of ticketBatches) { try { /* eslint-disable no-await-in-loop */ const tx = await callWithEstimateGas( lotteryContract, 'claimTickets', [lotteryId, ticketBatch.ticketIds, ticketBatch.brackets], { gasPrice }, ) const receipt = await tx.wait() /* eslint-enable no-await-in-loop */ if (receipt.status) { // One transaction within batch has succeeded receipts.push(receipt) setPendingBatchClaims(transactionsToFire - receipts.length) // More transactions are to be done within the batch. Issue toast to give user feedback. if (receipts.length !== transactionsToFire) { toastSuccess( t('Prizes Collected!'), <ToastDescriptionWithTx txHash={receipt.transactionHash}> {t( 'Claim %claimNum% of %claimTotal% for round %lotteryId% was successful. Please confirm the next transaction', { claimNum: receipts.length, claimTotal: transactionsToFire, lotteryId, }, )} </ToastDescriptionWithTx>, ) } } } catch (error) { console.error(error) setPendingTx(false) toastError(t('Error'), t('%error% - Please try again.', { error: error.message })) break } } // Batch is finished if (receipts.length === transactionsToFire) { setPendingTx(false) toastSuccess( t('Prizes Collected!'), t('Your CAKE prizes for round %lotteryId% have been sent to your wallet', { lotteryId }), ) handleProgressToNextClaim() } } return ( <> <Flex flexDirection="column"> <Text mb="4px" textAlign={['center', null, 'left']}> {t('You won')} </Text> <Flex alignItems={['flex-start', null, 'center']} justifyContent={['flex-start', null, 'space-between']} flexDirection={['column', null, 'row']} > <Balance textAlign={['center', null, 'left']} lineHeight="1.1" value={rewardAsBalance} fontSize="44px" bold color="secondary" unit=" CAKE!" /> <PresentWonIcon ml={['0', null, '12px']} width="64px" /> </Flex> <Balance mt={['12px', null, '0']} textAlign={['center', null, 'left']} value={dollarRewardAsBalance} fontSize="12px" color="textSubtle" unit=" USD" prefix="~" /> </Flex> <Flex alignItems="center" justifyContent="center"> <Text mt="8px" fontSize="12px" color="textSubtle"> {t('Round')} #{activeClaimData.roundId} </Text> </Flex> <Flex alignItems="center" justifyContent="center"> <Button isLoading={pendingTx} endIcon={pendingTx ? <AutoRenewIcon spin color="currentColor" /> : null} mt="20px" width="100%" onClick={() => (shouldBatchRequest ? handleBatchClaim() : handleClaim())} > {pendingTx ? t('Claiming') : t('Claim')} {pendingBatchClaims > 1 ? `(${pendingBatchClaims})` : ''} </Button> </Flex> </> ) }