diff --git a/CHANGELOG.md b/CHANGELOG.md index dd3ab922d..1ab983154 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,6 +39,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Features +- [#98](https://github.com/alleslabs/celatone-frontend/pull/98) Add migrate, update admin, clear admin menu on contract list and detail +- [#121](https://github.com/alleslabs/celatone-frontend/pull/121) Fix code snippet for query axios - [#102](https://github.com/alleslabs/celatone-frontend/pull/102) Add quick menu in overview and add highlighted in left sidebar - [#125](https://github.com/alleslabs/celatone-frontend/pull/125) Add connect wallet alert in instantiate page - [#126](https://github.com/alleslabs/celatone-frontend/pull/126) Add port id copier for IBC port id diff --git a/src/lib/app-fns/tx/clearAdmin.tsx b/src/lib/app-fns/tx/clearAdmin.tsx new file mode 100644 index 000000000..52e0a156a --- /dev/null +++ b/src/lib/app-fns/tx/clearAdmin.tsx @@ -0,0 +1,72 @@ +import { Icon } from "@chakra-ui/react"; +import type { + SigningCosmWasmClient, + ChangeAdminResult, +} from "@cosmjs/cosmwasm-stargate"; +import type { StdFee } from "@cosmjs/stargate"; +import { pipe } from "@rx-stream/pipe"; +import { MdCheckCircle } from "react-icons/md"; +import type { Observable } from "rxjs"; + +import { ExplorerLink } from "lib/components/ExplorerLink"; +import { TxStreamPhase } from "lib/types"; +import type { TxResultRendering, ContractAddr } from "lib/types"; +import { formatUFee } from "lib/utils"; + +import { catchTxError } from "./common/catchTxError"; +import { postTx } from "./common/post"; +import { sendingTx } from "./common/sending"; + +interface ClearAdminTxParams { + address: string; + contractAddress: ContractAddr; + fee: StdFee; + memo?: string; + client: SigningCosmWasmClient; + onTxSucceed?: (txHash: string) => void; +} + +export const clearAdminTx = ({ + address, + contractAddress, + fee, + memo, + client, + onTxSucceed, +}: ClearAdminTxParams): Observable => { + return pipe( + sendingTx(fee), + postTx({ + postFn: () => client.clearAdmin(address, contractAddress, fee, memo), + }), + ({ value: txInfo }) => { + onTxSucceed?.(txInfo.transactionHash); + return { + value: null, + phase: TxStreamPhase.SUCCEED, + receipts: [ + { + title: "Tx Hash", + value: txInfo.transactionHash, + html: ( + + ), + }, + { + title: "Tx Fee", + value: `${formatUFee( + txInfo.events.find((e) => e.type === "tx")?.attributes[0].value ?? + "0u" + )}`, + }, + ], + receiptInfo: { + header: "Transaction Complete", + headerIcon: ( + + ), + }, + } as TxResultRendering; + } + )().pipe(catchTxError()); +}; diff --git a/src/lib/app-provider/tx/clearAdmin.ts b/src/lib/app-provider/tx/clearAdmin.ts new file mode 100644 index 000000000..601538350 --- /dev/null +++ b/src/lib/app-provider/tx/clearAdmin.ts @@ -0,0 +1,34 @@ +import { useWallet } from "@cosmos-kit/react"; +import { useCallback } from "react"; + +import { useFabricateFee } from "../hooks"; +import { clearAdminTx } from "lib/app-fns/tx/clearAdmin"; +import { CLEAR_ADMIN_GAS } from "lib/data"; +import type { ContractAddr } from "lib/types"; + +export interface ClearAdminStreamParams { + onTxSucceed?: (txHash: string) => void; +} + +export const useClearAdminTx = (contractAddress: ContractAddr) => { + const { address, getCosmWasmClient } = useWallet(); + const fabricateFee = useFabricateFee(); + const clearAdminFee = fabricateFee(CLEAR_ADMIN_GAS); + + return useCallback( + async ({ onTxSucceed }: ClearAdminStreamParams) => { + const client = await getCosmWasmClient(); + if (!address || !client) + throw new Error("Please check your wallet connection."); + + return clearAdminTx({ + address, + contractAddress, + fee: clearAdminFee, + client, + onTxSucceed, + }); + }, + [address, clearAdminFee, contractAddress, getCosmWasmClient] + ); +}; diff --git a/src/lib/app-provider/tx/index.ts b/src/lib/app-provider/tx/index.ts index 8f7fec410..de35b0c2e 100644 --- a/src/lib/app-provider/tx/index.ts +++ b/src/lib/app-provider/tx/index.ts @@ -1,2 +1,5 @@ export * from "./upload"; export * from "./resend"; +export * from "./clearAdmin"; +export * from "./execute"; +export * from "./instantiate"; diff --git a/src/lib/components/button/AdminButton.tsx b/src/lib/components/button/AdminButton.tsx new file mode 100644 index 000000000..22883b6bc --- /dev/null +++ b/src/lib/components/button/AdminButton.tsx @@ -0,0 +1,102 @@ +import { + Button, + chakra, + Icon, + Menu, + MenuButton, + MenuItem, + MenuList, + Tooltip, +} from "@chakra-ui/react"; +import { useWallet } from "@cosmos-kit/react"; +import { + MdKeyboardArrowDown, + MdPerson, + MdPersonRemove, + MdReadMore, +} from "react-icons/md"; + +import { ClearAdminContract } from "../modal/contract/ClearAdminContract"; +import { useInternalNavigate } from "lib/app-provider"; +import type { ContractAddr, HumanAddr, Option } from "lib/types"; + +const StyledMenuItem = chakra(MenuItem, { + baseStyle: { + fontSize: "14px", + }, +}); + +const StyledIcon = chakra(Icon, { + baseStyle: { + boxSize: "4", + display: "flex", + alignItems: "center", + }, +}); + +interface AdminButtonProps { + contractAddress: ContractAddr; + admin: Option; +} + +export const AdminButton = ({ contractAddress, admin }: AdminButtonProps) => { + const { address } = useWallet(); + const navigate = useInternalNavigate(); + + const isAdmin = !!address && address === admin; + return ( + + + } + > + Admin + + + + } + onClick={() => { + navigate({ + pathname: "/migrate", + query: { contract: contractAddress }, + }); + }} + > + Migrate + + } + onClick={() => { + navigate({ + pathname: "/admin", + query: { contract: contractAddress }, + }); + }} + > + Update Admin + + } + > + Clear Admin + + } + /> + + + ); +}; diff --git a/src/lib/components/button/index.ts b/src/lib/components/button/index.ts index 5bd24bce8..2833e104d 100644 --- a/src/lib/components/button/index.ts +++ b/src/lib/components/button/index.ts @@ -1,3 +1,5 @@ export * from "./BackButton"; export * from "./ConnectWallet"; +export * from "./InstantiateButton"; export * from "./ShowMoreButton"; +export * from "./AdminButton"; diff --git a/src/lib/components/modal/ActionModal.tsx b/src/lib/components/modal/ActionModal.tsx index 09f29367c..a3bb4f68a 100644 --- a/src/lib/components/modal/ActionModal.tsx +++ b/src/lib/components/modal/ActionModal.tsx @@ -28,9 +28,11 @@ export interface ActionModalProps { children?: ReactNode; mainBtnTitle?: string; mainAction: () => void; + mainVariant?: string; disabledMain?: boolean; otherBtnTitle?: string; otherAction?: () => void; + otherVariant?: string; noHeaderBorder?: boolean; noCloseButton?: boolean; } @@ -44,9 +46,11 @@ export function ActionModal({ children, mainBtnTitle = "Proceed", mainAction, + mainVariant = "primary", disabledMain = false, otherBtnTitle = "Cancel", otherAction, + otherVariant = "outline-primary", noHeaderBorder = false, noCloseButton = false, }: ActionModalProps) { @@ -93,15 +97,12 @@ export function ActionModal({ - diff --git a/src/lib/components/modal/contract/ClearAdminContract.tsx b/src/lib/components/modal/contract/ClearAdminContract.tsx new file mode 100644 index 000000000..1644d903d --- /dev/null +++ b/src/lib/components/modal/contract/ClearAdminContract.tsx @@ -0,0 +1,45 @@ +import { Text } from "@chakra-ui/react"; +import { useCallback } from "react"; +import { MdDeleteForever } from "react-icons/md"; + +import { ActionModal } from "../ActionModal"; +import { useClearAdminTx } from "lib/app-provider"; +import { useTxBroadcast } from "lib/providers/tx-broadcast"; +import type { ContractAddr } from "lib/types"; + +interface ClearAdminContractProps { + contractAddress: ContractAddr; + triggerElement: JSX.Element; +} + +export const ClearAdminContract = ({ + contractAddress, + triggerElement, +}: ClearAdminContractProps) => { + const { broadcast } = useTxBroadcast(); + const clearAdminTx = useClearAdminTx(contractAddress); + + const proceed = useCallback(async () => { + const stream = await clearAdminTx({ onTxSucceed: () => {} }); + if (stream) broadcast(stream); + }, [broadcast, clearAdminTx]); + + return ( + + + Clearing the admin is a permanent action. You'll not be able to + reassign an admin and migrations will no longer be possible. + + + ); +}; diff --git a/src/lib/data/constant.ts b/src/lib/data/constant.ts index 318accb79..bbdc666c3 100644 --- a/src/lib/data/constant.ts +++ b/src/lib/data/constant.ts @@ -56,7 +56,9 @@ export const DEFAULT_ADDRESS = "default-address"; export const MAX_FILE_SIZE = 800_000; -export const MICRO = 1000000; +export const CLEAR_ADMIN_GAS = 50_000; + +export const MICRO = 1_000_000; export const typeUrlDict = { [MsgType.STORE_CODE]: "/cosmwasm.wasm.v1.MsgStoreCode", diff --git a/src/lib/data/queries.ts b/src/lib/data/queries.ts index 5c4198906..5a15c6fa0 100644 --- a/src/lib/data/queries.ts +++ b/src/lib/data/queries.ts @@ -130,6 +130,19 @@ export const getInstantiateDetailByContractQueryDocument = graphql(` } `); +export const getAdminByContractAddressesQueryDocument = graphql(` + query getAdminByContractAddressesQueryDocument( + $contractAddresses: [String!]! + ) { + contracts(where: { address: { _in: $contractAddresses } }) { + address + admin: account { + address + } + } + } +`); + export const getExecuteTxsByContractAddress = graphql(` query getExecuteTxsByContractAddress( $contractAddress: String! @@ -278,6 +291,9 @@ export const getContractListByCodeId = graphql(` ) { address label + admin: account { + address + } init_by: contract_histories( order_by: { block: { timestamp: asc } } limit: 1 diff --git a/src/lib/gql/gql.ts b/src/lib/gql/gql.ts index 82d9d4ae4..db3703f43 100644 --- a/src/lib/gql/gql.ts +++ b/src/lib/gql/gql.ts @@ -17,6 +17,8 @@ const documents = { types.GetInstantiatedListByUserQueryDocumentDocument, '\n query getInstantiateDetailByContractQueryDocument($contractAddress: String!) {\n contracts_by_pk(address: $contractAddress) {\n init_msg\n transaction {\n hash\n }\n contract_proposals(\n where: {\n proposal: {\n type: {\n _in: [\n "InstantiateContract"\n "InstantiateContract2"\n "SoftwareUpgrade"\n ]\n }\n }\n }\n order_by: { proposal: { id: asc } }\n limit: 1\n ) {\n proposal {\n id\n title\n }\n }\n }\n }\n': types.GetInstantiateDetailByContractQueryDocumentDocument, + "\n query getAdminByContractAddressesQueryDocument(\n $contractAddresses: [String!]!\n ) {\n contracts(where: { address: { _in: $contractAddresses } }) {\n address\n admin: account {\n address\n }\n }\n }\n": + types.GetAdminByContractAddressesQueryDocumentDocument, "\n query getExecuteTxsByContractAddress(\n $contractAddress: String!\n $offset: Int!\n $pageSize: Int!\n ) {\n contract_transactions(\n where: {\n contract: { address: { _eq: $contractAddress } }\n transaction: { is_execute: { _eq: true } }\n }\n order_by: { transaction: { block: { timestamp: desc } } }\n limit: $pageSize\n offset: $offset\n ) {\n transaction {\n hash\n messages\n success\n account {\n address\n }\n block {\n height\n timestamp\n }\n }\n }\n }\n": types.GetExecuteTxsByContractAddressDocument, "\n query getExecuteTxsCountByContractAddress($contractAddress: String!) {\n contract_transactions_aggregate(\n where: {\n contract: { address: { _eq: $contractAddress } }\n transaction: { is_execute: { _eq: true } }\n }\n ) {\n aggregate {\n count\n }\n }\n }\n": @@ -31,7 +33,7 @@ const documents = { types.GetRelatedProposalsCountByContractAddressDocument, "\n query getContractListByAdmin($address: String!) {\n contracts(\n where: { account: { address: { _eq: $address } } }\n order_by: { id: desc }\n ) {\n address\n label\n accountByInitBy {\n address\n }\n }\n }\n": types.GetContractListByAdminDocument, - "\n query getContractListByCodeId($codeId: Int!, $offset: Int!, $pageSize: Int!) {\n contracts(\n where: { code_id: { _eq: $codeId } }\n order_by: { id: desc }\n offset: $offset\n limit: $pageSize\n ) {\n address\n label\n init_by: contract_histories(\n order_by: { block: { timestamp: asc } }\n limit: 1\n ) {\n block {\n timestamp\n }\n account {\n address\n }\n }\n contract_histories(order_by: { block: { timestamp: desc } }, limit: 1) {\n block {\n timestamp\n }\n account {\n address\n }\n }\n }\n }\n": + "\n query getContractListByCodeId($codeId: Int!, $offset: Int!, $pageSize: Int!) {\n contracts(\n where: { code_id: { _eq: $codeId } }\n order_by: { id: desc }\n offset: $offset\n limit: $pageSize\n ) {\n address\n label\n admin: account {\n address\n }\n init_by: contract_histories(\n order_by: { block: { timestamp: asc } }\n limit: 1\n ) {\n block {\n timestamp\n }\n account {\n address\n }\n }\n contract_histories(order_by: { block: { timestamp: desc } }, limit: 1) {\n block {\n timestamp\n }\n account {\n address\n }\n }\n }\n }\n": types.GetContractListByCodeIdDocument, "\n query getContractListCountByCodeId($codeId: Int!) {\n contracts_aggregate(where: { code_id: { _eq: $codeId } }) {\n aggregate {\n count\n }\n }\n }\n": types.GetContractListCountByCodeIdDocument, @@ -64,6 +66,9 @@ export function graphql( export function graphql( source: '\n query getInstantiateDetailByContractQueryDocument($contractAddress: String!) {\n contracts_by_pk(address: $contractAddress) {\n init_msg\n transaction {\n hash\n }\n contract_proposals(\n where: {\n proposal: {\n type: {\n _in: [\n "InstantiateContract"\n "InstantiateContract2"\n "SoftwareUpgrade"\n ]\n }\n }\n }\n order_by: { proposal: { id: asc } }\n limit: 1\n ) {\n proposal {\n id\n title\n }\n }\n }\n }\n' ): typeof documents['\n query getInstantiateDetailByContractQueryDocument($contractAddress: String!) {\n contracts_by_pk(address: $contractAddress) {\n init_msg\n transaction {\n hash\n }\n contract_proposals(\n where: {\n proposal: {\n type: {\n _in: [\n "InstantiateContract"\n "InstantiateContract2"\n "SoftwareUpgrade"\n ]\n }\n }\n }\n order_by: { proposal: { id: asc } }\n limit: 1\n ) {\n proposal {\n id\n title\n }\n }\n }\n }\n']; +export function graphql( + source: "\n query getAdminByContractAddressesQueryDocument(\n $contractAddresses: [String!]!\n ) {\n contracts(where: { address: { _in: $contractAddresses } }) {\n address\n admin: account {\n address\n }\n }\n }\n" +): typeof documents["\n query getAdminByContractAddressesQueryDocument(\n $contractAddresses: [String!]!\n ) {\n contracts(where: { address: { _in: $contractAddresses } }) {\n address\n admin: account {\n address\n }\n }\n }\n"]; export function graphql( source: "\n query getExecuteTxsByContractAddress(\n $contractAddress: String!\n $offset: Int!\n $pageSize: Int!\n ) {\n contract_transactions(\n where: {\n contract: { address: { _eq: $contractAddress } }\n transaction: { is_execute: { _eq: true } }\n }\n order_by: { transaction: { block: { timestamp: desc } } }\n limit: $pageSize\n offset: $offset\n ) {\n transaction {\n hash\n messages\n success\n account {\n address\n }\n block {\n height\n timestamp\n }\n }\n }\n }\n" ): typeof documents["\n query getExecuteTxsByContractAddress(\n $contractAddress: String!\n $offset: Int!\n $pageSize: Int!\n ) {\n contract_transactions(\n where: {\n contract: { address: { _eq: $contractAddress } }\n transaction: { is_execute: { _eq: true } }\n }\n order_by: { transaction: { block: { timestamp: desc } } }\n limit: $pageSize\n offset: $offset\n ) {\n transaction {\n hash\n messages\n success\n account {\n address\n }\n block {\n height\n timestamp\n }\n }\n }\n }\n"]; @@ -86,8 +91,8 @@ export function graphql( source: "\n query getContractListByAdmin($address: String!) {\n contracts(\n where: { account: { address: { _eq: $address } } }\n order_by: { id: desc }\n ) {\n address\n label\n accountByInitBy {\n address\n }\n }\n }\n" ): typeof documents["\n query getContractListByAdmin($address: String!) {\n contracts(\n where: { account: { address: { _eq: $address } } }\n order_by: { id: desc }\n ) {\n address\n label\n accountByInitBy {\n address\n }\n }\n }\n"]; export function graphql( - source: "\n query getContractListByCodeId($codeId: Int!, $offset: Int!, $pageSize: Int!) {\n contracts(\n where: { code_id: { _eq: $codeId } }\n order_by: { id: desc }\n offset: $offset\n limit: $pageSize\n ) {\n address\n label\n init_by: contract_histories(\n order_by: { block: { timestamp: asc } }\n limit: 1\n ) {\n block {\n timestamp\n }\n account {\n address\n }\n }\n contract_histories(order_by: { block: { timestamp: desc } }, limit: 1) {\n block {\n timestamp\n }\n account {\n address\n }\n }\n }\n }\n" -): typeof documents["\n query getContractListByCodeId($codeId: Int!, $offset: Int!, $pageSize: Int!) {\n contracts(\n where: { code_id: { _eq: $codeId } }\n order_by: { id: desc }\n offset: $offset\n limit: $pageSize\n ) {\n address\n label\n init_by: contract_histories(\n order_by: { block: { timestamp: asc } }\n limit: 1\n ) {\n block {\n timestamp\n }\n account {\n address\n }\n }\n contract_histories(order_by: { block: { timestamp: desc } }, limit: 1) {\n block {\n timestamp\n }\n account {\n address\n }\n }\n }\n }\n"]; + source: "\n query getContractListByCodeId($codeId: Int!, $offset: Int!, $pageSize: Int!) {\n contracts(\n where: { code_id: { _eq: $codeId } }\n order_by: { id: desc }\n offset: $offset\n limit: $pageSize\n ) {\n address\n label\n admin: account {\n address\n }\n init_by: contract_histories(\n order_by: { block: { timestamp: asc } }\n limit: 1\n ) {\n block {\n timestamp\n }\n account {\n address\n }\n }\n contract_histories(order_by: { block: { timestamp: desc } }, limit: 1) {\n block {\n timestamp\n }\n account {\n address\n }\n }\n }\n }\n" +): typeof documents["\n query getContractListByCodeId($codeId: Int!, $offset: Int!, $pageSize: Int!) {\n contracts(\n where: { code_id: { _eq: $codeId } }\n order_by: { id: desc }\n offset: $offset\n limit: $pageSize\n ) {\n address\n label\n admin: account {\n address\n }\n init_by: contract_histories(\n order_by: { block: { timestamp: asc } }\n limit: 1\n ) {\n block {\n timestamp\n }\n account {\n address\n }\n }\n contract_histories(order_by: { block: { timestamp: desc } }, limit: 1) {\n block {\n timestamp\n }\n account {\n address\n }\n }\n }\n }\n"]; export function graphql( source: "\n query getContractListCountByCodeId($codeId: Int!) {\n contracts_aggregate(where: { code_id: { _eq: $codeId } }) {\n aggregate {\n count\n }\n }\n }\n" ): typeof documents["\n query getContractListCountByCodeId($codeId: Int!) {\n contracts_aggregate(where: { code_id: { _eq: $codeId } }) {\n aggregate {\n count\n }\n }\n }\n"]; diff --git a/src/lib/gql/graphql.ts b/src/lib/gql/graphql.ts index 7980aad7b..3a76e2b74 100644 --- a/src/lib/gql/graphql.ts +++ b/src/lib/gql/graphql.ts @@ -6366,6 +6366,19 @@ export type GetInstantiateDetailByContractQueryDocumentQuery = { } | null; }; +export type GetAdminByContractAddressesQueryDocumentQueryVariables = Exact<{ + contractAddresses: Array | Scalars["String"]; +}>; + +export type GetAdminByContractAddressesQueryDocumentQuery = { + __typename?: "query_root"; + contracts: Array<{ + __typename?: "contracts"; + address: string; + admin?: { __typename?: "accounts"; address: string } | null; + }>; +}; + export type GetExecuteTxsByContractAddressQueryVariables = Exact<{ contractAddress: Scalars["String"]; offset: Scalars["Int"]; @@ -6499,6 +6512,7 @@ export type GetContractListByCodeIdQuery = { __typename?: "contracts"; address: string; label: string; + admin?: { __typename?: "accounts"; address: string } | null; init_by: Array<{ __typename?: "contract_histories"; block: { __typename?: "blocks"; timestamp: any }; @@ -7479,6 +7493,101 @@ export const GetInstantiateDetailByContractQueryDocumentDocument = { GetInstantiateDetailByContractQueryDocumentQuery, GetInstantiateDetailByContractQueryDocumentQueryVariables >; +export const GetAdminByContractAddressesQueryDocumentDocument = { + kind: "Document", + definitions: [ + { + kind: "OperationDefinition", + operation: "query", + name: { kind: "Name", value: "getAdminByContractAddressesQueryDocument" }, + variableDefinitions: [ + { + kind: "VariableDefinition", + variable: { + kind: "Variable", + name: { kind: "Name", value: "contractAddresses" }, + }, + type: { + kind: "NonNullType", + type: { + kind: "ListType", + type: { + kind: "NonNullType", + type: { + kind: "NamedType", + name: { kind: "Name", value: "String" }, + }, + }, + }, + }, + }, + ], + selectionSet: { + kind: "SelectionSet", + selections: [ + { + kind: "Field", + name: { kind: "Name", value: "contracts" }, + arguments: [ + { + kind: "Argument", + name: { kind: "Name", value: "where" }, + value: { + kind: "ObjectValue", + fields: [ + { + kind: "ObjectField", + name: { kind: "Name", value: "address" }, + value: { + kind: "ObjectValue", + fields: [ + { + kind: "ObjectField", + name: { kind: "Name", value: "_in" }, + value: { + kind: "Variable", + name: { + kind: "Name", + value: "contractAddresses", + }, + }, + }, + ], + }, + }, + ], + }, + }, + ], + selectionSet: { + kind: "SelectionSet", + selections: [ + { kind: "Field", name: { kind: "Name", value: "address" } }, + { + kind: "Field", + alias: { kind: "Name", value: "admin" }, + name: { kind: "Name", value: "account" }, + selectionSet: { + kind: "SelectionSet", + selections: [ + { + kind: "Field", + name: { kind: "Name", value: "address" }, + }, + ], + }, + }, + ], + }, + }, + ], + }, + }, + ], +} as unknown as DocumentNode< + GetAdminByContractAddressesQueryDocumentQuery, + GetAdminByContractAddressesQueryDocumentQueryVariables +>; export const GetExecuteTxsByContractAddressDocument = { kind: "Document", definitions: [ @@ -8583,6 +8692,20 @@ export const GetContractListByCodeIdDocument = { selections: [ { kind: "Field", name: { kind: "Name", value: "address" } }, { kind: "Field", name: { kind: "Name", value: "label" } }, + { + kind: "Field", + alias: { kind: "Name", value: "admin" }, + name: { kind: "Name", value: "account" }, + selectionSet: { + kind: "SelectionSet", + selections: [ + { + kind: "Field", + name: { kind: "Name", value: "address" }, + }, + ], + }, + }, { kind: "Field", alias: { kind: "Name", value: "init_by" }, diff --git a/src/lib/pages/code-details/components/CTASection.tsx b/src/lib/pages/code-details/components/CTASection.tsx index 856602d3a..d4e6e7b9b 100644 --- a/src/lib/pages/code-details/components/CTASection.tsx +++ b/src/lib/pages/code-details/components/CTASection.tsx @@ -2,7 +2,7 @@ import { Flex, Button, chakra, Icon } from "@chakra-ui/react"; import { observer } from "mobx-react-lite"; import { MdCheck } from "react-icons/md"; -import { InstantiateButton } from "lib/components/button/InstantiateButton"; +import { InstantiateButton } from "lib/components/button"; import { RemoveCode } from "lib/components/modal/code/RemoveCode"; import { SaveOrEditCodeModal } from "lib/components/modal/code/SaveOrEditCode"; import { useCodeStore } from "lib/hooks"; diff --git a/src/lib/pages/codes/components/CodesTable.tsx b/src/lib/pages/codes/components/CodesTable.tsx index fd80afc8d..45e5a689a 100644 --- a/src/lib/pages/codes/components/CodesTable.tsx +++ b/src/lib/pages/codes/components/CodesTable.tsx @@ -19,7 +19,7 @@ import type { ReactNode } from "react"; import { MdSearchOff } from "react-icons/md"; import { useInternalNavigate } from "lib/app-provider"; -import { InstantiateButton } from "lib/components/button/InstantiateButton"; +import { InstantiateButton } from "lib/components/button"; import { ExplorerLink } from "lib/components/ExplorerLink"; import { RemoveCode } from "lib/components/modal/code/RemoveCode"; import { SaveOrRemoveCode } from "lib/components/modal/code/SaveOrRemoveCode"; diff --git a/src/lib/pages/contract-details/components/ContractTop.tsx b/src/lib/pages/contract-details/components/ContractTop.tsx index d844738e2..dab7a4dc7 100644 --- a/src/lib/pages/contract-details/components/ContractTop.tsx +++ b/src/lib/pages/contract-details/components/ContractTop.tsx @@ -7,15 +7,11 @@ import { Icon, IconButton, } from "@chakra-ui/react"; -import { - MdBookmark, - MdBookmarkBorder, - MdInput, - MdKeyboardArrowDown, -} from "react-icons/md"; +import { MdBookmark, MdBookmarkBorder, MdInput } from "react-icons/md"; import { RiPencilFill } from "react-icons/ri"; import { useInternalNavigate } from "lib/app-provider"; +import { AdminButton } from "lib/components/button"; import { ExplorerLink } from "lib/components/ExplorerLink"; import { AddToOtherList, @@ -30,10 +26,10 @@ interface ContractTopProps { } export const ContractTop = ({ contractData }: ContractTopProps) => { const navigate = useInternalNavigate(); + const { contractLocalInfo, instantiateInfo, publicInfo } = contractData; const contractAddress = instantiateInfo?.contractAddress as ContractAddr; - const displayName = contractLocalInfo?.name || publicInfo?.name || instantiateInfo?.label; @@ -134,14 +130,11 @@ export const ContractTop = ({ contractData }: ContractTopProps) => { )} - - {/* TODO - Revisit, implement admin button */} - + +