diff --git a/packages/core/src/types/coreTypesTx.ts b/packages/core/src/types/coreTypesTx.ts
index 9dced02d5ec..376c45d276e 100644
--- a/packages/core/src/types/coreTypesTx.ts
+++ b/packages/core/src/types/coreTypesTx.ts
@@ -2,7 +2,7 @@ import type {
IApproveInfo,
ITransferInfo,
} from '@onekeyhq/kit-bg/src/vaults/types';
-import type { IFeeInfoUnit } from '@onekeyhq/shared/types/fee';
+import type { IFeeInfoUnit, IFeesInfoUnit } from '@onekeyhq/shared/types/fee';
import type { IEncodedTxLightning } from '@onekeyhq/shared/types/lightning';
import type { IStakingInfo } from '@onekeyhq/shared/types/staking';
import type { ISwapTxInfo } from '@onekeyhq/shared/types/swap/types';
@@ -107,6 +107,7 @@ export type IUnsignedTx = {
export type IUnsignedTxPro = IUnsignedTx & {
encodedTx: IEncodedTx;
feeInfo?: IFeeInfoUnit | undefined;
+ feesInfo?: IFeesInfoUnit | undefined;
swapInfo?: ISwapTxInfo | undefined;
approveInfo?: IApproveInfo | undefined;
stakingInfo?: IStakingInfo;
diff --git a/packages/kit/src/hooks/useSendConfirm.ts b/packages/kit/src/hooks/useSendConfirm.ts
index ee4fa971caa..03e769ca1b5 100644
--- a/packages/kit/src/hooks/useSendConfirm.ts
+++ b/packages/kit/src/hooks/useSendConfirm.ts
@@ -116,8 +116,12 @@ function useSendConfirm(params: IParams) {
);
}
+ const target = params.isInternalSwap
+ ? EModalSendRoutes.SendConfirmFromSwap
+ : EModalSendRoutes.SendConfirm;
+
if (sameModal) {
- navigation.push(EModalSendRoutes.SendConfirm, {
+ navigation.push(target, {
accountId,
networkId,
unsignedTxs,
@@ -131,7 +135,7 @@ function useSendConfirm(params: IParams) {
});
} else {
navigation.pushModal(EModalRoutes.SendModal, {
- screen: EModalSendRoutes.SendConfirm,
+ screen: target,
params: {
accountId,
networkId,
diff --git a/packages/kit/src/views/Developer/pages/Gallery/Components/stories/Toast.tsx b/packages/kit/src/views/Developer/pages/Gallery/Components/stories/Toast.tsx
index c1f498b2703..444b60769ff 100644
--- a/packages/kit/src/views/Developer/pages/Gallery/Components/stories/Toast.tsx
+++ b/packages/kit/src/views/Developer/pages/Gallery/Components/stories/Toast.tsx
@@ -41,7 +41,8 @@ const ToastGallery = () => (
onPress={() => {
Toast.success({
title: 'url!',
- message: 'look, OneKey here. aaa',
+ message:
+ 'look, OneKey here. aaa',
});
}}
>
diff --git a/packages/kit/src/views/Send/pages/SendConfirm/SendConfirmActionsContainer.tsx b/packages/kit/src/views/Send/pages/SendConfirm/SendConfirmActionsContainer.tsx
index 336f42181df..6919012c2e7 100644
--- a/packages/kit/src/views/Send/pages/SendConfirm/SendConfirmActionsContainer.tsx
+++ b/packages/kit/src/views/Send/pages/SendConfirm/SendConfirmActionsContainer.tsx
@@ -52,6 +52,7 @@ type IProps = {
transferPayload: ITransferPayload | undefined;
useFeeInTx?: boolean;
feeInfoEditable?: boolean;
+ popStack?: boolean;
};
function SendConfirmActionsContainer(props: IProps) {
@@ -66,6 +67,7 @@ function SendConfirmActionsContainer(props: IProps) {
transferPayload,
useFeeInTx,
feeInfoEditable,
+ popStack = true,
} = props;
const intl = useIntl();
const isSubmitted = useRef(false);
@@ -243,7 +245,11 @@ function SendConfirmActionsContainer(props: IProps) {
void dappApprove.resolve({ result: signedTx });
- navigation.popStack();
+ if (popStack) {
+ navigation.popStack();
+ } else {
+ navigation.pop();
+ }
updateSendTxStatus({ isSubmitting: false });
onSuccess?.(result);
} catch (e: any) {
@@ -276,8 +282,9 @@ function SendConfirmActionsContainer(props: IProps) {
sourceInfo,
transferPayload,
intl,
- navigation,
+ popStack,
onSuccess,
+ navigation,
]);
const cancelCalledRef = useRef(false);
diff --git a/packages/kit/src/views/Send/pages/SendConfirm/SendConfirmContainer.tsx b/packages/kit/src/views/Send/pages/SendConfirm/SendConfirmContainer.tsx
index efb5d16520c..9dc0859d7c1 100644
--- a/packages/kit/src/views/Send/pages/SendConfirm/SendConfirmContainer.tsx
+++ b/packages/kit/src/views/Send/pages/SendConfirm/SendConfirmContainer.tsx
@@ -64,6 +64,7 @@ function SendConfirmContainer() {
useFeeInTx,
transferPayload,
feeInfoEditable,
+ popStack,
} = route.params;
const dappApprove = useDappApproveAction({
@@ -208,6 +209,7 @@ function SendConfirmContainer() {
/>
unsignedTxs.length === 1 && unsignedTxs[0].feesInfo,
+ [unsignedTxs],
+ );
+
const isSecondApproveTxWithFeeInfo = useMemo(
() =>
unsignedTxs.length === 1 &&
@@ -185,6 +190,21 @@ function TxFeeContainer(props: IProps) {
encodedTx: unsignedTxs[0].encodedTx,
});
+ if (isSingleTxWithFeesInfo) {
+ const r = unsignedTxs[0].feesInfo;
+ updateSendFeeStatus({
+ status: ESendFeeStatus.Success,
+ errMessage: '',
+ });
+ setTxFeeInit(true);
+ updateTxAdvancedSettings({ dataChanged: false });
+ return {
+ r,
+ e,
+ m: undefined,
+ };
+ }
+
if (
(isLastSwapTxWithFeeInfo || isSecondApproveTxWithFeeInfo) &&
unsignedTxs[0].feeInfo
@@ -256,6 +276,7 @@ function TxFeeContainer(props: IProps) {
isLastSwapTxWithFeeInfo,
isMultiTxs,
isSecondApproveTxWithFeeInfo,
+ isSingleTxWithFeesInfo,
networkId,
unsignedTxs,
updateSendFeeStatus,
diff --git a/packages/kit/src/views/Send/pages/SendConfirmFromSwap/SendConfirmFromSwap.tsx b/packages/kit/src/views/Send/pages/SendConfirmFromSwap/SendConfirmFromSwap.tsx
new file mode 100644
index 00000000000..6827021d3c4
--- /dev/null
+++ b/packages/kit/src/views/Send/pages/SendConfirmFromSwap/SendConfirmFromSwap.tsx
@@ -0,0 +1,160 @@
+import { useCallback, useEffect, useRef } from 'react';
+
+import { useRoute } from '@react-navigation/core';
+import { StackActions, useNavigation } from '@react-navigation/native';
+import { AppState } from 'react-native';
+
+import { Page, Spinner, Stack } from '@onekeyhq/components';
+import backgroundApiProxy from '@onekeyhq/kit/src/background/instance/backgroundApiProxy';
+import useAppNavigation from '@onekeyhq/kit/src/hooks/useAppNavigation';
+import type { IModalSendParamList } from '@onekeyhq/shared/src/routes';
+import { EModalSendRoutes } from '@onekeyhq/shared/src/routes';
+import accountUtils from '@onekeyhq/shared/src/utils/accountUtils';
+import type { IGasEIP1559, IGasLegacy } from '@onekeyhq/shared/types/fee';
+import type { ISendTxOnSuccessData } from '@onekeyhq/shared/types/tx';
+
+import type { RouteProp } from '@react-navigation/core';
+import type { StackActionType } from '@react-navigation/native';
+
+function SendConfirmFromSwap() {
+ const pendingAction = useRef();
+ const navigation = useNavigation();
+ const appNavigation = useAppNavigation();
+
+ const route =
+ useRoute<
+ RouteProp
+ >();
+
+ const { networkId, accountId, unsignedTxs, onSuccess, onFail, onCancel } =
+ route.params;
+
+ const handleConfirmMultiTxsOnHwOrExternal = useCallback(
+ async (multiTxsFeeResult: {
+ common: {
+ baseFee: string | undefined;
+ feeDecimals: number;
+ feeSymbol: string;
+ nativeDecimals: number;
+ nativeSymbol: string;
+ nativeTokenPrice: number | undefined;
+ };
+ txFees: {
+ gas: IGasLegacy[];
+ gasEIP1559: IGasEIP1559[];
+ }[];
+ }) => {
+ for (let i = 0, len = unsignedTxs.length; i < len; i += 1) {
+ const unsignedTx = unsignedTxs[i];
+ unsignedTx.feesInfo = {
+ common: multiTxsFeeResult.common,
+ gas: multiTxsFeeResult.txFees[i].gas,
+ gasEIP1559: multiTxsFeeResult.txFees[i].gasEIP1559,
+ };
+ const isLastTx = i === len - 1;
+
+ await new Promise((resolve) => {
+ appNavigation.push(EModalSendRoutes.SendConfirm, {
+ ...route.params,
+ popStack: false,
+ unsignedTxs: [unsignedTx],
+ onSuccess: (data: ISendTxOnSuccessData[]) => {
+ if (isLastTx) {
+ onSuccess?.(data);
+ appNavigation.popStack();
+ }
+ resolve(data);
+ },
+ onFail: (error: Error) => {
+ onFail?.(error);
+
+ appNavigation.popStack();
+ },
+ onCancel: () => {
+ onCancel?.();
+ appNavigation.popStack();
+ },
+ });
+ });
+ }
+ },
+ [unsignedTxs, appNavigation, route.params, onSuccess, onFail, onCancel],
+ );
+
+ const navigationToSendConfirm = useCallback(async () => {
+ let action: any;
+ let batchEstimateButSingleConfirm = false;
+ const isMultiTxs = unsignedTxs.length > 1;
+ if (
+ isMultiTxs &&
+ (accountUtils.isHwAccount({ accountId }) ||
+ accountUtils.isExternalAccount({ accountId }))
+ ) {
+ const vaultSettings =
+ await backgroundApiProxy.serviceNetwork.getVaultSettings({
+ networkId,
+ });
+ if (vaultSettings.supportBatchEstimateFee?.[networkId]) {
+ try {
+ const encodedTxList = unsignedTxs.map((tx) => tx.encodedTx);
+ const multiTxsFeeResult =
+ await backgroundApiProxy.serviceGas.batchEstimateFee({
+ accountId,
+ networkId,
+ encodedTxs: encodedTxList,
+ });
+ if (multiTxsFeeResult.txFees.length === unsignedTxs.length) {
+ await handleConfirmMultiTxsOnHwOrExternal(multiTxsFeeResult);
+ batchEstimateButSingleConfirm = true;
+ } else {
+ batchEstimateButSingleConfirm = false;
+ }
+ } catch (e) {
+ batchEstimateButSingleConfirm = false;
+ }
+ }
+ }
+
+ if (!batchEstimateButSingleConfirm) {
+ action = StackActions.replace(EModalSendRoutes.SendConfirm, {
+ ...route.params,
+ // @ts-ignore
+ _disabledAnimationOfNavigate: true,
+ });
+ }
+
+ if (action) {
+ if (AppState.currentState === 'active') {
+ setTimeout(() => navigation.dispatch(action));
+ } else {
+ pendingAction.current = action;
+ }
+ }
+ }, [
+ accountId,
+ handleConfirmMultiTxsOnHwOrExternal,
+ navigation,
+ networkId,
+ route.params,
+ unsignedTxs,
+ ]);
+
+ const handleOnClose = () => {
+ onCancel?.();
+ };
+
+ useEffect(() => {
+ void navigationToSendConfirm();
+ }, [navigation, navigationToSendConfirm, route.params, unsignedTxs]);
+
+ return (
+
+
+
+
+
+
+
+ );
+}
+export { SendConfirmFromSwap };
diff --git a/packages/kit/src/views/Send/router/index.ts b/packages/kit/src/views/Send/router/index.ts
index da1b72b799d..3cf487062ac 100644
--- a/packages/kit/src/views/Send/router/index.ts
+++ b/packages/kit/src/views/Send/router/index.ts
@@ -9,6 +9,7 @@ import { EModalSendRoutes } from '@onekeyhq/shared/src/routes';
import { LazyLoadPage } from '../../../components/LazyLoadPage';
import { SendConfirmFromDApp } from '../pages/SendConfirmFromDApp/SendConfirmFromDApp';
+import { SendConfirmFromSwap } from '../pages/SendConfirmFromSwap/SendConfirmFromSwap';
const LnurlPayRequestModal = LazyLoadPage(
() =>
@@ -63,6 +64,10 @@ export const ModalSendStack: IModalFlowNavigatorConfig<
name: EModalSendRoutes.SendConfirmFromDApp,
component: SendConfirmFromDApp,
},
+ {
+ name: EModalSendRoutes.SendConfirmFromSwap,
+ component: SendConfirmFromSwap,
+ },
{
name: EModalSendRoutes.SendReplaceTx,
component: SendReplaceTx,
diff --git a/packages/kit/src/views/Swap/hooks/useSwapBuiltTx.ts b/packages/kit/src/views/Swap/hooks/useSwapBuiltTx.ts
index 2898043646e..afc55f0612c 100644
--- a/packages/kit/src/views/Swap/hooks/useSwapBuiltTx.ts
+++ b/packages/kit/src/views/Swap/hooks/useSwapBuiltTx.ts
@@ -18,7 +18,6 @@ import type {
} from '@onekeyhq/kit-bg/src/vaults/types';
import { ETranslations } from '@onekeyhq/shared/src/locale';
import { defaultLogger } from '@onekeyhq/shared/src/logger/logger';
-import accountUtils from '@onekeyhq/shared/src/utils/accountUtils';
import {
numberFormat,
toBigIntHex,
@@ -571,12 +570,6 @@ export function useSwapBuildTx() {
const createBuildTxRes = await createBuildTx();
if (createBuildTxRes) {
if (
- accountUtils.isHwAccount({
- accountId: swapFromAddressInfo.accountInfo.account.id,
- }) ||
- accountUtils.isExternalAccount({
- accountId: swapFromAddressInfo.accountInfo.account.id,
- }) ||
SwapBuildUseMultiplePopoversNetworkIds.includes(
fromToken.networkId,
)
diff --git a/packages/shared/src/routes/send.ts b/packages/shared/src/routes/send.ts
index d351cfdf20d..4b757548380 100644
--- a/packages/shared/src/routes/send.ts
+++ b/packages/shared/src/routes/send.ts
@@ -23,6 +23,7 @@ import type { EReplaceTxType, ISendTxOnSuccessData } from '../../types/tx';
export enum EModalSendRoutes {
SendDataInput = 'SendDataInput',
SendConfirmFromDApp = 'SendConfirmFromDApp',
+ SendConfirmFromSwap = 'SendConfirmFromSwap',
SendConfirm = 'SendConfirm',
SendFeedback = 'SendFeedback',
SendReplaceTx = 'SendReplaceTx',
@@ -63,8 +64,22 @@ export type IModalSendParamList = {
onFail?: (error: Error) => void;
onCancel?: () => void;
transferPayload?: ITransferPayload;
+ popStack?: boolean;
};
[EModalSendRoutes.SendConfirmFromDApp]: undefined;
+ [EModalSendRoutes.SendConfirmFromSwap]: {
+ networkId: string;
+ accountId: string;
+ unsignedTxs: IUnsignedTxPro[];
+ sourceInfo?: IDappSourceInfo;
+ signOnly?: boolean;
+ useFeeInTx?: boolean;
+ feeInfoEditable?: boolean;
+ onSuccess?: (txs: ISendTxOnSuccessData[]) => void;
+ onFail?: (error: Error) => void;
+ onCancel?: () => void;
+ transferPayload?: ITransferPayload;
+ };
[EModalSendRoutes.SendReplaceTx]: {
networkId: string;
accountId: string;
diff --git a/packages/shared/types/fee.ts b/packages/shared/types/fee.ts
index c0061ed5e43..4750c99164c 100644
--- a/packages/shared/types/fee.ts
+++ b/packages/shared/types/fee.ts
@@ -89,6 +89,26 @@ export type IEstimateGasParams = {
encodedTx?: IEncodedTx;
};
+export type IFeesInfoUnit = {
+ common: {
+ baseFee?: string;
+ feeDecimals: number;
+ feeSymbol: string;
+ nativeDecimals: number;
+ nativeSymbol: string;
+ nativeTokenPrice?: number;
+ };
+ gas?: IGasLegacy[];
+ gasEIP1559?: IGasEIP1559[];
+ feeUTXO?: IFeeUTXO[];
+ feeTron?: IFeeTron[];
+ feeSol?: IFeeSol[];
+ feeCkb?: IFeeCkb[];
+ feeAlgo?: IFeeAlgo[];
+ feeDot?: IFeeDot[];
+ feeBudget?: IFeeSui[];
+};
+
export type IFeeInfoUnit = {
common: {
baseFee?: string;