-
+ { tx.translation ?
+ :
+
+ }
diff --git a/ui/txs/TxsTableItem.tsx b/ui/txs/TxsTableItem.tsx
index b1a4121cf5..216003bfeb 100644
--- a/ui/txs/TxsTableItem.tsx
+++ b/ui/txs/TxsTableItem.tsx
@@ -21,6 +21,7 @@ import TxFeeStability from 'ui/shared/tx/TxFeeStability';
import TxWatchListTags from 'ui/shared/tx/TxWatchListTags';
import TxAdditionalInfo from 'ui/txs/TxAdditionalInfo';
+import TxTranslationType from './TxTranslationType';
import TxType from './TxType';
type Props = {
@@ -62,7 +63,10 @@ const TxsTableItem = ({ tx, showBlockInfo, currentAddress, enableTimeIncrement,
-
+ { tx.translation ?
+ :
+
+ }
diff --git a/ui/txs/noves/useDescribeTxs.tsx b/ui/txs/noves/useDescribeTxs.tsx
new file mode 100644
index 0000000000..d9081492cd
--- /dev/null
+++ b/ui/txs/noves/useDescribeTxs.tsx
@@ -0,0 +1,89 @@
+import { useQuery } from '@tanstack/react-query';
+import _ from 'lodash';
+import React from 'react';
+
+import type { NovesDescribeTxsResponse } from 'types/api/noves';
+import type { Transaction } from 'types/api/transaction';
+
+import config from 'configs/app';
+import useApiFetch from 'lib/api/useApiFetch';
+
+const feature = config.features.txInterpretation;
+
+const translateEnabled = feature.isEnabled && feature.provider === 'noves';
+
+export default function useDescribeTxs(items: Array | undefined, viewAsAccountAddress: string | undefined, isPlaceholderData: boolean) {
+ const apiFetch = useApiFetch();
+
+ const txsHash = _.uniq(items?.map(i => i.hash));
+ const txChunks = _.chunk(txsHash, 10);
+
+ const queryKey = {
+ viewAsAccountAddress,
+ firstHash: txsHash[0] || '',
+ lastHash: txsHash[txsHash.length - 1] || '',
+ };
+
+ const describeQuery = useQuery({
+ queryKey: [ 'noves_describe_txs', queryKey ],
+ queryFn: async() => {
+ const queries = txChunks.map((hashes) => {
+ if (hashes.length === 0) {
+ return Promise.resolve([]);
+ }
+
+ return apiFetch('noves_describe_txs', {
+ queryParams: {
+ viewAsAccountAddress,
+ hashes,
+ },
+ }) as Promise;
+ });
+
+ return Promise.all(queries);
+ },
+ select: (data) => {
+ return data.flat();
+ },
+ enabled: translateEnabled && !isPlaceholderData,
+ });
+
+ const itemsWithTranslation = React.useMemo(() => items?.map(tx => {
+ const queryData = describeQuery.data;
+ const isLoading = describeQuery.isLoading;
+
+ if (isLoading) {
+ return {
+ ...tx,
+ translation: {
+ isLoading,
+ },
+ };
+ }
+
+ if (!queryData || !translateEnabled) {
+ return tx;
+ }
+
+ const query = queryData.find(data => data.txHash.toLowerCase() === tx.hash.toLowerCase());
+
+ if (query) {
+ return {
+ ...tx,
+ translation: {
+ data: query,
+ isLoading: false,
+ },
+ };
+ }
+
+ return tx;
+ }), [ items, describeQuery ]);
+
+ if (!translateEnabled || isPlaceholderData) {
+ return items;
+ }
+
+ // return same "items" array of Transaction with a new "translation" field.
+ return itemsWithTranslation;
+}
diff --git a/ui/txs/noves/utils.ts b/ui/txs/noves/utils.ts
new file mode 100644
index 0000000000..c5a986b66a
--- /dev/null
+++ b/ui/txs/noves/utils.ts
@@ -0,0 +1,11 @@
+export function camelCaseToSentence(camelCaseString: string | undefined) {
+ if (!camelCaseString) {
+ return '';
+ }
+
+ let sentence = camelCaseString.replace(/([a-z])([A-Z])/g, '$1 $2');
+ sentence = sentence.replace(/([A-Z])([A-Z][a-z])/g, '$1 $2');
+ sentence = sentence.charAt(0).toUpperCase() + sentence.slice(1);
+
+ return sentence;
+}
|