import React, { useEffect, useMemo, useState } from 'react'; import { enqueueSnackbar } from 'notistack'; import { useNavigate } from 'react-router-dom'; import { MsgCreateValidator } from 'cosmjs-types/cosmos/staking/v1beta1/tx'; import { Box, Link, MenuItem, Select, TextField, Typography } from '@mui/material'; 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 { Participant } from '../types'; const Validator = () => { const { session, signClient, isSessionLoading } = useWalletConnectContext(); const navigate = useNavigate(); const [cosmosAddress, setCosmosAddress] = useState(''); const [isLoading, setIsLoading] = useState(false); const [moniker, setMoniker] = useState(''); const [pubKey, setPubKey] = useState(''); const [participant, setParticipant] = useState(null); const [isError, setIsError] = useState(false); useEffect(() => { if (isSessionLoading) { return; } if (!session) { navigate("/connect-wallet?redirectTo=validator"); } }, [session, navigate, isSessionLoading]); useEffect(() => { if (!cosmosAddress) { setParticipant(null); return; } const fetchParticipant = async () => { const registry = new Registry(process.env.REACT_APP_REGISTRY_GQL_ENDPOINT!); try { const fetchedParticipant = await registry.getParticipantByAddress(cosmosAddress); if (fetchedParticipant) { setParticipant(fetchedParticipant); } else { throw new Error("Participant not found"); } } catch (error) { console.error("Error fetching participant", error); enqueueSnackbar("Error in fetching participant", { variant: "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({ type: "tendermint/PubKeyEd25519", value: pubKey.length === 44 ? pubKey : '', }); 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]); const msgCreateValidatorEncodeObject: EncodeObject = { typeUrl: '/cosmos.staking.v1beta1.MsgCreateValidator', value: MsgCreateValidator.toJSON(msgCreateValidator), }; const sendTransaction = async () => { if ( !isMonikerValid || !isPubKeyValid || !msgCreateValidator.validatorAddress ) { setIsError(true); return; } setIsLoading(true); 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, chainId: `cosmos:${process.env.REACT_APP_LACONICD_CHAIN_ID}`, request: { method: "cosmos_sendTransaction", params, }, }); if (response.code !== 0) { throw new Error("Transaction not sent"); } else { navigate("/validator-success", { state: { validatorAddress: msgCreateValidator.validatorAddress, } }); } } catch (error) { console.error("Error sending transaction", error); enqueueSnackbar("Error in sending transaction", { variant: "error" }); } finally { setIsLoading(false); } }; const replacer = (key: string, value: any): any => { if (value instanceof Uint8Array) { return Buffer.from(value).toString('hex'); } return value; }; return ( Create a validator Select Laconic account: {Boolean(cosmosAddress) && ( <> {participant ? ( Onboarded participant ) : ( No participant found )} {participant && (
                Cosmos Address: {participant.cosmosAddress} 
Nitro Address: {participant.nitroAddress}
Role: {participant.role}
KYC ID: {participant.kycId}
)}
{participant?.role === "validator" && ( <> { setIsError(false); setMoniker(e.target.value); }} error={!isMonikerValid && isError} helperText={!isMonikerValid && isError ? "Moniker is required" : ""} /> Fetch your validator public key using the following command (refer  this guide )
                  {`laconic-so deployment --dir testnet-laconicd-deployment exec laconicd "laconicd cometbft show-validator" | jq -r .key`}
                
{ setIsError(false); setPubKey(e.target.value); }} error={!isPubKeyValid && isError} helperText={!isPubKeyValid && isError ? "Public key must be 44 characters" : ""} /> Send transaction to chain
                  {JSON.stringify(msgCreateValidator, replacer, 2)}
                
Send transaction )} )}
); }; export default Validator;