From 4a09715a0fd851088f3259ad00244299a3e4ef57 Mon Sep 17 00:00:00 2001 From: devinxl Date: Tue, 8 Aug 2023 10:11:23 +0800 Subject: [PATCH 1/2] fix(dcellar-web-ui): upload error and add tmp account fee --- .../components/layout/Header/GlobalTasks.tsx | 7 ++++--- apps/dcellar-web-ui/src/facade/account.ts | 1 + .../src/modules/upload/SimulateFee.tsx | 15 ++++++++++----- .../src/modules/upload/UploadObjects.tsx | 1 - apps/dcellar-web-ui/src/store/slices/global.ts | 14 ++++++++++++-- apps/dcellar-web-ui/src/utils/common/index.tsx | 17 +++++++++++++++++ 6 files changed, 44 insertions(+), 11 deletions(-) create mode 100644 apps/dcellar-web-ui/src/utils/common/index.tsx diff --git a/apps/dcellar-web-ui/src/components/layout/Header/GlobalTasks.tsx b/apps/dcellar-web-ui/src/components/layout/Header/GlobalTasks.tsx index 8859ed05..f77ed80e 100644 --- a/apps/dcellar-web-ui/src/components/layout/Header/GlobalTasks.tsx +++ b/apps/dcellar-web-ui/src/components/layout/Header/GlobalTasks.tsx @@ -24,6 +24,7 @@ import { genCreateObjectTx } from '@/modules/file/utils/genCreateObjectTx'; import { resolve } from '@/facade/common'; import { broadcastFault, commonFault, createTxFault, simulateFault } from '@/facade/error'; import { isEmpty } from 'lodash-es'; +import { parseErrorXml } from '@/utils/common'; interface GlobalTasksProps {} @@ -159,12 +160,12 @@ export const GlobalTasks = memo(function GlobalTasks() { 'X-Gnfd-User-Address': headers.get('X-Gnfd-User-Address'), 'X-Gnfd-App-Domain': headers.get('X-Gnfd-App-Domain'), }, - }).catch(e => { - console.log('upload error', e); + }).catch(async (e: Response) => { + const {code, message} = await parseErrorXml(e) dispatch(updateUploadTaskMsg({ account: loginAccount, id: task.id, - msg: e?.message || 'Upload error', + msg: message || 'Upload error', })); }) }; diff --git a/apps/dcellar-web-ui/src/facade/account.ts b/apps/dcellar-web-ui/src/facade/account.ts index b4181370..72345e8d 100644 --- a/apps/dcellar-web-ui/src/facade/account.ts +++ b/apps/dcellar-web-ui/src/facade/account.ts @@ -51,6 +51,7 @@ export const createTmpAccount = async ({ // 2. allow temporary account to submit specified tx and amount const client = await getClient(); + // MsgGrantAllowanceTypeUrl const grantAllowanceTx = await client.feegrant.grantAllowance({ granter: address, grantee: wallet.address, diff --git a/apps/dcellar-web-ui/src/modules/upload/SimulateFee.tsx b/apps/dcellar-web-ui/src/modules/upload/SimulateFee.tsx index 7ac7743c..55aae2cf 100644 --- a/apps/dcellar-web-ui/src/modules/upload/SimulateFee.tsx +++ b/apps/dcellar-web-ui/src/modules/upload/SimulateFee.tsx @@ -6,15 +6,14 @@ import { renderPrelockedFeeValue, } from '@/modules/file/utils'; import { useAppDispatch, useAppSelector } from '@/store'; -import { MsgCreateObjectTypeUrl } from '@bnb-chain/greenfield-chain-sdk'; -import { Box, Flex, Slide, Text, useDisclosure, Link } from '@totejs/uikit'; +import { MsgCreateObjectTypeUrl, MsgGrantAllowanceTypeUrl, MsgPutPolicyTypeUrl } from '@bnb-chain/greenfield-chain-sdk'; +import { Box, Flex, Text, useDisclosure, Link } from '@totejs/uikit'; import React, { useEffect, useMemo } from 'react'; import { useAsyncEffect, useMount } from 'ahooks'; import { WaitFile, setupPreLockFeeObjects, setupTmpAvailableBalance } from '@/store/slices/global'; import { isEmpty } from 'lodash-es'; import { calPreLockFee } from '@/utils/sp'; import { MenuCloseIcon } from '@totejs/icons'; -import { useUpdateEffect } from 'react-use'; import { setEditUpload } from '@/store/slices/object'; import BigNumber from 'bignumber.js'; import { DECIMAL_NUMBER } from '../wallet/constants'; @@ -39,8 +38,14 @@ export const Fee = () => { } }, [primarySp?.operatorAddress]); - const lockFee = useMemo(() => { + const createTmpAccountGasFee = useMemo(() => { + const grantAllowTxFee = BigNumber(gasObjects[MsgGrantAllowanceTypeUrl].gasFee).plus(BigNumber(gasObjects[MsgGrantAllowanceTypeUrl].perItemFee).times(1)); + const putPolicyTxFee = BigNumber(gasObjects[MsgPutPolicyTypeUrl].gasFee); + + return grantAllowTxFee.plus(putPolicyTxFee).toString(DECIMAL_NUMBER); + }, [gasObjects]); + const lockFee = useMemo(() => { if (!primarySp?.operatorAddress) return; const preLockFeeObject = preLockFeeObjects[primarySp.operatorAddress]; if (isEmpty(preLockFeeObject) || isChecking) { @@ -63,7 +68,7 @@ export const Fee = () => { const gasFee = isChecking ? -1 - : waitQueue.filter((item: WaitFile) => item.status !== 'ERROR').length * singleTxGasFee; + : BigNumber(waitQueue.filter((item: WaitFile) => item.status !== 'ERROR').length).times(singleTxGasFee).plus(BigNumber(createTmpAccountGasFee).toString(DECIMAL_NUMBER)).toString(DECIMAL_NUMBER); useEffect(() => { if (gasFee && lockFee) { diff --git a/apps/dcellar-web-ui/src/modules/upload/UploadObjects.tsx b/apps/dcellar-web-ui/src/modules/upload/UploadObjects.tsx index 1d63e260..bcee45ec 100644 --- a/apps/dcellar-web-ui/src/modules/upload/UploadObjects.tsx +++ b/apps/dcellar-web-ui/src/modules/upload/UploadObjects.tsx @@ -207,7 +207,6 @@ export const UploadObjects = memo(function UploadObjects() { }, [preLockFeeObjects, selectedFiles]); const checkedQueue = selectedFiles.filter((item) => item.status === 'WAIT'); - // console.log(loading, creating, !checkedQueue?.length, !editUpload.isBalanceAvailable, editUpload); return ( diff --git a/apps/dcellar-web-ui/src/store/slices/global.ts b/apps/dcellar-web-ui/src/store/slices/global.ts index 8c92855d..cae2f20d 100644 --- a/apps/dcellar-web-ui/src/store/slices/global.ts +++ b/apps/dcellar-web-ui/src/store/slices/global.ts @@ -9,12 +9,14 @@ import { getSpOffChainData } from '@/store/slices/persist'; import { defaultBalance } from '@/store/slices/balance'; import Long from 'long'; import { VisibilityType } from '@bnb-chain/greenfield-cosmos-types/greenfield/storage/common'; +import { MsgGrantAllowanceTypeUrl } from '@bnb-chain/greenfield-chain-sdk'; export type TGasList = { [msgTypeUrl: string]: { gasLimit: number; msgTypeUrl: string; gasFee: number; + perItemFee: number; }; }; @@ -201,12 +203,20 @@ export const globalSlice = createSlice({ const { gasPrice } = state.gasHub; const gasObjects = keyBy( payload.msgGasParams.map((item) => { - const gasLimit = item.fixedType?.fixedGas.low || 0; - const gasFee = gasPrice * gasLimit; + let gasLimit = item.fixedType?.fixedGas.low || 0; + let gasFee = gasPrice * gasLimit; + let perItemFee = 0; + if (item.msgTypeUrl === MsgGrantAllowanceTypeUrl) { + gasLimit = item.grantAllowanceType?.fixedGas.low || 0; + gasFee = gasPrice * gasLimit; + perItemFee = (item.grantAllowanceType?.gasPerItem.low || 0) * gasPrice; + } + return { msgTypeUrl: item.msgTypeUrl, gasLimit, gasFee, + perItemFee, }; }), 'msgTypeUrl', diff --git a/apps/dcellar-web-ui/src/utils/common/index.tsx b/apps/dcellar-web-ui/src/utils/common/index.tsx new file mode 100644 index 00000000..7b20adbe --- /dev/null +++ b/apps/dcellar-web-ui/src/utils/common/index.tsx @@ -0,0 +1,17 @@ +export const parseErrorXml = async (result: Response) => { + try { + const xmlText = await result.text(); + const xml = await new window.DOMParser().parseFromString(xmlText, 'text/xml'); + const code = (xml as XMLDocument).getElementsByTagName('Code')[0].textContent; + const message = (xml as XMLDocument).getElementsByTagName('Message')[0].textContent; + return { + code, + message, + }; + } catch { + return { + code: null, + message: null, + }; + } +}; \ No newline at end of file From 7798de14f1583034003ef22432d977d6afb3b62c Mon Sep 17 00:00:00 2001 From: devinxl Date: Wed, 9 Aug 2023 17:58:48 +0800 Subject: [PATCH 2/2] fix(dcellar-web-ui): recover sealing status to table --- .../src/components/common/DCTable/index.tsx | 27 ++++++++++++++----- .../src/modules/upload/UploadObjects.tsx | 20 +++++++------- 2 files changed, 32 insertions(+), 15 deletions(-) diff --git a/apps/dcellar-web-ui/src/components/common/DCTable/index.tsx b/apps/dcellar-web-ui/src/components/common/DCTable/index.tsx index 65704fe7..824efabd 100644 --- a/apps/dcellar-web-ui/src/components/common/DCTable/index.tsx +++ b/apps/dcellar-web-ui/src/components/common/DCTable/index.tsx @@ -70,12 +70,27 @@ export const SealLoading = () => { } `; return ( - + + + + + + Sealing... + + ); }; diff --git a/apps/dcellar-web-ui/src/modules/upload/UploadObjects.tsx b/apps/dcellar-web-ui/src/modules/upload/UploadObjects.tsx index bcee45ec..a8b6d0ec 100644 --- a/apps/dcellar-web-ui/src/modules/upload/UploadObjects.tsx +++ b/apps/dcellar-web-ui/src/modules/upload/UploadObjects.tsx @@ -120,16 +120,18 @@ export const UploadObjects = memo(function UploadObjects() { if (file.name.includes('//')) { return E_OBJECT_NAME_CONTAINS_SLASH; } - const objectListNames = objectList.map((item) => item.name); - const uploadingNames = (uploadQueue?.[loginAccount] || []) + // Validation only works to data within the current path. + const objectListObjectNames = objectList.map((item) => bucketName + '/' + item.objectName); + // Avoid add same file to the uploading queue. + const uploadingObjectNames = (uploadQueue?.[loginAccount] || []) + .filter((item) => ['WAIT', 'HASH', 'READY', 'UPLOAD', 'SEAL'].includes(item.status)) .map((item) => { - const curPrefix = [bucketName, ...folders].join('/'); - const filePrefix = [item.bucketName, ...item.prefixFolders].join('/'); - return curPrefix === filePrefix ? item.file.name : ''; - }) - .filter((item) => item); - const isExistObjectList = objectListNames.includes(file.name); - const isExistUploadList = uploadingNames.includes(file.name); + return [item.bucketName, ...item.prefixFolders, item.file.name].join('/'); + }); + const fullObjectName = [path, file.name].join('/'); + const isExistObjectList = objectListObjectNames.includes(fullObjectName); + const isExistUploadList = uploadingObjectNames.includes(fullObjectName); + if (isExistObjectList || isExistUploadList) { return E_OBJECT_NAME_EXISTS; }