diff --git a/src/components/NewPosition/PoolInit/PoolInit.tsx b/src/components/NewPosition/PoolInit/PoolInit.tsx index 4fedccaf..bbc39973 100644 --- a/src/components/NewPosition/PoolInit/PoolInit.tsx +++ b/src/components/NewPosition/PoolInit/PoolInit.tsx @@ -407,7 +407,7 @@ export const PoolInit: React.FC = ({ /> ) : ( - + diff --git a/src/components/NewPosition/PoolInit/style.ts b/src/components/NewPosition/PoolInit/style.ts index 514ba843..b89d4550 100644 --- a/src/components/NewPosition/PoolInit/style.ts +++ b/src/components/NewPosition/PoolInit/style.ts @@ -77,8 +77,9 @@ const useStyles = makeStyles()(theme => { } }, buttons: { - marginTop: 38, + marginTop: 4, width: '100%', + height: 70, flexDirection: 'row', gap: 16, alignItems: 'center' diff --git a/src/components/Swap/ExchangeRate/ExchangeRate.tsx b/src/components/Swap/ExchangeRate/ExchangeRate.tsx index 2a9cb7ae..3de7e86c 100644 --- a/src/components/Swap/ExchangeRate/ExchangeRate.tsx +++ b/src/components/Swap/ExchangeRate/ExchangeRate.tsx @@ -29,7 +29,12 @@ const ExchangeRate: React.FC = ({ ) : ( - 1 {tokenFromSymbol} = {isNaN(amount) ? 0 : formatNumber(amount.toFixed(tokenToDecimals))}{' '} + 1 {tokenFromSymbol} ={' '} + {isNaN(amount) + ? 0 + : formatNumber(amount.toFixed(tokenToDecimals)) === '0' + ? '~0' + : formatNumber(amount.toFixed(tokenToDecimals))}{' '} {tokenToSymbol} ) diff --git a/src/components/Swap/TransactionDetailsBox/TransactionDetailsBox.tsx b/src/components/Swap/TransactionDetailsBox/TransactionDetailsBox.tsx index 79be311b..1b59cdde 100644 --- a/src/components/Swap/TransactionDetailsBox/TransactionDetailsBox.tsx +++ b/src/components/Swap/TransactionDetailsBox/TransactionDetailsBox.tsx @@ -39,7 +39,7 @@ const TransactionDetailsBox: React.FC = ({ {exchangeRate.val === Infinity ? '-' - : `${formatNumber(exchangeRate.val.toFixed(exchangeRate.decimal))} ${exchangeRate.symbol}`} + : `${formatNumber(exchangeRate.val.toFixed(exchangeRate.decimal)) === '0' ? '~0' : formatNumber(exchangeRate.val.toFixed(exchangeRate.decimal))} ${exchangeRate.symbol}`} )} diff --git a/src/containers/NewPositionWrapper/NewPositionWrapper.tsx b/src/containers/NewPositionWrapper/NewPositionWrapper.tsx index 46c803be..83286c86 100644 --- a/src/containers/NewPositionWrapper/NewPositionWrapper.tsx +++ b/src/containers/NewPositionWrapper/NewPositionWrapper.tsx @@ -255,14 +255,24 @@ export const NewPositionWrapper: React.FC = ({ }, [isWaitingForNewPool, tokenA, tokenB, feeIndex, poolKey, allPoolKeys, allPools.length]) useEffect(() => { - if (poolKey !== '') { - dispatch( - positionsActions.getCurrentPlotTicks({ - poolKey: allPoolKeys[poolKey], - isXtoY, - fetchTicksAndTickmap: true - }) - ) + if (poolKey !== '' && !isWaitingForNewPool) { + const isCurrentTokenX = isXtoY + ? allPoolKeys[poolKey].tokenX === tokenA + : allPoolKeys[poolKey].tokenX === tokenB + + const isCurrentTokenY = isXtoY + ? allPoolKeys[poolKey].tokenY === tokenB + : allPoolKeys[poolKey].tokenY === tokenA + + if (isCurrentTokenX && isCurrentTokenY) { + dispatch( + positionsActions.getCurrentPlotTicks({ + poolKey: allPoolKeys[poolKey], + isXtoY, + fetchTicksAndTickmap: true + }) + ) + } } }, [isWaitingForNewPool, tokenA, tokenB, poolKey, allPoolKeys]) diff --git a/src/containers/SinglePositionWrapper/SinglePositionWrapper.tsx b/src/containers/SinglePositionWrapper/SinglePositionWrapper.tsx index 146dcd54..f98161ed 100644 --- a/src/containers/SinglePositionWrapper/SinglePositionWrapper.tsx +++ b/src/containers/SinglePositionWrapper/SinglePositionWrapper.tsx @@ -272,7 +272,7 @@ export const SinglePositionWrapper: React.FC = ({ id }) => { } useEffect(() => { - dispatch(actions.getRemainingPositions()) + dispatch(actions.getRemainingPositions({ setLoaded: false })) const timer = setTimeout(() => { setIsFinishedDelayRender(true) }, 1000) diff --git a/src/containers/WrappedPositionsList/WrappedPositionsList.tsx b/src/containers/WrappedPositionsList/WrappedPositionsList.tsx index 96d7fff7..de44689a 100644 --- a/src/containers/WrappedPositionsList/WrappedPositionsList.tsx +++ b/src/containers/WrappedPositionsList/WrappedPositionsList.tsx @@ -187,7 +187,7 @@ export const WrappedPositionsList: React.FC = () => { length={length} loadedPages={loadedPages} getRemainingPositions={() => { - dispatch(actions.getRemainingPositions()) + dispatch(actions.getRemainingPositions({ setLoaded: true })) }} noInitialPositions={list.length === 0} /> diff --git a/src/hideErrors.ts b/src/hideErrors.ts index 74eae44f..1ad3e612 100644 --- a/src/hideErrors.ts +++ b/src/hideErrors.ts @@ -6,6 +6,8 @@ export const messagesToHide: string[] = [ ' attribute d: Expected moveto path command' ] +if (process.env.NODE_ENV === 'production') console.log = () => {} + export function filterConsoleMessages(hideMessages: string[]): void { if (typeof window === 'undefined') { return diff --git a/src/store/reducers/pools.ts b/src/store/reducers/pools.ts index b0333bfc..8b3addc8 100644 --- a/src/store/reducers/pools.ts +++ b/src/store/reducers/pools.ts @@ -77,6 +77,7 @@ export interface FetchTicksAndTickMaps { tokenFrom: string tokenTo: string allPools: PoolWithPoolKey[] + poolKey?: PoolKey } const network = diff --git a/src/store/reducers/positions.ts b/src/store/reducers/positions.ts index 124ceb09..e215aa2e 100644 --- a/src/store/reducers/positions.ts +++ b/src/store/reducers/positions.ts @@ -161,7 +161,7 @@ const positionsSlice = createSlice({ state.positionsList.loading = true return state }, - getRemainingPositions(state, _action: PayloadAction) { + getRemainingPositions(state, _action: PayloadAction<{ setLoaded: boolean }>) { state.positionsList.loading = true return state }, diff --git a/src/store/sagas/pools.ts b/src/store/sagas/pools.ts index c6533b54..5642101e 100644 --- a/src/store/sagas/pools.ts +++ b/src/store/sagas/pools.ts @@ -1,11 +1,11 @@ import { PoolKey, newPoolKey } from '@invariant-labs/a0-sdk' import { PayloadAction } from '@reduxjs/toolkit' -import { findPairs, getTokenBalances, getTokenDataByAddresses } from '@utils/utils' +import { findPairs, getTokenBalances, getTokenDataByAddresses, poolKeyToString } from '@utils/utils' import { FetchTicksAndTickMaps, PairTokens, PoolWithPoolKey, actions } from '@store/reducers/pools' import { actions as walletActions } from '@store/reducers/wallet' -import { tokens } from '@store/selectors/pools' +import { poolsArraySortedByFees, tokens } from '@store/selectors/pools' import { address } from '@store/selectors/wallet' -import { all, call, put, select, spawn, takeEvery, takeLatest } from 'typed-redux-saga' +import { all, call, put, select, spawn, take, takeEvery, takeLatest } from 'typed-redux-saga' import { MAX_POOL_KEYS_RETURNED } from '@invariant-labs/a0-sdk/target/consts' import { getInvariant, getPSP22 } from './connection' @@ -77,11 +77,22 @@ export function* fetchAllPoolsForPairData(action: PayloadAction) { } export function* fetchTicksAndTickMaps(action: PayloadAction) { - const { tokenFrom, tokenTo, allPools } = action.payload + const { tokenFrom, tokenTo, poolKey } = action.payload + let poolsData = yield* select(poolsArraySortedByFees) + + if (poolKey) { + let pools = poolsData.filter(pool => poolKeyToString(pool.poolKey) === poolKeyToString(poolKey)) + + if (pools.length === 0) { + yield* take(actions.addPool) + + poolsData = yield* select(poolsArraySortedByFees) + } + } try { const invariant = yield* getInvariant() - const pools = findPairs(tokenFrom.toString(), tokenTo.toString(), allPools) + const pools = findPairs(tokenFrom.toString(), tokenTo.toString(), poolsData) const tickmapCalls = pools.map(pool => call([invariant, invariant.getFullTickmap], pool.poolKey) diff --git a/src/store/sagas/positions.ts b/src/store/sagas/positions.ts index a7013d0c..9d047336 100644 --- a/src/store/sagas/positions.ts +++ b/src/store/sagas/positions.ts @@ -9,6 +9,7 @@ import { INVARIANT_CREATE_POSITION_OPTIONS, INVARIANT_REMOVE_POSITION_OPTIONS, INVARIANT_WITHDRAW_ALL_WAZERO, + POOL_SAFE_TRANSACTION_FEE, POSITIONS_PER_QUERY, PSP22_APPROVE_OPTIONS, U128MAX, @@ -122,8 +123,13 @@ function* handleInitPosition(action: PayloadAction): Generator (tokenY === wazeroAddress && tokenYAmount !== 0n) ) { const isTokenX = tokenX === wazeroAddress + const azeroInputAmount = isTokenX ? tokenXAmount : tokenYAmount + const slippageAmount = isTokenX ? xAmountWithSlippage : yAmountWithSlippage - const azeroAmount = azeroBalance > slippageAmount ? slippageAmount : azeroBalance + const azeroAmount = + azeroBalance - POOL_SAFE_TRANSACTION_FEE > slippageAmount + ? slippageAmount + : azeroInputAmount const depositTx = wazero.depositTx(azeroAmount, WAZERO_DEPOSIT_OPTIONS) txs.push(depositTx) @@ -275,7 +281,8 @@ export function* handleGetCurrentPlotTicks(action: PayloadAction) { } } -export function* handleGetRemainingPositions(): Generator { +export function* handleGetRemainingPositions( + action: PayloadAction<{ setLoaded: boolean }> +): Generator { const walletAddress = yield* select(address) const { length, list, loadedPages } = yield* select(positionsList) @@ -641,7 +651,7 @@ export function* handleGetRemainingPositions(): Generator { yield* put( actions.setPositionsListLoadedStatus({ indexes: pages.map(({ index }: { index: number }) => index), - isLoaded: true + isLoaded: action.payload.setLoaded }) ) } catch (error) { diff --git a/src/store/sagas/swap.ts b/src/store/sagas/swap.ts index c00fab77..1675fa7a 100644 --- a/src/store/sagas/swap.ts +++ b/src/store/sagas/swap.ts @@ -15,6 +15,7 @@ import { ErrorMessage, INVARIANT_SWAP_OPTIONS, PSP22_APPROVE_OPTIONS, + SWAP_SAFE_TRANSACTION_FEE, U128MAX, WAZERO_DEPOSIT_OPTIONS, WAZERO_WITHDRAW_OPTIONS @@ -98,7 +99,10 @@ export function* handleSwap(action: PayloadAction>): Generato if ((xToY && poolKey.tokenX === wazeroAddress) || (!xToY && poolKey.tokenY === wazeroAddress)) { const azeroBalance = yield* select(balance) const azeroAmountInWithSlippage = - azeroBalance > calculatedAmountIn ? calculatedAmountIn : azeroBalance + azeroBalance - SWAP_SAFE_TRANSACTION_FEE > calculatedAmountIn + ? calculatedAmountIn + : amountIn + const depositTx = wazero.depositTx(azeroAmountInWithSlippage, WAZERO_DEPOSIT_OPTIONS) txs.push(depositTx) } @@ -282,7 +286,6 @@ export function* handleGetSimulateResult(action: PayloadAction) { let fee = 0n let swapPossible = false - let insufficientLiquidityPoolKey = null const errors = [] @@ -300,7 +303,7 @@ export function* handleGetSimulateResult(action: PayloadAction) { byAmountIn, xToY ? MIN_SQRT_PRICE : MAX_SQRT_PRICE ) - + console.log(result) if (result.maxSwapStepsReached || result.globalInsufficientLiquidity) { if ( byAmountIn @@ -309,7 +312,7 @@ export function* handleGetSimulateResult(action: PayloadAction) { ) { insufficientLiquidityAmountOut = byAmountIn ? result.amountOut : result.amountIn fee = pool.poolKey.feeTier.fee - insufficientLiquidityPoolKey = pool.poolKey + priceImpact = 1 errors.push(SwapError.MaxSwapStepsReached) } @@ -346,7 +349,7 @@ export function* handleGetSimulateResult(action: PayloadAction) { yield put( actions.setSimulateResult({ - poolKey: swapPossible ? poolKey : insufficientLiquidityPoolKey, + poolKey: swapPossible ? poolKey : null, amountOut: validatedAmountOut, priceImpact, targetSqrtPrice,