Integrate sumsub KYC with terms & conditions (#6)
Part of [Sumsub KYC integration in onboarding app](https://www.notion.so/Sumsub-KYC-integration-in-onboarding-app-607b598c9c1d4d12adc71725e2ab5e7e) Reviewed-on: cerc-io/testnet-onboarding-app#6
This commit is contained in:
parent
e95071fc62
commit
2a24985930
@ -6,3 +6,4 @@ REACT_APP_LACONICD_RPC_ENDPOINT=http://localhost:26657
|
|||||||
REACT_APP_LACONICD_DENOM=photon
|
REACT_APP_LACONICD_DENOM=photon
|
||||||
REACT_APP_FAUCET_ENDPOINT=http://localhost:4000
|
REACT_APP_FAUCET_ENDPOINT=http://localhost:4000
|
||||||
REACT_APP_WALLET_META_URL=http://localhost:3000
|
REACT_APP_WALLET_META_URL=http://localhost:3000
|
||||||
|
REACT_APP_SUMSUB_API_ENDPOINT=
|
||||||
|
18
package.json
18
package.json
@ -3,13 +3,15 @@
|
|||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@cerc-io/registry-sdk": "^0.2.2",
|
"@cerc-io/registry-sdk": "^0.2.4",
|
||||||
"@cosmjs/stargate": "^0.32.4",
|
"@cosmjs/stargate": "^0.32.4",
|
||||||
"@emotion/react": "^11.11.4",
|
"@emotion/react": "^11.11.4",
|
||||||
"@emotion/styled": "^11.11.0",
|
"@emotion/styled": "^11.11.0",
|
||||||
"@mui/icons-material": "^5.15.14",
|
"@mui/icons-material": "^5.15.14",
|
||||||
"@mui/lab": "^5.0.0-alpha.169",
|
"@mui/lab": "^5.0.0-alpha.169",
|
||||||
"@mui/material": "^5.15.14",
|
"@mui/material": "^5.15.14",
|
||||||
|
"@sumsub/websdk": "^2.3.1",
|
||||||
|
"@sumsub/websdk-react": "^2.3.1",
|
||||||
"@walletconnect/encoding": "^1.0.2",
|
"@walletconnect/encoding": "^1.0.2",
|
||||||
"@walletconnect/modal": "^2.6.2",
|
"@walletconnect/modal": "^2.6.2",
|
||||||
"@walletconnect/sign-client": "^2.11.3",
|
"@walletconnect/sign-client": "^2.11.3",
|
||||||
@ -51,8 +53,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@typescript-eslint/eslint-plugin": "^6.13.2",
|
"@babel/core": "^7.16.0",
|
||||||
"@typescript-eslint/parser": "^6.13.2",
|
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.3",
|
||||||
|
"@svgr/webpack": "^5.5.0",
|
||||||
"@testing-library/jest-dom": "^5.17.0",
|
"@testing-library/jest-dom": "^5.17.0",
|
||||||
"@testing-library/react": "^13.4.0",
|
"@testing-library/react": "^13.4.0",
|
||||||
"@testing-library/user-event": "^13.5.0",
|
"@testing-library/user-event": "^13.5.0",
|
||||||
@ -60,11 +63,8 @@
|
|||||||
"@types/node": "^16.18.90",
|
"@types/node": "^16.18.90",
|
||||||
"@types/react": "^18.2.67",
|
"@types/react": "^18.2.67",
|
||||||
"@types/react-dom": "^18.2.22",
|
"@types/react-dom": "^18.2.22",
|
||||||
"@babel/core": "^7.16.0",
|
"@typescript-eslint/eslint-plugin": "^6.13.2",
|
||||||
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.3",
|
"@typescript-eslint/parser": "^6.13.2",
|
||||||
"@svgr/webpack": "^5.5.0",
|
|
||||||
"eslint-plugin-react": "^7.33.2",
|
|
||||||
"husky": "^9.0.11",
|
|
||||||
"babel-jest": "^27.4.2",
|
"babel-jest": "^27.4.2",
|
||||||
"babel-loader": "^8.2.3",
|
"babel-loader": "^8.2.3",
|
||||||
"babel-plugin-named-asset-import": "^0.3.8",
|
"babel-plugin-named-asset-import": "^0.3.8",
|
||||||
@ -78,10 +78,12 @@
|
|||||||
"dotenv-expand": "^5.1.0",
|
"dotenv-expand": "^5.1.0",
|
||||||
"eslint": "^8.3.0",
|
"eslint": "^8.3.0",
|
||||||
"eslint-config-react-app": "^7.0.1",
|
"eslint-config-react-app": "^7.0.1",
|
||||||
|
"eslint-plugin-react": "^7.33.2",
|
||||||
"eslint-webpack-plugin": "^3.1.1",
|
"eslint-webpack-plugin": "^3.1.1",
|
||||||
"file-loader": "^6.2.0",
|
"file-loader": "^6.2.0",
|
||||||
"fs-extra": "^10.0.0",
|
"fs-extra": "^10.0.0",
|
||||||
"html-webpack-plugin": "^5.5.0",
|
"html-webpack-plugin": "^5.5.0",
|
||||||
|
"husky": "^9.0.11",
|
||||||
"identity-obj-proxy": "^3.0.0",
|
"identity-obj-proxy": "^3.0.0",
|
||||||
"jest": "^27.4.3",
|
"jest": "^27.4.3",
|
||||||
"jest-resolve": "^27.4.2",
|
"jest-resolve": "^27.4.2",
|
||||||
|
15
src/App.tsx
15
src/App.tsx
@ -7,22 +7,31 @@ import SignWithCosmos from "./pages/SignWithCosmos";
|
|||||||
import PageNotFound from "./pages/PageNotFound";
|
import PageNotFound from "./pages/PageNotFound";
|
||||||
import OnboardingSuccess from "./pages/OnboardingSuccess";
|
import OnboardingSuccess from "./pages/OnboardingSuccess";
|
||||||
import SignPageLayout from "./layout/SignPageLayout";
|
import SignPageLayout from "./layout/SignPageLayout";
|
||||||
|
import UserVerification from "./pages/UserVerification";
|
||||||
|
import TermsAndConditions from "./pages/TermsAndConditions";
|
||||||
|
import Header from "./components/Header";
|
||||||
import { WalletConnectProvider } from "./context/WalletConnectContext";
|
import { WalletConnectProvider } from "./context/WalletConnectContext";
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
return (
|
return (
|
||||||
<Router>
|
<Router>
|
||||||
|
<Header />
|
||||||
<WalletConnectProvider>
|
<WalletConnectProvider>
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route path="/" element={<ConnectWallet />} />
|
<Route path="/" element={<TermsAndConditions />} />
|
||||||
|
<Route path="/connect-wallet" element={<ConnectWallet />} />
|
||||||
<Route element={<SignPageLayout />}>
|
<Route element={<SignPageLayout />}>
|
||||||
<Route path="/sign-with-nitro-key" element={<SignWithNitroKey />} />
|
<Route path="/sign-with-nitro-key" element={<SignWithNitroKey />} />
|
||||||
<Route
|
<Route
|
||||||
path="/sign-with-cosmos/:cosmosAddress/:ethSignature"
|
path="/user-verification"
|
||||||
|
element={<UserVerification />}
|
||||||
|
/>
|
||||||
|
<Route
|
||||||
|
path="/sign-with-cosmos"
|
||||||
element={<SignWithCosmos />}
|
element={<SignWithCosmos />}
|
||||||
/>
|
/>
|
||||||
<Route
|
<Route
|
||||||
path="/onboarding-success/:cosmosAddress"
|
path="/onboarding-success"
|
||||||
element={<OnboardingSuccess />}
|
element={<OnboardingSuccess />}
|
||||||
></Route>
|
></Route>
|
||||||
</Route>
|
</Route>
|
||||||
|
33
src/components/Header.tsx
Normal file
33
src/components/Header.tsx
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { Link, useLocation } from 'react-router-dom';
|
||||||
|
|
||||||
|
import { AppBar, Toolbar, Avatar, Box, IconButton } from '@mui/material';
|
||||||
|
|
||||||
|
const Header: React.FC = () => {
|
||||||
|
const location = useLocation()
|
||||||
|
|
||||||
|
return (
|
||||||
|
<AppBar position="static" color="inherit">
|
||||||
|
<Toolbar>
|
||||||
|
<Link to={location.pathname === "/" ? "/" : "/connect-wallet"} style={{ color: "inherit", textDecoration: "none" }}>
|
||||||
|
<Box sx={{ display: "flex", alignItems: "center" }}>
|
||||||
|
<Avatar
|
||||||
|
alt="Laconic logo"
|
||||||
|
src="https://avatars.githubusercontent.com/u/92608123"
|
||||||
|
/>
|
||||||
|
<IconButton
|
||||||
|
edge="start"
|
||||||
|
color="inherit"
|
||||||
|
aria-label="menu"
|
||||||
|
sx={{ ml: 2, mr: 2 }}
|
||||||
|
>
|
||||||
|
Testnet Onboarding
|
||||||
|
</IconButton>
|
||||||
|
</Box>
|
||||||
|
</Link>
|
||||||
|
</Toolbar>
|
||||||
|
</AppBar>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Header;
|
83
src/components/TermsAndConditionsCard.tsx
Normal file
83
src/components/TermsAndConditionsCard.tsx
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
import React, { useState } from 'react';
|
||||||
|
|
||||||
|
import { Typography, Button, Box, Paper, Radio, RadioGroup, FormControlLabel, FormControl, FormLabel, Link, Checkbox } from '@mui/material';
|
||||||
|
|
||||||
|
import TermsAndConditionsDialog from './TermsAndConditionsDialog';
|
||||||
|
|
||||||
|
export enum Role {
|
||||||
|
Validator = 'validator',
|
||||||
|
Participant = 'participant'
|
||||||
|
}
|
||||||
|
|
||||||
|
const TermsAndConditionsCard = ({ handleAccept, handleRoleChange }: { handleAccept: () => void, handleRoleChange: (role: Role) => void }) => {
|
||||||
|
const [selectedRole, setSelectedRole] = useState<Role>(Role.Participant);
|
||||||
|
const [checked, setChecked] = useState(false);
|
||||||
|
const [isHidden, setIsHidden] = useState(false);
|
||||||
|
|
||||||
|
const [isDialogOpen, setisDialogOpen] = useState(false)
|
||||||
|
|
||||||
|
const handleCheckboxChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
setChecked(event.target.checked);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleContinue = () => {
|
||||||
|
handleAccept()
|
||||||
|
setIsHidden(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleRadioChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
setSelectedRole(event.target.value as Role);
|
||||||
|
handleRoleChange((event.target as HTMLInputElement).value === Role.Validator ? Role.Validator : Role.Participant);
|
||||||
|
setChecked(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Paper elevation={3} style={{ padding: '2rem', marginTop: '2rem', display: isHidden ? "none" : "block" }}>
|
||||||
|
<FormControl component="fieldset">
|
||||||
|
<FormLabel component="legend">Select your role</FormLabel>
|
||||||
|
<RadioGroup
|
||||||
|
aria-label="roles"
|
||||||
|
name="roles"
|
||||||
|
value={selectedRole}
|
||||||
|
onChange={handleRadioChange}
|
||||||
|
>
|
||||||
|
<FormControlLabel
|
||||||
|
value={Role.Validator}
|
||||||
|
control={<Radio />}
|
||||||
|
label="Validator"
|
||||||
|
/>
|
||||||
|
<FormControlLabel
|
||||||
|
value={Role.Participant}
|
||||||
|
control={<Radio />}
|
||||||
|
label="Participant"
|
||||||
|
/>
|
||||||
|
</RadioGroup>
|
||||||
|
</FormControl>
|
||||||
|
<Box mt={2} display="flex" alignItems="center">
|
||||||
|
<Checkbox
|
||||||
|
checked={checked}
|
||||||
|
onChange={handleCheckboxChange}
|
||||||
|
color="primary"
|
||||||
|
/>
|
||||||
|
<Typography variant="body1">
|
||||||
|
I accept the <Link onClick={() => setisDialogOpen(true)} target="_blank" rel="noopener">
|
||||||
|
terms and conditions
|
||||||
|
</Link>
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
<Box mt={4} display="flex" justifyContent="end">
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
color="primary"
|
||||||
|
onClick={handleContinue}
|
||||||
|
disabled={!checked}
|
||||||
|
>
|
||||||
|
Continue
|
||||||
|
</Button>
|
||||||
|
</Box>
|
||||||
|
<TermsAndConditionsDialog isValidator = { selectedRole === Role.Validator } open={isDialogOpen} onClose={() => setisDialogOpen(false)}/>
|
||||||
|
</Paper>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default TermsAndConditionsCard;
|
34
src/components/TermsAndConditionsDialog.tsx
Normal file
34
src/components/TermsAndConditionsDialog.tsx
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import { Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle, Button, Typography } from '@mui/material';
|
||||||
|
|
||||||
|
import { TNC_PARTICIPANT_CONTENT, TNC_VALIDATOR_CONTENT } from '../constants';
|
||||||
|
|
||||||
|
interface TermsDialogProps {
|
||||||
|
isValidator: boolean;
|
||||||
|
open: boolean;
|
||||||
|
onClose: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const TermsAndConditionsDialog: React.FC<TermsDialogProps> = ({ isValidator, open, onClose }) => {
|
||||||
|
return (
|
||||||
|
<Dialog open={open} onClose={onClose}>
|
||||||
|
<DialogTitle>Terms and Conditions</DialogTitle>
|
||||||
|
<DialogContent>
|
||||||
|
<Typography variant="h6" gutterBottom>
|
||||||
|
Onboard as a {isValidator ? "validator" : "participant"}
|
||||||
|
</Typography>
|
||||||
|
<DialogContentText>
|
||||||
|
<div dangerouslySetInnerHTML={{__html: isValidator ? TNC_VALIDATOR_CONTENT : TNC_PARTICIPANT_CONTENT }} />
|
||||||
|
</DialogContentText>
|
||||||
|
</DialogContent>
|
||||||
|
<DialogActions>
|
||||||
|
<Button onClick={onClose} color="primary">
|
||||||
|
Close
|
||||||
|
</Button>
|
||||||
|
</DialogActions>
|
||||||
|
</Dialog>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default TermsAndConditionsDialog;
|
29
src/constants.ts
Normal file
29
src/constants.ts
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
export const TNC_GENERIC_CONTENT = `Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. <br/>
|
||||||
|
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. <br/>
|
||||||
|
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. <br/>
|
||||||
|
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. <br/>
|
||||||
|
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. <br/>
|
||||||
|
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. <br/>
|
||||||
|
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. <br/>
|
||||||
|
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. <br/>
|
||||||
|
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.`;
|
||||||
|
|
||||||
|
export const TNC_VALIDATOR_CONTENT = `Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. <br/>
|
||||||
|
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. <br/>
|
||||||
|
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. <br/>
|
||||||
|
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. <br/>
|
||||||
|
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. <br/>
|
||||||
|
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. <br/>
|
||||||
|
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. <br/>
|
||||||
|
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. <br/>
|
||||||
|
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.`;
|
||||||
|
|
||||||
|
export const TNC_PARTICIPANT_CONTENT = `Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. <br/>
|
||||||
|
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. <br/>
|
||||||
|
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. <br/>
|
||||||
|
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. <br/>
|
||||||
|
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. <br/>
|
||||||
|
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. <br/>
|
||||||
|
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. <br/>
|
||||||
|
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. <br/>
|
||||||
|
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.`;
|
@ -1,14 +1,12 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { Outlet, useNavigate, Link } from "react-router-dom";
|
import { Outlet, useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Toolbar,
|
Toolbar,
|
||||||
IconButton,
|
|
||||||
Avatar,
|
Avatar,
|
||||||
Button,
|
Button,
|
||||||
Typography,
|
Typography,
|
||||||
Container,
|
Container
|
||||||
Box,
|
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
|
|
||||||
import { useWalletConnectContext } from "../context/WalletConnectContext";
|
import { useWalletConnectContext } from "../context/WalletConnectContext";
|
||||||
@ -25,22 +23,6 @@ const SignPageLayout = () => {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Toolbar variant="dense">
|
<Toolbar variant="dense">
|
||||||
<Link to="/" style={{ color: "inherit", textDecoration: "none" }}>
|
|
||||||
<Box sx={{ display: "flex", alignItems: "center" }}>
|
|
||||||
<Avatar
|
|
||||||
alt="Laconic logo"
|
|
||||||
src="https://avatars.githubusercontent.com/u/92608123"
|
|
||||||
/>
|
|
||||||
<IconButton
|
|
||||||
edge="start"
|
|
||||||
color="inherit"
|
|
||||||
aria-label="menu"
|
|
||||||
sx={{ ml: 2, mr: 2 }}
|
|
||||||
>
|
|
||||||
Testnet Onboarding
|
|
||||||
</IconButton>
|
|
||||||
</Box>
|
|
||||||
</Link>
|
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import React, { useEffect } from "react";
|
import React, { useEffect } from "react";
|
||||||
import { useNavigate } from "react-router-dom";
|
import {useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
import { Typography, Button, Box, Container, Avatar } from "@mui/material";
|
import { Button, Box, Container } from "@mui/material";
|
||||||
|
|
||||||
import { useWalletConnectContext } from "../context/WalletConnectContext";
|
import { useWalletConnectContext } from "../context/WalletConnectContext";
|
||||||
|
|
||||||
@ -10,11 +10,13 @@ const ConnectWallet = () => {
|
|||||||
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
||||||
if (session) {
|
if (session) {
|
||||||
navigate("/sign-with-nitro-key");
|
navigate("/sign-with-nitro-key");
|
||||||
}
|
}
|
||||||
}, [session, navigate]);
|
}, [session, navigate,]);
|
||||||
|
|
||||||
const handler = async () => {
|
const handler = async () => {
|
||||||
await connect();
|
await connect();
|
||||||
@ -30,28 +32,12 @@ const ConnectWallet = () => {
|
|||||||
justifyContent="center"
|
justifyContent="center"
|
||||||
padding={5}
|
padding={5}
|
||||||
>
|
>
|
||||||
<Box display="flex" alignItems="center">
|
|
||||||
<Avatar
|
|
||||||
alt="Laconic logo"
|
|
||||||
src="https://avatars.githubusercontent.com/u/92608123"
|
|
||||||
/>
|
|
||||||
<Typography
|
|
||||||
variant="h4"
|
|
||||||
component="h6"
|
|
||||||
style={{ marginLeft: "10px" }}
|
|
||||||
>
|
|
||||||
Testnet Onboarding
|
|
||||||
</Typography>
|
|
||||||
</Box>
|
|
||||||
<Typography variant="h6" component="h6" style={{ marginTop: "30px" }}>
|
|
||||||
Connect wallet
|
|
||||||
</Typography>
|
|
||||||
<Button
|
<Button
|
||||||
variant="contained"
|
variant="contained"
|
||||||
onClick={handler}
|
onClick={handler}
|
||||||
style={{ marginTop: "20px" }}
|
style={{ marginTop: "20px" }}
|
||||||
>
|
>
|
||||||
Connect
|
Connect Wallet
|
||||||
</Button>
|
</Button>
|
||||||
</Box>
|
</Box>
|
||||||
</Container>
|
</Container>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import { SnackbarProvider, enqueueSnackbar } from "notistack";
|
import { SnackbarProvider, enqueueSnackbar } from "notistack";
|
||||||
import { useParams } from "react-router-dom";
|
import { useLocation } from "react-router-dom";
|
||||||
|
|
||||||
import { Box, Typography } from "@mui/material";
|
import { Box, Typography } from "@mui/material";
|
||||||
import { Registry } from "@cerc-io/registry-sdk";
|
import { Registry } from "@cerc-io/registry-sdk";
|
||||||
@ -8,6 +8,8 @@ import { Registry } from "@cerc-io/registry-sdk";
|
|||||||
interface Participant {
|
interface Participant {
|
||||||
cosmosAddress: string;
|
cosmosAddress: string;
|
||||||
nitroAddress: string;
|
nitroAddress: string;
|
||||||
|
role: string;
|
||||||
|
kycId: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const registry = new Registry(
|
const registry = new Registry(
|
||||||
@ -15,18 +17,21 @@ const registry = new Registry(
|
|||||||
);
|
);
|
||||||
|
|
||||||
const OnboardingSuccess = () => {
|
const OnboardingSuccess = () => {
|
||||||
const { cosmosAddress } = useParams();
|
const location = useLocation();
|
||||||
|
const { cosmosAddress } = location.state as {
|
||||||
|
cosmosAddress?: string
|
||||||
|
}
|
||||||
|
|
||||||
const [participant, setParticipant] = useState<Participant>();
|
const [participant, setParticipant] = useState<Participant>();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const fetchParticipants = async () => {
|
const fetchParticipants = async () => {
|
||||||
try {
|
try {
|
||||||
const allParticipants: Participant[] = await registry.getParticipants();
|
if (!cosmosAddress) {
|
||||||
const participant = allParticipants.find(
|
enqueueSnackbar("Cosmos address is not provided", { variant: "error" });
|
||||||
(participant) => participant.cosmosAddress === cosmosAddress
|
return;
|
||||||
);
|
}
|
||||||
|
const participant: Participant = await registry.getParticipantByAddress(cosmosAddress);
|
||||||
if (!participant) {
|
if (!participant) {
|
||||||
enqueueSnackbar("Participant not found", { variant: "error" });
|
enqueueSnackbar("Participant not found", { variant: "error" });
|
||||||
return;
|
return;
|
||||||
@ -66,6 +71,8 @@ const OnboardingSuccess = () => {
|
|||||||
<div>
|
<div>
|
||||||
Cosmos Address: {participant.cosmosAddress} <br />
|
Cosmos Address: {participant.cosmosAddress} <br />
|
||||||
Nitro Address: {participant.nitroAddress} <br />
|
Nitro Address: {participant.nitroAddress} <br />
|
||||||
|
Role: {participant.role} <br />
|
||||||
|
KYC ID: {participant.kycId} <br />
|
||||||
<br />
|
<br />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import React, { useCallback, useEffect, useMemo, useState } from "react";
|
import React, { useCallback, useEffect, useMemo, useState } from "react";
|
||||||
import { useParams, useLocation, useNavigate } from "react-router-dom";
|
import { useLocation, useNavigate } from "react-router-dom";
|
||||||
import { SnackbarProvider, enqueueSnackbar } from "notistack";
|
import { SnackbarProvider, enqueueSnackbar } from "notistack";
|
||||||
|
|
||||||
import { Box, Card, CardContent, Grid, Typography } from "@mui/material";
|
import { Box, Card, CardContent, Grid, Typography } from "@mui/material";
|
||||||
@ -11,20 +11,31 @@ import {
|
|||||||
import { StargateClient } from "@cosmjs/stargate";
|
import { StargateClient } from "@cosmjs/stargate";
|
||||||
|
|
||||||
import { useWalletConnectContext } from "../context/WalletConnectContext";
|
import { useWalletConnectContext } from "../context/WalletConnectContext";
|
||||||
|
import TermsAndConditionsCard, {Role} from "../components/TermsAndConditionsCard";
|
||||||
|
|
||||||
const SignWithCosmos = () => {
|
const SignWithCosmos = () => {
|
||||||
const { session, signClient } = useWalletConnectContext();
|
const { session, signClient } = useWalletConnectContext();
|
||||||
|
|
||||||
const { cosmosAddress, ethSignature } = useParams();
|
const location = useLocation();
|
||||||
|
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
const [balance, setBalance] = useState('');
|
const [balance, setBalance] = useState('');
|
||||||
const [isRequesting, setIsRequesting] = useState(false);
|
const [isRequesting, setIsRequesting] = useState(false);
|
||||||
|
const [isTncAccepted, setIsTncAccepted] = useState(false);
|
||||||
|
const [role, setRole] = useState(Role.Participant);
|
||||||
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const location = useLocation();
|
|
||||||
const innerMessage = location.state;
|
const {message: innerMessage, cosmosAddress, receivedEthSig: ethSignature, kycId} = location.state as {
|
||||||
const ethAddress = innerMessage.address;
|
message?: {
|
||||||
|
msg: string;
|
||||||
|
address: string;
|
||||||
|
};
|
||||||
|
cosmosAddress?: string;
|
||||||
|
receivedEthSig?: string;
|
||||||
|
kycId?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
const ethAddress = innerMessage!.address;
|
||||||
|
|
||||||
const createCosmosClient = useCallback(async (endpoint: string) => {
|
const createCosmosClient = useCallback(async (endpoint: string) => {
|
||||||
return await StargateClient.connect(endpoint);
|
return await StargateClient.connect(endpoint);
|
||||||
@ -35,12 +46,14 @@ const SignWithCosmos = () => {
|
|||||||
return {
|
return {
|
||||||
typeUrl: typeUrlMsgOnboardParticipant,
|
typeUrl: typeUrlMsgOnboardParticipant,
|
||||||
value: {
|
value: {
|
||||||
participant: cosmosAddress,
|
participant: cosmosAddress!,
|
||||||
ethPayload: innerMessage,
|
ethPayload: innerMessage,
|
||||||
ethSignature,
|
ethSignature: ethSignature!,
|
||||||
|
kycId: kycId!,
|
||||||
|
role
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}, [cosmosAddress, innerMessage, ethSignature]);
|
}, [cosmosAddress, innerMessage, ethSignature, kycId, role]);
|
||||||
|
|
||||||
const handleTokenRequest = async () => {
|
const handleTokenRequest = async () => {
|
||||||
try {
|
try {
|
||||||
@ -100,7 +113,11 @@ const SignWithCosmos = () => {
|
|||||||
if (responseFromWallet.code !== 0) {
|
if (responseFromWallet.code !== 0) {
|
||||||
enqueueSnackbar("Transaction not sent", { variant: "error" });
|
enqueueSnackbar("Transaction not sent", { variant: "error" });
|
||||||
} else {
|
} else {
|
||||||
navigate(`/onboarding-success/${cosmosAddress}`);
|
navigate("/onboarding-success", {
|
||||||
|
state: {
|
||||||
|
cosmosAddress
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
@ -130,10 +147,12 @@ const SignWithCosmos = () => {
|
|||||||
sx={{
|
sx={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
flexDirection: "column",
|
flexDirection: "column",
|
||||||
marginTop: "100px",
|
marginY: "100px",
|
||||||
gap: "10px",
|
gap: "10px",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
<Typography variant="h5" display={`${isTncAccepted ? "none" : "block"}`}>Please accept terms and conditions to continue</Typography>
|
||||||
|
<TermsAndConditionsCard handleAccept={() => setIsTncAccepted(true)} handleRoleChange={setRole}/>
|
||||||
<Typography variant="h5">Send transaction to chain</Typography>
|
<Typography variant="h5">Send transaction to chain</Typography>
|
||||||
<Typography>Cosmos Account:</Typography>
|
<Typography>Cosmos Account:</Typography>
|
||||||
<Card className='mt-1 mb-1'>
|
<Card className='mt-1 mb-1'>
|
||||||
@ -147,7 +166,7 @@ const SignWithCosmos = () => {
|
|||||||
<LoadingButton
|
<LoadingButton
|
||||||
variant="contained"
|
variant="contained"
|
||||||
onClick={handleTokenRequest}
|
onClick={handleTokenRequest}
|
||||||
disabled={isRequesting}
|
disabled={isTncAccepted ? isRequesting : !isTncAccepted}
|
||||||
loading={isRequesting}
|
loading={isRequesting}
|
||||||
>
|
>
|
||||||
Request tokens from Faucet
|
Request tokens from Faucet
|
||||||
@ -178,7 +197,7 @@ const SignWithCosmos = () => {
|
|||||||
await sendTransaction(onboardParticipantMsg);
|
await sendTransaction(onboardParticipantMsg);
|
||||||
}}
|
}}
|
||||||
loading={isLoading}
|
loading={isLoading}
|
||||||
disabled={balance === '0'}
|
disabled={isTncAccepted ? (balance === '0') : !isTncAccepted}
|
||||||
>
|
>
|
||||||
Send transaction
|
Send transaction
|
||||||
</LoadingButton>
|
</LoadingButton>
|
||||||
|
@ -15,6 +15,7 @@ import { utf8ToHex } from "@walletconnect/encoding";
|
|||||||
import { useWalletConnectContext } from "../context/WalletConnectContext";
|
import { useWalletConnectContext } from "../context/WalletConnectContext";
|
||||||
|
|
||||||
const SignWithNitroKey = () => {
|
const SignWithNitroKey = () => {
|
||||||
|
|
||||||
const { session, signClient, checkPersistedState } =
|
const { session, signClient, checkPersistedState } =
|
||||||
useWalletConnectContext();
|
useWalletConnectContext();
|
||||||
|
|
||||||
@ -34,7 +35,7 @@ const SignWithNitroKey = () => {
|
|||||||
|
|
||||||
const message = useMemo(() => {
|
const message = useMemo(() => {
|
||||||
return {
|
return {
|
||||||
msg: "Register my account as a validator on the Laconic network",
|
msg: "Register my account as a participant on the Laconic network",
|
||||||
address: ethAddress,
|
address: ethAddress,
|
||||||
};
|
};
|
||||||
}, [ethAddress]);
|
}, [ethAddress]);
|
||||||
@ -55,8 +56,12 @@ const SignWithNitroKey = () => {
|
|||||||
});
|
});
|
||||||
setIsLoading(false)
|
setIsLoading(false)
|
||||||
setEthSignature(ethSignature);
|
setEthSignature(ethSignature);
|
||||||
navigate(`/sign-with-cosmos/${cosmosAddress}/${receivedEthSig}`, {
|
navigate("/user-verification", {
|
||||||
state: message,
|
state: {
|
||||||
|
message,
|
||||||
|
cosmosAddress,
|
||||||
|
receivedEthSig,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log("err in signing ", error);
|
console.log("err in signing ", error);
|
||||||
@ -66,7 +71,6 @@ const SignWithNitroKey = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{session ? (
|
{session ? (
|
||||||
@ -129,7 +133,7 @@ const SignWithNitroKey = () => {
|
|||||||
style={{ marginTop: "20px" }}
|
style={{ marginTop: "20px" }}
|
||||||
loading={isLoading}
|
loading={isLoading}
|
||||||
>
|
>
|
||||||
Sign using Nitro key
|
Sign using Nitro key
|
||||||
</LoadingButton>
|
</LoadingButton>
|
||||||
</Box>
|
</Box>
|
||||||
<SnackbarProvider />
|
<SnackbarProvider />
|
||||||
|
48
src/pages/TermsAndConditions.tsx
Normal file
48
src/pages/TermsAndConditions.tsx
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
|
||||||
|
import { Container, Typography, Button, Box, Paper } from '@mui/material';
|
||||||
|
|
||||||
|
import { TNC_GENERIC_CONTENT } from '../constants';
|
||||||
|
|
||||||
|
const TermsAndConditions = () => {
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
const handleAccept = () => {
|
||||||
|
navigate('/connect-wallet');
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Container maxWidth="md">
|
||||||
|
<Paper elevation={3} style={{ padding: '2rem', marginTop: '2rem', height: '80vh', display: 'flex', flexDirection: 'column' }}>
|
||||||
|
<Typography variant="h4" gutterBottom>
|
||||||
|
Terms and Conditions
|
||||||
|
</Typography>
|
||||||
|
<Box
|
||||||
|
style={{
|
||||||
|
overflowY: 'auto',
|
||||||
|
flexGrow: 1,
|
||||||
|
paddingRight: '1rem',
|
||||||
|
marginBottom: '1rem',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Typography
|
||||||
|
variant="body1"
|
||||||
|
gutterBottom
|
||||||
|
component="div"
|
||||||
|
>
|
||||||
|
<div dangerouslySetInnerHTML={{__html: TNC_GENERIC_CONTENT}} />
|
||||||
|
</Typography>
|
||||||
|
|
||||||
|
</Box>
|
||||||
|
<Box mt={2} display="flex" justifyContent="center">
|
||||||
|
<Button variant="contained" color="primary" onClick={handleAccept}>
|
||||||
|
Accept
|
||||||
|
</Button>
|
||||||
|
</Box>
|
||||||
|
</Paper>
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default TermsAndConditions;
|
116
src/pages/UserVerification.tsx
Normal file
116
src/pages/UserVerification.tsx
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
import React, { useEffect, useState } from 'react';
|
||||||
|
import { useLocation, useNavigate } from 'react-router-dom';
|
||||||
|
|
||||||
|
import { Box, Typography } from '@mui/material';
|
||||||
|
import SumsubWebSdk from '@sumsub/websdk-react';
|
||||||
|
import { MessageHandler } from '@sumsub/websdk';
|
||||||
|
import { EventPayload } from '@sumsub/websdk/types/types';
|
||||||
|
|
||||||
|
import { fetchAccessToken } from '../utils/sumsub';
|
||||||
|
|
||||||
|
const config = {
|
||||||
|
lang: "en", // language of WebSDK texts and comments (ISO 639-1 format)
|
||||||
|
theme: "light",
|
||||||
|
};
|
||||||
|
|
||||||
|
const options = {
|
||||||
|
addViewportTag: false,
|
||||||
|
adaptIframeHeight: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
const UserVerification = () => {
|
||||||
|
const [kycId, setKycId] = useState<string>('unknown');
|
||||||
|
const [applicationSubmitted, setApplicationSubmitted] = useState<boolean>(false);
|
||||||
|
const [token, setToken] = useState<string>('');
|
||||||
|
const [loading, setLoading] = useState<boolean>(true);
|
||||||
|
|
||||||
|
const location = useLocation();
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
const {message, cosmosAddress, receivedEthSig} = location.state as {
|
||||||
|
message?: string;
|
||||||
|
cosmosAddress?: string;
|
||||||
|
receivedEthSig?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
const userId = cosmosAddress;
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const getToken = async (userId: string) => {
|
||||||
|
console.log(userId);
|
||||||
|
const newToken = await fetchAccessToken(userId);
|
||||||
|
|
||||||
|
setToken(newToken);
|
||||||
|
setLoading(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (userId) {
|
||||||
|
getToken(userId).catch(error => {
|
||||||
|
console.error(error);
|
||||||
|
alert("Failed to fetch token");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, [userId]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (applicationSubmitted && kycId !== '') {
|
||||||
|
navigate("/sign-with-cosmos", {
|
||||||
|
state: {
|
||||||
|
message,
|
||||||
|
cosmosAddress,
|
||||||
|
receivedEthSig,
|
||||||
|
kycId,
|
||||||
|
}})
|
||||||
|
}
|
||||||
|
}, [applicationSubmitted, kycId, navigate, cosmosAddress, message, receivedEthSig]);
|
||||||
|
|
||||||
|
const accessTokenExpirationHandler = async () => {
|
||||||
|
alert("Please renew token");
|
||||||
|
return "Token expired";
|
||||||
|
};
|
||||||
|
|
||||||
|
const messageHandler: MessageHandler = (event, payload) => {
|
||||||
|
console.log('sumsubEvent:', event);
|
||||||
|
|
||||||
|
if (event === 'idCheck.onApplicantLoaded') {
|
||||||
|
setKycId((payload as EventPayload<'idCheck.onApplicantLoaded'>).applicantId);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event === 'idCheck.onApplicantSubmitted') {
|
||||||
|
setApplicationSubmitted(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event === 'idCheck.onApplicantStatusChanged') {
|
||||||
|
if ((payload as EventPayload<'idCheck.onApplicantStatusChanged'>).reviewStatus === 'pending') {
|
||||||
|
setApplicationSubmitted(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
marginTop: "100px",
|
||||||
|
gap: "10px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Typography variant="h5">User verification</Typography>
|
||||||
|
<div id="sumsub-websdk-container"></div>
|
||||||
|
</Box>
|
||||||
|
{!loading && token && (
|
||||||
|
<SumsubWebSdk
|
||||||
|
accessToken={token}
|
||||||
|
expirationHandler={accessTokenExpirationHandler}
|
||||||
|
config={config}
|
||||||
|
options={options}
|
||||||
|
onMessage={messageHandler}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default UserVerification;
|
16
src/utils/sumsub.ts
Normal file
16
src/utils/sumsub.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
export const fetchAccessToken = async (userId: string): Promise<string> => {
|
||||||
|
const response = await fetch(`${process.env.REACT_APP_SUMSUB_API_ENDPOINT}/generate-token`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
body: JSON.stringify({ userId })
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error('Network response was not ok');
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
return data.token;
|
||||||
|
};
|
20
yarn.lock
20
yarn.lock
@ -1183,10 +1183,10 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
|
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
|
||||||
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
|
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
|
||||||
|
|
||||||
"@cerc-io/registry-sdk@^0.2.2":
|
"@cerc-io/registry-sdk@^0.2.4":
|
||||||
version "0.2.2"
|
version "0.2.4"
|
||||||
resolved "https://git.vdb.to/api/packages/cerc-io/npm/%40cerc-io%2Fregistry-sdk/-/0.2.2/registry-sdk-0.2.2.tgz#2e8a533f069b4bb9f4cd4798e783f52e29167d0d"
|
resolved "https://git.vdb.to/api/packages/cerc-io/npm/%40cerc-io%2Fregistry-sdk/-/0.2.4/registry-sdk-0.2.4.tgz#60e4e75b1e6a957cf2b97490af4fda4af07b105f"
|
||||||
integrity sha512-ocRMbWtdewOg02ORfK1U+qbTqB46anHP4ApXokGkY4d+mFSApR3sdUEi2geHcs8oh+SG8YAp7LUJ9AAJneNY8g==
|
integrity sha512-hRZJP+s+uBvfrqtmQ38pmf74SyfFDC65AVwvWigJGxc6uKJG4jyuMyhsoD1P4XkjwAQSnFO89TuDC5JGkdXyrA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@cosmjs/amino" "^0.28.1"
|
"@cosmjs/amino" "^0.28.1"
|
||||||
"@cosmjs/crypto" "^0.28.1"
|
"@cosmjs/crypto" "^0.28.1"
|
||||||
@ -3015,6 +3015,16 @@
|
|||||||
"@stablelib/random" "^1.0.2"
|
"@stablelib/random" "^1.0.2"
|
||||||
"@stablelib/wipe" "^1.0.1"
|
"@stablelib/wipe" "^1.0.1"
|
||||||
|
|
||||||
|
"@sumsub/websdk-react@^2.3.1":
|
||||||
|
version "2.3.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@sumsub/websdk-react/-/websdk-react-2.3.1.tgz#43345cbe8bfe08f38da172b8a8d282dcbca9cb17"
|
||||||
|
integrity sha512-v6ZKsz3DRBNRzB36hx4pPGlMJH7Biwso3YWVtApgb0pJlhWkONUnuokhd58qnA4qwAPQAamI5JOkjFL8qsFhmw==
|
||||||
|
|
||||||
|
"@sumsub/websdk@^2.3.1":
|
||||||
|
version "2.3.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@sumsub/websdk/-/websdk-2.3.1.tgz#20177e08dee8b15527c8a10722fa72d713e94b7f"
|
||||||
|
integrity sha512-pIxjLZybN+7eqVC7Hpl24Jf2Vk0ahsRuCO+wuNA8h4dna9AdnyjOxpxS4Akw7knNi8AHs4fQFHaDa9WfUPgTBQ==
|
||||||
|
|
||||||
"@surma/rollup-plugin-off-main-thread@^2.2.3":
|
"@surma/rollup-plugin-off-main-thread@^2.2.3":
|
||||||
version "2.2.3"
|
version "2.2.3"
|
||||||
resolved "https://registry.yarnpkg.com/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-2.2.3.tgz#ee34985952ca21558ab0d952f00298ad2190c053"
|
resolved "https://registry.yarnpkg.com/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-2.2.3.tgz#ee34985952ca21558ab0d952f00298ad2190c053"
|
||||||
@ -12199,8 +12209,6 @@ tr46@^1.0.1:
|
|||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/tr46/-/tr46-1.0.1.tgz#a8b13fd6bfd2489519674ccde55ba3693b706d09"
|
resolved "https://registry.yarnpkg.com/tr46/-/tr46-1.0.1.tgz#a8b13fd6bfd2489519674ccde55ba3693b706d09"
|
||||||
integrity sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==
|
integrity sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==
|
||||||
dependencies:
|
|
||||||
punycode "^2.1.0"
|
|
||||||
|
|
||||||
tr46@^2.1.0:
|
tr46@^2.1.0:
|
||||||
version "2.1.0"
|
version "2.1.0"
|
||||||
|
Loading…
Reference in New Issue
Block a user