Skip to content

Commit

Permalink
Merge branch 'dev' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
yasha-black authored Jan 7, 2022
2 parents d0587ec + fe59f22 commit 7cc1b62
Show file tree
Hide file tree
Showing 48 changed files with 1,017 additions and 876 deletions.
2 changes: 1 addition & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
"simple-import-sort/exports": "error",
"prettier/prettier": "error",
"react-hooks/rules-of-hooks": "error",
"react-hooks/exhaustive-deps": "warn",
"react-hooks/exhaustive-deps": "off",
"no-console": ["warn", { "allow": ["warn", "error"] }],
"@typescript-eslint/explicit-function-return-type": "off",
"@typescript-eslint/indent": "off",
Expand Down
3 changes: 3 additions & 0 deletions src/@types/asset.d.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { AssetInfo } from '@ergolabs/ergo-sdk/build/main/entities/assetInfo';

type Asset = {
name?: string;
amount?: number;
earnedFees?: number;
asset?: AssetInfo;
};

type AssetPair = {
Expand Down
6 changes: 5 additions & 1 deletion src/assets/styles/styles.less
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@ body {
background-color: var(--ergo-body-bg) !important;
}

*, *::before, *::after {
* {
box-sizing: border-box !important;
}

*::before, *::after {
box-sizing: border-box !important;
transition: none !important;
}
Expand Down
106 changes: 106 additions & 0 deletions src/common/models/AmmPool.ts
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);
}
}
151 changes: 151 additions & 0 deletions src/common/models/Currency.ts
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);
}
}
23 changes: 23 additions & 0 deletions src/common/utils/amount.ts
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),
);
};
Loading

0 comments on commit 7cc1b62

Please sign in to comment.