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
3 changes: 3 additions & 0 deletions pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@ export default function Home() {
[Field.OUTPUT]: { currencyId: null },
});
const activeChain = passphraseToBackendNetworkName[activeNetwork!].toLowerCase();

useEffect(() => {
if (!activeChain || !xlmTokenList) return undefined

if (prefilledState.INPUT?.currencyId == null) {
const newXlmToken =
xlmTokenList.find((tList) => tList.network === activeChain)?.assets[0].contract ?? null;
Expand Down
1 change: 1 addition & 0 deletions pages/swap/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export default function SwapPage() {
});

useEffect(() => {
if (!activeChain || !xlmTokenList) return undefined
const newXlmToken =
xlmTokenList.find((tList) => tList.network === activeChain)?.assets[0].contract ?? null;
setXlmToken(newXlmToken);
Expand Down
95 changes: 32 additions & 63 deletions src/components/CurrencyInputPanel/CurrencyBalance.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
import { styled, useTheme } from 'soroswap-ui';
import { RowFixed } from 'components/Row';
import { BodySmall } from 'components/Text';
import { MouseoverTooltip } from 'components/Tooltip';
import useGetMyBalances from 'hooks/useGetMyBalances';
import { styled } from 'soroswap-ui';;
import XlmCurrencyBalance from './XlmCurrencyBalance';
import TokenCurrencyBalance from './TokenCurrencyBalance';

import { useSorobanReact, WalletNetwork } from 'stellar-react';
import BigNumber from 'bignumber.js';
import { TextWithLoadingPlaceholder } from 'components/Swap/AdvancedSwapDetails';
import { xlmTokenList } from 'constants/xlmToken';
import { useEffect, useMemo, useState } from 'react';
import { memo, useEffect, useMemo, useState } from 'react';

const StyledBalanceMax = styled('button')<{ disabled?: boolean }>`
background-color: transparent;
Expand Down Expand Up @@ -39,19 +36,14 @@ interface CurrencyBalanceProps {
isLoadingNetworkFees?: boolean;
}

export default function CurrencyBalance({
const CurrencyBalance = ({
contract,
onMax,
hideBalance,
showMaxButton,
networkFees,
isLoadingNetworkFees,
}: CurrencyBalanceProps) {
const {
tokenBalancesResponse,
availableNativeBalance,
isLoading: isLoadingMyBalances,
} = useGetMyBalances();
}: CurrencyBalanceProps) => {
const { activeNetwork } = useSorobanReact();
const [activeChain, setActiveChain] = useState('');
useEffect(() => {
Expand All @@ -68,61 +60,38 @@ export default function CurrencyBalance({
}
}, [activeNetwork]);
const xlmTokenContract = useMemo(() => {

return xlmTokenList.find((tList) => tList.network === activeChain)?.assets[0].contract;
}, [activeChain]);

const isXLM = contract === xlmTokenContract;
const balance =
tokenBalancesResponse?.balances?.find((b) => b?.contract === contract)?.balance || '0';

let availableBalance = balance;
if (isLoadingNetworkFees || !xlmTokenContract) return

/**
* NOTE: Decomposite Balance view for XLM/OTHER tokens and minifed requests
* */
if (isXLM) {
availableBalance = availableNativeBalance(networkFees);
return (
<XlmCurrencyBalance
contract={contract}
onMax={onMax!}
hideBalance={hideBalance}
showMaxButton={showMaxButton}
networkFees={networkFees}
isLoadingNetworkFees={isLoadingNetworkFees}
/>
);
} else {
return (
<TokenCurrencyBalance
contract={contract}
onMax={onMax!}
hideBalance={hideBalance}
showMaxButton={showMaxButton}
/>
);
}

const theme = useTheme();

return (
<TextWithLoadingPlaceholder
syncing={
(isXLM && Boolean(isLoadingNetworkFees)) || isLoadingMyBalances || !tokenBalancesResponse
}
width={150}
>
<RowFixed style={{ height: '17px' }}>
{isXLM ? (
<MouseoverTooltip
title={
<span>
All Stellar accounts must maintain a minimum balance of lumens.{' '}
<a
href="https://developers.stellar.org/docs/learn/fundamentals/lumens#minimum-balance"
style={{ textDecoration: 'underline' }}
target="_blank"
rel="noopener noreferrer"
>
Learn More
</a>
</span>
}
>
<BodySmall color={theme.palette.secondary.main}>
{!hideBalance && contract ? `Available balance: ${Number(availableBalance)}` : null}
</BodySmall>
</MouseoverTooltip>
) : (
<BodySmall color={theme.palette.secondary.main}>
{!hideBalance && contract ? `Balance: ${Number(availableBalance)}` : null}
</BodySmall>
)}

{showMaxButton && Number(availableBalance) > 0 ? (
<StyledBalanceMax onClick={() => onMax(availableBalance.toString())}>
Max
</StyledBalanceMax>
) : null}
</RowFixed>
</TextWithLoadingPlaceholder>
);
}

export default memo(CurrencyBalance);
10 changes: 7 additions & 3 deletions src/components/CurrencyInputPanel/SwapCurrencyInputPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { ButtonBase, styled, useMediaQuery, useTheme } from 'soroswap-ui';
import { useSorobanReact } from 'stellar-react';
import { darken } from 'polished';
import { ReactNode, useCallback, useState } from 'react';
import { memo, ReactNode, useCallback, useState } from 'react';
import { ChevronDown } from 'react-feather';
import { TokenType } from '../../interfaces';
import { flexColumnNoWrap, flexRowNoWrap } from '../../themes/styles';
Expand Down Expand Up @@ -186,7 +186,7 @@ interface SwapCurrencyInputPanelProps {
isLoadingNetworkFees?: boolean;
}

export default function SwapCurrencyInputPanel({
const SwapCurrencyInputPanel = ({
value,
onUserInput,
onMax,
Expand All @@ -210,7 +210,7 @@ export default function SwapCurrencyInputPanel({
networkFees,
isLoadingNetworkFees,
...rest
}: SwapCurrencyInputPanelProps) {
}: SwapCurrencyInputPanelProps) => {
const [modalOpen, setModalOpen] = useState(false);
const { address } = useSorobanReact();
const theme = useTheme();
Expand Down Expand Up @@ -310,6 +310,10 @@ export default function SwapCurrencyInputPanel({
showCurrencyAmount={showCurrencyAmount}
disableNonToken={disableNonToken}
/>

</InputPanel>
);
}


export default memo(SwapCurrencyInputPanel)
75 changes: 75 additions & 0 deletions src/components/CurrencyInputPanel/TokenCurrencyBalance.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { styled, useTheme } from 'soroswap-ui';
import { RowFixed } from 'components/Row';
import { BodySmall } from 'components/Text';
import useGetMyBalances from 'hooks/useGetMyBalances';
import BigNumber from 'bignumber.js';
import { TextWithLoadingPlaceholder } from 'components/Swap/AdvancedSwapDetails';
import { memo } from 'react';

const StyledBalanceMax = styled('button')<{ disabled?: boolean }>`
background-color: transparent;
border: none;
color: ${({ theme }) => theme.palette.custom.borderColor};
cursor: pointer;
font-size: 14px;
font-weight: 600;
opacity: ${({ disabled }) => (!disabled ? 1 : 0.4)};
padding: 4px 6px;
pointer-events: ${({ disabled }) => (!disabled ? 'initial' : 'none')};

:hover {
opacity: ${({ disabled }) => (!disabled ? 0.8 : 0.4)};
}

:focus {
outline: none;
}
`;

interface TokenCurrencyBalanceProps {
contract: string;
onMax: (maxValue: string) => void;
hideBalance: any;
showMaxButton: any;
}

const TokenCurrencyBalance = ({
contract,
onMax,
hideBalance,
showMaxButton,
}: TokenCurrencyBalanceProps) => {

const {
tokenBalancesResponse,
isLoading: isLoadingMyBalances,
} = useGetMyBalances();

const balance =
tokenBalancesResponse?.balances?.find((b) => b?.contract === contract)?.balance || '0';

const availableBalance = balance;

const theme = useTheme();

return (
<TextWithLoadingPlaceholder
syncing={isLoadingMyBalances || !tokenBalancesResponse}
width={150}
>
<RowFixed style={{ height: '17px' }}>
<BodySmall color={theme.palette.secondary.main}>
{!hideBalance && contract ? `Balance: ${Number(availableBalance)}` : null}
</BodySmall>

{showMaxButton && Number(availableBalance) > 0 ? (
<StyledBalanceMax onClick={() => onMax(availableBalance.toString())}>
Max
</StyledBalanceMax>
) : null}
</RowFixed>
</TextWithLoadingPlaceholder>
);
}

export default memo(TokenCurrencyBalance);
91 changes: 91 additions & 0 deletions src/components/CurrencyInputPanel/XlmCurrencyBalance.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import { styled, useTheme } from 'soroswap-ui';
import { RowFixed } from 'components/Row';
import { BodySmall } from 'components/Text';
import { MouseoverTooltip } from 'components/Tooltip';
import useGetMyBalances, { calculateAvailableBalance } from 'hooks/useGetMyBalances';
import BigNumber from 'bignumber.js';
import { TextWithLoadingPlaceholder } from 'components/Swap/AdvancedSwapDetails';
import useGetSubentryCount from 'hooks/useGetSubentryCount';
import { memo } from 'react';

const StyledBalanceMax = styled('button')<{ disabled?: boolean }>`
background-color: transparent;
border: none;
color: ${({ theme }) => theme.palette.custom.borderColor};
cursor: pointer;
font-size: 14px;
font-weight: 600;
opacity: ${({ disabled }) => (!disabled ? 1 : 0.4)};
padding: 4px 6px;
pointer-events: ${({ disabled }) => (!disabled ? 'initial' : 'none')};

:hover {
opacity: ${({ disabled }) => (!disabled ? 0.8 : 0.4)};
}

:focus {
outline: none;
}
`;

interface XlmCurrencyBalanceProps {
contract: string;
onMax: (maxValue: string) => void;
hideBalance: any;
showMaxButton: any;
networkFees?: string | number | BigNumber | null;
isLoadingNetworkFees?: boolean;
}

const XlmCurrencyBalance = ({
contract,
onMax,
hideBalance,
showMaxButton,
networkFees,
isLoadingNetworkFees,
}: XlmCurrencyBalanceProps) => {

const { subentryCount, nativeBalance, isLoading: isSubentryLoading } = useGetSubentryCount();

const availableBalance = calculateAvailableBalance(nativeBalance, networkFees, subentryCount)

const theme = useTheme();

return (
<TextWithLoadingPlaceholder
syncing={Boolean(isLoadingNetworkFees)}
width={150}
>
<RowFixed style={{ height: '17px' }}>
<MouseoverTooltip
title={
<span>
All Stellar accounts must maintain a minimum balance of lumens.{' '}
<a
href="https://developers.stellar.org/docs/learn/fundamentals/lumens#minimum-balance"
style={{ textDecoration: 'underline' }}
target="_blank"
rel="noopener noreferrer"
>
Learn More
</a>
</span>
}
>
<BodySmall color={theme.palette.secondary.main}>
{!hideBalance && contract ? `Available balance: ${Number(availableBalance)}` : null}
</BodySmall>
</MouseoverTooltip>

{showMaxButton && Number(availableBalance) > 0 ? (
<StyledBalanceMax onClick={() => onMax(availableBalance.toString())}>
Max
</StyledBalanceMax>
) : null}
</RowFixed>
</TextWithLoadingPlaceholder>
);
}

export default memo(XlmCurrencyBalance)
24 changes: 15 additions & 9 deletions src/components/NumericalInput/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,17 @@
import { styled } from 'soroswap-ui';
import React from 'react';
import React, { useMemo } from 'react';
import { escapeRegExp } from '../../utils/escapeRegExp';

interface InnerInputProps extends Omit<React.HTMLProps<HTMLInputElement>, 'ref' | 'onChange' | 'as'> {
value: string | number;
onUserInput: (input: string) => void;
error ?: boolean;
fontSize ?: string;
align ?: 'right' | 'left';
prependSymbol ?: string;
}


const StyledInput = styled('input')<{ error?: boolean; fontSize?: string; align?: string }>`
color: ${({ error, theme }) => (error ? theme.palette.error.main : theme.palette.primary.main)};
width: 0;
Expand Down Expand Up @@ -46,14 +56,9 @@ export const Input = React.memo(function InnerInput({
placeholder,
prependSymbol,
...rest
}: {
value: string | number;
onUserInput: (input: string) => void;
error?: boolean;
fontSize?: string;
align?: 'right' | 'left';
prependSymbol?: string;
} & Omit<React.HTMLProps<HTMLInputElement>, 'ref' | 'onChange' | 'as'>) {
}: InnerInputProps) {


const enforcer = (nextUserInput: string) => {
if (nextUserInput === '' || inputRegex.test(escapeRegExp(nextUserInput))) {
onUserInput(nextUserInput);
Expand Down Expand Up @@ -94,4 +99,5 @@ export const Input = React.memo(function InnerInput({
);
});


export default Input;
Loading
Loading