Skip to content

Commit

Permalink
Fix: when exact out quote swaping gets bigInt error (#334)
Browse files Browse the repository at this point in the history
* improve error message

* fee param on SwaprV3 needs to be uint24 type so it needed conversion.
- improve tokens names
- improve test spec

* small improvements
  • Loading branch information
Diogomartf authored Jan 12, 2024
1 parent fd37ded commit f207c04
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 67 deletions.
60 changes: 29 additions & 31 deletions src/entities/trades/swapr-v3/SwaprV3.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { getRoutes } from './routes'
import { maximumSlippage as defaultMaximumSlippage } from '../constants'
import { Currency } from '../../currency'
import { Token, WXDAI } from '../../token'
import JSBI from 'jsbi'

interface SwaprV3ConstructorParams {
maximumSlippage: Percent
Expand All @@ -38,6 +39,7 @@ export interface SwaprV3GetQuoteParams {
maximumSlippage?: Percent
recipient?: string
}
const ALGEBRA_FEE_PARTS_PER_MILLION = JSBI.BigInt(1_000_000)

export class SwaprV3Trade extends TradeWithSwapTransaction {
public constructor({
Expand Down Expand Up @@ -79,8 +81,13 @@ export class SwaprV3Trade extends TradeWithSwapTransaction {
maximumSlippage = maximumSlippage ?? defaultMaximumSlippage
provider = provider ?? getProvider(chainId)

invariant(
(await provider.getNetwork()).chainId == chainId,
`SwaprV3Trade.getQuote: currencies chainId does not match provider's chainId`,
)

invariant(amount.currency.address, `SwaprV3Trade.getQuote: amount.currency.address is required`)
const tokenIn = Currency.isNative(amount.currency)
const setToken = Currency.isNative(amount.currency)
? WXDAI[ChainId.GNOSIS]
: new Token(
ChainId.GNOSIS,
Expand All @@ -91,7 +98,7 @@ export class SwaprV3Trade extends TradeWithSwapTransaction {
)

invariant(quoteCurrency.address, `SwaprV3Trade.getQuote: quoteCurrency.address is required`)
const tokenOut = Currency.isNative(quoteCurrency)
const quoteToken = Currency.isNative(quoteCurrency)
? WXDAI[ChainId.GNOSIS]
: new Token(
ChainId.GNOSIS,
Expand All @@ -101,26 +108,18 @@ export class SwaprV3Trade extends TradeWithSwapTransaction {
quoteCurrency.name,
)

invariant(
(await provider.getNetwork()).chainId == chainId,
`SwaprV3Trade.getQuote: currencies chainId does not match provider's chainId`,
)

const routes = await getRoutes(tokenIn, tokenOut, chainId)
const routes = await getRoutes(setToken, quoteToken, chainId)

const fee =
routes?.length > 0 && routes[0].pools.length > 0
? new Percent(routes[0].pools[0].fee.toString(), '1000000')
: new Percent('0', '0')
? new Percent(routes[0].pools[0].fee.toString(), ALGEBRA_FEE_PARTS_PER_MILLION)
: new Percent('0', '1')

const parsedAmount = parseUnits(amount.toSignificant(), amount.currency.decimals)

if (tradeType === TradeType.EXACT_INPUT) {
const quotedAmountOut = await getQuoterContract()
.callStatic.quoteExactInputSingle(
tokenIn.address,
tokenOut.address,
parseUnits(amount.toSignificant(), amount.currency.decimals),
0,
)
.callStatic.quoteExactInputSingle(setToken.address, quoteToken.address, parsedAmount, 0)
.catch((error) => {
console.error(`Error sending quoteExactInputSingle transaction: ${error}`)
return null
Expand All @@ -130,21 +129,16 @@ export class SwaprV3Trade extends TradeWithSwapTransaction {
return new SwaprV3Trade({
maximumSlippage,
inputAmount: amount,
outputAmount: new TokenAmount(tokenOut, quotedAmountOut),
outputAmount: new TokenAmount(quoteToken, quotedAmountOut),
tradeType: tradeType,
chainId: chainId,
priceImpact: new Percent('0', '1000'),
priceImpact: new Percent('0', '100'),
fee,
})
}
} else {
const quotedAmountIn = await getQuoterContract()
.callStatic.quoteExactOutputSingle(
tokenOut.address,
amount.currency.address,
parseUnits(amount.toSignificant(), amount.currency.decimals),
0,
)
.callStatic.quoteExactOutputSingle(quoteToken.address, setToken.address, parsedAmount, 0)
.catch((error) => {
console.error(`Error sending quoteExactOutputSingle transaction: ${error}`)
return null
Expand All @@ -153,11 +147,11 @@ export class SwaprV3Trade extends TradeWithSwapTransaction {
if (quotedAmountIn) {
return new SwaprV3Trade({
maximumSlippage,
inputAmount: new TokenAmount(tokenOut, quotedAmountIn),
inputAmount: new TokenAmount(quoteToken, quotedAmountIn),
outputAmount: amount,
tradeType: tradeType,
chainId: chainId,
priceImpact: new Percent('0', '1000'),
priceImpact: new Percent('0', '100'),
fee: fee,
})
}
Expand Down Expand Up @@ -196,22 +190,26 @@ export class SwaprV3Trade extends TradeWithSwapTransaction {
public async swapTransaction(options: TradeOptions): Promise<UnsignedTransaction> {
const isNativeIn = Currency.isNative(this.inputAmount.currency)
const isNativeOut = Currency.isNative(this.outputAmount.currency)
invariant(!(isNativeIn && isNativeOut), 'SwaprV3Trade.swapTransaction: the router does not support both native in and out')
invariant(
!(isNativeIn && isNativeOut),
'SwaprV3Trade.swapTransaction: the router does not support both native in and out',
)

const recipient = validateAndParseAddress(options.recipient)
const amountIn = `0x${this.maximumAmountIn().raw.toString(16)}`
const amountOut = `0x${this.minimumAmountOut().raw.toString(16)}`

const isTradeExactInput = this.tradeType === TradeType.EXACT_INPUT
const routerContract = getRouterContract()

// Swapr Algebra Contract fee param is uint24 type
const algebraFee = this.fee.multiply(ALGEBRA_FEE_PARTS_PER_MILLION).toSignificant(1)
const baseParams = {
tokenIn: isNativeIn ? WXDAI[ChainId.GNOSIS].address : this.inputAmount.currency.address,
tokenIn: isNativeIn ? WXDAI[ChainId.GNOSIS].address : this.inputAmount.currency.address,
tokenOut: isNativeOut ? WXDAI[ChainId.GNOSIS].address : this.outputAmount.currency.address,
recipient,
deadline: dayjs().add(30, 'm').unix(),
sqrtPriceLimitX96: 0,
fee: this.fee,
fee: algebraFee,
}

const value = isNativeIn ? amountIn : undefined
Expand All @@ -230,7 +228,7 @@ export class SwaprV3Trade extends TradeWithSwapTransaction {

const methodName = isTradeExactInput ? 'exactInputSingle' : 'exactOutputSingle'
const params = isTradeExactInput ? exactInputSingleParams : exactOutputSingleParams
const populatedTransaction = await routerContract.populateTransaction[methodName](params, { value })
const populatedTransaction = await getRouterContract().populateTransaction[methodName](params, { value })

return populatedTransaction
}
Expand Down
95 changes: 59 additions & 36 deletions src/entities/trades/swapr-v3/swapr-v3.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const recipient = NULL_ADDRESS

describe('SwaprV3', () => {
describe('Quote', () => {
test('should return a EXACT INPUT quote on Gnosis for USDC - WXDAI', async () => {
test('should return a EXACT INPUT quote for USDC - WXDAI', async () => {
const currencyAmount = new TokenAmount(tokenUSDC, parseUnits('2.59', 6).toString())
const trade = await SwaprV3Trade.getQuote({
amount: currencyAmount,
Expand All @@ -34,7 +34,7 @@ describe('SwaprV3', () => {
expect(trade?.outputAmount.currency.address).toBe(tokenWXDAI.address)
})

test('should return a EXACT INPUT quote on Gnosis for WETH - WXDAI', async () => {
test('should return a EXACT INPUT quote for WETH - WXDAI', async () => {
const currencyAmount = new TokenAmount(tokenWETH, parseUnits('1', 18).toString())
const trade = await SwaprV3Trade.getQuote({
amount: currencyAmount,
Expand All @@ -50,7 +50,7 @@ describe('SwaprV3', () => {
expect(trade?.outputAmount.currency.address).toBe(tokenWXDAI.address)
})

test('should return a EXACT INPUT quote on Gnosis for SWPR - WXDAI', async () => {
test('should return a EXACT INPUT quote for SWPR - WXDAI', async () => {
const currencyAmount = new TokenAmount(tokenWXDAI, parseUnits('1', 18).toString())
const trade = await SwaprV3Trade.getQuote({
amount: currencyAmount,
Expand All @@ -66,7 +66,7 @@ describe('SwaprV3', () => {
expect(trade?.outputAmount.currency.address).toBe(tokenSWPR.address)
})

test('should return a exact output quote on Gnosis for WXDAI - USDC', async () => {
test('should return a exact output quote for WXDAI - USDC', async () => {
const currencyAmount = new TokenAmount(tokenWXDAI, parseUnits('2', 18).toString())
const trade = await SwaprV3Trade.getQuote({
quoteCurrency: tokenUSDC,
Expand All @@ -81,41 +81,41 @@ describe('SwaprV3', () => {
expect(trade?.inputAmount.currency.address).toBe(tokenUSDC.address)
})

test('should return a exact input quote for a native token XDAI - USDC', async () => {
const currencyAmount = new TokenAmount(tokenUSDC, parseUnits('2', 6).toString())
const trade = await SwaprV3Trade.getQuote({
quoteCurrency: Currency.getNative(ChainId.GNOSIS),
amount: currencyAmount,
maximumSlippage,
recipient,
tradeType: TradeType.EXACT_OUTPUT,
})
test('should return a exact input quote for a native token XDAI - USDC', async () => {
const currencyAmount = new TokenAmount(tokenUSDC, parseUnits('2', 6).toString())
const trade = await SwaprV3Trade.getQuote({
quoteCurrency: Currency.getNative(ChainId.GNOSIS),
amount: currencyAmount,
maximumSlippage,
recipient,
tradeType: TradeType.EXACT_OUTPUT,
})

expect(trade).toBeDefined()
expect(trade?.chainId).toEqual(ChainId.GNOSIS)
expect(trade?.tradeType).toEqual(TradeType.EXACT_OUTPUT)
expect(trade?.outputAmount.currency.address).toBe(tokenUSDC.address)
})
expect(trade).toBeDefined()
expect(trade?.chainId).toEqual(ChainId.GNOSIS)
expect(trade?.tradeType).toEqual(TradeType.EXACT_OUTPUT)
expect(trade?.outputAmount.currency.address).toBe(tokenUSDC.address)
})

// test('should return a EXACT INPUT quote on Gnosis for GNO - WETH', async () => {
// const currencyAmount = new TokenAmount(tokenGNO, parseUnits('1', 18).toString())
// const trade = await SwaprV3Trade.getQuote({
// amount: currencyAmount,
// quoteCurrency: tokenWETH,
// maximumSlippage,
// recipient,
// tradeType: TradeType.EXACT_INPUT,
// })

// expect(trade).toBeDefined()
// expect(trade?.chainId).toEqual(ChainId.GNOSIS)
// expect(trade?.tradeType).toEqual(TradeType.EXACT_INPUT)
// expect(trade?.outputAmount.currency.address).toBe(tokenWETH.address)
// })
// test('should return a EXACT INPUT quote on Gnosis for GNO - WETH', async () => {
// const currencyAmount = new TokenAmount(tokenGNO, parseUnits('1', 18).toString())
// const trade = await SwaprV3Trade.getQuote({
// amount: currencyAmount,
// quoteCurrency: tokenWETH,
// maximumSlippage,
// recipient,
// tradeType: TradeType.EXACT_INPUT,
// })

// expect(trade).toBeDefined()
// expect(trade?.chainId).toEqual(ChainId.GNOSIS)
// expect(trade?.tradeType).toEqual(TradeType.EXACT_INPUT)
// expect(trade?.outputAmount.currency.address).toBe(tokenWETH.address)
// })
})

describe('Swap', () => {
test('should return a swap for Gnosis for USDC - WXDAI', async () => {
test('should return a swap EXACT INPUT for USDC - WXDAI', async () => {
const currencyAmount = new TokenAmount(tokenUSDC, parseUnits('2', 6).toString())

const trade = await SwaprV3Trade.getQuote({
Expand All @@ -134,7 +134,30 @@ describe('SwaprV3', () => {
const swap = await trade?.swapTransaction(swapOptions)
expect(swap !== undefined)
})
test('should return a swap on gnosis with native token XDAI - USDC', async () => {
test('should return a swap EXACT OUTPUT for USDC - WXDAI', async () => {
const currencyAmount = new TokenAmount(tokenWXDAI, parseUnits('2', 18).toString())
const trade = await SwaprV3Trade.getQuote({
quoteCurrency: tokenUSDC,
amount: currencyAmount,
maximumSlippage,
recipient,
tradeType: TradeType.EXACT_OUTPUT,
})

expect(trade).toBeDefined()
expect(trade?.chainId).toEqual(ChainId.GNOSIS)
expect(trade?.tradeType).toEqual(TradeType.EXACT_OUTPUT)
expect(trade?.inputAmount.currency.address).toBe(tokenUSDC.address)

const swapOptions = {
recipient: recipient,
account: recipient,
}

const swap = await trade?.swapTransaction(swapOptions)
expect(swap !== undefined)
})
test('should return a swap EXACT INPUT for XDAI - USDC', async () => {
const currencyAmount = new TokenAmount(tokenUSDC, parseUnits('2', 6).toString())

const trade = await SwaprV3Trade.getQuote({
Expand All @@ -154,4 +177,4 @@ describe('SwaprV3', () => {
expect(swap !== undefined)
})
})
})
})

0 comments on commit f207c04

Please sign in to comment.