// Copyright 2017-2020 @polkadot/app-toolbox authors & contributors // This software may be modified and distributed under the terms // of the Apache-2.0 license. See the LICENSE file for details. import { Signer } from '@polkadot/api/types'; import { KeyringPair } from '@polkadot/keyring/types'; import React, { useEffect, useState } from 'react'; import styled from 'styled-components'; import { web3FromSource } from '@polkadot/extension-dapp'; import { Button, Input, InputAddress, Output, Static } from '@polkadot/react-components'; import keyring from '@polkadot/ui-keyring'; import { hexToU8a, isFunction, isHex, stringToHex, stringToU8a, u8aToHex } from '@polkadot/util'; import { useTranslation } from './translate'; import Unlock from './Unlock'; interface Props { className?: string; } interface AccountState { isExternal: boolean; isHardware: boolean; isInjected: boolean; } function Sign ({ className }: Props): React.ReactElement { const { t } = useTranslation(); const [currentPair, setCurrentPair] = useState(keyring.getPairs()[0] || null); const [{ data, isHexData }, setData] = useState<{ data: string; isHexData: boolean }>({ data: '', isHexData: false }); const [{ isInjected }, setAccountState] = useState({ isExternal: false, isHardware: false, isInjected: false }); const [isLocked, setIsLocked] = useState(false); const [{ isUsable, signer }, setSigner] = useState<{ isUsable: boolean; signer: Signer | null }>({ isUsable: true, signer: null }); const [signature, setSignature] = useState(''); const [isUnlockVisible, setIsUnlockVisible] = useState(false); useEffect((): void => { const isExternal = currentPair?.meta.isExternal || false; const isHardware = currentPair?.meta.isHardware || false; const isInjected = currentPair?.meta.isInjected || false; const isUsable = !(isExternal || isHardware || isInjected); setAccountState({ isExternal, isHardware, isInjected }); setIsLocked( isInjected ? false : currentPair?.isLocked || false ); setSignature(''); setSigner({ isUsable, signer: null }); // for injected, retrieve the signer if (currentPair && isInjected) { const { meta: { source } } = currentPair; web3FromSource(source) .catch((): null => null) .then((injected): void => setSigner({ isUsable: isFunction(injected?.signer?.signRaw), signer: injected?.signer || null })); } }, [currentPair]); const _toggleUnlock = (): void => setIsUnlockVisible(!isUnlockVisible); const _onChangeAccount = (accountId: string | null): void => setCurrentPair(keyring.getPair(accountId || '')); const _onChangeData = (data: string): void => setData({ data, isHexData: isHex(data) }); const _onSign = (): void => { if (isLocked || !isUsable || !currentPair) { return; } if (signer?.signRaw) { setSignature(''); signer .signRaw({ address: currentPair.address, data: isHexData ? data : stringToHex(data), type: 'bytes' }) .then(({ signature }): void => setSignature(signature)); } else { setSignature(u8aToHex( currentPair.sign( isHexData ? hexToU8a(data) : stringToU8a(data) ) )); } }; const _onUnlock = (): void => { setIsLocked(false); _toggleUnlock(); }; return (
{isUnlockVisible && ( )}
); } export default styled(Sign)` .toolbox--Sign-input { position: relative; width: 100%; height: 100%; .unlock-overlay { position: absolute; width: 100%; height: 100%; top:0; left:0; background-color: #0f0e0e7a; } .unlock-overlay-warning { display: flex; align-items: center; justify-content: center; height:100%; } .unlock-overlay-content { color:#fff; padding: 0 2.5rem; text-align:center; .ui--Button-Group { text-align: center; } } } `;