Use replacer to display public key

This commit is contained in:
Adw8 2024-08-09 09:57:50 +05:30
parent 30300b6cca
commit 79f0ff8b6c
2 changed files with 124 additions and 139 deletions

View File

@ -1,5 +1,5 @@
import React, { useEffect } from "react"; import React, { useEffect } from "react";
import {useLocation, useNavigate, useParams, useSearchParams } from "react-router-dom"; import {useLocation, useNavigate, useSearchParams } from "react-router-dom";
import { Button, Box, Container, Typography, colors } from "@mui/material"; import { Button, Box, Container, Typography, colors } from "@mui/material";

View File

@ -1,12 +1,14 @@
import React, { useEffect, useMemo, useState } from 'react'; import React, { useEffect, useMemo, useState } from 'react';
import { Box, MenuItem, Select, TextField, Typography } from '@mui/material';
import { enqueueSnackbar } from 'notistack'; import { enqueueSnackbar } from 'notistack';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import { Box, MenuItem, Select, TextField, Typography } from '@mui/material';
import { MsgCreateValidator } from 'cosmjs-types/cosmos/staking/v1beta1/tx'; import { MsgCreateValidator } from 'cosmjs-types/cosmos/staking/v1beta1/tx';
import { fromBech32, toBech32 } from '@cosmjs/encoding'; import { fromBech32, toBech32 } from '@cosmjs/encoding';
import { LoadingButton } from '@mui/lab'; import { LoadingButton } from '@mui/lab';
import { EncodeObject, encodePubkey } from '@cosmjs/proto-signing'; import { EncodeObject, encodePubkey } from '@cosmjs/proto-signing';
import { Registry } from '@cerc-io/registry-sdk'; import { Registry } from '@cerc-io/registry-sdk';
import { useWalletConnectContext } from '../context/WalletConnectContext'; import { useWalletConnectContext } from '../context/WalletConnectContext';
import { Participant } from '../types'; import { Participant } from '../types';
@ -21,27 +23,45 @@ const Validator = () => {
const [participant, setParticipant] = useState<Participant | null>(null); const [participant, setParticipant] = useState<Participant | null>(null);
const [isError, setIsError] = useState(false); const [isError, setIsError] = useState(false);
if (!session) { useEffect(() => {
navigate("/connect-wallet?redirectTo=create-validator"); if (!session) {
} navigate("/connect-wallet?redirectTo=validator");
}
}, [session, navigate]);
const isMonikerValid = useMemo(()=>{ useEffect(() => {
return moniker.trim().length > 0; if (!cosmosAddress) {
}, [moniker]); setParticipant(null);
return;
}
const isPubKeyValid = useMemo(()=>{ const fetchParticipant = async () => {
return pubKey.length === 44 const registry = new Registry(process.env.REACT_APP_REGISTRY_GQL_ENDPOINT!);
}, [pubKey]);
const msgCreateValidator: MsgCreateValidator = useMemo(() => { try {
let value = ''; const fetchedParticipant = await registry.getParticipantByAddress(cosmosAddress);
if (pubKey.length === 44) { if (fetchedParticipant) {
value = pubKey; setParticipant(fetchedParticipant);
} else {
enqueueSnackbar("Participant not found", { variant: "error" });
setParticipant(null);
}
} catch (error) {
console.error("Error fetching participant", error);
setParticipant(null);
}
}; };
fetchParticipant();
}, [cosmosAddress]);
const isMonikerValid = useMemo(() => moniker.trim().length > 0, [moniker]);
const isPubKeyValid = useMemo(() => pubKey.length === 44, [pubKey]);
const msgCreateValidator: MsgCreateValidator = useMemo(() => {
const encodedPubKey = encodePubkey({ const encodedPubKey = encodePubkey({
type: "tendermint/PubKeyEd25519", type: "tendermint/PubKeyEd25519",
value, value: pubKey.length === 44 ? pubKey : '',
}); });
return { return {
@ -70,15 +90,25 @@ const Validator = () => {
const msgCreateValidatorEncodeObject: EncodeObject = { const msgCreateValidatorEncodeObject: EncodeObject = {
typeUrl: '/cosmos.staking.v1beta1.MsgCreateValidator', typeUrl: '/cosmos.staking.v1beta1.MsgCreateValidator',
value: MsgCreateValidator.toJSON(msgCreateValidator) value: MsgCreateValidator.toJSON(msgCreateValidator),
}; };
const sendTransaction = async (transactionMessage: EncodeObject) => { const sendTransaction = async () => {
try { if (
setIsLoading(true); !isMonikerValid ||
!isPubKeyValid ||
!msgCreateValidator.validatorAddress
) {
setIsError(true);
return;
}
const params = { transactionMessage, signer: cosmosAddress }; setIsLoading(true);
const responseFromWallet = await signClient!.request<{ code: number }>({ enqueueSnackbar("View and sign the message from your Laconic Wallet", { variant: "info" });
try {
const params = { transactionMessage: msgCreateValidatorEncodeObject, signer: cosmosAddress };
const response = await signClient!.request<{ code: number }>({
topic: session!.topic, topic: session!.topic,
chainId: `cosmos:${process.env.REACT_APP_LACONICD_CHAIN_ID}`, chainId: `cosmos:${process.env.REACT_APP_LACONICD_CHAIN_ID}`,
request: { request: {
@ -86,61 +116,34 @@ const Validator = () => {
params, params,
}, },
}); });
if (responseFromWallet.code !== 0) {
if (response.code !== 0) {
enqueueSnackbar("Transaction not sent", { variant: "error" }); enqueueSnackbar("Transaction not sent", { variant: "error" });
} else { } else {
navigate("/onboarding-success", { navigate("/onboarding-success", { state: { cosmosAddress } });
state: { cosmosAddress },
});
} }
} catch (error) { } catch (error) {
console.error(error); console.error("Error sending transaction", error);
enqueueSnackbar("Error in sending transaction", { variant: "error" }); enqueueSnackbar("Error in sending transaction", { variant: "error" });
} finally { } finally {
setIsLoading(false); setIsLoading(false);
} }
}; };
useEffect(() => { const replacer = (key: string, value: any): any => {
const registry = new Registry(process.env.REACT_APP_REGISTRY_GQL_ENDPOINT!); if (value instanceof Uint8Array) {
return Buffer.from(value).toString('hex');
const fetchParticipant = async () => { }
try { return value;
if (!cosmosAddress) { };
setParticipant(null);
return;
}
const fetchedParticipant: Participant = await registry.getParticipantByAddress(cosmosAddress);
if (!fetchedParticipant) {
enqueueSnackbar("Participant not found", { variant: "error" });
setParticipant(null);
return;
}
setParticipant(fetchedParticipant);
} catch (error) {
console.error("Error fetching participant", error);
setParticipant(null);
}
};
fetchParticipant();
}, [cosmosAddress]);
return ( return (
<Box <Box sx={{ display: "flex", flexDirection: "column", marginTop: 6, gap: 1 }}>
sx={{
display: "flex",
flexDirection: "column",
marginTop: 6,
gap: 1,
}}
>
<Typography variant="h5">Create a validator</Typography> <Typography variant="h5">Create a validator</Typography>
<Typography variant="body1">Select Laconic account:</Typography> <Typography variant="body1">Select Laconic account:</Typography>
<Select <Select
sx={{ marginBottom: 2 }} sx={{ marginBottom: 2 }}
labelId="demo-simple-select-label" id="cosmos-address-select"
id="demo-simple-select"
value={cosmosAddress} value={cosmosAddress}
onChange={(e) => setCosmosAddress(e.target.value)} onChange={(e) => setCosmosAddress(e.target.value)}
style={{ maxWidth: "600px", display: "block" }} style={{ maxWidth: "600px", display: "block" }}
@ -153,16 +156,16 @@ const Validator = () => {
</Select> </Select>
{Boolean(cosmosAddress) && ( {Boolean(cosmosAddress) && (
<div> <>
{participant === null ? ( {participant ? (
<Typography>No participant found</Typography>
) : (
<Typography>Onboarded participant</Typography> <Typography>Onboarded participant</Typography>
) : (
<Typography>No participant found</Typography>
)} )}
<Box <Box
sx={{ sx={{
backgroundColor: participant === null ? "white" : "lightgray", backgroundColor: participant ? "lightgray" : "white",
padding: 3, padding: 3,
wordWrap: "break-word", wordWrap: "break-word",
marginBottom: 3, marginBottom: 3,
@ -170,83 +173,65 @@ const Validator = () => {
> >
{participant && ( {participant && (
<pre style={{ whiteSpace: "pre-wrap", margin: 0 }}> <pre style={{ whiteSpace: "pre-wrap", margin: 0 }}>
<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 />
Role: {participant.role} <br /> KYC ID: {participant.kycId} <br />
KYC ID: {participant.kycId} <br />
</div>
</pre> </pre>
)} )}
</Box> </Box>
<Box style={{ maxWidth: "600px" }}> {participant?.role === "validator" && (
<TextField <>
id="moniker" <Box style={{ maxWidth: "600px" }}>
label="Enter your node moniker" <TextField
variant="outlined" id="moniker"
fullWidth label="Enter your node moniker"
margin="normal" variant="outlined"
value={moniker} fullWidth
onChange={(e) => { margin="normal"
setIsError(false); value={moniker}
setMoniker(e.target.value) onChange={(e) => {
}} setIsError(false);
error={!isMonikerValid && isError } setMoniker(e.target.value);
helperText={!isMonikerValid && isError ? "Moniker is required" : ""} }}
/> error={!isMonikerValid && isError}
<TextField helperText={!isMonikerValid && isError ? "Moniker is required" : ""}
id="pub-key" />
label="Enter your public key" <TextField
variant="outlined" id="pub-key"
fullWidth label="Enter your public key"
margin="normal" variant="outlined"
value={pubKey} fullWidth
onChange={(e) => { margin="normal"
setIsError(false); value={pubKey}
setPubKey(e.target.value) onChange={(e) => {
}} setIsError(false);
error={!isPubKeyValid && isError} setPubKey(e.target.value);
helperText={!isPubKeyValid ? "Public key must be 44 characters" : ""} }}
/> error={!isPubKeyValid && isError}
</Box> helperText={!isPubKeyValid && isError ? "Public key must be 44 characters" : ""}
/>
<> </Box>
<Typography>Send transaction to chain</Typography> <Typography>Send transaction to chain</Typography>
<Box <Box sx={{ backgroundColor: "lightgray", padding: 3, wordWrap: "break-word" }}>
sx={{ <pre style={{ whiteSpace: "pre-wrap", margin: 0 }}>
backgroundColor: "lightgray", {JSON.stringify(msgCreateValidator, replacer, 2)}
padding: 3, </pre>
wordWrap: "break-word", </Box>
}} <Box marginTop={1} marginBottom={1}>
> <LoadingButton
<pre style={{ whiteSpace: "pre-wrap", margin: 0 }}> variant="contained"
{JSON.stringify(msgCreateValidator, null, 2)} onClick={sendTransaction}
</pre> loading={isLoading}
</Box> disabled={isError}
<Box marginTop={1} marginBottom={1}> >
<LoadingButton Send transaction
variant="contained" </LoadingButton>
onClick={async () => { </Box>
console.log(msgCreateValidatorEncodeObject); </>
if ( )}
msgCreateValidator.pubkey?.value?.length !== 34 || </>
msgCreateValidator.description.moniker.length === 0 ||
msgCreateValidator.validatorAddress.length === 0
) {
setIsError(true);
return;
}
await sendTransaction(msgCreateValidatorEncodeObject);
}}
loading={isLoading}
disabled={isError}
>
Send transaction
</LoadingButton>
</Box>
</>
</div>
)} )}
</Box> </Box>
); );