From ac9d093aba7a6fd656984f26aa545d9bba80bc4f Mon Sep 17 00:00:00 2001 From: poomthiti Date: Thu, 20 Jul 2023 11:45:20 +0700 Subject: [PATCH 01/94] feat: first draft for upload schema --- CHANGELOG.md | 1 + src/lib/app-fns/tx/upload.tsx | 107 +++++++++------- src/lib/app-provider/tx/upload.ts | 11 +- src/lib/components/stepper/StepperItem.tsx | 12 +- src/lib/components/stepper/types.ts | 2 +- src/lib/components/tx/modal/ButtonSection.tsx | 28 ---- src/lib/components/upload/UploadSection.tsx | 14 +- src/lib/pages/upload/completed.tsx | 110 ++++++++++++++++ .../pages/upload/components/UploadSchema.tsx | 120 ++++++++++++++++++ src/lib/pages/upload/index.tsx | 77 ++++------- src/lib/pages/upload/upload.tsx | 56 ++++++++ src/lib/types/tx/model.ts | 1 - 12 files changed, 399 insertions(+), 140 deletions(-) create mode 100644 src/lib/pages/upload/completed.tsx create mode 100644 src/lib/pages/upload/components/UploadSchema.tsx create mode 100644 src/lib/pages/upload/upload.tsx diff --git a/CHANGELOG.md b/CHANGELOG.md index 027052c56..9bf4053d3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,6 +39,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Features +- [#453](https://github.com/alleslabs/celatone-frontend/pull/453) Attach schema feature on upload complete - [#419](https://github.com/alleslabs/celatone-frontend/pull/419) Add error message box for tx failed modal and enhance styling - [#415](https://github.com/alleslabs/celatone-frontend/pull/415) Search by icns names feature and Show registered icns names on account details page - [#438](https://github.com/alleslabs/celatone-frontend/pull/438) Add new home page diff --git a/src/lib/app-fns/tx/upload.tsx b/src/lib/app-fns/tx/upload.tsx index 8d84d3b28..8f14b8c86 100644 --- a/src/lib/app-fns/tx/upload.tsx +++ b/src/lib/app-fns/tx/upload.tsx @@ -3,6 +3,7 @@ import type { DeliverTxResponse, logs, StdFee } from "@cosmjs/stargate"; import { pipe } from "@rx-stream/pipe"; import type { Observable } from "rxjs"; +import type { UploadSucceedCallback } from "lib/app-provider"; import { ExplorerLink } from "lib/components/ExplorerLink"; import { CustomIcon } from "lib/components/icon"; import { AmpEvent, AmpTrack } from "lib/services/amplitude"; @@ -23,7 +24,7 @@ interface UploadTxParams { fee: StdFee; memo?: string; client: SigningCosmWasmClient; - onTxSucceed?: (codeId: number) => void; + onTxSucceed: UploadSucceedCallback; isMigrate: boolean; } @@ -52,56 +53,64 @@ export const uploadContractTx = ({ }; const codeId = findAttr(mimicLog, "store_code", "code_id") ?? "0"; - - onTxSucceed?.(parseInt(codeId, 10)); const txFee = txInfo.events.find((e) => e.type === "tx")?.attributes[0] .value; - return { - value: null, - phase: TxStreamPhase.SUCCEED, - receipts: [ - { - title: "Code ID", - value: codeId, - html: ( -
- -
- ), - }, - { - title: "Tx Hash", - value: txInfo.transactionHash, - html: ( - - ), - }, - { - title: "Tx Fee", - value: txFee ? formatUFee(txFee) : "N/A", - }, - ], - receiptInfo: { - header: "Upload Wasm Complete", - description: ( - <> - - ‘{codeName || `${wasmFileName}(${codeId})`}’ - {" "} - is has been uploaded. Would you like to{" "} - {isMigrate ? "migrate" : "instantiate"} your code now? - - ), - headerIcon: ( - - ), - }, - actionVariant: isMigrate ? "upload-migrate" : "upload", - } as TxResultRendering; + const formattedFee = txFee ? formatUFee(txFee) : "N/A"; + + onTxSucceed({ + codeId: parseInt(codeId, 10).toString(), + codeDisplayName: codeName || `${wasmFileName}(${codeId})`, + txHash: txInfo.transactionHash, + formattedFee, + }); + + return isMigrate + ? ({ + value: null, + phase: TxStreamPhase.SUCCEED, + receipts: [ + { + title: "Code ID", + value: codeId, + html: ( +
+ +
+ ), + }, + { + title: "Tx Hash", + value: txInfo.transactionHash, + html: ( + + ), + }, + { + title: "Tx Fee", + value: formattedFee, + }, + ], + receiptInfo: { + header: "Upload Wasm Complete", + description: ( + <> + + ‘{codeName || `${wasmFileName}(${codeId})`}’ + {" "} + is has been uploaded. Would you like to migrate your code now? + + ), + headerIcon: ( + + ), + }, + actionVariant: "upload-migrate", + } as TxResultRendering) + : (null as unknown as TxResultRendering); } )().pipe(catchTxError()); }; diff --git a/src/lib/app-provider/tx/upload.ts b/src/lib/app-provider/tx/upload.ts index 028d3dd3d..b76700165 100644 --- a/src/lib/app-provider/tx/upload.ts +++ b/src/lib/app-provider/tx/upload.ts @@ -7,6 +7,15 @@ import { uploadContractTx } from "lib/app-fns/tx/upload"; import type { AccessType, Addr, HumanAddr, Option } from "lib/types"; import { composeStoreCodeMsg } from "lib/utils"; +export interface UploadTxInternalResult { + codeDisplayName: string; + codeId: string; + txHash: string; + formattedFee: string; +} + +export type UploadSucceedCallback = (txResult: UploadTxInternalResult) => void; + export interface UploadStreamParams { wasmFileName: Option; wasmCode: Option>; @@ -14,7 +23,7 @@ export interface UploadStreamParams { permission: AccessType; codeName: string; estimatedFee: Option; - onTxSucceed?: (codeId: number) => void; + onTxSucceed: UploadSucceedCallback; } export const useUploadContractTx = (isMigrate: boolean) => { diff --git a/src/lib/components/stepper/StepperItem.tsx b/src/lib/components/stepper/StepperItem.tsx index e6ab67010..fde456232 100644 --- a/src/lib/components/stepper/StepperItem.tsx +++ b/src/lib/components/stepper/StepperItem.tsx @@ -5,7 +5,7 @@ import { CustomIcon } from "../icon"; import type { Mode, Step } from "./types"; export const stepperText: Record> = { - deploy: { 1: "Upload or Select Code ID", 2: "Instantiate Code" }, + deploy: { 1: "Upload or Select Code ID", 2: "Instantiate Contract" }, migrate: { 1: "Migrate Options", 2: "Migrate Details" }, }; @@ -21,7 +21,7 @@ const StepLabel = ({ step ? ( ) : ( - {step} + + {step} + )} ); @@ -54,7 +56,7 @@ export const StepperItem = ({ content: '""', flex: 1, height: "1px", - backgroundColor: "gray.600", + backgroundColor: "gray.400", marginInlineEnd: "8px", }, }} @@ -63,7 +65,7 @@ export const StepperItem = ({ {stepperText[mode][step]} diff --git a/src/lib/components/stepper/types.ts b/src/lib/components/stepper/types.ts index 9fd28002a..987cac2a5 100644 --- a/src/lib/components/stepper/types.ts +++ b/src/lib/components/stepper/types.ts @@ -1,3 +1,3 @@ -export type Step = 1 | 2; +export type Step = 1 | 1.5 | 2; export type Mode = "deploy" | "migrate"; diff --git a/src/lib/components/tx/modal/ButtonSection.tsx b/src/lib/components/tx/modal/ButtonSection.tsx index 9f887766d..548d579c6 100644 --- a/src/lib/components/tx/modal/ButtonSection.tsx +++ b/src/lib/components/tx/modal/ButtonSection.tsx @@ -62,34 +62,6 @@ export const ButtonSection = ({ switch (actionVariant) { case "sending": return null; - case "upload": - return ( - <> - - - - ); case "upload-migrate": return ( + + + ); +}); diff --git a/src/lib/pages/upload/components/UploadSchema.tsx b/src/lib/pages/upload/components/UploadSchema.tsx new file mode 100644 index 000000000..811293adb --- /dev/null +++ b/src/lib/pages/upload/components/UploadSchema.tsx @@ -0,0 +1,120 @@ +import { + Box, + Button, + Drawer, + DrawerBody, + DrawerCloseButton, + DrawerContent, + DrawerHeader, + DrawerOverlay, + Flex, + Heading, + IconButton, + Text, + useDisclosure, +} from "@chakra-ui/react"; +import { observer } from "mobx-react-lite"; + +import { CustomIcon } from "lib/components/icon"; + +const Content = ({ attached }: { attached: boolean }) => { + const { isOpen, onOpen, onClose } = useDisclosure(); + return ( + <> + {!attached ? ( + <> + Attach JSON Schema + + + ) : ( + <> + + + JSON Schema attached + + + + + } + /> + onClose()} + icon={ + + } + /> + + + )} + + + + + + + + + Attach JSON Schema for code ID “1” + + + + Your attached JSON schema will be stored locally on your device + + + + + + + + Please note that the JSON schema you upload on our website will + only be stored locally on your device. For public projects with + verified JSON schemas, they will be visible and accessible to + others. + + + + + + + ); +}; + +export const UploadSchema = observer(({ attached }: { attached: boolean }) => { + // Check attachment state from local storage + return ( + + + + ); +}); diff --git a/src/lib/pages/upload/index.tsx b/src/lib/pages/upload/index.tsx index 9452005ff..923e7728d 100644 --- a/src/lib/pages/upload/index.tsx +++ b/src/lib/pages/upload/index.tsx @@ -1,59 +1,32 @@ -import { Heading, Text } from "@chakra-ui/react"; -import { useRouter } from "next/router"; -import { useEffect } from "react"; +import { useState } from "react"; -import { - useCurrentChain, - useInternalNavigate, - useWasmConfig, -} from "lib/app-provider"; -import { ConnectWalletAlert } from "lib/components/ConnectWalletAlert"; -import { Stepper } from "lib/components/stepper"; -import { UploadSection } from "lib/components/upload/UploadSection"; -import WasmPageContainer from "lib/components/WasmPageContainer"; -import { AmpEvent, AmpTrack } from "lib/services/amplitude"; -import { useUploadAccessParams } from "lib/services/proposalService"; -import type { HumanAddr } from "lib/types"; -import { AccessConfigPermission } from "lib/types"; +import type { UploadTxInternalResult } from "lib/app-provider"; +import { useWasmConfig } from "lib/app-provider"; -const Upload = () => { - const router = useRouter(); - const { address } = useCurrentChain(); - const navigate = useInternalNavigate(); - const { data, isLoading } = useUploadAccessParams(); - - const isPermissionedNetwork = - data?.permission !== AccessConfigPermission.EVERYBODY; - - const enableUpload = - !isPermissionedNetwork || - Boolean(data?.addresses?.includes(address as HumanAddr)); +import { UploadComplete } from "./completed"; +import { Upload } from "./upload"; +const UploadIndex = () => { useWasmConfig({ shouldRedirect: true }); - - useEffect(() => { - // Redirect back to deploy page - if (!enableUpload && !isLoading) - navigate({ pathname: "/deploy", replace: true }); - else if (router.isReady) AmpTrack(AmpEvent.TO_UPLOAD); - }, [enableUpload, isLoading, navigate, router.isReady]); - - return ( - - - DEPLOY NEW CONTRACT - - - - Upload Wasm file - - - router.back()} /> - + const [txInfo, setTxInfo] = useState({ + codeDisplayName: "", + codeId: "", + txHash: "", + formattedFee: "", + }); + + const [completed, setCompleted] = useState(false); + + return completed ? ( + + ) : ( + { + setTxInfo(txResult); + setCompleted(true); + }} + /> ); }; -export default Upload; +export default UploadIndex; diff --git a/src/lib/pages/upload/upload.tsx b/src/lib/pages/upload/upload.tsx new file mode 100644 index 000000000..dc35d4a80 --- /dev/null +++ b/src/lib/pages/upload/upload.tsx @@ -0,0 +1,56 @@ +import { Heading, Text } from "@chakra-ui/react"; +import { useRouter } from "next/router"; +import { useEffect } from "react"; + +import type { UploadSucceedCallback } from "lib/app-provider"; +import { useCurrentChain, useInternalNavigate } from "lib/app-provider"; +import { ConnectWalletAlert } from "lib/components/ConnectWalletAlert"; +import { Stepper } from "lib/components/stepper"; +import { UploadSection } from "lib/components/upload/UploadSection"; +import WasmPageContainer from "lib/components/WasmPageContainer"; +import { AmpEvent, AmpTrack } from "lib/services/amplitude"; +import { useUploadAccessParams } from "lib/services/proposalService"; +import type { HumanAddr } from "lib/types"; +import { AccessConfigPermission } from "lib/types"; + +export const Upload = ({ + onComplete, +}: { + onComplete: UploadSucceedCallback; +}) => { + const router = useRouter(); + const { address } = useCurrentChain(); + const navigate = useInternalNavigate(); + const { data, isLoading } = useUploadAccessParams(); + + const isPermissionedNetwork = + data?.permission !== AccessConfigPermission.EVERYBODY; + + const enableUpload = + !isPermissionedNetwork || + Boolean(data?.addresses?.includes(address as HumanAddr)); + + useEffect(() => { + // Redirect back to deploy page + if (!enableUpload && !isLoading) + navigate({ pathname: "/deploy", replace: true }); + else if (router.isReady) AmpTrack(AmpEvent.TO_UPLOAD); + }, [enableUpload, isLoading, navigate, router.isReady]); + + return ( + + + DEPLOY NEW CONTRACT + + + + Upload Wasm file + + + + + ); +}; diff --git a/src/lib/types/tx/model.ts b/src/lib/types/tx/model.ts index 081b9129a..880bf8262 100644 --- a/src/lib/types/tx/model.ts +++ b/src/lib/types/tx/model.ts @@ -26,7 +26,6 @@ export interface ReceiptInfo { export type ActionVariant = | "sending" - | "upload" | "upload-migrate" | "migrate" | "rejected" From 7e75cefef1214e3bba557802da63668573bd249f Mon Sep 17 00:00:00 2001 From: poomthiti Date: Thu, 20 Jul 2023 12:16:49 +0700 Subject: [PATCH 02/94] feat: add scroll to top when upload complete --- src/lib/pages/upload/index.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lib/pages/upload/index.tsx b/src/lib/pages/upload/index.tsx index 923e7728d..c341033c0 100644 --- a/src/lib/pages/upload/index.tsx +++ b/src/lib/pages/upload/index.tsx @@ -2,6 +2,7 @@ import { useState } from "react"; import type { UploadTxInternalResult } from "lib/app-provider"; import { useWasmConfig } from "lib/app-provider"; +import { scrollToTop } from "lib/utils"; import { UploadComplete } from "./completed"; import { Upload } from "./upload"; @@ -24,6 +25,7 @@ const UploadIndex = () => { onComplete={(txResult: UploadTxInternalResult) => { setTxInfo(txResult); setCompleted(true); + scrollToTop(); }} /> ); From 5f0cf04db6a6ab90c5ca68d07e21aae85830b8e2 Mon Sep 17 00:00:00 2001 From: poomthiti Date: Fri, 21 Jul 2023 10:59:07 +0700 Subject: [PATCH 03/94] fix: inconsistent copier size on hover --- src/lib/styles/globals.css | 1 - 1 file changed, 1 deletion(-) diff --git a/src/lib/styles/globals.css b/src/lib/styles/globals.css index 96c442899..ed1ceb774 100644 --- a/src/lib/styles/globals.css +++ b/src/lib/styles/globals.css @@ -1,7 +1,6 @@ /* Global Styling here */ .copier-wrapper:hover .copier { display: inline; - max-height: 11px; } .accordion-stepper-wrapper:not(:first-of-type) div#before-stepper { From 56c454cd730f3d34a358b26d7f8ca3392e9332e1 Mon Sep 17 00:00:00 2001 From: poomthiti Date: Fri, 21 Jul 2023 16:11:26 +0700 Subject: [PATCH 04/94] feat: implement schema store and unit test --- CHANGELOG.md | 1 + src/lib/providers/store.tsx | 5 + src/lib/stores/root.ts | 4 + src/lib/stores/schema-example.json | 395 +++++++++++++++++++++++++++++ src/lib/stores/schema.test.ts | 76 ++++++ src/lib/stores/schema.ts | 57 +++++ 6 files changed, 538 insertions(+) create mode 100644 src/lib/stores/schema-example.json create mode 100644 src/lib/stores/schema.test.ts create mode 100644 src/lib/stores/schema.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 9bf4053d3..9b5a5edb8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,6 +39,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Features +- [#455](https://github.com/alleslabs/celatone-frontend/pull/455) Implement schema store and unit test - [#453](https://github.com/alleslabs/celatone-frontend/pull/453) Attach schema feature on upload complete - [#419](https://github.com/alleslabs/celatone-frontend/pull/419) Add error message box for tx failed modal and enhance styling - [#415](https://github.com/alleslabs/celatone-frontend/pull/415) Search by icns names feature and Show registered icns names on account details page diff --git a/src/lib/providers/store.tsx b/src/lib/providers/store.tsx index baea529b4..298637b41 100644 --- a/src/lib/providers/store.tsx +++ b/src/lib/providers/store.tsx @@ -49,3 +49,8 @@ export function usePublicProjectStore() { const { publicProjectStore } = useStore(); return publicProjectStore; } + +export function useSchemaStore() { + const { schemaStore } = useStore(); + return schemaStore; +} diff --git a/src/lib/stores/root.ts b/src/lib/stores/root.ts index 5b7f32e53..19696e075 100644 --- a/src/lib/stores/root.ts +++ b/src/lib/stores/root.ts @@ -1,6 +1,7 @@ import { CodeStore } from "./code"; import { ContractStore } from "./contract"; import { PublicProjectStore } from "./project"; +import { SchemaStore } from "./schema"; export class RootStore { codeStore: CodeStore; @@ -9,9 +10,12 @@ export class RootStore { publicProjectStore: PublicProjectStore; + schemaStore: SchemaStore; + constructor() { this.codeStore = new CodeStore(); this.contractStore = new ContractStore(); this.publicProjectStore = new PublicProjectStore(); + this.schemaStore = new SchemaStore(); } } diff --git a/src/lib/stores/schema-example.json b/src/lib/stores/schema-example.json new file mode 100644 index 000000000..84ad59865 --- /dev/null +++ b/src/lib/stores/schema-example.json @@ -0,0 +1,395 @@ +{ + "contract_name": "mars-address-provider", + "contract_version": "1.0.1", + "idl_version": "1.0.0", + "instantiate": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "InstantiateMsg", + "description": "Essentially, mars-address-provider is a required init param for all other contracts, so it needs to be initialised first (Only owner can be set on initialization). So the deployment looks like this:\n\n1. Init the address provider 2. Init all other contracts, passing in the address provider address (not ALL contracts need this but many do) 3. Update the address provider, with an update config call to contain all the other contract addresses from step 2, this is why we need it to be owned by an EOA (externally owned account) - so we can do this update as part of the deployment 4. Update the owner of the address provider contract at the end of deployment to be either a. the multisig or b. the gov/council contract", + "type": "object", + "required": ["owner", "prefix"], + "properties": { + "owner": { + "description": "The contract's owner", + "type": "string" + }, + "prefix": { + "description": "The address prefix of the chain this contract is deployed on", + "type": "string" + } + }, + "additionalProperties": false + }, + "execute": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "ExecuteMsg", + "oneOf": [ + { + "description": "Set address", + "type": "object", + "required": ["set_address"], + "properties": { + "set_address": { + "type": "object", + "required": ["address", "address_type"], + "properties": { + "address": { + "type": "string" + }, + "address_type": { + "$ref": "#/definitions/MarsAddressType" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Manages admin role state", + "type": "object", + "required": ["update_owner"], + "properties": { + "update_owner": { + "$ref": "#/definitions/OwnerUpdate" + } + }, + "additionalProperties": false + } + ], + "definitions": { + "MarsAddressType": { + "oneOf": [ + { + "type": "string", + "enum": ["incentives", "oracle", "red_bank", "rewards_collector"] + }, + { + "description": "Protocol admin is an ICS-27 interchain account controlled by Mars Hub's x/gov module. This account will take the owner and admin roles of red-bank contracts.\n\nOwner means the account who can invoke certain priviliged execute methods on a contract, such as updating the config. Admin means the account who can migrate a contract.", + "type": "string", + "enum": ["protocol_admin"] + }, + { + "description": "The `fee_collector` module account controlled by Mars Hub's x/distribution module. Funds sent to this account will be distributed as staking rewards.\n\nNOTE: This is a Mars Hub address with the `mars` bech32 prefix, which may not be recognized by the `api.addr_validate` method.", + "type": "string", + "enum": ["fee_collector"] + }, + { + "description": "The module account controlled by the by Mars Hub's x/safety module. Funds sent to this account will be deposited into the safety fund.\n\nNOTE: This is a Mars Hub address with the `mars` bech32 prefix, which may not be recognized by the `api.addr_validate` method.", + "type": "string", + "enum": ["safety_fund"] + } + ] + }, + "OwnerUpdate": { + "oneOf": [ + { + "description": "Proposes a new owner to take role. Only current owner can execute.", + "type": "object", + "required": ["propose_new_owner"], + "properties": { + "propose_new_owner": { + "type": "object", + "required": ["proposed"], + "properties": { + "proposed": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Clears the currently proposed owner. Only current owner can execute.", + "type": "string", + "enum": ["clear_proposed"] + }, + { + "description": "Promotes the proposed owner to be the current one. Only the proposed owner can execute.", + "type": "string", + "enum": ["accept_proposed"] + }, + { + "description": "Throws away the keys to the Owner role forever. Once done, no owner can ever be set later.", + "type": "string", + "enum": ["abolish_owner_role"] + } + ] + } + } + }, + "query": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "QueryMsg", + "oneOf": [ + { + "description": "Get config", + "type": "object", + "required": ["config"], + "properties": { + "config": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Get a single address", + "type": "object", + "required": ["address"], + "properties": { + "address": { + "$ref": "#/definitions/MarsAddressType" + } + }, + "additionalProperties": false + }, + { + "description": "Get a list of addresses", + "type": "object", + "required": ["addresses"], + "properties": { + "addresses": { + "type": "array", + "items": { + "$ref": "#/definitions/MarsAddressType" + } + } + }, + "additionalProperties": false + }, + { + "description": "Query all stored addresses with pagination", + "type": "object", + "required": ["all_addresses"], + "properties": { + "all_addresses": { + "type": "object", + "properties": { + "limit": { + "type": ["integer", "null"], + "format": "uint32", + "minimum": 0 + }, + "start_after": { + "anyOf": [ + { + "$ref": "#/definitions/MarsAddressType" + }, + { + "type": "null" + } + ] + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ], + "definitions": { + "MarsAddressType": { + "oneOf": [ + { + "type": "string", + "enum": ["incentives", "oracle", "red_bank", "rewards_collector"] + }, + { + "description": "Protocol admin is an ICS-27 interchain account controlled by Mars Hub's x/gov module. This account will take the owner and admin roles of red-bank contracts.\n\nOwner means the account who can invoke certain priviliged execute methods on a contract, such as updating the config. Admin means the account who can migrate a contract.", + "type": "string", + "enum": ["protocol_admin"] + }, + { + "description": "The `fee_collector` module account controlled by Mars Hub's x/distribution module. Funds sent to this account will be distributed as staking rewards.\n\nNOTE: This is a Mars Hub address with the `mars` bech32 prefix, which may not be recognized by the `api.addr_validate` method.", + "type": "string", + "enum": ["fee_collector"] + }, + { + "description": "The module account controlled by the by Mars Hub's x/safety module. Funds sent to this account will be deposited into the safety fund.\n\nNOTE: This is a Mars Hub address with the `mars` bech32 prefix, which may not be recognized by the `api.addr_validate` method.", + "type": "string", + "enum": ["safety_fund"] + } + ] + } + } + }, + "migrate": null, + "sudo": null, + "responses": { + "address": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "AddressResponseItem", + "type": "object", + "required": ["address", "address_type"], + "properties": { + "address": { + "description": "Address value", + "type": "string" + }, + "address_type": { + "description": "The type of address", + "allOf": [ + { + "$ref": "#/definitions/MarsAddressType" + } + ] + } + }, + "additionalProperties": false, + "definitions": { + "MarsAddressType": { + "oneOf": [ + { + "type": "string", + "enum": ["incentives", "oracle", "red_bank", "rewards_collector"] + }, + { + "description": "Protocol admin is an ICS-27 interchain account controlled by Mars Hub's x/gov module. This account will take the owner and admin roles of red-bank contracts.\n\nOwner means the account who can invoke certain priviliged execute methods on a contract, such as updating the config. Admin means the account who can migrate a contract.", + "type": "string", + "enum": ["protocol_admin"] + }, + { + "description": "The `fee_collector` module account controlled by Mars Hub's x/distribution module. Funds sent to this account will be distributed as staking rewards.\n\nNOTE: This is a Mars Hub address with the `mars` bech32 prefix, which may not be recognized by the `api.addr_validate` method.", + "type": "string", + "enum": ["fee_collector"] + }, + { + "description": "The module account controlled by the by Mars Hub's x/safety module. Funds sent to this account will be deposited into the safety fund.\n\nNOTE: This is a Mars Hub address with the `mars` bech32 prefix, which may not be recognized by the `api.addr_validate` method.", + "type": "string", + "enum": ["safety_fund"] + } + ] + } + } + }, + "addresses": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Array_of_AddressResponseItem", + "type": "array", + "items": { + "$ref": "#/definitions/AddressResponseItem" + }, + "definitions": { + "AddressResponseItem": { + "type": "object", + "required": ["address", "address_type"], + "properties": { + "address": { + "description": "Address value", + "type": "string" + }, + "address_type": { + "description": "The type of address", + "allOf": [ + { + "$ref": "#/definitions/MarsAddressType" + } + ] + } + }, + "additionalProperties": false + }, + "MarsAddressType": { + "oneOf": [ + { + "type": "string", + "enum": ["incentives", "oracle", "red_bank", "rewards_collector"] + }, + { + "description": "Protocol admin is an ICS-27 interchain account controlled by Mars Hub's x/gov module. This account will take the owner and admin roles of red-bank contracts.\n\nOwner means the account who can invoke certain priviliged execute methods on a contract, such as updating the config. Admin means the account who can migrate a contract.", + "type": "string", + "enum": ["protocol_admin"] + }, + { + "description": "The `fee_collector` module account controlled by Mars Hub's x/distribution module. Funds sent to this account will be distributed as staking rewards.\n\nNOTE: This is a Mars Hub address with the `mars` bech32 prefix, which may not be recognized by the `api.addr_validate` method.", + "type": "string", + "enum": ["fee_collector"] + }, + { + "description": "The module account controlled by the by Mars Hub's x/safety module. Funds sent to this account will be deposited into the safety fund.\n\nNOTE: This is a Mars Hub address with the `mars` bech32 prefix, which may not be recognized by the `api.addr_validate` method.", + "type": "string", + "enum": ["safety_fund"] + } + ] + } + } + }, + "all_addresses": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Array_of_AddressResponseItem", + "type": "array", + "items": { + "$ref": "#/definitions/AddressResponseItem" + }, + "definitions": { + "AddressResponseItem": { + "type": "object", + "required": ["address", "address_type"], + "properties": { + "address": { + "description": "Address value", + "type": "string" + }, + "address_type": { + "description": "The type of address", + "allOf": [ + { + "$ref": "#/definitions/MarsAddressType" + } + ] + } + }, + "additionalProperties": false + }, + "MarsAddressType": { + "oneOf": [ + { + "type": "string", + "enum": ["incentives", "oracle", "red_bank", "rewards_collector"] + }, + { + "description": "Protocol admin is an ICS-27 interchain account controlled by Mars Hub's x/gov module. This account will take the owner and admin roles of red-bank contracts.\n\nOwner means the account who can invoke certain priviliged execute methods on a contract, such as updating the config. Admin means the account who can migrate a contract.", + "type": "string", + "enum": ["protocol_admin"] + }, + { + "description": "The `fee_collector` module account controlled by Mars Hub's x/distribution module. Funds sent to this account will be distributed as staking rewards.\n\nNOTE: This is a Mars Hub address with the `mars` bech32 prefix, which may not be recognized by the `api.addr_validate` method.", + "type": "string", + "enum": ["fee_collector"] + }, + { + "description": "The module account controlled by the by Mars Hub's x/safety module. Funds sent to this account will be deposited into the safety fund.\n\nNOTE: This is a Mars Hub address with the `mars` bech32 prefix, which may not be recognized by the `api.addr_validate` method.", + "type": "string", + "enum": ["safety_fund"] + } + ] + } + } + }, + "config": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "ConfigResponse", + "type": "object", + "required": ["prefix"], + "properties": { + "owner": { + "description": "The contract's owner", + "type": ["string", "null"] + }, + "prefix": { + "description": "The address prefix of the chain this contract is deployed on", + "type": "string" + }, + "proposed_new_owner": { + "description": "The contract's proposed owner", + "type": ["string", "null"] + } + }, + "additionalProperties": false + } + } +} diff --git a/src/lib/stores/schema.test.ts b/src/lib/stores/schema.test.ts new file mode 100644 index 000000000..dd842c0e5 --- /dev/null +++ b/src/lib/stores/schema.test.ts @@ -0,0 +1,76 @@ +import { SchemaProperties, SchemaStore } from "./schema"; +import exampleSchema from "./schema-example.json"; + +let schemaStore: SchemaStore; +const codeHash = "a1b2c3d4e5f6g7"; + +beforeAll(() => { + schemaStore = new SchemaStore(); +}); + +describe("SchemaStore initialization", () => { + test("Correctly initialize SchemaStore", () => { + expect(schemaStore instanceof SchemaStore).toBeTruthy(); + }); +}); + +describe("saveNewSchema", () => { + test("correctly save new schema", () => { + schemaStore.saveNewSchema(codeHash, exampleSchema); + expect(schemaStore.jsonSchemas).toStrictEqual({ + [codeHash]: exampleSchema, + }); + }); +}); + +describe("getSchemaByCodeHash", () => { + test("correctly get schema by code hash", () => { + expect(schemaStore.getSchemaByCodeHash(codeHash)).toStrictEqual( + exampleSchema + ); + }); + test("return undefined on code hash not found", () => { + expect(schemaStore.getSchemaByCodeHash("randomHash")).toBeUndefined(); + }); +}); + +describe("getSchemaProperty", () => { + test("correctly retrieve schema property", () => { + expect( + schemaStore.getSchemaProperty(codeHash, SchemaProperties.CONTRACT_NAME) + ).toStrictEqual(exampleSchema.contract_name); + expect( + schemaStore.getSchemaProperty(codeHash, SchemaProperties.CONTRACT_VERSION) + ).toStrictEqual(exampleSchema.contract_version); + expect( + schemaStore.getSchemaProperty(codeHash, SchemaProperties.IDL_VERSION) + ).toStrictEqual(exampleSchema.idl_version); + expect( + schemaStore.getSchemaProperty(codeHash, SchemaProperties.INSTANTIATE) + ).toStrictEqual(exampleSchema.instantiate); + expect( + schemaStore.getSchemaProperty(codeHash, SchemaProperties.EXECUTE) + ).toStrictEqual(exampleSchema.execute); + expect( + schemaStore.getSchemaProperty(codeHash, SchemaProperties.QUERY) + ).toStrictEqual(exampleSchema.query); + expect( + schemaStore.getSchemaProperty(codeHash, SchemaProperties.MIGRATE) + ).toStrictEqual(exampleSchema.migrate); + expect( + schemaStore.getSchemaProperty(codeHash, SchemaProperties.SUDO) + ).toStrictEqual(exampleSchema.sudo); + expect( + schemaStore.getSchemaProperty(codeHash, SchemaProperties.RESPONSES) + ).toStrictEqual(exampleSchema.responses); + }); + + test("correctly return undefined on code hash not found", () => { + expect( + schemaStore.getSchemaProperty( + "randomHash", + SchemaProperties.CONTRACT_NAME + ) + ).toBeUndefined(); + }); +}); diff --git a/src/lib/stores/schema.ts b/src/lib/stores/schema.ts new file mode 100644 index 000000000..13c001b49 --- /dev/null +++ b/src/lib/stores/schema.ts @@ -0,0 +1,57 @@ +import { makeAutoObservable } from "mobx"; +import { makePersistable } from "mobx-persist-store"; + +import type { Dict, Option } from "lib/types"; + +type JsonSchema = Dict; + +// TODO: this is derived from an example schema, ensure that the properties are comprehensively defined +export enum SchemaProperties { + CONTRACT_NAME = "contract_name", + CONTRACT_VERSION = "contract_version", + IDL_VERSION = "idl_version", + INSTANTIATE = "instantiate", + EXECUTE = "execute", + QUERY = "query", + MIGRATE = "migrate", + SUDO = "sudo", + RESPONSES = "responses", +} + +export class SchemaStore { + /** + * @remarks code hash as key and json schema as value (annotated as Dict>) + * e.g. + * { + * "ad5b2af9a177ffc": { + * "contract_name": ..., + * "instantiate": { ... }, + * ... + * } + * } + */ + jsonSchemas: Dict; + + constructor() { + this.jsonSchemas = {}; + + makeAutoObservable(this, {}, { autoBind: true }); + + makePersistable(this, { + name: "SchemaStore", + properties: ["jsonSchemas"], + }); + } + + saveNewSchema(codeHash: string, schema: JsonSchema) { + this.jsonSchemas[codeHash] = schema; + } + + getSchemaByCodeHash(codeHash: string): Option { + return this.jsonSchemas[codeHash]; + } + + getSchemaProperty(codeHash: string, property: SchemaProperties) { + return this.jsonSchemas[codeHash]?.[property]; + } +} From fb701ef33e82f8fe86d98b902518d03ebce925cd Mon Sep 17 00:00:00 2001 From: poomthiti Date: Wed, 26 Jul 2023 17:44:15 +0700 Subject: [PATCH 05/94] feat: add query and execute schema form array getter --- .../execute-schema-output.json | 160 ++++++++ .../query-schema-output.json | 355 ++++++++++++++++++ .../schema-example.json | 0 src/lib/stores/schema.test.ts | 33 +- src/lib/stores/schema.ts | 56 +++ 5 files changed, 603 insertions(+), 1 deletion(-) create mode 100644 src/lib/stores/schema-test-suite/execute-schema-output.json create mode 100644 src/lib/stores/schema-test-suite/query-schema-output.json rename src/lib/stores/{ => schema-test-suite}/schema-example.json (100%) diff --git a/src/lib/stores/schema-test-suite/execute-schema-output.json b/src/lib/stores/schema-test-suite/execute-schema-output.json new file mode 100644 index 000000000..49e92c248 --- /dev/null +++ b/src/lib/stores/schema-test-suite/execute-schema-output.json @@ -0,0 +1,160 @@ +[ + { + "description": "Set address", + "type": "object", + "required": ["set_address"], + "properties": { + "set_address": { + "type": "object", + "required": ["address", "address_type"], + "properties": { + "address": { + "type": "string" + }, + "address_type": { + "$ref": "#/definitions/MarsAddressType" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false, + "$schema": "http://json-schema.org/draft-07/schema#", + "definitions": { + "MarsAddressType": { + "oneOf": [ + { + "type": "string", + "enum": ["incentives", "oracle", "red_bank", "rewards_collector"] + }, + { + "description": "Protocol admin is an ICS-27 interchain account controlled by Mars Hub's x/gov module. This account will take the owner and admin roles of red-bank contracts.\n\nOwner means the account who can invoke certain priviliged execute methods on a contract, such as updating the config. Admin means the account who can migrate a contract.", + "type": "string", + "enum": ["protocol_admin"] + }, + { + "description": "The `fee_collector` module account controlled by Mars Hub's x/distribution module. Funds sent to this account will be distributed as staking rewards.\n\nNOTE: This is a Mars Hub address with the `mars` bech32 prefix, which may not be recognized by the `api.addr_validate` method.", + "type": "string", + "enum": ["fee_collector"] + }, + { + "description": "The module account controlled by the by Mars Hub's x/safety module. Funds sent to this account will be deposited into the safety fund.\n\nNOTE: This is a Mars Hub address with the `mars` bech32 prefix, which may not be recognized by the `api.addr_validate` method.", + "type": "string", + "enum": ["safety_fund"] + } + ] + }, + "OwnerUpdate": { + "oneOf": [ + { + "description": "Proposes a new owner to take role. Only current owner can execute.", + "type": "object", + "required": ["propose_new_owner"], + "properties": { + "propose_new_owner": { + "type": "object", + "required": ["proposed"], + "properties": { + "proposed": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Clears the currently proposed owner. Only current owner can execute.", + "type": "string", + "enum": ["clear_proposed"] + }, + { + "description": "Promotes the proposed owner to be the current one. Only the proposed owner can execute.", + "type": "string", + "enum": ["accept_proposed"] + }, + { + "description": "Throws away the keys to the Owner role forever. Once done, no owner can ever be set later.", + "type": "string", + "enum": ["abolish_owner_role"] + } + ] + } + } + }, + { + "description": "Manages admin role state", + "type": "object", + "required": ["update_owner"], + "properties": { + "update_owner": { + "$ref": "#/definitions/OwnerUpdate" + } + }, + "additionalProperties": false, + "$schema": "http://json-schema.org/draft-07/schema#", + "definitions": { + "MarsAddressType": { + "oneOf": [ + { + "type": "string", + "enum": ["incentives", "oracle", "red_bank", "rewards_collector"] + }, + { + "description": "Protocol admin is an ICS-27 interchain account controlled by Mars Hub's x/gov module. This account will take the owner and admin roles of red-bank contracts.\n\nOwner means the account who can invoke certain priviliged execute methods on a contract, such as updating the config. Admin means the account who can migrate a contract.", + "type": "string", + "enum": ["protocol_admin"] + }, + { + "description": "The `fee_collector` module account controlled by Mars Hub's x/distribution module. Funds sent to this account will be distributed as staking rewards.\n\nNOTE: This is a Mars Hub address with the `mars` bech32 prefix, which may not be recognized by the `api.addr_validate` method.", + "type": "string", + "enum": ["fee_collector"] + }, + { + "description": "The module account controlled by the by Mars Hub's x/safety module. Funds sent to this account will be deposited into the safety fund.\n\nNOTE: This is a Mars Hub address with the `mars` bech32 prefix, which may not be recognized by the `api.addr_validate` method.", + "type": "string", + "enum": ["safety_fund"] + } + ] + }, + "OwnerUpdate": { + "oneOf": [ + { + "description": "Proposes a new owner to take role. Only current owner can execute.", + "type": "object", + "required": ["propose_new_owner"], + "properties": { + "propose_new_owner": { + "type": "object", + "required": ["proposed"], + "properties": { + "proposed": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Clears the currently proposed owner. Only current owner can execute.", + "type": "string", + "enum": ["clear_proposed"] + }, + { + "description": "Promotes the proposed owner to be the current one. Only the proposed owner can execute.", + "type": "string", + "enum": ["accept_proposed"] + }, + { + "description": "Throws away the keys to the Owner role forever. Once done, no owner can ever be set later.", + "type": "string", + "enum": ["abolish_owner_role"] + } + ] + } + } + } +] diff --git a/src/lib/stores/schema-test-suite/query-schema-output.json b/src/lib/stores/schema-test-suite/query-schema-output.json new file mode 100644 index 000000000..106861581 --- /dev/null +++ b/src/lib/stores/schema-test-suite/query-schema-output.json @@ -0,0 +1,355 @@ +[ + [ + { + "description": "Get config", + "type": "object", + "required": ["config"], + "properties": { + "config": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false, + "$schema": "http://json-schema.org/draft-07/schema#", + "definitions": { + "MarsAddressType": { + "oneOf": [ + { + "type": "string", + "enum": ["incentives", "oracle", "red_bank", "rewards_collector"] + }, + { + "description": "Protocol admin is an ICS-27 interchain account controlled by Mars Hub's x/gov module. This account will take the owner and admin roles of red-bank contracts.\n\nOwner means the account who can invoke certain priviliged execute methods on a contract, such as updating the config. Admin means the account who can migrate a contract.", + "type": "string", + "enum": ["protocol_admin"] + }, + { + "description": "The `fee_collector` module account controlled by Mars Hub's x/distribution module. Funds sent to this account will be distributed as staking rewards.\n\nNOTE: This is a Mars Hub address with the `mars` bech32 prefix, which may not be recognized by the `api.addr_validate` method.", + "type": "string", + "enum": ["fee_collector"] + }, + { + "description": "The module account controlled by the by Mars Hub's x/safety module. Funds sent to this account will be deposited into the safety fund.\n\nNOTE: This is a Mars Hub address with the `mars` bech32 prefix, which may not be recognized by the `api.addr_validate` method.", + "type": "string", + "enum": ["safety_fund"] + } + ] + } + } + }, + { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "ConfigResponse", + "type": "object", + "required": ["prefix"], + "properties": { + "owner": { + "description": "The contract's owner", + "type": ["string", "null"] + }, + "prefix": { + "description": "The address prefix of the chain this contract is deployed on", + "type": "string" + }, + "proposed_new_owner": { + "description": "The contract's proposed owner", + "type": ["string", "null"] + } + }, + "additionalProperties": false, + "readOnly": true + } + ], + [ + { + "description": "Get a single address", + "type": "object", + "required": ["address"], + "properties": { + "address": { + "$ref": "#/definitions/MarsAddressType" + } + }, + "additionalProperties": false, + "$schema": "http://json-schema.org/draft-07/schema#", + "definitions": { + "MarsAddressType": { + "oneOf": [ + { + "type": "string", + "enum": ["incentives", "oracle", "red_bank", "rewards_collector"] + }, + { + "description": "Protocol admin is an ICS-27 interchain account controlled by Mars Hub's x/gov module. This account will take the owner and admin roles of red-bank contracts.\n\nOwner means the account who can invoke certain priviliged execute methods on a contract, such as updating the config. Admin means the account who can migrate a contract.", + "type": "string", + "enum": ["protocol_admin"] + }, + { + "description": "The `fee_collector` module account controlled by Mars Hub's x/distribution module. Funds sent to this account will be distributed as staking rewards.\n\nNOTE: This is a Mars Hub address with the `mars` bech32 prefix, which may not be recognized by the `api.addr_validate` method.", + "type": "string", + "enum": ["fee_collector"] + }, + { + "description": "The module account controlled by the by Mars Hub's x/safety module. Funds sent to this account will be deposited into the safety fund.\n\nNOTE: This is a Mars Hub address with the `mars` bech32 prefix, which may not be recognized by the `api.addr_validate` method.", + "type": "string", + "enum": ["safety_fund"] + } + ] + } + } + }, + { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "AddressResponseItem", + "type": "object", + "required": ["address", "address_type"], + "properties": { + "address": { + "description": "Address value", + "type": "string" + }, + "address_type": { + "description": "The type of address", + "allOf": [ + { + "$ref": "#/definitions/MarsAddressType" + } + ] + } + }, + "additionalProperties": false, + "definitions": { + "MarsAddressType": { + "oneOf": [ + { + "type": "string", + "enum": ["incentives", "oracle", "red_bank", "rewards_collector"] + }, + { + "description": "Protocol admin is an ICS-27 interchain account controlled by Mars Hub's x/gov module. This account will take the owner and admin roles of red-bank contracts.\n\nOwner means the account who can invoke certain priviliged execute methods on a contract, such as updating the config. Admin means the account who can migrate a contract.", + "type": "string", + "enum": ["protocol_admin"] + }, + { + "description": "The `fee_collector` module account controlled by Mars Hub's x/distribution module. Funds sent to this account will be distributed as staking rewards.\n\nNOTE: This is a Mars Hub address with the `mars` bech32 prefix, which may not be recognized by the `api.addr_validate` method.", + "type": "string", + "enum": ["fee_collector"] + }, + { + "description": "The module account controlled by the by Mars Hub's x/safety module. Funds sent to this account will be deposited into the safety fund.\n\nNOTE: This is a Mars Hub address with the `mars` bech32 prefix, which may not be recognized by the `api.addr_validate` method.", + "type": "string", + "enum": ["safety_fund"] + } + ] + } + }, + "readOnly": true + } + ], + [ + { + "description": "Get a list of addresses", + "type": "object", + "required": ["addresses"], + "properties": { + "addresses": { + "type": "array", + "items": { + "$ref": "#/definitions/MarsAddressType" + } + } + }, + "additionalProperties": false, + "$schema": "http://json-schema.org/draft-07/schema#", + "definitions": { + "MarsAddressType": { + "oneOf": [ + { + "type": "string", + "enum": ["incentives", "oracle", "red_bank", "rewards_collector"] + }, + { + "description": "Protocol admin is an ICS-27 interchain account controlled by Mars Hub's x/gov module. This account will take the owner and admin roles of red-bank contracts.\n\nOwner means the account who can invoke certain priviliged execute methods on a contract, such as updating the config. Admin means the account who can migrate a contract.", + "type": "string", + "enum": ["protocol_admin"] + }, + { + "description": "The `fee_collector` module account controlled by Mars Hub's x/distribution module. Funds sent to this account will be distributed as staking rewards.\n\nNOTE: This is a Mars Hub address with the `mars` bech32 prefix, which may not be recognized by the `api.addr_validate` method.", + "type": "string", + "enum": ["fee_collector"] + }, + { + "description": "The module account controlled by the by Mars Hub's x/safety module. Funds sent to this account will be deposited into the safety fund.\n\nNOTE: This is a Mars Hub address with the `mars` bech32 prefix, which may not be recognized by the `api.addr_validate` method.", + "type": "string", + "enum": ["safety_fund"] + } + ] + } + } + }, + { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Array_of_AddressResponseItem", + "type": "array", + "items": { + "$ref": "#/definitions/AddressResponseItem" + }, + "definitions": { + "AddressResponseItem": { + "type": "object", + "required": ["address", "address_type"], + "properties": { + "address": { + "description": "Address value", + "type": "string" + }, + "address_type": { + "description": "The type of address", + "allOf": [ + { + "$ref": "#/definitions/MarsAddressType" + } + ] + } + }, + "additionalProperties": false + }, + "MarsAddressType": { + "oneOf": [ + { + "type": "string", + "enum": ["incentives", "oracle", "red_bank", "rewards_collector"] + }, + { + "description": "Protocol admin is an ICS-27 interchain account controlled by Mars Hub's x/gov module. This account will take the owner and admin roles of red-bank contracts.\n\nOwner means the account who can invoke certain priviliged execute methods on a contract, such as updating the config. Admin means the account who can migrate a contract.", + "type": "string", + "enum": ["protocol_admin"] + }, + { + "description": "The `fee_collector` module account controlled by Mars Hub's x/distribution module. Funds sent to this account will be distributed as staking rewards.\n\nNOTE: This is a Mars Hub address with the `mars` bech32 prefix, which may not be recognized by the `api.addr_validate` method.", + "type": "string", + "enum": ["fee_collector"] + }, + { + "description": "The module account controlled by the by Mars Hub's x/safety module. Funds sent to this account will be deposited into the safety fund.\n\nNOTE: This is a Mars Hub address with the `mars` bech32 prefix, which may not be recognized by the `api.addr_validate` method.", + "type": "string", + "enum": ["safety_fund"] + } + ] + } + }, + "readOnly": true + } + ], + [ + { + "description": "Query all stored addresses with pagination", + "type": "object", + "required": ["all_addresses"], + "properties": { + "all_addresses": { + "type": "object", + "properties": { + "limit": { + "type": ["integer", "null"], + "format": "uint32", + "minimum": 0 + }, + "start_after": { + "anyOf": [ + { + "$ref": "#/definitions/MarsAddressType" + }, + { + "type": "null" + } + ] + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false, + "$schema": "http://json-schema.org/draft-07/schema#", + "definitions": { + "MarsAddressType": { + "oneOf": [ + { + "type": "string", + "enum": ["incentives", "oracle", "red_bank", "rewards_collector"] + }, + { + "description": "Protocol admin is an ICS-27 interchain account controlled by Mars Hub's x/gov module. This account will take the owner and admin roles of red-bank contracts.\n\nOwner means the account who can invoke certain priviliged execute methods on a contract, such as updating the config. Admin means the account who can migrate a contract.", + "type": "string", + "enum": ["protocol_admin"] + }, + { + "description": "The `fee_collector` module account controlled by Mars Hub's x/distribution module. Funds sent to this account will be distributed as staking rewards.\n\nNOTE: This is a Mars Hub address with the `mars` bech32 prefix, which may not be recognized by the `api.addr_validate` method.", + "type": "string", + "enum": ["fee_collector"] + }, + { + "description": "The module account controlled by the by Mars Hub's x/safety module. Funds sent to this account will be deposited into the safety fund.\n\nNOTE: This is a Mars Hub address with the `mars` bech32 prefix, which may not be recognized by the `api.addr_validate` method.", + "type": "string", + "enum": ["safety_fund"] + } + ] + } + } + }, + { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Array_of_AddressResponseItem", + "type": "array", + "items": { + "$ref": "#/definitions/AddressResponseItem" + }, + "definitions": { + "AddressResponseItem": { + "type": "object", + "required": ["address", "address_type"], + "properties": { + "address": { + "description": "Address value", + "type": "string" + }, + "address_type": { + "description": "The type of address", + "allOf": [ + { + "$ref": "#/definitions/MarsAddressType" + } + ] + } + }, + "additionalProperties": false + }, + "MarsAddressType": { + "oneOf": [ + { + "type": "string", + "enum": ["incentives", "oracle", "red_bank", "rewards_collector"] + }, + { + "description": "Protocol admin is an ICS-27 interchain account controlled by Mars Hub's x/gov module. This account will take the owner and admin roles of red-bank contracts.\n\nOwner means the account who can invoke certain priviliged execute methods on a contract, such as updating the config. Admin means the account who can migrate a contract.", + "type": "string", + "enum": ["protocol_admin"] + }, + { + "description": "The `fee_collector` module account controlled by Mars Hub's x/distribution module. Funds sent to this account will be distributed as staking rewards.\n\nNOTE: This is a Mars Hub address with the `mars` bech32 prefix, which may not be recognized by the `api.addr_validate` method.", + "type": "string", + "enum": ["fee_collector"] + }, + { + "description": "The module account controlled by the by Mars Hub's x/safety module. Funds sent to this account will be deposited into the safety fund.\n\nNOTE: This is a Mars Hub address with the `mars` bech32 prefix, which may not be recognized by the `api.addr_validate` method.", + "type": "string", + "enum": ["safety_fund"] + } + ] + } + }, + "readOnly": true + } + ] +] diff --git a/src/lib/stores/schema-example.json b/src/lib/stores/schema-test-suite/schema-example.json similarity index 100% rename from src/lib/stores/schema-example.json rename to src/lib/stores/schema-test-suite/schema-example.json diff --git a/src/lib/stores/schema.test.ts b/src/lib/stores/schema.test.ts index dd842c0e5..fec2c9cca 100644 --- a/src/lib/stores/schema.test.ts +++ b/src/lib/stores/schema.test.ts @@ -1,5 +1,7 @@ import { SchemaProperties, SchemaStore } from "./schema"; -import exampleSchema from "./schema-example.json"; +import executeSchemaOutput from "./schema-test-suite/execute-schema-output.json"; +import querySchemaOutput from "./schema-test-suite/query-schema-output.json"; +import exampleSchema from "./schema-test-suite/schema-example.json"; let schemaStore: SchemaStore; const codeHash = "a1b2c3d4e5f6g7"; @@ -74,3 +76,32 @@ describe("getSchemaProperty", () => { ).toBeUndefined(); }); }); + +describe("getQuerySchemaFormArray", () => { + beforeAll(() => { + schemaStore.saveNewSchema(codeHash, exampleSchema); + }); + test("correctly get form array for query schema", () => { + expect(schemaStore.getQuerySchemaFormArray(codeHash)).toEqual( + querySchemaOutput + ); + }); + + test("correctly return undefined for non-existent code hash", () => { + expect(schemaStore.getQuerySchemaFormArray("randomHash")).toBeUndefined(); + }); +}); + +describe("getExecuteSchemaFormArray", () => { + beforeAll(() => { + schemaStore.saveNewSchema(codeHash, exampleSchema); + }); + test("correctly get form array for execute schema", () => { + expect(schemaStore.getExecuteSchemaFormArray(codeHash)).toEqual( + executeSchemaOutput + ); + }); + test("correctly return undefined for non-existent code hash", () => { + expect(schemaStore.getExecuteSchemaFormArray("randomHash")).toBeUndefined(); + }); +}); diff --git a/src/lib/stores/schema.ts b/src/lib/stores/schema.ts index 13c001b49..3190b566f 100644 --- a/src/lib/stores/schema.ts +++ b/src/lib/stores/schema.ts @@ -5,6 +5,19 @@ import type { Dict, Option } from "lib/types"; type JsonSchema = Dict; +// InternalMsg interface assists with accessing certain known properties without getting type errors when writing getter functions +interface InternalSchema { + $schema: string; + oneOf: Array>; + definitions: Dict; + [key: string]: unknown; +} + +interface InternalQueryMsg { + required: string[]; + [key: string]: unknown; +} + // TODO: this is derived from an example schema, ensure that the properties are comprehensively defined export enum SchemaProperties { CONTRACT_NAME = "contract_name", @@ -54,4 +67,47 @@ export class SchemaStore { getSchemaProperty(codeHash: string, property: SchemaProperties) { return this.jsonSchemas[codeHash]?.[property]; } + + getQuerySchemaFormArray(codeHash: string) { + const responsesSchema = this.getSchemaProperty( + codeHash, + SchemaProperties.RESPONSES + ) as { [key: string]: object }; + const querySchema = this.getSchemaProperty( + codeHash, + SchemaProperties.QUERY + ) as InternalSchema; + + if (!querySchema || !responsesSchema) return undefined; + + return querySchema.oneOf.map((msg) => { + const response = responsesSchema[(msg as InternalQueryMsg).required[0]]; + return [ + { + ...msg, + $schema: querySchema.$schema, + definitions: querySchema.definitions, + }, + { + ...response, + readOnly: true, + }, + ]; + }); + } + + getExecuteSchemaFormArray(codeHash: string) { + const executeSchema = this.getSchemaProperty( + codeHash, + SchemaProperties.EXECUTE + ) as InternalSchema; + + if (!executeSchema) return undefined; + + return executeSchema.oneOf.map((msg) => ({ + ...msg, + $schema: executeSchema.$schema, + definitions: executeSchema.definitions, + })); + } } From 216106f8ddd46244f8584de8a46b1c46c664b586 Mon Sep 17 00:00:00 2001 From: poomthiti Date: Mon, 31 Jul 2023 12:05:47 +0700 Subject: [PATCH 06/94] refactor: getters and schema typing --- package.json | 1 + src/lib/stores/schema.test.ts | 16 +++---- src/lib/stores/schema.ts | 86 +++++++++++++++++---------------- yarn.lock | 90 ++++++++++++++++++++++++++++++++++- 4 files changed, 142 insertions(+), 51 deletions(-) diff --git a/package.json b/package.json index b0eae819b..c353a4e52 100644 --- a/package.json +++ b/package.json @@ -37,6 +37,7 @@ "@cosmos-kit/react": "^1.3.31", "@graphql-codegen/cli": "^2.13.12", "@graphql-codegen/client-preset": "^1.1.4", + "@rjsf/utils": "^5.10.0", "@rx-stream/pipe": "^0.7.1", "@sentry/nextjs": "7.37.0", "@tanstack/react-query": "^4.16.1", diff --git a/src/lib/stores/schema.test.ts b/src/lib/stores/schema.test.ts index fec2c9cca..687b5df36 100644 --- a/src/lib/stores/schema.test.ts +++ b/src/lib/stores/schema.test.ts @@ -1,9 +1,11 @@ +import type { CodeSchema } from "./schema"; import { SchemaProperties, SchemaStore } from "./schema"; import executeSchemaOutput from "./schema-test-suite/execute-schema-output.json"; import querySchemaOutput from "./schema-test-suite/query-schema-output.json"; -import exampleSchema from "./schema-test-suite/schema-example.json"; +import schema from "./schema-test-suite/schema-example.json"; let schemaStore: SchemaStore; +const exampleSchema = schema as unknown as CodeSchema; const codeHash = "a1b2c3d4e5f6g7"; beforeAll(() => { @@ -82,13 +84,11 @@ describe("getQuerySchemaFormArray", () => { schemaStore.saveNewSchema(codeHash, exampleSchema); }); test("correctly get form array for query schema", () => { - expect(schemaStore.getQuerySchemaFormArray(codeHash)).toEqual( - querySchemaOutput - ); + expect(schemaStore.getQuerySchema(codeHash)).toEqual(querySchemaOutput); }); test("correctly return undefined for non-existent code hash", () => { - expect(schemaStore.getQuerySchemaFormArray("randomHash")).toBeUndefined(); + expect(schemaStore.getQuerySchema("randomHash")).toBeUndefined(); }); }); @@ -97,11 +97,9 @@ describe("getExecuteSchemaFormArray", () => { schemaStore.saveNewSchema(codeHash, exampleSchema); }); test("correctly get form array for execute schema", () => { - expect(schemaStore.getExecuteSchemaFormArray(codeHash)).toEqual( - executeSchemaOutput - ); + expect(schemaStore.getExecuteSchema(codeHash)).toEqual(executeSchemaOutput); }); test("correctly return undefined for non-existent code hash", () => { - expect(schemaStore.getExecuteSchemaFormArray("randomHash")).toBeUndefined(); + expect(schemaStore.getExecuteSchema("randomHash")).toBeUndefined(); }); }); diff --git a/src/lib/stores/schema.ts b/src/lib/stores/schema.ts index 3190b566f..3a80d8686 100644 --- a/src/lib/stores/schema.ts +++ b/src/lib/stores/schema.ts @@ -1,23 +1,10 @@ +import type { RJSFSchema as JsonSchema } from "@rjsf/utils"; +import type { JSONSchema7 } from "json-schema"; import { makeAutoObservable } from "mobx"; import { makePersistable } from "mobx-persist-store"; import type { Dict, Option } from "lib/types"; -type JsonSchema = Dict; - -// InternalMsg interface assists with accessing certain known properties without getting type errors when writing getter functions -interface InternalSchema { - $schema: string; - oneOf: Array>; - definitions: Dict; - [key: string]: unknown; -} - -interface InternalQueryMsg { - required: string[]; - [key: string]: unknown; -} - // TODO: this is derived from an example schema, ensure that the properties are comprehensively defined export enum SchemaProperties { CONTRACT_NAME = "contract_name", @@ -31,6 +18,20 @@ export enum SchemaProperties { RESPONSES = "responses", } +type NullableJsonSchema = JsonSchema | null; + +export interface CodeSchema { + [SchemaProperties.CONTRACT_NAME]: string; + [SchemaProperties.CONTRACT_VERSION]: string; + [SchemaProperties.IDL_VERSION]: string; + [SchemaProperties.INSTANTIATE]: NonNullable; + [SchemaProperties.EXECUTE]: NullableJsonSchema; + [SchemaProperties.QUERY]: NullableJsonSchema; + [SchemaProperties.MIGRATE]: NullableJsonSchema; + [SchemaProperties.SUDO]: NullableJsonSchema; + [SchemaProperties.RESPONSES]: { [key: string]: JsonSchema }; +} + export class SchemaStore { /** * @remarks code hash as key and json schema as value (annotated as Dict>) @@ -43,7 +44,7 @@ export class SchemaStore { * } * } */ - jsonSchemas: Dict; + jsonSchemas: Dict; constructor() { this.jsonSchemas = {}; @@ -56,56 +57,61 @@ export class SchemaStore { }); } - saveNewSchema(codeHash: string, schema: JsonSchema) { + saveNewSchema(codeHash: string, schema: CodeSchema) { this.jsonSchemas[codeHash] = schema; } - getSchemaByCodeHash(codeHash: string): Option { + getSchemaByCodeHash(codeHash: string): Option { return this.jsonSchemas[codeHash]; } - getSchemaProperty(codeHash: string, property: SchemaProperties) { + getSchemaProperty(codeHash: string, property: T) { return this.jsonSchemas[codeHash]?.[property]; } - getQuerySchemaFormArray(codeHash: string) { + getQuerySchema(codeHash: string): Option> { const responsesSchema = this.getSchemaProperty( codeHash, SchemaProperties.RESPONSES - ) as { [key: string]: object }; + ); const querySchema = this.getSchemaProperty( codeHash, SchemaProperties.QUERY - ) as InternalSchema; + ); if (!querySchema || !responsesSchema) return undefined; - return querySchema.oneOf.map((msg) => { - const response = responsesSchema[(msg as InternalQueryMsg).required[0]]; - return [ - { - ...msg, - $schema: querySchema.$schema, - definitions: querySchema.definitions, - }, - { - ...response, - readOnly: true, - }, - ]; - }); + return querySchema.oneOf + ?.map((msg) => { + const schema7 = msg as JSONSchema7; + const { required } = schema7; + return ( + required !== undefined && [ + { + ...schema7, + $schema: querySchema.$schema, + definitions: querySchema.definitions, + }, + { + ...responsesSchema[required[0]], + readOnly: true, + }, + ] + ); + }) + .filter((tuple) => Boolean(tuple)) as Array<[JSONSchema7, JsonSchema]>; } - getExecuteSchemaFormArray(codeHash: string) { + getExecuteSchema(codeHash: string): Option> { const executeSchema = this.getSchemaProperty( codeHash, SchemaProperties.EXECUTE - ) as InternalSchema; + ); if (!executeSchema) return undefined; - return executeSchema.oneOf.map((msg) => ({ - ...msg, + return executeSchema.oneOf?.map((msg) => ({ + ...(msg as JSONSchema7), $schema: executeSchema.$schema, definitions: executeSchema.definitions, })); diff --git a/yarn.lock b/yarn.lock index 794e353a4..5976bc60f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4388,6 +4388,17 @@ resolved "https://registry.npmjs.org/@repeaterjs/repeater/-/repeater-3.0.4.tgz" integrity sha512-AW8PKd6iX3vAZ0vA43nOUOnbq/X5ihgU+mSXXqunMkeQADGiqw/PY0JNeYtD5sr0PAy51YPgAPbDoeapv9r8WA== +"@rjsf/utils@^5.10.0": + version "5.10.0" + resolved "https://registry.yarnpkg.com/@rjsf/utils/-/utils-5.10.0.tgz#502eaa8db3ba2a8f31a3c963158e62fd96f8980a" + integrity sha512-HGytUxCGtV6OCOw4PbjFcksxrPIxUt0y3T9oqCTsP4xiqnLfve4ZfY9FkbHzPSGOXVp57yCNNEZTWiK6tcV9uA== + dependencies: + json-schema-merge-allof "^0.8.1" + jsonpointer "^5.0.1" + lodash "^4.17.21" + lodash-es "^4.17.21" + react-is "^18.2.0" + "@rollup/plugin-commonjs@24.0.0": version "24.0.0" resolved "https://registry.yarnpkg.com/@rollup/plugin-commonjs/-/plugin-commonjs-24.0.0.tgz#fb7cf4a6029f07ec42b25daa535c75b05a43f75c" @@ -6339,6 +6350,25 @@ compare-func@^2.0.0: array-ify "^1.0.0" dot-prop "^5.1.0" +compute-gcd@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/compute-gcd/-/compute-gcd-1.2.1.tgz#34d639f3825625e1357ce81f0e456a6249d8c77f" + integrity sha512-TwMbxBNz0l71+8Sc4czv13h4kEqnchV9igQZBi6QUaz09dnz13juGnnaWWJTRsP3brxOoxeB4SA2WELLw1hCtg== + dependencies: + validate.io-array "^1.0.3" + validate.io-function "^1.0.2" + validate.io-integer-array "^1.0.0" + +compute-lcm@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/compute-lcm/-/compute-lcm-1.1.2.tgz#9107c66b9dca28cefb22b4ab4545caac4034af23" + integrity sha512-OFNPdQAXnQhDSKioX8/XYT6sdUlXwpeMjfd6ApxMJfyZ4GxmLR1xvMERctlYhlHwIiz6CSpBc2+qYKjHGZw4TQ== + dependencies: + compute-gcd "^1.2.1" + validate.io-array "^1.0.3" + validate.io-function "^1.0.2" + validate.io-integer-array "^1.0.0" + compute-scroll-into-view@1.0.14: version "1.0.14" resolved "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-1.0.14.tgz" @@ -9127,6 +9157,22 @@ json-parse-even-better-errors@^2.3.0: resolved "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz" integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== +json-schema-compare@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/json-schema-compare/-/json-schema-compare-0.2.2.tgz#dd601508335a90c7f4cfadb6b2e397225c908e56" + integrity sha512-c4WYmDKyJXhs7WWvAWm3uIYnfyWFoIp+JEoX34rctVvEkMYCPGhXtvmFFXiffBbxfZsvQ0RNnV5H7GvDF5HCqQ== + dependencies: + lodash "^4.17.4" + +json-schema-merge-allof@^0.8.1: + version "0.8.1" + resolved "https://registry.yarnpkg.com/json-schema-merge-allof/-/json-schema-merge-allof-0.8.1.tgz#ed2828cdd958616ff74f932830a26291789eaaf2" + integrity sha512-CTUKmIlPJbsWfzRRnOXz+0MjIqvnleIXwFTzz+t9T86HnYX/Rozria6ZVGLktAU9e+NygNljveP+yxqtQp/Q4w== + dependencies: + compute-lcm "^1.1.2" + json-schema-compare "^0.2.2" + lodash "^4.17.20" + json-schema-traverse@^0.4.1: version "0.4.1" resolved "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz" @@ -9198,6 +9244,11 @@ jsonparse@^1.2.0: resolved "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz" integrity sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA= +jsonpointer@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-5.0.1.tgz#2110e0af0900fd37467b5907ecd13a7884a1b559" + integrity sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ== + jsonwebtoken@^8.5.1: version "8.5.1" resolved "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz" @@ -9395,6 +9446,11 @@ locate-path@^6.0.0: dependencies: p-locate "^5.0.0" +lodash-es@^4.17.21: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee" + integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw== + lodash.debounce@^4.0.8: version "4.0.8" resolved "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz" @@ -9470,7 +9526,7 @@ lodash.once@^4.0.0: resolved "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz" integrity sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg== -lodash@4.17.21, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@~4.17.0: +lodash@4.17.21, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.4, lodash@~4.17.0: version "4.17.21" resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -10648,7 +10704,7 @@ react-is@^16.13.1, react-is@^16.7.0: resolved "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== -react-is@^18.0.0: +react-is@^18.0.0, react-is@^18.2.0: version "18.2.0" resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b" integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w== @@ -12026,6 +12082,36 @@ validate-npm-package-license@^3.0.1: spdx-correct "^3.0.0" spdx-expression-parse "^3.0.0" +validate.io-array@^1.0.3: + version "1.0.6" + resolved "https://registry.yarnpkg.com/validate.io-array/-/validate.io-array-1.0.6.tgz#5b5a2cafd8f8b85abb2f886ba153f2d93a27774d" + integrity sha512-DeOy7CnPEziggrOO5CZhVKJw6S3Yi7e9e65R1Nl/RTN1vTQKnzjfvks0/8kQ40FP/dsjRAOd4hxmJ7uLa6vxkg== + +validate.io-function@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/validate.io-function/-/validate.io-function-1.0.2.tgz#343a19802ed3b1968269c780e558e93411c0bad7" + integrity sha512-LlFybRJEriSuBnUhQyG5bwglhh50EpTL2ul23MPIuR1odjO7XaMLFV8vHGwp7AZciFxtYOeiSCT5st+XSPONiQ== + +validate.io-integer-array@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/validate.io-integer-array/-/validate.io-integer-array-1.0.0.tgz#2cabde033293a6bcbe063feafe91eaf46b13a089" + integrity sha512-mTrMk/1ytQHtCY0oNO3dztafHYyGU88KL+jRxWuzfOmQb+4qqnWmI+gykvGp8usKZOM0H7keJHEbRaFiYA0VrA== + dependencies: + validate.io-array "^1.0.3" + validate.io-integer "^1.0.4" + +validate.io-integer@^1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/validate.io-integer/-/validate.io-integer-1.0.5.tgz#168496480b95be2247ec443f2233de4f89878068" + integrity sha512-22izsYSLojN/P6bppBqhgUDjCkr5RY2jd+N2a3DCAUey8ydvrZ/OkGvFPR7qfOpwR2LC5p4Ngzxz36g5Vgr/hQ== + dependencies: + validate.io-number "^1.0.3" + +validate.io-number@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/validate.io-number/-/validate.io-number-1.0.3.tgz#f63ffeda248bf28a67a8d48e0e3b461a1665baf8" + integrity sha512-kRAyotcbNaSYoDnXvb4MHg/0a1egJdLwS6oJ38TJY7aw9n93Fl/3blIXdyYvPOp55CNxywooG/3BcrwNrBpcSg== + value-or-promise@1.0.11, value-or-promise@^1.0.11: version "1.0.11" resolved "https://registry.npmjs.org/value-or-promise/-/value-or-promise-1.0.11.tgz" From a93d8bf0cd0347fd537d02600f1efa93fd882bdf Mon Sep 17 00:00:00 2001 From: poomthiti Date: Mon, 31 Jul 2023 18:12:33 +0700 Subject: [PATCH 07/94] feat: implement JSON schema upload drawer, pending schema storage wireup --- src/lib/app-fns/tx/upload.tsx | 2 + src/lib/app-provider/tx/upload.ts | 1 + src/lib/components/dropzone/config.ts | 28 ++ src/lib/components/dropzone/index.tsx | 27 +- src/lib/components/forms/FormStatus.tsx | 10 +- src/lib/components/forms/TextInput.tsx | 4 +- src/lib/components/upload/UploadCard.tsx | 99 +++++-- src/lib/components/upload/UploadSection.tsx | 5 +- src/lib/pages/proposal/store-code/index.tsx | 1 + src/lib/pages/upload/completed.tsx | 17 +- .../pages/upload/components/UploadMethod.tsx | 242 ++++++++++++++++++ .../pages/upload/components/UploadSchema.tsx | 57 ++++- src/lib/pages/upload/index.tsx | 1 + src/lib/styles/theme/components/form.ts | 13 +- src/lib/styles/theme/components/radio.ts | 4 +- 15 files changed, 457 insertions(+), 54 deletions(-) create mode 100644 src/lib/components/dropzone/config.ts create mode 100644 src/lib/pages/upload/components/UploadMethod.tsx diff --git a/src/lib/app-fns/tx/upload.tsx b/src/lib/app-fns/tx/upload.tsx index 8f14b8c86..78fec4d71 100644 --- a/src/lib/app-fns/tx/upload.tsx +++ b/src/lib/app-fns/tx/upload.tsx @@ -53,12 +53,14 @@ export const uploadContractTx = ({ }; const codeId = findAttr(mimicLog, "store_code", "code_id") ?? "0"; + const codeHash = findAttr(mimicLog, "store_code", "code_checksum") ?? ""; const txFee = txInfo.events.find((e) => e.type === "tx")?.attributes[0] .value; const formattedFee = txFee ? formatUFee(txFee) : "N/A"; onTxSucceed({ codeId: parseInt(codeId, 10).toString(), + codeHash, codeDisplayName: codeName || `${wasmFileName}(${codeId})`, txHash: txInfo.transactionHash, formattedFee, diff --git a/src/lib/app-provider/tx/upload.ts b/src/lib/app-provider/tx/upload.ts index b76700165..57ee35d98 100644 --- a/src/lib/app-provider/tx/upload.ts +++ b/src/lib/app-provider/tx/upload.ts @@ -10,6 +10,7 @@ import { composeStoreCodeMsg } from "lib/utils"; export interface UploadTxInternalResult { codeDisplayName: string; codeId: string; + codeHash: string; txHash: string; formattedFee: string; } diff --git a/src/lib/components/dropzone/config.ts b/src/lib/components/dropzone/config.ts new file mode 100644 index 000000000..7cada0f96 --- /dev/null +++ b/src/lib/components/dropzone/config.ts @@ -0,0 +1,28 @@ +import type { Accept } from "react-dropzone"; + +export type DropzoneFileType = "wasm" | "schema"; + +interface DropzoneConfig { + accept: Accept; + text: { + prettyFileType: string; + rawFileType: string; + }; +} + +export const DROPZONE_CONFIG: { [key in DropzoneFileType]: DropzoneConfig } = { + wasm: { + accept: { "application/wasm": [".wasm"] }, + text: { + prettyFileType: "Wasm", + rawFileType: ".wasm", + }, + }, + schema: { + accept: { "application/json": [".schema.json"] }, + text: { + prettyFileType: "JSON Schema", + rawFileType: ".schema.json", + }, + }, +}; diff --git a/src/lib/components/dropzone/index.tsx b/src/lib/components/dropzone/index.tsx index 4559e4d8d..deeefb35c 100644 --- a/src/lib/components/dropzone/index.tsx +++ b/src/lib/components/dropzone/index.tsx @@ -6,14 +6,21 @@ import { useDropzone } from "react-dropzone"; import { UploadIcon } from "../icon"; import { useWasmConfig } from "lib/app-provider"; +import type { DropzoneFileType } from "./config"; +import { DROPZONE_CONFIG } from "./config"; + interface DropZoneProps extends DetailedHTMLProps, HTMLDivElement> { setFile: (file: File) => void; + fileType: DropzoneFileType; } -export function DropZone({ setFile, ...componentProps }: DropZoneProps) { +export function DropZone({ + setFile, + fileType, + ...componentProps +}: DropZoneProps) { const wasm = useWasmConfig({ shouldRedirect: false }); - const onDrop = useCallback( (file: File[]) => { setFile(file[0]); @@ -21,16 +28,17 @@ export function DropZone({ setFile, ...componentProps }: DropZoneProps) { [setFile] ); + const config = DROPZONE_CONFIG[fileType]; + // Throwing error when wasm is disabled will cause the page to not redirect, so default value is assigned instead const maxSize = wasm.enabled ? wasm.storeCodeMaxFileSize : 0; + // TODO: JSON Schema file size ?? const { getRootProps, getInputProps, fileRejections } = useDropzone({ onDrop, maxFiles: 1, - accept: { - "application/wasm": [".wasm"], - }, - maxSize, + accept: config.accept, + maxSize: fileType === "wasm" ? maxSize : undefined, }); return ( @@ -61,10 +69,13 @@ export function DropZone({ setFile, ...componentProps }: DropZoneProps) { > Click to upload - or drag Wasm file here + + or drag {config.text.prettyFileType} file here + - .wasm (max. {maxSize / 1000}KB) + {config.text.rawFileType}{" "} + {fileType === "wasm" && `(max. ${maxSize / 1000}KB)`} {fileRejections.length > 0 && ( diff --git a/src/lib/components/forms/FormStatus.tsx b/src/lib/components/forms/FormStatus.tsx index d32e291d5..20e8c6efb 100644 --- a/src/lib/components/forms/FormStatus.tsx +++ b/src/lib/components/forms/FormStatus.tsx @@ -6,7 +6,7 @@ export type ResponseState = "init" | "loading" | "success" | "error"; export interface FormStatus { state: ResponseState; - message?: string; + message?: string | null; messageColor?: string; } @@ -40,13 +40,13 @@ export const getResponseMsg = (statusInfo: FormStatus, helperText = "") => { switch (statusInfo.state) { case "success": return ( - + {statusInfo.message} ); case "error": return ( - + {statusInfo.message} ); @@ -54,7 +54,9 @@ export const getResponseMsg = (statusInfo: FormStatus, helperText = "") => { case "loading": default: return ( - {helperText} + + {helperText} + ); } }; diff --git a/src/lib/components/forms/TextInput.tsx b/src/lib/components/forms/TextInput.tsx index e0b13ce70..49f4d7797 100644 --- a/src/lib/components/forms/TextInput.tsx +++ b/src/lib/components/forms/TextInput.tsx @@ -22,7 +22,7 @@ import { getResponseMsg, getStatusIcon } from "./FormStatus"; export interface TextInputProps extends FormControlProps { value: string; - setInputState: Dispatch>; + setInputState: Dispatch> | ((value: string) => void); label?: string; labelBgColor?: string; helperText?: string; @@ -71,7 +71,7 @@ export const TextInput = ({ maxLength={maxLength} /> - {status && getStatusIcon(status.state, "20px")} + {status && getStatusIcon(status.state, "16px")} diff --git a/src/lib/components/upload/UploadCard.tsx b/src/lib/components/upload/UploadCard.tsx index 44c2d9d1b..8e25e0a78 100644 --- a/src/lib/components/upload/UploadCard.tsx +++ b/src/lib/components/upload/UploadCard.tsx @@ -3,35 +3,82 @@ import big from "big.js"; import { CustomIcon, UploadIcon } from "lib/components/icon"; +type CardTheme = "primary" | "secondary"; + interface UploadCardProps { file: File; deleteFile: () => void; + theme?: CardTheme; + error?: string | null; } -export const UploadCard = ({ file, deleteFile }: UploadCardProps) => ( - - - - - {file.name} - - {big(file.size).div(1000).toFixed(0)} KB - +const getTheme = (theme: CardTheme) => { + switch (theme) { + case "secondary": + return { + bgColor: "gray.800", + border: "1px solid var(--chakra-colors-gray-700)", + iconColor: "gray.600", + }; + case "primary": + default: + return { + bgColor: "gray.900", + border: "none", + iconColor: "text.dark", + }; + } +}; +export const UploadCard = ({ + file, + deleteFile, + theme = "primary", + error, +}: UploadCardProps) => { + const themeConfig = getTheme(theme); + return ( + <> + + + + + {file.name} + + {big(file.size).div(1000).toFixed(0)} KB + + + + + + {error && ( + + )} + - - - -); + {error && ( + + {error} + + )} + + ); +}; diff --git a/src/lib/components/upload/UploadSection.tsx b/src/lib/components/upload/UploadSection.tsx index a6c81fd0a..00bb44ec2 100644 --- a/src/lib/components/upload/UploadSection.tsx +++ b/src/lib/components/upload/UploadSection.tsx @@ -206,7 +206,10 @@ export const UploadSection = ({ }} /> ) : ( - setValue("wasmFile", file)} /> + setValue("wasmFile", file)} + fileType="wasm" + /> )} { ) : ( uploadSectionSetValue("wasmFile", file)} + fileType="wasm" /> )} diff --git a/src/lib/pages/upload/completed.tsx b/src/lib/pages/upload/completed.tsx index 6197c825e..8e078da98 100644 --- a/src/lib/pages/upload/completed.tsx +++ b/src/lib/pages/upload/completed.tsx @@ -17,8 +17,13 @@ interface UploadCompleteProps { export const UploadComplete = observer(({ txResult }: UploadCompleteProps) => { const navigate = useInternalNavigate(); - // Retrieve attached state from local storage - const attached = false; + // Retrieve schema from local storage + const schema = { + wow: "asdasdsad", + wowza: "xzkcnzxlkczxnc", + instantiate: "sadkasdkamdaskldks", + }; + const attached = Boolean(schema); return ( @@ -69,7 +74,13 @@ export const UploadComplete = observer(({ txResult }: UploadCompleteProps) => { Your attached JSON schema will be stored locally on your device - + + + {!attached && ( diff --git a/src/lib/pages/upload/components/UploadMethod.tsx b/src/lib/pages/upload/components/UploadMethod.tsx new file mode 100644 index 000000000..1b9093c9f --- /dev/null +++ b/src/lib/pages/upload/components/UploadMethod.tsx @@ -0,0 +1,242 @@ +import { Button, Flex, Heading, Radio, RadioGroup } from "@chakra-ui/react"; +import type { Dispatch } from "react"; +import { useCallback, useReducer, useState } from "react"; + +import { DropZone } from "lib/components/dropzone"; +import type { ResponseState } from "lib/components/forms"; +import { TextInput } from "lib/components/forms"; +import JsonInput from "lib/components/json/JsonInput"; +import { UploadCard } from "lib/components/upload/UploadCard"; +import { jsonValidate } from "lib/utils"; + +enum Method { + UPLOAD_FILE = "upload-file", + LOAD_URL = "load-url", + FILL_MANUALLY = "fill-manually", +} + +type JsonState = Record; + +enum ActionType { + SET_SCHEMA = "set-schema", + SET_ERROR = "set-error", + RESET = "reset", +} + +type Action = { + type: ActionType; + method: Method; + schemaString?: string; + error?: string | null; +}; + +const initialJsonState: JsonState = { + [Method.UPLOAD_FILE]: { schemaString: "", error: null }, + [Method.LOAD_URL]: { schemaString: "", error: null }, + [Method.FILL_MANUALLY]: { schemaString: "", error: null }, +}; + +const reducer = (state: JsonState, action: Action): JsonState => { + switch (action.type) { + case "set-error": + return { + ...state, + [action.method]: { + schemaString: state[action.method].schemaString, + error: action.error, + }, + }; + case "set-schema": + return { + ...state, + [action.method]: { schemaString: action.schemaString, error: null }, + }; + case "reset": + default: + return initialJsonState; + } +}; + +const MethodRender = ({ + method, + state, + urlLoading, + dispatch, +}: { + method: Method; + state: JsonState; + urlLoading: boolean; + dispatch: Dispatch; +}) => { + const [jsonFile, setJsonFile] = useState(); + const { error, schemaString } = state[method]; + switch (method) { + case Method.UPLOAD_FILE: + return jsonFile ? ( + { + setJsonFile(undefined); + dispatch({ + type: ActionType.SET_SCHEMA, + method, + schemaString: "", + }); + }} + error={error} + /> + ) : ( + { + const reader = new FileReader(); + reader.onload = () => { + try { + const content = reader.result as string; + dispatch({ + type: ActionType.SET_SCHEMA, + method, + schemaString: content, + }); + } catch (err) { + throw new Error("Error reading or parsing json schema file"); + } + }; + reader.readAsText(file); + setJsonFile(file); + }} + /> + ); + case Method.LOAD_URL: { + let status: ResponseState = "init"; + if (urlLoading) status = "loading"; + else if (error) status = "error"; + return ( + <> + + Fill in URL to load JSON Schema + + + dispatch({ + type: ActionType.SET_SCHEMA, + method, + schemaString: url, + }) + } + /> + + ); + } + case Method.FILL_MANUALLY: + return ( + <> + + Contract Schema + + + dispatch({ + type: ActionType.SET_SCHEMA, + method, + schemaString: value, + }) + } + /> + + ); + default: + return null; + } +}; + +interface UploadMethodInterface { + closeDrawer: () => void; +} + +export const UploadMethod = ({ closeDrawer }: UploadMethodInterface) => { + const [method, setMethod] = useState(Method.UPLOAD_FILE); + const [jsonState, dispatchJsonState] = useReducer(reducer, initialJsonState); + const [urlLoading, setUrlLoading] = useState(false); + + const handleSave = useCallback(async () => { + let { schemaString } = jsonState[method]; + if (!schemaString) + return dispatchJsonState({ + type: ActionType.SET_ERROR, + method, + error: "Empty schema input", + }); + + // Retrieve schemaString from url + if (method === Method.LOAD_URL) { + try { + setUrlLoading(true); + const response = await fetch(schemaString); + if (!response.ok) { + setUrlLoading(false); + return dispatchJsonState({ + type: ActionType.SET_ERROR, + method, + error: response.statusText, + }); + } + schemaString = JSON.stringify(await response.json()); + } catch (err) { + setUrlLoading(false); + return dispatchJsonState({ + type: ActionType.SET_ERROR, + method, + error: (err as Error).message, + }); + } + } + const validSchema = + !jsonValidate(schemaString) && "instantiate" in JSON.parse(schemaString); + + if (!validSchema) { + setUrlLoading(false); + return dispatchJsonState({ + type: ActionType.SET_ERROR, + method, + error: "JSON Schema validation failed.", + }); + } + // ***Save schema to local storage*** + setUrlLoading(false); + closeDrawer(); + return dispatchJsonState({ type: ActionType.RESET, method }); + }, [method, jsonState, closeDrawer]); + + return ( + + setMethod(nextVal as Method)} + value={method} + mb={6} + > + + Upload File + Load from URL + Fill Manually + + + + + + ); +}; diff --git a/src/lib/pages/upload/components/UploadSchema.tsx b/src/lib/pages/upload/components/UploadSchema.tsx index 811293adb..365d695ca 100644 --- a/src/lib/pages/upload/components/UploadSchema.tsx +++ b/src/lib/pages/upload/components/UploadSchema.tsx @@ -17,7 +17,20 @@ import { observer } from "mobx-react-lite"; import { CustomIcon } from "lib/components/icon"; -const Content = ({ attached }: { attached: boolean }) => { +import { UploadMethod } from "./UploadMethod"; + +interface UploadSchemaContentInterface { + attached: boolean; + // fix type + schema: object; + codeId: string; +} + +const Content = ({ + attached, + schema, + codeId, +}: UploadSchemaContentInterface) => { const { isOpen, onOpen, onClose } = useDisclosure(); return ( <> @@ -39,7 +52,35 @@ const Content = ({ attached }: { attached: boolean }) => { JSON Schema attached - { variant="gray" aria-label="delete_schema" // onClick={() => onClose()} + // implement delete function for json schema store icon={ } @@ -71,7 +113,7 @@ const Content = ({ attached }: { attached: boolean }) => { - Attach JSON Schema for code ID “1” + Attach JSON Schema for code ID “{codeId}” @@ -86,6 +128,7 @@ const Content = ({ attached }: { attached: boolean }) => { borderRadius="8px" border="1px solid var(--chakra-colors-gray-700)" bg="gray.800" + mb={6} > Please note that the JSON schema you upload on our website will @@ -94,6 +137,7 @@ const Content = ({ attached }: { attached: boolean }) => { others. + @@ -101,8 +145,7 @@ const Content = ({ attached }: { attached: boolean }) => { ); }; -export const UploadSchema = observer(({ attached }: { attached: boolean }) => { - // Check attachment state from local storage +export const UploadSchema = observer((props: UploadSchemaContentInterface) => { return ( { p={4} w="full" borderRadius="4px" - mb={attached ? 8 : 0} + mb={props.attached ? 8 : 0} > - + ); }); diff --git a/src/lib/pages/upload/index.tsx b/src/lib/pages/upload/index.tsx index c341033c0..3156aef77 100644 --- a/src/lib/pages/upload/index.tsx +++ b/src/lib/pages/upload/index.tsx @@ -12,6 +12,7 @@ const UploadIndex = () => { const [txInfo, setTxInfo] = useState({ codeDisplayName: "", codeId: "", + codeHash: "", txHash: "", formattedFee: "", }); diff --git a/src/lib/styles/theme/components/form.ts b/src/lib/styles/theme/components/form.ts index 43c8354d9..145bf31ad 100644 --- a/src/lib/styles/theme/components/form.ts +++ b/src/lib/styles/theme/components/form.ts @@ -1,10 +1,19 @@ import type { ComponentStyleConfig } from "@chakra-ui/react"; +const errorMain = "error.main"; + export const Form: ComponentStyleConfig = { baseStyle: { container: { label: { - _invalid: { color: "error.main" }, + _invalid: { color: errorMain }, + }, + ".error-text": { + fontSize: "12px", + mt: 1, + "&.chakra-form__error-message": { + color: errorMain, + }, }, }, }, @@ -45,7 +54,7 @@ export const Form: ComponentStyleConfig = { color: "text.disabled", }, "&.chakra-form__error-message": { - color: "error.main", + color: errorMain, }, }, }, diff --git a/src/lib/styles/theme/components/radio.ts b/src/lib/styles/theme/components/radio.ts index a39618f1f..39f800d92 100644 --- a/src/lib/styles/theme/components/radio.ts +++ b/src/lib/styles/theme/components/radio.ts @@ -37,7 +37,6 @@ export const Radio: ComponentStyleConfig = { }, }, }, - variants: { card: { container: { @@ -63,4 +62,7 @@ export const Radio: ComponentStyleConfig = { }, }, }, + defaultProps: { + size: "lg", + }, }; From e987f38de52dd280a4b5b604a97d2513d8943c51 Mon Sep 17 00:00:00 2001 From: poomthiti Date: Thu, 3 Aug 2023 14:20:00 +0700 Subject: [PATCH 08/94] feat: wireup disabled state to button --- src/lib/components/json/JsonInput.tsx | 12 ++-- .../pages/upload/components/UploadMethod.tsx | 64 +++++++++++++------ .../pages/upload/components/UploadSchema.tsx | 7 +- 3 files changed, 54 insertions(+), 29 deletions(-) diff --git a/src/lib/components/json/JsonInput.tsx b/src/lib/components/json/JsonInput.tsx index f312f427a..90acfc999 100644 --- a/src/lib/components/json/JsonInput.tsx +++ b/src/lib/components/json/JsonInput.tsx @@ -12,8 +12,9 @@ const JsonEditor = dynamic(() => import("./JsonEditor"), { interface JsonInputProps { topic?: string; text?: string; - setText: (value: string) => void; minLines?: number; + setText: (value: string) => void; + validateFn?: (value: string) => string | null; } interface JsonState { @@ -72,8 +73,9 @@ const getResponse = (jsonState: JsonState) => { const JsonInput = ({ topic, text = "", - setText, minLines = 16, + setText, + validateFn = jsonValidate, }: JsonInputProps) => { const [jsonState, setJsonState] = useState({ state: "empty" }); @@ -84,7 +86,7 @@ const JsonInput = ({ useEffect(() => { const timeoutId = setTimeout(() => { - const error = jsonValidate(text); + const error = validateFn(text); if (text.trim().length === 0) setJsonState({ state: "empty" }); else if (error) setJsonState({ state: "error", errMsg: error }); @@ -92,10 +94,10 @@ const JsonInput = ({ }, 400); return () => clearTimeout(timeoutId); - }, [text]); + }, [text, validateFn]); const { color, response } = getResponse(jsonState); - const isValidJson = jsonValidate(text) === null; + const isValidJson = validateFn(text) === null; const showLines = useMemo(() => { const lines = jsonLineCount(text); diff --git a/src/lib/pages/upload/components/UploadMethod.tsx b/src/lib/pages/upload/components/UploadMethod.tsx index 1b9093c9f..9f9ed11fd 100644 --- a/src/lib/pages/upload/components/UploadMethod.tsx +++ b/src/lib/pages/upload/components/UploadMethod.tsx @@ -1,6 +1,6 @@ import { Button, Flex, Heading, Radio, RadioGroup } from "@chakra-ui/react"; import type { Dispatch } from "react"; -import { useCallback, useReducer, useState } from "react"; +import { useMemo, useCallback, useReducer, useState } from "react"; import { DropZone } from "lib/components/dropzone"; import type { ResponseState } from "lib/components/forms"; @@ -57,6 +57,15 @@ const reducer = (state: JsonState, action: Action): JsonState => { } }; +const validateSchema = (schemaString: string): string | null => { + return ( + jsonValidate(schemaString) ?? + ("instantiate" in JSON.parse(schemaString) + ? null + : "`instantiate` field is missing in JSON Schema") + ); +}; + const MethodRender = ({ method, state, @@ -92,19 +101,19 @@ const MethodRender = ({ setFile={async (file: File) => { const reader = new FileReader(); reader.onload = () => { - try { - const content = reader.result as string; - dispatch({ - type: ActionType.SET_SCHEMA, - method, - schemaString: content, - }); - } catch (err) { - throw new Error("Error reading or parsing json schema file"); - } + const content = reader.result as string; + dispatch({ + type: ActionType.SET_SCHEMA, + method, + schemaString: content, + }); }; - reader.readAsText(file); - setJsonFile(file); + try { + reader.readAsText(file); + setJsonFile(file); + } catch (err) { + // + } }} /> ); @@ -149,6 +158,7 @@ const MethodRender = ({ schemaString: value, }) } + validateFn={validateSchema} /> ); @@ -198,15 +208,14 @@ export const UploadMethod = ({ closeDrawer }: UploadMethodInterface) => { }); } } - const validSchema = - !jsonValidate(schemaString) && "instantiate" in JSON.parse(schemaString); + const schemaValidateError = validateSchema(schemaString); - if (!validSchema) { + if (schemaValidateError) { setUrlLoading(false); return dispatchJsonState({ type: ActionType.SET_ERROR, method, - error: "JSON Schema validation failed.", + error: schemaValidateError, }); } // ***Save schema to local storage*** @@ -215,6 +224,19 @@ export const UploadMethod = ({ closeDrawer }: UploadMethodInterface) => { return dispatchJsonState({ type: ActionType.RESET, method }); }, [method, jsonState, closeDrawer]); + const disabledState = useMemo(() => { + switch (method) { + case Method.UPLOAD_FILE: + return !jsonState[method].schemaString; + case Method.LOAD_URL: + return !jsonState[method].schemaString || urlLoading; + case Method.FILL_MANUALLY: + return Boolean(validateSchema(jsonState[method].schemaString)); + default: + return false; + } + }, [method, jsonState, urlLoading]); + return ( { urlLoading={urlLoading} dispatch={dispatchJsonState} /> - diff --git a/src/lib/pages/upload/components/UploadSchema.tsx b/src/lib/pages/upload/components/UploadSchema.tsx index 365d695ca..a0bad4a2b 100644 --- a/src/lib/pages/upload/components/UploadSchema.tsx +++ b/src/lib/pages/upload/components/UploadSchema.tsx @@ -62,7 +62,7 @@ const Content = ({ if (jsonWindow) { // Modify styling later jsonWindow.document.write( - "JSON Window" + `JSON Schema | Code ID ${codeId}` ); // Add styling @@ -70,11 +70,6 @@ const Content = ({ "" ); - // Change the URL of the new window - jsonWindow.document.write( - '' - ); - jsonWindow.document.write( `
${jsonString}
` ); From b1440017df961c3498c85e6892187c4fb344866c Mon Sep 17 00:00:00 2001 From: evilpeach Date: Thu, 3 Aug 2023 15:00:40 +0700 Subject: [PATCH 09/94] chore: refactor schema store --- src/lib/app-fns/tx/upload.tsx | 2 +- .../execute-schema-output.json | 292 +++++++++--------- src/lib/stores/schema.ts | 78 +++-- 3 files changed, 200 insertions(+), 172 deletions(-) diff --git a/src/lib/app-fns/tx/upload.tsx b/src/lib/app-fns/tx/upload.tsx index 8f14b8c86..01b635ab8 100644 --- a/src/lib/app-fns/tx/upload.tsx +++ b/src/lib/app-fns/tx/upload.tsx @@ -95,7 +95,7 @@ export const uploadContractTx = ({ }, ], receiptInfo: { - header: "Upload Wasm Complete", + header: "Upload Wasm Complete!", description: ( <> diff --git a/src/lib/stores/schema-test-suite/execute-schema-output.json b/src/lib/stores/schema-test-suite/execute-schema-output.json index 49e92c248..9ff869d97 100644 --- a/src/lib/stores/schema-test-suite/execute-schema-output.json +++ b/src/lib/stores/schema-test-suite/execute-schema-output.json @@ -1,159 +1,165 @@ [ { + "title": "set_address", "description": "Set address", - "type": "object", - "required": ["set_address"], - "properties": { - "set_address": { - "type": "object", - "required": ["address", "address_type"], - "properties": { - "address": { - "type": "string" - }, - "address_type": { - "$ref": "#/definitions/MarsAddressType" - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false, - "$schema": "http://json-schema.org/draft-07/schema#", - "definitions": { - "MarsAddressType": { - "oneOf": [ - { - "type": "string", - "enum": ["incentives", "oracle", "red_bank", "rewards_collector"] - }, - { - "description": "Protocol admin is an ICS-27 interchain account controlled by Mars Hub's x/gov module. This account will take the owner and admin roles of red-bank contracts.\n\nOwner means the account who can invoke certain priviliged execute methods on a contract, such as updating the config. Admin means the account who can migrate a contract.", - "type": "string", - "enum": ["protocol_admin"] - }, - { - "description": "The `fee_collector` module account controlled by Mars Hub's x/distribution module. Funds sent to this account will be distributed as staking rewards.\n\nNOTE: This is a Mars Hub address with the `mars` bech32 prefix, which may not be recognized by the `api.addr_validate` method.", - "type": "string", - "enum": ["fee_collector"] + "schema": { + "type": "object", + "required": ["set_address"], + "properties": { + "set_address": { + "type": "object", + "required": ["address", "address_type"], + "properties": { + "address": { + "type": "string" + }, + "address_type": { + "$ref": "#/definitions/MarsAddressType" + } }, - { - "description": "The module account controlled by the by Mars Hub's x/safety module. Funds sent to this account will be deposited into the safety fund.\n\nNOTE: This is a Mars Hub address with the `mars` bech32 prefix, which may not be recognized by the `api.addr_validate` method.", - "type": "string", - "enum": ["safety_fund"] - } - ] + "additionalProperties": false + } }, - "OwnerUpdate": { - "oneOf": [ - { - "description": "Proposes a new owner to take role. Only current owner can execute.", - "type": "object", - "required": ["propose_new_owner"], - "properties": { - "propose_new_owner": { - "type": "object", - "required": ["proposed"], - "properties": { - "proposed": { - "type": "string" - } - }, - "additionalProperties": false - } + "additionalProperties": false, + "$schema": "http://json-schema.org/draft-07/schema#", + "definitions": { + "MarsAddressType": { + "oneOf": [ + { + "type": "string", + "enum": ["incentives", "oracle", "red_bank", "rewards_collector"] }, - "additionalProperties": false - }, - { - "description": "Clears the currently proposed owner. Only current owner can execute.", - "type": "string", - "enum": ["clear_proposed"] - }, - { - "description": "Promotes the proposed owner to be the current one. Only the proposed owner can execute.", - "type": "string", - "enum": ["accept_proposed"] - }, - { - "description": "Throws away the keys to the Owner role forever. Once done, no owner can ever be set later.", - "type": "string", - "enum": ["abolish_owner_role"] - } - ] + { + "description": "Protocol admin is an ICS-27 interchain account controlled by Mars Hub's x/gov module. This account will take the owner and admin roles of red-bank contracts.\n\nOwner means the account who can invoke certain priviliged execute methods on a contract, such as updating the config. Admin means the account who can migrate a contract.", + "type": "string", + "enum": ["protocol_admin"] + }, + { + "description": "The `fee_collector` module account controlled by Mars Hub's x/distribution module. Funds sent to this account will be distributed as staking rewards.\n\nNOTE: This is a Mars Hub address with the `mars` bech32 prefix, which may not be recognized by the `api.addr_validate` method.", + "type": "string", + "enum": ["fee_collector"] + }, + { + "description": "The module account controlled by the by Mars Hub's x/safety module. Funds sent to this account will be deposited into the safety fund.\n\nNOTE: This is a Mars Hub address with the `mars` bech32 prefix, which may not be recognized by the `api.addr_validate` method.", + "type": "string", + "enum": ["safety_fund"] + } + ] + }, + "OwnerUpdate": { + "oneOf": [ + { + "description": "Proposes a new owner to take role. Only current owner can execute.", + "type": "object", + "required": ["propose_new_owner"], + "properties": { + "propose_new_owner": { + "type": "object", + "required": ["proposed"], + "properties": { + "proposed": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Clears the currently proposed owner. Only current owner can execute.", + "type": "string", + "enum": ["clear_proposed"] + }, + { + "description": "Promotes the proposed owner to be the current one. Only the proposed owner can execute.", + "type": "string", + "enum": ["accept_proposed"] + }, + { + "description": "Throws away the keys to the Owner role forever. Once done, no owner can ever be set later.", + "type": "string", + "enum": ["abolish_owner_role"] + } + ] + } } } }, { + "title": "update_owner", "description": "Manages admin role state", - "type": "object", - "required": ["update_owner"], - "properties": { - "update_owner": { - "$ref": "#/definitions/OwnerUpdate" - } - }, - "additionalProperties": false, - "$schema": "http://json-schema.org/draft-07/schema#", - "definitions": { - "MarsAddressType": { - "oneOf": [ - { - "type": "string", - "enum": ["incentives", "oracle", "red_bank", "rewards_collector"] - }, - { - "description": "Protocol admin is an ICS-27 interchain account controlled by Mars Hub's x/gov module. This account will take the owner and admin roles of red-bank contracts.\n\nOwner means the account who can invoke certain priviliged execute methods on a contract, such as updating the config. Admin means the account who can migrate a contract.", - "type": "string", - "enum": ["protocol_admin"] - }, - { - "description": "The `fee_collector` module account controlled by Mars Hub's x/distribution module. Funds sent to this account will be distributed as staking rewards.\n\nNOTE: This is a Mars Hub address with the `mars` bech32 prefix, which may not be recognized by the `api.addr_validate` method.", - "type": "string", - "enum": ["fee_collector"] - }, - { - "description": "The module account controlled by the by Mars Hub's x/safety module. Funds sent to this account will be deposited into the safety fund.\n\nNOTE: This is a Mars Hub address with the `mars` bech32 prefix, which may not be recognized by the `api.addr_validate` method.", - "type": "string", - "enum": ["safety_fund"] - } - ] + "schema": { + "type": "object", + "required": ["update_owner"], + "properties": { + "update_owner": { + "$ref": "#/definitions/OwnerUpdate" + } }, - "OwnerUpdate": { - "oneOf": [ - { - "description": "Proposes a new owner to take role. Only current owner can execute.", - "type": "object", - "required": ["propose_new_owner"], - "properties": { - "propose_new_owner": { - "type": "object", - "required": ["proposed"], - "properties": { - "proposed": { - "type": "string" - } - }, - "additionalProperties": false - } + "additionalProperties": false, + "$schema": "http://json-schema.org/draft-07/schema#", + "definitions": { + "MarsAddressType": { + "oneOf": [ + { + "type": "string", + "enum": ["incentives", "oracle", "red_bank", "rewards_collector"] }, - "additionalProperties": false - }, - { - "description": "Clears the currently proposed owner. Only current owner can execute.", - "type": "string", - "enum": ["clear_proposed"] - }, - { - "description": "Promotes the proposed owner to be the current one. Only the proposed owner can execute.", - "type": "string", - "enum": ["accept_proposed"] - }, - { - "description": "Throws away the keys to the Owner role forever. Once done, no owner can ever be set later.", - "type": "string", - "enum": ["abolish_owner_role"] - } - ] + { + "description": "Protocol admin is an ICS-27 interchain account controlled by Mars Hub's x/gov module. This account will take the owner and admin roles of red-bank contracts.\n\nOwner means the account who can invoke certain priviliged execute methods on a contract, such as updating the config. Admin means the account who can migrate a contract.", + "type": "string", + "enum": ["protocol_admin"] + }, + { + "description": "The `fee_collector` module account controlled by Mars Hub's x/distribution module. Funds sent to this account will be distributed as staking rewards.\n\nNOTE: This is a Mars Hub address with the `mars` bech32 prefix, which may not be recognized by the `api.addr_validate` method.", + "type": "string", + "enum": ["fee_collector"] + }, + { + "description": "The module account controlled by the by Mars Hub's x/safety module. Funds sent to this account will be deposited into the safety fund.\n\nNOTE: This is a Mars Hub address with the `mars` bech32 prefix, which may not be recognized by the `api.addr_validate` method.", + "type": "string", + "enum": ["safety_fund"] + } + ] + }, + "OwnerUpdate": { + "oneOf": [ + { + "description": "Proposes a new owner to take role. Only current owner can execute.", + "type": "object", + "required": ["propose_new_owner"], + "properties": { + "propose_new_owner": { + "type": "object", + "required": ["proposed"], + "properties": { + "proposed": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Clears the currently proposed owner. Only current owner can execute.", + "type": "string", + "enum": ["clear_proposed"] + }, + { + "description": "Promotes the proposed owner to be the current one. Only the proposed owner can execute.", + "type": "string", + "enum": ["accept_proposed"] + }, + { + "description": "Throws away the keys to the Owner role forever. Once done, no owner can ever be set later.", + "type": "string", + "enum": ["abolish_owner_role"] + } + ] + } } } } diff --git a/src/lib/stores/schema.ts b/src/lib/stores/schema.ts index 3a80d8686..65a804fcd 100644 --- a/src/lib/stores/schema.ts +++ b/src/lib/stores/schema.ts @@ -1,11 +1,9 @@ import type { RJSFSchema as JsonSchema } from "@rjsf/utils"; -import type { JSONSchema7 } from "json-schema"; import { makeAutoObservable } from "mobx"; import { makePersistable } from "mobx-persist-store"; import type { Dict, Option } from "lib/types"; -// TODO: this is derived from an example schema, ensure that the properties are comprehensively defined export enum SchemaProperties { CONTRACT_NAME = "contract_name", CONTRACT_VERSION = "contract_version", @@ -20,11 +18,17 @@ export enum SchemaProperties { type NullableJsonSchema = JsonSchema | null; +interface ExecuteSchema { + title: Option; + description: Option; + schema: JsonSchema; +} + export interface CodeSchema { [SchemaProperties.CONTRACT_NAME]: string; [SchemaProperties.CONTRACT_VERSION]: string; [SchemaProperties.IDL_VERSION]: string; - [SchemaProperties.INSTANTIATE]: NonNullable; + [SchemaProperties.INSTANTIATE]: JsonSchema; [SchemaProperties.EXECUTE]: NullableJsonSchema; [SchemaProperties.QUERY]: NullableJsonSchema; [SchemaProperties.MIGRATE]: NullableJsonSchema; @@ -69,7 +73,7 @@ export class SchemaStore { return this.jsonSchemas[codeHash]?.[property]; } - getQuerySchema(codeHash: string): Option> { + getQuerySchema(codeHash: string): Option> { const responsesSchema = this.getSchemaProperty( codeHash, SchemaProperties.RESPONSES @@ -81,28 +85,35 @@ export class SchemaStore { if (!querySchema || !responsesSchema) return undefined; - return querySchema.oneOf - ?.map((msg) => { - const schema7 = msg as JSONSchema7; + return querySchema.oneOf?.reduce>( + (acc, msg) => { + const schema7 = msg as JsonSchema; const { required } = schema7; - return ( - required !== undefined && [ - { - ...schema7, - $schema: querySchema.$schema, - definitions: querySchema.definitions, - }, - { - ...responsesSchema[required[0]], - readOnly: true, - }, - ] - ); - }) - .filter((tuple) => Boolean(tuple)) as Array<[JSONSchema7, JsonSchema]>; + + if (required) { + return [ + ...acc, + [ + { + ...schema7, + $schema: querySchema.$schema, + definitions: querySchema.definitions, + }, + { + ...responsesSchema[required[0]], + readOnly: true, + }, + ], + ]; + } + + return acc; + }, + [] + ); } - getExecuteSchema(codeHash: string): Option> { + getExecuteSchema(codeHash: string): Option> { const executeSchema = this.getSchemaProperty( codeHash, SchemaProperties.EXECUTE @@ -110,10 +121,21 @@ export class SchemaStore { if (!executeSchema) return undefined; - return executeSchema.oneOf?.map((msg) => ({ - ...(msg as JSONSchema7), - $schema: executeSchema.$schema, - definitions: executeSchema.definitions, - })); + return executeSchema.oneOf?.map((msg) => { + const eachSchema = msg as JsonSchema; + const { required, description } = eachSchema; + + delete eachSchema.description; + + return { + title: required?.[0], + description, + schema: { + ...eachSchema, + $schema: executeSchema.$schema, + definitions: executeSchema.definitions, + }, + }; + }); } } From 42230d6a541e52eed3b15c50a22b6319b7b63554 Mon Sep 17 00:00:00 2001 From: songwongtp <16089160+songwongtp@users.noreply.github.com> Date: Thu, 3 Aug 2023 18:28:44 +0700 Subject: [PATCH 10/94] feat: first schemaform version --- package.json | 6 + .../json-schema/contract_schema.json | 797 ++++++++++++++++++ .../json-schema/fields/MultiSchemaField.tsx | 275 ++++++ .../components/json-schema/fields/index.ts | 6 + src/lib/components/json-schema/index.tsx | 271 ++++++ .../templates/ArrayFieldItemTemplate.tsx | 81 ++ .../templates/ArrayFieldTemplate.tsx | 88 ++ .../templates/BaseInputTemplate.tsx | 179 ++++ .../templates/DescriptionFieldTemplate.tsx | 36 + .../json-schema/templates/FieldTemplate.tsx | 62 ++ .../json-schema/templates/FieldTypeTag.tsx | 23 + .../templates/ObjectFieldTemplate.tsx | 68 ++ .../templates/TitleFieldTemplate.tsx | 22 + .../templates/button-templates/AddButton.tsx | 20 + .../button-templates/SubmitButton.tsx | 25 + .../icon-buttons/ChakraIconButton.tsx | 23 + .../icon-buttons/IconButton.tsx | 33 + .../button-templates/icon-buttons/index.ts | 1 + .../templates/button-templates/index.ts | 11 + .../components/json-schema/templates/index.ts | 19 + src/lib/components/json-schema/utils.ts | 74 ++ .../json-schema/widgets/SelectWidget.tsx | 152 ++++ .../components/json-schema/widgets/index.ts | 6 + .../widgets/useDefaultChakraSelectStyle.ts | 42 + src/lib/pages/home/index.tsx | 3 +- yarn.lock | 321 ++++++- 26 files changed, 2641 insertions(+), 3 deletions(-) create mode 100644 src/lib/components/json-schema/contract_schema.json create mode 100644 src/lib/components/json-schema/fields/MultiSchemaField.tsx create mode 100644 src/lib/components/json-schema/fields/index.ts create mode 100644 src/lib/components/json-schema/index.tsx create mode 100644 src/lib/components/json-schema/templates/ArrayFieldItemTemplate.tsx create mode 100644 src/lib/components/json-schema/templates/ArrayFieldTemplate.tsx create mode 100644 src/lib/components/json-schema/templates/BaseInputTemplate.tsx create mode 100644 src/lib/components/json-schema/templates/DescriptionFieldTemplate.tsx create mode 100644 src/lib/components/json-schema/templates/FieldTemplate.tsx create mode 100644 src/lib/components/json-schema/templates/FieldTypeTag.tsx create mode 100644 src/lib/components/json-schema/templates/ObjectFieldTemplate.tsx create mode 100644 src/lib/components/json-schema/templates/TitleFieldTemplate.tsx create mode 100644 src/lib/components/json-schema/templates/button-templates/AddButton.tsx create mode 100644 src/lib/components/json-schema/templates/button-templates/SubmitButton.tsx create mode 100644 src/lib/components/json-schema/templates/button-templates/icon-buttons/ChakraIconButton.tsx create mode 100644 src/lib/components/json-schema/templates/button-templates/icon-buttons/IconButton.tsx create mode 100644 src/lib/components/json-schema/templates/button-templates/icon-buttons/index.ts create mode 100644 src/lib/components/json-schema/templates/button-templates/index.ts create mode 100644 src/lib/components/json-schema/templates/index.ts create mode 100644 src/lib/components/json-schema/utils.ts create mode 100644 src/lib/components/json-schema/widgets/SelectWidget.tsx create mode 100644 src/lib/components/json-schema/widgets/index.ts create mode 100644 src/lib/components/json-schema/widgets/useDefaultChakraSelectStyle.ts diff --git a/package.json b/package.json index b0eae819b..95aa4476a 100644 --- a/package.json +++ b/package.json @@ -37,6 +37,10 @@ "@cosmos-kit/react": "^1.3.31", "@graphql-codegen/cli": "^2.13.12", "@graphql-codegen/client-preset": "^1.1.4", + "@rjsf/chakra-ui": "v5.0.0-beta.10", + "@rjsf/core": "v5.0.0-beta.10", + "@rjsf/utils": "v5.0.0-beta.10", + "@rjsf/validator-ajv8": "v5.0.0-beta.10", "@rx-stream/pipe": "^0.7.1", "@sentry/nextjs": "7.37.0", "@tanstack/react-query": "^4.16.1", @@ -48,6 +52,7 @@ "big.js": "^6.2.1", "camelcase": "^7.0.0", "chain-registry": "^1.14.0", + "chakra-react-select": "^4.7.0", "cosmjs-types": "^0.7.2", "dayjs": "^1.11.6", "framer-motion": "^7.6.12", @@ -55,6 +60,7 @@ "graphql-request": "^5.0.0", "js-base64": "^3.7.4", "localforage": "^1.10.0", + "lodash": "^4.17.21", "long": "^5.2.1", "map-obj": "^5.0.2", "match-sorter": "^6.3.1", diff --git a/src/lib/components/json-schema/contract_schema.json b/src/lib/components/json-schema/contract_schema.json new file mode 100644 index 000000000..7b0445f35 --- /dev/null +++ b/src/lib/components/json-schema/contract_schema.json @@ -0,0 +1,797 @@ +{ + "contract_name": "mars-incentives", + "contract_version": "1.1.0", + "idl_version": "1.0.0", + "instantiate": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "InstantiateMsg", + "type": "object", + "required": [ + "address_provider", + "epoch_duration", + "max_whitelisted_denoms", + "owner" + ], + "properties": { + "address_provider": { + "description": "Address provider", + "type": "string" + }, + "epoch_duration": { + "description": "The amount of time in seconds for each incentive epoch. This is the minimum amount of time that an incentive can last, and each incentive must be a multiple of this duration.", + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "max_whitelisted_denoms": { + "description": "The maximum number of incentive denoms that can be whitelisted at any given time. This is a guard against accidentally whitelisting too many denoms, which could cause max gas errors.", + "type": "integer", + "format": "uint8", + "minimum": 0.0 + }, + "owner": { + "description": "Contract owner", + "type": "string" + } + }, + "additionalProperties": false + }, + "execute": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "ExecuteMsg", + "oneOf": [ + { + "description": "Add or remove incentive denoms from the whitelist. Only admin can do this.", + "type": "object", + "required": ["update_whitelist"], + "properties": { + "update_whitelist": { + "type": "object", + "required": ["add_denoms", "remove_denoms"], + "properties": { + "add_denoms": { + "description": "The denoms to add to the whitelist as well as a minimum emission rate per second for each. If the denom is already in the whitelist, the minimum emission rate will be updated.", + "type": "array", + "items": { + "$ref": "#/definitions/WhitelistEntry" + } + }, + "remove_denoms": { + "description": "The denoms to remove from the whitelist. This will update the index of the incentive state and then remove any active incentive schedules.\n\nNB: If any incentive schedules are still active for this incentive denom, the incentive tokens will be trapped forever in the contract.", + "type": "array", + "items": { + "type": "string" + } + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Add incentives for a given collateral denom and incentive denom pair", + "type": "object", + "required": ["set_asset_incentive"], + "properties": { + "set_asset_incentive": { + "type": "object", + "required": [ + "collateral_denom", + "duration", + "emission_per_second", + "incentive_denom", + "start_time" + ], + "properties": { + "collateral_denom": { + "description": "The denom of the collatearal token to receive incentives", + "type": "string" + }, + "duration": { + "description": "How many seconds the incentives last", + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "emission_per_second": { + "description": "How many `incentive_denom` tokens will be assigned per second to be distributed among all Red Bank depositors", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + }, + "incentive_denom": { + "description": "The denom of the token to give incentives with", + "type": "string" + }, + "start_time": { + "description": "Start time of the incentive (in seconds) since the UNIX epoch (00:00:00 on 1970-01-01 UTC).", + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Handle balance change updating user and asset rewards. Sent from an external contract, triggered on user balance changes. Will return an empty response if no incentive is applied for the asset", + "type": "object", + "required": ["balance_change"], + "properties": { + "balance_change": { + "type": "object", + "required": [ + "denom", + "total_amount_scaled_before", + "user_addr", + "user_amount_scaled_before" + ], + "properties": { + "denom": { + "description": "Denom of the asset of which deposited balance is changed", + "type": "string" + }, + "total_amount_scaled_before": { + "description": "The market's total scaled collateral amount up to the instant before the change", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + }, + "user_addr": { + "description": "User address. Address is trusted as it must be validated by the Red Bank contract before calling this method", + "allOf": [ + { + "$ref": "#/definitions/Addr" + } + ] + }, + "user_amount_scaled_before": { + "description": "The user's scaled collateral amount up to the instant before the change", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Claim rewards. MARS rewards accrued by the user will be staked into xMARS before being sent.", + "type": "object", + "required": ["claim_rewards"], + "properties": { + "claim_rewards": { + "type": "object", + "properties": { + "limit": { + "description": "The maximum number of results to return. If not set, 5 is used. If larger than 10, 10 is used.", + "type": ["integer", "null"], + "format": "uint32", + "minimum": 0.0 + }, + "start_after_collateral_denom": { + "description": "Start pagination after this collateral denom", + "type": ["string", "null"] + }, + "start_after_incentive_denom": { + "description": "Start pagination after this incentive denom. If supplied you must also supply start_after_collateral_denom.", + "type": ["string", "null"] + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Update contract config (only callable by owner)", + "type": "object", + "required": ["update_config"], + "properties": { + "update_config": { + "type": "object", + "properties": { + "address_provider": { + "description": "The address provider contract address", + "type": ["string", "null"] + }, + "max_whitelisted_denoms": { + "description": "The maximum number of incentive denoms that can be whitelisted at any given time. This is a guard against accidentally whitelisting too many denoms, which could cause max gas errors.", + "type": ["integer", "null"], + "format": "uint8", + "minimum": 0.0 + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Manages admin role state", + "type": "object", + "required": ["update_owner"], + "properties": { + "update_owner": { + "$ref": "#/definitions/OwnerUpdate" + } + }, + "additionalProperties": false + } + ], + "definitions": { + "Addr": { + "description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.", + "type": "string" + }, + "OwnerUpdate": { + "oneOf": [ + { + "description": "Proposes a new owner to take role. Only current owner can execute.", + "type": "object", + "required": ["propose_new_owner"], + "properties": { + "propose_new_owner": { + "type": "object", + "required": ["proposed"], + "properties": { + "proposed": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Clears the currently proposed owner. Only current owner can execute.", + "type": "string", + "enum": ["clear_proposed"] + }, + { + "description": "Promotes the proposed owner to be the current one. Only the proposed owner can execute.", + "type": "string", + "enum": ["accept_proposed"] + }, + { + "description": "Throws away the keys to the Owner role forever. Once done, no owner can ever be set later.", + "type": "string", + "enum": ["abolish_owner_role"] + }, + { + "description": "A separate entity managed by Owner that can be used for granting specific emergency powers.", + "type": "object", + "required": ["set_emergency_owner"], + "properties": { + "set_emergency_owner": { + "type": "object", + "required": ["emergency_owner"], + "properties": { + "emergency_owner": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Remove the entity in the Emergency Owner role", + "type": "string", + "enum": ["clear_emergency_owner"] + } + ] + }, + "Uint128": { + "description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```", + "type": "string" + }, + "WhitelistEntry": { + "type": "object", + "required": ["denom", "min_emission_rate"], + "properties": { + "denom": { + "description": "The incentive token denom that is whitelisted", + "type": "string" + }, + "min_emission_rate": { + "description": "The minimum emission rate per second for this incentive token", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + } + }, + "additionalProperties": false + } + } + }, + "query": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "QueryMsg", + "oneOf": [ + { + "description": "Query all active incentive emissions for a collateral denom", + "type": "object", + "required": ["active_emissions"], + "properties": { + "active_emissions": { + "type": "object", + "required": ["collateral_denom"], + "properties": { + "collateral_denom": { + "description": "The denom of the token that users supply as collateral to receive incentives", + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Query contract config", + "type": "object", + "required": ["config"], + "properties": { + "config": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Query info about the state of an incentive for a given collateral and incentive denom pair", + "type": "object", + "required": ["incentive_state"], + "properties": { + "incentive_state": { + "type": "object", + "required": ["collateral_denom", "incentive_denom"], + "properties": { + "collateral_denom": { + "description": "The denom of the token that users supply as collateral to receive incentives", + "type": "string" + }, + "incentive_denom": { + "description": "The denom of the token which is used to give incentives with", + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Enumerate incentive states with pagination", + "type": "object", + "required": ["incentive_states"], + "properties": { + "incentive_states": { + "type": "object", + "properties": { + "limit": { + "description": "The maximum number of results to return. If not set, 5 is used. If larger than 10, 10 is used.", + "type": ["integer", "null"], + "format": "uint32", + "minimum": 0.0 + }, + "start_after_collateral_denom": { + "description": "Start pagination after this collateral denom", + "type": ["string", "null"] + }, + "start_after_incentive_denom": { + "description": "Start pagination after this incentive denom. If supplied you must also supply start_after_collateral_denom.", + "type": ["string", "null"] + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Queries the planned emission rate for a given collateral and incentive denom tuple at the specified unix timestamp. The emission rate returned is the amount of incentive tokens that will be emitted per second for each unit of collateral supplied during the epoch. NB: that the returned value can change if someone adds incentives to the contract.", + "type": "object", + "required": ["emission"], + "properties": { + "emission": { + "type": "object", + "required": ["collateral_denom", "incentive_denom", "timestamp"], + "properties": { + "collateral_denom": { + "description": "The denom of the token that users supply as collateral to receive incentives", + "type": "string" + }, + "incentive_denom": { + "description": "The denom of the token which is used to give incentives with", + "type": "string" + }, + "timestamp": { + "description": "The unix timestamp in second to query the emission rate at.", + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Enumerate all incentive emission rates with pagination for a specified collateral and indentive denom pair", + "type": "object", + "required": ["emissions"], + "properties": { + "emissions": { + "type": "object", + "required": ["collateral_denom", "incentive_denom"], + "properties": { + "collateral_denom": { + "description": "The denom of the token that users supply as collateral to receive incentives", + "type": "string" + }, + "incentive_denom": { + "description": "The denom of the token which is used to give incentives with", + "type": "string" + }, + "limit": { + "description": "The maximum number of results to return. If not set, 5 is used. If larger than 10, 10 is used.", + "type": ["integer", "null"], + "format": "uint32", + "minimum": 0.0 + }, + "start_after_timestamp": { + "description": "Start pagination after this timestamp", + "type": ["integer", "null"], + "format": "uint64", + "minimum": 0.0 + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Query user current unclaimed rewards", + "type": "object", + "required": ["user_unclaimed_rewards"], + "properties": { + "user_unclaimed_rewards": { + "type": "object", + "required": ["user"], + "properties": { + "limit": { + "description": "The maximum number of results to return. If not set, 5 is used. If larger than 10, 10 is used.", + "type": ["integer", "null"], + "format": "uint32", + "minimum": 0.0 + }, + "start_after_collateral_denom": { + "description": "Start pagination after this collateral denom", + "type": ["string", "null"] + }, + "start_after_incentive_denom": { + "description": "Start pagination after this incentive denom. If supplied you must also supply start_after_collateral_denom.", + "type": ["string", "null"] + }, + "user": { + "description": "The user address for which to query unclaimed rewards", + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Queries the incentive denom whitelist. Returns a Vec<(String, Uint128)> containing the denoms of all whitelisted incentive denoms, as well as the minimum emission rate for each.", + "type": "object", + "required": ["whitelist"], + "properties": { + "whitelist": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + }, + "migrate": null, + "sudo": null, + "responses": { + "active_emissions": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Array_of_ActiveEmission", + "type": "array", + "items": { + "$ref": "#/definitions/ActiveEmission" + }, + "definitions": { + "ActiveEmission": { + "description": "The currently active emission for a given incentive denom", + "type": "object", + "required": ["denom", "emission_rate"], + "properties": { + "denom": { + "description": "The denom for which incentives are being distributed", + "type": "string" + }, + "emission_rate": { + "description": "The amount of incentive tokens that are being emitted per second", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + } + }, + "additionalProperties": false + }, + "Uint128": { + "description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```", + "type": "string" + } + } + }, + "config": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "ConfigResponse", + "type": "object", + "required": [ + "address_provider", + "epoch_duration", + "max_whitelisted_denoms" + ], + "properties": { + "address_provider": { + "description": "Address provider", + "allOf": [ + { + "$ref": "#/definitions/Addr" + } + ] + }, + "epoch_duration": { + "description": "The epoch duration in seconds", + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "max_whitelisted_denoms": { + "description": "The maximum number of incentive denoms that can be whitelisted at any given time. This is a guard against accidentally whitelisting too many denoms, which could cause max gas errors.", + "type": "integer", + "format": "uint8", + "minimum": 0.0 + }, + "owner": { + "description": "The contract's owner", + "type": ["string", "null"] + }, + "proposed_new_owner": { + "description": "The contract's proposed owner", + "type": ["string", "null"] + } + }, + "additionalProperties": false, + "definitions": { + "Addr": { + "description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.", + "type": "string" + } + } + }, + "emission": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Uint128", + "description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```", + "type": "string" + }, + "emissions": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Array_of_EmissionResponse", + "type": "array", + "items": { + "$ref": "#/definitions/EmissionResponse" + }, + "definitions": { + "EmissionResponse": { + "type": "object", + "required": ["emission_rate", "epoch_start"], + "properties": { + "emission_rate": { + "description": "The emission rate returned is the amount of incentive tokens that will be emitted per second for each unit of collateral supplied during the epoch.", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + }, + "epoch_start": { + "description": "The unix timestamp in seconds at which the emission epoch starts", + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + }, + "additionalProperties": false + }, + "Uint128": { + "description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```", + "type": "string" + } + } + }, + "incentive_state": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "IncentiveStateResponse", + "description": "Incentive Metadata for a given incentive denom", + "type": "object", + "required": [ + "collateral_denom", + "incentive_denom", + "index", + "last_updated" + ], + "properties": { + "collateral_denom": { + "description": "The denom for which users get the incentive if they provide collateral in the Red Bank", + "type": "string" + }, + "incentive_denom": { + "description": "The denom of the token these incentives are paid with", + "type": "string" + }, + "index": { + "description": "An index that represents how many incentive tokens have been distributed per unit of collateral", + "allOf": [ + { + "$ref": "#/definitions/Decimal" + } + ] + }, + "last_updated": { + "description": "Last time (in seconds) index was updated", + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + }, + "additionalProperties": false, + "definitions": { + "Decimal": { + "description": "A fixed-point decimal value with 18 fractional digits, i.e. Decimal(1_000_000_000_000_000_000) == 1.0\n\nThe greatest possible value that can be represented is 340282366920938463463.374607431768211455 (which is (2^128 - 1) / 10^18)", + "type": "string" + } + } + }, + "incentive_states": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Array_of_IncentiveStateResponse", + "type": "array", + "items": { + "$ref": "#/definitions/IncentiveStateResponse" + }, + "definitions": { + "Decimal": { + "description": "A fixed-point decimal value with 18 fractional digits, i.e. Decimal(1_000_000_000_000_000_000) == 1.0\n\nThe greatest possible value that can be represented is 340282366920938463463.374607431768211455 (which is (2^128 - 1) / 10^18)", + "type": "string" + }, + "IncentiveStateResponse": { + "description": "Incentive Metadata for a given incentive denom", + "type": "object", + "required": [ + "collateral_denom", + "incentive_denom", + "index", + "last_updated" + ], + "properties": { + "collateral_denom": { + "description": "The denom for which users get the incentive if they provide collateral in the Red Bank", + "type": "string" + }, + "incentive_denom": { + "description": "The denom of the token these incentives are paid with", + "type": "string" + }, + "index": { + "description": "An index that represents how many incentive tokens have been distributed per unit of collateral", + "allOf": [ + { + "$ref": "#/definitions/Decimal" + } + ] + }, + "last_updated": { + "description": "Last time (in seconds) index was updated", + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + }, + "additionalProperties": false + } + } + }, + "user_unclaimed_rewards": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Array_of_Coin", + "type": "array", + "items": { + "$ref": "#/definitions/Coin" + }, + "definitions": { + "Coin": { + "type": "object", + "required": ["amount", "denom"], + "properties": { + "amount": { + "$ref": "#/definitions/Uint128" + }, + "denom": { + "type": "string" + } + } + }, + "Uint128": { + "description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```", + "type": "string" + } + } + }, + "whitelist": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Array_of_WhitelistEntry", + "type": "array", + "items": { + "$ref": "#/definitions/WhitelistEntry" + }, + "definitions": { + "Uint128": { + "description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```", + "type": "string" + }, + "WhitelistEntry": { + "type": "object", + "required": ["denom", "min_emission_rate"], + "properties": { + "denom": { + "description": "The incentive token denom that is whitelisted", + "type": "string" + }, + "min_emission_rate": { + "description": "The minimum emission rate per second for this incentive token", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + } + }, + "additionalProperties": false + } + } + } + } +} diff --git a/src/lib/components/json-schema/fields/MultiSchemaField.tsx b/src/lib/components/json-schema/fields/MultiSchemaField.tsx new file mode 100644 index 000000000..97b5370d9 --- /dev/null +++ b/src/lib/components/json-schema/fields/MultiSchemaField.tsx @@ -0,0 +1,275 @@ +/* eslint-disable */ +import type { FieldProps, RJSFSchema } from "@rjsf/utils"; +import { + ERRORS_KEY, + deepEquals, + getUiOptions, + getWidget, + guessType, +} from "@rjsf/utils"; +import get from "lodash/get"; +import isEmpty from "lodash/isEmpty"; +import omit from "lodash/omit"; +import unset from "lodash/unset"; +import { Component } from "react"; + +/** Type used for the state of the `AnyOfField` component */ +type AnyOfFieldState = { + /** The currently selected option */ + selectedOptionIndex: number; +}; + +/** + * Replacement from react-jsonschema-form. Ensures fields are named correctly + * The `AnyOfField` component is used to render a field in the schema that is an `anyOf`, `allOf` + * or `oneOf`. It tracks the currently selected option and cleans up any irrelevant data in + * `formData`. + * + * @param props - The `FieldProps` for this template + */ +class MultiSchemaField extends Component< + FieldProps, + AnyOfFieldState +> { + /** Constructs an `AnyOfField` with the given `props` to initialize the initially selected option in state + * + * @param props - The `FieldProps` for this template + */ + constructor(props: FieldProps) { + super(props); + + const { formData, options } = this.props; + + this.state = { + selectedOptionIndex: this.getMatchingOption(0, formData, options), + }; + } + + /** + * React lifecycle methos that is called when the props and/or state for this component is + * updated. It recomputes the currently selected option based on the overall `formData` + * + * @param prevProps - The previous `FieldProps` for this template + * @param prevState - The previous `AnyOfFieldState` for this template + */ + componentDidUpdate( + prevProps: Readonly>, + prevState: Readonly + ) { + const { formData, options, idSchema } = this.props; + const { selectedOptionIndex } = this.state; + if ( + !deepEquals(formData, prevProps.formData) && + idSchema.$id === prevProps.idSchema.$id + ) { + const matchingOption = this.getMatchingOption( + selectedOptionIndex, + formData, + options + ); + + if (!prevState || matchingOption === selectedOptionIndex) { + return; + } + + this.setState({ + selectedOptionIndex: matchingOption, + }); + } + } + + /** + * Determines the best matching option for the given `formData` and `options`. + * + * @param formData - The new formData + * @param options - The list of options to choose from + * @return - The index of the `option` that best matches the `formData` + */ + getMatchingOption( + selectedOption: number, + formData: T, + options: RJSFSchema[] + ) { + const { + registry: { schemaUtils }, + } = this.props; + + const option = schemaUtils.getMatchingOption(formData, options); + if (option !== 0) { + return option; + } + // If the form data matches none of the options, use the currently selected + // option, assuming it's available; otherwise use the first option + return selectedOption || 0; + } + + /** + * Callback handler to remember what the currently selected option is. In addition to that the + * `formData` is updated to remove properties that are not part of the newly selected option + * schema, and then the updated data is passed to the `onChange` handler. + * + * @param option - + */ + onOptionChange = (selectedOption: any) => { + const selectedOptionIndex = parseInt(selectedOption, 10); + // console.log("I HAVE SELECTED", selectedOptionIndex) + const { formData, onChange, options, registry } = this.props; + const { schemaUtils } = registry; + const newOption = schemaUtils.retrieveSchema( + options[selectedOptionIndex], + formData + ); + + // If the new option is of type object and the current data is an object, + // discard properties added using the old option. + let newFormData: T | undefined; + if ( + guessType(formData) === "object" && + (newOption.type === "object" || newOption.properties) + ) { + newFormData = { ...formData }; + + const optionsToDiscard = options.slice(); + // Remove the newly selected option from the list of options to discard + optionsToDiscard.splice(selectedOptionIndex, 1); + // console.log("OPTIONS TO DISCARD", optionsToDiscard) + + // Discard any data added using other options + for (const option of optionsToDiscard) { + if (option.properties) { + for (const key in option.properties) { + if (key in newFormData) { + // console.log("UNSET", newFormData, key) + unset(newFormData, key); + } + } + } + } + } + + // Call getDefaultFormState to make sure defaults are populated on change. + const defaultFormState = schemaUtils.getDefaultFormState( + options[selectedOptionIndex], + newFormData + ) as T; + // console.log("DEFAULT FORM STATE", defaultFormState) + onChange(defaultFormState); + + this.setState({ + selectedOptionIndex, + }); + }; + + /** + * Renders the `AnyOfField` selector along with a `SchemaField` for the value of the `formData` + */ + render() { + const { + name, + disabled = false, + baseType, + errorSchema = {}, + formContext, + idSchema, + onBlur, + onFocus, + options, + registry, + uiSchema, + schema, + } = this.props; + + const { widgets, fields, schemaUtils } = registry; + const { SchemaField } = fields; + const { selectedOptionIndex } = this.state; + const { + widget = "select", + placeholder, + autofocus, + autocomplete, + title = schema.title, + ...uiOptions + } = getUiOptions(uiSchema); + const Widget = getWidget({ type: "number" }, widget, widgets); + const rawErrors = get(errorSchema, ERRORS_KEY, []); + const fieldErrorSchema = omit(errorSchema, [ERRORS_KEY]); + const displayLabel = schemaUtils.getDisplayLabel(schema, uiSchema); + + const selectedOption = options[selectedOptionIndex] || null; + let optionSchema; + if (selectedOption) { + // If the subschema doesn't declare a type, infer the type from the + // parent schema + optionSchema = selectedOption.type + ? selectedOption + : { ...selectedOption, type: baseType }; + } + + // if the second option's type is "null" it's probably a rust optional. + // This means that the nonnull value should use the name as the option name + const enumOptions = options.map((option: RJSFSchema, index: number) => { + let optionTitle = option.title; + + // Rust optional case + if (option.required?.length && option.required.length > 0) { + // there is one option available, so we can use its title + if (option.required.length === 1) { + optionTitle = option.required[0]; + } + } + if (option.type === "string" && option.enum?.length === 1) { + optionTitle = option.enum[0]?.toString(); + } + // Rust optional case + else if (option.type === "null") { + optionTitle = `No ${name}`; + } + // Here we do the second part of the above, because the non optional + else if ( + options.length === 2 && + options.some((opt: RJSFSchema) => opt.type === "null") + ) { + optionTitle = name; + } + + return { + label: optionTitle || `Option ${index + 1}`, + value: index, + }; + }); + + return ( +
+
+ = 0 ? selectedOptionIndex : undefined} + options={{ enumOptions, ...uiOptions }} + registry={registry} + formContext={formContext} + placeholder={placeholder} + autocomplete={autocomplete} + autofocus={autofocus} + label={title ?? name} + hideLabel={!displayLabel} + /> +
+ {selectedOption !== null && ( + + )} +
+ ); + } +} + +export default MultiSchemaField; diff --git a/src/lib/components/json-schema/fields/index.ts b/src/lib/components/json-schema/fields/index.ts new file mode 100644 index 000000000..cfa5e2d90 --- /dev/null +++ b/src/lib/components/json-schema/fields/index.ts @@ -0,0 +1,6 @@ +import MultiSchemaField from "./MultiSchemaField"; + +export const Fields = { + OneOfField: MultiSchemaField, + AnyOfField: MultiSchemaField, +}; diff --git a/src/lib/components/json-schema/index.tsx b/src/lib/components/json-schema/index.tsx new file mode 100644 index 000000000..6948b0463 --- /dev/null +++ b/src/lib/components/json-schema/index.tsx @@ -0,0 +1,271 @@ +/* eslint-disable */ +import { + Accordion, + AccordionButton, + AccordionIcon, + AccordionItem, + AccordionPanel, + Box, + Heading, + Text, + useToast, +} from "@chakra-ui/react"; +import { + Form, + Templates as DefaultTemplates, + Widgets as DefaultWidgets, +} from "@rjsf/chakra-ui"; +import type { FormProps } from "@rjsf/core"; +import type { RJSFSchema } from "@rjsf/utils"; +import { createSchemaUtils, type GenericObjectType } from "@rjsf/utils"; +import v8Validator from "@rjsf/validator-ajv8"; +import isEqual from "lodash/isEqual"; +import type { FC } from "react"; +import { useCallback, useMemo, useState } from "react"; + +import JsonReadOnly from "../json/JsonReadOnly"; +import { jsonPrettify } from "lib/utils"; + +import contractSchema from "./contract_schema.json"; +import { Fields } from "./fields"; +import { Templates } from "./templates"; +import { Widgets } from "./widgets"; + +function deleteExtraneousOneOfKeys(value: Record) { + const actualOneOfOptions = Object.keys(value); + + // check if there are TOO many options selected in the value + if (actualOneOfOptions.length === 2) { + console.log("Deleting", actualOneOfOptions[0]); + delete value[actualOneOfOptions[0]]; + } else if (actualOneOfOptions.length > 2) { + console.warn("Unexpected number of oneOf options", actualOneOfOptions); + // TODO: throw an error? + } +} + +/** + * A helper method to fix a bug in the rjsf library. + * The bug is that `oneOf` properties will ALWAYS contain the first option. + * @param formData + * @param collapsedSchema - the schema that has been collapsed via `createSchemaUtils` + */ +function fixOneOfKeys( + formData: Record, + collapsedSchema: RJSFSchema +) { + // console.log(collapsedSchema); + + // if the entry is supposed to be a oneof *itself*, then check that it only has one key + if (collapsedSchema.oneOf) { + deleteExtraneousOneOfKeys(formData); + + // Now recursively check the keys (though there should only be one) + for (const [key, value] of Object.entries(formData)) { + if (typeof value === "object") { + // Find the schema for the key('s value) + const valueSchema = collapsedSchema.oneOf + .filter((i): i is RJSFSchema => typeof i === "object") + .find((i) => i.required?.length === 1 && i.required[0] === key); + + if (!valueSchema) return; + fixOneOfKeys(value as Record, valueSchema); + } + } + return; + } + + // iterate through each entry in the formData to check if it's oneOf + for (const [key, value] of Object.entries(formData)) { + // skip non-objects + if (!value || typeof value !== "object") continue; + + const valueSchema = collapsedSchema.properties?.[key]; + // Skip those without a valid schema + if (!valueSchema || typeof valueSchema === "boolean") continue; + + // if the entry is supposed to be a oneof, then check that it only has one key + if (valueSchema.oneOf) { + console.log("Found oneOf", key, value); + deleteExtraneousOneOfKeys(value as Record); + } + + // Since we know that the value is an object, we can recurse + fixOneOfKeys(value as Record, valueSchema); + } +} + +export interface JsonSchemaFormProps + extends Pick< + Partial, + "widgets" | "fields" | "templates" | "uiSchema" + > { + schema: RJSFSchema; + formId: string; + onSubmit: (data: Record) => void; + /** Onchange callback is with BROKEN data */ + onChange?: (data: Record) => void; + formContext?: Record; +} + +// TODO: create JsonSchemaFormProps +export const JsonSchemaForm: FC = ({ + formId, + schema, + onSubmit: propsOnSubmit, + onChange: propsOnChange, + widgets, + fields, + templates, + uiSchema, + formContext, +}) => { + const [formData, setFormData] = useState>({}); + + const collapsedSchema = useMemo( + () => createSchemaUtils(v8Validator, schema).retrieveSchema(schema), + [schema] + ); + + const fixOneOfKeysCallback = useCallback( + (data: Record) => fixOneOfKeys(data, collapsedSchema), + [collapsedSchema] + ); + + const onSubmit = (values: Record) => { + fixOneOfKeysCallback(values); + console.log("onSubmit", values); + + propsOnSubmit(values); + }; + + const onChange = useCallback( + (data: Record) => { + const values = { ...data }; + if (data) { + fixOneOfKeysCallback(values); + if (!isEqual(formData, values)) { + setFormData(values); + propsOnChange?.(values); + } + } + }, + [fixOneOfKeysCallback, formData, propsOnChange] + ); + + return ( +
{ + // log.info(values) + onChange?.(values); + }} + onSubmit={({ formData: values }) => { + // log.info(values) + onSubmit(values); + }} + onError={() => console.error("errors")} + /> + ); +}; + +export const DummyJsonSchema = () => { + // TODO: remove mock data + const toast = useToast({ containerStyle: { width: "fit-content" } }); + const { oneOf: msgs, definitions } = contractSchema.execute; + + // const schema = contractSchema.execute as GenericObjectType; + + return ( + + {msgs.map((msg, index) => ( + +

+ + + + {msg.required[0]} + + + {msg.description} + + + + +

+ + + toast({ + title: "Form Data", + description: ( + + + + ), + status: "success", + isClosable: true, + }) + } + onChange={(data) => console.log("data", data)} + /> + +
+ ))} +
+ // + // toast({ + // title: "Form Data", + // description: ( + // + // + // + // ), + // status: "success", + // isClosable: true, + // }) + // } + // onChange={(data) => { + // console.log("data", data); + // }} + // /> + ); +}; diff --git a/src/lib/components/json-schema/templates/ArrayFieldItemTemplate.tsx b/src/lib/components/json-schema/templates/ArrayFieldItemTemplate.tsx new file mode 100644 index 000000000..c5a52065f --- /dev/null +++ b/src/lib/components/json-schema/templates/ArrayFieldItemTemplate.tsx @@ -0,0 +1,81 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { Box, ButtonGroup, HStack } from "@chakra-ui/react"; +import type { ArrayFieldTemplateItemType } from "@rjsf/utils"; +import { useMemo } from "react"; + +export default function ArrayFieldItemTemplate( + props: ArrayFieldTemplateItemType +) { + const { + children, + disabled, + hasToolbar, + hasMoveDown, + hasMoveUp, + hasRemove, + index, + onDropIndexClick, + onReorderClick, + readonly, + uiSchema, + registry, + } = props; + const { MoveDownButton, MoveUpButton, RemoveButton } = + registry.templates.ButtonTemplates; + + const onRemoveClick = useMemo( + () => onDropIndexClick(index), + [index, onDropIndexClick] + ); + + const onArrowUpClick = useMemo( + () => onReorderClick(index, index - 1), + [index, onReorderClick] + ); + + const onArrowDownClick = useMemo( + () => onReorderClick(index, index + 1), + [index, onReorderClick] + ); + + return ( + + div > div > div": { gap: "4px" } }} + > + {children} + + {hasToolbar && ( + + {(hasMoveUp || hasMoveDown) && ( + + )} + {(hasMoveUp || hasMoveDown) && ( + + )} + {hasRemove && ( + + )} + + )} + + ); +} diff --git a/src/lib/components/json-schema/templates/ArrayFieldTemplate.tsx b/src/lib/components/json-schema/templates/ArrayFieldTemplate.tsx new file mode 100644 index 000000000..f6c7a4054 --- /dev/null +++ b/src/lib/components/json-schema/templates/ArrayFieldTemplate.tsx @@ -0,0 +1,88 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { Box, Flex, Grid, GridItem } from "@chakra-ui/react"; +import type { + ArrayFieldTemplateItemType, + ArrayFieldTemplateProps, +} from "@rjsf/utils"; +import { getTemplate, getUiOptions } from "@rjsf/utils"; + +import { FieldTypeTag } from "./FieldTypeTag"; + +export default function ArrayFieldTemplate( + props: ArrayFieldTemplateProps +) { + const { + canAdd, + disabled, + idSchema, + uiSchema, + items, + onAddClick, + readonly, + registry, + required, + schema, + title, + } = props; + const uiOptions = getUiOptions(uiSchema); + const ArrayFieldDescriptionTemplate = getTemplate< + "ArrayFieldDescriptionTemplate", + T, + F + >("ArrayFieldDescriptionTemplate", registry, uiOptions); + const ArrayFieldItemTemplate = getTemplate<"ArrayFieldItemTemplate", T, F>( + "ArrayFieldItemTemplate", + registry, + uiOptions + ); + const ArrayFieldTitleTemplate = getTemplate<"ArrayFieldTitleTemplate", T, F>( + "ArrayFieldTitleTemplate", + registry, + uiOptions + ); + // Button templates are not overridden in the uiSchema + const { + ButtonTemplates: { AddButton }, + } = registry.templates; + return ( + + + + + + + + + {items.length > 0 && + items.map( + ({ key, ...itemProps }: ArrayFieldTemplateItemType) => ( + + + + ) + )} + {canAdd && ( + + + + )} + + + ); +} diff --git a/src/lib/components/json-schema/templates/BaseInputTemplate.tsx b/src/lib/components/json-schema/templates/BaseInputTemplate.tsx new file mode 100644 index 000000000..f3e5f464e --- /dev/null +++ b/src/lib/components/json-schema/templates/BaseInputTemplate.tsx @@ -0,0 +1,179 @@ +/* eslint-disable react/destructuring-assignment */ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { + Box, + Button, + Flex, + FormControl, + FormLabel, + HStack, + Input, + InputGroup, + InputRightAddon, +} from "@chakra-ui/react"; +import { fromBase64, fromUtf8, toBase64, toUtf8 } from "@cosmjs/encoding"; +import type { WidgetProps } from "@rjsf/utils"; +import { getInputProps, getTemplate, getUiOptions } from "@rjsf/utils"; +import type { ChangeEvent, FocusEvent } from "react"; + +import { FieldTypeTag } from "./FieldTypeTag"; + +const PLACEHOLDERS = { + addr: "cosmos1...", + code_id: "1", + contract: "cosmos1...", +}; + +const renderRightAddOn = ( + value: WidgetProps["value"], + label: WidgetProps["label"], + schema: WidgetProps["schema"], + onChange: WidgetProps["onChange"], + formContext: WidgetProps["formContext"] +) => { + // console.log(formContext, "formContext"); + if (schema.description?.includes("Binary is a wrapper around Vec")) { + return ( + + + + + ); + } + if ( + label.includes("addr") && + formContext && + typeof formContext === "object" && + "address" in formContext + ) { + return ( + + ); + } + return null; +}; + +const BaseInputTemplate = (props: WidgetProps) => { + const { + id, + type, + value, + label, + schema, + uiSchema, + onChange, + onBlur, + onFocus, + options, + required, + readonly, + rawErrors, + autofocus, + placeholder, + disabled, + formContext, + registry, + } = props; + const inputProps = getInputProps(schema, type, options); + + const uiOptions = getUiOptions(uiSchema); + const DescriptionFieldTemplate = getTemplate< + "DescriptionFieldTemplate", + T, + F + >("DescriptionFieldTemplate", registry, uiOptions); + + const { schemaUtils } = registry; + const displayLabel = + schemaUtils.getDisplayLabel(schema, uiSchema) && + (!!label || !!schema.title); + + const handleOnChange = ({ target }: ChangeEvent) => + onChange(target.value === "" ? options.emptyValue : target.value); + const handleOnBlur = ({ target }: FocusEvent) => + onBlur(id, target.value); + const handleOnFocus = ({ target }: FocusEvent) => + onFocus(id, target.value); + + const rightAddon = renderRightAddOn( + value, + label, + schema, + onChange, + formContext + ); + + return ( + 0} + > + {displayLabel && ( + + + {label} + + + + )} + + + label.includes(key) + )?.[1] + } + {...inputProps} + list={schema.examples ? `examples_${id}` : undefined} + /> + {rightAddon && {rightAddon}} + + {Array.isArray(schema.examples) ? ( + + {(schema.examples as string[]) + .concat( + schema.default && !schema.examples.includes(schema.default) + ? ([schema.default] as string[]) + : [] + ) + .map((example: any) => { + return ( + + ) : null} + {!!schema.description && ( + + + + )} + + ); +}; + +export default BaseInputTemplate; diff --git a/src/lib/components/json-schema/templates/DescriptionFieldTemplate.tsx b/src/lib/components/json-schema/templates/DescriptionFieldTemplate.tsx new file mode 100644 index 000000000..5ccf5d969 --- /dev/null +++ b/src/lib/components/json-schema/templates/DescriptionFieldTemplate.tsx @@ -0,0 +1,36 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { Text } from "@chakra-ui/react"; +import type { DescriptionFieldProps } from "@rjsf/utils"; + +/** + * Description Field for the jsonschema forms. + * @param description + * @param id + */ +const DescriptionFieldTemplate = ( + props: DescriptionFieldProps +) => { + const { id, description } = props; + if (!description) { + return null; + } + if (typeof description === "string") { + return ( + + {description} + + ); + } + return ( +
+ {description} +
+ ); +}; + +export default DescriptionFieldTemplate; diff --git a/src/lib/components/json-schema/templates/FieldTemplate.tsx b/src/lib/components/json-schema/templates/FieldTemplate.tsx new file mode 100644 index 000000000..efb16a438 --- /dev/null +++ b/src/lib/components/json-schema/templates/FieldTemplate.tsx @@ -0,0 +1,62 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { FormControl } from "@chakra-ui/react"; +import type { FieldTemplateProps } from "@rjsf/utils"; +import { getTemplate, getUiOptions } from "@rjsf/utils"; + +export default function FieldTemplate( + props: FieldTemplateProps +) { + const { + id, + children, + classNames, + disabled, + hidden, + label, + onDropPropertyClick, + onKeyChange, + readonly, + registry, + required, + rawErrors = [], + errors, + help, + schema, + uiSchema, + } = props; + const uiOptions = getUiOptions(uiSchema); + const WrapIfAdditionalTemplate = getTemplate< + "WrapIfAdditionalTemplate", + T, + F + >("WrapIfAdditionalTemplate", registry, uiOptions); + + if (hidden) { + return
{children}
; + } + + return ( + + 0} + > + {children} + {errors} + {help} + + + ); +} diff --git a/src/lib/components/json-schema/templates/FieldTypeTag.tsx b/src/lib/components/json-schema/templates/FieldTypeTag.tsx new file mode 100644 index 000000000..2cee22401 --- /dev/null +++ b/src/lib/components/json-schema/templates/FieldTypeTag.tsx @@ -0,0 +1,23 @@ +import { Flex, Tag } from "@chakra-ui/react"; +import type { RJSFSchema } from "@rjsf/utils"; + +export const FieldTypeTag = ({ type }: Pick) => { + if (!type) return null; + if (Array.isArray(type)) { + const types: string[] = type; + return ( + + {types.map((value) => ( + + {value} + + ))} + + ); + } + return ( + + {type} + + ); +}; diff --git a/src/lib/components/json-schema/templates/ObjectFieldTemplate.tsx b/src/lib/components/json-schema/templates/ObjectFieldTemplate.tsx new file mode 100644 index 000000000..06617cdfd --- /dev/null +++ b/src/lib/components/json-schema/templates/ObjectFieldTemplate.tsx @@ -0,0 +1,68 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { Grid, GridItem } from "@chakra-ui/react"; +import type { ObjectFieldTemplateProps } from "@rjsf/utils"; +import { canExpand, getTemplate, getUiOptions } from "@rjsf/utils"; + +const ObjectFieldTemplate = ( + props: ObjectFieldTemplateProps +) => { + const { + description, + properties, + disabled, + readonly, + uiSchema, + idSchema, + schema, + formData, + onAddClick, + registry, + } = props; + const uiOptions = getUiOptions(uiSchema); + const DescriptionFieldTemplate = getTemplate<"DescriptionFieldTemplate">( + "DescriptionFieldTemplate", + registry, + uiOptions + ); + // Button templates are not overridden in the uiSchema + const { + ButtonTemplates: { AddButton }, + } = registry.templates; + + return ( + <> + {(uiOptions.description || description) && ( + + )} + + {properties.map((element, index) => + element.hidden ? ( + element.content + ) : ( + + {element.content} + + ) + )} + {canExpand(schema, uiSchema, formData) && ( + + + + )} + + + ); +}; + +export default ObjectFieldTemplate; diff --git a/src/lib/components/json-schema/templates/TitleFieldTemplate.tsx b/src/lib/components/json-schema/templates/TitleFieldTemplate.tsx new file mode 100644 index 000000000..7b033586e --- /dev/null +++ b/src/lib/components/json-schema/templates/TitleFieldTemplate.tsx @@ -0,0 +1,22 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { Text } from "@chakra-ui/react"; +import type { TitleFieldProps } from "@rjsf/utils"; +/** The `TitleField` is the template to use to render the title of a field + * + * @param props - The `TitleFieldProps` for this component + */ +export default function TitleFieldTemplate( + props: TitleFieldProps +) { + const { id, title } = props; + return ( + + {title} + {/* {required && ( + + * + + )} */} + + ); +} diff --git a/src/lib/components/json-schema/templates/button-templates/AddButton.tsx b/src/lib/components/json-schema/templates/button-templates/AddButton.tsx new file mode 100644 index 000000000..a6107dc6b --- /dev/null +++ b/src/lib/components/json-schema/templates/button-templates/AddButton.tsx @@ -0,0 +1,20 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { Button } from "@chakra-ui/react"; +import type { IconButtonProps } from "@rjsf/utils"; + +export default function AddButton({ + uiSchema, + ...props +}: IconButtonProps) { + return ( + + ); +} diff --git a/src/lib/components/json-schema/templates/button-templates/SubmitButton.tsx b/src/lib/components/json-schema/templates/button-templates/SubmitButton.tsx new file mode 100644 index 000000000..81ecaff3a --- /dev/null +++ b/src/lib/components/json-schema/templates/button-templates/SubmitButton.tsx @@ -0,0 +1,25 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { Box, Button } from "@chakra-ui/react"; +import type { SubmitButtonProps } from "@rjsf/utils"; +import { getSubmitButtonOptions } from "@rjsf/utils"; + +export default function SubmitButton({ + uiSchema, +}: SubmitButtonProps) { + const { + submitText, + norender, + props: submitButtonProps, + } = getSubmitButtonOptions(uiSchema); + if (norender) { + return null; + } + + return ( + + + + ); +} diff --git a/src/lib/components/json-schema/templates/button-templates/icon-buttons/ChakraIconButton.tsx b/src/lib/components/json-schema/templates/button-templates/icon-buttons/ChakraIconButton.tsx new file mode 100644 index 000000000..700f60245 --- /dev/null +++ b/src/lib/components/json-schema/templates/button-templates/icon-buttons/ChakraIconButton.tsx @@ -0,0 +1,23 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import type { IconButtonProps as ChakraIconButtonProps } from "@chakra-ui/react"; +import { IconButton } from "@chakra-ui/react"; +import type { IconButtonProps } from "@rjsf/utils"; +import { memo } from "react"; + +function ChakraIconButton(props: IconButtonProps) { + const { title, icon, iconType, uiSchema, ...otherProps } = props; + return ( + + ); +} + +ChakraIconButton.displayName = "ChakraIconButton"; + +export default memo(ChakraIconButton) as typeof ChakraIconButton; diff --git a/src/lib/components/json-schema/templates/button-templates/icon-buttons/IconButton.tsx b/src/lib/components/json-schema/templates/button-templates/icon-buttons/IconButton.tsx new file mode 100644 index 000000000..fea067783 --- /dev/null +++ b/src/lib/components/json-schema/templates/button-templates/icon-buttons/IconButton.tsx @@ -0,0 +1,33 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { ArrowUpIcon, ArrowDownIcon } from "@chakra-ui/icons"; +import type { IconButtonProps } from "@rjsf/utils"; + +import { CustomIcon } from "lib/components/icon"; + +import ChakraIconButton from "./ChakraIconButton"; + +export function MoveDownButton(props: IconButtonProps) { + return ( + + title="Move Down" + {...props} + icon={} + /> + ); +} + +export function MoveUpButton(props: IconButtonProps) { + return ( + title="Move Up" {...props} icon={} /> + ); +} + +export function RemoveButton(props: IconButtonProps) { + return ( + + title="Remove" + {...props} + icon={} + /> + ); +} diff --git a/src/lib/components/json-schema/templates/button-templates/icon-buttons/index.ts b/src/lib/components/json-schema/templates/button-templates/icon-buttons/index.ts new file mode 100644 index 000000000..53185101d --- /dev/null +++ b/src/lib/components/json-schema/templates/button-templates/icon-buttons/index.ts @@ -0,0 +1 @@ +export * from "./IconButton"; diff --git a/src/lib/components/json-schema/templates/button-templates/index.ts b/src/lib/components/json-schema/templates/button-templates/index.ts new file mode 100644 index 000000000..fcdf9a227 --- /dev/null +++ b/src/lib/components/json-schema/templates/button-templates/index.ts @@ -0,0 +1,11 @@ +import AddButton from "./AddButton"; +import { MoveDownButton, MoveUpButton, RemoveButton } from "./icon-buttons"; +import SubmitButton from "./SubmitButton"; + +export const ButtonTemplates = { + AddButton, + MoveDownButton, + MoveUpButton, + RemoveButton, + SubmitButton, +}; diff --git a/src/lib/components/json-schema/templates/index.ts b/src/lib/components/json-schema/templates/index.ts new file mode 100644 index 000000000..c55f18d94 --- /dev/null +++ b/src/lib/components/json-schema/templates/index.ts @@ -0,0 +1,19 @@ +import ArrayFieldItemTemplate from "./ArrayFieldItemTemplate"; +import ArrayFieldTemplate from "./ArrayFieldTemplate"; +import BaseInputTemplate from "./BaseInputTemplate"; +import { ButtonTemplates } from "./button-templates"; +import DescriptionFieldTemplate from "./DescriptionFieldTemplate"; +import FieldTemplate from "./FieldTemplate"; +import ObjectFieldTemplate from "./ObjectFieldTemplate"; +import TitleFieldTemplate from "./TitleFieldTemplate"; + +export const Templates = { + ArrayFieldItemTemplate, + ArrayFieldTemplate, + BaseInputTemplate, + ButtonTemplates, + FieldTemplate, + ObjectFieldTemplate, + DescriptionFieldTemplate, + TitleFieldTemplate, +}; diff --git a/src/lib/components/json-schema/utils.ts b/src/lib/components/json-schema/utils.ts new file mode 100644 index 000000000..60de3f6a7 --- /dev/null +++ b/src/lib/components/json-schema/utils.ts @@ -0,0 +1,74 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import type { EnumOptionsType } from "@rjsf/utils"; +import isEqual from "lodash/isEqual"; + +/** Determines whether the given `value` is (one of) the `selected` value(s). + * + * @param value - The value being checked to see if it is selected + * @param selected - The current selected value or list of values + * @returns - true if the `value` is one of the `selected` ones, false otherwise + */ +export function enumOptionsIsSelected( + value: EnumOptionsType["value"], + selected: EnumOptionsType["value"] | EnumOptionsType["value"][] +) { + if (Array.isArray(selected)) { + return selected.some((sel) => isEqual(sel, value)); + } + return isEqual(selected, value); +} + +/** Returns the index(es) of the options in `allEnumOptions` whose value(s) match the ones in `value`. All the + * `enumOptions` are filtered based on whether they are a "selected" `value` and the index of each selected one is then + * stored in an array. If `multiple` is true, that array is returned, otherwise the first element in the array is + * returned. + * + * @param value - The single value or list of values for which indexes are desired + * @param [allEnumOptions=[]] - The list of all the known enumOptions + * @param [multiple=false] - Optional flag, if true will return a list of index, otherwise a single one + * @returns - A single string index for the first `value` in `allEnumOptions`, if not `multiple`. Otherwise, the list + * of indexes for (each of) the value(s) in `value`. + */ +export function enumOptionsIndexForValue( + value: EnumOptionsType["value"] | EnumOptionsType["value"][], + allEnumOptions: EnumOptionsType[] = [], + multiple = false +): string | string[] | undefined { + const selectedIndexes: string[] = allEnumOptions + .map((opt, index) => + enumOptionsIsSelected(opt.value, value) ? String(index) : undefined + ) + .filter((opt) => typeof opt !== "undefined") as string[]; + if (!multiple) { + return selectedIndexes[0]; + } + return selectedIndexes; +} + +/** Returns the value(s) from `allEnumOptions` at the index(es) provided by `valueIndex`. If `valueIndex` is not an + * array AND the index is not valid for `allEnumOptions`, `emptyValue` is returned. If `valueIndex` is an array, AND it + * contains an invalid index, the returned array will have the resulting undefined values filtered out, leaving only + * valid values or in the worst case, an empty array. + * + * @param valueIndex - The index(es) of the value(s) that should be returned + * @param [allEnumOptions=[]] - The list of all the known enumOptions + * @param [emptyValue] - The value to return when the non-array `valueIndex` does not refer to a real option + * @returns - The single or list of values specified by the single or list of indexes if they are valid. Otherwise, + * `emptyValue` or an empty list. + */ +export default function enumOptionsValueForIndex( + valueIndex: string | number | Array, + allEnumOptions: EnumOptionsType[] = [], + emptyValue?: EnumOptionsType["value"] +): EnumOptionsType["value"] | EnumOptionsType["value"][] | undefined { + if (Array.isArray(valueIndex)) { + return valueIndex + .map((index) => enumOptionsValueForIndex(index, allEnumOptions)) + .filter((val) => val); + } + // So Number(null) and Number('') both return 0, so use emptyValue for those two values + const index = + valueIndex === "" || valueIndex === null ? -1 : Number(valueIndex); + const option = allEnumOptions[index]; + return option ? option.value : emptyValue; +} diff --git a/src/lib/components/json-schema/widgets/SelectWidget.tsx b/src/lib/components/json-schema/widgets/SelectWidget.tsx new file mode 100644 index 000000000..3f4549411 --- /dev/null +++ b/src/lib/components/json-schema/widgets/SelectWidget.tsx @@ -0,0 +1,152 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { FormControl } from "@chakra-ui/react"; +import type { EnumOptionsType, WidgetProps } from "@rjsf/utils"; +import { getTemplate, getUiOptions } from "@rjsf/utils"; +import type { OptionsOrGroups } from "chakra-react-select"; +import { Select } from "chakra-react-select"; +import type React from "react"; + +import enumOptionsValueForIndex, { enumOptionsIndexForValue } from "../utils"; + +/** + * chakra-react-select option base. + */ +interface OptionBase { + variant?: string; + colorScheme?: string; + isFixed?: boolean; + isDisabled?: boolean; +} + +export interface SelectOptionBase extends OptionBase { + label: string; + value: T; +} + +/** + * Custom select for use with the react-jsonschema-form. + * We do not create custom options because the entire library depends on the value being a number. + * @param props + * @todo Multi select + */ +const SelectWidget = (props: WidgetProps) => { + const { + schema, + id, + options, + placeholder, + multiple, + required, + disabled, + readonly, + value, + autofocus, + onChange, + onBlur, + onFocus, + rawErrors = [], + uiSchema, + registry, + } = props; + const uiOptions = getUiOptions(uiSchema); + const { enumOptions, enumDisabled, emptyValue } = options; + + const DescriptionFieldTemplate = getTemplate<"DescriptionFieldTemplate", T>( + "DescriptionFieldTemplate", + registry, + uiOptions + ); + + const handleOnMultiChange = (e: any) => { + return onChange( + enumOptionsValueForIndex( + e.map((v: { value: any }) => { + return v.value; + }), + enumOptions, + emptyValue + ) + ); + }; + + const handleOnChange = (e: any) => + onChange(enumOptionsValueForIndex(e.value, enumOptions, emptyValue)); + + const handleOnBlur = ({ target }: React.FocusEvent) => + onBlur(id, enumOptionsValueForIndex(target.value, enumOptions, emptyValue)); + + const handleOnFocus = ({ target }: React.FocusEvent) => + onFocus( + id, + enumOptionsValueForIndex(target.value, enumOptions, emptyValue) + ); + + const valueLabelMap: any = {}; + const displayEnumOptions: OptionsOrGroups = Array.isArray( + enumOptions + ) + ? enumOptions.map((option: EnumOptionsType, index: number) => { + const { value: optionValue, label: optionLabel } = option; + valueLabelMap[index] = optionLabel || String(optionValue); + return { + label: optionLabel, + value: String(index), + isDisabled: + Array.isArray(enumDisabled) && + enumDisabled.indexOf(optionValue) !== -1, + }; + }) + : []; + + const isMultiple = multiple && Boolean(enumOptions); + const selectedIndex = enumOptionsIndexForValue( + value, + enumOptions, + isMultiple + ); + const formValue: any = isMultiple + ? ((selectedIndex as string[]) || []).map((i: string) => { + return { + label: valueLabelMap[i], + value: i, + }; + }) + : { + label: valueLabelMap[selectedIndex as string] || "", + value: selectedIndex, + }; + return ( + 0} + > + {!!schema.description && ( + + )} + setKeyword(e.target.value)} + h="40px" + /> + + + + + + + setExpandedIndexes(indexes)} + sx={{ ".chakra-accordion__icon": { color: "gray.600" } }} + > + {schema + .filter((querySchema) => querySchema[0].title?.includes(keyword)) + .map(([msg, res]) => ( + + ))} + + + ); +}; diff --git a/src/lib/pages/query/index.tsx b/src/lib/pages/query/index.tsx index 99c625607..a5f4c474e 100644 --- a/src/lib/pages/query/index.tsx +++ b/src/lib/pages/query/index.tsx @@ -1,23 +1,19 @@ import { Heading, Button, Box, Flex } from "@chakra-ui/react"; -import { useQuery } from "@tanstack/react-query"; -import type { AxiosError } from "axios"; +import { observer } from "mobx-react-lite"; import { useRouter } from "next/router"; import { useCallback, useEffect, useState } from "react"; import { - CELATONE_QUERY_KEYS, - useBaseApiRoute, useInternalNavigate, useWasmConfig, useMobile, } from "lib/app-provider"; import { ContractSelectSection } from "lib/components/ContractSelectSection"; import { CustomIcon } from "lib/components/icon"; -import { LoadingOverlay } from "lib/components/LoadingOverlay"; import PageContainer from "lib/components/PageContainer"; +import { useSchemaStore } from "lib/providers/store"; import { AmpTrackToQuery } from "lib/services/amplitude"; -import { queryData } from "lib/services/contract"; -import type { ContractAddr, RpcQueryError } from "lib/types"; +import type { ContractAddr } from "lib/types"; import { jsonPrettify, getFirstQueryParam, @@ -27,16 +23,18 @@ import { import { QueryArea } from "./components/QueryArea"; -const Query = () => { +const Query = observer(() => { useWasmConfig({ shouldRedirect: true }); const router = useRouter(); const navigate = useInternalNavigate(); - const lcdEndpoint = useBaseApiRoute("rest"); + const { getQuerySchema } = useSchemaStore(); const [contractAddress, setContractAddress] = useState("" as ContractAddr); + const [codeHash, setCodeHash] = useState(""); const [initialMsg, setInitialMsg] = useState(""); - const [cmds, setCmds] = useState<[string, string][]>([]); const isMobile = useMobile(); + const schema = getQuerySchema(codeHash); + const goToExecute = () => { navigate({ pathname: "/execute", @@ -55,30 +53,6 @@ const Query = () => { [navigate] ); - // TODO: Abstract query and make query key - const { isFetching } = useQuery( - [ - CELATONE_QUERY_KEYS.CONTRACT_QUERY_CMDS, - lcdEndpoint, - contractAddress, - '{"": {}}', - ], - async () => queryData(lcdEndpoint, contractAddress, '{"": {}}'), - { - enabled: !!contractAddress, - retry: false, - cacheTime: 0, - refetchOnWindowFocus: false, - onError: (e: AxiosError) => { - const queryCmds: string[] = []; - Array.from(e.response?.data.message?.matchAll(/`(.*?)`/g) || []) - .slice(1) - .forEach((match) => queryCmds.push(match[1])); - setCmds(queryCmds.map((cmd) => [cmd, `{"${cmd}": {}}`])); - }, - } - ); - useEffect(() => { if (router.isReady) { const contractAddressParam = getFirstQueryParam( @@ -95,7 +69,6 @@ const Query = () => { setContractAddress(contractAddressParam); setInitialMsg(jsonMsg); - if (!contractAddressParam) setCmds([]); AmpTrackToQuery(!!contractAddressParam, !!msgParam); } @@ -103,7 +76,6 @@ const Query = () => { return ( - {isFetching && } Query Contract @@ -128,15 +100,16 @@ const Query = () => { mode="all-lists" contractAddress={contractAddress} onContractSelect={onContractSelect} + setCodeHash={setCodeHash} /> ); -}; +}); export default Query; diff --git a/src/lib/services/contractService.ts b/src/lib/services/contractService.ts index 7c58778c5..0904b1069 100644 --- a/src/lib/services/contractService.ts +++ b/src/lib/services/contractService.ts @@ -4,6 +4,7 @@ import { useCallback } from "react"; import { CELATONE_QUERY_KEYS, + useBaseApiRoute, useCelatoneApp, useWasmConfig, } from "lib/app-provider"; @@ -36,8 +37,11 @@ import type { } from "lib/types"; import { parseDate, parseTxHashOpt, parseDateOpt } from "lib/utils"; +import { getCodeIdInfo } from "./code"; + export interface ContractDetail extends ContractLocalInfo { codeId: number; + codeHash: string; admin: Option; } @@ -56,15 +60,21 @@ export const useContractDetailByContractAddress = ( onError?: (err: Error) => void ): UseQueryResult => { const { indexerGraphClient } = useCelatoneApp(); + const lcdEndpoint = useBaseApiRoute("rest"); const queryFn = useCallback(async () => { return indexerGraphClient .request(getContractByContractAddressQueryDocument, { contractAddress }) - .then(({ contracts_by_pk }) => { + .then(async ({ contracts_by_pk }) => { if (!contracts_by_pk) throw Error("Contract not found"); + const codeHash = await getCodeIdInfo( + lcdEndpoint, + String(contracts_by_pk.code_id) + ).then((data) => data.code_info.data_hash); return { contractAddress, codeId: contracts_by_pk.code_id, + codeHash, label: contracts_by_pk.label, instantiator: contracts_by_pk.accountByInitBy?.address as Addr, admin: contracts_by_pk.admin @@ -72,7 +82,7 @@ export const useContractDetailByContractAddress = ( : undefined, }; }); - }, [contractAddress, indexerGraphClient]); + }, [contractAddress, lcdEndpoint, indexerGraphClient]); return useQuery( [ diff --git a/src/lib/stores/contract.ts b/src/lib/stores/contract.ts index 651f5e575..d8019ae6e 100644 --- a/src/lib/stores/contract.ts +++ b/src/lib/stores/contract.ts @@ -354,7 +354,8 @@ export class ContractStore { list.lastUpdated = getCurrentDate(); } - addActivity(userKey: string, activity: Activity) { + addActivity(activity: Activity) { + const { userKey } = this; const recent = this.recentActivities[userKey]; if (recent) { diff --git a/src/lib/stores/schema.ts b/src/lib/stores/schema.ts index c2bd31b2d..72ff2903b 100644 --- a/src/lib/stores/schema.ts +++ b/src/lib/stores/schema.ts @@ -18,10 +18,11 @@ export enum SchemaProperties { type NullableJsonSchema = JsonSchema | null; -interface QueryExecuteSchema { +export interface QueryExecuteSchema { title: Option; description: Option; schema: JsonSchema; + inputRequired?: boolean; } export interface CodeSchema { @@ -36,6 +37,8 @@ export interface CodeSchema { [SchemaProperties.RESPONSES]: { [key: string]: JsonSchema }; } +export type QuerySchema = Array<[QueryExecuteSchema, JsonSchema]>; + export class SchemaStore { /** * @remarks code hash as key and json schema as value (annotated as Dict>) @@ -77,9 +80,7 @@ export class SchemaStore { return this.jsonSchemas[codeHash]?.[property]; } - getQuerySchema( - codeHash: string - ): Option> { + getQuerySchema(codeHash: string): Option { const querySchema = this.getSchemaProperty( codeHash, SchemaProperties.QUERY @@ -102,17 +103,23 @@ export class SchemaStore { delete eachQuerySchema.description; + const title = required[0]; + const queryInputStruct = ( + eachQuerySchema.properties?.[title] as JsonSchema + ).properties; + return [ ...acc, [ { - title: required[0], + title, description: desc1, schema: { ...eachQuerySchema, $schema: querySchema.$schema, definitions: querySchema.definitions, }, + inputRequired: Boolean(queryInputStruct), }, { ...responsesSchema[required[0]], From 4b8befa6a49c9596ab706b5ae97df9326022a2eb Mon Sep 17 00:00:00 2001 From: poomthiti Date: Fri, 18 Aug 2023 14:16:17 +0700 Subject: [PATCH 35/94] feat: enhance query ui, lowercase code hash in store fn --- src/lib/components/ContractSelectSection.tsx | 8 +- src/lib/components/InputWithIcon.tsx | 6 +- src/lib/components/copy/CopyButton.tsx | 2 + src/lib/components/copy/CopyTemplate.tsx | 4 + .../json-schema/MessageInputSwitch.tsx | 4 +- src/lib/pages/query/components/QueryArea.tsx | 21 ++- .../pages/query/components/SchemaQuery.tsx | 123 +++++++++++++----- src/lib/pages/query/index.tsx | 9 +- src/lib/services/contractService.ts | 1 + .../query-schema-output.json | 4 + src/lib/stores/schema.test.ts | 25 ++++ src/lib/stores/schema.ts | 22 ++-- 12 files changed, 178 insertions(+), 51 deletions(-) diff --git a/src/lib/components/ContractSelectSection.tsx b/src/lib/components/ContractSelectSection.tsx index 5c18648fa..2c1ed7621 100644 --- a/src/lib/components/ContractSelectSection.tsx +++ b/src/lib/components/ContractSelectSection.tsx @@ -1,11 +1,11 @@ import { Button, Flex, Text } from "@chakra-ui/react"; import { observer } from "mobx-react-lite"; -import type { Dispatch, SetStateAction } from "react"; import { useEffect, useMemo } from "react"; import { useForm } from "react-hook-form"; import { useMobile } from "lib/app-provider"; import { useContractStore } from "lib/providers/store"; +import type { ContractDetail } from "lib/services/contractService"; import { useContractDetailByContractAddress } from "lib/services/contractService"; import type { ContractLocalInfo } from "lib/stores/contract"; import type { Addr, ContractAddr, Option } from "lib/types"; @@ -36,7 +36,7 @@ interface ContractSelectSectionProps { mode: "all-lists" | "only-admin"; contractAddress: ContractAddr; onContractSelect: (contract: ContractAddr) => void; - setCodeHash?: Dispatch>; + successCallback?: (data: ContractDetail) => void; } const modeStyle = (mode: string) => { @@ -137,7 +137,7 @@ export const ContractSelectSection = observer( mode, contractAddress, onContractSelect, - setCodeHash, + successCallback, }: ContractSelectSectionProps) => { const { getContractLocalInfo } = useContractStore(); const isMobile = useMobile(); @@ -159,7 +159,7 @@ export const ContractSelectSection = observer( const { refetch } = useContractDetailByContractAddress( contractAddress, (data) => { - setCodeHash?.(data.codeHash.toLowerCase()); + successCallback?.(data); reset({ isValid: true, instantiator: data.instantiator, diff --git a/src/lib/components/InputWithIcon.tsx b/src/lib/components/InputWithIcon.tsx index 402cf8f9e..f924571bd 100644 --- a/src/lib/components/InputWithIcon.tsx +++ b/src/lib/components/InputWithIcon.tsx @@ -29,7 +29,11 @@ const InputWithIcon = ({ size={size} onClick={action ? () => AmpTrack(AmpEvent.USE_SEARCH_INPUT) : undefined} /> - + diff --git a/src/lib/components/copy/CopyButton.tsx b/src/lib/components/copy/CopyButton.tsx index 944a80434..8dbc6e412 100644 --- a/src/lib/components/copy/CopyButton.tsx +++ b/src/lib/components/copy/CopyButton.tsx @@ -24,12 +24,14 @@ export const CopyButton = ({ variant = "outline-accent", buttonText = "Copy", amptrackSection, + ml, ...buttonProps }: CopyButtonProps) => ( { const { onCopy, hasCopied, setValue } = useClipboard(value); useEffect(() => setValue(value), [value, setValue]); @@ -27,6 +30,7 @@ export const CopyTemplate = ({ onCopy(); e.stopPropagation(); }} + ml={ml} > {triggerElement} diff --git a/src/lib/components/json-schema/MessageInputSwitch.tsx b/src/lib/components/json-schema/MessageInputSwitch.tsx index 2dad7c871..507d9314b 100644 --- a/src/lib/components/json-schema/MessageInputSwitch.tsx +++ b/src/lib/components/json-schema/MessageInputSwitch.tsx @@ -16,6 +16,7 @@ export const yourSchemaInputFormKey = MessageTabs.YOUR_SCHEMA as "Your Schema"; interface MessageInputSwitchProps { currentTab: MessageTabs; disabled?: boolean; + tooltipLabel?: string; onTabChange: Dispatch>; } @@ -24,12 +25,13 @@ const tabs = Object.values(MessageTabs); export const MessageInputSwitch = ({ currentTab, disabled = false, + tooltipLabel = "Select or fill code id first", onTabChange, }: MessageInputSwitchProps) => { const tabRefs = useRef<(HTMLDivElement | null)[]>([]); const activeIndex = tabs.indexOf(currentTab); return ( - +
; initialMsg: string; } export const QueryArea = ({ contractAddress, + codeId, + codeHash, schema, initialMsg, }: QueryAreaProps) => { @@ -39,6 +44,11 @@ export const QueryArea = ({ currentTab={tab} onTabChange={setTab} disabled={!schema} + tooltipLabel={ + codeId && !schema + ? `You haven't attached the JSON Schema for code id ${codeId}. \n To use the schema, please add it on the code detail page.` + : "Please select contract first." + } /> } schemaContent={ - + codeHash ? ( + + ) : ( + + ) } /> diff --git a/src/lib/pages/query/components/SchemaQuery.tsx b/src/lib/pages/query/components/SchemaQuery.tsx index 659754e4e..a5100230b 100644 --- a/src/lib/pages/query/components/SchemaQuery.tsx +++ b/src/lib/pages/query/components/SchemaQuery.tsx @@ -9,9 +9,6 @@ import { Flex, Grid, GridItem, - Input, - InputGroup, - InputRightElement, Text, } from "@chakra-ui/react"; import type { RJSFSchema } from "@rjsf/utils"; @@ -19,7 +16,7 @@ import { useQuery } from "@tanstack/react-query"; import type { AxiosError } from "axios"; import { encode } from "js-base64"; import dynamic from "next/dynamic"; -import { useCallback, useEffect, useState } from "react"; +import { useCallback, useEffect, useMemo, useState } from "react"; import { CELATONE_QUERY_KEYS, @@ -28,7 +25,9 @@ import { } from "lib/app-provider"; import { CopyButton } from "lib/components/copy"; import { CustomIcon } from "lib/components/icon"; +import InputWithIcon from "lib/components/InputWithIcon"; import { JsonSchemaForm } from "lib/components/json-schema"; +import { EmptyState } from "lib/components/state"; import { DEFAULT_RPC_ERROR } from "lib/data"; import { useContractStore } from "lib/providers/store"; import { AmpTrack, AmpEvent, AmpTrackExpandAll } from "lib/services/amplitude"; @@ -61,7 +60,7 @@ const QueryComponent = ({ }: QueryComponentInterface) => { const [msg, setMsg] = useState("{}"); const [res, setRes] = useState("{}"); - // console.log(JSON.stringify({ [msgSchema.title]: {} })); + // TODO: Abstract query const { refetch, @@ -126,7 +125,7 @@ const QueryComponent = ({ - + )} + {msgSchema.inputRequired && ( + + + Return Output + + + Query response will display here + + + + )} { + try { + return JSON.parse(res); + } catch (_) { + return {}; + } + })()} /> + {!msgSchema.inputRequired && ( + + + + + + + + + )} @@ -192,23 +247,22 @@ export const SchemaQuery = ({ schema, contractAddress }: SchemaQueryProps) => { const [keyword, setKeyword] = useState(""); const [expandedIndexes, setExpandedIndexes] = useState([]); + const filteredMsgs = useMemo( + () => + schema?.filter((querySchema) => querySchema[0].title?.includes(keyword)), + [schema, keyword] + ); + if (!schema) return null; return ( <> - - setKeyword(e.target.value)} - h="40px" - /> - - - - + setKeyword(e.target.value)} + /> - setExpandedIndexes(indexes)} - sx={{ ".chakra-accordion__icon": { color: "gray.600" } }} - > - {schema - .filter((querySchema) => querySchema[0].title?.includes(keyword)) - .map(([msg, res]) => ( + {filteredMsgs?.length ? ( + setExpandedIndexes(indexes)} + sx={{ ".chakra-accordion__icon": { color: "gray.600" } }} + > + {filteredMsgs.map(([msg, res]) => ( { addActivity={addActivity} /> ))} - + + ) : ( + + )} ); }; diff --git a/src/lib/pages/query/index.tsx b/src/lib/pages/query/index.tsx index a5f4c474e..1a71657b8 100644 --- a/src/lib/pages/query/index.tsx +++ b/src/lib/pages/query/index.tsx @@ -13,6 +13,7 @@ import { CustomIcon } from "lib/components/icon"; import PageContainer from "lib/components/PageContainer"; import { useSchemaStore } from "lib/providers/store"; import { AmpTrackToQuery } from "lib/services/amplitude"; +import type { ContractDetail } from "lib/services/contractService"; import type { ContractAddr } from "lib/types"; import { jsonPrettify, @@ -31,6 +32,7 @@ const Query = observer(() => { const [contractAddress, setContractAddress] = useState("" as ContractAddr); const [codeHash, setCodeHash] = useState(""); + const [codeId, setCodeId] = useState(""); const [initialMsg, setInitialMsg] = useState(""); const isMobile = useMobile(); const schema = getQuerySchema(codeHash); @@ -100,13 +102,18 @@ const Query = observer(() => { mode="all-lists" contractAddress={contractAddress} onContractSelect={onContractSelect} - setCodeHash={setCodeHash} + successCallback={(data: ContractDetail) => { + setCodeHash(data.codeHash); + setCodeId(String(data.codeId)); + }} /> ); diff --git a/src/lib/services/contractService.ts b/src/lib/services/contractService.ts index 0904b1069..6a30f813b 100644 --- a/src/lib/services/contractService.ts +++ b/src/lib/services/contractService.ts @@ -67,6 +67,7 @@ export const useContractDetailByContractAddress = ( .request(getContractByContractAddressQueryDocument, { contractAddress }) .then(async ({ contracts_by_pk }) => { if (!contracts_by_pk) throw Error("Contract not found"); + // TODO: retrieve code hash from gql instead when available const codeHash = await getCodeIdInfo( lcdEndpoint, String(contracts_by_pk.code_id) diff --git a/src/lib/stores/schema-test-suite/query-schema-output.json b/src/lib/stores/schema-test-suite/query-schema-output.json index 2f73d3b1c..998531025 100644 --- a/src/lib/stores/schema-test-suite/query-schema-output.json +++ b/src/lib/stores/schema-test-suite/query-schema-output.json @@ -3,6 +3,7 @@ { "title": "config", "description": "Get config", + "inputRequired": false, "schema": { "type": "object", "required": ["config"], @@ -73,6 +74,7 @@ { "title": "address", "description": "Get a single address", + "inputRequired": true, "schema": { "type": "object", "required": ["address"], @@ -167,6 +169,7 @@ { "title": "addresses", "description": "Get a list of addresses", + "inputRequired": true, "schema": { "type": "object", "required": ["addresses"], @@ -270,6 +273,7 @@ { "title": "all_addresses", "description": "Query all stored addresses with pagination", + "inputRequired": true, "schema": { "type": "object", "required": ["all_addresses"], diff --git a/src/lib/stores/schema.test.ts b/src/lib/stores/schema.test.ts index c6ef825a9..f31aef830 100644 --- a/src/lib/stores/schema.test.ts +++ b/src/lib/stores/schema.test.ts @@ -38,6 +38,11 @@ describe("getSchemaByCodeHash", () => { exampleSchema ); }); + test("correctly get schema by uppercase code hash", () => { + expect( + schemaStore.getSchemaByCodeHash(codeHash.toUpperCase()) + ).toStrictEqual(exampleSchema); + }); test("return undefined on code hash not found", () => { expect(schemaStore.getSchemaByCodeHash("randomHash")).toBeUndefined(); }); @@ -74,6 +79,15 @@ describe("getSchemaProperty", () => { ).toStrictEqual(exampleSchema.responses); }); + test("correctly retrieve schema property from uppercase code hash", () => { + expect( + schemaStore.getSchemaProperty( + codeHash.toUpperCase(), + SchemaProperties.CONTRACT_NAME + ) + ).toStrictEqual(exampleSchema.contract_name); + }); + test("correctly return undefined on code hash not found", () => { expect( schemaStore.getSchemaProperty( @@ -89,6 +103,12 @@ describe("getQuerySchemaFormArray", () => { expect(schemaStore.getQuerySchema(codeHash)).toEqual(querySchemaOutput); }); + test("correctly get form array for query schema from uppercase code hash", () => { + expect(schemaStore.getQuerySchema(codeHash.toUpperCase())).toEqual( + querySchemaOutput + ); + }); + test("correctly return undefined for non-existent code hash", () => { expect(schemaStore.getQuerySchema("randomHash")).toBeUndefined(); }); @@ -98,6 +118,11 @@ describe("getExecuteSchemaFormArray", () => { test("correctly get form array for execute schema", () => { expect(schemaStore.getExecuteSchema(codeHash)).toEqual(executeSchemaOutput); }); + test("correctly get form array for execute schema from uppercase code hash", () => { + expect(schemaStore.getExecuteSchema(codeHash.toUpperCase())).toEqual( + executeSchemaOutput + ); + }); test("correctly return undefined for non-existent code hash", () => { expect(schemaStore.getExecuteSchema("randomHash")).toBeUndefined(); }); diff --git a/src/lib/stores/schema.ts b/src/lib/stores/schema.ts index 72ff2903b..ce8270b42 100644 --- a/src/lib/stores/schema.ts +++ b/src/lib/stores/schema.ts @@ -65,29 +65,29 @@ export class SchemaStore { } saveNewSchema(codeHash: string, schema: CodeSchema) { - this.jsonSchemas[codeHash] = schema; + this.jsonSchemas[codeHash.toLowerCase()] = schema; } deleteSchema(codeHash: string) { - delete this.jsonSchemas[codeHash]; + delete this.jsonSchemas[codeHash.toLowerCase()]; } getSchemaByCodeHash(codeHash: string): Option { - return this.jsonSchemas[codeHash]; + return this.jsonSchemas[codeHash.toLowerCase()]; } getSchemaProperty(codeHash: string, property: T) { - return this.jsonSchemas[codeHash]?.[property]; + return this.jsonSchemas[codeHash.toLowerCase()]?.[property]; } getQuerySchema(codeHash: string): Option { const querySchema = this.getSchemaProperty( - codeHash, + codeHash.toLowerCase(), SchemaProperties.QUERY ); const responsesSchema = this.getSchemaProperty( - codeHash, + codeHash.toLowerCase(), SchemaProperties.RESPONSES ); @@ -104,9 +104,9 @@ export class SchemaStore { delete eachQuerySchema.description; const title = required[0]; - const queryInputStruct = ( - eachQuerySchema.properties?.[title] as JsonSchema - ).properties; + const propertyKey = eachQuerySchema.properties?.[title] as JsonSchema; + const noInputRequired = + propertyKey.type === "object" && !("properties" in propertyKey); return [ ...acc, @@ -119,7 +119,7 @@ export class SchemaStore { $schema: querySchema.$schema, definitions: querySchema.definitions, }, - inputRequired: Boolean(queryInputStruct), + inputRequired: !noInputRequired, }, { ...responsesSchema[required[0]], @@ -137,7 +137,7 @@ export class SchemaStore { getExecuteSchema(codeHash: string): Option> { const executeSchema = this.getSchemaProperty( - codeHash, + codeHash.toLowerCase(), SchemaProperties.EXECUTE ); From 295d49d70bcd8a996863e82fa0a59bf56656a6a7 Mon Sep 17 00:00:00 2001 From: poomthiti Date: Fri, 18 Aug 2023 14:27:13 +0700 Subject: [PATCH 36/94] fix: add query error alert --- src/lib/pages/query/components/SchemaQuery.tsx | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/lib/pages/query/components/SchemaQuery.tsx b/src/lib/pages/query/components/SchemaQuery.tsx index a5100230b..21e91b1ab 100644 --- a/src/lib/pages/query/components/SchemaQuery.tsx +++ b/src/lib/pages/query/components/SchemaQuery.tsx @@ -4,6 +4,8 @@ import { AccordionIcon, AccordionItem, AccordionPanel, + Alert, + AlertDescription, Box, Button, Flex, @@ -60,6 +62,7 @@ const QueryComponent = ({ }: QueryComponentInterface) => { const [msg, setMsg] = useState("{}"); const [res, setRes] = useState("{}"); + const [queryError, setQueryError] = useState(""); // TODO: Abstract query const { @@ -87,6 +90,7 @@ const QueryComponent = ({ retry: false, cacheTime: 0, onSuccess(data) { + setQueryError(""); setRes(JSON.stringify(data.data, null, 2)); addActivity({ type: "query", @@ -98,7 +102,7 @@ const QueryComponent = ({ }); }, onError(err: AxiosError) { - setRes(err.response?.data.message || DEFAULT_RPC_ERROR); + setQueryError(err.response?.data.message || DEFAULT_RPC_ERROR); }, } ); @@ -139,7 +143,6 @@ const QueryComponent = ({ /> )} + {queryError && ( + + + {queryError} + + + )} Date: Fri, 18 Aug 2023 14:59:37 +0700 Subject: [PATCH 37/94] chore: add normailize fn --- src/lib/stores/schema.ts | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/lib/stores/schema.ts b/src/lib/stores/schema.ts index ce8270b42..dd695ab1f 100644 --- a/src/lib/stores/schema.ts +++ b/src/lib/stores/schema.ts @@ -39,6 +39,10 @@ export interface CodeSchema { export type QuerySchema = Array<[QueryExecuteSchema, JsonSchema]>; +const normalize = (codeHash: string) => { + return codeHash.toLowerCase(); +}; + export class SchemaStore { /** * @remarks code hash as key and json schema as value (annotated as Dict>) @@ -65,29 +69,29 @@ export class SchemaStore { } saveNewSchema(codeHash: string, schema: CodeSchema) { - this.jsonSchemas[codeHash.toLowerCase()] = schema; + this.jsonSchemas[normalize(codeHash)] = schema; } deleteSchema(codeHash: string) { - delete this.jsonSchemas[codeHash.toLowerCase()]; + delete this.jsonSchemas[normalize(codeHash)]; } getSchemaByCodeHash(codeHash: string): Option { - return this.jsonSchemas[codeHash.toLowerCase()]; + return this.jsonSchemas[normalize(codeHash)]; } getSchemaProperty(codeHash: string, property: T) { - return this.jsonSchemas[codeHash.toLowerCase()]?.[property]; + return this.jsonSchemas[normalize(codeHash)]?.[property]; } getQuerySchema(codeHash: string): Option { const querySchema = this.getSchemaProperty( - codeHash.toLowerCase(), + normalize(codeHash), SchemaProperties.QUERY ); const responsesSchema = this.getSchemaProperty( - codeHash.toLowerCase(), + normalize(codeHash), SchemaProperties.RESPONSES ); @@ -137,7 +141,7 @@ export class SchemaStore { getExecuteSchema(codeHash: string): Option> { const executeSchema = this.getSchemaProperty( - codeHash.toLowerCase(), + normalize(codeHash), SchemaProperties.EXECUTE ); From eec4919ed2bcf204e08732fbda45f3c5cf511a61 Mon Sep 17 00:00:00 2001 From: poomthiti Date: Mon, 21 Aug 2023 15:31:45 +0700 Subject: [PATCH 38/94] feat: switch to schema tab when available and prefill,expand,and scroll to the prefill msg --- CHANGELOG.md | 1 + src/lib/app-provider/contexts/app.tsx | 25 +--- src/lib/app-provider/contexts/index.ts | 1 + src/lib/app-provider/contexts/nav.tsx | 42 ++++++ src/lib/components/ContractSelectSection.tsx | 140 +++++++++--------- src/lib/layout/index.tsx | 4 +- src/lib/pages/home/index.tsx | 8 +- src/lib/pages/query/components/QueryArea.tsx | 9 +- .../pages/query/components/SchemaQuery.tsx | 62 ++++++-- src/lib/utils/json.ts | 10 ++ src/pages/_app.tsx | 14 +- 11 files changed, 203 insertions(+), 113 deletions(-) create mode 100644 src/lib/app-provider/contexts/nav.tsx diff --git a/CHANGELOG.md b/CHANGELOG.md index 3f3a5b434..a21dcd3a3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,6 +39,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Features +- [#486](https://github.com/alleslabs/celatone-frontend/pull/486) Switch to schema tab when available and prefill,expand,and scroll to the prefill msg - [#482](https://github.com/alleslabs/celatone-frontend/pull/482) Add json schema functionality to query page - [#477](https://github.com/alleslabs/celatone-frontend/pull/477) Add json schema section on code detail page - [#475](https://github.com/alleslabs/celatone-frontend/pull/475) Add json schema functionality to instantiate contract diff --git a/src/lib/app-provider/contexts/app.tsx b/src/lib/app-provider/contexts/app.tsx index 967f78395..d0870a9fb 100644 --- a/src/lib/app-provider/contexts/app.tsx +++ b/src/lib/app-provider/contexts/app.tsx @@ -1,7 +1,7 @@ import { useModalTheme } from "@cosmos-kit/react"; import { GraphQLClient } from "graphql-request"; import { observer } from "mobx-react-lite"; -import type { Dispatch, ReactNode, SetStateAction } from "react"; +import type { ReactNode } from "react"; import { useCallback, useState, @@ -21,13 +21,11 @@ import { SUPPORTED_CHAIN_IDS } from "env"; import { LoadingOverlay } from "lib/components/LoadingOverlay"; import { NetworkErrorState } from "lib/components/state/NetworkErrorState"; import { DEFAULT_ADDRESS } from "lib/data"; -import { useLocalStorage } from "lib/hooks/useLocalStorage"; import { useCodeStore, useContractStore, usePublicProjectStore, } from "lib/providers/store"; -import type { Option } from "lib/types"; import { formatUserKey } from "lib/utils"; interface AppProviderProps { @@ -40,10 +38,6 @@ interface AppContextInterface { chainConfig: ChainConfig; indexerGraphClient: GraphQLClient; constants: ProjectConstants; - isExpand: boolean; - isDevMode: Option; - setIsExpand: Dispatch>; - setIsDevMode: Dispatch>>; } const AppContext = createContext({ @@ -52,10 +46,6 @@ const AppContext = createContext({ chainConfig: DEFAULT_CHAIN_CONFIG, indexerGraphClient: new GraphQLClient(DEFAULT_CHAIN_CONFIG.indexer), constants: PROJECT_CONSTANTS, - isExpand: false, - isDevMode: undefined, - setIsExpand: () => {}, - setIsDevMode: () => {}, }); export const AppProvider = observer(({ children }: AppProviderProps) => { @@ -67,13 +57,6 @@ export const AppProvider = observer(({ children }: AppProviderProps) => { const [currentChainName, setCurrentChainName] = useState(); const [currentChainId, setCurrentChainId] = useState(""); - // TODO - Revisit localstorage - const [isDevMode, setIsDevMode] = useLocalStorage>( - "devMode", - undefined - ); - const [isExpand, setIsExpand] = useLocalStorage("navbar", false); - // Remark: this function is only used in useSelectChain. Do not use in other places. const handleOnChainIdChange = useCallback((newChainId: string) => { const config = CHAIN_CONFIGS[newChainId]; @@ -90,12 +73,8 @@ export const AppProvider = observer(({ children }: AppProviderProps) => { chainConfig, indexerGraphClient: new GraphQLClient(chainConfig.indexer), constants: PROJECT_CONSTANTS, - isDevMode, - isExpand, - setIsDevMode, - setIsExpand, }; - }, [currentChainId, isDevMode, isExpand, setIsDevMode, setIsExpand]); + }, [currentChainId]); useEffect(() => { if (currentChainName) { diff --git a/src/lib/app-provider/contexts/index.ts b/src/lib/app-provider/contexts/index.ts index ac5307def..641ade193 100644 --- a/src/lib/app-provider/contexts/index.ts +++ b/src/lib/app-provider/contexts/index.ts @@ -1 +1,2 @@ export * from "./app"; +export * from "./nav"; diff --git a/src/lib/app-provider/contexts/nav.tsx b/src/lib/app-provider/contexts/nav.tsx new file mode 100644 index 000000000..8eea19795 --- /dev/null +++ b/src/lib/app-provider/contexts/nav.tsx @@ -0,0 +1,42 @@ +import type { Dispatch, ReactNode, SetStateAction } from "react"; +import { useContext, createContext, useMemo } from "react"; + +import { useLocalStorage } from "lib/hooks/useLocalStorage"; +import type { Option } from "lib/types"; + +interface NavContextInterface { + isExpand: boolean; + isDevMode: Option; + setIsExpand: Dispatch>; + setIsDevMode: Dispatch>>; +} +const NavContext = createContext({ + isExpand: false, + isDevMode: undefined, + setIsExpand: () => {}, + setIsDevMode: () => {}, +}); + +export const NavProvider = ({ children }: { children: ReactNode }) => { + const [isDevMode, setIsDevMode] = useLocalStorage>( + "devMode", + undefined + ); + const [isExpand, setIsExpand] = useLocalStorage("navbar", false); + + const states = useMemo( + () => ({ + isDevMode, + isExpand, + setIsDevMode, + setIsExpand, + }), + [isDevMode, isExpand, setIsDevMode, setIsExpand] + ); + + return {children}; +}; + +export const useNavContext = (): NavContextInterface => { + return useContext(NavContext); +}; diff --git a/src/lib/components/ContractSelectSection.tsx b/src/lib/components/ContractSelectSection.tsx index 2c1ed7621..bcde0c295 100644 --- a/src/lib/components/ContractSelectSection.tsx +++ b/src/lib/components/ContractSelectSection.tsx @@ -12,6 +12,7 @@ import type { Addr, ContractAddr, Option } from "lib/types"; import { ExplorerLink } from "./ExplorerLink"; import { CustomIcon } from "./icon"; +import { LoadingOverlay } from "./LoadingOverlay"; import { EditContractDetailsModal, SaveContractDetailsModal } from "./modal"; import { SelectContractAdmin, @@ -156,7 +157,7 @@ export const ContractSelectSection = observer( mode: "all", }); - const { refetch } = useContractDetailByContractAddress( + const { refetch, isFetching } = useContractDetailByContractAddress( contractAddress, (data) => { successCallback?.(data); @@ -188,77 +189,80 @@ export const ContractSelectSection = observer( const style = modeStyle(mode); return ( - - - - Contract Address - {!notSelected ? ( - - ) : ( - - Not Selected - - )} - - - Contract Name - - - - {mode === "all-lists" && contractState.isValid && ( - - )} - {mode === "all-lists" ? ( - - ) : ( - + {isFetching && } + + + + Contract Address + {!notSelected ? ( + + ) : ( + + Not Selected + + )} + + + Contract Name + - )} + + + {mode === "all-lists" && contractState.isValid && ( + + )} + {mode === "all-lists" ? ( + + ) : ( + + )} + - + ); } ); diff --git a/src/lib/layout/index.tsx b/src/lib/layout/index.tsx index 180746438..171a1e431 100644 --- a/src/lib/layout/index.tsx +++ b/src/lib/layout/index.tsx @@ -3,7 +3,7 @@ import { useRouter } from "next/router"; import type { ReactNode } from "react"; import { useEffect, useMemo } from "react"; -import { useCelatoneApp, useMobile } from "lib/app-provider"; +import { useMobile, useNavContext } from "lib/app-provider"; import { scrollToTop } from "lib/utils"; import Footer from "./Footer"; @@ -19,7 +19,7 @@ type LayoutProps = { const Layout = ({ children }: LayoutProps) => { const router = useRouter(); const isMobile = useMobile(); - const { isExpand, isDevMode, setIsExpand, setIsDevMode } = useCelatoneApp(); + const { isExpand, isDevMode, setIsExpand, setIsDevMode } = useNavContext(); const defaultRow = "70px 48px 1fr"; const mode = useMemo(() => { diff --git a/src/lib/pages/home/index.tsx b/src/lib/pages/home/index.tsx index f83c50f01..2b4409f39 100644 --- a/src/lib/pages/home/index.tsx +++ b/src/lib/pages/home/index.tsx @@ -4,7 +4,11 @@ import { useRouter } from "next/router"; import { useEffect } from "react"; import { CURR_THEME } from "env"; -import { useCelatoneApp, useInternalNavigate } from "lib/app-provider"; +import { + useCelatoneApp, + useInternalNavigate, + useNavContext, +} from "lib/app-provider"; import { ConnectWalletAlert } from "lib/components/ConnectWalletAlert"; import { CustomIcon } from "lib/components/icon"; import PageContainer from "lib/components/PageContainer"; @@ -108,7 +112,7 @@ const calculateAverageBlockTime = ( const Home = () => { const router = useRouter(); const navigate = useInternalNavigate(); - const { isDevMode } = useCelatoneApp(); + const { isDevMode } = useNavContext(); const { chainConfig: { prettyName }, diff --git a/src/lib/pages/query/components/QueryArea.tsx b/src/lib/pages/query/components/QueryArea.tsx index 59c576c49..1be05e451 100644 --- a/src/lib/pages/query/components/QueryArea.tsx +++ b/src/lib/pages/query/components/QueryArea.tsx @@ -32,6 +32,9 @@ export const QueryArea = ({ useEffect(() => { if (!schema) setTab(MessageTabs.JSON_INPUT); + else { + setTab(MessageTabs.YOUR_SCHEMA); + } }, [schema]); return ( @@ -61,7 +64,11 @@ export const QueryArea = ({ } schemaContent={ codeHash ? ( - + ) : ( import("lib/components/modal/CodeSnippet"), { ssr: false, @@ -49,6 +53,7 @@ interface QueryComponentInterface { contractAddress: ContractAddr; lcdEndpoint: string; walletAddress: Option; + initialMsg: Record; addActivity: (activity: Activity) => void; } @@ -58,6 +63,7 @@ const QueryComponent = ({ contractAddress, lcdEndpoint, walletAddress, + initialMsg, addActivity, }: QueryComponentInterface) => { const [msg, setMsg] = useState("{}"); @@ -117,7 +123,7 @@ const QueryComponent = ({ }, [msgSchema.inputRequired, refetch]); return ( - +
@@ -140,6 +146,7 @@ const QueryComponent = ({ formId={`query-${msgSchema.title}`} schema={msgSchema.schema} onChange={(data) => setMsg(JSON.stringify(data))} + initialFormData={initialMsg} /> { - try { - return JSON.parse(res); - } catch (_) { - return {}; - } - })()} + initialFormData={parseSchemaInitialData(res)} /> {!msgSchema.inputRequired && ( @@ -247,13 +248,29 @@ const QueryComponent = ({ interface SchemaQueryProps { schema: Option; contractAddress: ContractAddr; + initialMsg: string; } -export const SchemaQuery = ({ schema, contractAddress }: SchemaQueryProps) => { +const resolveInitialMsg = ( + initialMsg: string, + msgSchema: QueryExecuteSchema +) => { + const parsed = parseSchemaInitialData(initialMsg); + return Object.keys(parsed)[0] === msgSchema.schema.required?.[0] + ? parsed + : {}; +}; + +export const SchemaQuery = ({ + schema, + contractAddress, + initialMsg, +}: SchemaQueryProps) => { const { addActivity } = useContractStore(); const { address } = useCurrentChain(); const lcdEndpoint = useBaseApiRoute("rest"); + const accordionRef = useRef(null); const [keyword, setKeyword] = useState(""); const [expandedIndexes, setExpandedIndexes] = useState([]); @@ -263,6 +280,27 @@ export const SchemaQuery = ({ schema, contractAddress }: SchemaQueryProps) => { [schema, keyword] ); + useEffect(() => { + if (schema && initialMsg && accordionRef.current) { + try { + const parsedMsg = JSON.parse(initialMsg); + const msgIndex = schema.findIndex( + ([msg]) => msg.schema.required?.[0] === Object.keys(parsedMsg)[0] + ); + setExpandedIndexes((prev) => + prev.includes(msgIndex) ? prev : prev.concat(msgIndex) + ); + const el = document.querySelector( + `.msg-${schema[msgIndex][0].schema.required?.[0]}` + ); + el?.scrollIntoView(); + } catch (_) { + // + } + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [schema, initialMsg, accordionRef.current]); + if (!schema) return null; return ( @@ -289,6 +327,7 @@ export const SchemaQuery = ({ schema, contractAddress }: SchemaQueryProps) => { {filteredMsgs?.length ? ( { contractAddress={contractAddress} lcdEndpoint={lcdEndpoint} walletAddress={address} + initialMsg={resolveInitialMsg(initialMsg, msg)} addActivity={addActivity} /> ))} diff --git a/src/lib/utils/json.ts b/src/lib/utils/json.ts index 48f0670d4..f743ab333 100644 --- a/src/lib/utils/json.ts +++ b/src/lib/utils/json.ts @@ -18,3 +18,13 @@ export const jsonPrettify = (text: string) => { }; export const jsonLineCount = (text: string) => text.split(/\n/).length; + +export const parseSchemaInitialData = ( + json: string +): Record => { + try { + return JSON.parse(json); + } catch (_) { + return {}; + } +}; diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx index 3a32134f8..41b94ade0 100644 --- a/src/pages/_app.tsx +++ b/src/pages/_app.tsx @@ -11,7 +11,7 @@ import Head from "next/head"; import Script from "next/script"; import { CHAIN_CONFIGS } from "config/chain"; -import { AppProvider } from "lib/app-provider/contexts/app"; +import { AppProvider, NavProvider } from "lib/app-provider"; import { localosmosis, localosmosisAsset, @@ -99,11 +99,13 @@ const MyApp = ({ Component, pageProps }: AppProps) => { /> - - - - - + + + + + + + From bfb058e016b351d6a29c446979841648629f8751 Mon Sep 17 00:00:00 2001 From: poomthiti Date: Mon, 21 Aug 2023 16:00:50 +0700 Subject: [PATCH 39/94] fix: set msg state on prefill --- src/lib/pages/query/components/SchemaQuery.tsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/lib/pages/query/components/SchemaQuery.tsx b/src/lib/pages/query/components/SchemaQuery.tsx index 2ee3c0cf0..ceb67ded5 100644 --- a/src/lib/pages/query/components/SchemaQuery.tsx +++ b/src/lib/pages/query/components/SchemaQuery.tsx @@ -70,6 +70,10 @@ const QueryComponent = ({ const [res, setRes] = useState("{}"); const [queryError, setQueryError] = useState(""); + useEffect(() => { + if (Object.keys(initialMsg).length) setMsg(JSON.stringify(initialMsg)); + }, [initialMsg]); + // TODO: Abstract query const { refetch, From 687bf398e23d04709eff64abb1bbfd5d07e57ec5 Mon Sep 17 00:00:00 2001 From: songwongtp <16089160+songwongtp@users.noreply.github.com> Date: Tue, 22 Aug 2023 01:59:49 +0700 Subject: [PATCH 40/94] feat: jsonschema responseUI --- CHANGELOG.md | 1 + .../json-schema/MessageInputSwitch.tsx | 4 +- .../json-schema/form/contract_schema.json | 797 ------------------ .../form/fields/MultiSchemaField.tsx | 12 +- src/lib/components/json-schema/form/index.tsx | 195 ++--- .../form/templates/ArrayFieldItemTemplate.tsx | 12 +- .../form/templates/ArrayFieldTemplate.tsx | 58 +- .../form/templates/BaseInputTemplate.tsx | 18 +- .../form/templates/FieldTemplate.tsx | 2 +- .../form/templates/FieldTypeTag.tsx | 11 +- .../form/templates/ObjectFieldTemplate.tsx | 16 +- src/lib/components/json-schema/form/utils.ts | 74 +- .../json-schema/form/widgets/SelectWidget.tsx | 21 +- .../pages/query/components/SchemaQuery.tsx | 9 +- 14 files changed, 232 insertions(+), 998 deletions(-) delete mode 100644 src/lib/components/json-schema/form/contract_schema.json diff --git a/CHANGELOG.md b/CHANGELOG.md index 3f3a5b434..5cc771797 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -56,6 +56,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Improvements +- [#489](https://github.com/alleslabs/celatone-frontend/pull/489) Improve jsonschema query response UI and fix jsonschema incorrect oneOf behavior - [#457](https://github.com/alleslabs/celatone-frontend/pull/457) Add alert for proposal forum review - [#389](https://github.com/alleslabs/celatone-frontend/pull/389) Fix modal consistency - [#381](https://github.com/alleslabs/celatone-frontend/pull/381) Correctly infer output type from snake-camel utils diff --git a/src/lib/components/json-schema/MessageInputSwitch.tsx b/src/lib/components/json-schema/MessageInputSwitch.tsx index 507d9314b..4388987a2 100644 --- a/src/lib/components/json-schema/MessageInputSwitch.tsx +++ b/src/lib/components/json-schema/MessageInputSwitch.tsx @@ -73,7 +73,9 @@ export const MessageInputSwitch = ({ position="absolute" borderRadius="2px" backgroundColor="primary.dark" - animate={{ left: `${tabRefs.current[activeIndex]?.offsetLeft}px` }} + animate={{ + left: `${tabRefs.current[activeIndex]?.offsetLeft ?? 0}px`, + }} transition={{ type: "spring", stiffness: "250", diff --git a/src/lib/components/json-schema/form/contract_schema.json b/src/lib/components/json-schema/form/contract_schema.json deleted file mode 100644 index 7b0445f35..000000000 --- a/src/lib/components/json-schema/form/contract_schema.json +++ /dev/null @@ -1,797 +0,0 @@ -{ - "contract_name": "mars-incentives", - "contract_version": "1.1.0", - "idl_version": "1.0.0", - "instantiate": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "InstantiateMsg", - "type": "object", - "required": [ - "address_provider", - "epoch_duration", - "max_whitelisted_denoms", - "owner" - ], - "properties": { - "address_provider": { - "description": "Address provider", - "type": "string" - }, - "epoch_duration": { - "description": "The amount of time in seconds for each incentive epoch. This is the minimum amount of time that an incentive can last, and each incentive must be a multiple of this duration.", - "type": "integer", - "format": "uint64", - "minimum": 0.0 - }, - "max_whitelisted_denoms": { - "description": "The maximum number of incentive denoms that can be whitelisted at any given time. This is a guard against accidentally whitelisting too many denoms, which could cause max gas errors.", - "type": "integer", - "format": "uint8", - "minimum": 0.0 - }, - "owner": { - "description": "Contract owner", - "type": "string" - } - }, - "additionalProperties": false - }, - "execute": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "ExecuteMsg", - "oneOf": [ - { - "description": "Add or remove incentive denoms from the whitelist. Only admin can do this.", - "type": "object", - "required": ["update_whitelist"], - "properties": { - "update_whitelist": { - "type": "object", - "required": ["add_denoms", "remove_denoms"], - "properties": { - "add_denoms": { - "description": "The denoms to add to the whitelist as well as a minimum emission rate per second for each. If the denom is already in the whitelist, the minimum emission rate will be updated.", - "type": "array", - "items": { - "$ref": "#/definitions/WhitelistEntry" - } - }, - "remove_denoms": { - "description": "The denoms to remove from the whitelist. This will update the index of the incentive state and then remove any active incentive schedules.\n\nNB: If any incentive schedules are still active for this incentive denom, the incentive tokens will be trapped forever in the contract.", - "type": "array", - "items": { - "type": "string" - } - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false - }, - { - "description": "Add incentives for a given collateral denom and incentive denom pair", - "type": "object", - "required": ["set_asset_incentive"], - "properties": { - "set_asset_incentive": { - "type": "object", - "required": [ - "collateral_denom", - "duration", - "emission_per_second", - "incentive_denom", - "start_time" - ], - "properties": { - "collateral_denom": { - "description": "The denom of the collatearal token to receive incentives", - "type": "string" - }, - "duration": { - "description": "How many seconds the incentives last", - "type": "integer", - "format": "uint64", - "minimum": 0.0 - }, - "emission_per_second": { - "description": "How many `incentive_denom` tokens will be assigned per second to be distributed among all Red Bank depositors", - "allOf": [ - { - "$ref": "#/definitions/Uint128" - } - ] - }, - "incentive_denom": { - "description": "The denom of the token to give incentives with", - "type": "string" - }, - "start_time": { - "description": "Start time of the incentive (in seconds) since the UNIX epoch (00:00:00 on 1970-01-01 UTC).", - "type": "integer", - "format": "uint64", - "minimum": 0.0 - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false - }, - { - "description": "Handle balance change updating user and asset rewards. Sent from an external contract, triggered on user balance changes. Will return an empty response if no incentive is applied for the asset", - "type": "object", - "required": ["balance_change"], - "properties": { - "balance_change": { - "type": "object", - "required": [ - "denom", - "total_amount_scaled_before", - "user_addr", - "user_amount_scaled_before" - ], - "properties": { - "denom": { - "description": "Denom of the asset of which deposited balance is changed", - "type": "string" - }, - "total_amount_scaled_before": { - "description": "The market's total scaled collateral amount up to the instant before the change", - "allOf": [ - { - "$ref": "#/definitions/Uint128" - } - ] - }, - "user_addr": { - "description": "User address. Address is trusted as it must be validated by the Red Bank contract before calling this method", - "allOf": [ - { - "$ref": "#/definitions/Addr" - } - ] - }, - "user_amount_scaled_before": { - "description": "The user's scaled collateral amount up to the instant before the change", - "allOf": [ - { - "$ref": "#/definitions/Uint128" - } - ] - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false - }, - { - "description": "Claim rewards. MARS rewards accrued by the user will be staked into xMARS before being sent.", - "type": "object", - "required": ["claim_rewards"], - "properties": { - "claim_rewards": { - "type": "object", - "properties": { - "limit": { - "description": "The maximum number of results to return. If not set, 5 is used. If larger than 10, 10 is used.", - "type": ["integer", "null"], - "format": "uint32", - "minimum": 0.0 - }, - "start_after_collateral_denom": { - "description": "Start pagination after this collateral denom", - "type": ["string", "null"] - }, - "start_after_incentive_denom": { - "description": "Start pagination after this incentive denom. If supplied you must also supply start_after_collateral_denom.", - "type": ["string", "null"] - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false - }, - { - "description": "Update contract config (only callable by owner)", - "type": "object", - "required": ["update_config"], - "properties": { - "update_config": { - "type": "object", - "properties": { - "address_provider": { - "description": "The address provider contract address", - "type": ["string", "null"] - }, - "max_whitelisted_denoms": { - "description": "The maximum number of incentive denoms that can be whitelisted at any given time. This is a guard against accidentally whitelisting too many denoms, which could cause max gas errors.", - "type": ["integer", "null"], - "format": "uint8", - "minimum": 0.0 - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false - }, - { - "description": "Manages admin role state", - "type": "object", - "required": ["update_owner"], - "properties": { - "update_owner": { - "$ref": "#/definitions/OwnerUpdate" - } - }, - "additionalProperties": false - } - ], - "definitions": { - "Addr": { - "description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.", - "type": "string" - }, - "OwnerUpdate": { - "oneOf": [ - { - "description": "Proposes a new owner to take role. Only current owner can execute.", - "type": "object", - "required": ["propose_new_owner"], - "properties": { - "propose_new_owner": { - "type": "object", - "required": ["proposed"], - "properties": { - "proposed": { - "type": "string" - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false - }, - { - "description": "Clears the currently proposed owner. Only current owner can execute.", - "type": "string", - "enum": ["clear_proposed"] - }, - { - "description": "Promotes the proposed owner to be the current one. Only the proposed owner can execute.", - "type": "string", - "enum": ["accept_proposed"] - }, - { - "description": "Throws away the keys to the Owner role forever. Once done, no owner can ever be set later.", - "type": "string", - "enum": ["abolish_owner_role"] - }, - { - "description": "A separate entity managed by Owner that can be used for granting specific emergency powers.", - "type": "object", - "required": ["set_emergency_owner"], - "properties": { - "set_emergency_owner": { - "type": "object", - "required": ["emergency_owner"], - "properties": { - "emergency_owner": { - "type": "string" - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false - }, - { - "description": "Remove the entity in the Emergency Owner role", - "type": "string", - "enum": ["clear_emergency_owner"] - } - ] - }, - "Uint128": { - "description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```", - "type": "string" - }, - "WhitelistEntry": { - "type": "object", - "required": ["denom", "min_emission_rate"], - "properties": { - "denom": { - "description": "The incentive token denom that is whitelisted", - "type": "string" - }, - "min_emission_rate": { - "description": "The minimum emission rate per second for this incentive token", - "allOf": [ - { - "$ref": "#/definitions/Uint128" - } - ] - } - }, - "additionalProperties": false - } - } - }, - "query": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "QueryMsg", - "oneOf": [ - { - "description": "Query all active incentive emissions for a collateral denom", - "type": "object", - "required": ["active_emissions"], - "properties": { - "active_emissions": { - "type": "object", - "required": ["collateral_denom"], - "properties": { - "collateral_denom": { - "description": "The denom of the token that users supply as collateral to receive incentives", - "type": "string" - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false - }, - { - "description": "Query contract config", - "type": "object", - "required": ["config"], - "properties": { - "config": { - "type": "object", - "additionalProperties": false - } - }, - "additionalProperties": false - }, - { - "description": "Query info about the state of an incentive for a given collateral and incentive denom pair", - "type": "object", - "required": ["incentive_state"], - "properties": { - "incentive_state": { - "type": "object", - "required": ["collateral_denom", "incentive_denom"], - "properties": { - "collateral_denom": { - "description": "The denom of the token that users supply as collateral to receive incentives", - "type": "string" - }, - "incentive_denom": { - "description": "The denom of the token which is used to give incentives with", - "type": "string" - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false - }, - { - "description": "Enumerate incentive states with pagination", - "type": "object", - "required": ["incentive_states"], - "properties": { - "incentive_states": { - "type": "object", - "properties": { - "limit": { - "description": "The maximum number of results to return. If not set, 5 is used. If larger than 10, 10 is used.", - "type": ["integer", "null"], - "format": "uint32", - "minimum": 0.0 - }, - "start_after_collateral_denom": { - "description": "Start pagination after this collateral denom", - "type": ["string", "null"] - }, - "start_after_incentive_denom": { - "description": "Start pagination after this incentive denom. If supplied you must also supply start_after_collateral_denom.", - "type": ["string", "null"] - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false - }, - { - "description": "Queries the planned emission rate for a given collateral and incentive denom tuple at the specified unix timestamp. The emission rate returned is the amount of incentive tokens that will be emitted per second for each unit of collateral supplied during the epoch. NB: that the returned value can change if someone adds incentives to the contract.", - "type": "object", - "required": ["emission"], - "properties": { - "emission": { - "type": "object", - "required": ["collateral_denom", "incentive_denom", "timestamp"], - "properties": { - "collateral_denom": { - "description": "The denom of the token that users supply as collateral to receive incentives", - "type": "string" - }, - "incentive_denom": { - "description": "The denom of the token which is used to give incentives with", - "type": "string" - }, - "timestamp": { - "description": "The unix timestamp in second to query the emission rate at.", - "type": "integer", - "format": "uint64", - "minimum": 0.0 - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false - }, - { - "description": "Enumerate all incentive emission rates with pagination for a specified collateral and indentive denom pair", - "type": "object", - "required": ["emissions"], - "properties": { - "emissions": { - "type": "object", - "required": ["collateral_denom", "incentive_denom"], - "properties": { - "collateral_denom": { - "description": "The denom of the token that users supply as collateral to receive incentives", - "type": "string" - }, - "incentive_denom": { - "description": "The denom of the token which is used to give incentives with", - "type": "string" - }, - "limit": { - "description": "The maximum number of results to return. If not set, 5 is used. If larger than 10, 10 is used.", - "type": ["integer", "null"], - "format": "uint32", - "minimum": 0.0 - }, - "start_after_timestamp": { - "description": "Start pagination after this timestamp", - "type": ["integer", "null"], - "format": "uint64", - "minimum": 0.0 - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false - }, - { - "description": "Query user current unclaimed rewards", - "type": "object", - "required": ["user_unclaimed_rewards"], - "properties": { - "user_unclaimed_rewards": { - "type": "object", - "required": ["user"], - "properties": { - "limit": { - "description": "The maximum number of results to return. If not set, 5 is used. If larger than 10, 10 is used.", - "type": ["integer", "null"], - "format": "uint32", - "minimum": 0.0 - }, - "start_after_collateral_denom": { - "description": "Start pagination after this collateral denom", - "type": ["string", "null"] - }, - "start_after_incentive_denom": { - "description": "Start pagination after this incentive denom. If supplied you must also supply start_after_collateral_denom.", - "type": ["string", "null"] - }, - "user": { - "description": "The user address for which to query unclaimed rewards", - "type": "string" - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false - }, - { - "description": "Queries the incentive denom whitelist. Returns a Vec<(String, Uint128)> containing the denoms of all whitelisted incentive denoms, as well as the minimum emission rate for each.", - "type": "object", - "required": ["whitelist"], - "properties": { - "whitelist": { - "type": "object", - "additionalProperties": false - } - }, - "additionalProperties": false - } - ] - }, - "migrate": null, - "sudo": null, - "responses": { - "active_emissions": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "Array_of_ActiveEmission", - "type": "array", - "items": { - "$ref": "#/definitions/ActiveEmission" - }, - "definitions": { - "ActiveEmission": { - "description": "The currently active emission for a given incentive denom", - "type": "object", - "required": ["denom", "emission_rate"], - "properties": { - "denom": { - "description": "The denom for which incentives are being distributed", - "type": "string" - }, - "emission_rate": { - "description": "The amount of incentive tokens that are being emitted per second", - "allOf": [ - { - "$ref": "#/definitions/Uint128" - } - ] - } - }, - "additionalProperties": false - }, - "Uint128": { - "description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```", - "type": "string" - } - } - }, - "config": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "ConfigResponse", - "type": "object", - "required": [ - "address_provider", - "epoch_duration", - "max_whitelisted_denoms" - ], - "properties": { - "address_provider": { - "description": "Address provider", - "allOf": [ - { - "$ref": "#/definitions/Addr" - } - ] - }, - "epoch_duration": { - "description": "The epoch duration in seconds", - "type": "integer", - "format": "uint64", - "minimum": 0.0 - }, - "max_whitelisted_denoms": { - "description": "The maximum number of incentive denoms that can be whitelisted at any given time. This is a guard against accidentally whitelisting too many denoms, which could cause max gas errors.", - "type": "integer", - "format": "uint8", - "minimum": 0.0 - }, - "owner": { - "description": "The contract's owner", - "type": ["string", "null"] - }, - "proposed_new_owner": { - "description": "The contract's proposed owner", - "type": ["string", "null"] - } - }, - "additionalProperties": false, - "definitions": { - "Addr": { - "description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.", - "type": "string" - } - } - }, - "emission": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "Uint128", - "description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```", - "type": "string" - }, - "emissions": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "Array_of_EmissionResponse", - "type": "array", - "items": { - "$ref": "#/definitions/EmissionResponse" - }, - "definitions": { - "EmissionResponse": { - "type": "object", - "required": ["emission_rate", "epoch_start"], - "properties": { - "emission_rate": { - "description": "The emission rate returned is the amount of incentive tokens that will be emitted per second for each unit of collateral supplied during the epoch.", - "allOf": [ - { - "$ref": "#/definitions/Uint128" - } - ] - }, - "epoch_start": { - "description": "The unix timestamp in seconds at which the emission epoch starts", - "type": "integer", - "format": "uint64", - "minimum": 0.0 - } - }, - "additionalProperties": false - }, - "Uint128": { - "description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```", - "type": "string" - } - } - }, - "incentive_state": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "IncentiveStateResponse", - "description": "Incentive Metadata for a given incentive denom", - "type": "object", - "required": [ - "collateral_denom", - "incentive_denom", - "index", - "last_updated" - ], - "properties": { - "collateral_denom": { - "description": "The denom for which users get the incentive if they provide collateral in the Red Bank", - "type": "string" - }, - "incentive_denom": { - "description": "The denom of the token these incentives are paid with", - "type": "string" - }, - "index": { - "description": "An index that represents how many incentive tokens have been distributed per unit of collateral", - "allOf": [ - { - "$ref": "#/definitions/Decimal" - } - ] - }, - "last_updated": { - "description": "Last time (in seconds) index was updated", - "type": "integer", - "format": "uint64", - "minimum": 0.0 - } - }, - "additionalProperties": false, - "definitions": { - "Decimal": { - "description": "A fixed-point decimal value with 18 fractional digits, i.e. Decimal(1_000_000_000_000_000_000) == 1.0\n\nThe greatest possible value that can be represented is 340282366920938463463.374607431768211455 (which is (2^128 - 1) / 10^18)", - "type": "string" - } - } - }, - "incentive_states": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "Array_of_IncentiveStateResponse", - "type": "array", - "items": { - "$ref": "#/definitions/IncentiveStateResponse" - }, - "definitions": { - "Decimal": { - "description": "A fixed-point decimal value with 18 fractional digits, i.e. Decimal(1_000_000_000_000_000_000) == 1.0\n\nThe greatest possible value that can be represented is 340282366920938463463.374607431768211455 (which is (2^128 - 1) / 10^18)", - "type": "string" - }, - "IncentiveStateResponse": { - "description": "Incentive Metadata for a given incentive denom", - "type": "object", - "required": [ - "collateral_denom", - "incentive_denom", - "index", - "last_updated" - ], - "properties": { - "collateral_denom": { - "description": "The denom for which users get the incentive if they provide collateral in the Red Bank", - "type": "string" - }, - "incentive_denom": { - "description": "The denom of the token these incentives are paid with", - "type": "string" - }, - "index": { - "description": "An index that represents how many incentive tokens have been distributed per unit of collateral", - "allOf": [ - { - "$ref": "#/definitions/Decimal" - } - ] - }, - "last_updated": { - "description": "Last time (in seconds) index was updated", - "type": "integer", - "format": "uint64", - "minimum": 0.0 - } - }, - "additionalProperties": false - } - } - }, - "user_unclaimed_rewards": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "Array_of_Coin", - "type": "array", - "items": { - "$ref": "#/definitions/Coin" - }, - "definitions": { - "Coin": { - "type": "object", - "required": ["amount", "denom"], - "properties": { - "amount": { - "$ref": "#/definitions/Uint128" - }, - "denom": { - "type": "string" - } - } - }, - "Uint128": { - "description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```", - "type": "string" - } - } - }, - "whitelist": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "Array_of_WhitelistEntry", - "type": "array", - "items": { - "$ref": "#/definitions/WhitelistEntry" - }, - "definitions": { - "Uint128": { - "description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```", - "type": "string" - }, - "WhitelistEntry": { - "type": "object", - "required": ["denom", "min_emission_rate"], - "properties": { - "denom": { - "description": "The incentive token denom that is whitelisted", - "type": "string" - }, - "min_emission_rate": { - "description": "The minimum emission rate per second for this incentive token", - "allOf": [ - { - "$ref": "#/definitions/Uint128" - } - ] - } - }, - "additionalProperties": false - } - } - } - } -} diff --git a/src/lib/components/json-schema/form/fields/MultiSchemaField.tsx b/src/lib/components/json-schema/form/fields/MultiSchemaField.tsx index 97b5370d9..2d62d2514 100644 --- a/src/lib/components/json-schema/form/fields/MultiSchemaField.tsx +++ b/src/lib/components/json-schema/form/fields/MultiSchemaField.tsx @@ -12,6 +12,7 @@ import isEmpty from "lodash/isEmpty"; import omit from "lodash/omit"; import unset from "lodash/unset"; import { Component } from "react"; +import { getMatchingOptionFixed } from "../utils"; /** Type used for the state of the `AnyOfField` component */ type AnyOfFieldState = { @@ -91,11 +92,16 @@ class MultiSchemaField extends Component< options: RJSFSchema[] ) { const { - registry: { schemaUtils }, + registry: { schemaUtils, rootSchema }, } = this.props; - const option = schemaUtils.getMatchingOption(formData, options); - if (option !== 0) { + const option = getMatchingOptionFixed( + schemaUtils.getValidator(), + formData, + options, + rootSchema + ); + if (option !== -1) { return option; } // If the form data matches none of the options, use the currently selected diff --git a/src/lib/components/json-schema/form/index.tsx b/src/lib/components/json-schema/form/index.tsx index 7ddd4eed2..4f9a6e435 100644 --- a/src/lib/components/json-schema/form/index.tsx +++ b/src/lib/components/json-schema/form/index.tsx @@ -1,15 +1,9 @@ -/* eslint-disable */ -import { - Accordion, - AccordionButton, - AccordionIcon, - AccordionItem, - AccordionPanel, - Box, - Heading, - Text, - useToast, -} from "@chakra-ui/react"; +/* eslint-disable react-hooks/exhaustive-deps */ +/* eslint-disable sonarjs/cognitive-complexity */ +/* eslint-disable no-param-reassign */ +/* eslint-disable no-continue */ +/* eslint-disable no-console */ +/* eslint-disable no-restricted-syntax */ import { Form, Templates as DefaultTemplates, @@ -17,20 +11,22 @@ import { } from "@rjsf/chakra-ui"; import type { FormProps } from "@rjsf/core"; import type { RJSFSchema } from "@rjsf/utils"; -import { createSchemaUtils, type GenericObjectType } from "@rjsf/utils"; -import v8Validator from "@rjsf/validator-ajv8"; +import { createSchemaUtils } from "@rjsf/utils"; +import { customizeValidator } from "@rjsf/validator-ajv8"; import isEqual from "lodash/isEqual"; -import { FC, useEffect } from "react"; -import { useCallback, useMemo, useState } from "react"; - -import JsonReadOnly from "../../json/JsonReadOnly"; -import { jsonPrettify } from "lib/utils"; +import type { FC } from "react"; +import { useEffect, useCallback, useMemo, useState } from "react"; -import contractSchema from "./contract_schema.json"; import { Fields } from "./fields"; import { Templates } from "./templates"; import { Widgets } from "./widgets"; +// NOTE: Set `validateFormats` to false, since some custom format +// e.g. `uint32` causing an unexpected behavior +const v8Validator = customizeValidator({ + ajvOptionsOverrides: { validateFormats: false }, +}); + function deleteExtraneousOneOfKeys(value: Record) { const actualOneOfOptions = Object.keys(value); @@ -54,8 +50,6 @@ function fixOneOfKeys( formData: Record, collapsedSchema: RJSFSchema ) { - // console.log(collapsedSchema); - // if the entry is supposed to be a oneof *itself*, then check that it only has one key if (collapsedSchema.oneOf) { deleteExtraneousOneOfKeys(formData); @@ -161,123 +155,44 @@ export const JsonSchemaForm: FC = ({ ); return ( - - { - // log.info(values) - onChange?.(values); - }} - onSubmit={({ formData: values }) => { - // log.info(values) - onSubmit(values); - }} - onError={() => console.error("errors")} - /> - - ); -}; - -export const DummyJsonSchema = () => { - // TODO: remove mock data - const toast = useToast({ containerStyle: { width: "fit-content" } }); - const { oneOf: msgs, definitions } = contractSchema.execute; - - // const schema = contractSchema.execute as GenericObjectType; - - return ( - - {msgs.map((msg, index) => ( - -

- - - - {msg.required[0]} - - - {msg.description} - - - - -

- - - toast({ - title: "Form Data", - description: ( - - - - ), - status: "success", - isClosable: true, - }) - } - onChange={(data) => console.log("data", data)} - /> - -
- ))} -
- // - // toast({ - // title: "Form Data", - // description: ( - // - // - // - // ), - // status: "success", - // isClosable: true, - // }) - // } - // onChange={(data) => { - // console.log("data", data); - // }} - // /> + { + // log.info(formData) + onChange?.(values); + }} + onSubmit={({ formData: values }) => { + // log.info(values) + onSubmit(values); + }} + onError={() => console.error("errors")} + /> ); }; diff --git a/src/lib/components/json-schema/form/templates/ArrayFieldItemTemplate.tsx b/src/lib/components/json-schema/form/templates/ArrayFieldItemTemplate.tsx index c5a52065f..e0fee96a9 100644 --- a/src/lib/components/json-schema/form/templates/ArrayFieldItemTemplate.tsx +++ b/src/lib/components/json-schema/form/templates/ArrayFieldItemTemplate.tsx @@ -42,16 +42,14 @@ export default function ArrayFieldItemTemplate( div > div > div": { gap: "4px" } }} + border="1px solid var(--chakra-colors-gray-600)" + borderRadius="8px" + p={4} + sx={{ "> div > div > div": { gap: 2 } }} > {children} - {hasToolbar && ( + {hasToolbar && !readonly && ( {(hasMoveUp || hasMoveDown) && ( ( uiSchema={uiSchema} registry={registry} /> - - {items.length > 0 && - items.map( + {readonly && items.length === 0 ? ( + + Empty + + ) : ( + + {items.map( ({ key, ...itemProps }: ArrayFieldTemplateItemType) => ( ) )} - {canAdd && ( - - - - )} - + {canAdd && !readonly && ( + + + + )} + + )} ); } diff --git a/src/lib/components/json-schema/form/templates/BaseInputTemplate.tsx b/src/lib/components/json-schema/form/templates/BaseInputTemplate.tsx index 7703748a1..70baa2c69 100644 --- a/src/lib/components/json-schema/form/templates/BaseInputTemplate.tsx +++ b/src/lib/components/json-schema/form/templates/BaseInputTemplate.tsx @@ -1,3 +1,4 @@ +/* eslint-disable sonarjs/cognitive-complexity */ /* eslint-disable react/destructuring-assignment */ /* eslint-disable @typescript-eslint/no-explicit-any */ import { @@ -116,7 +117,7 @@ const BaseInputTemplate = (props: WidgetProps) => { return ( 0} > @@ -128,10 +129,13 @@ const BaseInputTemplate = (props: WidgetProps) => { fontSize="12px" fontWeight={700} marginInlineEnd={1} + _disabled={{ + color: "text.main", + }} > {label} - + )} @@ -151,6 +155,16 @@ const BaseInputTemplate = (props: WidgetProps) => { } {...inputProps} list={schema.examples ? `examples_${id}` : undefined} + _disabled={{ + color: "text.main", + cursor: "not-allowed", + _hover: { + borderColor: "gray.700", + }, + _active: { + border: "1px solid var(--chakra-colors-gray-700)", + }, + }} /> {rightAddon && {rightAddon}} diff --git a/src/lib/components/json-schema/form/templates/FieldTemplate.tsx b/src/lib/components/json-schema/form/templates/FieldTemplate.tsx index efb16a438..9b1d943a9 100644 --- a/src/lib/components/json-schema/form/templates/FieldTemplate.tsx +++ b/src/lib/components/json-schema/form/templates/FieldTemplate.tsx @@ -50,7 +50,7 @@ export default function FieldTemplate( registry={registry} > 0} > {children} diff --git a/src/lib/components/json-schema/form/templates/FieldTypeTag.tsx b/src/lib/components/json-schema/form/templates/FieldTypeTag.tsx index 2cee22401..56f61b03a 100644 --- a/src/lib/components/json-schema/form/templates/FieldTypeTag.tsx +++ b/src/lib/components/json-schema/form/templates/FieldTypeTag.tsx @@ -1,15 +1,20 @@ import { Flex, Tag } from "@chakra-ui/react"; import type { RJSFSchema } from "@rjsf/utils"; -export const FieldTypeTag = ({ type }: Pick) => { +export const FieldTypeTag = ({ + type, + format, +}: Pick) => { if (!type) return null; if (Array.isArray(type)) { const types: string[] = type; return ( {types.map((value) => ( + // NOTE: Assuming there is only one Nonnullable type, + // since `format` is of type string - {value} + {value !== "null" ? format ?? value : value} ))} @@ -17,7 +22,7 @@ export const FieldTypeTag = ({ type }: Pick) => { } return ( - {type} + {format ?? type} ); }; diff --git a/src/lib/components/json-schema/form/templates/ObjectFieldTemplate.tsx b/src/lib/components/json-schema/form/templates/ObjectFieldTemplate.tsx index f41476afa..e94ed1b31 100644 --- a/src/lib/components/json-schema/form/templates/ObjectFieldTemplate.tsx +++ b/src/lib/components/json-schema/form/templates/ObjectFieldTemplate.tsx @@ -1,9 +1,6 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import { Grid, GridItem } from "@chakra-ui/react"; -import type { - ObjectFieldTemplatePropertyType, - ObjectFieldTemplateProps, -} from "@rjsf/utils"; +import type { ObjectFieldTemplateProps } from "@rjsf/utils"; import { canExpand, getSchemaType, @@ -11,11 +8,6 @@ import { getUiOptions, } from "@rjsf/utils"; -interface ObjectFieldTemplatePropertyTypeWithRequired - extends ObjectFieldTemplatePropertyType { - required?: boolean; -} - const ObjectFieldTemplate = ( props: ObjectFieldTemplateProps ) => { @@ -55,10 +47,10 @@ const ObjectFieldTemplate = ( {properties.map((element, index) => { // NOTE: required array field doesn't create an empty array as a default const elementType = getSchemaType(element.content.props.schema); - const elementRequired = ( - element as ObjectFieldTemplatePropertyTypeWithRequired - ).required; + const elementRequired = + (element.content.props.required as boolean) ?? false; if ( + formData && typeof elementType === "string" && elementType === "array" && elementRequired && diff --git a/src/lib/components/json-schema/form/utils.ts b/src/lib/components/json-schema/form/utils.ts index 60de3f6a7..6079e4bd2 100644 --- a/src/lib/components/json-schema/form/utils.ts +++ b/src/lib/components/json-schema/form/utils.ts @@ -1,7 +1,11 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import type { EnumOptionsType } from "@rjsf/utils"; +import type { EnumOptionsType, RJSFSchema, ValidatorType } from "@rjsf/utils"; import isEqual from "lodash/isEqual"; +export function getIsResponse(formContext: any) { + return (formContext?.isResponse as boolean) ?? false; +} + /** Determines whether the given `value` is (one of) the `selected` value(s). * * @param value - The value being checked to see if it is selected @@ -56,7 +60,7 @@ export function enumOptionsIndexForValue( * @returns - The single or list of values specified by the single or list of indexes if they are valid. Otherwise, * `emptyValue` or an empty list. */ -export default function enumOptionsValueForIndex( +export function enumOptionsValueForIndex( valueIndex: string | number | Array, allEnumOptions: EnumOptionsType[] = [], emptyValue?: EnumOptionsType["value"] @@ -72,3 +76,69 @@ export default function enumOptionsValueForIndex( const option = allEnumOptions[index]; return option ? option.value : emptyValue; } + +/** Given the `formData` and list of `options`, attempts to find the index of the option that best matches the data. + * + * @param validator - An implementation of the `ValidatorType` interface that will be used when necessary + * @param formData - The current formData, if any, used to figure out a match + * @param options - The list of options to find a matching options from + * @param rootSchema - The root schema, used to primarily to look up `$ref`s + * @returns - The index of the matched option or 0 if none is available + */ +export function getMatchingOptionFixed( + validator: ValidatorType, + formData: T | undefined, + options: RJSFSchema[], + rootSchema: RJSFSchema +): number { + // For performance, skip validating subschemas if formData is undefined. We just + // want to get the first option in that case. + if (formData === undefined) { + return -1; + } + return options.findIndex((option) => { + // If the schema describes an object then we need to add slightly more + // strict matching to the schema, because unless the schema uses the + // "requires" keyword, an object will match the schema as long as it + // doesn't have matching keys with a conflicting type. To do this we use an + // "anyOf" with an array of requires. This augmentation expresses that the + // schema should match if any of the keys in the schema are present on the + // object and pass validation. + if (option.properties) { + // Create an "anyOf" schema that requires at least one of the keys in the + // "properties" object + const requiresAnyOf = { + anyOf: Object.keys(option.properties).map((key) => ({ + required: [key], + })), + }; + + let augmentedSchema; + // If the "anyOf" keyword already exists, wrap the augmentation in an "allOf" + if (option.anyOf) { + // Create a shallow clone of the option + const { ...shallowClone } = option; + + if (!shallowClone.allOf) { + shallowClone.allOf = []; + } else { + // If "allOf" already exists, shallow clone the array + shallowClone.allOf = shallowClone.allOf.slice(); + } + + shallowClone.allOf.push(requiresAnyOf); + + augmentedSchema = shallowClone; + } else { + augmentedSchema = { ...option, ...requiresAnyOf }; + } + + // Remove the "required" field as it's likely that not all fields have + // been filled in yet, which will mean that the schema is not valid + delete augmentedSchema.required; + + return validator.isValid(augmentedSchema, formData, rootSchema); + } + return validator.isValid(option, formData, rootSchema); + }); +} diff --git a/src/lib/components/json-schema/form/widgets/SelectWidget.tsx b/src/lib/components/json-schema/form/widgets/SelectWidget.tsx index 5246b729e..6ca025ee3 100644 --- a/src/lib/components/json-schema/form/widgets/SelectWidget.tsx +++ b/src/lib/components/json-schema/form/widgets/SelectWidget.tsx @@ -6,7 +6,11 @@ import type { OptionsOrGroups } from "chakra-react-select"; import { Select } from "chakra-react-select"; import type React from "react"; -import enumOptionsValueForIndex, { enumOptionsIndexForValue } from "../utils"; +import { + enumOptionsIndexForValue, + enumOptionsValueForIndex, + getIsResponse, +} from "../utils"; /** * chakra-react-select option base. @@ -47,10 +51,13 @@ const SelectWidget = (props: WidgetProps) => { rawErrors = [], uiSchema, registry, + formContext, } = props; - const uiOptions = getUiOptions(uiSchema); + const uiOptions = getUiOptions(uiSchema); const { enumOptions, enumDisabled, emptyValue } = options; + const isReadonly = readonly || getIsResponse(formContext); + const DescriptionFieldTemplate = getTemplate<"DescriptionFieldTemplate", T>( "DescriptionFieldTemplate", registry, @@ -119,9 +126,9 @@ const SelectWidget = (props: WidgetProps) => { return ( 0} sx={{ "& > p": { mt: 4, mb: 2 } }} > @@ -146,6 +153,10 @@ const SelectWidget = (props: WidgetProps) => { value={formValue} menuPosition="fixed" chakraStyles={{ + control: (provided) => ({ + ...provided, + _disabled: { color: "text.main" }, + }), option: (provided, state) => ({ ...provided, bg: state.isSelected ? "gray.800" : undefined, diff --git a/src/lib/pages/query/components/SchemaQuery.tsx b/src/lib/pages/query/components/SchemaQuery.tsx index 21e91b1ab..dc63b848b 100644 --- a/src/lib/pages/query/components/SchemaQuery.tsx +++ b/src/lib/pages/query/components/SchemaQuery.tsx @@ -117,9 +117,9 @@ const QueryComponent = ({ }, [msgSchema.inputRequired, refetch]); return ( - +
- + {msgSchema.title} @@ -129,7 +129,7 @@ const QueryComponent = ({
- + {!msgSchema.inputRequired && ( From 77084185252b0e08127472469bbd40c011871389 Mon Sep 17 00:00:00 2001 From: songwongtp <16089160+songwongtp@users.noreply.github.com> Date: Tue, 22 Aug 2023 02:43:01 +0700 Subject: [PATCH 41/94] fix: boolean logic --- .../components/json-schema/form/templates/BaseInputTemplate.tsx | 2 +- src/lib/components/json-schema/form/widgets/SelectWidget.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/components/json-schema/form/templates/BaseInputTemplate.tsx b/src/lib/components/json-schema/form/templates/BaseInputTemplate.tsx index 70baa2c69..1781cb404 100644 --- a/src/lib/components/json-schema/form/templates/BaseInputTemplate.tsx +++ b/src/lib/components/json-schema/form/templates/BaseInputTemplate.tsx @@ -117,7 +117,7 @@ const BaseInputTemplate = (props: WidgetProps) => { return ( 0} > diff --git a/src/lib/components/json-schema/form/widgets/SelectWidget.tsx b/src/lib/components/json-schema/form/widgets/SelectWidget.tsx index 6ca025ee3..694287955 100644 --- a/src/lib/components/json-schema/form/widgets/SelectWidget.tsx +++ b/src/lib/components/json-schema/form/widgets/SelectWidget.tsx @@ -127,7 +127,7 @@ const SelectWidget = (props: WidgetProps) => { 0} sx={{ "& > p": { mt: 4, mb: 2 } }} From db6c83a9b259bd753fa72f24422add56e5909c93 Mon Sep 17 00:00:00 2001 From: songwongtp <16089160+songwongtp@users.noreply.github.com> Date: Tue, 22 Aug 2023 02:49:04 +0700 Subject: [PATCH 42/94] fix: panel padding --- src/lib/pages/query/components/SchemaQuery.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/pages/query/components/SchemaQuery.tsx b/src/lib/pages/query/components/SchemaQuery.tsx index dc63b848b..439ce2d90 100644 --- a/src/lib/pages/query/components/SchemaQuery.tsx +++ b/src/lib/pages/query/components/SchemaQuery.tsx @@ -129,7 +129,7 @@ const QueryComponent = ({
- + Date: Tue, 22 Aug 2023 10:19:51 +0700 Subject: [PATCH 43/94] fix: comment out placeholder logic --- .../form/templates/ArrayFieldItemTemplate.tsx | 1 - .../form/templates/BaseInputTemplate.tsx | 62 +++++++++---------- .../form/templates/FieldTemplate.tsx | 2 +- 3 files changed, 32 insertions(+), 33 deletions(-) diff --git a/src/lib/components/json-schema/form/templates/ArrayFieldItemTemplate.tsx b/src/lib/components/json-schema/form/templates/ArrayFieldItemTemplate.tsx index e0fee96a9..d693b9c06 100644 --- a/src/lib/components/json-schema/form/templates/ArrayFieldItemTemplate.tsx +++ b/src/lib/components/json-schema/form/templates/ArrayFieldItemTemplate.tsx @@ -45,7 +45,6 @@ export default function ArrayFieldItemTemplate( border="1px solid var(--chakra-colors-gray-600)" borderRadius="8px" p={4} - sx={{ "> div > div > div": { gap: 2 } }} > {children}
diff --git a/src/lib/components/json-schema/form/templates/BaseInputTemplate.tsx b/src/lib/components/json-schema/form/templates/BaseInputTemplate.tsx index 1781cb404..621598131 100644 --- a/src/lib/components/json-schema/form/templates/BaseInputTemplate.tsx +++ b/src/lib/components/json-schema/form/templates/BaseInputTemplate.tsx @@ -19,18 +19,18 @@ import type { ChangeEvent, FocusEvent } from "react"; import { FieldTypeTag } from "./FieldTypeTag"; -const PLACEHOLDERS = { - addr: "cosmos1...", - code_id: "1", - contract: "cosmos1...", -}; +// const PLACEHOLDERS = { +// addr: "cosmos1...", +// code_id: "1", +// contract: "cosmos1...", +// }; const renderRightAddOn = ( value: WidgetProps["value"], - label: WidgetProps["label"], + // label: WidgetProps["label"], schema: WidgetProps["schema"], - onChange: WidgetProps["onChange"], - formContext: WidgetProps["formContext"] + onChange: WidgetProps["onChange"] + // formContext: WidgetProps["formContext"] ) => { // console.log(formContext, "formContext"); if (schema.description?.includes("Binary is a wrapper around Vec")) { @@ -49,18 +49,18 @@ const renderRightAddOn = ( ); } - if ( - label.includes("addr") && - formContext && - typeof formContext === "object" && - "address" in formContext - ) { - return ( - - ); - } + // if ( + // label.includes("addr") && + // formContext && + // typeof formContext === "object" && + // "address" in formContext + // ) { + // return ( + // + // ); + // } return null; }; @@ -80,9 +80,9 @@ const BaseInputTemplate = (props: WidgetProps) => { readonly, rawErrors, autofocus, - placeholder, + // placeholder, disabled, - formContext, + // formContext, registry, } = props; const inputProps = getInputProps(schema, type, options); @@ -108,10 +108,10 @@ const BaseInputTemplate = (props: WidgetProps) => { const rightAddon = renderRightAddOn( value, - label, + // label, schema, - onChange, - formContext + onChange + // formContext ); return ( @@ -147,12 +147,12 @@ const BaseInputTemplate = (props: WidgetProps) => { onBlur={handleOnBlur} onFocus={handleOnFocus} autoFocus={autofocus} - placeholder={ - placeholder || - Object.entries(PLACEHOLDERS).find(([key]) => - label.includes(key) - )?.[1] - } + // placeholder={ + // placeholder || + // Object.entries(PLACEHOLDERS).find(([key]) => + // label.includes(key) + // )?.[1] + // } {...inputProps} list={schema.examples ? `examples_${id}` : undefined} _disabled={{ diff --git a/src/lib/components/json-schema/form/templates/FieldTemplate.tsx b/src/lib/components/json-schema/form/templates/FieldTemplate.tsx index 9b1d943a9..74bd6ef0a 100644 --- a/src/lib/components/json-schema/form/templates/FieldTemplate.tsx +++ b/src/lib/components/json-schema/form/templates/FieldTemplate.tsx @@ -50,7 +50,7 @@ export default function FieldTemplate( registry={registry} > 0} > {children} From dec5f34a0dd48091615443421563cb1b600f865b Mon Sep 17 00:00:00 2001 From: evilpeach Date: Tue, 22 Aug 2023 10:34:36 +0700 Subject: [PATCH 44/94] fix: add key in list StyledCustomTab --- .../code-details/components/json-schema/CodeSchemaSection.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/lib/pages/code-details/components/json-schema/CodeSchemaSection.tsx b/src/lib/pages/code-details/components/json-schema/CodeSchemaSection.tsx index 6784dc810..040d9b049 100644 --- a/src/lib/pages/code-details/components/json-schema/CodeSchemaSection.tsx +++ b/src/lib/pages/code-details/components/json-schema/CodeSchemaSection.tsx @@ -104,7 +104,9 @@ export const CodeSchemaSection = ({ Full Schema {SchemaMsgTabList.map((schemaProperty) => ( - {capitalize(schemaProperty)}Msg + + {capitalize(schemaProperty)}Msg + ))} From 961b13726a1e0ba20fc7a8e7c31d66f46f6d9eab Mon Sep 17 00:00:00 2001 From: songwongtp <16089160+songwongtp@users.noreply.github.com> Date: Tue, 22 Aug 2023 10:58:08 +0700 Subject: [PATCH 45/94] fix: response title --- .../pages/query/components/SchemaQuery.tsx | 34 +++++++++---------- 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/src/lib/pages/query/components/SchemaQuery.tsx b/src/lib/pages/query/components/SchemaQuery.tsx index 439ce2d90..c47b6ddc1 100644 --- a/src/lib/pages/query/components/SchemaQuery.tsx +++ b/src/lib/pages/query/components/SchemaQuery.tsx @@ -129,7 +129,7 @@ const QueryComponent = ({ - + )} - {msgSchema.inputRequired && ( - - - Return Output - - - Query response will display here - - - - )} + + + Return Output + + + Query response will display here + + + {queryError && ( From 8bdf12160b300a5f055101518a4be76ff34a9082 Mon Sep 17 00:00:00 2001 From: songwongtp <16089160+songwongtp@users.noreply.github.com> Date: Tue, 22 Aug 2023 11:49:41 +0700 Subject: [PATCH 46/94] fix: comment --- .../json-schema/form/fields/MultiSchemaField.tsx | 4 ++++ src/lib/components/json-schema/form/index.tsx | 4 ++-- src/lib/components/json-schema/form/utils.ts | 4 ---- .../json-schema/form/widgets/SelectWidget.tsx | 15 ++++----------- src/lib/pages/query/components/SchemaQuery.tsx | 3 --- 5 files changed, 10 insertions(+), 20 deletions(-) diff --git a/src/lib/components/json-schema/form/fields/MultiSchemaField.tsx b/src/lib/components/json-schema/form/fields/MultiSchemaField.tsx index 2d62d2514..001f5af47 100644 --- a/src/lib/components/json-schema/form/fields/MultiSchemaField.tsx +++ b/src/lib/components/json-schema/form/fields/MultiSchemaField.tsx @@ -183,6 +183,8 @@ class MultiSchemaField extends Component< registry, uiSchema, schema, + required, + readonly, } = this.props; const { widgets, fields, schemaUtils } = registry; @@ -252,6 +254,8 @@ class MultiSchemaField extends Component< schema.oneOf ? "__oneof_select" : "__anyof_select" }`} schema={{ type: "number", default: 0 }} + required={required} + readonly={readonly} onChange={this.onOptionChange} onBlur={onBlur} onFocus={onFocus} diff --git a/src/lib/components/json-schema/form/index.tsx b/src/lib/components/json-schema/form/index.tsx index 4f9a6e435..5f2ce9d2d 100644 --- a/src/lib/components/json-schema/form/index.tsx +++ b/src/lib/components/json-schema/form/index.tsx @@ -159,7 +159,7 @@ export const JsonSchemaForm: FC = ({ id={formId} formContext={formContext} formData={formData} - schema={collapsedSchema} + schema={schema} uiSchema={{ "ui:submitButtonOptions": { norender: true, @@ -185,7 +185,7 @@ export const JsonSchemaForm: FC = ({ }} validator={v8Validator} onChange={({ formData: values }) => { - // log.info(formData) + // log.info(values) onChange?.(values); }} onSubmit={({ formData: values }) => { diff --git a/src/lib/components/json-schema/form/utils.ts b/src/lib/components/json-schema/form/utils.ts index 6079e4bd2..5b5867425 100644 --- a/src/lib/components/json-schema/form/utils.ts +++ b/src/lib/components/json-schema/form/utils.ts @@ -2,10 +2,6 @@ import type { EnumOptionsType, RJSFSchema, ValidatorType } from "@rjsf/utils"; import isEqual from "lodash/isEqual"; -export function getIsResponse(formContext: any) { - return (formContext?.isResponse as boolean) ?? false; -} - /** Determines whether the given `value` is (one of) the `selected` value(s). * * @param value - The value being checked to see if it is selected diff --git a/src/lib/components/json-schema/form/widgets/SelectWidget.tsx b/src/lib/components/json-schema/form/widgets/SelectWidget.tsx index 694287955..9972957b1 100644 --- a/src/lib/components/json-schema/form/widgets/SelectWidget.tsx +++ b/src/lib/components/json-schema/form/widgets/SelectWidget.tsx @@ -6,11 +6,7 @@ import type { OptionsOrGroups } from "chakra-react-select"; import { Select } from "chakra-react-select"; import type React from "react"; -import { - enumOptionsIndexForValue, - enumOptionsValueForIndex, - getIsResponse, -} from "../utils"; +import { enumOptionsIndexForValue, enumOptionsValueForIndex } from "../utils"; /** * chakra-react-select option base. @@ -51,13 +47,10 @@ const SelectWidget = (props: WidgetProps) => { rawErrors = [], uiSchema, registry, - formContext, } = props; const uiOptions = getUiOptions(uiSchema); const { enumOptions, enumDisabled, emptyValue } = options; - const isReadonly = readonly || getIsResponse(formContext); - const DescriptionFieldTemplate = getTemplate<"DescriptionFieldTemplate", T>( "DescriptionFieldTemplate", registry, @@ -126,9 +119,9 @@ const SelectWidget = (props: WidgetProps) => { return ( 0} sx={{ "& > p": { mt: 4, mb: 2 } }} > diff --git a/src/lib/pages/query/components/SchemaQuery.tsx b/src/lib/pages/query/components/SchemaQuery.tsx index c47b6ddc1..ec975757d 100644 --- a/src/lib/pages/query/components/SchemaQuery.tsx +++ b/src/lib/pages/query/components/SchemaQuery.tsx @@ -200,9 +200,6 @@ const QueryComponent = ({ return {}; } })()} - formContext={{ - isResponse: true, - }} /> {!msgSchema.inputRequired && ( From 82eb1b169ce5d45b066b8eb03325b8400bb33602 Mon Sep 17 00:00:00 2001 From: songwongtp <16089160+songwongtp@users.noreply.github.com> Date: Tue, 22 Aug 2023 12:10:33 +0700 Subject: [PATCH 47/94] fix: comment out rightaddon --- .../form/templates/BaseInputTemplate.tsx | 97 +++++++++---------- 1 file changed, 47 insertions(+), 50 deletions(-) diff --git a/src/lib/components/json-schema/form/templates/BaseInputTemplate.tsx b/src/lib/components/json-schema/form/templates/BaseInputTemplate.tsx index 621598131..04fed4510 100644 --- a/src/lib/components/json-schema/form/templates/BaseInputTemplate.tsx +++ b/src/lib/components/json-schema/form/templates/BaseInputTemplate.tsx @@ -3,16 +3,13 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import { Box, - Button, Flex, FormControl, FormLabel, - HStack, Input, InputGroup, - InputRightAddon, } from "@chakra-ui/react"; -import { fromBase64, fromUtf8, toBase64, toUtf8 } from "@cosmjs/encoding"; +// import { fromBase64, fromUtf8, toBase64, toUtf8 } from "@cosmjs/encoding"; import type { WidgetProps } from "@rjsf/utils"; import { getInputProps, getTemplate, getUiOptions } from "@rjsf/utils"; import type { ChangeEvent, FocusEvent } from "react"; @@ -25,44 +22,44 @@ import { FieldTypeTag } from "./FieldTypeTag"; // contract: "cosmos1...", // }; -const renderRightAddOn = ( - value: WidgetProps["value"], - // label: WidgetProps["label"], - schema: WidgetProps["schema"], - onChange: WidgetProps["onChange"] - // formContext: WidgetProps["formContext"] -) => { - // console.log(formContext, "formContext"); - if (schema.description?.includes("Binary is a wrapper around Vec")) { - return ( - - - - - ); - } - // if ( - // label.includes("addr") && - // formContext && - // typeof formContext === "object" && - // "address" in formContext - // ) { - // return ( - // - // ); - // } - return null; -}; +// const renderRightAddOn = ( +// value: WidgetProps["value"], +// label: WidgetProps["label"], +// schema: WidgetProps["schema"], +// onChange: WidgetProps["onChange"], +// formContext: WidgetProps["formContext"] +// ) => { +// // console.log(formContext, "formContext"); +// if (schema.description?.includes("Binary is a wrapper around Vec")) { +// return ( +// +// +// +// +// ); +// } +// if ( +// label.includes("addr") && +// formContext && +// typeof formContext === "object" && +// "address" in formContext +// ) { +// return ( +// +// ); +// } +// return null; +// }; const BaseInputTemplate = (props: WidgetProps) => { const { @@ -106,13 +103,13 @@ const BaseInputTemplate = (props: WidgetProps) => { const handleOnFocus = ({ target }: FocusEvent) => onFocus(id, target.value); - const rightAddon = renderRightAddOn( - value, - // label, - schema, - onChange - // formContext - ); + // const rightAddon = renderRightAddOn( + // value, + // label, + // schema, + // onChange, + // formContext + // ); return ( (props: WidgetProps) => { }, }} /> - {rightAddon && {rightAddon}} + {/* {rightAddon && {rightAddon}} */} {Array.isArray(schema.examples) ? ( From 9ed0398263b7d47b361186558721e10f080c47e6 Mon Sep 17 00:00:00 2001 From: poomthiti Date: Tue, 22 Aug 2023 14:27:35 +0700 Subject: [PATCH 48/94] fix: improve scrolling into view by delaying scroll function --- CHANGELOG.md | 1 + src/lib/pages/query/components/SchemaQuery.tsx | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7bf10baea..01b56dcdc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -57,6 +57,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Improvements +- [#491](https://github.com/alleslabs/celatone-frontend/pull/491) Improve scrolling into view by delaying scroll function - [#489](https://github.com/alleslabs/celatone-frontend/pull/489) Improve jsonschema query response UI and fix jsonschema incorrect oneOf behavior - [#457](https://github.com/alleslabs/celatone-frontend/pull/457) Add alert for proposal forum review - [#389](https://github.com/alleslabs/celatone-frontend/pull/389) Fix modal consistency diff --git a/src/lib/pages/query/components/SchemaQuery.tsx b/src/lib/pages/query/components/SchemaQuery.tsx index 992ec167b..3642f9a51 100644 --- a/src/lib/pages/query/components/SchemaQuery.tsx +++ b/src/lib/pages/query/components/SchemaQuery.tsx @@ -295,11 +295,14 @@ export const SchemaQuery = ({ const el = document.querySelector( `.msg-${schema[msgIndex][0].schema.required?.[0]}` ); - el?.scrollIntoView(); + // TODO: This is a workaround, refactor to a proper solution later + const timeoutId = setTimeout(() => el?.scrollIntoView(), 200); + return () => clearInterval(timeoutId); } catch (_) { // } } + return () => {}; // eslint-disable-next-line react-hooks/exhaustive-deps }, [schema, initialMsg, accordionRef.current]); From 878f2c85eff9317ea62c09cc44967456c86261f5 Mon Sep 17 00:00:00 2001 From: evilpeach Date: Fri, 18 Aug 2023 17:49:47 +0700 Subject: [PATCH 49/94] feat: json schema execute --- .../pages/execute/components/ExecuteArea.tsx | 333 +++--------------- .../pages/execute/components/JsonExecute.tsx | 301 ++++++++++++++++ .../execute/components/MsgSuggestion.tsx | 57 +++ .../components/schema-execute/ExecuteBox.tsx | 295 ++++++++++++++++ .../components/schema-execute/index.tsx | 88 +++++ src/lib/pages/execute/index.tsx | 44 ++- src/lib/pages/query/components/QueryArea.tsx | 2 +- .../pages/query/components/SchemaQuery.tsx | 5 +- src/lib/stores/schema.ts | 4 +- 9 files changed, 836 insertions(+), 293 deletions(-) create mode 100644 src/lib/pages/execute/components/JsonExecute.tsx create mode 100644 src/lib/pages/execute/components/MsgSuggestion.tsx create mode 100644 src/lib/pages/execute/components/schema-execute/ExecuteBox.tsx create mode 100644 src/lib/pages/execute/components/schema-execute/index.tsx diff --git a/src/lib/pages/execute/components/ExecuteArea.tsx b/src/lib/pages/execute/components/ExecuteArea.tsx index 1b7919390..115c5aa48 100644 --- a/src/lib/pages/execute/components/ExecuteArea.tsx +++ b/src/lib/pages/execute/components/ExecuteArea.tsx @@ -1,304 +1,81 @@ -import { Box, Flex, Button, ButtonGroup, Text } from "@chakra-ui/react"; -import type { Coin, StdFee } from "@cosmjs/stargate"; -import dynamic from "next/dynamic"; -import { useCallback, useEffect, useMemo, useState } from "react"; -import { useForm, useFormState } from "react-hook-form"; +import { Box, Flex, Heading } from "@chakra-ui/react"; +import type { Coin } from "@cosmjs/stargate"; +import { useState, useEffect } from "react"; import { - useFabricateFee, - useExecuteContractTx, - useCurrentChain, - useMobile, -} from "lib/app-provider"; -import { useAttachFunds } from "lib/app-provider/hooks/useAttachFunds"; -import { useSimulateFeeQuery } from "lib/app-provider/queries"; -import { ContractCmdButton } from "lib/components/ContractCmdButton"; -import { CopyButton } from "lib/components/copy"; -import { ErrorMessageRender } from "lib/components/ErrorMessageRender"; -import { EstimatedFeeRender } from "lib/components/EstimatedFeeRender"; -import { AttachFund } from "lib/components/fund"; -import { - ASSETS_JSON_STR, - ATTACH_FUNDS_OPTION, - defaultAsset, - defaultAssetJsonStr, -} from "lib/components/fund/data"; -import type { AttachFundsState } from "lib/components/fund/types"; -import { AttachFundsType } from "lib/components/fund/types"; -import { CustomIcon } from "lib/components/icon"; -import JsonInput from "lib/components/json/JsonInput"; -import { useContractStore } from "lib/providers/store"; -import { useTxBroadcast } from "lib/providers/tx-broadcast"; -import { AmpEvent, AmpTrack, AmpTrackAction } from "lib/services/amplitude"; -import type { Activity } from "lib/stores/contract"; -import type { ComposedMsg, ContractAddr, HumanAddr } from "lib/types"; -import { MsgType } from "lib/types"; -import { composeMsg, jsonPrettify, jsonValidate } from "lib/utils"; + MessageInputContent, + MessageInputSwitch, + MessageTabs, +} from "lib/components/json-schema"; +import { EmptyState } from "lib/components/state"; +import type { ExecuteSchema } from "lib/stores/schema"; +import type { ContractAddr, Option } from "lib/types"; -const CodeSnippet = dynamic(() => import("lib/components/modal/CodeSnippet"), { - ssr: false, -}); +import { JsonExecute } from "./JsonExecute"; +import { SchemaExecute } from "./schema-execute"; interface ExecuteAreaProps { contractAddress: ContractAddr; initialMsg: string; initialFunds: Coin[]; - cmds: [string, string][]; + codeId: string; + codeHash: string; + schema: Option; } -const assetDefault = { - assetsSelect: defaultAsset, - assetsJsonStr: defaultAssetJsonStr, - attachFundsOption: AttachFundsType.ATTACH_FUNDS_NULL, -}; - export const ExecuteArea = ({ contractAddress, initialMsg, initialFunds, - cmds, + codeHash, + codeId, + schema, }: ExecuteAreaProps) => { - const { address } = useCurrentChain(); - const fabricateFee = useFabricateFee(); - const executeTx = useExecuteContractTx(); - const { broadcast } = useTxBroadcast(); - const { addActivity } = useContractStore(); - const getAttachFunds = useAttachFunds(); - const [fee, setFee] = useState(); - const [msg, setMsg] = useState(initialMsg); - - const [error, setError] = useState(); - const [composedTxMsg, setComposedTxMsg] = useState([]); - const [processing, setProcessing] = useState(false); - - const { control, setValue, watch, reset } = useForm({ - mode: "all", - defaultValues: assetDefault, - }); - - /** - * @remarks - * Handle when there is an initialFunds - */ - useEffect(() => { - try { - if (initialFunds.length) { - setValue(ASSETS_JSON_STR, jsonPrettify(JSON.stringify(initialFunds))); - setValue(ATTACH_FUNDS_OPTION, AttachFundsType.ATTACH_FUNDS_JSON); - } else { - reset(assetDefault); - } - } catch { - // comment just to avoid eslint no-empty - } - }, [initialFunds, reset, setValue]); - - const { errors } = useFormState({ control }); - - const { assetsJsonStr, assetsSelect, attachFundsOption } = watch(); - - const isValidAssetsSelect = !errors.assetsSelect; - const isValidAssetsJsonStr = - !errors.assetsJsonStr && jsonValidate(assetsJsonStr) === null; - - const enableExecute = useMemo(() => { - const generalCheck = !!( - msg.trim().length && - jsonValidate(msg) === null && - address && - contractAddress - ); - switch (attachFundsOption) { - case AttachFundsType.ATTACH_FUNDS_SELECT: - return generalCheck && isValidAssetsSelect; - case AttachFundsType.ATTACH_FUNDS_JSON: - return generalCheck && isValidAssetsJsonStr; - default: - return generalCheck; - } - }, [ - msg, - address, - contractAddress, - attachFundsOption, - isValidAssetsSelect, - isValidAssetsJsonStr, - ]); - - const { isFetching } = useSimulateFeeQuery({ - enabled: composedTxMsg.length > 0, - messages: composedTxMsg, - onSuccess: (gasRes) => { - setError(undefined); - if (gasRes) setFee(fabricateFee(gasRes)); - else setFee(undefined); - }, - onError: (e) => { - setError(e.message); - setFee(undefined); - }, - }); - - const proceed = useCallback(async () => { - const funds = getAttachFunds( - attachFundsOption, - assetsJsonStr, - assetsSelect - ); - AmpTrackAction(AmpEvent.ACTION_EXECUTE, funds.length, attachFundsOption); - const stream = await executeTx({ - onTxSucceed: (activity: Activity) => { - addActivity(activity); - setProcessing(false); - }, - onTxFailed: () => setProcessing(false), - estimatedFee: fee, - contractAddress, - msg: JSON.parse(msg), - funds, - }); - if (stream) { - setProcessing(true); - broadcast(stream); - } - }, [ - attachFundsOption, - executeTx, - fee, - contractAddress, - msg, - getAttachFunds, - assetsJsonStr, - assetsSelect, - addActivity, - broadcast, - ]); - - useEffect(() => setMsg(initialMsg), [initialMsg]); - - const assetsSelectString = JSON.stringify(assetsSelect); - useEffect(() => { - if (enableExecute) { - const composedMsg = composeMsg(MsgType.EXECUTE, { - sender: address as HumanAddr, - contract: contractAddress as ContractAddr, - msg: Buffer.from(msg), - funds: getAttachFunds(attachFundsOption, assetsJsonStr, assetsSelect), - }); - - const timeoutId = setTimeout(() => { - setComposedTxMsg([composedMsg]); - }, 1000); - return () => clearTimeout(timeoutId); - } - return () => {}; - }, [ - address, - contractAddress, - enableExecute, - msg, - assetsJsonStr, - assetsSelectString, - getAttachFunds, - attachFundsOption, - assetsSelect, - ]); + const [tab, setTab] = useState(MessageTabs.JSON_INPUT); useEffect(() => { - const keydownHandler = (e: KeyboardEvent) => { - // TODO: problem with safari if focusing in the textarea - if (e.ctrlKey && e.key === "Enter") { - proceed(); - } - }; - document.addEventListener("keydown", keydownHandler); - return () => { - document.removeEventListener("keydown", keydownHandler); - }; - }); + if (!schema) setTab(MessageTabs.JSON_INPUT); + }, [schema]); - const isMobile = useMobile(); return ( - {contractAddress && ( - - Message Suggestions: - - )} - {cmds.length ? ( - button": { - marginInlineStart: "0 !important", - marginInlineEnd: "1", - }, - }} - > - {cmds.sort().map(([cmd, queryMsg]) => ( - { - AmpTrack(AmpEvent.USE_CMD_EXECUTE); - setMsg(jsonPrettify(queryMsg)); - }} - /> - ))} - - ) : ( - contractAddress && ( - - No ExecuteMsgs suggestion available - - ) - )} - - - - {error && } - - - - + + + Execute Message + + - - - - - - - - Transaction Fee:{" "} - - - - - + } + schemaContent={ + codeHash && schema ? ( + + ) : ( + + ) + } + /> ); }; diff --git a/src/lib/pages/execute/components/JsonExecute.tsx b/src/lib/pages/execute/components/JsonExecute.tsx new file mode 100644 index 000000000..682402c2d --- /dev/null +++ b/src/lib/pages/execute/components/JsonExecute.tsx @@ -0,0 +1,301 @@ +import { Box, Flex, Button } from "@chakra-ui/react"; +import type { Coin, StdFee } from "@cosmjs/stargate"; +import dynamic from "next/dynamic"; +import { useCallback, useEffect, useMemo, useState } from "react"; +import { useForm, useFormState } from "react-hook-form"; + +import { + useFabricateFee, + useExecuteContractTx, + useCurrentChain, + useMobile, +} from "lib/app-provider"; +import { useAttachFunds } from "lib/app-provider/hooks/useAttachFunds"; +import { useSimulateFeeQuery } from "lib/app-provider/queries"; +import { CopyButton } from "lib/components/copy"; +import { ErrorMessageRender } from "lib/components/ErrorMessageRender"; +import { EstimatedFeeRender } from "lib/components/EstimatedFeeRender"; +import { AttachFund } from "lib/components/fund"; +import { + ASSETS_JSON_STR, + ATTACH_FUNDS_OPTION, + defaultAsset, + defaultAssetJsonStr, +} from "lib/components/fund/data"; +import type { AttachFundsState } from "lib/components/fund/types"; +import { AttachFundsType } from "lib/components/fund/types"; +import { CustomIcon } from "lib/components/icon"; +import JsonInput from "lib/components/json/JsonInput"; +import { LoadingOverlay } from "lib/components/LoadingOverlay"; +import { useExecuteCmds } from "lib/hooks"; +import { useContractStore } from "lib/providers/store"; +import { useTxBroadcast } from "lib/providers/tx-broadcast"; +import { AmpEvent, AmpTrackAction } from "lib/services/amplitude"; +import type { Activity } from "lib/stores/contract"; +import type { ComposedMsg, ContractAddr, HumanAddr } from "lib/types"; +import { MsgType } from "lib/types"; +import { composeMsg, jsonPrettify, jsonValidate } from "lib/utils"; + +import { MsgSuggestion } from "./MsgSuggestion"; + +interface JsonExecuteProps { + contractAddress: ContractAddr; + initialMsg: string; + initialFunds: Coin[]; +} + +const CodeSnippet = dynamic(() => import("lib/components/modal/CodeSnippet"), { + ssr: false, +}); + +const assetDefault = { + assetsSelect: defaultAsset, + assetsJsonStr: defaultAssetJsonStr, + attachFundsOption: AttachFundsType.ATTACH_FUNDS_NULL, +}; + +export const JsonExecute = ({ + contractAddress, + initialFunds, + initialMsg, +}: JsonExecuteProps) => { + // ------------------------------------------// + // --------------DEPENDENCIES----------------// + // ------------------------------------------// + const isMobile = useMobile(); + const { address } = useCurrentChain(); + const fabricateFee = useFabricateFee(); + const executeTx = useExecuteContractTx(); + const { broadcast } = useTxBroadcast(); + const { addActivity } = useContractStore(); + const getAttachFunds = useAttachFunds(); + + // ------------------------------------------// + // ------------------STATES------------------// + // ------------------------------------------// + const [fee, setFee] = useState(); + const [msg, setMsg] = useState(initialMsg); + const [error, setError] = useState(); + const [composedTxMsg, setComposedTxMsg] = useState([]); + const [processing, setProcessing] = useState(false); + + // ------------------------------------------// + // ----------------FORM HOOKS----------------// + // ------------------------------------------// + const { control, setValue, watch, reset } = useForm({ + mode: "all", + defaultValues: assetDefault, + }); + const { errors } = useFormState({ control }); + const { assetsJsonStr, assetsSelect, attachFundsOption } = watch(); + + // ------------------------------------------// + // -------------------LOGICS-----------------// + // ------------------------------------------// + const isValidAssetsSelect = !errors.assetsSelect; + const isValidAssetsJsonStr = + !errors.assetsJsonStr && jsonValidate(assetsJsonStr) === null; + + const assetsSelectString = JSON.stringify(assetsSelect); + + const enableExecute = useMemo(() => { + const generalCheck = !!( + msg.trim().length && + jsonValidate(msg) === null && + address && + contractAddress + ); + switch (attachFundsOption) { + case AttachFundsType.ATTACH_FUNDS_SELECT: + return generalCheck && isValidAssetsSelect; + case AttachFundsType.ATTACH_FUNDS_JSON: + return generalCheck && isValidAssetsJsonStr; + default: + return generalCheck; + } + }, [ + msg, + address, + contractAddress, + attachFundsOption, + isValidAssetsSelect, + isValidAssetsJsonStr, + ]); + + // ------------------------------------------// + // -----------------REACT QUERY--------------// + // ------------------------------------------// + const { isFetching: cmdsFetching, execCmds } = useExecuteCmds( + contractAddress as ContractAddr + ); + const { isFetching } = useSimulateFeeQuery({ + enabled: composedTxMsg.length > 0, + messages: composedTxMsg, + onSuccess: (gasRes) => { + setError(undefined); + if (gasRes) setFee(fabricateFee(gasRes)); + else setFee(undefined); + }, + onError: (e) => { + setError(e.message); + setFee(undefined); + }, + }); + + // ------------------------------------------// + // ------------------CALLBACKS---------------// + // ------------------------------------------// + + const proceed = useCallback(async () => { + const funds = getAttachFunds( + attachFundsOption, + assetsJsonStr, + assetsSelect + ); + AmpTrackAction(AmpEvent.ACTION_EXECUTE, funds.length, attachFundsOption); + const stream = await executeTx({ + onTxSucceed: (activity: Activity) => { + addActivity(activity); + setProcessing(false); + }, + onTxFailed: () => setProcessing(false), + estimatedFee: fee, + contractAddress, + msg: JSON.parse(msg), + funds, + }); + if (stream) { + setProcessing(true); + broadcast(stream); + } + }, [ + attachFundsOption, + executeTx, + fee, + contractAddress, + msg, + getAttachFunds, + assetsJsonStr, + assetsSelect, + addActivity, + broadcast, + ]); + + // ------------------------------------------// + // ----------------SIDE EFFECTS--------------// + // ------------------------------------------// + /** + * @remarks + * Handle when there is an initialFunds + */ + useEffect(() => { + try { + if (initialFunds.length) { + setValue(ASSETS_JSON_STR, jsonPrettify(JSON.stringify(initialFunds))); + setValue(ATTACH_FUNDS_OPTION, AttachFundsType.ATTACH_FUNDS_JSON); + } else { + reset(assetDefault); + } + } catch { + // comment just to avoid eslint no-empty + } + }, [initialFunds, reset, setValue]); + + useEffect(() => setMsg(initialMsg), [initialMsg]); + + useEffect(() => { + if (enableExecute) { + const composedMsg = composeMsg(MsgType.EXECUTE, { + sender: address as HumanAddr, + contract: contractAddress as ContractAddr, + msg: Buffer.from(msg), + funds: getAttachFunds(attachFundsOption, assetsJsonStr, assetsSelect), + }); + + const timeoutId = setTimeout(() => { + setComposedTxMsg([composedMsg]); + }, 1000); + return () => clearTimeout(timeoutId); + } + return () => {}; + }, [ + address, + contractAddress, + enableExecute, + msg, + assetsJsonStr, + assetsSelectString, + getAttachFunds, + attachFundsOption, + assetsSelect, + ]); + + useEffect(() => { + const keydownHandler = (e: KeyboardEvent) => { + // TODO: problem with safari if focusing in the textarea + if (e.ctrlKey && e.key === "Enter") { + proceed(); + } + }; + document.addEventListener("keydown", keydownHandler); + return () => { + document.removeEventListener("keydown", keydownHandler); + }; + }); + + return ( + <> + {cmdsFetching && } + + + + + {error && } + + + + + + + + + + + + + Transaction Fee:{" "} + + + + + + + ); +}; diff --git a/src/lib/pages/execute/components/MsgSuggestion.tsx b/src/lib/pages/execute/components/MsgSuggestion.tsx new file mode 100644 index 000000000..0ed57c46f --- /dev/null +++ b/src/lib/pages/execute/components/MsgSuggestion.tsx @@ -0,0 +1,57 @@ +import { Box, Text, ButtonGroup } from "@chakra-ui/react"; + +import { ContractCmdButton } from "lib/components/ContractCmdButton"; +import { AmpEvent, AmpTrack } from "lib/services/amplitude"; +import type { ContractAddr } from "lib/types"; +import { jsonPrettify } from "lib/utils"; + +interface MsgSuggestionProps { + contractAddress: ContractAddr; + cmds: [string, string][]; + setMsg: (msg: string) => void; +} + +export const MsgSuggestion = ({ + contractAddress, + cmds, + setMsg, +}: MsgSuggestionProps) => { + return ( + + {contractAddress && ( + + Message Suggestions: + + )} + {cmds.length ? ( + button": { + marginInlineStart: "0 !important", + marginInlineEnd: "1", + }, + }} + > + {cmds.sort().map(([cmd, queryMsg]) => ( + { + AmpTrack(AmpEvent.USE_CMD_EXECUTE); + setMsg(jsonPrettify(queryMsg)); + }} + /> + ))} + + ) : ( + contractAddress && ( + + No ExecuteMsgs suggestion available + + ) + )} + + ); +}; diff --git a/src/lib/pages/execute/components/schema-execute/ExecuteBox.tsx b/src/lib/pages/execute/components/schema-execute/ExecuteBox.tsx new file mode 100644 index 000000000..73a15857d --- /dev/null +++ b/src/lib/pages/execute/components/schema-execute/ExecuteBox.tsx @@ -0,0 +1,295 @@ +import { + AccordionButton, + AccordionIcon, + AccordionItem, + AccordionPanel, + Alert, + AlertDescription, + Box, + Button, + Flex, + Grid, + GridItem, + Text, +} from "@chakra-ui/react"; +import type { StdFee } from "@cosmjs/stargate"; +import dynamic from "next/dynamic"; +import { useCallback, useEffect, useState, useMemo } from "react"; +import { useForm, useFormState } from "react-hook-form"; + +import { + useCurrentChain, + useExecuteContractTx, + useFabricateFee, + useSimulateFeeQuery, +} from "lib/app-provider"; +import { useAttachFunds } from "lib/app-provider/hooks/useAttachFunds"; +import { CopyButton } from "lib/components/copy"; +import { EstimatedFeeRender } from "lib/components/EstimatedFeeRender"; +import { AttachFund } from "lib/components/fund"; +import { defaultAsset, defaultAssetJsonStr } from "lib/components/fund/data"; +import type { AttachFundsState } from "lib/components/fund/types"; +import { AttachFundsType } from "lib/components/fund/types"; +import { CustomIcon } from "lib/components/icon"; +import { JsonSchemaForm } from "lib/components/json-schema"; +import { useContractStore } from "lib/providers/store"; +import { useTxBroadcast } from "lib/providers/tx-broadcast"; +import { AmpEvent, AmpTrackAction } from "lib/services/amplitude"; +import type { Activity } from "lib/stores/contract"; +import type { QueryExecuteSchema } from "lib/stores/schema"; +import type { ComposedMsg, ContractAddr, HumanAddr } from "lib/types"; +import { MsgType } from "lib/types"; +import { composeMsg, jsonValidate } from "lib/utils"; + +const CodeSnippet = dynamic(() => import("lib/components/modal/CodeSnippet"), { + ssr: false, +}); + +interface ExecuteBoxProps { + msgSchema: QueryExecuteSchema; + contractAddress: ContractAddr; + opened: boolean; +} + +const assetDefault = { + assetsSelect: defaultAsset, + assetsJsonStr: defaultAssetJsonStr, + attachFundsOption: AttachFundsType.ATTACH_FUNDS_NULL, +}; + +export const ExecuteBox = ({ + msgSchema, + contractAddress, + opened, +}: ExecuteBoxProps) => { + // ------------------------------------------// + // --------------DEPENDENCIES----------------// + // ------------------------------------------// + const { address } = useCurrentChain(); + const fabricateFee = useFabricateFee(); + const executeTx = useExecuteContractTx(); + const { broadcast } = useTxBroadcast(); + const { addActivity } = useContractStore(); + const getAttachFunds = useAttachFunds(); + + // ------------------------------------------// + // ------------------STATES------------------// + // ------------------------------------------// + const [fee, setFee] = useState(); + // TODO: add initial msg + const [msg, setMsg] = useState("{}"); + const [error, setError] = useState(); + const [composedTxMsg, setComposedTxMsg] = useState([]); + const [processing, setProcessing] = useState(false); + + // ------------------------------------------// + // ----------------FORM HOOKS----------------// + // ------------------------------------------// + const { control, setValue, watch } = useForm({ + mode: "all", + defaultValues: assetDefault, + }); + const { errors } = useFormState({ control }); + const { assetsJsonStr, assetsSelect, attachFundsOption } = watch(); + + // ------------------------------------------// + // -------------------LOGICS-----------------// + // ------------------------------------------// + const isValidAssetsSelect = !errors.assetsSelect; + const isValidAssetsJsonStr = + !errors.assetsJsonStr && jsonValidate(assetsJsonStr) === null; + + const assetsSelectString = JSON.stringify(assetsSelect); + + const enableExecute = useMemo(() => { + const generalCheck = !!( + msg.trim().length && + jsonValidate(msg) === null && + address && + contractAddress && + opened + ); + switch (attachFundsOption) { + case AttachFundsType.ATTACH_FUNDS_SELECT: + return generalCheck && isValidAssetsSelect; + case AttachFundsType.ATTACH_FUNDS_JSON: + return generalCheck && isValidAssetsJsonStr; + default: + return generalCheck; + } + }, [ + msg, + address, + opened, + contractAddress, + attachFundsOption, + isValidAssetsSelect, + isValidAssetsJsonStr, + ]); + + // ------------------------------------------// + // -----------------REACT QUERY--------------// + // ------------------------------------------// + const { isFetching } = useSimulateFeeQuery({ + enabled: composedTxMsg.length > 0, + messages: composedTxMsg, + onSuccess: (gasRes) => { + setError(undefined); + if (gasRes) setFee(fabricateFee(gasRes)); + else setFee(undefined); + }, + onError: (e) => { + setError(e.message); + setFee(undefined); + }, + }); + + // ------------------------------------------// + // ------------------CALLBACKS---------------// + // ------------------------------------------// + + const proceed = useCallback(async () => { + const funds = getAttachFunds( + attachFundsOption, + assetsJsonStr, + assetsSelect + ); + AmpTrackAction(AmpEvent.ACTION_EXECUTE, funds.length, attachFundsOption); + const stream = await executeTx({ + onTxSucceed: (activity: Activity) => { + addActivity(activity); + setProcessing(false); + }, + onTxFailed: () => setProcessing(false), + estimatedFee: fee, + contractAddress, + msg: JSON.parse(msg), + funds, + }); + if (stream) { + setProcessing(true); + broadcast(stream); + } + }, [ + attachFundsOption, + executeTx, + fee, + contractAddress, + msg, + getAttachFunds, + assetsJsonStr, + assetsSelect, + addActivity, + broadcast, + ]); + + // ------------------------------------------// + // ----------------SIDE EFFECTS--------------// + // ------------------------------------------// + useEffect(() => { + if (enableExecute) { + const composedMsg = composeMsg(MsgType.EXECUTE, { + sender: address as HumanAddr, + contract: contractAddress as ContractAddr, + msg: Buffer.from(msg), + funds: getAttachFunds(attachFundsOption, assetsJsonStr, assetsSelect), + }); + + const timeoutId = setTimeout(() => { + setComposedTxMsg([composedMsg]); + }, 1000); + return () => clearTimeout(timeoutId); + } + return () => {}; + }, [ + address, + contractAddress, + enableExecute, + msg, + assetsJsonStr, + assetsSelectString, + getAttachFunds, + attachFundsOption, + assetsSelect, + ]); + + return ( + +
+ + + + {msgSchema.title} + + {msgSchema.description} + + + +
+ + + + setMsg(JSON.stringify(data))} + /> + {error && ( + + + {error} + + + )} + + + + + + + + + + + + + + Transaction Fee:{" "} + + + + + + + +
+ ); +}; diff --git a/src/lib/pages/execute/components/schema-execute/index.tsx b/src/lib/pages/execute/components/schema-execute/index.tsx new file mode 100644 index 000000000..6e91a5413 --- /dev/null +++ b/src/lib/pages/execute/components/schema-execute/index.tsx @@ -0,0 +1,88 @@ +import { Accordion, Button, Flex } from "@chakra-ui/react"; +import { useMemo, useState } from "react"; + +import { CustomIcon } from "lib/components/icon"; +import InputWithIcon from "lib/components/InputWithIcon"; +import { EmptyState } from "lib/components/state"; +import { AmpTrackExpandAll } from "lib/services/amplitude"; +import type { ExecuteSchema } from "lib/stores/schema"; +import type { ContractAddr } from "lib/types"; + +import { ExecuteBox } from "./ExecuteBox"; + +interface SchemaExecuteProps { + contractAddress: ContractAddr; + schema: ExecuteSchema; +} + +// TODO: add initialMsg and initialFunds +export const SchemaExecute = ({ + contractAddress, + schema, +}: SchemaExecuteProps) => { + // ------------------------------------------// + // -------------------STATES-----------------// + // ------------------------------------------// + const [keyword, setKeyword] = useState(""); + const [expandedIndexes, setExpandedIndexes] = useState([]); + + // ------------------------------------------// + // -------------------LOGICS-----------------// + // ------------------------------------------// + const filteredMsgs = useMemo(() => { + if (!keyword) return schema; + + return schema.filter((msg) => msg.title?.includes(keyword)); + }, [keyword, schema]); + + return ( + <> + + setKeyword(e.target.value)} + action="execute-message-search" + /> + + + {filteredMsgs?.length ? ( + setExpandedIndexes(indexes)} + sx={{ ".chakra-accordion__icon": { color: "gray.600" } }} + > + {filteredMsgs.map((msgSchema, idx) => ( + + ))} + + ) : ( + + )} + + ); +}; diff --git a/src/lib/pages/execute/index.tsx b/src/lib/pages/execute/index.tsx index bd6de7667..07a99eb3a 100644 --- a/src/lib/pages/execute/index.tsx +++ b/src/lib/pages/execute/index.tsx @@ -7,10 +7,10 @@ import { useInternalNavigate, useWasmConfig } from "lib/app-provider"; import { ConnectWalletAlert } from "lib/components/ConnectWalletAlert"; import { ContractSelectSection } from "lib/components/ContractSelectSection"; import { CustomIcon } from "lib/components/icon"; -import { LoadingOverlay } from "lib/components/LoadingOverlay"; import PageContainer from "lib/components/PageContainer"; -import { useExecuteCmds } from "lib/hooks"; +import { useSchemaStore } from "lib/providers/store"; import { AmpTrackToExecute } from "lib/services/amplitude"; +import type { ContractDetail } from "lib/services/contractService"; import type { ContractAddr } from "lib/types"; import { getFirstQueryParam, @@ -22,17 +22,32 @@ import { import { ExecuteArea } from "./components/ExecuteArea"; const Execute = () => { + // ------------------------------------------// + // --------------DEPENDENCIES----------------// + // ------------------------------------------// useWasmConfig({ shouldRedirect: true }); + const router = useRouter(); const navigate = useInternalNavigate(); + const { getExecuteSchema } = useSchemaStore(); + + // ------------------------------------------// + // ------------------STATES------------------// + // ------------------------------------------// const [initialMsg, setInitialMsg] = useState(""); - const [contractAddress, setContractAddress] = useState(""); + const [contractAddress, setContractAddress] = useState("" as ContractAddr); const [initialFunds, setInitialFunds] = useState([]); + const [codeHash, setCodeHash] = useState(""); + const [codeId, setCodeId] = useState(""); - const { isFetching, execCmds } = useExecuteCmds( - contractAddress as ContractAddr - ); + // ------------------------------------------// + // ------------------LOGICS------------------// + // ------------------------------------------// + const schema = getExecuteSchema(codeHash); + // ------------------------------------------// + // ----------------CALLBACKS-----------------// + // ------------------------------------------// const goToQuery = () => { navigate({ pathname: "/query", @@ -53,6 +68,9 @@ const Execute = () => { [navigate] ); + // ------------------------------------------// + // ---------------SIDE EFFECTS---------------// + // ------------------------------------------// useEffect(() => { const msgParam = getFirstQueryParam(router.query.msg); if (router.isReady) { @@ -84,7 +102,6 @@ const Execute = () => { return ( - {isFetching && } Execute Contract @@ -106,17 +123,24 @@ const Execute = () => { subtitle="You need to connect your wallet to perform this action" mb={8} /> + { + setCodeHash(data.codeHash); + setCodeId(String(data.codeId)); + }} /> ); diff --git a/src/lib/pages/query/components/QueryArea.tsx b/src/lib/pages/query/components/QueryArea.tsx index 1be05e451..f714ad39c 100644 --- a/src/lib/pages/query/components/QueryArea.tsx +++ b/src/lib/pages/query/components/QueryArea.tsx @@ -63,7 +63,7 @@ export const QueryArea = ({ /> } schemaContent={ - codeHash ? ( + codeHash && schema ? ( ; + schema: QuerySchema; contractAddress: ContractAddr; initialMsg: string; } @@ -306,8 +306,6 @@ export const SchemaQuery = ({ // eslint-disable-next-line react-hooks/exhaustive-deps }, [schema, initialMsg, accordionRef.current]); - if (!schema) return null; - return ( <> @@ -315,6 +313,7 @@ export const SchemaQuery = ({ placeholder="Search by command" value={keyword} onChange={(e) => setKeyword(e.target.value)} + action="query-message-search" /> + } + > + Delete Schema + + } + /> + +); diff --git a/src/lib/components/json-schema/JsonSchemaDrawer.tsx b/src/lib/components/json-schema/JsonSchemaDrawer.tsx index 968ef4b75..5e7beab85 100644 --- a/src/lib/components/json-schema/JsonSchemaDrawer.tsx +++ b/src/lib/components/json-schema/JsonSchemaDrawer.tsx @@ -59,7 +59,11 @@ export const JsonSchemaDrawer = ({ JSON schemas, they will be visible and accessible to others. - + diff --git a/src/lib/components/json-schema/UploadTemplate.tsx b/src/lib/components/json-schema/UploadTemplate.tsx index 20e78b0cd..f7578b76c 100644 --- a/src/lib/components/json-schema/UploadTemplate.tsx +++ b/src/lib/components/json-schema/UploadTemplate.tsx @@ -170,11 +170,13 @@ const MethodRender = ({ interface UploadTemplateInterface { codeHash: string; + codeId: string; closeDrawer: () => void; } export const UploadTemplate = ({ codeHash, + codeId, closeDrawer, }: UploadTemplateInterface) => { const { saveNewSchema } = useSchemaStore(); @@ -224,11 +226,11 @@ export const UploadTemplate = ({ error: schemaValidateError, }); } - saveNewSchema(codeHash, JSON.parse(schemaString)); + saveNewSchema(codeHash, codeId, JSON.parse(schemaString)); setUrlLoading(false); closeDrawer(); return dispatchJsonState({ type: ActionType.RESET, method }); - }, [codeHash, method, jsonState, closeDrawer, saveNewSchema]); + }, [closeDrawer, codeHash, codeId, jsonState, method, saveNewSchema]); const disabledState = useMemo(() => { const methodSchemaString = jsonState[method].schemaString; diff --git a/src/lib/components/json-schema/index.ts b/src/lib/components/json-schema/index.ts index 8f6de4766..b5df2cc67 100644 --- a/src/lib/components/json-schema/index.ts +++ b/src/lib/components/json-schema/index.ts @@ -1,5 +1,6 @@ export * from "./form"; export * from "./AttachSchemaCard"; +export * from "./EditSchemaButtons"; export * from "./JsonSchemaDrawer"; export * from "./UploadTemplate"; export * from "./ViewSchemaButton"; diff --git a/src/lib/pages/code-details/components/json-schema/CodeSchemaSection.tsx b/src/lib/pages/code-details/components/json-schema/CodeSchemaSection.tsx index 040d9b049..15ac96183 100644 --- a/src/lib/pages/code-details/components/json-schema/CodeSchemaSection.tsx +++ b/src/lib/pages/code-details/components/json-schema/CodeSchemaSection.tsx @@ -1,5 +1,4 @@ import { - Button, chakra, Flex, Heading, @@ -14,9 +13,11 @@ import { capitalize } from "lodash"; import { CustomTab } from "lib/components/CustomTab"; import { CustomIcon } from "lib/components/icon"; -import { JsonSchemaDrawer } from "lib/components/json-schema"; +import { + JsonSchemaDrawer, + EditSchemaButtons, +} from "lib/components/json-schema"; import { Loading } from "lib/components/Loading"; -import { RemoveSchemaModal } from "lib/components/modal/RemoveSchemaModal"; import type { CodeSchema } from "lib/stores/schema"; import { SchemaProperties } from "lib/stores/schema"; import type { Option } from "lib/types"; @@ -67,25 +68,11 @@ export const CodeSchemaSection = ({ JSON Schema {!!jsonSchema && ( - - - - - - } - /> - + )} { +export const CommandSection = ({ + contractAddress, + codeHash, + codeId, +}: CommandSectionProps) => { const navigate = useInternalNavigate(); + const { isOpen, onClose, onOpen } = useDisclosure(); + + const { getSchemaByCodeHash } = useSchemaStore(); + const attached = !!getSchemaByCodeHash(codeHash); const { isFetching: isQueryCmdsFetching, queryCmds } = useQueryCmds(contractAddress); - const { isFetching: isExecuteCmdsFetching, execCmds } = useExecuteCmds(contractAddress); @@ -66,35 +91,71 @@ export const CommandSection = ({ contractAddress }: CommandSectionProps) => { }; return ( - - - - Query Shortcuts - - {renderCmds(isQueryCmdsFetching, queryCmds, "query")} + + + + Available command shortcuts + + {attached ? ( + + + + Attached JSON Schema + + + + ) : ( + + + + )} - - Execute Shortcuts - - {renderCmds(isExecuteCmdsFetching, execCmds, "execute")} + + + Query Shortcuts + + {renderCmds(isQueryCmdsFetching, queryCmds, "query")} + + + + Execute Shortcuts + + {renderCmds(isExecuteCmdsFetching, execCmds, "execute")} + + ); }; diff --git a/src/lib/pages/contract-details/index.tsx b/src/lib/pages/contract-details/index.tsx index da5030834..f4d37ad08 100644 --- a/src/lib/pages/contract-details/index.tsx +++ b/src/lib/pages/contract-details/index.tsx @@ -63,7 +63,11 @@ const ContractDetailsBody = observer( {/* Contract Description Section */} {/* Query/Execute commands section */} - + {/* Instantiate/Contract Info Section */} { schemaStore = new SchemaStore(); }); beforeEach(() => { - schemaStore.saveNewSchema(codeHash, exampleSchema); + schemaStore.saveNewSchema(codeHash, codeId, exampleSchema); }); describe("SchemaStore initialization", () => { @@ -77,6 +81,9 @@ describe("getSchemaProperty", () => { expect( schemaStore.getSchemaProperty(codeHash, SchemaProperties.RESPONSES) ).toStrictEqual(exampleSchema.responses); + expect( + schemaStore.getSchemaProperty(codeHash, SchemaProperties.ATTACHED_CODE_ID) + ).toStrictEqual(exampleSchema.attached_code_id); }); test("correctly retrieve schema property from uppercase code hash", () => { diff --git a/src/lib/stores/schema.ts b/src/lib/stores/schema.ts index dd695ab1f..3de4e6890 100644 --- a/src/lib/stores/schema.ts +++ b/src/lib/stores/schema.ts @@ -14,6 +14,7 @@ export enum SchemaProperties { MIGRATE = "migrate", SUDO = "sudo", RESPONSES = "responses", + ATTACHED_CODE_ID = "attached_code_id", } type NullableJsonSchema = JsonSchema | null; @@ -35,6 +36,7 @@ export interface CodeSchema { [SchemaProperties.MIGRATE]: NullableJsonSchema; [SchemaProperties.SUDO]: NullableJsonSchema; [SchemaProperties.RESPONSES]: { [key: string]: JsonSchema }; + [SchemaProperties.ATTACHED_CODE_ID]: string; } export type QuerySchema = Array<[QueryExecuteSchema, JsonSchema]>; @@ -68,8 +70,11 @@ export class SchemaStore { }); } - saveNewSchema(codeHash: string, schema: CodeSchema) { - this.jsonSchemas[normalize(codeHash)] = schema; + saveNewSchema(codeHash: string, codeId: string, schema: CodeSchema) { + this.jsonSchemas[normalize(codeHash)] = { + ...schema, + [SchemaProperties.ATTACHED_CODE_ID]: codeId, + }; } deleteSchema(codeHash: string) { From dd75da80255ea08fe1b82402149c0c5ad18e8c45 Mon Sep 17 00:00:00 2001 From: evilpeach Date: Tue, 22 Aug 2023 15:26:43 +0700 Subject: [PATCH 52/94] feat: auto scroll when redo --- .../json-schema/MessageInputContent.tsx | 32 +++++---- .../pages/execute/components/ExecuteArea.tsx | 14 +++- .../components/schema-execute/ExecuteBox.tsx | 46 ++++++++++--- .../components/schema-execute/index.tsx | 65 ++++++++++++++++--- .../pages/query/components/SchemaQuery.tsx | 4 +- 5 files changed, 122 insertions(+), 39 deletions(-) diff --git a/src/lib/components/json-schema/MessageInputContent.tsx b/src/lib/components/json-schema/MessageInputContent.tsx index 4f3da7710..fcdf2d46d 100644 --- a/src/lib/components/json-schema/MessageInputContent.tsx +++ b/src/lib/components/json-schema/MessageInputContent.tsx @@ -21,20 +21,18 @@ export const MessageInputContent = ({ currentTab, jsonContent, schemaContent, -}: MessageInputContentProps) => { - return ( - -
{jsonContent}
-
{schemaContent}
-
- ); -}; +}: MessageInputContentProps) => ( + +
{jsonContent}
+
{schemaContent}
+
+); diff --git a/src/lib/pages/execute/components/ExecuteArea.tsx b/src/lib/pages/execute/components/ExecuteArea.tsx index 115c5aa48..6065728d7 100644 --- a/src/lib/pages/execute/components/ExecuteArea.tsx +++ b/src/lib/pages/execute/components/ExecuteArea.tsx @@ -35,12 +35,15 @@ export const ExecuteArea = ({ useEffect(() => { if (!schema) setTab(MessageTabs.JSON_INPUT); + else { + setTab(MessageTabs.YOUR_SCHEMA); + } }, [schema]); return ( - - + + Execute Message + ) : ( import("lib/components/modal/CodeSnippet"), { ssr: false, @@ -48,6 +53,8 @@ const CodeSnippet = dynamic(() => import("lib/components/modal/CodeSnippet"), { interface ExecuteBoxProps { msgSchema: QueryExecuteSchema; contractAddress: ContractAddr; + initialMsg: Record; + initialFunds: Coin[]; opened: boolean; } @@ -60,6 +67,8 @@ const assetDefault = { export const ExecuteBox = ({ msgSchema, contractAddress, + initialMsg, + initialFunds, opened, }: ExecuteBoxProps) => { // ------------------------------------------// @@ -76,7 +85,6 @@ export const ExecuteBox = ({ // ------------------STATES------------------// // ------------------------------------------// const [fee, setFee] = useState(); - // TODO: add initial msg const [msg, setMsg] = useState("{}"); const [error, setError] = useState(); const [composedTxMsg, setComposedTxMsg] = useState([]); @@ -85,7 +93,7 @@ export const ExecuteBox = ({ // ------------------------------------------// // ----------------FORM HOOKS----------------// // ------------------------------------------// - const { control, setValue, watch } = useForm({ + const { control, setValue, watch, reset } = useForm({ mode: "all", defaultValues: assetDefault, }); @@ -186,6 +194,27 @@ export const ExecuteBox = ({ // ------------------------------------------// // ----------------SIDE EFFECTS--------------// // ------------------------------------------// + /** + * @remarks + * Handle when there is an initialFunds + */ + useEffect(() => { + try { + if (initialFunds.length) { + setValue(ASSETS_JSON_STR, jsonPrettify(JSON.stringify(initialFunds))); + setValue(ATTACH_FUNDS_OPTION, AttachFundsType.ATTACH_FUNDS_JSON); + } else { + reset(assetDefault); + } + } catch { + // comment just to avoid eslint no-empty + } + }, [initialFunds, reset, setValue]); + + useEffect(() => { + if (Object.keys(initialMsg).length) setMsg(JSON.stringify(initialMsg)); + }, [initialMsg]); + useEffect(() => { if (enableExecute) { const composedMsg = composeMsg(MsgType.EXECUTE, { @@ -214,9 +243,9 @@ export const ExecuteBox = ({ ]); return ( - +
- + {msgSchema.title} @@ -226,12 +255,13 @@ export const ExecuteBox = ({
- + setMsg(JSON.stringify(data))} /> {error && ( diff --git a/src/lib/pages/execute/components/schema-execute/index.tsx b/src/lib/pages/execute/components/schema-execute/index.tsx index 6e91a5413..31eb24c44 100644 --- a/src/lib/pages/execute/components/schema-execute/index.tsx +++ b/src/lib/pages/execute/components/schema-execute/index.tsx @@ -1,5 +1,6 @@ import { Accordion, Button, Flex } from "@chakra-ui/react"; -import { useMemo, useState } from "react"; +import type { Coin } from "@cosmjs/stargate"; +import { useEffect, useMemo, useRef, useState } from "react"; import { CustomIcon } from "lib/components/icon"; import InputWithIcon from "lib/components/InputWithIcon"; @@ -7,19 +8,29 @@ import { EmptyState } from "lib/components/state"; import { AmpTrackExpandAll } from "lib/services/amplitude"; import type { ExecuteSchema } from "lib/stores/schema"; import type { ContractAddr } from "lib/types"; +import { parseSchemaInitialData } from "lib/utils"; import { ExecuteBox } from "./ExecuteBox"; interface SchemaExecuteProps { contractAddress: ContractAddr; schema: ExecuteSchema; + initialMsg: string; + initialFunds: Coin[]; } // TODO: add initialMsg and initialFunds export const SchemaExecute = ({ contractAddress, schema, + initialMsg, + initialFunds, }: SchemaExecuteProps) => { + // ------------------------------------------// + // --------------------REF-------------------// + // ------------------------------------------// + const accordionRef = useRef(null); + // ------------------------------------------// // -------------------STATES-----------------// // ------------------------------------------// @@ -35,6 +46,33 @@ export const SchemaExecute = ({ return schema.filter((msg) => msg.title?.includes(keyword)); }, [keyword, schema]); + // ------------------------------------------// + // -------------------EFFECTS----------------// + // ------------------------------------------// + useEffect(() => { + if (schema && initialMsg && accordionRef.current) { + try { + const parsedMsg = JSON.parse(initialMsg); + const msgIndex = schema.findIndex( + (msg) => msg.schema.required?.[0] === Object.keys(parsedMsg)[0] + ); + setExpandedIndexes((prev) => + prev.includes(msgIndex) ? prev : prev.concat(msgIndex) + ); + const el = document.querySelector( + `.execute_msg_${schema[msgIndex].schema.required?.[0]}` + ); + // TODO: This is a workaround, refactor to a proper solution later + const timeoutId = setTimeout(() => el?.scrollIntoView(), 200); + return () => clearInterval(timeoutId); + } catch (_) { + // + } + } + return () => {}; + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [schema, initialMsg, accordionRef.current]); + return ( <> @@ -60,6 +98,7 @@ export const SchemaExecute = ({ {filteredMsgs?.length ? ( setExpandedIndexes(indexes)} sx={{ ".chakra-accordion__icon": { color: "gray.600" } }} > - {filteredMsgs.map((msgSchema, idx) => ( - - ))} + {filteredMsgs.map((msgSchema, idx) => { + const parsed = parseSchemaInitialData(initialMsg); + const hasPayload = + Object.keys(parsed)[0] === msgSchema.schema.required?.[0]; + + return ( + + ); + })} ) : ( +
@@ -293,7 +293,7 @@ export const SchemaQuery = ({ prev.includes(msgIndex) ? prev : prev.concat(msgIndex) ); const el = document.querySelector( - `.msg-${schema[msgIndex][0].schema.required?.[0]}` + `.query_msg_${schema[msgIndex][0].schema.required?.[0]}` ); // TODO: This is a workaround, refactor to a proper solution later const timeoutId = setTimeout(() => el?.scrollIntoView(), 200); From c7eabdddc8fef71d1b36645a47dd7a28cd1c8a2d Mon Sep 17 00:00:00 2001 From: songwongtp <16089160+songwongtp@users.noreply.github.com> Date: Tue, 22 Aug 2023 15:43:01 +0700 Subject: [PATCH 53/94] fix: drawer --- .../json-schema/EditSchemaButtons.tsx | 8 +- .../json-schema/JsonSchemaDrawer.tsx | 7 +- .../components/CommandSection.tsx | 239 +++++++++--------- 3 files changed, 129 insertions(+), 125 deletions(-) diff --git a/src/lib/components/json-schema/EditSchemaButtons.tsx b/src/lib/components/json-schema/EditSchemaButtons.tsx index 8809c68e3..77d102813 100644 --- a/src/lib/components/json-schema/EditSchemaButtons.tsx +++ b/src/lib/components/json-schema/EditSchemaButtons.tsx @@ -17,8 +17,8 @@ export const EditSchemaButtons = ({ diff --git a/src/lib/components/json-schema/JsonSchemaDrawer.tsx b/src/lib/components/json-schema/JsonSchemaDrawer.tsx index 5e7beab85..bdc665866 100644 --- a/src/lib/components/json-schema/JsonSchemaDrawer.tsx +++ b/src/lib/components/json-schema/JsonSchemaDrawer.tsx @@ -28,7 +28,12 @@ export const JsonSchemaDrawer = ({ isOpen, onClose, }: JsonSchemaDrawerProps) => ( - + diff --git a/src/lib/pages/contract-details/components/CommandSection.tsx b/src/lib/pages/contract-details/components/CommandSection.tsx index 60c007388..b38375f43 100644 --- a/src/lib/pages/contract-details/components/CommandSection.tsx +++ b/src/lib/pages/contract-details/components/CommandSection.tsx @@ -8,6 +8,7 @@ import { Text, useDisclosure, } from "@chakra-ui/react"; +import { observer } from "mobx-react-lite"; import { useInternalNavigate } from "lib/app-provider"; import { ContractCmdButton } from "lib/components/ContractCmdButton"; @@ -28,134 +29,132 @@ interface CommandSectionProps { codeId: number; } -export const CommandSection = ({ - contractAddress, - codeHash, - codeId, -}: CommandSectionProps) => { - const navigate = useInternalNavigate(); - const { isOpen, onClose, onOpen } = useDisclosure(); +export const CommandSection = observer( + ({ contractAddress, codeHash, codeId }: CommandSectionProps) => { + const navigate = useInternalNavigate(); + const { isOpen, onClose, onOpen } = useDisclosure(); - const { getSchemaByCodeHash } = useSchemaStore(); - const attached = !!getSchemaByCodeHash(codeHash); + const { getSchemaByCodeHash } = useSchemaStore(); + const attached = !!getSchemaByCodeHash(codeHash); - const { isFetching: isQueryCmdsFetching, queryCmds } = - useQueryCmds(contractAddress); - const { isFetching: isExecuteCmdsFetching, execCmds } = - useExecuteCmds(contractAddress); + const { isFetching: isQueryCmdsFetching, queryCmds } = + useQueryCmds(contractAddress); + const { isFetching: isExecuteCmdsFetching, execCmds } = + useExecuteCmds(contractAddress); - const renderCmds = ( - isFetching: boolean, - cmds: [string, string][], - type: string - ) => { - if (isFetching) { - return ; - } - if (cmds.length) { + const renderCmds = ( + isFetching: boolean, + cmds: [string, string][], + type: string + ) => { + if (isFetching) { + return ; + } + if (cmds.length) { + return ( + button": { + marginInlineStart: "0 !important", + marginInlineEnd: "1", + }, + }} + > + {cmds.sort().map(([cmd, msg]) => ( + { + navigate({ + pathname: `/${type}`, + query: { + contract: contractAddress, + msg: encode(jsonPrettify(msg)), + }, + }); + }} + /> + ))} + + ); + } return ( - button": { - marginInlineStart: "0 !important", - marginInlineEnd: "1", - }, - }} - > - {cmds.sort().map(([cmd, msg]) => ( - { - navigate({ - pathname: `/${type}`, - query: { - contract: contractAddress, - msg: encode(jsonPrettify(msg)), - }, - }); - }} - /> - ))} - + + No messages available + ); - } - return ( - - No messages available - - ); - }; + }; - return ( - - - - Available command shortcuts - - {attached ? ( - - - - Attached JSON Schema - - - - ) : ( - - - - )} - - - - - Query Shortcuts - - {renderCmds(isQueryCmdsFetching, queryCmds, "query")} + return ( + + + + Available command shortcuts + + {attached ? ( + + + + Attached JSON Schema + + + + ) : ( + + + + )} - - Execute Shortcuts - - {renderCmds(isExecuteCmdsFetching, execCmds, "execute")} + + + Query Shortcuts + + {renderCmds(isQueryCmdsFetching, queryCmds, "query")} + + + + Execute Shortcuts + + {renderCmds(isExecuteCmdsFetching, execCmds, "execute")} + + - - - ); -}; + ); + } +); From 32d88966bf266e64accd8905ae262969a2cfc5f0 Mon Sep 17 00:00:00 2001 From: evilpeach Date: Tue, 22 Aug 2023 15:45:36 +0700 Subject: [PATCH 54/94] fix: move json switch --- src/lib/pages/execute/components/ExecuteArea.tsx | 4 ++-- src/lib/pages/query/components/QueryArea.tsx | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/lib/pages/execute/components/ExecuteArea.tsx b/src/lib/pages/execute/components/ExecuteArea.tsx index 6065728d7..777d36292 100644 --- a/src/lib/pages/execute/components/ExecuteArea.tsx +++ b/src/lib/pages/execute/components/ExecuteArea.tsx @@ -42,8 +42,8 @@ export const ExecuteArea = ({ return ( - - + + Execute Message - - + + Query Message Date: Tue, 22 Aug 2023 15:47:45 +0700 Subject: [PATCH 55/94] fix: as comments --- src/lib/pages/execute/components/ExecuteArea.tsx | 4 +--- src/lib/pages/query/components/QueryArea.tsx | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/lib/pages/execute/components/ExecuteArea.tsx b/src/lib/pages/execute/components/ExecuteArea.tsx index 777d36292..e491f5d76 100644 --- a/src/lib/pages/execute/components/ExecuteArea.tsx +++ b/src/lib/pages/execute/components/ExecuteArea.tsx @@ -35,9 +35,7 @@ export const ExecuteArea = ({ useEffect(() => { if (!schema) setTab(MessageTabs.JSON_INPUT); - else { - setTab(MessageTabs.YOUR_SCHEMA); - } + else setTab(MessageTabs.YOUR_SCHEMA); }, [schema]); return ( diff --git a/src/lib/pages/query/components/QueryArea.tsx b/src/lib/pages/query/components/QueryArea.tsx index bdc0f8c56..39c117f40 100644 --- a/src/lib/pages/query/components/QueryArea.tsx +++ b/src/lib/pages/query/components/QueryArea.tsx @@ -32,9 +32,7 @@ export const QueryArea = ({ useEffect(() => { if (!schema) setTab(MessageTabs.JSON_INPUT); - else { - setTab(MessageTabs.YOUR_SCHEMA); - } + else setTab(MessageTabs.YOUR_SCHEMA); }, [schema]); return ( From 23849cedaff66a40477c20bbd6b4d2ea9a0af9d2 Mon Sep 17 00:00:00 2001 From: songwongtp <16089160+songwongtp@users.noreply.github.com> Date: Tue, 22 Aug 2023 16:10:20 +0700 Subject: [PATCH 56/94] fix: use Boolean --- src/lib/pages/contract-details/components/CommandSection.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/pages/contract-details/components/CommandSection.tsx b/src/lib/pages/contract-details/components/CommandSection.tsx index b38375f43..7e5fc6ab6 100644 --- a/src/lib/pages/contract-details/components/CommandSection.tsx +++ b/src/lib/pages/contract-details/components/CommandSection.tsx @@ -35,7 +35,7 @@ export const CommandSection = observer( const { isOpen, onClose, onOpen } = useDisclosure(); const { getSchemaByCodeHash } = useSchemaStore(); - const attached = !!getSchemaByCodeHash(codeHash); + const attached = Boolean(getSchemaByCodeHash(codeHash)); const { isFetching: isQueryCmdsFetching, queryCmds } = useQueryCmds(contractAddress); From 75f04bbd9f8783f5a815af5333b942ff1428f639 Mon Sep 17 00:00:00 2001 From: poomthiti Date: Tue, 22 Aug 2023 16:24:22 +0700 Subject: [PATCH 57/94] fix: merge conflict --- CHANGELOG.md | 17 + package.json | 17 +- src/config/chain/default.ts | 5 + src/config/chain/index.ts | 2 + src/config/chain/neutron.ts | 14 +- src/config/chain/osmosis.ts | 25 +- src/config/chain/sei.ts | 26 +- src/config/chain/stargaze.ts | 51 +- src/config/chain/terra.ts | 92 + src/config/chain/types.ts | 17 + src/env.ts | 3 + src/lib/app-provider/contexts/app.tsx | 11 +- src/lib/app-provider/hooks/useConfig.ts | 14 + src/lib/app-provider/hooks/useCurrentChain.ts | 1 + src/lib/app-provider/queries/simulateFee.ts | 2 +- src/lib/app-provider/tx/upload.ts | 2 +- src/lib/chain-registry/terra2testnet.ts | 122 + src/lib/components/Chakra.tsx | 12 - src/lib/components/ExplorerLink.tsx | 1 - src/lib/components/PrimaryNameMark.tsx | 2 +- src/lib/components/TxFilterSelection.tsx | 3 +- src/lib/components/action-msg/MsgToken.tsx | 2 +- .../action-msg/MultipleActionsMsg.tsx | 2 +- src/lib/components/action-msg/SingleMsg.tsx | 11 +- .../components/button/NewProposalButton.tsx | 27 +- .../components/forms/FilterByPermission.tsx | 6 +- src/lib/components/modal/CodeSnippet.tsx | 24 +- src/lib/components/pagination/Next.tsx | 3 +- .../table/transactions/TransactionsTable.tsx | 4 +- .../transactions/TransactionsTableRow.tsx | 2 +- src/lib/components/tx/TxReceiptRender.tsx | 8 +- .../upload/InstantiatePermissionRadio.tsx | 155 +- src/lib/components/upload/UploadSection.tsx | 18 +- src/lib/layout/SubHeader.tsx | 33 +- src/lib/layout/navbar/Expand.tsx | 2 +- src/lib/layout/navbar/index.tsx | 6 +- .../components/AccountHeader.tsx | 34 +- .../pages/blocks/components/BlocksTable.tsx | 6 +- .../components/tables/TxsTable.tsx | 8 +- src/lib/pages/contract-details/index.tsx | 4 +- src/lib/pages/home/components/DevShortcut.tsx | 4 +- .../components/MySavedCodesSection.tsx | 36 - .../components/MyStoredCodesSection.tsx | 61 - src/lib/pages/my-codes/index.tsx | 138 -- .../components/pool-details/header/index.tsx | 9 +- .../tables/pool-txs/PoolTxsMsg.tsx | 2 +- .../tables/pool-txs/PoolTxsTable.tsx | 2 +- .../messages/lp/components/PoolAssetsGrid.tsx | 2 +- .../messages/swap/components/PoolSwap.tsx | 2 +- .../tables/pool-txs/messages/utils.ts | 11 - src/lib/pages/pools/poolId.tsx | 2 - src/lib/pages/proposals/index.tsx | 7 +- .../components/MySavedCodesSection.tsx | 24 + .../components/SaveCodeButton.tsx | 0 src/lib/pages/saved-codes/index.tsx | 99 + .../components/DeployButton.tsx | 0 .../components/MyStoredCodesSection.tsx | 29 + .../components/ProposalButton.tsx | 0 .../components/UploadButton.tsx | 0 src/lib/pages/stored-codes/index.tsx | 134 ++ .../components/tx-message/EventBox.tsx | 55 +- .../components/tx-message/TxMsgExpand.tsx | 4 +- src/lib/providers/amplitude.tsx | 16 + src/lib/providers/chakra.tsx | 7 + src/lib/providers/cosmos-kit.tsx | 57 + src/lib/providers/index.tsx | 24 + src/lib/providers/query-client.tsx | 11 + src/lib/services/faucetService.ts | 2 +- src/lib/services/validatorService.ts | 4 +- src/lib/types/tx/msg.ts | 2 +- src/lib/utils/funds.test.ts | 32 +- src/lib/utils/funds.ts | 13 +- src/lib/utils/tx/composeMsg.ts | 2 +- src/pages/[network]/my-codes.tsx | 3 - src/pages/[network]/saved-codes.tsx | 3 + src/pages/[network]/stored-codes.tsx | 3 + src/pages/_app.tsx | 105 +- src/pages/_document.tsx | 17 +- src/pages/my-codes.tsx | 3 - src/pages/saved-codes.tsx | 3 + src/pages/stored-codes.tsx | 3 + yarn.lock | 2043 ++++++----------- 82 files changed, 1916 insertions(+), 1852 deletions(-) create mode 100644 src/config/chain/terra.ts create mode 100644 src/lib/chain-registry/terra2testnet.ts delete mode 100644 src/lib/components/Chakra.tsx delete mode 100644 src/lib/pages/my-codes/components/MySavedCodesSection.tsx delete mode 100644 src/lib/pages/my-codes/components/MyStoredCodesSection.tsx delete mode 100644 src/lib/pages/my-codes/index.tsx create mode 100644 src/lib/pages/saved-codes/components/MySavedCodesSection.tsx rename src/lib/pages/{my-codes => saved-codes}/components/SaveCodeButton.tsx (100%) create mode 100644 src/lib/pages/saved-codes/index.tsx rename src/lib/pages/{my-codes => stored-codes}/components/DeployButton.tsx (100%) create mode 100644 src/lib/pages/stored-codes/components/MyStoredCodesSection.tsx rename src/lib/pages/{my-codes => stored-codes}/components/ProposalButton.tsx (100%) rename src/lib/pages/{my-codes => stored-codes}/components/UploadButton.tsx (100%) create mode 100644 src/lib/pages/stored-codes/index.tsx create mode 100644 src/lib/providers/amplitude.tsx create mode 100644 src/lib/providers/chakra.tsx create mode 100644 src/lib/providers/cosmos-kit.tsx create mode 100644 src/lib/providers/index.tsx create mode 100644 src/lib/providers/query-client.tsx delete mode 100644 src/pages/[network]/my-codes.tsx create mode 100644 src/pages/[network]/saved-codes.tsx create mode 100644 src/pages/[network]/stored-codes.tsx delete mode 100644 src/pages/my-codes.tsx create mode 100644 src/pages/saved-codes.tsx create mode 100644 src/pages/stored-codes.tsx diff --git a/CHANGELOG.md b/CHANGELOG.md index 5a9a0266d..d60fa3b34 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -48,6 +48,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - [#461](https://github.com/alleslabs/celatone-frontend/pull/461) Add json schema form - [#455](https://github.com/alleslabs/celatone-frontend/pull/455) Implement schema store and unit test - [#453](https://github.com/alleslabs/celatone-frontend/pull/453) Attach schema feature on upload complete +- [#481](https://github.com/alleslabs/celatone-frontend/pull/481) Support Stargaze testnet +- [#471](https://github.com/alleslabs/celatone-frontend/pull/471) Add proposal config, use Hasura admin secret +- [#467](https://github.com/alleslabs/celatone-frontend/pull/467) Dynamic wallet by network, add disableAnyofAddress config - [#322](https://github.com/alleslabs/celatone-frontend/pull/322) Tab url path for account details and public project details pages - [#449](https://github.com/alleslabs/celatone-frontend/pull/449) Support searching with pool id - [#419](https://github.com/alleslabs/celatone-frontend/pull/419) Add error message box for tx failed modal and enhance styling @@ -60,6 +63,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - [#491](https://github.com/alleslabs/celatone-frontend/pull/491) Improve scrolling into view by delaying scroll function - [#489](https://github.com/alleslabs/celatone-frontend/pull/489) Improve jsonschema query response UI and fix jsonschema incorrect oneOf behavior +- [#484](https://github.com/alleslabs/celatone-frontend/pull/484) Fix text size consistency in txs message +- [#480](https://github.com/alleslabs/celatone-frontend/pull/480) Update chain registry package and add attach funds in code snippet +- [#478](https://github.com/alleslabs/celatone-frontend/pull/478) Fix pool txs icon and style +- [#474](https://github.com/alleslabs/celatone-frontend/pull/474) Refactor stored and saved codes pages +- [#468](https://github.com/alleslabs/celatone-frontend/pull/468) Add breadcrumb to pool id page +- [#466](https://github.com/alleslabs/celatone-frontend/pull/466) Fix developer mode alert - [#457](https://github.com/alleslabs/celatone-frontend/pull/457) Add alert for proposal forum review - [#389](https://github.com/alleslabs/celatone-frontend/pull/389) Fix modal consistency - [#381](https://github.com/alleslabs/celatone-frontend/pull/381) Correctly infer output type from snake-camel utils @@ -77,6 +86,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Bug fixes - [#470](https://github.com/alleslabs/celatone-frontend/pull/470) Fix json schema array field default behavior +- [#476](https://github.com/alleslabs/celatone-frontend/pull/476) Fix terra rpc +- [#473](https://github.com/alleslabs/celatone-frontend/pull/473) Fix wording on upload code modal +- [#465](https://github.com/alleslabs/celatone-frontend/pull/465) Fix wrong access queryKey in validator info +- [#464](https://github.com/alleslabs/celatone-frontend/pull/464) Fix `useFaucetInfo` hook by adding `assetInfos` to its dependencies +- [#463](https://github.com/alleslabs/celatone-frontend/pull/463) Fix event box content clipping and improve animation +- [#462](https://github.com/alleslabs/celatone-frontend/pull/462) Fix validator query dependencies +- [#460](https://github.com/alleslabs/celatone-frontend/pull/460) Fix icns names and contract address alignment +- [#459](https://github.com/alleslabs/celatone-frontend/pull/459) Fix contract txs by using contract account id instead of contract address - [#456](https://github.com/alleslabs/celatone-frontend/pull/456) Fix pool count chip in pool transaction table - [#454](https://github.com/alleslabs/celatone-frontend/pull/454) Fix contract selection loading state for other folders - [#452](https://github.com/alleslabs/celatone-frontend/pull/452) Fix public project data on the account details and code details page still remains when switching network diff --git a/package.json b/package.json index 95aa4476a..4852dfebf 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,6 @@ { "name": "celatone", - "version": "1.0.5", - "private": true, + "version": "1.1.0", "author": "Alles Labs", "scripts": { "dev": "next dev", @@ -25,16 +24,20 @@ "@chakra-ui/anatomy": "^2.1.0", "@chakra-ui/card": "^2.1.1", "@chakra-ui/icons": "^2.0.11", - "@chakra-ui/react": "^2.3.6", + "@chakra-ui/react": "2.3.6", "@chakra-ui/styled-system": "^2.3.5", "@cosmjs/cosmwasm-stargate": "^0.30.1", "@cosmjs/crypto": "^0.30.1", "@cosmjs/encoding": "^0.30.1", "@cosmjs/proto-signing": "^0.30.1", "@cosmjs/stargate": "^0.30.1", - "@cosmos-kit/core": "^1.5.8", - "@cosmos-kit/keplr": "^0.33.38", - "@cosmos-kit/react": "^1.3.31", + "@cosmos-kit/compass": "^2.1.6", + "@cosmos-kit/core": "2.2.1", + "@cosmos-kit/keplr": "2.1.6", + "@cosmos-kit/react": "2.2.1", + "@cosmos-kit/station": "2.1.6", + "@emotion/react": "^11", + "@emotion/styled": "^11", "@graphql-codegen/cli": "^2.13.12", "@graphql-codegen/client-preset": "^1.1.4", "@rjsf/chakra-ui": "v5.0.0-beta.10", @@ -51,7 +54,7 @@ "axios": "^1.1.3", "big.js": "^6.2.1", "camelcase": "^7.0.0", - "chain-registry": "^1.14.0", + "chain-registry": "^1.19.0", "chakra-react-select": "^4.7.0", "cosmjs-types": "^0.7.2", "dayjs": "^1.11.6", diff --git a/src/config/chain/default.ts b/src/config/chain/default.ts index 88f48e3f8..f2e899988 100644 --- a/src/config/chain/default.ts +++ b/src/config/chain/default.ts @@ -8,6 +8,7 @@ export const DEFAULT_CHAIN_CONFIG: ChainConfig = { rpc: "", indexer: "", api: "", + wallets: [], features: { faucet: { enabled: false, @@ -21,6 +22,9 @@ export const DEFAULT_CHAIN_CONFIG: ChainConfig = { publicProject: { enabled: false, }, + gov: { + enabled: false, + }, }, gas: { gasPrice: { @@ -34,4 +38,5 @@ export const DEFAULT_CHAIN_CONFIG: ChainConfig = { validator: "", proposal: "", }, + extra: {}, }; diff --git a/src/config/chain/index.ts b/src/config/chain/index.ts index 8810a3d05..6299e2761 100644 --- a/src/config/chain/index.ts +++ b/src/config/chain/index.ts @@ -2,6 +2,7 @@ import { NEUTRON_CHAIN_CONFIGS } from "./neutron"; import { OSMOSIS_CHAIN_CONFIGS } from "./osmosis"; import { SEI_CHAIN_CONFIGS } from "./sei"; import { STARGAZE_CHAIN_CONFIGS } from "./stargaze"; +import { TERRA_CHAIN_CONFIGS } from "./terra"; import type { ChainConfigs } from "./types"; export * from "./types"; @@ -12,4 +13,5 @@ export const CHAIN_CONFIGS: ChainConfigs = { ...SEI_CHAIN_CONFIGS, ...NEUTRON_CHAIN_CONFIGS, ...STARGAZE_CHAIN_CONFIGS, + ...TERRA_CHAIN_CONFIGS, }; diff --git a/src/config/chain/neutron.ts b/src/config/chain/neutron.ts index bd6480bc8..455cd693c 100644 --- a/src/config/chain/neutron.ts +++ b/src/config/chain/neutron.ts @@ -1,3 +1,5 @@ +import { wallets as keplrWallets } from "@cosmos-kit/keplr"; + import type { ChainConfigs } from "./types"; export const NEUTRON_CHAIN_CONFIGS: ChainConfigs = { @@ -6,9 +8,10 @@ export const NEUTRON_CHAIN_CONFIGS: ChainConfigs = { registryChainName: "neutron", prettyName: "Neutron", lcd: "https://rest-kralum.neutron-1.neutron.org", - rpc: "https://rpc-kralum.neutron-1.neutron.org", + rpc: "https://rpc-kralum.neutron-1.neutron.org:443", indexer: "https://neutron-1-graphql.alleslabs.dev/v1/graphql", api: "https://celatone-api.alleslabs.dev", + wallets: [...keplrWallets], features: { faucet: { enabled: false, @@ -24,6 +27,9 @@ export const NEUTRON_CHAIN_CONFIGS: ChainConfigs = { publicProject: { enabled: true, }, + gov: { + enabled: true, + }, }, gas: { gasPrice: { @@ -37,6 +43,7 @@ export const NEUTRON_CHAIN_CONFIGS: ChainConfigs = { validator: "https://www.mintscan.io/neutron/validators", proposal: "", }, + extra: {}, }, "pion-1": { chain: "neutron", @@ -46,6 +53,7 @@ export const NEUTRON_CHAIN_CONFIGS: ChainConfigs = { rpc: "https://rpc-palvus.pion-1.ntrn.tech:443", indexer: "https://pion-1-graphql.alleslabs.dev/v1/graphql", api: "https://celatone-api.alleslabs.dev", + wallets: [...keplrWallets], features: { faucet: { enabled: false, @@ -61,6 +69,9 @@ export const NEUTRON_CHAIN_CONFIGS: ChainConfigs = { publicProject: { enabled: false, }, + gov: { + enabled: true, + }, }, gas: { gasPrice: { @@ -74,5 +85,6 @@ export const NEUTRON_CHAIN_CONFIGS: ChainConfigs = { validator: "https://www.mintscan.io/neutron/validators", proposal: "", }, + extra: {}, }, }; diff --git a/src/config/chain/osmosis.ts b/src/config/chain/osmosis.ts index 89b8dcce9..457c258c2 100644 --- a/src/config/chain/osmosis.ts +++ b/src/config/chain/osmosis.ts @@ -1,3 +1,5 @@ +import { wallets as keplrWallets } from "@cosmos-kit/keplr"; + import type { ChainConfigs } from "./types"; export const OSMOSIS_CHAIN_CONFIGS: ChainConfigs = { @@ -6,9 +8,10 @@ export const OSMOSIS_CHAIN_CONFIGS: ChainConfigs = { registryChainName: "osmosis", prettyName: "Osmosis", lcd: "https://lcd.osmosis.zone", - rpc: "https://rpc.osmosis.zone", + rpc: "https://rpc.osmosis.zone:443", indexer: "https://osmosis-mainnet-graphql.alleslabs.dev/v1/graphql", api: "https://celatone-api.alleslabs.dev", + wallets: [...keplrWallets], features: { faucet: { enabled: false, @@ -25,6 +28,9 @@ export const OSMOSIS_CHAIN_CONFIGS: ChainConfigs = { publicProject: { enabled: true, }, + gov: { + enabled: true, + }, }, gas: { gasPrice: { @@ -38,15 +44,17 @@ export const OSMOSIS_CHAIN_CONFIGS: ChainConfigs = { validator: "https://www.mintscan.io/osmosis/validators", proposal: "https://www.mintscan.io/osmosis/proposals", }, + extra: {}, }, "osmo-test-5": { chain: "osmosis", - registryChainName: "osmosistestnet5", + registryChainName: "osmosistestnet", prettyName: "Osmosis Testnet", lcd: "https://lcd.osmotest5.osmosis.zone", - rpc: "https://rpc.osmotest5.osmosis.zone", + rpc: "https://rpc.osmotest5.osmosis.zone:443", indexer: "https://osmo-test-5-graphql.alleslabs.dev/v1/graphql", api: "https://celatone-api.alleslabs.dev", + wallets: [...keplrWallets], features: { faucet: { enabled: true, @@ -64,6 +72,9 @@ export const OSMOSIS_CHAIN_CONFIGS: ChainConfigs = { publicProject: { enabled: false, }, + gov: { + enabled: true, + }, }, gas: { gasPrice: { @@ -77,15 +88,17 @@ export const OSMOSIS_CHAIN_CONFIGS: ChainConfigs = { validator: "https://testnet.mintscan.io/osmosis-testnet/validators", proposal: "https://testnet.mintscan.io/osmosis-testnet/proposals", }, + extra: {}, }, localosmosis: { chain: "osmosis", registryChainName: "localosmosis", prettyName: "Local Osmosis", lcd: "http://localhost/rest", - rpc: "http://localhost/rpc/", + rpc: "http://localhost:80/rpc/", indexer: "http://localhost/hasura/v1/graphql", api: "http://localhost/api", + wallets: [...keplrWallets], features: { faucet: { enabled: true, @@ -102,6 +115,9 @@ export const OSMOSIS_CHAIN_CONFIGS: ChainConfigs = { publicProject: { enabled: false, }, + gov: { + enabled: true, + }, }, gas: { gasPrice: { @@ -115,5 +131,6 @@ export const OSMOSIS_CHAIN_CONFIGS: ChainConfigs = { validator: "", proposal: "", }, + extra: {}, }, }; diff --git a/src/config/chain/sei.ts b/src/config/chain/sei.ts index 5044cc546..800985ca7 100644 --- a/src/config/chain/sei.ts +++ b/src/config/chain/sei.ts @@ -1,14 +1,23 @@ +import { wallets as compassWallets } from "@cosmos-kit/compass"; +import { wallets as keplrWallets } from "@cosmos-kit/keplr"; + import type { ChainConfigs } from "./types"; +/** + * @remarks + * Because Sei utilizes Cosmos SDK v0.26, which lacks the anyOfAddresses feature, we need to disable it. + * We already have disabled only normal upload section, not proposal to store code section. + */ export const SEI_CHAIN_CONFIGS: ChainConfigs = { "pacific-1": { chain: "sei", registryChainName: "sei", prettyName: "Sei", lcd: "https://sei-api.polkachu.com", - rpc: "https://sei-rpc.polkachu.com", + rpc: "https://sei-rpc.polkachu.com:443", indexer: "https://pacific-1-graphql.alleslabs.dev/v1/graphql", api: "https://celatone-api.alleslabs.dev", + wallets: [...compassWallets, ...keplrWallets], features: { faucet: { enabled: false, @@ -24,6 +33,9 @@ export const SEI_CHAIN_CONFIGS: ChainConfigs = { publicProject: { enabled: true, }, + gov: { + enabled: false, + }, }, gas: { gasPrice: { @@ -37,15 +49,19 @@ export const SEI_CHAIN_CONFIGS: ChainConfigs = { validator: "", proposal: "", }, + extra: { + disableAnyOfAddresses: true, + }, }, "atlantic-2": { chain: "sei", registryChainName: "seitestnet2", prettyName: "Sei Testnet2", lcd: "https://rest.atlantic-2.seinetwork.io", - rpc: "https://rpc.atlantic-2.seinetwork.io", + rpc: "https://rpc.atlantic-2.seinetwork.io:443", indexer: "https://atlantic-2-graphql.alleslabs.dev/v1/graphql", api: "https://celatone-api.alleslabs.dev", + wallets: [...compassWallets, ...keplrWallets], features: { faucet: { enabled: false, @@ -61,6 +77,9 @@ export const SEI_CHAIN_CONFIGS: ChainConfigs = { publicProject: { enabled: false, }, + gov: { + enabled: false, + }, }, gas: { gasPrice: { @@ -74,5 +93,8 @@ export const SEI_CHAIN_CONFIGS: ChainConfigs = { validator: "https://testnet.mintscan.io/sei-testnet/validators", proposal: "https://testnet.mintscan.io/sei-testnet/proposals", }, + extra: { + disableAnyOfAddresses: true, + }, }, }; diff --git a/src/config/chain/stargaze.ts b/src/config/chain/stargaze.ts index e1a013a15..189f55da7 100644 --- a/src/config/chain/stargaze.ts +++ b/src/config/chain/stargaze.ts @@ -1,3 +1,5 @@ +import { wallets as keplrWallets } from "@cosmos-kit/keplr"; + import type { ChainConfigs } from "./types"; export const STARGAZE_CHAIN_CONFIGS: ChainConfigs = { @@ -6,9 +8,10 @@ export const STARGAZE_CHAIN_CONFIGS: ChainConfigs = { registryChainName: "stargaze", prettyName: "Stargaze", lcd: "https://rest.stargaze-apis.com", - rpc: "https://rpc.stargaze-apis.com", + rpc: "https://rpc.stargaze-apis.com:443", indexer: "https://stargaze-mainnet-graphql.alleslabs.dev/v1/graphql", api: "https://celatone-api.alleslabs.dev", + wallets: [...keplrWallets], features: { faucet: { enabled: false, @@ -24,6 +27,9 @@ export const STARGAZE_CHAIN_CONFIGS: ChainConfigs = { publicProject: { enabled: true, }, + gov: { + enabled: true, + }, }, gas: { gasPrice: { @@ -37,5 +43,48 @@ export const STARGAZE_CHAIN_CONFIGS: ChainConfigs = { validator: "https://www.mintscan.io/stargaze/validators", proposal: "https://www.mintscan.io/stargaze/proposals", }, + extra: {}, + }, + "elgafar-1": { + chain: "stargaze", + registryChainName: "stargazetestnet", + prettyName: "Stargaze Testnet", + lcd: "https://rest.elgafar-1.stargaze-apis.com", + rpc: "https://rpc.elgafar-1.stargaze-apis.com", + indexer: "https://elgafar-1-graphql.alleslabs.dev/v1/graphql", + api: "https://celatone-api.alleslabs.dev", + wallets: [...keplrWallets], + features: { + faucet: { + enabled: false, + }, + wasm: { + enabled: true, + storeCodeMaxFileSize: 800_000, + clearAdminGas: 50_000, + }, + pool: { + enabled: false, + }, + publicProject: { + enabled: true, + }, + gov: { + enabled: true, + }, + }, + gas: { + gasPrice: { + tokenPerGas: 0.04, + denom: "ustars", + }, + gasAdjustment: 1.5, + maxGasLimit: 50_000_000, + }, + explorerLink: { + validator: "https://testnet-explorer.publicawesome.dev/stargaze/staking", + proposal: "https://testnet-explorer.publicawesome.dev/stargaze/gov", + }, + extra: {}, }, }; diff --git a/src/config/chain/terra.ts b/src/config/chain/terra.ts new file mode 100644 index 000000000..35d39106b --- /dev/null +++ b/src/config/chain/terra.ts @@ -0,0 +1,92 @@ +import { wallets as keplrWallets } from "@cosmos-kit/keplr"; + +import type { ChainConfigs } from "./types"; + +export const TERRA_CHAIN_CONFIGS: ChainConfigs = { + "phoenix-1": { + chain: "terra", + registryChainName: "terra2", + prettyName: "Terra", + lcd: "https://phoenix-lcd.terra.dev:443", + rpc: "https://terra2-rpc.lavenderfive.com:443", + indexer: "https://phoenix-1-graphql.alleslabs.dev/v1/graphql", + api: "https://celatone-api.alleslabs.dev", + wallets: [...keplrWallets], + features: { + faucet: { + enabled: false, + }, + wasm: { + enabled: true, + storeCodeMaxFileSize: 800_000, + clearAdminGas: 50_000, + }, + pool: { + enabled: false, + }, + publicProject: { + enabled: true, + }, + gov: { + enabled: true, + disableOpenProposal: true, + }, + }, + gas: { + gasPrice: { + tokenPerGas: 0.0125, + denom: "uluna", + }, + gasAdjustment: 1.5, + maxGasLimit: 25_000_000, + }, + explorerLink: { + validator: "https://finder.terra.money/mainnet/validator", + proposal: "https://station.terra.money/proposal/phoenix-1", + }, + extra: {}, + }, + "pisco-1": { + chain: "terra", + registryChainName: "terra2testnet", + prettyName: "Terra Testnet", + lcd: "https://pisco-lcd.terra.dev:443", + rpc: "https://terra-testnet-rpc.polkachu.com:443", + indexer: "https://pisco-1-graphql.alleslabs.dev/v1/graphql", + api: "https://celatone-api.alleslabs.dev", + wallets: [...keplrWallets], + features: { + faucet: { + enabled: false, + }, + wasm: { + enabled: true, + storeCodeMaxFileSize: 800_000, + clearAdminGas: 50_000, + }, + pool: { + enabled: false, + }, + publicProject: { + enabled: false, + }, + gov: { + enabled: true, + disableOpenProposal: true, + }, + }, + gas: { + gasPrice: { + tokenPerGas: 0.0125, + denom: "uluna", + }, + gasAdjustment: 1.5, + maxGasLimit: 25_000_000, + }, + explorerLink: { + validator: "https://finder.terra.money/testnet/validator", + proposal: "https://station.terra.money/proposal/pisco-1", + }, + extra: {}, + }, +}; diff --git a/src/config/chain/types.ts b/src/config/chain/types.ts index 5f200cd54..a2df8bade 100644 --- a/src/config/chain/types.ts +++ b/src/config/chain/types.ts @@ -1,3 +1,5 @@ +import type { MainWalletBase } from "@cosmos-kit/core"; + type FaucetConfig = | { enabled: true; @@ -24,6 +26,16 @@ type PoolConfig = type PublicProjectConfig = { enabled: boolean }; +type GovConfig = + | { + enabled: true; + disableOpenProposal?: boolean; + disableStoreCodeProposal?: boolean; + } + | { + enabled: false; + }; + export interface ExplorerConfig { validator: string; proposal: string; @@ -37,11 +49,13 @@ export interface ChainConfig { rpc: string; indexer: string; api: string; + wallets: MainWalletBase[]; features: { faucet: FaucetConfig; wasm: WasmConfig; pool: PoolConfig; publicProject: PublicProjectConfig; + gov: GovConfig; }; gas: { gasPrice: { @@ -52,6 +66,9 @@ export interface ChainConfig { maxGasLimit: number; }; explorerLink: ExplorerConfig; + extra: { + disableAnyOfAddresses?: boolean; + }; } export interface ChainConfigs { diff --git a/src/env.ts b/src/env.ts index edd7d9c21..6ad0eb6d9 100644 --- a/src/env.ts +++ b/src/env.ts @@ -40,3 +40,6 @@ export const CURR_THEME = (() => { return DEFAULT_THEME; } })(); + +export const HASURA_ADMIN_SECRET = + process.env.NEXT_PUBLIC_HASURA_ADMIN_SECRET ?? ""; diff --git a/src/lib/app-provider/contexts/app.tsx b/src/lib/app-provider/contexts/app.tsx index d0870a9fb..cc66c6315 100644 --- a/src/lib/app-provider/contexts/app.tsx +++ b/src/lib/app-provider/contexts/app.tsx @@ -11,13 +11,12 @@ import { createContext, } from "react"; -import { useAmplitude } from "../hooks/useAmplitude"; import { useNetworkChange } from "../hooks/useNetworkChange"; import { CHAIN_CONFIGS, DEFAULT_CHAIN_CONFIG } from "config/chain"; import type { ChainConfig } from "config/chain"; import { PROJECT_CONSTANTS } from "config/project"; import type { ProjectConstants } from "config/project"; -import { SUPPORTED_CHAIN_IDS } from "env"; +import { HASURA_ADMIN_SECRET, SUPPORTED_CHAIN_IDS } from "env"; import { LoadingOverlay } from "lib/components/LoadingOverlay"; import { NetworkErrorState } from "lib/components/state/NetworkErrorState"; import { DEFAULT_ADDRESS } from "lib/data"; @@ -71,7 +70,11 @@ export const AppProvider = observer(({ children }: AppProviderProps) => { availableChainIds: SUPPORTED_CHAIN_IDS, currentChainId, chainConfig, - indexerGraphClient: new GraphQLClient(chainConfig.indexer), + indexerGraphClient: new GraphQLClient(chainConfig.indexer, { + headers: { + "x-hasura-admin-secret": HASURA_ADMIN_SECRET, + }, + }), constants: PROJECT_CONSTANTS, }; }, [currentChainId]); @@ -103,8 +106,6 @@ export const AppProvider = observer(({ children }: AppProviderProps) => { useNetworkChange(handleOnChainIdChange); - useAmplitude(currentChainName); - if (currentChainId && !(currentChainId in CHAIN_CONFIGS)) return ; diff --git a/src/lib/app-provider/hooks/useConfig.ts b/src/lib/app-provider/hooks/useConfig.ts index ff36d189b..8fe3e31ed 100644 --- a/src/lib/app-provider/hooks/useConfig.ts +++ b/src/lib/app-provider/hooks/useConfig.ts @@ -79,3 +79,17 @@ export const usePublicProjectConfig = ({ return useBaseConfig({ feature: publicProject, shouldRedirect }); }; + +export const useGovConfig = ({ + shouldRedirect, +}: { + shouldRedirect: boolean; +}) => { + const { + chainConfig: { + features: { gov }, + }, + } = useCelatoneApp(); + + return useBaseConfig({ feature: gov, shouldRedirect }); +}; diff --git a/src/lib/app-provider/hooks/useCurrentChain.ts b/src/lib/app-provider/hooks/useCurrentChain.ts index c961c3fc2..68c233780 100644 --- a/src/lib/app-provider/hooks/useCurrentChain.ts +++ b/src/lib/app-provider/hooks/useCurrentChain.ts @@ -6,5 +6,6 @@ export const useCurrentChain = () => { const { chainConfig: { registryChainName }, } = useCelatoneApp(); + return useChain(registryChainName); }; diff --git a/src/lib/app-provider/queries/simulateFee.ts b/src/lib/app-provider/queries/simulateFee.ts index a77d1d009..e41b1e65b 100644 --- a/src/lib/app-provider/queries/simulateFee.ts +++ b/src/lib/app-provider/queries/simulateFee.ts @@ -78,7 +78,7 @@ interface SimulateQueryParamsForStoreCode { enabled: boolean; wasmFile: Option; permission: AccessType; - addresses: Addr[]; + addresses?: Addr[]; onSuccess?: (gas: Gas | undefined) => void; onError?: (err: Error) => void; } diff --git a/src/lib/app-provider/tx/upload.ts b/src/lib/app-provider/tx/upload.ts index 57ee35d98..9718212f0 100644 --- a/src/lib/app-provider/tx/upload.ts +++ b/src/lib/app-provider/tx/upload.ts @@ -20,7 +20,7 @@ export type UploadSucceedCallback = (txResult: UploadTxInternalResult) => void; export interface UploadStreamParams { wasmFileName: Option; wasmCode: Option>; - addresses: Addr[]; + addresses?: Addr[]; permission: AccessType; codeName: string; estimatedFee: Option; diff --git a/src/lib/chain-registry/terra2testnet.ts b/src/lib/chain-registry/terra2testnet.ts new file mode 100644 index 000000000..2ab63dbcf --- /dev/null +++ b/src/lib/chain-registry/terra2testnet.ts @@ -0,0 +1,122 @@ +import type { Chain, AssetList } from "@chain-registry/types"; + +export const terra2testnet: Chain = { + $schema: "../../chain.schema.json", + chain_name: "terra2testnet", + status: "live", + network_type: "testnet", + website: "https://www.terra.money/", + pretty_name: "Terra 2.0", + chain_id: "pisco-1", + daemon_name: "terrad", + node_home: "$HOME/.terra", + bech32_prefix: "terra", + slip44: 330, + fees: { + fee_tokens: [ + { + denom: "uluna", + fixed_min_gas_price: 0.0125, + low_gas_price: 0.0125, + average_gas_price: 0.015, + high_gas_price: 0.04, + }, + ], + }, + staking: { + staking_tokens: [ + { + denom: "uluna", + }, + ], + }, + peers: { + seeds: [ + { + id: "3bfc40d3d7f14b59c5943bf2d45ce103d42174c5", + address: "seed-terra-testnet.moonshot.army:26655", + provider: "Moonshot Army", + }, + { + id: "ade4d8bc8cbe014af6ebdf3cb7b1e9ad36f412c0", + address: "testnet-seeds.polkachu.com:11756", + provider: "Polkachu", + }, + ], + persistent_peers: [ + { + id: "0d194f5236a420147b05d9556ac0cf928c36e647", + address: "65.109.23.114:11756", + provider: "Polkachu", + }, + { + id: "5cc5e6506818a113387d92e0b60a7206845b4d7e", + address: "pisco-1-sentinel.skip.money:26656", + provider: "Skip.Money", + }, + ], + }, + apis: { + rpc: [ + { + address: "https://pisco-rpc.terra.dev:443", + provider: "Terraform Labs", + }, + { + address: "https://terra-testnet-rpc.polkachu.com:443", + provider: "Polkachu", + }, + ], + rest: [ + { + address: "https://pisco-lcd.terra.dev:443", + provider: "Terraform Labs", + }, + { + address: "https://terra-testnet-api.polkachu.com:443", + provider: "Polkachu", + }, + ], + grpc: [ + { + address: "terra-testnet-grpc.polkachu.com:11790", + provider: "Polkachu", + }, + ], + }, + explorers: [ + { + kind: "finder", + url: "http://finder.terra.money/testnet/", + }, + ], +}; + +export const terra2testnetAssets: AssetList = { + $schema: "../../assetlist.schema.json", + chain_name: "terra2testnet", + assets: [ + { + description: "The native staking token of Terra.", + denom_units: [ + { + denom: "uluna", + exponent: 0, + }, + { + denom: "luna", + exponent: 6, + }, + ], + base: "uluna", + name: "Luna", + display: "luna", + symbol: "LUNA", + logo_URIs: { + svg: "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra2/images/luna.svg", + png: "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra2/images/luna.png", + }, + coingecko_id: "terra-luna-2", + }, + ], +}; diff --git a/src/lib/components/Chakra.tsx b/src/lib/components/Chakra.tsx deleted file mode 100644 index 59515b05d..000000000 --- a/src/lib/components/Chakra.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import { ChakraProvider } from "@chakra-ui/react"; -import type { ReactNode } from "react"; - -import customTheme from "lib/styles/theme"; - -interface ChakraProps { - children: ReactNode; -} - -export const Chakra = ({ children }: ChakraProps) => ( - {children} -); diff --git a/src/lib/components/ExplorerLink.tsx b/src/lib/components/ExplorerLink.tsx index 3b48fbe85..ecec72e40 100644 --- a/src/lib/components/ExplorerLink.tsx +++ b/src/lib/components/ExplorerLink.tsx @@ -128,7 +128,6 @@ const LinkRender = ({ pointerEvents={hrefLink ? "auto" : "none"} wordBreak={{ base: "break-all", md: "inherit" }} display={{ base: "inline", md: "flex" }} - align={{ base: "start", md: "center" }} > {textValue} diff --git a/src/lib/components/PrimaryNameMark.tsx b/src/lib/components/PrimaryNameMark.tsx index 8ad8a330a..d1676eabe 100644 --- a/src/lib/components/PrimaryNameMark.tsx +++ b/src/lib/components/PrimaryNameMark.tsx @@ -3,7 +3,7 @@ import { Tooltip } from "lib/components/Tooltip"; export const PrimaryNameMark = () => ( -
+
diff --git a/src/lib/components/TxFilterSelection.tsx b/src/lib/components/TxFilterSelection.tsx index 46c5b9b43..10ae6e782 100644 --- a/src/lib/components/TxFilterSelection.tsx +++ b/src/lib/components/TxFilterSelection.tsx @@ -131,14 +131,13 @@ export const TxFilterSelection = forwardRef< > {displayActionValue(option)} - + ))} diff --git a/src/lib/components/action-msg/MsgToken.tsx b/src/lib/components/action-msg/MsgToken.tsx index 5dffbbdb2..8f74a50e2 100644 --- a/src/lib/components/action-msg/MsgToken.tsx +++ b/src/lib/components/action-msg/MsgToken.tsx @@ -21,7 +21,7 @@ export const MsgToken = ({ ampCopierSection, }: MsgTokenProps) => ( - + {formatBalanceWithDenom({ coin, symbol, diff --git a/src/lib/components/action-msg/MultipleActionsMsg.tsx b/src/lib/components/action-msg/MultipleActionsMsg.tsx index 9f664ece3..bd1cb4bb8 100644 --- a/src/lib/components/action-msg/MultipleActionsMsg.tsx +++ b/src/lib/components/action-msg/MultipleActionsMsg.tsx @@ -15,7 +15,7 @@ export const MultipleActionsMsg = ({ messages }: MultipleActionsMsgProps) => { {displayMessagesCount.map((msg, index) => ( - {msg.type} + {msg.type} {msg.count} {index < displayMessagesCount.length - 1 && ","} diff --git a/src/lib/components/action-msg/SingleMsg.tsx b/src/lib/components/action-msg/SingleMsg.tsx index ea5f69b38..5616aaaab 100644 --- a/src/lib/components/action-msg/SingleMsg.tsx +++ b/src/lib/components/action-msg/SingleMsg.tsx @@ -43,13 +43,10 @@ export const SingleMsg = ({ text3, link2, }: SingleMsgProps) => { - if (!type) - return ( - Message Unavailable - ); + if (!type) return Message Unavailable; return ( - + {type} {text1} {tokens?.map((token: Token, index: number) => ( @@ -85,7 +82,7 @@ export const SingleMsg = ({ )} {/* Text2 */} - {text2} + {text2} {/* Link */} {link1 && ( )} {/* Text3 */} - {text3} + {text3} {/* Link2 */} {link2 && ( { const navigate = useInternalNavigate(); + const govConfig = useGovConfig({ shouldRedirect: false }); // const { data: govParams } = useGovParams(); // const isPermissionless = // govParams?.uploadAccess.permission === AccessConfigPermission.EVERYBODY; + if (govConfig.enabled && govConfig.disableOpenProposal) return null; + return ( { Create New Proposal - } - onClick={() => { - navigate({ - pathname: "/proposals/store-code", - }); - }} - > - To Store Code - + {govConfig.enabled && !govConfig.disableStoreCodeProposal && ( + } + onClick={() => { + navigate({ + pathname: "/proposals/store-code", + }); + }} + > + To Store Code + + )} {/* } onClick={() => { diff --git a/src/lib/components/forms/FilterByPermission.tsx b/src/lib/components/forms/FilterByPermission.tsx index 07ff00633..56e8628f2 100644 --- a/src/lib/components/forms/FilterByPermission.tsx +++ b/src/lib/components/forms/FilterByPermission.tsx @@ -9,7 +9,8 @@ interface PermissionOption { label: string; value: PermissionFilterValue; disabled: boolean; - icon?: IconKeys; + icon: IconKeys; + iconColor: string; } interface FilterByPermissionProps { @@ -25,18 +26,21 @@ const options: PermissionOption[] = [ value: "all", disabled: false, icon: "check", + iconColor: "gray.600", }, { label: "Can Instantiate without proposal", value: "without-proposal", disabled: false, icon: "instantiate", + iconColor: "gray.600", }, { label: "Instantiate through proposal only", value: "with-proposal", disabled: false, icon: "vote", + iconColor: "gray.600", }, ]; diff --git a/src/lib/components/modal/CodeSnippet.tsx b/src/lib/components/modal/CodeSnippet.tsx index 3dcb5b118..2adfb4bf7 100644 --- a/src/lib/components/modal/CodeSnippet.tsx +++ b/src/lib/components/modal/CodeSnippet.tsx @@ -15,6 +15,7 @@ import { Heading, Box, } from "@chakra-ui/react"; +import type { Coin } from "@cosmjs/stargate"; import AceEditor from "react-ace"; import { CopyButton } from "../copy"; @@ -29,6 +30,7 @@ import { import { CustomTab } from "lib/components/CustomTab"; import { AmpEvent, AmpTrack } from "lib/services/amplitude"; import type { ContractAddr } from "lib/types"; +import { coinsToStr, jsonPrettify } from "lib/utils"; import "ace-builds/src-noconflict/ace"; import "ace-builds/src-noconflict/mode-sh"; @@ -43,6 +45,7 @@ interface CodeSnippetProps { message: string; type: "query" | "execute"; ml?: ButtonProps["ml"]; + funds?: Coin[]; } const CodeSnippet = ({ @@ -50,6 +53,7 @@ const CodeSnippet = ({ message, type = "query", ml, + funds = [], }: CodeSnippetProps) => { const { isOpen, onClose, onOpen } = useDisclosure(); const { @@ -65,6 +69,9 @@ const CodeSnippet = ({ }, } = useCelatoneApp(); + const gasPriceStr = `${gasPrice.tokenPerGas}${gasPrice.denom}`; + const fundsFlags = funds.length ? `\n --amount ${coinsToStr(funds)} \\` : ""; + const codeSnippets: Record< string, { name: string; mode: string; snippet: string }[] @@ -141,7 +148,10 @@ export EXECUTE_MSG='${message}'\n ${daemonName} tx wasm execute $CONTRACT_ADDRESS $EXECUTE_MSG \\ --from celatone \\ --chain-id $CHAIN_ID \\ - --node $RPC_URL`, + --node $RPC_URL \\${fundsFlags} + --gas auto \\ + --gas-prices ${gasPriceStr} \\ + --gas-adjustment 1.5`, }, { name: "CosmJS", @@ -157,6 +167,8 @@ const mnemonic = const chain = chains.find(({ chain_name }) => chain_name === '${chainName}'); const contractAddress = '${contractAddress}'; +const msg = ${message}; +const funds = [${funds.map((coin) => jsonPrettify(JSON.stringify(coin)))}]; const execute = async () => { const rpcEndpoint = '${rpcEndpoint}'; @@ -165,7 +177,7 @@ const execute = async () => { rpcEndpoint, signer, { - gasPrice: GasPrice.fromString("${gasPrice.tokenPerGas}${gasPrice.denom}"), + gasPrice: GasPrice.fromString("${gasPriceStr}"), } ); @@ -175,15 +187,17 @@ const execute = async () => { const tx = await client.execute( sender.address, contractAddress, - ${message}, - fee + msg, + fee, + undefined, + funds ); console.log(tx.transactionHash); }; execute(); -;`, +`, }, ], }; diff --git a/src/lib/components/pagination/Next.tsx b/src/lib/components/pagination/Next.tsx index cd12db938..0024f06a3 100644 --- a/src/lib/components/pagination/Next.tsx +++ b/src/lib/components/pagination/Next.tsx @@ -1,6 +1,5 @@ import type { ButtonProps } from "@chakra-ui/react"; import { Button } from "@chakra-ui/react"; -import type react from "react"; import { useContext } from "react"; import { AmpTrackPaginationNavigate } from "lib/services/amplitude"; @@ -8,7 +7,7 @@ import { AmpTrackPaginationNavigate } from "lib/services/amplitude"; import { PaginatorContext } from "./PaginatorProvider"; interface NextProps extends ButtonProps { - children: react.ReactNode; + children: React.ReactNode; pageSize: number; } diff --git a/src/lib/components/table/transactions/TransactionsTable.tsx b/src/lib/components/table/transactions/TransactionsTable.tsx index e99ef3dd0..11fc8ee3e 100644 --- a/src/lib/components/table/transactions/TransactionsTable.tsx +++ b/src/lib/components/table/transactions/TransactionsTable.tsx @@ -25,9 +25,9 @@ export const TransactionsTable = ({ if (isLoading) return ; if (!transactions?.length) return emptyState; - const templateColumns = `25px 180px 40px minmax(360px, 1fr) ${ + const templateColumns = `0px 190px 48px minmax(360px, 1fr) ${ showRelations ? "100px " : "" - }max(160px) ${showTimestamp ? "max(220px) " : ""}${ + }max(190px) ${showTimestamp ? "max(230px) " : ""}${ showAction ? "100px " : "" }`; diff --git a/src/lib/components/table/transactions/TransactionsTableRow.tsx b/src/lib/components/table/transactions/TransactionsTableRow.tsx index 39f2773fe..f05b1f512 100644 --- a/src/lib/components/table/transactions/TransactionsTableRow.tsx +++ b/src/lib/components/table/transactions/TransactionsTableRow.tsx @@ -57,7 +57,7 @@ export const TransactionsTableRow = ({ /> )} - + <> ( - + {receipts.map((receipt, idx) => ( { const { address: walletAddress } = useCurrentChain(); + const { + chainConfig: { + extra: { disableAnyOfAddresses }, + }, + } = useCelatoneApp(); const { fields, append, remove } = useFieldArray({ control, @@ -95,79 +100,83 @@ export const InstantiatePermissionRadio = ({ value={AccessType.ACCESS_TYPE_NOBODY} text="Instantiate through governance only (Nobody)" /> - - - {permission === AccessType.ACCESS_TYPE_ANY_OF_ADDRESSES && ( - - {fields.map((field, idx) => ( - - - i < idx && address === addresses[idx]?.address - ) && - "You already input this address") || - errors.addresses?.[idx]?.address?.message - } - helperAction={ - { - AmpTrack(AmpEvent.USE_ASSIGN_ME); - setValue( - `addresses.${idx}.address`, - walletAddress as Addr - ); - trigger(`addresses.${idx}.address`); - }} - isDisable={ - addresses.findIndex( - (x) => x.address === walletAddress - ) > -1 - } - /> - } - /> - - - ))} - - - )} - + + + ))} + + + )} + + )} ); diff --git a/src/lib/components/upload/UploadSection.tsx b/src/lib/components/upload/UploadSection.tsx index 00bb44ec2..7356d3a75 100644 --- a/src/lib/components/upload/UploadSection.tsx +++ b/src/lib/components/upload/UploadSection.tsx @@ -48,7 +48,12 @@ export const UploadSection = ({ onComplete, isMigrate = false, }: UploadSectionProps) => { - const { constants } = useCelatoneApp(); + const { + constants, + chainConfig: { + extra: { disableAnyOfAddresses }, + }, + } = useCelatoneApp(); const getMaxLengthError = useGetMaxLengthError(); const fabricateFee = useFabricateFee(); const { address } = useCurrentChain(); @@ -113,7 +118,10 @@ export const UploadSection = ({ enabled: Boolean(wasmFile && address && !shouldNotSimulate), wasmFile, permission, - addresses: addresses.map((addr) => addr.address), + // Remarks: disableAnyOfAddresses is only used for Cosmos SDK 0.26 + addresses: disableAnyOfAddresses + ? undefined + : addresses.map((addr) => addr.address), onSuccess: (fee) => { if (wasmFile && address) { if (shouldNotSimulate) { @@ -144,7 +152,10 @@ export const UploadSection = ({ const stream = await postUploadTx({ wasmFileName: wasmFile?.name, wasmCode: wasmFile?.arrayBuffer(), - addresses: addresses.map((addr) => addr.address), + // Remarks: disableAnyOfAddresses is only used for Cosmos SDK 0.26 + addresses: disableAnyOfAddresses + ? undefined + : addresses.map((addr) => addr.address), permission, codeName, estimatedFee, @@ -171,6 +182,7 @@ export const UploadSection = ({ broadcast, updateCodeInfo, onComplete, + disableAnyOfAddresses, // eslint-disable-next-line react-hooks/exhaustive-deps JSON.stringify(addresses), ]); diff --git a/src/lib/layout/SubHeader.tsx b/src/lib/layout/SubHeader.tsx index 749eab36d..13f919202 100644 --- a/src/lib/layout/SubHeader.tsx +++ b/src/lib/layout/SubHeader.tsx @@ -6,10 +6,10 @@ import { FormLabel, Button, } from "@chakra-ui/react"; -import type { Dispatch, SetStateAction } from "react"; +import type { CSSProperties, Dispatch, SetStateAction } from "react"; import { useEffect, useRef } from "react"; -import { usePoolConfig, useWasmConfig } from "lib/app-provider"; +import { usePoolConfig, useGovConfig, useWasmConfig } from "lib/app-provider"; import { AppLink } from "lib/components/AppLink"; import type { IconKeys } from "lib/components/icon"; import { CustomIcon } from "lib/components/icon"; @@ -22,6 +22,7 @@ interface SubHeaderMenuInfo { icon: IconKeys; } +const boxShadow = "0px 1px 5px 0px var(--chakra-colors-gray-900)"; const FirstLandPrompt = ({ setIsDevMode, }: { @@ -35,7 +36,8 @@ const FirstLandPrompt = ({ bg="gray.800" color="text.main" w="430px" - borderRadius={1} + borderRadius={4} + boxShadow={boxShadow} zIndex="popover" sx={{ "& > header": { p: "16px 24px", fontSize: "18px", fontWeight: 500 }, @@ -76,6 +78,7 @@ const SubHeader = ({ }: SubHeaderProps) => { const wasmConfig = useWasmConfig({ shouldRedirect: false }); const poolConfig = usePoolConfig({ shouldRedirect: false }); + const govConfig = useGovConfig({ shouldRedirect: false }); const prevIsDevModeRef = useRef(Boolean(isDevMode)); @@ -89,7 +92,9 @@ const SubHeader = ({ { name: "Contracts", slug: "/contracts", icon: "contract-address" }, ] as const) : []), - { name: "Proposals", slug: "/proposals", icon: "proposal" }, + ...(govConfig.enabled + ? ([{ name: "Proposals", slug: "/proposals", icon: "proposal" }] as const) + : []), ...(poolConfig.enabled ? ([{ name: "Osmosis Pools", slug: "/pools", icon: "pool" }] as const) : []), @@ -98,6 +103,12 @@ const SubHeader = ({ const activeColor = "primary.light"; + const switchHighlight: CSSProperties = { + borderRadius: "4px", + padding: "6px 8px", + backgroundColor: "var(--chakra-colors-gray-800)", + }; + useEffect(() => { // Basic to dev and nav is collapse -> should exapnd if (isDevMode && !prevIsDevModeRef.current && !isExpand) { @@ -153,9 +164,17 @@ const SubHeader = ({ ))} - - - + + + Dev Mode diff --git a/src/lib/layout/navbar/Expand.tsx b/src/lib/layout/navbar/Expand.tsx index c7ec78f49..af5515ce5 100644 --- a/src/lib/layout/navbar/Expand.tsx +++ b/src/lib/layout/navbar/Expand.tsx @@ -48,7 +48,7 @@ const NavInfo = ({ submenu, isCurrentPage }: NavInfoProps) => ( {submenu.name} diff --git a/src/lib/layout/navbar/index.tsx b/src/lib/layout/navbar/index.tsx index 87678bc2a..61138553e 100644 --- a/src/lib/layout/navbar/index.tsx +++ b/src/lib/layout/navbar/index.tsx @@ -51,8 +51,8 @@ const Navbar = ({ isExpand, isDevMode, setIsExpand }: NavbarProps) => { ...(isDevMode && wasm.enabled ? [ { - name: "My Codes", - slug: "/codes", + name: "My Stored Codes", + slug: "/stored-codes", icon: "code" as IconKeys, }, { @@ -107,7 +107,7 @@ const Navbar = ({ isExpand, isDevMode, setIsExpand }: NavbarProps) => { submenu: [ { name: "Saved Codes", - slug: "/my-codes", + slug: "/saved-codes", icon: "code" as IconKeys, }, { diff --git a/src/lib/pages/account-details/components/AccountHeader.tsx b/src/lib/pages/account-details/components/AccountHeader.tsx index 1d2d6a885..8cbdd4bbc 100644 --- a/src/lib/pages/account-details/components/AccountHeader.tsx +++ b/src/lib/pages/account-details/components/AccountHeader.tsx @@ -63,24 +63,24 @@ export const AccountHeader = ({ {icnsName.names.map((name) => ( -
+ {name === icnsName.primary_name && } - -
+ +
))} diff --git a/src/lib/pages/blocks/components/BlocksTable.tsx b/src/lib/pages/blocks/components/BlocksTable.tsx index 15176df0d..4f76853cc 100644 --- a/src/lib/pages/blocks/components/BlocksTable.tsx +++ b/src/lib/pages/blocks/components/BlocksTable.tsx @@ -95,7 +95,11 @@ export const BlocksTable = ({ isViewMore }: BlocksTableProps) => { scrollComponentId={scrollComponentId} /> {blocksData.map((block) => ( - + ))} )} diff --git a/src/lib/pages/contract-details/components/tables/TxsTable.tsx b/src/lib/pages/contract-details/components/tables/TxsTable.tsx index 9ed71c47c..6cf9b46a5 100644 --- a/src/lib/pages/contract-details/components/tables/TxsTable.tsx +++ b/src/lib/pages/contract-details/components/tables/TxsTable.tsx @@ -9,17 +9,17 @@ import { EmptyState } from "lib/components/state"; import { TransactionsTable } from "lib/components/table"; import { DEFAULT_TX_FILTERS } from "lib/data"; import { useTxsByAddressPagination } from "lib/services/txService"; -import type { ContractAddr, Option } from "lib/types"; +import type { Option } from "lib/types"; interface TxsTableProps { - contractAddress: ContractAddr; + contractAccountId: Option; scrollComponentId: string; totalData: Option; refetchCount: () => void; } export const TxsTable = ({ - contractAddress, + contractAccountId, scrollComponentId, totalData, refetchCount, @@ -41,8 +41,8 @@ export const TxsTable = ({ }); const { data: transactions, isLoading } = useTxsByAddressPagination( - contractAddress, undefined, + contractAccountId, "", DEFAULT_TX_FILTERS, undefined, diff --git a/src/lib/pages/contract-details/index.tsx b/src/lib/pages/contract-details/index.tsx index da5030834..68421cc51 100644 --- a/src/lib/pages/contract-details/index.tsx +++ b/src/lib/pages/contract-details/index.tsx @@ -16,6 +16,7 @@ import { Loading } from "lib/components/Loading"; import PageContainer from "lib/components/PageContainer"; import { InvalidState } from "lib/components/state"; import { useContractDetailsTableCounts } from "lib/model/contract"; +import { useAccountId } from "lib/services/accountService"; import { AmpEvent, AmpTrack } from "lib/services/amplitude"; import type { ContractAddr } from "lib/types"; import { getFirstQueryParam, jsonPrettify } from "lib/utils"; @@ -50,6 +51,7 @@ const ContractDetailsBody = observer( refetchTransactions, refetchRelatedProposals, } = useContractDetailsTableCounts(contractAddress); + const { data: contractAccountId } = useAccountId(contractAddress); const isMobile = useMobile(); if (!contractData.contractDetail) return ; @@ -127,7 +129,7 @@ const ContractDetailsBody = observer( { return ( {shortcutList.map((item) => ( - <> +
{!isMobile || item.slug === "query" ? ( { )} - +
))}
); diff --git a/src/lib/pages/my-codes/components/MySavedCodesSection.tsx b/src/lib/pages/my-codes/components/MySavedCodesSection.tsx deleted file mode 100644 index fdf4e898e..000000000 --- a/src/lib/pages/my-codes/components/MySavedCodesSection.tsx +++ /dev/null @@ -1,36 +0,0 @@ -import { Box, Heading, HStack } from "@chakra-ui/react"; - -import { MySavedCodesTable } from "lib/components/table"; -import type { CodeInfo } from "lib/types"; - -import { SaveCodeButton } from "./SaveCodeButton"; - -interface MySavedCodesSectionProps { - codes: CodeInfo[]; - isLoading: boolean; - onRowSelect: (codeId: number) => void; - isSearching: boolean; -} - -export const MySavedCodesSection = ({ - codes, - isLoading, - onRowSelect, - isSearching, -}: MySavedCodesSectionProps) => ( - - - - My Saved Codes - - - - - -); diff --git a/src/lib/pages/my-codes/components/MyStoredCodesSection.tsx b/src/lib/pages/my-codes/components/MyStoredCodesSection.tsx deleted file mode 100644 index 1f16cef95..000000000 --- a/src/lib/pages/my-codes/components/MyStoredCodesSection.tsx +++ /dev/null @@ -1,61 +0,0 @@ -import { Box, Flex, Heading, HStack } from "@chakra-ui/react"; - -import { useCurrentChain } from "lib/app-provider"; -import { MyStoredCodesTable } from "lib/components/table"; -import { useUploadAccessParams } from "lib/services/proposalService"; -import type { Addr, CodeInfo } from "lib/types"; -import { AccessConfigPermission } from "lib/types"; - -import { ProposalButton } from "./ProposalButton"; -import { UploadButton } from "./UploadButton"; - -interface MyStoredCodesSectionProps { - codes: CodeInfo[]; - isLoading: boolean; - onRowSelect: (codeId: number) => void; - disconnectedMessage: string; - isSearching: boolean; -} - -export const MyStoredCodesSection = ({ - codes, - isLoading, - onRowSelect, - disconnectedMessage, - isSearching, -}: MyStoredCodesSectionProps) => { - const { data } = useUploadAccessParams(); - const { address } = useCurrentChain(); - const isAllowed = Boolean(data?.addresses?.includes(address as Addr)); - - const isPermissionedNetwork = - data?.permission !== AccessConfigPermission.EVERYBODY; - - return ( - - - - My Stored Codes - - - {isPermissionedNetwork ? ( - <> - - - - ) : ( - - )} - - - - - ); -}; diff --git a/src/lib/pages/my-codes/index.tsx b/src/lib/pages/my-codes/index.tsx deleted file mode 100644 index 81af5c11f..000000000 --- a/src/lib/pages/my-codes/index.tsx +++ /dev/null @@ -1,138 +0,0 @@ -import { - Heading, - Tabs, - TabList, - TabPanels, - TabPanel, - Flex, -} from "@chakra-ui/react"; -import { observer } from "mobx-react-lite"; -import { useRouter } from "next/router"; -import type { ChangeEvent } from "react"; -import { useEffect } from "react"; -import { useForm } from "react-hook-form"; - -import { useInternalNavigate } from "lib/app-provider"; -import { CustomTab } from "lib/components/CustomTab"; -import { FilterByPermission } from "lib/components/forms"; -import InputWithIcon from "lib/components/InputWithIcon"; -import PageContainer from "lib/components/PageContainer"; -import type { PermissionFilterValue } from "lib/hooks"; -import { useMyCodesData } from "lib/model/code"; -import { AmpEvent, AmpTrack } from "lib/services/amplitude"; - -import { MySavedCodesSection } from "./components/MySavedCodesSection"; -import { MyStoredCodesSection } from "./components/MyStoredCodesSection"; - -interface CodeFilterState { - keyword: string; - permissionValue: PermissionFilterValue; -} - -const MyCodes = observer(() => { - const router = useRouter(); - const navigate = useInternalNavigate(); - const onRowSelect = (codeId: number) => - navigate({ - pathname: "/codes/[codeId]", - query: { codeId }, - }); - // TODO refactor to useState - const { watch, setValue } = useForm({ - defaultValues: { - permissionValue: "all", - keyword: "", - }, - }); - const { keyword, permissionValue } = watch(); - - const { - storedCodesCount, - storedCodes: stored, - savedCodesCount, - savedCodes: saved, - allCodesCount, - isStoredCodesLoading, - isSavedCodesLoading, - } = useMyCodesData(keyword, permissionValue); - - const isSearching = !!keyword || permissionValue !== "all"; - - useEffect(() => { - if (router.isReady) AmpTrack(AmpEvent.TO_MY_CODES); - }, [router.isReady]); - - return ( - - - My Codes - - - - All Codes - My Stored Codes - My Saved Codes - - - ) => - setValue("keyword", e.target.value) - } - size="lg" - /> - { - if (newVal === permissionValue) return; - setValue("permissionValue", newVal); - }} - /> - - - - - - - - - - - - - - - - ); -}); - -export default MyCodes; diff --git a/src/lib/pages/pools/components/pool-details/header/index.tsx b/src/lib/pages/pools/components/pool-details/header/index.tsx index ba532c24b..61dede94d 100644 --- a/src/lib/pages/pools/components/pool-details/header/index.tsx +++ b/src/lib/pages/pools/components/pool-details/header/index.tsx @@ -2,6 +2,7 @@ import { Button, Flex } from "@chakra-ui/react"; import { PoolHeader } from "../../PoolHeader"; import { useBaseApiRoute, usePoolConfig } from "lib/app-provider"; +import { Breadcrumb } from "lib/components/Breadcrumb"; import { CustomIcon } from "lib/components/icon"; import { AmpTrackViewJson, AmpTrackWebsite } from "lib/services/amplitude"; import type { PoolDetail } from "lib/types"; @@ -29,7 +30,13 @@ export const PoolTopSection = ({ pool }: PoolTopSectionProps) => { }; return ( <> - + + `gamm/pool/${poolId}`; -export const coinsFromStr = (str: string): Coin[] => { - try { - return parseCoins(str); - } catch { - return []; - } -}; - export const extractPoolMsgs = (msgs: Message[], poolId: number) => { const result: { msgs: { msg: Message; index: number }[]; diff --git a/src/lib/pages/pools/poolId.tsx b/src/lib/pages/pools/poolId.tsx index a11d70cda..fae694e03 100644 --- a/src/lib/pages/pools/poolId.tsx +++ b/src/lib/pages/pools/poolId.tsx @@ -2,7 +2,6 @@ import { useRouter } from "next/router"; import { useEffect } from "react"; import { useInternalNavigate } from "lib/app-provider"; -import { BackButton } from "lib/components/button"; import { Loading } from "lib/components/Loading"; import PageContainer from "lib/components/PageContainer"; import { AmpEvent, AmpTrack } from "lib/services/amplitude"; @@ -29,7 +28,6 @@ export const PoolId = () => { if (!pool) return navigate({ pathname: `/pools` }); return ( - diff --git a/src/lib/pages/proposals/index.tsx b/src/lib/pages/proposals/index.tsx index 0ec37a5f8..bed4766ea 100644 --- a/src/lib/pages/proposals/index.tsx +++ b/src/lib/pages/proposals/index.tsx @@ -3,7 +3,11 @@ import { useRouter } from "next/router"; import type { ChangeEvent } from "react"; import { useState, useEffect } from "react"; -import { useCelatoneApp, useCurrentChain } from "lib/app-provider"; +import { + useCelatoneApp, + useCurrentChain, + useGovConfig, +} from "lib/app-provider"; import { NewProposalButton } from "lib/components/button/NewProposalButton"; import InputWithIcon from "lib/components/InputWithIcon"; import PageContainer from "lib/components/PageContainer"; @@ -24,6 +28,7 @@ import { ProposalTypeFilter } from "./components/ProposalTypeFilter"; const Proposals = () => { const { currentChainId } = useCelatoneApp(); + useGovConfig({ shouldRedirect: true }); const router = useRouter(); const [statuses, setStatuses] = useState([]); const [types, setTypes] = useState([]); diff --git a/src/lib/pages/saved-codes/components/MySavedCodesSection.tsx b/src/lib/pages/saved-codes/components/MySavedCodesSection.tsx new file mode 100644 index 000000000..c2eaaef55 --- /dev/null +++ b/src/lib/pages/saved-codes/components/MySavedCodesSection.tsx @@ -0,0 +1,24 @@ +import { MySavedCodesTable } from "lib/components/table"; +import type { CodeInfo } from "lib/types"; + +interface MySavedCodesSectionProps { + codes: CodeInfo[]; + isLoading: boolean; + onRowSelect: (codeId: number) => void; + isSearching: boolean; +} + +export const MySavedCodesSection = ({ + codes, + isLoading, + onRowSelect, + isSearching, +}: MySavedCodesSectionProps) => ( + +); diff --git a/src/lib/pages/my-codes/components/SaveCodeButton.tsx b/src/lib/pages/saved-codes/components/SaveCodeButton.tsx similarity index 100% rename from src/lib/pages/my-codes/components/SaveCodeButton.tsx rename to src/lib/pages/saved-codes/components/SaveCodeButton.tsx diff --git a/src/lib/pages/saved-codes/index.tsx b/src/lib/pages/saved-codes/index.tsx new file mode 100644 index 000000000..6e4555909 --- /dev/null +++ b/src/lib/pages/saved-codes/index.tsx @@ -0,0 +1,99 @@ +import { Heading, Flex, Badge } from "@chakra-ui/react"; +import { observer } from "mobx-react-lite"; +import { useRouter } from "next/router"; +import type { ChangeEvent } from "react"; +import { useEffect } from "react"; +import { useForm } from "react-hook-form"; + +import { useInternalNavigate } from "lib/app-provider"; +import { FilterByPermission } from "lib/components/forms"; +import InputWithIcon from "lib/components/InputWithIcon"; +import PageContainer from "lib/components/PageContainer"; +import type { PermissionFilterValue } from "lib/hooks"; +import { useMyCodesData } from "lib/model/code"; +import { AmpEvent, AmpTrack } from "lib/services/amplitude"; + +import { MySavedCodesSection } from "./components/MySavedCodesSection"; +import { SaveCodeButton } from "./components/SaveCodeButton"; + +interface CodeFilterState { + keyword: string; + permissionValue: PermissionFilterValue; +} + +const SavedCodes = observer(() => { + const router = useRouter(); + const navigate = useInternalNavigate(); + const onRowSelect = (codeId: number) => + navigate({ + pathname: "/codes/[codeId]", + query: { codeId }, + }); + // TODO refactor to useState + const { watch, setValue } = useForm({ + defaultValues: { + permissionValue: "all", + keyword: "", + }, + }); + const { keyword, permissionValue } = watch(); + + const { + savedCodesCount, + savedCodes: saved, + isSavedCodesLoading, + } = useMyCodesData(keyword, permissionValue); + + const isSearching = !!keyword || permissionValue !== "all"; + + useEffect(() => { + if (router.isReady) AmpTrack(AmpEvent.TO_MY_CODES); + }, [router.isReady]); + + return ( + + + + + Saved Codes + + + {savedCodesCount} + + + + + + ) => + setValue("keyword", e.target.value) + } + size="lg" + /> + { + if (newVal === permissionValue) return; + setValue("permissionValue", newVal); + }} + /> + + + + ); +}); + +export default SavedCodes; diff --git a/src/lib/pages/my-codes/components/DeployButton.tsx b/src/lib/pages/stored-codes/components/DeployButton.tsx similarity index 100% rename from src/lib/pages/my-codes/components/DeployButton.tsx rename to src/lib/pages/stored-codes/components/DeployButton.tsx diff --git a/src/lib/pages/stored-codes/components/MyStoredCodesSection.tsx b/src/lib/pages/stored-codes/components/MyStoredCodesSection.tsx new file mode 100644 index 000000000..da7401527 --- /dev/null +++ b/src/lib/pages/stored-codes/components/MyStoredCodesSection.tsx @@ -0,0 +1,29 @@ +import { MyStoredCodesTable } from "lib/components/table"; +import type { CodeInfo } from "lib/types"; + +interface MyStoredCodesSectionProps { + codes: CodeInfo[]; + isLoading: boolean; + onRowSelect: (codeId: number) => void; + disconnectedMessage: string; + isSearching: boolean; +} + +export const MyStoredCodesSection = ({ + codes, + isLoading, + onRowSelect, + disconnectedMessage, + isSearching, +}: MyStoredCodesSectionProps) => { + return ( + + ); +}; diff --git a/src/lib/pages/my-codes/components/ProposalButton.tsx b/src/lib/pages/stored-codes/components/ProposalButton.tsx similarity index 100% rename from src/lib/pages/my-codes/components/ProposalButton.tsx rename to src/lib/pages/stored-codes/components/ProposalButton.tsx diff --git a/src/lib/pages/my-codes/components/UploadButton.tsx b/src/lib/pages/stored-codes/components/UploadButton.tsx similarity index 100% rename from src/lib/pages/my-codes/components/UploadButton.tsx rename to src/lib/pages/stored-codes/components/UploadButton.tsx diff --git a/src/lib/pages/stored-codes/index.tsx b/src/lib/pages/stored-codes/index.tsx new file mode 100644 index 000000000..f8674abca --- /dev/null +++ b/src/lib/pages/stored-codes/index.tsx @@ -0,0 +1,134 @@ +import { Heading, Flex, Badge, Skeleton } from "@chakra-ui/react"; +import { observer } from "mobx-react-lite"; +import { useRouter } from "next/router"; +import type { ChangeEvent } from "react"; +import { useEffect } from "react"; +import { useForm } from "react-hook-form"; + +import { + useCurrentChain, + useGovConfig, + useInternalNavigate, +} from "lib/app-provider"; +import { FilterByPermission } from "lib/components/forms"; +import InputWithIcon from "lib/components/InputWithIcon"; +import PageContainer from "lib/components/PageContainer"; +import type { PermissionFilterValue } from "lib/hooks"; +import { useMyCodesData } from "lib/model/code"; +import { AmpEvent, AmpTrack } from "lib/services/amplitude"; +import { useUploadAccessParams } from "lib/services/proposalService"; +import type { Addr } from "lib/types"; +import { AccessConfigPermission } from "lib/types"; + +import { MyStoredCodesSection } from "./components/MyStoredCodesSection"; +import { ProposalButton } from "./components/ProposalButton"; +import { UploadButton } from "./components/UploadButton"; + +interface CodeFilterState { + keyword: string; + permissionValue: PermissionFilterValue; +} + +const StoredCodes = observer(() => { + const router = useRouter(); + const govConfig = useGovConfig({ shouldRedirect: false }); + const navigate = useInternalNavigate(); + const onRowSelect = (codeId: number) => + navigate({ + pathname: "/codes/[codeId]", + query: { codeId }, + }); + // TODO refactor to useState + const { watch, setValue } = useForm({ + defaultValues: { + permissionValue: "all", + keyword: "", + }, + }); + const { keyword, permissionValue } = watch(); + + const { + storedCodesCount, + storedCodes: stored, + isStoredCodesLoading, + } = useMyCodesData(keyword, permissionValue); + + const isSearching = !!keyword || permissionValue !== "all"; + + useEffect(() => { + if (router.isReady) AmpTrack(AmpEvent.TO_MY_CODES); + }, [router.isReady]); + const { data, isFetching: isUploadAccessFetching } = useUploadAccessParams(); + const { address } = useCurrentChain(); + const isAllowed = Boolean(data?.addresses?.includes(address as Addr)); + + const isPermissionedNetwork = + data?.permission !== AccessConfigPermission.EVERYBODY; + + return ( + + + + + My Stored Codes + + + {storedCodesCount} + + + + {isPermissionedNetwork ? ( + <> + + {govConfig.enabled && + !( + govConfig.disableStoreCodeProposal || + govConfig.disableOpenProposal + ) && } + + ) : ( + + )} + + + + ) => + setValue("keyword", e.target.value) + } + size="lg" + /> + { + if (newVal === permissionValue) return; + setValue("permissionValue", newVal); + }} + /> + + + + + ); +}); + +export default StoredCodes; diff --git a/src/lib/pages/tx-details/components/tx-message/EventBox.tsx b/src/lib/pages/tx-details/components/tx-message/EventBox.tsx index 1ac2aae54..678579d39 100644 --- a/src/lib/pages/tx-details/components/tx-message/EventBox.tsx +++ b/src/lib/pages/tx-details/components/tx-message/EventBox.tsx @@ -1,7 +1,8 @@ -import { Box, Flex } from "@chakra-ui/react"; +import { Box, Flex, chakra, shouldForwardProp } from "@chakra-ui/react"; import type { Event } from "@cosmjs/stargate"; +import { isValidMotionProp, motion } from "framer-motion"; import type { ReactNode } from "react"; -import { useCallback, useState } from "react"; +import { useState } from "react"; import { useGetAddressType } from "lib/app-provider"; import type { LinkType } from "lib/components/ExplorerLink"; @@ -13,6 +14,11 @@ import { AmpTrackExpand } from "lib/services/amplitude"; import type { TxReceipt } from "lib/types"; import { jsonPrettify, jsonValidate } from "lib/utils"; +const MotionBox = chakra(motion.div, { + shouldForwardProp: (prop) => + isValidMotionProp(prop) || shouldForwardProp(prop), +}); + interface EventBoxProps { event: Event; msgIndex: number; @@ -21,15 +27,6 @@ interface EventBoxProps { export const EventBox = ({ event, msgIndex }: EventBoxProps) => { const getAddressType = useGetAddressType(); const [expand, setExpand] = useState(true); - const [receiptHeight, setReceiptHeight] = useState(0); - - const measuredRef = useCallback((node: HTMLDivElement | null) => { - if (node !== null) { - setTimeout(() => { - setReceiptHeight(node.clientHeight); - }, 100); - } - }, []); const receipts = event.attributes.map(({ key, value }) => { const addrType = getAddressType(value); @@ -108,7 +105,6 @@ export const EventBox = ({ event, msgIndex }: EventBoxProps) => { position="relative" direction="column" borderRadius="8px" - transition="all .25s ease-in-out" backgroundColor="gray.900" _hover={{ backgroundColor: "gray.800" }} > @@ -139,21 +135,30 @@ export const EventBox = ({ event, msgIndex }: EventBoxProps) => { m={0} /> - - - - - - + + + ); }; diff --git a/src/lib/pages/tx-details/components/tx-message/TxMsgExpand.tsx b/src/lib/pages/tx-details/components/tx-message/TxMsgExpand.tsx index bdbb9dcf0..de758d290 100644 --- a/src/lib/pages/tx-details/components/tx-message/TxMsgExpand.tsx +++ b/src/lib/pages/tx-details/components/tx-message/TxMsgExpand.tsx @@ -1,5 +1,5 @@ /* eslint-disable complexity */ -import { Flex, Tag } from "@chakra-ui/react"; +import { Flex, Tag, Text } from "@chakra-ui/react"; import type { Coin } from "@cosmjs/stargate"; import { findAttribute } from "@cosmjs/stargate/build/logs"; import type { ReactNode } from "react"; @@ -134,7 +134,7 @@ export const TxMsgExpand = ({ msgIcon = "migrate"; content = ( - Migrate{" "} + Migrate { + const { + chainConfig: { registryChainName }, + } = useCelatoneApp(); + + // TODO: revisit new structure later + useAmplitude(registryChainName); + + return <>{children}; +}; diff --git a/src/lib/providers/chakra.tsx b/src/lib/providers/chakra.tsx new file mode 100644 index 000000000..04ad3c136 --- /dev/null +++ b/src/lib/providers/chakra.tsx @@ -0,0 +1,7 @@ +import { ChakraProvider as Provider } from "@chakra-ui/react"; + +import customTheme from "lib/styles/theme"; + +export const ChakraProvider = ({ children }: { children: React.ReactNode }) => ( + {children} +); diff --git a/src/lib/providers/cosmos-kit.tsx b/src/lib/providers/cosmos-kit.tsx new file mode 100644 index 000000000..fe53fc3f0 --- /dev/null +++ b/src/lib/providers/cosmos-kit.tsx @@ -0,0 +1,57 @@ +import type { EndpointOptions } from "@cosmos-kit/core"; +import { ChainProvider as Provider } from "@cosmos-kit/react"; +import { assets, chains } from "chain-registry"; + +import { CHAIN_CONFIGS } from "config/chain"; +import { useCelatoneApp } from "lib/app-provider"; +import { + localosmosis, + localosmosisAsset, +} from "lib/chain-registry/localosmosis"; +import { sei, seiAssets } from "lib/chain-registry/sei"; +import { + terra2testnet, + terra2testnetAssets, +} from "lib/chain-registry/terra2testnet"; + +// Remark: The avaliable wallet list won't change after the app is loaded. +// So we have to revisit this later if we have another solution. +export const ChainProvider = ({ children }: { children: React.ReactNode }) => { + const { + chainConfig: { wallets }, + } = useCelatoneApp(); + const availableChainsEndpoints = Object.values(CHAIN_CONFIGS).reduce< + EndpointOptions["endpoints"] + >( + (endpoints, config) => ({ + ...endpoints, + [config.registryChainName]: { + rpc: [config.rpc], + rest: [config.lcd], + }, + }), + {} + ); + + return ( + "direct", + }} + > + {children} + + ); +}; diff --git a/src/lib/providers/index.tsx b/src/lib/providers/index.tsx new file mode 100644 index 000000000..1c5a14b53 --- /dev/null +++ b/src/lib/providers/index.tsx @@ -0,0 +1,24 @@ +import { AppProvider } from "lib/app-provider"; + +import { AmplitudeProvider } from "./amplitude"; +import { ChakraProvider } from "./chakra"; +import { ChainProvider } from "./cosmos-kit"; +import { QueryClientProvider } from "./query-client"; +import { StoreProvider } from "./store"; +import { TxBroadcastProvider } from "./tx-broadcast"; + +export default ({ children }: { children: React.ReactNode }) => ( + + + + + + + {children} + + + + + + +); diff --git a/src/lib/providers/query-client.tsx b/src/lib/providers/query-client.tsx new file mode 100644 index 000000000..bc01c3872 --- /dev/null +++ b/src/lib/providers/query-client.tsx @@ -0,0 +1,11 @@ +import { + QueryClient, + QueryClientProvider as Provider, +} from "@tanstack/react-query"; +import type { ReactNode } from "react"; + +export const QueryClientProvider = ({ children }: { children: ReactNode }) => { + const queryClient = new QueryClient(); + + return {children}; +}; diff --git a/src/lib/services/faucetService.ts b/src/lib/services/faucetService.ts index 410a45e43..a90c7e021 100644 --- a/src/lib/services/faucetService.ts +++ b/src/lib/services/faucetService.ts @@ -32,7 +32,7 @@ export const useFaucetInfo = (): UseQueryResult => { }; return useQuery({ - queryKey: [CELATONE_QUERY_KEYS.FAUCET_INFO, faucet], + queryKey: [CELATONE_QUERY_KEYS.FAUCET_INFO, faucet, assetInfos], queryFn, enabled: faucet.enabled, retry: 2, diff --git a/src/lib/services/validatorService.ts b/src/lib/services/validatorService.ts index 33295ba6e..ff3fb00a8 100644 --- a/src/lib/services/validatorService.ts +++ b/src/lib/services/validatorService.ts @@ -22,7 +22,7 @@ export const useValidator = ( ): UseQueryResult => { const lcdEndpoint = useBaseApiRoute("rest"); const queryFn = async ({ queryKey }: QueryFunctionContext) => - getValidator(queryKey[2], queryKey[3] as ValidatorAddr); + getValidator(queryKey[1], queryKey[2] as ValidatorAddr); return useQuery( [ @@ -81,6 +81,8 @@ export const useValidatorImage = ( CELATONE_QUERY_KEYS.VALIDATOR_IDENTITY_BY_ADDRESS, chainName, validator?.validatorAddress, + validator?.identity, + validator?.moniker, ], queryFn: async () => { if (!validator) return Promise.resolve(""); diff --git a/src/lib/types/tx/msg.ts b/src/lib/types/tx/msg.ts index 9609344c3..5f8ef35b7 100644 --- a/src/lib/types/tx/msg.ts +++ b/src/lib/types/tx/msg.ts @@ -24,7 +24,7 @@ export enum AccessType { export interface AccessConfig { permission: AccessType; address: Addr; - addresses: Addr[]; + addresses?: Addr[]; } export interface MsgStoreCode { diff --git a/src/lib/utils/funds.test.ts b/src/lib/utils/funds.test.ts index fa9c87687..cd64bf4b0 100644 --- a/src/lib/utils/funds.test.ts +++ b/src/lib/utils/funds.test.ts @@ -1,6 +1,6 @@ import type { Coin } from "@cosmjs/stargate"; -import { sortDenoms } from "./funds"; +import { coinsFromStr, coinsToStr, sortDenoms } from "./funds"; describe("sortDenoms", () => { const sortedCoins = [ @@ -97,4 +97,34 @@ describe("sortDenoms", () => { }, ]); }); + + test("parse Coins from empty string", () => { + expect(coinsFromStr("")).toEqual([]); + }); + + test("parse Coins from string", () => { + expect(coinsFromStr("1000adenom, 1ibc/bdenom")).toEqual([ + { denom: "adenom", amount: "1000" }, + { + denom: "ibc/bdenom", + amount: "1", + }, + ]); + }); + + test("parse empty Coins to string", () => { + expect(coinsToStr([])).toEqual(""); + }); + + test("parse Coins to string", () => { + expect( + coinsToStr([ + { + denom: "ibc/bdenom", + amount: "1", + }, + { denom: "adenom", amount: "1000" }, + ]) + ).toEqual("1ibc/bdenom,1000adenom"); + }); }); diff --git a/src/lib/utils/funds.ts b/src/lib/utils/funds.ts index e00a21eb2..484552e31 100644 --- a/src/lib/utils/funds.ts +++ b/src/lib/utils/funds.ts @@ -1,4 +1,4 @@ -import type { Coin } from "@cosmjs/stargate"; +import { parseCoins, type Coin } from "@cosmjs/stargate"; import type { Token, Option } from "lib/types"; @@ -22,3 +22,14 @@ export const fabricateFunds = (assets: CoinWithPrecision[]): Coin[] => amount: exponentify(asset.amount as Token, asset.precision).toFixed(0), })) ); + +export const coinsFromStr = (str: string): Coin[] => { + try { + return parseCoins(str); + } catch { + return []; + } +}; + +export const coinsToStr = (coins: Coin[]): string => + coins.map((coin) => `${coin.amount}${coin.denom}`).toString(); diff --git a/src/lib/utils/tx/composeMsg.ts b/src/lib/utils/tx/composeMsg.ts index ec1b5ca9f..afcd8e5f5 100644 --- a/src/lib/utils/tx/composeMsg.ts +++ b/src/lib/utils/tx/composeMsg.ts @@ -27,7 +27,7 @@ interface StoreCodeMsgArgs { sender: Addr; wasmByteCode: Uint8Array; permission: AccessType; - addresses: Addr[]; + addresses?: Addr[]; } export const composeStoreCodeMsg = ({ diff --git a/src/pages/[network]/my-codes.tsx b/src/pages/[network]/my-codes.tsx deleted file mode 100644 index 9b0ad628f..000000000 --- a/src/pages/[network]/my-codes.tsx +++ /dev/null @@ -1,3 +0,0 @@ -import MyCodes from "lib/pages/my-codes"; - -export default MyCodes; diff --git a/src/pages/[network]/saved-codes.tsx b/src/pages/[network]/saved-codes.tsx new file mode 100644 index 000000000..4cbc968a9 --- /dev/null +++ b/src/pages/[network]/saved-codes.tsx @@ -0,0 +1,3 @@ +import SavedCodes from "lib/pages/saved-codes"; + +export default SavedCodes; diff --git a/src/pages/[network]/stored-codes.tsx b/src/pages/[network]/stored-codes.tsx new file mode 100644 index 000000000..216bd75bc --- /dev/null +++ b/src/pages/[network]/stored-codes.tsx @@ -0,0 +1,3 @@ +import StoredCodes from "lib/pages/stored-codes"; + +export default StoredCodes; diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx index 41b94ade0..035ac7b08 100644 --- a/src/pages/_app.tsx +++ b/src/pages/_app.tsx @@ -1,29 +1,15 @@ -import type { EndpointOptions } from "@cosmos-kit/core"; -import { wallets } from "@cosmos-kit/keplr"; -import { ChainProvider } from "@cosmos-kit/react"; -import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; -import { assets, chains } from "chain-registry"; import localforage from "localforage"; import { configurePersistable } from "mobx-persist-store"; import { enableStaticRendering } from "mobx-react-lite"; import type { AppProps } from "next/app"; import Head from "next/head"; -import Script from "next/script"; +import "@interchain-ui/react/styles"; -import { CHAIN_CONFIGS } from "config/chain"; -import { AppProvider, NavProvider } from "lib/app-provider"; -import { - localosmosis, - localosmosisAsset, -} from "lib/chain-registry/localosmosis"; -import { sei, seiAssets } from "lib/chain-registry/sei"; -import { Chakra } from "lib/components/Chakra"; import { MobileGuard } from "lib/components/MobileGuard"; import { CelatoneSeo } from "lib/components/Seo"; import Layout from "lib/layout"; import "lib/styles/globals.css"; -import { StoreProvider } from "lib/providers/store"; -import { TxBroadcastProvider } from "lib/providers/tx-broadcast"; +import Providers from "lib/providers"; enableStaticRendering(typeof window === "undefined"); @@ -41,78 +27,21 @@ configurePersistable({ stringify: false, }); -const availableChainsEndpoints = Object.values(CHAIN_CONFIGS).reduce< - EndpointOptions["endpoints"] ->( - (endpoints, config) => ({ - ...endpoints, - [config.registryChainName]: { - rpc: [config.rpc], - rest: [config.lcd], - }, - }), - {} -); - -const MyApp = ({ Component, pageProps }: AppProps) => { - const queryClient = new QueryClient(); - - return ( - - - - - "direct", - }} - wrappedWithChakra - > - - - - - - - - - - - - - - - - - - - - - ); -}; + + + + + + + + +); export default MyApp; diff --git a/src/pages/_document.tsx b/src/pages/_document.tsx index a20167b4c..ed59cb40c 100644 --- a/src/pages/_document.tsx +++ b/src/pages/_document.tsx @@ -1,7 +1,7 @@ -/* eslint-disable react/jsx-props-no-spreading */ import { ColorModeScript } from "@chakra-ui/react"; import type { DocumentContext } from "next/document"; import Document, { Html, Head, Main, NextScript } from "next/document"; +import Script from "next/script"; import { CURR_THEME } from "env"; import Meta from "lib/components/Meta"; @@ -27,6 +27,21 @@ class MyDocument extends Document { />
+ ); diff --git a/src/pages/my-codes.tsx b/src/pages/my-codes.tsx deleted file mode 100644 index 9b0ad628f..000000000 --- a/src/pages/my-codes.tsx +++ /dev/null @@ -1,3 +0,0 @@ -import MyCodes from "lib/pages/my-codes"; - -export default MyCodes; diff --git a/src/pages/saved-codes.tsx b/src/pages/saved-codes.tsx new file mode 100644 index 000000000..4cbc968a9 --- /dev/null +++ b/src/pages/saved-codes.tsx @@ -0,0 +1,3 @@ +import SavedCodes from "lib/pages/saved-codes"; + +export default SavedCodes; diff --git a/src/pages/stored-codes.tsx b/src/pages/stored-codes.tsx new file mode 100644 index 000000000..216bd75bc --- /dev/null +++ b/src/pages/stored-codes.tsx @@ -0,0 +1,3 @@ +import StoredCodes from "lib/pages/stored-codes"; + +export default StoredCodes; diff --git a/yarn.lock b/yarn.lock index 93153037e..2d6414267 100644 --- a/yarn.lock +++ b/yarn.lock @@ -801,24 +801,24 @@ core-js-pure "^3.20.2" regenerator-runtime "^0.13.4" -"@babel/runtime@7.11.2": - version "7.11.2" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.11.2.tgz#f549c13c754cc40b87644b9fa9f09a6a95fe0736" - integrity sha512-TeWkU52so0mPtDcaCTxNBI/IHiz0pZgr8VEFqXFtZWpYD08ZB6FaSwVAS8MKRQAP3bYKiVjwysOJgMFY28o6Tw== - dependencies: - regenerator-runtime "^0.13.4" - -"@babel/runtime@^7.0.0", "@babel/runtime@^7.10.2", "@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.16.3": +"@babel/runtime@^7.0.0", "@babel/runtime@^7.10.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.16.3": version "7.19.0" resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.19.0.tgz" integrity sha512-eR8Lo9hnDS7tqkO7NsV+mKvCmv5boaXFSZ70DnfhcgiEne8hv9oCEd36Klw74EtizEqLsy4YnW8UWwpBVolHZA== dependencies: regenerator-runtime "^0.13.4" -"@babel/runtime@^7.11.2", "@babel/runtime@^7.12.0", "@babel/runtime@^7.18.3", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.7": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.22.5.tgz#8564dd588182ce0047d55d7a75e93921107b57ec" - integrity sha512-ecjvYlnAaZ/KVneE/OdKYBYfgXV3Ptu6zQWmgEF7vwKhQnvVS6bjMD2XYgj+SNvQ1GfK/pjgokfPkC/2CO8CuA== +"@babel/runtime@^7.12.0", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.7": + version "7.22.10" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.22.10.tgz#ae3e9631fd947cb7e3610d3e9d8fef5f76696682" + integrity sha512-21t/fkKLMZI4pqP2wlmsQAWnYW1PDyKyyUV4vCi+B25ydmdaYTKXPwCj0BzSUnZf4seIiYvSA3jcZ3gdsMFkLQ== + dependencies: + regenerator-runtime "^0.14.0" + +"@babel/runtime@^7.12.13", "@babel/runtime@^7.17.8", "@babel/runtime@^7.18.3": + version "7.22.6" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.22.6.tgz#57d64b9ae3cff1d67eb067ae117dac087f5bd438" + integrity sha512-wDb5pWm4WDdF6LFUde3Jl8WzPA+3ZbxYqkC6xAXuD3irdEHN1k0NfTRrJD8ZD378SJ61miMLCqIOXYhd8x+AJQ== dependencies: regenerator-runtime "^0.13.11" @@ -970,7 +970,7 @@ "@chakra-ui/accordion@2.1.2": version "2.1.2" - resolved "https://registry.npmjs.org/@chakra-ui/accordion/-/accordion-2.1.2.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/accordion/-/accordion-2.1.2.tgz#f9d384b80f68a92689fa7ad4e43bd8944e6945c6" integrity sha512-Jf7A6I0eIGk34zO5TiTW8orJOFQb5A/D1ekNYbaukNccoUPKJg/xdQ/b00oIR6LT93nJxggkoP/vszfmmTHuFg== dependencies: "@chakra-ui/descendant" "3.0.10" @@ -980,48 +980,20 @@ "@chakra-ui/react-use-merge-refs" "2.0.4" "@chakra-ui/transition" "2.0.11" -"@chakra-ui/accordion@2.2.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@chakra-ui/accordion/-/accordion-2.2.0.tgz#a38ed8e7d0a7ccc6910282f913c42cf6deea7215" - integrity sha512-2IK1iLzTZ22u8GKPPPn65mqJdZidn4AvkgAbv17ISdKA07VHJ8jSd4QF1T5iCXjKfZ0XaXozmhP4kDhjwF2IbQ== - dependencies: - "@chakra-ui/descendant" "3.0.14" - "@chakra-ui/icon" "3.0.16" - "@chakra-ui/react-context" "2.0.8" - "@chakra-ui/react-use-controllable-state" "2.0.8" - "@chakra-ui/react-use-merge-refs" "2.0.7" - "@chakra-ui/shared-utils" "2.0.5" - "@chakra-ui/transition" "2.0.16" - "@chakra-ui/alert@2.0.11": version "2.0.11" - resolved "https://registry.npmjs.org/@chakra-ui/alert/-/alert-2.0.11.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/alert/-/alert-2.0.11.tgz#d792b0684ae7810befa3874af5bdd4aa115513a2" integrity sha512-n40KHU3j1H6EbIdgptjEad92V7Fpv7YD++ZBjy2g1h4w9ay9nw4kGHib3gaIkBupLf52CfLqySEc8w0taoIlXQ== dependencies: "@chakra-ui/icon" "3.0.11" "@chakra-ui/react-context" "2.0.4" "@chakra-ui/spinner" "2.0.10" -"@chakra-ui/alert@2.1.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@chakra-ui/alert/-/alert-2.1.0.tgz#7a234ac6426231b39243088648455cbcf1cbdf24" - integrity sha512-OcfHwoXI5VrmM+tHJTHT62Bx6TfyfCxSa0PWUOueJzSyhlUOKBND5we6UtrOB7D0jwX45qKKEDJOLG5yCG21jQ== - dependencies: - "@chakra-ui/icon" "3.0.16" - "@chakra-ui/react-context" "2.0.8" - "@chakra-ui/shared-utils" "2.0.5" - "@chakra-ui/spinner" "2.0.13" - "@chakra-ui/anatomy@2.0.7": version "2.0.7" - resolved "https://registry.npmjs.org/@chakra-ui/anatomy/-/anatomy-2.0.7.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/anatomy/-/anatomy-2.0.7.tgz#33e60c7c4d6e5f949f6f8308249dc571f84ead1e" integrity sha512-vzcB2gcsGCxhrKbldQQV6LnBPys4eSSsH2UA2mLsT+J3WlXw0aodZw0eE/nH7yLxe4zaQ4Gnc0KjkFW4EWNKSg== -"@chakra-ui/anatomy@2.1.2": - version "2.1.2" - resolved "https://registry.yarnpkg.com/@chakra-ui/anatomy/-/anatomy-2.1.2.tgz#ea66b1841e7195da08ddc862daaa3f3e56e565f5" - integrity sha512-pKfOS/mztc4sUXHNc8ypJ1gPWSolWT770jrgVRfolVbYlki8y5Y+As996zMF6k5lewTu6j9DQequ7Cc9a69IVQ== - "@chakra-ui/anatomy@^2.1.0": version "2.1.0" resolved "https://registry.npmjs.org/@chakra-ui/anatomy/-/anatomy-2.1.0.tgz" @@ -1029,78 +1001,35 @@ "@chakra-ui/avatar@2.2.0": version "2.2.0" - resolved "https://registry.npmjs.org/@chakra-ui/avatar/-/avatar-2.2.0.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/avatar/-/avatar-2.2.0.tgz#58b5e650f7e4b3ab229f50e6a102c54b6eb4b23a" integrity sha512-mpAkfr/JG+BNBw2WvU55CSRFYKeFBUyAQAu3YulznLzi2U3e7k3IA0J8ofbrDYlSH/9KqkDuuSrxqGZgct+Nug== dependencies: "@chakra-ui/image" "2.0.11" "@chakra-ui/react-children-utils" "2.0.3" "@chakra-ui/react-context" "2.0.4" -"@chakra-ui/avatar@2.2.11": - version "2.2.11" - resolved "https://registry.yarnpkg.com/@chakra-ui/avatar/-/avatar-2.2.11.tgz#1e5ded963ab3209fe1d16bba21f0aec616be56da" - integrity sha512-CJFkoWvlCTDJTUBrKA/aVyG5Zz6TBEIVmmsJtqC6VcQuVDTxkWod8ruXnjb0LT2DUveL7xR5qZM9a5IXcsH3zg== - dependencies: - "@chakra-ui/image" "2.0.16" - "@chakra-ui/react-children-utils" "2.0.6" - "@chakra-ui/react-context" "2.0.8" - "@chakra-ui/shared-utils" "2.0.5" - "@chakra-ui/breadcrumb@2.1.0": version "2.1.0" - resolved "https://registry.npmjs.org/@chakra-ui/breadcrumb/-/breadcrumb-2.1.0.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/breadcrumb/-/breadcrumb-2.1.0.tgz#530ded99f931cfcb9f4bd4d951bc82b0a4e102ac" integrity sha512-khBR579SLDEo6Wuo3tETRY6m0yJD/WCvSR7Res2g1B6OJgc9OQGM7yIMu4OdLUTwfXsCnlHTDoSQPUxFOVAMIQ== dependencies: "@chakra-ui/react-children-utils" "2.0.3" "@chakra-ui/react-context" "2.0.4" -"@chakra-ui/breadcrumb@2.1.5": - version "2.1.5" - resolved "https://registry.yarnpkg.com/@chakra-ui/breadcrumb/-/breadcrumb-2.1.5.tgz#a43b22cc8005291a615696a8c88efc37064562f3" - integrity sha512-p3eQQrHQBkRB69xOmNyBJqEdfCrMt+e0eOH+Pm/DjFWfIVIbnIaFbmDCeWClqlLa21Ypc6h1hR9jEmvg8kmOog== - dependencies: - "@chakra-ui/react-children-utils" "2.0.6" - "@chakra-ui/react-context" "2.0.8" - "@chakra-ui/shared-utils" "2.0.5" - "@chakra-ui/breakpoint-utils@2.0.4": version "2.0.4" - resolved "https://registry.npmjs.org/@chakra-ui/breakpoint-utils/-/breakpoint-utils-2.0.4.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/breakpoint-utils/-/breakpoint-utils-2.0.4.tgz#6231eff8b20f4e3cbb4eb7c86d05c927679d905b" integrity sha512-SUUEYnA/FCIKYDHMuEXcnBMwet+6RAAjQ+CqGD1hlwKPTfh7EK9fS8FoVAJa9KpRKAc/AawzPkgwvorzPj8NSg== -"@chakra-ui/breakpoint-utils@2.0.8": - version "2.0.8" - resolved "https://registry.yarnpkg.com/@chakra-ui/breakpoint-utils/-/breakpoint-utils-2.0.8.tgz#750d3712668b69f6e8917b45915cee0e08688eed" - integrity sha512-Pq32MlEX9fwb5j5xx8s18zJMARNHlQZH2VH1RZgfgRDpp7DcEgtRW5AInfN5CfqdHLO1dGxA7I3MqEuL5JnIsA== - dependencies: - "@chakra-ui/shared-utils" "2.0.5" - "@chakra-ui/button@2.0.11": version "2.0.11" - resolved "https://registry.npmjs.org/@chakra-ui/button/-/button-2.0.11.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/button/-/button-2.0.11.tgz#98e0aa1e35ea7e193bb50f9a4b5d0ea23202ace8" integrity sha512-J6iMRITqxTxa0JexHUY9c7BXUrTZtSkl3jZ2hxiFybB4MQL8J2wZ24O846B6M+WTYqy7XVuHRuVURnH4czWesw== dependencies: "@chakra-ui/react-context" "2.0.4" "@chakra-ui/react-use-merge-refs" "2.0.4" "@chakra-ui/spinner" "2.0.10" -"@chakra-ui/button@2.0.18": - version "2.0.18" - resolved "https://registry.yarnpkg.com/@chakra-ui/button/-/button-2.0.18.tgz#c13d2e404e22a9873ba5373fde494bedafe32fdd" - integrity sha512-E3c99+lOm6ou4nQVOTLkG+IdOPMjsQK+Qe7VyP8A/xeAMFONuibrWPRPpprr4ZkB4kEoLMfNuyH2+aEza3ScUA== - dependencies: - "@chakra-ui/react-context" "2.0.8" - "@chakra-ui/react-use-merge-refs" "2.0.7" - "@chakra-ui/shared-utils" "2.0.5" - "@chakra-ui/spinner" "2.0.13" - -"@chakra-ui/card@2.1.6": - version "2.1.6" - resolved "https://registry.yarnpkg.com/@chakra-ui/card/-/card-2.1.6.tgz#27176bdee363ecab7d563c4997c4b2fe9e835ecc" - integrity sha512-fFd/WAdRNVY/WOSQv4skpy0WeVhhI0f7dTY1Sm0jVl0KLmuP/GnpsWtKtqWjNcV00K963EXDyhlk6+9oxbP4gw== - dependencies: - "@chakra-ui/shared-utils" "2.0.5" - "@chakra-ui/card@^2.1.1": version "2.1.1" resolved "https://registry.npmjs.org/@chakra-ui/card/-/card-2.1.1.tgz" @@ -1108,26 +1037,9 @@ dependencies: "@chakra-ui/react-context" "2.0.5" -"@chakra-ui/checkbox@2.2.15": - version "2.2.15" - resolved "https://registry.yarnpkg.com/@chakra-ui/checkbox/-/checkbox-2.2.15.tgz#e5ff65159f698d50edecee6b661b87e341eace70" - integrity sha512-Ju2yQjX8azgFa5f6VLPuwdGYobZ+rdbcYqjiks848JvPc75UsPhpS05cb4XlrKT7M16I8txDA5rPJdqqFicHCA== - dependencies: - "@chakra-ui/form-control" "2.0.18" - "@chakra-ui/react-context" "2.0.8" - "@chakra-ui/react-types" "2.0.7" - "@chakra-ui/react-use-callback-ref" "2.0.7" - "@chakra-ui/react-use-controllable-state" "2.0.8" - "@chakra-ui/react-use-merge-refs" "2.0.7" - "@chakra-ui/react-use-safe-layout-effect" "2.0.5" - "@chakra-ui/react-use-update-effect" "2.0.7" - "@chakra-ui/shared-utils" "2.0.5" - "@chakra-ui/visually-hidden" "2.0.15" - "@zag-js/focus-visible" "0.2.2" - "@chakra-ui/checkbox@2.2.2": version "2.2.2" - resolved "https://registry.npmjs.org/@chakra-ui/checkbox/-/checkbox-2.2.2.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/checkbox/-/checkbox-2.2.2.tgz#494d7090ac11a0a43d05b7849aff6085f7a91045" integrity sha512-Y6Zbkkk5VNoe0RzqU6F+rKlFVPlubz1KIgYcb7CCNHGOM97dLtRm78eAvJ+7Xmpitr+7zZ4hJLLjfAz+e1X7rA== dependencies: "@chakra-ui/form-control" "2.0.11" @@ -1151,33 +1063,18 @@ "@chakra-ui/clickable@2.0.10": version "2.0.10" - resolved "https://registry.npmjs.org/@chakra-ui/clickable/-/clickable-2.0.10.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/clickable/-/clickable-2.0.10.tgz#e89b7b3eaf9364753f6205e36fd5128b26a617d8" integrity sha512-G6JdR6yAMlXpfjOJ70W2FL7aUwNuomiMFtkneeTpk7Q42bJ5iGHfYlbZEx5nJd8iB+UluXVM4xlhMv2MyytjGw== dependencies: "@chakra-ui/react-use-merge-refs" "2.0.4" -"@chakra-ui/clickable@2.0.14": - version "2.0.14" - resolved "https://registry.yarnpkg.com/@chakra-ui/clickable/-/clickable-2.0.14.tgz#88093008672a2a30bdd2a30ff815dcc2c88c01a5" - integrity sha512-jfsM1qaD74ZykLHmvmsKRhDyokLUxEfL8Il1VoZMNX5RBI0xW/56vKpLTFF/v/+vLPLS+Te2cZdD4+2O+G6ulA== - dependencies: - "@chakra-ui/react-use-merge-refs" "2.0.7" - "@chakra-ui/shared-utils" "2.0.5" - "@chakra-ui/close-button@2.0.11": version "2.0.11" - resolved "https://registry.npmjs.org/@chakra-ui/close-button/-/close-button-2.0.11.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/close-button/-/close-button-2.0.11.tgz#8b0679da42738229014d3807885d05fac0fdf448" integrity sha512-9WF/nwwK9BldS89WQ5PtXK2nFS4r8QOgKls2BOwXfE+rGmOUZtOsu8ne/drXRjgkiBRETR6CxdyUjm7EPzXllw== dependencies: "@chakra-ui/icon" "3.0.11" -"@chakra-ui/close-button@2.0.17": - version "2.0.17" - resolved "https://registry.yarnpkg.com/@chakra-ui/close-button/-/close-button-2.0.17.tgz#d43d3a2ea1f08250f8d0da7704baf0e1fbd91b4b" - integrity sha512-05YPXk456t1Xa3KpqTrvm+7smx+95dmaPiwjiBN3p7LHUQVHJd8ZXSDB0V+WKi419k3cVQeJUdU/azDO2f40sw== - dependencies: - "@chakra-ui/icon" "3.0.16" - "@chakra-ui/color-mode@1.4.8": version "1.4.8" resolved "https://registry.yarnpkg.com/@chakra-ui/color-mode/-/color-mode-1.4.8.tgz#e5367b909f5b4c782b239f9d37d4cf1a44c28559" @@ -1187,57 +1084,31 @@ "@chakra-ui/react-env" "1.1.6" "@chakra-ui/utils" "1.10.4" -"@chakra-ui/color-mode@2.1.12": - version "2.1.12" - resolved "https://registry.yarnpkg.com/@chakra-ui/color-mode/-/color-mode-2.1.12.tgz#c0caeadd5f87fadbeefc6826beabac6c4a88d8f5" - integrity sha512-sYyfJGDoJSLYO+V2hxV9r033qhte5Nw/wAn5yRGGZnEEN1dKPEdWQ3XZvglWSDTNd0w9zkoH2w6vP4FBBYb/iw== - dependencies: - "@chakra-ui/react-use-safe-layout-effect" "2.0.5" - "@chakra-ui/color-mode@2.1.9": version "2.1.9" - resolved "https://registry.npmjs.org/@chakra-ui/color-mode/-/color-mode-2.1.9.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/color-mode/-/color-mode-2.1.9.tgz#d3a6f9ba9eee15d9e14cc96484e25d44cef1dbc1" integrity sha512-0kx0I+AQon8oS23/X+qMtnhsv/1BUulyJvU56p3Uh8CRaBfgJ7Ly9CerShoUL+5kadu6hN1M9oty4cugaCwv2w== dependencies: "@chakra-ui/react-use-safe-layout-effect" "2.0.2" "@chakra-ui/control-box@2.0.10": version "2.0.10" - resolved "https://registry.npmjs.org/@chakra-ui/control-box/-/control-box-2.0.10.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/control-box/-/control-box-2.0.10.tgz#e8a849c9f0fa085da78ee15dda7e13e1734b983d" integrity sha512-sHmZanFLEv4IDATl19ZTxq8Bi8PtjfvnsN6xF4k7JGSYUnk1YXUf1coyW7WKdcsczOASrMikfsLc3iEVAzx4Ng== -"@chakra-ui/control-box@2.0.13": - version "2.0.13" - resolved "https://registry.yarnpkg.com/@chakra-ui/control-box/-/control-box-2.0.13.tgz#ffe9634d0c3aecb8e1eb7da19e64fb3d2b181d03" - integrity sha512-FEyrU4crxati80KUF/+1Z1CU3eZK6Sa0Yv7Z/ydtz9/tvGblXW9NFanoomXAOvcIFLbaLQPPATm9Gmpr7VG05A== - "@chakra-ui/counter@2.0.10": version "2.0.10" - resolved "https://registry.npmjs.org/@chakra-ui/counter/-/counter-2.0.10.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/counter/-/counter-2.0.10.tgz#861f00db021235892dfe0407e739a259f1c233b2" integrity sha512-MZK8UKUZp4nFMd+GlV/cq0NIARS7UdlubTuCx+wockw9j2JI5OHzsyK0XiWuJiq5psegSTzpbtT99QfAUm3Yiw== dependencies: "@chakra-ui/number-utils" "2.0.4" "@chakra-ui/react-use-callback-ref" "2.0.4" -"@chakra-ui/counter@2.0.14": - version "2.0.14" - resolved "https://registry.yarnpkg.com/@chakra-ui/counter/-/counter-2.0.14.tgz#6e37a863afd2e87d7c94208245e81777640e76e2" - integrity sha512-KxcSRfUbb94dP77xTip2myoE7P2HQQN4V5fRJmNAGbzcyLciJ+aDylUU/UxgNcEjawUp6Q242NbWb1TSbKoqog== - dependencies: - "@chakra-ui/number-utils" "2.0.7" - "@chakra-ui/react-use-callback-ref" "2.0.7" - "@chakra-ui/shared-utils" "2.0.5" - "@chakra-ui/css-reset@2.0.8": version "2.0.8" - resolved "https://registry.npmjs.org/@chakra-ui/css-reset/-/css-reset-2.0.8.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/css-reset/-/css-reset-2.0.8.tgz#093ce6b166b37f2dd14e63f246635c463a59c106" integrity sha512-VuDD1rk1pFc+dItk4yUcstyoC9D2B35hatHDBtlPMqTczFAzpbgVJJYgEHANatXGfulM5SdckmYEIJ3Tac1Rtg== -"@chakra-ui/css-reset@2.1.2": - version "2.1.2" - resolved "https://registry.yarnpkg.com/@chakra-ui/css-reset/-/css-reset-2.1.2.tgz#a4cd1601e8376a74b8dd62a9089cb8aaac1ee800" - integrity sha512-4ySTLd+3iRpp4lX0yI9Yo2uQm2f+qwYGNOZF0cNcfN+4UJCd3IsaWxYRR/Anz+M51NVldZbYzC+TEYC/kpJc4A== - "@chakra-ui/descendant@2.1.4": version "2.1.4" resolved "https://registry.yarnpkg.com/@chakra-ui/descendant/-/descendant-2.1.4.tgz#b85c52b0b429da0a08d0950b4f8bef61b94f43f6" @@ -1247,33 +1118,20 @@ "@chakra-ui/descendant@3.0.10": version "3.0.10" - resolved "https://registry.npmjs.org/@chakra-ui/descendant/-/descendant-3.0.10.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/descendant/-/descendant-3.0.10.tgz#e54c95270896c451f61b57d31719ee042f4e1827" integrity sha512-MHH0Qdm0fGllGP2xgx4WOycmrpctyyEdGw6zxcfs2VqZNlrwmjG3Yb9eVY+Q7UmEv5rwAq6qRn7BhQxgSPn3Cg== dependencies: "@chakra-ui/react-context" "2.0.4" "@chakra-ui/react-use-merge-refs" "2.0.4" -"@chakra-ui/descendant@3.0.14": - version "3.0.14" - resolved "https://registry.yarnpkg.com/@chakra-ui/descendant/-/descendant-3.0.14.tgz#fe8bac3f0e1ffe562e3e73eac393dbf222d57e13" - integrity sha512-+Ahvp9H4HMpfScIv9w1vaecGz7qWAaK1YFHHolz/SIsGLaLGlbdp+5UNabQC7L6TUnzzJDQDxzwif78rTD7ang== - dependencies: - "@chakra-ui/react-context" "2.0.8" - "@chakra-ui/react-use-merge-refs" "2.0.7" - "@chakra-ui/dom-utils@2.0.3": version "2.0.3" - resolved "https://registry.npmjs.org/@chakra-ui/dom-utils/-/dom-utils-2.0.3.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/dom-utils/-/dom-utils-2.0.3.tgz#8a5498b107d3a42662f3502f7b8965cb73bf6a33" integrity sha512-aeGlRmTxcv0cvW44DyeZHru1i68ZDQsXpfX2dnG1I1yBlT6GlVx1xYjCULis9mjhgvd2O3NfcYPRTkjNWTDUbA== -"@chakra-ui/dom-utils@2.1.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@chakra-ui/dom-utils/-/dom-utils-2.1.0.tgz#d15df89e458ef19756db04c7cfd084eb552454f0" - integrity sha512-ZmF2qRa1QZ0CMLU8M1zCfmw29DmPNtfjR9iTo74U5FPr3i1aoAh7fbJ4qAlZ197Xw9eAW28tvzQuoVWeL5C7fQ== - "@chakra-ui/editable@2.0.13": version "2.0.13" - resolved "https://registry.npmjs.org/@chakra-ui/editable/-/editable-2.0.13.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/editable/-/editable-2.0.13.tgz#4e6ff480956ae2dcacf4ba2a15019336486bd613" integrity sha512-GM3n8t3/TOFFcDOWF/tuKsnqn66isZLsU+FkMRY2o0E8XjLBGjCKuXInPW5SRBqhje7EHC+kwViLE780PfwXbw== dependencies: "@chakra-ui/react-context" "2.0.4" @@ -1286,50 +1144,22 @@ "@chakra-ui/react-use-update-effect" "2.0.4" "@chakra-ui/shared-utils" "2.0.2" -"@chakra-ui/editable@3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@chakra-ui/editable/-/editable-3.0.0.tgz#b61d4fba5a581b41856ebd85fd5d17c96a224323" - integrity sha512-q/7C/TM3iLaoQKlEiM8AY565i9NoaXtS6N6N4HWIEL5mZJPbMeHKxrCHUZlHxYuQJqFOGc09ZPD9fAFx1GkYwQ== - dependencies: - "@chakra-ui/react-context" "2.0.8" - "@chakra-ui/react-types" "2.0.7" - "@chakra-ui/react-use-callback-ref" "2.0.7" - "@chakra-ui/react-use-controllable-state" "2.0.8" - "@chakra-ui/react-use-focus-on-pointer-down" "2.0.6" - "@chakra-ui/react-use-merge-refs" "2.0.7" - "@chakra-ui/react-use-safe-layout-effect" "2.0.5" - "@chakra-ui/react-use-update-effect" "2.0.7" - "@chakra-ui/shared-utils" "2.0.5" - "@chakra-ui/event-utils@2.0.5": version "2.0.5" - resolved "https://registry.npmjs.org/@chakra-ui/event-utils/-/event-utils-2.0.5.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/event-utils/-/event-utils-2.0.5.tgz#23de21e319d1a70863953402d64cb4b0e6ce322f" integrity sha512-VXoOAIsM0PFKDlhm+EZxkWlUXd5UFTb/LTux3y3A+S9G5fDxLRvpiLWByPUgTFTCDFcgTCF+YnQtdWJB4DLyxg== -"@chakra-ui/event-utils@2.0.8": - version "2.0.8" - resolved "https://registry.yarnpkg.com/@chakra-ui/event-utils/-/event-utils-2.0.8.tgz#e6439ba200825a2f15d8f1973d267d1c00a6d1b4" - integrity sha512-IGM/yGUHS+8TOQrZGpAKOJl/xGBrmRYJrmbHfUE7zrG3PpQyXvbLDP1M+RggkCFVgHlJi2wpYIf0QtQlU0XZfw== - "@chakra-ui/focus-lock@2.0.12": version "2.0.12" - resolved "https://registry.npmjs.org/@chakra-ui/focus-lock/-/focus-lock-2.0.12.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/focus-lock/-/focus-lock-2.0.12.tgz#11c0301a326249efe269c2dd0f54b11a67a04321" integrity sha512-NvIP59A11ZNbxXZ3qwxSiQ5npjABkpSbTIjK0uZ9bZm5LMfepRnuuA19VsVlq31/BYV9nHFAy6xzIuG+Qf9xMA== dependencies: "@chakra-ui/dom-utils" "2.0.3" react-focus-lock "^2.9.1" -"@chakra-ui/focus-lock@2.0.17": - version "2.0.17" - resolved "https://registry.yarnpkg.com/@chakra-ui/focus-lock/-/focus-lock-2.0.17.tgz#c1896a80896e752b88e8681f9c9d626046de6dd5" - integrity sha512-V+m4Ml9E8QY66DUpHX/imInVvz5XJ5zx59Tl0aNancXgeVY1Rt/ZdxuZdPLCAmPC/MF3GUOgnEA+WU8i+VL6Gw== - dependencies: - "@chakra-ui/dom-utils" "2.1.0" - react-focus-lock "^2.9.4" - "@chakra-ui/form-control@2.0.11": version "2.0.11" - resolved "https://registry.npmjs.org/@chakra-ui/form-control/-/form-control-2.0.11.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/form-control/-/form-control-2.0.11.tgz#fbfdddb02d1b5d2c67ffdc721c434ff16693e4bd" integrity sha512-MVhIe0xY4Zn06IXRXFmS9tCa93snppK1SdUQb1P99Ipo424RrL5ykzLnJ8CAkQrhoVP3sxF7z3eOSzk8/iRfow== dependencies: "@chakra-ui/icon" "3.0.11" @@ -1337,17 +1167,6 @@ "@chakra-ui/react-types" "2.0.3" "@chakra-ui/react-use-merge-refs" "2.0.4" -"@chakra-ui/form-control@2.0.18": - version "2.0.18" - resolved "https://registry.yarnpkg.com/@chakra-ui/form-control/-/form-control-2.0.18.tgz#1923f293afde70b2b07ca731d98fef3660098c56" - integrity sha512-I0a0jG01IAtRPccOXSNugyRdUAe8Dy40ctqedZvznMweOXzbMCF1m+sHPLdWeWC/VI13VoAispdPY0/zHOdjsQ== - dependencies: - "@chakra-ui/icon" "3.0.16" - "@chakra-ui/react-context" "2.0.8" - "@chakra-ui/react-types" "2.0.7" - "@chakra-ui/react-use-merge-refs" "2.0.7" - "@chakra-ui/shared-utils" "2.0.5" - "@chakra-ui/form-control@^1.0.0": version "1.6.0" resolved "https://registry.yarnpkg.com/@chakra-ui/form-control/-/form-control-1.6.0.tgz#a2a7b82a385f75fababf3947d39e227b4d073929" @@ -1370,7 +1189,7 @@ "@chakra-ui/hooks@2.1.0": version "2.1.0" - resolved "https://registry.npmjs.org/@chakra-ui/hooks/-/hooks-2.1.0.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/hooks/-/hooks-2.1.0.tgz#a8df3692e407c2fed8cc551c8ce7f3fcd0ea9864" integrity sha512-4H6BDITq/YrStW99LXurgPkcz4qHSVy9V/QWXCvt1pCuiDTqNztiW4r508H3ApAOsL9NEbyXcM/zWYD7r5VDjA== dependencies: "@chakra-ui/react-utils" "2.0.8" @@ -1378,16 +1197,6 @@ compute-scroll-into-view "1.0.14" copy-to-clipboard "3.3.1" -"@chakra-ui/hooks@2.2.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@chakra-ui/hooks/-/hooks-2.2.0.tgz#f779bf85542dacd607abe7e67f4571cf8a1102fa" - integrity sha512-GZE64mcr20w+3KbCUPqQJHHmiFnX5Rcp8jS3YntGA4D5X2qU85jka7QkjfBwv/iduZ5Ei0YpCMYGCpi91dhD1Q== - dependencies: - "@chakra-ui/react-utils" "2.0.12" - "@chakra-ui/utils" "2.0.15" - compute-scroll-into-view "1.0.20" - copy-to-clipboard "3.3.3" - "@chakra-ui/icon@2.0.5", "@chakra-ui/icon@^2.0.0": version "2.0.5" resolved "https://registry.yarnpkg.com/@chakra-ui/icon/-/icon-2.0.5.tgz#d57f53e6a2c7ae1bae7292a1778fd466c02e2e29" @@ -1402,13 +1211,6 @@ dependencies: "@chakra-ui/shared-utils" "2.0.2" -"@chakra-ui/icon@3.0.16": - version "3.0.16" - resolved "https://registry.yarnpkg.com/@chakra-ui/icon/-/icon-3.0.16.tgz#6413ec637c0c3acc204301485f05451b5bcd6ba4" - integrity sha512-RpA1X5Ptz8Mt39HSyEIW1wxAz2AXyf9H0JJ5HVx/dBdMZaGMDJ0HyyPBVci0m4RCoJuyG1HHG/DXJaVfUTVAeg== - dependencies: - "@chakra-ui/shared-utils" "2.0.5" - "@chakra-ui/icons@^2.0.11": version "2.0.11" resolved "https://registry.npmjs.org/@chakra-ui/icons/-/icons-2.0.11.tgz" @@ -1418,22 +1220,14 @@ "@chakra-ui/image@2.0.11": version "2.0.11" - resolved "https://registry.npmjs.org/@chakra-ui/image/-/image-2.0.11.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/image/-/image-2.0.11.tgz#eb880ecd2fce47f22ef50bbbba66cbb027c0304c" integrity sha512-S6NqAprPcbHnck/J+2wg06r9SSol62v5A01O8Kke2PnAyjalMcS+6P59lDRO7wvPqsdxq4PPbSTZP6Dww2CvcA== dependencies: "@chakra-ui/react-use-safe-layout-effect" "2.0.2" -"@chakra-ui/image@2.0.16": - version "2.0.16" - resolved "https://registry.yarnpkg.com/@chakra-ui/image/-/image-2.0.16.tgz#0e3a48c3caa6dc1d340502ea96766d9ef31e27e8" - integrity sha512-iFypk1slgP3OK7VIPOtkB0UuiqVxNalgA59yoRM43xLIeZAEZpKngUVno4A2kFS61yKN0eIY4hXD3Xjm+25EJA== - dependencies: - "@chakra-ui/react-use-safe-layout-effect" "2.0.5" - "@chakra-ui/shared-utils" "2.0.5" - "@chakra-ui/input@2.0.12": version "2.0.12" - resolved "https://registry.npmjs.org/@chakra-ui/input/-/input-2.0.12.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/input/-/input-2.0.12.tgz#332db53a831daea4d76e1de6d3b4462fd50ae167" integrity sha512-lJ5necu+Wt698HdCTC7L/ErA2nNVJAra7+knPe0qMR+AizGEL7LKCV/bdQe7eggjvKsDGD4alJIEczUvm3JVUQ== dependencies: "@chakra-ui/form-control" "2.0.11" @@ -1442,20 +1236,9 @@ "@chakra-ui/react-context" "2.0.4" "@chakra-ui/shared-utils" "2.0.2" -"@chakra-ui/input@2.0.22": - version "2.0.22" - resolved "https://registry.yarnpkg.com/@chakra-ui/input/-/input-2.0.22.tgz#4c1f166f53555c698bb65950772314f78c147450" - integrity sha512-dCIC0/Q7mjZf17YqgoQsnXn0bus6vgriTRn8VmxOc+WcVl+KBSTBWujGrS5yu85WIFQ0aeqQvziDnDQybPqAbA== - dependencies: - "@chakra-ui/form-control" "2.0.18" - "@chakra-ui/object-utils" "2.1.0" - "@chakra-ui/react-children-utils" "2.0.6" - "@chakra-ui/react-context" "2.0.8" - "@chakra-ui/shared-utils" "2.0.5" - "@chakra-ui/layout@2.1.9": version "2.1.9" - resolved "https://registry.npmjs.org/@chakra-ui/layout/-/layout-2.1.9.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/layout/-/layout-2.1.9.tgz#3e9cc7b5915e033907367e40fc97d218efa5f777" integrity sha512-ztsavtirtdtjxdqIkGR6fVcrffHp6hs1twRFO/dK14FGXrX3Nn9mi3J1fr1ITBHJq6y5B3yFEj0LHN2fO8dYyw== dependencies: "@chakra-ui/breakpoint-utils" "2.0.4" @@ -1465,18 +1248,6 @@ "@chakra-ui/react-context" "2.0.4" "@chakra-ui/shared-utils" "2.0.2" -"@chakra-ui/layout@2.2.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@chakra-ui/layout/-/layout-2.2.0.tgz#a0832ba419743d8d7e442acfce59740626664d2f" - integrity sha512-WvfsWQjqzbCxv7pbpPGVKxj9eQr7MC2i37ag4Wn7ClIG7uPuwHYTUWOnjnu27O3H/zA4cRVZ4Hs3GpSPbojZFQ== - dependencies: - "@chakra-ui/breakpoint-utils" "2.0.8" - "@chakra-ui/icon" "3.0.16" - "@chakra-ui/object-utils" "2.1.0" - "@chakra-ui/react-children-utils" "2.0.6" - "@chakra-ui/react-context" "2.0.8" - "@chakra-ui/shared-utils" "2.0.5" - "@chakra-ui/layout@^1.0.0": version "1.8.0" resolved "https://registry.yarnpkg.com/@chakra-ui/layout/-/layout-1.8.0.tgz#f95e78168644b45ac7327e4e0cfb1f0e6f7c3b4d" @@ -1488,65 +1259,25 @@ "@chakra-ui/lazy-utils@2.0.2": version "2.0.2" - resolved "https://registry.npmjs.org/@chakra-ui/lazy-utils/-/lazy-utils-2.0.2.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/lazy-utils/-/lazy-utils-2.0.2.tgz#d85f9afc60c2434ba76376fd4b23a7a0a1341e14" integrity sha512-MTxutBJZvqNNqrrS0722cI7qrnGu0yUQpIebmTxYwI+F3cOnPEKf5Ni+hrA8hKcw4XJhSY4npAPPYu1zJbOV4w== -"@chakra-ui/lazy-utils@2.0.5": - version "2.0.5" - resolved "https://registry.yarnpkg.com/@chakra-ui/lazy-utils/-/lazy-utils-2.0.5.tgz#363c3fa1d421362790b416ffa595acb835e1ae5b" - integrity sha512-UULqw7FBvcckQk2n3iPO56TMJvDsNv0FKZI6PlUNJVaGsPbsYxK/8IQ60vZgaTVPtVcjY6BE+y6zg8u9HOqpyg== - "@chakra-ui/live-region@2.0.10": version "2.0.10" - resolved "https://registry.npmjs.org/@chakra-ui/live-region/-/live-region-2.0.10.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/live-region/-/live-region-2.0.10.tgz#d33a784c85feed7ba96e2579553ca1d20c965171" integrity sha512-eQ2ZIreR/plzi/KGszDYTi1TvIyGEBcPiWP52BQOS7xwpzb1vsoR1FgFAIELxAGJvKnMUs+9qVogfyRBX8PdOg== -"@chakra-ui/live-region@2.0.13": - version "2.0.13" - resolved "https://registry.yarnpkg.com/@chakra-ui/live-region/-/live-region-2.0.13.tgz#1d00a637b74372d1ee0b215c649ebd4a33893e58" - integrity sha512-Ja+Slk6ZkxSA5oJzU2VuGU7TpZpbMb/4P4OUhIf2D30ctmIeXkxTWw1Bs1nGJAVtAPcGS5sKA+zb89i8g+0cTQ== - -"@chakra-ui/media-query@3.2.12": - version "3.2.12" - resolved "https://registry.yarnpkg.com/@chakra-ui/media-query/-/media-query-3.2.12.tgz#75e31f3c88818e687a4d90a2993286c2c3ca2453" - integrity sha512-8pSLDf3oxxhFrhd40rs7vSeIBfvOmIKHA7DJlGUC/y+9irD24ZwgmCtFnn+y3gI47hTJsopbSX+wb8nr7XPswA== - dependencies: - "@chakra-ui/breakpoint-utils" "2.0.8" - "@chakra-ui/react-env" "3.0.0" - "@chakra-ui/shared-utils" "2.0.5" - "@chakra-ui/media-query@3.2.7": version "3.2.7" - resolved "https://registry.npmjs.org/@chakra-ui/media-query/-/media-query-3.2.7.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/media-query/-/media-query-3.2.7.tgz#ece5b2181136145305bf5e6ec82c696ef1d59a77" integrity sha512-hbgm6JCe0kYU3PAhxASYYDopFQI26cW9kZnbp+5tRL1fykkVWNMPwoGC8FEZPur9JjXp7aoL6H4Jk7nrxY/XWw== dependencies: "@chakra-ui/breakpoint-utils" "2.0.4" "@chakra-ui/react-env" "2.0.10" -"@chakra-ui/menu@2.1.15": - version "2.1.15" - resolved "https://registry.yarnpkg.com/@chakra-ui/menu/-/menu-2.1.15.tgz#116520a2746d848e2a44fdbf03d66353cd1e1b39" - integrity sha512-+1fh7KBKZyhy8wi7Q6nQAzrvjM6xggyhGMnSna0rt6FJVA2jlfkjb5FozyIVPnkfJKjkKd8THVhrs9E7pHNV/w== - dependencies: - "@chakra-ui/clickable" "2.0.14" - "@chakra-ui/descendant" "3.0.14" - "@chakra-ui/lazy-utils" "2.0.5" - "@chakra-ui/popper" "3.0.14" - "@chakra-ui/react-children-utils" "2.0.6" - "@chakra-ui/react-context" "2.0.8" - "@chakra-ui/react-use-animation-state" "2.0.9" - "@chakra-ui/react-use-controllable-state" "2.0.8" - "@chakra-ui/react-use-disclosure" "2.0.8" - "@chakra-ui/react-use-focus-effect" "2.0.11" - "@chakra-ui/react-use-merge-refs" "2.0.7" - "@chakra-ui/react-use-outside-click" "2.1.0" - "@chakra-ui/react-use-update-effect" "2.0.7" - "@chakra-ui/shared-utils" "2.0.5" - "@chakra-ui/transition" "2.0.16" - "@chakra-ui/menu@2.1.2": version "2.1.2" - resolved "https://registry.npmjs.org/@chakra-ui/menu/-/menu-2.1.2.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/menu/-/menu-2.1.2.tgz#bbe39e1efdb408ba8e6616e0ec290417474f9454" integrity sha512-6Z7ecXjp6BtZ1ExbFggfxsAj1hwtcathXekmCTxHpXOD+BdjAC/13+oLclwXeuBO85aoTmQrQ2ovfTkO31bzRQ== dependencies: "@chakra-ui/clickable" "2.0.10" @@ -1577,25 +1308,9 @@ "@chakra-ui/transition" "1.4.8" "@chakra-ui/utils" "1.10.4" -"@chakra-ui/modal@2.2.12": - version "2.2.12" - resolved "https://registry.yarnpkg.com/@chakra-ui/modal/-/modal-2.2.12.tgz#8c6dc66a6db4abdaf6f5e0dae70183ee41ce361a" - integrity sha512-F1nNmYGvyqlmxidbwaBM3y57NhZ/Qeyc8BE9tb1FL1v9nxQhkfrPvMQ9miK0O1syPN6aZ5MMj+uD3AsRFE+/tA== - dependencies: - "@chakra-ui/close-button" "2.0.17" - "@chakra-ui/focus-lock" "2.0.17" - "@chakra-ui/portal" "2.0.16" - "@chakra-ui/react-context" "2.0.8" - "@chakra-ui/react-types" "2.0.7" - "@chakra-ui/react-use-merge-refs" "2.0.7" - "@chakra-ui/shared-utils" "2.0.5" - "@chakra-ui/transition" "2.0.16" - aria-hidden "^1.2.2" - react-remove-scroll "^2.5.5" - "@chakra-ui/modal@2.2.2": version "2.2.2" - resolved "https://registry.npmjs.org/@chakra-ui/modal/-/modal-2.2.2.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/modal/-/modal-2.2.2.tgz#bf3ef2673a8641a5c851faceb7811e0c0f323517" integrity sha512-cCYuqLZO4QqFUI1H+uEqixDk6UiCP3yC+sxkhFTXHIApSG9Z44v5np7BVTd6LKdmAN8pAWcc8Oxf14RvD6LWLw== dependencies: "@chakra-ui/close-button" "2.0.11" @@ -1610,7 +1325,7 @@ "@chakra-ui/number-input@2.0.12": version "2.0.12" - resolved "https://registry.npmjs.org/@chakra-ui/number-input/-/number-input-2.0.12.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/number-input/-/number-input-2.0.12.tgz#90a8408e6abb2d021793888ef2119d01761d7614" integrity sha512-3owLjl01sCYpTd3xbq//fJo9QJ0Q3PVYSx9JeOzlXnnTW8ws+yHPrqQzPe7G+tO4yOYynWuUT+NJ9oyCeAJIxA== dependencies: "@chakra-ui/counter" "2.0.10" @@ -1625,47 +1340,19 @@ "@chakra-ui/react-use-safe-layout-effect" "2.0.2" "@chakra-ui/react-use-update-effect" "2.0.4" -"@chakra-ui/number-input@2.0.19": - version "2.0.19" - resolved "https://registry.yarnpkg.com/@chakra-ui/number-input/-/number-input-2.0.19.tgz#82d4522036904c04d07e7050822fc522f9b32233" - integrity sha512-HDaITvtMEqOauOrCPsARDxKD9PSHmhWywpcyCSOX0lMe4xx2aaGhU0QQFhsJsykj8Er6pytMv6t0KZksdDv3YA== - dependencies: - "@chakra-ui/counter" "2.0.14" - "@chakra-ui/form-control" "2.0.18" - "@chakra-ui/icon" "3.0.16" - "@chakra-ui/react-context" "2.0.8" - "@chakra-ui/react-types" "2.0.7" - "@chakra-ui/react-use-callback-ref" "2.0.7" - "@chakra-ui/react-use-event-listener" "2.0.7" - "@chakra-ui/react-use-interval" "2.0.5" - "@chakra-ui/react-use-merge-refs" "2.0.7" - "@chakra-ui/react-use-safe-layout-effect" "2.0.5" - "@chakra-ui/react-use-update-effect" "2.0.7" - "@chakra-ui/shared-utils" "2.0.5" - "@chakra-ui/number-utils@2.0.4": version "2.0.4" - resolved "https://registry.npmjs.org/@chakra-ui/number-utils/-/number-utils-2.0.4.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/number-utils/-/number-utils-2.0.4.tgz#0331be05956f2c03125c073d35655e261e267cd4" integrity sha512-MdYd29GboBoKaXY9jhbY0Wl+0NxG1t/fa32ZSIbU6VrfMsZuAMl4NEJsz7Xvhy50fummLdKn5J6HFS7o5iyIgw== -"@chakra-ui/number-utils@2.0.7": - version "2.0.7" - resolved "https://registry.yarnpkg.com/@chakra-ui/number-utils/-/number-utils-2.0.7.tgz#aaee979ca2fb1923a0373a91619473811315db11" - integrity sha512-yOGxBjXNvLTBvQyhMDqGU0Oj26s91mbAlqKHiuw737AXHt0aPllOthVUqQMeaYLwLCjGMg0jtI7JReRzyi94Dg== - "@chakra-ui/object-utils@2.0.4": version "2.0.4" - resolved "https://registry.npmjs.org/@chakra-ui/object-utils/-/object-utils-2.0.4.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/object-utils/-/object-utils-2.0.4.tgz#d890ce285103a5e9b993f016a4fb38307aa55ac0" integrity sha512-sY98L4v2wcjpwRX8GCXqT+WzpL0i5FHVxT1Okxw0360T2tGnZt7toAwpMfIOR3dzkemP9LfXMCyBmWR5Hi2zpQ== -"@chakra-ui/object-utils@2.1.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@chakra-ui/object-utils/-/object-utils-2.1.0.tgz#a4ecf9cea92f1de09f5531f53ffdc41e0b19b6c3" - integrity sha512-tgIZOgLHaoti5PYGPTwK3t/cqtcycW0owaiOXoZOcpwwX/vlVb+H1jFsQyWiiwQVPt9RkoSLtxzXamx+aHH+bQ== - "@chakra-ui/pin-input@2.0.15": version "2.0.15" - resolved "https://registry.npmjs.org/@chakra-ui/pin-input/-/pin-input-2.0.15.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/pin-input/-/pin-input-2.0.15.tgz#08e65c5e8468cef6192634a53859169b51c2c4a7" integrity sha512-Ha8siSZm9gyjHHBK8ejwhKT6+75U12I/hNiYFvl2JHhc+Uh8tdi7+N+9SILO5vqbIv9kb+WGitvZ67I0cHjSfw== dependencies: "@chakra-ui/descendant" "3.0.10" @@ -1674,21 +1361,9 @@ "@chakra-ui/react-use-controllable-state" "2.0.5" "@chakra-ui/react-use-merge-refs" "2.0.4" -"@chakra-ui/pin-input@2.0.20": - version "2.0.20" - resolved "https://registry.yarnpkg.com/@chakra-ui/pin-input/-/pin-input-2.0.20.tgz#5bf115bf4282b69fc6532a9c542cbf41f815d200" - integrity sha512-IHVmerrtHN8F+jRB3W1HnMir1S1TUCWhI7qDInxqPtoRffHt6mzZgLZ0izx8p1fD4HkW4c1d4/ZLEz9uH9bBRg== - dependencies: - "@chakra-ui/descendant" "3.0.14" - "@chakra-ui/react-children-utils" "2.0.6" - "@chakra-ui/react-context" "2.0.8" - "@chakra-ui/react-use-controllable-state" "2.0.8" - "@chakra-ui/react-use-merge-refs" "2.0.7" - "@chakra-ui/shared-utils" "2.0.5" - "@chakra-ui/popover@2.1.1": version "2.1.1" - resolved "https://registry.npmjs.org/@chakra-ui/popover/-/popover-2.1.1.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/popover/-/popover-2.1.1.tgz#1b5e05e334ba5f9bce4bc5bcabfb92563393fc84" integrity sha512-j09NsesfT+eaYITkITYJXDlRcPoOeQUM80neJZKOBgul2iHkVsEoii8dwS5Ip5ONeu4ane1b6zEOlYvYj2SrkA== dependencies: "@chakra-ui/close-button" "2.0.11" @@ -1702,23 +1377,6 @@ "@chakra-ui/react-use-focus-on-pointer-down" "2.0.3" "@chakra-ui/react-use-merge-refs" "2.0.4" -"@chakra-ui/popover@2.1.12": - version "2.1.12" - resolved "https://registry.yarnpkg.com/@chakra-ui/popover/-/popover-2.1.12.tgz#093bb60f7c044f829e2acc3a93f0c1077ba58cfb" - integrity sha512-Corh8trA1f3ydcMQqomgSvYNNhAlpxiBpMY2sglwYazOJcueHA8CI05cJVD0T/wwoTob7BShabhCGFZThn61Ng== - dependencies: - "@chakra-ui/close-button" "2.0.17" - "@chakra-ui/lazy-utils" "2.0.5" - "@chakra-ui/popper" "3.0.14" - "@chakra-ui/react-context" "2.0.8" - "@chakra-ui/react-types" "2.0.7" - "@chakra-ui/react-use-animation-state" "2.0.9" - "@chakra-ui/react-use-disclosure" "2.0.8" - "@chakra-ui/react-use-focus-effect" "2.0.11" - "@chakra-ui/react-use-focus-on-pointer-down" "2.0.6" - "@chakra-ui/react-use-merge-refs" "2.0.7" - "@chakra-ui/shared-utils" "2.0.5" - "@chakra-ui/popper@2.4.3": version "2.4.3" resolved "https://registry.yarnpkg.com/@chakra-ui/popper/-/popper-2.4.3.tgz#fcdc917d13a56b9d44868c78a009e4dd692697a2" @@ -1727,18 +1385,9 @@ "@chakra-ui/react-utils" "1.2.3" "@popperjs/core" "^2.9.3" -"@chakra-ui/popper@3.0.14": - version "3.0.14" - resolved "https://registry.yarnpkg.com/@chakra-ui/popper/-/popper-3.0.14.tgz#598feec8825df99270585319f7becbb6cf33558a" - integrity sha512-RDMmmSfjsmHJbVn2agDyoJpTbQK33fxx//njwJdeyM0zTG/3/4xjI/Cxru3acJ2Y+1jFGmPqhO81stFjnbtfIw== - dependencies: - "@chakra-ui/react-types" "2.0.7" - "@chakra-ui/react-use-merge-refs" "2.0.7" - "@popperjs/core" "^2.9.3" - "@chakra-ui/popper@3.0.8": version "3.0.8" - resolved "https://registry.npmjs.org/@chakra-ui/popper/-/popper-3.0.8.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/popper/-/popper-3.0.8.tgz#89b6984aee405316974dbb70ba451f85832bf44e" integrity sha512-246eUwuCRsLpTPxn5T8D8T9/6ODqmmz6pRRJAjGnLlUB0gNHgjisBn0UDBic5Gbxcg0sqKvxOMY3uurbW5lXTA== dependencies: "@chakra-ui/react-types" "2.0.3" @@ -1747,37 +1396,22 @@ "@chakra-ui/portal@2.0.10": version "2.0.10" - resolved "https://registry.npmjs.org/@chakra-ui/portal/-/portal-2.0.10.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/portal/-/portal-2.0.10.tgz#8ac21131cb0666a0bf6565468b3f7e799ef3bc8d" integrity sha512-VRYvVAggIuqIZ3IQ6XZ1b5ujjjOUgPk9PPdc9jssUngZa7RG+5NXNhgoM8a5TsXv6aPEolBOlDNWuxzRQ4RSSg== dependencies: "@chakra-ui/react-context" "2.0.4" "@chakra-ui/react-use-safe-layout-effect" "2.0.2" -"@chakra-ui/portal@2.0.16": - version "2.0.16" - resolved "https://registry.yarnpkg.com/@chakra-ui/portal/-/portal-2.0.16.tgz#e5ce3f9d9e559f17a95276e0c006d0e9b7703442" - integrity sha512-bVID0qbQ0l4xq38LdqAN4EKD4/uFkDnXzFwOlviC9sl0dNhzICDb1ltuH/Adl1d2HTMqyN60O3GO58eHy7plnQ== - dependencies: - "@chakra-ui/react-context" "2.0.8" - "@chakra-ui/react-use-safe-layout-effect" "2.0.5" - "@chakra-ui/progress@2.0.12": version "2.0.12" - resolved "https://registry.npmjs.org/@chakra-ui/progress/-/progress-2.0.12.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/progress/-/progress-2.0.12.tgz#7ce57fe2822d1741c26e82960ca02c667a265a05" integrity sha512-9qtZimZosTliI7siAZkLeCVdCpXCTxmSETCudHcCUsC+FtcFacmA65+We8qij1nOIqmsbm+NYU6PP89TU2n4Hg== dependencies: "@chakra-ui/react-context" "2.0.4" -"@chakra-ui/progress@2.1.6": - version "2.1.6" - resolved "https://registry.yarnpkg.com/@chakra-ui/progress/-/progress-2.1.6.tgz#398db20440979c37adb0a34821f805ae3471873b" - integrity sha512-hHh5Ysv4z6bK+j2GJbi/FT9CVyto2PtNUNwBmr3oNMVsoOUMoRjczfXvvYqp0EHr9PCpxqrq7sRwgQXUzhbDSw== - dependencies: - "@chakra-ui/react-context" "2.0.8" - "@chakra-ui/provider@2.0.20": version "2.0.20" - resolved "https://registry.npmjs.org/@chakra-ui/provider/-/provider-2.0.20.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/provider/-/provider-2.0.20.tgz#2f3f73f6142f4d2b2a5a8ad6dbd777a3fc4390ce" integrity sha512-mNNfsgm05G4x1VzvHVR9+PNEiuxNnn9xUKDuEwoaO7+IHCMzCRMtPbSJjwmv0xvHUGB9+JChjPpZI5RuHQziJQ== dependencies: "@chakra-ui/css-reset" "2.0.8" @@ -1786,20 +1420,9 @@ "@chakra-ui/system" "2.3.0" "@chakra-ui/utils" "2.0.11" -"@chakra-ui/provider@2.3.0": - version "2.3.0" - resolved "https://registry.yarnpkg.com/@chakra-ui/provider/-/provider-2.3.0.tgz#18b3bdc3087e90569049832b2f0f4f8afd5cedf6" - integrity sha512-vKgmjoLVS3NnHW8RSYwmhhda2ZTi3fQc1egkYSVwngGky4CsN15I+XDhxJitVd66H41cjah/UNJyoeq7ACseLA== - dependencies: - "@chakra-ui/css-reset" "2.1.2" - "@chakra-ui/portal" "2.0.16" - "@chakra-ui/react-env" "3.0.0" - "@chakra-ui/system" "2.5.8" - "@chakra-ui/utils" "2.0.15" - "@chakra-ui/radio@2.0.12": version "2.0.12" - resolved "https://registry.npmjs.org/@chakra-ui/radio/-/radio-2.0.12.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/radio/-/radio-2.0.12.tgz#d89eb463df0247a0e634cff1fb9ca755bcbab825" integrity sha512-871hqAGQaufxyUzPP3aautPBIRZQmpi3fw5XPZ6SbY62dV61M4sjcttd46HfCf5SrAonoOADFQLMGQafznjhaA== dependencies: "@chakra-ui/form-control" "2.0.11" @@ -1808,31 +1431,14 @@ "@chakra-ui/react-use-merge-refs" "2.0.4" "@zag-js/focus-visible" "0.1.0" -"@chakra-ui/radio@2.0.22": - version "2.0.22" - resolved "https://registry.yarnpkg.com/@chakra-ui/radio/-/radio-2.0.22.tgz#fad0ce7c9ba4051991ed517cac4cfe526d6d47d9" - integrity sha512-GsQ5WAnLwivWl6gPk8P1x+tCcpVakCt5R5T0HumF7DGPXKdJbjS+RaFySrbETmyTJsKY4QrfXn+g8CWVrMjPjw== - dependencies: - "@chakra-ui/form-control" "2.0.18" - "@chakra-ui/react-context" "2.0.8" - "@chakra-ui/react-types" "2.0.7" - "@chakra-ui/react-use-merge-refs" "2.0.7" - "@chakra-ui/shared-utils" "2.0.5" - "@zag-js/focus-visible" "0.2.2" - "@chakra-ui/react-children-utils@2.0.3": version "2.0.3" - resolved "https://registry.npmjs.org/@chakra-ui/react-children-utils/-/react-children-utils-2.0.3.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/react-children-utils/-/react-children-utils-2.0.3.tgz#406b984c653befd6c99636fcefb55bd01d436a7d" integrity sha512-tPQjLEEuAw/DYLRw0cNs/g8tcdhZ3r21Sr9dTAzoyvfk0vbZ24gCXRElltW2GZLiFA63mAidzhPmc+yQF3Wtgg== -"@chakra-ui/react-children-utils@2.0.6": - version "2.0.6" - resolved "https://registry.yarnpkg.com/@chakra-ui/react-children-utils/-/react-children-utils-2.0.6.tgz#6c480c6a60678fcb75cb7d57107c7a79e5179b92" - integrity sha512-QVR2RC7QsOsbWwEnq9YduhpqSFnZGvjjGREV8ygKi8ADhXh93C8azLECCUVgRJF2Wc+So1fgxmjLcbZfY2VmBA== - "@chakra-ui/react-context@2.0.4": version "2.0.4" - resolved "https://registry.npmjs.org/@chakra-ui/react-context/-/react-context-2.0.4.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/react-context/-/react-context-2.0.4.tgz#1b6ab260d44d9073c95b975b7d1643f011e65e02" integrity sha512-eBITFkf7fLSiMZrSdhweK4fYr41WUNMEeIEOP2dCWolE7WgKxNYaYleC+iRGY0GeXkFM2KYywUtixjJe29NuVA== "@chakra-ui/react-context@2.0.5": @@ -1840,11 +1446,6 @@ resolved "https://registry.npmjs.org/@chakra-ui/react-context/-/react-context-2.0.5.tgz" integrity sha512-WYS0VBl5Q3/kNShQ26BP+Q0OGMeTQWco3hSiJWvO2wYLY7N1BLq6dKs8vyKHZfpwKh2YL2bQeAObi+vSkXp6tQ== -"@chakra-ui/react-context@2.0.8": - version "2.0.8" - resolved "https://registry.yarnpkg.com/@chakra-ui/react-context/-/react-context-2.0.8.tgz#5e0ed33ac3995875a21dea0e12b0ee5fc4c2e3cc" - integrity sha512-tRTKdn6lCTXM6WPjSokAAKCw2ioih7Eg8cNgaYRSwKBck8nkz9YqxgIIEj3dJD7MGtpl24S/SNI98iRWkRwR/A== - "@chakra-ui/react-env@1.1.6": version "1.1.6" resolved "https://registry.yarnpkg.com/@chakra-ui/react-env/-/react-env-1.1.6.tgz#9915b02fd1f8ca62ccf578eaec793f1c4dea78b0" @@ -1854,107 +1455,51 @@ "@chakra-ui/react-env@2.0.10": version "2.0.10" - resolved "https://registry.npmjs.org/@chakra-ui/react-env/-/react-env-2.0.10.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/react-env/-/react-env-2.0.10.tgz#2eaa4ba64a14ecd2d279c32d5edfef7a6b5de3e8" integrity sha512-3Yab5EbFcCGYzEsoijy4eA3354Z/JoXyk9chYIuW7Uwd+K6g/R8C0mUSAHeTmfp6Fix9kzDgerO5MWNM87b8cA== -"@chakra-ui/react-env@3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@chakra-ui/react-env/-/react-env-3.0.0.tgz#2c3c9dc0e529b9b474a386a2b24988317b2a0811" - integrity sha512-tfMRO2v508HQWAqSADFrwZgR9oU10qC97oV6zGbjHh9ALP0/IcFR+Bi71KRTveDTm85fMeAzZYGj57P3Dsipkw== - dependencies: - "@chakra-ui/react-use-safe-layout-effect" "2.0.5" - "@chakra-ui/react-types@2.0.3": version "2.0.3" - resolved "https://registry.npmjs.org/@chakra-ui/react-types/-/react-types-2.0.3.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/react-types/-/react-types-2.0.3.tgz#dc454c4703b4de585e6461fd607304ede06fe595" integrity sha512-1mJYOQldFTALE0Wr3j6tk/MYvgQIp6CKkJulNzZrI8QN+ox/bJOh8OVP4vhwqvfigdLTui0g0k8M9h+j2ub/Mw== -"@chakra-ui/react-types@2.0.7": - version "2.0.7" - resolved "https://registry.yarnpkg.com/@chakra-ui/react-types/-/react-types-2.0.7.tgz#799c166a44882b23059c8f510eac9bd5d0869ac4" - integrity sha512-12zv2qIZ8EHwiytggtGvo4iLT0APris7T0qaAWqzpUGS0cdUtR8W+V1BJ5Ocq+7tA6dzQ/7+w5hmXih61TuhWQ== - "@chakra-ui/react-use-animation-state@2.0.5": version "2.0.5" - resolved "https://registry.npmjs.org/@chakra-ui/react-use-animation-state/-/react-use-animation-state-2.0.5.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-animation-state/-/react-use-animation-state-2.0.5.tgz#f022baf0103c35aa494227b041422e7d2401b0d4" integrity sha512-8gZIqZpMS5yTGlC+IqYoSrV13joiAYoeI0YR2t68WuDagcZ459OrjE57+gF04NLxfdV7eUgwqnpuv7IOLbJX/A== dependencies: "@chakra-ui/dom-utils" "2.0.3" "@chakra-ui/react-use-event-listener" "2.0.4" -"@chakra-ui/react-use-animation-state@2.0.9": - version "2.0.9" - resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-animation-state/-/react-use-animation-state-2.0.9.tgz#8e6377e7583cc80c649cdc443c90ab5b48a03e78" - integrity sha512-WFoD5OG03PBmzJCoRwM8rVfU442AvKBPPgA0yGGlKioH29OGuX7W78Ml+cYdXxonTiB03YSRZzUwaUnP4wAy1Q== - dependencies: - "@chakra-ui/dom-utils" "2.1.0" - "@chakra-ui/react-use-event-listener" "2.0.7" - "@chakra-ui/react-use-callback-ref@2.0.4": version "2.0.4" - resolved "https://registry.npmjs.org/@chakra-ui/react-use-callback-ref/-/react-use-callback-ref-2.0.4.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-callback-ref/-/react-use-callback-ref-2.0.4.tgz#5099ef1df4413af42e434945f541de99394ec96f" integrity sha512-he7EQfwMA4mwiDDKvX7cHIJaboCqf7UD3KYHGUcIjsF4dSc2Y8X5Ze4w+hmVZoJWIe4DWUzb3ili2SUm8eTgPg== -"@chakra-ui/react-use-callback-ref@2.0.7": - version "2.0.7" - resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-callback-ref/-/react-use-callback-ref-2.0.7.tgz#9b844a81037d0ecaaa8031979fa050165635e211" - integrity sha512-YjT76nTpfHAK5NxplAlZsQwNju5KmQExnqsWNPFeOR6vvbC34+iPSTr+r91i1Hdy7gBSbevsOsd5Wm6RN3GuMw== - "@chakra-ui/react-use-controllable-state@2.0.5": version "2.0.5" - resolved "https://registry.npmjs.org/@chakra-ui/react-use-controllable-state/-/react-use-controllable-state-2.0.5.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-controllable-state/-/react-use-controllable-state-2.0.5.tgz#5ef9f600ae134a2a37fe080fd6231bbed83544bb" integrity sha512-JrZZpMX24CUyfDuyqDczw9Z9IMvjH8ujETHK0Zu4M0SIsX/q4EqOwwngUFL03I2gx/O38HfSdeX8hMu4zbTAGA== dependencies: "@chakra-ui/react-use-callback-ref" "2.0.4" -"@chakra-ui/react-use-controllable-state@2.0.8": - version "2.0.8" - resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-controllable-state/-/react-use-controllable-state-2.0.8.tgz#6b71187e03be632c244dde9f16ed685428087ec9" - integrity sha512-F7rdCbLEmRjwwODqWZ3y+mKgSSHPcLQxeUygwk1BkZPXbKkJJKymOIjIynil2cbH7ku3hcSIWRvuhpCcfQWJ7Q== - dependencies: - "@chakra-ui/react-use-callback-ref" "2.0.7" - "@chakra-ui/react-use-disclosure@2.0.5": version "2.0.5" - resolved "https://registry.npmjs.org/@chakra-ui/react-use-disclosure/-/react-use-disclosure-2.0.5.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-disclosure/-/react-use-disclosure-2.0.5.tgz#bb52340f0e7d614cc95819bd21cffd050783f96c" integrity sha512-kPLB9oxImASRhAbKfvfc03/lbAJbsXndEVRzd+nvvL+QZm2RRfnel3k6OIkWvGFOXXYOPE2+slLe8ZPwbTGg9g== dependencies: "@chakra-ui/react-use-callback-ref" "2.0.4" -"@chakra-ui/react-use-disclosure@2.0.8": - version "2.0.8" - resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-disclosure/-/react-use-disclosure-2.0.8.tgz#e0e0445afc6d6d96bb262b99751e675034c31497" - integrity sha512-2ir/mHe1YND40e+FyLHnDsnDsBQPwzKDLzfe9GZri7y31oU83JSbHdlAXAhp3bpjohslwavtRCp+S/zRxfO9aQ== - dependencies: - "@chakra-ui/react-use-callback-ref" "2.0.7" - "@chakra-ui/react-use-event-listener@2.0.4": version "2.0.4" - resolved "https://registry.npmjs.org/@chakra-ui/react-use-event-listener/-/react-use-event-listener-2.0.4.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-event-listener/-/react-use-event-listener-2.0.4.tgz#3f893def57a7b10db6c355740dd1e82cd3216259" integrity sha512-VqmalfKWMO8D21XuZO19WUtcP5xhbHXKzkggApTChZUN02UC5TC4pe0pYbDygoeUuNBhY+9lJKHeS08vYsljRg== dependencies: "@chakra-ui/react-use-callback-ref" "2.0.4" -"@chakra-ui/react-use-event-listener@2.0.7": - version "2.0.7" - resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-event-listener/-/react-use-event-listener-2.0.7.tgz#ed08164164e79183d876eeb71e12c6bfaca3ad17" - integrity sha512-4wvpx4yudIO3B31pOrXuTHDErawmwiXnvAN7gLEOVREi16+YGNcFnRJ5X5nRrmB7j2MDUtsEDpRBFfw5Z9xQ5g== - dependencies: - "@chakra-ui/react-use-callback-ref" "2.0.7" - -"@chakra-ui/react-use-focus-effect@2.0.11": - version "2.0.11" - resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-focus-effect/-/react-use-focus-effect-2.0.11.tgz#9a5c76981677fc356308526c7d2b3dc48101ea06" - integrity sha512-/zadgjaCWD50TfuYsO1vDS2zSBs2p/l8P2DPEIA8FuaowbBubKrk9shKQDWmbfDU7KArGxPxrvo+VXvskPPjHw== - dependencies: - "@chakra-ui/dom-utils" "2.1.0" - "@chakra-ui/react-use-event-listener" "2.0.7" - "@chakra-ui/react-use-safe-layout-effect" "2.0.5" - "@chakra-ui/react-use-update-effect" "2.0.7" - "@chakra-ui/react-use-focus-effect@2.0.5": version "2.0.5" - resolved "https://registry.npmjs.org/@chakra-ui/react-use-focus-effect/-/react-use-focus-effect-2.0.5.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-focus-effect/-/react-use-focus-effect-2.0.5.tgz#b554277c38e84468b019e08a73579e9700e1003a" integrity sha512-sbe1QnsXXfjukM+laxbKnT0UnMpHe/7kTzEPG/BYM6/ZDUUmrC1Nz+8l+3H/52iWIaruikDBdif/Xd37Yvu3Kg== dependencies: "@chakra-ui/dom-utils" "2.0.3" @@ -1963,142 +1508,73 @@ "@chakra-ui/react-use-focus-on-pointer-down@2.0.3": version "2.0.3" - resolved "https://registry.npmjs.org/@chakra-ui/react-use-focus-on-pointer-down/-/react-use-focus-on-pointer-down-2.0.3.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-focus-on-pointer-down/-/react-use-focus-on-pointer-down-2.0.3.tgz#8b605063c9e707a18b021fbcaed8919c8660d1ed" integrity sha512-8cKmpv26JnblexNaekWxEDI7M+MZnJcp1PJUz6lByjfQ1m4YjFr1cdbdhG4moaqzzYs7vTmO/qL8KVq8ZLUwyQ== dependencies: "@chakra-ui/react-use-event-listener" "2.0.4" -"@chakra-ui/react-use-focus-on-pointer-down@2.0.6": - version "2.0.6" - resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-focus-on-pointer-down/-/react-use-focus-on-pointer-down-2.0.6.tgz#13330eb518c17e591c908cb8f4a30d43a978e3f2" - integrity sha512-OigXiLRVySn3tyVqJ/rn57WGuukW8TQe8fJYiLwXbcNyAMuYYounvRxvCy2b53sQ7QIZamza0N0jhirbH5FNoQ== - dependencies: - "@chakra-ui/react-use-event-listener" "2.0.7" - "@chakra-ui/react-use-interval@2.0.2": version "2.0.2" - resolved "https://registry.npmjs.org/@chakra-ui/react-use-interval/-/react-use-interval-2.0.2.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-interval/-/react-use-interval-2.0.2.tgz#6d1d5d5b5c5604ee2ea47f1e140e6eaf6e885df5" integrity sha512-5U1c0pEB5n0Yri0E4RdFXWx2RVBZBBhD8Uu49dM33jkIguCbIPmZ+YgVry5DDzCHyz4RgDg4yZKOPK0PI8lEUg== dependencies: "@chakra-ui/react-use-callback-ref" "2.0.4" -"@chakra-ui/react-use-interval@2.0.5": - version "2.0.5" - resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-interval/-/react-use-interval-2.0.5.tgz#c1a0043bf188b19b790a27668f4e860391335a60" - integrity sha512-1nbdwMi2K87V6p5f5AseOKif2CkldLaJlq1TOqaPRwb7v3aU9rltBtYdf+fIyuHSToNJUV6wd9budCFdLCl3Fg== - dependencies: - "@chakra-ui/react-use-callback-ref" "2.0.7" - "@chakra-ui/react-use-latest-ref@2.0.2": version "2.0.2" - resolved "https://registry.npmjs.org/@chakra-ui/react-use-latest-ref/-/react-use-latest-ref-2.0.2.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-latest-ref/-/react-use-latest-ref-2.0.2.tgz#4895d3ae2dc93a660ed86aaec7021b729830d3d2" integrity sha512-Ra/NMV+DSQ3n0AdKsyIqdgnFzls5UntabtIRfDXLrqmJ4tI0a1tDdop2qop0Ue87AcqD9P1KtQue4KPx7wCElw== -"@chakra-ui/react-use-latest-ref@2.0.5": - version "2.0.5" - resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-latest-ref/-/react-use-latest-ref-2.0.5.tgz#b61dc4dadda340f7b14df0ec1d50ab2e507b3b3e" - integrity sha512-3mIuFzMyIo3Ok/D8uhV9voVg7KkrYVO/pwVvNPJOHsDQqCA6DpYE4WDsrIx+fVcwad3Ta7SupexR5PoI+kq6QQ== - "@chakra-ui/react-use-merge-refs@2.0.4": version "2.0.4" - resolved "https://registry.npmjs.org/@chakra-ui/react-use-merge-refs/-/react-use-merge-refs-2.0.4.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-merge-refs/-/react-use-merge-refs-2.0.4.tgz#c23f10fda1d3a6327a48708a8a7ad4b62ba918d3" integrity sha512-aoWvtE5tDQNaLCiNUI6WV+MA2zVcCLR5mHSCISmowlTXyXOqOU5Fo9ZoUftzrmgCJpDu5x1jfUOivxuHUueb0g== -"@chakra-ui/react-use-merge-refs@2.0.7": - version "2.0.7" - resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-merge-refs/-/react-use-merge-refs-2.0.7.tgz#1a1fe800fb5501ec3da4088fbac78c03bbad13a7" - integrity sha512-zds4Uhsc+AMzdH8JDDkLVet9baUBgtOjPbhC5r3A0ZXjZvGhCztFAVE3aExYiVoMPoHLKbLcqvCWE6ioFKz1lw== - "@chakra-ui/react-use-outside-click@2.0.4": version "2.0.4" - resolved "https://registry.npmjs.org/@chakra-ui/react-use-outside-click/-/react-use-outside-click-2.0.4.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-outside-click/-/react-use-outside-click-2.0.4.tgz#977d873cfedec615c8e3acd48fca7b094b464b6e" integrity sha512-uerJKS8dqg2kHs1xozA5vcCqW0UInuwrfCPb+rDWBTpu7aEqxABMw9W3e4gfOABrAjhKz2I0a/bu2i8zbVwdLw== dependencies: "@chakra-ui/react-use-callback-ref" "2.0.4" -"@chakra-ui/react-use-outside-click@2.1.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-outside-click/-/react-use-outside-click-2.1.0.tgz#f7e27653c470e516c55d79df67ed8b0ba2c4ec8d" - integrity sha512-JanCo4QtWvMl9ZZUpKJKV62RlMWDFdPCE0Q64a7eWTOQgWWcpyBW7TOYRunQTqrK30FqkYFJCOlAWOtn+6Rw7A== - dependencies: - "@chakra-ui/react-use-callback-ref" "2.0.7" - "@chakra-ui/react-use-pan-event@2.0.5": version "2.0.5" - resolved "https://registry.npmjs.org/@chakra-ui/react-use-pan-event/-/react-use-pan-event-2.0.5.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-pan-event/-/react-use-pan-event-2.0.5.tgz#9269d4b798d1447e18b00ee0b28fa52c5c8efb26" integrity sha512-nhE3b85++EEmBD2v6m46TLoA4LehSCZ349P8kvEjw/RC0K6XDOZndaBucIeAlnpEENSSUpczFfMSOLxSHdu0oA== dependencies: "@chakra-ui/event-utils" "2.0.5" "@chakra-ui/react-use-latest-ref" "2.0.2" framesync "5.3.0" -"@chakra-ui/react-use-pan-event@2.0.9": - version "2.0.9" - resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-pan-event/-/react-use-pan-event-2.0.9.tgz#0ff33a285e75a692d1ed52dbb9f3046a593b8004" - integrity sha512-xu35QXkiyrgsHUOnctl+SwNcwf9Rl62uYE5y8soKOZdBm8E+FvZIt2hxUzK1EoekbJCMzEZ0Yv1ZQCssVkSLaQ== - dependencies: - "@chakra-ui/event-utils" "2.0.8" - "@chakra-ui/react-use-latest-ref" "2.0.5" - framesync "6.1.2" - "@chakra-ui/react-use-previous@2.0.2": version "2.0.2" - resolved "https://registry.npmjs.org/@chakra-ui/react-use-previous/-/react-use-previous-2.0.2.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-previous/-/react-use-previous-2.0.2.tgz#1091ae8abc2082ab504e3742f8b1d75409ae7b27" integrity sha512-ap/teLRPKopaHYD80fnf0TR/NpTWHJO5VdKg6sPyF1y5ediYLAzPT1G2OqMCj4QfJsYDctioT142URDYe0Nn7w== -"@chakra-ui/react-use-previous@2.0.5": - version "2.0.5" - resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-previous/-/react-use-previous-2.0.5.tgz#65836cc81e3a1bf4252cd08a71094f1be827b56c" - integrity sha512-BIZgjycPE4Xr+MkhKe0h67uHXzQQkBX/u5rYPd65iMGdX1bCkbE0oorZNfOHLKdTmnEb4oVsNvfN6Rfr+Mnbxw== - "@chakra-ui/react-use-safe-layout-effect@2.0.2": version "2.0.2" - resolved "https://registry.npmjs.org/@chakra-ui/react-use-safe-layout-effect/-/react-use-safe-layout-effect-2.0.2.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-safe-layout-effect/-/react-use-safe-layout-effect-2.0.2.tgz#31088eeb4b2a6910251683ddb15fb855d6127adf" integrity sha512-gl5HDq9RVeDJiT8udtpx12KRV8JPLJHDIUX8f/yZcKpXow0C7FFGg5Yy5I9397NQog5ZjKMuOg+AUq9TLJxsyQ== -"@chakra-ui/react-use-safe-layout-effect@2.0.5": - version "2.0.5" - resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-safe-layout-effect/-/react-use-safe-layout-effect-2.0.5.tgz#6cf388c37fd2a42b5295a292e149b32f860a00a7" - integrity sha512-MwAQBz3VxoeFLaesaSEN87reVNVbjcQBDex2WGexAg6hUB6n4gc1OWYH/iXp4tzp4kuggBNhEHkk9BMYXWfhJQ== - -"@chakra-ui/react-use-size@2.0.10": - version "2.0.10" - resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-size/-/react-use-size-2.0.10.tgz#6131950852490c06e5fb3760bf64097c8057391f" - integrity sha512-fdIkH14GDnKQrtQfxX8N3gxbXRPXEl67Y3zeD9z4bKKcQUAYIMqs0MsPZY+FMpGQw8QqafM44nXfL038aIrC5w== - dependencies: - "@zag-js/element-size" "0.3.2" - "@chakra-ui/react-use-size@2.0.4": version "2.0.4" - resolved "https://registry.npmjs.org/@chakra-ui/react-use-size/-/react-use-size-2.0.4.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-size/-/react-use-size-2.0.4.tgz#3634782f8dab6aa2a37699188afa89251cbae8f3" integrity sha512-W6rgTLuoSC4ovZtqYco8cG+yBadH3bhlg92T5lgpKDakSDr0mXcZdbGx6g0AOkgxXm0V1jWNGO1743wudtF7ew== dependencies: "@zag-js/element-size" "0.1.0" "@chakra-ui/react-use-timeout@2.0.2": version "2.0.2" - resolved "https://registry.npmjs.org/@chakra-ui/react-use-timeout/-/react-use-timeout-2.0.2.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-timeout/-/react-use-timeout-2.0.2.tgz#f1378de0d5e01f7aee60d5b9ec3205e1fc7d2fc4" integrity sha512-n6zb3OmxtDmRMxYkDgILqKh15aDOa8jNLHBlqHzmlL6mEGNKmMFPW9j/KvpAqSgKjUTDRnnXcpneprTMKy/yrw== dependencies: "@chakra-ui/react-use-callback-ref" "2.0.4" -"@chakra-ui/react-use-timeout@2.0.5": - version "2.0.5" - resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-timeout/-/react-use-timeout-2.0.5.tgz#13c4e48e48d4b84ce1e062f0f1c9ec401ece78c9" - integrity sha512-QqmB+jVphh3h/CS60PieorpY7UqSPkrQCB7f7F+i9vwwIjtP8fxVHMmkb64K7VlzQiMPzv12nlID5dqkzlv0mw== - dependencies: - "@chakra-ui/react-use-callback-ref" "2.0.7" - "@chakra-ui/react-use-update-effect@2.0.4": version "2.0.4" - resolved "https://registry.npmjs.org/@chakra-ui/react-use-update-effect/-/react-use-update-effect-2.0.4.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-update-effect/-/react-use-update-effect-2.0.4.tgz#522bc58b943fffe540a91f7a096d42e4a91b9748" integrity sha512-F/I9LVnGAQyvww+x7tQb47wCwjhMYjpxtM1dTg1U3oCEXY0yF1Ts3NJLUAlsr3nAW6epJIwWx61niC7KWpam1w== -"@chakra-ui/react-use-update-effect@2.0.7": - version "2.0.7" - resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-update-effect/-/react-use-update-effect-2.0.7.tgz#f94b7975ebb150c03d410e754b54f0e9dd263134" - integrity sha512-vBM2bmmM83ZdDtasWv3PXPznpTUd+FvqBC8J8rxoRmvdMEfrxTiQRBJhiGHLpS9BPLLPQlosN6KdFU97csB6zg== - "@chakra-ui/react-utils@1.2.3", "@chakra-ui/react-utils@^1.2.3": version "1.2.3" resolved "https://registry.yarnpkg.com/@chakra-ui/react-utils/-/react-utils-1.2.3.tgz#3356c9299bc8faada8fac6c5886ca65ec95bb5be" @@ -2106,23 +1582,16 @@ dependencies: "@chakra-ui/utils" "^1.10.4" -"@chakra-ui/react-utils@2.0.12": - version "2.0.12" - resolved "https://registry.yarnpkg.com/@chakra-ui/react-utils/-/react-utils-2.0.12.tgz#d6b773b9a5b2e51dce61f51ac8a0e9a0f534f479" - integrity sha512-GbSfVb283+YA3kA8w8xWmzbjNWk14uhNpntnipHCftBibl0lxtQ9YqMFQLwuFOO0U2gYVocszqqDWX+XNKq9hw== - dependencies: - "@chakra-ui/utils" "2.0.15" - "@chakra-ui/react-utils@2.0.8": version "2.0.8" - resolved "https://registry.npmjs.org/@chakra-ui/react-utils/-/react-utils-2.0.8.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/react-utils/-/react-utils-2.0.8.tgz#1db4e920386f4afbf44fe9dd8aaaf6f22eefb371" integrity sha512-OSHHBKZlJWTi2NZcPnBx1PyZvLQY+n5RPBtcri7/89EDdAwz2NdEhp2Dz1yQRctOSCF1kB/rnCYDP1U0oRk9RQ== dependencies: "@chakra-ui/utils" "2.0.11" -"@chakra-ui/react@^2.3.6": +"@chakra-ui/react@2.3.6": version "2.3.6" - resolved "https://registry.npmjs.org/@chakra-ui/react/-/react-2.3.6.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/react/-/react-2.3.6.tgz#a6d3e092cab433fcd9cf8e9876756818c4261df6" integrity sha512-xo43UU+yMqRGHZLU4fSgzojeRl5stlIfT+GLbT9CUVEm0HMJCt2m8RsNPBvGOMzANdC+bzwSiOm+MNzQBi9IBQ== dependencies: "@chakra-ui/accordion" "2.1.2" @@ -2175,109 +1644,29 @@ "@chakra-ui/utils" "2.0.11" "@chakra-ui/visually-hidden" "2.0.11" -"@chakra-ui/react@^2.5.1": - version "2.7.0" - resolved "https://registry.yarnpkg.com/@chakra-ui/react/-/react-2.7.0.tgz#0fdeb5d5ec0faf97e143cba94498b055a093f671" - integrity sha512-+FcUFQMsPfhWuM9Iu7uqufwwhmHN2IX6FWsBixYGOalO86dpgETsILMZP9PuWfgj7GpWiy2Dum6HXekh0Tk2Mg== - dependencies: - "@chakra-ui/accordion" "2.2.0" - "@chakra-ui/alert" "2.1.0" - "@chakra-ui/avatar" "2.2.11" - "@chakra-ui/breadcrumb" "2.1.5" - "@chakra-ui/button" "2.0.18" - "@chakra-ui/card" "2.1.6" - "@chakra-ui/checkbox" "2.2.15" - "@chakra-ui/close-button" "2.0.17" - "@chakra-ui/control-box" "2.0.13" - "@chakra-ui/counter" "2.0.14" - "@chakra-ui/css-reset" "2.1.2" - "@chakra-ui/editable" "3.0.0" - "@chakra-ui/focus-lock" "2.0.17" - "@chakra-ui/form-control" "2.0.18" - "@chakra-ui/hooks" "2.2.0" - "@chakra-ui/icon" "3.0.16" - "@chakra-ui/image" "2.0.16" - "@chakra-ui/input" "2.0.22" - "@chakra-ui/layout" "2.2.0" - "@chakra-ui/live-region" "2.0.13" - "@chakra-ui/media-query" "3.2.12" - "@chakra-ui/menu" "2.1.15" - "@chakra-ui/modal" "2.2.12" - "@chakra-ui/number-input" "2.0.19" - "@chakra-ui/pin-input" "2.0.20" - "@chakra-ui/popover" "2.1.12" - "@chakra-ui/popper" "3.0.14" - "@chakra-ui/portal" "2.0.16" - "@chakra-ui/progress" "2.1.6" - "@chakra-ui/provider" "2.3.0" - "@chakra-ui/radio" "2.0.22" - "@chakra-ui/react-env" "3.0.0" - "@chakra-ui/select" "2.0.19" - "@chakra-ui/skeleton" "2.0.24" - "@chakra-ui/slider" "2.0.25" - "@chakra-ui/spinner" "2.0.13" - "@chakra-ui/stat" "2.0.18" - "@chakra-ui/stepper" "2.2.0" - "@chakra-ui/styled-system" "2.9.1" - "@chakra-ui/switch" "2.0.27" - "@chakra-ui/system" "2.5.8" - "@chakra-ui/table" "2.0.17" - "@chakra-ui/tabs" "2.1.9" - "@chakra-ui/tag" "3.0.0" - "@chakra-ui/textarea" "2.0.19" - "@chakra-ui/theme" "3.1.2" - "@chakra-ui/theme-utils" "2.0.18" - "@chakra-ui/toast" "6.1.4" - "@chakra-ui/tooltip" "2.2.9" - "@chakra-ui/transition" "2.0.16" - "@chakra-ui/utils" "2.0.15" - "@chakra-ui/visually-hidden" "2.0.15" - "@chakra-ui/select@2.0.12": version "2.0.12" - resolved "https://registry.npmjs.org/@chakra-ui/select/-/select-2.0.12.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/select/-/select-2.0.12.tgz#9b485e6a28c9aa468bc1c0d8a78aabd985b0c370" integrity sha512-NCDMb0w48GYCHmazVSQ7/ysEpbnri+Up6n+v7yytf6g43TPRkikvK5CsVgLnAEj0lIdCJhWXTcZer5wG5KOEgA== dependencies: "@chakra-ui/form-control" "2.0.11" -"@chakra-ui/select@2.0.19": - version "2.0.19" - resolved "https://registry.yarnpkg.com/@chakra-ui/select/-/select-2.0.19.tgz#957e95a17a890d8c0a851e2f00a8d8dd17932d66" - integrity sha512-eAlFh+JhwtJ17OrB6fO6gEAGOMH18ERNrXLqWbYLrs674Le7xuREgtuAYDoxUzvYXYYTTdOJtVbcHGriI3o6rA== - dependencies: - "@chakra-ui/form-control" "2.0.18" - "@chakra-ui/shared-utils" "2.0.5" - "@chakra-ui/shared-utils@2.0.2": version "2.0.2" resolved "https://registry.npmjs.org/@chakra-ui/shared-utils/-/shared-utils-2.0.2.tgz" integrity sha512-wC58Fh6wCnFFQyiebVZ0NI7PFW9+Vch0QE6qN7iR+bLseOzQY9miYuzPJ1kMYiFd6QTOmPJkI39M3wHqrPYiOg== -"@chakra-ui/shared-utils@2.0.5": - version "2.0.5" - resolved "https://registry.yarnpkg.com/@chakra-ui/shared-utils/-/shared-utils-2.0.5.tgz#cb2b49705e113853647f1822142619570feba081" - integrity sha512-4/Wur0FqDov7Y0nCXl7HbHzCg4aq86h+SXdoUeuCMD3dSj7dpsVnStLYhng1vxvlbUnLpdF4oz5Myt3i/a7N3Q== - "@chakra-ui/skeleton@2.0.17": version "2.0.17" - resolved "https://registry.npmjs.org/@chakra-ui/skeleton/-/skeleton-2.0.17.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/skeleton/-/skeleton-2.0.17.tgz#737e08f771980f5b73060dc6c940691e7759d044" integrity sha512-dL7viXEKDEzmAJGbHMj+QbGl9PAd0VWztEcWcz5wOGfmAcJllA0lVh6NmG/yqLb6iXPCX4Y1Y0Yurm459TEYWg== dependencies: "@chakra-ui/media-query" "3.2.7" "@chakra-ui/react-use-previous" "2.0.2" -"@chakra-ui/skeleton@2.0.24": - version "2.0.24" - resolved "https://registry.yarnpkg.com/@chakra-ui/skeleton/-/skeleton-2.0.24.tgz#dc9dcca6fc43005544fabfd38a444943b0a29cad" - integrity sha512-1jXtVKcl/jpbrJlc/TyMsFyI651GTXY5ma30kWyTXoby2E+cxbV6OR8GB/NMZdGxbQBax8/VdtYVjI0n+OBqWA== - dependencies: - "@chakra-ui/media-query" "3.2.12" - "@chakra-ui/react-use-previous" "2.0.5" - "@chakra-ui/shared-utils" "2.0.5" - "@chakra-ui/slider@2.0.12": version "2.0.12" - resolved "https://registry.npmjs.org/@chakra-ui/slider/-/slider-2.0.12.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/slider/-/slider-2.0.12.tgz#42fc5fe385c507276da29f4aa49a6408ee853978" integrity sha512-Cna04J7e4+F3tJNb7tRNfPP+koicbDsKJBp+f1NpR32JbRzIfrf2Vdr4hfD5/uOfC4RGxnVInNZzZLGBelLtLw== dependencies: "@chakra-ui/number-utils" "2.0.4" @@ -2291,34 +1680,11 @@ "@chakra-ui/react-use-size" "2.0.4" "@chakra-ui/react-use-update-effect" "2.0.4" -"@chakra-ui/slider@2.0.25": - version "2.0.25" - resolved "https://registry.yarnpkg.com/@chakra-ui/slider/-/slider-2.0.25.tgz#2d69af68f4afcc648d14603d7c3163660d35e9eb" - integrity sha512-FnWSi0AIXP+9sHMCPboOKGqm902k8dJtsJ7tu3D0AcKkE62WtYLZ2sTqvwJxCfSl4KqVI1i571SrF9WadnnJ8w== - dependencies: - "@chakra-ui/number-utils" "2.0.7" - "@chakra-ui/react-context" "2.0.8" - "@chakra-ui/react-types" "2.0.7" - "@chakra-ui/react-use-callback-ref" "2.0.7" - "@chakra-ui/react-use-controllable-state" "2.0.8" - "@chakra-ui/react-use-latest-ref" "2.0.5" - "@chakra-ui/react-use-merge-refs" "2.0.7" - "@chakra-ui/react-use-pan-event" "2.0.9" - "@chakra-ui/react-use-size" "2.0.10" - "@chakra-ui/react-use-update-effect" "2.0.7" - "@chakra-ui/spinner@2.0.10": version "2.0.10" - resolved "https://registry.npmjs.org/@chakra-ui/spinner/-/spinner-2.0.10.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/spinner/-/spinner-2.0.10.tgz#f8b1b6f1c8f45e3aeab44d5ab1f1debc71e52573" integrity sha512-SwId1xPaaFAaEYrR9eHkQHAuB66CbxwjWaQonEjeEUSh9ecxkd5WbXlsQSyf2hVRIqXJg0m3HIYblcKUsQt9Rw== -"@chakra-ui/spinner@2.0.13": - version "2.0.13" - resolved "https://registry.yarnpkg.com/@chakra-ui/spinner/-/spinner-2.0.13.tgz#64fe919c18305c653ced046e25d5883ee4c1e7d7" - integrity sha512-T1/aSkVpUIuiYyrjfn1+LsQEG7Onbi1UE9ccS/evgf61Dzy4GgTXQUnDuWFSgpV58owqirqOu6jn/9eCwDlzlg== - dependencies: - "@chakra-ui/shared-utils" "2.0.5" - "@chakra-ui/spinner@^1.0.0": version "1.2.6" resolved "https://registry.yarnpkg.com/@chakra-ui/spinner/-/spinner-1.2.6.tgz#d85fb3d763a69d40570b591507c5087dba38e6c4" @@ -2329,30 +1695,12 @@ "@chakra-ui/stat@2.0.11": version "2.0.11" - resolved "https://registry.npmjs.org/@chakra-ui/stat/-/stat-2.0.11.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/stat/-/stat-2.0.11.tgz#0c052aee68486a892e09e802bb569dc984e31eae" integrity sha512-ZPFK2fKufDSHD8bp/KhO3jLgW/b3PzdG4zV+7iTO7OYjxm5pkBfBAeMqfXGx4cl51rtWUKzsY0HV4vLLjcSjHw== dependencies: "@chakra-ui/icon" "3.0.11" "@chakra-ui/react-context" "2.0.4" -"@chakra-ui/stat@2.0.18": - version "2.0.18" - resolved "https://registry.yarnpkg.com/@chakra-ui/stat/-/stat-2.0.18.tgz#9e5d21d162b7cf2cf92065c19291ead2d4660772" - integrity sha512-wKyfBqhVlIs9bkSerUc6F9KJMw0yTIEKArW7dejWwzToCLPr47u+CtYO6jlJHV6lRvkhi4K4Qc6pyvtJxZ3VpA== - dependencies: - "@chakra-ui/icon" "3.0.16" - "@chakra-ui/react-context" "2.0.8" - "@chakra-ui/shared-utils" "2.0.5" - -"@chakra-ui/stepper@2.2.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@chakra-ui/stepper/-/stepper-2.2.0.tgz#c42562fd1b210595303f14970d9df6b32e1ad5a1" - integrity sha512-8ZLxV39oghSVtOUGK8dX8Z6sWVSQiKVmsK4c3OQDa8y2TvxP0VtFD0Z5U1xJlOjQMryZRWhGj9JBc3iQLukuGg== - dependencies: - "@chakra-ui/icon" "3.0.16" - "@chakra-ui/react-context" "2.0.8" - "@chakra-ui/shared-utils" "2.0.5" - "@chakra-ui/styled-system@1.19.0": version "1.19.0" resolved "https://registry.yarnpkg.com/@chakra-ui/styled-system/-/styled-system-1.19.0.tgz#102fadaefc1a2dfd8e0c4837eafa660531a08419" @@ -2363,21 +1711,12 @@ "@chakra-ui/styled-system@2.3.4": version "2.3.4" - resolved "https://registry.npmjs.org/@chakra-ui/styled-system/-/styled-system-2.3.4.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/styled-system/-/styled-system-2.3.4.tgz#6022c5a675b54a69b1d3c2d3e60258901dc7b82a" integrity sha512-Lozbedu+GBj4EbHB/eGv475SFDLApsIEN9gNKiZJBJAE1HIhHn3Seh1iZQSrHC/Beq+D5cQq3Z+yPn3bXtFU7w== dependencies: csstype "^3.0.11" lodash.mergewith "4.6.2" -"@chakra-ui/styled-system@2.9.1": - version "2.9.1" - resolved "https://registry.yarnpkg.com/@chakra-ui/styled-system/-/styled-system-2.9.1.tgz#888a4901b2afa174461259a8875379adb0363934" - integrity sha512-jhYKBLxwOPi9/bQt9kqV3ELa/4CjmNNruTyXlPp5M0v0+pDMUngPp48mVLoskm9RKZGE0h1qpvj/jZ3K7c7t8w== - dependencies: - "@chakra-ui/shared-utils" "2.0.5" - csstype "^3.0.11" - lodash.mergewith "4.6.2" - "@chakra-ui/styled-system@^2.3.5": version "2.3.5" resolved "https://registry.npmjs.org/@chakra-ui/styled-system/-/styled-system-2.3.5.tgz" @@ -2388,22 +1727,14 @@ "@chakra-ui/switch@2.0.14": version "2.0.14" - resolved "https://registry.npmjs.org/@chakra-ui/switch/-/switch-2.0.14.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/switch/-/switch-2.0.14.tgz#62372355bf73c19896b39fb7e75c132333c5a882" integrity sha512-6lzhCkJq7vbD3yGaorGLp0ZZU4ewdKwAu0e62qR8TfYZwbcbpkXbBKloIHbA2XKOduISzS2WYqjmoP6jSKIxrA== dependencies: "@chakra-ui/checkbox" "2.2.2" -"@chakra-ui/switch@2.0.27": - version "2.0.27" - resolved "https://registry.yarnpkg.com/@chakra-ui/switch/-/switch-2.0.27.tgz#e76e5afdfc837c83fce34480de4431ff8c19fcb8" - integrity sha512-z76y2fxwMlvRBrC5W8xsZvo3gP+zAEbT3Nqy5P8uh/IPd5OvDsGeac90t5cgnQTyxMOpznUNNK+1eUZqtLxWnQ== - dependencies: - "@chakra-ui/checkbox" "2.2.15" - "@chakra-ui/shared-utils" "2.0.5" - "@chakra-ui/system@2.3.0": version "2.3.0" - resolved "https://registry.npmjs.org/@chakra-ui/system/-/system-2.3.0.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/system/-/system-2.3.0.tgz#b7ba122872d4d48806fbf994f1187680ae2296a6" integrity sha512-BxikahglBI0uU8FE3anEorDTU5oKTUuBIEKVcQrEVnrbNuRJEy1OVYyCNXfqW3MpruRO9ypYV2bWt02AZZWEaQ== dependencies: "@chakra-ui/color-mode" "2.1.9" @@ -2413,19 +1744,6 @@ "@chakra-ui/utils" "2.0.11" react-fast-compare "3.2.0" -"@chakra-ui/system@2.5.8": - version "2.5.8" - resolved "https://registry.yarnpkg.com/@chakra-ui/system/-/system-2.5.8.tgz#9026090b792320683bf1cc3a8f04af7b10c947ce" - integrity sha512-Vy8UUaCxikOzOGE54IP8tKouvU38rEYU1HCSquU9+oe7Jd70HaiLa4vmUKvHyMUmxkOzDHIkgZLbVQCubSnN5w== - dependencies: - "@chakra-ui/color-mode" "2.1.12" - "@chakra-ui/object-utils" "2.1.0" - "@chakra-ui/react-utils" "2.0.12" - "@chakra-ui/styled-system" "2.9.1" - "@chakra-ui/theme-utils" "2.0.18" - "@chakra-ui/utils" "2.0.15" - react-fast-compare "3.2.1" - "@chakra-ui/system@^1.2.0": version "1.12.1" resolved "https://registry.yarnpkg.com/@chakra-ui/system/-/system-1.12.1.tgz#608655ef3f7cb82eedd8f20d2546458d90d77cce" @@ -2439,22 +1757,14 @@ "@chakra-ui/table@2.0.11": version "2.0.11" - resolved "https://registry.npmjs.org/@chakra-ui/table/-/table-2.0.11.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/table/-/table-2.0.11.tgz#9bd25d5383c94982b89e792675bc1d1f667f81f3" integrity sha512-zQTiqPKEgjdeO/PG0FByn0fH4sPF7dLJF+YszrIzDc6wvpD96iY6MYLeV+CSelbH1g0/uibcJ10PSaFStfGUZg== dependencies: "@chakra-ui/react-context" "2.0.4" -"@chakra-ui/table@2.0.17": - version "2.0.17" - resolved "https://registry.yarnpkg.com/@chakra-ui/table/-/table-2.0.17.tgz#ad394dc6dcbe5a8a9e6d899997ecca3471603977" - integrity sha512-OScheTEp1LOYvTki2NFwnAYvac8siAhW9BI5RKm5f5ORL2gVJo4I72RUqE0aKe1oboxgm7CYt5afT5PS5cG61A== - dependencies: - "@chakra-ui/react-context" "2.0.8" - "@chakra-ui/shared-utils" "2.0.5" - "@chakra-ui/tabs@2.1.4": version "2.1.4" - resolved "https://registry.npmjs.org/@chakra-ui/tabs/-/tabs-2.1.4.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/tabs/-/tabs-2.1.4.tgz#38d9748ce2cfa583a123c0f695ea1cbce1a6bd42" integrity sha512-/CQGj1lC9lvruT5BCYZH6Ok64W4CDSysDXuR2XPZXIih9kVOdXQEMXxG8+3vc63WqTBjHuURtZI0g8ouOy84ew== dependencies: "@chakra-ui/clickable" "2.0.10" @@ -2466,108 +1776,49 @@ "@chakra-ui/react-use-merge-refs" "2.0.4" "@chakra-ui/react-use-safe-layout-effect" "2.0.2" -"@chakra-ui/tabs@2.1.9": - version "2.1.9" - resolved "https://registry.yarnpkg.com/@chakra-ui/tabs/-/tabs-2.1.9.tgz#2e5214cb453c6cc0c240e82bd88af1042fc6fe0e" - integrity sha512-Yf8e0kRvaGM6jfkJum0aInQ0U3ZlCafmrYYni2lqjcTtThqu+Yosmo3iYlnullXxCw5MVznfrkb9ySvgQowuYg== - dependencies: - "@chakra-ui/clickable" "2.0.14" - "@chakra-ui/descendant" "3.0.14" - "@chakra-ui/lazy-utils" "2.0.5" - "@chakra-ui/react-children-utils" "2.0.6" - "@chakra-ui/react-context" "2.0.8" - "@chakra-ui/react-use-controllable-state" "2.0.8" - "@chakra-ui/react-use-merge-refs" "2.0.7" - "@chakra-ui/react-use-safe-layout-effect" "2.0.5" - "@chakra-ui/shared-utils" "2.0.5" - "@chakra-ui/tag@2.0.11": version "2.0.11" - resolved "https://registry.npmjs.org/@chakra-ui/tag/-/tag-2.0.11.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/tag/-/tag-2.0.11.tgz#14702adf5d1456dbbb84ea7a4b314953b92c323f" integrity sha512-iJJcX+4hl+6Se/8eCRzG+xxDwZfiYgc4Ly/8s93M0uW2GLb+ybbfSE2DjeKSyk3mQVeGzuxGkBfDHH2c2v26ew== dependencies: "@chakra-ui/icon" "3.0.11" "@chakra-ui/react-context" "2.0.4" -"@chakra-ui/tag@3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@chakra-ui/tag/-/tag-3.0.0.tgz#d86cdab59bb3ff7fc628c2dbe7a5ff1b36bd3e96" - integrity sha512-YWdMmw/1OWRwNkG9pX+wVtZio+B89odaPj6XeMn5nfNN8+jyhIEpouWv34+CO9G0m1lupJTxPSfgLAd7cqXZMA== - dependencies: - "@chakra-ui/icon" "3.0.16" - "@chakra-ui/react-context" "2.0.8" - "@chakra-ui/textarea@2.0.12": version "2.0.12" - resolved "https://registry.npmjs.org/@chakra-ui/textarea/-/textarea-2.0.12.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/textarea/-/textarea-2.0.12.tgz#469c1d64cb855b3b534dcd7fcc1d927e60da8da1" integrity sha512-msR9YMynRXwZIqR6DgjQ2MogA/cW1syBx/R0v3es+9Zx8zlbuKdoLhYqajHteCup8dUzTeIH2Vs2vAwgq4wu5A== dependencies: "@chakra-ui/form-control" "2.0.11" -"@chakra-ui/textarea@2.0.19": - version "2.0.19" - resolved "https://registry.yarnpkg.com/@chakra-ui/textarea/-/textarea-2.0.19.tgz#470b459f9cb3255d2abbe07d46b0a5b60a6a32c5" - integrity sha512-adJk+qVGsFeJDvfn56CcJKKse8k7oMGlODrmpnpTdF+xvlsiTM+1GfaJvgNSpHHuQFdz/A0z1uJtfGefk0G2ZA== - dependencies: - "@chakra-ui/form-control" "2.0.18" - "@chakra-ui/shared-utils" "2.0.5" - "@chakra-ui/theme-tools@2.0.12": version "2.0.12" - resolved "https://registry.npmjs.org/@chakra-ui/theme-tools/-/theme-tools-2.0.12.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/theme-tools/-/theme-tools-2.0.12.tgz#b29d9fb626d35e3b00f532c64f95ea261d8f6997" integrity sha512-mnMlKSmXkCjHUJsKWmJbgBTGF2vnLaMLv1ihkBn5eQcCubMQrBLTiMAEFl5pZdzuHItU6QdnLGA10smcXbNl0g== dependencies: "@chakra-ui/anatomy" "2.0.7" "@ctrl/tinycolor" "^3.4.0" -"@chakra-ui/theme-tools@2.0.18": - version "2.0.18" - resolved "https://registry.yarnpkg.com/@chakra-ui/theme-tools/-/theme-tools-2.0.18.tgz#8160f0abe331e60b56f77426c28ff9a605c1a5c4" - integrity sha512-MbiRuXb2tb41FbnW41zhsYYAU0znlpfYZnu0mxCf8U2otCwPekJCfESUGYypjq4JnydQ7TDOk+Kz/Wi974l4mw== - dependencies: - "@chakra-ui/anatomy" "2.1.2" - "@chakra-ui/shared-utils" "2.0.5" - color2k "^2.0.0" - "@chakra-ui/theme-utils@2.0.1": version "2.0.1" - resolved "https://registry.npmjs.org/@chakra-ui/theme-utils/-/theme-utils-2.0.1.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/theme-utils/-/theme-utils-2.0.1.tgz#a3dc99331ba943e155dd683fe25ce302e3084db0" integrity sha512-NDwzgTPxm+v3PAJlSSU1MORHLMqO9vsRJ+ObELD5wpvE9aEyRziN/AZSoK2oLwCQMPEiU7R99K5ij1E6ptMt7w== dependencies: "@chakra-ui/styled-system" "2.3.4" "@chakra-ui/theme" "2.1.14" lodash.mergewith "4.6.2" -"@chakra-ui/theme-utils@2.0.18": - version "2.0.18" - resolved "https://registry.yarnpkg.com/@chakra-ui/theme-utils/-/theme-utils-2.0.18.tgz#c240545d0f00b6cc059195a784683d1f143a44af" - integrity sha512-aSbkUUiFpc1NHC7lQdA6uYlr6EcZFXz6b4aJ7VRDpqTiywvqYnvfGzhmsB0z94vgtS9qXc6HoIwBp25jYGV2MA== - dependencies: - "@chakra-ui/shared-utils" "2.0.5" - "@chakra-ui/styled-system" "2.9.1" - "@chakra-ui/theme" "3.1.2" - lodash.mergewith "4.6.2" - "@chakra-ui/theme@2.1.14": version "2.1.14" - resolved "https://registry.npmjs.org/@chakra-ui/theme/-/theme-2.1.14.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/theme/-/theme-2.1.14.tgz#4726d65a65515f8ee96b5f2a725d0d17804ddfc9" integrity sha512-6EYJCQlrjSjNAJvZmw1un50F8+sQDFsdwu/7UzWe+TeANpKlz4ZcHbh0gkl3PD62lGis+ehITUwqRm8htvDOjw== dependencies: "@chakra-ui/anatomy" "2.0.7" "@chakra-ui/theme-tools" "2.0.12" -"@chakra-ui/theme@3.1.2": - version "3.1.2" - resolved "https://registry.yarnpkg.com/@chakra-ui/theme/-/theme-3.1.2.tgz#1e78a19083adecb38b884c1c2da6dee2c84c81f2" - integrity sha512-ebUXMS3LZw2OZxEQNYaFw3/XuA3jpyprhS/frjHMvZKSOaCjMW+c9z25S0jp1NnpQff08VGI8EWbyVZECXU1QA== - dependencies: - "@chakra-ui/anatomy" "2.1.2" - "@chakra-ui/shared-utils" "2.0.5" - "@chakra-ui/theme-tools" "2.0.18" - "@chakra-ui/toast@4.0.0": version "4.0.0" - resolved "https://registry.npmjs.org/@chakra-ui/toast/-/toast-4.0.0.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/toast/-/toast-4.0.0.tgz#797c34c4ecfcad7c6899c1cda221af0ff04d5d0b" integrity sha512-abeeloJac5T9WK2IN76fEM5FSRH+erNXln2HqDf5wLBn33avSBXWyTiUL8riVSUqto0lrIn6FuK/MmKo0DH4og== dependencies: "@chakra-ui/alert" "2.0.11" @@ -2578,24 +1829,9 @@ "@chakra-ui/styled-system" "2.3.4" "@chakra-ui/theme" "2.1.14" -"@chakra-ui/toast@6.1.4": - version "6.1.4" - resolved "https://registry.yarnpkg.com/@chakra-ui/toast/-/toast-6.1.4.tgz#853a844408c0e22f15c66b4f2607b8416300c649" - integrity sha512-wAcPHq/N/ar4jQxkUGhnsbp+lx2eKOpHxn1KaWdHXUkqCNUA1z09fvBsoMyzObSiiwbDuQPZG5RxsOhzfPZX4Q== - dependencies: - "@chakra-ui/alert" "2.1.0" - "@chakra-ui/close-button" "2.0.17" - "@chakra-ui/portal" "2.0.16" - "@chakra-ui/react-context" "2.0.8" - "@chakra-ui/react-use-timeout" "2.0.5" - "@chakra-ui/react-use-update-effect" "2.0.7" - "@chakra-ui/shared-utils" "2.0.5" - "@chakra-ui/styled-system" "2.9.1" - "@chakra-ui/theme" "3.1.2" - "@chakra-ui/tooltip@2.2.0": version "2.2.0" - resolved "https://registry.npmjs.org/@chakra-ui/tooltip/-/tooltip-2.2.0.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/tooltip/-/tooltip-2.2.0.tgz#24e005f831cddf1c0e41dd246ed2771a97b8637c" integrity sha512-oB97aQJBW+U3rRIt1ct7NaDRMnbW16JQ5ZBCl3BzN1VJWO3djiNuscpjVdZSceb+FdGSFo+GoDozp1ZwqdfFeQ== dependencies: "@chakra-ui/popper" "3.0.8" @@ -2605,20 +1841,6 @@ "@chakra-ui/react-use-event-listener" "2.0.4" "@chakra-ui/react-use-merge-refs" "2.0.4" -"@chakra-ui/tooltip@2.2.9": - version "2.2.9" - resolved "https://registry.yarnpkg.com/@chakra-ui/tooltip/-/tooltip-2.2.9.tgz#a7f25f7e6d1304ea448a3420ed99f79a657537bd" - integrity sha512-ZoksllanqXRUyMDaiogvUVJ+RdFXwZrfrwx3RV22fejYZIQ602hZ3QHtHLB5ZnKFLbvXKMZKM23HxFTSb0Ytqg== - dependencies: - "@chakra-ui/dom-utils" "2.1.0" - "@chakra-ui/popper" "3.0.14" - "@chakra-ui/portal" "2.0.16" - "@chakra-ui/react-types" "2.0.7" - "@chakra-ui/react-use-disclosure" "2.0.8" - "@chakra-ui/react-use-event-listener" "2.0.7" - "@chakra-ui/react-use-merge-refs" "2.0.7" - "@chakra-ui/shared-utils" "2.0.5" - "@chakra-ui/transition@1.4.8": version "1.4.8" resolved "https://registry.yarnpkg.com/@chakra-ui/transition/-/transition-1.4.8.tgz#ac0f4675da929ae69fc9d6db6a1edf61e982772c" @@ -2628,16 +1850,9 @@ "@chakra-ui/transition@2.0.11": version "2.0.11" - resolved "https://registry.npmjs.org/@chakra-ui/transition/-/transition-2.0.11.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/transition/-/transition-2.0.11.tgz#b2cfeb2150871c635cb9d03d9b525481dbe56f56" integrity sha512-O0grc162LARPurjz1R+J+zr4AAKsVwN5+gaqLfZLMWg6TpvczJhwEA2fLCNAdkC/gomere390bJsy52xfUacUw== -"@chakra-ui/transition@2.0.16": - version "2.0.16" - resolved "https://registry.yarnpkg.com/@chakra-ui/transition/-/transition-2.0.16.tgz#498c91e6835bb5d950fd1d1402f483b85f7dcd87" - integrity sha512-E+RkwlPc3H7P1crEXmXwDXMB2lqY2LLia2P5siQ4IEnRWIgZXlIw+8Em+NtHNgusel2N+9yuB0wT9SeZZeZ3CQ== - dependencies: - "@chakra-ui/shared-utils" "2.0.5" - "@chakra-ui/utils@1.10.4", "@chakra-ui/utils@^1.10.4": version "1.10.4" resolved "https://registry.yarnpkg.com/@chakra-ui/utils/-/utils-1.10.4.tgz#40a32d4efd8684b2e7432a40b285796383eacfd3" @@ -2650,7 +1865,7 @@ "@chakra-ui/utils@2.0.11": version "2.0.11" - resolved "https://registry.npmjs.org/@chakra-ui/utils/-/utils-2.0.11.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/utils/-/utils-2.0.11.tgz#8e773f900a8356bd10c48b59151a781dba1c7b70" integrity sha512-4ZQdK6tbOuTrUCsAQBHWo7tw5/Q6pBV93ZbVpats61cSWMFGv32AIQw9/hA4un2zDeSWN9ZMVLNjAY2Dq/KQOA== dependencies: "@types/lodash.mergewith" "4.6.6" @@ -2658,16 +1873,6 @@ framesync "5.3.0" lodash.mergewith "4.6.2" -"@chakra-ui/utils@2.0.15": - version "2.0.15" - resolved "https://registry.yarnpkg.com/@chakra-ui/utils/-/utils-2.0.15.tgz#bd800b1cff30eb5a5e8c36fa039f49984b4c5e4a" - integrity sha512-El4+jL0WSaYYs+rJbuYFDbjmfCcfGDmRY95GO4xwzit6YAPZBLcR65rOEwLps+XWluZTy1xdMrusg/hW0c1aAA== - dependencies: - "@types/lodash.mergewith" "4.6.7" - css-box-model "1.2.1" - framesync "6.1.2" - lodash.mergewith "4.6.2" - "@chakra-ui/visually-hidden@1.1.6": version "1.1.6" resolved "https://registry.yarnpkg.com/@chakra-ui/visually-hidden/-/visually-hidden-1.1.6.tgz#7a546a5aebe4779c8f18d65b1f0e56249720f28d" @@ -2677,14 +1882,9 @@ "@chakra-ui/visually-hidden@2.0.11": version "2.0.11" - resolved "https://registry.npmjs.org/@chakra-ui/visually-hidden/-/visually-hidden-2.0.11.tgz" + resolved "https://registry.yarnpkg.com/@chakra-ui/visually-hidden/-/visually-hidden-2.0.11.tgz#b2eb236e803451b39cdfcce3c5ab52e773c066a3" integrity sha512-e+5amYvnsmEQdiWH4XMyvrtGTdwz//+48vwj5CsNWWcselzkwqodmciy5rIrT71/SCQDOtmgnL7ZWAUOffxfsQ== -"@chakra-ui/visually-hidden@2.0.15": - version "2.0.15" - resolved "https://registry.yarnpkg.com/@chakra-ui/visually-hidden/-/visually-hidden-2.0.15.tgz#60df64e0ab97d95fee4e6c61ccabd15fd5ace398" - integrity sha512-WWULIiucYRBIewHKFA7BssQ2ABLHLVd9lrUo3N3SZgR0u4ZRDDVEUNOy+r+9ruDze8+36dGbN9wsN1IdELtdOw== - "@commitlint/cli@^17.1.2": version "17.1.2" resolved "https://registry.npmjs.org/@commitlint/cli/-/cli-17.1.2.tgz" @@ -3019,118 +2219,101 @@ resolved "https://registry.yarnpkg.com/@cosmjs/utils/-/utils-0.30.1.tgz#6d92582341be3c2ec8d82090253cfa4b7f959edb" integrity sha512-KvvX58MGMWh7xA+N+deCfunkA/ZNDvFLw4YbOmX3f/XBIkqrVY7qlotfy2aNb1kgp6h4B6Yc8YawJPDTfvWX7g== -"@cosmology-ui/react@^0.1.21": - version "0.1.21" - resolved "https://registry.yarnpkg.com/@cosmology-ui/react/-/react-0.1.21.tgz#53a2a42b6805baec4541928d9a98a9cab0caef31" - integrity sha512-eOaYIFhm8XBf1bex49AuZjiv4livhUUXGmq5rJua5m+B4JxKOcyC5w+e38KoYQT9c6yiwsFfBSnIENdTtbRw7g== +"@cosmos-kit/compass-extension@^2.1.6": + version "2.1.6" + resolved "https://registry.yarnpkg.com/@cosmos-kit/compass-extension/-/compass-extension-2.1.6.tgz#0d9b17315ded2826c7c242d37e8b3ed852cb04a1" + integrity sha512-jyrMw/x4s+nVxk0GKg4Qv2CUKFWMuAgYb/o+j3/bsoLuAFELHmlNW6cOuSy9R5ypZ38rK8net2UZq8AL0qsp1w== dependencies: - "@babel/runtime" "^7.11.2" - "@chakra-ui/react" "^2.5.1" - "@cosmology-ui/utils" "^0.1.24" - "@emotion/react" "^11.10.6" - "@emotion/styled" "^11.10.6" - bowser "2.11.0" - chain-registry "^1.5.0" - chakra-react-select "^4.4.2" - fast-fuzzy "^1.12.0" - framer-motion "^9.0.7" - qrcode.react "^3.1.0" - react "18.2.0" - react-icons "^4.4.0" - react-resize-detector "^8.0.3" - -"@cosmology-ui/utils@^0.1.24": - version "0.1.24" - resolved "https://registry.yarnpkg.com/@cosmology-ui/utils/-/utils-0.1.24.tgz#5544cebfca6a6a679a4c13a9d3ed6866712619fd" - integrity sha512-jtJGCMVQMt3SrZFMi3WJ+4+ad1Puux4KQmEZGCnlZLMj+6ebEEdkUuYsmVxTdI/qlAo9RlVVIzVgD4gTelbD7w== - dependencies: - "@babel/runtime" "^7.11.2" - "@chakra-ui/react" "^2.5.1" - "@cosmology-ui/utils" "^0.1.24" - "@emotion/react" "^11.10.6" - "@emotion/styled" "^11.10.6" - bowser "2.11.0" - chain-registry "^1.5.0" - chakra-react-select "^4.4.2" - fast-fuzzy "^1.12.0" - framer-motion "^9.0.7" - qrcode.react "^3.1.0" - react "18.2.0" - react-icons "^4.4.0" - react-resize-detector "^8.0.3" - -"@cosmos-kit/core@^1.5.8": - version "1.5.8" - resolved "https://registry.yarnpkg.com/@cosmos-kit/core/-/core-1.5.8.tgz#dcbda6d2819c2d69948331004818598db768d56b" - integrity sha512-dC8w0k+rNEdCiYOBd8aBM6ZLGxkXRKG9vjWeVmUD5xuNa2YQh192pdOYEu2U2wc8FgjixuR5hOSvUBMsfTt+cw== + "@chain-registry/keplr" "1.8.0" + "@cosmos-kit/core" "^2.2.1" + +"@cosmos-kit/compass@^2.1.6": + version "2.1.6" + resolved "https://registry.yarnpkg.com/@cosmos-kit/compass/-/compass-2.1.6.tgz#0cf991320e78239c2fdc2e37470a324bbdb4d5f6" + integrity sha512-YTvaIOmCfgsxJBQGTxc4sAOLEEXLyeL2SXaFC5TSfi9yiBivm2mvIilaWjn3fq7KlqSbt6LZW6N7FZqevZEZzg== + dependencies: + "@cosmos-kit/compass-extension" "^2.1.6" + +"@cosmos-kit/core@2.2.1", "@cosmos-kit/core@^2.2.1": + version "2.2.1" + resolved "https://registry.yarnpkg.com/@cosmos-kit/core/-/core-2.2.1.tgz#d586f38e41a43869d02d77dd4d3df0a64f99277c" + integrity sha512-OJYQC8LsNGsoifz7/T5xhj9qddCBX74/vLrl9cxI+EjSLxWm/ow5JvKgvGWzGZ7gmjRsaP2b+KpuSUIZNHEldA== dependencies: "@chain-registry/types" "0.13.0" "@walletconnect/types" "2.7.2" bowser "2.11.0" events "3.3.0" -"@cosmos-kit/keplr-extension@^0.35.9": - version "0.35.9" - resolved "https://registry.yarnpkg.com/@cosmos-kit/keplr-extension/-/keplr-extension-0.35.9.tgz#a0793b334181e0f2c921071d236dca5b5951dfbd" - integrity sha512-ifb3AL7EKmynVRYIbGRNs+QQdoRfOrVPEivBHuaJDQ6tV+d3isV6lNLXCewL/CLS+EaM0qOemMm+PzhNVGJKwA== +"@cosmos-kit/keplr-extension@^2.1.6": + version "2.1.6" + resolved "https://registry.yarnpkg.com/@cosmos-kit/keplr-extension/-/keplr-extension-2.1.6.tgz#4e17ca99a146cc768b8f657f9f93e0d5f666c5da" + integrity sha512-vEjgRnLhSrWReb+Ty0gAh1luOEJTeNc7nw3GxbKpXXqDtEi6wUzaNIfvMXbdyFGFQemLoTDVbMlPauel8g4w4g== dependencies: "@chain-registry/keplr" "1.8.0" - "@cosmos-kit/core" "^1.5.8" + "@cosmos-kit/core" "^2.2.1" -"@cosmos-kit/keplr-mobile@^0.33.38": - version "0.33.38" - resolved "https://registry.yarnpkg.com/@cosmos-kit/keplr-mobile/-/keplr-mobile-0.33.38.tgz#f0bf7193ef0204883d6603a0d911728eb5aed815" - integrity sha512-7BKlmmZF6YwOtFBgaS0HtwhuJrCd313qaetqLSaX8sf1mRSHJjE/UVcBhD1m3Rw/jmclGvuSDcpfF8rp1u8SEg== +"@cosmos-kit/keplr-mobile@^2.1.6": + version "2.1.6" + resolved "https://registry.yarnpkg.com/@cosmos-kit/keplr-mobile/-/keplr-mobile-2.1.6.tgz#3f280a9c0dcef5ad87e3368a7039d5b4fcf81f7a" + integrity sha512-iF2lY8iKoSWhWs82szhgJpFMl04jbGfbT63jyUKRXUBOMpzfwNhQ5mJyVcd1QvP5qR8gMTTZuc1wKD9ziPhJkA== dependencies: "@chain-registry/keplr" "1.8.0" - "@cosmos-kit/core" "^1.5.8" - "@cosmos-kit/walletconnect" "^0.3.15" + "@cosmos-kit/core" "^2.2.1" + "@cosmos-kit/walletconnect" "^2.1.6" -"@cosmos-kit/keplr@^0.33.38": - version "0.33.38" - resolved "https://registry.yarnpkg.com/@cosmos-kit/keplr/-/keplr-0.33.38.tgz#a1eca7f4030e80a1ade9fc55b61b54d4ce479478" - integrity sha512-Txe+RDbtOCNtDw/qzs7MzqR2Yuj0CvMTJTtiO1Tn1SKGIQV7PkW2uoIcoDGnpjOVlmbt0Q2hrAImAzjLknYP6Q== +"@cosmos-kit/keplr@2.1.6": + version "2.1.6" + resolved "https://registry.yarnpkg.com/@cosmos-kit/keplr/-/keplr-2.1.6.tgz#d152bcd7073d44bdb5f2ffd7cedbeef3998cc970" + integrity sha512-7YZSo5k9KWPeUEbxI+GRyeWGpVirn9xN78W+pvGL04A6Yi7wKzq0Jb/0x+NczGndBy62oY35/5zdR5SiWE9yUQ== dependencies: - "@cosmos-kit/keplr-extension" "^0.35.9" - "@cosmos-kit/keplr-mobile" "^0.33.38" + "@cosmos-kit/keplr-extension" "^2.1.6" + "@cosmos-kit/keplr-mobile" "^2.1.6" -"@cosmos-kit/react-lite@^1.4.10": - version "1.4.10" - resolved "https://registry.yarnpkg.com/@cosmos-kit/react-lite/-/react-lite-1.4.10.tgz#4f405a315fe9f0a4fb2c7a0734a21194d147f04a" - integrity sha512-VJi4mR2i2mCUB7NudsktEpDo8Jec9zZVbx0/yC9xxDfi2Q535yGsUxTWxnZpoYTZAh2n0yq7iigNAz5DAk+nJQ== +"@cosmos-kit/react-lite@^2.1.7": + version "2.1.7" + resolved "https://registry.yarnpkg.com/@cosmos-kit/react-lite/-/react-lite-2.1.7.tgz#3e8868e67b7a39d2281090d8192f74b34a2eb65e" + integrity sha512-XqxzL8vq7TAgqIXbEGDUnSdwsGCBZPcptsFJtkvuVYz7gExTafQ1pSSLpaFXXWPKLaH2fjrEBqJSg7BvJ6v3eA== dependencies: - "@babel/runtime" "7.11.2" "@chain-registry/types" "0.13.1" - "@cosmos-kit/core" "^1.5.8" - react "18.2.0" + "@cosmos-kit/core" "^2.2.1" -"@cosmos-kit/react@^1.3.31": - version "1.3.31" - resolved "https://registry.yarnpkg.com/@cosmos-kit/react/-/react-1.3.31.tgz#735de3c2beb536d4c0f5ab0e54adf6fd438efcce" - integrity sha512-5xEMEMdn6xwFQcYXmakaQ0Pyvu7DVMA0pDPAIKqV1ICpl4NlIqX3jhMtfH/535DTjcy8St9lnPlKR75T78uqlQ== +"@cosmos-kit/react@2.2.1": + version "2.2.1" + resolved "https://registry.yarnpkg.com/@cosmos-kit/react/-/react-2.2.1.tgz#c3e5180fb7856c3e3944b29602e41e730597f03f" + integrity sha512-CxJjPdRJ97jAQTCbotU53TKinPTgguw/T9ty3otQrG+ikj7KPF4DYDm3fRFL7exYoFqn5DoM392d6vccJTqqFg== dependencies: - "@babel/runtime" "7.11.2" "@chain-registry/types" "0.13.1" - "@chakra-ui/react" "^2.5.1" - "@cosmology-ui/react" "^0.1.21" - "@cosmos-kit/core" "^1.5.8" - "@cosmos-kit/react-lite" "^1.4.10" - "@emotion/react" "^11.10.6" - "@emotion/styled" "^11.10.6" - framer-motion "^9.0.7" - react "18.2.0" - react-icons "4.4.0" - -"@cosmos-kit/walletconnect@^0.3.15": - version "0.3.15" - resolved "https://registry.yarnpkg.com/@cosmos-kit/walletconnect/-/walletconnect-0.3.15.tgz#34b6ff1f2a1fe2d8f9a6af0686b4581d50286f2e" - integrity sha512-efcGZllo3peO9+vs5imkYG1PSpB4SW2sOwWTB4HfUZtUree5sX1+viDNwinEYjncxc6ScvAxvPPcVuhWW6V9BA== - dependencies: - "@babel/runtime" "7.11.2" - "@cosmos-kit/core" "^1.5.8" - "@walletconnect/sign-client" "^2.7.2" - "@walletconnect/types" "^2.7.2" - "@walletconnect/utils" "^2.7.2" + "@cosmos-kit/core" "^2.2.1" + "@cosmos-kit/react-lite" "^2.1.7" + "@interchain-ui/react" "1.3.0" + "@react-icons/all-files" "^4.1.0" + +"@cosmos-kit/station-extension@^2.1.6": + version "2.1.6" + resolved "https://registry.yarnpkg.com/@cosmos-kit/station-extension/-/station-extension-2.1.6.tgz#74033af2b5c23646514351817197c1f8d49b9e8c" + integrity sha512-AY4tPVrQkjjo6+Rc3Bcyp1QSuJyMqcy6sVwP7vKfOvPmYD9FUo+MktwfiDp0zu5DuTB5YWjguYNv6S8/II+/iw== + dependencies: + "@chain-registry/types" "0.13.1" + "@cosmos-kit/core" "^2.2.1" + "@terra-money/feather.js" "^1.0.4" + "@terra-money/wallet-types" "^3.11.2" + +"@cosmos-kit/station@2.1.6": + version "2.1.6" + resolved "https://registry.yarnpkg.com/@cosmos-kit/station/-/station-2.1.6.tgz#d2304f35f287edca3ebda98ccf28d7cfdec83e15" + integrity sha512-pfxt4ZfZJ5zyQMqBjLgYjptsH3D4nOATZLlZdwtXKpP5hraBwbuhG1p/gMLMdgwXI7aYAp6ZkBTsoEgr7Sy9WA== + dependencies: + "@cosmos-kit/station-extension" "^2.1.6" + +"@cosmos-kit/walletconnect@^2.1.6": + version "2.1.6" + resolved "https://registry.yarnpkg.com/@cosmos-kit/walletconnect/-/walletconnect-2.1.6.tgz#25de2158d80965550f96b727e2b0a4b1611fa345" + integrity sha512-ljBAES4Po6uSPmpkA7uVFTqG5cqi7PBM8FW/noxONh0DFGdl2XvHb1vyZnkIvA87jJxL2AgDm26jskgvh0zxzw== + dependencies: + "@cosmos-kit/core" "^2.2.1" + "@walletconnect/sign-client" "^2.9.0" + "@walletconnect/types" "^2.9.0" + "@walletconnect/utils" "^2.9.0" events "3.3.0" "@cspotcode/source-map-support@^0.8.0": @@ -3141,9 +2324,9 @@ "@jridgewell/trace-mapping" "0.3.9" "@ctrl/tinycolor@^3.4.0": - version "3.4.1" - resolved "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.4.1.tgz" - integrity sha512-ej5oVy6lykXsvieQtqZxCOaLT+xD4+QNarq78cIYISHmZXshCvROLudpQN3lfL8G0NL7plMSSK+zlyvCaIJ4Iw== + version "3.6.0" + resolved "https://registry.yarnpkg.com/@ctrl/tinycolor/-/tinycolor-3.6.0.tgz#53fa5fe9c34faee89469e48f91d51a3766108bc8" + integrity sha512-/Z3l6pXthq0JvMYdUFyX9j0MaCltlIn6mfh9jLyQwg5aPKxkyNa0PTHtU1AlFXLNk55ZuAeJRcpvq+tmLfKmaQ== "@emotion/babel-plugin@^11.11.0": version "11.11.0" @@ -3173,7 +2356,7 @@ "@emotion/weak-memoize" "^0.3.1" stylis "4.2.0" -"@emotion/hash@^0.9.1": +"@emotion/hash@^0.9.0", "@emotion/hash@^0.9.1": version "0.9.1" resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.9.1.tgz#4ffb0055f7ef676ebc3a5a91fb621393294e2f43" integrity sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ== @@ -3202,7 +2385,7 @@ resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.8.1.tgz#c1ddb040429c6d21d38cc945fe75c818cfb68e17" integrity sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA== -"@emotion/react@^11.10.6", "@emotion/react@^11.8.1": +"@emotion/react@^11", "@emotion/react@^11.8.1": version "11.11.1" resolved "https://registry.yarnpkg.com/@emotion/react/-/react-11.11.1.tgz#b2c36afac95b184f73b08da8c214fdf861fa4157" integrity sha512-5mlW1DquU5HaxjLkfkGN1GA/fvVGdyHURRiX/0FHl2cfIfRxSOfmxEH5YS43edp0OldZrZ+dkBKbngxcNCdZvA== @@ -3232,7 +2415,7 @@ resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-1.2.2.tgz#d58e788ee27267a14342303e1abb3d508b6d0fec" integrity sha512-0QBtGvaqtWi+nx6doRwDdBIzhNdZrXUppvTM4dtZZWEGTXL/XE/yJxLMGlDT1Gt+UHH5IX1n+jkXyytE/av7OA== -"@emotion/styled@^11.10.6": +"@emotion/styled@^11": version "11.11.0" resolved "https://registry.yarnpkg.com/@emotion/styled/-/styled-11.11.0.tgz#26b75e1b5a1b7a629d7c0a8b708fbf5a9cdce346" integrity sha512-hM5Nnvu9P3midq5aaXj4I+lnSfNi7Pmd4EWk1fOZ3pxookaQTNew6bp4JaCBYM4HVFZF9g7UjJmsUmC2JlxOng== @@ -3327,17 +2510,35 @@ "@ethersproject/bytes" "^5.7.0" "@ethersproject/logger" "^5.7.0" -"@floating-ui/core@^1.2.6": - version "1.2.6" - resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.2.6.tgz#d21ace437cc919cdd8f1640302fa8851e65e75c0" - integrity sha512-EvYTiXet5XqweYGClEmpu3BoxmsQ4hkj3QaYA6qEnigCWffTP3vNRwBReTdrwDwo7OoJ3wM8Uoe9Uk4n+d4hfg== +"@fastify/deepmerge@^1.3.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@fastify/deepmerge/-/deepmerge-1.3.0.tgz#8116858108f0c7d9fd460d05a7d637a13fe3239a" + integrity sha512-J8TOSBq3SoZbDhM9+R/u77hP93gz/rajSA+K2kGyijPpORPWUXHUpTaleoj+92As0S9uPRP7Oi8IqMf0u+ro6A== + +"@floating-ui/core@^1.4.1": + version "1.4.1" + resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.4.1.tgz#0d633f4b76052668afb932492ac452f7ebe97f17" + integrity sha512-jk3WqquEJRlcyu7997NtR5PibI+y5bi+LS3hPmguVClypenMsCY3CBa3LAQnozRCtCrYWSEtAdiskpamuJRFOQ== + dependencies: + "@floating-ui/utils" "^0.1.1" "@floating-ui/dom@^1.0.1": - version "1.2.9" - resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-1.2.9.tgz#b9ed1c15d30963419a6736f1b7feb350dd49c603" - integrity sha512-sosQxsqgxMNkV3C+3UqTS6LxP7isRLwX8WMepp843Rb3/b0Wz8+MdUkxJksByip3C2WwLugLHN1b4ibn//zKwQ== + version "1.5.1" + resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-1.5.1.tgz#88b70defd002fe851f17b4a25efb2d3c04d7a8d7" + integrity sha512-KwvVcPSXg6mQygvA1TjbN/gh///36kKtllIF8SUm0qpFj8+rvYrpvlYdL1JoA71SHpDqgSSdGOSoQ0Mp3uY5aw== dependencies: - "@floating-ui/core" "^1.2.6" + "@floating-ui/core" "^1.4.1" + "@floating-ui/utils" "^0.1.1" + +"@floating-ui/utils@^0.1.1": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.1.1.tgz#1a5b1959a528e374e8037c4396c3e825d6cf4a83" + integrity sha512-m0G6wlnhm/AX0H12IOWtK8gASEMffnX08RtKkCgTdHb9JpHKGloI7icFfLg9ZmQeavcvR0PKmzxClyuFPSjKWw== + +"@formkit/auto-animate@1.0.0-beta.6": + version "1.0.0-beta.6" + resolved "https://registry.yarnpkg.com/@formkit/auto-animate/-/auto-animate-1.0.0-beta.6.tgz#ed7f8bc47d774a7764756646e9e3432e8be51cb3" + integrity sha512-PVDhLAlr+B4Xb7e+1wozBUWmXa6BFU8xUPR/W/E+TsQhPS1qkAdAsJ25keEnFrcePSnXHrOsh3tiFbEToOzV9w== "@graphql-codegen/add@^3.2.1": version "3.2.1" @@ -3837,6 +3038,38 @@ resolved "https://registry.npmjs.org/@iarna/toml/-/toml-2.2.5.tgz" integrity sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg== +"@improbable-eng/grpc-web@^0.14.1": + version "0.14.1" + resolved "https://registry.yarnpkg.com/@improbable-eng/grpc-web/-/grpc-web-0.14.1.tgz#f4662f64dc89c0f956a94bb8a3b576556c74589c" + integrity sha512-XaIYuunepPxoiGVLLHmlnVminUGzBTnXr8Wv7khzmLWbNw4TCwJKX09GSMJlKhu/TRk6gms0ySFxewaETSBqgw== + dependencies: + browser-headers "^0.4.1" + +"@interchain-ui/react@1.3.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@interchain-ui/react/-/react-1.3.0.tgz#57e98420c37585055880c1ab56cadb2a59e473db" + integrity sha512-17Forqigz0o0vUsg9b+oJoYiYTr5FLwCcj5VNivOBH4+Icg/IzAl7nR5UeCkcpXbd6QHdFPBZtijLKLmfj1O1Q== + dependencies: + "@fastify/deepmerge" "^1.3.0" + "@formkit/auto-animate" "1.0.0-beta.6" + "@types/react-transition-group" "4.4.5" + "@vanilla-extract/css" "^1.12.0" + "@vanilla-extract/css-utils" "^0.1.3" + "@vanilla-extract/dynamic" "^2.0.3" + "@vanilla-extract/recipes" "^0.4.0" + "@zag-js/dialog" "^0.9.2" + "@zag-js/react" "^0.9.2" + animejs "^3.2.1" + bignumber.js "^9.1.1" + clsx "^1.2.1" + copy-to-clipboard "^3.3.3" + immer "^9.0.19" + lodash "^4.17.21" + motion "^10.16.2" + polished "^4.2.2" + rainbow-sprinkles "^0.17.0" + zustand "^4.3.8" + "@iov/crypto@2.1.0": version "2.1.0" resolved "https://registry.yarnpkg.com/@iov/crypto/-/crypto-2.1.0.tgz#10e91b6692e154958c11626dfd096a80e8a481a4" @@ -4283,59 +3516,75 @@ big-integer "^1.6.48" utility-types "^3.10.0" -"@motionone/animation@^10.13.1": - version "10.14.0" - resolved "https://registry.npmjs.org/@motionone/animation/-/animation-10.14.0.tgz" - integrity sha512-h+1sdyBP8vbxEBW5gPFDnj+m2DCqdlAuf2g6Iafb1lcMnqjsRXWlPw1AXgvUMXmreyhqmPbJqoNfIKdytampRQ== +"@motionone/animation@^10.15.1": + version "10.15.1" + resolved "https://registry.yarnpkg.com/@motionone/animation/-/animation-10.15.1.tgz#4a85596c31cbc5100ae8eb8b34c459fb0ccf6807" + integrity sha512-mZcJxLjHor+bhcPuIFErMDNyrdb2vJur8lSfMCsuCB4UyV8ILZLvK+t+pg56erv8ud9xQGK/1OGPt10agPrCyQ== dependencies: - "@motionone/easing" "^10.14.0" - "@motionone/types" "^10.14.0" - "@motionone/utils" "^10.14.0" + "@motionone/easing" "^10.15.1" + "@motionone/types" "^10.15.1" + "@motionone/utils" "^10.15.1" tslib "^2.3.1" -"@motionone/dom@10.13.1": - version "10.13.1" - resolved "https://registry.npmjs.org/@motionone/dom/-/dom-10.13.1.tgz" - integrity sha512-zjfX+AGMIt/fIqd/SL1Lj93S6AiJsEA3oc5M9VkUr+Gz+juRmYN1vfvZd6MvEkSqEjwPQgcjN7rGZHrDB9APfQ== +"@motionone/dom@^10.15.3", "@motionone/dom@^10.16.2": + version "10.16.2" + resolved "https://registry.yarnpkg.com/@motionone/dom/-/dom-10.16.2.tgz#0c44df8ee3d1cfc50ee11d27050b27824355a61a" + integrity sha512-bnuHdNbge1FutZXv+k7xub9oPWcF0hsu8y1HTH/qg6av58YI0VufZ3ngfC7p2xhMJMnoh0LXFma2EGTgPeCkeg== dependencies: - "@motionone/animation" "^10.13.1" - "@motionone/generators" "^10.13.1" - "@motionone/types" "^10.13.0" - "@motionone/utils" "^10.13.1" + "@motionone/animation" "^10.15.1" + "@motionone/generators" "^10.15.1" + "@motionone/types" "^10.15.1" + "@motionone/utils" "^10.15.1" hey-listen "^1.0.8" tslib "^2.3.1" -"@motionone/easing@^10.14.0": - version "10.14.0" - resolved "https://registry.npmjs.org/@motionone/easing/-/easing-10.14.0.tgz" - integrity sha512-2vUBdH9uWTlRbuErhcsMmt1jvMTTqvGmn9fHq8FleFDXBlHFs5jZzHJT9iw+4kR1h6a4SZQuCf72b9ji92qNYA== +"@motionone/easing@^10.15.1": + version "10.15.1" + resolved "https://registry.yarnpkg.com/@motionone/easing/-/easing-10.15.1.tgz#95cf3adaef34da6deebb83940d8143ede3deb693" + integrity sha512-6hIHBSV+ZVehf9dcKZLT7p5PEKHGhDwky2k8RKkmOvUoYP3S+dXsKupyZpqx5apjd9f+php4vXk4LuS+ADsrWw== + dependencies: + "@motionone/utils" "^10.15.1" + tslib "^2.3.1" + +"@motionone/generators@^10.15.1": + version "10.15.1" + resolved "https://registry.yarnpkg.com/@motionone/generators/-/generators-10.15.1.tgz#dc6abb11139d1bafe758a41c134d4c753a9b871c" + integrity sha512-67HLsvHJbw6cIbLA/o+gsm7h+6D4Sn7AUrB/GPxvujse1cGZ38F5H7DzoH7PhX+sjvtDnt2IhFYF2Zp1QTMKWQ== dependencies: - "@motionone/utils" "^10.14.0" + "@motionone/types" "^10.15.1" + "@motionone/utils" "^10.15.1" tslib "^2.3.1" -"@motionone/generators@^10.13.1": - version "10.14.0" - resolved "https://registry.npmjs.org/@motionone/generators/-/generators-10.14.0.tgz" - integrity sha512-6kRHezoFfIjFN7pPpaxmkdZXD36tQNcyJe3nwVqwJ+ZfC0e3rFmszR8kp9DEVFs9QL/akWjuGPSLBI1tvz+Vjg== +"@motionone/svelte@^10.16.2": + version "10.16.2" + resolved "https://registry.yarnpkg.com/@motionone/svelte/-/svelte-10.16.2.tgz#0b37c3b12927814d31d24941d1ca0ff49981b444" + integrity sha512-38xsroKrfK+aHYhuQlE6eFcGy0EwrB43Q7RGjF73j/kRUTcLNu/LAaKiLLsN5lyqVzCgTBVt4TMT/ShWbTbc5Q== dependencies: - "@motionone/types" "^10.14.0" - "@motionone/utils" "^10.14.0" + "@motionone/dom" "^10.16.2" tslib "^2.3.1" -"@motionone/types@^10.13.0", "@motionone/types@^10.14.0": - version "10.14.0" - resolved "https://registry.npmjs.org/@motionone/types/-/types-10.14.0.tgz" - integrity sha512-3bNWyYBHtVd27KncnJLhksMFQ5o2MSdk1cA/IZqsHtA9DnRM1SYgN01CTcJ8Iw8pCXF5Ocp34tyAjY7WRpOJJQ== +"@motionone/types@^10.15.1": + version "10.15.1" + resolved "https://registry.yarnpkg.com/@motionone/types/-/types-10.15.1.tgz#89441b54285012795cbba8612cbaa0fa420db3eb" + integrity sha512-iIUd/EgUsRZGrvW0jqdst8st7zKTzS9EsKkP+6c6n4MPZoQHwiHuVtTQLD6Kp0bsBLhNzKIBlHXponn/SDT4hA== -"@motionone/utils@^10.13.1", "@motionone/utils@^10.14.0": - version "10.14.0" - resolved "https://registry.npmjs.org/@motionone/utils/-/utils-10.14.0.tgz" - integrity sha512-sLWBLPzRqkxmOTRzSaD3LFQXCPHvDzyHJ1a3VP9PRzBxyVd2pv51/gMOsdAcxQ9n+MIeGJnxzXBYplUHKj4jkw== +"@motionone/utils@^10.15.1": + version "10.15.1" + resolved "https://registry.yarnpkg.com/@motionone/utils/-/utils-10.15.1.tgz#6b5f51bde75be88b5411e084310299050368a438" + integrity sha512-p0YncgU+iklvYr/Dq4NobTRdAPv9PveRDUXabPEeOjBLSO/1FNB2phNTZxOxpi1/GZwYpAoECEa0Wam+nsmhSw== dependencies: - "@motionone/types" "^10.14.0" + "@motionone/types" "^10.15.1" hey-listen "^1.0.8" tslib "^2.3.1" +"@motionone/vue@^10.16.2": + version "10.16.2" + resolved "https://registry.yarnpkg.com/@motionone/vue/-/vue-10.16.2.tgz#faf13afc27620a2df870c71c58a04ee8de8dea65" + integrity sha512-7/dEK/nWQXOkJ70bqb2KyNfSWbNvWqKKq1C8juj+0Mg/AorgD8O5wE3naddK0G+aXuNMqRuc4jlsYHHWHtIzVw== + dependencies: + "@motionone/dom" "^10.16.2" + tslib "^2.3.1" + "@next/env@13.0.0": version "13.0.0" resolved "https://registry.npmjs.org/@next/env/-/env-13.0.0.tgz" @@ -4472,9 +3721,9 @@ webcrypto-core "^1.7.4" "@popperjs/core@^2.9.3": - version "2.11.5" - resolved "https://registry.npmjs.org/@popperjs/core/-/core-2.11.5.tgz" - integrity sha512-9X2obfABZuDVLCgPK9aX0a/x4jaOEweTTWE2+9sr0Qqqevj2Uv5XorvusThmc9XGYpS9yI+fhh8RTafBtGposw== + version "2.11.8" + resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.11.8.tgz#6b79032e760a0899cd4204710beede972a3a185f" + integrity sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A== "@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2": version "1.1.2" @@ -4529,6 +3778,11 @@ resolved "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz" integrity sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw== +"@react-icons/all-files@^4.1.0": + version "4.1.0" + resolved "https://registry.yarnpkg.com/@react-icons/all-files/-/all-files-4.1.0.tgz#477284873a0821928224b6fc84c62d2534d6650b" + integrity sha512-hxBI2UOuVaI3O/BhQfhtb4kcGn9ft12RWAFVMUeNjqqhLsHvFtzIkFaptBJpFDANTKoDfdVoHTKZDlwKCACbMQ== + "@repeaterjs/repeater@3.0.4": version "3.0.4" resolved "https://registry.npmjs.org/@repeaterjs/repeater/-/repeater-3.0.4.tgz" @@ -4904,6 +4158,51 @@ "@tanstack/query-core" "4.15.1" use-sync-external-store "^1.2.0" +"@terra-money/feather.js@^1.0.4": + version "1.0.10" + resolved "https://registry.yarnpkg.com/@terra-money/feather.js/-/feather.js-1.0.10.tgz#595853bc39144d89bcbfdc15022958621b9b352c" + integrity sha512-kC9EqoB/663JG21EHE5XOvQ9fs3rn/ePl0qlVb9F9aZpp4IBsDsvUYm7bLHbRgdfZz167/6y6HovHYmK3MzRSw== + dependencies: + "@terra-money/legacy.proto" "npm:@terra-money/terra.proto@^0.1.7" + "@terra-money/terra.proto" "3.0.5" + axios "^0.27.2" + bech32 "^2.0.0" + bip32 "^2.0.6" + bip39 "^3.0.3" + bufferutil "^4.0.3" + decimal.js "^10.2.1" + jscrypto "^1.0.1" + long "^5.2.3" + readable-stream "^3.6.0" + secp256k1 "^4.0.2" + tmp "^0.2.1" + utf-8-validate "^5.0.5" + ws "^7.5.9" + +"@terra-money/legacy.proto@npm:@terra-money/terra.proto@^0.1.7": + version "0.1.7" + resolved "https://registry.yarnpkg.com/@terra-money/terra.proto/-/terra.proto-0.1.7.tgz#59c18f30da10d43200bab3ba8feb5b17e43a365f" + integrity sha512-NXD7f6pQCulvo6+mv6MAPzhOkUzRjgYVuHZE/apih+lVnPG5hDBU0rRYnOGGofwvKT5/jQoOENnFn/gioWWnyQ== + dependencies: + google-protobuf "^3.17.3" + long "^4.0.0" + protobufjs "~6.11.2" + +"@terra-money/terra.proto@3.0.5": + version "3.0.5" + resolved "https://registry.yarnpkg.com/@terra-money/terra.proto/-/terra.proto-3.0.5.tgz#96f17410a044459412491959b615c52faa2eb338" + integrity sha512-8tvT41qte2mpiNoHq2dMmV7soMxwf4ckuJ+F2pMrb7iVcqaBo30/dIfyTdFm5mEH5i5P6cTJggm+UlIZBSPhwQ== + dependencies: + "@improbable-eng/grpc-web" "^0.14.1" + google-protobuf "^3.17.3" + long "^4.0.0" + protobufjs "~6.11.2" + +"@terra-money/wallet-types@^3.11.2": + version "3.11.2" + resolved "https://registry.yarnpkg.com/@terra-money/wallet-types/-/wallet-types-3.11.2.tgz#5be7016abcd249b4839b1aadb837a6aa043dfaf2" + integrity sha512-vIHCqL4gtiAlvhnxDSnh6bTXIIZGNOIEfH/lWEgwCHXp4cGh0MeZixcnd4UvpW2ynirwtWkppAz9N4qX9zTtAA== + "@tootallnate/once@2": version "2.0.0" resolved "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz" @@ -5035,22 +4334,15 @@ "@types/lodash.mergewith@4.6.6": version "4.6.6" - resolved "https://registry.npmjs.org/@types/lodash.mergewith/-/lodash.mergewith-4.6.6.tgz" + resolved "https://registry.yarnpkg.com/@types/lodash.mergewith/-/lodash.mergewith-4.6.6.tgz#c4698f5b214a433ff35cb2c75ee6ec7f99d79f10" integrity sha512-RY/8IaVENjG19rxTZu9Nukqh0W2UrYgmBj5sdns4hWRZaV8PqR7wIKHFKzvOTjo4zVRV7sVI+yFhAJql12Kfqg== dependencies: "@types/lodash" "*" -"@types/lodash.mergewith@4.6.7": - version "4.6.7" - resolved "https://registry.yarnpkg.com/@types/lodash.mergewith/-/lodash.mergewith-4.6.7.tgz#eaa65aa5872abdd282f271eae447b115b2757212" - integrity sha512-3m+lkO5CLRRYU0fhGRp7zbsGi6+BZj0uTVSwvcKU+nSlhjA9/QRNfuSGnD2mX6hQA7ZbmcCkzk5h4ZYGOtk14A== - dependencies: - "@types/lodash" "*" - "@types/lodash@*": - version "4.14.182" - resolved "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.182.tgz" - integrity sha512-/THyiqyQAP9AfARo4pF+aCGcyiQ94tX/Is2I7HofNRqoYLgN1PBoOWu2/zTA5zMxzP5EFutMtWtGAFRKUe961Q== + version "4.14.196" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.196.tgz#a7c3d6fc52d8d71328b764e28e080b4169ec7a95" + integrity sha512-22y3o88f4a94mKljsZcanlNWPzO0uBsBdzLAngf2tp533LzZcQzb6+eZPJ+vCTt+bqF2XnvT9gejTLsAcJAJyQ== "@types/long@^4.0.1": version "4.0.2" @@ -5128,6 +4420,13 @@ dependencies: "@types/react" "*" +"@types/react-transition-group@4.4.5": + version "4.4.5" + resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-4.4.5.tgz#aae20dcf773c5aa275d5b9f7cdbca638abc5e416" + integrity sha512-juKD/eiSM3/xZYzjuzH6ZwpP+/lejltmiS3QEzV/vmb/Q8+HfDmxu+Baga8UEMGBqV88Nbg4l2hY/K2DkyaLLA== + dependencies: + "@types/react" "*" + "@types/react-transition-group@^4.4.0": version "4.4.6" resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-4.4.6.tgz#18187bcda5281f8e10dfc48f0943e2fdf4f75e2e" @@ -5258,24 +4557,63 @@ "@typescript-eslint/types" "5.23.0" eslint-visitor-keys "^3.0.0" -"@walletconnect/core@2.8.0": - version "2.8.0" - resolved "https://registry.yarnpkg.com/@walletconnect/core/-/core-2.8.0.tgz#f694e1562413c4eb700f6b3a83fa7964342100c0" - integrity sha512-pl7x4sq1nuU0ixA9wF2ecjDecUzIauKr7ZwC29rs9qTcmDpxgJbbOdZwaSl+dJlf1bHC87adVLf5KAkwwo9PzQ== +"@vanilla-extract/css-utils@^0.1.3": + version "0.1.3" + resolved "https://registry.yarnpkg.com/@vanilla-extract/css-utils/-/css-utils-0.1.3.tgz#cadeb6bc563547b20e9b903647d8b334d3a79ef8" + integrity sha512-PZAcHROlgtCUGI2y0JntdNwvPwCNyeVnkQu6KTYKdmxBbK3w72XJUmLFYapfaFfgami4I9CTLnrJTPdtmS3gpw== + +"@vanilla-extract/css@^1.12.0": + version "1.12.0" + resolved "https://registry.yarnpkg.com/@vanilla-extract/css/-/css-1.12.0.tgz#aa7af9a5afac97d0cbabbc2387ab1a7adc6c8cb2" + integrity sha512-TEttZfnqTRtwgVYiBWQSGGUiVaYWReHp59DsavITEvh4TpJNifZFGhBznHx4wQFEsyio6xA513jps4tmqR6zmw== + dependencies: + "@emotion/hash" "^0.9.0" + "@vanilla-extract/private" "^1.0.3" + ahocorasick "1.0.2" + chalk "^4.1.1" + css-what "^6.1.0" + cssesc "^3.0.0" + csstype "^3.0.7" + deep-object-diff "^1.1.9" + deepmerge "^4.2.2" + media-query-parser "^2.0.2" + outdent "^0.8.0" + +"@vanilla-extract/dynamic@^2.0.3": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@vanilla-extract/dynamic/-/dynamic-2.0.3.tgz#44b4e018cbdfb6af3d27e73c78b38617dfe419ad" + integrity sha512-Rglfw2gXAYiBzAQ4jgUG7rBgE2c88e/zcG27ZVoIqMHVq56wf2C1katGMm1yFMNBgzqM7oBNYzz4YOMzznydkg== + dependencies: + "@vanilla-extract/private" "^1.0.3" + +"@vanilla-extract/private@^1.0.3": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@vanilla-extract/private/-/private-1.0.3.tgz#7ec72bc2ff6fe51f9d650f962e8d1989b073690f" + integrity sha512-17kVyLq3ePTKOkveHxXuIJZtGYs+cSoev7BlP+Lf4916qfDhk/HBjvlYDe8egrea7LNPHKwSZJK/bzZC+Q6AwQ== + +"@vanilla-extract/recipes@^0.4.0": + version "0.4.0" + resolved "https://registry.yarnpkg.com/@vanilla-extract/recipes/-/recipes-0.4.0.tgz#7bb2edb0757b6f40c244d72569da7f74d6afa427" + integrity sha512-gFgB7BofUYbtbxINHK6DhMv1JDFDXp/YI/Xm+cqKar+1I/2dfxPepeDxSexL6YB4ftfeaDw8Kn5zydMvHcGOEQ== + +"@walletconnect/core@2.9.2": + version "2.9.2" + resolved "https://registry.yarnpkg.com/@walletconnect/core/-/core-2.9.2.tgz#c46734ca63771b28fd77606fd521930b7ecfc5e1" + integrity sha512-VARMPAx8sIgodeyngDHbealP3B621PQqjqKsByFUTOep8ZI1/R/20zU+cmq6j9RCrL+kLKZcrZqeVzs8Z7OlqQ== dependencies: "@walletconnect/heartbeat" "1.2.1" "@walletconnect/jsonrpc-provider" "1.0.13" "@walletconnect/jsonrpc-types" "1.0.3" "@walletconnect/jsonrpc-utils" "1.0.8" - "@walletconnect/jsonrpc-ws-connection" "^1.0.11" + "@walletconnect/jsonrpc-ws-connection" "1.0.13" "@walletconnect/keyvaluestorage" "^1.0.2" "@walletconnect/logger" "^2.0.1" "@walletconnect/relay-api" "^1.0.9" "@walletconnect/relay-auth" "^1.0.4" "@walletconnect/safe-json" "^1.0.2" "@walletconnect/time" "^1.0.2" - "@walletconnect/types" "2.8.0" - "@walletconnect/utils" "2.8.0" + "@walletconnect/types" "2.9.2" + "@walletconnect/utils" "2.9.2" events "^3.3.0" lodash.isequal "4.5.0" uint8arrays "^3.1.0" @@ -5330,10 +4668,10 @@ "@walletconnect/jsonrpc-types" "^1.0.3" tslib "1.14.1" -"@walletconnect/jsonrpc-ws-connection@^1.0.11": - version "1.0.11" - resolved "https://registry.yarnpkg.com/@walletconnect/jsonrpc-ws-connection/-/jsonrpc-ws-connection-1.0.11.tgz#1ce59d86f273d576ca73385961303ebd44dd923f" - integrity sha512-TiFJ6saasKXD+PwGkm5ZGSw0837nc6EeFmurSPgIT/NofnOV4Tv7CVJqGQN0rQYoJUSYu21cwHNYaFkzNpUN+w== +"@walletconnect/jsonrpc-ws-connection@1.0.13": + version "1.0.13" + resolved "https://registry.yarnpkg.com/@walletconnect/jsonrpc-ws-connection/-/jsonrpc-ws-connection-1.0.13.tgz#23b0cdd899801bfbb44a6556936ec2b93ef2adf4" + integrity sha512-mfOM7uFH4lGtQxG+XklYuFBj6dwVvseTt5/ahOkkmpcAEgz2umuzu7fTR+h5EmjQBdrmYyEBOWADbeaFNxdySg== dependencies: "@walletconnect/jsonrpc-utils" "^1.0.6" "@walletconnect/safe-json" "^1.0.2" @@ -5384,19 +4722,19 @@ dependencies: tslib "1.14.1" -"@walletconnect/sign-client@^2.7.2": - version "2.8.0" - resolved "https://registry.yarnpkg.com/@walletconnect/sign-client/-/sign-client-2.8.0.tgz#735dc8bf120242584fb2ff22c6a3d672c1fae1a1" - integrity sha512-+l9qwvVeUGk0fBQsgx6yb6hdGYt8uQ3a9jR9GgsJvm8FjFh1oUzTKqFnG7XdhCBnzFnbSoLr41Xe8PbN8qoUSw== +"@walletconnect/sign-client@^2.9.0": + version "2.9.2" + resolved "https://registry.yarnpkg.com/@walletconnect/sign-client/-/sign-client-2.9.2.tgz#ff4c81c082c2078878367d07f24bcb20b1f7ab9e" + integrity sha512-anRwnXKlR08lYllFMEarS01hp1gr6Q9XUgvacr749hoaC/AwGVlxYFdM8+MyYr3ozlA+2i599kjbK/mAebqdXg== dependencies: - "@walletconnect/core" "2.8.0" + "@walletconnect/core" "2.9.2" "@walletconnect/events" "^1.0.1" "@walletconnect/heartbeat" "1.2.1" "@walletconnect/jsonrpc-utils" "1.0.8" "@walletconnect/logger" "^2.0.1" "@walletconnect/time" "^1.0.2" - "@walletconnect/types" "2.8.0" - "@walletconnect/utils" "2.8.0" + "@walletconnect/types" "2.9.2" + "@walletconnect/utils" "2.9.2" events "^3.3.0" "@walletconnect/time@^1.0.2": @@ -5418,10 +4756,10 @@ "@walletconnect/logger" "^2.0.1" events "^3.3.0" -"@walletconnect/types@2.8.0", "@walletconnect/types@^2.7.2": - version "2.8.0" - resolved "https://registry.yarnpkg.com/@walletconnect/types/-/types-2.8.0.tgz#f8a5f09ee2b31abed231966e7e1eebd22be058a2" - integrity sha512-FMeGK3lGXFDwcs5duoN74xL1aLrkgYqnavWE0DnFPt2i1QmSUITU9c8f88EDh8uPXANd2WIYOItm0DVCNxLGGA== +"@walletconnect/types@2.9.2", "@walletconnect/types@^2.9.0": + version "2.9.2" + resolved "https://registry.yarnpkg.com/@walletconnect/types/-/types-2.9.2.tgz#d5fd5a61dc0f41cbdca59d1885b85207ac7bf8c5" + integrity sha512-7Rdn30amnJEEal4hk83cdwHUuxI1SWQ+K7fFFHBMqkuHLGi3tpMY6kpyfDxnUScYEZXqgRps4Jo5qQgnRqVM7A== dependencies: "@walletconnect/events" "^1.0.1" "@walletconnect/heartbeat" "1.2.1" @@ -5430,10 +4768,10 @@ "@walletconnect/logger" "^2.0.1" events "^3.3.0" -"@walletconnect/utils@2.8.0", "@walletconnect/utils@^2.7.2": - version "2.8.0" - resolved "https://registry.yarnpkg.com/@walletconnect/utils/-/utils-2.8.0.tgz#c219e78fd2c35062cf3e37f84961afde8da9b9a1" - integrity sha512-Q8OwMtUevIn1+64LXyTMLlhH58k3UOAjU5b3smYZ7CEEmwEGpOTfTDAWrB3v+ZDIhjyqP94+8fuvKIbcVLKLWA== +"@walletconnect/utils@2.9.2", "@walletconnect/utils@^2.9.0": + version "2.9.2" + resolved "https://registry.yarnpkg.com/@walletconnect/utils/-/utils-2.9.2.tgz#035bdb859ee81a4bcc6420f56114cc5ec3e30afb" + integrity sha512-D44hwXET/8JhhIjqljY6qxSu7xXnlPrf63UN/Qfl98vDjWlYVcDl2+JIQRxD9GPastw0S8XZXdRq59XDXLuZBg== dependencies: "@stablelib/chacha20poly1305" "1.0.1" "@stablelib/hkdf" "1.0.1" @@ -5443,7 +4781,7 @@ "@walletconnect/relay-api" "^1.0.9" "@walletconnect/safe-json" "^1.0.2" "@walletconnect/time" "^1.0.2" - "@walletconnect/types" "2.8.0" + "@walletconnect/types" "2.9.2" "@walletconnect/window-getters" "^1.0.1" "@walletconnect/window-metadata" "^1.0.1" detect-browser "5.3.0" @@ -5508,25 +4846,133 @@ undici "^5.12.0" web-streams-polyfill "^3.2.0" +"@zag-js/anatomy@0.9.2": + version "0.9.2" + resolved "https://registry.yarnpkg.com/@zag-js/anatomy/-/anatomy-0.9.2.tgz#40d0be8491388bb7b8251f3bad64edde2516b8ed" + integrity sha512-DgzZf4oo1/tdnSzUDu75pdxYep8WmgvxZi3h1Qa0hlu0erGvWPV0L7aAkdrau+Z3z4phc0FndieIDZN1oN1bEg== + +"@zag-js/aria-hidden@0.9.2": + version "0.9.2" + resolved "https://registry.yarnpkg.com/@zag-js/aria-hidden/-/aria-hidden-0.9.2.tgz#0480110580851be30e5def79554bd4d1c9bc96fe" + integrity sha512-Md+RCv8yOQ7uALjE8GRV0al3sb007aobFn1g6Vz0OSUD6Owsl4k1hwV1ZBWkSq6+OHhty35HROydqsKANDGc1g== + dependencies: + "@zag-js/dom-query" "0.9.2" + +"@zag-js/core@0.9.2": + version "0.9.2" + resolved "https://registry.yarnpkg.com/@zag-js/core/-/core-0.9.2.tgz#3cdd262248b5b78c757c9c8dd3334743e2f1cee4" + integrity sha512-L8MwOCuKnOdWqjSRlgb8HQYuD29yRmi0PrTip+T42YK4+SiBiROeGcExYH2txIpVCk3Gww8TU5TzOHDvKCACyA== + dependencies: + "@zag-js/store" "0.9.2" + klona "2.0.6" + +"@zag-js/dialog@^0.9.2": + version "0.9.2" + resolved "https://registry.yarnpkg.com/@zag-js/dialog/-/dialog-0.9.2.tgz#705d041cad96be9cb790260a258503fa6900241a" + integrity sha512-F7LrX2W5lSXukzRNnEL9z8E4zoHmqagrfP/o55jlM8+U/CVoLrRzTmPfl9b3ARguidkFIKj1ZgxZkphM9B0xoQ== + dependencies: + "@zag-js/anatomy" "0.9.2" + "@zag-js/aria-hidden" "0.9.2" + "@zag-js/core" "0.9.2" + "@zag-js/dismissable" "0.9.2" + "@zag-js/dom-query" "0.9.2" + "@zag-js/remove-scroll" "0.9.2" + "@zag-js/types" "0.9.2" + "@zag-js/utils" "0.9.2" + focus-trap "7.4.1" + +"@zag-js/dismissable@0.9.2": + version "0.9.2" + resolved "https://registry.yarnpkg.com/@zag-js/dismissable/-/dismissable-0.9.2.tgz#5526c7fec8ca07d4815db36c4a6f2be67f021f3a" + integrity sha512-e654TDrIMedzFawTF6o/o4Pdf5k78asE5nSBKri3FZqbHWmpCacLc+vil5d27nc7Y3BXRuM7AyAaFoyBnZ/IOw== + dependencies: + "@zag-js/dom-event" "0.9.2" + "@zag-js/dom-query" "0.9.2" + "@zag-js/interact-outside" "0.9.2" + "@zag-js/utils" "0.9.2" + +"@zag-js/dom-event@0.9.2": + version "0.9.2" + resolved "https://registry.yarnpkg.com/@zag-js/dom-event/-/dom-event-0.9.2.tgz#50faa8c889612b5afc4ee246416be2608a3cb469" + integrity sha512-2HUoIZw7Ig5bzm3S1f5i7S50LlyakhAD1seHBw6w+VwM7I6AFpbpJZjYAESeeKE+SAIA5q3CpdpL+KfdO5jpRg== + dependencies: + "@zag-js/text-selection" "0.9.2" + "@zag-js/types" "0.9.2" + +"@zag-js/dom-query@0.9.2": + version "0.9.2" + resolved "https://registry.yarnpkg.com/@zag-js/dom-query/-/dom-query-0.9.2.tgz#06f8b6402280992e9790c9dd691a3b1103d54211" + integrity sha512-N4K9sl3Dup+Jb0kaXrrwClwUdXgpgBb4xKYRDfG9HPO8ixX11Px8j4iTU3MdvhEt81sE7SkECdJNoyXaNxFqZA== + "@zag-js/element-size@0.1.0": version "0.1.0" - resolved "https://registry.npmjs.org/@zag-js/element-size/-/element-size-0.1.0.tgz" + resolved "https://registry.yarnpkg.com/@zag-js/element-size/-/element-size-0.1.0.tgz#dfdb3f66a70328d0c3149aae29b8f99c10590c22" integrity sha512-QF8wp0+V8++z+FHXiIw93+zudtubYszOtYbNgK39fg3pi+nCZtuSm4L1jC5QZMatNZ83MfOzyNCfgUubapagJQ== -"@zag-js/element-size@0.3.2": - version "0.3.2" - resolved "https://registry.yarnpkg.com/@zag-js/element-size/-/element-size-0.3.2.tgz#ebb76af2a024230482406db41344598d1a9f54f4" - integrity sha512-bVvvigUGvAuj7PCkE5AbzvTJDTw5f3bg9nQdv+ErhVN8SfPPppLJEmmWdxqsRzrHXgx8ypJt/+Ty0kjtISVDsQ== - "@zag-js/focus-visible@0.1.0": version "0.1.0" - resolved "https://registry.npmjs.org/@zag-js/focus-visible/-/focus-visible-0.1.0.tgz" + resolved "https://registry.yarnpkg.com/@zag-js/focus-visible/-/focus-visible-0.1.0.tgz#9777bbaff8316d0b3a14a9095631e1494f69dbc7" integrity sha512-PeaBcTmdZWcFf7n1aM+oiOdZc+sy14qi0emPIeUuGMTjbP0xLGrZu43kdpHnWSXy7/r4Ubp/vlg50MCV8+9Isg== -"@zag-js/focus-visible@0.2.2": - version "0.2.2" - resolved "https://registry.yarnpkg.com/@zag-js/focus-visible/-/focus-visible-0.2.2.tgz#56233480ca1275d3218fb2e10696a33d1a6b9e64" - integrity sha512-0j2gZq8HiZ51z4zNnSkF1iSkqlwRDvdH+son3wHdoz+7IUdMN/5Exd4TxMJ+gq2Of1DiXReYLL9qqh2PdQ4wgA== +"@zag-js/interact-outside@0.9.2": + version "0.9.2" + resolved "https://registry.yarnpkg.com/@zag-js/interact-outside/-/interact-outside-0.9.2.tgz#7c0d7b25ca6410ec3d4b83a73a78f94e41574cea" + integrity sha512-UYaim/6dgqo5lUyfag5SeWqyGwGHyBgh7MC92eymI86Kb3BYOUhIfXEUaoaacFBxRuJbhmFEsxFF8bN/tWNTJw== + dependencies: + "@zag-js/dom-event" "0.9.2" + "@zag-js/dom-query" "0.9.2" + "@zag-js/tabbable" "0.9.2" + "@zag-js/utils" "0.9.2" + +"@zag-js/react@^0.9.2": + version "0.9.2" + resolved "https://registry.yarnpkg.com/@zag-js/react/-/react-0.9.2.tgz#1908cfbe1bae37a30a8a416ab57b62033efac258" + integrity sha512-7HBRfXQnPghWQwH/SY4MjUfRg8F6JaX/AosUA1mgUAi6WAIMEr8bIwb3iRVdRdjMoya/w3uynESpuimvo/7GFA== + dependencies: + "@zag-js/core" "0.9.2" + "@zag-js/store" "0.9.2" + "@zag-js/types" "0.9.2" + proxy-compare "2.5.1" + +"@zag-js/remove-scroll@0.9.2": + version "0.9.2" + resolved "https://registry.yarnpkg.com/@zag-js/remove-scroll/-/remove-scroll-0.9.2.tgz#228fe925187e68f5dfa44e246a7bea1df2e17697" + integrity sha512-SJti7IWmsXQU58vlMOz6BxzfSVKjLWMf7TJB2S6B/vuxLqrDpVal4+K5kgYqwa2rmbf/NkR+4ocdLyF63YupUg== + dependencies: + "@zag-js/dom-query" "0.9.2" + +"@zag-js/store@0.9.2": + version "0.9.2" + resolved "https://registry.yarnpkg.com/@zag-js/store/-/store-0.9.2.tgz#d60bc825170ada654db1c27df0912d3dab6ff2dd" + integrity sha512-FO6BUK6ri0pZCEWqT8veiaZoTQwnCMqQ+C1pvf+ZtMnGMCjMXe/QvNUx/dcHSrscGckWJDBTJRbLhmDedyDPUA== + dependencies: + proxy-compare "2.5.1" + +"@zag-js/tabbable@0.9.2": + version "0.9.2" + resolved "https://registry.yarnpkg.com/@zag-js/tabbable/-/tabbable-0.9.2.tgz#c45fad9fb487b6ac732b49c3190815142bed1024" + integrity sha512-CekXUcJ7HqK+MIFXazBD7KIrntOIJZc8lscf3aXEkpbYfTmilad1ZORAR5tnsIkYIoDHcLdxhT69CKR87NMNFA== + dependencies: + "@zag-js/dom-query" "0.9.2" + +"@zag-js/text-selection@0.9.2": + version "0.9.2" + resolved "https://registry.yarnpkg.com/@zag-js/text-selection/-/text-selection-0.9.2.tgz#db434bb638a4ae39cc014daaa9df9e77dd202816" + integrity sha512-xaXeLb9U7wZ5kEZ/L/if5INcX2YWi+Yzr8KIH2cNUaRE79cJFf0z1JG4D8VmO40EnCE396DVyNeLFdQXOAsu4Q== + dependencies: + "@zag-js/dom-query" "0.9.2" + +"@zag-js/types@0.9.2": + version "0.9.2" + resolved "https://registry.yarnpkg.com/@zag-js/types/-/types-0.9.2.tgz#53fafb8d2e44cf3122ef9d4f1e5e48f608d4fec0" + integrity sha512-MM8KPTW5nX438fDb57K0DM+nxcLA9+WoFyE9A/fEaCH2kGsaVltmsY1ejolU4duYNOEQVon9T39QlGfgc81f/w== + dependencies: + csstype "3.1.2" + +"@zag-js/utils@0.9.2": + version "0.9.2" + resolved "https://registry.yarnpkg.com/@zag-js/utils/-/utils-0.9.2.tgz#33645f6f81dc7dc0ad006b250fbc5105108df9c5" + integrity sha512-PQZRIhgaowNrON7UF4u1JTABUhlWhMiu4uwN7S7SXcpyq1z8JXb4j5YEHNkH4F7lLMQAwmMdpJXHfjH5bYXR1Q== JSONStream@^1.0.4: version "1.3.5" @@ -5583,6 +5029,11 @@ aggregate-error@^3.0.0: clean-stack "^2.0.0" indent-string "^4.0.0" +ahocorasick@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/ahocorasick/-/ahocorasick-1.0.2.tgz#9eee93aef9d02bfb476d9b648d9b7a40ef2fd500" + integrity sha512-hCOfMzbFx5IDutmWLAt6MZwOUjIfSM9G9FyVxytmE4Rs/5YDPWQrD/+IR1w+FweD9H2oOZEnv36TmkjhNURBVA== + ajv-formats@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-2.1.1.tgz#6e669400659eb74973bbf2e33327180a0996b520" @@ -5620,6 +5071,11 @@ ajv@^8.11.0: require-from-string "^2.0.2" uri-js "^4.2.2" +animejs@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/animejs/-/animejs-3.2.1.tgz#de9fe2e792f44a777a7fdf6ae160e26604b0cdda" + integrity sha512-sWno3ugFryK5nhiDm/2BKeFCpZv7vzerWUcUPyAZLDhMek3+S/p418ldZJbJXo5ZUOpfm2kP2XRO4NJcULMy9A== + ansi-escapes@^4.2.1, ansi-escapes@^4.3.0, ansi-escapes@^4.3.1: version "4.3.2" resolved "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz" @@ -5713,13 +5169,6 @@ argparse@^2.0.1: integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== aria-hidden@^1.1.1: - version "1.1.3" - resolved "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.1.3.tgz" - integrity sha512-RhVWFtKH5BiGMycI72q2RAFMLQi8JP9bLuQXgR5a8Znp7P5KOIADSJeyfI8PCVxLEp067B2HbP5JIiI/PXIZeA== - dependencies: - tslib "^1.0.0" - -aria-hidden@^1.2.2: version "1.2.3" resolved "https://registry.yarnpkg.com/aria-hidden/-/aria-hidden-1.2.3.tgz#14aeb7fb692bbb72d69bebfa47279c1fd725e954" integrity sha512-xcLxITLe2HYa1cnYnwCjkOO1PqUHQpozB8x9AR0OgWN2woOBi5kSDVxKfd0b7sb1hw5qFeJhXm9H1nu3xSfLeQ== @@ -5999,6 +5448,11 @@ bech32@^1.1.3, bech32@^1.1.4: resolved "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz" integrity sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ== +bech32@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/bech32/-/bech32-2.0.0.tgz#078d3686535075c8c79709f054b1b226a133b355" + integrity sha512-LcknSilhIGatDAsY1ak2I8VtGaHNhgMSYVxFrGLXv+xLHytaKZKcaUJJUE7qmBr7h33o5YQwP55pMI0xmkpJwg== + big-integer@^1.6.48: version "1.6.51" resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.51.tgz#0df92a5d9880560d3ff2d5fd20245c889d130686" @@ -6009,6 +5463,11 @@ big.js@^6.2.1: resolved "https://registry.npmjs.org/big.js/-/big.js-6.2.1.tgz" integrity sha512-bCtHMwL9LeDIozFn+oNhhFoq+yQ3BNdnsLSASUxLciOb1vgvpHsIO1dsENiGMgbb4SkP5TrzWzRiLddn8ahVOQ== +bignumber.js@^9.1.1: + version "9.1.1" + resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.1.1.tgz#c4df7dc496bd849d4c9464344c1aa74228b4dac6" + integrity sha512-pHm4LsMJ6lzgNGVfZHjMoO8sdoRhOzOH4MLmY65Jg70bpxCKu5iOHNJyfF6OyvYw7t8Fpf35RuzUyqnQsj8Vig== + binary-extensions@^2.0.0: version "2.2.0" resolved "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz" @@ -6092,6 +5551,11 @@ brorand@^1.1.0: resolved "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz" integrity sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w== +browser-headers@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/browser-headers/-/browser-headers-0.4.1.tgz#4308a7ad3b240f4203dbb45acedb38dc2d65dd02" + integrity sha512-CA9hsySZVo9371qEHjHZtYxV2cFtVj5Wj/ZHi8ooEsrtm4vOnl9Y9HmyYWk9q+05d7K3rdoAE0j3MVEFVvtQtg== + browserslist@^4.20.2, browserslist@^4.21.3: version "4.21.3" resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.21.3.tgz" @@ -6166,6 +5630,13 @@ buffer@~5.4.3: base64-js "^1.0.2" ieee754 "^1.1.4" +bufferutil@^4.0.3: + version "4.0.7" + resolved "https://registry.yarnpkg.com/bufferutil/-/bufferutil-4.0.7.tgz#60c0d19ba2c992dd8273d3f73772ffc894c153ad" + integrity sha512-kukuqc39WOHtdxtw4UScxF/WVnMFVSQVKhtx3AjZJzhd0RGZZldcrfSEbVsWWe6KNH253574cq5F+wpv0G9pJw== + dependencies: + node-gyp-build "^4.3.0" + busboy@^1.6.0: version "1.6.0" resolved "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz" @@ -6237,10 +5708,10 @@ capital-case@^1.0.4: tslib "^2.0.3" upper-case-first "^2.0.2" -chain-registry@^1.14.0, chain-registry@^1.5.0: - version "1.14.0" - resolved "https://registry.yarnpkg.com/chain-registry/-/chain-registry-1.14.0.tgz#874f7c4d416b5122f25d7d8e89e22368074bef1b" - integrity sha512-j5PgLP8coJ4uIUtpd2fXTLa3ass2ahbx35+g6eLquDZpIg/0Sr7SKX7M2/0jnaT7ohHKnRLMJxOnBHaDpuotoQ== +chain-registry@^1.19.0: + version "1.19.0" + resolved "https://registry.yarnpkg.com/chain-registry/-/chain-registry-1.19.0.tgz#6d2d56b56efebee0d15ced8f9bd8329a099ce04d" + integrity sha512-7Ax0cRurfS+I0Oru3Td8NqBY/2YRCv570XM555E5vu3ib3f/k5SELwxsSalTtQj+Furx6quEyKWuOjrNwPpcQg== dependencies: "@babel/runtime" "^7.21.0" "@chain-registry/types" "^0.16.0" @@ -6258,13 +5729,6 @@ chakra-react-select@^3.3.8: "@chakra-ui/system" "^1.2.0" react-select "5.7.0" -chakra-react-select@^4.4.2: - version "4.6.0" - resolved "https://registry.yarnpkg.com/chakra-react-select/-/chakra-react-select-4.6.0.tgz#a1a35ee7c531db47ac9c8bd412fb0a3745e77321" - integrity sha512-Ckcs+ofX5LxCc0oOz4SorDIRqF/afd5tAQOa694JVJiIckYorUmZASEUSSDdXaZltsUAtJE11CUmEZgVVsk9Eg== - dependencies: - react-select "5.7.0" - chakra-react-select@^4.7.0: version "4.7.0" resolved "https://registry.yarnpkg.com/chakra-react-select/-/chakra-react-select-4.7.0.tgz#a0b5206416a858e77e7a4f38345a12bfe8425d7a" @@ -6454,6 +5918,11 @@ clone@^1.0.2: resolved "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz" integrity sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg== +clsx@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.2.1.tgz#0ddc4a20a549b59c93a4116bb26f5294ca17dc12" + integrity sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg== + co@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" @@ -6493,11 +5962,6 @@ color-name@~1.1.4: resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== -color2k@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/color2k/-/color2k-2.0.2.tgz#ac2b4aea11c822a6bcb70c768b5a289f4fffcebb" - integrity sha512-kJhwH5nAwb34tmyuqq/lgjEKzlFXn1U99NlnB6Ws4qVaERcRUYeYP1cBw6BJ4vxaWStAUEef4WMr7WjOCnBt8w== - colorette@^2.0.16, colorette@^2.0.17: version "2.0.19" resolved "https://registry.npmjs.org/colorette/-/colorette-2.0.19.tgz" @@ -6582,14 +6046,9 @@ compute-lcm@^1.1.2: compute-scroll-into-view@1.0.14: version "1.0.14" - resolved "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-1.0.14.tgz" + resolved "https://registry.yarnpkg.com/compute-scroll-into-view/-/compute-scroll-into-view-1.0.14.tgz#80e3ebb25d6aa89f42e533956cb4b16a04cfe759" integrity sha512-mKDjINe3tc6hGelUMNDzuhorIUZ7kS7BwyY0r2wQd2HOH2tRuJykiC06iSEX8y1TuhNzvz4GcJnK16mM2J1NMQ== -compute-scroll-into-view@1.0.20: - version "1.0.20" - resolved "https://registry.yarnpkg.com/compute-scroll-into-view/-/compute-scroll-into-view-1.0.20.tgz#1768b5522d1172754f5d0c9b02de3af6be506a43" - integrity sha512-UCB0ioiyj8CRjtrvaceBLqqhZCVP+1B8+NWQhmdsm0VXOJtobBCf1dBQmebCCo34qZmUwZfIH2MZLqNHazrfjg== - concat-map@0.0.1: version "0.0.1" resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" @@ -6825,12 +6284,12 @@ cookie@^0.4.1: copy-to-clipboard@3.3.1: version "3.3.1" - resolved "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.1.tgz" + resolved "https://registry.yarnpkg.com/copy-to-clipboard/-/copy-to-clipboard-3.3.1.tgz#115aa1a9998ffab6196f93076ad6da3b913662ae" integrity sha512-i13qo6kIHTTpCm8/Wup+0b1mVWETvu2kIMzKoK8FpkLkFxlt0znUAHcMzox+T8sPlqtZXq3CulEjQHsYiGFJUw== dependencies: toggle-selection "^1.0.6" -copy-to-clipboard@3.3.3: +copy-to-clipboard@^3.3.3: version "3.3.3" resolved "https://registry.yarnpkg.com/copy-to-clipboard/-/copy-to-clipboard-3.3.3.tgz#55ac43a1db8ae639a4bd99511c148cdd1b83a1b0" integrity sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA== @@ -6946,7 +6405,7 @@ crypto-js@^4.0.0: css-box-model@1.2.1: version "1.2.1" - resolved "https://registry.npmjs.org/css-box-model/-/css-box-model-1.2.1.tgz" + resolved "https://registry.yarnpkg.com/css-box-model/-/css-box-model-1.2.1.tgz#59951d3b81fd6b2074a62d49444415b0d2b4d7c1" integrity sha512-a7Vr4Q/kd/aw96bnJG332W9V9LkJO69JRcaCYDUqjp6/z0w6VcZjgAcTbgFxEPfBgdnAwlh3iwu+hLopa+flJw== dependencies: tiny-invariant "^1.0.6" @@ -6956,11 +6415,26 @@ css-mediaquery@^0.1.2: resolved "https://registry.npmjs.org/css-mediaquery/-/css-mediaquery-0.1.2.tgz" integrity sha512-COtn4EROW5dBGlE/4PiKnh6rZpAPxDeFLaEEwt4i10jpDMFt2EhQGS79QmmrO+iKCHv0PU/HrOWEhijFd1x99Q== +css-what@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/css-what/-/css-what-6.1.0.tgz#fb5effcf76f1ddea2c81bdfaa4de44e79bac70f4" + integrity sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw== + +cssesc@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" + integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== + csstype@3.0.9: version "3.0.9" resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.9.tgz#6410af31b26bd0520933d02cbc64fce9ce3fbf0b" integrity sha512-rpw6JPxK6Rfg1zLOYCSwle2GFOOsnjmDYDaBwEcwoOg4qlsIVCN789VkBZDJAGi4T07gI4YSutR43t9Zz4Lzuw== +csstype@3.1.2, csstype@^3.0.7: + version "3.1.2" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.2.tgz#1d4bf9d572f11c14031f0436e1c10bc1f571f50b" + integrity sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ== + csstype@^3.0.11, csstype@^3.0.2: version "3.0.11" resolved "https://registry.npmjs.org/csstype/-/csstype-3.0.11.tgz" @@ -7049,6 +6523,11 @@ decamelize@^1.1.0, decamelize@^1.2.0: resolved "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz" integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= +decimal.js@^10.2.1: + version "10.4.3" + resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.4.3.tgz#1044092884d245d1b7f65725fa4ad4c6f781cc23" + integrity sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA== + decode-uri-component@^0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.2.tgz#e69dbe25d37941171dd540e024c444cd5188e1e9" @@ -7064,6 +6543,11 @@ deep-is@^0.1.3: resolved "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz" integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== +deep-object-diff@^1.1.9: + version "1.1.9" + resolved "https://registry.yarnpkg.com/deep-object-diff/-/deep-object-diff-1.1.9.tgz#6df7ef035ad6a0caa44479c536ed7b02570f4595" + integrity sha512-Rn+RuwkmkDwCi2/oXOFS9Gsr5lJZu/yTGpK7wAaAIE75CC+LCGEZHpY6VQJa/RoJcrmaA/docWJZvYohlNkWPA== + deepmerge@^4.2.2: version "4.3.1" resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a" @@ -7126,7 +6610,7 @@ detect-newline@^3.0.0, detect-newline@^3.1.0: detect-node-es@^1.1.0: version "1.1.0" - resolved "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz" + resolved "https://registry.yarnpkg.com/detect-node-es/-/detect-node-es-1.1.0.tgz#163acdf643330caa0b4cd7c21e7ee7755d6fa493" integrity sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ== diff-match-patch@^1.0.5: @@ -7732,13 +7216,6 @@ fast-diff@^1.1.2: resolved "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz" integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== -fast-fuzzy@^1.12.0: - version "1.12.0" - resolved "https://registry.yarnpkg.com/fast-fuzzy/-/fast-fuzzy-1.12.0.tgz#f900a8165bffbb7dd5c013a1bb96ee22179ba406" - integrity sha512-sXxGgHS+ubYpsdLnvOvJ9w5GYYZrtL9mkosG3nfuD446ahvoWEsSKBP7ieGmWIKVLnaxRDgUJkZMdxRgA2Ni+Q== - dependencies: - graphemesplit "^2.4.1" - fast-glob@^3.2.9: version "3.2.11" resolved "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz" @@ -7901,13 +7378,6 @@ flatted@^3.1.0: resolved "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz" integrity sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg== -focus-lock@^0.11.2: - version "0.11.2" - resolved "https://registry.npmjs.org/focus-lock/-/focus-lock-0.11.2.tgz" - integrity sha512-pZ2bO++NWLHhiKkgP1bEXHhR1/OjVcSvlCJ98aNJDFeb7H5OOQaO+SKOZle6041O9rv2tmbrO4JzClAvDUHf0g== - dependencies: - tslib "^2.0.3" - focus-lock@^0.11.6: version "0.11.6" resolved "https://registry.yarnpkg.com/focus-lock/-/focus-lock-0.11.6.tgz#e8821e21d218f03e100f7dc27b733f9c4f61e683" @@ -7915,6 +7385,13 @@ focus-lock@^0.11.6: dependencies: tslib "^2.0.3" +focus-trap@7.4.1: + version "7.4.1" + resolved "https://registry.yarnpkg.com/focus-trap/-/focus-trap-7.4.1.tgz#321cd8313c75f6c22ed3c472e04b913e5ee2eb5a" + integrity sha512-rnXP5ERIjlo1gEZp7hQb4ekYqUxRuSDQeyWvxhahH3/GkWtd8h8g1C8Eu/KGpuvbUWNVeogK0kuzzrM4u2Z9jA== + dependencies: + tabbable "^6.1.2" + follow-redirects@^1.10.0, follow-redirects@^1.14.0, follow-redirects@^1.14.9, follow-redirects@^1.15.0: version "1.15.2" resolved "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz" @@ -7952,42 +7429,23 @@ formdata-node@^4.3.1: web-streams-polyfill "4.0.0-beta.3" framer-motion@^7.6.12: - version "7.6.12" - resolved "https://registry.npmjs.org/framer-motion/-/framer-motion-7.6.12.tgz" - integrity sha512-Xm1jPB91v6vIr9b+V3q6c96sPzU1jWdvN+Mv4CvIAY23ZIezGNIWxWNGIWj1We0CZ8SSOQkttz8921M10TQjXg== + version "7.10.3" + resolved "https://registry.yarnpkg.com/framer-motion/-/framer-motion-7.10.3.tgz#8b23f50bbc1ee8c830c869c5398e457d5272feb5" + integrity sha512-k2ccYeZNSpPg//HTaqrU+4pRq9f9ZpaaN7rr0+Rx5zA4wZLbk547wtDzge2db1sB+1mnJ6r59P4xb+aEIi/W+w== dependencies: - "@motionone/dom" "10.13.1" - framesync "6.1.2" + "@motionone/dom" "^10.15.3" hey-listen "^1.0.8" - popmotion "11.0.5" - style-value-types "5.1.2" tslib "2.4.0" optionalDependencies: "@emotion/is-prop-valid" "^0.8.2" -framer-motion@^9.0.7: - version "9.1.7" - resolved "https://registry.yarnpkg.com/framer-motion/-/framer-motion-9.1.7.tgz#1dc7dbd5bca086c90d09847c3fcaec3ecb7906af" - integrity sha512-nKxBkIO4IPkMEqcBbbATxsVjwPYShKl051yhBv9628iAH6JLeHD0siBHxkL62oQzMC1+GNX73XtPjgP753ufuw== - dependencies: - tslib "^2.4.0" - optionalDependencies: - "@emotion/is-prop-valid" "^0.8.2" - framesync@5.3.0: version "5.3.0" - resolved "https://registry.npmjs.org/framesync/-/framesync-5.3.0.tgz" + resolved "https://registry.yarnpkg.com/framesync/-/framesync-5.3.0.tgz#0ecfc955e8f5a6ddc8fdb0cc024070947e1a0d9b" integrity sha512-oc5m68HDO/tuK2blj7ZcdEBRx3p1PjrgHazL8GYEpvULhrtGIFbQArN6cQS2QhW8mitffaB+VYzMjDqBxxQeoA== dependencies: tslib "^2.1.0" -framesync@6.1.2: - version "6.1.2" - resolved "https://registry.npmjs.org/framesync/-/framesync-6.1.2.tgz" - integrity sha512-jBTqhX6KaQVDyus8muwZbBeGGP0XgujBRbQ7gM7BRdS3CadCZIHiawyzYLnafYcvZIh5j8WE7cxZKFn7dXhu9g== - dependencies: - tslib "2.4.0" - fs-extra@9.1.0: version "9.1.0" resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz" @@ -8077,7 +7535,7 @@ get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1: get-nonce@^1.0.0: version "1.0.1" - resolved "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz" + resolved "https://registry.yarnpkg.com/get-nonce/-/get-nonce-1.0.1.tgz#fdf3f0278073820d2ce9426c18f07481b1e0cdf3" integrity sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q== get-package-type@^0.1.0: @@ -8249,6 +7707,11 @@ globby@^11.0.3, globby@^11.0.4, globby@^11.1.0: merge2 "^1.4.1" slash "^3.0.0" +google-protobuf@^3.17.3: + version "3.21.2" + resolved "https://registry.yarnpkg.com/google-protobuf/-/google-protobuf-3.21.2.tgz#4580a2bea8bbb291ee579d1fefb14d6fa3070ea4" + integrity sha512-3MSOYFO5U9mPGikIYCzK0SaThypfGgS6bHqrUGXG3DPHCrb+txNqeEcns1W0lkGfk0rCyNXm7xB9rMxnCiZOoA== + graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0: version "4.2.10" resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz" @@ -8264,14 +7727,6 @@ grapheme-splitter@^1.0.4: resolved "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz" integrity sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ== -graphemesplit@^2.4.1: - version "2.4.4" - resolved "https://registry.yarnpkg.com/graphemesplit/-/graphemesplit-2.4.4.tgz#6d325c61e928efdaec2189f54a9b87babf89b75a" - integrity sha512-lKrpp1mk1NH26USxC/Asw4OHbhSQf5XfrWZ+CDv/dFVvd1j17kFgMotdJvOesmHkbFX9P9sBfpH8VogxOWLg8w== - dependencies: - js-base64 "^3.6.0" - unicode-trie "^2.0.0" - graphql-config@4.3.6: version "4.3.6" resolved "https://registry.npmjs.org/graphql-config/-/graphql-config-4.3.6.tgz" @@ -8510,6 +7965,11 @@ immediate@~3.0.5: resolved "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz" integrity sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ== +immer@^9.0.19: + version "9.0.21" + resolved "https://registry.yarnpkg.com/immer/-/immer-9.0.21.tgz#1e025ea31a40f24fb064f1fef23e931496330176" + integrity sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA== + immutable@~3.7.6: version "3.7.6" resolved "https://registry.npmjs.org/immutable/-/immutable-3.7.6.tgz" @@ -8651,10 +8111,10 @@ is-callable@^1.1.4, is-callable@^1.2.4: resolved "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz" integrity sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w== -is-core-module@^2.11.0: - version "2.12.1" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.12.1.tgz#0c0b6885b6f80011c71541ce15c8d66cf5a4f9fd" - integrity sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg== +is-core-module@^2.13.0: + version "2.13.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.0.tgz#bb52aa6e2cbd49a30c2ba68c42bf3435ba6072db" + integrity sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ== dependencies: has "^1.0.3" @@ -9272,11 +8732,6 @@ jest@^29.5.0: import-local "^3.0.2" jest-cli "^29.5.0" -js-base64@^3.6.0: - version "3.7.5" - resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-3.7.5.tgz#21e24cf6b886f76d6f5f165bfcd69cc55b9e3fca" - integrity sha512-3MEt5DTINKqfScXKfJFrRbxkrnk2AxPWGBL/ycjz4dK8iqiSJ06UxD8jh8xuh6p10TX4t2+7FsBYVxxQbMg+qA== - js-base64@^3.7.4: version "3.7.4" resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-3.7.4.tgz#af95b20f23efc8034afd2d1cc5b9d0adf7419037" @@ -9358,6 +8813,11 @@ js-yaml@^4.0.0, js-yaml@^4.1.0: dependencies: argparse "^2.0.1" +jscrypto@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/jscrypto/-/jscrypto-1.0.3.tgz#598febca2a939d6f679c54f56e1fe364cef30cc9" + integrity sha512-lryZl0flhodv4SZHOqyb1bx5sKcJxj0VBo0Kzb4QMAg3L021IC9uGpl0RCZa+9KJwlRGSK2C80ITcwbe19OKLQ== + jsesc@^2.5.1: version "2.5.2" resolved "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz" @@ -9521,6 +8981,11 @@ kleur@^3.0.3: resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== +klona@2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/klona/-/klona-2.0.6.tgz#85bffbf819c03b2f53270412420a4555ef882e22" + integrity sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA== + language-subtag-registry@~0.3.2: version "0.3.21" resolved "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.21.tgz" @@ -9775,6 +9240,11 @@ long@^5.2.1: resolved "https://registry.npmjs.org/long/-/long-5.2.1.tgz" integrity sha512-GKSNGeNAtw8IryjjkhZxuKB3JzlcLTwjtiQCHKvqQet81I93kXslhDQruGI/QsddO83mcDToBVy7GqGS/zYf/A== +long@^5.2.3: + version "5.2.3" + resolved "https://registry.yarnpkg.com/long/-/long-5.2.3.tgz#a3ba97f3877cf1d778eccbcb048525ebb77499e1" + integrity sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q== + longest@^2.0.1: version "2.0.1" resolved "https://registry.npmjs.org/longest/-/longest-2.0.1.tgz" @@ -9899,6 +9369,13 @@ md5@~2.2.1: crypt "~0.0.1" is-buffer "~1.1.1" +media-query-parser@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/media-query-parser/-/media-query-parser-2.0.2.tgz#ff79e56cee92615a304a1c2fa4f2bd056c0a1d29" + integrity sha512-1N4qp+jE0pL5Xv4uEcwVUhIkwdUO3S/9gML90nqKA7v7FcOS5vUtatfzok9S9U1EJU8dHWlcv95WLnKmmxZI9w== + dependencies: + "@babel/runtime" "^7.12.5" + memoize-one@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-6.0.0.tgz#b2591b871ed82948aee4727dc6abceeeac8c1045" @@ -10063,6 +9540,18 @@ modify-values@^1.0.0: resolved "https://registry.npmjs.org/modify-values/-/modify-values-1.0.1.tgz" integrity sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw== +motion@^10.16.2: + version "10.16.2" + resolved "https://registry.yarnpkg.com/motion/-/motion-10.16.2.tgz#7dc173c6ad62210a7e9916caeeaf22c51e598d21" + integrity sha512-p+PurYqfUdcJZvtnmAqu5fJgV2kR0uLFQuBKtLeFVTrYEVllI99tiOTSefVNYuip9ELTEkepIIDftNdze76NAQ== + dependencies: + "@motionone/animation" "^10.15.1" + "@motionone/dom" "^10.16.2" + "@motionone/svelte" "^10.16.2" + "@motionone/types" "^10.15.1" + "@motionone/utils" "^10.15.1" + "@motionone/vue" "^10.16.2" + ms@2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" @@ -10155,6 +9644,11 @@ no-case@^3.0.4: lower-case "^2.0.2" tslib "^2.0.3" +node-addon-api@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-2.0.2.tgz#432cfa82962ce494b132e9d72a15b29f71ff5d32" + integrity sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA== + node-domexception@1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz" @@ -10167,6 +9661,11 @@ node-fetch@2.6.7, node-fetch@^2.6.1, node-fetch@^2.6.7: dependencies: whatwg-url "^5.0.0" +node-gyp-build@^4.2.0, node-gyp-build@^4.3.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.6.0.tgz#0c52e4cbf54bbd28b709820ef7b6a3c2d6209055" + integrity sha512-NTZVKn9IylLwUzaKjkas1e4u2DLNcV4rdYagA4PWdPwW87Bi7z+BznyKSRwS/761tV/lzCGXplWsiaMjLqP2zQ== + node-gzip@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/node-gzip/-/node-gzip-1.1.2.tgz#245bd171b31ce7c7f50fc4cd0ca7195534359afb" @@ -10366,6 +9865,11 @@ os-tmpdir@~1.0.2: resolved "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz" integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= +outdent@^0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/outdent/-/outdent-0.8.0.tgz#2ebc3e77bf49912543f1008100ff8e7f44428eb0" + integrity sha512-KiOAIsdpUTcAXuykya5fnVVT+/5uS0Q1mrkRHcF89tpieSmY33O/tmc54CqwA+bfhbtEfZUNLHaPUiB9X3jt1A== + p-limit@3.1.0, p-limit@^3.0.2, p-limit@^3.1.0: version "3.1.0" resolved "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz" @@ -10437,11 +9941,6 @@ pako@1.0.11: resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw== -pako@^0.2.5: - version "0.2.9" - resolved "https://registry.yarnpkg.com/pako/-/pako-0.2.9.tgz#f3f7522f4ef782348da8161bad9ecfd51bf83a75" - integrity sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA== - pako@^2.0.2: version "2.1.0" resolved "https://registry.yarnpkg.com/pako/-/pako-2.1.0.tgz#266cc37f98c7d883545d11335c00fbd4062c9a86" @@ -10654,15 +10153,12 @@ plur@^5.1.0: dependencies: irregular-plurals "^3.3.0" -popmotion@11.0.5: - version "11.0.5" - resolved "https://registry.npmjs.org/popmotion/-/popmotion-11.0.5.tgz" - integrity sha512-la8gPM1WYeFznb/JqF4GiTkRRPZsfaj2+kCxqQgr2MJylMmIKUwBfWW8Wa5fml/8gmtlD5yI01MP1QCZPWmppA== +polished@^4.2.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/polished/-/polished-4.2.2.tgz#2529bb7c3198945373c52e34618c8fe7b1aa84d1" + integrity sha512-Sz2Lkdxz6F2Pgnpi9U5Ng/WdWAUZxmHrNPoVlm3aAemxoy2Qy7LGjQg4uf8qKelDAUW94F4np3iH2YPf2qefcQ== dependencies: - framesync "6.1.2" - hey-listen "^1.0.8" - style-value-types "5.1.2" - tslib "2.4.0" + "@babel/runtime" "^7.17.8" postcss@8.4.14: version "8.4.14" @@ -10757,6 +10253,11 @@ protobufjs@6.11.3, protobufjs@^6.11.2, protobufjs@^6.8.8, protobufjs@~6.11.2, pr "@types/node" ">=13.7.0" long "^4.0.0" +proxy-compare@2.5.1: + version "2.5.1" + resolved "https://registry.yarnpkg.com/proxy-compare/-/proxy-compare-2.5.1.tgz#17818e33d1653fbac8c2ec31406bce8a2966f600" + integrity sha512-oyfc0Tx87Cpwva5ZXezSp5V9vht1c7dZBhvuV/y3ctkgMVUmiAGDVeeB0dKhGSyT0v1ZTEQYpe/RXlBVBNuCLA== + proxy-from-env@^1.1.0: version "1.1.0" resolved "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz" @@ -10789,11 +10290,6 @@ q@^1.5.1: resolved "https://registry.npmjs.org/q/-/q-1.5.1.tgz" integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc= -qrcode.react@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/qrcode.react/-/qrcode.react-3.1.0.tgz#5c91ddc0340f768316fbdb8fff2765134c2aecd8" - integrity sha512-oyF+Urr3oAMUG/OiOuONL3HXM+53wvuH3mtIWQrYmsXoAq0DkvZp2RYUWFSMFtbdOpuS++9v+WAkzNVkMlNW6Q== - query-string@7.1.3: version "7.1.3" resolved "https://registry.yarnpkg.com/query-string/-/query-string-7.1.3.tgz#a1cf90e994abb113a325804a972d98276fe02328" @@ -10826,6 +10322,11 @@ raf@^3.4.1: dependencies: performance-now "^2.1.0" +rainbow-sprinkles@^0.17.0: + version "0.17.0" + resolved "https://registry.yarnpkg.com/rainbow-sprinkles/-/rainbow-sprinkles-0.17.0.tgz#6ee06c6decc767b89bf01fc5fe87ecf859fd4c2f" + integrity sha512-ok3NrylQ0szvJtuBYaB/w09L9zOvvqcSQrvycT2A5XJxQNvwvkeADvTqQWGOQ3b6MkO8UmYccBPt8g8vVvxM9A== + react-ace@^10.1.0: version "10.1.0" resolved "https://registry.npmjs.org/react-ace/-/react-ace-10.1.0.tgz" @@ -10839,7 +10340,7 @@ react-ace@^10.1.0: react-clientside-effect@^1.2.6: version "1.2.6" - resolved "https://registry.npmjs.org/react-clientside-effect/-/react-clientside-effect-1.2.6.tgz" + resolved "https://registry.yarnpkg.com/react-clientside-effect/-/react-clientside-effect-1.2.6.tgz#29f9b14e944a376b03fb650eed2a754dd128ea3a" integrity sha512-XGGGRQAKY+q25Lz9a/4EPqom7WRjz3z9R2k4jhVKA/puQFH/5Nt27vFZYql4m4NVNdUvX8PS3O7r/Zzm7cjUlg== dependencies: "@babel/runtime" "^7.12.13" @@ -10863,30 +10364,13 @@ react-dropzone@^14.2.3: react-fast-compare@3.2.0: version "3.2.0" - resolved "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.0.tgz" + resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-3.2.0.tgz#641a9da81b6a6320f270e89724fb45a0b39e43bb" integrity sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA== -react-fast-compare@3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-3.2.1.tgz#53933d9e14f364281d6cba24bfed7a4afb808b5f" - integrity sha512-xTYf9zFim2pEif/Fw16dBiXpe0hoy5PxcD8+OwBnTtNLfIm3g6WxhKNurY+6OmdH1u6Ta/W/Vl6vjbYP1MFnDg== - react-focus-lock@^2.9.1: - version "2.9.1" - resolved "https://registry.npmjs.org/react-focus-lock/-/react-focus-lock-2.9.1.tgz" - integrity sha512-pSWOQrUmiKLkffPO6BpMXN7SNKXMsuOakl652IBuALAu1esk+IcpJyM+ALcYzPTTFz1rD0R54aB9A4HuP5t1Wg== - dependencies: - "@babel/runtime" "^7.0.0" - focus-lock "^0.11.2" - prop-types "^15.6.2" - react-clientside-effect "^1.2.6" - use-callback-ref "^1.3.0" - use-sidecar "^1.1.2" - -react-focus-lock@^2.9.4: - version "2.9.4" - resolved "https://registry.yarnpkg.com/react-focus-lock/-/react-focus-lock-2.9.4.tgz#4753f6dcd167c39050c9d84f9c63c71b3ff8462e" - integrity sha512-7pEdXyMseqm3kVjhdVH18sovparAzLg5h6WvIx7/Ck3ekjhrrDMEegHSa3swwC8wgfdd7DIdUVRGeiHT9/7Sgg== + version "2.9.5" + resolved "https://registry.yarnpkg.com/react-focus-lock/-/react-focus-lock-2.9.5.tgz#8a82f4f0128cccc27b9e77a4472e8a22f1b52189" + integrity sha512-h6vrdgUbsH2HeD5I7I3Cx1PPrmwGuKYICS+kB9m+32X/9xHRrAbxgvaBpG7BFBN9h3tO+C3qX1QAVESmi4CiIA== dependencies: "@babel/runtime" "^7.0.0" focus-lock "^0.11.6" @@ -10900,16 +10384,6 @@ react-hook-form@^7.39.7: resolved "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.39.7.tgz" integrity sha512-RT0NE1uW1bY3nAuMdzfqHrpv2+sICVFaxBOvNJsCva4if2sxPxcyJy/CSqU56UXqAdRg724CNDhjMYPSHSF3rg== -react-icons@4.4.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/react-icons/-/react-icons-4.4.0.tgz#a13a8a20c254854e1ec9aecef28a95cdf24ef703" - integrity sha512-fSbvHeVYo/B5/L4VhB7sBA1i2tS8MkT0Hb9t2H1AVPkwGfVHLJCqyr2Py9dKMxsyM63Eng1GkdZfbWj+Fmv8Rg== - -react-icons@^4.4.0: - version "4.9.0" - resolved "https://registry.yarnpkg.com/react-icons/-/react-icons-4.9.0.tgz#ba44f436a053393adb1bdcafbc5c158b7b70d2a3" - integrity sha512-ijUnFr//ycebOqujtqtV9PFS7JjhWg0QU6ykURVHuL4cbofvRCf3f6GMn9+fBktEFQOIVZnuAYLZdiyadRQRFg== - react-icons@^4.6.0: version "4.6.0" resolved "https://registry.npmjs.org/react-icons/-/react-icons-4.6.0.tgz" @@ -10933,14 +10407,6 @@ react-linkify@^1.0.0-alpha: linkify-it "^2.0.3" tlds "^1.199.0" -react-remove-scroll-bar@^2.3.3: - version "2.3.3" - resolved "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.3.tgz" - integrity sha512-i9GMNWwpz8XpUpQ6QlevUtFjHGqnPG4Hxs+wlIJntu/xcsZVEpJcIV71K3ZkqNy2q3GfgvkD7y6t/Sv8ofYSbw== - dependencies: - react-style-singleton "^2.2.1" - tslib "^2.0.0" - react-remove-scroll-bar@^2.3.4: version "2.3.4" resolved "https://registry.yarnpkg.com/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.4.tgz#53e272d7a5cb8242990c7f144c44d8bd8ab5afd9" @@ -10950,17 +10416,6 @@ react-remove-scroll-bar@^2.3.4: tslib "^2.0.0" react-remove-scroll@^2.5.4: - version "2.5.4" - resolved "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.5.4.tgz" - integrity sha512-xGVKJJr0SJGQVirVFAUZ2k1QLyO6m+2fy0l8Qawbp5Jgrv3DeLalrfMNBFSlmz5kriGGzsVBtGVnf4pTKIhhWA== - dependencies: - react-remove-scroll-bar "^2.3.3" - react-style-singleton "^2.2.1" - tslib "^2.1.0" - use-callback-ref "^1.3.0" - use-sidecar "^1.1.2" - -react-remove-scroll@^2.5.5: version "2.5.6" resolved "https://registry.yarnpkg.com/react-remove-scroll/-/react-remove-scroll-2.5.6.tgz#7510b8079e9c7eebe00e65a33daaa3aa29a10336" integrity sha512-bO856ad1uDYLefgArk559IzUNeQ6SWH4QnrevIUjH+GczV56giDfl3h0Idptf2oIKxQmd1p9BN25jleKodTALg== @@ -10971,13 +10426,6 @@ react-remove-scroll@^2.5.5: use-callback-ref "^1.3.0" use-sidecar "^1.1.2" -react-resize-detector@^8.0.3: - version "8.1.0" - resolved "https://registry.yarnpkg.com/react-resize-detector/-/react-resize-detector-8.1.0.tgz#1c7817db8bc886e2dbd3fbe3b26ea8e56be0524a" - integrity sha512-S7szxlaIuiy5UqLhLL1KY3aoyGHbZzsTpYal9eYMwCyKqoqoVLCmIgAgNyIM1FhnP2KyBygASJxdhejrzjMb+w== - dependencies: - lodash "^4.17.21" - react-responsive@^9.0.0: version "9.0.0" resolved "https://registry.npmjs.org/react-responsive/-/react-responsive-9.0.0.tgz" @@ -11020,7 +10468,7 @@ react-select@5.7.4, react-select@^5.4.0: react-style-singleton@^2.2.1: version "2.2.1" - resolved "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.1.tgz" + resolved "https://registry.yarnpkg.com/react-style-singleton/-/react-style-singleton-2.2.1.tgz#f99e420492b2d8f34d38308ff660b60d0b1205b4" integrity sha512-ZWj0fHEMyWkHzKYUr2Bs/4zU6XLmq9HsgBURm7g5pAVfyn49DgUiNgY2d4lXRlYSiCif9YBGpQleewkcqddc7g== dependencies: get-nonce "^1.0.0" @@ -11037,7 +10485,7 @@ react-transition-group@^4.3.0: loose-envify "^1.4.0" prop-types "^15.6.2" -react@18.2.0, react@^18.2.0: +react@^18.2.0: version "18.2.0" resolved "https://registry.npmjs.org/react/-/react-18.2.0.tgz" integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ== @@ -11151,6 +10599,11 @@ regenerator-runtime@^0.13.4: resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz" integrity sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA== +regenerator-runtime@^0.14.0: + version "0.14.0" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz#5e19d68eb12d486f797e15a3c6a918f7cec5eb45" + integrity sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA== + regexp.prototype.flags@^1.4.1: version "1.4.3" resolved "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz" @@ -11256,11 +10709,11 @@ resolve@^1.10.0, resolve@^1.20.0, resolve@^1.22.0: supports-preserve-symlinks-flag "^1.0.0" resolve@^1.19.0: - version "1.22.2" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.2.tgz#0ed0943d4e301867955766c9f3e1ae6d01c6845f" - integrity sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g== + version "1.22.4" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.4.tgz#1dc40df46554cdaf8948a486a10f6ba1e2026c34" + integrity sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg== dependencies: - is-core-module "^2.11.0" + is-core-module "^2.13.0" path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" @@ -11290,7 +10743,7 @@ rfdc@^1.3.0: resolved "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz" integrity sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA== -rimraf@^3.0.2: +rimraf@^3.0.0, rimraf@^3.0.2: version "3.0.2" resolved "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz" integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== @@ -11383,6 +10836,15 @@ scuid@^1.1.0: resolved "https://registry.npmjs.org/scuid/-/scuid-1.1.0.tgz" integrity sha512-MuCAyrGZcTLfQoH2XoBlQ8C6bzwN88XT/0slOGz0pn8+gIP85BOAfYa44ZXQUTOwRwPU0QvgU+V+OSajl/59Xg== +secp256k1@^4.0.2: + version "4.0.3" + resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-4.0.3.tgz#c4559ecd1b8d3c1827ed2d1b94190d69ce267303" + integrity sha512-NLZVf+ROMxwtEj3Xa562qgv2BK5e2WNmXPiOdVIPLgs6lyTzMvBq0aWTYMI5XCP9jZMVKOcqZLw/Wc4vDkuxhA== + dependencies: + elliptic "^6.5.4" + node-addon-api "^2.0.0" + node-gyp-build "^4.2.0" + secretjs@0.17.7: version "0.17.7" resolved "https://registry.yarnpkg.com/secretjs/-/secretjs-0.17.7.tgz#a1aef5866a35cf673be9ddd717d20729afd056ac" @@ -11838,14 +11300,6 @@ strip-json-comments@3.1.1, strip-json-comments@^3.1.0, strip-json-comments@^3.1. resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== -style-value-types@5.1.2: - version "5.1.2" - resolved "https://registry.npmjs.org/style-value-types/-/style-value-types-5.1.2.tgz" - integrity sha512-Vs9fNreYF9j6W2VvuDTP7kepALi7sk0xtk2Tu8Yxi9UoajJdEVpNpCov0HsLTqXvNGKX+Uv09pkozVITi1jf3Q== - dependencies: - hey-listen "^1.0.8" - tslib "2.4.0" - styled-jsx@5.1.0: version "5.1.0" resolved "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.0.tgz" @@ -11896,6 +11350,11 @@ symbol-observable@^2.0.3: resolved "https://registry.npmjs.org/symbol-observable/-/symbol-observable-2.0.3.tgz" integrity sha512-sQV7phh2WCYAn81oAkakC5qjq2Ml0g8ozqz03wOGnx9dDlG1de6yrF+0RAzSJD8fPUow3PTSMf2SAbOGxb93BA== +tabbable@^6.1.2: + version "6.2.0" + resolved "https://registry.yarnpkg.com/tabbable/-/tabbable-6.2.0.tgz#732fb62bc0175cfcec257330be187dcfba1f3b97" + integrity sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew== + test-exclude@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" @@ -11942,15 +11401,10 @@ through@2, "through@>=2.2.7 <3", through@^2.3.6, through@^2.3.8: resolved "https://registry.npmjs.org/through/-/through-2.3.8.tgz" integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= -tiny-inflate@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/tiny-inflate/-/tiny-inflate-1.0.3.tgz#122715494913a1805166aaf7c93467933eea26c4" - integrity sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw== - tiny-invariant@^1.0.6: - version "1.2.0" - resolved "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.2.0.tgz" - integrity sha512-1Uhn/aqw5C6RI4KejVeTg6mIS7IqxnLJ8Mv2tV5rTc0qWobay7pDUz6Wi392Cnc8ak1H0F2cjoRzb2/AW4+Fvg== + version "1.3.1" + resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.3.1.tgz#8560808c916ef02ecfd55e66090df23a4b7aa642" + integrity sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw== tiny-secp256k1@^1.1.3: version "1.1.6" @@ -11982,6 +11436,13 @@ tmp@^0.0.33: dependencies: os-tmpdir "~1.0.2" +tmp@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.1.tgz#8457fc3037dcf4719c251367a1af6500ee1ccf14" + integrity sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ== + dependencies: + rimraf "^3.0.0" + tmpl@1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" @@ -12062,7 +11523,7 @@ tsconfig-paths@^3.14.1: minimist "^1.2.6" strip-bom "^3.0.0" -tslib@1.14.1, tslib@^1.0.0, tslib@^1.8.1, tslib@^1.9.3: +tslib@1.14.1, tslib@^1.8.1, tslib@^1.9.3: version "1.14.1" resolved "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== @@ -12190,14 +11651,6 @@ undici@^5.12.0, undici@^5.8.0: dependencies: busboy "^1.6.0" -unicode-trie@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/unicode-trie/-/unicode-trie-2.0.0.tgz#8fd8845696e2e14a8b67d78fa9e0dd2cad62fec8" - integrity sha512-x7bc76x0bm4prf1VLg79uhAzKw8DVboClSN5VxJuQ+LKDOVEW9CdH+VY7SP+vX7xCYQqzzgQpFqz15zeLvAtZQ== - dependencies: - pako "^0.2.5" - tiny-inflate "^1.0.0" - universalify@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz" @@ -12246,7 +11699,7 @@ uri-js@^4.2.2: use-callback-ref@^1.3.0: version "1.3.0" - resolved "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.0.tgz" + resolved "https://registry.yarnpkg.com/use-callback-ref/-/use-callback-ref-1.3.0.tgz#772199899b9c9a50526fedc4993fc7fa1f7e32d5" integrity sha512-3FT9PRuRdbB9HfXhEq35u4oZkvpJ5kuYbpqhCfmiZyReuRgpnhDlbr2ZEnnuS0RrJAPn6l23xjFg9kpDM+Ms7w== dependencies: tslib "^2.0.0" @@ -12265,7 +11718,7 @@ use-isomorphic-layout-effect@^1.1.2: use-sidecar@^1.1.2: version "1.1.2" - resolved "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.2.tgz" + resolved "https://registry.yarnpkg.com/use-sidecar/-/use-sidecar-1.1.2.tgz#2f43126ba2d7d7e117aa5855e5d8f0276dfe73c2" integrity sha512-epTbsLuzZ7lPClpz2TyryBfztm7m+28DlEv2ZCQ3MDr5ssiwyOwGH/e5F9CkfWjJ1t4clvI58yF822/GUkjjhw== dependencies: detect-node-es "^1.1.0" @@ -12276,6 +11729,13 @@ use-sync-external-store@1.2.0, use-sync-external-store@^1.2.0: resolved "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz" integrity sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA== +utf-8-validate@^5.0.5: + version "5.0.10" + resolved "https://registry.yarnpkg.com/utf-8-validate/-/utf-8-validate-5.0.10.tgz#d7d10ea39318171ca982718b6b96a8d2442571a2" + integrity sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ== + dependencies: + node-gyp-build "^4.3.0" + util-deprecate@^1.0.1, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" @@ -12496,7 +11956,7 @@ ws@8.11.0: resolved "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz" integrity sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg== -ws@^7, ws@^7.5.1: +ws@^7, ws@^7.5.1, ws@^7.5.9: version "7.5.9" resolved "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz" integrity sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q== @@ -12637,3 +12097,10 @@ yocto-queue@^0.1.0: version "0.1.0" resolved "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== + +zustand@^4.3.8: + version "4.4.1" + resolved "https://registry.yarnpkg.com/zustand/-/zustand-4.4.1.tgz#0cd3a3e4756f21811bd956418fdc686877e8b3b0" + integrity sha512-QCPfstAS4EBiTQzlaGP1gmorkh/UL1Leaj2tdj+zZCZ/9bm0WS7sI2wnfD5lpOszFqWJ1DcPnGoY8RDL61uokw== + dependencies: + use-sync-external-store "1.2.0" From 9cfe5e68e1e447cc141bc2cb7851aab3ad63f585 Mon Sep 17 00:00:00 2001 From: poomthiti Date: Tue, 22 Aug 2023 16:56:50 +0700 Subject: [PATCH 58/94] fix: render NavProvider --- src/lib/providers/index.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/lib/providers/index.tsx b/src/lib/providers/index.tsx index 1c5a14b53..08b34a48c 100644 --- a/src/lib/providers/index.tsx +++ b/src/lib/providers/index.tsx @@ -1,4 +1,4 @@ -import { AppProvider } from "lib/app-provider"; +import { AppProvider, NavProvider } from "lib/app-provider"; import { AmplitudeProvider } from "./amplitude"; import { ChakraProvider } from "./chakra"; @@ -14,7 +14,9 @@ export default ({ children }: { children: React.ReactNode }) => ( - {children} + + {children} + From 43663de9285edf9d65acabb27a31192a5b21b425 Mon Sep 17 00:00:00 2001 From: songwongtp <16089160+songwongtp@users.noreply.github.com> Date: Tue, 22 Aug 2023 17:33:43 +0700 Subject: [PATCH 59/94] fix: chevron color --- .../components/json-schema/form/widgets/SelectWidget.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/lib/components/json-schema/form/widgets/SelectWidget.tsx b/src/lib/components/json-schema/form/widgets/SelectWidget.tsx index 9972957b1..d9578ffda 100644 --- a/src/lib/components/json-schema/form/widgets/SelectWidget.tsx +++ b/src/lib/components/json-schema/form/widgets/SelectWidget.tsx @@ -148,7 +148,11 @@ const SelectWidget = (props: WidgetProps) => { chakraStyles={{ control: (provided) => ({ ...provided, - _disabled: { color: "text.main" }, + _disabled: undefined, + }), + dropdownIndicator: (provided, state) => ({ + ...provided, + color: state.isDisabled ? "gray.700" : undefined, }), option: (provided, state) => ({ ...provided, From 952e9359755c30d7e381eedb897b7478b8dd6b9b Mon Sep 17 00:00:00 2001 From: songwongtp <16089160+songwongtp@users.noreply.github.com> Date: Tue, 22 Aug 2023 17:37:00 +0700 Subject: [PATCH 60/94] fix: text --- src/lib/components/json-schema/form/widgets/SelectWidget.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/lib/components/json-schema/form/widgets/SelectWidget.tsx b/src/lib/components/json-schema/form/widgets/SelectWidget.tsx index d9578ffda..b2aca4957 100644 --- a/src/lib/components/json-schema/form/widgets/SelectWidget.tsx +++ b/src/lib/components/json-schema/form/widgets/SelectWidget.tsx @@ -148,7 +148,9 @@ const SelectWidget = (props: WidgetProps) => { chakraStyles={{ control: (provided) => ({ ...provided, - _disabled: undefined, + _disabled: { + color: "text.main", + }, }), dropdownIndicator: (provided, state) => ({ ...provided, From 2312110a14ba6e7101299126d9a46685126d5dc8 Mon Sep 17 00:00:00 2001 From: evilpeach Date: Tue, 22 Aug 2023 18:14:16 +0700 Subject: [PATCH 61/94] feat: support nullable schema --- .../pages/execute/components/ExecuteArea.tsx | 25 ++++++++++++------- src/lib/pages/execute/index.tsx | 8 ------ src/lib/pages/query/components/QueryArea.tsx | 25 ++++++++++++------- src/lib/pages/query/index.tsx | 4 --- 4 files changed, 32 insertions(+), 30 deletions(-) diff --git a/src/lib/pages/execute/components/ExecuteArea.tsx b/src/lib/pages/execute/components/ExecuteArea.tsx index e491f5d76..3d58b2d09 100644 --- a/src/lib/pages/execute/components/ExecuteArea.tsx +++ b/src/lib/pages/execute/components/ExecuteArea.tsx @@ -8,8 +8,8 @@ import { MessageTabs, } from "lib/components/json-schema"; import { EmptyState } from "lib/components/state"; -import type { ExecuteSchema } from "lib/stores/schema"; -import type { ContractAddr, Option } from "lib/types"; +import { useSchemaStore } from "lib/providers/store"; +import type { ContractAddr } from "lib/types"; import { JsonExecute } from "./JsonExecute"; import { SchemaExecute } from "./schema-execute"; @@ -20,7 +20,6 @@ interface ExecuteAreaProps { initialFunds: Coin[]; codeId: string; codeHash: string; - schema: Option; } export const ExecuteArea = ({ @@ -29,10 +28,22 @@ export const ExecuteArea = ({ initialFunds, codeHash, codeId, - schema, }: ExecuteAreaProps) => { const [tab, setTab] = useState(MessageTabs.JSON_INPUT); + const { getExecuteSchema, getSchemaByCodeHash } = useSchemaStore(); + const schema = getExecuteSchema(codeHash); + const attached = Boolean(getSchemaByCodeHash(codeHash)); + + const tooltipLabel = (() => { + if (!codeId) return "Please select contract first."; + + if (!attached) + return `You haven't attached the JSON Schema for code id ${codeId}. \n To use the schema, please add it on the code detail page.`; + + return "Attached JSON Schema doesn’t have execute message."; + })(); + useEffect(() => { if (!schema) setTab(MessageTabs.JSON_INPUT); else setTab(MessageTabs.YOUR_SCHEMA); @@ -48,11 +59,7 @@ export const ExecuteArea = ({ currentTab={tab} onTabChange={setTab} disabled={!schema} - tooltipLabel={ - codeId && !schema - ? `You haven't attached the JSON Schema for code id ${codeId}. \n To use the schema, please add it on the code detail page.` - : "Please select contract first." - } + tooltipLabel={tooltipLabel} /> { const router = useRouter(); const navigate = useInternalNavigate(); - const { getExecuteSchema } = useSchemaStore(); // ------------------------------------------// // ------------------STATES------------------// @@ -40,11 +38,6 @@ const Execute = () => { const [codeHash, setCodeHash] = useState(""); const [codeId, setCodeId] = useState(""); - // ------------------------------------------// - // ------------------LOGICS------------------// - // ------------------------------------------// - const schema = getExecuteSchema(codeHash); - // ------------------------------------------// // ----------------CALLBACKS-----------------// // ------------------------------------------// @@ -138,7 +131,6 @@ const Execute = () => { contractAddress={contractAddress} initialMsg={initialMsg} initialFunds={initialFunds} - schema={schema} codeId={codeId} codeHash={codeHash} /> diff --git a/src/lib/pages/query/components/QueryArea.tsx b/src/lib/pages/query/components/QueryArea.tsx index 39c117f40..5ff4c0589 100644 --- a/src/lib/pages/query/components/QueryArea.tsx +++ b/src/lib/pages/query/components/QueryArea.tsx @@ -7,8 +7,8 @@ import { MessageTabs, } from "lib/components/json-schema"; import { EmptyState } from "lib/components/state"; -import type { QuerySchema } from "lib/stores/schema"; -import type { ContractAddr, Option } from "lib/types"; +import { useSchemaStore } from "lib/providers/store"; +import type { ContractAddr } from "lib/types"; import { JsonQuery } from "./JsonQuery"; import { SchemaQuery } from "./SchemaQuery"; @@ -17,7 +17,6 @@ interface QueryAreaProps { contractAddress: ContractAddr; codeId: string; codeHash: string; - schema: Option; initialMsg: string; } @@ -25,11 +24,23 @@ export const QueryArea = ({ contractAddress, codeId, codeHash, - schema, initialMsg, }: QueryAreaProps) => { const [tab, setTab] = useState(MessageTabs.JSON_INPUT); + const { getQuerySchema, getSchemaByCodeHash } = useSchemaStore(); + const schema = getQuerySchema(codeHash); + const attached = Boolean(getSchemaByCodeHash(codeHash)); + + const tooltipLabel = (() => { + if (!codeId) return "Please select contract first."; + + if (!attached) + return `You haven't attached the JSON Schema for code id ${codeId}. \n To use the schema, please add it on the code detail page.`; + + return "Attached JSON Schema doesn’t have query message."; + })(); + useEffect(() => { if (!schema) setTab(MessageTabs.JSON_INPUT); else setTab(MessageTabs.YOUR_SCHEMA); @@ -45,11 +56,7 @@ export const QueryArea = ({ currentTab={tab} onTabChange={setTab} disabled={!schema} - tooltipLabel={ - codeId && !schema - ? `You haven't attached the JSON Schema for code id ${codeId}. \n To use the schema, please add it on the code detail page.` - : "Please select contract first." - } + tooltipLabel={tooltipLabel} /> { useWasmConfig({ shouldRedirect: true }); const router = useRouter(); const navigate = useInternalNavigate(); - const { getQuerySchema } = useSchemaStore(); const [contractAddress, setContractAddress] = useState("" as ContractAddr); const [codeHash, setCodeHash] = useState(""); const [codeId, setCodeId] = useState(""); const [initialMsg, setInitialMsg] = useState(""); const isMobile = useMobile(); - const schema = getQuerySchema(codeHash); const goToExecute = () => { navigate({ @@ -110,7 +107,6 @@ const Query = observer(() => { Date: Wed, 23 Aug 2023 11:28:10 +0700 Subject: [PATCH 62/94] fix: cannot switch execute query --- src/lib/pages/execute/components/ExecuteArea.tsx | 3 ++- src/lib/pages/query/components/QueryArea.tsx | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/lib/pages/execute/components/ExecuteArea.tsx b/src/lib/pages/execute/components/ExecuteArea.tsx index 3d58b2d09..885515d7c 100644 --- a/src/lib/pages/execute/components/ExecuteArea.tsx +++ b/src/lib/pages/execute/components/ExecuteArea.tsx @@ -47,7 +47,8 @@ export const ExecuteArea = ({ useEffect(() => { if (!schema) setTab(MessageTabs.JSON_INPUT); else setTab(MessageTabs.YOUR_SCHEMA); - }, [schema]); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [JSON.stringify(schema)]); return ( diff --git a/src/lib/pages/query/components/QueryArea.tsx b/src/lib/pages/query/components/QueryArea.tsx index 5ff4c0589..d771c3993 100644 --- a/src/lib/pages/query/components/QueryArea.tsx +++ b/src/lib/pages/query/components/QueryArea.tsx @@ -44,7 +44,8 @@ export const QueryArea = ({ useEffect(() => { if (!schema) setTab(MessageTabs.JSON_INPUT); else setTab(MessageTabs.YOUR_SCHEMA); - }, [schema]); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [JSON.stringify(schema)]); return ( <> From bd993848bfb74095a3ef3facfb0957506ed2c43e Mon Sep 17 00:00:00 2001 From: poomthiti Date: Wed, 23 Aug 2023 15:37:04 +0700 Subject: [PATCH 63/94] fix: fix icns bech32 prefix searchbar display and schema switch highlight on query page --- CHANGELOG.md | 1 + .../json-schema/MessageInputContent.tsx | 6 ++-- .../json-schema/MessageInputSwitch.tsx | 7 +++-- src/lib/layout/Searchbar.tsx | 8 +++-- .../pages/execute/components/ExecuteArea.tsx | 2 +- src/lib/pages/instantiate/instantiate.tsx | 4 +-- .../migrate/components/MigrateContract.tsx | 31 ++++++++++++------- src/lib/pages/query/components/QueryArea.tsx | 2 +- src/lib/services/searchService.ts | 11 ++++++- 9 files changed, 48 insertions(+), 24 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8a782e778..9198e74b9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -86,6 +86,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Bug fixes +- [#496](https://github.com/alleslabs/celatone-frontend/pull/496) Fix icns bech32 prefix searchbar display and schema switch highlight on query page - [#470](https://github.com/alleslabs/celatone-frontend/pull/470) Fix json schema array field default behavior - [#476](https://github.com/alleslabs/celatone-frontend/pull/476) Fix terra rpc - [#473](https://github.com/alleslabs/celatone-frontend/pull/473) Fix wording on upload code modal diff --git a/src/lib/components/json-schema/MessageInputContent.tsx b/src/lib/components/json-schema/MessageInputContent.tsx index fcdf2d46d..69d1c0ec2 100644 --- a/src/lib/components/json-schema/MessageInputContent.tsx +++ b/src/lib/components/json-schema/MessageInputContent.tsx @@ -2,16 +2,18 @@ import type { BoxProps } from "@chakra-ui/react"; import { Box } from "@chakra-ui/react"; import type { ReactNode } from "react"; +import type { Option } from "lib/types"; + import { MessageTabs } from "./MessageInputSwitch"; interface MessageInputContentProps { - currentTab: MessageTabs; + currentTab: Option; jsonContent: ReactNode; schemaContent: ReactNode; } const resolveTabDisplay = ( - current: MessageTabs, + current: Option, target: MessageTabs ): BoxProps["display"] => { return current === target ? "block" : "none"; diff --git a/src/lib/components/json-schema/MessageInputSwitch.tsx b/src/lib/components/json-schema/MessageInputSwitch.tsx index 4388987a2..56272b86e 100644 --- a/src/lib/components/json-schema/MessageInputSwitch.tsx +++ b/src/lib/components/json-schema/MessageInputSwitch.tsx @@ -4,6 +4,7 @@ import { useRef } from "react"; import { Tooltip } from "../Tooltip"; import { MotionBox } from "lib/components/MotionBox"; +import type { Option } from "lib/types"; export enum MessageTabs { JSON_INPUT = "JSON Input", @@ -14,10 +15,10 @@ export const jsonInputFormKey = MessageTabs.JSON_INPUT as "JSON Input"; export const yourSchemaInputFormKey = MessageTabs.YOUR_SCHEMA as "Your Schema"; interface MessageInputSwitchProps { - currentTab: MessageTabs; + currentTab: Option; disabled?: boolean; tooltipLabel?: string; - onTabChange: Dispatch>; + onTabChange: Dispatch>>; } const tabs = Object.values(MessageTabs); @@ -29,7 +30,7 @@ export const MessageInputSwitch = ({ onTabChange, }: MessageInputSwitchProps) => { const tabRefs = useRef<(HTMLDivElement | null)[]>([]); - const activeIndex = tabs.indexOf(currentTab); + const activeIndex = currentTab ? tabs.indexOf(currentTab) : -1; return (
diff --git a/src/lib/layout/Searchbar.tsx b/src/lib/layout/Searchbar.tsx index 162d9b5b7..26718bc9d 100644 --- a/src/lib/layout/Searchbar.tsx +++ b/src/lib/layout/Searchbar.tsx @@ -96,6 +96,9 @@ const ResultItem = ({ onClose, }: ResultItemProps) => { const route = getRouteOptions(type)?.pathname; + const normalizedIcnsValue = value.includes(`.${metadata.icns.bech32Prefix}`) + ? value + : `${value}.${metadata.icns.bech32Prefix}`; return ( @@ -126,7 +129,8 @@ const ResultItem = ({ {value !== metadata.icns.address && - value !== metadata.icns.icnsNames?.primary_name && ( + normalizedIcnsValue !== + metadata.icns.icnsNames?.primary_name && ( - {value} + {normalizedIcnsValue} )} diff --git a/src/lib/pages/execute/components/ExecuteArea.tsx b/src/lib/pages/execute/components/ExecuteArea.tsx index 885515d7c..cedf5c6b8 100644 --- a/src/lib/pages/execute/components/ExecuteArea.tsx +++ b/src/lib/pages/execute/components/ExecuteArea.tsx @@ -29,7 +29,7 @@ export const ExecuteArea = ({ codeHash, codeId, }: ExecuteAreaProps) => { - const [tab, setTab] = useState(MessageTabs.JSON_INPUT); + const [tab, setTab] = useState(); const { getExecuteSchema, getSchemaByCodeHash } = useSchemaStore(); const schema = getExecuteSchema(codeHash); diff --git a/src/lib/pages/instantiate/instantiate.tsx b/src/lib/pages/instantiate/instantiate.tsx index 8bf340720..5e45a377e 100644 --- a/src/lib/pages/instantiate/instantiate.tsx +++ b/src/lib/pages/instantiate/instantiate.tsx @@ -100,7 +100,7 @@ const Instantiate = ({ onComplete }: InstantiatePageProps) => { const [estimatedFee, setEstimatedFee] = useState(); const [simulateError, setSimulateError] = useState(""); const [processing, setProcessing] = useState(false); - const [tab, setTab] = useState(MessageTabs.JSON_INPUT); + const [tab, setTab] = useState(); // ------------------------------------------// // ----------------FORM HOOKS----------------// // ------------------------------------------// @@ -123,7 +123,7 @@ const Instantiate = ({ onComplete }: InstantiatePageProps) => { }, }); const { codeId, codeHash, label, adminAddress, msgInput } = watch(); - const currentInput = msgInput[tab]; + const currentInput = tab ? msgInput[tab] : "{}"; const { control: assetsControl, diff --git a/src/lib/pages/migrate/components/MigrateContract.tsx b/src/lib/pages/migrate/components/MigrateContract.tsx index 2f2331936..5b2d56a5f 100644 --- a/src/lib/pages/migrate/components/MigrateContract.tsx +++ b/src/lib/pages/migrate/components/MigrateContract.tsx @@ -28,7 +28,7 @@ import { useTxBroadcast } from "lib/providers/tx-broadcast"; import { AmpEvent, AmpTrack } from "lib/services/amplitude"; import type { CodeIdInfoResponse } from "lib/services/code"; import { useLCDCodeInfo } from "lib/services/codeService"; -import type { ComposedMsg, ContractAddr, HumanAddr } from "lib/types"; +import type { ComposedMsg, ContractAddr, HumanAddr, Option } from "lib/types"; import { MsgType } from "lib/types"; import { composeMsg, @@ -43,6 +43,17 @@ interface MigrateContractProps { handleBack: () => void; } +const resolveEnable = ( + address: Option, + codeId: string, + currentInput: string, + status: FormStatus +) => + !!address && + isCodeId(codeId) && + jsonValidate(currentInput) === null && + status.state === "success"; + export const MigrateContract = observer( ({ contractAddress, codeIdParam, handleBack }: MigrateContractProps) => { const { address } = useCurrentChain(); @@ -68,28 +79,24 @@ export const MigrateContract = observer( }); const { codeId, codeHash, msgInput } = watch(); - const [tab, setTab] = useState(MessageTabs.JSON_INPUT); + const [tab, setTab] = useState(); const [status, setStatus] = useState({ state: "init" }); const [composedTxMsg, setComposedTxMsg] = useState([]); const [estimatedFee, setEstimatedFee] = useState(); const [simulateError, setSimulateError] = useState(""); const [processing, setProcessing] = useState(false); - const currentInput = msgInput[tab]; + const currentInput = tab ? msgInput[tab] : "{}"; - const enableMigrate = - !!address && - isCodeId(codeId) && - jsonValidate(currentInput) === null && - status.state === "success"; + const enableMigrate = resolveEnable(address, codeId, currentInput, status); const { isFetching: isSimulating } = useSimulateFeeQuery({ enabled: composedTxMsg.length > 0, messages: composedTxMsg, - onSuccess: (gasRes) => { - if (gasRes) setEstimatedFee(fabricateFee(gasRes)); - else setEstimatedFee(undefined); - }, + onSuccess: (gasRes) => + gasRes + ? setEstimatedFee(fabricateFee(gasRes)) + : setEstimatedFee(undefined), onError: (e) => { setSimulateError(e.message); setEstimatedFee(undefined); diff --git a/src/lib/pages/query/components/QueryArea.tsx b/src/lib/pages/query/components/QueryArea.tsx index d771c3993..32857c624 100644 --- a/src/lib/pages/query/components/QueryArea.tsx +++ b/src/lib/pages/query/components/QueryArea.tsx @@ -26,7 +26,7 @@ export const QueryArea = ({ codeHash, initialMsg, }: QueryAreaProps) => { - const [tab, setTab] = useState(MessageTabs.JSON_INPUT); + const [tab, setTab] = useState(); const { getQuerySchema, getSchemaByCodeHash } = useSchemaStore(); const schema = getQuerySchema(codeHash); diff --git a/src/lib/services/searchService.ts b/src/lib/services/searchService.ts index 4497e539b..01fb2ba90 100644 --- a/src/lib/services/searchService.ts +++ b/src/lib/services/searchService.ts @@ -5,6 +5,7 @@ import { CELATONE_QUERY_KEYS, useBaseApiRoute, useCelatoneApp, + useCurrentChain, useGetAddressType, } from "lib/app-provider"; import type { Addr, ContractAddr, Option } from "lib/types"; @@ -28,7 +29,11 @@ export type SearchResultType = | "Pool ID"; export interface ResultMetadata { - icns: { icnsNames: Option; address: Option }; + icns: { + icnsNames: Option; + address: Option; + bech32Prefix: string; + }; } // TODO: Add Proposal ID @@ -51,6 +56,9 @@ export const useSearchHandler = ( }, } = useCelatoneApp(); const lcdEndpoint = useBaseApiRoute("rest"); + const { + chain: { bech32_prefix: bech32Prefix }, + } = useCurrentChain(); const getAddressType = useGetAddressType(); const addressType = getAddressType(debouncedKeyword); const { data: txData, isFetching: txFetching } = useTxData(debouncedKeyword); @@ -125,6 +133,7 @@ export const useSearchHandler = ( icns: { icnsNames, address: (isAddr ? debouncedKeyword : icnsAddressData?.address) as Addr, + bech32Prefix, }, }, }; From 6108fd1a395b0a4190c680d2012972cdd4ce5039 Mon Sep 17 00:00:00 2001 From: songwongtp <16089160+songwongtp@users.noreply.github.com> Date: Wed, 23 Aug 2023 16:00:40 +0700 Subject: [PATCH 64/94] fix: storedcode and navbar dev to normal --- CHANGELOG.md | 1 + next.config.js | 3 ++- src/lib/layout/SubHeader.tsx | 7 +------ src/lib/pages/upload/completed.tsx | 4 ++-- 4 files changed, 6 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8a782e778..99a43d753 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -86,6 +86,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Bug fixes +- [#497](https://github.com/alleslabs/celatone-frontend/pull/497) Fix stored codes route and navbar behavior from dev to normal mode - [#470](https://github.com/alleslabs/celatone-frontend/pull/470) Fix json schema array field default behavior - [#476](https://github.com/alleslabs/celatone-frontend/pull/476) Fix terra rpc - [#473](https://github.com/alleslabs/celatone-frontend/pull/473) Fix wording on upload code modal diff --git a/next.config.js b/next.config.js index c4058f97d..8596995b9 100644 --- a/next.config.js +++ b/next.config.js @@ -44,7 +44,8 @@ const nextConfig = { "project", "contract-list", "past-tx", - "my-code", + "stored-codes", + "saved-codes", "pool", ]; diff --git a/src/lib/layout/SubHeader.tsx b/src/lib/layout/SubHeader.tsx index 13f919202..82b264787 100644 --- a/src/lib/layout/SubHeader.tsx +++ b/src/lib/layout/SubHeader.tsx @@ -111,12 +111,7 @@ const SubHeader = ({ useEffect(() => { // Basic to dev and nav is collapse -> should exapnd - if (isDevMode && !prevIsDevModeRef.current && !isExpand) { - setIsExpand(true); - // Dev to basic and nav is exapnd -> should collapse - } else if (!isDevMode && prevIsDevModeRef.current && isExpand) { - setIsExpand(false); - } + if (isDevMode && !prevIsDevModeRef.current && !isExpand) setIsExpand(true); prevIsDevModeRef.current = Boolean(isDevMode); }, [isDevMode, isExpand, setIsExpand]); diff --git a/src/lib/pages/upload/completed.tsx b/src/lib/pages/upload/completed.tsx index 2a11275da..e39fa721e 100644 --- a/src/lib/pages/upload/completed.tsx +++ b/src/lib/pages/upload/completed.tsx @@ -111,10 +111,10 @@ export const UploadComplete = observer(({ txResult }: UploadCompleteProps) => { variant="outline-primary" w="full" onClick={() => { - navigate({ pathname: "/my-codes" }); + navigate({ pathname: "/stored-codes" }); }} > - Go to my code list + Go to my stored codes ); From 6b8547699749bbe8f9c94f395185d65b1d6a3d06 Mon Sep 17 00:00:00 2001 From: poomthiti Date: Wed, 23 Aug 2023 17:20:25 +0700 Subject: [PATCH 65/94] fix: automatically switch to schema tab and show 404 not found error --- CHANGELOG.md | 1 + .../components/json-schema/UploadTemplate.tsx | 3 +- .../section/SchemaInputSection.tsx | 158 +++++++++--------- src/lib/pages/home/components/DevShortcut.tsx | 2 +- src/lib/pages/instantiate/instantiate.tsx | 15 +- .../migrate/components/MigrateContract.tsx | 10 +- 6 files changed, 103 insertions(+), 86 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8a782e778..6c5faae90 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -62,6 +62,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Improvements +- [#498](https://github.com/alleslabs/celatone-frontend/pull/498) Automatically switch to schema tab and show 404 not found error - [#491](https://github.com/alleslabs/celatone-frontend/pull/491) Improve scrolling into view by delaying scroll function - [#489](https://github.com/alleslabs/celatone-frontend/pull/489) Improve jsonschema query response UI and fix jsonschema incorrect oneOf behavior - [#484](https://github.com/alleslabs/celatone-frontend/pull/484) Fix text size consistency in txs message diff --git a/src/lib/components/json-schema/UploadTemplate.tsx b/src/lib/components/json-schema/UploadTemplate.tsx index f7578b76c..a4946baae 100644 --- a/src/lib/components/json-schema/UploadTemplate.tsx +++ b/src/lib/components/json-schema/UploadTemplate.tsx @@ -203,7 +203,8 @@ export const UploadTemplate = ({ return dispatchJsonState({ type: ActionType.SET_ERROR, method, - error: response.statusText, + error: + response.status === 404 ? "404 Not Found" : response.statusText, }); } schemaString = JSON.stringify(await response.json()); diff --git a/src/lib/components/json-schema/section/SchemaInputSection.tsx b/src/lib/components/json-schema/section/SchemaInputSection.tsx index 0bfd42eff..6cdc91a08 100644 --- a/src/lib/components/json-schema/section/SchemaInputSection.tsx +++ b/src/lib/components/json-schema/section/SchemaInputSection.tsx @@ -1,99 +1,97 @@ import { Button, Flex, Text, useDisclosure } from "@chakra-ui/react"; import type { RJSFSchema } from "@rjsf/utils"; import { capitalize } from "lodash"; -import { observer } from "mobx-react-lite"; import { AttachSchemaCard } from "../AttachSchemaCard"; import { JsonSchemaForm } from "../form"; import { JsonSchemaDrawer } from "../JsonSchemaDrawer"; import { ViewSchemaButton } from "../ViewSchemaButton"; -import { useSchemaStore } from "lib/providers/store"; +import type { CodeSchema } from "lib/stores/schema"; +import type { Option } from "lib/types"; interface SchemaSectionProps { type: "migrate" | "instantiate"; codeHash: string; codeId: string; + jsonSchema: Option; initialFormData?: Record; setSchemaInput: (input: string) => void; } -export const SchemaInputSection = observer( - ({ - type, - codeHash, - codeId, - initialFormData, - setSchemaInput, - }: SchemaSectionProps) => { - const { getSchemaByCodeHash } = useSchemaStore(); - const jsonSchema = getSchemaByCodeHash(codeHash); - const { isOpen, onClose, onOpen } = useDisclosure(); - const prettyType = capitalize(type); +export const SchemaInputSection = ({ + type, + codeHash, + codeId, + jsonSchema, + initialFormData, + setSchemaInput, +}: SchemaSectionProps) => { + const { isOpen, onClose, onOpen } = useDisclosure(); + const prettyType = capitalize(type); - return ( - - {jsonSchema?.[type] ? ( - <> - - - You are using a locally attached JSON Schema - - - - - - - {/* TODO: revisit type assertion later */} - setSchemaInput(JSON.stringify(data))} - /> - - ) : ( - <> - - {jsonSchema - ? `Attached JSON Schema doesn’t have ${prettyType}Msg` - : `You haven't attached the JSON Schema for code ${codeId} yet`} - - - {jsonSchema - ? `Please fill in ${prettyType} Message manually or change the schema` - : "Your attached JSON schema will be stored locally on your device"} + return ( + + {jsonSchema?.[type] ? ( + <> + + + You are using a locally attached JSON Schema - - - )} - - - ); - } -); + + + + + + {/* TODO: revisit type assertion later */} + setSchemaInput(JSON.stringify(data))} + /> + + ) : ( + <> + + {jsonSchema + ? `Attached JSON Schema doesn’t have ${prettyType}Msg` + : `You haven't attached the JSON Schema for code ${codeId} yet`} + + + {jsonSchema + ? `Please fill in ${prettyType} Message manually or change the schema` + : "Your attached JSON schema will be stored locally on your device"} + + + + )} + + + ); +}; diff --git a/src/lib/pages/home/components/DevShortcut.tsx b/src/lib/pages/home/components/DevShortcut.tsx index 453c86d7f..9af690c72 100644 --- a/src/lib/pages/home/components/DevShortcut.tsx +++ b/src/lib/pages/home/components/DevShortcut.tsx @@ -29,7 +29,7 @@ const shortcutList: ShortcutMetadata[] = [ { title: "Deploy", subtitle: "Upload code or instantiate contract", - slug: "/deploy", + slug: "deploy", icon: "add-new", }, { diff --git a/src/lib/pages/instantiate/instantiate.tsx b/src/lib/pages/instantiate/instantiate.tsx index 8bf340720..e93b21449 100644 --- a/src/lib/pages/instantiate/instantiate.tsx +++ b/src/lib/pages/instantiate/instantiate.tsx @@ -2,6 +2,7 @@ import { Flex, Heading, Text } from "@chakra-ui/react"; import type { InstantiateResult } from "@cosmjs/cosmwasm-stargate"; import type { StdFee } from "@cosmjs/stargate"; import Long from "long"; +import { observer } from "mobx-react-lite"; import { useRouter } from "next/router"; import { useCallback, useEffect, useMemo, useState } from "react"; import { useForm } from "react-hook-form"; @@ -37,6 +38,7 @@ import JsonInput from "lib/components/json/JsonInput"; import { CodeSelectSection } from "lib/components/select-code"; import { Stepper } from "lib/components/stepper"; import WasmPageContainer from "lib/components/WasmPageContainer"; +import { useSchemaStore } from "lib/providers/store"; import { useTxBroadcast } from "lib/providers/tx-broadcast"; import { AmpEvent, @@ -75,7 +77,7 @@ interface InstantiatePageProps { onComplete: (txResult: InstantiateResult, contractLabel: string) => void; } -const Instantiate = ({ onComplete }: InstantiatePageProps) => { +const Instantiate = observer(({ onComplete }: InstantiatePageProps) => { // ------------------------------------------// // ---------------DEPENDENCIES---------------// // ------------------------------------------// @@ -91,7 +93,7 @@ const Instantiate = ({ onComplete }: InstantiatePageProps) => { const { broadcast } = useTxBroadcast(); const { validateUserAddress, validateContractAddress } = useValidateAddress(); const getAttachFunds = useAttachFunds(); - + const { getSchemaByCodeHash } = useSchemaStore(); // ------------------------------------------// // ------------------STATES------------------// // ------------------------------------------// @@ -139,6 +141,7 @@ const Instantiate = ({ onComplete }: InstantiatePageProps) => { }); const { assetsSelect, assetsJsonStr, attachFundsOption } = watchAssets(); + const jsonSchema = getSchemaByCodeHash(codeHash); const funds = getAttachFunds(attachFundsOption, assetsJsonStr, assetsSelect); const enableInstantiate = useMemo( () => @@ -234,6 +237,7 @@ const Instantiate = ({ onComplete }: InstantiatePageProps) => { useEffect(() => { setValue("codeHash", ""); setTab(MessageTabs.JSON_INPUT); + setValue(`msgInput.${yourSchemaInputFormKey}`, "{}"); if (codeId.length) { setStatus({ state: "loading" }); const timer = setTimeout(() => { @@ -307,6 +311,10 @@ const Instantiate = ({ onComplete }: InstantiatePageProps) => { } }, [codeIdQuery, msgQuery, setAssets, setValue]); + useEffect(() => { + if (jsonSchema) setTab(MessageTabs.YOUR_SCHEMA); + }, [jsonSchema]); + useEffect(() => { if (router.isReady) AmpTrackToInstantiate(!!msgQuery, !!codeIdQuery); }, [router.isReady, msgQuery, codeIdQuery]); @@ -400,6 +408,7 @@ const Instantiate = ({ onComplete }: InstantiatePageProps) => { type="instantiate" codeHash={codeHash} codeId={codeId} + jsonSchema={jsonSchema} setSchemaInput={(msg: string) => setValue(`msgInput.${yourSchemaInputFormKey}`, msg) } @@ -450,6 +459,6 @@ const Instantiate = ({ onComplete }: InstantiatePageProps) => { /> ); -}; +}); export default Instantiate; diff --git a/src/lib/pages/migrate/components/MigrateContract.tsx b/src/lib/pages/migrate/components/MigrateContract.tsx index 2f2331936..6905e294b 100644 --- a/src/lib/pages/migrate/components/MigrateContract.tsx +++ b/src/lib/pages/migrate/components/MigrateContract.tsx @@ -24,6 +24,7 @@ import { } from "lib/components/json-schema"; import JsonInput from "lib/components/json/JsonInput"; import { CodeSelectSection } from "lib/components/select-code"; +import { useSchemaStore } from "lib/providers/store"; import { useTxBroadcast } from "lib/providers/tx-broadcast"; import { AmpEvent, AmpTrack } from "lib/services/amplitude"; import type { CodeIdInfoResponse } from "lib/services/code"; @@ -49,6 +50,7 @@ export const MigrateContract = observer( const { broadcast } = useTxBroadcast(); const migrateTx = useMigrateTx(); const fabricateFee = useFabricateFee(); + const { getSchemaByCodeHash } = useSchemaStore(); const { control, @@ -76,7 +78,7 @@ export const MigrateContract = observer( const [processing, setProcessing] = useState(false); const currentInput = msgInput[tab]; - + const jsonSchema = getSchemaByCodeHash(codeHash); const enableMigrate = !!address && isCodeId(codeId) && @@ -155,6 +157,7 @@ export const MigrateContract = observer( useEffect(() => { setValue("codeHash", ""); setTab(MessageTabs.JSON_INPUT); + setValue(`msgInput.${yourSchemaInputFormKey}`, "{}"); if (codeId.length) { setStatus({ state: "loading" }); const timer = setTimeout(() => { @@ -184,6 +187,10 @@ export const MigrateContract = observer( return () => {}; }, [address, codeId, contractAddress, enableMigrate, currentInput]); + useEffect(() => { + if (jsonSchema) setTab(MessageTabs.YOUR_SCHEMA); + }, [jsonSchema]); + return ( <> @@ -228,6 +235,7 @@ export const MigrateContract = observer( type="migrate" codeHash={codeHash} codeId={codeId} + jsonSchema={jsonSchema} setSchemaInput={(msg: string) => setValue(`msgInput.${yourSchemaInputFormKey}`, msg) } From fe1a53c8c256ee9a188dbadcdd4bcae8f353793c Mon Sep 17 00:00:00 2001 From: songwongtp <16089160+songwongtp@users.noreply.github.com> Date: Wed, 23 Aug 2023 18:18:17 +0700 Subject: [PATCH 66/94] fix: schema input, maxlines, chevron --- CHANGELOG.md | 1 + src/lib/components/json-schema/UploadTemplate.tsx | 1 + .../json-schema/section/SchemaInputSection.tsx | 14 ++++++++------ src/lib/components/json/JsonInput.tsx | 6 ++++-- .../execute/components/schema-execute/index.tsx | 7 ++++++- .../pools/components/unsupportedSection/index.tsx | 9 +++++++-- src/lib/pages/query/components/SchemaQuery.tsx | 8 +++++++- 7 files changed, 34 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8a782e778..2735b4f5d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -86,6 +86,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Bug fixes +- [#499](https://github.com/alleslabs/celatone-frontend/pull/499) Fix sometimes select widget input not full, manual schema upload max lines, and expand/collapse all chevron - [#470](https://github.com/alleslabs/celatone-frontend/pull/470) Fix json schema array field default behavior - [#476](https://github.com/alleslabs/celatone-frontend/pull/476) Fix terra rpc - [#473](https://github.com/alleslabs/celatone-frontend/pull/473) Fix wording on upload code modal diff --git a/src/lib/components/json-schema/UploadTemplate.tsx b/src/lib/components/json-schema/UploadTemplate.tsx index f7578b76c..86e072589 100644 --- a/src/lib/components/json-schema/UploadTemplate.tsx +++ b/src/lib/components/json-schema/UploadTemplate.tsx @@ -160,6 +160,7 @@ const MethodRender = ({ }) } validateFn={validateSchema} + maxLines={25} /> ); diff --git a/src/lib/components/json-schema/section/SchemaInputSection.tsx b/src/lib/components/json-schema/section/SchemaInputSection.tsx index 0bfd42eff..ca3c05b5d 100644 --- a/src/lib/components/json-schema/section/SchemaInputSection.tsx +++ b/src/lib/components/json-schema/section/SchemaInputSection.tsx @@ -53,12 +53,14 @@ export const SchemaInputSection = observer( {/* TODO: revisit type assertion later */} - setSchemaInput(JSON.stringify(data))} - /> +
+ setSchemaInput(JSON.stringify(data))} + /> +
) : ( <> diff --git a/src/lib/components/json/JsonInput.tsx b/src/lib/components/json/JsonInput.tsx index 90acfc999..dfc514e17 100644 --- a/src/lib/components/json/JsonInput.tsx +++ b/src/lib/components/json/JsonInput.tsx @@ -13,6 +13,7 @@ interface JsonInputProps { topic?: string; text?: string; minLines?: number; + maxLines?: number; setText: (value: string) => void; validateFn?: (value: string) => string | null; } @@ -74,6 +75,7 @@ const JsonInput = ({ topic, text = "", minLines = 16, + maxLines = 100, setText, validateFn = jsonValidate, }: JsonInputProps) => { @@ -103,8 +105,8 @@ const JsonInput = ({ const lines = jsonLineCount(text); // Limit the number of lines from minLines (default is 16) to 100 - return Math.min(Math.max(lines, minLines), 100); - }, [text, minLines]); + return Math.min(Math.max(lines, minLines), maxLines); + }, [text, minLines, maxLines]); return ( <> diff --git a/src/lib/pages/execute/components/schema-execute/index.tsx b/src/lib/pages/execute/components/schema-execute/index.tsx index 31eb24c44..67635fdd5 100644 --- a/src/lib/pages/execute/components/schema-execute/index.tsx +++ b/src/lib/pages/execute/components/schema-execute/index.tsx @@ -84,7 +84,12 @@ export const SchemaExecute = ({ /> - - - )} - - - - Return Output - - - {msgSchema.inputRequired ? ( - - ) : ( - - )} - - {queryError && ( - - - {queryError} - - - )} - {resTab === MessageTabs.JSON_INPUT ? ( - - ) : ( - - - - )} - {!msgSchema.inputRequired && ( - - - - - - - - - )} - - - - - ); -}; +import { SchemaQueryComponent } from "./SchemaQueryComponent"; interface SchemaQueryProps { schema: QuerySchema; @@ -412,7 +113,7 @@ export const SchemaQuery = ({ sx={{ ".chakra-accordion__icon": { color: "gray.600" } }} > {filteredMsgs.map(([msg, res]) => ( - import("lib/components/modal/CodeSnippet"), { + ssr: false, +}); + +interface SchemaQueryComponentInterface { + msgSchema: QueryExecuteSchema; + resSchema: RJSFSchema; + contractAddress: ContractAddr; + lcdEndpoint: string; + walletAddress: Option; + initialMsg: Record; + addActivity: (activity: Activity) => void; +} + +const TimestampText = memo(({ timestamp }: { timestamp: Option }) => { + const [, setRenderCount] = useState(0); + let text = "Query response will display here"; + if (timestamp) + text = `Last Queried at ${formatUTC(timestamp)} (${dateFromNow( + timestamp + )})`; + + useEffect(() => { + const interval = setInterval(() => { + setRenderCount((prev) => prev + 1); + }, 60 * 1000); + return () => clearInterval(interval); + }, []); + + return ( + + {text} + + ); +}); + +interface ReturnWidgetsProps { + timestamp: Option; + inputRequired: Option; + res: string; + resTab: Option; + queryError: string; + setResTab: Dispatch>>; +} + +const ReturnWidgets = ({ + timestamp, + inputRequired, + res, + resTab, + queryError, + setResTab, +}: ReturnWidgetsProps) => { + return !inputRequired ? ( + + + Return Output + + + + + ) : ( + + + + Return Output + + + + + + + + + ); +}; + +export const SchemaQueryComponent = ({ + msgSchema, + resSchema, + contractAddress, + lcdEndpoint, + walletAddress, + initialMsg, + addActivity, +}: SchemaQueryComponentInterface) => { + const [resTab, setResTab] = useState(); + const [msg, setMsg] = useState("{}"); + const [res, setRes] = useState("{}"); + const [queryError, setQueryError] = useState(""); + const [timestamp, setTimestamp] = useState(); + + useEffect(() => { + if (Object.keys(initialMsg).length) setMsg(JSON.stringify(initialMsg)); + }, [initialMsg]); + + useEffect(() => { + if (msgSchema.inputRequired) setResTab(OutputMessageTabs.YOUR_SCHEMA); + else setResTab(OutputMessageTabs.JSON_OUTPUT); + }, [msgSchema.inputRequired, setResTab]); + + // TODO: Abstract query + const { + refetch, + isFetching: queryFetching, + isRefetching: queryRefetching, + } = useQuery( + [ + CELATONE_QUERY_KEYS.CONTRACT_QUERY, + lcdEndpoint, + contractAddress, + msgSchema.title, + msg, + ], + async () => + queryData( + lcdEndpoint, + contractAddress, + msgSchema.inputRequired + ? msg + : JSON.stringify({ [msgSchema.title ?? ""]: {} }) + ), + { + enabled: false, + retry: false, + cacheTime: 0, + onSuccess(data) { + const currentDate = getCurrentDate(); + setQueryError(""); + setRes(JSON.stringify(data.data, null, 2)); + setTimestamp(currentDate); + addActivity({ + type: "query", + action: msgSchema.title ?? "Unknown", + sender: walletAddress as HumanAddr, + contractAddress, + msg: encode(msg), + timestamp: currentDate, + }); + }, + onError(err: AxiosError) { + setQueryError(err.response?.data.message || DEFAULT_RPC_ERROR); + setTimestamp(undefined); + setRes("{}"); + }, + } + ); + + const handleQuery = useCallback(() => { + AmpTrack(AmpEvent.ACTION_QUERY); + refetch(); + }, [refetch]); + + useEffect(() => { + if (!msgSchema.inputRequired) refetch(); + }, [msgSchema.inputRequired, refetch]); + + return ( + +
+ + + + {msgSchema.title} + + {msgSchema.description} + + + +
+ + + {msgSchema.inputRequired && ( + + setMsg(JSON.stringify(data))} + initialFormData={initialMsg} + /> + + + + + + + )} + + + {queryError && ( + + + {queryError} + + + )} + {resTab === OutputMessageTabs.JSON_OUTPUT ? ( + + ) : ( + + + + )} + {!msgSchema.inputRequired && ( + + + + + + + + + )} + + + +
+ ); +}; From 83e55dfb51d4c3ebe3fb3ca4fdbadb8c461ddc14 Mon Sep 17 00:00:00 2001 From: poomthiti Date: Fri, 25 Aug 2023 11:56:52 +0700 Subject: [PATCH 74/94] fix: remove math.ran --- .../json-schema/MessageInputSwitch.tsx | 54 +++++++++---------- 1 file changed, 25 insertions(+), 29 deletions(-) diff --git a/src/lib/components/json-schema/MessageInputSwitch.tsx b/src/lib/components/json-schema/MessageInputSwitch.tsx index 0bac3aeb6..89ccfd76f 100644 --- a/src/lib/components/json-schema/MessageInputSwitch.tsx +++ b/src/lib/components/json-schema/MessageInputSwitch.tsx @@ -58,35 +58,31 @@ export const MessageInputSwitch = < position="relative" sx={{ ...(disabled ? { pointerEvents: "none", opacity: 0.3 } : {}) }} > - {tabs.map((tab, idx) => { - const x = String(Math.random() * 100); - return ( - { - tabRefs.current[idx] = el; - }} - cursor="pointer" - p="2px 10px" - fontSize="12px" - fontWeight={700} - variants={{ - active: { color: "var(--chakra-colors-text-main)" }, - inactive: { - color: "var(--chakra-colors-primary-light)", - }, - }} - initial="inactive" - animate={currentTab === tab ? "active" : "inactive"} - onClick={() => onTabChange(tab)} - zIndex={1} - textAlign="center" - > - {tab} - - ); - })} + {tabs.map((tab, idx) => ( + { + tabRefs.current[idx] = el; + }} + cursor="pointer" + p="2px 10px" + fontSize="12px" + fontWeight={700} + variants={{ + active: { color: "var(--chakra-colors-text-main)" }, + inactive: { + color: "var(--chakra-colors-primary-light)", + }, + }} + initial="inactive" + animate={currentTab === tab ? "active" : "inactive"} + onClick={() => onTabChange(tab)} + zIndex={1} + textAlign="center" + > + {tab} + + ))} Date: Fri, 25 Aug 2023 13:43:37 +0700 Subject: [PATCH 75/94] fix: bool field to select widget, no validate on res --- .../json-schema/form/fields/BooleanField.tsx | 8 +- src/lib/components/json-schema/form/index.tsx | 2 +- .../form/widgets/CheckboxWidget.tsx | 90 ------------------- .../json-schema/form/widgets/index.ts | 2 - src/lib/stores/schema.test.ts | 42 +++++---- 5 files changed, 28 insertions(+), 116 deletions(-) delete mode 100644 src/lib/components/json-schema/form/widgets/CheckboxWidget.tsx diff --git a/src/lib/components/json-schema/form/fields/BooleanField.tsx b/src/lib/components/json-schema/form/fields/BooleanField.tsx index b0b8e55ce..3567fffb1 100644 --- a/src/lib/components/json-schema/form/fields/BooleanField.tsx +++ b/src/lib/components/json-schema/form/fields/BooleanField.tsx @@ -32,7 +32,7 @@ function BooleanField(props: FieldProps) { } = props; const { title } = schema; const { widgets, formContext } = registry; - const { widget = "checkbox", ...options } = getUiOptions(uiSchema); + const { widget = "select", ...options } = getUiOptions(uiSchema); const Widget = getWidget(schema, widget, widgets); let enumOptions: EnumOptionsType[] | undefined; @@ -44,7 +44,7 @@ function BooleanField(props: FieldProps) { if (isObject(option)) { return { ...option, - title: option.title || (option.const === true ? "Yes" : "No"), + title: option.title || (option.const === true ? "True" : "False"), }; } return undefined; @@ -64,11 +64,11 @@ function BooleanField(props: FieldProps) { enumOptions = [ { value: enums[0], - label: enums[0] ? "Yes" : "No", + label: enums[0] ? "True" : "False", }, { value: enums[1], - label: enums[1] ? "Yes" : "No", + label: enums[1] ? "True" : "False", }, ]; } else { diff --git a/src/lib/components/json-schema/form/index.tsx b/src/lib/components/json-schema/form/index.tsx index 5b0f22984..31c918ab7 100644 --- a/src/lib/components/json-schema/form/index.tsx +++ b/src/lib/components/json-schema/form/index.tsx @@ -184,7 +184,7 @@ export const JsonSchemaForm: FC = ({ ...templates, }} validator={v8Validator} - liveValidate + liveValidate={!schema.readOnly} showErrorList={false} onChange={({ formData: values, errors }) => { // log.info(values) diff --git a/src/lib/components/json-schema/form/widgets/CheckboxWidget.tsx b/src/lib/components/json-schema/form/widgets/CheckboxWidget.tsx deleted file mode 100644 index dc0f43904..000000000 --- a/src/lib/components/json-schema/form/widgets/CheckboxWidget.tsx +++ /dev/null @@ -1,90 +0,0 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ -import { Checkbox, FormControl, FormLabel, Text } from "@chakra-ui/react"; -import type { WidgetProps } from "@rjsf/utils"; -import { getTemplate } from "@rjsf/utils"; -import type { ChangeEvent, FocusEvent } from "react"; - -export default function CheckboxWidget( - props: WidgetProps -) { - const { - id, - value, - disabled, - readonly, - required, - onChange, - onBlur, - onFocus, - label, - hideLabel, - registry, - options, - schema, - uiSchema, - } = props; - const DescriptionFieldTemplate = getTemplate< - "DescriptionFieldTemplate", - T, - F - >("DescriptionFieldTemplate", registry, options); - const description = options.description || schema.description; - - const { schemaUtils } = registry; - const displayLabel = - schemaUtils.getDisplayLabel(schema, uiSchema) && - (!!label || !!schema.title); - - const handleOnChange = ({ - target: { checked }, - }: ChangeEvent) => onChange(checked); - const handleOnBlur = ({ - target: { value: newValue }, - }: FocusEvent) => onBlur(id, newValue); - const handleOnFocus = ({ - target: { value: newValue }, - }: FocusEvent) => onFocus(id, newValue); - - return ( - - {displayLabel && ( - - {label} - - )} - {!hideLabel && !!description && ( - - )} - - - {typeof value === "undefined" ? `false` : `${value}`} - - - - ); -} diff --git a/src/lib/components/json-schema/form/widgets/index.ts b/src/lib/components/json-schema/form/widgets/index.ts index 2d3ec05ca..879c170b5 100644 --- a/src/lib/components/json-schema/form/widgets/index.ts +++ b/src/lib/components/json-schema/form/widgets/index.ts @@ -1,8 +1,6 @@ -import CheckboxWidget from "./CheckboxWidget"; import SelectWidget from "./SelectWidget"; export const Widgets = { CustomSelect: SelectWidget, SelectWidget, - CheckboxWidget, }; diff --git a/src/lib/stores/schema.test.ts b/src/lib/stores/schema.test.ts index 8105a6410..f406503e9 100644 --- a/src/lib/stores/schema.test.ts +++ b/src/lib/stores/schema.test.ts @@ -10,14 +10,18 @@ const codeId = "1234"; const exampleSchema = { ...schema, [SchemaProperties.ATTACHED_CODE_ID]: codeId, -} as unknown as CodeSchema; +}; beforeAll(() => { schemaStore = new SchemaStore(); }); beforeEach(() => { - schemaStore.saveNewSchema(codeHash, codeId, exampleSchema); + schemaStore.saveNewSchema( + codeHash, + codeId, + JSON.parse(JSON.stringify(schema)) as CodeSchema + ); }); describe("SchemaStore initialization", () => { @@ -28,7 +32,7 @@ describe("SchemaStore initialization", () => { describe("saveNewSchema and deleteSchema", () => { test("correctly save new schema and delete schema by codeHash", () => { - expect(schemaStore.jsonSchemas).toStrictEqual({ + expect(schemaStore.jsonSchemas).toEqual({ [codeHash]: exampleSchema, }); schemaStore.deleteSchema(codeHash); @@ -38,14 +42,12 @@ describe("saveNewSchema and deleteSchema", () => { describe("getSchemaByCodeHash", () => { test("correctly get schema by code hash", () => { - expect(schemaStore.getSchemaByCodeHash(codeHash)).toStrictEqual( - exampleSchema - ); + expect(schemaStore.getSchemaByCodeHash(codeHash)).toEqual(exampleSchema); }); test("correctly get schema by uppercase code hash", () => { - expect( - schemaStore.getSchemaByCodeHash(codeHash.toUpperCase()) - ).toStrictEqual(exampleSchema); + expect(schemaStore.getSchemaByCodeHash(codeHash.toUpperCase())).toEqual( + exampleSchema + ); }); test("return undefined on code hash not found", () => { expect(schemaStore.getSchemaByCodeHash("randomHash")).toBeUndefined(); @@ -56,34 +58,34 @@ describe("getSchemaProperty", () => { test("correctly retrieve schema property", () => { expect( schemaStore.getSchemaProperty(codeHash, SchemaProperties.CONTRACT_NAME) - ).toStrictEqual(exampleSchema.contract_name); + ).toEqual(exampleSchema.contract_name); expect( schemaStore.getSchemaProperty(codeHash, SchemaProperties.CONTRACT_VERSION) - ).toStrictEqual(exampleSchema.contract_version); + ).toEqual(exampleSchema.contract_version); expect( schemaStore.getSchemaProperty(codeHash, SchemaProperties.IDL_VERSION) - ).toStrictEqual(exampleSchema.idl_version); + ).toEqual(exampleSchema.idl_version); expect( schemaStore.getSchemaProperty(codeHash, SchemaProperties.INSTANTIATE) - ).toStrictEqual(exampleSchema.instantiate); + ).toEqual(exampleSchema.instantiate); expect( schemaStore.getSchemaProperty(codeHash, SchemaProperties.EXECUTE) - ).toStrictEqual(exampleSchema.execute); + ).toEqual(exampleSchema.execute); expect( schemaStore.getSchemaProperty(codeHash, SchemaProperties.QUERY) - ).toStrictEqual(exampleSchema.query); + ).toEqual(exampleSchema.query); expect( schemaStore.getSchemaProperty(codeHash, SchemaProperties.MIGRATE) - ).toStrictEqual(exampleSchema.migrate); + ).toEqual(exampleSchema.migrate); expect( schemaStore.getSchemaProperty(codeHash, SchemaProperties.SUDO) - ).toStrictEqual(exampleSchema.sudo); + ).toEqual(exampleSchema.sudo); expect( schemaStore.getSchemaProperty(codeHash, SchemaProperties.RESPONSES) - ).toStrictEqual(exampleSchema.responses); + ).toEqual(exampleSchema.responses); expect( schemaStore.getSchemaProperty(codeHash, SchemaProperties.ATTACHED_CODE_ID) - ).toStrictEqual(exampleSchema.attached_code_id); + ).toEqual(codeId); }); test("correctly retrieve schema property from uppercase code hash", () => { @@ -108,6 +110,7 @@ describe("getSchemaProperty", () => { describe("getQuerySchemaFormArray", () => { test("correctly get form array for query schema", () => { expect(schemaStore.getQuerySchema(codeHash)).toEqual(querySchemaOutput); + expect(schemaStore.getQuerySchema(codeHash)).toEqual(querySchemaOutput); }); test("correctly get form array for query schema from uppercase code hash", () => { @@ -124,6 +127,7 @@ describe("getQuerySchemaFormArray", () => { describe("getExecuteSchemaFormArray", () => { test("correctly get form array for execute schema", () => { expect(schemaStore.getExecuteSchema(codeHash)).toEqual(executeSchemaOutput); + expect(schemaStore.getExecuteSchema(codeHash)).toEqual(executeSchemaOutput); }); test("correctly get form array for execute schema from uppercase code hash", () => { expect(schemaStore.getExecuteSchema(codeHash.toUpperCase())).toEqual( From 553c825289eb5ff26554f3e3fc88a956d29f273c Mon Sep 17 00:00:00 2001 From: Jennie Alles Date: Fri, 25 Aug 2023 13:47:03 +0700 Subject: [PATCH 76/94] fix(components): fix view more button and txs chevron --- CHANGELOG.md | 1 + .../table/transactions/TransactionsTable.tsx | 2 +- .../pages/account-details/components/asset/index.tsx | 12 ++++++------ 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d5347db13..4420be05c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -74,6 +74,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Bug fixes +- [#503](https://github.com/alleslabs/celatone-frontend/pull/503) Fix assets `view more` button in account detail and fix txs row - [#476](https://github.com/alleslabs/celatone-frontend/pull/476) Fix terra rpc - [#473](https://github.com/alleslabs/celatone-frontend/pull/473) Fix wording on upload code modal - [#465](https://github.com/alleslabs/celatone-frontend/pull/465) Fix wrong access queryKey in validator info diff --git a/src/lib/components/table/transactions/TransactionsTable.tsx b/src/lib/components/table/transactions/TransactionsTable.tsx index 11fc8ee3e..a452f8bae 100644 --- a/src/lib/components/table/transactions/TransactionsTable.tsx +++ b/src/lib/components/table/transactions/TransactionsTable.tsx @@ -25,7 +25,7 @@ export const TransactionsTable = ({ if (isLoading) return ; if (!transactions?.length) return emptyState; - const templateColumns = `0px 190px 48px minmax(360px, 1fr) ${ + const templateColumns = `40px 190px 48px minmax(360px, 1fr) ${ showRelations ? "100px " : "" }max(190px) ${showTimestamp ? "max(230px) " : ""}${ showAction ? "100px " : "" diff --git a/src/lib/pages/account-details/components/asset/index.tsx b/src/lib/pages/account-details/components/asset/index.tsx index c69124a3b..4150029b9 100644 --- a/src/lib/pages/account-details/components/asset/index.tsx +++ b/src/lib/pages/account-details/components/asset/index.tsx @@ -192,12 +192,12 @@ export const AssetsSection = ({ )} )} - {!isMobile || - (supportedAssets && - onViewMore && - supportedAssets.length > MaxAssetsShow && ( - - ))} + {!isMobile && + supportedAssets && + onViewMore && + supportedAssets.length > MaxAssetsShow && ( + + )} ); }; From 0dd0cb7711d97e532b4f5070cf82f2e9e9c369ae Mon Sep 17 00:00:00 2001 From: Jennie Alles Date: Fri, 25 Aug 2023 15:58:34 +0700 Subject: [PATCH 77/94] fix(components): fix tx message migrate alignment --- .../pages/tx-details/components/tx-message/TxMsgExpand.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/pages/tx-details/components/tx-message/TxMsgExpand.tsx b/src/lib/pages/tx-details/components/tx-message/TxMsgExpand.tsx index de758d290..bdbb9dcf0 100644 --- a/src/lib/pages/tx-details/components/tx-message/TxMsgExpand.tsx +++ b/src/lib/pages/tx-details/components/tx-message/TxMsgExpand.tsx @@ -1,5 +1,5 @@ /* eslint-disable complexity */ -import { Flex, Tag, Text } from "@chakra-ui/react"; +import { Flex, Tag } from "@chakra-ui/react"; import type { Coin } from "@cosmjs/stargate"; import { findAttribute } from "@cosmjs/stargate/build/logs"; import type { ReactNode } from "react"; @@ -134,7 +134,7 @@ export const TxMsgExpand = ({ msgIcon = "migrate"; content = ( - Migrate + Migrate{" "} Date: Fri, 25 Aug 2023 16:02:23 +0700 Subject: [PATCH 78/94] fix(components): fix changelog --- CHANGELOG.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 12b731979..80941ce59 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -88,14 +88,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Bug fixes -<<<<<<< HEAD - [#503](https://github.com/alleslabs/celatone-frontend/pull/503) Fix assets `view more` button in account detail and fix txs row -======= - [#496](https://github.com/alleslabs/celatone-frontend/pull/496) Fix icns bech32 prefix searchbar display and schema switch highlight on query page - [#499](https://github.com/alleslabs/celatone-frontend/pull/499) Fix sometimes select widget input not full, manual schema upload max lines, and expand/collapse all chevron - [#497](https://github.com/alleslabs/celatone-frontend/pull/497) Fix stored codes route and navbar behavior from dev to normal mode - [#470](https://github.com/alleslabs/celatone-frontend/pull/470) Fix json schema array field default behavior ->>>>>>> feat/json-schema - [#476](https://github.com/alleslabs/celatone-frontend/pull/476) Fix terra rpc - [#473](https://github.com/alleslabs/celatone-frontend/pull/473) Fix wording on upload code modal - [#465](https://github.com/alleslabs/celatone-frontend/pull/465) Fix wrong access queryKey in validator info From 56736dcc22f21009a3712fb5d95805cdc4f8729e Mon Sep 17 00:00:00 2001 From: songwongtp <16089160+songwongtp@users.noreply.github.com> Date: Fri, 25 Aug 2023 16:04:59 +0700 Subject: [PATCH 79/94] fix: default null --- .../json-schema/form/templates/BaseInputTemplate.tsx | 2 +- .../json-schema/form/templates/FieldTemplate.tsx | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/lib/components/json-schema/form/templates/BaseInputTemplate.tsx b/src/lib/components/json-schema/form/templates/BaseInputTemplate.tsx index 04fed4510..d90fd0fed 100644 --- a/src/lib/components/json-schema/form/templates/BaseInputTemplate.tsx +++ b/src/lib/components/json-schema/form/templates/BaseInputTemplate.tsx @@ -97,7 +97,7 @@ const BaseInputTemplate = (props: WidgetProps) => { (!!label || !!schema.title); const handleOnChange = ({ target }: ChangeEvent) => - onChange(target.value === "" ? options.emptyValue : target.value); + onChange(target.value); const handleOnBlur = ({ target }: FocusEvent) => onBlur(id, target.value); const handleOnFocus = ({ target }: FocusEvent) => diff --git a/src/lib/components/json-schema/form/templates/FieldTemplate.tsx b/src/lib/components/json-schema/form/templates/FieldTemplate.tsx index af818b754..14117479a 100644 --- a/src/lib/components/json-schema/form/templates/FieldTemplate.tsx +++ b/src/lib/components/json-schema/form/templates/FieldTemplate.tsx @@ -35,9 +35,11 @@ export default function FieldTemplate( >("WrapIfAdditionalTemplate", registry, uiOptions); useEffect(() => { - if (required && formData === undefined) { - if (schema.type === "array") onChange([] as T); - else if (schema.type === "boolean") onChange(false as T); + if (formData === undefined) { + if (required) { + if (schema.type === "array") onChange([] as T); + else if (schema.type === "boolean") onChange(false as T); + } else onChange(null as T); } // eslint-disable-next-line react-hooks/exhaustive-deps }, [JSON.stringify(formData), onChange, required, schema.type]); From 7c71c55931c01df849dc58438a5fff4f3c01635f Mon Sep 17 00:00:00 2001 From: songwongtp <16089160+songwongtp@users.noreply.github.com> Date: Fri, 25 Aug 2023 16:27:15 +0700 Subject: [PATCH 80/94] fix: add default required string --- src/lib/components/json-schema/form/templates/FieldTemplate.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lib/components/json-schema/form/templates/FieldTemplate.tsx b/src/lib/components/json-schema/form/templates/FieldTemplate.tsx index 14117479a..3efbb369b 100644 --- a/src/lib/components/json-schema/form/templates/FieldTemplate.tsx +++ b/src/lib/components/json-schema/form/templates/FieldTemplate.tsx @@ -39,6 +39,7 @@ export default function FieldTemplate( if (required) { if (schema.type === "array") onChange([] as T); else if (schema.type === "boolean") onChange(false as T); + else if (schema.type === "string") onChange("" as T); } else onChange(null as T); } // eslint-disable-next-line react-hooks/exhaustive-deps From 858d8d17eccff06a530608b071c51e2fa0c43ac3 Mon Sep 17 00:00:00 2001 From: poomthiti Date: Fri, 25 Aug 2023 16:37:27 +0700 Subject: [PATCH 81/94] fix: change implementation of sliding box dimensions from ref to hardcode --- .../json-schema/MessageInputSwitch.tsx | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/lib/components/json-schema/MessageInputSwitch.tsx b/src/lib/components/json-schema/MessageInputSwitch.tsx index 89ccfd76f..86c4a4b24 100644 --- a/src/lib/components/json-schema/MessageInputSwitch.tsx +++ b/src/lib/components/json-schema/MessageInputSwitch.tsx @@ -1,5 +1,5 @@ import { Flex } from "@chakra-ui/react"; -import { useMemo, useRef } from "react"; +import { useMemo } from "react"; import type { CSSProperties, Dispatch, SetStateAction } from "react"; import { Tooltip } from "../Tooltip"; @@ -40,12 +40,15 @@ export const MessageInputSwitch = < isOutput = false, onTabChange, }: MessageInputSwitchProps) => { - const tabs = useMemo( + const tabs = useMemo( () => Object.values(isOutput ? OutputMessageTabs : MessageTabs), [isOutput] ); - const tabRefs = useRef<(HTMLDivElement | null)[]>([]); - const activeIndex = currentTab ? tabs.indexOf(currentTab) : -1; + const activeIndex = currentTab ? tabs.indexOf(currentTab) : 0; + + /** + * @todos current implementation of sliding box dimensions and position is hardcoded due to issues with ref, improve this later + */ return (
@@ -58,14 +61,12 @@ export const MessageInputSwitch = < position="relative" sx={{ ...(disabled ? { pointerEvents: "none", opacity: 0.3 } : {}) }} > - {tabs.map((tab, idx) => ( + {tabs.map((tab) => ( { - tabRefs.current[idx] = el; - }} cursor="pointer" p="2px 10px" + w="96px" fontSize="12px" fontWeight={700} variants={{ @@ -84,13 +85,13 @@ export const MessageInputSwitch = < ))} Date: Fri, 25 Aug 2023 16:37:28 +0700 Subject: [PATCH 82/94] fix: remove default required string --- src/lib/components/json-schema/form/templates/FieldTemplate.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/lib/components/json-schema/form/templates/FieldTemplate.tsx b/src/lib/components/json-schema/form/templates/FieldTemplate.tsx index 3efbb369b..14117479a 100644 --- a/src/lib/components/json-schema/form/templates/FieldTemplate.tsx +++ b/src/lib/components/json-schema/form/templates/FieldTemplate.tsx @@ -39,7 +39,6 @@ export default function FieldTemplate( if (required) { if (schema.type === "array") onChange([] as T); else if (schema.type === "boolean") onChange(false as T); - else if (schema.type === "string") onChange("" as T); } else onChange(null as T); } // eslint-disable-next-line react-hooks/exhaustive-deps From 41de0b456fe815302916084192741da2977cfdc0 Mon Sep 17 00:00:00 2001 From: songwongtp <16089160+songwongtp@users.noreply.github.com> Date: Fri, 25 Aug 2023 17:38:55 +0700 Subject: [PATCH 83/94] fix: default query --- src/lib/pages/query/components/SchemaQueryComponent.tsx | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/lib/pages/query/components/SchemaQueryComponent.tsx b/src/lib/pages/query/components/SchemaQueryComponent.tsx index 7dfa15884..aa8a2be50 100644 --- a/src/lib/pages/query/components/SchemaQueryComponent.tsx +++ b/src/lib/pages/query/components/SchemaQueryComponent.tsx @@ -173,14 +173,7 @@ export const SchemaQueryComponent = ({ msgSchema.title, msg, ], - async () => - queryData( - lcdEndpoint, - contractAddress, - msgSchema.inputRequired - ? msg - : JSON.stringify({ [msgSchema.title ?? ""]: {} }) - ), + async () => queryData(lcdEndpoint, contractAddress, msg), { enabled: false, retry: false, From 32f7ddc9ad2c1fd9e0d681ce04ebde354e7283eb Mon Sep 17 00:00:00 2001 From: poomthiti Date: Fri, 25 Aug 2023 17:50:46 +0700 Subject: [PATCH 84/94] fix: define attached schema tag gap --- src/lib/pages/contract-details/components/CommandSection.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/pages/contract-details/components/CommandSection.tsx b/src/lib/pages/contract-details/components/CommandSection.tsx index 7e5fc6ab6..6c3de9443 100644 --- a/src/lib/pages/contract-details/components/CommandSection.tsx +++ b/src/lib/pages/contract-details/components/CommandSection.tsx @@ -96,7 +96,7 @@ export const CommandSection = observer( {attached ? ( - + Attached JSON Schema From 5c42428a382476326469727ed90b781398ff520a Mon Sep 17 00:00:00 2001 From: songwongtp <16089160+songwongtp@users.noreply.github.com> Date: Fri, 25 Aug 2023 17:58:47 +0700 Subject: [PATCH 85/94] feat: disable response copy condition --- src/lib/pages/query/components/SchemaQueryComponent.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/pages/query/components/SchemaQueryComponent.tsx b/src/lib/pages/query/components/SchemaQueryComponent.tsx index aa8a2be50..98d87e7ea 100644 --- a/src/lib/pages/query/components/SchemaQueryComponent.tsx +++ b/src/lib/pages/query/components/SchemaQueryComponent.tsx @@ -133,7 +133,7 @@ const ReturnWidgets = ({ isOutput /> ) : ( From 5f0de1427967ca4b33516e1180bfd5e11a0602fc Mon Sep 17 00:00:00 2001 From: songwongtp <16089160+songwongtp@users.noreply.github.com> Date: Fri, 25 Aug 2023 19:17:49 +0700 Subject: [PATCH 86/94] fix: response Json schema UI --- CHANGELOG.md | 1 + .../query/components/SchemaQueryComponent.tsx | 97 ++--- .../query-schema-output.json | 336 ++++++++++-------- .../schema-test-suite/schema-example.json | 3 + src/lib/stores/schema.test.ts | 2 +- src/lib/stores/schema.ts | 113 +++--- 6 files changed, 267 insertions(+), 285 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 235d61d81..3520ecd2f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -90,6 +90,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Bug fixes +- [#504](https://github.com/alleslabs/celatone-frontend/pull/504) Fix response Json schema UI - [#503](https://github.com/alleslabs/celatone-frontend/pull/503) Fix assets `view more` button in account detail and fix txs row - [#496](https://github.com/alleslabs/celatone-frontend/pull/496) Fix icns bech32 prefix searchbar display and schema switch highlight on query page - [#499](https://github.com/alleslabs/celatone-frontend/pull/499) Fix sometimes select widget input not full, manual schema upload max lines, and expand/collapse all chevron diff --git a/src/lib/pages/query/components/SchemaQueryComponent.tsx b/src/lib/pages/query/components/SchemaQueryComponent.tsx index 98d87e7ea..5e43a2cf6 100644 --- a/src/lib/pages/query/components/SchemaQueryComponent.tsx +++ b/src/lib/pages/query/components/SchemaQueryComponent.tsx @@ -12,11 +12,9 @@ import { Box, Text, } from "@chakra-ui/react"; -import type { RJSFSchema } from "@rjsf/utils"; import { useQuery } from "@tanstack/react-query"; import type { AxiosError } from "axios"; import dynamic from "next/dynamic"; -import type { SetStateAction, Dispatch } from "react"; import { memo, useState, useEffect, useCallback } from "react"; import { CELATONE_QUERY_KEYS } from "lib/app-provider"; @@ -43,7 +41,6 @@ import type { import { dateFromNow, encode, - formatUTC, getCurrentDate, getDefaultMsg, isNonEmptyJsonData, @@ -55,18 +52,9 @@ const CodeSnippet = dynamic(() => import("lib/components/modal/CodeSnippet"), { ssr: false, }); -interface ReturnWidgetsProps { - timestamp: Option; - inputRequired: Option; - res: string; - resTab: Option; - queryError: string; - setResTab: Dispatch>>; -} - interface SchemaQueryComponentProps { msgSchema: QueryExecuteSchema; - resSchema: RJSFSchema; + resSchema: QueryExecuteSchema; contractAddress: ContractAddr; lcdEndpoint: string; walletAddress: Option; @@ -76,11 +64,6 @@ interface SchemaQueryComponentProps { const TimestampText = memo(({ timestamp }: { timestamp: Option }) => { const [, setRenderCount] = useState(0); - let text = "Query response will display here"; - if (timestamp) - text = `Last Queried at ${formatUTC(timestamp)} (${dateFromNow( - timestamp - )})`; useEffect(() => { const interval = setInterval(() => { @@ -90,59 +73,12 @@ const TimestampText = memo(({ timestamp }: { timestamp: Option }) => { }, []); return ( - - {text} + + ({timestamp ? `Last queried ${dateFromNow(timestamp)}` : "N/A"}) ); }); -const ReturnWidgets = ({ - timestamp, - inputRequired, - res, - resTab, - queryError, - setResTab, -}: ReturnWidgetsProps) => - !inputRequired ? ( - - - Return Output - - - - - ) : ( - - - - Return Output - - - - - - - - - ); - export const SchemaQueryComponent = ({ msgSchema, resSchema, @@ -268,14 +204,23 @@ export const SchemaQueryComponent = ({ )} - + + + + Return Output + + + {resSchema.description} + + + + + {queryError && ( @@ -294,7 +239,7 @@ export const SchemaQueryComponent = ({ diff --git a/src/lib/stores/schema-test-suite/query-schema-output.json b/src/lib/stores/schema-test-suite/query-schema-output.json index 998531025..c66737695 100644 --- a/src/lib/stores/schema-test-suite/query-schema-output.json +++ b/src/lib/stores/schema-test-suite/query-schema-output.json @@ -48,26 +48,28 @@ } }, { - "$schema": "http://json-schema.org/draft-07/schema#", "title": "ConfigResponse", - "type": "object", - "required": ["prefix"], - "properties": { - "owner": { - "description": "The contract's owner", - "type": ["string", "null"] - }, - "prefix": { - "description": "The address prefix of the chain this contract is deployed on", - "type": "string" + "schema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "required": ["prefix"], + "properties": { + "owner": { + "description": "The contract's owner", + "type": ["string", "null"] + }, + "prefix": { + "description": "The address prefix of the chain this contract is deployed on", + "type": "string" + }, + "proposed_new_owner": { + "description": "The contract's proposed owner", + "type": ["string", "null"] + } }, - "proposed_new_owner": { - "description": "The contract's proposed owner", - "type": ["string", "null"] - } - }, - "additionalProperties": false, - "readOnly": true + "additionalProperties": false, + "readOnly": true + } } ], [ @@ -118,51 +120,59 @@ } }, { - "$schema": "http://json-schema.org/draft-07/schema#", "title": "AddressResponseItem", - "type": "object", - "required": ["address", "address_type"], - "properties": { - "address": { - "description": "Address value", - "type": "string" + "description": "Response for get_address", + "schema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "required": ["address", "address_type"], + "properties": { + "address": { + "description": "Address value", + "type": "string" + }, + "address_type": { + "description": "The type of address", + "allOf": [ + { + "$ref": "#/definitions/MarsAddressType" + } + ] + } }, - "address_type": { - "description": "The type of address", - "allOf": [ - { - "$ref": "#/definitions/MarsAddressType" - } - ] - } - }, - "additionalProperties": false, - "definitions": { - "MarsAddressType": { - "oneOf": [ - { - "type": "string", - "enum": ["incentives", "oracle", "red_bank", "rewards_collector"] - }, - { - "description": "Protocol admin is an ICS-27 interchain account controlled by Mars Hub's x/gov module. This account will take the owner and admin roles of red-bank contracts.\n\nOwner means the account who can invoke certain priviliged execute methods on a contract, such as updating the config. Admin means the account who can migrate a contract.", - "type": "string", - "enum": ["protocol_admin"] - }, - { - "description": "The `fee_collector` module account controlled by Mars Hub's x/distribution module. Funds sent to this account will be distributed as staking rewards.\n\nNOTE: This is a Mars Hub address with the `mars` bech32 prefix, which may not be recognized by the `api.addr_validate` method.", - "type": "string", - "enum": ["fee_collector"] - }, - { - "description": "The module account controlled by the by Mars Hub's x/safety module. Funds sent to this account will be deposited into the safety fund.\n\nNOTE: This is a Mars Hub address with the `mars` bech32 prefix, which may not be recognized by the `api.addr_validate` method.", - "type": "string", - "enum": ["safety_fund"] - } - ] - } - }, - "readOnly": true + "additionalProperties": false, + "definitions": { + "MarsAddressType": { + "oneOf": [ + { + "type": "string", + "enum": [ + "incentives", + "oracle", + "red_bank", + "rewards_collector" + ] + }, + { + "description": "Protocol admin is an ICS-27 interchain account controlled by Mars Hub's x/gov module. This account will take the owner and admin roles of red-bank contracts.\n\nOwner means the account who can invoke certain priviliged execute methods on a contract, such as updating the config. Admin means the account who can migrate a contract.", + "type": "string", + "enum": ["protocol_admin"] + }, + { + "description": "The `fee_collector` module account controlled by Mars Hub's x/distribution module. Funds sent to this account will be distributed as staking rewards.\n\nNOTE: This is a Mars Hub address with the `mars` bech32 prefix, which may not be recognized by the `api.addr_validate` method.", + "type": "string", + "enum": ["fee_collector"] + }, + { + "description": "The module account controlled by the by Mars Hub's x/safety module. Funds sent to this account will be deposited into the safety fund.\n\nNOTE: This is a Mars Hub address with the `mars` bech32 prefix, which may not be recognized by the `api.addr_validate` method.", + "type": "string", + "enum": ["safety_fund"] + } + ] + } + }, + "readOnly": true + } } ], [ @@ -216,57 +226,65 @@ } }, { - "$schema": "http://json-schema.org/draft-07/schema#", "title": "Array_of_AddressResponseItem", - "type": "array", - "items": { - "$ref": "#/definitions/AddressResponseItem" - }, - "definitions": { - "AddressResponseItem": { - "type": "object", - "required": ["address", "address_type"], - "properties": { - "address": { - "description": "Address value", - "type": "string" + "description": "Response for get_addresses", + "schema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "array", + "items": { + "$ref": "#/definitions/AddressResponseItem" + }, + "definitions": { + "AddressResponseItem": { + "type": "object", + "required": ["address", "address_type"], + "properties": { + "address": { + "description": "Address value", + "type": "string" + }, + "address_type": { + "description": "The type of address", + "allOf": [ + { + "$ref": "#/definitions/MarsAddressType" + } + ] + } }, - "address_type": { - "description": "The type of address", - "allOf": [ - { - "$ref": "#/definitions/MarsAddressType" - } - ] - } + "additionalProperties": false }, - "additionalProperties": false + "MarsAddressType": { + "oneOf": [ + { + "type": "string", + "enum": [ + "incentives", + "oracle", + "red_bank", + "rewards_collector" + ] + }, + { + "description": "Protocol admin is an ICS-27 interchain account controlled by Mars Hub's x/gov module. This account will take the owner and admin roles of red-bank contracts.\n\nOwner means the account who can invoke certain priviliged execute methods on a contract, such as updating the config. Admin means the account who can migrate a contract.", + "type": "string", + "enum": ["protocol_admin"] + }, + { + "description": "The `fee_collector` module account controlled by Mars Hub's x/distribution module. Funds sent to this account will be distributed as staking rewards.\n\nNOTE: This is a Mars Hub address with the `mars` bech32 prefix, which may not be recognized by the `api.addr_validate` method.", + "type": "string", + "enum": ["fee_collector"] + }, + { + "description": "The module account controlled by the by Mars Hub's x/safety module. Funds sent to this account will be deposited into the safety fund.\n\nNOTE: This is a Mars Hub address with the `mars` bech32 prefix, which may not be recognized by the `api.addr_validate` method.", + "type": "string", + "enum": ["safety_fund"] + } + ] + } }, - "MarsAddressType": { - "oneOf": [ - { - "type": "string", - "enum": ["incentives", "oracle", "red_bank", "rewards_collector"] - }, - { - "description": "Protocol admin is an ICS-27 interchain account controlled by Mars Hub's x/gov module. This account will take the owner and admin roles of red-bank contracts.\n\nOwner means the account who can invoke certain priviliged execute methods on a contract, such as updating the config. Admin means the account who can migrate a contract.", - "type": "string", - "enum": ["protocol_admin"] - }, - { - "description": "The `fee_collector` module account controlled by Mars Hub's x/distribution module. Funds sent to this account will be distributed as staking rewards.\n\nNOTE: This is a Mars Hub address with the `mars` bech32 prefix, which may not be recognized by the `api.addr_validate` method.", - "type": "string", - "enum": ["fee_collector"] - }, - { - "description": "The module account controlled by the by Mars Hub's x/safety module. Funds sent to this account will be deposited into the safety fund.\n\nNOTE: This is a Mars Hub address with the `mars` bech32 prefix, which may not be recognized by the `api.addr_validate` method.", - "type": "string", - "enum": ["safety_fund"] - } - ] - } - }, - "readOnly": true + "readOnly": true + } } ], [ @@ -335,57 +353,65 @@ } }, { - "$schema": "http://json-schema.org/draft-07/schema#", "title": "Array_of_AddressResponseItem", - "type": "array", - "items": { - "$ref": "#/definitions/AddressResponseItem" - }, - "definitions": { - "AddressResponseItem": { - "type": "object", - "required": ["address", "address_type"], - "properties": { - "address": { - "description": "Address value", - "type": "string" + "description": "Response for get_all_addresses", + "schema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "array", + "items": { + "$ref": "#/definitions/AddressResponseItem" + }, + "definitions": { + "AddressResponseItem": { + "type": "object", + "required": ["address", "address_type"], + "properties": { + "address": { + "description": "Address value", + "type": "string" + }, + "address_type": { + "description": "The type of address", + "allOf": [ + { + "$ref": "#/definitions/MarsAddressType" + } + ] + } }, - "address_type": { - "description": "The type of address", - "allOf": [ - { - "$ref": "#/definitions/MarsAddressType" - } - ] - } + "additionalProperties": false }, - "additionalProperties": false + "MarsAddressType": { + "oneOf": [ + { + "type": "string", + "enum": [ + "incentives", + "oracle", + "red_bank", + "rewards_collector" + ] + }, + { + "description": "Protocol admin is an ICS-27 interchain account controlled by Mars Hub's x/gov module. This account will take the owner and admin roles of red-bank contracts.\n\nOwner means the account who can invoke certain priviliged execute methods on a contract, such as updating the config. Admin means the account who can migrate a contract.", + "type": "string", + "enum": ["protocol_admin"] + }, + { + "description": "The `fee_collector` module account controlled by Mars Hub's x/distribution module. Funds sent to this account will be distributed as staking rewards.\n\nNOTE: This is a Mars Hub address with the `mars` bech32 prefix, which may not be recognized by the `api.addr_validate` method.", + "type": "string", + "enum": ["fee_collector"] + }, + { + "description": "The module account controlled by the by Mars Hub's x/safety module. Funds sent to this account will be deposited into the safety fund.\n\nNOTE: This is a Mars Hub address with the `mars` bech32 prefix, which may not be recognized by the `api.addr_validate` method.", + "type": "string", + "enum": ["safety_fund"] + } + ] + } }, - "MarsAddressType": { - "oneOf": [ - { - "type": "string", - "enum": ["incentives", "oracle", "red_bank", "rewards_collector"] - }, - { - "description": "Protocol admin is an ICS-27 interchain account controlled by Mars Hub's x/gov module. This account will take the owner and admin roles of red-bank contracts.\n\nOwner means the account who can invoke certain priviliged execute methods on a contract, such as updating the config. Admin means the account who can migrate a contract.", - "type": "string", - "enum": ["protocol_admin"] - }, - { - "description": "The `fee_collector` module account controlled by Mars Hub's x/distribution module. Funds sent to this account will be distributed as staking rewards.\n\nNOTE: This is a Mars Hub address with the `mars` bech32 prefix, which may not be recognized by the `api.addr_validate` method.", - "type": "string", - "enum": ["fee_collector"] - }, - { - "description": "The module account controlled by the by Mars Hub's x/safety module. Funds sent to this account will be deposited into the safety fund.\n\nNOTE: This is a Mars Hub address with the `mars` bech32 prefix, which may not be recognized by the `api.addr_validate` method.", - "type": "string", - "enum": ["safety_fund"] - } - ] - } - }, - "readOnly": true + "readOnly": true + } } ] ] diff --git a/src/lib/stores/schema-test-suite/schema-example.json b/src/lib/stores/schema-test-suite/schema-example.json index 84ad59865..8c4e05eff 100644 --- a/src/lib/stores/schema-test-suite/schema-example.json +++ b/src/lib/stores/schema-test-suite/schema-example.json @@ -223,6 +223,7 @@ "address": { "$schema": "http://json-schema.org/draft-07/schema#", "title": "AddressResponseItem", + "description": "Response for get_address", "type": "object", "required": ["address", "address_type"], "properties": { @@ -269,6 +270,7 @@ "addresses": { "$schema": "http://json-schema.org/draft-07/schema#", "title": "Array_of_AddressResponseItem", + "description": "Response for get_addresses", "type": "array", "items": { "$ref": "#/definitions/AddressResponseItem" @@ -321,6 +323,7 @@ "all_addresses": { "$schema": "http://json-schema.org/draft-07/schema#", "title": "Array_of_AddressResponseItem", + "description": "Response for get_all_addresses", "type": "array", "items": { "$ref": "#/definitions/AddressResponseItem" diff --git a/src/lib/stores/schema.test.ts b/src/lib/stores/schema.test.ts index f406503e9..5d5ce167a 100644 --- a/src/lib/stores/schema.test.ts +++ b/src/lib/stores/schema.test.ts @@ -10,7 +10,7 @@ const codeId = "1234"; const exampleSchema = { ...schema, [SchemaProperties.ATTACHED_CODE_ID]: codeId, -}; +} as unknown as CodeSchema; beforeAll(() => { schemaStore = new SchemaStore(); diff --git a/src/lib/stores/schema.ts b/src/lib/stores/schema.ts index 34e18acae..7999053a0 100644 --- a/src/lib/stores/schema.ts +++ b/src/lib/stores/schema.ts @@ -39,7 +39,7 @@ export interface CodeSchema { [SchemaProperties.ATTACHED_CODE_ID]: string; } -export type QuerySchema = Array<[QueryExecuteSchema, JsonSchema]>; +export type QuerySchema = Array<[QueryExecuteSchema, QueryExecuteSchema]>; export type ExecuteSchema = Array; @@ -104,66 +104,73 @@ export class SchemaStore { if (!querySchema || !responsesSchema) return undefined; - return querySchema.oneOf?.reduce>( - (acc, msg) => { - const eachQuerySchema = msg as JsonSchema; - const { type, enum: enumOptions, required } = eachQuerySchema; - if (type === "string" && enumOptions) { - return [ - ...acc, - ...enumOptions.map<[QueryExecuteSchema, JsonSchema]>( - (enumOption) => [ - { - title: enumOption as string, - description: eachQuerySchema.description, - schema: { - $schema: querySchema.$schema, - type, - enum: [enumOption], - }, - inputRequired: false, - }, - { - ...responsesSchema[enumOption as string], - readOnly: true, - }, - ] - ), - ]; - } - if (required) { - const { description, ...msgSchema } = eachQuerySchema; - - const title = required[0]; - const propertyKey = eachQuerySchema.properties?.[title] as JsonSchema; - const noInputRequired = - propertyKey.type === "object" && !("properties" in propertyKey); + const getResponseSchema = ( + responseSchema: JsonSchema + ): QueryExecuteSchema => { + const { title, description, ...msgSchema } = responseSchema; + return { + title, + description, + schema: { + ...msgSchema, + readOnly: true, + }, + }; + }; - return [ - ...acc, - [ + return querySchema.oneOf?.reduce< + Array<[QueryExecuteSchema, QueryExecuteSchema]> + >((acc, msg) => { + const eachQuerySchema = msg as JsonSchema; + const { type, enum: enumOptions, required } = eachQuerySchema; + if (type === "string" && enumOptions) { + return [ + ...acc, + ...enumOptions.map<[QueryExecuteSchema, QueryExecuteSchema]>( + (enumOption) => [ { - title, - description, + title: enumOption as string, + description: eachQuerySchema.description, schema: { - ...msgSchema, $schema: querySchema.$schema, - definitions: querySchema.definitions, + type, + enum: [enumOption], }, - inputRequired: !noInputRequired, + inputRequired: false, }, - { - ...responsesSchema[required[0]], - readOnly: true, + getResponseSchema(responsesSchema[enumOption as string]), + ] + ), + ]; + } + if (required) { + const { description, ...msgSchema } = eachQuerySchema; + + const title = required[0]; + const propertyKey = eachQuerySchema.properties?.[title] as JsonSchema; + const noInputRequired = + propertyKey.type === "object" && !("properties" in propertyKey); + + return [ + ...acc, + [ + { + title, + description, + schema: { + ...msgSchema, + $schema: querySchema.$schema, + definitions: querySchema.definitions, }, - ], - ]; - } + inputRequired: !noInputRequired, + }, + getResponseSchema(responsesSchema[required[0]]), + ], + ]; + } - return acc; - }, - [] - ); + return acc; + }, []); } getExecuteSchema(codeHash: string): Option { From 41f7c0742df94fda5d8db072f5e23280bf9e02ae Mon Sep 17 00:00:00 2001 From: songwongtp <16089160+songwongtp@users.noreply.github.com> Date: Fri, 25 Aug 2023 23:19:27 +0700 Subject: [PATCH 87/94] fix: renaming variable for better context --- .../components/schema-execute/ExecuteBox.tsx | 4 +- .../query/components/SchemaQueryComponent.tsx | 6 +- src/lib/stores/schema.ts | 140 +++++++++--------- src/lib/utils/json.ts | 6 +- 4 files changed, 75 insertions(+), 81 deletions(-) diff --git a/src/lib/pages/execute/components/schema-execute/ExecuteBox.tsx b/src/lib/pages/execute/components/schema-execute/ExecuteBox.tsx index e2e041c29..4f264f729 100644 --- a/src/lib/pages/execute/components/schema-execute/ExecuteBox.tsx +++ b/src/lib/pages/execute/components/schema-execute/ExecuteBox.tsx @@ -41,7 +41,7 @@ import { useContractStore } from "lib/providers/store"; import { useTxBroadcast } from "lib/providers/tx-broadcast"; import { AmpEvent, AmpTrackAction } from "lib/services/amplitude"; import type { Activity } from "lib/stores/contract"; -import type { QueryExecuteSchema } from "lib/stores/schema"; +import type { SchemaInfo } from "lib/stores/schema"; import type { ComposedMsg, ContractAddr, @@ -62,7 +62,7 @@ const CodeSnippet = dynamic(() => import("lib/components/modal/CodeSnippet"), { }); interface ExecuteBoxProps { - msgSchema: QueryExecuteSchema; + msgSchema: SchemaInfo; contractAddress: ContractAddr; initialMsg: JsonDataType; initialFunds: Coin[]; diff --git a/src/lib/pages/query/components/SchemaQueryComponent.tsx b/src/lib/pages/query/components/SchemaQueryComponent.tsx index 5e43a2cf6..259663400 100644 --- a/src/lib/pages/query/components/SchemaQueryComponent.tsx +++ b/src/lib/pages/query/components/SchemaQueryComponent.tsx @@ -30,7 +30,7 @@ import { DEFAULT_RPC_ERROR } from "lib/data"; import { AmpTrack, AmpEvent } from "lib/services/amplitude"; import { queryData } from "lib/services/contract"; import type { Activity } from "lib/stores/contract"; -import type { QueryExecuteSchema } from "lib/stores/schema"; +import type { SchemaInfo } from "lib/stores/schema"; import type { ContractAddr, HumanAddr, @@ -53,8 +53,8 @@ const CodeSnippet = dynamic(() => import("lib/components/modal/CodeSnippet"), { }); interface SchemaQueryComponentProps { - msgSchema: QueryExecuteSchema; - resSchema: QueryExecuteSchema; + msgSchema: SchemaInfo; + resSchema: SchemaInfo; contractAddress: ContractAddr; lcdEndpoint: string; walletAddress: Option; diff --git a/src/lib/stores/schema.ts b/src/lib/stores/schema.ts index 7999053a0..654d75f36 100644 --- a/src/lib/stores/schema.ts +++ b/src/lib/stores/schema.ts @@ -19,7 +19,7 @@ export enum SchemaProperties { type NullableJsonSchema = JsonSchema | null; -export interface QueryExecuteSchema { +export interface SchemaInfo { title: Option; description: Option; schema: JsonSchema; @@ -39,9 +39,9 @@ export interface CodeSchema { [SchemaProperties.ATTACHED_CODE_ID]: string; } -export type QuerySchema = Array<[QueryExecuteSchema, QueryExecuteSchema]>; +export type QuerySchema = Array<[SchemaInfo, SchemaInfo]>; -export type ExecuteSchema = Array; +export type ExecuteSchema = Array; const normalize = (codeHash: string) => { return codeHash.toLowerCase(); @@ -104,9 +104,7 @@ export class SchemaStore { if (!querySchema || !responsesSchema) return undefined; - const getResponseSchema = ( - responseSchema: JsonSchema - ): QueryExecuteSchema => { + const getResponseSchema = (responseSchema: JsonSchema): SchemaInfo => { const { title, description, ...msgSchema } = responseSchema; return { title, @@ -118,16 +116,14 @@ export class SchemaStore { }; }; - return querySchema.oneOf?.reduce< - Array<[QueryExecuteSchema, QueryExecuteSchema]> - >((acc, msg) => { - const eachQuerySchema = msg as JsonSchema; - const { type, enum: enumOptions, required } = eachQuerySchema; - if (type === "string" && enumOptions) { - return [ - ...acc, - ...enumOptions.map<[QueryExecuteSchema, QueryExecuteSchema]>( - (enumOption) => [ + return querySchema.oneOf?.reduce>( + (acc, msg) => { + const eachQuerySchema = msg as JsonSchema; + const { type, enum: enumOptions, required } = eachQuerySchema; + if (type === "string" && enumOptions) { + return [ + ...acc, + ...enumOptions.map<[SchemaInfo, SchemaInfo]>((enumOption) => [ { title: enumOption as string, description: eachQuerySchema.description, @@ -139,38 +135,39 @@ export class SchemaStore { inputRequired: false, }, getResponseSchema(responsesSchema[enumOption as string]), - ] - ), - ]; - } - if (required) { - const { description, ...msgSchema } = eachQuerySchema; + ]), + ]; + } + if (required) { + const { description, ...msgSchema } = eachQuerySchema; - const title = required[0]; - const propertyKey = eachQuerySchema.properties?.[title] as JsonSchema; - const noInputRequired = - propertyKey.type === "object" && !("properties" in propertyKey); + const title = required[0]; + const propertyKey = eachQuerySchema.properties?.[title] as JsonSchema; + const noInputRequired = + propertyKey.type === "object" && !("properties" in propertyKey); - return [ - ...acc, - [ - { - title, - description, - schema: { - ...msgSchema, - $schema: querySchema.$schema, - definitions: querySchema.definitions, + return [ + ...acc, + [ + { + title, + description, + schema: { + ...msgSchema, + $schema: querySchema.$schema, + definitions: querySchema.definitions, + }, + inputRequired: !noInputRequired, }, - inputRequired: !noInputRequired, - }, - getResponseSchema(responsesSchema[required[0]]), - ], - ]; - } + getResponseSchema(responsesSchema[required[0]]), + ], + ]; + } - return acc; - }, []); + return acc; + }, + [] + ); } getExecuteSchema(codeHash: string): Option { @@ -181,40 +178,37 @@ export class SchemaStore { if (!executeSchema) return undefined; - return executeSchema.oneOf?.reduce>( - (acc, msg) => { - const eachExecuteSchema = msg as JsonSchema; - const { type, required, enum: enumOptions } = eachExecuteSchema; - const { description, ...msgSchema } = eachExecuteSchema; + return executeSchema.oneOf?.reduce>((acc, msg) => { + const eachExecuteSchema = msg as JsonSchema; + const { type, required, enum: enumOptions } = eachExecuteSchema; + const { description, ...msgSchema } = eachExecuteSchema; - if (type === "string" && enumOptions) { - return [ - ...acc, - ...enumOptions.map((enumOption) => ({ - title: enumOption as string, - description: eachExecuteSchema.description, - schema: { - $schema: eachExecuteSchema.$schema, - type, - enum: [enumOption], - }, - })), - ]; - } + if (type === "string" && enumOptions) { return [ ...acc, - { - title: required?.[0], - description, + ...enumOptions.map((enumOption) => ({ + title: enumOption as string, + description: eachExecuteSchema.description, schema: { - ...msgSchema, - $schema: executeSchema.$schema, - definitions: executeSchema.definitions, + $schema: eachExecuteSchema.$schema, + type, + enum: [enumOption], }, - }, + })), ]; - }, - [] - ); + } + return [ + ...acc, + { + title: required?.[0], + description, + schema: { + ...msgSchema, + $schema: executeSchema.$schema, + definitions: executeSchema.definitions, + }, + }, + ]; + }, []); } } diff --git a/src/lib/utils/json.ts b/src/lib/utils/json.ts index bdb940a94..40ab6a687 100644 --- a/src/lib/utils/json.ts +++ b/src/lib/utils/json.ts @@ -1,6 +1,6 @@ import type { RJSFSchema } from "@rjsf/utils"; -import type { QueryExecuteSchema } from "lib/stores/schema"; +import type { SchemaInfo } from "lib/stores/schema"; import type { JsonDataType } from "lib/types"; export const jsonValidate = (text: string) => { @@ -40,7 +40,7 @@ export const isNonEmptyJsonData = (jsonData: JsonDataType): boolean => { return true; }; -export const getDefaultMsg = (msgSchema: QueryExecuteSchema) => { +export const getDefaultMsg = (msgSchema: SchemaInfo) => { const { type, required, enum: enumOptions, properties } = msgSchema.schema; if (type === "object") { if (required && properties) { @@ -57,7 +57,7 @@ export const getDefaultMsg = (msgSchema: QueryExecuteSchema) => { export const resolveInitialMsg = ( initialMsg: string, - msgSchema: QueryExecuteSchema + msgSchema: SchemaInfo ) => { const parsed = parseSchemaInitialData(initialMsg); const { required, enum: enumOptions } = msgSchema.schema; From 08ce9aa80903bbd43f0394f4fab4c1b83a3259bb Mon Sep 17 00:00:00 2001 From: songwongtp <16089160+songwongtp@users.noreply.github.com> Date: Fri, 25 Aug 2023 23:21:00 +0700 Subject: [PATCH 88/94] fix: name variable --- src/lib/stores/schema.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/stores/schema.ts b/src/lib/stores/schema.ts index 654d75f36..0246da604 100644 --- a/src/lib/stores/schema.ts +++ b/src/lib/stores/schema.ts @@ -105,12 +105,12 @@ export class SchemaStore { if (!querySchema || !responsesSchema) return undefined; const getResponseSchema = (responseSchema: JsonSchema): SchemaInfo => { - const { title, description, ...msgSchema } = responseSchema; + const { title, description, ...resSchema } = responseSchema; return { title, description, schema: { - ...msgSchema, + ...resSchema, readOnly: true, }, }; From a5b47a2f7bd6f0b0f9c52b6801fd5f3d9de5ab4c Mon Sep 17 00:00:00 2001 From: poomthiti Date: Mon, 28 Aug 2023 12:05:53 +0700 Subject: [PATCH 89/94] fix: adjust attach funds form label and icon styling for schema section --- CHANGELOG.md | 1 + src/lib/components/forms/AssetInput.tsx | 6 +++++- src/lib/components/fund/index.tsx | 14 ++++++++++++-- src/lib/components/fund/selectFund.tsx | 4 ++++ 4 files changed, 22 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3520ecd2f..4da62db15 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -62,6 +62,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Improvements +- [#505](https://github.com/alleslabs/celatone-frontend/pull/505) Adjust attach funds form label and icon styling for schema section - [#501](https://github.com/alleslabs/celatone-frontend/pull/501) Add more JSON Schema state, e.g. empty object state, boolean field - [#502](https://github.com/alleslabs/celatone-frontend/pull/502) Display queried time and add json/schema output switch - [#500](https://github.com/alleslabs/celatone-frontend/pull/500) Disable estimated fee when input is invalid diff --git a/src/lib/components/forms/AssetInput.tsx b/src/lib/components/forms/AssetInput.tsx index a3605f2af..b27722b61 100644 --- a/src/lib/components/forms/AssetInput.tsx +++ b/src/lib/components/forms/AssetInput.tsx @@ -17,6 +17,7 @@ interface AssetInputProps { amountInput: JSX.Element; assetOptions: AssetOptions[]; initialSelected: string; + labelBgColor?: string; } export const AssetInput = ({ @@ -26,6 +27,7 @@ export const AssetInput = ({ amountInput: AmountInput, assetOptions, initialSelected, + labelBgColor, }: AssetInputProps) => ( {AmountInput} ); diff --git a/src/lib/components/fund/index.tsx b/src/lib/components/fund/index.tsx index b67caa303..be066af8f 100644 --- a/src/lib/components/fund/index.tsx +++ b/src/lib/components/fund/index.tsx @@ -13,6 +13,7 @@ import { AttachFundsType } from "./types"; interface AttachFundContentProps { control: Control; setValue: UseFormSetValue; + labelBgColor?: string; } const attachFundsOptions = [ @@ -33,7 +34,11 @@ const attachFundsOptions = [ }, ]; -const AttachFundContent = ({ control, setValue }: AttachFundContentProps) => { +const AttachFundContent = ({ + control, + setValue, + labelBgColor, +}: AttachFundContentProps) => { const [assetsSelect, assetsJson, attachFundsOption] = useWatch({ control, name: [ASSETS_SELECT, ASSETS_JSON_STR, ATTACH_FUNDS_OPTION], @@ -46,6 +51,7 @@ const AttachFundContent = ({ control, setValue }: AttachFundContentProps) => { assetsSelect={assetsSelect} control={control} setValue={setValue} + labelBgColor={labelBgColor} /> ); case AttachFundsType.ATTACH_FUNDS_JSON: @@ -95,6 +101,10 @@ export const AttachFund = ({ labelBgColor={labelBgColor} /> - + ); diff --git a/src/lib/components/fund/selectFund.tsx b/src/lib/components/fund/selectFund.tsx index dc7979d41..71297fb45 100644 --- a/src/lib/components/fund/selectFund.tsx +++ b/src/lib/components/fund/selectFund.tsx @@ -14,6 +14,7 @@ interface SelectFundProps { control: Control; setValue: UseFormSetValue; assetsSelect: Coin[]; + labelBgColor?: string; } /** @@ -23,6 +24,7 @@ export const SelectFund = ({ control, setValue, assetsSelect, + labelBgColor, }: SelectFundProps) => { const { data: assetInfos = [] } = useAssetInfoList(); const { fields, append, remove } = useFieldArray({ @@ -61,6 +63,7 @@ export const SelectFund = ({ } assetOptions={assetOptions} initialSelected={field.denom} + labelBgColor={labelBgColor} amountInput={ } /> From dd0a0b4ab466357f68d4cdd67a55b660a8b45602 Mon Sep 17 00:00:00 2001 From: evilpeach Date: Mon, 28 Aug 2023 17:19:56 +0700 Subject: [PATCH 90/94] fix: simulate with initial msg, retry in exe cmds --- src/lib/app-provider/queries/simulateFee.ts | 9 +++-- src/lib/hooks/useExecuteCmds.ts | 1 + .../components/schema-execute/ExecuteBox.tsx | 39 +++++++++++++------ .../components/schema-execute/index.tsx | 5 ++- 4 files changed, 39 insertions(+), 15 deletions(-) diff --git a/src/lib/app-provider/queries/simulateFee.ts b/src/lib/app-provider/queries/simulateFee.ts index e41b1e65b..ce88f63cc 100644 --- a/src/lib/app-provider/queries/simulateFee.ts +++ b/src/lib/app-provider/queries/simulateFee.ts @@ -1,5 +1,6 @@ import type { Coin } from "@cosmjs/amino"; import { SigningCosmWasmClient } from "@cosmjs/cosmwasm-stargate"; +import type { UseQueryOptions } from "@tanstack/react-query"; import { useQuery } from "@tanstack/react-query"; import { gzip } from "node-gzip"; @@ -19,6 +20,7 @@ interface SimulateQueryParams { enabled: boolean; messages: ComposedMsg[]; isDummyUser?: boolean; + retry?: UseQueryOptions["retry"]; onSuccess?: (gas: Gas | undefined) => void; onError?: (err: Error) => void; } @@ -27,6 +29,7 @@ export const useSimulateFeeQuery = ({ enabled, messages, isDummyUser, + retry = 2, onSuccess, onError, }: SimulateQueryParams) => { @@ -61,12 +64,12 @@ export const useSimulateFeeQuery = ({ CELATONE_QUERY_KEYS.SIMULATE_FEE, chain.chain_name, userAddress, - messages, + JSON.stringify(messages), rpcEndpoint, ], - queryFn: async ({ queryKey }) => simulateFn(queryKey[3] as ComposedMsg[]), + queryFn: async () => simulateFn(messages), enabled, - retry: 2, + retry, refetchOnReconnect: false, refetchOnWindowFocus: false, onSuccess, diff --git a/src/lib/hooks/useExecuteCmds.ts b/src/lib/hooks/useExecuteCmds.ts index 0d04c76a0..a7de7f29f 100644 --- a/src/lib/hooks/useExecuteCmds.ts +++ b/src/lib/hooks/useExecuteCmds.ts @@ -24,6 +24,7 @@ export const useExecuteCmds = (contractAddress: ContractAddr) => { funds: [], }), ], + retry: false, onError: (e) => { if (e.message.includes("contract: ")) { setExecCmds([]); diff --git a/src/lib/pages/execute/components/schema-execute/ExecuteBox.tsx b/src/lib/pages/execute/components/schema-execute/ExecuteBox.tsx index 4f264f729..32e8645f8 100644 --- a/src/lib/pages/execute/components/schema-execute/ExecuteBox.tsx +++ b/src/lib/pages/execute/components/schema-execute/ExecuteBox.tsx @@ -13,6 +13,7 @@ import { Text, } from "@chakra-ui/react"; import type { Coin, StdFee } from "@cosmjs/stargate"; +import type { RJSFValidationError } from "@rjsf/utils"; import dynamic from "next/dynamic"; import { useCallback, useEffect, useState, useMemo } from "react"; import { useForm, useFormState } from "react-hook-form"; @@ -98,6 +99,7 @@ export const ExecuteBox = ({ const [fee, setFee] = useState(); const [msg, setMsg] = useState(JSON.stringify(getDefaultMsg(msgSchema))); const [isValidForm, setIsValidForm] = useState(false); + const [hasInitMsg, setHasInitMsg] = useState(false); const [simulateFeeError, setSimulateFeeError] = useState(); const [composedTxMsg, setComposedTxMsg] = useState([]); const [processing, setProcessing] = useState(false); @@ -122,13 +124,15 @@ export const ExecuteBox = ({ const assetsSelectString = JSON.stringify(assetsSelect); const enableExecute = useMemo(() => { - const generalCheck = !!( + const generalCheck = Boolean( msg.trim().length && - jsonValidate(msg) === null && - address && - contractAddress && - opened && - isValidForm + jsonValidate(msg) === null && + address && + contractAddress && + opened && + // In cases where there is an initial message, `isValidForm` isn't updated upon the component's first render. + // because `isValidForm` can be updated via form's onchange event only. + (hasInitMsg || isValidForm) ); switch (attachFundsOption) { case AttachFundsType.ATTACH_FUNDS_SELECT: @@ -143,6 +147,7 @@ export const ExecuteBox = ({ address, opened, isValidForm, + hasInitMsg, contractAddress, attachFundsOption, isValidAssetsSelect, @@ -169,6 +174,17 @@ export const ExecuteBox = ({ // ------------------------------------------// // ------------------CALLBACKS---------------// // ------------------------------------------// + const handleOnChange = (data: unknown, errors: RJSFValidationError[]) => { + setIsValidForm(errors.length === 0); + setMsg(JSON.stringify(data)); + + // reset fee and error when user change the input + setSimulateFeeError(undefined); + setFee(undefined); + + // reset hasInitalMsg after user change the input + setHasInitMsg(false); + }; const proceed = useCallback(async () => { const funds = getAttachFunds( @@ -230,7 +246,11 @@ export const ExecuteBox = ({ * Handle when there is an initialMsg */ useEffect(() => { - if (isNonEmptyJsonData(initialMsg)) setMsg(JSON.stringify(initialMsg)); + if (isNonEmptyJsonData(initialMsg)) { + setMsg(JSON.stringify(initialMsg)); + setHasInitMsg(true); + } + // eslint-disable-next-line react-hooks/exhaustive-deps }, [JSON.stringify(initialMsg)]); @@ -288,10 +308,7 @@ export const ExecuteBox = ({ formId={`execute-${msgSchema.title}`} schema={msgSchema.schema} initialFormData={initialMsg} - onChange={(data, errors) => { - setIsValidForm(errors.length === 0); - setMsg(JSON.stringify(data)); - }} + onChange={handleOnChange} /> {simulateFeeError && ( diff --git a/src/lib/pages/execute/components/schema-execute/index.tsx b/src/lib/pages/execute/components/schema-execute/index.tsx index ce3d30695..7eebfc9a1 100644 --- a/src/lib/pages/execute/components/schema-execute/index.tsx +++ b/src/lib/pages/execute/components/schema-execute/index.tsx @@ -121,7 +121,10 @@ export const SchemaExecute = ({ contractAddress={contractAddress} initialMsg={parsed} initialFunds={ - parsed !== getDefaultMsg(msgSchema) ? initialFunds : [] + JSON.stringify(parsed) !== + JSON.stringify(getDefaultMsg(msgSchema)) + ? initialFunds + : [] } opened={expandedIndexes.includes(idx)} /> From bd2d8c875f95baa2e05b233fe6af9ab27fb3fcb5 Mon Sep 17 00:00:00 2001 From: evilpeach Date: Mon, 28 Aug 2023 17:21:17 +0700 Subject: [PATCH 91/94] fix: order --- src/lib/app-provider/queries/simulateFee.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/app-provider/queries/simulateFee.ts b/src/lib/app-provider/queries/simulateFee.ts index ce88f63cc..3c2d6988a 100644 --- a/src/lib/app-provider/queries/simulateFee.ts +++ b/src/lib/app-provider/queries/simulateFee.ts @@ -1,7 +1,7 @@ import type { Coin } from "@cosmjs/amino"; import { SigningCosmWasmClient } from "@cosmjs/cosmwasm-stargate"; -import type { UseQueryOptions } from "@tanstack/react-query"; import { useQuery } from "@tanstack/react-query"; +import type { UseQueryOptions } from "@tanstack/react-query"; import { gzip } from "node-gzip"; import { CELATONE_QUERY_KEYS } from "../env"; From 4d8f3ddc02c9267636977a4263cff977db5ee28e Mon Sep 17 00:00:00 2001 From: evilpeach Date: Mon, 28 Aug 2023 17:25:43 +0700 Subject: [PATCH 92/94] docs: add changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4da62db15..83a363368 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -91,6 +91,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Bug fixes +- [#506](https://github.com/alleslabs/celatone-frontend/pull/506) Fix simulation bugs - [#504](https://github.com/alleslabs/celatone-frontend/pull/504) Fix response Json schema UI - [#503](https://github.com/alleslabs/celatone-frontend/pull/503) Fix assets `view more` button in account detail and fix txs row - [#496](https://github.com/alleslabs/celatone-frontend/pull/496) Fix icns bech32 prefix searchbar display and schema switch highlight on query page From ff499d6d12b782b67a182b87e0e26e45611f70eb Mon Sep 17 00:00:00 2001 From: evilpeach Date: Mon, 28 Aug 2023 17:27:49 +0700 Subject: [PATCH 93/94] fix: redo --- src/lib/app-provider/queries/simulateFee.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/app-provider/queries/simulateFee.ts b/src/lib/app-provider/queries/simulateFee.ts index 3c2d6988a..535fcafa8 100644 --- a/src/lib/app-provider/queries/simulateFee.ts +++ b/src/lib/app-provider/queries/simulateFee.ts @@ -64,7 +64,7 @@ export const useSimulateFeeQuery = ({ CELATONE_QUERY_KEYS.SIMULATE_FEE, chain.chain_name, userAddress, - JSON.stringify(messages), + messages, rpcEndpoint, ], queryFn: async () => simulateFn(messages), From a49b95897adcca44e332e15e7591e697f4d81793 Mon Sep 17 00:00:00 2001 From: evilpeach Date: Mon, 28 Aug 2023 17:58:31 +0700 Subject: [PATCH 94/94] fix: as comments --- .../components/schema-execute/ExecuteBox.tsx | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/lib/pages/execute/components/schema-execute/ExecuteBox.tsx b/src/lib/pages/execute/components/schema-execute/ExecuteBox.tsx index 32e8645f8..397312054 100644 --- a/src/lib/pages/execute/components/schema-execute/ExecuteBox.tsx +++ b/src/lib/pages/execute/components/schema-execute/ExecuteBox.tsx @@ -174,17 +174,20 @@ export const ExecuteBox = ({ // ------------------------------------------// // ------------------CALLBACKS---------------// // ------------------------------------------// - const handleOnChange = (data: unknown, errors: RJSFValidationError[]) => { - setIsValidForm(errors.length === 0); - setMsg(JSON.stringify(data)); + const handleOnChange = useCallback( + (data: unknown, errors: RJSFValidationError[]) => { + setIsValidForm(errors.length === 0); + setMsg(JSON.stringify(data)); - // reset fee and error when user change the input - setSimulateFeeError(undefined); - setFee(undefined); + // reset fee and error when user change the input + setSimulateFeeError(undefined); + setFee(undefined); - // reset hasInitalMsg after user change the input - setHasInitMsg(false); - }; + // reset hasInitalMsg after user change the input + setHasInitMsg(false); + }, + [] + ); const proceed = useCallback(async () => { const funds = getAttachFunds(