Handle subscriber ID check in nitro key signature page
This commit is contained in:
parent
76e9f996a3
commit
04b2eeb77a
@ -12,7 +12,6 @@
|
||||
"@mui/material": "^5.15.14",
|
||||
"@sumsub/websdk": "^2.3.1",
|
||||
"@sumsub/websdk-react": "^2.3.1",
|
||||
"@types/jsonwebtoken": "^9.0.6",
|
||||
"@walletconnect/encoding": "^1.0.2",
|
||||
"@walletconnect/modal": "^2.6.2",
|
||||
"@walletconnect/sign-client": "^2.11.3",
|
||||
@ -24,7 +23,7 @@
|
||||
"crypto-browserify": "^3.12.0",
|
||||
"ethers": "5.7.2",
|
||||
"https-browserify": "^1.0.0",
|
||||
"jsonwebtoken": "^9.0.2",
|
||||
"jwt-decode": "^4.0.0",
|
||||
"notistack": "^3.0.1",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
|
@ -12,7 +12,8 @@ import TermsAndConditions from "./pages/TermsAndConditions";
|
||||
import Header from "./components/Header";
|
||||
import { WalletConnectProvider } from "./context/WalletConnectContext";
|
||||
import VerifyEmail from "./pages/VerifyEmail";
|
||||
import RedirectEmail from "./pages/RedirectEmail";
|
||||
import Email from "./pages/Email";
|
||||
import Thanks from "./pages/Thanks";
|
||||
|
||||
function App() {
|
||||
return (
|
||||
@ -22,8 +23,9 @@ function App() {
|
||||
<Routes>
|
||||
<Route path="/" element={<TermsAndConditions />} />
|
||||
<Route path="/verify-email" element={<VerifyEmail />} />
|
||||
<Route path="/email" element={<RedirectEmail/>} />
|
||||
<Route path="/email" element={<Email/>} />
|
||||
<Route path="/connect-wallet" element={<ConnectWallet />} />
|
||||
<Route path="/thanks" element={<Thanks />} />
|
||||
<Route element={<SignPageLayout />}>
|
||||
<Route path="/sign-with-nitro-key" element={<SignWithNitroKey />} />
|
||||
<Route
|
||||
|
@ -12,23 +12,14 @@ const ConnectWallet = () => {
|
||||
const navigate = useNavigate();
|
||||
const location = useLocation();
|
||||
|
||||
const {kycIdHash} = location.state as {
|
||||
kycIdHash?: string
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (!kycIdHash) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (session) {
|
||||
navigate("/sign-with-nitro-key", {
|
||||
state: {
|
||||
kycIdHash
|
||||
}
|
||||
state: location.state
|
||||
});
|
||||
}
|
||||
}, [session, navigate, kycIdHash]);
|
||||
}, [session, navigate, location]);
|
||||
|
||||
const handler = async () => {
|
||||
await connect();
|
||||
@ -36,7 +27,6 @@ const ConnectWallet = () => {
|
||||
|
||||
return (
|
||||
<Container maxWidth="lg">
|
||||
{kycIdHash ? <>
|
||||
<Box
|
||||
display="flex"
|
||||
flexDirection="column"
|
||||
@ -70,26 +60,6 @@ const ConnectWallet = () => {
|
||||
Connect Wallet
|
||||
</Button>
|
||||
</Box>
|
||||
</> : <Box
|
||||
display="flex"
|
||||
flexDirection="column"
|
||||
alignItems="center"
|
||||
justifyContent="center"
|
||||
marginTop={10}
|
||||
sx={{
|
||||
border: 1,
|
||||
borderColor: 'grey.500',
|
||||
}}
|
||||
padding={5}
|
||||
>
|
||||
<Typography variant="h5" component="h1" gutterBottom color={colors.red[400]}>
|
||||
Error
|
||||
</Typography>
|
||||
<Typography variant="body1">
|
||||
KYC ID not found. Please verify your email and try again
|
||||
</Typography>
|
||||
</Box>
|
||||
}
|
||||
</Container>
|
||||
);
|
||||
};
|
||||
|
@ -1,8 +1,10 @@
|
||||
import { Box, Typography } from '@mui/material'
|
||||
import React from 'react'
|
||||
|
||||
import { Box, Typography } from '@mui/material'
|
||||
|
||||
import { REDIRECT_EMAIL_MSG } from '../constants'
|
||||
|
||||
const RedirectEmail = () => {
|
||||
const Email = () => {
|
||||
return (
|
||||
<Box
|
||||
display="flex"
|
||||
@ -28,4 +30,4 @@ const RedirectEmail = () => {
|
||||
)
|
||||
}
|
||||
|
||||
export default RedirectEmail
|
||||
export default Email
|
@ -25,14 +25,14 @@ const SignWithCosmos = () => {
|
||||
|
||||
const navigate = useNavigate();
|
||||
|
||||
const {message: innerMessage, cosmosAddress, receivedEthSig: ethSignature, kycIdHash} = location.state as {
|
||||
const {message: innerMessage, cosmosAddress, receivedEthSig: ethSignature, subscriberIdHash} = location.state as {
|
||||
message?: {
|
||||
msg: string;
|
||||
address: string;
|
||||
};
|
||||
cosmosAddress?: string;
|
||||
receivedEthSig?: string;
|
||||
kycIdHash?: string;
|
||||
subscriberIdHash?: string;
|
||||
};
|
||||
|
||||
const ethAddress = innerMessage!.address;
|
||||
@ -49,11 +49,11 @@ const SignWithCosmos = () => {
|
||||
participant: cosmosAddress!,
|
||||
ethPayload: innerMessage,
|
||||
ethSignature: ethSignature!,
|
||||
kycId: kycIdHash!,
|
||||
kycId: subscriberIdHash!,
|
||||
role
|
||||
},
|
||||
};
|
||||
}, [cosmosAddress, innerMessage, ethSignature, kycIdHash, role]);
|
||||
}, [cosmosAddress, innerMessage, ethSignature, subscriberIdHash, role]);
|
||||
|
||||
const handleTokenRequest = async () => {
|
||||
try {
|
||||
|
@ -68,8 +68,12 @@ const SignWithNitroKey = () => {
|
||||
},
|
||||
});
|
||||
} else {
|
||||
const {kycIdHash} = location.state as {
|
||||
kycIdHash?: string
|
||||
const state = location.state as {
|
||||
subscriberIdHash?: string
|
||||
}
|
||||
|
||||
if (!state.subscriberIdHash) {
|
||||
throw new Error("Subscriber ID not found. Please verify your email and try again")
|
||||
}
|
||||
|
||||
navigate("/sign-with-cosmos", {
|
||||
@ -77,7 +81,7 @@ const SignWithNitroKey = () => {
|
||||
message,
|
||||
cosmosAddress,
|
||||
receivedEthSig,
|
||||
kycIdHash,
|
||||
subscriberIdHash: state.subscriberIdHash,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
73
src/pages/Thanks.tsx
Normal file
73
src/pages/Thanks.tsx
Normal file
@ -0,0 +1,73 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { useLocation, useNavigate } from 'react-router-dom';
|
||||
import { jwtDecode } from "jwt-decode";
|
||||
import { ethers } from 'ethers';
|
||||
|
||||
import { Box, colors, Typography } from '@mui/material';
|
||||
|
||||
interface JwtPayload {
|
||||
subscriber_id: string;
|
||||
exp: number;
|
||||
iss: string;
|
||||
iat: number;
|
||||
}
|
||||
|
||||
const Thanks: React.FC = () => {
|
||||
const location = useLocation();
|
||||
const navigate = useNavigate();
|
||||
|
||||
const [err, setErr] = useState<string>();
|
||||
|
||||
useEffect(() => {
|
||||
const queryParams = new URLSearchParams(location.search);
|
||||
const token = queryParams.get('jwt_token');
|
||||
|
||||
try {
|
||||
if(!token){
|
||||
throw new Error("Invalid JWT Token")
|
||||
}
|
||||
|
||||
const decoded = jwtDecode(token) as JwtPayload;
|
||||
const currentTime = Math.floor(Date.now() / 1000);
|
||||
|
||||
if (!decoded.subscriber_id) {
|
||||
throw new Error("Subscriber ID not found")
|
||||
}
|
||||
|
||||
if (decoded.exp < currentTime) {
|
||||
throw new Error("Token has expired");
|
||||
}
|
||||
|
||||
const uuidBuffer = Buffer.from(decoded.subscriber_id.replace(/-/g, ''), 'hex');
|
||||
|
||||
const subscriberIdHash = ethers.utils.sha256(uuidBuffer);
|
||||
|
||||
navigate('/connect-wallet', {
|
||||
state:{
|
||||
subscriberIdHash
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
setErr(String(error));
|
||||
}
|
||||
|
||||
}, [location.search, navigate]);
|
||||
|
||||
return (
|
||||
<Box
|
||||
display="flex"
|
||||
flexDirection="column"
|
||||
alignItems="center"
|
||||
justifyContent="center"
|
||||
marginY={20}
|
||||
marginX={50}
|
||||
padding={5}
|
||||
>
|
||||
<Typography variant="h4" component="h1" gutterBottom color={colors.red[400]}>
|
||||
{err ? err : "Loading..."}
|
||||
</Typography>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
export default Thanks;
|
@ -50,7 +50,7 @@ const UserVerification = () => {
|
||||
message,
|
||||
cosmosAddress,
|
||||
receivedEthSig,
|
||||
kycIdHash,
|
||||
subscriberIdHash: kycIdHash,
|
||||
}})
|
||||
}
|
||||
}, [applicationSubmitted, kycId, navigate, cosmosAddress, message, receivedEthSig]);
|
||||
|
@ -1,47 +0,0 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { useLocation, useNavigate } from 'react-router-dom';
|
||||
import jwt from 'jsonwebtoken';
|
||||
import { sha256 } from 'ethers/lib/utils';
|
||||
|
||||
interface JwtPayload {
|
||||
subscriber_id: string;
|
||||
exp: number;
|
||||
iss: string;
|
||||
iat: number;
|
||||
}
|
||||
const VerifyJWTToken: React.FC = () => {
|
||||
const location = useLocation();
|
||||
const navigate = useNavigate();
|
||||
|
||||
const [err, setErr] = useState<string>();
|
||||
|
||||
useEffect(() => {
|
||||
const queryParams = new URLSearchParams(location.search);
|
||||
const token = queryParams.get('jwt_token');
|
||||
|
||||
if (token) {
|
||||
try {
|
||||
const decoded = jwt.decode(token) as JwtPayload;
|
||||
const currentTime = Math.floor(Date.now() / 1000);
|
||||
|
||||
if (decoded.exp < currentTime) {
|
||||
throw new Error("Token has expired");
|
||||
}
|
||||
|
||||
const kycIdHash = sha256(decoded.subscriber_id);
|
||||
|
||||
navigate('/connect-wallet', {
|
||||
state:{
|
||||
kycIdHash
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
setErr(String(error));
|
||||
}
|
||||
}
|
||||
}, [location.search, navigate]);
|
||||
|
||||
return (<div>{err ? err : "Loading..."}</div>);
|
||||
};
|
||||
|
||||
export default VerifyJWTToken;
|
90
yarn.lock
90
yarn.lock
@ -3453,13 +3453,6 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee"
|
||||
integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==
|
||||
|
||||
"@types/jsonwebtoken@^9.0.6":
|
||||
version "9.0.6"
|
||||
resolved "https://registry.yarnpkg.com/@types/jsonwebtoken/-/jsonwebtoken-9.0.6.tgz#d1af3544d99ad992fb6681bbe60676e06b032bd3"
|
||||
integrity sha512-/5hndP5dCjloafCXns6SZyESp3Ldq7YjH3zwzwczYnjxIT0Fqzk5ROSYVGfFyczIue7IUEj8hkvLbPoLQ18vQw==
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/long@^4.0.1":
|
||||
version "4.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@types/long/-/long-4.0.2.tgz#b74129719fc8d11c01868010082d483b7545591a"
|
||||
@ -5047,11 +5040,6 @@ bser@2.1.1:
|
||||
dependencies:
|
||||
node-int64 "^0.4.0"
|
||||
|
||||
buffer-equal-constant-time@1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819"
|
||||
integrity sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==
|
||||
|
||||
buffer-from@^1.0.0:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5"
|
||||
@ -6220,13 +6208,6 @@ eastasianwidth@^0.2.0:
|
||||
resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb"
|
||||
integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==
|
||||
|
||||
ecdsa-sig-formatter@1.0.11:
|
||||
version "1.0.11"
|
||||
resolved "https://registry.yarnpkg.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz#ae0f0fa2d85045ef14a817daa3ce9acd0489e5bf"
|
||||
integrity sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==
|
||||
dependencies:
|
||||
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"
|
||||
@ -9036,22 +9017,6 @@ jsonpointer@^5.0.0:
|
||||
resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-5.0.1.tgz#2110e0af0900fd37467b5907ecd13a7884a1b559"
|
||||
integrity sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==
|
||||
|
||||
jsonwebtoken@^9.0.2:
|
||||
version "9.0.2"
|
||||
resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz#65ff91f4abef1784697d40952bb1998c504caaf3"
|
||||
integrity sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==
|
||||
dependencies:
|
||||
jws "^3.2.2"
|
||||
lodash.includes "^4.3.0"
|
||||
lodash.isboolean "^3.0.3"
|
||||
lodash.isinteger "^4.0.4"
|
||||
lodash.isnumber "^3.0.3"
|
||||
lodash.isplainobject "^4.0.6"
|
||||
lodash.isstring "^4.0.1"
|
||||
lodash.once "^4.0.0"
|
||||
ms "^2.1.1"
|
||||
semver "^7.5.4"
|
||||
|
||||
"jsx-ast-utils@^2.4.1 || ^3.0.0", jsx-ast-utils@^3.3.5:
|
||||
version "3.3.5"
|
||||
resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz#4766bd05a8e2a11af222becd19e15575e52a853a"
|
||||
@ -9067,22 +9032,10 @@ junk@3.1.0:
|
||||
resolved "https://registry.yarnpkg.com/junk/-/junk-3.1.0.tgz#31499098d902b7e98c5d9b9c80f43457a88abfa1"
|
||||
integrity sha512-pBxcB3LFc8QVgdggvZWyeys+hnrNWg4OcZIU/1X59k5jQdLBlCsYGRQaz234SqoRLTCgMH00fY0xRJH+F9METQ==
|
||||
|
||||
jwa@^1.4.1:
|
||||
version "1.4.1"
|
||||
resolved "https://registry.yarnpkg.com/jwa/-/jwa-1.4.1.tgz#743c32985cb9e98655530d53641b66c8645b039a"
|
||||
integrity sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==
|
||||
dependencies:
|
||||
buffer-equal-constant-time "1.0.1"
|
||||
ecdsa-sig-formatter "1.0.11"
|
||||
safe-buffer "^5.0.1"
|
||||
|
||||
jws@^3.2.2:
|
||||
version "3.2.2"
|
||||
resolved "https://registry.yarnpkg.com/jws/-/jws-3.2.2.tgz#001099f3639468c9414000e99995fa52fb478304"
|
||||
integrity sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==
|
||||
dependencies:
|
||||
jwa "^1.4.1"
|
||||
safe-buffer "^5.0.1"
|
||||
jwt-decode@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/jwt-decode/-/jwt-decode-4.0.0.tgz#2270352425fd413785b2faf11f6e755c5151bd4b"
|
||||
integrity sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==
|
||||
|
||||
keccak@^3.0.0:
|
||||
version "3.0.4"
|
||||
@ -9302,41 +9255,11 @@ lodash.debounce@^4.0.8:
|
||||
resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af"
|
||||
integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==
|
||||
|
||||
lodash.includes@^4.3.0:
|
||||
version "4.3.0"
|
||||
resolved "https://registry.yarnpkg.com/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f"
|
||||
integrity sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==
|
||||
|
||||
lodash.isboolean@^3.0.3:
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6"
|
||||
integrity sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==
|
||||
|
||||
lodash.isequal@4.5.0:
|
||||
version "4.5.0"
|
||||
resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0"
|
||||
integrity sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==
|
||||
|
||||
lodash.isinteger@^4.0.4:
|
||||
version "4.0.4"
|
||||
resolved "https://registry.yarnpkg.com/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz#619c0af3d03f8b04c31f5882840b77b11cd68343"
|
||||
integrity sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==
|
||||
|
||||
lodash.isnumber@^3.0.3:
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz#3ce76810c5928d03352301ac287317f11c0b1ffc"
|
||||
integrity sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==
|
||||
|
||||
lodash.isplainobject@^4.0.6:
|
||||
version "4.0.6"
|
||||
resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb"
|
||||
integrity sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==
|
||||
|
||||
lodash.isstring@^4.0.1:
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451"
|
||||
integrity sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==
|
||||
|
||||
lodash.memoize@^4.1.2:
|
||||
version "4.1.2"
|
||||
resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe"
|
||||
@ -9347,11 +9270,6 @@ lodash.merge@^4.6.2:
|
||||
resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a"
|
||||
integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==
|
||||
|
||||
lodash.once@^4.0.0:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac"
|
||||
integrity sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==
|
||||
|
||||
lodash.sortby@^4.7.0:
|
||||
version "4.7.0"
|
||||
resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438"
|
||||
|
Loading…
Reference in New Issue
Block a user