Commit f34b3d9d authored by Moody Salem's avatar Moody Salem

no more instanceof

parent a371e547
import JSBI from 'jsbi'
import invariant from 'tiny-invariant'
import { ChainId, WETH9 as _WETH9, TradeType, Rounding, Token, TokenAmount } from '@uniswap/sdk-core'
import { ChainId, WETH9 as _WETH9, TradeType, Rounding, Token, CurrencyAmount } from '@uniswap/sdk-core'
import { Pair, Route, Trade } from '../index'
const ADDRESSES = [
......@@ -37,16 +37,16 @@ describe('entities', () => {
it('Pair', () => {
pairs = [
new Pair(
new TokenAmount(tokens[0], decimalize(1, tokens[0].decimals)),
new TokenAmount(tokens[1], decimalize(1, tokens[1].decimals))
new CurrencyAmount(tokens[0], decimalize(1, tokens[0].decimals)),
new CurrencyAmount(tokens[1], decimalize(1, tokens[1].decimals))
),
new Pair(
new TokenAmount(tokens[1], decimalize(1, tokens[1].decimals)),
new TokenAmount(tokens[2], decimalize(1, tokens[2].decimals))
new CurrencyAmount(tokens[1], decimalize(1, tokens[1].decimals)),
new CurrencyAmount(tokens[2], decimalize(1, tokens[2].decimals))
),
new Pair(
new TokenAmount(tokens[2], decimalize(1, tokens[2].decimals)),
new TokenAmount(WETH9, decimalize(1234, WETH9.decimals))
new CurrencyAmount(tokens[2], decimalize(1, tokens[2].decimals)),
new CurrencyAmount(WETH9, decimalize(1234, WETH9.decimals))
)
]
})
......@@ -61,14 +61,14 @@ describe('entities', () => {
})
it('Price:Route.midPrice', () => {
invariant(route.input instanceof Token)
invariant(route.output instanceof Token)
expect(route.midPrice.quote(new TokenAmount(route.input, decimalize(1, route.input.decimals)))).toEqual(
new TokenAmount(route.output, decimalize(1234, route.output.decimals))
invariant(route.input.isToken)
invariant(route.output.isToken)
expect(route.midPrice.quote(new CurrencyAmount(route.input, decimalize(1, route.input.decimals)))).toEqual(
new CurrencyAmount(route.output, decimalize(1234, route.output.decimals))
)
expect(
route.midPrice.invert().quote(new TokenAmount(route.output, decimalize(1234, route.output.decimals)))
).toEqual(new TokenAmount(route.input, decimalize(1, route.input.decimals)))
route.midPrice.invert().quote(new CurrencyAmount(route.output, decimalize(1234, route.output.decimals)))
).toEqual(new CurrencyAmount(route.input, decimalize(1, route.input.decimals)))
expect(route.midPrice.toSignificant(1)).toEqual('1000')
expect(route.midPrice.toSignificant(2)).toEqual('1200')
......@@ -105,14 +105,14 @@ describe('entities', () => {
route = new Route(
[
new Pair(
new TokenAmount(tokens[1], decimalize(5, tokens[1].decimals)),
new TokenAmount(WETH9, decimalize(10, WETH9.decimals))
new CurrencyAmount(tokens[1], decimalize(5, tokens[1].decimals)),
new CurrencyAmount(WETH9, decimalize(10, WETH9.decimals))
)
],
tokens[1]
)
const inputAmount = new TokenAmount(tokens[1], decimalize(1, tokens[1].decimals))
const expectedOutputAmount = new TokenAmount(WETH9, '1662497915624478906')
const inputAmount = new CurrencyAmount(tokens[1], decimalize(1, tokens[1].decimals))
const expectedOutputAmount = new CurrencyAmount(WETH9, '1662497915624478906')
const trade = new Trade(route, inputAmount, TradeType.EXACT_INPUT)
expect(trade.route).toEqual(route)
expect(trade.tradeType).toEqual(TradeType.EXACT_INPUT)
......@@ -131,8 +131,8 @@ describe('entities', () => {
})
it('TradeType.EXACT_OUTPUT', () => {
const outputAmount = new TokenAmount(WETH9, '1662497915624478906')
const expectedInputAmount = new TokenAmount(tokens[1], decimalize(1, tokens[1].decimals))
const outputAmount = new CurrencyAmount(WETH9, '1662497915624478906')
const expectedInputAmount = new CurrencyAmount(tokens[1], decimalize(1, tokens[1].decimals))
const trade = new Trade(route, outputAmount, TradeType.EXACT_OUTPUT)
expect(trade.route).toEqual(route)
expect(trade.tradeType).toEqual(TradeType.EXACT_OUTPUT)
......@@ -155,8 +155,8 @@ describe('entities', () => {
const route = new Route(
[
new Pair(
new TokenAmount(tokens[1], decimalize(1, tokens[1].decimals)),
new TokenAmount(
new CurrencyAmount(tokens[1], decimalize(1, tokens[1].decimals)),
new CurrencyAmount(
WETH9,
JSBI.add(
decimalize(10, WETH9.decimals),
......@@ -167,7 +167,7 @@ describe('entities', () => {
],
tokens[1]
)
const outputAmount = new TokenAmount(tokens[1], '1')
const outputAmount = new CurrencyAmount(tokens[1], '1')
const trade = new Trade(route, outputAmount, TradeType.EXACT_INPUT)
expect(trade.priceImpact.toSignificant(18)).toEqual(
......@@ -177,8 +177,8 @@ describe('entities', () => {
})
})
it('TokenAmount', () => {
const amount = new TokenAmount(WETH9, '1234567000000000000000')
it('CurrencyAmount', () => {
const amount = new CurrencyAmount(WETH9, '1234567000000000000000')
expect(amount.toExact()).toEqual('1234.567')
expect(amount.toExact({ groupSeparator: ',' })).toEqual('1,234.567')
})
......
import { ChainId, Token, TokenAmount, WETH9, Price } from '@uniswap/sdk-core'
import { ChainId, Token, WETH9, Price, CurrencyAmount, currencyEquals } from '@uniswap/sdk-core'
import { InsufficientInputAmountError } from '../errors'
import { computePairAddress, Pair } from './pair'
......@@ -43,9 +43,9 @@ describe('Pair', () => {
describe('constructor', () => {
it('cannot be used for tokens on different chains', () => {
expect(() => new Pair(new TokenAmount(USDC, '100'), new TokenAmount(WETH9[ChainId.RINKEBY], '100'))).toThrow(
'CHAIN_IDS'
)
expect(
() => new Pair(new CurrencyAmount(USDC, '100'), new CurrencyAmount(WETH9[ChainId.RINKEBY], '100'))
).toThrow('CHAIN_IDS')
})
})
......@@ -57,43 +57,43 @@ describe('Pair', () => {
describe('#token0', () => {
it('always is the token that sorts before', () => {
expect(new Pair(new TokenAmount(USDC, '100'), new TokenAmount(DAI, '100')).token0).toEqual(DAI)
expect(new Pair(new TokenAmount(DAI, '100'), new TokenAmount(USDC, '100')).token0).toEqual(DAI)
expect(new Pair(new CurrencyAmount(USDC, '100'), new CurrencyAmount(DAI, '100')).token0).toEqual(DAI)
expect(new Pair(new CurrencyAmount(DAI, '100'), new CurrencyAmount(USDC, '100')).token0).toEqual(DAI)
})
})
describe('#token1', () => {
it('always is the token that sorts after', () => {
expect(new Pair(new TokenAmount(USDC, '100'), new TokenAmount(DAI, '100')).token1).toEqual(USDC)
expect(new Pair(new TokenAmount(DAI, '100'), new TokenAmount(USDC, '100')).token1).toEqual(USDC)
expect(new Pair(new CurrencyAmount(USDC, '100'), new CurrencyAmount(DAI, '100')).token1).toEqual(USDC)
expect(new Pair(new CurrencyAmount(DAI, '100'), new CurrencyAmount(USDC, '100')).token1).toEqual(USDC)
})
})
describe('#reserve0', () => {
it('always comes from the token that sorts before', () => {
expect(new Pair(new TokenAmount(USDC, '100'), new TokenAmount(DAI, '101')).reserve0).toEqual(
new TokenAmount(DAI, '101')
expect(new Pair(new CurrencyAmount(USDC, '100'), new CurrencyAmount(DAI, '101')).reserve0).toEqual(
new CurrencyAmount(DAI, '101')
)
expect(new Pair(new TokenAmount(DAI, '101'), new TokenAmount(USDC, '100')).reserve0).toEqual(
new TokenAmount(DAI, '101')
expect(new Pair(new CurrencyAmount(DAI, '101'), new CurrencyAmount(USDC, '100')).reserve0).toEqual(
new CurrencyAmount(DAI, '101')
)
})
})
describe('#reserve1', () => {
it('always comes from the token that sorts after', () => {
expect(new Pair(new TokenAmount(USDC, '100'), new TokenAmount(DAI, '101')).reserve1).toEqual(
new TokenAmount(USDC, '100')
expect(new Pair(new CurrencyAmount(USDC, '100'), new CurrencyAmount(DAI, '101')).reserve1).toEqual(
new CurrencyAmount(USDC, '100')
)
expect(new Pair(new TokenAmount(DAI, '101'), new TokenAmount(USDC, '100')).reserve1).toEqual(
new TokenAmount(USDC, '100')
expect(new Pair(new CurrencyAmount(DAI, '101'), new CurrencyAmount(USDC, '100')).reserve1).toEqual(
new CurrencyAmount(USDC, '100')
)
})
})
describe('#token0Price', () => {
it('returns price of token0 in terms of token1', () => {
expect(new Pair(new TokenAmount(USDC, '101'), new TokenAmount(DAI, '100')).token0Price).toEqual(
expect(new Pair(new CurrencyAmount(USDC, '101'), new CurrencyAmount(DAI, '100')).token0Price).toEqual(
new Price(DAI, USDC, '100', '101')
)
expect(new Pair(new TokenAmount(DAI, '100'), new TokenAmount(USDC, '101')).token0Price).toEqual(
expect(new Pair(new CurrencyAmount(DAI, '100'), new CurrencyAmount(USDC, '101')).token0Price).toEqual(
new Price(DAI, USDC, '100', '101')
)
})
......@@ -101,17 +101,17 @@ describe('Pair', () => {
describe('#token1Price', () => {
it('returns price of token1 in terms of token0', () => {
expect(new Pair(new TokenAmount(USDC, '101'), new TokenAmount(DAI, '100')).token1Price).toEqual(
expect(new Pair(new CurrencyAmount(USDC, '101'), new CurrencyAmount(DAI, '100')).token1Price).toEqual(
new Price(USDC, DAI, '101', '100')
)
expect(new Pair(new TokenAmount(DAI, '100'), new TokenAmount(USDC, '101')).token1Price).toEqual(
expect(new Pair(new CurrencyAmount(DAI, '100'), new CurrencyAmount(USDC, '101')).token1Price).toEqual(
new Price(USDC, DAI, '101', '100')
)
})
})
describe('#priceOf', () => {
const pair = new Pair(new TokenAmount(USDC, '101'), new TokenAmount(DAI, '100'))
const pair = new Pair(new CurrencyAmount(USDC, '101'), new CurrencyAmount(DAI, '100'))
it('returns price of token in terms of other token', () => {
expect(pair.priceOf(DAI)).toEqual(pair.token0Price)
expect(pair.priceOf(USDC)).toEqual(pair.token1Price)
......@@ -124,60 +124,60 @@ describe('Pair', () => {
describe('#reserveOf', () => {
it('returns reserves of the given token', () => {
expect(new Pair(new TokenAmount(USDC, '100'), new TokenAmount(DAI, '101')).reserveOf(USDC)).toEqual(
new TokenAmount(USDC, '100')
expect(new Pair(new CurrencyAmount(USDC, '100'), new CurrencyAmount(DAI, '101')).reserveOf(USDC)).toEqual(
new CurrencyAmount(USDC, '100')
)
expect(new Pair(new TokenAmount(DAI, '101'), new TokenAmount(USDC, '100')).reserveOf(USDC)).toEqual(
new TokenAmount(USDC, '100')
expect(new Pair(new CurrencyAmount(DAI, '101'), new CurrencyAmount(USDC, '100')).reserveOf(USDC)).toEqual(
new CurrencyAmount(USDC, '100')
)
})
it('throws if not in the pair', () => {
expect(() =>
new Pair(new TokenAmount(DAI, '101'), new TokenAmount(USDC, '100')).reserveOf(WETH9[ChainId.MAINNET])
new Pair(new CurrencyAmount(DAI, '101'), new CurrencyAmount(USDC, '100')).reserveOf(WETH9[ChainId.MAINNET])
).toThrow('TOKEN')
})
})
describe('#chainId', () => {
it('returns the token0 chainId', () => {
expect(new Pair(new TokenAmount(USDC, '100'), new TokenAmount(DAI, '100')).chainId).toEqual(ChainId.MAINNET)
expect(new Pair(new TokenAmount(DAI, '100'), new TokenAmount(USDC, '100')).chainId).toEqual(ChainId.MAINNET)
expect(new Pair(new CurrencyAmount(USDC, '100'), new CurrencyAmount(DAI, '100')).chainId).toEqual(ChainId.MAINNET)
expect(new Pair(new CurrencyAmount(DAI, '100'), new CurrencyAmount(USDC, '100')).chainId).toEqual(ChainId.MAINNET)
})
})
describe('#involvesToken', () => {
expect(new Pair(new TokenAmount(USDC, '100'), new TokenAmount(DAI, '100')).involvesToken(USDC)).toEqual(true)
expect(new Pair(new TokenAmount(USDC, '100'), new TokenAmount(DAI, '100')).involvesToken(DAI)).toEqual(true)
expect(new Pair(new CurrencyAmount(USDC, '100'), new CurrencyAmount(DAI, '100')).involvesToken(USDC)).toEqual(true)
expect(new Pair(new CurrencyAmount(USDC, '100'), new CurrencyAmount(DAI, '100')).involvesToken(DAI)).toEqual(true)
expect(
new Pair(new TokenAmount(USDC, '100'), new TokenAmount(DAI, '100')).involvesToken(WETH9[ChainId.MAINNET])
new Pair(new CurrencyAmount(USDC, '100'), new CurrencyAmount(DAI, '100')).involvesToken(WETH9[ChainId.MAINNET])
).toEqual(false)
})
describe('miscellaneous', () => {
it('getLiquidityMinted:0', async () => {
const tokenA = new Token(ChainId.RINKEBY, '0x0000000000000000000000000000000000000001', 18)
const tokenB = new Token(ChainId.RINKEBY, '0x0000000000000000000000000000000000000002', 18)
const pair = new Pair(new TokenAmount(tokenA, '0'), new TokenAmount(tokenB, '0'))
const pair = new Pair(new CurrencyAmount(tokenA, '0'), new CurrencyAmount(tokenB, '0'))
expect(() => {
pair.getLiquidityMinted(
new TokenAmount(pair.liquidityToken, '0'),
new TokenAmount(tokenA, '1000'),
new TokenAmount(tokenB, '1000')
new CurrencyAmount(pair.liquidityToken, '0'),
new CurrencyAmount(tokenA, '1000'),
new CurrencyAmount(tokenB, '1000')
)
}).toThrow(InsufficientInputAmountError)
expect(() => {
pair.getLiquidityMinted(
new TokenAmount(pair.liquidityToken, '0'),
new TokenAmount(tokenA, '1000000'),
new TokenAmount(tokenB, '1')
new CurrencyAmount(pair.liquidityToken, '0'),
new CurrencyAmount(tokenA, '1000000'),
new CurrencyAmount(tokenB, '1')
)
}).toThrow(InsufficientInputAmountError)
const liquidity = pair.getLiquidityMinted(
new TokenAmount(pair.liquidityToken, '0'),
new TokenAmount(tokenA, '1001'),
new TokenAmount(tokenB, '1001')
new CurrencyAmount(pair.liquidityToken, '0'),
new CurrencyAmount(tokenA, '1001'),
new CurrencyAmount(tokenB, '1001')
)
expect(liquidity.raw.toString()).toEqual('1')
......@@ -186,14 +186,14 @@ describe('Pair', () => {
it('getLiquidityMinted:!0', async () => {
const tokenA = new Token(ChainId.RINKEBY, '0x0000000000000000000000000000000000000001', 18)
const tokenB = new Token(ChainId.RINKEBY, '0x0000000000000000000000000000000000000002', 18)
const pair = new Pair(new TokenAmount(tokenA, '10000'), new TokenAmount(tokenB, '10000'))
const pair = new Pair(new CurrencyAmount(tokenA, '10000'), new CurrencyAmount(tokenB, '10000'))
expect(
pair
.getLiquidityMinted(
new TokenAmount(pair.liquidityToken, '10000'),
new TokenAmount(tokenA, '2000'),
new TokenAmount(tokenB, '2000')
new CurrencyAmount(pair.liquidityToken, '10000'),
new CurrencyAmount(tokenA, '2000'),
new CurrencyAmount(tokenB, '2000')
)
.raw.toString()
).toEqual('2000')
......@@ -202,16 +202,16 @@ describe('Pair', () => {
it('getLiquidityValue:!feeOn', async () => {
const tokenA = new Token(ChainId.RINKEBY, '0x0000000000000000000000000000000000000001', 18)
const tokenB = new Token(ChainId.RINKEBY, '0x0000000000000000000000000000000000000002', 18)
const pair = new Pair(new TokenAmount(tokenA, '1000'), new TokenAmount(tokenB, '1000'))
const pair = new Pair(new CurrencyAmount(tokenA, '1000'), new CurrencyAmount(tokenB, '1000'))
{
const liquidityValue = pair.getLiquidityValue(
tokenA,
new TokenAmount(pair.liquidityToken, '1000'),
new TokenAmount(pair.liquidityToken, '1000'),
new CurrencyAmount(pair.liquidityToken, '1000'),
new CurrencyAmount(pair.liquidityToken, '1000'),
false
)
expect(liquidityValue.token.equals(tokenA)).toBe(true)
expect(currencyEquals(liquidityValue.currency, tokenA)).toBe(true)
expect(liquidityValue.raw.toString()).toBe('1000')
}
......@@ -219,11 +219,11 @@ describe('Pair', () => {
{
const liquidityValue = pair.getLiquidityValue(
tokenA,
new TokenAmount(pair.liquidityToken, '1000'),
new TokenAmount(pair.liquidityToken, '500'),
new CurrencyAmount(pair.liquidityToken, '1000'),
new CurrencyAmount(pair.liquidityToken, '500'),
false
)
expect(liquidityValue.token.equals(tokenA)).toBe(true)
expect(currencyEquals(liquidityValue.currency, tokenA)).toBe(true)
expect(liquidityValue.raw.toString()).toBe('500')
}
......@@ -231,11 +231,11 @@ describe('Pair', () => {
{
const liquidityValue = pair.getLiquidityValue(
tokenB,
new TokenAmount(pair.liquidityToken, '1000'),
new TokenAmount(pair.liquidityToken, '1000'),
new CurrencyAmount(pair.liquidityToken, '1000'),
new CurrencyAmount(pair.liquidityToken, '1000'),
false
)
expect(liquidityValue.token.equals(tokenB)).toBe(true)
expect(currencyEquals(liquidityValue.currency, tokenB)).toBe(true)
expect(liquidityValue.raw.toString()).toBe('1000')
}
})
......@@ -243,16 +243,16 @@ describe('Pair', () => {
it('getLiquidityValue:feeOn', async () => {
const tokenA = new Token(ChainId.RINKEBY, '0x0000000000000000000000000000000000000001', 18)
const tokenB = new Token(ChainId.RINKEBY, '0x0000000000000000000000000000000000000002', 18)
const pair = new Pair(new TokenAmount(tokenA, '1000'), new TokenAmount(tokenB, '1000'))
const pair = new Pair(new CurrencyAmount(tokenA, '1000'), new CurrencyAmount(tokenB, '1000'))
const liquidityValue = pair.getLiquidityValue(
tokenA,
new TokenAmount(pair.liquidityToken, '500'),
new TokenAmount(pair.liquidityToken, '500'),
new CurrencyAmount(pair.liquidityToken, '500'),
new CurrencyAmount(pair.liquidityToken, '500'),
true,
'250000' // 500 ** 2
)
expect(liquidityValue.token.equals(tokenA)).toBe(true)
expect(currencyEquals(liquidityValue.currency, tokenA)).toBe(true)
expect(liquidityValue.raw.toString()).toBe('917') // ceiling(1000 - (500 * (1 / 6)))
})
})
......
import { BigintIsh, ChainId, Price, sqrt, Token, TokenAmount } from '@uniswap/sdk-core'
import { BigintIsh, ChainId, Price, sqrt, Token, CurrencyAmount } from '@uniswap/sdk-core'
import invariant from 'tiny-invariant'
import JSBI from 'jsbi'
import { pack, keccak256 } from '@ethersproject/solidity'
......@@ -25,24 +25,26 @@ export const computePairAddress = ({
}
export class Pair {
public readonly liquidityToken: Token
private readonly tokenAmounts: [TokenAmount, TokenAmount]
private readonly tokenAmounts: [CurrencyAmount, CurrencyAmount]
public static getAddress(tokenA: Token, tokenB: Token): string {
return computePairAddress({ factoryAddress: FACTORY_ADDRESS, tokenA, tokenB })
}
public constructor(tokenAmountA: TokenAmount, tokenAmountB: TokenAmount) {
const tokenAmounts = tokenAmountA.token.sortsBefore(tokenAmountB.token) // does safety checks
? [tokenAmountA, tokenAmountB]
: [tokenAmountB, tokenAmountA]
public constructor(currencyAmountA: CurrencyAmount, tokenAmountB: CurrencyAmount) {
invariant(currencyAmountA.currency.isToken && tokenAmountB.currency.isToken, 'TOKEN')
const tokenAmounts = currencyAmountA.currency.sortsBefore(tokenAmountB.currency) // does safety checks
? [currencyAmountA, tokenAmountB]
: [tokenAmountB, currencyAmountA]
invariant(tokenAmounts[0].currency.isToken && tokenAmounts[1].currency.isToken, 'TOKEN')
this.liquidityToken = new Token(
tokenAmounts[0].token.chainId,
Pair.getAddress(tokenAmounts[0].token, tokenAmounts[1].token),
tokenAmounts[0].currency.chainId,
Pair.getAddress(tokenAmounts[0].currency, tokenAmounts[1].currency),
18,
'UNI-V2',
'Uniswap V2'
)
this.tokenAmounts = tokenAmounts as [TokenAmount, TokenAmount]
this.tokenAmounts = tokenAmounts as [CurrencyAmount, CurrencyAmount]
}
/**
......@@ -84,38 +86,40 @@ export class Pair {
}
public get token0(): Token {
return this.tokenAmounts[0].token
invariant(this.tokenAmounts[0].currency.isToken)
return this.tokenAmounts[0].currency
}
public get token1(): Token {
return this.tokenAmounts[1].token
invariant(this.tokenAmounts[1].currency.isToken)
return this.tokenAmounts[1].currency
}
public get reserve0(): TokenAmount {
public get reserve0(): CurrencyAmount {
return this.tokenAmounts[0]
}
public get reserve1(): TokenAmount {
public get reserve1(): CurrencyAmount {
return this.tokenAmounts[1]
}
public reserveOf(token: Token): TokenAmount {
public reserveOf(token: Token): CurrencyAmount {
invariant(this.involvesToken(token), 'TOKEN')
return token.equals(this.token0) ? this.reserve0 : this.reserve1
}
public getOutputAmount(inputAmount: TokenAmount): [TokenAmount, Pair] {
invariant(this.involvesToken(inputAmount.token), 'TOKEN')
public getOutputAmount(inputAmount: CurrencyAmount): [CurrencyAmount, Pair] {
invariant(inputAmount.currency.isToken && this.involvesToken(inputAmount.currency), 'TOKEN')
if (JSBI.equal(this.reserve0.raw, ZERO) || JSBI.equal(this.reserve1.raw, ZERO)) {
throw new InsufficientReservesError()
}
const inputReserve = this.reserveOf(inputAmount.token)
const outputReserve = this.reserveOf(inputAmount.token.equals(this.token0) ? this.token1 : this.token0)
const inputReserve = this.reserveOf(inputAmount.currency)
const outputReserve = this.reserveOf(inputAmount.currency.equals(this.token0) ? this.token1 : this.token0)
const inputAmountWithFee = JSBI.multiply(inputAmount.raw, _997)
const numerator = JSBI.multiply(inputAmountWithFee, outputReserve.raw)
const denominator = JSBI.add(JSBI.multiply(inputReserve.raw, _1000), inputAmountWithFee)
const outputAmount = new TokenAmount(
inputAmount.token.equals(this.token0) ? this.token1 : this.token0,
const outputAmount = new CurrencyAmount(
inputAmount.currency.equals(this.token0) ? this.token1 : this.token0,
JSBI.divide(numerator, denominator)
)
if (JSBI.equal(outputAmount.raw, ZERO)) {
......@@ -124,37 +128,41 @@ export class Pair {
return [outputAmount, new Pair(inputReserve.add(inputAmount), outputReserve.subtract(outputAmount))]
}
public getInputAmount(outputAmount: TokenAmount): [TokenAmount, Pair] {
invariant(this.involvesToken(outputAmount.token), 'TOKEN')
public getInputAmount(outputAmount: CurrencyAmount): [CurrencyAmount, Pair] {
invariant(outputAmount.currency.isToken && this.involvesToken(outputAmount.currency), 'TOKEN')
if (
JSBI.equal(this.reserve0.raw, ZERO) ||
JSBI.equal(this.reserve1.raw, ZERO) ||
JSBI.greaterThanOrEqual(outputAmount.raw, this.reserveOf(outputAmount.token).raw)
JSBI.greaterThanOrEqual(outputAmount.raw, this.reserveOf(outputAmount.currency).raw)
) {
throw new InsufficientReservesError()
}
const outputReserve = this.reserveOf(outputAmount.token)
const inputReserve = this.reserveOf(outputAmount.token.equals(this.token0) ? this.token1 : this.token0)
const outputReserve = this.reserveOf(outputAmount.currency)
const inputReserve = this.reserveOf(outputAmount.currency.equals(this.token0) ? this.token1 : this.token0)
const numerator = JSBI.multiply(JSBI.multiply(inputReserve.raw, outputAmount.raw), _1000)
const denominator = JSBI.multiply(JSBI.subtract(outputReserve.raw, outputAmount.raw), _997)
const inputAmount = new TokenAmount(
outputAmount.token.equals(this.token0) ? this.token1 : this.token0,
const inputAmount = new CurrencyAmount(
outputAmount.currency.equals(this.token0) ? this.token1 : this.token0,
JSBI.add(JSBI.divide(numerator, denominator), ONE)
)
return [inputAmount, new Pair(inputReserve.add(inputAmount), outputReserve.subtract(outputAmount))]
}
public getLiquidityMinted(
totalSupply: TokenAmount,
tokenAmountA: TokenAmount,
tokenAmountB: TokenAmount
): TokenAmount {
invariant(totalSupply.token.equals(this.liquidityToken), 'LIQUIDITY')
const tokenAmounts = tokenAmountA.token.sortsBefore(tokenAmountB.token) // does safety checks
? [tokenAmountA, tokenAmountB]
: [tokenAmountB, tokenAmountA]
invariant(tokenAmounts[0].token.equals(this.token0) && tokenAmounts[1].token.equals(this.token1), 'TOKEN')
totalSupply: CurrencyAmount,
tokenAmountA: CurrencyAmount,
tokenAmountB: CurrencyAmount
): CurrencyAmount {
invariant(totalSupply.currency.isToken && totalSupply.currency.equals(this.liquidityToken), 'LIQUIDITY')
const tokenAmounts =
tokenAmountA.currency.isToken &&
tokenAmountB.currency.isToken &&
tokenAmountA.currency.sortsBefore(tokenAmountB.currency) // does safety checks
? [tokenAmountA, tokenAmountB]
: [tokenAmountB, tokenAmountA]
invariant(tokenAmounts[0].currency.isToken && tokenAmounts[1].currency.isToken)
invariant(tokenAmounts[0].currency.equals(this.token0) && tokenAmounts[1].currency.equals(this.token1), 'TOKEN')
let liquidity: JSBI
if (JSBI.equal(totalSupply.raw, ZERO)) {
......@@ -167,22 +175,22 @@ export class Pair {
if (!JSBI.greaterThan(liquidity, ZERO)) {
throw new InsufficientInputAmountError()
}
return new TokenAmount(this.liquidityToken, liquidity)
return new CurrencyAmount(this.liquidityToken, liquidity)
}
public getLiquidityValue(
token: Token,
totalSupply: TokenAmount,
liquidity: TokenAmount,
totalSupply: CurrencyAmount,
liquidity: CurrencyAmount,
feeOn: boolean = false,
kLast?: BigintIsh
): TokenAmount {
): CurrencyAmount {
invariant(this.involvesToken(token), 'TOKEN')
invariant(totalSupply.token.equals(this.liquidityToken), 'TOTAL_SUPPLY')
invariant(liquidity.token.equals(this.liquidityToken), 'LIQUIDITY')
invariant(totalSupply.currency.isToken && totalSupply.currency.equals(this.liquidityToken), 'TOTAL_SUPPLY')
invariant(liquidity.currency.isToken && liquidity.currency.equals(this.liquidityToken), 'LIQUIDITY')
invariant(JSBI.lessThanOrEqual(liquidity.raw, totalSupply.raw), 'LIQUIDITY')
let totalSupplyAdjusted: TokenAmount
let totalSupplyAdjusted: CurrencyAmount
if (!feeOn) {
totalSupplyAdjusted = totalSupply
} else {
......@@ -195,7 +203,7 @@ export class Pair {
const numerator = JSBI.multiply(totalSupply.raw, JSBI.subtract(rootK, rootKLast))
const denominator = JSBI.add(JSBI.multiply(rootK, FIVE), rootKLast)
const feeLiquidity = JSBI.divide(numerator, denominator)
totalSupplyAdjusted = totalSupply.add(new TokenAmount(this.liquidityToken, feeLiquidity))
totalSupplyAdjusted = totalSupply.add(new CurrencyAmount(this.liquidityToken, feeLiquidity))
} else {
totalSupplyAdjusted = totalSupply
}
......@@ -204,7 +212,7 @@ export class Pair {
}
}
return new TokenAmount(
return new CurrencyAmount(
token,
JSBI.divide(JSBI.multiply(liquidity.raw, this.reserveOf(token).raw), totalSupplyAdjusted.raw)
)
......
import { Token, WETH9, ChainId, TokenAmount, ETHER } from '@uniswap/sdk-core'
import { Token, WETH9, ChainId, CurrencyAmount, ETHER } from '@uniswap/sdk-core'
import { Pair, Route } from './index'
describe('Route', () => {
const token0 = new Token(ChainId.MAINNET, '0x0000000000000000000000000000000000000001', 18, 't0')
const token1 = new Token(ChainId.MAINNET, '0x0000000000000000000000000000000000000002', 18, 't1')
const weth = WETH9[ChainId.MAINNET]
const pair_0_1 = new Pair(new TokenAmount(token0, '100'), new TokenAmount(token1, '200'))
const pair_0_weth = new Pair(new TokenAmount(token0, '100'), new TokenAmount(weth, '100'))
const pair_1_weth = new Pair(new TokenAmount(token1, '175'), new TokenAmount(weth, '100'))
const pair_0_1 = new Pair(new CurrencyAmount(token0, '100'), new CurrencyAmount(token1, '200'))
const pair_0_weth = new Pair(new CurrencyAmount(token0, '100'), new CurrencyAmount(weth, '100'))
const pair_1_weth = new Pair(new CurrencyAmount(token1, '175'), new CurrencyAmount(weth, '100'))
it('constructs a path from the tokens', () => {
const route = new Route([pair_0_1], token0)
......
......@@ -32,18 +32,17 @@ export class Route {
const weth: Token | undefined = WETH9[chainId as ChainId]
invariant(
(input instanceof Token && pairs[0].involvesToken(input)) ||
(input === ETHER && weth && pairs[0].involvesToken(weth)),
(input.isToken && pairs[0].involvesToken(input)) || (input === ETHER && weth && pairs[0].involvesToken(weth)),
'INPUT'
)
invariant(
typeof output === 'undefined' ||
(output instanceof Token && pairs[pairs.length - 1].involvesToken(output)) ||
(output.isToken && pairs[pairs.length - 1].involvesToken(output)) ||
(output === ETHER && weth && pairs[pairs.length - 1].involvesToken(weth)),
'OUTPUT'
)
const path: Token[] = [input instanceof Token ? input : weth]
const path: Token[] = [input.isToken ? input : weth]
for (const [i, pair] of pairs.entries()) {
const currentInput = path[i]
invariant(currentInput.equals(pair.token0) || currentInput.equals(pair.token1), 'PATH')
......
......@@ -2,7 +2,7 @@ import { Pair } from './pair'
import { Route } from './route'
import { Trade } from './trade'
import JSBI from 'jsbi'
import { ChainId, ETHER, CurrencyAmount, Percent, Token, TokenAmount, TradeType, WETH9, Price } from '@uniswap/sdk-core'
import { ChainId, ETHER, CurrencyAmount, Percent, Token, TradeType, WETH9, Price } from '@uniswap/sdk-core'
describe('Trade', () => {
const token0 = new Token(ChainId.MAINNET, '0x0000000000000000000000000000000000000001', 18, 't0')
......@@ -10,18 +10,33 @@ describe('Trade', () => {
const token2 = new Token(ChainId.MAINNET, '0x0000000000000000000000000000000000000003', 18, 't2')
const token3 = new Token(ChainId.MAINNET, '0x0000000000000000000000000000000000000004', 18, 't3')
const pair_0_1 = new Pair(new TokenAmount(token0, JSBI.BigInt(1000)), new TokenAmount(token1, JSBI.BigInt(1000)))
const pair_0_2 = new Pair(new TokenAmount(token0, JSBI.BigInt(1000)), new TokenAmount(token2, JSBI.BigInt(1100)))
const pair_0_3 = new Pair(new TokenAmount(token0, JSBI.BigInt(1000)), new TokenAmount(token3, JSBI.BigInt(900)))
const pair_1_2 = new Pair(new TokenAmount(token1, JSBI.BigInt(1200)), new TokenAmount(token2, JSBI.BigInt(1000)))
const pair_1_3 = new Pair(new TokenAmount(token1, JSBI.BigInt(1200)), new TokenAmount(token3, JSBI.BigInt(1300)))
const pair_0_1 = new Pair(
new CurrencyAmount(token0, JSBI.BigInt(1000)),
new CurrencyAmount(token1, JSBI.BigInt(1000))
)
const pair_0_2 = new Pair(
new CurrencyAmount(token0, JSBI.BigInt(1000)),
new CurrencyAmount(token2, JSBI.BigInt(1100))
)
const pair_0_3 = new Pair(new CurrencyAmount(token0, JSBI.BigInt(1000)), new CurrencyAmount(token3, JSBI.BigInt(900)))
const pair_1_2 = new Pair(
new CurrencyAmount(token1, JSBI.BigInt(1200)),
new CurrencyAmount(token2, JSBI.BigInt(1000))
)
const pair_1_3 = new Pair(
new CurrencyAmount(token1, JSBI.BigInt(1200)),
new CurrencyAmount(token3, JSBI.BigInt(1300))
)
const pair_weth_0 = new Pair(
new TokenAmount(WETH9[ChainId.MAINNET], JSBI.BigInt(1000)),
new TokenAmount(token0, JSBI.BigInt(1000))
new CurrencyAmount(WETH9[ChainId.MAINNET], JSBI.BigInt(1000)),
new CurrencyAmount(token0, JSBI.BigInt(1000))
)
const empty_pair_0_1 = new Pair(new TokenAmount(token0, JSBI.BigInt(0)), new TokenAmount(token1, JSBI.BigInt(0)))
const empty_pair_0_1 = new Pair(
new CurrencyAmount(token0, JSBI.BigInt(0)),
new CurrencyAmount(token1, JSBI.BigInt(0))
)
it('can be constructed with ETHER as input', () => {
const trade = new Trade(
......@@ -35,7 +50,7 @@ describe('Trade', () => {
it('can be constructed with ETHER as input for exact output', () => {
const trade = new Trade(
new Route([pair_weth_0], ETHER, token0),
new TokenAmount(token0, JSBI.BigInt(100)),
new CurrencyAmount(token0, JSBI.BigInt(100)),
TradeType.EXACT_OUTPUT
)
expect(trade.inputAmount.currency).toEqual(ETHER)
......@@ -54,7 +69,7 @@ describe('Trade', () => {
it('can be constructed with ETHER as output for exact input', () => {
const trade = new Trade(
new Route([pair_weth_0], token0, ETHER),
new TokenAmount(token0, JSBI.BigInt(100)),
new CurrencyAmount(token0, JSBI.BigInt(100)),
TradeType.EXACT_INPUT
)
expect(trade.inputAmount.currency).toEqual(token0)
......@@ -63,41 +78,41 @@ describe('Trade', () => {
describe('#bestTradeExactIn', () => {
it('throws with empty pairs', () => {
expect(() => Trade.bestTradeExactIn([], new TokenAmount(token0, JSBI.BigInt(100)), token2)).toThrow('PAIRS')
expect(() => Trade.bestTradeExactIn([], new CurrencyAmount(token0, JSBI.BigInt(100)), token2)).toThrow('PAIRS')
})
it('throws with max hops of 0', () => {
expect(() =>
Trade.bestTradeExactIn([pair_0_2], new TokenAmount(token0, JSBI.BigInt(100)), token2, { maxHops: 0 })
Trade.bestTradeExactIn([pair_0_2], new CurrencyAmount(token0, JSBI.BigInt(100)), token2, { maxHops: 0 })
).toThrow('MAX_HOPS')
})
it('provides best route', () => {
const result = Trade.bestTradeExactIn(
[pair_0_1, pair_0_2, pair_1_2],
new TokenAmount(token0, JSBI.BigInt(100)),
new CurrencyAmount(token0, JSBI.BigInt(100)),
token2
)
expect(result).toHaveLength(2)
expect(result[0].route.pairs).toHaveLength(1) // 0 -> 2 at 10:11
expect(result[0].route.path).toEqual([token0, token2])
expect(result[0].inputAmount).toEqual(new TokenAmount(token0, JSBI.BigInt(100)))
expect(result[0].outputAmount).toEqual(new TokenAmount(token2, JSBI.BigInt(99)))
expect(result[0].inputAmount).toEqual(new CurrencyAmount(token0, JSBI.BigInt(100)))
expect(result[0].outputAmount).toEqual(new CurrencyAmount(token2, JSBI.BigInt(99)))
expect(result[1].route.pairs).toHaveLength(2) // 0 -> 1 -> 2 at 12:12:10
expect(result[1].route.path).toEqual([token0, token1, token2])
expect(result[1].inputAmount).toEqual(new TokenAmount(token0, JSBI.BigInt(100)))
expect(result[1].outputAmount).toEqual(new TokenAmount(token2, JSBI.BigInt(69)))
expect(result[1].inputAmount).toEqual(new CurrencyAmount(token0, JSBI.BigInt(100)))
expect(result[1].outputAmount).toEqual(new CurrencyAmount(token2, JSBI.BigInt(69)))
})
it('doesnt throw for zero liquidity pairs', () => {
expect(Trade.bestTradeExactIn([empty_pair_0_1], new TokenAmount(token0, JSBI.BigInt(100)), token1)).toHaveLength(
0
)
expect(
Trade.bestTradeExactIn([empty_pair_0_1], new CurrencyAmount(token0, JSBI.BigInt(100)), token1)
).toHaveLength(0)
})
it('respects maxHops', () => {
const result = Trade.bestTradeExactIn(
[pair_0_1, pair_0_2, pair_1_2],
new TokenAmount(token0, JSBI.BigInt(10)),
new CurrencyAmount(token0, JSBI.BigInt(10)),
token2,
{ maxHops: 1 }
)
......@@ -109,19 +124,19 @@ describe('Trade', () => {
it('insufficient input for one pair', () => {
const result = Trade.bestTradeExactIn(
[pair_0_1, pair_0_2, pair_1_2],
new TokenAmount(token0, JSBI.BigInt(1)),
new CurrencyAmount(token0, JSBI.BigInt(1)),
token2
)
expect(result).toHaveLength(1)
expect(result[0].route.pairs).toHaveLength(1) // 0 -> 2 at 10:11
expect(result[0].route.path).toEqual([token0, token2])
expect(result[0].outputAmount).toEqual(new TokenAmount(token2, JSBI.BigInt(1)))
expect(result[0].outputAmount).toEqual(new CurrencyAmount(token2, JSBI.BigInt(1)))
})
it('respects n', () => {
const result = Trade.bestTradeExactIn(
[pair_0_1, pair_0_2, pair_1_2],
new TokenAmount(token0, JSBI.BigInt(10)),
new CurrencyAmount(token0, JSBI.BigInt(10)),
token2,
{ maxNumResults: 1 }
)
......@@ -132,7 +147,7 @@ describe('Trade', () => {
it('no path', () => {
const result = Trade.bestTradeExactIn(
[pair_0_1, pair_0_3, pair_1_3],
new TokenAmount(token0, JSBI.BigInt(10)),
new CurrencyAmount(token0, JSBI.BigInt(10)),
token2
)
expect(result).toHaveLength(0)
......@@ -155,7 +170,7 @@ describe('Trade', () => {
it('works for ETHER currency output', () => {
const result = Trade.bestTradeExactIn(
[pair_weth_0, pair_0_1, pair_0_3, pair_1_3],
new TokenAmount(token3, JSBI.BigInt(100)),
new CurrencyAmount(token3, JSBI.BigInt(100)),
ETHER
)
expect(result).toHaveLength(2)
......@@ -172,7 +187,7 @@ describe('Trade', () => {
describe('tradeType = EXACT_INPUT', () => {
const exactIn = new Trade(
new Route([pair_0_1, pair_1_2], token0),
new TokenAmount(token0, JSBI.BigInt(100)),
new CurrencyAmount(token0, JSBI.BigInt(100)),
TradeType.EXACT_INPUT
)
it('throws if less than 0', () => {
......@@ -185,20 +200,20 @@ describe('Trade', () => {
})
it('returns exact if nonzero', () => {
expect(exactIn.maximumAmountIn(new Percent(JSBI.BigInt(0), JSBI.BigInt(100)))).toEqual(
new TokenAmount(token0, JSBI.BigInt(100))
new CurrencyAmount(token0, JSBI.BigInt(100))
)
expect(exactIn.maximumAmountIn(new Percent(JSBI.BigInt(5), JSBI.BigInt(100)))).toEqual(
new TokenAmount(token0, JSBI.BigInt(100))
new CurrencyAmount(token0, JSBI.BigInt(100))
)
expect(exactIn.maximumAmountIn(new Percent(JSBI.BigInt(200), JSBI.BigInt(100)))).toEqual(
new TokenAmount(token0, JSBI.BigInt(100))
new CurrencyAmount(token0, JSBI.BigInt(100))
)
})
})
describe('tradeType = EXACT_OUTPUT', () => {
const exactOut = new Trade(
new Route([pair_0_1, pair_1_2], token0),
new TokenAmount(token2, JSBI.BigInt(100)),
new CurrencyAmount(token2, JSBI.BigInt(100)),
TradeType.EXACT_OUTPUT
)
......@@ -212,13 +227,13 @@ describe('Trade', () => {
})
it('returns slippage amount if nonzero', () => {
expect(exactOut.maximumAmountIn(new Percent(JSBI.BigInt(0), JSBI.BigInt(100)))).toEqual(
new TokenAmount(token0, JSBI.BigInt(156))
new CurrencyAmount(token0, JSBI.BigInt(156))
)
expect(exactOut.maximumAmountIn(new Percent(JSBI.BigInt(5), JSBI.BigInt(100)))).toEqual(
new TokenAmount(token0, JSBI.BigInt(163))
new CurrencyAmount(token0, JSBI.BigInt(163))
)
expect(exactOut.maximumAmountIn(new Percent(JSBI.BigInt(200), JSBI.BigInt(100)))).toEqual(
new TokenAmount(token0, JSBI.BigInt(468))
new CurrencyAmount(token0, JSBI.BigInt(468))
)
})
})
......@@ -228,7 +243,7 @@ describe('Trade', () => {
describe('tradeType = EXACT_INPUT', () => {
const exactIn = new Trade(
new Route([pair_0_1, pair_1_2], token0),
new TokenAmount(token0, JSBI.BigInt(100)),
new CurrencyAmount(token0, JSBI.BigInt(100)),
TradeType.EXACT_INPUT
)
it('throws if less than 0', () => {
......@@ -241,20 +256,20 @@ describe('Trade', () => {
})
it('returns exact if nonzero', () => {
expect(exactIn.minimumAmountOut(new Percent(JSBI.BigInt(0), JSBI.BigInt(100)))).toEqual(
new TokenAmount(token2, JSBI.BigInt(69))
new CurrencyAmount(token2, JSBI.BigInt(69))
)
expect(exactIn.minimumAmountOut(new Percent(JSBI.BigInt(5), JSBI.BigInt(100)))).toEqual(
new TokenAmount(token2, JSBI.BigInt(65))
new CurrencyAmount(token2, JSBI.BigInt(65))
)
expect(exactIn.minimumAmountOut(new Percent(JSBI.BigInt(200), JSBI.BigInt(100)))).toEqual(
new TokenAmount(token2, JSBI.BigInt(23))
new CurrencyAmount(token2, JSBI.BigInt(23))
)
})
})
describe('tradeType = EXACT_OUTPUT', () => {
const exactOut = new Trade(
new Route([pair_0_1, pair_1_2], token0),
new TokenAmount(token2, JSBI.BigInt(100)),
new CurrencyAmount(token2, JSBI.BigInt(100)),
TradeType.EXACT_OUTPUT
)
......@@ -268,13 +283,13 @@ describe('Trade', () => {
})
it('returns slippage amount if nonzero', () => {
expect(exactOut.minimumAmountOut(new Percent(JSBI.BigInt(0), JSBI.BigInt(100)))).toEqual(
new TokenAmount(token2, JSBI.BigInt(100))
new CurrencyAmount(token2, JSBI.BigInt(100))
)
expect(exactOut.minimumAmountOut(new Percent(JSBI.BigInt(5), JSBI.BigInt(100)))).toEqual(
new TokenAmount(token2, JSBI.BigInt(100))
new CurrencyAmount(token2, JSBI.BigInt(100))
)
expect(exactOut.minimumAmountOut(new Percent(JSBI.BigInt(200), JSBI.BigInt(100)))).toEqual(
new TokenAmount(token2, JSBI.BigInt(100))
new CurrencyAmount(token2, JSBI.BigInt(100))
)
})
})
......@@ -284,7 +299,7 @@ describe('Trade', () => {
describe('tradeType = EXACT_INPUT', () => {
const exactIn = new Trade(
new Route([pair_0_1, pair_1_2], token0),
new TokenAmount(token0, 100),
new CurrencyAmount(token0, 100),
TradeType.EXACT_INPUT
)
it('throws if less than 0', () => {
......@@ -302,7 +317,7 @@ describe('Trade', () => {
describe('tradeType = EXACT_OUTPUT', () => {
const exactOut = new Trade(
new Route([pair_0_1, pair_1_2], token0),
new TokenAmount(token2, 100),
new CurrencyAmount(token2, 100),
TradeType.EXACT_OUTPUT
)
......@@ -322,11 +337,11 @@ describe('Trade', () => {
describe('#bestTradeExactOut', () => {
it('throws with empty pairs', () => {
expect(() => Trade.bestTradeExactOut([], token0, new TokenAmount(token2, JSBI.BigInt(100)))).toThrow('PAIRS')
expect(() => Trade.bestTradeExactOut([], token0, new CurrencyAmount(token2, JSBI.BigInt(100)))).toThrow('PAIRS')
})
it('throws with max hops of 0', () => {
expect(() =>
Trade.bestTradeExactOut([pair_0_2], token0, new TokenAmount(token2, JSBI.BigInt(100)), { maxHops: 0 })
Trade.bestTradeExactOut([pair_0_2], token0, new CurrencyAmount(token2, JSBI.BigInt(100)), { maxHops: 0 })
).toThrow('MAX_HOPS')
})
......@@ -334,30 +349,30 @@ describe('Trade', () => {
const result = Trade.bestTradeExactOut(
[pair_0_1, pair_0_2, pair_1_2],
token0,
new TokenAmount(token2, JSBI.BigInt(100))
new CurrencyAmount(token2, JSBI.BigInt(100))
)
expect(result).toHaveLength(2)
expect(result[0].route.pairs).toHaveLength(1) // 0 -> 2 at 10:11
expect(result[0].route.path).toEqual([token0, token2])
expect(result[0].inputAmount).toEqual(new TokenAmount(token0, JSBI.BigInt(101)))
expect(result[0].outputAmount).toEqual(new TokenAmount(token2, JSBI.BigInt(100)))
expect(result[0].inputAmount).toEqual(new CurrencyAmount(token0, JSBI.BigInt(101)))
expect(result[0].outputAmount).toEqual(new CurrencyAmount(token2, JSBI.BigInt(100)))
expect(result[1].route.pairs).toHaveLength(2) // 0 -> 1 -> 2 at 12:12:10
expect(result[1].route.path).toEqual([token0, token1, token2])
expect(result[1].inputAmount).toEqual(new TokenAmount(token0, JSBI.BigInt(156)))
expect(result[1].outputAmount).toEqual(new TokenAmount(token2, JSBI.BigInt(100)))
expect(result[1].inputAmount).toEqual(new CurrencyAmount(token0, JSBI.BigInt(156)))
expect(result[1].outputAmount).toEqual(new CurrencyAmount(token2, JSBI.BigInt(100)))
})
it('doesnt throw for zero liquidity pairs', () => {
expect(Trade.bestTradeExactOut([empty_pair_0_1], token1, new TokenAmount(token1, JSBI.BigInt(100)))).toHaveLength(
0
)
expect(
Trade.bestTradeExactOut([empty_pair_0_1], token1, new CurrencyAmount(token1, JSBI.BigInt(100)))
).toHaveLength(0)
})
it('respects maxHops', () => {
const result = Trade.bestTradeExactOut(
[pair_0_1, pair_0_2, pair_1_2],
token0,
new TokenAmount(token2, JSBI.BigInt(10)),
new CurrencyAmount(token2, JSBI.BigInt(10)),
{ maxHops: 1 }
)
expect(result).toHaveLength(1)
......@@ -369,7 +384,7 @@ describe('Trade', () => {
const result = Trade.bestTradeExactOut(
[pair_0_1, pair_0_2, pair_1_2],
token0,
new TokenAmount(token2, JSBI.BigInt(1200))
new CurrencyAmount(token2, JSBI.BigInt(1200))
)
expect(result).toHaveLength(0)
})
......@@ -378,7 +393,7 @@ describe('Trade', () => {
const result = Trade.bestTradeExactOut(
[pair_0_1, pair_0_2, pair_1_2],
token0,
new TokenAmount(token2, JSBI.BigInt(1050))
new CurrencyAmount(token2, JSBI.BigInt(1050))
)
expect(result).toHaveLength(1)
})
......@@ -387,7 +402,7 @@ describe('Trade', () => {
const result = Trade.bestTradeExactOut(
[pair_0_1, pair_0_2, pair_1_2],
token0,
new TokenAmount(token2, JSBI.BigInt(10)),
new CurrencyAmount(token2, JSBI.BigInt(10)),
{ maxNumResults: 1 }
)
......@@ -398,7 +413,7 @@ describe('Trade', () => {
const result = Trade.bestTradeExactOut(
[pair_0_1, pair_0_3, pair_1_3],
token0,
new TokenAmount(token2, JSBI.BigInt(10))
new CurrencyAmount(token2, JSBI.BigInt(10))
)
expect(result).toHaveLength(0)
})
......@@ -407,7 +422,7 @@ describe('Trade', () => {
const result = Trade.bestTradeExactOut(
[pair_weth_0, pair_0_1, pair_0_3, pair_1_3],
ETHER,
new TokenAmount(token3, JSBI.BigInt(100))
new CurrencyAmount(token3, JSBI.BigInt(100))
)
expect(result).toHaveLength(2)
expect(result[0].inputAmount.currency).toEqual(ETHER)
......
......@@ -9,7 +9,6 @@ import {
Price,
sortedInsert,
Token,
TokenAmount,
TradeType,
WETH9
} from '@uniswap/sdk-core'
......@@ -94,16 +93,16 @@ export interface BestTradeOptions {
* In other words, if the currency is ETHER, returns the WETH9 token amount for the given chain. Otherwise, returns
* the input currency amount.
*/
function wrappedAmount(currencyAmount: CurrencyAmount, chainId: ChainId): TokenAmount {
if (currencyAmount instanceof TokenAmount) return currencyAmount
if (currencyAmount.currency === ETHER) return new TokenAmount(WETH9[chainId], currencyAmount.raw)
invariant(false, 'CURRENCY')
function wrappedAmount(currencyAmount: CurrencyAmount, chainId: ChainId): CurrencyAmount {
if (currencyAmount.currency.isToken) return currencyAmount
if (currencyAmount.currency.isEther) return new CurrencyAmount(WETH9[chainId], currencyAmount.raw)
throw new Error('CURRENCY')
}
function wrappedCurrency(currency: Currency, chainId: ChainId): Token {
if (currency instanceof Token) return currency
if (currency.isToken) return currency
if (currency === ETHER) return WETH9[chainId]
invariant(false, 'CURRENCY')
throw new Error('CURRENCY')
}
/**
......@@ -159,7 +158,7 @@ export class Trade {
}
public constructor(route: Route, amount: CurrencyAmount, tradeType: TradeType) {
const amounts: TokenAmount[] = new Array(route.path.length)
const amounts: CurrencyAmount[] = new Array(route.path.length)
const nextPairs: Pair[] = new Array(route.pairs.length)
if (tradeType === TradeType.EXACT_INPUT) {
invariant(currencyEquals(amount.currency, route.input), 'INPUT')
......@@ -218,9 +217,7 @@ export class Trade {
.add(slippageTolerance)
.invert()
.multiply(this.outputAmount.raw).quotient
return this.outputAmount instanceof TokenAmount
? new TokenAmount(this.outputAmount.token, slippageAdjustedAmountOut)
: CurrencyAmount.ether(slippageAdjustedAmountOut)
return new CurrencyAmount(this.outputAmount.currency, slippageAdjustedAmountOut)
}
}
......@@ -234,9 +231,7 @@ export class Trade {
return this.inputAmount
} else {
const slippageAdjustedAmountIn = new Fraction(ONE).add(slippageTolerance).multiply(this.inputAmount.raw).quotient
return this.inputAmount instanceof TokenAmount
? new TokenAmount(this.inputAmount.token, slippageAdjustedAmountIn)
: CurrencyAmount.ether(slippageAdjustedAmountIn)
return new CurrencyAmount(this.inputAmount.currency, slippageAdjustedAmountIn)
}
}
......@@ -267,12 +262,11 @@ export class Trade {
invariant(pairs.length > 0, 'PAIRS')
invariant(maxHops > 0, 'MAX_HOPS')
invariant(originalAmountIn === currencyAmountIn || currentPairs.length > 0, 'INVALID_RECURSION')
const chainId: ChainId | undefined =
currencyAmountIn instanceof TokenAmount
? currencyAmountIn.token.chainId
: currencyOut instanceof Token
? currencyOut.chainId
: undefined
const chainId: ChainId | undefined = currencyAmountIn.currency.isToken
? currencyAmountIn.currency.chainId
: currencyOut.isToken
? currencyOut.chainId
: undefined
invariant(chainId !== undefined, 'CHAIN_ID')
const amountIn = wrappedAmount(currencyAmountIn, chainId)
......@@ -280,10 +274,10 @@ export class Trade {
for (let i = 0; i < pairs.length; i++) {
const pair = pairs[i]
// pair irrelevant
if (!pair.token0.equals(amountIn.token) && !pair.token1.equals(amountIn.token)) continue
if (!currencyEquals(pair.token0, amountIn.currency) && !currencyEquals(pair.token1, amountIn.currency)) continue
if (pair.reserve0.equalTo(ZERO) || pair.reserve1.equalTo(ZERO)) continue
let amountOut: TokenAmount
let amountOut: CurrencyAmount
try {
;[amountOut] = pair.getOutputAmount(amountIn)
} catch (error) {
......@@ -294,7 +288,7 @@ export class Trade {
throw error
}
// we have arrived at the output token, so this is the final trade of one of the paths
if (amountOut.token.equals(tokenOut)) {
if (currencyEquals(amountOut.currency, tokenOut)) {
sortedInsert(
bestTrades,
new Trade(
......@@ -368,12 +362,11 @@ export class Trade {
invariant(pairs.length > 0, 'PAIRS')
invariant(maxHops > 0, 'MAX_HOPS')
invariant(originalAmountOut === currencyAmountOut || currentPairs.length > 0, 'INVALID_RECURSION')
const chainId: ChainId | undefined =
currencyAmountOut instanceof TokenAmount
? currencyAmountOut.token.chainId
: currencyIn instanceof Token
? currencyIn.chainId
: undefined
const chainId: ChainId | undefined = currencyAmountOut.currency.isToken
? currencyAmountOut.currency.chainId
: currencyIn.isToken
? currencyIn.chainId
: undefined
invariant(chainId !== undefined, 'CHAIN_ID')
const amountOut = wrappedAmount(currencyAmountOut, chainId)
......@@ -381,10 +374,10 @@ export class Trade {
for (let i = 0; i < pairs.length; i++) {
const pair = pairs[i]
// pair irrelevant
if (!pair.token0.equals(amountOut.token) && !pair.token1.equals(amountOut.token)) continue
if (!currencyEquals(pair.token0, amountOut.currency) && !currencyEquals(pair.token1, amountOut.currency)) continue
if (pair.reserve0.equalTo(ZERO) || pair.reserve1.equalTo(ZERO)) continue
let amountIn: TokenAmount
let amountIn: CurrencyAmount
try {
;[amountIn] = pair.getInputAmount(amountOut)
} catch (error) {
......@@ -395,7 +388,7 @@ export class Trade {
throw error
}
// we have arrived at the input token, so this is the first trade of one of the paths
if (amountIn.token.equals(tokenIn)) {
if (currencyEquals(amountIn.currency, tokenIn)) {
sortedInsert(
bestTrades,
new Trade(
......
......@@ -2,7 +2,7 @@ import JSBI from 'jsbi'
import { Pair, Route, Trade } from './entities'
import { Router } from './router'
import invariant from 'tiny-invariant'
import { ChainId, CurrencyAmount, ETHER, Percent, Token, TokenAmount, WETH9 } from '@uniswap/sdk-core'
import { ChainId, CurrencyAmount, ETHER, Percent, Token, WETH9 } from '@uniswap/sdk-core'
function checkDeadline(deadline: string[] | string): void {
expect(typeof deadline).toBe('string')
......@@ -15,9 +15,12 @@ describe('Router', () => {
const token0 = new Token(ChainId.MAINNET, '0x0000000000000000000000000000000000000001', 18, 't0')
const token1 = new Token(ChainId.MAINNET, '0x0000000000000000000000000000000000000002', 18, 't1')
const pair_0_1 = new Pair(new TokenAmount(token0, JSBI.BigInt(1000)), new TokenAmount(token1, JSBI.BigInt(1000)))
const pair_0_1 = new Pair(
new CurrencyAmount(token0, JSBI.BigInt(1000)),
new CurrencyAmount(token1, JSBI.BigInt(1000))
)
const pair_weth_0 = new Pair(new TokenAmount(WETH9[ChainId.MAINNET], '1000'), new TokenAmount(token0, '1000'))
const pair_weth_0 = new Pair(new CurrencyAmount(WETH9[ChainId.MAINNET], '1000'), new CurrencyAmount(token0, '1000'))
describe('#swapCallParameters', () => {
describe('exact in', () => {
......@@ -57,7 +60,10 @@ describe('Router', () => {
it('token1 to ether', () => {
const result = Router.swapCallParameters(
Trade.exactIn(new Route([pair_0_1, pair_weth_0], token1, ETHER), new TokenAmount(token1, JSBI.BigInt(100))),
Trade.exactIn(
new Route([pair_0_1, pair_weth_0], token1, ETHER),
new CurrencyAmount(token1, JSBI.BigInt(100))
),
{ ttl: 50, recipient: '0x0000000000000000000000000000000000000004', allowedSlippage: new Percent('1', '100') }
)
expect(result.methodName).toEqual('swapExactTokensForETH')
......@@ -72,7 +78,7 @@ describe('Router', () => {
})
it('token0 to token1', () => {
const result = Router.swapCallParameters(
Trade.exactIn(new Route([pair_0_1], token0, token1), new TokenAmount(token0, JSBI.BigInt(100))),
Trade.exactIn(new Route([pair_0_1], token0, token1), new CurrencyAmount(token0, JSBI.BigInt(100))),
{ ttl: 50, recipient: '0x0000000000000000000000000000000000000004', allowedSlippage: new Percent('1', '100') }
)
expect(result.methodName).toEqual('swapExactTokensForTokens')
......@@ -89,7 +95,10 @@ describe('Router', () => {
describe('exact out', () => {
it('ether to token1', () => {
const result = Router.swapCallParameters(
Trade.exactOut(new Route([pair_weth_0, pair_0_1], ETHER, token1), new TokenAmount(token1, JSBI.BigInt(100))),
Trade.exactOut(
new Route([pair_weth_0, pair_0_1], ETHER, token1),
new CurrencyAmount(token1, JSBI.BigInt(100))
),
{ ttl: 50, recipient: '0x0000000000000000000000000000000000000004', allowedSlippage: new Percent('1', '100') }
)
expect(result.methodName).toEqual('swapETHForExactTokens')
......@@ -118,7 +127,7 @@ describe('Router', () => {
})
it('token0 to token1', () => {
const result = Router.swapCallParameters(
Trade.exactOut(new Route([pair_0_1], token0, token1), new TokenAmount(token1, JSBI.BigInt(100))),
Trade.exactOut(new Route([pair_0_1], token0, token1), new CurrencyAmount(token1, JSBI.BigInt(100))),
{ ttl: 50, recipient: '0x0000000000000000000000000000000000000004', allowedSlippage: new Percent('1', '100') }
)
expect(result.methodName).toEqual('swapTokensForExactTokens')
......@@ -155,7 +164,10 @@ describe('Router', () => {
})
it('token1 to ether', () => {
const result = Router.swapCallParameters(
Trade.exactIn(new Route([pair_0_1, pair_weth_0], token1, ETHER), new TokenAmount(token1, JSBI.BigInt(100))),
Trade.exactIn(
new Route([pair_0_1, pair_weth_0], token1, ETHER),
new CurrencyAmount(token1, JSBI.BigInt(100))
),
{
ttl: 50,
recipient: '0x0000000000000000000000000000000000000004',
......@@ -175,7 +187,7 @@ describe('Router', () => {
})
it('token0 to token1', () => {
const result = Router.swapCallParameters(
Trade.exactIn(new Route([pair_0_1], token0, token1), new TokenAmount(token0, JSBI.BigInt(100))),
Trade.exactIn(new Route([pair_0_1], token0, token1), new CurrencyAmount(token0, JSBI.BigInt(100))),
{
ttl: 50,
recipient: '0x0000000000000000000000000000000000000004',
......@@ -200,7 +212,7 @@ describe('Router', () => {
Router.swapCallParameters(
Trade.exactOut(
new Route([pair_weth_0, pair_0_1], ETHER, token1),
new TokenAmount(token1, JSBI.BigInt(100))
new CurrencyAmount(token1, JSBI.BigInt(100))
),
{
ttl: 50,
......@@ -227,7 +239,7 @@ describe('Router', () => {
it('token0 to token1', () => {
expect(() =>
Router.swapCallParameters(
Trade.exactOut(new Route([pair_0_1], token0, token1), new TokenAmount(token1, JSBI.BigInt(100))),
Trade.exactOut(new Route([pair_0_1], token0, token1), new CurrencyAmount(token1, JSBI.BigInt(100))),
{
ttl: 50,
recipient: '0x0000000000000000000000000000000000000004',
......
......@@ -1706,10 +1706,10 @@
semver "^7.3.2"
tsutils "^3.17.1"
"@uniswap/sdk-core@^1.0.11":
version "1.0.11"
resolved "https://registry.yarnpkg.com/@uniswap/sdk-core/-/sdk-core-1.0.11.tgz#f135a06696dc7cef0886e4f2edb1ce484a2cc4b7"
integrity sha512-fFfFBaum4AKYyaGbDc9b8hyW/2NEK1tH+bqewyJaY6QTAc4Q2snwcYFvreD+cgo1kGXj4L4XPrP6MdZr4uuBUQ==
"@uniswap/sdk-core@^2.0.2":
version "2.0.2"
resolved "https://registry.yarnpkg.com/@uniswap/sdk-core/-/sdk-core-2.0.2.tgz#748d1d189503d20d3027ef69927ad13cbf2d224a"
integrity sha512-Cx6epJgXE/b9ZP8GAes3LiYFXuxfd7UDZtn8Wvxr6xEMh8T21HHbsoEs9sB8iCBYfYuw2PT+Pza4GJqQNvnddg==
dependencies:
"@ethersproject/address" "^5.0.2"
big.js "^5.2.2"
......
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