forked from Uniswap/v2-sdk
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add a currency entity for ether (Uniswap#26)
* add a currency entity * revert test change, remove unnecessary `as any` * remove unnecessary truthy assertions * support currency amounts for input/output of trades * support currency amounts for input/output of trades * allow routes to encode if they end in ETH/WETH * get the trade/route to support ether input/output * router test * add some todos * working best trade exact in * working best trade exact out * remove only * tests for exact in router methods * complete the router tests * add value as an output swap parameter
- Loading branch information
1 parent
d8cc586
commit 14aeb6e
Showing
18 changed files
with
890 additions
and
140 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import JSBI from 'jsbi' | ||
|
||
import { SolidityType } from '../constants' | ||
import { validateSolidityTypeInstance } from '../utils' | ||
|
||
/** | ||
* A currency is any fungible financial instrument on Ethereum, including Ether and all ERC20 tokens. | ||
* | ||
* The only instance of the base class `Currency` is Ether. | ||
*/ | ||
export class Currency { | ||
public readonly decimals: number | ||
public readonly symbol?: string | ||
public readonly name?: string | ||
|
||
public static readonly ETHER: Currency = new Currency(18, 'ETH', 'Ether') | ||
|
||
protected constructor(decimals: number, symbol?: string, name?: string) { | ||
validateSolidityTypeInstance(JSBI.BigInt(decimals), SolidityType.uint8) | ||
|
||
this.decimals = decimals | ||
this.symbol = symbol | ||
this.name = name | ||
} | ||
} | ||
|
||
const ETHER = Currency.ETHER | ||
export { ETHER } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
import { currencyEquals } from '../token' | ||
import { Currency, ETHER } from '../currency' | ||
import invariant from 'tiny-invariant' | ||
import JSBI from 'jsbi' | ||
import _Big from 'big.js' | ||
import toFormat from 'toformat' | ||
|
||
import { BigintIsh, Rounding, TEN, SolidityType } from '../../constants' | ||
import { parseBigintIsh, validateSolidityTypeInstance } from '../../utils' | ||
import { Fraction } from './fraction' | ||
|
||
const Big = toFormat(_Big) | ||
|
||
export class CurrencyAmount extends Fraction { | ||
public readonly currency: Currency | ||
|
||
/** | ||
* Helper that calls the constructor with the ETHER currency | ||
* @param amount ether amount in wei | ||
*/ | ||
public static ether(amount: BigintIsh): CurrencyAmount { | ||
return new CurrencyAmount(ETHER, amount) | ||
} | ||
|
||
// amount _must_ be raw, i.e. in the native representation | ||
protected constructor(currency: Currency, amount: BigintIsh) { | ||
const parsedAmount = parseBigintIsh(amount) | ||
validateSolidityTypeInstance(parsedAmount, SolidityType.uint256) | ||
|
||
super(parsedAmount, JSBI.exponentiate(TEN, JSBI.BigInt(currency.decimals))) | ||
this.currency = currency | ||
} | ||
|
||
get raw(): JSBI { | ||
return this.numerator | ||
} | ||
|
||
add(other: CurrencyAmount): CurrencyAmount { | ||
invariant(currencyEquals(this.currency, other.currency), 'TOKEN') | ||
return new CurrencyAmount(this.currency, JSBI.add(this.raw, other.raw)) | ||
} | ||
|
||
subtract(other: CurrencyAmount): CurrencyAmount { | ||
invariant(currencyEquals(this.currency, other.currency), 'TOKEN') | ||
return new CurrencyAmount(this.currency, JSBI.subtract(this.raw, other.raw)) | ||
} | ||
|
||
toSignificant(significantDigits: number = 6, format?: object, rounding: Rounding = Rounding.ROUND_DOWN): string { | ||
return super.toSignificant(significantDigits, format, rounding) | ||
} | ||
|
||
toFixed( | ||
decimalPlaces: number = this.currency.decimals, | ||
format?: object, | ||
rounding: Rounding = Rounding.ROUND_DOWN | ||
): string { | ||
invariant(decimalPlaces <= this.currency.decimals, 'DECIMALS') | ||
return super.toFixed(decimalPlaces, format, rounding) | ||
} | ||
|
||
toExact(format: object = { groupSeparator: '' }): string { | ||
Big.DP = this.currency.decimals | ||
return new Big(this.numerator.toString()).div(this.denominator.toString()).toFormat(format) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
export * from './fraction' | ||
export * from './percent' | ||
export * from './tokenAmount' | ||
export * from './currencyAmount' | ||
export * from './price' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,39 +1,52 @@ | ||
import { ChainId } from '../constants' | ||
import invariant from 'tiny-invariant' | ||
|
||
import { Token } from './token' | ||
import { Currency, ETHER } from './currency' | ||
import { Token, WETH } from './token' | ||
import { Pair } from './pair' | ||
import { Price } from './fractions/price' | ||
|
||
export class Route { | ||
public readonly pairs: Pair[] | ||
public readonly path: Token[] | ||
public readonly input: Currency | ||
public readonly output: Currency | ||
public readonly midPrice: Price | ||
|
||
constructor(pairs: Pair[], input: Token) { | ||
constructor(pairs: Pair[], input: Currency, output?: Currency) { | ||
invariant(pairs.length > 0, 'PAIRS') | ||
invariant( | ||
pairs.map(pair => pair.token0.chainId === pairs[0].token0.chainId).every(x => x), | ||
pairs.every(pair => pair.chainId === pairs[0].chainId), | ||
'CHAIN_IDS' | ||
) | ||
const path = [input] | ||
invariant( | ||
(input instanceof Token && pairs[0].involvesToken(input)) || | ||
(input === ETHER && pairs[0].involvesToken(WETH[pairs[0].chainId])), | ||
'INPUT' | ||
) | ||
invariant( | ||
typeof output === 'undefined' || | ||
(output instanceof Token && pairs[pairs.length - 1].involvesToken(output)) || | ||
(output === ETHER && pairs[pairs.length - 1].involvesToken(WETH[pairs[0].chainId])), | ||
'OUTPUT' | ||
) | ||
|
||
const path: Token[] = [input instanceof Token ? input : WETH[pairs[0].chainId]] | ||
for (const [i, pair] of pairs.entries()) { | ||
const currentInput = path[i] | ||
invariant(currentInput.equals(pair.token0) || currentInput.equals(pair.token1), 'PATH') | ||
const output = currentInput.equals(pair.token0) ? pair.token1 : pair.token0 | ||
path.push(output) | ||
} | ||
invariant(path.length === new Set(path).size, 'PATH') | ||
|
||
this.pairs = pairs | ||
this.path = path | ||
this.midPrice = Price.fromRoute(this) | ||
this.input = input | ||
this.output = output ?? path[path.length - 1] | ||
} | ||
|
||
get input(): Token { | ||
return this.path[0] | ||
} | ||
|
||
get output(): Token { | ||
return this.path[this.path.length - 1] | ||
get chainId(): ChainId { | ||
return this.pairs[0].chainId | ||
} | ||
} |
Oops, something went wrong.