This repository has been archived by the owner on Apr 25, 2024. It is now read-only.
/
price.ts
88 lines (77 loc) · 3.35 KB
/
price.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
import JSBI from 'jsbi'
import invariant from 'tiny-invariant'
import { BigintIsh, Rounding } from '../../constants'
import { Currency } from '../currency'
import { Fraction } from './fraction'
import { CurrencyAmount } from './currencyAmount'
export class Price<TBase extends Currency, TQuote extends Currency> extends Fraction {
public readonly baseCurrency: TBase // input i.e. denominator
public readonly quoteCurrency: TQuote // output i.e. numerator
public readonly scalar: Fraction // used to adjust the raw fraction w/r/t the decimals of the {base,quote}Token
/**
* Construct a price, either with the base and quote currency amount, or the
* @param args
*/
public constructor(
...args:
| [TBase, TQuote, BigintIsh, BigintIsh]
| [{ baseAmount: CurrencyAmount<TBase>; quoteAmount: CurrencyAmount<TQuote> }]
) {
let baseCurrency: TBase, quoteCurrency: TQuote, denominator: BigintIsh, numerator: BigintIsh
if (args.length === 4) {
;[baseCurrency, quoteCurrency, denominator, numerator] = args
} else {
const result = args[0].quoteAmount.divide(args[0].baseAmount)
;[baseCurrency, quoteCurrency, denominator, numerator] = [
args[0].baseAmount.currency,
args[0].quoteAmount.currency,
result.denominator,
result.numerator
]
}
super(numerator, denominator)
this.baseCurrency = baseCurrency
this.quoteCurrency = quoteCurrency
this.scalar = new Fraction(
JSBI.exponentiate(JSBI.BigInt(10), JSBI.BigInt(baseCurrency.decimals)),
JSBI.exponentiate(JSBI.BigInt(10), JSBI.BigInt(quoteCurrency.decimals))
)
}
/**
* Flip the price, switching the base and quote currency
*/
public invert(): Price<TQuote, TBase> {
return new Price(this.quoteCurrency, this.baseCurrency, this.numerator, this.denominator)
}
/**
* Multiply the price by another price, returning a new price. The other price must have the same base currency as this price's quote currency
* @param other the other price
*/
public multiply<TOtherQuote extends Currency>(other: Price<TQuote, TOtherQuote>): Price<TBase, TOtherQuote> {
invariant(this.quoteCurrency.equals(other.baseCurrency), 'TOKEN')
const fraction = super.multiply(other)
return new Price(this.baseCurrency, other.quoteCurrency, fraction.denominator, fraction.numerator)
}
/**
* Return the amount of quote currency corresponding to a given amount of the base currency
* @param currencyAmount the amount of base currency to quote against the price
*/
public quote(currencyAmount: CurrencyAmount<TBase>): CurrencyAmount<TQuote> {
invariant(currencyAmount.currency.equals(this.baseCurrency), 'TOKEN')
const result = super.multiply(currencyAmount)
return CurrencyAmount.fromFractionalAmount(this.quoteCurrency, result.numerator, result.denominator)
}
/**
* Get the value scaled by decimals for formatting
* @private
*/
private get adjustedForDecimals(): Fraction {
return super.multiply(this.scalar)
}
public toSignificant(significantDigits: number = 6, format?: object, rounding?: Rounding): string {
return this.adjustedForDecimals.toSignificant(significantDigits, format, rounding)
}
public toFixed(decimalPlaces: number = 4, format?: object, rounding?: Rounding): string {
return this.adjustedForDecimals.toFixed(decimalPlaces, format, rounding)
}
}