diff --git a/web/src/auth/Web3Auth.js b/web/src/auth/Web3Auth.js
new file mode 100644
index 00000000..5c59cd8c
--- /dev/null
+++ b/web/src/auth/Web3Auth.js
@@ -0,0 +1,149 @@
+// // Copyright 2023 The Casdoor Authors. All Rights Reserved.
+// //
+// // Licensed under the Apache License, Version 2.0 (the "License");
+// // you may not use this file except in compliance with the License.
+// // You may obtain a copy of the License at
+// //
+// // http://www.apache.org/licenses/LICENSE-2.0
+// //
+// // Unless required by applicable law or agreed to in writing, software
+// // distributed under the License is distributed on an "AS IS" BASIS,
+// // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// // See the License for the specific language governing permissions and
+// // limitations under the License.
+
+import {goToLink, showMessage} from "../Setting";
+import i18next from "i18next";
+import {v4 as uuidv4} from "uuid";
+import {SignTypedDataVersion, recoverTypedSignature} from "@metamask/eth-sig-util";
+import {getAuthUrl} from "./Provider";
+import {Buffer} from "buffer";
+// import {toChecksumAddress} from "ethereumjs-util";
+global.Buffer = Buffer;
+
+export function generateNonce() {
+ const nonce = uuidv4();
+ return nonce;
+}
+
+export function getWeb3AuthTokenKey(address) {
+ return `Web3AuthToken_${address}`;
+}
+
+export function setWeb3AuthToken(token) {
+ const key = getWeb3AuthTokenKey(token.address);
+ localStorage.setItem(key, JSON.stringify(token));
+}
+
+export function getWeb3AuthToken(address) {
+ const key = getWeb3AuthTokenKey(address);
+ return JSON.parse(localStorage.getItem(key));
+}
+
+export function delWeb3AuthToken(address) {
+ const key = getWeb3AuthTokenKey(address);
+ localStorage.removeItem(key);
+}
+
+export function clearWeb3AuthToken() {
+ const keys = Object.keys(localStorage);
+ keys.forEach(key => {
+ if (key.startsWith("Web3AuthToken_")) {
+ localStorage.removeItem(key);
+ }
+ });
+}
+
+export function detectMetaMaskPlugin() {
+ // check if ethereum extension MetaMask is installed
+ return window.ethereum && window.ethereum.isMetaMask;
+}
+
+export function requestEthereumAccount() {
+ const method = "eth_requestAccounts";
+ const selectedAccount = window.ethereum.request({method})
+ .then((accounts) => {
+ return accounts[0];
+ });
+ return selectedAccount;
+}
+
+export function signEthereumTypedData(from, nonce) {
+ // https://docs.metamask.io/wallet/how-to/sign-data/
+ const date = new Date();
+ const typedData = JSON.stringify({
+ domain: {
+ chainId: window.ethereum.chainId,
+ name: "Casdoor",
+ version: "1",
+ },
+ message: {
+ prompt: "In order to authenticate to this website, sign this request and your public address will be sent to the server in a verifiable way.",
+ nonce: nonce,
+ createAt: `${date.toLocaleString()}`,
+ },
+ primaryType: "AuthRequest",
+ types: {
+ EIP712Domain: [
+ {name: "name", type: "string"},
+ {name: "version", type: "string"},
+ {name: "chainId", type: "uint256"},
+ ],
+ AuthRequest: [
+ {name: "prompt", type: "string"},
+ {name: "nonce", type: "string"},
+ {name: "createAt", type: "string"},
+ ],
+ },
+ });
+
+ const method = "eth_signTypedData_v4";
+ const params = [from, typedData];
+
+ return window.ethereum.request({method, params})
+ .then((sign) => {
+ return {
+ address: from,
+ createAt: Math.floor(date.getTime() / 1000),
+ typedData: typedData,
+ signature: sign,
+ };
+ });
+}
+
+export function checkEthereumSignedTypedData(token) {
+ if (token === undefined || token === null) {
+ return false;
+ }
+ if (token.address && token.typedData && token.signature) {
+ const recoveredAddr = recoverTypedSignature({
+ data: JSON.parse(token.typedData),
+ signature: token.signature,
+ version: SignTypedDataVersion.V4,
+ });
+ // const recoveredAddr = token.address;
+ return recoveredAddr === token.address;
+ // return toChecksumAddress(recoveredAddr) === toChecksumAddress(token.address);
+ }
+ return false;
+}
+
+export async function authViaMetaMask(application, provider, method) {
+ if (!detectMetaMaskPlugin()) {
+ showMessage("error", `${i18next.t("login:MetaMask plugin not detected")}`);
+ return;
+ }
+ try {
+ const account = await requestEthereumAccount();
+ let token = getWeb3AuthToken(account);
+ if (!checkEthereumSignedTypedData(token)) {
+ const nonce = generateNonce();
+ token = await signEthereumTypedData(account, nonce);
+ setWeb3AuthToken(token);
+ }
+ const redirectUri = `${getAuthUrl(application, provider, method)}&web3AuthTokenKey=${getWeb3AuthTokenKey(account)}`;
+ goToLink(redirectUri);
+ } catch (err) {
+ showMessage("error", `${i18next.t("login:Failed to obtain MetaMask authorization")}: ${err.message}`);
+ }
+}
diff --git a/web/src/common/OAuthWidget.js b/web/src/common/OAuthWidget.js
index 5c93ea56..d61fc97f 100644
--- a/web/src/common/OAuthWidget.js
+++ b/web/src/common/OAuthWidget.js
@@ -19,6 +19,9 @@ import * as UserBackend from "../backend/UserBackend";
import * as Setting from "../Setting";
import * as Provider from "../auth/Provider";
import * as AuthBackend from "../auth/AuthBackend";
+import {goToWeb3Url} from "../auth/ProviderButton";
+import {delWeb3AuthToken} from "../auth/Web3Auth";
+import AccountAvatar from "../account/AccountAvatar";
class OAuthWidget extends React.Component {
constructor(props) {
@@ -88,12 +91,15 @@ class OAuthWidget extends React.Component {
return user.properties[key];
}
- unlinkUser(providerType) {
+ unlinkUser(providerType, linkedValue) {
const body = {
providerType: providerType,
// should add the unlink user's info, cause the user may not be logged in, but a admin want to unlink the user.
user: this.props.user,
};
+ if (providerType === "MetaMask") {
+ delWeb3AuthToken(linkedValue);
+ }
AuthBackend.unlink(body)
.then((res) => {
if (res.status === "ok") {
@@ -151,7 +157,7 @@ class OAuthWidget extends React.Component {
-

+
{
linkedValue === "" ? (
@@ -169,11 +175,15 @@ class OAuthWidget extends React.Component {
{
linkedValue === "" ? (
-
-
-
+ provider.category === "Web3" ? (
+
+ ) : (
+
+
+
+ )
) : (
-
+
)
}
diff --git a/web/src/locales/de/data.json b/web/src/locales/de/data.json
index a5b8c3fd..8be8f12f 100644
--- a/web/src/locales/de/data.json
+++ b/web/src/locales/de/data.json
@@ -392,9 +392,11 @@
"Auto sign in": "Automatische Anmeldung",
"Continue with": "Weitermachen mit",
"Email or phone": "E-Mail oder Telefon",
+ "Failed to obtain MetaMask authorization": "Failed to obtain MetaMask authorization",
"Forgot password?": "Passwort vergessen?",
"Loading": "Laden",
"Logging out...": "Ausloggen...",
+ "MetaMask plugin not detected": "MetaMask plugin not detected",
"No account?": "Kein Konto?",
"Or sign in with another account": "Oder mit einem anderen Konto anmelden",
"Please input your Email or Phone!": "Bitte geben Sie Ihre E-Mail oder Telefonnummer ein!",
diff --git a/web/src/locales/en/data.json b/web/src/locales/en/data.json
index a55d4936..3de3127e 100644
--- a/web/src/locales/en/data.json
+++ b/web/src/locales/en/data.json
@@ -392,9 +392,11 @@
"Auto sign in": "Auto sign in",
"Continue with": "Continue with",
"Email or phone": "Email or phone",
+ "Failed to obtain MetaMask authorization": "Failed to obtain MetaMask authorization",
"Forgot password?": "Forgot password?",
"Loading": "Loading",
"Logging out...": "Logging out...",
+ "MetaMask plugin not detected": "MetaMask plugin not detected",
"No account?": "No account?",
"Or sign in with another account": "Or sign in with another account",
"Please input your Email or Phone!": "Please input your Email or Phone!",
diff --git a/web/src/locales/es/data.json b/web/src/locales/es/data.json
index 0450651e..2dd937ef 100644
--- a/web/src/locales/es/data.json
+++ b/web/src/locales/es/data.json
@@ -392,9 +392,11 @@
"Auto sign in": "Inicio de sesión automático",
"Continue with": "Continúe con",
"Email or phone": "Correo electrónico o teléfono",
+ "Failed to obtain MetaMask authorization": "Failed to obtain MetaMask authorization",
"Forgot password?": "¿Olvidaste tu contraseña?",
"Loading": "Cargando",
"Logging out...": "Cerrando sesión...",
+ "MetaMask plugin not detected": "MetaMask plugin not detected",
"No account?": "¿No tienes cuenta?",
"Or sign in with another account": "O inicia sesión con otra cuenta",
"Please input your Email or Phone!": "¡Por favor introduzca su correo electrónico o teléfono!",
diff --git a/web/src/locales/fr/data.json b/web/src/locales/fr/data.json
index fa962b96..c9353bc8 100644
--- a/web/src/locales/fr/data.json
+++ b/web/src/locales/fr/data.json
@@ -392,9 +392,11 @@
"Auto sign in": "Connexion automatique",
"Continue with": "Continuer avec",
"Email or phone": "Email ou téléphone",
+ "Failed to obtain MetaMask authorization": "Failed to obtain MetaMask authorization",
"Forgot password?": "Mot de passe oublié ?",
"Loading": "Chargement",
"Logging out...": "Déconnexion...",
+ "MetaMask plugin not detected": "MetaMask plugin not detected",
"No account?": "Aucun compte ?",
"Or sign in with another account": "Ou connectez-vous avec un autre compte",
"Please input your Email or Phone!": "S'il vous plaît, entrez votre adresse e-mail ou votre numéro de téléphone !",
diff --git a/web/src/locales/id/data.json b/web/src/locales/id/data.json
index 91b03040..fde7488b 100644
--- a/web/src/locales/id/data.json
+++ b/web/src/locales/id/data.json
@@ -392,9 +392,11 @@
"Auto sign in": "Masuk otomatis",
"Continue with": "Lanjutkan dengan",
"Email or phone": "Email atau telepon",
+ "Failed to obtain MetaMask authorization": "Failed to obtain MetaMask authorization",
"Forgot password?": "Lupa kata sandi?",
"Loading": "Memuat",
"Logging out...": "Keluar...",
+ "MetaMask plugin not detected": "MetaMask plugin not detected",
"No account?": "Tidak memiliki akun?",
"Or sign in with another account": "Atau masuk dengan akun lain",
"Please input your Email or Phone!": "Silahkan masukkan email atau nomor telepon Anda!",
diff --git a/web/src/locales/ja/data.json b/web/src/locales/ja/data.json
index 078d76f8..17b14f99 100644
--- a/web/src/locales/ja/data.json
+++ b/web/src/locales/ja/data.json
@@ -392,9 +392,11 @@
"Auto sign in": "自動サインイン",
"Continue with": "続ける",
"Email or phone": "メールまたは電話",
+ "Failed to obtain MetaMask authorization": "Failed to obtain MetaMask authorization",
"Forgot password?": "パスワードを忘れましたか?",
"Loading": "ローディング",
"Logging out...": "ログアウト中...",
+ "MetaMask plugin not detected": "MetaMask plugin not detected",
"No account?": "アカウントがありませんか?",
"Or sign in with another account": "別のアカウントでサインインする",
"Please input your Email or Phone!": "あなたのメールアドレスまたは電話番号を入力してください!",
diff --git a/web/src/locales/ko/data.json b/web/src/locales/ko/data.json
index 90716d0b..38c1747f 100644
--- a/web/src/locales/ko/data.json
+++ b/web/src/locales/ko/data.json
@@ -392,9 +392,11 @@
"Auto sign in": "자동 로그인",
"Continue with": "계속하다",
"Email or phone": "이메일 또는 전화",
+ "Failed to obtain MetaMask authorization": "Failed to obtain MetaMask authorization",
"Forgot password?": "비밀번호를 잊으셨나요?",
"Loading": "로딩 중입니다",
"Logging out...": "로그아웃 중...",
+ "MetaMask plugin not detected": "MetaMask plugin not detected",
"No account?": "계정이 없나요?",
"Or sign in with another account": "다른 계정으로 로그인하세요",
"Please input your Email or Phone!": "이메일 또는 전화번호를 입력해주세요!",
diff --git a/web/src/locales/pt/data.json b/web/src/locales/pt/data.json
index efa1779c..f1cb2506 100644
--- a/web/src/locales/pt/data.json
+++ b/web/src/locales/pt/data.json
@@ -392,9 +392,11 @@
"Auto sign in": "Entrar automaticamente",
"Continue with": "Continuar com",
"Email or phone": "Email ou telefone",
+ "Failed to obtain MetaMask authorization": "Failed to obtain MetaMask authorization",
"Forgot password?": "Esqueceu a senha?",
"Loading": "Carregando",
"Logging out...": "Saindo...",
+ "MetaMask plugin not detected": "MetaMask plugin not detected",
"No account?": "Não possui uma conta?",
"Or sign in with another account": "Ou entre com outra conta",
"Please input your Email or Phone!": "Por favor, informe seu email ou telefone!",
diff --git a/web/src/locales/ru/data.json b/web/src/locales/ru/data.json
index 49670c2f..5661e346 100644
--- a/web/src/locales/ru/data.json
+++ b/web/src/locales/ru/data.json
@@ -392,9 +392,11 @@
"Auto sign in": "Автоматическая авторизация",
"Continue with": "Продолжайте с",
"Email or phone": "Электронная почта или телефон",
+ "Failed to obtain MetaMask authorization": "Failed to obtain MetaMask authorization",
"Forgot password?": "Забыли пароль?",
"Loading": "Загрузка",
"Logging out...": "Выход...",
+ "MetaMask plugin not detected": "MetaMask plugin not detected",
"No account?": "Нет аккаунта?",
"Or sign in with another account": "Или войти с другой учетной записью",
"Please input your Email or Phone!": "Пожалуйста, введите свой адрес электронной почты или номер телефона!",
diff --git a/web/src/locales/vi/data.json b/web/src/locales/vi/data.json
index 63b51429..696c6a62 100644
--- a/web/src/locales/vi/data.json
+++ b/web/src/locales/vi/data.json
@@ -392,9 +392,11 @@
"Auto sign in": "Tự động đăng nhập",
"Continue with": "Tiếp tục với",
"Email or phone": "Email hoặc điện thoại",
+ "Failed to obtain MetaMask authorization": "Failed to obtain MetaMask authorization",
"Forgot password?": "Quên mật khẩu?",
"Loading": "Đang tải",
"Logging out...": "Đăng xuất ...",
+ "MetaMask plugin not detected": "MetaMask plugin not detected",
"No account?": "Không có tài khoản?",
"Or sign in with another account": "Hoặc đăng nhập bằng tài khoản khác",
"Please input your Email or Phone!": "Vui lòng nhập địa chỉ Email hoặc số điện thoại của bạn!",
diff --git a/web/src/locales/zh/data.json b/web/src/locales/zh/data.json
index 5eb9f7b1..ab75d3a2 100644
--- a/web/src/locales/zh/data.json
+++ b/web/src/locales/zh/data.json
@@ -392,9 +392,11 @@
"Auto sign in": "下次自动登录",
"Continue with": "使用以下账号继续",
"Email or phone": "Email或手机号",
+ "Failed to obtain MetaMask authorization": "获取MetaMask授权失败",
"Forgot password?": "忘记密码?",
"Loading": "加载中",
"Logging out...": "正在退出登录...",
+ "MetaMask plugin not detected": "未检测到MetaMask插件",
"No account?": "没有账号?",
"Or sign in with another account": "或者,登录其他账号",
"Please input your Email or Phone!": "请输入您的Email或手机号!",
@@ -746,6 +748,8 @@
"Token URL - Tooltip": "自定义OAuth的Token URL",
"Type": "类型",
"Type - Tooltip": "类型",
+ "User mapping": "User mapping",
+ "User mapping - Tooltip": "User mapping - Tooltip",
"UserInfo URL": "UserInfo URL",
"UserInfo URL - Tooltip": "自定义OAuth的UserInfo URL",
"admin (Shared)": "admin(共享)"
diff --git a/web/src/table/ProviderTable.js b/web/src/table/ProviderTable.js
index 101683a8..6899816d 100644
--- a/web/src/table/ProviderTable.js
+++ b/web/src/table/ProviderTable.js
@@ -110,7 +110,7 @@ class ProviderTable extends React.Component {
key: "canSignUp",
width: "120px",
render: (text, record, index) => {
- if (record.provider?.category !== "OAuth") {
+ if (!["OAuth", "Web3"].includes(record.provider?.category)) {
return null;
}
@@ -127,7 +127,7 @@ class ProviderTable extends React.Component {
key: "canSignIn",
width: "120px",
render: (text, record, index) => {
- if (record.provider?.category !== "OAuth") {
+ if (!["OAuth", "Web3"].includes(record.provider?.category)) {
return null;
}
@@ -144,7 +144,7 @@ class ProviderTable extends React.Component {
key: "canUnlink",
width: "120px",
render: (text, record, index) => {
- if (record.provider?.category !== "OAuth") {
+ if (!["OAuth", "Web3"].includes(record.provider?.category)) {
return null;
}
@@ -161,7 +161,7 @@ class ProviderTable extends React.Component {
key: "prompted",
width: "120px",
render: (text, record, index) => {
- if (record.provider?.category !== "OAuth") {
+ if (!["OAuth", "Web3"].includes(record.provider?.category)) {
return null;
}
diff --git a/web/yarn.lock b/web/yarn.lock
index 1e5aa7a8..5b868403 100644
--- a/web/yarn.lock
+++ b/web/yarn.lock
@@ -173,7 +173,7 @@
lru-cache "^5.1.1"
semver "^6.3.0"
-"@babel/helper-create-class-features-plugin@^7.18.6", "@babel/helper-create-class-features-plugin@^7.21.0", "@babel/helper-create-class-features-plugin@^7.22.5":
+"@babel/helper-create-class-features-plugin@^7.18.6", "@babel/helper-create-class-features-plugin@^7.22.5":
version "7.22.5"
resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.22.5.tgz#2192a1970ece4685fbff85b48da2c32fcb130b7c"
integrity sha512-xkb58MyOYIslxu3gKmVXmjTtUPvBU4odYzbiIQbWwLKIHCsx6UGZGX6F1IznMFVnDdirseUZopzN+ZRt8Xb33Q==
@@ -433,16 +433,6 @@
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz#7844f9289546efa9febac2de4cfe358a050bd703"
integrity sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==
-"@babel/plugin-proposal-private-property-in-object@^7.21.11":
- version "7.21.11"
- resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.11.tgz#69d597086b6760c4126525cfa154f34631ff272c"
- integrity sha512-0QZ8qP/3RLDVBwBFoWAwCtgcDZJVwA5LUJRZU8x2YFfKNuFq161wK3cuGrALu5yiPu+vzwTAg/sMWVNeWeNyaw==
- dependencies:
- "@babel/helper-annotate-as-pure" "^7.18.6"
- "@babel/helper-create-class-features-plugin" "^7.21.0"
- "@babel/helper-plugin-utils" "^7.20.2"
- "@babel/plugin-syntax-private-property-in-object" "^7.14.5"
-
"@babel/plugin-proposal-unicode-property-regex@^7.4.4":
version "7.18.6"
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz#af613d2cd5e643643b65cded64207b15c85cb78e"
@@ -1590,6 +1580,20 @@
resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.43.0.tgz#559ca3d9ddbd6bf907ad524320a0d14b85586af0"
integrity sha512-s2UHCoiXfxMvmfzqoN+vrQ84ahUSYde9qNO1MdxmoEhyHWsfmwOpFlwYV+ePJEVc7gFnATGUi376WowX1N7tFg==
+"@ethereumjs/rlp@^4.0.1":
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/@ethereumjs/rlp/-/rlp-4.0.1.tgz#626fabfd9081baab3d0a3074b0c7ecaf674aaa41"
+ integrity sha512-tqsQiBQDQdmPWE1xkkBq4rlSW5QZpLOUJ5RJh2/9fug+q9tnUhuZoVLk7s0scUIKTOzEtR72DFBXI4WiZcMpvw==
+
+"@ethereumjs/util@^8.0.6":
+ version "8.1.0"
+ resolved "https://registry.yarnpkg.com/@ethereumjs/util/-/util-8.1.0.tgz#299df97fb6b034e0577ce9f94c7d9d1004409ed4"
+ integrity sha512-zQ0IqbdX8FZ9aw11vP+dZkKDkS+kgIvQPHnSAXzP9pLu+Rfu3D3XEeLbicvoXJTYnhZiPmsZUxgdzXwNKxRPbA==
+ dependencies:
+ "@ethereumjs/rlp" "^4.0.1"
+ ethereum-cryptography "^2.0.0"
+ micro-ftch "^0.3.1"
+
"@humanwhocodes/config-array@^0.10.4":
version "0.10.7"
resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.10.7.tgz#6d53769fd0c222767e6452e8ebda825c22e9f0dc"
@@ -1931,6 +1935,18 @@
resolved "https://registry.yarnpkg.com/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz#b2ac626d6cb9c8718ab459166d4bb405b8ffa78b"
integrity sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==
+"@metamask/eth-sig-util@^6.0.0":
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/@metamask/eth-sig-util/-/eth-sig-util-6.0.0.tgz#083321dc7285a9aa6e066db7c49be6e94c5e03a3"
+ integrity sha512-M0ezVz8lirXG1P6rHPzx+9i4zfhebCgVHE8XQT8VWxy/eUWllHQGcBcE8QmOusC7su55M4CMr9AyMIu0lx452g==
+ dependencies:
+ "@ethereumjs/util" "^8.0.6"
+ bn.js "^4.12.0"
+ ethereum-cryptography "^2.0.0"
+ ethjs-util "^0.1.6"
+ tweetnacl "^1.0.3"
+ tweetnacl-util "^0.15.1"
+
"@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1":
version "5.1.1-v1"
resolved "https://registry.yarnpkg.com/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz#dbf733a965ca47b1973177dc0bb6c889edcfb129"
@@ -1938,6 +1954,18 @@
dependencies:
eslint-scope "5.1.1"
+"@noble/curves@1.1.0", "@noble/curves@~1.1.0":
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.1.0.tgz#f13fc667c89184bc04cccb9b11e8e7bae27d8c3d"
+ integrity sha512-091oBExgENk/kGj3AZmtBDMpxQPDtxQABR2B9lb1JbVTs6ytdzZNwvhxQ4MWasRNEzlbEH8jCWFCwhF/Obj5AA==
+ dependencies:
+ "@noble/hashes" "1.3.1"
+
+"@noble/hashes@1.3.1", "@noble/hashes@~1.3.0", "@noble/hashes@~1.3.1":
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.1.tgz#8831ef002114670c603c458ab8b11328406953a9"
+ integrity sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA==
+
"@nodelib/fs.scandir@2.1.5":
version "2.1.5"
resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5"
@@ -2094,6 +2122,28 @@
resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.3.2.tgz#31b9c510d8cada9683549e1dbb4284cca5001faf"
integrity sha512-V+MvGwaHH03hYhY+k6Ef/xKd6RYlc4q8WBx+2ANmipHJcKuktNcI/NgEsJgdSUF6Lw32njT6OnrRsKYCdgHjYw==
+"@scure/base@~1.1.0":
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.1.tgz#ebb651ee52ff84f420097055f4bf46cfba403938"
+ integrity sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA==
+
+"@scure/bip32@1.3.1":
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.3.1.tgz#7248aea723667f98160f593d621c47e208ccbb10"
+ integrity sha512-osvveYtyzdEVbt3OfwwXFr4P2iVBL5u1Q3q4ONBfDY/UpOuXmOlbgwc1xECEboY8wIays8Yt6onaWMUdUbfl0A==
+ dependencies:
+ "@noble/curves" "~1.1.0"
+ "@noble/hashes" "~1.3.1"
+ "@scure/base" "~1.1.0"
+
+"@scure/bip39@1.2.1":
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.2.1.tgz#5cee8978656b272a917b7871c981e0541ad6ac2a"
+ integrity sha512-Z3/Fsz1yr904dduJD0NpiyRHhRYHdcnyh73FZWiV+/qhWi83wNJ3NWolYqCEN+ZWsUz2TWwajJggcRE9r1zUYg==
+ dependencies:
+ "@noble/hashes" "~1.3.0"
+ "@scure/base" "~1.1.0"
+
"@sheerun/mutationobserver-shim@^0.3.2":
version "0.3.3"
resolved "https://registry.yarnpkg.com/@sheerun/mutationobserver-shim/-/mutationobserver-shim-0.3.3.tgz#5405ee8e444ed212db44e79351f0c70a582aae25"
@@ -3674,6 +3724,11 @@ bluebird@^3.5.5, bluebird@^3.7.2:
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f"
integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==
+bn.js@^4.12.0:
+ version "4.12.0"
+ resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88"
+ integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==
+
body-parser@1.20.1:
version "1.20.1"
resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.1.tgz#b1812a8912c195cd371a3ee5e66faa2338a5c668"
@@ -3769,6 +3824,14 @@ buffer@^5.6.0:
base64-js "^1.3.1"
ieee754 "^1.1.13"
+buffer@^6.0.3:
+ version "6.0.3"
+ resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6"
+ integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==
+ dependencies:
+ base64-js "^1.3.1"
+ ieee754 "^1.2.1"
+
builtin-modules@^3.1.0:
version "3.3.0"
resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.3.0.tgz#cae62812b89801e9656336e46223e030386be7b6"
@@ -5480,6 +5543,24 @@ etag@~1.8.1:
resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==
+ethereum-cryptography@^2.0.0:
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-2.1.2.tgz#18fa7108622e56481157a5cb7c01c0c6a672eb67"
+ integrity sha512-Z5Ba0T0ImZ8fqXrJbpHcbpAvIswRte2wGNR/KePnu8GbbvgJ47lMxT/ZZPG6i9Jaht4azPDop4HaM00J0J59ug==
+ dependencies:
+ "@noble/curves" "1.1.0"
+ "@noble/hashes" "1.3.1"
+ "@scure/bip32" "1.3.1"
+ "@scure/bip39" "1.2.1"
+
+ethjs-util@^0.1.6:
+ version "0.1.6"
+ resolved "https://registry.yarnpkg.com/ethjs-util/-/ethjs-util-0.1.6.tgz#f308b62f185f9fe6237132fb2a9818866a5cd536"
+ integrity sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==
+ dependencies:
+ is-hex-prefixed "1.0.0"
+ strip-hex-prefix "1.0.0"
+
eventemitter2@6.4.7:
version "6.4.7"
resolved "https://registry.yarnpkg.com/eventemitter2/-/eventemitter2-6.4.7.tgz#a7f6c4d7abf28a14c1ef3442f21cb306a054271d"
@@ -6463,7 +6544,7 @@ identity-obj-proxy@^3.0.0:
dependencies:
harmony-reflect "^1.4.6"
-ieee754@^1.1.13:
+ieee754@^1.1.13, ieee754@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352"
integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==
@@ -6668,6 +6749,11 @@ is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1:
dependencies:
is-extglob "^2.1.1"
+is-hex-prefixed@1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz#7d8d37e6ad77e5d127148913c573e082d777f554"
+ integrity sha512-WvtOiug1VFrE9v1Cydwm+FnXd3+w9GaeVUss5W4v/SLy3UW00vP+6iNF2SdnfiBoLy4bTqVdkftNGTUeOFVsbA==
+
is-installed-globally@~0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-0.4.0.tgz#9a0fd407949c30f86eb6959ef1b7994ed0b7b520"
@@ -7978,6 +8064,11 @@ methods@~1.1.2:
resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==
+micro-ftch@^0.3.1:
+ version "0.3.1"
+ resolved "https://registry.yarnpkg.com/micro-ftch/-/micro-ftch-0.3.1.tgz#6cb83388de4c1f279a034fb0cf96dfc050853c5f"
+ integrity sha512-/0LLxhzP0tfiR5hcQebtudP56gUurs2CLkGarnCiB/OqEyUFQ6U3paQi/tgLv0hBJYt2rnr9MNpxz4fiiugstg==
+
micromatch@^4.0.2, micromatch@^4.0.4, micromatch@^4.0.5:
version "4.0.5"
resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6"
@@ -10150,6 +10241,11 @@ react-is@^18.0.0:
resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b"
integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==
+react-metamask-avatar@^1.2.1:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/react-metamask-avatar/-/react-metamask-avatar-1.2.1.tgz#f0623e00ebc90ec24b8ac91cad3a25f653e7bc25"
+ integrity sha512-EQhaW27PdqGKLxCnDgpCTWnEs1bjba+l5b/ZQc1V/GSWrCznAcrQ2HrcjSPgmuud2rvDChYyrzgRB5sBU33gSw==
+
react-refresh@^0.11.0:
version "0.11.0"
resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.11.0.tgz#77198b944733f0f1f1a90e791de4541f9f074046"
@@ -11194,6 +11290,13 @@ strip-final-newline@^3.0.0:
resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-3.0.0.tgz#52894c313fbff318835280aed60ff71ebf12b8fd"
integrity sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==
+strip-hex-prefix@1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz#0c5f155fef1151373377de9dbb588da05500e36f"
+ integrity sha512-q8d4ue7JGEiVcypji1bALTos+0pWtyGlivAWyPuTkHzuTCJqrK9sWxYQZUq6Nq3cuyv3bm734IhHvHtGGURU6A==
+ dependencies:
+ is-hex-prefixed "1.0.0"
+
strip-indent@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-3.0.0.tgz#c32e1cee940b6b3432c771bc2c54bcce73cd3001"
@@ -11731,11 +11834,21 @@ tunnel-agent@^0.6.0:
dependencies:
safe-buffer "^5.0.1"
+tweetnacl-util@^0.15.1:
+ version "0.15.1"
+ resolved "https://registry.yarnpkg.com/tweetnacl-util/-/tweetnacl-util-0.15.1.tgz#b80fcdb5c97bcc508be18c44a4be50f022eea00b"
+ integrity sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw==
+
tweetnacl@^0.14.3, tweetnacl@~0.14.0:
version "0.14.5"
resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
integrity sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==
+tweetnacl@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-1.0.3.tgz#ac0af71680458d8a6378d0d0d050ab1407d35596"
+ integrity sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==
+
type-check@^0.4.0, type-check@~0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1"