Source: did/typed-did/did-method-key.js

import { u8aToHex, hexToU8a } from '@polkadot/util';
import bs58 from 'bs58';
import varint from 'varint';
import { base58btc } from 'multiformats/bases/base58';

import { PublicKeyEd25519, PublicKeySecp256k1 } from '../../public-keys';

import { parseDIDUrl } from '../../resolver/did/did-resolver';

import {
  DidMethodKeyQualifier,
  DidMethodKeyBytePrefixEd25519,
  DidMethodKeyBytePrefixSecp256k1,
  Ed25519PublicKeyPrefix,
  Secp256k1PublicKeyPrefix,
} from '../constants';
import DockDidOrDidMethodKey from './dock-did-or-did-method-key';

/**
 * `did:key:*`
 *
 * As of now, the public key can be either `PublicKeyEd25519` or `PublicKeySecp256k1`.
 */
export default class DidMethodKey extends DockDidOrDidMethodKey {
  static Qualifier = DidMethodKeyQualifier;
  static Type = 'didMethodKey';
  /**
   * Instantiates `did:key:*` using supplied public key.
   * As of now, the public key can be either `PublicKeyEd25519` or `PublicKeySecp256k1`.
   *
   * @param {PublicKeyEd25519|PublicKeySecp256k1} didMethodKey
   */
  constructor(didMethodKey) {
    super(didMethodKey);

    if (
      !(
        didMethodKey instanceof PublicKeyEd25519
        || didMethodKey instanceof PublicKeySecp256k1
      )
    ) {
      throw new Error('Unsupported public key type');
    }
  }

  /**
   * Creates a new `DidMethodKey` from the supplied keypair.
   *
   * @param {DockKeypair} keypair
   * @returns {DidMethodKey}
   */
  static fromKeypair(keypair) {
    return new this(keypair.publicKey());
  }

  /**
   * Instantiates `DidMethodKey` from a fully qualified did string.
   * @param {string} did - fully qualified `did:key:*` string
   * @returns {DidMethodKey}
   */
  static fromQualifiedString(did) {
    const { id } = parseDIDUrl(did);

    const multicodecPubKey = base58btc.decode(id);
    varint.decode(multicodecPubKey); // NOTE: called to get byte length below
    const pubKeyBytes = multicodecPubKey.slice(varint.decode.bytes);
    const pubkeyHex = u8aToHex(pubKeyBytes);

    if (id.startsWith(Secp256k1PublicKeyPrefix)) {
      return new this(new PublicKeySecp256k1(pubkeyHex));
    } else if (id.startsWith(Ed25519PublicKeyPrefix)) {
      return new this(new PublicKeyEd25519(pubkeyHex));
    } else {
      throw new Error(`Unsupported \`did:key:*\`: \`${did}\``);
    }
  }

  /**
   * Instantiates `DidMethodKey` from an unqualified did string.
   * @param {string} did - BS58 encoded did key.
   * @returns {DidMethodKey}
   */
  static fromUnqualifiedString(did) {
    return this.fromQualifiedString(`did:key:${did}`);
  }

  /**
   * Instantiates `DockDid` from a did method key object received from the substrate side.
   * @param {object} key - substrate did method key
   * @returns {DidMethodKey}
   */
  static fromSubstrateValue(did) {
    const key = did.asDidMethodKey;

    if (key.isSecp256k1) {
      return new this(new PublicKeySecp256k1(u8aToHex(key.asSecp256k1)));
    } else if (key.isEd25519) {
      return new this(new PublicKeyEd25519(u8aToHex(key.asEd25519)));
    } else {
      throw new Error(`Invalid \`did:key:*\`: provided: \`${key}\``);
    }
  }

  get isDidMethodKey() {
    return true;
  }

  get asDidMethodKey() {
    return this.didMethodKey;
  }

  /**
   * Returns underlying public key.
   * @returns {PublicKeyEd25519|PublicKeySecp256k1}
   */
  get publicKey() {
    return this.didMethodKey;
  }

  /**
   * Returns unqualified public key encoded in `BS58`.
   */
  toEncodedString() {
    // Define the prefix for ed25519 DID key
    const publicKeyBytes = hexToU8a(this.publicKey.value);
    const prefix = this.didMethodKey.ed25519
      ? DidMethodKeyBytePrefixEd25519
      : DidMethodKeyBytePrefixSecp256k1;

    // Concatenate the prefix and the public key bytes
    const didKeyBytes = new Uint8Array(prefix.length + publicKeyBytes.length);
    didKeyBytes.set(prefix);
    didKeyBytes.set(publicKeyBytes, prefix.length);

    // Encode the concatenated bytes to Base58 with z prefix
    return `z${bs58.encode(didKeyBytes)}`;
  }
}

DockDidOrDidMethodKey.DidMethodKey = DidMethodKey;