Skip to content

Commit

Permalink
dapp-feat: QueryTokenPermission feature complete (#318) (#377)
Browse files Browse the repository at this point in the history
Signed-off-by: Logan Nguyen <[email protected]>
  • Loading branch information
quiet-node authored Sep 7, 2023
1 parent 2d37a7f commit d4394d7
Show file tree
Hide file tree
Showing 6 changed files with 498 additions and 16 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
/*-
*
* 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 { Dispatch, SetStateAction } from 'react';
import { convertCalmelCaseFunctionName } from '@/utils/common/helpers';
import {
Tr,
Th,
Td,
Modal,
Table,
Tbody,
ModalBody,
ModalFooter,
ModalHeader,
ModalOverlay,
ModalContent,
TableContainer,
ModalCloseButton,
} from '@chakra-ui/react';

interface PageProps {
APIMethods: 'ALLOWANCE' | 'GET_APPROVED' | 'IS_APPROVAL';
tokenInfo: any;
eventMaps: any;
isOpen: boolean;
onClose: () => void;
initialParamValues?: any;
setTokenInfo?: Dispatch<any>;
setParamValues?: Dispatch<any>;
setIsSuccessful?: Dispatch<SetStateAction<boolean>>;
}

const TokenPermissionInfoModal = ({
APIMethods,
tokenInfo,
isOpen,
onClose,
setTokenInfo,
eventMaps,
setParamValues,
setIsSuccessful,
initialParamValues,
}: PageProps) => {
return (
<Modal
isOpen={isOpen}
onClose={() => {
onClose();
if (setTokenInfo) setTokenInfo({});
if (setIsSuccessful) setIsSuccessful(false);
if (setParamValues) setParamValues(initialParamValues);
}}
isCentered
size={'3xl'}
>
<ModalOverlay />
<ModalContent
className="h-fit flex flex-col gap-3 rounded-xl drop-shadow-xl
bg-secondary text-white font-styrene w-[30rem]"
>
{/* title */}
<ModalHeader>Token Information</ModalHeader>
<ModalCloseButton />

{/* break line */}
<hr className="border-t border-white/40 -mt-3" />

{/* body */}
<ModalBody>
<TableContainer className="overflow-x-hidden">
<Table variant="simple" size={'sm'}>
<Tbody>
<Tr>
<Th color={'#82ACF9'}>{convertCalmelCaseFunctionName(eventMaps[APIMethods])}</Th>
{APIMethods === 'GET_APPROVED' && (
<Td className="flex justify-end">
{`${tokenInfo.slice(0, 6)}...${tokenInfo.slice(-6)}`}
</Td>
)}
{APIMethods === 'IS_APPROVAL' && (
<Td className="flex justify-end">
{JSON.stringify(tokenInfo === 1).toUpperCase()}
</Td>
)}
{APIMethods === 'ALLOWANCE' && <Td className="flex justify-end">{tokenInfo}</Td>}
</Tr>
</Tbody>
</Table>
</TableContainer>
</ModalBody>

{/* footer */}
<ModalFooter className="flex flex-col gap-3">
<button
onClick={() => {
onClose();
if (setTokenInfo) setTokenInfo({});
if (setIsSuccessful) setIsSuccessful(false);
if (setParamValues) setParamValues(initialParamValues);
}}
className="border border-button-stroke-violet px-6 py-2 rounded-lg font-medium hover:bg-button-stroke-violet hover:text-white transition duration-300"
>
Acknowledge
</button>
</ModalFooter>
</ModalContent>
</Modal>
);
};

export default TokenPermissionInfoModal;
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,14 @@ interface TransactionResultTablePageProps {
setTransactionResults: Dispatch<SetStateAction<TransactionResult[]>>;
setKeyTypeFromTxResult?: Dispatch<SetStateAction<IHederaTokenServiceKeyType>>;
API:
| 'TokenCreate'
| 'TokenMint'
| 'TokenAssociate'
| 'GrantKYC'
| 'TokenMint'
| 'TokenCreate'
| 'QueryValidity'
| 'TokenAssociate'
| 'QuerySpecificInfo'
| 'QueryTokenGeneralInfo'
| 'QuerySpecificInfo';
| 'QueryTokenPermission';
}

export const TransactionResultTable = ({
Expand Down Expand Up @@ -92,6 +93,7 @@ export const TransactionResultTable = ({
case 'TokenMint':
case 'QuerySpecificInfo':
case 'QueryTokenGeneralInfo':
case 'QueryTokenPermission':
beginingHashIndex = 8;
endingHashIndex = -4;
break;
Expand Down Expand Up @@ -120,10 +122,14 @@ export const TransactionResultTable = ({
)}
{API === 'GrantKYC' && <Th color={HEDERA_BRANDING_COLORS.violet}>KYCed Account</Th>}
{API === 'QueryValidity' && <Th color={HEDERA_BRANDING_COLORS.violet}>Valid Token</Th>}
{(API === 'QueryTokenGeneralInfo' || API === 'QuerySpecificInfo') && (
{(API === 'QueryTokenGeneralInfo' ||
API === 'QuerySpecificInfo' ||
API === 'QueryTokenPermission') && (
<Th color={HEDERA_BRANDING_COLORS.violet}>Token Info</Th>
)}
{(API === 'QueryTokenGeneralInfo' || API === 'QuerySpecificInfo') && (
{(API === 'QueryTokenGeneralInfo' ||
API === 'QuerySpecificInfo' ||
API === 'QueryTokenPermission') && (
<Th color={HEDERA_BRANDING_COLORS.violet}>API called</Th>
)}
<Th />
Expand Down Expand Up @@ -211,7 +217,8 @@ export const TransactionResultTable = ({
API === 'GrantKYC' ||
API === 'QueryValidity' ||
API === 'QueryTokenGeneralInfo' ||
API === 'QuerySpecificInfo') && (
API === 'QuerySpecificInfo' ||
API === 'QueryTokenPermission') && (
<Td className="cursor-pointer">
{transactionResult.tokenAddress ? (
<div className="flex gap-1 items-center">
Expand Down Expand Up @@ -436,10 +443,12 @@ export const TransactionResultTable = ({
)}

{/* query - token info */}
{(API === 'QueryTokenGeneralInfo' || API === 'QuerySpecificInfo') && (
{(API === 'QueryTokenGeneralInfo' ||
API === 'QuerySpecificInfo' ||
API === 'QueryTokenPermission') && (
<Td className="cursor-pointer">
<div className="flex gap-1 items-center">
{transactionResult.tokenInfo ? (
{typeof transactionResult.tokenInfo !== 'undefined' ? (
<div
onClick={() => {
onOpen!();
Expand Down Expand Up @@ -468,7 +477,9 @@ export const TransactionResultTable = ({
)}

{/* query - API called */}
{(API === 'QueryTokenGeneralInfo' || API === 'QuerySpecificInfo') && (
{(API === 'QueryTokenGeneralInfo' ||
API === 'QuerySpecificInfo' ||
API === 'QueryTokenPermission') && (
<Td>
{transactionResult.APICalled ? (
<>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ interface ParamsProps {
maxSupply?: string;
initSupply?: string;
serialNumber?: string;
ownerAddress?: string;
spenderAddress?: string;
withCustomFee?: boolean;
accountAddress?: string;
feeTokenAddress?: string;
Expand Down Expand Up @@ -60,7 +62,11 @@ interface ParamsProps {
| 'WIPE_NON_FUNGIBLE'
| 'BURN'
| 'DELETE'
| 'QueryTokenInfo';
| 'QueryTokenInfo'
| 'QueryTokenInfo'
| 'ALLOWANCE'
| 'GET_APPROVED'
| 'IS_APPROVAL';
}
/** @dev handle sanitizing Hedera token form inputs */
export const handleSanitizeHederaFormInputs = ({
Expand All @@ -75,8 +81,10 @@ export const handleSanitizeHederaFormInputs = ({
feeValue,
maxSupply,
initSupply,
ownerAddress,
serialNumber,
withCustomFee,
spenderAddress,
accountAddress,
feeTokenAddress,
autoRenewPeriod,
Expand Down Expand Up @@ -281,6 +289,20 @@ export const handleSanitizeHederaFormInputs = ({
if (!isAddress(hederaTokenAddress)) {
sanitizeErr = 'Invalid token address';
}
} else if (API === 'ALLOWANCE' || API === 'IS_APPROVAL') {
if (!isAddress(hederaTokenAddress)) {
sanitizeErr = 'Invalid token address';
} else if (!isAddress(ownerAddress)) {
sanitizeErr = 'Invalid owner address';
} else if (!isAddress(spenderAddress)) {
sanitizeErr = 'Invalid spender address';
}
} else if (API === 'GET_APPROVED') {
if (!isAddress(hederaTokenAddress)) {
sanitizeErr = 'Invalid token address';
} else if (serialNumber === '' || Number(serialNumber) < 0) {
sanitizeErr = 'Invalid serial number';
}
}

return sanitizeErr;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { Contract } from 'ethers';
import QueryTokenValidity from './queryTokenValidity';
import QueryTokenSpecificInfomation from './querySpecificToken';
import QueryTokenGeneralInfomation from './queryTokenGeneralInfo';
import QueryTokenPermissionInfomation from './queryTokenPermission';

interface PageProps {
method: string;
Expand All @@ -32,12 +33,12 @@ const HederaTokenQueryMethods = ({ baseContract, method }: PageProps) => {
return (
<>
{method === 'tokenRelation' && <>tokenRelation</>}
{method === 'tokenRelation' && <>tokenRelation</>}
{method === 'tokenPermission' && <>tokenPermission</>}
{method === 'tokenPermission' && <>tokenPermission</>}
{method === 'tokenValidity' && <QueryTokenValidity baseContract={baseContract} />}
{method === 'generalInfo' && <QueryTokenGeneralInfomation baseContract={baseContract} />}
{method === 'specificInfo' && <QueryTokenSpecificInfomation baseContract={baseContract} />}
{method === 'tokenPermission' && (
<QueryTokenPermissionInfomation baseContract={baseContract} />
)}
</>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,10 @@ const QueryTokenSpecificInfomation = ({ baseContract }: PageProps) => {
const [showTokenInfo, setShowTokenInfo] = useState(false);
const hederaNetwork = JSON.parse(Cookies.get('_network') as string);
const [currentTransactionPage, setCurrentTransactionPage] = useState(1);
const [APIMethods, setAPIMethods] = useState<API_NAMES>('DEFAULT_FREEZE_STATUS');
const [tokenInfoFromTxResult, setTokenInfoFromTxResult] = useState<any>();
const [keyType, setKeyType] = useState<IHederaTokenServiceKeyType>('ADMIN');
const [tokenAddressFromTxResult, setTokenAddressFromTxResult] = useState('');
const [APIMethods, setAPIMethods] = useState<API_NAMES>('DEFAULT_FREEZE_STATUS');
const [transactionResults, setTransactionResults] = useState<TransactionResult[]>([]);
const transactionResultStorageKey = 'HEDERA.HTS.TOKEN-QUERY.TOKEN-SPECIFIC-INFO-RESULTS';
const [APIMethodsFromTxResult, setAPIMethodsFromTxResult] =
Expand Down Expand Up @@ -148,7 +148,7 @@ const QueryTokenSpecificInfomation = ({ baseContract }: PageProps) => {
setParamValues((prev: any) => ({ ...prev, [param]: e.target.value }));
};

/** @dev handle invoking the API to interact with smart contract and update token relation */
/** @dev handle invoking the API to interact with smart contract and query token info */
const handleQuerySpecificInfo = async (API: API_NAMES) => {
// sanitize params
if (!isAddress(paramValues.hederaTokenAddress)) {
Expand Down
Loading

0 comments on commit d4394d7

Please sign in to comment.