-
Notifications
You must be signed in to change notification settings - Fork 41
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
48 changed files
with
1,017 additions
and
876 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
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 |
---|---|---|
@@ -0,0 +1,106 @@ | ||
import { PoolId } from '@ergolabs/ergo-dex-sdk'; | ||
import { AmmPool as BaseAmmPool } from '@ergolabs/ergo-dex-sdk/build/main/amm/entities/ammPool'; | ||
import { AssetAmount } from '@ergolabs/ergo-sdk'; | ||
import { AssetInfo } from '@ergolabs/ergo-sdk/build/main/entities/assetInfo'; | ||
|
||
import { math } from '../../utils/math'; | ||
import { normalizeAmount } from '../utils/amount'; | ||
import { Currency } from './Currency'; | ||
|
||
export class AmmPool { | ||
constructor(private pool: BaseAmmPool) {} | ||
|
||
get id(): PoolId { | ||
return this.pool.id; | ||
} | ||
|
||
get poolFeeNum(): number { | ||
return this.pool.poolFeeNum; | ||
} | ||
|
||
get feeNum(): bigint { | ||
return this.pool.feeNum; | ||
} | ||
|
||
get lp(): Currency { | ||
return new Currency(this.pool.lp.amount, this.pool.lp.asset); | ||
} | ||
|
||
get y(): Currency { | ||
return new Currency(this.pool.y.amount, this.pool.y.asset); | ||
} | ||
|
||
get x(): Currency { | ||
return new Currency(this.pool.x.amount, this.pool.x.asset); | ||
} | ||
|
||
getAssetAmount(asset: AssetInfo): Currency { | ||
if (this.pool.x.asset.id === asset.id) { | ||
return this.x; | ||
} | ||
if (this.pool.y.asset.id === asset.id) { | ||
return this.y; | ||
} | ||
throw new Error('unknown asset'); | ||
} | ||
|
||
calculateOutputPrice(inputCurrency: Currency): Currency { | ||
const outputCurrency = this.calculateOutputAmount(inputCurrency); | ||
|
||
if (inputCurrency.amount === 1n) { | ||
return outputCurrency; | ||
} | ||
|
||
const fmtInput = inputCurrency.toString({ suffix: false }); | ||
const fmtOutput = outputCurrency.toString({ suffix: false }); | ||
|
||
const p = math.evaluate!(`${fmtOutput} / ${fmtInput}`).toString(); | ||
|
||
return new Currency( | ||
normalizeAmount(p, outputCurrency.asset), | ||
outputCurrency.asset, | ||
); | ||
} | ||
|
||
calculateInputPrice(outputCurrency: Currency): Currency { | ||
const inputCurrency = this.calculateInputAmount(outputCurrency); | ||
|
||
if (outputCurrency.amount === 1n) { | ||
return inputCurrency; | ||
} | ||
|
||
const fmtInput = inputCurrency.toString({ suffix: false }); | ||
const fmtOutput = outputCurrency.toString({ suffix: false }); | ||
|
||
const p = math.evaluate!(`${fmtInput} / ${fmtOutput}`).toString(); | ||
|
||
return new Currency( | ||
normalizeAmount(p, inputCurrency.asset), | ||
inputCurrency.asset, | ||
); | ||
} | ||
|
||
calculateDepositAmount(currency: Currency): Currency { | ||
const depositAmount = this.pool.depositAmount( | ||
new AssetAmount(currency.asset, currency.amount), | ||
); | ||
|
||
return new Currency(depositAmount?.amount, depositAmount?.asset); | ||
} | ||
|
||
calculateInputAmount(currency: Currency): Currency { | ||
const inputAmount = this.pool.inputAmount( | ||
new AssetAmount(currency.asset, currency.amount), | ||
); | ||
|
||
return new Currency(inputAmount?.amount, inputAmount?.asset); | ||
} | ||
|
||
calculateOutputAmount(currency: Currency): Currency { | ||
const outputAmount = this.pool.outputAmount( | ||
new AssetAmount(currency.asset, currency.amount), | ||
); | ||
|
||
return new Currency(outputAmount.amount, outputAmount?.asset); | ||
} | ||
} |
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,151 @@ | ||
import { AssetInfo } from '@ergolabs/ergo-sdk/build/main/entities/assetInfo'; | ||
|
||
import { parseUserInputToFractions, renderFractions } from '../../utils/math'; | ||
import { getDecimalsCount, normalizeAmount } from '../utils/amount'; | ||
|
||
const createUnknownAsset = (decimals = 0): AssetInfo => ({ | ||
id: '-1', | ||
name: 'unknown', | ||
decimals, | ||
}); | ||
|
||
const isUnknownAsset = (asset: AssetInfo): boolean => asset.name === 'unknown'; | ||
|
||
export class Currency { | ||
private _amount = 0n; | ||
|
||
private _asset: AssetInfo = createUnknownAsset(0); | ||
|
||
constructor(amount?: bigint | string, asset?: AssetInfo) { | ||
if (!!asset) { | ||
this._asset = asset; | ||
} | ||
if (typeof amount === 'bigint') { | ||
this._amount = amount; | ||
} | ||
if (typeof amount === 'string') { | ||
this.checkAmountErrors(amount, this._asset); | ||
this._amount = parseUserInputToFractions(amount, this._asset.decimals); | ||
} | ||
} | ||
|
||
get amount(): bigint { | ||
return this._amount; | ||
} | ||
|
||
get asset(): AssetInfo { | ||
return this._asset; | ||
} | ||
|
||
fromAmount(amount: bigint | string): Currency { | ||
return this.changeAmount(amount); | ||
} | ||
|
||
isUnknownAsset(): boolean { | ||
return isUnknownAsset(this.asset); | ||
} | ||
|
||
isAssetEquals(a: AssetInfo): boolean { | ||
return a.id === this.asset.id; | ||
} | ||
|
||
isPositive(): boolean { | ||
return this.amount > 0n; | ||
} | ||
|
||
changeAmount(amount: bigint | string): Currency { | ||
return new Currency(amount, this.asset); | ||
} | ||
|
||
changeAsset(asset: AssetInfo): Currency { | ||
return new Currency( | ||
this.normalizeAmount(this.amount, this.asset, asset), | ||
asset, | ||
); | ||
} | ||
|
||
gt(currency: Currency): boolean { | ||
this.checkComparisonErrors(currency); | ||
return this.amount > currency.amount; | ||
} | ||
|
||
lt(currency: Currency): boolean { | ||
this.checkComparisonErrors(currency); | ||
return this.amount < currency.amount; | ||
} | ||
|
||
gte(currency: Currency): boolean { | ||
this.checkComparisonErrors(currency); | ||
return this.amount >= currency.amount; | ||
} | ||
|
||
lte(currency: Currency): boolean { | ||
this.checkComparisonErrors(currency); | ||
return this.amount <= currency.amount; | ||
} | ||
|
||
plus(currency: Currency): Currency { | ||
if (isUnknownAsset(this.asset)) { | ||
throw new Error("can't sum unknown asset"); | ||
} | ||
if (this.asset.id !== currency.asset.id) { | ||
throw new Error("can't sum currencies with different assets"); | ||
} | ||
|
||
return new Currency(this.amount + currency.amount, this.asset); | ||
} | ||
|
||
minus(currency: Currency): Currency { | ||
if (isUnknownAsset(this.asset)) { | ||
throw new Error("can't subtract unknown asset"); | ||
} | ||
if (this.asset.id !== currency.asset.id) { | ||
throw new Error("can't subtract currencies with different assets"); | ||
} | ||
|
||
return new Currency(this.amount - currency.amount, this.asset); | ||
} | ||
|
||
toString(config?: { suffix: boolean }): string { | ||
if ((!config || !!config?.suffix) && !isUnknownAsset(this.asset)) { | ||
return `${renderFractions(this.amount, this.asset.decimals)} ${ | ||
this.asset.name | ||
}`; | ||
} | ||
|
||
return `${renderFractions(this.amount, this.asset.decimals)}`; | ||
} | ||
|
||
toUsd(): void {} | ||
|
||
private checkComparisonErrors(currency: Currency): void { | ||
if (isUnknownAsset(this.asset)) { | ||
throw new Error("can't compare unknown asset"); | ||
} | ||
if (this.asset.id !== currency.asset.id) { | ||
throw new Error("can't compare currencies with different assets"); | ||
} | ||
} | ||
|
||
private checkAmountErrors(amount: string, asset: AssetInfo): void { | ||
const decimalsCount = getDecimalsCount(amount); | ||
|
||
if (isUnknownAsset(asset)) { | ||
this._asset = createUnknownAsset(decimalsCount); | ||
return; | ||
} | ||
if (decimalsCount > (asset?.decimals || 0)) { | ||
throw new Error('amount has to many fractions'); | ||
} | ||
} | ||
|
||
private normalizeAmount( | ||
amount: bigint, | ||
currentAsset: AssetInfo, | ||
newAsset: AssetInfo, | ||
): string { | ||
const amountString = renderFractions(amount, currentAsset.decimals); | ||
|
||
return normalizeAmount(amountString, newAsset); | ||
} | ||
} |
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,23 @@ | ||
import { AssetInfo } from '@ergolabs/ergo-sdk/build/main/entities/assetInfo'; | ||
|
||
export const getDecimalsCount = (amount: string): number => { | ||
const decimals = amount.split('.')[1]; | ||
|
||
if (decimals) { | ||
return decimals.length; | ||
} | ||
return 0; | ||
}; | ||
|
||
export const normalizeAmount = (amount: string, asset: AssetInfo): string => { | ||
const currentDecimalsCount = getDecimalsCount(amount); | ||
|
||
if (currentDecimalsCount <= (asset.decimals || 0)) { | ||
return amount; | ||
} | ||
|
||
return amount.slice( | ||
0, | ||
amount.length - currentDecimalsCount + (asset.decimals || 0), | ||
); | ||
}; |
Oops, something went wrong.