InitiateIdentity

 avatar
unknown
typescript
6 months ago
7.7 kB
3
Indexable
import { useEffect, useState } from "react";
import { Dimensions, Platform, Text, View } from "react-native";
import { useNavigation } from "@react-navigation/native";
import { NativeStackNavigationProp } from "@react-navigation/native-stack";
import { useTranslation } from "react-i18next";
import { useToast } from "react-native-toast-notifications";

import { signupStyles } from "@screens/SignupScreen/Signup.style";
import { Button, FormInput, Header } from "@share/components";
import { theme } from "@share/theme/theme";
import { useColors } from "@share/hooks";
import SignupLayout from "../SignupLayout/SignupLayout";
import * as Sentry from "@sentry/react-native";
import { SignupStackParamList } from "@screens/SignupScreen/Signup";
import { API_USER } from "@api/user";
import { useMutateUser } from "@features/GlobalProvider/UserDataProvider/UserDataProvider";
import { errorHandler } from "@share/utils";
import { Controller, FieldValues, useForm } from "react-hook-form";
import { sealdService } from "@services/seald.service";
import SendAgain from "@share/components/SendAgain/SendAgain";

type SealdState =
  | { status: "initializing" }
  | {
      status: "success";
      sessionId: string;
      ruleKey: string;
      mustAuthenticate: boolean;
    }
  | { status: "error" };

interface FormProps extends FieldValues {
  challange: string;
}
const InitateIdentity = () => {
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
  const signupNavigation =
    useNavigation<
      NativeStackNavigationProp<SignupStackParamList, "InitateIdentity">
    >();
  const { height } = Dimensions.get("window");
  const Colors = useColors();
  const { t } = useTranslation("translation", {
    keyPrefix: "screens.signup.initateIdentity",
  });
  const toast = useToast();
  const { control, handleSubmit, watch } = useForm<FormProps>({});
  const { userData, getUserProfile } = useMutateUser();
  const [sealdState, setSealdState] = useState<SealdState>({
    status: "initializing",
  });
  const [isLoading, setIsLoading] = useState(false);

  const initiateIdentity = async () => {
    try {
      if (!userData?.sealdUser) {
        await getUserProfile();
        console.error("User data not found");
        throw new Error("User data not found");
      }
      setIsLoading(true);

      console.log("userData.sealdUser", userData.sealdUser);

      if (!userData.sealdUser.sealdId) {
        const {
          data: { signupJWT },
        } = await API_USER.generateSealdSignupJWT();

        const { sealdId, deviceExpires, deviceId } =
          await sealdService.createIdentity({
            databaseRawKey: userData.sealdUser.databaseRawKey,
            sessionID: userData.sealdUser.databaseSessionId,
            signupJWT,
          });
        await API_USER.setEncryptionUser({ sealdId });
        await API_USER.setEncryptionDevice({
          sealdId,
          deviceExpires,
          deviceId,
        });
      }

      await getUserProfile();
      const {
        data: { mustAuthenticate, rawTwoManRuleKey, twoManRuleSessionId },
      } = await API_USER.getSealdSSKSSession();
      console.log("mustAuthenticate", mustAuthenticate);
      console.log("rawTwoManRuleKey", rawTwoManRuleKey);
      setSealdState({
        status: "success",
        sessionId: twoManRuleSessionId,
        ruleKey: rawTwoManRuleKey,
        mustAuthenticate,
      });
      setIsLoading(false);
    } catch (error) {
      Sentry.captureException(error);
      console.error("Seald initiateIdentity: ", error);
      toast.show(...errorHandler(error));
      setSealdState({
        status: "error",
      });
      setIsLoading(false);
    }
  };

  useEffect(() => {
    initiateIdentity();
  }, []);

  const onHandleSubmit = async (data: FormProps) => {
    try {
      if (
        sealdState.status === "error" ||
        sealdState.status === "initializing"
      ) {
        console.error("Re fetch data from server");
        return;
      }
      if (!userData?.sealdUser) {
        throw new Error("User data not found");
      }
      setIsLoading(true);
      if (!sealdService.getSealdSDKInstance()) {
        await sealdService.instantiateSealdSDK({
          databaseRawKey: userData.sealdUser.databaseRawKey,
          sessionID: userData.sealdUser.databaseSessionId,
        });
      } else if (userData.sealdUser.ssksId) {
        await sealdService.retrieveIdentity2MR({
          userId: String(userData.sealdUser.userId),
          phoneNumber: userData.phoneNumber,
          rawTwoManRuleKey: sealdState.ruleKey,
          twoManRuleSessionId: sealdState.sessionId,
          challenge: sealdState.mustAuthenticate ? data.challange : undefined,
          databaseRawKey: userData.sealdUser.databaseRawKey,
          sessionID: userData.sealdUser.databaseSessionId,
        });
      } else {
        const ssksId = await sealdService.saveIdentity2MR({
          userId: String(userData.sealdUser.userId),
          rawTwoManRuleKey: sealdState.ruleKey,
          phoneNumber: userData.phoneNumber,
          twoManRuleSessionId: sealdState.sessionId,
          challenge: sealdState.mustAuthenticate ? data.challange : undefined,
        });
        await API_USER.setEncryptionUser({ ssksId });
      }

      await getUserProfile();
      setIsLoading(false);
      signupNavigation.reset({
        index: 0,
        routes: [{ name: "StepFour" }],
      });
    } catch (error: unknown) {
      Sentry.captureException(error);
      setIsLoading(false);
      toast.show(...errorHandler(error));
    }
  };

  return (
    <SignupLayout>
      <View
        style={[
          signupStyles.wrapper,
          { marginVertical: height * 0.05, justifyContent: "flex-end" },
        ]}
      >
        <Header />
        <Text style={[theme.typography.title, signupStyles.title]}>
          {t("title")}
        </Text>
        <Text style={[signupStyles.subTitle, theme.typography.description]}>
          {t("subTitle")}
        </Text>
        <View style={{ marginTop: 19 }}>
          <Controller
            name="challange"
            control={control}
            rules={{
              required: true,
            }}
            render={({ field: { onChange, value }, fieldState: { error } }) => (
              <FormInput
                label={t("name")}
                value={value}
                onChangeText={onChange}
                style={{ marginTop: 16 }}
                placeholder={t("namePlaceholder")}
                errorNote={error?.message}
                textContentType="oneTimeCode"
                autoComplete="sms-otp"
              />
            )}
          />
        </View>
        <View style={{ marginTop: "auto" }}>
          <View style={{ alignItems: "center", marginBottom: 24 }}>
            <SendAgain onResend={initiateIdentity} time={60} />
          </View>
          <Button
            onPress={handleSubmit(onHandleSubmit)}
            variant="secondary"
            size="medium"
            disabled={Boolean(!watch("challange")) || isLoading}
            isLoading={isLoading}
          >
            <Text
              style={[
                theme.typography.description,
                {
                  color: Colors.bgSecondary,
                  fontFamily: Platform.select({
                    ios: "Inter",
                    android: "Inter-SemiBold",
                  }) as string,
                  fontWeight: Platform.select({ ios: "600" }) as "600",
                },
              ]}
            >
              {t("button")}
            </Text>
          </Button>
        </View>
      </View>
    </SignupLayout>
  );
};

export default InitateIdentity;
Editor is loading...
Leave a Comment