Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions app/graphql/generated.gql
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,31 @@ mutation lnUsdInvoiceFeeProbe($input: LnUsdInvoiceFeeProbeInput!) {
}
}

mutation newUserEmailRegistrationInitiate($input: NewUserEmailRegistrationInitiateInput!) {
newUserEmailRegistrationInitiate(input: $input) {
errors {
message
code
__typename
}
emailFlowId
__typename
}
}

mutation newUserEmailRegistrationValidate($input: NewUserEmailRegistrationValidateInput!) {
newUserEmailRegistrationValidate(input: $input) {
errors {
message
code
__typename
}
authToken
totpRequired
__typename
}
}

mutation onChainAddressCurrent($input: OnChainAddressCurrentInput!) {
onChainAddressCurrent(input: $input) {
errors {
Expand Down
116 changes: 116 additions & 0 deletions app/graphql/generated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -816,6 +816,8 @@ export type Mutation = {
readonly lnUsdInvoiceCreateOnBehalfOfRecipient: LnInvoicePayload;
readonly lnUsdInvoiceFeeProbe: CentAmountPayload;
readonly merchantMapSuggest: MerchantPayload;
readonly newUserEmailRegistrationInitiate: NewUserEmailRegistrationInitiatePayload;
readonly newUserEmailRegistrationValidate: AuthTokenPayload;
readonly onChainAddressCreate: OnChainAddressPayload;
readonly onChainAddressCurrent: OnChainAddressPayload;
readonly onChainPaymentSend: PaymentSendPayload;
Expand Down Expand Up @@ -991,6 +993,16 @@ export type MutationMerchantMapSuggestArgs = {
};


export type MutationNewUserEmailRegistrationInitiateArgs = {
input: NewUserEmailRegistrationInitiateInput;
};


export type MutationNewUserEmailRegistrationValidateArgs = {
input: NewUserEmailRegistrationValidateInput;
};


export type MutationOnChainAddressCreateArgs = {
input: OnChainAddressCreateInput;
};
Expand Down Expand Up @@ -1120,6 +1132,21 @@ export const Network = {
} as const;

export type Network = typeof Network[keyof typeof Network];
export type NewUserEmailRegistrationInitiateInput = {
readonly email: Scalars['EmailAddress']['input'];
};

export type NewUserEmailRegistrationInitiatePayload = {
readonly __typename: 'NewUserEmailRegistrationInitiatePayload';
readonly emailFlowId?: Maybe<Scalars['String']['output']>;
readonly errors: ReadonlyArray<Error>;
};

export type NewUserEmailRegistrationValidateInput = {
readonly code: Scalars['OneTimeAuthCode']['input'];
readonly emailFlowId: Scalars['String']['input'];
};

export const NotificationChannel = {
Push: 'PUSH'
} as const;
Expand Down Expand Up @@ -2340,6 +2367,20 @@ export type QuizCompletedMutationVariables = Exact<{

export type QuizCompletedMutation = { readonly __typename: 'Mutation', readonly quizCompleted: { readonly __typename: 'QuizCompletedPayload', readonly errors: ReadonlyArray<{ readonly __typename: 'GraphQLApplicationError', readonly message: string }>, readonly quiz?: { readonly __typename: 'Quiz', readonly id: string, readonly completed: boolean } | null } };

export type NewUserEmailRegistrationInitiateMutationVariables = Exact<{
input: NewUserEmailRegistrationInitiateInput;
}>;


export type NewUserEmailRegistrationInitiateMutation = { readonly __typename: 'Mutation', readonly newUserEmailRegistrationInitiate: { readonly __typename: 'NewUserEmailRegistrationInitiatePayload', readonly emailFlowId?: string | null, readonly errors: ReadonlyArray<{ readonly __typename: 'GraphQLApplicationError', readonly message: string, readonly code?: string | null }> } };

export type NewUserEmailRegistrationValidateMutationVariables = Exact<{
input: NewUserEmailRegistrationValidateInput;
}>;


export type NewUserEmailRegistrationValidateMutation = { readonly __typename: 'Mutation', readonly newUserEmailRegistrationValidate: { readonly __typename: 'AuthTokenPayload', readonly authToken?: string | null, readonly totpRequired?: boolean | null, readonly errors: ReadonlyArray<{ readonly __typename: 'GraphQLApplicationError', readonly message: string, readonly code?: string | null }> } };

export type UserEmailRegistrationInitiateMutationVariables = Exact<{
input: UserEmailRegistrationInitiateInput;
}>;
Expand Down Expand Up @@ -5130,6 +5171,81 @@ export function useQuizCompletedMutation(baseOptions?: Apollo.MutationHookOption
export type QuizCompletedMutationHookResult = ReturnType<typeof useQuizCompletedMutation>;
export type QuizCompletedMutationResult = Apollo.MutationResult<QuizCompletedMutation>;
export type QuizCompletedMutationOptions = Apollo.BaseMutationOptions<QuizCompletedMutation, QuizCompletedMutationVariables>;
export const NewUserEmailRegistrationInitiateDocument = gql`
mutation newUserEmailRegistrationInitiate($input: NewUserEmailRegistrationInitiateInput!) {
newUserEmailRegistrationInitiate(input: $input) {
errors {
message
code
}
emailFlowId
}
}
`;
export type NewUserEmailRegistrationInitiateMutationFn = Apollo.MutationFunction<NewUserEmailRegistrationInitiateMutation, NewUserEmailRegistrationInitiateMutationVariables>;

/**
* __useNewUserEmailRegistrationInitiateMutation__
*
* To run a mutation, you first call `useNewUserEmailRegistrationInitiateMutation` within a React component and pass it any options that fit your needs.
* When your component renders, `useNewUserEmailRegistrationInitiateMutation` returns a tuple that includes:
* - A mutate function that you can call at any time to execute the mutation
* - An object with fields that represent the current status of the mutation's execution
*
* @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;
*
* @example
* const [newUserEmailRegistrationInitiateMutation, { data, loading, error }] = useNewUserEmailRegistrationInitiateMutation({
* variables: {
* input: // value for 'input'
* },
* });
*/
export function useNewUserEmailRegistrationInitiateMutation(baseOptions?: Apollo.MutationHookOptions<NewUserEmailRegistrationInitiateMutation, NewUserEmailRegistrationInitiateMutationVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useMutation<NewUserEmailRegistrationInitiateMutation, NewUserEmailRegistrationInitiateMutationVariables>(NewUserEmailRegistrationInitiateDocument, options);
}
export type NewUserEmailRegistrationInitiateMutationHookResult = ReturnType<typeof useNewUserEmailRegistrationInitiateMutation>;
export type NewUserEmailRegistrationInitiateMutationResult = Apollo.MutationResult<NewUserEmailRegistrationInitiateMutation>;
export type NewUserEmailRegistrationInitiateMutationOptions = Apollo.BaseMutationOptions<NewUserEmailRegistrationInitiateMutation, NewUserEmailRegistrationInitiateMutationVariables>;
export const NewUserEmailRegistrationValidateDocument = gql`
mutation newUserEmailRegistrationValidate($input: NewUserEmailRegistrationValidateInput!) {
newUserEmailRegistrationValidate(input: $input) {
errors {
message
code
}
authToken
totpRequired
}
}
`;
export type NewUserEmailRegistrationValidateMutationFn = Apollo.MutationFunction<NewUserEmailRegistrationValidateMutation, NewUserEmailRegistrationValidateMutationVariables>;

/**
* __useNewUserEmailRegistrationValidateMutation__
*
* To run a mutation, you first call `useNewUserEmailRegistrationValidateMutation` within a React component and pass it any options that fit your needs.
* When your component renders, `useNewUserEmailRegistrationValidateMutation` returns a tuple that includes:
* - A mutate function that you can call at any time to execute the mutation
* - An object with fields that represent the current status of the mutation's execution
*
* @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;
*
* @example
* const [newUserEmailRegistrationValidateMutation, { data, loading, error }] = useNewUserEmailRegistrationValidateMutation({
* variables: {
* input: // value for 'input'
* },
* });
*/
export function useNewUserEmailRegistrationValidateMutation(baseOptions?: Apollo.MutationHookOptions<NewUserEmailRegistrationValidateMutation, NewUserEmailRegistrationValidateMutationVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useMutation<NewUserEmailRegistrationValidateMutation, NewUserEmailRegistrationValidateMutationVariables>(NewUserEmailRegistrationValidateDocument, options);
}
export type NewUserEmailRegistrationValidateMutationHookResult = ReturnType<typeof useNewUserEmailRegistrationValidateMutation>;
export type NewUserEmailRegistrationValidateMutationResult = Apollo.MutationResult<NewUserEmailRegistrationValidateMutation>;
export type NewUserEmailRegistrationValidateMutationOptions = Apollo.BaseMutationOptions<NewUserEmailRegistrationValidateMutation, NewUserEmailRegistrationValidateMutationVariables>;
export const UserEmailRegistrationInitiateDocument = gql`
mutation userEmailRegistrationInitiate($input: UserEmailRegistrationInitiateInput!) {
userEmailRegistrationInitiate(input: $input) {
Expand Down
14 changes: 7 additions & 7 deletions app/i18n/i18n-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2708,7 +2708,7 @@ type RootTranslation = {
*/
advanceMode: string
/**
* K​e​y​s​ ​m​a​n​a​g​e​m​e​n​t
* K​e​y​ ​m​a​n​a​g​e​m​e​n​t
*/
keysManagement: string
/**
Expand Down Expand Up @@ -7241,23 +7241,23 @@ export type TranslationFunctions = {
/**
* The amount you entered is less than the minimum amount required to send an on-chain transaction {amount}. Please consider sending this amount via Lightning!
*/
onchainMinAmountInvoiceError: (arg: { amount: number | string }) => LocalizedString
onchainMinAmountInvoiceError: (arg: { amount: number }) => LocalizedString
/**
* The amount on the invoice is less than minimum amount {amount}
*/
minAmountInvoiceError: (arg: { amount: number | string }) => LocalizedString
minAmountInvoiceError: (arg: { amount: number }) => LocalizedString
/**
* The amount on the invoice is greater than maximum amount {amount}
*/
maxAmountInvoiceError: (arg: { amount: number | string }) => LocalizedString
maxAmountInvoiceError: (arg: { amount: number }) => LocalizedString
/**
* The conversion amount is less than minimum required amount {amount}
*/
minAmountConvertError: (arg: { amount: number | string }) => LocalizedString
minAmountConvertError: (arg: { amount: number }) => LocalizedString
/**
* The conversion amount is greater than maximum amount {amount}
*/
maxAmountConvertError: (arg: { amount: number | string }) => LocalizedString
maxAmountConvertError: (arg: { amount: number }) => LocalizedString
}
SettingsScreen: {
/**
Expand Down Expand Up @@ -7401,7 +7401,7 @@ export type TranslationFunctions = {
*/
advanceMode: () => LocalizedString
/**
* Keys management
* Key management
*/
keysManagement: () => LocalizedString
/**
Expand Down
2 changes: 1 addition & 1 deletion app/i18n/raw-i18n/source/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -461,7 +461,7 @@
"unlockQuestion": "To unlock, answer the question:",
"youEarned": "You Earned",
"registerTitle": "Need to upgrade your account",
"registerContent": "Register with your phone number to receive bitcoin"
"registerContent": "Register with your phone number to receive sats"
},
"GetStartedScreen": {
"logInCreateAccount": "Log in / create account",
Expand Down
2 changes: 1 addition & 1 deletion app/navigation/stack-param-lists.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ export type RootStackParamList = {
emailRegistrationInitiate: undefined
emailRegistrationValidate: { email: string; emailRegistrationId: string }
emailLoginInitiate: undefined
emailLoginValidate: { email: string; emailLoginId: string }
emailLoginValidate: { email: string; emailFlowId: string }
totpRegistrationInitiate: undefined
totpRegistrationValidate: { totpRegistrationId: string }
totpLoginValidate: { authToken: string }
Expand Down
73 changes: 43 additions & 30 deletions app/screens/email-login-screen/email-login-initiate.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import React, { useEffect, useState } from "react"
import React, { useState } from "react"
import { View } from "react-native"
import axios, { isAxiosError } from "axios"
import crashlytics from "@react-native-firebase/crashlytics"
import { Input, Text, makeStyles } from "@rneui/themed"
import { StackScreenProps } from "@react-navigation/stack"
import { RootStackParamList } from "@app/navigation/stack-param-lists"
import { gql } from "@apollo/client"
import { useNewUserEmailRegistrationInitiateMutation } from "@app/graphql/generated"

// components
import { Screen } from "../../components/screen"
Expand All @@ -12,23 +14,35 @@ import { GaloyErrorBox } from "@app/components/atomic/galoy-error-box"

// hooks
import { useI18nContext } from "@app/i18n/i18n-react"
import { useAppConfig } from "@app/hooks"

// utils
import { testProps } from "@app/utils/testProps"
import validator from "validator"

gql`
mutation newUserEmailRegistrationInitiate($input: NewUserEmailRegistrationInitiateInput!) {
newUserEmailRegistrationInitiate(input: $input) {
errors {
message
code
}
emailFlowId
}
}
`

type Props = StackScreenProps<RootStackParamList, "emailLoginInitiate">

export const EmailLoginInitiateScreen: React.FC<Props> = ({ navigation }) => {
const styles = useStyles()
const { LL } = useI18nContext()
const { authUrl } = useAppConfig().appConfig.galoyInstance

const [emailInput, setEmailInput] = useState<string>("")
const [errorMessage, setErrorMessage] = useState<string>("")
const [loading, setLoading] = useState<boolean>(false)

const [newUserEmailRegistrationInitiate] = useNewUserEmailRegistrationInitiateMutation()

const updateInput = (text: string) => {
setEmailInput(text)
setErrorMessage("")
Expand All @@ -42,40 +56,39 @@ export const EmailLoginInitiateScreen: React.FC<Props> = ({ navigation }) => {

setLoading(true)

const url = `${authUrl}/auth/email/code`

try {
const res = await axios({
url,
method: "POST",
data: {
email: emailInput,
const { data } = await newUserEmailRegistrationInitiate({
variables: {
input: {
email: emailInput,
},
},
})
// TODO: manage error on ip rate limit
// TODO: manage error when trying the same email too often
const emailLoginId = res.data.result

if (emailLoginId) {
console.log({ emailLoginId })
navigation.navigate("emailLoginValidate", { emailLoginId, email: emailInput })
const errors = data?.newUserEmailRegistrationInitiate?.errors
const emailFlowId = data?.newUserEmailRegistrationInitiate?.emailFlowId

if (emailFlowId) {
navigation.navigate("emailLoginValidate", {
emailFlowId,
email: emailInput
})
} else if (errors && errors.length > 0) {
// Handle specific error codes
const error = errors[0]
if (error.code === "TOO_MANY_REQUEST") {
setErrorMessage(LL.errors.tooManyRequestsPhoneCode())
} else {
setErrorMessage(error.message || LL.errors.generic())
}
} else {
console.warn("no flow returned")
setErrorMessage(LL.errors.generic())
}
} catch (err) {
console.error(err, "error in setEmailMutation")
if (isAxiosError(err)) {
console.log(err.message) // Gives you the basic error message
console.log(err.response?.data) // Gives you the response payload from the server
console.log(err.response?.status) // Gives you the HTTP status code
console.log(err.response?.headers) // Gives you the response headers

// If the request was made but no response was received
if (!err.response) {
console.log(err.request)
}
setErrorMessage(err.message)
if (err instanceof Error) {
crashlytics().recordError(err)
}
setErrorMessage(LL.errors.generic())
} finally {
setLoading(false)
}
Expand Down
Loading