@rainbow-me/rainbowkit
Version:
The best way to connect a wallet
273 lines (270 loc) • 7.41 kB
JavaScript
"use client";
import {
useAuthenticationAdapter
} from "./chunk-HV6CXRKE.js";
import {
ActionButton
} from "./chunk-7P76HI55.js";
import {
CloseButton
} from "./chunk-6EUFMSBE.js";
import {
I18nContext
} from "./chunk-E5IRXM5F.js";
import {
Text
} from "./chunk-32RBZPUM.js";
import {
touchableStyles
} from "./chunk-2W63IDAD.js";
import {
AsyncImage
} from "./chunk-Z2CMCMO5.js";
import {
isMobile
} from "./chunk-N6EWR2LO.js";
import {
Box
} from "./chunk-ZKEPQLOV.js";
// src/components/SignIn/SignIn.tsx
import React, { useCallback, useContext, useRef } from "react";
import { UserRejectedRequestError } from "viem";
import { useAccount, useSignMessage } from "wagmi";
var signInIcon = async () => (await import("./sign-A7IJEUT5.js")).default;
function SignIn({
onClose,
onCloseModal
}) {
const { i18n } = useContext(I18nContext);
const [{ status, ...state }, setState] = React.useState({ status: "idle" });
const authAdapter = useAuthenticationAdapter();
const getNonce = useCallback(async () => {
try {
const nonce = await authAdapter.getNonce();
setState((x) => ({ ...x, nonce }));
} catch {
setState((x) => ({
...x,
errorMessage: i18n.t("sign_in.message.preparing_error"),
status: "idle"
}));
}
}, [authAdapter, i18n.t]);
const onceRef = useRef(false);
React.useEffect(() => {
if (onceRef.current) return;
onceRef.current = true;
getNonce();
}, [getNonce]);
const mobile = isMobile();
const { address, chain: activeChain } = useAccount();
const { signMessageAsync } = useSignMessage();
const signIn = async () => {
try {
const chainId = activeChain?.id;
const { nonce } = state;
if (!address || !chainId || !nonce) {
return;
}
setState((x) => ({
...x,
errorMessage: void 0
}));
let message;
try {
const messageResult = authAdapter.createMessage({
address,
chainId,
nonce
});
if (messageResult instanceof Promise) {
setState((x) => ({ ...x, status: "creatingMessage" }));
}
message = await messageResult;
} catch {
return setState((x) => ({
...x,
errorMessage: i18n.t("sign_in.message.preparing_error"),
status: "idle"
}));
}
let signature;
try {
setState((x) => ({ ...x, status: "signing" }));
signature = await signMessageAsync({
message
});
} catch (error) {
if (error instanceof UserRejectedRequestError) {
return setState((x) => ({
...x,
status: "idle"
}));
}
return setState((x) => ({
...x,
errorMessage: i18n.t("sign_in.signature.signing_error"),
status: "idle"
}));
}
setState((x) => ({ ...x, status: "verifying" }));
try {
const verified = await authAdapter.verify({ message, signature });
if (verified) {
onCloseModal();
return;
}
throw new Error();
} catch {
return setState((x) => ({
...x,
errorMessage: i18n.t("sign_in.signature.verifying_error"),
status: "idle"
}));
}
} catch {
setState((x) => ({
...x,
errorMessage: i18n.t("sign_in.signature.oops_error"),
status: "idle"
}));
}
};
return /* @__PURE__ */ React.createElement(Box, { position: "relative" }, /* @__PURE__ */ React.createElement(
Box,
{
display: "flex",
paddingRight: "16",
paddingTop: "16",
position: "absolute",
right: "0"
},
/* @__PURE__ */ React.createElement(CloseButton, { onClose })
), /* @__PURE__ */ React.createElement(
Box,
{
alignItems: "center",
display: "flex",
flexDirection: "column",
gap: mobile ? "32" : "24",
padding: "24",
paddingX: "18",
style: { paddingTop: mobile ? "60px" : "36px" }
},
/* @__PURE__ */ React.createElement(
Box,
{
alignItems: "center",
display: "flex",
flexDirection: "column",
gap: mobile ? "6" : "4",
style: { maxWidth: mobile ? 320 : 280 }
},
/* @__PURE__ */ React.createElement(
Box,
{
alignItems: "center",
display: "flex",
flexDirection: "column",
gap: mobile ? "32" : "16"
},
/* @__PURE__ */ React.createElement(AsyncImage, { height: 40, src: signInIcon, width: 40 }),
/* @__PURE__ */ React.createElement(
Text,
{
color: "modalText",
size: mobile ? "20" : "18",
textAlign: "center",
weight: "heavy"
},
i18n.t("sign_in.label")
)
),
/* @__PURE__ */ React.createElement(
Box,
{
alignItems: "center",
display: "flex",
flexDirection: "column",
gap: mobile ? "16" : "12"
},
/* @__PURE__ */ React.createElement(
Text,
{
color: "modalTextSecondary",
size: mobile ? "16" : "14",
textAlign: "center"
},
i18n.t("sign_in.description")
),
status === "idle" && state.errorMessage ? /* @__PURE__ */ React.createElement(
Text,
{
color: "error",
size: mobile ? "16" : "14",
textAlign: "center",
weight: "bold"
},
state.errorMessage
) : null
)
),
/* @__PURE__ */ React.createElement(
Box,
{
alignItems: !mobile ? "center" : void 0,
display: "flex",
flexDirection: "column",
gap: "8",
width: "full"
},
/* @__PURE__ */ React.createElement(
ActionButton,
{
disabled: !state.nonce || status === "creatingMessage" || status === "signing" || status === "verifying",
label: !state.nonce || status === "creatingMessage" ? i18n.t("sign_in.message.preparing") : status === "signing" ? i18n.t("sign_in.signature.waiting") : status === "verifying" ? i18n.t("sign_in.signature.verifying") : i18n.t("sign_in.message.send"),
onClick: signIn,
size: mobile ? "large" : "medium",
testId: "auth-message-button"
}
),
mobile ? /* @__PURE__ */ React.createElement(
ActionButton,
{
label: "Cancel",
onClick: onClose,
size: "large",
type: "secondary"
}
) : /* @__PURE__ */ React.createElement(
Box,
{
as: "button",
borderRadius: "full",
className: touchableStyles({ active: "shrink", hover: "grow" }),
display: "block",
onClick: onClose,
paddingX: "10",
paddingY: "5",
rel: "noreferrer",
style: { willChange: "transform" },
target: "_blank",
transition: "default"
},
/* @__PURE__ */ React.createElement(
Text,
{
color: "closeButton",
size: mobile ? "16" : "14",
weight: "bold"
},
i18n.t("sign_in.message.cancel")
)
)
)
));
}
export {
signInIcon,
SignIn
};