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 ( -
+