Skip to content

Commit

Permalink
add usd price from Dusa
Browse files Browse the repository at this point in the history
  • Loading branch information
peterjah committed Jun 19, 2024
1 parent 3cc9360 commit dd55700
Show file tree
Hide file tree
Showing 5 changed files with 148 additions and 2 deletions.
38 changes: 38 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"postcy:component-ci": "mv -n cypress-visual-report/cypress-visual-report.html cypress-visual-report/cypress-visual-report-component.html"
},
"dependencies": {
"@dusalabs/sdk": "^0.5.28",
"@massalabs/massa-web3": "^4.0.2-dev",
"@massalabs/react-ui-kit": "^0.0.5-dev",
"@massalabs/wallet-provider": "^2.0.1-dev",
Expand Down
13 changes: 12 additions & 1 deletion src/components/inputAmount/inputAmount.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ import { Money, formatAmount } from '@massalabs/react-ui-kit';
import Big from 'big.js';
import { parseUnits } from 'viem';
import useEvmToken from '../../custom/bridge/useEvmToken';
import { useMassaNetworkValidation } from '../../custom/bridge/useNetworkValidation';
import { useServiceFee } from '../../custom/bridge/useServiceFee';
import { useUsdValue } from '../../custom/usdPrice/useFetchPrice';
import { TokenBalance, TokenOptions } from '../../pages';
import { useGlobalStatusesStore } from '../../store/globalStatusesStore';
import { useOperationStore } from '../../store/operationStore';
Expand All @@ -25,10 +27,17 @@ export const InputAmount = (props: InputAmountProps) => {
const { tokenBalance: _tokenBalanceEVM, isFetched: isBalanceFetched } =
useEvmToken();
const { setAmountError, amountError } = useGlobalStatusesStore();
// Price are fetched onchain from Dusa. If massa network is not valid, we don't show the price
const isValidMassaNetwork = useMassaNetworkValidation();

const massaToEvm = isMassaToEvm();
const decimals = selectedToken?.decimals;

const { usdValue } = useUsdValue(
isInput ? inputAmount : outputAmount,
selectedToken,
);

function changeAmount(amount: string) {
if (!isInput || !selectedToken) {
return;
Expand Down Expand Up @@ -95,7 +104,9 @@ export const InputAmount = (props: InputAmountProps) => {
error={isInput ? amountError : ''}
/>
</div>
{!!inputAmount && <div className="pl-4 mb-1">USD value</div>}
{isValidMassaNetwork && !!inputAmount && !!usdValue && (
<div className="pl-4 mb-1">USD {usdValue}</div>
)}
</div>
<div className="flex flex-col items-center gap-2 mt-2">
<div className="w-full">
Expand Down
96 changes: 96 additions & 0 deletions src/custom/usdPrice/useFetchPrice.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import { useCallback, useEffect, useState } from 'react';
import {
ChainId,
IQuoter,
LB_QUOTER_ADDRESS,
PairV2,
RouteV2,
USDC as _USDC,
WMAS as _WMAS,
WETH as _WETH,
TradeV2,
TokenAmount,
} from '@dusalabs/sdk';
import { formatAmount } from '@massalabs/react-ui-kit';
import { useDebounceValue } from 'usehooks-ts';
import { useBridgeModeStore } from '../../store/modeStore';
import { useAccountStore } from '../../store/store';
import { IToken } from '../../store/tokenStore';

export const useUsdValue = (amount?: bigint, token?: IToken) => {
const { isMainnet } = useBridgeModeStore();
const [usdValue, setUsdValue] = useState<string>();
const [debouncedAmount] = useDebounceValue(amount, 300);
const { massaClient } = useAccountStore();

const getUsdValue = useCallback(async () => {
if (!token || !debouncedAmount || !massaClient) {
return;
}

const symbol = token.symbolEVM.toUpperCase();
let outputAmount: string;
if (symbol.includes('USD') || symbol.includes('DAI')) {
outputAmount = formatAmount(debouncedAmount, token.decimals).preview;
} else {
const chainId = isMainnet() ? ChainId.MAINNET : ChainId.BUILDNET;
const USDC = _USDC[chainId];
const ETH = _WETH[chainId];
const WMAS = _WMAS[chainId];

// little hack because Dusa buildnet doesn't use same token addresses as Bridge
const inputToken = symbol.includes('ETH') ? ETH : WMAS;
const outputToken = USDC;

const allTokenPairs = PairV2.createAllTokenPairs(
inputToken,
outputToken,
[ETH, USDC, WMAS],
);

const allPairs = PairV2.initPairs(allTokenPairs);

// generates all possible routes to consider
const allRoutes = RouteV2.createAllRoutes(
allPairs,
inputToken,
outputToken,
3, // maxHops
);

// generates all possible TradeV2 instances
const trades = await TradeV2.getTradesExactIn(
allRoutes,
new TokenAmount(inputToken, debouncedAmount),
outputToken,
false,
false,
massaClient,
chainId,
);

// chooses the best trade
const bestTrade = TradeV2.chooseBestTrade(trades, true);

const quoter = new IQuoter(LB_QUOTER_ADDRESS[chainId], massaClient);

const prices = await quoter.findBestPathFromAmountIn(
bestTrade.route.pathToStrArr(),
debouncedAmount.toString(),
);
// get the output amount without slippage
outputAmount = formatAmount(
prices.virtualAmountsWithoutSlippage[2],
outputToken.decimals,
).preview;
}

setUsdValue(outputAmount);
}, [debouncedAmount, token, massaClient, isMainnet]);

useEffect(() => {
getUsdValue();
}, [getUsdValue]);

return { usdValue };
};
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export function MassaHeader() {
</div>
<div className="flex items-center gap-3">
<p className="mas-body">
{isConnected && currentProvider
{isConnected
? Intl.t(`connect-wallet.${currentProvider.name()}`)
: Intl.t('connect-wallet.card-destination.to')}
</p>
Expand Down

0 comments on commit dd55700

Please sign in to comment.