Skip to content

Commit a3a81e9

Browse files
authored
fix: requires selected account for interaction to be available (#552)
1 parent f1d8c8e commit a3a81e9

File tree

3 files changed

+49
-19
lines changed

3 files changed

+49
-19
lines changed

src/ui/components/contract/Interact.tsx

+20-15
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,34 @@
11
// Copyright 2022-2024 @paritytech/contracts-ui authors & contributors
22
// SPDX-License-Identifier: GPL-3.0-only
33

4-
import { useEffect, useState, useRef, useMemo } from 'react';
4+
import { useEffect, useMemo, useRef, useState } from 'react';
55
import { ResultsOutput } from './ResultsOutput';
6+
import { BN_ZERO } from 'lib/bn';
7+
import {
8+
decodeStorageDeposit,
9+
getGasLimit,
10+
getStorageDepositLimit,
11+
transformUserInput,
12+
} from 'lib/callOptions';
13+
import { getDecodedOutput } from 'lib/output';
614
import {
715
AbiMessage,
16+
Balance,
17+
CallResult,
818
ContractExecResult,
19+
ContractOptions,
920
ContractSubmittableResult,
10-
CallResult,
1121
SubmittableResult,
12-
ContractOptions,
13-
Balance,
1422
UIContract,
1523
} from 'types';
1624
import { AccountSelect } from 'ui/components/account';
17-
import { Dropdown, Button, Buttons } from 'ui/components/common';
25+
import { Button, Buttons, Dropdown } from 'ui/components/common';
1826
import { ArgumentForm, Form, FormField, OptionsForm } from 'ui/components/form';
19-
import { BN_ZERO } from 'lib/bn';
2027
import { useApi, useTransactions } from 'ui/contexts';
21-
import { useWeight, useBalance, useArgValues } from 'ui/hooks';
28+
import { useArgValues, useBalance, useWeight } from 'ui/hooks';
29+
import { useAccountAvailable } from 'ui/hooks/useAccountAvailable';
2230
import { useStorageDepositLimit } from 'ui/hooks/useStorageDepositLimit';
2331
import { createMessageOptions } from 'ui/util/dropdown';
24-
import {
25-
decodeStorageDeposit,
26-
getGasLimit,
27-
getStorageDepositLimit,
28-
transformUserInput,
29-
} from 'lib/callOptions';
30-
import { getDecodedOutput } from 'lib/output';
3132

3233
interface Props {
3334
contract: UIContract;
@@ -57,6 +58,7 @@ export const InteractTab = ({
5758
const proofSize = useWeight(outcome?.gasRequired.proofSize.toBn());
5859
const timeoutId = useRef<NodeJS.Timeout | null>(null);
5960
const isCustom = refTime.mode === 'custom' || proofSize.mode === 'custom';
61+
const isAccountAvailable = useAccountAvailable(accountId);
6062

6163
useEffect((): void => {
6264
if (!accounts || accounts.length === 0) return;
@@ -181,7 +183,8 @@ export const InteractTab = ({
181183
!proofSize.isValid ||
182184
txs[txId]?.status === 'processing' ||
183185
!!outcome?.result.isErr ||
184-
!!decodedOutput?.isError;
186+
!!decodedOutput?.isError ||
187+
isAccountAvailable === false;
185188

186189
const isDispatchable = message?.isMutating || message?.isPayable;
187190

@@ -193,7 +196,9 @@ export const InteractTab = ({
193196
className="caller mb-8"
194197
help="The sending account for this interaction. Any transaction fees will be deducted from this account."
195198
id="accountId"
199+
isError={isAccountAvailable === false}
196200
label="Caller"
201+
message="Selected Account is not available to sign extrinsics."
197202
>
198203
<AccountSelect
199204
className="mb-2"

src/ui/components/instantiate/Step1.tsx

+13-4
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,20 @@
33

44
import { useEffect, useState } from 'react';
55
import { useParams } from 'react-router';
6+
import { AccountSelect } from '../account';
67
import { Button, Buttons } from '../common/Button';
7-
import { Input, InputFile, Form, FormField, useMetadataField, getValidation } from '../form';
88
import { Loader } from '../common/Loader';
9-
import { AccountSelect } from '../account';
9+
import { Form, FormField, Input, InputFile, getValidation, useMetadataField } from '../form';
1010
import { MessageDocs } from '../message';
1111
import { Metadata } from '../metadata';
1212
import { CodeHash } from './CodeHash';
13-
import { useNonEmptyString } from 'ui/hooks/useNonEmptyString';
1413
import { useApi, useDatabase, useInstantiate } from 'ui/contexts';
1514
import { useDbQuery } from 'ui/hooks';
15+
import { useNonEmptyString } from 'ui/hooks/useNonEmptyString';
1616

1717
import { fileToFileState } from 'lib/fileToFileState';
1818
import { getContractFromPatron } from 'lib/getContractFromPatron';
19+
import { useAccountAvailable } from 'ui/hooks/useAccountAvailable';
1920

2021
export function Step1() {
2122
const { codeHash: codeHashUrlParam } = useParams<{ codeHash: string }>();
@@ -29,6 +30,7 @@ export function Step1() {
2930
const { setStep, setData, data, step } = useInstantiate();
3031

3132
const [accountId, setAccountId] = useState('');
33+
const isAccountAvailable = useAccountAvailable(accountId);
3234
const { value: name, onChange: setName, ...nameValidation } = useNonEmptyString();
3335

3436
const {
@@ -90,6 +92,8 @@ export function Step1() {
9092
help="The account to use for this instantiation. The fees and storage deposit will be deducted from this account."
9193
id="accountId"
9294
label="Account"
95+
isError={isAccountAvailable === false}
96+
message="Selected Account is not available to sign extrinsics."
9397
>
9498
<AccountSelect
9599
className="mb-2"
@@ -185,7 +189,12 @@ export function Step1() {
185189
<Buttons>
186190
<Button
187191
data-cy="next-btn"
188-
isDisabled={!metadata || !nameValidation.isValid || !metadataValidation.isValid}
192+
isDisabled={
193+
!metadata ||
194+
!nameValidation.isValid ||
195+
!metadataValidation.isValid ||
196+
isAccountAvailable === false
197+
}
189198
onClick={submitStep1}
190199
variant="primary"
191200
>

src/ui/hooks/useAccountAvailable.ts

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Copyright 2022-2024 @paritytech/contracts-ui authors & contributors
2+
// SPDX-License-Identifier: GPL-3.0-only
3+
4+
import { keyring } from '@polkadot/ui-keyring';
5+
import { useMemo } from 'react';
6+
7+
export const useAccountAvailable = (accountId?: string): boolean | undefined =>
8+
useMemo(() => {
9+
if (accountId === '' || accountId === undefined) return undefined;
10+
try {
11+
keyring.getPair(accountId);
12+
return true;
13+
} catch {
14+
return false;
15+
}
16+
}, [accountId]);

0 commit comments

Comments
 (0)