text: import BadKeyError from "./BadKeyError.js";
  import EcdsaPublicKey from "./EcdsaPublicKey.js";
  import * as hex from "./encoding/hex.js";
  import * as ecdsa from "./primitive/ecdsa.js";
  import { arrayStartsWith } from "./util/array.js";
  
  const derPrefix = "3030020100300706052b8104000a04220420";
  const derPrefixBytes = hex.decode(derPrefix);
  
  /**
   * @typedef {object} KeyPair
   * @property {Uint8Array} publicKey
   * @property {Uint8Array} privateKey
   */
  
  export default class EcdsaPrivateKey {
      /**
       * @hideconstructor
       * @internal
       * @param {KeyPair} keyPair
       * @param {(Uint8Array)=} chainCode
       */
      constructor(keyPair, chainCode) {
          /**
           * @type {KeyPair}
           * @readonly
           * @private
           */
          this._keyPair = keyPair;
  
          /**
           * @type {?Uint8Array}
           * @readonly
           */
          this._chainCode = chainCode != null ? chainCode : null;
      }
  
      /**
       * @returns {string}
       */
      get _type() {
          return "secp256k1";
      }
  
      /**
       * Generate a random ECDSA private key.
       *
       * @returns {EcdsaPrivateKey}
       */
      static generate() {
          return new EcdsaPrivateKey(ecdsa.generate());
      }
  
      /**
       * Generate a random Ed25519 private key.
       *
       * @returns {Promise<EcdsaPrivateKey>}
       */
      static async generateAsync() {
          return new EcdsaPrivateKey(await ecdsa.generateAsync());
      }
  
      /**
       * Construct a private key from bytes.
       *
       * @param {Uint8Array} data
       * @returns {EcdsaPrivateKey}
       */
      static fromBytes(data) {
          switch (data.length) {
              case 32:
                  return EcdsaPrivateKey.fromBytesRaw(data);
              case 50:
                  return EcdsaPrivateKey.fromBytesDer(data);
              default:
                  throw new BadKeyError(
                      `invalid private key length: ${data.length} bytes`
                  );
          }
      }
  
      /**
       * Construct a private key from bytes.
       *
       * @param {Uint8Array} data
       * @returns {EcdsaPrivateKey}
       */
      static fromBytesDer(data) {
          if (data.length != 32 && !arrayStartsWith(data, derPrefixBytes)) {
              throw new BadKeyError("invalid der header");
          }
  
          return new EcdsaPrivateKey(
              ecdsa.fromBytes(data.subarray(derPrefixBytes.length))
          );
      }
  
      /**
       * Construct a private key from bytes.
       *
       * @param {Uint8Array} data
       * @returns {EcdsaPrivateKey}
       */
      static fromBytesRaw(data) {
          return new EcdsaPrivateKey(ecdsa.fromBytes(data));
      }
  
      /**
       * Construct a private key from a hex-encoded string.
       *
       * @param {string} text
       * @returns {EcdsaPrivateKey}
       */
      static fromString(text) {
          return EcdsaPrivateKey.fromBytes(hex.decode(text));
      }
  
      /**
       * Construct a private key from a hex-encoded string.
       *
       * @param {string} text
       * @returns {EcdsaPrivateKey}
       */
      static fromStringDer(text) {
          return EcdsaPrivateKey.fromBytesDer(hex.decode(text));
      }
  
      /**
       * Construct a private key from a hex-encoded string.
       *
       * @param {string} text
       * @returns {EcdsaPrivateKey}
       */
      static fromStringRaw(text) {
          return EcdsaPrivateKey.fromBytesRaw(hex.decode(text));
      }
  
      /**
       * Get the public key associated with this private key.
       *
       * The public key can be freely given and used by other parties to verify
       * the signatures generated by this private key.
       *
       * @returns {EcdsaPublicKey}
       */
      get publicKey() {
          return new EcdsaPublicKey(this._keyPair.publicKey);
      }
  
      /**
       * Sign a message with this private key.
       *
       * @param {Uint8Array} bytes
       * @returns {Uint8Array} - The signature bytes without the message
       */
      sign(bytes) {
          return ecdsa.sign(this._keyPair.privateKey, bytes);
      }
  
      /**
       * @returns {Uint8Array}
       */
      toBytesDer() {
          const bytes = new Uint8Array(derPrefixBytes.length + 32);
  
          bytes.set(derPrefixBytes, 0);
          bytes.set(
              this._keyPair.privateKey.subarray(0, 32),
              derPrefixBytes.length
          );
  
          return bytes;
      }
  
      /**
       * @returns {Uint8Array}
       */
      toBytesRaw() {
          return this._keyPair.privateKey.slice(0, 32);
      }
  }
  