223 lines
6.4 KiB
TypeScript
223 lines
6.4 KiB
TypeScript
import React, { useCallback, useEffect, useMemo, useState } from "react";
|
|
import { useLocation, useNavigate } from "react-router-dom";
|
|
import { enqueueSnackbar } from "notistack";
|
|
|
|
import { Box, Divider, Typography } from "@mui/material";
|
|
import LoadingButton from "@mui/lab/LoadingButton/LoadingButton";
|
|
import {
|
|
MsgOnboardParticipantEncodeObject,
|
|
typeUrlMsgOnboardParticipant,
|
|
} from "@cerc-io/registry-sdk";
|
|
import { StargateClient } from "@cosmjs/stargate";
|
|
|
|
import { useWalletConnectContext } from "../context/WalletConnectContext";
|
|
import SelectRoleCard, { Role } from "../components/SelectRoleCard";
|
|
import { HASHED_SUBSCRIBER_ID_KEY } from "../constants";
|
|
import { Layout } from "../layout/Layout";
|
|
import { CodeBlock } from "../components/CodeBlock";
|
|
|
|
const SignWithCosmos = () => {
|
|
const { session, signClient } = useWalletConnectContext();
|
|
|
|
const location = useLocation();
|
|
const [isLoading, setIsLoading] = useState(false);
|
|
const [balance, setBalance] = useState("");
|
|
const [isRequesting, setIsRequesting] = useState(false);
|
|
const [isTncAccepted, setIsTncAccepted] = useState(false);
|
|
const [role, setRole] = useState(Role.Participant);
|
|
|
|
const navigate = useNavigate();
|
|
|
|
const {
|
|
message: innerMessage,
|
|
cosmosAddress,
|
|
receivedEthSig: ethSignature,
|
|
} = location.state as {
|
|
message?: {
|
|
msg: string;
|
|
address: string;
|
|
};
|
|
cosmosAddress?: string;
|
|
receivedEthSig?: string;
|
|
};
|
|
|
|
const ethAddress = innerMessage!.address;
|
|
const subscriberIdHash = localStorage.getItem(HASHED_SUBSCRIBER_ID_KEY);
|
|
|
|
const createCosmosClient = useCallback(async (endpoint: string) => {
|
|
return await StargateClient.connect(endpoint);
|
|
}, []);
|
|
|
|
const onboardParticipantMsg: MsgOnboardParticipantEncodeObject =
|
|
useMemo(() => {
|
|
return {
|
|
typeUrl: typeUrlMsgOnboardParticipant,
|
|
value: {
|
|
participant: cosmosAddress!,
|
|
ethPayload: innerMessage,
|
|
ethSignature: ethSignature!,
|
|
kycId: subscriberIdHash!,
|
|
role,
|
|
},
|
|
};
|
|
}, [cosmosAddress, innerMessage, ethSignature, subscriberIdHash, role]);
|
|
|
|
const handleTokenRequest = async () => {
|
|
try {
|
|
setIsRequesting(true);
|
|
const response = await fetch(
|
|
`${process.env.REACT_APP_FAUCET_ENDPOINT!}/faucet`,
|
|
{
|
|
method: "POST",
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
},
|
|
body: JSON.stringify({
|
|
address: cosmosAddress,
|
|
}),
|
|
},
|
|
);
|
|
|
|
if (response.ok) {
|
|
enqueueSnackbar("Tokens sent successfully", { variant: "success" });
|
|
} else {
|
|
const errorResponse = await response.json();
|
|
if (response.status === 429) {
|
|
enqueueSnackbar(`${response.statusText} : ${errorResponse.error}`, {
|
|
variant: "error",
|
|
});
|
|
} else {
|
|
throw new Error(errorResponse.error);
|
|
}
|
|
}
|
|
|
|
getBalances();
|
|
} catch (error) {
|
|
console.error(error);
|
|
enqueueSnackbar("Error getting tokens from faucet", { variant: "error" });
|
|
} finally {
|
|
setIsRequesting(false);
|
|
}
|
|
};
|
|
|
|
const sendTransaction = async (
|
|
transactionMessage: MsgOnboardParticipantEncodeObject,
|
|
) => {
|
|
if (!ethAddress) {
|
|
enqueueSnackbar("Set nitro address");
|
|
return;
|
|
}
|
|
|
|
try {
|
|
setIsLoading(true);
|
|
|
|
enqueueSnackbar("View and sign the message from your Laconic Wallet", {
|
|
variant: "info",
|
|
});
|
|
|
|
const params = { transactionMessage, signer: cosmosAddress };
|
|
const responseFromWallet = await signClient!.request<{
|
|
code: number;
|
|
}>({
|
|
topic: session!.topic,
|
|
chainId: `cosmos:${process.env.REACT_APP_LACONICD_CHAIN_ID}`,
|
|
request: {
|
|
method: "cosmos_sendTransaction",
|
|
params,
|
|
},
|
|
});
|
|
if (responseFromWallet.code !== 0) {
|
|
enqueueSnackbar("Transaction not sent", { variant: "error" });
|
|
} else {
|
|
navigate("/onboarding-success", {
|
|
state: {
|
|
cosmosAddress,
|
|
},
|
|
});
|
|
}
|
|
} catch (error) {
|
|
console.error(error);
|
|
enqueueSnackbar("Error in sending transaction", { variant: "error" });
|
|
} finally {
|
|
setIsLoading(false);
|
|
}
|
|
};
|
|
|
|
const getBalances = useCallback(async () => {
|
|
try {
|
|
const cosmosClient = await createCosmosClient(
|
|
process.env.REACT_APP_LACONICD_RPC_ENDPOINT!,
|
|
);
|
|
const balance = await cosmosClient.getBalance(
|
|
cosmosAddress!,
|
|
process.env.REACT_APP_LACONICD_DENOM!,
|
|
);
|
|
setBalance(balance.amount);
|
|
} catch (error) {
|
|
console.error("Error fetching balance:", error);
|
|
throw error;
|
|
}
|
|
}, [cosmosAddress, createCosmosClient]);
|
|
|
|
useEffect(() => {
|
|
getBalances();
|
|
}, [getBalances]);
|
|
|
|
return (
|
|
<>
|
|
{!isTncAccepted && (
|
|
<Layout
|
|
title="Please accept the terms and conditions to continue"
|
|
noBackButton
|
|
>
|
|
<SelectRoleCard
|
|
handleAccept={() => setIsTncAccepted(true)}
|
|
handleRoleChange={setRole}
|
|
/>
|
|
</Layout>
|
|
)}
|
|
<Layout title="Send transaction to chain" noBackButton>
|
|
<Typography>Laconic Account:</Typography>
|
|
<Box sx={{ backgroundColor: "#29292E", p: 2, borderRadius: 1, mb: 2 }}>
|
|
<Typography variant="body1">Address: {cosmosAddress}</Typography>
|
|
<Typography variant="body1">
|
|
Balance: {balance} {process.env.REACT_APP_LACONICD_DENOM}
|
|
</Typography>
|
|
</Box>
|
|
<LoadingButton
|
|
variant="contained"
|
|
onClick={handleTokenRequest}
|
|
disabled={isTncAccepted ? isRequesting : !isTncAccepted}
|
|
loading={isRequesting}
|
|
>
|
|
Request tokens from Faucet
|
|
</LoadingButton>
|
|
<Divider flexItem sx={{ my: 2 }} />
|
|
<Typography variant="body1">Onboarding message:</Typography>
|
|
|
|
<CodeBlock>{JSON.stringify(onboardParticipantMsg, null, 2)} </CodeBlock>
|
|
|
|
<Box
|
|
sx={{
|
|
paddingBottom: 2,
|
|
mt: 2,
|
|
}}
|
|
>
|
|
<LoadingButton
|
|
variant="contained"
|
|
onClick={async () => {
|
|
await sendTransaction(onboardParticipantMsg);
|
|
}}
|
|
loading={isLoading}
|
|
disabled={isTncAccepted ? balance === "0" : !isTncAccepted}
|
|
>
|
|
Send transaction
|
|
</LoadingButton>
|
|
</Box>
|
|
</Layout>
|
|
</>
|
|
);
|
|
};
|
|
|
|
export default SignWithCosmos;
|