/******/ (() => { // webpackBootstrap
/******/ 	"use strict";
/******/ 	// The require scope
/******/ 	var __webpack_require__ = {};
/******/ 	
/************************************************************************/
/******/ 	/* webpack/runtime/compat get default export */
/******/ 	(() => {
/******/ 		// getDefaultExport function for compatibility with non-harmony modules
/******/ 		__webpack_require__.n = (module) => {
/******/ 			var getter = module && module.__esModule ?
/******/ 				() => (module['default']) :
/******/ 				() => (module);
/******/ 			__webpack_require__.d(getter, { a: getter });
/******/ 			return getter;
/******/ 		};
/******/ 	})();
/******/ 	
/******/ 	/* webpack/runtime/define property getters */
/******/ 	(() => {
/******/ 		// define getter functions for harmony exports
/******/ 		__webpack_require__.d = (exports, definition) => {
/******/ 			for(var key in definition) {
/******/ 				if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
/******/ 					Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
/******/ 				}
/******/ 			}
/******/ 		};
/******/ 	})();
/******/ 	
/******/ 	/* webpack/runtime/hasOwnProperty shorthand */
/******/ 	(() => {
/******/ 		__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
/******/ 	})();
/******/ 	
/******/ 	/* webpack/runtime/make namespace object */
/******/ 	(() => {
/******/ 		// define __esModule on exports
/******/ 		__webpack_require__.r = (exports) => {
/******/ 			if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ 				Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ 			}
/******/ 			Object.defineProperty(exports, '__esModule', { value: true });
/******/ 		};
/******/ 	})();
/******/ 	
/************************************************************************/
var __webpack_exports__ = {};
// ESM COMPAT FLAG
__webpack_require__.r(__webpack_exports__);

// EXPORTS
__webpack_require__.d(__webpack_exports__, {
  DeviceEncryptedMessage: () => (/* reexport */ deviceEncryptedMessage),
  WEB_STORAGE_MODULE_NAME: () => (/* reexport */ WEB_STORAGE_MODULE_NAME),
  WebStorageError: () => (/* reexport */ errors),
  WebStorageModule: () => (/* reexport */ src_WebStorageModule),
  canAccessFileStorage: () => (/* reexport */ canAccessFileStorage),
  "default": () => (/* reexport */ src_WebStorageModule),
  getPrivateKeyFromLocalStorage: () => (/* reexport */ getPrivateKeyFromLocalStorage),
  getShareFromFileStorage: () => (/* reexport */ getShareFromFileStorage),
  getShareFromLocalStorage: () => (/* reexport */ getShareFromLocalStorage),
  storeKeyOnLocalStorage: () => (/* reexport */ storeKeyOnLocalStorage),
  storePrivateKeyOnLocalStorage: () => (/* reexport */ storePrivateKeyOnLocalStorage),
  storeShareOnFileStorage: () => (/* reexport */ storeShareOnFileStorage),
  storeShareOnLocalStorage: () => (/* reexport */ storeShareOnLocalStorage)
});

;// CONCATENATED MODULE: external "@babel/runtime/helpers/defineProperty"
const defineProperty_namespaceObject = require("@babel/runtime/helpers/defineProperty");
var defineProperty_default = /*#__PURE__*/__webpack_require__.n(defineProperty_namespaceObject);
;// CONCATENATED MODULE: ./src/deviceEncryptedMessage.ts

class DeviceEncryptedMessage {
  constructor(ciphertext, ephemPublicKey, iv, mac) {
    defineProperty_default()(this, "ciphertext", void 0);
    defineProperty_default()(this, "ephemPublicKey", void 0);
    defineProperty_default()(this, "iv", void 0);
    defineProperty_default()(this, "mac", void 0);
    this.ciphertext = ciphertext;
    this.ephemPublicKey = ephemPublicKey;
    this.iv = iv;
    this.mac = mac;
  }
  static fromJSON(value) {
    const {
      ciphertext,
      ephemPublicKey,
      iv,
      mac
    } = value;
    return new DeviceEncryptedMessage(ciphertext, ephemPublicKey, iv, mac);
  }
  toJSON() {
    return {
      ciphertext: this.ciphertext.toString(),
      ephemPublicKey: this.ephemPublicKey.toString(),
      iv: this.iv.toString(),
      mac: this.mac.toString()
    };
  }
}
/* harmony default export */ const deviceEncryptedMessage = (DeviceEncryptedMessage);
;// CONCATENATED MODULE: external "@tkey-singularity/common-types"
const common_types_namespaceObject = require("@tkey-singularity/common-types");
;// CONCATENATED MODULE: ./src/errors.ts


class WebStorageError extends common_types_namespaceObject.TkeyError {
  constructor(code, message) {
    // takes care of stack and proto
    super(code, message);
    // Set name explicitly as minification can mangle class names
    Object.defineProperty(this, "name", {
      value: "WebStorageError"
    });
  }
  static fromCode(code) {
    let extraMessage = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : "";
    return new WebStorageError(code, `${WebStorageError.messages[code]}${extraMessage}`);
  }
  static default() {
    let extraMessage = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : "";
    return new WebStorageError(3000, `${WebStorageError.messages[3000]}${extraMessage}`);
  }

  // Custom methods
  static unableToReadFromStorage() {
    let extraMessage = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : "";
    return WebStorageError.fromCode(3101, extraMessage);
  }
  static shareUnavailableInFileStorage() {
    let extraMessage = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : "";
    return WebStorageError.fromCode(3201, extraMessage);
  }
  static fileStorageUnavailable() {
    let extraMessage = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : "";
    return WebStorageError.fromCode(3202, extraMessage);
  }
  static localStorageUnavailable() {
    let extraMessage = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : "";
    return WebStorageError.fromCode(3301, extraMessage);
  }
  static shareUnavailableInLocalStorage() {
    let extraMessage = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : "";
    return WebStorageError.fromCode(3302, extraMessage);
  }
}
defineProperty_default()(WebStorageError, "messages", {
  3000: "default",
  // module
  3101: "unableToReadFromStorage",
  // fileStorage
  3201: "No Share exists in file system",
  3202: "No requestFileSystem",
  // localstorage
  3301: "Local storage is not enabled",
  3302: "No share exists in localstorage"
});
/* harmony default export */ const errors = (WebStorageError);
;// CONCATENATED MODULE: external "@toruslabs/eccrypto"
const eccrypto_namespaceObject = require("@toruslabs/eccrypto");
;// CONCATENATED MODULE: external "@toruslabs/metadata-helpers"
const metadata_helpers_namespaceObject = require("@toruslabs/metadata-helpers");
;// CONCATENATED MODULE: ./src/utils.ts


function getWindow() {
  if (typeof window !== "undefined") return window;
  if (typeof self !== "undefined") return self;
  throw new Error("Unable to locate window object.");
}
function encParamsHexToBuf(encParamsHex) {
  return {
    iv: Buffer.from(encParamsHex.iv, "hex"),
    ephemPublicKey: Buffer.from(encParamsHex.ephemPublicKey, "hex"),
    ciphertext: Buffer.from(encParamsHex.ciphertext, "hex"),
    mac: Buffer.from(encParamsHex.mac, "hex")
  };
}
function encParamsBufToHex(encParams) {
  return {
    iv: Buffer.from(encParams.iv).toString("hex"),
    ephemPublicKey: Buffer.from(encParams.ephemPublicKey).toString("hex"),
    ciphertext: Buffer.from(encParams.ciphertext).toString("hex"),
    mac: Buffer.from(encParams.mac).toString("hex")
  };
}
async function encryptData(privKeyHex, d) {
  const serializedDec = JSON.stringify(d);
  const serializedBuf = Buffer.from(serializedDec, "utf-8");
  const encParams = await (0,eccrypto_namespaceObject.encrypt)((0,eccrypto_namespaceObject.getPublic)(Buffer.from(privKeyHex, "hex")), serializedBuf);
  const encParamsHex = encParamsBufToHex(encParams);
  const sData = JSON.stringify(encParamsHex);
  return sData;
}
async function decryptData(privKeyHex, d) {
  const encParamsHex = JSON.parse(d);
  const encParams = encParamsHexToBuf(encParamsHex);
  const keyPair = metadata_helpers_namespaceObject.ec.keyFromPrivate(privKeyHex);
  const serializedBuf = await (0,eccrypto_namespaceObject.decrypt)(Buffer.from(keyPair.getPrivate().toString("hex", 64), "hex"), encParams);
  const serializedDec = serializedBuf.toString("utf-8");
  const data = JSON.parse(serializedDec);
  return data;
}
;// CONCATENATED MODULE: ./src/FileStorageHelpers.ts




// Web Specific declarations
const requestedBytes = 1024 * 1024 * 10; // 10MB

const win = getWindow();
win.requestFileSystem = win.requestFileSystem || win.webkitRequestFileSystem;
function download(filename, text) {
  const element = document.createElement("a");
  element.setAttribute("href", `data:application/json;charset=utf-8,${encodeURIComponent(text)}`);
  element.setAttribute("download", filename);
  element.style.display = "none";
  document.body.appendChild(element);
  element.click();
  document.body.removeChild(element);
}
async function requestQuota() {
  return new Promise((resolve, reject) => {
    navigator.webkitPersistentStorage.requestQuota(requestedBytes, resolve, reject);
  });
}
async function browserRequestFileSystem(grantedBytes) {
  return new Promise((resolve, reject) => {
    win.requestFileSystem(win.PERSISTENT, grantedBytes, resolve, reject);
  });
}
async function getFile(fs, path, create) {
  return new Promise((resolve, reject) => {
    fs.root.getFile(path, {
      create
    }, data => resolve(data), reject);
  });
}
async function readFile(fileEntry) {
  return new Promise((resolve, reject) => {
    fileEntry.file(resolve, reject);
  });
}
const getShareFromFileStorage = async key => {
  if (win.requestFileSystem) {
    const fs = await browserRequestFileSystem(requestedBytes);
    const fileEntry = await getFile(fs, key, false);
    const file = await readFile(fileEntry);
    const fileStr = await file.text();
    if (!fileStr) {
      throw errors.shareUnavailableInFileStorage();
    }
    return common_types_namespaceObject.ShareStore.fromJSON(JSON.parse(fileStr));
  }
  throw errors.fileStorageUnavailable();
};
const storeShareOnFileStorage = async (share, key) => {
  // if we're on chrome (thus window.requestFileSystem exists) we use it
  const fileName = `${key}.json`;
  const fileStr = JSON.stringify(share);
  if (win.requestFileSystem) {
    const grantedBytes = await requestQuota();
    const fs = await browserRequestFileSystem(grantedBytes);
    const fileEntry = await getFile(fs, key, true);
    await new Promise((resolve, reject) => {
      fileEntry.createWriter(fileWriter => {
        fileWriter.onwriteend = resolve;
        fileWriter.onerror = reject;
        const bb = new Blob([fileStr], {
          type: "application/json"
        });
        fileWriter.write(bb);
      }, reject);
    });
  } else {
    // we make the user download a file
    download(fileName, fileStr);
  }
};
const canAccessFileStorage = async () => navigator.permissions.query({
  name: "persistent-storage"
});
;// CONCATENATED MODULE: ./src/LocalStorageHelpers.ts



const LocalStorageHelpers_win = getWindow();
const localStorageKey = "KEY_FOR_PRIVATE_KEY";
function storageAvailable(type) {
  let storage;
  try {
    storage = LocalStorageHelpers_win[type];
    const x = "__storage_test__";
    storage.setItem(x, x);
    storage.removeItem(x);
    return true;
  } catch (e) {
    return e instanceof DOMException && (
    // everything except Firefox
    e.code === 22 ||
    // Firefox
    e.code === 1014 ||
    // test name field too, because code might not be present
    // everything except Firefox
    e.name === "QuotaExceededError" ||
    // Firefox
    e.name === "NS_ERROR_DOM_QUOTA_REACHED") &&
    // acknowledge QuotaExceededError only if there's something already stored
    storage && storage.length !== 0;
  }
}
const storeShareOnLocalStorage = async (share, key) => {
  const fileStr = JSON.stringify(share);
  if (!storageAvailable("localStorage")) {
    throw errors.localStorageUnavailable();
  }
  LocalStorageHelpers_win.localStorage.setItem(key, fileStr);
};
const storePrivateKeyOnLocalStorage = async (privateKey, verifier) => {
  if (!storageAvailable("localStorage")) {
    throw errors.localStorageUnavailable();
  }
  LocalStorageHelpers_win.localStorage.setItem(verifier, privateKey);
};
const getPrivateKeyFromLocalStorage = async key => {
  if (!storageAvailable("localStorage")) {
    throw errors.localStorageUnavailable();
  }
  const foundKey = LocalStorageHelpers_win.localStorage.getItem(key);
  if (!foundKey) throw errors.shareUnavailableInLocalStorage();
  return foundKey;
};
const getShareFromLocalStorage = async key => {
  if (!storageAvailable("localStorage")) {
    throw errors.localStorageUnavailable();
  }
  const foundFile = LocalStorageHelpers_win.localStorage.getItem(key);
  if (!foundFile) throw errors.shareUnavailableInLocalStorage();
  return common_types_namespaceObject.ShareStore.fromJSON(JSON.parse(foundFile));
};
const storeKeyOnLocalStorage = privateKey => {
  if (!storageAvailable("localStorage")) {
    throw errors.localStorageUnavailable();
  }
  LocalStorageHelpers_win.localStorage.setItem(localStorageKey, privateKey);
};
;// CONCATENATED MODULE: external "bn.js"
const external_bn_js_namespaceObject = require("bn.js");
var external_bn_js_default = /*#__PURE__*/__webpack_require__.n(external_bn_js_namespaceObject);
;// CONCATENATED MODULE: external "axios"
const external_axios_namespaceObject = require("axios");
var external_axios_default = /*#__PURE__*/__webpack_require__.n(external_axios_namespaceObject);
;// CONCATENATED MODULE: ./src/http.ts

async function get(url) {
  try {
    const response = await axios.get(url);
    return response.data;
  } catch (exception) {
    throw new exception.Error();
  }
}
async function post(url, requestBody, requestHeaders) {
  const response = await external_axios_default().post(url, requestBody, requestHeaders);
  return response;
}
;// CONCATENATED MODULE: ./src/WebStorageModule.ts









const WEB_STORAGE_MODULE_NAME = "webStorage";
class WebStorageModule {
  constructor() {
    let canUseFileStorage = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
    defineProperty_default()(this, "moduleName", void 0);
    defineProperty_default()(this, "tbSDK", void 0);
    defineProperty_default()(this, "canUseFileStorage", void 0);
    this.moduleName = WEB_STORAGE_MODULE_NAME;
    this.canUseFileStorage = canUseFileStorage;
    this.setFileStorageAccess();
  }
  async setFileStorageAccess() {
    try {
      const result = await canAccessFileStorage();
      if (result.state === "denied") {
        this.canUseFileStorage = false;
      } else if (result.state === "granted") {
        this.canUseFileStorage = true;
      }
      // eslint-disable-next-line @typescript-eslint/no-this-alias
      const self = this;
      result.onchange = function permissionChange() {
        if (this.state === "denied") {
          self.canUseFileStorage = false;
        } else if (this.state === "granted") {
          self.canUseFileStorage = true;
        }
      };
    } catch (error) {}
  }
  setModuleReferences(tbSDK) {
    this.tbSDK = tbSDK;
    this.tbSDK._setDeviceStorage(this.storeDeviceShare.bind(this));
  }

  // eslint-disable-next-line
  async initialize() {}
  async storeDeviceShare(url, authDetails, deviceShareStore, customDeviceInfo) {
    const encryptedShare = await this.encryptShareWithPublicKey(deviceShareStore);
    await storePrivateKeyOnLocalStorage(encryptedShare.privateKey.toString("hex"), authDetails.verifier);
    // await this.storeCookieShare(encryptedShare, authDetails.verifier, authDetails.apiKey, authDetails.bearerToken, url);
    const shareDescription = {
      module: this.moduleName,
      userAgent: navigator.userAgent,
      dateAdded: Date.now()
    };
    if (customDeviceInfo) {
      shareDescription.customDeviceInfo = JSON.stringify(customDeviceInfo);
    }
    await this.tbSDK.addShareDescription(deviceShareStore.share.shareIndex.toString("hex"), JSON.stringify(shareDescription), true);
    return encryptedShare;
  }
  async storeDeviceShareOnFileStorage(shareIndex) {
    const metadata = this.tbSDK.getMetadata();
    const tkeypubx = metadata.pubKey.x.toString("hex");
    const shareStore = this.tbSDK.outputShareStore(new (external_bn_js_default())(shareIndex));
    return storeShareOnFileStorage(shareStore, tkeypubx);
  }
  async getDeviceShare(encryptedMessage, verifier) {
    let shareStore;
    try {
      shareStore = await this.getCookieShare(encryptedMessage, verifier);
    } catch (localErr) {
      throw errors.unableToReadFromStorage(`Error inputShareFromWebStorage: ${(0,common_types_namespaceObject.prettyPrintError)(localErr)}`);
    }
    return shareStore;
  }
  async inputShareFromWebStorage(authDetails, encryptedMessage) {
    const shareStore = await this.getCookieShare(encryptedMessage, authDetails.verifier);
    this.tbSDK.inputShareStore(shareStore);
    return {
      latestShareStore: shareStore
    };
  }
  async encryptShareWithPublicKey(share) {
    const privateKey = (0,eccrypto_namespaceObject.generatePrivate)();
    const privKeyHex = privateKey.toString("hex");
    const publicKey = (0,eccrypto_namespaceObject.getPublic)(privateKey);
    const encryptedShareMessage = await encryptData(privKeyHex, share);
    return {
      publickey: publicKey,
      privateKey,
      encryptedShare: encryptedShareMessage
    };
  }
  async getCookieShare(encryptedString, verifier) {
    const privateKeyHex = await getPrivateKeyFromLocalStorage(verifier);
    const shareStore = await decryptData(privateKeyHex, encryptedString);
    return shareStore;
  }
  async storeCookieShare(encryptedShare, verifier, apikey, bearerToken, url) {
    const body = JSON.stringify({
      encryptedShare
    });
    const header = {
      credentials: "include",
      withCredentials: true,
      crossDomain: true,
      "x-api-key": apikey,
      authorization: `Bearer ${bearerToken}`,
      "Content-Type": "application/json"
    };
    return post(url, body, header);
  }
  async getMetaData(url, apikey, bearerToken) {
    const body = "";
    const header = {
      credentials: "include",
      withCredentials: true,
      crossDomain: true,
      "x-api-key": apikey,
      authorization: `Bearer ${bearerToken}`,
      "Content-Type": "application/json"
    };
    return post(url, body, header);
  }
  async getMetaDataFlow(url, apikey, bearerToken) {
    const metadata = this.getMetaData(url, apikey, bearerToken);
    if (metadata == null) {
      const sdkMetadata = this.tbSDK.getMetadata();
      await this.storeMetadata(url, apikey, bearerToken, sdkMetadata);
    } else {
      return metadata;
    }
  }
  async storeMetadata(url, apikey, bearerToken, sdkMetadata) {
    const body = JSON.stringify(sdkMetadata);
    const header = {
      credentials: "include",
      withCredentials: true,
      crossDomain: true,
      "x-api-key": apikey,
      authorization: `Bearer ${bearerToken}`,
      "Content-Type": "application/json"
    };
    return post(url, body, header);
  }
}
/* harmony default export */ const src_WebStorageModule = (WebStorageModule);
;// CONCATENATED MODULE: ./src/index.ts





module.exports = __webpack_exports__;
/******/ })()
;
//# sourceMappingURL=webStorage.cjs.js.map