Skip to content

Commit

Permalink
[wallet]: add balance in USD for recognized coins (#15399)
Browse files Browse the repository at this point in the history
## Description 

- Add balance in USD for recognized coins
- https://mysten.atlassian.net/browse/APPS-2026
- Slack thread
https://mysten-labs.slack.com/archives/C042YF60NH2/p1702521120146499

<img width="386" alt="Screenshot 2023-12-15 at 10 39 30 PM"
src="https://github.com/MystenLabs/sui/assets/127577476/648e1bc7-52c7-4905-986a-0167c29cc7a6">

## Test Plan 

How did you test the new or updated feature?

---
If your changes are not user-facing and not a breaking change, you can
skip the following section. Otherwise, please indicate what changed, and
then add to the Release Notes section as highlighted during the release
process.

### Type of Change (Check all that apply)

- [ ] protocol change
- [ ] user-visible impact
- [ ] breaking change for a client SDKs
- [ ] breaking change for FNs (FN binary must upgrade)
- [ ] breaking change for validators or node operators (must upgrade
binaries)
- [ ] breaking change for on-chain data layout
- [ ] necessitate either a data wipe or data migration

### Release notes

---------

Co-authored-by: Jordan Gensler <jordan@mystenlabs.com>
  • Loading branch information
plam-ml and Jordan-Mysten authored Dec 18, 2023
1 parent e21ed08 commit cfcd572
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 2 deletions.
32 changes: 32 additions & 0 deletions apps/core/src/hooks/useTokenPrice.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Copyright (c) Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

import { useQuery } from '@tanstack/react-query';
import BigNumber from 'bignumber.js';

import { useAppsBackend } from './useAppsBackend';
import { useCoinMetadata } from './useFormatCoin';

type TokenPriceResponse = { price: string | null };

export function useTokenPrice(coinType: string) {
const { request } = useAppsBackend();
return useQuery({
queryKey: ['apps-backend', 'token-price', coinType],
queryFn: () => request<TokenPriceResponse>(`cetus/${coinType}`),

// These values are set to one minute to prevent displaying stale data, as token prices can change frequently.
staleTime: 60 * 1000,
gcTime: 60 * 1000,
});
}

export function useBalanceInUSD(coinType: string, balance: bigint | string | number) {
const { data: coinMetadata } = useCoinMetadata(coinType);
const { data: tokenPrice } = useTokenPrice(coinType);
if (!tokenPrice || !coinMetadata || !tokenPrice.price) return null;
return new BigNumber(balance.toString())
.shiftedBy(-1 * coinMetadata.decimals)
.multipliedBy(tokenPrice.price)
.toNumber();
}
1 change: 1 addition & 0 deletions apps/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,4 @@ export * from './hooks/useElementDimensions';
export * from './hooks/useSuiCoinData';
export * from './hooks/useLocalStorage';
export * from './hooks/useGetDelegatedStake';
export * from './hooks/useTokenPrice';
21 changes: 19 additions & 2 deletions apps/wallet/src/ui/app/pages/home/tokens/TokensDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,13 @@ import { usePinnedCoinTypes } from '_src/ui/app/hooks/usePinnedCoinTypes';
import FaucetRequestButton from '_src/ui/app/shared/faucet/FaucetRequestButton';
import PageTitle from '_src/ui/app/shared/PageTitle';
import { useFeature } from '@growthbook/growthbook-react';
import { useAppsBackend, useCoinMetadata, useFormatCoin, useResolveSuiNSName } from '@mysten/core';
import {
useAppsBackend,
useBalanceInUSD,
useCoinMetadata,
useFormatCoin,
useResolveSuiNSName,
} from '@mysten/core';
import { useSuiClientQuery } from '@mysten/dapp-kit';
import { Info12, Pin16, Unpin16 } from '@mysten/icons';
import { type CoinBalance as CoinBalanceType } from '@mysten/sui.js/client';
Expand Down Expand Up @@ -104,6 +110,8 @@ export function TokenRow({
});
const allowedSwapCoinsList = useAllowedSwapCoinsList();

const balanceInUsd = useBalanceInUSD(coinBalance.coinType, coinBalance.totalBalance);

const isRenderSwapButton = allowedSwapCoinsList.includes(coinType);

return (
Expand Down Expand Up @@ -172,12 +180,21 @@ export function TokenRow({
</div>
</div>

<div className="ml-auto flex flex-col items-end gap-1.5">
<div className="ml-auto flex flex-col items-end gap-1">
{balance > 0n && (
<Text variant="body" color="gray-90" weight="medium">
{formatted} {symbol}
</Text>
)}

{balanceInUsd && balanceInUsd > 0 && (
<Text variant="subtitle" color="steel-dark" weight="medium">
{Number(balanceInUsd).toLocaleString('en', {
style: 'currency',
currency: 'USD',
})}
</Text>
)}
</div>
</Tag>
);
Expand Down

4 comments on commit cfcd572

@vercel
Copy link

@vercel vercel bot commented on cfcd572 Dec 18, 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 cfcd572 Dec 18, 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 cfcd572 Dec 18, 2023

Choose a reason for hiding this comment

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

Successfully deployed to the following URLs:

mysten-ui – ./apps/ui

mysten-ui-mysten-labs.vercel.app
mysten-ui.vercel.app
mysten-ui-git-main-mysten-labs.vercel.app

@vercel
Copy link

@vercel vercel bot commented on cfcd572 Dec 18, 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.