diff --git a/apps/dcellar-web-ui/src/components/layout/Header/PaymentAccounts.tsx b/apps/dcellar-web-ui/src/components/layout/Header/PaymentAccounts.tsx index c1fe28ab..73dded9e 100644 --- a/apps/dcellar-web-ui/src/components/layout/Header/PaymentAccounts.tsx +++ b/apps/dcellar-web-ui/src/components/layout/Header/PaymentAccounts.tsx @@ -1,15 +1,22 @@ -import { GREENFIELD_CHAIN_ID } from "@/base/env"; -import { useAppDispatch, useAppSelector } from "@/store"; -import { setBankBalance, setupAccountsInfo, setupOAList, setupPAList } from "@/store/slices/accounts"; -import { setupGasObjects } from "@/store/slices/global"; -import { useAsyncEffect } from "ahooks"; -import { useRouter } from "next/router"; -import { useBalance } from "wagmi"; +import { GREENFIELD_CHAIN_ID } from '@/base/env'; +import { useAppDispatch, useAppSelector } from '@/store'; +import { + setBankBalance, + setupAccountsInfo, + setupOAList, + setupPAList, +} from '@/store/slices/accounts'; +import { setupGasObjects } from '@/store/slices/global'; +import { useAsyncEffect, useThrottleEffect } from 'ahooks'; +import { useRouter } from 'next/router'; +import { useBalance } from 'wagmi'; export const PaymentAccounts = () => { const dispatch = useAppDispatch(); const { asPath } = useRouter(); const { loginAccount } = useAppSelector((state) => state.persist); + const { bucketInfo } = useAppSelector((state) => state.bucket); + const { bucketName } = useAppSelector((state) => state.object); useAsyncEffect(async () => { dispatch(setupOAList()); dispatch(setupPAList()); @@ -29,5 +36,11 @@ export const PaymentAccounts = () => { dispatch(setBankBalance(metamaskValue)); }, [asPath, refetch]); - return <> -} \ No newline at end of file + useThrottleEffect(() => { + console.log('invoke get paymentAddress info'); + const paymentAddress = bucketInfo[bucketName]?.PaymentAddress; + paymentAddress && dispatch(setupAccountsInfo(paymentAddress)); + }, [asPath]); + + return <>; +}; diff --git a/apps/dcellar-web-ui/src/modules/file/components/Fees.tsx b/apps/dcellar-web-ui/src/modules/file/components/Fees.tsx index db8498ab..0380a510 100644 --- a/apps/dcellar-web-ui/src/modules/file/components/Fees.tsx +++ b/apps/dcellar-web-ui/src/modules/file/components/Fees.tsx @@ -1,11 +1,13 @@ import { memo } from 'react'; -import { Flex, Link, Text } from '@totejs/uikit'; +import { Flex, Link, Text, useDisclosure } from '@totejs/uikit'; import { renderBalanceNumber, renderFeeValue, renderUsd } from '@/modules/file/utils'; import { useAppDispatch, useAppSelector } from '@/store'; import { selectBnbPrice, setupTmpAvailableBalance } from '@/store/slices/global'; import { selectBalance } from '@/store/slices/balance'; import { useMount } from 'ahooks'; import { GAS_FEE_DOC } from '../constant'; +import { MenuCloseIcon } from '@totejs/icons'; +import BigNumber from 'bignumber.js'; interface GasFeeItemProps { label?: string; @@ -14,13 +16,12 @@ interface GasFeeItemProps { } export const Fees = memo(function GasFeeItem(props) { + const { isOpen: isOpenFees, onToggle: onToggleFees } = useDisclosure(); + const exchangeRate = useAppSelector(selectBnbPrice); const dispatch = useAppDispatch(); - const bnbPrice = useAppSelector(selectBnbPrice); const { loginAccount: address } = useAppSelector((root) => root.persist); const { bankBalance: availableBalance } = useAppSelector((root) => root.accounts); - const exchangeRate = Number(bnbPrice); const { label = 'Gas Fee', gasFee, lockFee } = props; - useMount(() => { dispatch(setupTmpAvailableBalance(address)); }); @@ -31,39 +32,74 @@ export const Fees = memo(function GasFeeItem(props) { gap={4} padding={16} borderRadius={12} - mt={32} + // mt={32} w="100%" bg="bg.secondary" flexDirection="column" > - - - - {label} ( - - Pay by Owner Account - - ) - - - - {renderFeeValue(gasFee, exchangeRate)} + + Total Fees + + {renderFeeValue(BigNumber(gasFee).plus(BigNumber(lockFee)).toString(), exchangeRate)} + - - - - 6 months prepaid fee + {isOpenFees && ( + <> + + + + {label} ( + + Pay by Owner Account + + ) + + + + {renderFeeValue(gasFee, exchangeRate)} + + + + + + 6 months prepaid fee + + + + {renderFeeValue(lockFee, exchangeRate)} + + + + Available balance: {renderBalanceNumber(availableBalance || '0')} ( + {renderUsd(availableBalance || '0', exchangeRate)}) - - - {renderFeeValue(lockFee, exchangeRate)} - - - - Available balance: {renderBalanceNumber(availableBalance || '0')} ( - {renderUsd(availableBalance || '0', exchangeRate)}) - + + )} ); diff --git a/apps/dcellar-web-ui/src/modules/file/utils/index.tsx b/apps/dcellar-web-ui/src/modules/file/utils/index.tsx index c0ea9cd8..79ae512c 100644 --- a/apps/dcellar-web-ui/src/modules/file/utils/index.tsx +++ b/apps/dcellar-web-ui/src/modules/file/utils/index.tsx @@ -15,6 +15,8 @@ import { getClient } from '@/base/client'; import { generateGetObjectOptions } from './generateGetObjectOptions'; import { ChainVisibilityEnum } from '../type'; import { SpItem } from '@/store/slices/sp'; +import BigNumber from 'bignumber.js'; +import { GasFee } from '@/modules/buckets/List/components/GasFee'; const formatBytes = (bytes: number | string, isFloor = false) => { if (typeof bytes === 'string') { @@ -44,7 +46,7 @@ const renderFeeValue = (bnbValue: string, exchangeRate: number | string) => { if (!bnbValue || Number(bnbValue) < 0) { return '--'; } - + return `${renderBnb(bnbValue)} BNB (${renderUsd(bnbValue, exchangeRate)})`; }; const renderPrelockedFeeValue = (bnbValue: string, exchangeRate: number | string) => { @@ -319,6 +321,69 @@ const truncateFileName = (fileName: string) => { )}...${fileNameWithoutExtension.slice(-4)}${fileExtension}`; }; +const renderPaymentInsufficientBalance = ({ + gasFee, + lockFee, + payGasFeeBalance, + payLockFeeBalance, + ownerAccount, + payAccount, + gaOptions, +}:{ + gasFee: string, + lockFee: string, + payGasFeeBalance: string, + payLockFeeBalance: string, + ownerAccount: string, + payAccount: string, + gaOptions?: { gaClickName: string; gaShowName: string }, +}) => { + if (!gasFee || Number(gasFee) < 0 || !lockFee || Number(lockFee) < 0) return <>; + const items = []; + const isOwnerAccount = ownerAccount === payAccount; + if (isOwnerAccount) { + if (!BigNumber(payGasFeeBalance).gt(BigNumber(gasFee)) + && BigNumber(payGasFeeBalance).minus(BigNumber(gasFee)).plus(BigNumber(payLockFeeBalance)).gt(BigNumber(lockFee))) { + items.push({ + link: InternalRoutePaths.transfer_in, + text: 'Transfer in', + }); + } + } else { + if (!BigNumber(payGasFeeBalance).gt(BigNumber(gasFee))) { + items.push({ + link: InternalRoutePaths.transfer_in, + text: 'Transfer in', + }); + } + if (!BigNumber(payLockFeeBalance).gt(BigNumber(lockFee))) { + items.push({ + link: InternalRoutePaths.send, + text: 'Deposit', + }); + } + } + if (items.length === 0) return <>; + + return ( + <> + {items.map((item, index) => ( + + Insufficient balance.  + + + Transfer in + + + + ))} + + ); +}; export { formatBytes, getObjectInfo, @@ -337,4 +402,5 @@ export { truncateFileName, renderPrelockedFeeValue, getBuiltInLink, + renderPaymentInsufficientBalance, }; diff --git a/apps/dcellar-web-ui/src/modules/object/components/CreateFolder.tsx b/apps/dcellar-web-ui/src/modules/object/components/CreateFolder.tsx index 624e0a91..179b6dca 100644 --- a/apps/dcellar-web-ui/src/modules/object/components/CreateFolder.tsx +++ b/apps/dcellar-web-ui/src/modules/object/components/CreateFolder.tsx @@ -69,8 +69,7 @@ interface modalProps { export const CreateFolder = memo(function CreateFolderDrawer({ refetch }) { const dispatch = useAppDispatch(); const { connector } = useAccount(); - const { isOpen: isOpenFees, onToggle: onToggleFees } = useDisclosure(); - const exchangeRate = useAppSelector(selectBnbPrice); + const { preLockFeeObjects } = useAppSelector((root) => root.global); const checksumWorkerApi = useChecksumApi(); const { primarySpInfo } = useAppSelector((root) => root.sp); @@ -116,7 +115,7 @@ export const CreateFolder = memo(function CreateFolderDrawer({ refet const loadingFee = useMemo(() => { return isEmpty(preLockFeeObjects); }, [preLockFeeObjects]); - const preLockFee = calPreLockFee({ + const preLockFee = !isEmpty(preLockFeeObject) && calPreLockFee({ size: 0, primarySpAddress: primarySp.operatorAddress, preLockFeeObject: preLockFeeObject, @@ -370,25 +369,6 @@ export const CreateFolder = memo(function CreateFolderDrawer({ refet - - Total Fees - - {renderFeeValue(preLockFee.toString(), exchangeRate)} - - - {lackGasFee && ( diff --git a/apps/dcellar-web-ui/src/modules/upload/SimulateFee.tsx b/apps/dcellar-web-ui/src/modules/upload/SimulateFee.tsx index cd651b12..85d77a9f 100644 --- a/apps/dcellar-web-ui/src/modules/upload/SimulateFee.tsx +++ b/apps/dcellar-web-ui/src/modules/upload/SimulateFee.tsx @@ -2,7 +2,7 @@ import { Tips } from '@/components/common/Tips'; import { renderBalanceNumber, renderFeeValue, - renderInsufficientBalance, + renderPaymentInsufficientBalance, renderPrelockedFeeValue, } from '@/modules/file/utils'; import { useAppDispatch, useAppSelector } from '@/store'; @@ -18,21 +18,23 @@ import { WaitFile, setupPreLockFeeObjects, setupTmpAvailableBalance } from '@/st import { isEmpty } from 'lodash-es'; import { calPreLockFee } from '@/utils/sp'; import { MenuCloseIcon } from '@totejs/icons'; -import { setEditUpload } from '@/store/slices/object'; +import { selectPayLockFeeAccount, setEditUpload } from '@/store/slices/object'; import BigNumber from 'bignumber.js'; import { DECIMAL_NUMBER } from '../wallet/constants'; export const Fee = () => { const dispatch = useAppDispatch(); const { loginAccount } = useAppSelector((root) => root.persist); - // TODO根据payment account进行不同预算 - const { bankBalance: availableBalance } = useAppSelector((root) => root.accounts); const { gasObjects = {} } = useAppSelector((root) => root.global.gasHub); const { gasFee: singleTxGasFee } = gasObjects?.[MsgCreateObjectTypeUrl] || {}; const { price: exchangeRate } = useAppSelector((root) => root.global.bnb); const { waitQueue, preLockFeeObjects } = useAppSelector((root) => root.global); const { bucketName } = useAppSelector((root) => root.object); const { primarySpInfo } = useAppSelector((root) => root.sp); + const payLockFeeAccount = useAppSelector(selectPayLockFeeAccount); + const { bankBalance } = useAppSelector((root) => root.accounts); + const isOwnerAccount = payLockFeeAccount.address === loginAccount; + const availableBalance = isOwnerAccount ? BigNumber(bankBalance).plus(payLockFeeAccount.staticBalance).toString() : payLockFeeAccount.staticBalance; const isChecking = waitQueue.some((item) => item.status === 'CHECK') || isEmpty(preLockFeeObjects); const { isOpen, onToggle } = useDisclosure(); @@ -85,6 +87,16 @@ export const Fee = () => { .times(singleTxGasFee) .plus(BigNumber(createTmpAccountGasFee).toString(DECIMAL_NUMBER)) .toString(DECIMAL_NUMBER); + const isBalanceAvailable = useMemo(() => { + if (isOwnerAccount) { + return BigNumber(bankBalance) + .minus(BigNumber(gasFee)) + .isPositive() + && BigNumber(bankBalance).minus(BigNumber(gasFee)).plus(payLockFeeAccount.staticBalance).minus(BigNumber(lockFee || 0)).isPositive(); + } else { + return BigNumber(bankBalance).minus(BigNumber(gasFee)).isPositive() && BigNumber(payLockFeeAccount.staticBalance).minus(BigNumber(lockFee || 0)).isPositive(); + } + }, [bankBalance, gasFee, isOwnerAccount, lockFee, payLockFeeAccount.staticBalance]); useEffect(() => { if (gasFee && lockFee) { @@ -93,14 +105,11 @@ export const Fee = () => { gasFee: BigNumber(gasFee).toString(DECIMAL_NUMBER), preLockFee: BigNumber(lockFee).toString(DECIMAL_NUMBER), totalFee: BigNumber(gasFee).plus(BigNumber(lockFee)).toString(DECIMAL_NUMBER), - isBalanceAvailable: BigNumber(availableBalance) - .minus(BigNumber(gasFee)) - .minus(BigNumber(lockFee)) - .isPositive(), + isBalanceAvailable: isBalanceAvailable }), ); } - }, [availableBalance, dispatch, gasFee, lockFee]); + }, [availableBalance, dispatch, gasFee, isBalanceAvailable, lockFee]); useMount(() => { dispatch(setupTmpAvailableBalance(loginAccount)); }); @@ -201,10 +210,17 @@ export const Fee = () => { {/*todo correct the error showing logics*/} {!isChecking && - renderInsufficientBalance(gasFee + '', lockFee + '', availableBalance || '0', { + renderPaymentInsufficientBalance({ + gasFee: gasFee + '', + lockFee: lockFee + '', + payGasFeeBalance: bankBalance, + payLockFeeBalance: payLockFeeAccount.staticBalance, + payAccount: payLockFeeAccount.address, + ownerAccount: loginAccount, + gaOptions: { gaShowName: 'dc.file.upload_modal.transferin.show', gaClickName: 'dc.file.upload_modal.transferin.click', - })} + }})} Available balance: {renderBalanceNumber(availableBalance || '0')} diff --git a/apps/dcellar-web-ui/src/modules/upload/UploadObjects.tsx b/apps/dcellar-web-ui/src/modules/upload/UploadObjects.tsx index e89065e2..5bf5a91a 100644 --- a/apps/dcellar-web-ui/src/modules/upload/UploadObjects.tsx +++ b/apps/dcellar-web-ui/src/modules/upload/UploadObjects.tsx @@ -92,7 +92,6 @@ export const UploadObjects = memo(function UploadObjects() { const { tabOptions, activeKey, setActiveKey } = useUploadTab(); const { PaymentAddress } = bucketInfo[bucketName] || {}; - console.log('bucketInfo[bucketName]', bucketInfo[bucketName]); const onClose = () => { dispatch(setEditUploadStatus(false)); dispatch(setEditUpload({} as TEditUpload)); diff --git a/apps/dcellar-web-ui/src/store/slices/global.ts b/apps/dcellar-web-ui/src/store/slices/global.ts index 536bf83c..029203fd 100644 --- a/apps/dcellar-web-ui/src/store/slices/global.ts +++ b/apps/dcellar-web-ui/src/store/slices/global.ts @@ -430,7 +430,6 @@ export const setupPreLockFeeObjects = const client = await getClient(); const now = Math.floor(getUtcZeroTimestamp()/1000); const globalSpStoragePrice = await client.sp.getQueryGlobalSpStorePriceByTime({ timestamp: Long.fromNumber(now) }); - console.log('globalSpStoragePrice', globalSpStoragePrice) const { params: storageParams } = await client.storage.params(); const { minChargeSize = new Long(0), diff --git a/apps/dcellar-web-ui/src/store/slices/object.ts b/apps/dcellar-web-ui/src/store/slices/object.ts index f3c13900..903d9dda 100644 --- a/apps/dcellar-web-ui/src/store/slices/object.ts +++ b/apps/dcellar-web-ui/src/store/slices/object.ts @@ -362,6 +362,13 @@ export const selectPathCurrent = (root: AppState) => { return currentPage[path] || 0; }; +export const selectPayLockFeeAccount = (root: AppState) => { + const { bucketInfo } = root.bucket; + const { bucketName } = root.object; + const { PaymentAddress } = bucketInfo[bucketName] || {}; + const { accountsInfo } = root.accounts; + return accountsInfo[PaymentAddress]; +} const defaultObjectList = Array(); export const selectObjectList = (root: AppState) => { const { objects, path } = root.object;