diff --git a/system-contract-dapp-playground/src/components/contract-interaction/hts/shared/components/TokenGeneralInfoModal.tsx b/system-contract-dapp-playground/src/components/contract-interaction/hts/shared/components/TokenGeneralInfoModal.tsx new file mode 100644 index 000000000..5096de97b --- /dev/null +++ b/system-contract-dapp-playground/src/components/contract-interaction/hts/shared/components/TokenGeneralInfoModal.tsx @@ -0,0 +1,199 @@ +/*- + * + * 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 Link from 'next/link'; +import React, { Dispatch, SetStateAction } from 'react'; +import { convertCalmelCaseFunctionName } from '@/utils/common/helpers'; +import { prepareInfoValuesToShow } from '../methods/prepareInfoValuesToShow'; +import { + Tr, + Th, + Td, + Modal, + Table, + Tbody, + ModalBody, + ModalFooter, + ModalHeader, + ModalOverlay, + ModalContent, + TableContainer, + ModalCloseButton, +} from '@chakra-ui/react'; +import { + TOKEN_INFO_ADVANCED_KEYS, + TOKEN_INFO_BASIC_KEYS, + TOKEN_INFO_NFT_KEYS, +} from '@/utils/contract-interactions/HTS/token-query/constant'; + +interface PageProps { + tokenInfo: any; + isOpen: boolean; + onClose: () => void; + hederaNetwork: string; + initialParamValues?: any; + hederaTokenAddress: string; + setTokenInfo?: Dispatch; + setParamValues?: Dispatch; + setShowToken?: Dispatch>; + setIsSuccessful?: Dispatch>; + APIMethods: 'TOKEN' | 'FUNGIBLE' | 'NON_FUNFIBLE'; +} + +const TokenGeneralInfoModal = ({ + isOpen, + onClose, + tokenInfo, + APIMethods, + setTokenInfo, + setShowToken, + hederaNetwork, + setParamValues, + setIsSuccessful, + initialParamValues, + hederaTokenAddress, +}: PageProps) => { + const commonBasicKeysTokenInfo = + APIMethods === 'TOKEN' ? tokenInfo.token : tokenInfo.tokenInfo.token; + + const commonAdvancedKeysTokenInfo = APIMethods === 'TOKEN' ? tokenInfo : tokenInfo.tokenInfo; + + return ( + { + onClose(); + if (setTokenInfo) setTokenInfo({}); + if (setShowToken) setShowToken(false); + if (setIsSuccessful) setIsSuccessful(false); + if (setParamValues) setParamValues(initialParamValues); + }} + isCentered + > + + + {/* title */} + Token Information + + + {/* break line */} +
+ + {/* body */} + + + + + {/* basic keys */} + {TOKEN_INFO_BASIC_KEYS.map((key) => { + const keyToShow = convertCalmelCaseFunctionName(key); + const valueToShow = prepareInfoValuesToShow(key, commonBasicKeysTokenInfo); + + return ( + + + + + ); + })} + + {/* advanced keys */} + {TOKEN_INFO_ADVANCED_KEYS.map((key) => { + const keyToShow = convertCalmelCaseFunctionName(key); + const valueToShow = prepareInfoValuesToShow(key, commonAdvancedKeysTokenInfo); + + return ( + + + + + ); + })} + + {/* Fungible extra keys */} + {APIMethods === 'FUNGIBLE' && ( + + + + + )} + + {/* Non-Fungible extra keys */} + {APIMethods === 'NON_FUNFIBLE' && + TOKEN_INFO_NFT_KEYS.map((key) => { + const keyToShow = convertCalmelCaseFunctionName(key); + const valueToShow = prepareInfoValuesToShow(key, tokenInfo); + return ( + + + + + ); + })} + +
{keyToShow} + {valueToShow} +
{keyToShow} + {valueToShow} +
Decimals + {tokenInfo.decimals.toString()} +
{keyToShow} + {valueToShow} +
+
+ + {/* tip */} +

+ **note: For a more comprehensive view of this token's information,{' '} + + explore it on HashScan + + . +

+
+ + {/* footer */} + + + +
+
+ ); +}; + +export default TokenGeneralInfoModal; diff --git a/system-contract-dapp-playground/src/components/contract-interaction/hts/shared/components/TransactionResultTable.tsx b/system-contract-dapp-playground/src/components/contract-interaction/hts/shared/components/TransactionResultTable.tsx index 5ccf57a01..af72a07d9 100644 --- a/system-contract-dapp-playground/src/components/contract-interaction/hts/shared/components/TransactionResultTable.tsx +++ b/system-contract-dapp-playground/src/components/contract-interaction/hts/shared/components/TransactionResultTable.tsx @@ -24,42 +24,61 @@ import { FiExternalLink } from 'react-icons/fi'; import { AiOutlineMinus } from 'react-icons/ai'; import { Dispatch, SetStateAction } from 'react'; import { MdNavigateBefore, MdNavigateNext } from 'react-icons/md'; -import { TransactionResult } from '@/types/contract-interactions/HTS'; +import { IHederaTokenServiceKeyType, TransactionResult } from '@/types/contract-interactions/HTS'; import { - TableContainer, - Table, - Thead, Tr, Th, - Tbody, Td, + Table, + Thead, + Tbody, Popover, - PopoverTrigger, Tooltip, + TableContainer, + PopoverTrigger, PopoverContent, } from '@chakra-ui/react'; /** @dev shared component representing the list of transactions */ interface TransactionResultTablePageProps { + onOpen?: () => void; hederaNetwork: string; TRANSACTION_PAGE_SIZE: number; currentTransactionPage: number; transactionResultStorageKey: string; transactionResults: TransactionResult[]; + setTokenInfoFromTxResult?: Dispatch; paginatedTransactionResults: TransactionResult[]; + setShowTokenInfo?: Dispatch>; + setAPIMethodsFromTxResult?: Dispatch>; setCurrentTransactionPage: Dispatch>; + setTokenAddressFromTxResult?: Dispatch>; setTransactionResults: Dispatch>; - API: 'TokenCreate' | 'TokenMint' | 'TokenAssociate' | 'GrantKYC' | 'QueryValidity'; + setKeyTypeFromTxResult?: Dispatch>; + API: + | 'TokenCreate' + | 'TokenMint' + | 'TokenAssociate' + | 'GrantKYC' + | 'QueryValidity' + | 'QueryTokenGeneralInfo' + | 'QuerySpecificInfo'; } export const TransactionResultTable = ({ API, + onOpen, hederaNetwork, + setShowTokenInfo, transactionResults, - TRANSACTION_PAGE_SIZE, setTransactionResults, + TRANSACTION_PAGE_SIZE, currentTransactionPage, + setKeyTypeFromTxResult, + setTokenInfoFromTxResult, + setAPIMethodsFromTxResult, setCurrentTransactionPage, + setTokenAddressFromTxResult, transactionResultStorageKey, paginatedTransactionResults, }: TransactionResultTablePageProps) => { @@ -70,11 +89,13 @@ export const TransactionResultTable = ({ endingHashIndex = -12; break; case 'TokenMint': + case 'QuerySpecificInfo': + case 'QueryTokenGeneralInfo': beginingHashIndex = 8; endingHashIndex = -4; break; - case 'TokenAssociate': case 'GrantKYC': + case 'TokenAssociate': case 'QueryValidity': beginingHashIndex = 10; endingHashIndex = -5; @@ -96,6 +117,12 @@ export const TransactionResultTable = ({ {API === 'TokenAssociate' && Associated Account} {API === 'GrantKYC' && KYCed Account} {API === 'QueryValidity' && Valid Token} + {(API === 'QueryTokenGeneralInfo' || API === 'QuerySpecificInfo') && ( + Token Info + )} + {(API === 'QueryTokenGeneralInfo' || API === 'QuerySpecificInfo') && ( + API called + )} @@ -179,7 +206,9 @@ export const TransactionResultTable = ({ {(API === 'TokenCreate' || API === 'TokenMint' || API === 'GrantKYC' || - API === 'QueryValidity') && ( + API === 'QueryValidity' || + API === 'QueryTokenGeneralInfo' || + API === 'QuerySpecificInfo') && ( {transactionResult.tokenAddress ? (
@@ -403,6 +432,57 @@ export const TransactionResultTable = ({ )} + {/* query - token info */} + {(API === 'QueryTokenGeneralInfo' || API === 'QuerySpecificInfo') && ( + +
+ {transactionResult.tokenInfo ? ( +
{ + onOpen!(); + if (setShowTokenInfo) setShowTokenInfo(true); + if (setTokenInfoFromTxResult) + setTokenInfoFromTxResult(transactionResult.tokenInfo); + if (setAPIMethodsFromTxResult) + setAPIMethodsFromTxResult(transactionResult.APICalled); + if (setKeyTypeFromTxResult) + setKeyTypeFromTxResult(transactionResult.keyTypeCalled); + if (setTokenAddressFromTxResult) + setTokenAddressFromTxResult(transactionResult.tokenAddress as string); + }} + > +
+ +

Token Info

+
+
+
+ ) : ( + <>NULL + )} +
+ + )} + + {/* query - API called */} + {(API === 'QueryTokenGeneralInfo' || API === 'QuerySpecificInfo') && ( + + {transactionResult.APICalled ? ( + <> +

+ {transactionResult.APICalled === 'TOKEN_KEYS' + ? `${transactionResult.APICalled.replace('TOKEN_', '')}_${ + transactionResult.keyTypeCalled + }` + : transactionResult.APICalled} +

+ + ) : ( + <>NULL + )} + + )} + {/* delete button */} 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 3133eb366..0f872bb4e 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,12 +20,14 @@ import { Dispatch, SetStateAction } from 'react'; import { CommonErrorToast } from '@/components/toast/CommonToast'; -import { TransactionResult } from '@/types/contract-interactions/HTS'; +import { IHederaTokenServiceKeyType, TransactionResult } from '@/types/contract-interactions/HTS'; /** @dev handle error returned back from invoking method APIs*/ export const handleAPIErrors = ({ err, toaster, + keyTypeCalled, + APICalled, tokenAddress, tokenAddresses, accountAddress, @@ -34,10 +36,12 @@ export const handleAPIErrors = ({ }: { err: any; toaster: any; - accountAddress?: string; + APICalled?: string; tokenAddress?: string; + accountAddress?: string; tokenAddresses?: string[]; transactionHash: string | undefined; + keyTypeCalled?: IHederaTokenServiceKeyType; setTransactionResults: Dispatch>; }) => { const errorMessage = JSON.stringify(err); @@ -56,12 +60,14 @@ export const handleAPIErrors = ({ setTransactionResults((prev) => [ ...prev, { + APICalled, + keyTypeCalled, status: 'fail', + isToken: false, txHash: transactionHash, tokenAddress: tokenAddress ? tokenAddress : '', accountAddress: accountAddress ? accountAddress : '', tokenAddresses: tokenAddresses ? tokenAddresses : [''], - isToken: false, }, ]); diff --git a/system-contract-dapp-playground/src/components/contract-interaction/hts/shared/methods/handleSanitizeFormInputs.tsx b/system-contract-dapp-playground/src/components/contract-interaction/hts/shared/methods/handleSanitizeFormInputs.tsx index ddc04b1af..69587df12 100644 --- a/system-contract-dapp-playground/src/components/contract-interaction/hts/shared/methods/handleSanitizeFormInputs.tsx +++ b/system-contract-dapp-playground/src/components/contract-interaction/hts/shared/methods/handleSanitizeFormInputs.tsx @@ -59,7 +59,8 @@ interface ParamsProps { | 'WIPE_FUNGIBLE' | 'WIPE_NON_FUNGIBLE' | 'BURN' - | 'DELETE'; + | 'DELETE' + | 'QueryTokenInfo'; } /** @dev handle sanitizing Hedera token form inputs */ export const handleSanitizeHederaFormInputs = ({ @@ -276,6 +277,10 @@ export const handleSanitizeHederaFormInputs = ({ } else if (feeValue === '') { sanitizeErr = 'Gas limit should be set for this transaction'; } + } else if (API === 'QueryTokenInfo') { + if (!isAddress(hederaTokenAddress)) { + sanitizeErr = 'Invalid token address'; + } } return sanitizeErr; diff --git a/system-contract-dapp-playground/src/components/contract-interaction/hts/shared/methods/prepareInfoValuesToShow.tsx b/system-contract-dapp-playground/src/components/contract-interaction/hts/shared/methods/prepareInfoValuesToShow.tsx new file mode 100644 index 000000000..95107abba --- /dev/null +++ b/system-contract-dapp-playground/src/components/contract-interaction/hts/shared/methods/prepareInfoValuesToShow.tsx @@ -0,0 +1,42 @@ +/*- + * + * 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 { isAddress } from 'ethers'; + +/** + * @dev prepare value to show inside token info modals based on tokenInfo + */ +export const prepareInfoValuesToShow = (key: string, tokenInfo: any) => { + let valueToShow; + if (!tokenInfo) return 'N/A'; + + if (isAddress(tokenInfo[key])) { + valueToShow = `${tokenInfo[key].slice(0, 6)}...${tokenInfo[key].slice(-6)}`; + } else if (tokenInfo[key] === '') { + valueToShow = 'N/A'; + } else if (typeof tokenInfo[key] === 'bigint') { + valueToShow = tokenInfo[key].toString(); + } else if (typeof tokenInfo[key] === 'boolean') { + valueToShow = JSON.stringify(tokenInfo[key]); + } else { + valueToShow = tokenInfo[key]; + } + return valueToShow; +}; diff --git a/system-contract-dapp-playground/src/components/contract-interaction/hts/shared/states/commonStates.ts b/system-contract-dapp-playground/src/components/contract-interaction/hts/shared/states/commonStates.ts index 28d03d616..7882759ed 100644 --- a/system-contract-dapp-playground/src/components/contract-interaction/hts/shared/states/commonStates.ts +++ b/system-contract-dapp-playground/src/components/contract-interaction/hts/shared/states/commonStates.ts @@ -36,6 +36,8 @@ export const HederaTokenKeyTypes: IHederaTokenServiceKeyType[] = [ 'FEE', 'PAUSE', ]; + +// key value types export const HederaTokenKeyValueType: IHederaTokenServiceKeyValueType[] = [ 'inheritAccountKey', 'contractId', diff --git a/system-contract-dapp-playground/src/components/contract-interaction/hts/token-query-contract/methods/index.tsx b/system-contract-dapp-playground/src/components/contract-interaction/hts/token-query-contract/methods/index.tsx index 9e83826fd..3064a441b 100644 --- a/system-contract-dapp-playground/src/components/contract-interaction/hts/token-query-contract/methods/index.tsx +++ b/system-contract-dapp-playground/src/components/contract-interaction/hts/token-query-contract/methods/index.tsx @@ -20,6 +20,7 @@ import { Contract } from 'ethers'; import QueryTokenValidity from './queryTokenValidity'; +import QueryTokenGeneralInfomation from './queryTokenGeneralInfo'; interface PageProps { method: string; @@ -29,11 +30,11 @@ interface PageProps { const HederaTokenQueryMethods = ({ baseContract, method }: PageProps) => { return ( <> - {method === 'tokenValidity' && } - {method === 'generalInfo' && <>generalInfo} {method === 'specificInfo' && <>specificInfo} - {method === 'tokenPermission' && <>tokenPermission} {method === 'tokenRelation' && <>tokenRelation} + {method === 'tokenPermission' && <>tokenPermission} + {method === 'tokenValidity' && } + {method === 'generalInfo' && } ); }; diff --git a/system-contract-dapp-playground/src/components/contract-interaction/hts/token-query-contract/methods/queryTokenGeneralInfo/index.tsx b/system-contract-dapp-playground/src/components/contract-interaction/hts/token-query-contract/methods/queryTokenGeneralInfo/index.tsx new file mode 100644 index 000000000..b453124c7 --- /dev/null +++ b/system-contract-dapp-playground/src/components/contract-interaction/hts/token-query-contract/methods/queryTokenGeneralInfo/index.tsx @@ -0,0 +1,294 @@ +/*- + * + * 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 Cookies from 'js-cookie'; +import { Contract } from 'ethers'; +import { useEffect, useMemo, useState } from 'react'; +import { useDisclosure, useToast } from '@chakra-ui/react'; +import { CommonErrorToast } from '@/components/toast/CommonToast'; +import { TransactionResult } from '@/types/contract-interactions/HTS'; +import { handleAPIErrors } from '../../../shared/methods/handleAPIErrors'; +import { TRANSACTION_PAGE_SIZE } from '../../../shared/states/commonStates'; +import { queryTokenGeneralInfomation } from '@/api/hedera/tokenQuery-interactions'; +import { usePaginatedTxResults } from '../../../shared/hooks/usePaginatedTxResults'; +import TokenGeneralInfoModal from '../../../shared/components/TokenGeneralInfoModal'; +import { TransactionResultTable } from '../../../shared/components/TransactionResultTable'; +import { handleSanitizeHederaFormInputs } from '../../../shared/methods/handleSanitizeFormInputs'; +import { htsQueryTokenInfoParamFields } from '@/utils/contract-interactions/HTS/token-query/constant'; +import { useUpdateTransactionResultsToLocalStorage } from '../../../shared/hooks/useUpdateLocalStorage'; +import { handleRetrievingTransactionResultsFromLocalStorage } from '../../../shared/methods/handleRetrievingTransactionResultsFromLocalStorage'; +import { + SharedExecuteButton, + SharedFormButton, + SharedFormInputField, +} from '../../../shared/components/ParamInputForm'; + +interface PageProps { + baseContract: Contract; +} + +type API_NAMES = 'TOKEN' | 'FUNGIBLE' | 'NON_FUNFIBLE'; +type EVENT_NAMES = 'TokenInfo' | 'FungibleTokenInfo' | 'NonFungibleTokenInfo'; + +const QueryTokenGeneralInfomation = ({ baseContract }: PageProps) => { + // general states + const toaster = useToast(); + const [isLoading, setIsLoading] = useState(false); + const [tokenInfo, setTokenInfo] = useState(); + const { isOpen, onOpen, onClose } = useDisclosure(); + const [isSuccessful, setIsSuccessful] = useState(false); + const [showTokenInfo, setShowTokenInfo] = useState(false); + const [APIMethods, setAPIMethods] = useState('TOKEN'); + const hederaNetwork = JSON.parse(Cookies.get('_network') as string); + const [currentTransactionPage, setCurrentTransactionPage] = useState(1); + const [tokenInfoFromTxResult, setTokenInfoFromTxResult] = useState(); + const [tokenAddressFromTxResult, setTokenAddressFromTxResult] = useState(''); + const [transactionResults, setTransactionResults] = useState([]); + const transactionResultStorageKey = 'HEDERA.HTS.TOKEN-QUERY.TOKEN-GENERAL-INFO-RESULTS'; + const [APIMethodsFromTxResult, setAPIMethodsFromTxResult] = useState('TOKEN'); + const initialParamValues = { + serialNumber: '', + hederaTokenAddress: '', + }; + const [paramValues, setParamValues] = useState(initialParamValues); + const tokenCommonFields = useMemo(() => { + if (APIMethods === 'NON_FUNFIBLE') { + return ['hederaTokenAddress', 'serialNumber']; + } else { + return ['hederaTokenAddress']; + } + }, [APIMethods]); + + // prepare events map + const eventMaps: Record = { + TOKEN: 'TokenInfo', + FUNGIBLE: 'FungibleTokenInfo', + NON_FUNFIBLE: 'NonFungibleTokenInfo', + }; + + const APIButtonTitles: { API: API_NAMES; apiSwitchTitle: string; executeTitle: any }[] = [ + { + API: 'TOKEN', + apiSwitchTitle: 'Token Info', + executeTitle: 'Query General Token Info', + }, + { + API: 'FUNGIBLE', + apiSwitchTitle: 'Fungible Info', + executeTitle: 'Query Fungible Token Info', + }, + { + API: 'NON_FUNFIBLE', + apiSwitchTitle: 'Non-Fungible Info', + executeTitle: 'Query Non-Fungible Token Info', + }, + ]; + + /** @dev retrieve token creation results from localStorage to maintain data on re-renders */ + useEffect(() => { + handleRetrievingTransactionResultsFromLocalStorage( + toaster, + transactionResultStorageKey, + setCurrentTransactionPage, + setTransactionResults + ); + }, [toaster]); + + // declare a paginatedTransactionResults + const paginatedTransactionResults = usePaginatedTxResults( + currentTransactionPage, + transactionResults + ); + + /** @dev handle form inputs on change */ + const handleInputOnChange = (e: any, param: string) => { + setParamValues((prev: any) => ({ ...prev, [param]: e.target.value })); + }; + + /** @dev handle invoking the API to interact with smart contract and query token info */ + /** @NOTICE WILL COME BACK SOON */ + const handleQueryTokenInfo = async (API: API_NAMES) => { + // destructuring param values + const { hederaTokenAddress, serialNumber } = paramValues; + + // sanitize params + const sanitizeErr = handleSanitizeHederaFormInputs({ + API: 'QueryTokenInfo', + hederaTokenAddress, + serialNumber, + }); + + // toast error if any param is invalid + if (sanitizeErr) { + CommonErrorToast({ toaster, title: 'Invalid parameters', description: sanitizeErr }); + return; + } + + // turn is loading on + setIsLoading(true); + + // invoking method API + const { transactionHash, err, ...tokenInfoResult } = await queryTokenGeneralInfomation( + baseContract, + API, + hederaTokenAddress, + serialNumber + ); + + // turn is loading off + setIsLoading(false); + + // handle err + if (err) { + handleAPIErrors({ + toaster, + err: err, + setTransactionResults, + transactionHash: transactionHash, + tokenAddress: paramValues.hederaTokenAddress, + }); + return; + } else { + setTokenInfo(tokenInfoResult[eventMaps[API]]); + + setTransactionResults((prev) => [ + ...prev, + { + APICalled: API, + status: 'sucess', + txHash: transactionHash as string, + tokenAddress: paramValues.hederaTokenAddress, + tokenInfo: tokenInfoResult[eventMaps[API]], + }, + ]); + setIsSuccessful(true); + onOpen(); + } + }; + + /** @dev listen to change event on transactionResults state => load to localStorage */ + useUpdateTransactionResultsToLocalStorage(transactionResults, transactionResultStorageKey); + + return ( +
+ {/* Query token form */} +
+ {/* API methods */} +
+ {APIButtonTitles.map((APIButton) => ( +
+ setAPIMethods(APIButton.API)} + /> +
+ ))} +
+ + {/* hederaTokenAddress & targetApprovedAddress */} + {tokenCommonFields.map((param) => { + return ( +
+ +
+ ); + })} + + {/* Execute buttons */} + {APIButtonTitles.map((APIButton) => { + if (APIMethods === APIButton.API) { + return ( +
+ handleQueryTokenInfo(APIButton.API)} + buttonTitle={APIButton.executeTitle} + /> +
+ ); + } + })} +
+ + {/* transaction results table */} + {transactionResults.length > 0 && ( + + )} + + {/* token info popup - after done calling the API */} + {isSuccessful && ( + + )} + + {/* token info popup - by clicking on the `Token Info` from transaction Result table*/} + {showTokenInfo && !isSuccessful && ( + + )} +
+ ); +}; + +export default QueryTokenGeneralInfomation; diff --git a/system-contract-dapp-playground/src/utils/contract-interactions/HTS/token-query/constant.ts b/system-contract-dapp-playground/src/utils/contract-interactions/HTS/token-query/constant.ts new file mode 100644 index 000000000..c3272bf43 --- /dev/null +++ b/system-contract-dapp-playground/src/utils/contract-interactions/HTS/token-query/constant.ts @@ -0,0 +1,162 @@ +/*- + * + * 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. + * + */ + +/** @notice an object holding information for the tokenRelation's input fields */ +export const htsQueryTokenInfoParamFields = { + hederaTokenAddress: { + inputType: 'text', + inputPlaceholder: 'Token address...', + inputSize: 'md', + inputFocusBorderColor: '#A98DF4', + inputClassname: 'w-full border-white/30', + paramKey: 'hederaTokenAddress', + explanation: 'represents the Hedera Token for querying', + }, + serialNumber: { + inputType: 'number', + inputPlaceholder: 'Serial number...', + inputSize: 'md', + inputFocusBorderColor: '#A98DF4', + inputClassname: 'w-full border-white/30', + paramKey: 'serialNumber', + explanation: "represents the NFT's serial number to be queried", + }, +}; + +/** @notice an object holding information for the queryTokenPermission's input fields */ +export const htsQueryTokenPermissionParamFields = { + hederaTokenAddress: { + inputType: 'text', + inputPlaceholder: 'Token address...', + inputSize: 'md', + inputFocusBorderColor: '#A98DF4', + inputClassname: 'w-full border-white/30', + paramKey: 'hederaTokenAddress', + explanation: 'represents the Hedera Token for querying', + }, + serialNumber: { + inputType: 'number', + inputPlaceholder: 'Serial number...', + inputSize: 'md', + inputFocusBorderColor: '#A98DF4', + inputClassname: 'w-full border-white/30', + paramKey: 'serialNumber', + explanation: "represents the NFT's serial number to be queried", + }, + ownerAddress: { + inputType: 'string', + inputPlaceholder: 'Owner address...', + inputSize: 'md', + inputFocusBorderColor: '#A98DF4', + inputClassname: 'w-full border-white/30', + paramKey: 'ownerAddress', + explanation: "represents the address of the token's owner", + }, + spenderAddress: { + inputType: 'string', + inputPlaceholder: 'Spender/Operator address...', + inputSize: 'md', + inputFocusBorderColor: '#A98DF4', + inputClassname: 'w-full border-white/30', + paramKey: 'spenderAddress', + explanation: 'represents the spender or operator address', + }, +}; + +/** @notice an object holding information for the queryTokenInfo's input fields */ +export const htsQueryTokenRelationParamFields = { + hederaTokenAddress: { + inputType: 'text', + inputPlaceholder: 'Token address...', + inputSize: 'md', + inputFocusBorderColor: '#A98DF4', + inputClassname: 'w-full border-white/30', + paramKey: 'hederaTokenAddress', + explanation: 'represents the Hedera Token for querying', + }, + accountAddress: { + inputType: 'text', + inputPlaceholder: 'Account address...', + inputSize: 'md', + inputFocusBorderColor: '#A98DF4', + inputClassname: 'w-full border-white/30', + paramKey: 'accountAddress', + explanation: 'represents the account address to check status against', + }, +}; + +export const TOKEN_INFO_BASIC_KEYS = [ + 'name', + 'symbol', + 'treasury', + 'memo', + 'tokenSupplyType', + 'maxSupply', + 'freezeDefault', +]; +export const TOKEN_INFO_ADVANCED_KEYS = [ + 'totalSupply', + 'deleted', + 'defaultKycStatus', + 'pauseStatus', + 'ledgerId', +]; +export const TOKEN_INFO_NFT_KEYS = [ + 'serialNumber', + 'ownerId', + 'creationTime', + 'metadata', + 'spenderId', +]; + +type CustomFeeKeys = 'fixedFees' | 'fractionalFees' | 'royaltyFees'; +export const CUSTOM_FEES_KEYS: CustomFeeKeys[] = ['fixedFees', 'fractionalFees', 'royaltyFees']; + +export const FIXED_FEES_KEYS = [ + 'amount', + 'tokenId', + 'useHbarsForPayment', + 'useCurrentTokenForPayment', + 'feeCollector', +]; +export const FRACTIONAL_FEES_KEYS = [ + 'numerator', + 'denominator', + 'minimumAmount', + 'maximumAmount', + 'netOfTransfers', + 'feeCollector', +]; +export const ROYALTY_FEES_KEYS = [ + 'numerator', + 'denominator', + 'amount', + 'tokenId', + 'useHbarsForPayment', + 'feeCollector', +]; +export const KEY_VALUE_KEYS = [ + 'inheritAccountKey', + 'contractId', + 'ed25519', + 'ECDSA_secp256k1', + 'delegatableContractId', +]; +export const EXPIRY_KEYS = ['second', 'autoRenewAccount', 'autoRenewPeriod'];