diff --git a/public/assets/tokens/token-ada-disabled.svg b/public/assets/tokens/token-ada-disabled.svg
new file mode 100755
index 000000000..021109af4
--- /dev/null
+++ b/public/assets/tokens/token-ada-disabled.svg
@@ -0,0 +1,40 @@
+
diff --git a/public/assets/tokens/token-ada.svg b/public/assets/tokens/token-ada.svg
new file mode 100755
index 000000000..d98137137
--- /dev/null
+++ b/public/assets/tokens/token-ada.svg
@@ -0,0 +1,40 @@
+
diff --git a/public/assets/tokens/token-empty.svg b/public/assets/tokens/token-empty.svg
new file mode 100755
index 000000000..c997eba7c
--- /dev/null
+++ b/public/assets/tokens/token-empty.svg
@@ -0,0 +1,4 @@
+
diff --git a/public/assets/tokens/token-erdoge.svg b/public/assets/tokens/token-erdoge.svg
new file mode 100644
index 000000000..1ffe0e643
--- /dev/null
+++ b/public/assets/tokens/token-erdoge.svg
@@ -0,0 +1,42 @@
+
diff --git a/public/assets/tokens/token-erg.svg b/public/assets/tokens/token-erg.svg
new file mode 100755
index 000000000..363c26306
--- /dev/null
+++ b/public/assets/tokens/token-erg.svg
@@ -0,0 +1,4 @@
+
diff --git a/public/assets/tokens/token-ergopad.svg b/public/assets/tokens/token-ergopad.svg
new file mode 100644
index 000000000..6f0c6d36f
--- /dev/null
+++ b/public/assets/tokens/token-ergopad.svg
@@ -0,0 +1,43 @@
+
diff --git a/public/assets/tokens/token-kushti.svg b/public/assets/tokens/token-kushti.svg
new file mode 100644
index 000000000..a2506ca9f
--- /dev/null
+++ b/public/assets/tokens/token-kushti.svg
@@ -0,0 +1,5 @@
+
diff --git a/public/assets/tokens/token-lunadog.svg b/public/assets/tokens/token-lunadog.svg
new file mode 100644
index 000000000..961560dc2
--- /dev/null
+++ b/public/assets/tokens/token-lunadog.svg
@@ -0,0 +1,15 @@
+
diff --git a/public/assets/tokens/token-neta.svg b/public/assets/tokens/token-neta.svg
new file mode 100644
index 000000000..0b9da0002
--- /dev/null
+++ b/public/assets/tokens/token-neta.svg
@@ -0,0 +1,10 @@
+
diff --git a/public/assets/tokens/token-sigrsv.svg b/public/assets/tokens/token-sigrsv.svg
new file mode 100644
index 000000000..6b66f5d4f
--- /dev/null
+++ b/public/assets/tokens/token-sigrsv.svg
@@ -0,0 +1,7 @@
+
diff --git a/public/assets/tokens/token-sigusd.svg b/public/assets/tokens/token-sigusd.svg
new file mode 100644
index 000000000..fb0f59067
--- /dev/null
+++ b/public/assets/tokens/token-sigusd.svg
@@ -0,0 +1,6 @@
+
diff --git a/src/@types/dapp-wallet-web-bridge.d.ts b/src/@types/dapp-wallet-web-bridge.d.ts
index 498ca2e15..a012068fc 100644
--- a/src/@types/dapp-wallet-web-bridge.d.ts
+++ b/src/@types/dapp-wallet-web-bridge.d.ts
@@ -27,7 +27,7 @@ namespace ErgoBridge {
get_used_addresses: (paginate?: Paging) => Promise
;
- get_unused_addresses: () => Address[];
+ get_unused_addresses: () => Promise;
sign_tx: (tx: UnsignedErgoTxProxy) => Promise;
diff --git a/src/App.tsx b/src/App.tsx
index 230757ee2..e7f1c7a70 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -5,9 +5,9 @@ import React, { Suspense, useEffect, useState } from 'react';
import { withTranslation } from 'react-i18next';
import { Redirect, Route, Router, Switch } from 'react-router-dom';
+import { TABLET_BRAKE_POINT } from './common/constants/screen';
import Layout from './components/common/Layout/Layout';
import { MobilePlug } from './components/MobilePlug/MobilePlug';
-import { TABLET_BRAKE_POINT } from './constants/screen';
import {
AppLoadingProvider,
SettingsProvider,
diff --git a/src/api/addresses.ts b/src/api/addresses.ts
new file mode 100644
index 000000000..cc2202c88
--- /dev/null
+++ b/src/api/addresses.ts
@@ -0,0 +1,9 @@
+import { publishReplay, refCount, switchMap } from 'rxjs';
+
+import { selectedNetwork$ } from '../network/network';
+
+export const addresses$ = selectedNetwork$.pipe(
+ switchMap((network) => network.addresses$),
+ publishReplay(1),
+ refCount(),
+);
diff --git a/src/api/pendingTransactions.ts b/src/api/pendingTransactions.ts
new file mode 100644
index 000000000..ee928cbb6
--- /dev/null
+++ b/src/api/pendingTransactions.ts
@@ -0,0 +1,15 @@
+import { publishReplay, refCount, switchMap } from 'rxjs';
+
+import { selectedNetwork$ } from '../network/network';
+
+// export const pendingTransactions$ = selectedNetwork$.pipe(
+// switchMap((network) => network.pendingTransactions$),
+// publishReplay(1),
+// refCount(),
+// );
+
+export const pendingTransactionsCount$ = selectedNetwork$.pipe(
+ switchMap((network) => network.pendingTransactionsCount$),
+ publishReplay(1),
+ refCount(),
+);
diff --git a/src/api/transactionsHistory.ts b/src/api/transactionsHistory.ts
new file mode 100644
index 000000000..ddb92dfca
--- /dev/null
+++ b/src/api/transactionsHistory.ts
@@ -0,0 +1,7 @@
+import { switchMap } from 'rxjs';
+
+import { selectedNetwork$ } from '../network/network';
+
+export const transactionsHistory$ = selectedNetwork$.pipe(
+ switchMap((network) => network.getTxHistory(50)),
+);
diff --git a/src/constants/env.ts b/src/common/constants/env.ts
similarity index 100%
rename from src/constants/env.ts
rename to src/common/constants/env.ts
diff --git a/src/constants/erg.ts b/src/common/constants/erg.ts
similarity index 100%
rename from src/constants/erg.ts
rename to src/common/constants/erg.ts
diff --git a/src/constants/screen.ts b/src/common/constants/screen.ts
similarity index 100%
rename from src/constants/screen.ts
rename to src/common/constants/screen.ts
diff --git a/src/constants/settings.ts b/src/common/constants/settings.ts
similarity index 91%
rename from src/constants/settings.ts
rename to src/common/constants/settings.ts
index 69e0ab94f..a5a09ee53 100644
--- a/src/constants/settings.ts
+++ b/src/common/constants/settings.ts
@@ -1,4 +1,4 @@
-import { fractionsToNum } from '../utils/math';
+import { fractionsToNum } from '../../utils/math';
import { DEFAULT_MINER_FEE, ERG_DECIMALS, MIN_EX_FEE } from './erg';
export const defaultMinerFee = fractionsToNum(DEFAULT_MINER_FEE, ERG_DECIMALS);
diff --git a/src/hooks/useObservable.ts b/src/common/hooks/useObservable.ts
similarity index 88%
rename from src/hooks/useObservable.ts
rename to src/common/hooks/useObservable.ts
index 1215f8b6d..f31864d67 100644
--- a/src/hooks/useObservable.ts
+++ b/src/common/hooks/useObservable.ts
@@ -1,3 +1,4 @@
+/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import { useEffect, useState } from 'react';
import { Observable, Subject, Subscription, switchMap } from 'rxjs';
@@ -5,22 +6,24 @@ import { Unpacked } from '../utils/unpacked';
export function useObservable(
observable: Observable,
- config?: { deps?: any[] },
+ deps?: any[],
): [T | undefined, boolean, Error];
export function useObservable(
observable: Observable,
- config: { defaultValue: T; deps?: any[] },
+ deps: any[],
+ defaultValue: T,
): [T, boolean, Error];
export function useObservable(
observable: Observable,
- config?: { defaultValue?: T; deps?: any[] },
+ deps?: any[],
+ defaultValue?: T,
): [T | undefined, boolean, Error | undefined] {
const [{ data, error, loading }, setParams] = useState<{
data: T | undefined;
error: Error | undefined;
loading: boolean;
}>({
- data: config?.defaultValue,
+ data: defaultValue,
error: undefined,
loading: false,
});
@@ -38,14 +41,14 @@ export function useObservable(
});
return () => subscription.unsubscribe();
- }, config?.deps || []);
+ }, deps || []);
return [data, loading, error];
}
export function useSubject Observable>(
observableAction: F,
- config?: { deps?: any[] },
+ deps?: any[],
): [
Unpacked> | undefined,
(...args: Parameters) => void,
@@ -54,7 +57,8 @@ export function useSubject Observable>(
];
export function useSubject Observable>(
observableAction: F,
- config: { deps?: any[]; defaultValue: Unpacked> },
+ deps: any[],
+ defaultValue: Unpacked>,
): [
Unpacked>,
(...args: Parameters) => void,
@@ -63,7 +67,8 @@ export function useSubject Observable>(
];
export function useSubject Observable>(
observableAction: F,
- config?: { deps?: any[]; defaultValue?: Unpacked> },
+ deps?: any[],
+ defaultValue?: Unpacked>,
): [
Unpacked> | undefined,
(...args: Parameters) => void,
@@ -75,7 +80,7 @@ export function useSubject Observable>(
error: Error | undefined;
loading: boolean;
}>({
- data: config?.defaultValue,
+ data: defaultValue,
error: undefined,
loading: false,
});
@@ -106,7 +111,7 @@ export function useSubject Observable>(
});
return () => subscription.unsubscribe();
- }, config?.deps || []);
+ }, deps || []);
return [data, nextData.next, loading, error];
}
@@ -121,12 +126,12 @@ export function useSubscription Observable>(
callback: (value: Unpacked>) => void,
deps?: any[],
): [(...args: Parameters) => void];
-export function useSubscription(
+export function useSubscription(
item: any,
callback: any,
deps?: any[],
): void | [any] {
- const [nextData, setNextData] = useState<{
+ const [nextData] = useState<{
subject: Subject;
next: (...args: any[]) => void;
//@ts-ignore
diff --git a/src/common/models/AmmPool.ts b/src/common/models/AmmPool.ts
index fc06107b0..eab84ab96 100644
--- a/src/common/models/AmmPool.ts
+++ b/src/common/models/AmmPool.ts
@@ -34,6 +34,17 @@ export class AmmPool {
return new Currency(this.pool.x.amount, this.pool.x.asset);
}
+ shares(input: Currency): [Currency, Currency] {
+ const [assetX, assetY] = this.pool.shares(
+ new AssetAmount(input.asset, input.amount),
+ );
+
+ return [
+ new Currency(assetX.amount, assetX.asset),
+ new Currency(assetY.amount, assetY.asset),
+ ];
+ }
+
getAssetAmount(asset: AssetInfo): Currency {
if (this.pool.x.asset.id === asset.id) {
return this.x;
diff --git a/src/common/models/Currency.ts b/src/common/models/Currency.ts
index 0f0a71677..835aaa95d 100644
--- a/src/common/models/Currency.ts
+++ b/src/common/models/Currency.ts
@@ -1,6 +1,10 @@
import { AssetInfo } from '@ergolabs/ergo-sdk/build/main/entities/assetInfo';
-import { parseUserInputToFractions, renderFractions } from '../../utils/math';
+import {
+ math,
+ parseUserInputToFractions,
+ renderFractions,
+} from '../../utils/math';
import { getDecimalsCount, normalizeAmount } from '../utils/amount';
const createUnknownAsset = (decimals = 0): AssetInfo => ({
@@ -106,6 +110,18 @@ export class Currency {
return new Currency(this.amount - currency.amount, this.asset);
}
+ percent(percent: number | string): Currency {
+ if (this.amount === 0n) {
+ return this;
+ }
+ const fmtAmount = this.toString({ suffix: false });
+ const newAmount = math.evaluate!(
+ `${fmtAmount} / 100 * ${percent}`,
+ ).toString();
+
+ return new Currency(normalizeAmount(newAmount, this.asset), this.asset);
+ }
+
toString(config?: { suffix: boolean }): string {
if ((!config || !!config?.suffix) && !isUnknownAsset(this.asset)) {
return `${renderFractions(this.amount, this.asset.decimals)} ${
diff --git a/src/utils/unpacked.ts b/src/common/utils/unpacked.ts
similarity index 100%
rename from src/utils/unpacked.ts
rename to src/common/utils/unpacked.ts
diff --git a/src/components/Header/AnalyticsDataTag/AnalyticsDataTag.tsx b/src/components/Header/AnalyticsDataTag/AnalyticsDataTag.tsx
index ee6e14aab..3c6e668cd 100644
--- a/src/components/Header/AnalyticsDataTag/AnalyticsDataTag.tsx
+++ b/src/components/Header/AnalyticsDataTag/AnalyticsDataTag.tsx
@@ -1,16 +1,14 @@
import { LoadingOutlined } from '@ant-design/icons';
import React from 'react';
+import { useObservable } from '../../../common/hooks/useObservable';
import { Box, Flex, Typography } from '../../../ergodex-cdk';
-import { useObservable } from '../../../hooks/useObservable';
import { aggregatedAnalyticsData24H$ } from '../../../services/new/analytics';
import { formatToUSD } from '../../../services/number';
import { renderFractions } from '../../../utils/math';
export const AnalyticsDataTag = (): JSX.Element => {
- const [currentStats] = useObservable(aggregatedAnalyticsData24H$, {
- defaultValue: {},
- });
+ const [currentStats] = useObservable(aggregatedAnalyticsData24H$, [], {});
return (
diff --git a/src/components/Header/GlobalSettingsModal/GlobalSettingsModal.tsx b/src/components/Header/GlobalSettingsModal/GlobalSettingsModal.tsx
index ea5e07651..15932142e 100644
--- a/src/components/Header/GlobalSettingsModal/GlobalSettingsModal.tsx
+++ b/src/components/Header/GlobalSettingsModal/GlobalSettingsModal.tsx
@@ -2,7 +2,7 @@ import './GlobalSettingsModal.less';
import React, { useState } from 'react';
-import { defaultMinerFee } from '../../../constants/settings';
+import { defaultMinerFee } from '../../../common/constants/settings';
import { useSettings } from '../../../context';
import {
Button,
diff --git a/src/components/Header/Header.less b/src/components/Header/Header.less
index ad19734d4..a336c516b 100644
--- a/src/components/Header/Header.less
+++ b/src/components/Header/Header.less
@@ -6,6 +6,7 @@
width: 100%;
flex-flow: row nowrap;
justify-content: space-between;
+ transition: transform .3s;
&__wrapper {
position: relative;
@@ -53,4 +54,8 @@
&__btn {
border: 1px solid transparent;
}
+
+ &_hidden {
+ transform: translateY(-72px);
+ }
}
diff --git a/src/components/Header/Header.tsx b/src/components/Header/Header.tsx
index 89a0e98a1..291ec54be 100644
--- a/src/components/Header/Header.tsx
+++ b/src/components/Header/Header.tsx
@@ -1,10 +1,11 @@
import './Header.less';
-import React from 'react';
+import cn from 'classnames';
+import React, { useEffect, useState } from 'react';
-import { ERG_TOKEN_NAME } from '../../constants/erg';
+import { ERG_TOKEN_NAME } from '../../common/constants/erg';
+import { useObservable } from '../../common/hooks/useObservable';
import { useSettings } from '../../context';
-import { useObservable } from '../../hooks/useObservable';
import {
nativeTokenBalance$,
WalletState,
@@ -28,9 +29,27 @@ export const Header: React.FC = () => {
// TODO: Update with rx [EDEX-487]
const [balance] = useObservable(nativeTokenBalance$);
const [walletState] = useObservable(walletState$);
+ const [hidden, setHidden] = useState(false);
+
+ useEffect(() => {
+ let currentScrollY = window.scrollY;
+ const handleScroll = () => {
+ if (currentScrollY > window.scrollY) {
+ setHidden(false);
+ }
+ if (currentScrollY < window.scrollY) {
+ setHidden(true);
+ }
+ currentScrollY = window.scrollY;
+ };
+
+ document.addEventListener('scroll', handleScroll);
+
+ return () => document.removeEventListener('scroll', handleScroll);
+ }, []);
return (
-
+
diff --git a/src/components/MobilePlug/MobilePlug.tsx b/src/components/MobilePlug/MobilePlug.tsx
index ed498d468..c76d73a92 100644
--- a/src/components/MobilePlug/MobilePlug.tsx
+++ b/src/components/MobilePlug/MobilePlug.tsx
@@ -1,7 +1,7 @@
import React from 'react';
import { ReactComponent as SmartphoneImage } from '../../assets/images/smartphone.svg';
-import { LANDING_URL } from '../../constants/env';
+import { LANDING_URL } from '../../common/constants/env';
import { Button, Flex, Typography } from '../../ergodex-cdk';
const MobilePlug = (): JSX.Element => {
diff --git a/src/components/TokenIcon/TokenIcon.tsx b/src/components/TokenIcon/TokenIcon.tsx
index 3afbdf717..49d17bcbd 100644
--- a/src/components/TokenIcon/TokenIcon.tsx
+++ b/src/components/TokenIcon/TokenIcon.tsx
@@ -1,7 +1,5 @@
import React from 'react';
-import sprite from '../../assets/icons/sprite/sprite.svg';
-
type TokenIconProps = React.DetailedHTMLProps<
React.HTMLAttributes
,
HTMLDivElement
@@ -38,16 +36,13 @@ const TokenIcon: React.FC = ({ name, size, ...rest }) => {
}}
{...rest}
>
-
+ />
);
};
diff --git a/src/components/WalletModal/AddressesTab/AddressesTab.tsx b/src/components/WalletModal/AddressesTab/AddressesTab.tsx
index e236b8338..e5ccd07e8 100644
--- a/src/components/WalletModal/AddressesTab/AddressesTab.tsx
+++ b/src/components/WalletModal/AddressesTab/AddressesTab.tsx
@@ -2,7 +2,7 @@ import './AddressTab.less';
import React, { useCallback, useEffect, useMemo, useState } from 'react';
-import { ERG_DECIMALS } from '../../../constants/erg';
+import { ERG_DECIMALS } from '../../../common/constants/erg';
import {
Address,
useSettings,
diff --git a/src/components/WalletModal/TokensTab/TokensTab.tsx b/src/components/WalletModal/TokensTab/TokensTab.tsx
index 548ae4b17..2babd1d80 100644
--- a/src/components/WalletModal/TokensTab/TokensTab.tsx
+++ b/src/components/WalletModal/TokensTab/TokensTab.tsx
@@ -1,11 +1,11 @@
import React from 'react';
import { Flex, List } from '../../../ergodex-cdk';
-import { useWalletBalance } from '../../../services/new/balance';
+import { useAssetWalletBalance } from '../../../services/new/balance';
import { TokenListItem } from './TokenListItem/TokenListItem';
export const TokensTab: React.FC = () => {
- const [balance] = useWalletBalance();
+ const [balance] = useAssetWalletBalance();
return (
diff --git a/src/components/WalletModal/WalletModal.tsx b/src/components/WalletModal/WalletModal.tsx
index 18805f457..a5eb4aa58 100644
--- a/src/components/WalletModal/WalletModal.tsx
+++ b/src/components/WalletModal/WalletModal.tsx
@@ -1,8 +1,8 @@
import React from 'react';
+import { useObservable } from '../../common/hooks/useObservable';
import { Box, Flex, Modal, Typography } from '../../ergodex-cdk';
import { Tabs } from '../../ergodex-cdk/components/Tabs/Tabs';
-import { useObservable } from '../../hooks/useObservable';
import { nativeTokenBalance$ } from '../../services/new/core';
import { isLowBalance } from '../../utils/walletMath';
import { AddressesTab } from './AddressesTab/AddressesTab';
diff --git a/src/components/common/ActionForm/ActionButton/ActionButton.tsx b/src/components/common/ActionForm/ActionButton/ActionButton.tsx
index e97b2e8cc..ef66f411f 100644
--- a/src/components/common/ActionForm/ActionButton/ActionButton.tsx
+++ b/src/components/common/ActionForm/ActionButton/ActionButton.tsx
@@ -1,7 +1,10 @@
import './ActionButton.less';
+import { DateTime } from 'luxon';
import React, { FC, ReactNode } from 'react';
+import { interval, map } from 'rxjs';
+import { useObservable } from '../../../../common/hooks/useObservable';
import { Button, ButtonProps } from '../../../../ergodex-cdk';
import { ConnectWalletButton } from '../../ConnectWalletButton/ConnectWalletButton';
@@ -13,9 +16,15 @@ export enum ActionButtonState {
INSUFFICIENT_LIQUIDITY,
LOADING,
CHECK_INTERNET_CONNECTION,
+ ANETA_SWAP_LOCK,
ACTION,
}
+export const END_TIMER_DATE = DateTime.utc(2022, 1, 28, 18, 0, 0);
+
+export const LOCKED_TOKEN_ID =
+ '472c3d4ecaa08fb7392ff041ee2e6af75f4a558810a74b28600549d5392810e8';
+
const selectTokenState = (): ButtonProps => ({
children: 'Select a token',
type: 'primary',
@@ -99,7 +108,39 @@ export interface ActionButtonProps {
readonly children: ReactNode;
}
+const getDiff = () =>
+ END_TIMER_DATE.diffNow(['hour', 'minute', 'second', 'millisecond']);
+
+// const renderTimer = () =>
+
+const timer$ = interval(1000).pipe(map(() => getDiff()));
+
export const ActionButton: FC = (props) => {
+ const [timer] = useObservable(timer$, [], getDiff());
+
+ if (props.state === ActionButtonState.ANETA_SWAP_LOCK) {
+ return (
+
+ );
+ }
+
const { children, ...other } = getButtonPropsByState(
props.state,
props.token,
diff --git a/src/components/common/ActionForm/ActionForm.tsx b/src/components/common/ActionForm/ActionForm.tsx
index 03960c939..d3ddba68e 100644
--- a/src/components/common/ActionForm/ActionForm.tsx
+++ b/src/components/common/ActionForm/ActionForm.tsx
@@ -2,9 +2,9 @@
import React, { FC, ReactNode, useEffect, useState } from 'react';
import { debounceTime, first, Observable } from 'rxjs';
+import { useObservable } from '../../../common/hooks/useObservable';
import { Flex } from '../../../ergodex-cdk';
import { Form, FormGroup } from '../../../ergodex-cdk/components/Form/NewForm';
-import { useObservable } from '../../../hooks/useObservable';
import { isWalletLoading$ } from '../../../services/new/core';
import { isOnline$ } from '../../../services/new/networkConnection';
import { ActionButton, ActionButtonState } from './ActionButton/ActionButton';
@@ -15,6 +15,7 @@ export interface ActionFormProps {
readonly isTokensNotSelected?: (form: T) => boolean;
readonly isAmountNotEntered?: (form: T) => boolean;
readonly isLiquidityInsufficient?: (form: T) => boolean;
+ readonly isSwapLocked?: (form: T) => boolean;
readonly getInsufficientTokenNameForTx?: (form: T) => undefined | string;
readonly getInsufficientTokenNameForFee?: (form: T) => undefined | string;
readonly action?: (form: T) => Promise | Observable | void;
@@ -29,6 +30,7 @@ export const ActionForm: FC> = ({
isAmountNotEntered,
isTokensNotSelected,
getInsufficientTokenNameForFee,
+ isSwapLocked,
getInsufficientTokenNameForTx,
children,
}) => {
@@ -36,10 +38,8 @@ export const ActionForm: FC> = ({
const [isWalletLoading] = useObservable(isWalletLoading$);
const [value] = useObservable(
form.valueChangesWithSilent$.pipe(debounceTime(100)),
- {
- deps: [form],
- defaultValue: {},
- },
+ [form],
+ {},
);
const [buttonData, setButtonData] = useState<{
state: ActionButtonState;
@@ -55,6 +55,8 @@ export const ActionForm: FC> = ({
setButtonData({ state: ActionButtonState.LOADING });
} else if (isTokensNotSelected && isTokensNotSelected(value)) {
setButtonData({ state: ActionButtonState.SELECT_TOKEN });
+ } else if (isSwapLocked && isSwapLocked(value)) {
+ setButtonData({ state: ActionButtonState.ANETA_SWAP_LOCK });
} else if (isAmountNotEntered && isAmountNotEntered(value)) {
setButtonData({ state: ActionButtonState.ENTER_AMOUNT });
} else if (
diff --git a/src/components/common/ConnectWalletButton/ConnectWalletButton.tsx b/src/components/common/ConnectWalletButton/ConnectWalletButton.tsx
index 42d8ee20d..d20722920 100644
--- a/src/components/common/ConnectWalletButton/ConnectWalletButton.tsx
+++ b/src/components/common/ConnectWalletButton/ConnectWalletButton.tsx
@@ -3,9 +3,9 @@ import './ConnectWalletButton.less';
import cn from 'classnames';
import React, { FC, ReactNode } from 'react';
+import { useObservable } from '../../../common/hooks/useObservable';
import { useAppLoadingState } from '../../../context';
import { Button, ButtonProps, Modal } from '../../../ergodex-cdk';
-import { useObservable } from '../../../hooks/useObservable';
import { isWalletSetuped$ } from '../../../services/new/core';
import { ChooseWalletModal } from './ChooseWalletModal/ChooseWalletModal';
diff --git a/src/components/common/TokenControl/TokenControl.tsx b/src/components/common/TokenControl/TokenControl.tsx
index 72a72db14..2a4b45df0 100644
--- a/src/components/common/TokenControl/TokenControl.tsx
+++ b/src/components/common/TokenControl/TokenControl.tsx
@@ -6,14 +6,14 @@ import React, { FC, ReactNode } from 'react';
import { useTranslation } from 'react-i18next';
import { Observable, of } from 'rxjs';
+import { useObservable } from '../../../common/hooks/useObservable';
import { Currency } from '../../../common/models/Currency';
import { Animation, Box, Button, Flex, Typography } from '../../../ergodex-cdk';
import {
Form,
useFormContext,
} from '../../../ergodex-cdk/components/Form/NewForm';
-import { useObservable } from '../../../hooks/useObservable';
-import { useWalletBalance } from '../../../services/new/balance';
+import { useAssetWalletBalance } from '../../../services/new/balance';
import { isWalletLoading$ } from '../../../services/new/core';
import {
TokenAmountInput,
@@ -80,7 +80,7 @@ export const TokenControlFormItem: FC = ({
}) => {
const { t } = useTranslation();
const { form } = useFormContext();
- const [balance, balanceLoading] = useWalletBalance();
+ const [balance, balanceLoading] = useAssetWalletBalance();
const [selectedAsset] = useObservable(
tokenName
? form.controls[tokenName].valueChangesWithSilent$
diff --git a/src/components/common/TokenControl/TokenSelect/TokenListModal/TokenListModal.tsx b/src/components/common/TokenControl/TokenSelect/TokenListModal/TokenListModal.tsx
index 9c0b28662..fb5a5feed 100644
--- a/src/components/common/TokenControl/TokenSelect/TokenListModal/TokenListModal.tsx
+++ b/src/components/common/TokenControl/TokenSelect/TokenListModal/TokenListModal.tsx
@@ -4,8 +4,8 @@ import { AssetInfo } from '@ergolabs/ergo-sdk';
import React, { useState } from 'react';
import { Observable, of } from 'rxjs';
+import { useObservable } from '../../../../../common/hooks/useObservable';
import { Flex, Input, Modal, SearchOutlined } from '../../../../../ergodex-cdk';
-import { useObservable } from '../../../../../hooks/useObservable';
import { TokenListItem } from './TokenListItem';
interface TokenListModalProps {
diff --git a/src/components/common/TxHistory/RefundConfirmationModal/RefundConfirmationModal.tsx b/src/components/common/TxHistory/RefundConfirmationModal/RefundConfirmationModal.tsx
index a6c6e4861..28e0a2049 100644
--- a/src/components/common/TxHistory/RefundConfirmationModal/RefundConfirmationModal.tsx
+++ b/src/components/common/TxHistory/RefundConfirmationModal/RefundConfirmationModal.tsx
@@ -1,6 +1,7 @@
import { TxId } from '@ergolabs/ergo-sdk';
import React, { useState } from 'react';
+import { useObservable } from '../../../../common/hooks/useObservable';
import { Address, useSettings } from '../../../../context';
import {
Box,
@@ -12,7 +13,6 @@ import {
Modal,
Typography,
} from '../../../../ergodex-cdk';
-import { useObservable } from '../../../../hooks/useObservable';
import { utxos$ } from '../../../../services/new/core';
import { submitTx } from '../../../../services/yoroi';
import { refund } from '../../../../utils/ammOperations';
diff --git a/src/components/common/TxHistory/TxHistoryModal/TxHistoryModal.tsx b/src/components/common/TxHistory/TxHistoryModal/TxHistoryModal.tsx
index e1ae5f127..e7a3d6e84 100644
--- a/src/components/common/TxHistory/TxHistoryModal/TxHistoryModal.tsx
+++ b/src/components/common/TxHistory/TxHistoryModal/TxHistoryModal.tsx
@@ -1,9 +1,11 @@
import Icon from '@ant-design/icons';
import { TxId } from '@ergolabs/ergo-sdk';
import { Typography } from 'antd';
-import React, { useCallback, useEffect, useState } from 'react';
+import React, { useCallback } from 'react';
+import { transactionsHistory$ } from '../../../../api/transactionsHistory';
import { ReactComponent as DotsVertical } from '../../../../assets/icons/icon-dots-vertical.svg';
+import { useObservable } from '../../../../common/hooks/useObservable';
import { useWalletAddresses, WalletAddressState } from '../../../../context';
import {
Box,
@@ -14,32 +16,21 @@ import {
Modal,
Skeleton,
} from '../../../../ergodex-cdk';
-import networkHistory from '../../../../services/networkHistory';
import { isRefundableOperation } from '../../../../utils/ammOperations';
import { exploreTx } from '../../../../utils/redirect';
import { InputOutputColumn } from '../InputOutputColumn/InputOutputColumn';
import { RefundConfirmationModal } from '../RefundConfirmationModal/RefundConfirmationModal';
import { TxStatusTag } from '../TxStatusTag/TxStatusTag';
import { TxTypeTag } from '../TxTypeTag/TxTypeTag';
-import { Operation, OperationStatus } from '../types';
+import { OperationStatus } from '../types';
import { normalizeOperations } from '../utils';
const DotsIconVertical = () => ;
const TxHistoryModal = (): JSX.Element => {
- const TXS_TO_DISPLAY = 50;
-
- const [operations, setOperations] = useState();
+ const [txs] = useObservable(transactionsHistory$);
const walletAddresses = useWalletAddresses();
- useEffect(() => {
- if (walletAddresses.state === WalletAddressState.LOADED) {
- networkHistory
- .getAllByAddresses(walletAddresses.addresses, TXS_TO_DISPLAY)
- .then((ops) => setOperations(normalizeOperations(ops)));
- }
- }, [walletAddresses]);
-
const handleOpenRefundConfirmationModal = useCallback(
(txId) => {
if (walletAddresses.state === WalletAddressState.LOADED) {
@@ -94,8 +85,8 @@ const TxHistoryModal = (): JSX.Element => {
- {operations ? (
- operations.map((op, index) => {
+ {txs ? (
+ normalizeOperations(txs).map((op, index) => {
return (
implements AbstractFormItem {
constructor(
public name: string,
private param: FormControlParams,
+ // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
private parent: any,
) {}
@@ -359,7 +360,11 @@ export const FormContext = createContext<{
warningMessages?: Messages;
}>({} as any);
-export const useFormContext = () => useContext(FormContext);
+export const useFormContext = (): {
+ form: FormGroup;
+ errorMessages?: Messages;
+ warningMessages?: Messages;
+} => useContext(FormContext);
class _Form extends React.Component> {
constructor(props: FormProps) {
diff --git a/src/hooks/usePair.ts b/src/hooks/usePair.ts
index d00438d2e..0fb04cab7 100644
--- a/src/hooks/usePair.ts
+++ b/src/hooks/usePair.ts
@@ -2,10 +2,10 @@ import { AssetAmount } from '@ergolabs/ergo-sdk';
import { useEffect, useState } from 'react';
import { AssetPair } from '../@types/asset';
+import { useObservable } from '../common/hooks/useObservable';
import { AmmPool } from '../common/models/AmmPool';
import { isWalletLoading$ } from '../services/new/core';
import { parseUserInputToFractions, renderFractions } from '../utils/math';
-import { useObservable } from './useObservable';
interface Pair {
pair?: AssetPair;
diff --git a/src/mappers/tokenMapper.ts b/src/mappers/tokenMapper.ts
index aeffc27b1..3297d09cc 100644
--- a/src/mappers/tokenMapper.ts
+++ b/src/mappers/tokenMapper.ts
@@ -28,4 +28,9 @@ export const TOKEN_MAPPER = new Map([
'30974274078845f263b4f21787e33cc99e9ec19a17ad85a5bc6da2cca91c5a2e',
'WT_ADA',
],
+ [
+ 'd71693c49a84fbbecd4908c94813b46514b18b67a99952dc1e6e4791556de413',
+ 'ergopad',
+ ],
+ ['472c3d4ecaa08fb7392ff041ee2e6af75f4a558810a74b28600549d5392810e8', 'NETA'],
]);
diff --git a/src/mappers/varifiedTokensMapper.ts b/src/mappers/varifiedTokensMapper.ts
index 105380172..9287b4527 100644
--- a/src/mappers/varifiedTokensMapper.ts
+++ b/src/mappers/varifiedTokensMapper.ts
@@ -16,4 +16,9 @@ export const VERIFIED_TOKENS = new Map([
'36aba4b4a97b65be491cf9f5ca57b5408b0da8d0194f30ec8330d1e8946161c1',
'Erdoge',
],
+ [
+ 'd71693c49a84fbbecd4908c94813b46514b18b67a99952dc1e6e4791556de413',
+ 'ergopad',
+ ],
+ ['472c3d4ecaa08fb7392ff041ee2e6af75f4a558810a74b28600549d5392810e8', 'NETA'],
]);
diff --git a/src/network/common.ts b/src/network/common.ts
new file mode 100644
index 000000000..b3c3c4af3
--- /dev/null
+++ b/src/network/common.ts
@@ -0,0 +1,9 @@
+import { AmmDexOperation } from '@ergolabs/ergo-dex-sdk';
+import { Address } from '@ergolabs/ergo-sdk';
+import { Observable } from 'rxjs';
+
+export interface Network {
+ readonly addresses$: Observable;
+ readonly pendingTransactionsCount$: Observable;
+ readonly getTxHistory: (limit: number) => Observable;
+}
diff --git a/src/network/ergo/addresses/addresses.ts b/src/network/ergo/addresses/addresses.ts
new file mode 100644
index 000000000..1211976f4
--- /dev/null
+++ b/src/network/ergo/addresses/addresses.ts
@@ -0,0 +1,28 @@
+import {
+ combineLatest,
+ defer,
+ from,
+ map,
+ publishReplay,
+ refCount,
+ switchMap,
+} from 'rxjs';
+
+import { isWalletConnected$ } from '../../../services/new/core';
+
+const usedAddresses$ = isWalletConnected$.pipe(
+ switchMap(() => defer(() => from(ergo.get_used_addresses()))),
+);
+
+const unusedAddresses$ = isWalletConnected$.pipe(
+ switchMap(() => defer(() => from(ergo.get_unused_addresses()))),
+);
+
+export const addresses$ = combineLatest([
+ usedAddresses$,
+ unusedAddresses$,
+]).pipe(
+ map(([usedAddrs, unusedAddrs]) => unusedAddrs.concat(usedAddrs)),
+ publishReplay(1),
+ refCount(),
+);
diff --git a/src/network/ergo/index.ts b/src/network/ergo/index.ts
new file mode 100644
index 000000000..00dffea11
--- /dev/null
+++ b/src/network/ergo/index.ts
@@ -0,0 +1,10 @@
+import { Network } from '../common';
+import { addresses$ } from './addresses/addresses';
+import { pendingTransactionsCount$ } from './transactions/pendingTransactions';
+import { getTxHistory } from './transactions/transactionsHistory';
+
+export const ergoNetwork: Network = {
+ addresses$,
+ pendingTransactionsCount$,
+ getTxHistory,
+};
diff --git a/src/network/ergo/transactions/common.ts b/src/network/ergo/transactions/common.ts
new file mode 100644
index 000000000..245289e6f
--- /dev/null
+++ b/src/network/ergo/transactions/common.ts
@@ -0,0 +1 @@
+export const TX_LIMIT = 100;
diff --git a/src/network/ergo/transactions/pendingTransactions.ts b/src/network/ergo/transactions/pendingTransactions.ts
new file mode 100644
index 000000000..365f2fb8b
--- /dev/null
+++ b/src/network/ergo/transactions/pendingTransactions.ts
@@ -0,0 +1,48 @@
+import { AugErgoTx } from '@ergolabs/ergo-sdk';
+import {
+ combineLatest,
+ from,
+ map,
+ Observable,
+ of,
+ publishReplay,
+ refCount,
+ switchMap,
+} from 'rxjs';
+
+import networkHistory from '../../../services/networkHistory';
+import { addresses$ } from '../addresses/addresses';
+import { TX_LIMIT } from './common';
+
+const getUTxsByAddress = (
+ address: string,
+ offset = 0,
+): Observable => {
+ return from(
+ networkHistory.network.getUTxsByAddress(address, {
+ offset,
+ limit: TX_LIMIT,
+ }),
+ ).pipe(
+ switchMap(([txs, count]) => {
+ return count < TX_LIMIT
+ ? of(txs)
+ : getUTxsByAddress(address, offset + TX_LIMIT).pipe(
+ map((newTxs) => txs.concat(newTxs)),
+ );
+ }),
+ );
+};
+
+const uTxs$: Observable = addresses$.pipe(
+ switchMap((addresses) => combineLatest(addresses.map(getUTxsByAddress))),
+ map((uTxs) => uTxs.flatMap((i) => i)),
+ publishReplay(1),
+ refCount(),
+);
+
+export const pendingTransactionsCount$ = uTxs$.pipe(
+ map((uTxs) => uTxs.length),
+ publishReplay(1),
+ refCount(),
+);
diff --git a/src/network/ergo/transactions/transactionsHistory.ts b/src/network/ergo/transactions/transactionsHistory.ts
new file mode 100644
index 000000000..93e685917
--- /dev/null
+++ b/src/network/ergo/transactions/transactionsHistory.ts
@@ -0,0 +1,68 @@
+import { AmmDexOperation } from '@ergolabs/ergo-dex-sdk';
+import { Address, AugErgoTx } from '@ergolabs/ergo-sdk';
+import {
+ combineLatest,
+ first,
+ from,
+ map,
+ Observable,
+ of,
+ publishReplay,
+ refCount,
+ switchMap,
+} from 'rxjs';
+
+import networkHistory from '../../../services/networkHistory';
+import { addresses$ } from '../addresses/addresses';
+import { TX_LIMIT } from './common';
+
+const parseOp = (
+ tx: AugErgoTx,
+ address: Address,
+): AmmDexOperation | undefined =>
+ networkHistory['parseOp'](tx, true, [address]);
+
+const getTxsByAddress = (
+ address: string,
+ limit = 50,
+ offset = 0,
+ prevOperationsCount = 0,
+): Observable => {
+ return from(
+ networkHistory.network.getTxsByAddress(address, {
+ offset,
+ limit: TX_LIMIT,
+ }),
+ ).pipe(
+ map<
+ [AugErgoTx[], number],
+ [AugErgoTx[], number, AmmDexOperation[], number]
+ >(([txs, txsCount]) => {
+ const ops = txs.map((tx) => parseOp(tx, address)).filter(Boolean);
+
+ return [txs, txsCount, ops as any, ops.length];
+ }),
+ switchMap(([, txsCount, ops, opsCount]) => {
+ if (txsCount < TX_LIMIT || opsCount + prevOperationsCount > limit) {
+ return of(ops);
+ }
+ return getTxsByAddress(
+ address,
+ limit,
+ offset + TX_LIMIT,
+ opsCount + prevOperationsCount,
+ ).pipe(map((newOps) => ops.concat(newOps)));
+ }),
+ );
+};
+
+export const getTxHistory = (limit: number): Observable =>
+ addresses$.pipe(
+ switchMap((addresses) =>
+ combineLatest(addresses.map((a) => getTxsByAddress(a, limit))),
+ ),
+ map((txs) => txs.flatMap((tx) => tx)),
+ first(),
+ publishReplay(1),
+ refCount(),
+ );
diff --git a/src/network/network.ts b/src/network/network.ts
new file mode 100644
index 000000000..22f83e059
--- /dev/null
+++ b/src/network/network.ts
@@ -0,0 +1,12 @@
+import { BehaviorSubject, Observable } from 'rxjs';
+
+import { Network } from './common';
+import { ergoNetwork } from './ergo';
+
+const updateSelectedNetwork$ = new BehaviorSubject(ergoNetwork);
+
+export const changeSelectedNetwork = (network: Network): void =>
+ updateSelectedNetwork$.next(network);
+
+export const selectedNetwork$: Observable =
+ updateSelectedNetwork$.asObservable();
diff --git a/src/pages/Pool/AddLiquidity/AddLiquidity.tsx b/src/pages/Pool/AddLiquidity/AddLiquidity.tsx
index 621d9ff77..6bdbdcb9f 100644
--- a/src/pages/Pool/AddLiquidity/AddLiquidity.tsx
+++ b/src/pages/Pool/AddLiquidity/AddLiquidity.tsx
@@ -17,6 +17,11 @@ import {
switchMap,
} from 'rxjs';
+import {
+ useObservable,
+ useSubject,
+ useSubscription,
+} from '../../../common/hooks/useObservable';
import { ActionForm } from '../../../components/common/ActionForm/ActionForm';
import { PoolSelect } from '../../../components/common/PoolSelect/PoolSelect';
import { TokenControlFormItem } from '../../../components/common/TokenControl/TokenControl';
@@ -28,13 +33,8 @@ import {
import { FormPageWrapper } from '../../../components/FormPageWrapper/FormPageWrapper';
import { Flex, Typography } from '../../../ergodex-cdk';
import { Form, useForm } from '../../../ergodex-cdk/components/Form/NewForm';
-import {
- useObservable,
- useSubject,
- useSubscription,
-} from '../../../hooks/useObservable';
import { assets$, getAvailableAssetFor } from '../../../services/new/assets';
-import { useWalletBalance } from '../../../services/new/balance';
+import { useAssetWalletBalance } from '../../../services/new/balance';
import { useMaxTotalFees, useNetworkAsset } from '../../../services/new/core';
import {
getAvailablePoolById,
@@ -51,7 +51,7 @@ const getAvailablePools = (xId?: string, yId?: string) =>
xId && yId ? getPoolByPair(xId, yId) : of([]);
const AddLiquidity = (): JSX.Element => {
- const [balance] = useWalletBalance();
+ const [balance] = useAssetWalletBalance();
const totalFees = useMaxTotalFees();
const networkAsset = useNetworkAsset();
const { poolId } = useParams<{ poolId?: PoolId }>();
diff --git a/src/pages/Pool/AddLiquidity/AddLiquidityConfirmationModal/AddLiquidityConfirmationModal.tsx b/src/pages/Pool/AddLiquidity/AddLiquidityConfirmationModal/AddLiquidityConfirmationModal.tsx
index 196a760ac..860aa4863 100644
--- a/src/pages/Pool/AddLiquidity/AddLiquidityConfirmationModal/AddLiquidityConfirmationModal.tsx
+++ b/src/pages/Pool/AddLiquidity/AddLiquidityConfirmationModal/AddLiquidityConfirmationModal.tsx
@@ -2,15 +2,13 @@ import { minValueForOrder } from '@ergolabs/ergo-dex-sdk';
import { BoxSelection, DefaultBoxSelector, ErgoTx } from '@ergolabs/ergo-sdk';
import React, { FC } from 'react';
+import { ERG_DECIMALS, UI_FEE } from '../../../../common/constants/erg';
+import { useObservable } from '../../../../common/hooks/useObservable';
import { InfoTooltip } from '../../../../components/InfoTooltip/InfoTooltip';
-import { ERG_DECIMALS, UI_FEE } from '../../../../constants/erg';
-import { defaultExFee } from '../../../../constants/settings';
import { useSettings } from '../../../../context';
import { Box, Button, Flex, Modal, Typography } from '../../../../ergodex-cdk';
-import { useObservable } from '../../../../hooks/useObservable';
import { explorer } from '../../../../services/explorer';
import {
- useMaxTotalFees,
useMinExFee,
useMinTotalFees,
utxos$,
diff --git a/src/pages/Pool/Pool.less b/src/pages/Pool/Pool.less
index ba8700b60..d01b4abe7 100644
--- a/src/pages/Pool/Pool.less
+++ b/src/pages/Pool/Pool.less
@@ -6,7 +6,7 @@
.ant-tabs-tabpane {
overflow: auto;
- max-height: 62vh;
+ max-height: 63vh;
}
}
}
diff --git a/src/pages/Pool/Pool.tsx b/src/pages/Pool/Pool.tsx
index ee68df830..fd9ebf823 100644
--- a/src/pages/Pool/Pool.tsx
+++ b/src/pages/Pool/Pool.tsx
@@ -3,10 +3,10 @@ import './Pool.less';
import React from 'react';
import { useHistory } from 'react-router-dom';
+import { useObservable } from '../../common/hooks/useObservable';
import { ConnectWalletButton } from '../../components/common/ConnectWalletButton/ConnectWalletButton';
import { FormPageWrapper } from '../../components/FormPageWrapper/FormPageWrapper';
import { Button, Flex, PlusOutlined, Tabs } from '../../ergodex-cdk';
-import { useObservable } from '../../hooks/useObservable';
import { isWalletLoading$, isWalletSetuped$ } from '../../services/new/core';
import { availablePools$, pools$ } from '../../services/new/pools';
import { EmptyPositionsWrapper } from './components/EmptyPositionsWrapper/EmptyPositionsWrapper';
@@ -30,7 +30,7 @@ const PoolPageWrapper: React.FC = ({
= ({
};
const Pool = (): JSX.Element => {
- const [isWalletConnected] = useObservable(isWalletSetuped$, {
- defaultValue: false,
- });
+ const [isWalletConnected] = useObservable(isWalletSetuped$, [], false);
const [isWalletLoading] = useObservable(isWalletLoading$);
const [availablePools, isAvailablePoolsLoading] = useObservable(
availablePools$,
- {
- defaultValue: [],
- },
+ [],
+ [],
);
- const [pools, isPoolsLoading] = useObservable(pools$, {
- defaultValue: [],
- });
+ const [pools, isPoolsLoading] = useObservable(pools$, [], []);
const history = useHistory();
@@ -81,6 +76,9 @@ const Pool = (): JSX.Element => {
onClick={handleAddLiquidity}
>
+
+
+
{isWalletConnected ? (
{
)}
-
-
-
);
diff --git a/src/pages/Pool/PoolPosition/PoolPosition.tsx b/src/pages/Pool/PoolPosition/PoolPosition.tsx
index 2a4de2c1e..3891fe187 100644
--- a/src/pages/Pool/PoolPosition/PoolPosition.tsx
+++ b/src/pages/Pool/PoolPosition/PoolPosition.tsx
@@ -4,6 +4,7 @@ import { PoolId } from '@ergolabs/ergo-dex-sdk';
import React, { useEffect, useState } from 'react';
import { useHistory, useParams } from 'react-router-dom';
+import { useSubject } from '../../../common/hooks/useObservable';
import { FormPageWrapper } from '../../../components/FormPageWrapper/FormPageWrapper';
import { TokenIcon } from '../../../components/TokenIcon/TokenIcon';
import { TokenIconPair } from '../../../components/TokenIconPair/TokenIconPair';
@@ -16,7 +17,6 @@ import {
Skeleton,
Typography,
} from '../../../ergodex-cdk';
-import { useSubject } from '../../../hooks/useObservable';
import { usePair } from '../../../hooks/usePair';
import { getPoolById } from '../../../services/new/pools';
import { getPoolFee } from '../../../utils/pool';
diff --git a/src/pages/Pool/components/LiquidityPositionsList/LiquidityPositionsItem/LiquidityPositionsItem.tsx b/src/pages/Pool/components/LiquidityPositionsList/LiquidityPositionsItem/LiquidityPositionsItem.tsx
index 2e84f7965..811d2b1bc 100644
--- a/src/pages/Pool/components/LiquidityPositionsList/LiquidityPositionsItem/LiquidityPositionsItem.tsx
+++ b/src/pages/Pool/components/LiquidityPositionsList/LiquidityPositionsItem/LiquidityPositionsItem.tsx
@@ -1,9 +1,9 @@
import { PoolId } from '@ergolabs/ergo-dex-sdk';
import React, { useEffect } from 'react';
+import { useSubject } from '../../../../../common/hooks/useObservable';
import { AmmPool } from '../../../../../common/models/AmmPool';
import { Flex } from '../../../../../ergodex-cdk';
-import { useSubject } from '../../../../../hooks/useObservable';
import { getAggregatedPoolAnalyticsDataById24H } from '../../../../../services/new/analytics';
import { LiquidityPositionsItemAnalytics } from './LiquidityPositionsItemAnalytics/LiquidityPositionsItemAnalytics';
import { LiquidityPositionsItemWrapper } from './LiquidityPositionsItemWrapper/LiquidityPositionsItemWrapper';
diff --git a/src/pages/Pool/components/LiquidityPositionsList/LiquidityPositionsList.tsx b/src/pages/Pool/components/LiquidityPositionsList/LiquidityPositionsList.tsx
index a7c9ea065..0268fca0f 100644
--- a/src/pages/Pool/components/LiquidityPositionsList/LiquidityPositionsList.tsx
+++ b/src/pages/Pool/components/LiquidityPositionsList/LiquidityPositionsList.tsx
@@ -5,8 +5,10 @@ import { isEmpty } from 'lodash';
import React, { FC } from 'react';
import { useHistory } from 'react-router-dom';
+import { useObservable } from '../../../../common/hooks/useObservable';
import { AmmPool } from '../../../../common/models/AmmPool';
-import { Button, Flex, PlusOutlined } from '../../../../ergodex-cdk';
+import { Button, Flex, List, PlusOutlined } from '../../../../ergodex-cdk';
+import { isWalletSetuped$ } from '../../../../services/new/core';
import { EmptyPositionsWrapper } from '../EmptyPositionsWrapper/EmptyPositionsWrapper';
import { PositionListLoader } from '../PositionListLoader/PositionListLoader';
import { LiquidityPositionsItem } from './LiquidityPositionsItem/LiquidityPositionsItem';
@@ -20,10 +22,14 @@ const LiquidityPositionsList: FC = ({
loading,
pools,
}): JSX.Element => {
+ const [isWalletConnected] = useObservable(isWalletSetuped$, [], false);
+
const history = useHistory();
const onPositionClick = (id: PoolId) => {
- history.push(`/pool/${id}/`);
+ if (isWalletConnected) {
+ history.push(`/pool/${id}/`);
+ }
};
function handleAddLiquidity() {
@@ -51,16 +57,11 @@ const LiquidityPositionsList: FC = ({
return (
- {pools.map((pool, index) => {
- return (
-
-
-
- );
- })}
+
+ {(pool) => (
+
+ )}
+
);
};
diff --git a/src/pages/Remove/ConfirmRemoveModal/ConfirmRemoveModal.tsx b/src/pages/Remove/ConfirmRemoveModal/ConfirmRemoveModal.tsx
index 86316617d..6f62e2395 100644
--- a/src/pages/Remove/ConfirmRemoveModal/ConfirmRemoveModal.tsx
+++ b/src/pages/Remove/ConfirmRemoveModal/ConfirmRemoveModal.tsx
@@ -2,11 +2,10 @@ import { minValueForOrder } from '@ergolabs/ergo-dex-sdk';
import { BoxSelection, DefaultBoxSelector } from '@ergolabs/ergo-sdk';
import React from 'react';
+import { ERG_DECIMALS, UI_FEE } from '../../../common/constants/erg';
import { AmmPool } from '../../../common/models/AmmPool';
import { Currency } from '../../../common/models/Currency';
import { InfoTooltip } from '../../../components/InfoTooltip/InfoTooltip';
-import { ERG_DECIMALS, UI_FEE } from '../../../constants/erg';
-import { defaultExFee } from '../../../constants/settings';
import { useSettings } from '../../../context';
import {
Box,
@@ -23,14 +22,13 @@ import { poolActions } from '../../../services/poolActions';
import { submitTx } from '../../../services/yoroi';
import { makeTarget } from '../../../utils/ammMath';
import { parseUserInputToFractions } from '../../../utils/math';
-import { calculateTotalFee } from '../../../utils/transactions';
import { PairSpace } from '../PairSpace/PairSpace';
import { RemoveFormSpaceWrapper } from '../RemoveFormSpaceWrapper/RemoveFormSpaceWrapper';
interface ConfirmRemoveModalProps {
onClose: (p: Promise) => void;
pool: AmmPool;
- lpToRemove: number;
+ lpToRemove: Currency;
xAmount: Currency;
yAmount: Currency;
}
@@ -53,7 +51,7 @@ const ConfirmRemoveModal: React.FC = ({
const removeOperation = async (pool: AmmPool) => {
const actions = poolActions(pool['pool']);
- const lp = pool['pool'].lp.withAmount(BigInt(lpToRemove.toFixed(0)));
+ const lp = pool['pool'].lp.withAmount(lpToRemove.amount);
const poolId = pool.id;
diff --git a/src/pages/Remove/Remove.tsx b/src/pages/Remove/Remove.tsx
index 7ce328ccb..2d1f76b2c 100644
--- a/src/pages/Remove/Remove.tsx
+++ b/src/pages/Remove/Remove.tsx
@@ -1,10 +1,15 @@
// TODO: REPLACE_ANTD_SKELETON_COMPONENT[EDEX-467]
import { PoolId } from '@ergolabs/ergo-dex-sdk';
-import { evaluate } from 'mathjs';
-import React, { useCallback, useEffect, useState } from 'react';
+import React, { FC, useEffect } from 'react';
import { useParams } from 'react-router';
+import { combineLatest, debounceTime, map, Observable, of, skip } from 'rxjs';
-import { AssetPair } from '../../@types/asset';
+import {
+ useObservable,
+ useSubject,
+ useSubscription,
+} from '../../common/hooks/useObservable';
+import { AmmPool } from '../../common/models/AmmPool';
import { Currency } from '../../common/models/Currency';
import {
openConfirmationModal,
@@ -14,145 +19,142 @@ import { FormPageWrapper } from '../../components/FormPageWrapper/FormPageWrappe
import { SubmitButton } from '../../components/SubmitButton/SubmitButton';
import { TokenIconPair } from '../../components/TokenIconPair/TokenIconPair';
import { Flex, Skeleton, Typography } from '../../ergodex-cdk';
-import { usePair } from '../../hooks/usePair';
-import { usePosition } from '../../hooks/usePosition';
+import {
+ Form,
+ FormGroup,
+ useForm,
+} from '../../ergodex-cdk/components/Form/NewForm';
+import { lpWalletBalance$ } from '../../services/new/balance';
+import { getPoolById } from '../../services/new/pools';
import { ConfirmRemoveModal } from './ConfirmRemoveModal/ConfirmRemoveModal';
import { PairSpace } from './PairSpace/PairSpace';
import { RemoveFormSpaceWrapper } from './RemoveFormSpaceWrapper/RemoveFormSpaceWrapper';
import { RemovePositionSlider } from './RemovePositionSlider/RemovePositionSlider';
-const getPercent = (val: number | undefined, percent: string): number =>
- Number(evaluate(`${val} * ${percent}%`));
+interface PoolData {
+ readonly pool: AmmPool;
+ readonly lpBalance: Currency;
+ readonly xAmount: Currency;
+ readonly yAmount: Currency;
+}
-export const Remove = (): JSX.Element => {
- const { poolId } = useParams<{ poolId: PoolId }>();
+interface RemoveFormModel {
+ readonly percent: number;
+ readonly xAmount?: Currency;
+ readonly yAmount?: Currency;
+}
- const DEFAULT_SLIDER_PERCENTAGE = '100';
- const [percent, setPercent] = useState(DEFAULT_SLIDER_PERCENTAGE);
- const [initialPair, setInitialPair] = useState();
- const [isFirstPairLoading, setIsFirstPairLoading] = useState(true);
- const [lpToRemove, setLpToRemove] = useState();
+const getPoolDataById = (poolId: PoolId): Observable =>
+ !poolId
+ ? of(undefined)
+ : combineLatest([getPoolById(poolId), lpWalletBalance$]).pipe(
+ map(([pool, balance]) => {
+ if (!pool) {
+ return undefined;
+ }
+ const lpBalance = balance.get(pool.lp.asset);
+ const [xAmount, assetY] = pool.shares(lpBalance);
- const position = usePosition(poolId);
- const { pair, lpBalance, setPair } = usePair(position);
+ return { pool, lpBalance, xAmount: xAmount, yAmount: assetY };
+ }),
+ );
- useEffect(() => {
- if (isFirstPairLoading && pair && lpBalance) {
- setInitialPair(pair);
- setIsFirstPairLoading(false);
- setLpToRemove(lpBalance);
- }
- }, [isFirstPairLoading, pair, lpBalance]);
+export const Remove: FC = () => {
+ const { poolId } = useParams<{ poolId: PoolId }>();
+ const [poolData, updatePoolData] = useSubject(getPoolDataById);
+ const form = useForm({
+ percent: 100,
+ xAmount: undefined,
+ yAmount: undefined,
+ });
+ const [formValue] = useObservable(
+ form.valueChangesWithSilent$.pipe(debounceTime(100)),
+ );
- const handleChangePercent = useCallback(
- (percentage) => {
- setPercent(percentage);
+ useEffect(() => updatePoolData(poolId), []);
- if (position && pair && initialPair && setPair && lpBalance) {
- setLpToRemove(getPercent(lpBalance, percentage));
- setPair({
- assetX: {
- name: pair.assetX.name,
- asset: pair.assetX.asset,
- amount: +getPercent(initialPair.assetX.amount, percentage).toFixed(
- pair.assetX.asset?.decimals,
- ),
- earnedFees: pair.assetX?.earnedFees,
- },
- assetY: {
- name: pair.assetY.name,
- asset: pair.assetY.asset,
- amount: +getPercent(initialPair.assetY.amount, percentage).toFixed(
- pair.assetY.asset?.decimals,
- ),
- earnedFees: pair.assetY?.earnedFees,
- },
- });
- }
+ useSubscription(
+ form.controls.percent.valueChanges$.pipe(skip(1)),
+ (percent) => {
+ form.patchValue({
+ xAmount:
+ percent === 100
+ ? poolData?.xAmount
+ : poolData?.xAmount.percent(percent),
+ yAmount:
+ percent === 100
+ ? poolData?.yAmount
+ : poolData?.yAmount.percent(percent),
+ });
},
- [position, pair, initialPair, setPair, lpBalance],
+ [poolData],
);
- const handleRemove = () => {
- if (pair && position && lpToRemove) {
- const xAmount = new Currency(
- pair.assetX.amount?.toString(),
- position.x.asset,
- );
- const yAmount = new Currency(
- pair.assetY.amount?.toString(),
- position.y.asset,
- );
+ const handleRemove = (
+ form: FormGroup,
+ poolData: PoolData,
+ ) => {
+ const xAmount = form.value.xAmount || poolData.xAmount;
+ const yAmount = form.value.yAmount || poolData.yAmount;
- openConfirmationModal(
- (next) => {
- return (
-
- );
- },
- Operation.REMOVE_LIQUIDITY,
- xAmount,
- yAmount,
- );
- }
+ openConfirmationModal(
+ (next) => {
+ return (
+
+ );
+ },
+ Operation.REMOVE_LIQUIDITY,
+ xAmount,
+ yAmount,
+ );
};
return (
- <>
-
- {pair ? (
+
+ {poolData ? (
+ */}
- Remove
+
+ Remove
+
- ) : (
-
- )}
-
- >
+
+ ) : (
+
+ )}
+
);
};
diff --git a/src/pages/Remove/RemovePositionSlider/RemovePositionSlider.tsx b/src/pages/Remove/RemovePositionSlider/RemovePositionSlider.tsx
index a32f4c724..7861e7201 100644
--- a/src/pages/Remove/RemovePositionSlider/RemovePositionSlider.tsx
+++ b/src/pages/Remove/RemovePositionSlider/RemovePositionSlider.tsx
@@ -11,12 +11,12 @@ const marks = {
};
interface RemovePositionSliderProps {
- percent: string;
+ value: number;
onChange: (p: number) => void;
}
const RemovePositionSlider: React.FC = ({
- percent,
+ value,
onChange,
}) => {
return (
@@ -26,14 +26,14 @@ const RemovePositionSlider: React.FC = ({
- {percent}%
+ {value}%
diff --git a/src/pages/Swap/OperationSettings/NitroInput/NitroInput.tsx b/src/pages/Swap/OperationSettings/NitroInput/NitroInput.tsx
index 756defa13..53e75a7e6 100644
--- a/src/pages/Swap/OperationSettings/NitroInput/NitroInput.tsx
+++ b/src/pages/Swap/OperationSettings/NitroInput/NitroInput.tsx
@@ -1,6 +1,6 @@
import React, { ChangeEvent, FC } from 'react';
-import { MIN_NITRO } from '../../../../constants/erg';
+import { MIN_NITRO } from '../../../../common/constants/erg';
import { Alert, Button, Flex, Input } from '../../../../ergodex-cdk';
import { Control } from '../../../../ergodex-cdk/components/Form/NewForm';
diff --git a/src/pages/Swap/OperationSettings/OperationSettings.tsx b/src/pages/Swap/OperationSettings/OperationSettings.tsx
index 498736840..b0a21b676 100644
--- a/src/pages/Swap/OperationSettings/OperationSettings.tsx
+++ b/src/pages/Swap/OperationSettings/OperationSettings.tsx
@@ -1,9 +1,10 @@
import React, { useState } from 'react';
import { filter, skip } from 'rxjs';
+import { MIN_NITRO } from '../../../common/constants/erg';
+import { defaultSlippage } from '../../../common/constants/settings';
+import { useSubscription } from '../../../common/hooks/useObservable';
import { InfoTooltip } from '../../../components/InfoTooltip/InfoTooltip';
-import { MIN_NITRO } from '../../../constants/erg';
-import { defaultSlippage } from '../../../constants/settings';
import { useSettings } from '../../../context';
import {
Box,
@@ -19,7 +20,6 @@ import {
Messages,
useForm,
} from '../../../ergodex-cdk/components/Form/NewForm';
-import { useSubscription } from '../../../hooks/useObservable';
import { NitroInput } from './NitroInput/NitroInput';
import { SlippageInput } from './SlippageInput/SlippageInput';
diff --git a/src/pages/Swap/OperationSettings/SlippageInput/SlippageInput.tsx b/src/pages/Swap/OperationSettings/SlippageInput/SlippageInput.tsx
index 4a28245f2..ec6369ca7 100644
--- a/src/pages/Swap/OperationSettings/SlippageInput/SlippageInput.tsx
+++ b/src/pages/Swap/OperationSettings/SlippageInput/SlippageInput.tsx
@@ -1,12 +1,12 @@
import './SlippageInput.less';
-import React, { ChangeEvent, FC, useState } from 'react';
+import React, { ChangeEvent, FC } from 'react';
import {
defaultSlippage,
SlippageMax,
SlippageMin,
-} from '../../../../constants/settings';
+} from '../../../../common/constants/settings';
import { Alert, Button, Flex, Input } from '../../../../ergodex-cdk';
import { Control } from '../../../../ergodex-cdk/components/Form/NewForm';
diff --git a/src/pages/Swap/Ratio/Ratio.tsx b/src/pages/Swap/Ratio/Ratio.tsx
index 3e1976cb0..47d90c3dd 100644
--- a/src/pages/Swap/Ratio/Ratio.tsx
+++ b/src/pages/Swap/Ratio/Ratio.tsx
@@ -3,10 +3,10 @@ import './Ratio.less';
import React, { FC, useState } from 'react';
import { debounceTime, map } from 'rxjs';
+import { useObservable } from '../../../common/hooks/useObservable';
import { Currency } from '../../../common/models/Currency';
import { Animation, Typography } from '../../../ergodex-cdk';
import { FormGroup } from '../../../ergodex-cdk/components/Form/NewForm';
-import { useObservable } from '../../../hooks/useObservable';
import { SwapFormModel } from '../SwapFormModel';
const calculateOutputPrice = ({
@@ -54,7 +54,7 @@ export const Ratio: FC<{ form: FormGroup }> = ({ form }) => {
: `1 ${form.value.fromAsset?.name} = ${price?.toString()}`,
),
),
- { deps: [form, reversedRatio] },
+ [form, reversedRatio],
);
const toggleReversedRatio = () =>
diff --git a/src/pages/Swap/Swap.tsx b/src/pages/Swap/Swap.tsx
index 3f31fccec..cb2a72fc5 100644
--- a/src/pages/Swap/Swap.tsx
+++ b/src/pages/Swap/Swap.tsx
@@ -1,7 +1,7 @@
import './Swap.less';
-import { AssetInfo } from '@ergolabs/ergo-sdk/build/main/entities/assetInfo';
import { maxBy } from 'lodash';
+import { DateTime } from 'luxon';
import React, { useEffect, useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import {
@@ -17,7 +17,12 @@ import {
tap,
} from 'rxjs';
+import { useSubscription } from '../../common/hooks/useObservable';
import { AmmPool } from '../../common/models/AmmPool';
+import {
+ END_TIMER_DATE,
+ LOCKED_TOKEN_ID,
+} from '../../components/common/ActionForm/ActionButton/ActionButton';
import { ActionForm } from '../../components/common/ActionForm/ActionForm';
import { TokenControlFormItem } from '../../components/common/TokenControl/TokenControl';
import {
@@ -27,9 +32,8 @@ import {
import { FormPageWrapper } from '../../components/FormPageWrapper/FormPageWrapper';
import { Button, Flex, SwapOutlined, Typography } from '../../ergodex-cdk';
import { useForm } from '../../ergodex-cdk/components/Form/NewForm';
-import { useSubscription } from '../../hooks/useObservable';
import { assets$, getAvailableAssetFor } from '../../services/new/assets';
-import { useWalletBalance } from '../../services/new/balance';
+import { useAssetWalletBalance } from '../../services/new/balance';
import { useMaxTotalFees, useNetworkAsset } from '../../services/new/core';
import { getPoolByPair } from '../../services/new/pools';
import { OperationSettings } from './OperationSettings/OperationSettings';
@@ -60,7 +64,7 @@ export const Swap = (): JSX.Element => {
pool: undefined,
});
const networkAsset = useNetworkAsset();
- const [balance] = useWalletBalance();
+ const [balance] = useAssetWalletBalance();
const totalFees = useMaxTotalFees();
const updateToAssets$ = useMemo(
() => new BehaviorSubject(undefined),
@@ -101,6 +105,10 @@ export const Swap = (): JSX.Element => {
const isTokensNotSelected = ({ toAsset, fromAsset }: SwapFormModel) =>
!toAsset || !fromAsset;
+ const isSwapLocked = ({ toAsset, fromAsset }: SwapFormModel) =>
+ (toAsset?.id === LOCKED_TOKEN_ID || fromAsset?.id === LOCKED_TOKEN_ID) &&
+ DateTime.now().toMillis() < END_TIMER_DATE.toMillis();
+
const submitSwap = (value: Required) => {
openConfirmationModal(
(next) => {
@@ -119,11 +127,8 @@ export const Swap = (): JSX.Element => {
return toAmount?.gt(pool.getAssetAmount(toAmount?.asset));
};
- useSubscription(form.valueChangesWithSilent$, (value) => console.log(value));
-
- useSubscription(
- form.controls.fromAsset.valueChangesWithSilent$,
- (token: AssetInfo | undefined) => updateToAssets$.next(token?.id),
+ useSubscription(form.controls.fromAsset.valueChangesWithSilent$, (token) =>
+ updateToAssets$.next(token?.id),
);
useSubscription(form.controls.fromAsset.valueChanges$, () =>
@@ -164,7 +169,7 @@ export const Swap = (): JSX.Element => {
form.controls.pool.valueChanges$,
]).pipe(
debounceTime(100),
- filter(([_, pool]) => !!form.value.fromAsset && !!pool),
+ filter(([, pool]) => !!form.value.fromAsset && !!pool),
),
([amount, pool]) => {
form.patchValue(
@@ -214,6 +219,7 @@ export const Swap = (): JSX.Element => {
isAmountNotEntered={isAmountNotEntered}
isTokensNotSelected={isTokensNotSelected}
isLiquidityInsufficient={isLiquidityInsufficient}
+ isSwapLocked={isSwapLocked}
action={submitSwap}
>
diff --git a/src/pages/Swap/SwapConfirmationModal/SwapConfirmationModal.tsx b/src/pages/Swap/SwapConfirmationModal/SwapConfirmationModal.tsx
index 6aacf91b4..bc8de1308 100644
--- a/src/pages/Swap/SwapConfirmationModal/SwapConfirmationModal.tsx
+++ b/src/pages/Swap/SwapConfirmationModal/SwapConfirmationModal.tsx
@@ -8,20 +8,15 @@ import {
} from '@ergolabs/ergo-sdk';
import React, { FC, useEffect, useState } from 'react';
+import { ERG_DECIMALS, UI_FEE } from '../../../common/constants/erg';
+import { useObservable } from '../../../common/hooks/useObservable';
import { TokenControlFormItem } from '../../../components/common/TokenControl/TokenControl';
import { InfoTooltip } from '../../../components/InfoTooltip/InfoTooltip';
-import { ERG_DECIMALS, UI_FEE } from '../../../constants/erg';
-import { defaultExFee } from '../../../constants/settings';
import { useSettings } from '../../../context';
import { Box, Button, Flex, Modal, Typography } from '../../../ergodex-cdk';
import { Form, useForm } from '../../../ergodex-cdk/components/Form/NewForm';
-import { useObservable } from '../../../hooks/useObservable';
import { explorer } from '../../../services/explorer';
-import {
- useMaxTotalFees,
- useMinExFee,
- utxos$,
-} from '../../../services/new/core';
+import { useMinExFee, utxos$ } from '../../../services/new/core';
import { poolActions } from '../../../services/poolActions';
import { submitTx } from '../../../services/yoroi';
import { makeTarget } from '../../../utils/ammMath';
diff --git a/src/pages/Swap/SwapTooltip/SwapTooltip.tsx b/src/pages/Swap/SwapTooltip/SwapTooltip.tsx
index 252c87c9b..336251307 100644
--- a/src/pages/Swap/SwapTooltip/SwapTooltip.tsx
+++ b/src/pages/Swap/SwapTooltip/SwapTooltip.tsx
@@ -2,24 +2,21 @@
import { swapVars } from '@ergolabs/ergo-dex-sdk/build/main/amm/math/swap';
import React, { FC } from 'react';
+import { useObservable } from '../../../common/hooks/useObservable';
import { InfoTooltip } from '../../../components/InfoTooltip/InfoTooltip';
-import { ERG_DECIMALS, MIN_EX_FEE } from '../../../constants/erg';
-import { defaultExFee } from '../../../constants/settings';
import { useSettings } from '../../../context';
import { Flex } from '../../../ergodex-cdk';
import { FormGroup } from '../../../ergodex-cdk/components/Form/NewForm';
-import { useObservable } from '../../../hooks/useObservable';
import { useMaxTotalFees, useMinExFee } from '../../../services/new/core';
import { renderFractions } from '../../../utils/math';
-import { calculateTotalFee } from '../../../utils/transactions';
import { getBaseInputParameters } from '../../../utils/walletMath';
import { SwapFormModel } from '../SwapFormModel';
const TxInfoTooltipContent: FC<{ value: SwapFormModel }> = ({ value }) => {
- const [{ slippage, minerFee, nitro }] = useSettings();
+ const [{ slippage, nitro }] = useSettings();
const totalFees = useMaxTotalFees();
const minExFee = useMinExFee();
- console.log(totalFees, minExFee, minerFee);
+
const swapExtremums =
value.fromAmount?.isPositive() && value.toAmount?.isPositive() && value.pool
? swapVars(
@@ -72,10 +69,11 @@ export const SwapTooltip = ({
}: {
form: FormGroup;
}): JSX.Element => {
- const [value] = useObservable(form.valueChangesWithSilent$, {
- deps: [form],
- defaultValue: form.value,
- });
+ const [value] = useObservable(
+ form.valueChangesWithSilent$,
+ [form],
+ form.value,
+ );
return value.pool &&
value.toAsset &&
diff --git a/src/services/explorer.ts b/src/services/explorer.ts
index e3c4d9549..a56c58da9 100644
--- a/src/services/explorer.ts
+++ b/src/services/explorer.ts
@@ -1,6 +1,6 @@
import { Explorer } from '@ergolabs/ergo-sdk';
-import { ERGO_BASE_URL } from '../constants/env';
+import { ERGO_BASE_URL } from '../common/constants/env';
const explorer = new Explorer(ERGO_BASE_URL);
diff --git a/src/services/new/assets.ts b/src/services/new/assets.ts
index 672178aee..a14d57e25 100644
--- a/src/services/new/assets.ts
+++ b/src/services/new/assets.ts
@@ -11,6 +11,13 @@ export const assets$ = pools$.pipe(
refCount(),
);
+export const lpAssets$ = pools$.pipe(
+ map((pools) => pools.map((p) => p.lp.asset)),
+ map((assets) => uniqBy(assets, 'id')),
+ publishReplay(1),
+ refCount(),
+);
+
export const getAssetById = (id: string): Observable =>
assets$.pipe(map((assets) => find(assets, ['id', id])!));
diff --git a/src/services/new/balance.ts b/src/services/new/balance.ts
index 64ffd26ac..d83568223 100644
--- a/src/services/new/balance.ts
+++ b/src/services/new/balance.ts
@@ -9,12 +9,12 @@ import {
switchMap,
} from 'rxjs';
+import { ERG_DECIMALS } from '../../common/constants/erg';
+import { useObservable } from '../../common/hooks/useObservable';
import { Currency } from '../../common/models/Currency';
-import { ERG_DECIMALS } from '../../constants/erg';
-import { useObservable } from '../../hooks/useObservable';
import { getListAvailableTokens } from '../../utils/getListAvailableTokens';
import { parseUserInputToFractions } from '../../utils/math';
-import { assets$ } from './assets';
+import { assets$, lpAssets$ } from './assets';
import { nativeTokenBalance$, utxos$ } from './core';
const ERGO_ID =
@@ -45,7 +45,7 @@ export class Balance {
}
}
-export const walletBalance$ = combineLatest([
+export const assetWalletBalance$ = combineLatest([
nativeTokenBalance$.pipe(
map((balance) => parseUserInputToFractions(balance, ERG_DECIMALS)),
),
@@ -66,15 +66,36 @@ export const walletBalance$ = combineLatest([
publishReplay(1),
refCount(),
);
-walletBalance$.subscribe(() => {});
-export const useWalletBalance = () =>
- useObservable(walletBalance$, {
- defaultValue: new Balance([]),
- });
+export const lpWalletBalance$ = combineLatest([
+ utxos$.pipe(switchMap(() => lpAssets$)),
+ utxos$.pipe(map((utxos) => Object.values(getListAvailableTokens(utxos)))),
+]).pipe(
+ debounceTime(200),
+ map(([assets, boxAssets]) =>
+ boxAssets
+ .map<[bigint, AssetInfo]>((ba) => [
+ ba.amount,
+ assets.find((a) => a.id === ba.tokenId)!,
+ ])
+ .filter((i) => !!i[1]),
+ ),
+ map((data) => new Balance(data)),
+ publishReplay(1),
+ refCount(),
+);
+
+lpWalletBalance$.subscribe(() => {});
+assetWalletBalance$.subscribe(() => {});
+
+export const useAssetWalletBalance = (): [Balance, boolean, Error] =>
+ useObservable(assetWalletBalance$, [], new Balance([]));
+
+export const useLpWalletBalance = (): [Balance, boolean, Error] =>
+ useObservable(lpWalletBalance$, [], new Balance([]));
export const getBalanceByAsset = (asset: AssetInfo): Observable =>
- walletBalance$.pipe(
+ assetWalletBalance$.pipe(
map((balance) => balance.get(asset)),
publishReplay(1),
refCount(),
diff --git a/src/services/new/core.ts b/src/services/new/core.ts
index e3284d853..97d81a466 100644
--- a/src/services/new/core.ts
+++ b/src/services/new/core.ts
@@ -17,12 +17,12 @@ import {
switchMap,
} from 'rxjs';
+import { ERG_DECIMALS, ERG_TOKEN_NAME } from '../../common/constants/erg';
+import { defaultExFee } from '../../common/constants/settings';
+import { useObservable } from '../../common/hooks/useObservable';
import { Currency } from '../../common/models/Currency';
import { normalizeAmount } from '../../common/utils/amount';
-import { ERG_DECIMALS, ERG_TOKEN_NAME } from '../../constants/erg';
-import { defaultExFee } from '../../constants/settings';
import { useSettings } from '../../context';
-import { useObservable } from '../../hooks/useObservable';
import { walletCookies } from '../../utils/cookies';
import { renderFractions } from '../../utils/math';
import { calculateTotalFee } from '../../utils/transactions';
@@ -70,6 +70,13 @@ export const isWalletSetuped$ = walletState$.pipe(
refCount(),
);
+export const isWalletConnected$ = walletState$.pipe(
+ filter((state) => state === WalletState.CONNECTED),
+ mapTo(true),
+ publishReplay(1),
+ refCount(),
+);
+
export const appTick$ = walletState$.pipe(
filter((state) => state === WalletState.CONNECTED),
switchMap(() => interval(UPDATE_TIME).pipe(startWith(0))),
@@ -133,9 +140,7 @@ export const defaultExFee$: Observable = networkAsset$.pipe(
);
export const useNetworkAsset = (): AssetInfo => {
- const [_nativeToken] = useObservable(networkAsset$, {
- defaultValue: networkAsset,
- });
+ const [_nativeToken] = useObservable(networkAsset$, [], networkAsset);
return _nativeToken;
};
diff --git a/src/services/poolActions.ts b/src/services/poolActions.ts
index d175a7536..bbb9253d2 100644
--- a/src/services/poolActions.ts
+++ b/src/services/poolActions.ts
@@ -1,6 +1,6 @@
import { makeDefaultPoolActionsSelector } from '@ergolabs/ergo-dex-sdk';
-import { UiRewardAddress } from '../constants/settings';
+import { UiRewardAddress } from '../common/constants/settings';
import { mainnetTxAssembler } from './defaultTxAssembler';
import yoroiProver from './yoroi/prover';
diff --git a/src/utils/ammOperations.ts b/src/utils/ammOperations.ts
index 433dd1c9f..30b17e5bc 100644
--- a/src/utils/ammOperations.ts
+++ b/src/utils/ammOperations.ts
@@ -8,7 +8,7 @@ import {
TxId,
} from '@ergolabs/ergo-sdk';
-import { ERG_DECIMALS } from '../constants/erg';
+import { ERG_DECIMALS } from '../common/constants/erg';
import { ammOrderRefunds } from '../services/amm';
import { explorer } from '../services/explorer';
import { parseUserInputToFractions } from './math';
diff --git a/src/utils/debounce.ts b/src/utils/debounce.ts
deleted file mode 100644
index 39954d5af..000000000
--- a/src/utils/debounce.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-const noop = (...args: any[]) => {};
-
-export const debounce =
- void>(fn: F | undefined, time: number) =>
- (...args: Parameters) => {
- let timerId: any = undefined;
- return (...args: any[]) => {
- if (timerId) {
- clearTimeout(timerId);
- }
- timerId = setTimeout((fn || noop).bind(null, ...args), time);
- };
- };
diff --git a/src/utils/getListAvailableTokens.ts b/src/utils/getListAvailableTokens.ts
index 3bd3e1578..429a4de60 100644
--- a/src/utils/getListAvailableTokens.ts
+++ b/src/utils/getListAvailableTokens.ts
@@ -7,7 +7,7 @@ export type Asset = {
decimals?: number;
};
-export const isAsset = (value: any): value is Asset => !!value?.tokenId;
+// export const isAsset = (value: any): value is Asset => !!value?.tokenId;
export type AssetDictionary = Record;
diff --git a/src/utils/redirect.ts b/src/utils/redirect.ts
index ff6a8a11c..b95b08fe7 100644
--- a/src/utils/redirect.ts
+++ b/src/utils/redirect.ts
@@ -1,6 +1,6 @@
import { Address, TxId } from '@ergolabs/ergo-sdk';
-import { ERG_EXPLORER_URL } from '../constants/env';
+import { ERG_EXPLORER_URL } from '../common/constants/env';
export const exploreTx = (txId: TxId): unknown =>
window.open(`${ERG_EXPLORER_URL}/transactions/${txId}`, '_blank');
diff --git a/src/utils/wallets/yoroi.tsx b/src/utils/wallets/yoroi.tsx
index e400774e2..77c610d90 100644
--- a/src/utils/wallets/yoroi.tsx
+++ b/src/utils/wallets/yoroi.tsx
@@ -4,7 +4,7 @@ import {
DISCORD_SUPPORT_URL,
TELEGRAM_SUPPORT_URL,
YOROI_NIGHTLY_LINK,
-} from '../../constants/env';
+} from '../../common/constants/env';
import { WalletContextType } from '../../context';
import { Typography } from '../../ergodex-cdk';
import { walletCookies } from '../cookies';