Commit e07599ef authored by Justin Domingue's avatar Justin Domingue Committed by GitHub

fix: better support decimal overflow (#2075)

* better support decimal overflow

* improve tests

* explicitly define num digits in toSignificant

* add tests for 0 decimals

* undo change to tryParseAmount and instead compute price without relying on parse

* remove console log and add test

* removed comment

* addressed pr feedback

* improve parsing logic

* addressed pr feedback
parent 311bdc19
import { Token } from '@uniswap/sdk-core'
import { tryParsePrice } from './utils'
describe('hooks', () => {
describe('#tryParsePrice', () => {
it('should return undefined if amount is not a number', () => {
const baseToken = new Token(1, '0x6b175474e89094c44da98b954eedeac495271d0f', 6)
const quoteToken = new Token(1, '0x1b175474e89094c44da98b954eedeac495271d0f', 6)
expect(tryParsePrice(undefined, undefined, undefined)).toBeUndefined()
expect(tryParsePrice(baseToken, quoteToken)).toBeUndefined()
expect(tryParsePrice(baseToken, quoteToken, '')).toBeUndefined()
expect(tryParsePrice(baseToken, quoteToken, 'abc.123')).toBeUndefined()
expect(tryParsePrice(baseToken, quoteToken, '1.2.3')).toBeUndefined()
expect(tryParsePrice(baseToken, quoteToken, '20.')).toEqual(undefined)
})
it('should return a price', () => {
const baseToken = new Token(1, '0x6b175474e89094c44da98b954eedeac495271d0f', 6)
const quoteToken = new Token(1, '0x1b175474e89094c44da98b954eedeac495271d0f', 6)
expect(tryParsePrice(baseToken, quoteToken, '20')?.toSignificant(6)).toEqual('20')
expect(tryParsePrice(baseToken, quoteToken, '20.05')?.toSignificant(6)).toEqual('20.05')
expect(tryParsePrice(baseToken, quoteToken, '20.123456789')?.toSignificant(6)).toEqual('20.1235')
expect(tryParsePrice(baseToken, quoteToken, '0.123456789')?.toSignificant(6)).toEqual('0.123457')
expect(tryParsePrice(baseToken, quoteToken, '.123456789')?.toSignificant(6)).toEqual('0.123457')
expect(
tryParsePrice(
baseToken,
quoteToken,
(2 ** 128).toLocaleString('fullwide', { useGrouping: false })
)?.toSignificant(6)
).toEqual('340282000000000000000000000000000000000')
expect(
tryParsePrice(baseToken, quoteToken, /* ~2^-128 */ '0.000000000000000000000000000587747')?.toSignificant(6)
).toEqual('0.000000000000000000000000000587747')
})
})
})
......@@ -7,9 +7,30 @@ import {
TickMath,
} from '@uniswap/v3-sdk/dist/'
import { Price, Token } from '@uniswap/sdk-core'
import { tryParseAmount } from 'state/swap/hooks'
import JSBI from 'jsbi'
export function tryParsePrice(baseToken?: Token, quoteToken?: Token, value?: string) {
if (!baseToken || !quoteToken || !value) {
return undefined
}
if (!value.match(/^\d*\.?\d+$/)) {
return undefined
}
const [whole, fraction] = value.split('.')
const decimals = fraction?.length ?? 0
const withoutDecimals = JSBI.BigInt((whole ?? '') + (fraction ?? ''))
return new Price(
baseToken,
quoteToken,
JSBI.multiply(JSBI.BigInt(10 ** decimals), JSBI.BigInt(10 ** baseToken.decimals)),
JSBI.multiply(withoutDecimals, JSBI.BigInt(10 ** quoteToken.decimals))
)
}
export function tryParseTick(
baseToken?: Token,
quoteToken?: Token,
......@@ -20,14 +41,11 @@ export function tryParseTick(
return undefined
}
// base token fixed at 1 unit, quote token amount based on typed input
const amount = tryParseAmount(value, quoteToken)
const amountOne = tryParseAmount('1', baseToken)
const price = tryParsePrice(baseToken, quoteToken, value)
if (!amount || !amountOne) return undefined
// parse the typed value into a price
const price = new Price(baseToken, quoteToken, amountOne.quotient, amount.quotient)
if (!price) {
return undefined
}
let tick: number
......
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