From 7c6829f04a5b443839312b34e50b267d1f4ba71a Mon Sep 17 00:00:00 2001 From: Thibaut Sardan <33178835+Tbaut@users.noreply.github.com> Date: Tue, 1 Jun 2021 13:38:25 +0200 Subject: [PATCH] Support signing messages for external accounts (#718) * support signing messages * Apply suggestions from code review Co-authored-by: Jaco Co-authored-by: Jaco --- .../extension-ui/src/Popup/Signing/Qr.tsx | 43 ++++++++++++++----- .../src/Popup/Signing/Request/index.tsx | 35 +++++++++++---- 2 files changed, 59 insertions(+), 19 deletions(-) diff --git a/packages/extension-ui/src/Popup/Signing/Qr.tsx b/packages/extension-ui/src/Popup/Signing/Qr.tsx index f17afbf4..e67223e4 100644 --- a/packages/extension-ui/src/Popup/Signing/Qr.tsx +++ b/packages/extension-ui/src/Popup/Signing/Qr.tsx @@ -2,33 +2,44 @@ // SPDX-License-Identifier: Apache-2.0 import type { ExtrinsicPayload } from '@polkadot/types/interfaces'; -import type { SignerPayloadJSON } from '@polkadot/types/types'; import React, { useCallback, useMemo, useState } from 'react'; import styled from 'styled-components'; import { QrDisplayPayload, QrScanSignature } from '@polkadot/react-qr'; +import { hexToU8a } from '@polkadot/util'; import { Button } from '../../components'; import useTranslation from '../../hooks/useTranslation'; +import { CMD_MORTAL, CMD_SIGN_MESSAGE } from './Request'; interface Props { + address: string; children?: React.ReactNode; className?: string; + cmd: number; + genesisHash: string; onSignature: ({ signature }: { signature: string }) => void; - payload: ExtrinsicPayload; - request: SignerPayloadJSON; + payload: ExtrinsicPayload | string; + } -const CMD_MORTAL = 2; - -function Qr ({ className, onSignature, payload, request }: Props): React.ReactElement { +function Qr ({ address, className, cmd, genesisHash, onSignature, payload }: Props): React.ReactElement { const { t } = useTranslation(); const [isScanning, setIsScanning] = useState(false); const payloadU8a = useMemo( - () => payload.toU8a(), - [payload] + () => { + switch (cmd) { + case CMD_MORTAL: + return (payload as ExtrinsicPayload).toU8a(); + case CMD_SIGN_MESSAGE: + return hexToU8a(payload as string); + default: + return null; + } + }, + [cmd, payload] ); const _onShowQr = useCallback( @@ -36,6 +47,16 @@ function Qr ({ className, onSignature, payload, request }: Props): React.ReactEl [] ); + if (!payloadU8a) { + return ( +
+
+ Transaction command:{cmd} not supported. +
+
+ ); + } + return (
@@ -43,9 +64,9 @@ function Qr ({ className, onSignature, payload, request }: Props): React.ReactEl ? : ( ) diff --git a/packages/extension-ui/src/Popup/Signing/Request/index.tsx b/packages/extension-ui/src/Popup/Signing/Request/index.tsx index d1a99f9e..9240f7e8 100644 --- a/packages/extension-ui/src/Popup/Signing/Request/index.tsx +++ b/packages/extension-ui/src/Popup/Signing/Request/index.tsx @@ -8,8 +8,9 @@ import type { SignerPayloadJSON, SignerPayloadRaw } from '@polkadot/types/types' import React, { useCallback, useContext, useEffect, useState } from 'react'; import { TypeRegistry } from '@polkadot/types'; +import { decodeAddress } from '@polkadot/util-crypto'; -import { ActionContext, Address, VerticalSpace } from '../../../components'; +import { AccountContext, ActionContext, Address, VerticalSpace } from '../../../components'; import { approveSignSignature } from '../../../messaging'; import Bytes from '../Bytes'; import Extrinsic from '../Extrinsic'; @@ -31,6 +32,9 @@ interface Data { payload: ExtrinsicPayload | null; } +export const CMD_MORTAL = 2; +export const CMD_SIGN_MESSAGE = 3; + // keep it global, we can and will re-use this across requests const registry = new TypeRegistry(); @@ -42,6 +46,7 @@ export default function Request ({ account: { accountIndex, addressOffset, isExt const onAction = useContext(ActionContext); const [{ hexBytes, payload }, setData] = useState({ hexBytes: null, payload: null }); const [error, setError] = useState(null); + const { accounts } = useContext(AccountContext); useEffect((): void => { const payload = request.payload; @@ -88,9 +93,11 @@ export default function Request ({ account: { accountIndex, addressOffset, isExt {isExternal && !isHardware ? ( ) : ( @@ -123,20 +130,32 @@ export default function Request ({ account: { accountIndex, addressOffset, isExt ); } else if (hexBytes !== null) { - const raw = request.payload as SignerPayloadRaw; + const { address, data } = request.payload as SignerPayloadRaw; + const account = accounts.find((account) => decodeAddress(account.address).toString() === decodeAddress(address).toString()); return ( <>
- + {isExternal && !isHardware && account?.genesisHash + ? ( + + ) + : + }