diff --git a/apps/main/src/dex/components/PageCreatePool/Parameters/SelectPreset.tsx b/apps/main/src/dex/components/PageCreatePool/Parameters/SelectPreset.tsx index 12003694ae..b2260f69b9 100644 --- a/apps/main/src/dex/components/PageCreatePool/Parameters/SelectPreset.tsx +++ b/apps/main/src/dex/components/PageCreatePool/Parameters/SelectPreset.tsx @@ -2,7 +2,7 @@ import { Dispatch, SetStateAction, useEffect, useRef, useState } from 'react' import { styled } from 'styled-components' import SelectButton from '@/dex/components/PageCreatePool/components/SelectButton' import ModalDialog from '@/dex/components/PageCreatePool/ConfirmModal/ModalDialog' -import { CRYPTOSWAP, POOL_PRESETS, STABLESWAP } from '@/dex/components/PageCreatePool/constants' +import { CRYPTOSWAP, FXSWAP, POOL_PRESETS, STABLESWAP } from '@/dex/components/PageCreatePool/constants' import useStore from '@/dex/store/useStore' import type { UrlParams } from '@/dex/types/main.types' import { getPath } from '@/dex/utils/utilsRouter' @@ -184,22 +184,6 @@ const SelectPreset = ({ setStableFeeValue, setMidValue, setOutValue }: Props) => paddingSize={'small'} /> - - { - updatePoolPresetIndex(9) - setMidValue(t(POOL_PRESETS[9].defaultParams.midFee)) - setOutValue(t(POOL_PRESETS[9].defaultParams.outFee)) - overlayTriggerState.close() - }} - paddingSize={'small'} - disabled={true} // Coming soon! - /> - > )} {swapType === CRYPTOSWAP && tokenAmount === 3 && ( @@ -236,18 +220,49 @@ const SelectPreset = ({ setStableFeeValue, setMidValue, setOutValue }: Props) => > )} - - {t`Can't find the pool preset you want? Check out`} - {t`existing pools`} - {t`with similar assets for inspiration (or use`} - - curvesim - - {t`to sim).`} - + {swapType === FXSWAP && tokenAmount === 2 && ( + <> + + { + updatePoolPresetIndex(9) + setMidValue(t(POOL_PRESETS[9].defaultParams.midFee)) + setOutValue(t(POOL_PRESETS[9].defaultParams.outFee)) + overlayTriggerState.close() + }} + paddingSize={'small'} + /> + + > + )} + {swapType === FXSWAP ? ( + + {t`FXSwap pools are experimental and still evolving. Can't find the right preset?`} + + {t`Reach out to the team.`} + + + ) : ( + + {t`Can't find the pool preset you want? Check out`} + {t`existing pools`} + {t`with similar assets for inspiration (or use`} + + curvesim + + {t`to sim).`} + + )} )} diff --git a/apps/main/src/dex/components/PageCreatePool/PoolType/index.tsx b/apps/main/src/dex/components/PageCreatePool/PoolType/index.tsx index 6bb0084bab..60d635b743 100644 --- a/apps/main/src/dex/components/PageCreatePool/PoolType/index.tsx +++ b/apps/main/src/dex/components/PageCreatePool/PoolType/index.tsx @@ -1,6 +1,6 @@ import { styled } from 'styled-components' import SelectButton from '@/dex/components/PageCreatePool/components/SelectButton' -import { STABLESWAP, CRYPTOSWAP } from '@/dex/components/PageCreatePool/constants' +import { STABLESWAP, CRYPTOSWAP, FXSWAP } from '@/dex/components/PageCreatePool/constants' import { useNetworkByChain } from '@/dex/entities/networks' import useStore from '@/dex/store/useStore' import { ChainId } from '@/dex/types/main.types' @@ -15,7 +15,7 @@ const PoolType = ({ chainId }: Props) => { const swapType = useStore((state) => state.createPool.swapType) const updateSwapType = useStore((state) => state.createPool.updateSwapType) const { - data: { stableswapFactory, tricryptoFactory, twocryptoFactory }, + data: { stableswapFactory, tricryptoFactory, twocryptoFactory, fxswapFactory }, } = useNetworkByChain({ chainId }) return ( @@ -49,6 +49,16 @@ const PoolType = ({ chainId }: Props) => { {t`Cryptoswap pools are currently unavailable on this chain`} )} + + updateSwapType(FXSWAP, chainId)} + /> + > diff --git a/apps/main/src/dex/components/PageCreatePool/Summary/PoolTypeSummary.tsx b/apps/main/src/dex/components/PageCreatePool/Summary/PoolTypeSummary.tsx index 9a756f993f..3f43649dda 100644 --- a/apps/main/src/dex/components/PageCreatePool/Summary/PoolTypeSummary.tsx +++ b/apps/main/src/dex/components/PageCreatePool/Summary/PoolTypeSummary.tsx @@ -1,5 +1,5 @@ import { styled } from 'styled-components' -import { CRYPTOSWAP } from '@/dex/components/PageCreatePool/constants' +import { STABLESWAP } from '@/dex/components/PageCreatePool/constants' import { CategoryColumn, SummaryData, @@ -27,7 +27,7 @@ const PoolTypeSummary = () => { {t`No pool type selected`} ) : ( - {swapType === CRYPTOSWAP ? t`Cryptoswap` : t`Stableswap${metaPoolToken ? '-Meta' : ''}`} + {swapType === STABLESWAP ? t`${swapType}${metaPoolToken ? '-Meta' : ''}` : swapType} )} diff --git a/apps/main/src/dex/components/PageCreatePool/Summary/index.tsx b/apps/main/src/dex/components/PageCreatePool/Summary/index.tsx index 6a647e0271..de82705ca8 100644 --- a/apps/main/src/dex/components/PageCreatePool/Summary/index.tsx +++ b/apps/main/src/dex/components/PageCreatePool/Summary/index.tsx @@ -75,7 +75,7 @@ const TopBox = styled(Box)` const SummaryBox = styled(Box)` padding: var(--spacing-normal); - background: var(--box_header--secondary--background-color); + background: var(--box--primary--content--background-color); ` const BottomBox = styled(Box)` diff --git a/apps/main/src/dex/components/PageCreatePool/TokensInPool/index.tsx b/apps/main/src/dex/components/PageCreatePool/TokensInPool/index.tsx index 8d8f3f2747..54cbc6ce8f 100644 --- a/apps/main/src/dex/components/PageCreatePool/TokensInPool/index.tsx +++ b/apps/main/src/dex/components/PageCreatePool/TokensInPool/index.tsx @@ -14,6 +14,7 @@ import { TOKEN_F, TOKEN_G, TOKEN_H, + FXSWAP, } from '@/dex/components/PageCreatePool/constants' import SelectToken from '@/dex/components/PageCreatePool/TokensInPool/SelectToken' import SetOracle from '@/dex/components/PageCreatePool/TokensInPool/SetOracle' @@ -773,7 +774,7 @@ const TokensInPool = ({ curve, chainId, haveSigner }: Props) => { ) : ( - {t`Rebasing tokens are not supported in ${CRYPTOSWAP} pools`} + {t`Rebasing tokens are not supported in ${swapType} pools`} )} @@ -783,6 +784,7 @@ const TokensInPool = ({ curve, chainId, haveSigner }: Props) => { onClick={addToken} variant="filled" disabled={ + swapType === FXSWAP || (swapType === STABLESWAP && stableswapFactory && tokensInPool.tokenAmount === 8) || (swapType === STABLESWAP && !stableswapFactory && tokensInPool.tokenAmount === 4) || (swapType === STABLESWAP && tokensInPool.metaPoolToken) || diff --git a/apps/main/src/dex/components/PageCreatePool/constants.ts b/apps/main/src/dex/components/PageCreatePool/constants.ts index 87b8309ffa..7637435d36 100644 --- a/apps/main/src/dex/components/PageCreatePool/constants.ts +++ b/apps/main/src/dex/components/PageCreatePool/constants.ts @@ -3,6 +3,7 @@ import { t } from '@ui-kit/lib/i18n' export const CRYPTOSWAP = 'Cryptoswap' export const STABLESWAP = 'Stableswap' +export const FXSWAP = 'FXSwap' export const TOKEN_A = 'tokenA' export const TOKEN_B = 'tokenB' export const TOKEN_C = 'tokenC' @@ -185,10 +186,11 @@ export const POOL_PRESETS: PRESETS = { maHalfTime: '600', }, }, + // fxswap 9: { name: 'FXSwap', descriptionName: t`FXSwap`, - description: t`Suitable for FX swaps`, + description: t`Suitable for forex tokens with low volatility`, defaultParams: { ...fillerParams, midFee: '0.25', // 25/10_000 * 10**10 (25 bps) diff --git a/apps/main/src/dex/components/PageCreatePool/types.ts b/apps/main/src/dex/components/PageCreatePool/types.ts index 2b0b5e958e..b84d1ca521 100644 --- a/apps/main/src/dex/components/PageCreatePool/types.ts +++ b/apps/main/src/dex/components/PageCreatePool/types.ts @@ -1,6 +1,7 @@ import { CRYPTOSWAP, STABLESWAP, + FXSWAP, TOKEN_A, TOKEN_B, TOKEN_C, @@ -45,7 +46,7 @@ export type SelectTokenFormValues = { [TOKEN_H]: TokenState } -export type SwapType = typeof CRYPTOSWAP | typeof STABLESWAP | '' +export type SwapType = typeof CRYPTOSWAP | typeof STABLESWAP | typeof FXSWAP | '' export type NgAssetType = 0 | 1 | 2 | 3 export type TokenId = | typeof TOKEN_A diff --git a/apps/main/src/dex/components/PageCreatePool/utils.ts b/apps/main/src/dex/components/PageCreatePool/utils.ts index 01850280b2..9241917c4c 100644 --- a/apps/main/src/dex/components/PageCreatePool/utils.ts +++ b/apps/main/src/dex/components/PageCreatePool/utils.ts @@ -1,5 +1,5 @@ import { isAddress } from 'viem' -import { STABLESWAP, CRYPTOSWAP } from '@/dex/components/PageCreatePool/constants' +import { STABLESWAP, CRYPTOSWAP, FXSWAP } from '@/dex/components/PageCreatePool/constants' import type { SwapType, TokenState } from '@/dex/components/PageCreatePool/types' import { BasePool } from '@/dex/types/main.types' export const checkSwapType = (swapType: SwapType) => swapType !== '' @@ -66,7 +66,7 @@ export const checkParameters = ( ) => { if (poolPresetIndex === null) return false if (swapType === STABLESWAP) return stableSwapFee !== null - if (swapType === CRYPTOSWAP) { + if (swapType === CRYPTOSWAP || swapType === FXSWAP) { if (isTricrypto(tricryptoEnabled, tokenAmount, tokenA, tokenB, tokenC)) return midFee !== null && initialPrice[0] !== '0' && initialPrice[1] !== '0' return midFee !== null && initialPrice[0] !== '0' diff --git a/apps/main/src/dex/constants.ts b/apps/main/src/dex/constants.ts index 653e149b8d..8832dd7f0d 100644 --- a/apps/main/src/dex/constants.ts +++ b/apps/main/src/dex/constants.ts @@ -45,6 +45,7 @@ export const DEFAULT_NETWORK_CONFIG = { twocryptoFactoryOld: false, // determines support in pool creation and gauge deployment twocryptoFactory: false, // determines support in pool creation and gauge deployment tricryptoFactory: false, // determines support in pool creation and gauge deployment + fxswapFactory: false, // determines support in pool creation and gauge deployment hasFactory: false, pricesApi: false, } diff --git a/apps/main/src/dex/lib/networks.ts b/apps/main/src/dex/lib/networks.ts index 4d14af2a0a..2aaac74a24 100644 --- a/apps/main/src/dex/lib/networks.ts +++ b/apps/main/src/dex/lib/networks.ts @@ -67,6 +67,7 @@ export const defaultNetworks = Object.entries({ twocryptoFactoryOld: true, twocryptoFactory: true, tricryptoFactory: true, + fxswapFactory: true, hasFactory: true, pricesApi: true, }, @@ -262,6 +263,7 @@ export const defaultNetworks = Object.entries({ twocryptoFactoryOld: true, twocryptoFactory: true, tricryptoFactory: true, + fxswapFactory: true, hasFactory: true, pricesApi: true, }, @@ -283,6 +285,7 @@ export const defaultNetworks = Object.entries({ twocryptoFactoryOld: true, twocryptoFactory: true, tricryptoFactory: true, + fxswapFactory: true, hasFactory: true, pricesApi: true, }, @@ -375,6 +378,7 @@ export async function getNetworks() { stableswapFactory: true, twocryptoFactory: true, tricryptoFactory: true, + fxswapFactory: false, pricesApi: isUpgraded, isLite: !isUpgraded, isCrvRewardsEnabled: isUpgraded, diff --git a/apps/main/src/dex/store/createCreatePoolSlice.ts b/apps/main/src/dex/store/createCreatePoolSlice.ts index 31c1545279..d182cf8f09 100644 --- a/apps/main/src/dex/store/createCreatePoolSlice.ts +++ b/apps/main/src/dex/store/createCreatePoolSlice.ts @@ -7,6 +7,7 @@ import { CRYPTOSWAP, POOL_PRESETS, STABLESWAP, + FXSWAP, TOKEN_A, TOKEN_B, TOKEN_C, @@ -20,6 +21,7 @@ import { CreateToken, NgAssetType, SwapType, TokenId, TokenState } from '@/dex/c import { isTricrypto } from '@/dex/components/PageCreatePool/utils' import type { State } from '@/dex/store/useStore' import { ChainId, CurveApi } from '@/dex/types/main.types' +import { TwoCryptoImplementation } from '@curvefi/api/lib/constants/twoCryptoImplementations' import { scanTxPath } from '@ui/utils' import { notify } from '@ui-kit/features/connect-wallet' import { t } from '@ui-kit/lib/i18n' @@ -786,7 +788,87 @@ const createCreatePoolSlice = ( ) const networks = await fetchNetworks() - if (swapType === CRYPTOSWAP) { + if (swapType === FXSWAP) { + // ----- FXSWAP ----- + const coins = [tokenA.address, tokenB.address] + + try { + const maExpTime = Math.round(+maHalfTime / 0.693) + + const deployPoolTx = await curve.twocryptoFactory.deployPool( + poolName, + poolSymbol, + coins, + cryptoA, + gamma, + midFee, + outFee, + allowedExtraProfit, + feeGamma, + adjustmentStep, + maExpTime, + initialPrice.initialPrice[0], + TwoCryptoImplementation.FX_REGULAR_50_PERCENT, + ) + + set( + produce((state) => { + state.createPool.transactionState.txStatus = 'LOADING' + state.createPool.transactionState.transaction = deployPoolTx + state.createPool.transactionState.txLink = scanTxPath(networks[chainId], deployPoolTx.hash) + }), + ) + + // set up deploying message + dismissConfirm() + const deployingNotificationMessage = t`Deploying pool ${poolName}...` + const { dismiss: dismissDeploying } = notify(deployingNotificationMessage, 'pending') + dismissNotificationHandler = dismissDeploying + + const poolAddress = await curve.twocryptoFactory.getDeployedPoolAddress(deployPoolTx) + // deploy pool tx success + set( + produce((state) => { + state.createPool.transactionState.txStatus = 'SUCCESS' + state.createPool.transactionState.txSuccess = true + state.createPool.transactionState.fetchPoolStatus = 'LOADING' + state.createPool.transactionState.poolAddress = poolAddress + }), + ) + + // set up success message + dismissDeploying() + const successNotificationMessage = t`Pool ${poolName} deployment successful.` + notify(successNotificationMessage, 'success', 15000) + + const poolId = await curve.twocryptoFactory.fetchRecentlyDeployedPool(poolAddress) + set( + produce((state) => { + state.createPool.transactionState.poolId = poolId + }), + ) + + const poolData = await fetchNewPool(curve, poolId) + if (poolData) { + set( + produce((state) => { + state.createPool.transactionState.fetchPoolStatus = 'SUCCESS' + state.createPool.transactionState.lpTokenAddress = poolData.pool.lpToken + }), + ) + } + } catch (error) { + if (typeof dismissNotificationHandler === 'function') { + dismissNotificationHandler() + } + set( + produce((state) => { + state.createPool.transactionState.txStatus = 'ERROR' + state.createPool.transactionState.errorMessage = error.message + }), + ) + } + } else if (swapType === CRYPTOSWAP) { // ----- TRICRYPTO ----- if (isTricrypto(networks[chainId].tricryptoFactory, tokenAmount, tokenA, tokenB, tokenC)) { const coins = [tokenA.address, tokenB.address, tokenC.address] diff --git a/apps/main/src/dex/types/main.types.ts b/apps/main/src/dex/types/main.types.ts index d088a0ebf5..d0b70ff8cd 100644 --- a/apps/main/src/dex/types/main.types.ts +++ b/apps/main/src/dex/types/main.types.ts @@ -52,6 +52,7 @@ export interface NetworkConfig extends BaseConfig { twocryptoFactoryOld: boolean twocryptoFactory: boolean tricryptoFactory: boolean + fxswapFactory: boolean hasFactory: boolean pricesApi: boolean }
{t`Rebasing tokens are not supported in ${CRYPTOSWAP} pools`}
{t`Rebasing tokens are not supported in ${swapType} pools`}