From 9683f77071b3ccf4c27f590dc174c1b523b82839 Mon Sep 17 00:00:00 2001 From: midas-myth Date: Thu, 11 Dec 2025 15:20:36 +0100 Subject: [PATCH 01/23] Refactor technical fees handling in GmSwapBox components to utilize a unified TechnicalGmFees type. Update fee estimation logic for deposits and withdrawals, enhancing clarity and maintainability. Introduce buildDepositTransferRequests and buildWithdrawalTransferRequests functions for improved transfer request management. --- .../lpTxn/useDepositTransactions.tsx | 127 +++-- .../lpTxn/useLpTransactions.tsx | 14 +- .../useMultichainDepositExpressTxnParams.tsx | 11 +- ...seMultichainWithdrawalExpressTxnParams.tsx | 10 +- .../lpTxn/useWithdrawalTransactions.tsx | 96 ++-- .../useDepositWithdrawalFees.tsx | 36 +- .../useGmSwapSubmitState.tsx | 24 +- .../useTechnicalFeesAsyncResult.tsx | 482 ++++++++++++++++-- .../buildDepositTransferRequests.tsx | 88 ++++ .../buildWithdrawalTransferRequests.tsx | 51 ++ src/domain/multichain/technical-fees-types.ts | 45 ++ .../synthetics/express/relayParamsUtils.ts | 3 - .../markets/createMultichainDepositTxn.ts | 16 +- .../markets/createMultichainGlvDepositTxn.ts | 16 +- .../createMultichainGlvWithdrawalTxn.ts | 16 +- .../markets/createMultichainWithdrawalTxn.ts | 16 +- 16 files changed, 801 insertions(+), 250 deletions(-) create mode 100644 src/domain/multichain/buildDepositTransferRequests.tsx create mode 100644 src/domain/multichain/buildWithdrawalTransferRequests.tsx create mode 100644 src/domain/multichain/technical-fees-types.ts diff --git a/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx b/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx index ae172ab54a..f4dd175bbf 100644 --- a/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx +++ b/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx @@ -3,7 +3,6 @@ import { useCallback, useMemo } from "react"; import { zeroAddress } from "viem"; import type { SettlementChainId } from "config/chains"; -import { DEFAULT_SLIPPAGE_AMOUNT } from "config/factors"; import { usePendingTxns } from "context/PendingTxnsContext/PendingTxnsContext"; import { selectPoolsDetailsFirstTokenAddress, @@ -36,8 +35,9 @@ import { TokensBalancesUpdates, useTokensBalancesUpdates, } from "context/TokensBalancesContext/TokensBalancesContextProvider"; -import { getTransferRequests } from "domain/multichain/getTransferRequests"; +import { buildDepositTransferRequests } from "domain/multichain/buildDepositTransferRequests"; import { GlvBuyTask, GmBuyTask } from "domain/multichain/progress/GmOrGlvBuyProgress"; +import type { TechnicalGmFees } from "domain/multichain/technical-fees-types"; import { toastCustomOrStargateError } from "domain/multichain/toastCustomOrStargateError"; import { TransferRequests } from "domain/multichain/types"; import { @@ -52,8 +52,6 @@ import { createMultichainDepositTxn } from "domain/synthetics/markets/createMult import { createMultichainGlvDepositTxn } from "domain/synthetics/markets/createMultichainGlvDepositTxn"; import { createSourceChainDepositTxn } from "domain/synthetics/markets/createSourceChainDepositTxn"; import { createSourceChainGlvDepositTxn } from "domain/synthetics/markets/createSourceChainGlvDepositTxn"; -import { SourceChainDepositFees } from "domain/synthetics/markets/feeEstimation/estimateSourceChainDepositFees"; -import { SourceChainGlvDepositFees } from "domain/synthetics/markets/feeEstimation/estimateSourceChainGlvDepositFees"; import { ERC20Address, NativeTokenSupportedAddress, TokenBalanceType } from "domain/tokens"; import { helperToast } from "lib/helperToast"; import { @@ -66,13 +64,9 @@ import { } from "lib/metrics"; import { makeUserAnalyticsOrderFailResultHandler, sendUserAnalyticsOrderConfirmClickEvent } from "lib/userAnalytics"; import useWallet from "lib/wallets/useWallet"; -import { getContract } from "sdk/configs/contracts"; import { convertTokenAddress, getWrappedToken } from "sdk/configs/tokens"; -import { ExecutionFee } from "sdk/types/fees"; import { getGlvToken, getGmToken } from "sdk/utils/tokens"; -import { applySlippageToMinOut } from "sdk/utils/trade"; -import type { TechnicalFees } from "../useTechnicalFeesAsyncResult"; import type { UseLpTransactionProps } from "./useLpTransactions"; import { useMultichainDepositExpressTxnParams } from "./useMultichainDepositExpressTxnParams"; @@ -130,16 +124,24 @@ export const useDepositTransactions = ({ return undefined; } - const executionFee = - paySource === "sourceChain" - ? (technicalFees as SourceChainDepositFees | SourceChainGlvDepositFees).executionFee - : (technicalFees as ExecutionFee).feeTokenAmount; + let executionFee: bigint | undefined; + if (technicalFees.kind === "sourceChain" && technicalFees.isDeposit) { + executionFee = technicalFees.fees.executionFee; + } else if (technicalFees.kind === "gmxAccount") { + executionFee = technicalFees.fees.executionFee.feeTokenAmount; + } else if (technicalFees.kind === "settlementChain") { + executionFee = technicalFees.fees.feeTokenAmount; + } + + if (executionFee === undefined) { + return undefined; + } return { ...(rawParams as RawCreateDepositParams), executionFee, }; - }, [rawParams, technicalFees, isDeposit, paySource]); + }, [rawParams, technicalFees, isDeposit]); const gasPaymentTokenAddress = useSelector(selectGasPaymentTokenAddress); const gasPaymentTokenAsCollateralAmount = useMemo((): bigint | undefined => { @@ -254,6 +256,11 @@ export const useDepositTransactions = ({ tokenAddress = convertTokenAddress(chainId, tokenAddress, "native"); const tokenAmount = longTokenAmount! > 0n ? longTokenAmount! : shortTokenAmount!; + const fees = technicalFees.kind === "sourceChain" && technicalFees.isDeposit ? technicalFees.fees : undefined; + if (!fees) { + throw new Error("Technical fees are not set"); + } + promise = createSourceChainDepositTxn({ chainId: chainId as SettlementChainId, srcChainId: srcChainId!, @@ -262,7 +269,7 @@ export const useDepositTransactions = ({ params: rawParams as RawCreateDepositParams, tokenAddress, tokenAmount, - fees: technicalFees as SourceChainDepositFees, + fees, }) .then((res) => { if (res.transactionHash) { @@ -273,7 +280,7 @@ export const useDepositTransactions = ({ token: getGmToken(chainId, (rawParams as RawCreateDepositParams).addresses.market), amount: marketTokenAmount!, settlementChainId: chainId, - estimatedFeeUsd: (technicalFees as SourceChainDepositFees).relayFeeUsd, + estimatedFeeUsd: fees.relayFeeUsd, }) ); } @@ -283,6 +290,7 @@ export const useDepositTransactions = ({ }); } else if (paySource === "gmxAccount") { const expressTxnParams = multichainDepositExpressTxnParams.data; + if (!expressTxnParams) { throw new Error("Express txn params are not set"); } @@ -325,14 +333,19 @@ export const useDepositTransactions = ({ } }); } else if (paySource === "settlementChain") { + const fees = technicalFees?.kind === "settlementChain" ? technicalFees.fees : undefined; + if (!fees) { + throw new Error("Technical fees are not set"); + } + promise = createDepositTxn({ chainId, signer, blockTimestampData, longTokenAmount: longTokenAmount ?? 0n, shortTokenAmount: shortTokenAmount ?? 0n, - executionFee: (technicalFees as ExecutionFee).feeTokenAmount, - executionGasLimit: (technicalFees as ExecutionFee).gasLimit, + executionFee: fees.feeTokenAmount, + executionGasLimit: fees.gasLimit, skipSimulation: shouldDisableValidation, tokensData, metricId: metricData.metricId, @@ -405,6 +418,11 @@ export const useDepositTransactions = ({ throw new Error("Technical fees are not set"); } + const fees = technicalFees.kind === "sourceChain" && technicalFees.isDeposit ? technicalFees.fees : undefined; + if (!fees) { + throw new Error("Technical fees are not set"); + } + if (!longTokenAddress || !shortTokenAddress) { throw new Error("Long or short token address is not set"); } @@ -432,7 +450,7 @@ export const useDepositTransactions = ({ params: rawParams as RawCreateGlvDepositParams, tokenAddress, tokenAmount, - fees: technicalFees as SourceChainGlvDepositFees, + fees, }) .then((res) => { if (res.transactionHash) { @@ -443,7 +461,7 @@ export const useDepositTransactions = ({ token: getGlvToken(chainId, (rawParams as RawCreateGlvDepositParams).addresses.glv), amount: glvTokenAmount!, settlementChainId: chainId, - estimatedFeeUsd: (technicalFees as SourceChainGlvDepositFees).relayFeeUsd, + estimatedFeeUsd: fees.relayFeeUsd, }) ); } @@ -511,6 +529,11 @@ export const useDepositTransactions = ({ ? zeroAddress : shortTokenAddress; + const fees = technicalFees?.kind === "settlementChain" ? technicalFees.fees : undefined; + if (!fees) { + throw new Error("Technical fees are not set"); + } + promise = createGlvDepositTxn({ chainId, signer, @@ -520,8 +543,8 @@ export const useDepositTransactions = ({ longTokenAmount: longTokenAmount ?? 0n, shortTokenAmount: shortTokenAmount ?? 0n, marketTokenAmount: marketTokenAmount ?? 0n, - executionFee: (technicalFees as ExecutionFee).feeTokenAmount, - executionGasLimit: (technicalFees as ExecutionFee).gasLimit, + executionFee: fees.feeTokenAmount, + executionGasLimit: fees.gasLimit, skipSimulation: shouldDisableValidation, tokensData, blockTimestampData, @@ -584,7 +607,7 @@ export const useDepositTransactions = ({ function useDepositTransferRequests({ technicalFees, }: { - technicalFees: TechnicalFees | undefined; + technicalFees: TechnicalGmFees | undefined; }): TransferRequests | undefined { const chainId = useSelector(selectChainId); const { isDeposit } = useSelector(selectPoolsDetailsFlags); @@ -615,52 +638,20 @@ function useDepositTransferRequests({ : undefined; return useMemo((): TransferRequests | undefined => { - if (!isDeposit) { - return undefined; - } - - const vaultAddress = isGlv ? getContract(chainId, "GlvVault") : getContract(chainId, "DepositVault"); - - if (isMarketTokenDeposit) { - return getTransferRequests([ - { - to: vaultAddress, - token: marketTokenAddress, - amount: marketTokenAmount, - }, - ]); - } - - if (paySource === "sourceChain") { - let tokenAddress = - longTokenAmount !== undefined && longTokenAmount > 0n ? initialLongTokenAddress : initialShortTokenAddress; - - let amount = longTokenAmount !== undefined && longTokenAmount > 0n ? longTokenAmount : shortTokenAmount!; - - const estimatedReceivedAmount = (technicalFees as SourceChainDepositFees | SourceChainGlvDepositFees | undefined) - ?.txnEstimatedReceivedAmount; - - if (estimatedReceivedAmount !== undefined && estimatedReceivedAmount > amount) { - return undefined; - } - - amount = applySlippageToMinOut(DEFAULT_SLIPPAGE_AMOUNT, estimatedReceivedAmount ?? amount); - - return getTransferRequests([{ to: vaultAddress, token: tokenAddress, amount }]); - } - - return getTransferRequests([ - { - to: vaultAddress, - token: initialLongTokenAddress, - amount: longTokenAmount, - }, - { - to: vaultAddress, - token: initialShortTokenAddress, - amount: shortTokenAmount, - }, - ]); + return buildDepositTransferRequests({ + isDeposit, + isGlv, + chainId, + paySource, + isMarketTokenDeposit, + marketTokenAddress, + marketTokenAmount, + longTokenAmount, + shortTokenAmount, + initialLongTokenAddress, + initialShortTokenAddress, + technicalFees, + }); }, [ isDeposit, isGlv, diff --git a/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useLpTransactions.tsx b/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useLpTransactions.tsx index 229eab2533..b39a869365 100644 --- a/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useLpTransactions.tsx +++ b/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useLpTransactions.tsx @@ -2,11 +2,7 @@ import { useCallback, useState } from "react"; import { selectPoolsDetailsOperation } from "context/PoolsDetailsContext/selectors"; import { useSelector } from "context/SyntheticsStateContext/utils"; -import type { ExecutionFee } from "domain/synthetics/fees"; -import type { SourceChainDepositFees } from "domain/synthetics/markets/feeEstimation/estimateSourceChainDepositFees"; -import type { SourceChainGlvDepositFees } from "domain/synthetics/markets/feeEstimation/estimateSourceChainGlvDepositFees"; -import { SourceChainGlvWithdrawalFees } from "domain/synthetics/markets/feeEstimation/estimateSourceChainGlvWithdrawalFees"; -import { SourceChainWithdrawalFees } from "domain/synthetics/markets/feeEstimation/estimateSourceChainWithdrawalFees"; +import { TechnicalGmFees } from "domain/multichain/technical-fees-types"; import { useDepositTransactions } from "./useDepositTransactions"; import { useWithdrawalTransactions } from "./useWithdrawalTransactions"; @@ -14,13 +10,7 @@ import { Operation } from "../../types"; export interface UseLpTransactionProps { shouldDisableValidation?: boolean; - technicalFees: - | ExecutionFee - | SourceChainGlvDepositFees - | SourceChainDepositFees - | SourceChainWithdrawalFees - | SourceChainGlvWithdrawalFees - | undefined; + technicalFees: TechnicalGmFees | undefined; } export const useLpTransactions = ( diff --git a/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useMultichainDepositExpressTxnParams.tsx b/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useMultichainDepositExpressTxnParams.tsx index 2f67b80fae..d0a2c30635 100644 --- a/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useMultichainDepositExpressTxnParams.tsx +++ b/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useMultichainDepositExpressTxnParams.tsx @@ -7,7 +7,6 @@ import { buildAndSignMultichainGlvDepositTxn } from "domain/synthetics/markets/c import type { GmPaySource } from "domain/synthetics/markets/types"; import { useChainId } from "lib/chains"; import { AsyncResult } from "lib/useThrottledAsync"; -import useWallet from "lib/wallets/useWallet"; import { DEFAULT_EXPRESS_ORDER_DEADLINE_DURATION } from "sdk/configs/express"; import { nowInSeconds } from "sdk/utils/time"; @@ -27,14 +26,8 @@ export function useMultichainDepositExpressTxnParams({ gasPaymentTokenAsCollateralAmount: bigint | undefined; }): AsyncResult { const { chainId, srcChainId } = useChainId(); - const { signer } = useWallet(); - const enabled = - paySource === "gmxAccount" && - Boolean(params) && - isDeposit && - transferRequests !== undefined && - signer !== undefined; + const enabled = paySource === "gmxAccount" && Boolean(params) && isDeposit && transferRequests !== undefined; const multichainDepositExpressTxnParams = useArbitraryRelayParamsAndPayload({ isGmxAccount: paySource === "gmxAccount", @@ -61,7 +54,6 @@ export function useMultichainDepositExpressTxnParams({ ...relayParams, deadline: BigInt(nowInSeconds() + DEFAULT_EXPRESS_ORDER_DEADLINE_DURATION), }, - signer, transferRequests, }); @@ -84,7 +76,6 @@ export function useMultichainDepositExpressTxnParams({ ...relayParams, deadline: BigInt(nowInSeconds() + DEFAULT_EXPRESS_ORDER_DEADLINE_DURATION), }, - signer, transferRequests, }); diff --git a/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useMultichainWithdrawalExpressTxnParams.tsx b/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useMultichainWithdrawalExpressTxnParams.tsx index a47583ab1c..370caea085 100644 --- a/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useMultichainWithdrawalExpressTxnParams.tsx +++ b/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useMultichainWithdrawalExpressTxnParams.tsx @@ -23,14 +23,8 @@ export function useMultichainWithdrawalExpressTxnParams({ isWithdrawal: boolean; }) { const { chainId, srcChainId } = useChainId(); - const { signer } = useWallet(); - const enabled = - paySource === "gmxAccount" && - isWithdrawal && - Boolean(params) && - transferRequests !== undefined && - signer !== undefined; + const enabled = paySource === "gmxAccount" && isWithdrawal && Boolean(params) && transferRequests !== undefined; const multichainWithdrawalExpressTxnParams = useArbitraryRelayParamsAndPayload({ isGmxAccount: paySource === "gmxAccount", @@ -56,7 +50,6 @@ export function useMultichainWithdrawalExpressTxnParams({ ...relayParams, deadline: BigInt(nowInSeconds() + DEFAULT_EXPRESS_ORDER_DEADLINE_DURATION), }, - signer, transferRequests, }); @@ -78,7 +71,6 @@ export function useMultichainWithdrawalExpressTxnParams({ ...relayParams, deadline: BigInt(nowInSeconds() + DEFAULT_EXPRESS_ORDER_DEADLINE_DURATION), }, - signer, transferRequests, }); diff --git a/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx b/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx index ad916ec9a7..def1c80c0c 100644 --- a/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx +++ b/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx @@ -26,7 +26,7 @@ import { TokensBalancesUpdates, useTokensBalancesUpdates, } from "context/TokensBalancesContext/TokensBalancesContextProvider"; -import { getTransferRequests } from "domain/multichain/getTransferRequests"; +import { buildWithdrawalTransferRequests } from "domain/multichain/buildWithdrawalTransferRequests"; import { GlvSellTask, GmSellTask } from "domain/multichain/progress/GmOrGlvSellProgress"; import { toastCustomOrStargateError } from "domain/multichain/toastCustomOrStargateError"; import { TransferRequests } from "domain/multichain/types"; @@ -42,8 +42,6 @@ import { createMultichainGlvWithdrawalTxn } from "domain/synthetics/markets/crea import { createMultichainWithdrawalTxn } from "domain/synthetics/markets/createMultichainWithdrawalTxn"; import { createSourceChainGlvWithdrawalTxn } from "domain/synthetics/markets/createSourceChainGlvWithdrawalTxn"; import { createSourceChainWithdrawalTxn } from "domain/synthetics/markets/createSourceChainWithdrawalTxn"; -import { SourceChainGlvWithdrawalFees } from "domain/synthetics/markets/feeEstimation/estimateSourceChainGlvWithdrawalFees"; -import { SourceChainWithdrawalFees } from "domain/synthetics/markets/feeEstimation/estimateSourceChainWithdrawalFees"; import { useChainId } from "lib/chains"; import { helperToast } from "lib/helperToast"; import { @@ -54,9 +52,7 @@ import { sendTxnValidationErrorMetric, } from "lib/metrics"; import useWallet from "lib/wallets/useWallet"; -import { getContract } from "sdk/configs/contracts"; import { getWrappedToken } from "sdk/configs/tokens"; -import { ExecutionFee } from "sdk/types/fees"; import { TokenBalanceType } from "sdk/types/tokens"; import { WithdrawalAmounts } from "sdk/types/trade"; import { getGlvToken, getGmToken } from "sdk/utils/tokens"; @@ -115,16 +111,23 @@ export const useWithdrawalTransactions = ({ return undefined; } - const executionFee = - paySource === "sourceChain" - ? (technicalFees as SourceChainWithdrawalFees | SourceChainGlvWithdrawalFees).executionFee - : (technicalFees as ExecutionFee).feeTokenAmount; + let executionFee: bigint | undefined; + if (technicalFees.kind === "sourceChain" && technicalFees.isDeposit) { + executionFee = technicalFees.fees.executionFee; + } else if (technicalFees.kind === "gmxAccount") { + executionFee = technicalFees.fees.executionFee.feeTokenAmount; + } else if (technicalFees.kind === "settlementChain") { + executionFee = technicalFees.fees.feeTokenAmount; + } + if (executionFee === undefined) { + return undefined; + } return { ...(rawParams as RawCreateWithdrawalParams), executionFee, }; - }, [rawParams, technicalFees, isWithdrawal, paySource]); + }, [rawParams, technicalFees, isWithdrawal]); const multichainWithdrawalExpressTxnParams = useMultichainWithdrawalExpressTxnParams({ transferRequests, @@ -226,6 +229,14 @@ export const useWithdrawalTransactions = ({ throw new Error("An error occurred"); } + const fees = + technicalFees?.kind === "sourceChain" && !technicalFees.isDeposit && technicalFees.isGlv + ? technicalFees.fees + : undefined; + if (!fees) { + throw new Error("Technical fees are not set"); + } + promise = createSourceChainGlvWithdrawalTxn({ chainId, srcChainId, @@ -233,7 +244,7 @@ export const useWithdrawalTransactions = ({ transferRequests, params: rawParams as CreateGlvWithdrawalParams, tokenAmount: glvTokenAmount!, - fees: technicalFees as SourceChainGlvWithdrawalFees, + fees, }) .then((res) => { if (res.transactionHash) { @@ -244,7 +255,7 @@ export const useWithdrawalTransactions = ({ token: getGlvToken(chainId, (rawParams as RawCreateGlvWithdrawalParams).addresses.glv), amount: (amounts as WithdrawalAmounts).glvTokenAmount, settlementChainId: chainId, - estimatedFeeUsd: (technicalFees as SourceChainGlvWithdrawalFees).relayFeeUsd, + estimatedFeeUsd: fees.relayFeeUsd, }) ); } @@ -290,11 +301,15 @@ export const useWithdrawalTransactions = ({ } }); } else if (paySource === "settlementChain") { + const fees = technicalFees?.kind === "settlementChain" ? technicalFees.fees : undefined; + if (!fees) { + throw new Error("Technical fees are not set"); + } promise = createGlvWithdrawalTxn({ chainId, signer, params: params as CreateGlvWithdrawalParams, - executionGasLimit: (technicalFees as ExecutionFee).gasLimit, + executionGasLimit: fees.gasLimit, tokensData, setPendingTxns, setPendingWithdrawal, @@ -370,11 +385,19 @@ export const useWithdrawalTransactions = ({ throw new Error("An error occurred"); } + const fees = + technicalFees.kind === "sourceChain" && !technicalFees.isDeposit && !technicalFees.isGlv + ? technicalFees.fees + : undefined; + if (!fees) { + throw new Error("Technical fees are not set"); + } + promise = createSourceChainWithdrawalTxn({ chainId, srcChainId, signer, - fees: technicalFees as SourceChainWithdrawalFees, + fees, transferRequests, params: rawParams as RawCreateWithdrawalParams, tokenAmount: marketTokenAmount!, @@ -387,7 +410,7 @@ export const useWithdrawalTransactions = ({ token: getGmToken(chainId, (rawParams as RawCreateWithdrawalParams).addresses.market), amount: (amounts as WithdrawalAmounts).marketTokenAmount, settlementChainId: chainId, - estimatedFeeUsd: (technicalFees as SourceChainWithdrawalFees).relayFeeUsd, + estimatedFeeUsd: fees.relayFeeUsd, }) ); } @@ -430,11 +453,15 @@ export const useWithdrawalTransactions = ({ } }); } else if (paySource === "settlementChain") { + const fees = technicalFees?.kind === "settlementChain" ? technicalFees.fees : undefined; + if (!fees) { + throw new Error("Technical fees are not set"); + } promise = createWithdrawalTxn({ chainId, signer, marketTokenAmount: marketTokenAmount!, - executionGasLimit: (technicalFees as ExecutionFee).gasLimit, + executionGasLimit: fees.gasLimit, params: params as CreateWithdrawalParams, tokensData, skipSimulation: shouldDisableValidation, @@ -509,33 +536,14 @@ function useWithdrawalTransferRequests(): TransferRequests | undefined { const glvTokenAddress = glvInfo?.glvTokenAddress; return useMemo((): TransferRequests | undefined => { - if (!isWithdrawal) { - return undefined; - } - - if (isGlv) { - if (!glvTokenAddress) { - return undefined; - } - return getTransferRequests([ - { - to: getContract(chainId, "GlvVault"), - token: glvTokenAddress, - amount: glvTokenAmount, - }, - ]); - } - - if (!marketTokenAddress) { - return undefined; - } - - return getTransferRequests([ - { - to: getContract(chainId, "WithdrawalVault"), - token: marketTokenAddress, - amount: marketTokenAmount, - }, - ]); + return buildWithdrawalTransferRequests({ + isWithdrawal, + isGlv, + chainId: chainId, + glvTokenAddress, + glvTokenAmount, + marketTokenAddress, + marketTokenAmount, + }); }, [chainId, glvTokenAddress, glvTokenAmount, isGlv, isWithdrawal, marketTokenAddress, marketTokenAmount]); } diff --git a/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/useDepositWithdrawalFees.tsx b/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/useDepositWithdrawalFees.tsx index 53fc2d049c..fbb149a312 100644 --- a/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/useDepositWithdrawalFees.tsx +++ b/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/useDepositWithdrawalFees.tsx @@ -1,11 +1,9 @@ import { useMemo } from "react"; +import { TechnicalGmFees } from "domain/multichain/technical-fees-types"; import { useGasMultichainUsd, useNativeTokenMultichainUsd } from "domain/multichain/useMultichainQuoteFeeUsd"; -import { ExecutionFee, getFeeItem, getTotalFeeItem, type FeeItem, type GasLimitsConfig } from "domain/synthetics/fees"; +import { getFeeItem, getTotalFeeItem, type FeeItem, type GasLimitsConfig } from "domain/synthetics/fees"; import { GlvInfo } from "domain/synthetics/markets"; -import { SourceChainDepositFees } from "domain/synthetics/markets/feeEstimation/estimateSourceChainDepositFees"; -import { SourceChainGlvDepositFees } from "domain/synthetics/markets/feeEstimation/estimateSourceChainGlvDepositFees"; -import { SourceChainWithdrawalFees } from "domain/synthetics/markets/feeEstimation/estimateSourceChainWithdrawalFees"; import { convertToUsd, getMidPrice, TokensData } from "domain/synthetics/tokens"; import { DepositAmounts, GmSwapFees, WithdrawalAmounts } from "domain/synthetics/trade"; import { ContractsChainId, SourceChainId } from "sdk/configs/chains"; @@ -29,24 +27,18 @@ export const useDepositWithdrawalFees = ({ tokensData: TokensData | undefined; glvInfo: GlvInfo | undefined; isMarketTokenDeposit: boolean; - technicalFees: - | ExecutionFee - | SourceChainGlvDepositFees - | SourceChainDepositFees - | SourceChainWithdrawalFees - | undefined; + technicalFees: TechnicalGmFees | undefined; srcChainId: SourceChainId | undefined; }): { logicalFees?: GmSwapFees } => { const sourceChainEstimatedNativeFeeUsd = useNativeTokenMultichainUsd({ sourceChainTokenAmount: - technicalFees && "txnEstimatedNativeFee" in technicalFees ? technicalFees.txnEstimatedNativeFee : undefined, + technicalFees?.kind === "sourceChain" ? technicalFees.fees.txnEstimatedNativeFee : undefined, sourceChainId: srcChainId, targetChainId: chainId, }); const sourceChainTxnEstimatedGasUsd = useGasMultichainUsd({ - sourceChainGas: - technicalFees && "txnEstimatedGasLimit" in technicalFees ? technicalFees.txnEstimatedGasLimit : undefined, + sourceChainGas: technicalFees?.kind === "sourceChain" ? technicalFees.fees.txnEstimatedGasLimit : undefined, sourceChainId: srcChainId, targetChainId: chainId, }); @@ -66,14 +58,18 @@ export const useDepositWithdrawalFees = ({ shouldRoundUp: true, }); + const wrappedToken = getWrappedToken(chainId); + const wrappedTokenData = tokensData[wrappedToken.address]; + const wrappedTokenPrice = getMidPrice(wrappedTokenData.prices); + let logicalNetworkFeeUsd = 0n; - if ("feeTokenAmount" in technicalFees) { - logicalNetworkFeeUsd = convertToUsd( - technicalFees.feeTokenAmount * -1n, - getWrappedToken(chainId).decimals, - getMidPrice(tokensData[getWrappedToken(chainId).address].prices) - )!; - } else { + + if (technicalFees.kind === "settlementChain") { + const keeperUsd = convertToUsd(technicalFees.fees.feeTokenAmount, wrappedToken.decimals, wrappedTokenPrice)!; + logicalNetworkFeeUsd = keeperUsd * -1n; + } else if (technicalFees.kind === "gmxAccount") { + logicalNetworkFeeUsd = (technicalFees.fees.executionFee.feeUsd + technicalFees.fees.relayFeeUsd) * -1n; + } else if (technicalFees.kind === "sourceChain") { logicalNetworkFeeUsd = ((sourceChainEstimatedNativeFeeUsd ?? 0n) + (sourceChainTxnEstimatedGasUsd ?? 0n)) * -1n; } diff --git a/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/useGmSwapSubmitState.tsx b/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/useGmSwapSubmitState.tsx index c2fed44049..fa2020210d 100644 --- a/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/useGmSwapSubmitState.tsx +++ b/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/useGmSwapSubmitState.tsx @@ -21,14 +21,10 @@ import { selectGasPaymentToken } from "context/SyntheticsStateContext/selectors/ import { selectChainId, selectSrcChainId } from "context/SyntheticsStateContext/selectors/globalSelectors"; import { selectGasPaymentTokenAddress } from "context/SyntheticsStateContext/selectors/settingsSelectors"; import { useSelector } from "context/SyntheticsStateContext/utils"; +import { TechnicalGmFees } from "domain/multichain/technical-fees-types"; import { useSourceChainError } from "domain/multichain/useSourceChainError"; import { ExpressEstimationInsufficientGasPaymentTokenBalanceError } from "domain/synthetics/express/expressOrderUtils"; -import type { ExecutionFee } from "domain/synthetics/fees"; import type { GlvAndGmMarketsInfoData, GmPaySource, MarketsInfoData } from "domain/synthetics/markets"; -import type { SourceChainDepositFees } from "domain/synthetics/markets/feeEstimation/estimateSourceChainDepositFees"; -import type { SourceChainGlvDepositFees } from "domain/synthetics/markets/feeEstimation/estimateSourceChainGlvDepositFees"; -import { SourceChainGlvWithdrawalFees } from "domain/synthetics/markets/feeEstimation/estimateSourceChainGlvWithdrawalFees"; -import { SourceChainWithdrawalFees } from "domain/synthetics/markets/feeEstimation/estimateSourceChainWithdrawalFees"; import { convertToTokenAmount, type TokenData } from "domain/synthetics/tokens"; import { getCommonError, getGmSwapError } from "domain/synthetics/trade/utils/validation"; import { useHasOutdatedUi } from "lib/useHasOutdatedUi"; @@ -40,20 +36,13 @@ import SpinnerIcon from "img/ic_spinner.svg?react"; import { Operation } from "../types"; import { useLpTransactions } from "./lpTxn/useLpTransactions"; -import { TechnicalFees } from "./useTechnicalFeesAsyncResult"; import { useTokensToApprove } from "./useTokensToApprove"; interface Props { longTokenLiquidityUsd?: bigint | undefined; shortTokenLiquidityUsd?: bigint | undefined; shouldDisableValidation?: boolean; - technicalFees: - | ExecutionFee - | SourceChainGlvDepositFees - | SourceChainDepositFees - | SourceChainWithdrawalFees - | SourceChainGlvWithdrawalFees - | undefined; + technicalFees: TechnicalGmFees | undefined; logicalFees: GmSwapFees | undefined; marketsInfoData?: MarketsInfoData; glvAndMarketsInfoData: GlvAndGmMarketsInfoData; @@ -312,7 +301,7 @@ function useExpressError({ isDeposit, }: { paySource: GmPaySource | undefined; - technicalFees: TechnicalFees | undefined; + technicalFees: TechnicalGmFees | undefined; gasPaymentToken: TokenData | undefined; gasPaymentTokenAddress: string | undefined; longTokenAddress: string | undefined; @@ -330,14 +319,17 @@ function useExpressError({ return undefined; } - const executionFee = technicalFees as ExecutionFee; + const fees = technicalFees.kind === "gmxAccount" ? technicalFees.fees : undefined; + if (!fees) { + return undefined; + } if (gasPaymentToken.prices.minPrice === undefined) { return undefined; } const gasPaymentTokenAmount = convertToTokenAmount( - executionFee.feeUsd, + fees.executionFee.feeUsd + fees.relayFeeUsd, gasPaymentToken.decimals, gasPaymentToken.prices.minPrice ); diff --git a/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/useTechnicalFeesAsyncResult.tsx b/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/useTechnicalFeesAsyncResult.tsx index fe8cdbf695..97effe907a 100644 --- a/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/useTechnicalFeesAsyncResult.tsx +++ b/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/useTechnicalFeesAsyncResult.tsx @@ -7,6 +7,8 @@ import { selectPoolsDetailsMarketOrGlvTokenAmount, selectPoolsDetailsOperation, selectPoolsDetailsPaySource, + selectPoolsDetailsSecondTokenAddress, + selectPoolsDetailsSecondTokenAmount, selectPoolsDetailsSelectedMarketAddressForGlv, } from "context/PoolsDetailsContext/selectors"; import { selectDepositWithdrawalAmounts } from "context/PoolsDetailsContext/selectors/selectDepositWithdrawalAmounts"; @@ -18,48 +20,40 @@ import { selectTokensData, } from "context/SyntheticsStateContext/selectors/globalSelectors"; import { useSelector } from "context/SyntheticsStateContext/utils"; +import { estimateArbitraryRelayFee, getRawBaseRelayerParams } from "domain/multichain/arbitraryRelayParams"; +import { buildDepositTransferRequests } from "domain/multichain/buildDepositTransferRequests"; +import { buildWithdrawalTransferRequests } from "domain/multichain/buildWithdrawalTransferRequests"; +import { TechnicalGmFees } from "domain/multichain/technical-fees-types"; +import { ExpressTransactionBuilder } from "domain/synthetics/express/types"; import { RawCreateDepositParams, RawCreateGlvDepositParams, RawCreateGlvWithdrawalParams, RawCreateWithdrawalParams, } from "domain/synthetics/markets"; +import { buildAndSignMultichainDepositTxn } from "domain/synthetics/markets/createMultichainDepositTxn"; +import { buildAndSignMultichainGlvDepositTxn } from "domain/synthetics/markets/createMultichainGlvDepositTxn"; +import { buildAndSignMultichainGlvWithdrawalTxn } from "domain/synthetics/markets/createMultichainGlvWithdrawalTxn"; +import { buildAndSignMultichainWithdrawalTxn } from "domain/synthetics/markets/createMultichainWithdrawalTxn"; import { estimatePureLpActionExecutionFee } from "domain/synthetics/markets/feeEstimation/estimatePureLpActionExecutionFee"; -import { - estimateSourceChainDepositFees, - SourceChainDepositFees, -} from "domain/synthetics/markets/feeEstimation/estimateSourceChainDepositFees"; -import { - estimateSourceChainGlvDepositFees, - SourceChainGlvDepositFees, -} from "domain/synthetics/markets/feeEstimation/estimateSourceChainGlvDepositFees"; -import { - estimateSourceChainGlvWithdrawalFees, - SourceChainGlvWithdrawalFees, -} from "domain/synthetics/markets/feeEstimation/estimateSourceChainGlvWithdrawalFees"; -import { - estimateSourceChainWithdrawalFees, - SourceChainWithdrawalFees, -} from "domain/synthetics/markets/feeEstimation/estimateSourceChainWithdrawalFees"; +import { estimateSourceChainDepositFees } from "domain/synthetics/markets/feeEstimation/estimateSourceChainDepositFees"; +import { estimateSourceChainGlvDepositFees } from "domain/synthetics/markets/feeEstimation/estimateSourceChainGlvDepositFees"; +import { estimateSourceChainGlvWithdrawalFees } from "domain/synthetics/markets/feeEstimation/estimateSourceChainGlvWithdrawalFees"; +import { estimateSourceChainWithdrawalFees } from "domain/synthetics/markets/feeEstimation/estimateSourceChainWithdrawalFees"; +import { convertToUsd } from "domain/tokens"; import { useChainId } from "lib/chains"; import { usePrevious } from "lib/usePrevious"; import { useThrottledAsync } from "lib/useThrottledAsync"; +import { getPublicClientWithRpc } from "lib/wallets/rainbowKitConfig"; +import { DEFAULT_EXPRESS_ORDER_DEADLINE_DURATION } from "sdk/configs/express"; import { MARKETS } from "sdk/configs/markets"; -import { ExecutionFee } from "sdk/types/fees"; import { WithdrawalAmounts } from "sdk/types/trade"; import { absDiffBps } from "sdk/utils/numbers"; +import { nowInSeconds } from "sdk/utils/time"; import { Operation } from "../types"; -export type TechnicalFees = - | ExecutionFee - | SourceChainGlvDepositFees - | SourceChainDepositFees - | SourceChainWithdrawalFees - | SourceChainGlvWithdrawalFees - | undefined; - -export function useTechnicalFees(): TechnicalFees { +export function useTechnicalFees(): TechnicalGmFees { const { chainId, srcChainId } = useChainId(); const operation = useSelector(selectPoolsDetailsOperation); @@ -72,6 +66,8 @@ export function useTechnicalFees(): TechnicalFees { const firstTokenAddress = useSelector(selectPoolsDetailsFirstTokenAddress); const firstTokenAmount = useSelector(selectPoolsDetailsFirstTokenAmount); + const secondTokenAddress = useSelector(selectPoolsDetailsSecondTokenAddress); + const secondTokenAmount = useSelector(selectPoolsDetailsSecondTokenAmount); const marketOrGlvTokenAmount = useSelector(selectPoolsDetailsMarketOrGlvTokenAmount); const prevPaySource = usePrevious(paySource); @@ -95,12 +91,12 @@ export function useTechnicalFees(): TechnicalFees { const amounts = useSelector(selectDepositWithdrawalAmounts); const technicalFeesAsyncResult = useThrottledAsync( - async (p) => { - if (p.params.paySource === "gmxAccount" || p.params.paySource === "settlementChain") { + async (p): Promise => { + if (p.params.paySource === "settlementChain") { if (p.params.operation === Operation.Deposit) { if (p.params.isGlv) { const castedParams = p.params.rawParams as RawCreateGlvDepositParams; - return estimatePureLpActionExecutionFee({ + const fees = estimatePureLpActionExecutionFee({ action: { operation: Operation.Deposit, isGlv: true, @@ -115,9 +111,14 @@ export function useTechnicalFees(): TechnicalFees { tokensData: p.params.tokensData, gasPrice: p.params.gasPrice, }); + + return { + kind: "settlementChain", + fees, + }; } else { const castedParams = p.params.rawParams as RawCreateDepositParams; - return estimatePureLpActionExecutionFee({ + const fees = estimatePureLpActionExecutionFee({ action: { operation: Operation.Deposit, isGlv: false, @@ -130,11 +131,16 @@ export function useTechnicalFees(): TechnicalFees { tokensData: p.params.tokensData, gasPrice: p.params.gasPrice, }); + + return { + kind: "settlementChain", + fees, + }; } } else if (p.params.operation === Operation.Withdrawal) { if (p.params.isGlv) { const castedParams = p.params.rawParams as RawCreateGlvWithdrawalParams; - return estimatePureLpActionExecutionFee({ + const fees = estimatePureLpActionExecutionFee({ action: { operation: Operation.Withdrawal, isGlv: true, @@ -148,27 +154,362 @@ export function useTechnicalFees(): TechnicalFees { tokensData: p.params.tokensData, gasPrice: p.params.gasPrice, }); + + return { + kind: "settlementChain", + fees, + }; + } else { + const castedParams = p.params.rawParams as RawCreateWithdrawalParams; + const fees = estimatePureLpActionExecutionFee({ + action: { + operation: Operation.Withdrawal, + isGlv: false, + swapsCount: BigInt( + castedParams.addresses.longTokenSwapPath.length + castedParams.addresses.shortTokenSwapPath.length + ), + }, + chainId: p.params.chainId, + gasLimits: p.params.gasLimits, + tokensData: p.params.tokensData, + gasPrice: p.params.gasPrice, + }); + + return { + kind: "settlementChain", + fees, + }; } + } + } else if (p.params.paySource === "gmxAccount") { + if (!p.params.globalExpressParams) { + return undefined; + } + + const { rawBaseRelayParamsPayload, baseRelayFeeSwapParams } = getRawBaseRelayerParams({ + chainId, + account: p.params.rawParams.addresses.receiver, + globalExpressParams: p.params.globalExpressParams, + }); + + if (!rawBaseRelayParamsPayload || !baseRelayFeeSwapParams) { + return undefined; + } + + if (p.params.operation === Operation.Deposit) { + if (p.params.isGlv) { + const castedParams = p.params.rawParams as RawCreateGlvDepositParams; + const executionFee = estimatePureLpActionExecutionFee({ + action: { + operation: Operation.Deposit, + isGlv: true, + marketsCount: BigInt(p.params.glvInfo!.markets.length), + swapsCount: BigInt( + castedParams.addresses.longTokenSwapPath.length + castedParams.addresses.shortTokenSwapPath.length + ), + isMarketTokenDeposit: castedParams.isMarketTokenDeposit, + }, + chainId: p.params.chainId, + gasLimits: p.params.gasLimits, + tokensData: p.params.tokensData, + gasPrice: p.params.gasPrice, + }); + + const transferRequests = buildDepositTransferRequests({ + isDeposit: true, + isGlv: true, + chainId: p.params.chainId, + paySource: p.params.paySource, + isMarketTokenDeposit: castedParams.isMarketTokenDeposit, + marketTokenAddress: p.params.rawParams.addresses.market, + marketTokenAmount: p.params.firstTokenAmount, + longTokenAmount: p.params.firstTokenAmount, + shortTokenAmount: p.params.secondTokenAmount, + initialLongTokenAddress: castedParams.addresses.initialLongToken, + initialShortTokenAddress: castedParams.addresses.initialShortToken, + technicalFees: undefined, + }); + + if (!transferRequests) { + return undefined; + } + + const expressTransactionBuilder: ExpressTransactionBuilder = async ({ relayParams, gasPaymentParams }) => { + return { + txnData: await buildAndSignMultichainGlvDepositTxn({ + chainId: p.params.chainId, + srcChainId: p.params.srcChainId, + emptySignature: true, + signer: undefined, + account: p.params.rawParams.addresses.receiver, + params: { ...castedParams, executionFee: executionFee.feeTokenAmount }, + relayerFeeAmount: gasPaymentParams.relayerFeeAmount, + relayerFeeTokenAddress: gasPaymentParams.relayerFeeTokenAddress, + relayParams: { + ...relayParams, + deadline: BigInt(nowInSeconds() + DEFAULT_EXPRESS_ORDER_DEADLINE_DURATION), + }, + transferRequests, + }), + }; + }; + + const relayFee = await estimateArbitraryRelayFee({ + account: p.params.rawParams.addresses.receiver, + chainId: p.params.chainId, + client: getPublicClientWithRpc(p.params.chainId), + rawRelayParamsPayload: rawBaseRelayParamsPayload, + expressTransactionBuilder: expressTransactionBuilder, + gasPaymentParams: baseRelayFeeSwapParams.gasPaymentParams, + subaccount: undefined, + }); + + const relayFeeUsd = convertToUsd( + relayFee, + p.params.globalExpressParams.relayerFeeToken.decimals, + p.params.globalExpressParams.relayerFeeToken.prices.maxPrice + )!; - const castedParams = p.params.rawParams as RawCreateWithdrawalParams; - return estimatePureLpActionExecutionFee({ - action: { - operation: Operation.Withdrawal, + return { + kind: "gmxAccount", + fees: { + executionFee, + relayFeeUsd, + }, + }; + } else { + const castedParams = p.params.rawParams as RawCreateDepositParams; + const executionFee = estimatePureLpActionExecutionFee({ + action: { + operation: Operation.Deposit, + isGlv: false, + swapsCount: BigInt( + castedParams.addresses.longTokenSwapPath.length + castedParams.addresses.shortTokenSwapPath.length + ), + }, + chainId: p.params.chainId, + gasLimits: p.params.gasLimits, + tokensData: p.params.tokensData, + gasPrice: p.params.gasPrice, + }); + + const transferRequests = buildDepositTransferRequests({ + isDeposit: true, isGlv: false, - swapsCount: BigInt( - castedParams.addresses.longTokenSwapPath.length + castedParams.addresses.shortTokenSwapPath.length - ), - }, - chainId: p.params.chainId, - gasLimits: p.params.gasLimits, - tokensData: p.params.tokensData, - gasPrice: p.params.gasPrice, - }); + chainId: p.params.chainId, + paySource: p.params.paySource, + isMarketTokenDeposit: false, + marketTokenAddress: undefined, + marketTokenAmount: 0n, + longTokenAmount: p.params.firstTokenAmount, + shortTokenAmount: p.params.secondTokenAmount, + initialLongTokenAddress: castedParams.addresses.initialLongToken, + initialShortTokenAddress: castedParams.addresses.initialShortToken, + technicalFees: undefined, + }); + + if (!transferRequests) { + return undefined; + } + + const expressTransactionBuilder: ExpressTransactionBuilder = async ({ relayParams, gasPaymentParams }) => { + return { + txnData: await buildAndSignMultichainDepositTxn({ + chainId: p.params.chainId, + srcChainId: p.params.srcChainId, + emptySignature: true, + signer: undefined, + account: p.params.rawParams.addresses.receiver, + params: { ...castedParams, executionFee: executionFee.feeTokenAmount }, + relayerFeeAmount: gasPaymentParams.relayerFeeAmount, + relayerFeeTokenAddress: gasPaymentParams.relayerFeeTokenAddress, + relayParams: { + ...relayParams, + deadline: BigInt(nowInSeconds() + DEFAULT_EXPRESS_ORDER_DEADLINE_DURATION), + }, + transferRequests, + }), + }; + }; + + const relayFee = await estimateArbitraryRelayFee({ + account: p.params.rawParams.addresses.receiver, + chainId: p.params.chainId, + client: getPublicClientWithRpc(p.params.chainId), + rawRelayParamsPayload: rawBaseRelayParamsPayload, + expressTransactionBuilder: expressTransactionBuilder, + gasPaymentParams: baseRelayFeeSwapParams.gasPaymentParams, + subaccount: undefined, + }); + + const relayFeeUsd = convertToUsd( + relayFee, + p.params.globalExpressParams.relayerFeeToken.decimals, + p.params.globalExpressParams.relayerFeeToken.prices.maxPrice + )!; + + return { + kind: "gmxAccount", + fees: { + executionFee, + relayFeeUsd, + }, + }; + } + } else if (p.params.operation === Operation.Withdrawal) { + if (p.params.isGlv) { + const castedParams = p.params.rawParams as RawCreateGlvWithdrawalParams; + const fees = estimatePureLpActionExecutionFee({ + action: { + operation: Operation.Withdrawal, + isGlv: true, + marketsCount: BigInt(p.params.glvInfo!.markets.length), + swapsCount: BigInt( + castedParams.addresses.longTokenSwapPath.length + castedParams.addresses.shortTokenSwapPath.length + ), + }, + chainId: p.params.chainId, + gasLimits: p.params.gasLimits, + tokensData: p.params.tokensData, + gasPrice: p.params.gasPrice, + }); + + const transferRequests = buildWithdrawalTransferRequests({ + isWithdrawal: true, + isGlv: true, + chainId: p.params.chainId, + glvTokenAddress: castedParams.addresses.glv, + glvTokenAmount: p.params.marketTokenAmount, + marketTokenAddress: undefined, + marketTokenAmount: 0n, + }); + + if (!transferRequests) { + return undefined; + } + + const expressTransactionBuilder: ExpressTransactionBuilder = async ({ relayParams, gasPaymentParams }) => { + return { + txnData: await buildAndSignMultichainGlvWithdrawalTxn({ + chainId: p.params.chainId, + srcChainId: p.params.srcChainId, + emptySignature: true, + signer: undefined, + account: p.params.rawParams.addresses.receiver, + params: { ...castedParams, executionFee: fees.feeTokenAmount }, + relayerFeeAmount: gasPaymentParams.relayerFeeAmount, + relayerFeeTokenAddress: gasPaymentParams.relayerFeeTokenAddress, + relayParams: { + ...relayParams, + deadline: BigInt(nowInSeconds() + DEFAULT_EXPRESS_ORDER_DEADLINE_DURATION), + }, + transferRequests, + }), + }; + }; + + const relayFee = await estimateArbitraryRelayFee({ + account: p.params.rawParams.addresses.receiver, + chainId: p.params.chainId, + client: getPublicClientWithRpc(p.params.chainId), + rawRelayParamsPayload: rawBaseRelayParamsPayload, + expressTransactionBuilder: expressTransactionBuilder, + gasPaymentParams: baseRelayFeeSwapParams.gasPaymentParams, + subaccount: undefined, + }); + + const relayFeeUsd = convertToUsd( + relayFee, + p.params.globalExpressParams.relayerFeeToken.decimals, + p.params.globalExpressParams.relayerFeeToken.prices.maxPrice + )!; + + return { + kind: "gmxAccount", + fees: { + executionFee: fees, + relayFeeUsd, + }, + }; + } else { + const castedParams = p.params.rawParams as RawCreateWithdrawalParams; + const fees = estimatePureLpActionExecutionFee({ + action: { + operation: Operation.Withdrawal, + isGlv: false, + swapsCount: BigInt( + castedParams.addresses.longTokenSwapPath.length + castedParams.addresses.shortTokenSwapPath.length + ), + }, + chainId: p.params.chainId, + gasLimits: p.params.gasLimits, + tokensData: p.params.tokensData, + gasPrice: p.params.gasPrice, + }); + + const transferRequests = buildWithdrawalTransferRequests({ + isWithdrawal: true, + isGlv: false, + chainId: p.params.chainId, + glvTokenAddress: undefined, + glvTokenAmount: 0n, + marketTokenAddress: castedParams.addresses.market, + marketTokenAmount: p.params.marketTokenAmount, + }); + + if (!transferRequests) { + return undefined; + } + + const expressTransactionBuilder: ExpressTransactionBuilder = async ({ relayParams, gasPaymentParams }) => { + return { + txnData: await buildAndSignMultichainWithdrawalTxn({ + chainId: p.params.chainId, + srcChainId: p.params.srcChainId, + emptySignature: true, + signer: undefined as any, + account: p.params.rawParams.addresses.receiver, + params: { ...castedParams, executionFee: fees.feeTokenAmount }, + relayerFeeAmount: gasPaymentParams.relayerFeeAmount, + relayerFeeTokenAddress: gasPaymentParams.relayerFeeTokenAddress, + relayParams: { + ...relayParams, + deadline: BigInt(nowInSeconds() + DEFAULT_EXPRESS_ORDER_DEADLINE_DURATION), + }, + transferRequests, + }), + }; + }; + + const relayFee = await estimateArbitraryRelayFee({ + account: p.params.rawParams.addresses.receiver, + chainId: p.params.chainId, + client: getPublicClientWithRpc(p.params.chainId), + rawRelayParamsPayload: rawBaseRelayParamsPayload, + expressTransactionBuilder: expressTransactionBuilder, + gasPaymentParams: baseRelayFeeSwapParams.gasPaymentParams, + subaccount: undefined, + }); + + const relayFeeUsd = convertToUsd( + relayFee, + p.params.globalExpressParams.relayerFeeToken.decimals, + p.params.globalExpressParams.relayerFeeToken.prices.maxPrice + )!; + + return { + kind: "gmxAccount", + fees: { + executionFee: fees, + relayFeeUsd, + }, + }; + } } } else if (p.params.paySource === "sourceChain") { if ( - p.params.tokenAddress === undefined || - p.params.tokenAmount === undefined || + p.params.firstTokenAddress === undefined || + p.params.firstTokenAmount === undefined || !p.params.globalExpressParams ) { return undefined; @@ -176,25 +517,38 @@ export function useTechnicalFees(): TechnicalFees { if (p.params.operation === Operation.Deposit) { if (p.params.isGlv) { const castedParams = p.params.rawParams as RawCreateGlvDepositParams; - return await estimateSourceChainGlvDepositFees({ + const fees = await estimateSourceChainGlvDepositFees({ chainId: p.params.chainId as SettlementChainId, srcChainId: p.params.srcChainId as SourceChainId, params: castedParams, - tokenAddress: p.params.tokenAddress, - tokenAmount: p.params.tokenAmount, + tokenAddress: p.params.firstTokenAddress, + tokenAmount: p.params.firstTokenAmount, globalExpressParams: p.params.globalExpressParams, glvMarketCount: BigInt(p.params.glvInfo!.markets.length), }); + + return { + kind: "sourceChain", + isGlv: true, + isDeposit: true, + fees, + }; } else { const castedParams = p.params.rawParams as RawCreateDepositParams; - return await estimateSourceChainDepositFees({ + const fees = await estimateSourceChainDepositFees({ chainId: p.params.chainId as SettlementChainId, srcChainId: p.params.srcChainId as SourceChainId, params: castedParams, - tokenAddress: p.params.tokenAddress, - tokenAmount: p.params.tokenAmount, + tokenAddress: p.params.firstTokenAddress, + tokenAmount: p.params.firstTokenAmount, globalExpressParams: p.params.globalExpressParams, }); + return { + kind: "sourceChain", + isGlv: false, + isDeposit: true, + fees, + }; } } else if (p.params.operation === Operation.Withdrawal) { if (p.params.isGlv) { @@ -205,7 +559,7 @@ export function useTechnicalFees(): TechnicalFees { const outputShortTokenAddress = glvWithdrawalAmounts.shortTokenSwapPathStats?.tokenOutAddress ?? glvInfo!.shortTokenAddress; - return await estimateSourceChainGlvWithdrawalFees({ + const fees = await estimateSourceChainGlvWithdrawalFees({ chainId: p.params.chainId as SettlementChainId, srcChainId: p.params.srcChainId as SourceChainId, params: castedParams, @@ -216,6 +570,13 @@ export function useTechnicalFees(): TechnicalFees { outputLongTokenAddress, outputShortTokenAddress, }); + + return { + kind: "sourceChain", + isGlv: true, + isDeposit: false, + fees, + }; } else { const castedParams = p.params.rawParams as RawCreateWithdrawalParams; if (!p.params.amounts) { @@ -231,7 +592,7 @@ export function useTechnicalFees(): TechnicalFees { gmWithdrawalAmounts.shortTokenSwapPathStats?.tokenOutAddress ?? MARKETS[p.params.chainId][p.params.rawParams.addresses.market].shortTokenAddress; - return await estimateSourceChainWithdrawalFees({ + const fees = await estimateSourceChainWithdrawalFees({ chainId: p.params.chainId as SettlementChainId, srcChainId: p.params.srcChainId as SourceChainId, params: castedParams, @@ -241,6 +602,13 @@ export function useTechnicalFees(): TechnicalFees { outputLongTokenAddress, outputShortTokenAddress, }); + + return { + kind: "sourceChain", + isGlv: false, + isDeposit: false, + fees, + }; } } } @@ -256,8 +624,10 @@ export function useTechnicalFees(): TechnicalFees { glvInfo, paySource, srcChainId, - tokenAddress: firstTokenAddress, - tokenAmount: firstTokenAmount, + firstTokenAddress, + firstTokenAmount, + secondTokenAddress, + secondTokenAmount, marketTokenAmount: marketOrGlvTokenAmount, operation, amounts, diff --git a/src/domain/multichain/buildDepositTransferRequests.tsx b/src/domain/multichain/buildDepositTransferRequests.tsx new file mode 100644 index 0000000000..169ffd5c6b --- /dev/null +++ b/src/domain/multichain/buildDepositTransferRequests.tsx @@ -0,0 +1,88 @@ +import type { ContractsChainId } from "config/chains"; +import { getContract } from "config/contracts"; +import { DEFAULT_SLIPPAGE_AMOUNT } from "config/factors"; +import { getTransferRequests } from "domain/multichain/getTransferRequests"; +import type { TechnicalGmFees } from "domain/multichain/technical-fees-types"; +import type { TransferRequests } from "domain/multichain/types"; +import type { GmPaySource } from "domain/synthetics/markets"; +import { applySlippageToMinOut } from "sdk/utils/trade"; + +export function buildDepositTransferRequests({ + isDeposit, + isGlv, + chainId, + paySource, + isMarketTokenDeposit, + marketTokenAddress, + marketTokenAmount, + longTokenAmount, + shortTokenAmount, + initialLongTokenAddress, + initialShortTokenAddress, + technicalFees, +}: { + isDeposit: boolean; + isGlv: boolean; + chainId: ContractsChainId; + paySource: GmPaySource; + isMarketTokenDeposit: boolean; + marketTokenAddress: string | undefined; + marketTokenAmount: bigint; + longTokenAmount: bigint | undefined; + shortTokenAmount: bigint | undefined; + initialLongTokenAddress: string | undefined; + initialShortTokenAddress: string | undefined; + /** + * Used for source chain deposit to adjust the transfer amount + */ + technicalFees: TechnicalGmFees | undefined; +}): TransferRequests | undefined { + if (!isDeposit) { + return undefined; + } + + const vaultAddress = isGlv ? getContract(chainId, "GlvVault") : getContract(chainId, "DepositVault"); + + if (isMarketTokenDeposit) { + return getTransferRequests([ + { + to: vaultAddress, + token: marketTokenAddress, + amount: marketTokenAmount, + }, + ]); + } + + if (paySource === "sourceChain") { + let tokenAddress = + longTokenAmount !== undefined && longTokenAmount > 0n ? initialLongTokenAddress : initialShortTokenAddress; + + let amount = longTokenAmount !== undefined && longTokenAmount > 0n ? longTokenAmount : shortTokenAmount!; + + const estimatedReceivedAmount = + technicalFees?.kind === "sourceChain" && technicalFees.isDeposit + ? technicalFees.fees.txnEstimatedReceivedAmount + : undefined; + + if (estimatedReceivedAmount !== undefined && estimatedReceivedAmount > amount) { + return undefined; + } + + amount = applySlippageToMinOut(DEFAULT_SLIPPAGE_AMOUNT, estimatedReceivedAmount ?? amount); + + return getTransferRequests([{ to: vaultAddress, token: tokenAddress, amount }]); + } + + return getTransferRequests([ + { + to: vaultAddress, + token: initialLongTokenAddress, + amount: longTokenAmount, + }, + { + to: vaultAddress, + token: initialShortTokenAddress, + amount: shortTokenAmount, + }, + ]); +} diff --git a/src/domain/multichain/buildWithdrawalTransferRequests.tsx b/src/domain/multichain/buildWithdrawalTransferRequests.tsx new file mode 100644 index 0000000000..9d4d40ecaf --- /dev/null +++ b/src/domain/multichain/buildWithdrawalTransferRequests.tsx @@ -0,0 +1,51 @@ +import type { ContractsChainId } from "config/chains"; +import { getContract } from "config/contracts"; +import { getTransferRequests } from "domain/multichain/getTransferRequests"; +import type { TransferRequests } from "domain/multichain/types"; + +export function buildWithdrawalTransferRequests({ + isWithdrawal, + isGlv, + chainId, + glvTokenAddress, + glvTokenAmount, + marketTokenAddress, + marketTokenAmount, +}: { + isWithdrawal: boolean; + isGlv: boolean; + chainId: ContractsChainId; + glvTokenAddress: string | undefined; + glvTokenAmount: bigint; + marketTokenAddress: string | undefined; + marketTokenAmount: bigint; +}): TransferRequests | undefined { + if (!isWithdrawal) { + return undefined; + } + + if (isGlv) { + if (!glvTokenAddress) { + return undefined; + } + return getTransferRequests([ + { + to: getContract(chainId, "GlvVault"), + token: glvTokenAddress, + amount: glvTokenAmount, + }, + ]); + } + + if (!marketTokenAddress) { + return undefined; + } + + return getTransferRequests([ + { + to: getContract(chainId, "WithdrawalVault"), + token: marketTokenAddress, + amount: marketTokenAmount, + }, + ]); +} diff --git a/src/domain/multichain/technical-fees-types.ts b/src/domain/multichain/technical-fees-types.ts new file mode 100644 index 0000000000..943838e90c --- /dev/null +++ b/src/domain/multichain/technical-fees-types.ts @@ -0,0 +1,45 @@ +import type { SourceChainDepositFees } from "domain/synthetics/markets/feeEstimation/estimateSourceChainDepositFees"; +import type { SourceChainGlvDepositFees } from "domain/synthetics/markets/feeEstimation/estimateSourceChainGlvDepositFees"; +import type { SourceChainGlvWithdrawalFees } from "domain/synthetics/markets/feeEstimation/estimateSourceChainGlvWithdrawalFees"; +import type { SourceChainWithdrawalFees } from "domain/synthetics/markets/feeEstimation/estimateSourceChainWithdrawalFees"; +import type { ExecutionFee } from "sdk/types/fees"; + +type SameChainGmFees = { + kind: "settlementChain"; + fees: ExecutionFee; +}; + +type GmxAccountGmFees = { + kind: "gmxAccount"; + fees: { + executionFee: ExecutionFee; + relayFeeUsd: bigint; + }; +}; + +type SourceChainGmFees = { + kind: "sourceChain"; +} & ( + | { + isGlv: false; + isDeposit: false; + fees: SourceChainWithdrawalFees; + } + | { + isGlv: false; + isDeposit: true; + fees: SourceChainDepositFees; + } + | { + isGlv: true; + isDeposit: false; + fees: SourceChainGlvWithdrawalFees; + } + | { + isGlv: true; + isDeposit: true; + fees: SourceChainGlvDepositFees; + } +); + +export type TechnicalGmFees = SameChainGmFees | GmxAccountGmFees | SourceChainGmFees | undefined; diff --git a/src/domain/synthetics/express/relayParamsUtils.ts b/src/domain/synthetics/express/relayParamsUtils.ts index 80f528d845..11d9dd4993 100644 --- a/src/domain/synthetics/express/relayParamsUtils.ts +++ b/src/domain/synthetics/express/relayParamsUtils.ts @@ -204,7 +204,6 @@ export function getRawRelayerParams({ feeParams, externalCalls, tokenPermits, - // marketsInfoData, }: { chainId: ContractsChainId; gasPaymentTokenAddress: string; @@ -212,7 +211,6 @@ export function getRawRelayerParams({ feeParams: RelayFeePayload; externalCalls: ExternalCallsPayload; tokenPermits: SignedTokenPermit[]; - // marketsInfoData: MarketsInfoData; }): RawRelayParamsPayload { const oracleParams = getOracleParamsForRelayParams({ chainId, @@ -220,7 +218,6 @@ export function getRawRelayerParams({ feeSwapPath: feeParams.feeSwapPath, gasPaymentTokenAddress, relayerFeeTokenAddress, - // marketsInfoData, }); const relayParamsPayload: RawRelayParamsPayload = { diff --git a/src/domain/synthetics/markets/createMultichainDepositTxn.ts b/src/domain/synthetics/markets/createMultichainDepositTxn.ts index 3ec2fed01d..6d9160a726 100644 --- a/src/domain/synthetics/markets/createMultichainDepositTxn.ts +++ b/src/domain/synthetics/markets/createMultichainDepositTxn.ts @@ -16,15 +16,22 @@ import { signCreateDeposit } from "./signCreateDeposit"; type TxnParams = { chainId: ContractsChainId; srcChainId: SourceChainId | undefined; - signer: WalletSigner; relayParams: RelayParamsPayload; - emptySignature?: boolean; account: string; transferRequests: TransferRequests; params: CreateDepositParams; relayerFeeTokenAddress: string; relayerFeeAmount: bigint; -}; +} & ( + | { + signer?: undefined; + emptySignature: true; + } + | { + signer: WalletSigner; + emptySignature?: false; + } +); export async function buildAndSignMultichainDepositTxn({ chainId, @@ -43,6 +50,9 @@ export async function buildAndSignMultichainDepositTxn({ if (emptySignature) { signature = "0x"; } else { + if (!signer) { + throw new Error("Signer is required when emptySignature is false"); + } signature = await signCreateDeposit({ chainId, srcChainId, diff --git a/src/domain/synthetics/markets/createMultichainGlvDepositTxn.ts b/src/domain/synthetics/markets/createMultichainGlvDepositTxn.ts index 341701851f..f1f203ba4b 100644 --- a/src/domain/synthetics/markets/createMultichainGlvDepositTxn.ts +++ b/src/domain/synthetics/markets/createMultichainGlvDepositTxn.ts @@ -16,15 +16,22 @@ import { signCreateGlvDeposit } from "./signCreateGlvDeposit"; export type CreateMultichainGlvDepositParams = { chainId: ContractsChainId; srcChainId: SourceChainId | undefined; - signer: WalletSigner; relayParams: RelayParamsPayload; - emptySignature?: boolean; account: string; transferRequests: TransferRequests; params: CreateGlvDepositParams; relayerFeeTokenAddress: string; relayerFeeAmount: bigint; -}; +} & ( + | { + signer?: undefined; + emptySignature: true; + } + | { + signer: WalletSigner; + emptySignature?: false; + } +); export async function buildAndSignMultichainGlvDepositTxn({ chainId, @@ -43,6 +50,9 @@ export async function buildAndSignMultichainGlvDepositTxn({ if (emptySignature) { signature = "0x"; } else { + if (!signer) { + throw new Error("Signer is required when emptySignature is false"); + } signature = await signCreateGlvDeposit({ chainId, srcChainId, diff --git a/src/domain/synthetics/markets/createMultichainGlvWithdrawalTxn.ts b/src/domain/synthetics/markets/createMultichainGlvWithdrawalTxn.ts index 9fc9c23d83..092aa459ed 100644 --- a/src/domain/synthetics/markets/createMultichainGlvWithdrawalTxn.ts +++ b/src/domain/synthetics/markets/createMultichainGlvWithdrawalTxn.ts @@ -16,15 +16,22 @@ import type { CreateGlvWithdrawalParams } from "./types"; type TxnParams = { chainId: ContractsChainId; srcChainId: SourceChainId | undefined; - signer: WalletSigner; relayParams: RelayParamsPayload; - emptySignature?: boolean; account: string; transferRequests: TransferRequests; params: CreateGlvWithdrawalParams; relayerFeeTokenAddress: string; relayerFeeAmount: bigint; -}; +} & ( + | { + signer?: undefined; + emptySignature: true; + } + | { + signer: WalletSigner; + emptySignature?: false; + } +); export async function buildAndSignMultichainGlvWithdrawalTxn({ chainId, @@ -43,6 +50,9 @@ export async function buildAndSignMultichainGlvWithdrawalTxn({ if (emptySignature) { signature = "0x"; } else { + if (!signer) { + throw new Error("Signer is required when emptySignature is false"); + } signature = await signCreateGlvWithdrawal({ chainId, srcChainId, diff --git a/src/domain/synthetics/markets/createMultichainWithdrawalTxn.ts b/src/domain/synthetics/markets/createMultichainWithdrawalTxn.ts index 134b0cd6dc..9217c89022 100644 --- a/src/domain/synthetics/markets/createMultichainWithdrawalTxn.ts +++ b/src/domain/synthetics/markets/createMultichainWithdrawalTxn.ts @@ -16,15 +16,22 @@ import { signCreateWithdrawal } from "./signCreateWithdrawal"; type TxnParams = { chainId: ContractsChainId; srcChainId: SourceChainId | undefined; - signer: WalletSigner; relayParams: RelayParamsPayload; - emptySignature?: boolean; account: string; transferRequests: TransferRequests; params: CreateWithdrawalParams; relayerFeeTokenAddress: string; relayerFeeAmount: bigint; -}; +} & ( + | { + signer?: undefined; + emptySignature: true; + } + | { + signer: WalletSigner; + emptySignature?: false; + } +); export async function buildAndSignMultichainWithdrawalTxn({ chainId, @@ -43,6 +50,9 @@ export async function buildAndSignMultichainWithdrawalTxn({ if (emptySignature) { signature = "0x"; } else { + if (!signer) { + throw new Error("Signer is required when emptySignature is false"); + } signature = await signCreateWithdrawal({ chainId, srcChainId, From 9dc994e1425244e523ff6c71aee6e99fda28de04 Mon Sep 17 00:00:00 2001 From: midas-myth Date: Thu, 11 Dec 2025 15:20:36 +0100 Subject: [PATCH 02/23] Refactor technical fees handling in GmSwapBox components to utilize a unified TechnicalGmFees type. Update fee estimation logic for deposits and withdrawals, enhancing clarity and maintainability. Introduce buildDepositTransferRequests and buildWithdrawalTransferRequests functions for improved transfer request management. --- .../lpTxn/useDepositTransactions.tsx | 127 +++-- .../lpTxn/useLpTransactions.tsx | 14 +- .../useMultichainDepositExpressTxnParams.tsx | 11 +- ...seMultichainWithdrawalExpressTxnParams.tsx | 10 +- .../lpTxn/useWithdrawalTransactions.tsx | 96 ++-- .../useDepositWithdrawalFees.tsx | 36 +- .../useGmSwapSubmitState.tsx | 24 +- .../useTechnicalFeesAsyncResult.tsx | 482 ++++++++++++++++-- .../buildDepositTransferRequests.tsx | 88 ++++ .../buildWithdrawalTransferRequests.tsx | 51 ++ src/domain/multichain/technical-fees-types.ts | 45 ++ .../synthetics/express/relayParamsUtils.ts | 3 - .../markets/createMultichainDepositTxn.ts | 16 +- .../markets/createMultichainGlvDepositTxn.ts | 16 +- .../createMultichainGlvWithdrawalTxn.ts | 16 +- .../markets/createMultichainWithdrawalTxn.ts | 16 +- 16 files changed, 801 insertions(+), 250 deletions(-) create mode 100644 src/domain/multichain/buildDepositTransferRequests.tsx create mode 100644 src/domain/multichain/buildWithdrawalTransferRequests.tsx create mode 100644 src/domain/multichain/technical-fees-types.ts diff --git a/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx b/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx index ae172ab54a..f4dd175bbf 100644 --- a/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx +++ b/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx @@ -3,7 +3,6 @@ import { useCallback, useMemo } from "react"; import { zeroAddress } from "viem"; import type { SettlementChainId } from "config/chains"; -import { DEFAULT_SLIPPAGE_AMOUNT } from "config/factors"; import { usePendingTxns } from "context/PendingTxnsContext/PendingTxnsContext"; import { selectPoolsDetailsFirstTokenAddress, @@ -36,8 +35,9 @@ import { TokensBalancesUpdates, useTokensBalancesUpdates, } from "context/TokensBalancesContext/TokensBalancesContextProvider"; -import { getTransferRequests } from "domain/multichain/getTransferRequests"; +import { buildDepositTransferRequests } from "domain/multichain/buildDepositTransferRequests"; import { GlvBuyTask, GmBuyTask } from "domain/multichain/progress/GmOrGlvBuyProgress"; +import type { TechnicalGmFees } from "domain/multichain/technical-fees-types"; import { toastCustomOrStargateError } from "domain/multichain/toastCustomOrStargateError"; import { TransferRequests } from "domain/multichain/types"; import { @@ -52,8 +52,6 @@ import { createMultichainDepositTxn } from "domain/synthetics/markets/createMult import { createMultichainGlvDepositTxn } from "domain/synthetics/markets/createMultichainGlvDepositTxn"; import { createSourceChainDepositTxn } from "domain/synthetics/markets/createSourceChainDepositTxn"; import { createSourceChainGlvDepositTxn } from "domain/synthetics/markets/createSourceChainGlvDepositTxn"; -import { SourceChainDepositFees } from "domain/synthetics/markets/feeEstimation/estimateSourceChainDepositFees"; -import { SourceChainGlvDepositFees } from "domain/synthetics/markets/feeEstimation/estimateSourceChainGlvDepositFees"; import { ERC20Address, NativeTokenSupportedAddress, TokenBalanceType } from "domain/tokens"; import { helperToast } from "lib/helperToast"; import { @@ -66,13 +64,9 @@ import { } from "lib/metrics"; import { makeUserAnalyticsOrderFailResultHandler, sendUserAnalyticsOrderConfirmClickEvent } from "lib/userAnalytics"; import useWallet from "lib/wallets/useWallet"; -import { getContract } from "sdk/configs/contracts"; import { convertTokenAddress, getWrappedToken } from "sdk/configs/tokens"; -import { ExecutionFee } from "sdk/types/fees"; import { getGlvToken, getGmToken } from "sdk/utils/tokens"; -import { applySlippageToMinOut } from "sdk/utils/trade"; -import type { TechnicalFees } from "../useTechnicalFeesAsyncResult"; import type { UseLpTransactionProps } from "./useLpTransactions"; import { useMultichainDepositExpressTxnParams } from "./useMultichainDepositExpressTxnParams"; @@ -130,16 +124,24 @@ export const useDepositTransactions = ({ return undefined; } - const executionFee = - paySource === "sourceChain" - ? (technicalFees as SourceChainDepositFees | SourceChainGlvDepositFees).executionFee - : (technicalFees as ExecutionFee).feeTokenAmount; + let executionFee: bigint | undefined; + if (technicalFees.kind === "sourceChain" && technicalFees.isDeposit) { + executionFee = technicalFees.fees.executionFee; + } else if (technicalFees.kind === "gmxAccount") { + executionFee = technicalFees.fees.executionFee.feeTokenAmount; + } else if (technicalFees.kind === "settlementChain") { + executionFee = technicalFees.fees.feeTokenAmount; + } + + if (executionFee === undefined) { + return undefined; + } return { ...(rawParams as RawCreateDepositParams), executionFee, }; - }, [rawParams, technicalFees, isDeposit, paySource]); + }, [rawParams, technicalFees, isDeposit]); const gasPaymentTokenAddress = useSelector(selectGasPaymentTokenAddress); const gasPaymentTokenAsCollateralAmount = useMemo((): bigint | undefined => { @@ -254,6 +256,11 @@ export const useDepositTransactions = ({ tokenAddress = convertTokenAddress(chainId, tokenAddress, "native"); const tokenAmount = longTokenAmount! > 0n ? longTokenAmount! : shortTokenAmount!; + const fees = technicalFees.kind === "sourceChain" && technicalFees.isDeposit ? technicalFees.fees : undefined; + if (!fees) { + throw new Error("Technical fees are not set"); + } + promise = createSourceChainDepositTxn({ chainId: chainId as SettlementChainId, srcChainId: srcChainId!, @@ -262,7 +269,7 @@ export const useDepositTransactions = ({ params: rawParams as RawCreateDepositParams, tokenAddress, tokenAmount, - fees: technicalFees as SourceChainDepositFees, + fees, }) .then((res) => { if (res.transactionHash) { @@ -273,7 +280,7 @@ export const useDepositTransactions = ({ token: getGmToken(chainId, (rawParams as RawCreateDepositParams).addresses.market), amount: marketTokenAmount!, settlementChainId: chainId, - estimatedFeeUsd: (technicalFees as SourceChainDepositFees).relayFeeUsd, + estimatedFeeUsd: fees.relayFeeUsd, }) ); } @@ -283,6 +290,7 @@ export const useDepositTransactions = ({ }); } else if (paySource === "gmxAccount") { const expressTxnParams = multichainDepositExpressTxnParams.data; + if (!expressTxnParams) { throw new Error("Express txn params are not set"); } @@ -325,14 +333,19 @@ export const useDepositTransactions = ({ } }); } else if (paySource === "settlementChain") { + const fees = technicalFees?.kind === "settlementChain" ? technicalFees.fees : undefined; + if (!fees) { + throw new Error("Technical fees are not set"); + } + promise = createDepositTxn({ chainId, signer, blockTimestampData, longTokenAmount: longTokenAmount ?? 0n, shortTokenAmount: shortTokenAmount ?? 0n, - executionFee: (technicalFees as ExecutionFee).feeTokenAmount, - executionGasLimit: (technicalFees as ExecutionFee).gasLimit, + executionFee: fees.feeTokenAmount, + executionGasLimit: fees.gasLimit, skipSimulation: shouldDisableValidation, tokensData, metricId: metricData.metricId, @@ -405,6 +418,11 @@ export const useDepositTransactions = ({ throw new Error("Technical fees are not set"); } + const fees = technicalFees.kind === "sourceChain" && technicalFees.isDeposit ? technicalFees.fees : undefined; + if (!fees) { + throw new Error("Technical fees are not set"); + } + if (!longTokenAddress || !shortTokenAddress) { throw new Error("Long or short token address is not set"); } @@ -432,7 +450,7 @@ export const useDepositTransactions = ({ params: rawParams as RawCreateGlvDepositParams, tokenAddress, tokenAmount, - fees: technicalFees as SourceChainGlvDepositFees, + fees, }) .then((res) => { if (res.transactionHash) { @@ -443,7 +461,7 @@ export const useDepositTransactions = ({ token: getGlvToken(chainId, (rawParams as RawCreateGlvDepositParams).addresses.glv), amount: glvTokenAmount!, settlementChainId: chainId, - estimatedFeeUsd: (technicalFees as SourceChainGlvDepositFees).relayFeeUsd, + estimatedFeeUsd: fees.relayFeeUsd, }) ); } @@ -511,6 +529,11 @@ export const useDepositTransactions = ({ ? zeroAddress : shortTokenAddress; + const fees = technicalFees?.kind === "settlementChain" ? technicalFees.fees : undefined; + if (!fees) { + throw new Error("Technical fees are not set"); + } + promise = createGlvDepositTxn({ chainId, signer, @@ -520,8 +543,8 @@ export const useDepositTransactions = ({ longTokenAmount: longTokenAmount ?? 0n, shortTokenAmount: shortTokenAmount ?? 0n, marketTokenAmount: marketTokenAmount ?? 0n, - executionFee: (technicalFees as ExecutionFee).feeTokenAmount, - executionGasLimit: (technicalFees as ExecutionFee).gasLimit, + executionFee: fees.feeTokenAmount, + executionGasLimit: fees.gasLimit, skipSimulation: shouldDisableValidation, tokensData, blockTimestampData, @@ -584,7 +607,7 @@ export const useDepositTransactions = ({ function useDepositTransferRequests({ technicalFees, }: { - technicalFees: TechnicalFees | undefined; + technicalFees: TechnicalGmFees | undefined; }): TransferRequests | undefined { const chainId = useSelector(selectChainId); const { isDeposit } = useSelector(selectPoolsDetailsFlags); @@ -615,52 +638,20 @@ function useDepositTransferRequests({ : undefined; return useMemo((): TransferRequests | undefined => { - if (!isDeposit) { - return undefined; - } - - const vaultAddress = isGlv ? getContract(chainId, "GlvVault") : getContract(chainId, "DepositVault"); - - if (isMarketTokenDeposit) { - return getTransferRequests([ - { - to: vaultAddress, - token: marketTokenAddress, - amount: marketTokenAmount, - }, - ]); - } - - if (paySource === "sourceChain") { - let tokenAddress = - longTokenAmount !== undefined && longTokenAmount > 0n ? initialLongTokenAddress : initialShortTokenAddress; - - let amount = longTokenAmount !== undefined && longTokenAmount > 0n ? longTokenAmount : shortTokenAmount!; - - const estimatedReceivedAmount = (technicalFees as SourceChainDepositFees | SourceChainGlvDepositFees | undefined) - ?.txnEstimatedReceivedAmount; - - if (estimatedReceivedAmount !== undefined && estimatedReceivedAmount > amount) { - return undefined; - } - - amount = applySlippageToMinOut(DEFAULT_SLIPPAGE_AMOUNT, estimatedReceivedAmount ?? amount); - - return getTransferRequests([{ to: vaultAddress, token: tokenAddress, amount }]); - } - - return getTransferRequests([ - { - to: vaultAddress, - token: initialLongTokenAddress, - amount: longTokenAmount, - }, - { - to: vaultAddress, - token: initialShortTokenAddress, - amount: shortTokenAmount, - }, - ]); + return buildDepositTransferRequests({ + isDeposit, + isGlv, + chainId, + paySource, + isMarketTokenDeposit, + marketTokenAddress, + marketTokenAmount, + longTokenAmount, + shortTokenAmount, + initialLongTokenAddress, + initialShortTokenAddress, + technicalFees, + }); }, [ isDeposit, isGlv, diff --git a/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useLpTransactions.tsx b/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useLpTransactions.tsx index 229eab2533..b39a869365 100644 --- a/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useLpTransactions.tsx +++ b/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useLpTransactions.tsx @@ -2,11 +2,7 @@ import { useCallback, useState } from "react"; import { selectPoolsDetailsOperation } from "context/PoolsDetailsContext/selectors"; import { useSelector } from "context/SyntheticsStateContext/utils"; -import type { ExecutionFee } from "domain/synthetics/fees"; -import type { SourceChainDepositFees } from "domain/synthetics/markets/feeEstimation/estimateSourceChainDepositFees"; -import type { SourceChainGlvDepositFees } from "domain/synthetics/markets/feeEstimation/estimateSourceChainGlvDepositFees"; -import { SourceChainGlvWithdrawalFees } from "domain/synthetics/markets/feeEstimation/estimateSourceChainGlvWithdrawalFees"; -import { SourceChainWithdrawalFees } from "domain/synthetics/markets/feeEstimation/estimateSourceChainWithdrawalFees"; +import { TechnicalGmFees } from "domain/multichain/technical-fees-types"; import { useDepositTransactions } from "./useDepositTransactions"; import { useWithdrawalTransactions } from "./useWithdrawalTransactions"; @@ -14,13 +10,7 @@ import { Operation } from "../../types"; export interface UseLpTransactionProps { shouldDisableValidation?: boolean; - technicalFees: - | ExecutionFee - | SourceChainGlvDepositFees - | SourceChainDepositFees - | SourceChainWithdrawalFees - | SourceChainGlvWithdrawalFees - | undefined; + technicalFees: TechnicalGmFees | undefined; } export const useLpTransactions = ( diff --git a/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useMultichainDepositExpressTxnParams.tsx b/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useMultichainDepositExpressTxnParams.tsx index 2f67b80fae..d0a2c30635 100644 --- a/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useMultichainDepositExpressTxnParams.tsx +++ b/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useMultichainDepositExpressTxnParams.tsx @@ -7,7 +7,6 @@ import { buildAndSignMultichainGlvDepositTxn } from "domain/synthetics/markets/c import type { GmPaySource } from "domain/synthetics/markets/types"; import { useChainId } from "lib/chains"; import { AsyncResult } from "lib/useThrottledAsync"; -import useWallet from "lib/wallets/useWallet"; import { DEFAULT_EXPRESS_ORDER_DEADLINE_DURATION } from "sdk/configs/express"; import { nowInSeconds } from "sdk/utils/time"; @@ -27,14 +26,8 @@ export function useMultichainDepositExpressTxnParams({ gasPaymentTokenAsCollateralAmount: bigint | undefined; }): AsyncResult { const { chainId, srcChainId } = useChainId(); - const { signer } = useWallet(); - const enabled = - paySource === "gmxAccount" && - Boolean(params) && - isDeposit && - transferRequests !== undefined && - signer !== undefined; + const enabled = paySource === "gmxAccount" && Boolean(params) && isDeposit && transferRequests !== undefined; const multichainDepositExpressTxnParams = useArbitraryRelayParamsAndPayload({ isGmxAccount: paySource === "gmxAccount", @@ -61,7 +54,6 @@ export function useMultichainDepositExpressTxnParams({ ...relayParams, deadline: BigInt(nowInSeconds() + DEFAULT_EXPRESS_ORDER_DEADLINE_DURATION), }, - signer, transferRequests, }); @@ -84,7 +76,6 @@ export function useMultichainDepositExpressTxnParams({ ...relayParams, deadline: BigInt(nowInSeconds() + DEFAULT_EXPRESS_ORDER_DEADLINE_DURATION), }, - signer, transferRequests, }); diff --git a/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useMultichainWithdrawalExpressTxnParams.tsx b/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useMultichainWithdrawalExpressTxnParams.tsx index a47583ab1c..370caea085 100644 --- a/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useMultichainWithdrawalExpressTxnParams.tsx +++ b/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useMultichainWithdrawalExpressTxnParams.tsx @@ -23,14 +23,8 @@ export function useMultichainWithdrawalExpressTxnParams({ isWithdrawal: boolean; }) { const { chainId, srcChainId } = useChainId(); - const { signer } = useWallet(); - const enabled = - paySource === "gmxAccount" && - isWithdrawal && - Boolean(params) && - transferRequests !== undefined && - signer !== undefined; + const enabled = paySource === "gmxAccount" && isWithdrawal && Boolean(params) && transferRequests !== undefined; const multichainWithdrawalExpressTxnParams = useArbitraryRelayParamsAndPayload({ isGmxAccount: paySource === "gmxAccount", @@ -56,7 +50,6 @@ export function useMultichainWithdrawalExpressTxnParams({ ...relayParams, deadline: BigInt(nowInSeconds() + DEFAULT_EXPRESS_ORDER_DEADLINE_DURATION), }, - signer, transferRequests, }); @@ -78,7 +71,6 @@ export function useMultichainWithdrawalExpressTxnParams({ ...relayParams, deadline: BigInt(nowInSeconds() + DEFAULT_EXPRESS_ORDER_DEADLINE_DURATION), }, - signer, transferRequests, }); diff --git a/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx b/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx index ad916ec9a7..def1c80c0c 100644 --- a/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx +++ b/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx @@ -26,7 +26,7 @@ import { TokensBalancesUpdates, useTokensBalancesUpdates, } from "context/TokensBalancesContext/TokensBalancesContextProvider"; -import { getTransferRequests } from "domain/multichain/getTransferRequests"; +import { buildWithdrawalTransferRequests } from "domain/multichain/buildWithdrawalTransferRequests"; import { GlvSellTask, GmSellTask } from "domain/multichain/progress/GmOrGlvSellProgress"; import { toastCustomOrStargateError } from "domain/multichain/toastCustomOrStargateError"; import { TransferRequests } from "domain/multichain/types"; @@ -42,8 +42,6 @@ import { createMultichainGlvWithdrawalTxn } from "domain/synthetics/markets/crea import { createMultichainWithdrawalTxn } from "domain/synthetics/markets/createMultichainWithdrawalTxn"; import { createSourceChainGlvWithdrawalTxn } from "domain/synthetics/markets/createSourceChainGlvWithdrawalTxn"; import { createSourceChainWithdrawalTxn } from "domain/synthetics/markets/createSourceChainWithdrawalTxn"; -import { SourceChainGlvWithdrawalFees } from "domain/synthetics/markets/feeEstimation/estimateSourceChainGlvWithdrawalFees"; -import { SourceChainWithdrawalFees } from "domain/synthetics/markets/feeEstimation/estimateSourceChainWithdrawalFees"; import { useChainId } from "lib/chains"; import { helperToast } from "lib/helperToast"; import { @@ -54,9 +52,7 @@ import { sendTxnValidationErrorMetric, } from "lib/metrics"; import useWallet from "lib/wallets/useWallet"; -import { getContract } from "sdk/configs/contracts"; import { getWrappedToken } from "sdk/configs/tokens"; -import { ExecutionFee } from "sdk/types/fees"; import { TokenBalanceType } from "sdk/types/tokens"; import { WithdrawalAmounts } from "sdk/types/trade"; import { getGlvToken, getGmToken } from "sdk/utils/tokens"; @@ -115,16 +111,23 @@ export const useWithdrawalTransactions = ({ return undefined; } - const executionFee = - paySource === "sourceChain" - ? (technicalFees as SourceChainWithdrawalFees | SourceChainGlvWithdrawalFees).executionFee - : (technicalFees as ExecutionFee).feeTokenAmount; + let executionFee: bigint | undefined; + if (technicalFees.kind === "sourceChain" && technicalFees.isDeposit) { + executionFee = technicalFees.fees.executionFee; + } else if (technicalFees.kind === "gmxAccount") { + executionFee = technicalFees.fees.executionFee.feeTokenAmount; + } else if (technicalFees.kind === "settlementChain") { + executionFee = technicalFees.fees.feeTokenAmount; + } + if (executionFee === undefined) { + return undefined; + } return { ...(rawParams as RawCreateWithdrawalParams), executionFee, }; - }, [rawParams, technicalFees, isWithdrawal, paySource]); + }, [rawParams, technicalFees, isWithdrawal]); const multichainWithdrawalExpressTxnParams = useMultichainWithdrawalExpressTxnParams({ transferRequests, @@ -226,6 +229,14 @@ export const useWithdrawalTransactions = ({ throw new Error("An error occurred"); } + const fees = + technicalFees?.kind === "sourceChain" && !technicalFees.isDeposit && technicalFees.isGlv + ? technicalFees.fees + : undefined; + if (!fees) { + throw new Error("Technical fees are not set"); + } + promise = createSourceChainGlvWithdrawalTxn({ chainId, srcChainId, @@ -233,7 +244,7 @@ export const useWithdrawalTransactions = ({ transferRequests, params: rawParams as CreateGlvWithdrawalParams, tokenAmount: glvTokenAmount!, - fees: technicalFees as SourceChainGlvWithdrawalFees, + fees, }) .then((res) => { if (res.transactionHash) { @@ -244,7 +255,7 @@ export const useWithdrawalTransactions = ({ token: getGlvToken(chainId, (rawParams as RawCreateGlvWithdrawalParams).addresses.glv), amount: (amounts as WithdrawalAmounts).glvTokenAmount, settlementChainId: chainId, - estimatedFeeUsd: (technicalFees as SourceChainGlvWithdrawalFees).relayFeeUsd, + estimatedFeeUsd: fees.relayFeeUsd, }) ); } @@ -290,11 +301,15 @@ export const useWithdrawalTransactions = ({ } }); } else if (paySource === "settlementChain") { + const fees = technicalFees?.kind === "settlementChain" ? technicalFees.fees : undefined; + if (!fees) { + throw new Error("Technical fees are not set"); + } promise = createGlvWithdrawalTxn({ chainId, signer, params: params as CreateGlvWithdrawalParams, - executionGasLimit: (technicalFees as ExecutionFee).gasLimit, + executionGasLimit: fees.gasLimit, tokensData, setPendingTxns, setPendingWithdrawal, @@ -370,11 +385,19 @@ export const useWithdrawalTransactions = ({ throw new Error("An error occurred"); } + const fees = + technicalFees.kind === "sourceChain" && !technicalFees.isDeposit && !technicalFees.isGlv + ? technicalFees.fees + : undefined; + if (!fees) { + throw new Error("Technical fees are not set"); + } + promise = createSourceChainWithdrawalTxn({ chainId, srcChainId, signer, - fees: technicalFees as SourceChainWithdrawalFees, + fees, transferRequests, params: rawParams as RawCreateWithdrawalParams, tokenAmount: marketTokenAmount!, @@ -387,7 +410,7 @@ export const useWithdrawalTransactions = ({ token: getGmToken(chainId, (rawParams as RawCreateWithdrawalParams).addresses.market), amount: (amounts as WithdrawalAmounts).marketTokenAmount, settlementChainId: chainId, - estimatedFeeUsd: (technicalFees as SourceChainWithdrawalFees).relayFeeUsd, + estimatedFeeUsd: fees.relayFeeUsd, }) ); } @@ -430,11 +453,15 @@ export const useWithdrawalTransactions = ({ } }); } else if (paySource === "settlementChain") { + const fees = technicalFees?.kind === "settlementChain" ? technicalFees.fees : undefined; + if (!fees) { + throw new Error("Technical fees are not set"); + } promise = createWithdrawalTxn({ chainId, signer, marketTokenAmount: marketTokenAmount!, - executionGasLimit: (technicalFees as ExecutionFee).gasLimit, + executionGasLimit: fees.gasLimit, params: params as CreateWithdrawalParams, tokensData, skipSimulation: shouldDisableValidation, @@ -509,33 +536,14 @@ function useWithdrawalTransferRequests(): TransferRequests | undefined { const glvTokenAddress = glvInfo?.glvTokenAddress; return useMemo((): TransferRequests | undefined => { - if (!isWithdrawal) { - return undefined; - } - - if (isGlv) { - if (!glvTokenAddress) { - return undefined; - } - return getTransferRequests([ - { - to: getContract(chainId, "GlvVault"), - token: glvTokenAddress, - amount: glvTokenAmount, - }, - ]); - } - - if (!marketTokenAddress) { - return undefined; - } - - return getTransferRequests([ - { - to: getContract(chainId, "WithdrawalVault"), - token: marketTokenAddress, - amount: marketTokenAmount, - }, - ]); + return buildWithdrawalTransferRequests({ + isWithdrawal, + isGlv, + chainId: chainId, + glvTokenAddress, + glvTokenAmount, + marketTokenAddress, + marketTokenAmount, + }); }, [chainId, glvTokenAddress, glvTokenAmount, isGlv, isWithdrawal, marketTokenAddress, marketTokenAmount]); } diff --git a/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/useDepositWithdrawalFees.tsx b/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/useDepositWithdrawalFees.tsx index 53fc2d049c..fbb149a312 100644 --- a/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/useDepositWithdrawalFees.tsx +++ b/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/useDepositWithdrawalFees.tsx @@ -1,11 +1,9 @@ import { useMemo } from "react"; +import { TechnicalGmFees } from "domain/multichain/technical-fees-types"; import { useGasMultichainUsd, useNativeTokenMultichainUsd } from "domain/multichain/useMultichainQuoteFeeUsd"; -import { ExecutionFee, getFeeItem, getTotalFeeItem, type FeeItem, type GasLimitsConfig } from "domain/synthetics/fees"; +import { getFeeItem, getTotalFeeItem, type FeeItem, type GasLimitsConfig } from "domain/synthetics/fees"; import { GlvInfo } from "domain/synthetics/markets"; -import { SourceChainDepositFees } from "domain/synthetics/markets/feeEstimation/estimateSourceChainDepositFees"; -import { SourceChainGlvDepositFees } from "domain/synthetics/markets/feeEstimation/estimateSourceChainGlvDepositFees"; -import { SourceChainWithdrawalFees } from "domain/synthetics/markets/feeEstimation/estimateSourceChainWithdrawalFees"; import { convertToUsd, getMidPrice, TokensData } from "domain/synthetics/tokens"; import { DepositAmounts, GmSwapFees, WithdrawalAmounts } from "domain/synthetics/trade"; import { ContractsChainId, SourceChainId } from "sdk/configs/chains"; @@ -29,24 +27,18 @@ export const useDepositWithdrawalFees = ({ tokensData: TokensData | undefined; glvInfo: GlvInfo | undefined; isMarketTokenDeposit: boolean; - technicalFees: - | ExecutionFee - | SourceChainGlvDepositFees - | SourceChainDepositFees - | SourceChainWithdrawalFees - | undefined; + technicalFees: TechnicalGmFees | undefined; srcChainId: SourceChainId | undefined; }): { logicalFees?: GmSwapFees } => { const sourceChainEstimatedNativeFeeUsd = useNativeTokenMultichainUsd({ sourceChainTokenAmount: - technicalFees && "txnEstimatedNativeFee" in technicalFees ? technicalFees.txnEstimatedNativeFee : undefined, + technicalFees?.kind === "sourceChain" ? technicalFees.fees.txnEstimatedNativeFee : undefined, sourceChainId: srcChainId, targetChainId: chainId, }); const sourceChainTxnEstimatedGasUsd = useGasMultichainUsd({ - sourceChainGas: - technicalFees && "txnEstimatedGasLimit" in technicalFees ? technicalFees.txnEstimatedGasLimit : undefined, + sourceChainGas: technicalFees?.kind === "sourceChain" ? technicalFees.fees.txnEstimatedGasLimit : undefined, sourceChainId: srcChainId, targetChainId: chainId, }); @@ -66,14 +58,18 @@ export const useDepositWithdrawalFees = ({ shouldRoundUp: true, }); + const wrappedToken = getWrappedToken(chainId); + const wrappedTokenData = tokensData[wrappedToken.address]; + const wrappedTokenPrice = getMidPrice(wrappedTokenData.prices); + let logicalNetworkFeeUsd = 0n; - if ("feeTokenAmount" in technicalFees) { - logicalNetworkFeeUsd = convertToUsd( - technicalFees.feeTokenAmount * -1n, - getWrappedToken(chainId).decimals, - getMidPrice(tokensData[getWrappedToken(chainId).address].prices) - )!; - } else { + + if (technicalFees.kind === "settlementChain") { + const keeperUsd = convertToUsd(technicalFees.fees.feeTokenAmount, wrappedToken.decimals, wrappedTokenPrice)!; + logicalNetworkFeeUsd = keeperUsd * -1n; + } else if (technicalFees.kind === "gmxAccount") { + logicalNetworkFeeUsd = (technicalFees.fees.executionFee.feeUsd + technicalFees.fees.relayFeeUsd) * -1n; + } else if (technicalFees.kind === "sourceChain") { logicalNetworkFeeUsd = ((sourceChainEstimatedNativeFeeUsd ?? 0n) + (sourceChainTxnEstimatedGasUsd ?? 0n)) * -1n; } diff --git a/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/useGmSwapSubmitState.tsx b/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/useGmSwapSubmitState.tsx index ed82b2d3cb..42a72740ad 100644 --- a/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/useGmSwapSubmitState.tsx +++ b/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/useGmSwapSubmitState.tsx @@ -21,14 +21,10 @@ import { selectGasPaymentToken } from "context/SyntheticsStateContext/selectors/ import { selectChainId, selectSrcChainId } from "context/SyntheticsStateContext/selectors/globalSelectors"; import { selectGasPaymentTokenAddress } from "context/SyntheticsStateContext/selectors/settingsSelectors"; import { useSelector } from "context/SyntheticsStateContext/utils"; +import { TechnicalGmFees } from "domain/multichain/technical-fees-types"; import { useSourceChainNativeFeeError } from "domain/multichain/useSourceChainNetworkFeeError"; import { ExpressEstimationInsufficientGasPaymentTokenBalanceError } from "domain/synthetics/express/expressOrderUtils"; -import type { ExecutionFee } from "domain/synthetics/fees"; import type { GlvAndGmMarketsInfoData, GmPaySource, MarketsInfoData } from "domain/synthetics/markets"; -import type { SourceChainDepositFees } from "domain/synthetics/markets/feeEstimation/estimateSourceChainDepositFees"; -import type { SourceChainGlvDepositFees } from "domain/synthetics/markets/feeEstimation/estimateSourceChainGlvDepositFees"; -import { SourceChainGlvWithdrawalFees } from "domain/synthetics/markets/feeEstimation/estimateSourceChainGlvWithdrawalFees"; -import { SourceChainWithdrawalFees } from "domain/synthetics/markets/feeEstimation/estimateSourceChainWithdrawalFees"; import { convertToTokenAmount, type TokenData } from "domain/synthetics/tokens"; import { getCommonError, getGmSwapError } from "domain/synthetics/trade/utils/validation"; import { useHasOutdatedUi } from "lib/useHasOutdatedUi"; @@ -40,20 +36,13 @@ import SpinnerIcon from "img/ic_spinner.svg?react"; import { Operation } from "../types"; import { useLpTransactions } from "./lpTxn/useLpTransactions"; -import { TechnicalFees } from "./useTechnicalFeesAsyncResult"; import { useTokensToApprove } from "./useTokensToApprove"; interface Props { longTokenLiquidityUsd?: bigint | undefined; shortTokenLiquidityUsd?: bigint | undefined; shouldDisableValidation?: boolean; - technicalFees: - | ExecutionFee - | SourceChainGlvDepositFees - | SourceChainDepositFees - | SourceChainWithdrawalFees - | SourceChainGlvWithdrawalFees - | undefined; + technicalFees: TechnicalGmFees | undefined; logicalFees: GmSwapFees | undefined; marketsInfoData?: MarketsInfoData; glvAndMarketsInfoData: GlvAndGmMarketsInfoData; @@ -312,7 +301,7 @@ function useExpressError({ isDeposit, }: { paySource: GmPaySource | undefined; - technicalFees: TechnicalFees | undefined; + technicalFees: TechnicalGmFees | undefined; gasPaymentToken: TokenData | undefined; gasPaymentTokenAddress: string | undefined; longTokenAddress: string | undefined; @@ -330,14 +319,17 @@ function useExpressError({ return undefined; } - const executionFee = technicalFees as ExecutionFee; + const fees = technicalFees.kind === "gmxAccount" ? technicalFees.fees : undefined; + if (!fees) { + return undefined; + } if (gasPaymentToken.prices.minPrice === undefined) { return undefined; } const gasPaymentTokenAmount = convertToTokenAmount( - executionFee.feeUsd, + fees.executionFee.feeUsd + fees.relayFeeUsd, gasPaymentToken.decimals, gasPaymentToken.prices.minPrice ); diff --git a/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/useTechnicalFeesAsyncResult.tsx b/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/useTechnicalFeesAsyncResult.tsx index fe8cdbf695..97effe907a 100644 --- a/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/useTechnicalFeesAsyncResult.tsx +++ b/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/useTechnicalFeesAsyncResult.tsx @@ -7,6 +7,8 @@ import { selectPoolsDetailsMarketOrGlvTokenAmount, selectPoolsDetailsOperation, selectPoolsDetailsPaySource, + selectPoolsDetailsSecondTokenAddress, + selectPoolsDetailsSecondTokenAmount, selectPoolsDetailsSelectedMarketAddressForGlv, } from "context/PoolsDetailsContext/selectors"; import { selectDepositWithdrawalAmounts } from "context/PoolsDetailsContext/selectors/selectDepositWithdrawalAmounts"; @@ -18,48 +20,40 @@ import { selectTokensData, } from "context/SyntheticsStateContext/selectors/globalSelectors"; import { useSelector } from "context/SyntheticsStateContext/utils"; +import { estimateArbitraryRelayFee, getRawBaseRelayerParams } from "domain/multichain/arbitraryRelayParams"; +import { buildDepositTransferRequests } from "domain/multichain/buildDepositTransferRequests"; +import { buildWithdrawalTransferRequests } from "domain/multichain/buildWithdrawalTransferRequests"; +import { TechnicalGmFees } from "domain/multichain/technical-fees-types"; +import { ExpressTransactionBuilder } from "domain/synthetics/express/types"; import { RawCreateDepositParams, RawCreateGlvDepositParams, RawCreateGlvWithdrawalParams, RawCreateWithdrawalParams, } from "domain/synthetics/markets"; +import { buildAndSignMultichainDepositTxn } from "domain/synthetics/markets/createMultichainDepositTxn"; +import { buildAndSignMultichainGlvDepositTxn } from "domain/synthetics/markets/createMultichainGlvDepositTxn"; +import { buildAndSignMultichainGlvWithdrawalTxn } from "domain/synthetics/markets/createMultichainGlvWithdrawalTxn"; +import { buildAndSignMultichainWithdrawalTxn } from "domain/synthetics/markets/createMultichainWithdrawalTxn"; import { estimatePureLpActionExecutionFee } from "domain/synthetics/markets/feeEstimation/estimatePureLpActionExecutionFee"; -import { - estimateSourceChainDepositFees, - SourceChainDepositFees, -} from "domain/synthetics/markets/feeEstimation/estimateSourceChainDepositFees"; -import { - estimateSourceChainGlvDepositFees, - SourceChainGlvDepositFees, -} from "domain/synthetics/markets/feeEstimation/estimateSourceChainGlvDepositFees"; -import { - estimateSourceChainGlvWithdrawalFees, - SourceChainGlvWithdrawalFees, -} from "domain/synthetics/markets/feeEstimation/estimateSourceChainGlvWithdrawalFees"; -import { - estimateSourceChainWithdrawalFees, - SourceChainWithdrawalFees, -} from "domain/synthetics/markets/feeEstimation/estimateSourceChainWithdrawalFees"; +import { estimateSourceChainDepositFees } from "domain/synthetics/markets/feeEstimation/estimateSourceChainDepositFees"; +import { estimateSourceChainGlvDepositFees } from "domain/synthetics/markets/feeEstimation/estimateSourceChainGlvDepositFees"; +import { estimateSourceChainGlvWithdrawalFees } from "domain/synthetics/markets/feeEstimation/estimateSourceChainGlvWithdrawalFees"; +import { estimateSourceChainWithdrawalFees } from "domain/synthetics/markets/feeEstimation/estimateSourceChainWithdrawalFees"; +import { convertToUsd } from "domain/tokens"; import { useChainId } from "lib/chains"; import { usePrevious } from "lib/usePrevious"; import { useThrottledAsync } from "lib/useThrottledAsync"; +import { getPublicClientWithRpc } from "lib/wallets/rainbowKitConfig"; +import { DEFAULT_EXPRESS_ORDER_DEADLINE_DURATION } from "sdk/configs/express"; import { MARKETS } from "sdk/configs/markets"; -import { ExecutionFee } from "sdk/types/fees"; import { WithdrawalAmounts } from "sdk/types/trade"; import { absDiffBps } from "sdk/utils/numbers"; +import { nowInSeconds } from "sdk/utils/time"; import { Operation } from "../types"; -export type TechnicalFees = - | ExecutionFee - | SourceChainGlvDepositFees - | SourceChainDepositFees - | SourceChainWithdrawalFees - | SourceChainGlvWithdrawalFees - | undefined; - -export function useTechnicalFees(): TechnicalFees { +export function useTechnicalFees(): TechnicalGmFees { const { chainId, srcChainId } = useChainId(); const operation = useSelector(selectPoolsDetailsOperation); @@ -72,6 +66,8 @@ export function useTechnicalFees(): TechnicalFees { const firstTokenAddress = useSelector(selectPoolsDetailsFirstTokenAddress); const firstTokenAmount = useSelector(selectPoolsDetailsFirstTokenAmount); + const secondTokenAddress = useSelector(selectPoolsDetailsSecondTokenAddress); + const secondTokenAmount = useSelector(selectPoolsDetailsSecondTokenAmount); const marketOrGlvTokenAmount = useSelector(selectPoolsDetailsMarketOrGlvTokenAmount); const prevPaySource = usePrevious(paySource); @@ -95,12 +91,12 @@ export function useTechnicalFees(): TechnicalFees { const amounts = useSelector(selectDepositWithdrawalAmounts); const technicalFeesAsyncResult = useThrottledAsync( - async (p) => { - if (p.params.paySource === "gmxAccount" || p.params.paySource === "settlementChain") { + async (p): Promise => { + if (p.params.paySource === "settlementChain") { if (p.params.operation === Operation.Deposit) { if (p.params.isGlv) { const castedParams = p.params.rawParams as RawCreateGlvDepositParams; - return estimatePureLpActionExecutionFee({ + const fees = estimatePureLpActionExecutionFee({ action: { operation: Operation.Deposit, isGlv: true, @@ -115,9 +111,14 @@ export function useTechnicalFees(): TechnicalFees { tokensData: p.params.tokensData, gasPrice: p.params.gasPrice, }); + + return { + kind: "settlementChain", + fees, + }; } else { const castedParams = p.params.rawParams as RawCreateDepositParams; - return estimatePureLpActionExecutionFee({ + const fees = estimatePureLpActionExecutionFee({ action: { operation: Operation.Deposit, isGlv: false, @@ -130,11 +131,16 @@ export function useTechnicalFees(): TechnicalFees { tokensData: p.params.tokensData, gasPrice: p.params.gasPrice, }); + + return { + kind: "settlementChain", + fees, + }; } } else if (p.params.operation === Operation.Withdrawal) { if (p.params.isGlv) { const castedParams = p.params.rawParams as RawCreateGlvWithdrawalParams; - return estimatePureLpActionExecutionFee({ + const fees = estimatePureLpActionExecutionFee({ action: { operation: Operation.Withdrawal, isGlv: true, @@ -148,27 +154,362 @@ export function useTechnicalFees(): TechnicalFees { tokensData: p.params.tokensData, gasPrice: p.params.gasPrice, }); + + return { + kind: "settlementChain", + fees, + }; + } else { + const castedParams = p.params.rawParams as RawCreateWithdrawalParams; + const fees = estimatePureLpActionExecutionFee({ + action: { + operation: Operation.Withdrawal, + isGlv: false, + swapsCount: BigInt( + castedParams.addresses.longTokenSwapPath.length + castedParams.addresses.shortTokenSwapPath.length + ), + }, + chainId: p.params.chainId, + gasLimits: p.params.gasLimits, + tokensData: p.params.tokensData, + gasPrice: p.params.gasPrice, + }); + + return { + kind: "settlementChain", + fees, + }; } + } + } else if (p.params.paySource === "gmxAccount") { + if (!p.params.globalExpressParams) { + return undefined; + } + + const { rawBaseRelayParamsPayload, baseRelayFeeSwapParams } = getRawBaseRelayerParams({ + chainId, + account: p.params.rawParams.addresses.receiver, + globalExpressParams: p.params.globalExpressParams, + }); + + if (!rawBaseRelayParamsPayload || !baseRelayFeeSwapParams) { + return undefined; + } + + if (p.params.operation === Operation.Deposit) { + if (p.params.isGlv) { + const castedParams = p.params.rawParams as RawCreateGlvDepositParams; + const executionFee = estimatePureLpActionExecutionFee({ + action: { + operation: Operation.Deposit, + isGlv: true, + marketsCount: BigInt(p.params.glvInfo!.markets.length), + swapsCount: BigInt( + castedParams.addresses.longTokenSwapPath.length + castedParams.addresses.shortTokenSwapPath.length + ), + isMarketTokenDeposit: castedParams.isMarketTokenDeposit, + }, + chainId: p.params.chainId, + gasLimits: p.params.gasLimits, + tokensData: p.params.tokensData, + gasPrice: p.params.gasPrice, + }); + + const transferRequests = buildDepositTransferRequests({ + isDeposit: true, + isGlv: true, + chainId: p.params.chainId, + paySource: p.params.paySource, + isMarketTokenDeposit: castedParams.isMarketTokenDeposit, + marketTokenAddress: p.params.rawParams.addresses.market, + marketTokenAmount: p.params.firstTokenAmount, + longTokenAmount: p.params.firstTokenAmount, + shortTokenAmount: p.params.secondTokenAmount, + initialLongTokenAddress: castedParams.addresses.initialLongToken, + initialShortTokenAddress: castedParams.addresses.initialShortToken, + technicalFees: undefined, + }); + + if (!transferRequests) { + return undefined; + } + + const expressTransactionBuilder: ExpressTransactionBuilder = async ({ relayParams, gasPaymentParams }) => { + return { + txnData: await buildAndSignMultichainGlvDepositTxn({ + chainId: p.params.chainId, + srcChainId: p.params.srcChainId, + emptySignature: true, + signer: undefined, + account: p.params.rawParams.addresses.receiver, + params: { ...castedParams, executionFee: executionFee.feeTokenAmount }, + relayerFeeAmount: gasPaymentParams.relayerFeeAmount, + relayerFeeTokenAddress: gasPaymentParams.relayerFeeTokenAddress, + relayParams: { + ...relayParams, + deadline: BigInt(nowInSeconds() + DEFAULT_EXPRESS_ORDER_DEADLINE_DURATION), + }, + transferRequests, + }), + }; + }; + + const relayFee = await estimateArbitraryRelayFee({ + account: p.params.rawParams.addresses.receiver, + chainId: p.params.chainId, + client: getPublicClientWithRpc(p.params.chainId), + rawRelayParamsPayload: rawBaseRelayParamsPayload, + expressTransactionBuilder: expressTransactionBuilder, + gasPaymentParams: baseRelayFeeSwapParams.gasPaymentParams, + subaccount: undefined, + }); + + const relayFeeUsd = convertToUsd( + relayFee, + p.params.globalExpressParams.relayerFeeToken.decimals, + p.params.globalExpressParams.relayerFeeToken.prices.maxPrice + )!; - const castedParams = p.params.rawParams as RawCreateWithdrawalParams; - return estimatePureLpActionExecutionFee({ - action: { - operation: Operation.Withdrawal, + return { + kind: "gmxAccount", + fees: { + executionFee, + relayFeeUsd, + }, + }; + } else { + const castedParams = p.params.rawParams as RawCreateDepositParams; + const executionFee = estimatePureLpActionExecutionFee({ + action: { + operation: Operation.Deposit, + isGlv: false, + swapsCount: BigInt( + castedParams.addresses.longTokenSwapPath.length + castedParams.addresses.shortTokenSwapPath.length + ), + }, + chainId: p.params.chainId, + gasLimits: p.params.gasLimits, + tokensData: p.params.tokensData, + gasPrice: p.params.gasPrice, + }); + + const transferRequests = buildDepositTransferRequests({ + isDeposit: true, isGlv: false, - swapsCount: BigInt( - castedParams.addresses.longTokenSwapPath.length + castedParams.addresses.shortTokenSwapPath.length - ), - }, - chainId: p.params.chainId, - gasLimits: p.params.gasLimits, - tokensData: p.params.tokensData, - gasPrice: p.params.gasPrice, - }); + chainId: p.params.chainId, + paySource: p.params.paySource, + isMarketTokenDeposit: false, + marketTokenAddress: undefined, + marketTokenAmount: 0n, + longTokenAmount: p.params.firstTokenAmount, + shortTokenAmount: p.params.secondTokenAmount, + initialLongTokenAddress: castedParams.addresses.initialLongToken, + initialShortTokenAddress: castedParams.addresses.initialShortToken, + technicalFees: undefined, + }); + + if (!transferRequests) { + return undefined; + } + + const expressTransactionBuilder: ExpressTransactionBuilder = async ({ relayParams, gasPaymentParams }) => { + return { + txnData: await buildAndSignMultichainDepositTxn({ + chainId: p.params.chainId, + srcChainId: p.params.srcChainId, + emptySignature: true, + signer: undefined, + account: p.params.rawParams.addresses.receiver, + params: { ...castedParams, executionFee: executionFee.feeTokenAmount }, + relayerFeeAmount: gasPaymentParams.relayerFeeAmount, + relayerFeeTokenAddress: gasPaymentParams.relayerFeeTokenAddress, + relayParams: { + ...relayParams, + deadline: BigInt(nowInSeconds() + DEFAULT_EXPRESS_ORDER_DEADLINE_DURATION), + }, + transferRequests, + }), + }; + }; + + const relayFee = await estimateArbitraryRelayFee({ + account: p.params.rawParams.addresses.receiver, + chainId: p.params.chainId, + client: getPublicClientWithRpc(p.params.chainId), + rawRelayParamsPayload: rawBaseRelayParamsPayload, + expressTransactionBuilder: expressTransactionBuilder, + gasPaymentParams: baseRelayFeeSwapParams.gasPaymentParams, + subaccount: undefined, + }); + + const relayFeeUsd = convertToUsd( + relayFee, + p.params.globalExpressParams.relayerFeeToken.decimals, + p.params.globalExpressParams.relayerFeeToken.prices.maxPrice + )!; + + return { + kind: "gmxAccount", + fees: { + executionFee, + relayFeeUsd, + }, + }; + } + } else if (p.params.operation === Operation.Withdrawal) { + if (p.params.isGlv) { + const castedParams = p.params.rawParams as RawCreateGlvWithdrawalParams; + const fees = estimatePureLpActionExecutionFee({ + action: { + operation: Operation.Withdrawal, + isGlv: true, + marketsCount: BigInt(p.params.glvInfo!.markets.length), + swapsCount: BigInt( + castedParams.addresses.longTokenSwapPath.length + castedParams.addresses.shortTokenSwapPath.length + ), + }, + chainId: p.params.chainId, + gasLimits: p.params.gasLimits, + tokensData: p.params.tokensData, + gasPrice: p.params.gasPrice, + }); + + const transferRequests = buildWithdrawalTransferRequests({ + isWithdrawal: true, + isGlv: true, + chainId: p.params.chainId, + glvTokenAddress: castedParams.addresses.glv, + glvTokenAmount: p.params.marketTokenAmount, + marketTokenAddress: undefined, + marketTokenAmount: 0n, + }); + + if (!transferRequests) { + return undefined; + } + + const expressTransactionBuilder: ExpressTransactionBuilder = async ({ relayParams, gasPaymentParams }) => { + return { + txnData: await buildAndSignMultichainGlvWithdrawalTxn({ + chainId: p.params.chainId, + srcChainId: p.params.srcChainId, + emptySignature: true, + signer: undefined, + account: p.params.rawParams.addresses.receiver, + params: { ...castedParams, executionFee: fees.feeTokenAmount }, + relayerFeeAmount: gasPaymentParams.relayerFeeAmount, + relayerFeeTokenAddress: gasPaymentParams.relayerFeeTokenAddress, + relayParams: { + ...relayParams, + deadline: BigInt(nowInSeconds() + DEFAULT_EXPRESS_ORDER_DEADLINE_DURATION), + }, + transferRequests, + }), + }; + }; + + const relayFee = await estimateArbitraryRelayFee({ + account: p.params.rawParams.addresses.receiver, + chainId: p.params.chainId, + client: getPublicClientWithRpc(p.params.chainId), + rawRelayParamsPayload: rawBaseRelayParamsPayload, + expressTransactionBuilder: expressTransactionBuilder, + gasPaymentParams: baseRelayFeeSwapParams.gasPaymentParams, + subaccount: undefined, + }); + + const relayFeeUsd = convertToUsd( + relayFee, + p.params.globalExpressParams.relayerFeeToken.decimals, + p.params.globalExpressParams.relayerFeeToken.prices.maxPrice + )!; + + return { + kind: "gmxAccount", + fees: { + executionFee: fees, + relayFeeUsd, + }, + }; + } else { + const castedParams = p.params.rawParams as RawCreateWithdrawalParams; + const fees = estimatePureLpActionExecutionFee({ + action: { + operation: Operation.Withdrawal, + isGlv: false, + swapsCount: BigInt( + castedParams.addresses.longTokenSwapPath.length + castedParams.addresses.shortTokenSwapPath.length + ), + }, + chainId: p.params.chainId, + gasLimits: p.params.gasLimits, + tokensData: p.params.tokensData, + gasPrice: p.params.gasPrice, + }); + + const transferRequests = buildWithdrawalTransferRequests({ + isWithdrawal: true, + isGlv: false, + chainId: p.params.chainId, + glvTokenAddress: undefined, + glvTokenAmount: 0n, + marketTokenAddress: castedParams.addresses.market, + marketTokenAmount: p.params.marketTokenAmount, + }); + + if (!transferRequests) { + return undefined; + } + + const expressTransactionBuilder: ExpressTransactionBuilder = async ({ relayParams, gasPaymentParams }) => { + return { + txnData: await buildAndSignMultichainWithdrawalTxn({ + chainId: p.params.chainId, + srcChainId: p.params.srcChainId, + emptySignature: true, + signer: undefined as any, + account: p.params.rawParams.addresses.receiver, + params: { ...castedParams, executionFee: fees.feeTokenAmount }, + relayerFeeAmount: gasPaymentParams.relayerFeeAmount, + relayerFeeTokenAddress: gasPaymentParams.relayerFeeTokenAddress, + relayParams: { + ...relayParams, + deadline: BigInt(nowInSeconds() + DEFAULT_EXPRESS_ORDER_DEADLINE_DURATION), + }, + transferRequests, + }), + }; + }; + + const relayFee = await estimateArbitraryRelayFee({ + account: p.params.rawParams.addresses.receiver, + chainId: p.params.chainId, + client: getPublicClientWithRpc(p.params.chainId), + rawRelayParamsPayload: rawBaseRelayParamsPayload, + expressTransactionBuilder: expressTransactionBuilder, + gasPaymentParams: baseRelayFeeSwapParams.gasPaymentParams, + subaccount: undefined, + }); + + const relayFeeUsd = convertToUsd( + relayFee, + p.params.globalExpressParams.relayerFeeToken.decimals, + p.params.globalExpressParams.relayerFeeToken.prices.maxPrice + )!; + + return { + kind: "gmxAccount", + fees: { + executionFee: fees, + relayFeeUsd, + }, + }; + } } } else if (p.params.paySource === "sourceChain") { if ( - p.params.tokenAddress === undefined || - p.params.tokenAmount === undefined || + p.params.firstTokenAddress === undefined || + p.params.firstTokenAmount === undefined || !p.params.globalExpressParams ) { return undefined; @@ -176,25 +517,38 @@ export function useTechnicalFees(): TechnicalFees { if (p.params.operation === Operation.Deposit) { if (p.params.isGlv) { const castedParams = p.params.rawParams as RawCreateGlvDepositParams; - return await estimateSourceChainGlvDepositFees({ + const fees = await estimateSourceChainGlvDepositFees({ chainId: p.params.chainId as SettlementChainId, srcChainId: p.params.srcChainId as SourceChainId, params: castedParams, - tokenAddress: p.params.tokenAddress, - tokenAmount: p.params.tokenAmount, + tokenAddress: p.params.firstTokenAddress, + tokenAmount: p.params.firstTokenAmount, globalExpressParams: p.params.globalExpressParams, glvMarketCount: BigInt(p.params.glvInfo!.markets.length), }); + + return { + kind: "sourceChain", + isGlv: true, + isDeposit: true, + fees, + }; } else { const castedParams = p.params.rawParams as RawCreateDepositParams; - return await estimateSourceChainDepositFees({ + const fees = await estimateSourceChainDepositFees({ chainId: p.params.chainId as SettlementChainId, srcChainId: p.params.srcChainId as SourceChainId, params: castedParams, - tokenAddress: p.params.tokenAddress, - tokenAmount: p.params.tokenAmount, + tokenAddress: p.params.firstTokenAddress, + tokenAmount: p.params.firstTokenAmount, globalExpressParams: p.params.globalExpressParams, }); + return { + kind: "sourceChain", + isGlv: false, + isDeposit: true, + fees, + }; } } else if (p.params.operation === Operation.Withdrawal) { if (p.params.isGlv) { @@ -205,7 +559,7 @@ export function useTechnicalFees(): TechnicalFees { const outputShortTokenAddress = glvWithdrawalAmounts.shortTokenSwapPathStats?.tokenOutAddress ?? glvInfo!.shortTokenAddress; - return await estimateSourceChainGlvWithdrawalFees({ + const fees = await estimateSourceChainGlvWithdrawalFees({ chainId: p.params.chainId as SettlementChainId, srcChainId: p.params.srcChainId as SourceChainId, params: castedParams, @@ -216,6 +570,13 @@ export function useTechnicalFees(): TechnicalFees { outputLongTokenAddress, outputShortTokenAddress, }); + + return { + kind: "sourceChain", + isGlv: true, + isDeposit: false, + fees, + }; } else { const castedParams = p.params.rawParams as RawCreateWithdrawalParams; if (!p.params.amounts) { @@ -231,7 +592,7 @@ export function useTechnicalFees(): TechnicalFees { gmWithdrawalAmounts.shortTokenSwapPathStats?.tokenOutAddress ?? MARKETS[p.params.chainId][p.params.rawParams.addresses.market].shortTokenAddress; - return await estimateSourceChainWithdrawalFees({ + const fees = await estimateSourceChainWithdrawalFees({ chainId: p.params.chainId as SettlementChainId, srcChainId: p.params.srcChainId as SourceChainId, params: castedParams, @@ -241,6 +602,13 @@ export function useTechnicalFees(): TechnicalFees { outputLongTokenAddress, outputShortTokenAddress, }); + + return { + kind: "sourceChain", + isGlv: false, + isDeposit: false, + fees, + }; } } } @@ -256,8 +624,10 @@ export function useTechnicalFees(): TechnicalFees { glvInfo, paySource, srcChainId, - tokenAddress: firstTokenAddress, - tokenAmount: firstTokenAmount, + firstTokenAddress, + firstTokenAmount, + secondTokenAddress, + secondTokenAmount, marketTokenAmount: marketOrGlvTokenAmount, operation, amounts, diff --git a/src/domain/multichain/buildDepositTransferRequests.tsx b/src/domain/multichain/buildDepositTransferRequests.tsx new file mode 100644 index 0000000000..169ffd5c6b --- /dev/null +++ b/src/domain/multichain/buildDepositTransferRequests.tsx @@ -0,0 +1,88 @@ +import type { ContractsChainId } from "config/chains"; +import { getContract } from "config/contracts"; +import { DEFAULT_SLIPPAGE_AMOUNT } from "config/factors"; +import { getTransferRequests } from "domain/multichain/getTransferRequests"; +import type { TechnicalGmFees } from "domain/multichain/technical-fees-types"; +import type { TransferRequests } from "domain/multichain/types"; +import type { GmPaySource } from "domain/synthetics/markets"; +import { applySlippageToMinOut } from "sdk/utils/trade"; + +export function buildDepositTransferRequests({ + isDeposit, + isGlv, + chainId, + paySource, + isMarketTokenDeposit, + marketTokenAddress, + marketTokenAmount, + longTokenAmount, + shortTokenAmount, + initialLongTokenAddress, + initialShortTokenAddress, + technicalFees, +}: { + isDeposit: boolean; + isGlv: boolean; + chainId: ContractsChainId; + paySource: GmPaySource; + isMarketTokenDeposit: boolean; + marketTokenAddress: string | undefined; + marketTokenAmount: bigint; + longTokenAmount: bigint | undefined; + shortTokenAmount: bigint | undefined; + initialLongTokenAddress: string | undefined; + initialShortTokenAddress: string | undefined; + /** + * Used for source chain deposit to adjust the transfer amount + */ + technicalFees: TechnicalGmFees | undefined; +}): TransferRequests | undefined { + if (!isDeposit) { + return undefined; + } + + const vaultAddress = isGlv ? getContract(chainId, "GlvVault") : getContract(chainId, "DepositVault"); + + if (isMarketTokenDeposit) { + return getTransferRequests([ + { + to: vaultAddress, + token: marketTokenAddress, + amount: marketTokenAmount, + }, + ]); + } + + if (paySource === "sourceChain") { + let tokenAddress = + longTokenAmount !== undefined && longTokenAmount > 0n ? initialLongTokenAddress : initialShortTokenAddress; + + let amount = longTokenAmount !== undefined && longTokenAmount > 0n ? longTokenAmount : shortTokenAmount!; + + const estimatedReceivedAmount = + technicalFees?.kind === "sourceChain" && technicalFees.isDeposit + ? technicalFees.fees.txnEstimatedReceivedAmount + : undefined; + + if (estimatedReceivedAmount !== undefined && estimatedReceivedAmount > amount) { + return undefined; + } + + amount = applySlippageToMinOut(DEFAULT_SLIPPAGE_AMOUNT, estimatedReceivedAmount ?? amount); + + return getTransferRequests([{ to: vaultAddress, token: tokenAddress, amount }]); + } + + return getTransferRequests([ + { + to: vaultAddress, + token: initialLongTokenAddress, + amount: longTokenAmount, + }, + { + to: vaultAddress, + token: initialShortTokenAddress, + amount: shortTokenAmount, + }, + ]); +} diff --git a/src/domain/multichain/buildWithdrawalTransferRequests.tsx b/src/domain/multichain/buildWithdrawalTransferRequests.tsx new file mode 100644 index 0000000000..9d4d40ecaf --- /dev/null +++ b/src/domain/multichain/buildWithdrawalTransferRequests.tsx @@ -0,0 +1,51 @@ +import type { ContractsChainId } from "config/chains"; +import { getContract } from "config/contracts"; +import { getTransferRequests } from "domain/multichain/getTransferRequests"; +import type { TransferRequests } from "domain/multichain/types"; + +export function buildWithdrawalTransferRequests({ + isWithdrawal, + isGlv, + chainId, + glvTokenAddress, + glvTokenAmount, + marketTokenAddress, + marketTokenAmount, +}: { + isWithdrawal: boolean; + isGlv: boolean; + chainId: ContractsChainId; + glvTokenAddress: string | undefined; + glvTokenAmount: bigint; + marketTokenAddress: string | undefined; + marketTokenAmount: bigint; +}): TransferRequests | undefined { + if (!isWithdrawal) { + return undefined; + } + + if (isGlv) { + if (!glvTokenAddress) { + return undefined; + } + return getTransferRequests([ + { + to: getContract(chainId, "GlvVault"), + token: glvTokenAddress, + amount: glvTokenAmount, + }, + ]); + } + + if (!marketTokenAddress) { + return undefined; + } + + return getTransferRequests([ + { + to: getContract(chainId, "WithdrawalVault"), + token: marketTokenAddress, + amount: marketTokenAmount, + }, + ]); +} diff --git a/src/domain/multichain/technical-fees-types.ts b/src/domain/multichain/technical-fees-types.ts new file mode 100644 index 0000000000..943838e90c --- /dev/null +++ b/src/domain/multichain/technical-fees-types.ts @@ -0,0 +1,45 @@ +import type { SourceChainDepositFees } from "domain/synthetics/markets/feeEstimation/estimateSourceChainDepositFees"; +import type { SourceChainGlvDepositFees } from "domain/synthetics/markets/feeEstimation/estimateSourceChainGlvDepositFees"; +import type { SourceChainGlvWithdrawalFees } from "domain/synthetics/markets/feeEstimation/estimateSourceChainGlvWithdrawalFees"; +import type { SourceChainWithdrawalFees } from "domain/synthetics/markets/feeEstimation/estimateSourceChainWithdrawalFees"; +import type { ExecutionFee } from "sdk/types/fees"; + +type SameChainGmFees = { + kind: "settlementChain"; + fees: ExecutionFee; +}; + +type GmxAccountGmFees = { + kind: "gmxAccount"; + fees: { + executionFee: ExecutionFee; + relayFeeUsd: bigint; + }; +}; + +type SourceChainGmFees = { + kind: "sourceChain"; +} & ( + | { + isGlv: false; + isDeposit: false; + fees: SourceChainWithdrawalFees; + } + | { + isGlv: false; + isDeposit: true; + fees: SourceChainDepositFees; + } + | { + isGlv: true; + isDeposit: false; + fees: SourceChainGlvWithdrawalFees; + } + | { + isGlv: true; + isDeposit: true; + fees: SourceChainGlvDepositFees; + } +); + +export type TechnicalGmFees = SameChainGmFees | GmxAccountGmFees | SourceChainGmFees | undefined; diff --git a/src/domain/synthetics/express/relayParamsUtils.ts b/src/domain/synthetics/express/relayParamsUtils.ts index 80f528d845..11d9dd4993 100644 --- a/src/domain/synthetics/express/relayParamsUtils.ts +++ b/src/domain/synthetics/express/relayParamsUtils.ts @@ -204,7 +204,6 @@ export function getRawRelayerParams({ feeParams, externalCalls, tokenPermits, - // marketsInfoData, }: { chainId: ContractsChainId; gasPaymentTokenAddress: string; @@ -212,7 +211,6 @@ export function getRawRelayerParams({ feeParams: RelayFeePayload; externalCalls: ExternalCallsPayload; tokenPermits: SignedTokenPermit[]; - // marketsInfoData: MarketsInfoData; }): RawRelayParamsPayload { const oracleParams = getOracleParamsForRelayParams({ chainId, @@ -220,7 +218,6 @@ export function getRawRelayerParams({ feeSwapPath: feeParams.feeSwapPath, gasPaymentTokenAddress, relayerFeeTokenAddress, - // marketsInfoData, }); const relayParamsPayload: RawRelayParamsPayload = { diff --git a/src/domain/synthetics/markets/createMultichainDepositTxn.ts b/src/domain/synthetics/markets/createMultichainDepositTxn.ts index 3ec2fed01d..6d9160a726 100644 --- a/src/domain/synthetics/markets/createMultichainDepositTxn.ts +++ b/src/domain/synthetics/markets/createMultichainDepositTxn.ts @@ -16,15 +16,22 @@ import { signCreateDeposit } from "./signCreateDeposit"; type TxnParams = { chainId: ContractsChainId; srcChainId: SourceChainId | undefined; - signer: WalletSigner; relayParams: RelayParamsPayload; - emptySignature?: boolean; account: string; transferRequests: TransferRequests; params: CreateDepositParams; relayerFeeTokenAddress: string; relayerFeeAmount: bigint; -}; +} & ( + | { + signer?: undefined; + emptySignature: true; + } + | { + signer: WalletSigner; + emptySignature?: false; + } +); export async function buildAndSignMultichainDepositTxn({ chainId, @@ -43,6 +50,9 @@ export async function buildAndSignMultichainDepositTxn({ if (emptySignature) { signature = "0x"; } else { + if (!signer) { + throw new Error("Signer is required when emptySignature is false"); + } signature = await signCreateDeposit({ chainId, srcChainId, diff --git a/src/domain/synthetics/markets/createMultichainGlvDepositTxn.ts b/src/domain/synthetics/markets/createMultichainGlvDepositTxn.ts index 341701851f..f1f203ba4b 100644 --- a/src/domain/synthetics/markets/createMultichainGlvDepositTxn.ts +++ b/src/domain/synthetics/markets/createMultichainGlvDepositTxn.ts @@ -16,15 +16,22 @@ import { signCreateGlvDeposit } from "./signCreateGlvDeposit"; export type CreateMultichainGlvDepositParams = { chainId: ContractsChainId; srcChainId: SourceChainId | undefined; - signer: WalletSigner; relayParams: RelayParamsPayload; - emptySignature?: boolean; account: string; transferRequests: TransferRequests; params: CreateGlvDepositParams; relayerFeeTokenAddress: string; relayerFeeAmount: bigint; -}; +} & ( + | { + signer?: undefined; + emptySignature: true; + } + | { + signer: WalletSigner; + emptySignature?: false; + } +); export async function buildAndSignMultichainGlvDepositTxn({ chainId, @@ -43,6 +50,9 @@ export async function buildAndSignMultichainGlvDepositTxn({ if (emptySignature) { signature = "0x"; } else { + if (!signer) { + throw new Error("Signer is required when emptySignature is false"); + } signature = await signCreateGlvDeposit({ chainId, srcChainId, diff --git a/src/domain/synthetics/markets/createMultichainGlvWithdrawalTxn.ts b/src/domain/synthetics/markets/createMultichainGlvWithdrawalTxn.ts index 9fc9c23d83..092aa459ed 100644 --- a/src/domain/synthetics/markets/createMultichainGlvWithdrawalTxn.ts +++ b/src/domain/synthetics/markets/createMultichainGlvWithdrawalTxn.ts @@ -16,15 +16,22 @@ import type { CreateGlvWithdrawalParams } from "./types"; type TxnParams = { chainId: ContractsChainId; srcChainId: SourceChainId | undefined; - signer: WalletSigner; relayParams: RelayParamsPayload; - emptySignature?: boolean; account: string; transferRequests: TransferRequests; params: CreateGlvWithdrawalParams; relayerFeeTokenAddress: string; relayerFeeAmount: bigint; -}; +} & ( + | { + signer?: undefined; + emptySignature: true; + } + | { + signer: WalletSigner; + emptySignature?: false; + } +); export async function buildAndSignMultichainGlvWithdrawalTxn({ chainId, @@ -43,6 +50,9 @@ export async function buildAndSignMultichainGlvWithdrawalTxn({ if (emptySignature) { signature = "0x"; } else { + if (!signer) { + throw new Error("Signer is required when emptySignature is false"); + } signature = await signCreateGlvWithdrawal({ chainId, srcChainId, diff --git a/src/domain/synthetics/markets/createMultichainWithdrawalTxn.ts b/src/domain/synthetics/markets/createMultichainWithdrawalTxn.ts index 134b0cd6dc..9217c89022 100644 --- a/src/domain/synthetics/markets/createMultichainWithdrawalTxn.ts +++ b/src/domain/synthetics/markets/createMultichainWithdrawalTxn.ts @@ -16,15 +16,22 @@ import { signCreateWithdrawal } from "./signCreateWithdrawal"; type TxnParams = { chainId: ContractsChainId; srcChainId: SourceChainId | undefined; - signer: WalletSigner; relayParams: RelayParamsPayload; - emptySignature?: boolean; account: string; transferRequests: TransferRequests; params: CreateWithdrawalParams; relayerFeeTokenAddress: string; relayerFeeAmount: bigint; -}; +} & ( + | { + signer?: undefined; + emptySignature: true; + } + | { + signer: WalletSigner; + emptySignature?: false; + } +); export async function buildAndSignMultichainWithdrawalTxn({ chainId, @@ -43,6 +50,9 @@ export async function buildAndSignMultichainWithdrawalTxn({ if (emptySignature) { signature = "0x"; } else { + if (!signer) { + throw new Error("Signer is required when emptySignature is false"); + } signature = await signCreateWithdrawal({ chainId, srcChainId, From c7c347252b9eb9596ef6deb89f1398d914c0d388 Mon Sep 17 00:00:00 2001 From: midas-myth Date: Fri, 12 Dec 2025 16:18:39 +0100 Subject: [PATCH 03/23] Refactor deposit and withdrawal transaction hooks to improve error handling and selector usage. Removed unnecessary account and marketInfo checks, streamlined conditions for order submission, and updated token data selectors for consistency. Enhanced logic for determining best GM market based on amount changes. --- .../lpTxn/useDepositTransactions.tsx | 73 ++++++++------ .../lpTxn/useWithdrawalTransactions.tsx | 94 +++++++++---------- .../MarketStats/hooks/useBestGmPoolForGlv.ts | 36 ++++--- .../selectors/selectPoolsDetailsParams.tsx | 10 +- 4 files changed, 114 insertions(+), 99 deletions(-) diff --git a/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx b/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx index f4dd175bbf..5bf57c05e5 100644 --- a/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx +++ b/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx @@ -19,7 +19,6 @@ import { selectPoolsDetailsSelectedMarketAddressForGlv, selectPoolsDetailsSelectedMarketInfoForGlv, selectPoolsDetailsShortTokenAddress, - selectPoolsDetailsTradeTokensDataWithSourceChainBalances, } from "context/PoolsDetailsContext/selectors"; import { selectDepositWithdrawalAmounts } from "context/PoolsDetailsContext/selectors/selectDepositWithdrawalAmounts"; import { selectPoolsDetailsParams } from "context/PoolsDetailsContext/selectors/selectPoolsDetailsParams"; @@ -28,6 +27,7 @@ import { selectBlockTimestampData, selectChainId, selectSrcChainId, + selectTokensData, } from "context/SyntheticsStateContext/selectors/globalSelectors"; import { selectGasPaymentTokenAddress } from "context/SyntheticsStateContext/selectors/settingsSelectors"; import { useSelector } from "context/SyntheticsStateContext/utils"; @@ -80,7 +80,7 @@ export const useDepositTransactions = ({ } => { const chainId = useSelector(selectChainId); const srcChainId = useSelector(selectSrcChainId); - const { signer, account } = useWallet(); + const { signer } = useWallet(); const { setPendingDeposit } = useSyntheticsEvents(); const { addOptimisticTokensBalancesUpdates } = useTokensBalancesUpdates(); const { setPendingTxns } = usePendingTxns(); @@ -97,7 +97,7 @@ export const useDepositTransactions = ({ const paySource = useSelector(selectPoolsDetailsPaySource); const selectedMarketForGlv = useSelector(selectPoolsDetailsSelectedMarketAddressForGlv); - const tokensData = useSelector(selectPoolsDetailsTradeTokensDataWithSourceChainBalances); + const tokensData = useSelector(selectTokensData); const amounts = useSelector(selectDepositWithdrawalAmounts); const { @@ -224,7 +224,7 @@ export const useDepositTransactions = ({ const onCreateGmDeposit = useCallback( async function onCreateGmDeposit(): Promise { - if (!isDeposit) { + if (!isDeposit || isGlv) { return Promise.reject(); } @@ -232,7 +232,7 @@ export const useDepositTransactions = ({ sendOrderSubmittedMetric(metricData.metricId); - if (!tokensData || !account || !signer || !rawParams || !transferRequests) { + if (!signer || !rawParams) { helperToast.error(t`Error submitting order`); sendTxnValidationErrorMetric(metricData.metricId); return Promise.resolve(); @@ -243,12 +243,14 @@ export const useDepositTransactions = ({ let promise: Promise; if (paySource === "sourceChain") { - if (longTokenAmount! > 0n && shortTokenAmount! > 0n) { - throw new Error("Pay source sourceChain does not support both long and short token deposits"); + if (!transferRequests) { + helperToast.error(t`Error submitting order`); + sendTxnValidationErrorMetric(metricData.metricId); + return; } - if (!technicalFees) { - throw new Error("Technical fees are not set"); + if (longTokenAmount! > 0n && shortTokenAmount! > 0n) { + throw new Error("Pay source sourceChain does not support both long and short token deposits"); } let tokenAddress: ERC20Address | NativeTokenSupportedAddress = @@ -256,7 +258,7 @@ export const useDepositTransactions = ({ tokenAddress = convertTokenAddress(chainId, tokenAddress, "native"); const tokenAmount = longTokenAmount! > 0n ? longTokenAmount! : shortTokenAmount!; - const fees = technicalFees.kind === "sourceChain" && technicalFees.isDeposit ? technicalFees.fees : undefined; + const fees = technicalFees?.kind === "sourceChain" && technicalFees.isDeposit ? technicalFees.fees : undefined; if (!fees) { throw new Error("Technical fees are not set"); } @@ -290,9 +292,10 @@ export const useDepositTransactions = ({ }); } else if (paySource === "gmxAccount") { const expressTxnParams = multichainDepositExpressTxnParams.data; - - if (!expressTxnParams) { - throw new Error("Express txn params are not set"); + if (!transferRequests || !expressTxnParams) { + helperToast.error(t`Error submitting order`); + sendTxnValidationErrorMetric(metricData.metricId); + return; } promise = createMultichainDepositTxn({ @@ -334,8 +337,10 @@ export const useDepositTransactions = ({ }); } else if (paySource === "settlementChain") { const fees = technicalFees?.kind === "settlementChain" ? technicalFees.fees : undefined; - if (!fees) { - throw new Error("Technical fees are not set"); + if (!fees || !tokensData) { + helperToast.error(t`Error submitting order`); + sendTxnValidationErrorMetric(metricData.metricId); + return; } promise = createDepositTxn({ @@ -364,9 +369,9 @@ export const useDepositTransactions = ({ }, [ isDeposit, + isGlv, getDepositMetricData, tokensData, - account, signer, rawParams, transferRequests, @@ -380,19 +385,19 @@ export const useDepositTransactions = ({ srcChainId, setMultichainTransferProgress, marketTokenAmount, - multichainDepositExpressTxnParams, + multichainDepositExpressTxnParams.data, params, + addOptimisticTokensBalancesUpdates, + setPendingDeposit, blockTimestampData, shouldDisableValidation, setPendingTxns, - setPendingDeposit, - addOptimisticTokensBalancesUpdates, ] ); const onCreateGlvDeposit = useCallback( async function onCreateGlvDeposit(): Promise { - if (!isDeposit) { + if (!isDeposit || !isGlv) { return Promise.reject(); } @@ -400,7 +405,7 @@ export const useDepositTransactions = ({ sendOrderSubmittedMetric(metricData.metricId); - if (!account || !marketInfo || !amounts || !tokensData || !signer || (isGlv && !rawParams) || !transferRequests) { + if (!signer || !rawParams) { helperToast.error(t`Error submitting order`); sendTxnValidationErrorMetric(metricData.metricId); return Promise.resolve(); @@ -410,12 +415,14 @@ export const useDepositTransactions = ({ let promise: Promise; if (paySource === "sourceChain") { - if (longTokenAmount! > 0n && shortTokenAmount! > 0n) { - throw new Error("Pay source sourceChain does not support both long and short token deposits"); + if (!transferRequests || !technicalFees) { + helperToast.error(t`Error submitting order`); + sendTxnValidationErrorMetric(metricData.metricId); + return; } - if (!technicalFees) { - throw new Error("Technical fees are not set"); + if (longTokenAmount! > 0n && shortTokenAmount! > 0n) { + throw new Error("Pay source sourceChain does not support both long and short token deposits"); } const fees = technicalFees.kind === "sourceChain" && technicalFees.isDeposit ? technicalFees.fees : undefined; @@ -471,8 +478,11 @@ export const useDepositTransactions = ({ }); } else if (paySource === "gmxAccount") { const expressTxnParams = multichainDepositExpressTxnParams.data; - if (!expressTxnParams) { - throw new Error("Express txn params are not set"); + + if (!transferRequests || !expressTxnParams) { + helperToast.error(t`Error submitting order`); + sendTxnValidationErrorMetric(metricData.metricId); + return; } promise = createMultichainGlvDepositTxn({ @@ -517,6 +527,12 @@ export const useDepositTransactions = ({ } }); } else if (paySource === "settlementChain") { + if (!tokensData) { + helperToast.error(t`Error submitting order`); + sendTxnValidationErrorMetric(metricData.metricId); + return; + } + const someInputTokenIsNative = firstTokenAddress === zeroAddress || secondTokenAddress === zeroAddress; const maybeNativeLongTokenAddress = @@ -563,9 +579,6 @@ export const useDepositTransactions = ({ [ isDeposit, getDepositMetricData, - account, - marketInfo, - amounts, tokensData, signer, isGlv, diff --git a/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx b/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx index def1c80c0c..b287858726 100644 --- a/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx +++ b/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx @@ -14,13 +14,16 @@ import { selectPoolsDetailsSelectedMarketAddressForGlv, selectPoolsDetailsSelectedMarketInfoForGlv, selectPoolsDetailsShortTokenAddress, - selectPoolsDetailsTradeTokensDataWithSourceChainBalances, } from "context/PoolsDetailsContext/selectors"; import { selectDepositWithdrawalAmounts } from "context/PoolsDetailsContext/selectors/selectDepositWithdrawalAmounts"; import { selectPoolsDetailsParams } from "context/PoolsDetailsContext/selectors/selectPoolsDetailsParams"; import { useSyntheticsEvents } from "context/SyntheticsEvents"; import { selectExpressGlobalParams } from "context/SyntheticsStateContext/selectors/expressSelectors"; -import { selectBlockTimestampData, selectChainId } from "context/SyntheticsStateContext/selectors/globalSelectors"; +import { + selectBlockTimestampData, + selectChainId, + selectTokensData, +} from "context/SyntheticsStateContext/selectors/globalSelectors"; import { useSelector } from "context/SyntheticsStateContext/utils"; import { TokensBalancesUpdates, @@ -69,7 +72,7 @@ export const useWithdrawalTransactions = ({ error: Error | undefined; } => { const { chainId, srcChainId } = useChainId(); - const { signer, account } = useWallet(); + const { signer } = useWallet(); const { setPendingWithdrawal } = useSyntheticsEvents(); const { setPendingTxns } = usePendingTxns(); const { addOptimisticTokensBalancesUpdates } = useTokensBalancesUpdates(); @@ -81,7 +84,7 @@ export const useWithdrawalTransactions = ({ const amounts = useSelector(selectDepositWithdrawalAmounts); const paySource = useSelector(selectPoolsDetailsPaySource); const selectedMarketForGlv = useSelector(selectPoolsDetailsSelectedMarketAddressForGlv); - const tokensData = useSelector(selectPoolsDetailsTradeTokensDataWithSourceChainBalances); + const tokensData = useSelector(selectTokensData); const { longTokenAmount = 0n, @@ -206,17 +209,7 @@ export const useWithdrawalTransactions = ({ const metricData = getWithdrawalMetricData(); - if ( - !account || - !marketInfo || - !marketToken || - !amounts || - !transferRequests || - !tokensData || - !signer || - !params || - !isGlv - ) { + if (!amounts || !signer || !params) { helperToast.error(t`Error submitting order`); sendTxnValidationErrorMetric(metricData.metricId); return Promise.resolve(); @@ -233,8 +226,11 @@ export const useWithdrawalTransactions = ({ technicalFees?.kind === "sourceChain" && !technicalFees.isDeposit && technicalFees.isGlv ? technicalFees.fees : undefined; - if (!fees) { - throw new Error("Technical fees are not set"); + + if (!fees || !transferRequests) { + helperToast.error(t`Error submitting order`); + sendTxnValidationErrorMetric(metricData.metricId); + return; } promise = createSourceChainGlvWithdrawalTxn({ @@ -265,8 +261,10 @@ export const useWithdrawalTransactions = ({ }); } else if (paySource === "gmxAccount") { const expressTxnParams = multichainWithdrawalExpressTxnParams.data; - if (!expressTxnParams) { - throw new Error("Express txn params are not set"); + if (!transferRequests || !expressTxnParams) { + helperToast.error(t`Error submitting order`); + sendTxnValidationErrorMetric(metricData.metricId); + return; } promise = createMultichainGlvWithdrawalTxn({ @@ -302,9 +300,13 @@ export const useWithdrawalTransactions = ({ }); } else if (paySource === "settlementChain") { const fees = technicalFees?.kind === "settlementChain" ? technicalFees.fees : undefined; - if (!fees) { - throw new Error("Technical fees are not set"); + + if (!fees || !tokensData) { + helperToast.error(t`Error submitting order`); + sendTxnValidationErrorMetric(metricData.metricId); + return; } + promise = createGlvWithdrawalTxn({ chainId, signer, @@ -328,15 +330,11 @@ export const useWithdrawalTransactions = ({ [ isWithdrawal, getWithdrawalMetricData, - account, - marketInfo, - marketToken, amounts, transferRequests, tokensData, signer, params, - isGlv, paySource, chainId, srcChainId, @@ -362,17 +360,7 @@ export const useWithdrawalTransactions = ({ const metricData = getWithdrawalMetricData(); - if ( - !account || - !marketInfo || - !marketToken || - !amounts || - !transferRequests || - !tokensData || - !signer || - !params || - isGlv - ) { + if (!amounts || !signer || !params) { helperToast.error(t`Error submitting order`); sendTxnValidationErrorMetric(metricData.metricId); return Promise.resolve(); @@ -389,8 +377,11 @@ export const useWithdrawalTransactions = ({ technicalFees.kind === "sourceChain" && !technicalFees.isDeposit && !technicalFees.isGlv ? technicalFees.fees : undefined; - if (!fees) { - throw new Error("Technical fees are not set"); + + if (!fees || !transferRequests) { + helperToast.error(t`Error submitting order`); + sendTxnValidationErrorMetric(metricData.metricId); + return; } promise = createSourceChainWithdrawalTxn({ @@ -417,14 +408,18 @@ export const useWithdrawalTransactions = ({ }); } else if (paySource === "gmxAccount") { const expressTxnParams = multichainWithdrawalExpressTxnParams.data; - if (!expressTxnParams) { - throw new Error("Express txn params are not set"); + if (!transferRequests || !expressTxnParams) { + helperToast.error(t`Error submitting order`); + sendTxnValidationErrorMetric(metricData.metricId); + return; } + const withdrawalParams = params as CreateWithdrawalParams; + promise = createMultichainWithdrawalTxn({ chainId, signer, - params: params as CreateWithdrawalParams, + params: withdrawalParams, expressTxnParams, transferRequests, srcChainId, @@ -441,7 +436,6 @@ export const useWithdrawalTransactions = ({ }); addOptimisticTokensBalancesUpdates(balanceUpdates); - const withdrawalParams = params as CreateWithdrawalParams; setPendingWithdrawal({ account: withdrawalParams.addresses.receiver, marketAddress: withdrawalParams.addresses.market, @@ -454,15 +448,21 @@ export const useWithdrawalTransactions = ({ }); } else if (paySource === "settlementChain") { const fees = technicalFees?.kind === "settlementChain" ? technicalFees.fees : undefined; - if (!fees) { - throw new Error("Technical fees are not set"); + + if (!fees || !tokensData) { + helperToast.error(t`Error submitting order`); + sendTxnValidationErrorMetric(metricData.metricId); + return; } + + const withdrawalParams = params as CreateWithdrawalParams; + promise = createWithdrawalTxn({ chainId, signer, marketTokenAmount: marketTokenAmount!, + params: withdrawalParams, executionGasLimit: fees.gasLimit, - params: params as CreateWithdrawalParams, tokensData, skipSimulation: shouldDisableValidation, setPendingTxns, @@ -483,15 +483,11 @@ export const useWithdrawalTransactions = ({ [ isWithdrawal, getWithdrawalMetricData, - account, - marketInfo, - marketToken, amounts, transferRequests, tokensData, signer, params, - isGlv, paySource, chainId, srcChainId, diff --git a/src/components/MarketStats/hooks/useBestGmPoolForGlv.ts b/src/components/MarketStats/hooks/useBestGmPoolForGlv.ts index 9765111e2d..ffbcefac6c 100644 --- a/src/components/MarketStats/hooks/useBestGmPoolForGlv.ts +++ b/src/components/MarketStats/hooks/useBestGmPoolForGlv.ts @@ -21,12 +21,15 @@ import { TokensData } from "domain/synthetics/tokens"; import { getDepositAmounts } from "domain/synthetics/trade/utils/deposit"; import { getGmSwapError } from "domain/synthetics/trade/utils/validation"; import { useChainId } from "lib/chains"; +import { absDiffBps } from "lib/numbers"; import { usePrevious } from "lib/usePrevious"; import type { useDepositWithdrawalFees } from "components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/useDepositWithdrawalFees"; import { useGlvGmMarketsWithComposition } from "./useMarketGlvGmMarketsCompositions"; +const AMOUNT_CHANGE_THRESHOLD_BPS = 50n; // 0.5% + export const useBestGmPoolAddressForGlv = ({ fees, uiFeeFactor, @@ -230,18 +233,29 @@ export const useBestGmPoolAddressForGlv = ({ return; } + if (!selectedMarketForGlv && bestGmMarketAddress) { + setSelectedMarketAddressForGlv(bestGmMarketAddress); + return; + } + + if (isMarketForGlvSelectedManually || bestGmMarketAddress === selectedMarketForGlv) { + return; + } + + const longAmountChanged = absDiffBps(longTokenAmount ?? 0n, previousLongAmount ?? 0n) > AMOUNT_CHANGE_THRESHOLD_BPS; + const shortAmountChanged = + absDiffBps(shortTokenAmount ?? 0n, previousShortAmount ?? 0n) > AMOUNT_CHANGE_THRESHOLD_BPS; + const marketTokenAmountChanged = + absDiffBps(marketTokenAmount ?? 0n, previousMarketTokenAmount ?? 0n) > AMOUNT_CHANGE_THRESHOLD_BPS; + const shouldSetBestGmMarket = - !isMarketForGlvSelectedManually && - (previousLongAmount !== longTokenAmount || - previousShortAmount !== shortTokenAmount || - previousMarketTokenAmount !== marketTokenAmount || - previousLongTokenAddress !== longTokenAddress || - previousShortTokenAddress !== shortTokenAddress); - - if ( - ((!selectedMarketForGlv && bestGmMarketAddress) || shouldSetBestGmMarket) && - bestGmMarketAddress !== selectedMarketForGlv - ) { + longAmountChanged || + shortAmountChanged || + marketTokenAmountChanged || + previousLongTokenAddress !== longTokenAddress || + previousShortTokenAddress !== shortTokenAddress; + + if (shouldSetBestGmMarket && bestGmMarketAddress !== selectedMarketForGlv) { setSelectedMarketAddressForGlv(bestGmMarketAddress); } }, [ diff --git a/src/context/PoolsDetailsContext/selectors/selectPoolsDetailsParams.tsx b/src/context/PoolsDetailsContext/selectors/selectPoolsDetailsParams.tsx index 295d007758..a96c8be60f 100644 --- a/src/context/PoolsDetailsContext/selectors/selectPoolsDetailsParams.tsx +++ b/src/context/PoolsDetailsContext/selectors/selectPoolsDetailsParams.tsx @@ -29,7 +29,6 @@ import { selectAccount, selectChainId, selectGlvAndMarketsInfoData, - selectMarketsInfoData, selectSrcChainId, } from "context/SyntheticsStateContext/selectors/globalSelectors"; import { createSelector } from "context/SyntheticsStateContext/utils"; @@ -82,7 +81,6 @@ export const selectPoolsDetailsParams = createSelector((q): PoolsDetailsParams = const shortTokenAmount = q(selectPoolsDetailsShortTokenAmount); const glvAndMarketsInfoData = q(selectGlvAndMarketsInfoData); - const marketsInfoData = q(selectMarketsInfoData); const marketOrGlvTokenAddress = q(selectPoolsDetailsGlvOrMarketAddress); const selectedMarketForGlv = q(selectPoolsDetailsSelectedMarketAddressForGlv); @@ -109,12 +107,6 @@ export const selectPoolsDetailsParams = createSelector((q): PoolsDetailsParams = return undefined; } - const marketInfo = isGlv - ? selectedMarketForGlv - ? marketsInfoData?.[selectedMarketForGlv] - : undefined - : glvOrMarketInfo; - const glvInfo = isGlv ? glvOrMarketInfo : undefined; const wrappedNativeTokenAddress = getWrappedToken(chainId); @@ -188,7 +180,7 @@ export const selectPoolsDetailsParams = createSelector((q): PoolsDetailsParams = //#region GLV Deposit if (isDeposit && isGlv) { // Raw GLV Deposit Params - if (!marketInfo || !glvTokenAddress || !selectedMarketForGlv || marketOrGlvTokenAmount === undefined) { + if (!glvTokenAddress || !selectedMarketForGlv || marketOrGlvTokenAmount === undefined) { return undefined; } From d1c51e15f922a015227e89b5123bbfe8e206f7b7 Mon Sep 17 00:00:00 2001 From: midas-myth Date: Fri, 12 Dec 2025 16:23:42 +0100 Subject: [PATCH 04/23] Refactor deposit transaction logic to remove unnecessary isGlv checks, simplifying conditions for deposit creation. This enhances clarity and maintains functionality. --- .../GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx b/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx index 5bf57c05e5..e6a7b09311 100644 --- a/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx +++ b/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx @@ -224,7 +224,7 @@ export const useDepositTransactions = ({ const onCreateGmDeposit = useCallback( async function onCreateGmDeposit(): Promise { - if (!isDeposit || isGlv) { + if (!isDeposit) { return Promise.reject(); } @@ -369,7 +369,6 @@ export const useDepositTransactions = ({ }, [ isDeposit, - isGlv, getDepositMetricData, tokensData, signer, @@ -397,7 +396,7 @@ export const useDepositTransactions = ({ const onCreateGlvDeposit = useCallback( async function onCreateGlvDeposit(): Promise { - if (!isDeposit || !isGlv) { + if (!isDeposit) { return Promise.reject(); } @@ -581,7 +580,6 @@ export const useDepositTransactions = ({ getDepositMetricData, tokensData, signer, - isGlv, rawParams, transferRequests, chainId, From 69ab4b6bc51adee32ad66dd992d5ecb48cd2a5fb Mon Sep 17 00:00:00 2001 From: midas-myth Date: Fri, 12 Dec 2025 16:26:18 +0100 Subject: [PATCH 05/23] Sync translations --- src/locales/de/messages.po | 12 ++++++++++++ src/locales/en/messages.po | 12 ++++++++++++ src/locales/es/messages.po | 12 ++++++++++++ src/locales/fr/messages.po | 12 ++++++++++++ src/locales/ja/messages.po | 12 ++++++++++++ src/locales/ko/messages.po | 12 ++++++++++++ src/locales/pseudo/messages.po | 12 ++++++++++++ src/locales/ru/messages.po | 12 ++++++++++++ src/locales/zh/messages.po | 12 ++++++++++++ 9 files changed, 108 insertions(+) diff --git a/src/locales/de/messages.po b/src/locales/de/messages.po index 0f2ed75c41..566d5004ec 100644 --- a/src/locales/de/messages.po +++ b/src/locales/de/messages.po @@ -6593,6 +6593,18 @@ msgstr "" #: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx #: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx #: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx #: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx #: src/components/GmSwap/GmSwapBox/GmShiftBox/useShiftTransactions.tsx diff --git a/src/locales/en/messages.po b/src/locales/en/messages.po index cbbcd20576..ffedb524f8 100644 --- a/src/locales/en/messages.po +++ b/src/locales/en/messages.po @@ -6593,6 +6593,18 @@ msgstr "Create code" #: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx #: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx #: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx #: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx #: src/components/GmSwap/GmSwapBox/GmShiftBox/useShiftTransactions.tsx diff --git a/src/locales/es/messages.po b/src/locales/es/messages.po index a4357c54a8..b0773ef20a 100644 --- a/src/locales/es/messages.po +++ b/src/locales/es/messages.po @@ -6593,6 +6593,18 @@ msgstr "" #: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx #: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx #: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx #: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx #: src/components/GmSwap/GmSwapBox/GmShiftBox/useShiftTransactions.tsx diff --git a/src/locales/fr/messages.po b/src/locales/fr/messages.po index 544a385ef2..bb5952902e 100644 --- a/src/locales/fr/messages.po +++ b/src/locales/fr/messages.po @@ -6593,6 +6593,18 @@ msgstr "" #: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx #: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx #: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx #: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx #: src/components/GmSwap/GmSwapBox/GmShiftBox/useShiftTransactions.tsx diff --git a/src/locales/ja/messages.po b/src/locales/ja/messages.po index 5fb4e4e61e..dbcbef4785 100644 --- a/src/locales/ja/messages.po +++ b/src/locales/ja/messages.po @@ -6593,6 +6593,18 @@ msgstr "" #: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx #: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx #: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx #: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx #: src/components/GmSwap/GmSwapBox/GmShiftBox/useShiftTransactions.tsx diff --git a/src/locales/ko/messages.po b/src/locales/ko/messages.po index 6928e7620c..75d40bc413 100644 --- a/src/locales/ko/messages.po +++ b/src/locales/ko/messages.po @@ -6593,6 +6593,18 @@ msgstr "" #: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx #: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx #: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx #: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx #: src/components/GmSwap/GmSwapBox/GmShiftBox/useShiftTransactions.tsx diff --git a/src/locales/pseudo/messages.po b/src/locales/pseudo/messages.po index 3b3a24fa53..e0cb0baf3c 100644 --- a/src/locales/pseudo/messages.po +++ b/src/locales/pseudo/messages.po @@ -6593,6 +6593,18 @@ msgstr "" #: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx #: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx #: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx #: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx #: src/components/GmSwap/GmSwapBox/GmShiftBox/useShiftTransactions.tsx diff --git a/src/locales/ru/messages.po b/src/locales/ru/messages.po index 71ec44e222..8727615430 100644 --- a/src/locales/ru/messages.po +++ b/src/locales/ru/messages.po @@ -6593,6 +6593,18 @@ msgstr "" #: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx #: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx #: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx #: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx #: src/components/GmSwap/GmSwapBox/GmShiftBox/useShiftTransactions.tsx diff --git a/src/locales/zh/messages.po b/src/locales/zh/messages.po index d23f0be5fc..4865c2021c 100644 --- a/src/locales/zh/messages.po +++ b/src/locales/zh/messages.po @@ -6593,6 +6593,18 @@ msgstr "" #: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx #: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx +#: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx #: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx #: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx #: src/components/GmSwap/GmSwapBox/GmShiftBox/useShiftTransactions.tsx From 69a0912614f6ce7655e40deb4638ac79e7a6aeac Mon Sep 17 00:00:00 2001 From: midas-myth Date: Tue, 23 Dec 2025 14:33:43 +0100 Subject: [PATCH 06/23] Sync translations --- src/locales/de/messages.po | 16 ---------------- src/locales/en/messages.po | 16 ---------------- src/locales/es/messages.po | 16 ---------------- src/locales/fr/messages.po | 16 ---------------- src/locales/ja/messages.po | 16 ---------------- src/locales/ko/messages.po | 16 ---------------- src/locales/pseudo/messages.po | 16 ---------------- src/locales/ru/messages.po | 16 ---------------- src/locales/zh/messages.po | 16 ---------------- 9 files changed, 144 deletions(-) diff --git a/src/locales/de/messages.po b/src/locales/de/messages.po index 566d5004ec..1cc4fa7482 100644 --- a/src/locales/de/messages.po +++ b/src/locales/de/messages.po @@ -178,10 +178,6 @@ msgstr "Aktualisiere {updateOrdersCount} TP/SL-Order(s)" msgid "RabbitHole" msgstr "RabbitHole" -#: src/pages/Dashboard/WeightText.tsx -#~ msgid "{0} is above its target weight.<0/><1/>Get lower fees to <2>swap tokens for {1}." -#~ msgstr "{0} liegt über der Zielgewichtung.<0/><1/>Erhalte niedrigere Gebühren, um <2>Token für {1} zu tauschen." - #: src/domain/synthetics/markets/createGlvWithdrawalTxn.ts #: src/domain/synthetics/markets/createWithdrawalTxn.ts msgid "Withdrawal error." @@ -5063,10 +5059,6 @@ msgstr "zahlen" msgid "Total circulating supply of GMX tokens." msgstr "Gesamte umlaufende Versorgung von GMX-Token." -#: src/pages/Dashboard/WeightText.tsx -#~ msgid "Target Weight" -#~ msgstr "Ziel-Gewichtung" - #: src/domain/synthetics/trade/useMaxAutoCancelOrdersState.tsx msgid "You can have up to {allowedAutoCancelOrdersNumber} active auto-cancelable TP/SL orders. Additional orders must be canceled manually, while existing ones will still close automatically with their related position." msgstr "Du kannst bis zu {allowedAutoCancelOrdersNumber} aktive auto-stornierbare TP/SL-Orders haben. Zusätzliche Orders müssen manuell storniert werden, während bestehende automatisch mit ihrer zugehörigen Position schließen." @@ -6301,10 +6293,6 @@ msgstr "Gebühren überschreiten Betrag" msgid "Search Type" msgstr "Suchtyp" -#: src/pages/Dashboard/WeightText.tsx -#~ msgid "{0} is below its target weight.<0/><1/>Get lower fees to <2>buy GLP with {1}, and to <3>swap {2} for other tokens." -#~ msgstr "{0} ist unter seinem Zielgewicht.<0/><1/>Erhalte niedrigere Gebühren zum <2>Kaufen von GLP mit {1}, und zum <3>Swappen von {2} für andere Token." - #: src/pages/AccountDashboard/GeneralPerformanceDetails.tsx #: src/pages/LeaderboardPage/components/LeaderboardAccountsTable.tsx msgid "Win Rate" @@ -6955,10 +6943,6 @@ msgstr "Min. Anzahl der Teile: {MIN_TWAP_NUMBER_OF_PARTS}" msgid "Request Settlement of Funding Fees" msgstr "Antrag auf Abrechnung von Finanzierungsgebühren" -#: src/pages/Dashboard/WeightText.tsx -#~ msgid "Current Weight" -#~ msgstr "Aktuelle Gewichtung" - #: src/pages/Ecosystem/Ecosystem.tsx msgid "Partnerships and Integrations" msgstr "Partnerschaften und Integrationen" diff --git a/src/locales/en/messages.po b/src/locales/en/messages.po index ffedb524f8..95dc7b02f7 100644 --- a/src/locales/en/messages.po +++ b/src/locales/en/messages.po @@ -178,10 +178,6 @@ msgstr "Updating {updateOrdersCount} TP/SL order(s)" msgid "RabbitHole" msgstr "RabbitHole" -#: src/pages/Dashboard/WeightText.tsx -#~ msgid "{0} is above its target weight.<0/><1/>Get lower fees to <2>swap tokens for {1}." -#~ msgstr "{0} is above its target weight.<0/><1/>Get lower fees to <2>swap tokens for {1}." - #: src/domain/synthetics/markets/createGlvWithdrawalTxn.ts #: src/domain/synthetics/markets/createWithdrawalTxn.ts msgid "Withdrawal error." @@ -5063,10 +5059,6 @@ msgstr "pay" msgid "Total circulating supply of GMX tokens." msgstr "Total circulating supply of GMX tokens." -#: src/pages/Dashboard/WeightText.tsx -#~ msgid "Target Weight" -#~ msgstr "Target Weight" - #: src/domain/synthetics/trade/useMaxAutoCancelOrdersState.tsx msgid "You can have up to {allowedAutoCancelOrdersNumber} active auto-cancelable TP/SL orders. Additional orders must be canceled manually, while existing ones will still close automatically with their related position." msgstr "You can have up to {allowedAutoCancelOrdersNumber} active auto-cancelable TP/SL orders. Additional orders must be canceled manually, while existing ones will still close automatically with their related position." @@ -6301,10 +6293,6 @@ msgstr "Fees exceed amount" msgid "Search Type" msgstr "Search Type" -#: src/pages/Dashboard/WeightText.tsx -#~ msgid "{0} is below its target weight.<0/><1/>Get lower fees to <2>buy GLP with {1}, and to <3>swap {2} for other tokens." -#~ msgstr "{0} is below its target weight.<0/><1/>Get lower fees to <2>buy GLP with {1}, and to <3>swap {2} for other tokens." - #: src/pages/AccountDashboard/GeneralPerformanceDetails.tsx #: src/pages/LeaderboardPage/components/LeaderboardAccountsTable.tsx msgid "Win Rate" @@ -6955,10 +6943,6 @@ msgstr "Min number of parts: {MIN_TWAP_NUMBER_OF_PARTS}" msgid "Request Settlement of Funding Fees" msgstr "Request Settlement of Funding Fees" -#: src/pages/Dashboard/WeightText.tsx -#~ msgid "Current Weight" -#~ msgstr "Current Weight" - #: src/pages/Ecosystem/Ecosystem.tsx msgid "Partnerships and Integrations" msgstr "Partnerships and Integrations" diff --git a/src/locales/es/messages.po b/src/locales/es/messages.po index b0773ef20a..9d857550c5 100644 --- a/src/locales/es/messages.po +++ b/src/locales/es/messages.po @@ -178,10 +178,6 @@ msgstr "Actualizando {updateOrdersCount} orden(es) TP/SL" msgid "RabbitHole" msgstr "RabbitHole" -#: src/pages/Dashboard/WeightText.tsx -#~ msgid "{0} is above its target weight.<0/><1/>Get lower fees to <2>swap tokens for {1}." -#~ msgstr "{0} está por encima de su peso objetivo.<0/><1/>Consigue menores comisiones para <2>intercambiar tokens por {1}." - #: src/domain/synthetics/markets/createGlvWithdrawalTxn.ts #: src/domain/synthetics/markets/createWithdrawalTxn.ts msgid "Withdrawal error." @@ -5063,10 +5059,6 @@ msgstr "pagar" msgid "Total circulating supply of GMX tokens." msgstr "Suministro circulante total de tokens GMX." -#: src/pages/Dashboard/WeightText.tsx -#~ msgid "Target Weight" -#~ msgstr "Peso Objetivo" - #: src/domain/synthetics/trade/useMaxAutoCancelOrdersState.tsx msgid "You can have up to {allowedAutoCancelOrdersNumber} active auto-cancelable TP/SL orders. Additional orders must be canceled manually, while existing ones will still close automatically with their related position." msgstr "Puedes tener hasta {allowedAutoCancelOrdersNumber} órdenes TP/SL autocancelables activas. Órdenes adicionales deben cancelarse manualmente, mientras que las existentes se cerrarán automáticamente con su posición relacionada." @@ -6301,10 +6293,6 @@ msgstr "Comisiones exceden la cantidad" msgid "Search Type" msgstr "Buscar Tipo" -#: src/pages/Dashboard/WeightText.tsx -#~ msgid "{0} is below its target weight.<0/><1/>Get lower fees to <2>buy GLP with {1}, and to <3>swap {2} for other tokens." -#~ msgstr "{0} está por debajo de su peso objetivo.<0/><1/>Consigue menores comisiones <2>comprar GLP con {1}, y para <3>intercambiar {2} por otros tokens." - #: src/pages/AccountDashboard/GeneralPerformanceDetails.tsx #: src/pages/LeaderboardPage/components/LeaderboardAccountsTable.tsx msgid "Win Rate" @@ -6955,10 +6943,6 @@ msgstr "Número mínimo de partes: {MIN_TWAP_NUMBER_OF_PARTS}" msgid "Request Settlement of Funding Fees" msgstr "Solicitar liquidación de comisiones de financiación" -#: src/pages/Dashboard/WeightText.tsx -#~ msgid "Current Weight" -#~ msgstr "Peso Actual" - #: src/pages/Ecosystem/Ecosystem.tsx msgid "Partnerships and Integrations" msgstr "Asociaciones e Integraciones" diff --git a/src/locales/fr/messages.po b/src/locales/fr/messages.po index bb5952902e..a6ef6344d7 100644 --- a/src/locales/fr/messages.po +++ b/src/locales/fr/messages.po @@ -178,10 +178,6 @@ msgstr "Mise à jour de {updateOrdersCount} ordre(s) TP/SL" msgid "RabbitHole" msgstr "RabbitHole" -#: src/pages/Dashboard/WeightText.tsx -#~ msgid "{0} is above its target weight.<0/><1/>Get lower fees to <2>swap tokens for {1}." -#~ msgstr "{0} est au-dessus de son poids cible.<0/><1/>Obtenez une réduction des frais pour <2>échanger les tokens pour {1}." - #: src/domain/synthetics/markets/createGlvWithdrawalTxn.ts #: src/domain/synthetics/markets/createWithdrawalTxn.ts msgid "Withdrawal error." @@ -5063,10 +5059,6 @@ msgstr "payer" msgid "Total circulating supply of GMX tokens." msgstr "Offre totale en circulation de tokens GMX." -#: src/pages/Dashboard/WeightText.tsx -#~ msgid "Target Weight" -#~ msgstr "Poids cible" - #: src/domain/synthetics/trade/useMaxAutoCancelOrdersState.tsx msgid "You can have up to {allowedAutoCancelOrdersNumber} active auto-cancelable TP/SL orders. Additional orders must be canceled manually, while existing ones will still close automatically with their related position." msgstr "Vous pouvez avoir jusqu'à {allowedAutoCancelOrdersNumber} ordres TP/SL auto-annulables actifs. Les ordres supplémentaires doivent être annulés manuellement, tandis que les existants se fermeront automatiquement avec leur position associée." @@ -6301,10 +6293,6 @@ msgstr "Frais dépassent le montant" msgid "Search Type" msgstr "Type de recherche" -#: src/pages/Dashboard/WeightText.tsx -#~ msgid "{0} is below its target weight.<0/><1/>Get lower fees to <2>buy GLP with {1}, and to <3>swap {2} for other tokens." -#~ msgstr "{0} est en dessous de son poids cible.<0/><1/>Obtenez des frais réduits pour <2>acheter GLP avec {1}, et pour <3>échanger {2} contre d'autres tokens." - #: src/pages/AccountDashboard/GeneralPerformanceDetails.tsx #: src/pages/LeaderboardPage/components/LeaderboardAccountsTable.tsx msgid "Win Rate" @@ -6955,10 +6943,6 @@ msgstr "Nombre min. de parties : {MIN_TWAP_NUMBER_OF_PARTS}" msgid "Request Settlement of Funding Fees" msgstr "Demander le règlement des frais de financement" -#: src/pages/Dashboard/WeightText.tsx -#~ msgid "Current Weight" -#~ msgstr "Poids actuel" - #: src/pages/Ecosystem/Ecosystem.tsx msgid "Partnerships and Integrations" msgstr "Partenariats et intégrations" diff --git a/src/locales/ja/messages.po b/src/locales/ja/messages.po index dbcbef4785..c56238e843 100644 --- a/src/locales/ja/messages.po +++ b/src/locales/ja/messages.po @@ -178,10 +178,6 @@ msgstr "{updateOrdersCount}件のTP/SL注文を更新中" msgid "RabbitHole" msgstr "RabbitHole" -#: src/pages/Dashboard/WeightText.tsx -#~ msgid "{0} is above its target weight.<0/><1/>Get lower fees to <2>swap tokens for {1}." -#~ msgstr "{0}はターゲットウェイトを超過しています。<0/><1/>トークンを{1}に<2>スワップすると手数料が低くなります。" - #: src/domain/synthetics/markets/createGlvWithdrawalTxn.ts #: src/domain/synthetics/markets/createWithdrawalTxn.ts msgid "Withdrawal error." @@ -5063,10 +5059,6 @@ msgstr "支払い" msgid "Total circulating supply of GMX tokens." msgstr "GMXトークンの総循環供給量。" -#: src/pages/Dashboard/WeightText.tsx -#~ msgid "Target Weight" -#~ msgstr "ターゲットウェイト" - #: src/domain/synthetics/trade/useMaxAutoCancelOrdersState.tsx msgid "You can have up to {allowedAutoCancelOrdersNumber} active auto-cancelable TP/SL orders. Additional orders must be canceled manually, while existing ones will still close automatically with their related position." msgstr "最大{allowedAutoCancelOrdersNumber}件のアクティブな自動キャンセル可能TP/SL注文を持つことができます。追加注文は手動でキャンセルする必要があり、既存のものは関連ポジションとともに自動クローズされます。" @@ -6301,10 +6293,6 @@ msgstr "手数料が額を超過" msgid "Search Type" msgstr "検索タイプ" -#: src/pages/Dashboard/WeightText.tsx -#~ msgid "{0} is below its target weight.<0/><1/>Get lower fees to <2>buy GLP with {1}, and to <3>swap {2} for other tokens." -#~ msgstr "{0}はターゲットウェイトより低くなっています。<0/><1/>手数料を低くするには、{1}で<2>GLPを購入し、{2}を別のトークンに<3>スワップしてください。" - #: src/pages/AccountDashboard/GeneralPerformanceDetails.tsx #: src/pages/LeaderboardPage/components/LeaderboardAccountsTable.tsx msgid "Win Rate" @@ -6955,10 +6943,6 @@ msgstr "最小パート数: {MIN_TWAP_NUMBER_OF_PARTS}" msgid "Request Settlement of Funding Fees" msgstr "ファンディング手数料の決済リクエスト" -#: src/pages/Dashboard/WeightText.tsx -#~ msgid "Current Weight" -#~ msgstr "現在のウェイト" - #: src/pages/Ecosystem/Ecosystem.tsx msgid "Partnerships and Integrations" msgstr "パートナーシップと統合" diff --git a/src/locales/ko/messages.po b/src/locales/ko/messages.po index 75d40bc413..f27b2270f3 100644 --- a/src/locales/ko/messages.po +++ b/src/locales/ko/messages.po @@ -178,10 +178,6 @@ msgstr "{updateOrdersCount} TP/SL 주문 업데이트 중" msgid "RabbitHole" msgstr "RabbitHole" -#: src/pages/Dashboard/WeightText.tsx -#~ msgid "{0} is above its target weight.<0/><1/>Get lower fees to <2>swap tokens for {1}." -#~ msgstr "{0}은 목표 가중치를 초과 했습니다.<0/><1/>토큰을 {1}로 <2>스왑하는 수수료가 감소합니다." - #: src/domain/synthetics/markets/createGlvWithdrawalTxn.ts #: src/domain/synthetics/markets/createWithdrawalTxn.ts msgid "Withdrawal error." @@ -5063,10 +5059,6 @@ msgstr "지불" msgid "Total circulating supply of GMX tokens." msgstr "GMX 토큰의 총 순환 공급량." -#: src/pages/Dashboard/WeightText.tsx -#~ msgid "Target Weight" -#~ msgstr "목표 가중치" - #: src/domain/synthetics/trade/useMaxAutoCancelOrdersState.tsx msgid "You can have up to {allowedAutoCancelOrdersNumber} active auto-cancelable TP/SL orders. Additional orders must be canceled manually, while existing ones will still close automatically with their related position." msgstr "최대 {allowedAutoCancelOrdersNumber}개의 활성 자동 취소 가능 TP/SL 주문을 가질 수 있습니다. 추가 주문은 수동으로 취소해야 하며, 기존 주문은 관련 포지션과 함께 자동으로 종료됩니다." @@ -6301,10 +6293,6 @@ msgstr "수수료가 금액 초과" msgid "Search Type" msgstr "검색 유형" -#: src/pages/Dashboard/WeightText.tsx -#~ msgid "{0} is below its target weight.<0/><1/>Get lower fees to <2>buy GLP with {1}, and to <3>swap {2} for other tokens." -#~ msgstr "{0}이 목표 가중치 미만입니다.<0/><1/>{1}로 <2>GLP 구매하여 낮은 수수료를 받고, {2}을 다른 토큰으로 <3>스왑하세요." - #: src/pages/AccountDashboard/GeneralPerformanceDetails.tsx #: src/pages/LeaderboardPage/components/LeaderboardAccountsTable.tsx msgid "Win Rate" @@ -6955,10 +6943,6 @@ msgstr "최소 파트 수: {MIN_TWAP_NUMBER_OF_PARTS}" msgid "Request Settlement of Funding Fees" msgstr "자금 수수료 정산 요청" -#: src/pages/Dashboard/WeightText.tsx -#~ msgid "Current Weight" -#~ msgstr "현재 가중치" - #: src/pages/Ecosystem/Ecosystem.tsx msgid "Partnerships and Integrations" msgstr "파트너십 및 통합" diff --git a/src/locales/pseudo/messages.po b/src/locales/pseudo/messages.po index e0cb0baf3c..8a2fb71ae5 100644 --- a/src/locales/pseudo/messages.po +++ b/src/locales/pseudo/messages.po @@ -178,10 +178,6 @@ msgstr "" msgid "RabbitHole" msgstr "" -#: src/pages/Dashboard/WeightText.tsx -#~ msgid "{0} is above its target weight.<0/><1/>Get lower fees to <2>swap tokens for {1}." -#~ msgstr "" - #: src/domain/synthetics/markets/createGlvWithdrawalTxn.ts #: src/domain/synthetics/markets/createWithdrawalTxn.ts msgid "Withdrawal error." @@ -5063,10 +5059,6 @@ msgstr "" msgid "Total circulating supply of GMX tokens." msgstr "" -#: src/pages/Dashboard/WeightText.tsx -#~ msgid "Target Weight" -#~ msgstr "" - #: src/domain/synthetics/trade/useMaxAutoCancelOrdersState.tsx msgid "You can have up to {allowedAutoCancelOrdersNumber} active auto-cancelable TP/SL orders. Additional orders must be canceled manually, while existing ones will still close automatically with their related position." msgstr "" @@ -6301,10 +6293,6 @@ msgstr "" msgid "Search Type" msgstr "" -#: src/pages/Dashboard/WeightText.tsx -#~ msgid "{0} is below its target weight.<0/><1/>Get lower fees to <2>buy GLP with {1}, and to <3>swap {2} for other tokens." -#~ msgstr "" - #: src/pages/AccountDashboard/GeneralPerformanceDetails.tsx #: src/pages/LeaderboardPage/components/LeaderboardAccountsTable.tsx msgid "Win Rate" @@ -6955,10 +6943,6 @@ msgstr "" msgid "Request Settlement of Funding Fees" msgstr "" -#: src/pages/Dashboard/WeightText.tsx -#~ msgid "Current Weight" -#~ msgstr "" - #: src/pages/Ecosystem/Ecosystem.tsx msgid "Partnerships and Integrations" msgstr "" diff --git a/src/locales/ru/messages.po b/src/locales/ru/messages.po index 8727615430..7e4824bbaf 100644 --- a/src/locales/ru/messages.po +++ b/src/locales/ru/messages.po @@ -178,10 +178,6 @@ msgstr "Обновление {updateOrdersCount} TP/SL ордеров" msgid "RabbitHole" msgstr "RabbitHole" -#: src/pages/Dashboard/WeightText.tsx -#~ msgid "{0} is above its target weight.<0/><1/>Get lower fees to <2>swap tokens for {1}." -#~ msgstr "{0} превышает целевой вес.<0/><1/>Получите меньшую комиссию, чтобы <2>обменять токены на {1}." - #: src/domain/synthetics/markets/createGlvWithdrawalTxn.ts #: src/domain/synthetics/markets/createWithdrawalTxn.ts msgid "Withdrawal error." @@ -5063,10 +5059,6 @@ msgstr "оплатить" msgid "Total circulating supply of GMX tokens." msgstr "Общий циркулирующий запас токенов GMX." -#: src/pages/Dashboard/WeightText.tsx -#~ msgid "Target Weight" -#~ msgstr "Целевой вес" - #: src/domain/synthetics/trade/useMaxAutoCancelOrdersState.tsx msgid "You can have up to {allowedAutoCancelOrdersNumber} active auto-cancelable TP/SL orders. Additional orders must be canceled manually, while existing ones will still close automatically with their related position." msgstr "У вас может быть до {allowedAutoCancelOrdersNumber} активных автоканцелируемых ордеров TP/SL. Дополнительные ордера должны отменяться вручную, в то время как существующие все равно закроются автоматически с связанной позицией." @@ -6301,10 +6293,6 @@ msgstr "Комиссии превышают сумму" msgid "Search Type" msgstr "Тип поиска" -#: src/pages/Dashboard/WeightText.tsx -#~ msgid "{0} is below its target weight.<0/><1/>Get lower fees to <2>buy GLP with {1}, and to <3>swap {2} for other tokens." -#~ msgstr "{0} ниже целевого веса.<0/><1/>Получите более низкие комиссии для <2>покупки GLP с {1}, и для <3>обмена {2} на другие токены." - #: src/pages/AccountDashboard/GeneralPerformanceDetails.tsx #: src/pages/LeaderboardPage/components/LeaderboardAccountsTable.tsx msgid "Win Rate" @@ -6955,10 +6943,6 @@ msgstr "Минимальное количество частей: {MIN_TWAP_NUMB msgid "Request Settlement of Funding Fees" msgstr "Запрос на расчет комиссий за финансирование" -#: src/pages/Dashboard/WeightText.tsx -#~ msgid "Current Weight" -#~ msgstr "Текущий вес" - #: src/pages/Ecosystem/Ecosystem.tsx msgid "Partnerships and Integrations" msgstr "Партнерства и интеграции" diff --git a/src/locales/zh/messages.po b/src/locales/zh/messages.po index 4865c2021c..e688b2b289 100644 --- a/src/locales/zh/messages.po +++ b/src/locales/zh/messages.po @@ -178,10 +178,6 @@ msgstr "更新 {updateOrdersCount} 个 TP/SL 订单" msgid "RabbitHole" msgstr "RabbitHole" -#: src/pages/Dashboard/WeightText.tsx -#~ msgid "{0} is above its target weight.<0/><1/>Get lower fees to <2>swap tokens for {1}." -#~ msgstr "{0} 高于其目标权重。<0/><1/>获取较低费用,以 <2>交换 代币为 {1}。" - #: src/domain/synthetics/markets/createGlvWithdrawalTxn.ts #: src/domain/synthetics/markets/createWithdrawalTxn.ts msgid "Withdrawal error." @@ -5063,10 +5059,6 @@ msgstr "支付" msgid "Total circulating supply of GMX tokens." msgstr "GMX 代币的总流通供应量。" -#: src/pages/Dashboard/WeightText.tsx -#~ msgid "Target Weight" -#~ msgstr "目标权重" - #: src/domain/synthetics/trade/useMaxAutoCancelOrdersState.tsx msgid "You can have up to {allowedAutoCancelOrdersNumber} active auto-cancelable TP/SL orders. Additional orders must be canceled manually, while existing ones will still close automatically with their related position." msgstr "您最多可以有 {allowedAutoCancelOrdersNumber} 个活跃的可自动取消 TP/SL 订单。额外订单必须手动取消,而现有订单仍将与其相关头寸自动关闭。" @@ -6301,10 +6293,6 @@ msgstr "费用超过金额" msgid "Search Type" msgstr "搜索类型" -#: src/pages/Dashboard/WeightText.tsx -#~ msgid "{0} is below its target weight.<0/><1/>Get lower fees to <2>buy GLP with {1}, and to <3>swap {2} for other tokens." -#~ msgstr "{0} 低于其目标权重。<0/><1/>获取较低费用,以 <2>用 {1} 购买 GLP,并 <3>交换 {2} 为其他代币。" - #: src/pages/AccountDashboard/GeneralPerformanceDetails.tsx #: src/pages/LeaderboardPage/components/LeaderboardAccountsTable.tsx msgid "Win Rate" @@ -6955,10 +6943,6 @@ msgstr "最小部分数量:{MIN_TWAP_NUMBER_OF_PARTS}" msgid "Request Settlement of Funding Fees" msgstr "请求结算资金费用" -#: src/pages/Dashboard/WeightText.tsx -#~ msgid "Current Weight" -#~ msgstr "当前权重" - #: src/pages/Ecosystem/Ecosystem.tsx msgid "Partnerships and Integrations" msgstr "合作伙伴与整合" From 30e022377f8fefc3f852d15cd9536cc09eace88e Mon Sep 17 00:00:00 2001 From: midas-myth Date: Tue, 23 Dec 2025 19:09:45 +0100 Subject: [PATCH 07/23] Refactor signCreateGlvWithdrawal function to accept AbstractSigner and optional shouldUseSignerMethod parameter. Update related fee estimation logic to use the new function signature, enhancing flexibility in signing transactions. --- ...teGlvWithdrawalPlatformTokenTransferInFees.ts | 4 ++-- .../markets/signCreateGlvWithdrawal.ts | 16 +++++++++------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/domain/synthetics/markets/feeEstimation/estimateGlvWithdrawalPlatformTokenTransferInFees.ts b/src/domain/synthetics/markets/feeEstimation/estimateGlvWithdrawalPlatformTokenTransferInFees.ts index a55f309a37..ae45c97201 100644 --- a/src/domain/synthetics/markets/feeEstimation/estimateGlvWithdrawalPlatformTokenTransferInFees.ts +++ b/src/domain/synthetics/markets/feeEstimation/estimateGlvWithdrawalPlatformTokenTransferInFees.ts @@ -13,7 +13,7 @@ import { getWrappedToken } from "sdk/configs/tokens"; import { getEmptyExternalCallsPayload } from "sdk/utils/orderTransactions"; import { nowInSeconds } from "sdk/utils/time"; -import { signCreateWithdrawal } from "../signCreateWithdrawal"; +import { signCreateGlvWithdrawal } from "../signCreateGlvWithdrawal"; import { CreateGlvWithdrawalParams } from "../types"; import { stargateTransferFees } from "./stargateTransferFees"; @@ -72,7 +72,7 @@ export async function estimateGlvWithdrawalPlatformTokenTransferInFees({ throw new Error("Transfer requests not found"); } - const signature = await signCreateWithdrawal({ + const signature = await signCreateGlvWithdrawal({ chainId, srcChainId, signer: RANDOM_WALLET, diff --git a/src/domain/synthetics/markets/signCreateGlvWithdrawal.ts b/src/domain/synthetics/markets/signCreateGlvWithdrawal.ts index 5fbed3cbe1..72f5108c96 100644 --- a/src/domain/synthetics/markets/signCreateGlvWithdrawal.ts +++ b/src/domain/synthetics/markets/signCreateGlvWithdrawal.ts @@ -1,13 +1,13 @@ -import type { Wallet } from "ethers"; +import type { AbstractSigner, Wallet } from "ethers"; import type { ContractsChainId, SourceChainId } from "config/chains"; import { getContract } from "config/contracts"; -import { TransferRequests } from "domain/multichain/types"; -import { ISigner } from "lib/transactions/iSigner"; +import type { TransferRequests } from "domain/multichain/types"; +import type { ISigner } from "lib/transactions/iSigner"; import type { WalletSigner } from "lib/wallets"; import { signTypedData } from "lib/wallets/signing"; -import type { CreateWithdrawalParams } from "."; +import type { CreateGlvWithdrawalParams } from "."; import { getGelatoRelayRouterDomain, hashRelayParams } from "../express/relayParamsUtils"; import type { RelayParamsPayload } from "../express/types"; @@ -18,13 +18,15 @@ export async function signCreateGlvWithdrawal({ relayParams, transferRequests, params, + shouldUseSignerMethod, }: { - signer: WalletSigner | Wallet | ISigner; + signer: WalletSigner | Wallet | ISigner | AbstractSigner; relayParams: RelayParamsPayload; transferRequests: TransferRequests; - params: CreateWithdrawalParams; + params: CreateGlvWithdrawalParams; chainId: ContractsChainId; srcChainId: SourceChainId | undefined; + shouldUseSignerMethod?: boolean; }) { const types = { CreateGlvWithdrawal: [ @@ -66,5 +68,5 @@ export async function signCreateGlvWithdrawal({ relayParams: hashRelayParams(relayParams), }; - return signTypedData({ signer, domain, types, typedData }); + return signTypedData({ signer, domain, types, typedData, shouldUseSignerMethod }); } From 53714dba68379eb8beb191f667f1471603688e8d Mon Sep 17 00:00:00 2001 From: midas-myth Date: Tue, 23 Dec 2025 23:33:51 +0100 Subject: [PATCH 08/23] Refactor technical fees handling in useGmSwapSubmitState and useWithdrawalTransactions hooks. Remove unnecessary fee checks and update conditions for execution fee calculation, improving clarity and maintainability. --- .../lpTxn/useWithdrawalTransactions.tsx | 2 +- .../GmSwapBox/GmDepositWithdrawalBox/useGmSwapSubmitState.tsx | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx b/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx index e19e518de2..1d75c74742 100644 --- a/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx +++ b/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx @@ -115,7 +115,7 @@ export const useWithdrawalTransactions = ({ } let executionFee: bigint | undefined; - if (technicalFees.kind === "sourceChain" && technicalFees.isDeposit) { + if (technicalFees.kind === "sourceChain" && !technicalFees.isDeposit) { executionFee = technicalFees.fees.executionFee; } else if (technicalFees.kind === "gmxAccount") { executionFee = technicalFees.fees.executionFee.feeTokenAmount; diff --git a/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/useGmSwapSubmitState.tsx b/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/useGmSwapSubmitState.tsx index 42a72740ad..0987b4d9a8 100644 --- a/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/useGmSwapSubmitState.tsx +++ b/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/useGmSwapSubmitState.tsx @@ -315,10 +315,6 @@ function useExpressError({ return undefined; } - if (!("feeUsd" in technicalFees)) { - return undefined; - } - const fees = technicalFees.kind === "gmxAccount" ? technicalFees.fees : undefined; if (!fees) { return undefined; From 0dfa1832361c1b6f5d1c65420a45ee52641f66c1 Mon Sep 17 00:00:00 2001 From: midas-myth Date: Wed, 24 Dec 2025 19:35:01 +0100 Subject: [PATCH 09/23] Enhance technical fees handling by adding isDeposit and isGlv flags to fee types. Update deposit and withdrawal transaction hooks to utilize these flags for improved logic flow. --- .../lpTxn/useDepositTransactions.tsx | 4 ++-- .../lpTxn/useWithdrawalTransactions.tsx | 4 ++-- .../useTechnicalFeesAsyncResult.tsx | 16 ++++++++++++++++ src/domain/multichain/technical-fees-types.ts | 4 ++++ 4 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx b/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx index e6a7b09311..0363cf869f 100644 --- a/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx +++ b/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx @@ -120,12 +120,12 @@ export const useDepositTransactions = ({ const rawParams = useSelector(selectPoolsDetailsParams); const params = useMemo((): CreateDepositParams | CreateGlvDepositParams | undefined => { - if (!rawParams || !technicalFees || !isDeposit) { + if (!rawParams || !technicalFees || !isDeposit || !technicalFees.isDeposit) { return undefined; } let executionFee: bigint | undefined; - if (technicalFees.kind === "sourceChain" && technicalFees.isDeposit) { + if (technicalFees.kind === "sourceChain") { executionFee = technicalFees.fees.executionFee; } else if (technicalFees.kind === "gmxAccount") { executionFee = technicalFees.fees.executionFee.feeTokenAmount; diff --git a/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx b/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx index 1d75c74742..d98059d056 100644 --- a/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx +++ b/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx @@ -110,12 +110,12 @@ export const useWithdrawalTransactions = ({ const rawParams = useSelector(selectPoolsDetailsParams); const params = useMemo((): CreateWithdrawalParams | CreateGlvWithdrawalParams | undefined => { - if (!rawParams || !technicalFees || !isWithdrawal) { + if (!rawParams || !technicalFees || !isWithdrawal || technicalFees.isDeposit) { return undefined; } let executionFee: bigint | undefined; - if (technicalFees.kind === "sourceChain" && !technicalFees.isDeposit) { + if (technicalFees.kind === "sourceChain") { executionFee = technicalFees.fees.executionFee; } else if (technicalFees.kind === "gmxAccount") { executionFee = technicalFees.fees.executionFee.feeTokenAmount; diff --git a/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/useTechnicalFeesAsyncResult.tsx b/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/useTechnicalFeesAsyncResult.tsx index 97effe907a..06a9c27fe3 100644 --- a/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/useTechnicalFeesAsyncResult.tsx +++ b/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/useTechnicalFeesAsyncResult.tsx @@ -115,6 +115,8 @@ export function useTechnicalFees(): TechnicalGmFees { return { kind: "settlementChain", fees, + isDeposit: true, + isGlv: true, }; } else { const castedParams = p.params.rawParams as RawCreateDepositParams; @@ -135,6 +137,8 @@ export function useTechnicalFees(): TechnicalGmFees { return { kind: "settlementChain", fees, + isDeposit: true, + isGlv: false, }; } } else if (p.params.operation === Operation.Withdrawal) { @@ -158,6 +162,8 @@ export function useTechnicalFees(): TechnicalGmFees { return { kind: "settlementChain", fees, + isDeposit: false, + isGlv: true, }; } else { const castedParams = p.params.rawParams as RawCreateWithdrawalParams; @@ -178,6 +184,8 @@ export function useTechnicalFees(): TechnicalGmFees { return { kind: "settlementChain", fees, + isDeposit: false, + isGlv: false, }; } } @@ -276,6 +284,8 @@ export function useTechnicalFees(): TechnicalGmFees { executionFee, relayFeeUsd, }, + isDeposit: true, + isGlv: true, }; } else { const castedParams = p.params.rawParams as RawCreateDepositParams; @@ -354,6 +364,8 @@ export function useTechnicalFees(): TechnicalGmFees { executionFee, relayFeeUsd, }, + isDeposit: true, + isGlv: false, }; } } else if (p.params.operation === Operation.Withdrawal) { @@ -430,6 +442,8 @@ export function useTechnicalFees(): TechnicalGmFees { executionFee: fees, relayFeeUsd, }, + isDeposit: false, + isGlv: true, }; } else { const castedParams = p.params.rawParams as RawCreateWithdrawalParams; @@ -503,6 +517,8 @@ export function useTechnicalFees(): TechnicalGmFees { executionFee: fees, relayFeeUsd, }, + isDeposit: false, + isGlv: false, }; } } diff --git a/src/domain/multichain/technical-fees-types.ts b/src/domain/multichain/technical-fees-types.ts index 943838e90c..a81a47838a 100644 --- a/src/domain/multichain/technical-fees-types.ts +++ b/src/domain/multichain/technical-fees-types.ts @@ -7,6 +7,8 @@ import type { ExecutionFee } from "sdk/types/fees"; type SameChainGmFees = { kind: "settlementChain"; fees: ExecutionFee; + isDeposit: boolean; + isGlv: boolean; }; type GmxAccountGmFees = { @@ -15,6 +17,8 @@ type GmxAccountGmFees = { executionFee: ExecutionFee; relayFeeUsd: bigint; }; + isDeposit: boolean; + isGlv: boolean; }; type SourceChainGmFees = { From cf8597c139e4522c9070862967ed83e3b4a8f677 Mon Sep 17 00:00:00 2001 From: midas-myth Date: Wed, 24 Dec 2025 19:35:56 +0100 Subject: [PATCH 10/23] Refactor gas estimation logic in arbitraryRelayParams.ts to utilize EstimateGasParameters for improved clarity and maintainability. Introduce state overrides for relayer fee token and DataStore, enhancing the handling of gas payment parameters. --- src/domain/multichain/arbitraryRelayParams.ts | 67 ++++++++++++------- 1 file changed, 43 insertions(+), 24 deletions(-) diff --git a/src/domain/multichain/arbitraryRelayParams.ts b/src/domain/multichain/arbitraryRelayParams.ts index bdf6bf59b7..7118892de4 100644 --- a/src/domain/multichain/arbitraryRelayParams.ts +++ b/src/domain/multichain/arbitraryRelayParams.ts @@ -1,9 +1,19 @@ import { useMemo } from "react"; -import { encodeAbiParameters, encodePacked, keccak256, maxUint256, PublicClient, toHex } from "viem"; +import { + encodeAbiParameters, + encodePacked, + EstimateGasParameters, + keccak256, + maxUint256, + PublicClient, + toHex, + zeroHash, +} from "viem"; import type { ContractsChainId } from "config/chains"; import { getContract } from "config/contracts"; import { GMX_SIMULATION_ORIGIN, multichainBalanceKey } from "config/dataStore"; +import { OVERRIDE_ERC20_BYTECODE, RANDOM_SLOT } from "config/multichain"; import { selectExpressGlobalParams } from "context/SyntheticsStateContext/selectors/expressSelectors"; import { selectAccount, @@ -151,30 +161,39 @@ async function estimateArbitraryGasLimit({ [baseTxnData.callData, getContract(chainId, "GelatoRelayAddress"), baseTxnData.feeToken, baseTxnData.feeAmount] ); + const params: EstimateGasParameters = { + account: GMX_SIMULATION_ORIGIN, + to: baseTxnData.to, + data: baseData, + value: 0n, + stateOverride: [ + { + address: getContract(chainId, "DataStore"), + stateDiff: [ + { + slot: calculateMappingSlot( + multichainBalanceKey(account, gasPaymentParams.gasPaymentTokenAddress), + DATASTORE_SLOT_INDEXES.uintValues + ), + value: toHex(maxUint256 / 100n, { size: 32 }), + }, + ], + }, + { + address: gasPaymentParams.relayerFeeTokenAddress, + code: OVERRIDE_ERC20_BYTECODE, + state: [ + { + slot: RANDOM_SLOT, + value: zeroHash, + }, + ], + }, + ], + }; + const gasLimit = await fallbackCustomError( - async () => - client - .estimateGas({ - account: GMX_SIMULATION_ORIGIN, - to: baseTxnData.to, - data: baseData, - value: 0n, - stateOverride: [ - { - address: getContract(chainId, "DataStore"), - stateDiff: [ - { - slot: calculateMappingSlot( - multichainBalanceKey(account, gasPaymentParams.gasPaymentTokenAddress), - DATASTORE_SLOT_INDEXES.uintValues - ), - value: toHex(maxUint256), - }, - ], - }, - ], - }) - .then(applyGasLimitBuffer), + async () => client.estimateGas(params).then(applyGasLimitBuffer), "gasLimit" ); From 7e901567553243bf393974aeb52acf6c8e1c25b9 Mon Sep 17 00:00:00 2001 From: midas-myth Date: Wed, 24 Dec 2025 19:38:48 +0100 Subject: [PATCH 11/23] Update value calculation in estimateExpressParams to divide maxUint256 by 100n to avoid overflow --- src/domain/synthetics/express/expressOrderUtils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/domain/synthetics/express/expressOrderUtils.ts b/src/domain/synthetics/express/expressOrderUtils.ts index b076a01feb..379df7acf1 100644 --- a/src/domain/synthetics/express/expressOrderUtils.ts +++ b/src/domain/synthetics/express/expressOrderUtils.ts @@ -386,7 +386,7 @@ export async function estimateExpressParams({ multichainBalanceKey(account, gasPaymentToken.address), DATASTORE_SLOT_INDEXES.uintValues ), - value: toHex(maxUint256), + value: toHex(maxUint256 / 100n, { size: 32 }), }, ], }, From 41a2538ad459b2fe97a387946394f0bdd689171e Mon Sep 17 00:00:00 2001 From: midas-myth Date: Wed, 24 Dec 2025 21:52:32 +0100 Subject: [PATCH 12/23] Refactor wrapped token data retrieval in useDepositWithdrawalFees to use getByKey for improved safety and clarity. Add check for wrapped token data existence to prevent potential errors. --- .../useDepositWithdrawalFees.tsx | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/useDepositWithdrawalFees.tsx b/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/useDepositWithdrawalFees.tsx index fbb149a312..4e09bc2980 100644 --- a/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/useDepositWithdrawalFees.tsx +++ b/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/useDepositWithdrawalFees.tsx @@ -6,6 +6,7 @@ import { getFeeItem, getTotalFeeItem, type FeeItem, type GasLimitsConfig } from import { GlvInfo } from "domain/synthetics/markets"; import { convertToUsd, getMidPrice, TokensData } from "domain/synthetics/tokens"; import { DepositAmounts, GmSwapFees, WithdrawalAmounts } from "domain/synthetics/trade"; +import { getByKey } from "lib/objects"; import { ContractsChainId, SourceChainId } from "sdk/configs/chains"; import { getWrappedToken } from "sdk/configs/tokens"; @@ -58,13 +59,15 @@ export const useDepositWithdrawalFees = ({ shouldRoundUp: true, }); - const wrappedToken = getWrappedToken(chainId); - const wrappedTokenData = tokensData[wrappedToken.address]; - const wrappedTokenPrice = getMidPrice(wrappedTokenData.prices); - let logicalNetworkFeeUsd = 0n; if (technicalFees.kind === "settlementChain") { + const wrappedToken = getWrappedToken(chainId); + const wrappedTokenData = getByKey(tokensData, wrappedToken.address); + if (!wrappedTokenData) { + return { logicalFees: undefined }; + } + const wrappedTokenPrice = getMidPrice(wrappedTokenData.prices); const keeperUsd = convertToUsd(technicalFees.fees.feeTokenAmount, wrappedToken.decimals, wrappedTokenPrice)!; logicalNetworkFeeUsd = keeperUsd * -1n; } else if (technicalFees.kind === "gmxAccount") { From 42cb996dd7989abd04bf326916dd10e9afa027cd Mon Sep 17 00:00:00 2001 From: midas-myth Date: Tue, 6 Jan 2026 19:34:40 +0100 Subject: [PATCH 13/23] Refactor GmSwap components to centralize operation and mode types - Moved and enums from to for better accessibility. - Updated imports across various components to use the new centralized types. - Removed redundant type definitions and cleaned up imports in several files. - Enhanced the hook to streamline fee calculations and improve code clarity. --- .../Portfolio/AssetsList/GmGlvAssetCard.tsx | 2 +- src/components/GmSwap/GmFees/GmFees.tsx | 3 +- .../GmDepositWithdrawalBox.tsx | 2 +- .../GmDepositWithdrawalBox/InfoRows.tsx | 3 +- .../lpTxn/useDepositTransactions.tsx | 4 +- .../lpTxn/useLpTransactions.tsx | 4 +- .../lpTxn/useWithdrawalTransactions.tsx | 8 +- .../useDepositWithdrawalFees.tsx | 122 ++-- .../useGmSwapSubmitState.tsx | 4 +- .../useTechnicalFeesAsyncResult.tsx | 625 +----------------- .../GmSwapBox/GmShiftBox/GmShiftBox.tsx | 2 +- src/components/GmSwap/GmSwapBox/GmSwapBox.tsx | 2 +- .../GmSwap/GmSwapBox/GmSwapBoxHeader.tsx | 3 +- .../GmSwapBox/getGmSwapBoxAvailableModes.tsx | 4 +- src/components/GmSwap/GmSwapBox/types.ts | 18 - .../MarketStats/hooks/useBestGmPoolForGlv.ts | 7 +- src/config/multichain.ts | 7 +- .../PoolsDetailsContext.tsx | 3 +- .../selectors/baseSelectors.ts | 3 +- .../selectors/poolsDetailsDerivedSelectors.ts | 2 +- src/domain/multichain/arbitraryRelayParams.ts | 4 +- .../buildWithdrawalTransferRequests.tsx | 51 -- .../multichain/progress/GmOrGlvBuyProgress.ts | 3 +- .../progress/GmOrGlvSellProgress.ts | 3 +- .../progress/MultichainTransferProgress.ts | 3 +- .../MultichainTransferProgressView.tsx | 6 +- .../progress/__tests__/tracker.spec.ts | 3 +- src/domain/multichain/technical-fees-types.ts | 49 -- .../synthetics/express/expressOrderUtils.ts | 4 +- .../markets/buildDepositTransferRequests.ts} | 3 +- .../buildWithdrawalTransferRequests.ts | 37 ++ .../estimatePureLpActionExecutionFee.ts | 2 +- .../estimateSourceChainDepositFees.ts | 4 +- .../estimateSourceChainGlvDepositFees.ts | 4 +- .../estimateSourceChainGlvWithdrawalFees.ts | 6 +- .../estimateSourceChainWithdrawalFees.ts | 4 +- .../calculateGmxAccountTechnicalFees.ts | 286 ++++++++ .../calculateSettlementChainTechnicalFees.ts | 81 +++ .../calculateSourceChainTechnicalFees.ts | 121 ++++ .../technicalFees/calculateTechnicalFees.ts | 16 + .../technicalFees/technical-fees-types.ts | 86 +++ src/domain/synthetics/markets/types.ts | 19 + 42 files changed, 805 insertions(+), 818 deletions(-) delete mode 100644 src/components/GmSwap/GmSwapBox/types.ts delete mode 100644 src/domain/multichain/buildWithdrawalTransferRequests.tsx delete mode 100644 src/domain/multichain/technical-fees-types.ts rename src/domain/{multichain/buildDepositTransferRequests.tsx => synthetics/markets/buildDepositTransferRequests.ts} (97%) create mode 100644 src/domain/synthetics/markets/buildWithdrawalTransferRequests.ts create mode 100644 src/domain/synthetics/markets/technicalFees/calculateGmxAccountTechnicalFees.ts create mode 100644 src/domain/synthetics/markets/technicalFees/calculateSettlementChainTechnicalFees.ts create mode 100644 src/domain/synthetics/markets/technicalFees/calculateSourceChainTechnicalFees.ts create mode 100644 src/domain/synthetics/markets/technicalFees/calculateTechnicalFees.ts create mode 100644 src/domain/synthetics/markets/technicalFees/technical-fees-types.ts diff --git a/src/components/Earn/Portfolio/AssetsList/GmGlvAssetCard.tsx b/src/components/Earn/Portfolio/AssetsList/GmGlvAssetCard.tsx index d7e5e80083..1654fd0f14 100644 --- a/src/components/Earn/Portfolio/AssetsList/GmGlvAssetCard.tsx +++ b/src/components/Earn/Portfolio/AssetsList/GmGlvAssetCard.tsx @@ -11,6 +11,7 @@ import { getMarketPoolName, } from "domain/synthetics/markets"; import { isGlvInfo } from "domain/synthetics/markets/glv"; +import { Mode, Operation } from "domain/synthetics/markets/types"; import { formatPercentage } from "lib/numbers"; import { EarnPagePortfolioItemType, sendEarnPortfolioItemClickEvent } from "lib/userAnalytics/earnEvents"; import { ContractsChainId } from "sdk/configs/chains"; @@ -18,7 +19,6 @@ import { getNormalizedTokenSymbol } from "sdk/configs/tokens"; import { AmountWithUsdBalance } from "components/AmountWithUsd/AmountWithUsd"; import Button from "components/Button/Button"; -import { Mode, Operation } from "components/GmSwap/GmSwapBox/types"; import { MultichainBalanceTooltip } from "components/MultichainBalanceTooltip/MultichainBalanceTooltip"; import { SyntheticsInfoRow } from "components/SyntheticsInfoRow"; import TokenIcon from "components/TokenIcon/TokenIcon"; diff --git a/src/components/GmSwap/GmFees/GmFees.tsx b/src/components/GmSwap/GmFees/GmFees.tsx index 6f120d4267..8a85c28bf8 100644 --- a/src/components/GmSwap/GmFees/GmFees.tsx +++ b/src/components/GmSwap/GmFees/GmFees.tsx @@ -3,6 +3,7 @@ import cx from "classnames"; import { ReactNode, useMemo } from "react"; import Skeleton from "react-loading-skeleton"; +import { Operation } from "domain/synthetics/markets/types"; import { formatDeltaUsd, formatPercentage } from "lib/numbers"; import { getPositiveOrNegativeClass } from "lib/utils"; import { FeeItem } from "sdk/types/fees"; @@ -12,8 +13,6 @@ import StatsTooltipRow from "components/StatsTooltip/StatsTooltipRow"; import { SyntheticsInfoRow } from "components/SyntheticsInfoRow"; import Tooltip from "components/Tooltip/Tooltip"; -import { Operation } from "../GmSwapBox/types"; - import "./GmFees.scss"; type Props = { diff --git a/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/GmDepositWithdrawalBox.tsx b/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/GmDepositWithdrawalBox.tsx index 8f852c91fd..32ef039a15 100644 --- a/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/GmDepositWithdrawalBox.tsx +++ b/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/GmDepositWithdrawalBox.tsx @@ -184,7 +184,7 @@ export function GmSwapBoxDepositWithdrawal() { const technicalFees = useTechnicalFees(); - const { logicalFees } = useDepositWithdrawalFees({ + const logicalFees = useDepositWithdrawalFees({ amounts, chainId, gasLimits, diff --git a/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/InfoRows.tsx b/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/InfoRows.tsx index 2c983fc9b9..c3944d466d 100644 --- a/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/InfoRows.tsx +++ b/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/InfoRows.tsx @@ -1,6 +1,7 @@ import { t, Trans } from "@lingui/macro"; import { useState } from "react"; +import { Operation } from "domain/synthetics/markets/types"; import { GmSwapFees } from "domain/synthetics/trade"; import { formatDeltaUsd } from "lib/numbers"; @@ -9,8 +10,6 @@ import { GmFees } from "components/GmSwap/GmFees/GmFees"; import { SyntheticsInfoRow } from "components/SyntheticsInfoRow"; import { UsdValueWithSkeleton } from "components/UsdValueWithSkeleton/UsdValueWithSkeleton"; -import { Operation } from "../types"; - export function InfoRows({ isDeposit, fees, diff --git a/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx b/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx index 0363cf869f..f1df206207 100644 --- a/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx +++ b/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useDepositTransactions.tsx @@ -35,9 +35,7 @@ import { TokensBalancesUpdates, useTokensBalancesUpdates, } from "context/TokensBalancesContext/TokensBalancesContextProvider"; -import { buildDepositTransferRequests } from "domain/multichain/buildDepositTransferRequests"; import { GlvBuyTask, GmBuyTask } from "domain/multichain/progress/GmOrGlvBuyProgress"; -import type { TechnicalGmFees } from "domain/multichain/technical-fees-types"; import { toastCustomOrStargateError } from "domain/multichain/toastCustomOrStargateError"; import { TransferRequests } from "domain/multichain/types"; import { @@ -47,11 +45,13 @@ import { RawCreateDepositParams, RawCreateGlvDepositParams, } from "domain/synthetics/markets"; +import { buildDepositTransferRequests } from "domain/synthetics/markets/buildDepositTransferRequests"; import { createGlvDepositTxn } from "domain/synthetics/markets/createGlvDepositTxn"; import { createMultichainDepositTxn } from "domain/synthetics/markets/createMultichainDepositTxn"; import { createMultichainGlvDepositTxn } from "domain/synthetics/markets/createMultichainGlvDepositTxn"; import { createSourceChainDepositTxn } from "domain/synthetics/markets/createSourceChainDepositTxn"; import { createSourceChainGlvDepositTxn } from "domain/synthetics/markets/createSourceChainGlvDepositTxn"; +import { TechnicalGmFees } from "domain/synthetics/markets/technicalFees/technical-fees-types"; import { ERC20Address, NativeTokenSupportedAddress, TokenBalanceType } from "domain/tokens"; import { helperToast } from "lib/helperToast"; import { diff --git a/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useLpTransactions.tsx b/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useLpTransactions.tsx index b39a869365..adc4aaa8d0 100644 --- a/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useLpTransactions.tsx +++ b/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useLpTransactions.tsx @@ -2,11 +2,11 @@ import { useCallback, useState } from "react"; import { selectPoolsDetailsOperation } from "context/PoolsDetailsContext/selectors"; import { useSelector } from "context/SyntheticsStateContext/utils"; -import { TechnicalGmFees } from "domain/multichain/technical-fees-types"; +import { TechnicalGmFees } from "domain/synthetics/markets/technicalFees/technical-fees-types"; +import { Operation } from "domain/synthetics/markets/types"; import { useDepositTransactions } from "./useDepositTransactions"; import { useWithdrawalTransactions } from "./useWithdrawalTransactions"; -import { Operation } from "../../types"; export interface UseLpTransactionProps { shouldDisableValidation?: boolean; diff --git a/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx b/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx index d98059d056..19311eadea 100644 --- a/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx +++ b/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/lpTxn/useWithdrawalTransactions.tsx @@ -29,7 +29,6 @@ import { TokensBalancesUpdates, useTokensBalancesUpdates, } from "context/TokensBalancesContext/TokensBalancesContextProvider"; -import { buildWithdrawalTransferRequests } from "domain/multichain/buildWithdrawalTransferRequests"; import { GlvSellTask, GmSellTask } from "domain/multichain/progress/GmOrGlvSellProgress"; import { toastCustomOrStargateError } from "domain/multichain/toastCustomOrStargateError"; import { TransferRequests } from "domain/multichain/types"; @@ -40,6 +39,7 @@ import { RawCreateGlvWithdrawalParams, RawCreateWithdrawalParams, } from "domain/synthetics/markets"; +import { buildWithdrawalTransferRequests } from "domain/synthetics/markets/buildWithdrawalTransferRequests"; import { createGlvWithdrawalTxn } from "domain/synthetics/markets/createGlvWithdrawalTxn"; import { createMultichainGlvWithdrawalTxn } from "domain/synthetics/markets/createMultichainGlvWithdrawalTxn"; import { createMultichainWithdrawalTxn } from "domain/synthetics/markets/createMultichainWithdrawalTxn"; @@ -535,10 +535,8 @@ function useWithdrawalTransferRequests(): TransferRequests | undefined { isWithdrawal, isGlv, chainId: chainId, - glvTokenAddress, - glvTokenAmount, - marketTokenAddress, - marketTokenAmount, + glvOrMarketTokenAddress: isGlv ? glvTokenAddress : marketTokenAddress, + glvOrMarketAmount: isGlv ? glvTokenAmount : marketTokenAmount, }); }, [chainId, glvTokenAddress, glvTokenAmount, isGlv, isWithdrawal, marketTokenAddress, marketTokenAmount]); } diff --git a/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/useDepositWithdrawalFees.tsx b/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/useDepositWithdrawalFees.tsx index 4e09bc2980..787e13d1c1 100644 --- a/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/useDepositWithdrawalFees.tsx +++ b/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/useDepositWithdrawalFees.tsx @@ -1,15 +1,79 @@ import { useMemo } from "react"; -import { TechnicalGmFees } from "domain/multichain/technical-fees-types"; import { useGasMultichainUsd, useNativeTokenMultichainUsd } from "domain/multichain/useMultichainQuoteFeeUsd"; import { getFeeItem, getTotalFeeItem, type FeeItem, type GasLimitsConfig } from "domain/synthetics/fees"; import { GlvInfo } from "domain/synthetics/markets"; -import { convertToUsd, getMidPrice, TokensData } from "domain/synthetics/tokens"; +import type { TechnicalGmFees } from "domain/synthetics/markets/technicalFees/technical-fees-types"; +import { convertToUsd, getMidPrice, TokenData, TokensData } from "domain/synthetics/tokens"; import { DepositAmounts, GmSwapFees, WithdrawalAmounts } from "domain/synthetics/trade"; import { getByKey } from "lib/objects"; import { ContractsChainId, SourceChainId } from "sdk/configs/chains"; import { getWrappedToken } from "sdk/configs/tokens"; +function calculateLogicalNetworkFeeUsd({ + technicalFees, + wrappedTokenData, + sourceChainEstimatedNativeFeeUsd, + sourceChainTxnEstimatedGasUsd, +}: { + technicalFees: TechnicalGmFees; + wrappedTokenData: TokenData | undefined; + sourceChainEstimatedNativeFeeUsd: bigint | undefined; + sourceChainTxnEstimatedGasUsd: bigint | undefined; +}): bigint | undefined { + if (technicalFees.kind === "settlementChain") { + if (!wrappedTokenData) { + return undefined; + } + const wrappedTokenPrice = getMidPrice(wrappedTokenData.prices); + const keeperUsd = convertToUsd(technicalFees.fees.feeTokenAmount, wrappedTokenData.decimals, wrappedTokenPrice)!; + return keeperUsd * -1n; + } + + if (technicalFees.kind === "gmxAccount") { + return (technicalFees.fees.executionFee.feeUsd + technicalFees.fees.relayFeeUsd) * -1n; + } + + if (technicalFees.kind === "sourceChain") { + return ((sourceChainEstimatedNativeFeeUsd ?? 0n) + (sourceChainTxnEstimatedGasUsd ?? 0n)) * -1n; + } + + return 0n; +} + +function calculateLogicalFees({ + amounts, + isDeposit, + logicalNetworkFeeUsd, +}: { + amounts: DepositAmounts | WithdrawalAmounts; + isDeposit: boolean; + logicalNetworkFeeUsd: bigint; +}): GmSwapFees { + const basisUsd = isDeposit + ? (amounts.longTokenUsd ?? 0n) + (amounts.shortTokenUsd ?? 0n) + : amounts.marketTokenUsd ?? 0n; + + const swapFee = getFeeItem(amounts.swapFeeUsd * -1n, basisUsd); + const swapPriceImpact = getFeeItem(amounts.swapPriceImpactDeltaUsd, basisUsd); + const uiFee = getFeeItem(amounts.uiFeeUsd * -1n, basisUsd, { + shouldRoundUp: true, + }); + + const logicalNetworkFee = getFeeItem(logicalNetworkFeeUsd, basisUsd)!; + // TODO ADD stargate protocol fees + const logicalProtocolFee = getTotalFeeItem([swapFee, uiFee, swapPriceImpact].filter(Boolean) as FeeItem[]); + + const logicalFees: GmSwapFees = { + totalFees: logicalProtocolFee, + swapPriceImpact, + logicalNetworkFee, + swapFee, + }; + + return logicalFees; +} + export const useDepositWithdrawalFees = ({ amounts, chainId, @@ -30,7 +94,7 @@ export const useDepositWithdrawalFees = ({ isMarketTokenDeposit: boolean; technicalFees: TechnicalGmFees | undefined; srcChainId: SourceChainId | undefined; -}): { logicalFees?: GmSwapFees } => { +}): GmSwapFees | undefined => { const sourceChainEstimatedNativeFeeUsd = useNativeTokenMultichainUsd({ sourceChainTokenAmount: technicalFees?.kind === "sourceChain" ? technicalFees.fees.txnEstimatedNativeFee : undefined, @@ -46,50 +110,28 @@ export const useDepositWithdrawalFees = ({ return useMemo(() => { if (!gasLimits || gasPrice === undefined || !tokensData || !amounts || !technicalFees) { - return { logicalFees: undefined }; + return undefined; } - const basisUsd = isDeposit - ? (amounts?.longTokenUsd ?? 0n) + (amounts?.shortTokenUsd ?? 0n) - : amounts?.marketTokenUsd || 0n; + const wrappedToken = getWrappedToken(chainId); + const wrappedTokenData = getByKey(tokensData, wrappedToken.address); - const swapFee = getFeeItem(amounts.swapFeeUsd * -1n, basisUsd); - const swapPriceImpact = getFeeItem(amounts.swapPriceImpactDeltaUsd, basisUsd); - const uiFee = getFeeItem(amounts.uiFeeUsd * -1n, basisUsd, { - shouldRoundUp: true, + const logicalNetworkFeeUsd = calculateLogicalNetworkFeeUsd({ + technicalFees, + wrappedTokenData, + sourceChainEstimatedNativeFeeUsd, + sourceChainTxnEstimatedGasUsd, }); - let logicalNetworkFeeUsd = 0n; - - if (technicalFees.kind === "settlementChain") { - const wrappedToken = getWrappedToken(chainId); - const wrappedTokenData = getByKey(tokensData, wrappedToken.address); - if (!wrappedTokenData) { - return { logicalFees: undefined }; - } - const wrappedTokenPrice = getMidPrice(wrappedTokenData.prices); - const keeperUsd = convertToUsd(technicalFees.fees.feeTokenAmount, wrappedToken.decimals, wrappedTokenPrice)!; - logicalNetworkFeeUsd = keeperUsd * -1n; - } else if (technicalFees.kind === "gmxAccount") { - logicalNetworkFeeUsd = (technicalFees.fees.executionFee.feeUsd + technicalFees.fees.relayFeeUsd) * -1n; - } else if (technicalFees.kind === "sourceChain") { - logicalNetworkFeeUsd = ((sourceChainEstimatedNativeFeeUsd ?? 0n) + (sourceChainTxnEstimatedGasUsd ?? 0n)) * -1n; + if (logicalNetworkFeeUsd === undefined) { + return undefined; } - const logicalNetworkFee = getFeeItem(logicalNetworkFeeUsd, basisUsd)!; - // TODO ADD stargate protocol fees - const logicalProtocolFee = getTotalFeeItem([swapFee, uiFee, swapPriceImpact].filter(Boolean) as FeeItem[]); - - const logicalFees: GmSwapFees = { - totalFees: logicalProtocolFee, - swapPriceImpact, - logicalNetworkFee, - swapFee, - }; - - return { - logicalFees, - }; + return calculateLogicalFees({ + amounts, + isDeposit, + logicalNetworkFeeUsd, + }); }, [ amounts, chainId, diff --git a/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/useGmSwapSubmitState.tsx b/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/useGmSwapSubmitState.tsx index 0987b4d9a8..36457f1bd5 100644 --- a/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/useGmSwapSubmitState.tsx +++ b/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/useGmSwapSubmitState.tsx @@ -21,10 +21,11 @@ import { selectGasPaymentToken } from "context/SyntheticsStateContext/selectors/ import { selectChainId, selectSrcChainId } from "context/SyntheticsStateContext/selectors/globalSelectors"; import { selectGasPaymentTokenAddress } from "context/SyntheticsStateContext/selectors/settingsSelectors"; import { useSelector } from "context/SyntheticsStateContext/utils"; -import { TechnicalGmFees } from "domain/multichain/technical-fees-types"; import { useSourceChainNativeFeeError } from "domain/multichain/useSourceChainNetworkFeeError"; import { ExpressEstimationInsufficientGasPaymentTokenBalanceError } from "domain/synthetics/express/expressOrderUtils"; import type { GlvAndGmMarketsInfoData, GmPaySource, MarketsInfoData } from "domain/synthetics/markets"; +import { TechnicalGmFees } from "domain/synthetics/markets/technicalFees/technical-fees-types"; +import { Operation } from "domain/synthetics/markets/types"; import { convertToTokenAmount, type TokenData } from "domain/synthetics/tokens"; import { getCommonError, getGmSwapError } from "domain/synthetics/trade/utils/validation"; import { useHasOutdatedUi } from "lib/useHasOutdatedUi"; @@ -34,7 +35,6 @@ import { bigMath } from "sdk/utils/bigmath"; import SpinnerIcon from "img/ic_spinner.svg?react"; -import { Operation } from "../types"; import { useLpTransactions } from "./lpTxn/useLpTransactions"; import { useTokensToApprove } from "./useTokensToApprove"; diff --git a/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/useTechnicalFeesAsyncResult.tsx b/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/useTechnicalFeesAsyncResult.tsx index 06a9c27fe3..f737c043a2 100644 --- a/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/useTechnicalFeesAsyncResult.tsx +++ b/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/useTechnicalFeesAsyncResult.tsx @@ -1,4 +1,3 @@ -import { SettlementChainId, SourceChainId } from "config/chains"; import { selectPoolsDetailsFirstTokenAddress, selectPoolsDetailsFirstTokenAmount, @@ -20,40 +19,14 @@ import { selectTokensData, } from "context/SyntheticsStateContext/selectors/globalSelectors"; import { useSelector } from "context/SyntheticsStateContext/utils"; -import { estimateArbitraryRelayFee, getRawBaseRelayerParams } from "domain/multichain/arbitraryRelayParams"; -import { buildDepositTransferRequests } from "domain/multichain/buildDepositTransferRequests"; -import { buildWithdrawalTransferRequests } from "domain/multichain/buildWithdrawalTransferRequests"; -import { TechnicalGmFees } from "domain/multichain/technical-fees-types"; -import { ExpressTransactionBuilder } from "domain/synthetics/express/types"; -import { - RawCreateDepositParams, - RawCreateGlvDepositParams, - RawCreateGlvWithdrawalParams, - RawCreateWithdrawalParams, -} from "domain/synthetics/markets"; -import { buildAndSignMultichainDepositTxn } from "domain/synthetics/markets/createMultichainDepositTxn"; -import { buildAndSignMultichainGlvDepositTxn } from "domain/synthetics/markets/createMultichainGlvDepositTxn"; -import { buildAndSignMultichainGlvWithdrawalTxn } from "domain/synthetics/markets/createMultichainGlvWithdrawalTxn"; -import { buildAndSignMultichainWithdrawalTxn } from "domain/synthetics/markets/createMultichainWithdrawalTxn"; -import { estimatePureLpActionExecutionFee } from "domain/synthetics/markets/feeEstimation/estimatePureLpActionExecutionFee"; -import { estimateSourceChainDepositFees } from "domain/synthetics/markets/feeEstimation/estimateSourceChainDepositFees"; -import { estimateSourceChainGlvDepositFees } from "domain/synthetics/markets/feeEstimation/estimateSourceChainGlvDepositFees"; -import { estimateSourceChainGlvWithdrawalFees } from "domain/synthetics/markets/feeEstimation/estimateSourceChainGlvWithdrawalFees"; -import { estimateSourceChainWithdrawalFees } from "domain/synthetics/markets/feeEstimation/estimateSourceChainWithdrawalFees"; -import { convertToUsd } from "domain/tokens"; +import { calculateTechnicalFees } from "domain/synthetics/markets/technicalFees/calculateTechnicalFees"; +import type { TechnicalGmFees } from "domain/synthetics/markets/technicalFees/technical-fees-types"; import { useChainId } from "lib/chains"; import { usePrevious } from "lib/usePrevious"; import { useThrottledAsync } from "lib/useThrottledAsync"; -import { getPublicClientWithRpc } from "lib/wallets/rainbowKitConfig"; -import { DEFAULT_EXPRESS_ORDER_DEADLINE_DURATION } from "sdk/configs/express"; -import { MARKETS } from "sdk/configs/markets"; -import { WithdrawalAmounts } from "sdk/types/trade"; import { absDiffBps } from "sdk/utils/numbers"; -import { nowInSeconds } from "sdk/utils/time"; - -import { Operation } from "../types"; -export function useTechnicalFees(): TechnicalGmFees { +export function useTechnicalFees(): TechnicalGmFees | undefined { const { chainId, srcChainId } = useChainId(); const operation = useSelector(selectPoolsDetailsOperation); @@ -90,573 +63,33 @@ export function useTechnicalFees(): TechnicalGmFees { const rawParams = useSelector(selectPoolsDetailsParams); const amounts = useSelector(selectDepositWithdrawalAmounts); - const technicalFeesAsyncResult = useThrottledAsync( - async (p): Promise => { - if (p.params.paySource === "settlementChain") { - if (p.params.operation === Operation.Deposit) { - if (p.params.isGlv) { - const castedParams = p.params.rawParams as RawCreateGlvDepositParams; - const fees = estimatePureLpActionExecutionFee({ - action: { - operation: Operation.Deposit, - isGlv: true, - marketsCount: BigInt(p.params.glvInfo!.markets.length), - swapsCount: BigInt( - castedParams.addresses.longTokenSwapPath.length + castedParams.addresses.shortTokenSwapPath.length - ), - isMarketTokenDeposit: castedParams.isMarketTokenDeposit, - }, - chainId: p.params.chainId, - gasLimits: p.params.gasLimits, - tokensData: p.params.tokensData, - gasPrice: p.params.gasPrice, - }); - - return { - kind: "settlementChain", - fees, - isDeposit: true, - isGlv: true, - }; - } else { - const castedParams = p.params.rawParams as RawCreateDepositParams; - const fees = estimatePureLpActionExecutionFee({ - action: { - operation: Operation.Deposit, - isGlv: false, - swapsCount: BigInt( - castedParams.addresses.longTokenSwapPath.length + castedParams.addresses.shortTokenSwapPath.length - ), - }, - chainId: p.params.chainId, - gasLimits: p.params.gasLimits, - tokensData: p.params.tokensData, - gasPrice: p.params.gasPrice, - }); - - return { - kind: "settlementChain", - fees, - isDeposit: true, - isGlv: false, - }; - } - } else if (p.params.operation === Operation.Withdrawal) { - if (p.params.isGlv) { - const castedParams = p.params.rawParams as RawCreateGlvWithdrawalParams; - const fees = estimatePureLpActionExecutionFee({ - action: { - operation: Operation.Withdrawal, - isGlv: true, - marketsCount: BigInt(p.params.glvInfo!.markets.length), - swapsCount: BigInt( - castedParams.addresses.longTokenSwapPath.length + castedParams.addresses.shortTokenSwapPath.length - ), - }, - chainId: p.params.chainId, - gasLimits: p.params.gasLimits, - tokensData: p.params.tokensData, - gasPrice: p.params.gasPrice, - }); - - return { - kind: "settlementChain", - fees, - isDeposit: false, - isGlv: true, - }; - } else { - const castedParams = p.params.rawParams as RawCreateWithdrawalParams; - const fees = estimatePureLpActionExecutionFee({ - action: { - operation: Operation.Withdrawal, - isGlv: false, - swapsCount: BigInt( - castedParams.addresses.longTokenSwapPath.length + castedParams.addresses.shortTokenSwapPath.length - ), - }, - chainId: p.params.chainId, - gasLimits: p.params.gasLimits, - tokensData: p.params.tokensData, - gasPrice: p.params.gasPrice, - }); - - return { - kind: "settlementChain", - fees, - isDeposit: false, - isGlv: false, - }; - } - } - } else if (p.params.paySource === "gmxAccount") { - if (!p.params.globalExpressParams) { - return undefined; - } - - const { rawBaseRelayParamsPayload, baseRelayFeeSwapParams } = getRawBaseRelayerParams({ - chainId, - account: p.params.rawParams.addresses.receiver, - globalExpressParams: p.params.globalExpressParams, - }); - - if (!rawBaseRelayParamsPayload || !baseRelayFeeSwapParams) { - return undefined; - } - - if (p.params.operation === Operation.Deposit) { - if (p.params.isGlv) { - const castedParams = p.params.rawParams as RawCreateGlvDepositParams; - const executionFee = estimatePureLpActionExecutionFee({ - action: { - operation: Operation.Deposit, - isGlv: true, - marketsCount: BigInt(p.params.glvInfo!.markets.length), - swapsCount: BigInt( - castedParams.addresses.longTokenSwapPath.length + castedParams.addresses.shortTokenSwapPath.length - ), - isMarketTokenDeposit: castedParams.isMarketTokenDeposit, - }, - chainId: p.params.chainId, - gasLimits: p.params.gasLimits, - tokensData: p.params.tokensData, - gasPrice: p.params.gasPrice, - }); - - const transferRequests = buildDepositTransferRequests({ - isDeposit: true, - isGlv: true, - chainId: p.params.chainId, - paySource: p.params.paySource, - isMarketTokenDeposit: castedParams.isMarketTokenDeposit, - marketTokenAddress: p.params.rawParams.addresses.market, - marketTokenAmount: p.params.firstTokenAmount, - longTokenAmount: p.params.firstTokenAmount, - shortTokenAmount: p.params.secondTokenAmount, - initialLongTokenAddress: castedParams.addresses.initialLongToken, - initialShortTokenAddress: castedParams.addresses.initialShortToken, - technicalFees: undefined, - }); - - if (!transferRequests) { - return undefined; - } - - const expressTransactionBuilder: ExpressTransactionBuilder = async ({ relayParams, gasPaymentParams }) => { - return { - txnData: await buildAndSignMultichainGlvDepositTxn({ - chainId: p.params.chainId, - srcChainId: p.params.srcChainId, - emptySignature: true, - signer: undefined, - account: p.params.rawParams.addresses.receiver, - params: { ...castedParams, executionFee: executionFee.feeTokenAmount }, - relayerFeeAmount: gasPaymentParams.relayerFeeAmount, - relayerFeeTokenAddress: gasPaymentParams.relayerFeeTokenAddress, - relayParams: { - ...relayParams, - deadline: BigInt(nowInSeconds() + DEFAULT_EXPRESS_ORDER_DEADLINE_DURATION), - }, - transferRequests, - }), - }; - }; - - const relayFee = await estimateArbitraryRelayFee({ - account: p.params.rawParams.addresses.receiver, - chainId: p.params.chainId, - client: getPublicClientWithRpc(p.params.chainId), - rawRelayParamsPayload: rawBaseRelayParamsPayload, - expressTransactionBuilder: expressTransactionBuilder, - gasPaymentParams: baseRelayFeeSwapParams.gasPaymentParams, - subaccount: undefined, - }); - - const relayFeeUsd = convertToUsd( - relayFee, - p.params.globalExpressParams.relayerFeeToken.decimals, - p.params.globalExpressParams.relayerFeeToken.prices.maxPrice - )!; - - return { - kind: "gmxAccount", - fees: { - executionFee, - relayFeeUsd, - }, - isDeposit: true, - isGlv: true, - }; - } else { - const castedParams = p.params.rawParams as RawCreateDepositParams; - const executionFee = estimatePureLpActionExecutionFee({ - action: { - operation: Operation.Deposit, - isGlv: false, - swapsCount: BigInt( - castedParams.addresses.longTokenSwapPath.length + castedParams.addresses.shortTokenSwapPath.length - ), - }, - chainId: p.params.chainId, - gasLimits: p.params.gasLimits, - tokensData: p.params.tokensData, - gasPrice: p.params.gasPrice, - }); - - const transferRequests = buildDepositTransferRequests({ - isDeposit: true, - isGlv: false, - chainId: p.params.chainId, - paySource: p.params.paySource, - isMarketTokenDeposit: false, - marketTokenAddress: undefined, - marketTokenAmount: 0n, - longTokenAmount: p.params.firstTokenAmount, - shortTokenAmount: p.params.secondTokenAmount, - initialLongTokenAddress: castedParams.addresses.initialLongToken, - initialShortTokenAddress: castedParams.addresses.initialShortToken, - technicalFees: undefined, - }); - - if (!transferRequests) { - return undefined; - } - - const expressTransactionBuilder: ExpressTransactionBuilder = async ({ relayParams, gasPaymentParams }) => { - return { - txnData: await buildAndSignMultichainDepositTxn({ - chainId: p.params.chainId, - srcChainId: p.params.srcChainId, - emptySignature: true, - signer: undefined, - account: p.params.rawParams.addresses.receiver, - params: { ...castedParams, executionFee: executionFee.feeTokenAmount }, - relayerFeeAmount: gasPaymentParams.relayerFeeAmount, - relayerFeeTokenAddress: gasPaymentParams.relayerFeeTokenAddress, - relayParams: { - ...relayParams, - deadline: BigInt(nowInSeconds() + DEFAULT_EXPRESS_ORDER_DEADLINE_DURATION), - }, - transferRequests, - }), - }; - }; - - const relayFee = await estimateArbitraryRelayFee({ - account: p.params.rawParams.addresses.receiver, - chainId: p.params.chainId, - client: getPublicClientWithRpc(p.params.chainId), - rawRelayParamsPayload: rawBaseRelayParamsPayload, - expressTransactionBuilder: expressTransactionBuilder, - gasPaymentParams: baseRelayFeeSwapParams.gasPaymentParams, - subaccount: undefined, - }); - - const relayFeeUsd = convertToUsd( - relayFee, - p.params.globalExpressParams.relayerFeeToken.decimals, - p.params.globalExpressParams.relayerFeeToken.prices.maxPrice - )!; - - return { - kind: "gmxAccount", - fees: { - executionFee, - relayFeeUsd, - }, - isDeposit: true, - isGlv: false, - }; - } - } else if (p.params.operation === Operation.Withdrawal) { - if (p.params.isGlv) { - const castedParams = p.params.rawParams as RawCreateGlvWithdrawalParams; - const fees = estimatePureLpActionExecutionFee({ - action: { - operation: Operation.Withdrawal, - isGlv: true, - marketsCount: BigInt(p.params.glvInfo!.markets.length), - swapsCount: BigInt( - castedParams.addresses.longTokenSwapPath.length + castedParams.addresses.shortTokenSwapPath.length - ), - }, - chainId: p.params.chainId, - gasLimits: p.params.gasLimits, - tokensData: p.params.tokensData, - gasPrice: p.params.gasPrice, - }); - - const transferRequests = buildWithdrawalTransferRequests({ - isWithdrawal: true, - isGlv: true, - chainId: p.params.chainId, - glvTokenAddress: castedParams.addresses.glv, - glvTokenAmount: p.params.marketTokenAmount, - marketTokenAddress: undefined, - marketTokenAmount: 0n, - }); - - if (!transferRequests) { - return undefined; - } - - const expressTransactionBuilder: ExpressTransactionBuilder = async ({ relayParams, gasPaymentParams }) => { - return { - txnData: await buildAndSignMultichainGlvWithdrawalTxn({ - chainId: p.params.chainId, - srcChainId: p.params.srcChainId, - emptySignature: true, - signer: undefined, - account: p.params.rawParams.addresses.receiver, - params: { ...castedParams, executionFee: fees.feeTokenAmount }, - relayerFeeAmount: gasPaymentParams.relayerFeeAmount, - relayerFeeTokenAddress: gasPaymentParams.relayerFeeTokenAddress, - relayParams: { - ...relayParams, - deadline: BigInt(nowInSeconds() + DEFAULT_EXPRESS_ORDER_DEADLINE_DURATION), - }, - transferRequests, - }), - }; - }; - - const relayFee = await estimateArbitraryRelayFee({ - account: p.params.rawParams.addresses.receiver, - chainId: p.params.chainId, - client: getPublicClientWithRpc(p.params.chainId), - rawRelayParamsPayload: rawBaseRelayParamsPayload, - expressTransactionBuilder: expressTransactionBuilder, - gasPaymentParams: baseRelayFeeSwapParams.gasPaymentParams, - subaccount: undefined, - }); - - const relayFeeUsd = convertToUsd( - relayFee, - p.params.globalExpressParams.relayerFeeToken.decimals, - p.params.globalExpressParams.relayerFeeToken.prices.maxPrice - )!; - - return { - kind: "gmxAccount", - fees: { - executionFee: fees, - relayFeeUsd, - }, - isDeposit: false, - isGlv: true, - }; - } else { - const castedParams = p.params.rawParams as RawCreateWithdrawalParams; - const fees = estimatePureLpActionExecutionFee({ - action: { - operation: Operation.Withdrawal, - isGlv: false, - swapsCount: BigInt( - castedParams.addresses.longTokenSwapPath.length + castedParams.addresses.shortTokenSwapPath.length - ), - }, - chainId: p.params.chainId, - gasLimits: p.params.gasLimits, - tokensData: p.params.tokensData, - gasPrice: p.params.gasPrice, - }); - - const transferRequests = buildWithdrawalTransferRequests({ - isWithdrawal: true, - isGlv: false, - chainId: p.params.chainId, - glvTokenAddress: undefined, - glvTokenAmount: 0n, - marketTokenAddress: castedParams.addresses.market, - marketTokenAmount: p.params.marketTokenAmount, - }); - - if (!transferRequests) { - return undefined; - } - - const expressTransactionBuilder: ExpressTransactionBuilder = async ({ relayParams, gasPaymentParams }) => { - return { - txnData: await buildAndSignMultichainWithdrawalTxn({ - chainId: p.params.chainId, - srcChainId: p.params.srcChainId, - emptySignature: true, - signer: undefined as any, - account: p.params.rawParams.addresses.receiver, - params: { ...castedParams, executionFee: fees.feeTokenAmount }, - relayerFeeAmount: gasPaymentParams.relayerFeeAmount, - relayerFeeTokenAddress: gasPaymentParams.relayerFeeTokenAddress, - relayParams: { - ...relayParams, - deadline: BigInt(nowInSeconds() + DEFAULT_EXPRESS_ORDER_DEADLINE_DURATION), - }, - transferRequests, - }), - }; - }; - - const relayFee = await estimateArbitraryRelayFee({ - account: p.params.rawParams.addresses.receiver, - chainId: p.params.chainId, - client: getPublicClientWithRpc(p.params.chainId), - rawRelayParamsPayload: rawBaseRelayParamsPayload, - expressTransactionBuilder: expressTransactionBuilder, - gasPaymentParams: baseRelayFeeSwapParams.gasPaymentParams, - subaccount: undefined, - }); - - const relayFeeUsd = convertToUsd( - relayFee, - p.params.globalExpressParams.relayerFeeToken.decimals, - p.params.globalExpressParams.relayerFeeToken.prices.maxPrice - )!; - - return { - kind: "gmxAccount", - fees: { - executionFee: fees, - relayFeeUsd, - }, - isDeposit: false, - isGlv: false, - }; - } - } - } else if (p.params.paySource === "sourceChain") { - if ( - p.params.firstTokenAddress === undefined || - p.params.firstTokenAmount === undefined || - !p.params.globalExpressParams - ) { - return undefined; - } - if (p.params.operation === Operation.Deposit) { - if (p.params.isGlv) { - const castedParams = p.params.rawParams as RawCreateGlvDepositParams; - const fees = await estimateSourceChainGlvDepositFees({ - chainId: p.params.chainId as SettlementChainId, - srcChainId: p.params.srcChainId as SourceChainId, - params: castedParams, - tokenAddress: p.params.firstTokenAddress, - tokenAmount: p.params.firstTokenAmount, - globalExpressParams: p.params.globalExpressParams, - glvMarketCount: BigInt(p.params.glvInfo!.markets.length), - }); - - return { - kind: "sourceChain", - isGlv: true, - isDeposit: true, - fees, - }; - } else { - const castedParams = p.params.rawParams as RawCreateDepositParams; - const fees = await estimateSourceChainDepositFees({ - chainId: p.params.chainId as SettlementChainId, - srcChainId: p.params.srcChainId as SourceChainId, - params: castedParams, - tokenAddress: p.params.firstTokenAddress, - tokenAmount: p.params.firstTokenAmount, - globalExpressParams: p.params.globalExpressParams, - }); - return { - kind: "sourceChain", - isGlv: false, - isDeposit: true, - fees, - }; - } - } else if (p.params.operation === Operation.Withdrawal) { - if (p.params.isGlv) { - const castedParams = p.params.rawParams as RawCreateGlvWithdrawalParams; - const glvWithdrawalAmounts = p.params.amounts as WithdrawalAmounts; - const outputLongTokenAddress = - glvWithdrawalAmounts.longTokenSwapPathStats?.tokenOutAddress ?? glvInfo!.longTokenAddress; - const outputShortTokenAddress = - glvWithdrawalAmounts.shortTokenSwapPathStats?.tokenOutAddress ?? glvInfo!.shortTokenAddress; - - const fees = await estimateSourceChainGlvWithdrawalFees({ - chainId: p.params.chainId as SettlementChainId, - srcChainId: p.params.srcChainId as SourceChainId, - params: castedParams, - tokenAddress: castedParams.addresses.glv, - tokenAmount: p.params.marketTokenAmount, - globalExpressParams: p.params.globalExpressParams, - marketsCount: BigInt(p.params.glvInfo!.markets.length), - outputLongTokenAddress, - outputShortTokenAddress, - }); - - return { - kind: "sourceChain", - isGlv: true, - isDeposit: false, - fees, - }; - } else { - const castedParams = p.params.rawParams as RawCreateWithdrawalParams; - if (!p.params.amounts) { - return undefined; - } - - const gmWithdrawalAmounts = p.params.amounts as WithdrawalAmounts; - - const outputLongTokenAddress = - gmWithdrawalAmounts.longTokenSwapPathStats?.tokenOutAddress ?? - MARKETS[p.params.chainId][p.params.rawParams.addresses.market].longTokenAddress; - const outputShortTokenAddress = - gmWithdrawalAmounts.shortTokenSwapPathStats?.tokenOutAddress ?? - MARKETS[p.params.chainId][p.params.rawParams.addresses.market].shortTokenAddress; - - const fees = await estimateSourceChainWithdrawalFees({ - chainId: p.params.chainId as SettlementChainId, - srcChainId: p.params.srcChainId as SourceChainId, - params: castedParams, - tokenAddress: p.params.rawParams.addresses.market, - tokenAmount: p.params.marketTokenAmount, - globalExpressParams: p.params.globalExpressParams, - outputLongTokenAddress, - outputShortTokenAddress, - }); - - return { - kind: "sourceChain", - isGlv: false, - isDeposit: false, - fees, - }; + const technicalFeesAsyncResult = useThrottledAsync(async (p) => calculateTechnicalFees(p.params), { + params: + rawParams && gasLimits && tokensData && gasPrice !== undefined + ? { + chainId, + globalExpressParams, + rawParams, + isGlv, + glvInfo, + paySource, + srcChainId, + firstTokenAddress, + firstTokenAmount, + secondTokenAddress, + secondTokenAmount, + marketTokenAmount: marketOrGlvTokenAmount, + operation, + amounts, + gasLimits, + tokensData, + gasPrice, } - } - } - }, - { - params: - rawParams && gasLimits && tokensData && gasPrice !== undefined - ? { - chainId, - globalExpressParams, - rawParams, - isGlv, - glvInfo, - paySource, - srcChainId, - firstTokenAddress, - firstTokenAmount, - secondTokenAddress, - secondTokenAmount, - marketTokenAmount: marketOrGlvTokenAmount, - operation, - amounts, - gasLimits, - tokensData, - gasPrice, - } - : undefined, - withLoading: false, - forceRecalculate, - resetOnForceRecalculate: true, - } - ); + : undefined, + withLoading: false, + forceRecalculate, + resetOnForceRecalculate: true, + }); return technicalFeesAsyncResult.data; } diff --git a/src/components/GmSwap/GmSwapBox/GmShiftBox/GmShiftBox.tsx b/src/components/GmSwap/GmSwapBox/GmShiftBox/GmShiftBox.tsx index fd1c38a053..ceccb79bd9 100644 --- a/src/components/GmSwap/GmSwapBox/GmShiftBox/GmShiftBox.tsx +++ b/src/components/GmSwap/GmSwapBox/GmShiftBox/GmShiftBox.tsx @@ -16,6 +16,7 @@ import { selectShiftAvailableMarkets } from "context/SyntheticsStateContext/sele import { useSelector } from "context/SyntheticsStateContext/utils"; import { GlvOrMarketInfo, getGlvOrMarketAddress, getMarketIndexName } from "domain/synthetics/markets"; import { isGlvInfo } from "domain/synthetics/markets/glv"; +import { Operation } from "domain/synthetics/markets/types"; import { useMarketTokensData } from "domain/synthetics/markets/useMarketTokensData"; import useSortedPoolsWithIndexToken from "domain/synthetics/trade/useSortedPoolsWithIndexToken"; import { ERC20Address, NativeTokenSupportedAddress } from "domain/tokens"; @@ -34,7 +35,6 @@ import { SwitchToSettlementChainWarning } from "components/SwitchToSettlementCha import { GmFees } from "../../GmFees/GmFees"; import { GmSwapWarningsRow } from "../GmSwapWarningsRow"; import { SelectedPool } from "../SelectedPool"; -import { Operation } from "../types"; import { useGmWarningState } from "../useGmWarningState"; import { useShiftAmounts } from "./useShiftAmounts"; import { useShiftAvailableRelatedMarkets } from "./useShiftAvailableRelatedMarkets"; diff --git a/src/components/GmSwap/GmSwapBox/GmSwapBox.tsx b/src/components/GmSwap/GmSwapBox/GmSwapBox.tsx index cdedb4a9fc..ef8a12643a 100644 --- a/src/components/GmSwap/GmSwapBox/GmSwapBox.tsx +++ b/src/components/GmSwap/GmSwapBox/GmSwapBox.tsx @@ -12,13 +12,13 @@ import { selectPoolsDetailsSetSelectedMarketAddressForGlv, } from "context/PoolsDetailsContext/selectors"; import { useSelector } from "context/SyntheticsStateContext/utils"; +import { Mode, Operation } from "domain/synthetics/markets/types"; import { useLocalizedMap } from "lib/i18n"; import Tabs from "components/Tabs/Tabs"; import { GmSwapBoxDepositWithdrawal } from "./GmDepositWithdrawalBox/GmDepositWithdrawalBox"; import { GmShiftBox } from "./GmShiftBox/GmShiftBox"; -import { Mode, Operation } from "./types"; import "./GmSwapBox.scss"; diff --git a/src/components/GmSwap/GmSwapBox/GmSwapBoxHeader.tsx b/src/components/GmSwap/GmSwapBox/GmSwapBoxHeader.tsx index 206517fdd6..97a596d970 100644 --- a/src/components/GmSwap/GmSwapBox/GmSwapBoxHeader.tsx +++ b/src/components/GmSwap/GmSwapBox/GmSwapBoxHeader.tsx @@ -10,14 +10,13 @@ import { selectGlvAndMarketsInfoData } from "context/SyntheticsStateContext/sele import { selectShiftAvailableMarkets } from "context/SyntheticsStateContext/selectors/shiftSelectors"; import { useSelector } from "context/SyntheticsStateContext/utils"; import { isGlvInfo } from "domain/synthetics/markets/glv"; +import { Operation } from "domain/synthetics/markets/types"; import { getGlvOrMarketAddress } from "domain/synthetics/markets/utils"; import { useLocalizedMap } from "lib/i18n"; import { getByKey } from "lib/objects"; import Tabs from "components/Tabs/Tabs"; -import { Operation } from "./types"; - const OPERATION_LABELS_GM = { [Operation.Deposit]: msg`Buy GM`, [Operation.Withdrawal]: msg`Sell GM`, diff --git a/src/components/GmSwap/GmSwapBox/getGmSwapBoxAvailableModes.tsx b/src/components/GmSwap/GmSwapBox/getGmSwapBoxAvailableModes.tsx index f194d4a403..a528000bd6 100644 --- a/src/components/GmSwap/GmSwapBox/getGmSwapBoxAvailableModes.tsx +++ b/src/components/GmSwap/GmSwapBox/getGmSwapBoxAvailableModes.tsx @@ -1,6 +1,4 @@ -import { GmPaySource, Market } from "domain/synthetics/markets/types"; - -import { Mode, Operation } from "./types"; +import { GmPaySource, Market, Mode, Operation } from "domain/synthetics/markets/types"; export function getGmSwapBoxAvailableModes({ operation, diff --git a/src/components/GmSwap/GmSwapBox/types.ts b/src/components/GmSwap/GmSwapBox/types.ts deleted file mode 100644 index 6393145d7d..0000000000 --- a/src/components/GmSwap/GmSwapBox/types.ts +++ /dev/null @@ -1,18 +0,0 @@ -export enum Operation { - Deposit = "Deposit", - Withdrawal = "Withdrawal", - Shift = "Shift", -} - -export enum Mode { - Single = "Single", - Pair = "Pair", -} - -export function isOperation(operation: string): operation is Operation { - return Object.values(Operation).includes(operation as Operation); -} - -export function isMode(mode: string): mode is Mode { - return Object.values(Mode).includes(mode as Mode); -} diff --git a/src/components/MarketStats/hooks/useBestGmPoolForGlv.ts b/src/components/MarketStats/hooks/useBestGmPoolForGlv.ts index ffbcefac6c..aceca12bb5 100644 --- a/src/components/MarketStats/hooks/useBestGmPoolForGlv.ts +++ b/src/components/MarketStats/hooks/useBestGmPoolForGlv.ts @@ -2,10 +2,10 @@ import { useEffect, useMemo } from "react"; import { selectPoolsDetailsFlags, - selectPoolsDetailsIsMarketForGlvSelectedManually, selectPoolsDetailsFocusedInput, selectPoolsDetailsGlvInfo, selectPoolsDetailsGlvTokenAmount, + selectPoolsDetailsIsMarketForGlvSelectedManually, selectPoolsDetailsIsMarketTokenDeposit, selectPoolsDetailsLongTokenAddress, selectPoolsDetailsLongTokenAmount, @@ -23,8 +23,7 @@ import { getGmSwapError } from "domain/synthetics/trade/utils/validation"; import { useChainId } from "lib/chains"; import { absDiffBps } from "lib/numbers"; import { usePrevious } from "lib/usePrevious"; - -import type { useDepositWithdrawalFees } from "components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/useDepositWithdrawalFees"; +import type { GmSwapFees } from "sdk/types/trade"; import { useGlvGmMarketsWithComposition } from "./useMarketGlvGmMarketsCompositions"; @@ -39,7 +38,7 @@ export const useBestGmPoolAddressForGlv = ({ uiFeeFactor: bigint; marketTokenAmount: bigint; marketTokensData: TokensData | undefined; - fees: ReturnType["logicalFees"]; + fees: GmSwapFees | undefined; }) => { const { chainId, srcChainId } = useChainId(); diff --git a/src/config/multichain.ts b/src/config/multichain.ts index e6631c99ad..f1399cb7c1 100644 --- a/src/config/multichain.ts +++ b/src/config/multichain.ts @@ -25,7 +25,7 @@ import invert from "lodash/invert"; import mapValues from "lodash/mapValues"; import uniq from "lodash/uniq"; import type { Abi, Hex } from "viem"; -import { zeroAddress } from "viem"; +import { maxUint256, zeroAddress } from "viem"; import { AnyChainId, @@ -499,6 +499,11 @@ export const FAKE_INPUT_AMOUNT_MAP: Record = { export const RANDOM_SLOT = "0x23995301f0ea59f7cace2ae906341fc4662f3f5d23f124431ee3520d1070148c"; export const RANDOM_WALLET = Wallet.createRandom(); +/** + * Uses maxUint256 / 100n to avoid number overflows in EVM operations. + */ +export const SIMULATED_MULTICHAIN_BALANCE = maxUint256 / 100n; + export function getSourceChainDecimalsMapped( chainId: ContractsChainId, srcChainId: SourceChainId, diff --git a/src/context/PoolsDetailsContext/PoolsDetailsContext.tsx b/src/context/PoolsDetailsContext/PoolsDetailsContext.tsx index 865cd7129d..567d24031c 100644 --- a/src/context/PoolsDetailsContext/PoolsDetailsContext.tsx +++ b/src/context/PoolsDetailsContext/PoolsDetailsContext.tsx @@ -4,7 +4,7 @@ import { SYNTHETICS_MARKET_DEPOSIT_TOKEN_KEY } from "config/localStorage"; import { getAreBothCollateralsCrossChain } from "domain/multichain/areBothCollateralsCrossChain"; import { GlvInfoData, MarketsInfoData, useMarketTokensDataRequest } from "domain/synthetics/markets"; import { isGlvAddress } from "domain/synthetics/markets/glv"; -import { GmPaySource } from "domain/synthetics/markets/types"; +import { GmPaySource, Mode, Operation, isMode, isOperation } from "domain/synthetics/markets/types"; import { TokensData } from "domain/synthetics/tokens"; import { ERC20Address, NativeTokenSupportedAddress } from "domain/tokens"; import { useChainId } from "lib/chains"; @@ -17,7 +17,6 @@ import { isMarketTokenAddress } from "sdk/configs/markets"; import { getGmSwapBoxAvailableModes } from "components/GmSwap/GmSwapBox/getGmSwapBoxAvailableModes"; import { FocusedInput } from "components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/types"; -import { Mode, Operation, isMode, isOperation } from "components/GmSwap/GmSwapBox/types"; import { useMultichainMarketTokensBalancesRequest, useMultichainTokens, diff --git a/src/context/PoolsDetailsContext/selectors/baseSelectors.ts b/src/context/PoolsDetailsContext/selectors/baseSelectors.ts index a233f5a827..222eef3886 100644 --- a/src/context/PoolsDetailsContext/selectors/baseSelectors.ts +++ b/src/context/PoolsDetailsContext/selectors/baseSelectors.ts @@ -1,10 +1,9 @@ import noop from "lodash/noop"; import { SyntheticsState } from "context/SyntheticsStateContext/SyntheticsStateContextProvider"; +import { Mode, Operation } from "domain/synthetics/markets/types"; import { EMPTY_ARRAY } from "lib/objects"; -import { Mode, Operation } from "components/GmSwap/GmSwapBox/types"; - export const PLATFORM_TOKEN_DECIMALS = 18; const FALLBACK_STRING_SETTER = noop as (value: string) => void; diff --git a/src/context/PoolsDetailsContext/selectors/poolsDetailsDerivedSelectors.ts b/src/context/PoolsDetailsContext/selectors/poolsDetailsDerivedSelectors.ts index 4913026653..27852523c2 100644 --- a/src/context/PoolsDetailsContext/selectors/poolsDetailsDerivedSelectors.ts +++ b/src/context/PoolsDetailsContext/selectors/poolsDetailsDerivedSelectors.ts @@ -16,6 +16,7 @@ import { createSelector } from "context/SyntheticsStateContext/utils"; import { getAreBothCollateralsCrossChain } from "domain/multichain/areBothCollateralsCrossChain"; import { isMarketInfo } from "domain/synthetics/markets"; import { isGlvInfo } from "domain/synthetics/markets/glv"; +import { Mode, Operation } from "domain/synthetics/markets/types"; import { ERC20Address, getGmToken, getTokenData, Token, TokenBalanceType } from "domain/tokens"; import { parseValue } from "lib/numbers"; import { getByKey } from "lib/objects"; @@ -29,7 +30,6 @@ import { convertTokenAddress, getToken } from "sdk/configs/tokens"; import { SwapPricingType } from "sdk/types/orders"; import { getGmSwapBoxAvailableModes } from "components/GmSwap/GmSwapBox/getGmSwapBoxAvailableModes"; -import { Mode, Operation } from "components/GmSwap/GmSwapBox/types"; import { PLATFORM_TOKEN_DECIMALS, diff --git a/src/domain/multichain/arbitraryRelayParams.ts b/src/domain/multichain/arbitraryRelayParams.ts index 7118892de4..b4ac4f0cfe 100644 --- a/src/domain/multichain/arbitraryRelayParams.ts +++ b/src/domain/multichain/arbitraryRelayParams.ts @@ -4,7 +4,6 @@ import { encodePacked, EstimateGasParameters, keccak256, - maxUint256, PublicClient, toHex, zeroHash, @@ -13,6 +12,7 @@ import { import type { ContractsChainId } from "config/chains"; import { getContract } from "config/contracts"; import { GMX_SIMULATION_ORIGIN, multichainBalanceKey } from "config/dataStore"; +import { SIMULATED_MULTICHAIN_BALANCE } from "config/multichain"; import { OVERRIDE_ERC20_BYTECODE, RANDOM_SLOT } from "config/multichain"; import { selectExpressGlobalParams } from "context/SyntheticsStateContext/selectors/expressSelectors"; import { @@ -175,7 +175,7 @@ async function estimateArbitraryGasLimit({ multichainBalanceKey(account, gasPaymentParams.gasPaymentTokenAddress), DATASTORE_SLOT_INDEXES.uintValues ), - value: toHex(maxUint256 / 100n, { size: 32 }), + value: toHex(SIMULATED_MULTICHAIN_BALANCE, { size: 32 }), }, ], }, diff --git a/src/domain/multichain/buildWithdrawalTransferRequests.tsx b/src/domain/multichain/buildWithdrawalTransferRequests.tsx deleted file mode 100644 index 9d4d40ecaf..0000000000 --- a/src/domain/multichain/buildWithdrawalTransferRequests.tsx +++ /dev/null @@ -1,51 +0,0 @@ -import type { ContractsChainId } from "config/chains"; -import { getContract } from "config/contracts"; -import { getTransferRequests } from "domain/multichain/getTransferRequests"; -import type { TransferRequests } from "domain/multichain/types"; - -export function buildWithdrawalTransferRequests({ - isWithdrawal, - isGlv, - chainId, - glvTokenAddress, - glvTokenAmount, - marketTokenAddress, - marketTokenAmount, -}: { - isWithdrawal: boolean; - isGlv: boolean; - chainId: ContractsChainId; - glvTokenAddress: string | undefined; - glvTokenAmount: bigint; - marketTokenAddress: string | undefined; - marketTokenAmount: bigint; -}): TransferRequests | undefined { - if (!isWithdrawal) { - return undefined; - } - - if (isGlv) { - if (!glvTokenAddress) { - return undefined; - } - return getTransferRequests([ - { - to: getContract(chainId, "GlvVault"), - token: glvTokenAddress, - amount: glvTokenAmount, - }, - ]); - } - - if (!marketTokenAddress) { - return undefined; - } - - return getTransferRequests([ - { - to: getContract(chainId, "WithdrawalVault"), - token: marketTokenAddress, - amount: marketTokenAmount, - }, - ]); -} diff --git a/src/domain/multichain/progress/GmOrGlvBuyProgress.ts b/src/domain/multichain/progress/GmOrGlvBuyProgress.ts index b063caaaf1..b25f1d9640 100644 --- a/src/domain/multichain/progress/GmOrGlvBuyProgress.ts +++ b/src/domain/multichain/progress/GmOrGlvBuyProgress.ts @@ -1,12 +1,11 @@ import { decodeEventLog, encodeEventTopics, getAbiItem } from "viem"; import { ContractsChainId } from "config/chains"; +import { Operation } from "domain/synthetics/markets/types"; import { Token } from "domain/tokens"; import { abis } from "sdk/abis"; import { getContract } from "sdk/configs/contracts"; -import { Operation } from "components/GmSwap/GmSwapBox/types"; - import { fetchLogsInTx } from "./fetchLogsInTx"; import { getOrWaitLogs } from "./getOrWaitLogs"; import { debugLog, isStringEqualInsensitive, matchLogRequest } from "./LongCrossChainTask"; diff --git a/src/domain/multichain/progress/GmOrGlvSellProgress.ts b/src/domain/multichain/progress/GmOrGlvSellProgress.ts index 37ff40c293..615e5c9313 100644 --- a/src/domain/multichain/progress/GmOrGlvSellProgress.ts +++ b/src/domain/multichain/progress/GmOrGlvSellProgress.ts @@ -1,12 +1,11 @@ import { decodeEventLog, encodeEventTopics, getAbiItem } from "viem"; import { ContractsChainId } from "config/chains"; +import { Operation } from "domain/synthetics/markets/types"; import { Token } from "domain/tokens"; import { abis } from "sdk/abis"; import { getContract } from "sdk/configs/contracts"; -import { Operation } from "components/GmSwap/GmSwapBox/types"; - import { fetchLogsInTx } from "./fetchLogsInTx"; import { getOrWaitLogs } from "./getOrWaitLogs"; import { debugLog, isStringEqualInsensitive, matchLogRequest } from "./LongCrossChainTask"; diff --git a/src/domain/multichain/progress/MultichainTransferProgress.ts b/src/domain/multichain/progress/MultichainTransferProgress.ts index 5f092a3fca..a169646da3 100644 --- a/src/domain/multichain/progress/MultichainTransferProgress.ts +++ b/src/domain/multichain/progress/MultichainTransferProgress.ts @@ -1,8 +1,7 @@ /* eslint-disable @typescript-eslint/no-namespace */ +import { Operation } from "domain/synthetics/markets/types"; import { Token } from "domain/tokens"; -import { Operation } from "components/GmSwap/GmSwapBox/types"; - import { LongCrossChainTask } from "./LongCrossChainTask"; type FundsLeftIn = "source" | "lz" | "gmx-lz" | "unknown"; diff --git a/src/domain/multichain/progress/MultichainTransferProgressView.tsx b/src/domain/multichain/progress/MultichainTransferProgressView.tsx index a267daacb2..7941a5b4f4 100644 --- a/src/domain/multichain/progress/MultichainTransferProgressView.tsx +++ b/src/domain/multichain/progress/MultichainTransferProgressView.tsx @@ -8,17 +8,18 @@ import { useCopyToClipboard } from "react-use"; import { getChainName } from "config/chains"; import { getChainIcon } from "config/icons"; import { getTokenAddressByGlv } from "domain/synthetics/markets/glv"; +import { Operation } from "domain/synthetics/markets/types"; import { Token } from "domain/tokens"; import { useChainId } from "lib/chains"; import { CHAIN_ID_TO_TX_URL_BUILDER } from "lib/chains/blockExplorers"; import { shortenAddressOrEns } from "lib/wallets"; import { getRainbowKitConfig } from "lib/wallets/rainbowKitConfig"; import { - getMarketIndexToken, getIsSpotOnlyMarket, - isMarketTokenAddress, + getMarketIndexToken, getTokenAddressByMarket, getTokenSymbolByMarket, + isMarketTokenAddress, } from "sdk/configs/markets"; import { getToken } from "sdk/configs/tokens"; import { getMarketIndexName, getMarketPoolName } from "sdk/utils/markets"; @@ -28,7 +29,6 @@ import Button from "components/Button/Button"; import { ColorfulBanner } from "components/ColorfulBanner/ColorfulBanner"; import { EXPAND_ANIMATION_VARIANTS } from "components/ExpandableRow"; import ExternalLink from "components/ExternalLink/ExternalLink"; -import { Operation } from "components/GmSwap/GmSwapBox/types"; import { SyntheticsInfoRow } from "components/SyntheticsInfoRow"; import TokenIcon from "components/TokenIcon/TokenIcon"; diff --git a/src/domain/multichain/progress/__tests__/tracker.spec.ts b/src/domain/multichain/progress/__tests__/tracker.spec.ts index e06e9bb759..fb0a25d21a 100644 --- a/src/domain/multichain/progress/__tests__/tracker.spec.ts +++ b/src/domain/multichain/progress/__tests__/tracker.spec.ts @@ -1,11 +1,10 @@ import { describe, expect, it } from "vitest"; import { ARBITRUM, ARBITRUM_SEPOLIA, SOURCE_BASE_MAINNET, SOURCE_SEPOLIA } from "config/chains"; +import { Operation } from "domain/synthetics/markets/types"; import { getGlvToken, getGmToken } from "domain/tokens"; import { expandDecimals, numberToBigint } from "lib/numbers"; -import { Operation } from "components/GmSwap/GmSwapBox/types"; - import { GlvBuyTask, GmBuyTask } from "../GmOrGlvBuyProgress"; import { GlvSellTask, GmSellTask } from "../GmOrGlvSellProgress"; import { BridgeInFailed, ConversionFailed } from "../MultichainTransferProgress"; diff --git a/src/domain/multichain/technical-fees-types.ts b/src/domain/multichain/technical-fees-types.ts deleted file mode 100644 index a81a47838a..0000000000 --- a/src/domain/multichain/technical-fees-types.ts +++ /dev/null @@ -1,49 +0,0 @@ -import type { SourceChainDepositFees } from "domain/synthetics/markets/feeEstimation/estimateSourceChainDepositFees"; -import type { SourceChainGlvDepositFees } from "domain/synthetics/markets/feeEstimation/estimateSourceChainGlvDepositFees"; -import type { SourceChainGlvWithdrawalFees } from "domain/synthetics/markets/feeEstimation/estimateSourceChainGlvWithdrawalFees"; -import type { SourceChainWithdrawalFees } from "domain/synthetics/markets/feeEstimation/estimateSourceChainWithdrawalFees"; -import type { ExecutionFee } from "sdk/types/fees"; - -type SameChainGmFees = { - kind: "settlementChain"; - fees: ExecutionFee; - isDeposit: boolean; - isGlv: boolean; -}; - -type GmxAccountGmFees = { - kind: "gmxAccount"; - fees: { - executionFee: ExecutionFee; - relayFeeUsd: bigint; - }; - isDeposit: boolean; - isGlv: boolean; -}; - -type SourceChainGmFees = { - kind: "sourceChain"; -} & ( - | { - isGlv: false; - isDeposit: false; - fees: SourceChainWithdrawalFees; - } - | { - isGlv: false; - isDeposit: true; - fees: SourceChainDepositFees; - } - | { - isGlv: true; - isDeposit: false; - fees: SourceChainGlvWithdrawalFees; - } - | { - isGlv: true; - isDeposit: true; - fees: SourceChainGlvDepositFees; - } -); - -export type TechnicalGmFees = SameChainGmFees | GmxAccountGmFees | SourceChainGmFees | undefined; diff --git a/src/domain/synthetics/express/expressOrderUtils.ts b/src/domain/synthetics/express/expressOrderUtils.ts index 379df7acf1..c7e5b96790 100644 --- a/src/domain/synthetics/express/expressOrderUtils.ts +++ b/src/domain/synthetics/express/expressOrderUtils.ts @@ -2,7 +2,6 @@ import { AbstractSigner, Provider, Signer, Wallet } from "ethers"; import { Address, encodeFunctionData, - maxUint256, PublicClient, recoverTypedDataAddress, size, @@ -15,6 +14,7 @@ import { BOTANIX } from "config/chains"; import { getContract } from "config/contracts"; import { GMX_SIMULATION_ORIGIN, multichainBalanceKey } from "config/dataStore"; import { BASIS_POINTS_DIVISOR_BIGINT } from "config/factors"; +import { SIMULATED_MULTICHAIN_BALANCE } from "config/multichain"; import { isSourceChain } from "config/multichain"; import { calculateMappingSlot, DATASTORE_SLOT_INDEXES } from "domain/multichain/arbitraryRelayParams"; import { fallbackCustomError } from "domain/multichain/fallbackCustomError"; @@ -386,7 +386,7 @@ export async function estimateExpressParams({ multichainBalanceKey(account, gasPaymentToken.address), DATASTORE_SLOT_INDEXES.uintValues ), - value: toHex(maxUint256 / 100n, { size: 32 }), + value: toHex(SIMULATED_MULTICHAIN_BALANCE, { size: 32 }), }, ], }, diff --git a/src/domain/multichain/buildDepositTransferRequests.tsx b/src/domain/synthetics/markets/buildDepositTransferRequests.ts similarity index 97% rename from src/domain/multichain/buildDepositTransferRequests.tsx rename to src/domain/synthetics/markets/buildDepositTransferRequests.ts index 169ffd5c6b..cff0e85e2e 100644 --- a/src/domain/multichain/buildDepositTransferRequests.tsx +++ b/src/domain/synthetics/markets/buildDepositTransferRequests.ts @@ -2,11 +2,12 @@ import type { ContractsChainId } from "config/chains"; import { getContract } from "config/contracts"; import { DEFAULT_SLIPPAGE_AMOUNT } from "config/factors"; import { getTransferRequests } from "domain/multichain/getTransferRequests"; -import type { TechnicalGmFees } from "domain/multichain/technical-fees-types"; import type { TransferRequests } from "domain/multichain/types"; import type { GmPaySource } from "domain/synthetics/markets"; import { applySlippageToMinOut } from "sdk/utils/trade"; +import type { TechnicalGmFees } from "./technicalFees/technical-fees-types"; + export function buildDepositTransferRequests({ isDeposit, isGlv, diff --git a/src/domain/synthetics/markets/buildWithdrawalTransferRequests.ts b/src/domain/synthetics/markets/buildWithdrawalTransferRequests.ts new file mode 100644 index 0000000000..159807c19a --- /dev/null +++ b/src/domain/synthetics/markets/buildWithdrawalTransferRequests.ts @@ -0,0 +1,37 @@ +import type { ContractsChainId } from "config/chains"; +import { getContract } from "config/contracts"; +import { getTransferRequests } from "domain/multichain/getTransferRequests"; +import type { TransferRequests } from "domain/multichain/types"; +import type { ContractName } from "sdk/configs/contracts"; + +export function buildWithdrawalTransferRequests({ + isWithdrawal, + isGlv, + chainId, + glvOrMarketTokenAddress, + glvOrMarketAmount, +}: { + isWithdrawal: boolean; + isGlv: boolean; + chainId: ContractsChainId; + glvOrMarketTokenAddress: string | undefined; + glvOrMarketAmount: bigint; +}): TransferRequests | undefined { + if (!isWithdrawal) { + return undefined; + } + + if (!glvOrMarketTokenAddress) { + return undefined; + } + + const vaultContract: ContractName = isGlv ? "GlvVault" : "WithdrawalVault"; + + return getTransferRequests([ + { + to: getContract(chainId, vaultContract), + token: glvOrMarketTokenAddress, + amount: glvOrMarketAmount, + }, + ]); +} diff --git a/src/domain/synthetics/markets/feeEstimation/estimatePureLpActionExecutionFee.ts b/src/domain/synthetics/markets/feeEstimation/estimatePureLpActionExecutionFee.ts index 895d61e5cd..b1bae47257 100644 --- a/src/domain/synthetics/markets/feeEstimation/estimatePureLpActionExecutionFee.ts +++ b/src/domain/synthetics/markets/feeEstimation/estimatePureLpActionExecutionFee.ts @@ -13,7 +13,7 @@ import { getExecutionFee, } from "sdk/utils/fees"; -import { Operation } from "components/GmSwap/GmSwapBox/types"; +import { Operation } from "../types"; export type PureAction = | { operation: Operation.Deposit; isGlv: false; swapsCount: bigint } diff --git a/src/domain/synthetics/markets/feeEstimation/estimateSourceChainDepositFees.ts b/src/domain/synthetics/markets/feeEstimation/estimateSourceChainDepositFees.ts index 0dd2ab1d06..fd28a8fa60 100644 --- a/src/domain/synthetics/markets/feeEstimation/estimateSourceChainDepositFees.ts +++ b/src/domain/synthetics/markets/feeEstimation/estimateSourceChainDepositFees.ts @@ -18,11 +18,9 @@ import { convertTokenAddress, getToken, getWrappedToken } from "sdk/configs/toke import { getEmptyExternalCallsPayload } from "sdk/utils/orderTransactions"; import { nowInSeconds } from "sdk/utils/time"; -import { Operation } from "components/GmSwap/GmSwapBox/types"; - import { convertToUsd, getMidPrice } from "../../tokens"; import { signCreateDeposit } from "../signCreateDeposit"; -import { CreateDepositParams, RawCreateDepositParams } from "../types"; +import { CreateDepositParams, Operation, RawCreateDepositParams } from "../types"; import { estimateDepositPlatformTokenTransferOutFees } from "./estimateDepositPlatformTokenTransferOutFees"; import { estimatePureLpActionExecutionFee } from "./estimatePureLpActionExecutionFee"; import { stargateTransferFees } from "./stargateTransferFees"; diff --git a/src/domain/synthetics/markets/feeEstimation/estimateSourceChainGlvDepositFees.ts b/src/domain/synthetics/markets/feeEstimation/estimateSourceChainGlvDepositFees.ts index b767de887d..e337daac26 100644 --- a/src/domain/synthetics/markets/feeEstimation/estimateSourceChainGlvDepositFees.ts +++ b/src/domain/synthetics/markets/feeEstimation/estimateSourceChainGlvDepositFees.ts @@ -18,11 +18,9 @@ import { convertTokenAddress, getToken, getWrappedToken } from "sdk/configs/toke import { getEmptyExternalCallsPayload } from "sdk/utils/orderTransactions"; import { nowInSeconds } from "sdk/utils/time"; -import { Operation } from "components/GmSwap/GmSwapBox/types"; - import { convertToUsd, getMidPrice } from "../../tokens"; import { signCreateGlvDeposit } from "../signCreateGlvDeposit"; -import { CreateGlvDepositParams, RawCreateGlvDepositParams } from "../types"; +import { CreateGlvDepositParams, Operation, RawCreateGlvDepositParams } from "../types"; import { estimateDepositPlatformTokenTransferOutFees } from "./estimateDepositPlatformTokenTransferOutFees"; import { estimatePureLpActionExecutionFee } from "./estimatePureLpActionExecutionFee"; import { stargateTransferFees } from "./stargateTransferFees"; diff --git a/src/domain/synthetics/markets/feeEstimation/estimateSourceChainGlvWithdrawalFees.ts b/src/domain/synthetics/markets/feeEstimation/estimateSourceChainGlvWithdrawalFees.ts index 52968cf560..7b9dac83cf 100644 --- a/src/domain/synthetics/markets/feeEstimation/estimateSourceChainGlvWithdrawalFees.ts +++ b/src/domain/synthetics/markets/feeEstimation/estimateSourceChainGlvWithdrawalFees.ts @@ -2,13 +2,11 @@ import { SettlementChainId, SourceChainId } from "config/chains"; import { GlobalExpressParams, RelayParamsPayload } from "domain/synthetics/express"; import { getToken } from "sdk/configs/tokens"; -import { Operation } from "components/GmSwap/GmSwapBox/types"; - +import { convertToUsd, getMidPrice } from "../../tokens"; +import { CreateGlvWithdrawalParams, Operation, RawCreateGlvWithdrawalParams } from "../types"; import { estimateGlvWithdrawalPlatformTokenTransferInFees } from "./estimateGlvWithdrawalPlatformTokenTransferInFees"; import { estimatePureLpActionExecutionFee } from "./estimatePureLpActionExecutionFee"; import { estimateSourceChainWithdrawalReturnTokenTransferFees } from "./estimateSourceChainWithdrawalFees"; -import { convertToUsd, getMidPrice } from "../../tokens"; -import { CreateGlvWithdrawalParams, RawCreateGlvWithdrawalParams } from "../types"; export type SourceChainGlvWithdrawalFees = { /** diff --git a/src/domain/synthetics/markets/feeEstimation/estimateSourceChainWithdrawalFees.ts b/src/domain/synthetics/markets/feeEstimation/estimateSourceChainWithdrawalFees.ts index c9db118d09..788a1ca2fe 100644 --- a/src/domain/synthetics/markets/feeEstimation/estimateSourceChainWithdrawalFees.ts +++ b/src/domain/synthetics/markets/feeEstimation/estimateSourceChainWithdrawalFees.ts @@ -8,10 +8,8 @@ import { GlobalExpressParams, RelayParamsPayload } from "domain/synthetics/expre import { expandDecimals } from "lib/numbers"; import { convertTokenAddress, getToken } from "sdk/configs/tokens"; -import { Operation } from "components/GmSwap/GmSwapBox/types"; - import { convertToUsd, getMidPrice } from "../../tokens"; -import { CreateWithdrawalParams, RawCreateWithdrawalParams } from "../types"; +import { CreateWithdrawalParams, Operation, RawCreateWithdrawalParams } from "../types"; import { estimatePureLpActionExecutionFee } from "./estimatePureLpActionExecutionFee"; import { estimateWithdrawalPlatformTokenTransferInFees } from "./estimateWithdrawalPlatformTokenTransferInFees"; import { stargateTransferFees } from "./stargateTransferFees"; diff --git a/src/domain/synthetics/markets/technicalFees/calculateGmxAccountTechnicalFees.ts b/src/domain/synthetics/markets/technicalFees/calculateGmxAccountTechnicalFees.ts new file mode 100644 index 0000000000..6a02464c99 --- /dev/null +++ b/src/domain/synthetics/markets/technicalFees/calculateGmxAccountTechnicalFees.ts @@ -0,0 +1,286 @@ +import { estimateArbitraryRelayFee, getRawBaseRelayerParams } from "domain/multichain/arbitraryRelayParams"; +import { ExpressTransactionBuilder } from "domain/synthetics/express"; +import { + RawCreateDepositParams, + RawCreateGlvDepositParams, + RawCreateGlvWithdrawalParams, + RawCreateWithdrawalParams, +} from "domain/synthetics/markets"; +import { buildAndSignMultichainDepositTxn } from "domain/synthetics/markets/createMultichainDepositTxn"; +import { buildAndSignMultichainGlvDepositTxn } from "domain/synthetics/markets/createMultichainGlvDepositTxn"; +import { buildAndSignMultichainGlvWithdrawalTxn } from "domain/synthetics/markets/createMultichainGlvWithdrawalTxn"; +import { buildAndSignMultichainWithdrawalTxn } from "domain/synthetics/markets/createMultichainWithdrawalTxn"; +import { estimatePureLpActionExecutionFee } from "domain/synthetics/markets/feeEstimation/estimatePureLpActionExecutionFee"; +import { convertToUsd } from "domain/tokens"; +import { getPublicClientWithRpc } from "lib/wallets/rainbowKitConfig"; +import { DEFAULT_EXPRESS_ORDER_DEADLINE_DURATION } from "sdk/configs/express"; +import { nowInSeconds } from "sdk/utils/time"; + +import { buildDepositTransferRequests } from "../buildDepositTransferRequests"; +import { buildWithdrawalTransferRequests } from "../buildWithdrawalTransferRequests"; +import { CalculateTechnicalFeesParams, TechnicalGmFees } from "./technical-fees-types"; +import { Operation } from "../types"; + +type GmxAccountFeesParams = CalculateTechnicalFeesParams & + Required> & { + globalExpressParams: NonNullable; + }; + +async function calculateGmxAccountDepositTechnicalFees( + params: GmxAccountFeesParams +): Promise { + const castedParams = params.rawParams as RawCreateGlvDepositParams | RawCreateDepositParams; + + const swapsCount = BigInt( + castedParams.addresses.longTokenSwapPath.length + castedParams.addresses.shortTokenSwapPath.length + ); + + const executionFee = estimatePureLpActionExecutionFee({ + action: params.isGlv + ? { + operation: Operation.Deposit, + isGlv: true, + marketsCount: BigInt(params.glvInfo!.markets.length), + swapsCount, + isMarketTokenDeposit: (params.rawParams as RawCreateGlvDepositParams).isMarketTokenDeposit, + } + : { + operation: Operation.Deposit, + isGlv: false, + swapsCount, + }, + chainId: params.chainId, + gasLimits: params.gasLimits, + tokensData: params.tokensData, + gasPrice: params.gasPrice, + }); + + const transferRequests = buildDepositTransferRequests({ + isDeposit: true, + isGlv: params.isGlv, + chainId: params.chainId, + paySource: params.paySource, + isMarketTokenDeposit: params.isGlv ? (params.rawParams as RawCreateGlvDepositParams).isMarketTokenDeposit : false, + marketTokenAddress: params.isGlv ? params.rawParams.addresses.market : undefined, + marketTokenAmount: params.isGlv ? params.firstTokenAmount : 0n, + longTokenAmount: params.firstTokenAmount, + shortTokenAmount: params.secondTokenAmount, + initialLongTokenAddress: castedParams.addresses.initialLongToken, + initialShortTokenAddress: castedParams.addresses.initialShortToken, + technicalFees: undefined, + }); + + if (!transferRequests) { + return undefined; + } + + const expressTransactionBuilder: ExpressTransactionBuilder = async ({ relayParams, gasPaymentParams }) => { + if (params.isGlv) { + const glvParams = params.rawParams as RawCreateGlvDepositParams; + return { + txnData: await buildAndSignMultichainGlvDepositTxn({ + chainId: params.chainId, + srcChainId: params.srcChainId, + emptySignature: true, + signer: undefined, + account: params.rawParams.addresses.receiver, + params: { ...glvParams, executionFee: executionFee.feeTokenAmount }, + relayerFeeAmount: gasPaymentParams.relayerFeeAmount, + relayerFeeTokenAddress: gasPaymentParams.relayerFeeTokenAddress, + relayParams: { + ...relayParams, + deadline: BigInt(nowInSeconds() + DEFAULT_EXPRESS_ORDER_DEADLINE_DURATION), + }, + transferRequests, + }), + }; + } else { + const depositParams = params.rawParams as RawCreateDepositParams; + return { + txnData: await buildAndSignMultichainDepositTxn({ + chainId: params.chainId, + srcChainId: params.srcChainId, + emptySignature: true, + signer: undefined, + account: params.rawParams.addresses.receiver, + params: { ...depositParams, executionFee: executionFee.feeTokenAmount }, + relayerFeeAmount: gasPaymentParams.relayerFeeAmount, + relayerFeeTokenAddress: gasPaymentParams.relayerFeeTokenAddress, + relayParams: { + ...relayParams, + deadline: BigInt(nowInSeconds() + DEFAULT_EXPRESS_ORDER_DEADLINE_DURATION), + }, + transferRequests, + }), + }; + } + }; + + const relayFee = await estimateArbitraryRelayFee({ + account: params.rawParams.addresses.receiver, + chainId: params.chainId, + client: getPublicClientWithRpc(params.chainId), + rawRelayParamsPayload: params.rawBaseRelayParamsPayload, + expressTransactionBuilder: expressTransactionBuilder, + gasPaymentParams: params.baseRelayFeeSwapParams.gasPaymentParams, + subaccount: undefined, + }); + + const relayFeeUsd = convertToUsd( + relayFee, + params.globalExpressParams.relayerFeeToken.decimals, + params.globalExpressParams.relayerFeeToken.prices.maxPrice + )!; + + return { + kind: "gmxAccount", + fees: { + executionFee, + relayFeeUsd, + }, + isDeposit: true, + isGlv: params.isGlv, + }; +} + +async function calculateGmxAccountWithdrawalTechnicalFees( + params: GmxAccountFeesParams +): Promise { + const castedParams = params.rawParams as RawCreateGlvWithdrawalParams | RawCreateWithdrawalParams; + + const swapsCount = BigInt( + castedParams.addresses.longTokenSwapPath.length + castedParams.addresses.shortTokenSwapPath.length + ); + + const fees = estimatePureLpActionExecutionFee({ + action: params.isGlv + ? { + operation: Operation.Withdrawal, + isGlv: true, + marketsCount: BigInt(params.glvInfo!.markets.length), + swapsCount, + } + : { + operation: Operation.Withdrawal, + isGlv: false, + swapsCount, + }, + chainId: params.chainId, + gasLimits: params.gasLimits, + tokensData: params.tokensData, + gasPrice: params.gasPrice, + }); + + const transferRequests = buildWithdrawalTransferRequests({ + isWithdrawal: true, + isGlv: params.isGlv, + chainId: params.chainId, + glvOrMarketTokenAddress: params.isGlv + ? (params.rawParams as RawCreateGlvWithdrawalParams).addresses.glv + : (params.rawParams as RawCreateWithdrawalParams).addresses.market, + glvOrMarketAmount: params.marketTokenAmount, + }); + + if (!transferRequests) { + return undefined; + } + + const expressTransactionBuilder: ExpressTransactionBuilder = async ({ relayParams, gasPaymentParams }) => { + if (params.isGlv) { + const glvParams = params.rawParams as RawCreateGlvWithdrawalParams; + return { + txnData: await buildAndSignMultichainGlvWithdrawalTxn({ + chainId: params.chainId, + srcChainId: params.srcChainId, + emptySignature: true, + signer: undefined, + account: params.rawParams.addresses.receiver, + params: { ...glvParams, executionFee: fees.feeTokenAmount }, + relayerFeeAmount: gasPaymentParams.relayerFeeAmount, + relayerFeeTokenAddress: gasPaymentParams.relayerFeeTokenAddress, + relayParams: { + ...relayParams, + deadline: BigInt(nowInSeconds() + DEFAULT_EXPRESS_ORDER_DEADLINE_DURATION), + }, + transferRequests, + }), + }; + } else { + const withdrawalParams = params.rawParams as RawCreateWithdrawalParams; + return { + txnData: await buildAndSignMultichainWithdrawalTxn({ + chainId: params.chainId, + srcChainId: params.srcChainId, + emptySignature: true, + signer: undefined, + account: params.rawParams.addresses.receiver, + params: { ...withdrawalParams, executionFee: fees.feeTokenAmount }, + relayerFeeAmount: gasPaymentParams.relayerFeeAmount, + relayerFeeTokenAddress: gasPaymentParams.relayerFeeTokenAddress, + relayParams: { + ...relayParams, + deadline: BigInt(nowInSeconds() + DEFAULT_EXPRESS_ORDER_DEADLINE_DURATION), + }, + transferRequests, + }), + }; + } + }; + + const relayFee = await estimateArbitraryRelayFee({ + account: params.rawParams.addresses.receiver, + chainId: params.chainId, + client: getPublicClientWithRpc(params.chainId), + rawRelayParamsPayload: params.rawBaseRelayParamsPayload, + expressTransactionBuilder: expressTransactionBuilder, + gasPaymentParams: params.baseRelayFeeSwapParams.gasPaymentParams, + subaccount: undefined, + }); + + const relayFeeUsd = convertToUsd( + relayFee, + params.globalExpressParams.relayerFeeToken.decimals, + params.globalExpressParams.relayerFeeToken.prices.maxPrice + )!; + + return { + kind: "gmxAccount", + fees: { + executionFee: fees, + relayFeeUsd, + }, + isDeposit: false, + isGlv: params.isGlv, + }; +} + +export async function calculateGmxAccountTechnicalFees( + params: CalculateTechnicalFeesParams +): Promise { + if (!params.globalExpressParams) { + return undefined; + } + + const { rawBaseRelayParamsPayload, baseRelayFeeSwapParams } = getRawBaseRelayerParams({ + chainId: params.chainId, + account: params.rawParams.addresses.receiver, + globalExpressParams: params.globalExpressParams, + }); + + if (!rawBaseRelayParamsPayload || !baseRelayFeeSwapParams) { + return undefined; + } + + const feesParams: GmxAccountFeesParams = { + ...params, + rawBaseRelayParamsPayload, + baseRelayFeeSwapParams, + globalExpressParams: params.globalExpressParams, + }; + + if (params.operation === Operation.Deposit) { + return calculateGmxAccountDepositTechnicalFees(feesParams); + } else if (params.operation === Operation.Withdrawal) { + return calculateGmxAccountWithdrawalTechnicalFees(feesParams); + } +} diff --git a/src/domain/synthetics/markets/technicalFees/calculateSettlementChainTechnicalFees.ts b/src/domain/synthetics/markets/technicalFees/calculateSettlementChainTechnicalFees.ts new file mode 100644 index 0000000000..cc687a6ac3 --- /dev/null +++ b/src/domain/synthetics/markets/technicalFees/calculateSettlementChainTechnicalFees.ts @@ -0,0 +1,81 @@ +import { + RawCreateGlvDepositParams, + RawCreateDepositParams, + RawCreateGlvWithdrawalParams, + RawCreateWithdrawalParams, +} from "domain/synthetics/markets"; +import { estimatePureLpActionExecutionFee } from "domain/synthetics/markets/feeEstimation/estimatePureLpActionExecutionFee"; + +import { CalculateTechnicalFeesParams, TechnicalGmFees } from "./technical-fees-types"; +import { Operation } from "../types"; + +export async function calculateSettlementChainTechnicalFees( + params: CalculateTechnicalFeesParams +): Promise { + if (params.operation === Operation.Deposit) { + const castedParams = params.rawParams as RawCreateGlvDepositParams | RawCreateDepositParams; + + const swapsCount = BigInt( + castedParams.addresses.longTokenSwapPath.length + castedParams.addresses.shortTokenSwapPath.length + ); + + const fees = estimatePureLpActionExecutionFee({ + action: params.isGlv + ? { + operation: Operation.Deposit, + isGlv: true, + marketsCount: BigInt(params.glvInfo!.markets.length), + swapsCount, + isMarketTokenDeposit: (params.rawParams as RawCreateGlvDepositParams).isMarketTokenDeposit, + } + : { + operation: Operation.Deposit, + isGlv: false, + swapsCount, + }, + chainId: params.chainId, + gasLimits: params.gasLimits, + tokensData: params.tokensData, + gasPrice: params.gasPrice, + }); + + return { + kind: "settlementChain", + fees, + isDeposit: true, + isGlv: params.isGlv, + }; + } else if (params.operation === Operation.Withdrawal) { + const castedParams = params.rawParams as RawCreateGlvWithdrawalParams | RawCreateWithdrawalParams; + + const swapsCount = BigInt( + castedParams.addresses.longTokenSwapPath.length + castedParams.addresses.shortTokenSwapPath.length + ); + + const fees = estimatePureLpActionExecutionFee({ + action: params.isGlv + ? { + operation: Operation.Withdrawal, + isGlv: true, + marketsCount: BigInt(params.glvInfo!.markets.length), + swapsCount, + } + : { + operation: Operation.Withdrawal, + isGlv: false, + swapsCount, + }, + chainId: params.chainId, + gasLimits: params.gasLimits, + tokensData: params.tokensData, + gasPrice: params.gasPrice, + }); + + return { + kind: "settlementChain", + fees, + isDeposit: false, + isGlv: params.isGlv, + }; + } +} diff --git a/src/domain/synthetics/markets/technicalFees/calculateSourceChainTechnicalFees.ts b/src/domain/synthetics/markets/technicalFees/calculateSourceChainTechnicalFees.ts new file mode 100644 index 0000000000..1355b258fb --- /dev/null +++ b/src/domain/synthetics/markets/technicalFees/calculateSourceChainTechnicalFees.ts @@ -0,0 +1,121 @@ +import { SettlementChainId, SourceChainId } from "config/chains"; +import { + RawCreateGlvDepositParams, + RawCreateDepositParams, + RawCreateGlvWithdrawalParams, + RawCreateWithdrawalParams, +} from "domain/synthetics/markets"; +import { estimateSourceChainDepositFees } from "domain/synthetics/markets/feeEstimation/estimateSourceChainDepositFees"; +import { estimateSourceChainGlvDepositFees } from "domain/synthetics/markets/feeEstimation/estimateSourceChainGlvDepositFees"; +import { estimateSourceChainGlvWithdrawalFees } from "domain/synthetics/markets/feeEstimation/estimateSourceChainGlvWithdrawalFees"; +import { estimateSourceChainWithdrawalFees } from "domain/synthetics/markets/feeEstimation/estimateSourceChainWithdrawalFees"; +import { MARKETS } from "sdk/configs/markets"; +import { WithdrawalAmounts } from "sdk/types/trade"; + +import { CalculateTechnicalFeesParams, TechnicalGmFees } from "./technical-fees-types"; +import { Operation } from "../types"; + +export async function calculateSourceChainTechnicalFees( + params: CalculateTechnicalFeesParams +): Promise { + if (params.firstTokenAddress === undefined || params.firstTokenAmount === undefined || !params.globalExpressParams) { + return undefined; + } + if (params.operation === Operation.Deposit) { + if (params.isGlv) { + const castedParams = params.rawParams as RawCreateGlvDepositParams; + const fees = await estimateSourceChainGlvDepositFees({ + chainId: params.chainId as SettlementChainId, + srcChainId: params.srcChainId as SourceChainId, + params: castedParams, + tokenAddress: params.firstTokenAddress, + tokenAmount: params.firstTokenAmount, + globalExpressParams: params.globalExpressParams, + glvMarketCount: BigInt(params.glvInfo!.markets.length), + }); + + return { + kind: "sourceChain", + isGlv: true, + isDeposit: true, + fees, + }; + } else { + const castedParams = params.rawParams as RawCreateDepositParams; + const fees = await estimateSourceChainDepositFees({ + chainId: params.chainId as SettlementChainId, + srcChainId: params.srcChainId as SourceChainId, + params: castedParams, + tokenAddress: params.firstTokenAddress, + tokenAmount: params.firstTokenAmount, + globalExpressParams: params.globalExpressParams, + }); + return { + kind: "sourceChain", + isGlv: false, + isDeposit: true, + fees, + }; + } + } else if (params.operation === Operation.Withdrawal) { + if (params.isGlv) { + const castedParams = params.rawParams as RawCreateGlvWithdrawalParams; + const glvWithdrawalAmounts = params.amounts as WithdrawalAmounts; + const outputLongTokenAddress = + glvWithdrawalAmounts.longTokenSwapPathStats?.tokenOutAddress ?? params.glvInfo!.longTokenAddress; + const outputShortTokenAddress = + glvWithdrawalAmounts.shortTokenSwapPathStats?.tokenOutAddress ?? params.glvInfo!.shortTokenAddress; + + const fees = await estimateSourceChainGlvWithdrawalFees({ + chainId: params.chainId as SettlementChainId, + srcChainId: params.srcChainId as SourceChainId, + params: castedParams, + tokenAddress: castedParams.addresses.glv, + tokenAmount: params.marketTokenAmount, + globalExpressParams: params.globalExpressParams, + marketsCount: BigInt(params.glvInfo!.markets.length), + outputLongTokenAddress, + outputShortTokenAddress, + }); + + return { + kind: "sourceChain", + isGlv: true, + isDeposit: false, + fees, + }; + } else { + const castedParams = params.rawParams as RawCreateWithdrawalParams; + if (!params.amounts) { + return undefined; + } + + const gmWithdrawalAmounts = params.amounts as WithdrawalAmounts; + + const outputLongTokenAddress = + gmWithdrawalAmounts.longTokenSwapPathStats?.tokenOutAddress ?? + MARKETS[params.chainId][params.rawParams.addresses.market].longTokenAddress; + const outputShortTokenAddress = + gmWithdrawalAmounts.shortTokenSwapPathStats?.tokenOutAddress ?? + MARKETS[params.chainId][params.rawParams.addresses.market].shortTokenAddress; + + const fees = await estimateSourceChainWithdrawalFees({ + chainId: params.chainId as SettlementChainId, + srcChainId: params.srcChainId as SourceChainId, + params: castedParams, + tokenAddress: params.rawParams.addresses.market, + tokenAmount: params.marketTokenAmount, + globalExpressParams: params.globalExpressParams, + outputLongTokenAddress, + outputShortTokenAddress, + }); + + return { + kind: "sourceChain", + isGlv: false, + isDeposit: false, + fees, + }; + } + } +} diff --git a/src/domain/synthetics/markets/technicalFees/calculateTechnicalFees.ts b/src/domain/synthetics/markets/technicalFees/calculateTechnicalFees.ts new file mode 100644 index 0000000000..3a1c229ef4 --- /dev/null +++ b/src/domain/synthetics/markets/technicalFees/calculateTechnicalFees.ts @@ -0,0 +1,16 @@ +import { calculateGmxAccountTechnicalFees } from "./calculateGmxAccountTechnicalFees"; +import { calculateSettlementChainTechnicalFees } from "./calculateSettlementChainTechnicalFees"; +import { calculateSourceChainTechnicalFees } from "./calculateSourceChainTechnicalFees"; +import { CalculateTechnicalFeesParams, TechnicalGmFees } from "./technical-fees-types"; + +export async function calculateTechnicalFees( + params: CalculateTechnicalFeesParams +): Promise { + if (params.paySource === "settlementChain") { + return calculateSettlementChainTechnicalFees(params); + } else if (params.paySource === "gmxAccount") { + return calculateGmxAccountTechnicalFees(params); + } else if (params.paySource === "sourceChain") { + return calculateSourceChainTechnicalFees(params); + } +} diff --git a/src/domain/synthetics/markets/technicalFees/technical-fees-types.ts b/src/domain/synthetics/markets/technicalFees/technical-fees-types.ts new file mode 100644 index 0000000000..080bd3f498 --- /dev/null +++ b/src/domain/synthetics/markets/technicalFees/technical-fees-types.ts @@ -0,0 +1,86 @@ +import { type ContractsChainId, SourceChainId } from "config/chains"; +import type { GlobalExpressParams } from "domain/synthetics/express"; +import { + RawCreateDepositParams, + RawCreateGlvDepositParams, + RawCreateWithdrawalParams, + RawCreateGlvWithdrawalParams, + type GlvInfo, +} from "domain/synthetics/markets"; +import type { SourceChainDepositFees } from "domain/synthetics/markets/feeEstimation/estimateSourceChainDepositFees"; +import type { SourceChainGlvDepositFees } from "domain/synthetics/markets/feeEstimation/estimateSourceChainGlvDepositFees"; +import type { SourceChainGlvWithdrawalFees } from "domain/synthetics/markets/feeEstimation/estimateSourceChainGlvWithdrawalFees"; +import type { SourceChainWithdrawalFees } from "domain/synthetics/markets/feeEstimation/estimateSourceChainWithdrawalFees"; +import type { NativeTokenSupportedAddress, ERC20Address, TokensData } from "domain/tokens"; +import type { ExecutionFee, GasLimitsConfig } from "sdk/types/fees"; +import { type DepositAmounts, WithdrawalAmounts } from "sdk/types/trade"; + +import { Operation } from "../types"; + +type SameChainGmFees = { + kind: "settlementChain"; + fees: ExecutionFee; + isDeposit: boolean; + isGlv: boolean; +}; + +type GmxAccountGmFees = { + kind: "gmxAccount"; + fees: { + executionFee: ExecutionFee; + relayFeeUsd: bigint; + }; + isDeposit: boolean; + isGlv: boolean; +}; + +type SourceChainGmFees = { + kind: "sourceChain"; +} & ( + | { + isGlv: false; + isDeposit: false; + fees: SourceChainWithdrawalFees; + } + | { + isGlv: false; + isDeposit: true; + fees: SourceChainDepositFees; + } + | { + isGlv: true; + isDeposit: false; + fees: SourceChainGlvWithdrawalFees; + } + | { + isGlv: true; + isDeposit: true; + fees: SourceChainGlvDepositFees; + } +); + +export type TechnicalGmFees = SameChainGmFees | GmxAccountGmFees | SourceChainGmFees; + +export type CalculateTechnicalFeesParams = { + chainId: ContractsChainId; + globalExpressParams: GlobalExpressParams | undefined; + rawParams: + | RawCreateDepositParams + | RawCreateGlvDepositParams + | RawCreateWithdrawalParams + | RawCreateGlvWithdrawalParams; + isGlv: boolean; + glvInfo: GlvInfo | undefined; + paySource: "settlementChain" | "gmxAccount" | "sourceChain"; + srcChainId: SourceChainId | undefined; + firstTokenAddress: NativeTokenSupportedAddress | ERC20Address | undefined; + firstTokenAmount: bigint; + secondTokenAddress: NativeTokenSupportedAddress | ERC20Address | undefined; + secondTokenAmount: bigint; + marketTokenAmount: bigint; + operation: Operation; + amounts: DepositAmounts | WithdrawalAmounts | undefined; + gasLimits: GasLimitsConfig; + tokensData: TokensData; + gasPrice: bigint; +}; diff --git a/src/domain/synthetics/markets/types.ts b/src/domain/synthetics/markets/types.ts index c42e5dae5b..7d0499944e 100644 --- a/src/domain/synthetics/markets/types.ts +++ b/src/domain/synthetics/markets/types.ts @@ -161,3 +161,22 @@ export type RawCreateGlvWithdrawalParams = Omit Date: Tue, 6 Jan 2026 20:08:00 +0100 Subject: [PATCH 14/23] Refactor technical fees handling in GmSwap components - Updated the hook to replace second token references with long and short token amounts for improved clarity. - Adjusted the type to reflect the new token amount structure. - Modified the function to utilize the updated parameters for long and short token amounts. --- .../useTechnicalFeesAsyncResult.tsx | 21 +++++++++++-------- .../calculateGmxAccountTechnicalFees.ts | 4 ++-- .../technicalFees/technical-fees-types.ts | 4 ++-- 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/useTechnicalFeesAsyncResult.tsx b/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/useTechnicalFeesAsyncResult.tsx index f737c043a2..589c80410a 100644 --- a/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/useTechnicalFeesAsyncResult.tsx +++ b/src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/useTechnicalFeesAsyncResult.tsx @@ -3,12 +3,12 @@ import { selectPoolsDetailsFirstTokenAmount, selectPoolsDetailsFlags, selectPoolsDetailsGlvInfo, + selectPoolsDetailsLongTokenAmount, selectPoolsDetailsMarketOrGlvTokenAmount, selectPoolsDetailsOperation, selectPoolsDetailsPaySource, - selectPoolsDetailsSecondTokenAddress, - selectPoolsDetailsSecondTokenAmount, selectPoolsDetailsSelectedMarketAddressForGlv, + selectPoolsDetailsShortTokenAmount, } from "context/PoolsDetailsContext/selectors"; import { selectDepositWithdrawalAmounts } from "context/PoolsDetailsContext/selectors/selectDepositWithdrawalAmounts"; import { selectPoolsDetailsParams } from "context/PoolsDetailsContext/selectors/selectPoolsDetailsParams"; @@ -20,7 +20,10 @@ import { } from "context/SyntheticsStateContext/selectors/globalSelectors"; import { useSelector } from "context/SyntheticsStateContext/utils"; import { calculateTechnicalFees } from "domain/synthetics/markets/technicalFees/calculateTechnicalFees"; -import type { TechnicalGmFees } from "domain/synthetics/markets/technicalFees/technical-fees-types"; +import type { + CalculateTechnicalFeesParams, + TechnicalGmFees, +} from "domain/synthetics/markets/technicalFees/technical-fees-types"; import { useChainId } from "lib/chains"; import { usePrevious } from "lib/usePrevious"; import { useThrottledAsync } from "lib/useThrottledAsync"; @@ -39,8 +42,8 @@ export function useTechnicalFees(): TechnicalGmFees | undefined { const firstTokenAddress = useSelector(selectPoolsDetailsFirstTokenAddress); const firstTokenAmount = useSelector(selectPoolsDetailsFirstTokenAmount); - const secondTokenAddress = useSelector(selectPoolsDetailsSecondTokenAddress); - const secondTokenAmount = useSelector(selectPoolsDetailsSecondTokenAmount); + const longTokenAmount = useSelector(selectPoolsDetailsLongTokenAmount); + const shortTokenAmount = useSelector(selectPoolsDetailsShortTokenAmount); const marketOrGlvTokenAmount = useSelector(selectPoolsDetailsMarketOrGlvTokenAmount); const prevPaySource = usePrevious(paySource); @@ -66,7 +69,7 @@ export function useTechnicalFees(): TechnicalGmFees | undefined { const technicalFeesAsyncResult = useThrottledAsync(async (p) => calculateTechnicalFees(p.params), { params: rawParams && gasLimits && tokensData && gasPrice !== undefined - ? { + ? ({ chainId, globalExpressParams, rawParams, @@ -76,15 +79,15 @@ export function useTechnicalFees(): TechnicalGmFees | undefined { srcChainId, firstTokenAddress, firstTokenAmount, - secondTokenAddress, - secondTokenAmount, + longTokenAmount, + shortTokenAmount, marketTokenAmount: marketOrGlvTokenAmount, operation, amounts, gasLimits, tokensData, gasPrice, - } + } satisfies CalculateTechnicalFeesParams) : undefined, withLoading: false, forceRecalculate, diff --git a/src/domain/synthetics/markets/technicalFees/calculateGmxAccountTechnicalFees.ts b/src/domain/synthetics/markets/technicalFees/calculateGmxAccountTechnicalFees.ts index 6a02464c99..a075c5763d 100644 --- a/src/domain/synthetics/markets/technicalFees/calculateGmxAccountTechnicalFees.ts +++ b/src/domain/synthetics/markets/technicalFees/calculateGmxAccountTechnicalFees.ts @@ -63,8 +63,8 @@ async function calculateGmxAccountDepositTechnicalFees( isMarketTokenDeposit: params.isGlv ? (params.rawParams as RawCreateGlvDepositParams).isMarketTokenDeposit : false, marketTokenAddress: params.isGlv ? params.rawParams.addresses.market : undefined, marketTokenAmount: params.isGlv ? params.firstTokenAmount : 0n, - longTokenAmount: params.firstTokenAmount, - shortTokenAmount: params.secondTokenAmount, + longTokenAmount: params.longTokenAmount, + shortTokenAmount: params.shortTokenAmount, initialLongTokenAddress: castedParams.addresses.initialLongToken, initialShortTokenAddress: castedParams.addresses.initialShortToken, technicalFees: undefined, diff --git a/src/domain/synthetics/markets/technicalFees/technical-fees-types.ts b/src/domain/synthetics/markets/technicalFees/technical-fees-types.ts index 080bd3f498..606ded5b53 100644 --- a/src/domain/synthetics/markets/technicalFees/technical-fees-types.ts +++ b/src/domain/synthetics/markets/technicalFees/technical-fees-types.ts @@ -75,8 +75,8 @@ export type CalculateTechnicalFeesParams = { srcChainId: SourceChainId | undefined; firstTokenAddress: NativeTokenSupportedAddress | ERC20Address | undefined; firstTokenAmount: bigint; - secondTokenAddress: NativeTokenSupportedAddress | ERC20Address | undefined; - secondTokenAmount: bigint; + longTokenAmount: bigint; + shortTokenAmount: bigint; marketTokenAmount: bigint; operation: Operation; amounts: DepositAmounts | WithdrawalAmounts | undefined; From 65d9694f3d30b06dd3232bf166aa5723c466b5f3 Mon Sep 17 00:00:00 2001 From: midas-myth Date: Wed, 7 Jan 2026 19:58:34 +0100 Subject: [PATCH 15/23] Fix estimateArbitraryGasLimit --- src/domain/multichain/arbitraryRelayParams.ts | 21 +------------------ 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/src/domain/multichain/arbitraryRelayParams.ts b/src/domain/multichain/arbitraryRelayParams.ts index b4ac4f0cfe..041d9d4f40 100644 --- a/src/domain/multichain/arbitraryRelayParams.ts +++ b/src/domain/multichain/arbitraryRelayParams.ts @@ -1,19 +1,10 @@ import { useMemo } from "react"; -import { - encodeAbiParameters, - encodePacked, - EstimateGasParameters, - keccak256, - PublicClient, - toHex, - zeroHash, -} from "viem"; +import { encodeAbiParameters, encodePacked, EstimateGasParameters, keccak256, PublicClient, toHex } from "viem"; import type { ContractsChainId } from "config/chains"; import { getContract } from "config/contracts"; import { GMX_SIMULATION_ORIGIN, multichainBalanceKey } from "config/dataStore"; import { SIMULATED_MULTICHAIN_BALANCE } from "config/multichain"; -import { OVERRIDE_ERC20_BYTECODE, RANDOM_SLOT } from "config/multichain"; import { selectExpressGlobalParams } from "context/SyntheticsStateContext/selectors/expressSelectors"; import { selectAccount, @@ -179,16 +170,6 @@ async function estimateArbitraryGasLimit({ }, ], }, - { - address: gasPaymentParams.relayerFeeTokenAddress, - code: OVERRIDE_ERC20_BYTECODE, - state: [ - { - slot: RANDOM_SLOT, - value: zeroHash, - }, - ], - }, ], }; From ec543df7bfe4c68bc29f5b39b403522ea70582e0 Mon Sep 17 00:00:00 2001 From: midas-myth Date: Wed, 7 Jan 2026 20:06:14 +0100 Subject: [PATCH 16/23] Add useOpenInterestInTokensForBalance field and related enums to MarketInfo --- sdk/src/types/subsquid.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/sdk/src/types/subsquid.ts b/sdk/src/types/subsquid.ts index ee911ff29f..7df7dc4aac 100644 --- a/sdk/src/types/subsquid.ts +++ b/sdk/src/types/subsquid.ts @@ -2556,6 +2556,7 @@ export interface MarketInfo { thresholdForDecreaseFunding: Scalars["BigInt"]["output"]; thresholdForStableFunding: Scalars["BigInt"]["output"]; totalBorrowingFees: Scalars["BigInt"]["output"]; + useOpenInterestInTokensForBalance: Scalars["Boolean"]["output"]; virtualIndexTokenId: Scalars["String"]["output"]; virtualInventoryForPositions: Scalars["BigInt"]["output"]; virtualLongTokenId: Scalars["String"]["output"]; @@ -3088,6 +3089,12 @@ export enum MarketInfoOrderByInput { totalBorrowingFees_DESC = "totalBorrowingFees_DESC", totalBorrowingFees_DESC_NULLS_FIRST = "totalBorrowingFees_DESC_NULLS_FIRST", totalBorrowingFees_DESC_NULLS_LAST = "totalBorrowingFees_DESC_NULLS_LAST", + useOpenInterestInTokensForBalance_ASC = "useOpenInterestInTokensForBalance_ASC", + useOpenInterestInTokensForBalance_ASC_NULLS_FIRST = "useOpenInterestInTokensForBalance_ASC_NULLS_FIRST", + useOpenInterestInTokensForBalance_ASC_NULLS_LAST = "useOpenInterestInTokensForBalance_ASC_NULLS_LAST", + useOpenInterestInTokensForBalance_DESC = "useOpenInterestInTokensForBalance_DESC", + useOpenInterestInTokensForBalance_DESC_NULLS_FIRST = "useOpenInterestInTokensForBalance_DESC_NULLS_FIRST", + useOpenInterestInTokensForBalance_DESC_NULLS_LAST = "useOpenInterestInTokensForBalance_DESC_NULLS_LAST", virtualIndexTokenId_ASC = "virtualIndexTokenId_ASC", virtualIndexTokenId_ASC_NULLS_FIRST = "virtualIndexTokenId_ASC_NULLS_FIRST", virtualIndexTokenId_ASC_NULLS_LAST = "virtualIndexTokenId_ASC_NULLS_LAST", @@ -3937,6 +3944,9 @@ export interface MarketInfoWhereInput { totalBorrowingFees_lte?: InputMaybe; totalBorrowingFees_not_eq?: InputMaybe; totalBorrowingFees_not_in?: InputMaybe>; + useOpenInterestInTokensForBalance_eq?: InputMaybe; + useOpenInterestInTokensForBalance_isNull?: InputMaybe; + useOpenInterestInTokensForBalance_not_eq?: InputMaybe; virtualIndexTokenId_contains?: InputMaybe; virtualIndexTokenId_containsInsensitive?: InputMaybe; virtualIndexTokenId_endsWith?: InputMaybe; From 9ebf3bf65cf2869311e37c4f3ec5e4e51f944392 Mon Sep 17 00:00:00 2001 From: midas-myth Date: Wed, 7 Jan 2026 20:22:07 +0100 Subject: [PATCH 17/23] Reorder import statements in TradeBox component for consistency --- src/components/TradeBox/TradeBox.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/TradeBox/TradeBox.tsx b/src/components/TradeBox/TradeBox.tsx index ba3e23e61a..f0819b8f60 100644 --- a/src/components/TradeBox/TradeBox.tsx +++ b/src/components/TradeBox/TradeBox.tsx @@ -93,8 +93,8 @@ import { TradeMode } from "sdk/types/trade"; import { AlertInfoCard } from "components/AlertInfo/AlertInfoCard"; import Button from "components/Button/Button"; import BuyInputSection from "components/BuyInputSection/BuyInputSection"; -import ExternalLink from "components/ExternalLink/ExternalLink"; import { ColorfulBanner } from "components/ColorfulBanner/ColorfulBanner"; +import ExternalLink from "components/ExternalLink/ExternalLink"; import { LeverageSlider } from "components/LeverageSlider/LeverageSlider"; import { MarketSelector } from "components/MarketSelector/MarketSelector"; import SuggestionInput from "components/SuggestionInput/SuggestionInput"; From 64e15c998de4d16b04bf7525ede89d7c9de3ab66 Mon Sep 17 00:00:00 2001 From: midas-myth Date: Tue, 13 Jan 2026 16:11:53 +0100 Subject: [PATCH 18/23] Update WithdrawalView to prevent button state change during loading of express transaction parameters --- src/components/GmxAccountModal/WithdrawalView.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/GmxAccountModal/WithdrawalView.tsx b/src/components/GmxAccountModal/WithdrawalView.tsx index a89fc3b7ba..061d0b7362 100644 --- a/src/components/GmxAccountModal/WithdrawalView.tsx +++ b/src/components/GmxAccountModal/WithdrawalView.tsx @@ -805,7 +805,7 @@ export const WithdrawalView = () => { text: t`Insufficient ${isOutOfTokenErrorToken?.symbol} balance`, disabled: true, }; - } else if (showWntWarning) { + } else if (showWntWarning && !expressTxnParamsAsyncResult.isLoading) { buttonState = { text: t`Insufficient ${wrappedNativeToken?.symbol} balance`, disabled: true, From 189478c418d487563494e2cecc2a47388f98cadf Mon Sep 17 00:00:00 2001 From: midas-myth Date: Tue, 13 Jan 2026 23:35:50 +0100 Subject: [PATCH 19/23] Refactor TransferDetailsView and WithdrawalView for token address handling --- src/components/GmxAccountModal/TransferDetailsView.tsx | 4 ++-- src/components/GmxAccountModal/WithdrawalView.tsx | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/components/GmxAccountModal/TransferDetailsView.tsx b/src/components/GmxAccountModal/TransferDetailsView.tsx index 9fe18d41b7..501375d51c 100644 --- a/src/components/GmxAccountModal/TransferDetailsView.tsx +++ b/src/components/GmxAccountModal/TransferDetailsView.tsx @@ -18,7 +18,7 @@ import { useChainId } from "lib/chains"; import { CHAIN_ID_TO_EXPLORER_NAME, CHAIN_ID_TO_TX_URL_BUILDER } from "lib/chains/blockExplorers"; import { formatAmountFree } from "lib/numbers"; import { shortenAddressOrEns } from "lib/wallets"; -import { getToken } from "sdk/configs/tokens"; +import { convertTokenAddress, getToken } from "sdk/configs/tokens"; import { AlertInfoCard } from "components/AlertInfo/AlertInfoCard"; import { Amount } from "components/Amount/Amount"; @@ -84,7 +84,7 @@ export const TransferDetailsView = () => { if (selectedTransfer.operation === "withdrawal") { setGmxAccountWithdrawalViewChain(selectedTransfer.sourceChainId as SourceChainId); - setGmxAccountWithdrawalViewTokenAddress(selectedTransfer.token); + setGmxAccountWithdrawalViewTokenAddress(convertTokenAddress(chainId, selectedTransfer.token, "wrapped")); setGmxAccountWithdrawalViewTokenInputValue(formatAmountFree(selectedTransfer.sentAmount, token.decimals)); setGmxAccountModalOpen("withdraw"); } diff --git a/src/components/GmxAccountModal/WithdrawalView.tsx b/src/components/GmxAccountModal/WithdrawalView.tsx index 061d0b7362..415959a457 100644 --- a/src/components/GmxAccountModal/WithdrawalView.tsx +++ b/src/components/GmxAccountModal/WithdrawalView.tsx @@ -833,10 +833,11 @@ export const WithdrawalView = () => { } } - const hasSelectedToken = selectedTokenAddress !== undefined; + const hasValidSelectedToken = + selectedTokenAddress !== undefined && MULTI_CHAIN_WITHDRAWAL_TRADE_TOKENS[chainId]?.includes(selectedTokenAddress); useEffect( function fallbackWithdrawTokens() { - if (hasSelectedToken || !withdrawalViewChain || !isSettlementChain(chainId) || isVisibleOrView === false) { + if (hasValidSelectedToken || !withdrawalViewChain || !isSettlementChain(chainId) || isVisibleOrView === false) { return; } @@ -886,7 +887,7 @@ export const WithdrawalView = () => { setSelectedTokenAddress(maxBalanceSettlementChainTokenAddress); } }, - [chainId, hasSelectedToken, isVisibleOrView, setSelectedTokenAddress, tokensData, withdrawalViewChain] + [chainId, hasValidSelectedToken, isVisibleOrView, setSelectedTokenAddress, tokensData, withdrawalViewChain] ); const isTestnet = isTestnetChain(chainId); From a331e153c4c966515bc173cbfc9f9da64c11d0ad Mon Sep 17 00:00:00 2001 From: midas-myth Date: Wed, 14 Jan 2026 15:46:40 +0100 Subject: [PATCH 20/23] Enhance loading state handling in WithdrawalView to include additional error checks and warnings --- src/components/GmxAccountModal/WithdrawalView.tsx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/components/GmxAccountModal/WithdrawalView.tsx b/src/components/GmxAccountModal/WithdrawalView.tsx index 415959a457..4a56f8d9d4 100644 --- a/src/components/GmxAccountModal/WithdrawalView.tsx +++ b/src/components/GmxAccountModal/WithdrawalView.tsx @@ -817,9 +817,13 @@ export const WithdrawalView = () => { }; } else if ( // We do not show loading state if we have valid params - // But show loafing periodically if the params are not valid to show the user some action + // But show loading periodically if the params are not valid to show the user some action !expressTxnParamsAsyncResult.data || - (expressTxnParamsAsyncResult.isLoading && !expressTxnParamsAsyncResult.data.gasPaymentValidations.isValid) + (expressTxnParamsAsyncResult.isLoading && + (!expressTxnParamsAsyncResult.data.gasPaymentValidations.isValid || + showWntWarning || + errors?.isOutOfTokenError || + expressTxnParamsAsyncResult.error)) ) { buttonState = { text: ( From 967f9c6563b0c00de9b4a690d13b5d68c0fee4d3 Mon Sep 17 00:00:00 2001 From: midas-myth Date: Thu, 15 Jan 2026 00:11:33 +0100 Subject: [PATCH 21/23] Add gas payment network fee display in BridgeOutModal --- src/components/BridgeModal/BridgeOutModal.tsx | 60 ++++++++++++++++++- src/domain/multichain/useQuoteSend.ts | 4 -- 2 files changed, 58 insertions(+), 6 deletions(-) diff --git a/src/components/BridgeModal/BridgeOutModal.tsx b/src/components/BridgeModal/BridgeOutModal.tsx index 29208e212b..ec3a13d67c 100644 --- a/src/components/BridgeModal/BridgeOutModal.tsx +++ b/src/components/BridgeModal/BridgeOutModal.tsx @@ -1,7 +1,7 @@ import { t, Trans } from "@lingui/macro"; import { ReactNode, useEffect, useMemo, useState } from "react"; import Skeleton from "react-loading-skeleton"; -import { Address, encodeAbiParameters } from "viem"; +import { Address, encodeAbiParameters, zeroAddress } from "viem"; import { useAccount } from "wagmi"; import { @@ -15,10 +15,15 @@ import { getChainIcon } from "config/icons"; import { getLayerZeroEndpointId, getStargatePoolAddress } from "config/multichain"; import { useGmxAccountSettlementChainId } from "context/GmxAccountContext/hooks"; import { selectMultichainMarketTokenBalances } from "context/PoolsDetailsContext/selectors/selectMultichainMarketTokenBalances"; -import { selectDepositMarketTokensData } from "context/SyntheticsStateContext/selectors/globalSelectors"; +import { + selectDepositMarketTokensData, + selectTokensData, +} from "context/SyntheticsStateContext/selectors/globalSelectors"; import { useSelector } from "context/SyntheticsStateContext/utils"; import { useArbitraryError, useArbitraryRelayParamsAndPayload } from "domain/multichain/arbitraryRelayParams"; +import { getMultichainTransferSendParams } from "domain/multichain/getSendParams"; import type { BridgeOutParams } from "domain/multichain/types"; +import { useQuoteSendNativeFee } from "domain/multichain/useQuoteSend"; import { buildAndSignBridgeOutTxn } from "domain/synthetics/express/expressOrderUtils"; import { ExpressTransactionBuilder } from "domain/synthetics/express/types"; import { getGlvOrMarketAddress, GlvOrMarketInfo } from "domain/synthetics/markets"; @@ -61,6 +66,7 @@ export function BridgeOutModal({ const [bridgeOutInputValue, setBridgeOutInputValue] = useState(""); const [isCreatingTxn, setIsCreatingTxn] = useState(false); + const tokensData = useSelector(selectTokensData); const depositMarketTokensData = useSelector(selectDepositMarketTokensData); const glvOrMarketAddress = glvOrMarketInfo ? getGlvOrMarketAddress(glvOrMarketInfo) : undefined; const marketToken = getTokenData(depositMarketTokensData, glvOrMarketAddress); @@ -150,6 +156,53 @@ export function BridgeOutModal({ enabled: isVisible, }); + const sendParams = useMemo(() => { + if (!bridgeOutChain || !account || bridgeOutAmount === undefined || bridgeOutAmount <= 0n) { + return; + } + + return getMultichainTransferSendParams({ + dstChainId: bridgeOutChain, + account, + amountLD: bridgeOutAmount, + isToGmx: false, + isManualGas: true, + srcChainId: chainId, + }); + }, [bridgeOutChain, account, bridgeOutAmount, chainId]); + + const transferNativeFee = useQuoteSendNativeFee({ + fromChainId: chainId, + toChainId: bridgeOutChain, + sendParams, + fromStargateAddress: bridgeOutParams?.provider, + }); + + const networkFeeUsd = useMemo(() => { + if ( + transferNativeFee === undefined || + tokensData === undefined || + tokensData[zeroAddress] === undefined || + expressTxnParamsAsyncResult.data === undefined + ) { + return; + } + + const relayFeeUsd = convertToUsd( + expressTxnParamsAsyncResult.data.gasPaymentParams.gasPaymentTokenAmount, + expressTxnParamsAsyncResult.data.gasPaymentParams.gasPaymentToken.decimals, + getMidPrice(expressTxnParamsAsyncResult.data.gasPaymentParams.gasPaymentToken.prices) + )!; + + const transferNativeFeeUsd = convertToUsd( + transferNativeFee, + tokensData[zeroAddress].decimals, + tokensData[zeroAddress].prices.minPrice + )!; + + return relayFeeUsd + transferNativeFeeUsd; + }, [transferNativeFee, tokensData, expressTxnParamsAsyncResult.data]); + const errors = useArbitraryError(expressTxnParamsAsyncResult.error); const hasOutdatedUi = useHasOutdatedUi(); @@ -354,6 +407,9 @@ export function BridgeOutModal({ + + + Date: Thu, 15 Jan 2026 00:12:21 +0100 Subject: [PATCH 22/23] Sync translations --- src/locales/de/messages.po | 1 + src/locales/en/messages.po | 1 + src/locales/es/messages.po | 1 + src/locales/fr/messages.po | 1 + src/locales/ja/messages.po | 1 + src/locales/ko/messages.po | 1 + src/locales/pseudo/messages.po | 1 + src/locales/ru/messages.po | 1 + src/locales/zh/messages.po | 1 + 9 files changed, 9 insertions(+) diff --git a/src/locales/de/messages.po b/src/locales/de/messages.po index 8a2a93ba8d..f989d39cba 100644 --- a/src/locales/de/messages.po +++ b/src/locales/de/messages.po @@ -2942,6 +2942,7 @@ msgid "Learn how the GMX, GLV, and GM tokens work together to power a decentrali msgstr "Erfahre, wie GMX-, GLV- und GM-Token zusammenwirken, um ein dezentrales Trading-Erlebnis zu ermöglichen. Entdecke die Rolle jedes Tokens und wie du durch Staking oder Liquiditätsbereitstellung Belohnungen verdienen kannst – genau wie Zehntausende andere GMX-Nutzer." #: src/components/BridgeModal/BridgeInModal.tsx +#: src/components/BridgeModal/BridgeOutModal.tsx #: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/InfoRows.tsx #: src/components/GmxAccountModal/DepositView.tsx #: src/components/GmxAccountModal/WithdrawalView.tsx diff --git a/src/locales/en/messages.po b/src/locales/en/messages.po index 95a3fd4322..0ec1c99b1e 100644 --- a/src/locales/en/messages.po +++ b/src/locales/en/messages.po @@ -2942,6 +2942,7 @@ msgid "Learn how the GMX, GLV, and GM tokens work together to power a decentrali msgstr "Learn how the GMX, GLV, and GM tokens work together to power a decentralized trading experience. Explore the role of each token, and discover how you can stake or provide liquidity to earn rewards — just like tens of thousands of other GMX users." #: src/components/BridgeModal/BridgeInModal.tsx +#: src/components/BridgeModal/BridgeOutModal.tsx #: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/InfoRows.tsx #: src/components/GmxAccountModal/DepositView.tsx #: src/components/GmxAccountModal/WithdrawalView.tsx diff --git a/src/locales/es/messages.po b/src/locales/es/messages.po index 1aa91ee225..1c4c013b4d 100644 --- a/src/locales/es/messages.po +++ b/src/locales/es/messages.po @@ -2942,6 +2942,7 @@ msgid "Learn how the GMX, GLV, and GM tokens work together to power a decentrali msgstr "Descubre cómo los tokens GMX, GLV y GM trabajan juntos para potenciar una experiencia de trading descentralizada. Explora el rol de cada token y descubre cómo puedes hacer staking o proveer liquidez para ganar recompensas, igual que decenas de miles de otros usuarios de GMX." #: src/components/BridgeModal/BridgeInModal.tsx +#: src/components/BridgeModal/BridgeOutModal.tsx #: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/InfoRows.tsx #: src/components/GmxAccountModal/DepositView.tsx #: src/components/GmxAccountModal/WithdrawalView.tsx diff --git a/src/locales/fr/messages.po b/src/locales/fr/messages.po index 25850185d4..c263dd74c2 100644 --- a/src/locales/fr/messages.po +++ b/src/locales/fr/messages.po @@ -2942,6 +2942,7 @@ msgid "Learn how the GMX, GLV, and GM tokens work together to power a decentrali msgstr "Découvrez comment les tokens GMX, GLV et GM fonctionnent ensemble pour alimenter une expérience de trading décentralisée. Explorez le rôle de chaque token et découvrez comment vous pouvez staker ou fournir de la liquidité pour gagner des récompenses — comme des dizaines de milliers d'autres utilisateurs GMX." #: src/components/BridgeModal/BridgeInModal.tsx +#: src/components/BridgeModal/BridgeOutModal.tsx #: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/InfoRows.tsx #: src/components/GmxAccountModal/DepositView.tsx #: src/components/GmxAccountModal/WithdrawalView.tsx diff --git a/src/locales/ja/messages.po b/src/locales/ja/messages.po index 385dd425e8..7d98d6769e 100644 --- a/src/locales/ja/messages.po +++ b/src/locales/ja/messages.po @@ -2942,6 +2942,7 @@ msgid "Learn how the GMX, GLV, and GM tokens work together to power a decentrali msgstr "GMX、GLV、GMトークンがどのように連携して分散型取引体験を実現しているかをご覧ください。各トークンの役割を探り、数万人の他のGMXユーザーと同様に、ステーキングや流動性提供で報酬を得る方法を発見しましょう。" #: src/components/BridgeModal/BridgeInModal.tsx +#: src/components/BridgeModal/BridgeOutModal.tsx #: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/InfoRows.tsx #: src/components/GmxAccountModal/DepositView.tsx #: src/components/GmxAccountModal/WithdrawalView.tsx diff --git a/src/locales/ko/messages.po b/src/locales/ko/messages.po index 63345694a0..be9dd5916f 100644 --- a/src/locales/ko/messages.po +++ b/src/locales/ko/messages.po @@ -2942,6 +2942,7 @@ msgid "Learn how the GMX, GLV, and GM tokens work together to power a decentrali msgstr "GMX, GLV 및 GM 토큰이 어떻게 협력하여 탈중앙화 거래 경험을 제공하는지 알아보세요. 각 토큰의 역할을 탐색하고, 수만 명의 다른 GMX 사용자처럼 스테이킹하거나 유동성을 제공하여 보상을 받는 방법을 발견하세요." #: src/components/BridgeModal/BridgeInModal.tsx +#: src/components/BridgeModal/BridgeOutModal.tsx #: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/InfoRows.tsx #: src/components/GmxAccountModal/DepositView.tsx #: src/components/GmxAccountModal/WithdrawalView.tsx diff --git a/src/locales/pseudo/messages.po b/src/locales/pseudo/messages.po index c3632e6865..a5ea4a93ed 100644 --- a/src/locales/pseudo/messages.po +++ b/src/locales/pseudo/messages.po @@ -2942,6 +2942,7 @@ msgid "Learn how the GMX, GLV, and GM tokens work together to power a decentrali msgstr "" #: src/components/BridgeModal/BridgeInModal.tsx +#: src/components/BridgeModal/BridgeOutModal.tsx #: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/InfoRows.tsx #: src/components/GmxAccountModal/DepositView.tsx #: src/components/GmxAccountModal/WithdrawalView.tsx diff --git a/src/locales/ru/messages.po b/src/locales/ru/messages.po index 7752ce3869..81c6d34a0b 100644 --- a/src/locales/ru/messages.po +++ b/src/locales/ru/messages.po @@ -2942,6 +2942,7 @@ msgid "Learn how the GMX, GLV, and GM tokens work together to power a decentrali msgstr "Узнайте, как токены GMX, GLV и GM работают вместе для обеспечения децентрализованного торгового опыта. Изучите роль каждого токена и откройте для себя, как можно стейкать или предоставлять ликвидность для получения наград — как и десятки тысяч других пользователей GMX." #: src/components/BridgeModal/BridgeInModal.tsx +#: src/components/BridgeModal/BridgeOutModal.tsx #: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/InfoRows.tsx #: src/components/GmxAccountModal/DepositView.tsx #: src/components/GmxAccountModal/WithdrawalView.tsx diff --git a/src/locales/zh/messages.po b/src/locales/zh/messages.po index 50f9a12895..648598951b 100644 --- a/src/locales/zh/messages.po +++ b/src/locales/zh/messages.po @@ -2942,6 +2942,7 @@ msgid "Learn how the GMX, GLV, and GM tokens work together to power a decentrali msgstr "了解 GMX、GLV 和 GM 代币如何协同工作,为去中心化交易体验提供动力。探索每个代币的作用,发现如何通过质押或提供流动性来获得奖励——就像数万名其他 GMX 用户一样。" #: src/components/BridgeModal/BridgeInModal.tsx +#: src/components/BridgeModal/BridgeOutModal.tsx #: src/components/GmSwap/GmSwapBox/GmDepositWithdrawalBox/InfoRows.tsx #: src/components/GmxAccountModal/DepositView.tsx #: src/components/GmxAccountModal/WithdrawalView.tsx From c37acacfea93f576ea2ab7bb390ce64700d296af Mon Sep 17 00:00:00 2001 From: midas-myth Date: Thu, 15 Jan 2026 12:14:25 +0100 Subject: [PATCH 23/23] Remove unused fromChainProvider parameter in DepositView and WithdrawalView components --- src/components/GmxAccountModal/DepositView.tsx | 1 - src/components/GmxAccountModal/WithdrawalView.tsx | 2 -- 2 files changed, 3 deletions(-) diff --git a/src/components/GmxAccountModal/DepositView.tsx b/src/components/GmxAccountModal/DepositView.tsx index 41e5e4539b..386edf77f1 100644 --- a/src/components/GmxAccountModal/DepositView.tsx +++ b/src/components/GmxAccountModal/DepositView.tsx @@ -381,7 +381,6 @@ export const DepositView = () => { const quoteSendNativeFee = useQuoteSendNativeFee({ sendParams: sendParamsWithSlippage, fromStargateAddress: selectedTokenSourceChainTokenId?.stargate, - fromChainProvider: sourceChainProvider, fromChainId: depositViewChain, toChainId: settlementChainId, composeGas, diff --git a/src/components/GmxAccountModal/WithdrawalView.tsx b/src/components/GmxAccountModal/WithdrawalView.tsx index 85012e8f02..b1f7ea0426 100644 --- a/src/components/GmxAccountModal/WithdrawalView.tsx +++ b/src/components/GmxAccountModal/WithdrawalView.tsx @@ -296,7 +296,6 @@ export const WithdrawalView = () => { const nativeFee = useQuoteSendNativeFee({ sendParams: sendParamsWithSlippage, fromStargateAddress: selectedTokenSettlementChainTokenId?.stargate, - fromChainProvider: provider, fromChainId: chainId, toChainId: withdrawalViewChain, }); @@ -332,7 +331,6 @@ export const WithdrawalView = () => { const baseNativeFee = useQuoteSendNativeFee({ sendParams: baseSendParams, fromStargateAddress: selectedTokenSettlementChainTokenId?.stargate, - fromChainProvider: provider, fromChainId: chainId, toChainId: withdrawalViewChain, });