diff --git a/system-contract-dapp-playground/__tests__/hedera/index.test.ts b/system-contract-dapp-playground/__tests__/hedera/index.test.ts index bc51d001f..0e0f7cf62 100644 --- a/system-contract-dapp-playground/__tests__/hedera/index.test.ts +++ b/system-contract-dapp-playground/__tests__/hedera/index.test.ts @@ -22,6 +22,7 @@ import { ContractFactory } from 'ethers'; import { deploySmartContract } from '@/api/hedera'; import { HederaSmartContractResult } from '@/types/common'; import { HEDERA_SMART_CONTRACTS_ASSETS } from '@/utils/common/constants'; +import { MOCK_CONTRACT_ID, MOCK_TX_HASH } from '../utils/common/constants'; // Mock ethers jest.mock('ethers', () => { @@ -53,13 +54,15 @@ describe('deploySmartContract', () => { it('should deploy the smart contract', async () => { // prepare states const deployParams = [100]; - const contractAddr = '0x8f18eCFeC4dB88ACe84dD1c8d11eBFeDd9274324'; const contractABI = HEDERA_SMART_CONTRACTS_ASSETS.EXCHANGE_RATE.contractABI; const contractBytecode = HEDERA_SMART_CONTRACTS_ASSETS.EXCHANGE_RATE.contractBytecode; // mock contractDeployTx const mockContractDeployTx = { - getAddress: jest.fn().mockResolvedValue(contractAddr), + getAddress: jest.fn().mockResolvedValue(MOCK_CONTRACT_ID), + deploymentTransaction: jest.fn().mockResolvedValue({ + hash: MOCK_TX_HASH, + }), }; // mock contract @@ -80,7 +83,7 @@ describe('deploySmartContract', () => { // validation expect(result.err).toBeNull; expect(deploySmartContract).toBeCalled; - expect(result.contractAddress).toEqual(contractAddr); + expect(result.contractAddress).toEqual(MOCK_CONTRACT_ID); expect(mockContractDeployTx.getAddress).toHaveBeenCalled(); expect(mockContract.deploy).toHaveBeenCalledWith(...deployParams, { gasLimit: 4_000_000 }); }); diff --git a/system-contract-dapp-playground/src/api/cookies/index.ts b/system-contract-dapp-playground/src/api/cookies/index.ts index dc004d0ff..cab304c0a 100644 --- a/system-contract-dapp-playground/src/api/cookies/index.ts +++ b/system-contract-dapp-playground/src/api/cookies/index.ts @@ -110,6 +110,15 @@ export const getInfoFromCookies = ( } }; +/** + * @dev remove specific cookie + * + * @param key: string + */ +export const removeCookieAt = (key: string) => { + Cookies.remove(key); +}; + /** * @dev clear account information stored in cookies */ diff --git a/system-contract-dapp-playground/src/api/hedera/index.ts b/system-contract-dapp-playground/src/api/hedera/index.ts index 568b72fda..f9349c780 100644 --- a/system-contract-dapp-playground/src/api/hedera/index.ts +++ b/system-contract-dapp-playground/src/api/hedera/index.ts @@ -20,7 +20,9 @@ import { ContractFactory } from 'ethers'; import { getWalletProvider } from '../wallet'; +import { TransactionResult } from '@/types/contract-interactions/HTS'; import { ContractABI, HederaSmartContractResult } from '@/types/common'; +import { HEDERA_TRANSACTION_RESULT_STORAGE_KEYS } from '@/utils/common/constants'; /** * @dev deploys smart contract to Hedera network @@ -38,13 +40,18 @@ export const deploySmartContract = async ( contractBytecode: string, params: any[] ): Promise => { - // get wallet provider + // states + const transactionResultStorageKey = HEDERA_TRANSACTION_RESULT_STORAGE_KEYS['CONTRACT-CREATE']; + + // get contract create transactions from localStorage + const cachedCreateTransactions = localStorage.getItem(transactionResultStorageKey); + const contractCreateTransactions = cachedCreateTransactions ? JSON.parse(cachedCreateTransactions) : []; + + // get signer const walletProvider = getWalletProvider(); if (walletProvider.err || !walletProvider.walletProvider) { return { err: walletProvider.err }; } - - // get signer const walletSigner = await walletProvider.walletProvider.getSigner(); // Deploy smart contract @@ -53,11 +60,7 @@ export const deploySmartContract = async ( const gasLimit = 4_000_000; // get contract from contract factory - const contract = new ContractFactory( - JSON.stringify(contractABI), - contractBytecode, - walletSigner - ); + const contract = new ContractFactory(JSON.stringify(contractABI), contractBytecode, walletSigner); // execute deploy transaction const contractDeployTx = await contract.deploy(...params, { @@ -66,6 +69,23 @@ export const deploySmartContract = async ( // get contractAddress const contractAddress = await contractDeployTx.getAddress(); + + // retrieve transaction receipt + const txReceipt = contractDeployTx.deploymentTransaction(); + + // prepare create transaction result + if (txReceipt) { + const createTransactionResult: TransactionResult = { + status: 'success', + transactionTimeStamp: Date.now(), + txHash: txReceipt.hash as string, + transactionType: 'CONTRACT-CREATE', + sessionedContractAddress: contractAddress, + }; + contractCreateTransactions.push(createTransactionResult); + localStorage.setItem(transactionResultStorageKey, JSON.stringify(contractCreateTransactions)); + } + return { contractAddress }; } catch (err) { console.error(err); diff --git a/system-contract-dapp-playground/src/api/localStorage/index.ts b/system-contract-dapp-playground/src/api/localStorage/index.ts index 531b38a3a..bf76d0e28 100644 --- a/system-contract-dapp-playground/src/api/localStorage/index.ts +++ b/system-contract-dapp-playground/src/api/localStorage/index.ts @@ -61,9 +61,16 @@ export const getArrayTypedValuesFromLocalStorage = (key: string) => { }; /** - * @dev clear all HEDERA transaction results cached in localStorage + * @dev clear HEDERA transaction results cached in localStorage + * + * @param contractKey?: string + * + * @param readonly?: boolean */ -export const clearTransactionCache = () => { +export const clearCachedTransactions = (contractKey?: string, readonly?: boolean) => { + // prepare key + const targetKey = contractKey ? contractKey : OFFCIAL_NETWORK_NAME; + // loop through localStorage items if (localStorage) { for (let i = 0; i < localStorage.length; i++) { @@ -71,9 +78,16 @@ export const clearTransactionCache = () => { const key = localStorage.key(i); // remove items that have keys start with HEDERA - if (key?.startsWith(OFFCIAL_NETWORK_NAME)) { - localStorage.removeItem(key); - i--; + if (key?.includes(targetKey)) { + if (readonly) { + if (key?.includes('READONLY')) { + localStorage.removeItem(key); + i--; + } + } else { + localStorage.removeItem(key); + i--; + } } } } diff --git a/system-contract-dapp-playground/src/components/common/ConfirmModal.tsx b/system-contract-dapp-playground/src/components/common/ConfirmModal.tsx new file mode 100644 index 000000000..02bac9032 --- /dev/null +++ b/system-contract-dapp-playground/src/components/common/ConfirmModal.tsx @@ -0,0 +1,74 @@ +/*- + * + * Hedera Smart Contracts + * + * Copyright (C) 2023 Hedera Hashgraph, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +import { + Modal, + ModalOverlay, + ModalContent, + ModalHeader, + ModalCloseButton, + ModalBody, + ModalFooter, +} from '@chakra-ui/react'; + +interface PageProps { + isOpen: boolean; + modalBody: any; + onClose: () => void; + modalHeader: string; + handleAcknowledge: any; +} + +const ConfirmModal = ({ + isOpen, + modalBody, + onClose, + modalHeader, + handleAcknowledge, +}: PageProps) => { + return ( + + + + {modalHeader} + + + {/* break line */} +
+ + {modalBody} + + + + +
+
+ ); +}; + +export default ConfirmModal; diff --git a/system-contract-dapp-playground/src/components/contract-interaction/erc/erc-20/methods/mint/index.tsx b/system-contract-dapp-playground/src/components/contract-interaction/erc/erc-20/methods/mint/index.tsx index 94a9060b3..c99747e7e 100644 --- a/system-contract-dapp-playground/src/components/contract-interaction/erc/erc-20/methods/mint/index.tsx +++ b/system-contract-dapp-playground/src/components/contract-interaction/erc/erc-20/methods/mint/index.tsx @@ -18,6 +18,7 @@ * */ +import Cookies from 'js-cookie'; import { useToast } from '@chakra-ui/react'; import { useEffect, useState } from 'react'; import { Contract, isAddress } from 'ethers'; @@ -25,8 +26,8 @@ import { erc20Mint } from '@/api/hedera/erc20-interactions'; import { CommonErrorToast } from '@/components/toast/CommonToast'; import MultiLineMethod from '@/components/common/MultiLineMethod'; import { TransactionResult } from '@/types/contract-interactions/HTS'; -import { HEDERA_TRANSACTION_RESULT_STORAGE_KEYS } from '@/utils/common/constants'; import { mintParamFields } from '@/utils/contract-interactions/erc/erc20/constant'; +import { CONTRACT_NAMES, HEDERA_TRANSACTION_RESULT_STORAGE_KEYS } from '@/utils/common/constants'; import { handleAPIErrors } from '@/components/contract-interaction/hts/shared/methods/handleAPIErrors'; import { useUpdateTransactionResultsToLocalStorage } from '@/components/contract-interaction/hts/shared/hooks/useUpdateLocalStorage'; @@ -38,6 +39,7 @@ const Mint = ({ baseContract }: PageProps) => { const toaster = useToast(); const [isLoading, setIsLoading] = useState(false); const [isSuccessful, setIsSuccessful] = useState(false); + const currentContractAddress = Cookies.get(CONTRACT_NAMES.ERC20) as string; const [transactionResults, setTransactionResults] = useState([]); const transactionResultStorageKey = HEDERA_TRANSACTION_RESULT_STORAGE_KEYS['ERC20-RESULT']['TOKEN-MINT']; const [mintParams, setMintParams] = useState({ @@ -74,6 +76,7 @@ const Mint = ({ baseContract }: PageProps) => { setTransactionResults, transactionHash: txHash, transactionType: 'ERC20-MINT', + sessionedContractAddress: currentContractAddress, }); return; } else { @@ -85,6 +88,7 @@ const Mint = ({ baseContract }: PageProps) => { txHash: txHash as string, transactionType: 'ERC20-MINT', transactionTimeStamp: Date.now(), + sessionedContractAddress: currentContractAddress, }, ]); diff --git a/system-contract-dapp-playground/src/components/contract-interaction/erc/erc-20/methods/token-permission/index.tsx b/system-contract-dapp-playground/src/components/contract-interaction/erc/erc-20/methods/token-permission/index.tsx index 045bc6e00..4cd89352a 100644 --- a/system-contract-dapp-playground/src/components/contract-interaction/erc/erc-20/methods/token-permission/index.tsx +++ b/system-contract-dapp-playground/src/components/contract-interaction/erc/erc-20/methods/token-permission/index.tsx @@ -18,6 +18,7 @@ * */ +import Cookies from 'js-cookie'; import { Contract } from 'ethers'; import { isAddress } from 'ethers'; import { BiCopy } from 'react-icons/bi'; @@ -39,7 +40,14 @@ import { HEDERA_CHAKRA_INPUT_BOX_SIZES, HEDERA_COMMON_WALLET_REVERT_REASONS, HEDERA_TRANSACTION_RESULT_STORAGE_KEYS, + CONTRACT_NAMES, } from '@/utils/common/constants'; +import { + approveParamFields, + allowanceParamFields, + increaseAllowanceParamFields, + decreaseAllowanceParamFields, +} from '@/utils/contract-interactions/erc/erc20/constant'; import { Td, Th, @@ -54,12 +62,6 @@ import { PopoverTrigger, TableContainer, } from '@chakra-ui/react'; -import { - approveParamFields, - allowanceParamFields, - increaseAllowanceParamFields, - decreaseAllowanceParamFields, -} from '@/utils/contract-interactions/erc/erc20/constant'; interface PageProps { baseContract: Contract; @@ -74,6 +76,7 @@ type Allowance = { const TokenPermission = ({ baseContract }: PageProps) => { const toaster = useToast(); const [allowances, setAllowances] = useState([]); + const currentContractAddress = Cookies.get(CONTRACT_NAMES.ERC20) as string; const [transactionResults, setTransactionResults] = useState([]); const transactionResultStorageKey = HEDERA_TRANSACTION_RESULT_STORAGE_KEYS['ERC20-RESULT']['TOKEN-PERMISSION']; @@ -212,6 +215,7 @@ const TokenPermission = ({ baseContract }: PageProps) => { setTransactionResults, err: tokenPermissionRes.err, transactionHash: tokenPermissionRes.txHash, + sessionedContractAddress: currentContractAddress, transactionType: (transferTypeMap as any)[method], }); return; @@ -263,6 +267,7 @@ const TokenPermission = ({ baseContract }: PageProps) => { status: 'success', transactionTimeStamp: Date.now(), txHash: tokenPermissionRes.txHash as string, + sessionedContractAddress: currentContractAddress, transactionType: (transferTypeMap as any)[method], }, ]); diff --git a/system-contract-dapp-playground/src/components/contract-interaction/erc/erc-20/methods/token-transfer/index.tsx b/system-contract-dapp-playground/src/components/contract-interaction/erc/erc-20/methods/token-transfer/index.tsx index c923cd135..2b962bb79 100644 --- a/system-contract-dapp-playground/src/components/contract-interaction/erc/erc-20/methods/token-transfer/index.tsx +++ b/system-contract-dapp-playground/src/components/contract-interaction/erc/erc-20/methods/token-transfer/index.tsx @@ -18,6 +18,7 @@ * */ +import Cookies from 'js-cookie'; import { Contract } from 'ethers'; import { isAddress } from 'ethers'; import { useToast } from '@chakra-ui/react'; @@ -27,7 +28,7 @@ import MultiLineMethod from '@/components/common/MultiLineMethod'; import { Dispatch, SetStateAction, useEffect, useState } from 'react'; import { TransactionResult } from '@/types/contract-interactions/HTS'; import { convertCalmelCaseFunctionName } from '@/utils/common/helpers'; -import { HEDERA_TRANSACTION_RESULT_STORAGE_KEYS } from '@/utils/common/constants'; +import { CONTRACT_NAMES, HEDERA_TRANSACTION_RESULT_STORAGE_KEYS } from '@/utils/common/constants'; import { handleAPIErrors } from '@/components/contract-interaction/hts/shared/methods/handleAPIErrors'; import { useUpdateTransactionResultsToLocalStorage } from '@/components/contract-interaction/hts/shared/hooks/useUpdateLocalStorage'; import { handleRetrievingTransactionResultsFromLocalStorage } from '@/components/contract-interaction/hts/shared/methods/handleRetrievingTransactionResultsFromLocalStorage'; @@ -44,6 +45,7 @@ const Transfer = ({ baseContract }: PageProps) => { const toaster = useToast(); const transactionResultStorageKey = HEDERA_TRANSACTION_RESULT_STORAGE_KEYS['ERC20-RESULT']['TOKEN-TRANSFER']; + const currentContractAddress = Cookies.get(CONTRACT_NAMES.ERC20) as string; const [transactionResults, setTransactionResults] = useState([]); const [transferParams, setTransferParams] = useState({ @@ -128,6 +130,7 @@ const Transfer = ({ baseContract }: PageProps) => { setTransactionResults, err: tokenTransferRes.err, transactionHash: tokenTransferRes.txHash, + sessionedContractAddress: currentContractAddress, transactionType: `ERC20-${convertCalmelCaseFunctionName(method).replace(' ', '-')}`, }); return; @@ -142,6 +145,7 @@ const Transfer = ({ baseContract }: PageProps) => { status: 'success', transactionTimeStamp: Date.now(), txHash: tokenTransferRes.txHash as string, + sessionedContractAddress: currentContractAddress, transactionType: `ERC20-${convertCalmelCaseFunctionName(method).toUpperCase().replace(' ', '-')}`, }, ]); diff --git a/system-contract-dapp-playground/src/components/contract-interaction/erc/erc-721/methods/approve/index.tsx b/system-contract-dapp-playground/src/components/contract-interaction/erc/erc-721/methods/approve/index.tsx index cfa2c3199..c777f0cb2 100644 --- a/system-contract-dapp-playground/src/components/contract-interaction/erc/erc-721/methods/approve/index.tsx +++ b/system-contract-dapp-playground/src/components/contract-interaction/erc/erc-721/methods/approve/index.tsx @@ -19,6 +19,7 @@ */ import Image from 'next/image'; +import Cookies from 'js-cookie'; import { Contract } from 'ethers'; import { isAddress } from 'ethers'; import MultiLineMethod from '@/components/common/MultiLineMethod'; @@ -35,6 +36,7 @@ import useRetrieveMapValueFromLocalStorage from '../../../shared/hooks/useRetrie import { useUpdateTransactionResultsToLocalStorage } from '@/components/contract-interaction/hts/shared/hooks/useUpdateLocalStorage'; import { handleRetrievingTransactionResultsFromLocalStorage } from '@/components/contract-interaction/hts/shared/methods/handleRetrievingTransactionResultsFromLocalStorage'; import { + CONTRACT_NAMES, HEDERA_BRANDING_COLORS, HEDERA_CHAKRA_TABLE_VARIANTS, HEDERA_CHAKRA_INPUT_BOX_SIZES, @@ -50,6 +52,7 @@ const ERC721Approve = ({ baseContract }: PageProps) => { const [successStatus, setSuccessStatus] = useState(false); const [ractNodes, setReactNodes] = useState([]); const [getApproveTokenId, setGetApproveTokenId] = useState(''); + const currentContractAddress = Cookies.get(CONTRACT_NAMES.ERC721) as string; const [tokenSpenders, setTokenSpenders] = useState(new Map()); const [transactionResults, setTransactionResults] = useState([]); const tokenSpenderResultsStorageKey = @@ -121,8 +124,9 @@ const ERC721Approve = ({ baseContract }: PageProps) => { toaster, setTransactionResults, err: erc721ApproveResult.err, - transactionHash: erc721ApproveResult.txHash, transactionType: 'ERC721-APPROVE', + transactionHash: erc721ApproveResult.txHash, + sessionedContractAddress: currentContractAddress, }); return; } else { @@ -133,8 +137,9 @@ const ERC721Approve = ({ baseContract }: PageProps) => { { status: 'success', transactionTimeStamp: Date.now(), - txHash: erc721ApproveResult.txHash as string, transactionType: 'ERC721-APPROVE', + txHash: erc721ApproveResult.txHash as string, + sessionedContractAddress: currentContractAddress, }, ]); @@ -151,7 +156,14 @@ const ERC721Approve = ({ baseContract }: PageProps) => { } } }, - [toaster, baseContract, getApproveTokenId, approveParams.spenderAddress, approveParams.tokenId] + [ + toaster, + baseContract, + getApproveTokenId, + approveParams.tokenId, + currentContractAddress, + approveParams.spenderAddress, + ] ); /** @dev listen to change event on transactionResults state => load to localStorage */ diff --git a/system-contract-dapp-playground/src/components/contract-interaction/erc/erc-721/methods/mint/index.tsx b/system-contract-dapp-playground/src/components/contract-interaction/erc/erc-721/methods/mint/index.tsx index c9679686e..2f2801763 100644 --- a/system-contract-dapp-playground/src/components/contract-interaction/erc/erc-721/methods/mint/index.tsx +++ b/system-contract-dapp-playground/src/components/contract-interaction/erc/erc-721/methods/mint/index.tsx @@ -18,6 +18,7 @@ * */ +import Cookies from 'js-cookie'; import { useToast } from '@chakra-ui/react'; import { useEffect, useState } from 'react'; import { Contract, isAddress } from 'ethers'; @@ -25,7 +26,7 @@ import { erc721Mint } from '@/api/hedera/erc721-interactions'; import { CommonErrorToast } from '@/components/toast/CommonToast'; import MultiLineMethod from '@/components/common/MultiLineMethod'; import { TransactionResult } from '@/types/contract-interactions/HTS'; -import { HEDERA_TRANSACTION_RESULT_STORAGE_KEYS } from '@/utils/common/constants'; +import { CONTRACT_NAMES, HEDERA_TRANSACTION_RESULT_STORAGE_KEYS } from '@/utils/common/constants'; import { mintParamFields } from '@/utils/contract-interactions/erc/erc721/constant'; import { handleAPIErrors } from '@/components/contract-interaction/hts/shared/methods/handleAPIErrors'; import { useUpdateTransactionResultsToLocalStorage } from '@/components/contract-interaction/hts/shared/hooks/useUpdateLocalStorage'; @@ -38,6 +39,7 @@ const Mint = ({ baseContract }: PageProps) => { const toaster = useToast(); const [isLoading, setIsLoading] = useState(false); const [isSuccessful, setIsSuccessful] = useState(false); + const currentContractAddress = Cookies.get(CONTRACT_NAMES.ERC721) as string; const [transactionResults, setTransactionResults] = useState([]); const transactionResultStorageKey = HEDERA_TRANSACTION_RESULT_STORAGE_KEYS['ERC721-RESULT']['TOKEN-MINT']; const [mintParams, setMintParams] = useState({ @@ -74,6 +76,7 @@ const Mint = ({ baseContract }: PageProps) => { setTransactionResults, transactionHash: txHash, transactionType: 'ERC721-MINT', + sessionedContractAddress: currentContractAddress, }); return; } else { @@ -85,6 +88,7 @@ const Mint = ({ baseContract }: PageProps) => { txHash: txHash as string, transactionType: 'ERC721-MINT', transactionTimeStamp: Date.now(), + sessionedContractAddress: currentContractAddress, }, ]); diff --git a/system-contract-dapp-playground/src/components/contract-interaction/erc/erc-721/methods/operator-approve/index.tsx b/system-contract-dapp-playground/src/components/contract-interaction/erc/erc-721/methods/operator-approve/index.tsx index 4386fe162..749e2a736 100644 --- a/system-contract-dapp-playground/src/components/contract-interaction/erc/erc-721/methods/operator-approve/index.tsx +++ b/system-contract-dapp-playground/src/components/contract-interaction/erc/erc-721/methods/operator-approve/index.tsx @@ -18,6 +18,7 @@ * */ +import Cookies from 'js-cookie'; import { Contract } from 'ethers'; import { isAddress } from 'ethers'; import { BiCopy } from 'react-icons/bi'; @@ -49,6 +50,7 @@ import { TableContainer, } from '@chakra-ui/react'; import { + CONTRACT_NAMES, HEDERA_BRANDING_COLORS, HEDERA_CHAKRA_TABLE_VARIANTS, HEDERA_CHAKRA_INPUT_BOX_SIZES, @@ -75,6 +77,7 @@ type ApprovalStatus = { const ERC721OperatorApproval = ({ baseContract }: PageProps) => { const toaster = useToast(); const [successStatus, setSuccessStatus] = useState(false); + const currentContractAddress = Cookies.get(CONTRACT_NAMES.ERC721) as string; const [approvalRecords, setApprovalRecords] = useState([]); const [transactionResults, setTransactionResults] = useState([]); const approvalStatusStorageKey = HEDERA_TRANSACTION_RESULT_STORAGE_KEYS['ERC721-RESULT']['GET-APPROVAL']; @@ -167,8 +170,9 @@ const ERC721OperatorApproval = ({ baseContract }: PageProps) => { toaster, setTransactionResults, err: tokenApprovalRes.err, - transactionHash: tokenApprovalRes.txHash, transactionType: 'ERC721-SET-APPROVAL', + transactionHash: tokenApprovalRes.txHash, + sessionedContractAddress: currentContractAddress, }); return; } else { @@ -179,8 +183,9 @@ const ERC721OperatorApproval = ({ baseContract }: PageProps) => { { status: 'success', transactionTimeStamp: Date.now(), - txHash: tokenApprovalRes.txHash as string, transactionType: 'ERC721-SET-APPROVAL', + txHash: tokenApprovalRes.txHash as string, + sessionedContractAddress: currentContractAddress, }, ]); diff --git a/system-contract-dapp-playground/src/components/contract-interaction/erc/erc-721/methods/token-transfer/index.tsx b/system-contract-dapp-playground/src/components/contract-interaction/erc/erc-721/methods/token-transfer/index.tsx index ccb0d4ebf..782a9a3ae 100644 --- a/system-contract-dapp-playground/src/components/contract-interaction/erc/erc-721/methods/token-transfer/index.tsx +++ b/system-contract-dapp-playground/src/components/contract-interaction/erc/erc-721/methods/token-transfer/index.tsx @@ -18,6 +18,7 @@ * */ +import Cookies from 'js-cookie'; import { Contract } from 'ethers'; import { isAddress } from 'ethers'; import { useToast } from '@chakra-ui/react'; @@ -27,7 +28,7 @@ import MultiLineMethod from '@/components/common/MultiLineMethod'; import { erc721Transfers } from '@/api/hedera/erc721-interactions'; import { TransactionResult } from '@/types/contract-interactions/HTS'; import { convertCalmelCaseFunctionName } from '@/utils/common/helpers'; -import { HEDERA_TRANSACTION_RESULT_STORAGE_KEYS } from '@/utils/common/constants'; +import { CONTRACT_NAMES, HEDERA_TRANSACTION_RESULT_STORAGE_KEYS } from '@/utils/common/constants'; import { handleAPIErrors } from '@/components/contract-interaction/hts/shared/methods/handleAPIErrors'; import { useUpdateTransactionResultsToLocalStorage } from '@/components/contract-interaction/hts/shared/hooks/useUpdateLocalStorage'; import { handleRetrievingTransactionResultsFromLocalStorage } from '@/components/contract-interaction/hts/shared/methods/handleRetrievingTransactionResultsFromLocalStorage'; @@ -44,6 +45,7 @@ const ERC721Transfer = ({ baseContract }: PageProps) => { const toaster = useToast(); const transactionResultStorageKey = HEDERA_TRANSACTION_RESULT_STORAGE_KEYS['ERC721-RESULT']['TOKEN-TRANSFER']; + const currentContractAddress = Cookies.get(CONTRACT_NAMES.ERC721) as string; const [transactionResults, setTransactionResults] = useState([]); const [transferFromParams, setTransferFromParams] = useState({ @@ -120,6 +122,7 @@ const ERC721Transfer = ({ baseContract }: PageProps) => { setTransactionResults, err: tokenTransferRes.err, transactionHash: tokenTransferRes.txHash, + sessionedContractAddress: currentContractAddress, transactionType: `ERC721-${convertCalmelCaseFunctionName(method).replace(' ', '-')}`, }); return; @@ -133,6 +136,7 @@ const ERC721Transfer = ({ baseContract }: PageProps) => { status: 'success', transactionTimeStamp: Date.now(), txHash: tokenTransferRes.txHash as string, + sessionedContractAddress: currentContractAddress, transactionType: `ERC721-${convertCalmelCaseFunctionName(method).toUpperCase().replace(' ', '-')}`, }, ]); diff --git a/system-contract-dapp-playground/src/components/contract-interaction/hts/shared/hooks/useFilterTransactionsByContractAddress.tsx b/system-contract-dapp-playground/src/components/contract-interaction/hts/shared/hooks/useFilterTransactionsByContractAddress.tsx new file mode 100644 index 000000000..1b50f2ba1 --- /dev/null +++ b/system-contract-dapp-playground/src/components/contract-interaction/hts/shared/hooks/useFilterTransactionsByContractAddress.tsx @@ -0,0 +1,36 @@ +/*- + * + * Hedera Smart Contracts + * + * Copyright (C) 2023 Hedera Hashgraph, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +import { useMemo } from 'react'; +import { TransactionResult } from '@/types/contract-interactions/HTS'; + +/** @dev custom hook to filter transactions by contract address */ + +const useFilterTransactionsByContractAddress = ( + transactionResults: TransactionResult[], + contractAddress: string +) => { + return useMemo( + () => transactionResults.filter((result) => result.sessionedContractAddress === contractAddress), + [transactionResults, contractAddress] + ); +}; + +export default useFilterTransactionsByContractAddress; diff --git a/system-contract-dapp-playground/src/components/contract-interaction/hts/shared/methods/handleAPIErrors.tsx b/system-contract-dapp-playground/src/components/contract-interaction/hts/shared/methods/handleAPIErrors.tsx index 935c64711..f031e7ade 100644 --- a/system-contract-dapp-playground/src/components/contract-interaction/hts/shared/methods/handleAPIErrors.tsx +++ b/system-contract-dapp-playground/src/components/contract-interaction/hts/shared/methods/handleAPIErrors.tsx @@ -20,8 +20,8 @@ import { Dispatch, SetStateAction } from 'react'; import { CommonErrorToast } from '@/components/toast/CommonToast'; -import { IHederaTokenServiceKeyType, TransactionResult } from '@/types/contract-interactions/HTS'; import { HEDERA_COMMON_WALLET_REVERT_REASONS } from '@/utils/common/constants'; +import { IHederaTokenServiceKeyType, TransactionResult } from '@/types/contract-interactions/HTS'; /** @dev handle error returned back from invoking method APIs*/ export const handleAPIErrors = ({ @@ -36,6 +36,7 @@ export const handleAPIErrors = ({ transactionHash, receiverAddress, setTransactionResults, + sessionedContractAddress, }: { err: any; toaster: any; @@ -45,6 +46,7 @@ export const handleAPIErrors = ({ transactionType: string; receiverAddress?: string; tokenAddresses?: string[]; + sessionedContractAddress: string; transactionHash: string | undefined; keyTypeCalled?: IHederaTokenServiceKeyType; setTransactionResults: Dispatch>; @@ -82,6 +84,7 @@ export const handleAPIErrors = ({ isToken: false, transactionType, txHash: transactionHash, + sessionedContractAddress, tokenAddress: tokenAddress ? tokenAddress : '', accountAddress: accountAddress ? accountAddress : '', tokenAddresses: tokenAddresses ? tokenAddresses : [''], diff --git a/system-contract-dapp-playground/src/components/contract-interaction/hts/token-create-custom/methods/AssociateHederaToken.tsx b/system-contract-dapp-playground/src/components/contract-interaction/hts/token-create-custom/methods/AssociateHederaToken.tsx index 3734a19a1..a7874ca9f 100644 --- a/system-contract-dapp-playground/src/components/contract-interaction/hts/token-create-custom/methods/AssociateHederaToken.tsx +++ b/system-contract-dapp-playground/src/components/contract-interaction/hts/token-create-custom/methods/AssociateHederaToken.tsx @@ -29,14 +29,15 @@ import { handleAPIErrors } from '../../shared/methods/handleAPIErrors'; import { TRANSACTION_PAGE_SIZE } from '../../shared/states/commonStates'; import { useToastSuccessful } from '../../shared/hooks/useToastSuccessful'; import { usePaginatedTxResults } from '../../shared/hooks/usePaginatedTxResults'; -import { HEDERA_TRANSACTION_RESULT_STORAGE_KEYS } from '@/utils/common/constants'; import TokenAddressesInputForm from '../../shared/components/TokenAddressesInputForm'; import { TransactionResultTable } from '../../shared/components/TransactionResultTable'; -import { associateHederaTokensToAccounts } from '@/api/hedera/hts-interactions/tokenCreateCustom-interactions'; import { handleSanitizeHederaFormInputs } from '../../shared/methods/handleSanitizeFormInputs'; +import { CONTRACT_NAMES, HEDERA_TRANSACTION_RESULT_STORAGE_KEYS } from '@/utils/common/constants'; import { SharedFormInputField, SharedExecuteButton } from '../../shared/components/ParamInputForm'; import { useUpdateTransactionResultsToLocalStorage } from '../../shared/hooks/useUpdateLocalStorage'; import { htsTokenAssociateParamFields } from '@/utils/contract-interactions/HTS/token-create-custom/constant'; +import { associateHederaTokensToAccounts } from '@/api/hedera/hts-interactions/tokenCreateCustom-interactions'; +import useFilterTransactionsByContractAddress from '../../shared/hooks/useFilterTransactionsByContractAddress'; import { handleRetrievingTransactionResultsFromLocalStorage } from '../../shared/methods/handleRetrievingTransactionResultsFromLocalStorage'; interface PageProps { @@ -52,6 +53,7 @@ const AssociateHederaToken = ({ baseContract }: PageProps) => { const hederaNetwork = JSON.parse(Cookies.get('_network') as string); const [currentTransactionPage, setCurrentTransactionPage] = useState(1); const [paramValues, setParamValues] = useState(initialParamValues); + const currentContractAddress = Cookies.get(CONTRACT_NAMES.TOKEN_CREATE) as string; const [transactionResults, setTransactionResults] = useState([]); const initialTokenAddressesValues = { fieldKey: generatedRandomUniqueKey(9), fieldValue: '' }; const transactionResultStorageKey = @@ -60,6 +62,11 @@ const AssociateHederaToken = ({ baseContract }: PageProps) => { { fieldKey: string; fieldValue: string }[] >([initialTokenAddressesValues]); + const transactionResultsToShow = useFilterTransactionsByContractAddress( + transactionResults, + currentContractAddress + ); + /** @dev retrieve token creation results from localStorage to maintain data on re-renders */ useEffect(() => { handleRetrievingTransactionResultsFromLocalStorage( @@ -71,7 +78,7 @@ const AssociateHederaToken = ({ baseContract }: PageProps) => { }, [toaster, transactionResultStorageKey]); // declare a paginatedTransactionResults - const paginatedTransactionResults = usePaginatedTxResults(currentTransactionPage, transactionResults); + const paginatedTransactionResults = usePaginatedTxResults(currentTransactionPage, transactionResultsToShow); /** @dev handle form inputs on change */ const handleInputOnChange = (e: any, param: string, fieldKey?: string) => { @@ -147,6 +154,7 @@ const AssociateHederaToken = ({ baseContract }: PageProps) => { setTransactionResults, accountAddress: associatingAddress, transactionType: 'HTS-TOKEN-ASSOCIATE', + sessionedContractAddress: currentContractAddress, }); return; } else { @@ -160,6 +168,7 @@ const AssociateHederaToken = ({ baseContract }: PageProps) => { txHash: transactionHash as string, accountAddress: associatingAddress, transactionType: 'HTS-TOKEN-ASSOCIATE', + sessionedContractAddress: currentContractAddress, }, ]); @@ -218,7 +227,7 @@ const AssociateHederaToken = ({ baseContract }: PageProps) => { {/* transaction results table */} - {transactionResults.length > 0 && ( + {transactionResultsToShow.length > 0 && ( { const [isSuccessful, setIsSuccessful] = useState(false); const [withCustomFee, setWithCustomFee] = useState(false); const [isDefaultFreeze, setIsDefaultFreeze] = useState(false); - const hederaNetwork = JSON.parse(Cookies.get('_network') as string); + const HEDERA_NETWORK = JSON.parse(Cookies.get('_network') as string); const [currentTransactionPage, setCurrentTransactionPage] = useState(1); + const currentContractAddress = Cookies.get(CONTRACT_NAMES.TOKEN_CREATE) as string; + const [transactionResults, setTransactionResults] = useState([]); const transactionResultStorageKey = HEDERA_TRANSACTION_RESULT_STORAGE_KEYS['TOKEN-CREATE']['FUNGIBLE-TOKEN']; - const [transactionResults, setTransactionResults] = useState([]); const tokenCreateFields = { info: ['name', 'symbol', 'memo'], supply: ['initSupply', 'maxSupply', 'decimals'], @@ -86,6 +88,11 @@ const FungibleTokenCreate = ({ baseContract }: PageProps) => { }; const [paramValues, setParamValues] = useState(initialParamValues); + const transactionResultsToShow = useFilterTransactionsByContractAddress( + transactionResults, + currentContractAddress + ); + // Keys states const [keys, setKeys] = useState([]); // keeps track of keys array to pass to the API const [chosenKeys, setChosenKeys] = useState(new Set()); // keeps track of keyTypes which have already been chosen in the list @@ -102,7 +109,7 @@ const FungibleTokenCreate = ({ baseContract }: PageProps) => { }, [toaster, transactionResultStorageKey]); // declare a paginatedTransactionResults - const paginatedTransactionResults = usePaginatedTxResults(currentTransactionPage, transactionResults); + const paginatedTransactionResults = usePaginatedTxResults(currentTransactionPage, transactionResultsToShow); /** @dev handle form inputs on change */ const handleInputOnChange = (e: any, param: string) => { @@ -175,6 +182,7 @@ const FungibleTokenCreate = ({ baseContract }: PageProps) => { transactionHash, setTransactionResults, transactionType: 'HTS-TOKEN-CREATE', + sessionedContractAddress: currentContractAddress, }); return; } else { @@ -187,6 +195,7 @@ const FungibleTokenCreate = ({ baseContract }: PageProps) => { transactionTimeStamp: Date.now(), txHash: transactionHash as string, transactionType: 'HTS-TOKEN-CREATE', + sessionedContractAddress: currentContractAddress, }, ]); @@ -362,10 +371,10 @@ const FungibleTokenCreate = ({ baseContract }: PageProps) => { {/* transaction results table */} - {transactionResults.length > 0 && ( + {transactionResultsToShow.length > 0 && ( { const hederaNetwork = JSON.parse(Cookies.get('_network') as string); const [currentTransactionPage, setCurrentTransactionPage] = useState(1); const grantKYCFields = ['hederaTokenAddress', 'grantingKYCAccountAddress']; - const transactionResultStorageKey = HEDERA_TRANSACTION_RESULT_STORAGE_KEYS['TOKEN-CREATE']['TOKEN-KYC']; + const currentContractAddress = Cookies.get(CONTRACT_NAMES.TOKEN_CREATE) as string; const [transactionResults, setTransactionResults] = useState([]); + const transactionResultStorageKey = HEDERA_TRANSACTION_RESULT_STORAGE_KEYS['TOKEN-CREATE']['TOKEN-KYC']; const initialParamValues = { hederaTokenAddress: '', grantingKYCAccountAddress: '', }; const [paramValues, setParamValues] = useState(initialParamValues); + const transactionResultsToShow = useFilterTransactionsByContractAddress( + transactionResults, + currentContractAddress + ); + /** @dev retrieve token creation results from localStorage to maintain data on re-renders */ useEffect(() => { handleRetrievingTransactionResultsFromLocalStorage( @@ -68,7 +75,7 @@ const GrantTokenKYC = ({ baseContract }: PageProps) => { }, [toaster, transactionResultStorageKey]); // declare a paginatedTransactionResults - const paginatedTransactionResults = usePaginatedTxResults(currentTransactionPage, transactionResults); + const paginatedTransactionResults = usePaginatedTxResults(currentTransactionPage, transactionResultsToShow); /** @dev handle form inputs on change */ const handleInputOnChange = (e: any, param: string) => { @@ -115,6 +122,7 @@ const GrantTokenKYC = ({ baseContract }: PageProps) => { tokenAddress: hederaTokenAddress, transactionType: 'HTS-GRANT-KYC', accountAddress: grantingKYCAccountAddress, + sessionedContractAddress: currentContractAddress, }); return; } else { @@ -128,6 +136,7 @@ const GrantTokenKYC = ({ baseContract }: PageProps) => { tokenAddress: hederaTokenAddress, txHash: transactionHash as string, accountAddress: grantingKYCAccountAddress, + sessionedContractAddress: currentContractAddress, }, ]); @@ -182,7 +191,7 @@ const GrantTokenKYC = ({ baseContract }: PageProps) => { {/* transaction results table */} - {transactionResults.length > 0 && ( + {transactionResultsToShow.length > 0 && ( { const [isLoading, setIsLoading] = useState(false); const [isSuccessful, setIsSuccessful] = useState(false); const [APIMethods, setAPIMethods] = useState('FUNGIBLE'); - const hederaNetwork = JSON.parse(Cookies.get('_network') as string); + const HEDERA_NETWORK = JSON.parse(Cookies.get('_network') as string); const [currentTransactionPage, setCurrentTransactionPage] = useState(1); - const transactionResultStorageKey = HEDERA_TRANSACTION_RESULT_STORAGE_KEYS['TOKEN-CREATE']['MINT-TOKEN']; + const currentContractAddress = Cookies.get(CONTRACT_NAMES.TOKEN_CREATE) as string; const [transactionResults, setTransactionResults] = useState([]); const [metadata, setMetadata] = useState<{ metaKey: string; metaValue: string }[]>([]); + const transactionResultStorageKey = HEDERA_TRANSACTION_RESULT_STORAGE_KEYS['TOKEN-CREATE']['MINT-TOKEN']; const tokenMintFields = useMemo(() => { return APIMethods === 'FUNGIBLE' ? ['tokenAddressToMint', 'amount', 'recipientAddress'] @@ -75,6 +77,11 @@ const MintHederaToken = ({ baseContract }: PageProps) => { }; const [paramValues, setParamValues] = useState(initialParamValues); + const transactionResultsToShow = useFilterTransactionsByContractAddress( + transactionResults, + currentContractAddress + ); + const APIButtonTitles: { API: API_NAMES; apiSwitchTitle: string; executeTitle: string }[] = [ { API: 'FUNGIBLE', @@ -99,7 +106,7 @@ const MintHederaToken = ({ baseContract }: PageProps) => { }, [toaster, transactionResultStorageKey]); /** @dev declare a paginatedTransactionResults */ - const paginatedTransactionResults = usePaginatedTxResults(currentTransactionPage, transactionResults); + const paginatedTransactionResults = usePaginatedTxResults(currentTransactionPage, transactionResultsToShow); /** @dev handle form inputs on change */ const handleInputOnChange = (e: any, param: string, metaKey?: string) => { @@ -185,6 +192,7 @@ const MintHederaToken = ({ baseContract }: PageProps) => { setTransactionResults, tokenAddress: tokenAddressToMint, transactionHash: txRes.transactionHash, + sessionedContractAddress: currentContractAddress, transactionType: `HTS-${APIMethods === 'FUNGIBLE' ? 'TOKEN' : 'NFT'}-MINT`, }); return; @@ -198,6 +206,7 @@ const MintHederaToken = ({ baseContract }: PageProps) => { transactionTimeStamp: Date.now(), txHash: txRes.transactionHash as string, tokenAddress: paramValues.tokenAddressToMint, + sessionedContractAddress: currentContractAddress, transactionType: `HTS-${APIMethods === 'FUNGIBLE' ? 'TOKEN' : 'NFT'}-MINT`, }, ]); @@ -288,10 +297,10 @@ const MintHederaToken = ({ baseContract }: PageProps) => { {/* transaction results table */} - {transactionResults.length > 0 && ( + {transactionResultsToShow.length > 0 && ( { const [withCustomFee, setWithCustomFee] = useState(false); const HEDERA_NETWORK = JSON.parse(Cookies.get('_network') as string); const [currentTransactionPage, setCurrentTransactionPage] = useState(1); + const currentContractAddress = Cookies.get(CONTRACT_NAMES.TOKEN_CREATE) as string; const [transactionResults, setTransactionResults] = useState([]); const transactionResultStorageKey = HEDERA_TRANSACTION_RESULT_STORAGE_KEYS['TOKEN-CREATE']['NON-FUNGIBLE-TOKEN']; @@ -80,6 +82,11 @@ const NonFungibleTokenCreate = ({ baseContract }: PageProps) => { }; const [paramValues, setParamValues] = useState(initialParamValues); + const transactionResultsToShow = useFilterTransactionsByContractAddress( + transactionResults, + currentContractAddress + ); + // keys states const [keys, setKeys] = useState([]); // keeps track of keys array to pass to the API const [chosenKeys, setChosenKeys] = useState(new Set()); // keeps track of keyTypes which have already been chosen in the list @@ -96,7 +103,7 @@ const NonFungibleTokenCreate = ({ baseContract }: PageProps) => { }, [toaster, transactionResultStorageKey]); // declare a paginatedTransactionResults - const paginatedTransactionResults = usePaginatedTxResults(currentTransactionPage, transactionResults); + const paginatedTransactionResults = usePaginatedTxResults(currentTransactionPage, transactionResultsToShow); /** @dev handle form inputs on change */ const handleInputOnChange = (e: any, param: string) => { @@ -153,6 +160,7 @@ const NonFungibleTokenCreate = ({ baseContract }: PageProps) => { transactionHash, setTransactionResults, transactionType: 'HTS-NFT-CREATE', + sessionedContractAddress: currentContractAddress, }); return; } else { @@ -162,9 +170,10 @@ const NonFungibleTokenCreate = ({ baseContract }: PageProps) => { { tokenAddress, status: 'success', - txHash: transactionHash as string, - transactionType: 'HTS-NFT-CREATE', transactionTimeStamp: Date.now(), + transactionType: 'HTS-NFT-CREATE', + txHash: transactionHash as string, + sessionedContractAddress: currentContractAddress, }, ]); @@ -280,7 +289,7 @@ const NonFungibleTokenCreate = ({ baseContract }: PageProps) => { {/* transaction results table */} - {transactionResults.length > 0 && ( + {transactionResultsToShow.length > 0 && ( { TRANSACTION_PAGE_SIZE={TRANSACTION_PAGE_SIZE} setTransactionResults={setTransactionResults} currentTransactionPage={currentTransactionPage} + setCurrentTransactionPage={setCurrentTransactionPage} transactionResultStorageKey={transactionResultStorageKey} paginatedTransactionResults={paginatedTransactionResults} - setCurrentTransactionPage={setCurrentTransactionPage} /> )} diff --git a/system-contract-dapp-playground/src/components/contract-interaction/hts/token-management-contract/methods/manageTokenDelete/index.tsx b/system-contract-dapp-playground/src/components/contract-interaction/hts/token-management-contract/methods/manageTokenDelete/index.tsx index 21880064c..b702fb5a6 100644 --- a/system-contract-dapp-playground/src/components/contract-interaction/hts/token-management-contract/methods/manageTokenDelete/index.tsx +++ b/system-contract-dapp-playground/src/components/contract-interaction/hts/token-management-contract/methods/manageTokenDelete/index.tsx @@ -27,14 +27,15 @@ import { TransactionResult } from '@/types/contract-interactions/HTS'; import { handleAPIErrors } from '../../../shared/methods/handleAPIErrors'; import { TRANSACTION_PAGE_SIZE } from '../../../shared/states/commonStates'; import { useToastSuccessful } from '../../../shared/hooks/useToastSuccessful'; -import { HEDERA_TRANSACTION_RESULT_STORAGE_KEYS } from '@/utils/common/constants'; import { usePaginatedTxResults } from '../../../shared/hooks/usePaginatedTxResults'; import { TransactionResultTable } from '../../../shared/components/TransactionResultTable'; import { handleSanitizeHederaFormInputs } from '../../../shared/methods/handleSanitizeFormInputs'; import { manageTokenDeduction } from '@/api/hedera/hts-interactions/tokenManagement-interactions'; +import { CONTRACT_NAMES, HEDERA_TRANSACTION_RESULT_STORAGE_KEYS } from '@/utils/common/constants'; import { useUpdateTransactionResultsToLocalStorage } from '../../../shared/hooks/useUpdateLocalStorage'; import { htsTokenDeductionParamFields } from '@/utils/contract-interactions/HTS/token-management/constant'; import { SharedFormInputField, SharedExecuteButtonWithFee } from '../../../shared/components/ParamInputForm'; +import useFilterTransactionsByContractAddress from '../../../shared/hooks/useFilterTransactionsByContractAddress'; import { handleRetrievingTransactionResultsFromLocalStorage } from '../../../shared/methods/handleRetrievingTransactionResultsFromLocalStorage'; interface PageProps { @@ -48,6 +49,7 @@ const ManageTokenDelete = ({ baseContract }: PageProps) => { const [isSuccessful, setIsSuccessful] = useState(false); const hederaNetwork = JSON.parse(Cookies.get('_network') as string); const [currentTransactionPage, setCurrentTransactionPage] = useState(1); + const currentContractAddress = Cookies.get(CONTRACT_NAMES.TOKEN_MANAGE) as string; const [transactionResults, setTransactionResults] = useState([]); const transactionResultStorageKey = HEDERA_TRANSACTION_RESULT_STORAGE_KEYS['TOKEN-MANAGE']['TOKEN-DELETE']; const initialParamValues = { @@ -55,6 +57,12 @@ const ManageTokenDelete = ({ baseContract }: PageProps) => { hederaTokenAddress: '', }; const [paramValues, setParamValues] = useState(initialParamValues); + + const transactionResultsToShow = useFilterTransactionsByContractAddress( + transactionResults, + currentContractAddress + ); + /** @dev retrieve token creation results from localStorage to maintain data on re-renders */ useEffect(() => { handleRetrievingTransactionResultsFromLocalStorage( @@ -66,7 +74,8 @@ const ManageTokenDelete = ({ baseContract }: PageProps) => { }, [toaster, transactionResultStorageKey]); // declare a paginatedTransactionResults - const paginatedTransactionResults = usePaginatedTxResults(currentTransactionPage, transactionResults); + const paginatedTransactionResults = usePaginatedTxResults(currentTransactionPage, transactionResultsToShow); + /** @dev handle form inputs on change */ const handleInputOnChange = (e: any, param: string) => { setParamValues((prev: any) => ({ ...prev, [param]: e.target.value })); @@ -113,6 +122,7 @@ const ManageTokenDelete = ({ baseContract }: PageProps) => { setTransactionResults, tokenAddress: hederaTokenAddress, transactionType: 'HTS-TOKEN-DELETE', + sessionedContractAddress: currentContractAddress, }); return; } else { @@ -125,6 +135,7 @@ const ManageTokenDelete = ({ baseContract }: PageProps) => { transactionTimeStamp: Date.now(), txHash: transactionHash as string, transactionType: 'HTS-TOKEN-DELETE', + sessionedContractAddress: currentContractAddress, }, ]); @@ -180,7 +191,7 @@ const ManageTokenDelete = ({ baseContract }: PageProps) => { {/* transaction results table */} - {transactionResults.length > 0 && ( + {transactionResultsToShow.length > 0 && ( { const hederaNetwork = JSON.parse(Cookies.get('_network') as string); const [APIMethods, setAPIMethods] = useState('UPDATE_INFO'); const [currentTransactionPage, setCurrentTransactionPage] = useState(1); - const transactionResultStorageKey = HEDERA_TRANSACTION_RESULT_STORAGE_KEYS['TOKEN-MANAGE']['TOKEN-INFO']; + const currentContractAddress = Cookies.get(CONTRACT_NAMES.TOKEN_MANAGE) as string; const [transactionResults, setTransactionResults] = useState([]); + const transactionResultStorageKey = HEDERA_TRANSACTION_RESULT_STORAGE_KEYS['TOKEN-MANAGE']['TOKEN-INFO']; const APIButtonTitles: { API: API_NAMES; apiSwitchTitle: string; executeTitle: string }[] = [ { API: 'UPDATE_INFO', @@ -107,6 +109,11 @@ const ManageTokenInfo = ({ baseContract }: PageProps) => { }; const [paramValues, setParamValues] = useState(initialParamValues); + const transactionResultsToShow = useFilterTransactionsByContractAddress( + transactionResults, + currentContractAddress + ); + const HederaTokenKeyValueType: IHederaTokenServiceKeyValueType[] = [ 'inheritAccountKey', 'contractId', @@ -156,7 +163,7 @@ const ManageTokenInfo = ({ baseContract }: PageProps) => { }, [toaster, transactionResultStorageKey]); // declare a paginatedTransactionResults - const paginatedTransactionResults = usePaginatedTxResults(currentTransactionPage, transactionResults); + const paginatedTransactionResults = usePaginatedTxResults(currentTransactionPage, transactionResultsToShow); /** @dev handle form inputs on change */ const handleInputOnChange = (e: any, param: string) => { @@ -256,6 +263,7 @@ const ManageTokenInfo = ({ baseContract }: PageProps) => { transactionHash, setTransactionResults, tokenAddress: hederaTokenAddress, + sessionedContractAddress: currentContractAddress, transactionType: `HTS-${APIMethods.replace('_', '-')}`, }); return; @@ -268,6 +276,7 @@ const ManageTokenInfo = ({ baseContract }: PageProps) => { tokenAddress: hederaTokenAddress, transactionTimeStamp: Date.now(), txHash: transactionHash as string, + sessionedContractAddress: currentContractAddress, transactionType: `HTS-${APIMethods.replace('_', '-')}`, }, ]); @@ -392,7 +401,7 @@ const ManageTokenInfo = ({ baseContract }: PageProps) => { {/* transaction results table */} - {transactionResults.length > 0 && ( + {transactionResultsToShow.length > 0 && ( { const [currentTransactionPage, setCurrentTransactionPage] = useState(1); const tokenCommonFields = ['hederaTokenAddress', 'targetApprovedAddress']; const [APIMethods, setAPIMethods] = useState('APPROVED_FUNGIBLE'); + const currentContractAddress = Cookies.get(CONTRACT_NAMES.TOKEN_MANAGE) as string; const [transactionResults, setTransactionResults] = useState([]); const transactionResultStorageKey = HEDERA_TRANSACTION_RESULT_STORAGE_KEYS['TOKEN-MANAGE']['TOKEN-PERMISSION']; @@ -89,6 +91,11 @@ const ManageTokenPermission = ({ baseContract }: PageProps) => { { API: 'SET_APPROVAL', apiSwitchTitle: 'Set Approval', executeTitle: 'Set Approval For All' }, ]; + const transactionResultsToShow = useFilterTransactionsByContractAddress( + transactionResults, + currentContractAddress + ); + /** @dev retrieve token creation results from localStorage to maintain data on re-renders */ useEffect(() => { handleRetrievingTransactionResultsFromLocalStorage( @@ -100,7 +107,7 @@ const ManageTokenPermission = ({ baseContract }: PageProps) => { }, [toaster, transactionResultStorageKey]); // declare a paginatedTransactionResults - const paginatedTransactionResults = usePaginatedTxResults(currentTransactionPage, transactionResults); + const paginatedTransactionResults = usePaginatedTxResults(currentTransactionPage, transactionResultsToShow); /** @dev handle form inputs on change */ const handleInputOnChange = (e: any, param: string) => { @@ -162,6 +169,7 @@ const ManageTokenPermission = ({ baseContract }: PageProps) => { setTransactionResults, tokenAddress: hederaTokenAddress, transactionType: transactionTypeMap[API], + sessionedContractAddress: currentContractAddress, }); return; } else { @@ -174,6 +182,7 @@ const ManageTokenPermission = ({ baseContract }: PageProps) => { transactionTimeStamp: Date.now(), txHash: transactionHash as string, transactionType: transactionTypeMap[API], + sessionedContractAddress: currentContractAddress, }, ]); @@ -317,7 +326,7 @@ const ManageTokenPermission = ({ baseContract }: PageProps) => { {/* transaction results table */} - {transactionResults.length > 0 && ( + {transactionResultsToShow.length > 0 && ( { const hederaNetwork = JSON.parse(Cookies.get('_network') as string); const [APIMethods, setAPIMethods] = useState('REVOKE_KYC'); const [currentTransactionPage, setCurrentTransactionPage] = useState(1); + const currentContractAddress = Cookies.get(CONTRACT_NAMES.TOKEN_MANAGE) as string; const [transactionResults, setTransactionResults] = useState([]); const transactionResultStorageKey = HEDERA_TRANSACTION_RESULT_STORAGE_KEYS['TOKEN-MANAGE']['TOKEN-RELATION']; @@ -109,6 +112,11 @@ const ManageTokenRelation = ({ baseContract }: PageProps) => { }, ]; + const transactionResultsToShow = useFilterTransactionsByContractAddress( + transactionResults, + currentContractAddress + ); + /** @dev handle adding metadata */ const handleModifyTokenAddresses = (type: 'ADD' | 'REMOVE', removingFieldKey?: string) => { switch (type) { @@ -136,7 +144,7 @@ const ManageTokenRelation = ({ baseContract }: PageProps) => { }, [toaster, transactionResultStorageKey]); // declare a paginatedTransactionResults - const paginatedTransactionResults = usePaginatedTxResults(currentTransactionPage, transactionResults); + const paginatedTransactionResults = usePaginatedTxResults(currentTransactionPage, transactionResultsToShow); /** @dev handle form inputs on change */ const handleInputOnChange = (e: any, param: string, fieldKey?: string) => { @@ -210,8 +218,9 @@ const ManageTokenRelation = ({ baseContract }: PageProps) => { toaster, transactionHash, setTransactionResults, - transactionType: `HTS-${API.replace('_', '-')}`, tokenAddress: paramValues.hederaTokenAddress, + transactionType: `HTS-${API.replace('_', '-')}`, + sessionedContractAddress: currentContractAddress, }); return; } else { @@ -224,6 +233,7 @@ const ManageTokenRelation = ({ baseContract }: PageProps) => { txHash: transactionHash as string, tokenAddress: paramValues.hederaTokenAddress, transactionType: `HTS-${API.replace('_', '-')}`, + sessionedContractAddress: currentContractAddress, }, ]); @@ -342,7 +352,7 @@ const ManageTokenRelation = ({ baseContract }: PageProps) => { {/* transaction results table */} - {transactionResults.length > 0 && ( + {transactionResultsToShow.length > 0 && ( { const [paramValues, setParamValues] = useState(initialParamValues); const hederaNetwork = JSON.parse(Cookies.get('_network') as string); const [currentTransactionPage, setCurrentTransactionPage] = useState(1); + const currentContractAddress = Cookies.get(CONTRACT_NAMES.TOKEN_MANAGE) as string; const [transactionResults, setTransactionResults] = useState([]); const transactionResultStorageKey = HEDERA_TRANSACTION_RESULT_STORAGE_KEYS['TOKEN-MANAGE']['TOKEN-STATUS']; const [isLoading, setIsLoading] = useState({ @@ -67,6 +69,11 @@ const ManageTokenStatus = ({ baseContract }: PageProps) => { }, ]; + const transactionResultsToShow = useFilterTransactionsByContractAddress( + transactionResults, + currentContractAddress + ); + /** @dev retrieve token creation results from localStorage to maintain data on re-renders */ useEffect(() => { handleRetrievingTransactionResultsFromLocalStorage( @@ -78,7 +85,7 @@ const ManageTokenStatus = ({ baseContract }: PageProps) => { }, [toaster, transactionResultStorageKey]); // declare a paginatedTransactionResults - const paginatedTransactionResults = usePaginatedTxResults(currentTransactionPage, transactionResults); + const paginatedTransactionResults = usePaginatedTxResults(currentTransactionPage, transactionResultsToShow); /** @dev handle form inputs on change */ const handleInputOnChange = (e: any, param: string) => { @@ -125,6 +132,7 @@ const ManageTokenStatus = ({ baseContract }: PageProps) => { setTransactionResults, transactionType: `HTS-TOKEN-${API}`, tokenAddress: paramValues.hederaTokenAddress, + sessionedContractAddress: currentContractAddress, }); return; } else { @@ -137,6 +145,7 @@ const ManageTokenStatus = ({ baseContract }: PageProps) => { txHash: transactionHash as string, transactionType: `HTS-TOKEN-${API}`, tokenAddress: paramValues.hederaTokenAddress, + sessionedContractAddress: currentContractAddress, }, ]); @@ -195,7 +204,7 @@ const ManageTokenStatus = ({ baseContract }: PageProps) => { {/* transaction results table */} - {transactionResults.length > 0 && ( + {transactionResultsToShow.length > 0 && ( { const hederaNetwork = JSON.parse(Cookies.get('_network') as string); const [currentTransactionPage, setCurrentTransactionPage] = useState(1); const [APIMethods, setAPIMethods] = useState('WIPE_FUNGIBLE'); + const currentContractAddress = Cookies.get(CONTRACT_NAMES.TOKEN_MANAGE) as string; const [transactionResults, setTransactionResults] = useState([]); const transactionResultStorageKey = HEDERA_TRANSACTION_RESULT_STORAGE_KEYS['TOKEN-MANAGE']['TOKEN-REDUCTION']; @@ -96,6 +98,11 @@ const ManageTokenDeduction = ({ baseContract }: PageProps) => { } }, [APIMethods]); + const transactionResultsToShow = useFilterTransactionsByContractAddress( + transactionResults, + currentContractAddress + ); + /** @dev retrieve token creation results from localStorage to maintain data on re-renders */ useEffect(() => { handleRetrievingTransactionResultsFromLocalStorage( @@ -107,7 +114,7 @@ const ManageTokenDeduction = ({ baseContract }: PageProps) => { }, [toaster, transactionResultStorageKey]); // declare a paginatedTransactionResults - const paginatedTransactionResults = usePaginatedTxResults(currentTransactionPage, transactionResults); + const paginatedTransactionResults = usePaginatedTxResults(currentTransactionPage, transactionResultsToShow); /** @dev handle form inputs on change */ const handleInputOnChange = (e: any, param: string) => { setParamValues((prev: any) => ({ ...prev, [param]: e.target.value })); @@ -160,6 +167,7 @@ const ManageTokenDeduction = ({ baseContract }: PageProps) => { setTransactionResults, tokenAddress: hederaTokenAddress, transactionType: transactionTypeMap[API], + sessionedContractAddress: currentContractAddress, }); return; } else { @@ -172,6 +180,7 @@ const ManageTokenDeduction = ({ baseContract }: PageProps) => { tokenAddress: hederaTokenAddress, txHash: transactionHash as string, transactionType: transactionTypeMap[API], + sessionedContractAddress: currentContractAddress, }, ]); @@ -254,7 +263,7 @@ const ManageTokenDeduction = ({ baseContract }: PageProps) => { {/* transaction results table */} - {transactionResults.length > 0 && ( + {transactionResultsToShow.length > 0 && ( { const [isLoading, setIsLoading] = useState(false); const [tokenInfo, setTokenInfo] = useState(); const { isOpen, onOpen, onClose } = useDisclosure(); + const initialParamValues = { hederaTokenAddress: '' }; const [isSuccessful, setIsSuccessful] = useState(false); const [showTokenInfo, setShowTokenInfo] = useState(false); const hederaNetwork = JSON.parse(Cookies.get('_network') as string); + const [paramValues, setParamValues] = useState(initialParamValues); const [currentTransactionPage, setCurrentTransactionPage] = useState(1); const [tokenInfoFromTxResult, setTokenInfoFromTxResult] = useState(); const [keyType, setKeyType] = useState('ADMIN'); const [tokenAddressFromTxResult, setTokenAddressFromTxResult] = useState(''); const [APIMethods, setAPIMethods] = useState('DEFAULT_FREEZE_STATUS'); + const currentContractAddress = Cookies.get(CONTRACT_NAMES.TOKEN_QUERY) as string; const [transactionResults, setTransactionResults] = useState([]); + const [keyTypeFromTxResult, setKeyTypeFromTxResult] = useState('ADMIN'); + const [APIMethodsFromTxResult, setAPIMethodsFromTxResult] = useState('DEFAULT_FREEZE_STATUS'); const transactionResultStorageKey = HEDERA_TRANSACTION_RESULT_STORAGE_KEYS['TOKEN-QUERY']['TOKEN-SPECIFIC-INFO']; - const [APIMethodsFromTxResult, setAPIMethodsFromTxResult] = useState('DEFAULT_FREEZE_STATUS'); - const [keyTypeFromTxResult, setKeyTypeFromTxResult] = useState('ADMIN'); - const initialParamValues = { - hederaTokenAddress: '', - }; - const [paramValues, setParamValues] = useState(initialParamValues); // prepare events map const eventMaps: Record = { @@ -126,6 +130,12 @@ const QueryTokenSpecificInfomation = ({ baseContract }: PageProps) => { executeTitle: 'Query Token Keys', }, ]; + + const transactionResultsToShow = useFilterTransactionsByContractAddress( + transactionResults, + currentContractAddress + ); + /** @dev retrieve token creation results from localStorage to maintain data on re-renders */ useEffect(() => { handleRetrievingTransactionResultsFromLocalStorage( @@ -137,7 +147,7 @@ const QueryTokenSpecificInfomation = ({ baseContract }: PageProps) => { }, [toaster, transactionResultStorageKey]); // declare a paginatedTransactionResults - const paginatedTransactionResults = usePaginatedTxResults(currentTransactionPage, transactionResults); + const paginatedTransactionResults = usePaginatedTxResults(currentTransactionPage, transactionResultsToShow); /** @dev handle form inputs on change */ const handleInputOnChange = (e: any, param: string) => { @@ -178,9 +188,10 @@ const QueryTokenSpecificInfomation = ({ baseContract }: PageProps) => { setTransactionResults, keyTypeCalled: keyType, err: tokenInfoResult.err, - transactionType: `HTS-QUERY-${API.replace('_', '-')}`, tokenAddress: paramValues.hederaTokenAddress, + sessionedContractAddress: currentContractAddress, transactionHash: tokenInfoResult.transactionHash, + transactionType: `HTS-QUERY-${API.replace('_', '-')}`, }); return; } else { @@ -224,6 +235,7 @@ const QueryTokenSpecificInfomation = ({ baseContract }: PageProps) => { tokenInfo: cachedTokenInfo, transactionTimeStamp: Date.now(), tokenAddress: paramValues.hederaTokenAddress, + sessionedContractAddress: currentContractAddress, txHash: tokenInfoResult.transactionHash as string, transactionType: `HTS-QUERY-${API.replace('_', '-')}`, }, @@ -310,7 +322,7 @@ const QueryTokenSpecificInfomation = ({ baseContract }: PageProps) => { {/* transaction results table */} - {transactionResults.length > 0 && ( + {transactionResultsToShow.length > 0 && ( { const [currentTransactionPage, setCurrentTransactionPage] = useState(1); const [tokenInfoFromTxResult, setTokenInfoFromTxResult] = useState(); const [tokenAddressFromTxResult, setTokenAddressFromTxResult] = useState(''); + const currentContractAddress = Cookies.get(CONTRACT_NAMES.TOKEN_QUERY) as string; const [transactionResults, setTransactionResults] = useState([]); const transactionResultStorageKey = HEDERA_TRANSACTION_RESULT_STORAGE_KEYS['TOKEN-QUERY']['TOKEN-GENERAL-INFO']; @@ -109,6 +111,11 @@ const QueryTokenGeneralInfomation = ({ baseContract }: PageProps) => { }, ]; + const transactionResultsToShow = useFilterTransactionsByContractAddress( + transactionResults, + currentContractAddress + ); + /** @dev retrieve token creation results from localStorage to maintain data on re-renders */ useEffect(() => { handleRetrievingTransactionResultsFromLocalStorage( @@ -120,7 +127,7 @@ const QueryTokenGeneralInfomation = ({ baseContract }: PageProps) => { }, [toaster, transactionResultStorageKey]); // declare a paginatedTransactionResults - const paginatedTransactionResults = usePaginatedTxResults(currentTransactionPage, transactionResults); + const paginatedTransactionResults = usePaginatedTxResults(currentTransactionPage, transactionResultsToShow); /** @dev handle form inputs on change */ const handleInputOnChange = (e: any, param: string) => { @@ -169,6 +176,7 @@ const QueryTokenGeneralInfomation = ({ baseContract }: PageProps) => { transactionHash: transactionHash, transactionType: transactionTypeMap[API], tokenAddress: paramValues.hederaTokenAddress, + sessionedContractAddress: currentContractAddress, }); return; } else { @@ -184,6 +192,7 @@ const QueryTokenGeneralInfomation = ({ baseContract }: PageProps) => { transactionType: transactionTypeMap[API], tokenInfo: tokenInfoResult[eventMaps[API]], tokenAddress: paramValues.hederaTokenAddress, + sessionedContractAddress: currentContractAddress, }, ]); setIsSuccessful(true); @@ -249,7 +258,7 @@ const QueryTokenGeneralInfomation = ({ baseContract }: PageProps) => { {/* transaction results table */} - {transactionResults.length > 0 && ( + {transactionResultsToShow.length > 0 && ( { const [APIMethods, setAPIMethods] = useState('ALLOWANCE'); const [currentTransactionPage, setCurrentTransactionPage] = useState(1); const [tokenInfoFromTxResult, setTokenInfoFromTxResult] = useState(); + const currentContractAddress = Cookies.get(CONTRACT_NAMES.TOKEN_QUERY) as string; const [transactionResults, setTransactionResults] = useState([]); const [APIMethodsFromTxResult, setAPIMethodsFromTxResult] = useState('ALLOWANCE'); const transactionResultStorageKey = @@ -107,6 +109,11 @@ const QueryTokenPermissionInfomation = ({ baseContract }: PageProps) => { GET_APPROVED: 'ApprovedAddress', }; + const transactionResultsToShow = useFilterTransactionsByContractAddress( + transactionResults, + currentContractAddress + ); + /** @dev retrieve token creation results from localStorage to maintain data on re-renders */ useEffect(() => { handleRetrievingTransactionResultsFromLocalStorage( @@ -118,7 +125,7 @@ const QueryTokenPermissionInfomation = ({ baseContract }: PageProps) => { }, [toaster, transactionResultStorageKey]); // declare a paginatedTransactionResults - const paginatedTransactionResults = usePaginatedTxResults(currentTransactionPage, transactionResults); + const paginatedTransactionResults = usePaginatedTxResults(currentTransactionPage, transactionResultsToShow); /** @dev handle form inputs on change */ const handleInputOnChange = (e: any, param: string) => { @@ -169,8 +176,9 @@ const QueryTokenPermissionInfomation = ({ baseContract }: PageProps) => { setTransactionResults, err: tokenInfoResult.err, tokenAddress: paramValues.hederaTokenAddress, - transactionHash: tokenInfoResult.transactionHash, transactionType: `HTS-${API.replace('_', '-')}`, + transactionHash: tokenInfoResult.transactionHash, + sessionedContractAddress: currentContractAddress, }); return; } else { @@ -193,8 +201,9 @@ const QueryTokenPermissionInfomation = ({ baseContract }: PageProps) => { tokenInfo: cachedTokenInfo, transactionTimeStamp: Date.now(), tokenAddress: paramValues.hederaTokenAddress, - txHash: tokenInfoResult.transactionHash as string, transactionType: `HTS-${API.replace('_', '-')}`, + sessionedContractAddress: currentContractAddress, + txHash: tokenInfoResult.transactionHash as string, }, ]); @@ -264,7 +273,7 @@ const QueryTokenPermissionInfomation = ({ baseContract }: PageProps) => { {/* transaction results table */} - {transactionResults.length > 0 && ( + {transactionResultsToShow.length > 0 && ( { // general states const toaster = useToast(); const [isSuccessful, setIsSuccessful] = useState(false); + const tokenCommonFields = ['hederaTokenAddress', 'accountAddress']; const hederaNetwork = JSON.parse(Cookies.get('_network') as string); const [currentTransactionPage, setCurrentTransactionPage] = useState(1); + const currentContractAddress = Cookies.get(CONTRACT_NAMES.TOKEN_QUERY) as string; const [transactionResults, setTransactionResults] = useState([]); const transactionResultStorageKey = HEDERA_TRANSACTION_RESULT_STORAGE_KEYS['TOKEN-QUERY']['TOKEN-STATUS-INFO']; @@ -58,7 +61,6 @@ const QueryTokenStatusInfomation = ({ baseContract }: PageProps) => { accountAddress: '', }; const [paramValues, setParamValues] = useState(initialParamValues); - const tokenCommonFields = ['hederaTokenAddress', 'accountAddress']; const APIButtonTitles: { API: API_NAMES; apiSwitchTitle: string; executeTitle: any }[] = [ { API: 'IS_KYC', @@ -82,6 +84,11 @@ const QueryTokenStatusInfomation = ({ baseContract }: PageProps) => { IS_FROZEN: 'Frozen', }; + const transactionResultsToShow = useFilterTransactionsByContractAddress( + transactionResults, + currentContractAddress + ); + /** @dev retrieve token creation results from localStorage to maintain data on re-renders */ useEffect(() => { handleRetrievingTransactionResultsFromLocalStorage( @@ -93,7 +100,7 @@ const QueryTokenStatusInfomation = ({ baseContract }: PageProps) => { }, [toaster, transactionResultStorageKey]); // declare a paginatedTransactionResults - const paginatedTransactionResults = usePaginatedTxResults(currentTransactionPage, transactionResults); + const paginatedTransactionResults = usePaginatedTxResults(currentTransactionPage, transactionResultsToShow); /** @dev handle form inputs on change */ const handleInputOnChange = (e: any, param: string) => { @@ -151,6 +158,7 @@ const QueryTokenStatusInfomation = ({ baseContract }: PageProps) => { tokenAddress: paramValues.hederaTokenAddress, transactionType: `HTS-${API.replace('_', '-')}`, transactionHash: tokenInfoResult.transactionHash, + sessionedContractAddress: currentContractAddress, }); return; } else { @@ -164,6 +172,7 @@ const QueryTokenStatusInfomation = ({ baseContract }: PageProps) => { accountAddress: paramValues.accountAddress, tokenAddress: paramValues.hederaTokenAddress, transactionType: `HTS-${API.replace('_', '-')}`, + sessionedContractAddress: currentContractAddress, txHash: tokenInfoResult.transactionHash as string, tokenInfo: Number(tokenInfoResult[eventMaps[API]]), }, @@ -230,7 +239,7 @@ const QueryTokenStatusInfomation = ({ baseContract }: PageProps) => { {/* transaction results table */} - {transactionResults.length > 0 && ( + {transactionResultsToShow.length > 0 && ( { const [paramValues, setParamValues] = useState(initialParamValues); const hederaNetwork = JSON.parse(Cookies.get('_network') as string); const [currentTransactionPage, setCurrentTransactionPage] = useState(1); - const transactionResultStorageKey = HEDERA_TRANSACTION_RESULT_STORAGE_KEYS['TOKEN-QUERY']['TOKEN-VALIDITY']; + const currentContractAddress = Cookies.get(CONTRACT_NAMES.TOKEN_QUERY) as string; const [transactionResults, setTransactionResults] = useState([]); + const transactionResultStorageKey = HEDERA_TRANSACTION_RESULT_STORAGE_KEYS['TOKEN-QUERY']['TOKEN-VALIDITY']; + const transactionResultsToShow = useFilterTransactionsByContractAddress( + transactionResults, + currentContractAddress + ); /** @dev retrieve token creation results from localStorage to maintain data on re-renders */ useEffect(() => { @@ -67,7 +74,7 @@ const QueryTokenValidity = ({ baseContract }: PageProps) => { }, [toaster, transactionResultStorageKey]); // declare a paginatedTransactionResults - const paginatedTransactionResults = usePaginatedTxResults(currentTransactionPage, transactionResults); + const paginatedTransactionResults = usePaginatedTxResults(currentTransactionPage, transactionResultsToShow); /** @dev handle form inputs on change */ const handleInputOnChange = (e: any, param: string) => { @@ -106,6 +113,7 @@ const QueryTokenValidity = ({ baseContract }: PageProps) => { setTransactionResults, transactionType: 'HTS-IS-TOKEN', tokenAddress: paramValues.hederaTokenAddress, + sessionedContractAddress: currentContractAddress, }); return; } else { @@ -119,6 +127,7 @@ const QueryTokenValidity = ({ baseContract }: PageProps) => { txHash: transactionHash as string, transactionTimeStamp: Date.now(), tokenAddress: paramValues.hederaTokenAddress, + sessionedContractAddress: currentContractAddress, }, ]); @@ -169,7 +178,7 @@ const QueryTokenValidity = ({ baseContract }: PageProps) => { {/* transaction results table */} - {transactionResults.length > 0 && ( + {transactionResultsToShow.length > 0 && ( { const hederaNetwork = JSON.parse(Cookies.get('_network') as string); const [currentTransactionPage, setCurrentTransactionPage] = useState(1); const contractCaller = JSON.parse(Cookies.get('_connectedAccounts') as string)[0]; + const currentContractAddress = Cookies.get(CONTRACT_NAMES.TOKEN_TRANSFER) as string; const [transactionResults, setTransactionResults] = useState([]); - const transactionResultStorageKey = - HEDERA_TRANSACTION_RESULT_STORAGE_KEYS['TOKEN-TRANSFER']['CRYPTO-TRANSFER']; const [tokenTransferParamValues, setTokenTransferParamValues] = useState([]); const [cryptoTransferParamValues, setCryptoTransferParamValues] = useState([]); + const transactionResultStorageKey = + HEDERA_TRANSACTION_RESULT_STORAGE_KEYS['TOKEN-TRANSFER']['CRYPTO-TRANSFER']; + const transactionResultsToShow = useFilterTransactionsByContractAddress( + transactionResults, + currentContractAddress + ); /** @dev retrieve token creation results from localStorage to maintain data on re-renders */ useEffect(() => { @@ -246,6 +252,7 @@ const CryptoTransfer = ({ baseContract }: PageProps) => { transactionHash, setTransactionResults, transactionType: 'HTS-CRYPTO-TRANSFER', + sessionedContractAddress: currentContractAddress, }); return; } else { @@ -257,6 +264,7 @@ const CryptoTransfer = ({ baseContract }: PageProps) => { transactionTimeStamp: Date.now(), txHash: transactionHash as string, transactionType: 'HTS-CRYPTO-TRANSFER', + sessionedContractAddress: currentContractAddress, }, ]); @@ -314,7 +322,7 @@ const CryptoTransfer = ({ baseContract }: PageProps) => { {/* transaction results table */} - {transactionResults.length > 0 && ( + {transactionResultsToShow.length > 0 && ( { // general states const toaster = useToast(); - const [isLoading, setIsLoading] = useState({ - FUNGIBLE: false, - NON_FUNGIBLE: false, - }); const [isSuccessful, setIsSuccessful] = useState(false); const hederaNetwork = JSON.parse(Cookies.get('_network') as string); const [APIMethods, setAPIMethods] = useState('FUNGIBLE'); const [currentTransactionPage, setCurrentTransactionPage] = useState(1); const contractCaller = JSON.parse(Cookies.get('_connectedAccounts') as string)[0]; + const currentContractAddress = Cookies.get(CONTRACT_NAMES.TOKEN_TRANSFER) as string; const [transactionResults, setTransactionResults] = useState([]); + const [isLoading, setIsLoading] = useState({ + FUNGIBLE: false, + NON_FUNGIBLE: false, + }); const transactionResultStorageKey = HEDERA_TRANSACTION_RESULT_STORAGE_KEYS['TOKEN-TRANSFER']['MULTIPLE-TOKENS']; const tokenCommonFields = useMemo(() => { @@ -100,6 +102,11 @@ const TransferMultipleTokens = ({ baseContract }: PageProps) => { generateInitialNonFungibleParamValue(), ]); + const transactionResultsToShow = useFilterTransactionsByContractAddress( + transactionResults, + currentContractAddress + ); + /** @dev retrieve token creation results from localStorage to maintain data on re-renders */ useEffect(() => { handleRetrievingTransactionResultsFromLocalStorage( @@ -111,7 +118,7 @@ const TransferMultipleTokens = ({ baseContract }: PageProps) => { }, [toaster, transactionResultStorageKey]); // declare a paginatedTransactionResults - const paginatedTransactionResults = usePaginatedTxResults(currentTransactionPage, transactionResults); + const paginatedTransactionResults = usePaginatedTxResults(currentTransactionPage, transactionResultsToShow); /** @dev handle modifying transfer records */ const handleModifyTransferRecords = ( @@ -235,6 +242,7 @@ const TransferMultipleTokens = ({ baseContract }: PageProps) => { setTransactionResults, err: transactionResult.err, transactionType: 'HTS-TOKENS-TRANSFER', + sessionedContractAddress: currentContractAddress, tokenAddress: commonParamValues.hederaTokenAddress, transactionHash: transactionResult.transactionHash, }); @@ -248,6 +256,7 @@ const TransferMultipleTokens = ({ baseContract }: PageProps) => { status: 'success', transactionTimeStamp: Date.now(), transactionType: 'HTS-TOKENS-TRANSFER', + sessionedContractAddress: currentContractAddress, tokenAddress: commonParamValues.hederaTokenAddress, txHash: transactionResult.transactionHash as string, }, @@ -389,7 +398,7 @@ const TransferMultipleTokens = ({ baseContract }: PageProps) => { {/* transaction results table */} - {transactionResults.length > 0 && ( + {transactionResultsToShow.length > 0 && ( { const [isSuccessful, setIsSuccessful] = useState(false); const hederaNetwork = JSON.parse(Cookies.get('_network') as string); const [currentTransactionPage, setCurrentTransactionPage] = useState(1); - const transactionResultStorageKey = - HEDERA_TRANSACTION_RESULT_STORAGE_KEYS['TOKEN-TRANSFER']['SINGLE-TOKEN']; + const currentContractAddress = Cookies.get(CONTRACT_NAMES.TOKEN_TRANSFER) as string; const [transactionResults, setTransactionResults] = useState([]); const tokenInfoFields = ['hederaTokenAddress', 'senderAddress', 'receiverAddress', 'quantity', 'feeValue']; + const transactionResultStorageKey = + HEDERA_TRANSACTION_RESULT_STORAGE_KEYS['TOKEN-TRANSFER']['SINGLE-TOKEN']; const [isLoading, setIsLoading] = useState({ NFT: false, FUNGIBLE: false, @@ -74,6 +76,11 @@ const TransferSingleToken = ({ baseContract }: PageProps) => { }; const [paramValues, setParamValues] = useState(initialParamValues); + const transactionResultsToShow = useFilterTransactionsByContractAddress( + transactionResults, + currentContractAddress + ); + /** @dev retrieve token creation results from localStorage to maintain data on re-renders */ useEffect(() => { handleRetrievingTransactionResultsFromLocalStorage( @@ -85,7 +92,7 @@ const TransferSingleToken = ({ baseContract }: PageProps) => { }, [toaster, transactionResultStorageKey]); // declare a paginatedTransactionResults - const paginatedTransactionResults = usePaginatedTxResults(currentTransactionPage, transactionResults); + const paginatedTransactionResults = usePaginatedTxResults(currentTransactionPage, transactionResultsToShow); /** @dev handle form inputs on change */ const handleInputOnChange = (e: any, param: string) => { @@ -142,6 +149,7 @@ const TransferSingleToken = ({ baseContract }: PageProps) => { accountAddress: senderAddress, transactionType: 'HTS-TOKEN-TRANSFER', tokenAddress: paramValues.hederaTokenAddress, + sessionedContractAddress: currentContractAddress, }); return; } else { @@ -157,6 +165,7 @@ const TransferSingleToken = ({ baseContract }: PageProps) => { txHash: transactionHash as string, transactionType: 'HTS-TOKEN-TRANSFER', tokenAddress: paramValues.hederaTokenAddress, + sessionedContractAddress: currentContractAddress, }, ]); @@ -225,7 +234,7 @@ const TransferSingleToken = ({ baseContract }: PageProps) => { {/* transaction results table */} - {transactionResults.length > 0 && ( + {transactionResultsToShow.length > 0 && ( { toaster, transactionHash, setTransactionResults, + sessionedContractAddress: '', transactionType: `IHRC719-${API}`, tokenAddress: paramValues.hederaTokenAddress, }); @@ -132,6 +133,7 @@ const HederaIHRC719Methods = ({ network }: PageProps) => { ...prev, { status: 'success', + sessionedContractAddress: '', transactionTimeStamp: Date.now(), txHash: transactionHash as string, transactionType: `IHRC719-${API}`, diff --git a/system-contract-dapp-playground/src/components/contract-interaction/index.tsx b/system-contract-dapp-playground/src/components/contract-interaction/index.tsx index 43d00c5cf..a02323652 100644 --- a/system-contract-dapp-playground/src/components/contract-interaction/index.tsx +++ b/system-contract-dapp-playground/src/components/contract-interaction/index.tsx @@ -21,11 +21,13 @@ import Link from 'next/link'; import Image from 'next/image'; import { Contract } from 'ethers'; +import { BsTrash } from 'react-icons/bs'; import HederaPRNGMethods from './prng/methods'; -import ERC20Methods from './erc/erc-20/methods'; import { FiExternalLink } from 'react-icons/fi'; -import HederaIHRC719Methods from './ihrc/methods'; +import ERC20Methods from './erc/erc-20/methods'; +import ConfirmModal from '../common/ConfirmModal'; import ERC721Methods from './erc/erc-721/methods'; +import HederaIHRC719Methods from './ihrc/methods'; import { deploySmartContract } from '@/api/hedera'; import HederaAlertDialog from '../common/AlertDialog'; import { useCallback, useEffect, useState } from 'react'; @@ -34,21 +36,13 @@ import ERC20DeployField from './erc/deployment/ERCDeployField'; import { HederaContractAsset, NetworkName } from '@/types/common'; import { getHederaNativeIDFromEvmAddress } from '@/api/mirror-node'; import { CommonErrorToast, NoWalletToast } from '../toast/CommonToast'; -import { getInfoFromCookies, storeInfoInCookies } from '@/api/cookies'; import { convertCalmelCaseFunctionName } from '@/utils/common/helpers'; import HederaTokenCreateMethods from './hts/token-create-custom/methods'; import HederaTokenQueryMethods from './hts/token-query-contract/methods'; import HederaTokenTransferMethods from './hts/token-transfer-contract/method'; import HederaTokenManagementMethods from './hts/token-management-contract/methods'; +import { getInfoFromCookies, removeCookieAt, storeInfoInCookies } from '@/api/cookies'; import ExchangeRateDeployField from './exchange-rate-hip-475/deployment/ExchangeRateDeployField'; -import { - HASHSCAN_BASE_URL, - OFFCIAL_NETWORK_NAME, - HEDERA_BRANDING_COLORS, - HEDERA_CHAKRA_TABLE_VARIANTS, - HEDERA_SMART_CONTRACTS_ASSETS, - HEDERA_COMMON_WALLET_REVERT_REASONS, -} from '@/utils/common/constants'; import { Tab, Tabs, @@ -58,9 +52,20 @@ import { TabPanel, useToast, TabPanels, + useDisclosure, PopoverContent, PopoverTrigger, } from '@chakra-ui/react'; +import { + CONTRACT_NAMES, + HASHSCAN_BASE_URL, + OFFCIAL_NETWORK_NAME, + HEDERA_BRANDING_COLORS, + HEDERA_CHAKRA_TABLE_VARIANTS, + HEDERA_COMMON_WALLET_REVERT_REASONS, + CONTRACT_NAME_TO_STORAGE_KEY_VALUE, +} from '@/utils/common/constants'; +import { clearCachedTransactions } from '@/api/localStorage'; interface PageProps { contract: HederaContractAsset; @@ -70,6 +75,7 @@ const ContractInteraction = ({ contract }: PageProps) => { const toaster = useToast(); const [mounted, setMounted] = useState(false); const [contractId, setContractId] = useState(''); + const { isOpen, onOpen, onClose } = useDisclosure(); const [isDeployed, setIsDeployed] = useState(false); const [isDeploying, setIsDeploying] = useState(false); const [network, setNetwork] = useState(); @@ -213,6 +219,24 @@ const ContractInteraction = ({ contract }: PageProps) => { })(); }, [network, contractAddress, toaster]); + // handle removing contract instance + const handleRemoveContractInstance = () => { + // close the modal + onClose(); + + // remove contract record in cookies + removeCookieAt(contract.name); + + // remove all readonly transactions + clearCachedTransactions(CONTRACT_NAME_TO_STORAGE_KEY_VALUE[contract.name], true); + + // reset states + setContractId(''); + setIsDeployed(false); + setContractAddress(''); + setBaseContract(undefined); + }; + useEffect(() => setMounted(true), []); if (!mounted) return null; return ( @@ -223,7 +247,7 @@ const ContractInteraction = ({ contract }: PageProps) => { className="bg-panel rounded-xl max-w-4xl text-white border border-white/30 shadow-2xl text-lg" > {/* @notice TokenAssociation IHRC719 does not need to deploy */} - {isDeployed || contract.name === HEDERA_SMART_CONTRACTS_ASSETS.TOKEN_ASSOCIATION.name ? ( + {isDeployed || contract.name === CONTRACT_NAMES.IHRC719 ? ( <> {/* Tab headers */} { return ( {/* Contract information - not for IHRC729Contract*/} - {contract.name !== HEDERA_SMART_CONTRACTS_ASSETS.TOKEN_ASSOCIATION.name && ( + {contract.name !== CONTRACT_NAMES.IHRC719 && ( <> -
+
+ {/* remove contract instance button */} +
+ + + +
+ {/* Contract ID */}

Hedera contract ID:

@@ -345,12 +381,12 @@ const ContractInteraction = ({ contract }: PageProps) => { {/* Contract methods */}
{/* HTS Token Create */} - {contract.name === HEDERA_SMART_CONTRACTS_ASSETS.HTS_PRECOMPILED[0].name && ( + {contract.name === CONTRACT_NAMES.TOKEN_CREATE && ( )} {/* HTS Token Management*/} - {contract.name === HEDERA_SMART_CONTRACTS_ASSETS.HTS_PRECOMPILED[1].name && ( + {contract.name === CONTRACT_NAMES.TOKEN_MANAGE && ( { )} {/* HTS Token Query*/} - {contract.name === HEDERA_SMART_CONTRACTS_ASSETS.HTS_PRECOMPILED[2].name && ( + {contract.name === CONTRACT_NAMES.TOKEN_QUERY && ( )} {/* HTS Token Transfer*/} - {contract.name === HEDERA_SMART_CONTRACTS_ASSETS.HTS_PRECOMPILED[3].name && ( + {contract.name === CONTRACT_NAMES.TOKEN_TRANSFER && ( )} {/* IHRC719 contract */} - {contract.name === HEDERA_SMART_CONTRACTS_ASSETS.TOKEN_ASSOCIATION.name && ( + {contract.name === CONTRACT_NAMES.IHRC719 && ( )} {/* HRC contract */} - {contract.name === 'PrngSystemContract' && ( + {contract.name === CONTRACT_NAMES.PRNG && ( )} {/* ERC-20 */} - {contract.name === HEDERA_SMART_CONTRACTS_ASSETS.ERC_20.name && ( + {contract.name === CONTRACT_NAMES.ERC20 && ( )} {/* ERC-721 */} - {contract.name === HEDERA_SMART_CONTRACTS_ASSETS.ERC_721.name && ( + {contract.name === CONTRACT_NAMES.ERC721 && ( )}
@@ -398,7 +434,7 @@ const ContractInteraction = ({ contract }: PageProps) => {

Let's get started by deploying this contract first!

{/* ExchangeRate contract needs params to deploy */} - {contract.name === HEDERA_SMART_CONTRACTS_ASSETS.EXCHANGE_RATE.name && ( + {contract.name === CONTRACT_NAMES.EXCHANGE_RATE && ( { )} {/* ERC20 & ERC721 contract needs params to deploy */} - {(contract.name === HEDERA_SMART_CONTRACTS_ASSETS.ERC_20.name || - contract.name === HEDERA_SMART_CONTRACTS_ASSETS.ERC_721.name) && ( + {(contract.name === CONTRACT_NAMES.ERC20 || contract.name === CONTRACT_NAMES.ERC721) && ( { )} {/* Contracts other than ExchangeRate, ERC20, ERC20 does not need params to deploy */} - {contract.name !== HEDERA_SMART_CONTRACTS_ASSETS.EXCHANGE_RATE.name && - contract.name !== HEDERA_SMART_CONTRACTS_ASSETS.ERC_20.name && - contract.name !== HEDERA_SMART_CONTRACTS_ASSETS.ERC_721.name && ( + {contract.name !== CONTRACT_NAMES.EXCHANGE_RATE && + contract.name !== CONTRACT_NAMES.ERC20 && + contract.name !== CONTRACT_NAMES.ERC721 && (
{/* transaction results table */} - {transactionResults.length > 0 && ( + {transactionResultsToShow.length > 0 && ( { await clearCookies(); // clear localStorage cache - clearTransactionCache(); + clearCachedTransactions(); // redirect user to landing page setIsOpen(false); @@ -278,36 +270,20 @@ const WalletPopup = ({ setIsOpen, userAddress, network }: PageProps) => {

- - - - Sure to disconnect? - - - {/* break line */} -
- - -

- By completing this action, all the transactions you have made during this session will be - permanently erased from the DApp's cache, but they will still be accessible through - HashScan or other explorer solutions. -

-
- - - - -
-
+ + By completing this action, all the deployed smart contract instances and all the + transactions you have made during this session will be permanently erased from the + DApp's cache, but they will still be accessible through HashScan or other explorer + solutions. +

+ } + modalHeader={'Sure to disconnect?'} + handleAcknowledge={handleDisconnect} + />
diff --git a/system-contract-dapp-playground/src/types/contract-interactions/HTS/index.d.ts b/system-contract-dapp-playground/src/types/contract-interactions/HTS/index.d.ts index bc327234c..8c57b56dc 100644 --- a/system-contract-dapp-playground/src/types/contract-interactions/HTS/index.d.ts +++ b/system-contract-dapp-playground/src/types/contract-interactions/HTS/index.d.ts @@ -34,6 +34,7 @@ export type TransactionResult = { pseudoRandomSeed?: string; tokenAddresses?: string[]; transactionTimeStamp: number; + sessionedContractAddress: string; }; /** @dev an interface for the results returned back from interacting with Hedera System Smart Contracts */ diff --git a/system-contract-dapp-playground/src/utils/common/constants.ts b/system-contract-dapp-playground/src/utils/common/constants.ts index 9bdc04e7b..fe88f862a 100644 --- a/system-contract-dapp-playground/src/utils/common/constants.ts +++ b/system-contract-dapp-playground/src/utils/common/constants.ts @@ -180,6 +180,21 @@ export const LEFT_SIDE_BAR_ITEMS = [ }, ]; +/** + * @notice an object storing contract names + */ +export const CONTRACT_NAMES: Record = { + ERC20: 'ERC20Mock', + ERC721: 'ERC721Mock', + PRNG: 'PrngSystemContract', + IHRC719: 'IHRC729Contract', + TOKEN_QUERY: 'TokenQueryContract', + TOKEN_TRANSFER: 'TokenTransferContract', + EXCHANGE_RATE: 'ExchangeRatePrecompile', + TOKEN_MANAGE: 'TokenManagementContract', + TOKEN_CREATE: 'TokenCreateCustomContract', +}; + /** * @notice information about Hedera Smart Contract assets */ @@ -314,6 +329,21 @@ export const HEDERA_SHARED_PARAM_INPUT_FIELDS = { inputClassname: HEDERA_CHAKRA_INPUT_BOX_SHARED_CLASSNAME, }; +/** + * @notice a shared object maping contract name to storage key value + */ +export const CONTRACT_NAME_TO_STORAGE_KEY_VALUE: Record = { + ERC20Mock: 'ERC-20', + ERC721Mock: 'ERC-721', + IHRC729Contract: 'IHRC719', + PrngSystemContract: 'PRNG', + TokenQueryContract: 'TOKEN-QUERY', + TokenTransferContract: 'TOKEN-TRANSFER', + ExchangeRatePrecompile: 'EXCHANGE-RATE', + TokenManagementContract: 'TOKEN-MANAGE', + TokenCreateCustomContract: 'TOKEN-CREATE', +}; + /** * @notice a shared object stores all transaction result storage keys */ @@ -326,6 +356,7 @@ const prepareTransactionResultStorageKey = ( return `HEDERA.${contractKey}.${methodKey}.${resultKey}-RESULTS${readonly ? `.READONLY` : ``}`; }; export const HEDERA_TRANSACTION_RESULT_STORAGE_KEYS = { + 'CONTRACT-CREATE': 'HEDERA.CONTRACT-CREATE-RESULTS', 'TOKEN-CREATE': { 'TOKEN-KYC': prepareTransactionResultStorageKey('HTS', 'TOKEN-CREATE', 'TOKEN-KYC'), 'MINT-TOKEN': prepareTransactionResultStorageKey('HTS', 'TOKEN-CREATE', 'MINT-TOKEN'),