Leprechaun avatar

Logon to ProofofBrain with a QR Code

leprechaun

Published: 09 Dec 2023 › Updated: 09 Dec 2023Logon to ProofofBrain with a QR Code

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

Leave Logon to ProofofBrain with a QR Code to:

Written by

An Economist, a Coder and a Carbonist. Author of https://Steemfiles.com, Author of https://ProofofBrain.blog Carbonist community admin (https://www.proofofbrain.blog/created/hive-139995). Discord: leprechaun#2185 Email: theleprechaun2022@steemfiles.com Lover of freedom

Read more #hive-139531 posts


Best Posts From Leprechaun

We have not curated any of leprechaun's posts yet. But you can encourage our curation team to review posts by visiting them regularly and by referring other readers. Because we give priority to frequently read content.

More Posts From Leprechaun