Source: public-keys/public-key.js

import { u8aToHex } from '@polkadot/util';
import { isHexWithGivenByteSize } from '../utils/codec';
import { SizedTypedEnum } from '../utils/typed-enum';

/** Class representing a PublicKey. This export class should always be extended (abstract export class in some languages) */
export default class PublicKey extends SizedTypedEnum {
  /**
   * Check that the given public key has the expected byte size. Assumes the public key is in hex.
   */
  static validateSize(value) {
    if (!isHexWithGivenByteSize(value, this.Size)) {
      throw new Error(
        `Public key must be ${this.Size} bytes, got ${value.replace('0x', '').length / 2} bytes from value: ${value}`,
      );
    }

    return value;
  }

  /**
   * Validates the provided keyring pair and returns it in case of success.
   * @param {object} keyringPair
   * @returns {object}
   */
  static validateKeyringPair(keyringPair) {
    const pairType = getKeyPairType(keyringPair);

    if (this.Type !== pairType) {
      throw new Error(
        `Invalid keypair type - expected: ${this.Type}, received: ${pairType}`,
      );
    }

    return keyringPair;
  }

  /**
   * Extracts the public key from a pair. Assumes the KeyringPair is of the correct type. The `type` is intentionally not
   * inspected to follow dependency inversion principle.
   * generate the instance correct subclass
   * @param {object} pair A polkadot-js KeyringPair.
   * @returns {PublicKey}
   */
  static fromKeyringPair(keyringPair) {
    return new this(u8aToHex(this.validateKeyringPair(keyringPair).publicKey));
  }
}

/**
 * Return the type of signature from a given keypair
 * @param {object} pair - Can be a keypair from polkadot-js or elliptic library.
 * @returns {string|*}
 */
export function getKeyPairType(pair) {
  if (pair.type) {
    return pair.type;
  }

  if (pair.ec && pair.priv) {
    // elliptic library's pair has `ec`, `priv` and `pub`. There is not a cleaner way to detect that
    return 'secp256k1';
  }
  throw new Error('Cannot detect key pair type');
}