From 8101003838f42589347aaa1aa4a20cefa1d8a839 Mon Sep 17 00:00:00 2001 From: findolor Date: Mon, 23 May 2022 08:17:46 +0300 Subject: [PATCH 01/10] Remove comment --- pages/contracts/upload.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/pages/contracts/upload.tsx b/pages/contracts/upload.tsx index e3720e58..025fce5b 100644 --- a/pages/contracts/upload.tsx +++ b/pages/contracts/upload.tsx @@ -24,7 +24,6 @@ const UploadContract: NextPage = () => { const onFileChange = (e: React.ChangeEvent) => { if (!e.target.files) return - console.log(e.target.files) setWasmFile(e.target.files[0]) } From 3901d97014c2c20e0e58ae91b0248018beb3629d Mon Sep 17 00:00:00 2001 From: findolor Date: Wed, 25 May 2022 09:52:49 +0300 Subject: [PATCH 02/10] Update testnet chain id --- config/network.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/network.ts b/config/network.ts index c926a771..bec6150c 100644 --- a/config/network.ts +++ b/config/network.ts @@ -20,7 +20,7 @@ export const mainnetConfig: AppConfig = { } export const uniTestnetConfig: AppConfig = { - chainId: 'uni-2', + chainId: 'uni-3', chainName: 'Uni', addressPrefix: 'juno', rpcUrl: 'https://rpc.uni.juno.deuslabs.fi', From bbfb3592bd05e793750daacf63a5a28a122fdff4 Mon Sep 17 00:00:00 2001 From: Lyte Date: Mon, 30 May 2022 01:41:57 -0400 Subject: [PATCH 03/10] Typo fixes (#208) * Changed "swiss knife" to "Swiss Army knife" * Removed unnecessary and unconventional "as" before "Smart Contract Dashboard" * Capitalized first letter of "Airdrops" and "Create Airdrop" page names, changed reference to Create Airdrop page to mention the page name --- pages/index.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pages/index.tsx b/pages/index.tsx index df04ab27..06110c4f 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -11,8 +11,8 @@ const HomePage: NextPage = () => {

Welcome!

- JunoTools is a swiss knife that helps you build on Juno by providing smart contract front ends. We call these - front-end apps as Smart Contact Dashboards. + JunoTools is a Swiss Army knife that helps you build on Juno by providing smart contract front ends. We call these + front-end apps Smart Contact Dashboards.


@@ -24,10 +24,10 @@ const HomePage: NextPage = () => { title="Manage Airdrops" > Looking for a fast and efficient way to airdrop your project? Or come to claim your allocation? Open the - airdrops page and view and claim your airdrop! + Airdrops page to view and claim your airdrop! - Looking to create your own airdrop for your project? Use our airdrop creation page and get started! + Looking to create your own airdrop for your project? Use our Create Airdrop page and get started! {/*
From 2509e16ae88169eda6e57e5e3fdb93757319cac4 Mon Sep 17 00:00:00 2001 From: Highlander <68139321+Highlander-maker@users.noreply.github.com> Date: Mon, 30 May 2022 10:56:58 +0100 Subject: [PATCH 04/10] Sign and verify placeholder (#207) * add placeholders for sign and verify * Fix signature placeholder * fix placeholder --- pages/sign-verify.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pages/sign-verify.tsx b/pages/sign-verify.tsx index efcd1b0f..9f75d60a 100644 --- a/pages/sign-verify.tsx +++ b/pages/sign-verify.tsx @@ -131,7 +131,7 @@ Verify tweet using:`, setMessageToSign(e.target.value) setSignedMessage(null) }} - placeholder="" + placeholder="Hello world from my wallet!" value={messageToSign} /> @@ -184,7 +184,7 @@ Verify tweet using:`, id="signer-address" name="signer-address" onChange={(e) => setSignerAddress(e.target.value)} - placeholder="" + placeholder="juno1234567890abcdefghijklmnopqrstuvwxyz..." type="text" value={signerAddress} /> @@ -197,7 +197,7 @@ Verify tweet using:`, id="message" name="message" onChange={(e) => setMessageToVerify(e.target.value)} - placeholder="" + placeholder="Hello world from my wallet!" value={messageToVerify} /> @@ -208,7 +208,7 @@ Verify tweet using:`, id="signature" name="signature" onChange={(e) => setSignature(e.target.value.replaceAll('"', ''))} - placeholder="" + placeholder="dbNQOORuE80hUpoklFJITktXU6q/Dx07iC0KFI9rPEJGXk........." value={signature} /> From df9d249265799b574f0388e0477331bd022cbacd Mon Sep 17 00:00:00 2001 From: Highlander-Maker Date: Tue, 31 May 2022 09:57:06 +0100 Subject: [PATCH 05/10] update testnet explorer --- .env.example | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.env.example b/.env.example index 2fb28a1b..d361b1c7 100644 --- a/.env.example +++ b/.env.example @@ -5,7 +5,7 @@ NEXT_PUBLIC_CW20_MERKLE_DROP_CODE_ID=8 NEXT_PUBLIC_CW20_STAKING_CODE_ID=7 NEXT_PUBLIC_API_URL=https://test-api.juno.tools/v1 -NEXT_PUBLIC_BLOCK_EXPLORER_URL=https://explorer.uni.chaintools.tech/uni +NEXT_PUBLIC_BLOCK_EXPLORER_URL=https://testnet.explorer.chaintools.tech/juno%20(uni) NEXT_PUBLIC_ESCROW_AMOUNT=1 NEXT_PUBLIC_ESCROW_CONTRACT_ADDRESS= # TODO NEXT_PUBLIC_NETWORK=testnet From c1408d0a08bdeefd619e1addb22d102aa980c1b3 Mon Sep 17 00:00:00 2001 From: findolor Date: Wed, 1 Jun 2022 17:32:43 +0300 Subject: [PATCH 06/10] Add features to keplr config --- config/keplr.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/config/keplr.ts b/config/keplr.ts index e9d55644..16370117 100644 --- a/config/keplr.ts +++ b/config/keplr.ts @@ -77,4 +77,5 @@ export const keplrConfig = (config: AppConfig): ChainInfo => ({ }, bip44: { coinType: 118 }, coinType: 118, + features: ['ibc-transfer', 'cosmwasm', 'ibc-go'], }) From 6294de80ac806dd5b4e1036d2681fa5c3ad62549 Mon Sep 17 00:00:00 2001 From: Serkan Reis Date: Mon, 6 Jun 2022 11:08:39 +0300 Subject: [PATCH 07/10] The utility function isValidAccountsFile() now includes a check for duplicate addresses --- utils/isValidAccountsFile.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/utils/isValidAccountsFile.ts b/utils/isValidAccountsFile.ts index c8bdbc2b..faaeb612 100644 --- a/utils/isValidAccountsFile.ts +++ b/utils/isValidAccountsFile.ts @@ -8,6 +8,10 @@ export interface AccountProps { } export const isValidAccountsFile = (file: AccountProps[]) => { + const duplicateCheck = file + .map((account) => account.address) + .filter((address, index, self) => self.indexOf(address) !== index) + const checks = file.map((account) => { // Check if address is valid bech32 address if (!isValidAddress(account.address)) { @@ -33,5 +37,10 @@ export const isValidAccountsFile = (file: AccountProps[]) => { return false } + if (duplicateCheck.length > 0) { + toast.error('The file contains duplicate addresses.') + return false + } + return true } From 0c623606dfb76ab1d1a298930be0f7e82cd70fc8 Mon Sep 17 00:00:00 2001 From: name-user1 <101495985+name-user1@users.noreply.github.com> Date: Thu, 9 Jun 2022 12:47:50 +0300 Subject: [PATCH 08/10] Json formatted execute operation entry changed (#206) * Json formatted execute operation entry turned into form like formatted entry * Minor fixs * Minor fixes * Minor fixes --- .../cw1/subkeys/ExecutableCombobox.tsx | 83 +++++++++++++ .../cw1/subkeys/ExecuteCombobox.hooks.ts | 7 +- components/forms/FormInput.tsx | 14 +++ pages/contracts/cw1/subkeys/execute.tsx | 76 +++++++++--- pages/contracts/cw1/subkeys/query.tsx | 114 ++++++++++++++++-- utils/contracts/cw1/subkeys/execute.ts | 42 +++++++ utils/contracts/cw1/subkeys/query.ts | 13 ++ 7 files changed, 318 insertions(+), 31 deletions(-) create mode 100644 components/contracts/cw1/subkeys/ExecutableCombobox.tsx diff --git a/components/contracts/cw1/subkeys/ExecutableCombobox.tsx b/components/contracts/cw1/subkeys/ExecutableCombobox.tsx new file mode 100644 index 00000000..a39645e1 --- /dev/null +++ b/components/contracts/cw1/subkeys/ExecutableCombobox.tsx @@ -0,0 +1,83 @@ +import { Combobox, Transition } from '@headlessui/react' +import clsx from 'clsx' +import { FormControl } from 'components/FormControl' +import { matchSorter } from 'match-sorter' +import { Fragment, useState } from 'react' +import { FaChevronDown } from 'react-icons/fa' +import type { ExecutableListItem } from 'utils/contracts/cw1/subkeys/execute' +import { EXECUTABLE_LIST } from 'utils/contracts/cw1/subkeys/execute' + +export interface ExecutableComboboxProps { + value: ExecutableListItem | null + onChange: (item: ExecutableListItem) => void +} + +export const ExecutableCombobox = ({ value, onChange }: ExecutableComboboxProps) => { + const [search, setSearch] = useState('') + + const filtered = + search === '' ? EXECUTABLE_LIST : matchSorter(EXECUTABLE_LIST, search, { keys: ['id', 'name', 'description'] }) + + return ( + +
+ val?.name ?? ''} + id="message-type" + onChange={(event) => setSearch(event.target.value)} + placeholder="Select sub message type" + /> + + + {({ open }) => + + setSearch('')} as={Fragment}> + + {filtered.length < 1 && ( + + Message type not found. + + )} + {filtered.map((entry) => ( + + clsx('flex relative flex-col py-2 px-4 space-y-1 cursor-pointer', { 'bg-plumbus-70': active }) + } + value={entry} + > + {entry.name} + {entry.description} + + ))} + + +
+
+ ) +} diff --git a/components/contracts/cw1/subkeys/ExecuteCombobox.hooks.ts b/components/contracts/cw1/subkeys/ExecuteCombobox.hooks.ts index caeacdb6..397d6356 100644 --- a/components/contracts/cw1/subkeys/ExecuteCombobox.hooks.ts +++ b/components/contracts/cw1/subkeys/ExecuteCombobox.hooks.ts @@ -1,7 +1,12 @@ import { useState } from 'react' -import type { ExecuteListItem } from 'utils/contracts/cw1/subkeys/execute' +import type { ExecutableListItem, ExecuteListItem } from 'utils/contracts/cw1/subkeys/execute' export const useExecuteComboboxState = () => { const [value, setValue] = useState(null) return { value, onChange: (item: ExecuteListItem) => setValue(item) } } + +export const useExecutableComboboxState = () => { + const [value, setValue] = useState(null) + return { value, onChange: (item: ExecutableListItem) => setValue(item) } +} diff --git a/components/forms/FormInput.tsx b/components/forms/FormInput.tsx index 94c3b474..534ae9d8 100644 --- a/components/forms/FormInput.tsx +++ b/components/forms/FormInput.tsx @@ -41,6 +41,20 @@ export const AddressInput = forwardRef( // ) +export const ValidatorAddressInput = forwardRef( + function ValidatorAddressInput(props, ref) { + return ( + + ) + }, + // +) + export const NumberInput = forwardRef( function NumberInput(props, ref) { return diff --git a/pages/contracts/cw1/subkeys/execute.tsx b/pages/contracts/cw1/subkeys/execute.tsx index 77fe70b7..4453de29 100644 --- a/pages/contracts/cw1/subkeys/execute.tsx +++ b/pages/contracts/cw1/subkeys/execute.tsx @@ -1,13 +1,16 @@ import { Button } from 'components/Button' import { ContractPageHeader } from 'components/ContractPageHeader' +import { ExecutableCombobox } from 'components/contracts/cw1/subkeys/ExecutableCombobox' import { ExecuteCombobox } from 'components/contracts/cw1/subkeys/ExecuteCombobox' -import { useExecuteComboboxState } from 'components/contracts/cw1/subkeys/ExecuteCombobox.hooks' +import { + useExecutableComboboxState, + useExecuteComboboxState, +} from 'components/contracts/cw1/subkeys/ExecuteCombobox.hooks' import { FormControl } from 'components/FormControl' import { AddressList } from 'components/forms/AddressList' import { useAddressListState } from 'components/forms/AddressList.hooks' -import { AddressInput, NumberInput } from 'components/forms/FormInput' +import { AddressInput, NumberInput, ValidatorAddressInput } from 'components/forms/FormInput' import { useInputState, useNumberInputState } from 'components/forms/FormInput.hooks' -import { JsonTextArea } from 'components/forms/FormTextArea' import { JsonPreview } from 'components/JsonPreview' import { LinkTabs } from 'components/LinkTabs' import { cw1SubkeysLinkTabs } from 'components/LinkTabs.data' @@ -24,7 +27,12 @@ import { toast } from 'react-hot-toast' import { FaArrowRight } from 'react-icons/fa' import { useMutation } from 'react-query' import type { DispatchExecuteArgs } from 'utils/contracts/cw1/subkeys/execute' -import { dispatchExecute, isEitherType, previewExecutePayload } from 'utils/contracts/cw1/subkeys/execute' +import { + dispatchExecute, + isEitherExecuteType, + isEitherType, + previewExecutePayload, +} from 'utils/contracts/cw1/subkeys/execute' import { parseJson } from 'utils/json' import { withMetadata } from 'utils/layout' import { links } from 'utils/links' @@ -64,6 +72,9 @@ const CW1SubkeysExecutePage: NextPage = () => { const comboboxState = useExecuteComboboxState() const type = comboboxState.value?.id + const exeComboboxState = useExecutableComboboxState() + const executeType = exeComboboxState.value?.id + const [permissions, setPermissions] = useState({ delegate: false, undelegate: false, @@ -85,14 +96,6 @@ const CW1SubkeysExecutePage: NextPage = () => { subtitle: 'Address of the CW1 Subkeys contract', }) - const messageState = useInputState({ - id: 'message', - name: 'message', - title: 'Message', - subtitle: 'Message to execute on the contract', - defaultValue: JSON.stringify({ key: 'value' }, null, 2), - }) - const recipientState = useInputState({ id: 'recipient-address', name: 'recipient', @@ -100,18 +103,55 @@ const CW1SubkeysExecutePage: NextPage = () => { subtitle: 'Address of the recipient', }) - const showAmountField = type && isEitherType(type, ['increase_allowance', 'decrease_allowance']) - const showMessageField = isEitherType(type, ['execute']) - const showRecipientField = isEitherType(type, ['increase_allowance', 'decrease_allowance', 'set_permissions']) + const validatorState = useInputState({ + id: 'validator-address', + name: 'validator', + title: 'Validator Address', + subtitle: 'Address of the validator', + }) + + const dstValidatorState = useInputState({ + id: 'validator-address', + name: 'validator', + title: 'Destination Validator Address', + subtitle: 'Address of the destination validator', + }) + + const showAmountField = + (type && isEitherType(type, ['increase_allowance', 'decrease_allowance'])) || + (type === 'execute' && isEitherExecuteType(executeType, ['send', 'delegate', 'undelegate', 'redelegate'])) + const showMessageField = type === 'execute' + const showRecipientField = + isEitherType(type, ['increase_allowance', 'decrease_allowance', 'set_permissions']) || + isEitherExecuteType(executeType, ['send', 'withdraw']) const showAdminsField = type === 'update_admins' const showPermissionField = type === 'set_permissions' + const showValidatorField = + type === 'execute' && isEitherExecuteType(executeType, ['delegate', 'undelegate', 'redelegate']) + const showDstValidatorField = type === 'execute' && executeType === 'redelegate' + + const messageState = () => { + switch (executeType) { + case 'send': + return `{"bank": {"send": {"to_address": "${recipientState.value}", "amount": [{"amount": "${amountState.value}", "denom": "ujunox"}]}}}` + case 'withdraw': + return `{"distribution": {"set_withdraw_address": {"address": "${recipientState.value}"}}}` + case 'redelegate': + return `{"staking": {"redelegate": {"src_validator": "${validatorState.value}","dst_validator": "${dstValidatorState.value}","amount": {"amount":"${amountState.value}", "denom": "ujunox"}}}}` + case 'delegate': + case 'undelegate': + return `{"staking": {"${executeType}": {"validator": "${validatorState.value}","amount": {"amount":"${amountState.value}", "denom": "ujunox"}}}}` + default: + return `` + } + } const messages = useMemo(() => contract?.use(contractState.value), [contract, wallet.address, contractState.value]) const payload: DispatchExecuteArgs = { amount: amountState.value.toString(), contract: contractState.value, messages, - msgs: [parseJson(messageState.value)], + msgs: [parseJson(messageState())], recipient: recipientState.value, txSigner: wallet.address, type, @@ -170,9 +210,11 @@ const CW1SubkeysExecutePage: NextPage = () => { title="Admins" /> )} + {showMessageField && } {showRecipientField && } + {showValidatorField && } + {showDstValidatorField && } {showAmountField && } - {showMessageField && } {showPermissionField && (
diff --git a/pages/contracts/cw1/subkeys/query.tsx b/pages/contracts/cw1/subkeys/query.tsx index 8042b816..a2a932c6 100644 --- a/pages/contracts/cw1/subkeys/query.tsx +++ b/pages/contracts/cw1/subkeys/query.tsx @@ -2,9 +2,8 @@ import clsx from 'clsx' import { Conditional } from 'components/Conditional' import { ContractPageHeader } from 'components/ContractPageHeader' import { FormControl } from 'components/FormControl' -import { AddressInput } from 'components/forms/FormInput' +import { AddressInput, NumberInput, ValidatorAddressInput } from 'components/forms/FormInput' import { useInputState } from 'components/forms/FormInput.hooks' -import { JsonTextArea } from 'components/forms/FormTextArea' import { JsonPreview } from 'components/JsonPreview' import { LinkTabs } from 'components/LinkTabs' import { cw1SubkeysLinkTabs } from 'components/LinkTabs.data' @@ -17,7 +16,7 @@ import { useEffect, useState } from 'react' import { toast } from 'react-hot-toast' import { useQuery } from 'react-query' import type { QueryType } from 'utils/contracts/cw1/subkeys/query' -import { dispatchQuery, QUERY_LIST } from 'utils/contracts/cw1/subkeys/query' +import { dispatchQuery, QUERY_EXECUTE_LIST, QUERY_LIST } from 'utils/contracts/cw1/subkeys/query' import { withMetadata } from 'utils/layout' import { links } from 'utils/links' @@ -41,29 +40,89 @@ const CW1SubkeysQueryPage: NextPage = () => { }) const ownerAddress = ownerState.value - const messageState = useInputState({ - id: 'message', - name: 'message', - title: 'Message', - subtitle: 'Message to check if execution is possible', - defaultValue: JSON.stringify({ key: 'value' }, null, 2), + const toAddressState = useInputState({ + id: 'recipient-address', + name: 'recipient', + title: 'Recipient Address', + subtitle: 'Address of the recipient', + }) + + const validatorState = useInputState({ + id: 'validator-address', + name: 'validator-address', + title: 'Validator Address', + subtitle: 'Address of the validator', + }) + + const dstValidatorState = useInputState({ + id: 'dst-validator-address', + name: 'dst-validator-address', + title: 'Destination Validator Address', + subtitle: 'Address of the destination validator', + }) + + const amountState = useInputState({ + id: 'amount', + name: 'amount', + title: 'Amount', + subtitle: 'Amount of tokens for allowance operations', }) const [type, setType] = useState('admins') + const [executeType, setExecuteType] = useState('send') const addressVisible = type === 'allowance' || type === 'permissions' || type === 'can_execute' + const toAddressVisible = executeType === 'send' || executeType === 'withdraw' + const validatorVisible = executeType === 'delegate' || executeType === 'undelegate' || executeType === 'redelegate' + const dstValidatorVisible = executeType === 'redelegate' + const amountVisible = + executeType === 'send' || executeType === 'delegate' || executeType === 'undelegate' || executeType === 'redelegate' const { data: response } = useQuery( - [address, type, contract, wallet, ownerAddress, messageState] as const, + [ + address, + type, + contract, + wallet, + ownerAddress, + executeType, + toAddressState, + validatorState, + dstValidatorState, + amountState, + ] as const, async ({ queryKey }) => { - const [_address, _type, _contract, _wallet, _ownerAddress, _messageState] = queryKey + const [ + _address, + _type, + _contract, + _wallet, + _ownerAddress, + _executeType, + _toAddressState, + _validatorState, + _dstValidatorState, + _amountState, + ] = queryKey const messages = contract?.use(_address) // eslint-disable-next-line @typescript-eslint/no-shadow const ownerAddress = _ownerAddress || _wallet.address + const _canExecuteMessage = () => { + switch (executeType) { + case 'send': + return `{"bank": {"send": {"to_address": "${_toAddressState.value}", "amount": [{"amount": "${_amountState.value}", "denom": "ujunox"}]}}}` + case 'withdraw': + return `{"distribution": {"set_withdraw_address": {"address": "${_toAddressState.value}"}}}` + case 'redelegate': + return `{"staking": {"${_executeType}": {"src_validator": "${_validatorState.value}+'","dst_validator": "${_dstValidatorState.value}","amount": {"amount":"${_amountState.value}", "denom": "ujunox"}}}}` + default: + return `{"staking": {"${_executeType}": {"validator": "${_validatorState.value}","amount": {"amount":"${_amountState.value}", "denom": "ujunox"}}}}` + } + } const result = await dispatchQuery({ ownerAddress, - canExecuteMessage: JSON.parse(messageState.value), + canExecuteMessage: JSON.parse(_canExecuteMessage()), messages, type, }) @@ -126,7 +185,36 @@ const CW1SubkeysQueryPage: NextPage = () => { - + + + + + + + + + + + + + + +
diff --git a/utils/contracts/cw1/subkeys/execute.ts b/utils/contracts/cw1/subkeys/execute.ts index a0cf8172..62c7ef17 100644 --- a/utils/contracts/cw1/subkeys/execute.ts +++ b/utils/contracts/cw1/subkeys/execute.ts @@ -54,6 +54,44 @@ export const EXECUTE_LIST: ExecuteListItem[] = [ }, ] +export type ExecutableType = typeof EXECUTABLE_TYPES[number] + +export const EXECUTABLE_TYPES = ['send', 'delegate', 'undelegate', 'redelegate', 'withdraw'] as const + +export interface ExecutableListItem { + id: ExecutableType + name: string + description?: string +} + +export const EXECUTABLE_LIST: ExecutableListItem[] = [ + { + id: 'send', + name: 'Send', + description: `Send tokens to given address`, + }, + { + id: 'delegate', + name: 'Delegate', + description: `Delegate to a validator address`, + }, + { + id: 'undelegate', + name: 'Undelegate', + description: `Undelegate from a previously delegated validator address`, + }, + { + id: 'redelegate', + name: 'Redelegate', + description: `Redelegate from a delegated validator address to another validator address`, + }, + { + id: 'withdraw', + name: 'Withdraw', + description: `Set withdraw address for staking rewards`, + }, +] + export interface DispatchExecuteProps { type: ExecuteType [k: string]: unknown @@ -151,3 +189,7 @@ export const previewExecutePayload = (args: DispatchExecuteArgs) => { export const isEitherType = (type: unknown, arr: T[]): type is T => { return arr.some((val) => type === val) } + +export const isEitherExecuteType = (type: unknown, arr: T[]): type is T => { + return arr.some((val) => type === val) +} diff --git a/utils/contracts/cw1/subkeys/query.ts b/utils/contracts/cw1/subkeys/query.ts index 0433b924..c3215da9 100644 --- a/utils/contracts/cw1/subkeys/query.ts +++ b/utils/contracts/cw1/subkeys/query.ts @@ -9,6 +9,11 @@ export const QUERY_TYPES = [ 'permissions', 'all_permissions', 'can_execute', + 'send', + 'delegate', + 'undelegate', + 'redelegate', + 'withdraw', ] as const export interface QueryListItem { @@ -26,6 +31,14 @@ export const QUERY_LIST: QueryListItem[] = [ { id: 'can_execute', name: 'Can Execute', description: 'Check if an address is able to execute given message' }, ] +export const QUERY_EXECUTE_LIST: QueryListItem[] = [ + { id: 'send', name: 'Send', description: 'View current admins' }, + { id: 'delegate', name: 'Delegate', description: 'View current allowance for an address' }, + { id: 'undelegate', name: 'Undelegate', description: 'View all allowances' }, + { id: 'redelegate', name: 'Redelegate', description: 'View all permissions for an address' }, + { id: 'withdraw', name: 'Withdraw', description: 'View all permissions' }, +] + export interface DispatchQueryProps { ownerAddress: string canExecuteMessage: CosmosMsg From 9fe6a420f0911eaa652ddb10f37812e83cf873da Mon Sep 17 00:00:00 2001 From: name-user1 <101495985+name-user1@users.noreply.github.com> Date: Thu, 9 Jun 2022 16:25:20 +0300 Subject: [PATCH 09/10] Walletless query (#212) * Wallet.tsx client turned into cosmwasmclient when not initialised * Minor fix * Minor fixes --- contexts/wallet.tsx | 30 ++++++++++++++++++--- contracts/cw1/subkeys/useContract.ts | 6 ++--- contracts/cw20/base/useContract.ts | 7 ++--- contracts/cw20/bonding/useContract.ts | 6 ++--- contracts/cw20/merkleAirdrop/useContract.ts | 7 ++--- contracts/cw20/staking/useContract.ts | 6 ++--- contracts/cw721/base/useContract.ts | 7 ++--- 7 files changed, 38 insertions(+), 31 deletions(-) diff --git a/contexts/wallet.tsx b/contexts/wallet.tsx index 7578cf69..b0cb1e2e 100644 --- a/contexts/wallet.tsx +++ b/contexts/wallet.tsx @@ -55,6 +55,8 @@ export interface KeplrWalletStore extends State { /** @see https://github.com/CosmosContracts/juno-tools/blob/41c256f71d2b8b55fade12fae3b8c6a493a1e3ce/contexts/wallet.tsx#L91-L93 */ readonly updateSigner: (singer: OfflineSigner) => void + + readonly setQueryClient: () => void } /** @@ -120,6 +122,15 @@ export const useWalletStore = create( }, setNetwork: (network) => set({ network }), updateSigner: (signer) => set({ signer }), + setQueryClient: async () => { + try { + const client = (await createQueryClient()) as SigningCosmWasmClient + set({ client }) + } catch (err: any) { + toast.error(err?.message) + set({ initializing: false }) + } + }, })), ) @@ -170,6 +181,7 @@ const WalletSubscription = () => { void useWalletStore.getState().connect() } else { useWalletStore.setState({ initializing: false }) + useWalletStore.getState().setQueryClient() } const listenChange = () => { @@ -198,11 +210,16 @@ const WalletSubscription = () => { (x) => x.signer, // eslint-disable-next-line @typescript-eslint/no-misused-promises async (signer) => { - if (!signer) return try { - useWalletStore.setState({ - client: await createClient({ signer }), - }) + if (!signer) { + useWalletStore.setState({ + client: (await createQueryClient()) as SigningCosmWasmClient, + }) + } else { + useWalletStore.setState({ + client: await createClient({ signer }), + }) + } } catch (error) { console.log(error) } @@ -263,6 +280,11 @@ const createClient = ({ signer }: { signer: OfflineSigner }) => { }) } +const createQueryClient = () => { + const { config } = useWalletStore.getState() + return SigningCosmWasmClient.connect(config.rpcUrl) +} + /** * Function to load keplr wallet signer. * diff --git a/contracts/cw1/subkeys/useContract.ts b/contracts/cw1/subkeys/useContract.ts index f3b1b8e3..ce882cd4 100644 --- a/contracts/cw1/subkeys/useContract.ts +++ b/contracts/cw1/subkeys/useContract.ts @@ -32,10 +32,8 @@ export function useCW1SubkeysContract(): UseCW1SubkeysContractProps { }, []) useEffect(() => { - if (wallet.initialized) { - const cw20BaseContract = initContract(wallet.getClient(), wallet.address) - setCW1Subkeys(cw20BaseContract) - } + const cw20BaseContract = initContract(wallet.getClient(), wallet.address) + setCW1Subkeys(cw20BaseContract) }, [wallet]) const updateContractAddress = (contractAddress: string) => { diff --git a/contracts/cw20/base/useContract.ts b/contracts/cw20/base/useContract.ts index c36d71c3..b7571a60 100644 --- a/contracts/cw20/base/useContract.ts +++ b/contracts/cw20/base/useContract.ts @@ -32,11 +32,8 @@ export function useCW20BaseContract(): UseCW20BaseContractProps { }, []) useEffect(() => { - if (wallet.initialized) { - const client = wallet.getClient() - const cw20BaseContract = initContract(client, wallet.address) - setCW20Base(cw20BaseContract) - } + const cw20BaseContract = initContract(wallet.getClient(), wallet.address) + setCW20Base(cw20BaseContract) }, [wallet]) const updateContractAddress = (contractAddress: string) => { diff --git a/contracts/cw20/bonding/useContract.ts b/contracts/cw20/bonding/useContract.ts index c0358f0c..b28bf14f 100644 --- a/contracts/cw20/bonding/useContract.ts +++ b/contracts/cw20/bonding/useContract.ts @@ -31,10 +31,8 @@ export function useCW20BondingContract(): UseCW20BondingContractProps { }, []) useEffect(() => { - if (wallet.initialized) { - const cw20BondingContract = initContract(wallet.getClient()) - setCW20Bonding(cw20BondingContract) - } + const cw20BondingContract = initContract(wallet.getClient()) + setCW20Bonding(cw20BondingContract) }, [wallet]) const updateContractAddress = (contractAddress: string) => { diff --git a/contracts/cw20/merkleAirdrop/useContract.ts b/contracts/cw20/merkleAirdrop/useContract.ts index 5838f0ad..a563aa58 100644 --- a/contracts/cw20/merkleAirdrop/useContract.ts +++ b/contracts/cw20/merkleAirdrop/useContract.ts @@ -32,11 +32,8 @@ export function useCW20MerkleAirdropContract(): UseCW20MerkleAirdropContractProp }, []) useEffect(() => { - if (wallet.initialized) { - const client = wallet.getClient() - const cw20MerkleAirdropContract = initContract(client, wallet.address) - setCW20MerkleAirdrop(cw20MerkleAirdropContract) - } + const cw20MerkleAirdropContract = initContract(wallet.getClient(), wallet.address) + setCW20MerkleAirdrop(cw20MerkleAirdropContract) }, [wallet]) const updateContractAddress = (contractAddress: string) => { diff --git a/contracts/cw20/staking/useContract.ts b/contracts/cw20/staking/useContract.ts index acd19fe2..b40f8b37 100644 --- a/contracts/cw20/staking/useContract.ts +++ b/contracts/cw20/staking/useContract.ts @@ -31,10 +31,8 @@ export function useCW20StakingContract(): UseCW20StakingContractProps { }, []) useEffect(() => { - if (wallet.initialized) { - const cw20StakingContract = initContract(wallet.getClient()) - setCW20Staking(cw20StakingContract) - } + const cw20StakingContract = initContract(wallet.getClient()) + setCW20Staking(cw20StakingContract) }, [wallet]) const updateContractAddress = (contractAddress: string) => { diff --git a/contracts/cw721/base/useContract.ts b/contracts/cw721/base/useContract.ts index 4fbb0aae..10e4f7a0 100644 --- a/contracts/cw721/base/useContract.ts +++ b/contracts/cw721/base/useContract.ts @@ -32,11 +32,8 @@ export function useCW721BaseContract(): UseCW721BaseContractProps { }, []) useEffect(() => { - if (wallet.initialized) { - const client = wallet.getClient() - const cw721BaseContract = initContract(client, wallet.address) - setCW721Base(cw721BaseContract) - } + const cw721BaseContract = initContract(wallet.getClient(), wallet.address) + setCW721Base(cw721BaseContract) }, [wallet]) const updateContractAddress = (contractAddress: string) => { From c1760729e44ee702c3026707217e118dddeff72c Mon Sep 17 00:00:00 2001 From: findolor Date: Thu, 9 Jun 2022 18:28:53 +0300 Subject: [PATCH 10/10] Run linter --- pages/index.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pages/index.tsx b/pages/index.tsx index 06110c4f..6dc2deea 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -11,8 +11,8 @@ const HomePage: NextPage = () => {

Welcome!

- JunoTools is a Swiss Army knife that helps you build on Juno by providing smart contract front ends. We call these - front-end apps Smart Contact Dashboards. + JunoTools is a Swiss Army knife that helps you build on Juno by providing smart contract front ends. We call + these front-end apps Smart Contact Dashboards.