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'
import { getCreate2Address } from '@ethersproject/address'
import { FACTORY_ADDRESS, INIT_CODE_HASH, MINIMUM_LIQUIDITY, FIVE, _997, _1000, ONE, ZERO } from '../constants'
import { parseBigintIsh } from '../utils'
import { InsufficientReservesError, InsufficientInputAmountError } from '../errors'
export class Pair {
......@@ -70,7 +69,7 @@ export class Pair {
/**
* Returns the chain ID of the tokens in the pair.
*/
public get chainId(): ChainId {
public get chainId(): ChainId | number {
return this.token0.chainId
}
......@@ -181,7 +180,7 @@ export class Pair {
totalSupplyAdjusted = totalSupply
} else {
invariant(!!kLast, 'K_LAST')
const kLastParsed = parseBigintIsh(kLast)
const kLastParsed = JSBI.BigInt(kLast)
if (!JSBI.equal(kLastParsed, ZERO)) {
const rootK = babylonianSqrt(JSBI.multiply(this.reserve0.raw, this.reserve1.raw))
const rootKLast = babylonianSqrt(kLastParsed)
......
......@@ -23,23 +23,27 @@ export class Route {
public constructor(pairs: Pair[], input: Currency, output?: Currency) {
invariant(pairs.length > 0, 'PAIRS')
const chainId: ChainId | number = pairs[0].chainId
invariant(
pairs.every(pair => pair.chainId === pairs[0].chainId),
pairs.every(pair => pair.chainId === chainId),
'CHAIN_IDS'
)
const weth: Token | undefined = WETH9[chainId as ChainId]
invariant(
(input instanceof Token && pairs[0].involvesToken(input)) ||
(input === ETHER && pairs[0].involvesToken(WETH9[pairs[0].chainId])),
(input === ETHER && weth && pairs[0].involvesToken(weth)),
'INPUT'
)
invariant(
typeof output === 'undefined' ||
(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'
)
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()) {
const currentInput = path[i]
invariant(currentInput.equals(pair.token0) || currentInput.equals(pair.token1), 'PATH')
......@@ -53,7 +57,7 @@ export class Route {
this.output = output ?? path[path.length - 1]
}
public get chainId(): ChainId {
public get chainId(): ChainId | number {
return this.pairs[0].chainId
}
}
......@@ -7,6 +7,7 @@ import {
Fraction,
Percent,
Price,
sortedInsert,
Token,
TokenAmount,
TradeType,
......@@ -15,7 +16,6 @@ import {
import { ONE, ZERO } from '../constants'
import invariant from 'tiny-invariant'
import { sortedInsert } from '../utils'
import { Pair } from './pair'
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 invariant from 'tiny-invariant'
import { validateAndParseAddress } from './utils'
/**
* 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