Add text fields for moniker and public key

This commit is contained in:
Adw8 2024-08-08 19:31:29 +05:30
parent c461e90768
commit 30300b6cca

View File

@ -1,78 +1,84 @@
import { Box, MenuItem, Select, Typography } from '@mui/material'
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 { useNavigate } from 'react-router-dom';
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 { EncodeObject, encodePubkey } from '@cosmjs/proto-signing';
import { Registry } from '@cerc-io/registry-sdk';
import { useWalletConnectContext } from '../context/WalletConnectContext'
import { useWalletConnectContext } from '../context/WalletConnectContext';
import { Participant } from '../types';
const Validator = () => {
const {session, signClient} = useWalletConnectContext();
const { session, signClient } = useWalletConnectContext();
const navigate = useNavigate();
const [cosmosAddress, setCosmosAddress] = useState('laconic1z4l4556v8jnk7k456ujme720nk8mzjwhka7qvw');
const [cosmosAddress, setCosmosAddress] = useState('');
const [isLoading, setIsLoading] = useState(false);
const [pubkey, setPubkey] = useState('qiQEvyqIf9/e912ZEIZD5CfdqR3iOlpI+NVtRnpHuYc=');
const [moniker, setMoniker] = useState('');
const [pubKey, setPubKey] = useState('');
const [participant, setParticipant] = useState<Participant | null>(null);
const [isError, setIsError] = useState(false);
if (!session){
if (!session) {
navigate("/connect-wallet?redirectTo=create-validator");
}
const msgCreateValidator: MsgCreateValidator =
useMemo(() => {
return {
description: {
moniker: "dockerNode2",
identity: "",
website: "",
securityContact: "",
details: "",
},
commission: {
maxChangeRate: "10000000000000000", // 0.01
maxRate: "200000000000000000", // 0.2
rate: "100000000000000000", // 0.1
},
minSelfDelegation: "1",
delegatorAddress: '',
validatorAddress: toBech32('laconicvaloper', fromBech32(cosmosAddress).data),
pubkey: encodePubkey({
type: "tendermint/PubKeyEd25519",
value: pubkey,
}),
value: {
amount: process.env.REACT_APP_STAKING_AMOUNT!,
denom: process.env.REACT_APP_LACONICD_DENOM!,
},
};
}, [cosmosAddress, pubkey]);
const isMonikerValid = useMemo(()=>{
return moniker.trim().length > 0;
}, [moniker]);
const isPubKeyValid = useMemo(()=>{
return pubKey.length === 44
}, [pubKey]);
const msgCreateValidator: MsgCreateValidator = useMemo(() => {
let value = '';
if (pubKey.length === 44) {
value = pubKey;
};
const encodedPubKey = encodePubkey({
type: "tendermint/PubKeyEd25519",
value,
});
return {
description: {
moniker,
identity: "",
website: "",
securityContact: "",
details: "",
},
commission: {
maxChangeRate: "10000000000000000", // 0.01
maxRate: "200000000000000000", // 0.2
rate: "100000000000000000", // 0.1
},
minSelfDelegation: "1",
delegatorAddress: '',
validatorAddress: cosmosAddress && toBech32('laconicvaloper', fromBech32(cosmosAddress).data),
pubkey: encodedPubKey,
value: {
amount: process.env.REACT_APP_STAKING_AMOUNT!,
denom: process.env.REACT_APP_LACONICD_DENOM!,
},
};
}, [cosmosAddress, pubKey, moniker]);
// When sending a typed message value, the pubkey value type (Uint8Array) gets lost when wallet connect JSON-stringifies the tx message;
// resulting into a type error from the chain
// Workaround: Encode the tx value instead of sending a typed message directly, has to be decoded using MsgCreateValidator.fromJSON on the wallet side
const msgCreateValidatorEncodeObject: EncodeObject = {
typeUrl: '/cosmos.staking.v1beta1.MsgCreateValidator',
value: MsgCreateValidator.toJSON(msgCreateValidator)
// value: msgCreateValidator
};
const sendTransaction = async (
transactionMessage: EncodeObject
) => {
const sendTransaction = async (transactionMessage: EncodeObject) => {
try {
setIsLoading(true);
const params = { transactionMessage, signer: cosmosAddress };
const responseFromWallet = await signClient!.request<{
code: number;
}>({
const responseFromWallet = await signClient!.request<{ code: number }>({
topic: session!.topic,
chainId: `cosmos:${process.env.REACT_APP_LACONICD_CHAIN_ID}`,
request: {
@ -84,9 +90,7 @@ const Validator = () => {
enqueueSnackbar("Transaction not sent", { variant: "error" });
} else {
navigate("/onboarding-success", {
state: {
cosmosAddress
}
state: { cosmosAddress },
});
}
} catch (error) {
@ -98,9 +102,7 @@ const Validator = () => {
};
useEffect(() => {
const registry = new Registry(
process.env.REACT_APP_REGISTRY_GQL_ENDPOINT!
);
const registry = new Registry(process.env.REACT_APP_REGISTRY_GQL_ENDPOINT!);
const fetchParticipant = async () => {
try {
@ -114,7 +116,6 @@ const Validator = () => {
setParticipant(null);
return;
}
setParticipant(fetchedParticipant);
} catch (error) {
console.error("Error fetching participant", error);
@ -137,15 +138,11 @@ const Validator = () => {
<Typography variant="h5">Create a validator</Typography>
<Typography variant="body1">Select Laconic account:</Typography>
<Select
sx={{
marginBottom: 2
}}
sx={{ marginBottom: 2 }}
labelId="demo-simple-select-label"
id="demo-simple-select"
value={cosmosAddress}
onChange={(e: any) => {
setCosmosAddress(e.target.value);
}}
onChange={(e) => setCosmosAddress(e.target.value)}
style={{ maxWidth: "600px", display: "block" }}
>
{session?.namespaces.cosmos.accounts.map((address, index) => (
@ -158,14 +155,14 @@ const Validator = () => {
{Boolean(cosmosAddress) && (
<div>
{participant === null ? (
<Typography >No participant found</Typography>
<Typography>No participant found</Typography>
) : (
<Typography >Onboarded participant</Typography>
<Typography>Onboarded participant</Typography>
)}
<Box
sx={{
backgroundColor: participant === null? "white": "lightgray",
backgroundColor: participant === null ? "white" : "lightgray",
padding: 3,
wordWrap: "break-word",
marginBottom: 3,
@ -183,9 +180,39 @@ const Validator = () => {
)}
</Box>
{/* {participant && participant.role === "validator" && ( */}
<Box style={{ maxWidth: "600px" }}>
<TextField
id="moniker"
label="Enter your node moniker"
variant="outlined"
fullWidth
margin="normal"
value={moniker}
onChange={(e) => {
setIsError(false);
setMoniker(e.target.value)
}}
error={!isMonikerValid && isError }
helperText={!isMonikerValid && isError ? "Moniker is required" : ""}
/>
<TextField
id="pub-key"
label="Enter your public key"
variant="outlined"
fullWidth
margin="normal"
value={pubKey}
onChange={(e) => {
setIsError(false);
setPubKey(e.target.value)
}}
error={!isPubKeyValid && isError}
helperText={!isPubKeyValid ? "Public key must be 44 characters" : ""}
/>
</Box>
<>
<Typography >Send transaction to chain</Typography>
<Typography>Send transaction to chain</Typography>
<Box
sx={{
backgroundColor: "lightgray",
@ -197,24 +224,32 @@ const Validator = () => {
{JSON.stringify(msgCreateValidator, null, 2)}
</pre>
</Box>
<Box marginTop={1}>
<Box marginTop={1} marginBottom={1}>
<LoadingButton
variant="contained"
onClick={async () => {
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>
)
}
);
};
export default Validator
export default Validator;