Skip to content

Commit

Permalink
feat: add My Contracts, Query and Execute tabs
Browse files Browse the repository at this point in the history
  • Loading branch information
marslavish committed Sep 12, 2024
1 parent e420c63 commit c904729
Show file tree
Hide file tree
Showing 8 changed files with 251 additions and 3 deletions.
17 changes: 17 additions & 0 deletions examples/chain-template/components/contract/EmptyState.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import Image from 'next/image';
import { Box, Text } from '@interchain-ui/react';

export const EmptyState = ({ text }: { text: string }) => (
<Box
display="flex"
justifyContent="center"
alignItems="center"
flexDirection="column"
gap="10px"
>
<Image alt="empty" src="/images/empty.svg" width="72" height="72" />
<Text color="$blackAlpha500" fontSize="16px" fontWeight="500">
{text}
</Text>
</Box>
);
19 changes: 19 additions & 0 deletions examples/chain-template/components/contract/ExecuteTab.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { Box, Text } from '@interchain-ui/react';

type ExecuteTabProps = {
show: boolean;
initialAddress: string;
clearInitAddress: () => void;
};

export const ExecuteTab = ({
show,
initialAddress,
clearInitAddress,
}: ExecuteTabProps) => {
return (
<Box display={show ? 'block' : 'none'}>
<Text>Execute Contract</Text>
</Box>
);
};
129 changes: 129 additions & 0 deletions examples/chain-template/components/contract/MyContractsTab.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
import { useState } from 'react';
import { useChain } from '@cosmos-kit/react';
import { Box, Icon, Spinner, Text } from '@interchain-ui/react';

import { useCopyToClipboard, useMyContracts } from '@/hooks';
import { Button, Table } from '../common';
import { shortenAddress } from '@/utils';
import { TabLabel } from '@/pages/contract';
import { EmptyState } from './EmptyState';
import { useChainStore } from '@/contexts';

type MyContractsTabProps = {
show: boolean;
switchTab: (initialAddress: string, tabId: number) => void;
};

export const MyContractsTab = ({ show, switchTab }: MyContractsTabProps) => {
const { selectedChain } = useChainStore();
const { address } = useChain(selectedChain);
const { data: myContracts = [], isLoading } = useMyContracts();

return (
<Box display={show ? 'block' : 'none'} maxWidth="900px" mt="40px" mx="auto">
<Text color="$blackAlpha600" fontSize="24px" fontWeight="700">
My contracts
</Text>
<Box
display="flex"
justifyContent="center"
alignItems="center"
minHeight="300px"
>
{!address ? (
<EmptyState text="Connect wallet to see your previously instantiated contracts." />
) : isLoading ? (
<Spinner size="$6xl" color="$blackAlpha600" />
) : myContracts.length === 0 ? (
<EmptyState text="No contracts found" />
) : (
<Box width="$full" alignSelf="start" overflowX="auto">
<Table minWidth="650px">
<Table.Header>
<Table.Row height="$fit">
<Table.HeaderCell width="15%">
Contract Address
</Table.HeaderCell>
<Table.HeaderCell width="20%">Contract Name</Table.HeaderCell>
<Table.HeaderCell width="10%">Code ID</Table.HeaderCell>
<Table.HeaderCell width="6%" />
</Table.Row>
</Table.Header>
<Table.Body>
{myContracts.map(({ address, contractInfo }) => (
<Table.Row key={address}>
<Table.Cell>
<CopyText
displayValue={shortenAddress(address)}
copyValue={address}
/>
</Table.Cell>
<Table.Cell>{contractInfo?.label}</Table.Cell>
<Table.Cell color="$blackAlpha500" fontWeight="500">
{Number(contractInfo?.codeId)}
</Table.Cell>
<Table.Cell>
<Box display="flex" gap="10px">
<Button
size="sm"
onClick={() => switchTab(address, TabLabel.Query)}
>
Query
</Button>
<Button
size="sm"
onClick={() => switchTab(address, TabLabel.Execute)}
>
Execute
</Button>
</Box>
</Table.Cell>
</Table.Row>
))}
</Table.Body>
</Table>
</Box>
)}
</Box>
</Box>
);
};

const CopyText = ({
copyValue,
displayValue,
}: {
displayValue: string;
copyValue: string;
}) => {
const [isHover, setIsHover] = useState(false);
const { copyToClipboard, isCopied } = useCopyToClipboard();

return (
<Box
display="flex"
alignItems="center"
gap="8px"
width="$fit"
cursor="pointer"
attributes={{
onMouseEnter: () => setIsHover(true),
onMouseLeave: () => setIsHover(false),
onClick: () => copyToClipboard(copyValue),
}}
>
<Text color="$blackAlpha600" fontSize="14px" fontWeight="600">
{displayValue}
</Text>
{isHover && (
<Box display="flex" transform="translateY(2px)">
<Icon
name={isCopied ? 'checkLine' : 'copy'}
color={isCopied ? '$green600' : '$blackAlpha500'}
size="$md"
/>
</Box>
)}
</Box>
);
};
19 changes: 19 additions & 0 deletions examples/chain-template/components/contract/QueryTab.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { Box, Text } from '@interchain-ui/react';

type QueryTabProps = {
show: boolean;
initialAddress: string;
clearInitAddress: () => void;
};

export const QueryTab = ({
show,
initialAddress,
clearInitAddress,
}: QueryTabProps) => {
return (
<Box display={show ? 'block' : 'none'}>
<Text>Query Contract</Text>
</Box>
);
};
3 changes: 3 additions & 0 deletions examples/chain-template/components/contract/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from './QueryTab';
export * from './ExecuteTab';
export * from './MyContractsTab';
1 change: 1 addition & 0 deletions examples/chain-template/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ export * from './common';
export * from './staking';
export * from './voting';
export * from './asset-list';
export * from './contract';
2 changes: 1 addition & 1 deletion examples/chain-template/hooks/contract/useStoreCodeTx.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export const useStoreCodeTx = (chainName: string) => {
});

const wasmCode = await wasmFile.arrayBuffer();
const wasmByteCode = await gzip(new Uint8Array(wasmCode));
const wasmByteCode = new Uint8Array(await gzip(new Uint8Array(wasmCode)));

const message = storeCode({
sender: address,
Expand Down
64 changes: 62 additions & 2 deletions examples/chain-template/pages/contract.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,65 @@
import { Box } from '@interchain-ui/react';
import { useEffect, useState } from 'react';
import { Box, Tabs } from '@interchain-ui/react';

import { ExecuteTab, MyContractsTab, QueryTab } from '@/components';
import { splitCamelCase } from '@/utils';
import styles from '@/styles/comp.module.css';

export enum TabLabel {
MyContracts,
Query,
Execute,
}

export default function Contract() {
return <Box>Contract</Box>;
const [activeTab, setActiveTab] = useState(TabLabel.MyContracts);
const [initQueryAddress, setInitQueryAddress] = useState('');
const [initExecuteAddress, setInitExecuteAddress] = useState('');

useEffect(() => {
if (activeTab !== TabLabel.Query) setInitQueryAddress('');
if (activeTab !== TabLabel.Execute) setInitExecuteAddress('');
}, [activeTab]);

const switchTabWithAddress = (address: string, tabId: TabLabel) => {
setActiveTab(tabId);
if (tabId === TabLabel.Query) setInitQueryAddress(address);
if (tabId === TabLabel.Execute) setInitExecuteAddress(address);
};

return (
<>
<Tabs
tabs={Object.values(TabLabel)
.filter((v) => typeof v === 'string')
.map((label) => ({
label: splitCamelCase(label as string),
content: undefined,
}))}
activeTab={activeTab}
onActiveTabChange={(tabId) => setActiveTab(tabId)}
className={styles.tabs}
/>
<Box mt="40px">
<MyContractsTab
show={activeTab === TabLabel.MyContracts}
switchTab={switchTabWithAddress}
/>
<QueryTab
show={activeTab === TabLabel.Query}
initialAddress={initQueryAddress}
clearInitAddress={() => {
if (initQueryAddress) setInitQueryAddress('');
}}
/>
<ExecuteTab
show={activeTab === TabLabel.Execute}
initialAddress={initExecuteAddress}
clearInitAddress={() => {
if (initExecuteAddress) setInitExecuteAddress('');
}}
/>
</Box>
</>
);
}

0 comments on commit c904729

Please sign in to comment.