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
5 changes: 3 additions & 2 deletions src/helper/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ export const getNetworkGasPrice = async (chainId): Promise<number> => {
if (findToken) {
return findToken.feeCurrencies[0].gasPriceStep.average;
}
} catch {}
} catch { }
return 0;
};

Expand Down Expand Up @@ -400,6 +400,7 @@ export const isConnectSpecificNetwork = (status: string | null) => {
export const getAddressTransferForEvm = async (walletByNetworks: WalletsByNetwork, network: CustomChainInfo) => {
let address = '';
if (network.chainId === EVM_CHAIN_ID_COMMON.TRON_CHAIN_ID) {
if (!isMobile() && isConnectSpecificNetwork(walletByNetworks.tron)) return '';
const accountTron: interfaceRequestTron = await window.tronLinkDapp.request({
method: 'tron_requestAccounts'
});
Expand All @@ -426,7 +427,7 @@ export const getAddressTransfer = async (network: CustomChainInfo, walletByNetwo
JSON.parse(JSON.parse(localStorage.getItem('persist:root'))?.config)?.tonAddress ||
toUserFriendlyAddress(window.Ton?.account?.address);
// address = useTonAddress();
} else if (network.networkType === 'evm' && isConnectSpecificNetwork(walletByNetworks.evm)) {
} else if (network.networkType === 'evm') {
address = await getAddressTransferForEvm(walletByNetworks, network);
} else if (network.networkType == 'svm' && isConnectSpecificNetwork(walletByNetworks.solana)) {
let provider = window?.solana;
Expand Down
8 changes: 8 additions & 0 deletions src/pages/Balance/TransferConvertToken/index.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,14 @@
}
white-space: pre;
.bridgeFee {
display: flex;
flex-direction: row;
gap: 3px;

@include mobile {
gap: 0px;
flex-direction: column;
}
font-weight: 400;
font-size: 14px;
margin-top: 12px;
Expand Down
18 changes: 9 additions & 9 deletions src/pages/Balance/TransferConvertToken/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ const TransferConvertToken: FC<{
if (tonTokenFee > 0) {
msgTokenFee = (
<div className={styles.relayerFee}>
- Token fee:
Token fee:
<span>
{tonTokenFee} {token.name}{' '}
</span>
Expand All @@ -236,7 +236,7 @@ const TransferConvertToken: FC<{
if (relayerFeeTokenFee > 0) {
msgRelayerFee = (
<div className={styles.relayerFee}>
- Relayer fee:
Relayer fee:
<span>
{relayerFeeTokenFee} {token.name}
</span>
Expand All @@ -246,7 +246,7 @@ const TransferConvertToken: FC<{

const msgReceiveAmount = (
<>
- Received amount:{' '}
Received amount:{' '}
<span>
{FormatNumberFixed({
value: Math.max(Number(isSolToOraichain || isOraichainToSol ? solFee.sendAmount : receivedAmount), 0)
Expand Down Expand Up @@ -278,12 +278,12 @@ const TransferConvertToken: FC<{

return (
<div className={styles.bridgeFee}>
Bridge fee: <span>{msgBridgeFee + " " + suffixe}</span>
{msgTokenFee}
{msgRelayerFee}
{msgReceiveAmount}
{msgBTCfee}
{msgTonMax}
<div>Bridge fee: <span>{msgBridgeFee + " " + suffixe}</span></div>
<div>{msgTokenFee}</div>
<div>{msgRelayerFee}</div>
<div>{msgReceiveAmount}</div>
<div>{msgBTCfee}</div>
<div>{msgTonMax}</div>
</div>
);
};
Expand Down
4 changes: 1 addition & 3 deletions src/pages/Pools/NewTokenModal/NewTokenModal.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@

.box {
width: 100%;

// background-color: #17181c;
// border: 1px solid rgba(225, 240, 255, 0.2027);
&.light {
Expand All @@ -90,7 +89,6 @@

@include mobile {
width: 100%;

&:nth-child(1) {
margin-right: 0px;
}
Expand All @@ -99,8 +97,8 @@
margin-left: 0px;
}

margin-bottom: 100px;
margin-top: 10px;
margin-bottom: 10px;
}

padding: 24px 24px 0 24px;
Expand Down
4 changes: 4 additions & 0 deletions src/pages/UniversalSwap/Component/AssetsTab.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,10 @@
.tableWrapper {
overflow-x: auto;

@include mobile() {
overflow-x: hidden;
}

table {
min-width: 400px;
}
Expand Down
20 changes: 16 additions & 4 deletions src/pages/UniversalSwap/Component/AssetsTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
parseTokenInfoRawDenom,
toAmount,
toDisplay,
tokensIcon
TokenItemType,
} from '@oraichain/oraidex-common';
import DefaultIcon from 'assets/icons/tokens.svg?react';
import { isMobile } from '@walletconnect/browser-utils';
Expand All @@ -16,7 +16,7 @@ import ToggleSwitch from 'components/ToggleSwitch';
import { useCoinGeckoPrices } from 'hooks/useCoingecko';
import useConfigReducer from 'hooks/useConfigReducer';
import { flattenTokens, tokenMap } from 'initCommon';
import { getTotalUsd, toSumDisplay } from 'libs/utils';
import { getTotalUsd, getUsd, toSumDisplay } from 'libs/utils';
import { useGetTotalLpV3 } from 'pages/Pool-V3/hooks/useGetTotalLp';
import { formatDisplayUsdt, toFixedIfNecessary } from 'pages/Pools/helpers';
import { useGetMyStake } from 'pages/Pools/hooks';
Expand All @@ -26,6 +26,8 @@ import { updateTotalLpv3 } from 'reducer/token';
import { RootState } from 'store/configure';
import { AssetInfoResponse } from 'types/swap';
import styles from './AssetsTab.module.scss';
import { useGetMyStakeRewardInfo } from 'pages/Staking/hooks';
import { ORAIX_TOKEN_INFO } from 'pages/Staking/constants';

const cx = cn.bind(styles);

Expand All @@ -47,6 +49,16 @@ export const AssetsTab: FC<{ networkFilter: string }> = ({ networkFilter }) => {
const { totalStaked } = useGetMyStake({
stakerAddress: address
});

const { myStakeRewardInfo } = useGetMyStakeRewardInfo(
ORAIX_TOKEN_INFO.contractAddress,
address
);

const ORAIX_TOKEN = ORAIX_TOKEN_INFO as TokenItemType;
const stakedAmount = myStakeRewardInfo?.stakedAmount || '0';
const stakeAmountUsd = getUsd(stakedAmount, ORAIX_TOKEN, prices);

let totalUsd: number = getTotalUsd(amounts, prices);
if (networkFilter) {
const subAmounts = Object.fromEntries(
Expand Down Expand Up @@ -76,8 +88,8 @@ export const AssetsTab: FC<{ networkFilter: string }> = ({ networkFilter }) => {
...listAsset,
{
src: StakeIcon,
label: 'Total LP',
balance: formatDisplayUsdt(toDisplay(BigInt(Math.trunc(totalStaked)), CW20_DECIMALS) + Number(totalLpv3) || 0)
label: 'Total LP & Stake',
balance: formatDisplayUsdt(toDisplay(BigInt(Math.trunc(totalStaked)), CW20_DECIMALS) + Number(totalLpv3) + Number(stakeAmountUsd) || 0)
}
];
}
Expand Down
9 changes: 6 additions & 3 deletions src/pages/UniversalSwap/Component/HeaderTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { ChartTokenType } from '../hooks/useChartUsdPrice';
import styles from './HeaderTab.module.scss';
import { flattenTokens } from 'initCommon';
import { getTokenIsStableCoin } from '../helpers';
import DefaultIcon from 'assets/icons/tokens.svg?react';

const cx = cn.bind(styles);

Expand Down Expand Up @@ -136,10 +137,12 @@ export const HeaderTop = ({
let [ToTokenIcon, FromTokenIcon] = [null, null];

const generateIconTokenByTheme = (token) => {
return theme === 'light' ? (
<img style={{ borderRadius: '100%' }} src={token.iconLight} width={30} height={30} alt="token" />
return token?.icon ? theme === 'light' ? (
<img style={{ borderRadius: '100%', backgroundColor: token?.coinGeckoId === 'usdai' ? 'white' : 'transparent', }} src={token.iconLight} width={30} height={30} alt="token" />
) : (
<img style={{ borderRadius: '100%' }} src={token.icon} alt="token" width={30} height={30} />
<img style={{ borderRadius: '100%', backgroundColor: token?.coinGeckoId === 'usdai' ? 'white' : 'transparent', }} src={token.icon} alt="token" width={30} height={30} />
) : (
<DefaultIcon />
);
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,9 +119,9 @@
<div className={cx('left')}>
<div className={cx('icon')}>
{(token.icon && isConfirmToken === 'init') || isConfirmToken === 'confirmed' ? (
<img className={cx('logo')} src={token.icon} alt="icon" width={30} height={30} />
<img className={cx('logo')} style={{ borderRadius: '100%', backgroundColor: token?.coinGeckoId === 'usdai' ? 'white' : 'transparent' }} src={token.icon} alt="icon" width={30} height={30} />

Check warning

Code scanning / CodeQL

DOM text reinterpreted as HTML Medium

DOM text
is reinterpreted as HTML without escaping meta-characters.

Copilot Autofix

AI 5 months ago

To fix the issue, we need to ensure that the token.icon value is sanitized or validated before being used as the src attribute of an <img> tag. A common approach is to validate that the URL is a safe and valid image URL. This can be achieved by:

  1. Using a utility function to validate the URL format and ensure it points to an image.
  2. Replacing invalid or unsafe URLs with a default placeholder image.

The changes will be made in InputSwap.tsx to validate the token.icon value before rendering it. Additionally, we will introduce a utility function for URL validation.


Suggested changeset 1
src/pages/UniversalSwap/Swap/components/InputSwap/InputSwap.tsx

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/src/pages/UniversalSwap/Swap/components/InputSwap/InputSwap.tsx b/src/pages/UniversalSwap/Swap/components/InputSwap/InputSwap.tsx
--- a/src/pages/UniversalSwap/Swap/components/InputSwap/InputSwap.tsx
+++ b/src/pages/UniversalSwap/Swap/components/InputSwap/InputSwap.tsx
@@ -16,4 +16,13 @@
 
-const cx = cn.bind(styles);
+const isValidImageUrl = (url: string | undefined): boolean => {
+  if (!url) return false;
+  try {
+    const parsedUrl = new URL(url);
+    return ['http:', 'https:'].includes(parsedUrl.protocol) && /\.(jpeg|jpg|gif|png|svg|webp)$/.test(parsedUrl.pathname);
+  } catch {
+    return false;
+  }
+};
 
+const cx = cn.bind(styles);
 interface InputSwapProps {
@@ -120,3 +129,3 @@
             <div className={cx('icon')}>
-              {(token.icon && isConfirmToken === 'init') || isConfirmToken === 'confirmed' ? (
+              {(isValidImageUrl(token.icon) && isConfirmToken === 'init') || isConfirmToken === 'confirmed' ? (
                 <img className={cx('logo')} style={{ borderRadius: '100%', backgroundColor: token?.coinGeckoId === 'usdai' ? 'white' : 'transparent' }} src={token.icon} alt="icon" width={30} height={30} />
EOF
@@ -16,4 +16,13 @@

const cx = cn.bind(styles);
const isValidImageUrl = (url: string | undefined): boolean => {
if (!url) return false;
try {
const parsedUrl = new URL(url);
return ['http:', 'https:'].includes(parsedUrl.protocol) && /\.(jpeg|jpg|gif|png|svg|webp)$/.test(parsedUrl.pathname);
} catch {
return false;
}
};

const cx = cn.bind(styles);
interface InputSwapProps {
@@ -120,3 +129,3 @@
<div className={cx('icon')}>
{(token.icon && isConfirmToken === 'init') || isConfirmToken === 'confirmed' ? (
{(isValidImageUrl(token.icon) && isConfirmToken === 'init') || isConfirmToken === 'confirmed' ? (
<img className={cx('logo')} style={{ borderRadius: '100%', backgroundColor: token?.coinGeckoId === 'usdai' ? 'white' : 'transparent' }} src={token.icon} alt="icon" width={30} height={30} />
Copilot is powered by AI and may make mistakes. Always verify output.
) : (
<img className={cx('logo')} src={DEFAULT_TOKEN_ICON_URL} alt="icon" width={30} height={30} />
<img className={cx('logo')} style={{ borderRadius: '100%', backgroundColor: token?.coinGeckoId === 'usdai' ? 'white' : 'transparent' }} src={DEFAULT_TOKEN_ICON_URL} alt="icon" width={30} height={30} />
)}
</div>

Expand Down
12 changes: 10 additions & 2 deletions src/pages/UniversalSwap/hooks/useChartUsdPrice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ import { oraichainTokens } from 'initCommon';
import { toFixedIfNecessary } from 'pages/Pools/helpers';
import { useEffect, useState } from 'react';
import { useSelector } from 'react-redux';
import { selectCurrentFromToken, selectCurrentToToken } from 'reducer/tradingSlice';
import { FILTER_TIME_CHART } from 'reducer/type';
import axios from 'rest/request';
import { RootState } from 'store/configure';
import { getTokenIsStableCoin } from '../helpers';

export enum ChartTokenType {
Price = 'Price',
Expand Down Expand Up @@ -34,7 +36,9 @@ export const useChartUsdPrice = (
const [currentData, setCurrentData] = useState<ChartDataValue[]>([]);
const [changePercent, setChangePercent] = useState<string | number>(0);
const allOraichainTokens = useSelector((state: RootState) => state.token.allOraichainTokens || []);

const currentToToken = useSelector(selectCurrentToToken);
const currentFromToken = useSelector(selectCurrentFromToken);
const toTokenDenomIsStable = getTokenIsStableCoin(currentToToken);
// TODO: add loading animation later.
const [isLoading, setIsLoading] = useState(false);

Expand Down Expand Up @@ -76,7 +80,11 @@ export const useChartUsdPrice = (
const onChangeRange = async (type: FILTER_TIME_CHART = FILTER_TIME_CHART.DAY) => {
try {
setIsLoading(true);
const tokenOnOraichain = allOraichainTokens.find((t) => t.contractAddress === token || t.denom === token);
// const tokenOnOraichain = allOraichainTokens.find((t) => t.contractAddress === token || t.denom === token);
const tokenOnOraichain = toTokenDenomIsStable
? allOraichainTokens.find((t) => t.coinGeckoId === currentFromToken?.coinGeckoId) || allOraichainTokens.find((t) => t.coinGeckoId === 'tether')
: allOraichainTokens.find((t) => t.coinGeckoId === currentToToken?.coinGeckoId) || allOraichainTokens.find((t) => t.coinGeckoId === 'oraichain-token')

const tokenDenom = parseTokenInfoRawDenom(tokenOnOraichain);

const data = await getDataPriceMarket(tokenDenom, type);
Expand Down
Loading