Browse Source

JSON v3 support (#3256)

* JSON v3 support

* Update deps

* isBusy adjustments

* Cleanup import

* Linting

* trigger

* Derive fixed, remove unused styles

* Backup adjustments

* Overlay & spinner ordering
Jaco Greeff 4 years ago
parent
commit
51bceafb03

+ 2 - 2
.123trigger

@@ -1,2 +1,2 @@
-10
-0.45.2
+11
+0.45.2

+ 3 - 3
package.json

@@ -35,10 +35,10 @@
   "resolutions": {
     "@polkadot/api": "^1.26.0-beta.1",
     "@polkadot/api-contract": "^1.26.0-beta.1",
-    "@polkadot/keyring": "^2.18.1",
+    "@polkadot/keyring": "^3.0.0-beta.3",
     "@polkadot/types": "^1.26.0-beta.1",
-    "@polkadot/util": "^2.18.1",
-    "@polkadot/util-crypto": "^2.18.1",
+    "@polkadot/util": "^3.0.0-beta.3",
+    "@polkadot/util-crypto": "^3.0.0-beta.3",
     "@polkadot/wasm-crypto": "^1.2.1",
     "babel-core": "^7.0.0-bridge.0"
   },

+ 1 - 1
packages/apps/webpack.base.config.js

@@ -149,7 +149,7 @@ function createWebpack (ENV, context) {
           ...mapChunks('polkadot', [
             /* 00 */ /node_modules\/@polkadot\/(wasm)/,
             /* 01 */ /node_modules\/(@polkadot\/(api|metadata|rpc|types))/,
-            /* 02 */ /node_modules\/(@polkadot\/(extension|keyring|react|ui|util|vanitygen)|@edgeware|@ledgerhq|@zondax|edgeware)/
+            /* 02 */ /node_modules\/(@polkadot\/(extension|keyring|react|ui|util|vanitygen)|@acala-network|@edgeware|@ledgerhq|@open-web3|@zondax|edgeware)/
           ]),
           ...mapChunks('react', [
             /* 00 */ /node_modules\/(@fortawesome)/,

+ 46 - 69
packages/page-accounts/src/Accounts/modals/Backup.tsx

@@ -3,7 +3,7 @@
 // of the Apache-2.0 license. See the LICENSE file for details.
 
 import FileSaver from 'file-saver';
-import React, { useCallback, useMemo, useState } from 'react';
+import React, { useCallback, useState } from 'react';
 import { AddressRow, Button, Modal, Password } from '@polkadot/react-components';
 import keyring from '@polkadot/ui-keyring';
 
@@ -14,52 +14,42 @@ interface Props {
   address: string;
 }
 
-interface ContentProps {
-  address: string;
-  doBackup: () => void;
-  isPassTouched: boolean;
-  isPassValid: boolean;
-  onChangePass: (password: string) => void;
-  password: string;
-}
-
 function Backup ({ address, onClose }: Props): React.ReactElement<Props> {
   const { t } = useTranslation();
-  const [password, setPassword] = useState('');
-  const [isPassTouched, setIsPassTouched] = useState(false);
+  const [isBusy, setIsBusy] = useState(false);
+  const [{ isPassTouched, password }, setPassword] = useState({ isPassTouched: false, password: '' });
   const [backupFailed, setBackupFailed] = useState(false);
-  const isPassValid = useMemo(() =>
-    keyring.isPassValid(password) && !backupFailed,
-  [password, backupFailed]);
+  const isPassValid = !backupFailed && keyring.isPassValid(password);
 
   const _onChangePass = useCallback(
-    (value: string): void => {
-      if (!isPassTouched) {
-        setIsPassTouched(true);
-      }
-
+    (password: string): void => {
       setBackupFailed(false);
-      setPassword(value);
+      setPassword({ isPassTouched: true, password });
     },
-    [isPassTouched]
+    []
   );
 
   const _doBackup = useCallback(
     (): void => {
-      try {
-        const addressKeyring = address && keyring.getPair(address);
-        const json = addressKeyring && keyring.backupAccount(addressKeyring, password);
-        const blob = new Blob([JSON.stringify(json)], { type: 'application/json; charset=utf-8' });
+      setIsBusy(true);
+      setTimeout((): void => {
+        try {
+          const addressKeyring = address && keyring.getPair(address);
+          const json = addressKeyring && keyring.backupAccount(addressKeyring, password);
+          const blob = new Blob([JSON.stringify(json)], { type: 'application/json; charset=utf-8' });
 
-        FileSaver.saveAs(blob, `${address}.json`);
-      } catch (error) {
-        setBackupFailed(true);
-        console.error(error);
+          FileSaver.saveAs(blob, `${address}.json`);
+        } catch (error) {
+          setBackupFailed(true);
+          setIsBusy(false);
+          console.error(error);
 
-        return;
-      }
+          return;
+        }
 
-      onClose();
+        setIsBusy(false);
+        onClose();
+      }, 0);
     },
     [address, onClose, password]
   );
@@ -69,18 +59,33 @@ function Backup ({ address, onClose }: Props): React.ReactElement<Props> {
       className='app--accounts-Modal'
       header={t<string>('Backup account')}
     >
-      <Content
-        address={address}
-        doBackup={_doBackup}
-        isPassTouched={isPassTouched}
-        isPassValid={isPassValid}
-        onChangePass={_onChangePass}
-        password={password}
-      />
+      <Modal.Content>
+        <AddressRow
+          isInline
+          value={address}
+        >
+          <p>{t<string>('An encrypted backup file will be created once you have pressed the "Download" button. This can be used to re-import your account on any other machine.')}</p>
+          <p>{t<string>('Save this backup file in a secure location. Additionally, the password associated with this account is needed together with this backup file in order to restore your account.')}</p>
+          <div>
+            <Password
+              autoFocus
+              help={t<string>('The account password as specified when creating the account. This is used to encrypt the backup file and subsequently decrypt it when restoring the account.')}
+              isError={isPassTouched && !isPassValid}
+              label={t<string>('password')}
+              onChange={_onChangePass}
+              onEnter={_doBackup}
+              tabIndex={0}
+              value={password}
+            />
+          </div>
+        </AddressRow>
+      </Modal.Content>
       <Modal.Actions onCancel={onClose}>
         <Button
           icon='download'
+          isBusy={isBusy}
           isDisabled={!isPassValid}
+          isPrimary
           label={t<string>('Download')}
           onClick={_doBackup}
         />
@@ -89,32 +94,4 @@ function Backup ({ address, onClose }: Props): React.ReactElement<Props> {
   );
 }
 
-function Content ({ address, doBackup, isPassTouched, isPassValid, onChangePass, password }: ContentProps): React.ReactElement<ContentProps> {
-  const { t } = useTranslation();
-
-  return (
-    <Modal.Content>
-      <AddressRow
-        isInline
-        value={address}
-      >
-        <p>{t<string>('An encrypted backup file will be created once you have pressed the "Download" button. This can be used to re-import your account on any other machine.')}</p>
-        <p>{t<string>('Save this backup file in a secure location. Additionally, the password associated with this account is needed together with this backup file in order to restore your account.')}</p>
-        <div>
-          <Password
-            autoFocus
-            help={t<string>('The account password as specified when creating the account. This is used to encrypt the backup file and subsequently decrypt it when restoring the account.')}
-            isError={isPassTouched && !isPassValid}
-            label={t<string>('password')}
-            onChange={onChangePass}
-            onEnter={doBackup}
-            tabIndex={0}
-            value={password}
-          />
-        </div>
-      </AddressRow>
-    </Modal.Content>
-  );
-}
-
 export default React.memo(Backup);

+ 25 - 18
packages/page-accounts/src/Accounts/modals/ChangePass.tsx

@@ -26,6 +26,7 @@ interface OldPass {
 
 function ChangePass ({ address, className = '', onClose }: Props): React.ReactElement<Props> {
   const { t } = useTranslation();
+  const [isBusy, setIsBusy] = useState(false);
   const [newPass1, setNewPass1] = useState<NewPass>({ isValid: false, password: '' });
   const [newPass2, setNewPass2] = useState<NewPass>({ isValid: false, password: '' });
   const [{ isOldValid, oldPass }, setOldPass] = useState<OldPass>({ isOldValid: false, oldPass: '' });
@@ -43,8 +44,7 @@ function ChangePass ({ address, className = '', onClose }: Props): React.ReactEl
   );
 
   const _onChangeOld = useCallback(
-    (oldPass: string) =>
-      setOldPass({ isOldValid: keyring.isPassValid(oldPass), oldPass }),
+    (oldPass: string) => setOldPass({ isOldValid: keyring.isPassValid(oldPass), oldPass }),
     []
   );
 
@@ -56,27 +56,33 @@ function ChangePass ({ address, className = '', onClose }: Props): React.ReactEl
         return;
       }
 
-      try {
-        if (!account.isLocked) {
-          account.lock();
-        }
+      setIsBusy(true);
+      setTimeout((): void => {
+        try {
+          if (!account.isLocked) {
+            account.lock();
+          }
 
-        account.decodePkcs8(oldPass);
-      } catch (error) {
-        setOldPass((state: OldPass) => ({ ...state, isOldValid: false }));
+          account.decodePkcs8(oldPass);
+        } catch (error) {
+          setOldPass((state: OldPass) => ({ ...state, isOldValid: false }));
+          setIsBusy(false);
 
-        return;
-      }
+          return;
+        }
 
-      try {
-        keyring.encryptAccount(account, newPass1.password);
-      } catch (error) {
-        setNewPass2((state: NewPass) => ({ ...state, isValid: false }));
+        try {
+          keyring.encryptAccount(account, newPass1.password);
+        } catch (error) {
+          setNewPass2((state: NewPass) => ({ ...state, isValid: false }));
+          setIsBusy(false);
 
-        return;
-      }
+          return;
+        }
 
-      onClose();
+        setIsBusy(false);
+        onClose();
+      }, 0);
     },
     [address, newPass1, oldPass, onClose]
   );
@@ -126,6 +132,7 @@ function ChangePass ({ address, className = '', onClose }: Props): React.ReactEl
       <Modal.Actions onCancel={onClose}>
         <Button
           icon='sign-in-alt'
+          isBusy={isBusy}
           isDisabled={!newPass1.isValid || !newPass2.isValid || !isOldValid}
           isPrimary
           label={t<string>('Change')}

+ 12 - 5
packages/page-accounts/src/Accounts/modals/Create.tsx

@@ -168,6 +168,7 @@ function Create ({ className = '', onClose, onStatusChange, seed: propsSeed, typ
   const { api, isDevelopment } = useApi();
   const [{ address, deriveError, derivePath, isSeedValid, pairType, seed, seedType }, setAddress] = useState<AddressState>(generateSeed(propsSeed, '', propsSeed ? 'raw' : 'bip', propsType));
   const [isConfirmationOpen, toggleConfirmation] = useToggle();
+  const [isBusy, setIsBusy] = useState(false);
   const [{ isNameValid, name }, setName] = useState({ isNameValid: false, name: '' });
   const [{ isPasswordValid, password }, setPassword] = useState({ isPasswordValid: false, password: '' });
   const isValid = !!address && !deriveError && isNameValid && isPasswordValid && isSeedValid;
@@ -220,12 +221,16 @@ function Create ({ className = '', onClose, onStatusChange, seed: propsSeed, typ
         return;
       }
 
-      const options = { genesisHash: isDevelopment ? undefined : api.genesisHash.toString(), name: name.trim() };
-      const status = createAccount(`${seed}${derivePath}`, pairType, options, password, t<string>('created account'));
+      setIsBusy(true);
+      setTimeout((): void => {
+        const options = { genesisHash: isDevelopment ? undefined : api.genesisHash.toString(), name: name.trim() };
+        const status = createAccount(`${seed}${derivePath}`, pairType, options, password, t<string>('created account'));
 
-      toggleConfirmation();
-      onStatusChange(status);
-      onClose();
+        toggleConfirmation();
+        onStatusChange(status);
+        setIsBusy(false);
+        onClose();
+      }, 0);
     },
     [api, derivePath, isDevelopment, isValid, name, onClose, onStatusChange, pairType, password, seed, t, toggleConfirmation]
   );
@@ -239,6 +244,7 @@ function Create ({ className = '', onClose, onStatusChange, seed: propsSeed, typ
       {address && isConfirmationOpen && (
         <CreateConfirmation
           address={address}
+          isBusy={isBusy}
           name={name}
           onClose={toggleConfirmation}
           onCommit={_onCommit}
@@ -355,6 +361,7 @@ function Create ({ className = '', onClose, onStatusChange, seed: propsSeed, typ
       <Modal.Actions onCancel={onClose}>
         <Button
           icon='plus'
+          isBusy={isBusy}
           isDisabled={!isValid}
           isPrimary
           label={t<string>('Save')}

+ 3 - 1
packages/page-accounts/src/Accounts/modals/CreateConfirmation.tsx

@@ -9,12 +9,13 @@ import { useTranslation } from '../../translate';
 
 interface Props {
   address: string;
+  isBusy: boolean;
   name: string;
   onClose: () => void;
   onCommit: () => void;
 }
 
-function CreateConfirmation ({ address, name, onClose, onCommit }: Props): React.ReactElement<Props> | null {
+function CreateConfirmation ({ address, isBusy, name, onClose, onCommit }: Props): React.ReactElement<Props> | null {
   const { t } = useTranslation();
 
   return (
@@ -33,6 +34,7 @@ function CreateConfirmation ({ address, name, onClose, onCommit }: Props): React
       <Modal.Actions onCancel={onClose}>
         <Button
           icon='plus'
+          isBusy={isBusy}
           isPrimary
           label={t<string>('Create and backup account')}
           onClick={onCommit}

+ 35 - 14
packages/page-accounts/src/Accounts/modals/Derive.tsx

@@ -78,13 +78,14 @@ function Derive ({ className = '', from, onClose }: Props): React.ReactElement {
   const { api, isDevelopment } = useApi();
   const { queueAction } = useContext(StatusContext);
   const [source] = useState(keyring.getPair(from));
+  const [isBusy, setIsBusy] = useState(false);
   const [{ address, deriveError }, setDerive] = useState<DeriveAddress>({ address: null, deriveError: null });
   const [isConfirmationOpen, toggleConfirmation] = useToggle();
   const [{ isLocked, lockedError }, setIsLocked] = useState<LockState>({ isLocked: source.isLocked, lockedError: null });
   const [{ isNameValid, name }, setName] = useState({ isNameValid: false, name: '' });
   const [{ isPassValid, password }, setPassword] = useState({ isPassValid: false, password: '' });
   const [{ isPass2Valid, password2 }, setPassword2] = useState({ isPass2Valid: false, password2: '' });
-  const [rootPass, setRootPass] = useState('');
+  const [{ isRootValid, rootPass }, setRootPass] = useState({ isRootValid: false, rootPass: '' });
   const [suri, setSuri] = useState('');
   const debouncedSuri = useDebounce(suri);
   const isValid = !!address && !deriveError && isNameValid && isPassValid && isPass2Valid;
@@ -123,15 +124,28 @@ function Derive ({ className = '', from, onClose }: Props): React.ReactElement {
     [password]
   );
 
+  const _onChangeRootPass = useCallback(
+    (rootPass: string): void => {
+      setRootPass({ isRootValid: !!rootPass, rootPass });
+      setIsLocked(({ isLocked }) => ({ isLocked, lockedError: null }));
+    },
+    []
+  );
+
   const _onUnlock = useCallback(
     (): void => {
-      try {
-        source.decodePkcs8(rootPass);
-        setIsLocked({ isLocked: source.isLocked, lockedError: null });
-      } catch (error) {
-        console.error(error);
-        setIsLocked({ isLocked: true, lockedError: (error as Error).message });
-      }
+      setIsBusy(true);
+      setTimeout((): void => {
+        try {
+          source.decodePkcs8(rootPass);
+          setIsLocked({ isLocked: source.isLocked, lockedError: null });
+        } catch (error) {
+          console.error(error);
+          setIsLocked({ isLocked: true, lockedError: (error as Error).message });
+        }
+
+        setIsBusy(false);
+      }, 0);
     },
     [rootPass, source]
   );
@@ -142,11 +156,15 @@ function Derive ({ className = '', from, onClose }: Props): React.ReactElement {
         return;
       }
 
-      const status = createAccount(source, suri, name, password, t<string>('created account'), isDevelopment ? undefined : api.genesisHash.toString());
+      setIsBusy(true);
+      setTimeout((): void => {
+        const status = createAccount(source, suri, name, password, t<string>('created account'), isDevelopment ? undefined : api.genesisHash.toString());
 
-      toggleConfirmation();
-      queueAction(status);
-      onClose();
+        toggleConfirmation();
+        queueAction(status);
+        setIsBusy(false);
+        onClose();
+      }, 0);
     },
     [api, isDevelopment, isValid, name, onClose, password, queueAction, source, suri, t, toggleConfirmation]
   );
@@ -168,6 +186,7 @@ function Derive ({ className = '', from, onClose }: Props): React.ReactElement {
       {address && isConfirmationOpen && (
         <CreateConfirmation
           address={address}
+          isBusy={isBusy}
           name={name}
           onClose={toggleConfirmation}
           onCommit={_onCommit}
@@ -182,7 +201,7 @@ function Derive ({ className = '', from, onClose }: Props): React.ReactElement {
               help={t<string>('The password to unlock the selected account.')}
               isError={!!lockedError}
               label={t<string>('password')}
-              onChange={setRootPass}
+              onChange={_onChangeRootPass}
               value={rootPass}
             />
           </>
@@ -237,7 +256,8 @@ function Derive ({ className = '', from, onClose }: Props): React.ReactElement {
           ? (
             <Button
               icon='lock'
-              isDisabled={!rootPass}
+              isBusy={isBusy}
+              isDisabled={!isRootValid}
               isPrimary
               label={t<string>('Unlock')}
               onClick={_onUnlock}
@@ -246,6 +266,7 @@ function Derive ({ className = '', from, onClose }: Props): React.ReactElement {
           : (
             <Button
               icon='plus'
+              isBusy={isBusy}
               isDisabled={!isValid}
               isPrimary
               label={t<string>('Save')}

+ 28 - 24
packages/page-accounts/src/Accounts/modals/Import.tsx

@@ -8,7 +8,7 @@ import { ModalProps } from '../../types';
 
 import React, { useCallback, useState } from 'react';
 import { AddressRow, Button, InputAddress, InputFile, Modal, Password } from '@polkadot/react-components';
-import { isHex, isObject, u8aToString } from '@polkadot/util';
+import { isObject, u8aToString } from '@polkadot/util';
 import keyring from '@polkadot/ui-keyring';
 
 import { useTranslation } from '../../translate';
@@ -37,7 +37,7 @@ function parseFile (file: Uint8Array): FileState {
     const json = JSON.parse(u8aToString(file)) as KeyringPair$Json;
     const publicKey = keyring.decodeAddress(json.address, true);
     const address = keyring.encodeAddress(publicKey);
-    const isFileValid = publicKey.length === 32 && isHex(json.encoded) && isObject(json.meta) && (
+    const isFileValid = publicKey.length === 32 && !!json.encoded && isObject(json.meta) && (
       Array.isArray(json.encoding.content)
         ? json.encoding.content[0] === 'pkcs8'
         : json.encoding.content === 'pkcs8'
@@ -53,18 +53,17 @@ function parseFile (file: Uint8Array): FileState {
 
 function Import ({ className = '', onClose, onStatusChange }: Props): React.ReactElement<Props> {
   const { t } = useTranslation();
+  const [isBusy, setIsBusy] = useState(false);
   const [{ address, isFileValid, json }, setFile] = useState<FileState>({ address: null, isFileValid: false, json: null });
   const [{ isPassValid, password }, setPass] = useState<PassState>({ isPassValid: false, password: '' });
 
   const _onChangeFile = useCallback(
-    (file: Uint8Array): void =>
-      setFile(parseFile(file)),
+    (file: Uint8Array) => setFile(parseFile(file)),
     []
   );
 
   const _onChangePass = useCallback(
-    (password: string): void =>
-      setPass({ isPassValid: keyring.isPassValid(password), password }),
+    (password: string) => setPass({ isPassValid: keyring.isPassValid(password), password }),
     []
   );
 
@@ -74,30 +73,34 @@ function Import ({ className = '', onClose, onStatusChange }: Props): React.Reac
         return;
       }
 
-      const status: Partial<ActionStatus> = { action: 'restore' };
+      setIsBusy(true);
+      setTimeout((): void => {
+        const status: Partial<ActionStatus> = { action: 'restore' };
 
-      try {
-        const pair = keyring.restoreAccount(json, password);
-        const { address } = pair;
+        try {
+          const pair = keyring.restoreAccount(json, password);
+          const { address } = pair;
 
-        status.status = pair ? 'success' : 'error';
-        status.account = address;
-        status.message = t<string>('account restored');
+          status.status = pair ? 'success' : 'error';
+          status.account = address;
+          status.message = t<string>('account restored');
 
-        InputAddress.setLastValue('account', address);
-      } catch (error) {
-        setPass((state: PassState) => ({ ...state, isPassValid: false }));
+          InputAddress.setLastValue('account', address);
+        } catch (error) {
+          setPass((state: PassState) => ({ ...state, isPassValid: false }));
 
-        status.status = 'error';
-        status.message = (error as Error).message;
-        console.error(error);
-      }
+          status.status = 'error';
+          status.message = (error as Error).message;
+          console.error(error);
+        }
 
-      onStatusChange(status as ActionStatus);
+        setIsBusy(false);
+        onStatusChange(status as ActionStatus);
 
-      if (status.status !== 'error') {
-        onClose();
-      }
+        if (status.status !== 'error') {
+          onClose();
+        }
+      }, 0);
     },
     [json, onClose, onStatusChange, password, t]
   );
@@ -155,6 +158,7 @@ function Import ({ className = '', onClose, onStatusChange }: Props): React.Reac
       <Modal.Actions onCancel={onClose}>
         <Button
           icon='sync'
+          isBusy={isBusy}
           isDisabled={!isFileValid || !isPassValid}
           isPrimary
           label={t<string>('Restore')}

+ 0 - 1
packages/page-accounts/src/Sidebar/Sidebar.tsx

@@ -136,7 +136,6 @@ function Sidebar ({ address, className = '', onClose, onUpdateName }: Props): Re
               <Button
                 className='ui--AddressMenu-button'
                 icon='ban'
-                isAnimated
                 isNegative={isHoveringButton}
                 isPositive={!isHoveringButton}
                 label={t<string>('Remove')}

+ 2 - 2
packages/page-accounts/src/Vanity/index.tsx

@@ -108,7 +108,7 @@ function VanityApp ({ className = '', onStatusChange }: Props): React.ReactEleme
         return _checkMatches();
       }
 
-      setImmediate((): void => {
+      setTimeout((): void => {
         if (mountedRef.current) {
           if (results.current.length === 25) {
             _checkMatches();
@@ -120,7 +120,7 @@ function VanityApp ({ className = '', onStatusChange }: Props): React.ReactEleme
 
           _executeGeneration();
         }
-      });
+      }, 0);
     },
     [_checkMatches, match, mountedRef, runningRef, type, withCase]
   );

+ 14 - 6
packages/page-toolbox/src/Unlock.tsx

@@ -17,6 +17,7 @@ interface Props {
 
 function Unlock ({ onClose, onUnlock, pair }: Props): React.ReactElement<Props> | null {
   const { t } = useTranslation();
+  const [isBusy, setIsBusy] = useState(false);
   const [address, setAddress] = useState('');
   const [password, setPassword] = useState('');
   const [unlockError, setUnlockError] = useState<string | null>(null);
@@ -35,13 +36,19 @@ function Unlock ({ onClose, onUnlock, pair }: Props): React.ReactElement<Props>
         return;
       }
 
-      try {
-        pair.decodePkcs8(password);
-      } catch (error) {
-        return setUnlockError((error as Error).message);
-      }
+      setIsBusy(true);
+      setTimeout((): void => {
+        try {
+          pair.decodePkcs8(password);
+        } catch (error) {
+          setIsBusy(false);
+
+          return setUnlockError((error as Error).message);
+        }
 
-      onUnlock();
+        setIsBusy(false);
+        onUnlock();
+      }, 0);
     },
     [onUnlock, pair, password]
   );
@@ -90,6 +97,7 @@ function Unlock ({ onClose, onUnlock, pair }: Props): React.ReactElement<Props>
       <Modal.Actions onCancel={onClose}>
         <Button
           icon='unlock'
+          isBusy={isBusy}
           isPrimary
           label={t<string>('Unlock')}
           onClick={_onUnlock}

+ 1 - 1
packages/react-api/package.json

@@ -32,7 +32,7 @@
   "dependencies": {
     "@babel/runtime": "^7.10.5",
     "@polkadot/api": "^1.26.0-beta.1",
-    "@polkadot/extension-dapp": "^0.32.0-beta.8",
+    "@polkadot/extension-dapp": "^0.32.0-beta.9",
     "rxjs-compat": "^6.6.0"
   }
 }

+ 2 - 2
packages/react-api/src/hoc/call.tsx

@@ -106,12 +106,12 @@ export default function withCall<P extends ApiProps> (endpoint: string, {
 
         // The attachment takes time when a lot is available, set a timeout
         // to first handle the current queue before subscribing
-        setImmediate((): void => {
+        setTimeout((): void => {
           this
             .subscribe(this.getParams(this.props))
             .then(NOOP)
             .catch(NOOP);
-        });
+        }, 0);
       }
 
       public componentWillUnmount (): void {

+ 7 - 7
packages/react-components/package.json

@@ -14,15 +14,15 @@
     "@fortawesome/fontawesome-svg-core": "^1.2.30",
     "@fortawesome/free-solid-svg-icons": "^5.14.0",
     "@fortawesome/react-fontawesome": "^0.1.11",
-    "@polkadot/keyring": "^2.18.1",
+    "@polkadot/keyring": "^3.0.0-beta.3",
     "@polkadot/react-api": "0.51.0-beta.17",
-    "@polkadot/react-identicon": "^0.56.1",
-    "@polkadot/react-qr": "^0.56.1",
+    "@polkadot/react-identicon": "^0.57.0-beta.1",
+    "@polkadot/react-qr": "^0.57.0-beta.1",
     "@polkadot/react-query": "0.51.0-beta.17",
-    "@polkadot/ui-keyring": "^0.56.1",
-    "@polkadot/ui-settings": "^0.56.1",
-    "@polkadot/util": "^2.18.1",
-    "@polkadot/util-crypto": "^2.18.1",
+    "@polkadot/ui-keyring": "^0.57.0-beta.1",
+    "@polkadot/ui-settings": "^0.57.0-beta.1",
+    "@polkadot/util": "^3.0.0-beta.3",
+    "@polkadot/util-crypto": "^3.0.0-beta.3",
     "chart.js": "^2.9.3",
     "codeflask": "^1.4.1",
     "i18next": "^19.6.2",

+ 49 - 17
packages/react-components/src/Button/Button.tsx

@@ -8,40 +8,42 @@ import React, { useCallback } from 'react';
 import styled from 'styled-components';
 
 import Icon from '../Icon';
+import Spinner from '../Spinner';
 
-function Button ({ children, className = '', icon, isBasic = false, isCircular = false, isDisabled = false, isFull = false, isIcon, isNegative = false, isPositive = false, isPrimary = false, label, onClick, onMouseEnter, onMouseLeave, tabIndex }: ButtonProps): React.ReactElement<ButtonProps> {
+function Button ({ children, className = '', icon, isBasic, isBusy, isCircular, isDisabled, isFull, isIcon, isNegative, isPositive, isPrimary, label, onClick, onMouseEnter, onMouseLeave, tabIndex }: ButtonProps): React.ReactElement<ButtonProps> {
   const _onClick = useCallback(
-    (): void => {
-      !isDisabled && onClick && onClick();
-    },
-    [isDisabled, onClick]
+    () => !(isBusy || isDisabled) && onClick && onClick(),
+    [isBusy, isDisabled, onClick]
   );
 
   return (
     <button
-      className={`ui--Button${label ? ' hasLabel' : ''}${isBasic ? ' isBasic' : ''}${isCircular ? ' isCircular' : ''}${isFull ? ' isFull' : ''}${isIcon ? ' isIcon' : ''}${isNegative ? ' isNegative' : ''}${isPositive ? ' isPositive' : ''}${isPrimary ? (isBasic ? ' ui--highlight--border' : ' ui--highlight--button') : ''} ${className}`}
-      disabled={isDisabled}
+      className={`ui--Button${label ? ' hasLabel' : ''}${isBasic ? ' isBasic' : ''}${isCircular ? ' isCircular' : ''}${isFull ? ' isFull' : ''}${isIcon ? ' isIcon' : ''}${isNegative ? ' isNegative' : ''}${isPositive ? ' isPositive' : ''}${isPrimary ? (isBasic ? ' ui--highlight--border' : ' ui--highlight--button') : ''}${isDisabled ? ' isDisabled' : ''}${isBusy ? ' isBusy' : ''} ${className}`}
       onClick={_onClick}
       onMouseEnter={onMouseEnter}
       onMouseLeave={onMouseLeave}
       tabIndex={tabIndex}
     >
-      {icon && <Icon icon={icon} />}
+      <Icon icon={icon} />
       {label}
       {children}
+      <div className='ui--Button-overlay'>
+        <Spinner
+          className='ui--Button-spinner'
+          variant='cover'
+        />
+      </div>
     </button>
   );
 }
 
 export default React.memo(styled(Button)`
   border: none;
+  cursor: pointer;
   font-size: 0.92857142857rem; // 13/14px
+  position: relative;
   text-align: center;
 
-  &:not(:disabled) {
-    cursor: pointer;
-  }
-
   &:not(.hasLabel) {
     padding: 0.75em;
 
@@ -55,11 +57,6 @@ export default React.memo(styled(Button)`
     border-radius: 0.25rem;
   }
 
-  &:disabled {
-    cursor: not-allowed;
-    opacity: 0.15;
-  }
-
   &:focus {
     outline:0;
   }
@@ -78,10 +75,18 @@ export default React.memo(styled(Button)`
     color: inherit !important;
   }
 
+  &.isBusy {
+    cursor: wait;
+  }
+
   &.isCircular {
     border-radius: 10rem;
   }
 
+  &.isDisabled {
+    cursor: not-allowed;
+  }
+
   &.isFull {
     display: block;
     width: 100%;
@@ -90,4 +95,31 @@ export default React.memo(styled(Button)`
   &.isIcon {
     background: transparent;
   }
+
+  .ui--Button-spinner {
+    visibility: hidden;
+  }
+
+  .ui--Button-overlay {
+    background: rgba(255, 255, 255, 0.75);
+    bottom: 0;
+    left: 0;
+    position: absolute;
+    right: 0;
+    top: 0;
+    visibility: hidden;
+  }
+
+  &.isBusy {
+    .ui--Button-spinner {
+      visibility: visible;
+    }
+  }
+
+  &.isBusy,
+  &.isDisabled {
+    .ui--Button-overlay {
+      visibility: visible;
+    }
+  }
 `);

+ 2 - 3
packages/react-components/src/Button/types.ts

@@ -3,7 +3,6 @@
 // of the Apache-2.0 license. See the LICENSE file for details.
 
 import { IconName } from '@fortawesome/fontawesome-svg-core';
-import { ButtonProps as SUIButtonProps } from 'semantic-ui-react/dist/commonjs/elements/Button/Button';
 import { BareProps } from '../types';
 
 export type Button$Callback = () => void | Promise<void>;
@@ -11,9 +10,9 @@ export type Button$Callback = () => void | Promise<void>;
 export interface ButtonProps {
   children?: React.ReactNode;
   className?: string;
-  icon?: IconName;
-  isAnimated?: SUIButtonProps['animated'];
+  icon: IconName;
   isBasic?: boolean;
+  isBusy?: boolean;
   isCircular?: boolean;
   isDisabled?: boolean;
   isFull?: boolean;

+ 0 - 2
packages/react-components/src/Password.tsx

@@ -3,7 +3,6 @@
 // of the Apache-2.0 license. See the LICENSE file for details.
 
 import React from 'react';
-import { MAX_PASS_LEN } from '@polkadot/ui-keyring/defaults';
 
 import Input from './Input';
 
@@ -39,7 +38,6 @@ function Password ({ autoFocus, children, className = '', defaultValue, help, is
       isFull={isFull}
       label={label}
       labelExtra={labelExtra}
-      maxLength={MAX_PASS_LEN}
       name={name}
       onChange={onChange}
       onEnter={onEnter}

+ 22 - 4
packages/react-components/src/Spinner.tsx

@@ -11,17 +11,22 @@ import spinnerSrc from './Spinner-2.png';
 interface Props {
   className?: string;
   label?: React.ReactNode;
-  variant?: 'app' | 'push' | 'mini';
+  variant?: 'app' | 'cover' | 'push' | 'mini';
 }
 
+// prefetch
+const img = new Image();
+
+img.src = spinnerSrc as string;
+
 function Spinner ({ className = '', label, variant = 'app' }: Props): React.ReactElement<Props> | null {
   const { t } = useTranslation();
 
   return (
-    <div className={`${className} ui--Spinner`}>
+    <div className={`${className} ui--Spinner${variant === 'cover' ? ' isCover' : ''}`}>
       <img
-        className={variant === 'push' ? '' : 'ui--highlight--bg'}
-        src={spinnerSrc as unknown as string}
+        className={variant === 'push' ? '' : 'ui--highlight--bg ui--highlight--border'}
+        src={spinnerSrc as string}
       />
       {variant === 'app' && <div className='text'>{label || t('Retrieving data')}</div>}
     </div>
@@ -34,7 +39,20 @@ export default React.memo(styled(Spinner)`
   margin: 0 auto;
   text-align: center;
 
+  &.isCover {
+    bottom: 0;
+    left: 0;
+    position: absolute;
+    right: 0;
+
+    img {
+      margin: 0 auto;
+      opacity: 1;
+    }
+  }
+
   img {
+    border: 1px solid transparent;
     border-radius: 10rem;
     opacity: 0.75;
   }

+ 2 - 1
packages/react-components/src/TxButton.tsx

@@ -14,7 +14,7 @@ import Button from './Button';
 import { StatusContext } from './Status';
 import { useTranslation } from './translate';
 
-function TxButton ({ accountId, className = '', extrinsic: propsExtrinsic, icon, isBasic, isDisabled, isIcon, isNegative, isPrimary, isUnsigned, label, onClick, onFailed, onSendRef, onStart, onSuccess, onUpdate, params, tooltip, tx, withSpinner }: Props): React.ReactElement<Props> {
+function TxButton ({ accountId, className = '', extrinsic: propsExtrinsic, icon, isBasic, isBusy, isDisabled, isIcon, isNegative, isPrimary, isUnsigned, label, onClick, onFailed, onSendRef, onStart, onSuccess, onUpdate, params, tooltip, tx, withSpinner }: Props): React.ReactElement<Props> {
   const { t } = useTranslation();
   const { api } = useApi();
   const { queueExtrinsic } = useContext(StatusContext);
@@ -87,6 +87,7 @@ function TxButton ({ accountId, className = '', extrinsic: propsExtrinsic, icon,
       className={className}
       icon={icon || 'check'}
       isBasic={isBasic}
+      isBusy={isBusy}
       isDisabled={isSending || isDisabled || needsAccount}
       isIcon={isIcon}
       isNegative={isNegative}

+ 0 - 11
packages/react-components/src/styles/index.ts

@@ -121,17 +121,6 @@ export default createGlobalStyle<Props>`
     position: relative;
     text-align: left;
 
-    &:not(:hover):not(.keepAlive) {
-      .ui.button:not(.disabled) {
-        background: #eee !important;
-        color: #555 !important;
-      }
-
-      .ui.button.show-on-hover {
-        visibility: hidden;
-      }
-    }
-
     > ul {
       margin: 0;
       padding: 0;

+ 0 - 8
packages/react-components/src/styles/semantic.ts

@@ -149,14 +149,6 @@ export default css`
     opacity: 1;
   }
 
-  .ui.button:disabled,
-  .ui.buttons .disabled.button,
-  .ui.disabled.active.button,
-  .ui.disabled.button,
-  .ui.disabled.button:hover {
-    opacity: 0.2 !important;
-  }
-
   /* modals aligned to top, not center */
   .ui.dimmer {
     background-color: rgba(0,0,0,0.5);

+ 1 - 0
packages/react-components/src/types.ts

@@ -57,6 +57,7 @@ export interface TxButtonProps extends TxProps {
   className?: string;
   icon?: IconName;
   isBasic?: boolean;
+  isBusy?: boolean;
   isDisabled?: boolean;
   isIcon?: boolean;
   isNegative?: boolean;

+ 2 - 2
packages/react-signer/src/PaymentInfo.tsx

@@ -29,7 +29,7 @@ function PaymentInfo ({ accountId, className = '', extrinsic }: Props): React.Re
   useEffect((): void => {
     // eslint-disable-next-line @typescript-eslint/unbound-method
     accountId && extrinsic && isFunction(extrinsic.paymentInfo) && isFunction(api.rpc.payment?.queryInfo) &&
-      setImmediate((): void => {
+      setTimeout((): void => {
         try {
           extrinsic
             .paymentInfo(accountId)
@@ -38,7 +38,7 @@ function PaymentInfo ({ accountId, className = '', extrinsic }: Props): React.Re
         } catch (error) {
           console.error((error as Error).message);
         }
-      });
+      }, 0);
   }, [api, accountId, extrinsic, mountedRef]);
 
   if (!dispatchInfo) {

+ 32 - 34
packages/react-signer/src/TxSigned.tsx

@@ -264,8 +264,7 @@ function TxSigned ({ className, currentItem, requestAddress }: Props): React.Rea
   const _doStart = useCallback(
     (): void => {
       setBusy(true);
-
-      setImmediate((): void => {
+      setTimeout((): void => {
         if (_unlock()) {
           isSubmit
             ? currentItem.payload
@@ -275,7 +274,7 @@ function TxSigned ({ className, currentItem, requestAddress }: Props): React.Rea
         } else {
           setBusy(false);
         }
-      });
+      }, 0);
     },
     [_onSend, _onSendPayload, _onSign, _unlock, currentItem, isSubmit, queueSetTxStatus, senderInfo]
   );
@@ -338,38 +337,37 @@ function TxSigned ({ className, currentItem, requestAddress }: Props): React.Rea
         </ErrorBoundary>
       </Modal.Content>
       <Modal.Actions onCancel={_onCancel}>
+        <Button
+          icon={
+            flags.isQr
+              ? 'qrcode'
+              : 'sign-in-alt'
+          }
+          isBusy={isBusy}
+          isDisabled={!senderInfo.signAddress || isRenderError}
+          isPrimary
+          label={
+            flags.isQr
+              ? t<string>('Sign via Qr')
+              : isSubmit
+                ? t<string>('Sign and Submit')
+                : t<string>('Sign (no submission)')
+          }
+          onClick={_doStart}
+          tabIndex={2}
+        />
         {!isBusy && (
-          <>
-            <Button
-              icon={
-                flags.isQr
-                  ? 'qrcode'
-                  : 'sign-in-alt'
-              }
-              isDisabled={!senderInfo.signAddress || isRenderError}
-              isPrimary
-              label={
-                flags.isQr
-                  ? t<string>('Sign via Qr')
-                  : isSubmit
-                    ? t<string>('Sign and Submit')
-                    : t<string>('Sign (no submission)')
-              }
-              onClick={_doStart}
-              tabIndex={2}
-            />
-            <Toggle
-              className='signToggle'
-              isDisabled={!!currentItem.payload}
-              label={
-                isSubmit
-                  ? t<string>('Sign and Submit')
-                  : t<string>('Sign (no submission)')
-              }
-              onChange={setIsSubmit}
-              value={isSubmit}
-            />
-          </>
+          <Toggle
+            className='signToggle'
+            isDisabled={!!currentItem.payload}
+            label={
+              isSubmit
+                ? t<string>('Sign and Submit')
+                : t<string>('Sign (no submission)')
+            }
+            onChange={setIsSubmit}
+            value={isSubmit}
+          />
         )}
       </Modal.Actions>
     </>

+ 68 - 60
yarn.lock

@@ -1354,7 +1354,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"@babel/runtime@npm:^7.1.2, @babel/runtime@npm:^7.10.1, @babel/runtime@npm:^7.10.3, @babel/runtime@npm:^7.10.4, @babel/runtime@npm:^7.10.5, @babel/runtime@npm:^7.3.1, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.9.6":
+"@babel/runtime@npm:^7.1.2, @babel/runtime@npm:^7.10.1, @babel/runtime@npm:^7.10.3, @babel/runtime@npm:^7.10.5, @babel/runtime@npm:^7.3.1, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.9.6":
   version: 7.10.5
   resolution: "@babel/runtime@npm:7.10.5"
   dependencies:
@@ -3363,39 +3363,39 @@ __metadata:
   languageName: node
   linkType: hard
 
-"@polkadot/extension-dapp@npm:^0.32.0-beta.8":
-  version: 0.32.0-beta.8
-  resolution: "@polkadot/extension-dapp@npm:0.32.0-beta.8"
+"@polkadot/extension-dapp@npm:^0.32.0-beta.9":
+  version: 0.32.0-beta.9
+  resolution: "@polkadot/extension-dapp@npm:0.32.0-beta.9"
   dependencies:
     "@babel/runtime": ^7.10.5
-    "@polkadot/extension-inject": 0.32.0-beta.8
-    "@polkadot/util": ^2.18.1
-    "@polkadot/util-crypto": ^2.18.1
+    "@polkadot/extension-inject": 0.32.0-beta.9
+    "@polkadot/util": ^3.0.0-beta.2
+    "@polkadot/util-crypto": ^3.0.0-beta.2
   peerDependencies:
     "@polkadot/api": "*"
-  checksum: 3/3391648f0a010ae4cacf5e6c6e32bf4683f1f0aa0b57014e6cc30745a1b11d970f794d82c436fd492ad0f637aef30dd86eb8847b4d9e5324b947c5828bb8ebaf
+  checksum: 3/70ef177238eff0bcfcb2a15f570fa83646a1684aec25ba20cdf91d84ba888b9c375a7ebac3f3c2a7a20dc60afff54d54108fd8586fe6579fd53b8cd1158d291f
   languageName: node
   linkType: hard
 
-"@polkadot/extension-inject@npm:0.32.0-beta.8":
-  version: 0.32.0-beta.8
-  resolution: "@polkadot/extension-inject@npm:0.32.0-beta.8"
+"@polkadot/extension-inject@npm:0.32.0-beta.9":
+  version: 0.32.0-beta.9
+  resolution: "@polkadot/extension-inject@npm:0.32.0-beta.9"
   dependencies:
     "@babel/runtime": ^7.10.5
   peerDependencies:
     "@polkadot/api": "*"
-  checksum: 3/3dd34a291c24151f9f2e0f755f59ce3525b4d43d81d2b928a9596c00a713204380eacc2e1bf90e1a1d4ec8b639ec5a3639d5cd960621b237711b119b6c99bb5e
+  checksum: 3/8536f3cbc74702ee468644767f87c43d6872d26b17c3a363bc2e96d2f775df0292565e7c2378f99760ba5df3535d442d67dfc1aa0ca8236fed4754bdf434bca1
   languageName: node
   linkType: hard
 
-"@polkadot/keyring@npm:^2.18.1":
-  version: 2.18.1
-  resolution: "@polkadot/keyring@npm:2.18.1"
+"@polkadot/keyring@npm:^3.0.0-beta.3":
+  version: 3.0.0-beta.3
+  resolution: "@polkadot/keyring@npm:3.0.0-beta.3"
   dependencies:
-    "@babel/runtime": ^7.10.4
-    "@polkadot/util": 2.18.1
-    "@polkadot/util-crypto": 2.18.1
-  checksum: 3/293c9a25c33234a85710b10a6a253b76930ba0be7b42825af6bfc19d47579c185133d7b793c3e34ac0de9189563f65949cf08bf8dabf04c02661c675ee87e41d
+    "@babel/runtime": ^7.10.5
+    "@polkadot/util": 3.0.0-beta.3
+    "@polkadot/util-crypto": 3.0.0-beta.3
+  checksum: 3/38e19ebe85db6a03828481b6302e985a49070ebb934c269e5e0962862015f1aa7db5b8d6573dcfd586b08f36ea7dba86c58a0d763896d87c26a501bb82d9f774
   languageName: node
   linkType: hard
 
@@ -3419,7 +3419,7 @@ __metadata:
   dependencies:
     "@babel/runtime": ^7.10.5
     "@polkadot/api": ^1.26.0-beta.1
-    "@polkadot/extension-dapp": ^0.32.0-beta.8
+    "@polkadot/extension-dapp": ^0.32.0-beta.9
     rxjs-compat: ^6.6.0
   languageName: unknown
   linkType: soft
@@ -3432,15 +3432,15 @@ __metadata:
     "@fortawesome/fontawesome-svg-core": ^1.2.30
     "@fortawesome/free-solid-svg-icons": ^5.14.0
     "@fortawesome/react-fontawesome": ^0.1.11
-    "@polkadot/keyring": ^2.18.1
+    "@polkadot/keyring": ^3.0.0-beta.3
     "@polkadot/react-api": 0.51.0-beta.17
-    "@polkadot/react-identicon": ^0.56.1
-    "@polkadot/react-qr": ^0.56.1
+    "@polkadot/react-identicon": ^0.57.0-beta.1
+    "@polkadot/react-qr": ^0.57.0-beta.1
     "@polkadot/react-query": 0.51.0-beta.17
-    "@polkadot/ui-keyring": ^0.56.1
-    "@polkadot/ui-settings": ^0.56.1
-    "@polkadot/util": ^2.18.1
-    "@polkadot/util-crypto": ^2.18.1
+    "@polkadot/ui-keyring": ^0.57.0-beta.1
+    "@polkadot/ui-settings": ^0.57.0-beta.1
+    "@polkadot/util": ^3.0.0-beta.3
+    "@polkadot/util-crypto": ^3.0.0-beta.3
     "@types/codeflask": ^1.4.1
     chart.js: ^2.9.3
     codeflask: ^1.4.1
@@ -3476,13 +3476,13 @@ __metadata:
   languageName: unknown
   linkType: soft
 
-"@polkadot/react-identicon@npm:^0.56.1":
-  version: 0.56.1
-  resolution: "@polkadot/react-identicon@npm:0.56.1"
+"@polkadot/react-identicon@npm:^0.57.0-beta.1":
+  version: 0.57.0-beta.1
+  resolution: "@polkadot/react-identicon@npm:0.57.0-beta.1"
   dependencies:
     "@babel/runtime": ^7.10.5
-    "@polkadot/ui-settings": 0.56.1
-    "@polkadot/ui-shared": 0.56.1
+    "@polkadot/ui-settings": 0.57.0-beta.1
+    "@polkadot/ui-shared": 0.57.0-beta.1
     color: ^3.1.2
     jdenticon: 2.2.0
     react-copy-to-clipboard: ^5.0.2
@@ -3494,7 +3494,7 @@ __metadata:
     react-dom: "*"
     react-is: "*"
     styled-components: "*"
-  checksum: 3/6e1ff0c9e3dcf3b588b486cc308e0ec7b33fc41459ef52c126cc286e99df0789cf712563213c7cebf13e880efe9cbea06ddeaf0a2ed91a8c897df53caec269b7
+  checksum: 3/03ee88220f6f40433d80cda02af636c411cb67faac6256d55ba4144b1b2b473527276d245dfab6307b5b9aa2a2e15359a6c9ca3477534264df67f774f99ebd9b
   languageName: node
   linkType: hard
 
@@ -3507,9 +3507,9 @@ __metadata:
   languageName: unknown
   linkType: soft
 
-"@polkadot/react-qr@npm:^0.56.1":
-  version: 0.56.1
-  resolution: "@polkadot/react-qr@npm:0.56.1"
+"@polkadot/react-qr@npm:^0.57.0-beta.1":
+  version: 0.57.0-beta.1
+  resolution: "@polkadot/react-qr@npm:0.57.0-beta.1"
   dependencies:
     "@babel/runtime": ^7.10.5
     qrcode-generator: ^1.4.4
@@ -3520,7 +3520,7 @@ __metadata:
     react: "*"
     react-dom: "*"
     styled-components: "*"
-  checksum: 3/612ad6a250d3d2aeb93c471f5fadb4972673dafd07e90ca6e56ae70713d71c115bbf1f40837ed18e896bc4e36fb0da9fa1c2000c835a31dadb0eeee1a791b5b5
+  checksum: 3/3dff1f6993acb7d1ba82c086f39858b3fa4337c1c6dc1470b2f1b5537c5a01fa0d269d852e0862c870c521665a09ea38819886e1d31d2fc0d6c864a73304a9d6
   languageName: node
   linkType: hard
 
@@ -3610,9 +3610,9 @@ __metadata:
   languageName: node
   linkType: hard
 
-"@polkadot/ui-keyring@npm:^0.56.1":
-  version: 0.56.1
-  resolution: "@polkadot/ui-keyring@npm:0.56.1"
+"@polkadot/ui-keyring@npm:^0.57.0-beta.1":
+  version: 0.57.0-beta.1
+  resolution: "@polkadot/ui-keyring@npm:0.57.0-beta.1"
   dependencies:
     "@babel/runtime": ^7.10.5
     "@ledgerhq/hw-transport-node-hid": ^5.19.1
@@ -3628,42 +3628,42 @@ __metadata:
   dependenciesMeta:
     "@ledgerhq/hw-transport-node-hid":
       optional: true
-  checksum: 3/96f28f61310e0c23d9534246aa16917d98000eb9abd2c9d95b1ef9b91198d328960f4c1ab8917478e7ba9059be4d24e7c918448710ad72a7796b1e48d7c4f5b6
+  checksum: 3/55962fac3fbc07d85dcede5fb478d942a31f6dab231c4181f75b5b5f01047fff54d9c6dfa5aee01481d83a74bebb65da0285bfb88e063c542a38a75c29ce17b6
   languageName: node
   linkType: hard
 
-"@polkadot/ui-settings@npm:0.56.1, @polkadot/ui-settings@npm:^0.56.1":
-  version: 0.56.1
-  resolution: "@polkadot/ui-settings@npm:0.56.1"
+"@polkadot/ui-settings@npm:0.57.0-beta.1, @polkadot/ui-settings@npm:^0.57.0-beta.1":
+  version: 0.57.0-beta.1
+  resolution: "@polkadot/ui-settings@npm:0.57.0-beta.1"
   dependencies:
     "@babel/runtime": ^7.10.5
     eventemitter3: ^4.0.4
     store: ^2.0.12
   peerDependencies:
     "@polkadot/util": "*"
-  checksum: 3/a40d42823b712cd430386291647475b4b1184d1423431383c2cf2b9570b85ece8af005b72d209bf5851c96e6bb374f51ca6099508ae8c7e66f5e677cbb445e40
+  checksum: 3/710aedfda14af1dbc7602fdc68e0c121cf6646a27e788d690acec29bd899263acc76dff4fbd1909abe85aabcaf2997e42095445e3ac56f300eda23734a3df1a2
   languageName: node
   linkType: hard
 
-"@polkadot/ui-shared@npm:0.56.1":
-  version: 0.56.1
-  resolution: "@polkadot/ui-shared@npm:0.56.1"
+"@polkadot/ui-shared@npm:0.57.0-beta.1":
+  version: 0.57.0-beta.1
+  resolution: "@polkadot/ui-shared@npm:0.57.0-beta.1"
   dependencies:
     "@babel/runtime": ^7.10.5
     color: ^3.1.2
   peerDependencies:
     "@polkadot/util": "*"
     "@polkadot/util-crypto": "*"
-  checksum: 3/ad4f0cd5243f16aa35fdbedb0ba536784c7237ccb5baea4a1e5fd5c615d362efc9feae6e0c0805cd3571ee9609213820716a66340b9dfee287c664e300c9146a
+  checksum: 3/5c3abd8a6bf6cb8c6fc07f9478e15334c9a243ab63e8ceb527558fdca5fa7749ec764f4721b992de9d3eb4b09d3d6f6535d924c742d9989c84108a8a25871da7
   languageName: node
   linkType: hard
 
-"@polkadot/util-crypto@npm:^2.18.1":
-  version: 2.18.1
-  resolution: "@polkadot/util-crypto@npm:2.18.1"
+"@polkadot/util-crypto@npm:^3.0.0-beta.3":
+  version: 3.0.0-beta.3
+  resolution: "@polkadot/util-crypto@npm:3.0.0-beta.3"
   dependencies:
-    "@babel/runtime": ^7.10.4
-    "@polkadot/util": 2.18.1
+    "@babel/runtime": ^7.10.5
+    "@polkadot/util": 3.0.0-beta.3
     "@polkadot/wasm-crypto": ^1.2.1
     base-x: ^3.0.8
     bip39: ^3.0.2
@@ -3672,23 +3672,24 @@ __metadata:
     elliptic: ^6.5.3
     js-sha3: ^0.8.0
     pbkdf2: ^3.1.1
+    scryptsy: ^2.1.0
     tweetnacl: ^1.0.3
     xxhashjs: ^0.2.2
-  checksum: 3/412d3f1c0d0c318130808cdb6d0097fc0be915412e505d86e38ea7f2e131f0a7277b371bd4a9f41608d5220fc04f71de29409781f75f2a40399490827603f6fd
+  checksum: 3/cc39d6fc7c693b0a278f6fa8042d9054fffd49931437bc974ba7f1646b212c48b84966b918e0595c851014dd35466815ac886b65f0fea33a032e559086f0cb03
   languageName: node
   linkType: hard
 
-"@polkadot/util@npm:^2.18.1":
-  version: 2.18.1
-  resolution: "@polkadot/util@npm:2.18.1"
+"@polkadot/util@npm:^3.0.0-beta.3":
+  version: 3.0.0-beta.3
+  resolution: "@polkadot/util@npm:3.0.0-beta.3"
   dependencies:
-    "@babel/runtime": ^7.10.4
+    "@babel/runtime": ^7.10.5
     "@types/bn.js": ^4.11.6
     bn.js: ^5.1.2
     camelcase: ^5.3.1
     chalk: ^4.1.0
     ip-regex: ^4.1.0
-  checksum: 3/df6cb63e7d5cff1f0075e7807b76c6ea26c1a52f887dc20558d8717cde81713fa391cfd17dd82792f4c6271be30f143d3a11c816b7c00eaeea1d411fe5208e71
+  checksum: 3/93156add0469b8013a424ea25813c2c4f4ab16c1ab6fb20e85a66963f31a77b4a581bde69e711a7e25d167980fddba11ef5e2bd15a041eb7c592961112659789
   languageName: node
   linkType: hard
 
@@ -20582,6 +20583,13 @@ __metadata:
   languageName: node
   linkType: hard
 
+"scryptsy@npm:^2.1.0":
+  version: 2.1.0
+  resolution: "scryptsy@npm:2.1.0"
+  checksum: 3/9fd847955caa9d13a6d58a0360ba8fb31f8e7e7da9250b4c09c67db784a0f6dda757bc837313b0860c0e35f84a56ba068394c682dd4fba81c5899d82832aa7d6
+  languageName: node
+  linkType: hard
+
 "sdp@npm:^2.12.0, sdp@npm:^2.6.0":
   version: 2.12.0
   resolution: "sdp@npm:2.12.0"