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

Fix: when exact out quote swaping gets bigInt error #334

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
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)
})
})
})
})
Loading