Commit b09eb8fb authored by Moody Salem's avatar Moody Salem

mess with the gas estimation code a bit to allow swapping

parent 5b49cede
...@@ -28,18 +28,20 @@ interface SwapCall { ...@@ -28,18 +28,20 @@ interface SwapCall {
value: string value: string
} }
interface SuccessfulCall { interface SwapCallEstimate {
call: SwapCall
}
interface SuccessfulCall extends SwapCallEstimate {
call: SwapCall call: SwapCall
gasEstimate: BigNumber gasEstimate: BigNumber
} }
interface FailedCall { interface FailedCall extends SwapCallEstimate {
call: SwapCall call: SwapCall
error: Error error: Error
} }
type EstimatedSwapCall = SuccessfulCall | FailedCall
/** /**
* Returns the swap calls that can be used to make the trade * Returns the swap calls that can be used to make the trade
* @param trade trade to execute * @param trade trade to execute
...@@ -141,7 +143,7 @@ export function useSwapCallback( ...@@ -141,7 +143,7 @@ export function useSwapCallback(
return { return {
state: SwapCallbackState.VALID, state: SwapCallbackState.VALID,
callback: async function onSwap(): Promise<string> { callback: async function onSwap(): Promise<string> {
const estimatedCalls: EstimatedSwapCall[] = await Promise.all( const estimatedCalls: SwapCallEstimate[] = await Promise.all(
swapCalls.map((call) => { swapCalls.map((call) => {
const { address, calldata, value } = call const { address, calldata, value } = call
...@@ -175,13 +177,24 @@ export function useSwapCallback( ...@@ -175,13 +177,24 @@ export function useSwapCallback(
console.debug('Call threw error', call, callError) console.debug('Call threw error', call, callError)
let errorMessage: string let errorMessage: string
switch (callError.reason) { switch (callError.reason) {
case 'UniswapV2Router: EXPIRED':
errorMessage =
'The transaction could not be sent because the deadline has passed. Please check that your transaction deadline is not too low.'
break
case 'UniswapV2Router: INSUFFICIENT_OUTPUT_AMOUNT': case 'UniswapV2Router: INSUFFICIENT_OUTPUT_AMOUNT':
case 'UniswapV2Router: EXCESSIVE_INPUT_AMOUNT': case 'UniswapV2Router: EXCESSIVE_INPUT_AMOUNT':
errorMessage = errorMessage =
'This transaction will not succeed either due to price movement or fee on transfer. Try increasing your slippage tolerance.' 'This transaction will not succeed either due to price movement or fee on transfer. Try increasing your slippage tolerance.'
break break
case 'UniswapV2: TRANSFER_FAILED':
errorMessage = 'The token could not be transferred. There may be an issue with the token.'
break
case 'UniswapV2: K':
errorMessage =
'The Uniswap invariant x*y=k was not satisfied by the swap. This usually means one of the tokens you are swapping incorporates custom behavior on transfer.'
break
default: default:
errorMessage = `The transaction cannot succeed due to error: ${callError.reason}. This is probably an issue with one of the tokens you are swapping.` return { call }
} }
return { call, error: new Error(errorMessage) } return { call, error: new Error(errorMessage) }
}) })
...@@ -190,21 +203,25 @@ export function useSwapCallback( ...@@ -190,21 +203,25 @@ export function useSwapCallback(
) )
// a successful estimation is a bignumber gas estimate and the next call is also a bignumber gas estimate // a successful estimation is a bignumber gas estimate and the next call is also a bignumber gas estimate
const successfulEstimation = estimatedCalls.find( let bestCallOption: SuccessfulCall | SwapCallEstimate | undefined = estimatedCalls.find(
(el, ix, list): el is SuccessfulCall => (el, ix, list): el is SuccessfulCall =>
'gasEstimate' in el && (ix === list.length - 1 || 'gasEstimate' in list[ix + 1]) 'gasEstimate' in el && (ix === list.length - 1 || 'gasEstimate' in list[ix + 1])
) )
if (!successfulEstimation) { // check if any calls errored with a recognizable error
if (!bestCallOption) {
const errorCalls = estimatedCalls.filter((call): call is FailedCall => 'error' in call) const errorCalls = estimatedCalls.filter((call): call is FailedCall => 'error' in call)
if (errorCalls.length > 0) throw errorCalls[errorCalls.length - 1].error if (errorCalls.length > 0) throw errorCalls[errorCalls.length - 1].error
throw new Error('Unexpected error. Please contact support.') const firstNoErrorCall = estimatedCalls.find<SwapCallEstimate>(
(call): call is SwapCallEstimate => !('error' in call)
)
if (!firstNoErrorCall) throw new Error('Unexpected error. Could not estimate gas for the swap.')
bestCallOption = firstNoErrorCall
} }
const { const {
call: { address, calldata, value }, call: { address, calldata, value },
gasEstimate, } = bestCallOption
} = successfulEstimation
return library return library
.getSigner() .getSigner()
...@@ -212,7 +229,10 @@ export function useSwapCallback( ...@@ -212,7 +229,10 @@ export function useSwapCallback(
from: account, from: account,
to: address, to: address,
data: calldata, data: calldata,
gasLimit: calculateGasMargin(gasEstimate), // let the wallet try if we can't estimate the gas
...('gasEstimate' in bestCallOption
? { gasLimit: calculateGasMargin(bestCallOption.gasEstimate) }
: { gasLimit: 1_000_000 }),
...(value && !isZero(value) ? { value } : {}), ...(value && !isZero(value) ? { value } : {}),
}) })
.then((response) => { .then((response) => {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment