Address.tsx 2.73 KiB
Newer Older
Andrei Eres's avatar
Andrei Eres committed
import { AccountJson } from '@polkadot/extension-base/background/types'
import { KeypairType } from '@polkadot/util-crypto/types'
import { useStore } from 'nanostores/react'
import React, { useEffect, useState } from 'react'
import styled from 'styled-components'
Andrei Eres's avatar
Andrei Eres committed
import useMetadata from '../hooks/useMetadata'
Andrei Eres's avatar
Andrei Eres committed
import { accounts as accountsStore } from '../stores/accounts'
import { BaseProps } from '../types'
Andrei Eres's avatar
Andrei Eres committed
import { DEFAULT_TYPE } from '../utils/defaultType'
import { findAccountByAddress } from '../utils/findAccountByAddress'
import { recodeAddress, Recoded } from '../utils/recodeAddress'
Andrei Eres's avatar
Andrei Eres committed
import { goTo } from '../utils/routing'
Andrei Eres's avatar
Andrei Eres committed
type Props = BaseProps & {
Andrei Eres's avatar
Andrei Eres committed
  address?: string
  genesisHash?: string | null
  name?: string
  type?: KeypairType
Andrei Eres's avatar
Andrei Eres committed
  hideActions?: boolean
Andrei Eres's avatar
Andrei Eres committed
}

const defaultRecoded = {
  account: null,
  formatted: null,
  prefix: 42,
  type: DEFAULT_TYPE,
}

const Address: React.FC<Props> = ({
  address,
  children,
  className,
  genesisHash,
  name,
  type: givenType,
Andrei Eres's avatar
Andrei Eres committed
  hideActions,
Andrei Eres's avatar
Andrei Eres committed
}) => {
  const [{ account, formatted, genesisHash: recodedGenesis }, setRecoded] =
    useState<Recoded>(defaultRecoded)
Andrei Eres's avatar
Andrei Eres committed
  const accounts = useStore(accountsStore) as AccountJson[]
Andrei Eres's avatar
Andrei Eres committed
  const chain = useMetadata(genesisHash || recodedGenesis, true)

  const onCopy = () => {
    navigator.clipboard.writeText(formatted || '').catch(console.error)
  }
Andrei Eres's avatar
Andrei Eres committed
  const forget = () => goTo(`/account/forget/${address}`)

  useEffect(() => {
    if (!address) return

    const accountByAddress = findAccountByAddress(accounts, address)
    const isEthereum =
      chain?.definition.chainType === 'ethereum' ||
      accountByAddress?.type === 'ethereum' ||
      (!accountByAddress && givenType === 'ethereum')
    const recoded = isEthereum
      ? ({
          account: accountByAddress,
          formatted: address,
          type: 'ethereum',
        } as Recoded)
Andrei Eres's avatar
Andrei Eres committed
      : recodeAddress(address, accounts, chain)
Andrei Eres's avatar
Andrei Eres committed

    recoded && setRecoded(recoded)
Andrei Eres's avatar
Andrei Eres committed
  }, [accounts, address, chain, givenType])
Andrei Eres's avatar
Andrei Eres committed

  return (
    <div className={className}>
Andrei Eres's avatar
Andrei Eres committed
      <div>
        <div>{name || account?.name || '<unknown>'}</div>
Andrei Eres's avatar
Andrei Eres committed
        <div className='address'>{formatted || address || '<unknown>'}</div>
        {!hideActions && (
          <div className='actions'>
            <button onClick={onCopy}>{'Copy'}</button>
            <button onClick={forget}>{'Forget'}</button>
          </div>
        )}
Andrei Eres's avatar
Andrei Eres committed
      </div>
      {children}
    </div>
  )
}

export default styled(Address)`
Andrei Eres's avatar
Andrei Eres committed
  width: 100%;
  background: ${({ theme }: Props) => theme.background};
  margin-bottom: 0.5rem;
  border-radius: 0.2rem;
  padding: 0.4rem;
  padding-top: 0.2rem;

  .address {
    color: ${({ theme }: Props) => theme.subTextColor};
  }

  .actions {
    margin-top: 0.4rem;
  }

  .actions * {
    margin-right: 0.4rem;
  }
Andrei Eres's avatar
Andrei Eres committed
`