polkadot-js/apps

View on GitHub
packages/page-contracts/src/Contracts/Add.tsx

Summary

Maintainability
A
3 hrs
Test Coverage
// Copyright 2017-2024 @polkadot/app-contracts authors & contributors
// SPDX-License-Identifier: Apache-2.0

import type { ActionStatus } from '@polkadot/react-components/Status/types';

import React, { useCallback, useState } from 'react';

import { AddressRow, Button, Input, Modal } from '@polkadot/react-components';
import { useApi, useNonEmptyString } from '@polkadot/react-hooks';
import { keyring } from '@polkadot/ui-keyring';

import { ABI, InputName } from '../shared/index.js';
import { useTranslation } from '../translate.js';
import useAbi from '../useAbi.js';
import ValidateAddr from './ValidateAddr.js';

interface Props {
  onClose: () => void;
}

function Add ({ onClose }: Props): React.ReactElement {
  const { t } = useTranslation();
  const { api } = useApi();
  const [address, setAddress] = useState<string | null>(null);
  const [isAddressValid, setIsAddressValid] = useState(false);
  const [name, isNameValid, setName] = useNonEmptyString('New Contract');
  const { abi, contractAbi, errorText, isAbiError, isAbiSupplied, isAbiValid, onChangeAbi, onRemoveAbi } = useAbi([null, null], null, true);

  const _onAdd = useCallback(
    (): void => {
      const status: Partial<ActionStatus> = { action: 'create' };

      if (!address || !abi || !name) {
        return;
      }

      try {
        const json = {
          contract: {
            abi,
            genesisHash: api.genesisHash.toHex()
          },
          name,
          tags: []
        };

        keyring.saveContract(address, json);

        status.account = address;
        status.status = address ? 'success' : 'error';
        status.message = 'contract added';

        onClose();
      } catch (error) {
        console.error(error);

        status.status = 'error';
        status.message = (error as Error).message;
      }
    },
    [abi, address, api, name, onClose]
  );

  const isValid = isAddressValid && isNameValid && isAbiValid;

  return (
    <Modal
      header={t('Add an existing contract')}
      onClose={onClose}
    >
      <Modal.Content>
        <AddressRow
          defaultName={name}
          isValid
          value={address || null}
        >
          <Input
            autoFocus
            isError={!isAddressValid}
            label={t('contract address')}
            onChange={setAddress}
            value={address || ''}
          />
          <ValidateAddr
            address={address}
            onChange={setIsAddressValid}
          />
          <InputName
            isContract
            isError={!isNameValid}
            onChange={setName}
            value={name || undefined}
          />
          <ABI
            contractAbi={contractAbi}
            errorText={errorText}
            isError={isAbiError || !isAbiValid}
            isSupplied={isAbiSupplied}
            isValid={isAbiValid}
            onChange={onChangeAbi}
            onRemove={onRemoveAbi}
          />
        </AddressRow>
      </Modal.Content>
      <Modal.Actions>
        <Button
          icon='save'
          isDisabled={!isValid}
          label={t('Save')}
          onClick={_onAdd}
        />
      </Modal.Actions>
    </Modal>
  );
}

export default React.memo(Add);