From 82ebb5978550e0cc6387f2cfd95b2895c069ba91 Mon Sep 17 00:00:00 2001
From: Gerald
Date: Thu, 17 Feb 2022 18:41:48 +0100
Subject: [PATCH 01/86] feat: derivate a new signer key for each account (store
derivation path in data storage)
---
packages/extension/jest.config.js | 6 +
packages/extension/package.json | 4 +
packages/extension/src/background/index.ts | 4 +-
.../src/background/keys/keyDerivation.ts | 73 +
packages/extension/src/background/keys/l1.ts | 38 +-
.../src/background/selectedWallet.ts | 6 +-
packages/extension/src/shared/MessageType.ts | 1 +
packages/extension/src/shared/backup.model.ts | 6 +
packages/extension/src/ui/Account.ts | 17 +-
packages/extension/src/ui/utils/accounts.ts | 1 +
packages/extension/src/ui/utils/recovery.ts | 10 +-
packages/extension/test/keyDerivation.test.ts | 66 +
yarn.lock | 1600 ++++++++++++++++-
13 files changed, 1780 insertions(+), 52 deletions(-)
create mode 100644 packages/extension/jest.config.js
create mode 100644 packages/extension/src/background/keys/keyDerivation.ts
create mode 100644 packages/extension/test/keyDerivation.test.ts
diff --git a/packages/extension/jest.config.js b/packages/extension/jest.config.js
new file mode 100644
index 000000000..9b8aaf38e
--- /dev/null
+++ b/packages/extension/jest.config.js
@@ -0,0 +1,6 @@
+module.exports = {
+ preset: "ts-jest",
+ transform: {
+ "^.+\\.(ts|tsx)?$": "ts-jest",
+ },
+}
diff --git a/packages/extension/package.json b/packages/extension/package.json
index 8a3d37430..b4c9952e4 100644
--- a/packages/extension/package.json
+++ b/packages/extension/package.json
@@ -5,6 +5,7 @@
"license": "MIT",
"devDependencies": {
"@svgr/webpack": "^6.0.0",
+ "@types/jest": "^27.4.0",
"@types/object-hash": "^2.2.1",
"@types/react": "^17.0.34",
"@types/react-copy-to-clipboard": "^5.0.2",
@@ -19,7 +20,9 @@
"eslint-webpack-plugin": "^3.1.1",
"file-loader": "^6.2.0",
"html-webpack-plugin": "^5.5.0",
+ "jest": "^27.5.1",
"raw-loader": "^4.0.2",
+ "ts-jest": "^27.1.3",
"ts-loader": "^9.2.6",
"typescript": "^4.4.4",
"url-loader": "^4.1.1",
@@ -30,6 +33,7 @@
"build": "NODE_ENV=production webpack",
"start": "webpack",
"dev": "webpack --color --watch",
+ "test": "jest",
"version": "yarn run sync-manifest-version",
"sync-manifest-version": "node -p \"JSON.stringify({...require('./src/manifest.json'), version: '$npm_package_version'}, null, 2)\" > ./src/manifest.temp.json && prettier --write ./src/manifest.temp.json && mv ./src/manifest.temp.json ./src/manifest.json"
},
diff --git a/packages/extension/src/background/index.ts b/packages/extension/src/background/index.ts
index e2b18971b..251d6c8f2 100644
--- a/packages/extension/src/background/index.ts
+++ b/packages/extension/src/background/index.ts
@@ -446,7 +446,7 @@ import { addToWhitelist, isOnWhitelist } from "./whitelist"
})
}
- const wallet = { address: newAccount.address, network }
+ const { wallet } = newAccount
selectedWalletStore.setItem("SELECTED_WALLET", wallet)
transactionTracker.trackTransaction(newAccount.txHash, wallet, {
title: "Deploy wallet",
@@ -454,7 +454,7 @@ import { addToWhitelist, isOnWhitelist } from "./whitelist"
return sendToTabAndUi({
type: "NEW_ACCOUNT_RES",
- data: { status: "ok", ...newAccount },
+ data: { status: "ok", address: wallet.address, ...newAccount },
})
}
diff --git a/packages/extension/src/background/keys/keyDerivation.ts b/packages/extension/src/background/keys/keyDerivation.ts
new file mode 100644
index 000000000..b4f9b37f1
--- /dev/null
+++ b/packages/extension/src/background/keys/keyDerivation.ts
@@ -0,0 +1,73 @@
+import { BigNumber, BigNumberish, utils } from "ethers"
+import { ec, number } from "starknet"
+
+// from https://github.com/ethereum/EIPs/blob/master/EIPS/eip-2645.md
+// m / purpose' / layer' / application' / eth_address_1' / eth_address_2' / index
+// layer = pathHash(starknet)
+// application = pathHash(argentx)
+
+const BASE_PATH = "m/2645'/1195502025'/1148870696'/0'/0'"
+
+export function getStarkPair(index: number, secret: BigNumberish) {
+ const masterNode = utils.HDNode.fromSeed(BigNumber.from(secret).toHexString())
+
+ const path = getPathForIndex(index)
+ const childNode = masterNode.derivePath(path)
+ const grindedKey = grindKey(childNode.privateKey)
+ const starkPair = ec.getKeyPair(grindedKey)
+ return starkPair
+}
+
+export function getPathForIndex(index: number) {
+ return `${BASE_PATH}/${index}`
+}
+
+export function getNextPathIndex(paths: string[]) {
+ return (
+ paths.reduce((prev, path) => {
+ if (!path.startsWith(BASE_PATH)) {
+ return prev
+ }
+ const stringIndex = path.replace(BASE_PATH + "/", "")
+ if (!stringIndex.match(/^\d*$/gm)) {
+ return prev
+ }
+ const index = parseInt(stringIndex)
+ return Math.max(prev, index)
+ }, -1) + 1
+ )
+}
+
+export function grindKey(keySeed: string) {
+ const keyValLimit = ec.ec.n
+ const sha256EcMaxDigest = number.toBN(
+ "1 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000",
+ 16,
+ )
+ const maxAllowedVal = sha256EcMaxDigest.sub(
+ sha256EcMaxDigest.mod(keyValLimit),
+ )
+ let i = 0
+ let key = hashKeyWithIndex(keySeed, i)
+ i++
+ // Make sure the produced key is devided by the Stark EC order, and falls within the range
+ // [0, maxAllowedVal).
+ while (!key.lt(maxAllowedVal)) {
+ key = hashKeyWithIndex(keySeed, i)
+ i++
+ }
+ return "0x" + key.umod(keyValLimit).toString("hex")
+}
+
+function hashKeyWithIndex(key: string, index: number) {
+ const payload = utils.concat([utils.arrayify(key), utils.arrayify(index)])
+ const hash = utils.sha256(payload)
+ return number.toBN(hash)
+}
+
+export function pathHash(name: string) {
+ const hash = utils.arrayify(utils.sha256(utils.toUtf8Bytes(name))).slice(-4)
+ return BigNumber.from(
+ utils.concat([[hash[0] & 127], hash.slice(-3)]),
+ ).toNumber()
+}
diff --git a/packages/extension/src/background/keys/l1.ts b/packages/extension/src/background/keys/l1.ts
index 4528c74bf..a1975d699 100644
--- a/packages/extension/src/background/keys/l1.ts
+++ b/packages/extension/src/background/keys/l1.ts
@@ -7,6 +7,11 @@ import { BackupWallet } from "../../shared/backup.model"
import { getProvider } from "../../shared/networks"
import { selectedWalletStore } from "../selectedWallet"
import { Storage } from "../storage"
+import {
+ getNextPathIndex,
+ getPathForIndex,
+ getStarkPair,
+} from "./keyDerivation"
const isDev = process.env.NODE_ENV === "development"
@@ -48,7 +53,11 @@ async function getKeystore() {
if (!encKeystore) {
throw Error("No keystore exists")
}
- return encKeystore
+ const encKeystoreObj = JSON.parse(encKeystore)
+ return JSON.stringify({
+ ...encKeystoreObj,
+ wallets: encKeystoreObj["x-argentx"].accounts,
+ })
}
export async function setKeystore(keystore: string) {
@@ -130,7 +139,10 @@ async function getEncKeystore(
const N = isDev ? 64 : 32768
const backup = await wallet.encrypt(password, { scrypt: { N } }, progressFn)
- const extendedBackup = { ...JSON.parse(backup), wallets }
+ const extendedBackup = {
+ ...JSON.parse(backup),
+ "x-argentx": { version: 1, accounts: wallets },
+ }
return JSON.stringify(extendedBackup, null, 2)
}
@@ -154,10 +166,16 @@ export async function createAccount(networkId: string) {
throw Error("Password required")
}
const l1 = await getL1()
- const starkPair = ec.getKeyPair(l1.privateKey)
+ const wallets = await getWallets()
+
+ const current_paths = wallets
+ .filter((wallet) => wallet.signer.type === "local_secret")
+ .map((wallet) => wallet.signer.derivation_path)
+
+ const index = getNextPathIndex(current_paths)
+ const starkPair = getStarkPair(index, l1.privateKey)
const starkPub = ec.getStarkKey(starkPair)
const seed = ec.getStarkKey(ec.genKeyPair())
- const wallets = await getWallets()
const provider = getProvider(networkId)
const deployTransaction = await provider.deployContract(
@@ -175,13 +193,21 @@ export async function createAccount(networkId: string) {
throw new Error("Deploy transaction failed")
}
- const newWallet = { network: networkId, address: deployTransaction.address }
+ const signer = {
+ type: "local_secret",
+ derivation_path: getPathForIndex(index),
+ }
+ const newWallet = {
+ network: networkId,
+ address: deployTransaction.address,
+ signer,
+ }
const newWallets = [...wallets, newWallet]
const encKeystore = await getEncKeystore(l1, sessionPassword, newWallets)
store.setItem("encKeystore", encKeystore)
return {
- address: deployTransaction.address,
+ wallet: newWallet,
txHash: deployTransaction.transaction_hash,
wallets,
}
diff --git a/packages/extension/src/background/selectedWallet.ts b/packages/extension/src/background/selectedWallet.ts
index 04a8916a9..9c1322cc7 100644
--- a/packages/extension/src/background/selectedWallet.ts
+++ b/packages/extension/src/background/selectedWallet.ts
@@ -4,5 +4,9 @@ import { Storage } from "./storage"
export const selectedWalletStore = new Storage<{
SELECTED_WALLET: BackupWallet
}>({
- SELECTED_WALLET: { address: "", network: "" },
+ SELECTED_WALLET: {
+ address: "",
+ network: "",
+ signer: { type: "", derivation_path: "" },
+ },
})
diff --git a/packages/extension/src/shared/MessageType.ts b/packages/extension/src/shared/MessageType.ts
index 90012f226..57963e6fa 100644
--- a/packages/extension/src/shared/MessageType.ts
+++ b/packages/extension/src/shared/MessageType.ts
@@ -59,6 +59,7 @@ export type MessageType =
status: "ok"
txHash: string
address: string
+ wallet: BackupWallet
wallets: BackupWallet[]
}
}
diff --git a/packages/extension/src/shared/backup.model.ts b/packages/extension/src/shared/backup.model.ts
index 9734f73b9..75fecb767 100644
--- a/packages/extension/src/shared/backup.model.ts
+++ b/packages/extension/src/shared/backup.model.ts
@@ -1,4 +1,10 @@
+export interface BackupWalletSigner {
+ type: string
+ derivation_path: string
+}
+
export interface BackupWallet {
address: string
network: string
+ signer: BackupWalletSigner
}
diff --git a/packages/extension/src/ui/Account.ts b/packages/extension/src/ui/Account.ts
index e32f07b21..932ca4a6f 100644
--- a/packages/extension/src/ui/Account.ts
+++ b/packages/extension/src/ui/Account.ts
@@ -1,6 +1,7 @@
import ArgentCompiledContract from "!!raw-loader!../contracts/ArgentAccount.txt"
import { CompiledContract, Contract, json } from "starknet"
+import { BackupWalletSigner } from "../shared/backup.model"
import { sendMessage, waitForMessage } from "../shared/messages"
import { getProvider } from "../shared/networks"
@@ -11,12 +12,19 @@ const ArgentCompiledContractJson: CompiledContract = json.parse(
export class Account {
address: string
networkId: string
+ signer: BackupWalletSigner
deployTransaction?: string
contract: Contract
- constructor(address: string, networkId: string, deployTransaction?: string) {
+ constructor(
+ address: string,
+ networkId: string,
+ signer: BackupWalletSigner,
+ deployTransaction?: string,
+ ) {
this.address = address
this.networkId = networkId
+ this.signer = signer
this.deployTransaction = deployTransaction
this.contract = new Contract(
ArgentCompiledContractJson.abi,
@@ -54,6 +62,11 @@ export class Account {
throw new Error(result.error)
}
- return new Account(result.address, networkId, result.txHash)
+ return new Account(
+ result.address,
+ networkId,
+ result.wallet.signer,
+ result.txHash,
+ )
}
}
diff --git a/packages/extension/src/ui/utils/accounts.ts b/packages/extension/src/ui/utils/accounts.ts
index f7c9644e4..75896c66b 100644
--- a/packages/extension/src/ui/utils/accounts.ts
+++ b/packages/extension/src/ui/utils/accounts.ts
@@ -39,6 +39,7 @@ export const connectAccount = async (
data: {
address: account.address,
network: localNetworkUrl(switcherNetworkId, localhostPort),
+ signer: account.signer,
},
})
try {
diff --git a/packages/extension/src/ui/utils/recovery.ts b/packages/extension/src/ui/utils/recovery.ts
index 364bb9615..ebf6084ae 100644
--- a/packages/extension/src/ui/utils/recovery.ts
+++ b/packages/extension/src/ui/utils/recovery.ts
@@ -25,14 +25,16 @@ export const recover = async ({
? localNetworkId(lastSelectedAccount?.network)
: defaultNetwork.id
- const backupWallets = networkWallets(await getWallets(), networkId)
+ const walletAccounts = networkWallets(await getWallets(), networkId)
- const selectedAccount = backupWallets.find(
+ const selectedAccount = walletAccounts.find(
({ address }) => address === lastSelectedAccount?.address,
)?.address
- const accounts = backupWallets
- .map(({ address, network }) => new Account(address, network))
+ const accounts = walletAccounts
+ .map(
+ ({ address, network, signer }) => new Account(address, network, signer),
+ )
.reduce((acc, account) => ({ ...acc, [account.address]: account }), {})
setDefaultAccountNames(accounts)
diff --git a/packages/extension/test/keyDerivation.test.ts b/packages/extension/test/keyDerivation.test.ts
new file mode 100644
index 000000000..47601e7f7
--- /dev/null
+++ b/packages/extension/test/keyDerivation.test.ts
@@ -0,0 +1,66 @@
+import { ec } from "starknet"
+
+import {
+ getNextPathIndex,
+ getStarkPair,
+ grindKey,
+ pathHash,
+} from "../src/background/keys/keyDerivation"
+
+test("generate Stark Pair", () => {
+ // secret is an L1 private key (stored locally in a keystore file)
+ const secret =
+ "0xe6904d63affe7a13cd30345b000c9b1ffc087832332d7303cf237ffda8a177d0"
+
+ const starkPair5 = getStarkPair(5, secret)
+ expect(ec.getStarkKey(starkPair5)).toBe(
+ "0x9be28603e0203db9adcac04302ba54f97f6d27abd8b801e3a80b20d25a7f21",
+ )
+
+ const starkPair7 = getStarkPair(7, secret)
+ expect(ec.getStarkKey(starkPair7)).toBe(
+ "0x0420c619da34e3bf4b050ddb980d81d715d90bb14ff379024845111fbf9971c2",
+ )
+})
+
+test("grindKey", () => {
+ const privateKey =
+ "0x86F3E7293141F20A8BAFF320E8EE4ACCB9D4A4BF2B4D295E8CEE784DB46E0519"
+ const res = grindKey(privateKey)
+ expect(res).toBe(
+ "0x5c8c8683596c732541a59e03007b2d30dbbbb873556fe65b5fb63c16688f941",
+ )
+})
+
+test("pathHash", () => {
+ expect(pathHash("starknet")).toBe(1195502025)
+ expect(pathHash("starkex")).toBe(579218131)
+ expect(pathHash("argentx")).toBe(1148870696)
+})
+
+test("getNextPathIndex", () => {
+ expect(
+ getNextPathIndex([
+ "m/2645'/1195502025'/1148870696'/0'/0'/0",
+ "m/2645'/1195502025'/1148870696'/0'/0'/1",
+ "m/2645'/1195502025'/1148870696'/0'/0'/2",
+ ]),
+ ).toBe(3)
+
+ expect(
+ getNextPathIndex([
+ "m/2645'/1195502025'/1148870696'/0'/0'/0",
+ "m/2645'/1195502025'/1148870696'/0'/0'/4",
+ "m/2645'/1195502025'/1148870696'/0'/0'/11",
+ ]),
+ ).toBe(12)
+
+ expect(
+ getNextPathIndex([
+ "m/2645'/1195502025'/1148870696'/0'/0'/3",
+ "m/2645'/1195502025'/1148870696'/0'/0'/1",
+ ]),
+ ).toBe(4)
+
+ expect(getNextPathIndex([])).toBe(0)
+})
diff --git a/yarn.lock b/yarn.lock
index eff255845..49859f7d9 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2,6 +2,13 @@
# yarn lockfile v1
+"@ampproject/remapping@^2.1.0":
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.1.2.tgz#4edca94973ded9630d20101cd8559cedb8d8bd34"
+ integrity sha512-hoyByceqwKirw7w3Z7gnIIZC3Wx3J484Y3L/cMpXFbr7d9ZQj2mODrirNzcJa+SM3UlpWXYvKV4RlRpFXlWgXg==
+ dependencies:
+ "@jridgewell/trace-mapping" "^0.3.0"
+
"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.16.0":
version "7.16.0"
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.16.0.tgz#0dfc80309beec8411e65e706461c408b0bb9b431"
@@ -9,11 +16,39 @@
dependencies:
"@babel/highlight" "^7.16.0"
+"@babel/code-frame@^7.12.13", "@babel/code-frame@^7.16.7":
+ version "7.16.7"
+ resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.16.7.tgz#44416b6bd7624b998f5b1af5d470856c40138789"
+ integrity sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==
+ dependencies:
+ "@babel/highlight" "^7.16.7"
+
"@babel/compat-data@^7.13.11", "@babel/compat-data@^7.16.0", "@babel/compat-data@^7.16.4":
version "7.16.4"
resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.16.4.tgz#081d6bbc336ec5c2435c6346b2ae1fb98b5ac68e"
integrity sha512-1o/jo7D+kC9ZjHX5v+EHrdjl3PhxMrLSOTGsOdHJ+KL8HCaEK6ehrVL2RS6oHDZp+L7xLirLrPmQtEng769J/Q==
+"@babel/core@^7.1.0", "@babel/core@^7.12.3", "@babel/core@^7.7.2", "@babel/core@^7.8.0":
+ version "7.17.4"
+ resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.17.4.tgz#a22f1ae8999122873b3d18865e98c7a3936b8c8b"
+ integrity sha512-R9x5r4t4+hBqZTmioSnkrW+I6NmbojwjGT8p4G2Gw1thWbXIHGDnmGdLdFw0/7ljucdIrNRp7Npgb4CyBYzzJg==
+ dependencies:
+ "@ampproject/remapping" "^2.1.0"
+ "@babel/code-frame" "^7.16.7"
+ "@babel/generator" "^7.17.3"
+ "@babel/helper-compilation-targets" "^7.16.7"
+ "@babel/helper-module-transforms" "^7.16.7"
+ "@babel/helpers" "^7.17.2"
+ "@babel/parser" "^7.17.3"
+ "@babel/template" "^7.16.7"
+ "@babel/traverse" "^7.17.3"
+ "@babel/types" "^7.17.0"
+ convert-source-map "^1.7.0"
+ debug "^4.1.0"
+ gensync "^1.0.0-beta.2"
+ json5 "^2.1.2"
+ semver "^6.3.0"
+
"@babel/core@^7.15.5", "@babel/core@^7.2.2":
version "7.16.0"
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.16.0.tgz#c4ff44046f5fe310525cc9eb4ef5147f0c5374d4"
@@ -44,6 +79,15 @@
jsesc "^2.5.1"
source-map "^0.5.0"
+"@babel/generator@^7.17.3", "@babel/generator@^7.7.2":
+ version "7.17.3"
+ resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.17.3.tgz#a2c30b0c4f89858cb87050c3ffdfd36bdf443200"
+ integrity sha512-+R6Dctil/MgUsZsZAkYgK+ADNSZzJRRy0TvY65T71z/CR854xHQ1EweBYXdfT+HNeN7w0cSJJEzgxZMv40pxsg==
+ dependencies:
+ "@babel/types" "^7.17.0"
+ jsesc "^2.5.1"
+ source-map "^0.5.0"
+
"@babel/helper-annotate-as-pure@^7.16.0":
version "7.16.0"
resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.0.tgz#9a1f0ebcda53d9a2d00108c4ceace6a5d5f1f08d"
@@ -69,6 +113,16 @@
browserslist "^4.17.5"
semver "^6.3.0"
+"@babel/helper-compilation-targets@^7.16.7":
+ version "7.16.7"
+ resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.16.7.tgz#06e66c5f299601e6c7da350049315e83209d551b"
+ integrity sha512-mGojBwIWcwGD6rfqgRXVlVYmPAv7eOpIemUG3dGnDdCY4Pae70ROij3XmfrH6Fa1h1aiDylpglbZyktfzyo/hA==
+ dependencies:
+ "@babel/compat-data" "^7.16.4"
+ "@babel/helper-validator-option" "^7.16.7"
+ browserslist "^4.17.5"
+ semver "^6.3.0"
+
"@babel/helper-create-class-features-plugin@^7.16.0":
version "7.16.0"
resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.16.0.tgz#090d4d166b342a03a9fec37ef4fd5aeb9c7c6a4b"
@@ -103,6 +157,13 @@
resolve "^1.14.2"
semver "^6.1.2"
+"@babel/helper-environment-visitor@^7.16.7":
+ version "7.16.7"
+ resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz#ff484094a839bde9d89cd63cba017d7aae80ecd7"
+ integrity sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag==
+ dependencies:
+ "@babel/types" "^7.16.7"
+
"@babel/helper-explode-assignable-expression@^7.16.0":
version "7.16.0"
resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.16.0.tgz#753017337a15f46f9c09f674cff10cee9b9d7778"
@@ -119,6 +180,15 @@
"@babel/template" "^7.16.0"
"@babel/types" "^7.16.0"
+"@babel/helper-function-name@^7.16.7":
+ version "7.16.7"
+ resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.16.7.tgz#f1ec51551fb1c8956bc8dd95f38523b6cf375f8f"
+ integrity sha512-QfDfEnIUyyBSR3HtrtGECuZ6DAyCkYFp7GHl75vFtTnn6pjKeK0T1DB5lLkFvBea8MdaiUABx3osbgLyInoejA==
+ dependencies:
+ "@babel/helper-get-function-arity" "^7.16.7"
+ "@babel/template" "^7.16.7"
+ "@babel/types" "^7.16.7"
+
"@babel/helper-get-function-arity@^7.16.0":
version "7.16.0"
resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.0.tgz#0088c7486b29a9cb5d948b1a1de46db66e089cfa"
@@ -126,6 +196,13 @@
dependencies:
"@babel/types" "^7.16.0"
+"@babel/helper-get-function-arity@^7.16.7":
+ version "7.16.7"
+ resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.7.tgz#ea08ac753117a669f1508ba06ebcc49156387419"
+ integrity sha512-flc+RLSOBXzNzVhcLu6ujeHUrD6tANAOU5ojrRx/as+tbzf8+stUCj7+IfRRoAbEZqj/ahXEMsjhOhgeZsrnTw==
+ dependencies:
+ "@babel/types" "^7.16.7"
+
"@babel/helper-hoist-variables@^7.16.0":
version "7.16.0"
resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.0.tgz#4c9023c2f1def7e28ff46fc1dbcd36a39beaa81a"
@@ -133,6 +210,13 @@
dependencies:
"@babel/types" "^7.16.0"
+"@babel/helper-hoist-variables@^7.16.7":
+ version "7.16.7"
+ resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz#86bcb19a77a509c7b77d0e22323ef588fa58c246"
+ integrity sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==
+ dependencies:
+ "@babel/types" "^7.16.7"
+
"@babel/helper-member-expression-to-functions@^7.16.0":
version "7.16.0"
resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.16.0.tgz#29287040efd197c77636ef75188e81da8bccd5a4"
@@ -147,6 +231,13 @@
dependencies:
"@babel/types" "^7.16.0"
+"@babel/helper-module-imports@^7.16.7":
+ version "7.16.7"
+ resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz#25612a8091a999704461c8a222d0efec5d091437"
+ integrity sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==
+ dependencies:
+ "@babel/types" "^7.16.7"
+
"@babel/helper-module-transforms@^7.16.0":
version "7.16.0"
resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.16.0.tgz#1c82a8dd4cb34577502ebd2909699b194c3e9bb5"
@@ -161,6 +252,20 @@
"@babel/traverse" "^7.16.0"
"@babel/types" "^7.16.0"
+"@babel/helper-module-transforms@^7.16.7":
+ version "7.16.7"
+ resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.16.7.tgz#7665faeb721a01ca5327ddc6bba15a5cb34b6a41"
+ integrity sha512-gaqtLDxJEFCeQbYp9aLAefjhkKdjKcdh6DB7jniIGU3Pz52WAmP268zK0VgPz9hUNkMSYeH976K2/Y6yPadpng==
+ dependencies:
+ "@babel/helper-environment-visitor" "^7.16.7"
+ "@babel/helper-module-imports" "^7.16.7"
+ "@babel/helper-simple-access" "^7.16.7"
+ "@babel/helper-split-export-declaration" "^7.16.7"
+ "@babel/helper-validator-identifier" "^7.16.7"
+ "@babel/template" "^7.16.7"
+ "@babel/traverse" "^7.16.7"
+ "@babel/types" "^7.16.7"
+
"@babel/helper-optimise-call-expression@^7.16.0":
version "7.16.0"
resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.16.0.tgz#cecdb145d70c54096b1564f8e9f10cd7d193b338"
@@ -173,6 +278,11 @@
resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.14.5.tgz#5ac822ce97eec46741ab70a517971e443a70c5a9"
integrity sha512-/37qQCE3K0vvZKwoK4XU/irIJQdIfCJuhU5eKnNxpFDsOkgFaUAwbv+RYw6eYgsC0E4hS7r5KqGULUogqui0fQ==
+"@babel/helper-plugin-utils@^7.16.7":
+ version "7.16.7"
+ resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.16.7.tgz#aa3a8ab4c3cceff8e65eb9e73d87dc4ff320b2f5"
+ integrity sha512-Qg3Nk7ZxpgMrsox6HreY1ZNKdBq7K72tDSliA6dCl5f007jR4ne8iD5UzuNnCJH2xBf2BEEVGr+/OL6Gdp7RxA==
+
"@babel/helper-remap-async-to-generator@^7.16.0", "@babel/helper-remap-async-to-generator@^7.16.4":
version "7.16.4"
resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.16.4.tgz#5d7902f61349ff6b963e07f06a389ce139fbfe6e"
@@ -199,6 +309,13 @@
dependencies:
"@babel/types" "^7.16.0"
+"@babel/helper-simple-access@^7.16.7":
+ version "7.16.7"
+ resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.16.7.tgz#d656654b9ea08dbb9659b69d61063ccd343ff0f7"
+ integrity sha512-ZIzHVyoeLMvXMN/vok/a4LWRy8G2v205mNP0XOuf9XRLyX5/u9CnVulUtDgUTama3lT+bf/UqucuZjqiGuTS1g==
+ dependencies:
+ "@babel/types" "^7.16.7"
+
"@babel/helper-skip-transparent-expression-wrappers@^7.16.0":
version "7.16.0"
resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.16.0.tgz#0ee3388070147c3ae051e487eca3ebb0e2e8bb09"
@@ -213,16 +330,33 @@
dependencies:
"@babel/types" "^7.16.0"
+"@babel/helper-split-export-declaration@^7.16.7":
+ version "7.16.7"
+ resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz#0b648c0c42da9d3920d85ad585f2778620b8726b"
+ integrity sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==
+ dependencies:
+ "@babel/types" "^7.16.7"
+
"@babel/helper-validator-identifier@^7.15.7":
version "7.15.7"
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz#220df993bfe904a4a6b02ab4f3385a5ebf6e2389"
integrity sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w==
+"@babel/helper-validator-identifier@^7.16.7":
+ version "7.16.7"
+ resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz#e8c602438c4a8195751243da9031d1607d247cad"
+ integrity sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==
+
"@babel/helper-validator-option@^7.14.5":
version "7.14.5"
resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.14.5.tgz#6e72a1fff18d5dfcb878e1e62f1a021c4b72d5a3"
integrity sha512-OX8D5eeX4XwcroVW45NMvoYaIuFI+GQpA2a8Gi+X/U/cDUIRsV37qQfF905F0htTRCREQIB4KqPeaveRJUl3Ow==
+"@babel/helper-validator-option@^7.16.7":
+ version "7.16.7"
+ resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz#b203ce62ce5fe153899b617c08957de860de4d23"
+ integrity sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==
+
"@babel/helper-wrap-function@^7.16.0":
version "7.16.0"
resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.16.0.tgz#b3cf318afce774dfe75b86767cd6d68f3482e57c"
@@ -242,6 +376,15 @@
"@babel/traverse" "^7.16.3"
"@babel/types" "^7.16.0"
+"@babel/helpers@^7.17.2":
+ version "7.17.2"
+ resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.17.2.tgz#23f0a0746c8e287773ccd27c14be428891f63417"
+ integrity sha512-0Qu7RLR1dILozr/6M0xgj+DFPmi6Bnulgm9M8BVa9ZCWxDqlSnqt3cf8IDPB5m45sVXUZ0kuQAgUrdSFFH79fQ==
+ dependencies:
+ "@babel/template" "^7.16.7"
+ "@babel/traverse" "^7.17.0"
+ "@babel/types" "^7.17.0"
+
"@babel/highlight@^7.16.0":
version "7.16.0"
resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.16.0.tgz#6ceb32b2ca4b8f5f361fb7fd821e3fddf4a1725a"
@@ -251,11 +394,25 @@
chalk "^2.0.0"
js-tokens "^4.0.0"
+"@babel/highlight@^7.16.7":
+ version "7.16.10"
+ resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.16.10.tgz#744f2eb81579d6eea753c227b0f570ad785aba88"
+ integrity sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw==
+ dependencies:
+ "@babel/helper-validator-identifier" "^7.16.7"
+ chalk "^2.0.0"
+ js-tokens "^4.0.0"
+
"@babel/parser@^7.0.0-beta.54", "@babel/parser@^7.16.0", "@babel/parser@^7.16.3":
version "7.16.4"
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.16.4.tgz#d5f92f57cf2c74ffe9b37981c0e72fee7311372e"
integrity sha512-6V0qdPUaiVHH3RtZeLIsc+6pDhbYzHR8ogA8w+f+Wc77DuXto19g2QUwveINoS34Uw+W8/hQDGJCx+i4n7xcng==
+"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.16.7", "@babel/parser@^7.17.3":
+ version "7.17.3"
+ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.17.3.tgz#b07702b982990bf6fdc1da5049a23fece4c5c3d0"
+ integrity sha512-7yJPvPV+ESz2IUTPbOL+YkIGyCqOyNIzdguKQuJGnH7bg1WTIifuM21YqokFt/THWh1AkCRn9IgoykTRCBVpzA==
+
"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.16.2":
version "7.16.2"
resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.16.2.tgz#2977fca9b212db153c195674e57cfab807733183"
@@ -407,7 +564,14 @@
dependencies:
"@babel/helper-plugin-utils" "^7.8.0"
-"@babel/plugin-syntax-class-properties@^7.12.13":
+"@babel/plugin-syntax-bigint@^7.8.3":
+ version "7.8.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz#4c9a6f669f5d0cdf1b90a1671e9a146be5300cea"
+ integrity sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.8.0"
+
+"@babel/plugin-syntax-class-properties@^7.12.13", "@babel/plugin-syntax-class-properties@^7.8.3":
version "7.12.13"
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10"
integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==
@@ -435,6 +599,13 @@
dependencies:
"@babel/helper-plugin-utils" "^7.8.3"
+"@babel/plugin-syntax-import-meta@^7.8.3":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51"
+ integrity sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.10.4"
+
"@babel/plugin-syntax-json-strings@^7.8.3":
version "7.8.3"
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a"
@@ -449,7 +620,7 @@
dependencies:
"@babel/helper-plugin-utils" "^7.14.5"
-"@babel/plugin-syntax-logical-assignment-operators@^7.10.4":
+"@babel/plugin-syntax-logical-assignment-operators@^7.10.4", "@babel/plugin-syntax-logical-assignment-operators@^7.8.3":
version "7.10.4"
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699"
integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==
@@ -463,7 +634,7 @@
dependencies:
"@babel/helper-plugin-utils" "^7.8.0"
-"@babel/plugin-syntax-numeric-separator@^7.10.4":
+"@babel/plugin-syntax-numeric-separator@^7.10.4", "@babel/plugin-syntax-numeric-separator@^7.8.3":
version "7.10.4"
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97"
integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==
@@ -498,7 +669,7 @@
dependencies:
"@babel/helper-plugin-utils" "^7.14.5"
-"@babel/plugin-syntax-top-level-await@^7.14.5":
+"@babel/plugin-syntax-top-level-await@^7.14.5", "@babel/plugin-syntax-top-level-await@^7.8.3":
version "7.14.5"
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c"
integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==
@@ -512,6 +683,13 @@
dependencies:
"@babel/helper-plugin-utils" "^7.14.5"
+"@babel/plugin-syntax-typescript@^7.7.2":
+ version "7.16.7"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.16.7.tgz#39c9b55ee153151990fb038651d58d3fd03f98f8"
+ integrity sha512-YhUIJHHGkqPgEcMYkPCKTyGUdoGKWtopIycQyjJH8OjvRgOYsXsaKehLVPScKJWAULPxMa4N1vCe6szREFlZ7A==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.16.7"
+
"@babel/plugin-transform-arrow-functions@^7.16.0":
version "7.16.0"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.16.0.tgz#951706f8b449c834ed07bd474c0924c944b95a8e"
@@ -945,6 +1123,15 @@
"@babel/parser" "^7.16.0"
"@babel/types" "^7.16.0"
+"@babel/template@^7.16.7", "@babel/template@^7.3.3":
+ version "7.16.7"
+ resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.16.7.tgz#8d126c8701fde4d66b264b3eba3d96f07666d155"
+ integrity sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==
+ dependencies:
+ "@babel/code-frame" "^7.16.7"
+ "@babel/parser" "^7.16.7"
+ "@babel/types" "^7.16.7"
+
"@babel/traverse@^7.0.0-beta.54", "@babel/traverse@^7.13.0", "@babel/traverse@^7.16.0", "@babel/traverse@^7.16.3", "@babel/traverse@^7.4.5":
version "7.16.3"
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.16.3.tgz#f63e8a938cc1b780f66d9ed3c54f532ca2d14787"
@@ -960,6 +1147,30 @@
debug "^4.1.0"
globals "^11.1.0"
+"@babel/traverse@^7.16.7", "@babel/traverse@^7.17.0", "@babel/traverse@^7.17.3", "@babel/traverse@^7.7.2":
+ version "7.17.3"
+ resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.17.3.tgz#0ae0f15b27d9a92ba1f2263358ea7c4e7db47b57"
+ integrity sha512-5irClVky7TxRWIRtxlh2WPUUOLhcPN06AGgaQSB8AEwuyEBgJVuJ5imdHm5zxk8w0QS5T+tDfnDxAlhWjpb7cw==
+ dependencies:
+ "@babel/code-frame" "^7.16.7"
+ "@babel/generator" "^7.17.3"
+ "@babel/helper-environment-visitor" "^7.16.7"
+ "@babel/helper-function-name" "^7.16.7"
+ "@babel/helper-hoist-variables" "^7.16.7"
+ "@babel/helper-split-export-declaration" "^7.16.7"
+ "@babel/parser" "^7.17.3"
+ "@babel/types" "^7.17.0"
+ debug "^4.1.0"
+ globals "^11.1.0"
+
+"@babel/types@^7.0.0", "@babel/types@^7.16.7", "@babel/types@^7.17.0", "@babel/types@^7.3.0", "@babel/types@^7.3.3":
+ version "7.17.0"
+ resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.17.0.tgz#a826e368bccb6b3d84acd76acad5c0d87342390b"
+ integrity sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==
+ dependencies:
+ "@babel/helper-validator-identifier" "^7.16.7"
+ to-fast-properties "^2.0.0"
+
"@babel/types@^7.0.0-beta.54", "@babel/types@^7.15.6", "@babel/types@^7.16.0", "@babel/types@^7.4.4":
version "7.16.0"
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.16.0.tgz#db3b313804f96aadd0b776c4823e127ad67289ba"
@@ -968,6 +1179,11 @@
"@babel/helper-validator-identifier" "^7.15.7"
to-fast-properties "^2.0.0"
+"@bcoe/v8-coverage@^0.2.3":
+ version "0.2.3"
+ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
+ integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
+
"@discoveryjs/json-ext@^0.5.0":
version "0.5.5"
resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.5.tgz#9283c9ce5b289a3c4f61c12757469e59377f81f3"
@@ -1421,6 +1637,209 @@
resolved "https://registry.yarnpkg.com/@hutson/parse-repository-url/-/parse-repository-url-3.0.2.tgz#98c23c950a3d9b6c8f0daed06da6c3af06981340"
integrity sha512-H9XAx3hc0BQHY6l+IFSWHDySypcXsvsuLhgYLUGywmJ5pswRVQJUHpOsobnLYp2ZUaUlKiKDrgWWhosOwAEM8Q==
+"@istanbuljs/load-nyc-config@^1.0.0":
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced"
+ integrity sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==
+ dependencies:
+ camelcase "^5.3.1"
+ find-up "^4.1.0"
+ get-package-type "^0.1.0"
+ js-yaml "^3.13.1"
+ resolve-from "^5.0.0"
+
+"@istanbuljs/schema@^0.1.2":
+ version "0.1.3"
+ resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98"
+ integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==
+
+"@jest/console@^27.5.1":
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/@jest/console/-/console-27.5.1.tgz#260fe7239602fe5130a94f1aa386eff54b014bba"
+ integrity sha512-kZ/tNpS3NXn0mlXXXPNuDZnb4c0oZ20r4K5eemM2k30ZC3G0T02nXUvyhf5YdbXWHPEJLc9qGLxEZ216MdL+Zg==
+ dependencies:
+ "@jest/types" "^27.5.1"
+ "@types/node" "*"
+ chalk "^4.0.0"
+ jest-message-util "^27.5.1"
+ jest-util "^27.5.1"
+ slash "^3.0.0"
+
+"@jest/core@^27.5.1":
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/@jest/core/-/core-27.5.1.tgz#267ac5f704e09dc52de2922cbf3af9edcd64b626"
+ integrity sha512-AK6/UTrvQD0Cd24NSqmIA6rKsu0tKIxfiCducZvqxYdmMisOYAsdItspT+fQDQYARPf8XgjAFZi0ogW2agH5nQ==
+ dependencies:
+ "@jest/console" "^27.5.1"
+ "@jest/reporters" "^27.5.1"
+ "@jest/test-result" "^27.5.1"
+ "@jest/transform" "^27.5.1"
+ "@jest/types" "^27.5.1"
+ "@types/node" "*"
+ ansi-escapes "^4.2.1"
+ chalk "^4.0.0"
+ emittery "^0.8.1"
+ exit "^0.1.2"
+ graceful-fs "^4.2.9"
+ jest-changed-files "^27.5.1"
+ jest-config "^27.5.1"
+ jest-haste-map "^27.5.1"
+ jest-message-util "^27.5.1"
+ jest-regex-util "^27.5.1"
+ jest-resolve "^27.5.1"
+ jest-resolve-dependencies "^27.5.1"
+ jest-runner "^27.5.1"
+ jest-runtime "^27.5.1"
+ jest-snapshot "^27.5.1"
+ jest-util "^27.5.1"
+ jest-validate "^27.5.1"
+ jest-watcher "^27.5.1"
+ micromatch "^4.0.4"
+ rimraf "^3.0.0"
+ slash "^3.0.0"
+ strip-ansi "^6.0.0"
+
+"@jest/environment@^27.5.1":
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-27.5.1.tgz#d7425820511fe7158abbecc010140c3fd3be9c74"
+ integrity sha512-/WQjhPJe3/ghaol/4Bq480JKXV/Rfw8nQdN7f41fM8VDHLcxKXou6QyXAh3EFr9/bVG3x74z1NWDkP87EiY8gA==
+ dependencies:
+ "@jest/fake-timers" "^27.5.1"
+ "@jest/types" "^27.5.1"
+ "@types/node" "*"
+ jest-mock "^27.5.1"
+
+"@jest/fake-timers@^27.5.1":
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-27.5.1.tgz#76979745ce0579c8a94a4678af7a748eda8ada74"
+ integrity sha512-/aPowoolwa07k7/oM3aASneNeBGCmGQsc3ugN4u6s4C/+s5M64MFo/+djTdiwcbQlRfFElGuDXWzaWj6QgKObQ==
+ dependencies:
+ "@jest/types" "^27.5.1"
+ "@sinonjs/fake-timers" "^8.0.1"
+ "@types/node" "*"
+ jest-message-util "^27.5.1"
+ jest-mock "^27.5.1"
+ jest-util "^27.5.1"
+
+"@jest/globals@^27.5.1":
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-27.5.1.tgz#7ac06ce57ab966566c7963431cef458434601b2b"
+ integrity sha512-ZEJNB41OBQQgGzgyInAv0UUfDDj3upmHydjieSxFvTRuZElrx7tXg/uVQ5hYVEwiXs3+aMsAeEc9X7xiSKCm4Q==
+ dependencies:
+ "@jest/environment" "^27.5.1"
+ "@jest/types" "^27.5.1"
+ expect "^27.5.1"
+
+"@jest/reporters@^27.5.1":
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-27.5.1.tgz#ceda7be96170b03c923c37987b64015812ffec04"
+ integrity sha512-cPXh9hWIlVJMQkVk84aIvXuBB4uQQmFqZiacloFuGiP3ah1sbCxCosidXFDfqG8+6fO1oR2dTJTlsOy4VFmUfw==
+ dependencies:
+ "@bcoe/v8-coverage" "^0.2.3"
+ "@jest/console" "^27.5.1"
+ "@jest/test-result" "^27.5.1"
+ "@jest/transform" "^27.5.1"
+ "@jest/types" "^27.5.1"
+ "@types/node" "*"
+ chalk "^4.0.0"
+ collect-v8-coverage "^1.0.0"
+ exit "^0.1.2"
+ glob "^7.1.2"
+ graceful-fs "^4.2.9"
+ istanbul-lib-coverage "^3.0.0"
+ istanbul-lib-instrument "^5.1.0"
+ istanbul-lib-report "^3.0.0"
+ istanbul-lib-source-maps "^4.0.0"
+ istanbul-reports "^3.1.3"
+ jest-haste-map "^27.5.1"
+ jest-resolve "^27.5.1"
+ jest-util "^27.5.1"
+ jest-worker "^27.5.1"
+ slash "^3.0.0"
+ source-map "^0.6.0"
+ string-length "^4.0.1"
+ terminal-link "^2.0.0"
+ v8-to-istanbul "^8.1.0"
+
+"@jest/source-map@^27.5.1":
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-27.5.1.tgz#6608391e465add4205eae073b55e7f279e04e8cf"
+ integrity sha512-y9NIHUYF3PJRlHk98NdC/N1gl88BL08aQQgu4k4ZopQkCw9t9cV8mtl3TV8b/YCB8XaVTFrmUTAJvjsntDireg==
+ dependencies:
+ callsites "^3.0.0"
+ graceful-fs "^4.2.9"
+ source-map "^0.6.0"
+
+"@jest/test-result@^27.5.1":
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-27.5.1.tgz#56a6585fa80f7cdab72b8c5fc2e871d03832f5bb"
+ integrity sha512-EW35l2RYFUcUQxFJz5Cv5MTOxlJIQs4I7gxzi2zVU7PJhOwfYq1MdC5nhSmYjX1gmMmLPvB3sIaC+BkcHRBfag==
+ dependencies:
+ "@jest/console" "^27.5.1"
+ "@jest/types" "^27.5.1"
+ "@types/istanbul-lib-coverage" "^2.0.0"
+ collect-v8-coverage "^1.0.0"
+
+"@jest/test-sequencer@^27.5.1":
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-27.5.1.tgz#4057e0e9cea4439e544c6353c6affe58d095745b"
+ integrity sha512-LCheJF7WB2+9JuCS7VB/EmGIdQuhtqjRNI9A43idHv3E4KltCTsPsLxvdaubFHSYwY/fNjMWjl6vNRhDiN7vpQ==
+ dependencies:
+ "@jest/test-result" "^27.5.1"
+ graceful-fs "^4.2.9"
+ jest-haste-map "^27.5.1"
+ jest-runtime "^27.5.1"
+
+"@jest/transform@^27.5.1":
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-27.5.1.tgz#6c3501dcc00c4c08915f292a600ece5ecfe1f409"
+ integrity sha512-ipON6WtYgl/1329g5AIJVbUuEh0wZVbdpGwC99Jw4LwuoBNS95MVphU6zOeD9pDkon+LLbFL7lOQRapbB8SCHw==
+ dependencies:
+ "@babel/core" "^7.1.0"
+ "@jest/types" "^27.5.1"
+ babel-plugin-istanbul "^6.1.1"
+ chalk "^4.0.0"
+ convert-source-map "^1.4.0"
+ fast-json-stable-stringify "^2.0.0"
+ graceful-fs "^4.2.9"
+ jest-haste-map "^27.5.1"
+ jest-regex-util "^27.5.1"
+ jest-util "^27.5.1"
+ micromatch "^4.0.4"
+ pirates "^4.0.4"
+ slash "^3.0.0"
+ source-map "^0.6.1"
+ write-file-atomic "^3.0.0"
+
+"@jest/types@^27.5.1":
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/@jest/types/-/types-27.5.1.tgz#3c79ec4a8ba61c170bf937bcf9e98a9df175ec80"
+ integrity sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==
+ dependencies:
+ "@types/istanbul-lib-coverage" "^2.0.0"
+ "@types/istanbul-reports" "^3.0.0"
+ "@types/node" "*"
+ "@types/yargs" "^16.0.0"
+ chalk "^4.0.0"
+
+"@jridgewell/resolve-uri@^3.0.3":
+ version "3.0.5"
+ resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.0.5.tgz#68eb521368db76d040a6315cdb24bf2483037b9c"
+ integrity sha512-VPeQ7+wH0itvQxnG+lIzWgkysKIr3L9sslimFW55rHMdGu/qCQ5z5h9zq4gI8uBtqkpHhsF4Z/OwExufUCThew==
+
+"@jridgewell/sourcemap-codec@^1.4.10":
+ version "1.4.11"
+ resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.11.tgz#771a1d8d744eeb71b6adb35808e1a6c7b9b8c8ec"
+ integrity sha512-Fg32GrJo61m+VqYSdRSjRXMjQ06j8YIYfcTqndLYVAaHmroZHLJZCydsWBOTDqXS2v+mjxohBWEMfg97GXmYQg==
+
+"@jridgewell/trace-mapping@^0.3.0":
+ version "0.3.4"
+ resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.4.tgz#f6a0832dffd5b8a6aaa633b7d9f8e8e94c83a0c3"
+ integrity sha512-vFv9ttIedivx0ux3QSjhgtCVjPZd5l46ZOMDSCwnH1yUO2e964gO8LZGyv2QkqcgR6TnBU1v+1IFqmeoG+0UJQ==
+ dependencies:
+ "@jridgewell/resolve-uri" "^3.0.3"
+ "@jridgewell/sourcemap-codec" "^1.4.10"
+
"@lerna/add@4.0.0":
version "4.0.0"
resolved "https://registry.yarnpkg.com/@lerna/add/-/add-4.0.0.tgz#c36f57d132502a57b9e7058d1548b7a565ef183f"
@@ -2503,6 +2922,20 @@
resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.1.0.tgz#7f698254aadf921e48dda8c0a6b304026b8a9323"
integrity sha512-JLo+Y592QzIE+q7Dl2pMUtt4q8SKYI5jDrZxrozEQxnGVOyYE+GWK9eLkwTaeN9DDctlaRAQ3TBmzZ1qdLE30A==
+"@sinonjs/commons@^1.7.0":
+ version "1.8.3"
+ resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.3.tgz#3802ddd21a50a949b6721ddd72da36e67e7f1b2d"
+ integrity sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==
+ dependencies:
+ type-detect "4.0.8"
+
+"@sinonjs/fake-timers@^8.0.1":
+ version "8.1.0"
+ resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-8.1.0.tgz#3fdc2b6cb58935b21bfb8d1625eb1300484316e7"
+ integrity sha512-OAPJUAtgeINhh/TAlUID4QTs53Njm7xzddaVlEs/SXwgtiD1tW22zAB/W1wdqfrpmikgaWQ9Fw6Ws+hsiRm5Vg==
+ dependencies:
+ "@sinonjs/commons" "^1.7.0"
+
"@svgr/babel-plugin-add-jsx-attribute@^6.0.0":
version "6.0.0"
resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-6.0.0.tgz#bd6d1ff32a31b82b601e73672a789cc41e84fe18"
@@ -2629,6 +3062,39 @@
resolved "https://registry.yarnpkg.com/@tsconfig/svelte/-/svelte-3.0.0.tgz#b06e059209f04c414de0069f2f0e2796d979fc6f"
integrity sha512-pYrtLtOwku/7r1i9AMONsJMVYAtk3hzOfiGNekhtq5tYBGA7unMve8RvUclKLMT3PrihvJqUmzsRGh0RP84hKg==
+"@types/babel__core@^7.0.0", "@types/babel__core@^7.1.14":
+ version "7.1.18"
+ resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.18.tgz#1a29abcc411a9c05e2094c98f9a1b7da6cdf49f8"
+ integrity sha512-S7unDjm/C7z2A2R9NzfKCK1I+BAALDtxEmsJBwlB3EzNfb929ykjL++1CK9LO++EIp2fQrC8O+BwjKvz6UeDyQ==
+ dependencies:
+ "@babel/parser" "^7.1.0"
+ "@babel/types" "^7.0.0"
+ "@types/babel__generator" "*"
+ "@types/babel__template" "*"
+ "@types/babel__traverse" "*"
+
+"@types/babel__generator@*":
+ version "7.6.4"
+ resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.4.tgz#1f20ce4c5b1990b37900b63f050182d28c2439b7"
+ integrity sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==
+ dependencies:
+ "@babel/types" "^7.0.0"
+
+"@types/babel__template@*":
+ version "7.4.1"
+ resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.4.1.tgz#3d1a48fd9d6c0edfd56f2ff578daed48f36c8969"
+ integrity sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==
+ dependencies:
+ "@babel/parser" "^7.1.0"
+ "@babel/types" "^7.0.0"
+
+"@types/babel__traverse@*", "@types/babel__traverse@^7.0.4", "@types/babel__traverse@^7.0.6":
+ version "7.14.2"
+ resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.14.2.tgz#ffcd470bbb3f8bf30481678fb5502278ca833a43"
+ integrity sha512-K2waXdXBi2302XUdcHcR1jCeU0LL4TD9HRs/gk0N2Xvrht+G/BfJa4QObBQZfhMdxiCpV3COl5Nfq4uKTeTnJA==
+ dependencies:
+ "@babel/types" "^7.3.0"
+
"@types/chrome@0.0.99":
version "0.0.99"
resolved "https://registry.yarnpkg.com/@types/chrome/-/chrome-0.0.99.tgz#9453a5082a5291e78a0d24604b69796b16e9342c"
@@ -2682,6 +3148,13 @@
resolved "https://registry.yarnpkg.com/@types/filewriter/-/filewriter-0.0.29.tgz#a48795ecadf957f6c0d10e0c34af86c098fa5bee"
integrity sha512-BsPXH/irW0ht0Ji6iw/jJaK8Lj3FJemon2gvEqHKpCdDCeemHa+rI3WBGq5z7cDMZgoLjY40oninGxqk+8NzNQ==
+"@types/graceful-fs@^4.1.2":
+ version "4.1.5"
+ resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.5.tgz#21ffba0d98da4350db64891f92a9e5db3cdb4e15"
+ integrity sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw==
+ dependencies:
+ "@types/node" "*"
+
"@types/hoist-non-react-statics@*":
version "3.3.1"
resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz#1124aafe5118cb591977aeb1ceaaed1070eb039f"
@@ -2695,6 +3168,33 @@
resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz#4fc33a00c1d0c16987b1a20cf92d20614c55ac35"
integrity sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==
+"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1":
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz#8467d4b3c087805d63580480890791277ce35c44"
+ integrity sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==
+
+"@types/istanbul-lib-report@*":
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#c14c24f18ea8190c118ee7562b7ff99a36552686"
+ integrity sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==
+ dependencies:
+ "@types/istanbul-lib-coverage" "*"
+
+"@types/istanbul-reports@^3.0.0":
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz#9153fe98bba2bd565a63add9436d6f0d7f8468ff"
+ integrity sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==
+ dependencies:
+ "@types/istanbul-lib-report" "*"
+
+"@types/jest@^27.4.0":
+ version "27.4.0"
+ resolved "https://registry.yarnpkg.com/@types/jest/-/jest-27.4.0.tgz#037ab8b872067cae842a320841693080f9cb84ed"
+ integrity sha512-gHl8XuC1RZ8H2j5sHv/JqsaxXkDDM9iDOgu0Wp8sjs4u/snb2PVehyWXJPr+ORA0RPpgw231mnutWI1+0hgjIQ==
+ dependencies:
+ jest-diff "^27.0.0"
+ pretty-format "^27.0.0"
+
"@types/json-schema@*", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9":
version "7.0.9"
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.9.tgz#97edc9037ea0c38585320b28964dde3b39e4660d"
@@ -2740,6 +3240,11 @@
resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0"
integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==
+"@types/prettier@^2.1.5":
+ version "2.4.4"
+ resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.4.4.tgz#5d9b63132df54d8909fce1c3f8ca260fdd693e17"
+ integrity sha512-ReVR2rLTV1kvtlWFyuot+d1pkpG2Fw/XKE3PDAdj57rbM97ttSp9JZ2UsP+2EHTylra9cUf6JA7tGwW1INzUrA==
+
"@types/prop-types@*", "@types/prop-types@^15.7.4":
version "15.7.4"
resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.4.tgz#fcf7205c25dff795ee79af1e30da2c9790808f11"
@@ -2806,6 +3311,11 @@
resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.2.tgz#1a62f89525723dde24ba1b01b092bf5df8ad4d39"
integrity sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==
+"@types/stack-utils@^2.0.0":
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.1.tgz#20f18294f797f2209b5f65c8e3b5c8e8261d127c"
+ integrity sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==
+
"@types/styled-components@^5.1.15":
version "5.1.23"
resolved "https://registry.yarnpkg.com/@types/styled-components/-/styled-components-5.1.23.tgz#11e5740047f292b42a042c60c0ef16b58d5adef6"
@@ -2820,6 +3330,18 @@
resolved "https://registry.yarnpkg.com/@types/webextension-polyfill/-/webextension-polyfill-0.8.2.tgz#d909371d332ce3e1a94684624deb0a8693eee900"
integrity sha512-Pd+p5AQx6s78jr4gDC2p3vbw+uxP2DLLqE9iAJJpZ+OUqDm3txr6uN2wUBEwjVgZTNdBHPsxawGvPCTipF2s6w==
+"@types/yargs-parser@*":
+ version "20.2.1"
+ resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-20.2.1.tgz#3b9ce2489919d9e4fea439b76916abc34b2df129"
+ integrity sha512-7tFImggNeNBVMsn0vLrpn1H1uPrUBdnARPTpZoitY37ZrdJREzf7I16tMrlK3hen349gr1NYh8CmZQa7CTG6Aw==
+
+"@types/yargs@^16.0.0":
+ version "16.0.4"
+ resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-16.0.4.tgz#26aad98dd2c2a38e421086ea9ad42b9e51642977"
+ integrity sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==
+ dependencies:
+ "@types/yargs-parser" "*"
+
"@typescript-eslint/eslint-plugin@^5.10.1":
version "5.12.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.12.0.tgz#bb46dd7ce7015c0928b98af1e602118e97df6c70"
@@ -3056,11 +3578,24 @@ JSONStream@^1.0.4:
jsonparse "^1.2.0"
through ">=2.2.7 <3"
+abab@^2.0.3, abab@^2.0.5:
+ version "2.0.5"
+ resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.5.tgz#c0b678fb32d60fc1219c784d6a826fe385aeb79a"
+ integrity sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q==
+
abbrev@1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8"
integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==
+acorn-globals@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-6.0.0.tgz#46cdd39f0f8ff08a876619b55f5ac8a6dc770b45"
+ integrity sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==
+ dependencies:
+ acorn "^7.1.1"
+ acorn-walk "^7.1.1"
+
acorn-import-assertions@^1.7.6:
version "1.8.0"
resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz#ba2b5939ce62c238db6d93d81c9b111b29b855e9"
@@ -3071,7 +3606,17 @@ acorn-jsx@^5.3.1:
resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937"
integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==
-acorn@^8.4.1, acorn@^8.7.0:
+acorn-walk@^7.1.1:
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc"
+ integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==
+
+acorn@^7.1.1:
+ version "7.4.1"
+ resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa"
+ integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==
+
+acorn@^8.2.4, acorn@^8.4.1, acorn@^8.7.0:
version "8.7.0"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.0.tgz#90951fde0f8f09df93549481e5fc141445b791cf"
integrity sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==
@@ -3180,7 +3725,12 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0:
dependencies:
color-convert "^2.0.1"
-anymatch@~3.1.2:
+ansi-styles@^5.0.0:
+ version "5.2.0"
+ resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b"
+ integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==
+
+anymatch@^3.0.3, anymatch@~3.1.2:
version "3.1.2"
resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716"
integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==
@@ -3349,6 +3899,20 @@ axobject-query@^2.2.0:
resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-2.2.0.tgz#943d47e10c0b704aa42275e20edf3722648989be"
integrity sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA==
+babel-jest@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-27.5.1.tgz#a1bf8d61928edfefd21da27eb86a695bfd691444"
+ integrity sha512-cdQ5dXjGRd0IBRATiQ4mZGlGlRE8kJpjPOixdNRdT+m3UcNqmYWN6rK6nvtXYfY3D76cb8s/O1Ss8ea24PIwcg==
+ dependencies:
+ "@jest/transform" "^27.5.1"
+ "@jest/types" "^27.5.1"
+ "@types/babel__core" "^7.1.14"
+ babel-plugin-istanbul "^6.1.1"
+ babel-preset-jest "^27.5.1"
+ chalk "^4.0.0"
+ graceful-fs "^4.2.9"
+ slash "^3.0.0"
+
babel-plugin-dynamic-import-node@^2.3.3:
version "2.3.3"
resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz#84fda19c976ec5c6defef57f9427b3def66e17a3"
@@ -3356,6 +3920,27 @@ babel-plugin-dynamic-import-node@^2.3.3:
dependencies:
object.assign "^4.1.0"
+babel-plugin-istanbul@^6.1.1:
+ version "6.1.1"
+ resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz#fa88ec59232fd9b4e36dbbc540a8ec9a9b47da73"
+ integrity sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.0.0"
+ "@istanbuljs/load-nyc-config" "^1.0.0"
+ "@istanbuljs/schema" "^0.1.2"
+ istanbul-lib-instrument "^5.0.4"
+ test-exclude "^6.0.0"
+
+babel-plugin-jest-hoist@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.5.1.tgz#9be98ecf28c331eb9f5df9c72d6f89deb8181c2e"
+ integrity sha512-50wCwD5EMNW4aRpOwtqzyZHIewTYNxLA4nhB+09d8BIssfNfzBRhkBIHiaPv1Si226TQSvp8gxAJm2iY2qs2hQ==
+ dependencies:
+ "@babel/template" "^7.3.3"
+ "@babel/types" "^7.3.3"
+ "@types/babel__core" "^7.0.0"
+ "@types/babel__traverse" "^7.0.6"
+
babel-plugin-polyfill-corejs2@^0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.0.tgz#407082d0d355ba565af24126fb6cb8e9115251fd"
@@ -3395,6 +3980,32 @@ babel-plugin-syntax-jsx@^6.18.0:
resolved "https://registry.yarnpkg.com/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz#0af32a9a6e13ca7a3fd5069e62d7b0f58d0d8946"
integrity sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY=
+babel-preset-current-node-syntax@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz#b4399239b89b2a011f9ddbe3e4f401fc40cff73b"
+ integrity sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==
+ dependencies:
+ "@babel/plugin-syntax-async-generators" "^7.8.4"
+ "@babel/plugin-syntax-bigint" "^7.8.3"
+ "@babel/plugin-syntax-class-properties" "^7.8.3"
+ "@babel/plugin-syntax-import-meta" "^7.8.3"
+ "@babel/plugin-syntax-json-strings" "^7.8.3"
+ "@babel/plugin-syntax-logical-assignment-operators" "^7.8.3"
+ "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3"
+ "@babel/plugin-syntax-numeric-separator" "^7.8.3"
+ "@babel/plugin-syntax-object-rest-spread" "^7.8.3"
+ "@babel/plugin-syntax-optional-catch-binding" "^7.8.3"
+ "@babel/plugin-syntax-optional-chaining" "^7.8.3"
+ "@babel/plugin-syntax-top-level-await" "^7.8.3"
+
+babel-preset-jest@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-27.5.1.tgz#91f10f58034cb7989cb4f962b69fa6eef6a6bc81"
+ integrity sha512-Nptf2FzlPCWYuJg41HBqXVT8ym6bXOevuCTbhxlUpjwtysGaIWFvDEjp4y+G7fl13FgOdjs7P/DmErqH7da0Ag==
+ dependencies:
+ babel-plugin-jest-hoist "^27.5.1"
+ babel-preset-current-node-syntax "^1.0.0"
+
balanced-match@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
@@ -3467,6 +4078,11 @@ brorand@^1.1.0:
resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f"
integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=
+browser-process-hrtime@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz#3c9b4b7d782c8121e56f10106d84c0d0ffc94626"
+ integrity sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==
+
browserslist@^4.14.5, browserslist@^4.17.5, browserslist@^4.17.6:
version "4.18.1"
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.18.1.tgz#60d3920f25b6860eb917c6c7b185576f4d8b017f"
@@ -3478,6 +4094,20 @@ browserslist@^4.14.5, browserslist@^4.17.5, browserslist@^4.17.6:
node-releases "^2.0.1"
picocolors "^1.0.0"
+bs-logger@0.x:
+ version "0.2.6"
+ resolved "https://registry.yarnpkg.com/bs-logger/-/bs-logger-0.2.6.tgz#eb7d365307a72cf974cc6cda76b68354ad336bd8"
+ integrity sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==
+ dependencies:
+ fast-json-stable-stringify "2.x"
+
+bser@2.1.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05"
+ integrity sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==
+ dependencies:
+ node-int64 "^0.4.0"
+
buffer-crc32@^0.2.5:
version "0.2.13"
resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242"
@@ -3623,6 +4253,11 @@ chalk@^4.0.0, chalk@^4.1.0:
ansi-styles "^4.1.0"
supports-color "^7.1.0"
+char-regex@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf"
+ integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==
+
chardet@^0.7.0:
version "0.7.0"
resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e"
@@ -3663,6 +4298,16 @@ ci-info@^2.0.0:
resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46"
integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==
+ci-info@^3.2.0:
+ version "3.3.0"
+ resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.3.0.tgz#b4ed1fb6818dea4803a55c623041f9165d2066b2"
+ integrity sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw==
+
+cjs-module-lexer@^1.0.0:
+ version "1.2.2"
+ resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz#9f84ba3244a512f3a54e5277e8eef4c489864e40"
+ integrity sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==
+
clean-css@^5.2.2:
version "5.2.2"
resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-5.2.2.tgz#d3a7c6ee2511011e051719838bdcf8314dc4548d"
@@ -3722,11 +4367,21 @@ cmd-shim@^4.1.0:
dependencies:
mkdirp-infer-owner "^2.0.0"
+co@^4.6.0:
+ version "4.6.0"
+ resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184"
+ integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=
+
code-point-at@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=
+collect-v8-coverage@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz#cc2c8e94fc18bbdffe64d6534570c8a673b27f59"
+ integrity sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==
+
color-convert@^1.9.0:
version "1.9.3"
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
@@ -3764,7 +4419,7 @@ columnify@^1.5.4:
strip-ansi "^3.0.0"
wcwidth "^1.0.0"
-combined-stream@^1.0.6, combined-stream@~1.0.6:
+combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6:
version "1.0.8"
resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
@@ -3909,7 +4564,7 @@ conventional-recommended-bump@^6.1.0:
meow "^8.0.0"
q "^1.5.1"
-convert-source-map@^1.7.0:
+convert-source-map@^1.4.0, convert-source-map@^1.6.0, convert-source-map@^1.7.0:
version "1.8.0"
resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.8.0.tgz#f3373c32d21b4d780dd8004514684fb791ca4369"
integrity sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==
@@ -4033,6 +4688,23 @@ csso@^4.2.0:
dependencies:
css-tree "^1.1.2"
+cssom@^0.4.4:
+ version "0.4.4"
+ resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.4.4.tgz#5a66cf93d2d0b661d80bf6a44fb65f5c2e4e0a10"
+ integrity sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw==
+
+cssom@~0.3.6:
+ version "0.3.8"
+ resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.8.tgz#9f1276f5b2b463f2114d3f2c75250af8c1a36f4a"
+ integrity sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==
+
+cssstyle@^2.3.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-2.3.0.tgz#ff665a0ddbdc31864b09647f34163443d90b0852"
+ integrity sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==
+ dependencies:
+ cssom "~0.3.6"
+
csstype@^3.0.10, csstype@^3.0.2:
version "3.0.10"
resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.10.tgz#2ad3a7bed70f35b965707c092e5f30b327c290e5"
@@ -4055,6 +4727,15 @@ dashdash@^1.12.0:
dependencies:
assert-plus "^1.0.0"
+data-urls@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-2.0.0.tgz#156485a72963a970f5d5821aaf642bef2bf2db9b"
+ integrity sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==
+ dependencies:
+ abab "^2.0.3"
+ whatwg-mimetype "^2.3.0"
+ whatwg-url "^8.0.0"
+
dateformat@^3.0.0:
version "3.0.3"
resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae"
@@ -4099,6 +4780,11 @@ decamelize@^1.1.0:
resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=
+decimal.js@^10.2.1:
+ version "10.3.1"
+ resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.3.1.tgz#d8c3a444a9c6774ba60ca6ad7261c3a94fd5e783"
+ integrity sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ==
+
decode-uri-component@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545"
@@ -4109,7 +4795,7 @@ dedent@^0.7.0:
resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c"
integrity sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=
-deep-is@^0.1.3:
+deep-is@^0.1.3, deep-is@~0.1.3:
version "0.1.4"
resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831"
integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==
@@ -4168,6 +4854,11 @@ detect-newline@^2.1.0:
resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-2.1.0.tgz#f41f1c10be4b00e87b5f13da680759f2c5bfd3e2"
integrity sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=
+detect-newline@^3.0.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651"
+ integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==
+
dezalgo@^1.0.0:
version "1.0.3"
resolved "https://registry.yarnpkg.com/dezalgo/-/dezalgo-1.0.3.tgz#7f742de066fc748bc8db820569dddce49bf0d456"
@@ -4176,6 +4867,11 @@ dezalgo@^1.0.0:
asap "^2.0.0"
wrappy "1"
+diff-sequences@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-27.5.1.tgz#eaecc0d327fd68c8d9672a1e64ab8dccb2ef5327"
+ integrity sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==
+
dir-glob@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f"
@@ -4226,6 +4922,13 @@ domelementtype@^2.0.1, domelementtype@^2.2.0:
resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.2.0.tgz#9a0b6c2782ed6a1c7323d42267183df9bd8b1d57"
integrity sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==
+domexception@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/domexception/-/domexception-2.0.1.tgz#fb44aefba793e1574b0af6aed2801d057529f304"
+ integrity sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg==
+ dependencies:
+ webidl-conversions "^5.0.0"
+
domhandler@^4.0.0, domhandler@^4.2.0:
version "4.2.2"
resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.2.2.tgz#e825d721d19a86b8c201a35264e226c678ee755f"
@@ -4295,6 +4998,11 @@ elliptic@6.5.4, elliptic@^6.5.4:
minimalistic-assert "^1.0.1"
minimalistic-crypto-utils "^1.0.1"
+emittery@^0.8.1:
+ version "0.8.1"
+ resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.8.1.tgz#bb23cc86d03b30aa75a7f734819dee2e1ba70860"
+ integrity sha512-uDfvUjVrfGJJhymx/kz6prltenw1u7WrCg1oa94zYY8xxVpLLUu045LAT0dhDZdXG58/EpPL/5kA180fQ/qudg==
+
emoji-regex@^8.0.0:
version "8.0.0"
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37"
@@ -4412,11 +5120,28 @@ escape-string-regexp@^1.0.5:
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
+escape-string-regexp@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344"
+ integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==
+
escape-string-regexp@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34"
integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==
+escodegen@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-2.0.0.tgz#5e32b12833e8aa8fa35e1bf0befa89380484c7dd"
+ integrity sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==
+ dependencies:
+ esprima "^4.0.1"
+ estraverse "^5.2.0"
+ esutils "^2.0.2"
+ optionator "^0.8.1"
+ optionalDependencies:
+ source-map "~0.6.1"
+
eslint-config-next@12.1.0:
version "12.1.0"
resolved "https://registry.yarnpkg.com/eslint-config-next/-/eslint-config-next-12.1.0.tgz#8ace680dc5207e6ab6c915f3989adec122f582e7"
@@ -4616,7 +5341,7 @@ espree@^9.3.1:
acorn-jsx "^5.3.1"
eslint-visitor-keys "^3.3.0"
-esprima@^4.0.0:
+esprima@^4.0.0, esprima@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71"
integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==
@@ -4735,6 +5460,21 @@ execa@^5.0.0:
signal-exit "^3.0.3"
strip-final-newline "^2.0.0"
+exit@^0.1.2:
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c"
+ integrity sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=
+
+expect@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/expect/-/expect-27.5.1.tgz#83ce59f1e5bdf5f9d2b94b61d2050db48f3fef74"
+ integrity sha512-E1q5hSUG2AmYQwQJ041nvgpkODHQvB+RKlB4IYdru6uJsyFTRyZAP463M+1lINorwbqAmUggi6+WwkD8lCS/Dw==
+ dependencies:
+ "@jest/types" "^27.5.1"
+ jest-get-type "^27.5.1"
+ jest-matcher-utils "^27.5.1"
+ jest-message-util "^27.5.1"
+
extend@~3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa"
@@ -4780,12 +5520,12 @@ fast-glob@^3.1.1, fast-glob@^3.2.7:
merge2 "^1.3.0"
micromatch "^4.0.4"
-fast-json-stable-stringify@^2.0.0:
+fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633"
integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==
-fast-levenshtein@^2.0.6:
+fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6:
version "2.0.6"
resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=
@@ -4802,6 +5542,13 @@ fastq@^1.6.0:
dependencies:
reusify "^1.0.4"
+fb-watchman@^2.0.0:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.1.tgz#fc84fb39d2709cf3ff6d743706157bb5708a8a85"
+ integrity sha512-DkPJKQeY6kKwmuMretBhr7G6Vodr7bFwDYTXIkfG1gjvNpaxBTQV3PbXg6bR1c1UP4jPOX0jHUbbHANL9vRjVg==
+ dependencies:
+ bser "2.1.1"
+
figures@^3.0.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af"
@@ -4891,6 +5638,15 @@ forever-agent@~0.6.1:
resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=
+form-data@^3.0.0:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f"
+ integrity sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==
+ dependencies:
+ asynckit "^0.4.0"
+ combined-stream "^1.0.8"
+ mime-types "^2.1.12"
+
form-data@~2.3.2:
version "2.3.3"
resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6"
@@ -4929,7 +5685,7 @@ fs.realpath@^1.0.0:
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8=
-fsevents@~2.3.2:
+fsevents@^2.3.2, fsevents@~2.3.2:
version "2.3.2"
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
@@ -4977,6 +5733,11 @@ get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1:
has "^1.0.3"
has-symbols "^1.0.1"
+get-package-type@^0.1.0:
+ version "0.1.0"
+ resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a"
+ integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==
+
get-pkg-repo@^4.0.0:
version "4.2.1"
resolved "https://registry.yarnpkg.com/get-pkg-repo/-/get-pkg-repo-4.2.1.tgz#75973e1c8050c73f48190c52047c4cee3acbf385"
@@ -5092,7 +5853,7 @@ glob@7.1.7:
once "^1.3.0"
path-is-absolute "^1.0.0"
-glob@^7.1.1, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@^7.1.7:
+glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@^7.1.7:
version "7.2.0"
resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023"
integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==
@@ -5262,6 +6023,18 @@ hosted-git-info@^4.0.0, hosted-git-info@^4.0.1:
dependencies:
lru-cache "^6.0.0"
+html-encoding-sniffer@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz#42a6dc4fd33f00281176e8b23759ca4e4fa185f3"
+ integrity sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ==
+ dependencies:
+ whatwg-encoding "^1.0.5"
+
+html-escaper@^2.0.0:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453"
+ integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==
+
html-minifier-terser@^6.0.2:
version "6.1.0"
resolved "https://registry.yarnpkg.com/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz#bfc818934cc07918f6b3669f5774ecdfd48f32ab"
@@ -5339,7 +6112,7 @@ humanize-ms@^1.2.1:
dependencies:
ms "^2.0.0"
-iconv-lite@^0.4.24:
+iconv-lite@0.4.24, iconv-lite@^0.4.24:
version "0.4.24"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
@@ -5614,6 +6387,11 @@ is-fullwidth-code-point@^3.0.0:
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d"
integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==
+is-generator-fn@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118"
+ integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==
+
is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1:
version "4.0.3"
resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084"
@@ -5675,6 +6453,11 @@ is-plain-object@^5.0.0:
resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-5.0.0.tgz#4427f50ab3429e9025ea7d52e9043a9ef4159344"
integrity sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==
+is-potential-custom-element-name@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz#171ed6f19e3ac554394edf78caa05784a45bebb5"
+ integrity sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==
+
is-reference@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/is-reference/-/is-reference-1.2.1.tgz#8b2dac0b371f4bc994fdeaba9eb542d03002d0b7"
@@ -5760,6 +6543,435 @@ isstream@~0.1.2:
resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=
+istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0:
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz#189e7909d0a39fa5a3dfad5b03f71947770191d3"
+ integrity sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==
+
+istanbul-lib-instrument@^5.0.4, istanbul-lib-instrument@^5.1.0:
+ version "5.1.0"
+ resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-5.1.0.tgz#7b49198b657b27a730b8e9cb601f1e1bff24c59a"
+ integrity sha512-czwUz525rkOFDJxfKK6mYfIs9zBKILyrZQxjz3ABhjQXhbhFsSbo1HW/BFcsDnfJYJWA6thRR5/TUY2qs5W99Q==
+ dependencies:
+ "@babel/core" "^7.12.3"
+ "@babel/parser" "^7.14.7"
+ "@istanbuljs/schema" "^0.1.2"
+ istanbul-lib-coverage "^3.2.0"
+ semver "^6.3.0"
+
+istanbul-lib-report@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#7518fe52ea44de372f460a76b5ecda9ffb73d8a6"
+ integrity sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==
+ dependencies:
+ istanbul-lib-coverage "^3.0.0"
+ make-dir "^3.0.0"
+ supports-color "^7.1.0"
+
+istanbul-lib-source-maps@^4.0.0:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz#895f3a709fcfba34c6de5a42939022f3e4358551"
+ integrity sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==
+ dependencies:
+ debug "^4.1.1"
+ istanbul-lib-coverage "^3.0.0"
+ source-map "^0.6.1"
+
+istanbul-reports@^3.1.3:
+ version "3.1.4"
+ resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.4.tgz#1b6f068ecbc6c331040aab5741991273e609e40c"
+ integrity sha512-r1/DshN4KSE7xWEknZLLLLDn5CJybV3nw01VTkp6D5jzLuELlcbudfj/eSQFvrKsJuTVCGnePO7ho82Nw9zzfw==
+ dependencies:
+ html-escaper "^2.0.0"
+ istanbul-lib-report "^3.0.0"
+
+jest-changed-files@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-27.5.1.tgz#a348aed00ec9bf671cc58a66fcbe7c3dfd6a68f5"
+ integrity sha512-buBLMiByfWGCoMsLLzGUUSpAmIAGnbR2KJoMN10ziLhOLvP4e0SlypHnAel8iqQXTrcbmfEY9sSqae5sgUsTvw==
+ dependencies:
+ "@jest/types" "^27.5.1"
+ execa "^5.0.0"
+ throat "^6.0.1"
+
+jest-circus@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-27.5.1.tgz#37a5a4459b7bf4406e53d637b49d22c65d125ecc"
+ integrity sha512-D95R7x5UtlMA5iBYsOHFFbMD/GVA4R/Kdq15f7xYWUfWHBto9NYRsOvnSauTgdF+ogCpJ4tyKOXhUifxS65gdw==
+ dependencies:
+ "@jest/environment" "^27.5.1"
+ "@jest/test-result" "^27.5.1"
+ "@jest/types" "^27.5.1"
+ "@types/node" "*"
+ chalk "^4.0.0"
+ co "^4.6.0"
+ dedent "^0.7.0"
+ expect "^27.5.1"
+ is-generator-fn "^2.0.0"
+ jest-each "^27.5.1"
+ jest-matcher-utils "^27.5.1"
+ jest-message-util "^27.5.1"
+ jest-runtime "^27.5.1"
+ jest-snapshot "^27.5.1"
+ jest-util "^27.5.1"
+ pretty-format "^27.5.1"
+ slash "^3.0.0"
+ stack-utils "^2.0.3"
+ throat "^6.0.1"
+
+jest-cli@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-27.5.1.tgz#278794a6e6458ea8029547e6c6cbf673bd30b145"
+ integrity sha512-Hc6HOOwYq4/74/c62dEE3r5elx8wjYqxY0r0G/nFrLDPMFRu6RA/u8qINOIkvhxG7mMQ5EJsOGfRpI8L6eFUVw==
+ dependencies:
+ "@jest/core" "^27.5.1"
+ "@jest/test-result" "^27.5.1"
+ "@jest/types" "^27.5.1"
+ chalk "^4.0.0"
+ exit "^0.1.2"
+ graceful-fs "^4.2.9"
+ import-local "^3.0.2"
+ jest-config "^27.5.1"
+ jest-util "^27.5.1"
+ jest-validate "^27.5.1"
+ prompts "^2.0.1"
+ yargs "^16.2.0"
+
+jest-config@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-27.5.1.tgz#5c387de33dca3f99ad6357ddeccd91bf3a0e4a41"
+ integrity sha512-5sAsjm6tGdsVbW9ahcChPAFCk4IlkQUknH5AvKjuLTSlcO/wCZKyFdn7Rg0EkC+OGgWODEy2hDpWB1PgzH0JNA==
+ dependencies:
+ "@babel/core" "^7.8.0"
+ "@jest/test-sequencer" "^27.5.1"
+ "@jest/types" "^27.5.1"
+ babel-jest "^27.5.1"
+ chalk "^4.0.0"
+ ci-info "^3.2.0"
+ deepmerge "^4.2.2"
+ glob "^7.1.1"
+ graceful-fs "^4.2.9"
+ jest-circus "^27.5.1"
+ jest-environment-jsdom "^27.5.1"
+ jest-environment-node "^27.5.1"
+ jest-get-type "^27.5.1"
+ jest-jasmine2 "^27.5.1"
+ jest-regex-util "^27.5.1"
+ jest-resolve "^27.5.1"
+ jest-runner "^27.5.1"
+ jest-util "^27.5.1"
+ jest-validate "^27.5.1"
+ micromatch "^4.0.4"
+ parse-json "^5.2.0"
+ pretty-format "^27.5.1"
+ slash "^3.0.0"
+ strip-json-comments "^3.1.1"
+
+jest-diff@^27.0.0, jest-diff@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-27.5.1.tgz#a07f5011ac9e6643cf8a95a462b7b1ecf6680def"
+ integrity sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==
+ dependencies:
+ chalk "^4.0.0"
+ diff-sequences "^27.5.1"
+ jest-get-type "^27.5.1"
+ pretty-format "^27.5.1"
+
+jest-docblock@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-27.5.1.tgz#14092f364a42c6108d42c33c8cf30e058e25f6c0"
+ integrity sha512-rl7hlABeTsRYxKiUfpHrQrG4e2obOiTQWfMEH3PxPjOtdsfLQO4ReWSZaQ7DETm4xu07rl4q/h4zcKXyU0/OzQ==
+ dependencies:
+ detect-newline "^3.0.0"
+
+jest-each@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-27.5.1.tgz#5bc87016f45ed9507fed6e4702a5b468a5b2c44e"
+ integrity sha512-1Ff6p+FbhT/bXQnEouYy00bkNSY7OUpfIcmdl8vZ31A1UUaurOLPA8a8BbJOF2RDUElwJhmeaV7LnagI+5UwNQ==
+ dependencies:
+ "@jest/types" "^27.5.1"
+ chalk "^4.0.0"
+ jest-get-type "^27.5.1"
+ jest-util "^27.5.1"
+ pretty-format "^27.5.1"
+
+jest-environment-jsdom@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-27.5.1.tgz#ea9ccd1fc610209655a77898f86b2b559516a546"
+ integrity sha512-TFBvkTC1Hnnnrka/fUb56atfDtJ9VMZ94JkjTbggl1PEpwrYtUBKMezB3inLmWqQsXYLcMwNoDQwoBTAvFfsfw==
+ dependencies:
+ "@jest/environment" "^27.5.1"
+ "@jest/fake-timers" "^27.5.1"
+ "@jest/types" "^27.5.1"
+ "@types/node" "*"
+ jest-mock "^27.5.1"
+ jest-util "^27.5.1"
+ jsdom "^16.6.0"
+
+jest-environment-node@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-27.5.1.tgz#dedc2cfe52fab6b8f5714b4808aefa85357a365e"
+ integrity sha512-Jt4ZUnxdOsTGwSRAfKEnE6BcwsSPNOijjwifq5sDFSA2kesnXTvNqKHYgM0hDq3549Uf/KzdXNYn4wMZJPlFLw==
+ dependencies:
+ "@jest/environment" "^27.5.1"
+ "@jest/fake-timers" "^27.5.1"
+ "@jest/types" "^27.5.1"
+ "@types/node" "*"
+ jest-mock "^27.5.1"
+ jest-util "^27.5.1"
+
+jest-get-type@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-27.5.1.tgz#3cd613c507b0f7ace013df407a1c1cd578bcb4f1"
+ integrity sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==
+
+jest-haste-map@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-27.5.1.tgz#9fd8bd7e7b4fa502d9c6164c5640512b4e811e7f"
+ integrity sha512-7GgkZ4Fw4NFbMSDSpZwXeBiIbx+t/46nJ2QitkOjvwPYyZmqttu2TDSimMHP1EkPOi4xUZAN1doE5Vd25H4Jng==
+ dependencies:
+ "@jest/types" "^27.5.1"
+ "@types/graceful-fs" "^4.1.2"
+ "@types/node" "*"
+ anymatch "^3.0.3"
+ fb-watchman "^2.0.0"
+ graceful-fs "^4.2.9"
+ jest-regex-util "^27.5.1"
+ jest-serializer "^27.5.1"
+ jest-util "^27.5.1"
+ jest-worker "^27.5.1"
+ micromatch "^4.0.4"
+ walker "^1.0.7"
+ optionalDependencies:
+ fsevents "^2.3.2"
+
+jest-jasmine2@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-27.5.1.tgz#a037b0034ef49a9f3d71c4375a796f3b230d1ac4"
+ integrity sha512-jtq7VVyG8SqAorDpApwiJJImd0V2wv1xzdheGHRGyuT7gZm6gG47QEskOlzsN1PG/6WNaCo5pmwMHDf3AkG2pQ==
+ dependencies:
+ "@jest/environment" "^27.5.1"
+ "@jest/source-map" "^27.5.1"
+ "@jest/test-result" "^27.5.1"
+ "@jest/types" "^27.5.1"
+ "@types/node" "*"
+ chalk "^4.0.0"
+ co "^4.6.0"
+ expect "^27.5.1"
+ is-generator-fn "^2.0.0"
+ jest-each "^27.5.1"
+ jest-matcher-utils "^27.5.1"
+ jest-message-util "^27.5.1"
+ jest-runtime "^27.5.1"
+ jest-snapshot "^27.5.1"
+ jest-util "^27.5.1"
+ pretty-format "^27.5.1"
+ throat "^6.0.1"
+
+jest-leak-detector@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-27.5.1.tgz#6ec9d54c3579dd6e3e66d70e3498adf80fde3fb8"
+ integrity sha512-POXfWAMvfU6WMUXftV4HolnJfnPOGEu10fscNCA76KBpRRhcMN2c8d3iT2pxQS3HLbA+5X4sOUPzYO2NUyIlHQ==
+ dependencies:
+ jest-get-type "^27.5.1"
+ pretty-format "^27.5.1"
+
+jest-matcher-utils@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz#9c0cdbda8245bc22d2331729d1091308b40cf8ab"
+ integrity sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw==
+ dependencies:
+ chalk "^4.0.0"
+ jest-diff "^27.5.1"
+ jest-get-type "^27.5.1"
+ pretty-format "^27.5.1"
+
+jest-message-util@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-27.5.1.tgz#bdda72806da10d9ed6425e12afff38cd1458b6cf"
+ integrity sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==
+ dependencies:
+ "@babel/code-frame" "^7.12.13"
+ "@jest/types" "^27.5.1"
+ "@types/stack-utils" "^2.0.0"
+ chalk "^4.0.0"
+ graceful-fs "^4.2.9"
+ micromatch "^4.0.4"
+ pretty-format "^27.5.1"
+ slash "^3.0.0"
+ stack-utils "^2.0.3"
+
+jest-mock@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-27.5.1.tgz#19948336d49ef4d9c52021d34ac7b5f36ff967d6"
+ integrity sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og==
+ dependencies:
+ "@jest/types" "^27.5.1"
+ "@types/node" "*"
+
+jest-pnp-resolver@^1.2.2:
+ version "1.2.2"
+ resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz#b704ac0ae028a89108a4d040b3f919dfddc8e33c"
+ integrity sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==
+
+jest-regex-util@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-27.5.1.tgz#4da143f7e9fd1e542d4aa69617b38e4a78365b95"
+ integrity sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==
+
+jest-resolve-dependencies@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-27.5.1.tgz#d811ecc8305e731cc86dd79741ee98fed06f1da8"
+ integrity sha512-QQOOdY4PE39iawDn5rzbIePNigfe5B9Z91GDD1ae/xNDlu9kaat8QQ5EKnNmVWPV54hUdxCVwwj6YMgR2O7IOg==
+ dependencies:
+ "@jest/types" "^27.5.1"
+ jest-regex-util "^27.5.1"
+ jest-snapshot "^27.5.1"
+
+jest-resolve@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-27.5.1.tgz#a2f1c5a0796ec18fe9eb1536ac3814c23617b384"
+ integrity sha512-FFDy8/9E6CV83IMbDpcjOhumAQPDyETnU2KZ1O98DwTnz8AOBsW/Xv3GySr1mOZdItLR+zDZ7I/UdTFbgSOVCw==
+ dependencies:
+ "@jest/types" "^27.5.1"
+ chalk "^4.0.0"
+ graceful-fs "^4.2.9"
+ jest-haste-map "^27.5.1"
+ jest-pnp-resolver "^1.2.2"
+ jest-util "^27.5.1"
+ jest-validate "^27.5.1"
+ resolve "^1.20.0"
+ resolve.exports "^1.1.0"
+ slash "^3.0.0"
+
+jest-runner@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-27.5.1.tgz#071b27c1fa30d90540805c5645a0ec167c7b62e5"
+ integrity sha512-g4NPsM4mFCOwFKXO4p/H/kWGdJp9V8kURY2lX8Me2drgXqG7rrZAx5kv+5H7wtt/cdFIjhqYx1HrlqWHaOvDaQ==
+ dependencies:
+ "@jest/console" "^27.5.1"
+ "@jest/environment" "^27.5.1"
+ "@jest/test-result" "^27.5.1"
+ "@jest/transform" "^27.5.1"
+ "@jest/types" "^27.5.1"
+ "@types/node" "*"
+ chalk "^4.0.0"
+ emittery "^0.8.1"
+ graceful-fs "^4.2.9"
+ jest-docblock "^27.5.1"
+ jest-environment-jsdom "^27.5.1"
+ jest-environment-node "^27.5.1"
+ jest-haste-map "^27.5.1"
+ jest-leak-detector "^27.5.1"
+ jest-message-util "^27.5.1"
+ jest-resolve "^27.5.1"
+ jest-runtime "^27.5.1"
+ jest-util "^27.5.1"
+ jest-worker "^27.5.1"
+ source-map-support "^0.5.6"
+ throat "^6.0.1"
+
+jest-runtime@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-27.5.1.tgz#4896003d7a334f7e8e4a53ba93fb9bcd3db0a1af"
+ integrity sha512-o7gxw3Gf+H2IGt8fv0RiyE1+r83FJBRruoA+FXrlHw6xEyBsU8ugA6IPfTdVyA0w8HClpbK+DGJxH59UrNMx8A==
+ dependencies:
+ "@jest/environment" "^27.5.1"
+ "@jest/fake-timers" "^27.5.1"
+ "@jest/globals" "^27.5.1"
+ "@jest/source-map" "^27.5.1"
+ "@jest/test-result" "^27.5.1"
+ "@jest/transform" "^27.5.1"
+ "@jest/types" "^27.5.1"
+ chalk "^4.0.0"
+ cjs-module-lexer "^1.0.0"
+ collect-v8-coverage "^1.0.0"
+ execa "^5.0.0"
+ glob "^7.1.3"
+ graceful-fs "^4.2.9"
+ jest-haste-map "^27.5.1"
+ jest-message-util "^27.5.1"
+ jest-mock "^27.5.1"
+ jest-regex-util "^27.5.1"
+ jest-resolve "^27.5.1"
+ jest-snapshot "^27.5.1"
+ jest-util "^27.5.1"
+ slash "^3.0.0"
+ strip-bom "^4.0.0"
+
+jest-serializer@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-27.5.1.tgz#81438410a30ea66fd57ff730835123dea1fb1f64"
+ integrity sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w==
+ dependencies:
+ "@types/node" "*"
+ graceful-fs "^4.2.9"
+
+jest-snapshot@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-27.5.1.tgz#b668d50d23d38054a51b42c4039cab59ae6eb6a1"
+ integrity sha512-yYykXI5a0I31xX67mgeLw1DZ0bJB+gpq5IpSuCAoyDi0+BhgU/RIrL+RTzDmkNTchvDFWKP8lp+w/42Z3us5sA==
+ dependencies:
+ "@babel/core" "^7.7.2"
+ "@babel/generator" "^7.7.2"
+ "@babel/plugin-syntax-typescript" "^7.7.2"
+ "@babel/traverse" "^7.7.2"
+ "@babel/types" "^7.0.0"
+ "@jest/transform" "^27.5.1"
+ "@jest/types" "^27.5.1"
+ "@types/babel__traverse" "^7.0.4"
+ "@types/prettier" "^2.1.5"
+ babel-preset-current-node-syntax "^1.0.0"
+ chalk "^4.0.0"
+ expect "^27.5.1"
+ graceful-fs "^4.2.9"
+ jest-diff "^27.5.1"
+ jest-get-type "^27.5.1"
+ jest-haste-map "^27.5.1"
+ jest-matcher-utils "^27.5.1"
+ jest-message-util "^27.5.1"
+ jest-util "^27.5.1"
+ natural-compare "^1.4.0"
+ pretty-format "^27.5.1"
+ semver "^7.3.2"
+
+jest-util@^27.0.0, jest-util@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-27.5.1.tgz#3ba9771e8e31a0b85da48fe0b0891fb86c01c2f9"
+ integrity sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==
+ dependencies:
+ "@jest/types" "^27.5.1"
+ "@types/node" "*"
+ chalk "^4.0.0"
+ ci-info "^3.2.0"
+ graceful-fs "^4.2.9"
+ picomatch "^2.2.3"
+
+jest-validate@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-27.5.1.tgz#9197d54dc0bdb52260b8db40b46ae668e04df067"
+ integrity sha512-thkNli0LYTmOI1tDB3FI1S1RTp/Bqyd9pTarJwL87OIBFuqEb5Apv5EaApEudYg4g86e3CT6kM0RowkhtEnCBQ==
+ dependencies:
+ "@jest/types" "^27.5.1"
+ camelcase "^6.2.0"
+ chalk "^4.0.0"
+ jest-get-type "^27.5.1"
+ leven "^3.1.0"
+ pretty-format "^27.5.1"
+
+jest-watcher@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-27.5.1.tgz#71bd85fb9bde3a2c2ec4dc353437971c43c642a2"
+ integrity sha512-z676SuD6Z8o8qbmEGhoEUFOM1+jfEiL3DXHK/xgEiG2EyNYfFG60jluWcupY6dATjfEsKQuibReS1djInQnoVw==
+ dependencies:
+ "@jest/test-result" "^27.5.1"
+ "@jest/types" "^27.5.1"
+ "@types/node" "*"
+ ansi-escapes "^4.2.1"
+ chalk "^4.0.0"
+ jest-util "^27.5.1"
+ string-length "^4.0.1"
+
jest-worker@^26.2.1:
version "26.6.2"
resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-26.6.2.tgz#7f72cbc4d643c365e27b9fd775f9d0eaa9c7a8ed"
@@ -5787,6 +6999,24 @@ jest-worker@^27.3.1:
merge-stream "^2.0.0"
supports-color "^8.0.0"
+jest-worker@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.5.1.tgz#8d146f0900e8973b106b6f73cc1e9a8cb86f8db0"
+ integrity sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==
+ dependencies:
+ "@types/node" "*"
+ merge-stream "^2.0.0"
+ supports-color "^8.0.0"
+
+jest@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest/-/jest-27.5.1.tgz#dadf33ba70a779be7a6fc33015843b51494f63fc"
+ integrity sha512-Yn0mADZB89zTtjkPJEXwrac3LHudkQMR+Paqa8uxJHCBr9agxztUifWCyiYrjhMPBoUVBjyny0I7XH6ozDr7QQ==
+ dependencies:
+ "@jest/core" "^27.5.1"
+ import-local "^3.0.2"
+ jest-cli "^27.5.1"
+
jose@^4.3.6:
version "4.5.0"
resolved "https://registry.yarnpkg.com/jose/-/jose-4.5.0.tgz#92829d8cf846351eb55aaaf94f252fb1d191f2d5"
@@ -5822,6 +7052,39 @@ jsbn@~0.1.0:
resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513"
integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM=
+jsdom@^16.6.0:
+ version "16.7.0"
+ resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-16.7.0.tgz#918ae71965424b197c819f8183a754e18977b710"
+ integrity sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw==
+ dependencies:
+ abab "^2.0.5"
+ acorn "^8.2.4"
+ acorn-globals "^6.0.0"
+ cssom "^0.4.4"
+ cssstyle "^2.3.0"
+ data-urls "^2.0.0"
+ decimal.js "^10.2.1"
+ domexception "^2.0.1"
+ escodegen "^2.0.0"
+ form-data "^3.0.0"
+ html-encoding-sniffer "^2.0.1"
+ http-proxy-agent "^4.0.1"
+ https-proxy-agent "^5.0.0"
+ is-potential-custom-element-name "^1.0.1"
+ nwsapi "^2.2.0"
+ parse5 "6.0.1"
+ saxes "^5.0.1"
+ symbol-tree "^3.2.4"
+ tough-cookie "^4.0.0"
+ w3c-hr-time "^1.0.2"
+ w3c-xmlserializer "^2.0.0"
+ webidl-conversions "^6.1.0"
+ whatwg-encoding "^1.0.5"
+ whatwg-mimetype "^2.3.0"
+ whatwg-url "^8.5.0"
+ ws "^7.4.6"
+ xml-name-validator "^3.0.0"
+
jsesc@^2.5.1:
version "2.5.2"
resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4"
@@ -5874,6 +7137,13 @@ json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1:
resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=
+json5@2.x, json5@^2.1.2:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.0.tgz#2dfefe720c6ba525d9ebd909950f0515316c89a3"
+ integrity sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==
+ dependencies:
+ minimist "^1.2.5"
+
json5@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe"
@@ -5881,13 +7151,6 @@ json5@^1.0.1:
dependencies:
minimist "^1.2.0"
-json5@^2.1.2:
- version "2.2.0"
- resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.0.tgz#2dfefe720c6ba525d9ebd909950f0515316c89a3"
- integrity sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==
- dependencies:
- minimist "^1.2.5"
-
jsonfile@^6.0.1:
version "6.1.0"
resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae"
@@ -5925,6 +7188,11 @@ kind-of@^6.0.2, kind-of@^6.0.3:
resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd"
integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==
+kleur@^3.0.3:
+ version "3.0.3"
+ resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e"
+ integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==
+
language-subtag-registry@~0.3.2:
version "0.3.21"
resolved "https://registry.yarnpkg.com/language-subtag-registry/-/language-subtag-registry-0.3.21.tgz#04ac218bea46f04cb039084602c6da9e788dd45a"
@@ -5961,6 +7229,11 @@ lerna@^4.0.0:
import-local "^3.0.2"
npmlog "^4.1.2"
+leven@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2"
+ integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==
+
levn@^0.4.1:
version "0.4.1"
resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade"
@@ -5969,6 +7242,14 @@ levn@^0.4.1:
prelude-ls "^1.2.1"
type-check "~0.4.0"
+levn@~0.3.0:
+ version "0.3.0"
+ resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee"
+ integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=
+ dependencies:
+ prelude-ls "~1.1.2"
+ type-check "~0.3.2"
+
libnpmaccess@^4.0.1:
version "4.0.3"
resolved "https://registry.yarnpkg.com/libnpmaccess/-/libnpmaccess-4.0.3.tgz#dfb0e5b0a53c315a2610d300e46b4ddeb66e7eec"
@@ -6059,6 +7340,11 @@ lodash.ismatch@^4.4.0:
resolved "https://registry.yarnpkg.com/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz#756cb5150ca3ba6f11085a78849645f188f85f37"
integrity sha1-dWy1FQyjum8RCFp4hJZF8Yj4Xzc=
+lodash.memoize@4.x:
+ version "4.1.2"
+ resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe"
+ integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=
+
lodash.merge@^4.6.2:
version "4.6.2"
resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a"
@@ -6127,6 +7413,11 @@ make-dir@^3.0.0:
dependencies:
semver "^6.0.0"
+make-error@1.x:
+ version "1.3.6"
+ resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2"
+ integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==
+
make-fetch-happen@^8.0.9:
version "8.0.14"
resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-8.0.14.tgz#aaba73ae0ab5586ad8eaa68bd83332669393e222"
@@ -6170,6 +7461,13 @@ make-fetch-happen@^9.0.1:
socks-proxy-agent "^6.0.0"
ssri "^8.0.0"
+makeerror@1.0.12:
+ version "1.0.12"
+ resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.12.tgz#3e5dd2079a82e812e983cc6610c4a2cb0eaa801a"
+ integrity sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==
+ dependencies:
+ tmpl "1.0.5"
+
map-obj@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d"
@@ -6518,6 +7816,11 @@ node-gyp@^7.1.0:
tar "^6.0.2"
which "^2.0.2"
+node-int64@^0.4.0:
+ version "0.4.0"
+ resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b"
+ integrity sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=
+
node-releases@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.1.tgz#3d1d395f204f1f2f29a54358b9fb678765ad2fc5"
@@ -6685,6 +7988,11 @@ number-is-nan@^1.0.0:
resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=
+nwsapi@^2.2.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.0.tgz#204879a9e3d068ff2a55139c2c772780681a38b7"
+ integrity sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==
+
oauth-sign@~0.9.0:
version "0.9.0"
resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455"
@@ -6778,6 +8086,18 @@ onetime@^5.1.0, onetime@^5.1.2:
dependencies:
mimic-fn "^2.1.0"
+optionator@^0.8.1:
+ version "0.8.3"
+ resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495"
+ integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==
+ dependencies:
+ deep-is "~0.1.3"
+ fast-levenshtein "~2.0.6"
+ levn "~0.3.0"
+ prelude-ls "~1.1.2"
+ type-check "~0.3.2"
+ word-wrap "~1.2.3"
+
optionator@^0.9.1:
version "0.9.1"
resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499"
@@ -6948,7 +8268,7 @@ parse-json@^4.0.0:
error-ex "^1.3.1"
json-parse-better-errors "^1.0.1"
-parse-json@^5.0.0:
+parse-json@^5.0.0, parse-json@^5.2.0:
version "5.2.0"
resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd"
integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==
@@ -6978,6 +8298,11 @@ parse-url@^6.0.0:
parse-path "^4.0.0"
protocols "^1.4.0"
+parse5@6.0.1:
+ version "6.0.1"
+ resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b"
+ integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==
+
pascal-case@^3.1.2:
version "3.1.2"
resolved "https://registry.yarnpkg.com/pascal-case/-/pascal-case-3.1.2.tgz#b48e0ef2b98e205e7c1dae747d0b1508237660eb"
@@ -7058,6 +8383,11 @@ pify@^5.0.0:
resolved "https://registry.yarnpkg.com/pify/-/pify-5.0.0.tgz#1f5eca3f5e87ebec28cc6d54a0e4aaf00acc127f"
integrity sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA==
+pirates@^4.0.4:
+ version "4.0.5"
+ resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.5.tgz#feec352ea5c3268fb23a37c702ab1699f35a5f3b"
+ integrity sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==
+
pkg-dir@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-2.0.0.tgz#f6d5d1109e19d63edf428e0bd57e12777615334b"
@@ -7091,6 +8421,11 @@ prelude-ls@^1.2.1:
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396"
integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==
+prelude-ls@~1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"
+ integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=
+
prettier-plugin-import-sort@^0.0.7:
version "0.0.7"
resolved "https://registry.yarnpkg.com/prettier-plugin-import-sort/-/prettier-plugin-import-sort-0.0.7.tgz#b13dcc4de98940b99066a9e34606a955d109b546"
@@ -7114,6 +8449,15 @@ pretty-error@^4.0.0:
lodash "^4.17.20"
renderkid "^3.0.0"
+pretty-format@^27.0.0, pretty-format@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.5.1.tgz#2181879fdea51a7a5851fb39d920faa63f01d88e"
+ integrity sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==
+ dependencies:
+ ansi-regex "^5.0.1"
+ ansi-styles "^5.0.0"
+ react-is "^17.0.1"
+
process-nextick-args@~2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
@@ -7132,6 +8476,14 @@ promise-retry@^2.0.1:
err-code "^2.0.2"
retry "^0.12.0"
+prompts@^2.0.1:
+ version "2.4.2"
+ resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069"
+ integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==
+ dependencies:
+ kleur "^3.0.3"
+ sisteransi "^1.0.5"
+
promzard@^0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/promzard/-/promzard-0.3.0.tgz#26a5d6ee8c7dee4cb12208305acfb93ba382a9ee"
@@ -7158,7 +8510,7 @@ protocols@^1.1.0, protocols@^1.4.0:
resolved "https://registry.yarnpkg.com/protocols/-/protocols-1.4.8.tgz#48eea2d8f58d9644a4a32caae5d5db290a075ce8"
integrity sha512-IgjKyaUSjsROSO8/D49Ab7hP8mJgTYcqApOqdPhLoPxAplXmkp+zRvsrSQjFn5by0rhm4VH0GAUELIPpx7B1yg==
-psl@^1.1.28:
+psl@^1.1.28, psl@^1.1.33:
version "1.8.0"
resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24"
integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==
@@ -7256,7 +8608,7 @@ react-is@^16.13.1, react-is@^16.7.0:
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
-react-is@^17.0.2:
+react-is@^17.0.1, react-is@^17.0.2:
version "17.0.2"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0"
integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==
@@ -7590,6 +8942,11 @@ resolve-from@^5.0.0:
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69"
integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==
+resolve.exports@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-1.1.0.tgz#5ce842b94b05146c0e03076985d1d0e7e48c90c9"
+ integrity sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ==
+
resolve@^1.10.0, resolve@^1.14.2, resolve@^1.17.0, resolve@^1.19.0, resolve@^1.20.0, resolve@^1.8.1, resolve@^1.9.0:
version "1.20.0"
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975"
@@ -7631,7 +8988,7 @@ rimraf@^2.5.2, rimraf@^2.6.3:
dependencies:
glob "^7.1.3"
-rimraf@^3.0.2:
+rimraf@^3.0.0, rimraf@^3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a"
integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==
@@ -7736,6 +9093,13 @@ sander@^0.5.0:
mkdirp "^0.5.1"
rimraf "^2.5.2"
+saxes@^5.0.1:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/saxes/-/saxes-5.0.1.tgz#eebab953fa3b7608dbe94e5dadb15c888fa6696d"
+ integrity sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==
+ dependencies:
+ xmlchars "^2.2.0"
+
scheduler@^0.20.2:
version "0.20.2"
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.20.2.tgz#4baee39436e34aa93b4874bddcbf0fe8b8b50e91"
@@ -7778,18 +9142,18 @@ semver@7.0.0:
resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e"
integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==
-semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.3.0:
- version "6.3.0"
- resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
- integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
-
-semver@^7.1.1, semver@^7.1.3, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5:
+semver@7.x, semver@^7.1.1, semver@^7.1.3, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5:
version "7.3.5"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7"
integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==
dependencies:
lru-cache "^6.0.0"
+semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.3.0:
+ version "6.3.0"
+ resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
+ integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
+
serialize-javascript@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-4.0.0.tgz#b525e1238489a5ecfc42afacc3fe99e666f4b1aa"
@@ -7847,6 +9211,11 @@ signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3:
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.6.tgz#24e630c4b0f03fea446a2bd299e62b4a6ca8d0af"
integrity sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==
+sisteransi@^1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed"
+ integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==
+
slash@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634"
@@ -7922,7 +9291,7 @@ source-map-js@^1.0.1:
resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c"
integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==
-source-map-support@~0.5.20:
+source-map-support@^0.5.6, source-map-support@~0.5.20:
version "0.5.21"
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f"
integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==
@@ -7935,7 +9304,7 @@ source-map@^0.5.0:
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=
-source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0:
+source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1:
version "0.6.1"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
@@ -8027,6 +9396,13 @@ stable@^0.1.8:
resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf"
integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==
+stack-utils@^2.0.3:
+ version "2.0.5"
+ resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.5.tgz#d25265fca995154659dbbfba3b49254778d2fdd5"
+ integrity sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==
+ dependencies:
+ escape-string-regexp "^2.0.0"
+
starknet@^2.5.0:
version "2.5.1"
resolved "https://registry.yarnpkg.com/starknet/-/starknet-2.5.1.tgz#894074db7882dc171da0db56661a86f71251dec7"
@@ -8048,6 +9424,14 @@ strict-uri-encode@^2.0.0:
resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546"
integrity sha1-ucczDHBChi9rFC3CdLvMWGbONUY=
+string-length@^4.0.1:
+ version "4.0.2"
+ resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a"
+ integrity sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==
+ dependencies:
+ char-regex "^1.0.2"
+ strip-ansi "^6.0.0"
+
string-width@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3"
@@ -8217,6 +9601,14 @@ supports-color@^8.0.0:
dependencies:
has-flag "^4.0.0"
+supports-hyperlinks@^2.0.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/supports-hyperlinks/-/supports-hyperlinks-2.2.0.tgz#4f77b42488765891774b70c79babd87f9bd594bb"
+ integrity sha512-6sXEzV5+I5j8Bmq9/vUphGRM/RJNT9SCURJLjwfOg51heRtguGWDzcaBlgAzKhQa0EVNpPEKzQuBwZ8S8WaCeQ==
+ dependencies:
+ has-flag "^4.0.0"
+ supports-color "^7.0.0"
+
svelte-check@^2.0.0:
version "2.4.5"
resolved "https://registry.yarnpkg.com/svelte-check/-/svelte-check-2.4.5.tgz#a2001993034d495118980bd95577fb3e7980661a"
@@ -8272,6 +9664,11 @@ swr@^1.1.0:
resolved "https://registry.yarnpkg.com/swr/-/swr-1.2.2.tgz#6cae09928d30593a7980d80f85823e57468fac5d"
integrity sha512-ky0BskS/V47GpW8d6RU7CPsr6J8cr7mQD6+do5eky3bM0IyJaoi3vO8UhvrzJaObuTlGhPl2szodeB2dUd76Xw==
+symbol-tree@^3.2.4:
+ version "3.2.4"
+ resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2"
+ integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==
+
tapable@^2.0.0, tapable@^2.1.1, tapable@^2.2.0:
version "2.2.1"
resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0"
@@ -8318,6 +9715,14 @@ temp-write@^4.0.0:
temp-dir "^1.0.0"
uuid "^3.3.2"
+terminal-link@^2.0.0:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/terminal-link/-/terminal-link-2.1.1.tgz#14a64a27ab3c0df933ea546fba55f2d078edc994"
+ integrity sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==
+ dependencies:
+ ansi-escapes "^4.2.1"
+ supports-hyperlinks "^2.0.0"
+
terser-webpack-plugin@^5.1.3:
version "5.2.5"
resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.2.5.tgz#ce65b9880a0c36872555c4874f45bbdb02ee32c9"
@@ -8338,6 +9743,15 @@ terser@^5.0.0, terser@^5.10.0, terser@^5.7.2:
source-map "~0.7.2"
source-map-support "~0.5.20"
+test-exclude@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e"
+ integrity sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==
+ dependencies:
+ "@istanbuljs/schema" "^0.1.2"
+ glob "^7.1.4"
+ minimatch "^3.0.4"
+
text-extensions@^1.0.0:
version "1.9.0"
resolved "https://registry.yarnpkg.com/text-extensions/-/text-extensions-1.9.0.tgz#1853e45fee39c945ce6f6c36b2d659b5aabc2a26"
@@ -8348,6 +9762,11 @@ text-table@^0.2.0:
resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=
+throat@^6.0.1:
+ version "6.0.1"
+ resolved "https://registry.yarnpkg.com/throat/-/throat-6.0.1.tgz#d514fedad95740c12c2d7fc70ea863eb51ade375"
+ integrity sha512-8hmiGIJMDlwjg7dlJ4yKGLK8EsYqKgPWbG3b4wjJddKNwc7N7Dpn08Df4szr/sZdMVeOstrdYSsqzX6BYbcB+w==
+
through2@^2.0.0:
version "2.0.5"
resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd"
@@ -8382,6 +9801,11 @@ tmp@^0.0.33:
dependencies:
os-tmpdir "~1.0.2"
+tmpl@1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc"
+ integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==
+
to-fast-properties@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e"
@@ -8399,6 +9823,15 @@ toggle-selection@^1.0.6:
resolved "https://registry.yarnpkg.com/toggle-selection/-/toggle-selection-1.0.6.tgz#6e45b1263f2017fa0acc7d89d78b15b8bf77da32"
integrity sha1-bkWxJj8gF/oKzH2J14sVuL932jI=
+tough-cookie@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.0.0.tgz#d822234eeca882f991f0f908824ad2622ddbece4"
+ integrity sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg==
+ dependencies:
+ psl "^1.1.33"
+ punycode "^2.1.1"
+ universalify "^0.1.2"
+
tough-cookie@~2.5.0:
version "2.5.0"
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2"
@@ -8424,6 +9857,20 @@ trim-newlines@^3.0.0:
resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-3.0.1.tgz#260a5d962d8b752425b32f3a7db0dcacd176c144"
integrity sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==
+ts-jest@^27.1.3:
+ version "27.1.3"
+ resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-27.1.3.tgz#1f723e7e74027c4da92c0ffbd73287e8af2b2957"
+ integrity sha512-6Nlura7s6uM9BVUAoqLH7JHyMXjz8gluryjpPXxr3IxZdAXnU6FhjvVLHFtfd1vsE1p8zD1OJfskkc0jhTSnkA==
+ dependencies:
+ bs-logger "0.x"
+ fast-json-stable-stringify "2.x"
+ jest-util "^27.0.0"
+ json5 "2.x"
+ lodash.memoize "4.x"
+ make-error "1.x"
+ semver "7.x"
+ yargs-parser "20.x"
+
ts-loader@^9.2.6:
version "9.2.6"
resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-9.2.6.tgz#9937c4dd0a1e3dbbb5e433f8102a6601c6615d74"
@@ -8485,6 +9932,18 @@ type-check@^0.4.0, type-check@~0.4.0:
dependencies:
prelude-ls "^1.2.1"
+type-check@~0.3.2:
+ version "0.3.2"
+ resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72"
+ integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=
+ dependencies:
+ prelude-ls "~1.1.2"
+
+type-detect@4.0.8:
+ version "4.0.8"
+ resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c"
+ integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==
+
type-fest@^0.18.0:
version "0.18.1"
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.18.1.tgz#db4bc151a4a2cf4eebf9add5db75508db6cc841f"
@@ -8604,6 +10063,11 @@ universal-user-agent@^6.0.0:
resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-6.0.0.tgz#3381f8503b251c0d9cd21bc1de939ec9df5480ee"
integrity sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==
+universalify@^0.1.2:
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66"
+ integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==
+
universalify@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717"
@@ -8669,6 +10133,15 @@ v8-compile-cache@^2.0.3:
resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee"
integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==
+v8-to-istanbul@^8.1.0:
+ version "8.1.1"
+ resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-8.1.1.tgz#77b752fd3975e31bbcef938f85e9bd1c7a8d60ed"
+ integrity sha512-FGtKtv3xIpR6BYhvgH8MI/y78oT7d8Au3ww4QIxymrCtZEh5b8gCw2siywE+puhEmuWKDtmfrvF5UlB298ut3w==
+ dependencies:
+ "@types/istanbul-lib-coverage" "^2.0.1"
+ convert-source-map "^1.6.0"
+ source-map "^0.7.3"
+
validate-npm-package-license@^3.0.1, validate-npm-package-license@^3.0.4:
version "3.0.4"
resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a"
@@ -8693,6 +10166,27 @@ verror@1.10.0:
core-util-is "1.0.2"
extsprintf "^1.2.0"
+w3c-hr-time@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz#0a89cdf5cc15822df9c360543676963e0cc308cd"
+ integrity sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==
+ dependencies:
+ browser-process-hrtime "^1.0.0"
+
+w3c-xmlserializer@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz#3e7104a05b75146cc60f564380b7f683acf1020a"
+ integrity sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==
+ dependencies:
+ xml-name-validator "^3.0.0"
+
+walker@^1.0.7:
+ version "1.0.8"
+ resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.8.tgz#bd498db477afe573dc04185f011d3ab8a8d7653f"
+ integrity sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==
+ dependencies:
+ makeerror "1.0.12"
+
watchpack@^2.3.1:
version "2.3.1"
resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.3.1.tgz#4200d9447b401156eeca7767ee610f8809bc9d25"
@@ -8718,6 +10212,11 @@ webidl-conversions@^3.0.0:
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"
integrity sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=
+webidl-conversions@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-5.0.0.tgz#ae59c8a00b121543a2acc65c0434f57b0fc11aff"
+ integrity sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==
+
webidl-conversions@^6.1.0:
version "6.1.0"
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-6.1.0.tgz#9111b4d7ea80acd40f5270d666621afa78b69514"
@@ -8784,6 +10283,18 @@ webpack@^5.62.1:
watchpack "^2.3.1"
webpack-sources "^3.2.3"
+whatwg-encoding@^1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz#5abacf777c32166a51d085d6b4f3e7d27113ddb0"
+ integrity sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==
+ dependencies:
+ iconv-lite "0.4.24"
+
+whatwg-mimetype@^2.3.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz#3d4b1e0312d2079879f826aff18dbeeca5960fbf"
+ integrity sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==
+
whatwg-url@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d"
@@ -8792,7 +10303,7 @@ whatwg-url@^5.0.0:
tr46 "~0.0.3"
webidl-conversions "^3.0.0"
-whatwg-url@^8.4.0:
+whatwg-url@^8.0.0, whatwg-url@^8.4.0, whatwg-url@^8.5.0:
version "8.7.0"
resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-8.7.0.tgz#656a78e510ff8f3937bc0bcbe9f5c0ac35941b77"
integrity sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==
@@ -8838,7 +10349,7 @@ wildcard@^2.0.0:
resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.0.tgz#a77d20e5200c6faaac979e4b3aadc7b3dd7f8fec"
integrity sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==
-word-wrap@^1.2.3:
+word-wrap@^1.2.3, word-wrap@~1.2.3:
version "1.2.3"
resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c"
integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==
@@ -8919,6 +10430,21 @@ ws@7.4.6:
resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c"
integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==
+ws@^7.4.6:
+ version "7.5.7"
+ resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.7.tgz#9e0ac77ee50af70d58326ecff7e85eb3fa375e67"
+ integrity sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A==
+
+xml-name-validator@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a"
+ integrity sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==
+
+xmlchars@^2.2.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb"
+ integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==
+
xtend@~4.0.1:
version "4.0.2"
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
@@ -8949,7 +10475,7 @@ yargs-parser@20.2.4:
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54"
integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==
-yargs-parser@^20.2.2, yargs-parser@^20.2.3:
+yargs-parser@20.x, yargs-parser@^20.2.2, yargs-parser@^20.2.3:
version "20.2.9"
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee"
integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==
From bd07a785988dc312212c62d036d1096f91be3d1e Mon Sep 17 00:00:00 2001
From: Gerald
Date: Fri, 18 Feb 2022 11:01:00 +0100
Subject: [PATCH 02/86] keyDerivation: refactoring
---
.../src/background/keys/keyDerivation.ts | 33 +++++++++++--------
1 file changed, 19 insertions(+), 14 deletions(-)
diff --git a/packages/extension/src/background/keys/keyDerivation.ts b/packages/extension/src/background/keys/keyDerivation.ts
index b4f9b37f1..9507cc37a 100644
--- a/packages/extension/src/background/keys/keyDerivation.ts
+++ b/packages/extension/src/background/keys/keyDerivation.ts
@@ -3,15 +3,19 @@ import { ec, number } from "starknet"
// from https://github.com/ethereum/EIPs/blob/master/EIPS/eip-2645.md
// m / purpose' / layer' / application' / eth_address_1' / eth_address_2' / index
-// layer = pathHash(starknet)
-// application = pathHash(argentx)
+// layer = pathHash("starknet")
+// application = pathHash("argentx")
const BASE_PATH = "m/2645'/1195502025'/1148870696'/0'/0'"
-export function getStarkPair(index: number, secret: BigNumberish) {
+export function getStarkPair(
+ indexOrPath: number | string,
+ secret: BigNumberish,
+) {
const masterNode = utils.HDNode.fromSeed(BigNumber.from(secret).toHexString())
- const path = getPathForIndex(index)
+ const path =
+ typeof indexOrPath === "number" ? getPathForIndex(indexOrPath) : indexOrPath
const childNode = masterNode.derivePath(path)
const grindedKey = grindKey(childNode.privateKey)
const starkPair = ec.getKeyPair(grindedKey)
@@ -47,15 +51,16 @@ export function grindKey(keySeed: string) {
const maxAllowedVal = sha256EcMaxDigest.sub(
sha256EcMaxDigest.mod(keyValLimit),
)
+
+ // Make sure the produced key is devided by the Stark EC order,
+ // and falls within the range [0, maxAllowedVal).
let i = 0
- let key = hashKeyWithIndex(keySeed, i)
- i++
- // Make sure the produced key is devided by the Stark EC order, and falls within the range
- // [0, maxAllowedVal).
- while (!key.lt(maxAllowedVal)) {
+ let key
+ do {
key = hashKeyWithIndex(keySeed, i)
i++
- }
+ } while (!key.lt(maxAllowedVal))
+
return "0x" + key.umod(keyValLimit).toString("hex")
}
@@ -66,8 +71,8 @@ function hashKeyWithIndex(key: string, index: number) {
}
export function pathHash(name: string) {
- const hash = utils.arrayify(utils.sha256(utils.toUtf8Bytes(name))).slice(-4)
- return BigNumber.from(
- utils.concat([[hash[0] & 127], hash.slice(-3)]),
- ).toNumber()
+ return number
+ .toBN(utils.sha256(utils.toUtf8Bytes(name)))
+ .maskn(31)
+ .toNumber()
}
From 66e6b9d4e92d75e63d7e9b4e8b2cc9d57ca3fb37 Mon Sep 17 00:00:00 2001
From: Gerald
Date: Fri, 18 Feb 2022 14:21:39 +0100
Subject: [PATCH 03/86] select the right keypair before signing tx validate
keystore file before importing
---
packages/extension/src/background/index.ts | 25 ++-------
packages/extension/src/background/keys/l1.ts | 53 ++++++++++++-------
.../extension/src/background/signer/index.ts | 24 ++++-----
3 files changed, 49 insertions(+), 53 deletions(-)
diff --git a/packages/extension/src/background/index.ts b/packages/extension/src/background/index.ts
index 251d6c8f2..02a719981 100644
--- a/packages/extension/src/background/index.ts
+++ b/packages/extension/src/background/index.ts
@@ -1,5 +1,5 @@
import { compactDecrypt } from "jose"
-import { ec, encode } from "starknet"
+import { encode } from "starknet"
import { ActionItem } from "../shared/actionQueue"
import { messageStream } from "../shared/messages"
@@ -19,12 +19,11 @@ import {
deleteAccount,
downloadBackupFile,
existsL1,
- getL1,
getWallets,
+ importKeystore,
isUnlocked,
lockWallet,
resetAll,
- setKeystore,
validatePassword,
} from "./keys/l1"
import { getNonce, increaseStoredNonce, resetStoredNonce } from "./nonce"
@@ -220,17 +219,10 @@ import { addToWhitelist, isOnWhitelist } from "./whitelist"
if (!isUnlocked()) {
throw Error("you need an open session")
}
- const l1 = await getL1()
- const keyPair = ec.getKeyPair(l1.privateKey)
const selectedWallet = await selectedWalletStore.getItem(
"SELECTED_WALLET",
)
- const signer = await getSigner({
- type: "LOCAL",
- address: selectedWallet.address,
- keyPair,
- network: selectedWallet.network,
- })
+ const signer = await getSigner(selectedWallet)
try {
const nonce = await getNonce(signer)
@@ -263,17 +255,10 @@ import { addToWhitelist, isOnWhitelist } from "./whitelist"
if (!isUnlocked()) {
throw Error("you need an open session")
}
- const l1 = await getL1()
- const keyPair = ec.getKeyPair(l1.privateKey)
const selectedWallet = await selectedWalletStore.getItem(
"SELECTED_WALLET",
)
- const signer = await getSigner({
- type: "LOCAL",
- address: selectedWallet.address,
- keyPair,
- network: selectedWallet.network,
- })
+ const signer = await getSigner(selectedWallet)
const [r, s] = await signer.signMessage(typedData)
@@ -473,7 +458,7 @@ import { addToWhitelist, isOnWhitelist } from "./whitelist"
}
case "RECOVER_KEYSTORE": {
- await setKeystore(msg.data)
+ await importKeystore(msg.data)
return sendToTabAndUi({ type: "RECOVER_KEYSTORE_RES" })
}
case "DOWNLOAD_BACKUP_FILE": {
diff --git a/packages/extension/src/background/keys/l1.ts b/packages/extension/src/background/keys/l1.ts
index a1975d699..9004af947 100644
--- a/packages/extension/src/background/keys/l1.ts
+++ b/packages/extension/src/background/keys/l1.ts
@@ -15,14 +15,15 @@ import {
const isDev = process.env.NODE_ENV === "development"
+const STORAGE_KEY = "KEYSTORE"
interface StorageProps {
- encKeystore?: string
+ [STORAGE_KEY]?: string
}
const store = new Storage({}, "L1")
export async function existsL1() {
- return Boolean(await store.getItem("encKeystore"))
+ return Boolean(await store.getItem(STORAGE_KEY))
}
export async function validatePassword(password: string) {
@@ -49,20 +50,32 @@ export function isUnlocked(): boolean {
}
async function getKeystore() {
- const encKeystore = await store.getItem("encKeystore")
+ const encKeystore = await store.getItem(STORAGE_KEY)
if (!encKeystore) {
throw Error("No keystore exists")
}
const encKeystoreObj = JSON.parse(encKeystore)
return JSON.stringify({
...encKeystoreObj,
- wallets: encKeystoreObj["x-argentx"].accounts,
+ wallets: encKeystoreObj["x-argent"].accounts,
})
}
-export async function setKeystore(keystore: string) {
+async function setKeystore(keystore: string) {
setRawWallet(undefined)
- await store.setItem("encKeystore", keystore)
+ await store.setItem(STORAGE_KEY, keystore)
+}
+
+async function validateKeystore(keystore: string) {
+ const keystoreObj = JSON.parse(keystore)
+ if (keystoreObj["x-version"] !== 1) {
+ throw Error("Invalid Keystore file format")
+ }
+}
+
+export async function importKeystore(keystore: string) {
+ validateKeystore(keystore)
+ setKeystore(keystore)
}
async function recoverL1(password: string): Promise {
@@ -97,9 +110,7 @@ export async function getL1(password?: string): Promise {
const recoveredWallet = await recoverPromise
setRawWallet(recoveredWallet)
sessionPassword = password
- const encKeystore = JSON.parse(
- (await store.getItem("encKeystore")) || "{}",
- )
+ const encKeystore = JSON.parse((await store.getItem(STORAGE_KEY)) || "{}")
if (
(await selectedWalletStore.getItem("SELECTED_WALLET")).address === "" &&
@@ -141,7 +152,8 @@ async function getEncKeystore(
const extendedBackup = {
...JSON.parse(backup),
- "x-argentx": { version: 1, accounts: wallets },
+ "x-version": 1,
+ "x-argent": { accounts: wallets },
}
return JSON.stringify(extendedBackup, null, 2)
}
@@ -175,7 +187,7 @@ export async function createAccount(networkId: string) {
const index = getNextPathIndex(current_paths)
const starkPair = getStarkPair(index, l1.privateKey)
const starkPub = ec.getStarkKey(starkPair)
- const seed = ec.getStarkKey(ec.genKeyPair())
+ const seed = starkPub //ec.getStarkKey(ec.genKeyPair())
const provider = getProvider(networkId)
const deployTransaction = await provider.deployContract(
@@ -193,18 +205,17 @@ export async function createAccount(networkId: string) {
throw new Error("Deploy transaction failed")
}
- const signer = {
- type: "local_secret",
- derivation_path: getPathForIndex(index),
- }
const newWallet = {
network: networkId,
address: deployTransaction.address,
- signer,
+ signer: {
+ type: "local_secret",
+ derivation_path: getPathForIndex(index),
+ },
}
const newWallets = [...wallets, newWallet]
const encKeystore = await getEncKeystore(l1, sessionPassword, newWallets)
- store.setItem("encKeystore", encKeystore)
+ store.setItem(STORAGE_KEY, encKeystore)
return {
wallet: newWallet,
@@ -214,7 +225,7 @@ export async function createAccount(networkId: string) {
}
export async function downloadBackupFile() {
- const encKeystore = (await store.getItem("encKeystore")) ?? ""
+ const encKeystore = (await store.getItem(STORAGE_KEY)) ?? ""
downloadTextFile(encKeystore, "starknet-backup.json")
}
@@ -228,7 +239,11 @@ export const deleteAccount = async (account: string) => {
const wallets = keystore.wallets.filter(
({ address }: any) => address !== account,
)
- const newKeystore = JSON.stringify({ ...keystore, wallets }, null, 2)
+ const newKeystore = JSON.stringify(
+ { ...keystore, "x-argent": { accounts: wallets } },
+ null,
+ 2,
+ )
await setKeystore(newKeystore)
await getL1()
}
diff --git a/packages/extension/src/background/signer/index.ts b/packages/extension/src/background/signer/index.ts
index ab08e725c..08972452e 100644
--- a/packages/extension/src/background/signer/index.ts
+++ b/packages/extension/src/background/signer/index.ts
@@ -1,23 +1,19 @@
import { Signer } from "starknet"
+import { BackupWallet } from "../../shared/backup.model"
import { getProvider } from "../../shared/networks"
+import { getStarkPair } from "../keys/keyDerivation"
+import { getL1 } from "../keys/l1"
-type GetSignerOptions = {
- type: "LOCAL"
- address: string
- network: string
- keyPair: string
-}
-
-export async function getSigner(options: GetSignerOptions): Promise {
- const { type, address, network, keyPair } = options
-
- const provider = getProvider(network)
+export async function getSigner(wallet: BackupWallet): Promise {
+ const provider = getProvider(wallet.network)
- switch (type) {
- case "LOCAL":
+ switch (wallet.signer.type) {
+ case "local_secret":
default: {
- return new Signer(provider, address, keyPair)
+ const l1 = await getL1()
+ const keyPair = getStarkPair(wallet.signer.derivation_path, l1.privateKey)
+ return new Signer(provider, wallet.address, keyPair)
}
}
}
From e4dc0966149ac7f4dd4213eaa14b4565fa4470bf Mon Sep 17 00:00:00 2001
From: Gerald
Date: Mon, 21 Feb 2022 17:55:59 +0100
Subject: [PATCH 04/86] refactor: replace l1.ts file by a Wallet object
---
packages/extension/package.json | 2 +
packages/extension/src/background/download.ts | 5 +
packages/extension/src/background/index.ts | 167 +++++-------
.../extension/src/background/interfaces.ts | 4 +
packages/extension/src/background/keys/l1.ts | 249 -----------------
.../src/background/selectedWallet.ts | 12 -
.../extension/src/background/signer/index.ts | 19 --
packages/extension/src/background/storage.ts | 17 +-
.../src/background/trackTransactions.ts | 4 +-
packages/extension/src/background/wallet.ts | 257 ++++++++++++++++++
packages/extension/src/shared/MessageType.ts | 14 +-
packages/extension/src/shared/backup.model.ts | 10 -
packages/extension/src/shared/networks.ts | 4 +-
packages/extension/src/shared/wallet.model.ts | 10 +
packages/extension/src/ui/Account.ts | 6 +-
packages/extension/test/backup.mock.json | 41 +++
packages/extension/test/backup.schema.json | 72 +++++
.../extension/test/backup_wrong.mock.json | 97 +++++++
packages/extension/test/wallet.test.ts | 150 ++++++++++
yarn.lock | 36 ++-
20 files changed, 775 insertions(+), 401 deletions(-)
create mode 100644 packages/extension/src/background/download.ts
create mode 100644 packages/extension/src/background/interfaces.ts
delete mode 100644 packages/extension/src/background/keys/l1.ts
delete mode 100644 packages/extension/src/background/selectedWallet.ts
delete mode 100644 packages/extension/src/background/signer/index.ts
create mode 100644 packages/extension/src/background/wallet.ts
delete mode 100644 packages/extension/src/shared/backup.model.ts
create mode 100644 packages/extension/src/shared/wallet.model.ts
create mode 100644 packages/extension/test/backup.mock.json
create mode 100644 packages/extension/test/backup.schema.json
create mode 100644 packages/extension/test/backup_wrong.mock.json
create mode 100644 packages/extension/test/wallet.test.ts
diff --git a/packages/extension/package.json b/packages/extension/package.json
index b4c9952e4..458321cf2 100644
--- a/packages/extension/package.json
+++ b/packages/extension/package.json
@@ -6,6 +6,7 @@
"devDependencies": {
"@svgr/webpack": "^6.0.0",
"@types/jest": "^27.4.0",
+ "@types/jest-json-schema": "^6.1.0",
"@types/object-hash": "^2.2.1",
"@types/react": "^17.0.34",
"@types/react-copy-to-clipboard": "^5.0.2",
@@ -21,6 +22,7 @@
"file-loader": "^6.2.0",
"html-webpack-plugin": "^5.5.0",
"jest": "^27.5.1",
+ "jest-json-schema": "^6.1.0",
"raw-loader": "^4.0.2",
"ts-jest": "^27.1.3",
"ts-loader": "^9.2.6",
diff --git a/packages/extension/src/background/download.ts b/packages/extension/src/background/download.ts
new file mode 100644
index 000000000..1c860e588
--- /dev/null
+++ b/packages/extension/src/background/download.ts
@@ -0,0 +1,5 @@
+import browser from "webextension-polyfill"
+
+export async function downloadFile(data: { url: string; filename: string }) {
+ browser.downloads.download(data)
+}
diff --git a/packages/extension/src/background/index.ts b/packages/extension/src/background/index.ts
index 02a719981..f244bb5b0 100644
--- a/packages/extension/src/background/index.ts
+++ b/packages/extension/src/background/index.ts
@@ -1,3 +1,4 @@
+import ArgentCompiledContract from "!!raw-loader!../contracts/ArgentAccount.txt"
import { compactDecrypt } from "jose"
import { encode } from "starknet"
@@ -13,19 +14,8 @@ import {
sendMessageToActiveTabsAndUi,
sendMessageToUi,
} from "./activeTabs"
+import { downloadFile } from "./download"
import { getKeyPair } from "./keys/communication"
-import {
- createAccount,
- deleteAccount,
- downloadBackupFile,
- existsL1,
- getWallets,
- importKeystore,
- isUnlocked,
- lockWallet,
- resetAll,
- validatePassword,
-} from "./keys/l1"
import { getNonce, increaseStoredNonce, resetStoredNonce } from "./nonce"
import {
addToAlreadyShown,
@@ -33,52 +23,51 @@ import {
sentTransactionNotification,
} from "./notification"
import { openUi } from "./openUi"
-import { selectedWalletStore } from "./selectedWallet"
-import { getSigner } from "./signer"
-import { setToStorage } from "./storage"
+import { Storage, clearStorage, setToStorage } from "./storage"
import { TransactionTracker, getTransactionStatus } from "./trackTransactions"
+import { Wallet, WalletStorageProps } from "./wallet"
import { addToWhitelist, isOnWhitelist } from "./whitelist"
;(async () => {
const { privateKey, publicKeyJwk } = await getKeyPair()
- const transactionTracker = new TransactionTracker(
- async (transactions) => {
- if (transactions.length > 0) {
- sendMessageToUi({
- type: "TRANSACTION_UPDATES",
- data: transactions,
- })
-
- for (const { hash, status, walletAddress, meta } of transactions) {
- if (
- (status === "ACCEPTED_ON_L2" || status === "REJECTED") &&
- !(await hasShownNotification(hash))
- ) {
- addToAlreadyShown(hash)
- sentTransactionNotification(hash, status, meta)
- if (walletAddress && status === "ACCEPTED_ON_L2") {
- sendMessageToUi({
- type: "TRANSACTION_SUCCESS",
- data: {
- hash,
- status,
- walletAddress,
- meta,
- },
- })
- }
- }
- // on error remove stored (increased) nonce
- if (walletAddress && status === "REJECTED") {
- resetStoredNonce(walletAddress)
+ const storage = new Storage({}, "WALLET")
+ const wallet = new Wallet(storage, ArgentCompiledContract)
+ await wallet.setup()
+
+ const transactionTracker = new TransactionTracker(async (transactions) => {
+ if (transactions.length > 0) {
+ sendMessageToUi({
+ type: "TRANSACTION_UPDATES",
+ data: transactions,
+ })
+
+ for (const { hash, status, walletAddress, meta } of transactions) {
+ if (
+ (status === "ACCEPTED_ON_L2" || status === "REJECTED") &&
+ !(await hasShownNotification(hash))
+ ) {
+ addToAlreadyShown(hash)
+ sentTransactionNotification(hash, status, meta)
+ if (walletAddress && status === "ACCEPTED_ON_L2") {
+ sendMessageToUi({
+ type: "TRANSACTION_SUCCESS",
+ data: {
+ hash,
+ status,
+ walletAddress,
+ meta,
+ },
+ })
}
}
+ // on error remove stored (increased) nonce
+ if (walletAddress && status === "REJECTED") {
+ resetStoredNonce(walletAddress)
+ }
}
- },
-
- 30 * 1000,
- )
+ }
+ }, 30 * 1000)
messageStream.subscribe(async ([msg, sender]) => {
const sendToTabAndUi = async (msg: MessageType) => {
@@ -154,9 +143,7 @@ import { addToWhitelist, isOnWhitelist } from "./whitelist"
}
case "GET_SELECTED_WALLET": {
- const selectedWallet = await selectedWalletStore.getItem(
- "SELECTED_WALLET",
- )
+ const selectedWallet = await wallet.getSelectedAccount()
return sendToTabAndUi({
type: "GET_SELECTED_WALLET_RES",
@@ -165,9 +152,7 @@ import { addToWhitelist, isOnWhitelist } from "./whitelist"
}
case "CONNECT": {
- const selectedWallet = await selectedWalletStore.getItem(
- "SELECTED_WALLET",
- )
+ const selectedWallet = await wallet.getSelectedAccount()
const isWhitelisted = await isOnWhitelist(msg.data.host)
addTab(sender.tab?.id)
@@ -187,7 +172,7 @@ import { addToWhitelist, isOnWhitelist } from "./whitelist"
}
case "WALLET_CONNECTED": {
- return selectedWalletStore.setItem("SELECTED_WALLET", msg.data)
+ return await wallet.selectAccount(msg.data.address)
}
case "APPROVE_ACTION": {
@@ -199,9 +184,7 @@ import { addToWhitelist, isOnWhitelist } from "./whitelist"
switch (action.type) {
case "CONNECT": {
const { host } = action.payload
- const selectedWallet = await selectedWalletStore.getItem(
- "SELECTED_WALLET",
- )
+ const selectedWallet = await wallet.getSelectedAccount()
await addToWhitelist(host)
@@ -216,13 +199,11 @@ import { addToWhitelist, isOnWhitelist } from "./whitelist"
case "TRANSACTION": {
const transaction = action.payload
- if (!isUnlocked()) {
+ if (!wallet.isSessionOpen()) {
throw Error("you need an open session")
}
- const selectedWallet = await selectedWalletStore.getItem(
- "SELECTED_WALLET",
- )
- const signer = await getSigner(selectedWallet)
+ const selectedWallet = await wallet.getSelectedAccount()
+ const signer = await wallet.getSelectedAccountSigner()
try {
const nonce = await getNonce(signer)
@@ -252,13 +233,10 @@ import { addToWhitelist, isOnWhitelist } from "./whitelist"
case "SIGN": {
const typedData = action.payload
- if (!isUnlocked()) {
+ if (!wallet.isSessionOpen()) {
throw Error("you need an open session")
}
- const selectedWallet = await selectedWalletStore.getItem(
- "SELECTED_WALLET",
- )
- const signer = await getSigner(selectedWallet)
+ const signer = await wallet.getSelectedAccountSigner()
const [r, s] = await signer.signMessage(typedData)
@@ -352,7 +330,8 @@ import { addToWhitelist, isOnWhitelist } from "./whitelist"
}
case "RESET_ALL": {
- return resetAll()
+ clearStorage()
+ return wallet.lock()
}
case "ADD_WHITELIST": {
@@ -380,7 +359,7 @@ import { addToWhitelist, isOnWhitelist } from "./whitelist"
}
const { plaintext } = await compactDecrypt(body, privateKey)
const sessionPassword = encode.arrayBufferToString(plaintext)
- if (await validatePassword(sessionPassword)) {
+ if (await wallet.startSession(sessionPassword)) {
sendToTabAndUi({ type: "START_SESSION_RES" })
}
return sendToTabAndUi({ type: "START_SESSION_REJ" })
@@ -388,33 +367,48 @@ import { addToWhitelist, isOnWhitelist } from "./whitelist"
case "HAS_SESSION": {
return sendToTabAndUi({
type: "HAS_SESSION_RES",
- data: isUnlocked(),
+ data: wallet.isSessionOpen(),
})
}
case "STOP_SESSION": {
- return lockWallet()
+ return wallet.lock()
}
case "IS_INITIALIZED": {
return sendToTabAndUi({
type: "IS_INITIALIZED_RES",
- data: await existsL1(),
+ data: await wallet.isInitialized(),
})
}
case "GET_WALLETS": {
return sendToTabAndUi({
type: "GET_WALLETS_RES",
- data: await getWallets(),
+ data: await wallet.getAccounts(),
})
}
case "NEW_ACCOUNT": {
- if (!isUnlocked()) {
+ if (!wallet.isSessionOpen()) {
throw Error("you need an open session")
}
const network = msg.data
- let newAccount
try {
- newAccount = await createAccount(network)
+ const { account, txHash } = await wallet.addAccount(network)
+ transactionTracker.trackTransaction(txHash, account, {
+ title: "Deploy wallet",
+ })
+
+ await downloadFile(wallet.exportBackup())
+
+ return sendToTabAndUi({
+ type: "NEW_ACCOUNT_RES",
+ data: {
+ status: "ok",
+ txHash,
+ address: account.address,
+ wallet: account,
+ wallets: wallet.getAccounts(),
+ },
+ })
} catch (e: any) {
let error = `${e}`
if (network.includes("localhost")) {
@@ -430,17 +424,6 @@ import { addToWhitelist, isOnWhitelist } from "./whitelist"
data: { status: "ko", error },
})
}
-
- const { wallet } = newAccount
- selectedWalletStore.setItem("SELECTED_WALLET", wallet)
- transactionTracker.trackTransaction(newAccount.txHash, wallet, {
- title: "Deploy wallet",
- })
-
- return sendToTabAndUi({
- type: "NEW_ACCOUNT_RES",
- data: { status: "ok", address: wallet.address, ...newAccount },
- })
}
case "ADD_SIGN": {
@@ -458,17 +441,17 @@ import { addToWhitelist, isOnWhitelist } from "./whitelist"
}
case "RECOVER_KEYSTORE": {
- await importKeystore(msg.data)
+ await wallet.importBackup(msg.data)
return sendToTabAndUi({ type: "RECOVER_KEYSTORE_RES" })
}
case "DOWNLOAD_BACKUP_FILE": {
- await downloadBackupFile()
+ await downloadFile(wallet.exportBackup())
return sendToTabAndUi({ type: "DOWNLOAD_BACKUP_FILE_RES" })
}
case "DELETE_ACCOUNT": {
try {
- await deleteAccount(msg.data)
+ await wallet.removeAccount(msg.data)
return sendToTabAndUi({ type: "DELETE_ACCOUNT_RES" })
} catch {
return sendToTabAndUi({ type: "DELETE_ACCOUNT_REJ" })
diff --git a/packages/extension/src/background/interfaces.ts b/packages/extension/src/background/interfaces.ts
new file mode 100644
index 000000000..a6e3ca773
--- /dev/null
+++ b/packages/extension/src/background/interfaces.ts
@@ -0,0 +1,4 @@
+export interface IStorage> {
+ getItem(key: K): Promise
+ setItem(key: K, value: T[K]): Promise
+}
diff --git a/packages/extension/src/background/keys/l1.ts b/packages/extension/src/background/keys/l1.ts
deleted file mode 100644
index 9004af947..000000000
--- a/packages/extension/src/background/keys/l1.ts
+++ /dev/null
@@ -1,249 +0,0 @@
-import ArgentCompiledContract from "!!raw-loader!../../contracts/ArgentAccount.txt"
-import { ethers } from "ethers"
-import { compileCalldata, ec } from "starknet"
-import browser from "webextension-polyfill"
-
-import { BackupWallet } from "../../shared/backup.model"
-import { getProvider } from "../../shared/networks"
-import { selectedWalletStore } from "../selectedWallet"
-import { Storage } from "../storage"
-import {
- getNextPathIndex,
- getPathForIndex,
- getStarkPair,
-} from "./keyDerivation"
-
-const isDev = process.env.NODE_ENV === "development"
-
-const STORAGE_KEY = "KEYSTORE"
-interface StorageProps {
- [STORAGE_KEY]?: string
-}
-
-const store = new Storage({}, "L1")
-
-export async function existsL1() {
- return Boolean(await store.getItem(STORAGE_KEY))
-}
-
-export async function validatePassword(password: string) {
- try {
- await getL1(password)
- return true
- } catch (e) {
- console.error(e)
- return false
- }
-}
-
-let rawWallet: ethers.Wallet | undefined
-
-function setRawWallet(wallet?: ethers.Wallet) {
- rawWallet = wallet
- setTimeout(() => {
- rawWallet = undefined
- }, 15 * 60 * 60 * 1000)
-}
-
-export function isUnlocked(): boolean {
- return Boolean(rawWallet)
-}
-
-async function getKeystore() {
- const encKeystore = await store.getItem(STORAGE_KEY)
- if (!encKeystore) {
- throw Error("No keystore exists")
- }
- const encKeystoreObj = JSON.parse(encKeystore)
- return JSON.stringify({
- ...encKeystoreObj,
- wallets: encKeystoreObj["x-argent"].accounts,
- })
-}
-
-async function setKeystore(keystore: string) {
- setRawWallet(undefined)
- await store.setItem(STORAGE_KEY, keystore)
-}
-
-async function validateKeystore(keystore: string) {
- const keystoreObj = JSON.parse(keystore)
- if (keystoreObj["x-version"] !== 1) {
- throw Error("Invalid Keystore file format")
- }
-}
-
-export async function importKeystore(keystore: string) {
- validateKeystore(keystore)
- setKeystore(keystore)
-}
-
-async function recoverL1(password: string): Promise {
- if (!(await existsL1())) {
- throw Error("No KeyPair exists")
- }
- const encKeystore = await getKeystore()
- return await ethers.Wallet.fromEncryptedJson(encKeystore, password)
-}
-
-async function generateL1(): Promise {
- if (await existsL1()) {
- throw Error("KeyPair already exists")
- }
- return ethers.Wallet.createRandom()
-}
-
-let sessionPassword: string | undefined
-let recoverPromise: Promise | undefined
-
-export async function getL1(password?: string): Promise {
- if (rawWallet) {
- return rawWallet
- } else if (await existsL1()) {
- if (!recoverPromise) {
- if (!password) {
- throw Error("Password required")
- }
- recoverPromise = recoverL1(password)
- }
- try {
- const recoveredWallet = await recoverPromise
- setRawWallet(recoveredWallet)
- sessionPassword = password
- const encKeystore = JSON.parse((await store.getItem(STORAGE_KEY)) || "{}")
-
- if (
- (await selectedWalletStore.getItem("SELECTED_WALLET")).address === "" &&
- encKeystore.wallets.length > 0
- ) {
- await selectedWalletStore.setItem(
- "SELECTED_WALLET",
- encKeystore.wallets[0],
- )
- }
- return recoveredWallet
- } catch (e) {
- recoverPromise = undefined
- throw e
- }
- } else {
- sessionPassword = password
- const wallet = await generateL1()
- setRawWallet(wallet)
- return wallet
- }
-}
-
-export function lockWallet() {
- setRawWallet(undefined)
- recoverPromise = undefined
- sessionPassword = undefined
-}
-
-async function getEncKeystore(
- wallet: ethers.Wallet,
- password: string,
- wallets: BackupWallet[],
- progressFn?: (progress: number) => void,
-): Promise {
- // The number of encryption rounds must be a power of 2 (default: 131072 = 2 ^ 17)
- const N = isDev ? 64 : 32768
- const backup = await wallet.encrypt(password, { scrypt: { N } }, progressFn)
-
- const extendedBackup = {
- ...JSON.parse(backup),
- "x-version": 1,
- "x-argent": { accounts: wallets },
- }
- return JSON.stringify(extendedBackup, null, 2)
-}
-
-function downloadTextFile(text: string, filename: string) {
- const blob = new Blob([text], { type: "application/json" })
- const url = URL.createObjectURL(blob)
- browser.downloads.download({ url, filename })
-}
-
-export const getWallets = async (): Promise => {
- try {
- const { wallets } = JSON.parse(await getKeystore())
- return wallets
- } catch {
- return []
- }
-}
-
-export async function createAccount(networkId: string) {
- if (!sessionPassword) {
- throw Error("Password required")
- }
- const l1 = await getL1()
- const wallets = await getWallets()
-
- const current_paths = wallets
- .filter((wallet) => wallet.signer.type === "local_secret")
- .map((wallet) => wallet.signer.derivation_path)
-
- const index = getNextPathIndex(current_paths)
- const starkPair = getStarkPair(index, l1.privateKey)
- const starkPub = ec.getStarkKey(starkPair)
- const seed = starkPub //ec.getStarkKey(ec.genKeyPair())
-
- const provider = getProvider(networkId)
- const deployTransaction = await provider.deployContract(
- ArgentCompiledContract,
- compileCalldata({ signer: starkPub, guardian: "0" }),
- seed,
- )
-
- // TODO: register a L1 address with the wallet as soon as some registry is online
-
- if (
- deployTransaction.code !== "TRANSACTION_RECEIVED" ||
- !deployTransaction.address
- ) {
- throw new Error("Deploy transaction failed")
- }
-
- const newWallet = {
- network: networkId,
- address: deployTransaction.address,
- signer: {
- type: "local_secret",
- derivation_path: getPathForIndex(index),
- },
- }
- const newWallets = [...wallets, newWallet]
- const encKeystore = await getEncKeystore(l1, sessionPassword, newWallets)
- store.setItem(STORAGE_KEY, encKeystore)
-
- return {
- wallet: newWallet,
- txHash: deployTransaction.transaction_hash,
- wallets,
- }
-}
-
-export async function downloadBackupFile() {
- const encKeystore = (await store.getItem(STORAGE_KEY)) ?? ""
- downloadTextFile(encKeystore, "starknet-backup.json")
-}
-
-export async function resetAll() {
- lockWallet()
- await browser.storage.local.clear()
-}
-
-export const deleteAccount = async (account: string) => {
- const keystore = JSON.parse(await getKeystore())
- const wallets = keystore.wallets.filter(
- ({ address }: any) => address !== account,
- )
- const newKeystore = JSON.stringify(
- { ...keystore, "x-argent": { accounts: wallets } },
- null,
- 2,
- )
- await setKeystore(newKeystore)
- await getL1()
-}
diff --git a/packages/extension/src/background/selectedWallet.ts b/packages/extension/src/background/selectedWallet.ts
deleted file mode 100644
index 9c1322cc7..000000000
--- a/packages/extension/src/background/selectedWallet.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-import { BackupWallet } from "../shared/backup.model"
-import { Storage } from "./storage"
-
-export const selectedWalletStore = new Storage<{
- SELECTED_WALLET: BackupWallet
-}>({
- SELECTED_WALLET: {
- address: "",
- network: "",
- signer: { type: "", derivation_path: "" },
- },
-})
diff --git a/packages/extension/src/background/signer/index.ts b/packages/extension/src/background/signer/index.ts
deleted file mode 100644
index 08972452e..000000000
--- a/packages/extension/src/background/signer/index.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-import { Signer } from "starknet"
-
-import { BackupWallet } from "../../shared/backup.model"
-import { getProvider } from "../../shared/networks"
-import { getStarkPair } from "../keys/keyDerivation"
-import { getL1 } from "../keys/l1"
-
-export async function getSigner(wallet: BackupWallet): Promise {
- const provider = getProvider(wallet.network)
-
- switch (wallet.signer.type) {
- case "local_secret":
- default: {
- const l1 = await getL1()
- const keyPair = getStarkPair(wallet.signer.derivation_path, l1.privateKey)
- return new Signer(provider, wallet.address, keyPair)
- }
- }
-}
diff --git a/packages/extension/src/background/storage.ts b/packages/extension/src/background/storage.ts
index 4a097356a..de1f3f83f 100644
--- a/packages/extension/src/background/storage.ts
+++ b/packages/extension/src/background/storage.ts
@@ -1,5 +1,7 @@
import browser from "webextension-polyfill"
+import { IStorage } from "./interfaces"
+
export async function getFromStorage(
key: K,
): Promise {
@@ -14,13 +16,22 @@ export function setToStorage(key: string, value: any) {
return browser.storage.local.set({ [key]: JSON.stringify(value) })
}
-export class Storage> {
+export function removeFromStorage(key: string) {
+ return browser.storage.local.remove(key)
+}
+
+export function clearStorage() {
+ return browser.storage.local.clear
+}
+
+export class Storage implements IStorage {
private NS: string
public defaults: T
constructor(defaults: T, namespace = "") {
this.NS = namespace
this.defaults = defaults
}
+
async getItem(key: K): Promise {
return (
(await getFromStorage(this.NS + ":" + key.toString())) ??
@@ -30,4 +41,8 @@ export class Storage> {
async setItem(key: K, value: T[K]): Promise {
return setToStorage(this.NS + ":" + key.toString(), value)
}
+
+ async removeItem(key: K): Promise {
+ return removeFromStorage(this.NS + ":" + key.toString())
+ }
}
diff --git a/packages/extension/src/background/trackTransactions.ts b/packages/extension/src/background/trackTransactions.ts
index 641dee190..3aba9be9b 100644
--- a/packages/extension/src/background/trackTransactions.ts
+++ b/packages/extension/src/background/trackTransactions.ts
@@ -1,11 +1,11 @@
import { Provider } from "starknet"
-import { BackupWallet } from "../shared/backup.model"
import { getProvider } from "../shared/networks"
import {
TransactionMeta,
TransactionStatus,
} from "../shared/transactions.model"
+import { WalletAccount } from "../shared/wallet.model"
interface TransactionStatusWithProvider extends TransactionStatus {
provider: Provider
@@ -38,7 +38,7 @@ export class TransactionTracker {
public async trackTransaction(
transactionHash: string,
- wallet: BackupWallet,
+ wallet: WalletAccount,
meta: TransactionMeta = {
title: "Contract interaction",
},
diff --git a/packages/extension/src/background/wallet.ts b/packages/extension/src/background/wallet.ts
new file mode 100644
index 000000000..ac8d7bdf8
--- /dev/null
+++ b/packages/extension/src/background/wallet.ts
@@ -0,0 +1,257 @@
+import { ethers } from "ethers"
+import { Signer, compileCalldata, ec } from "starknet"
+
+import { getProvider } from "../shared/networks"
+import { WalletAccount } from "../shared/wallet.model"
+import { IStorage } from "./interfaces"
+// import { Storage } from "../storage"
+import {
+ getNextPathIndex,
+ getPathForIndex,
+ getStarkPair,
+} from "./keys/keyDerivation"
+
+const isDev = process.env.NODE_ENV === "development"
+const isTest = process.env.NODE_ENV === "test"
+const isDevOrTest = isDev || isTest
+
+interface WalletSession {
+ secret: string
+ password: string
+}
+
+export interface WalletStorageProps {
+ BACKUP?: string
+ SELECTED?: string
+}
+
+export class Wallet {
+ private accounts: WalletAccount[] = []
+
+ private encryptedBackup: string | undefined
+ private session: WalletSession | undefined
+
+ private store: IStorage
+ private compiledContract: string
+
+ constructor(store: IStorage, compiledContract: string) {
+ this.store = store
+ this.compiledContract = compiledContract
+ }
+
+ public async setup() {
+ await this.readBackup()
+ }
+
+ public isInitialized(): boolean {
+ console.log("isInitialized")
+ return this.encryptedBackup !== undefined
+ }
+
+ public isSessionOpen(): boolean {
+ return this.session !== undefined
+ }
+
+ private async generateNewLocalSecret(
+ password: string,
+ progressFn?: (progress: number) => void,
+ ) {
+ if (this.isInitialized()) {
+ return
+ }
+ const N = isDevOrTest ? 64 : 32768
+ const ethersWallet = ethers.Wallet.createRandom()
+ this.encryptedBackup = await ethersWallet.encrypt(
+ password,
+ { scrypt: { N } },
+ progressFn,
+ )
+
+ await this.writeBackup()
+ this.setSession(ethersWallet.privateKey, password)
+ }
+
+ public async startSession(password: string): Promise {
+ // session has already started
+ if (this.session) {
+ return true
+ }
+
+ // wallet is not initialized: let's initialise it
+ if (!this.isInitialized()) {
+ await this.generateNewLocalSecret(password)
+ return true
+ }
+
+ try {
+ const { privateKey: secret } = await ethers.Wallet.fromEncryptedJson(
+ this.encryptedBackup as string,
+ password,
+ )
+ this.setSession(secret, password)
+ return true
+ } catch (error) {
+ return false
+ }
+ }
+
+ public async addAccount(
+ networkId: string,
+ ): Promise<{ account: WalletAccount; txHash: string }> {
+ if (!this.isSessionOpen()) {
+ throw Error("no open session")
+ }
+
+ const current_paths = this.accounts
+ .filter((account) => account.signer.type === "local_secret")
+ .map((account) => account.signer.derivation_path)
+
+ const index = getNextPathIndex(current_paths)
+ const starkPair = getStarkPair(index, this.session?.secret as string)
+ const starkPub = ec.getStarkKey(starkPair)
+ const seed = starkPub //ec.getStarkKey(ec.genKeyPair())
+
+ const provider = getProvider(networkId)
+ const deployTransaction = await provider.deployContract(
+ this.compiledContract,
+ compileCalldata({ signer: starkPub, guardian: "0" }),
+ seed,
+ )
+
+ // TODO: register a L1 address with the wallet as soon as some registry is online
+
+ if (
+ deployTransaction.code !== "TRANSACTION_RECEIVED" ||
+ !deployTransaction.address
+ ) {
+ throw new Error("Deploy transaction failed")
+ }
+
+ const account = {
+ network: networkId,
+ address: deployTransaction.address,
+ signer: {
+ type: "local_secret",
+ derivation_path: getPathForIndex(index),
+ },
+ }
+
+ this.accounts.push(account)
+
+ await this.writeBackup()
+ await this.selectAccount(deployTransaction.address)
+
+ return { account, txHash: deployTransaction.transaction_hash }
+ }
+
+ public getAccounts(): WalletAccount[] {
+ return this.accounts
+ }
+
+ public async getSelectedAccountSigner(): Promise {
+ if (!this.isSessionOpen()) {
+ throw Error("no open session")
+ }
+
+ const account = await this.getSelectedAccount()
+
+ const keyPair = getStarkPair(
+ account.signer.derivation_path,
+ this.session?.secret as string,
+ )
+ const provider = getProvider(account.network)
+ return new Signer(provider, account.address, keyPair)
+ }
+
+ public async getSelectedAccount(): Promise {
+ if (this.accounts.length === 0) {
+ throw new Error("no accounts")
+ }
+
+ const address = await this.store.getItem("SELECTED")
+ const account = this.accounts.find((account) => account.address === address)
+ return account ?? this.accounts[0]
+ }
+
+ public async selectAccount(address: string) {
+ const account = this.accounts.find((account) => account.address === address)
+ if (account === undefined) {
+ return
+ }
+ await this.store.setItem("SELECTED", account.address)
+ }
+
+ public async removeAccount(address: string) {
+ if (!this.isSessionOpen()) {
+ throw Error("no open session")
+ }
+ this.accounts = this.accounts.filter(
+ (account) => account.address !== address,
+ )
+ await this.writeBackup()
+ }
+
+ public lock() {
+ this.session = undefined
+ }
+
+ public async importBackup(backupString: string) {
+ // validate backup schema here !
+ await this.store.setItem("BACKUP", backupString)
+ await this.setup()
+ }
+
+ public exportBackup(): { url: string; filename: string } {
+ if (!this.isInitialized()) {
+ throw Error("no local backup")
+ }
+ const blob = new Blob([this.encryptedBackup as string], {
+ type: "application/json",
+ })
+ const url = URL.createObjectURL(blob)
+ const filename = "argent-x-backup.json"
+ return { url, filename }
+ }
+
+ private setSession(secret: string, password: string) {
+ this.session = { secret, password }
+ if (!isTest) {
+ setTimeout(() => {
+ this.lock()
+ }, 15 * 60 * 60 * 1000)
+ }
+ }
+
+ private async readBackup() {
+ this.encryptedBackup = await this.store.getItem("BACKUP")
+ if (this.encryptedBackup === undefined) {
+ return
+ }
+ const backup = JSON.parse(this.encryptedBackup)
+ // in the future, check version is compatible here
+ // and throw or migrate if not
+ if (backup["x-version"] !== 1) {
+ this.encryptedBackup = undefined
+ throw new Error("invalid keystore file format")
+ }
+
+ this.accounts = backup["x-argent"].accounts
+ }
+
+ private async writeBackup() {
+ if (this.encryptedBackup === undefined) {
+ return
+ }
+ const backup = JSON.parse(this.encryptedBackup)
+ const extendedBackup = {
+ ...backup,
+ "x-version": 1,
+ "x-argent": {
+ accounts: this.accounts,
+ },
+ }
+ const backupString = JSON.stringify(extendedBackup)
+ await this.store.setItem("BACKUP", backupString)
+ this.encryptedBackup = backupString
+ }
+}
diff --git a/packages/extension/src/shared/MessageType.ts b/packages/extension/src/shared/MessageType.ts
index 57963e6fa..a85f6a651 100644
--- a/packages/extension/src/shared/MessageType.ts
+++ b/packages/extension/src/shared/MessageType.ts
@@ -2,9 +2,9 @@ import type { JWK } from "jose"
import type { InvokeFunctionTransaction, typedData } from "starknet"
import { ExtActionItem } from "./actionQueue"
-import { BackupWallet } from "./backup.model"
import { AddToken } from "./token.model"
import { TransactionStatus } from "./transactions.model"
+import { WalletAccount } from "./wallet.model"
export type MessageType =
| { type: "OPEN_UI" }
@@ -20,9 +20,9 @@ export type MessageType =
data: ExtActionItem[]
}
| { type: "GET_SELECTED_WALLET" }
- | { type: "GET_SELECTED_WALLET_RES"; data: BackupWallet }
+ | { type: "GET_SELECTED_WALLET_RES"; data: WalletAccount }
| { type: "CONNECT"; data: { host: string } }
- | { type: "CONNECT_RES"; data: BackupWallet }
+ | { type: "CONNECT_RES"; data: WalletAccount }
| {
type: "SUBMITTED_TX"
data: {
@@ -47,7 +47,7 @@ export type MessageType =
| { type: "IS_WHITELIST"; data: string }
| { type: "IS_WHITELIST_RES"; data: boolean }
| { type: "RESET_WHITELIST" }
- | { type: "WALLET_CONNECTED"; data: BackupWallet }
+ | { type: "WALLET_CONNECTED"; data: WalletAccount }
| { type: "RESET_ALL" }
| { type: "REQ_PUB" }
| { type: "REQ_PUB_RES"; data: JWK }
@@ -59,8 +59,8 @@ export type MessageType =
status: "ok"
txHash: string
address: string
- wallet: BackupWallet
- wallets: BackupWallet[]
+ wallet: WalletAccount
+ wallets: WalletAccount[]
}
}
| { type: "NEW_ACCOUNT_REJ"; data: { status: "ko"; error: string } }
@@ -70,7 +70,7 @@ export type MessageType =
| { type: "IS_INITIALIZED" }
| { type: "IS_INITIALIZED_RES"; data: boolean }
| { type: "GET_WALLETS" }
- | { type: "GET_WALLETS_RES"; data: BackupWallet[] }
+ | { type: "GET_WALLETS_RES"; data: WalletAccount[] }
| { type: "START_SESSION"; data: { secure: true; body: string } }
| { type: "START_SESSION_REJ" }
| { type: "START_SESSION_RES" }
diff --git a/packages/extension/src/shared/backup.model.ts b/packages/extension/src/shared/backup.model.ts
deleted file mode 100644
index 75fecb767..000000000
--- a/packages/extension/src/shared/backup.model.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-export interface BackupWalletSigner {
- type: string
- derivation_path: string
-}
-
-export interface BackupWallet {
- address: string
- network: string
- signer: BackupWalletSigner
-}
diff --git a/packages/extension/src/shared/networks.ts b/packages/extension/src/shared/networks.ts
index b5481d483..866cf071d 100644
--- a/packages/extension/src/shared/networks.ts
+++ b/packages/extension/src/shared/networks.ts
@@ -1,6 +1,6 @@
import { Provider } from "starknet"
-import { BackupWallet } from "./backup.model"
+import { WalletAccount } from "./wallet.model"
export interface Network {
id: string
@@ -33,7 +33,7 @@ export const getNetwork = (networkId: string): Network => {
return networks.find(({ id }) => id === networkId) || defaultNetwork
}
-export const networkWallets = (wallets: BackupWallet[], networkId: string) =>
+export const networkWallets = (wallets: WalletAccount[], networkId: string) =>
wallets.filter(
({ network }) => localNetworkId(network) === localNetworkId(networkId),
)
diff --git a/packages/extension/src/shared/wallet.model.ts b/packages/extension/src/shared/wallet.model.ts
new file mode 100644
index 000000000..247f669f4
--- /dev/null
+++ b/packages/extension/src/shared/wallet.model.ts
@@ -0,0 +1,10 @@
+export interface WalletAccountSigner {
+ type: string
+ derivation_path: string
+}
+
+export interface WalletAccount {
+ address: string
+ network: string
+ signer: WalletAccountSigner
+}
diff --git a/packages/extension/src/ui/Account.ts b/packages/extension/src/ui/Account.ts
index 932ca4a6f..a224407c7 100644
--- a/packages/extension/src/ui/Account.ts
+++ b/packages/extension/src/ui/Account.ts
@@ -1,9 +1,9 @@
import ArgentCompiledContract from "!!raw-loader!../contracts/ArgentAccount.txt"
import { CompiledContract, Contract, json } from "starknet"
-import { BackupWalletSigner } from "../shared/backup.model"
import { sendMessage, waitForMessage } from "../shared/messages"
import { getProvider } from "../shared/networks"
+import { WalletAccountSigner } from "../shared/wallet.model"
const ArgentCompiledContractJson: CompiledContract = json.parse(
ArgentCompiledContract,
@@ -12,14 +12,14 @@ const ArgentCompiledContractJson: CompiledContract = json.parse(
export class Account {
address: string
networkId: string
- signer: BackupWalletSigner
+ signer: WalletAccountSigner
deployTransaction?: string
contract: Contract
constructor(
address: string,
networkId: string,
- signer: BackupWalletSigner,
+ signer: WalletAccountSigner,
deployTransaction?: string,
) {
this.address = address
diff --git a/packages/extension/test/backup.mock.json b/packages/extension/test/backup.mock.json
new file mode 100644
index 000000000..288e4f782
--- /dev/null
+++ b/packages/extension/test/backup.mock.json
@@ -0,0 +1,41 @@
+{
+ "address": "d34a9147bb9d4293d548e6163f1d3b06fea3d9ef",
+ "id": "3369142b-b008-45b5-aae4-c5aba532831f",
+ "version": 3,
+ "Crypto": {
+ "cipher": "aes-128-ctr",
+ "cipherparams": { "iv": "30a5f17ff2392afaee4c0b4797bb6d60" },
+ "ciphertext": "c1675d661371e4b01e079bb181e7031f2d2f419621f20727b9d0f082f5c4a19f",
+ "kdf": "scrypt",
+ "kdfparams": {
+ "salt": "3f5b46d003fe6ef81eae075ad715f926c9df1a63e58eb810fdd5b67ca131393b",
+ "n": 64,
+ "dklen": 32,
+ "p": 1,
+ "r": 8
+ },
+ "mac": "f2df5f18fdca8a5f1a6be040f8f607057cc404bdf3d3db9a50fb32bfa8e4880d"
+ },
+ "x-ethers": {
+ "client": "ethers.js",
+ "gethFilename": "UTC--2022-02-21T09-22-13.0Z--d34a9147bb9d4293d548e6163f1d3b06fea3d9ef",
+ "mnemonicCounter": "bbabecfca8065212cf0fb9923f9376b8",
+ "mnemonicCiphertext": "90f8520d33b5b2d5797a86462f61032e",
+ "path": "m/44'/60'/0'/0/0",
+ "locale": "en",
+ "version": "0.1"
+ },
+ "x-version": 1,
+ "x-argent": {
+ "accounts": [
+ {
+ "network": "http://localhost:5000",
+ "address": "0x06c67629cae87e7a1b284f1002747af681b39b8199f9263b9aed985e200d8f59",
+ "signer": {
+ "type": "local_secret",
+ "derivation_path": "m/2645'/1195502025'/1148870696'/0'/0'/0"
+ }
+ }
+ ]
+ }
+}
diff --git a/packages/extension/test/backup.schema.json b/packages/extension/test/backup.schema.json
new file mode 100644
index 000000000..27017612f
--- /dev/null
+++ b/packages/extension/test/backup.schema.json
@@ -0,0 +1,72 @@
+{
+ "$id": "ArgentXBackupSchema",
+ "title": "Argent X Backup file",
+ "description": "Argent X Backup file",
+ "type": "object",
+ "properties": {
+ "x-version": { "type": "integer" },
+ "address": { "type": "string" },
+ "version": { "type": "integer" },
+ "Crypto": {
+ "type": "object",
+ "properties": {
+ "cipher": { "type": "string" },
+ "ciphertext": { "type": "string" },
+ "kdf": { "type": "string" },
+ "mac": { "type": "string" },
+ "cipherparams": {
+ "type": "object",
+ "properties": {
+ "iv": { "type": "string" }
+ },
+ "required": ["iv"]
+ },
+ "kdfparams": {
+ "type": "object",
+ "properties": {
+ "salt": { "type": "string" },
+ "n": { "type": "number" },
+ "dklen": { "type": "number" },
+ "p": { "type": "number" },
+ "r": { "type": "number" }
+ },
+ "required": ["salt", "n", "dklen", "p", "r"]
+ }
+ },
+ "required": [
+ "cipher",
+ "ciphertext",
+ "kdf",
+ "mac",
+ "cipherparams",
+ "kdfparams"
+ ]
+ },
+ "x-argent": {
+ "type": "object",
+ "properties": {
+ "accounts": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "address": { "type": "string" },
+ "network": { "type": "string" },
+ "signer": {
+ "type": "object",
+ "properties": {
+ "type": { "type": "string" },
+ "derivation_path": { "type": "string" }
+ },
+ "required": ["type", "derivation_path"]
+ }
+ },
+ "required": ["address", "network", "signer"]
+ }
+ }
+ },
+ "required": ["accounts"]
+ }
+ },
+ "required": ["x-version", "Crypto", "x-argent", "address", "version"]
+}
diff --git a/packages/extension/test/backup_wrong.mock.json b/packages/extension/test/backup_wrong.mock.json
new file mode 100644
index 000000000..ad2d2d783
--- /dev/null
+++ b/packages/extension/test/backup_wrong.mock.json
@@ -0,0 +1,97 @@
+{
+ "address": "118e75402cd82a69747e853113b126a42be57cac",
+ "id": "97f06943-1758-47dc-97e5-19fcd3486302",
+ "version": 3,
+ "Crypto": {
+ "cipher": "aes-128-ctr",
+ "cipherparams": {
+ "iv": "b94616acc138f299cb1c6d4a08192315"
+ },
+ "ciphertext": "70bc7b5b8eac992bf5b8a62bcf981dd54435cc055405ec112482fc012185d952",
+ "kdf": "scrypt",
+ "kdfparams": {
+ "salt": "72999edf77f77938f514f6bdd6fd4b9aad43aa0c238e7cd7c2276c22a8995719",
+ "n": 64,
+ "dklen": 32,
+ "p": 1,
+ "r": 8
+ },
+ "mac": "88ac5a66aedf793a972466bc53ba26605f5ffdc00ff857e092b1d60c004f77e3"
+ },
+ "x-ethers": {
+ "client": "ethers.js",
+ "gethFilename": "UTC--2021-12-03T12-11-13.0Z--118e75402cd82a69747e853113b126a42be57cac",
+ "mnemonicCounter": "169827b07254ee36b927c297cf135925",
+ "mnemonicCiphertext": "0a30bb7be18dc15ee0715cbddb111d00",
+ "path": "m/44'/60'/0'/0/0",
+ "locale": "en",
+ "version": "0.1"
+ },
+ "wallets": [
+ {
+ "network": "goerli-alpha",
+ "address": "0x3971ad091725c08550755ad8b3b26224861a010dc4f41f6e84ff125746f5c09"
+ },
+ {
+ "network": "goerli-alpha",
+ "address": "0x1d780fcd405ce406afacd3a90c7e58c64b76c99290bb0b5c7ec5ff4977da013"
+ },
+ {
+ "network": "goerli-alpha",
+ "address": "0x7996320c6d483f248d3bfaa3c2684cf3ae45f625f500ceb00cf8f7b32606fb3"
+ },
+ {
+ "network": "goerli-alpha",
+ "address": "0x4e75b3096bf48895688df397390cd56351fc412571d98c4ab62b63b54ec4d76"
+ },
+ {
+ "network": "goerli-alpha",
+ "address": "0xf0ceecd4e48bb45bceb31665811371560447b74e68f4086e2602ab83c96546"
+ },
+ {
+ "network": "goerli-alpha",
+ "address": "0x47f3f2db53c93c9178b1060416253eedd3da4607661ef43d405abe9df1298a6",
+ "type": 0
+ },
+ {
+ "network": "goerli-alpha",
+ "address": "0x52fc9dda4c61cdf4cfba9b6cce5f8ec8eb471162aed5793b9f9eb440f4bed84",
+ "type": 1
+ },
+ {
+ "network": "goerli-alpha",
+ "address": "0x55e41fdfc8a9bb5494c6145ac8412bed8045d96766d8f0c7e692fc3590b067c",
+ "type": 1
+ },
+ {
+ "network": "goerli-alpha",
+ "address": "0x38e1e923860a2bc16b68c25d39972f9e05956f8894252ff61e8b42a81771bc",
+ "type": 1
+ },
+ {
+ "network": "goerli-alpha",
+ "address": "0x1475f89353c7b95faf510ab4852f080ddc76fd12fa6ff326c8955b78dc2fbc0",
+ "type": 1
+ },
+ {
+ "network": "goerli-alpha",
+ "address": "0x489aa864db26ce19d597984b31adea880c2198e637b276a0ee3357493f1d1a9",
+ "type": 1
+ },
+ {
+ "network": "goerli-alpha",
+ "address": "0x20019a823ecfca183894e16e748240d40c1b59799444bcebe35f30cc07ae06b",
+ "type": 1
+ },
+ {
+ "network": "goerli-alpha",
+ "address": "0x59e449776ef7962fc0f40136eb925d8864e4c0b8b7a4bfab58b71888ba5a29c",
+ "type": 1
+ },
+ {
+ "network": "goerli-alpha",
+ "address": "0x3e4bd8020473c60f2f89e2f15fba9c0ffe8f6df29823e80a2e52c7ae91921b5",
+ "type": 1
+ }
+ ]
+}
diff --git a/packages/extension/test/wallet.test.ts b/packages/extension/test/wallet.test.ts
new file mode 100644
index 000000000..2cdc6be54
--- /dev/null
+++ b/packages/extension/test/wallet.test.ts
@@ -0,0 +1,150 @@
+import fs from "fs"
+import path from "path"
+
+import { matchers } from "jest-json-schema"
+
+import { IStorage } from "../src/background/interfaces"
+import { Wallet, WalletStorageProps } from "../src/background/wallet"
+
+expect.extend(matchers)
+
+export class MockStorage implements IStorage {
+ public store: WalletStorageProps = {}
+
+ async getItem(key: keyof WalletStorageProps): Promise {
+ return Promise.resolve(this.store[key] || undefined)
+ }
+ async setItem(key: keyof WalletStorageProps, value: string): Promise {
+ this.store[key] = value
+ return Promise.resolve()
+ }
+}
+
+const compiledContract = fs.readFileSync(
+ path.join(__dirname, "../src/contracts/ArgentAccount.txt"),
+ "utf8",
+)
+
+const backupSchema = JSON.parse(
+ fs.readFileSync(path.join(__dirname, "./backup.schema.json"), "utf8"),
+)
+
+const backupString = fs.readFileSync(
+ path.join(__dirname, "./backup.mock.json"),
+ "utf8",
+)
+
+const backupWrongString = fs.readFileSync(
+ path.join(__dirname, "./backup_wrong.mock.json"),
+ "utf8",
+)
+
+const REGEX_HEXSTRING = /^0x[a-fA-F0-9]+/i
+
+const NETWORK = "http://localhost:5000" // "goerli-alpha"
+
+jest.setTimeout(999999)
+
+test("create a new wallet", async () => {
+ const storage = new MockStorage()
+ const wallet = new Wallet(storage, compiledContract)
+ await wallet.setup()
+
+ expect(wallet.isInitialized()).toBe(false)
+
+ const isValid = await wallet.startSession("my_secret_password")
+
+ expect(isValid).toBe(true)
+ expect(wallet.isInitialized()).toBe(true)
+ expect(wallet.isSessionOpen()).toBe(true)
+
+ const backupWithoutAccount = await storage.getItem("BACKUP")
+ expect(backupWithoutAccount).toBeDefined()
+ expect(JSON.parse(backupWithoutAccount as string)).toMatchSchema(backupSchema)
+
+ const { txHash } = await wallet.addAccount(NETWORK)
+ expect(txHash).toMatch(REGEX_HEXSTRING)
+
+ const accounts = wallet.getAccounts()
+ expect(accounts).toHaveLength(1)
+
+ const backupWithAccount = await storage.getItem("BACKUP")
+ expect(backupWithAccount).toBeDefined()
+ expect(JSON.parse(backupWithAccount as string)).toMatchSchema(backupSchema)
+
+ const selectedAccount = await wallet.getSelectedAccount()
+ expect(selectedAccount).toBeDefined()
+})
+
+test("open existing wallet", async () => {
+ const storage = new MockStorage()
+ storage.setItem("BACKUP", backupString)
+ const wallet = new Wallet(storage, compiledContract)
+ await wallet.setup()
+
+ expect(wallet.isInitialized()).toBe(true)
+
+ const isValid = await wallet.startSession("my_secret_password")
+ expect(isValid).toBe(true)
+ expect(wallet.isSessionOpen()).toBe(true)
+
+ const accounts = wallet.getAccounts()
+ expect(accounts).toHaveLength(1)
+ const account = accounts[0]
+ expect(account.address).toBe(
+ "0x06c67629cae87e7a1b284f1002747af681b39b8199f9263b9aed985e200d8f59",
+ )
+
+ const backupWithAccount = await storage.getItem("BACKUP")
+ expect(backupWithAccount).toBeDefined()
+ expect(JSON.parse(backupWithAccount as string)).toMatchSchema(backupSchema)
+
+ const selectedAccount = await wallet.getSelectedAccount()
+ expect(selectedAccount).toBeDefined()
+ expect(selectedAccount?.address).toBe(
+ "0x06c67629cae87e7a1b284f1002747af681b39b8199f9263b9aed985e200d8f59",
+ )
+})
+
+test("open existing wallet with wrong password", async () => {
+ const storage = new MockStorage()
+ storage.setItem("BACKUP", backupString)
+ const wallet = new Wallet(storage, compiledContract)
+ await wallet.setup()
+
+ expect(wallet.isInitialized()).toBe(true)
+
+ const isValid = await wallet.startSession("my_falsy_secret_password")
+ expect(isValid).toBe(false)
+ expect(wallet.isSessionOpen()).toBe(false)
+})
+
+test("import backup file", async () => {
+ const storage = new MockStorage()
+ const wallet = new Wallet(storage, compiledContract)
+ await wallet.setup()
+
+ expect(wallet.isInitialized()).toBe(false)
+
+ await wallet.importBackup(backupString)
+
+ expect(wallet.isInitialized()).toBe(true)
+
+ const isValid = await wallet.startSession("my_secret_password")
+ expect(isValid).toBe(true)
+ expect(wallet.isSessionOpen()).toBe(true)
+})
+
+test.skip("import wront backup file", async () => {
+ const storage = new MockStorage()
+ const wallet = new Wallet(storage, compiledContract)
+ await wallet.setup()
+
+ expect(wallet.isInitialized()).toBe(false)
+
+ expect(async () => {
+ await wallet.importBackup(backupWrongString)
+ }).toThrowError("invalid keystore")
+
+ expect(wallet.isInitialized()).toBe(false)
+})
diff --git a/yarn.lock b/yarn.lock
index 49859f7d9..15aa5c7e3 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -3187,7 +3187,15 @@
dependencies:
"@types/istanbul-lib-report" "*"
-"@types/jest@^27.4.0":
+"@types/jest-json-schema@^6.1.0":
+ version "6.1.0"
+ resolved "https://registry.yarnpkg.com/@types/jest-json-schema/-/jest-json-schema-6.1.0.tgz#99ee02d022d62dc94a2a5ace34e94841cffb6eb1"
+ integrity sha512-8e9qbbrXbDCxLQTLca84AF2oWTxa/Vd3tiOLq7cblsY6zgtk7JgZ7nsfYxqLQEWjXF3IC4sqOHsA84R/hr555Q==
+ dependencies:
+ "@types/jest" "*"
+ ajv "^6.10.2"
+
+"@types/jest@*", "@types/jest@^27.4.0":
version "27.4.0"
resolved "https://registry.yarnpkg.com/@types/jest/-/jest-27.4.0.tgz#037ab8b872067cae842a320841693080f9cb84ed"
integrity sha512-gHl8XuC1RZ8H2j5sHv/JqsaxXkDDM9iDOgu0Wp8sjs4u/snb2PVehyWXJPr+ORA0RPpgw231mnutWI1+0hgjIQ==
@@ -3674,7 +3682,7 @@ ajv-keywords@^5.0.0:
dependencies:
fast-deep-equal "^3.1.3"
-ajv@^6.10.0, ajv@^6.12.3, ajv@^6.12.4, ajv@^6.12.5:
+ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.3, ajv@^6.12.4, ajv@^6.12.5:
version "6.12.6"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4"
integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==
@@ -3694,6 +3702,16 @@ ajv@^8.0.0, ajv@^8.8.0:
require-from-string "^2.0.2"
uri-js "^4.2.2"
+ajv@^8.8.2:
+ version "8.10.0"
+ resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.10.0.tgz#e573f719bd3af069017e3b66538ab968d040e54d"
+ integrity sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw==
+ dependencies:
+ fast-deep-equal "^3.1.1"
+ json-schema-traverse "^1.0.0"
+ require-from-string "^2.0.2"
+ uri-js "^4.2.2"
+
ansi-escapes@^4.2.1:
version "4.3.2"
resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e"
@@ -4245,7 +4263,7 @@ chalk@^2.0.0:
escape-string-regexp "^1.0.5"
supports-color "^5.3.0"
-chalk@^4.0.0, chalk@^4.1.0:
+chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.2:
version "4.1.2"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
@@ -6768,6 +6786,16 @@ jest-jasmine2@^27.5.1:
pretty-format "^27.5.1"
throat "^6.0.1"
+jest-json-schema@^6.1.0:
+ version "6.1.0"
+ resolved "https://registry.yarnpkg.com/jest-json-schema/-/jest-json-schema-6.1.0.tgz#68ccc23424a7b20550d59ab9186530f81113e6af"
+ integrity sha512-LMHuLmKjr/4X+H8v1xF5TEwfYEkzwGeWJ0epYQVQhlVTDDR5FWCdSO8vmsecb5cLf9NeWAqMKn3qhJvP9um0AA==
+ dependencies:
+ ajv "^8.8.2"
+ ajv-formats "^2.1.1"
+ chalk "^4.1.2"
+ jest-matcher-utils "^27.3.1"
+
jest-leak-detector@^27.5.1:
version "27.5.1"
resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-27.5.1.tgz#6ec9d54c3579dd6e3e66d70e3498adf80fde3fb8"
@@ -6776,7 +6804,7 @@ jest-leak-detector@^27.5.1:
jest-get-type "^27.5.1"
pretty-format "^27.5.1"
-jest-matcher-utils@^27.5.1:
+jest-matcher-utils@^27.3.1, jest-matcher-utils@^27.5.1:
version "27.5.1"
resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz#9c0cdbda8245bc22d2331729d1091308b40cf8ab"
integrity sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw==
From fc06895d5c8081cdeaf8a6a64495ad18325a1854 Mon Sep 17 00:00:00 2001
From: Gerald
Date: Mon, 21 Feb 2022 19:00:24 +0100
Subject: [PATCH 05/86] add backup file validation
---
packages/extension/package.json | 2 +-
.../background/schema}/backup.schema.json | 2 +-
packages/extension/src/background/wallet.ts | 36 ++++++++++++++-----
packages/extension/test/wallet.test.ts | 27 ++++----------
yarn.lock | 2 +-
5 files changed, 37 insertions(+), 32 deletions(-)
rename packages/extension/{test => src/background/schema}/backup.schema.json (96%)
diff --git a/packages/extension/package.json b/packages/extension/package.json
index 458321cf2..c8964e36d 100644
--- a/packages/extension/package.json
+++ b/packages/extension/package.json
@@ -22,7 +22,6 @@
"file-loader": "^6.2.0",
"html-webpack-plugin": "^5.5.0",
"jest": "^27.5.1",
- "jest-json-schema": "^6.1.0",
"raw-loader": "^4.0.2",
"ts-jest": "^27.1.3",
"ts-loader": "^9.2.6",
@@ -45,6 +44,7 @@
"@mui/material": "^5.1.0",
"@mui/styled-engine-sc": "^5.1.0",
"@tippyjs/react": "^4.2.6",
+ "ajv": "^8.10.0",
"ethers": "^5.5.1",
"jose": "^4.3.6",
"object-hash": "^3.0.0",
diff --git a/packages/extension/test/backup.schema.json b/packages/extension/src/background/schema/backup.schema.json
similarity index 96%
rename from packages/extension/test/backup.schema.json
rename to packages/extension/src/background/schema/backup.schema.json
index 27017612f..ee4dcedad 100644
--- a/packages/extension/test/backup.schema.json
+++ b/packages/extension/src/background/schema/backup.schema.json
@@ -4,7 +4,7 @@
"description": "Argent X Backup file",
"type": "object",
"properties": {
- "x-version": { "type": "integer" },
+ "x-version": { "type": "integer", "minimum": 1, "maximum": 1 },
"address": { "type": "string" },
"version": { "type": "integer" },
"Crypto": {
diff --git a/packages/extension/src/background/wallet.ts b/packages/extension/src/background/wallet.ts
index ac8d7bdf8..8a4562620 100644
--- a/packages/extension/src/background/wallet.ts
+++ b/packages/extension/src/background/wallet.ts
@@ -1,20 +1,25 @@
+import Ajv from "ajv"
import { ethers } from "ethers"
import { Signer, compileCalldata, ec } from "starknet"
import { getProvider } from "../shared/networks"
import { WalletAccount } from "../shared/wallet.model"
import { IStorage } from "./interfaces"
-// import { Storage } from "../storage"
import {
getNextPathIndex,
getPathForIndex,
getStarkPair,
} from "./keys/keyDerivation"
+import backupSchema from "./schema/backup.schema.json"
const isDev = process.env.NODE_ENV === "development"
const isTest = process.env.NODE_ENV === "test"
const isDevOrTest = isDev || isTest
+const CURRENT_BACKUP_VERSION = 1
+
+const ajv = new Ajv()
+
interface WalletSession {
secret: string
password: string
@@ -44,7 +49,6 @@ export class Wallet {
}
public isInitialized(): boolean {
- console.log("isInitialized")
return this.encryptedBackup !== undefined
}
@@ -196,7 +200,9 @@ export class Wallet {
}
public async importBackup(backupString: string) {
- // validate backup schema here !
+ if (!Wallet.validateBackup(backupString)) {
+ throw new Error("invalid backup file")
+ }
await this.store.setItem("BACKUP", backupString)
await this.setup()
}
@@ -213,6 +219,15 @@ export class Wallet {
return { url, filename }
}
+ public static validateBackup(backupString: string): boolean {
+ try {
+ const backup = JSON.parse(backupString)
+ return ajv.validate(backupSchema, backup)
+ } catch (error) {
+ return false
+ }
+ }
+
private setSession(secret: string, password: string) {
this.session = { secret, password }
if (!isTest) {
@@ -227,12 +242,15 @@ export class Wallet {
if (this.encryptedBackup === undefined) {
return
}
- const backup = JSON.parse(this.encryptedBackup)
- // in the future, check version is compatible here
- // and throw or migrate if not
- if (backup["x-version"] !== 1) {
+
+ if (!Wallet.validateBackup(this.encryptedBackup)) {
this.encryptedBackup = undefined
- throw new Error("invalid keystore file format")
+ throw new Error("invalid backup file in local storage")
+ }
+
+ const backup = JSON.parse(this.encryptedBackup)
+ if (backup["x-version"] !== CURRENT_BACKUP_VERSION) {
+ // in the future, backup file migration will happen here
}
this.accounts = backup["x-argent"].accounts
@@ -245,7 +263,7 @@ export class Wallet {
const backup = JSON.parse(this.encryptedBackup)
const extendedBackup = {
...backup,
- "x-version": 1,
+ "x-version": CURRENT_BACKUP_VERSION,
"x-argent": {
accounts: this.accounts,
},
diff --git a/packages/extension/test/wallet.test.ts b/packages/extension/test/wallet.test.ts
index 2cdc6be54..4a021eabd 100644
--- a/packages/extension/test/wallet.test.ts
+++ b/packages/extension/test/wallet.test.ts
@@ -1,12 +1,13 @@
import fs from "fs"
import path from "path"
-import { matchers } from "jest-json-schema"
-
import { IStorage } from "../src/background/interfaces"
import { Wallet, WalletStorageProps } from "../src/background/wallet"
+import backupWrong from "./backup_wrong.mock.json"
+import backup from "./backup.mock.json"
-expect.extend(matchers)
+const backupString = JSON.stringify(backup)
+const backupWrongString = JSON.stringify(backupWrong)
export class MockStorage implements IStorage {
public store: WalletStorageProps = {}
@@ -25,20 +26,6 @@ const compiledContract = fs.readFileSync(
"utf8",
)
-const backupSchema = JSON.parse(
- fs.readFileSync(path.join(__dirname, "./backup.schema.json"), "utf8"),
-)
-
-const backupString = fs.readFileSync(
- path.join(__dirname, "./backup.mock.json"),
- "utf8",
-)
-
-const backupWrongString = fs.readFileSync(
- path.join(__dirname, "./backup_wrong.mock.json"),
- "utf8",
-)
-
const REGEX_HEXSTRING = /^0x[a-fA-F0-9]+/i
const NETWORK = "http://localhost:5000" // "goerli-alpha"
@@ -60,7 +47,7 @@ test("create a new wallet", async () => {
const backupWithoutAccount = await storage.getItem("BACKUP")
expect(backupWithoutAccount).toBeDefined()
- expect(JSON.parse(backupWithoutAccount as string)).toMatchSchema(backupSchema)
+ expect(Wallet.validateBackup(backupWithoutAccount as string)).toBe(true)
const { txHash } = await wallet.addAccount(NETWORK)
expect(txHash).toMatch(REGEX_HEXSTRING)
@@ -70,7 +57,7 @@ test("create a new wallet", async () => {
const backupWithAccount = await storage.getItem("BACKUP")
expect(backupWithAccount).toBeDefined()
- expect(JSON.parse(backupWithAccount as string)).toMatchSchema(backupSchema)
+ expect(Wallet.validateBackup(backupWithAccount as string)).toBe(true)
const selectedAccount = await wallet.getSelectedAccount()
expect(selectedAccount).toBeDefined()
@@ -97,7 +84,7 @@ test("open existing wallet", async () => {
const backupWithAccount = await storage.getItem("BACKUP")
expect(backupWithAccount).toBeDefined()
- expect(JSON.parse(backupWithAccount as string)).toMatchSchema(backupSchema)
+ expect(Wallet.validateBackup(backupWithAccount as string)).toBe(true)
const selectedAccount = await wallet.getSelectedAccount()
expect(selectedAccount).toBeDefined()
diff --git a/yarn.lock b/yarn.lock
index 15aa5c7e3..03e100a72 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -3702,7 +3702,7 @@ ajv@^8.0.0, ajv@^8.8.0:
require-from-string "^2.0.2"
uri-js "^4.2.2"
-ajv@^8.8.2:
+ajv@^8.10.0, ajv@^8.8.2:
version "8.10.0"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.10.0.tgz#e573f719bd3af069017e3b66538ab968d040e54d"
integrity sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw==
From cd7202ce278b0a5e9858a24453bd22bb9cc49d18 Mon Sep 17 00:00:00 2001
From: Gerald
Date: Mon, 21 Feb 2022 21:29:24 +0100
Subject: [PATCH 06/86] testing wallet lock after SESSION_DURATION
---
packages/extension/src/background/wallet.ts | 10 ++++----
packages/extension/test/wallet.test.ts | 26 ++++++++++++++++++++-
2 files changed, 30 insertions(+), 6 deletions(-)
diff --git a/packages/extension/src/background/wallet.ts b/packages/extension/src/background/wallet.ts
index 8a4562620..ac03e06cc 100644
--- a/packages/extension/src/background/wallet.ts
+++ b/packages/extension/src/background/wallet.ts
@@ -17,6 +17,7 @@ const isTest = process.env.NODE_ENV === "test"
const isDevOrTest = isDev || isTest
const CURRENT_BACKUP_VERSION = 1
+export const SESSION_DURATION = 15 * 60 * 60 * 1000 // 15 hours
const ajv = new Ajv()
@@ -230,11 +231,10 @@ export class Wallet {
private setSession(secret: string, password: string) {
this.session = { secret, password }
- if (!isTest) {
- setTimeout(() => {
- this.lock()
- }, 15 * 60 * 60 * 1000)
- }
+
+ setTimeout(() => {
+ this.lock()
+ }, SESSION_DURATION)
}
private async readBackup() {
diff --git a/packages/extension/test/wallet.test.ts b/packages/extension/test/wallet.test.ts
index 4a021eabd..e2e9d50a7 100644
--- a/packages/extension/test/wallet.test.ts
+++ b/packages/extension/test/wallet.test.ts
@@ -2,7 +2,11 @@ import fs from "fs"
import path from "path"
import { IStorage } from "../src/background/interfaces"
-import { Wallet, WalletStorageProps } from "../src/background/wallet"
+import {
+ SESSION_DURATION,
+ Wallet,
+ WalletStorageProps,
+} from "../src/background/wallet"
import backupWrong from "./backup_wrong.mock.json"
import backup from "./backup.mock.json"
@@ -27,12 +31,19 @@ const compiledContract = fs.readFileSync(
)
const REGEX_HEXSTRING = /^0x[a-fA-F0-9]+/i
+const SESSION_DURATION_PLUS_ONE_SEC = SESSION_DURATION + 1000
const NETWORK = "http://localhost:5000" // "goerli-alpha"
jest.setTimeout(999999)
+afterEach(() => {
+ jest.useRealTimers()
+})
+
test("create a new wallet", async () => {
+ jest.useFakeTimers()
+
const storage = new MockStorage()
const wallet = new Wallet(storage, compiledContract)
await wallet.setup()
@@ -61,9 +72,14 @@ test("create a new wallet", async () => {
const selectedAccount = await wallet.getSelectedAccount()
expect(selectedAccount).toBeDefined()
+
+ jest.advanceTimersByTime(SESSION_DURATION_PLUS_ONE_SEC)
+ expect(wallet.isSessionOpen()).toBe(false)
})
test("open existing wallet", async () => {
+ jest.useFakeTimers()
+
const storage = new MockStorage()
storage.setItem("BACKUP", backupString)
const wallet = new Wallet(storage, compiledContract)
@@ -91,6 +107,9 @@ test("open existing wallet", async () => {
expect(selectedAccount?.address).toBe(
"0x06c67629cae87e7a1b284f1002747af681b39b8199f9263b9aed985e200d8f59",
)
+
+ jest.advanceTimersByTime(SESSION_DURATION_PLUS_ONE_SEC)
+ expect(wallet.isSessionOpen()).toBe(false)
})
test("open existing wallet with wrong password", async () => {
@@ -107,6 +126,8 @@ test("open existing wallet with wrong password", async () => {
})
test("import backup file", async () => {
+ jest.useFakeTimers()
+
const storage = new MockStorage()
const wallet = new Wallet(storage, compiledContract)
await wallet.setup()
@@ -120,6 +141,9 @@ test("import backup file", async () => {
const isValid = await wallet.startSession("my_secret_password")
expect(isValid).toBe(true)
expect(wallet.isSessionOpen()).toBe(true)
+
+ jest.advanceTimersByTime(SESSION_DURATION_PLUS_ONE_SEC)
+ expect(wallet.isSessionOpen()).toBe(false)
})
test.skip("import wront backup file", async () => {
From ab82f8ce350d764f758c045f3fa9d88ae12b6fec Mon Sep 17 00:00:00 2001
From: Gerald
Date: Mon, 21 Feb 2022 22:06:06 +0100
Subject: [PATCH 07/86] test: fix "import wrong backup file"
---
packages/extension/test/wallet.test.ts | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/packages/extension/test/wallet.test.ts b/packages/extension/test/wallet.test.ts
index e2e9d50a7..f8204fb96 100644
--- a/packages/extension/test/wallet.test.ts
+++ b/packages/extension/test/wallet.test.ts
@@ -146,16 +146,16 @@ test("import backup file", async () => {
expect(wallet.isSessionOpen()).toBe(false)
})
-test.skip("import wront backup file", async () => {
+test("import wrong backup file", async () => {
const storage = new MockStorage()
const wallet = new Wallet(storage, compiledContract)
await wallet.setup()
expect(wallet.isInitialized()).toBe(false)
- expect(async () => {
- await wallet.importBackup(backupWrongString)
- }).toThrowError("invalid keystore")
+ await expect(wallet.importBackup(backupWrongString)).rejects.toThrow(
+ "invalid backup file",
+ )
expect(wallet.isInitialized()).toBe(false)
})
From 15616ae2726f6ede214e20b29a312243de2d2654 Mon Sep 17 00:00:00 2001
From: Gerald
Date: Mon, 21 Feb 2022 22:31:00 +0100
Subject: [PATCH 08/86] move storage into a dedicated folder
---
.../extension/src/background/{storage.ts => storage/default.ts} | 2 +-
packages/extension/src/background/storage/index.ts | 2 ++
.../src/background/{interfaces.ts => storage/interface.ts} | 0
packages/extension/src/background/wallet.ts | 2 +-
packages/extension/test/wallet.test.ts | 2 +-
5 files changed, 5 insertions(+), 3 deletions(-)
rename packages/extension/src/background/{storage.ts => storage/default.ts} (96%)
create mode 100644 packages/extension/src/background/storage/index.ts
rename packages/extension/src/background/{interfaces.ts => storage/interface.ts} (100%)
diff --git a/packages/extension/src/background/storage.ts b/packages/extension/src/background/storage/default.ts
similarity index 96%
rename from packages/extension/src/background/storage.ts
rename to packages/extension/src/background/storage/default.ts
index de1f3f83f..6040e4484 100644
--- a/packages/extension/src/background/storage.ts
+++ b/packages/extension/src/background/storage/default.ts
@@ -1,6 +1,6 @@
import browser from "webextension-polyfill"
-import { IStorage } from "./interfaces"
+import { IStorage } from "./interface"
export async function getFromStorage(
key: K,
diff --git a/packages/extension/src/background/storage/index.ts b/packages/extension/src/background/storage/index.ts
new file mode 100644
index 000000000..156dc1e4e
--- /dev/null
+++ b/packages/extension/src/background/storage/index.ts
@@ -0,0 +1,2 @@
+export * from "./interface"
+export * from "./default"
diff --git a/packages/extension/src/background/interfaces.ts b/packages/extension/src/background/storage/interface.ts
similarity index 100%
rename from packages/extension/src/background/interfaces.ts
rename to packages/extension/src/background/storage/interface.ts
diff --git a/packages/extension/src/background/wallet.ts b/packages/extension/src/background/wallet.ts
index ac03e06cc..8d78d084a 100644
--- a/packages/extension/src/background/wallet.ts
+++ b/packages/extension/src/background/wallet.ts
@@ -4,13 +4,13 @@ import { Signer, compileCalldata, ec } from "starknet"
import { getProvider } from "../shared/networks"
import { WalletAccount } from "../shared/wallet.model"
-import { IStorage } from "./interfaces"
import {
getNextPathIndex,
getPathForIndex,
getStarkPair,
} from "./keys/keyDerivation"
import backupSchema from "./schema/backup.schema.json"
+import { IStorage } from "./storage"
const isDev = process.env.NODE_ENV === "development"
const isTest = process.env.NODE_ENV === "test"
diff --git a/packages/extension/test/wallet.test.ts b/packages/extension/test/wallet.test.ts
index f8204fb96..ca7bea536 100644
--- a/packages/extension/test/wallet.test.ts
+++ b/packages/extension/test/wallet.test.ts
@@ -1,7 +1,7 @@
import fs from "fs"
import path from "path"
-import { IStorage } from "../src/background/interfaces"
+import { IStorage } from "../src/background/storage"
import {
SESSION_DURATION,
Wallet,
From ab120b8b28c8114386f9dffaec1e282500062ab1 Mon Sep 17 00:00:00 2001
From: Gerald
Date: Tue, 22 Feb 2022 08:55:33 +0100
Subject: [PATCH 09/86] add tests to ci
---
.github/workflows/test.yml | 30 ++++++++++++++++++++++++++++++
1 file changed, 30 insertions(+)
create mode 100644 .github/workflows/test.yml
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
new file mode 100644
index 000000000..6eaf621ff
--- /dev/null
+++ b/.github/workflows/test.yml
@@ -0,0 +1,30 @@
+name: Run Tests
+on:
+ push:
+ branches: [main]
+ pull_request:
+ branches: [main]
+
+jobs:
+ test:
+ runs-on: ubuntu-latest
+
+ services:
+ devnet:
+ image: shardlabs/starknet-devnet
+ ports:
+ - 5000:5000
+
+ steps:
+ - name: Check out repository code
+ uses: actions/checkout@v2
+
+ - uses: actions/setup-node@v2
+ with:
+ node-version: "14"
+
+ - name: Install dependencies
+ run: yarn install --frozen-lockfile
+
+ - name: Run tests
+ run: yarn --cwd packages/extension test
From 9578cd2fd8a6e5310c43c4a04c992ba11d410869 Mon Sep 17 00:00:00 2001
From: Gerald
Date: Tue, 22 Feb 2022 14:28:04 +0100
Subject: [PATCH 10/86] fixes
---
packages/extension/src/background/index.ts | 2 +-
.../src/background/keys/keyDerivation.ts | 10 ++---
.../src/background/schema/backup.schema.json | 4 +-
.../src/background/storage/default.ts | 2 +-
packages/extension/src/background/wallet.ts | 45 +++++++++----------
packages/extension/src/shared/wallet.model.ts | 2 +-
packages/extension/test/backup.mock.json | 2 +-
packages/extension/test/wallet.test.ts | 13 +++---
8 files changed, 37 insertions(+), 43 deletions(-)
diff --git a/packages/extension/src/background/index.ts b/packages/extension/src/background/index.ts
index f244bb5b0..6b3714ae4 100644
--- a/packages/extension/src/background/index.ts
+++ b/packages/extension/src/background/index.ts
@@ -31,7 +31,7 @@ import { addToWhitelist, isOnWhitelist } from "./whitelist"
;(async () => {
const { privateKey, publicKeyJwk } = await getKeyPair()
- const storage = new Storage({}, "WALLET")
+ const storage = new Storage({}, "wallet")
const wallet = new Wallet(storage, ArgentCompiledContract)
await wallet.setup()
diff --git a/packages/extension/src/background/keys/keyDerivation.ts b/packages/extension/src/background/keys/keyDerivation.ts
index 9507cc37a..1678e5493 100644
--- a/packages/extension/src/background/keys/keyDerivation.ts
+++ b/packages/extension/src/background/keys/keyDerivation.ts
@@ -17,8 +17,8 @@ export function getStarkPair(
const path =
typeof indexOrPath === "number" ? getPathForIndex(indexOrPath) : indexOrPath
const childNode = masterNode.derivePath(path)
- const grindedKey = grindKey(childNode.privateKey)
- const starkPair = ec.getKeyPair(grindedKey)
+ const groundKey = grindKey(childNode.privateKey)
+ const starkPair = ec.getKeyPair(groundKey)
return starkPair
}
@@ -43,13 +43,13 @@ export function getNextPathIndex(paths: string[]) {
}
export function grindKey(keySeed: string) {
- const keyValLimit = ec.ec.n
+ const keyValueLimit = ec.ec.n
const sha256EcMaxDigest = number.toBN(
"1 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000",
16,
)
const maxAllowedVal = sha256EcMaxDigest.sub(
- sha256EcMaxDigest.mod(keyValLimit),
+ sha256EcMaxDigest.mod(keyValueLimit),
)
// Make sure the produced key is devided by the Stark EC order,
@@ -61,7 +61,7 @@ export function grindKey(keySeed: string) {
i++
} while (!key.lt(maxAllowedVal))
- return "0x" + key.umod(keyValLimit).toString("hex")
+ return "0x" + key.umod(keyValueLimit).toString("hex")
}
function hashKeyWithIndex(key: string, index: number) {
diff --git a/packages/extension/src/background/schema/backup.schema.json b/packages/extension/src/background/schema/backup.schema.json
index ee4dcedad..12b86aa0f 100644
--- a/packages/extension/src/background/schema/backup.schema.json
+++ b/packages/extension/src/background/schema/backup.schema.json
@@ -56,9 +56,9 @@
"type": "object",
"properties": {
"type": { "type": "string" },
- "derivation_path": { "type": "string" }
+ "derivationPath": { "type": "string" }
},
- "required": ["type", "derivation_path"]
+ "required": ["type", "derivationPath"]
}
},
"required": ["address", "network", "signer"]
diff --git a/packages/extension/src/background/storage/default.ts b/packages/extension/src/background/storage/default.ts
index 6040e4484..1bc08ca1d 100644
--- a/packages/extension/src/background/storage/default.ts
+++ b/packages/extension/src/background/storage/default.ts
@@ -21,7 +21,7 @@ export function removeFromStorage(key: string) {
}
export function clearStorage() {
- return browser.storage.local.clear
+ return browser.storage.local.clear()
}
export class Storage implements IStorage {
diff --git a/packages/extension/src/background/wallet.ts b/packages/extension/src/background/wallet.ts
index 8d78d084a..30b560029 100644
--- a/packages/extension/src/background/wallet.ts
+++ b/packages/extension/src/background/wallet.ts
@@ -27,15 +27,15 @@ interface WalletSession {
}
export interface WalletStorageProps {
- BACKUP?: string
- SELECTED?: string
+ backup?: string
+ selected?: string
}
export class Wallet {
private accounts: WalletAccount[] = []
- private encryptedBackup: string | undefined
- private session: WalletSession | undefined
+ private encryptedBackup?: string
+ private session?: WalletSession
private store: IStorage
private compiledContract: string
@@ -57,20 +57,15 @@ export class Wallet {
return this.session !== undefined
}
- private async generateNewLocalSecret(
- password: string,
- progressFn?: (progress: number) => void,
- ) {
+ private async generateNewLocalSecret(password: string) {
if (this.isInitialized()) {
return
}
const N = isDevOrTest ? 64 : 32768
const ethersWallet = ethers.Wallet.createRandom()
- this.encryptedBackup = await ethersWallet.encrypt(
- password,
- { scrypt: { N } },
- progressFn,
- )
+ this.encryptedBackup = await ethersWallet.encrypt(password, {
+ scrypt: { N },
+ })
await this.writeBackup()
this.setSession(ethersWallet.privateKey, password)
@@ -109,12 +104,12 @@ export class Wallet {
const current_paths = this.accounts
.filter((account) => account.signer.type === "local_secret")
- .map((account) => account.signer.derivation_path)
+ .map((account) => account.signer.derivationPath)
const index = getNextPathIndex(current_paths)
const starkPair = getStarkPair(index, this.session?.secret as string)
const starkPub = ec.getStarkKey(starkPair)
- const seed = starkPub //ec.getStarkKey(ec.genKeyPair())
+ const seed = starkPub
const provider = getProvider(networkId)
const deployTransaction = await provider.deployContract(
@@ -137,7 +132,7 @@ export class Wallet {
address: deployTransaction.address,
signer: {
type: "local_secret",
- derivation_path: getPathForIndex(index),
+ derivationPath: getPathForIndex(index),
},
}
@@ -161,7 +156,7 @@ export class Wallet {
const account = await this.getSelectedAccount()
const keyPair = getStarkPair(
- account.signer.derivation_path,
+ account.signer.derivationPath,
this.session?.secret as string,
)
const provider = getProvider(account.network)
@@ -173,7 +168,7 @@ export class Wallet {
throw new Error("no accounts")
}
- const address = await this.store.getItem("SELECTED")
+ const address = await this.store.getItem("selected")
const account = this.accounts.find((account) => account.address === address)
return account ?? this.accounts[0]
}
@@ -183,7 +178,7 @@ export class Wallet {
if (account === undefined) {
return
}
- await this.store.setItem("SELECTED", account.address)
+ await this.store.setItem("selected", account.address)
}
public async removeAccount(address: string) {
@@ -204,15 +199,15 @@ export class Wallet {
if (!Wallet.validateBackup(backupString)) {
throw new Error("invalid backup file")
}
- await this.store.setItem("BACKUP", backupString)
+ await this.store.setItem("backup", backupString)
await this.setup()
}
public exportBackup(): { url: string; filename: string } {
- if (!this.isInitialized()) {
+ if (this.encryptedBackup === undefined) {
throw Error("no local backup")
}
- const blob = new Blob([this.encryptedBackup as string], {
+ const blob = new Blob([this.encryptedBackup], {
type: "application/json",
})
const url = URL.createObjectURL(blob)
@@ -224,7 +219,7 @@ export class Wallet {
try {
const backup = JSON.parse(backupString)
return ajv.validate(backupSchema, backup)
- } catch (error) {
+ } catch {
return false
}
}
@@ -238,7 +233,7 @@ export class Wallet {
}
private async readBackup() {
- this.encryptedBackup = await this.store.getItem("BACKUP")
+ this.encryptedBackup = await this.store.getItem("backup")
if (this.encryptedBackup === undefined) {
return
}
@@ -269,7 +264,7 @@ export class Wallet {
},
}
const backupString = JSON.stringify(extendedBackup)
- await this.store.setItem("BACKUP", backupString)
+ await this.store.setItem("backup", backupString)
this.encryptedBackup = backupString
}
}
diff --git a/packages/extension/src/shared/wallet.model.ts b/packages/extension/src/shared/wallet.model.ts
index 247f669f4..861559082 100644
--- a/packages/extension/src/shared/wallet.model.ts
+++ b/packages/extension/src/shared/wallet.model.ts
@@ -1,6 +1,6 @@
export interface WalletAccountSigner {
type: string
- derivation_path: string
+ derivationPath: string
}
export interface WalletAccount {
diff --git a/packages/extension/test/backup.mock.json b/packages/extension/test/backup.mock.json
index 288e4f782..b6b14ed58 100644
--- a/packages/extension/test/backup.mock.json
+++ b/packages/extension/test/backup.mock.json
@@ -33,7 +33,7 @@
"address": "0x06c67629cae87e7a1b284f1002747af681b39b8199f9263b9aed985e200d8f59",
"signer": {
"type": "local_secret",
- "derivation_path": "m/2645'/1195502025'/1148870696'/0'/0'/0"
+ "derivationPath": "m/2645'/1195502025'/1148870696'/0'/0'/0"
}
}
]
diff --git a/packages/extension/test/wallet.test.ts b/packages/extension/test/wallet.test.ts
index ca7bea536..0a9ba97a3 100644
--- a/packages/extension/test/wallet.test.ts
+++ b/packages/extension/test/wallet.test.ts
@@ -17,11 +17,10 @@ export class MockStorage implements IStorage {
public store: WalletStorageProps = {}
async getItem(key: keyof WalletStorageProps): Promise {
- return Promise.resolve(this.store[key] || undefined)
+ return Promise.resolve(this.store[key])
}
async setItem(key: keyof WalletStorageProps, value: string): Promise {
this.store[key] = value
- return Promise.resolve()
}
}
@@ -56,7 +55,7 @@ test("create a new wallet", async () => {
expect(wallet.isInitialized()).toBe(true)
expect(wallet.isSessionOpen()).toBe(true)
- const backupWithoutAccount = await storage.getItem("BACKUP")
+ const backupWithoutAccount = await storage.getItem("backup")
expect(backupWithoutAccount).toBeDefined()
expect(Wallet.validateBackup(backupWithoutAccount as string)).toBe(true)
@@ -66,7 +65,7 @@ test("create a new wallet", async () => {
const accounts = wallet.getAccounts()
expect(accounts).toHaveLength(1)
- const backupWithAccount = await storage.getItem("BACKUP")
+ const backupWithAccount = await storage.getItem("backup")
expect(backupWithAccount).toBeDefined()
expect(Wallet.validateBackup(backupWithAccount as string)).toBe(true)
@@ -81,7 +80,7 @@ test("open existing wallet", async () => {
jest.useFakeTimers()
const storage = new MockStorage()
- storage.setItem("BACKUP", backupString)
+ storage.setItem("backup", backupString)
const wallet = new Wallet(storage, compiledContract)
await wallet.setup()
@@ -98,7 +97,7 @@ test("open existing wallet", async () => {
"0x06c67629cae87e7a1b284f1002747af681b39b8199f9263b9aed985e200d8f59",
)
- const backupWithAccount = await storage.getItem("BACKUP")
+ const backupWithAccount = await storage.getItem("backup")
expect(backupWithAccount).toBeDefined()
expect(Wallet.validateBackup(backupWithAccount as string)).toBe(true)
@@ -114,7 +113,7 @@ test("open existing wallet", async () => {
test("open existing wallet with wrong password", async () => {
const storage = new MockStorage()
- storage.setItem("BACKUP", backupString)
+ storage.setItem("backup", backupString)
const wallet = new Wallet(storage, compiledContract)
await wallet.setup()
From e7ead733d85e6bb2f026c0d90f96b400b39b0e0b Mon Sep 17 00:00:00 2001
From: Gerald
Date: Tue, 22 Feb 2022 22:10:07 +0100
Subject: [PATCH 11/86] fix backup schema validation
---
packages/extension/package.json | 2 +-
packages/extension/src/background/index.ts | 2 -
.../src/background/schema/backup.schema.json | 72 -------------------
.../src/background/schema/backup.schema.ts | 49 +++++++++++++
packages/extension/src/background/wallet.ts | 15 ++--
packages/extension/test/backup.mock.json | 4 +-
packages/extension/test/wallet.test.ts | 10 +++
yarn.lock | 69 ++++++++++++------
8 files changed, 114 insertions(+), 109 deletions(-)
delete mode 100644 packages/extension/src/background/schema/backup.schema.json
create mode 100644 packages/extension/src/background/schema/backup.schema.ts
diff --git a/packages/extension/package.json b/packages/extension/package.json
index c8964e36d..81266c23c 100644
--- a/packages/extension/package.json
+++ b/packages/extension/package.json
@@ -44,7 +44,6 @@
"@mui/material": "^5.1.0",
"@mui/styled-engine-sc": "^5.1.0",
"@tippyjs/react": "^4.2.6",
- "ajv": "^8.10.0",
"ethers": "^5.5.1",
"jose": "^4.3.6",
"object-hash": "^3.0.0",
@@ -60,6 +59,7 @@
"styled-normalize": "^8.0.7",
"swr": "^1.1.0",
"webextension-polyfill": "^0.8.0",
+ "yup": "^0.32.11",
"zustand": "^3.6.5"
}
}
diff --git a/packages/extension/src/background/index.ts b/packages/extension/src/background/index.ts
index 6b3714ae4..0092e8d32 100644
--- a/packages/extension/src/background/index.ts
+++ b/packages/extension/src/background/index.ts
@@ -397,8 +397,6 @@ import { addToWhitelist, isOnWhitelist } from "./whitelist"
title: "Deploy wallet",
})
- await downloadFile(wallet.exportBackup())
-
return sendToTabAndUi({
type: "NEW_ACCOUNT_RES",
data: {
diff --git a/packages/extension/src/background/schema/backup.schema.json b/packages/extension/src/background/schema/backup.schema.json
deleted file mode 100644
index 12b86aa0f..000000000
--- a/packages/extension/src/background/schema/backup.schema.json
+++ /dev/null
@@ -1,72 +0,0 @@
-{
- "$id": "ArgentXBackupSchema",
- "title": "Argent X Backup file",
- "description": "Argent X Backup file",
- "type": "object",
- "properties": {
- "x-version": { "type": "integer", "minimum": 1, "maximum": 1 },
- "address": { "type": "string" },
- "version": { "type": "integer" },
- "Crypto": {
- "type": "object",
- "properties": {
- "cipher": { "type": "string" },
- "ciphertext": { "type": "string" },
- "kdf": { "type": "string" },
- "mac": { "type": "string" },
- "cipherparams": {
- "type": "object",
- "properties": {
- "iv": { "type": "string" }
- },
- "required": ["iv"]
- },
- "kdfparams": {
- "type": "object",
- "properties": {
- "salt": { "type": "string" },
- "n": { "type": "number" },
- "dklen": { "type": "number" },
- "p": { "type": "number" },
- "r": { "type": "number" }
- },
- "required": ["salt", "n", "dklen", "p", "r"]
- }
- },
- "required": [
- "cipher",
- "ciphertext",
- "kdf",
- "mac",
- "cipherparams",
- "kdfparams"
- ]
- },
- "x-argent": {
- "type": "object",
- "properties": {
- "accounts": {
- "type": "array",
- "items": {
- "type": "object",
- "properties": {
- "address": { "type": "string" },
- "network": { "type": "string" },
- "signer": {
- "type": "object",
- "properties": {
- "type": { "type": "string" },
- "derivationPath": { "type": "string" }
- },
- "required": ["type", "derivationPath"]
- }
- },
- "required": ["address", "network", "signer"]
- }
- }
- },
- "required": ["accounts"]
- }
- },
- "required": ["x-version", "Crypto", "x-argent", "address", "version"]
-}
diff --git a/packages/extension/src/background/schema/backup.schema.ts b/packages/extension/src/background/schema/backup.schema.ts
new file mode 100644
index 000000000..2e0cc3aa0
--- /dev/null
+++ b/packages/extension/src/background/schema/backup.schema.ts
@@ -0,0 +1,49 @@
+import { array, number, object, string } from "yup"
+
+export default object({
+ // standard keystore file
+ address: string().required(),
+ version: number().integer().required(),
+ Crypto: object()
+ .required()
+ .shape({
+ cipher: string().required(),
+ ciphertext: string().required(),
+ kdf: string().required(),
+ mac: string().required(),
+ cipherparams: object().required().shape({
+ iv: string().required(),
+ }),
+ kdfparams: object().required().shape({
+ salt: string().required(),
+ n: number().required(),
+ dklen: number().required(),
+ p: number().required(),
+ r: number().required(),
+ }),
+ }),
+ // ethers.js additions
+ "x-ethers": object().required().shape({
+ mnemonicCounter: string().required(),
+ mnemonicCiphertext: string().required(),
+ path: string().required(),
+ }),
+ // argent additions
+ argent: object()
+ .required()
+ .shape({
+ version: number().integer().min(1).max(1).required(),
+ accounts: array().of(
+ object()
+ .optional()
+ .shape({
+ address: string().required(),
+ network: string().required(),
+ signer: object().required().shape({
+ type: string().required(),
+ derivationPath: string().required(),
+ }),
+ }),
+ ),
+ }),
+})
diff --git a/packages/extension/src/background/wallet.ts b/packages/extension/src/background/wallet.ts
index 30b560029..7ffec58db 100644
--- a/packages/extension/src/background/wallet.ts
+++ b/packages/extension/src/background/wallet.ts
@@ -1,4 +1,3 @@
-import Ajv from "ajv"
import { ethers } from "ethers"
import { Signer, compileCalldata, ec } from "starknet"
@@ -9,7 +8,7 @@ import {
getPathForIndex,
getStarkPair,
} from "./keys/keyDerivation"
-import backupSchema from "./schema/backup.schema.json"
+import backupSchema from "./schema/backup.schema"
import { IStorage } from "./storage"
const isDev = process.env.NODE_ENV === "development"
@@ -19,8 +18,6 @@ const isDevOrTest = isDev || isTest
const CURRENT_BACKUP_VERSION = 1
export const SESSION_DURATION = 15 * 60 * 60 * 1000 // 15 hours
-const ajv = new Ajv()
-
interface WalletSession {
secret: string
password: string
@@ -218,7 +215,7 @@ export class Wallet {
public static validateBackup(backupString: string): boolean {
try {
const backup = JSON.parse(backupString)
- return ajv.validate(backupSchema, backup)
+ return backupSchema.isValidSync(backup)
} catch {
return false
}
@@ -244,11 +241,11 @@ export class Wallet {
}
const backup = JSON.parse(this.encryptedBackup)
- if (backup["x-version"] !== CURRENT_BACKUP_VERSION) {
+ if (backup.argent.version !== CURRENT_BACKUP_VERSION) {
// in the future, backup file migration will happen here
}
- this.accounts = backup["x-argent"].accounts
+ this.accounts = backup.argent.accounts
}
private async writeBackup() {
@@ -258,8 +255,8 @@ export class Wallet {
const backup = JSON.parse(this.encryptedBackup)
const extendedBackup = {
...backup,
- "x-version": CURRENT_BACKUP_VERSION,
- "x-argent": {
+ argent: {
+ version: CURRENT_BACKUP_VERSION,
accounts: this.accounts,
},
}
diff --git a/packages/extension/test/backup.mock.json b/packages/extension/test/backup.mock.json
index b6b14ed58..4861618ee 100644
--- a/packages/extension/test/backup.mock.json
+++ b/packages/extension/test/backup.mock.json
@@ -25,8 +25,8 @@
"locale": "en",
"version": "0.1"
},
- "x-version": 1,
- "x-argent": {
+ "argent": {
+ "version": 1,
"accounts": [
{
"network": "http://localhost:5000",
diff --git a/packages/extension/test/wallet.test.ts b/packages/extension/test/wallet.test.ts
index 0a9ba97a3..65be30f10 100644
--- a/packages/extension/test/wallet.test.ts
+++ b/packages/extension/test/wallet.test.ts
@@ -158,3 +158,13 @@ test("import wrong backup file", async () => {
expect(wallet.isInitialized()).toBe(false)
})
+
+test("schema validation should succeed", async () => {
+ const isValid = Wallet.validateBackup(backupString)
+ expect(isValid).toBe(true)
+})
+
+test("schema validation should fail", async () => {
+ const isValid = Wallet.validateBackup(backupWrongString)
+ expect(isValid).toBe(false)
+})
diff --git a/yarn.lock b/yarn.lock
index 03e100a72..18391813e 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1107,7 +1107,7 @@
core-js-pure "^3.19.0"
regenerator-runtime "^0.13.4"
-"@babel/runtime@^7.10.2", "@babel/runtime@^7.16.3", "@babel/runtime@^7.17.0", "@babel/runtime@^7.5.5", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7":
+"@babel/runtime@^7.10.2", "@babel/runtime@^7.15.4", "@babel/runtime@^7.16.3", "@babel/runtime@^7.17.0", "@babel/runtime@^7.5.5", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7":
version "7.17.2"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.17.2.tgz#66f68591605e59da47523c631416b18508779941"
integrity sha512-hzeyJyMA1YGdJTuWU0e/j4wKXrU4OMFvY2MSlaI9B7VQb0r5cxTE3EAIS2Q7Tn2RIcDkRvTA/v2JsAEhxe99uw==
@@ -3213,6 +3213,11 @@
resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee"
integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4=
+"@types/lodash@^4.14.175":
+ version "4.14.178"
+ resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.178.tgz#341f6d2247db528d4a13ddbb374bcdc80406f4f8"
+ integrity sha512-0d5Wd09ItQWH1qFbEyQ7oTQ3GZrMfth5JkbN3EvTKLXcHLRDSXeLnlvlOn0wvxVIwK5o2M8JzP/OWz7T3NRsbw==
+
"@types/minimatch@^3.0.3":
version "3.0.5"
resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.5.tgz#1001cc5e6a3704b83c236027e77f2f58ea010f40"
@@ -3228,6 +3233,11 @@
resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.18.tgz#3b4fed5cfb58010e3a2be4b6e74615e4847f1074"
integrity sha512-eKj4f/BsN/qcculZiRSujogjvp5O/k4lOW5m35NopjZM/QwLOR075a8pJW5hD+Rtdm2DaCVPENS6KtSQnUD6BA==
+"@types/node@17.0.18":
+ version "17.0.18"
+ resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.18.tgz#3b4fed5cfb58010e3a2be4b6e74615e4847f1074"
+ integrity sha512-eKj4f/BsN/qcculZiRSujogjvp5O/k4lOW5m35NopjZM/QwLOR075a8pJW5hD+Rtdm2DaCVPENS6KtSQnUD6BA==
+
"@types/node@^13.9.0":
version "13.13.52"
resolved "https://registry.yarnpkg.com/@types/node/-/node-13.13.52.tgz#03c13be70b9031baaed79481c0c0cfb0045e53f7"
@@ -3702,16 +3712,6 @@ ajv@^8.0.0, ajv@^8.8.0:
require-from-string "^2.0.2"
uri-js "^4.2.2"
-ajv@^8.10.0, ajv@^8.8.2:
- version "8.10.0"
- resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.10.0.tgz#e573f719bd3af069017e3b66538ab968d040e54d"
- integrity sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw==
- dependencies:
- fast-deep-equal "^3.1.1"
- json-schema-traverse "^1.0.0"
- require-from-string "^2.0.2"
- uri-js "^4.2.2"
-
ansi-escapes@^4.2.1:
version "4.3.2"
resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e"
@@ -4263,7 +4263,7 @@ chalk@^2.0.0:
escape-string-regexp "^1.0.5"
supports-color "^5.3.0"
-chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.2:
+chalk@^4.0.0, chalk@^4.1.0:
version "4.1.2"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
@@ -6786,16 +6786,6 @@ jest-jasmine2@^27.5.1:
pretty-format "^27.5.1"
throat "^6.0.1"
-jest-json-schema@^6.1.0:
- version "6.1.0"
- resolved "https://registry.yarnpkg.com/jest-json-schema/-/jest-json-schema-6.1.0.tgz#68ccc23424a7b20550d59ab9186530f81113e6af"
- integrity sha512-LMHuLmKjr/4X+H8v1xF5TEwfYEkzwGeWJ0epYQVQhlVTDDR5FWCdSO8vmsecb5cLf9NeWAqMKn3qhJvP9um0AA==
- dependencies:
- ajv "^8.8.2"
- ajv-formats "^2.1.1"
- chalk "^4.1.2"
- jest-matcher-utils "^27.3.1"
-
jest-leak-detector@^27.5.1:
version "27.5.1"
resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-27.5.1.tgz#6ec9d54c3579dd6e3e66d70e3498adf80fde3fb8"
@@ -6804,7 +6794,7 @@ jest-leak-detector@^27.5.1:
jest-get-type "^27.5.1"
pretty-format "^27.5.1"
-jest-matcher-utils@^27.3.1, jest-matcher-utils@^27.5.1:
+jest-matcher-utils@^27.5.1:
version "27.5.1"
resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz#9c0cdbda8245bc22d2331729d1091308b40cf8ab"
integrity sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw==
@@ -7353,6 +7343,11 @@ locate-path@^5.0.0:
dependencies:
p-locate "^4.1.0"
+lodash-es@^4.17.21:
+ version "4.17.21"
+ resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee"
+ integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==
+
lodash._reinterpolate@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d"
@@ -7743,6 +7738,11 @@ mute-stream@0.0.8, mute-stream@~0.0.4:
resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d"
integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==
+nanoclone@^0.2.1:
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/nanoclone/-/nanoclone-0.2.1.tgz#dd4090f8f1a110d26bb32c49ed2f5b9235209ed4"
+ integrity sha512-wynEP02LmIbLpcYw8uBKpcfF6dmg2vcpKqxeH5UcoKEYdExslsdUA4ugFauuaeYdTB76ez6gJW8XAZ6CgkXYxA==
+
nanoid@^3.1.30:
version "3.2.0"
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.2.0.tgz#62667522da6673971cca916a6d3eff3f415ff80c"
@@ -8528,6 +8528,11 @@ prop-types@^15.5.8, prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1:
object-assign "^4.1.1"
react-is "^16.13.1"
+property-expr@^2.0.4:
+ version "2.0.5"
+ resolved "https://registry.yarnpkg.com/property-expr/-/property-expr-2.0.5.tgz#278bdb15308ae16af3e3b9640024524f4dc02cb4"
+ integrity sha512-IJUkICM5dP5znhCckHSv30Q4b5/JA5enCtkRHYaOVOAocnH/1BQEYTC5NMfT3AVl/iXKdr3aqQbQn9DxyWknwA==
+
proto-list@~1.2.1:
version "1.2.4"
resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849"
@@ -9851,6 +9856,11 @@ toggle-selection@^1.0.6:
resolved "https://registry.yarnpkg.com/toggle-selection/-/toggle-selection-1.0.6.tgz#6e45b1263f2017fa0acc7d89d78b15b8bf77da32"
integrity sha1-bkWxJj8gF/oKzH2J14sVuL932jI=
+toposort@^2.0.2:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/toposort/-/toposort-2.0.2.tgz#ae21768175d1559d48bef35420b2f4962f09c330"
+ integrity sha1-riF2gXXRVZ1IvvNUILL0li8JwzA=
+
tough-cookie@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.0.0.tgz#d822234eeca882f991f0f908824ad2622ddbece4"
@@ -10521,6 +10531,19 @@ yargs@^16.2.0:
y18n "^5.0.5"
yargs-parser "^20.2.2"
+yup@^0.32.11:
+ version "0.32.11"
+ resolved "https://registry.yarnpkg.com/yup/-/yup-0.32.11.tgz#d67fb83eefa4698607982e63f7ca4c5ed3cf18c5"
+ integrity sha512-Z2Fe1bn+eLstG8DRR6FTavGD+MeAwyfmouhHsIUgaADz8jvFKbO/fXc2trJKZg+5EBjh4gGm3iU/t3onKlXHIg==
+ dependencies:
+ "@babel/runtime" "^7.15.4"
+ "@types/lodash" "^4.14.175"
+ lodash "^4.17.21"
+ lodash-es "^4.17.21"
+ nanoclone "^0.2.1"
+ property-expr "^2.0.4"
+ toposort "^2.0.2"
+
zustand@^3.6.5:
version "3.7.0"
resolved "https://registry.yarnpkg.com/zustand/-/zustand-3.7.0.tgz#a5c68fb06bdee9c63ad829de2432635be6d0ce69"
From a55bd31ab6848cb2f50c94b37dabcf371b8167fe Mon Sep 17 00:00:00 2001
From: Axel Delamarre <1091900+delaaxe@users.noreply.github.com>
Date: Thu, 24 Feb 2022 14:47:08 +0000
Subject: [PATCH 12/86] refactor(background): rename wallet to account
---
packages/extension/src/background/index.ts | 48 +++++++++----------
.../src/background/trackTransactions.ts | 22 ++++-----
packages/extension/src/inpage/index.ts | 2 +-
packages/extension/src/shared/MessageType.ts | 14 +++---
packages/extension/src/shared/networks.ts | 7 ++-
.../src/shared/transactions.model.ts | 2 +-
packages/extension/src/ui/Account.ts | 2 +-
.../src/ui/states/accountTransactions.ts | 2 +-
packages/extension/src/ui/utils/accounts.ts | 2 +-
packages/extension/src/ui/utils/messaging.ts | 19 ++++----
packages/extension/src/ui/utils/recovery.ts | 8 ++--
11 files changed, 67 insertions(+), 61 deletions(-)
diff --git a/packages/extension/src/background/index.ts b/packages/extension/src/background/index.ts
index 0092e8d32..52ab65d70 100644
--- a/packages/extension/src/background/index.ts
+++ b/packages/extension/src/background/index.ts
@@ -42,28 +42,28 @@ import { addToWhitelist, isOnWhitelist } from "./whitelist"
data: transactions,
})
- for (const { hash, status, walletAddress, meta } of transactions) {
+ for (const { hash, status, accountAddress, meta } of transactions) {
if (
(status === "ACCEPTED_ON_L2" || status === "REJECTED") &&
!(await hasShownNotification(hash))
) {
addToAlreadyShown(hash)
sentTransactionNotification(hash, status, meta)
- if (walletAddress && status === "ACCEPTED_ON_L2") {
+ if (accountAddress && status === "ACCEPTED_ON_L2") {
sendMessageToUi({
type: "TRANSACTION_SUCCESS",
data: {
hash,
status,
- walletAddress,
+ accountAddress,
meta,
},
})
}
}
// on error remove stored (increased) nonce
- if (walletAddress && status === "REJECTED") {
- resetStoredNonce(walletAddress)
+ if (accountAddress && status === "REJECTED") {
+ resetStoredNonce(accountAddress)
}
}
}
@@ -142,17 +142,17 @@ import { addToWhitelist, isOnWhitelist } from "./whitelist"
})
}
- case "GET_SELECTED_WALLET": {
- const selectedWallet = await wallet.getSelectedAccount()
+ case "GET_SELECTED_ACCOUNT": {
+ const selectedAccount = await wallet.getSelectedAccount()
return sendToTabAndUi({
- type: "GET_SELECTED_WALLET_RES",
- data: selectedWallet,
+ type: "GET_SELECTED_ACCOUNT_RES",
+ data: selectedAccount,
})
}
case "CONNECT": {
- const selectedWallet = await wallet.getSelectedAccount()
+ const selectedAccount = await wallet.getSelectedAccount()
const isWhitelisted = await isOnWhitelist(msg.data.host)
addTab(sender.tab?.id)
@@ -164,14 +164,14 @@ import { addToWhitelist, isOnWhitelist } from "./whitelist"
})
}
- if (isWhitelisted && selectedWallet.address) {
- return sendToTabAndUi({ type: "CONNECT_RES", data: selectedWallet })
+ if (isWhitelisted && selectedAccount.address) {
+ return sendToTabAndUi({ type: "CONNECT_RES", data: selectedAccount })
}
return openUi()
}
- case "WALLET_CONNECTED": {
+ case "CONNECT_ACCOUNT": {
return await wallet.selectAccount(msg.data.address)
}
@@ -184,14 +184,14 @@ import { addToWhitelist, isOnWhitelist } from "./whitelist"
switch (action.type) {
case "CONNECT": {
const { host } = action.payload
- const selectedWallet = await wallet.getSelectedAccount()
+ const selectedAccount = await wallet.getSelectedAccount()
await addToWhitelist(host)
- if (selectedWallet) {
+ if (selectedAccount) {
return sendToTabAndUi({
type: "CONNECT_RES",
- data: selectedWallet,
+ data: selectedAccount,
})
}
return openUi()
@@ -202,7 +202,7 @@ import { addToWhitelist, isOnWhitelist } from "./whitelist"
if (!wallet.isSessionOpen()) {
throw Error("you need an open session")
}
- const selectedWallet = await wallet.getSelectedAccount()
+ const selectedAccount = await wallet.getSelectedAccount()
const signer = await wallet.getSelectedAccountSigner()
try {
@@ -213,7 +213,7 @@ import { addToWhitelist, isOnWhitelist } from "./whitelist"
increaseStoredNonce(signer.address)
transactionTracker.trackTransaction(
tx.transaction_hash,
- selectedWallet,
+ selectedAccount,
)
return sendToTabAndUi({
@@ -376,13 +376,13 @@ import { addToWhitelist, isOnWhitelist } from "./whitelist"
case "IS_INITIALIZED": {
return sendToTabAndUi({
type: "IS_INITIALIZED_RES",
- data: await wallet.isInitialized(),
+ data: wallet.isInitialized(),
})
}
- case "GET_WALLETS": {
+ case "GET_ACCOUNTS": {
return sendToTabAndUi({
- type: "GET_WALLETS_RES",
- data: await wallet.getAccounts(),
+ type: "GET_ACCOUNTS_RES",
+ data: wallet.getAccounts(),
})
}
case "NEW_ACCOUNT": {
@@ -403,8 +403,8 @@ import { addToWhitelist, isOnWhitelist } from "./whitelist"
status: "ok",
txHash,
address: account.address,
- wallet: account,
- wallets: wallet.getAccounts(),
+ account: account,
+ accounts: wallet.getAccounts(),
},
})
} catch (e: any) {
diff --git a/packages/extension/src/background/trackTransactions.ts b/packages/extension/src/background/trackTransactions.ts
index 3aba9be9b..0c9fe3a48 100644
--- a/packages/extension/src/background/trackTransactions.ts
+++ b/packages/extension/src/background/trackTransactions.ts
@@ -13,7 +13,7 @@ interface TransactionStatusWithProvider extends TransactionStatus {
type FetchedTransactionStatus = Omit<
TransactionStatus,
- "walletAddress" | "meta"
+ "accountAddress" | "meta"
>
type Listener = (transactions: TransactionStatus[]) => void
@@ -38,17 +38,17 @@ export class TransactionTracker {
public async trackTransaction(
transactionHash: string,
- wallet: WalletAccount,
+ account: WalletAccount,
meta: TransactionMeta = {
title: "Contract interaction",
},
): Promise {
try {
- const provider = getProvider(wallet.network)
+ const provider = getProvider(account.network)
this.transactions.push({
hash: transactionHash,
provider,
- walletAddress: wallet.address,
+ accountAddress: account.address,
status: "RECEIVED",
meta,
})
@@ -61,15 +61,15 @@ export class TransactionTracker {
}
}
- public getAllTransactions(byWalletAddress?: string): TransactionStatus[] {
+ public getAllTransactions(byAccountAddress?: string): TransactionStatus[] {
return this.transactions
.filter(
(transaction) =>
- !byWalletAddress || transaction.walletAddress === byWalletAddress,
+ !byAccountAddress || transaction.accountAddress === byAccountAddress,
)
- .map(({ hash, walletAddress, meta }) => ({
+ .map(({ hash, accountAddress, meta }) => ({
hash,
- walletAddress,
+ accountAddress,
status: this.getTransactionStatus(hash)?.status || "NOT_RECEIVED",
meta,
}))
@@ -82,21 +82,21 @@ export class TransactionTracker {
private async checkTransactions(): Promise {
const transactionStatuses = await Promise.all(
this.transactions.map(
- async ({ hash, provider, walletAddress, meta, status }) => {
+ async ({ hash, provider, accountAddress, meta, status }) => {
// TODO: We dont need to check for ACCEPTED_ON_L1 currently, as we just handle ACCEPTED_ON_L2 anyways. This may changes in the future.
// if (status === "ACCEPTED_ON_L1" || status === "REJECTED") {
if (status === "ACCEPTED_ON_L2" || status === "REJECTED") {
return Promise.resolve({
hash,
provider,
- walletAddress,
+ accountAddress,
meta,
status,
})
}
return getTransactionStatus(provider, hash).then((status) => ({
...status,
- walletAddress,
+ accountAddress,
provider,
meta,
}))
diff --git a/packages/extension/src/inpage/index.ts b/packages/extension/src/inpage/index.ts
index c373ddde1..059caf684 100644
--- a/packages/extension/src/inpage/index.ts
+++ b/packages/extension/src/inpage/index.ts
@@ -150,7 +150,7 @@ window.addEventListener(
"message",
({ data }: MessageEvent) => {
const { starknet } = window
- if (starknet && starknet.signer && data.type === "WALLET_CONNECTED") {
+ if (starknet && starknet.signer && data.type === "CONNECT_ACCOUNT") {
const { address, network } = data.data
if (address !== starknet.selectedAddress) {
starknet.selectedAddress = address
diff --git a/packages/extension/src/shared/MessageType.ts b/packages/extension/src/shared/MessageType.ts
index a85f6a651..4c3ccc01e 100644
--- a/packages/extension/src/shared/MessageType.ts
+++ b/packages/extension/src/shared/MessageType.ts
@@ -19,8 +19,8 @@ export type MessageType =
type: "GET_ACTIONS_RES"
data: ExtActionItem[]
}
- | { type: "GET_SELECTED_WALLET" }
- | { type: "GET_SELECTED_WALLET_RES"; data: WalletAccount }
+ | { type: "GET_SELECTED_ACCOUNT" }
+ | { type: "GET_SELECTED_ACCOUNT_RES"; data: WalletAccount }
| { type: "CONNECT"; data: { host: string } }
| { type: "CONNECT_RES"; data: WalletAccount }
| {
@@ -47,7 +47,7 @@ export type MessageType =
| { type: "IS_WHITELIST"; data: string }
| { type: "IS_WHITELIST_RES"; data: boolean }
| { type: "RESET_WHITELIST" }
- | { type: "WALLET_CONNECTED"; data: WalletAccount }
+ | { type: "CONNECT_ACCOUNT"; data: WalletAccount }
| { type: "RESET_ALL" }
| { type: "REQ_PUB" }
| { type: "REQ_PUB_RES"; data: JWK }
@@ -59,8 +59,8 @@ export type MessageType =
status: "ok"
txHash: string
address: string
- wallet: WalletAccount
- wallets: WalletAccount[]
+ account: WalletAccount
+ accounts: WalletAccount[]
}
}
| { type: "NEW_ACCOUNT_REJ"; data: { status: "ko"; error: string } }
@@ -69,8 +69,8 @@ export type MessageType =
| { type: "HAS_SESSION_RES"; data: boolean }
| { type: "IS_INITIALIZED" }
| { type: "IS_INITIALIZED_RES"; data: boolean }
- | { type: "GET_WALLETS" }
- | { type: "GET_WALLETS_RES"; data: WalletAccount[] }
+ | { type: "GET_ACCOUNTS" }
+ | { type: "GET_ACCOUNTS_RES"; data: WalletAccount[] }
| { type: "START_SESSION"; data: { secure: true; body: string } }
| { type: "START_SESSION_REJ" }
| { type: "START_SESSION_RES" }
diff --git a/packages/extension/src/shared/networks.ts b/packages/extension/src/shared/networks.ts
index 866cf071d..2d214cfc7 100644
--- a/packages/extension/src/shared/networks.ts
+++ b/packages/extension/src/shared/networks.ts
@@ -33,8 +33,11 @@ export const getNetwork = (networkId: string): Network => {
return networks.find(({ id }) => id === networkId) || defaultNetwork
}
-export const networkWallets = (wallets: WalletAccount[], networkId: string) =>
- wallets.filter(
+export const accountsOnNetwork = (
+ accounts: WalletAccount[],
+ networkId: string,
+) =>
+ accounts.filter(
({ network }) => localNetworkId(network) === localNetworkId(networkId),
)
diff --git a/packages/extension/src/shared/transactions.model.ts b/packages/extension/src/shared/transactions.model.ts
index cc84872b3..fef3633fe 100644
--- a/packages/extension/src/shared/transactions.model.ts
+++ b/packages/extension/src/shared/transactions.model.ts
@@ -6,7 +6,7 @@ export interface TransactionMeta {
export interface TransactionStatus {
hash: string
- walletAddress?: string
+ accountAddress?: string
status: Status
meta?: TransactionMeta
}
diff --git a/packages/extension/src/ui/Account.ts b/packages/extension/src/ui/Account.ts
index a224407c7..c5af7679b 100644
--- a/packages/extension/src/ui/Account.ts
+++ b/packages/extension/src/ui/Account.ts
@@ -65,7 +65,7 @@ export class Account {
return new Account(
result.address,
networkId,
- result.wallet.signer,
+ result.account.signer,
result.txHash,
)
}
diff --git a/packages/extension/src/ui/states/accountTransactions.ts b/packages/extension/src/ui/states/accountTransactions.ts
index b8a9e42d3..f2fac8541 100644
--- a/packages/extension/src/ui/states/accountTransactions.ts
+++ b/packages/extension/src/ui/states/accountTransactions.ts
@@ -23,7 +23,7 @@ export const useAccountTransactions = (accountAddress: string) => {
if (message.type === "TRANSACTION_UPDATES") {
useTransactionsStore.setState({
transactions: message.data.filter(
- ({ walletAddress: wa }) => wa === accountAddress,
+ ({ accountAddress: wa }) => wa === accountAddress,
),
})
}
diff --git a/packages/extension/src/ui/utils/accounts.ts b/packages/extension/src/ui/utils/accounts.ts
index 75896c66b..9968b1db3 100644
--- a/packages/extension/src/ui/utils/accounts.ts
+++ b/packages/extension/src/ui/utils/accounts.ts
@@ -35,7 +35,7 @@ export const connectAccount = async (
localhostPort: number,
) => {
sendMessage({
- type: "WALLET_CONNECTED",
+ type: "CONNECT_ACCOUNT",
data: {
address: account.address,
network: localNetworkUrl(switcherNetworkId, localhostPort),
diff --git a/packages/extension/src/ui/utils/messaging.ts b/packages/extension/src/ui/utils/messaging.ts
index f92a81889..0ef6d3d2e 100644
--- a/packages/extension/src/ui/utils/messaging.ts
+++ b/packages/extension/src/ui/utils/messaging.ts
@@ -22,18 +22,21 @@ export const getTransactions = async (address: string) => {
sendMessage({ type: "GET_TRANSACTIONS" })
const allTransactions = await waitForMessage("GET_TRANSACTIONS_RES")
return allTransactions.filter(
- ({ walletAddress }) => walletAddress === address,
+ ({ accountAddress }) => accountAddress === address,
)
}
export const getTransactionStatus = async (hash: string, network: string) => {
sendMessage({ type: "GET_TRANSACTION", data: { hash, network } })
- return waitForMessage("GET_TRANSACTION_RES", (x) => x.data.hash === hash)
+ return waitForMessage(
+ "GET_TRANSACTION_RES",
+ (status) => status.data.hash === hash,
+ )
}
-export const getLastSelectedWallet = async () => {
- sendMessage({ type: "GET_SELECTED_WALLET" })
- return waitForMessage("GET_SELECTED_WALLET_RES")
+export const getLastSelectedAccount = async () => {
+ sendMessage({ type: "GET_SELECTED_ACCOUNT" })
+ return waitForMessage("GET_SELECTED_ACCOUNT_RES")
}
export const getPublicKey = async () => {
@@ -59,9 +62,9 @@ export const hasActiveSession = async () => {
return waitForMessage("HAS_SESSION_RES")
}
-export const getWallets = async () => {
- sendMessage({ type: "GET_WALLETS" })
- return waitForMessage("GET_WALLETS_RES")
+export const getAccounts = async () => {
+ sendMessage({ type: "GET_ACCOUNTS" })
+ return waitForMessage("GET_ACCOUNTS_RES")
}
export const startSession = async (password: string): Promise => {
diff --git a/packages/extension/src/ui/utils/recovery.ts b/packages/extension/src/ui/utils/recovery.ts
index ebf6084ae..923f1ae56 100644
--- a/packages/extension/src/ui/utils/recovery.ts
+++ b/packages/extension/src/ui/utils/recovery.ts
@@ -1,14 +1,14 @@
import {
+ accountsOnNetwork,
defaultNetwork,
localNetworkId,
- networkWallets,
} from "../../shared/networks"
import { Account } from "../Account"
import { routes } from "../routes"
import { useAccount } from "../states/account"
import { setDefaultAccountNames } from "../states/accountMetadata"
import { useAppState } from "../states/app"
-import { getLastSelectedWallet, getWallets } from "./messaging"
+import { getAccounts, getLastSelectedAccount } from "./messaging"
interface RecoveryOptions {
networkId?: string
@@ -20,12 +20,12 @@ export const recover = async ({
showAccountList,
}: RecoveryOptions = {}) => {
try {
- const lastSelectedAccount = await getLastSelectedWallet().catch(() => null)
+ const lastSelectedAccount = await getLastSelectedAccount().catch(() => null)
networkId ||= lastSelectedAccount
? localNetworkId(lastSelectedAccount?.network)
: defaultNetwork.id
- const walletAccounts = networkWallets(await getWallets(), networkId)
+ const walletAccounts = accountsOnNetwork(await getAccounts(), networkId)
const selectedAccount = walletAccounts.find(
({ address }) => address === lastSelectedAccount?.address,
From ce876d3ccf379dbbe83163715cdaa4ea57a639ba Mon Sep 17 00:00:00 2001
From: Gerald
Date: Thu, 24 Feb 2022 16:26:10 +0100
Subject: [PATCH 13/86] show a screen for users with legacy accounts in their
local storage
---
packages/extension/src/background/index.ts | 10 +++-
packages/extension/src/background/legacy.ts | 18 ++++++
.../src/background/storage/default.ts | 4 ++
packages/extension/src/shared/MessageType.ts | 7 ++-
packages/extension/src/ui/App.tsx | 2 +
packages/extension/src/ui/hooks/useEntry.tsx | 5 +-
packages/extension/src/ui/routes.ts | 1 +
.../extension/src/ui/screens/LegacyScreen.tsx | 59 +++++++++++++++++++
8 files changed, 103 insertions(+), 3 deletions(-)
create mode 100644 packages/extension/src/background/legacy.ts
create mode 100644 packages/extension/src/ui/screens/LegacyScreen.tsx
diff --git a/packages/extension/src/background/index.ts b/packages/extension/src/background/index.ts
index 0092e8d32..935a7c998 100644
--- a/packages/extension/src/background/index.ts
+++ b/packages/extension/src/background/index.ts
@@ -16,6 +16,7 @@ import {
} from "./activeTabs"
import { downloadFile } from "./download"
import { getKeyPair } from "./keys/communication"
+import { exportLegacyBackup, hasLegacy } from "./legacy"
import { getNonce, increaseStoredNonce, resetStoredNonce } from "./nonce"
import {
addToAlreadyShown,
@@ -374,9 +375,11 @@ import { addToWhitelist, isOnWhitelist } from "./whitelist"
return wallet.lock()
}
case "IS_INITIALIZED": {
+ const initialized = await wallet.isInitialized()
+ const legacy = initialized ? false : await hasLegacy()
return sendToTabAndUi({
type: "IS_INITIALIZED_RES",
- data: await wallet.isInitialized(),
+ data: { initialized, hasLegacy: legacy },
})
}
case "GET_WALLETS": {
@@ -447,6 +450,11 @@ import { addToWhitelist, isOnWhitelist } from "./whitelist"
return sendToTabAndUi({ type: "DOWNLOAD_BACKUP_FILE_RES" })
}
+ case "DOWNLOAD_LEGACY_BACKUP_FILE": {
+ await downloadFile(await exportLegacyBackup())
+ return sendToTabAndUi({ type: "DOWNLOAD_LEGACY_BACKUP_FILE_RES" })
+ }
+
case "DELETE_ACCOUNT": {
try {
await wallet.removeAccount(msg.data)
diff --git a/packages/extension/src/background/legacy.ts b/packages/extension/src/background/legacy.ts
new file mode 100644
index 000000000..330ceb1fc
--- /dev/null
+++ b/packages/extension/src/background/legacy.ts
@@ -0,0 +1,18 @@
+import { getFromStorage } from "./storage"
+
+const STORAGE_KEY = "L1:encKeystore"
+
+export const hasLegacy = async () => {
+ return Boolean(await getFromStorage(STORAGE_KEY))
+}
+
+export const exportLegacyBackup = async () => {
+ const backupString = await getFromStorage(STORAGE_KEY)
+
+ const blob = new Blob([backupString as string], {
+ type: "application/json",
+ })
+ const url = URL.createObjectURL(blob)
+ const filename = "starknet-backup.json"
+ return { url, filename }
+}
diff --git a/packages/extension/src/background/storage/default.ts b/packages/extension/src/background/storage/default.ts
index 1bc08ca1d..27419f834 100644
--- a/packages/extension/src/background/storage/default.ts
+++ b/packages/extension/src/background/storage/default.ts
@@ -24,6 +24,10 @@ export function clearStorage() {
return browser.storage.local.clear()
}
+export function getAllStorage() {
+ return browser.storage.local.get()
+}
+
export class Storage implements IStorage {
private NS: string
public defaults: T
diff --git a/packages/extension/src/shared/MessageType.ts b/packages/extension/src/shared/MessageType.ts
index a85f6a651..df4877cb0 100644
--- a/packages/extension/src/shared/MessageType.ts
+++ b/packages/extension/src/shared/MessageType.ts
@@ -68,7 +68,10 @@ export type MessageType =
| { type: "HAS_SESSION" }
| { type: "HAS_SESSION_RES"; data: boolean }
| { type: "IS_INITIALIZED" }
- | { type: "IS_INITIALIZED_RES"; data: boolean }
+ | {
+ type: "IS_INITIALIZED_RES"
+ data: { initialized: boolean; hasLegacy: boolean }
+ }
| { type: "GET_WALLETS" }
| { type: "GET_WALLETS_RES"; data: WalletAccount[] }
| { type: "START_SESSION"; data: { secure: true; body: string } }
@@ -92,6 +95,8 @@ export type MessageType =
| { type: "SUCCESS_SIGN"; data: { r: string; s: string; actionHash: string } }
| { type: "DOWNLOAD_BACKUP_FILE" }
| { type: "DOWNLOAD_BACKUP_FILE_RES" }
+ | { type: "DOWNLOAD_LEGACY_BACKUP_FILE" }
+ | { type: "DOWNLOAD_LEGACY_BACKUP_FILE_RES" }
| { type: "GET_TRANSACTIONS" }
| { type: "GET_TRANSACTIONS_RES"; data: TransactionStatus[] }
| { type: "DELETE_ACCOUNT"; data: string }
diff --git a/packages/extension/src/ui/App.tsx b/packages/extension/src/ui/App.tsx
index ca0df7c60..b1f7d8dbb 100644
--- a/packages/extension/src/ui/App.tsx
+++ b/packages/extension/src/ui/App.tsx
@@ -14,6 +14,7 @@ import { AddTokenScreen } from "./screens/AddTokenScreen"
import { BackupDownloadScreen } from "./screens/BackupDownloadScreen"
import { DappsScreen } from "./screens/DappsScreen"
import { DisclaimerScreen } from "./screens/DisclaimerScreen"
+import { LegacyScreen } from "./screens/LegacyScreen"
import { ErrorScreen } from "./screens/ErrorScreen"
import { HideTokenScreen } from "./screens/HideTokenScreen"
import { LoadingScreen } from "./screens/LoadingScreen"
@@ -92,6 +93,7 @@ const Screen: FC = () => {
} />
} />
} />
+ } />
} />
{/* Routes which need an unlocked keystore and therefore can also sign actions */}
diff --git a/packages/extension/src/ui/hooks/useEntry.tsx b/packages/extension/src/ui/hooks/useEntry.tsx
index e1e1ade40..671329c85 100644
--- a/packages/extension/src/ui/hooks/useEntry.tsx
+++ b/packages/extension/src/ui/hooks/useEntry.tsx
@@ -30,8 +30,11 @@ const determineEntry = async (isBackupDownloadRequired: boolean) => {
return routes.backupDownload()
}
- const initialized = await isInitialized()
+ const { initialized, hasLegacy } = await isInitialized()
if (!initialized) {
+ if (hasLegacy) {
+ return routes.legacy()
+ }
if (!isDisclaimerUnderstood()) {
return routes.disclaimer()
}
diff --git a/packages/extension/src/ui/routes.ts b/packages/extension/src/ui/routes.ts
index 0eef5f083..6de3e9159 100644
--- a/packages/extension/src/ui/routes.ts
+++ b/packages/extension/src/ui/routes.ts
@@ -12,6 +12,7 @@ export const routes = {
hideTokenPath: () => "/tokens/:tokenAddress/hide",
reset: () => "/reset",
disclaimer: () => "/disclaimer",
+ legacy: () => "/legacy",
settings: () => "/settings",
backupDownload: (isFromSettings?: boolean) =>
`/backup-download${isFromSettings ? "?settings" : ""}`,
diff --git a/packages/extension/src/ui/screens/LegacyScreen.tsx b/packages/extension/src/ui/screens/LegacyScreen.tsx
new file mode 100644
index 000000000..a7a75ca98
--- /dev/null
+++ b/packages/extension/src/ui/screens/LegacyScreen.tsx
@@ -0,0 +1,59 @@
+import { FC, FormEventHandler } from "react"
+import { useNavigate } from "react-router-dom"
+import styled from "styled-components"
+
+import { sendMessage } from "../../shared/messages"
+import { Button } from "../components/Button"
+import { Header } from "../components/Header"
+import { H2, P } from "../components/Typography"
+import { routes } from "../routes"
+import { useBackupDownload } from "../states/backupDownload"
+
+const DownloadButton = styled(Button)`
+ margin-top: 20px;
+`
+
+const ContinueButton = styled(Button)`
+ margin-top: auto;
+`
+
+const Container = styled.div`
+ padding: 40px 40px 24px;
+ display: flex;
+ flex-direction: column;
+ height: calc(100vh - 68px);
+`
+
+export const LegacyScreen: FC = () => {
+ const navigate = useNavigate()
+
+ const handleDownload: FormEventHandler = async () => {
+ sendMessage({ type: "DOWNLOAD_LEGACY_BACKUP_FILE" })
+ }
+
+ return (
+ <>
+
+ Breaking Changes
+
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit.
+ Pellentesque vitae ex ut ipsum tristique laoreet.
+
+
+ Nam facilisis vehicula velit ut sodales. For more info click
+
+ this link
+
+
+ Download
+ navigate(routes.welcome())}>
+ Continue without downloading
+
+
+ >
+ )
+}
From b790f714b644d4447c6fea4d85781fce47cba93d Mon Sep 17 00:00:00 2001
From: Axel Delamarre <1091900+delaaxe@users.noreply.github.com>
Date: Fri, 25 Feb 2022 08:16:10 +0000
Subject: [PATCH 14/86] refactor(shared): organize message types
---
packages/extension/src/shared/MessageType.ts | 95 +++++++++++---------
1 file changed, 52 insertions(+), 43 deletions(-)
diff --git a/packages/extension/src/shared/MessageType.ts b/packages/extension/src/shared/MessageType.ts
index 4c3ccc01e..c8893e06d 100644
--- a/packages/extension/src/shared/MessageType.ts
+++ b/packages/extension/src/shared/MessageType.ts
@@ -7,22 +7,36 @@ import { TransactionStatus } from "./transactions.model"
import { WalletAccount } from "./wallet.model"
export type MessageType =
- | { type: "OPEN_UI" }
+ // ***** accounts *****
+ | { type: "NEW_ACCOUNT"; data: string }
+ | {
+ type: "NEW_ACCOUNT_RES"
+ data: {
+ status: "ok"
+ txHash: string
+ address: string
+ account: WalletAccount
+ accounts: WalletAccount[]
+ }
+ }
+ | { type: "NEW_ACCOUNT_REJ"; data: { status: "ko"; error: string } }
+ | { type: "GET_ACCOUNTS" }
+ | { type: "GET_ACCOUNTS_RES"; data: WalletAccount[] }
+ | { type: "CONNECT_ACCOUNT"; data: WalletAccount }
+ | { type: "GET_SELECTED_ACCOUNT" }
+ | { type: "GET_SELECTED_ACCOUNT_RES"; data: WalletAccount }
+ | { type: "DELETE_ACCOUNT"; data: string }
+ | { type: "DELETE_ACCOUNT_RES" }
+ | { type: "DELETE_ACCOUNT_REJ" }
+ // ***** transactions *****
+ | { type: "GET_TRANSACTIONS" }
+ | { type: "GET_TRANSACTIONS_RES"; data: TransactionStatus[] }
| { type: "ADD_TRANSACTION"; data: InvokeFunctionTransaction }
| { type: "ADD_TRANSACTION_RES"; data: { actionHash: string } }
| { type: "TRANSACTION_UPDATES"; data: TransactionStatus[] }
| { type: "TRANSACTION_SUCCESS"; data: TransactionStatus }
| { type: "GET_TRANSACTION"; data: { hash: string; network: string } }
| { type: "GET_TRANSACTION_RES"; data: TransactionStatus }
- | { type: "GET_ACTIONS" }
- | {
- type: "GET_ACTIONS_RES"
- data: ExtActionItem[]
- }
- | { type: "GET_SELECTED_ACCOUNT" }
- | { type: "GET_SELECTED_ACCOUNT_RES"; data: WalletAccount }
- | { type: "CONNECT"; data: { host: string } }
- | { type: "CONNECT_RES"; data: WalletAccount }
| {
type: "SUBMITTED_TX"
data: {
@@ -34,11 +48,16 @@ export type MessageType =
type: "FAILED_TX"
data: { actionHash: string; error?: string }
}
+ // ***** actions *****
+ | { type: "GET_ACTIONS" }
+ | {
+ type: "GET_ACTIONS_RES"
+ data: ExtActionItem[]
+ }
+ // ***** pre-authorizations *****
+ | { type: "CONNECT"; data: { host: string } }
+ | { type: "CONNECT_RES"; data: WalletAccount }
| { type: "ADD_WHITELIST"; data: string }
- | { type: "ADD_TOKEN"; data: AddToken }
- | { type: "ADD_TOKEN_RES"; data: { actionHash: string } }
- | { type: "REJECT_ADD_TOKEN"; data: { actionHash: string } }
- | { type: "APPROVE_ADD_TOKEN"; data: { actionHash: string } }
| { type: "APPROVE_WHITELIST"; data: { host: string; actionHash: string } }
| { type: "REJECT_WHITELIST"; data: { host: string; actionHash: string } }
| { type: "REMOVE_WHITELIST"; data: string }
@@ -47,35 +66,27 @@ export type MessageType =
| { type: "IS_WHITELIST"; data: string }
| { type: "IS_WHITELIST_RES"; data: boolean }
| { type: "RESET_WHITELIST" }
- | { type: "CONNECT_ACCOUNT"; data: WalletAccount }
- | { type: "RESET_ALL" }
- | { type: "REQ_PUB" }
- | { type: "REQ_PUB_RES"; data: JWK }
- | { type: "NEW_ACCOUNT"; data: string }
+ // ***** tokens *****
+ | { type: "ADD_TOKEN"; data: AddToken }
+ | { type: "ADD_TOKEN_RES"; data: { actionHash: string } }
+ | { type: "REJECT_ADD_TOKEN"; data: { actionHash: string } }
+ | { type: "APPROVE_ADD_TOKEN"; data: { actionHash: string } }
+ // ***** sessions *****
| { type: "STOP_SESSION" }
- | {
- type: "NEW_ACCOUNT_RES"
- data: {
- status: "ok"
- txHash: string
- address: string
- account: WalletAccount
- accounts: WalletAccount[]
- }
- }
- | { type: "NEW_ACCOUNT_REJ"; data: { status: "ko"; error: string } }
| { type: "REPORT_PROGRESS"; data: number }
| { type: "HAS_SESSION" }
| { type: "HAS_SESSION_RES"; data: boolean }
| { type: "IS_INITIALIZED" }
| { type: "IS_INITIALIZED_RES"; data: boolean }
- | { type: "GET_ACCOUNTS" }
- | { type: "GET_ACCOUNTS_RES"; data: WalletAccount[] }
| { type: "START_SESSION"; data: { secure: true; body: string } }
| { type: "START_SESSION_REJ" }
| { type: "START_SESSION_RES" }
- | { type: "RECOVER_KEYSTORE"; data: string }
- | { type: "RECOVER_KEYSTORE_RES" }
+ // ***** backup *****
+ | { type: "RECOVER_BACKUP"; data: string }
+ | { type: "RECOVER_BACKUP_RES" }
+ | { type: "DOWNLOAD_BACKUP_FILE" }
+ | { type: "DOWNLOAD_BACKUP_FILE_RES" }
+ // ***** actions *****
| { type: "ADD_SIGN"; data: typedData.TypedData }
| { type: "ADD_SIGN_RES"; data: { actionHash: string } }
| { type: "APPROVE_ACTION"; data: { actionHash: string } }
@@ -90,15 +101,13 @@ export type MessageType =
}
| { type: "FAILED_SIGN"; data: { actionHash: string } }
| { type: "SUCCESS_SIGN"; data: { r: string; s: string; actionHash: string } }
- | { type: "DOWNLOAD_BACKUP_FILE" }
- | { type: "DOWNLOAD_BACKUP_FILE_RES" }
- | { type: "GET_TRANSACTIONS" }
- | { type: "GET_TRANSACTIONS_RES"; data: TransactionStatus[] }
- | { type: "DELETE_ACCOUNT"; data: string }
- | { type: "DELETE_ACCOUNT_RES" }
- | { type: "DELETE_ACCOUNT_REJ" }
+ // ***** misc *****
+ | { type: "OPEN_UI" }
+ | { type: "RESET_ALL" }
+ | { type: "REQ_PUB" }
+ | { type: "REQ_PUB_RES"; data: JWK }
-export type WindowMessageType = {
+export type WindowMessageType = MessageType & {
forwarded?: boolean
extensionId: string
-} & MessageType
+}
From 893c8e266a40597a0ca1e41c5882af48ccb14a9b Mon Sep 17 00:00:00 2001
From: Axel Delamarre <1091900+delaaxe@users.noreply.github.com>
Date: Fri, 25 Feb 2022 08:16:46 +0000
Subject: [PATCH 15/86] refactor(extension): rename keystore to backup
---
packages/extension/src/background/index.ts | 4 ++--
.../extension/src/background/schema/backup.schema.ts | 2 +-
packages/extension/src/ui/App.tsx | 8 ++++----
...oadKeystoreScreen.tsx => RecoverBackupScreen.tsx} | 12 ++++++------
packages/extension/src/ui/utils/messaging.ts | 8 ++++----
5 files changed, 17 insertions(+), 17 deletions(-)
rename packages/extension/src/ui/screens/{UploadKeystoreScreen.tsx => RecoverBackupScreen.tsx} (88%)
diff --git a/packages/extension/src/background/index.ts b/packages/extension/src/background/index.ts
index 52ab65d70..ae8c1accb 100644
--- a/packages/extension/src/background/index.ts
+++ b/packages/extension/src/background/index.ts
@@ -438,9 +438,9 @@ import { addToWhitelist, isOnWhitelist } from "./whitelist"
})
}
- case "RECOVER_KEYSTORE": {
+ case "RECOVER_BACKUP": {
await wallet.importBackup(msg.data)
- return sendToTabAndUi({ type: "RECOVER_KEYSTORE_RES" })
+ return sendToTabAndUi({ type: "RECOVER_BACKUP_RES" })
}
case "DOWNLOAD_BACKUP_FILE": {
await downloadFile(wallet.exportBackup())
diff --git a/packages/extension/src/background/schema/backup.schema.ts b/packages/extension/src/background/schema/backup.schema.ts
index 2e0cc3aa0..a85ad1cd1 100644
--- a/packages/extension/src/background/schema/backup.schema.ts
+++ b/packages/extension/src/background/schema/backup.schema.ts
@@ -1,7 +1,7 @@
import { array, number, object, string } from "yup"
export default object({
- // standard keystore file
+ // standard backup/keystore file
address: string().required(),
version: number().integer().required(),
Crypto: object()
diff --git a/packages/extension/src/ui/App.tsx b/packages/extension/src/ui/App.tsx
index ca0df7c60..0335e8223 100644
--- a/packages/extension/src/ui/App.tsx
+++ b/packages/extension/src/ui/App.tsx
@@ -19,10 +19,10 @@ import { HideTokenScreen } from "./screens/HideTokenScreen"
import { LoadingScreen } from "./screens/LoadingScreen"
import { NewWalletScreen } from "./screens/NewWalletScreen"
import { PasswordScreen } from "./screens/PasswordScreen"
+import { RecoverBackupScreen } from "./screens/RecoverBackupScreen"
import { ResetScreen } from "./screens/ResetScreen"
import { SettingsScreen } from "./screens/SettingsScreen"
import { TokenScreen } from "./screens/TokenScreen"
-import { UploadKeystoreScreen } from "./screens/UploadKeystoreScreen"
import { WelcomeScreen } from "./screens/WelcomeScreen"
import { useActions, useActionsSubscription } from "./states/actions"
import { useAppState } from "./states/app"
@@ -85,16 +85,16 @@ const Screen: FC = () => {
return (
- {/* Routes which need no unlocked keystore */}
+ {/* Routes which need no unlocked backup */}
} />
} />
- } />
+ } />
} />
} />
} />
} />
- {/* Routes which need an unlocked keystore and therefore can also sign actions */}
+ {/* Routes which need an unlocked backup and therefore can also sign actions */}
{actions[0] ? (
} />
) : (
diff --git a/packages/extension/src/ui/screens/UploadKeystoreScreen.tsx b/packages/extension/src/ui/screens/RecoverBackupScreen.tsx
similarity index 88%
rename from packages/extension/src/ui/screens/UploadKeystoreScreen.tsx
rename to packages/extension/src/ui/screens/RecoverBackupScreen.tsx
index 75ab3d46e..960f9bc36 100644
--- a/packages/extension/src/ui/screens/UploadKeystoreScreen.tsx
+++ b/packages/extension/src/ui/screens/RecoverBackupScreen.tsx
@@ -10,9 +10,9 @@ import { H2 } from "../components/Typography"
import { routes } from "../routes"
import { useAppState } from "../states/app"
import { fileToString } from "../utils/files"
-import { recoverKeystore } from "../utils/messaging"
+import { recoverBackup } from "../utils/messaging"
-const UploadKeystoreScreenWrapper = styled.div`
+const Wrapper = styled.div`
display: flex;
flex-direction: column;
padding: 48px 32px;
@@ -41,7 +41,7 @@ const DropZone = styled.div`
}
`
-export const UploadKeystoreScreen: FC = () => {
+export const RecoverBackupScreen: FC = () => {
const navigate = useNavigate()
const {
acceptedFiles: [acceptedFile],
@@ -56,7 +56,7 @@ export const UploadKeystoreScreen: FC = () => {
const handleRestoreClick = async () => {
try {
const data = await fileToString(acceptedFile)
- await recoverKeystore(data)
+ await recoverBackup(data)
navigate(routes.password())
} catch (error: any) {
useAppState.setState({ error: `${error}` })
@@ -65,7 +65,7 @@ export const UploadKeystoreScreen: FC = () => {
}
return (
-
+
Select backup
@@ -83,6 +83,6 @@ export const UploadKeystoreScreen: FC = () => {
-
+
)
}
diff --git a/packages/extension/src/ui/utils/messaging.ts b/packages/extension/src/ui/utils/messaging.ts
index 0ef6d3d2e..7a300a633 100644
--- a/packages/extension/src/ui/utils/messaging.ts
+++ b/packages/extension/src/ui/utils/messaging.ts
@@ -44,12 +44,12 @@ export const getPublicKey = async () => {
return waitForMessage("REQ_PUB_RES")
}
-export const recoverKeystore = async (keystore: string) => {
+export const recoverBackup = async (backup: string) => {
sendMessage({
- type: "RECOVER_KEYSTORE",
- data: keystore,
+ type: "RECOVER_BACKUP",
+ data: backup,
})
- return waitForMessage("RECOVER_KEYSTORE_RES")
+ return waitForMessage("RECOVER_BACKUP_RES")
}
export const isInitialized = async () => {
From f5a759e3c41788190ffb66bd0c9fe56afd79d844 Mon Sep 17 00:00:00 2001
From: Axel Delamarre <1091900+delaaxe@users.noreply.github.com>
Date: Fri, 25 Feb 2022 08:22:48 +0000
Subject: [PATCH 16/86] refactor(extension): harmonize connect to dapp vs.
account
---
packages/extension/src/background/index.ts | 17 ++++++++++-------
packages/extension/src/inpage/index.ts | 7 +++++--
packages/extension/src/shared/MessageType.ts | 4 ++--
packages/extension/src/shared/actionQueue.ts | 2 +-
.../extension/src/ui/screens/ActionScreen.tsx | 2 +-
5 files changed, 19 insertions(+), 13 deletions(-)
diff --git a/packages/extension/src/background/index.ts b/packages/extension/src/background/index.ts
index ae8c1accb..5882841ec 100644
--- a/packages/extension/src/background/index.ts
+++ b/packages/extension/src/background/index.ts
@@ -151,7 +151,7 @@ import { addToWhitelist, isOnWhitelist } from "./whitelist"
})
}
- case "CONNECT": {
+ case "CONNECT_DAPP": {
const selectedAccount = await wallet.getSelectedAccount()
const isWhitelisted = await isOnWhitelist(msg.data.host)
@@ -159,13 +159,16 @@ import { addToWhitelist, isOnWhitelist } from "./whitelist"
if (!isWhitelisted) {
await actionQueue.push({
- type: "CONNECT",
+ type: "CONNECT_DAPP",
payload: { host: msg.data.host },
})
}
if (isWhitelisted && selectedAccount.address) {
- return sendToTabAndUi({ type: "CONNECT_RES", data: selectedAccount })
+ return sendToTabAndUi({
+ type: "CONNECT_DAPP_RES",
+ data: selectedAccount,
+ })
}
return openUi()
@@ -182,7 +185,7 @@ import { addToWhitelist, isOnWhitelist } from "./whitelist"
throw new Error("Action not found")
}
switch (action.type) {
- case "CONNECT": {
+ case "CONNECT_DAPP": {
const { host } = action.payload
const selectedAccount = await wallet.getSelectedAccount()
@@ -190,7 +193,7 @@ import { addToWhitelist, isOnWhitelist } from "./whitelist"
if (selectedAccount) {
return sendToTabAndUi({
- type: "CONNECT_RES",
+ type: "CONNECT_DAPP_RES",
data: selectedAccount,
})
}
@@ -284,7 +287,7 @@ import { addToWhitelist, isOnWhitelist } from "./whitelist"
throw new Error("Action not found")
}
switch (action.type) {
- case "CONNECT": {
+ case "CONNECT_DAPP": {
return sendToTabAndUi({
type: "REJECT_WHITELIST",
data: {
@@ -336,7 +339,7 @@ import { addToWhitelist, isOnWhitelist } from "./whitelist"
case "ADD_WHITELIST": {
return actionQueue.push({
- type: "CONNECT",
+ type: "CONNECT_DAPP",
payload: { host: msg.data },
})
}
diff --git a/packages/extension/src/inpage/index.ts b/packages/extension/src/inpage/index.ts
index 059caf684..9629d4d75 100644
--- a/packages/extension/src/inpage/index.ts
+++ b/packages/extension/src/inpage/index.ts
@@ -108,7 +108,7 @@ const starknetWindowObject: StarknetWindowObject = {
return
}
- if (data.type === "CONNECT_RES" && data.data) {
+ if (data.type === "CONNECT_DAPP_RES" && data.data) {
window.removeEventListener("message", handleMessage)
const { address, network } = data.data
starknet.provider = getProvider(network)
@@ -120,7 +120,10 @@ const starknetWindowObject: StarknetWindowObject = {
}
window.addEventListener("message", handleMessage)
- sendMessage({ type: "CONNECT", data: { host: window.location.host } })
+ sendMessage({
+ type: "CONNECT_DAPP",
+ data: { host: window.location.host },
+ })
}),
isPreauthorized: async () => {
sendMessage({
diff --git a/packages/extension/src/shared/MessageType.ts b/packages/extension/src/shared/MessageType.ts
index c8893e06d..db4ba3928 100644
--- a/packages/extension/src/shared/MessageType.ts
+++ b/packages/extension/src/shared/MessageType.ts
@@ -55,8 +55,8 @@ export type MessageType =
data: ExtActionItem[]
}
// ***** pre-authorizations *****
- | { type: "CONNECT"; data: { host: string } }
- | { type: "CONNECT_RES"; data: WalletAccount }
+ | { type: "CONNECT_DAPP"; data: { host: string } }
+ | { type: "CONNECT_DAPP_RES"; data: WalletAccount }
| { type: "ADD_WHITELIST"; data: string }
| { type: "APPROVE_WHITELIST"; data: { host: string; actionHash: string } }
| { type: "REJECT_WHITELIST"; data: { host: string; actionHash: string } }
diff --git a/packages/extension/src/shared/actionQueue.ts b/packages/extension/src/shared/actionQueue.ts
index 2a6a747ae..326f4e09a 100644
--- a/packages/extension/src/shared/actionQueue.ts
+++ b/packages/extension/src/shared/actionQueue.ts
@@ -4,7 +4,7 @@ import type { ExtQueueItem } from "../background/actionQueue"
export type ActionItem =
| {
- type: "CONNECT"
+ type: "CONNECT_DAPP"
payload: {
host: string
}
diff --git a/packages/extension/src/ui/screens/ActionScreen.tsx b/packages/extension/src/ui/screens/ActionScreen.tsx
index d054424a4..1a7c5f098 100644
--- a/packages/extension/src/ui/screens/ActionScreen.tsx
+++ b/packages/extension/src/ui/screens/ActionScreen.tsx
@@ -21,7 +21,7 @@ export const ActionScreen: FC = () => {
const [action] = actions
const isLastAction = actions.length === 1
switch (action.type) {
- case "CONNECT":
+ case "CONNECT_DAPP":
return (
Date: Fri, 25 Feb 2022 08:46:23 +0000
Subject: [PATCH 17/86] refactor(extension): rename whitelist to pre
authorization
---
packages/extension/src/background/index.ts | 53 +++++++++--------
.../src/background/preAuthorizations.ts | 24 ++++++++
.../extension/src/background/whitelist.ts | 24 --------
packages/extension/src/inpage/index.ts | 22 +++----
packages/extension/src/shared/MessageType.ts | 59 +++++++++----------
.../src/ui/components/Account/DappsList.tsx | 20 +++----
.../extension/src/ui/screens/ActionScreen.tsx | 6 +-
.../src/ui/screens/SettingsScreen.tsx | 2 +-
packages/extension/src/ui/utils/messaging.ts | 4 +-
9 files changed, 107 insertions(+), 107 deletions(-)
create mode 100644 packages/extension/src/background/preAuthorizations.ts
delete mode 100644 packages/extension/src/background/whitelist.ts
diff --git a/packages/extension/src/background/index.ts b/packages/extension/src/background/index.ts
index 5882841ec..621af573e 100644
--- a/packages/extension/src/background/index.ts
+++ b/packages/extension/src/background/index.ts
@@ -23,10 +23,10 @@ import {
sentTransactionNotification,
} from "./notification"
import { openUi } from "./openUi"
+import { isPreAuthorized, preAuthorize } from "./preAuthorizations"
import { Storage, clearStorage, setToStorage } from "./storage"
import { TransactionTracker, getTransactionStatus } from "./trackTransactions"
import { Wallet, WalletStorageProps } from "./wallet"
-import { addToWhitelist, isOnWhitelist } from "./whitelist"
;(async () => {
const { privateKey, publicKeyJwk } = await getKeyPair()
@@ -153,18 +153,18 @@ import { addToWhitelist, isOnWhitelist } from "./whitelist"
case "CONNECT_DAPP": {
const selectedAccount = await wallet.getSelectedAccount()
- const isWhitelisted = await isOnWhitelist(msg.data.host)
+ const isAuthorized = await isPreAuthorized(msg.data.host)
addTab(sender.tab?.id)
- if (!isWhitelisted) {
+ if (!isAuthorized) {
await actionQueue.push({
type: "CONNECT_DAPP",
payload: { host: msg.data.host },
})
}
- if (isWhitelisted && selectedAccount.address) {
+ if (isAuthorized && selectedAccount.address) {
return sendToTabAndUi({
type: "CONNECT_DAPP_RES",
data: selectedAccount,
@@ -189,7 +189,7 @@ import { addToWhitelist, isOnWhitelist } from "./whitelist"
const { host } = action.payload
const selectedAccount = await wallet.getSelectedAccount()
- await addToWhitelist(host)
+ await preAuthorize(host)
if (selectedAccount) {
return sendToTabAndUi({
@@ -220,7 +220,7 @@ import { addToWhitelist, isOnWhitelist } from "./whitelist"
)
return sendToTabAndUi({
- type: "SUBMITTED_TX",
+ type: "TRANSACTION_SUBMITTED",
data: {
txHash: tx.transaction_hash,
actionHash,
@@ -228,7 +228,7 @@ import { addToWhitelist, isOnWhitelist } from "./whitelist"
})
} catch (error: any) {
return sendToTabAndUi({
- type: "FAILED_TX",
+ type: "TRANSACTION_FAILED",
data: { actionHash, error: `${error}` },
})
}
@@ -244,7 +244,7 @@ import { addToWhitelist, isOnWhitelist } from "./whitelist"
const [r, s] = await signer.signMessage(typedData)
return sendToTabAndUi({
- type: "SUCCESS_SIGN",
+ type: "SIGNATURE_SUCCESS",
data: {
r: r.toString(),
s: s.toString(),
@@ -289,7 +289,7 @@ import { addToWhitelist, isOnWhitelist } from "./whitelist"
switch (action.type) {
case "CONNECT_DAPP": {
return sendToTabAndUi({
- type: "REJECT_WHITELIST",
+ type: "REJECT_PREAUTHORIZATION",
data: {
host: action.payload.host,
actionHash,
@@ -298,7 +298,7 @@ import { addToWhitelist, isOnWhitelist } from "./whitelist"
}
case "TRANSACTION": {
return sendToTabAndUi({
- type: "FAILED_TX",
+ type: "TRANSACTION_FAILED",
data: {
actionHash,
},
@@ -306,7 +306,7 @@ import { addToWhitelist, isOnWhitelist } from "./whitelist"
}
case "SIGN": {
return sendToTabAndUi({
- type: "FAILED_SIGN",
+ type: "SIGNATURE_FAILURE",
data: {
actionHash,
},
@@ -325,10 +325,10 @@ import { addToWhitelist, isOnWhitelist } from "./whitelist"
}
}
- case "FAILED_SIGN":
- case "REJECT_WHITELIST":
+ case "SIGNATURE_FAILURE":
+ case "REJECT_PREAUTHORIZATION":
case "REJECT_ADD_TOKEN":
- case "FAILED_TX": {
+ case "TRANSACTION_FAILED": {
return await actionQueue.remove(msg.data.actionHash)
}
@@ -337,23 +337,26 @@ import { addToWhitelist, isOnWhitelist } from "./whitelist"
return wallet.lock()
}
- case "ADD_WHITELIST": {
+ case "PREAUTHORIZE": {
return actionQueue.push({
type: "CONNECT_DAPP",
payload: { host: msg.data },
})
}
- case "IS_WHITELIST": {
- const valid = await isOnWhitelist(msg.data)
- return sendToTabAndUi({ type: "IS_WHITELIST_RES", data: valid })
+ case "IS_PREAUTHORIZED": {
+ const valid = await isPreAuthorized(msg.data)
+ return sendToTabAndUi({ type: "IS_PREAUTHORIZED_RES", data: valid })
}
- case "RESET_WHITELIST": {
- setToStorage(`WHITELIST:APPROVED`, [])
- setToStorage(`WHITELIST:PENDING`, [])
+ case "RESET_PREAUTHORIZATIONS": {
+ setToStorage(`PREAUTHORIZATION:APPROVED`, [])
+ setToStorage(`PREAUTHORIZATION:PENDING`, [])
return
}
- case "REQ_PUB": {
- return sendToTabAndUi({ type: "REQ_PUB_RES", data: publicKeyJwk })
+ case "GET_PUBLIC_KEY": {
+ return sendToTabAndUi({
+ type: "GET_PUBLIC_KEY_RES",
+ data: publicKeyJwk,
+ })
}
case "START_SESSION": {
const { secure, body } = msg.data
@@ -427,14 +430,14 @@ import { addToWhitelist, isOnWhitelist } from "./whitelist"
}
}
- case "ADD_SIGN": {
+ case "SIGN_MESSAGE": {
const { meta } = await actionQueue.push({
type: "SIGN",
payload: msg.data,
})
return sendToTabAndUi({
- type: "ADD_SIGN_RES",
+ type: "SIGN_MESSAGE_RES",
data: {
actionHash: meta.hash,
},
diff --git a/packages/extension/src/background/preAuthorizations.ts b/packages/extension/src/background/preAuthorizations.ts
new file mode 100644
index 000000000..7248c91d8
--- /dev/null
+++ b/packages/extension/src/background/preAuthorizations.ts
@@ -0,0 +1,24 @@
+import { getFromStorage, setToStorage } from "./storage"
+
+export async function preAuthorize(host: string) {
+ const approved = await getFromStorage(`PREAUTHORIZATION:APPROVED`)
+ await setToStorage(`PREAUTHORIZATION:APPROVED`, [...(approved || []), host])
+}
+
+export async function getPreAuthorizations() {
+ const approved = await getFromStorage(`PREAUTHORIZATION:APPROVED`)
+ return approved || []
+}
+
+export async function removePreAuthorization(host: string) {
+ const approved = await getFromStorage(`PREAUTHORIZATION:APPROVED`)
+ await setToStorage(
+ `PREAUTHORIZATION:APPROVED`,
+ (approved || []).filter((x) => x !== host),
+ )
+}
+
+export async function isPreAuthorized(host: string) {
+ const approved = await getFromStorage(`PREAUTHORIZATION:APPROVED`)
+ return (approved || []).includes(host)
+}
diff --git a/packages/extension/src/background/whitelist.ts b/packages/extension/src/background/whitelist.ts
deleted file mode 100644
index bfb3bb093..000000000
--- a/packages/extension/src/background/whitelist.ts
+++ /dev/null
@@ -1,24 +0,0 @@
-import { getFromStorage, setToStorage } from "./storage"
-
-export async function addToWhitelist(host: string) {
- const approved = await getFromStorage(`WHITELIST:APPROVED`)
- await setToStorage(`WHITELIST:APPROVED`, [...(approved || []), host])
-}
-
-export async function getWhitelist() {
- const approved = await getFromStorage(`WHITELIST:APPROVED`)
- return approved || []
-}
-
-export async function removeFromWhitelist(host: string) {
- const approved = await getFromStorage(`WHITELIST:APPROVED`)
- await setToStorage(
- `WHITELIST:APPROVED`,
- (approved || []).filter((x) => x !== host),
- )
-}
-
-export async function isOnWhitelist(host: string) {
- const approved = await getFromStorage(`WHITELIST:APPROVED`)
- return (approved || []).includes(host)
-}
diff --git a/packages/extension/src/inpage/index.ts b/packages/extension/src/inpage/index.ts
index 9629d4d75..928071506 100644
--- a/packages/extension/src/inpage/index.ts
+++ b/packages/extension/src/inpage/index.ts
@@ -84,7 +84,7 @@ const starknetWindowObject: StarknetWindowObject = {
)
.then(() => "error" as const)
.catch(() => {
- sendMessage({ type: "FAILED_TX", data: { actionHash } })
+ sendMessage({ type: "TRANSACTION_FAILED", data: { actionHash } })
return "timeout" as const
}),
])
@@ -127,10 +127,10 @@ const starknetWindowObject: StarknetWindowObject = {
}),
isPreauthorized: async () => {
sendMessage({
- type: "IS_WHITELIST",
+ type: "IS_PREAUTHORIZED",
data: window.location.host,
})
- return waitForMsgOfType("IS_WHITELIST_RES", 1000)
+ return waitForMsgOfType("IS_PREAUTHORIZED_RES", 1000)
},
on: (event, handleEvent) => {
if (event !== "accountsChanged") {
@@ -194,18 +194,18 @@ export class WalletSigner extends Provider implements SignerInterface {
const result = await Promise.race([
waitForMsgOfType(
- "SUBMITTED_TX",
+ "TRANSACTION_SUBMITTED",
11 * 60 * 1000,
(x) => x.data.actionHash === actionHash,
),
waitForMsgOfType(
- "FAILED_TX",
+ "TRANSACTION_FAILED",
10 * 60 * 1000,
(x) => x.data.actionHash === actionHash,
)
.then(() => "error" as const)
.catch(() => {
- sendMessage({ type: "FAILED_TX", data: { actionHash } })
+ sendMessage({ type: "TRANSACTION_FAILED", data: { actionHash } })
return "timeout" as const
}),
])
@@ -229,24 +229,24 @@ export class WalletSigner extends Provider implements SignerInterface {
}
public async signMessage(data: typedData.TypedData): Promise {
- sendMessage({ type: "ADD_SIGN", data })
- const { actionHash } = await waitForMsgOfType("ADD_SIGN_RES", 1000)
+ sendMessage({ type: "SIGN_MESSAGE", data })
+ const { actionHash } = await waitForMsgOfType("SIGN_MESSAGE_RES", 1000)
sendMessage({ type: "OPEN_UI" })
const result = await Promise.race([
waitForMsgOfType(
- "SUCCESS_SIGN",
+ "SIGNATURE_SUCCESS",
11 * 60 * 1000,
(x) => x.data.actionHash === actionHash,
),
waitForMsgOfType(
- "FAILED_SIGN",
+ "SIGNATURE_FAILURE",
10 * 60 * 1000,
(x) => x.data.actionHash === actionHash,
)
.then(() => "error" as const)
.catch(() => {
- sendMessage({ type: "FAILED_SIGN", data: { actionHash } })
+ sendMessage({ type: "SIGNATURE_FAILURE", data: { actionHash } })
return "timeout" as const
}),
])
diff --git a/packages/extension/src/shared/MessageType.ts b/packages/extension/src/shared/MessageType.ts
index db4ba3928..c367362ec 100644
--- a/packages/extension/src/shared/MessageType.ts
+++ b/packages/extension/src/shared/MessageType.ts
@@ -38,42 +38,30 @@ export type MessageType =
| { type: "GET_TRANSACTION"; data: { hash: string; network: string } }
| { type: "GET_TRANSACTION_RES"; data: TransactionStatus }
| {
- type: "SUBMITTED_TX"
+ type: "TRANSACTION_SUBMITTED"
data: {
txHash: string
actionHash: string
}
}
| {
- type: "FAILED_TX"
+ type: "TRANSACTION_FAILED"
data: { actionHash: string; error?: string }
}
- // ***** actions *****
- | { type: "GET_ACTIONS" }
- | {
- type: "GET_ACTIONS_RES"
- data: ExtActionItem[]
- }
// ***** pre-authorizations *****
| { type: "CONNECT_DAPP"; data: { host: string } }
| { type: "CONNECT_DAPP_RES"; data: WalletAccount }
- | { type: "ADD_WHITELIST"; data: string }
- | { type: "APPROVE_WHITELIST"; data: { host: string; actionHash: string } }
- | { type: "REJECT_WHITELIST"; data: { host: string; actionHash: string } }
- | { type: "REMOVE_WHITELIST"; data: string }
- | { type: "GET_PENDING_WHITELIST" }
- | { type: "GET_PENDING_WHITELIST_RES"; data: string[] }
- | { type: "IS_WHITELIST"; data: string }
- | { type: "IS_WHITELIST_RES"; data: boolean }
- | { type: "RESET_WHITELIST" }
- // ***** tokens *****
- | { type: "ADD_TOKEN"; data: AddToken }
- | { type: "ADD_TOKEN_RES"; data: { actionHash: string } }
- | { type: "REJECT_ADD_TOKEN"; data: { actionHash: string } }
- | { type: "APPROVE_ADD_TOKEN"; data: { actionHash: string } }
+ | { type: "PREAUTHORIZE"; data: string }
+ | {
+ type: "REJECT_PREAUTHORIZATION"
+ data: { host: string; actionHash: string }
+ }
+ | { type: "REMOVE_PREAUTHORIZATION"; data: string }
+ | { type: "IS_PREAUTHORIZED"; data: string }
+ | { type: "IS_PREAUTHORIZED_RES"; data: boolean }
+ | { type: "RESET_PREAUTHORIZATIONS" }
// ***** sessions *****
| { type: "STOP_SESSION" }
- | { type: "REPORT_PROGRESS"; data: number }
| { type: "HAS_SESSION" }
| { type: "HAS_SESSION_RES"; data: boolean }
| { type: "IS_INITIALIZED" }
@@ -86,26 +74,35 @@ export type MessageType =
| { type: "RECOVER_BACKUP_RES" }
| { type: "DOWNLOAD_BACKUP_FILE" }
| { type: "DOWNLOAD_BACKUP_FILE_RES" }
+ // ***** tokens *****
+ | { type: "ADD_TOKEN"; data: AddToken }
+ | { type: "ADD_TOKEN_RES"; data: { actionHash: string } }
+ | { type: "REJECT_ADD_TOKEN"; data: { actionHash: string } }
+ | { type: "APPROVE_ADD_TOKEN"; data: { actionHash: string } }
// ***** actions *****
- | { type: "ADD_SIGN"; data: typedData.TypedData }
- | { type: "ADD_SIGN_RES"; data: { actionHash: string } }
+ | { type: "GET_ACTIONS" }
+ | {
+ type: "GET_ACTIONS_RES"
+ data: ExtActionItem[]
+ }
| { type: "APPROVE_ACTION"; data: { actionHash: string } }
| { type: "REJECT_ACTION"; data: { actionHash: string } }
| {
type: "ACTIONS_QUEUE_UPDATE"
data: { actions: ExtActionItem[] }
}
+ | { type: "SIGN_MESSAGE"; data: typedData.TypedData }
+ | { type: "SIGN_MESSAGE_RES"; data: { actionHash: string } }
+ | { type: "SIGNATURE_FAILURE"; data: { actionHash: string } }
| {
- type: "APPROVE_SIGN"
- data: { typedData: typedData.TypedData; actionHash: string }
+ type: "SIGNATURE_SUCCESS"
+ data: { r: string; s: string; actionHash: string }
}
- | { type: "FAILED_SIGN"; data: { actionHash: string } }
- | { type: "SUCCESS_SIGN"; data: { r: string; s: string; actionHash: string } }
// ***** misc *****
| { type: "OPEN_UI" }
| { type: "RESET_ALL" }
- | { type: "REQ_PUB" }
- | { type: "REQ_PUB_RES"; data: JWK }
+ | { type: "GET_PUBLIC_KEY" }
+ | { type: "GET_PUBLIC_KEY_RES"; data: JWK }
export type WindowMessageType = MessageType & {
forwarded?: boolean
diff --git a/packages/extension/src/ui/components/Account/DappsList.tsx b/packages/extension/src/ui/components/Account/DappsList.tsx
index 3933611dd..b7132b65c 100644
--- a/packages/extension/src/ui/components/Account/DappsList.tsx
+++ b/packages/extension/src/ui/components/Account/DappsList.tsx
@@ -1,33 +1,33 @@
import { FC, useCallback, useEffect, useState } from "react"
import {
- getWhitelist,
- removeFromWhitelist,
-} from "../../../background/whitelist"
+ getPreAuthorizations,
+ removePreAuthorization,
+} from "../../../background/preAuthorizations"
import { DappListItem } from "./Dapp"
import { SectionHeader } from "./SectionHeader"
export const DappsList: FC = () => {
- const [dappsWhitelist, setDappsWhitelist] = useState([])
+ const [preAuthorizations, setPreAuthorizations] = useState([])
- const getWhitelistDapps = useCallback(async () => {
- setDappsWhitelist(await getWhitelist())
+ const requestPreAuthorizations = useCallback(async () => {
+ setPreAuthorizations(await getPreAuthorizations())
}, [])
useEffect(() => {
- getWhitelistDapps()
+ requestPreAuthorizations()
}, [])
return (
<>
Dapps
- {dappsWhitelist.map((dapp) => (
+ {preAuthorizations.map((dapp) => (
{
- await removeFromWhitelist(dapp)
- getWhitelistDapps()
+ await removePreAuthorization(dapp)
+ requestPreAuthorizations()
}}
/>
))}
diff --git a/packages/extension/src/ui/screens/ActionScreen.tsx b/packages/extension/src/ui/screens/ActionScreen.tsx
index 1a7c5f098..242355b3a 100644
--- a/packages/extension/src/ui/screens/ActionScreen.tsx
+++ b/packages/extension/src/ui/screens/ActionScreen.tsx
@@ -68,11 +68,11 @@ export const ActionScreen: FC = () => {
useAppState.setState({ isLoading: true })
const result = await Promise.race([
waitForMessage(
- "SUBMITTED_TX",
+ "TRANSACTION_SUBMITTED",
({ data }) => data.actionHash === action.meta.hash,
),
waitForMessage(
- "FAILED_TX",
+ "TRANSACTION_FAILED",
({ data }) => data.actionHash === action.meta.hash,
),
])
@@ -107,7 +107,7 @@ export const ActionScreen: FC = () => {
await approve(action)
useAppState.setState({ isLoading: true })
await waitForMessage(
- "SUCCESS_SIGN",
+ "SIGNATURE_SUCCESS",
({ data }) => data.actionHash === action.meta.hash,
)
if (isPopup && isLastAction) {
diff --git a/packages/extension/src/ui/screens/SettingsScreen.tsx b/packages/extension/src/ui/screens/SettingsScreen.tsx
index a6595864b..0668da6bc 100644
--- a/packages/extension/src/ui/screens/SettingsScreen.tsx
+++ b/packages/extension/src/ui/screens/SettingsScreen.tsx
@@ -57,7 +57,7 @@ export const SettingsScreen: FC = () => {