Commit 0db1207e authored by Moody Salem's avatar Moody Salem

bit more cleanup, move babylonianSqrt.ts from sdk-core to v2-sdk

parent 546a6b1e
...@@ -5,7 +5,6 @@ import { pack, keccak256 } from '@ethersproject/solidity' ...@@ -5,7 +5,6 @@ import { pack, keccak256 } from '@ethersproject/solidity'
import { getCreate2Address } from '@ethersproject/address' import { getCreate2Address } from '@ethersproject/address'
import { FACTORY_ADDRESS, INIT_CODE_HASH, MINIMUM_LIQUIDITY, FIVE, _997, _1000, ONE, ZERO } from '../constants' import { FACTORY_ADDRESS, INIT_CODE_HASH, MINIMUM_LIQUIDITY, FIVE, _997, _1000, ONE, ZERO } from '../constants'
import { parseBigintIsh } from '../utils'
import { InsufficientReservesError, InsufficientInputAmountError } from '../errors' import { InsufficientReservesError, InsufficientInputAmountError } from '../errors'
export class Pair { export class Pair {
...@@ -70,7 +69,7 @@ export class Pair { ...@@ -70,7 +69,7 @@ export class Pair {
/** /**
* Returns the chain ID of the tokens in the pair. * Returns the chain ID of the tokens in the pair.
*/ */
public get chainId(): ChainId { public get chainId(): ChainId | number {
return this.token0.chainId return this.token0.chainId
} }
...@@ -181,7 +180,7 @@ export class Pair { ...@@ -181,7 +180,7 @@ export class Pair {
totalSupplyAdjusted = totalSupply totalSupplyAdjusted = totalSupply
} else { } else {
invariant(!!kLast, 'K_LAST') invariant(!!kLast, 'K_LAST')
const kLastParsed = parseBigintIsh(kLast) const kLastParsed = JSBI.BigInt(kLast)
if (!JSBI.equal(kLastParsed, ZERO)) { if (!JSBI.equal(kLastParsed, ZERO)) {
const rootK = babylonianSqrt(JSBI.multiply(this.reserve0.raw, this.reserve1.raw)) const rootK = babylonianSqrt(JSBI.multiply(this.reserve0.raw, this.reserve1.raw))
const rootKLast = babylonianSqrt(kLastParsed) const rootKLast = babylonianSqrt(kLastParsed)
......
...@@ -23,23 +23,27 @@ export class Route { ...@@ -23,23 +23,27 @@ export class Route {
public constructor(pairs: Pair[], input: Currency, output?: Currency) { public constructor(pairs: Pair[], input: Currency, output?: Currency) {
invariant(pairs.length > 0, 'PAIRS') invariant(pairs.length > 0, 'PAIRS')
const chainId: ChainId | number = pairs[0].chainId
invariant( invariant(
pairs.every(pair => pair.chainId === pairs[0].chainId), pairs.every(pair => pair.chainId === chainId),
'CHAIN_IDS' 'CHAIN_IDS'
) )
const weth: Token | undefined = WETH9[chainId as ChainId]
invariant( invariant(
(input instanceof Token && pairs[0].involvesToken(input)) || (input instanceof Token && pairs[0].involvesToken(input)) ||
(input === ETHER && pairs[0].involvesToken(WETH9[pairs[0].chainId])), (input === ETHER && weth && pairs[0].involvesToken(weth)),
'INPUT' 'INPUT'
) )
invariant( invariant(
typeof output === 'undefined' || typeof output === 'undefined' ||
(output instanceof Token && pairs[pairs.length - 1].involvesToken(output)) || (output instanceof Token && pairs[pairs.length - 1].involvesToken(output)) ||
(output === ETHER && pairs[pairs.length - 1].involvesToken(WETH9[pairs[0].chainId])), (output === ETHER && weth && pairs[pairs.length - 1].involvesToken(weth)),
'OUTPUT' 'OUTPUT'
) )
const path: Token[] = [input instanceof Token ? input : WETH9[pairs[0].chainId]] const path: Token[] = [input instanceof Token ? input : weth]
for (const [i, pair] of pairs.entries()) { for (const [i, pair] of pairs.entries()) {
const currentInput = path[i] const currentInput = path[i]
invariant(currentInput.equals(pair.token0) || currentInput.equals(pair.token1), 'PATH') invariant(currentInput.equals(pair.token0) || currentInput.equals(pair.token1), 'PATH')
...@@ -53,7 +57,7 @@ export class Route { ...@@ -53,7 +57,7 @@ export class Route {
this.output = output ?? path[path.length - 1] this.output = output ?? path[path.length - 1]
} }
public get chainId(): ChainId { public get chainId(): ChainId | number {
return this.pairs[0].chainId return this.pairs[0].chainId
} }
} }
...@@ -7,6 +7,7 @@ import { ...@@ -7,6 +7,7 @@ import {
Fraction, Fraction,
Percent, Percent,
Price, Price,
sortedInsert,
Token, Token,
TokenAmount, TokenAmount,
TradeType, TradeType,
...@@ -15,7 +16,6 @@ import { ...@@ -15,7 +16,6 @@ import {
import { ONE, ZERO } from '../constants' import { ONE, ZERO } from '../constants'
import invariant from 'tiny-invariant' import invariant from 'tiny-invariant'
import { sortedInsert } from '../utils'
import { Pair } from './pair' import { Pair } from './pair'
import { Route } from './route' import { Route } from './route'
......
import { CurrencyAmount, ETHER, Percent, TradeType } from '@uniswap/sdk-core' import { CurrencyAmount, ETHER, Percent, TradeType, validateAndParseAddress } from '@uniswap/sdk-core'
import { Trade } from 'entities' import { Trade } from 'entities'
import invariant from 'tiny-invariant' import invariant from 'tiny-invariant'
import { validateAndParseAddress } from './utils'
/** /**
* Options for producing the arguments to send call to the router. * Options for producing the arguments to send call to the router.
......
import invariant from 'tiny-invariant'
import warning from 'tiny-warning'
import JSBI from 'jsbi'
import { getAddress } from '@ethersproject/address'
import { BigintIsh } from '@uniswap/sdk-core'
// warns if addresses are not checksummed
export function validateAndParseAddress(address: string): string {
try {
const checksummedAddress = getAddress(address)
warning(address === checksummedAddress, `${address} is not checksummed.`)
return checksummedAddress
} catch (error) {
invariant(false, `${address} is not a valid address.`)
}
}
export function parseBigintIsh(bigintIsh: BigintIsh): JSBI {
return bigintIsh instanceof JSBI ? bigintIsh : JSBI.BigInt(bigintIsh)
}
// given an array of items sorted by `comparator`, insert an item into its sort index and constrain the size to
// `maxSize` by removing the last item
export function sortedInsert<T>(items: T[], add: T, maxSize: number, comparator: (a: T, b: T) => number): T | null {
invariant(maxSize > 0, 'MAX_SIZE_ZERO')
// this is an invariant because the interface cannot return multiple removed items if items.length exceeds maxSize
invariant(items.length <= maxSize, 'ITEMS_SIZE')
// short circuit first item add
if (items.length === 0) {
items.push(add)
return null
} else {
const isFull = items.length === maxSize
// short circuit if full and the additional item does not come before the last item
if (isFull && comparator(items[items.length - 1], add) <= 0) {
return add
}
let lo = 0,
hi = items.length
while (lo < hi) {
const mid = (lo + hi) >>> 1
if (comparator(items[mid], add) <= 0) {
lo = mid + 1
} else {
hi = mid
}
}
items.splice(lo, 0, add)
return isFull ? items.pop()! : null
}
}
import JSBI from 'jsbi'
import babylonianSqrt from './babylonianSqrt'
describe('#babylonianSqrt', () => {
it('correct for 0-1000', () => {
for (let i = 0; i < 1000; i++) {
expect(babylonianSqrt(JSBI.BigInt(i))).toEqual(JSBI.BigInt(Math.floor(Math.sqrt(i))))
}
})
})
import JSBI from 'jsbi'
const ZERO = JSBI.BigInt(0)
const ONE = JSBI.BigInt(1)
const TWO = JSBI.BigInt(2)
const THREE = JSBI.BigInt(3)
// computes floor(babylonianSqrt(y)) using the babylonian method (not the fastest way)
export default function babylonianSqrt(y: JSBI): JSBI {
let z: JSBI = ZERO
let x: JSBI
if (JSBI.greaterThan(y, THREE)) {
z = y
x = JSBI.add(JSBI.divide(y, TWO), ONE)
while (JSBI.lessThan(x, z)) {
z = x
x = JSBI.divide(JSBI.add(JSBI.divide(y, x), x), TWO)
}
} else if (JSBI.notEqual(y, ZERO)) {
z = ONE
}
return z
}
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