Logon to ProofofBrain with a QR Code

You can make a QR code of your posting private key and login to proofofbrain.blog app with the QR code.

The diff against my forked code follows:

diff --git a/package.json b/package.json
index 70a3fc2bb..991fc1b18 100644
--- a/package.json
+++ b/package.json
@@ -18,7 +18,7 @@
     "@firebase/analytics": "^0.8.0",
     "@firebase/app": "^0.7.28",
     "@firebase/messaging": "^0.9.16",
-    "@hiveio/dhive": "^1.2.1",
+    "@hiveio/dhive": "^1.2.8",
     "@hiveio/hivescript": "^1.2.7",
     "@loadable/component": "^5.15.2",
     "@loadable/server": "^5.15.2",
@@ -43,6 +43,7 @@
     "hive-uri": "^0.2.3",
     "hivesigner": "^3.2.8",
     "html-react-parser": "^1.2.1",
+    "html5-qrcode": "^2.3.8",
     "i18next": "^19.4.4",
     "i18next-browser-languagedetector": "^4.2.0",
     "immutability-helper": "^3.0.2",
diff --git a/src/common/components/login/index.tsx b/src/common/components/login/index.tsx
index e334cd69e..1d3f5db83 100644
--- a/src/common/components/login/index.tsx
+++ b/src/common/components/login/index.tsx
@@ -1,4 +1,4 @@
-import React, { Component } from "react";
+import React, { Component, MouseEvent } from "react";
 
 import { Modal, Form, Button, FormControl, Spinner } from "react-bootstrap";
 
@@ -28,15 +28,13 @@ import { error } from "../feedback";
 import { getAuthUrl, makeHsCode } from "../../helper/hive-signer";
 import { hsLogin } from "../../../desktop/app/helper/hive-signer";
 
-import { getAccount } from "../../api/hive";
+import { client, getAccount } from "../../api/hive";
 import { usrActivity } from "../../api/private-api";
 import { hsTokenRenew } from "../../api/auth-api";
 import { formatError, grantPostingPermission, revokePostingPermission } from "../../api/operations";
 
 import { getRefreshToken } from "../../helper/user-token";
 
-import ReCAPTCHA from "react-google-recaptcha";
-
 import { addAccountAuthority, removeAccountAuthority, signBuffer } from "../../helper/keychain";
 import { logUser } from "../../helper/log-user";
 import { _t } from "../../i18n";
@@ -44,6 +42,8 @@ import { _t } from "../../i18n";
 import _c from "../../util/fix-class-names";
 
 import { deleteForeverSvg } from "../../img/svg";
+import {Html5QrcodeScanner, Html5QrcodeResult} from "html5-qrcode";
+
 
 declare var window: AppWindow;
 
@@ -410,15 +410,21 @@ interface State {
   username: string;
   key: string;
   inProgress: boolean;
+  quickReliablePreviewVisible: boolean;
+  quickReliablePreviewSetup: boolean;
 }
 
 export class Login extends BaseComponent<LoginProps, State> {
   state: State = {
     username: "",
     key: "",
-    inProgress: false
+    inProgress: false,
+    quickReliablePreviewVisible: false,
+    quickReliablePreviewSetup: false,
   };
-
+  
+  html5QrcodeScanner: undefined|Html5QrcodeScanner = undefined;
+  
   shouldComponentUpdate(nextProps: Readonly<LoginProps>, nextState: Readonly<State>): boolean {
     return (
       !isEqual(this.props.users, nextProps.users) ||
@@ -429,7 +435,9 @@ export class Login extends BaseComponent<LoginProps, State> {
 
   hide = () => {
     const { toggleUIProp } = this.props;
+    this.stateSet({ quickReliablePreviewVisible: false });
     toggleUIProp("login");
+    
   };
 
   userSelect = (user: User) => {
@@ -516,7 +524,7 @@ export class Login extends BaseComponent<LoginProps, State> {
 
   login = async () => {
     const { hsClientId } = this.props.global;
-    const { username, key } = this.state;
+    const { username, key, quickReliablePreviewVisible } = this.state;
 
     if (username === "" || key === "") {
       error(_t("login.error-fields-required"));
@@ -613,25 +621,7 @@ export class Login extends BaseComponent<LoginProps, State> {
     const { doLogin } = this.props;
 
     doLogin(code, withPostingKey ? key : null, account)
-      .then(() => {
-        if (
-          !ls.get(`${username}HadTutorial`) ||
-          (ls.get(`${username}HadTutorial`) && ls.get(`${username}HadTutorial`) !== "true")
-        ) {
-          ls.set(`${username}HadTutorial`, "false");
-        }
-
-        let shouldShowTutorialJourney = ls.get(`${username}HadTutorial`);
-
-        if (
-          !shouldShowTutorialJourney &&
-          shouldShowTutorialJourney &&
-          shouldShowTutorialJourney === "false"
-        ) {
-          ls.set(`${username}HadTutorial`, "false");
-        }
-        this.hide();
-      })
+      .then(this.handleDoLogin.bind(this,username))
       .catch(() => {
         error(_t("g.server-error"));
       })
@@ -639,9 +629,169 @@ export class Login extends BaseComponent<LoginProps, State> {
         this.stateSet({ inProgress: false });
       });
   };
+  
+  handleDoLogin = (username: string) => {
+      if (
+        !ls.get(`${username}HadTutorial`) ||
+        (ls.get(`${username}HadTutorial`) && ls.get(`${username}HadTutorial`) !== "true")
+      ) {
+        ls.set(`${username}HadTutorial`, "false");
+      }
+
+      let shouldShowTutorialJourney = ls.get(`${username}HadTutorial`);
 
+      if (
+        !shouldShowTutorialJourney &&
+        shouldShowTutorialJourney &&
+        shouldShowTutorialJourney === "false"
+      ) {
+        ls.set(`${username}HadTutorial`, "false");
+      }
+      
+      if (this.html5QrcodeScanner) {
+        this.html5QrcodeScanner.clear();
+      }
+      
+      this.hide();
+  };
+  
+  hideQRPreview = (e: MouseEvent<typeof FormControl & HTMLInputElement>): void => {
+    if (this.state.quickReliablePreviewSetup === false)
+      return;
+    const scanner = this.html5QrcodeScanner;
+    if (this.state.quickReliablePreviewVisible === true && scanner) {
+      this.setState((old_state:State)=>{
+          if (!old_state.quickReliablePreviewVisible)
+            return old_state;
+          try {
+            scanner.pause()
+          } catch (emessage : string) {
+            console.error(emessage)
+          } finally {
+            return {...old_state, quickReliablePreviewVisible: false}
+          }
+      });
+    } // if
+  }
+  
+  showQRPreview = (e: MouseEvent<typeof FormControl & HTMLInputElement>): void => {
+    const { hsClientId } = this.props.global;
+    const { quickReliablePreviewSetup, quickReliablePreviewVisible } = this.state;
+    if (quickReliablePreviewVisible) {
+      return;
+    } else if (quickReliablePreviewSetup) {
+      const scanner = this.html5QrcodeScanner;
+      if (scanner) {
+        this.stateSet((old_state:State)=> {
+            if (old_state.quickReliablePreviewVisible)
+              return old_state;
+            try {
+              scanner.resume()
+            } catch (emessage:string) {
+              console.error(emessage)
+            } finally{
+              return {...old_state, quickReliablePreviewVisible: true}
+            }
+        });
+      }
+    } else {
+      this.stateSet({ quickReliablePreviewVisible: true, quickReliablePreviewSetup: true });          
+      
+      if (!navigator.mediaDevices.getUserMedia) {
+        console.log('media devices not supported');
+        return;
+      }
+      
+      const onScanSuccess = (decodedText: string, decodedResult: Html5QrcodeResult) => {
+        // handle the scanned code as you like, for example:
+        const privateKeyString = decodedText.trim();
+        const handleFailure = () => this.setState({key: privateKeyString, quickReliablePreviewVisible: false});
+        // setting the username leaves the login button disabled (why?).  
+        try {
+          const privateKeyObject = PrivateKey.fromString(privateKeyString);
+          const publicKeyObject = privateKeyObject.createPublic();
+          const publicKeyString = publicKeyObject.toString();
+          console.log('line 671:', {publicKeyString});
+          // still in development:          //getKeyReferences({"keys": [publicKey]})
+          client.call("account_by_key_api", "get_key_references", {"keys":[publicKeyString]})
+            .then( async (result: {"accounts": string[][]}) => {
+                console.log('line 675:', result);
+                if (result.accounts.length == 0) {
+                  handleFailure();          
+                  error("Invalid return value from server.");                  
+                } else {
+                  const usernamesForFirstKey : string[] = result.accounts[0];
+                  if (usernamesForFirstKey.length === 0) {
+                    handleFailure();
+                    error("No user for this key");
+                  } else if (usernamesForFirstKey.length > 1) {
+                    handleFailure();
+                    error("More than one user for this key");
+                  } else {
+                    const firstUsername : string = usernamesForFirstKey[0];
+  
+                    let account: Account;
+                    
+                    this.stateSet({key: privateKeyString, quickReliablePreviewVisible: false, inProgress: true, "username": firstUsername});
+                    
+                    try {
+                      console.log({username: firstUsername});
+                      account = await getAccount(firstUsername);
+                    } catch (err) {
+                      this.stateSet({ inProgress: false });
+                      error(_t("login.error-user-fetch"));
+                      return;
+                    }
+                                  
+                    // Prepare hivesigner code
+                    const signer = (message: string): Promise<string> => {
+                      const hash = cryptoUtils.sha256(message);
+                      return new Promise<string>((resolve) => resolve(privateKeyObject.sign(hash).toString()));
+                    };
+                    const code = await makeHsCode(hsClientId, firstUsername, signer);
+                
+                    const { doLogin } = this.props;
+                    
+                    doLogin(code, privateKeyString, account)
+                      .then(this.handleDoLogin.bind(this,firstUsername))
+                      .catch(() => {
+                        error(_t("g.server-error"));
+                      })
+                      .finally(() => {
+                        this.stateSet({ inProgress: false });
+                      });
+                    }                  
+                }
+            })
+            .catch(e => {
+                console.log(685, e);
+                handleFailure();
+            });
+        } catch (e) {
+          console.log('689',e);
+          if (typeof e.message == 'string') {
+            error(e.message);
+          }
+        }
+      };
+      
+      function onScanFailure(error: string) {
+        // handle scan failure, usually better to ignore and keep scanning.
+        // for example:
+        
+        // doing nothing
+      }
+      
+      this.html5QrcodeScanner = new Html5QrcodeScanner(
+        "reader",
+        { fps: 10, qrbox: {width: 250, height: 250} },
+        /* verbose= */ false);
+      this.html5QrcodeScanner.render(onScanSuccess, onScanFailure);
+    }
+  }
+  
   render() {
-    const { username, key, inProgress } = this.state;
+    const { username, key, inProgress, quickReliablePreviewVisible } = this.state;
     const { users, activeUser, global, userListRef } = this.props;
     const isEcency = false;
     const logo = global.isElectron ? "./img/logo-circle.svg" : require("../../img/logo-circle.svg");
@@ -707,14 +857,31 @@ export class Login extends BaseComponent<LoginProps, State> {
             />
           </Form.Group>
           <Form.Group>
-            <Form.Control
-              type="password"
-              value={key}
-              autoComplete="off"
-              onChange={this.keyChanged}
-              placeholder={_t("login.key-placeholder")}
-              onKeyDown={this.inputKeyDown}
-            />
+            <div style={{display: 'flex', flexDirection: 'row'}}>
+              <Form.Control
+                type="password"
+                value={key}
+                autoComplete="off"
+                onChange={this.keyChanged}
+                placeholder={_t("login.key-placeholder")}
+                onKeyDown={this.inputKeyDown}
+                style={{display: quickReliablePreviewVisible ? 'none' : 'inherit'}}
+              />
+              {navigator.mediaDevices.getUserMedia && !quickReliablePreviewVisible &&
+                <Button
+                  onClick={this.showQRPreview}
+                >
+                  QR
+                </Button>
+              }        
+            </div>
+            <div style={{display: quickReliablePreviewVisible? 'inherit':'none'}}>
+              <div id="reader" />
+              <Button
+                onClick={this.hideQRPreview}
+               >Type password
+              </Button>
+            </div>    
           </Form.Group>
           <p className="login-form-text">
             {_t("login.login-info-1")}{" "}
diff --git a/yarn.lock b/yarn.lock
index f5e028b57..aa4021e5e 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1396,18 +1396,21 @@
   dependencies:
     tslib "^2.1.0"
 
-"@hiveio/dhive@^1.2.1":
-  version "1.2.1"
-  resolved "https://registry.yarnpkg.com/@hiveio/dhive/-/dhive-1.2.1.tgz#bcae9b809c15150e5cb0e64aa571c84b6851bf73"
-  integrity sha512-ZOyYQBXvsqTMGXTf/8mI7rtGvsNjiRM30H8nUWamy0iYjEzYNO/4KL0sSJFGA9dxIQbEMp4h7KfASAJJGFYXyA==
+"@hiveio/dhive@^1.2.8":
+  version "1.2.8"
+  resolved "https://registry.yarnpkg.com/@hiveio/dhive/-/dhive-1.2.8.tgz#1ad13d92649a6db8c01b3a80872bcba218f91ba9"
+  integrity sha512-prarzjLnnQagE4wdcdeSzPuzlW7sw/WE6WYJ/mXHuqwiyay2cK8fyoRgGdE5bDQYEzgH5x+jQELbJYbg0ZJ5Sg==
   dependencies:
+    bigi "^1.4.2"
     bs58 "^4.0.1"
     bytebuffer "^5.0.1"
     core-js "^3.6.4"
     cross-fetch "^3.0.4"
+    ecurve "^1.0.6"
     https "^1.0.0"
     jsbi "^3.1.4"
     node-fetch "^2.6.0"
+    ripemd160 "^2.0.2"
     secp256k1 "^3.8.0"
     verror "^1.10.0"
     whatwg-fetch "^3.0.0"
@@ -3052,6 +3055,11 @@ big.js@^5.2.2:
   resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328"
   integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==
 
+bigi@^1.1.0, bigi@^1.4.2:
+  version "1.4.2"
+  resolved "https://registry.yarnpkg.com/bigi/-/bigi-1.4.2.tgz#9c665a95f88b8b08fc05cfd731f561859d725825"
+  integrity sha512-ddkU+dFIuEIW8lE7ZwdIAf2UPoM90eaprg5m3YXAVVTmKlqV/9BX4A2M8BOK2yOq6/VgZFVhK6QAxJebhlbhzw==
+
 binary-extensions@^1.0.0:
   version "1.13.1"
   resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65"
@@ -3072,7 +3080,7 @@ bindings@^1.5.0:
 bip66@^1.1.5:
   version "1.1.5"
   resolved "https://registry.yarnpkg.com/bip66/-/bip66-1.1.5.tgz#01fa8748785ca70955d5011217d1b3139969ca22"
-  integrity sha1-AfqHSHhcpwlV1QESF9GzE5lpyiI=
+  integrity sha512-nemMHz95EmS38a26XbbdxIYj5csHd3RMP3H5bwQknX0WYHF01qhpufP42mLOwVICuH2JmhIhXiWs89MfUGL7Xw==
   dependencies:
     safe-buffer "^5.0.1"
 
@@ -3306,7 +3314,7 @@ buffer-indexof@^1.0.0:
 buffer-xor@^1.0.3:
   version "1.0.3"
   resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9"
-  integrity sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=
+  integrity sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==
 
 buffer@^4.3.0:
   version "4.9.2"
@@ -3338,7 +3346,7 @@ builtin-status-codes@^3.0.0:
 bytebuffer@^5.0.1:
   version "5.0.1"
   resolved "https://registry.yarnpkg.com/bytebuffer/-/bytebuffer-5.0.1.tgz#582eea4b1a873b6d020a48d58df85f0bba6cfddd"
-  integrity sha1-WC7qSxqHO20CCkjVjfhfC7ps/d0=
+  integrity sha512-IuzSdmADppkZ6DlpycMkm8l9zeEq16fWtLvunEwFiYciR/BHo4E8/xs5piFquG+Za8OWmMqHF8zuRviz2LHvRQ==
   dependencies:
     long "~3"
 
@@ -4070,9 +4078,9 @@ core-js-compat@^3.21.0, core-js-compat@^3.22.1:
     semver "7.0.0"
 
 core-js@^3.6.4:
-  version "3.15.2"
-  resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.15.2.tgz#740660d2ff55ef34ce664d7e2455119c5bdd3d61"
-  integrity sha512-tKs41J7NJVuaya8DxIOCnl8QuPHx5/ZVbFo1oKgVl1qHFBBrDctzQGtuLjPpRdNTWmKPH6oEvgN/MUID+l485Q==
+  version "3.34.0"
+  resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.34.0.tgz#5705e6ad5982678612e96987d05b27c6c7c274a5"
+  integrity sha512-aDdvlDder8QmY91H88GzNi9EtQi2TjvQhpCX6B1v/dAZHU1AuLgHvRh54RiOerpEhEW46Tkf+vgAViB/CWC0ag==
 
 core-util-is@1.0.2, core-util-is@~1.0.0:
   version "1.0.2"
@@ -4138,7 +4146,14 @@ cross-fetch@3.1.2:
   dependencies:
     node-fetch "2.6.1"
 
-cross-fetch@^3.0.4, cross-fetch@^3.0.6:
+cross-fetch@^3.0.4:
+  version "3.1.8"
+  resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.8.tgz#0327eba65fd68a7d119f8fb2bf9334a1a7956f82"
+  integrity sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg==
+  dependencies:
+    node-fetch "^2.6.12"
+
+cross-fetch@^3.0.6:
   version "3.1.5"
   resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.5.tgz#e1389f44d9e7ba767907f7af8454787952ab534f"
   integrity sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==
@@ -4898,7 +4913,7 @@ dotenv@^8.2.0:
 drbg.js@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/drbg.js/-/drbg.js-1.0.1.tgz#3e36b6c42b37043823cdbc332d58f31e2445480b"
-  integrity sha1-Pja2xCs3BDgjzbwzLVjzHiRFSAs=
+  integrity sha512-F4wZ06PvqxYLFEZKkFxTDcns9oFNk34hvmJSEwdzsxVQ8YI5YaxtACgQatkYgv2VI2CFkUd2Y+xosPQnHv809g==
   dependencies:
     browserify-aes "^1.0.6"
     create-hash "^1.1.2"
@@ -4932,6 +4947,14 @@ ecc-jsbn@~0.1.1:
     jsbn "~0.1.0"
     safer-buffer "^2.1.0"
 
+ecurve@^1.0.6:
+  version "1.0.6"
+  resolved "https://registry.yarnpkg.com/ecurve/-/ecurve-1.0.6.tgz#dfdabbb7149f8d8b78816be5a7d5b83fcf6de797"
+  integrity sha512-/BzEjNfiSuB7jIWKcS/z8FK9jNjmEWvUV2YZ4RLSmcDtP7Lq0m6FvDuSnJpBlDpGRpfRQeTLGLBI8H+kEv0r+w==
+  dependencies:
+    bigi "^1.1.0"
+    safe-buffer "^5.0.1"
+
 ee-first@1.1.1:
   version "1.1.1"
   resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
@@ -5399,9 +5422,9 @@ extsprintf@1.3.0:
   integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=
 
 extsprintf@^1.2.0:
-  version "1.4.0"
-  resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f"
-  integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8=
+  version "1.4.1"
+  resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.1.tgz#8d172c064867f235c0c84a596806d279bf4bcc07"
+  integrity sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA==
 
 fast-deep-equal@^3.1.1:
   version "3.1.3"
@@ -6119,7 +6142,7 @@ hivesigner@^3.2.8:
 hmac-drbg@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1"
-  integrity sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=
+  integrity sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==
   dependencies:
     hash.js "^1.0.3"
     minimalistic-assert "^1.0.0"
@@ -6227,6 +6250,11 @@ html-webpack-plugin@4.5.2:
     tapable "^1.1.3"
     util.promisify "1.0.0"
 
+html5-qrcode@^2.3.8:
+  version "2.3.8"
+  resolved "https://registry.yarnpkg.com/html5-qrcode/-/html5-qrcode-2.3.8.tgz#0b0cdf7a9926cfd4be530e13a51db47592adfa0d"
+  integrity sha512-jsr4vafJhwoLVEDW3n1KvPnCCXWaQfRng0/EEYk1vNcQGcG/htAdhJX0be8YyqMoSz7+hZvOZSTAepsabiuhiQ==
+
 htmlparser2@6.1.0, htmlparser2@^6.1.0:
   version "6.1.0"
   resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-6.1.0.tgz#c4d762b6c3371a05dbe65e94ae43a9f845fb8fb7"
@@ -7454,9 +7482,9 @@ js-yaml@^3.13.1:
     esprima "^4.0.0"
 
 jsbi@^3.1.4:
-  version "3.1.5"
-  resolved "https://registry.yarnpkg.com/jsbi/-/jsbi-3.1.5.tgz#70c2aaa2f75e1dc7604fed45298061ca23724046"
-  integrity sha512-w2BY0VOYC1ahe+w6Qhl4SFoPvPsZ9NPHY4bwass+LCgU7RK3PBoVQlQ3G1s7vI8W3CYyJiEXcbKF7FIM/L8q3Q==
+  version "3.2.5"
+  resolved "https://registry.yarnpkg.com/jsbi/-/jsbi-3.2.5.tgz#b37bb90e0e5c2814c1c2a1bcd8c729888a2e37d6"
+  integrity sha512-aBE4n43IPvjaddScbvWRA2YlTzKEynHzu7MqOyTipdHucf/VxS63ViCjxYRg86M8Rxwbt/GfzHl1kKERkt45fQ==
 
 jsbn@~0.1.0:
   version "0.1.1"
@@ -7806,7 +7834,7 @@ lolight@^1.4.0:
 long@~3:
   version "3.2.0"
   resolved "https://registry.yarnpkg.com/long/-/long-3.2.0.tgz#d821b7138ca1cb581c172990ef14db200b5c474b"
-  integrity sha1-2CG3E4yhy1gcFymQ7xTbIAtcR0s=
+  integrity sha512-ZYvPPOMqUwPoDsbJaR10iQJYnMuZhRTvHYl62ErLIEX7RgFlziSBUUvrt3OVfc47QlHHpzPZYP17g3Fv7oeJkg==
 
 loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.2.0, loose-envify@^1.3.1, loose-envify@^1.4.0:
   version "1.4.0"
@@ -8117,7 +8145,7 @@ minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1:
 minimalistic-crypto-utils@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a"
-  integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=
+  integrity sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==
 
 minimatch@3.0.4, minimatch@^3.0.4, minimatch@~3.0.2:
   version "3.0.4"
@@ -8285,11 +8313,16 @@ mute-stream@0.0.8:
   resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d"
   integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==
 
-nan@^2.12.1, nan@^2.13.2, nan@^2.14.0:
+nan@^2.12.1, nan@^2.13.2:
   version "2.14.2"
   resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.2.tgz#f5376400695168f4cc694ac9393d0c9585eeea19"
   integrity sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==
 
+nan@^2.14.0:
+  version "2.18.0"
+  resolved "https://registry.yarnpkg.com/nan/-/nan-2.18.0.tgz#26a6faae7ffbeb293a39660e88a76b82e30b7554"
+  integrity sha512-W7tfG7vMOGtD30sHoZSSc/JVYiyDPEyQVso/Zz+/uQd0B0L46gtC+pHha5FFMRpil6fm/AoEcRWyOVi4+E/f8w==
+
 nanoid@^3.1.22, nanoid@^3.1.23:
   version "3.2.0"
   resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.2.0.tgz#62667522da6673971cca916a6d3eff3f415ff80c"
@@ -8378,13 +8411,20 @@ node-fetch@2.6.1:
   resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052"
   integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==
 
-node-fetch@2.6.7, node-fetch@^2.6.0:
+node-fetch@2.6.7:
   version "2.6.7"
   resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad"
   integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==
   dependencies:
     whatwg-url "^5.0.0"
 
+node-fetch@^2.6.0, node-fetch@^2.6.12:
+  version "2.7.0"
+  resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d"
+  integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==
+  dependencies:
+    whatwg-url "^5.0.0"
+
 node-forge@^0.10.0:
   version "0.10.0"
   resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.10.0.tgz#32dea2afb3e9926f02ee5ce8794902691a676bf3"
@@ -10305,7 +10345,7 @@ read-pkg@^5.2.0:
     string_decoder "~1.1.1"
     util-deprecate "~1.0.1"
 
-readable-stream@^3.0.6, readable-stream@^3.6.0:
+readable-stream@^3.0.6:
   version "3.6.0"
   resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198"
   integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==
@@ -10314,6 +10354,15 @@ readable-stream@^3.0.6, readable-stream@^3.6.0:
     string_decoder "^1.1.1"
     util-deprecate "^1.0.1"
 
+readable-stream@^3.6.0:
+  version "3.6.2"
+  resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967"
+  integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==
+  dependencies:
+    inherits "^2.0.3"
+    string_decoder "^1.1.1"
+    util-deprecate "^1.0.1"
+
 readdirp@^2.2.1:
   version "2.2.1"
   resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525"
@@ -10705,7 +10754,7 @@ rimraf@^3.0.0, rimraf@^3.0.2:
   dependencies:
     glob "^7.1.3"
 
-ripemd160@^2.0.0, ripemd160@^2.0.1:
+ripemd160@^2.0.0, ripemd160@^2.0.1, ripemd160@^2.0.2:
   version "2.0.2"
   resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c"
   integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==
@@ -12001,7 +12050,7 @@ tr46@^2.1.0:
 tr46@~0.0.3:
   version "0.0.3"
   resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a"
-  integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=
+  integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==
 
 traverse@0.6.6:
   version "0.6.6"
@@ -12463,7 +12512,7 @@ vendors@^1.0.0:
   resolved "https://registry.yarnpkg.com/vendors/-/vendors-1.0.4.tgz#e2b800a53e7a29b93506c3cf41100d16c4c4ad8e"
   integrity sha512-/juG65kTL4Cy2su4P8HjtkTxk6VmJDiOPBufWniqQ6wknac6jNiXS9vU+hO3wgusiyqWlzTbVHi0dyJqRONg3w==
 
-verror@1.10.0, verror@^1.10.0:
+verror@1.10.0:
   version "1.10.0"
   resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400"
   integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=
@@ -12472,6 +12521,15 @@ verror@1.10.0, verror@^1.10.0:
     core-util-is "1.0.2"
     extsprintf "^1.2.0"
 
+verror@^1.10.0:
+  version "1.10.1"
+  resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.1.tgz#4bf09eeccf4563b109ed4b3d458380c972b0cdeb"
+  integrity sha512-veufcmxri4e3XSrT0xwfUR7kguIkaxBeosDg00yDWhk49wdwkSUrvvsm7nc75e1PUyvIeZj6nS8VQRYz2/S4Xg==
+  dependencies:
+    assert-plus "^1.0.0"
+    core-util-is "1.0.2"
+    extsprintf "^1.2.0"
+
 vm-browserify@^1.0.1:
   version "1.1.2"
   resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0"
@@ -12533,7 +12591,7 @@ wbuf@^1.1.0, wbuf@^1.7.3:
 webidl-conversions@^3.0.0:
   version "3.0.1"
   resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"
-  integrity sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=
+  integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==
 
 webidl-conversions@^5.0.0:
   version "5.0.0"
@@ -12738,9 +12796,9 @@ whatwg-encoding@^1.0.5:
     iconv-lite "0.4.24"
 
 whatwg-fetch@^3.0.0:
-  version "3.6.2"
-  resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz#dced24f37f2624ed0281725d51d0e2e3fe677f8c"
-  integrity sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA==
+  version "3.6.19"
+  resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.6.19.tgz#caefd92ae630b91c07345537e67f8354db470973"
+  integrity sha512-d67JP4dHSbm2TrpFj8AbO8DnL1JXL5J9u0Kq2xW6d0TFDbCA3Muhdt8orXC22utleTVj7Prqt82baN6RBvnEgw==
 
 whatwg-mimetype@^2.3.0:
   version "2.3.0"
@@ -12750,7 +12808,7 @@ whatwg-mimetype@^2.3.0:
 whatwg-url@^5.0.0:
   version "5.0.0"
   resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d"
-  integrity sha1-lmRU6HZUYuN2RNNib2dCzotwll0=
+  integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==
   dependencies:
     tr46 "~0.0.3"
     webidl-conversions "^3.0.0"

Posted with proof of brain

H2
H3
H4
3 columns
2 columns
1 column
Join the conversation now
Logo
Center