Skip to content

Commit

Permalink
Merge pull request #682 from alleslabs/feat/lp-display
Browse files Browse the repository at this point in the history
Feat/lp display
  • Loading branch information
songwongtp authored Dec 20, 2023
2 parents 70c5427 + 5fea93f commit 8f027c0
Show file tree
Hide file tree
Showing 10 changed files with 112 additions and 83 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Improvements

- [#682](https://github.com/alleslabs/celatone-frontend/pull/682) Render token amount < 0.000001 properly
- [#669](https://github.com/alleslabs/celatone-frontend/pull/669) api v1 - contract transaction
- [#672](https://github.com/alleslabs/celatone-frontend/pull/672) refactor balances
- [#662](https://github.com/alleslabs/celatone-frontend/pull/662) Add republish button in module detail
Expand Down
2 changes: 1 addition & 1 deletion src/config/chain/initia.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ export const INITIA_CHAIN_CONFIGS: ChainConfigs = {
prettyName: "Initia Testnet 12-1",
lcd: "https://next-stone-rest.initia.tech",
rpc: "https://next-stone-rpc.initia.tech:443",
indexer: "https://stone-12-1-graphql.alleslabs.dev/v1/graphql",
indexer: "https://stone-12-1-nft-graphql.alleslabs.dev/v1/graphql",
wallets: [...keplrWallets],
features: {
faucet: {
Expand Down
10 changes: 8 additions & 2 deletions src/lib/components/token/TokenComposition.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@ export const TokenComposition = ({
<Flex wrap="wrap">
<Text variant="body2">
<Text as="span" mr={1} fontWeight={700}>
{token.poolInfo.coinA.amount}
{formatUTokenWithPrecision(
token.poolInfo.coinA.amount,
token.poolInfo.coinA.precision ?? 0
)}
</Text>
{getTokenLabel(
token.poolInfo.coinA.denom,
Expand All @@ -32,7 +35,10 @@ export const TokenComposition = ({
</Text>
<Text variant="body2">
<Text as="span" mr={1} fontWeight={700}>
{token.poolInfo.coinB.amount}
{formatUTokenWithPrecision(
token.poolInfo.coinB.amount,
token.poolInfo.coinB.precision ?? 0
)}
</Text>
{getTokenLabel(
token.poolInfo.coinB.denom,
Expand Down
70 changes: 37 additions & 33 deletions src/lib/services/move/poolService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,30 +8,35 @@ import {
useBaseApiRoute,
useMoveConfig,
} from "lib/app-provider";
import type { MovePoolInfos, Option, USD } from "lib/types";
import type { MovePoolInfos, Option, Token, U, USD } from "lib/types";
import { calculateAssetValue, toToken } from "lib/utils";

import { getMovePoolInfos } from "./pool";

const computePricePerShare = (
amountAPerShare: Big,
const computePricePerPShare = (
amountAPerShare: Token<Big>,
weightA: string,
priceA: Option<number>,
amountBPerShare: Big,
amountBPerShare: Token<Big>,
weightB: string,
priceB: Option<number>
priceB: Option<number>,
poolPrecision: number
): Option<USD<Big>> => {
const multiplier = big(10).pow(poolPrecision);
if (priceA && priceB)
return big(priceA)
.times(amountAPerShare)
.plus(big(priceB).times(amountBPerShare)) as USD<Big>;
if (priceA)
return big(priceA)
.times(amountAPerShare)
.times(big(weightA).plus(weightB).div(weightA)) as USD<Big>;
if (priceB)
return big(priceB)
.times(amountBPerShare)
.times(big(weightA).plus(weightB).div(weightB)) as USD<Big>;
return calculateAssetValue(amountAPerShare, priceA as USD<number>)
.plus(calculateAssetValue(amountBPerShare, priceB as USD<number>))
.times(multiplier) as USD<Big>;

const totalWeight = big(weightA).plus(weightB);
if (priceA && big(weightA).gt(0))
return calculateAssetValue(amountAPerShare, priceA as USD<number>)
.times(totalWeight.div(weightA))
.times(multiplier) as USD<Big>;
if (priceB && big(weightB).gt(0))
return calculateAssetValue(amountBPerShare, priceB as USD<number>)
.times(totalWeight.div(weightB))
.times(multiplier) as USD<Big>;
return undefined;
};

Expand Down Expand Up @@ -61,48 +66,47 @@ export const useMovePoolInfos = () => {

const data = pools?.reduce<MovePoolInfos>((acc, curr) => {
const coinAInfo = assetInfos?.[curr.coin_a.denom];
const coinAprecision = coinAInfo?.precision ?? 0;
const coinBInfo = assetInfos?.[curr.coin_b.denom];
const coinBprecision = coinBInfo?.precision ?? 0;

const totalShares = big(curr.total_share).div(big(10).pow(curr.precision));
const [amountAPerShare, amountBPerShare] = totalShares.eq(0)
const totalShares = big(curr.total_share);
const [tempA, tempB] = totalShares.eq(0)
? [big(0), big(0)]
: [
big(curr.coin_a.amount)
.div(big(10).pow(coinAprecision))
.div(totalShares),
big(curr.coin_b.amount)
.div(big(10).pow(coinBprecision))
.div(totalShares),
big(curr.coin_a.amount).div(totalShares),
big(curr.coin_b.amount).div(totalShares),
];
const [amountAPerShare, amountBPerShare] = [tempA, tempB] as [
U<Token<Big>>,
U<Token<Big>>,
];

const lpPricePerShare = computePricePerShare(
amountAPerShare,
const lpPricePerPShare = computePricePerPShare(
toToken(amountAPerShare, coinAInfo?.precision ?? 0),
curr.coin_a.weight,
coinAInfo?.price,
amountBPerShare,
toToken(amountBPerShare, coinBInfo?.precision ?? 0),
curr.coin_b.weight,
coinBInfo?.price
coinBInfo?.price,
curr.precision
);

return {
...acc,
[curr.lp_denom]: {
coinA: {
...curr.coin_a,
precision: coinAprecision,
amountAPerShare,
precision: coinAInfo?.precision,
symbol: coinAInfo?.symbol,
},
coinB: {
...curr.coin_b,
precision: coinBprecision,
amountBPerShare,
precision: coinBInfo?.precision,
symbol: coinBInfo?.symbol,
},
precision: curr.precision,
lpPricePerShare,
lpPricePerPShare,
logo: [coinAInfo?.logo, coinBInfo?.logo],
},
};
Expand Down
14 changes: 8 additions & 6 deletions src/lib/types/move/pool.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,27 @@
import type Big from "big.js";

import type { HexAddr } from "../addrs";
import type { Option } from "../common";
import type { USD } from "../currency";
import type { Token, U, USD } from "../currency";

export type MovePoolInfos = Record<
string,
{
coinA: {
metadata: HexAddr;
denom: string;
precision: number;
amountAPerShare: Big;
amountAPerShare: U<Token<Big>>;
precision: Option<number>;
symbol: Option<string>;
};
coinB: {
metadata: HexAddr;
denom: string;
precision: number;
amountBPerShare: Big;
amountBPerShare: U<Token<Big>>;
precision: Option<number>;
symbol: Option<string>;
};
lpPricePerShare: Option<USD<Big>>;
lpPricePerPShare: Option<USD<Big>>;
precision: number;
logo: Option<string>[];
}
Expand Down
8 changes: 6 additions & 2 deletions src/lib/types/pool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ import type {
ContractAddr,
Nullable,
Option,
Token,
TokenWithValue,
U,
} from "lib/types";

export enum PoolType {
Expand Down Expand Up @@ -57,12 +59,14 @@ export interface PoolDetail<

export interface PoolInfo {
coinA: {
amount: string;
amount: U<Token<Big>>;
precision: Option<number>;
denom: string;
symbol: Option<string>;
};
coinB: {
amount: string;
amount: U<Token<Big>>;
precision: Option<number>;
denom: string;
symbol: Option<string>;
};
Expand Down
37 changes: 17 additions & 20 deletions src/lib/utils/assetValue.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import {
coinToTokenWithValue,
filterSupportedTokens,
} from "./assetValue";
import { formatUTokenWithPrecision } from "./formatter";

describe("filterSupportedTokens", () => {
const token1: TokenWithValue = {
Expand Down Expand Up @@ -53,12 +52,14 @@ describe("filterSupportedTokens", () => {
poolInfo: {
coinA: {
denom: "",
amount: "",
amount: big(0) as U<Token<Big>>,
precision: undefined,
symbol: undefined,
},
coinB: {
denom: "",
amount: "",
amount: big(0) as U<Token<Big>>,
precision: undefined,
symbol: undefined,
},
},
Expand Down Expand Up @@ -106,17 +107,17 @@ describe("coinToTokenWithValue", () => {
metadata: zHexAddr.parse("0x1"),
denom: "denom1",
precision: 6,
amountAPerShare: big(1),
amountAPerShare: big(1) as U<Token<Big>>,
symbol: undefined,
},
coinB: {
metadata: zHexAddr.parse("0x2"),
denom: "denom2",
precision: 6,
amountBPerShare: big(1),
amountBPerShare: big(1) as U<Token<Big>>,
symbol: "DENOM_2",
},
lpPricePerShare: big(1) as USD<Big>,
lpPricePerPShare: big(0.000001) as USD<Big>,
precision: 6,
logo: ["denom1_logo", "denom2_logo"],
},
Expand Down Expand Up @@ -144,28 +145,24 @@ describe("coinToTokenWithValue", () => {
amount: big(coin.amount) as U<Token<Big>>,
symbol: `${movePoolInfo.coinA.denom}-${movePoolInfo.coinB.symbol}`,
precision: movePoolInfo.precision,
price: movePoolInfo.lpPricePerShare,
price: movePoolInfo.lpPricePerPShare,
value: big(coin.amount)
.mul(movePoolInfo.lpPricePerShare ?? big(0))
.mul(movePoolInfo.lpPricePerPShare ?? big(0))
.div(10 ** movePoolInfo.precision) as USD<Big>,
poolInfo: {
coinA: {
amount: formatUTokenWithPrecision(
big(coin.amount).times(movePoolInfo.coinA.amountAPerShare) as U<
Token<Big>
>,
movePoolInfo.precision
),
amount: movePoolInfo.coinA.amountAPerShare.times(coin.amount) as U<
Token<Big>
>,
precision: 6,
denom: movePoolInfo.coinA.denom,
symbol: movePoolInfo.coinA.symbol,
},
coinB: {
amount: formatUTokenWithPrecision(
big(coin.amount).times(movePoolInfo.coinB.amountBPerShare) as U<
Token<Big>
>,
movePoolInfo.precision
),
amount: movePoolInfo.coinB.amountBPerShare.times(coin.amount) as U<
Token<Big>
>,
precision: 6,
denom: movePoolInfo.coinB.denom,
symbol: movePoolInfo.coinB.symbol,
},
Expand Down
36 changes: 17 additions & 19 deletions src/lib/utils/assetValue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ import type {
USD,
} from "lib/types";

import { formatUTokenWithPrecision, getTokenLabel, toToken } from "./formatter";
import { getTokenLabel, toToken } from "./formatter";

export const calculateAssetValue = (
amount: Token<BigSource>,
price: USD<number>
price: USD<BigSource>
): USD<Big> => big(amount).mul(price) as USD<Big>;

export const filterSupportedTokens = (tokens: Option<TokenWithValue[]>) =>
Expand Down Expand Up @@ -45,6 +45,7 @@ export const coinToTokenWithValue = (
const tokenAmount = big(amount) as U<Token<Big>>;
const assetInfo = assetInfos?.[denom];
const movePoolInfo = poolInfos?.[denom];

return movePoolInfo
? {
isLPToken: true,
Expand All @@ -59,30 +60,27 @@ export const coinToTokenWithValue = (
)}`,
logo: movePoolInfo.logo,
precision: movePoolInfo.precision,
price: movePoolInfo.lpPricePerShare,
value: movePoolInfo.lpPricePerShare
? (tokenAmount
.times(movePoolInfo.lpPricePerShare)
.div(big(10).pow(movePoolInfo.precision)) as USD<Big>)
price: movePoolInfo.lpPricePerPShare,
value: movePoolInfo.lpPricePerPShare
? calculateAssetValue(
toToken(tokenAmount, movePoolInfo.precision),
movePoolInfo.lpPricePerPShare
)
: undefined,
poolInfo: {
coinA: {
amount: formatUTokenWithPrecision(
tokenAmount.times(movePoolInfo.coinA.amountAPerShare) as U<
Token<Big>
>,
movePoolInfo.precision
),
amount: tokenAmount.times(movePoolInfo.coinA.amountAPerShare) as U<
Token<Big>
>,
precision: movePoolInfo.coinA.precision,
denom: movePoolInfo.coinA.denom,
symbol: movePoolInfo.coinA.symbol,
},
coinB: {
amount: formatUTokenWithPrecision(
tokenAmount.times(movePoolInfo.coinB.amountBPerShare) as U<
Token<Big>
>,
movePoolInfo.precision
),
amount: tokenAmount.times(movePoolInfo.coinB.amountBPerShare) as U<
Token<Big>
>,
precision: movePoolInfo.coinB.precision,
denom: movePoolInfo.coinB.denom,
symbol: movePoolInfo.coinB.symbol,
},
Expand Down
11 changes: 11 additions & 0 deletions src/lib/utils/formatter/token.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,17 @@ describe("formatUTokenWithPrecision", () => {
).toEqual("0.000");
});
});
test("too small", () => {
expect(formatUTokenWithPrecision("0.1" as U<Token>, 6, false)).toEqual(
"<0.000001"
);
expect(formatUTokenWithPrecision("0.1" as U<Token>, 7, false)).toEqual(
"<0.0000001"
);
expect(formatUTokenWithPrecision("0.1" as U<Token>, 6, false, 2)).toEqual(
"<0.01"
);
});
test("no suffix", () => {
expect(
formatUTokenWithPrecision("12345678901234567890" as U<Token>, 6, false)
Expand Down
Loading

2 comments on commit 8f027c0

@vercel
Copy link

@vercel vercel bot commented on 8f027c0 Dec 20, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vercel
Copy link

@vercel vercel bot commented on 8f027c0 Dec 20, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.