SigningRequest.tsx 2.95 KiB
Newer Older
Andrei Eres's avatar
Andrei Eres committed
import {
Andrei Eres's avatar
Andrei Eres committed
  AccountJson,
  RequestSign,
} from '@polkadot/extension-base/background/types'
Andrei Eres's avatar
Andrei Eres committed
import { ExtrinsicPayload } from '@polkadot/types/interfaces'
import { SignerPayloadJSON, SignerPayloadRaw } from '@polkadot/types/types'
Andrei Eres's avatar
Andrei Eres committed
import { decodeAddress } from '@polkadot/util-crypto'
Andrei Eres's avatar
Andrei Eres committed
import { useStore } from 'nanostores/react'
import React, { useEffect, useState } from 'react'
Andrei Eres's avatar
Andrei Eres committed
import Address from '../components/Address'
Andrei Eres's avatar
Andrei Eres committed
import { accounts as accountsStore } from '../stores/accounts'
import { approveSignSignature, cancelSignRequest } from '../utils/messaging'
Andrei Eres's avatar
Andrei Eres committed
import { isRawPayload } from '../utils/guards'
Andrei Eres's avatar
Andrei Eres committed
import Qr, { CMD_MORTAL, CMD_SIGN_MESSAGE } from './Qr'
Andrei Eres's avatar
Andrei Eres committed
import { registry } from '../utils/registry'
Andrei Eres's avatar
Andrei Eres committed
import { BaseProps } from '../types'
import styled from 'styled-components'
Andrei Eres's avatar
Andrei Eres committed
type Props = BaseProps & {
Andrei Eres's avatar
Andrei Eres committed
  account: AccountJson
  buttonText: string
  isFirst: boolean
  request: RequestSign
  signId: string
  url: string
}

Andrei Eres's avatar
Andrei Eres committed
type Data = {
Andrei Eres's avatar
Andrei Eres committed
  hexBytes: string | null
  payload: ExtrinsicPayload | null
}

Andrei Eres's avatar
Andrei Eres committed
const Request: React.FC<Props> = ({ request, signId, className }) => {
Andrei Eres's avatar
Andrei Eres committed
  const accounts = useStore(accountsStore)
Andrei Eres's avatar
Andrei Eres committed
  const [{ hexBytes, payload }, setData] = useState<Data>({
    hexBytes: null,
    payload: null,
  })

  const onSignature = ({ signature }: { signature: string }) =>
    approveSignSignature(signId, signature).catch(console.error)
  const onCancel = () => cancelSignRequest(signId).catch(console.error)

  useEffect(() => {
    const payload = request.payload

    if (isRawPayload(payload)) {
Andrei Eres's avatar
Andrei Eres committed
      setData({ hexBytes: payload.data, payload: null })
Andrei Eres's avatar
Andrei Eres committed
    } else {
      registry.setSignedExtensions(payload.signedExtensions)
Andrei Eres's avatar
Andrei Eres committed
      const newPayload = registry.createType('ExtrinsicPayload', payload, {
        version: payload.version,
Andrei Eres's avatar
Andrei Eres committed
      })
Andrei Eres's avatar
Andrei Eres committed
      setData({ hexBytes: null, payload: newPayload })
Andrei Eres's avatar
Andrei Eres committed
    }
  }, [request])

  if (payload !== null) {
    const json = request.payload as SignerPayloadJSON

    return (
Andrei Eres's avatar
Andrei Eres committed
      <div className={className}>
Andrei Eres's avatar
Andrei Eres committed
        <Address address={json.address} genesisHash={json.genesisHash} />
Andrei Eres's avatar
Andrei Eres committed
        <Qr
          address={json.address}
          cmd={CMD_MORTAL}
          genesisHash={json.genesisHash}
          onSignature={onSignature}
Andrei Eres's avatar
Andrei Eres committed
          onCancel={onCancel}
Andrei Eres's avatar
Andrei Eres committed
          payload={payload}
        />
Andrei Eres's avatar
Andrei Eres committed
      </div>
Andrei Eres's avatar
Andrei Eres committed
    )
  }

  if (hexBytes !== null) {
    const { address, data } = request.payload as SignerPayloadRaw
    const account = accounts.find(
      (account) =>
        decodeAddress(account.address).toString() ===
        decodeAddress(address).toString()
    )

    return (
      <>
        <Address address={address} />
        {account?.genesisHash && (
          <Qr
            address={address}
            cmd={CMD_SIGN_MESSAGE}
            genesisHash={account.genesisHash}
            onSignature={onSignature}
Andrei Eres's avatar
Andrei Eres committed
            onCancel={onCancel}
Andrei Eres's avatar
Andrei Eres committed
            payload={data}
          />
        )}
      </>
    )
  }

  return null
}

Andrei Eres's avatar
Andrei Eres committed
export default styled(Request)`
  display: flex;
  flex-direction: column;
  align-items: center;
`