Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/helper/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export type ConverterPairParams = {
isMintBurn: boolean;
};

export const SOL_NATIVE_DENOM = 'So11111111111111111111111111111111111111112';
export const USDC_SOL_DENOM =
'factory/orai1wuvhex9xqs3r539mvc6mtm7n20fcj3qr2m0y9khx6n5vtlngfzes3k0rq9/EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v';

Expand Down
149 changes: 85 additions & 64 deletions src/pages/Balance/TransferConvertToken/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
import { NetworkChainId } from '@oraichain/common';
import { BigDecimal, BTC_CONTRACT, parseTokenInfoRawDenom, toDisplay, TokenItemType } from '@oraichain/oraidex-common';
import {
BigDecimal,
BTC_CONTRACT,
parseTokenInfoRawDenom,
toDisplay,
TokenItemType,
solChainId
} from '@oraichain/oraidex-common';
import loadingGif from 'assets/gif/loading.gif';
import ArrowDownIcon from 'assets/icons/arrow.svg?react';
import ArrowDownIconLight from 'assets/icons/arrow_light.svg?react';
Expand Down Expand Up @@ -28,6 +35,7 @@ import NumberFormat from 'react-number-format';
import {
calcMaxAmount,
FormatNumberFixed,
getRemoteTokenDenom,
useDepositFeesBitcoin,
useDepositFeesBitcoinV2,
useGetWithdrawlFeesBitcoin,
Expand Down Expand Up @@ -120,7 +128,7 @@ const TransferConvertToken: FC<TransferConvertProps> = ({
await onClickTransfer(convertAmount, toNetworkChainId);
return;
}
return await onClickTransfer(convertAmount, toNetworkChainId);
return await onClickTransfer(convertAmount, toNetworkChainId, { solBridgeWallet });
} catch (error) {
console.log({ error });
} finally {
Expand All @@ -133,11 +141,6 @@ const TransferConvertToken: FC<TransferConvertProps> = ({
const to =
toToken ?? flattenTokens.find((t) => t.coinGeckoId === token.coinGeckoId && t.chainId === toNetworkChainId);

const getRemoteTokenDenom = (token: TokenItemType) => {
if (!token) return null;
return token.contractAddress ? token.prefix + token.contractAddress : token.denom;
};

const remoteTokenDenomFrom = getRemoteTokenDenom(token);
const remoteTokenDenomTo = getRemoteTokenDenom(to);

Expand All @@ -152,7 +155,7 @@ const TransferConvertToken: FC<TransferConvertProps> = ({
});

const isMemeBridge = getStatusMemeBridge(token);
const { solFee, isOraichainToSol, isSolToOraichain } = useGetFeeSol({
const { message, maxBalance, solBridgeWallet, solFee, isOraichainToSol, isSolToOraichain } = useGetFeeSol({
originalFromToken: token,
toChainId: toNetworkChainId,
amountToken: convertAmount,
Expand Down Expand Up @@ -223,65 +226,84 @@ const TransferConvertToken: FC<TransferConvertProps> = ({
})();
}, [token, toNetworkChainId]);

return (
<div className={styles.bridgeFee}>
{isSolToOraichain || isOraichainToSol ? (
<>
Bridge fee:{' '}
<span>
{solFee.totalFee} {token.name}
</span>
</>
) : bridgeFeeTon ? (
<>
Bridge fee:{' '}
<span>
{bridgeFeeTon} {token.name}{' '}
</span>
</>
) : (
<>
Bridge fee: <span>{bridgeFee || '0'}% </span>
</>
)}
{tonTokenFee > 0 ? (
<div className={styles.relayerFee}>
- Token fee:{' '}
<span>
{' '}
{tonTokenFee} {token.name}{' '}
</span>
</div>
) : null}
{relayerFeeTokenFee > 0 ? (
<div className={styles.relayerFee}>
- Relayer fee:
<span>
{relayerFeeTokenFee} {token.name}
</span>
</div>
) : null}
if (message) return <div className={styles.bridgeFee}>{message}</div>;

let msgBridgeFee = '0';
let msgTokenFee = null;
let msgRelayerFee = null;
let msgBTCfee = null;
let msgTonMax = null;

if (isSolToOraichain || isOraichainToSol) {
msgBridgeFee = solFee.totalFee + ' ' + token.name;
} else if (bridgeFeeTon) {
msgBridgeFee = bridgeFeeTon + ' ' + token.name;
} else {
msgBridgeFee = bridgeFee + '%';
}

if (tonTokenFee > 0) {
msgTokenFee = (
<div className={styles.relayerFee}>
- Token fee:
<span>
{tonTokenFee} {token.name}{' '}
</span>
</div>
);
}

if (relayerFeeTokenFee > 0) {
msgRelayerFee = (
<div className={styles.relayerFee}>
- Relayer fee:
<span>
{relayerFeeTokenFee} {token.name}
</span>
</div>
);
}

const msgReceiveAmount = (
<>
- Received amount:{' '}
<span>
{FormatNumberFixed({
value: Math.max(Number(isSolToOraichain || isOraichainToSol ? solFee.sendAmount : receivedAmount), 0)
})}{' '}
{token.name}
</span>
{!!toDisplayBTCFee && (
<>
{' '}
- BTC fee: <span>{toDisplayBTCFee} BTC </span>
</>
)}
{toNetworkChainId === TonChainId && (
<p>
Available amount:{' '}
<span>
{balanceMax.toFixed(6)} {token.name}
</span>
</p>
)}
</>
);

if (!!toDisplayBTCFee) {
msgBTCfee = (
<>
{' '}
- BTC fee: <span>{toDisplayBTCFee} BTC </span>
</>
);
}

if (toNetworkChainId === TonChainId) {
msgTonMax = (
<p>
Available amount:{' '}
<span>
{balanceMax.toFixed(6)} {token.name}
</span>
</p>
);
}

return (
<div className={styles.bridgeFee}>
Bridge fee: <span>{msgBridgeFee}</span>
{msgTokenFee}
{msgRelayerFee}
{msgReceiveAmount}
{msgBTCfee}
{msgTonMax}
</div>
);
};
Expand Down Expand Up @@ -481,11 +503,10 @@ const TransferConvertToken: FC<TransferConvertProps> = ({
btcChains.find((chain) => chain.chainId !== token.chainId)
) {
const isValidateFeeTon = bridgeFeeTon ? convertAmount < bridgeFeeTon : false;
// const isSolBridge = token.chainId === solChainId || toNetworkChainId === solChainId;
// const isBridgeBitcoin = token.chainId === ('bitcoin' as any) || toNetworkChainId === ('bitcoin' as any);
const isSolBridgeHasBridgeWallet =
[token.chainId, toNetworkChainId].includes(solChainId) && solBridgeWallet;
const isDisabled =
// isSolBridge ||
// isBridgeBitcoin ||
!isSolBridgeHasBridgeWallet ||
transferLoading ||
!addressTransfer ||
receivedAmount < 0 ||
Expand Down
30 changes: 27 additions & 3 deletions src/pages/Balance/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ import {
oraichain2oraib,
parseTokenInfo,
toAmount,
validateNumber
validateNumber,
solChainId
} from '@oraichain/oraidex-common';
import { feeEstimate, getNetworkGasPrice } from 'helper';

Expand All @@ -27,15 +28,16 @@ import { useQuery } from '@tanstack/react-query';
import { BitcoinUnit } from 'bitcoin-units';
import { opcodes, script } from 'bitcoinjs-lib';
import { MsgTransfer } from 'cosmjs-types/ibc/applications/transfer/v1/tx';
import { bitcoinLcdV2 } from 'helper/constants';
import { chainInfos, network, tokenMap } from 'initCommon';
import { bitcoinChainId, bitcoinLcdV2 } from 'helper/constants';
import { chainInfos, flattenTokens, network, tokenMap } from 'initCommon';
import CosmJs, { collectWallet, connectWithSigner, getCosmWasmClient } from 'libs/cosmjs';
import { NomicClient } from 'libs/nomic/models/nomic-client/nomic-client';
import { generateError } from 'libs/utils';
import { Type, generateConvertCw20Erc20Message, generateConvertMsgs, generateMoveOraib2OraiMessages } from 'rest/api';
import axios from 'rest/request';
import { RemainingOraibTokenItem } from './StuckOraib/useGetOraiBridgeBalances';
import { store } from 'store/configure';
import { TonChainId } from 'context/ton-provider';

export const transferIBC = async (data: {
fromToken: TokenItemType;
Expand Down Expand Up @@ -685,3 +687,25 @@ export const FormatNumberFixed: React.FC<FormatNumberProps> = ({ value, decimalP
const formattedValue = numberValue === 0 ? '0' : numberValue.toFixed(decimalPlaces);
return formattedValue;
};

export const getRemoteTokenDenom = (token: TokenItemType) => {
if (!token) return null;
return token.contractAddress ? token.prefix + token.contractAddress : token.denom;
};

export const checkTransfer = (fromToken: TokenItemType, toToken: TokenItemType, endToChainId) => {
const isSoltoOraichain = fromToken.chainId === solChainId && endToChainId === 'Oraichain';
const isOraichainToSol = fromToken.chainId === 'Oraichain' && endToChainId === solChainId;
const isBTCtoOraichain = fromToken.chainId === bitcoinChainId && toToken.chainId === 'Oraichain';
const isOraichainToBTC = fromToken.chainId === 'Oraichain' && toToken.chainId === bitcoinChainId;
return [isSoltoOraichain, isOraichainToSol, isBTCtoOraichain, isBTCtoOraichain || isOraichainToBTC];
};

export const checkTransferTon = async (fromToken: TokenItemType, toNetworkChainId: string) => {
const isFromTonToCosmos = fromToken.chainId === TonChainId && toNetworkChainId !== TonChainId;
const isFromCosmosToTON = fromToken.cosmosBased && toNetworkChainId === TonChainId;
const findToNetwork = flattenTokens.find((flat) => flat.chainId === toNetworkChainId);
const isFromCosmosToCosmos =
fromToken.cosmosBased && findToNetwork.cosmosBased && fromToken.coinGeckoId === 'the-open-network';
return { isFromTonToCosmos, isFromCosmosToTON, isFromCosmosToCosmos };
};
81 changes: 40 additions & 41 deletions src/pages/Balance/hooks/useGetFeeSol.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { BigDecimal, solChainId, toAmount, toDisplay, TokenItemType } from '@oraichain/oraidex-common';
import axios from 'axios';
import { SOL_NATIVE_DENOM, USDC_SOL_DENOM } from 'helper/constants';
import { useDebounce } from 'hooks/useDebounce';
import { flattenTokens, solTokens } from 'initCommon';
import { useEffect, useState } from 'react';
Expand All @@ -9,22 +10,11 @@ export enum Direction {
ORAI_TO_SOLANA = 'orai_to_solana'
}

export enum SUPPORT_TOKEN {
ORAI = 'orai',
MAX = 'max',
RACKS = 'rack',
GNRT = 'gnrt',
LEE = 'lee',
MOOBS = 'moobs',
CRISIS = 'crisis'
}

const useGetFeeSol = ({
originalFromToken,
toChainId,
amountToken,
toToken,
isMemeBridge
toChainId
}: {
amountToken: string;
originalFromToken: TokenItemType;
Expand All @@ -44,11 +34,9 @@ const useGetFeeSol = ({
};

const [solFee, setSolFee] = useState(defaultSolFee);

const getSupportToken = (denom) => {
if (denom === 'RACKS') return SUPPORT_TOKEN.RACKS;
return denom?.toLowerCase();
};
const [solWallet, setSolWallet] = useState('');
const [maxBalance, setMaxBalance] = useState('');
const [message, setMessage] = useState('');

useEffect(() => {
(async () => {
Expand All @@ -62,43 +50,54 @@ const useGetFeeSol = ({

const amount: string = toAmount(debouncedAmountToken, originalFromToken.decimals).toString();
const direction: Direction = toChainId === solChainId ? Direction.ORAI_TO_SOLANA : Direction.SOLANA_TO_ORAI;
// const supportedToken: SUPPORT_TOKEN =
// originalFromToken.coinGeckoId === 'oraichain-token' ? SUPPORT_TOKEN.ORAI : SUPPORT_TOKEN.MAX;
let supportedToken: SUPPORT_TOKEN | string = getSupportToken(originalFromToken.name);
let baseURL = `https://solana-relayer.orai.io`;
const baseURL = `https://sol-bridge-3-staging.agents.land`;

if (isMemeBridge) {
const splitDenomInOraichain = originalFromToken.denom.split('/');
supportedToken =
originalFromToken?.contractAddress || splitDenomInOraichain[splitDenomInOraichain.length - 1];
baseURL = 'https://sol-meme-bridge.agents.land';
}
let denom = originalFromToken?.contractAddress ?? originalFromToken.denom;
if (originalFromToken.coinGeckoId === 'solana' && toChainId === 'Oraichain') denom = SOL_NATIVE_DENOM;
if (originalFromToken.coinGeckoId === 'usd-coin' && toChainId === solChainId) denom = USDC_SOL_DENOM;

const url: string = `${baseURL}/account/bridge?direction=${direction}&amount=${amount}&denom=${encodeURIComponent(
denom
)}`;

const url: string = `${baseURL}/fee?direction=${direction}&amount=${amount}&supportedToken=${supportedToken}`;
const { data } = await axios.get(url);
const originalToToken =
toToken ??
flattenTokens.find(
let originalToToken = toToken;

if (!originalToToken) {
originalToToken = flattenTokens.find(
(flat) => flat.coinGeckoId === originalFromToken.coinGeckoId && flat.chainId === toChainId
);
const totalFeeSol = new BigDecimal(data?.oraichainFee ?? data?.solanaFee)
.add(data.tokenFeeAmount)
.div(10 ** originalToToken.decimals)
.toNumber();
}

if (data?.tokenFeeAmount) {
const totalFeeSol = new BigDecimal(data?.oraichainFee ?? data?.solanaFee)
.add(data.tokenFeeAmount)
.div(10 ** originalToToken.decimals)
.toNumber();

setSolFee({
sendAmount: toDisplay(data.sendAmount, originalToToken.decimals),
tokenFeeAmount: toDisplay(data.tokenFeeAmount, originalToToken.decimals),
relayerFee: toDisplay(data?.oraichainFee ?? data?.solanaFee, originalToToken.decimals),
totalFee: totalFeeSol
});
setSolFee({
sendAmount: toDisplay(data.sendAmount, originalToToken.decimals),
tokenFeeAmount: toDisplay(data.tokenFeeAmount, originalToToken.decimals),
relayerFee: toDisplay(data?.oraichainFee ?? data?.solanaFee, originalToToken.decimals),
totalFee: totalFeeSol
});
setSolWallet(data.wallet);
}

if (data?.message) {
setMaxBalance(data.maxBalance);
setMessage(data.message);
}
} catch (error) {
console.log({ error });
}
})();
}, [originalFromToken, toChainId, debouncedAmountToken]);

return {
message,
maxBalance,
solBridgeWallet: solWallet,
solFee,
isSolToOraichain,
isOraichainToSol
Expand Down
Loading
Loading